diff --git a/br-ext-chip-hisilicon/Config.in b/br-ext-chip-hisilicon/Config.in new file mode 100644 index 000000000..93b298aef --- /dev/null +++ b/br-ext-chip-hisilicon/Config.in @@ -0,0 +1,7 @@ +source "$BR2_EXTERNAL_HISILICON_PATH/linux/Config.ext.in" +source "$BR2_EXTERNAL_HISILICON_PATH/package/hisi_patcher/Config.in" +source "$BR2_EXTERNAL_HISILICON_PATH/package/fwprintenv-ng/Config.in" +source "$BR2_EXTERNAL_HISILICON_PATH/package/hisilicon-osdrv4/Config.in" +source "$BR2_EXTERNAL_HISILICON_PATH/package/ipctool/Config.in" +source "$BR2_EXTERNAL_HISILICON_PATH/package/majestic/Config.in" +source "$BR2_EXTERNAL_HISILICON_PATH/package/libevent-mini/Config.in" diff --git a/br-ext-chip-hisilicon/board/hi3516cv200/hi3516cv200.config b/br-ext-chip-hisilicon/board/hi3516cv200/hi3516cv200.config new file mode 100644 index 000000000..72e91bbfb --- /dev/null +++ b/br-ext-chip-hisilicon/board/hi3516cv200/hi3516cv200.config @@ -0,0 +1,2 @@ +MEM_START_ADDR=0x80000000 +KERNEL_UPLOAD_ADDR=0x81000000 diff --git a/br-ext-chip-hisilicon/board/hi3516cv200/hi3518ev200.config b/br-ext-chip-hisilicon/board/hi3516cv200/hi3518ev200.config new file mode 100644 index 000000000..72e91bbfb --- /dev/null +++ b/br-ext-chip-hisilicon/board/hi3516cv200/hi3518ev200.config @@ -0,0 +1,2 @@ +MEM_START_ADDR=0x80000000 +KERNEL_UPLOAD_ADDR=0x81000000 diff --git a/br-ext-chip-hisilicon/board/hi3516cv200/hi3518ev201.config b/br-ext-chip-hisilicon/board/hi3516cv200/hi3518ev201.config new file mode 100644 index 000000000..72e91bbfb --- /dev/null +++ b/br-ext-chip-hisilicon/board/hi3516cv200/hi3518ev201.config @@ -0,0 +1,2 @@ +MEM_START_ADDR=0x80000000 +KERNEL_UPLOAD_ADDR=0x81000000 diff --git a/br-ext-chip-hisilicon/board/hi3516cv200/kernel/hi3516cv200.generic.config b/br-ext-chip-hisilicon/board/hi3516cv200/kernel/hi3516cv200.generic.config new file mode 100644 index 000000000..fe4a6addb --- /dev/null +++ b/br-ext-chip-hisilicon/board/hi3516cv200/kernel/hi3516cv200.generic.config @@ -0,0 +1,2653 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 4.9.37 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_ARM_HAS_SG_CHAIN=y +CONFIG_MIGHT_HAVE_PCI=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_GENERIC_BUG=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_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +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_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_FHANDLE=y +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_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=17 +CONFIG_NMI_LOG_BUF_SHIFT=13 +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_CGROUPS=y +# CONFIG_MEMCG is not set +# CONFIG_BLK_CGROUP is not set +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_CFS_BANDWIDTH is not set +# CONFIG_RT_GROUP_SCHED is not set +# CONFIG_CGROUP_PIDS is not set +# CONFIG_CGROUP_FREEZER is not set +# CONFIG_CPUSETS is not set +# CONFIG_CGROUP_DEVICE is not set +# CONFIG_CGROUP_CPUACCT is not set +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_IPC_NS=y +# CONFIG_USER_NS is not set +CONFIG_PID_NS=y +CONFIG_NET_NS=y +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_RD_LZ4=y +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_BPF=y +# CONFIG_EXPERT is not set +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_ALL is not set +# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set +CONFIG_KALLSYMS_BASE_RELATIVE=y +CONFIG_PRINTK=y +CONFIG_PRINTK_NMI=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +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=y +CONFIG_SLUB_DEBUG=y +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# 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 is not set +# CONFIG_UPROBES is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +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_ARCH_HAS_GCOV_PROFILE_ALL=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=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=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +CONFIG_BLK_CMDLINE_PARSER=y + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_CMDLINE_PARTITION=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" +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=y + +# +# System Type +# +CONFIG_MMU=y +CONFIG_ARCH_MULTIPLATFORM=y +# 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_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 + +# +# Multiple platform selection +# + +# +# CPU Core family selection +# +# CONFIG_ARCH_MULTI_V4 is not set +# CONFIG_ARCH_MULTI_V4T is not set +CONFIG_ARCH_MULTI_V5=y +CONFIG_ARCH_MULTI_V4_V5=y +# CONFIG_ARCH_MULTI_V6 is not set +# CONFIG_ARCH_MULTI_V7 is not set +CONFIG_ARCH_MULTI_CPU_AUTO=y +# CONFIG_ARCH_MVEBU is not set +# CONFIG_MACH_ASM9260 is not set +# CONFIG_ARCH_AT91 is not set +CONFIG_ARCH_HISI_BVT=y + +# +# Hisilicon BVT platform type +# +CONFIG_ARCH_HI3518EV20X=y +CONFIG_HI_ZRELADDR=0x80008000 +CONFIG_HI_PARAMS_PHYS=0x00000100 +CONFIG_HI_INITRD_PHYS=0x00800000 +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_ASPEED is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_NSPIRE is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_OXNAS is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_WM8505 is not set + +# +# Processor Type +# +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_PABRT_LEGACY=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_USE_DOMAINS=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_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +CONFIG_NEED_KUSER_HELPERS=y +CONFIG_KUSER_HELPERS=y +# CONFIG_CACHE_L2X0 is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 +# CONFIG_DEBUG_RODATA is not set +CONFIG_MULTI_IRQ_HANDLER=y + +# +# Bus support +# +# CONFIG_PCI is not set +# 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 is not set +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=999999 +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_FRONTSWAP 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=y +# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set +CONFIG_CMDLINE="" +# 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 is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_ELFCORE=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=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=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_HIBERNATION is not set +CONFIG_PM_SLEEP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM_EMULATION is not set +CONFIG_PM_CLK=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_CPU_PM=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_NET=y +CONFIG_NET_INGRESS=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 is not set +# 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=m +# 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=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +# 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_IPV6_ILA is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_VTI is not set +CONFIG_IPV6_SIT=m +# 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=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_INGRESS=y +# CONFIG_NETFILTER_NETLINK_ACCT is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NF_TABLES is not set +# CONFIG_NETFILTER_XTABLES is not set +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV4 is not set +# CONFIG_NF_DUP_IPV4 is not set +# CONFIG_NF_LOG_ARP is not set +# CONFIG_NF_LOG_IPV4 is not set +# CONFIG_NF_REJECT_IPV4 is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set + +# +# IPv6: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV6 is not set +# CONFIG_NF_DUP_IPV6 is not set +# CONFIG_NF_REJECT_IPV6 is not set +# CONFIG_NF_LOG_IPV6 is not set +# CONFIG_IP6_NF_IPTABLES 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_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_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_CGROUP_NET_PRIO is not set +# CONFIG_CGROUP_NET_CLASSID 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 is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL 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 +# +CONFIG_ARM_AMBA=y + +# +# Generic Driver Options +# +# CONFIG_UEVENT_HELPER is not set +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set +CONFIG_ALLOW_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +# 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_SWAP 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 is not set +# 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_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_DENALI_DT is not set +# CONFIG_MTD_NAND_GPIO is not set +# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_DOCG4 is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_BRCMNAND is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_NAND_HISI504 is not set +# CONFIG_MTD_NAND_MTK is not set +CONFIG_MTD_SPI_NAND_HISI_BVT=y +# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set +# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set +CONFIG_MTD_SPI_NAND_HIFMC100=y +# 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 is not set +# CONFIG_SPI_CADENCE_QUADSPI is not set +CONFIG_SPI_HISI_SFC=y +# CONFIG_MTD_SPI_IDS is not set +CONFIG_CLOSE_SPI_8PIN_4IO=y +CONFIG_HISI_SPI_BLOCK_PROTECT=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_LIMIT=20 +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +# CONFIG_MTD_UBI_BLOCK 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=y +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=65536 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_NVME_TARGET is not set + +# +# Misc devices +# +# 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=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=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=y +# CONFIG_HIX5HD2_GMAC is not set +CONFIG_HISI_FEMAC=y +# CONFIG_HIP04_ETH is not set +# CONFIG_HNS is not set +# CONFIG_HNS_DSAF is not set +# CONFIG_HNS_ENET is not set +# CONFIG_HIETH_GMAC 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_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=y +# CONFIG_MDIO_HISI_GEMAC 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_IPHETH is not set +# CONFIG_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=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=y +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_BCM is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_BYD=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_CYPRESS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +CONFIG_MOUSE_PS2_FOCALTECH=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set +CONFIG_INPUT_JOYSTICK=y +# CONFIG_JOYSTICK_ANALOG is not set +# CONFIG_JOYSTICK_A3D is not set +# CONFIG_JOYSTICK_ADI is not set +# CONFIG_JOYSTICK_COBRA is not set +# CONFIG_JOYSTICK_GF2K is not set +# CONFIG_JOYSTICK_GRIP is not set +# CONFIG_JOYSTICK_GRIP_MP is not set +# CONFIG_JOYSTICK_GUILLEMOT is not set +# CONFIG_JOYSTICK_INTERACT is not set +# CONFIG_JOYSTICK_SIDEWINDER is not set +# CONFIG_JOYSTICK_TMDC is not set +# CONFIG_JOYSTICK_IFORCE is not set +# CONFIG_JOYSTICK_WARRIOR is not set +# CONFIG_JOYSTICK_MAGELLAN is not set +# CONFIG_JOYSTICK_SPACEORB is not set +# CONFIG_JOYSTICK_SPACEBALL is not set +# CONFIG_JOYSTICK_STINGER is not set +# CONFIG_JOYSTICK_TWIDJOY is not set +# CONFIG_JOYSTICK_ZHENHUA is not set +# CONFIG_JOYSTICK_AS5011 is not set +# CONFIG_JOYSTICK_JOYDUMP is not set +# CONFIG_JOYSTICK_XPAD 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=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_USERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=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=y + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +# 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_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_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM 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=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_MUX is not set +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# 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_HIBVT is not set +# CONFIG_I2C_NOMADIK 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_HISI=y +# 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_DEBUG is not set +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_GPIO is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +CONFIG_SPI_PL022=y +# 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=y +# 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_PINCONF=y +CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_AMD is not set +CONFIG_PINCTRL_SINGLE=y +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_GPIOLIB=y +CONFIG_OF_GPIO=y +CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers +# +# CONFIG_GPIO_74XX_MMIO is not set +# CONFIG_GPIO_ALTERA is not set +# 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_PL061=y +# CONFIG_GPIO_SYSCON 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_BRCMSTB is not set +# CONFIG_POWER_RESET_GPIO is not set +# CONFIG_POWER_RESET_GPIO_RESTART is not set +# CONFIG_POWER_RESET_LTC2952 is not set +# CONFIG_POWER_RESET_RESTART is not set +# CONFIG_POWER_RESET_VERSATILE is not set +CONFIG_POWER_RESET_SYSCON=y +# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set +# CONFIG_SYSCON_REBOOT_MODE is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27XXX is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_BQ25890 is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_CHARGER_RT9455 is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG 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=y +# 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_MFD_HISI_FMC=y +# 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=y +# 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 + +# +# Graphics support +# +# CONFIG_IMX_IPUV3_CORE is not set +# CONFIG_DRM is not set + +# +# ACP (Audio CoProcessor) Configuration +# + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_CMDLINE=y +CONFIG_FB_NOTIFY=y +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_IBM_GXT4500 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_FB_SSD1307 is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_VGASTATE is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set +# CONFIG_LOGO is not set +# CONFIG_SOUND is not set + +# +# HID support +# +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set +# CONFIG_HIDRAW is not set +# CONFIG_UHID is not set +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +CONFIG_HID_A4TECH=y +# CONFIG_HID_ACRUX is not set +CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_AUREAL is not set +CONFIG_HID_BELKIN=y +# CONFIG_HID_BETOP_FF is not set +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +# CONFIG_HID_CMEDIA is not set +# CONFIG_HID_CP2112 is not set +CONFIG_HID_CYPRESS=y +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_ELECOM is not set +# CONFIG_HID_ELO is not set +CONFIG_HID_EZKEY=y +# CONFIG_HID_GEMBIRD is not set +# CONFIG_HID_GFRM is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_TWINHAN is not set +CONFIG_HID_KENSINGTON=y +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LENOVO is not set +CONFIG_HID_LOGITECH=y +# CONFIG_HID_LOGITECH_HIDPP is not set +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGIG940_FF is not set +# CONFIG_LOGIWHEELS_FF is not set +# CONFIG_HID_MAGICMOUSE is not set +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PENMOUNT is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PLANTRONICS is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_RMI is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HID_SENSOR_HUB is not set +# CONFIG_HID_ALPS is not set + +# +# USB HID support +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV 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 is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB_CBAF 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=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +# 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=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +# 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 is not set +# 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 +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK 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 is not set +# CONFIG_USB_CHIPIDEA 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_SISUSBVGA 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 +# CONFIG_USB_CHAOSKEY 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=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_MV_UDC is not set +CONFIG_HIUSB_DEVICE2_0=y +CONFIG_USB_HISI_UDC=m +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_BDC_UDC is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_LIBCOMPOSITE=m +CONFIG_USB_F_MASS_STORAGE=m +# CONFIG_USB_CONFIGFS is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +CONFIG_USB_MASS_STORAGE=m +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP 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_ARMMMCI is not set +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_SPI is not set +# 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_HIMCI=y +CONFIG_SEND_AUTO_STOP=y +# 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 is not set +# CONFIG_DMADEVICES 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_PXA is not set +# CONFIG_COMMON_CLK_PIC32 is not set +CONFIG_COMMON_CLK_HI3518EV20X=y +CONFIG_RESET_HISI=y + +# +# Hardware Spinlock drivers +# + +# +# Clock Source drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_PROBE=y +CONFIG_CLKSRC_MMIO=y +CONFIG_ARM_TIMER_SP804=y +# 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 is not set +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC_MAX_NR=1 +CONFIG_ARM_VIC=y +CONFIG_ARM_VIC_NR=2 +# CONFIG_IPACK_BUS is not set +CONFIG_RESET_CONTROLLER=y +# CONFIG_RESET_ATH79 is not set +# CONFIG_RESET_BERLIN is not set +# CONFIG_RESET_LPC18XX is not set +# CONFIG_RESET_MESON is not set +# CONFIG_RESET_PISTACHIO is not set +# CONFIG_RESET_SOCFPGA is not set +# CONFIG_RESET_STM32 is not set +# CONFIG_RESET_SUNXI is not set +# CONFIG_TI_SYSCON_RESET is not set +# CONFIG_RESET_ZYNQ is not set +# CONFIG_FMC is not set + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +# 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_PHY_HISI_USB2=y +# 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 +CONFIG_HI_DMAC=y +CONFIG_HI_DMAC_CHANNEL_NUM=4 + +# +# Hisilicon driver support +# + +# +# Firmware Drivers +# +# CONFIG_FIRMWARE_MEMMAP is not set +# CONFIG_FW_CFG_SYSFS is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT2=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_ENCRYPTION is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_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=y +CONFIG_EXPORTFS=y +# CONFIG_EXPORTFS_BLOCK_OPS is not set +CONFIG_FILE_LOCKING=y +# CONFIG_MANDATORY_FILE_LOCKING is not set +# 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=y +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=m +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ORANGEFS_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_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_YAFFS_FS=y +CONFIG_YAFFS_YAFFS1=y +# CONFIG_YAFFS_9BYTE_TAGS is not set +# CONFIG_YAFFS_DOES_ECC is not set +CONFIG_YAFFS_YAFFS2=y +CONFIG_YAFFS_AUTO_YAFFS2=y +# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set +# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set +# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set +# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set +# CONFIG_YAFFS_DISABLE_BACKGROUND is not set +# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set +CONFIG_YAFFS_XATTR=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_ATIME_SUPPORT is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_FILE_CACHE=y +# CONFIG_SQUASHFS_FILE_DIRECT is not set +CONFIG_SQUASHFS_DECOMP_SINGLE=y +# CONFIG_SQUASHFS_DECOMP_MULTI is not set +# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set +# CONFIG_SQUASHFS_XATTR is not set +CONFIG_SQUASHFS_ZLIB=y +# CONFIG_SQUASHFS_LZ4 is not set +# CONFIG_SQUASHFS_LZO is not set +CONFIG_SQUASHFS_XZ=y +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# 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=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +# 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_ACL_SUPPORT=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 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set + +# +# Compile-time checks and compiler options +# +# CONFIG_DEBUG_INFO is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_PAGE_OWNER is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_SECTION_MISMATCH_WARN_ONLY=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_PAGE_POISONING is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_WQ_WATCHDOG is not set +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_ON_OOPS_VALUE=1 +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHED_INFO is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set +# CONFIG_TIMER_STATS is not set + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS 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_RCU_PERF_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_RCU_EQS_DEBUG is not set +# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP 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 is not set + +# +# Runtime Testing +# +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST 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_KGDB is not set +# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set +# CONFIG_UBSAN is not set +CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y +CONFIG_STRICT_DEVMEM=y +# CONFIG_IO_STRICT_DEVMEM is not set +# CONFIG_ARM_PTDUMP is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_LL 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_DEBUG_SET_MODULE_RONX is not set +# CONFIG_CORESIGHT is not set + +# +# Security options +# +# CONFIG_KEYS 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_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=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 is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +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 is not set +# CONFIG_CRYPTO_ECHAINIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# 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 is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# 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 is not set +# 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 is not set +# 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 is not set +# 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=y +CONFIG_CRYPTO_LZO=y +# 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 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 + +# +# 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_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_DECOMPRESS=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_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_LZ4=y +CONFIG_GENERIC_ALLOCATOR=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=y +CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_SBITMAP=y +# CONFIG_VIRTUALIZATION is not set diff --git a/br-ext-chip-hisilicon/board/hi3516cv200/kernel/hi3518ev200.generic.config b/br-ext-chip-hisilicon/board/hi3516cv200/kernel/hi3518ev200.generic.config new file mode 100644 index 000000000..c534f70b0 --- /dev/null +++ b/br-ext-chip-hisilicon/board/hi3516cv200/kernel/hi3518ev200.generic.config @@ -0,0 +1,2627 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 4.9.37 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_ARM_HAS_SG_CHAIN=y +CONFIG_MIGHT_HAVE_PCI=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_GENERIC_BUG=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_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +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_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_FHANDLE=y +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_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=17 +CONFIG_NMI_LOG_BUF_SHIFT=13 +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_CGROUPS=y +# CONFIG_MEMCG is not set +# CONFIG_BLK_CGROUP is not set +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_CFS_BANDWIDTH is not set +# CONFIG_RT_GROUP_SCHED is not set +# CONFIG_CGROUP_PIDS is not set +# CONFIG_CGROUP_FREEZER is not set +# CONFIG_CPUSETS is not set +# CONFIG_CGROUP_DEVICE is not set +# CONFIG_CGROUP_CPUACCT is not set +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_IPC_NS=y +# CONFIG_USER_NS is not set +CONFIG_PID_NS=y +CONFIG_NET_NS=y +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_RD_LZ4=y +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_BPF=y +# CONFIG_EXPERT is not set +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_ALL is not set +# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set +CONFIG_KALLSYMS_BASE_RELATIVE=y +CONFIG_PRINTK=y +CONFIG_PRINTK_NMI=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +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=y +CONFIG_SLUB_DEBUG=y +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# 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 is not set +# CONFIG_UPROBES is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +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_ARCH_HAS_GCOV_PROFILE_ALL=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=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=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +CONFIG_BLK_CMDLINE_PARSER=y + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_CMDLINE_PARTITION=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" +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=y + +# +# System Type +# +CONFIG_MMU=y +CONFIG_ARCH_MULTIPLATFORM=y +# 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_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 + +# +# Multiple platform selection +# + +# +# CPU Core family selection +# +# CONFIG_ARCH_MULTI_V4 is not set +# CONFIG_ARCH_MULTI_V4T is not set +CONFIG_ARCH_MULTI_V5=y +CONFIG_ARCH_MULTI_V4_V5=y +# CONFIG_ARCH_MULTI_V6 is not set +# CONFIG_ARCH_MULTI_V7 is not set +CONFIG_ARCH_MULTI_CPU_AUTO=y +# CONFIG_ARCH_MVEBU is not set +# CONFIG_MACH_ASM9260 is not set +# CONFIG_ARCH_AT91 is not set +CONFIG_ARCH_HISI_BVT=y + +# +# Hisilicon BVT platform type +# +CONFIG_ARCH_HI3518EV20X=y +CONFIG_HI_ZRELADDR=0x80008000 +CONFIG_HI_PARAMS_PHYS=0x00000100 +CONFIG_HI_INITRD_PHYS=0x00800000 +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_ASPEED is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_NSPIRE is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_OXNAS is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_WM8505 is not set + +# +# Processor Type +# +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_PABRT_LEGACY=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_USE_DOMAINS=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_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +CONFIG_NEED_KUSER_HELPERS=y +CONFIG_KUSER_HELPERS=y +# CONFIG_CACHE_L2X0 is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 +# CONFIG_DEBUG_RODATA is not set +CONFIG_MULTI_IRQ_HANDLER=y + +# +# Bus support +# +# CONFIG_PCI is not set +# 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 is not set +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=999999 +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_FRONTSWAP 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=y +# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set +CONFIG_CMDLINE="" +# 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 is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_ELFCORE=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=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=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_HIBERNATION is not set +CONFIG_PM_SLEEP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM_EMULATION is not set +CONFIG_PM_CLK=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_CPU_PM=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_NET=y +CONFIG_NET_INGRESS=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 is not set +# 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=m +# 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=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +# 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_IPV6_ILA is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_VTI is not set +CONFIG_IPV6_SIT=m +# 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=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_INGRESS=y +# CONFIG_NETFILTER_NETLINK_ACCT is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NF_TABLES is not set +# CONFIG_NETFILTER_XTABLES is not set +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV4 is not set +# CONFIG_NF_DUP_IPV4 is not set +# CONFIG_NF_LOG_ARP is not set +# CONFIG_NF_LOG_IPV4 is not set +# CONFIG_NF_REJECT_IPV4 is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set + +# +# IPv6: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV6 is not set +# CONFIG_NF_DUP_IPV6 is not set +# CONFIG_NF_REJECT_IPV6 is not set +# CONFIG_NF_LOG_IPV6 is not set +# CONFIG_IP6_NF_IPTABLES 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_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_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_CGROUP_NET_PRIO is not set +# CONFIG_CGROUP_NET_CLASSID 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 is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL 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 +# +CONFIG_ARM_AMBA=y + +# +# Generic Driver Options +# +# CONFIG_UEVENT_HELPER is not set +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set +CONFIG_ALLOW_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +# 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_SWAP 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 is not set +# 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_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_DENALI_DT is not set +# CONFIG_MTD_NAND_GPIO is not set +# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_DOCG4 is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_BRCMNAND is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_NAND_HISI504 is not set +# CONFIG_MTD_NAND_MTK is not set +CONFIG_MTD_SPI_NAND_HISI_BVT=y +# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set +# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set +CONFIG_MTD_SPI_NAND_HIFMC100=y +# 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 is not set +# CONFIG_SPI_CADENCE_QUADSPI is not set +CONFIG_SPI_HISI_SFC=y +# CONFIG_MTD_SPI_IDS is not set +CONFIG_CLOSE_SPI_8PIN_4IO=y +CONFIG_HISI_SPI_BLOCK_PROTECT=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_LIMIT=20 +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +# CONFIG_MTD_UBI_BLOCK 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=y +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=65536 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_NVME_TARGET is not set + +# +# Misc devices +# +# 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=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=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=y +# CONFIG_HIX5HD2_GMAC is not set +CONFIG_HISI_FEMAC=y +# CONFIG_HIP04_ETH is not set +# CONFIG_HNS is not set +# CONFIG_HNS_DSAF is not set +# CONFIG_HNS_ENET is not set +# CONFIG_HIETH_GMAC 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_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=y +# CONFIG_MDIO_HISI_GEMAC 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_IPHETH is not set +# CONFIG_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=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=y +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_BCM is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_BYD=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_CYPRESS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +CONFIG_MOUSE_PS2_FOCALTECH=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set +CONFIG_INPUT_JOYSTICK=y +# CONFIG_JOYSTICK_ANALOG is not set +# CONFIG_JOYSTICK_A3D is not set +# CONFIG_JOYSTICK_ADI is not set +# CONFIG_JOYSTICK_COBRA is not set +# CONFIG_JOYSTICK_GF2K is not set +# CONFIG_JOYSTICK_GRIP is not set +# CONFIG_JOYSTICK_GRIP_MP is not set +# CONFIG_JOYSTICK_GUILLEMOT is not set +# CONFIG_JOYSTICK_INTERACT is not set +# CONFIG_JOYSTICK_SIDEWINDER is not set +# CONFIG_JOYSTICK_TMDC is not set +# CONFIG_JOYSTICK_IFORCE is not set +# CONFIG_JOYSTICK_WARRIOR is not set +# CONFIG_JOYSTICK_MAGELLAN is not set +# CONFIG_JOYSTICK_SPACEORB is not set +# CONFIG_JOYSTICK_SPACEBALL is not set +# CONFIG_JOYSTICK_STINGER is not set +# CONFIG_JOYSTICK_TWIDJOY is not set +# CONFIG_JOYSTICK_ZHENHUA is not set +# CONFIG_JOYSTICK_AS5011 is not set +# CONFIG_JOYSTICK_JOYDUMP is not set +# CONFIG_JOYSTICK_XPAD 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=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_USERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=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=y + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +# 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_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_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM 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=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_MUX is not set +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# 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_HIBVT is not set +# CONFIG_I2C_NOMADIK 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_HISI=y +# 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_DEBUG is not set +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_GPIO is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +CONFIG_SPI_PL022=y +# 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=y +# 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_PINCONF=y +CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_AMD is not set +CONFIG_PINCTRL_SINGLE=y +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_GPIOLIB=y +CONFIG_OF_GPIO=y +CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers +# +# CONFIG_GPIO_74XX_MMIO is not set +# CONFIG_GPIO_ALTERA is not set +# 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_PL061=y +# CONFIG_GPIO_SYSCON 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_BRCMSTB is not set +# CONFIG_POWER_RESET_GPIO is not set +# CONFIG_POWER_RESET_GPIO_RESTART is not set +# CONFIG_POWER_RESET_LTC2952 is not set +# CONFIG_POWER_RESET_RESTART is not set +# CONFIG_POWER_RESET_VERSATILE is not set +CONFIG_POWER_RESET_SYSCON=y +# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set +# CONFIG_SYSCON_REBOOT_MODE is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27XXX is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_BQ25890 is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_CHARGER_RT9455 is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG 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=y +# 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_MFD_HISI_FMC=y +# 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=y +# 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 + +# +# Graphics support +# +# CONFIG_IMX_IPUV3_CORE is not set +# CONFIG_DRM is not set + +# +# ACP (Audio CoProcessor) Configuration +# + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_CMDLINE=y +CONFIG_FB_NOTIFY=y +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_IBM_GXT4500 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_FB_SSD1307 is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_VGASTATE is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set +# CONFIG_LOGO is not set +# CONFIG_SOUND is not set + +# +# HID support +# +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set +# CONFIG_HIDRAW is not set +# CONFIG_UHID is not set +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +CONFIG_HID_A4TECH=y +# CONFIG_HID_ACRUX is not set +CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_AUREAL is not set +CONFIG_HID_BELKIN=y +# CONFIG_HID_BETOP_FF is not set +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +# CONFIG_HID_CMEDIA is not set +# CONFIG_HID_CP2112 is not set +CONFIG_HID_CYPRESS=y +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_ELECOM is not set +# CONFIG_HID_ELO is not set +CONFIG_HID_EZKEY=y +# CONFIG_HID_GEMBIRD is not set +# CONFIG_HID_GFRM is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_TWINHAN is not set +CONFIG_HID_KENSINGTON=y +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LENOVO is not set +CONFIG_HID_LOGITECH=y +# CONFIG_HID_LOGITECH_HIDPP is not set +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGIG940_FF is not set +# CONFIG_LOGIWHEELS_FF is not set +# CONFIG_HID_MAGICMOUSE is not set +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PENMOUNT is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PLANTRONICS is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_RMI is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HID_SENSOR_HUB is not set +# CONFIG_HID_ALPS is not set + +# +# USB HID support +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV 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 is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB_CBAF 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=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +# 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=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +# 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 is not set +# 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 +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK 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 is not set +# CONFIG_USB_CHIPIDEA 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_SISUSBVGA 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 +# CONFIG_USB_CHAOSKEY 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=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_MV_UDC is not set +CONFIG_HIUSB_DEVICE2_0=y +CONFIG_USB_HISI_UDC=m +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_BDC_UDC is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_LIBCOMPOSITE=m +CONFIG_USB_F_MASS_STORAGE=m +# CONFIG_USB_CONFIGFS is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +CONFIG_USB_MASS_STORAGE=m +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_ULPI_BUS is not set +# CONFIG_UWB is not set +# CONFIG_MMC 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 is not set +# CONFIG_DMADEVICES 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_PXA is not set +# CONFIG_COMMON_CLK_PIC32 is not set +CONFIG_COMMON_CLK_HI3518EV20X=y +CONFIG_RESET_HISI=y + +# +# Hardware Spinlock drivers +# + +# +# Clock Source drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_PROBE=y +CONFIG_CLKSRC_MMIO=y +CONFIG_ARM_TIMER_SP804=y +# 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 is not set +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC_MAX_NR=1 +CONFIG_ARM_VIC=y +CONFIG_ARM_VIC_NR=2 +# CONFIG_IPACK_BUS is not set +CONFIG_RESET_CONTROLLER=y +# CONFIG_RESET_ATH79 is not set +# CONFIG_RESET_BERLIN is not set +# CONFIG_RESET_LPC18XX is not set +# CONFIG_RESET_MESON is not set +# CONFIG_RESET_PISTACHIO is not set +# CONFIG_RESET_SOCFPGA is not set +# CONFIG_RESET_STM32 is not set +# CONFIG_RESET_SUNXI is not set +# CONFIG_TI_SYSCON_RESET is not set +# CONFIG_RESET_ZYNQ is not set +# CONFIG_FMC is not set + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +# 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_PHY_HISI_USB2=y +# 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 +CONFIG_HI_DMAC=y +CONFIG_HI_DMAC_CHANNEL_NUM=4 + +# +# Hisilicon driver support +# + +# +# Firmware Drivers +# +# CONFIG_FIRMWARE_MEMMAP is not set +# CONFIG_FW_CFG_SYSFS is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT2=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_ENCRYPTION is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_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=y +CONFIG_EXPORTFS=y +# CONFIG_EXPORTFS_BLOCK_OPS is not set +CONFIG_FILE_LOCKING=y +# CONFIG_MANDATORY_FILE_LOCKING is not set +# 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=y +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=m +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ORANGEFS_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_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_YAFFS_FS=y +CONFIG_YAFFS_YAFFS1=y +# CONFIG_YAFFS_9BYTE_TAGS is not set +# CONFIG_YAFFS_DOES_ECC is not set +CONFIG_YAFFS_YAFFS2=y +CONFIG_YAFFS_AUTO_YAFFS2=y +# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set +# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set +# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set +# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set +# CONFIG_YAFFS_DISABLE_BACKGROUND is not set +# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set +CONFIG_YAFFS_XATTR=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_ATIME_SUPPORT is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_FILE_CACHE=y +# CONFIG_SQUASHFS_FILE_DIRECT is not set +CONFIG_SQUASHFS_DECOMP_SINGLE=y +# CONFIG_SQUASHFS_DECOMP_MULTI is not set +# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set +# CONFIG_SQUASHFS_XATTR is not set +CONFIG_SQUASHFS_ZLIB=y +# CONFIG_SQUASHFS_LZ4 is not set +# CONFIG_SQUASHFS_LZO is not set +CONFIG_SQUASHFS_XZ=y +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# 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=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +# 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_ACL_SUPPORT=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 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set + +# +# Compile-time checks and compiler options +# +# CONFIG_DEBUG_INFO is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_PAGE_OWNER is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_SECTION_MISMATCH_WARN_ONLY=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_PAGE_POISONING is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_WQ_WATCHDOG is not set +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_ON_OOPS_VALUE=1 +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHED_INFO is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set +# CONFIG_TIMER_STATS is not set + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS 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_RCU_PERF_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_RCU_EQS_DEBUG is not set +# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP 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 is not set + +# +# Runtime Testing +# +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST 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_KGDB is not set +# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set +# CONFIG_UBSAN is not set +CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y +CONFIG_STRICT_DEVMEM=y +# CONFIG_IO_STRICT_DEVMEM is not set +# CONFIG_ARM_PTDUMP is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_LL 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_DEBUG_SET_MODULE_RONX is not set +# CONFIG_CORESIGHT is not set + +# +# Security options +# +# CONFIG_KEYS 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_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=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 is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +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 is not set +# CONFIG_CRYPTO_ECHAINIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# 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 is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# 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 is not set +# 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 is not set +# 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 is not set +# 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=y +CONFIG_CRYPTO_LZO=y +# 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 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 + +# +# 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_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_DECOMPRESS=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_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_LZ4=y +CONFIG_GENERIC_ALLOCATOR=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=y +CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_SBITMAP=y +# CONFIG_VIRTUALIZATION is not set diff --git a/br-ext-chip-hisilicon/board/hi3516cv200/kernel/hi3518ev201.generic.config b/br-ext-chip-hisilicon/board/hi3516cv200/kernel/hi3518ev201.generic.config new file mode 100644 index 000000000..954c11d0a --- /dev/null +++ b/br-ext-chip-hisilicon/board/hi3516cv200/kernel/hi3518ev201.generic.config @@ -0,0 +1,2331 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 4.9.37 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_ARM_HAS_SG_CHAIN=y +CONFIG_MIGHT_HAVE_PCI=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_GENERIC_BUG=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_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +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_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_FHANDLE=y +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_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=17 +CONFIG_NMI_LOG_BUF_SHIFT=13 +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_CGROUPS=y +# CONFIG_MEMCG is not set +# CONFIG_BLK_CGROUP is not set +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_CFS_BANDWIDTH is not set +# CONFIG_RT_GROUP_SCHED is not set +# CONFIG_CGROUP_PIDS is not set +# CONFIG_CGROUP_FREEZER is not set +# CONFIG_CPUSETS is not set +# CONFIG_CGROUP_DEVICE is not set +# CONFIG_CGROUP_CPUACCT is not set +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_IPC_NS=y +# CONFIG_USER_NS is not set +CONFIG_PID_NS=y +CONFIG_NET_NS=y +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_RD_LZ4=y +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_BPF=y +# CONFIG_EXPERT is not set +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_ALL is not set +# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set +CONFIG_KALLSYMS_BASE_RELATIVE=y +CONFIG_PRINTK=y +CONFIG_PRINTK_NMI=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +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=y +CONFIG_SLUB_DEBUG=y +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# 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 is not set +# CONFIG_UPROBES is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +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_ARCH_HAS_GCOV_PROFILE_ALL=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=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=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +CONFIG_BLK_CMDLINE_PARSER=y + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_CMDLINE_PARTITION=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" +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=y + +# +# System Type +# +CONFIG_MMU=y +CONFIG_ARCH_MULTIPLATFORM=y +# 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_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 + +# +# Multiple platform selection +# + +# +# CPU Core family selection +# +# CONFIG_ARCH_MULTI_V4 is not set +# CONFIG_ARCH_MULTI_V4T is not set +CONFIG_ARCH_MULTI_V5=y +CONFIG_ARCH_MULTI_V4_V5=y +# CONFIG_ARCH_MULTI_V6 is not set +# CONFIG_ARCH_MULTI_V7 is not set +CONFIG_ARCH_MULTI_CPU_AUTO=y +# CONFIG_ARCH_MVEBU is not set +# CONFIG_MACH_ASM9260 is not set +# CONFIG_ARCH_AT91 is not set +CONFIG_ARCH_HISI_BVT=y + +# +# Hisilicon BVT platform type +# +CONFIG_ARCH_HI3518EV20X=y +CONFIG_HI_ZRELADDR=0x80008000 +CONFIG_HI_PARAMS_PHYS=0x00000100 +CONFIG_HI_INITRD_PHYS=0x00800000 +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_ASPEED is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_NSPIRE is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_OXNAS is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_WM8505 is not set + +# +# Processor Type +# +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_PABRT_LEGACY=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_USE_DOMAINS=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_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +CONFIG_NEED_KUSER_HELPERS=y +CONFIG_KUSER_HELPERS=y +# CONFIG_CACHE_L2X0 is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 +# CONFIG_DEBUG_RODATA is not set +CONFIG_MULTI_IRQ_HANDLER=y + +# +# Bus support +# +# CONFIG_PCI is not set +# 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 is not set +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=999999 +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_FRONTSWAP 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=y +# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set +CONFIG_CMDLINE="" +# 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 is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_ELFCORE=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=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=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_HIBERNATION is not set +CONFIG_PM_SLEEP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM_EMULATION is not set +CONFIG_PM_CLK=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_CPU_PM=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_NET=y +CONFIG_NET_INGRESS=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 is not set +# 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=m +# 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=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +# 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_IPV6_ILA is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_VTI is not set +CONFIG_IPV6_SIT=m +# 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=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_INGRESS=y +# CONFIG_NETFILTER_NETLINK_ACCT is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NF_TABLES is not set +# CONFIG_NETFILTER_XTABLES is not set +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV4 is not set +# CONFIG_NF_DUP_IPV4 is not set +# CONFIG_NF_LOG_ARP is not set +# CONFIG_NF_LOG_IPV4 is not set +# CONFIG_NF_REJECT_IPV4 is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set + +# +# IPv6: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV6 is not set +# CONFIG_NF_DUP_IPV6 is not set +# CONFIG_NF_REJECT_IPV6 is not set +# CONFIG_NF_LOG_IPV6 is not set +# CONFIG_IP6_NF_IPTABLES 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_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_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_CGROUP_NET_PRIO is not set +# CONFIG_CGROUP_NET_CLASSID 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 is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL 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 +# +CONFIG_ARM_AMBA=y + +# +# Generic Driver Options +# +# CONFIG_UEVENT_HELPER is not set +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set +CONFIG_ALLOW_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +# 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_SWAP 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 is not set +# 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 is not set +# CONFIG_SPI_CADENCE_QUADSPI is not set +CONFIG_SPI_HISI_SFC=y +# CONFIG_MTD_SPI_IDS is not set +CONFIG_CLOSE_SPI_8PIN_4IO=y +CONFIG_HISI_SPI_BLOCK_PROTECT=y +# 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=y +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=65536 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_NVME_TARGET is not set + +# +# Misc devices +# +# 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=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=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=y +# CONFIG_HIX5HD2_GMAC is not set +CONFIG_HISI_FEMAC=y +# CONFIG_HIP04_ETH is not set +# CONFIG_HNS is not set +# CONFIG_HNS_DSAF is not set +# CONFIG_HNS_ENET is not set +# CONFIG_HIETH_GMAC 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_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=y +# CONFIG_MDIO_HISI_GEMAC 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 + +# +# Host-side USB support is needed for USB Network Adapter support +# +# CONFIG_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=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=y +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_BCM is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_BYD=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_CYPRESS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +CONFIG_MOUSE_PS2_FOCALTECH=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +CONFIG_INPUT_JOYSTICK=y +# CONFIG_JOYSTICK_ANALOG is not set +# CONFIG_JOYSTICK_A3D is not set +# CONFIG_JOYSTICK_ADI is not set +# CONFIG_JOYSTICK_COBRA is not set +# CONFIG_JOYSTICK_GF2K is not set +# CONFIG_JOYSTICK_GRIP is not set +# CONFIG_JOYSTICK_GRIP_MP is not set +# CONFIG_JOYSTICK_GUILLEMOT is not set +# CONFIG_JOYSTICK_INTERACT is not set +# CONFIG_JOYSTICK_SIDEWINDER is not set +# CONFIG_JOYSTICK_TMDC is not set +# CONFIG_JOYSTICK_IFORCE is not set +# CONFIG_JOYSTICK_WARRIOR is not set +# CONFIG_JOYSTICK_MAGELLAN is not set +# CONFIG_JOYSTICK_SPACEORB is not set +# CONFIG_JOYSTICK_SPACEBALL is not set +# CONFIG_JOYSTICK_STINGER is not set +# CONFIG_JOYSTICK_TWIDJOY is not set +# CONFIG_JOYSTICK_ZHENHUA is not set +# CONFIG_JOYSTICK_AS5011 is not set +# CONFIG_JOYSTICK_JOYDUMP 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=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_USERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=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=y + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +# 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_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_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM 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=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_MUX is not set +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# 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_HIBVT is not set +# CONFIG_I2C_NOMADIK 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_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set + +# +# Other I2C/SMBus bus drivers +# +CONFIG_I2C_HISI=y +# 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_DEBUG is not set +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_GPIO is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +CONFIG_SPI_PL022=y +# 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=y +# 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_PINCONF=y +CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_AMD is not set +CONFIG_PINCTRL_SINGLE=y +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_GPIOLIB=y +CONFIG_OF_GPIO=y +CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers +# +# CONFIG_GPIO_74XX_MMIO is not set +# CONFIG_GPIO_ALTERA is not set +# 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_PL061=y +# CONFIG_GPIO_SYSCON 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 +# 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_BRCMSTB is not set +# CONFIG_POWER_RESET_GPIO is not set +# CONFIG_POWER_RESET_GPIO_RESTART is not set +# CONFIG_POWER_RESET_LTC2952 is not set +# CONFIG_POWER_RESET_RESTART is not set +# CONFIG_POWER_RESET_VERSATILE is not set +CONFIG_POWER_RESET_SYSCON=y +# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set +# CONFIG_SYSCON_REBOOT_MODE is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27XXX is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_BQ25890 is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_CHARGER_RT9455 is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG 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=y +# 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_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_MFD_HISI_FMC=y +# 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_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_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=y +# 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 + +# +# Graphics support +# +# CONFIG_IMX_IPUV3_CORE is not set +# CONFIG_DRM is not set + +# +# ACP (Audio CoProcessor) Configuration +# + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_CMDLINE=y +CONFIG_FB_NOTIFY=y +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_IBM_GXT4500 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_FB_SSD1307 is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_VGASTATE is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set +# CONFIG_LOGO is not set +# CONFIG_SOUND is not set + +# +# HID support +# +# CONFIG_HID is not set + +# +# I2C HID support +# +# CONFIG_I2C_HID is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SUPPORT is not set +# CONFIG_UWB is not set +# CONFIG_MMC 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 is not set +# CONFIG_DMADEVICES 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_PXA is not set +# CONFIG_COMMON_CLK_PIC32 is not set +CONFIG_COMMON_CLK_HI3518EV20X=y +CONFIG_RESET_HISI=y + +# +# Hardware Spinlock drivers +# + +# +# Clock Source drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_PROBE=y +CONFIG_CLKSRC_MMIO=y +CONFIG_ARM_TIMER_SP804=y +# 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 is not set +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC_MAX_NR=1 +CONFIG_ARM_VIC=y +CONFIG_ARM_VIC_NR=2 +# CONFIG_IPACK_BUS is not set +CONFIG_RESET_CONTROLLER=y +# CONFIG_RESET_ATH79 is not set +# CONFIG_RESET_BERLIN is not set +# CONFIG_RESET_LPC18XX is not set +# CONFIG_RESET_MESON is not set +# CONFIG_RESET_PISTACHIO is not set +# CONFIG_RESET_SOCFPGA is not set +# CONFIG_RESET_STM32 is not set +# CONFIG_RESET_SUNXI is not set +# CONFIG_TI_SYSCON_RESET is not set +# CONFIG_RESET_ZYNQ is not set +# CONFIG_FMC is not set + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +# 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_PHY_HISI_USB2=y +# 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 +CONFIG_HI_DMAC=y +CONFIG_HI_DMAC_CHANNEL_NUM=4 + +# +# Hisilicon driver support +# + +# +# Firmware Drivers +# +# CONFIG_FIRMWARE_MEMMAP is not set +# CONFIG_FW_CFG_SYSFS is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT2=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_ENCRYPTION is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +CONFIG_GFS2_FS=y +# 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=y +CONFIG_EXPORTFS=y +# CONFIG_EXPORTFS_BLOCK_OPS is not set +CONFIG_FILE_LOCKING=y +# CONFIG_MANDATORY_FILE_LOCKING is not set +# 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_QUOTA_NETLINK_INTERFACE=y +CONFIG_QUOTACTL=y +# 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=y +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=m +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ORANGEFS_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_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_YAFFS_FS=y +CONFIG_YAFFS_YAFFS1=y +# CONFIG_YAFFS_9BYTE_TAGS is not set +# CONFIG_YAFFS_DOES_ECC is not set +CONFIG_YAFFS_YAFFS2=y +CONFIG_YAFFS_AUTO_YAFFS2=y +# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set +# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set +# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set +# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set +# CONFIG_YAFFS_DISABLE_BACKGROUND is not set +# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set +CONFIG_YAFFS_XATTR=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y +CONFIG_SQUASHFS_FILE_CACHE=y +# CONFIG_SQUASHFS_FILE_DIRECT is not set +CONFIG_SQUASHFS_DECOMP_SINGLE=y +# CONFIG_SQUASHFS_DECOMP_MULTI is not set +# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set +# CONFIG_SQUASHFS_XATTR is not set +CONFIG_SQUASHFS_ZLIB=y +# CONFIG_SQUASHFS_LZ4 is not set +# CONFIG_SQUASHFS_LZO is not set +CONFIG_SQUASHFS_XZ=y +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# 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=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +# 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_ACL_SUPPORT=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 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set + +# +# Compile-time checks and compiler options +# +# CONFIG_DEBUG_INFO is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_PAGE_OWNER is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_SECTION_MISMATCH_WARN_ONLY=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_PAGE_POISONING is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_WQ_WATCHDOG is not set +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_ON_OOPS_VALUE=1 +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHED_INFO is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set +# CONFIG_TIMER_STATS is not set + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS 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_RCU_PERF_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_RCU_EQS_DEBUG is not set +# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP 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 is not set + +# +# Runtime Testing +# +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST 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_KGDB is not set +# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set +# CONFIG_UBSAN is not set +CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y +CONFIG_STRICT_DEVMEM=y +# CONFIG_IO_STRICT_DEVMEM is not set +# CONFIG_ARM_PTDUMP is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_LL 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_DEBUG_SET_MODULE_RONX is not set +# CONFIG_CORESIGHT is not set + +# +# Security options +# +# CONFIG_KEYS 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_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +# CONFIG_CRYPTO_RSA is not set +# CONFIG_CRYPTO_DH is not set +# CONFIG_CRYPTO_ECDH is not set +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +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 is not set +# CONFIG_CRYPTO_ECHAINIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# 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 is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# 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 is not set +# 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 is not set +# 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 is not set +# 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 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 + +# +# 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_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_DECOMPRESS=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_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_LZ4=y +CONFIG_GENERIC_ALLOCATOR=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=y +CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_SBITMAP=y +# CONFIG_VIRTUALIZATION is not set diff --git a/br-ext-chip-hisilicon/board/hi3516cv200/kernel/patches/hi3516cv200_kernel-4.9.37_sdk-1.0.5.0.patch b/br-ext-chip-hisilicon/board/hi3516cv200/kernel/patches/hi3516cv200_kernel-4.9.37_sdk-1.0.5.0.patch new file mode 100644 index 000000000..41a0c16f7 --- /dev/null +++ b/br-ext-chip-hisilicon/board/hi3516cv200/kernel/patches/hi3516cv200_kernel-4.9.37_sdk-1.0.5.0.patch @@ -0,0 +1,199311 @@ +diff --git a/.gitignore b/.gitignore +index c2ed4ec..d67212e 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -114,3 +114,4 @@ all.config + + # Kdevelop4 + *.kdev4 ++arch/arm64/boot/uImage +diff --git a/Documentation/devicetree/bindings/net/hisilicon-femac.txt b/Documentation/devicetree/bindings/net/hisilicon-femac.txt +index d11af5e..17da719 100644 +--- a/Documentation/devicetree/bindings/net/hisilicon-femac.txt ++++ b/Documentation/devicetree/bindings/net/hisilicon-femac.txt +@@ -4,7 +4,10 @@ Required properties: + - compatible: should contain one of the following version strings: + * "hisilicon,hisi-femac-v1" + * "hisilicon,hisi-femac-v2" +- and the soc string "hisilicon,hi3516cv300-femac". ++ and one of the following soc strings: ++ * "hisilicon,hi3516cv300-femac" ++ * "hisilicon,hi3536dv100-femac" ++ * "hisilicon,hi3518ev20x-femac" + - reg: specifies base physical address(s) and size of the device registers. + The first region is the MAC core register base and size. + The second region is the global MAC control register. +diff --git a/Documentation/devicetree/bindings/net/hisilicon-gemac-mdio.txt b/Documentation/devicetree/bindings/net/hisilicon-gemac-mdio.txt +new file mode 100644 +index 0000000..c6f8202 +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/hisilicon-gemac-mdio.txt +@@ -0,0 +1,22 @@ ++Hisilicon Gigabit Ethernet MDIO Controller interface ++ ++Required properties: ++- compatible: should be "hisilicon,hisi-gemac-mdio". ++- reg: address and length of the register set for the device. ++- clocks: A phandle to the reference clock for this device. ++ ++- PHY subnode: inherits from phy binding [1] ++[1] Documentation/devicetree/bindings/net/phy.txt ++ ++Example: ++mdio: mdio@100503c0 { ++ compatible = "hisilicon,hisi-gemac-mdio"; ++ reg = <0x100503c0 0x20>; ++ clocks = <&crg HI3519V100_MDIO_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ phy0: phy@1 { ++ reg = <1>; ++ }; ++}; +diff --git a/Documentation/devicetree/bindings/net/hisilicon-higmac.txt b/Documentation/devicetree/bindings/net/hisilicon-higmac.txt +new file mode 100644 +index 0000000..ea096d2 +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/hisilicon-higmac.txt +@@ -0,0 +1,52 @@ ++Hisilicon higmac controller ++ ++Required properties: ++- compatible: should be "hisilicon,higmac" and one of the following: ++ - "hisilicon,higmac-v1" ++ - "hisilicon,higmac-v2" ++ - "hisilicon,higmac-v3" ++ - "hisilicon,higmac-v4" ++ - "hisilicon,higmac-v5" ++- reg: specifies base physical address(s) and size of the device registers. ++ The first region is the MAC register base and size. ++ The second region is external interface control register. ++- interrupts: should contain the MAC interrupt. ++- #address-cells: must be <1>. ++- #size-cells: must be <0>. ++- phy-mode: see ethernet.txt [1]. ++- phy-handle: see ethernet.txt [1]. ++- mac-address: see ethernet.txt [1]. ++- clocks: clock phandle and specifier pair. ++- resets: reset controller phandle and specifier pair. ++ ++- PHY subnode: inherits from phy binding [2] ++ ++[1] Documentation/devicetree/bindings/net/ethernet.txt ++[2] Documentation/devicetree/bindings/net/phy.txt ++ ++Example: ++ higmac: ethernet@10050000 { ++ compatible = "hisilicon,higmac"; ++ reg = <0x10050000 0x1000>,<0x120100ec 0x4>; ++ interrupts = <0 25 4>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ phy-mode = "rgmii"; ++ phy-handle = <ð_phy>; ++ mac-address = [00 00 00 00 00 00]; ++ clocks = <&clock HI3519_ETH_CLK>, ++ <&clock HI3519_ETH_MACIF_CLK>; ++ clock-names = "higmac_clk", ++ "macif_clk"; ++ ++ resets = <&clock 0xcc 0>, ++ <&clock 0xcc 2>, ++ <&clock 0xcc 7>; ++ reset-names = "port_reset", ++ "macif_reset", ++ "phy_reset"; ++ ++ eth_phy: ethernet-phy@1 { ++ reg = <1>; ++ }; ++ }; +diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt +index 7ab9404..501222b 100644 +--- a/Documentation/networking/phy.txt ++++ b/Documentation/networking/phy.txt +@@ -347,3 +347,12 @@ Board Fixups + The stubs set one of the two matching criteria, and set the other one to + match anything. + ++ When phy_register_fixup() or *_for_uid()/*_for_id() is called at module, ++ unregister fixup and free allocate memory are required. ++ ++ Call one of following function before unloading module. ++ ++ int phy_unregister_fixup(const char *phy_id, u32 phy_uid, u32 phy_uid_mask); ++ int phy_unregister_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask); ++ int phy_register_fixup_for_id(const char *phy_id); ++ +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index b5d529f..100df1d 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -747,6 +747,8 @@ source "arch/arm/mach-highbank/Kconfig" + + source "arch/arm/mach-hisi/Kconfig" + ++source "arch/arm/mach-hibvt/Kconfig" ++ + source "arch/arm/mach-integrator/Kconfig" + + source "arch/arm/mach-iop32x/Kconfig" +diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug +index d83f7c3..66ef450 100644 +--- a/arch/arm/Kconfig.debug ++++ b/arch/arm/Kconfig.debug +@@ -287,6 +287,46 @@ choice + Say Y here if you want kernel low-level debugging support + on HI3620 UART. + ++ config DEBUG_HI3516A_UART ++ bool "Hisilicon Hi3516A Debug UART" ++ depends on ARCH_HI3516A ++ select DEBUG_UART_PL01X ++ help ++ Say Y here if you want kernel low-level debugging support ++ on HI3516A UART. ++ ++ config DEBUG_HI3518EV20X_UART ++ bool "Hisilicon Hi3518EV20X Debug UART" ++ depends on ARCH_HI3518EV20X ++ select DEBUG_UART_PL01X ++ help ++ Say Y here if you want kernel low-level debugging support ++ on HI3518EV20X UART. ++ ++ config DEBUG_HI3536DV100_UART ++ bool "Hisilicon Hi3536DV100 Debug UART" ++ depends on ARCH_HI3536DV100 ++ select DEBUG_UART_PL01X ++ help ++ Say Y here if you want kernel low-level debugging support ++ on HI3536DV100 UART. ++ ++ config DEBUG_HI3521A_UART ++ bool "Hisilicon Hi3521A Debug UART" ++ depends on ARCH_HI3521A ++ select DEBUG_UART_PL01X ++ help ++ Say Y here if you want kernel low-level debugging support ++ on HI3521A UART. ++ ++ config DEBUG_HI3531A_UART ++ bool "Hisilicon Hi3531A Debug UART" ++ depends on ARCH_HI3531A ++ select DEBUG_UART_PL01X ++ help ++ Say Y here if you want kernel low-level debugging support ++ on HI3531A UART. ++ + config DEBUG_HIGHBANK_UART + bool "Kernel low-level debugging messages via Highbank UART" + depends on ARCH_HIGHBANK +@@ -1530,6 +1570,11 @@ config DEBUG_UART_PHYS + default 0xf991e000 if DEBUG_QCOM_UARTDM + default 0xfc00c000 if DEBUG_AT91_SAMA5D4_USART3 + default 0xfcb00000 if DEBUG_HI3620_UART ++ default 0x20080000 if DEBUG_HI3516A_UART ++ default 0x20080000 if DEBUG_HI3518EV20X_UART ++ default 0x12080000 if DEBUG_HI3536DV100_UART ++ default 0x12080000 if DEBUG_HI3521A_UART ++ default 0x12080000 if DEBUG_HI3531A_UART + default 0xfd883000 if DEBUG_ALPINE_UART0 + default 0xfe800000 if ARCH_IOP32X + default 0xff690000 if DEBUG_RK32_UART2 +@@ -1619,6 +1664,11 @@ config DEBUG_UART_VIRT + default 0xfe300000 if DEBUG_BCM_KONA_UART + default 0xfe800000 if ARCH_IOP32X + default 0xfeb00000 if DEBUG_HI3620_UART || DEBUG_HIX5HD2_UART ++ default 0xfe900000 if DEBUG_HI3516A_UART ++ default 0xfe180000 if DEBUG_HI3518EV20X_UART ++ default 0xfe480000 if DEBUG_HI3536DV100_UART ++ default 0xfe480000 if DEBUG_HI3521A_UART ++ default 0xfe880000 if DEBUG_HI3531A_UART + default 0xfeb24000 if DEBUG_RK3X_UART0 + default 0xfeb26000 if DEBUG_RK3X_UART1 + default 0xfeb30c00 if DEBUG_KEYSTONE_UART0 +diff --git a/arch/arm/Makefile b/arch/arm/Makefile +index 6be9ee1..53409ce 100644 +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -170,6 +170,7 @@ machine-$(CONFIG_ARCH_FOOTBRIDGE) += footbridge + machine-$(CONFIG_ARCH_GEMINI) += gemini + machine-$(CONFIG_ARCH_HIGHBANK) += highbank + machine-$(CONFIG_ARCH_HISI) += hisi ++machine-$(CONFIG_ARCH_HISI_BVT) += hibvt + machine-$(CONFIG_ARCH_INTEGRATOR) += integrator + machine-$(CONFIG_ARCH_IOP13XX) += iop13xx + machine-$(CONFIG_ARCH_IOP32X) += iop32x +@@ -268,6 +269,10 @@ endif + endif + endif + ++ifeq ($(CONFIG_ARCH_HISI_BVT),y) ++KBUILD_CPPFLAGS += $(patsubst %,-I%include,$(machdirs) $(platdirs)) ++endif ++ + export TEXT_OFFSET GZFLAGS MMUEXT + + # Do we have FASTFPE? +diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile +index 50f8d1b..9732bdf 100644 +--- a/arch/arm/boot/Makefile ++++ b/arch/arm/boot/Makefile +@@ -16,6 +16,8 @@ OBJCOPYFLAGS :=-O binary -R .comment -S + ifneq ($(MACHINE),) + include $(MACHINE)/Makefile.boot + endif ++include $(srctree)/arch/arm/mach-hibvt/Makefile.boot ++include $(srctree)/arch/arm/boot/dts/Makefile + + # Note: the following conditions must always be true: + # ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET) +@@ -24,10 +26,12 @@ endif + ZRELADDR := $(zreladdr-y) + PARAMS_PHYS := $(params_phys-y) + INITRD_PHYS := $(initrd_phys-y) ++DTB_OBJS ?= $(dtb-y) ++DTB_OBJS_FULL := $(addprefix $(obj)/dts/,$(DTB_OBJS)) + + export ZRELADDR INITRD_PHYS PARAMS_PHYS + +-targets := Image zImage xipImage bootpImage uImage ++targets := Image zImage xipImage bootpImage uImage zImage-dtb + + ifeq ($(CONFIG_XIP_KERNEL),y) + +@@ -55,6 +59,10 @@ $(obj)/compressed/vmlinux: $(obj)/Image FORCE + $(obj)/zImage: $(obj)/compressed/vmlinux FORCE + $(call if_changed,objcopy) + ++$(obj)/zImage-dtb: $(obj)/zImage $(DTB_OBJS_FULL) FORCE ++ @cat $(obj)/zImage $(DTB_OBJS_FULL) > $@ ++ @$(kecho) ' Kernel: $@ is ready' ++ + endif + + ifneq ($(LOADADDR),) +@@ -75,7 +83,7 @@ if [ $(words $(UIMAGE_LOADADDR)) -ne 1 ]; then \ + false; \ + fi + +-$(obj)/uImage: $(obj)/zImage FORCE ++$(obj)/uImage: $(obj)/zImage-dtb FORCE + @$(check_for_multiple_loadaddr) + $(call if_changed,uimage) + +diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S +index fc6d541..9c0a324 100644 +--- a/arch/arm/boot/compressed/head.S ++++ b/arch/arm/boot/compressed/head.S +@@ -218,6 +218,20 @@ not_angel: + addcc r0, r0, pc + cmpcc r4, r0 + orrcc r4, r4, #1 @ remember we skipped cache_on ++ ++/*TODO all the Cortex-A7 Single Core must fix this bug */ ++#if defined(CONFIG_ARCH_HI3516A) || defined(CONFIG_ARCH_HI3536DV100) ++/* ++ * This is a bug on Cortex-A7 MPCORE. see buglist of Cortex-A7 ++ * The D-caches are disabled when ACTLR.SMP is set to 0 regardless of the ++ * value of the cache enable bit. so we must set SMP bit of ACTLR register ++ * before enable D cache ++ */ ++ 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/dts/Makefile b/arch/arm/boot/dts/Makefile +index 7037201..b7b8e2a 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -174,6 +174,16 @@ dtb-$(CONFIG_ARCH_HISI) += \ + hi3519-demb.dtb + dtb-$(CONFIG_ARCH_HIX5HD2) += \ + hisi-x5hd2-dkb.dtb ++dtb-$(CONFIG_ARCH_HI3516A) += \ ++ hi3516a-demb.dtb ++dtb-$(CONFIG_ARCH_HI3518EV20X) += \ ++ hi3518ev20x-demb.dtb ++dtb-$(CONFIG_ARCH_HI3521A) += \ ++ hi3521a-demb.dtb ++dtb-$(CONFIG_ARCH_HI3531A) += \ ++ hi3531a-demb.dtb ++dtb-$(CONFIG_ARCH_HI3536DV100) += \ ++ hi3536dv100-demb.dtb + dtb-$(CONFIG_ARCH_INTEGRATOR) += \ + integratorap.dtb \ + integratorcp.dtb +diff --git a/arch/arm/boot/dts/hi3516a-demb.dts b/arch/arm/boot/dts/hi3516a-demb.dts +new file mode 100644 +index 0000000..ca9f7bc +--- /dev/null ++++ b/arch/arm/boot/dts/hi3516a-demb.dts +@@ -0,0 +1,233 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/dts-v1/; ++#include "hi3516a.dtsi" ++ ++/ { ++ model = "Hisilicon HI3516A DEMO Board"; ++ compatible = "hiSilicon,hi3516a"; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a7"; ++ reg = <0>; ++ ++ operating-points = < ++ /* KHz uV */ ++ 600000 1100000 ++ 732000 1200000 ++ 850000 1300000 ++ 500000 1060000 ++ 400000 1020000 ++ >; ++ ++ clocks = <&clock HI3516A_A7_MUX>, ++ <&clock HI3516A_FIXED_400M>, ++ <&clock HI3516A_FIXED_500M>, ++ <&clock HI3516A_APLL_CLK>; ++ clock-names = "a7_mux","400m", "500m","apll"; ++ ++ vcc-supply = <&a7_regulator>; ++ }; ++ }; ++ ++ avs { ++ compatible = "hi3516a,avs"; ++ avs-num = <2>; ++ avs-name-array = "cpu-avs","media-avs"; ++ cpu_avs: cpu_avs{ ++ avs-name = "cpu-avs"; ++ opp-num = <5>; ++ opp-freq = <600000 732000 850000 500000 400000>; ++ opp-volt-min = <940000 1000000 1070000 940000 940000>; ++ opp-hpm = <270 325 365 255 240>; ++ opp-div = <11 14 16 10 8>; ++ opp-volt-max = <1310000>; ++ }; ++ ++ media_avs: media_avs{ ++ avs-name = "media-avs"; ++ opp-num = <5>; ++ opp-freq = <0 1 2 3 4>; ++ opp-volt-min = <930000 930000 930000 930000 930000>; ++ opp-hpm = <245 245 245 260 285>; ++ opp-div = <3 3 4 5 5>; ++ opp-volt-max = <1310000>; ++ }; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x40000000>; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&dual_timer0 { ++ status = "okay"; ++}; ++ ++&hidmac { ++ status = "okay"; ++}; ++ ++&i2c_bus0 { ++ status = "okay"; ++}; ++ ++&i2c_bus1 { ++ status = "okay"; ++}; ++ ++&i2c_bus2 { ++ status = "okay"; ++}; ++ ++&spi_bus0{ ++ status = "okay"; ++ num-cs = <1>; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <24000000>; ++ }; ++}; ++ ++&spi_bus1{ ++ status = "okay"; ++ num-cs = <3>; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <24000000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <24000000>; ++ }; ++ ++ spidev@2 { ++ compatible = "rohm,dh2228fv"; ++ reg = <2>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <24000000>; ++ }; ++}; ++ ++&mdio { ++ ethphy: ethernet-phy@1 { ++ reg = <1>; ++ }; ++}; ++ ++&higmac { ++ phy-handle = <ðphy>; ++ phy-mode = "rgmii"; ++}; ++ ++&mmc0 { ++ status = "okay"; ++}; ++ ++&mmc1 { ++ status = "okay"; ++}; ++ ++&gpio_chip0 { ++ status = "okay"; ++}; ++ ++&gpio_chip1 { ++ status = "okay"; ++}; ++ ++&gpio_chip2 { ++ status = "okay"; ++}; ++ ++&gpio_chip3 { ++ status = "okay"; ++}; ++ ++&gpio_chip4 { ++ status = "okay"; ++}; ++ ++&gpio_chip5 { ++ status = "okay"; ++}; ++ ++&gpio_chip6 { ++ status = "okay"; ++}; ++ ++&gpio_chip7 { ++ status = "okay"; ++}; ++ ++&gpio_chip8 { ++ status = "okay"; ++}; ++ ++&gpio_chip9 { ++ status = "okay"; ++}; ++ ++&gpio_chip10 { ++ status = "okay"; ++}; ++ ++&gpio_chip11 { ++ status = "okay"; ++}; ++ ++&gpio_chip12 { ++ status = "okay"; ++}; ++ ++&gpio_chip13 { ++ status = "okay"; ++}; ++ ++&gpio_chip14 { ++ status = "okay"; ++}; ++ ++&gpio_chip15 { ++ status = "okay"; ++}; +diff --git a/arch/arm/boot/dts/hi3516a.dtsi b/arch/arm/boot/dts/hi3516a.dtsi +new file mode 100644 +index 0000000..c5f9777 +--- /dev/null ++++ b/arch/arm/boot/dts/hi3516a.dtsi +@@ -0,0 +1,690 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "skeleton.dtsi" ++#include ++ ++/ { ++ aliases { ++ serial0 = &uart0; ++ i2c0 = &i2c_bus0; ++ i2c1 = &i2c_bus1; ++ i2c2 = &i2c_bus2; ++ spi0 = &spi_bus0; ++ spi1 = &spi_bus1; ++ gpio0 = &gpio_chip0; ++ gpio1 = &gpio_chip1; ++ gpio2 = &gpio_chip2; ++ gpio3 = &gpio_chip3; ++ gpio4 = &gpio_chip4; ++ gpio5 = &gpio_chip5; ++ gpio6 = &gpio_chip6; ++ gpio7 = &gpio_chip7; ++ gpio8 = &gpio_chip8; ++ gpio9 = &gpio_chip9; ++ gpio10 = &gpio_chip10; ++ gpio11 = &gpio_chip11; ++ gpio12 = &gpio_chip12; ++ gpio13 = &gpio_chip13; ++ gpio14 = &gpio_chip14; ++ gpio15 = &gpio_chip15; ++ }; ++ ++ clock: clock@20030000 { ++ compatible = "hisilicon,hi3516a-clock"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ #clock-cells = <1>; ++ #reset-cells = <2>; ++ reg = <0x20030000 0x1000>; ++ }; ++ ++ gic: interrupt-controller@20300000 { ++ compatible = "arm,cortex-a7-gic"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ /* gic dist base, gic cpu base , no virtual support */ ++ reg = <0x20301000 0x1000>, <0x20302000 0x100>; ++ }; ++ ++ sysctrl: system-controller@20050000 { ++ compatible = "hisilicon,hi3516a-sysctrl", "syscon"; ++ reg = <0x20050000 0x1000>; ++ #clock-cells = <1>; ++ }; ++ ++ reboot { ++ compatible = "syscon-reboot"; ++ regmap = <&sysctrl>; ++ offset = <0x4>; ++ mask = <0xdeadbeef>; ++ }; ++ ++ soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ ++ pmu { ++ compatible = "arm,cortex-a7-pmu"; ++ interrupts = <0 32 4>; ++ }; ++ ++ amba { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "arm,amba-bus"; ++ ranges; ++ ++ uart0: uart@20080000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x20080000 0x1000>; ++ interrupts = <0 8 4>; ++ clocks = <&clock HI3516A_UART0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart1: uart@20090000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x20090000 0x1000>; ++ interrupts = <0 9 4>; ++ clocks = <&clock HI3516A_UART1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart2: uart@200a0000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x200a0000 0x1000>; ++ interrupts = <0 10 4>; ++ clocks = <&clock HI3516A_UART2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart3: uart@20230000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x20230000 0x1000>; ++ interrupts = <0 11 4>; ++ clocks = <&clock HI3516A_UART3_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ }; ++ ++ usb_phy: phy { ++ compatible = "hisilicon,hisi-usb-phy"; ++ reg = <0x20030000 0x10000>, <0x20120000 0x10000>, ++ <0x20050000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ++ ehci@0x100b0000 { ++ compatible = "generic-ehci"; ++ reg = <0x100b0000 0x10000>; ++ interrupts = <0 21 4>; ++ ++ clocks = <&clock HI3516A_USB2_CTRL_UTMI0_REQ>, ++ <&clock HI3516A_USB2_HRST_REQ>; ++ clock-names = "usb2_cttl_utmi0_req", "usb2_hrst_req"; ++ }; ++ ++ ohci@0x100a0000 { ++ compatible = "generic-ohci"; ++ reg = <0x100a0000 0x10000>; ++ interrupts = <0 22 4>; ++ ++ clocks = <&clock HI3516A_USB2_CTRL_UTMI0_REQ>, ++ <&clock HI3516A_USB2_HRST_REQ>; ++ clock-names = "usb2_cttl_utmi0_req", "usb2_hrst_req"; ++ }; ++ ++ hiudc@0x10080000 { ++ compatible = "hiudc"; ++ reg = <0x10080000 0x10000>; ++ interrupts = <0 23 4>; ++ ++ clocks = <&clock HI3516A_USB2_HRST_REQ>; ++ clock-names = "clk"; ++ }; ++ ++ dual_timer0: dual_timer@20000000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ interrupts = <0 3 4>; ++ reg = <0x20000000 0x1000>; ++ clocks = <&sysctrl HI3516A_TIME0_0_CLK>, ++ <&sysctrl HI3516A_TIME0_1_CLK>, ++ <&clock HI3516A_SYSAXI_CLK>; ++ clock-names = "timer0", "timer1", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer1: dual_timer@20010000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer0 & timer1 */ ++ interrupts = <0 4 4>; ++ reg = <0x20010000 0x1000>; ++ clocks = <&sysctrl HI3516A_TIME1_2_CLK>, ++ <&sysctrl HI3516A_TIME1_3_CLK>, ++ <&clock HI3516A_SYSAXI_CLK>; ++ clock-names = "timer2", "timer3", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ hidmac: hidma-controller@10060000 { ++ compatible = "hisilicon,hisi-dmac"; ++ reg = <0x10060000 0x1000>; ++ interrupts = <0 5 4>; ++ clocks = <&clock HI3516A_DMAC_CLK>; ++ clock-names = "dmac_clk"; ++ resets = <&clock 0xd8 4>; ++ reset-names = "dma-reset"; ++ #dma-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus0: i2c@200d0000 { ++ compatible = "hisilicon,hisi-i2c-hisilicon"; ++ reg = <0x200d0000 0x100>; ++ interrupts = <0 14 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-frequency = <100000>; ++ io-size = <0x1000>; ++ id = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus1: i2c@20240000 { ++ compatible = "hisilicon,hisi-i2c-hisilicon"; ++ reg = <0x20240000 0x100>; ++ interrupts = <0 57 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-frequency = <100000>; ++ io-size = <0x1000>; ++ id = <1>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus2: i2c@20250000 { ++ compatible = "hisilicon,hisi-i2c-hisilicon"; ++ reg = <0x20250000 0x100>; ++ interrupts = <0 58 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-frequency = <100000>; ++ io-size = <0x1000>; ++ id = <2>; ++ status = "disabled"; ++ }; ++ ++ spi_bus0: spi@200c0000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x200c0000 0x1000>; ++ interrupts = <0 12 4>; ++ clocks = <&clock HI3516A_SPI0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ spi_bus1: spi@200e0000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x200e0000 0x1000>, <0x20120004 0x4>; ++ interrupts = <0 13 4>; ++ clocks = <&clock HI3516A_SPI1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ hisi,spi_cs_sb = <26>; ++ hisi,spi_cs_mask_bit = <0x0c000000>; ++ }; ++ ++ hisfc350: spi_nor_controller@10010000 { ++ compatible = "hisilicon,hisi-spi-nor"; ++ interrupts = <0 17 4>; ++ reg = <0x10010000 0x1000>, <0x58000000 0x1000000>; ++ reg-names = "control", "memory"; ++ clocks = <&clock HI3516A_SNOR_CLK>; ++ assigned-clocks = <&clock HI3516A_SNOR_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <1>; ++ }; ++ }; ++ ++ hisnfc100: spi_nand_controller@10040000 { ++ compatible = "hisilicon,hisi-spi-nand"; ++ reg = <0x10040000 0x1000>, <0x54000000 0x10000>; ++ reg-names = "control", "memory"; ++ clocks = <&clock HI3516A_SNAND_CLK>; ++ assigned-clocks = <&clock HI3516A_SNAND_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <1>; ++ }; ++ }; ++ ++ hinfc610: nand_controller@10000000 { ++ compatible = "hisilicon,hisi-parallel-nand"; ++ reg = <0x10000000 0x1000>, <0x50000000 0x10000>; ++ reg-names = "control", "memory"; ++ clocks = <&clock HI3516A_NAND_CLK>; ++ assigned-clocks = <&clock HI3516A_NAND_CLK>; ++ assigned-clock-rates = <198000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hinand { ++ compatible = "jedec,parallel-nand"; ++ reg = <1>; ++ }; ++ }; ++ ++ gpio_chip0: gpio_chip@20140000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x20140000 0x10000>; ++ interrupts = <0 47 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip1: gpio_chip@20150000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x20150000 0x10000>; ++ interrupts = <0 48 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip2: gpio_chip@20160000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x20160000 0x10000>; ++ interrupts = <0 49 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip3: gpio_chip@20170000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x20170000 0x10000>; ++ interrupts = <0 50 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip4: gpio_chip@20180000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x20180000 0x10000>; ++ interrupts = <0 51 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip5: gpio_chip@20190000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x20190000 0x10000>; ++ interrupts = <0 52 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip6: gpio_chip@201a0000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x201a0000 0x10000>; ++ interrupts = <0 53 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip7: gpio_chip@201b0000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x201b0000 0x10000>; ++ interrupts = <0 54 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip8: gpio_chip@201c0000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x201c0000 0x10000>; ++ interrupts = <0 55 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip9: gpio_chip@201d0000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x201d0000 0x10000>; ++ interrupts = <0 55 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip10: gpio_chip@201e0000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x201e0000 0x10000>; ++ interrupts = <0 54 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip11: gpio_chip@201f0000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x201f0000 0x10000>; ++ interrupts = <0 53 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip12: gpio_chip@20200000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x20200000 0x10000>; ++ interrupts = <0 52 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip13: gpio_chip@20210000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x20210000 0x10000>; ++ interrupts = <0 51 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip14: gpio_chip@20220000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x20220000 0x10000>; ++ interrupts = <0 50 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip15: gpio_chip@20260000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x20260000 0x10000>; ++ interrupts = <0 49 4>; ++ clocks = <&clock HI3516A_SYSAXI_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ regulators@20270000 { ++ compatible = "hi3516a,regulators"; ++ reg = <0x20270000 0x1000>; ++ regulator-num = <2>; ++ regulator-name-array = "regulator-a7","regulator-media"; ++ ++ a7_regulator: a7_regulator{ ++ regulator-name = "regulator-a7"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <1310000>; ++ regulator-always-on; ++ reg_offset = <0x4>; ++ }; ++ ++ media_regulator: media_regulator{ ++ regulator-name = "regulator-media"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <1310000>; ++ regulator-always-on; ++ reg_offset = <0xC>; ++ }; ++ }; ++ mdio: mdio@100903c0 { ++ compatible = "hisilicon,hisi-gemac-mdio"; ++ reg = <0x100903c0 0x20>; ++ clocks = <&clock HI3516A_ETH_CLK>, ++ <&clock HI3516A_ETH_PHY_MUX>; ++ assigned-clocks = <&clock HI3516A_ETH_PHY_MUX>; ++ assigned-clock-rates = <25000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ higmac: ethernet@10090000 { ++ compatible = "hisilicon,higmac"; ++ reg = <0x10090000 0x1000>,<0x200300ec 0x4>; ++ interrupts = <0 25 4>; ++ ++ clocks = <&clock HI3516A_ETH_CLK>, ++ <&clock HI3516A_ETH_MACIF_CLK>; ++ clock-names = "higmac_clk", ++ "macif_clk"; ++ ++ resets = <&clock 0xcc 0>, ++ <&clock 0xcc 2>; ++ reset-names = "port_reset", ++ "macif_reset"; ++ ++ mac-address = [00 00 00 00 00 00]; ++ }; ++ ++ mmc0: himci.SD@0x206e0000 { ++ compatible = "hisilicon,hi3516a-himci"; ++ reg = <0x206e0000 0x1000>; ++ interrupts = <0 19 4>; ++ clocks = <&clock HI3516A_MMC0_CLK>; ++ clock-names = "mmc_clk"; ++ resets = <&clock 0xc4 0>; ++ reset-names = "mmc_reset"; ++ max-frequency = <100000000>; ++ bus-width = <4>; ++ cap-sd-highspeed; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ devid = <0>; ++ status = "disabled"; ++ }; ++ ++ mmc1: himci.SD@0x206f0000 { ++ compatible = "hisilicon,hi3516a-himci"; ++ reg = <0x206f0000 0x1000>; ++ interrupts = <0 20 4>; ++ clocks = <&clock HI3516A_MMC1_CLK>; ++ clock-names = "mmc_clk"; ++ resets = <&clock 0xc4 8>; ++ reset-names = "mmc_reset"; ++ max-frequency = <100000000>; ++ bus-width = <4>; ++ cap-sd-highspeed; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ devid = <1>; ++ status = "disabled"; ++ }; ++ }; ++ ++ media { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ sys: sys@20030000 { ++ compatible = "hisilicon,hi35xx_sys"; ++ reg = <0x20030000 0x10000>, <0x20050000 0x10000>, ++ <0x20110000 0x10000>, <0x20120000 0x10000>; ++ reg-names = "crg", "sys", "ddr", "misc"; ++ }; ++ ++ audio: audio@20650000 { ++ compatible = "hisilicon,hi35xx_aiao"; ++ interrupts = <0 39 4>; ++ reg = <0x20650000 0x10000>; ++ reg-names = "aiao"; ++ }; ++ ++ ive: ive@206a0000 { ++ compatible = "hisilicon,hi35xx_ive"; ++ interrupts = <0 45 4>; ++ reg = <0x206a0000 0x10000>; ++ }; ++ ++ vda: vda@206c0000 { ++ compatible = "hisilicon,hi35xx_vda"; ++ interrupts = <0 44 4>; ++ reg = <0x206c0000 0x10000>; ++ }; ++ ++ mipi: mipi@20680000 { ++ compatible = "hisilicon,hi35xx_mipi"; ++ interrupts = <0 34 4>; ++ reg = <0x20680000 0x10000>; ++ }; ++ ++ isp: isp@20580000 { ++ compatible = "hisilicon,hi35xx_isp"; ++ interrupts = <0 35 4>; ++ reg = <0x20580000 0x10000>, <0x205a0000 0x20000>; ++ reg-names = "reg_vicap_base_va", "reg_isp_base_va"; ++ }; ++ ++ viu: viu@20580000 { ++ compatible = "hisilicon,hi35xx_viu"; ++ interrupts = <0 35 4>; ++ reg = <0x20580000 0x40000>; ++ }; ++ ++ vou: vou@205c0000 { ++ compatible = "hisilicon,hi35xx_vou"; ++ interrupts = <0 33 4>; ++ reg = <0x205c0000 0x10000>; ++ }; ++ ++ vgs: vgs@20630000 { ++ compatible = "hisilicon,hi35xx_vgs"; ++ interrupts = <0 38 4>; ++ reg = <0x20630000 0x10000>; ++ }; ++ ++ vpss: vpss@20600000 { ++ compatible = "hisilicon,hi35xx_vpss"; ++ interrupts = <0 36 4>; ++ reg = <0x20600000 0x10000>; ++ }; ++ ++ vedu: vedu@20640000 { ++ compatible = "hisilicon,hi35xx_vedu"; ++ interrupts = <0 43 4>; ++ reg = <0x20640000 0x10000>; ++ }; ++ ++ avc: avc@20620000 { ++ compatible = "hisilicon,hi35xx_avc"; ++ interrupts = <0 40 4>; ++ reg = <0x20620000 0x10000>; ++ }; ++ ++ jpege: jpege@20660000 { ++ compatible = "hisilicon,hi35xx_jpege"; ++ interrupts = <0 41 4>; ++ reg = <0x20660000 0x10000>; ++ }; ++ ++ tde: tde@20610000 { ++ compatible = "hisilicon,hi35xx_tde"; ++ interrupts = <0 37 4>; ++ reg = <0x20610000 0x10000>; ++ }; ++ ++ pwm: pwm@20130000 { ++ compatible = "hisilicon,hi3516cv300-pwm"; ++ reg = <0x20130000 0x10000>; ++ }; ++ ++ wtdg: wtdg@20040000 { ++ compatible = "hisilicon,hi_wdg"; ++ reg = <0x20040000 0x10000>; ++ reg-names = "wtdg"; ++ }; ++ ++ rtc: rtc@20060000 { ++ compatible = "hisilicon,hi_rtc"; ++ interrupts = <0 7 4>, <0 56 4>; ++ interrupt-names = "rtc", "rtc_temp"; ++ reg = <0x20060000 0x10000>; ++ }; ++ ++ ir: ir@20070000{ ++ compatible = "hisilicon,hi_ir"; ++ interrupts = <0 15 4>; ++ reg = <0x20070000 0x10000>; ++ }; ++ ++ cipher: cipher@100c0000{ ++ compatible = "hisilicon,hi_cipher"; ++ interrupts = <0 26 4>; ++ reg = <0x100c0000 0x10000>; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/hi3518ev20x-demb.dts b/arch/arm/boot/dts/hi3518ev20x-demb.dts +new file mode 100644 +index 0000000..e11b93b +--- /dev/null ++++ b/arch/arm/boot/dts/hi3518ev20x-demb.dts +@@ -0,0 +1,197 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/dts-v1/; ++#include "hi3518ev20x.dtsi" ++ ++/ { ++ model = "Hisilicon HI3518EV20X DEMO Board"; ++ compatible = "hisilicon,hi3518ev20x"; ++ ++ aliases { ++ serial0 = &uart0; ++ serial1 = &uart1; ++ serial2 = &uart2; ++ i2c0 = &i2c_bus0; ++ i2c1 = &i2c_bus1; ++ i2c2 = &i2c_bus2; ++ spi0 = &spi_bus0; ++ spi1 = &spi_bus1; ++ gpio0 = &gpio_chip0; ++ gpio1 = &gpio_chip1; ++ gpio2 = &gpio_chip2; ++ gpio3 = &gpio_chip3; ++ gpio4 = &gpio_chip4; ++ gpio5 = &gpio_chip5; ++ gpio6 = &gpio_chip6; ++ gpio7 = &gpio_chip7; ++ gpio8 = &gpio_chip8; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x20000000>; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "disabled"; ++}; ++ ++&dual_timer0 { ++ status = "okay"; ++}; ++ ++&dual_timer1 { ++ status = "disabled"; ++}; ++ ++&hisfc { ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++}; ++ ++&hisnfc { ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++}; ++ ++&mdio { ++ hisilicon,phy-reset-delays-us = <10000 20000 150000>; ++ phy0: ethernet-phy@1 { ++ reg = <1>; ++ }; ++}; ++ ++&hisi_femac { ++ mac-address = [00 00 00 00 00 00]; ++ phy-mode = "rmii"; ++ phy-handle = <&phy0>; ++}; ++ ++&hidmac { ++ status = "okay"; ++}; ++ ++/* mmc0_emmc and mmc0_sd can not "okay" at the same time */ ++&mmc0_emmc { ++ status = "disabled"; ++}; ++ ++&mmc0_sd { ++ status = "okay"; ++}; ++ ++&mmc1_sd { ++ status = "okay"; ++}; ++ ++&i2c_bus0 { ++ status = "okay"; ++}; ++ ++&i2c_bus1 { ++ status = "okay"; ++}; ++ ++&i2c_bus2 { ++ status = "okay"; ++}; ++ ++&spi_bus0{ ++ status = "okay"; ++ num-cs = <1>; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++}; ++ ++&spi_bus1{ ++ status = "okay"; ++ num-cs = <2>; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++}; ++ ++&gpio_chip0 { ++ status = "okay"; ++}; ++ ++&gpio_chip1 { ++ status = "okay"; ++}; ++ ++&gpio_chip2 { ++ status = "okay"; ++}; ++ ++&gpio_chip3 { ++ status = "okay"; ++}; ++ ++&gpio_chip4 { ++ status = "okay"; ++}; ++ ++&gpio_chip5 { ++ status = "okay"; ++}; ++ ++&gpio_chip6 { ++ status = "okay"; ++}; ++ ++&gpio_chip7 { ++ status = "okay"; ++}; ++ ++&gpio_chip8 { ++ status = "okay"; ++}; +diff --git a/arch/arm/boot/dts/hi3518ev20x.dtsi b/arch/arm/boot/dts/hi3518ev20x.dtsi +new file mode 100644 +index 0000000..3d1bb96 +--- /dev/null ++++ b/arch/arm/boot/dts/hi3518ev20x.dtsi +@@ -0,0 +1,580 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,arm926ej-s"; ++ reg = <0>; ++ }; ++ }; ++ ++ vic: interrupt-controller@100d0000 { ++ compatible = "arm,pl190-vic"; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ reg = <0x100d0000 0x1000>; ++ }; ++ ++ soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&vic>; ++ ranges; ++ ++ clock: clock@20030000 { ++ compatible = "hisilicon,hi3518ev20x-clock"; ++ reg = <0x20030000 0x1000>; ++ #clock-cells = <1>; ++ #reset-cells = <2>; ++ }; ++ ++ sysctrl: system-controller@20050000 { ++ compatible = "hisilicon,hi3518ev20x-sysctrl", ++ "syscon"; ++ reg = <0x20050000 0x1000>; ++ #clock-cells = <1>; ++ }; ++ ++ reboot { ++ compatible = "syscon-reboot"; ++ regmap = <&sysctrl>; ++ offset = <0x4>; ++ mask = <0xdeadbeef>; ++ }; ++ ++ dual_timer0: dual_timer@20000000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer0 & timer1 */ ++ interrupts = <3>; ++ reg = <0x20000000 0x1000>; ++ clocks = <&sysctrl HI3518EV20X_TIME0_0_CLK>, ++ <&sysctrl HI3518EV20X_TIME0_1_CLK>, ++ <&clock HI3518EV20X_SYSAPB_CLK>; ++ clock-names = "timer0", "timer1", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer1: dual_timer@20010000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer2 & timer3 */ ++ interrupts = <4>; ++ reg = <0x20010000 0x1000>; ++ clocks = <&sysctrl HI3518EV20X_TIME1_2_CLK>, ++ <&sysctrl HI3518EV20X_TIME1_3_CLK>, ++ <&clock HI3518EV20X_SYSAPB_CLK>; ++ clock-names = "timer2", "timer3", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart0: uart@20080000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x20080000 0x1000>; ++ interrupts = <5>; ++ clocks = <&clock HI3518EV20X_UART0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart1: uart@20090000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x20090000 0x1000>; ++ interrupts = <30>; ++ clocks = <&clock HI3518EV20X_UART1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart2: uart@200a0000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x200a0000 0x1000>; ++ interrupts = <25>; ++ clocks = <&clock HI3518EV20X_UART2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ usb_phy: phy { ++ compatible = "hisilicon,hisi-usb-phy"; ++ reg = <0x20030000 0x10000>, <0x20120000 0x10000>, ++ <0x20050000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ++ ehci@0x100b0000 { ++ compatible = "generic-ehci"; ++ reg = <0x100b0000 0x10000>; ++ interrupts = <15>; ++ ++ clocks = <&clock HI3518EV20X_USB2_CTRL_UTMI0_REQ>, ++ <&clock HI3518EV20X_USB2_HRST_REQ>; ++ clock-names = "usb2_cttl_utmi0_req", "usb2_hrst_req"; ++ }; ++ ++ ohci@0x100a0000 { ++ compatible = "generic-ohci"; ++ reg = <0x100a0000 0x10000>; ++ interrupts = <16>; ++ ++ clocks = <&clock HI3518EV20X_USB2_CTRL_UTMI0_REQ>, ++ <&clock HI3518EV20X_USB2_HRST_REQ>; ++ clock-names = "usb2_cttl_utmi0_req", "usb2_hrst_req"; ++ }; ++ ++ hiudc@0x10080000 { ++ compatible = "hiudc"; ++ reg = <0x10080000 0x10000>; ++ interrupts = <10>; ++ ++ clocks = <&clock HI3518EV20X_USB2_HRST_REQ>; ++ clock-names = "clk"; ++ }; ++ ++ i2c_bus0: i2c@200d0000 { ++ compatible = "hisilicon,hisi-i2c-hisilicon"; ++ reg = <0x200d0000 0x100>; ++ interrupts = <20>; ++ clocks = <&clock HI3518EV20X_SYSAPB_CLK>; ++ clock-frequency = <100000>; ++ io-size = <0x1000>; ++ id = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus1: i2c@20240000 { ++ compatible = "hisilicon,hisi-i2c-hisilicon"; ++ reg = <0x20240000 0x100>; ++ interrupts = <20>; ++ clocks = <&clock HI3518EV20X_SYSAPB_CLK>; ++ clock-frequency = <100000>; ++ io-size = <0x1000>; ++ id = <1>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus2: i2c@20250000 { ++ compatible = "hisilicon,hisi-i2c-hisilicon"; ++ reg = <0x20250000 0x100>; ++ interrupts = <20>; ++ clocks = <&clock HI3518EV20X_SYSAPB_CLK>; ++ clock-frequency = <100000>; ++ io-size = <0x1000>; ++ id = <2>; ++ status = "disabled"; ++ }; ++ ++ spi_bus0: spi@200c0000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x200c0000 0x1000>; ++ interrupts = <6>; ++ clocks = <&clock HI3518EV20X_SPI0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ spi_bus1: spi@200e0000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x200e0000 0x1000>, <0x20120004 0x4>; ++ interrupts = <7>; ++ clocks = <&clock HI3518EV20X_SPI1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ hisi,spi_cs_sb = <26>; ++ hisi,spi_cs_mask_bit = <0x0c000000>; ++ }; ++ ++ fmc: flash-memory-controller@10010000 { ++ compatible = "hisilicon,hisi-fmc"; ++ reg = <0x10010000 0x1000>, <0x58000000 0x10000>; ++ reg-names = "control", "memory"; ++ clocks = <&clock HI3518EV20X_FMC_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hisfc:spi-nor@0 { ++ compatible = "hisilicon,fmc-spi-nor"; ++ assigned-clocks = <&clock HI3518EV20X_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hisnfc:spi-nand@0 { ++ compatible = "hisilicon,fmc-spi-nand"; ++ assigned-clocks = <&clock HI3518EV20X_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ ++ mdio: mdio@10091100 { ++ compatible = "hisilicon,hisi-femac-mdio"; ++ reg = <0x10091100 0x10>; ++ clocks = <&clock HI3518EV20X_ETH_CLK>; ++ clock-names = "mdio"; ++ assigned-clocks = <&clock HI3518EV20X_ETH_CLK>; ++ assigned-clock-rates = <54000000>; ++ resets = <&clock 0xec 3>; ++ reset-names = "external-phy"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hisi_femac: ethernet@10090000 { ++ compatible = "hisilicon,hi3518ev20x-femac", ++ "hisilicon,hisi-femac-v2"; ++ reg = <0x10090000 0x1000>,<0x10091300 0x200>; ++ interrupts = <12>; ++ clocks = <&clock HI3518EV20X_ETH_CLK>; ++ resets = <&clock 0xec 0>; ++ reset-names = "mac"; ++ }; ++ ++ mmc0_emmc: himciv200.MMC@0x10020000{ ++ compatible = "hisilicon,hi3518ev20x-himci"; ++ reg = <0x10020000 0x1000>; ++ interrupts = <18>; ++ clocks = <&clock HI3518EV20X_MMC0_CLK>; ++ clock-names = "mmc_clk"; ++ max-frequency = <99000000>; ++ resets = <&clock 0xc4 8>; ++ reset-names = "mmc_reset"; ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ cap-mmc-hw-reset; ++ mmc-hs200-1_8v; ++ full-pwr-cycle; ++ devid = <0>; ++ status = "disabled"; ++ }; ++ ++ mmc0_sd: himciv200.SD@0x10020000{ ++ compatible = "hisilicon,hi3518ev20x-himci"; ++ reg = <0x10020000 0x1000>; ++ interrupts = <18>; ++ clocks = <&clock HI3518EV20X_MMC0_CLK>; ++ clock-names = "mmc_clk"; ++ max-frequency = <99000000>; ++ resets = <&clock 0xc4 8>; ++ reset-names = "mmc_reset"; ++ bus-width = <4>; ++ cap-sd-highspeed; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ devid = <0>; ++ status = "disabled"; ++ }; ++ ++ mmc1_sd: himciv200.SD@0x10030000{ ++ compatible = "hisilicon,hi3518ev20x-himci"; ++ reg = <0x10030000 0x1000>; ++ interrupts = <8>; ++ clocks = <&clock HI3518EV20X_MMC1_CLK>; ++ clock-names = "mmc_clk"; ++ max-frequency = <49500000>; ++ resets = <&clock 0xc4 0>; ++ reset-names = "mmc_reset"; ++ bus-width = <4>; ++ cap-sd-highspeed; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ devid = <1>; ++ status = "disabled"; ++ }; ++ ++ pmux: pinmux@200f0000 { ++ compatible = "pinctrl-single"; ++ reg = <0x200f0000 0x108>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ #gpio-range-cells = <3>; ++ ranges; ++ ++ pinctrl-single,register-width = <32>; ++ pinctrl-single,function-mask = <7>; ++ /* pin base, nr pins & gpio function */ ++ pinctrl-single,gpio-range = <&range 0 5 0 ++ &range 6 38 0 &range 44 1 2 ++ &range 45 13 0 &range 58 8 1>; ++ ++ range: gpio-range { ++ #pinctrl-single,gpio-range-cells = <3>; ++ }; ++ }; ++ ++ pconf: pinconf@200f0800 { ++ compatible = "pinconf-single"; ++ reg = <0x200f0800 0x130>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ pinctrl-single,register-width = <32>; ++ }; ++ ++ gpio_chip0: gpio_chip@20140000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x20140000 0x10000>; ++ interrupts = <31>; ++ clocks = <&clock HI3518EV20X_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ gpio-ranges = <&pmux 0 28 3>, <&pmux 3 12 1>, ++ <&pmux 4 0 4>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip1: gpio_chip@20150000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x20150000 0x10000>; ++ interrupts = <31>; ++ clocks = <&clock HI3518EV20X_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ gpio-ranges = <&pmux 0 31 8>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip2: gpio_chip@20160000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x20160000 0x10000>; ++ interrupts = <31>; ++ clocks = <&clock HI3518EV20X_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ gpio-ranges = <&pmux 0 4 8>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip3: gpio_chip@20170000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x20170000 0x10000>; ++ interrupts = <31>; ++ clocks = <&clock HI3518EV20X_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ gpio-ranges = <&pmux 0 13 8>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip4: gpio_chip@20180000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x20180000 0x10000>; ++ interrupts = <31>; ++ clocks = <&clock HI3518EV20X_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ gpio-ranges = <&pmux 0 21 7>, <&pmux 7 39 1>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip5: gpio_chip@20190000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x20190000 0x10000>; ++ interrupts = <31>; ++ clocks = <&clock HI3518EV20X_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ gpio-ranges = <&pmux 0 40 8>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip6: gpio_chip@201a0000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x201a0000 0x10000>; ++ interrupts = <31>; ++ clocks = <&clock HI3518EV20X_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ gpio-ranges = <&pmux 0 48 8>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip7: gpio_chip@201b0000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x201b0000 0x10000>; ++ interrupts = <31>; ++ clocks = <&clock HI3518EV20X_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ gpio-ranges = <&pmux 0 56 8>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip8: gpio_chip@201c0000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x201c0000 0x10000>; ++ interrupts = <31>; ++ clocks = <&clock HI3518EV20X_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ gpio-ranges = <&pmux 0 64 2>; ++ status = "disabled"; ++ }; ++ ++ hidmac: hidma-controller@10060000 { ++ compatible = "hisilicon,hisi-dmac"; ++ reg = <0x10060000 0x1000>; ++ interrupts = <14>; ++ clocks = <&clock HI3518EV20X_DMAC_CLK>; ++ clock-names = "dmac_clk"; ++ resets = <&clock 0xd8 4>; ++ reset-names = "dma-reset"; ++ #dma-cells = <2>; ++ status = "disabled"; ++ }; ++ }; ++ ++ media { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&vic>; ++ ranges; ++ ++ sys_config { ++ compatible = "hisilicon,sys_config"; ++ }; ++ ++ sys: sys@20030000 { ++ compatible = "hisilicon,hi35xx_sys"; ++ reg = <0x20030000 0x10000>, <0x20050000 0x10000>, ++ <0x20110000 0x10000>, <0x20120000 0x10000>; ++ reg-names = "crg", "sys", "ddr", "misc"; ++ }; ++ ++ audio: audio@20650000 { ++ compatible = "hisilicon,hi35xx_aiao"; ++ interrupts = <9>; ++ reg = <0x20650000 0x10000>; ++ reg-names = "aiao"; ++ }; ++ ++ ive: ive@206a0000 { ++ compatible = "hisilicon,hi35xx_ive"; ++ interrupts = <21>; ++ reg = <0x206a0000 0x10000>; ++ }; ++ ++ mipi: mipi@20680000 { ++ compatible = "hisilicon,hi35xx_mipi"; ++ interrupts = <28>; ++ reg = <0x20680000 0x10000>; ++ }; ++ ++ isp: isp@20580000 { ++ compatible = "hisilicon,hi35xx_isp"; ++ interrupts = <22>; ++ reg = <0x20580000 0x10000>, <0x205a0000 0x20000>; ++ reg-names = "reg_vicap_base_va", "reg_isp_base_va"; ++ }; ++ ++ viu: viu@20580000 { ++ compatible = "hisilicon,hi35xx_viu"; ++ interrupts = <22>; ++ reg = <0x20580000 0x40000>; ++ }; ++ ++ vou: vou@205c0000 { ++ compatible = "hisilicon,hi35xx_vou"; ++ interrupts = <23>; ++ reg = <0x205c0000 0x10000>; ++ }; ++ ++ vgs: vgs@20630000 { ++ compatible = "hisilicon,hi35xx_vgs"; ++ interrupts = <29>; ++ reg = <0x20630000 0x10000>; ++ }; ++ ++ vpss: vpss@20600000 { ++ compatible = "hisilicon,hi35xx_vpss"; ++ interrupts = <17>; ++ reg = <0x20600000 0x10000>; ++ }; ++ ++ avc: avc@20620000 { ++ compatible = "hisilicon,hi35xx_avc"; ++ interrupts = <24>; ++ reg = <0x20620000 0x10000>; ++ }; ++ ++ jpege: jpege@20660000 { ++ compatible = "hisilicon,hi35xx_jpege"; ++ interrupts = <26>; ++ reg = <0x20660000 0x10000>; ++ }; ++ ++ tde: tde@20610000 { ++ compatible = "hisilicon,hi35xx_tde"; ++ interrupts = <27>; ++ reg = <0x20610000 0x10000>; ++ }; ++ ++ pwm: pwm@20130000 { ++ compatible = "hisilicon,hi3516cv300-pwm"; ++ reg = <0x20130000 0x10000>; ++ }; ++ ++ wtdg: wtdg@20040000 { ++ compatible = "hisilicon,hi_wdg"; ++ reg = <0x20040000 0x10000>; ++ reg-names = "wtdg"; ++ }; ++ ++ rtc: rtc@20060000 { ++ compatible = "hisilicon,hi_rtc"; ++ interrupts = <2>, <2>; ++ interrupt-names = "rtc", "rtc_temp"; ++ reg = <0x20060000 0x10000>; ++ }; ++ ++ ir: ir@20070000{ ++ compatible = "hisilicon,hi_ir"; ++ interrupts = <19>; ++ reg = <0x20070000 0x10000>; ++ }; ++ ++ cipher: cipher@100c0000{ ++ compatible = "hisilicon,hi_cipher"; ++ interrupts = <13>; ++ reg = <0x100c0000 0x10000>; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/hi3521a-demb.dts b/arch/arm/boot/dts/hi3521a-demb.dts +new file mode 100644 +index 0000000..5d7be0d +--- /dev/null ++++ b/arch/arm/boot/dts/hi3521a-demb.dts +@@ -0,0 +1,103 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/dts-v1/; ++#include "hi3521a.dtsi" ++ ++/ { ++ model = "Hisilicon HI3521A DEMO Board"; ++ compatible = "hisilicon,hi3521a"; ++ ++ aliases { ++ serial0 = &uart0; ++ i2c0 = &i2c_bus0; ++ spi0 = &spi_bus0; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x20000000>; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&dual_timer0 { ++ status = "okay"; ++}; ++ ++&hidmac { ++ status = "okay"; ++}; ++ ++&hisfc { ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++}; ++ ++&hisnfc { ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++}; ++ ++&mdio { ++ ethphy: ethernet-phy@1 { ++ reg = <1>; ++ }; ++}; ++ ++&higmac { ++ phy-handle = <ðphy>; ++ phy-mode = "rgmii"; ++}; ++ ++&i2c_bus0 { ++ status = "okay"; ++}; ++ ++&spi_bus0{ ++ status = "okay"; ++ num-cs = <2>; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <31250000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <31250000>; ++ }; ++}; +diff --git a/arch/arm/boot/dts/hi3521a.dtsi b/arch/arm/boot/dts/hi3521a.dtsi +new file mode 100644 +index 0000000..506d515 +--- /dev/null ++++ b/arch/arm/boot/dts/hi3521a.dtsi +@@ -0,0 +1,405 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a7"; ++ reg = <0>; ++ }; ++ }; ++ ++ gic: interrupt-controller@10300000 { ++ compatible = "arm,cortex-a7-gic"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ /* gic dist base, gic cpu base , no virtual support */ ++ reg = <0x10301000 0x1000>, <0x10302000 0x100>; ++ }; ++ ++ soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ clock: clock@12040000 { ++ compatible = "hisilicon,hi3521a-clock"; ++ reg = <0x12040000 0x1000>; ++ #clock-cells = <1>; ++ #reset-cells = <2>; ++ }; ++ ++ sysctrl: system-controller@12050000 { ++ compatible = "hisilicon,hi3521a-sysctrl", "syscon"; ++ reg = <0x12050000 0x1000>; ++ #clock-cells = <1>; ++ }; ++ ++ reboot { ++ compatible = "syscon-reboot"; ++ regmap = <&sysctrl>; ++ offset = <0x4>; ++ mask = <0xdeadbeef>; ++ }; ++ ++ dual_timer0: dual_timer@12000000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer0 & timer1 */ ++ interrupts = ; ++ reg = <0x12000000 0x1000>; ++ clocks = <&sysctrl HI3521A_TIME0_0_CLK>, ++ <&sysctrl HI3521A_TIME0_1_CLK>, ++ <&clock HI3521A_SYSAPB_CLK>; ++ clock-names = "timer0", "timer1", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer1: dual_timer@12010000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer2 & timer3 */ ++ interrupts = ; ++ reg = <0x12010000 0x1000>; ++ clocks = <&sysctrl HI3521A_TIME1_2_CLK>, ++ <&sysctrl HI3521A_TIME1_3_CLK>, ++ <&clock HI3521A_SYSAPB_CLK>; ++ clock-names = "timer2", "timer3", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer2: dual_timer@12020000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer2 & timer3 */ ++ interrupts = ; ++ reg = <0x12020000 0x1000>; ++ clocks = <&sysctrl HI3521A_TIME2_4_CLK>, ++ <&sysctrl HI3521A_TIME2_5_CLK>, ++ <&clock HI3521A_SYSAPB_CLK>; ++ clock-names = "timer4", "timer5", "apb_pclk"; ++ ++ status = "disabled"; ++ }; ++ ++ dual_timer3: dual_timer@12030000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer2 & timer3 */ ++ interrupts = ; ++ reg = <0x12030000 0x1000>; ++ clocks = <&sysctrl HI3521A_TIME3_6_CLK>, ++ <&sysctrl HI3521A_TIME3_7_CLK>, ++ <&clock HI3521A_SYSAPB_CLK>; ++ clock-names = "timer6", "timer7", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ hidmac: hidma-controller@10060000 { ++ compatible = "hisilicon,hisi-dmac"; ++ reg = <0x10060000 0x1000>; ++ interrupts = ; ++ clocks = <&clock HI3521A_DMAC_CLK>; ++ clock-names = "dmac_clk"; ++ resets = <&clock 0x80 4>; ++ reset-names = "dma-reset"; ++ #dma-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ uart0: uart@12080000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12080000 0x1000>; ++ interrupts = ; ++ clocks = <&clock HI3521A_UART0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart1: uart@12090000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12090000 0x1000>; ++ interrupts = ; ++ clocks = <&clock HI3521A_UART1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart2: uart@120a0000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x120a0000 0x1000>; ++ interrupts = ; ++ clocks = <&clock HI3521A_UART2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ i2c_bus0: i2c@120c0000 { ++ compatible = "hisilicon,hisi-i2c-hisilicon"; ++ reg = <0x120c0000 0x100>; ++ interrupts = ; ++ clocks = <&clock HI3521A_SYSAPB_CLK>; ++ clock-frequency = <100000>; ++ io-size = <0x1000>; ++ id = <0>; ++ status = "disabled"; ++ }; ++ ++ spi_bus0: spi@120d0000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x120d0000 0x1000>, <0x12120014 0x4>; ++ interrupts = ; ++ clocks = <&clock HI3521A_SPI0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ hisi,spi_cs_sb = <0>; ++ hisi,spi_cs_mask_bit = <0x00000004>; ++ }; ++ ++ usb_phy: phy { ++ compatible = "hisilicon,hisi-usb-phy"; ++ reg = <0x12040000 0x10000>, <0x12120000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ++ ehci@0x10040000 { ++ compatible = "generic-ehci"; ++ reg = <0x10040000 0x10000>; ++ interrupts = ; ++ }; ++ ++ ohci@0x10030000 { ++ compatible = "generic-ohci"; ++ reg = <0x10030000 0x10000>; ++ interrupts = ; ++ }; ++ ++ fmc: flash-memory-controller@10000000 { ++ compatible = "hisilicon,hisi-fmc"; ++ reg = <0x10000000 0x1000>, <0x14000000 0x10000>; ++ reg-names = "control", "memory"; ++ clocks = <&clock HI3521A_FMC_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hisfc:spi-nor@0 { ++ compatible = "hisilicon,fmc-spi-nor"; ++ assigned-clocks = <&clock HI3521A_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hisnfc:spi-nand@0 { ++ compatible = "hisilicon,fmc-spi-nand"; ++ assigned-clocks = <&clock HI3521A_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ ++ mdio: mdio@100a03c0 { ++ compatible = "hisilicon,hisi-gemac-mdio"; ++ reg = <0x100a03c0 0x20>; ++ clocks = <&clock HI3521A_ETH_CLK>, ++ <&clock HI3521A_ETH_PHY_MUX>; ++ assigned-clocks = <&clock HI3521A_ETH_PHY_MUX>; ++ assigned-clock-rates = <25000000>; ++ resets = <&clock 0x78 5>; ++ reset-names = "phy_reset"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ higmac: ethernet@100a0000 { ++ compatible = "hisilicon,higmac"; ++ reg = <0x100a0000 0x1000>,<0x1204008c 0x4>, ++ <0x100a3014 0x4>; ++ interrupts = ; ++ ++ clocks = <&clock HI3521A_ETH_CLK>, ++ <&clock HI3521A_ETH_MACIF_CLK>; ++ clock-names = "higmac_clk", ++ "macif_clk"; ++ ++ resets = <&clock 0x78 0>, ++ <&clock 0x78 2>; ++ reset-names = "port_reset", ++ "macif_reset"; ++ ++ mac-address = [00 00 00 00 00 00]; ++ }; ++ ++ sata_phy: phy@11010000 { ++ compatible = "hisilicon,hisi-sata-phy"; ++ reg = <0x11010000 0x10000>; ++ ports_num_max = <2>; ++ #phy-cells = <0>; ++ }; ++ ++ ahci: sata@11010000 { ++ compatible = "hisilicon,hisi-ahci"; ++ reg = <0x11010000 0x1000>; ++ interrupts = ; ++ phys = <&sata_phy>; ++ phy-names = "sata-phy"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ ++ media { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ sys: sys@12040000 { ++ compatible = "hisilicon,hi35xx_sys"; ++ reg = <0x12040000 0x10000>, <0x12050000 0x10000>, ++ <0x12110000 0x10000>, <0x12120000 0x10000>; ++ reg-names = "crg", "sys", "ddr", "misc"; ++ }; ++ ++ rtc: rtc@120b0000 { ++ compatible = "hisilicon,hi35xx_rtc"; ++ interrupts = ; ++ reg = <0x120b0000 0x10000>; ++ }; ++ ++ hiir: hiir@0x12140000 { ++ compatible = "hisilicon,hi35xx_ir"; ++ interrupts = ; ++ reg = <0x12140000 0x10000>; ++ }; ++ ++ cipher: cipher@0x10070000 { ++ compatible = "hisilicon,hi35xx_cipher"; ++ interrupts = ; ++ reg = <0x10070000 0x2000>; ++ }; ++ ++ viu: viu@130C0000 { ++ compatible = "hisilicon,hi35xx_viu"; ++ interrupts = ; ++ reg = <0x130C0000 0x40000>; ++ }; ++ ++ vou: vou@13020000 { ++ compatible = "hisilicon,hi35xx_vou"; ++ interrupts = ; ++ reg = <0x13020000 0x10000>; ++ }; ++ ++ vpss: vpss@13110000 { ++ compatible = "hisilicon,hi35xx_vpss"; ++ interrupts = ; ++ interrupt-names = "vpss0"; ++ reg = <0x13110000 0x5000>; ++ reg-names = "vpss0"; ++ }; ++ ++ vgs: vgs@13080000 { ++ compatible = "hisilicon,hi35xx_vgs"; ++ interrupts = ; ++ reg = <0x13080000 0x5000>; ++ }; ++ ++ vda: vda@13150000 { ++ compatible = "hisilicon,hi35xx_vda"; ++ interrupts = ; ++ reg = <0x13150000 0x10000>; ++ }; ++ ++ tde: tde@13050000 { ++ compatible = "hisilicon,hi35xx_tde"; ++ interrupts = ; ++ reg = <0x13050000 0x1000>; ++ }; ++ ++ avc: avc@13040000 { ++ compatible = "hisilicon,hi35xx_avc"; ++ interrupts = , ++ ; ++ reg = <0x13040000 0x10000>, ++ <0x13100000 0x10000>; ++ reg-names = "vedu0", "vedu1"; ++ }; ++ ++ jpege: jpege@13130000 { ++ compatible = "hisilicon,hi35xx_jpege"; ++ interrupts = ; ++ reg = <0x13130000 0x10000>; ++ }; ++ ++ jpgd: jpgd@13070000 { ++ compatible = "hisilicon,hi35xx_jpgd"; ++ interrupts = ; ++ interrupt-names = "jpgd"; ++ reg = <0x13070000 0x10000>; ++ reg-names = "jpgd"; ++ }; ++ ++ ive: ive@13060000 { ++ compatible = "hisilicon,hi35xx_ive"; ++ interrupts = ; ++ reg = <0x13060000 0x10000>; ++ }; ++ ++ vdec: vdec@10080000 { ++ compatible = "hisilicon,hi35xx_vdec"; ++ interrupts = ; ++ interrupt-names = "scd"; ++ reg = <0x10080000 0x4000>; ++ reg-names = "scd"; ++ }; ++ ++ audio: audio@13140000 { ++ compatible = "hisilicon,hi35xx_aiao"; ++ interrupts = ; ++ reg = <0x13140000 0x10000>; ++ reg-names = "aiao"; ++ }; ++ ++ voie: audio@13120000 { ++ compatible = "hisilicon,hi35xx_aenc"; ++ interrupts = ; ++ reg = <0x13120000 0x10000>; ++ reg-names = "aenc"; ++ }; ++ ++ hdmi: hdmi@13010000 { ++ compatible = "hisilicon,hi35xx_hdmi"; ++ reg = <0x13010000 0x10000>; ++ reg-names = "hdmi"; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/hi3531a-demb.dts b/arch/arm/boot/dts/hi3531a-demb.dts +new file mode 100644 +index 0000000..f4f2831 +--- /dev/null ++++ b/arch/arm/boot/dts/hi3531a-demb.dts +@@ -0,0 +1,146 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/dts-v1/; ++#include "hi3531a.dtsi" ++ ++/ { ++ model = "Hisilicon HI3531A DEMO Board"; ++ compatible = "hisilicon,hi3531a"; ++ ++ chosen{ ++ linux,initrd-start = <0x42000000>; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ enable-method = "hisilicon,hi3531a-smp"; ++ ++ cpu@0 { ++ compatible = "arm,cortex-a9"; ++ device_type = "cpu"; ++ reg = <0>; ++ next-level-cache = <&L2>; ++ }; ++ ++ cpu@1 { ++ compatible = "arm,cortex-a9"; ++ device_type = "cpu"; ++ reg = <1>; ++ next-level-cache = <&L2>; ++ }; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x40000000 0xc0000000>; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&hidmac { ++ status = "okay"; ++}; ++ ++&hisfc { ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++}; ++ ++&hisnfc { ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ }; ++}; ++ ++&hinfc610 { ++ assigned-clocks = <&clock HI3531A_NFC_CLK>; ++ assigned-clock-rates = <200000000>; ++ ++ hinand { ++ compatible = "jedec,nand"; ++ reg = <0>; ++ nand-max-frequency = <200000000>; ++ }; ++}; ++ ++&mdio { ++ ethphy: ethernet-phy@1 { ++ reg = <1>; ++ }; ++}; ++ ++&higmac { ++ phy-handle = <ðphy>; ++ phy-mode = "rgmii"; ++}; ++ ++&i2c_bus0 { ++ status = "okay"; ++}; ++ ++&i2c_bus1 { ++ status = "okay"; ++}; ++ ++&spi_bus0{ ++ status = "okay"; ++ num-cs = <4>; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <31250000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <31250000>; ++ }; ++ ++ spidev@2 { ++ compatible = "rohm,dh2228fv"; ++ reg = <2>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <31250000>; ++ }; ++ spidev@3 { ++ compatible = "rohm,dh2228fv"; ++ reg = <3>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <31250000>; ++ }; ++}; +diff --git a/arch/arm/boot/dts/hi3531a.dtsi b/arch/arm/boot/dts/hi3531a.dtsi +new file mode 100644 +index 0000000..24db11b +--- /dev/null ++++ b/arch/arm/boot/dts/hi3531a.dtsi +@@ -0,0 +1,506 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ aliases { ++ fmc = &fmc; ++ serial0 = &uart0; ++ serial1 = &uart1; ++ serial2 = &uart2; ++ serial3 = &uart3; ++ i2c0 = &i2c_bus0; ++ i2c1 = &i2c_bus1; ++ spi0 = &spi_bus0; ++ }; ++ ++ gic: interrupt-controller@10300000 { ++ compatible = "arm,cortex-a9-gic"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ /* gic dist base, gic cpu base , no virtual support */ ++ reg = <0x10301000 0x1000>, <0x10300100 0x100>; ++ }; ++ ++ soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ clock: clock@12040000 { ++ compatible = "hisilicon,hi3531a-clock"; ++ reg = <0x12040000 0x1000>; ++ #clock-cells = <1>; ++ #reset-cells = <2>; ++ }; ++ ++ sysctrl: system-controller@12050000 { ++ compatible = "hisilicon,hi3531a-sysctrl", "syscon"; ++ reg = <0x12050000 0x1000>; ++ #clock-cells = <1>; ++ }; ++ ++ reboot { ++ compatible = "syscon-reboot"; ++ regmap = <&sysctrl>; ++ offset = <0x4>; ++ mask = <0xdeadbeef>; ++ }; ++ ++ pmu { ++ compatible = "arm,cortex-a9-pmu"; ++ interrupts = , ++ ; ++ }; ++ ++ L2: l2-cache@10700000 { ++ compatible = "arm,pl310-cache"; ++ reg = <0x10700000 0x10000>; ++ interrupts = ; ++ cache-unified; ++ cache-level = <2>; ++ }; ++ ++ hidmac: hidma-controller@10060000 { ++ compatible = "hisilicon,hisi-dmac"; ++ reg = <0x10060000 0x1000>; ++ interrupts = ; ++ clocks = <&clock HI3531A_DMAC_CLK>; ++ clock-names = "dmac_clk"; ++ resets = <&clock 0x144 0>; ++ reset-names = "dma-reset"; ++ #dma-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ uart0: uart@12080000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12080000 0x1000>; ++ interrupts = ; ++ clocks = <&clock HI3531A_UART0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart1: uart@121090000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12090000 0x1000>; ++ interrupts = ; ++ clocks = <&clock HI3531A_UART1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart2: uart@120a0000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x120a0000 0x1000>; ++ interrupts = ; ++ clocks = <&clock HI3531A_UART2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart3: uart@12130000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12130000 0x1000>; ++ interrupts = ; ++ clocks = <&clock HI3531A_UART3_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ usb_phy: phy { ++ compatible = "hisilicon,hisi-usb-phy"; ++ reg = <0x12040000 0x10000>, <0x12120000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ++ usb3_phy: phy3 { ++ compatible = "hisilicon,hisi-usb3-phy"; ++ reg = <0x12040000 0x10000>, <0x12120000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ++ xhci@0x11000000 { ++ compatible = "generic-xhci"; ++ reg = <0x11000000 0x10000>; ++ interrupts = <0 22 4>; ++ }; ++ ++ ehci@0x100c0000 { ++ compatible = "generic-ehci"; ++ reg = <0x100c0000 0x10000>; ++ interrupts = <0 19 4>; ++ }; ++ ++ ohci@0x100b0000 { ++ compatible = "generic-ohci"; ++ reg = <0x100b0000 0x10000>; ++ interrupts = <0 18 4>; ++ }; ++ ++ i2c_bus0: i2c@120c0000 { ++ compatible = "hisilicon,hisi-i2c-hisilicon"; ++ reg = <0x120c0000 0x100>; ++ interrupts = ; ++ clocks = <&clock HI3531A_PERIAXI_CLK>; ++ clock-frequency = <100000>; ++ io-size = <0x1000>; ++ id = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus1: i2c@122e0000 { ++ compatible = "hisilicon,hisi-i2c-hisilicon"; ++ reg = <0x122e0000 0x100>; ++ interrupts = ; ++ clocks = <&clock HI3531A_PERIAXI_CLK>; ++ clock-frequency = <100000>; ++ io-size = <0x1000>; ++ id = <1>; ++ status = "disabled"; ++ }; ++ ++ spi_bus0: spi@120d0000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x120d0000 0x1000>, <0x12120014 0x4>; ++ interrupts = ; ++ clocks = <&clock HI3531A_SPI0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ hisi,spi_cs_sb = <0>; ++ hisi,spi_cs_mask_bit = <0x00000004>; ++ }; ++ ++ timer@hisp804 { ++ compatible = "hisilicon,hisp804"; ++ /* timer0 & timer1 & timer2 */ ++ reg = <0x12000000 0x20>, /* clocksource */ ++ <0x12000020 0x20>, /* local timer for each cpu */ ++ <0x12010000 0x20>; ++ interrupts = , /* irq of local timer */ ++ ; ++ clocks = <&sysctrl HI3531A_TIME0_0_CLK>, ++ <&sysctrl HI3531A_TIME0_1_CLK>, ++ <&sysctrl HI3531A_TIME1_2_CLK>; ++ clock-names = "timer0", "timer1", "timer2"; ++ }; ++ ++ dual_timer2: dual_timer@12020000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer4 & timer5 */ ++ interrupts = ; ++ reg = <0x12020000 0x1000>; ++ clocks = <&sysctrl HI3531A_TIME2_4_CLK>, ++ <&sysctrl HI3531A_TIME2_5_CLK>, ++ <&clock HI3531A_PERIAXI_CLK>; ++ clock-names = "timer4", "timer5", "peri_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer3: dual_timer@12030000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer6 & timer7 */ ++ interrupts = ; ++ reg = <0x12030000 0x1000>; ++ clocks = <&sysctrl HI3531A_TIME3_6_CLK>, ++ <&sysctrl HI3531A_TIME3_7_CLK>, ++ <&clock HI3531A_PERIAXI_CLK>; ++ clock-names = "timer6", "timer7", "peri_pclk"; ++ status = "disabled"; ++ }; ++ ++ fmc: flash-memory-controller@10000000 { ++ compatible = "hisilicon,hisi-fmc"; ++ reg = <0x10000000 0x1000>, <0x14000000 0x10000>; ++ reg-names = "control", "memory"; ++ clocks = <&clock HI3531A_FMC_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hisfc:spi_nor_controller { ++ compatible = "hisilicon,fmc-spi-nor"; ++ assigned-clocks = <&clock HI3531A_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hisnfc:spi_nand_controller { ++ compatible = "hisilicon,fmc-spi-nand"; ++ assigned-clocks = <&clock HI3531A_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ ++ hinfc610: parallel-nand-controller@10010000 { ++ compatible = "hisilicon,hisi-parallel-nand"; ++ reg = <0x10010000 0x10000>, <0x15000000 0x10000>; ++ reg-names = "control", "memory"; ++ clocks = <&clock HI3531A_NFC_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ mdio: mdio@100a03c0 { ++ compatible = "hisilicon,hisi-gemac-mdio"; ++ reg = <0x100a03c0 0x20>; ++ clocks = <&clock HI3531A_ETH_CLK>, ++ <&clock HI3531A_ETH_PHY_MUX>; ++ assigned-clocks = <&clock HI3531A_ETH_PHY_MUX>; ++ assigned-clock-rates = <25000000>; ++ resets = <&clock 0x14c 5>; ++ reset-names = "phy_reset"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ higmac: ethernet@100a0000 { ++ compatible = "hisilicon,higmac"; ++ reg = <0x100a0000 0x1000>,<0x1204015c 0x4>, ++ <0x100a3014 0x4>; ++ interrupts = ; ++ ++ clocks = <&clock HI3531A_ETH_CLK>, ++ <&clock HI3531A_ETH_MACIF_CLK>; ++ clock-names = "higmac_clk", ++ "macif_clk"; ++ ++ resets = <&clock 0x14c 0>, ++ <&clock 0x14c 2>; ++ reset-names = "port_reset", ++ "macif_reset"; ++ ++ mac-address = [00 00 00 00 00 00]; ++ }; ++ ++ sata_phy: phy@11010000 { ++ compatible = "hisilicon,hisi-sata-phy"; ++ reg = <0x11010000 0x10000>; ++ ports_num_max = <4>; ++ #phy-cells = <0>; ++ }; ++ ++ ahci: sata@11010000 { ++ compatible = "hisilicon,hisi-ahci"; ++ reg = <0x11010000 0x1000>; ++ interrupts = ; ++ phys = <&sata_phy>; ++ phy-names = "sata-phy"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ pcie0: pcie0@0x11020000 { ++ device_type = "pci"; ++ compatible = "hisilicon,hisi-pcie"; ++ bus-range = <0x0 0xff>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ ranges = <0x02000000 0x00 0x28000000 0x28000000 0x00 0x8000000>; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0x0 0x0 0x0 0x4>; ++ interrupt-map = <0x0 0x0 0x0 0x1 &gic GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>; ++ pcie_controller = <0>; ++ dev_mem_size = <0x8000000>; ++ dev_conf_size = <0x8000000>; ++ pcie_dbi_base = <0x11020000>; ++ ep_conf_base = <0x20000000>; ++ }; ++ ++ pcie1: pcie1@0x11030000 { ++ device_type = "pci"; ++ compatible = "hisilicon,hisi-pcie"; ++ bus-range = <0x0 0xff>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ ranges = <0x02000000 0x00 0x38000000 0x38000000 0x00 0x8000000>; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0x0 0x0 0x0 0x4>; ++ interrupt-map = <0x0 0x0 0x0 0x1 &gic GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; ++ pcie_controller = <1>; ++ dev_mem_size = <0x8000000>; ++ dev_conf_size = <0x8000000>; ++ pcie_dbi_base = <0x11030000>; ++ ep_conf_base = <0x30000000>; ++ }; ++ ++ pcie_mcc: pcie_mcc@0x0 { ++ compatible = "hisilicon,pcie_mcc"; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ }; ++ }; ++ ++ media { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ sys: sys@12040000 { ++ compatible = "hisilicon,hi35xx_sys"; ++ reg = <0x12040000 0x10000>, <0x12050000 0x10000>, ++ <0x12110000 0x10000>, <0x12120000 0x10000>; ++ reg-names = "crg", "sys", "ddr", "misc"; ++ }; ++ ++ rtc: rtc@120b0000 { ++ compatible = "hisilicon,hi35xx_rtc"; ++ interrupts = ; ++ reg = <0x120b0000 0x10000>; ++ }; ++ ++ hiir: hiir@0x12140000 { ++ compatible = "hisilicon,hi35xx_ir"; ++ interrupts = ; ++ reg = <0x12140000 0x10000>; ++ }; ++ ++ cipher: cipher@0x10070000 { ++ compatible = "hisilicon,hi35xx_cipher"; ++ interrupts = ; ++ reg = <0x10070000 0x2000>; ++ }; ++ ++ viu: viu@130C0000 { ++ compatible = "hisilicon,hi35xx_viu"; ++ interrupts = ; ++ reg = <0x130C0000 0x40000>; ++ }; ++ ++ vou: vou@13020000 { ++ compatible = "hisilicon,hi35xx_vou"; ++ interrupts = ; ++ reg = <0x13020000 0x10000>; ++ }; ++ ++ vpss: vpss@13080000 { ++ compatible = "hisilicon,hi35xx_vpss"; ++ interrupts = , ++ , ++ ; ++ interrupt-names = "vpss0", "vpss1", "vpss2"; ++ reg = <0x13080000 0x5000>, ++ <0x13110000 0x5000>, ++ <0x13180000 0x5000>; ++ reg-names = "vpss0", "vpss1", "vpss2"; ++ }; ++ ++ vgs: vgs@13150000 { ++ compatible = "hisilicon,hi35xx_vgs"; ++ interrupts = ; ++ reg = <0x13150000 0x5000>; ++ }; ++ ++ vda: vda@13090000 { ++ compatible = "hisilicon,hi35xx_vda"; ++ interrupts = ; ++ reg = <0x13090000 0x10000>; ++ }; ++ ++ tde: tde@13050000 { ++ compatible = "hisilicon,hi35xx_tde"; ++ interrupts = ; ++ reg = <0x13050000 0x1000>; ++ }; ++ ++ avc: avc@13040000 { ++ compatible = "hisilicon,hi35xx_avc"; ++ interrupts = , ++ , ++ , ++ ; ++ reg = <0x13040000 0x10000>, ++ <0x13100000 0x10000>, ++ <0x13170000 0x10000>, ++ <0x13190000 0x10000>; ++ reg-names = "vedu0", "vedu1", "vedu2", "vedu3"; ++ }; ++ ++ jpege: jpege@13130000 { ++ compatible = "hisilicon,hi35xx_jpege"; ++ interrupts = ; ++ reg = <0x13130000 0x10000>; ++ }; ++ ++ jpgd: jpgd@13070000 { ++ compatible = "hisilicon,hi35xx_jpgd"; ++ interrupts = ; ++ interrupt-names = "jpgd"; ++ reg = <0x13070000 0x10000>; ++ reg-names = "jpgd"; ++ }; ++ ++ ive: ive@13060000 { ++ compatible = "hisilicon,hi35xx_ive"; ++ interrupts = ; ++ reg = <0x13060000 0x10000>; ++ }; ++ ++ vdec: vdec@10080000 { ++ compatible = "hisilicon,hi35xx_vdec"; ++ interrupts = ; ++ interrupt-names = "scd"; ++ reg = <0x10080000 0x4000>; ++ reg-names = "scd"; ++ }; ++ ++ audio: audio@13140000 { ++ compatible = "hisilicon,hi35xx_aiao"; ++ interrupts = ; ++ reg = <0x13140000 0x10000>; ++ reg-names = "aiao"; ++ }; ++ ++ voie: audio@13120000 { ++ compatible = "hisilicon,hi35xx_aenc"; ++ interrupts = ; ++ reg = <0x13120000 0x10000>; ++ reg-names = "aenc"; ++ }; ++ ++ hdmi: hdmi@13010000 { ++ compatible = "hisilicon,hi35xx_hdmi"; ++ reg = <0x13010000 0x10000>; ++ reg-names = "hdmi"; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/hi3536dv100-demb.dts b/arch/arm/boot/dts/hi3536dv100-demb.dts +new file mode 100644 +index 0000000..cb6968f +--- /dev/null ++++ b/arch/arm/boot/dts/hi3536dv100-demb.dts +@@ -0,0 +1,192 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/dts-v1/; ++#include "hi3536dv100.dtsi" ++ ++/ { ++ model = "Hisilicon HI3536DV100 DEMO Board"; ++ compatible = "hisilicon,hi3536dv100"; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x20000000>; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&i2c_bus0 { ++ status = "okay"; ++ clock-frequency = <100000>; ++}; ++ ++&dual_timer0 { ++ status = "okay"; ++}; ++ ++&mdio0 { ++ hisilicon,phy-reset-delays-us = <10000 20000 150000>; ++ phy0: ethernet-phy@1 { ++ reg = <1>; ++ }; ++}; ++ ++&hisi_femac0 { ++ mac-address = [00 00 00 00 00 00]; ++ phy-mode = "mii"; ++ phy-handle = <&phy0>; ++}; ++ ++&hisfc { ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ }; ++}; ++ ++&hisnfc { ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ }; ++}; ++ ++&hidmac { ++ status = "okay"; ++}; ++ ++&gpio_chip0 { ++ status = "okay"; ++}; ++ ++&gpio_chip1 { ++ status = "okay"; ++}; ++ ++&gpio_chip2 { ++ status = "okay"; ++}; ++ ++&gpio_chip3 { ++ status = "okay"; ++}; ++ ++&gpio_chip4 { ++ status = "okay"; ++}; ++ ++&gpio_chip5 { ++ status = "okay"; ++}; ++ ++&pmux { ++ ++ i2s1_pmux: i2s1_pmux { ++ pinctrl-single,pins = < ++ 0x0070 0x2 ++ 0x0078 0x2 ++ 0x007c 0x2 ++ 0x0090 0x2 ++ 0x0094 0x2 ++ >; ++ }; ++ i2s2_pmux: i2s2_pmux { ++ pinctrl-single,pins = < ++ 0x0040 0x3 /*I2S_SD_RX*/ ++ 0x0044 0x3 /*I2S_MCLK*/ ++ 0x0048 0x3 /*I2S_WS*/ ++ 0x004c 0x3 /*I2S_BCLK*/ ++ 0x0050 0x3 /*I2S_SD_TX*/ ++ >; ++ }; ++}; ++ ++&sys_config_ctrl { ++ padctrl-ability,demo = < ++ 0x120f08ac 0xb0 ++ 0x120f08b4 0xb0 ++ 0x120f08b8 0xb0 ++ 0x120f08cc 0xb0 ++ 0x120f08d0 0xb0 ++ >; ++ padctrl-ability,sck = < ++ 0x120f0868 0x80 ++ 0x120f086c 0xa0 ++ 0x120f0870 0xa0 ++ 0x120f0874 0xa0 ++ 0x120f0878 0xa0 ++ >; ++ sysctrl-ddr,pins = < ++ 0x12120078 0x55322100 /* JPGD - JPGE - TFE - VGS - VDH - A7 - VDP - AIAO */ ++ 0x1212007c 0x65665526 /* FMC - DMA1 - DMA9 - DDRT - SATA - ETH1 - ETH0 - VOIE */ ++ 0x12120080 0x66666666 /* - - - - - - CIPHER - USB */ ++ 0x12120084 0x55522100 /* JPGD - JPGE - TFE - VGS - VDH - A7 - VDP - AIAO */ ++ 0x12120088 0x65665526 /* FMC - DMA1 - DMA9 - DDRT - SATA - ETH1 - ETH0 - VOIE */ ++ 0x1212008c 0x66626666 /* - - - - - - CIPHER - USB */ ++ 0x12120094 0x10 /* aio_vdp_axi_pri*/ ++ 0x12120090 0x80020000 /* aio_vdp_axi_timeout*/ ++ 0x12110020 0x000fff01 /* AXI_ACTION[19:8]:wr_rcv_mode=0,12ports */ ++ 0x12110200 0x00200000 /* ports0 */ ++ 0x12110210 0x00300000 /* ports1 */ ++ 0x12110220 0x00300000 /* ports2 */ ++ 0x12110230 0x00300000 /* ports3 */ ++ 0x12110240 0x00300000 /* ports4 */ ++ 0x12110250 0x00300000 /* ports5 */ ++ 0x12110260 0x00300000 /* ports6 */ ++ 0x12110270 0x00300000 /* ports7 */ ++ 0x12110204 0x76543210 /* ports0 */ ++ 0x12110214 0x76543210 /* ports1 */ ++ 0x12110224 0x76543210 /* ports2 */ ++ 0x12110234 0x76543210 /* ports3 */ ++ 0x12110244 0x76543210 /* ports4 */ ++ 0x12110254 0x76543210 /* ports5 */ ++ 0x12110264 0x76543210 /* ports6 */ ++ 0x12110274 0x76543210 /* ports7 */ ++ 0x12110208 0x76543210 /* ports0 */ ++ 0x12110218 0x76543210 /* ports1 */ ++ 0x12110228 0x76543210 /* ports2 */ ++ 0x12110238 0x76543210 /* ports3 */ ++ 0x12110248 0x76543210 /* ports4 */ ++ 0x12110258 0x76543210 /* ports5 */ ++ 0x12110268 0x76543210 /* ports6 */ ++ 0x12110278 0x76543210 /* ports7 */ ++ 0x12114000 0x00000002 /*qosb_push_ctrl */ ++ 0x1211410c 0x0000000a /*qosb_dmc_lvl */ ++ 0x12114110 0x0000000a /*qosb_dmc_lvl */ ++ 0x1211408c 0xb3032010 /*qosb_wbuf_ctrl */ ++ 0x12114090 0xb3032010 /*qosb_wbuf_ctrl */ ++ 0x121140f4 0x00000033 /*row-hit enable */ ++ 0x121140ec 0x00000044 /*row-hit */ ++ 0x121140f0 0x00003333 /*row-hit */ ++ 0x121141f4 0x00000000 /*qosb_wbuf_pri_ctrl*/ ++ 0x121141f0 0x00000001 /*enable qosbuf timeout,through prilvl to remap timeout level*/ ++ 0x1211409c 0x0000000a /* wr_tout3 ~wr_tout0 */ ++ 0x121140ac 0x0000000a /* rd_tout3 ~rd_tout0 */ ++ 0x121141f8 0x00800002 /* qosb_rhit_ctrl,open_window=128,close_window=2*/ ++ >; ++ pinctrl-names = "demo", "sck", "default"; ++ pinctrl-0 = <&i2s1_pmux>; ++ pinctrl-1 = <&i2s2_pmux>; ++ pinctrl-2 = <>; ++}; +diff --git a/arch/arm/boot/dts/hi3536dv100.dtsi b/arch/arm/boot/dts/hi3536dv100.dtsi +new file mode 100644 +index 0000000..970be7a +--- /dev/null ++++ b/arch/arm/boot/dts/hi3536dv100.dtsi +@@ -0,0 +1,444 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "skeleton.dtsi" ++#include ++/ { ++ aliases { ++ serial0 = &uart0; ++ i2c0 = &i2c_bus0; ++ gpio0 = &gpio_chip0; ++ gpio1 = &gpio_chip1; ++ gpio2 = &gpio_chip2; ++ gpio3 = &gpio_chip3; ++ gpio4 = &gpio_chip4; ++ gpio5 = &gpio_chip5; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a7"; ++ reg = <0>; ++ }; ++ }; ++ ++ clock: clock@12040000 { ++ compatible = "hisilicon,hi3536dv100-clock"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ #clock-cells = <1>; ++ #reset-cells = <2>; ++ reg = <0x12040000 0x1000>; ++ }; ++ ++ gic: interrupt-controller@10300000 { ++ compatible = "arm,cortex-a7-gic"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ /* gic dist base, gic cpu base , no virtual support */ ++ reg = <0x10301000 0x1000>, <0x10302000 0x100>; ++ }; ++ ++ soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ pmu { ++ compatible = "arm,cortex-a7-pmu"; ++ interrupts = <0 54 4>; ++ }; ++ ++ sysctrl: system-controller@12050000 { ++ compatible = "hisilicon,hi3536dv100-sysctrl", "syscon"; ++ reg = <0x12050000 0x1000>; ++ #clock-cells = <1>; ++ }; ++ ++ reboot { ++ compatible = "syscon-reboot"; ++ regmap = <&sysctrl>; ++ offset = <0x4>; ++ mask = <0xdeadbeef>; ++ }; ++ ++ amba { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "arm,amba-bus"; ++ ranges; ++ ++ dual_timer0: dual_timer@12000000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer0 & timer1 */ ++ interrupts = <0 1 4>; ++ reg = <0x12000000 0x1000>; ++ clocks = <&sysctrl HI3536DV100_TIME0_0_CLK>, ++ <&sysctrl HI3536DV100_TIME0_1_CLK>, ++ <&clock HI3536DV100_SYSAPB_CLK>; ++ clock-names = "timer0", "timer1", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer1: dual_timer@12010000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer2 & timer3 */ ++ interrupts = <0 2 4>; ++ reg = <0x12010000 0x1000>; ++ clocks = <&sysctrl HI3536DV100_TIME1_2_CLK>, ++ <&sysctrl HI3536DV100_TIME1_3_CLK>, ++ <&clock HI3536DV100_SYSAPB_CLK>; ++ clock-names = "timer2", "timer3", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer2: dual_timer@12020000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer4 & timer5 */ ++ interrupts = <0 3 4>; ++ reg = <0x12020000 0x1000>; ++ clocks = <&sysctrl HI3536DV100_TIME2_4_CLK>, ++ <&sysctrl HI3536DV100_TIME2_5_CLK>, ++ <&clock HI3536DV100_SYSAPB_CLK>; ++ clock-names = "timer4", "timer5", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer3: dual_timer@12030000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer6 & timer7 */ ++ interrupts = <0 4 4>; ++ reg = <0x12030000 0x1000>; ++ clocks = <&sysctrl HI3536DV100_TIME3_6_CLK>, ++ <&sysctrl HI3536DV100_TIME3_7_CLK>, ++ <&clock HI3536DV100_SYSAPB_CLK>; ++ clock-names = "timer6", "timer7", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart0: uart@12080000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12080000 0x1000>; ++ interrupts = <0 6 4>; ++ clocks = <&clock HI3536DV100_UART0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart1: uart@12090000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12090000 0x1000>; ++ interrupts = <0 7 4>; ++ clocks = <&clock HI3536DV100_UART1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart2: uart@120a0000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x120a0000 0x1000>; ++ interrupts = <0 8 4>; ++ clocks = <&clock HI3536DV100_UART2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ }; ++ ++ i2c_bus0: i2c@120c0000 { ++ compatible = "hisilicon,hi3536dv100-i2c", ++ "hisilicon,hibvt-i2c"; ++ reg = <0x120c0000 0x1000>; ++ clocks = <&clock HI3536DV100_SYSAPB_CLK>; ++ status = "disabled"; ++ }; ++ ++ sata_phy: phy@10030000 { ++ compatible = "hisilicon,hisi-sata-phy"; ++ reg = <0x10030000 0x10000>; ++ ports_num_max = <1>; ++ #phy-cells = <0>; ++ }; ++ ++ ahci: sata@10030000 { ++ compatible = "hisilicon,hisi-ahci"; ++ reg = <0x10030000 0x1000>; ++ interrupts = <0 17 4>; ++ phys = <&sata_phy>; ++ phy-names = "sata-phy"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ mdio0: mdio@10011100 { ++ compatible = "hisilicon,hisi-femac-mdio"; ++ reg = <0x10011100 0x10>, <0x12120064 0x4>, ++ <0x12121000 0x4>; ++ clocks = <&clock HI3536DV100_ETH0_CLK>, ++ <&clock HI3536DV100_ETH0_PHY_CLK>; ++ clock-names = "mdio", "phy"; ++ resets = <&clock 0xc4 3>, <&clock 0xc4 9>; ++ reset-names = "external-phy", "internal-phy"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hisi_femac0: ethernet@10010000 { ++ compatible = "hisilicon,hi3536dv100-femac", ++ "hisilicon,hisi-femac-v2"; ++ reg = <0x10010000 0x1000>,<0x10011300 0x200>; ++ interrupts = <0 11 4>; ++ clocks = <&clock HI3536DV100_ETH0_CLK>; ++ resets = <&clock 0xc4 0>; ++ reset-names = "mac"; ++ }; ++ ++ usb_phy: usbphy { ++ compatible = "hisilicon,hisi-usb-phy"; ++ reg = <0x12040000 0x1000>, <0x12120000 0x10000>; ++ }; ++ ++ ehci@0x11010000 { ++ compatible = "generic-ehci"; ++ reg = <0x11010000 0x10000>; ++ interrupts = <0 19 4>; ++ }; ++ ++ ohci@0x11000000 { ++ compatible = "generic-ohci"; ++ reg = <0x11000000 0x10000>; ++ interrupts = <0 18 4>; ++ }; ++ ++ fmc: flash-memory-controller@10000000 { ++ compatible = "hisilicon,hisi-fmc"; ++ reg = <0x10000000 0x1000>, <0x14000000 0x10000>; ++ reg-names = "control", "memory"; ++ clocks = <&clock HI3536DV100_FMC_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hisfc:spi-nor@0 { ++ compatible = "hisilicon,fmc-spi-nor"; ++ assigned-clocks = <&clock HI3536DV100_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hisnfc:spi-nand@0 { ++ compatible = "hisilicon,fmc-spi-nand"; ++ assigned-clocks = <&clock HI3536DV100_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ ++ hidmac: hidma-controller@11020000 { ++ compatible = "hisilicon,hisi-dmac"; ++ reg = <0x11020000 0x1000>; ++ interrupts = <0 14 4>; ++ clocks = <&clock HI3536DV100_DMAC_CLK>; ++ clock-names = "dmac_clk"; ++ resets = <&clock 0xc8 4>; ++ reset-names = "dma-reset"; ++ #dma-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip0: gpio_chip@12150000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12150000 0x10000>; ++ interrupts = <0 55 4>; ++ clocks = <&clock HI3536DV100_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip1: gpio_chip@12160000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12160000 0x10000>; ++ interrupts = <0 56 4>; ++ clocks = <&clock HI3536DV100_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip2: gpio_chip@12170000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12170000 0x10000>; ++ interrupts = <0 57 4>; ++ clocks = <&clock HI3536DV100_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip3: gpio_chip@12180000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12180000 0x10000>; ++ interrupts = <0 58 4>; ++ clocks = <&clock HI3536DV100_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip4: gpio_chip@12190000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12190000 0x10000>; ++ interrupts = <0 59 4>; ++ clocks = <&clock HI3536DV100_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip5: gpio_chip@121a0000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x121a0000 0x10000>; ++ interrupts = <0 60 4>; ++ clocks = <&clock HI3536DV100_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ pmux: pinmux@120F0000 { ++ compatible = "pinctrl-single"; ++ reg = <0x120F0000 0x3A8>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ #gpio-range-cells = <3>; ++ ranges; ++ ++ pinctrl-single,register-width = <32>; ++ pinctrl-single,function-mask = <7>; ++ /* pin base, nr pins & gpio function */ ++ pinctrl-single,gpio-range = <&range 0 54 0 ++ &range 55 6 1 &range 61 5 0>; ++ ++ range: gpio-range { ++ #pinctrl-single,gpio-range-cells = <3>; ++ }; ++ }; ++ }; ++ ++ media { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ osal: osal { ++ compatible = "hisilicon,osal"; ++ }; ++ ++ sys: sys@12040000 { ++ compatible = "hisilicon,hi35xx_sys"; ++ reg = <0x12040000 0x10000>, <0x12050000 0x10000>, ++ <0x12110000 0x10000>, <0x12120000 0x10000>; ++ reg-names = "crg", "sys", "ddr", "misc"; ++ }; ++ ++ rtc: rtc@120b0000 { ++ compatible = "hisilicon,hi35xx-rtc"; ++ interrupts = <0 5 4>; ++ reg = <0x120b0000 0x10000>; ++ }; ++ ++ vou: vou@13020000 { ++ compatible = "hisilicon,hi35xx_vou"; ++ interrupts = <0 34 4>; ++ reg = <0x13020000 0x10000>; ++ }; ++ ++ vgs: vgs@13100000 { ++ compatible = "hisilicon,hi35xx_vgs"; ++ interrupts = <0 28 4>; ++ reg = <0x13100000 0x10000>; ++ }; ++ ++ audio: audio@13040000 { ++ compatible = "hisilicon,hi35xx_aiao"; ++ interrupts = <0 32 4>; ++ reg = <0x13040000 0x10000>, <0x130500d0 0x10000>; ++ reg-names = "aiao", "acodec"; ++ }; ++ ++ vdec: vdec@13200000 { ++ compatible = "hisilicon,hi35xx_vdec"; ++ interrupts = <0 21 4>, <0 23 4>; ++ interrupt-names = "vdm", "scd"; ++ reg = <0x13200000 0xc000>, <0x1320c000 0x4000>; ++ reg-names = "vdm", "scd"; ++ }; ++ ++ tde: tde@13130000 { ++ compatible = "hisilicon,hi35xx_tde"; ++ interrupts = <0 29 4>; ++ reg = <0x13130000 0x1000>; ++ }; ++ ++ jpgd: jpgd@13110000 { ++ compatible = "hisilicon,hi35xx_jpgd"; ++ interrupts = <0 31 4>; ++ interrupt-names = "jpgd"; ++ reg = <0x13110000 0x10000>; ++ reg-names = "jpgd"; ++ }; ++ ++ hiir: hiir@0x12140000 { ++ compatible = "hisilicon,hi_ir"; ++ interrupts = <0 9 4>; ++ reg = <0x12140000 0x10000>; ++ }; ++ ++ cipher: cipher@0x11030000 { ++ compatible = "hisilicon,hi_isr"; ++ interrupts = <0 13 4>; ++ reg = <0x11030000 0x10000>; ++ }; ++ ++ jpege: jpege@13120000 { ++ compatible = "hisilicon,hi35xx_jpege"; ++ interrupts = <0 30 4>; ++ reg = <0x13120000 0x10000>; ++ }; ++ ++ pin_ctrl_ddr: pin_ctrl_ddr { ++ compatible = "hisilicon,pinctrl-ddr"; ++ }; ++ ++ sys_config_ctrl: sys_config_ctrl { ++ compatible = "hisilicon,sys_config_ctrl"; ++ }; ++ }; ++}; +diff --git a/arch/arm/configs/hi3516a_full_defconfig b/arch/arm/configs/hi3516a_full_defconfig +new file mode 100644 +index 0000000..224aa31 +--- /dev/null ++++ b/arch/arm/configs/hi3516a_full_defconfig +@@ -0,0 +1,2736 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 4.9.37 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_GENERIC_BUG=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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++CONFIG_FHANDLE=y ++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_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=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=17 ++CONFIG_NMI_LOG_BUF_SHIFT=13 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_MEMCG is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CGROUP_SCHED is not set ++# CONFIG_CGROUP_PIDS is not set ++CONFIG_CGROUP_FREEZER=y ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++CONFIG_RD_LZ4=y ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++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_ALL is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_PRINTK_NMI=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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=y ++CONFIG_SLUB_DEBUG=y ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# 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 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_ARCH_HAS_GCOV_PROFILE_ALL=y ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# 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_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 ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_ARTPEC is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_DIGICOLOR is not set ++# CONFIG_ARCH_HIGHBANK is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++ ++# ++# Hisilicon BVT platform type ++# ++CONFIG_ARCH_HI3516A=y ++# CONFIG_ARCH_HI3536DV100 is not set ++# CONFIG_ARCH_HI3521A is not set ++# CONFIG_ARCH_HI3531A is not set ++CONFIG_HI_ZRELADDR=0x80008000 ++CONFIG_HI_PARAMS_PHYS=0x00000100 ++CONFIG_HI_INITRD_PHYS=0x00800000 ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TANGO is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQ is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++# CONFIG_SWP_EMULATE is not set ++# 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_VDSO=y ++CONFIG_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++# CONFIG_DEBUG_RODATA is not set ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++# CONFIG_ARM_ERRATA_818325_852422 is not set ++# CONFIG_ARM_ERRATA_821420 is not set ++# CONFIG_ARM_ERRATA_825619 is not set ++# CONFIG_ARM_ERRATA_852421 is not set ++# CONFIG_ARM_ERRATA_852423 is not set ++ ++# ++# Bus support ++# ++# CONFIG_PCI is not set ++# CONFIG_PCI_DOMAINS_GENERIC is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++# CONFIG_SMP is not set ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++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_ARM_PSCI is not set ++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_THUMB2_KERNEL is not set ++CONFIG_ARM_PATCH_IDIV=y ++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 is not set ++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_FRONTSWAP 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 ++# CONFIG_XEN 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# 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=y ++CONFIG_CPU_FREQ_GOV_ATTR_SET=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++ ++# ++# CPU frequency scaling drivers ++# ++CONFIG_CPUFREQ_DT=y ++CONFIG_CPUFREQ_DT_PLATDEV=y ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++# CONFIG_QORIQ_CPUFREQ 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++# CONFIG_KERNEL_MODE_NEON is not set ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=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=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HIBERNATION=y ++CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++CONFIG_PM_DEBUG=y ++# CONFIG_PM_ADVANCED_DEBUG is not set ++CONFIG_PM_SLEEP_DEBUG=y ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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_ALGO=y ++CONFIG_XFRM_USER=y ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++CONFIG_NET_KEY=y ++# CONFIG_NET_KEY_MIGRATE is not set ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++# CONFIG_IP_FIB_TRIE_STATS is not set ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++# CONFIG_IP_PNP_DHCP is not set ++# 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 is not set ++CONFIG_IP_MROUTE=y ++# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_SYN_COOKIES=y ++# CONFIG_NET_UDP_TUNNEL is not set ++# CONFIG_NET_FOU 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 is not set ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++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=y ++CONFIG_TCP_CONG_BIC=m ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_TCP_CONG_WESTWOOD=m ++CONFIG_TCP_CONG_HTCP=m ++# CONFIG_TCP_CONG_HSTCP is not set ++# CONFIG_TCP_CONG_HYBLA is not set ++# CONFIG_TCP_CONG_VEGAS is not set ++# CONFIG_TCP_CONG_NV is not set ++# CONFIG_TCP_CONG_SCALABLE is not set ++# CONFIG_TCP_CONG_LP is not set ++# CONFIG_TCP_CONG_VENO is not set ++# CONFIG_TCP_CONG_YEAH is not set ++# CONFIG_TCP_CONG_ILLINOIS is not set ++# CONFIG_TCP_CONG_DCTCP is not set ++# CONFIG_TCP_CONG_CDG is not set ++# CONFIG_TCP_CONG_BBR is not set ++CONFIG_DEFAULT_CUBIC=y ++# CONFIG_DEFAULT_RENO is not set ++CONFIG_DEFAULT_TCP_CONG="cubic" ++CONFIG_TCP_MD5SIG=y ++# CONFIG_IPV6 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_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_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_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_FIB_RULES=y ++CONFIG_WIRELESS=y ++CONFIG_WEXT_CORE=y ++CONFIG_WEXT_PROC=y ++CONFIG_CFG80211=m ++# CONFIG_NL80211_TESTMODE is not set ++# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set ++CONFIG_CFG80211_DEFAULT_PS=y ++# CONFIG_CFG80211_INTERNAL_REGDB is not set ++CONFIG_CFG80211_CRDA_SUPPORT=y ++CONFIG_CFG80211_WEXT=y ++# CONFIG_LIB80211 is not set ++CONFIG_MAC80211=m ++CONFIG_MAC80211_HAS_RC=y ++CONFIG_MAC80211_RC_MINSTREL=y ++CONFIG_MAC80211_RC_MINSTREL_HT=y ++# CONFIG_MAC80211_RC_MINSTREL_VHT is not set ++CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y ++CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" ++CONFIG_MAC80211_MESH=y ++# CONFIG_MAC80211_MESSAGE_TRACING is not set ++# CONFIG_MAC80211_DEBUG_MENU is not set ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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 is not set ++# CONFIG_NET_DEVLINK is not set ++CONFIG_MAY_USE_DEVLINK=y ++CONFIG_HAVE_CBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# 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_SWAP 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 is not set ++# 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_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++# CONFIG_MTD_SPI_NAND_HISI_BVT is not set ++CONFIG_MTD_NAND_HINFC610=y ++CONFIG_HINFC610_MAX_CHIP=1 ++CONFIG_HINFC610_DBG_NAND_DEBUG=y ++CONFIG_HINFC610_DBG_NAND_DUMP=y ++CONFIG_HINFC610_DBG_NAND_ERASE_COUNT=y ++CONFIG_HINFC610_DBG_NAND_ECC_COUNT=y ++CONFIG_HINFC610_DBG_NAND_READ_RETRY=y ++CONFIG_HINFC610_AUTO_PAGESIZE_ECC=y ++# CONFIG_HINFC610_PAGESIZE_AUTO_ECC_NONE 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 is not set ++# CONFIG_SPI_CADENCE_QUADSPI is not set ++# CONFIG_SPI_HISI_SFC is not set ++CONFIG_MTD_SPI_IDS=y ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_MTD_HISFC350=y ++CONFIG_HISFC350_SYSCTRL_ADDRESS=0x20030000 ++CONFIG_HISFC350_CHIP_NUM=2 ++# CONFIG_HISFC350_SHOW_CYCLE_TIMING is not set ++# CONFIG_HISFC350_ENABLE_CHIPSELECT_0 is not set ++CONFIG_HISFC350_ENABLE_CHIPSELECT_1=y ++# CONFIG_HISFC350_ENABLE_INTR_DMA is not set ++CONFIG_CMD_SPI_BLOCK_PROTECTION=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK 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=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# 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=y ++CONFIG_SCSI_DMA=y ++CONFIG_SCSI_NETLINK=y ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++CONFIG_SCSI_FC_ATTRS=y ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_LIBFC is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++CONFIG_HIETH_GMAC=y ++# CONFIG_HIGMAC_DESC_4WORD is not set ++# CONFIG_HIGMAC_RXCSUM is not set ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# 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_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 ++CONFIG_MDIO_HISI_GEMAC=y ++ ++# ++# 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_IPHETH is not set ++# CONFIG_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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_GP2A is not set ++# CONFIG_INPUT_GPIO_BEEPER is not set ++# CONFIG_INPUT_GPIO_TILT_POLLED is not set ++# CONFIG_INPUT_GPIO_DECODER is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INPUT_CM109 is not set ++# CONFIG_INPUT_REGULATOR_HAPTIC is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV260X_HAPTICS is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_USERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# 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_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_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=y ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_MUX is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# 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_HIBVT is not set ++# CONFIG_I2C_NOMADIK 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_HISI=y ++# 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_DEBUG is not set ++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_GPIO is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_OC_TINY is not set ++CONFIG_SPI_PL022=y ++# 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=y ++# 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_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers ++# ++# CONFIG_GPIO_74XX_MMIO is not set ++# CONFIG_GPIO_ALTERA is not set ++# 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_PL061=y ++# CONFIG_GPIO_SYSCON 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++CONFIG_POWER_RESET_SYSCON=y ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_MANAGER is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_BQ25890 is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_CHARGER_RT9455 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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_MFD_HISI_FMC 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=y ++# 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_LTC3676 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MT6311 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_PV88060 is not set ++# CONFIG_REGULATOR_PV88080 is not set ++# CONFIG_REGULATOR_PV88090 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++# CONFIG_HID_A4TECH is not set ++# CONFIG_HID_ACRUX is not set ++# CONFIG_HID_APPLE is not set ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++# CONFIG_HID_BELKIN is not set ++# CONFIG_HID_BETOP_FF is not set ++# CONFIG_HID_CHERRY is not set ++# CONFIG_HID_CHICONY is not set ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CP2112 is not set ++# CONFIG_HID_CYPRESS is not set ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++# CONFIG_HID_EZKEY is not set ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++# CONFIG_HID_KENSINGTON is not set ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++# CONFIG_HID_LOGITECH is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++# CONFIG_HID_MONTEREY is not set ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# 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=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_SISUSBVGA 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_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# CONFIG_MMC_SPI is not set ++# 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_HIMCI=y ++CONFIG_SEND_AUTO_STOP=y ++# 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 is not set ++# CONFIG_DMADEVICES 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_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++CONFIG_COMMON_CLK_HI3516A=y ++CONFIG_RESET_HISI=y ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++CONFIG_ARM_ARCH_TIMER_VCT_ACCESS=y ++CONFIG_ARM_TIMER_SP804=y ++# 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 is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_ZYNQ is not set ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# 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_PHY_HISI_USB2=y ++# 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 ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# Firmware Drivers ++# ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT2=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_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=y ++CONFIG_EXPORTFS=y ++# 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=y ++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=m ++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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_UBIFS_ATIME_SUPPORT is not set ++# CONFIG_LOGFS is not set ++CONFIG_CRAMFS=y ++# 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFS_V4_1 is not set ++CONFIG_ROOT_NFS=y ++# CONFIG_NFS_USE_LEGACY_DNS is not set ++CONFIG_NFS_USE_KERNEL_DNS=y ++# CONFIG_NFSD is not set ++CONFIG_GRACE_PERIOD=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++CONFIG_SUNRPC_GSS=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_WQ_WATCHDOG is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++# CONFIG_SCHED_DEBUG is not set ++# CONFIG_SCHED_INFO is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++CONFIG_DEBUG_MUTEXES=y ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS 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_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set ++# CONFIG_UBSAN is not set ++CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y ++CONFIG_STRICT_DEVMEM=y ++# CONFIG_IO_STRICT_DEVMEM is not set ++# CONFIG_ARM_PTDUMP is not set ++# CONFIG_ARM_UNWIND is not set ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL 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_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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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=m ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++CONFIG_CRYPTO_GF128MUL=m ++CONFIG_CRYPTO_NULL=m ++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=m ++CONFIG_CRYPTO_GCM=m ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# 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=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++CONFIG_CRYPTO_CRCT10DIF=y ++CONFIG_CRYPTO_GHASH=m ++# CONFIG_CRYPTO_POLY1305 is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=y ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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=y ++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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++# CONFIG_CRYPTO_HW 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=y ++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=y ++CONFIG_CRC16=y ++CONFIG_CRC_T10DIF=y ++CONFIG_CRC_ITU_T=y ++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=y ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_LZ4=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_CORDIC is not set ++# CONFIG_DDR is not set ++# CONFIG_IRQ_POLL is not set ++CONFIG_LIBFDT=y ++CONFIG_OID_REGISTRY=y ++# CONFIG_SG_SPLIT is not set ++CONFIG_SG_POOL=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3516a_mini_defconfig b/arch/arm/configs/hi3516a_mini_defconfig +new file mode 100644 +index 0000000..7d24d93 +--- /dev/null ++++ b/arch/arm/configs/hi3516a_mini_defconfig +@@ -0,0 +1,2335 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 4.9.37 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_GENERIC_BUG=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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++CONFIG_FHANDLE=y ++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_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=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=17 ++CONFIG_NMI_LOG_BUF_SHIFT=13 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_MEMCG is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CGROUP_SCHED is not set ++# CONFIG_CGROUP_PIDS is not set ++CONFIG_CGROUP_FREEZER=y ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++CONFIG_RD_LZ4=y ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++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_ALL is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_PRINTK_NMI=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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=y ++CONFIG_SLUB_DEBUG=y ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# 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 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_ARCH_HAS_GCOV_PROFILE_ALL=y ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# 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_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 ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_ARTPEC is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_DIGICOLOR is not set ++# CONFIG_ARCH_HIGHBANK is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++ ++# ++# Hisilicon BVT platform type ++# ++CONFIG_ARCH_HI3516A=y ++# CONFIG_ARCH_HI3536DV100 is not set ++# CONFIG_ARCH_HI3521A is not set ++# CONFIG_ARCH_HI3531A is not set ++CONFIG_HI_ZRELADDR=0x80008000 ++CONFIG_HI_PARAMS_PHYS=0x00000100 ++CONFIG_HI_INITRD_PHYS=0x00800000 ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TANGO is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQ is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++# CONFIG_SWP_EMULATE is not set ++# 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_VDSO=y ++CONFIG_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++# CONFIG_DEBUG_RODATA is not set ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++# CONFIG_ARM_ERRATA_818325_852422 is not set ++# CONFIG_ARM_ERRATA_821420 is not set ++# CONFIG_ARM_ERRATA_825619 is not set ++# CONFIG_ARM_ERRATA_852421 is not set ++# CONFIG_ARM_ERRATA_852423 is not set ++ ++# ++# Bus support ++# ++# CONFIG_PCI is not set ++# CONFIG_PCI_DOMAINS_GENERIC is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++# CONFIG_SMP is not set ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++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_ARM_PSCI is not set ++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_THUMB2_KERNEL is not set ++CONFIG_ARM_PATCH_IDIV=y ++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 is not set ++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_FRONTSWAP 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 ++# CONFIG_XEN 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# 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=y ++CONFIG_CPU_FREQ_GOV_ATTR_SET=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++ ++# ++# CPU frequency scaling drivers ++# ++CONFIG_CPUFREQ_DT=y ++CONFIG_CPUFREQ_DT_PLATDEV=y ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++# CONFIG_QORIQ_CPUFREQ 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++# CONFIG_KERNEL_MODE_NEON is not set ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=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=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HIBERNATION=y ++CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++CONFIG_PM_DEBUG=y ++# CONFIG_PM_ADVANCED_DEBUG is not set ++CONFIG_PM_SLEEP_DEBUG=y ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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_ALGO=y ++CONFIG_XFRM_USER=y ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++CONFIG_NET_KEY=y ++# CONFIG_NET_KEY_MIGRATE is not set ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++# CONFIG_IP_FIB_TRIE_STATS is not set ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++# CONFIG_IP_PNP_DHCP is not set ++# 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 is not set ++CONFIG_IP_MROUTE=y ++# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_SYN_COOKIES=y ++# CONFIG_NET_UDP_TUNNEL is not set ++# CONFIG_NET_FOU 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 is not set ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++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=y ++CONFIG_TCP_CONG_BIC=m ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_TCP_CONG_WESTWOOD=m ++CONFIG_TCP_CONG_HTCP=m ++# CONFIG_TCP_CONG_HSTCP is not set ++# CONFIG_TCP_CONG_HYBLA is not set ++# CONFIG_TCP_CONG_VEGAS is not set ++# CONFIG_TCP_CONG_NV is not set ++# CONFIG_TCP_CONG_SCALABLE is not set ++# CONFIG_TCP_CONG_LP is not set ++# CONFIG_TCP_CONG_VENO is not set ++# CONFIG_TCP_CONG_YEAH is not set ++# CONFIG_TCP_CONG_ILLINOIS is not set ++# CONFIG_TCP_CONG_DCTCP is not set ++# CONFIG_TCP_CONG_CDG is not set ++# CONFIG_TCP_CONG_BBR is not set ++CONFIG_DEFAULT_CUBIC=y ++# CONFIG_DEFAULT_RENO is not set ++CONFIG_DEFAULT_TCP_CONG="cubic" ++CONFIG_TCP_MD5SIG=y ++# CONFIG_IPV6 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_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_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_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_FIB_RULES=y ++# CONFIG_WIRELESS is not set ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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 is not set ++# CONFIG_NET_DEVLINK is not set ++CONFIG_MAY_USE_DEVLINK=y ++CONFIG_HAVE_CBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# 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_SWAP 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 is not set ++# 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_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++# CONFIG_MTD_SPI_NAND_HISI_BVT is not set ++CONFIG_MTD_NAND_HINFC610=y ++CONFIG_HINFC610_MAX_CHIP=1 ++CONFIG_HINFC610_DBG_NAND_DEBUG=y ++CONFIG_HINFC610_DBG_NAND_DUMP=y ++CONFIG_HINFC610_DBG_NAND_ERASE_COUNT=y ++CONFIG_HINFC610_DBG_NAND_ECC_COUNT=y ++CONFIG_HINFC610_DBG_NAND_READ_RETRY=y ++CONFIG_HINFC610_AUTO_PAGESIZE_ECC=y ++# CONFIG_HINFC610_PAGESIZE_AUTO_ECC_NONE 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 is not set ++# CONFIG_SPI_CADENCE_QUADSPI is not set ++# CONFIG_SPI_HISI_SFC is not set ++CONFIG_MTD_SPI_IDS=y ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_MTD_HISFC350=y ++CONFIG_HISFC350_SYSCTRL_ADDRESS=0x20030000 ++CONFIG_HISFC350_CHIP_NUM=2 ++# CONFIG_HISFC350_SHOW_CYCLE_TIMING is not set ++# CONFIG_HISFC350_ENABLE_CHIPSELECT_0 is not set ++CONFIG_HISFC350_ENABLE_CHIPSELECT_1=y ++# CONFIG_HISFC350_ENABLE_INTR_DMA is not set ++CONFIG_CMD_SPI_BLOCK_PROTECTION=y ++# 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=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# 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_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_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=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++CONFIG_HIETH_GMAC=y ++# CONFIG_HIGMAC_DESC_4WORD is not set ++# CONFIG_HIGMAC_RXCSUM is not set ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# 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_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_MMIOREG is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++ ++# ++# 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 ++ ++# ++# Host-side USB support is needed for USB Network Adapter support ++# ++# CONFIG_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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_REGULATOR_HAPTIC is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_USERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# 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_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART 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_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=y ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_MUX is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_EMEV2 is not set ++# CONFIG_I2C_HIBVT is not set ++# CONFIG_I2C_NOMADIK 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_PARPORT_LIGHT is not set ++# CONFIG_I2C_TAOS_EVM is not set ++ ++# ++# Other I2C/SMBus bus drivers ++# ++CONFIG_I2C_HISI=y ++# 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_DEBUG is not set ++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_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# 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=y ++# 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 is not set ++# 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++CONFIG_POWER_RESET_SYSCON=y ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_MANAGER is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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_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_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_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_MFD_HISI_FMC is not set ++# CONFIG_HTC_PASIC3 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_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_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=y ++# 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_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_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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_LTC3676 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MT6311 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_PV88060 is not set ++# CONFIG_REGULATOR_PV88080 is not set ++# CONFIG_REGULATOR_PV88090 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++# CONFIG_HID is not set ++ ++# ++# I2C HID support ++# ++# CONFIG_I2C_HID is not set ++CONFIG_USB_OHCI_LITTLE_ENDIAN=y ++# CONFIG_USB_SUPPORT is not set ++# CONFIG_UWB is not set ++# CONFIG_MMC 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 is not set ++# CONFIG_DMADEVICES 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_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++CONFIG_COMMON_CLK_HI3516A=y ++CONFIG_RESET_HISI=y ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++CONFIG_ARM_ARCH_TIMER_VCT_ACCESS=y ++CONFIG_ARM_TIMER_SP804=y ++# 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 is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_ZYNQ is not set ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# 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_PHY_HISI_USB2=y ++# 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 ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# Firmware Drivers ++# ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT2=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_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=y ++CONFIG_EXPORTFS=y ++# 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=y ++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=m ++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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++# 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFS_V4_1 is not set ++CONFIG_ROOT_NFS=y ++# CONFIG_NFS_USE_LEGACY_DNS is not set ++CONFIG_NFS_USE_KERNEL_DNS=y ++# CONFIG_NFSD is not set ++CONFIG_GRACE_PERIOD=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++CONFIG_SUNRPC_GSS=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_WQ_WATCHDOG is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++# CONFIG_SCHED_DEBUG is not set ++# CONFIG_SCHED_INFO is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++CONFIG_DEBUG_MUTEXES=y ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS 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_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set ++# CONFIG_UBSAN is not set ++CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y ++CONFIG_STRICT_DEVMEM=y ++# CONFIG_IO_STRICT_DEVMEM is not set ++# CONFIG_ARM_PTDUMP is not set ++# CONFIG_ARM_UNWIND is not set ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL 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_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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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=m ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++CONFIG_CRYPTO_GF128MUL=m ++CONFIG_CRYPTO_NULL=m ++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=m ++CONFIG_CRYPTO_GCM=m ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# 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=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++CONFIG_CRYPTO_CRCT10DIF=y ++CONFIG_CRYPTO_GHASH=m ++# CONFIG_CRYPTO_POLY1305 is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=y ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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=y ++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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++# CONFIG_CRYPTO_HW 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=y ++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=y ++CONFIG_CRC16=y ++CONFIG_CRC_T10DIF=y ++CONFIG_CRC_ITU_T=y ++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=y ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_LZ4=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_CORDIC is not set ++# CONFIG_DDR is not set ++# CONFIG_IRQ_POLL is not set ++CONFIG_LIBFDT=y ++CONFIG_OID_REGISTRY=y ++# CONFIG_SG_SPLIT is not set ++# CONFIG_SG_POOL is not set ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3516a_spinand_defconfig b/arch/arm/configs/hi3516a_spinand_defconfig +new file mode 100644 +index 0000000..349af50 +--- /dev/null ++++ b/arch/arm/configs/hi3516a_spinand_defconfig +@@ -0,0 +1,2732 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 4.9.37 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_GENERIC_BUG=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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++CONFIG_FHANDLE=y ++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_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=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=17 ++CONFIG_NMI_LOG_BUF_SHIFT=13 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_MEMCG is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CGROUP_SCHED is not set ++# CONFIG_CGROUP_PIDS is not set ++CONFIG_CGROUP_FREEZER=y ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++CONFIG_RD_LZ4=y ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++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_ALL is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_PRINTK_NMI=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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=y ++CONFIG_SLUB_DEBUG=y ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# 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 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_ARCH_HAS_GCOV_PROFILE_ALL=y ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# 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_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 ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_ARTPEC is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_DIGICOLOR is not set ++# CONFIG_ARCH_HIGHBANK is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++ ++# ++# Hisilicon BVT platform type ++# ++CONFIG_ARCH_HI3516A=y ++# CONFIG_ARCH_HI3536DV100 is not set ++# CONFIG_ARCH_HI3521A is not set ++# CONFIG_ARCH_HI3531A is not set ++CONFIG_HI_ZRELADDR=0x80008000 ++CONFIG_HI_PARAMS_PHYS=0x00000100 ++CONFIG_HI_INITRD_PHYS=0x00800000 ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TANGO is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQ is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++# CONFIG_SWP_EMULATE is not set ++# 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_VDSO=y ++CONFIG_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++# CONFIG_DEBUG_RODATA is not set ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++# CONFIG_ARM_ERRATA_818325_852422 is not set ++# CONFIG_ARM_ERRATA_821420 is not set ++# CONFIG_ARM_ERRATA_825619 is not set ++# CONFIG_ARM_ERRATA_852421 is not set ++# CONFIG_ARM_ERRATA_852423 is not set ++ ++# ++# Bus support ++# ++# CONFIG_PCI is not set ++# CONFIG_PCI_DOMAINS_GENERIC is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++# CONFIG_SMP is not set ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++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_ARM_PSCI is not set ++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_THUMB2_KERNEL is not set ++CONFIG_ARM_PATCH_IDIV=y ++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 is not set ++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_FRONTSWAP 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 ++# CONFIG_XEN 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# 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=y ++CONFIG_CPU_FREQ_GOV_ATTR_SET=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++ ++# ++# CPU frequency scaling drivers ++# ++CONFIG_CPUFREQ_DT=y ++CONFIG_CPUFREQ_DT_PLATDEV=y ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++# CONFIG_QORIQ_CPUFREQ 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++# CONFIG_KERNEL_MODE_NEON is not set ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=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=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HIBERNATION=y ++CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++CONFIG_PM_DEBUG=y ++# CONFIG_PM_ADVANCED_DEBUG is not set ++CONFIG_PM_SLEEP_DEBUG=y ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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_ALGO=y ++CONFIG_XFRM_USER=y ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++CONFIG_NET_KEY=y ++# CONFIG_NET_KEY_MIGRATE is not set ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++# CONFIG_IP_FIB_TRIE_STATS is not set ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++# CONFIG_IP_PNP_DHCP is not set ++# 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 is not set ++CONFIG_IP_MROUTE=y ++# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_SYN_COOKIES=y ++# CONFIG_NET_UDP_TUNNEL is not set ++# CONFIG_NET_FOU 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 is not set ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++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=y ++CONFIG_TCP_CONG_BIC=m ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_TCP_CONG_WESTWOOD=m ++CONFIG_TCP_CONG_HTCP=m ++# CONFIG_TCP_CONG_HSTCP is not set ++# CONFIG_TCP_CONG_HYBLA is not set ++# CONFIG_TCP_CONG_VEGAS is not set ++# CONFIG_TCP_CONG_NV is not set ++# CONFIG_TCP_CONG_SCALABLE is not set ++# CONFIG_TCP_CONG_LP is not set ++# CONFIG_TCP_CONG_VENO is not set ++# CONFIG_TCP_CONG_YEAH is not set ++# CONFIG_TCP_CONG_ILLINOIS is not set ++# CONFIG_TCP_CONG_DCTCP is not set ++# CONFIG_TCP_CONG_CDG is not set ++# CONFIG_TCP_CONG_BBR is not set ++CONFIG_DEFAULT_CUBIC=y ++# CONFIG_DEFAULT_RENO is not set ++CONFIG_DEFAULT_TCP_CONG="cubic" ++CONFIG_TCP_MD5SIG=y ++# CONFIG_IPV6 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_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_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_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_FIB_RULES=y ++CONFIG_WIRELESS=y ++CONFIG_WEXT_CORE=y ++CONFIG_WEXT_PROC=y ++CONFIG_CFG80211=m ++# CONFIG_NL80211_TESTMODE is not set ++# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set ++CONFIG_CFG80211_DEFAULT_PS=y ++# CONFIG_CFG80211_INTERNAL_REGDB is not set ++CONFIG_CFG80211_CRDA_SUPPORT=y ++CONFIG_CFG80211_WEXT=y ++# CONFIG_LIB80211 is not set ++CONFIG_MAC80211=m ++CONFIG_MAC80211_HAS_RC=y ++CONFIG_MAC80211_RC_MINSTREL=y ++CONFIG_MAC80211_RC_MINSTREL_HT=y ++# CONFIG_MAC80211_RC_MINSTREL_VHT is not set ++CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y ++CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" ++CONFIG_MAC80211_MESH=y ++# CONFIG_MAC80211_MESSAGE_TRACING is not set ++# CONFIG_MAC80211_DEBUG_MENU is not set ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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 is not set ++# CONFIG_NET_DEVLINK is not set ++CONFIG_MAY_USE_DEVLINK=y ++CONFIG_HAVE_CBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# 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_SWAP 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 is not set ++# 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_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++CONFIG_MTD_SPI_NAND_HISI_BVT=y ++CONFIG_MTD_NAND_HISNFC100=y ++CONFIG_HISNFC100_MAX_CHIP=1 ++CONFIG_HISNFC100_HARDWARE_PAGESIZE_ECC=y ++# CONFIG_HISNFC100_AUTO_PAGESIZE_ECC is not set ++# CONFIG_HISNFC100_PAGESIZE_AUTO_ECC_NONE 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 is not set ++# CONFIG_SPI_CADENCE_QUADSPI is not set ++# CONFIG_SPI_HISI_SFC is not set ++CONFIG_MTD_SPI_IDS=y ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_MTD_HISFC350=y ++CONFIG_HISFC350_SYSCTRL_ADDRESS=0x20030000 ++CONFIG_HISFC350_CHIP_NUM=2 ++# CONFIG_HISFC350_SHOW_CYCLE_TIMING is not set ++# CONFIG_HISFC350_ENABLE_CHIPSELECT_0 is not set ++CONFIG_HISFC350_ENABLE_CHIPSELECT_1=y ++# CONFIG_HISFC350_ENABLE_INTR_DMA is not set ++CONFIG_CMD_SPI_BLOCK_PROTECTION=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK 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=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# 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=y ++CONFIG_SCSI_DMA=y ++CONFIG_SCSI_NETLINK=y ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++CONFIG_SCSI_FC_ATTRS=y ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_LIBFC is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++CONFIG_HIETH_GMAC=y ++# CONFIG_HIGMAC_DESC_4WORD is not set ++# CONFIG_HIGMAC_RXCSUM is not set ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# 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_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 ++CONFIG_MDIO_HISI_GEMAC=y ++ ++# ++# 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_IPHETH is not set ++# CONFIG_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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_GP2A is not set ++# CONFIG_INPUT_GPIO_BEEPER is not set ++# CONFIG_INPUT_GPIO_TILT_POLLED is not set ++# CONFIG_INPUT_GPIO_DECODER is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INPUT_CM109 is not set ++# CONFIG_INPUT_REGULATOR_HAPTIC is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV260X_HAPTICS is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_USERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# 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_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_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=y ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_MUX is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# 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_HIBVT is not set ++# CONFIG_I2C_NOMADIK 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_HISI=y ++# 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_DEBUG is not set ++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_GPIO is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_OC_TINY is not set ++CONFIG_SPI_PL022=y ++# 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=y ++# 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_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers ++# ++# CONFIG_GPIO_74XX_MMIO is not set ++# CONFIG_GPIO_ALTERA is not set ++# 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_PL061=y ++# CONFIG_GPIO_SYSCON 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++CONFIG_POWER_RESET_SYSCON=y ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_MANAGER is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_BQ25890 is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_CHARGER_RT9455 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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_MFD_HISI_FMC 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=y ++# 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_LTC3676 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MT6311 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_PV88060 is not set ++# CONFIG_REGULATOR_PV88080 is not set ++# CONFIG_REGULATOR_PV88090 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++# CONFIG_HID_A4TECH is not set ++# CONFIG_HID_ACRUX is not set ++# CONFIG_HID_APPLE is not set ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++# CONFIG_HID_BELKIN is not set ++# CONFIG_HID_BETOP_FF is not set ++# CONFIG_HID_CHERRY is not set ++# CONFIG_HID_CHICONY is not set ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CP2112 is not set ++# CONFIG_HID_CYPRESS is not set ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++# CONFIG_HID_EZKEY is not set ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++# CONFIG_HID_KENSINGTON is not set ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++# CONFIG_HID_LOGITECH is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++# CONFIG_HID_MONTEREY is not set ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# 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=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_SISUSBVGA 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_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# CONFIG_MMC_SPI is not set ++# 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_HIMCI=y ++CONFIG_SEND_AUTO_STOP=y ++# 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 is not set ++# CONFIG_DMADEVICES 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_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++CONFIG_COMMON_CLK_HI3516A=y ++CONFIG_RESET_HISI=y ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++CONFIG_ARM_ARCH_TIMER_VCT_ACCESS=y ++CONFIG_ARM_TIMER_SP804=y ++# 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 is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_ZYNQ is not set ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# 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_PHY_HISI_USB2=y ++# 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 ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# Firmware Drivers ++# ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT2=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_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=y ++CONFIG_EXPORTFS=y ++# 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=y ++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=m ++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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_UBIFS_ATIME_SUPPORT is not set ++# CONFIG_LOGFS is not set ++CONFIG_CRAMFS=y ++# 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFS_V4_1 is not set ++CONFIG_ROOT_NFS=y ++# CONFIG_NFS_USE_LEGACY_DNS is not set ++CONFIG_NFS_USE_KERNEL_DNS=y ++# CONFIG_NFSD is not set ++CONFIG_GRACE_PERIOD=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++CONFIG_SUNRPC_GSS=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_WQ_WATCHDOG is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++# CONFIG_SCHED_DEBUG is not set ++# CONFIG_SCHED_INFO is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++CONFIG_DEBUG_MUTEXES=y ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS 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_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set ++# CONFIG_UBSAN is not set ++CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y ++CONFIG_STRICT_DEVMEM=y ++# CONFIG_IO_STRICT_DEVMEM is not set ++# CONFIG_ARM_PTDUMP is not set ++# CONFIG_ARM_UNWIND is not set ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL 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_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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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=m ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++CONFIG_CRYPTO_GF128MUL=m ++CONFIG_CRYPTO_NULL=m ++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=m ++CONFIG_CRYPTO_GCM=m ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# 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=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++CONFIG_CRYPTO_CRCT10DIF=y ++CONFIG_CRYPTO_GHASH=m ++# CONFIG_CRYPTO_POLY1305 is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=y ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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=y ++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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++# CONFIG_CRYPTO_HW 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=y ++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=y ++CONFIG_CRC16=y ++CONFIG_CRC_T10DIF=y ++CONFIG_CRC_ITU_T=y ++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=y ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_LZ4=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_CORDIC is not set ++# CONFIG_DDR is not set ++# CONFIG_IRQ_POLL is not set ++CONFIG_LIBFDT=y ++CONFIG_OID_REGISTRY=y ++# CONFIG_SG_SPLIT is not set ++CONFIG_SG_POOL=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3516a_spinand_mini_defconfig b/arch/arm/configs/hi3516a_spinand_mini_defconfig +new file mode 100644 +index 0000000..762167f +--- /dev/null ++++ b/arch/arm/configs/hi3516a_spinand_mini_defconfig +@@ -0,0 +1,2331 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 4.9.37 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_GENERIC_BUG=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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++CONFIG_FHANDLE=y ++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_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=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=17 ++CONFIG_NMI_LOG_BUF_SHIFT=13 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_MEMCG is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CGROUP_SCHED is not set ++# CONFIG_CGROUP_PIDS is not set ++CONFIG_CGROUP_FREEZER=y ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++CONFIG_RD_LZ4=y ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++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_ALL is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_PRINTK_NMI=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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=y ++CONFIG_SLUB_DEBUG=y ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# 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 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_ARCH_HAS_GCOV_PROFILE_ALL=y ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# 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_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 ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_ARTPEC is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_DIGICOLOR is not set ++# CONFIG_ARCH_HIGHBANK is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++ ++# ++# Hisilicon BVT platform type ++# ++CONFIG_ARCH_HI3516A=y ++# CONFIG_ARCH_HI3536DV100 is not set ++# CONFIG_ARCH_HI3521A is not set ++# CONFIG_ARCH_HI3531A is not set ++CONFIG_HI_ZRELADDR=0x80008000 ++CONFIG_HI_PARAMS_PHYS=0x00000100 ++CONFIG_HI_INITRD_PHYS=0x00800000 ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TANGO is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQ is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++# CONFIG_SWP_EMULATE is not set ++# 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_VDSO=y ++CONFIG_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++# CONFIG_DEBUG_RODATA is not set ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++# CONFIG_ARM_ERRATA_818325_852422 is not set ++# CONFIG_ARM_ERRATA_821420 is not set ++# CONFIG_ARM_ERRATA_825619 is not set ++# CONFIG_ARM_ERRATA_852421 is not set ++# CONFIG_ARM_ERRATA_852423 is not set ++ ++# ++# Bus support ++# ++# CONFIG_PCI is not set ++# CONFIG_PCI_DOMAINS_GENERIC is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++# CONFIG_SMP is not set ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++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_ARM_PSCI is not set ++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_THUMB2_KERNEL is not set ++CONFIG_ARM_PATCH_IDIV=y ++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 is not set ++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_FRONTSWAP 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 ++# CONFIG_XEN 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# 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=y ++CONFIG_CPU_FREQ_GOV_ATTR_SET=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++ ++# ++# CPU frequency scaling drivers ++# ++CONFIG_CPUFREQ_DT=y ++CONFIG_CPUFREQ_DT_PLATDEV=y ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++# CONFIG_QORIQ_CPUFREQ 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++# CONFIG_KERNEL_MODE_NEON is not set ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=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=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HIBERNATION=y ++CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++CONFIG_PM_DEBUG=y ++# CONFIG_PM_ADVANCED_DEBUG is not set ++CONFIG_PM_SLEEP_DEBUG=y ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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_ALGO=y ++CONFIG_XFRM_USER=y ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++CONFIG_NET_KEY=y ++# CONFIG_NET_KEY_MIGRATE is not set ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++# CONFIG_IP_FIB_TRIE_STATS is not set ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++# CONFIG_IP_PNP_DHCP is not set ++# 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 is not set ++CONFIG_IP_MROUTE=y ++# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_SYN_COOKIES=y ++# CONFIG_NET_UDP_TUNNEL is not set ++# CONFIG_NET_FOU 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 is not set ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++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=y ++CONFIG_TCP_CONG_BIC=m ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_TCP_CONG_WESTWOOD=m ++CONFIG_TCP_CONG_HTCP=m ++# CONFIG_TCP_CONG_HSTCP is not set ++# CONFIG_TCP_CONG_HYBLA is not set ++# CONFIG_TCP_CONG_VEGAS is not set ++# CONFIG_TCP_CONG_NV is not set ++# CONFIG_TCP_CONG_SCALABLE is not set ++# CONFIG_TCP_CONG_LP is not set ++# CONFIG_TCP_CONG_VENO is not set ++# CONFIG_TCP_CONG_YEAH is not set ++# CONFIG_TCP_CONG_ILLINOIS is not set ++# CONFIG_TCP_CONG_DCTCP is not set ++# CONFIG_TCP_CONG_CDG is not set ++# CONFIG_TCP_CONG_BBR is not set ++CONFIG_DEFAULT_CUBIC=y ++# CONFIG_DEFAULT_RENO is not set ++CONFIG_DEFAULT_TCP_CONG="cubic" ++CONFIG_TCP_MD5SIG=y ++# CONFIG_IPV6 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_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_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_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_FIB_RULES=y ++# CONFIG_WIRELESS is not set ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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 is not set ++# CONFIG_NET_DEVLINK is not set ++CONFIG_MAY_USE_DEVLINK=y ++CONFIG_HAVE_CBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# 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_SWAP 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 is not set ++# 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_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++CONFIG_MTD_SPI_NAND_HISI_BVT=y ++CONFIG_MTD_NAND_HISNFC100=y ++CONFIG_HISNFC100_MAX_CHIP=1 ++CONFIG_HISNFC100_HARDWARE_PAGESIZE_ECC=y ++# CONFIG_HISNFC100_AUTO_PAGESIZE_ECC is not set ++# CONFIG_HISNFC100_PAGESIZE_AUTO_ECC_NONE 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 is not set ++# CONFIG_SPI_CADENCE_QUADSPI is not set ++# CONFIG_SPI_HISI_SFC is not set ++CONFIG_MTD_SPI_IDS=y ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_MTD_HISFC350=y ++CONFIG_HISFC350_SYSCTRL_ADDRESS=0x20030000 ++CONFIG_HISFC350_CHIP_NUM=2 ++# CONFIG_HISFC350_SHOW_CYCLE_TIMING is not set ++# CONFIG_HISFC350_ENABLE_CHIPSELECT_0 is not set ++CONFIG_HISFC350_ENABLE_CHIPSELECT_1=y ++# CONFIG_HISFC350_ENABLE_INTR_DMA is not set ++CONFIG_CMD_SPI_BLOCK_PROTECTION=y ++# 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=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# 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_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_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=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++CONFIG_HIETH_GMAC=y ++# CONFIG_HIGMAC_DESC_4WORD is not set ++# CONFIG_HIGMAC_RXCSUM is not set ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# 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_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_MMIOREG is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++ ++# ++# 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 ++ ++# ++# Host-side USB support is needed for USB Network Adapter support ++# ++# CONFIG_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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_REGULATOR_HAPTIC is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_USERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# 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_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART 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_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=y ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_MUX is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_EMEV2 is not set ++# CONFIG_I2C_HIBVT is not set ++# CONFIG_I2C_NOMADIK 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_PARPORT_LIGHT is not set ++# CONFIG_I2C_TAOS_EVM is not set ++ ++# ++# Other I2C/SMBus bus drivers ++# ++CONFIG_I2C_HISI=y ++# 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_DEBUG is not set ++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_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# 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=y ++# 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 is not set ++# 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++CONFIG_POWER_RESET_SYSCON=y ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_MANAGER is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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_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_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_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_MFD_HISI_FMC is not set ++# CONFIG_HTC_PASIC3 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_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_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=y ++# 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_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_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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_LTC3676 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MT6311 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_PV88060 is not set ++# CONFIG_REGULATOR_PV88080 is not set ++# CONFIG_REGULATOR_PV88090 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++# CONFIG_HID is not set ++ ++# ++# I2C HID support ++# ++# CONFIG_I2C_HID is not set ++CONFIG_USB_OHCI_LITTLE_ENDIAN=y ++# CONFIG_USB_SUPPORT is not set ++# CONFIG_UWB is not set ++# CONFIG_MMC 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 is not set ++# CONFIG_DMADEVICES 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_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++CONFIG_COMMON_CLK_HI3516A=y ++CONFIG_RESET_HISI=y ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++CONFIG_ARM_ARCH_TIMER_VCT_ACCESS=y ++CONFIG_ARM_TIMER_SP804=y ++# 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 is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_ZYNQ is not set ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# 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_PHY_HISI_USB2=y ++# 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 ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# Firmware Drivers ++# ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT2=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_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=y ++CONFIG_EXPORTFS=y ++# 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=y ++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=m ++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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++# 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFS_V4_1 is not set ++CONFIG_ROOT_NFS=y ++# CONFIG_NFS_USE_LEGACY_DNS is not set ++CONFIG_NFS_USE_KERNEL_DNS=y ++# CONFIG_NFSD is not set ++CONFIG_GRACE_PERIOD=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++CONFIG_SUNRPC_GSS=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_WQ_WATCHDOG is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++# CONFIG_SCHED_DEBUG is not set ++# CONFIG_SCHED_INFO is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++CONFIG_DEBUG_MUTEXES=y ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS 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_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set ++# CONFIG_UBSAN is not set ++CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y ++CONFIG_STRICT_DEVMEM=y ++# CONFIG_IO_STRICT_DEVMEM is not set ++# CONFIG_ARM_PTDUMP is not set ++# CONFIG_ARM_UNWIND is not set ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL 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_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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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=m ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++CONFIG_CRYPTO_GF128MUL=m ++CONFIG_CRYPTO_NULL=m ++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=m ++CONFIG_CRYPTO_GCM=m ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# 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=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++CONFIG_CRYPTO_CRCT10DIF=y ++CONFIG_CRYPTO_GHASH=m ++# CONFIG_CRYPTO_POLY1305 is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=y ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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=y ++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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++# CONFIG_CRYPTO_HW 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=y ++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=y ++CONFIG_CRC16=y ++CONFIG_CRC_T10DIF=y ++CONFIG_CRC_ITU_T=y ++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=y ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_LZ4=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_CORDIC is not set ++# CONFIG_DDR is not set ++# CONFIG_IRQ_POLL is not set ++CONFIG_LIBFDT=y ++CONFIG_OID_REGISTRY=y ++# CONFIG_SG_SPLIT is not set ++# CONFIG_SG_POOL is not set ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3516cv200_full_defconfig b/arch/arm/configs/hi3516cv200_full_defconfig +new file mode 100644 +index 0000000..d7846be +--- /dev/null ++++ b/arch/arm/configs/hi3516cv200_full_defconfig +@@ -0,0 +1,2640 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 4.9.37 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_GENERIC_BUG=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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++CONFIG_FHANDLE=y ++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_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=17 ++CONFIG_NMI_LOG_BUF_SHIFT=13 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_MEMCG is not set ++# CONFIG_BLK_CGROUP is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_CGROUP_PIDS is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++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_ALL is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_PRINTK_NMI=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# 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 is not set ++# CONFIG_UPROBES is not set ++# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set ++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_ARCH_HAS_GCOV_PROFILE_ALL=y ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# 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_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 ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V4 is not set ++# CONFIG_ARCH_MULTI_V4T is not set ++CONFIG_ARCH_MULTI_V5=y ++CONFIG_ARCH_MULTI_V4_V5=y ++# CONFIG_ARCH_MULTI_V6 is not set ++# CONFIG_ARCH_MULTI_V7 is not set ++CONFIG_ARCH_MULTI_CPU_AUTO=y ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_MACH_ASM9260 is not set ++# CONFIG_ARCH_AT91 is not set ++CONFIG_ARCH_HISI_BVT=y ++ ++# ++# Hisilicon BVT platform type ++# ++CONFIG_ARCH_HI3518EV20X=y ++CONFIG_HI_ZRELADDR=0x80008000 ++CONFIG_HI_PARAMS_PHYS=0x00000100 ++CONFIG_HI_INITRD_PHYS=0x00800000 ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_ASPEED is not set ++# CONFIG_ARCH_MV78XX0 is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MXS is not set ++# CONFIG_ARCH_NOMADIK is not set ++# CONFIG_ARCH_NSPIRE is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_OXNAS is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_U300 is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_WM8505 is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_ARM926T=y ++CONFIG_CPU_32v5=y ++CONFIG_CPU_ABRT_EV5TJ=y ++CONFIG_CPU_PABRT_LEGACY=y ++CONFIG_CPU_CACHE_VIVT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++CONFIG_CPU_USE_DOMAINS=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_DCACHE_WRITETHROUGH is not set ++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set ++CONFIG_NEED_KUSER_HELPERS=y ++CONFIG_KUSER_HELPERS=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT=5 ++# CONFIG_DEBUG_RODATA is not set ++CONFIG_MULTI_IRQ_HANDLER=y ++ ++# ++# Bus support ++# ++# CONFIG_PCI is not set ++# 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 is not set ++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=999999 ++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_FRONTSWAP 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# 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 is not set ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=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=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_HIBERNATION is not set ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++CONFIG_ARCH_HIBERNATION_POSSIBLE=y ++CONFIG_NET=y ++CONFIG_NET_INGRESS=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 is not set ++# 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=m ++# 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=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=m ++CONFIG_INET_XFRM_MODE_TUNNEL=m ++CONFIG_INET_XFRM_MODE_BEET=m ++CONFIG_INET_DIAG=m ++CONFIG_INET_TCP_DIAG=m ++# 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_IPV6_ILA is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# 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=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++CONFIG_NETFILTER_INGRESS=y ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_DUP_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_DUP_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_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_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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 is not set ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL 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 ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# 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_SWAP 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 is not set ++# 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_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++CONFIG_MTD_SPI_NAND_HISI_BVT=y ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++CONFIG_MTD_SPI_NAND_HIFMC100=y ++# 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 is not set ++# CONFIG_SPI_CADENCE_QUADSPI is not set ++CONFIG_SPI_HISI_SFC=y ++# CONFIG_MTD_SPI_IDS is not set ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK 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=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# 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=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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=y ++# CONFIG_HIX5HD2_GMAC is not set ++CONFIG_HISI_FEMAC=y ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++# CONFIG_HIETH_GMAC 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_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=y ++# CONFIG_MDIO_HISI_GEMAC 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_IPHETH is not set ++# CONFIG_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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++CONFIG_INPUT_JOYSTICK=y ++# CONFIG_JOYSTICK_ANALOG is not set ++# CONFIG_JOYSTICK_A3D is not set ++# CONFIG_JOYSTICK_ADI is not set ++# CONFIG_JOYSTICK_COBRA is not set ++# CONFIG_JOYSTICK_GF2K is not set ++# CONFIG_JOYSTICK_GRIP is not set ++# CONFIG_JOYSTICK_GRIP_MP is not set ++# CONFIG_JOYSTICK_GUILLEMOT is not set ++# CONFIG_JOYSTICK_INTERACT is not set ++# CONFIG_JOYSTICK_SIDEWINDER is not set ++# CONFIG_JOYSTICK_TMDC is not set ++# CONFIG_JOYSTICK_IFORCE is not set ++# CONFIG_JOYSTICK_WARRIOR is not set ++# CONFIG_JOYSTICK_MAGELLAN is not set ++# CONFIG_JOYSTICK_SPACEORB is not set ++# CONFIG_JOYSTICK_SPACEBALL is not set ++# CONFIG_JOYSTICK_STINGER is not set ++# CONFIG_JOYSTICK_TWIDJOY is not set ++# CONFIG_JOYSTICK_ZHENHUA is not set ++# CONFIG_JOYSTICK_AS5011 is not set ++# CONFIG_JOYSTICK_JOYDUMP is not set ++# CONFIG_JOYSTICK_XPAD 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=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_USERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# 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_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_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_HW_RANDOM=y ++# CONFIG_HW_RANDOM_TIMERIOMEM 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=y ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_MUX is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# 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_HIBVT is not set ++# CONFIG_I2C_NOMADIK 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_HISI=y ++# 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_DEBUG is not set ++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_GPIO is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_OC_TINY is not set ++CONFIG_SPI_PL022=y ++# 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=y ++# 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++# CONFIG_PINCTRL_AMD is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++CONFIG_GPIOLIB=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers ++# ++# CONFIG_GPIO_74XX_MMIO is not set ++# CONFIG_GPIO_ALTERA is not set ++# 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_PL061=y ++# CONFIG_GPIO_SYSCON 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++CONFIG_POWER_RESET_SYSCON=y ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_BQ25890 is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_CHARGER_RT9455 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_MFD_HISI_FMC=y ++# 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=y ++# 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 ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++# CONFIG_HID_BETOP_FF is not set ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# 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=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_SISUSBVGA 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 ++# CONFIG_USB_CHAOSKEY 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_BDC_UDC is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_MASS_STORAGE=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP 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_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# CONFIG_MMC_SPI is not set ++# 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_HIMCI=y ++CONFIG_SEND_AUTO_STOP=y ++# 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 is not set ++# CONFIG_DMADEVICES 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_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++CONFIG_COMMON_CLK_HI3518EV20X=y ++CONFIG_RESET_HISI=y ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_TIMER_SP804=y ++# 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 is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC_MAX_NR=1 ++CONFIG_ARM_VIC=y ++CONFIG_ARM_VIC_NR=2 ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_ZYNQ is not set ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# 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_PHY_HISI_USB2=y ++# 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 ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# Firmware Drivers ++# ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++ ++# ++# File systems ++# ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT2=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_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=y ++CONFIG_EXPORTFS=y ++# CONFIG_EXPORTFS_BLOCK_OPS is not set ++CONFIG_FILE_LOCKING=y ++# CONFIG_MANDATORY_FILE_LOCKING is not set ++# 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=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ORANGEFS_FS is not set ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_UBIFS_ATIME_SUPPORT 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++# CONFIG_DLM is not set ++ ++# ++# Kernel hacking ++# ++ ++# ++# printk and dmesg options ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_WQ_WATCHDOG is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++# CONFIG_SCHED_DEBUG is not set ++# CONFIG_SCHED_INFO is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS 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_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set ++# CONFIG_UBSAN is not set ++CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y ++CONFIG_STRICT_DEVMEM=y ++# CONFIG_IO_STRICT_DEVMEM is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL 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_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS 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_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG2=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 is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++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 is not set ++# CONFIG_CRYPTO_ECHAINIV is not set ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# 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 is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# 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 is not set ++# 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 is not set ++# 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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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 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 ++ ++# ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=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=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3518ev200_full_defconfig b/arch/arm/configs/hi3518ev200_full_defconfig +new file mode 100644 +index 0000000..d7846be +--- /dev/null ++++ b/arch/arm/configs/hi3518ev200_full_defconfig +@@ -0,0 +1,2640 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 4.9.37 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_GENERIC_BUG=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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++CONFIG_FHANDLE=y ++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_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=17 ++CONFIG_NMI_LOG_BUF_SHIFT=13 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_MEMCG is not set ++# CONFIG_BLK_CGROUP is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_CGROUP_PIDS is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++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_ALL is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_PRINTK_NMI=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# 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 is not set ++# CONFIG_UPROBES is not set ++# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set ++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_ARCH_HAS_GCOV_PROFILE_ALL=y ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# 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_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 ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V4 is not set ++# CONFIG_ARCH_MULTI_V4T is not set ++CONFIG_ARCH_MULTI_V5=y ++CONFIG_ARCH_MULTI_V4_V5=y ++# CONFIG_ARCH_MULTI_V6 is not set ++# CONFIG_ARCH_MULTI_V7 is not set ++CONFIG_ARCH_MULTI_CPU_AUTO=y ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_MACH_ASM9260 is not set ++# CONFIG_ARCH_AT91 is not set ++CONFIG_ARCH_HISI_BVT=y ++ ++# ++# Hisilicon BVT platform type ++# ++CONFIG_ARCH_HI3518EV20X=y ++CONFIG_HI_ZRELADDR=0x80008000 ++CONFIG_HI_PARAMS_PHYS=0x00000100 ++CONFIG_HI_INITRD_PHYS=0x00800000 ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_ASPEED is not set ++# CONFIG_ARCH_MV78XX0 is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MXS is not set ++# CONFIG_ARCH_NOMADIK is not set ++# CONFIG_ARCH_NSPIRE is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_OXNAS is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_U300 is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_WM8505 is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_ARM926T=y ++CONFIG_CPU_32v5=y ++CONFIG_CPU_ABRT_EV5TJ=y ++CONFIG_CPU_PABRT_LEGACY=y ++CONFIG_CPU_CACHE_VIVT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++CONFIG_CPU_USE_DOMAINS=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_DCACHE_WRITETHROUGH is not set ++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set ++CONFIG_NEED_KUSER_HELPERS=y ++CONFIG_KUSER_HELPERS=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT=5 ++# CONFIG_DEBUG_RODATA is not set ++CONFIG_MULTI_IRQ_HANDLER=y ++ ++# ++# Bus support ++# ++# CONFIG_PCI is not set ++# 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 is not set ++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=999999 ++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_FRONTSWAP 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# 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 is not set ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=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=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_HIBERNATION is not set ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++CONFIG_ARCH_HIBERNATION_POSSIBLE=y ++CONFIG_NET=y ++CONFIG_NET_INGRESS=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 is not set ++# 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=m ++# 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=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=m ++CONFIG_INET_XFRM_MODE_TUNNEL=m ++CONFIG_INET_XFRM_MODE_BEET=m ++CONFIG_INET_DIAG=m ++CONFIG_INET_TCP_DIAG=m ++# 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_IPV6_ILA is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# 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=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++CONFIG_NETFILTER_INGRESS=y ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_DUP_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_DUP_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_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_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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 is not set ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL 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 ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# 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_SWAP 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 is not set ++# 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_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++CONFIG_MTD_SPI_NAND_HISI_BVT=y ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++CONFIG_MTD_SPI_NAND_HIFMC100=y ++# 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 is not set ++# CONFIG_SPI_CADENCE_QUADSPI is not set ++CONFIG_SPI_HISI_SFC=y ++# CONFIG_MTD_SPI_IDS is not set ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK 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=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# 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=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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=y ++# CONFIG_HIX5HD2_GMAC is not set ++CONFIG_HISI_FEMAC=y ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++# CONFIG_HIETH_GMAC 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_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=y ++# CONFIG_MDIO_HISI_GEMAC 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_IPHETH is not set ++# CONFIG_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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++CONFIG_INPUT_JOYSTICK=y ++# CONFIG_JOYSTICK_ANALOG is not set ++# CONFIG_JOYSTICK_A3D is not set ++# CONFIG_JOYSTICK_ADI is not set ++# CONFIG_JOYSTICK_COBRA is not set ++# CONFIG_JOYSTICK_GF2K is not set ++# CONFIG_JOYSTICK_GRIP is not set ++# CONFIG_JOYSTICK_GRIP_MP is not set ++# CONFIG_JOYSTICK_GUILLEMOT is not set ++# CONFIG_JOYSTICK_INTERACT is not set ++# CONFIG_JOYSTICK_SIDEWINDER is not set ++# CONFIG_JOYSTICK_TMDC is not set ++# CONFIG_JOYSTICK_IFORCE is not set ++# CONFIG_JOYSTICK_WARRIOR is not set ++# CONFIG_JOYSTICK_MAGELLAN is not set ++# CONFIG_JOYSTICK_SPACEORB is not set ++# CONFIG_JOYSTICK_SPACEBALL is not set ++# CONFIG_JOYSTICK_STINGER is not set ++# CONFIG_JOYSTICK_TWIDJOY is not set ++# CONFIG_JOYSTICK_ZHENHUA is not set ++# CONFIG_JOYSTICK_AS5011 is not set ++# CONFIG_JOYSTICK_JOYDUMP is not set ++# CONFIG_JOYSTICK_XPAD 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=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_USERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# 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_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_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_HW_RANDOM=y ++# CONFIG_HW_RANDOM_TIMERIOMEM 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=y ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_MUX is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# 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_HIBVT is not set ++# CONFIG_I2C_NOMADIK 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_HISI=y ++# 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_DEBUG is not set ++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_GPIO is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_OC_TINY is not set ++CONFIG_SPI_PL022=y ++# 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=y ++# 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++# CONFIG_PINCTRL_AMD is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++CONFIG_GPIOLIB=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers ++# ++# CONFIG_GPIO_74XX_MMIO is not set ++# CONFIG_GPIO_ALTERA is not set ++# 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_PL061=y ++# CONFIG_GPIO_SYSCON 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++CONFIG_POWER_RESET_SYSCON=y ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_BQ25890 is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_CHARGER_RT9455 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_MFD_HISI_FMC=y ++# 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=y ++# 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 ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++# CONFIG_HID_BETOP_FF is not set ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# 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=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_SISUSBVGA 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 ++# CONFIG_USB_CHAOSKEY 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_BDC_UDC is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_MASS_STORAGE=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP 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_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# CONFIG_MMC_SPI is not set ++# 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_HIMCI=y ++CONFIG_SEND_AUTO_STOP=y ++# 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 is not set ++# CONFIG_DMADEVICES 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_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++CONFIG_COMMON_CLK_HI3518EV20X=y ++CONFIG_RESET_HISI=y ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_TIMER_SP804=y ++# 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 is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC_MAX_NR=1 ++CONFIG_ARM_VIC=y ++CONFIG_ARM_VIC_NR=2 ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_ZYNQ is not set ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# 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_PHY_HISI_USB2=y ++# 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 ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# Firmware Drivers ++# ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++ ++# ++# File systems ++# ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT2=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_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=y ++CONFIG_EXPORTFS=y ++# CONFIG_EXPORTFS_BLOCK_OPS is not set ++CONFIG_FILE_LOCKING=y ++# CONFIG_MANDATORY_FILE_LOCKING is not set ++# 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=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ORANGEFS_FS is not set ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_UBIFS_ATIME_SUPPORT 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++# CONFIG_DLM is not set ++ ++# ++# Kernel hacking ++# ++ ++# ++# printk and dmesg options ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_WQ_WATCHDOG is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++# CONFIG_SCHED_DEBUG is not set ++# CONFIG_SCHED_INFO is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS 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_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set ++# CONFIG_UBSAN is not set ++CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y ++CONFIG_STRICT_DEVMEM=y ++# CONFIG_IO_STRICT_DEVMEM is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL 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_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS 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_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG2=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 is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++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 is not set ++# CONFIG_CRYPTO_ECHAINIV is not set ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# 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 is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# 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 is not set ++# 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 is not set ++# 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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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 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 ++ ++# ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=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=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3518ev201_full_defconfig b/arch/arm/configs/hi3518ev201_full_defconfig +new file mode 100644 +index 0000000..ba46b5b +--- /dev/null ++++ b/arch/arm/configs/hi3518ev201_full_defconfig +@@ -0,0 +1,2318 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 4.9.37 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_GENERIC_BUG=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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++CONFIG_FHANDLE=y ++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_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=17 ++CONFIG_NMI_LOG_BUF_SHIFT=13 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_MEMCG is not set ++# CONFIG_BLK_CGROUP is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_CGROUP_PIDS is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++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_ALL is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_PRINTK_NMI=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# 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 is not set ++# CONFIG_UPROBES is not set ++# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set ++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_ARCH_HAS_GCOV_PROFILE_ALL=y ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# 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_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 ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V4 is not set ++# CONFIG_ARCH_MULTI_V4T is not set ++CONFIG_ARCH_MULTI_V5=y ++CONFIG_ARCH_MULTI_V4_V5=y ++# CONFIG_ARCH_MULTI_V6 is not set ++# CONFIG_ARCH_MULTI_V7 is not set ++CONFIG_ARCH_MULTI_CPU_AUTO=y ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_MACH_ASM9260 is not set ++# CONFIG_ARCH_AT91 is not set ++CONFIG_ARCH_HISI_BVT=y ++ ++# ++# Hisilicon BVT platform type ++# ++CONFIG_ARCH_HI3518EV20X=y ++CONFIG_HI_ZRELADDR=0x80008000 ++CONFIG_HI_PARAMS_PHYS=0x00000100 ++CONFIG_HI_INITRD_PHYS=0x00800000 ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_ASPEED is not set ++# CONFIG_ARCH_MV78XX0 is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MXS is not set ++# CONFIG_ARCH_NOMADIK is not set ++# CONFIG_ARCH_NSPIRE is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_OXNAS is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_U300 is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_WM8505 is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_ARM926T=y ++CONFIG_CPU_32v5=y ++CONFIG_CPU_ABRT_EV5TJ=y ++CONFIG_CPU_PABRT_LEGACY=y ++CONFIG_CPU_CACHE_VIVT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++CONFIG_CPU_USE_DOMAINS=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++# CONFIG_ARM_THUMB is not set ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set ++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set ++CONFIG_NEED_KUSER_HELPERS=y ++CONFIG_KUSER_HELPERS=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT=5 ++# CONFIG_DEBUG_RODATA is not set ++CONFIG_MULTI_IRQ_HANDLER=y ++ ++# ++# Bus support ++# ++# CONFIG_PCI is not set ++# 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 is not set ++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=999999 ++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_FRONTSWAP 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# 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 is not set ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=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=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_HIBERNATION is not set ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++CONFIG_ARCH_HIBERNATION_POSSIBLE=y ++CONFIG_NET=y ++CONFIG_NET_INGRESS=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 is not set ++# 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=m ++# 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=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=m ++CONFIG_INET_XFRM_MODE_TUNNEL=m ++CONFIG_INET_XFRM_MODE_BEET=m ++CONFIG_INET_DIAG=m ++CONFIG_INET_TCP_DIAG=m ++# 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_IPV6_ILA is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# 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=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++CONFIG_NETFILTER_INGRESS=y ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_DUP_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_DUP_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_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_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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 is not set ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL 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 ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# 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_SWAP 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 is not set ++# 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 is not set ++# CONFIG_SPI_CADENCE_QUADSPI is not set ++CONFIG_SPI_HISI_SFC=y ++# CONFIG_MTD_SPI_IDS is not set ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++# 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=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# 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=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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=y ++# CONFIG_HIX5HD2_GMAC is not set ++CONFIG_HISI_FEMAC=y ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++# CONFIG_HIETH_GMAC 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_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=y ++# CONFIG_MDIO_HISI_GEMAC 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 ++ ++# ++# Host-side USB support is needed for USB Network Adapter support ++# ++# CONFIG_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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++CONFIG_INPUT_JOYSTICK=y ++# CONFIG_JOYSTICK_ANALOG is not set ++# CONFIG_JOYSTICK_A3D is not set ++# CONFIG_JOYSTICK_ADI is not set ++# CONFIG_JOYSTICK_COBRA is not set ++# CONFIG_JOYSTICK_GF2K is not set ++# CONFIG_JOYSTICK_GRIP is not set ++# CONFIG_JOYSTICK_GRIP_MP is not set ++# CONFIG_JOYSTICK_GUILLEMOT is not set ++# CONFIG_JOYSTICK_INTERACT is not set ++# CONFIG_JOYSTICK_SIDEWINDER is not set ++# CONFIG_JOYSTICK_TMDC is not set ++# CONFIG_JOYSTICK_IFORCE is not set ++# CONFIG_JOYSTICK_WARRIOR is not set ++# CONFIG_JOYSTICK_MAGELLAN is not set ++# CONFIG_JOYSTICK_SPACEORB is not set ++# CONFIG_JOYSTICK_SPACEBALL is not set ++# CONFIG_JOYSTICK_STINGER is not set ++# CONFIG_JOYSTICK_TWIDJOY is not set ++# CONFIG_JOYSTICK_ZHENHUA is not set ++# CONFIG_JOYSTICK_AS5011 is not set ++# CONFIG_JOYSTICK_JOYDUMP 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=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_USERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# 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_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_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_HW_RANDOM=y ++# CONFIG_HW_RANDOM_TIMERIOMEM 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=y ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_MUX is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# 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_HIBVT is not set ++# CONFIG_I2C_NOMADIK 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_PARPORT_LIGHT is not set ++# CONFIG_I2C_TAOS_EVM is not set ++ ++# ++# Other I2C/SMBus bus drivers ++# ++CONFIG_I2C_HISI=y ++# 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_DEBUG is not set ++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_GPIO is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_OC_TINY is not set ++CONFIG_SPI_PL022=y ++# 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=y ++# 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++# CONFIG_PINCTRL_AMD is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++CONFIG_GPIOLIB=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers ++# ++# CONFIG_GPIO_74XX_MMIO is not set ++# CONFIG_GPIO_ALTERA is not set ++# 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_PL061=y ++# CONFIG_GPIO_SYSCON 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 ++# 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++CONFIG_POWER_RESET_SYSCON=y ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_BQ25890 is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_CHARGER_RT9455 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_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_MFD_HISI_FMC=y ++# 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_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_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=y ++# 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 ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++# CONFIG_HID is not set ++ ++# ++# I2C HID support ++# ++# CONFIG_I2C_HID is not set ++CONFIG_USB_OHCI_LITTLE_ENDIAN=y ++# CONFIG_USB_SUPPORT is not set ++# CONFIG_UWB is not set ++# CONFIG_MMC 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 is not set ++# CONFIG_DMADEVICES 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_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++CONFIG_COMMON_CLK_HI3518EV20X=y ++CONFIG_RESET_HISI=y ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_TIMER_SP804=y ++# 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 is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC_MAX_NR=1 ++CONFIG_ARM_VIC=y ++CONFIG_ARM_VIC_NR=2 ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_ZYNQ is not set ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# 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_PHY_HISI_USB2=y ++# 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 ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# Firmware Drivers ++# ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++ ++# ++# File systems ++# ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT2=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++CONFIG_GFS2_FS=y ++# 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=y ++CONFIG_EXPORTFS=y ++# CONFIG_EXPORTFS_BLOCK_OPS is not set ++CONFIG_FILE_LOCKING=y ++# CONFIG_MANDATORY_FILE_LOCKING is not set ++# 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_QUOTA_NETLINK_INTERFACE=y ++CONFIG_QUOTACTL=y ++# 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=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ORANGEFS_FS is not set ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++# CONFIG_DLM is not set ++ ++# ++# Kernel hacking ++# ++ ++# ++# printk and dmesg options ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_WQ_WATCHDOG is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++# CONFIG_SCHED_DEBUG is not set ++# CONFIG_SCHED_INFO is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS 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_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set ++# CONFIG_UBSAN is not set ++CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y ++CONFIG_STRICT_DEVMEM=y ++# CONFIG_IO_STRICT_DEVMEM is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL 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_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS 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_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG2=y ++# CONFIG_CRYPTO_RSA is not set ++# CONFIG_CRYPTO_DH is not set ++# CONFIG_CRYPTO_ECDH is not set ++# CONFIG_CRYPTO_MANAGER is not set ++# CONFIG_CRYPTO_MANAGER2 is not set ++# CONFIG_CRYPTO_USER is not set ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++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 is not set ++# CONFIG_CRYPTO_ECHAINIV is not set ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# 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 is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# 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 is not set ++# 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 is not set ++# 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 is not set ++# 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 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 ++ ++# ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=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=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3520dv300_full_defconfig b/arch/arm/configs/hi3520dv300_full_defconfig +new file mode 100644 +index 0000000..82637a8 +--- /dev/null ++++ b/arch/arm/configs/hi3520dv300_full_defconfig +@@ -0,0 +1,2611 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 4.9.37 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_GENERIC_BUG=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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++CONFIG_FHANDLE=y ++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_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=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=17 ++CONFIG_NMI_LOG_BUF_SHIFT=13 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_MEMCG is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CGROUP_SCHED is not set ++# CONFIG_CGROUP_PIDS is not set ++CONFIG_CGROUP_FREEZER=y ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++CONFIG_RD_LZ4=y ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++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_ALL is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_PRINTK_NMI=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# 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 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_ARCH_HAS_GCOV_PROFILE_ALL=y ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# 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_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 ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_ARTPEC is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_DIGICOLOR is not set ++# CONFIG_ARCH_HIGHBANK is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++ ++# ++# Hisilicon BVT platform type ++# ++# CONFIG_ARCH_HI3516A is not set ++# CONFIG_ARCH_HI3536DV100 is not set ++CONFIG_ARCH_HI3521A=y ++# CONFIG_ARCH_HI3531A is not set ++CONFIG_HI_ZRELADDR=0x80008000 ++CONFIG_HI_PARAMS_PHYS=0x00000100 ++CONFIG_HI_INITRD_PHYS=0x00800000 ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TANGO is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQ is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++# CONFIG_SWP_EMULATE is not set ++# 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_VDSO=y ++CONFIG_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++# CONFIG_DEBUG_RODATA is not set ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++# CONFIG_ARM_ERRATA_818325_852422 is not set ++# CONFIG_ARM_ERRATA_821420 is not set ++# CONFIG_ARM_ERRATA_825619 is not set ++# CONFIG_ARM_ERRATA_852421 is not set ++# CONFIG_ARM_ERRATA_852423 is not set ++ ++# ++# Bus support ++# ++# CONFIG_PCI is not set ++# CONFIG_PCI_DOMAINS_GENERIC is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++# CONFIG_SMP is not set ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++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_ARM_PSCI is not set ++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_THUMB2_KERNEL is not set ++CONFIG_ARM_PATCH_IDIV=y ++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 is not set ++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_FRONTSWAP 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 ++# CONFIG_XEN 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# 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=y ++CONFIG_CPU_FREQ_GOV_ATTR_SET=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++ ++# ++# CPU frequency scaling drivers ++# ++CONFIG_CPUFREQ_DT=y ++CONFIG_CPUFREQ_DT_PLATDEV=y ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++# CONFIG_QORIQ_CPUFREQ 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++# CONFIG_KERNEL_MODE_NEON is not set ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=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=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_HIBERNATION is not set ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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_ALGO=y ++CONFIG_XFRM_USER=y ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++CONFIG_NET_KEY=y ++# CONFIG_NET_KEY_MIGRATE is not set ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++# CONFIG_IP_FIB_TRIE_STATS is not set ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++# CONFIG_IP_PNP_DHCP is not set ++# 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 is not set ++CONFIG_IP_MROUTE=y ++# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_SYN_COOKIES=y ++# CONFIG_NET_UDP_TUNNEL is not set ++# CONFIG_NET_FOU 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 is not set ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++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=y ++CONFIG_TCP_CONG_BIC=m ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_TCP_CONG_WESTWOOD=m ++CONFIG_TCP_CONG_HTCP=m ++# CONFIG_TCP_CONG_HSTCP is not set ++# CONFIG_TCP_CONG_HYBLA is not set ++# CONFIG_TCP_CONG_VEGAS is not set ++# CONFIG_TCP_CONG_NV is not set ++# CONFIG_TCP_CONG_SCALABLE is not set ++# CONFIG_TCP_CONG_LP is not set ++# CONFIG_TCP_CONG_VENO is not set ++# CONFIG_TCP_CONG_YEAH is not set ++# CONFIG_TCP_CONG_ILLINOIS is not set ++# CONFIG_TCP_CONG_DCTCP is not set ++# CONFIG_TCP_CONG_CDG is not set ++# CONFIG_TCP_CONG_BBR is not set ++CONFIG_DEFAULT_CUBIC=y ++# CONFIG_DEFAULT_RENO is not set ++CONFIG_DEFAULT_TCP_CONG="cubic" ++CONFIG_TCP_MD5SIG=y ++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 is not set ++# 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_VLAN_8021Q=y ++# CONFIG_VLAN_8021Q_GVRP is not set ++# CONFIG_VLAN_8021Q_MVRP 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_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_FIB_RULES=y ++CONFIG_WIRELESS=y ++CONFIG_WEXT_CORE=y ++CONFIG_WEXT_PROC=y ++CONFIG_CFG80211=m ++# CONFIG_NL80211_TESTMODE is not set ++# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set ++CONFIG_CFG80211_DEFAULT_PS=y ++# CONFIG_CFG80211_INTERNAL_REGDB is not set ++CONFIG_CFG80211_CRDA_SUPPORT=y ++CONFIG_CFG80211_WEXT=y ++# CONFIG_LIB80211 is not set ++CONFIG_MAC80211=m ++CONFIG_MAC80211_HAS_RC=y ++CONFIG_MAC80211_RC_MINSTREL=y ++CONFIG_MAC80211_RC_MINSTREL_HT=y ++# CONFIG_MAC80211_RC_MINSTREL_VHT is not set ++CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y ++CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" ++CONFIG_MAC80211_MESH=y ++# CONFIG_MAC80211_MESSAGE_TRACING is not set ++# CONFIG_MAC80211_DEBUG_MENU is not set ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL 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 is not set ++# CONFIG_NET_DEVLINK is not set ++CONFIG_MAY_USE_DEVLINK=y ++CONFIG_HAVE_CBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# 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_SWAP 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 is not set ++# 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_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++CONFIG_MTD_SPI_NAND_HISI_BVT=y ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++CONFIG_MTD_SPI_NAND_HIFMC100=y ++# 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 is not set ++# CONFIG_SPI_CADENCE_QUADSPI is not set ++CONFIG_SPI_HISI_SFC=y ++# CONFIG_MTD_SPI_IDS is not set ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK 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=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# 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_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=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HISI_SATA=y ++CONFIG_HISI_SATA_IOBASE=0x11010000 ++CONFIG_HISI_SATA_FBS=1 ++CONFIG_HISI_SATA_NCQ=1 ++# CONFIG_HISI_ESATA is not set ++CONFIG_ATA=y ++# CONFIG_ATA_NONSTANDARD is not set ++CONFIG_ATA_VERBOSE_ERROR=y ++CONFIG_SATA_PMP=y ++ ++# ++# Controllers with non-SFF native interface ++# ++CONFIG_SATA_AHCI_PLATFORM=y ++# CONFIG_AHCI_CEVA is not set ++# CONFIG_AHCI_QORIQ is not set ++# CONFIG_ATA_SFF is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# 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=y ++# CONFIG_ENC28J60 is not set ++# CONFIG_ENCX24J600 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_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_MMIOREG is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++ ++# ++# 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_IPHETH is not set ++# CONFIG_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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INPUT_CM109 is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_USERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# 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_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART 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_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=y ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_MUX is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_EMEV2 is not set ++# CONFIG_I2C_HIBVT is not set ++# CONFIG_I2C_NOMADIK 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_HISI=y ++# 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_DEBUG is not set ++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_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# 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=y ++# 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++# CONFIG_GPIOLIB is not set ++# 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++CONFIG_POWER_RESET_SYSCON=y ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_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_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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 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=y ++# 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_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_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 ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++# CONFIG_HID_A4TECH is not set ++# CONFIG_HID_ACRUX is not set ++# CONFIG_HID_APPLE is not set ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++# CONFIG_HID_BELKIN is not set ++# CONFIG_HID_BETOP_FF is not set ++# CONFIG_HID_CHERRY is not set ++# CONFIG_HID_CHICONY is not set ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CYPRESS is not set ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++# CONFIG_HID_EZKEY is not set ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++# CONFIG_HID_KENSINGTON is not set ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++# CONFIG_HID_LOGITECH is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++# CONFIG_HID_MONTEREY is not set ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_SISUSBVGA 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_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 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 is not set ++# CONFIG_DMADEVICES 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_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++CONFIG_COMMON_CLK_HI3521A=y ++CONFIG_RESET_HISI=y ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++CONFIG_ARM_ARCH_TIMER_VCT_ACCESS=y ++CONFIG_ARM_TIMER_SP804=y ++# 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 is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_ZYNQ is not set ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# 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_PHY_HISI_SATA=y ++CONFIG_HISI_SATA_MODE=1 ++CONFIG_PHY_HISI_USB2=y ++# 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 ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# Firmware Drivers ++# ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT2=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_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=y ++# 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=y ++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=m ++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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_UBIFS_ATIME_SUPPORT is not set ++# CONFIG_LOGFS is not set ++CONFIG_CRAMFS=y ++# 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=y ++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=y ++# 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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_WQ_WATCHDOG is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++# CONFIG_SCHED_DEBUG is not set ++# CONFIG_SCHED_INFO is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++CONFIG_DEBUG_MUTEXES=y ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS 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_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set ++# CONFIG_UBSAN is not set ++CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y ++CONFIG_STRICT_DEVMEM=y ++# CONFIG_IO_STRICT_DEVMEM is not set ++# CONFIG_ARM_PTDUMP is not set ++# CONFIG_ARM_UNWIND is not set ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL 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_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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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=m ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++CONFIG_CRYPTO_GF128MUL=m ++CONFIG_CRYPTO_NULL=m ++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=m ++CONFIG_CRYPTO_GCM=m ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# 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=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++CONFIG_CRYPTO_CRCT10DIF=y ++CONFIG_CRYPTO_GHASH=m ++# CONFIG_CRYPTO_POLY1305 is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=y ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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=y ++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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++# CONFIG_CRYPTO_HW 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=y ++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=y ++CONFIG_CRC16=y ++CONFIG_CRC_T10DIF=y ++CONFIG_CRC_ITU_T=y ++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=y ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_LZ4=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_GLOB=y ++# CONFIG_GLOB_SELFTEST is not set ++CONFIG_NLATTR=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=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3521a_full_defconfig b/arch/arm/configs/hi3521a_full_defconfig +new file mode 100644 +index 0000000..5336879 +--- /dev/null ++++ b/arch/arm/configs/hi3521a_full_defconfig +@@ -0,0 +1,2612 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 4.9.37 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_GENERIC_BUG=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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++CONFIG_FHANDLE=y ++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_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=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=17 ++CONFIG_NMI_LOG_BUF_SHIFT=13 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_MEMCG is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CGROUP_SCHED is not set ++# CONFIG_CGROUP_PIDS is not set ++CONFIG_CGROUP_FREEZER=y ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++CONFIG_RD_LZ4=y ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++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_ALL is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_PRINTK_NMI=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# 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 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_ARCH_HAS_GCOV_PROFILE_ALL=y ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# 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_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 ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_ARTPEC is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_DIGICOLOR is not set ++# CONFIG_ARCH_HIGHBANK is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++ ++# ++# Hisilicon BVT platform type ++# ++# CONFIG_ARCH_HI3516A is not set ++# CONFIG_ARCH_HI3536DV100 is not set ++CONFIG_ARCH_HI3521A=y ++# CONFIG_ARCH_HI3531A is not set ++CONFIG_HI_ZRELADDR=0x80008000 ++CONFIG_HI_PARAMS_PHYS=0x00000100 ++CONFIG_HI_INITRD_PHYS=0x00800000 ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TANGO is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQ is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++# CONFIG_SWP_EMULATE is not set ++# 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_VDSO=y ++CONFIG_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++# CONFIG_DEBUG_RODATA is not set ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++# CONFIG_ARM_ERRATA_818325_852422 is not set ++# CONFIG_ARM_ERRATA_821420 is not set ++# CONFIG_ARM_ERRATA_825619 is not set ++# CONFIG_ARM_ERRATA_852421 is not set ++# CONFIG_ARM_ERRATA_852423 is not set ++ ++# ++# Bus support ++# ++# CONFIG_PCI is not set ++# CONFIG_PCI_DOMAINS_GENERIC is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++# CONFIG_SMP is not set ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++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_ARM_PSCI is not set ++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_THUMB2_KERNEL is not set ++CONFIG_ARM_PATCH_IDIV=y ++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 is not set ++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_FRONTSWAP 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 ++# CONFIG_XEN 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# 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=y ++CONFIG_CPU_FREQ_GOV_ATTR_SET=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++ ++# ++# CPU frequency scaling drivers ++# ++CONFIG_CPUFREQ_DT=y ++CONFIG_CPUFREQ_DT_PLATDEV=y ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++# CONFIG_QORIQ_CPUFREQ 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++# CONFIG_KERNEL_MODE_NEON is not set ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=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=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_HIBERNATION is not set ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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_ALGO=y ++CONFIG_XFRM_USER=y ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++CONFIG_NET_KEY=y ++# CONFIG_NET_KEY_MIGRATE is not set ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++# CONFIG_IP_FIB_TRIE_STATS is not set ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++# CONFIG_IP_PNP_DHCP is not set ++# 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 is not set ++CONFIG_IP_MROUTE=y ++# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_SYN_COOKIES=y ++# CONFIG_NET_UDP_TUNNEL is not set ++# CONFIG_NET_FOU 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 is not set ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++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=y ++CONFIG_TCP_CONG_BIC=m ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_TCP_CONG_WESTWOOD=m ++CONFIG_TCP_CONG_HTCP=m ++# CONFIG_TCP_CONG_HSTCP is not set ++# CONFIG_TCP_CONG_HYBLA is not set ++# CONFIG_TCP_CONG_VEGAS is not set ++# CONFIG_TCP_CONG_NV is not set ++# CONFIG_TCP_CONG_SCALABLE is not set ++# CONFIG_TCP_CONG_LP is not set ++# CONFIG_TCP_CONG_VENO is not set ++# CONFIG_TCP_CONG_YEAH is not set ++# CONFIG_TCP_CONG_ILLINOIS is not set ++# CONFIG_TCP_CONG_DCTCP is not set ++# CONFIG_TCP_CONG_CDG is not set ++# CONFIG_TCP_CONG_BBR is not set ++CONFIG_DEFAULT_CUBIC=y ++# CONFIG_DEFAULT_RENO is not set ++CONFIG_DEFAULT_TCP_CONG="cubic" ++CONFIG_TCP_MD5SIG=y ++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 is not set ++# 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_VLAN_8021Q=y ++# CONFIG_VLAN_8021Q_GVRP is not set ++# CONFIG_VLAN_8021Q_MVRP 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_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_FIB_RULES=y ++CONFIG_WIRELESS=y ++CONFIG_WEXT_CORE=y ++CONFIG_WEXT_PROC=y ++CONFIG_CFG80211=m ++# CONFIG_NL80211_TESTMODE is not set ++# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set ++CONFIG_CFG80211_DEFAULT_PS=y ++# CONFIG_CFG80211_INTERNAL_REGDB is not set ++CONFIG_CFG80211_CRDA_SUPPORT=y ++CONFIG_CFG80211_WEXT=y ++# CONFIG_LIB80211 is not set ++CONFIG_MAC80211=m ++CONFIG_MAC80211_HAS_RC=y ++CONFIG_MAC80211_RC_MINSTREL=y ++CONFIG_MAC80211_RC_MINSTREL_HT=y ++# CONFIG_MAC80211_RC_MINSTREL_VHT is not set ++CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y ++CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" ++CONFIG_MAC80211_MESH=y ++# CONFIG_MAC80211_MESSAGE_TRACING is not set ++# CONFIG_MAC80211_DEBUG_MENU is not set ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL 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 is not set ++# CONFIG_NET_DEVLINK is not set ++CONFIG_MAY_USE_DEVLINK=y ++CONFIG_HAVE_CBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# 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_SWAP 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 is not set ++# 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_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++CONFIG_MTD_SPI_NAND_HISI_BVT=y ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++CONFIG_MTD_SPI_NAND_HIFMC100=y ++# 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 is not set ++# CONFIG_SPI_CADENCE_QUADSPI is not set ++CONFIG_SPI_HISI_SFC=y ++# CONFIG_MTD_SPI_IDS is not set ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK 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=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# 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_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=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HISI_SATA=y ++CONFIG_HISI_SATA_IOBASE=0x11010000 ++CONFIG_HISI_SATA_FBS=1 ++CONFIG_HISI_SATA_NCQ=1 ++# CONFIG_HISI_ESATA is not set ++CONFIG_ATA=y ++# CONFIG_ATA_NONSTANDARD is not set ++CONFIG_ATA_VERBOSE_ERROR=y ++CONFIG_SATA_PMP=y ++ ++# ++# Controllers with non-SFF native interface ++# ++CONFIG_SATA_AHCI_PLATFORM=y ++# CONFIG_AHCI_CEVA is not set ++# CONFIG_AHCI_QORIQ is not set ++# CONFIG_ATA_SFF is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# 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=y ++# CONFIG_ENC28J60 is not set ++# CONFIG_ENCX24J600 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_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_MMIOREG is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++ ++# ++# 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_IPHETH is not set ++# CONFIG_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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INPUT_CM109 is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_USERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# 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_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART 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_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=y ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_MUX is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_EMEV2 is not set ++# CONFIG_I2C_HIBVT is not set ++# CONFIG_I2C_NOMADIK 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_HISI=y ++# 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_DEBUG is not set ++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_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# 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=y ++# 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++# CONFIG_GPIOLIB is not set ++# 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++CONFIG_POWER_RESET_SYSCON=y ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_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_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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 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=y ++# 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_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_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 ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++# CONFIG_HID_A4TECH is not set ++# CONFIG_HID_ACRUX is not set ++# CONFIG_HID_APPLE is not set ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++# CONFIG_HID_BELKIN is not set ++# CONFIG_HID_BETOP_FF is not set ++# CONFIG_HID_CHERRY is not set ++# CONFIG_HID_CHICONY is not set ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CYPRESS is not set ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++# CONFIG_HID_EZKEY is not set ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++# CONFIG_HID_KENSINGTON is not set ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++# CONFIG_HID_LOGITECH is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++# CONFIG_HID_MONTEREY is not set ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# 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=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_SISUSBVGA 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_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 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 is not set ++# CONFIG_DMADEVICES 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_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++CONFIG_COMMON_CLK_HI3521A=y ++CONFIG_RESET_HISI=y ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set ++CONFIG_ARM_TIMER_SP804=y ++# 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 is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_ZYNQ is not set ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# 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_PHY_HISI_SATA=y ++CONFIG_HISI_SATA_MODE=1 ++CONFIG_PHY_HISI_USB2=y ++# 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 ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# Firmware Drivers ++# ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT2=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_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=y ++# 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=y ++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=m ++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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_UBIFS_ATIME_SUPPORT is not set ++# CONFIG_LOGFS is not set ++CONFIG_CRAMFS=y ++# 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=y ++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=y ++# 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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_WQ_WATCHDOG is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++# CONFIG_SCHED_DEBUG is not set ++# CONFIG_SCHED_INFO is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++CONFIG_DEBUG_MUTEXES=y ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS 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_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set ++# CONFIG_UBSAN is not set ++CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y ++CONFIG_STRICT_DEVMEM=y ++# CONFIG_IO_STRICT_DEVMEM is not set ++# CONFIG_ARM_PTDUMP is not set ++# CONFIG_ARM_UNWIND is not set ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL 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_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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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=m ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++CONFIG_CRYPTO_GF128MUL=m ++CONFIG_CRYPTO_NULL=m ++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=m ++CONFIG_CRYPTO_GCM=m ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# 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=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++CONFIG_CRYPTO_CRCT10DIF=y ++CONFIG_CRYPTO_GHASH=m ++# CONFIG_CRYPTO_POLY1305 is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=y ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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=y ++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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++# CONFIG_CRYPTO_HW 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=y ++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=y ++CONFIG_CRC16=y ++CONFIG_CRC_T10DIF=y ++CONFIG_CRC_ITU_T=y ++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=y ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_LZ4=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_GLOB=y ++# CONFIG_GLOB_SELFTEST is not set ++CONFIG_NLATTR=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=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3531a_full_defconfig b/arch/arm/configs/hi3531a_full_defconfig +new file mode 100644 +index 0000000..a859f61 +--- /dev/null ++++ b/arch/arm/configs/hi3531a_full_defconfig +@@ -0,0 +1,2872 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 4.9.37 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_NEED_MACH_IO_H=y ++CONFIG_GENERIC_BUG=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_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++# CONFIG_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++CONFIG_FHANDLE=y ++CONFIG_USELIB=y ++# CONFIG_AUDIT is not set ++ ++# ++# 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_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++# CONFIG_IRQ_DOMAIN_DEBUG is not set ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_HZ_PERIODIC=y ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NO_HZ_FULL 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_TREE_RCU=y ++# CONFIG_RCU_EXPERT is not set ++CONFIG_SRCU=y ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++# 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=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_NMI_LOG_BUF_SHIFT=13 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_MEMCG is not set ++# CONFIG_BLK_CGROUP is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_CGROUP_PIDS is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_CGROUP_PERF is not set ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++# CONFIG_NAMESPACES is not set ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++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 is not set ++CONFIG_SYSCTL_SYSCALL=y ++CONFIG_KALLSYMS=y ++CONFIG_KALLSYMS_ALL=y ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_PRINTK_NMI=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_PCI_QUIRKS=y ++CONFIG_MEMBARRIER=y ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++CONFIG_PERF_USE_VMALLOC=y ++ ++# ++# Kernel Performance Events And Counters ++# ++CONFIG_PERF_EVENTS=y ++# CONFIG_DEBUG_PERF_USE_VMALLOC is not set ++# CONFIG_VM_EVENT_COUNTERS is not set ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_SLAB_FREELIST_RANDOM is not set ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_SYSTEM_DATA_VERIFICATION is not set ++CONFIG_PROFILING=y ++CONFIG_OPROFILE=y ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_HW_BREAKPOINT=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_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_SLABINFO=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_MODULES_TREE_LOOKUP=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++CONFIG_BLK_MQ_PCI=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_LOCK_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# 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_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 ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_ARTPEC is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_DIGICOLOR is not set ++# CONFIG_ARCH_HIGHBANK is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++ ++# ++# Hisilicon BVT platform type ++# ++# CONFIG_ARCH_HI3516A is not set ++# CONFIG_ARCH_HI3536DV100 is not set ++# CONFIG_ARCH_HI3521A is not set ++CONFIG_ARCH_HI3531A=y ++CONFIG_HI_ZRELADDR=0x40008000 ++CONFIG_HI_PARAMS_PHYS=0x00000100 ++CONFIG_HI_INITRD_PHYS=0x00800000 ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TANGO is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQ is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=y ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_BPREDICT_DISABLE is not set ++CONFIG_KUSER_HELPERS=y ++CONFIG_VDSO=y ++CONFIG_OUTER_CACHE=y ++CONFIG_OUTER_CACHE_SYNC=y ++CONFIG_MIGHT_HAVE_CACHE_L2X0=y ++CONFIG_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0_PMU is not set ++# CONFIG_PL310_ERRATA_588369 is not set ++# CONFIG_PL310_ERRATA_727915 is not set ++# CONFIG_PL310_ERRATA_753970 is not set ++# CONFIG_PL310_ERRATA_769419 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_ARM_HEAVY_MB=y ++CONFIG_DEBUG_RODATA=y ++CONFIG_DEBUG_ALIGN_RODATA=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_643719 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_754327 is not set ++# CONFIG_ARM_ERRATA_764369 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_798181 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++# CONFIG_ARM_ERRATA_818325_852422 is not set ++# CONFIG_ARM_ERRATA_821420 is not set ++# CONFIG_ARM_ERRATA_825619 is not set ++# CONFIG_ARM_ERRATA_852421 is not set ++# CONFIG_ARM_ERRATA_852423 is not set ++ ++# ++# Bus support ++# ++CONFIG_PCI=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_PCI_DOMAINS_GENERIC=y ++CONFIG_PCI_SYSCALL=y ++CONFIG_PCIEPORTBUS=y ++CONFIG_PCIEAER=y ++# CONFIG_PCIE_ECRC is not set ++# CONFIG_PCIEAER_INJECT is not set ++CONFIG_PCIEASPM=y ++# CONFIG_PCIEASPM_DEBUG is not set ++CONFIG_PCIEASPM_DEFAULT=y ++# CONFIG_PCIEASPM_POWERSAVE is not set ++# CONFIG_PCIEASPM_PERFORMANCE is not set ++# CONFIG_PCIE_PME is not set ++# CONFIG_PCIE_DPC is not set ++# CONFIG_PCIE_PTM is not set ++# CONFIG_PCI_MSI is not set ++# CONFIG_PCI_DEBUG is not set ++# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set ++# CONFIG_PCI_STUB is not set ++# CONFIG_PCI_IOV is not set ++# CONFIG_PCI_PRI is not set ++# CONFIG_PCI_PASID is not set ++# CONFIG_HOTPLUG_PCI is not set ++ ++# ++# PCI host controller drivers ++# ++# CONFIG_PCI_HOST_GENERIC is not set ++# CONFIG_PCIE_ALTERA is not set ++CONFIG_HIPCIE=y ++ ++# ++# PCI Express configs ++# ++CONFIG_LIMIT_MAX_RD_REQ_SIZE=y ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++CONFIG_SMP=y ++CONFIG_SMP_ON_UP=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++# CONFIG_SCHED_MC is not set ++# CONFIG_SCHED_SMT is not set ++CONFIG_HAVE_ARM_SCU=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++# CONFIG_MCPM is not set ++# CONFIG_BIG_LITTLE is not set ++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_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_ARM_PSCI is not set ++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_THUMB2_KERNEL is not set ++CONFIG_ARM_PATCH_IDIV=y ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_HAVE_ARCH_PFN_VALID=y ++CONFIG_HIGHMEM=y ++# CONFIG_HIGHPTE is not set ++CONFIG_CPU_SW_DOMAIN_PAN=y ++CONFIG_HW_PERF_EVENTS=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_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# 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 ++# CONFIG_XEN 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# 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=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set ++ ++# ++# CPU frequency scaling drivers ++# ++CONFIG_CPUFREQ_DT=y ++CONFIG_CPUFREQ_DT_PLATDEV=y ++# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++# CONFIG_QORIQ_CPUFREQ 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_FPE_NWFPE=y ++# CONFIG_FPE_NWFPE_XP is not set ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_VFP=y ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++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=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_SUSPEND_SKIP_SYNC is not set ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++CONFIG_APM_EMULATION=y ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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_USER 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 is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++# CONFIG_NET_IP_TUNNEL is not set ++# CONFIG_IP_MROUTE is not set ++CONFIG_SYN_COOKIES=y ++# CONFIG_NET_UDP_TUNNEL is not set ++# CONFIG_NET_FOU 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 is not set ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++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=y ++# CONFIG_IPV6 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_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_IEEE802154 is not set ++# CONFIG_NET_SCHED is not set ++# CONFIG_DCB is not set ++# 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_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_SOCK_CGROUP_DATA is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_WEXT_CORE=y ++CONFIG_WEXT_PROC=y ++CONFIG_CFG80211=m ++# CONFIG_NL80211_TESTMODE is not set ++# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set ++# CONFIG_CFG80211_CERTIFICATION_ONUS is not set ++CONFIG_CFG80211_DEFAULT_PS=y ++# CONFIG_CFG80211_DEBUGFS is not set ++# CONFIG_CFG80211_INTERNAL_REGDB is not set ++CONFIG_CFG80211_CRDA_SUPPORT=y ++CONFIG_CFG80211_WEXT=y ++# CONFIG_LIB80211 is not set ++CONFIG_MAC80211=m ++CONFIG_MAC80211_HAS_RC=y ++CONFIG_MAC80211_RC_MINSTREL=y ++CONFIG_MAC80211_RC_MINSTREL_HT=y ++# CONFIG_MAC80211_RC_MINSTREL_VHT is not set ++CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y ++CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" ++CONFIG_MAC80211_MESH=y ++# CONFIG_MAC80211_DEBUGFS is not set ++# CONFIG_MAC80211_MESSAGE_TRACING is not set ++# CONFIG_MAC80211_DEBUG_MENU is not set ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL 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 is not set ++# CONFIG_NET_DEVLINK is not set ++CONFIG_MAY_USE_DEVLINK=y ++CONFIG_HAVE_CBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# CONFIG_DMA_SHARED_BUFFER is not set ++ ++# ++# Bus devices ++# ++# CONFIG_ARM_CCI400_PMU is not set ++# CONFIG_ARM_CCI5xx_PMU is not set ++# CONFIG_ARM_CCN is not set ++# 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_INTEL_VR_NOR is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_DATAFLASH is not set ++# CONFIG_MTD_M25P80 is not set ++# 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=y ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOCG3 is not set ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_PCI is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_RICOH is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++# CONFIG_MTD_SPI_NAND_HISI_BVT is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++CONFIG_MTD_NAND_HINFC610=y ++CONFIG_HINFC610_MAX_CHIP=1 ++# CONFIG_HINFC610_DBG_NAND_DEBUG is not set ++CONFIG_HINFC610_AUTO_PAGESIZE_ECC=y ++# CONFIG_HINFC610_PAGESIZE_AUTO_ECC_NONE is not set ++# CONFIG_MTD_NAND_HIFMC100 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 is not set ++# CONFIG_SPI_CADENCE_QUADSPI is not set ++CONFIG_SPI_HISI_SFC=y ++# CONFIG_MTD_SPI_IDS is not set ++# CONFIG_CLOSE_SPI_8PIN_4IO is not set ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++# 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_ADDRESS_PCI=y ++CONFIG_OF_IRQ=y ++CONFIG_OF_NET=y ++CONFIG_OF_MDIO=y ++CONFIG_OF_PCI=y ++CONFIG_OF_PCI_IRQ=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=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set ++# CONFIG_BLK_CPQ_CISS_DA is not set ++# CONFIG_BLK_DEV_DAC960 is not set ++# CONFIG_BLK_DEV_UMEM is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_SX8 is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_BLK_DEV_RSXX is not set ++# CONFIG_BLK_DEV_NVME is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# CONFIG_SENSORS_LIS3LV02D is not set ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_DUMMY_IRQ is not set ++# CONFIG_PHANTOM is not set ++# CONFIG_SGI_IOC4 is not set ++# CONFIG_TIFM_CORE is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_HP_ILO 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 ++# CONFIG_CB710_CORE is not set ++ ++# ++# Texas Instruments shared transport line discipline ++# ++# 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 ++CONFIG_HAVE_IDE=y ++# CONFIG_IDE is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++CONFIG_BLK_DEV_SR=y ++# CONFIG_BLK_DEV_SR_VENDOR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_SCSI_CXGB3_ISCSI is not set ++# CONFIG_SCSI_CXGB4_ISCSI is not set ++# CONFIG_SCSI_BNX2_ISCSI is not set ++# CONFIG_BE2ISCSI is not set ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_HPSA is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_3W_SAS is not set ++# CONFIG_SCSI_ACARD is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX is not set ++# CONFIG_SCSI_AIC79XX is not set ++# CONFIG_SCSI_AIC94XX is not set ++# CONFIG_SCSI_MVSAS is not set ++# CONFIG_SCSI_MVUMI is not set ++# CONFIG_SCSI_ADVANSYS is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_SCSI_ESAS2R is not set ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++# CONFIG_SCSI_MPT3SAS is not set ++# CONFIG_SCSI_MPT2SAS is not set ++# CONFIG_SCSI_SMARTPQI is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_SCSI_HPTIOP is not set ++# CONFIG_SCSI_SNIC is not set ++# CONFIG_SCSI_DMX3191D is not set ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_IPS is not set ++# CONFIG_SCSI_INITIO is not set ++# CONFIG_SCSI_INIA100 is not set ++# CONFIG_SCSI_STEX is not set ++# CONFIG_SCSI_SYM53C8XX_2 is not set ++# CONFIG_SCSI_IPR is not set ++# CONFIG_SCSI_QLOGIC_1280 is not set ++# CONFIG_SCSI_QLA_ISCSI is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_AM53C974 is not set ++# CONFIG_SCSI_NSP32 is not set ++# CONFIG_SCSI_WD719X is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_PMCRAID is not set ++# CONFIG_SCSI_PM8001 is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HISI_SATA=y ++CONFIG_HISI_SATA_IOBASE=0x11010000 ++CONFIG_HISI_SATA_FBS=1 ++CONFIG_HISI_SATA_NCQ=1 ++# CONFIG_HISI_ESATA is not set ++CONFIG_ATA=y ++# CONFIG_ATA_NONSTANDARD is not set ++CONFIG_ATA_VERBOSE_ERROR=y ++CONFIG_SATA_PMP=y ++ ++# ++# Controllers with non-SFF native interface ++# ++# CONFIG_SATA_AHCI is not set ++CONFIG_SATA_AHCI_PLATFORM=y ++# CONFIG_AHCI_CEVA is not set ++# CONFIG_AHCI_QORIQ is not set ++# CONFIG_SATA_INIC162X is not set ++# CONFIG_SATA_ACARD_AHCI is not set ++# CONFIG_SATA_SIL24 is not set ++# CONFIG_ATA_SFF is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++# CONFIG_FUSION is not set ++ ++# ++# IEEE 1394 (FireWire) support ++# ++# CONFIG_FIREWIRE is not set ++# CONFIG_FIREWIRE_NOSY is not set ++CONFIG_NETDEVICES=y ++CONFIG_NET_CORE=y ++# CONFIG_BONDING is not set ++# CONFIG_DUMMY is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC 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 ++# CONFIG_ARCNET is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++CONFIG_ETHERNET=y ++# CONFIG_NET_VENDOR_3COM is not set ++# CONFIG_NET_VENDOR_ADAPTEC is not set ++# CONFIG_NET_VENDOR_AGERE is not set ++# CONFIG_NET_VENDOR_ALTEON is not set ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_VENDOR_AMAZON is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_VENDOR_ARC is not set ++# CONFIG_NET_VENDOR_ATHEROS 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_BROCADE is not set ++# CONFIG_NET_VENDOR_CAVIUM is not set ++# CONFIG_NET_VENDOR_CHELSIO is not set ++# CONFIG_NET_VENDOR_CIRRUS is not set ++# CONFIG_NET_VENDOR_CISCO is not set ++# CONFIG_DM9000 is not set ++# CONFIG_DNET is not set ++# CONFIG_NET_VENDOR_DEC is not set ++# CONFIG_NET_VENDOR_DLINK is not set ++# CONFIG_NET_VENDOR_EMULEX is not set ++# CONFIG_NET_VENDOR_EZCHIP is not set ++# CONFIG_NET_VENDOR_EXAR is not set ++# CONFIG_NET_VENDOR_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# CONFIG_NET_VENDOR_HP is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_JME is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++# CONFIG_NET_VENDOR_MELLANOX is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_MICROCHIP is not set ++# CONFIG_NET_VENDOR_MYRI is not set ++# CONFIG_FEALNX is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NETRONOME is not set ++# CONFIG_NET_VENDOR_NVIDIA is not set ++# CONFIG_NET_VENDOR_OKI is not set ++# CONFIG_ETHOC is not set ++# CONFIG_NET_PACKET_ENGINE is not set ++# CONFIG_NET_VENDOR_QLOGIC is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++# CONFIG_NET_VENDOR_REALTEK is not set ++# CONFIG_NET_VENDOR_RENESAS is not set ++# CONFIG_NET_VENDOR_RDC 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_SILAN is not set ++# CONFIG_NET_VENDOR_SIS is not set ++# CONFIG_SFC is not set ++# CONFIG_NET_VENDOR_SMSC is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++# CONFIG_NET_VENDOR_SUN is not set ++# CONFIG_NET_VENDOR_SYNOPSYS is not set ++# CONFIG_NET_VENDOR_TEHUTI is not set ++# CONFIG_NET_VENDOR_TI is not set ++# CONFIG_NET_VENDOR_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_FDDI is not set ++# CONFIG_HIPPI is not set ++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_MMIOREG is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++ ++# ++# 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_IPHETH is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_VMXNET3 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_APMPOWER is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INPUT_CM109 is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_USERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_NOZOMI 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_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# 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_JSM is not set ++# CONFIG_SERIAL_SCCNXP is not set ++# CONFIG_SERIAL_SC16IS7XX is not set ++# CONFIG_SERIAL_BCM63XX is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++# CONFIG_SERIAL_ARC is not set ++# CONFIG_SERIAL_RP2 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_APPLICOM is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_DEVPORT=y ++# CONFIG_XILLYBUS is not set ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_COMPAT=y ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_MUX is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# PC SMBus host controller drivers ++# ++# CONFIG_I2C_ALI1535 is not set ++# CONFIG_I2C_ALI1563 is not set ++# CONFIG_I2C_ALI15X3 is not set ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++# CONFIG_I2C_I801 is not set ++# CONFIG_I2C_ISCH is not set ++# CONFIG_I2C_PIIX4 is not set ++# CONFIG_I2C_NFORCE2 is not set ++# CONFIG_I2C_SIS5595 is not set ++# CONFIG_I2C_SIS630 is not set ++# CONFIG_I2C_SIS96X is not set ++# CONFIG_I2C_VIA is not set ++# CONFIG_I2C_VIAPRO is not set ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_DESIGNWARE_PCI is not set ++# CONFIG_I2C_EMEV2 is not set ++# CONFIG_I2C_HIBVT is not set ++# CONFIG_I2C_NOMADIK 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_HISI=y ++# 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_DEBUG is not set ++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_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# CONFIG_SPI_PXA2XX 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=y ++# 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++# CONFIG_GPIOLIB is not set ++# 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++CONFIG_POWER_RESET_SYSCON=y ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_APM_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_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_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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_LPC_ICH is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_MFD_JANZ_CMODIO 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_RDC321X is not set ++# CONFIG_MFD_RTSX_PCI 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=y ++# 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_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_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_VX855 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 ++ ++# ++# Graphics support ++# ++CONFIG_VGA_ARB=y ++CONFIG_VGA_ARB_MAX_GPUS=16 ++# CONFIG_IMX_IPUV3_CORE is not set ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_CIRRUS is not set ++# CONFIG_FB_PM2 is not set ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_NVIDIA is not set ++# CONFIG_FB_RIVA is not set ++# CONFIG_FB_I740 is not set ++# CONFIG_FB_MATROX is not set ++# CONFIG_FB_RADEON is not set ++# CONFIG_FB_ATY128 is not set ++# CONFIG_FB_ATY is not set ++# CONFIG_FB_S3 is not set ++# CONFIG_FB_SAVAGE is not set ++# CONFIG_FB_SIS is not set ++# CONFIG_FB_NEOMAGIC is not set ++# CONFIG_FB_KYRO is not set ++# CONFIG_FB_3DFX is not set ++# CONFIG_FB_VOODOO1 is not set ++# CONFIG_FB_VT8623 is not set ++# CONFIG_FB_TRIDENT is not set ++# CONFIG_FB_ARK is not set ++# CONFIG_FB_PM3 is not set ++# CONFIG_FB_CARMINE is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_MB862XX is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SM712 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++# CONFIG_HID_A4TECH is not set ++# CONFIG_HID_ACRUX is not set ++# CONFIG_HID_APPLE is not set ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++# CONFIG_HID_BELKIN is not set ++# CONFIG_HID_BETOP_FF is not set ++# CONFIG_HID_CHERRY is not set ++# CONFIG_HID_CHICONY is not set ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CYPRESS is not set ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++# CONFIG_HID_EZKEY is not set ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++# CONFIG_HID_KENSINGTON is not set ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++# CONFIG_HID_LOGITECH is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++# CONFIG_HID_MONTEREY is not set ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# 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 is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PCI=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_EHCI_HCD=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_PCI=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# 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=y ++CONFIG_USB_OHCI_HCD_PCI=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# CONFIG_USB_UHCI_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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_SISUSBVGA 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_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 is not set ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_INFINIBAND is not set ++CONFIG_EDAC_ATOMIC_SCRUB=y ++CONFIG_EDAC_SUPPORT=y ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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_PCI is not set ++# 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_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++CONFIG_COMMON_CLK_HI3531A=y ++CONFIG_RESET_HISI=y ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set ++CONFIG_ARM_TIMER_SP804=y ++CONFIG_TIMER_HISP804=y ++# 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_NTB is not set ++# CONFIG_VME_BUS is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_ZYNQ is not set ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# 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_PHY_HISI_SATA=y ++CONFIG_HISI_SATA_MODE=1 ++CONFIG_PHY_HISI_USB2=y ++CONFIG_PHY_HISI_USB3=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++ ++# ++# Performance monitor support ++# ++CONFIG_ARM_PMU=y ++CONFIG_RAS=y ++# CONFIG_THUNDERBOLT 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 ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# Firmware Drivers ++# ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++CONFIG_FS_IOMAP=y ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT2=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_CHECK=y ++CONFIG_REISERFS_PROC_INFO=y ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_DEBUG=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++CONFIG_XFS_DEBUG=y ++# CONFIG_GFS2_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=y ++CONFIG_EXPORTFS=y ++# 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=y ++# CONFIG_QUOTA_NETLINK_INTERFACE is not set ++CONFIG_PRINT_QUOTA_WARNING=y ++# CONFIG_QUOTA_DEBUG is not set ++CONFIG_QUOTA_TREE=m ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_QUOTACTL=y ++CONFIG_AUTOFS4_FS=m ++CONFIG_FUSE_FS=y ++# CONFIG_CUSE is not set ++# CONFIG_OVERLAY_FS is not set ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=y ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++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=y ++CONFIG_TMPFS_XATTR=y ++# 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_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++# 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFSD is not set ++CONFIG_GRACE_PERIOD=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=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=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=y ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++# 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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++# CONFIG_DYNAMIC_DEBUG is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++CONFIG_ENABLE_WARN_DEPRECATED=y ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_WQ_WATCHDOG is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHED_INFO is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++# CONFIG_DEBUG_BUGVERBOSE is not set ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS 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_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_RCU_TRACE is not set ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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_TRACE_CLOCK=y ++CONFIG_RING_BUFFER=y ++CONFIG_RING_BUFFER_ALLOW_SWAP=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_UPROBE_EVENT is not set ++# CONFIG_PROBE_EVENTS is not set ++# CONFIG_TRACEPOINT_BENCHMARK is not set ++# CONFIG_RING_BUFFER_BENCHMARK is not set ++# CONFIG_RING_BUFFER_STARTUP_TEST is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_LKDTM is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set ++# CONFIG_UBSAN is not set ++CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y ++CONFIG_STRICT_DEVMEM=y ++# CONFIG_IO_STRICT_DEVMEM is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL 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 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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=m ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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=m ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++CONFIG_CRYPTO_GF128MUL=m ++CONFIG_CRYPTO_NULL=m ++CONFIG_CRYPTO_NULL2=y ++# CONFIG_CRYPTO_PCRYPT is not set ++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=m ++CONFIG_CRYPTO_GCM=m ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# 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=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++CONFIG_CRYPTO_GHASH=m ++# CONFIG_CRYPTO_POLY1305 is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=y ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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=m ++# 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=m ++# 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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_CRYPTO_DEV_HIFN_795X 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=y ++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=y ++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=m ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_GLOB=y ++# CONFIG_GLOB_SELFTEST is not set ++CONFIG_NLATTR=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=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3531a_full_slave_defconfig b/arch/arm/configs/hi3531a_full_slave_defconfig +new file mode 100644 +index 0000000..4c86970 +--- /dev/null ++++ b/arch/arm/configs/hi3531a_full_slave_defconfig +@@ -0,0 +1,2919 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 4.9.37 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_NEED_MACH_IO_H=y ++CONFIG_GENERIC_BUG=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_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++# CONFIG_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++CONFIG_FHANDLE=y ++CONFIG_USELIB=y ++# CONFIG_AUDIT is not set ++ ++# ++# 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_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++# CONFIG_IRQ_DOMAIN_DEBUG is not set ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_HZ_PERIODIC=y ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NO_HZ_FULL 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_TREE_RCU=y ++# CONFIG_RCU_EXPERT is not set ++CONFIG_SRCU=y ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++# 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=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_NMI_LOG_BUF_SHIFT=13 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_MEMCG is not set ++# CONFIG_BLK_CGROUP is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_CGROUP_PIDS is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_CGROUP_PERF is not set ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++# CONFIG_NAMESPACES is not set ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++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 is not set ++CONFIG_SYSCTL_SYSCALL=y ++CONFIG_KALLSYMS=y ++CONFIG_KALLSYMS_ALL=y ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_PRINTK_NMI=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_PCI_QUIRKS=y ++CONFIG_MEMBARRIER=y ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++CONFIG_PERF_USE_VMALLOC=y ++ ++# ++# Kernel Performance Events And Counters ++# ++CONFIG_PERF_EVENTS=y ++# CONFIG_DEBUG_PERF_USE_VMALLOC is not set ++# CONFIG_VM_EVENT_COUNTERS is not set ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_SLAB_FREELIST_RANDOM is not set ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_SYSTEM_DATA_VERIFICATION is not set ++CONFIG_PROFILING=y ++CONFIG_OPROFILE=y ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_HW_BREAKPOINT=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_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_SLABINFO=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_MODULES_TREE_LOOKUP=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++CONFIG_BLK_MQ_PCI=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_LOCK_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# 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_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 ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_ARTPEC is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_DIGICOLOR is not set ++# CONFIG_ARCH_HIGHBANK is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++ ++# ++# Hisilicon BVT platform type ++# ++# CONFIG_ARCH_HI3516A is not set ++# CONFIG_ARCH_HI3536DV100 is not set ++# CONFIG_ARCH_HI3521A is not set ++CONFIG_ARCH_HI3531A=y ++CONFIG_HI_ZRELADDR=0x40008000 ++CONFIG_HI_PARAMS_PHYS=0x00000100 ++CONFIG_HI_INITRD_PHYS=0x00800000 ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TANGO is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQ is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=y ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_BPREDICT_DISABLE is not set ++CONFIG_KUSER_HELPERS=y ++CONFIG_VDSO=y ++CONFIG_OUTER_CACHE=y ++CONFIG_OUTER_CACHE_SYNC=y ++CONFIG_MIGHT_HAVE_CACHE_L2X0=y ++CONFIG_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0_PMU is not set ++# CONFIG_PL310_ERRATA_588369 is not set ++# CONFIG_PL310_ERRATA_727915 is not set ++# CONFIG_PL310_ERRATA_753970 is not set ++# CONFIG_PL310_ERRATA_769419 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_ARM_HEAVY_MB=y ++CONFIG_DEBUG_RODATA=y ++CONFIG_DEBUG_ALIGN_RODATA=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_643719 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_754327 is not set ++# CONFIG_ARM_ERRATA_764369 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_798181 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++# CONFIG_ARM_ERRATA_818325_852422 is not set ++# CONFIG_ARM_ERRATA_821420 is not set ++# CONFIG_ARM_ERRATA_825619 is not set ++# CONFIG_ARM_ERRATA_852421 is not set ++# CONFIG_ARM_ERRATA_852423 is not set ++ ++# ++# Bus support ++# ++CONFIG_PCI=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_PCI_DOMAINS_GENERIC=y ++CONFIG_PCI_SYSCALL=y ++CONFIG_PCIEPORTBUS=y ++CONFIG_PCIEAER=y ++# CONFIG_PCIE_ECRC is not set ++# CONFIG_PCIEAER_INJECT is not set ++CONFIG_PCIEASPM=y ++# CONFIG_PCIEASPM_DEBUG is not set ++CONFIG_PCIEASPM_DEFAULT=y ++# CONFIG_PCIEASPM_POWERSAVE is not set ++# CONFIG_PCIEASPM_PERFORMANCE is not set ++# CONFIG_PCIE_PME is not set ++# CONFIG_PCIE_DPC is not set ++# CONFIG_PCIE_PTM is not set ++# CONFIG_PCI_MSI is not set ++# CONFIG_PCI_DEBUG is not set ++# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set ++# CONFIG_PCI_STUB is not set ++# CONFIG_PCI_IOV is not set ++# CONFIG_PCI_PRI is not set ++# CONFIG_PCI_PASID is not set ++# CONFIG_HOTPLUG_PCI is not set ++ ++# ++# PCI host controller drivers ++# ++# CONFIG_PCI_HOST_GENERIC is not set ++# CONFIG_PCIE_ALTERA is not set ++# CONFIG_HIPCIE is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++CONFIG_SMP=y ++CONFIG_SMP_ON_UP=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++# CONFIG_SCHED_MC is not set ++# CONFIG_SCHED_SMT is not set ++CONFIG_HAVE_ARM_SCU=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++# CONFIG_MCPM is not set ++# CONFIG_BIG_LITTLE is not set ++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_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_ARM_PSCI is not set ++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_THUMB2_KERNEL is not set ++CONFIG_ARM_PATCH_IDIV=y ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_HAVE_ARCH_PFN_VALID=y ++CONFIG_HIGHMEM=y ++# CONFIG_HIGHPTE is not set ++CONFIG_CPU_SW_DOMAIN_PAN=y ++CONFIG_HW_PERF_EVENTS=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_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# 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 ++# CONFIG_XEN 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# 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=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set ++ ++# ++# CPU frequency scaling drivers ++# ++CONFIG_CPUFREQ_DT=y ++CONFIG_CPUFREQ_DT_PLATDEV=y ++# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++# CONFIG_QORIQ_CPUFREQ 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_FPE_NWFPE=y ++# CONFIG_FPE_NWFPE_XP is not set ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_VFP=y ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++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=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_SUSPEND_SKIP_SYNC is not set ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++CONFIG_APM_EMULATION=y ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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_USER 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 is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++# CONFIG_NET_IP_TUNNEL is not set ++# CONFIG_IP_MROUTE is not set ++CONFIG_SYN_COOKIES=y ++# CONFIG_NET_UDP_TUNNEL is not set ++# CONFIG_NET_FOU 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 is not set ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++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=y ++# CONFIG_IPV6 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_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_IEEE802154 is not set ++# CONFIG_NET_SCHED is not set ++# CONFIG_DCB is not set ++# 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_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_SOCK_CGROUP_DATA is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_WEXT_CORE=y ++CONFIG_WEXT_PROC=y ++CONFIG_CFG80211=m ++# CONFIG_NL80211_TESTMODE is not set ++# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set ++# CONFIG_CFG80211_CERTIFICATION_ONUS is not set ++CONFIG_CFG80211_DEFAULT_PS=y ++# CONFIG_CFG80211_DEBUGFS is not set ++# CONFIG_CFG80211_INTERNAL_REGDB is not set ++CONFIG_CFG80211_CRDA_SUPPORT=y ++CONFIG_CFG80211_WEXT=y ++# CONFIG_LIB80211 is not set ++CONFIG_MAC80211=m ++CONFIG_MAC80211_HAS_RC=y ++CONFIG_MAC80211_RC_MINSTREL=y ++CONFIG_MAC80211_RC_MINSTREL_HT=y ++# CONFIG_MAC80211_RC_MINSTREL_VHT is not set ++CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y ++CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" ++CONFIG_MAC80211_MESH=y ++# CONFIG_MAC80211_DEBUGFS is not set ++# CONFIG_MAC80211_MESSAGE_TRACING is not set ++# CONFIG_MAC80211_DEBUG_MENU is not set ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL 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 is not set ++# CONFIG_NET_DEVLINK is not set ++CONFIG_MAY_USE_DEVLINK=y ++CONFIG_HAVE_CBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# CONFIG_DMA_SHARED_BUFFER is not set ++ ++# ++# Bus devices ++# ++# CONFIG_ARM_CCI400_PMU is not set ++# CONFIG_ARM_CCI5xx_PMU is not set ++# CONFIG_ARM_CCN is not set ++# 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_INTEL_VR_NOR is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_DATAFLASH is not set ++# CONFIG_MTD_M25P80 is not set ++# 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=y ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOCG3 is not set ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_PCI is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_RICOH is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++# CONFIG_MTD_SPI_NAND_HISI_BVT is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++CONFIG_MTD_NAND_HINFC610=y ++CONFIG_HINFC610_MAX_CHIP=1 ++# CONFIG_HINFC610_DBG_NAND_DEBUG is not set ++CONFIG_HINFC610_AUTO_PAGESIZE_ECC=y ++# CONFIG_HINFC610_PAGESIZE_AUTO_ECC_NONE is not set ++# CONFIG_MTD_NAND_HIFMC100 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 is not set ++# CONFIG_SPI_CADENCE_QUADSPI is not set ++CONFIG_SPI_HISI_SFC=y ++# CONFIG_MTD_SPI_IDS is not set ++# CONFIG_CLOSE_SPI_8PIN_4IO is not set ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++# 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_ADDRESS_PCI=y ++CONFIG_OF_IRQ=y ++CONFIG_OF_NET=y ++CONFIG_OF_MDIO=y ++CONFIG_OF_PCI=y ++CONFIG_OF_PCI_IRQ=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=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set ++# CONFIG_BLK_CPQ_CISS_DA is not set ++# CONFIG_BLK_DEV_DAC960 is not set ++# CONFIG_BLK_DEV_UMEM is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_SX8 is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_BLK_DEV_RSXX is not set ++# CONFIG_BLK_DEV_NVME is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# CONFIG_SENSORS_LIS3LV02D is not set ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_DUMMY_IRQ is not set ++# CONFIG_PHANTOM is not set ++# CONFIG_SGI_IOC4 is not set ++# CONFIG_TIFM_CORE is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_HP_ILO 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 ++# CONFIG_CB710_CORE is not set ++ ++# ++# Texas Instruments shared transport line discipline ++# ++# 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 ++CONFIG_HAVE_IDE=y ++# CONFIG_IDE is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++CONFIG_BLK_DEV_SR=y ++# CONFIG_BLK_DEV_SR_VENDOR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_SCSI_CXGB3_ISCSI is not set ++# CONFIG_SCSI_CXGB4_ISCSI is not set ++# CONFIG_SCSI_BNX2_ISCSI is not set ++# CONFIG_BE2ISCSI is not set ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_HPSA is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_3W_SAS is not set ++# CONFIG_SCSI_ACARD is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX is not set ++# CONFIG_SCSI_AIC79XX is not set ++# CONFIG_SCSI_AIC94XX is not set ++# CONFIG_SCSI_MVSAS is not set ++# CONFIG_SCSI_MVUMI is not set ++# CONFIG_SCSI_ADVANSYS is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_SCSI_ESAS2R is not set ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++# CONFIG_SCSI_MPT3SAS is not set ++# CONFIG_SCSI_MPT2SAS is not set ++# CONFIG_SCSI_SMARTPQI is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_SCSI_HPTIOP is not set ++# CONFIG_SCSI_SNIC is not set ++# CONFIG_SCSI_DMX3191D is not set ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_IPS is not set ++# CONFIG_SCSI_INITIO is not set ++# CONFIG_SCSI_INIA100 is not set ++# CONFIG_SCSI_STEX is not set ++# CONFIG_SCSI_SYM53C8XX_2 is not set ++# CONFIG_SCSI_IPR is not set ++# CONFIG_SCSI_QLOGIC_1280 is not set ++# CONFIG_SCSI_QLA_ISCSI is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_AM53C974 is not set ++# CONFIG_SCSI_NSP32 is not set ++# CONFIG_SCSI_WD719X is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_PMCRAID is not set ++# CONFIG_SCSI_PM8001 is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HISI_SATA=y ++CONFIG_HISI_SATA_IOBASE=0x11010000 ++CONFIG_HISI_SATA_FBS=1 ++CONFIG_HISI_SATA_NCQ=1 ++# CONFIG_HISI_ESATA is not set ++CONFIG_ATA=y ++# CONFIG_ATA_NONSTANDARD is not set ++CONFIG_ATA_VERBOSE_ERROR=y ++CONFIG_SATA_PMP=y ++ ++# ++# Controllers with non-SFF native interface ++# ++# CONFIG_SATA_AHCI is not set ++CONFIG_SATA_AHCI_PLATFORM=y ++# CONFIG_AHCI_CEVA is not set ++# CONFIG_AHCI_QORIQ is not set ++# CONFIG_SATA_INIC162X is not set ++# CONFIG_SATA_ACARD_AHCI is not set ++# CONFIG_SATA_SIL24 is not set ++# CONFIG_ATA_SFF is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++# CONFIG_FUSION is not set ++ ++# ++# IEEE 1394 (FireWire) support ++# ++# CONFIG_FIREWIRE is not set ++# CONFIG_FIREWIRE_NOSY is not set ++CONFIG_NETDEVICES=y ++CONFIG_NET_CORE=y ++# CONFIG_BONDING is not set ++# CONFIG_DUMMY is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC 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 ++# CONFIG_ARCNET is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++CONFIG_ETHERNET=y ++CONFIG_NET_VENDOR_3COM=y ++# CONFIG_VORTEX is not set ++# CONFIG_TYPHOON is not set ++CONFIG_NET_VENDOR_ADAPTEC=y ++# CONFIG_ADAPTEC_STARFIRE is not set ++CONFIG_NET_VENDOR_AGERE=y ++# CONFIG_ET131X is not set ++CONFIG_NET_VENDOR_ALTEON=y ++# CONFIG_ACENIC is not set ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_VENDOR_AMAZON is not set ++CONFIG_NET_VENDOR_AMD=y ++# CONFIG_AMD8111_ETH is not set ++# CONFIG_PCNET32 is not set ++# CONFIG_NET_VENDOR_ARC is not set ++CONFIG_NET_VENDOR_ATHEROS=y ++# CONFIG_ATL2 is not set ++# CONFIG_ATL1 is not set ++# CONFIG_ATL1E is not set ++# CONFIG_ATL1C is not set ++# CONFIG_ALX 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_BROCADE=y ++# CONFIG_BNA is not set ++CONFIG_NET_VENDOR_CAVIUM=y ++CONFIG_NET_VENDOR_CHELSIO=y ++# CONFIG_CHELSIO_T1 is not set ++# CONFIG_CHELSIO_T3 is not set ++# CONFIG_CHELSIO_T4 is not set ++# CONFIG_CHELSIO_T4VF is not set ++# CONFIG_NET_VENDOR_CIRRUS is not set ++CONFIG_NET_VENDOR_CISCO=y ++# CONFIG_ENIC is not set ++# CONFIG_DM9000 is not set ++# CONFIG_DNET is not set ++CONFIG_NET_VENDOR_DEC=y ++# CONFIG_NET_TULIP is not set ++CONFIG_NET_VENDOR_DLINK=y ++# CONFIG_DL2K is not set ++# CONFIG_SUNDANCE is not set ++CONFIG_NET_VENDOR_EMULEX=y ++# CONFIG_BE2NET is not set ++# CONFIG_NET_VENDOR_EZCHIP is not set ++CONFIG_NET_VENDOR_EXAR=y ++# CONFIG_S2IO is not set ++# CONFIG_VXGE is not set ++# CONFIG_NET_VENDOR_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++CONFIG_NET_VENDOR_HP=y ++# CONFIG_HP100 is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_JME is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++CONFIG_NET_VENDOR_MELLANOX=y ++# CONFIG_MLX4_EN is not set ++# CONFIG_MLX4_CORE is not set ++# CONFIG_MLX5_CORE is not set ++# CONFIG_MLXSW_CORE is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_MICROCHIP is not set ++CONFIG_NET_VENDOR_MYRI=y ++# CONFIG_MYRI10GE is not set ++# CONFIG_FEALNX is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NETRONOME is not set ++CONFIG_NET_VENDOR_NVIDIA=y ++# CONFIG_FORCEDETH is not set ++CONFIG_NET_VENDOR_OKI=y ++# CONFIG_ETHOC is not set ++CONFIG_NET_PACKET_ENGINE=y ++# CONFIG_HAMACHI is not set ++# CONFIG_YELLOWFIN is not set ++CONFIG_NET_VENDOR_QLOGIC=y ++# CONFIG_QLA3XXX is not set ++# CONFIG_QLCNIC is not set ++# CONFIG_QLGE is not set ++# CONFIG_NETXEN_NIC is not set ++# CONFIG_QED is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++CONFIG_NET_VENDOR_REALTEK=y ++# CONFIG_8139CP is not set ++# CONFIG_8139TOO is not set ++# CONFIG_R8169 is not set ++# CONFIG_NET_VENDOR_RENESAS is not set ++CONFIG_NET_VENDOR_RDC=y ++# CONFIG_R6040 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_SILAN=y ++# CONFIG_SC92031 is not set ++CONFIG_NET_VENDOR_SIS=y ++# CONFIG_SIS900 is not set ++# CONFIG_SIS190 is not set ++# CONFIG_SFC is not set ++# CONFIG_NET_VENDOR_SMSC is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++CONFIG_NET_VENDOR_SUN=y ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++# CONFIG_NIU is not set ++# CONFIG_NET_VENDOR_SYNOPSYS is not set ++CONFIG_NET_VENDOR_TEHUTI=y ++# CONFIG_TEHUTI is not set ++CONFIG_NET_VENDOR_TI=y ++# CONFIG_TI_CPSW_ALE is not set ++# CONFIG_TLAN is not set ++# CONFIG_NET_VENDOR_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_FDDI is not set ++# CONFIG_HIPPI is not set ++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_MMIOREG is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++ ++# ++# 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_IPHETH is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_VMXNET3 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_APMPOWER is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INPUT_CM109 is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_USERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_NOZOMI 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_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# 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_JSM is not set ++# CONFIG_SERIAL_SCCNXP is not set ++# CONFIG_SERIAL_SC16IS7XX is not set ++# CONFIG_SERIAL_BCM63XX is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++# CONFIG_SERIAL_ARC is not set ++# CONFIG_SERIAL_RP2 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_APPLICOM is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_DEVPORT=y ++# CONFIG_XILLYBUS is not set ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_COMPAT=y ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_MUX is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# PC SMBus host controller drivers ++# ++# CONFIG_I2C_ALI1535 is not set ++# CONFIG_I2C_ALI1563 is not set ++# CONFIG_I2C_ALI15X3 is not set ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++# CONFIG_I2C_I801 is not set ++# CONFIG_I2C_ISCH is not set ++# CONFIG_I2C_PIIX4 is not set ++# CONFIG_I2C_NFORCE2 is not set ++# CONFIG_I2C_SIS5595 is not set ++# CONFIG_I2C_SIS630 is not set ++# CONFIG_I2C_SIS96X is not set ++# CONFIG_I2C_VIA is not set ++# CONFIG_I2C_VIAPRO is not set ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_DESIGNWARE_PCI is not set ++# CONFIG_I2C_EMEV2 is not set ++# CONFIG_I2C_HIBVT is not set ++# CONFIG_I2C_NOMADIK 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_HISI=y ++# 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_DEBUG is not set ++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_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# CONFIG_SPI_PXA2XX 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=y ++# 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++# CONFIG_GPIOLIB is not set ++# 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++CONFIG_POWER_RESET_SYSCON=y ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_APM_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_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_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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_LPC_ICH is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_MFD_JANZ_CMODIO 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_RDC321X is not set ++# CONFIG_MFD_RTSX_PCI 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=y ++# 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_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_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_VX855 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 ++ ++# ++# Graphics support ++# ++CONFIG_VGA_ARB=y ++CONFIG_VGA_ARB_MAX_GPUS=16 ++# CONFIG_IMX_IPUV3_CORE is not set ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_CIRRUS is not set ++# CONFIG_FB_PM2 is not set ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_NVIDIA is not set ++# CONFIG_FB_RIVA is not set ++# CONFIG_FB_I740 is not set ++# CONFIG_FB_MATROX is not set ++# CONFIG_FB_RADEON is not set ++# CONFIG_FB_ATY128 is not set ++# CONFIG_FB_ATY is not set ++# CONFIG_FB_S3 is not set ++# CONFIG_FB_SAVAGE is not set ++# CONFIG_FB_SIS is not set ++# CONFIG_FB_NEOMAGIC is not set ++# CONFIG_FB_KYRO is not set ++# CONFIG_FB_3DFX is not set ++# CONFIG_FB_VOODOO1 is not set ++# CONFIG_FB_VT8623 is not set ++# CONFIG_FB_TRIDENT is not set ++# CONFIG_FB_ARK is not set ++# CONFIG_FB_PM3 is not set ++# CONFIG_FB_CARMINE is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_MB862XX is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SM712 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++# CONFIG_HID_A4TECH is not set ++# CONFIG_HID_ACRUX is not set ++# CONFIG_HID_APPLE is not set ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++# CONFIG_HID_BELKIN is not set ++# CONFIG_HID_BETOP_FF is not set ++# CONFIG_HID_CHERRY is not set ++# CONFIG_HID_CHICONY is not set ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CYPRESS is not set ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++# CONFIG_HID_EZKEY is not set ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++# CONFIG_HID_KENSINGTON is not set ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++# CONFIG_HID_LOGITECH is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++# CONFIG_HID_MONTEREY is not set ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# 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 is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PCI=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_EHCI_HCD=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_PCI=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# 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=y ++CONFIG_USB_OHCI_HCD_PCI=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# CONFIG_USB_UHCI_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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_SISUSBVGA 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_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 is not set ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_INFINIBAND is not set ++CONFIG_EDAC_ATOMIC_SCRUB=y ++CONFIG_EDAC_SUPPORT=y ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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_PCI is not set ++# 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_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++CONFIG_COMMON_CLK_HI3531A=y ++CONFIG_RESET_HISI=y ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set ++CONFIG_ARM_TIMER_SP804=y ++CONFIG_TIMER_HISP804=y ++# 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_NTB is not set ++# CONFIG_VME_BUS is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_ZYNQ is not set ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# 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_PHY_HISI_SATA=y ++CONFIG_HISI_SATA_MODE=1 ++CONFIG_PHY_HISI_USB2=y ++CONFIG_PHY_HISI_USB3=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++ ++# ++# Performance monitor support ++# ++CONFIG_ARM_PMU=y ++CONFIG_RAS=y ++# CONFIG_THUNDERBOLT 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 ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# Firmware Drivers ++# ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++CONFIG_FS_IOMAP=y ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT2=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_CHECK=y ++CONFIG_REISERFS_PROC_INFO=y ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_DEBUG=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++CONFIG_XFS_DEBUG=y ++# CONFIG_GFS2_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=y ++CONFIG_EXPORTFS=y ++# 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=y ++# CONFIG_QUOTA_NETLINK_INTERFACE is not set ++CONFIG_PRINT_QUOTA_WARNING=y ++# CONFIG_QUOTA_DEBUG is not set ++CONFIG_QUOTA_TREE=m ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_QUOTACTL=y ++CONFIG_AUTOFS4_FS=m ++CONFIG_FUSE_FS=y ++# CONFIG_CUSE is not set ++# CONFIG_OVERLAY_FS is not set ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=y ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++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=y ++CONFIG_TMPFS_XATTR=y ++# 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_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++# 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFSD is not set ++CONFIG_GRACE_PERIOD=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=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=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=y ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++# 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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++# CONFIG_DYNAMIC_DEBUG is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++CONFIG_ENABLE_WARN_DEPRECATED=y ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_WQ_WATCHDOG is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHED_INFO is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++# CONFIG_DEBUG_BUGVERBOSE is not set ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS 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_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_RCU_TRACE is not set ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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_TRACE_CLOCK=y ++CONFIG_RING_BUFFER=y ++CONFIG_RING_BUFFER_ALLOW_SWAP=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_UPROBE_EVENT is not set ++# CONFIG_PROBE_EVENTS is not set ++# CONFIG_TRACEPOINT_BENCHMARK is not set ++# CONFIG_RING_BUFFER_BENCHMARK is not set ++# CONFIG_RING_BUFFER_STARTUP_TEST is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_LKDTM is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set ++# CONFIG_UBSAN is not set ++CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y ++CONFIG_STRICT_DEVMEM=y ++# CONFIG_IO_STRICT_DEVMEM is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL 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 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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=m ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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=m ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++CONFIG_CRYPTO_GF128MUL=m ++CONFIG_CRYPTO_NULL=m ++CONFIG_CRYPTO_NULL2=y ++# CONFIG_CRYPTO_PCRYPT is not set ++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=m ++CONFIG_CRYPTO_GCM=m ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# 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=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++CONFIG_CRYPTO_GHASH=m ++# CONFIG_CRYPTO_POLY1305 is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=y ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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=m ++# 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=m ++# 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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_CRYPTO_DEV_HIFN_795X 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=y ++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=y ++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=m ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_GLOB=y ++# CONFIG_GLOB_SELFTEST is not set ++CONFIG_NLATTR=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=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3531a_spinand_defconfig b/arch/arm/configs/hi3531a_spinand_defconfig +new file mode 100644 +index 0000000..ff4877d +--- /dev/null ++++ b/arch/arm/configs/hi3531a_spinand_defconfig +@@ -0,0 +1,2867 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 4.9.37 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_NEED_MACH_IO_H=y ++CONFIG_GENERIC_BUG=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_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++# CONFIG_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++CONFIG_FHANDLE=y ++CONFIG_USELIB=y ++# CONFIG_AUDIT is not set ++ ++# ++# 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_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++# CONFIG_IRQ_DOMAIN_DEBUG is not set ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_HZ_PERIODIC=y ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NO_HZ_FULL 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_TREE_RCU=y ++# CONFIG_RCU_EXPERT is not set ++CONFIG_SRCU=y ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++# 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=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_NMI_LOG_BUF_SHIFT=13 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_MEMCG is not set ++# CONFIG_BLK_CGROUP is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_CGROUP_PIDS is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_CGROUP_PERF is not set ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++# CONFIG_NAMESPACES is not set ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++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 is not set ++CONFIG_SYSCTL_SYSCALL=y ++CONFIG_KALLSYMS=y ++CONFIG_KALLSYMS_ALL=y ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_PRINTK_NMI=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_PCI_QUIRKS=y ++CONFIG_MEMBARRIER=y ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++CONFIG_PERF_USE_VMALLOC=y ++ ++# ++# Kernel Performance Events And Counters ++# ++CONFIG_PERF_EVENTS=y ++# CONFIG_DEBUG_PERF_USE_VMALLOC is not set ++# CONFIG_VM_EVENT_COUNTERS is not set ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_SLAB_FREELIST_RANDOM is not set ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_SYSTEM_DATA_VERIFICATION is not set ++CONFIG_PROFILING=y ++CONFIG_OPROFILE=y ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_HW_BREAKPOINT=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_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_SLABINFO=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_MODULES_TREE_LOOKUP=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++CONFIG_BLK_MQ_PCI=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_LOCK_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# 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_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 ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_ARTPEC is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_DIGICOLOR is not set ++# CONFIG_ARCH_HIGHBANK is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++ ++# ++# Hisilicon BVT platform type ++# ++# CONFIG_ARCH_HI3516A is not set ++# CONFIG_ARCH_HI3536DV100 is not set ++# CONFIG_ARCH_HI3521A is not set ++CONFIG_ARCH_HI3531A=y ++CONFIG_HI_ZRELADDR=0x40008000 ++CONFIG_HI_PARAMS_PHYS=0x00000100 ++CONFIG_HI_INITRD_PHYS=0x00800000 ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TANGO is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQ is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=y ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_BPREDICT_DISABLE is not set ++CONFIG_KUSER_HELPERS=y ++CONFIG_VDSO=y ++CONFIG_OUTER_CACHE=y ++CONFIG_OUTER_CACHE_SYNC=y ++CONFIG_MIGHT_HAVE_CACHE_L2X0=y ++CONFIG_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0_PMU is not set ++# CONFIG_PL310_ERRATA_588369 is not set ++# CONFIG_PL310_ERRATA_727915 is not set ++# CONFIG_PL310_ERRATA_753970 is not set ++# CONFIG_PL310_ERRATA_769419 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_ARM_HEAVY_MB=y ++CONFIG_DEBUG_RODATA=y ++CONFIG_DEBUG_ALIGN_RODATA=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_643719 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_754327 is not set ++# CONFIG_ARM_ERRATA_764369 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_798181 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++# CONFIG_ARM_ERRATA_818325_852422 is not set ++# CONFIG_ARM_ERRATA_821420 is not set ++# CONFIG_ARM_ERRATA_825619 is not set ++# CONFIG_ARM_ERRATA_852421 is not set ++# CONFIG_ARM_ERRATA_852423 is not set ++ ++# ++# Bus support ++# ++CONFIG_PCI=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_PCI_DOMAINS_GENERIC=y ++CONFIG_PCI_SYSCALL=y ++CONFIG_PCIEPORTBUS=y ++CONFIG_PCIEAER=y ++# CONFIG_PCIE_ECRC is not set ++# CONFIG_PCIEAER_INJECT is not set ++CONFIG_PCIEASPM=y ++# CONFIG_PCIEASPM_DEBUG is not set ++CONFIG_PCIEASPM_DEFAULT=y ++# CONFIG_PCIEASPM_POWERSAVE is not set ++# CONFIG_PCIEASPM_PERFORMANCE is not set ++# CONFIG_PCIE_PME is not set ++# CONFIG_PCIE_DPC is not set ++# CONFIG_PCIE_PTM is not set ++# CONFIG_PCI_MSI is not set ++# CONFIG_PCI_DEBUG is not set ++# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set ++# CONFIG_PCI_STUB is not set ++# CONFIG_PCI_IOV is not set ++# CONFIG_PCI_PRI is not set ++# CONFIG_PCI_PASID is not set ++# CONFIG_HOTPLUG_PCI is not set ++ ++# ++# PCI host controller drivers ++# ++# CONFIG_PCI_HOST_GENERIC is not set ++# CONFIG_PCIE_ALTERA is not set ++CONFIG_HIPCIE=y ++ ++# ++# PCI Express configs ++# ++CONFIG_LIMIT_MAX_RD_REQ_SIZE=y ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++CONFIG_SMP=y ++CONFIG_SMP_ON_UP=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++# CONFIG_SCHED_MC is not set ++# CONFIG_SCHED_SMT is not set ++CONFIG_HAVE_ARM_SCU=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++# CONFIG_MCPM is not set ++# CONFIG_BIG_LITTLE is not set ++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_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_ARM_PSCI is not set ++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_THUMB2_KERNEL is not set ++CONFIG_ARM_PATCH_IDIV=y ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_HAVE_ARCH_PFN_VALID=y ++CONFIG_HIGHMEM=y ++# CONFIG_HIGHPTE is not set ++CONFIG_CPU_SW_DOMAIN_PAN=y ++CONFIG_HW_PERF_EVENTS=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_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# 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 ++# CONFIG_XEN 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# 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=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set ++ ++# ++# CPU frequency scaling drivers ++# ++CONFIG_CPUFREQ_DT=y ++CONFIG_CPUFREQ_DT_PLATDEV=y ++# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++# CONFIG_QORIQ_CPUFREQ 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_FPE_NWFPE=y ++# CONFIG_FPE_NWFPE_XP is not set ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_VFP=y ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++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=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_SUSPEND_SKIP_SYNC is not set ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++CONFIG_APM_EMULATION=y ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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_USER 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 is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++# CONFIG_NET_IP_TUNNEL is not set ++# CONFIG_IP_MROUTE is not set ++CONFIG_SYN_COOKIES=y ++# CONFIG_NET_UDP_TUNNEL is not set ++# CONFIG_NET_FOU 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 is not set ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++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=y ++# CONFIG_IPV6 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_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_IEEE802154 is not set ++# CONFIG_NET_SCHED is not set ++# CONFIG_DCB is not set ++# 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_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_SOCK_CGROUP_DATA is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_WEXT_CORE=y ++CONFIG_WEXT_PROC=y ++CONFIG_CFG80211=m ++# CONFIG_NL80211_TESTMODE is not set ++# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set ++# CONFIG_CFG80211_CERTIFICATION_ONUS is not set ++CONFIG_CFG80211_DEFAULT_PS=y ++# CONFIG_CFG80211_DEBUGFS is not set ++# CONFIG_CFG80211_INTERNAL_REGDB is not set ++CONFIG_CFG80211_CRDA_SUPPORT=y ++CONFIG_CFG80211_WEXT=y ++# CONFIG_LIB80211 is not set ++CONFIG_MAC80211=m ++CONFIG_MAC80211_HAS_RC=y ++CONFIG_MAC80211_RC_MINSTREL=y ++CONFIG_MAC80211_RC_MINSTREL_HT=y ++# CONFIG_MAC80211_RC_MINSTREL_VHT is not set ++CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y ++CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" ++CONFIG_MAC80211_MESH=y ++# CONFIG_MAC80211_DEBUGFS is not set ++# CONFIG_MAC80211_MESSAGE_TRACING is not set ++# CONFIG_MAC80211_DEBUG_MENU is not set ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL 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 is not set ++# CONFIG_NET_DEVLINK is not set ++CONFIG_MAY_USE_DEVLINK=y ++CONFIG_HAVE_CBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# CONFIG_DMA_SHARED_BUFFER is not set ++ ++# ++# Bus devices ++# ++# CONFIG_ARM_CCI400_PMU is not set ++# CONFIG_ARM_CCI5xx_PMU is not set ++# CONFIG_ARM_CCN is not set ++# 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_INTEL_VR_NOR is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_DATAFLASH is not set ++# CONFIG_MTD_M25P80 is not set ++# 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=y ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOCG3 is not set ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_PCI is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_RICOH is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++CONFIG_MTD_SPI_NAND_HISI_BVT=y ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++CONFIG_MTD_SPI_NAND_HIFMC100=y ++# 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 is not set ++# CONFIG_SPI_CADENCE_QUADSPI is not set ++CONFIG_SPI_HISI_SFC=y ++# CONFIG_MTD_SPI_IDS is not set ++# CONFIG_CLOSE_SPI_8PIN_4IO is not set ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++# 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_ADDRESS_PCI=y ++CONFIG_OF_IRQ=y ++CONFIG_OF_NET=y ++CONFIG_OF_MDIO=y ++CONFIG_OF_PCI=y ++CONFIG_OF_PCI_IRQ=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=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set ++# CONFIG_BLK_CPQ_CISS_DA is not set ++# CONFIG_BLK_DEV_DAC960 is not set ++# CONFIG_BLK_DEV_UMEM is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_SX8 is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_BLK_DEV_RSXX is not set ++# CONFIG_BLK_DEV_NVME is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# CONFIG_SENSORS_LIS3LV02D is not set ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_DUMMY_IRQ is not set ++# CONFIG_PHANTOM is not set ++# CONFIG_SGI_IOC4 is not set ++# CONFIG_TIFM_CORE is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_HP_ILO 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 ++# CONFIG_CB710_CORE is not set ++ ++# ++# Texas Instruments shared transport line discipline ++# ++# 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 ++CONFIG_HAVE_IDE=y ++# CONFIG_IDE is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++CONFIG_BLK_DEV_SR=y ++# CONFIG_BLK_DEV_SR_VENDOR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_SCSI_CXGB3_ISCSI is not set ++# CONFIG_SCSI_CXGB4_ISCSI is not set ++# CONFIG_SCSI_BNX2_ISCSI is not set ++# CONFIG_BE2ISCSI is not set ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_HPSA is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_3W_SAS is not set ++# CONFIG_SCSI_ACARD is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX is not set ++# CONFIG_SCSI_AIC79XX is not set ++# CONFIG_SCSI_AIC94XX is not set ++# CONFIG_SCSI_MVSAS is not set ++# CONFIG_SCSI_MVUMI is not set ++# CONFIG_SCSI_ADVANSYS is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_SCSI_ESAS2R is not set ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++# CONFIG_SCSI_MPT3SAS is not set ++# CONFIG_SCSI_MPT2SAS is not set ++# CONFIG_SCSI_SMARTPQI is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_SCSI_HPTIOP is not set ++# CONFIG_SCSI_SNIC is not set ++# CONFIG_SCSI_DMX3191D is not set ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_IPS is not set ++# CONFIG_SCSI_INITIO is not set ++# CONFIG_SCSI_INIA100 is not set ++# CONFIG_SCSI_STEX is not set ++# CONFIG_SCSI_SYM53C8XX_2 is not set ++# CONFIG_SCSI_IPR is not set ++# CONFIG_SCSI_QLOGIC_1280 is not set ++# CONFIG_SCSI_QLA_ISCSI is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_AM53C974 is not set ++# CONFIG_SCSI_NSP32 is not set ++# CONFIG_SCSI_WD719X is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_PMCRAID is not set ++# CONFIG_SCSI_PM8001 is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HISI_SATA=y ++CONFIG_HISI_SATA_IOBASE=0x11010000 ++CONFIG_HISI_SATA_FBS=1 ++CONFIG_HISI_SATA_NCQ=1 ++# CONFIG_HISI_ESATA is not set ++CONFIG_ATA=y ++# CONFIG_ATA_NONSTANDARD is not set ++CONFIG_ATA_VERBOSE_ERROR=y ++CONFIG_SATA_PMP=y ++ ++# ++# Controllers with non-SFF native interface ++# ++# CONFIG_SATA_AHCI is not set ++CONFIG_SATA_AHCI_PLATFORM=y ++# CONFIG_AHCI_CEVA is not set ++# CONFIG_AHCI_QORIQ is not set ++# CONFIG_SATA_INIC162X is not set ++# CONFIG_SATA_ACARD_AHCI is not set ++# CONFIG_SATA_SIL24 is not set ++# CONFIG_ATA_SFF is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++# CONFIG_FUSION is not set ++ ++# ++# IEEE 1394 (FireWire) support ++# ++# CONFIG_FIREWIRE is not set ++# CONFIG_FIREWIRE_NOSY is not set ++CONFIG_NETDEVICES=y ++CONFIG_NET_CORE=y ++# CONFIG_BONDING is not set ++# CONFIG_DUMMY is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC 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 ++# CONFIG_ARCNET is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++CONFIG_ETHERNET=y ++# CONFIG_NET_VENDOR_3COM is not set ++# CONFIG_NET_VENDOR_ADAPTEC is not set ++# CONFIG_NET_VENDOR_AGERE is not set ++# CONFIG_NET_VENDOR_ALTEON is not set ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_VENDOR_AMAZON is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_VENDOR_ARC is not set ++# CONFIG_NET_VENDOR_ATHEROS 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_BROCADE is not set ++# CONFIG_NET_VENDOR_CAVIUM is not set ++# CONFIG_NET_VENDOR_CHELSIO is not set ++# CONFIG_NET_VENDOR_CIRRUS is not set ++# CONFIG_NET_VENDOR_CISCO is not set ++# CONFIG_DM9000 is not set ++# CONFIG_DNET is not set ++# CONFIG_NET_VENDOR_DEC is not set ++# CONFIG_NET_VENDOR_DLINK is not set ++# CONFIG_NET_VENDOR_EMULEX is not set ++# CONFIG_NET_VENDOR_EZCHIP is not set ++# CONFIG_NET_VENDOR_EXAR is not set ++# CONFIG_NET_VENDOR_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# CONFIG_NET_VENDOR_HP is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_JME is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++# CONFIG_NET_VENDOR_MELLANOX is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_MICROCHIP is not set ++# CONFIG_NET_VENDOR_MYRI is not set ++# CONFIG_FEALNX is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NETRONOME is not set ++# CONFIG_NET_VENDOR_NVIDIA is not set ++# CONFIG_NET_VENDOR_OKI is not set ++# CONFIG_ETHOC is not set ++# CONFIG_NET_PACKET_ENGINE is not set ++# CONFIG_NET_VENDOR_QLOGIC is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++# CONFIG_NET_VENDOR_REALTEK is not set ++# CONFIG_NET_VENDOR_RENESAS is not set ++# CONFIG_NET_VENDOR_RDC 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_SILAN is not set ++# CONFIG_NET_VENDOR_SIS is not set ++# CONFIG_SFC is not set ++# CONFIG_NET_VENDOR_SMSC is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++# CONFIG_NET_VENDOR_SUN is not set ++# CONFIG_NET_VENDOR_SYNOPSYS is not set ++# CONFIG_NET_VENDOR_TEHUTI is not set ++# CONFIG_NET_VENDOR_TI is not set ++# CONFIG_NET_VENDOR_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_FDDI is not set ++# CONFIG_HIPPI is not set ++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_MMIOREG is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++ ++# ++# 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_IPHETH is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_VMXNET3 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_APMPOWER is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INPUT_CM109 is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_USERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_NOZOMI 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_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# 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_JSM is not set ++# CONFIG_SERIAL_SCCNXP is not set ++# CONFIG_SERIAL_SC16IS7XX is not set ++# CONFIG_SERIAL_BCM63XX is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++# CONFIG_SERIAL_ARC is not set ++# CONFIG_SERIAL_RP2 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_APPLICOM is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_DEVPORT=y ++# CONFIG_XILLYBUS is not set ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_COMPAT=y ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_MUX is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# PC SMBus host controller drivers ++# ++# CONFIG_I2C_ALI1535 is not set ++# CONFIG_I2C_ALI1563 is not set ++# CONFIG_I2C_ALI15X3 is not set ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++# CONFIG_I2C_I801 is not set ++# CONFIG_I2C_ISCH is not set ++# CONFIG_I2C_PIIX4 is not set ++# CONFIG_I2C_NFORCE2 is not set ++# CONFIG_I2C_SIS5595 is not set ++# CONFIG_I2C_SIS630 is not set ++# CONFIG_I2C_SIS96X is not set ++# CONFIG_I2C_VIA is not set ++# CONFIG_I2C_VIAPRO is not set ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_DESIGNWARE_PCI is not set ++# CONFIG_I2C_EMEV2 is not set ++# CONFIG_I2C_HIBVT is not set ++# CONFIG_I2C_NOMADIK 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_HISI=y ++# 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_DEBUG is not set ++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_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# CONFIG_SPI_PXA2XX 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=y ++# 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++# CONFIG_GPIOLIB is not set ++# 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++CONFIG_POWER_RESET_SYSCON=y ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_APM_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_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_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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_LPC_ICH is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_MFD_JANZ_CMODIO 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_RDC321X is not set ++# CONFIG_MFD_RTSX_PCI 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=y ++# 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_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_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_VX855 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 ++ ++# ++# Graphics support ++# ++CONFIG_VGA_ARB=y ++CONFIG_VGA_ARB_MAX_GPUS=16 ++# CONFIG_IMX_IPUV3_CORE is not set ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_CIRRUS is not set ++# CONFIG_FB_PM2 is not set ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_NVIDIA is not set ++# CONFIG_FB_RIVA is not set ++# CONFIG_FB_I740 is not set ++# CONFIG_FB_MATROX is not set ++# CONFIG_FB_RADEON is not set ++# CONFIG_FB_ATY128 is not set ++# CONFIG_FB_ATY is not set ++# CONFIG_FB_S3 is not set ++# CONFIG_FB_SAVAGE is not set ++# CONFIG_FB_SIS is not set ++# CONFIG_FB_NEOMAGIC is not set ++# CONFIG_FB_KYRO is not set ++# CONFIG_FB_3DFX is not set ++# CONFIG_FB_VOODOO1 is not set ++# CONFIG_FB_VT8623 is not set ++# CONFIG_FB_TRIDENT is not set ++# CONFIG_FB_ARK is not set ++# CONFIG_FB_PM3 is not set ++# CONFIG_FB_CARMINE is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_MB862XX is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SM712 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++# CONFIG_HID_A4TECH is not set ++# CONFIG_HID_ACRUX is not set ++# CONFIG_HID_APPLE is not set ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++# CONFIG_HID_BELKIN is not set ++# CONFIG_HID_BETOP_FF is not set ++# CONFIG_HID_CHERRY is not set ++# CONFIG_HID_CHICONY is not set ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CYPRESS is not set ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++# CONFIG_HID_EZKEY is not set ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++# CONFIG_HID_KENSINGTON is not set ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++# CONFIG_HID_LOGITECH is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++# CONFIG_HID_MONTEREY is not set ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# 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 is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PCI=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_EHCI_HCD=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_PCI=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# 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=y ++CONFIG_USB_OHCI_HCD_PCI=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# CONFIG_USB_UHCI_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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_SISUSBVGA 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_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 is not set ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_INFINIBAND is not set ++CONFIG_EDAC_ATOMIC_SCRUB=y ++CONFIG_EDAC_SUPPORT=y ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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_PCI is not set ++# 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_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++CONFIG_COMMON_CLK_HI3531A=y ++CONFIG_RESET_HISI=y ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set ++CONFIG_ARM_TIMER_SP804=y ++CONFIG_TIMER_HISP804=y ++# 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_NTB is not set ++# CONFIG_VME_BUS is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_ZYNQ is not set ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# 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_PHY_HISI_SATA=y ++CONFIG_HISI_SATA_MODE=1 ++CONFIG_PHY_HISI_USB2=y ++CONFIG_PHY_HISI_USB3=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++ ++# ++# Performance monitor support ++# ++CONFIG_ARM_PMU=y ++CONFIG_RAS=y ++# CONFIG_THUNDERBOLT 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 ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# Firmware Drivers ++# ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++CONFIG_FS_IOMAP=y ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT2=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_CHECK=y ++CONFIG_REISERFS_PROC_INFO=y ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_DEBUG=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++CONFIG_XFS_DEBUG=y ++# CONFIG_GFS2_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=y ++CONFIG_EXPORTFS=y ++# 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=y ++# CONFIG_QUOTA_NETLINK_INTERFACE is not set ++CONFIG_PRINT_QUOTA_WARNING=y ++# CONFIG_QUOTA_DEBUG is not set ++CONFIG_QUOTA_TREE=m ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_QUOTACTL=y ++CONFIG_AUTOFS4_FS=m ++CONFIG_FUSE_FS=y ++# CONFIG_CUSE is not set ++# CONFIG_OVERLAY_FS is not set ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=y ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++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=y ++CONFIG_TMPFS_XATTR=y ++# 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_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++# 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFSD is not set ++CONFIG_GRACE_PERIOD=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=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=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=y ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++# 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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++# CONFIG_DYNAMIC_DEBUG is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++CONFIG_ENABLE_WARN_DEPRECATED=y ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_WQ_WATCHDOG is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHED_INFO is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++# CONFIG_DEBUG_BUGVERBOSE is not set ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS 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_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_RCU_TRACE is not set ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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_TRACE_CLOCK=y ++CONFIG_RING_BUFFER=y ++CONFIG_RING_BUFFER_ALLOW_SWAP=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_UPROBE_EVENT is not set ++# CONFIG_PROBE_EVENTS is not set ++# CONFIG_TRACEPOINT_BENCHMARK is not set ++# CONFIG_RING_BUFFER_BENCHMARK is not set ++# CONFIG_RING_BUFFER_STARTUP_TEST is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_LKDTM is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set ++# CONFIG_UBSAN is not set ++CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y ++CONFIG_STRICT_DEVMEM=y ++# CONFIG_IO_STRICT_DEVMEM is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL 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 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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=m ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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=m ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++CONFIG_CRYPTO_GF128MUL=m ++CONFIG_CRYPTO_NULL=m ++CONFIG_CRYPTO_NULL2=y ++# CONFIG_CRYPTO_PCRYPT is not set ++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=m ++CONFIG_CRYPTO_GCM=m ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# 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=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++CONFIG_CRYPTO_GHASH=m ++# CONFIG_CRYPTO_POLY1305 is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=y ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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=m ++# 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=m ++# 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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_CRYPTO_DEV_HIFN_795X 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=y ++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=y ++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=m ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_GLOB=y ++# CONFIG_GLOB_SELFTEST is not set ++CONFIG_NLATTR=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=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3531a_spinand_slave_defconfig b/arch/arm/configs/hi3531a_spinand_slave_defconfig +new file mode 100644 +index 0000000..fdb11b7 +--- /dev/null ++++ b/arch/arm/configs/hi3531a_spinand_slave_defconfig +@@ -0,0 +1,2914 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 4.9.37 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_NEED_MACH_IO_H=y ++CONFIG_GENERIC_BUG=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_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++# CONFIG_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++CONFIG_FHANDLE=y ++CONFIG_USELIB=y ++# CONFIG_AUDIT is not set ++ ++# ++# 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_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++# CONFIG_IRQ_DOMAIN_DEBUG is not set ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_HZ_PERIODIC=y ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NO_HZ_FULL 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_TREE_RCU=y ++# CONFIG_RCU_EXPERT is not set ++CONFIG_SRCU=y ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++# 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=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_NMI_LOG_BUF_SHIFT=13 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_MEMCG is not set ++# CONFIG_BLK_CGROUP is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_CGROUP_PIDS is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_CGROUP_PERF is not set ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++# CONFIG_NAMESPACES is not set ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++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 is not set ++CONFIG_SYSCTL_SYSCALL=y ++CONFIG_KALLSYMS=y ++CONFIG_KALLSYMS_ALL=y ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_PRINTK_NMI=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_PCI_QUIRKS=y ++CONFIG_MEMBARRIER=y ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++CONFIG_PERF_USE_VMALLOC=y ++ ++# ++# Kernel Performance Events And Counters ++# ++CONFIG_PERF_EVENTS=y ++# CONFIG_DEBUG_PERF_USE_VMALLOC is not set ++# CONFIG_VM_EVENT_COUNTERS is not set ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_SLAB_FREELIST_RANDOM is not set ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_SYSTEM_DATA_VERIFICATION is not set ++CONFIG_PROFILING=y ++CONFIG_OPROFILE=y ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_HW_BREAKPOINT=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_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_SLABINFO=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_MODULES_TREE_LOOKUP=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++CONFIG_BLK_MQ_PCI=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_LOCK_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# 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_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 ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_ARTPEC is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_DIGICOLOR is not set ++# CONFIG_ARCH_HIGHBANK is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++ ++# ++# Hisilicon BVT platform type ++# ++# CONFIG_ARCH_HI3516A is not set ++# CONFIG_ARCH_HI3536DV100 is not set ++# CONFIG_ARCH_HI3521A is not set ++CONFIG_ARCH_HI3531A=y ++CONFIG_HI_ZRELADDR=0x40008000 ++CONFIG_HI_PARAMS_PHYS=0x00000100 ++CONFIG_HI_INITRD_PHYS=0x00800000 ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TANGO is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQ is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=y ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_BPREDICT_DISABLE is not set ++CONFIG_KUSER_HELPERS=y ++CONFIG_VDSO=y ++CONFIG_OUTER_CACHE=y ++CONFIG_OUTER_CACHE_SYNC=y ++CONFIG_MIGHT_HAVE_CACHE_L2X0=y ++CONFIG_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0_PMU is not set ++# CONFIG_PL310_ERRATA_588369 is not set ++# CONFIG_PL310_ERRATA_727915 is not set ++# CONFIG_PL310_ERRATA_753970 is not set ++# CONFIG_PL310_ERRATA_769419 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_ARM_HEAVY_MB=y ++CONFIG_DEBUG_RODATA=y ++CONFIG_DEBUG_ALIGN_RODATA=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_643719 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_754327 is not set ++# CONFIG_ARM_ERRATA_764369 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_798181 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++# CONFIG_ARM_ERRATA_818325_852422 is not set ++# CONFIG_ARM_ERRATA_821420 is not set ++# CONFIG_ARM_ERRATA_825619 is not set ++# CONFIG_ARM_ERRATA_852421 is not set ++# CONFIG_ARM_ERRATA_852423 is not set ++ ++# ++# Bus support ++# ++CONFIG_PCI=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_PCI_DOMAINS_GENERIC=y ++CONFIG_PCI_SYSCALL=y ++CONFIG_PCIEPORTBUS=y ++CONFIG_PCIEAER=y ++# CONFIG_PCIE_ECRC is not set ++# CONFIG_PCIEAER_INJECT is not set ++CONFIG_PCIEASPM=y ++# CONFIG_PCIEASPM_DEBUG is not set ++CONFIG_PCIEASPM_DEFAULT=y ++# CONFIG_PCIEASPM_POWERSAVE is not set ++# CONFIG_PCIEASPM_PERFORMANCE is not set ++# CONFIG_PCIE_PME is not set ++# CONFIG_PCIE_DPC is not set ++# CONFIG_PCIE_PTM is not set ++# CONFIG_PCI_MSI is not set ++# CONFIG_PCI_DEBUG is not set ++# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set ++# CONFIG_PCI_STUB is not set ++# CONFIG_PCI_IOV is not set ++# CONFIG_PCI_PRI is not set ++# CONFIG_PCI_PASID is not set ++# CONFIG_HOTPLUG_PCI is not set ++ ++# ++# PCI host controller drivers ++# ++# CONFIG_PCI_HOST_GENERIC is not set ++# CONFIG_PCIE_ALTERA is not set ++# CONFIG_HIPCIE is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++CONFIG_SMP=y ++CONFIG_SMP_ON_UP=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++# CONFIG_SCHED_MC is not set ++# CONFIG_SCHED_SMT is not set ++CONFIG_HAVE_ARM_SCU=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++# CONFIG_MCPM is not set ++# CONFIG_BIG_LITTLE is not set ++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_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_ARM_PSCI is not set ++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_THUMB2_KERNEL is not set ++CONFIG_ARM_PATCH_IDIV=y ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_HAVE_ARCH_PFN_VALID=y ++CONFIG_HIGHMEM=y ++# CONFIG_HIGHPTE is not set ++CONFIG_CPU_SW_DOMAIN_PAN=y ++CONFIG_HW_PERF_EVENTS=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_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# 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 ++# CONFIG_XEN 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# 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=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set ++ ++# ++# CPU frequency scaling drivers ++# ++CONFIG_CPUFREQ_DT=y ++CONFIG_CPUFREQ_DT_PLATDEV=y ++# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++# CONFIG_QORIQ_CPUFREQ 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_FPE_NWFPE=y ++# CONFIG_FPE_NWFPE_XP is not set ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_VFP=y ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++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=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_SUSPEND_SKIP_SYNC is not set ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++CONFIG_APM_EMULATION=y ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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_USER 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 is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++# CONFIG_NET_IP_TUNNEL is not set ++# CONFIG_IP_MROUTE is not set ++CONFIG_SYN_COOKIES=y ++# CONFIG_NET_UDP_TUNNEL is not set ++# CONFIG_NET_FOU 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 is not set ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++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=y ++# CONFIG_IPV6 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_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_IEEE802154 is not set ++# CONFIG_NET_SCHED is not set ++# CONFIG_DCB is not set ++# 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_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_SOCK_CGROUP_DATA is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_WEXT_CORE=y ++CONFIG_WEXT_PROC=y ++CONFIG_CFG80211=m ++# CONFIG_NL80211_TESTMODE is not set ++# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set ++# CONFIG_CFG80211_CERTIFICATION_ONUS is not set ++CONFIG_CFG80211_DEFAULT_PS=y ++# CONFIG_CFG80211_DEBUGFS is not set ++# CONFIG_CFG80211_INTERNAL_REGDB is not set ++CONFIG_CFG80211_CRDA_SUPPORT=y ++CONFIG_CFG80211_WEXT=y ++# CONFIG_LIB80211 is not set ++CONFIG_MAC80211=m ++CONFIG_MAC80211_HAS_RC=y ++CONFIG_MAC80211_RC_MINSTREL=y ++CONFIG_MAC80211_RC_MINSTREL_HT=y ++# CONFIG_MAC80211_RC_MINSTREL_VHT is not set ++CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y ++CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" ++CONFIG_MAC80211_MESH=y ++# CONFIG_MAC80211_DEBUGFS is not set ++# CONFIG_MAC80211_MESSAGE_TRACING is not set ++# CONFIG_MAC80211_DEBUG_MENU is not set ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL 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 is not set ++# CONFIG_NET_DEVLINK is not set ++CONFIG_MAY_USE_DEVLINK=y ++CONFIG_HAVE_CBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# CONFIG_DMA_SHARED_BUFFER is not set ++ ++# ++# Bus devices ++# ++# CONFIG_ARM_CCI400_PMU is not set ++# CONFIG_ARM_CCI5xx_PMU is not set ++# CONFIG_ARM_CCN is not set ++# 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_INTEL_VR_NOR is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_DATAFLASH is not set ++# CONFIG_MTD_M25P80 is not set ++# 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=y ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOCG3 is not set ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_PCI is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_RICOH is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++CONFIG_MTD_SPI_NAND_HISI_BVT=y ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++CONFIG_MTD_SPI_NAND_HIFMC100=y ++# 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 is not set ++# CONFIG_SPI_CADENCE_QUADSPI is not set ++CONFIG_SPI_HISI_SFC=y ++# CONFIG_MTD_SPI_IDS is not set ++# CONFIG_CLOSE_SPI_8PIN_4IO is not set ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++# 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_ADDRESS_PCI=y ++CONFIG_OF_IRQ=y ++CONFIG_OF_NET=y ++CONFIG_OF_MDIO=y ++CONFIG_OF_PCI=y ++CONFIG_OF_PCI_IRQ=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=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set ++# CONFIG_BLK_CPQ_CISS_DA is not set ++# CONFIG_BLK_DEV_DAC960 is not set ++# CONFIG_BLK_DEV_UMEM is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_SX8 is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_BLK_DEV_RSXX is not set ++# CONFIG_BLK_DEV_NVME is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# CONFIG_SENSORS_LIS3LV02D is not set ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_DUMMY_IRQ is not set ++# CONFIG_PHANTOM is not set ++# CONFIG_SGI_IOC4 is not set ++# CONFIG_TIFM_CORE is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_HP_ILO 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 ++# CONFIG_CB710_CORE is not set ++ ++# ++# Texas Instruments shared transport line discipline ++# ++# 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 ++CONFIG_HAVE_IDE=y ++# CONFIG_IDE is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++CONFIG_BLK_DEV_SR=y ++# CONFIG_BLK_DEV_SR_VENDOR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_SCSI_CXGB3_ISCSI is not set ++# CONFIG_SCSI_CXGB4_ISCSI is not set ++# CONFIG_SCSI_BNX2_ISCSI is not set ++# CONFIG_BE2ISCSI is not set ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_HPSA is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_3W_SAS is not set ++# CONFIG_SCSI_ACARD is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX is not set ++# CONFIG_SCSI_AIC79XX is not set ++# CONFIG_SCSI_AIC94XX is not set ++# CONFIG_SCSI_MVSAS is not set ++# CONFIG_SCSI_MVUMI is not set ++# CONFIG_SCSI_ADVANSYS is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_SCSI_ESAS2R is not set ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++# CONFIG_SCSI_MPT3SAS is not set ++# CONFIG_SCSI_MPT2SAS is not set ++# CONFIG_SCSI_SMARTPQI is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_SCSI_HPTIOP is not set ++# CONFIG_SCSI_SNIC is not set ++# CONFIG_SCSI_DMX3191D is not set ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_IPS is not set ++# CONFIG_SCSI_INITIO is not set ++# CONFIG_SCSI_INIA100 is not set ++# CONFIG_SCSI_STEX is not set ++# CONFIG_SCSI_SYM53C8XX_2 is not set ++# CONFIG_SCSI_IPR is not set ++# CONFIG_SCSI_QLOGIC_1280 is not set ++# CONFIG_SCSI_QLA_ISCSI is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_AM53C974 is not set ++# CONFIG_SCSI_NSP32 is not set ++# CONFIG_SCSI_WD719X is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_PMCRAID is not set ++# CONFIG_SCSI_PM8001 is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HISI_SATA=y ++CONFIG_HISI_SATA_IOBASE=0x11010000 ++CONFIG_HISI_SATA_FBS=1 ++CONFIG_HISI_SATA_NCQ=1 ++# CONFIG_HISI_ESATA is not set ++CONFIG_ATA=y ++# CONFIG_ATA_NONSTANDARD is not set ++CONFIG_ATA_VERBOSE_ERROR=y ++CONFIG_SATA_PMP=y ++ ++# ++# Controllers with non-SFF native interface ++# ++# CONFIG_SATA_AHCI is not set ++CONFIG_SATA_AHCI_PLATFORM=y ++# CONFIG_AHCI_CEVA is not set ++# CONFIG_AHCI_QORIQ is not set ++# CONFIG_SATA_INIC162X is not set ++# CONFIG_SATA_ACARD_AHCI is not set ++# CONFIG_SATA_SIL24 is not set ++# CONFIG_ATA_SFF is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++# CONFIG_FUSION is not set ++ ++# ++# IEEE 1394 (FireWire) support ++# ++# CONFIG_FIREWIRE is not set ++# CONFIG_FIREWIRE_NOSY is not set ++CONFIG_NETDEVICES=y ++CONFIG_NET_CORE=y ++# CONFIG_BONDING is not set ++# CONFIG_DUMMY is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC 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 ++# CONFIG_ARCNET is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++CONFIG_ETHERNET=y ++CONFIG_NET_VENDOR_3COM=y ++# CONFIG_VORTEX is not set ++# CONFIG_TYPHOON is not set ++CONFIG_NET_VENDOR_ADAPTEC=y ++# CONFIG_ADAPTEC_STARFIRE is not set ++CONFIG_NET_VENDOR_AGERE=y ++# CONFIG_ET131X is not set ++CONFIG_NET_VENDOR_ALTEON=y ++# CONFIG_ACENIC is not set ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_VENDOR_AMAZON is not set ++CONFIG_NET_VENDOR_AMD=y ++# CONFIG_AMD8111_ETH is not set ++# CONFIG_PCNET32 is not set ++# CONFIG_NET_VENDOR_ARC is not set ++CONFIG_NET_VENDOR_ATHEROS=y ++# CONFIG_ATL2 is not set ++# CONFIG_ATL1 is not set ++# CONFIG_ATL1E is not set ++# CONFIG_ATL1C is not set ++# CONFIG_ALX 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_BROCADE=y ++# CONFIG_BNA is not set ++CONFIG_NET_VENDOR_CAVIUM=y ++CONFIG_NET_VENDOR_CHELSIO=y ++# CONFIG_CHELSIO_T1 is not set ++# CONFIG_CHELSIO_T3 is not set ++# CONFIG_CHELSIO_T4 is not set ++# CONFIG_CHELSIO_T4VF is not set ++# CONFIG_NET_VENDOR_CIRRUS is not set ++CONFIG_NET_VENDOR_CISCO=y ++# CONFIG_ENIC is not set ++# CONFIG_DM9000 is not set ++# CONFIG_DNET is not set ++CONFIG_NET_VENDOR_DEC=y ++# CONFIG_NET_TULIP is not set ++CONFIG_NET_VENDOR_DLINK=y ++# CONFIG_DL2K is not set ++# CONFIG_SUNDANCE is not set ++CONFIG_NET_VENDOR_EMULEX=y ++# CONFIG_BE2NET is not set ++# CONFIG_NET_VENDOR_EZCHIP is not set ++CONFIG_NET_VENDOR_EXAR=y ++# CONFIG_S2IO is not set ++# CONFIG_VXGE is not set ++# CONFIG_NET_VENDOR_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++CONFIG_NET_VENDOR_HP=y ++# CONFIG_HP100 is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_JME is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++CONFIG_NET_VENDOR_MELLANOX=y ++# CONFIG_MLX4_EN is not set ++# CONFIG_MLX4_CORE is not set ++# CONFIG_MLX5_CORE is not set ++# CONFIG_MLXSW_CORE is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_MICROCHIP is not set ++CONFIG_NET_VENDOR_MYRI=y ++# CONFIG_MYRI10GE is not set ++# CONFIG_FEALNX is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NETRONOME is not set ++CONFIG_NET_VENDOR_NVIDIA=y ++# CONFIG_FORCEDETH is not set ++CONFIG_NET_VENDOR_OKI=y ++# CONFIG_ETHOC is not set ++CONFIG_NET_PACKET_ENGINE=y ++# CONFIG_HAMACHI is not set ++# CONFIG_YELLOWFIN is not set ++CONFIG_NET_VENDOR_QLOGIC=y ++# CONFIG_QLA3XXX is not set ++# CONFIG_QLCNIC is not set ++# CONFIG_QLGE is not set ++# CONFIG_NETXEN_NIC is not set ++# CONFIG_QED is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++CONFIG_NET_VENDOR_REALTEK=y ++# CONFIG_8139CP is not set ++# CONFIG_8139TOO is not set ++# CONFIG_R8169 is not set ++# CONFIG_NET_VENDOR_RENESAS is not set ++CONFIG_NET_VENDOR_RDC=y ++# CONFIG_R6040 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_SILAN=y ++# CONFIG_SC92031 is not set ++CONFIG_NET_VENDOR_SIS=y ++# CONFIG_SIS900 is not set ++# CONFIG_SIS190 is not set ++# CONFIG_SFC is not set ++# CONFIG_NET_VENDOR_SMSC is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++CONFIG_NET_VENDOR_SUN=y ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++# CONFIG_NIU is not set ++# CONFIG_NET_VENDOR_SYNOPSYS is not set ++CONFIG_NET_VENDOR_TEHUTI=y ++# CONFIG_TEHUTI is not set ++CONFIG_NET_VENDOR_TI=y ++# CONFIG_TI_CPSW_ALE is not set ++# CONFIG_TLAN is not set ++# CONFIG_NET_VENDOR_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_FDDI is not set ++# CONFIG_HIPPI is not set ++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_MMIOREG is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++ ++# ++# 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_IPHETH is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_VMXNET3 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_APMPOWER is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INPUT_CM109 is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_USERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_NOZOMI 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_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# 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_JSM is not set ++# CONFIG_SERIAL_SCCNXP is not set ++# CONFIG_SERIAL_SC16IS7XX is not set ++# CONFIG_SERIAL_BCM63XX is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++# CONFIG_SERIAL_ARC is not set ++# CONFIG_SERIAL_RP2 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_APPLICOM is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_DEVPORT=y ++# CONFIG_XILLYBUS is not set ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_COMPAT=y ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_MUX is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# PC SMBus host controller drivers ++# ++# CONFIG_I2C_ALI1535 is not set ++# CONFIG_I2C_ALI1563 is not set ++# CONFIG_I2C_ALI15X3 is not set ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++# CONFIG_I2C_I801 is not set ++# CONFIG_I2C_ISCH is not set ++# CONFIG_I2C_PIIX4 is not set ++# CONFIG_I2C_NFORCE2 is not set ++# CONFIG_I2C_SIS5595 is not set ++# CONFIG_I2C_SIS630 is not set ++# CONFIG_I2C_SIS96X is not set ++# CONFIG_I2C_VIA is not set ++# CONFIG_I2C_VIAPRO is not set ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_DESIGNWARE_PCI is not set ++# CONFIG_I2C_EMEV2 is not set ++# CONFIG_I2C_HIBVT is not set ++# CONFIG_I2C_NOMADIK 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_HISI=y ++# 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_DEBUG is not set ++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_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# CONFIG_SPI_PXA2XX 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=y ++# 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++# CONFIG_GPIOLIB is not set ++# 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++CONFIG_POWER_RESET_SYSCON=y ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_APM_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_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_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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_LPC_ICH is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_MFD_JANZ_CMODIO 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_RDC321X is not set ++# CONFIG_MFD_RTSX_PCI 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=y ++# 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_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_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_VX855 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 ++ ++# ++# Graphics support ++# ++CONFIG_VGA_ARB=y ++CONFIG_VGA_ARB_MAX_GPUS=16 ++# CONFIG_IMX_IPUV3_CORE is not set ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_CIRRUS is not set ++# CONFIG_FB_PM2 is not set ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_NVIDIA is not set ++# CONFIG_FB_RIVA is not set ++# CONFIG_FB_I740 is not set ++# CONFIG_FB_MATROX is not set ++# CONFIG_FB_RADEON is not set ++# CONFIG_FB_ATY128 is not set ++# CONFIG_FB_ATY is not set ++# CONFIG_FB_S3 is not set ++# CONFIG_FB_SAVAGE is not set ++# CONFIG_FB_SIS is not set ++# CONFIG_FB_NEOMAGIC is not set ++# CONFIG_FB_KYRO is not set ++# CONFIG_FB_3DFX is not set ++# CONFIG_FB_VOODOO1 is not set ++# CONFIG_FB_VT8623 is not set ++# CONFIG_FB_TRIDENT is not set ++# CONFIG_FB_ARK is not set ++# CONFIG_FB_PM3 is not set ++# CONFIG_FB_CARMINE is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_MB862XX is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SM712 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++# CONFIG_HID_A4TECH is not set ++# CONFIG_HID_ACRUX is not set ++# CONFIG_HID_APPLE is not set ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++# CONFIG_HID_BELKIN is not set ++# CONFIG_HID_BETOP_FF is not set ++# CONFIG_HID_CHERRY is not set ++# CONFIG_HID_CHICONY is not set ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CYPRESS is not set ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++# CONFIG_HID_EZKEY is not set ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++# CONFIG_HID_KENSINGTON is not set ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++# CONFIG_HID_LOGITECH is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++# CONFIG_HID_MONTEREY is not set ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# 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 is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PCI=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_EHCI_HCD=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_PCI=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# 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=y ++CONFIG_USB_OHCI_HCD_PCI=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# CONFIG_USB_UHCI_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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_SISUSBVGA 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_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 is not set ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_INFINIBAND is not set ++CONFIG_EDAC_ATOMIC_SCRUB=y ++CONFIG_EDAC_SUPPORT=y ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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_PCI is not set ++# 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_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++CONFIG_COMMON_CLK_HI3531A=y ++CONFIG_RESET_HISI=y ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set ++CONFIG_ARM_TIMER_SP804=y ++CONFIG_TIMER_HISP804=y ++# 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_NTB is not set ++# CONFIG_VME_BUS is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_ZYNQ is not set ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# 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_PHY_HISI_SATA=y ++CONFIG_HISI_SATA_MODE=1 ++CONFIG_PHY_HISI_USB2=y ++CONFIG_PHY_HISI_USB3=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++ ++# ++# Performance monitor support ++# ++CONFIG_ARM_PMU=y ++CONFIG_RAS=y ++# CONFIG_THUNDERBOLT 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 ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# Firmware Drivers ++# ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++CONFIG_FS_IOMAP=y ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT2=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_CHECK=y ++CONFIG_REISERFS_PROC_INFO=y ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_DEBUG=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++CONFIG_XFS_DEBUG=y ++# CONFIG_GFS2_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=y ++CONFIG_EXPORTFS=y ++# 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=y ++# CONFIG_QUOTA_NETLINK_INTERFACE is not set ++CONFIG_PRINT_QUOTA_WARNING=y ++# CONFIG_QUOTA_DEBUG is not set ++CONFIG_QUOTA_TREE=m ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_QUOTACTL=y ++CONFIG_AUTOFS4_FS=m ++CONFIG_FUSE_FS=y ++# CONFIG_CUSE is not set ++# CONFIG_OVERLAY_FS is not set ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=y ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++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=y ++CONFIG_TMPFS_XATTR=y ++# 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_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++# 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFSD is not set ++CONFIG_GRACE_PERIOD=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=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=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=y ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++# 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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++# CONFIG_DYNAMIC_DEBUG is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++CONFIG_ENABLE_WARN_DEPRECATED=y ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_WQ_WATCHDOG is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHED_INFO is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++# CONFIG_DEBUG_BUGVERBOSE is not set ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS 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_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_RCU_TRACE is not set ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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_TRACE_CLOCK=y ++CONFIG_RING_BUFFER=y ++CONFIG_RING_BUFFER_ALLOW_SWAP=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_UPROBE_EVENT is not set ++# CONFIG_PROBE_EVENTS is not set ++# CONFIG_TRACEPOINT_BENCHMARK is not set ++# CONFIG_RING_BUFFER_BENCHMARK is not set ++# CONFIG_RING_BUFFER_STARTUP_TEST is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_LKDTM is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set ++# CONFIG_UBSAN is not set ++CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y ++CONFIG_STRICT_DEVMEM=y ++# CONFIG_IO_STRICT_DEVMEM is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL 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 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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=m ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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=m ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++CONFIG_CRYPTO_GF128MUL=m ++CONFIG_CRYPTO_NULL=m ++CONFIG_CRYPTO_NULL2=y ++# CONFIG_CRYPTO_PCRYPT is not set ++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=m ++CONFIG_CRYPTO_GCM=m ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# 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=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++CONFIG_CRYPTO_GHASH=m ++# CONFIG_CRYPTO_POLY1305 is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=y ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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=m ++# 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=m ++# 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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_CRYPTO_DEV_HIFN_795X 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=y ++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=y ++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=m ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_GLOB=y ++# CONFIG_GLOB_SELFTEST is not set ++CONFIG_NLATTR=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=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3536dv100_full_defconfig b/arch/arm/configs/hi3536dv100_full_defconfig +new file mode 100644 +index 0000000..18b52e9 +--- /dev/null ++++ b/arch/arm/configs/hi3536dv100_full_defconfig +@@ -0,0 +1,2722 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 4.9.37 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_GENERIC_BUG=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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++CONFIG_FHANDLE=y ++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_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=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=17 ++CONFIG_NMI_LOG_BUF_SHIFT=13 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_MEMCG is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CGROUP_SCHED is not set ++# CONFIG_CGROUP_PIDS is not set ++CONFIG_CGROUP_FREEZER=y ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++CONFIG_RD_LZ4=y ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++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_ALL is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_PRINTK_NMI=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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=y ++CONFIG_SLUB_DEBUG=y ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# 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 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_ARCH_HAS_GCOV_PROFILE_ALL=y ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# 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_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 ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_ARTPEC is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_DIGICOLOR is not set ++# CONFIG_ARCH_HIGHBANK is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++ ++# ++# Hisilicon BVT platform type ++# ++# CONFIG_ARCH_HI3516A is not set ++CONFIG_ARCH_HI3536DV100=y ++CONFIG_HI_ZRELADDR=0x80008000 ++CONFIG_HI_PARAMS_PHYS=0x00000100 ++CONFIG_HI_INITRD_PHYS=0x00800000 ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TANGO is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQ is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++# CONFIG_SWP_EMULATE is not set ++# 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_VDSO=y ++CONFIG_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++# CONFIG_DEBUG_RODATA is not set ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++# CONFIG_ARM_ERRATA_818325_852422 is not set ++# CONFIG_ARM_ERRATA_821420 is not set ++# CONFIG_ARM_ERRATA_825619 is not set ++# CONFIG_ARM_ERRATA_852421 is not set ++# CONFIG_ARM_ERRATA_852423 is not set ++ ++# ++# Bus support ++# ++# CONFIG_PCI is not set ++# CONFIG_PCI_DOMAINS_GENERIC is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++# CONFIG_SMP is not set ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++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_ARM_PSCI is not set ++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_THUMB2_KERNEL is not set ++CONFIG_ARM_PATCH_IDIV=y ++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 is not set ++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_FRONTSWAP 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 ++# CONFIG_XEN 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++# CONFIG_KERNEL_MODE_NEON is not set ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=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=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HIBERNATION=y ++CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++CONFIG_PM_DEBUG=y ++# CONFIG_PM_ADVANCED_DEBUG is not set ++# CONFIG_PM_TEST_SUSPEND is not set ++CONFIG_PM_SLEEP_DEBUG=y ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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_ALGO=y ++CONFIG_XFRM_USER=y ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++CONFIG_NET_KEY=y ++# CONFIG_NET_KEY_MIGRATE is not set ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++# CONFIG_IP_FIB_TRIE_STATS is not set ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++# CONFIG_IP_PNP_DHCP is not set ++# 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 is not set ++CONFIG_IP_MROUTE=y ++# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_SYN_COOKIES=y ++# CONFIG_NET_UDP_TUNNEL is not set ++# CONFIG_NET_FOU 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 is not set ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++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=y ++CONFIG_TCP_CONG_BIC=m ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_TCP_CONG_WESTWOOD=m ++CONFIG_TCP_CONG_HTCP=m ++# CONFIG_TCP_CONG_HSTCP is not set ++# CONFIG_TCP_CONG_HYBLA is not set ++# CONFIG_TCP_CONG_VEGAS is not set ++# CONFIG_TCP_CONG_NV is not set ++# CONFIG_TCP_CONG_SCALABLE is not set ++# CONFIG_TCP_CONG_LP is not set ++# CONFIG_TCP_CONG_VENO is not set ++# CONFIG_TCP_CONG_YEAH is not set ++# CONFIG_TCP_CONG_ILLINOIS is not set ++# CONFIG_TCP_CONG_DCTCP is not set ++# CONFIG_TCP_CONG_CDG is not set ++# CONFIG_TCP_CONG_BBR is not set ++CONFIG_DEFAULT_CUBIC=y ++# CONFIG_DEFAULT_RENO is not set ++CONFIG_DEFAULT_TCP_CONG="cubic" ++CONFIG_TCP_MD5SIG=y ++# CONFIG_IPV6 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_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_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_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_FIB_RULES=y ++CONFIG_WIRELESS=y ++CONFIG_WEXT_CORE=y ++CONFIG_WEXT_PROC=y ++CONFIG_CFG80211=m ++# CONFIG_NL80211_TESTMODE is not set ++# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set ++CONFIG_CFG80211_DEFAULT_PS=y ++# CONFIG_CFG80211_INTERNAL_REGDB is not set ++CONFIG_CFG80211_CRDA_SUPPORT=y ++CONFIG_CFG80211_WEXT=y ++# CONFIG_LIB80211 is not set ++CONFIG_MAC80211=m ++CONFIG_MAC80211_HAS_RC=y ++CONFIG_MAC80211_RC_MINSTREL=y ++CONFIG_MAC80211_RC_MINSTREL_HT=y ++# CONFIG_MAC80211_RC_MINSTREL_VHT is not set ++CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y ++CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" ++CONFIG_MAC80211_MESH=y ++# CONFIG_MAC80211_MESSAGE_TRACING is not set ++# CONFIG_MAC80211_DEBUG_MENU is not set ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL 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 is not set ++# CONFIG_NET_DEVLINK is not set ++CONFIG_MAY_USE_DEVLINK=y ++CONFIG_HAVE_CBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER=y ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++# CONFIG_DEVTMPFS is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_I2C=y ++CONFIG_REGMAP_MMIO=y ++# 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_SWAP 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_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_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++CONFIG_MTD_SPI_NAND_HISI_BVT=y ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++CONFIG_MTD_SPI_NAND_HIFMC100=y ++# 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 is not set ++# CONFIG_SPI_CADENCE_QUADSPI is not set ++CONFIG_SPI_HISI_SFC=y ++# CONFIG_MTD_SPI_IDS is not set ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK 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=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# 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_USB_SWITCH_FSA9480 is not set ++# CONFIG_SRAM is not set ++# CONFIG_C2PORT is not set ++ ++# ++# EEPROM support ++# ++# CONFIG_EEPROM_AT24 is not set ++# CONFIG_EEPROM_LEGACY is not set ++# CONFIG_EEPROM_MAX6875 is not set ++# CONFIG_EEPROM_93CX6 is not set ++ ++# ++# Texas Instruments shared transport line discipline ++# ++# CONFIG_TI_ST 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=y ++CONFIG_SCSI_DMA=y ++CONFIG_SCSI_NETLINK=y ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++CONFIG_BLK_DEV_SR=y ++# CONFIG_BLK_DEV_SR_VENDOR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++CONFIG_SCSI_FC_ATTRS=y ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_LIBFC is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HISI_SATA=y ++CONFIG_HISI_SATA_IOBASE=0x10030000 ++CONFIG_HISI_SATA_FBS=1 ++CONFIG_HISI_SATA_NCQ=1 ++# CONFIG_HISI_ESATA is not set ++CONFIG_ATA=y ++# CONFIG_ATA_NONSTANDARD is not set ++CONFIG_ATA_VERBOSE_ERROR=y ++CONFIG_SATA_PMP=y ++ ++# ++# Controllers with non-SFF native interface ++# ++CONFIG_SATA_AHCI_PLATFORM=y ++# CONFIG_AHCI_CEVA is not set ++# CONFIG_AHCI_QORIQ is not set ++CONFIG_ATA_SFF=y ++ ++# ++# SFF controllers with custom DMA interface ++# ++CONFIG_ATA_BMDMA=y ++ ++# ++# SATA SFF controllers with BMDMA ++# ++ ++# ++# PATA SFF controllers with BMDMA ++# ++ ++# ++# PIO-only SFF controllers ++# ++ ++# ++# Generic fallback / legacy drivers ++# ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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=y ++# CONFIG_HIX5HD2_GMAC is not set ++CONFIG_HISI_FEMAC=y ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++# CONFIG_HIETH_GMAC 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_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_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=y ++# CONFIG_MDIO_HISI_GEMAC 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_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_IPHETH is not set ++# CONFIG_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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_GP2A is not set ++# CONFIG_INPUT_GPIO_BEEPER is not set ++# CONFIG_INPUT_GPIO_TILT_POLLED is not set ++# CONFIG_INPUT_GPIO_DECODER is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INPUT_CM109 is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV260X_HAPTICS is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_USERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST 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_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART 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_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_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_HIBVT=y ++# CONFIG_I2C_NOMADIK 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_DMA_MSG_MIN_LEN=5 ++CONFIG_DMA_MSG_MAX_LEN=4090 ++# 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 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++# CONFIG_PINCTRL_AMD is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++CONFIG_GPIOLIB=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers ++# ++# CONFIG_GPIO_74XX_MMIO is not set ++# CONFIG_GPIO_ALTERA is not set ++# 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_PL061=y ++# CONFIG_GPIO_SYSCON 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 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++CONFIG_POWER_RESET_SYSCON=y ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24257 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_BQ25890 is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_CHARGER_RT9455 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_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_I2C is not set ++# CONFIG_MFD_HI6421_PMIC is not set ++CONFIG_MFD_HISI_FMC=y ++# 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_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=y ++# 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_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_WM8400 is not set ++# CONFIG_MFD_WM831X_I2C 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 ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++# CONFIG_HID_A4TECH is not set ++# CONFIG_HID_ACRUX is not set ++# CONFIG_HID_APPLE is not set ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++# CONFIG_HID_BELKIN is not set ++# CONFIG_HID_BETOP_FF is not set ++# CONFIG_HID_CHERRY is not set ++# CONFIG_HID_CHICONY is not set ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CP2112 is not set ++# CONFIG_HID_CYPRESS is not set ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++# CONFIG_HID_EZKEY is not set ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++# CONFIG_HID_KENSINGTON is not set ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++# CONFIG_HID_LOGITECH is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++# CONFIG_HID_MONTEREY is not set ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# 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_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_SISUSBVGA 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 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_I2C_AND_SPI=y ++ ++# ++# SPI and I2C RTC drivers ++# ++# CONFIG_RTC_DRV_DS3232 is not set ++# CONFIG_RTC_DRV_PCF2127 is not set ++# CONFIG_RTC_DRV_RV3029C2 is not set ++ ++# ++# Platform RTC drivers ++# ++CONFIG_RTC_DRV_HIBVT=y ++# 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_PL030 is not set ++# CONFIG_RTC_DRV_PL031 is not set ++# CONFIG_RTC_DRV_SNVS is not set ++ ++# ++# HID Sensor RTC drivers ++# ++# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set ++# CONFIG_DMADEVICES 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_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++CONFIG_COMMON_CLK_HI3536DV100=y ++CONFIG_RESET_HISI=y ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++CONFIG_ARM_TIMER_SP804=y ++# 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 is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_ZYNQ is not set ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# 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_PHY_HISI_SATA=y ++CONFIG_HISI_SATA_MODE=1 ++CONFIG_PHY_HISI_USB2=y ++# 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 ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Firmware Drivers ++# ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++CONFIG_EXT2_FS=y ++# CONFIG_EXT2_FS_XATTR is not set ++CONFIG_EXT3_FS=y ++# CONFIG_EXT3_FS_POSIX_ACL is not set ++# CONFIG_EXT3_FS_SECURITY is not set ++CONFIG_EXT4_FS=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_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=y ++CONFIG_EXPORTFS=y ++# 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=y ++# CONFIG_JOLIET is not set ++# CONFIG_ZISOFS is not set ++# CONFIG_UDF_FS is not set ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++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=y ++CONFIG_TMPFS_XATTR=y ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_CONFIGFS_FS=m ++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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_UBIFS_ATIME_SUPPORT is not set ++# CONFIG_LOGFS is not set ++CONFIG_CRAMFS=y ++# 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFS_V4_1 is not set ++CONFIG_ROOT_NFS=y ++# CONFIG_NFS_USE_LEGACY_DNS is not set ++CONFIG_NFS_USE_KERNEL_DNS=y ++# CONFIG_NFSD is not set ++CONFIG_GRACE_PERIOD=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++CONFIG_SUNRPC_GSS=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=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=y ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++# 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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_WQ_WATCHDOG is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++# CONFIG_SCHED_DEBUG is not set ++# CONFIG_SCHED_INFO is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++CONFIG_DEBUG_MUTEXES=y ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS 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_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set ++# CONFIG_UBSAN is not set ++CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y ++CONFIG_STRICT_DEVMEM=y ++# CONFIG_IO_STRICT_DEVMEM is not set ++# CONFIG_ARM_PTDUMP is not set ++# CONFIG_ARM_UNWIND is not set ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL 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_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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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=m ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++CONFIG_CRYPTO_GF128MUL=m ++CONFIG_CRYPTO_NULL=m ++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=m ++CONFIG_CRYPTO_GCM=m ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# 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=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++CONFIG_CRYPTO_CRCT10DIF=y ++CONFIG_CRYPTO_GHASH=m ++# CONFIG_CRYPTO_POLY1305 is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=y ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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=y ++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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++# CONFIG_CRYPTO_HW 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=y ++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=y ++CONFIG_CRC16=y ++CONFIG_CRC_T10DIF=y ++CONFIG_CRC_ITU_T=y ++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=y ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_LZ4=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_GLOB=y ++# CONFIG_GLOB_SELFTEST is not set ++CONFIG_NLATTR=y ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++# CONFIG_IRQ_POLL is not set ++CONFIG_LIBFDT=y ++CONFIG_OID_REGISTRY=y ++# CONFIG_SG_SPLIT is not set ++CONFIG_SG_POOL=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/mach-hibvt/Kconfig b/arch/arm/mach-hibvt/Kconfig +new file mode 100644 +index 0000000..4541201 +--- /dev/null ++++ b/arch/arm/mach-hibvt/Kconfig +@@ -0,0 +1,80 @@ ++config ARCH_HISI_BVT ++ bool "Hisilicon BVT SoC Support" ++ select ARM_AMBA ++ select ARM_GIC if ARCH_MULTI_V7 ++ select ARM_VIC if ARCH_MULTI_V5 ++ select ARM_TIMER_SP804 ++ select POWER_RESET ++ select POWER_SUPPLY ++ ++if ARCH_HISI_BVT ++ ++menu "Hisilicon BVT platform type" ++ ++config ARCH_HI3516A ++ bool "Hisilicon Hi3516A Cortex-A7(Single) family" ++ depends on ARCH_MULTI_V7 ++ select HAVE_ARM_ARCH_TIMER ++ select ARM_GIC ++ select ARCH_HAS_RESET_CONTROLLER ++ select RESET_CONTROLLER ++ help ++ Support for Hisilicon Hi3516A Soc family. ++ ++config ARCH_HI3518EV20X ++ bool "Hisilicon Hi3518ev20x ARM926T(Single) family" ++ depends on ARCH_MULTI_V5 ++ select PINCTRL ++ select PINCTRL_SINGLE ++ help ++ Support for Hisilicon Hi3518ev20x Soc family. ++ ++config ARCH_HI3536DV100 ++ bool "Hisilicon Hi3536DV100 Cortex-A7(Single) family" ++ depends on ARCH_MULTI_V7 ++ select HAVE_ARM_ARCH_TIMER ++ select PINCTRL ++ help ++ Support for Hisilicon Hi3536DV100 Soc family. ++ ++config ARCH_HI3521A ++ bool "Hisilicon Hi3521A A7(Single) family" ++ depends on ARCH_MULTI_V7 ++ select HAVE_ARM_ARCH_TIMER ++ select ARM_GIC ++ select PINCTRL ++ select PINCTRL_SINGLE ++ help ++ Support for Hisilicon Hi3521a Soc family. ++ ++config ARCH_HI3531A ++ bool "Hisilicon Hi3531A A9 family" if ARCH_MULTI_V7 ++ select HAVE_ARM_ARCH_TIMER ++ select ARM_GIC ++ select CACHE_L2X0 ++ select PINCTRL ++ select PINCTRL_SINGLE ++ select HAVE_ARM_SCU if SMP ++ select NEED_MACH_IO_H if PCI ++ help ++ Support for Hisilicon Hi3531a Soc family. ++ ++config HI_ZRELADDR ++ hex 'zreladdr' ++ default "0x80008000" if ARCH_HI3516A ++ default "0x80008000" if ARCH_HI3518EV20X ++ default "0x80008000" if ARCH_HI3536DV100 ++ default "0x80008000" if ARCH_HI3521A ++ default "0x40008000" if ARCH_HI3531A ++ ++config HI_PARAMS_PHYS ++ hex 'params_phys' ++ default "0x00000100" ++ ++config HI_INITRD_PHYS ++ hex 'initrd_phys' ++ default "0x00800000" ++ ++endmenu ++ ++endif +diff --git a/arch/arm/mach-hibvt/Makefile b/arch/arm/mach-hibvt/Makefile +new file mode 100644 +index 0000000..90bfe53 +--- /dev/null ++++ b/arch/arm/mach-hibvt/Makefile +@@ -0,0 +1,13 @@ ++# ++# Makefile for Hisilicon processors family ++# ++ ++obj-$(CONFIG_ARCH_HI3516A) += mach-hi3516a.o ++obj-$(CONFIG_ARCH_HI3518EV20X) += mach-hi3518ev20x.o ++obj-$(CONFIG_ARCH_HI3536DV100) += mach-hi3536dv100.o ++obj-$(CONFIG_ARCH_HI3521A) += mach-hi3521a.o ++obj-$(CONFIG_ARCH_HI3531A) += mach-hi3531a.o ++ ++obj-$(CONFIG_CACHE_L2X0) += l2cache.o ++ ++obj-$(CONFIG_SMP) += platsmp.o +diff --git a/arch/arm/mach-hibvt/Makefile.boot b/arch/arm/mach-hibvt/Makefile.boot +new file mode 100644 +index 0000000..be34718 +--- /dev/null ++++ b/arch/arm/mach-hibvt/Makefile.boot +@@ -0,0 +1,3 @@ ++zreladdr-$(CONFIG_ARCH_HISI_BVT) := $(CONFIG_HI_ZRELADDR) ++params_phys-$(CONFIG_ARCH_HISI_BVT) := $(CONFIG_HI_PARAMS_PHYS) ++initrd_phys-$(CONFIG_ARCH_HISI_BVT) := $(CONFIG_HI_INITRD_PHYS) +diff --git a/arch/arm/mach-hibvt/include/mach/hi3516a_io.h b/arch/arm/mach-hibvt/include/mach/hi3516a_io.h +new file mode 100644 +index 0000000..7654fb7 +--- /dev/null ++++ b/arch/arm/mach-hibvt/include/mach/hi3516a_io.h +@@ -0,0 +1,25 @@ ++#ifndef __HI3516A_IO_H ++#define __HI3516A_IO_H ++ ++/* ++ * phy: 0x20000000 ~ 0x20700000 ++ * vir: 0xFE100000 ~ 0xFE800000 ++ */ ++#define HI3516A_IOCH2_PHYS 0x20000000 ++#define IO_OFFSET_HIGH 0xDE100000 ++#define HI3516A_IOCH2_VIRT (HI3516A_IOCH2_PHYS + IO_OFFSET_HIGH) ++#define HI3516A_IOCH2_SIZE 0x700000 ++ ++/* phy: 0x10000000 ~ 0x100D0000 ++ * vir: 0xFE000000 ~ 0xFE0D0000 ++ */ ++#define HI3516A_IOCH1_PHYS 0x10000000 ++#define IO_OFFSET_LOW 0xEE000000 ++#define HI3516A_IOCH1_VIRT (HI3516A_IOCH1_PHYS + IO_OFFSET_LOW) ++#define HI3516A_IOCH1_SIZE 0xD0000 ++ ++#define IO_ADDRESS(x) ((x) >= HI3516A_IOCH2_PHYS ? (x) + IO_OFFSET_HIGH \ ++ : (x) + IO_OFFSET_LOW) ++#endif ++ ++ +diff --git a/arch/arm/mach-hibvt/include/mach/hi3518ev20x_io.h b/arch/arm/mach-hibvt/include/mach/hi3518ev20x_io.h +new file mode 100644 +index 0000000..92d3b5f +--- /dev/null ++++ b/arch/arm/mach-hibvt/include/mach/hi3518ev20x_io.h +@@ -0,0 +1,26 @@ ++#ifndef __HI3518EV20X_IO_H ++#define __HI3518EV20X_IO_H ++ ++/* ++ * phy: 0x20000000 ~ 0x20700000 ++ * vir: 0xFE100000 ~ 0xFE800000 ++ */ ++#define HI3518EV20X_IOCH2_PHYS 0x20000000 ++#define IO_OFFSET_HIGH 0xDE100000 ++#define HI3518EV20X_IOCH2_VIRT (HI3518EV20X_IOCH2_PHYS + IO_OFFSET_HIGH) ++#define HI3518EV20X_IOCH2_SIZE 0x700000 ++ ++/* phy: 0x10000000 ~ 0x100E0000 ++ * vir: 0xFE000000 ~ 0xFE0E0000 ++ */ ++#define HI3518EV20X_IOCH1_PHYS 0x10000000 ++#define IO_OFFSET_LOW 0xEE000000 ++#define HI3518EV20X_IOCH1_VIRT (HI3518EV20X_IOCH1_PHYS + IO_OFFSET_LOW) ++#define HI3518EV20X_IOCH1_SIZE 0xE0000 ++ ++#define IO_ADDRESS(x) ((x) >= HI3518EV20X_IOCH2_PHYS ? (x) + IO_OFFSET_HIGH \ ++ : (x) + IO_OFFSET_LOW) ++ ++#define __io_address(n) ((void __iomem __force *)IO_ADDRESS(n)) ++ ++#endif +diff --git a/arch/arm/mach-hibvt/include/mach/hi3521a_io.h b/arch/arm/mach-hibvt/include/mach/hi3521a_io.h +new file mode 100644 +index 0000000..d02ed4e +--- /dev/null ++++ b/arch/arm/mach-hibvt/include/mach/hi3521a_io.h +@@ -0,0 +1,42 @@ ++#ifndef __HI3521A_IO_H ++#define __HI3521A_IO_H ++ ++/* phys_addr virt_addr ++ * 0x1000_0000 <-----> 0xFE00_0000 ++ */ ++#define HI3521A_IOCH1_VIRT (0xFE000000) ++#define HI3521A_IOCH1_PHYS (0x10000000) ++#define HI3521A_IOCH1_SIZE (0x00400000) ++ ++/* phys_addr virt_addr ++ * 0x1200_0000 <-----> 0xFE40_0000 ++ */ ++#define HI3521A_IOCH2_VIRT (0xFE400000) ++#define HI3521A_IOCH2_PHYS (0x12000000) ++#define HI3521A_IOCH2_SIZE (0x00230000) ++ ++/* phys_addr virt_addr ++ * 0x1301_0000 <-----> 0xFE70_0000 ++ */ ++#define HI3521A_IOCH3_VIRT (0xFE700000) ++#define HI3521A_IOCH3_PHYS (0x13000000) ++#define HI3521A_IOCH3_SIZE (0x00160000) ++ ++#define IO_OFFSET_LOW (0xEB700000) ++#define IO_OFFSET_MID (0xEC400000) ++#define IO_OFFSET_HIGH (0xEE000000) ++ ++#define IO_ADDRESS_LOW(x) ((x) + IO_OFFSET_LOW) ++#define IO_ADDRESS_MID(x) ((x) + IO_OFFSET_MID) ++#define IO_ADDRESS_HIGH(x) ((x) + IO_OFFSET_HIGH) ++ ++#define __IO_ADDRESS_HIGH(x) ((x >= HI3521A_IOCH2_PHYS) ? IO_ADDRESS_MID(x) \ ++ : IO_ADDRESS_HIGH(x)) ++#define IO_ADDRESS(x) ((x) >= HI3521A_IOCH3_PHYS ? IO_ADDRESS_LOW(x) \ ++ : __IO_ADDRESS_HIGH(x)) ++ ++#define __io_address(x) (IOMEM(IO_ADDRESS(x))) ++ ++#endif ++ ++ +diff --git a/arch/arm/mach-hibvt/include/mach/hi3521a_platform.h b/arch/arm/mach-hibvt/include/mach/hi3521a_platform.h +new file mode 100644 +index 0000000..e06b3dc +--- /dev/null ++++ b/arch/arm/mach-hibvt/include/mach/hi3521a_platform.h +@@ -0,0 +1,27 @@ ++#ifndef __HI3521A_H__ ++#define __HI3521A_H__ ++ ++/* -------------------------------------------------------------------- */ ++/* Clock and Reset Generator REG */ ++/* -------------------------------------------------------------------- */ ++#define REG_CRG_BASE 0x12040000 ++ ++/* -------------------------------------------------------------------- */ ++/* SATA REG */ ++/* -------------------------------------------------------------------- */ ++#define HISI_SATA_PHY0_CTLL 0xA0 ++#define HISI_SATA_PHY0_CTLH 0xA4 ++#define HISI_SATA_PHY1_CTLL 0xAC ++#define HISI_SATA_PHY1_CTLH 0xB0 ++ ++#define HISI_SATA_PORT_FIFOTH 0x44 ++#define HISI_SATA_PORT_PHYCTL1 0x48 ++#define HISI_SATA_PORT_PHYCTL2 0x4C ++#define HISI_SATA_PORT_PHYCTL 0x74 ++ ++#define HISI_SATA_PHY_RESET BIT(0) ++#define HISI_SATA_BIGENDINE BIT(3) ++#define HISI_SATA_PHY_REV_CLK BIT(9) ++#define HISI_SATA_LANE0_RESET BIT(18) ++ ++#endif /* End of __HI3521A_H__ */ +diff --git a/arch/arm/mach-hibvt/include/mach/hi3531a_io.h b/arch/arm/mach-hibvt/include/mach/hi3531a_io.h +new file mode 100644 +index 0000000..2d69139 +--- /dev/null ++++ b/arch/arm/mach-hibvt/include/mach/hi3531a_io.h +@@ -0,0 +1,63 @@ ++#ifndef __HI3531A_IO_H ++#define __HI3531A_IO_H ++ ++#ifdef CONFIG_PCI ++#define IO_SPACE_LIMIT 0xFFFFFFFF ++ ++#define __io(a) __typesafe_io(a) ++#define __mem_pci(a) (a) ++#endif ++ ++/* phys_addr virt_addr ++ * 0x1000_0000 <-----> 0xFE00_0000 ++ * 0x1071_0000 <-----> 0xFE71_0000 ++ */ ++#define HI3531A_IOCH1_VIRT (0xFE000000) ++#define HI3531A_IOCH1_PHYS (0x10000000) ++#define HI3531A_IOCH1_SIZE (0x00710000) ++#define IO_OFFSET_IOCH1 (0xEE000000) ++ ++/* phys_addr virt_addr ++ * 0x1100_0000 <-----> 0xFE78_0000 ++ * 0x1104_0000 <-----> 0xFE7C_0000 ++ */ ++#define HI3531A_IOCH2_VIRT (0xFE780000) ++#define HI3531A_IOCH2_PHYS (0x11000000) ++#define HI3531A_IOCH2_SIZE (0x00040000) ++#define IO_OFFSET_IOCH2 (0xED780000) ++ ++/* phys_addr virt_addr ++ * 0x1200_0000 <-----> 0xFE80_0000 ++ * 0x122F_0000 <-----> 0xFEAF_0000 ++ */ ++#define HI3531A_IOCH3_VIRT (0xFE800000) ++#define HI3531A_IOCH3_PHYS (0x12000000) ++#define HI3531A_IOCH3_SIZE (0x002F0000) ++#define IO_OFFSET_IOCH3 (0xEC800000) ++ ++/* phys_addr virt_addr ++ * 0x1300_0000 <-----> 0xFEB0_0000 ++ * 0x131A_0000 <-----> 0xFECA_0000 ++ */ ++#define HI3531A_IOCH4_VIRT (0xFEB00000) ++#define HI3531A_IOCH4_PHYS (0x13000000) ++#define HI3531A_IOCH4_SIZE (0x001A0000) ++#define IO_OFFSET_IOCH4 (0xEBB00000) ++ ++#define IO_ADDR_HIGH_H(x) ((x) + IO_OFFSET_IOCH4) ++#define IO_ADDR_HIGH_L(x) ((x) + IO_OFFSET_IOCH3) ++#define IO_ADDR_LOW_H(x) ((x) + IO_OFFSET_IOCH2) ++#define IO_ADDR_LOW_L(x) ((x) + IO_OFFSET_IOCH1) ++ ++#define __IO_ADDR_HIGH(x) ((x >= HI3531A_IOCH4_PHYS) ? IO_ADDR_HIGH_H(x) \ ++ : IO_ADDR_HIGH_L(x)) ++ ++#define __IO_ADDR_LOW(x) ((x >= HI3531A_IOCH2_PHYS) ? IO_ADDR_LOW_H(x) \ ++ : IO_ADDR_LOW_L(x)) ++ ++#define IO_ADDRESS(x) ((x) >= HI3531A_IOCH3_PHYS ? __IO_ADDR_HIGH(x) \ ++ : __IO_ADDR_LOW(x)) ++ ++#define __io_address(n) (IOMEM(IO_ADDRESS(n))) ++ ++#endif /* __HI3531A_IO_H */ +diff --git a/arch/arm/mach-hibvt/include/mach/hi3531a_platform.h b/arch/arm/mach-hibvt/include/mach/hi3531a_platform.h +new file mode 100644 +index 0000000..ca86b79 +--- /dev/null ++++ b/arch/arm/mach-hibvt/include/mach/hi3531a_platform.h +@@ -0,0 +1,65 @@ ++#ifndef __HI3531A_CHIP_REGS_H__ ++#define __HI3531A_CHIP_REGS_H__ ++ ++/* -------------------------------------------------------------------- */ ++/* Clock and Reset Generator REG */ ++/* -------------------------------------------------------------------- */ ++#define CRG_REG_BASE 0x12040000 ++ ++#define REG_CRG20 0x0050 ++#define REG_CRG32 0x0080 ++#define REG_CRG72 0x0120 ++#define REG_CRG75 0x012c ++#define REG_CRG76 0x0130 ++#define REG_CRG77 0x0134 ++#define REG_CRG79 0x013c ++#define REG_CRG81 0x0144 ++#define REG_CRG82 0x0148 ++#define REG_CRG83 0x014c ++#define REG_CRG85 0x0154 ++#define REG_CRG87 0x015c ++#define REG_CRG91 0x016c ++ ++/* -------------------------------------------------------------------- */ ++/* System controller register */ ++/* -------------------------------------------------------------------- */ ++#define SYS_CTRL_REG_BASE 0x12050000 ++ ++/* -------------------------------------------------------------------- */ ++/* MISC controller register */ ++/* -------------------------------------------------------------------- */ ++#define MISC_CTRL_REG_BASE 0x12120000 ++ ++/* -------------------------------------------------------------------- */ ++/* A9 soft reset request register offset */ ++/* -------------------------------------------------------------------- */ ++#define REG_A9_SRST_CRG REG_CRG32 ++#define WDG1_SRST_REQ BIT(6) ++#define DBG1_SRST_REQ BIT(5) ++#define CPU1_SRST_REQ BIT(4) ++ ++/* -------------------------------------------------------------------- */ ++/* CORTTX-A9 internal Register */ ++/* -------------------------------------------------------------------- */ ++#define A9_PERI_BASE 0x10300000 ++#define REG_A9_PERI_SCU 0x0000 ++ ++/* -------------------------------------------------------------------- */ ++#define REG_BASE_L2CACHE 0x10700000 ++ ++/* -------------------------------------------------------------------- */ ++/* SATA register */ ++/* -------------------------------------------------------------------- */ ++#define HISI_SATA_PORT_FIFOTH 0x44 ++#define HISI_SATA_PORT_PHYCTL1 0x48 ++#define HISI_SATA_PORT_PHYCTL 0x74 ++ ++#define HISI_SATA_PHY_CTL0 0xA0 ++#define HISI_SATA_PHY_CTL1 0xA4 ++#define HISI_SATA_PHY_CTL2 0xB0 ++#define HISI_SATA_RST_PHY_MASK 0xAC ++ ++#define HISI_SATA_FIFOTH_VALUE 0x6ED9F24 ++#define HISI_SATA_BIGENDINE BIT(3) ++ ++#endif /* End of __HI3531A_CHIP_REGS_H__ */ +diff --git a/arch/arm/mach-hibvt/include/mach/hi3536dv100_io.h b/arch/arm/mach-hibvt/include/mach/hi3536dv100_io.h +new file mode 100644 +index 0000000..6135e75 +--- /dev/null ++++ b/arch/arm/mach-hibvt/include/mach/hi3536dv100_io.h +@@ -0,0 +1,44 @@ ++#ifndef __HI3536DV100_IO_H ++#define __HI3536DV100_IO_H ++ ++/* phys_addr virt_addr ++ * 0x1100_0000 <-----> 0xFE00_0000 ++ * 0x1104_0000 <-----> 0xFE04_0000 ++ */ ++#define HI3536DV100_IOCH1_VIRT (0xFE000000) ++#define HI3536DV100_IOCH1_PHYS (0x11000000) ++#define HI3536DV100_IOCH1_SIZE (0x00040000) ++ ++/* phys_addr virt_addr ++ * 0x1200_0000 <-----> 0xFE10_0000 ++ * 0x121B_0000 <-----> 0xFE2B_0000 ++ */ ++#define HI3536DV100_IOCH2_VIRT (0xFE100000) ++#define HI3536DV100_IOCH2_PHYS (0x12000000) ++#define HI3536DV100_IOCH2_SIZE (0x001B0000) ++ ++/* phys_addr virt_addr ++ * 0x1300_0000 <-----> 0xFE30_0000 ++ * 0x1321_0000 <-----> 0xFE51_0000 ++ */ ++#define HI3536DV100_IOCH3_VIRT (0xFE300000) ++#define HI3536DV100_IOCH3_PHYS (0x13000000) ++#define HI3536DV100_IOCH3_SIZE (0x00210000) ++ ++#define IO_OFFSET_LOW (0xEB300000) ++#define IO_OFFSET_MID (0xEC100000) ++#define IO_OFFSET_HIGH (0xED000000) ++ ++#define IO_ADDRESS_LOW(x) ((x) + IO_OFFSET_LOW) ++#define IO_ADDRESS_MID(x) ((x) + IO_OFFSET_MID) ++#define IO_ADDRESS_HIGH(x) ((x) + IO_OFFSET_HIGH) ++ ++#define __IO_ADDRESS_HIGH(x) ((x >= HI3536DV100_IOCH2_PHYS) ? IO_ADDRESS_MID(x) \ ++ : IO_ADDRESS_HIGH(x)) ++#define IO_ADDRESS(x) ((x) >= HI3536DV100_IOCH3_PHYS ? IO_ADDRESS_LOW(x) \ ++ : __IO_ADDRESS_HIGH(x)) ++ ++#define __io_address(x) (IOMEM(IO_ADDRESS(x))) ++ ++#endif ++ +diff --git a/arch/arm/mach-hibvt/include/mach/hi3536dv100_platform.h b/arch/arm/mach-hibvt/include/mach/hi3536dv100_platform.h +new file mode 100644 +index 0000000..bf21bc5 +--- /dev/null ++++ b/arch/arm/mach-hibvt/include/mach/hi3536dv100_platform.h +@@ -0,0 +1,14 @@ ++#ifndef __HISI_CHIP_REGS_H__ ++#define __HISI_CHIP_REGS_H__ ++ ++/* -------------------------------------------------------------------- */ ++/* Clock and Reset Generator REG */ ++/* -------------------------------------------------------------------- */ ++#define REG_CRG_BASE 0x12040000 ++ ++/* -------------------------------------------------------------------- */ ++/* Misc control REG */ ++/* -------------------------------------------------------------------- */ ++#define REG_MISC_CTRL_BASE 0x12120000 ++ ++#endif /* End of __HISI_CHIP_REGS_H__ */ +diff --git a/arch/arm/mach-hibvt/include/mach/io.h b/arch/arm/mach-hibvt/include/mach/io.h +new file mode 100644 +index 0000000..befee25 +--- /dev/null ++++ b/arch/arm/mach-hibvt/include/mach/io.h +@@ -0,0 +1,24 @@ ++#ifndef __ASM_ARM_ARCH_IO_H ++#define __ASM_ARM_ARCH_IO_H ++ ++#ifdef CONFIG_ARCH_HI3516A ++#include ++#endif ++ ++#ifdef CONFIG_ARCH_HI3518EV20X ++#include ++#endif ++ ++#ifdef CONFIG_ARCH_HI3536DV100 ++#include ++#endif ++ ++#ifdef CONFIG_ARCH_HI3521A ++#include ++#endif ++ ++#ifdef CONFIG_ARCH_HI3531A ++#include ++#endif ++ ++#endif +diff --git a/arch/arm/mach-hibvt/include/mach/platform.h b/arch/arm/mach-hibvt/include/mach/platform.h +new file mode 100644 +index 0000000..4799b3a +--- /dev/null ++++ b/arch/arm/mach-hibvt/include/mach/platform.h +@@ -0,0 +1,16 @@ ++#ifndef __HISI_PLATFORM_H__ ++#define __HISI_PLATFORM_H__ ++ ++#ifdef CONFIG_ARCH_HI3536DV100 ++#include ++#endif ++ ++#ifdef CONFIG_ARCH_HI3521A ++#include ++#endif ++ ++#ifdef CONFIG_ARCH_HI3531A ++#include ++#endif ++ ++#endif /* End of __HISI_PLATFORM_H__ */ +diff --git a/arch/arm/mach-hibvt/l2cache.c b/arch/arm/mach-hibvt/l2cache.c +new file mode 100644 +index 0000000..52aa2ec +--- /dev/null ++++ b/arch/arm/mach-hibvt/l2cache.c +@@ -0,0 +1,71 @@ ++/* ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#define pr_fmt(fmt) "l2cache: " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static void __iomem *l2x0_virt_base = __io_address(REG_BASE_L2CACHE); ++ ++static int __init l2_cache_init(void) ++{ ++ u32 val; ++ /* ++ * Bits Value Description ++ * [31] 0 : SBZ ++ * [30] 1 : Double linefill enable (L3) ++ * [29] 1 : Instruction prefetching enable ++ * [28] 1 : Data prefetching enabled ++ * [27] 0 : Double linefill on WRAP read enabled (L3) ++ * [26:25] 0 : SBZ ++ * [24] 1 : Prefetch drop enable (L3) ++ * [23] 0 : Incr double Linefill enable (L3) ++ * [22] 0 : SBZ ++ * [21] 0 : Not same ID on exclusive sequence enable (L3) ++ * [20:5] 0 : SBZ ++ * [4:0] 0 : use the Prefetch offset values 0. ++ */ ++ /* writel_relaxed(0x71000000, l2x0_virt_base + L2X0_PREFETCH_CTRL); */ ++ writel_relaxed(0x71000000, l2x0_virt_base + L310_PREFETCH_CTRL); ++ ++ val = __raw_readl(l2x0_virt_base + L2X0_AUX_CTRL); ++ val |= (1 << 30); /* Early BRESP enabled */ ++ val |= (1 << 0); /* Full Line of Zero Enable */ ++ writel_relaxed(val, l2x0_virt_base + L2X0_AUX_CTRL); ++ l2x0_init(l2x0_virt_base, 0x00430000, 0xFFB0FFFF); ++ /* ++ * 2. enable L2 prefetch hint [1]a ++ * 3. enable write full line of zeros mode. [3]a ++ * a: This feature must be enabled only when the slaves ++ * connected on the Cortex-A9 AXI master port support it. ++ */ ++ asm volatile ( ++ " mrc p15, 0, r0, c1, c0, 1\n" ++ " orr r0, r0, #0x02\n" ++ " mcr p15, 0, r0, c1, c0, 1\n" ++ : ++ : ++ : "r0", "cc"); ++ ++ return 0; ++} ++early_initcall(l2_cache_init); +diff --git a/arch/arm/mach-hibvt/mach-common.h b/arch/arm/mach-hibvt/mach-common.h +new file mode 100644 +index 0000000..f5edadb +--- /dev/null ++++ b/arch/arm/mach-hibvt/mach-common.h +@@ -0,0 +1,9 @@ ++#ifndef __SMP_COMMON_H ++#define __SMP_COMMON_H ++ ++#ifdef CONFIG_SMP ++void hi35xx_set_cpu(unsigned int cpu, bool enable); ++void __init hi35xx_smp_prepare_cpus(unsigned int max_cpus); ++int hi35xx_boot_secondary(unsigned int cpu, struct task_struct *idle); ++#endif /* CONFIG_SMP */ ++#endif /* __SMP_COMMON_H */ +diff --git a/arch/arm/mach-hibvt/mach-hi3516a.c b/arch/arm/mach-hibvt/mach-hi3516a.c +new file mode 100644 +index 0000000..ed49f25 +--- /dev/null ++++ b/arch/arm/mach-hibvt/mach-hi3516a.c +@@ -0,0 +1,65 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++*/ ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* ++ * This table is only for optimization. Since ioremap() could always share ++ * the same mapping if it's defined as static IO mapping. ++ * ++ * Without this table, system could also work. The cost is some virtual address ++ * spaces wasted since ioremap() may be called multi times for the same ++ * IO space. ++ */ ++static struct map_desc hi3516a_io_desc[] __initdata = { ++ { ++ /* hi3516a_IOCH1 */ ++ .pfn = __phys_to_pfn(HI3516A_IOCH1_PHYS), ++ .virtual = HI3516A_IOCH1_VIRT, ++ .length = HI3516A_IOCH1_SIZE, ++ .type = MT_DEVICE, ++ }, ++ { ++ /* hi3516a_IOCH2 */ ++ .pfn = __phys_to_pfn(HI3516A_IOCH2_PHYS), ++ .virtual = HI3516A_IOCH2_VIRT, ++ .length = HI3516A_IOCH2_SIZE, ++ .type = MT_DEVICE, ++ }, ++}; ++ ++static void __init hi3516a_map_io(void) ++{ ++ /* debug_ll_io_init(); */ ++ iotable_init(hi3516a_io_desc, ARRAY_SIZE(hi3516a_io_desc)); ++} ++ ++static const char *const hi3516a_compat[] __initconst = { ++ "hisilicon,hi3516a", ++ NULL, ++}; ++ ++DT_MACHINE_START(HI3516A_DT, "Hisilicon Hi3516A (Flattened Device Tree)") ++ .map_io = hi3516a_map_io, ++ .dt_compat = hi3516a_compat, ++MACHINE_END +diff --git a/arch/arm/mach-hibvt/mach-hi3518ev20x.c b/arch/arm/mach-hibvt/mach-hi3518ev20x.c +new file mode 100644 +index 0000000..b8006d8 +--- /dev/null ++++ b/arch/arm/mach-hibvt/mach-hi3518ev20x.c +@@ -0,0 +1,63 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++*/ ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* ++ * This table is only for optimization. Since ioremap() could always share ++ * the same mapping if it's defined as static IO mapping. ++ * ++ * Without this table, system could also work. The cost is some virtual address ++ * spaces wasted since ioremap() may be called multi times for the same ++ * IO space. ++ */ ++static struct map_desc hi3518ev20x_io_desc[] __initdata = { ++ /* hi3518ev20x_IOCH1 */ ++ { ++ .virtual = HI3518EV20X_IOCH1_VIRT, ++ .pfn = __phys_to_pfn(HI3518EV20X_IOCH1_PHYS), ++ .length = HI3518EV20X_IOCH1_SIZE, ++ .type = MT_DEVICE ++ }, ++ /* hi3518ev20x_IOCH2 */ ++ { ++ .virtual = HI3518EV20X_IOCH2_VIRT, ++ .pfn = __phys_to_pfn(HI3518EV20X_IOCH2_PHYS), ++ .length = HI3518EV20X_IOCH2_SIZE, ++ .type = MT_DEVICE ++ }, ++}; ++ ++static void __init hi3518ev20x_map_io(void) ++{ ++ iotable_init(hi3518ev20x_io_desc, ARRAY_SIZE(hi3518ev20x_io_desc)); ++} ++static const char *const hi3518ev20x_compat[] __initconst = { ++ "hisilicon,hi3518ev20x", ++ NULL, ++}; ++ ++DT_MACHINE_START(HI3518EV20x_DT, "Hisilicon Hi3518EV20X (Flattened Device Tree)") ++ .map_io = hi3518ev20x_map_io, ++ .dt_compat = hi3518ev20x_compat, ++MACHINE_END +diff --git a/arch/arm/mach-hibvt/mach-hi3521a.c b/arch/arm/mach-hibvt/mach-hi3521a.c +new file mode 100644 +index 0000000..e8f3d99 +--- /dev/null ++++ b/arch/arm/mach-hibvt/mach-hi3521a.c +@@ -0,0 +1,74 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++*/ ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* ++ * This table is only for optimization. Since ioremap() could always share ++ * the same mapping if it's defined as static IO mapping. ++ * ++ * Without this table, system could also work. The cost is some virtual address ++ * spaces wasted since ioremap() may be called multi times for the same ++ * IO space. ++ */ ++static struct map_desc hi3521a_io_desc[] __initdata = { ++ /* hi3521a_IOCH1 */ ++ { ++ .pfn = __phys_to_pfn(HI3521A_IOCH1_PHYS), ++ .virtual = HI3521A_IOCH1_VIRT, ++ .length = HI3521A_IOCH1_SIZE, ++ .type = MT_DEVICE, ++ }, ++ ++ /* hi3521a_IOCH2 */ ++ { ++ .pfn = __phys_to_pfn(HI3521A_IOCH2_PHYS), ++ .virtual = HI3521A_IOCH2_VIRT, ++ .length = HI3521A_IOCH2_SIZE, ++ .type = MT_DEVICE, ++ }, ++ ++ /* hi3521a_IOCH3 */ ++ { ++ .pfn = __phys_to_pfn(HI3521A_IOCH3_PHYS), ++ .virtual = HI3521A_IOCH3_VIRT, ++ .length = HI3521A_IOCH3_SIZE, ++ .type = MT_DEVICE ++ }, ++}; ++ ++static void __init hi3521a_map_io(void) ++{ ++ /* debug_ll_io_init(); */ ++ iotable_init(hi3521a_io_desc, ARRAY_SIZE(hi3521a_io_desc)); ++} ++ ++static const char *const hi3521a_compat[] __initconst = { ++ "hisilicon,hi3521a", ++ NULL, ++}; ++ ++DT_MACHINE_START(HI3521A_DT, "Hisilicon Hi3521A (Flattened Device Tree)") ++ .map_io = hi3521a_map_io, ++ .dt_compat = hi3521a_compat, ++MACHINE_END +diff --git a/arch/arm/mach-hibvt/mach-hi3531a.c b/arch/arm/mach-hibvt/mach-hi3531a.c +new file mode 100644 +index 0000000..2fd52e9 +--- /dev/null ++++ b/arch/arm/mach-hibvt/mach-hi3531a.c +@@ -0,0 +1,187 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "mach-common.h" ++ ++/* ++ * This table is only for optimization. Since ioremap() could always share ++ * the same mapping if it's defined as static IO mapping. ++ * ++ * Without this table, system could also work. The cost is some virtual address ++ * spaces wasted since ioremap() may be called multi times for the same ++ * IO space. ++ */ ++static struct map_desc hi3531a_io_desc[] __initdata = { ++ /* hi3531a_IOCH1 */ ++ { ++ .pfn = __phys_to_pfn(HI3531A_IOCH1_PHYS), ++ .virtual = HI3531A_IOCH1_VIRT, ++ .length = HI3531A_IOCH1_SIZE, ++ .type = MT_DEVICE, ++ }, ++ ++ /* hi3531a_IOCH2 */ ++ { ++ .pfn = __phys_to_pfn(HI3531A_IOCH2_PHYS), ++ .virtual = HI3531A_IOCH2_VIRT, ++ .length = HI3531A_IOCH2_SIZE, ++ .type = MT_DEVICE, ++ }, ++ ++ /* hi3531a_IOCH3 */ ++ { ++ .pfn = __phys_to_pfn(HI3531A_IOCH3_PHYS), ++ .virtual = HI3531A_IOCH3_VIRT, ++ .length = HI3531A_IOCH3_SIZE, ++ .type = MT_DEVICE ++ }, ++ ++ /* hi3531a_IOCH4 */ ++ { ++ .pfn = __phys_to_pfn(HI3531A_IOCH4_PHYS), ++ .virtual = HI3531A_IOCH4_VIRT, ++ .length = HI3531A_IOCH4_SIZE, ++ .type = MT_DEVICE ++ }, ++}; ++ ++static void __init hi3531a_map_io(void) ++{ ++ /* debug_ll_io_init(); */ ++ iotable_init(hi3531a_io_desc, ARRAY_SIZE(hi3531a_io_desc)); ++} ++ ++static void __init hi3531a_init_early(void) ++{ ++ /* ++ * 1. enable L1 prefetch [2] ++ * 4. enable allocation in one cache way only. [8] ++ */ ++ asm volatile ( ++ " mrc p15, 0, r0, c1, c0, 1\n" ++ " orr r0, r0, #0x104\n" ++ " mcr p15, 0, r0, c1, c0, 1\n" ++ : ++ : ++ : "r0", "cc"); ++ ++} ++ ++static const char *const hi3531a_compat[] __initconst = { ++ "hisilicon,hi3531a", ++ NULL, ++}; ++ ++DT_MACHINE_START(HI3531A_DT, "Hisilicon Hi3531A (Flattened Device Tree)") ++ .map_io = hi3531a_map_io, ++ .dt_compat = hi3531a_compat, ++ .init_early = hi3531a_init_early, ++MACHINE_END ++ ++#if CONFIG_SMP ++ ++void hi35xx_set_cpu(unsigned int cpu, bool enable) ++{ ++ struct device_node *np = NULL; ++ unsigned int regval; ++ void __iomem *crg_base; ++ ++ np = of_find_compatible_node(NULL, NULL, "hisilicon,hi3531a-clock"); ++ if (!np) { ++ pr_err("failed to find hisilicon clock node\n"); ++ return; ++ } ++ ++ crg_base = of_iomap(np, 0); ++ if (!crg_base) { ++ pr_err("failed to map address\n"); ++ return; ++ } ++ ++ if (enable) { ++ /* clear the slave cpu reset */ ++ regval = readl(crg_base + REG_A9_SRST_CRG); ++ regval &= ~CPU1_SRST_REQ; ++ writel(regval, (crg_base + REG_A9_SRST_CRG)); ++ } else { ++ regval = readl(crg_base + REG_A9_SRST_CRG); ++ regval |= (WDG1_SRST_REQ | DBG1_SRST_REQ | CPU1_SRST_REQ); ++ writel(regval, (crg_base + REG_A9_SRST_CRG)); ++ } ++ ++ iounmap(crg_base); ++} ++ ++void hi35xx_secondary_init(unsigned int cpu) ++{ ++ /* ++ * 1. enable L1 prefetch [2] ++ * 2. enable L2 prefetch hint [1]a ++ * 3. enable write full line of zeros mode. [3]a ++ * 4. enable allocation in one cache way only. [8] ++ * a: This feature must be enabled only when the slaves ++ * connected on the Cortex-A17 AXI master port support it. ++ */ ++ asm volatile ( ++ " mrc p15, 0, r0, c1, c0, 1\n" ++ " orr r0, r0, #0x0104\n" ++ " orr r0, r0, #0x02\n" ++ " mcr p15, 0, r0, c1, c0, 1\n" ++ : ++ : ++ : "r0", "cc"); ++} ++ ++#ifdef CONFIG_HOTPLUG_CPU ++void hi35xx_cpu_die(unsigned int cpu) ++{ ++ flush_cache_all(); ++ hi35xx_set_cpu(cpu, false); ++ BUG(); ++} ++ ++int hi35xx_cpu_kill(unsigned int cpu) ++{ ++ return 0; ++} ++#endif /* CONFIG_HOTPLUG_CPU */ ++ ++static const struct smp_operations hi35xx_smp_ops __initconst = { ++ .smp_prepare_cpus = hi35xx_smp_prepare_cpus, ++ .smp_secondary_init = hi35xx_secondary_init, ++ .smp_boot_secondary = hi35xx_boot_secondary, ++#ifdef CONFIG_HOTPLUG_CPU ++ .cpu_die = hi35xx_cpu_die, ++ .cpu_kill = hi35xx_cpu_kill, ++#endif ++}; ++ ++CPU_METHOD_OF_DECLARE(hi3531a_smp, "hisilicon,hi3531a-smp", &hi35xx_smp_ops); ++#endif /* CONFIG_SMP */ +diff --git a/arch/arm/mach-hibvt/mach-hi3536dv100.c b/arch/arm/mach-hibvt/mach-hi3536dv100.c +new file mode 100644 +index 0000000..7b27dfa +--- /dev/null ++++ b/arch/arm/mach-hibvt/mach-hi3536dv100.c +@@ -0,0 +1,70 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++*/ ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* ++ * This table is only for optimization. Since ioremap() could always share ++ * the same mapping if it's defined as static IO mapping. ++ * ++ * Without this table, system could also work. The cost is some virtual address ++ * spaces wasted since ioremap() may be called multi times for the same ++ * IO space. ++ */ ++static struct map_desc hi3536dv100_io_desc[] __initdata = { ++ /* hi3536dv100_IOCH1 */ ++ { ++ .virtual = HI3536DV100_IOCH1_VIRT, ++ .pfn = __phys_to_pfn(HI3536DV100_IOCH1_PHYS), ++ .length = HI3536DV100_IOCH1_SIZE, ++ .type = MT_DEVICE ++ }, ++ /* hi3536dv100_IOCH2 */ ++ { ++ .virtual = HI3536DV100_IOCH2_VIRT, ++ .pfn = __phys_to_pfn(HI3536DV100_IOCH2_PHYS), ++ .length = HI3536DV100_IOCH2_SIZE, ++ .type = MT_DEVICE ++ }, ++ /* hi3536dv100_IOCH3 */ ++ { ++ .virtual = HI3536DV100_IOCH3_VIRT, ++ .pfn = __phys_to_pfn(HI3536DV100_IOCH3_PHYS), ++ .length = HI3536DV100_IOCH3_SIZE, ++ .type = MT_DEVICE ++ }, ++}; ++ ++static void __init hi3536dv100_map_io(void) ++{ ++ iotable_init(hi3536dv100_io_desc, ARRAY_SIZE(hi3536dv100_io_desc)); ++} ++static const char *const hi3536dv100_compat[] __initconst = { ++ "hisilicon,hi3536dv100", ++ NULL, ++}; ++ ++DT_MACHINE_START(HI3536DV100_DT, "Hisilicon Hi3536DV100 (Flattened Device Tree)") ++ .map_io = hi3536dv100_map_io, ++ .dt_compat = hi3536dv100_compat, ++MACHINE_END +diff --git a/arch/arm/mach-hibvt/platsmp.c b/arch/arm/mach-hibvt/platsmp.c +new file mode 100644 +index 0000000..db60c78 +--- /dev/null ++++ b/arch/arm/mach-hibvt/platsmp.c +@@ -0,0 +1,62 @@ ++/* ++ * 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 ++#include ++#include ++ ++#include "mach-common.h" ++ ++#define HI35XX_BOOT_ADDRESS (0x00000000) ++ ++void __init hi35xx_smp_prepare_cpus(unsigned int max_cpus) ++{ ++ unsigned long base = 0; ++ void __iomem *scu_base = NULL; ++ ++ if (scu_a9_has_base()) { ++ base = scu_a9_get_base(); ++ scu_base = ioremap(base, PAGE_SIZE); ++ if (!scu_base) { ++ pr_err("ioremap(scu_base) failed\n"); ++ return; ++ } ++ ++ scu_enable(scu_base); ++ iounmap(scu_base); ++ } ++} ++ ++void hi35xx_set_scu_boot_addr(phys_addr_t start_addr, phys_addr_t jump_addr) ++{ ++ void __iomem *virt; ++ ++ virt = ioremap(start_addr, PAGE_SIZE); ++ if (!virt) { ++ pr_err("ioremap(start_addr) failed\n"); ++ return; ++ } ++ ++ writel_relaxed(0xe51ff004, virt); /* ldr pc, [rc, #-4] */ ++ writel_relaxed(jump_addr, virt + 4); /* pc jump phy address */ ++ iounmap(virt); ++} ++ ++int hi35xx_boot_secondary(unsigned int cpu, struct task_struct *idle) ++{ ++ phys_addr_t jumpaddr; ++ ++ jumpaddr = virt_to_phys(secondary_startup); ++ hi35xx_set_scu_boot_addr(HI35XX_BOOT_ADDRESS, jumpaddr); ++ hi35xx_set_cpu(cpu, true); ++ arch_send_wakeup_ipi_mask(cpumask_of(cpu)); ++ return 0; ++} ++ +diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c +index ab77100..6143695 100644 +--- a/arch/arm/mm/dma-mapping.c ++++ b/arch/arm/mm/dma-mapping.c +@@ -2397,3 +2397,10 @@ void arch_teardown_dma_ops(struct device *dev) + { + arm_teardown_iommu_dma_ops(dev); + } ++ ++void hi_dmac_map_area(const void *kaddr, size_t size, ++ enum dma_data_direction dir) ++{ ++ dmac_map_area(kaddr, size, dir); ++} ++EXPORT_SYMBOL(hi_dmac_map_area); +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index cf57a77..693401e 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -998,6 +998,41 @@ config DMI + However, even with this option, the resultant kernel should + continue to boot on existing non-UEFI platforms. + ++config BUILD_ARM64_APPENDED_DTB_IMAGE ++ bool "Build a concatenated Image.gz/dtb by default" ++ depends on OF ++ help ++ Enabling this option will cause a concatenated Image.gz and list of ++ DTBs to be built by default (instead of a standalone Image.gz.) ++ The image will built in arch/arm64/boot/Image.gz-dtb ++ ++choice ++ prompt "Appended DTB Kernel Image name" ++ depends on BUILD_ARM64_APPENDED_DTB_IMAGE ++ help ++ Enabling this option will cause a specific kernel image Image or ++ Image.gz to be used for final image creation. ++ The image will built in arch/arm64/boot/IMAGE-NAME-dtb ++ ++ config IMG_GZ_DTB ++ bool "Image.gz-dtb" ++ config IMG_DTB ++ bool "Image-dtb" ++endchoice ++ ++config BUILD_ARM64_APPENDED_KERNEL_IMAGE_NAME ++ string ++ depends on BUILD_ARM64_APPENDED_DTB_IMAGE ++ default "Image.gz-dtb" if IMG_GZ_DTB ++ default "Image-dtb" if IMG_DTB ++ ++config BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES ++ string "Default dtb names" ++ depends on BUILD_ARM64_APPENDED_DTB_IMAGE ++ help ++ Space separated list of names of dtbs to append when ++ building a concatenated Image.gz-dtb. ++ + endmenu + + menu "Userspace binary formats" +diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms +index 101794f..6eeaa85 100644 +--- a/arch/arm64/Kconfig.platforms ++++ b/arch/arm64/Kconfig.platforms +@@ -81,6 +81,35 @@ config ARCH_HISI + help + This enables support for Hisilicon ARMv8 SoC family + ++config ARCH_HISI_BVT ++ bool "Hisilicon BVT SoC Family" ++ select ARM_TIMER_SP804 ++ select HISILICON_IRQ_MBIGEN if PCI ++ select PINCTRL ++ help ++ This enables support for Hisilicon BVT ARMv8 SoC family ++ ++config ARCH_HI3559AV100 ++ bool "Hisilicon hi3559av100 family" ++ depends on ARCH_HISI_BVT ++ select ARM_TIMER_SP804 ++ select HISILICON_IRQ_MBIGEN if PCI ++ select PINCTRL ++ help ++ Support for Hisilicon Hi3559AV100 Soc family ++ ++config ACCESS_M7_DEV ++ bool "Enable to access the devices of m7" ++ depends on ARCH_HI3559AV100 ++ help ++ supprot to access the devices of M7 ++ ++config ARCH_HISI_BVT_AMP ++ bool "Hisilicon AMP solution" ++ depends on ARCH_HI3559AV100 ++ help ++ Support for Hisilicon Hi3559AV100 AMP ++ + config ARCH_MEDIATEK + bool "Mediatek MT65xx & MT81xx ARMv8 SoC" + select ARM_GIC +diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile +index 3635b86..96de78d 100644 +--- a/arch/arm64/Makefile ++++ b/arch/arm64/Makefile +@@ -12,6 +12,7 @@ + + LDFLAGS_vmlinux :=-p --no-undefined -X + CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET) ++OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S + GZFLAGS :=-9 + + ifneq ($(CONFIG_RELOCATABLE),) +@@ -94,20 +95,27 @@ libs-y := arch/arm64/lib/ $(libs-y) + core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a + + # Default target when executing plain make ++ifeq ($(CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE),y) ++KBUILD_IMAGE := $(subst $\",,$(CONFIG_BUILD_ARM64_APPENDED_KERNEL_IMAGE_NAME)) ++else + KBUILD_IMAGE := Image.gz ++endif ++ + KBUILD_DTBS := dtbs + + all: $(KBUILD_IMAGE) $(KBUILD_DTBS) + + boot := arch/arm64/boot + +-Image: vmlinux ++uImage Image: vmlinux + $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ + +-Image.%: Image ++uImage: dtbs ++ ++Image.%: vmlinux + $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ + +-zinstall install: ++zinstall install: vmlinux + $(Q)$(MAKE) $(build)=$(boot) $@ + + %.dtb: scripts +@@ -121,6 +129,9 @@ dtbs: prepare scripts + dtbs_install: + $(Q)$(MAKE) $(dtbinst)=$(boot)/dts + ++Image-dtb Image.gz-dtb: vmlinux scripts dtbs ++ $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ ++ + PHONY += vdso_install + vdso_install: + $(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso $@ +diff --git a/arch/arm64/boot/Makefile b/arch/arm64/boot/Makefile +index 1f012c5..8ad5d9b 100644 +--- a/arch/arm64/boot/Makefile ++++ b/arch/arm64/boot/Makefile +@@ -14,9 +14,11 @@ + # Based on the ia64 boot/Makefile. + # + +-OBJCOPYFLAGS_Image :=-O binary -R .note -R .note.gnu.build-id -R .comment -S ++include $(srctree)/arch/arm64/boot/dts/Makefile + +-targets := Image Image.gz ++targets := Image Image.gz uImage ++ ++DTB_OBJS := $(addprefix $(obj)/dts/,$(DTB_LIST)) + + $(obj)/Image: vmlinux FORCE + $(call if_changed,objcopy) +@@ -24,6 +26,9 @@ $(obj)/Image: vmlinux FORCE + $(obj)/Image.bz2: $(obj)/Image FORCE + $(call if_changed,bzip2) + ++$(obj)/Image-dtb: $(obj)/Image $(DTB_OBJS) FORCE ++ $(call if_changed,cat) ++ + $(obj)/Image.gz: $(obj)/Image FORCE + $(call if_changed,gzip) + +@@ -36,10 +41,35 @@ $(obj)/Image.lzma: $(obj)/Image FORCE + $(obj)/Image.lzo: $(obj)/Image FORCE + $(call if_changed,lzo) + +-install: ++$(obj)/Image.gz-dtb: $(obj)/Image.gz $(DTB_OBJS) FORCE ++ $(call if_changed,cat) ++ ++UIMAGE_LOADADDR=$(TEXT_OFFSET) ++UIMAGE_ENTRYADDR=$(TEXT_OFFSET) ++#UIMAGE_COMPRESSION = gzip ++check_for_multiple_loadaddr = \ ++if [ $(words $(UIMAGE_LOADADDR)) -ne 1 ]; then \ ++ echo 'multiple (or no) load addresses: $(UIMAGE_LOADADDR)'; \ ++ echo 'This is incompatible with uImages'; \ ++ echo 'Specify LOADADDR on the commandline to build an uImage'; \ ++ false; \ ++fi ++ ++rm_uimage: ++ @rm -f $(obj)/uImage ++ ++$(obj)/uImage: $(obj)/Image rm_uimage FORCE ++ @$(check_for_multiple_loadaddr) ++ @dd if=$< of=$<.dd ibs=4096 conv=sync && mv $<.dd $< ++ $(call if_changed,uimage) ++ $(if $(CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE),@$(kecho) ' CAT $(DTB_OBJS) to $@') ++ $(if $(CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE),@cat $(DTB_OBJS) >>$@,) ++ @$(kecho) ' Image $@ is ready' ++ ++install: $(obj)/Image + $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \ + $(obj)/Image System.map "$(INSTALL_PATH)" + +-zinstall: ++zinstall: $(obj)/Image.gz + $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \ + $(obj)/Image.gz System.map "$(INSTALL_PATH)" +diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile +index 6684f97..b31e443 100644 +--- a/arch/arm64/boot/dts/Makefile ++++ b/arch/arm64/boot/dts/Makefile +@@ -23,8 +23,22 @@ dts-dirs += zte + + subdir-y := $(dts-dirs) + +-dtstree := $(srctree)/$(src) ++dtstree := $(srctree)/$(src)/dts + + dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(foreach d,$(dts-dirs), $(wildcard $(dtstree)/$(d)/*.dts))) + + always := $(dtb-y) ++ ++targets += dtbs ++ ++DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES)) ++ifneq ($(DTB_NAMES),) ++DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES)) ++else ++DTB_LIST := $(dtb-y) ++endif ++targets += $(DTB_LIST) ++ ++dtbs: $(addprefix $(obj)/, $(DTB_LIST)) ++ ++clean-files := dts/*.dtb *.dtb +diff --git a/arch/arm64/boot/dts/hisilicon/Makefile b/arch/arm64/boot/dts/hisilicon/Makefile +index d5f43a0..b632070 100644 +--- a/arch/arm64/boot/dts/hisilicon/Makefile ++++ b/arch/arm64/boot/dts/hisilicon/Makefile +@@ -1,6 +1,9 @@ + dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb + dtb-$(CONFIG_ARCH_HISI) += hip05-d02.dtb + dtb-$(CONFIG_ARCH_HISI) += hip06-d03.dtb ++dtb-$(CONFIG_ARCH_HI3559AV100) += hi3559av100-demb-flash.dtb ++dtb-$(CONFIG_ARCH_HI3559AV100) += hi3559av100-demb-emmc.dtb ++dtb-$(CONFIG_ARCH_HI3559AV100) += hi3559av100-demb-ufs.dtb + + always := $(dtb-y) + subdir-y := $(dts-dirs) +diff --git a/arch/arm64/boot/dts/hisilicon/hi3559av100-demb-amp.dts b/arch/arm64/boot/dts/hisilicon/hi3559av100-demb-amp.dts +new file mode 100644 +index 0000000..593af25 +--- /dev/null ++++ b/arch/arm64/boot/dts/hisilicon/hi3559av100-demb-amp.dts +@@ -0,0 +1,600 @@ ++/* Copyright (c) 2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/dts-v1/; ++/* reserved for warmreset */ ++/* reserved for arm trustedfirmware */ ++/* Modify this configuration according to the system framework */ ++/memreserve/ 0x53000000 0x00200000; ++#include "hi3559av100.dtsi" ++ ++/ { ++ model = "Hisilicon HI3559AV100 DEMO Board"; ++ compatible = "hisilicon,hi3559av100"; ++ ++ aliases { ++ serial0 = &uart0; ++ serial1 = &uart1; ++ serial2 = &uart2; ++ serial3 = &uart3; ++ serial4 = &uart4; ++ serial5 = &uart5; ++ serial6 = &uart6; ++ serial7 = &uart7; ++ serial8 = &uart8; ++ serial9 = &uart9; ++ ++ i2c0 = &i2c_bus0; ++ i2c1 = &i2c_bus1; ++ i2c2 = &i2c_bus2; ++ i2c3 = &i2c_bus3; ++ i2c4 = &i2c_bus4; ++ i2c5 = &i2c_bus5; ++ i2c6 = &i2c_bus6; ++ i2c7 = &i2c_bus7; ++ i2c8 = &i2c_bus8; ++ i2c9 = &i2c_bus9; ++ i2c10 = &i2c_bus10; ++ i2c11 = &i2c_bus11; ++ i2c12 = &i2c_bus12; ++ i2c13 = &i2c_bus13; ++ i2c14 = &i2c_bus14; ++ i2c15 = &i2c_bus15; ++ i2c16 = &i2c_bus16; ++ i2c17 = &i2c_bus17; ++ i2c18 = &i2c_bus18; ++ i2c19 = &i2c_bus19; ++ ++ spi0 = &spi_bus0; ++ spi1 = &spi_bus1; ++ spi2 = &spi_bus2; ++ spi3 = &spi_bus3; ++ spi4 = &spi_bus4; ++ spi5 = &spi_bus5; ++ spi6 = &spi_bus6; ++ spi7 = &spi_bus7; ++ ++ gpio0 = &gpio_chip0; ++ gpio1 = &gpio_chip1; ++ gpio2 = &gpio_chip2; ++ gpio3 = &gpio_chip3; ++ gpio4 = &gpio_chip4; ++ gpio5 = &gpio_chip5; ++ gpio6 = &gpio_chip6; ++ gpio7 = &gpio_chip7; ++ gpio8 = &gpio_chip8; ++ gpio9 = &gpio_chip9; ++ gpio10 = &gpio_chip10; ++ gpio11 = &gpio_chip11; ++ gpio12 = &gpio_chip12; ++ gpio13 = &gpio_chip13; ++ gpio14 = &gpio_chip14; ++ gpio15 = &gpio_chip15; ++ gpio16 = &gpio_chip16; ++ gpio17 = &gpio_chip17; ++ gpio18 = &gpio_chip18; ++ }; ++ ++ chosen { ++ bootargs = "mem=512M console=ttyAMA0,115200 clk_ignore_unused root=/dev/mtdblock2 rootfstype=yaffs2 rw mtdparts=hinand:1M(boot),9M(kernel),32M(rootfs),1M(this_bootargs_string_is_reserved_for_bootargs_form_uboot!!!_it_must_be_longer_than_bootargs_form_uboot!!!_this_bootargs_string_is_reserved_for_bootargs_form_uboot!!!_it_must_be_longer_than_bootargs_form_uboot!!!_this_bootargs_string_is_reserved_for_bootargs_form_uboot!!!_it_must_be_longer_than_bootargs_form_uboot!!!_this_bootargs_string_is_reserved_for_bootargs_form_uboot!!!_it_must_be_longer_than_bootargs_form_uboot!!!_this_bootargs_string_is_reserved_for_bootargs_form_uboot!!!_it_must_be_longer_than_bootargs_form_uboot!!!)"; ++ ++ linux,initrd-start = <0x60000040>; ++ linux,initrd-end = <0x61000000>; ++ }; ++ ++ cpus { ++ #address-cells = <2>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ compatible = "arm,cortex-a53"; ++ device_type = "cpu"; ++ reg = <0x0 0x0>; ++ enable-method = "psci"; ++ cpu-idle-states = <&CPU_POWERDOWN &CPU_STANDBY>; ++ }; ++ ++ cpu@1 { ++ compatible = "arm,cortex-a53"; ++ device_type = "cpu"; ++ reg = <0x0 0x1>; ++ enable-method = "psci"; ++ cpu-idle-states = <&CPU_POWERDOWN &CPU_STANDBY>; ++ }; ++ cpu@2 { ++ compatible = "arm,cortex-a73"; ++ device_type = "cpu"; ++ reg = <0x0 0x100>; ++ enable-method = "psci"; ++ cpu-idle-states = <&CPU_POWERDOWN &CPU_STANDBY>; ++ }; ++ cpu@3 { ++ compatible = "arm,cortex-a73"; ++ device_type = "cpu"; ++ reg = <0x0 0x101>; ++ enable-method = "psci"; ++ cpu-idle-states = <&CPU_POWERDOWN &CPU_STANDBY>; ++ }; ++ ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x0 0x50000000 0x0 0x80000000>; /* system memory base */ ++ }; ++}; ++ ++&ipcm { ++ status = "okay"; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "disabled"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&uart3 { ++ status = "okay"; ++}; ++ ++&uart4 { ++ status = "okay"; ++}; ++ ++&uart5 { ++ status = "disable"; ++}; ++ ++&uart6 { ++ status = "disable"; ++}; ++ ++&uart7 { ++ status = "disable"; ++}; ++ ++&uart8 { ++ status = "disable"; ++}; ++ ++&uart9 { ++ status = "disable"; ++}; ++ ++&i2c_bus0 { ++ status = "okay"; ++}; ++ ++&i2c_bus1 { ++ status = "okay"; ++}; ++ ++&i2c_bus2 { ++ status = "okay"; ++}; ++ ++&i2c_bus3 { ++ status = "okay"; ++}; ++ ++&i2c_bus4 { ++ status = "okay"; ++}; ++ ++&i2c_bus5 { ++ status = "okay"; ++}; ++ ++&i2c_bus6 { ++ status = "okay"; ++}; ++ ++&i2c_bus7 { ++ status = "okay"; ++}; ++ ++&i2c_bus8 { ++ status = "okay"; ++}; ++ ++&i2c_bus9 { ++ status = "okay"; ++}; ++ ++&i2c_bus10 { ++ status = "okay"; ++}; ++ ++&i2c_bus11 { ++ status = "okay"; ++}; ++ ++&i2c_bus12 { ++ status = "disable"; ++}; ++ ++&i2c_bus13 { ++ status = "disable"; ++}; ++ ++&i2c_bus14 { ++ status = "disable"; ++}; ++ ++&i2c_bus15 { ++ status = "disable"; ++}; ++ ++&i2c_bus16 { ++ status = "disable"; ++}; ++ ++&i2c_bus17 { ++ status = "disable"; ++}; ++ ++&i2c_bus18 { ++ status = "disable"; ++}; ++ ++&i2c_bus19 { ++ status = "disable"; ++}; ++ ++&spi_bus0{ ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++}; ++ ++&spi_bus1{ ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++}; ++ ++&spi_bus2{ ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++}; ++ ++&spi_bus3{ ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++}; ++ ++&spi_bus4{ ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ ++ spidev@2 { ++ compatible = "rohm,dh2228fv"; ++ reg = <2>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ ++ spidev@3 { ++ compatible = "rohm,dh2228fv"; ++ reg = <3>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++}; ++ ++&spi_bus5{ ++ status = "disable"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ spidev@2 { ++ compatible = "rohm,dh2228fv"; ++ reg = <2>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++}; ++ ++&spi_bus6{ ++ status = "disable"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ spidev@2 { ++ compatible = "rohm,dh2228fv"; ++ reg = <2>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++}; ++ ++&spi_bus7{ ++ status = "disable"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++}; ++ ++&gpio_chip0 { ++ status = "okay"; ++}; ++ ++&gpio_chip1 { ++ status = "okay"; ++}; ++ ++&gpio_chip2 { ++ status = "okay"; ++}; ++ ++&gpio_chip3 { ++ status = "okay"; ++}; ++ ++&gpio_chip4 { ++ status = "okay"; ++}; ++ ++&gpio_chip5 { ++ status = "okay"; ++}; ++ ++&gpio_chip6 { ++ status = "okay"; ++}; ++ ++&gpio_chip7 { ++ status = "okay"; ++}; ++ ++&gpio_chip8 { ++ status = "okay"; ++}; ++ ++&gpio_chip9 { ++ status = "okay"; ++}; ++ ++&gpio_chip10 { ++ status = "okay"; ++}; ++ ++&gpio_chip11 { ++ status = "okay"; ++}; ++ ++&gpio_chip12 { ++ status = "okay"; ++}; ++ ++&gpio_chip13 { ++ status = "okay"; ++}; ++ ++&gpio_chip14 { ++ status = "okay"; ++}; ++ ++&gpio_chip15 { ++ status = "okay"; ++}; ++ ++&gpio_chip16 { ++ status = "okay"; ++}; ++ ++&gpio_chip17 { ++ status = "okay"; ++}; ++ ++&gpio_chip18 { ++ status = "okay"; ++}; ++ ++&rtc{ ++ status = "okay"; ++}; ++ ++&hisfc { ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++}; ++ ++&hisnfc { ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ }; ++}; ++ ++&hinfc { ++ hinand { ++ compatible = "jedec,nand"; ++ reg = <0>; ++ nand-max-frequency = <200000000>; ++ }; ++}; ++ ++&mdio { ++ ethphy: ethernet-phy@1 { ++ reg = <1>; ++ }; ++}; ++ ++#if 0 ++&mdio1 { ++ ethphy1: ethernet-phy@3 { ++ reg = <3>; ++ }; ++}; ++#endif ++ ++&higmac { ++ phy-handle = <ðphy>; ++ phy-mode = "rgmii"; ++}; ++ ++#if 0 ++&higmac1 { ++ phy-handle = <ðphy1>; ++ phy-mode = "rgmii"; ++}; ++#endif ++ ++&mmc1 { ++ status = "okay"; ++}; ++ ++&mmc2 { ++ status = "okay"; ++}; ++ ++&mmc3 { ++ status = "disable"; ++}; ++ ++&hivdmac { ++ status = "disabled"; ++}; ++ ++&hiedmacv310_0 { ++ status = "okay"; ++}; ++ ++&hiedmacv310_1 { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/hisilicon/hi3559av100-demb-emmc.dts b/arch/arm64/boot/dts/hisilicon/hi3559av100-demb-emmc.dts +new file mode 100644 +index 0000000..09e8569 +--- /dev/null ++++ b/arch/arm64/boot/dts/hisilicon/hi3559av100-demb-emmc.dts +@@ -0,0 +1,32 @@ ++/* Copyright (c) 2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++#include <../../../../../include/generated/autoconf.h> ++ ++#ifdef CONFIG_ARCH_HISI_BVT_AMP ++#include "hi3559av100-demb-amp.dts" ++#else ++#include "hi3559av100-demb.dts" ++#endif ++ ++&mmc0 { ++ status = "okay"; ++}; ++ ++&ufs { ++ status = "disabled"; ++}; ++ +diff --git a/arch/arm64/boot/dts/hisilicon/hi3559av100-demb-flash.dts b/arch/arm64/boot/dts/hisilicon/hi3559av100-demb-flash.dts +new file mode 100644 +index 0000000..64ae273 +--- /dev/null ++++ b/arch/arm64/boot/dts/hisilicon/hi3559av100-demb-flash.dts +@@ -0,0 +1,32 @@ ++/* Copyright (c) 2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++#include <../../../../../include/generated/autoconf.h> ++ ++#ifdef CONFIG_ARCH_HISI_BVT_AMP ++#include "hi3559av100-demb-amp.dts" ++#else ++#include "hi3559av100-demb.dts" ++#endif ++ ++&mmc0 { ++ status = "disabled"; ++}; ++ ++&ufs { ++ status = "disabled"; ++}; ++ +diff --git a/arch/arm64/boot/dts/hisilicon/hi3559av100-demb-ufs.dts b/arch/arm64/boot/dts/hisilicon/hi3559av100-demb-ufs.dts +new file mode 100644 +index 0000000..cbc2a72 +--- /dev/null ++++ b/arch/arm64/boot/dts/hisilicon/hi3559av100-demb-ufs.dts +@@ -0,0 +1,32 @@ ++/* Copyright (c) 2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++#include <../../../../../include/generated/autoconf.h> ++ ++#ifdef CONFIG_ARCH_HISI_BVT_AMP ++#include "hi3559av100-demb-amp.dts" ++#else ++#include "hi3559av100-demb.dts" ++#endif ++ ++&mmc0 { ++ status = "disabled"; ++}; ++ ++&ufs { ++ status = "okay"; ++}; ++ +diff --git a/arch/arm64/boot/dts/hisilicon/hi3559av100-demb.dts b/arch/arm64/boot/dts/hisilicon/hi3559av100-demb.dts +new file mode 100644 +index 0000000..ba2d1ff +--- /dev/null ++++ b/arch/arm64/boot/dts/hisilicon/hi3559av100-demb.dts +@@ -0,0 +1,596 @@ ++/* Copyright (c) 2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/dts-v1/; ++/* reserved for warmreset */ ++/* reserved for arm trustedfirmware */ ++/* Modify this configuration according to the system framework */ ++/memreserve/ 0x47000000 0x00200000; ++#include "hi3559av100.dtsi" ++ ++/ { ++ model = "Hisilicon HI3559AV100 DEMO Board"; ++ compatible = "hisilicon,hi3559av100"; ++ ++ aliases { ++ serial0 = &uart0; ++ serial1 = &uart1; ++ serial2 = &uart2; ++ serial3 = &uart3; ++ serial4 = &uart4; ++ serial5 = &uart5; ++ serial6 = &uart6; ++ serial7 = &uart7; ++ serial8 = &uart8; ++ serial9 = &uart9; ++ ++ i2c0 = &i2c_bus0; ++ i2c1 = &i2c_bus1; ++ i2c2 = &i2c_bus2; ++ i2c3 = &i2c_bus3; ++ i2c4 = &i2c_bus4; ++ i2c5 = &i2c_bus5; ++ i2c6 = &i2c_bus6; ++ i2c7 = &i2c_bus7; ++ i2c8 = &i2c_bus8; ++ i2c9 = &i2c_bus9; ++ i2c10 = &i2c_bus10; ++ i2c11 = &i2c_bus11; ++ i2c12 = &i2c_bus12; ++ i2c13 = &i2c_bus13; ++ i2c14 = &i2c_bus14; ++ i2c15 = &i2c_bus15; ++ i2c16 = &i2c_bus16; ++ i2c17 = &i2c_bus17; ++ i2c18 = &i2c_bus18; ++ i2c19 = &i2c_bus19; ++ ++ spi0 = &spi_bus0; ++ spi1 = &spi_bus1; ++ spi2 = &spi_bus2; ++ spi3 = &spi_bus3; ++ spi4 = &spi_bus4; ++ spi5 = &spi_bus5; ++ spi6 = &spi_bus6; ++ spi7 = &spi_bus7; ++ ++ gpio0 = &gpio_chip0; ++ gpio1 = &gpio_chip1; ++ gpio2 = &gpio_chip2; ++ gpio3 = &gpio_chip3; ++ gpio4 = &gpio_chip4; ++ gpio5 = &gpio_chip5; ++ gpio6 = &gpio_chip6; ++ gpio7 = &gpio_chip7; ++ gpio8 = &gpio_chip8; ++ gpio9 = &gpio_chip9; ++ gpio10 = &gpio_chip10; ++ gpio11 = &gpio_chip11; ++ gpio12 = &gpio_chip12; ++ gpio13 = &gpio_chip13; ++ gpio14 = &gpio_chip14; ++ gpio15 = &gpio_chip15; ++ gpio16 = &gpio_chip16; ++ gpio17 = &gpio_chip17; ++ gpio18 = &gpio_chip18; ++ }; ++ ++ chosen { ++ bootargs = "mem=512M console=ttyAMA0,115200 clk_ignore_unused root=/dev/mtdblock2 rootfstype=yaffs2 rw mtdparts=hinand:1M(boot),9M(kernel),32M(rootfs),1M(this_bootargs_string_is_reserved_for_bootargs_form_uboot!!!_it_must_be_longer_than_bootargs_form_uboot!!!_this_bootargs_string_is_reserved_for_bootargs_form_uboot!!!_it_must_be_longer_than_bootargs_form_uboot!!!_this_bootargs_string_is_reserved_for_bootargs_form_uboot!!!_it_must_be_longer_than_bootargs_form_uboot!!!_this_bootargs_string_is_reserved_for_bootargs_form_uboot!!!_it_must_be_longer_than_bootargs_form_uboot!!!_this_bootargs_string_is_reserved_for_bootargs_form_uboot!!!_it_must_be_longer_than_bootargs_form_uboot!!!)"; ++ ++ linux,initrd-start = <0x60000040>; ++ linux,initrd-end = <0x61000000>; ++ }; ++ ++ cpus { ++ #address-cells = <2>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ compatible = "arm,cortex-a53"; ++ device_type = "cpu"; ++ reg = <0x0 0x0>; ++ enable-method = "psci"; ++ cpu-idle-states = <&CPU_POWERDOWN &CPU_STANDBY>; ++ }; ++ ++ cpu@1 { ++ compatible = "arm,cortex-a53"; ++ device_type = "cpu"; ++ reg = <0x0 0x1>; ++ enable-method = "psci"; ++ cpu-idle-states = <&CPU_POWERDOWN &CPU_STANDBY>; ++ }; ++ cpu@2 { ++ compatible = "arm,cortex-a73"; ++ device_type = "cpu"; ++ reg = <0x0 0x100>; ++ enable-method = "psci"; ++ cpu-idle-states = <&CPU_POWERDOWN &CPU_STANDBY>; ++ }; ++ cpu@3 { ++ compatible = "arm,cortex-a73"; ++ device_type = "cpu"; ++ reg = <0x0 0x101>; ++ enable-method = "psci"; ++ cpu-idle-states = <&CPU_POWERDOWN &CPU_STANDBY>; ++ }; ++ ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x0 0x44000000 0x0 0x80000000>; /* system memory base */ ++ }; ++}; ++ ++&ipcm { ++ status = "okay"; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&uart3 { ++ status = "okay"; ++}; ++ ++&uart4 { ++ status = "okay"; ++}; ++ ++&uart5 { ++ status = "disable"; ++}; ++ ++&uart6 { ++ status = "disable"; ++}; ++ ++&uart7 { ++ status = "disable"; ++}; ++ ++&uart8 { ++ status = "disable"; ++}; ++ ++&uart9 { ++ status = "disable"; ++}; ++ ++&i2c_bus0 { ++ status = "okay"; ++}; ++ ++&i2c_bus1 { ++ status = "okay"; ++}; ++ ++&i2c_bus2 { ++ status = "okay"; ++}; ++ ++&i2c_bus3 { ++ status = "okay"; ++}; ++ ++&i2c_bus4 { ++ status = "okay"; ++}; ++ ++&i2c_bus5 { ++ status = "okay"; ++}; ++ ++&i2c_bus6 { ++ status = "okay"; ++}; ++ ++&i2c_bus7 { ++ status = "okay"; ++}; ++ ++&i2c_bus8 { ++ status = "okay"; ++}; ++ ++&i2c_bus9 { ++ status = "okay"; ++}; ++ ++&i2c_bus10 { ++ status = "okay"; ++}; ++ ++&i2c_bus11 { ++ status = "okay"; ++}; ++ ++&i2c_bus12 { ++ status = "disable"; ++}; ++ ++&i2c_bus13 { ++ status = "disable"; ++}; ++ ++&i2c_bus14 { ++ status = "disable"; ++}; ++ ++&i2c_bus15 { ++ status = "disable"; ++}; ++ ++&i2c_bus16 { ++ status = "disable"; ++}; ++ ++&i2c_bus17 { ++ status = "disable"; ++}; ++ ++&i2c_bus18 { ++ status = "disable"; ++}; ++ ++&i2c_bus19 { ++ status = "disable"; ++}; ++ ++&spi_bus0{ ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++}; ++ ++&spi_bus1{ ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++}; ++ ++&spi_bus2{ ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++}; ++ ++&spi_bus3{ ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++}; ++ ++&spi_bus4{ ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ ++ spidev@2 { ++ compatible = "rohm,dh2228fv"; ++ reg = <2>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ ++ spidev@3 { ++ compatible = "rohm,dh2228fv"; ++ reg = <3>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++}; ++ ++&spi_bus5{ ++ status = "disable"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ spidev@2 { ++ compatible = "rohm,dh2228fv"; ++ reg = <2>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++}; ++ ++&spi_bus6{ ++ status = "disable"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++ spidev@2 { ++ compatible = "rohm,dh2228fv"; ++ reg = <2>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++}; ++ ++&spi_bus7{ ++ status = "disable"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com_mode = <0>; ++ spi-max-frequency = <12000000>; ++ }; ++}; ++ ++&gpio_chip0 { ++ status = "okay"; ++}; ++ ++&gpio_chip1 { ++ status = "okay"; ++}; ++ ++&gpio_chip2 { ++ status = "okay"; ++}; ++ ++&gpio_chip3 { ++ status = "okay"; ++}; ++ ++&gpio_chip4 { ++ status = "okay"; ++}; ++ ++&gpio_chip5 { ++ status = "okay"; ++}; ++ ++&gpio_chip6 { ++ status = "okay"; ++}; ++ ++&gpio_chip7 { ++ status = "okay"; ++}; ++ ++&gpio_chip8 { ++ status = "okay"; ++}; ++ ++&gpio_chip9 { ++ status = "okay"; ++}; ++ ++&gpio_chip10 { ++ status = "okay"; ++}; ++ ++&gpio_chip11 { ++ status = "okay"; ++}; ++ ++&gpio_chip12 { ++ status = "okay"; ++}; ++ ++&gpio_chip13 { ++ status = "okay"; ++}; ++ ++&gpio_chip14 { ++ status = "okay"; ++}; ++ ++&gpio_chip15 { ++ status = "okay"; ++}; ++ ++&gpio_chip16 { ++ status = "okay"; ++}; ++ ++&gpio_chip17 { ++ status = "okay"; ++}; ++ ++&gpio_chip18 { ++ status = "okay"; ++}; ++ ++&rtc{ ++ status = "okay"; ++}; ++ ++&hisfc { ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++}; ++ ++&hisnfc { ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ }; ++}; ++ ++&hinfc { ++ hinand { ++ compatible = "jedec,nand"; ++ reg = <0>; ++ nand-max-frequency = <200000000>; ++ }; ++}; ++ ++&mdio { ++ ethphy: ethernet-phy@1 { ++ reg = <1>; ++ }; ++}; ++ ++&mdio1 { ++ ethphy1: ethernet-phy@3 { ++ reg = <3>; ++ }; ++}; ++ ++&higmac { ++ phy-handle = <ðphy>; ++ phy-mode = "rgmii"; ++}; ++ ++&higmac1 { ++ phy-handle = <ðphy1>; ++ phy-mode = "rgmii"; ++}; ++ ++&mmc1 { ++ status = "okay"; ++}; ++ ++&mmc2 { ++ status = "okay"; ++}; ++ ++&mmc3 { ++ status = "disable"; ++}; ++ ++&hivdmac { ++ status = "disabled"; ++}; ++ ++&hiedmacv310_0 { ++ status = "okay"; ++}; ++ ++&hiedmacv310_1 { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/hisilicon/hi3559av100.dtsi b/arch/arm64/boot/dts/hisilicon/hi3559av100.dtsi +new file mode 100644 +index 0000000..0fae2e78 +--- /dev/null ++++ b/arch/arm64/boot/dts/hisilicon/hi3559av100.dtsi +@@ -0,0 +1,1261 @@ ++/* Copyright (c) 2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/* reserved for arm trustedfirmware */ ++#include ++/ { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ interrupt-parent = <&gic>; ++ ++ gic: interrupt-controller@1F100000 { ++ compatible = "arm,gic-400"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ /* gic dist base, gic cpu base */ ++ reg = <0x0 0x1F101000 0x0 0x1000>, <0x0 0x1F102000 0x0 0x100>; ++ }; ++ ++ psci { ++ compatible = "arm,psci-0.2"; ++ method = "smc"; ++ }; ++ ++ clock: clock0 { ++ compatible = "hisilicon,hi3559av100-clock", "syscon"; ++ #clock-cells = <1>; ++ #reset-cells = <2>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x0 0x12010000 0x0 0x10000>; ++ }; ++ clock_shub: clock_shub0 { ++ compatible = "hisilicon,hi3559av100-shub-clock"; ++ #clock-cells = <1>; ++ #reset-cells = <2>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x0 0x18020000 0x0 0x10000>; ++ }; ++ ++ idle-states { ++ entry-method = "arm,psci"; ++ ++ CPU_POWERDOWN: cpu-powerdown { ++ compatible = "arm,idle-state"; ++ local-timer-stop; ++ arm,psci-suspend-param = <0x0010000>; ++ entry-latency-us = <20>; ++ exit-latency-us = <40>; ++ min-residency-us = <80>; ++ }; ++ CPU_STANDBY: cpu-standby { ++ compatible = "arm,idle-state"; ++ arm,psci-suspend-param = <0x0000000>; ++ entry-latency-us = <0x3fffffff>; ++ exit-latency-us = <0x40000000>; ++ min-residency-us = <0xffffffff>; ++ }; ++ }; ++ ipcm: ipcm@12090000 { ++ compatible = "hisilicon,ipcm-interrupt"; ++ interrupt-parent = <&gic>; ++ interrupts = <0 211 4>, <0 212 4>; ++ reg = <0x0 0x12090000 0x0 0x1000>; ++ status = "disabled"; ++ }; ++ soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ device_type = "soc"; ++ interrupt-parent = <&gic>; ++ ranges = <0x0 0x00000000 0x0 0xffffffff>; ++ ++ clk_3m: clk_3m { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <3000000>; ++ }; ++ ++ amba { ++ compatible = "arm,amba-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ ranges; ++ ++ arm-timer { ++ compatible = "arm,armv8-timer"; ++ interrupts = <1 13 0xf04>, ++ <1 14 0xf04>; ++ clock-frequency = <50000000>; ++ }; ++ ++ timer@12000000 { ++ compatible = "hisilicon,hisp804"; ++ reg = <0x12000000 0x20>, /* clocksource */ ++ <0x1d840000 0x20>, /* local timer for each cpu */ ++ <0x1d840020 0x20>, ++ <0x1d850000 0x20>, ++ <0x1d850020 0x20>; ++ interrupts = <0 113 4>, /* irq of local timer0/1 */ ++ <0 114 4>, /* irq of local timer2/3 */ ++ <0 115 4>, /* irq of local timer4/5 */ ++ <0 116 4>; /* irq of local timer6/7 */ ++ clocks = <&clk_3m>; ++ clock-names = "apb_pclk"; ++ }; ++ ++ uart0: uart@12100000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12100000 0x1000>; ++ interrupts = <0 6 4>; ++ clocks = <&clock HI3559AV100_UART0_CLK>; ++ clock-names = "apb_pclk"; ++ //dmas = <&hiedmacv310_0 0 0>, <&hiedmacv310_0 1 1>; ++ //dma-names = "tx","rx"; ++ status = "disabled"; ++ }; ++ ++ uart1: uart@12101000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12101000 0x1000>; ++ interrupts = <0 7 4>; ++ clocks = <&clock HI3559AV100_UART1_CLK>; ++ clock-names = "apb_pclk"; ++ dmas = <&hiedmacv310_0 2 2>, <&hiedmacv310_0 3 3>; ++ dma-names = "tx","rx"; ++ status = "disabled"; ++ }; ++ ++ uart2: uart@12102000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12102000 0x1000>; ++ interrupts = <0 8 4>; ++ clocks = <&clock HI3559AV100_UART2_CLK>; ++ clock-names = "apb_pclk"; ++ dmas = <&hiedmacv310_0 4 4>, <&hiedmacv310_0 5 5>; ++ dma-names = "tx","rx"; ++ status = "disabled"; ++ }; ++ ++ uart3: uart@12103000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12103000 0x1000>; ++ interrupts = <0 9 4>; ++ clocks = <&clock HI3559AV100_UART3_CLK>; ++ clock-names = "apb_pclk"; ++ dmas = <&hiedmacv310_0 6 6>, <&hiedmacv310_0 7 7>; ++ dma-names = "tx","rx"; ++ status = "disabled"; ++ }; ++ ++ uart4: uart@12104000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12104000 0x1000>; ++ interrupts = <0 10 4>; ++ clocks = <&clock HI3559AV100_UART4_CLK>; ++ clock-names = "apb_pclk"; ++ dmas = <&hiedmacv310_0 8 8>, <&hiedmacv310_0 9 9>; ++ dma-names = "tx","rx"; ++ status = "disabled"; ++ }; ++ ++ uart5: uart@18060000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x18060000 0x1000>; ++ interrupts = <0 185 4>; ++ clocks = <&clock_shub HI3559AV100_SHUB_UART0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart6: uart@18061000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x18061000 0x1000>; ++ interrupts = <0 186 4>; ++ clocks = <&clock_shub HI3559AV100_SHUB_UART1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart7: uart@18062000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x18062000 0x1000>; ++ interrupts = <0 187 4>; ++ clocks = <&clock_shub HI3559AV100_SHUB_UART2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart8: uart@18063000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x18063000 0x1000>; ++ interrupts = <0 188 4>; ++ clocks = <&clock_shub HI3559AV100_SHUB_UART3_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart9: uart@18064000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x18064000 0x1000>; ++ interrupts = <0 189 4>; ++ clocks = <&clock_shub HI3559AV100_SHUB_UART4_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ i2c_bus0: i2c@12110000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x12110000 0x1000>; ++ clocks = <&clock HI3559AV100_I2C0_CLK>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ dmas = <&hiedmacv310_0 14 10>, <&hiedmacv310_0 15 11>; ++ dma-names = "tx","rx"; ++ }; ++ ++ i2c_bus1: i2c@12111000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x12111000 0x1000>; ++ clocks = <&clock HI3559AV100_I2C1_CLK>; ++ clock-frequency = <100000>; ++ dmas = <&hiedmacv310_0 12 12>, <&hiedmacv310_0 13 13>; ++ dma-names = "tx","rx"; ++ status = "disabled"; ++ }; ++ ++ i2c_bus2: i2c@12112000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x12112000 0x1000>; ++ clocks = <&clock HI3559AV100_I2C2_CLK>; ++ clock-frequency = <100000>; ++ dmas = <&hiedmacv310_0 14 14>, <&hiedmacv310_0 15 15>; ++ dma-names = "tx","rx"; ++ status = "disabled"; ++ }; ++ ++ i2c_bus3: i2c@12113000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x12113000 0x1000>; ++ clocks = <&clock HI3559AV100_I2C3_CLK>; ++ clock-frequency = <100000>; ++ dmas = <&hiedmacv310_0 16 16>, <&hiedmacv310_0 17 17>; ++ dma-names = "tx","rx"; ++ status = "disabled"; ++ }; ++ ++ i2c_bus4: i2c@12114000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x12114000 0x1000>; ++ clocks = <&clock HI3559AV100_I2C4_CLK>; ++ clock-frequency = <100000>; ++ dmas = <&hiedmacv310_0 18 18>, <&hiedmacv310_0 19 19>; ++ dma-names = "tx","rx"; ++ status = "disabled"; ++ }; ++ ++ i2c_bus5: i2c@12115000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x12115000 0x1000>; ++ clocks = <&clock HI3559AV100_I2C5_CLK>; ++ clock-frequency = <100000>; ++ dmas = <&hiedmacv310_0 20 20>, <&hiedmacv310_0 21 21>; ++ dma-names = "tx","rx"; ++ status = "disabled"; ++ }; ++ ++ i2c_bus6: i2c@12116000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x12116000 0x1000>; ++ clocks = <&clock HI3559AV100_I2C6_CLK>; ++ clock-frequency = <100000>; ++ dmas = <&hiedmacv310_0 22 22>, <&hiedmacv310_0 23 23>; ++ dma-names = "tx","rx"; ++ status = "disabled"; ++ }; ++ ++ i2c_bus7: i2c@12117000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x12117000 0x1000>; ++ clocks = <&clock HI3559AV100_I2C7_CLK>; ++ clock-frequency = <100000>; ++ dmas = <&hiedmacv310_0 24 24>, <&hiedmacv310_0 25 25>; ++ dma-names = "tx","rx"; ++ status = "disabled"; ++ }; ++ ++ i2c_bus8: i2c@12118000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x12118000 0x1000>; ++ clocks = <&clock HI3559AV100_I2C8_CLK>; ++ clock-frequency = <100000>; ++ dmas = <&hiedmacv310_0 26 26>, <&hiedmacv310_0 27 27>; ++ dma-names = "tx","rx"; ++ status = "disabled"; ++ }; ++ ++ i2c_bus9: i2c@12119000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x12119000 0x1000>; ++ clocks = <&clock HI3559AV100_I2C9_CLK>; ++ clock-frequency = <100000>; ++ dmas = <&hiedmacv310_0 28 28>, <&hiedmacv310_0 29 29>; ++ dma-names = "tx","rx"; ++ status = "disabled"; ++ }; ++ ++ i2c_bus10: i2c@1211a000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x1211a000 0x1000>; ++ clocks = <&clock HI3559AV100_I2C10_CLK>; ++ clock-frequency = <100000>; ++ dmas = <&hiedmacv310_0 30 30>, <&hiedmacv310_0 31 31>; ++ dma-names = "tx","rx"; ++ status = "disabled"; ++ }; ++ ++ i2c_bus11: i2c@1211b000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x1211b000 0x1000>; ++ clocks = <&clock HI3559AV100_I2C11_CLK>; ++ clock-frequency = <100000>; ++ dmas = <&hiedmacv310_1 0 32>, <&hiedmacv310_1 1 33>; ++ dma-names = "tx","rx"; ++ status = "disabled"; ++ }; ++ ++ i2c_bus12: i2c@18070000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x18070000 0x1000>; ++ clocks = <&clock_shub HI3559AV100_SHUB_I2C0_CLK>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus13: i2c@18071000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x18071000 0x1000>; ++ clocks = <&clock_shub HI3559AV100_SHUB_I2C1_CLK>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus14: i2c@18072000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x18072000 0x1000>; ++ clocks = <&clock_shub HI3559AV100_SHUB_I2C2_CLK>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus15: i2c@18073000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x18073000 0x1000>; ++ clocks = <&clock_shub HI3559AV100_SHUB_I2C3_CLK>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus16: i2c@18074000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x18074000 0x1000>; ++ clocks = <&clock_shub HI3559AV100_SHUB_I2C4_CLK>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus17: i2c@18075000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x18075000 0x1000>; ++ clocks = <&clock_shub HI3559AV100_SHUB_I2C5_CLK>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus18: i2c@18076000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x18076000 0x1000>; ++ clocks = <&clock_shub HI3559AV100_SHUB_I2C6_CLK>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus19: i2c@18077000 { ++ compatible = "hisilicon,hibvt-i2c"; ++ reg = <0x18077000 0x1000>; ++ clocks = <&clock_shub HI3559AV100_SHUB_I2C7_CLK>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ spi_bus0: spi@12120000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12120000 0x1000>, <0x1203004c 0x4>; ++ interrupts = <0 31 4>; ++ clocks = <&clock HI3559AV100_SPI0_CLK>; ++ clock-names = "apb_pclk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ num-cs = <2>; ++ dmas = <&hiedmacv310_1 2 34>, <&hiedmacv310_1 3 35>; ++ dma-names = "tx","rx"; ++ hisi,spi_cs_sb = <0>; ++ hisi,spi_cs_mask_bit = <1>; ++ }; ++ ++ spi_bus1: spi@12121000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12121000 0x1000>, <0x12030050 0x4>; ++ interrupts = <0 32 4>; ++ clocks = <&clock HI3559AV100_SPI1_CLK>; ++ clock-names = "apb_pclk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ num-cs = <2>; ++ dmas = <&hiedmacv310_1 4 36>, <&hiedmacv310_1 5 37>; ++ dma-names = "tx","rx"; ++ hisi,spi_cs_sb = <0>; ++ hisi,spi_cs_mask_bit = <1>; ++ }; ++ ++ spi_bus2: spi@12122000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12122000 0x1000>, <0x12030054 0x4>; ++ interrupts = <0 33 4>; ++ clocks = <&clock HI3559AV100_SPI2_CLK>; ++ clock-names = "apb_pclk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ num-cs = <2>; ++ dmas = <&hiedmacv310_1 6 38>, <&hiedmacv310_1 7 39>; ++ dma-names = "tx","rx"; ++ hisi,spi_cs_sb = <0>; ++ hisi,spi_cs_mask_bit = <1>; ++ }; ++ ++ spi_bus3: spi@12123000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12123000 0x1000>, <0x12030058 0x4>; ++ interrupts = <0 34 4>; ++ clocks = <&clock HI3559AV100_SPI3_CLK>; ++ clock-names = "apb_pclk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ num-cs = <2>; ++ dmas = <&hiedmacv310_1 8 40>, <&hiedmacv310_1 9 41>; ++ dma-names = "tx","rx"; ++ hisi,spi_cs_sb = <0>; ++ hisi,spi_cs_mask_bit = <1>; ++ }; ++ ++ spi_bus4: spi@12124000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12124000 0x1000>, <0x1203005c 0x4>; ++ interrupts = <0 35 4>; ++ clocks = <&clock HI3559AV100_SPI4_CLK>; ++ clock-names = "apb_pclk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ num-cs = <4>; ++ dmas = <&hiedmacv310_1 10 42>, <&hiedmacv310_1 11 43>; ++ dma-names = "tx","rx"; ++ hisi,spi_cs_sb = <0>; ++ hisi,spi_cs_mask_bit = <1>; ++ }; ++ ++ spi_bus5: spi@18080000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x18080000 0x1000>, <0x18030088 0x4>; ++ interrupts = <0 198 4>; ++ clocks = <&clock_shub HI3559AV100_SHUB_SPI0_CLK>; ++ clock-names = "apb_pclk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ num-cs = <3>; ++ dmas = <&hiedmacv310_1 12 44>, <&hiedmacv310_1 13 45>; ++ dma-names = "tx","rx"; ++ hisi,spi_cs_sb = <0>; ++ hisi,spi_cs_mask_bit = <3>; ++ }; ++ ++ spi_bus6: spi@18081000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x18081000 0x1000>, <0x18030088 0x4>; ++ interrupts = <0 199 4>; ++ clocks = <&clock_shub HI3559AV100_SHUB_SPI1_CLK>; ++ clock-names = "apb_pclk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ num-cs = <3>; ++ dmas = <&hiedmacv310_1 14 46>, <&hiedmacv310_1 15 47>; ++ dma-names = "tx","rx"; ++ hisi,spi_cs_sb = <2>; ++ hisi,spi_cs_mask_bit = <3>; ++ }; ++ ++ spi_bus7: spi@18082000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x18082000 0x1000>; ++ interrupts = <0 200 4>; ++ clocks = <&clock_shub HI3559AV100_SHUB_SPI2_CLK>; ++ clock-names = "apb_pclk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ num-cs = <1>; ++ hisi,spi_cs_sb = <0>; ++ hisi,spi_cs_mask_bit = <1>; ++ }; ++ ++ gpio_chip0: gpio_chip@12140000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12140000 0x1000>; ++ interrupts = <0 160 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ gpio_chip1: gpio_chip@12141000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12141000 0x1000>; ++ interrupts = <0 161 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ gpio_chip2: gpio_chip@12142000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12142000 0x1000>; ++ interrupts = <0 162 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ gpio_chip3: gpio_chip@12143000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12143000 0x1000>; ++ interrupts = <0 163 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ gpio_chip4: gpio_chip@12144000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12144000 0x1000>; ++ interrupts = <0 164 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ gpio_chip5: gpio_chip@12145000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12145000 0x1000>; ++ interrupts = <0 165 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ gpio_chip6: gpio_chip@12146000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12146000 0x1000>; ++ interrupts = <0 166 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ gpio_chip7: gpio_chip@12147000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12147000 0x1000>; ++ interrupts = <0 167 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ gpio_chip8: gpio_chip@12148000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12148000 0x1000>; ++ interrupts = <0 168 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ gpio_chip9: gpio_chip@12149000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12149000 0x1000>; ++ interrupts = <0 169 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ gpio_chip10: gpio_chip@1214a000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214a000 0x1000>; ++ interrupts = <0 170 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ gpio_chip11: gpio_chip@1214b000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214b000 0x1000>; ++ interrupts = <0 171 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ gpio_chip12: gpio_chip@1214c000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214c000 0x1000>; ++ interrupts = <0 172 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ gpio_chip13: gpio_chip@1214d000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214d000 0x1000>; ++ interrupts = <0 173 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ gpio_chip14: gpio_chip@1214e000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214e000 0x1000>; ++ interrupts = <0 174 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ gpio_chip15: gpio_chip@1214f000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214f000 0x1000>; ++ interrupts = <0 175 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ gpio_chip16: gpio_chip@12150000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12150000 0x1000>; ++ interrupts = <0 176 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ gpio_chip17: gpio_chip@12151000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12151000 0x1000>; ++ interrupts = <0 177 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ gpio_chip18: gpio_chip@12152000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12152000 0x1000>; ++ interrupts = <0 178 4>; ++ #gpio-cells = <2>; ++ clocks = <&clock HI3559AV100_FIXED_50M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ rtc: rtc@180b0000 { ++ compatible = "hisilicon,hi35xx-rtc"; ++ reg = <0x180b0000 0x1000>; ++ interrupts = <0 11 4>; ++ }; ++ }; ++ ++ sys: sys@12010000 { ++ compatible = "hisilicon,hisi-sys"; ++ reg = <0x12010000 0x10000>, <0x12020000 0x10000>, ++ <0x12060000 0x10000>, <0X12030000 0x10000>; ++ reg-names = "crg", "sys", "ddr", "misc"; ++ }; ++ ++ sysctrl: system-controller@00000000 { ++ compatible = "hisilicon,sysctrl"; ++ reg = <0x12020000 0x1000>; ++ reboot-offset = <0x4>; ++ }; ++ ++ misc_ctrl: misc-controller@12030000 { ++ compatible = "hisilicon,hisi-miscctrl", "syscon"; ++ reg = <0x12030000 0x10000>; ++ }; ++ ++ ioconfig: ioconfig@1f000000 { ++ compatible = "hisilicon,hisi-ioconfig", "syscon"; ++ reg = <0x1f000000 0x10000>; ++ }; ++ ++ /*FLASH DTS nodes*/ ++ fmc: flash-memory-controller@10000000 { ++ compatible = "hisilicon,hisi-fmc"; ++ reg = <0x10000000 0x1000>, <0x14000000 0x1000000>; ++ reg-names = "control", "memory"; ++ clocks = <&clock HI3559AV100_FMC_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hisfc:spi_nor_controller { ++ compatible = "hisilicon,fmc-spi-nor"; ++ assigned-clocks = <&clock HI3559AV100_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hisnfc:spi_nand_controller { ++ compatible = "hisilicon,fmc-spi-nand"; ++ assigned-clocks = <&clock HI3559AV100_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hinfc:parallel-nand-controller { ++ compatible = "hisilicon,fmc-nand"; ++ assigned-clocks = <&clock HI3559AV100_FMC_CLK>; ++ assigned-clock-rates = <200000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ ++ ufs: hiufs@0x10010000 { ++ compatible = "hiufs,hiufs_pltfm"; ++ reg = <0x10010000 0x1000>, <0x12010180 4>, <0x12030044 4>; /*for asci versionUFSbase:0x10010000 ufsCRGbase:0x12010000+180 MISCbase:0x12030000+0x44 for fpga version ufs base :0x113a0000 */ ++ interrupts = <0 83 4>; //after +32 == datasheet value ++ clocks = <&clock 40>; ++ clock-names = "clk"; ++ lanes-per-direction = <1>; ++ power-mode = <2>; /* 1:F 2:S 4:FA 5:SA */ ++ gear = <1>; /* 1:G1 2:G2 3:G3 4:G4 */ ++ rate = <1>; /* 1:A 2:B */ ++ }; ++ ++ /*ethernet DTS nodes*/ ++ mdio: mdio@101c03c0 { ++ compatible = "hisilicon,hisi-gemac-mdio"; ++ reg = <0x101c03c0 0x20>; ++ clocks = <&clock HI3559AV100_ETH_CLK>; ++ resets = <&clock 0x174 14>; ++ reset-names = "phy_reset"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++#ifndef CONFIG_ARCH_HISI_BVT_AMP ++ mdio1: mdio@101e03c0 { ++ compatible = "hisilicon,hisi-gemac-mdio"; ++ reg = <0x101e03c0 0x20>; ++ clocks = <&clock HI3559AV100_ETH1_CLK>; ++ resets = <&clock 0x174 15>; ++ reset-names = "phy_reset"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++#endif ++ higmac: ethernet@101c0000 { ++ compatible = "hisilicon,higmac"; ++ reg = <0x101c0000 0x1000>,<0x101c300c 0x4>; ++ interrupts = <0 36 4>; ++ ++ clocks = <&clock HI3559AV100_ETH_CLK>, ++ <&clock HI3559AV100_ETH_MACIF_CLK>; ++ clock-names = "higmac_clk", ++ "macif_clk"; ++ ++ resets = <&clock 0x174 0>, ++ <&clock 0x174 4>; ++ reset-names = "port_reset", ++ "macif_reset"; ++ ++ mac-address = [00 00 00 00 00 00]; ++ }; ++#ifndef CONFIG_ARCH_HISI_BVT_AMP ++ higmac1: ethernet@101e0000 { ++ compatible = "hisilicon,higmac"; ++ reg = <0x101e0000 0x1000>,<0x101e300c 0x4>; ++ interrupts = <0 37 4>; ++ ++ clocks = <&clock HI3559AV100_ETH1_CLK>, ++ <&clock HI3559AV100_ETH1_MACIF_CLK>; ++ clock-names = "higmac_clk", ++ "macif_clk"; ++ ++ resets = <&clock 0x174 2>, ++ <&clock 0x174 6>; ++ reset-names = "port_reset", ++ "macif_reset"; ++ ++ mac-address = [00 00 00 00 00 00]; ++ }; ++ ++#endif ++ /*USB DTS nodes*/ ++ usb3_phy_0: phy3_0 { ++ compatible = "hisilicon,hisi-usb3-phy_0"; ++ reg = <0x12300000 0x10000>, <0x12010000 0x10000>, <0x12030000 0x10000>; ++ phyid = <0>; ++ }; ++ ++ usb3_phy_1: phy3_1 { ++ compatible = "hisilicon,hisi-usb3-phy_1"; ++ reg = <0x12310000 0x10000>, <0x12010000 0x10000>, <0x12030000 0x10000>; ++ phyid = <1>; ++ }; ++ ++#if 0 ++ xhci_0:xhci_0@0x12300000 { ++ compatible = "generic-xhci"; ++ reg = <0x12300000 0x10000>; ++ interrupts = <0 84 4>; ++ }; ++#endif ++#if 1 ++ xhci_1:xhci_1@0x12310000 { ++ compatible = "generic-xhci"; ++ reg = <0x12310000 0x10000>; ++ interrupts = <0 85 4>; ++ }; ++#endif ++#if 1 ++ hiudc3_0:hiudc3_0@0x12300000 { ++ compatible = "snps,dwc3"; ++ reg = <0x12300000 0x10000>; ++ interrupts = <0 84 4>; ++ interrupt-names = "peripheral"; ++ maximum-speed = "super-speed"; ++ dr_mode = "peripheral"; ++ }; ++#endif ++#if 0 ++ hiudc3_1:hiudc3_1@0x12310000 { ++ compatible = "snps,dwc3"; ++ reg = <0x12310000 0x10000>; ++ interrupts = <0 85 4>; ++ interrupt-names = "peripheral"; ++ maximum-speed = "super-speed"; ++ dr_mode = "peripheral"; ++ }; ++#endif ++ /*EMMC/SD/SDIO DTS nodes*/ ++ mmc0: eMMC@0x100f0000 { ++ compatible = "hisi-sdhci"; ++ reg = <0x100f0000 0x1000>, <0x10290000 0x1000>; ++ interrupts = <0 26 4>; ++ clocks = <&clock HI3559AV100_MMC0_CLK>; ++ clock-names = "mmc_clk"; ++ resets = <&clock 0x1a8 27>, <&clock 0x1a8 29>, <&clock 0x1a8 30>; ++ reset-names = "crg_reset", "dll_reset", "sampl_reset"; ++ max-frequency = <198000000>; ++ crg_regmap = <&clock>; ++ non-removable; ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ mmc-hs400-1_8v; ++ mmc-hs400-enhanced-strobe; ++ cap-mmc-hw-reset; ++ full-pwr-cycle; ++ devid = <0>; ++ status = "disabled"; ++ }; ++ ++ mmc1: SD@0x10100000 { ++ compatible = "hisi-sdhci"; ++ reg = <0x10100000 0x1000>; ++ interrupts = <0 74 4>; ++ clocks = <&clock HI3559AV100_MMC1_CLK>; ++ clock-names = "mmc_clk"; ++ resets = <&clock 0x1ec 27>, <&clock 0x1ec 29>, <&clock 0x1ec 30>; ++ reset-names = "crg_reset", "dll_reset", "sampl_reset"; ++ max-frequency = <198000000>; ++ crg_regmap = <&clock>; ++ misc_regmap = <&misc_ctrl>; ++ iocfg_regmap = <&ioconfig>; ++ bus-width = <4>; ++ cap-sd-highspeed; ++ sd-uhs-sdr104; ++ devid = <1>; ++ status = "disabled"; ++ }; ++ ++ mmc2: SD@0x10110000 { ++ compatible = "hisi-sdhci"; ++ reg = <0x10110000 0x1000>; ++ interrupts = <0 75 4>; ++ clocks = <&clock HI3559AV100_MMC2_CLK>; ++ clock-names = "mmc_clk"; ++ resets = <&clock 0x214 27>, <&clock 0x214 29>, <&clock 0x214 30>; ++ reset-names = "crg_reset", "dll_reset", "sampl_reset"; ++ max-frequency = <49500000>; ++ crg_regmap = <&clock>; ++ misc_regmap = <&misc_ctrl>; ++ iocfg_regmap = <&ioconfig>; ++ bus-width = <4>; ++ cap-sd-highspeed; ++ devid = <2>; ++ status = "disabled"; ++ }; ++ ++ mmc3: SDIO@0x10120000 { ++ compatible = "hisi-sdhci"; ++ reg = <0x10120000 0x1000>; ++ interrupts = <0 76 4>; ++ clocks = <&clock HI3559AV100_MMC3_CLK>; ++ clock-names = "mmc_clk"; ++ resets = <&clock 0x23c 27>, <&clock 0x23c 29>, <&clock 0x23c 30>; ++ reset-names = "crg_reset", "dll_reset", "sampl_reset"; ++ max-frequency = <198000000>; ++ crg_regmap = <&clock>; ++ misc_regmap = <&misc_ctrl>; ++ iocfg_regmap = <&ioconfig>; ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ sd-uhs-sdr104; ++ devid = <3>; ++ status = "disabled"; ++ }; ++ ++ pcie0: pcie@0x12200000 { ++ device_type = "pci"; ++ compatible = "hisilicon,hisi-pcie"; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ #interrupt-cells = <1>; ++ bus-range = <0x0 0xff>; ++ reg = <0x00 0x12200000 0x00 0x2000>; ++ ranges = <0x02000000 0x00 0x30000000 0x30000000 0x00 0xff00000>; ++ interrupt-map-mask = <0x0 0x0 0x0 0x7>; ++ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 143 0x4 ++ 0x0 0x0 0x0 0x2 &gic 0x0 144 0x4 ++ 0x0 0x0 0x0 0x3 &gic 0x0 145 0x4 ++ 0x0 0x0 0x0 0x4 &gic 0x0 146 0x4>; ++ sys_ctrl_base = <0x12020000>; ++ }; ++ pcie_mcc: pcie_mcc@0x0 { ++ compatible = "hisilicon,pcie_mcc"; ++ interrupts = <0 143 4>,<0 144 4>,< 0 145 4> ++ ,< 0 146 4>,< 0 147 4>,< 0 38 4>; ++ }; ++ ++ hivdmac: hivdma-controller@1f010000 { ++ compatible = "hisilicon,hisi-vdmac"; ++ reg = <0x1f010000 0x1000>; ++ interrupts = <0 27 4>; ++ clocks = <&clock HI3559AV100_VDMAC_CLK>; ++ clock-names = "apb_pclk"; ++ resets = <&clock 0x14c 4>; ++ reset-names = "dma-reset"; ++ #dma-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ hiedmacv310_0: hiedma-controller@10030000 { ++ compatible = "hisilicon,hiedmacv310"; ++ reg = <0x10030000 0x1000>; ++ misc_regmap = <&misc_ctrl>; ++ misc_ctrl_base = <0x124>; ++ interrupts = <0 81 4>; ++ clocks = <&clock HI3559AV100_EDMAC_CLK>, <&clock HI3559AV100_EDMAC_AXICLK>; ++ clock-names = "apb_pclk", "axi_aclk"; ++ #clock-cells = <2>; ++ resets = <&clock 0x16c 4>; ++ reset-names = "dma-reset"; ++ dma-requests = <32>; ++ dma-channels = <8>; ++ devid = <0>; ++ #dma-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ hiedmacv310_1: hiedma-controller@10040000 { ++ compatible = "hisilicon,hiedmacv310"; ++ reg = <0x10040000 0x1000>; ++ misc_regmap = <&misc_ctrl>; ++ misc_ctrl_base = <0x144>; ++ interrupts = <0 82 4>; ++ clocks = <&clock HI3559AV100_EDMAC1_CLK>, <&clock HI3559AV100_EDMAC1_AXICLK>; ++ clock-names = "apb_pclk", "axi_aclk"; ++ #clock-cells = <2>; ++ resets = <&clock 0x16c 7>; ++ reset-names = "dma-reset"; ++ dma-requests = <32>; ++ dma-channels = <8>; ++ devid = <1>; ++ #dma-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ /*SDK DTS nodes*/ ++ vi: vi@0x11800000 { ++ compatible = "hisilicon,hisi-vi"; ++ reg = <0x11800000 0x30000>, <0x11a80000 0x40000>, <0x11ac0000 0x40000>; ++ reg-names = "VI_CAP0", "VI_PROC0", "VI_PROC1"; ++ interrupts = <0 60 4>, <0 61 4>, <0 62 4>; ++ interrupt-names = "VI_CAP0", "VI_PROC0", "VI_PROC1"; ++ }; ++ ++ isp: isp@0x11820000 { ++ compatible = "hisilicon,hisi-isp"; ++ reg = <0x11820000 0x100000>; ++ reg-names = "ISP"; ++ interrupts = <0 60 4>; ++ interrupt-names = "ISP"; ++ }; ++ ++ mipi: mipi@0x11a00000 { ++ compatible = "hisilicon,hisi-mipi"; ++ reg = <0x11a00000 0x20000>, <0x11a40000 0x10000>; ++ reg-names = "SLVS_EC0", "MIPI0"; ++ interrupts = <0 86 4>, <0 88 4>; ++ interrupt-names = "SLVS_EC0", "MIPI0"; ++ }; ++ ++ vpss: vpss@0x11420000 { ++ compatible = "hisilicon,hisi-vpss"; ++ reg = <0x11420000 0x20000>, <0x11440000 0x20000>; ++ reg-names = "vpss0", "vpss1"; ++ interrupts = <0 45 4>, <0 46 4>; ++ interrupt-names = "vpss0", "vpss1"; ++ }; ++ ++ vgs: vgs@0x11E20000 { ++ compatible = "hisilicon,hisi-vgs"; ++ reg = <0x11E20000 0x10000>, <0x11260000 0x10000>; ++ reg-names = "vgs0", "vgs1"; ++ interrupts = <0 43 4>, <0 44 4>; ++ interrupt-names = "vgs0", "vgs1"; ++ }; ++ ++ gdc: gdc@0x11240000 { ++ compatible = "hisilicon,hisi-gdc"; ++ reg = <0x11240000 0x10000>, <0x11250000 0x10000>; ++ reg-names = "gdc0", "gdc1"; ++ interrupts = <0 47 4>, <0 48 4>; ++ interrupt-names = "gdc0", "gdc1"; ++ }; ++ ++ dis: dis@0x11200000 { ++ compatible = "hisilicon,hisi-dis"; ++ reg = <0x11200000 0x10000>; ++ reg-names = "dis"; ++ interrupts = <0 51 4>; ++ interrupt-names = "dis"; ++ }; ++ ++ avs: avs@0x11d00000 { ++ compatible = "hisilicon,hisi-avs"; ++ reg = <0x11d00000 0x10000>; ++ reg-names = "avs"; ++ interrupts = <0 152 4>; ++ interrupt-names = "avs"; ++ }; ++ ++ vo: vo@0x11100000 { ++ compatible = "hisilicon,hisi-vo"; ++ reg = <0x11100000 0x20000>; ++ reg-names = "vo"; ++ interrupts = <0 67 4>; ++ interrupt-names = "vo"; ++ }; ++ ++ hdmi: hdmi@0x11140000 { ++ compatible = "hisilicon,hisi-hdmi"; ++ reg = <0x11140000 0x30000>, <0x12010000 0x10000>, <0x12000000 0x6000>; ++ reg-names = "hdmi0", "crg", "timer"; ++ interrupts = <0 5 4>; ++ interrupt-names = "timer"; ++ }; ++ ++ venc: venc@0x11300000 { ++ compatible = "hisilicon,hisi-vedu"; ++ reg = <0x11300000 0x10000>, <0x11310000 0x10000>,<0x11400000 0x10000>,<0x11320000 0x10000>; ++ reg-names = "vedu0", "vedu1","vedu2","jpge"; ++ interrupts = <0 39 4>, <0 40 4>,<0 41 4>,<0 49 4>; ++ interrupt-names = "vedu0", "vedu1","vedu2","jpge"; ++ }; ++ ++ vdh: vdh@0x11e10000 { ++ compatible = "hisilicon,hisi-vdh"; ++ reg = <0x11e10000 0x10000>; ++ reg-names = "vdh_scd" ; ++ interrupts = <0 91 4>,<0 92 4>,<0 94 4>; ++ interrupt-names = "vdh_olp","vdh_ilp","scd"; ++ }; ++ ++ jpegd: jpegd@0x11210000 { ++ compatible = "hisilicon,hisi-jpegd"; ++ reg = <0x11210000 0x10000>; ++ reg-names = "jpegd"; ++ interrupts = <0 52 4>; ++ interrupt-names = "jpegd"; ++ }; ++ ++ nnie: nnie@0x11500000 { ++ compatible = "hisilicon,hisi-nnie"; ++ reg = <0x11500000 0x10000>,<0x11600000 0x10000>; ++ reg-names = "nnie0", "nnie1"; ++ interrupts = <0 58 4>,<0 59 4>; ++ interrupt-names = "nnie0", "nnie1"; ++ }; ++ dpu_rect: dpu_rect@0x11630000 { ++ compatible = "hisilicon,hisi-dpu_rect"; ++ reg = <0x11630000 0x10000>; ++ reg-names = "dpu_rect"; ++ interrupts = <0 208 4>; ++ interrupt-names = "rect"; ++ }; ++ dpu_match: dpu_match@0x11630000 { ++ compatible = "hisilicon,hisi-dpu_match"; ++ reg = <0x11630000 0x10000>; ++ reg-names = "dpu_match"; ++ interrupts = <0 209 4>; ++ interrupt-names = "match"; ++ }; ++ dsp: dsp@0x11510000 { ++ compatible = "hisilicon,hisi-dsp"; ++ reg = <0x11510000 0x10000>,<0x11520000 0x10000>,<0x11610000 0x10000>,<0x11620000 0x10000>; ++ reg-names = "dsp0","dsp1","dsp2","dsp3"; ++ }; ++ ive: ive@0x11530000 { ++ compatible = "hisilicon,hisi-ive"; ++ reg = <0x11530000 0x10000>; ++ reg-names = "ive"; ++ interrupts = <0 56 4>; ++ interrupt-names = "ive"; ++ }; ++ fd: fd@0x11E00000 { ++ compatible = "hisilicon,hisi-fd"; ++ reg = <0x11E00000 0x10000>; ++ reg-names = "fd"; ++ interrupts = <0 57 4>; ++ interrupt-names = "fd"; ++ }; ++ aiao: aiao@11180000 { ++ compatible = "hisilicon,hisi-aiao"; ++ reg = <0x11180000 0x10000>,<0x11190000 0x10000>,<0x12010000 0x10000>; ++ reg-names = "acodec","aiao","crg"; ++ interrupts = <0 69 4>,<0 102 4>; ++ interrupt-names = "AIO","VOIE"; ++ }; ++ ++ tde: tde@0x11230000 { ++ compatible = "hisilicon,hisi-tde"; ++ reg = <0x11230000 0x10000>; ++ reg-names = "tde"; ++ interrupts = <0 53 4>; ++ interrupt-names = "tde_osr_isr"; ++ }; ++ ++ vddgpu: regulator@0x12030030 { ++ compatible = "hisilicon,hi3559a-volt"; ++ reg = <0x12030030 0x4>; ++ reg-names = "base-address"; ++ regulator-name = "vdd-gpu"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <940000>; ++ regulator-always-on; ++ status = "okay"; ++ }; ++ ++ gpu:gpu@0x11C00000 { ++ compatible = "arm,malit6xx", "arm,mali-midgard"; ++ reg = <0x11C00000 0x4000>; ++ interrupts = <0 102 4>, <0 103 4>, <0 101 4>; ++ interrupt-names = "JOB", "MMU", "GPU"; ++ ++ clocks = <&clock HI3559AV100_GPLL_CLK>; ++ clock-names = "clk_mali"; ++ mali-supply = <&vddgpu>; ++ operating-points = < ++ 400000 680000 ++ 700000 780000 ++ 950000 880000>; ++ ++ status = "okay"; ++ }; ++ ++ cipher: cipher@0x10200000 { ++ compatible = "hisilicon,hisi-cipher"; ++ reg = <0x10200000 0x10000>,<0x10220000 0x10000>; ++ reg-names = "cipher","rsa"; ++ interrupts = <0 30 4>,<0 30 4>,<0 104 4>; ++ interrupt-names = "cipher","hash","rsa"; ++ }; ++ }; ++}; +diff --git a/arch/arm64/configs/hi3559av100_arm64_big_little_amp_defconfig b/arch/arm64/configs/hi3559av100_arm64_big_little_amp_defconfig +new file mode 100644 +index 0000000..b77bb6d +--- /dev/null ++++ b/arch/arm64/configs/hi3559av100_arm64_big_little_amp_defconfig +@@ -0,0 +1,3852 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm64 4.9.37 Kernel Configuration ++# ++CONFIG_ARM64=y ++CONFIG_64BIT=y ++CONFIG_ARCH_PHYS_ADDR_T_64BIT=y ++CONFIG_MMU=y ++CONFIG_DEBUG_RODATA=y ++CONFIG_ARM64_PAGE_SHIFT=12 ++CONFIG_ARM64_CONT_SHIFT=4 ++CONFIG_ARCH_MMAP_RND_BITS_MIN=18 ++CONFIG_ARCH_MMAP_RND_BITS_MAX=24 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=y ++CONFIG_GENERIC_BUG=y ++CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CSUM=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_ZONE_DMA=y ++CONFIG_HAVE_GENERIC_RCU_GUP=y ++CONFIG_ARCH_DMA_ADDR_T_64BIT=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_NEED_SG_DMA_LENGTH=y ++CONFIG_SMP=y ++CONFIG_SWIOTLB=y ++CONFIG_IOMMU_HELPER=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_FIX_EARLYCON_MEM=y ++CONFIG_PGTABLE_LEVELS=3 ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++CONFIG_COMPILE_TEST=y ++CONFIG_LOCALVERSION="" ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_GENERIC_IRQ_MIGRATION=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_GENERIC_MSI_IRQ=y ++CONFIG_GENERIC_MSI_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++# CONFIG_IRQ_DOMAIN_DEBUG is not set ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_HZ_PERIODIC=y ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NO_HZ_FULL 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_TREE_RCU=y ++# CONFIG_RCU_EXPERT is not set ++CONFIG_SRCU=y ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++CONFIG_TREE_RCU_TRACE=y ++# CONFIG_RCU_EXPEDITE_BOOT is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=14 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y ++# CONFIG_CGROUPS is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++CONFIG_RELAY=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++# CONFIG_RD_LZ4 is not set ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_SYSCTL_EXCEPTION_TRACE=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_ALL is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y ++CONFIG_BPF_SYSCALL=y ++CONFIG_SHMEM=y ++CONFIG_AIO=y ++CONFIG_ADVISE_SYSCALLS=y ++CONFIG_USERFAULTFD=y ++CONFIG_PCI_QUIRKS=y ++CONFIG_MEMBARRIER=y ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++ ++# ++# Kernel Performance Events And Counters ++# ++CONFIG_PERF_EVENTS=y ++# CONFIG_DEBUG_PERF_USE_VMALLOC is not set ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_SLAB_FREELIST_RANDOM is not set ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_SYSTEM_DATA_VERIFICATION is not set ++# CONFIG_PROFILING is not set ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL is not set ++# CONFIG_UPROBES is not set ++# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set ++CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=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_HW_BREAKPOINT=y ++CONFIG_HAVE_PERF_REGS=y ++CONFIG_HAVE_PERF_USER_STACK_DUMP=y ++CONFIG_HAVE_ARCH_JUMP_LABEL=y ++CONFIG_HAVE_RCU_TABLE_FREE=y ++CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y ++CONFIG_HAVE_CMPXCHG_LOCAL=y ++CONFIG_HAVE_CMPXCHG_DOUBLE=y ++CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y ++CONFIG_HAVE_ARCH_SECCOMP_FILTER=y ++CONFIG_HAVE_GCC_PLUGINS=y ++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_ARCH_TRANSPARENT_HUGEPAGE=y ++CONFIG_HAVE_ARCH_HUGE_VMAP=y ++CONFIG_MODULES_USE_ELF_RELA=y ++CONFIG_ARCH_HAS_ELF_RANDOMIZE=y ++CONFIG_HAVE_ARCH_MMAP_RND_BITS=y ++CONFIG_ARCH_MMAP_RND_BITS=18 ++CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 ++# CONFIG_HAVE_ARCH_HASH is not set ++# CONFIG_ISA_BUS_API is not set ++CONFIG_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_COMPAT_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_SLABINFO=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_MODULES_TREE_LOOKUP=y ++CONFIG_BLOCK=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++CONFIG_BLOCK_COMPAT=y ++CONFIG_BLK_MQ_PCI=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_LOCK_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# Platform selection ++# ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_BCM2835 is not set ++# CONFIG_ARCH_BCM_IPROC is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_BRCMSTB is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_LAYERSCAPE is not set ++# CONFIG_ARCH_LG1K is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++CONFIG_ARCH_HI3559AV100=y ++# CONFIG_ACCESS_M7_DEV is not set ++CONFIG_ARCH_HISI_BVT_AMP=y ++# CONFIG_ARCH_MEDIATEK is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SEATTLE is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_STRATIX10 is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_SPRD is not set ++# CONFIG_ARCH_THUNDER is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_VULCAN is not set ++# CONFIG_ARCH_XGENE is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQMP is not set ++ ++# ++# Bus support ++# ++CONFIG_PCI=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_PCI_DOMAINS_GENERIC=y ++CONFIG_PCI_SYSCALL=y ++CONFIG_PCIEPORTBUS=y ++# CONFIG_PCIEAER is not set ++# CONFIG_PCIEASPM is not set ++# CONFIG_PCIE_PME is not set ++# CONFIG_PCIE_DPC is not set ++# CONFIG_PCIE_PTM is not set ++CONFIG_PCI_BUS_ADDR_T_64BIT=y ++CONFIG_PCI_MSI=y ++CONFIG_PCI_MSI_IRQ_DOMAIN=y ++# CONFIG_PCI_DEBUG is not set ++# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set ++# CONFIG_PCI_STUB is not set ++# CONFIG_PCI_IOV is not set ++# CONFIG_PCI_PRI is not set ++# CONFIG_PCI_PASID is not set ++# CONFIG_HOTPLUG_PCI is not set ++ ++# ++# PCI host controller drivers ++# ++# CONFIG_PCIE_DW_PLAT is not set ++# CONFIG_PCI_HOST_GENERIC is not set ++# CONFIG_PCI_HISI is not set ++# CONFIG_PCI_HOST_THUNDER_PEM is not set ++# CONFIG_PCI_HOST_THUNDER_ECAM is not set ++# CONFIG_HIPCIE is not set ++ ++# ++# Kernel Features ++# ++ ++# ++# ARM errata workarounds via the alternatives framework ++# ++CONFIG_ARM64_ERRATUM_826319=y ++CONFIG_ARM64_ERRATUM_827319=y ++CONFIG_ARM64_ERRATUM_824069=y ++CONFIG_ARM64_ERRATUM_819472=y ++CONFIG_ARM64_ERRATUM_832075=y ++CONFIG_ARM64_ERRATUM_845719=y ++CONFIG_ARM64_ERRATUM_843419=y ++CONFIG_CAVIUM_ERRATUM_22375=y ++CONFIG_CAVIUM_ERRATUM_23154=y ++CONFIG_CAVIUM_ERRATUM_27456=y ++CONFIG_QCOM_QDF2400_ERRATUM_0065=y ++CONFIG_ARM64_4K_PAGES=y ++# CONFIG_ARM64_16K_PAGES is not set ++# CONFIG_ARM64_64K_PAGES is not set ++CONFIG_ARM64_VA_BITS_39=y ++# CONFIG_ARM64_VA_BITS_48 is not set ++CONFIG_ARM64_VA_BITS=39 ++# CONFIG_CPU_BIG_ENDIAN is not set ++CONFIG_SCHED_MC=y ++# CONFIG_SCHED_SMT is not set ++CONFIG_NR_CPUS=64 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_NUMA is not set ++CONFIG_PREEMPT_NONE=y ++# CONFIG_PREEMPT_VOLUNTARY is not set ++# CONFIG_PREEMPT is not set ++# CONFIG_HZ_100 is not set ++# CONFIG_HZ_250 is not set ++# CONFIG_HZ_300 is not set ++CONFIG_HZ_1000=y ++CONFIG_HZ=1000 ++# CONFIG_SCHED_HRTICK is not set ++CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y ++CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y ++CONFIG_ARCH_SPARSEMEM_ENABLE=y ++CONFIG_ARCH_SPARSEMEM_DEFAULT=y ++CONFIG_ARCH_SELECT_MEMORY_MODEL=y ++CONFIG_HAVE_ARCH_PFN_VALID=y ++CONFIG_HW_PERF_EVENTS=y ++CONFIG_SYS_SUPPORTS_HUGETLBFS=y ++CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y ++CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_SPARSEMEM_MANUAL=y ++CONFIG_SPARSEMEM=y ++CONFIG_HAVE_MEMORY_PRESENT=y ++CONFIG_SPARSEMEM_EXTREME=y ++CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y ++CONFIG_SPARSEMEM_VMEMMAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=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=y ++CONFIG_BOUNCE=y ++CONFIG_KSM=y ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# CONFIG_TRANSPARENT_HUGEPAGE is not set ++# CONFIG_CLEANCACHE is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++# CONFIG_CMA_DEBUGFS is not set ++CONFIG_CMA_AREAS=7 ++# 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_FRAME_VECTOR=y ++# CONFIG_SECCOMP is not set ++# CONFIG_PARAVIRT is not set ++# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set ++# CONFIG_KEXEC is not set ++# CONFIG_XEN is not set ++CONFIG_FORCE_MAX_ZONEORDER=11 ++# CONFIG_ARMV8_DEPRECATED is not set ++ ++# ++# ARMv8.1 architectural features ++# ++CONFIG_ARM64_HW_AFDBM=y ++CONFIG_ARM64_PAN=y ++# CONFIG_ARM64_LSE_ATOMICS is not set ++CONFIG_ARM64_VHE=y ++ ++# ++# ARMv8.2 architectural features ++# ++CONFIG_ARM64_UAO=y ++CONFIG_ARM64_MODULE_CMODEL_LARGE=y ++# CONFIG_RANDOMIZE_BASE is not set ++ ++# ++# Boot options ++# ++CONFIG_CMDLINE="mem=128M console=ttyAMA0,115200 console=ttyMTD,blackbox" ++# CONFIG_CMDLINE_FORCE is not set ++# CONFIG_EFI is not set ++CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y ++CONFIG_IMG_GZ_DTB=y ++# CONFIG_IMG_DTB is not set ++CONFIG_BUILD_ARM64_APPENDED_KERNEL_IMAGE_NAME="Image.gz-dtb" ++CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES="hisilicon/hi3559av100-demb-flash" ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_COMPAT_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++CONFIG_COMPAT=y ++CONFIG_SYSVIPC_COMPAT=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_SUSPEND_SKIP_SYNC is not set ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++CONFIG_PM_CLK=y ++CONFIG_PM_GENERIC_DOMAINS=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_PM_GENERIC_DOMAINS_SLEEP=y ++CONFIG_PM_GENERIC_DOMAINS_OF=y ++CONFIG_CPU_PM=y ++CONFIG_ARCH_HIBERNATION_POSSIBLE=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Idle ++# ++# CONFIG_CPU_IDLE is not set ++# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_ATTR_SET=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_STAT_DETAILS=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set ++ ++# ++# CPU frequency scaling drivers ++# ++# CONFIG_CPUFREQ_DT is not set ++# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++CONFIG_NET=y ++CONFIG_NET_INGRESS=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 is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++CONFIG_NET_IP_TUNNEL=m ++# 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=m ++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=y ++# CONFIG_IPV6_ROUTE_INFO 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_IPV6_ILA is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# 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=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++CONFIG_NETFILTER_INGRESS=y ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_DUP_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_DUP_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_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_QRTR is not set ++# CONFIG_NET_NCSI is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_SOCK_CGROUP_DATA is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_EBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER=y ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++# CONFIG_DEVTMPFS is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_GENERIC_CPU_AUTOPROBE=y ++CONFIG_REGMAP=y ++CONFIG_REGMAP_I2C=y ++CONFIG_REGMAP_SPI=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=4 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_ARM_CCI400_PMU is not set ++# CONFIG_ARM_CCI5xx_PMU is not set ++# CONFIG_ARM_CCN is not set ++# CONFIG_QCOM_EBI2 is not set ++# CONFIG_SIMPLE_PM_BUS 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 ++# CONFIG_MTD_BCM63XX_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_TS5500 is not set ++# CONFIG_MTD_INTEL_VR_NOR is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_DATAFLASH is not set ++# CONFIG_MTD_M25P80 is not set ++# 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=y ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOCG3 is not set ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_PCI is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_RICOH is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_VF610_NFC is not set ++# CONFIG_MTD_NAND_SH_FLCTL is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++CONFIG_MTD_SPI_NAND_HISI_BVT=y ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++CONFIG_MTD_SPI_NAND_HIFMC100=y ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# LPDDR & LPDDR2 PCM memory drivers ++# ++# CONFIG_MTD_LPDDR is not set ++CONFIG_MTD_SPI_NOR=y ++# CONFIG_MTD_MT81xx_NOR is not set ++# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set ++# CONFIG_SPI_FSL_QUADSPI is not set ++CONFIG_SPI_HISI_SFC=y ++# CONFIG_SPI_NXP_SPIFI is not set ++# CONFIG_MTD_SPI_IDS is not set ++# CONFIG_CLOSE_SPI_8PIN_4IO is not set ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++# CONFIG_MTD_UBI is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++# CONFIG_OF_UNITTEST is not set ++# CONFIG_OF_ALL_DTBS is not set ++CONFIG_OF_FLATTREE=y ++CONFIG_OF_EARLY_FLATTREE=y ++CONFIG_OF_ADDRESS=y ++CONFIG_OF_ADDRESS_PCI=y ++CONFIG_OF_IRQ=y ++CONFIG_OF_NET=y ++CONFIG_OF_MDIO=y ++CONFIG_OF_PCI=y ++CONFIG_OF_PCI_IRQ=y ++CONFIG_OF_RESERVED_MEM=y ++# CONFIG_OF_OVERLAY is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set ++# CONFIG_BLK_CPQ_CISS_DA is not set ++# CONFIG_BLK_DEV_DAC960 is not set ++# CONFIG_BLK_DEV_UMEM is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_SKD is not set ++# CONFIG_BLK_DEV_SX8 is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_BLK_DEV_RSXX is not set ++# CONFIG_BLK_DEV_NVME is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# CONFIG_SENSORS_LIS3LV02D is not set ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_DUMMY_IRQ is not set ++# CONFIG_PHANTOM is not set ++# CONFIG_INTEL_MID_PTI is not set ++# CONFIG_SGI_IOC4 is not set ++# CONFIG_TIFM_CORE is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ATMEL_SSC is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_HP_ILO is not set ++# CONFIG_QCOM_COINCELL 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_PCH_PHUB 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 ++# CONFIG_CB710_CORE 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_GENWQE is not set ++# 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=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_SCSI_CXGB3_ISCSI is not set ++# CONFIG_SCSI_CXGB4_ISCSI is not set ++# CONFIG_SCSI_BNX2_ISCSI is not set ++# CONFIG_BE2ISCSI is not set ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_HPSA is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_3W_SAS is not set ++# CONFIG_SCSI_ACARD is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX is not set ++# CONFIG_SCSI_AIC79XX is not set ++# CONFIG_SCSI_AIC94XX is not set ++# CONFIG_SCSI_HISI_SAS is not set ++# CONFIG_SCSI_MVSAS is not set ++# CONFIG_SCSI_MVUMI is not set ++# CONFIG_SCSI_ADVANSYS is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_SCSI_ESAS2R is not set ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++# CONFIG_SCSI_MPT3SAS is not set ++# CONFIG_SCSI_MPT2SAS is not set ++# CONFIG_SCSI_SMARTPQI is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_SCSI_HPTIOP is not set ++# CONFIG_SCSI_SNIC is not set ++# CONFIG_SCSI_DMX3191D is not set ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_IPS is not set ++# CONFIG_SCSI_INITIO is not set ++# CONFIG_SCSI_INIA100 is not set ++# CONFIG_SCSI_STEX is not set ++# CONFIG_SCSI_SYM53C8XX_2 is not set ++# CONFIG_SCSI_QLOGIC_1280 is not set ++# CONFIG_SCSI_QLA_ISCSI is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_AM53C974 is not set ++# CONFIG_SCSI_WD719X is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_PMCRAID is not set ++# CONFIG_SCSI_PM8001 is not set ++# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HAVE_PATA_PLATFORM=y ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++# CONFIG_FUSION is not set ++ ++# ++# IEEE 1394 (FireWire) support ++# ++# CONFIG_FIREWIRE is not set ++# CONFIG_FIREWIRE_NOSY is not set ++CONFIG_NETDEVICES=y ++CONFIG_NET_CORE=y ++# CONFIG_BONDING is not set ++# CONFIG_DUMMY is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC 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 ++# CONFIG_ARCNET is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++CONFIG_ETHERNET=y ++CONFIG_NET_VENDOR_3COM=y ++# CONFIG_VORTEX is not set ++# CONFIG_TYPHOON is not set ++CONFIG_NET_VENDOR_ADAPTEC=y ++# CONFIG_ADAPTEC_STARFIRE is not set ++CONFIG_NET_VENDOR_AGERE=y ++# CONFIG_ET131X is not set ++CONFIG_NET_VENDOR_ALTEON=y ++# CONFIG_ACENIC is not set ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_VENDOR_AMAZON is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC is not set ++CONFIG_NET_VENDOR_ATHEROS=y ++# CONFIG_ATL2 is not set ++# CONFIG_ATL1 is not set ++# CONFIG_ATL1E is not set ++# CONFIG_ATL1C is not set ++# CONFIG_ALX 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_BROCADE=y ++# CONFIG_BNA is not set ++# CONFIG_NET_CALXEDA_XGMAC is not set ++CONFIG_NET_VENDOR_CAVIUM=y ++# CONFIG_THUNDER_NIC_PF is not set ++# CONFIG_THUNDER_NIC_VF is not set ++# CONFIG_THUNDER_NIC_BGX is not set ++# CONFIG_THUNDER_NIC_RGX is not set ++# CONFIG_LIQUIDIO is not set ++CONFIG_NET_VENDOR_CHELSIO=y ++# CONFIG_CHELSIO_T1 is not set ++# CONFIG_CHELSIO_T3 is not set ++# CONFIG_CHELSIO_T4 is not set ++# CONFIG_CHELSIO_T4VF is not set ++CONFIG_NET_VENDOR_CISCO=y ++# CONFIG_ENIC is not set ++# CONFIG_CX_ECAT is not set ++# CONFIG_DNET is not set ++CONFIG_NET_VENDOR_DEC=y ++# CONFIG_NET_TULIP is not set ++CONFIG_NET_VENDOR_DLINK=y ++# CONFIG_DL2K is not set ++# CONFIG_SUNDANCE is not set ++CONFIG_NET_VENDOR_EMULEX=y ++# CONFIG_BE2NET is not set ++# CONFIG_NET_VENDOR_EZCHIP is not set ++CONFIG_NET_VENDOR_EXAR=y ++# CONFIG_S2IO is not set ++# CONFIG_VXGE is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DDR_64BIT=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++CONFIG_NET_VENDOR_HP=y ++# CONFIG_HP100 is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_JME is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++CONFIG_NET_VENDOR_MELLANOX=y ++# CONFIG_MLX4_EN is not set ++# CONFIG_MLX4_CORE is not set ++# CONFIG_MLX5_CORE is not set ++# CONFIG_MLXSW_CORE is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_MICROCHIP is not set ++CONFIG_NET_VENDOR_MYRI=y ++# CONFIG_MYRI10GE is not set ++# CONFIG_FEALNX is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NETRONOME is not set ++CONFIG_NET_VENDOR_NVIDIA=y ++# CONFIG_FORCEDETH is not set ++CONFIG_NET_VENDOR_OKI=y ++# CONFIG_PCH_GBE is not set ++# CONFIG_ETHOC is not set ++CONFIG_NET_PACKET_ENGINE=y ++# CONFIG_HAMACHI is not set ++# CONFIG_YELLOWFIN is not set ++CONFIG_NET_VENDOR_QLOGIC=y ++# CONFIG_QLA3XXX is not set ++# CONFIG_QLCNIC is not set ++# CONFIG_QLGE is not set ++# CONFIG_NETXEN_NIC is not set ++# CONFIG_QED is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++CONFIG_NET_VENDOR_REALTEK=y ++# CONFIG_8139CP is not set ++# CONFIG_8139TOO is not set ++# CONFIG_R8169 is not set ++# CONFIG_NET_VENDOR_RENESAS is not set ++CONFIG_NET_VENDOR_RDC=y ++# CONFIG_R6040 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_SILAN=y ++# CONFIG_SC92031 is not set ++CONFIG_NET_VENDOR_SIS=y ++# CONFIG_SIS900 is not set ++# CONFIG_SIS190 is not set ++# CONFIG_SFC is not set ++# CONFIG_NET_VENDOR_SMSC is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++CONFIG_NET_VENDOR_SUN=y ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++# CONFIG_NIU is not set ++# CONFIG_NET_VENDOR_SYNOPSYS is not set ++CONFIG_NET_VENDOR_TEHUTI=y ++# CONFIG_TEHUTI is not set ++CONFIG_NET_VENDOR_TI=y ++# CONFIG_TI_CPSW_ALE is not set ++# CONFIG_TLAN is not set ++# CONFIG_NET_VENDOR_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_FDDI is not set ++# CONFIG_HIPPI is not set ++CONFIG_PHYLIB=y ++CONFIG_SWPHY=y ++ ++# ++# MDIO bus device drivers ++# ++# CONFIG_MDIO_BCM_IPROC is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_BCM_IPROC 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 ++CONFIG_MDIO_HISI_GEMAC=y ++# CONFIG_MDIO_OCTEON is not set ++# CONFIG_MDIO_THUNDER is not set ++# CONFIG_MDIO_XGENE 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_IPHETH is not set ++CONFIG_WLAN=y ++CONFIG_WLAN_VENDOR_ADMTEK=y ++CONFIG_WLAN_VENDOR_ATH=y ++# CONFIG_ATH_DEBUG is not set ++# CONFIG_ATH5K_PCI is not set ++CONFIG_WLAN_VENDOR_ATMEL=y ++CONFIG_WLAN_VENDOR_BROADCOM=y ++CONFIG_WLAN_VENDOR_CISCO=y ++CONFIG_WLAN_VENDOR_INTEL=y ++CONFIG_WLAN_VENDOR_INTERSIL=y ++# CONFIG_HOSTAP is not set ++# CONFIG_PRISM54 is not set ++CONFIG_WLAN_VENDOR_MARVELL=y ++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 ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_VMXNET3 is not set ++# CONFIG_ISDN is not set ++# CONFIG_NVM is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++CONFIG_INPUT_FF_MEMLESS=y ++# CONFIG_INPUT_POLLDEV is not set ++# CONFIG_INPUT_SPARSEKMAP is not set ++# CONFIG_INPUT_MATRIXKMAP is not set ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_CLPS711X is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_GOLDFISH_EVENTS is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_ST_KEYSCAN is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_SH_KEYSC is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++CONFIG_INPUT_JOYSTICK=y ++# CONFIG_JOYSTICK_ANALOG is not set ++# CONFIG_JOYSTICK_A3D is not set ++# CONFIG_JOYSTICK_ADI is not set ++# CONFIG_JOYSTICK_COBRA is not set ++# CONFIG_JOYSTICK_GF2K is not set ++# CONFIG_JOYSTICK_GRIP is not set ++# CONFIG_JOYSTICK_GRIP_MP is not set ++# CONFIG_JOYSTICK_GUILLEMOT is not set ++# CONFIG_JOYSTICK_INTERACT is not set ++# CONFIG_JOYSTICK_SIDEWINDER is not set ++# CONFIG_JOYSTICK_TMDC is not set ++# CONFIG_JOYSTICK_IFORCE is not set ++# CONFIG_JOYSTICK_WARRIOR is not set ++# CONFIG_JOYSTICK_MAGELLAN is not set ++# CONFIG_JOYSTICK_SPACEORB is not set ++# CONFIG_JOYSTICK_SPACEBALL is not set ++# CONFIG_JOYSTICK_STINGER is not set ++# CONFIG_JOYSTICK_TWIDJOY is not set ++# CONFIG_JOYSTICK_ZHENHUA is not set ++# CONFIG_JOYSTICK_AS5011 is not set ++# CONFIG_JOYSTICK_JOYDUMP is not set ++# CONFIG_JOYSTICK_XPAD is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_GP2A is not set ++# CONFIG_INPUT_GPIO_BEEPER is not set ++# CONFIG_INPUT_GPIO_TILT_POLLED is not set ++# CONFIG_INPUT_GPIO_DECODER is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INPUT_CM109 is not set ++# CONFIG_INPUT_REGULATOR_HAPTIC is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV260X_HAPTICS is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_INPUT_HISI_POWERKEY is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_SERIO_OLPC_APSP is not set ++# CONFIG_SERIO_SUN4I_PS2 is not set ++# CONFIG_USERIO is not set ++CONFIG_GAMEPORT=y ++# CONFIG_GAMEPORT_NS558 is not set ++# CONFIG_GAMEPORT_L4 is not set ++# CONFIG_GAMEPORT_EMU10K1 is not set ++# CONFIG_GAMEPORT_FM801 is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_NOZOMI is not set ++# CONFIG_N_GSM is not set ++# CONFIG_TRACE_SINK is not set ++CONFIG_DEVMEM=y ++CONFIG_DEVKMEM=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_ATMEL is not set ++# CONFIG_SERIAL_CLPS711X is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X is not set ++# CONFIG_SERIAL_IMX is not set ++# CONFIG_SERIAL_UARTLITE is not set ++# CONFIG_SERIAL_SH_SCI is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_JSM is not set ++# CONFIG_SERIAL_SCCNXP is not set ++# CONFIG_SERIAL_SC16IS7XX is not set ++# CONFIG_SERIAL_TIMBERDALE is not set ++# CONFIG_SERIAL_BCM63XX is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_IFX6X60 is not set ++# CONFIG_SERIAL_PCH_UART is not set ++# CONFIG_SERIAL_MXS_AUART is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++# CONFIG_SERIAL_MPS2_UART is not set ++# CONFIG_SERIAL_ARC is not set ++# CONFIG_SERIAL_RP2 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_SERIAL_MVEBU_UART 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_APPLICOM is not set ++ ++# ++# PCMCIA character devices ++# ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_DEVPORT=y ++# 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=y ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set ++# CONFIG_I2C_MUX_GPIO is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PCA954x is not set ++# CONFIG_I2C_MUX_PINCTRL is not set ++# CONFIG_I2C_MUX_REG is not set ++# CONFIG_I2C_DEMUX_PINCTRL 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 ++# ++ ++# ++# PC SMBus host controller drivers ++# ++# CONFIG_I2C_ALI1535 is not set ++# CONFIG_I2C_ALI1563 is not set ++# CONFIG_I2C_ALI15X3 is not set ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++# CONFIG_I2C_HIX5HD2 is not set ++# CONFIG_I2C_I801 is not set ++# CONFIG_I2C_ISCH is not set ++# CONFIG_I2C_PIIX4 is not set ++# CONFIG_I2C_NFORCE2 is not set ++# CONFIG_I2C_SIS5595 is not set ++# CONFIG_I2C_SIS630 is not set ++# CONFIG_I2C_SIS96X is not set ++# CONFIG_I2C_VIA is not set ++# CONFIG_I2C_VIAPRO is not set ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_AXXIA is not set ++# CONFIG_I2C_BCM_IPROC is not set ++# CONFIG_I2C_BRCMSTB is not set ++# CONFIG_I2C_CADENCE is not set ++# CONFIG_I2C_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_DESIGNWARE_PCI is not set ++# CONFIG_I2C_EFM32 is not set ++# CONFIG_I2C_EG20T is not set ++# CONFIG_I2C_EMEV2 is not set ++# CONFIG_I2C_GPIO is not set ++CONFIG_I2C_HIBVT=y ++# CONFIG_I2C_IMG is not set ++# CONFIG_I2C_JZ4780 is not set ++# CONFIG_I2C_LPC2K is not set ++# CONFIG_I2C_MESON is not set ++# CONFIG_I2C_MT65XX is not set ++# CONFIG_I2C_NOMADIK 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_RIIC is not set ++# CONFIG_I2C_RK3X is not set ++# CONFIG_I2C_SH_MOBILE is not set ++# CONFIG_I2C_SIMTEC is not set ++# CONFIG_I2C_SUN6I_P2WI is not set ++# CONFIG_I2C_UNIPHIER is not set ++# CONFIG_I2C_UNIPHIER_F is not set ++# CONFIG_I2C_VERSATILE is not set ++# CONFIG_I2C_THUNDERX is not set ++# CONFIG_I2C_XILINX is not set ++# CONFIG_I2C_XLP9XX is not set ++# CONFIG_I2C_RCAR 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_DMA_MSG_MIN_LEN=5 ++CONFIG_DMA_MSG_MAX_LEN=4090 ++# 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_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_ATMEL is not set ++# CONFIG_SPI_AXI_SPI_ENGINE is not set ++# CONFIG_SPI_BCM2835 is not set ++# CONFIG_SPI_BCM2835AUX is not set ++# CONFIG_SPI_BCM63XX is not set ++# CONFIG_SPI_BCM63XX_HSSPI is not set ++# CONFIG_SPI_BCM_QSPI is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_CLPS711X is not set ++# CONFIG_SPI_DESIGNWARE is not set ++# CONFIG_SPI_EP93XX is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_IMG_SPFI is not set ++# CONFIG_SPI_IMX is not set ++# CONFIG_SPI_JCORE is not set ++# CONFIG_SPI_LP8841_RTC is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_FSL_DSPI is not set ++# CONFIG_SPI_MESON_SPIFC is not set ++# CONFIG_SPI_MT65XX is not set ++# CONFIG_SPI_OC_TINY is not set ++# CONFIG_SPI_OMAP24XX is not set ++# CONFIG_SPI_TI_QSPI is not set ++# CONFIG_SPI_OMAP_100K is not set ++# CONFIG_SPI_ORION is not set ++# CONFIG_SPI_PIC32 is not set ++# CONFIG_SPI_PIC32_SQI is not set ++CONFIG_SPI_PL022=y ++# CONFIG_SPI_PXA2XX is not set ++# CONFIG_SPI_PXA2XX_PCI is not set ++# CONFIG_SPI_ROCKCHIP is not set ++# CONFIG_SPI_RSPI is not set ++# CONFIG_SPI_SC18IS602 is not set ++# CONFIG_SPI_SH_MSIOF is not set ++# CONFIG_SPI_SH is not set ++# CONFIG_SPI_SH_HSPI is not set ++# CONFIG_SPI_ST_SSC4 is not set ++# CONFIG_SPI_SUN4I is not set ++# CONFIG_SPI_SUN6I is not set ++# CONFIG_SPI_TEGRA114 is not set ++# CONFIG_SPI_TEGRA20_SFLASH is not set ++# CONFIG_SPI_TEGRA20_SLINK is not set ++# CONFIG_SPI_THUNDERX is not set ++# CONFIG_SPI_TOPCLIFF_PCH is not set ++# CONFIG_SPI_TXX9 is not set ++# CONFIG_SPI_XCOMM is not set ++# CONFIG_SPI_XILINX is not set ++# CONFIG_SPI_XLP is not set ++# CONFIG_SPI_XTENSA_XTFPGA is not set ++# CONFIG_SPI_ZYNQMP_GQSPI is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_PTP_1588_CLOCK_PCH is not set ++CONFIG_PINCTRL=y ++ ++# ++# Pin controllers ++# ++CONFIG_PINMUX=y ++CONFIG_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++# CONFIG_PINCTRL_AMD is not set ++# CONFIG_PINCTRL_LPC18XX is not set ++CONFIG_PINCTRL_SINGLE=y ++# CONFIG_PINCTRL_ASPEED_G4 is not set ++# CONFIG_PINCTRL_ASPEED_G5 is not set ++# CONFIG_PINCTRL_BCM281XX is not set ++# CONFIG_PINCTRL_IPROC_GPIO is not set ++# CONFIG_PINCTRL_CYGNUS_MUX is not set ++# CONFIG_PINCTRL_NSP_GPIO is not set ++# CONFIG_PINCTRL_NS2_MUX is not set ++# CONFIG_PINCTRL_NSP_MUX is not set ++# CONFIG_PINCTRL_BERLIN_BG2 is not set ++# CONFIG_PINCTRL_BERLIN_BG2CD is not set ++# CONFIG_PINCTRL_BERLIN_BG2Q is not set ++# CONFIG_PINCTRL_BERLIN_BG4CT is not set ++# CONFIG_PINCTRL_PXA25X is not set ++# CONFIG_PINCTRL_PXA27X is not set ++# CONFIG_PINCTRL_APQ8064 is not set ++# CONFIG_PINCTRL_APQ8084 is not set ++# CONFIG_PINCTRL_IPQ4019 is not set ++# CONFIG_PINCTRL_IPQ8064 is not set ++# CONFIG_PINCTRL_MSM8660 is not set ++# CONFIG_PINCTRL_MSM8960 is not set ++# CONFIG_PINCTRL_MDM9615 is not set ++# CONFIG_PINCTRL_MSM8X74 is not set ++# CONFIG_PINCTRL_MSM8916 is not set ++# CONFIG_PINCTRL_MSM8996 is not set ++# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set ++# CONFIG_PINCTRL_STM32F429 is not set ++# CONFIG_PINCTRL_STM32F746 is not set ++# CONFIG_PINCTRL_UNIPHIER is not set ++# CONFIG_PINCTRL_MT2701 is not set ++# CONFIG_PINCTRL_MT7623 is not set ++# CONFIG_PINCTRL_MT8135 is not set ++# CONFIG_PINCTRL_MT8127 is not set ++# CONFIG_PINCTRL_MT8173 is not set ++# CONFIG_PINCTRL_MT6397 is not set ++CONFIG_GPIOLIB=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_GENERIC=y ++ ++# ++# Memory mapped GPIO drivers ++# ++# CONFIG_GPIO_74XX_MMIO is not set ++# CONFIG_GPIO_ALTERA is not set ++# CONFIG_GPIO_ASPEED is not set ++# CONFIG_GPIO_ATH79 is not set ++# CONFIG_GPIO_BCM_KONA is not set ++# CONFIG_GPIO_BRCMSTB is not set ++# CONFIG_GPIO_CLPS711X is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_ETRAXFS is not set ++CONFIG_GPIO_GENERIC_PLATFORM=y ++# CONFIG_GPIO_GRGPIO is not set ++# CONFIG_GPIO_IOP is not set ++# CONFIG_GPIO_LPC18XX is not set ++# CONFIG_GPIO_MB86S7X is not set ++# CONFIG_GPIO_MOCKUP is not set ++# CONFIG_GPIO_MOXART is not set ++# CONFIG_GPIO_MPC8XXX is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_RCAR is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_TEGRA is not set ++# CONFIG_GPIO_TS4800 is not set ++# CONFIG_GPIO_VX855 is not set ++# CONFIG_GPIO_XGENE is not set ++# CONFIG_GPIO_XILINX is not set ++# CONFIG_GPIO_XLP 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 ++# ++ ++# ++# PCI GPIO expanders ++# ++# CONFIG_GPIO_AMD8111 is not set ++# CONFIG_GPIO_BT8XX is not set ++# CONFIG_GPIO_ML_IOH is not set ++# CONFIG_GPIO_PCH is not set ++# CONFIG_GPIO_RDC321X 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++# CONFIG_POWER_RESET_HISI is not set ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_XGENE is not set ++# CONFIG_POWER_RESET_KEYSTONE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_POWER_RESET_RMOBILE is not set ++# CONFIG_POWER_RESET_ZX is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_ACT8945A is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_MANAGER is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24257 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_BQ25890 is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_BATTERY_GOLDFISH is not set ++# CONFIG_CHARGER_RT9455 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_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_MX25_TSADC is not set ++# CONFIG_MFD_HI6421_PMIC is not set ++# CONFIG_MFD_HI655X_PMIC is not set ++CONFIG_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_HTC_I2CPLD is not set ++# CONFIG_LPC_ICH is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_INTEL_SOC_PMIC is not set ++# CONFIG_MFD_JANZ_CMODIO 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_RDC321X is not set ++# CONFIG_MFD_RTSX_PCI 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=y ++# 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_TIMBERDALE is not set ++# CONFIG_MFD_TC3589X is not set ++# CONFIG_MFD_TMIO is not set ++# CONFIG_MFD_VX855 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_MFD_STW481X is not set ++CONFIG_REGULATOR=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_LTC3676 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MT6311 is not set ++# CONFIG_REGULATOR_PBIAS is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_PV88060 is not set ++# CONFIG_REGULATOR_PV88080 is not set ++# CONFIG_REGULATOR_PV88090 is not set ++# CONFIG_REGULATOR_QCOM_SPMI is not set ++# CONFIG_REGULATOR_STW481X_VMMC is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=y ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=y ++CONFIG_VIDEO_V4L2=y ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=y ++CONFIG_VIDEOBUF2_MEMOPS=y ++CONFIG_VIDEOBUF2_VMALLOC=y ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++CONFIG_MEDIA_USB_SUPPORT=y ++ ++# ++# Webcam devices ++# ++CONFIG_USB_VIDEO_CLASS=y ++CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y ++CONFIG_USB_GSPCA=m ++# CONFIG_USB_M5602 is not set ++# CONFIG_USB_STV06XX is not set ++# CONFIG_USB_GL860 is not set ++# CONFIG_USB_GSPCA_BENQ is not set ++# CONFIG_USB_GSPCA_CONEX is not set ++# CONFIG_USB_GSPCA_CPIA1 is not set ++# CONFIG_USB_GSPCA_DTCS033 is not set ++# CONFIG_USB_GSPCA_ETOMS is not set ++# CONFIG_USB_GSPCA_FINEPIX is not set ++# CONFIG_USB_GSPCA_JEILINJ is not set ++# CONFIG_USB_GSPCA_JL2005BCD is not set ++# CONFIG_USB_GSPCA_KINECT is not set ++# CONFIG_USB_GSPCA_KONICA is not set ++# CONFIG_USB_GSPCA_MARS is not set ++# CONFIG_USB_GSPCA_MR97310A is not set ++# CONFIG_USB_GSPCA_NW80X is not set ++# CONFIG_USB_GSPCA_OV519 is not set ++# CONFIG_USB_GSPCA_OV534 is not set ++# CONFIG_USB_GSPCA_OV534_9 is not set ++# CONFIG_USB_GSPCA_PAC207 is not set ++# CONFIG_USB_GSPCA_PAC7302 is not set ++# CONFIG_USB_GSPCA_PAC7311 is not set ++# CONFIG_USB_GSPCA_SE401 is not set ++# CONFIG_USB_GSPCA_SN9C2028 is not set ++# CONFIG_USB_GSPCA_SN9C20X is not set ++# CONFIG_USB_GSPCA_SONIXB is not set ++# CONFIG_USB_GSPCA_SONIXJ is not set ++# CONFIG_USB_GSPCA_SPCA500 is not set ++# CONFIG_USB_GSPCA_SPCA501 is not set ++# CONFIG_USB_GSPCA_SPCA505 is not set ++# CONFIG_USB_GSPCA_SPCA506 is not set ++# CONFIG_USB_GSPCA_SPCA508 is not set ++# CONFIG_USB_GSPCA_SPCA561 is not set ++# CONFIG_USB_GSPCA_SPCA1528 is not set ++# CONFIG_USB_GSPCA_SQ905 is not set ++# CONFIG_USB_GSPCA_SQ905C is not set ++# CONFIG_USB_GSPCA_SQ930X is not set ++# CONFIG_USB_GSPCA_STK014 is not set ++# CONFIG_USB_GSPCA_STK1135 is not set ++# CONFIG_USB_GSPCA_STV0680 is not set ++# CONFIG_USB_GSPCA_SUNPLUS is not set ++# CONFIG_USB_GSPCA_T613 is not set ++# CONFIG_USB_GSPCA_TOPRO is not set ++# CONFIG_USB_GSPCA_TOUPTEK is not set ++# CONFIG_USB_GSPCA_TV8532 is not set ++# CONFIG_USB_GSPCA_VC032X is not set ++# CONFIG_USB_GSPCA_VICAM is not set ++# CONFIG_USB_GSPCA_XIRLINK_CIT is not set ++# CONFIG_USB_GSPCA_ZC3XX is not set ++# CONFIG_USB_PWC is not set ++# CONFIG_VIDEO_CPIA2 is not set ++# CONFIG_USB_ZR364XX is not set ++# CONFIG_USB_STKWEBCAM is not set ++# CONFIG_USB_S2255 is not set ++ ++# ++# Webcam, TV (analog/digital) USB devices ++# ++# CONFIG_VIDEO_EM28XX is not set ++# CONFIG_MEDIA_PCI_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, spi, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# I2C Encoders, decoders, sensors and other helper chips ++# ++ ++# ++# Audio decoders, processors and mixers ++# ++# CONFIG_VIDEO_TVAUDIO is not set ++# CONFIG_VIDEO_TDA7432 is not set ++# CONFIG_VIDEO_TDA9840 is not set ++# CONFIG_VIDEO_TEA6415C is not set ++# CONFIG_VIDEO_TEA6420 is not set ++# CONFIG_VIDEO_MSP3400 is not set ++# CONFIG_VIDEO_CS3308 is not set ++# CONFIG_VIDEO_CS5345 is not set ++# CONFIG_VIDEO_CS53L32A is not set ++# CONFIG_VIDEO_TLV320AIC23B is not set ++# CONFIG_VIDEO_UDA1342 is not set ++# CONFIG_VIDEO_WM8775 is not set ++# CONFIG_VIDEO_WM8739 is not set ++# CONFIG_VIDEO_VP27SMPX is not set ++# CONFIG_VIDEO_SONY_BTF_MPX is not set ++ ++# ++# RDS decoders ++# ++# CONFIG_VIDEO_SAA6588 is not set ++ ++# ++# Video decoders ++# ++# CONFIG_VIDEO_ADV7183 is not set ++# CONFIG_VIDEO_BT819 is not set ++# CONFIG_VIDEO_BT856 is not set ++# CONFIG_VIDEO_BT866 is not set ++# CONFIG_VIDEO_KS0127 is not set ++# CONFIG_VIDEO_ML86V7667 is not set ++# CONFIG_VIDEO_SAA7110 is not set ++# CONFIG_VIDEO_SAA711X is not set ++# CONFIG_VIDEO_TVP514X is not set ++# CONFIG_VIDEO_TVP5150 is not set ++# CONFIG_VIDEO_TVP7002 is not set ++# CONFIG_VIDEO_TW2804 is not set ++# CONFIG_VIDEO_TW9903 is not set ++# CONFIG_VIDEO_TW9906 is not set ++# CONFIG_VIDEO_VPX3220 is not set ++ ++# ++# Video and audio decoders ++# ++# CONFIG_VIDEO_SAA717X is not set ++# CONFIG_VIDEO_CX25840 is not set ++ ++# ++# Video encoders ++# ++# CONFIG_VIDEO_SAA7127 is not set ++# CONFIG_VIDEO_SAA7185 is not set ++# CONFIG_VIDEO_ADV7170 is not set ++# CONFIG_VIDEO_ADV7175 is not set ++# CONFIG_VIDEO_ADV7343 is not set ++# CONFIG_VIDEO_ADV7393 is not set ++# CONFIG_VIDEO_AK881X is not set ++# CONFIG_VIDEO_THS8200 is not set ++ ++# ++# Camera sensor devices ++# ++# CONFIG_VIDEO_OV2659 is not set ++# CONFIG_VIDEO_OV7640 is not set ++# CONFIG_VIDEO_OV7670 is not set ++# CONFIG_VIDEO_VS6624 is not set ++# CONFIG_VIDEO_MT9M111 is not set ++# CONFIG_VIDEO_MT9V011 is not set ++# CONFIG_VIDEO_SR030PC30 is not set ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++# CONFIG_VIDEO_UPD64031A is not set ++# CONFIG_VIDEO_UPD64083 is not set ++ ++# ++# Audio/Video compression chips ++# ++# CONFIG_VIDEO_SAA6752HS is not set ++ ++# ++# Miscellaneous helper chips ++# ++# CONFIG_VIDEO_THS7303 is not set ++# CONFIG_VIDEO_M52790 is not set ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# SPI helper chips ++# ++ ++# ++# Customise DVB Frontends ++# ++# CONFIG_DVB_AU8522_V4L is not set ++# CONFIG_DVB_TUNER_DIB0070 is not set ++# CONFIG_DVB_TUNER_DIB0090 is not set ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++CONFIG_VGA_ARB=y ++CONFIG_VGA_ARB_MAX_GPUS=16 ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_CIRRUS is not set ++# CONFIG_FB_PM2 is not set ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CLPS711X is not set ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_NVIDIA is not set ++# CONFIG_FB_RIVA is not set ++# CONFIG_FB_I740 is not set ++# CONFIG_FB_MATROX is not set ++# CONFIG_FB_RADEON is not set ++# CONFIG_FB_ATY128 is not set ++# CONFIG_FB_ATY is not set ++# CONFIG_FB_S3 is not set ++# CONFIG_FB_SAVAGE is not set ++# CONFIG_FB_SIS is not set ++# CONFIG_FB_NEOMAGIC is not set ++# CONFIG_FB_KYRO is not set ++# CONFIG_FB_3DFX is not set ++# CONFIG_FB_VOODOO1 is not set ++# CONFIG_FB_VT8623 is not set ++# CONFIG_FB_TRIDENT is not set ++# CONFIG_FB_ARK is not set ++# CONFIG_FB_PM3 is not set ++# CONFIG_FB_CARMINE is not set ++# CONFIG_FB_TMIO is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_GOLDFISH is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_MB862XX is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_FB_SM712 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++CONFIG_DUMMY_CONSOLE_COLUMNS=80 ++CONFIG_DUMMY_CONSOLE_ROWS=25 ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++# CONFIG_HID_BETOP_FF is not set ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# 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 is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PCI=y ++CONFIG_USB_XHCI_PLATFORM=y ++# CONFIG_USB_XHCI_MTK is not set ++# CONFIG_USB_XHCI_MVEBU is not set ++# CONFIG_USB_XHCI_RCAR 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_UHCI_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 ++# CONFIG_USB_RENESAS_USBHS is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++# CONFIG_USB_WDM is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++# CONFIG_USBIP_CORE is not set ++# CONFIG_USB_MUSB_HDRC is not set ++CONFIG_USB_DWC3=y ++# CONFIG_USB_DWC3_HOST is not set ++CONFIG_USB_DWC3_GADGET=y ++# CONFIG_USB_DWC3_DUAL_ROLE is not set ++ ++# ++# Platform Glue Driver Support ++# ++CONFIG_USB_DWC3_EXYNOS=y ++CONFIG_USB_DWC3_PCI=y ++CONFIG_USB_DWC3_KEYSTONE=y ++CONFIG_USB_DWC3_OF_SIMPLE=y ++# CONFIG_USB_DWC2 is not set ++# CONFIG_USB_CHIPIDEA 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++# CONFIG_USB_GADGET_DEBUG_FS is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_RENESAS_USB3 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_BDC_UDC is not set ++# CONFIG_USB_AMD5536UDC is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_NET2280 is not set ++# CONFIG_USB_GOKU is not set ++# CONFIG_USB_EG20T is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_MASS_STORAGE=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM 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_ARMMMCI is not set ++CONFIG_MMC_SDHCI=y ++# CONFIG_MMC_SDHCI_PCI is not set ++CONFIG_MMC_SDHCI_PLTFM=y ++# CONFIG_MMC_SDHCI_OF_ARASAN is not set ++# CONFIG_MMC_SDHCI_OF_AT91 is not set ++CONFIG_MMC_SDHCI_HISI=y ++# CONFIG_MMC_SDHCI_PXAV3 is not set ++# CONFIG_MMC_SDHCI_PXAV2 is not set ++# CONFIG_MMC_SDHCI_F_SDH30 is not set ++# CONFIG_MMC_SDHCI_IPROC is not set ++# CONFIG_MMC_OMAP_HS is not set ++# CONFIG_MMC_TIFM_SD is not set ++# CONFIG_MMC_GOLDFISH is not set ++# CONFIG_MMC_SPI is not set ++# CONFIG_MMC_SDHI is not set ++# CONFIG_MMC_CB710 is not set ++# CONFIG_MMC_VIA_SDMMC is not set ++# CONFIG_MMC_DW is not set ++# CONFIG_MMC_SH_MMCIF is not set ++# CONFIG_MMC_VUB300 is not set ++# CONFIG_MMC_USHC is not set ++# CONFIG_MMC_USDHI6ROL0 is not set ++# CONFIG_MMC_TOSHIBA_PCI 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_INFINIBAND is not set ++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=y ++ ++# ++# SPI and I2C RTC drivers ++# ++# CONFIG_RTC_DRV_DS3232 is not set ++# CONFIG_RTC_DRV_PCF2127 is not set ++# CONFIG_RTC_DRV_RV3029C2 is not set ++ ++# ++# Platform RTC drivers ++# ++CONFIG_RTC_DRV_HIBVT=y ++# 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_SPEAR is not set ++# CONFIG_RTC_DRV_NUC900 is not set ++# CONFIG_RTC_DRV_ZYNQMP is not set ++ ++# ++# on-CPU RTC drivers ++# ++# CONFIG_RTC_DRV_ASM9260 is not set ++# CONFIG_RTC_DRV_DAVINCI is not set ++# CONFIG_RTC_DRV_DIGICOLOR is not set ++# CONFIG_RTC_DRV_OMAP is not set ++# CONFIG_RTC_DRV_S3C is not set ++# CONFIG_RTC_DRV_EP93XX is not set ++# CONFIG_RTC_DRV_VR41XX is not set ++# CONFIG_RTC_DRV_PL030 is not set ++# CONFIG_RTC_DRV_PL031 is not set ++# CONFIG_RTC_DRV_AT32AP700X is not set ++# CONFIG_RTC_DRV_AT91RM9200 is not set ++# CONFIG_RTC_DRV_AT91SAM9 is not set ++# CONFIG_RTC_DRV_GENERIC is not set ++# CONFIG_RTC_DRV_VT8500 is not set ++# CONFIG_RTC_DRV_SUNXI is not set ++# CONFIG_RTC_DRV_MV is not set ++# CONFIG_RTC_DRV_ARMADA38X is not set ++# CONFIG_RTC_DRV_GEMINI is not set ++# CONFIG_RTC_DRV_COH901331 is not set ++# CONFIG_RTC_DRV_STMP is not set ++# CONFIG_RTC_DRV_JZ4740 is not set ++# CONFIG_RTC_DRV_LPC24XX is not set ++# CONFIG_RTC_DRV_LPC32XX is not set ++# CONFIG_RTC_DRV_PM8XXX is not set ++# CONFIG_RTC_DRV_TEGRA is not set ++# CONFIG_RTC_DRV_SNVS is not set ++# CONFIG_RTC_DRV_MOXART is not set ++# CONFIG_RTC_DRV_MT6397 is not set ++# CONFIG_RTC_DRV_XGENE is not set ++ ++# ++# HID Sensor RTC drivers ++# ++# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set ++CONFIG_DMADEVICES=y ++# CONFIG_DMADEVICES_DEBUG is not set ++ ++# ++# DMA Devices ++# ++CONFIG_DMA_ENGINE=y ++CONFIG_DMA_VIRTUAL_CHANNELS=y ++CONFIG_DMA_OF=y ++# CONFIG_AMBA_PL08X is not set ++# CONFIG_AXI_DMAC is not set ++# CONFIG_COH901318 is not set ++# CONFIG_DMA_JZ4740 is not set ++# CONFIG_DMA_JZ4780 is not set ++# CONFIG_DMA_OMAP is not set ++# CONFIG_DMA_SA11X0 is not set ++# CONFIG_DMA_SUN6I is not set ++# CONFIG_EP93XX_DMA is not set ++# CONFIG_FSL_EDMA is not set ++# CONFIG_IMG_MDC_DMA is not set ++# CONFIG_INTEL_IDMA64 is not set ++# CONFIG_K3_DMA is not set ++# CONFIG_MMP_PDMA is not set ++# CONFIG_MMP_TDMA is not set ++# CONFIG_MV_XOR is not set ++# CONFIG_MV_XOR_V2 is not set ++# CONFIG_NBPFAXI_DMA is not set ++# CONFIG_PCH_DMA is not set ++# CONFIG_PL330_DMA is not set ++# CONFIG_STM32_DMA is not set ++# CONFIG_S3C24XX_DMAC is not set ++# CONFIG_TEGRA210_ADMA is not set ++# CONFIG_TIMB_DMA is not set ++# CONFIG_TI_EDMA is not set ++# CONFIG_XGENE_DMA is not set ++# CONFIG_XILINX_DMA is not set ++# CONFIG_XILINX_ZYNQMP_DMA is not set ++# CONFIG_ZX_DMA is not set ++CONFIG_HIEDMACV310=y ++# CONFIG_QCOM_HIDMA_MGMT is not set ++# CONFIG_QCOM_HIDMA is not set ++# CONFIG_DW_DMAC is not set ++# CONFIG_DW_DMAC_PCI is not set ++CONFIG_RENESAS_DMA=y ++CONFIG_SH_DMAE_BASE=y ++# CONFIG_SH_DMAE is not set ++# CONFIG_RCAR_DMAC is not set ++# CONFIG_RENESAS_USB_DMAC is not set ++# CONFIG_SUDMAC 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_PCI is not set ++# CONFIG_VIRTIO_MMIO is not set ++ ++# ++# Microsoft Hyper-V guest support ++# ++CONFIG_STAGING=y ++# CONFIG_COMEDI is not set ++# CONFIG_RTL8192U is not set ++# CONFIG_RTLLIB is not set ++# CONFIG_R8712U is not set ++# CONFIG_RTS5208 is not set ++# CONFIG_FB_SM750 is not set ++# CONFIG_FB_XGI is not set ++ ++# ++# Speakup console speech ++# ++# CONFIG_SPEAKUP is not set ++# CONFIG_STAGING_MEDIA is not set ++ ++# ++# Android ++# ++# CONFIG_ASHMEM is not set ++# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set ++CONFIG_ION=y ++# CONFIG_ION_TEST is not set ++# CONFIG_ION_DUMMY is not set ++# CONFIG_ION_OF is not set ++# CONFIG_STAGING_BOARD is not set ++# CONFIG_LTE_GDM724X is not set ++# CONFIG_MTD_SPINAND_MT29F is not set ++# CONFIG_LNET is not set ++# CONFIG_DGNC is not set ++# CONFIG_GS_FPGABOOT is not set ++# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set ++# CONFIG_FB_TFT is not set ++# CONFIG_FSL_MC_BUS is not set ++# CONFIG_MOST is not set ++# CONFIG_KS7010 is not set ++# CONFIG_GREYBUS 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_VERSATILE is not set ++# CONFIG_COMMON_CLK_SCPI is not set ++# 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_COMMON_CLK_AXI_CLKGEN is not set ++# CONFIG_CLK_QORIQ is not set ++# CONFIG_COMMON_CLK_XGENE is not set ++# CONFIG_COMMON_CLK_KEYSTONE is not set ++# CONFIG_COMMON_CLK_NXP is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++# CONFIG_COMMON_CLK_OXNAS is not set ++# CONFIG_CLK_BCM_63XX is not set ++# CONFIG_CLK_BCM_KONA is not set ++# CONFIG_COMMON_CLK_IPROC is not set ++# CONFIG_COMMON_CLK_HI3519 is not set ++# CONFIG_COMMON_CLK_HI3516A is not set ++# CONFIG_COMMON_CLK_HI3518EV20X is not set ++# CONFIG_COMMON_CLK_HI3536DV100 is not set ++CONFIG_COMMON_CLK_HI3559AV100=y ++CONFIG_COMMON_CLK_HI3521A=y ++CONFIG_COMMON_CLK_HI3531A=y ++# CONFIG_COMMON_CLK_HI6220 is not set ++CONFIG_RESET_HISI=y ++# CONFIG_COMMON_CLK_MT8135 is not set ++# CONFIG_COMMON_CLK_MT8173 is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++# CONFIG_COMMON_CLK_SAMSUNG is not set ++# CONFIG_S3C2410_COMMON_CLK is not set ++# CONFIG_S3C2412_COMMON_CLK is not set ++# CONFIG_S3C2443_COMMON_CLK is not set ++# CONFIG_SUNXI_CCU is not set ++# CONFIG_COMMON_CLK_TI_ADPLL is not set ++# CONFIG_CLK_UNIPHIER is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++# CONFIG_BCM2835_TIMER is not set ++# CONFIG_BCM_KONA_TIMER is not set ++# CONFIG_DIGICOLOR_TIMER is not set ++# CONFIG_DW_APB_TIMER is not set ++# CONFIG_ROCKCHIP_TIMER is not set ++# CONFIG_MESON6_TIMER is not set ++# CONFIG_SUN4I_TIMER is not set ++# CONFIG_SUN5I_HSTIMER is not set ++# CONFIG_VT8500_TIMER is not set ++# CONFIG_CADENCE_TTC_TIMER is not set ++# CONFIG_ASM9260_TIMER is not set ++# CONFIG_CLKSRC_DBX500_PRCMU is not set ++# CONFIG_CLPS711X_TIMER is not set ++# CONFIG_ATLAS7_TIMER is not set ++# CONFIG_MOXART_TIMER is not set ++# CONFIG_MXS_TIMER is not set ++# CONFIG_PRIMA2_TIMER is not set ++# CONFIG_NSPIRE_TIMER is not set ++# CONFIG_KEYSTONE_TIMER is not set ++# CONFIG_INTEGRATOR_AP_TIMER is not set ++# CONFIG_CLKSRC_PISTACHIO is not set ++# CONFIG_CLKSRC_TI_32K is not set ++# CONFIG_CLKSRC_MPS2 is not set ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set ++CONFIG_FSL_ERRATUM_A008585=y ++CONFIG_ARM_TIMER_SP804=y ++# CONFIG_TIMER_HISP804 is not set ++# CONFIG_ARMV7M_SYSTICK is not set ++# CONFIG_ATMEL_PIT is not set ++# CONFIG_ATMEL_ST is not set ++# CONFIG_CLKSRC_EXYNOS_MCT is not set ++# CONFIG_CLKSRC_SAMSUNG_PWM is not set ++# CONFIG_FSL_FTM_TIMER is not set ++# CONFIG_OXNAS_RPS_TIMER is not set ++# CONFIG_MTK_TIMER is not set ++# CONFIG_CLKSRC_JCORE_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_CLKSRC_VERSATILE is not set ++# CONFIG_CLKSRC_PXA is not set ++# CONFIG_H8300_TMR8 is not set ++# CONFIG_H8300_TMR16 is not set ++# CONFIG_H8300_TPU is not set ++# CONFIG_CLKSRC_ST_LPC 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_MTK_INFRACFG is not set ++# CONFIG_MTK_SCPSYS is not set ++# CONFIG_ROCKCHIP_PM_DOMAINS is not set ++# CONFIG_SOC_SAMSUNG is not set ++# CONFIG_SUNXI_SRAM is not set ++# CONFIG_SOC_TI is not set ++# CONFIG_UX500_SOC_ID is not set ++CONFIG_PM_DEVFREQ=y ++ ++# ++# DEVFREQ Governors ++# ++CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y ++# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set ++# CONFIG_DEVFREQ_GOV_POWERSAVE is not set ++# CONFIG_DEVFREQ_GOV_USERSPACE is not set ++# CONFIG_DEVFREQ_GOV_PASSIVE is not set ++ ++# ++# DEVFREQ Drivers ++# ++# CONFIG_ARM_EXYNOS_BUS_DEVFREQ is not set ++# CONFIG_PM_DEVFREQ_EVENT is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_NTB is not set ++# CONFIG_VME_BUS is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++CONFIG_ARM_GIC_V2M=y ++CONFIG_ARM_GIC_V3=y ++CONFIG_ARM_GIC_V3_ITS=y ++CONFIG_HISILICON_IRQ_MBIGEN=y ++# CONFIG_JCORE_AIC is not set ++# CONFIG_TS4800_IRQ is not set ++CONFIG_PARTITION_PERCPU=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_UNIPHIER is not set ++# CONFIG_RESET_ZYNQ is not set ++CONFIG_COMMON_RESET_HI6220=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_PHY_BCM_NS_USB2 is not set ++# CONFIG_PHY_BCM_NS_USB3 is not set ++CONFIG_ARMADA375_USBCLUSTER_PHY=y ++# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set ++# CONFIG_PHY_LPC18XX_USB_OTG is not set ++# CONFIG_PHY_PXA_28NM_HSIC is not set ++# CONFIG_PHY_PXA_28NM_USB2 is not set ++# CONFIG_OMAP_CONTROL_PHY is not set ++# CONFIG_PHY_EXYNOS_DP_VIDEO is not set ++# CONFIG_BCM_KONA_USB2_PHY is not set ++# CONFIG_PHY_HI6220_USB is not set ++# CONFIG_PHY_ROCKCHIP_INNO_USB2 is not set ++# CONFIG_PHY_ROCKCHIP_PCIE is not set ++# CONFIG_PHY_ROCKCHIP_TYPEC is not set ++# CONFIG_PHY_ST_SPEAR1310_MIPHY is not set ++# CONFIG_PHY_ST_SPEAR1340_MIPHY is not set ++# CONFIG_PHY_XGENE is not set ++# CONFIG_PHY_STIH407_USB is not set ++# CONFIG_PHY_BRCM_SATA is not set ++# CONFIG_PHY_CYGNUS_PCIE is not set ++CONFIG_HISI_PHY_USB3=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++ ++# ++# Performance monitor support ++# ++CONFIG_ARM_PMU=y ++# CONFIG_RAS is not set ++# CONFIG_THUNDERBOLT is not set ++ ++# ++# Android ++# ++CONFIG_ANDROID=y ++# CONFIG_ANDROID_BINDER_IPC is not set ++# CONFIG_LIBNVDIMM 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 ++# CONFIG_HI_DMAC is not set ++# CONFIG_HIVDMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE is not set ++ ++# ++# Firmware Drivers ++# ++CONFIG_ARM_PSCI_FW=y ++CONFIG_ARM_SCPI_POWER_DOMAIN=y ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++# CONFIG_MESON_SM is not set ++# CONFIG_ACPI is not set ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++CONFIG_FS_IOMAP=y ++CONFIG_EXT2_FS=y ++CONFIG_EXT2_FS_XATTR=y ++CONFIG_EXT2_FS_POSIX_ACL=y ++CONFIG_EXT2_FS_SECURITY=y ++CONFIG_EXT3_FS=y ++CONFIG_EXT3_FS_POSIX_ACL=y ++CONFIG_EXT3_FS_SECURITY=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_CHECK=y ++CONFIG_REISERFS_PROC_INFO=y ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_DEBUG=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++# CONFIG_XFS_WARN is not set ++# CONFIG_XFS_DEBUG is not set ++# CONFIG_GFS2_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_DAX is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_EXPORTFS=m ++# 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=y ++# CONFIG_QUOTA_NETLINK_INTERFACE is not set ++CONFIG_PRINT_QUOTA_WARNING=y ++# CONFIG_QUOTA_DEBUG is not set ++CONFIG_QUOTA_TREE=m ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_QUOTACTL=y ++CONFIG_AUTOFS4_FS=m ++CONFIG_FUSE_FS=y ++# CONFIG_CUSE is not set ++# CONFIG_OVERLAY_FS is not set ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=y ++# CONFIG_JOLIET is not set ++# CONFIG_ZISOFS is not set ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++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_KCORE is not set ++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=y ++CONFIG_TMPFS_XATTR=y ++# CONFIG_HUGETLBFS is not set ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_ARCH_HAS_GIGANTIC_PAGE=y ++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_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++CONFIG_SQUASHFS=y ++CONFIG_SQUASHFS_FILE_CACHE=y ++# CONFIG_SQUASHFS_FILE_DIRECT is not set ++CONFIG_SQUASHFS_DECOMP_SINGLE=y ++# CONFIG_SQUASHFS_DECOMP_MULTI is not set ++# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set ++# CONFIG_SQUASHFS_XATTR is not set ++CONFIG_SQUASHFS_ZLIB=y ++# CONFIG_SQUASHFS_LZ4 is not set ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set ++# CONFIG_SQUASHFS_EMBEDDED is not set ++CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 ++# 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFSD is not set ++CONFIG_GRACE_PERIOD=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=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=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=y ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++# 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 ++# CONFIG_VIRTUALIZATION is not set ++ ++# ++# Kernel hacking ++# ++ ++# ++# printk and dmesg options ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++# 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=2048 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++CONFIG_ARCH_WANT_FRAME_POINTERS=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++CONFIG_HAVE_ARCH_KASAN=y ++# CONFIG_KASAN is not set ++CONFIG_ARCH_HAS_KCOV=y ++# CONFIG_KCOV is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++CONFIG_LOCKUP_DETECTOR=y ++# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set ++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 ++# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set ++CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 ++# CONFIG_WQ_WATCHDOG is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++CONFIG_SCHED_INFO=y ++CONFIG_SCHEDSTATS=y ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_HAVE_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_PROVE_RCU is not set ++CONFIG_SPARSE_RCU_POINTER=y ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=21 ++CONFIG_RCU_TRACE=y ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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_TRACE_CLOCK=y ++CONFIG_TRACING_SUPPORT=y ++# CONFIG_FTRACE is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_LKDTM is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=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_ARM64_PTDUMP is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_DEBUG_ALIGN_RODATA is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS 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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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 is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++CONFIG_CRYPTO_NULL=m ++CONFIG_CRYPTO_NULL2=y ++# CONFIG_CRYPTO_PCRYPT is not set ++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=m ++# CONFIG_CRYPTO_GCM is not set ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# 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=y ++CONFIG_CRYPTO_HMAC=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# 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 is not set ++# 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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_CRYPTO_DEV_S5P is not set ++# CONFIG_CRYPTO_DEV_ATMEL_AES is not set ++# CONFIG_CRYPTO_DEV_CCP is not set ++# CONFIG_CRYPTO_DEV_QCE is not set ++# CONFIG_CRYPTO_DEV_IMGTEC_HASH is not set ++ ++# ++# Certificates for signature checking ++# ++# CONFIG_ARM64_CRYPTO is not set ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++CONFIG_HAVE_ARCH_BITREVERSE=y ++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=y ++CONFIG_CRC16=y ++# CONFIG_CRC_T10DIF is not set ++CONFIG_CRC_ITU_T=y ++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=m ++# CONFIG_CRC8 is not set ++CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y ++# CONFIG_RANDOM32_SELFTEST is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=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_GZIP=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_NLATTR=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=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y +diff --git a/arch/arm64/configs/hi3559av100_arm64_big_little_defconfig b/arch/arm64/configs/hi3559av100_arm64_big_little_defconfig +new file mode 100644 +index 0000000..aac5af6 +--- /dev/null ++++ b/arch/arm64/configs/hi3559av100_arm64_big_little_defconfig +@@ -0,0 +1,3852 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm64 4.9.37 Kernel Configuration ++# ++CONFIG_ARM64=y ++CONFIG_64BIT=y ++CONFIG_ARCH_PHYS_ADDR_T_64BIT=y ++CONFIG_MMU=y ++CONFIG_DEBUG_RODATA=y ++CONFIG_ARM64_PAGE_SHIFT=12 ++CONFIG_ARM64_CONT_SHIFT=4 ++CONFIG_ARCH_MMAP_RND_BITS_MIN=18 ++CONFIG_ARCH_MMAP_RND_BITS_MAX=24 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=y ++CONFIG_GENERIC_BUG=y ++CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CSUM=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_ZONE_DMA=y ++CONFIG_HAVE_GENERIC_RCU_GUP=y ++CONFIG_ARCH_DMA_ADDR_T_64BIT=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_NEED_SG_DMA_LENGTH=y ++CONFIG_SMP=y ++CONFIG_SWIOTLB=y ++CONFIG_IOMMU_HELPER=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_FIX_EARLYCON_MEM=y ++CONFIG_PGTABLE_LEVELS=3 ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++CONFIG_COMPILE_TEST=y ++CONFIG_LOCALVERSION="" ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_GENERIC_IRQ_MIGRATION=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_GENERIC_MSI_IRQ=y ++CONFIG_GENERIC_MSI_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++# CONFIG_IRQ_DOMAIN_DEBUG is not set ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_HZ_PERIODIC=y ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NO_HZ_FULL 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_TREE_RCU=y ++# CONFIG_RCU_EXPERT is not set ++CONFIG_SRCU=y ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++CONFIG_TREE_RCU_TRACE=y ++# CONFIG_RCU_EXPEDITE_BOOT is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=14 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y ++# CONFIG_CGROUPS is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++CONFIG_RELAY=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++# CONFIG_RD_LZ4 is not set ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_SYSCTL_EXCEPTION_TRACE=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_ALL is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y ++CONFIG_BPF_SYSCALL=y ++CONFIG_SHMEM=y ++CONFIG_AIO=y ++CONFIG_ADVISE_SYSCALLS=y ++CONFIG_USERFAULTFD=y ++CONFIG_PCI_QUIRKS=y ++CONFIG_MEMBARRIER=y ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++ ++# ++# Kernel Performance Events And Counters ++# ++CONFIG_PERF_EVENTS=y ++# CONFIG_DEBUG_PERF_USE_VMALLOC is not set ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_SLAB_FREELIST_RANDOM is not set ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_SYSTEM_DATA_VERIFICATION is not set ++# CONFIG_PROFILING is not set ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL is not set ++# CONFIG_UPROBES is not set ++# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set ++CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=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_HW_BREAKPOINT=y ++CONFIG_HAVE_PERF_REGS=y ++CONFIG_HAVE_PERF_USER_STACK_DUMP=y ++CONFIG_HAVE_ARCH_JUMP_LABEL=y ++CONFIG_HAVE_RCU_TABLE_FREE=y ++CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y ++CONFIG_HAVE_CMPXCHG_LOCAL=y ++CONFIG_HAVE_CMPXCHG_DOUBLE=y ++CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y ++CONFIG_HAVE_ARCH_SECCOMP_FILTER=y ++CONFIG_HAVE_GCC_PLUGINS=y ++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_ARCH_TRANSPARENT_HUGEPAGE=y ++CONFIG_HAVE_ARCH_HUGE_VMAP=y ++CONFIG_MODULES_USE_ELF_RELA=y ++CONFIG_ARCH_HAS_ELF_RANDOMIZE=y ++CONFIG_HAVE_ARCH_MMAP_RND_BITS=y ++CONFIG_ARCH_MMAP_RND_BITS=18 ++CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 ++# CONFIG_HAVE_ARCH_HASH is not set ++# CONFIG_ISA_BUS_API is not set ++CONFIG_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_COMPAT_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_SLABINFO=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_MODULES_TREE_LOOKUP=y ++CONFIG_BLOCK=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++CONFIG_BLOCK_COMPAT=y ++CONFIG_BLK_MQ_PCI=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_LOCK_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# Platform selection ++# ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_BCM2835 is not set ++# CONFIG_ARCH_BCM_IPROC is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_BRCMSTB is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_LAYERSCAPE is not set ++# CONFIG_ARCH_LG1K is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++CONFIG_ARCH_HI3559AV100=y ++# CONFIG_ACCESS_M7_DEV is not set ++# CONFIG_ARCH_HISI_BVT_AMP is not set ++# CONFIG_ARCH_MEDIATEK is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SEATTLE is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_STRATIX10 is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_SPRD is not set ++# CONFIG_ARCH_THUNDER is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_VULCAN is not set ++# CONFIG_ARCH_XGENE is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQMP is not set ++ ++# ++# Bus support ++# ++CONFIG_PCI=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_PCI_DOMAINS_GENERIC=y ++CONFIG_PCI_SYSCALL=y ++CONFIG_PCIEPORTBUS=y ++# CONFIG_PCIEAER is not set ++# CONFIG_PCIEASPM is not set ++# CONFIG_PCIE_PME is not set ++# CONFIG_PCIE_DPC is not set ++# CONFIG_PCIE_PTM is not set ++CONFIG_PCI_BUS_ADDR_T_64BIT=y ++CONFIG_PCI_MSI=y ++CONFIG_PCI_MSI_IRQ_DOMAIN=y ++# CONFIG_PCI_DEBUG is not set ++# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set ++# CONFIG_PCI_STUB is not set ++# CONFIG_PCI_IOV is not set ++# CONFIG_PCI_PRI is not set ++# CONFIG_PCI_PASID is not set ++# CONFIG_HOTPLUG_PCI is not set ++ ++# ++# PCI host controller drivers ++# ++# CONFIG_PCIE_DW_PLAT is not set ++# CONFIG_PCI_HOST_GENERIC is not set ++# CONFIG_PCI_HISI is not set ++# CONFIG_PCI_HOST_THUNDER_PEM is not set ++# CONFIG_PCI_HOST_THUNDER_ECAM is not set ++# CONFIG_HIPCIE is not set ++ ++# ++# Kernel Features ++# ++ ++# ++# ARM errata workarounds via the alternatives framework ++# ++CONFIG_ARM64_ERRATUM_826319=y ++CONFIG_ARM64_ERRATUM_827319=y ++CONFIG_ARM64_ERRATUM_824069=y ++CONFIG_ARM64_ERRATUM_819472=y ++CONFIG_ARM64_ERRATUM_832075=y ++CONFIG_ARM64_ERRATUM_845719=y ++CONFIG_ARM64_ERRATUM_843419=y ++CONFIG_CAVIUM_ERRATUM_22375=y ++CONFIG_CAVIUM_ERRATUM_23154=y ++CONFIG_CAVIUM_ERRATUM_27456=y ++CONFIG_QCOM_QDF2400_ERRATUM_0065=y ++CONFIG_ARM64_4K_PAGES=y ++# CONFIG_ARM64_16K_PAGES is not set ++# CONFIG_ARM64_64K_PAGES is not set ++CONFIG_ARM64_VA_BITS_39=y ++# CONFIG_ARM64_VA_BITS_48 is not set ++CONFIG_ARM64_VA_BITS=39 ++# CONFIG_CPU_BIG_ENDIAN is not set ++CONFIG_SCHED_MC=y ++# CONFIG_SCHED_SMT is not set ++CONFIG_NR_CPUS=64 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_NUMA is not set ++CONFIG_PREEMPT_NONE=y ++# CONFIG_PREEMPT_VOLUNTARY is not set ++# CONFIG_PREEMPT is not set ++# CONFIG_HZ_100 is not set ++# CONFIG_HZ_250 is not set ++# CONFIG_HZ_300 is not set ++CONFIG_HZ_1000=y ++CONFIG_HZ=1000 ++# CONFIG_SCHED_HRTICK is not set ++CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y ++CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y ++CONFIG_ARCH_SPARSEMEM_ENABLE=y ++CONFIG_ARCH_SPARSEMEM_DEFAULT=y ++CONFIG_ARCH_SELECT_MEMORY_MODEL=y ++CONFIG_HAVE_ARCH_PFN_VALID=y ++CONFIG_HW_PERF_EVENTS=y ++CONFIG_SYS_SUPPORTS_HUGETLBFS=y ++CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y ++CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_SPARSEMEM_MANUAL=y ++CONFIG_SPARSEMEM=y ++CONFIG_HAVE_MEMORY_PRESENT=y ++CONFIG_SPARSEMEM_EXTREME=y ++CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y ++CONFIG_SPARSEMEM_VMEMMAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=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=y ++CONFIG_BOUNCE=y ++CONFIG_KSM=y ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# CONFIG_TRANSPARENT_HUGEPAGE is not set ++# CONFIG_CLEANCACHE is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++# CONFIG_CMA_DEBUGFS is not set ++CONFIG_CMA_AREAS=7 ++# 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_FRAME_VECTOR=y ++# CONFIG_SECCOMP is not set ++# CONFIG_PARAVIRT is not set ++# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set ++# CONFIG_KEXEC is not set ++# CONFIG_XEN is not set ++CONFIG_FORCE_MAX_ZONEORDER=11 ++# CONFIG_ARMV8_DEPRECATED is not set ++ ++# ++# ARMv8.1 architectural features ++# ++CONFIG_ARM64_HW_AFDBM=y ++CONFIG_ARM64_PAN=y ++# CONFIG_ARM64_LSE_ATOMICS is not set ++CONFIG_ARM64_VHE=y ++ ++# ++# ARMv8.2 architectural features ++# ++CONFIG_ARM64_UAO=y ++CONFIG_ARM64_MODULE_CMODEL_LARGE=y ++# CONFIG_RANDOMIZE_BASE is not set ++ ++# ++# Boot options ++# ++CONFIG_CMDLINE="mem=128M console=ttyAMA0,115200 console=ttyMTD,blackbox" ++# CONFIG_CMDLINE_FORCE is not set ++# CONFIG_EFI is not set ++CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y ++CONFIG_IMG_GZ_DTB=y ++# CONFIG_IMG_DTB is not set ++CONFIG_BUILD_ARM64_APPENDED_KERNEL_IMAGE_NAME="Image.gz-dtb" ++CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES="hisilicon/hi3559av100-demb-flash" ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_COMPAT_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++CONFIG_COMPAT=y ++CONFIG_SYSVIPC_COMPAT=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_SUSPEND_SKIP_SYNC is not set ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++CONFIG_PM_CLK=y ++CONFIG_PM_GENERIC_DOMAINS=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_PM_GENERIC_DOMAINS_SLEEP=y ++CONFIG_PM_GENERIC_DOMAINS_OF=y ++CONFIG_CPU_PM=y ++CONFIG_ARCH_HIBERNATION_POSSIBLE=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Idle ++# ++# CONFIG_CPU_IDLE is not set ++# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_ATTR_SET=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_STAT_DETAILS=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set ++ ++# ++# CPU frequency scaling drivers ++# ++# CONFIG_CPUFREQ_DT is not set ++# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++CONFIG_NET=y ++CONFIG_NET_INGRESS=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 is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++CONFIG_NET_IP_TUNNEL=m ++# 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=m ++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=y ++# CONFIG_IPV6_ROUTE_INFO 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_IPV6_ILA is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# 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=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++CONFIG_NETFILTER_INGRESS=y ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_DUP_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_DUP_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_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_QRTR is not set ++# CONFIG_NET_NCSI is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_SOCK_CGROUP_DATA is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_EBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER=y ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++# CONFIG_DEVTMPFS is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_GENERIC_CPU_AUTOPROBE=y ++CONFIG_REGMAP=y ++CONFIG_REGMAP_I2C=y ++CONFIG_REGMAP_SPI=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=4 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_ARM_CCI400_PMU is not set ++# CONFIG_ARM_CCI5xx_PMU is not set ++# CONFIG_ARM_CCN is not set ++# CONFIG_QCOM_EBI2 is not set ++# CONFIG_SIMPLE_PM_BUS 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 ++# CONFIG_MTD_BCM63XX_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_TS5500 is not set ++# CONFIG_MTD_INTEL_VR_NOR is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_DATAFLASH is not set ++# CONFIG_MTD_M25P80 is not set ++# 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=y ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOCG3 is not set ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_PCI is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_RICOH is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_VF610_NFC is not set ++# CONFIG_MTD_NAND_SH_FLCTL is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++CONFIG_MTD_SPI_NAND_HISI_BVT=y ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++CONFIG_MTD_SPI_NAND_HIFMC100=y ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# LPDDR & LPDDR2 PCM memory drivers ++# ++# CONFIG_MTD_LPDDR is not set ++CONFIG_MTD_SPI_NOR=y ++# CONFIG_MTD_MT81xx_NOR is not set ++# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set ++# CONFIG_SPI_FSL_QUADSPI is not set ++CONFIG_SPI_HISI_SFC=y ++# CONFIG_SPI_NXP_SPIFI is not set ++# CONFIG_MTD_SPI_IDS is not set ++# CONFIG_CLOSE_SPI_8PIN_4IO is not set ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++# CONFIG_MTD_UBI is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++# CONFIG_OF_UNITTEST is not set ++# CONFIG_OF_ALL_DTBS is not set ++CONFIG_OF_FLATTREE=y ++CONFIG_OF_EARLY_FLATTREE=y ++CONFIG_OF_ADDRESS=y ++CONFIG_OF_ADDRESS_PCI=y ++CONFIG_OF_IRQ=y ++CONFIG_OF_NET=y ++CONFIG_OF_MDIO=y ++CONFIG_OF_PCI=y ++CONFIG_OF_PCI_IRQ=y ++CONFIG_OF_RESERVED_MEM=y ++# CONFIG_OF_OVERLAY is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set ++# CONFIG_BLK_CPQ_CISS_DA is not set ++# CONFIG_BLK_DEV_DAC960 is not set ++# CONFIG_BLK_DEV_UMEM is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_SKD is not set ++# CONFIG_BLK_DEV_SX8 is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_BLK_DEV_RSXX is not set ++# CONFIG_BLK_DEV_NVME is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# CONFIG_SENSORS_LIS3LV02D is not set ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_DUMMY_IRQ is not set ++# CONFIG_PHANTOM is not set ++# CONFIG_INTEL_MID_PTI is not set ++# CONFIG_SGI_IOC4 is not set ++# CONFIG_TIFM_CORE is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ATMEL_SSC is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_HP_ILO is not set ++# CONFIG_QCOM_COINCELL 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_PCH_PHUB 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 ++# CONFIG_CB710_CORE 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_GENWQE is not set ++# 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=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_SCSI_CXGB3_ISCSI is not set ++# CONFIG_SCSI_CXGB4_ISCSI is not set ++# CONFIG_SCSI_BNX2_ISCSI is not set ++# CONFIG_BE2ISCSI is not set ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_HPSA is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_3W_SAS is not set ++# CONFIG_SCSI_ACARD is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX is not set ++# CONFIG_SCSI_AIC79XX is not set ++# CONFIG_SCSI_AIC94XX is not set ++# CONFIG_SCSI_HISI_SAS is not set ++# CONFIG_SCSI_MVSAS is not set ++# CONFIG_SCSI_MVUMI is not set ++# CONFIG_SCSI_ADVANSYS is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_SCSI_ESAS2R is not set ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++# CONFIG_SCSI_MPT3SAS is not set ++# CONFIG_SCSI_MPT2SAS is not set ++# CONFIG_SCSI_SMARTPQI is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_SCSI_HPTIOP is not set ++# CONFIG_SCSI_SNIC is not set ++# CONFIG_SCSI_DMX3191D is not set ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_IPS is not set ++# CONFIG_SCSI_INITIO is not set ++# CONFIG_SCSI_INIA100 is not set ++# CONFIG_SCSI_STEX is not set ++# CONFIG_SCSI_SYM53C8XX_2 is not set ++# CONFIG_SCSI_QLOGIC_1280 is not set ++# CONFIG_SCSI_QLA_ISCSI is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_AM53C974 is not set ++# CONFIG_SCSI_WD719X is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_PMCRAID is not set ++# CONFIG_SCSI_PM8001 is not set ++# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HAVE_PATA_PLATFORM=y ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++# CONFIG_FUSION is not set ++ ++# ++# IEEE 1394 (FireWire) support ++# ++# CONFIG_FIREWIRE is not set ++# CONFIG_FIREWIRE_NOSY is not set ++CONFIG_NETDEVICES=y ++CONFIG_NET_CORE=y ++# CONFIG_BONDING is not set ++# CONFIG_DUMMY is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC 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 ++# CONFIG_ARCNET is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++CONFIG_ETHERNET=y ++CONFIG_NET_VENDOR_3COM=y ++# CONFIG_VORTEX is not set ++# CONFIG_TYPHOON is not set ++CONFIG_NET_VENDOR_ADAPTEC=y ++# CONFIG_ADAPTEC_STARFIRE is not set ++CONFIG_NET_VENDOR_AGERE=y ++# CONFIG_ET131X is not set ++CONFIG_NET_VENDOR_ALTEON=y ++# CONFIG_ACENIC is not set ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_VENDOR_AMAZON is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC is not set ++CONFIG_NET_VENDOR_ATHEROS=y ++# CONFIG_ATL2 is not set ++# CONFIG_ATL1 is not set ++# CONFIG_ATL1E is not set ++# CONFIG_ATL1C is not set ++# CONFIG_ALX 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_BROCADE=y ++# CONFIG_BNA is not set ++# CONFIG_NET_CALXEDA_XGMAC is not set ++CONFIG_NET_VENDOR_CAVIUM=y ++# CONFIG_THUNDER_NIC_PF is not set ++# CONFIG_THUNDER_NIC_VF is not set ++# CONFIG_THUNDER_NIC_BGX is not set ++# CONFIG_THUNDER_NIC_RGX is not set ++# CONFIG_LIQUIDIO is not set ++CONFIG_NET_VENDOR_CHELSIO=y ++# CONFIG_CHELSIO_T1 is not set ++# CONFIG_CHELSIO_T3 is not set ++# CONFIG_CHELSIO_T4 is not set ++# CONFIG_CHELSIO_T4VF is not set ++CONFIG_NET_VENDOR_CISCO=y ++# CONFIG_ENIC is not set ++# CONFIG_CX_ECAT is not set ++# CONFIG_DNET is not set ++CONFIG_NET_VENDOR_DEC=y ++# CONFIG_NET_TULIP is not set ++CONFIG_NET_VENDOR_DLINK=y ++# CONFIG_DL2K is not set ++# CONFIG_SUNDANCE is not set ++CONFIG_NET_VENDOR_EMULEX=y ++# CONFIG_BE2NET is not set ++# CONFIG_NET_VENDOR_EZCHIP is not set ++CONFIG_NET_VENDOR_EXAR=y ++# CONFIG_S2IO is not set ++# CONFIG_VXGE is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DDR_64BIT=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++CONFIG_NET_VENDOR_HP=y ++# CONFIG_HP100 is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_JME is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++CONFIG_NET_VENDOR_MELLANOX=y ++# CONFIG_MLX4_EN is not set ++# CONFIG_MLX4_CORE is not set ++# CONFIG_MLX5_CORE is not set ++# CONFIG_MLXSW_CORE is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_MICROCHIP is not set ++CONFIG_NET_VENDOR_MYRI=y ++# CONFIG_MYRI10GE is not set ++# CONFIG_FEALNX is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NETRONOME is not set ++CONFIG_NET_VENDOR_NVIDIA=y ++# CONFIG_FORCEDETH is not set ++CONFIG_NET_VENDOR_OKI=y ++# CONFIG_PCH_GBE is not set ++# CONFIG_ETHOC is not set ++CONFIG_NET_PACKET_ENGINE=y ++# CONFIG_HAMACHI is not set ++# CONFIG_YELLOWFIN is not set ++CONFIG_NET_VENDOR_QLOGIC=y ++# CONFIG_QLA3XXX is not set ++# CONFIG_QLCNIC is not set ++# CONFIG_QLGE is not set ++# CONFIG_NETXEN_NIC is not set ++# CONFIG_QED is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++CONFIG_NET_VENDOR_REALTEK=y ++# CONFIG_8139CP is not set ++# CONFIG_8139TOO is not set ++# CONFIG_R8169 is not set ++# CONFIG_NET_VENDOR_RENESAS is not set ++CONFIG_NET_VENDOR_RDC=y ++# CONFIG_R6040 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_SILAN=y ++# CONFIG_SC92031 is not set ++CONFIG_NET_VENDOR_SIS=y ++# CONFIG_SIS900 is not set ++# CONFIG_SIS190 is not set ++# CONFIG_SFC is not set ++# CONFIG_NET_VENDOR_SMSC is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++CONFIG_NET_VENDOR_SUN=y ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++# CONFIG_NIU is not set ++# CONFIG_NET_VENDOR_SYNOPSYS is not set ++CONFIG_NET_VENDOR_TEHUTI=y ++# CONFIG_TEHUTI is not set ++CONFIG_NET_VENDOR_TI=y ++# CONFIG_TI_CPSW_ALE is not set ++# CONFIG_TLAN is not set ++# CONFIG_NET_VENDOR_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_FDDI is not set ++# CONFIG_HIPPI is not set ++CONFIG_PHYLIB=y ++CONFIG_SWPHY=y ++ ++# ++# MDIO bus device drivers ++# ++# CONFIG_MDIO_BCM_IPROC is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_BCM_IPROC 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 ++CONFIG_MDIO_HISI_GEMAC=y ++# CONFIG_MDIO_OCTEON is not set ++# CONFIG_MDIO_THUNDER is not set ++# CONFIG_MDIO_XGENE 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_IPHETH is not set ++CONFIG_WLAN=y ++CONFIG_WLAN_VENDOR_ADMTEK=y ++CONFIG_WLAN_VENDOR_ATH=y ++# CONFIG_ATH_DEBUG is not set ++# CONFIG_ATH5K_PCI is not set ++CONFIG_WLAN_VENDOR_ATMEL=y ++CONFIG_WLAN_VENDOR_BROADCOM=y ++CONFIG_WLAN_VENDOR_CISCO=y ++CONFIG_WLAN_VENDOR_INTEL=y ++CONFIG_WLAN_VENDOR_INTERSIL=y ++# CONFIG_HOSTAP is not set ++# CONFIG_PRISM54 is not set ++CONFIG_WLAN_VENDOR_MARVELL=y ++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 ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_VMXNET3 is not set ++# CONFIG_ISDN is not set ++# CONFIG_NVM is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++CONFIG_INPUT_FF_MEMLESS=y ++# CONFIG_INPUT_POLLDEV is not set ++# CONFIG_INPUT_SPARSEKMAP is not set ++# CONFIG_INPUT_MATRIXKMAP is not set ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_CLPS711X is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_GOLDFISH_EVENTS is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_ST_KEYSCAN is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_SH_KEYSC is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++CONFIG_INPUT_JOYSTICK=y ++# CONFIG_JOYSTICK_ANALOG is not set ++# CONFIG_JOYSTICK_A3D is not set ++# CONFIG_JOYSTICK_ADI is not set ++# CONFIG_JOYSTICK_COBRA is not set ++# CONFIG_JOYSTICK_GF2K is not set ++# CONFIG_JOYSTICK_GRIP is not set ++# CONFIG_JOYSTICK_GRIP_MP is not set ++# CONFIG_JOYSTICK_GUILLEMOT is not set ++# CONFIG_JOYSTICK_INTERACT is not set ++# CONFIG_JOYSTICK_SIDEWINDER is not set ++# CONFIG_JOYSTICK_TMDC is not set ++# CONFIG_JOYSTICK_IFORCE is not set ++# CONFIG_JOYSTICK_WARRIOR is not set ++# CONFIG_JOYSTICK_MAGELLAN is not set ++# CONFIG_JOYSTICK_SPACEORB is not set ++# CONFIG_JOYSTICK_SPACEBALL is not set ++# CONFIG_JOYSTICK_STINGER is not set ++# CONFIG_JOYSTICK_TWIDJOY is not set ++# CONFIG_JOYSTICK_ZHENHUA is not set ++# CONFIG_JOYSTICK_AS5011 is not set ++# CONFIG_JOYSTICK_JOYDUMP is not set ++# CONFIG_JOYSTICK_XPAD is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_GP2A is not set ++# CONFIG_INPUT_GPIO_BEEPER is not set ++# CONFIG_INPUT_GPIO_TILT_POLLED is not set ++# CONFIG_INPUT_GPIO_DECODER is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INPUT_CM109 is not set ++# CONFIG_INPUT_REGULATOR_HAPTIC is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV260X_HAPTICS is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_INPUT_HISI_POWERKEY is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_SERIO_OLPC_APSP is not set ++# CONFIG_SERIO_SUN4I_PS2 is not set ++# CONFIG_USERIO is not set ++CONFIG_GAMEPORT=y ++# CONFIG_GAMEPORT_NS558 is not set ++# CONFIG_GAMEPORT_L4 is not set ++# CONFIG_GAMEPORT_EMU10K1 is not set ++# CONFIG_GAMEPORT_FM801 is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_NOZOMI is not set ++# CONFIG_N_GSM is not set ++# CONFIG_TRACE_SINK is not set ++CONFIG_DEVMEM=y ++CONFIG_DEVKMEM=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_ATMEL is not set ++# CONFIG_SERIAL_CLPS711X is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X is not set ++# CONFIG_SERIAL_IMX is not set ++# CONFIG_SERIAL_UARTLITE is not set ++# CONFIG_SERIAL_SH_SCI is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_JSM is not set ++# CONFIG_SERIAL_SCCNXP is not set ++# CONFIG_SERIAL_SC16IS7XX is not set ++# CONFIG_SERIAL_TIMBERDALE is not set ++# CONFIG_SERIAL_BCM63XX is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_IFX6X60 is not set ++# CONFIG_SERIAL_PCH_UART is not set ++# CONFIG_SERIAL_MXS_AUART is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++# CONFIG_SERIAL_MPS2_UART is not set ++# CONFIG_SERIAL_ARC is not set ++# CONFIG_SERIAL_RP2 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_SERIAL_MVEBU_UART 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_APPLICOM is not set ++ ++# ++# PCMCIA character devices ++# ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_DEVPORT=y ++# 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=y ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set ++# CONFIG_I2C_MUX_GPIO is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PCA954x is not set ++# CONFIG_I2C_MUX_PINCTRL is not set ++# CONFIG_I2C_MUX_REG is not set ++# CONFIG_I2C_DEMUX_PINCTRL 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 ++# ++ ++# ++# PC SMBus host controller drivers ++# ++# CONFIG_I2C_ALI1535 is not set ++# CONFIG_I2C_ALI1563 is not set ++# CONFIG_I2C_ALI15X3 is not set ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++# CONFIG_I2C_HIX5HD2 is not set ++# CONFIG_I2C_I801 is not set ++# CONFIG_I2C_ISCH is not set ++# CONFIG_I2C_PIIX4 is not set ++# CONFIG_I2C_NFORCE2 is not set ++# CONFIG_I2C_SIS5595 is not set ++# CONFIG_I2C_SIS630 is not set ++# CONFIG_I2C_SIS96X is not set ++# CONFIG_I2C_VIA is not set ++# CONFIG_I2C_VIAPRO is not set ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_AXXIA is not set ++# CONFIG_I2C_BCM_IPROC is not set ++# CONFIG_I2C_BRCMSTB is not set ++# CONFIG_I2C_CADENCE is not set ++# CONFIG_I2C_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_DESIGNWARE_PCI is not set ++# CONFIG_I2C_EFM32 is not set ++# CONFIG_I2C_EG20T is not set ++# CONFIG_I2C_EMEV2 is not set ++# CONFIG_I2C_GPIO is not set ++CONFIG_I2C_HIBVT=y ++# CONFIG_I2C_IMG is not set ++# CONFIG_I2C_JZ4780 is not set ++# CONFIG_I2C_LPC2K is not set ++# CONFIG_I2C_MESON is not set ++# CONFIG_I2C_MT65XX is not set ++# CONFIG_I2C_NOMADIK 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_RIIC is not set ++# CONFIG_I2C_RK3X is not set ++# CONFIG_I2C_SH_MOBILE is not set ++# CONFIG_I2C_SIMTEC is not set ++# CONFIG_I2C_SUN6I_P2WI is not set ++# CONFIG_I2C_UNIPHIER is not set ++# CONFIG_I2C_UNIPHIER_F is not set ++# CONFIG_I2C_VERSATILE is not set ++# CONFIG_I2C_THUNDERX is not set ++# CONFIG_I2C_XILINX is not set ++# CONFIG_I2C_XLP9XX is not set ++# CONFIG_I2C_RCAR 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_DMA_MSG_MIN_LEN=5 ++CONFIG_DMA_MSG_MAX_LEN=4090 ++# 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_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_ATMEL is not set ++# CONFIG_SPI_AXI_SPI_ENGINE is not set ++# CONFIG_SPI_BCM2835 is not set ++# CONFIG_SPI_BCM2835AUX is not set ++# CONFIG_SPI_BCM63XX is not set ++# CONFIG_SPI_BCM63XX_HSSPI is not set ++# CONFIG_SPI_BCM_QSPI is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_CLPS711X is not set ++# CONFIG_SPI_DESIGNWARE is not set ++# CONFIG_SPI_EP93XX is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_IMG_SPFI is not set ++# CONFIG_SPI_IMX is not set ++# CONFIG_SPI_JCORE is not set ++# CONFIG_SPI_LP8841_RTC is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_FSL_DSPI is not set ++# CONFIG_SPI_MESON_SPIFC is not set ++# CONFIG_SPI_MT65XX is not set ++# CONFIG_SPI_OC_TINY is not set ++# CONFIG_SPI_OMAP24XX is not set ++# CONFIG_SPI_TI_QSPI is not set ++# CONFIG_SPI_OMAP_100K is not set ++# CONFIG_SPI_ORION is not set ++# CONFIG_SPI_PIC32 is not set ++# CONFIG_SPI_PIC32_SQI is not set ++CONFIG_SPI_PL022=y ++# CONFIG_SPI_PXA2XX is not set ++# CONFIG_SPI_PXA2XX_PCI is not set ++# CONFIG_SPI_ROCKCHIP is not set ++# CONFIG_SPI_RSPI is not set ++# CONFIG_SPI_SC18IS602 is not set ++# CONFIG_SPI_SH_MSIOF is not set ++# CONFIG_SPI_SH is not set ++# CONFIG_SPI_SH_HSPI is not set ++# CONFIG_SPI_ST_SSC4 is not set ++# CONFIG_SPI_SUN4I is not set ++# CONFIG_SPI_SUN6I is not set ++# CONFIG_SPI_TEGRA114 is not set ++# CONFIG_SPI_TEGRA20_SFLASH is not set ++# CONFIG_SPI_TEGRA20_SLINK is not set ++# CONFIG_SPI_THUNDERX is not set ++# CONFIG_SPI_TOPCLIFF_PCH is not set ++# CONFIG_SPI_TXX9 is not set ++# CONFIG_SPI_XCOMM is not set ++# CONFIG_SPI_XILINX is not set ++# CONFIG_SPI_XLP is not set ++# CONFIG_SPI_XTENSA_XTFPGA is not set ++# CONFIG_SPI_ZYNQMP_GQSPI is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_PTP_1588_CLOCK_PCH is not set ++CONFIG_PINCTRL=y ++ ++# ++# Pin controllers ++# ++CONFIG_PINMUX=y ++CONFIG_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++# CONFIG_PINCTRL_AMD is not set ++# CONFIG_PINCTRL_LPC18XX is not set ++CONFIG_PINCTRL_SINGLE=y ++# CONFIG_PINCTRL_ASPEED_G4 is not set ++# CONFIG_PINCTRL_ASPEED_G5 is not set ++# CONFIG_PINCTRL_BCM281XX is not set ++# CONFIG_PINCTRL_IPROC_GPIO is not set ++# CONFIG_PINCTRL_CYGNUS_MUX is not set ++# CONFIG_PINCTRL_NSP_GPIO is not set ++# CONFIG_PINCTRL_NS2_MUX is not set ++# CONFIG_PINCTRL_NSP_MUX is not set ++# CONFIG_PINCTRL_BERLIN_BG2 is not set ++# CONFIG_PINCTRL_BERLIN_BG2CD is not set ++# CONFIG_PINCTRL_BERLIN_BG2Q is not set ++# CONFIG_PINCTRL_BERLIN_BG4CT is not set ++# CONFIG_PINCTRL_PXA25X is not set ++# CONFIG_PINCTRL_PXA27X is not set ++# CONFIG_PINCTRL_APQ8064 is not set ++# CONFIG_PINCTRL_APQ8084 is not set ++# CONFIG_PINCTRL_IPQ4019 is not set ++# CONFIG_PINCTRL_IPQ8064 is not set ++# CONFIG_PINCTRL_MSM8660 is not set ++# CONFIG_PINCTRL_MSM8960 is not set ++# CONFIG_PINCTRL_MDM9615 is not set ++# CONFIG_PINCTRL_MSM8X74 is not set ++# CONFIG_PINCTRL_MSM8916 is not set ++# CONFIG_PINCTRL_MSM8996 is not set ++# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set ++# CONFIG_PINCTRL_STM32F429 is not set ++# CONFIG_PINCTRL_STM32F746 is not set ++# CONFIG_PINCTRL_UNIPHIER is not set ++# CONFIG_PINCTRL_MT2701 is not set ++# CONFIG_PINCTRL_MT7623 is not set ++# CONFIG_PINCTRL_MT8135 is not set ++# CONFIG_PINCTRL_MT8127 is not set ++# CONFIG_PINCTRL_MT8173 is not set ++# CONFIG_PINCTRL_MT6397 is not set ++CONFIG_GPIOLIB=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_GENERIC=y ++ ++# ++# Memory mapped GPIO drivers ++# ++# CONFIG_GPIO_74XX_MMIO is not set ++# CONFIG_GPIO_ALTERA is not set ++# CONFIG_GPIO_ASPEED is not set ++# CONFIG_GPIO_ATH79 is not set ++# CONFIG_GPIO_BCM_KONA is not set ++# CONFIG_GPIO_BRCMSTB is not set ++# CONFIG_GPIO_CLPS711X is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_ETRAXFS is not set ++CONFIG_GPIO_GENERIC_PLATFORM=y ++# CONFIG_GPIO_GRGPIO is not set ++# CONFIG_GPIO_IOP is not set ++# CONFIG_GPIO_LPC18XX is not set ++# CONFIG_GPIO_MB86S7X is not set ++# CONFIG_GPIO_MOCKUP is not set ++# CONFIG_GPIO_MOXART is not set ++# CONFIG_GPIO_MPC8XXX is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_RCAR is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_TEGRA is not set ++# CONFIG_GPIO_TS4800 is not set ++# CONFIG_GPIO_VX855 is not set ++# CONFIG_GPIO_XGENE is not set ++# CONFIG_GPIO_XILINX is not set ++# CONFIG_GPIO_XLP 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 ++# ++ ++# ++# PCI GPIO expanders ++# ++# CONFIG_GPIO_AMD8111 is not set ++# CONFIG_GPIO_BT8XX is not set ++# CONFIG_GPIO_ML_IOH is not set ++# CONFIG_GPIO_PCH is not set ++# CONFIG_GPIO_RDC321X 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++# CONFIG_POWER_RESET_HISI is not set ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_XGENE is not set ++# CONFIG_POWER_RESET_KEYSTONE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_POWER_RESET_RMOBILE is not set ++# CONFIG_POWER_RESET_ZX is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_ACT8945A is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_MANAGER is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24257 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_BQ25890 is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_BATTERY_GOLDFISH is not set ++# CONFIG_CHARGER_RT9455 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_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_MX25_TSADC is not set ++# CONFIG_MFD_HI6421_PMIC is not set ++# CONFIG_MFD_HI655X_PMIC is not set ++CONFIG_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_HTC_I2CPLD is not set ++# CONFIG_LPC_ICH is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_INTEL_SOC_PMIC is not set ++# CONFIG_MFD_JANZ_CMODIO 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_RDC321X is not set ++# CONFIG_MFD_RTSX_PCI 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=y ++# 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_TIMBERDALE is not set ++# CONFIG_MFD_TC3589X is not set ++# CONFIG_MFD_TMIO is not set ++# CONFIG_MFD_VX855 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_MFD_STW481X is not set ++CONFIG_REGULATOR=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_LTC3676 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MT6311 is not set ++# CONFIG_REGULATOR_PBIAS is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_PV88060 is not set ++# CONFIG_REGULATOR_PV88080 is not set ++# CONFIG_REGULATOR_PV88090 is not set ++# CONFIG_REGULATOR_QCOM_SPMI is not set ++# CONFIG_REGULATOR_STW481X_VMMC is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=y ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=y ++CONFIG_VIDEO_V4L2=y ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=y ++CONFIG_VIDEOBUF2_MEMOPS=y ++CONFIG_VIDEOBUF2_VMALLOC=y ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++CONFIG_MEDIA_USB_SUPPORT=y ++ ++# ++# Webcam devices ++# ++CONFIG_USB_VIDEO_CLASS=y ++CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y ++CONFIG_USB_GSPCA=m ++# CONFIG_USB_M5602 is not set ++# CONFIG_USB_STV06XX is not set ++# CONFIG_USB_GL860 is not set ++# CONFIG_USB_GSPCA_BENQ is not set ++# CONFIG_USB_GSPCA_CONEX is not set ++# CONFIG_USB_GSPCA_CPIA1 is not set ++# CONFIG_USB_GSPCA_DTCS033 is not set ++# CONFIG_USB_GSPCA_ETOMS is not set ++# CONFIG_USB_GSPCA_FINEPIX is not set ++# CONFIG_USB_GSPCA_JEILINJ is not set ++# CONFIG_USB_GSPCA_JL2005BCD is not set ++# CONFIG_USB_GSPCA_KINECT is not set ++# CONFIG_USB_GSPCA_KONICA is not set ++# CONFIG_USB_GSPCA_MARS is not set ++# CONFIG_USB_GSPCA_MR97310A is not set ++# CONFIG_USB_GSPCA_NW80X is not set ++# CONFIG_USB_GSPCA_OV519 is not set ++# CONFIG_USB_GSPCA_OV534 is not set ++# CONFIG_USB_GSPCA_OV534_9 is not set ++# CONFIG_USB_GSPCA_PAC207 is not set ++# CONFIG_USB_GSPCA_PAC7302 is not set ++# CONFIG_USB_GSPCA_PAC7311 is not set ++# CONFIG_USB_GSPCA_SE401 is not set ++# CONFIG_USB_GSPCA_SN9C2028 is not set ++# CONFIG_USB_GSPCA_SN9C20X is not set ++# CONFIG_USB_GSPCA_SONIXB is not set ++# CONFIG_USB_GSPCA_SONIXJ is not set ++# CONFIG_USB_GSPCA_SPCA500 is not set ++# CONFIG_USB_GSPCA_SPCA501 is not set ++# CONFIG_USB_GSPCA_SPCA505 is not set ++# CONFIG_USB_GSPCA_SPCA506 is not set ++# CONFIG_USB_GSPCA_SPCA508 is not set ++# CONFIG_USB_GSPCA_SPCA561 is not set ++# CONFIG_USB_GSPCA_SPCA1528 is not set ++# CONFIG_USB_GSPCA_SQ905 is not set ++# CONFIG_USB_GSPCA_SQ905C is not set ++# CONFIG_USB_GSPCA_SQ930X is not set ++# CONFIG_USB_GSPCA_STK014 is not set ++# CONFIG_USB_GSPCA_STK1135 is not set ++# CONFIG_USB_GSPCA_STV0680 is not set ++# CONFIG_USB_GSPCA_SUNPLUS is not set ++# CONFIG_USB_GSPCA_T613 is not set ++# CONFIG_USB_GSPCA_TOPRO is not set ++# CONFIG_USB_GSPCA_TOUPTEK is not set ++# CONFIG_USB_GSPCA_TV8532 is not set ++# CONFIG_USB_GSPCA_VC032X is not set ++# CONFIG_USB_GSPCA_VICAM is not set ++# CONFIG_USB_GSPCA_XIRLINK_CIT is not set ++# CONFIG_USB_GSPCA_ZC3XX is not set ++# CONFIG_USB_PWC is not set ++# CONFIG_VIDEO_CPIA2 is not set ++# CONFIG_USB_ZR364XX is not set ++# CONFIG_USB_STKWEBCAM is not set ++# CONFIG_USB_S2255 is not set ++ ++# ++# Webcam, TV (analog/digital) USB devices ++# ++# CONFIG_VIDEO_EM28XX is not set ++# CONFIG_MEDIA_PCI_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, spi, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# I2C Encoders, decoders, sensors and other helper chips ++# ++ ++# ++# Audio decoders, processors and mixers ++# ++# CONFIG_VIDEO_TVAUDIO is not set ++# CONFIG_VIDEO_TDA7432 is not set ++# CONFIG_VIDEO_TDA9840 is not set ++# CONFIG_VIDEO_TEA6415C is not set ++# CONFIG_VIDEO_TEA6420 is not set ++# CONFIG_VIDEO_MSP3400 is not set ++# CONFIG_VIDEO_CS3308 is not set ++# CONFIG_VIDEO_CS5345 is not set ++# CONFIG_VIDEO_CS53L32A is not set ++# CONFIG_VIDEO_TLV320AIC23B is not set ++# CONFIG_VIDEO_UDA1342 is not set ++# CONFIG_VIDEO_WM8775 is not set ++# CONFIG_VIDEO_WM8739 is not set ++# CONFIG_VIDEO_VP27SMPX is not set ++# CONFIG_VIDEO_SONY_BTF_MPX is not set ++ ++# ++# RDS decoders ++# ++# CONFIG_VIDEO_SAA6588 is not set ++ ++# ++# Video decoders ++# ++# CONFIG_VIDEO_ADV7183 is not set ++# CONFIG_VIDEO_BT819 is not set ++# CONFIG_VIDEO_BT856 is not set ++# CONFIG_VIDEO_BT866 is not set ++# CONFIG_VIDEO_KS0127 is not set ++# CONFIG_VIDEO_ML86V7667 is not set ++# CONFIG_VIDEO_SAA7110 is not set ++# CONFIG_VIDEO_SAA711X is not set ++# CONFIG_VIDEO_TVP514X is not set ++# CONFIG_VIDEO_TVP5150 is not set ++# CONFIG_VIDEO_TVP7002 is not set ++# CONFIG_VIDEO_TW2804 is not set ++# CONFIG_VIDEO_TW9903 is not set ++# CONFIG_VIDEO_TW9906 is not set ++# CONFIG_VIDEO_VPX3220 is not set ++ ++# ++# Video and audio decoders ++# ++# CONFIG_VIDEO_SAA717X is not set ++# CONFIG_VIDEO_CX25840 is not set ++ ++# ++# Video encoders ++# ++# CONFIG_VIDEO_SAA7127 is not set ++# CONFIG_VIDEO_SAA7185 is not set ++# CONFIG_VIDEO_ADV7170 is not set ++# CONFIG_VIDEO_ADV7175 is not set ++# CONFIG_VIDEO_ADV7343 is not set ++# CONFIG_VIDEO_ADV7393 is not set ++# CONFIG_VIDEO_AK881X is not set ++# CONFIG_VIDEO_THS8200 is not set ++ ++# ++# Camera sensor devices ++# ++# CONFIG_VIDEO_OV2659 is not set ++# CONFIG_VIDEO_OV7640 is not set ++# CONFIG_VIDEO_OV7670 is not set ++# CONFIG_VIDEO_VS6624 is not set ++# CONFIG_VIDEO_MT9M111 is not set ++# CONFIG_VIDEO_MT9V011 is not set ++# CONFIG_VIDEO_SR030PC30 is not set ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++# CONFIG_VIDEO_UPD64031A is not set ++# CONFIG_VIDEO_UPD64083 is not set ++ ++# ++# Audio/Video compression chips ++# ++# CONFIG_VIDEO_SAA6752HS is not set ++ ++# ++# Miscellaneous helper chips ++# ++# CONFIG_VIDEO_THS7303 is not set ++# CONFIG_VIDEO_M52790 is not set ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# SPI helper chips ++# ++ ++# ++# Customise DVB Frontends ++# ++# CONFIG_DVB_AU8522_V4L is not set ++# CONFIG_DVB_TUNER_DIB0070 is not set ++# CONFIG_DVB_TUNER_DIB0090 is not set ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++CONFIG_VGA_ARB=y ++CONFIG_VGA_ARB_MAX_GPUS=16 ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_CIRRUS is not set ++# CONFIG_FB_PM2 is not set ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CLPS711X is not set ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_NVIDIA is not set ++# CONFIG_FB_RIVA is not set ++# CONFIG_FB_I740 is not set ++# CONFIG_FB_MATROX is not set ++# CONFIG_FB_RADEON is not set ++# CONFIG_FB_ATY128 is not set ++# CONFIG_FB_ATY is not set ++# CONFIG_FB_S3 is not set ++# CONFIG_FB_SAVAGE is not set ++# CONFIG_FB_SIS is not set ++# CONFIG_FB_NEOMAGIC is not set ++# CONFIG_FB_KYRO is not set ++# CONFIG_FB_3DFX is not set ++# CONFIG_FB_VOODOO1 is not set ++# CONFIG_FB_VT8623 is not set ++# CONFIG_FB_TRIDENT is not set ++# CONFIG_FB_ARK is not set ++# CONFIG_FB_PM3 is not set ++# CONFIG_FB_CARMINE is not set ++# CONFIG_FB_TMIO is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_GOLDFISH is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_MB862XX is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_FB_SM712 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++CONFIG_DUMMY_CONSOLE_COLUMNS=80 ++CONFIG_DUMMY_CONSOLE_ROWS=25 ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++# CONFIG_HID_BETOP_FF is not set ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# 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 is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PCI=y ++CONFIG_USB_XHCI_PLATFORM=y ++# CONFIG_USB_XHCI_MTK is not set ++# CONFIG_USB_XHCI_MVEBU is not set ++# CONFIG_USB_XHCI_RCAR 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_UHCI_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 ++# CONFIG_USB_RENESAS_USBHS is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++# CONFIG_USB_WDM is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++# CONFIG_USBIP_CORE is not set ++# CONFIG_USB_MUSB_HDRC is not set ++CONFIG_USB_DWC3=y ++# CONFIG_USB_DWC3_HOST is not set ++CONFIG_USB_DWC3_GADGET=y ++# CONFIG_USB_DWC3_DUAL_ROLE is not set ++ ++# ++# Platform Glue Driver Support ++# ++CONFIG_USB_DWC3_EXYNOS=y ++CONFIG_USB_DWC3_PCI=y ++CONFIG_USB_DWC3_KEYSTONE=y ++CONFIG_USB_DWC3_OF_SIMPLE=y ++# CONFIG_USB_DWC2 is not set ++# CONFIG_USB_CHIPIDEA 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++# CONFIG_USB_GADGET_DEBUG_FS is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_RENESAS_USB3 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_BDC_UDC is not set ++# CONFIG_USB_AMD5536UDC is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_NET2280 is not set ++# CONFIG_USB_GOKU is not set ++# CONFIG_USB_EG20T is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_MASS_STORAGE=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM 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_ARMMMCI is not set ++CONFIG_MMC_SDHCI=y ++# CONFIG_MMC_SDHCI_PCI is not set ++CONFIG_MMC_SDHCI_PLTFM=y ++# CONFIG_MMC_SDHCI_OF_ARASAN is not set ++# CONFIG_MMC_SDHCI_OF_AT91 is not set ++CONFIG_MMC_SDHCI_HISI=y ++# CONFIG_MMC_SDHCI_PXAV3 is not set ++# CONFIG_MMC_SDHCI_PXAV2 is not set ++# CONFIG_MMC_SDHCI_F_SDH30 is not set ++# CONFIG_MMC_SDHCI_IPROC is not set ++# CONFIG_MMC_OMAP_HS is not set ++# CONFIG_MMC_TIFM_SD is not set ++# CONFIG_MMC_GOLDFISH is not set ++# CONFIG_MMC_SPI is not set ++# CONFIG_MMC_SDHI is not set ++# CONFIG_MMC_CB710 is not set ++# CONFIG_MMC_VIA_SDMMC is not set ++# CONFIG_MMC_DW is not set ++# CONFIG_MMC_SH_MMCIF is not set ++# CONFIG_MMC_VUB300 is not set ++# CONFIG_MMC_USHC is not set ++# CONFIG_MMC_USDHI6ROL0 is not set ++# CONFIG_MMC_TOSHIBA_PCI 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_INFINIBAND is not set ++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=y ++ ++# ++# SPI and I2C RTC drivers ++# ++# CONFIG_RTC_DRV_DS3232 is not set ++# CONFIG_RTC_DRV_PCF2127 is not set ++# CONFIG_RTC_DRV_RV3029C2 is not set ++ ++# ++# Platform RTC drivers ++# ++CONFIG_RTC_DRV_HIBVT=y ++# 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_SPEAR is not set ++# CONFIG_RTC_DRV_NUC900 is not set ++# CONFIG_RTC_DRV_ZYNQMP is not set ++ ++# ++# on-CPU RTC drivers ++# ++# CONFIG_RTC_DRV_ASM9260 is not set ++# CONFIG_RTC_DRV_DAVINCI is not set ++# CONFIG_RTC_DRV_DIGICOLOR is not set ++# CONFIG_RTC_DRV_OMAP is not set ++# CONFIG_RTC_DRV_S3C is not set ++# CONFIG_RTC_DRV_EP93XX is not set ++# CONFIG_RTC_DRV_VR41XX is not set ++# CONFIG_RTC_DRV_PL030 is not set ++# CONFIG_RTC_DRV_PL031 is not set ++# CONFIG_RTC_DRV_AT32AP700X is not set ++# CONFIG_RTC_DRV_AT91RM9200 is not set ++# CONFIG_RTC_DRV_AT91SAM9 is not set ++# CONFIG_RTC_DRV_GENERIC is not set ++# CONFIG_RTC_DRV_VT8500 is not set ++# CONFIG_RTC_DRV_SUNXI is not set ++# CONFIG_RTC_DRV_MV is not set ++# CONFIG_RTC_DRV_ARMADA38X is not set ++# CONFIG_RTC_DRV_GEMINI is not set ++# CONFIG_RTC_DRV_COH901331 is not set ++# CONFIG_RTC_DRV_STMP is not set ++# CONFIG_RTC_DRV_JZ4740 is not set ++# CONFIG_RTC_DRV_LPC24XX is not set ++# CONFIG_RTC_DRV_LPC32XX is not set ++# CONFIG_RTC_DRV_PM8XXX is not set ++# CONFIG_RTC_DRV_TEGRA is not set ++# CONFIG_RTC_DRV_SNVS is not set ++# CONFIG_RTC_DRV_MOXART is not set ++# CONFIG_RTC_DRV_MT6397 is not set ++# CONFIG_RTC_DRV_XGENE is not set ++ ++# ++# HID Sensor RTC drivers ++# ++# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set ++CONFIG_DMADEVICES=y ++# CONFIG_DMADEVICES_DEBUG is not set ++ ++# ++# DMA Devices ++# ++CONFIG_DMA_ENGINE=y ++CONFIG_DMA_VIRTUAL_CHANNELS=y ++CONFIG_DMA_OF=y ++# CONFIG_AMBA_PL08X is not set ++# CONFIG_AXI_DMAC is not set ++# CONFIG_COH901318 is not set ++# CONFIG_DMA_JZ4740 is not set ++# CONFIG_DMA_JZ4780 is not set ++# CONFIG_DMA_OMAP is not set ++# CONFIG_DMA_SA11X0 is not set ++# CONFIG_DMA_SUN6I is not set ++# CONFIG_EP93XX_DMA is not set ++# CONFIG_FSL_EDMA is not set ++# CONFIG_IMG_MDC_DMA is not set ++# CONFIG_INTEL_IDMA64 is not set ++# CONFIG_K3_DMA is not set ++# CONFIG_MMP_PDMA is not set ++# CONFIG_MMP_TDMA is not set ++# CONFIG_MV_XOR is not set ++# CONFIG_MV_XOR_V2 is not set ++# CONFIG_NBPFAXI_DMA is not set ++# CONFIG_PCH_DMA is not set ++# CONFIG_PL330_DMA is not set ++# CONFIG_STM32_DMA is not set ++# CONFIG_S3C24XX_DMAC is not set ++# CONFIG_TEGRA210_ADMA is not set ++# CONFIG_TIMB_DMA is not set ++# CONFIG_TI_EDMA is not set ++# CONFIG_XGENE_DMA is not set ++# CONFIG_XILINX_DMA is not set ++# CONFIG_XILINX_ZYNQMP_DMA is not set ++# CONFIG_ZX_DMA is not set ++CONFIG_HIEDMACV310=y ++# CONFIG_QCOM_HIDMA_MGMT is not set ++# CONFIG_QCOM_HIDMA is not set ++# CONFIG_DW_DMAC is not set ++# CONFIG_DW_DMAC_PCI is not set ++CONFIG_RENESAS_DMA=y ++CONFIG_SH_DMAE_BASE=y ++# CONFIG_SH_DMAE is not set ++# CONFIG_RCAR_DMAC is not set ++# CONFIG_RENESAS_USB_DMAC is not set ++# CONFIG_SUDMAC 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_PCI is not set ++# CONFIG_VIRTIO_MMIO is not set ++ ++# ++# Microsoft Hyper-V guest support ++# ++CONFIG_STAGING=y ++# CONFIG_COMEDI is not set ++# CONFIG_RTL8192U is not set ++# CONFIG_RTLLIB is not set ++# CONFIG_R8712U is not set ++# CONFIG_RTS5208 is not set ++# CONFIG_FB_SM750 is not set ++# CONFIG_FB_XGI is not set ++ ++# ++# Speakup console speech ++# ++# CONFIG_SPEAKUP is not set ++# CONFIG_STAGING_MEDIA is not set ++ ++# ++# Android ++# ++# CONFIG_ASHMEM is not set ++# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set ++CONFIG_ION=y ++# CONFIG_ION_TEST is not set ++# CONFIG_ION_DUMMY is not set ++# CONFIG_ION_OF is not set ++# CONFIG_STAGING_BOARD is not set ++# CONFIG_LTE_GDM724X is not set ++# CONFIG_MTD_SPINAND_MT29F is not set ++# CONFIG_LNET is not set ++# CONFIG_DGNC is not set ++# CONFIG_GS_FPGABOOT is not set ++# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set ++# CONFIG_FB_TFT is not set ++# CONFIG_FSL_MC_BUS is not set ++# CONFIG_MOST is not set ++# CONFIG_KS7010 is not set ++# CONFIG_GREYBUS 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_VERSATILE is not set ++# CONFIG_COMMON_CLK_SCPI is not set ++# 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_COMMON_CLK_AXI_CLKGEN is not set ++# CONFIG_CLK_QORIQ is not set ++# CONFIG_COMMON_CLK_XGENE is not set ++# CONFIG_COMMON_CLK_KEYSTONE is not set ++# CONFIG_COMMON_CLK_NXP is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++# CONFIG_COMMON_CLK_OXNAS is not set ++# CONFIG_CLK_BCM_63XX is not set ++# CONFIG_CLK_BCM_KONA is not set ++# CONFIG_COMMON_CLK_IPROC is not set ++# CONFIG_COMMON_CLK_HI3519 is not set ++# CONFIG_COMMON_CLK_HI3516A is not set ++# CONFIG_COMMON_CLK_HI3518EV20X is not set ++# CONFIG_COMMON_CLK_HI3536DV100 is not set ++CONFIG_COMMON_CLK_HI3559AV100=y ++CONFIG_COMMON_CLK_HI3521A=y ++CONFIG_COMMON_CLK_HI3531A=y ++# CONFIG_COMMON_CLK_HI6220 is not set ++CONFIG_RESET_HISI=y ++# CONFIG_COMMON_CLK_MT8135 is not set ++# CONFIG_COMMON_CLK_MT8173 is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++# CONFIG_COMMON_CLK_SAMSUNG is not set ++# CONFIG_S3C2410_COMMON_CLK is not set ++# CONFIG_S3C2412_COMMON_CLK is not set ++# CONFIG_S3C2443_COMMON_CLK is not set ++# CONFIG_SUNXI_CCU is not set ++# CONFIG_COMMON_CLK_TI_ADPLL is not set ++# CONFIG_CLK_UNIPHIER is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++# CONFIG_BCM2835_TIMER is not set ++# CONFIG_BCM_KONA_TIMER is not set ++# CONFIG_DIGICOLOR_TIMER is not set ++# CONFIG_DW_APB_TIMER is not set ++# CONFIG_ROCKCHIP_TIMER is not set ++# CONFIG_MESON6_TIMER is not set ++# CONFIG_SUN4I_TIMER is not set ++# CONFIG_SUN5I_HSTIMER is not set ++# CONFIG_VT8500_TIMER is not set ++# CONFIG_CADENCE_TTC_TIMER is not set ++# CONFIG_ASM9260_TIMER is not set ++# CONFIG_CLKSRC_DBX500_PRCMU is not set ++# CONFIG_CLPS711X_TIMER is not set ++# CONFIG_ATLAS7_TIMER is not set ++# CONFIG_MOXART_TIMER is not set ++# CONFIG_MXS_TIMER is not set ++# CONFIG_PRIMA2_TIMER is not set ++# CONFIG_NSPIRE_TIMER is not set ++# CONFIG_KEYSTONE_TIMER is not set ++# CONFIG_INTEGRATOR_AP_TIMER is not set ++# CONFIG_CLKSRC_PISTACHIO is not set ++# CONFIG_CLKSRC_TI_32K is not set ++# CONFIG_CLKSRC_MPS2 is not set ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set ++CONFIG_FSL_ERRATUM_A008585=y ++CONFIG_ARM_TIMER_SP804=y ++# CONFIG_TIMER_HISP804 is not set ++# CONFIG_ARMV7M_SYSTICK is not set ++# CONFIG_ATMEL_PIT is not set ++# CONFIG_ATMEL_ST is not set ++# CONFIG_CLKSRC_EXYNOS_MCT is not set ++# CONFIG_CLKSRC_SAMSUNG_PWM is not set ++# CONFIG_FSL_FTM_TIMER is not set ++# CONFIG_OXNAS_RPS_TIMER is not set ++# CONFIG_MTK_TIMER is not set ++# CONFIG_CLKSRC_JCORE_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_CLKSRC_VERSATILE is not set ++# CONFIG_CLKSRC_PXA is not set ++# CONFIG_H8300_TMR8 is not set ++# CONFIG_H8300_TMR16 is not set ++# CONFIG_H8300_TPU is not set ++# CONFIG_CLKSRC_ST_LPC 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_MTK_INFRACFG is not set ++# CONFIG_MTK_SCPSYS is not set ++# CONFIG_ROCKCHIP_PM_DOMAINS is not set ++# CONFIG_SOC_SAMSUNG is not set ++# CONFIG_SUNXI_SRAM is not set ++# CONFIG_SOC_TI is not set ++# CONFIG_UX500_SOC_ID is not set ++CONFIG_PM_DEVFREQ=y ++ ++# ++# DEVFREQ Governors ++# ++CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y ++# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set ++# CONFIG_DEVFREQ_GOV_POWERSAVE is not set ++# CONFIG_DEVFREQ_GOV_USERSPACE is not set ++# CONFIG_DEVFREQ_GOV_PASSIVE is not set ++ ++# ++# DEVFREQ Drivers ++# ++# CONFIG_ARM_EXYNOS_BUS_DEVFREQ is not set ++# CONFIG_PM_DEVFREQ_EVENT is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_NTB is not set ++# CONFIG_VME_BUS is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++CONFIG_ARM_GIC_V2M=y ++CONFIG_ARM_GIC_V3=y ++CONFIG_ARM_GIC_V3_ITS=y ++CONFIG_HISILICON_IRQ_MBIGEN=y ++# CONFIG_JCORE_AIC is not set ++# CONFIG_TS4800_IRQ is not set ++CONFIG_PARTITION_PERCPU=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_UNIPHIER is not set ++# CONFIG_RESET_ZYNQ is not set ++CONFIG_COMMON_RESET_HI6220=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_PHY_BCM_NS_USB2 is not set ++# CONFIG_PHY_BCM_NS_USB3 is not set ++CONFIG_ARMADA375_USBCLUSTER_PHY=y ++# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set ++# CONFIG_PHY_LPC18XX_USB_OTG is not set ++# CONFIG_PHY_PXA_28NM_HSIC is not set ++# CONFIG_PHY_PXA_28NM_USB2 is not set ++# CONFIG_OMAP_CONTROL_PHY is not set ++# CONFIG_PHY_EXYNOS_DP_VIDEO is not set ++# CONFIG_BCM_KONA_USB2_PHY is not set ++# CONFIG_PHY_HI6220_USB is not set ++# CONFIG_PHY_ROCKCHIP_INNO_USB2 is not set ++# CONFIG_PHY_ROCKCHIP_PCIE is not set ++# CONFIG_PHY_ROCKCHIP_TYPEC is not set ++# CONFIG_PHY_ST_SPEAR1310_MIPHY is not set ++# CONFIG_PHY_ST_SPEAR1340_MIPHY is not set ++# CONFIG_PHY_XGENE is not set ++# CONFIG_PHY_STIH407_USB is not set ++# CONFIG_PHY_BRCM_SATA is not set ++# CONFIG_PHY_CYGNUS_PCIE is not set ++CONFIG_HISI_PHY_USB3=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++ ++# ++# Performance monitor support ++# ++CONFIG_ARM_PMU=y ++# CONFIG_RAS is not set ++# CONFIG_THUNDERBOLT is not set ++ ++# ++# Android ++# ++CONFIG_ANDROID=y ++# CONFIG_ANDROID_BINDER_IPC is not set ++# CONFIG_LIBNVDIMM 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 ++# CONFIG_HI_DMAC is not set ++# CONFIG_HIVDMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE is not set ++ ++# ++# Firmware Drivers ++# ++CONFIG_ARM_PSCI_FW=y ++CONFIG_ARM_SCPI_POWER_DOMAIN=y ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++# CONFIG_MESON_SM is not set ++# CONFIG_ACPI is not set ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++CONFIG_FS_IOMAP=y ++CONFIG_EXT2_FS=y ++CONFIG_EXT2_FS_XATTR=y ++CONFIG_EXT2_FS_POSIX_ACL=y ++CONFIG_EXT2_FS_SECURITY=y ++CONFIG_EXT3_FS=y ++CONFIG_EXT3_FS_POSIX_ACL=y ++CONFIG_EXT3_FS_SECURITY=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_CHECK=y ++CONFIG_REISERFS_PROC_INFO=y ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_DEBUG=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++# CONFIG_XFS_WARN is not set ++# CONFIG_XFS_DEBUG is not set ++# CONFIG_GFS2_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_DAX is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_EXPORTFS=m ++# 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=y ++# CONFIG_QUOTA_NETLINK_INTERFACE is not set ++CONFIG_PRINT_QUOTA_WARNING=y ++# CONFIG_QUOTA_DEBUG is not set ++CONFIG_QUOTA_TREE=m ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_QUOTACTL=y ++CONFIG_AUTOFS4_FS=m ++CONFIG_FUSE_FS=y ++# CONFIG_CUSE is not set ++# CONFIG_OVERLAY_FS is not set ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=y ++# CONFIG_JOLIET is not set ++# CONFIG_ZISOFS is not set ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++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_KCORE is not set ++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=y ++CONFIG_TMPFS_XATTR=y ++# CONFIG_HUGETLBFS is not set ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_ARCH_HAS_GIGANTIC_PAGE=y ++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_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++CONFIG_SQUASHFS=y ++CONFIG_SQUASHFS_FILE_CACHE=y ++# CONFIG_SQUASHFS_FILE_DIRECT is not set ++CONFIG_SQUASHFS_DECOMP_SINGLE=y ++# CONFIG_SQUASHFS_DECOMP_MULTI is not set ++# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set ++# CONFIG_SQUASHFS_XATTR is not set ++CONFIG_SQUASHFS_ZLIB=y ++# CONFIG_SQUASHFS_LZ4 is not set ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set ++# CONFIG_SQUASHFS_EMBEDDED is not set ++CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 ++# 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFSD is not set ++CONFIG_GRACE_PERIOD=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=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=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=y ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++# 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 ++# CONFIG_VIRTUALIZATION is not set ++ ++# ++# Kernel hacking ++# ++ ++# ++# printk and dmesg options ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++# 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=2048 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++CONFIG_ARCH_WANT_FRAME_POINTERS=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++CONFIG_HAVE_ARCH_KASAN=y ++# CONFIG_KASAN is not set ++CONFIG_ARCH_HAS_KCOV=y ++# CONFIG_KCOV is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++CONFIG_LOCKUP_DETECTOR=y ++# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set ++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 ++# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set ++CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 ++# CONFIG_WQ_WATCHDOG is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++CONFIG_SCHED_INFO=y ++CONFIG_SCHEDSTATS=y ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_HAVE_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_PROVE_RCU is not set ++CONFIG_SPARSE_RCU_POINTER=y ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=21 ++CONFIG_RCU_TRACE=y ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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_TRACE_CLOCK=y ++CONFIG_TRACING_SUPPORT=y ++# CONFIG_FTRACE is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_LKDTM is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=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_ARM64_PTDUMP is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_DEBUG_ALIGN_RODATA is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS 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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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 is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++CONFIG_CRYPTO_NULL=m ++CONFIG_CRYPTO_NULL2=y ++# CONFIG_CRYPTO_PCRYPT is not set ++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=m ++# CONFIG_CRYPTO_GCM is not set ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# 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=y ++CONFIG_CRYPTO_HMAC=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# 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 is not set ++# 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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_CRYPTO_DEV_S5P is not set ++# CONFIG_CRYPTO_DEV_ATMEL_AES is not set ++# CONFIG_CRYPTO_DEV_CCP is not set ++# CONFIG_CRYPTO_DEV_QCE is not set ++# CONFIG_CRYPTO_DEV_IMGTEC_HASH is not set ++ ++# ++# Certificates for signature checking ++# ++# CONFIG_ARM64_CRYPTO is not set ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++CONFIG_HAVE_ARCH_BITREVERSE=y ++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=y ++CONFIG_CRC16=y ++# CONFIG_CRC_T10DIF is not set ++CONFIG_CRC_ITU_T=y ++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=m ++# CONFIG_CRC8 is not set ++CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y ++# CONFIG_RANDOM32_SELFTEST is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=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_GZIP=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_NLATTR=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=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y +diff --git a/arch/arm64/configs/hi3559av100_arm64_big_little_emmc_amp_defconfig b/arch/arm64/configs/hi3559av100_arm64_big_little_emmc_amp_defconfig +new file mode 100644 +index 0000000..2154a40 +--- /dev/null ++++ b/arch/arm64/configs/hi3559av100_arm64_big_little_emmc_amp_defconfig +@@ -0,0 +1,3852 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm64 4.9.37 Kernel Configuration ++# ++CONFIG_ARM64=y ++CONFIG_64BIT=y ++CONFIG_ARCH_PHYS_ADDR_T_64BIT=y ++CONFIG_MMU=y ++CONFIG_DEBUG_RODATA=y ++CONFIG_ARM64_PAGE_SHIFT=12 ++CONFIG_ARM64_CONT_SHIFT=4 ++CONFIG_ARCH_MMAP_RND_BITS_MIN=18 ++CONFIG_ARCH_MMAP_RND_BITS_MAX=24 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=y ++CONFIG_GENERIC_BUG=y ++CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CSUM=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_ZONE_DMA=y ++CONFIG_HAVE_GENERIC_RCU_GUP=y ++CONFIG_ARCH_DMA_ADDR_T_64BIT=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_NEED_SG_DMA_LENGTH=y ++CONFIG_SMP=y ++CONFIG_SWIOTLB=y ++CONFIG_IOMMU_HELPER=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_FIX_EARLYCON_MEM=y ++CONFIG_PGTABLE_LEVELS=3 ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++CONFIG_COMPILE_TEST=y ++CONFIG_LOCALVERSION="" ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_GENERIC_IRQ_MIGRATION=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_GENERIC_MSI_IRQ=y ++CONFIG_GENERIC_MSI_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++# CONFIG_IRQ_DOMAIN_DEBUG is not set ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_HZ_PERIODIC=y ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NO_HZ_FULL 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_TREE_RCU=y ++# CONFIG_RCU_EXPERT is not set ++CONFIG_SRCU=y ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++CONFIG_TREE_RCU_TRACE=y ++# CONFIG_RCU_EXPEDITE_BOOT is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=14 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y ++# CONFIG_CGROUPS is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++CONFIG_RELAY=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++# CONFIG_RD_LZ4 is not set ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_SYSCTL_EXCEPTION_TRACE=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_ALL is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y ++CONFIG_BPF_SYSCALL=y ++CONFIG_SHMEM=y ++CONFIG_AIO=y ++CONFIG_ADVISE_SYSCALLS=y ++CONFIG_USERFAULTFD=y ++CONFIG_PCI_QUIRKS=y ++CONFIG_MEMBARRIER=y ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++ ++# ++# Kernel Performance Events And Counters ++# ++CONFIG_PERF_EVENTS=y ++# CONFIG_DEBUG_PERF_USE_VMALLOC is not set ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_SLAB_FREELIST_RANDOM is not set ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_SYSTEM_DATA_VERIFICATION is not set ++# CONFIG_PROFILING is not set ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL is not set ++# CONFIG_UPROBES is not set ++# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set ++CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=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_HW_BREAKPOINT=y ++CONFIG_HAVE_PERF_REGS=y ++CONFIG_HAVE_PERF_USER_STACK_DUMP=y ++CONFIG_HAVE_ARCH_JUMP_LABEL=y ++CONFIG_HAVE_RCU_TABLE_FREE=y ++CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y ++CONFIG_HAVE_CMPXCHG_LOCAL=y ++CONFIG_HAVE_CMPXCHG_DOUBLE=y ++CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y ++CONFIG_HAVE_ARCH_SECCOMP_FILTER=y ++CONFIG_HAVE_GCC_PLUGINS=y ++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_ARCH_TRANSPARENT_HUGEPAGE=y ++CONFIG_HAVE_ARCH_HUGE_VMAP=y ++CONFIG_MODULES_USE_ELF_RELA=y ++CONFIG_ARCH_HAS_ELF_RANDOMIZE=y ++CONFIG_HAVE_ARCH_MMAP_RND_BITS=y ++CONFIG_ARCH_MMAP_RND_BITS=18 ++CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 ++# CONFIG_HAVE_ARCH_HASH is not set ++# CONFIG_ISA_BUS_API is not set ++CONFIG_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_COMPAT_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_SLABINFO=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_MODULES_TREE_LOOKUP=y ++CONFIG_BLOCK=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++CONFIG_BLOCK_COMPAT=y ++CONFIG_BLK_MQ_PCI=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_LOCK_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# Platform selection ++# ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_BCM2835 is not set ++# CONFIG_ARCH_BCM_IPROC is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_BRCMSTB is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_LAYERSCAPE is not set ++# CONFIG_ARCH_LG1K is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++CONFIG_ARCH_HI3559AV100=y ++# CONFIG_ACCESS_M7_DEV is not set ++CONFIG_ARCH_HISI_BVT_AMP=y ++# CONFIG_ARCH_MEDIATEK is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SEATTLE is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_STRATIX10 is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_SPRD is not set ++# CONFIG_ARCH_THUNDER is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_VULCAN is not set ++# CONFIG_ARCH_XGENE is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQMP is not set ++ ++# ++# Bus support ++# ++CONFIG_PCI=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_PCI_DOMAINS_GENERIC=y ++CONFIG_PCI_SYSCALL=y ++CONFIG_PCIEPORTBUS=y ++# CONFIG_PCIEAER is not set ++# CONFIG_PCIEASPM is not set ++# CONFIG_PCIE_PME is not set ++# CONFIG_PCIE_DPC is not set ++# CONFIG_PCIE_PTM is not set ++CONFIG_PCI_BUS_ADDR_T_64BIT=y ++CONFIG_PCI_MSI=y ++CONFIG_PCI_MSI_IRQ_DOMAIN=y ++# CONFIG_PCI_DEBUG is not set ++# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set ++# CONFIG_PCI_STUB is not set ++# CONFIG_PCI_IOV is not set ++# CONFIG_PCI_PRI is not set ++# CONFIG_PCI_PASID is not set ++# CONFIG_HOTPLUG_PCI is not set ++ ++# ++# PCI host controller drivers ++# ++# CONFIG_PCIE_DW_PLAT is not set ++# CONFIG_PCI_HOST_GENERIC is not set ++# CONFIG_PCI_HISI is not set ++# CONFIG_PCI_HOST_THUNDER_PEM is not set ++# CONFIG_PCI_HOST_THUNDER_ECAM is not set ++# CONFIG_HIPCIE is not set ++ ++# ++# Kernel Features ++# ++ ++# ++# ARM errata workarounds via the alternatives framework ++# ++CONFIG_ARM64_ERRATUM_826319=y ++CONFIG_ARM64_ERRATUM_827319=y ++CONFIG_ARM64_ERRATUM_824069=y ++CONFIG_ARM64_ERRATUM_819472=y ++CONFIG_ARM64_ERRATUM_832075=y ++CONFIG_ARM64_ERRATUM_845719=y ++CONFIG_ARM64_ERRATUM_843419=y ++CONFIG_CAVIUM_ERRATUM_22375=y ++CONFIG_CAVIUM_ERRATUM_23154=y ++CONFIG_CAVIUM_ERRATUM_27456=y ++CONFIG_QCOM_QDF2400_ERRATUM_0065=y ++CONFIG_ARM64_4K_PAGES=y ++# CONFIG_ARM64_16K_PAGES is not set ++# CONFIG_ARM64_64K_PAGES is not set ++CONFIG_ARM64_VA_BITS_39=y ++# CONFIG_ARM64_VA_BITS_48 is not set ++CONFIG_ARM64_VA_BITS=39 ++# CONFIG_CPU_BIG_ENDIAN is not set ++CONFIG_SCHED_MC=y ++# CONFIG_SCHED_SMT is not set ++CONFIG_NR_CPUS=64 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_NUMA is not set ++CONFIG_PREEMPT_NONE=y ++# CONFIG_PREEMPT_VOLUNTARY is not set ++# CONFIG_PREEMPT is not set ++# CONFIG_HZ_100 is not set ++# CONFIG_HZ_250 is not set ++# CONFIG_HZ_300 is not set ++CONFIG_HZ_1000=y ++CONFIG_HZ=1000 ++# CONFIG_SCHED_HRTICK is not set ++CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y ++CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y ++CONFIG_ARCH_SPARSEMEM_ENABLE=y ++CONFIG_ARCH_SPARSEMEM_DEFAULT=y ++CONFIG_ARCH_SELECT_MEMORY_MODEL=y ++CONFIG_HAVE_ARCH_PFN_VALID=y ++CONFIG_HW_PERF_EVENTS=y ++CONFIG_SYS_SUPPORTS_HUGETLBFS=y ++CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y ++CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_SPARSEMEM_MANUAL=y ++CONFIG_SPARSEMEM=y ++CONFIG_HAVE_MEMORY_PRESENT=y ++CONFIG_SPARSEMEM_EXTREME=y ++CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y ++CONFIG_SPARSEMEM_VMEMMAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=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=y ++CONFIG_BOUNCE=y ++CONFIG_KSM=y ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# CONFIG_TRANSPARENT_HUGEPAGE is not set ++# CONFIG_CLEANCACHE is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++# CONFIG_CMA_DEBUGFS is not set ++CONFIG_CMA_AREAS=7 ++# 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_FRAME_VECTOR=y ++# CONFIG_SECCOMP is not set ++# CONFIG_PARAVIRT is not set ++# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set ++# CONFIG_KEXEC is not set ++# CONFIG_XEN is not set ++CONFIG_FORCE_MAX_ZONEORDER=11 ++# CONFIG_ARMV8_DEPRECATED is not set ++ ++# ++# ARMv8.1 architectural features ++# ++CONFIG_ARM64_HW_AFDBM=y ++CONFIG_ARM64_PAN=y ++# CONFIG_ARM64_LSE_ATOMICS is not set ++CONFIG_ARM64_VHE=y ++ ++# ++# ARMv8.2 architectural features ++# ++CONFIG_ARM64_UAO=y ++CONFIG_ARM64_MODULE_CMODEL_LARGE=y ++# CONFIG_RANDOMIZE_BASE is not set ++ ++# ++# Boot options ++# ++CONFIG_CMDLINE="mem=128M console=ttyAMA0,115200 console=ttyMTD,blackbox" ++# CONFIG_CMDLINE_FORCE is not set ++# CONFIG_EFI is not set ++CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y ++CONFIG_IMG_GZ_DTB=y ++# CONFIG_IMG_DTB is not set ++CONFIG_BUILD_ARM64_APPENDED_KERNEL_IMAGE_NAME="Image.gz-dtb" ++CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES="hisilicon/hi3559av100-demb-emmc" ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_COMPAT_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++CONFIG_COMPAT=y ++CONFIG_SYSVIPC_COMPAT=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_SUSPEND_SKIP_SYNC is not set ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++CONFIG_PM_CLK=y ++CONFIG_PM_GENERIC_DOMAINS=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_PM_GENERIC_DOMAINS_SLEEP=y ++CONFIG_PM_GENERIC_DOMAINS_OF=y ++CONFIG_CPU_PM=y ++CONFIG_ARCH_HIBERNATION_POSSIBLE=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Idle ++# ++# CONFIG_CPU_IDLE is not set ++# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_ATTR_SET=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_STAT_DETAILS=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set ++ ++# ++# CPU frequency scaling drivers ++# ++# CONFIG_CPUFREQ_DT is not set ++# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++CONFIG_NET=y ++CONFIG_NET_INGRESS=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 is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++CONFIG_NET_IP_TUNNEL=m ++# 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=m ++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=y ++# CONFIG_IPV6_ROUTE_INFO 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_IPV6_ILA is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# 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=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++CONFIG_NETFILTER_INGRESS=y ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_DUP_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_DUP_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_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_QRTR is not set ++# CONFIG_NET_NCSI is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_SOCK_CGROUP_DATA is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_EBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER=y ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++# CONFIG_DEVTMPFS is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_GENERIC_CPU_AUTOPROBE=y ++CONFIG_REGMAP=y ++CONFIG_REGMAP_I2C=y ++CONFIG_REGMAP_SPI=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=4 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_ARM_CCI400_PMU is not set ++# CONFIG_ARM_CCI5xx_PMU is not set ++# CONFIG_ARM_CCN is not set ++# CONFIG_QCOM_EBI2 is not set ++# CONFIG_SIMPLE_PM_BUS 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 ++# CONFIG_MTD_BCM63XX_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_TS5500 is not set ++# CONFIG_MTD_INTEL_VR_NOR is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_DATAFLASH is not set ++# CONFIG_MTD_M25P80 is not set ++# 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=y ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOCG3 is not set ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_PCI is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_RICOH is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_VF610_NFC is not set ++# CONFIG_MTD_NAND_SH_FLCTL is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++CONFIG_MTD_SPI_NAND_HISI_BVT=y ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++CONFIG_MTD_SPI_NAND_HIFMC100=y ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# LPDDR & LPDDR2 PCM memory drivers ++# ++# CONFIG_MTD_LPDDR is not set ++CONFIG_MTD_SPI_NOR=y ++# CONFIG_MTD_MT81xx_NOR is not set ++# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set ++# CONFIG_SPI_FSL_QUADSPI is not set ++CONFIG_SPI_HISI_SFC=y ++# CONFIG_SPI_NXP_SPIFI is not set ++# CONFIG_MTD_SPI_IDS is not set ++# CONFIG_CLOSE_SPI_8PIN_4IO is not set ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++# CONFIG_MTD_UBI is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++# CONFIG_OF_UNITTEST is not set ++# CONFIG_OF_ALL_DTBS is not set ++CONFIG_OF_FLATTREE=y ++CONFIG_OF_EARLY_FLATTREE=y ++CONFIG_OF_ADDRESS=y ++CONFIG_OF_ADDRESS_PCI=y ++CONFIG_OF_IRQ=y ++CONFIG_OF_NET=y ++CONFIG_OF_MDIO=y ++CONFIG_OF_PCI=y ++CONFIG_OF_PCI_IRQ=y ++CONFIG_OF_RESERVED_MEM=y ++# CONFIG_OF_OVERLAY is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set ++# CONFIG_BLK_CPQ_CISS_DA is not set ++# CONFIG_BLK_DEV_DAC960 is not set ++# CONFIG_BLK_DEV_UMEM is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_SKD is not set ++# CONFIG_BLK_DEV_SX8 is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_BLK_DEV_RSXX is not set ++# CONFIG_BLK_DEV_NVME is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# CONFIG_SENSORS_LIS3LV02D is not set ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_DUMMY_IRQ is not set ++# CONFIG_PHANTOM is not set ++# CONFIG_INTEL_MID_PTI is not set ++# CONFIG_SGI_IOC4 is not set ++# CONFIG_TIFM_CORE is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ATMEL_SSC is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_HP_ILO is not set ++# CONFIG_QCOM_COINCELL 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_PCH_PHUB 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 ++# CONFIG_CB710_CORE 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_GENWQE is not set ++# 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=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_SCSI_CXGB3_ISCSI is not set ++# CONFIG_SCSI_CXGB4_ISCSI is not set ++# CONFIG_SCSI_BNX2_ISCSI is not set ++# CONFIG_BE2ISCSI is not set ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_HPSA is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_3W_SAS is not set ++# CONFIG_SCSI_ACARD is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX is not set ++# CONFIG_SCSI_AIC79XX is not set ++# CONFIG_SCSI_AIC94XX is not set ++# CONFIG_SCSI_HISI_SAS is not set ++# CONFIG_SCSI_MVSAS is not set ++# CONFIG_SCSI_MVUMI is not set ++# CONFIG_SCSI_ADVANSYS is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_SCSI_ESAS2R is not set ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++# CONFIG_SCSI_MPT3SAS is not set ++# CONFIG_SCSI_MPT2SAS is not set ++# CONFIG_SCSI_SMARTPQI is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_SCSI_HPTIOP is not set ++# CONFIG_SCSI_SNIC is not set ++# CONFIG_SCSI_DMX3191D is not set ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_IPS is not set ++# CONFIG_SCSI_INITIO is not set ++# CONFIG_SCSI_INIA100 is not set ++# CONFIG_SCSI_STEX is not set ++# CONFIG_SCSI_SYM53C8XX_2 is not set ++# CONFIG_SCSI_QLOGIC_1280 is not set ++# CONFIG_SCSI_QLA_ISCSI is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_AM53C974 is not set ++# CONFIG_SCSI_WD719X is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_PMCRAID is not set ++# CONFIG_SCSI_PM8001 is not set ++# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HAVE_PATA_PLATFORM=y ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++# CONFIG_FUSION is not set ++ ++# ++# IEEE 1394 (FireWire) support ++# ++# CONFIG_FIREWIRE is not set ++# CONFIG_FIREWIRE_NOSY is not set ++CONFIG_NETDEVICES=y ++CONFIG_NET_CORE=y ++# CONFIG_BONDING is not set ++# CONFIG_DUMMY is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC 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 ++# CONFIG_ARCNET is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++CONFIG_ETHERNET=y ++CONFIG_NET_VENDOR_3COM=y ++# CONFIG_VORTEX is not set ++# CONFIG_TYPHOON is not set ++CONFIG_NET_VENDOR_ADAPTEC=y ++# CONFIG_ADAPTEC_STARFIRE is not set ++CONFIG_NET_VENDOR_AGERE=y ++# CONFIG_ET131X is not set ++CONFIG_NET_VENDOR_ALTEON=y ++# CONFIG_ACENIC is not set ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_VENDOR_AMAZON is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC is not set ++CONFIG_NET_VENDOR_ATHEROS=y ++# CONFIG_ATL2 is not set ++# CONFIG_ATL1 is not set ++# CONFIG_ATL1E is not set ++# CONFIG_ATL1C is not set ++# CONFIG_ALX 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_BROCADE=y ++# CONFIG_BNA is not set ++# CONFIG_NET_CALXEDA_XGMAC is not set ++CONFIG_NET_VENDOR_CAVIUM=y ++# CONFIG_THUNDER_NIC_PF is not set ++# CONFIG_THUNDER_NIC_VF is not set ++# CONFIG_THUNDER_NIC_BGX is not set ++# CONFIG_THUNDER_NIC_RGX is not set ++# CONFIG_LIQUIDIO is not set ++CONFIG_NET_VENDOR_CHELSIO=y ++# CONFIG_CHELSIO_T1 is not set ++# CONFIG_CHELSIO_T3 is not set ++# CONFIG_CHELSIO_T4 is not set ++# CONFIG_CHELSIO_T4VF is not set ++CONFIG_NET_VENDOR_CISCO=y ++# CONFIG_ENIC is not set ++# CONFIG_CX_ECAT is not set ++# CONFIG_DNET is not set ++CONFIG_NET_VENDOR_DEC=y ++# CONFIG_NET_TULIP is not set ++CONFIG_NET_VENDOR_DLINK=y ++# CONFIG_DL2K is not set ++# CONFIG_SUNDANCE is not set ++CONFIG_NET_VENDOR_EMULEX=y ++# CONFIG_BE2NET is not set ++# CONFIG_NET_VENDOR_EZCHIP is not set ++CONFIG_NET_VENDOR_EXAR=y ++# CONFIG_S2IO is not set ++# CONFIG_VXGE is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DDR_64BIT=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++CONFIG_NET_VENDOR_HP=y ++# CONFIG_HP100 is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_JME is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++CONFIG_NET_VENDOR_MELLANOX=y ++# CONFIG_MLX4_EN is not set ++# CONFIG_MLX4_CORE is not set ++# CONFIG_MLX5_CORE is not set ++# CONFIG_MLXSW_CORE is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_MICROCHIP is not set ++CONFIG_NET_VENDOR_MYRI=y ++# CONFIG_MYRI10GE is not set ++# CONFIG_FEALNX is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NETRONOME is not set ++CONFIG_NET_VENDOR_NVIDIA=y ++# CONFIG_FORCEDETH is not set ++CONFIG_NET_VENDOR_OKI=y ++# CONFIG_PCH_GBE is not set ++# CONFIG_ETHOC is not set ++CONFIG_NET_PACKET_ENGINE=y ++# CONFIG_HAMACHI is not set ++# CONFIG_YELLOWFIN is not set ++CONFIG_NET_VENDOR_QLOGIC=y ++# CONFIG_QLA3XXX is not set ++# CONFIG_QLCNIC is not set ++# CONFIG_QLGE is not set ++# CONFIG_NETXEN_NIC is not set ++# CONFIG_QED is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++CONFIG_NET_VENDOR_REALTEK=y ++# CONFIG_8139CP is not set ++# CONFIG_8139TOO is not set ++# CONFIG_R8169 is not set ++# CONFIG_NET_VENDOR_RENESAS is not set ++CONFIG_NET_VENDOR_RDC=y ++# CONFIG_R6040 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_SILAN=y ++# CONFIG_SC92031 is not set ++CONFIG_NET_VENDOR_SIS=y ++# CONFIG_SIS900 is not set ++# CONFIG_SIS190 is not set ++# CONFIG_SFC is not set ++# CONFIG_NET_VENDOR_SMSC is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++CONFIG_NET_VENDOR_SUN=y ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++# CONFIG_NIU is not set ++# CONFIG_NET_VENDOR_SYNOPSYS is not set ++CONFIG_NET_VENDOR_TEHUTI=y ++# CONFIG_TEHUTI is not set ++CONFIG_NET_VENDOR_TI=y ++# CONFIG_TI_CPSW_ALE is not set ++# CONFIG_TLAN is not set ++# CONFIG_NET_VENDOR_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_FDDI is not set ++# CONFIG_HIPPI is not set ++CONFIG_PHYLIB=y ++CONFIG_SWPHY=y ++ ++# ++# MDIO bus device drivers ++# ++# CONFIG_MDIO_BCM_IPROC is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_BCM_IPROC 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 ++CONFIG_MDIO_HISI_GEMAC=y ++# CONFIG_MDIO_OCTEON is not set ++# CONFIG_MDIO_THUNDER is not set ++# CONFIG_MDIO_XGENE 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_IPHETH is not set ++CONFIG_WLAN=y ++CONFIG_WLAN_VENDOR_ADMTEK=y ++CONFIG_WLAN_VENDOR_ATH=y ++# CONFIG_ATH_DEBUG is not set ++# CONFIG_ATH5K_PCI is not set ++CONFIG_WLAN_VENDOR_ATMEL=y ++CONFIG_WLAN_VENDOR_BROADCOM=y ++CONFIG_WLAN_VENDOR_CISCO=y ++CONFIG_WLAN_VENDOR_INTEL=y ++CONFIG_WLAN_VENDOR_INTERSIL=y ++# CONFIG_HOSTAP is not set ++# CONFIG_PRISM54 is not set ++CONFIG_WLAN_VENDOR_MARVELL=y ++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 ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_VMXNET3 is not set ++# CONFIG_ISDN is not set ++# CONFIG_NVM is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++CONFIG_INPUT_FF_MEMLESS=y ++# CONFIG_INPUT_POLLDEV is not set ++# CONFIG_INPUT_SPARSEKMAP is not set ++# CONFIG_INPUT_MATRIXKMAP is not set ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_CLPS711X is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_GOLDFISH_EVENTS is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_ST_KEYSCAN is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_SH_KEYSC is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++CONFIG_INPUT_JOYSTICK=y ++# CONFIG_JOYSTICK_ANALOG is not set ++# CONFIG_JOYSTICK_A3D is not set ++# CONFIG_JOYSTICK_ADI is not set ++# CONFIG_JOYSTICK_COBRA is not set ++# CONFIG_JOYSTICK_GF2K is not set ++# CONFIG_JOYSTICK_GRIP is not set ++# CONFIG_JOYSTICK_GRIP_MP is not set ++# CONFIG_JOYSTICK_GUILLEMOT is not set ++# CONFIG_JOYSTICK_INTERACT is not set ++# CONFIG_JOYSTICK_SIDEWINDER is not set ++# CONFIG_JOYSTICK_TMDC is not set ++# CONFIG_JOYSTICK_IFORCE is not set ++# CONFIG_JOYSTICK_WARRIOR is not set ++# CONFIG_JOYSTICK_MAGELLAN is not set ++# CONFIG_JOYSTICK_SPACEORB is not set ++# CONFIG_JOYSTICK_SPACEBALL is not set ++# CONFIG_JOYSTICK_STINGER is not set ++# CONFIG_JOYSTICK_TWIDJOY is not set ++# CONFIG_JOYSTICK_ZHENHUA is not set ++# CONFIG_JOYSTICK_AS5011 is not set ++# CONFIG_JOYSTICK_JOYDUMP is not set ++# CONFIG_JOYSTICK_XPAD is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_GP2A is not set ++# CONFIG_INPUT_GPIO_BEEPER is not set ++# CONFIG_INPUT_GPIO_TILT_POLLED is not set ++# CONFIG_INPUT_GPIO_DECODER is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INPUT_CM109 is not set ++# CONFIG_INPUT_REGULATOR_HAPTIC is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV260X_HAPTICS is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_INPUT_HISI_POWERKEY is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_SERIO_OLPC_APSP is not set ++# CONFIG_SERIO_SUN4I_PS2 is not set ++# CONFIG_USERIO is not set ++CONFIG_GAMEPORT=y ++# CONFIG_GAMEPORT_NS558 is not set ++# CONFIG_GAMEPORT_L4 is not set ++# CONFIG_GAMEPORT_EMU10K1 is not set ++# CONFIG_GAMEPORT_FM801 is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_NOZOMI is not set ++# CONFIG_N_GSM is not set ++# CONFIG_TRACE_SINK is not set ++CONFIG_DEVMEM=y ++CONFIG_DEVKMEM=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_ATMEL is not set ++# CONFIG_SERIAL_CLPS711X is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X is not set ++# CONFIG_SERIAL_IMX is not set ++# CONFIG_SERIAL_UARTLITE is not set ++# CONFIG_SERIAL_SH_SCI is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_JSM is not set ++# CONFIG_SERIAL_SCCNXP is not set ++# CONFIG_SERIAL_SC16IS7XX is not set ++# CONFIG_SERIAL_TIMBERDALE is not set ++# CONFIG_SERIAL_BCM63XX is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_IFX6X60 is not set ++# CONFIG_SERIAL_PCH_UART is not set ++# CONFIG_SERIAL_MXS_AUART is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++# CONFIG_SERIAL_MPS2_UART is not set ++# CONFIG_SERIAL_ARC is not set ++# CONFIG_SERIAL_RP2 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_SERIAL_MVEBU_UART 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_APPLICOM is not set ++ ++# ++# PCMCIA character devices ++# ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_DEVPORT=y ++# 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=y ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set ++# CONFIG_I2C_MUX_GPIO is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PCA954x is not set ++# CONFIG_I2C_MUX_PINCTRL is not set ++# CONFIG_I2C_MUX_REG is not set ++# CONFIG_I2C_DEMUX_PINCTRL 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 ++# ++ ++# ++# PC SMBus host controller drivers ++# ++# CONFIG_I2C_ALI1535 is not set ++# CONFIG_I2C_ALI1563 is not set ++# CONFIG_I2C_ALI15X3 is not set ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++# CONFIG_I2C_HIX5HD2 is not set ++# CONFIG_I2C_I801 is not set ++# CONFIG_I2C_ISCH is not set ++# CONFIG_I2C_PIIX4 is not set ++# CONFIG_I2C_NFORCE2 is not set ++# CONFIG_I2C_SIS5595 is not set ++# CONFIG_I2C_SIS630 is not set ++# CONFIG_I2C_SIS96X is not set ++# CONFIG_I2C_VIA is not set ++# CONFIG_I2C_VIAPRO is not set ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_AXXIA is not set ++# CONFIG_I2C_BCM_IPROC is not set ++# CONFIG_I2C_BRCMSTB is not set ++# CONFIG_I2C_CADENCE is not set ++# CONFIG_I2C_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_DESIGNWARE_PCI is not set ++# CONFIG_I2C_EFM32 is not set ++# CONFIG_I2C_EG20T is not set ++# CONFIG_I2C_EMEV2 is not set ++# CONFIG_I2C_GPIO is not set ++CONFIG_I2C_HIBVT=y ++# CONFIG_I2C_IMG is not set ++# CONFIG_I2C_JZ4780 is not set ++# CONFIG_I2C_LPC2K is not set ++# CONFIG_I2C_MESON is not set ++# CONFIG_I2C_MT65XX is not set ++# CONFIG_I2C_NOMADIK 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_RIIC is not set ++# CONFIG_I2C_RK3X is not set ++# CONFIG_I2C_SH_MOBILE is not set ++# CONFIG_I2C_SIMTEC is not set ++# CONFIG_I2C_SUN6I_P2WI is not set ++# CONFIG_I2C_UNIPHIER is not set ++# CONFIG_I2C_UNIPHIER_F is not set ++# CONFIG_I2C_VERSATILE is not set ++# CONFIG_I2C_THUNDERX is not set ++# CONFIG_I2C_XILINX is not set ++# CONFIG_I2C_XLP9XX is not set ++# CONFIG_I2C_RCAR 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_DMA_MSG_MIN_LEN=5 ++CONFIG_DMA_MSG_MAX_LEN=4090 ++# 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_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_ATMEL is not set ++# CONFIG_SPI_AXI_SPI_ENGINE is not set ++# CONFIG_SPI_BCM2835 is not set ++# CONFIG_SPI_BCM2835AUX is not set ++# CONFIG_SPI_BCM63XX is not set ++# CONFIG_SPI_BCM63XX_HSSPI is not set ++# CONFIG_SPI_BCM_QSPI is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_CLPS711X is not set ++# CONFIG_SPI_DESIGNWARE is not set ++# CONFIG_SPI_EP93XX is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_IMG_SPFI is not set ++# CONFIG_SPI_IMX is not set ++# CONFIG_SPI_JCORE is not set ++# CONFIG_SPI_LP8841_RTC is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_FSL_DSPI is not set ++# CONFIG_SPI_MESON_SPIFC is not set ++# CONFIG_SPI_MT65XX is not set ++# CONFIG_SPI_OC_TINY is not set ++# CONFIG_SPI_OMAP24XX is not set ++# CONFIG_SPI_TI_QSPI is not set ++# CONFIG_SPI_OMAP_100K is not set ++# CONFIG_SPI_ORION is not set ++# CONFIG_SPI_PIC32 is not set ++# CONFIG_SPI_PIC32_SQI is not set ++CONFIG_SPI_PL022=y ++# CONFIG_SPI_PXA2XX is not set ++# CONFIG_SPI_PXA2XX_PCI is not set ++# CONFIG_SPI_ROCKCHIP is not set ++# CONFIG_SPI_RSPI is not set ++# CONFIG_SPI_SC18IS602 is not set ++# CONFIG_SPI_SH_MSIOF is not set ++# CONFIG_SPI_SH is not set ++# CONFIG_SPI_SH_HSPI is not set ++# CONFIG_SPI_ST_SSC4 is not set ++# CONFIG_SPI_SUN4I is not set ++# CONFIG_SPI_SUN6I is not set ++# CONFIG_SPI_TEGRA114 is not set ++# CONFIG_SPI_TEGRA20_SFLASH is not set ++# CONFIG_SPI_TEGRA20_SLINK is not set ++# CONFIG_SPI_THUNDERX is not set ++# CONFIG_SPI_TOPCLIFF_PCH is not set ++# CONFIG_SPI_TXX9 is not set ++# CONFIG_SPI_XCOMM is not set ++# CONFIG_SPI_XILINX is not set ++# CONFIG_SPI_XLP is not set ++# CONFIG_SPI_XTENSA_XTFPGA is not set ++# CONFIG_SPI_ZYNQMP_GQSPI is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_PTP_1588_CLOCK_PCH is not set ++CONFIG_PINCTRL=y ++ ++# ++# Pin controllers ++# ++CONFIG_PINMUX=y ++CONFIG_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++# CONFIG_PINCTRL_AMD is not set ++# CONFIG_PINCTRL_LPC18XX is not set ++CONFIG_PINCTRL_SINGLE=y ++# CONFIG_PINCTRL_ASPEED_G4 is not set ++# CONFIG_PINCTRL_ASPEED_G5 is not set ++# CONFIG_PINCTRL_BCM281XX is not set ++# CONFIG_PINCTRL_IPROC_GPIO is not set ++# CONFIG_PINCTRL_CYGNUS_MUX is not set ++# CONFIG_PINCTRL_NSP_GPIO is not set ++# CONFIG_PINCTRL_NS2_MUX is not set ++# CONFIG_PINCTRL_NSP_MUX is not set ++# CONFIG_PINCTRL_BERLIN_BG2 is not set ++# CONFIG_PINCTRL_BERLIN_BG2CD is not set ++# CONFIG_PINCTRL_BERLIN_BG2Q is not set ++# CONFIG_PINCTRL_BERLIN_BG4CT is not set ++# CONFIG_PINCTRL_PXA25X is not set ++# CONFIG_PINCTRL_PXA27X is not set ++# CONFIG_PINCTRL_APQ8064 is not set ++# CONFIG_PINCTRL_APQ8084 is not set ++# CONFIG_PINCTRL_IPQ4019 is not set ++# CONFIG_PINCTRL_IPQ8064 is not set ++# CONFIG_PINCTRL_MSM8660 is not set ++# CONFIG_PINCTRL_MSM8960 is not set ++# CONFIG_PINCTRL_MDM9615 is not set ++# CONFIG_PINCTRL_MSM8X74 is not set ++# CONFIG_PINCTRL_MSM8916 is not set ++# CONFIG_PINCTRL_MSM8996 is not set ++# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set ++# CONFIG_PINCTRL_STM32F429 is not set ++# CONFIG_PINCTRL_STM32F746 is not set ++# CONFIG_PINCTRL_UNIPHIER is not set ++# CONFIG_PINCTRL_MT2701 is not set ++# CONFIG_PINCTRL_MT7623 is not set ++# CONFIG_PINCTRL_MT8135 is not set ++# CONFIG_PINCTRL_MT8127 is not set ++# CONFIG_PINCTRL_MT8173 is not set ++# CONFIG_PINCTRL_MT6397 is not set ++CONFIG_GPIOLIB=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_GENERIC=y ++ ++# ++# Memory mapped GPIO drivers ++# ++# CONFIG_GPIO_74XX_MMIO is not set ++# CONFIG_GPIO_ALTERA is not set ++# CONFIG_GPIO_ASPEED is not set ++# CONFIG_GPIO_ATH79 is not set ++# CONFIG_GPIO_BCM_KONA is not set ++# CONFIG_GPIO_BRCMSTB is not set ++# CONFIG_GPIO_CLPS711X is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_ETRAXFS is not set ++CONFIG_GPIO_GENERIC_PLATFORM=y ++# CONFIG_GPIO_GRGPIO is not set ++# CONFIG_GPIO_IOP is not set ++# CONFIG_GPIO_LPC18XX is not set ++# CONFIG_GPIO_MB86S7X is not set ++# CONFIG_GPIO_MOCKUP is not set ++# CONFIG_GPIO_MOXART is not set ++# CONFIG_GPIO_MPC8XXX is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_RCAR is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_TEGRA is not set ++# CONFIG_GPIO_TS4800 is not set ++# CONFIG_GPIO_VX855 is not set ++# CONFIG_GPIO_XGENE is not set ++# CONFIG_GPIO_XILINX is not set ++# CONFIG_GPIO_XLP 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 ++# ++ ++# ++# PCI GPIO expanders ++# ++# CONFIG_GPIO_AMD8111 is not set ++# CONFIG_GPIO_BT8XX is not set ++# CONFIG_GPIO_ML_IOH is not set ++# CONFIG_GPIO_PCH is not set ++# CONFIG_GPIO_RDC321X 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++# CONFIG_POWER_RESET_HISI is not set ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_XGENE is not set ++# CONFIG_POWER_RESET_KEYSTONE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_POWER_RESET_RMOBILE is not set ++# CONFIG_POWER_RESET_ZX is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_ACT8945A is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_MANAGER is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24257 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_BQ25890 is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_BATTERY_GOLDFISH is not set ++# CONFIG_CHARGER_RT9455 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_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_MX25_TSADC is not set ++# CONFIG_MFD_HI6421_PMIC is not set ++# CONFIG_MFD_HI655X_PMIC is not set ++CONFIG_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_HTC_I2CPLD is not set ++# CONFIG_LPC_ICH is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_INTEL_SOC_PMIC is not set ++# CONFIG_MFD_JANZ_CMODIO 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_RDC321X is not set ++# CONFIG_MFD_RTSX_PCI 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=y ++# 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_TIMBERDALE is not set ++# CONFIG_MFD_TC3589X is not set ++# CONFIG_MFD_TMIO is not set ++# CONFIG_MFD_VX855 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_MFD_STW481X is not set ++CONFIG_REGULATOR=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_LTC3676 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MT6311 is not set ++# CONFIG_REGULATOR_PBIAS is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_PV88060 is not set ++# CONFIG_REGULATOR_PV88080 is not set ++# CONFIG_REGULATOR_PV88090 is not set ++# CONFIG_REGULATOR_QCOM_SPMI is not set ++# CONFIG_REGULATOR_STW481X_VMMC is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=y ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=y ++CONFIG_VIDEO_V4L2=y ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=y ++CONFIG_VIDEOBUF2_MEMOPS=y ++CONFIG_VIDEOBUF2_VMALLOC=y ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++CONFIG_MEDIA_USB_SUPPORT=y ++ ++# ++# Webcam devices ++# ++CONFIG_USB_VIDEO_CLASS=y ++CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y ++CONFIG_USB_GSPCA=m ++# CONFIG_USB_M5602 is not set ++# CONFIG_USB_STV06XX is not set ++# CONFIG_USB_GL860 is not set ++# CONFIG_USB_GSPCA_BENQ is not set ++# CONFIG_USB_GSPCA_CONEX is not set ++# CONFIG_USB_GSPCA_CPIA1 is not set ++# CONFIG_USB_GSPCA_DTCS033 is not set ++# CONFIG_USB_GSPCA_ETOMS is not set ++# CONFIG_USB_GSPCA_FINEPIX is not set ++# CONFIG_USB_GSPCA_JEILINJ is not set ++# CONFIG_USB_GSPCA_JL2005BCD is not set ++# CONFIG_USB_GSPCA_KINECT is not set ++# CONFIG_USB_GSPCA_KONICA is not set ++# CONFIG_USB_GSPCA_MARS is not set ++# CONFIG_USB_GSPCA_MR97310A is not set ++# CONFIG_USB_GSPCA_NW80X is not set ++# CONFIG_USB_GSPCA_OV519 is not set ++# CONFIG_USB_GSPCA_OV534 is not set ++# CONFIG_USB_GSPCA_OV534_9 is not set ++# CONFIG_USB_GSPCA_PAC207 is not set ++# CONFIG_USB_GSPCA_PAC7302 is not set ++# CONFIG_USB_GSPCA_PAC7311 is not set ++# CONFIG_USB_GSPCA_SE401 is not set ++# CONFIG_USB_GSPCA_SN9C2028 is not set ++# CONFIG_USB_GSPCA_SN9C20X is not set ++# CONFIG_USB_GSPCA_SONIXB is not set ++# CONFIG_USB_GSPCA_SONIXJ is not set ++# CONFIG_USB_GSPCA_SPCA500 is not set ++# CONFIG_USB_GSPCA_SPCA501 is not set ++# CONFIG_USB_GSPCA_SPCA505 is not set ++# CONFIG_USB_GSPCA_SPCA506 is not set ++# CONFIG_USB_GSPCA_SPCA508 is not set ++# CONFIG_USB_GSPCA_SPCA561 is not set ++# CONFIG_USB_GSPCA_SPCA1528 is not set ++# CONFIG_USB_GSPCA_SQ905 is not set ++# CONFIG_USB_GSPCA_SQ905C is not set ++# CONFIG_USB_GSPCA_SQ930X is not set ++# CONFIG_USB_GSPCA_STK014 is not set ++# CONFIG_USB_GSPCA_STK1135 is not set ++# CONFIG_USB_GSPCA_STV0680 is not set ++# CONFIG_USB_GSPCA_SUNPLUS is not set ++# CONFIG_USB_GSPCA_T613 is not set ++# CONFIG_USB_GSPCA_TOPRO is not set ++# CONFIG_USB_GSPCA_TOUPTEK is not set ++# CONFIG_USB_GSPCA_TV8532 is not set ++# CONFIG_USB_GSPCA_VC032X is not set ++# CONFIG_USB_GSPCA_VICAM is not set ++# CONFIG_USB_GSPCA_XIRLINK_CIT is not set ++# CONFIG_USB_GSPCA_ZC3XX is not set ++# CONFIG_USB_PWC is not set ++# CONFIG_VIDEO_CPIA2 is not set ++# CONFIG_USB_ZR364XX is not set ++# CONFIG_USB_STKWEBCAM is not set ++# CONFIG_USB_S2255 is not set ++ ++# ++# Webcam, TV (analog/digital) USB devices ++# ++# CONFIG_VIDEO_EM28XX is not set ++# CONFIG_MEDIA_PCI_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, spi, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# I2C Encoders, decoders, sensors and other helper chips ++# ++ ++# ++# Audio decoders, processors and mixers ++# ++# CONFIG_VIDEO_TVAUDIO is not set ++# CONFIG_VIDEO_TDA7432 is not set ++# CONFIG_VIDEO_TDA9840 is not set ++# CONFIG_VIDEO_TEA6415C is not set ++# CONFIG_VIDEO_TEA6420 is not set ++# CONFIG_VIDEO_MSP3400 is not set ++# CONFIG_VIDEO_CS3308 is not set ++# CONFIG_VIDEO_CS5345 is not set ++# CONFIG_VIDEO_CS53L32A is not set ++# CONFIG_VIDEO_TLV320AIC23B is not set ++# CONFIG_VIDEO_UDA1342 is not set ++# CONFIG_VIDEO_WM8775 is not set ++# CONFIG_VIDEO_WM8739 is not set ++# CONFIG_VIDEO_VP27SMPX is not set ++# CONFIG_VIDEO_SONY_BTF_MPX is not set ++ ++# ++# RDS decoders ++# ++# CONFIG_VIDEO_SAA6588 is not set ++ ++# ++# Video decoders ++# ++# CONFIG_VIDEO_ADV7183 is not set ++# CONFIG_VIDEO_BT819 is not set ++# CONFIG_VIDEO_BT856 is not set ++# CONFIG_VIDEO_BT866 is not set ++# CONFIG_VIDEO_KS0127 is not set ++# CONFIG_VIDEO_ML86V7667 is not set ++# CONFIG_VIDEO_SAA7110 is not set ++# CONFIG_VIDEO_SAA711X is not set ++# CONFIG_VIDEO_TVP514X is not set ++# CONFIG_VIDEO_TVP5150 is not set ++# CONFIG_VIDEO_TVP7002 is not set ++# CONFIG_VIDEO_TW2804 is not set ++# CONFIG_VIDEO_TW9903 is not set ++# CONFIG_VIDEO_TW9906 is not set ++# CONFIG_VIDEO_VPX3220 is not set ++ ++# ++# Video and audio decoders ++# ++# CONFIG_VIDEO_SAA717X is not set ++# CONFIG_VIDEO_CX25840 is not set ++ ++# ++# Video encoders ++# ++# CONFIG_VIDEO_SAA7127 is not set ++# CONFIG_VIDEO_SAA7185 is not set ++# CONFIG_VIDEO_ADV7170 is not set ++# CONFIG_VIDEO_ADV7175 is not set ++# CONFIG_VIDEO_ADV7343 is not set ++# CONFIG_VIDEO_ADV7393 is not set ++# CONFIG_VIDEO_AK881X is not set ++# CONFIG_VIDEO_THS8200 is not set ++ ++# ++# Camera sensor devices ++# ++# CONFIG_VIDEO_OV2659 is not set ++# CONFIG_VIDEO_OV7640 is not set ++# CONFIG_VIDEO_OV7670 is not set ++# CONFIG_VIDEO_VS6624 is not set ++# CONFIG_VIDEO_MT9M111 is not set ++# CONFIG_VIDEO_MT9V011 is not set ++# CONFIG_VIDEO_SR030PC30 is not set ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++# CONFIG_VIDEO_UPD64031A is not set ++# CONFIG_VIDEO_UPD64083 is not set ++ ++# ++# Audio/Video compression chips ++# ++# CONFIG_VIDEO_SAA6752HS is not set ++ ++# ++# Miscellaneous helper chips ++# ++# CONFIG_VIDEO_THS7303 is not set ++# CONFIG_VIDEO_M52790 is not set ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# SPI helper chips ++# ++ ++# ++# Customise DVB Frontends ++# ++# CONFIG_DVB_AU8522_V4L is not set ++# CONFIG_DVB_TUNER_DIB0070 is not set ++# CONFIG_DVB_TUNER_DIB0090 is not set ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++CONFIG_VGA_ARB=y ++CONFIG_VGA_ARB_MAX_GPUS=16 ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_CIRRUS is not set ++# CONFIG_FB_PM2 is not set ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CLPS711X is not set ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_NVIDIA is not set ++# CONFIG_FB_RIVA is not set ++# CONFIG_FB_I740 is not set ++# CONFIG_FB_MATROX is not set ++# CONFIG_FB_RADEON is not set ++# CONFIG_FB_ATY128 is not set ++# CONFIG_FB_ATY is not set ++# CONFIG_FB_S3 is not set ++# CONFIG_FB_SAVAGE is not set ++# CONFIG_FB_SIS is not set ++# CONFIG_FB_NEOMAGIC is not set ++# CONFIG_FB_KYRO is not set ++# CONFIG_FB_3DFX is not set ++# CONFIG_FB_VOODOO1 is not set ++# CONFIG_FB_VT8623 is not set ++# CONFIG_FB_TRIDENT is not set ++# CONFIG_FB_ARK is not set ++# CONFIG_FB_PM3 is not set ++# CONFIG_FB_CARMINE is not set ++# CONFIG_FB_TMIO is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_GOLDFISH is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_MB862XX is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_FB_SM712 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++CONFIG_DUMMY_CONSOLE_COLUMNS=80 ++CONFIG_DUMMY_CONSOLE_ROWS=25 ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++# CONFIG_HID_BETOP_FF is not set ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# 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 is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PCI=y ++CONFIG_USB_XHCI_PLATFORM=y ++# CONFIG_USB_XHCI_MTK is not set ++# CONFIG_USB_XHCI_MVEBU is not set ++# CONFIG_USB_XHCI_RCAR 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_UHCI_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 ++# CONFIG_USB_RENESAS_USBHS is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++# CONFIG_USB_WDM is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++# CONFIG_USBIP_CORE is not set ++# CONFIG_USB_MUSB_HDRC is not set ++CONFIG_USB_DWC3=y ++# CONFIG_USB_DWC3_HOST is not set ++CONFIG_USB_DWC3_GADGET=y ++# CONFIG_USB_DWC3_DUAL_ROLE is not set ++ ++# ++# Platform Glue Driver Support ++# ++CONFIG_USB_DWC3_EXYNOS=y ++CONFIG_USB_DWC3_PCI=y ++CONFIG_USB_DWC3_KEYSTONE=y ++CONFIG_USB_DWC3_OF_SIMPLE=y ++# CONFIG_USB_DWC2 is not set ++# CONFIG_USB_CHIPIDEA 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++# CONFIG_USB_GADGET_DEBUG_FS is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_RENESAS_USB3 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_BDC_UDC is not set ++# CONFIG_USB_AMD5536UDC is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_NET2280 is not set ++# CONFIG_USB_GOKU is not set ++# CONFIG_USB_EG20T is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_MASS_STORAGE=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM 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_ARMMMCI is not set ++CONFIG_MMC_SDHCI=y ++# CONFIG_MMC_SDHCI_PCI is not set ++CONFIG_MMC_SDHCI_PLTFM=y ++# CONFIG_MMC_SDHCI_OF_ARASAN is not set ++# CONFIG_MMC_SDHCI_OF_AT91 is not set ++CONFIG_MMC_SDHCI_HISI=y ++# CONFIG_MMC_SDHCI_PXAV3 is not set ++# CONFIG_MMC_SDHCI_PXAV2 is not set ++# CONFIG_MMC_SDHCI_F_SDH30 is not set ++# CONFIG_MMC_SDHCI_IPROC is not set ++# CONFIG_MMC_OMAP_HS is not set ++# CONFIG_MMC_TIFM_SD is not set ++# CONFIG_MMC_GOLDFISH is not set ++# CONFIG_MMC_SPI is not set ++# CONFIG_MMC_SDHI is not set ++# CONFIG_MMC_CB710 is not set ++# CONFIG_MMC_VIA_SDMMC is not set ++# CONFIG_MMC_DW is not set ++# CONFIG_MMC_SH_MMCIF is not set ++# CONFIG_MMC_VUB300 is not set ++# CONFIG_MMC_USHC is not set ++# CONFIG_MMC_USDHI6ROL0 is not set ++# CONFIG_MMC_TOSHIBA_PCI 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_INFINIBAND is not set ++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=y ++ ++# ++# SPI and I2C RTC drivers ++# ++# CONFIG_RTC_DRV_DS3232 is not set ++# CONFIG_RTC_DRV_PCF2127 is not set ++# CONFIG_RTC_DRV_RV3029C2 is not set ++ ++# ++# Platform RTC drivers ++# ++CONFIG_RTC_DRV_HIBVT=y ++# 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_SPEAR is not set ++# CONFIG_RTC_DRV_NUC900 is not set ++# CONFIG_RTC_DRV_ZYNQMP is not set ++ ++# ++# on-CPU RTC drivers ++# ++# CONFIG_RTC_DRV_ASM9260 is not set ++# CONFIG_RTC_DRV_DAVINCI is not set ++# CONFIG_RTC_DRV_DIGICOLOR is not set ++# CONFIG_RTC_DRV_OMAP is not set ++# CONFIG_RTC_DRV_S3C is not set ++# CONFIG_RTC_DRV_EP93XX is not set ++# CONFIG_RTC_DRV_VR41XX is not set ++# CONFIG_RTC_DRV_PL030 is not set ++# CONFIG_RTC_DRV_PL031 is not set ++# CONFIG_RTC_DRV_AT32AP700X is not set ++# CONFIG_RTC_DRV_AT91RM9200 is not set ++# CONFIG_RTC_DRV_AT91SAM9 is not set ++# CONFIG_RTC_DRV_GENERIC is not set ++# CONFIG_RTC_DRV_VT8500 is not set ++# CONFIG_RTC_DRV_SUNXI is not set ++# CONFIG_RTC_DRV_MV is not set ++# CONFIG_RTC_DRV_ARMADA38X is not set ++# CONFIG_RTC_DRV_GEMINI is not set ++# CONFIG_RTC_DRV_COH901331 is not set ++# CONFIG_RTC_DRV_STMP is not set ++# CONFIG_RTC_DRV_JZ4740 is not set ++# CONFIG_RTC_DRV_LPC24XX is not set ++# CONFIG_RTC_DRV_LPC32XX is not set ++# CONFIG_RTC_DRV_PM8XXX is not set ++# CONFIG_RTC_DRV_TEGRA is not set ++# CONFIG_RTC_DRV_SNVS is not set ++# CONFIG_RTC_DRV_MOXART is not set ++# CONFIG_RTC_DRV_MT6397 is not set ++# CONFIG_RTC_DRV_XGENE is not set ++ ++# ++# HID Sensor RTC drivers ++# ++# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set ++CONFIG_DMADEVICES=y ++# CONFIG_DMADEVICES_DEBUG is not set ++ ++# ++# DMA Devices ++# ++CONFIG_DMA_ENGINE=y ++CONFIG_DMA_VIRTUAL_CHANNELS=y ++CONFIG_DMA_OF=y ++# CONFIG_AMBA_PL08X is not set ++# CONFIG_AXI_DMAC is not set ++# CONFIG_COH901318 is not set ++# CONFIG_DMA_JZ4740 is not set ++# CONFIG_DMA_JZ4780 is not set ++# CONFIG_DMA_OMAP is not set ++# CONFIG_DMA_SA11X0 is not set ++# CONFIG_DMA_SUN6I is not set ++# CONFIG_EP93XX_DMA is not set ++# CONFIG_FSL_EDMA is not set ++# CONFIG_IMG_MDC_DMA is not set ++# CONFIG_INTEL_IDMA64 is not set ++# CONFIG_K3_DMA is not set ++# CONFIG_MMP_PDMA is not set ++# CONFIG_MMP_TDMA is not set ++# CONFIG_MV_XOR is not set ++# CONFIG_MV_XOR_V2 is not set ++# CONFIG_NBPFAXI_DMA is not set ++# CONFIG_PCH_DMA is not set ++# CONFIG_PL330_DMA is not set ++# CONFIG_STM32_DMA is not set ++# CONFIG_S3C24XX_DMAC is not set ++# CONFIG_TEGRA210_ADMA is not set ++# CONFIG_TIMB_DMA is not set ++# CONFIG_TI_EDMA is not set ++# CONFIG_XGENE_DMA is not set ++# CONFIG_XILINX_DMA is not set ++# CONFIG_XILINX_ZYNQMP_DMA is not set ++# CONFIG_ZX_DMA is not set ++CONFIG_HIEDMACV310=y ++# CONFIG_QCOM_HIDMA_MGMT is not set ++# CONFIG_QCOM_HIDMA is not set ++# CONFIG_DW_DMAC is not set ++# CONFIG_DW_DMAC_PCI is not set ++CONFIG_RENESAS_DMA=y ++CONFIG_SH_DMAE_BASE=y ++# CONFIG_SH_DMAE is not set ++# CONFIG_RCAR_DMAC is not set ++# CONFIG_RENESAS_USB_DMAC is not set ++# CONFIG_SUDMAC 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_PCI is not set ++# CONFIG_VIRTIO_MMIO is not set ++ ++# ++# Microsoft Hyper-V guest support ++# ++CONFIG_STAGING=y ++# CONFIG_COMEDI is not set ++# CONFIG_RTL8192U is not set ++# CONFIG_RTLLIB is not set ++# CONFIG_R8712U is not set ++# CONFIG_RTS5208 is not set ++# CONFIG_FB_SM750 is not set ++# CONFIG_FB_XGI is not set ++ ++# ++# Speakup console speech ++# ++# CONFIG_SPEAKUP is not set ++# CONFIG_STAGING_MEDIA is not set ++ ++# ++# Android ++# ++# CONFIG_ASHMEM is not set ++# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set ++CONFIG_ION=y ++# CONFIG_ION_TEST is not set ++# CONFIG_ION_DUMMY is not set ++# CONFIG_ION_OF is not set ++# CONFIG_STAGING_BOARD is not set ++# CONFIG_LTE_GDM724X is not set ++# CONFIG_MTD_SPINAND_MT29F is not set ++# CONFIG_LNET is not set ++# CONFIG_DGNC is not set ++# CONFIG_GS_FPGABOOT is not set ++# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set ++# CONFIG_FB_TFT is not set ++# CONFIG_FSL_MC_BUS is not set ++# CONFIG_MOST is not set ++# CONFIG_KS7010 is not set ++# CONFIG_GREYBUS 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_VERSATILE is not set ++# CONFIG_COMMON_CLK_SCPI is not set ++# 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_COMMON_CLK_AXI_CLKGEN is not set ++# CONFIG_CLK_QORIQ is not set ++# CONFIG_COMMON_CLK_XGENE is not set ++# CONFIG_COMMON_CLK_KEYSTONE is not set ++# CONFIG_COMMON_CLK_NXP is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++# CONFIG_COMMON_CLK_OXNAS is not set ++# CONFIG_CLK_BCM_63XX is not set ++# CONFIG_CLK_BCM_KONA is not set ++# CONFIG_COMMON_CLK_IPROC is not set ++# CONFIG_COMMON_CLK_HI3519 is not set ++# CONFIG_COMMON_CLK_HI3516A is not set ++# CONFIG_COMMON_CLK_HI3518EV20X is not set ++# CONFIG_COMMON_CLK_HI3536DV100 is not set ++CONFIG_COMMON_CLK_HI3559AV100=y ++CONFIG_COMMON_CLK_HI3521A=y ++CONFIG_COMMON_CLK_HI3531A=y ++# CONFIG_COMMON_CLK_HI6220 is not set ++CONFIG_RESET_HISI=y ++# CONFIG_COMMON_CLK_MT8135 is not set ++# CONFIG_COMMON_CLK_MT8173 is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++# CONFIG_COMMON_CLK_SAMSUNG is not set ++# CONFIG_S3C2410_COMMON_CLK is not set ++# CONFIG_S3C2412_COMMON_CLK is not set ++# CONFIG_S3C2443_COMMON_CLK is not set ++# CONFIG_SUNXI_CCU is not set ++# CONFIG_COMMON_CLK_TI_ADPLL is not set ++# CONFIG_CLK_UNIPHIER is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++# CONFIG_BCM2835_TIMER is not set ++# CONFIG_BCM_KONA_TIMER is not set ++# CONFIG_DIGICOLOR_TIMER is not set ++# CONFIG_DW_APB_TIMER is not set ++# CONFIG_ROCKCHIP_TIMER is not set ++# CONFIG_MESON6_TIMER is not set ++# CONFIG_SUN4I_TIMER is not set ++# CONFIG_SUN5I_HSTIMER is not set ++# CONFIG_VT8500_TIMER is not set ++# CONFIG_CADENCE_TTC_TIMER is not set ++# CONFIG_ASM9260_TIMER is not set ++# CONFIG_CLKSRC_DBX500_PRCMU is not set ++# CONFIG_CLPS711X_TIMER is not set ++# CONFIG_ATLAS7_TIMER is not set ++# CONFIG_MOXART_TIMER is not set ++# CONFIG_MXS_TIMER is not set ++# CONFIG_PRIMA2_TIMER is not set ++# CONFIG_NSPIRE_TIMER is not set ++# CONFIG_KEYSTONE_TIMER is not set ++# CONFIG_INTEGRATOR_AP_TIMER is not set ++# CONFIG_CLKSRC_PISTACHIO is not set ++# CONFIG_CLKSRC_TI_32K is not set ++# CONFIG_CLKSRC_MPS2 is not set ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set ++CONFIG_FSL_ERRATUM_A008585=y ++CONFIG_ARM_TIMER_SP804=y ++# CONFIG_TIMER_HISP804 is not set ++# CONFIG_ARMV7M_SYSTICK is not set ++# CONFIG_ATMEL_PIT is not set ++# CONFIG_ATMEL_ST is not set ++# CONFIG_CLKSRC_EXYNOS_MCT is not set ++# CONFIG_CLKSRC_SAMSUNG_PWM is not set ++# CONFIG_FSL_FTM_TIMER is not set ++# CONFIG_OXNAS_RPS_TIMER is not set ++# CONFIG_MTK_TIMER is not set ++# CONFIG_CLKSRC_JCORE_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_CLKSRC_VERSATILE is not set ++# CONFIG_CLKSRC_PXA is not set ++# CONFIG_H8300_TMR8 is not set ++# CONFIG_H8300_TMR16 is not set ++# CONFIG_H8300_TPU is not set ++# CONFIG_CLKSRC_ST_LPC 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_MTK_INFRACFG is not set ++# CONFIG_MTK_SCPSYS is not set ++# CONFIG_ROCKCHIP_PM_DOMAINS is not set ++# CONFIG_SOC_SAMSUNG is not set ++# CONFIG_SUNXI_SRAM is not set ++# CONFIG_SOC_TI is not set ++# CONFIG_UX500_SOC_ID is not set ++CONFIG_PM_DEVFREQ=y ++ ++# ++# DEVFREQ Governors ++# ++CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y ++# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set ++# CONFIG_DEVFREQ_GOV_POWERSAVE is not set ++# CONFIG_DEVFREQ_GOV_USERSPACE is not set ++# CONFIG_DEVFREQ_GOV_PASSIVE is not set ++ ++# ++# DEVFREQ Drivers ++# ++# CONFIG_ARM_EXYNOS_BUS_DEVFREQ is not set ++# CONFIG_PM_DEVFREQ_EVENT is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_NTB is not set ++# CONFIG_VME_BUS is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++CONFIG_ARM_GIC_V2M=y ++CONFIG_ARM_GIC_V3=y ++CONFIG_ARM_GIC_V3_ITS=y ++CONFIG_HISILICON_IRQ_MBIGEN=y ++# CONFIG_JCORE_AIC is not set ++# CONFIG_TS4800_IRQ is not set ++CONFIG_PARTITION_PERCPU=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_UNIPHIER is not set ++# CONFIG_RESET_ZYNQ is not set ++CONFIG_COMMON_RESET_HI6220=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_PHY_BCM_NS_USB2 is not set ++# CONFIG_PHY_BCM_NS_USB3 is not set ++CONFIG_ARMADA375_USBCLUSTER_PHY=y ++# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set ++# CONFIG_PHY_LPC18XX_USB_OTG is not set ++# CONFIG_PHY_PXA_28NM_HSIC is not set ++# CONFIG_PHY_PXA_28NM_USB2 is not set ++# CONFIG_OMAP_CONTROL_PHY is not set ++# CONFIG_PHY_EXYNOS_DP_VIDEO is not set ++# CONFIG_BCM_KONA_USB2_PHY is not set ++# CONFIG_PHY_HI6220_USB is not set ++# CONFIG_PHY_ROCKCHIP_INNO_USB2 is not set ++# CONFIG_PHY_ROCKCHIP_PCIE is not set ++# CONFIG_PHY_ROCKCHIP_TYPEC is not set ++# CONFIG_PHY_ST_SPEAR1310_MIPHY is not set ++# CONFIG_PHY_ST_SPEAR1340_MIPHY is not set ++# CONFIG_PHY_XGENE is not set ++# CONFIG_PHY_STIH407_USB is not set ++# CONFIG_PHY_BRCM_SATA is not set ++# CONFIG_PHY_CYGNUS_PCIE is not set ++CONFIG_HISI_PHY_USB3=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++ ++# ++# Performance monitor support ++# ++CONFIG_ARM_PMU=y ++# CONFIG_RAS is not set ++# CONFIG_THUNDERBOLT is not set ++ ++# ++# Android ++# ++CONFIG_ANDROID=y ++# CONFIG_ANDROID_BINDER_IPC is not set ++# CONFIG_LIBNVDIMM 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 ++# CONFIG_HI_DMAC is not set ++# CONFIG_HIVDMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE is not set ++ ++# ++# Firmware Drivers ++# ++CONFIG_ARM_PSCI_FW=y ++CONFIG_ARM_SCPI_POWER_DOMAIN=y ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++# CONFIG_MESON_SM is not set ++# CONFIG_ACPI is not set ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++CONFIG_FS_IOMAP=y ++CONFIG_EXT2_FS=y ++CONFIG_EXT2_FS_XATTR=y ++CONFIG_EXT2_FS_POSIX_ACL=y ++CONFIG_EXT2_FS_SECURITY=y ++CONFIG_EXT3_FS=y ++CONFIG_EXT3_FS_POSIX_ACL=y ++CONFIG_EXT3_FS_SECURITY=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_CHECK=y ++CONFIG_REISERFS_PROC_INFO=y ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_DEBUG=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++# CONFIG_XFS_WARN is not set ++# CONFIG_XFS_DEBUG is not set ++# CONFIG_GFS2_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_DAX is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_EXPORTFS=m ++# 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=y ++# CONFIG_QUOTA_NETLINK_INTERFACE is not set ++CONFIG_PRINT_QUOTA_WARNING=y ++# CONFIG_QUOTA_DEBUG is not set ++CONFIG_QUOTA_TREE=m ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_QUOTACTL=y ++CONFIG_AUTOFS4_FS=m ++CONFIG_FUSE_FS=y ++# CONFIG_CUSE is not set ++# CONFIG_OVERLAY_FS is not set ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=y ++# CONFIG_JOLIET is not set ++# CONFIG_ZISOFS is not set ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++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_KCORE is not set ++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=y ++CONFIG_TMPFS_XATTR=y ++# CONFIG_HUGETLBFS is not set ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_ARCH_HAS_GIGANTIC_PAGE=y ++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_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++CONFIG_SQUASHFS=y ++CONFIG_SQUASHFS_FILE_CACHE=y ++# CONFIG_SQUASHFS_FILE_DIRECT is not set ++CONFIG_SQUASHFS_DECOMP_SINGLE=y ++# CONFIG_SQUASHFS_DECOMP_MULTI is not set ++# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set ++# CONFIG_SQUASHFS_XATTR is not set ++CONFIG_SQUASHFS_ZLIB=y ++# CONFIG_SQUASHFS_LZ4 is not set ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set ++# CONFIG_SQUASHFS_EMBEDDED is not set ++CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 ++# 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFSD is not set ++CONFIG_GRACE_PERIOD=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=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=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=y ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++# 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 ++# CONFIG_VIRTUALIZATION is not set ++ ++# ++# Kernel hacking ++# ++ ++# ++# printk and dmesg options ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++# 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=2048 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++CONFIG_ARCH_WANT_FRAME_POINTERS=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++CONFIG_HAVE_ARCH_KASAN=y ++# CONFIG_KASAN is not set ++CONFIG_ARCH_HAS_KCOV=y ++# CONFIG_KCOV is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++CONFIG_LOCKUP_DETECTOR=y ++# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set ++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 ++# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set ++CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 ++# CONFIG_WQ_WATCHDOG is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++CONFIG_SCHED_INFO=y ++CONFIG_SCHEDSTATS=y ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_HAVE_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_PROVE_RCU is not set ++CONFIG_SPARSE_RCU_POINTER=y ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=21 ++CONFIG_RCU_TRACE=y ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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_TRACE_CLOCK=y ++CONFIG_TRACING_SUPPORT=y ++# CONFIG_FTRACE is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_LKDTM is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=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_ARM64_PTDUMP is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_DEBUG_ALIGN_RODATA is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS 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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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 is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++CONFIG_CRYPTO_NULL=m ++CONFIG_CRYPTO_NULL2=y ++# CONFIG_CRYPTO_PCRYPT is not set ++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=m ++# CONFIG_CRYPTO_GCM is not set ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# 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=y ++CONFIG_CRYPTO_HMAC=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# 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 is not set ++# 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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_CRYPTO_DEV_S5P is not set ++# CONFIG_CRYPTO_DEV_ATMEL_AES is not set ++# CONFIG_CRYPTO_DEV_CCP is not set ++# CONFIG_CRYPTO_DEV_QCE is not set ++# CONFIG_CRYPTO_DEV_IMGTEC_HASH is not set ++ ++# ++# Certificates for signature checking ++# ++# CONFIG_ARM64_CRYPTO is not set ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++CONFIG_HAVE_ARCH_BITREVERSE=y ++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=y ++CONFIG_CRC16=y ++# CONFIG_CRC_T10DIF is not set ++CONFIG_CRC_ITU_T=y ++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=m ++# CONFIG_CRC8 is not set ++CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y ++# CONFIG_RANDOM32_SELFTEST is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=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_GZIP=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_NLATTR=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=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y +diff --git a/arch/arm64/configs/hi3559av100_arm64_big_little_emmc_defconfig b/arch/arm64/configs/hi3559av100_arm64_big_little_emmc_defconfig +new file mode 100644 +index 0000000..738ac7e +--- /dev/null ++++ b/arch/arm64/configs/hi3559av100_arm64_big_little_emmc_defconfig +@@ -0,0 +1,3852 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm64 4.9.37 Kernel Configuration ++# ++CONFIG_ARM64=y ++CONFIG_64BIT=y ++CONFIG_ARCH_PHYS_ADDR_T_64BIT=y ++CONFIG_MMU=y ++CONFIG_DEBUG_RODATA=y ++CONFIG_ARM64_PAGE_SHIFT=12 ++CONFIG_ARM64_CONT_SHIFT=4 ++CONFIG_ARCH_MMAP_RND_BITS_MIN=18 ++CONFIG_ARCH_MMAP_RND_BITS_MAX=24 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=y ++CONFIG_GENERIC_BUG=y ++CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CSUM=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_ZONE_DMA=y ++CONFIG_HAVE_GENERIC_RCU_GUP=y ++CONFIG_ARCH_DMA_ADDR_T_64BIT=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_NEED_SG_DMA_LENGTH=y ++CONFIG_SMP=y ++CONFIG_SWIOTLB=y ++CONFIG_IOMMU_HELPER=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_FIX_EARLYCON_MEM=y ++CONFIG_PGTABLE_LEVELS=3 ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++CONFIG_COMPILE_TEST=y ++CONFIG_LOCALVERSION="" ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_GENERIC_IRQ_MIGRATION=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_GENERIC_MSI_IRQ=y ++CONFIG_GENERIC_MSI_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++# CONFIG_IRQ_DOMAIN_DEBUG is not set ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_HZ_PERIODIC=y ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NO_HZ_FULL 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_TREE_RCU=y ++# CONFIG_RCU_EXPERT is not set ++CONFIG_SRCU=y ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++CONFIG_TREE_RCU_TRACE=y ++# CONFIG_RCU_EXPEDITE_BOOT is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=14 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y ++# CONFIG_CGROUPS is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++CONFIG_RELAY=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++# CONFIG_RD_LZ4 is not set ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_SYSCTL_EXCEPTION_TRACE=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_ALL is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y ++CONFIG_BPF_SYSCALL=y ++CONFIG_SHMEM=y ++CONFIG_AIO=y ++CONFIG_ADVISE_SYSCALLS=y ++CONFIG_USERFAULTFD=y ++CONFIG_PCI_QUIRKS=y ++CONFIG_MEMBARRIER=y ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++ ++# ++# Kernel Performance Events And Counters ++# ++CONFIG_PERF_EVENTS=y ++# CONFIG_DEBUG_PERF_USE_VMALLOC is not set ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_SLAB_FREELIST_RANDOM is not set ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_SYSTEM_DATA_VERIFICATION is not set ++# CONFIG_PROFILING is not set ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL is not set ++# CONFIG_UPROBES is not set ++# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set ++CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=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_HW_BREAKPOINT=y ++CONFIG_HAVE_PERF_REGS=y ++CONFIG_HAVE_PERF_USER_STACK_DUMP=y ++CONFIG_HAVE_ARCH_JUMP_LABEL=y ++CONFIG_HAVE_RCU_TABLE_FREE=y ++CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y ++CONFIG_HAVE_CMPXCHG_LOCAL=y ++CONFIG_HAVE_CMPXCHG_DOUBLE=y ++CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y ++CONFIG_HAVE_ARCH_SECCOMP_FILTER=y ++CONFIG_HAVE_GCC_PLUGINS=y ++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_ARCH_TRANSPARENT_HUGEPAGE=y ++CONFIG_HAVE_ARCH_HUGE_VMAP=y ++CONFIG_MODULES_USE_ELF_RELA=y ++CONFIG_ARCH_HAS_ELF_RANDOMIZE=y ++CONFIG_HAVE_ARCH_MMAP_RND_BITS=y ++CONFIG_ARCH_MMAP_RND_BITS=18 ++CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 ++# CONFIG_HAVE_ARCH_HASH is not set ++# CONFIG_ISA_BUS_API is not set ++CONFIG_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_COMPAT_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_SLABINFO=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_MODULES_TREE_LOOKUP=y ++CONFIG_BLOCK=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++CONFIG_BLOCK_COMPAT=y ++CONFIG_BLK_MQ_PCI=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_LOCK_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# Platform selection ++# ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_BCM2835 is not set ++# CONFIG_ARCH_BCM_IPROC is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_BRCMSTB is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_LAYERSCAPE is not set ++# CONFIG_ARCH_LG1K is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++CONFIG_ARCH_HI3559AV100=y ++# CONFIG_ACCESS_M7_DEV is not set ++# CONFIG_ARCH_HISI_BVT_AMP is not set ++# CONFIG_ARCH_MEDIATEK is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SEATTLE is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_STRATIX10 is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_SPRD is not set ++# CONFIG_ARCH_THUNDER is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_VULCAN is not set ++# CONFIG_ARCH_XGENE is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQMP is not set ++ ++# ++# Bus support ++# ++CONFIG_PCI=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_PCI_DOMAINS_GENERIC=y ++CONFIG_PCI_SYSCALL=y ++CONFIG_PCIEPORTBUS=y ++# CONFIG_PCIEAER is not set ++# CONFIG_PCIEASPM is not set ++# CONFIG_PCIE_PME is not set ++# CONFIG_PCIE_DPC is not set ++# CONFIG_PCIE_PTM is not set ++CONFIG_PCI_BUS_ADDR_T_64BIT=y ++CONFIG_PCI_MSI=y ++CONFIG_PCI_MSI_IRQ_DOMAIN=y ++# CONFIG_PCI_DEBUG is not set ++# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set ++# CONFIG_PCI_STUB is not set ++# CONFIG_PCI_IOV is not set ++# CONFIG_PCI_PRI is not set ++# CONFIG_PCI_PASID is not set ++# CONFIG_HOTPLUG_PCI is not set ++ ++# ++# PCI host controller drivers ++# ++# CONFIG_PCIE_DW_PLAT is not set ++# CONFIG_PCI_HOST_GENERIC is not set ++# CONFIG_PCI_HISI is not set ++# CONFIG_PCI_HOST_THUNDER_PEM is not set ++# CONFIG_PCI_HOST_THUNDER_ECAM is not set ++# CONFIG_HIPCIE is not set ++ ++# ++# Kernel Features ++# ++ ++# ++# ARM errata workarounds via the alternatives framework ++# ++CONFIG_ARM64_ERRATUM_826319=y ++CONFIG_ARM64_ERRATUM_827319=y ++CONFIG_ARM64_ERRATUM_824069=y ++CONFIG_ARM64_ERRATUM_819472=y ++CONFIG_ARM64_ERRATUM_832075=y ++CONFIG_ARM64_ERRATUM_845719=y ++CONFIG_ARM64_ERRATUM_843419=y ++CONFIG_CAVIUM_ERRATUM_22375=y ++CONFIG_CAVIUM_ERRATUM_23154=y ++CONFIG_CAVIUM_ERRATUM_27456=y ++CONFIG_QCOM_QDF2400_ERRATUM_0065=y ++CONFIG_ARM64_4K_PAGES=y ++# CONFIG_ARM64_16K_PAGES is not set ++# CONFIG_ARM64_64K_PAGES is not set ++CONFIG_ARM64_VA_BITS_39=y ++# CONFIG_ARM64_VA_BITS_48 is not set ++CONFIG_ARM64_VA_BITS=39 ++# CONFIG_CPU_BIG_ENDIAN is not set ++CONFIG_SCHED_MC=y ++# CONFIG_SCHED_SMT is not set ++CONFIG_NR_CPUS=64 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_NUMA is not set ++CONFIG_PREEMPT_NONE=y ++# CONFIG_PREEMPT_VOLUNTARY is not set ++# CONFIG_PREEMPT is not set ++# CONFIG_HZ_100 is not set ++# CONFIG_HZ_250 is not set ++# CONFIG_HZ_300 is not set ++CONFIG_HZ_1000=y ++CONFIG_HZ=1000 ++# CONFIG_SCHED_HRTICK is not set ++CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y ++CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y ++CONFIG_ARCH_SPARSEMEM_ENABLE=y ++CONFIG_ARCH_SPARSEMEM_DEFAULT=y ++CONFIG_ARCH_SELECT_MEMORY_MODEL=y ++CONFIG_HAVE_ARCH_PFN_VALID=y ++CONFIG_HW_PERF_EVENTS=y ++CONFIG_SYS_SUPPORTS_HUGETLBFS=y ++CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y ++CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_SPARSEMEM_MANUAL=y ++CONFIG_SPARSEMEM=y ++CONFIG_HAVE_MEMORY_PRESENT=y ++CONFIG_SPARSEMEM_EXTREME=y ++CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y ++CONFIG_SPARSEMEM_VMEMMAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=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=y ++CONFIG_BOUNCE=y ++CONFIG_KSM=y ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# CONFIG_TRANSPARENT_HUGEPAGE is not set ++# CONFIG_CLEANCACHE is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++# CONFIG_CMA_DEBUGFS is not set ++CONFIG_CMA_AREAS=7 ++# 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_FRAME_VECTOR=y ++# CONFIG_SECCOMP is not set ++# CONFIG_PARAVIRT is not set ++# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set ++# CONFIG_KEXEC is not set ++# CONFIG_XEN is not set ++CONFIG_FORCE_MAX_ZONEORDER=11 ++# CONFIG_ARMV8_DEPRECATED is not set ++ ++# ++# ARMv8.1 architectural features ++# ++CONFIG_ARM64_HW_AFDBM=y ++CONFIG_ARM64_PAN=y ++# CONFIG_ARM64_LSE_ATOMICS is not set ++CONFIG_ARM64_VHE=y ++ ++# ++# ARMv8.2 architectural features ++# ++CONFIG_ARM64_UAO=y ++CONFIG_ARM64_MODULE_CMODEL_LARGE=y ++# CONFIG_RANDOMIZE_BASE is not set ++ ++# ++# Boot options ++# ++CONFIG_CMDLINE="mem=128M console=ttyAMA0,115200 console=ttyMTD,blackbox" ++# CONFIG_CMDLINE_FORCE is not set ++# CONFIG_EFI is not set ++CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y ++CONFIG_IMG_GZ_DTB=y ++# CONFIG_IMG_DTB is not set ++CONFIG_BUILD_ARM64_APPENDED_KERNEL_IMAGE_NAME="Image.gz-dtb" ++CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES="hisilicon/hi3559av100-demb-emmc" ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_COMPAT_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++CONFIG_COMPAT=y ++CONFIG_SYSVIPC_COMPAT=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_SUSPEND_SKIP_SYNC is not set ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++CONFIG_PM_CLK=y ++CONFIG_PM_GENERIC_DOMAINS=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_PM_GENERIC_DOMAINS_SLEEP=y ++CONFIG_PM_GENERIC_DOMAINS_OF=y ++CONFIG_CPU_PM=y ++CONFIG_ARCH_HIBERNATION_POSSIBLE=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Idle ++# ++# CONFIG_CPU_IDLE is not set ++# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_ATTR_SET=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_STAT_DETAILS=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set ++ ++# ++# CPU frequency scaling drivers ++# ++# CONFIG_CPUFREQ_DT is not set ++# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++CONFIG_NET=y ++CONFIG_NET_INGRESS=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 is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++CONFIG_NET_IP_TUNNEL=m ++# 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=m ++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=y ++# CONFIG_IPV6_ROUTE_INFO 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_IPV6_ILA is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# 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=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++CONFIG_NETFILTER_INGRESS=y ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_DUP_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_DUP_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_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_QRTR is not set ++# CONFIG_NET_NCSI is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_SOCK_CGROUP_DATA is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_EBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER=y ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++# CONFIG_DEVTMPFS is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_GENERIC_CPU_AUTOPROBE=y ++CONFIG_REGMAP=y ++CONFIG_REGMAP_I2C=y ++CONFIG_REGMAP_SPI=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=4 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_ARM_CCI400_PMU is not set ++# CONFIG_ARM_CCI5xx_PMU is not set ++# CONFIG_ARM_CCN is not set ++# CONFIG_QCOM_EBI2 is not set ++# CONFIG_SIMPLE_PM_BUS 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 ++# CONFIG_MTD_BCM63XX_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_TS5500 is not set ++# CONFIG_MTD_INTEL_VR_NOR is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_DATAFLASH is not set ++# CONFIG_MTD_M25P80 is not set ++# 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=y ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOCG3 is not set ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_PCI is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_RICOH is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_VF610_NFC is not set ++# CONFIG_MTD_NAND_SH_FLCTL is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++CONFIG_MTD_SPI_NAND_HISI_BVT=y ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++CONFIG_MTD_SPI_NAND_HIFMC100=y ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# LPDDR & LPDDR2 PCM memory drivers ++# ++# CONFIG_MTD_LPDDR is not set ++CONFIG_MTD_SPI_NOR=y ++# CONFIG_MTD_MT81xx_NOR is not set ++# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set ++# CONFIG_SPI_FSL_QUADSPI is not set ++CONFIG_SPI_HISI_SFC=y ++# CONFIG_SPI_NXP_SPIFI is not set ++# CONFIG_MTD_SPI_IDS is not set ++# CONFIG_CLOSE_SPI_8PIN_4IO is not set ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++# CONFIG_MTD_UBI is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++# CONFIG_OF_UNITTEST is not set ++# CONFIG_OF_ALL_DTBS is not set ++CONFIG_OF_FLATTREE=y ++CONFIG_OF_EARLY_FLATTREE=y ++CONFIG_OF_ADDRESS=y ++CONFIG_OF_ADDRESS_PCI=y ++CONFIG_OF_IRQ=y ++CONFIG_OF_NET=y ++CONFIG_OF_MDIO=y ++CONFIG_OF_PCI=y ++CONFIG_OF_PCI_IRQ=y ++CONFIG_OF_RESERVED_MEM=y ++# CONFIG_OF_OVERLAY is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set ++# CONFIG_BLK_CPQ_CISS_DA is not set ++# CONFIG_BLK_DEV_DAC960 is not set ++# CONFIG_BLK_DEV_UMEM is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_SKD is not set ++# CONFIG_BLK_DEV_SX8 is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_BLK_DEV_RSXX is not set ++# CONFIG_BLK_DEV_NVME is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# CONFIG_SENSORS_LIS3LV02D is not set ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_DUMMY_IRQ is not set ++# CONFIG_PHANTOM is not set ++# CONFIG_INTEL_MID_PTI is not set ++# CONFIG_SGI_IOC4 is not set ++# CONFIG_TIFM_CORE is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ATMEL_SSC is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_HP_ILO is not set ++# CONFIG_QCOM_COINCELL 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_PCH_PHUB 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 ++# CONFIG_CB710_CORE 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_GENWQE is not set ++# 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=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_SCSI_CXGB3_ISCSI is not set ++# CONFIG_SCSI_CXGB4_ISCSI is not set ++# CONFIG_SCSI_BNX2_ISCSI is not set ++# CONFIG_BE2ISCSI is not set ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_HPSA is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_3W_SAS is not set ++# CONFIG_SCSI_ACARD is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX is not set ++# CONFIG_SCSI_AIC79XX is not set ++# CONFIG_SCSI_AIC94XX is not set ++# CONFIG_SCSI_HISI_SAS is not set ++# CONFIG_SCSI_MVSAS is not set ++# CONFIG_SCSI_MVUMI is not set ++# CONFIG_SCSI_ADVANSYS is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_SCSI_ESAS2R is not set ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++# CONFIG_SCSI_MPT3SAS is not set ++# CONFIG_SCSI_MPT2SAS is not set ++# CONFIG_SCSI_SMARTPQI is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_SCSI_HPTIOP is not set ++# CONFIG_SCSI_SNIC is not set ++# CONFIG_SCSI_DMX3191D is not set ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_IPS is not set ++# CONFIG_SCSI_INITIO is not set ++# CONFIG_SCSI_INIA100 is not set ++# CONFIG_SCSI_STEX is not set ++# CONFIG_SCSI_SYM53C8XX_2 is not set ++# CONFIG_SCSI_QLOGIC_1280 is not set ++# CONFIG_SCSI_QLA_ISCSI is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_AM53C974 is not set ++# CONFIG_SCSI_WD719X is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_PMCRAID is not set ++# CONFIG_SCSI_PM8001 is not set ++# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HAVE_PATA_PLATFORM=y ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++# CONFIG_FUSION is not set ++ ++# ++# IEEE 1394 (FireWire) support ++# ++# CONFIG_FIREWIRE is not set ++# CONFIG_FIREWIRE_NOSY is not set ++CONFIG_NETDEVICES=y ++CONFIG_NET_CORE=y ++# CONFIG_BONDING is not set ++# CONFIG_DUMMY is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC 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 ++# CONFIG_ARCNET is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++CONFIG_ETHERNET=y ++CONFIG_NET_VENDOR_3COM=y ++# CONFIG_VORTEX is not set ++# CONFIG_TYPHOON is not set ++CONFIG_NET_VENDOR_ADAPTEC=y ++# CONFIG_ADAPTEC_STARFIRE is not set ++CONFIG_NET_VENDOR_AGERE=y ++# CONFIG_ET131X is not set ++CONFIG_NET_VENDOR_ALTEON=y ++# CONFIG_ACENIC is not set ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_VENDOR_AMAZON is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC is not set ++CONFIG_NET_VENDOR_ATHEROS=y ++# CONFIG_ATL2 is not set ++# CONFIG_ATL1 is not set ++# CONFIG_ATL1E is not set ++# CONFIG_ATL1C is not set ++# CONFIG_ALX 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_BROCADE=y ++# CONFIG_BNA is not set ++# CONFIG_NET_CALXEDA_XGMAC is not set ++CONFIG_NET_VENDOR_CAVIUM=y ++# CONFIG_THUNDER_NIC_PF is not set ++# CONFIG_THUNDER_NIC_VF is not set ++# CONFIG_THUNDER_NIC_BGX is not set ++# CONFIG_THUNDER_NIC_RGX is not set ++# CONFIG_LIQUIDIO is not set ++CONFIG_NET_VENDOR_CHELSIO=y ++# CONFIG_CHELSIO_T1 is not set ++# CONFIG_CHELSIO_T3 is not set ++# CONFIG_CHELSIO_T4 is not set ++# CONFIG_CHELSIO_T4VF is not set ++CONFIG_NET_VENDOR_CISCO=y ++# CONFIG_ENIC is not set ++# CONFIG_CX_ECAT is not set ++# CONFIG_DNET is not set ++CONFIG_NET_VENDOR_DEC=y ++# CONFIG_NET_TULIP is not set ++CONFIG_NET_VENDOR_DLINK=y ++# CONFIG_DL2K is not set ++# CONFIG_SUNDANCE is not set ++CONFIG_NET_VENDOR_EMULEX=y ++# CONFIG_BE2NET is not set ++# CONFIG_NET_VENDOR_EZCHIP is not set ++CONFIG_NET_VENDOR_EXAR=y ++# CONFIG_S2IO is not set ++# CONFIG_VXGE is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DDR_64BIT=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++CONFIG_NET_VENDOR_HP=y ++# CONFIG_HP100 is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_JME is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++CONFIG_NET_VENDOR_MELLANOX=y ++# CONFIG_MLX4_EN is not set ++# CONFIG_MLX4_CORE is not set ++# CONFIG_MLX5_CORE is not set ++# CONFIG_MLXSW_CORE is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_MICROCHIP is not set ++CONFIG_NET_VENDOR_MYRI=y ++# CONFIG_MYRI10GE is not set ++# CONFIG_FEALNX is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NETRONOME is not set ++CONFIG_NET_VENDOR_NVIDIA=y ++# CONFIG_FORCEDETH is not set ++CONFIG_NET_VENDOR_OKI=y ++# CONFIG_PCH_GBE is not set ++# CONFIG_ETHOC is not set ++CONFIG_NET_PACKET_ENGINE=y ++# CONFIG_HAMACHI is not set ++# CONFIG_YELLOWFIN is not set ++CONFIG_NET_VENDOR_QLOGIC=y ++# CONFIG_QLA3XXX is not set ++# CONFIG_QLCNIC is not set ++# CONFIG_QLGE is not set ++# CONFIG_NETXEN_NIC is not set ++# CONFIG_QED is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++CONFIG_NET_VENDOR_REALTEK=y ++# CONFIG_8139CP is not set ++# CONFIG_8139TOO is not set ++# CONFIG_R8169 is not set ++# CONFIG_NET_VENDOR_RENESAS is not set ++CONFIG_NET_VENDOR_RDC=y ++# CONFIG_R6040 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_SILAN=y ++# CONFIG_SC92031 is not set ++CONFIG_NET_VENDOR_SIS=y ++# CONFIG_SIS900 is not set ++# CONFIG_SIS190 is not set ++# CONFIG_SFC is not set ++# CONFIG_NET_VENDOR_SMSC is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++CONFIG_NET_VENDOR_SUN=y ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++# CONFIG_NIU is not set ++# CONFIG_NET_VENDOR_SYNOPSYS is not set ++CONFIG_NET_VENDOR_TEHUTI=y ++# CONFIG_TEHUTI is not set ++CONFIG_NET_VENDOR_TI=y ++# CONFIG_TI_CPSW_ALE is not set ++# CONFIG_TLAN is not set ++# CONFIG_NET_VENDOR_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_FDDI is not set ++# CONFIG_HIPPI is not set ++CONFIG_PHYLIB=y ++CONFIG_SWPHY=y ++ ++# ++# MDIO bus device drivers ++# ++# CONFIG_MDIO_BCM_IPROC is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_BCM_IPROC 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 ++CONFIG_MDIO_HISI_GEMAC=y ++# CONFIG_MDIO_OCTEON is not set ++# CONFIG_MDIO_THUNDER is not set ++# CONFIG_MDIO_XGENE 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_IPHETH is not set ++CONFIG_WLAN=y ++CONFIG_WLAN_VENDOR_ADMTEK=y ++CONFIG_WLAN_VENDOR_ATH=y ++# CONFIG_ATH_DEBUG is not set ++# CONFIG_ATH5K_PCI is not set ++CONFIG_WLAN_VENDOR_ATMEL=y ++CONFIG_WLAN_VENDOR_BROADCOM=y ++CONFIG_WLAN_VENDOR_CISCO=y ++CONFIG_WLAN_VENDOR_INTEL=y ++CONFIG_WLAN_VENDOR_INTERSIL=y ++# CONFIG_HOSTAP is not set ++# CONFIG_PRISM54 is not set ++CONFIG_WLAN_VENDOR_MARVELL=y ++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 ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_VMXNET3 is not set ++# CONFIG_ISDN is not set ++# CONFIG_NVM is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++CONFIG_INPUT_FF_MEMLESS=y ++# CONFIG_INPUT_POLLDEV is not set ++# CONFIG_INPUT_SPARSEKMAP is not set ++# CONFIG_INPUT_MATRIXKMAP is not set ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_CLPS711X is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_GOLDFISH_EVENTS is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_ST_KEYSCAN is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_SH_KEYSC is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++CONFIG_INPUT_JOYSTICK=y ++# CONFIG_JOYSTICK_ANALOG is not set ++# CONFIG_JOYSTICK_A3D is not set ++# CONFIG_JOYSTICK_ADI is not set ++# CONFIG_JOYSTICK_COBRA is not set ++# CONFIG_JOYSTICK_GF2K is not set ++# CONFIG_JOYSTICK_GRIP is not set ++# CONFIG_JOYSTICK_GRIP_MP is not set ++# CONFIG_JOYSTICK_GUILLEMOT is not set ++# CONFIG_JOYSTICK_INTERACT is not set ++# CONFIG_JOYSTICK_SIDEWINDER is not set ++# CONFIG_JOYSTICK_TMDC is not set ++# CONFIG_JOYSTICK_IFORCE is not set ++# CONFIG_JOYSTICK_WARRIOR is not set ++# CONFIG_JOYSTICK_MAGELLAN is not set ++# CONFIG_JOYSTICK_SPACEORB is not set ++# CONFIG_JOYSTICK_SPACEBALL is not set ++# CONFIG_JOYSTICK_STINGER is not set ++# CONFIG_JOYSTICK_TWIDJOY is not set ++# CONFIG_JOYSTICK_ZHENHUA is not set ++# CONFIG_JOYSTICK_AS5011 is not set ++# CONFIG_JOYSTICK_JOYDUMP is not set ++# CONFIG_JOYSTICK_XPAD is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_GP2A is not set ++# CONFIG_INPUT_GPIO_BEEPER is not set ++# CONFIG_INPUT_GPIO_TILT_POLLED is not set ++# CONFIG_INPUT_GPIO_DECODER is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INPUT_CM109 is not set ++# CONFIG_INPUT_REGULATOR_HAPTIC is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV260X_HAPTICS is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_INPUT_HISI_POWERKEY is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_SERIO_OLPC_APSP is not set ++# CONFIG_SERIO_SUN4I_PS2 is not set ++# CONFIG_USERIO is not set ++CONFIG_GAMEPORT=y ++# CONFIG_GAMEPORT_NS558 is not set ++# CONFIG_GAMEPORT_L4 is not set ++# CONFIG_GAMEPORT_EMU10K1 is not set ++# CONFIG_GAMEPORT_FM801 is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_NOZOMI is not set ++# CONFIG_N_GSM is not set ++# CONFIG_TRACE_SINK is not set ++CONFIG_DEVMEM=y ++CONFIG_DEVKMEM=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_ATMEL is not set ++# CONFIG_SERIAL_CLPS711X is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X is not set ++# CONFIG_SERIAL_IMX is not set ++# CONFIG_SERIAL_UARTLITE is not set ++# CONFIG_SERIAL_SH_SCI is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_JSM is not set ++# CONFIG_SERIAL_SCCNXP is not set ++# CONFIG_SERIAL_SC16IS7XX is not set ++# CONFIG_SERIAL_TIMBERDALE is not set ++# CONFIG_SERIAL_BCM63XX is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_IFX6X60 is not set ++# CONFIG_SERIAL_PCH_UART is not set ++# CONFIG_SERIAL_MXS_AUART is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++# CONFIG_SERIAL_MPS2_UART is not set ++# CONFIG_SERIAL_ARC is not set ++# CONFIG_SERIAL_RP2 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_SERIAL_MVEBU_UART 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_APPLICOM is not set ++ ++# ++# PCMCIA character devices ++# ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_DEVPORT=y ++# 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=y ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set ++# CONFIG_I2C_MUX_GPIO is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PCA954x is not set ++# CONFIG_I2C_MUX_PINCTRL is not set ++# CONFIG_I2C_MUX_REG is not set ++# CONFIG_I2C_DEMUX_PINCTRL 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 ++# ++ ++# ++# PC SMBus host controller drivers ++# ++# CONFIG_I2C_ALI1535 is not set ++# CONFIG_I2C_ALI1563 is not set ++# CONFIG_I2C_ALI15X3 is not set ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++# CONFIG_I2C_HIX5HD2 is not set ++# CONFIG_I2C_I801 is not set ++# CONFIG_I2C_ISCH is not set ++# CONFIG_I2C_PIIX4 is not set ++# CONFIG_I2C_NFORCE2 is not set ++# CONFIG_I2C_SIS5595 is not set ++# CONFIG_I2C_SIS630 is not set ++# CONFIG_I2C_SIS96X is not set ++# CONFIG_I2C_VIA is not set ++# CONFIG_I2C_VIAPRO is not set ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_AXXIA is not set ++# CONFIG_I2C_BCM_IPROC is not set ++# CONFIG_I2C_BRCMSTB is not set ++# CONFIG_I2C_CADENCE is not set ++# CONFIG_I2C_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_DESIGNWARE_PCI is not set ++# CONFIG_I2C_EFM32 is not set ++# CONFIG_I2C_EG20T is not set ++# CONFIG_I2C_EMEV2 is not set ++# CONFIG_I2C_GPIO is not set ++CONFIG_I2C_HIBVT=y ++# CONFIG_I2C_IMG is not set ++# CONFIG_I2C_JZ4780 is not set ++# CONFIG_I2C_LPC2K is not set ++# CONFIG_I2C_MESON is not set ++# CONFIG_I2C_MT65XX is not set ++# CONFIG_I2C_NOMADIK 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_RIIC is not set ++# CONFIG_I2C_RK3X is not set ++# CONFIG_I2C_SH_MOBILE is not set ++# CONFIG_I2C_SIMTEC is not set ++# CONFIG_I2C_SUN6I_P2WI is not set ++# CONFIG_I2C_UNIPHIER is not set ++# CONFIG_I2C_UNIPHIER_F is not set ++# CONFIG_I2C_VERSATILE is not set ++# CONFIG_I2C_THUNDERX is not set ++# CONFIG_I2C_XILINX is not set ++# CONFIG_I2C_XLP9XX is not set ++# CONFIG_I2C_RCAR 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_DMA_MSG_MIN_LEN=5 ++CONFIG_DMA_MSG_MAX_LEN=4090 ++# 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_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_ATMEL is not set ++# CONFIG_SPI_AXI_SPI_ENGINE is not set ++# CONFIG_SPI_BCM2835 is not set ++# CONFIG_SPI_BCM2835AUX is not set ++# CONFIG_SPI_BCM63XX is not set ++# CONFIG_SPI_BCM63XX_HSSPI is not set ++# CONFIG_SPI_BCM_QSPI is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_CLPS711X is not set ++# CONFIG_SPI_DESIGNWARE is not set ++# CONFIG_SPI_EP93XX is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_IMG_SPFI is not set ++# CONFIG_SPI_IMX is not set ++# CONFIG_SPI_JCORE is not set ++# CONFIG_SPI_LP8841_RTC is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_FSL_DSPI is not set ++# CONFIG_SPI_MESON_SPIFC is not set ++# CONFIG_SPI_MT65XX is not set ++# CONFIG_SPI_OC_TINY is not set ++# CONFIG_SPI_OMAP24XX is not set ++# CONFIG_SPI_TI_QSPI is not set ++# CONFIG_SPI_OMAP_100K is not set ++# CONFIG_SPI_ORION is not set ++# CONFIG_SPI_PIC32 is not set ++# CONFIG_SPI_PIC32_SQI is not set ++CONFIG_SPI_PL022=y ++# CONFIG_SPI_PXA2XX is not set ++# CONFIG_SPI_PXA2XX_PCI is not set ++# CONFIG_SPI_ROCKCHIP is not set ++# CONFIG_SPI_RSPI is not set ++# CONFIG_SPI_SC18IS602 is not set ++# CONFIG_SPI_SH_MSIOF is not set ++# CONFIG_SPI_SH is not set ++# CONFIG_SPI_SH_HSPI is not set ++# CONFIG_SPI_ST_SSC4 is not set ++# CONFIG_SPI_SUN4I is not set ++# CONFIG_SPI_SUN6I is not set ++# CONFIG_SPI_TEGRA114 is not set ++# CONFIG_SPI_TEGRA20_SFLASH is not set ++# CONFIG_SPI_TEGRA20_SLINK is not set ++# CONFIG_SPI_THUNDERX is not set ++# CONFIG_SPI_TOPCLIFF_PCH is not set ++# CONFIG_SPI_TXX9 is not set ++# CONFIG_SPI_XCOMM is not set ++# CONFIG_SPI_XILINX is not set ++# CONFIG_SPI_XLP is not set ++# CONFIG_SPI_XTENSA_XTFPGA is not set ++# CONFIG_SPI_ZYNQMP_GQSPI is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_PTP_1588_CLOCK_PCH is not set ++CONFIG_PINCTRL=y ++ ++# ++# Pin controllers ++# ++CONFIG_PINMUX=y ++CONFIG_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++# CONFIG_PINCTRL_AMD is not set ++# CONFIG_PINCTRL_LPC18XX is not set ++CONFIG_PINCTRL_SINGLE=y ++# CONFIG_PINCTRL_ASPEED_G4 is not set ++# CONFIG_PINCTRL_ASPEED_G5 is not set ++# CONFIG_PINCTRL_BCM281XX is not set ++# CONFIG_PINCTRL_IPROC_GPIO is not set ++# CONFIG_PINCTRL_CYGNUS_MUX is not set ++# CONFIG_PINCTRL_NSP_GPIO is not set ++# CONFIG_PINCTRL_NS2_MUX is not set ++# CONFIG_PINCTRL_NSP_MUX is not set ++# CONFIG_PINCTRL_BERLIN_BG2 is not set ++# CONFIG_PINCTRL_BERLIN_BG2CD is not set ++# CONFIG_PINCTRL_BERLIN_BG2Q is not set ++# CONFIG_PINCTRL_BERLIN_BG4CT is not set ++# CONFIG_PINCTRL_PXA25X is not set ++# CONFIG_PINCTRL_PXA27X is not set ++# CONFIG_PINCTRL_APQ8064 is not set ++# CONFIG_PINCTRL_APQ8084 is not set ++# CONFIG_PINCTRL_IPQ4019 is not set ++# CONFIG_PINCTRL_IPQ8064 is not set ++# CONFIG_PINCTRL_MSM8660 is not set ++# CONFIG_PINCTRL_MSM8960 is not set ++# CONFIG_PINCTRL_MDM9615 is not set ++# CONFIG_PINCTRL_MSM8X74 is not set ++# CONFIG_PINCTRL_MSM8916 is not set ++# CONFIG_PINCTRL_MSM8996 is not set ++# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set ++# CONFIG_PINCTRL_STM32F429 is not set ++# CONFIG_PINCTRL_STM32F746 is not set ++# CONFIG_PINCTRL_UNIPHIER is not set ++# CONFIG_PINCTRL_MT2701 is not set ++# CONFIG_PINCTRL_MT7623 is not set ++# CONFIG_PINCTRL_MT8135 is not set ++# CONFIG_PINCTRL_MT8127 is not set ++# CONFIG_PINCTRL_MT8173 is not set ++# CONFIG_PINCTRL_MT6397 is not set ++CONFIG_GPIOLIB=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_GENERIC=y ++ ++# ++# Memory mapped GPIO drivers ++# ++# CONFIG_GPIO_74XX_MMIO is not set ++# CONFIG_GPIO_ALTERA is not set ++# CONFIG_GPIO_ASPEED is not set ++# CONFIG_GPIO_ATH79 is not set ++# CONFIG_GPIO_BCM_KONA is not set ++# CONFIG_GPIO_BRCMSTB is not set ++# CONFIG_GPIO_CLPS711X is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_ETRAXFS is not set ++CONFIG_GPIO_GENERIC_PLATFORM=y ++# CONFIG_GPIO_GRGPIO is not set ++# CONFIG_GPIO_IOP is not set ++# CONFIG_GPIO_LPC18XX is not set ++# CONFIG_GPIO_MB86S7X is not set ++# CONFIG_GPIO_MOCKUP is not set ++# CONFIG_GPIO_MOXART is not set ++# CONFIG_GPIO_MPC8XXX is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_RCAR is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_TEGRA is not set ++# CONFIG_GPIO_TS4800 is not set ++# CONFIG_GPIO_VX855 is not set ++# CONFIG_GPIO_XGENE is not set ++# CONFIG_GPIO_XILINX is not set ++# CONFIG_GPIO_XLP 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 ++# ++ ++# ++# PCI GPIO expanders ++# ++# CONFIG_GPIO_AMD8111 is not set ++# CONFIG_GPIO_BT8XX is not set ++# CONFIG_GPIO_ML_IOH is not set ++# CONFIG_GPIO_PCH is not set ++# CONFIG_GPIO_RDC321X 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++# CONFIG_POWER_RESET_HISI is not set ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_XGENE is not set ++# CONFIG_POWER_RESET_KEYSTONE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_POWER_RESET_RMOBILE is not set ++# CONFIG_POWER_RESET_ZX is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_ACT8945A is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_MANAGER is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24257 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_BQ25890 is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_BATTERY_GOLDFISH is not set ++# CONFIG_CHARGER_RT9455 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_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_MX25_TSADC is not set ++# CONFIG_MFD_HI6421_PMIC is not set ++# CONFIG_MFD_HI655X_PMIC is not set ++CONFIG_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_HTC_I2CPLD is not set ++# CONFIG_LPC_ICH is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_INTEL_SOC_PMIC is not set ++# CONFIG_MFD_JANZ_CMODIO 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_RDC321X is not set ++# CONFIG_MFD_RTSX_PCI 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=y ++# 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_TIMBERDALE is not set ++# CONFIG_MFD_TC3589X is not set ++# CONFIG_MFD_TMIO is not set ++# CONFIG_MFD_VX855 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_MFD_STW481X is not set ++CONFIG_REGULATOR=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_LTC3676 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MT6311 is not set ++# CONFIG_REGULATOR_PBIAS is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_PV88060 is not set ++# CONFIG_REGULATOR_PV88080 is not set ++# CONFIG_REGULATOR_PV88090 is not set ++# CONFIG_REGULATOR_QCOM_SPMI is not set ++# CONFIG_REGULATOR_STW481X_VMMC is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=y ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=y ++CONFIG_VIDEO_V4L2=y ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=y ++CONFIG_VIDEOBUF2_MEMOPS=y ++CONFIG_VIDEOBUF2_VMALLOC=y ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++CONFIG_MEDIA_USB_SUPPORT=y ++ ++# ++# Webcam devices ++# ++CONFIG_USB_VIDEO_CLASS=y ++CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y ++CONFIG_USB_GSPCA=m ++# CONFIG_USB_M5602 is not set ++# CONFIG_USB_STV06XX is not set ++# CONFIG_USB_GL860 is not set ++# CONFIG_USB_GSPCA_BENQ is not set ++# CONFIG_USB_GSPCA_CONEX is not set ++# CONFIG_USB_GSPCA_CPIA1 is not set ++# CONFIG_USB_GSPCA_DTCS033 is not set ++# CONFIG_USB_GSPCA_ETOMS is not set ++# CONFIG_USB_GSPCA_FINEPIX is not set ++# CONFIG_USB_GSPCA_JEILINJ is not set ++# CONFIG_USB_GSPCA_JL2005BCD is not set ++# CONFIG_USB_GSPCA_KINECT is not set ++# CONFIG_USB_GSPCA_KONICA is not set ++# CONFIG_USB_GSPCA_MARS is not set ++# CONFIG_USB_GSPCA_MR97310A is not set ++# CONFIG_USB_GSPCA_NW80X is not set ++# CONFIG_USB_GSPCA_OV519 is not set ++# CONFIG_USB_GSPCA_OV534 is not set ++# CONFIG_USB_GSPCA_OV534_9 is not set ++# CONFIG_USB_GSPCA_PAC207 is not set ++# CONFIG_USB_GSPCA_PAC7302 is not set ++# CONFIG_USB_GSPCA_PAC7311 is not set ++# CONFIG_USB_GSPCA_SE401 is not set ++# CONFIG_USB_GSPCA_SN9C2028 is not set ++# CONFIG_USB_GSPCA_SN9C20X is not set ++# CONFIG_USB_GSPCA_SONIXB is not set ++# CONFIG_USB_GSPCA_SONIXJ is not set ++# CONFIG_USB_GSPCA_SPCA500 is not set ++# CONFIG_USB_GSPCA_SPCA501 is not set ++# CONFIG_USB_GSPCA_SPCA505 is not set ++# CONFIG_USB_GSPCA_SPCA506 is not set ++# CONFIG_USB_GSPCA_SPCA508 is not set ++# CONFIG_USB_GSPCA_SPCA561 is not set ++# CONFIG_USB_GSPCA_SPCA1528 is not set ++# CONFIG_USB_GSPCA_SQ905 is not set ++# CONFIG_USB_GSPCA_SQ905C is not set ++# CONFIG_USB_GSPCA_SQ930X is not set ++# CONFIG_USB_GSPCA_STK014 is not set ++# CONFIG_USB_GSPCA_STK1135 is not set ++# CONFIG_USB_GSPCA_STV0680 is not set ++# CONFIG_USB_GSPCA_SUNPLUS is not set ++# CONFIG_USB_GSPCA_T613 is not set ++# CONFIG_USB_GSPCA_TOPRO is not set ++# CONFIG_USB_GSPCA_TOUPTEK is not set ++# CONFIG_USB_GSPCA_TV8532 is not set ++# CONFIG_USB_GSPCA_VC032X is not set ++# CONFIG_USB_GSPCA_VICAM is not set ++# CONFIG_USB_GSPCA_XIRLINK_CIT is not set ++# CONFIG_USB_GSPCA_ZC3XX is not set ++# CONFIG_USB_PWC is not set ++# CONFIG_VIDEO_CPIA2 is not set ++# CONFIG_USB_ZR364XX is not set ++# CONFIG_USB_STKWEBCAM is not set ++# CONFIG_USB_S2255 is not set ++ ++# ++# Webcam, TV (analog/digital) USB devices ++# ++# CONFIG_VIDEO_EM28XX is not set ++# CONFIG_MEDIA_PCI_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, spi, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# I2C Encoders, decoders, sensors and other helper chips ++# ++ ++# ++# Audio decoders, processors and mixers ++# ++# CONFIG_VIDEO_TVAUDIO is not set ++# CONFIG_VIDEO_TDA7432 is not set ++# CONFIG_VIDEO_TDA9840 is not set ++# CONFIG_VIDEO_TEA6415C is not set ++# CONFIG_VIDEO_TEA6420 is not set ++# CONFIG_VIDEO_MSP3400 is not set ++# CONFIG_VIDEO_CS3308 is not set ++# CONFIG_VIDEO_CS5345 is not set ++# CONFIG_VIDEO_CS53L32A is not set ++# CONFIG_VIDEO_TLV320AIC23B is not set ++# CONFIG_VIDEO_UDA1342 is not set ++# CONFIG_VIDEO_WM8775 is not set ++# CONFIG_VIDEO_WM8739 is not set ++# CONFIG_VIDEO_VP27SMPX is not set ++# CONFIG_VIDEO_SONY_BTF_MPX is not set ++ ++# ++# RDS decoders ++# ++# CONFIG_VIDEO_SAA6588 is not set ++ ++# ++# Video decoders ++# ++# CONFIG_VIDEO_ADV7183 is not set ++# CONFIG_VIDEO_BT819 is not set ++# CONFIG_VIDEO_BT856 is not set ++# CONFIG_VIDEO_BT866 is not set ++# CONFIG_VIDEO_KS0127 is not set ++# CONFIG_VIDEO_ML86V7667 is not set ++# CONFIG_VIDEO_SAA7110 is not set ++# CONFIG_VIDEO_SAA711X is not set ++# CONFIG_VIDEO_TVP514X is not set ++# CONFIG_VIDEO_TVP5150 is not set ++# CONFIG_VIDEO_TVP7002 is not set ++# CONFIG_VIDEO_TW2804 is not set ++# CONFIG_VIDEO_TW9903 is not set ++# CONFIG_VIDEO_TW9906 is not set ++# CONFIG_VIDEO_VPX3220 is not set ++ ++# ++# Video and audio decoders ++# ++# CONFIG_VIDEO_SAA717X is not set ++# CONFIG_VIDEO_CX25840 is not set ++ ++# ++# Video encoders ++# ++# CONFIG_VIDEO_SAA7127 is not set ++# CONFIG_VIDEO_SAA7185 is not set ++# CONFIG_VIDEO_ADV7170 is not set ++# CONFIG_VIDEO_ADV7175 is not set ++# CONFIG_VIDEO_ADV7343 is not set ++# CONFIG_VIDEO_ADV7393 is not set ++# CONFIG_VIDEO_AK881X is not set ++# CONFIG_VIDEO_THS8200 is not set ++ ++# ++# Camera sensor devices ++# ++# CONFIG_VIDEO_OV2659 is not set ++# CONFIG_VIDEO_OV7640 is not set ++# CONFIG_VIDEO_OV7670 is not set ++# CONFIG_VIDEO_VS6624 is not set ++# CONFIG_VIDEO_MT9M111 is not set ++# CONFIG_VIDEO_MT9V011 is not set ++# CONFIG_VIDEO_SR030PC30 is not set ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++# CONFIG_VIDEO_UPD64031A is not set ++# CONFIG_VIDEO_UPD64083 is not set ++ ++# ++# Audio/Video compression chips ++# ++# CONFIG_VIDEO_SAA6752HS is not set ++ ++# ++# Miscellaneous helper chips ++# ++# CONFIG_VIDEO_THS7303 is not set ++# CONFIG_VIDEO_M52790 is not set ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# SPI helper chips ++# ++ ++# ++# Customise DVB Frontends ++# ++# CONFIG_DVB_AU8522_V4L is not set ++# CONFIG_DVB_TUNER_DIB0070 is not set ++# CONFIG_DVB_TUNER_DIB0090 is not set ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++CONFIG_VGA_ARB=y ++CONFIG_VGA_ARB_MAX_GPUS=16 ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_CIRRUS is not set ++# CONFIG_FB_PM2 is not set ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CLPS711X is not set ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_NVIDIA is not set ++# CONFIG_FB_RIVA is not set ++# CONFIG_FB_I740 is not set ++# CONFIG_FB_MATROX is not set ++# CONFIG_FB_RADEON is not set ++# CONFIG_FB_ATY128 is not set ++# CONFIG_FB_ATY is not set ++# CONFIG_FB_S3 is not set ++# CONFIG_FB_SAVAGE is not set ++# CONFIG_FB_SIS is not set ++# CONFIG_FB_NEOMAGIC is not set ++# CONFIG_FB_KYRO is not set ++# CONFIG_FB_3DFX is not set ++# CONFIG_FB_VOODOO1 is not set ++# CONFIG_FB_VT8623 is not set ++# CONFIG_FB_TRIDENT is not set ++# CONFIG_FB_ARK is not set ++# CONFIG_FB_PM3 is not set ++# CONFIG_FB_CARMINE is not set ++# CONFIG_FB_TMIO is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_GOLDFISH is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_MB862XX is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_FB_SM712 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++CONFIG_DUMMY_CONSOLE_COLUMNS=80 ++CONFIG_DUMMY_CONSOLE_ROWS=25 ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++# CONFIG_HID_BETOP_FF is not set ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# 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 is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PCI=y ++CONFIG_USB_XHCI_PLATFORM=y ++# CONFIG_USB_XHCI_MTK is not set ++# CONFIG_USB_XHCI_MVEBU is not set ++# CONFIG_USB_XHCI_RCAR 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_UHCI_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 ++# CONFIG_USB_RENESAS_USBHS is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++# CONFIG_USB_WDM is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++# CONFIG_USBIP_CORE is not set ++# CONFIG_USB_MUSB_HDRC is not set ++CONFIG_USB_DWC3=y ++# CONFIG_USB_DWC3_HOST is not set ++CONFIG_USB_DWC3_GADGET=y ++# CONFIG_USB_DWC3_DUAL_ROLE is not set ++ ++# ++# Platform Glue Driver Support ++# ++CONFIG_USB_DWC3_EXYNOS=y ++CONFIG_USB_DWC3_PCI=y ++CONFIG_USB_DWC3_KEYSTONE=y ++CONFIG_USB_DWC3_OF_SIMPLE=y ++# CONFIG_USB_DWC2 is not set ++# CONFIG_USB_CHIPIDEA 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++# CONFIG_USB_GADGET_DEBUG_FS is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_RENESAS_USB3 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_BDC_UDC is not set ++# CONFIG_USB_AMD5536UDC is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_NET2280 is not set ++# CONFIG_USB_GOKU is not set ++# CONFIG_USB_EG20T is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_MASS_STORAGE=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM 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_ARMMMCI is not set ++CONFIG_MMC_SDHCI=y ++# CONFIG_MMC_SDHCI_PCI is not set ++CONFIG_MMC_SDHCI_PLTFM=y ++# CONFIG_MMC_SDHCI_OF_ARASAN is not set ++# CONFIG_MMC_SDHCI_OF_AT91 is not set ++CONFIG_MMC_SDHCI_HISI=y ++# CONFIG_MMC_SDHCI_PXAV3 is not set ++# CONFIG_MMC_SDHCI_PXAV2 is not set ++# CONFIG_MMC_SDHCI_F_SDH30 is not set ++# CONFIG_MMC_SDHCI_IPROC is not set ++# CONFIG_MMC_OMAP_HS is not set ++# CONFIG_MMC_TIFM_SD is not set ++# CONFIG_MMC_GOLDFISH is not set ++# CONFIG_MMC_SPI is not set ++# CONFIG_MMC_SDHI is not set ++# CONFIG_MMC_CB710 is not set ++# CONFIG_MMC_VIA_SDMMC is not set ++# CONFIG_MMC_DW is not set ++# CONFIG_MMC_SH_MMCIF is not set ++# CONFIG_MMC_VUB300 is not set ++# CONFIG_MMC_USHC is not set ++# CONFIG_MMC_USDHI6ROL0 is not set ++# CONFIG_MMC_TOSHIBA_PCI 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_INFINIBAND is not set ++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=y ++ ++# ++# SPI and I2C RTC drivers ++# ++# CONFIG_RTC_DRV_DS3232 is not set ++# CONFIG_RTC_DRV_PCF2127 is not set ++# CONFIG_RTC_DRV_RV3029C2 is not set ++ ++# ++# Platform RTC drivers ++# ++CONFIG_RTC_DRV_HIBVT=y ++# 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_SPEAR is not set ++# CONFIG_RTC_DRV_NUC900 is not set ++# CONFIG_RTC_DRV_ZYNQMP is not set ++ ++# ++# on-CPU RTC drivers ++# ++# CONFIG_RTC_DRV_ASM9260 is not set ++# CONFIG_RTC_DRV_DAVINCI is not set ++# CONFIG_RTC_DRV_DIGICOLOR is not set ++# CONFIG_RTC_DRV_OMAP is not set ++# CONFIG_RTC_DRV_S3C is not set ++# CONFIG_RTC_DRV_EP93XX is not set ++# CONFIG_RTC_DRV_VR41XX is not set ++# CONFIG_RTC_DRV_PL030 is not set ++# CONFIG_RTC_DRV_PL031 is not set ++# CONFIG_RTC_DRV_AT32AP700X is not set ++# CONFIG_RTC_DRV_AT91RM9200 is not set ++# CONFIG_RTC_DRV_AT91SAM9 is not set ++# CONFIG_RTC_DRV_GENERIC is not set ++# CONFIG_RTC_DRV_VT8500 is not set ++# CONFIG_RTC_DRV_SUNXI is not set ++# CONFIG_RTC_DRV_MV is not set ++# CONFIG_RTC_DRV_ARMADA38X is not set ++# CONFIG_RTC_DRV_GEMINI is not set ++# CONFIG_RTC_DRV_COH901331 is not set ++# CONFIG_RTC_DRV_STMP is not set ++# CONFIG_RTC_DRV_JZ4740 is not set ++# CONFIG_RTC_DRV_LPC24XX is not set ++# CONFIG_RTC_DRV_LPC32XX is not set ++# CONFIG_RTC_DRV_PM8XXX is not set ++# CONFIG_RTC_DRV_TEGRA is not set ++# CONFIG_RTC_DRV_SNVS is not set ++# CONFIG_RTC_DRV_MOXART is not set ++# CONFIG_RTC_DRV_MT6397 is not set ++# CONFIG_RTC_DRV_XGENE is not set ++ ++# ++# HID Sensor RTC drivers ++# ++# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set ++CONFIG_DMADEVICES=y ++# CONFIG_DMADEVICES_DEBUG is not set ++ ++# ++# DMA Devices ++# ++CONFIG_DMA_ENGINE=y ++CONFIG_DMA_VIRTUAL_CHANNELS=y ++CONFIG_DMA_OF=y ++# CONFIG_AMBA_PL08X is not set ++# CONFIG_AXI_DMAC is not set ++# CONFIG_COH901318 is not set ++# CONFIG_DMA_JZ4740 is not set ++# CONFIG_DMA_JZ4780 is not set ++# CONFIG_DMA_OMAP is not set ++# CONFIG_DMA_SA11X0 is not set ++# CONFIG_DMA_SUN6I is not set ++# CONFIG_EP93XX_DMA is not set ++# CONFIG_FSL_EDMA is not set ++# CONFIG_IMG_MDC_DMA is not set ++# CONFIG_INTEL_IDMA64 is not set ++# CONFIG_K3_DMA is not set ++# CONFIG_MMP_PDMA is not set ++# CONFIG_MMP_TDMA is not set ++# CONFIG_MV_XOR is not set ++# CONFIG_MV_XOR_V2 is not set ++# CONFIG_NBPFAXI_DMA is not set ++# CONFIG_PCH_DMA is not set ++# CONFIG_PL330_DMA is not set ++# CONFIG_STM32_DMA is not set ++# CONFIG_S3C24XX_DMAC is not set ++# CONFIG_TEGRA210_ADMA is not set ++# CONFIG_TIMB_DMA is not set ++# CONFIG_TI_EDMA is not set ++# CONFIG_XGENE_DMA is not set ++# CONFIG_XILINX_DMA is not set ++# CONFIG_XILINX_ZYNQMP_DMA is not set ++# CONFIG_ZX_DMA is not set ++CONFIG_HIEDMACV310=y ++# CONFIG_QCOM_HIDMA_MGMT is not set ++# CONFIG_QCOM_HIDMA is not set ++# CONFIG_DW_DMAC is not set ++# CONFIG_DW_DMAC_PCI is not set ++CONFIG_RENESAS_DMA=y ++CONFIG_SH_DMAE_BASE=y ++# CONFIG_SH_DMAE is not set ++# CONFIG_RCAR_DMAC is not set ++# CONFIG_RENESAS_USB_DMAC is not set ++# CONFIG_SUDMAC 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_PCI is not set ++# CONFIG_VIRTIO_MMIO is not set ++ ++# ++# Microsoft Hyper-V guest support ++# ++CONFIG_STAGING=y ++# CONFIG_COMEDI is not set ++# CONFIG_RTL8192U is not set ++# CONFIG_RTLLIB is not set ++# CONFIG_R8712U is not set ++# CONFIG_RTS5208 is not set ++# CONFIG_FB_SM750 is not set ++# CONFIG_FB_XGI is not set ++ ++# ++# Speakup console speech ++# ++# CONFIG_SPEAKUP is not set ++# CONFIG_STAGING_MEDIA is not set ++ ++# ++# Android ++# ++# CONFIG_ASHMEM is not set ++# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set ++CONFIG_ION=y ++# CONFIG_ION_TEST is not set ++# CONFIG_ION_DUMMY is not set ++# CONFIG_ION_OF is not set ++# CONFIG_STAGING_BOARD is not set ++# CONFIG_LTE_GDM724X is not set ++# CONFIG_MTD_SPINAND_MT29F is not set ++# CONFIG_LNET is not set ++# CONFIG_DGNC is not set ++# CONFIG_GS_FPGABOOT is not set ++# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set ++# CONFIG_FB_TFT is not set ++# CONFIG_FSL_MC_BUS is not set ++# CONFIG_MOST is not set ++# CONFIG_KS7010 is not set ++# CONFIG_GREYBUS 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_VERSATILE is not set ++# CONFIG_COMMON_CLK_SCPI is not set ++# 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_COMMON_CLK_AXI_CLKGEN is not set ++# CONFIG_CLK_QORIQ is not set ++# CONFIG_COMMON_CLK_XGENE is not set ++# CONFIG_COMMON_CLK_KEYSTONE is not set ++# CONFIG_COMMON_CLK_NXP is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++# CONFIG_COMMON_CLK_OXNAS is not set ++# CONFIG_CLK_BCM_63XX is not set ++# CONFIG_CLK_BCM_KONA is not set ++# CONFIG_COMMON_CLK_IPROC is not set ++# CONFIG_COMMON_CLK_HI3519 is not set ++# CONFIG_COMMON_CLK_HI3516A is not set ++# CONFIG_COMMON_CLK_HI3518EV20X is not set ++# CONFIG_COMMON_CLK_HI3536DV100 is not set ++CONFIG_COMMON_CLK_HI3559AV100=y ++CONFIG_COMMON_CLK_HI3521A=y ++CONFIG_COMMON_CLK_HI3531A=y ++# CONFIG_COMMON_CLK_HI6220 is not set ++CONFIG_RESET_HISI=y ++# CONFIG_COMMON_CLK_MT8135 is not set ++# CONFIG_COMMON_CLK_MT8173 is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++# CONFIG_COMMON_CLK_SAMSUNG is not set ++# CONFIG_S3C2410_COMMON_CLK is not set ++# CONFIG_S3C2412_COMMON_CLK is not set ++# CONFIG_S3C2443_COMMON_CLK is not set ++# CONFIG_SUNXI_CCU is not set ++# CONFIG_COMMON_CLK_TI_ADPLL is not set ++# CONFIG_CLK_UNIPHIER is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++# CONFIG_BCM2835_TIMER is not set ++# CONFIG_BCM_KONA_TIMER is not set ++# CONFIG_DIGICOLOR_TIMER is not set ++# CONFIG_DW_APB_TIMER is not set ++# CONFIG_ROCKCHIP_TIMER is not set ++# CONFIG_MESON6_TIMER is not set ++# CONFIG_SUN4I_TIMER is not set ++# CONFIG_SUN5I_HSTIMER is not set ++# CONFIG_VT8500_TIMER is not set ++# CONFIG_CADENCE_TTC_TIMER is not set ++# CONFIG_ASM9260_TIMER is not set ++# CONFIG_CLKSRC_DBX500_PRCMU is not set ++# CONFIG_CLPS711X_TIMER is not set ++# CONFIG_ATLAS7_TIMER is not set ++# CONFIG_MOXART_TIMER is not set ++# CONFIG_MXS_TIMER is not set ++# CONFIG_PRIMA2_TIMER is not set ++# CONFIG_NSPIRE_TIMER is not set ++# CONFIG_KEYSTONE_TIMER is not set ++# CONFIG_INTEGRATOR_AP_TIMER is not set ++# CONFIG_CLKSRC_PISTACHIO is not set ++# CONFIG_CLKSRC_TI_32K is not set ++# CONFIG_CLKSRC_MPS2 is not set ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set ++CONFIG_FSL_ERRATUM_A008585=y ++CONFIG_ARM_TIMER_SP804=y ++# CONFIG_TIMER_HISP804 is not set ++# CONFIG_ARMV7M_SYSTICK is not set ++# CONFIG_ATMEL_PIT is not set ++# CONFIG_ATMEL_ST is not set ++# CONFIG_CLKSRC_EXYNOS_MCT is not set ++# CONFIG_CLKSRC_SAMSUNG_PWM is not set ++# CONFIG_FSL_FTM_TIMER is not set ++# CONFIG_OXNAS_RPS_TIMER is not set ++# CONFIG_MTK_TIMER is not set ++# CONFIG_CLKSRC_JCORE_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_CLKSRC_VERSATILE is not set ++# CONFIG_CLKSRC_PXA is not set ++# CONFIG_H8300_TMR8 is not set ++# CONFIG_H8300_TMR16 is not set ++# CONFIG_H8300_TPU is not set ++# CONFIG_CLKSRC_ST_LPC 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_MTK_INFRACFG is not set ++# CONFIG_MTK_SCPSYS is not set ++# CONFIG_ROCKCHIP_PM_DOMAINS is not set ++# CONFIG_SOC_SAMSUNG is not set ++# CONFIG_SUNXI_SRAM is not set ++# CONFIG_SOC_TI is not set ++# CONFIG_UX500_SOC_ID is not set ++CONFIG_PM_DEVFREQ=y ++ ++# ++# DEVFREQ Governors ++# ++CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y ++# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set ++# CONFIG_DEVFREQ_GOV_POWERSAVE is not set ++# CONFIG_DEVFREQ_GOV_USERSPACE is not set ++# CONFIG_DEVFREQ_GOV_PASSIVE is not set ++ ++# ++# DEVFREQ Drivers ++# ++# CONFIG_ARM_EXYNOS_BUS_DEVFREQ is not set ++# CONFIG_PM_DEVFREQ_EVENT is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_NTB is not set ++# CONFIG_VME_BUS is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++CONFIG_ARM_GIC_V2M=y ++CONFIG_ARM_GIC_V3=y ++CONFIG_ARM_GIC_V3_ITS=y ++CONFIG_HISILICON_IRQ_MBIGEN=y ++# CONFIG_JCORE_AIC is not set ++# CONFIG_TS4800_IRQ is not set ++CONFIG_PARTITION_PERCPU=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_UNIPHIER is not set ++# CONFIG_RESET_ZYNQ is not set ++CONFIG_COMMON_RESET_HI6220=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_PHY_BCM_NS_USB2 is not set ++# CONFIG_PHY_BCM_NS_USB3 is not set ++CONFIG_ARMADA375_USBCLUSTER_PHY=y ++# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set ++# CONFIG_PHY_LPC18XX_USB_OTG is not set ++# CONFIG_PHY_PXA_28NM_HSIC is not set ++# CONFIG_PHY_PXA_28NM_USB2 is not set ++# CONFIG_OMAP_CONTROL_PHY is not set ++# CONFIG_PHY_EXYNOS_DP_VIDEO is not set ++# CONFIG_BCM_KONA_USB2_PHY is not set ++# CONFIG_PHY_HI6220_USB is not set ++# CONFIG_PHY_ROCKCHIP_INNO_USB2 is not set ++# CONFIG_PHY_ROCKCHIP_PCIE is not set ++# CONFIG_PHY_ROCKCHIP_TYPEC is not set ++# CONFIG_PHY_ST_SPEAR1310_MIPHY is not set ++# CONFIG_PHY_ST_SPEAR1340_MIPHY is not set ++# CONFIG_PHY_XGENE is not set ++# CONFIG_PHY_STIH407_USB is not set ++# CONFIG_PHY_BRCM_SATA is not set ++# CONFIG_PHY_CYGNUS_PCIE is not set ++CONFIG_HISI_PHY_USB3=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++ ++# ++# Performance monitor support ++# ++CONFIG_ARM_PMU=y ++# CONFIG_RAS is not set ++# CONFIG_THUNDERBOLT is not set ++ ++# ++# Android ++# ++CONFIG_ANDROID=y ++# CONFIG_ANDROID_BINDER_IPC is not set ++# CONFIG_LIBNVDIMM 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 ++# CONFIG_HI_DMAC is not set ++# CONFIG_HIVDMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE is not set ++ ++# ++# Firmware Drivers ++# ++CONFIG_ARM_PSCI_FW=y ++CONFIG_ARM_SCPI_POWER_DOMAIN=y ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++# CONFIG_MESON_SM is not set ++# CONFIG_ACPI is not set ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++CONFIG_FS_IOMAP=y ++CONFIG_EXT2_FS=y ++CONFIG_EXT2_FS_XATTR=y ++CONFIG_EXT2_FS_POSIX_ACL=y ++CONFIG_EXT2_FS_SECURITY=y ++CONFIG_EXT3_FS=y ++CONFIG_EXT3_FS_POSIX_ACL=y ++CONFIG_EXT3_FS_SECURITY=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_CHECK=y ++CONFIG_REISERFS_PROC_INFO=y ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_DEBUG=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++# CONFIG_XFS_WARN is not set ++# CONFIG_XFS_DEBUG is not set ++# CONFIG_GFS2_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_DAX is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_EXPORTFS=m ++# 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=y ++# CONFIG_QUOTA_NETLINK_INTERFACE is not set ++CONFIG_PRINT_QUOTA_WARNING=y ++# CONFIG_QUOTA_DEBUG is not set ++CONFIG_QUOTA_TREE=m ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_QUOTACTL=y ++CONFIG_AUTOFS4_FS=m ++CONFIG_FUSE_FS=y ++# CONFIG_CUSE is not set ++# CONFIG_OVERLAY_FS is not set ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=y ++# CONFIG_JOLIET is not set ++# CONFIG_ZISOFS is not set ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++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_KCORE is not set ++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=y ++CONFIG_TMPFS_XATTR=y ++# CONFIG_HUGETLBFS is not set ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_ARCH_HAS_GIGANTIC_PAGE=y ++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_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++CONFIG_SQUASHFS=y ++CONFIG_SQUASHFS_FILE_CACHE=y ++# CONFIG_SQUASHFS_FILE_DIRECT is not set ++CONFIG_SQUASHFS_DECOMP_SINGLE=y ++# CONFIG_SQUASHFS_DECOMP_MULTI is not set ++# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set ++# CONFIG_SQUASHFS_XATTR is not set ++CONFIG_SQUASHFS_ZLIB=y ++# CONFIG_SQUASHFS_LZ4 is not set ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set ++# CONFIG_SQUASHFS_EMBEDDED is not set ++CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 ++# 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFSD is not set ++CONFIG_GRACE_PERIOD=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=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=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=y ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++# 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 ++# CONFIG_VIRTUALIZATION is not set ++ ++# ++# Kernel hacking ++# ++ ++# ++# printk and dmesg options ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++# 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=2048 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++CONFIG_ARCH_WANT_FRAME_POINTERS=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++CONFIG_HAVE_ARCH_KASAN=y ++# CONFIG_KASAN is not set ++CONFIG_ARCH_HAS_KCOV=y ++# CONFIG_KCOV is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++CONFIG_LOCKUP_DETECTOR=y ++# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set ++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 ++# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set ++CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 ++# CONFIG_WQ_WATCHDOG is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++CONFIG_SCHED_INFO=y ++CONFIG_SCHEDSTATS=y ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_HAVE_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_PROVE_RCU is not set ++CONFIG_SPARSE_RCU_POINTER=y ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=21 ++CONFIG_RCU_TRACE=y ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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_TRACE_CLOCK=y ++CONFIG_TRACING_SUPPORT=y ++# CONFIG_FTRACE is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_LKDTM is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=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_ARM64_PTDUMP is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_DEBUG_ALIGN_RODATA is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS 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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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 is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++CONFIG_CRYPTO_NULL=m ++CONFIG_CRYPTO_NULL2=y ++# CONFIG_CRYPTO_PCRYPT is not set ++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=m ++# CONFIG_CRYPTO_GCM is not set ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# 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=y ++CONFIG_CRYPTO_HMAC=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# 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 is not set ++# 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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_CRYPTO_DEV_S5P is not set ++# CONFIG_CRYPTO_DEV_ATMEL_AES is not set ++# CONFIG_CRYPTO_DEV_CCP is not set ++# CONFIG_CRYPTO_DEV_QCE is not set ++# CONFIG_CRYPTO_DEV_IMGTEC_HASH is not set ++ ++# ++# Certificates for signature checking ++# ++# CONFIG_ARM64_CRYPTO is not set ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++CONFIG_HAVE_ARCH_BITREVERSE=y ++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=y ++CONFIG_CRC16=y ++# CONFIG_CRC_T10DIF is not set ++CONFIG_CRC_ITU_T=y ++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=m ++# CONFIG_CRC8 is not set ++CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y ++# CONFIG_RANDOM32_SELFTEST is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=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_GZIP=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_NLATTR=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=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y +diff --git a/arch/arm64/configs/hi3559av100_arm64_big_little_nand_amp_defconfig b/arch/arm64/configs/hi3559av100_arm64_big_little_nand_amp_defconfig +new file mode 100644 +index 0000000..ab76a51 +--- /dev/null ++++ b/arch/arm64/configs/hi3559av100_arm64_big_little_nand_amp_defconfig +@@ -0,0 +1,3847 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm64 4.9.37 Kernel Configuration ++# ++CONFIG_ARM64=y ++CONFIG_64BIT=y ++CONFIG_ARCH_PHYS_ADDR_T_64BIT=y ++CONFIG_MMU=y ++CONFIG_DEBUG_RODATA=y ++CONFIG_ARM64_PAGE_SHIFT=12 ++CONFIG_ARM64_CONT_SHIFT=4 ++CONFIG_ARCH_MMAP_RND_BITS_MIN=18 ++CONFIG_ARCH_MMAP_RND_BITS_MAX=24 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=y ++CONFIG_GENERIC_BUG=y ++CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CSUM=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_ZONE_DMA=y ++CONFIG_HAVE_GENERIC_RCU_GUP=y ++CONFIG_ARCH_DMA_ADDR_T_64BIT=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_NEED_SG_DMA_LENGTH=y ++CONFIG_SMP=y ++CONFIG_SWIOTLB=y ++CONFIG_IOMMU_HELPER=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_FIX_EARLYCON_MEM=y ++CONFIG_PGTABLE_LEVELS=3 ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++CONFIG_COMPILE_TEST=y ++CONFIG_LOCALVERSION="" ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_GENERIC_IRQ_MIGRATION=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_GENERIC_MSI_IRQ=y ++CONFIG_GENERIC_MSI_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++# CONFIG_IRQ_DOMAIN_DEBUG is not set ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_HZ_PERIODIC=y ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NO_HZ_FULL 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_TREE_RCU=y ++# CONFIG_RCU_EXPERT is not set ++CONFIG_SRCU=y ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++CONFIG_TREE_RCU_TRACE=y ++# CONFIG_RCU_EXPEDITE_BOOT is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=14 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y ++# CONFIG_CGROUPS is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++CONFIG_RELAY=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++# CONFIG_RD_LZ4 is not set ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_SYSCTL_EXCEPTION_TRACE=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_ALL is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y ++CONFIG_BPF_SYSCALL=y ++CONFIG_SHMEM=y ++CONFIG_AIO=y ++CONFIG_ADVISE_SYSCALLS=y ++CONFIG_USERFAULTFD=y ++CONFIG_PCI_QUIRKS=y ++CONFIG_MEMBARRIER=y ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++ ++# ++# Kernel Performance Events And Counters ++# ++CONFIG_PERF_EVENTS=y ++# CONFIG_DEBUG_PERF_USE_VMALLOC is not set ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_SLAB_FREELIST_RANDOM is not set ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_SYSTEM_DATA_VERIFICATION is not set ++# CONFIG_PROFILING is not set ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL is not set ++# CONFIG_UPROBES is not set ++# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set ++CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=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_HW_BREAKPOINT=y ++CONFIG_HAVE_PERF_REGS=y ++CONFIG_HAVE_PERF_USER_STACK_DUMP=y ++CONFIG_HAVE_ARCH_JUMP_LABEL=y ++CONFIG_HAVE_RCU_TABLE_FREE=y ++CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y ++CONFIG_HAVE_CMPXCHG_LOCAL=y ++CONFIG_HAVE_CMPXCHG_DOUBLE=y ++CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y ++CONFIG_HAVE_ARCH_SECCOMP_FILTER=y ++CONFIG_HAVE_GCC_PLUGINS=y ++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_ARCH_TRANSPARENT_HUGEPAGE=y ++CONFIG_HAVE_ARCH_HUGE_VMAP=y ++CONFIG_MODULES_USE_ELF_RELA=y ++CONFIG_ARCH_HAS_ELF_RANDOMIZE=y ++CONFIG_HAVE_ARCH_MMAP_RND_BITS=y ++CONFIG_ARCH_MMAP_RND_BITS=18 ++CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 ++# CONFIG_HAVE_ARCH_HASH is not set ++# CONFIG_ISA_BUS_API is not set ++CONFIG_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_COMPAT_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_SLABINFO=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_MODULES_TREE_LOOKUP=y ++CONFIG_BLOCK=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++CONFIG_BLOCK_COMPAT=y ++CONFIG_BLK_MQ_PCI=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_LOCK_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# Platform selection ++# ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_BCM2835 is not set ++# CONFIG_ARCH_BCM_IPROC is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_BRCMSTB is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_LAYERSCAPE is not set ++# CONFIG_ARCH_LG1K is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++CONFIG_ARCH_HI3559AV100=y ++# CONFIG_ACCESS_M7_DEV is not set ++CONFIG_ARCH_HISI_BVT_AMP=y ++# CONFIG_ARCH_MEDIATEK is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SEATTLE is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_STRATIX10 is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_SPRD is not set ++# CONFIG_ARCH_THUNDER is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_VULCAN is not set ++# CONFIG_ARCH_XGENE is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQMP is not set ++ ++# ++# Bus support ++# ++CONFIG_PCI=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_PCI_DOMAINS_GENERIC=y ++CONFIG_PCI_SYSCALL=y ++CONFIG_PCIEPORTBUS=y ++# CONFIG_PCIEAER is not set ++# CONFIG_PCIEASPM is not set ++# CONFIG_PCIE_PME is not set ++# CONFIG_PCIE_DPC is not set ++# CONFIG_PCIE_PTM is not set ++CONFIG_PCI_BUS_ADDR_T_64BIT=y ++CONFIG_PCI_MSI=y ++CONFIG_PCI_MSI_IRQ_DOMAIN=y ++# CONFIG_PCI_DEBUG is not set ++# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set ++# CONFIG_PCI_STUB is not set ++# CONFIG_PCI_IOV is not set ++# CONFIG_PCI_PRI is not set ++# CONFIG_PCI_PASID is not set ++# CONFIG_HOTPLUG_PCI is not set ++ ++# ++# PCI host controller drivers ++# ++# CONFIG_PCIE_DW_PLAT is not set ++# CONFIG_PCI_HOST_GENERIC is not set ++# CONFIG_PCI_HISI is not set ++# CONFIG_PCI_HOST_THUNDER_PEM is not set ++# CONFIG_PCI_HOST_THUNDER_ECAM is not set ++# CONFIG_HIPCIE is not set ++ ++# ++# Kernel Features ++# ++ ++# ++# ARM errata workarounds via the alternatives framework ++# ++CONFIG_ARM64_ERRATUM_826319=y ++CONFIG_ARM64_ERRATUM_827319=y ++CONFIG_ARM64_ERRATUM_824069=y ++CONFIG_ARM64_ERRATUM_819472=y ++CONFIG_ARM64_ERRATUM_832075=y ++CONFIG_ARM64_ERRATUM_845719=y ++CONFIG_ARM64_ERRATUM_843419=y ++CONFIG_CAVIUM_ERRATUM_22375=y ++CONFIG_CAVIUM_ERRATUM_23154=y ++CONFIG_CAVIUM_ERRATUM_27456=y ++CONFIG_QCOM_QDF2400_ERRATUM_0065=y ++CONFIG_ARM64_4K_PAGES=y ++# CONFIG_ARM64_16K_PAGES is not set ++# CONFIG_ARM64_64K_PAGES is not set ++CONFIG_ARM64_VA_BITS_39=y ++# CONFIG_ARM64_VA_BITS_48 is not set ++CONFIG_ARM64_VA_BITS=39 ++# CONFIG_CPU_BIG_ENDIAN is not set ++CONFIG_SCHED_MC=y ++# CONFIG_SCHED_SMT is not set ++CONFIG_NR_CPUS=64 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_NUMA is not set ++CONFIG_PREEMPT_NONE=y ++# CONFIG_PREEMPT_VOLUNTARY is not set ++# CONFIG_PREEMPT is not set ++# CONFIG_HZ_100 is not set ++# CONFIG_HZ_250 is not set ++# CONFIG_HZ_300 is not set ++CONFIG_HZ_1000=y ++CONFIG_HZ=1000 ++# CONFIG_SCHED_HRTICK is not set ++CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y ++CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y ++CONFIG_ARCH_SPARSEMEM_ENABLE=y ++CONFIG_ARCH_SPARSEMEM_DEFAULT=y ++CONFIG_ARCH_SELECT_MEMORY_MODEL=y ++CONFIG_HAVE_ARCH_PFN_VALID=y ++CONFIG_HW_PERF_EVENTS=y ++CONFIG_SYS_SUPPORTS_HUGETLBFS=y ++CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y ++CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_SPARSEMEM_MANUAL=y ++CONFIG_SPARSEMEM=y ++CONFIG_HAVE_MEMORY_PRESENT=y ++CONFIG_SPARSEMEM_EXTREME=y ++CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y ++CONFIG_SPARSEMEM_VMEMMAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=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=y ++CONFIG_BOUNCE=y ++CONFIG_KSM=y ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# CONFIG_TRANSPARENT_HUGEPAGE is not set ++# CONFIG_CLEANCACHE is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++# CONFIG_CMA_DEBUGFS is not set ++CONFIG_CMA_AREAS=7 ++# 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_FRAME_VECTOR=y ++# CONFIG_SECCOMP is not set ++# CONFIG_PARAVIRT is not set ++# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set ++# CONFIG_KEXEC is not set ++# CONFIG_XEN is not set ++CONFIG_FORCE_MAX_ZONEORDER=11 ++# CONFIG_ARMV8_DEPRECATED is not set ++ ++# ++# ARMv8.1 architectural features ++# ++CONFIG_ARM64_HW_AFDBM=y ++CONFIG_ARM64_PAN=y ++# CONFIG_ARM64_LSE_ATOMICS is not set ++CONFIG_ARM64_VHE=y ++ ++# ++# ARMv8.2 architectural features ++# ++CONFIG_ARM64_UAO=y ++CONFIG_ARM64_MODULE_CMODEL_LARGE=y ++# CONFIG_RANDOMIZE_BASE is not set ++ ++# ++# Boot options ++# ++CONFIG_CMDLINE="mem=128M console=ttyAMA0,115200 console=ttyMTD,blackbox" ++# CONFIG_CMDLINE_FORCE is not set ++# CONFIG_EFI is not set ++CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y ++CONFIG_IMG_GZ_DTB=y ++# CONFIG_IMG_DTB is not set ++CONFIG_BUILD_ARM64_APPENDED_KERNEL_IMAGE_NAME="Image.gz-dtb" ++CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES="hisilicon/hi3559av100-demb-flash" ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_COMPAT_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++CONFIG_COMPAT=y ++CONFIG_SYSVIPC_COMPAT=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_SUSPEND_SKIP_SYNC is not set ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++CONFIG_PM_CLK=y ++CONFIG_PM_GENERIC_DOMAINS=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_PM_GENERIC_DOMAINS_SLEEP=y ++CONFIG_PM_GENERIC_DOMAINS_OF=y ++CONFIG_CPU_PM=y ++CONFIG_ARCH_HIBERNATION_POSSIBLE=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Idle ++# ++# CONFIG_CPU_IDLE is not set ++# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_ATTR_SET=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_STAT_DETAILS=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set ++ ++# ++# CPU frequency scaling drivers ++# ++# CONFIG_CPUFREQ_DT is not set ++# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++CONFIG_NET=y ++CONFIG_NET_INGRESS=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 is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++CONFIG_NET_IP_TUNNEL=m ++# 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=m ++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=y ++# CONFIG_IPV6_ROUTE_INFO 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_IPV6_ILA is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# 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=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++CONFIG_NETFILTER_INGRESS=y ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_DUP_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_DUP_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_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_QRTR is not set ++# CONFIG_NET_NCSI is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_SOCK_CGROUP_DATA is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_EBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER=y ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++# CONFIG_DEVTMPFS is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_GENERIC_CPU_AUTOPROBE=y ++CONFIG_REGMAP=y ++CONFIG_REGMAP_I2C=y ++CONFIG_REGMAP_SPI=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=4 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_ARM_CCI400_PMU is not set ++# CONFIG_ARM_CCI5xx_PMU is not set ++# CONFIG_ARM_CCN is not set ++# CONFIG_QCOM_EBI2 is not set ++# CONFIG_SIMPLE_PM_BUS 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 ++# CONFIG_MTD_BCM63XX_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_TS5500 is not set ++# CONFIG_MTD_INTEL_VR_NOR is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_DATAFLASH is not set ++# 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=y ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOCG3 is not set ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_PCI is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_RICOH is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_VF610_NFC is not set ++# CONFIG_MTD_NAND_SH_FLCTL is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++# CONFIG_MTD_SPI_NAND_HISI_BVT is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++CONFIG_MTD_NAND_HIFMC100=y ++# CONFIG_HIFMC100_NAND_EDO_MODE is not set ++CONFIG_RW_H_WIDTH=10 ++CONFIG_R_L_WIDTH=10 ++CONFIG_W_L_WIDTH=10 ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# LPDDR & LPDDR2 PCM memory drivers ++# ++# CONFIG_MTD_LPDDR is not set ++# CONFIG_MTD_SPI_NOR is not set ++# CONFIG_MTD_UBI is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++# CONFIG_OF_UNITTEST is not set ++# CONFIG_OF_ALL_DTBS is not set ++CONFIG_OF_FLATTREE=y ++CONFIG_OF_EARLY_FLATTREE=y ++CONFIG_OF_ADDRESS=y ++CONFIG_OF_ADDRESS_PCI=y ++CONFIG_OF_IRQ=y ++CONFIG_OF_NET=y ++CONFIG_OF_MDIO=y ++CONFIG_OF_PCI=y ++CONFIG_OF_PCI_IRQ=y ++CONFIG_OF_RESERVED_MEM=y ++# CONFIG_OF_OVERLAY is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set ++# CONFIG_BLK_CPQ_CISS_DA is not set ++# CONFIG_BLK_DEV_DAC960 is not set ++# CONFIG_BLK_DEV_UMEM is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_SKD is not set ++# CONFIG_BLK_DEV_SX8 is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_BLK_DEV_RSXX is not set ++# CONFIG_BLK_DEV_NVME is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# CONFIG_SENSORS_LIS3LV02D is not set ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_DUMMY_IRQ is not set ++# CONFIG_PHANTOM is not set ++# CONFIG_INTEL_MID_PTI is not set ++# CONFIG_SGI_IOC4 is not set ++# CONFIG_TIFM_CORE is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ATMEL_SSC is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_HP_ILO is not set ++# CONFIG_QCOM_COINCELL 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_PCH_PHUB 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 ++# CONFIG_CB710_CORE 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_GENWQE is not set ++# 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=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_SCSI_CXGB3_ISCSI is not set ++# CONFIG_SCSI_CXGB4_ISCSI is not set ++# CONFIG_SCSI_BNX2_ISCSI is not set ++# CONFIG_BE2ISCSI is not set ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_HPSA is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_3W_SAS is not set ++# CONFIG_SCSI_ACARD is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX is not set ++# CONFIG_SCSI_AIC79XX is not set ++# CONFIG_SCSI_AIC94XX is not set ++# CONFIG_SCSI_HISI_SAS is not set ++# CONFIG_SCSI_MVSAS is not set ++# CONFIG_SCSI_MVUMI is not set ++# CONFIG_SCSI_ADVANSYS is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_SCSI_ESAS2R is not set ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++# CONFIG_SCSI_MPT3SAS is not set ++# CONFIG_SCSI_MPT2SAS is not set ++# CONFIG_SCSI_SMARTPQI is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_SCSI_HPTIOP is not set ++# CONFIG_SCSI_SNIC is not set ++# CONFIG_SCSI_DMX3191D is not set ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_IPS is not set ++# CONFIG_SCSI_INITIO is not set ++# CONFIG_SCSI_INIA100 is not set ++# CONFIG_SCSI_STEX is not set ++# CONFIG_SCSI_SYM53C8XX_2 is not set ++# CONFIG_SCSI_QLOGIC_1280 is not set ++# CONFIG_SCSI_QLA_ISCSI is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_AM53C974 is not set ++# CONFIG_SCSI_WD719X is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_PMCRAID is not set ++# CONFIG_SCSI_PM8001 is not set ++# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HAVE_PATA_PLATFORM=y ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++# CONFIG_FUSION is not set ++ ++# ++# IEEE 1394 (FireWire) support ++# ++# CONFIG_FIREWIRE is not set ++# CONFIG_FIREWIRE_NOSY is not set ++CONFIG_NETDEVICES=y ++CONFIG_NET_CORE=y ++# CONFIG_BONDING is not set ++# CONFIG_DUMMY is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC 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 ++# CONFIG_ARCNET is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++CONFIG_ETHERNET=y ++CONFIG_NET_VENDOR_3COM=y ++# CONFIG_VORTEX is not set ++# CONFIG_TYPHOON is not set ++CONFIG_NET_VENDOR_ADAPTEC=y ++# CONFIG_ADAPTEC_STARFIRE is not set ++CONFIG_NET_VENDOR_AGERE=y ++# CONFIG_ET131X is not set ++CONFIG_NET_VENDOR_ALTEON=y ++# CONFIG_ACENIC is not set ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_VENDOR_AMAZON is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC is not set ++CONFIG_NET_VENDOR_ATHEROS=y ++# CONFIG_ATL2 is not set ++# CONFIG_ATL1 is not set ++# CONFIG_ATL1E is not set ++# CONFIG_ATL1C is not set ++# CONFIG_ALX 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_BROCADE=y ++# CONFIG_BNA is not set ++# CONFIG_NET_CALXEDA_XGMAC is not set ++CONFIG_NET_VENDOR_CAVIUM=y ++# CONFIG_THUNDER_NIC_PF is not set ++# CONFIG_THUNDER_NIC_VF is not set ++# CONFIG_THUNDER_NIC_BGX is not set ++# CONFIG_THUNDER_NIC_RGX is not set ++# CONFIG_LIQUIDIO is not set ++CONFIG_NET_VENDOR_CHELSIO=y ++# CONFIG_CHELSIO_T1 is not set ++# CONFIG_CHELSIO_T3 is not set ++# CONFIG_CHELSIO_T4 is not set ++# CONFIG_CHELSIO_T4VF is not set ++CONFIG_NET_VENDOR_CISCO=y ++# CONFIG_ENIC is not set ++# CONFIG_CX_ECAT is not set ++# CONFIG_DNET is not set ++CONFIG_NET_VENDOR_DEC=y ++# CONFIG_NET_TULIP is not set ++CONFIG_NET_VENDOR_DLINK=y ++# CONFIG_DL2K is not set ++# CONFIG_SUNDANCE is not set ++CONFIG_NET_VENDOR_EMULEX=y ++# CONFIG_BE2NET is not set ++# CONFIG_NET_VENDOR_EZCHIP is not set ++CONFIG_NET_VENDOR_EXAR=y ++# CONFIG_S2IO is not set ++# CONFIG_VXGE is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DDR_64BIT=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++CONFIG_NET_VENDOR_HP=y ++# CONFIG_HP100 is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_JME is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++CONFIG_NET_VENDOR_MELLANOX=y ++# CONFIG_MLX4_EN is not set ++# CONFIG_MLX4_CORE is not set ++# CONFIG_MLX5_CORE is not set ++# CONFIG_MLXSW_CORE is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_MICROCHIP is not set ++CONFIG_NET_VENDOR_MYRI=y ++# CONFIG_MYRI10GE is not set ++# CONFIG_FEALNX is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NETRONOME is not set ++CONFIG_NET_VENDOR_NVIDIA=y ++# CONFIG_FORCEDETH is not set ++CONFIG_NET_VENDOR_OKI=y ++# CONFIG_PCH_GBE is not set ++# CONFIG_ETHOC is not set ++CONFIG_NET_PACKET_ENGINE=y ++# CONFIG_HAMACHI is not set ++# CONFIG_YELLOWFIN is not set ++CONFIG_NET_VENDOR_QLOGIC=y ++# CONFIG_QLA3XXX is not set ++# CONFIG_QLCNIC is not set ++# CONFIG_QLGE is not set ++# CONFIG_NETXEN_NIC is not set ++# CONFIG_QED is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++CONFIG_NET_VENDOR_REALTEK=y ++# CONFIG_8139CP is not set ++# CONFIG_8139TOO is not set ++# CONFIG_R8169 is not set ++# CONFIG_NET_VENDOR_RENESAS is not set ++CONFIG_NET_VENDOR_RDC=y ++# CONFIG_R6040 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_SILAN=y ++# CONFIG_SC92031 is not set ++CONFIG_NET_VENDOR_SIS=y ++# CONFIG_SIS900 is not set ++# CONFIG_SIS190 is not set ++# CONFIG_SFC is not set ++# CONFIG_NET_VENDOR_SMSC is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++CONFIG_NET_VENDOR_SUN=y ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++# CONFIG_NIU is not set ++# CONFIG_NET_VENDOR_SYNOPSYS is not set ++CONFIG_NET_VENDOR_TEHUTI=y ++# CONFIG_TEHUTI is not set ++CONFIG_NET_VENDOR_TI=y ++# CONFIG_TI_CPSW_ALE is not set ++# CONFIG_TLAN is not set ++# CONFIG_NET_VENDOR_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_FDDI is not set ++# CONFIG_HIPPI is not set ++CONFIG_PHYLIB=y ++CONFIG_SWPHY=y ++ ++# ++# MDIO bus device drivers ++# ++# CONFIG_MDIO_BCM_IPROC is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_BCM_IPROC 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 ++CONFIG_MDIO_HISI_GEMAC=y ++# CONFIG_MDIO_OCTEON is not set ++# CONFIG_MDIO_THUNDER is not set ++# CONFIG_MDIO_XGENE 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_IPHETH is not set ++CONFIG_WLAN=y ++CONFIG_WLAN_VENDOR_ADMTEK=y ++CONFIG_WLAN_VENDOR_ATH=y ++# CONFIG_ATH_DEBUG is not set ++# CONFIG_ATH5K_PCI is not set ++CONFIG_WLAN_VENDOR_ATMEL=y ++CONFIG_WLAN_VENDOR_BROADCOM=y ++CONFIG_WLAN_VENDOR_CISCO=y ++CONFIG_WLAN_VENDOR_INTEL=y ++CONFIG_WLAN_VENDOR_INTERSIL=y ++# CONFIG_HOSTAP is not set ++# CONFIG_PRISM54 is not set ++CONFIG_WLAN_VENDOR_MARVELL=y ++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 ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_VMXNET3 is not set ++# CONFIG_ISDN is not set ++# CONFIG_NVM is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++CONFIG_INPUT_FF_MEMLESS=y ++# CONFIG_INPUT_POLLDEV is not set ++# CONFIG_INPUT_SPARSEKMAP is not set ++# CONFIG_INPUT_MATRIXKMAP is not set ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_CLPS711X is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_GOLDFISH_EVENTS is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_ST_KEYSCAN is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_SH_KEYSC is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++CONFIG_INPUT_JOYSTICK=y ++# CONFIG_JOYSTICK_ANALOG is not set ++# CONFIG_JOYSTICK_A3D is not set ++# CONFIG_JOYSTICK_ADI is not set ++# CONFIG_JOYSTICK_COBRA is not set ++# CONFIG_JOYSTICK_GF2K is not set ++# CONFIG_JOYSTICK_GRIP is not set ++# CONFIG_JOYSTICK_GRIP_MP is not set ++# CONFIG_JOYSTICK_GUILLEMOT is not set ++# CONFIG_JOYSTICK_INTERACT is not set ++# CONFIG_JOYSTICK_SIDEWINDER is not set ++# CONFIG_JOYSTICK_TMDC is not set ++# CONFIG_JOYSTICK_IFORCE is not set ++# CONFIG_JOYSTICK_WARRIOR is not set ++# CONFIG_JOYSTICK_MAGELLAN is not set ++# CONFIG_JOYSTICK_SPACEORB is not set ++# CONFIG_JOYSTICK_SPACEBALL is not set ++# CONFIG_JOYSTICK_STINGER is not set ++# CONFIG_JOYSTICK_TWIDJOY is not set ++# CONFIG_JOYSTICK_ZHENHUA is not set ++# CONFIG_JOYSTICK_AS5011 is not set ++# CONFIG_JOYSTICK_JOYDUMP is not set ++# CONFIG_JOYSTICK_XPAD is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_GP2A is not set ++# CONFIG_INPUT_GPIO_BEEPER is not set ++# CONFIG_INPUT_GPIO_TILT_POLLED is not set ++# CONFIG_INPUT_GPIO_DECODER is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INPUT_CM109 is not set ++# CONFIG_INPUT_REGULATOR_HAPTIC is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV260X_HAPTICS is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_INPUT_HISI_POWERKEY is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_SERIO_OLPC_APSP is not set ++# CONFIG_SERIO_SUN4I_PS2 is not set ++# CONFIG_USERIO is not set ++CONFIG_GAMEPORT=y ++# CONFIG_GAMEPORT_NS558 is not set ++# CONFIG_GAMEPORT_L4 is not set ++# CONFIG_GAMEPORT_EMU10K1 is not set ++# CONFIG_GAMEPORT_FM801 is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_NOZOMI is not set ++# CONFIG_N_GSM is not set ++# CONFIG_TRACE_SINK is not set ++CONFIG_DEVMEM=y ++CONFIG_DEVKMEM=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_ATMEL is not set ++# CONFIG_SERIAL_CLPS711X is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X is not set ++# CONFIG_SERIAL_IMX is not set ++# CONFIG_SERIAL_UARTLITE is not set ++# CONFIG_SERIAL_SH_SCI is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_JSM is not set ++# CONFIG_SERIAL_SCCNXP is not set ++# CONFIG_SERIAL_SC16IS7XX is not set ++# CONFIG_SERIAL_TIMBERDALE is not set ++# CONFIG_SERIAL_BCM63XX is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_IFX6X60 is not set ++# CONFIG_SERIAL_PCH_UART is not set ++# CONFIG_SERIAL_MXS_AUART is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++# CONFIG_SERIAL_MPS2_UART is not set ++# CONFIG_SERIAL_ARC is not set ++# CONFIG_SERIAL_RP2 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_SERIAL_MVEBU_UART 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_APPLICOM is not set ++ ++# ++# PCMCIA character devices ++# ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_DEVPORT=y ++# 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=y ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set ++# CONFIG_I2C_MUX_GPIO is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PCA954x is not set ++# CONFIG_I2C_MUX_PINCTRL is not set ++# CONFIG_I2C_MUX_REG is not set ++# CONFIG_I2C_DEMUX_PINCTRL 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 ++# ++ ++# ++# PC SMBus host controller drivers ++# ++# CONFIG_I2C_ALI1535 is not set ++# CONFIG_I2C_ALI1563 is not set ++# CONFIG_I2C_ALI15X3 is not set ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++# CONFIG_I2C_HIX5HD2 is not set ++# CONFIG_I2C_I801 is not set ++# CONFIG_I2C_ISCH is not set ++# CONFIG_I2C_PIIX4 is not set ++# CONFIG_I2C_NFORCE2 is not set ++# CONFIG_I2C_SIS5595 is not set ++# CONFIG_I2C_SIS630 is not set ++# CONFIG_I2C_SIS96X is not set ++# CONFIG_I2C_VIA is not set ++# CONFIG_I2C_VIAPRO is not set ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_AXXIA is not set ++# CONFIG_I2C_BCM_IPROC is not set ++# CONFIG_I2C_BRCMSTB is not set ++# CONFIG_I2C_CADENCE is not set ++# CONFIG_I2C_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_DESIGNWARE_PCI is not set ++# CONFIG_I2C_EFM32 is not set ++# CONFIG_I2C_EG20T is not set ++# CONFIG_I2C_EMEV2 is not set ++# CONFIG_I2C_GPIO is not set ++CONFIG_I2C_HIBVT=y ++# CONFIG_I2C_IMG is not set ++# CONFIG_I2C_JZ4780 is not set ++# CONFIG_I2C_LPC2K is not set ++# CONFIG_I2C_MESON is not set ++# CONFIG_I2C_MT65XX is not set ++# CONFIG_I2C_NOMADIK 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_RIIC is not set ++# CONFIG_I2C_RK3X is not set ++# CONFIG_I2C_SH_MOBILE is not set ++# CONFIG_I2C_SIMTEC is not set ++# CONFIG_I2C_SUN6I_P2WI is not set ++# CONFIG_I2C_UNIPHIER is not set ++# CONFIG_I2C_UNIPHIER_F is not set ++# CONFIG_I2C_VERSATILE is not set ++# CONFIG_I2C_THUNDERX is not set ++# CONFIG_I2C_XILINX is not set ++# CONFIG_I2C_XLP9XX is not set ++# CONFIG_I2C_RCAR 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_DMA_MSG_MIN_LEN=5 ++CONFIG_DMA_MSG_MAX_LEN=4090 ++# 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_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_ATMEL is not set ++# CONFIG_SPI_AXI_SPI_ENGINE is not set ++# CONFIG_SPI_BCM2835 is not set ++# CONFIG_SPI_BCM2835AUX is not set ++# CONFIG_SPI_BCM63XX is not set ++# CONFIG_SPI_BCM63XX_HSSPI is not set ++# CONFIG_SPI_BCM_QSPI is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_CLPS711X is not set ++# CONFIG_SPI_DESIGNWARE is not set ++# CONFIG_SPI_EP93XX is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_IMG_SPFI is not set ++# CONFIG_SPI_IMX is not set ++# CONFIG_SPI_JCORE is not set ++# CONFIG_SPI_LP8841_RTC is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_FSL_DSPI is not set ++# CONFIG_SPI_MESON_SPIFC is not set ++# CONFIG_SPI_MT65XX is not set ++# CONFIG_SPI_OC_TINY is not set ++# CONFIG_SPI_OMAP24XX is not set ++# CONFIG_SPI_TI_QSPI is not set ++# CONFIG_SPI_OMAP_100K is not set ++# CONFIG_SPI_ORION is not set ++# CONFIG_SPI_PIC32 is not set ++# CONFIG_SPI_PIC32_SQI is not set ++CONFIG_SPI_PL022=y ++# CONFIG_SPI_PXA2XX is not set ++# CONFIG_SPI_PXA2XX_PCI is not set ++# CONFIG_SPI_ROCKCHIP is not set ++# CONFIG_SPI_RSPI is not set ++# CONFIG_SPI_SC18IS602 is not set ++# CONFIG_SPI_SH_MSIOF is not set ++# CONFIG_SPI_SH is not set ++# CONFIG_SPI_SH_HSPI is not set ++# CONFIG_SPI_ST_SSC4 is not set ++# CONFIG_SPI_SUN4I is not set ++# CONFIG_SPI_SUN6I is not set ++# CONFIG_SPI_TEGRA114 is not set ++# CONFIG_SPI_TEGRA20_SFLASH is not set ++# CONFIG_SPI_TEGRA20_SLINK is not set ++# CONFIG_SPI_THUNDERX is not set ++# CONFIG_SPI_TOPCLIFF_PCH is not set ++# CONFIG_SPI_TXX9 is not set ++# CONFIG_SPI_XCOMM is not set ++# CONFIG_SPI_XILINX is not set ++# CONFIG_SPI_XLP is not set ++# CONFIG_SPI_XTENSA_XTFPGA is not set ++# CONFIG_SPI_ZYNQMP_GQSPI is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_PTP_1588_CLOCK_PCH is not set ++CONFIG_PINCTRL=y ++ ++# ++# Pin controllers ++# ++CONFIG_PINMUX=y ++CONFIG_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++# CONFIG_PINCTRL_AMD is not set ++# CONFIG_PINCTRL_LPC18XX is not set ++CONFIG_PINCTRL_SINGLE=y ++# CONFIG_PINCTRL_ASPEED_G4 is not set ++# CONFIG_PINCTRL_ASPEED_G5 is not set ++# CONFIG_PINCTRL_BCM281XX is not set ++# CONFIG_PINCTRL_IPROC_GPIO is not set ++# CONFIG_PINCTRL_CYGNUS_MUX is not set ++# CONFIG_PINCTRL_NSP_GPIO is not set ++# CONFIG_PINCTRL_NS2_MUX is not set ++# CONFIG_PINCTRL_NSP_MUX is not set ++# CONFIG_PINCTRL_BERLIN_BG2 is not set ++# CONFIG_PINCTRL_BERLIN_BG2CD is not set ++# CONFIG_PINCTRL_BERLIN_BG2Q is not set ++# CONFIG_PINCTRL_BERLIN_BG4CT is not set ++# CONFIG_PINCTRL_PXA25X is not set ++# CONFIG_PINCTRL_PXA27X is not set ++# CONFIG_PINCTRL_APQ8064 is not set ++# CONFIG_PINCTRL_APQ8084 is not set ++# CONFIG_PINCTRL_IPQ4019 is not set ++# CONFIG_PINCTRL_IPQ8064 is not set ++# CONFIG_PINCTRL_MSM8660 is not set ++# CONFIG_PINCTRL_MSM8960 is not set ++# CONFIG_PINCTRL_MDM9615 is not set ++# CONFIG_PINCTRL_MSM8X74 is not set ++# CONFIG_PINCTRL_MSM8916 is not set ++# CONFIG_PINCTRL_MSM8996 is not set ++# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set ++# CONFIG_PINCTRL_STM32F429 is not set ++# CONFIG_PINCTRL_STM32F746 is not set ++# CONFIG_PINCTRL_UNIPHIER is not set ++# CONFIG_PINCTRL_MT2701 is not set ++# CONFIG_PINCTRL_MT7623 is not set ++# CONFIG_PINCTRL_MT8135 is not set ++# CONFIG_PINCTRL_MT8127 is not set ++# CONFIG_PINCTRL_MT8173 is not set ++# CONFIG_PINCTRL_MT6397 is not set ++CONFIG_GPIOLIB=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_GENERIC=y ++ ++# ++# Memory mapped GPIO drivers ++# ++# CONFIG_GPIO_74XX_MMIO is not set ++# CONFIG_GPIO_ALTERA is not set ++# CONFIG_GPIO_ASPEED is not set ++# CONFIG_GPIO_ATH79 is not set ++# CONFIG_GPIO_BCM_KONA is not set ++# CONFIG_GPIO_BRCMSTB is not set ++# CONFIG_GPIO_CLPS711X is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_ETRAXFS is not set ++CONFIG_GPIO_GENERIC_PLATFORM=y ++# CONFIG_GPIO_GRGPIO is not set ++# CONFIG_GPIO_IOP is not set ++# CONFIG_GPIO_LPC18XX is not set ++# CONFIG_GPIO_MB86S7X is not set ++# CONFIG_GPIO_MOCKUP is not set ++# CONFIG_GPIO_MOXART is not set ++# CONFIG_GPIO_MPC8XXX is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_RCAR is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_TEGRA is not set ++# CONFIG_GPIO_TS4800 is not set ++# CONFIG_GPIO_VX855 is not set ++# CONFIG_GPIO_XGENE is not set ++# CONFIG_GPIO_XILINX is not set ++# CONFIG_GPIO_XLP 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 ++# ++ ++# ++# PCI GPIO expanders ++# ++# CONFIG_GPIO_AMD8111 is not set ++# CONFIG_GPIO_BT8XX is not set ++# CONFIG_GPIO_ML_IOH is not set ++# CONFIG_GPIO_PCH is not set ++# CONFIG_GPIO_RDC321X 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++# CONFIG_POWER_RESET_HISI is not set ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_XGENE is not set ++# CONFIG_POWER_RESET_KEYSTONE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_POWER_RESET_RMOBILE is not set ++# CONFIG_POWER_RESET_ZX is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_ACT8945A is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_MANAGER is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24257 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_BQ25890 is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_BATTERY_GOLDFISH is not set ++# CONFIG_CHARGER_RT9455 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_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_MX25_TSADC is not set ++# CONFIG_MFD_HI6421_PMIC is not set ++# CONFIG_MFD_HI655X_PMIC is not set ++CONFIG_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_HTC_I2CPLD is not set ++# CONFIG_LPC_ICH is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_INTEL_SOC_PMIC is not set ++# CONFIG_MFD_JANZ_CMODIO 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_RDC321X is not set ++# CONFIG_MFD_RTSX_PCI 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=y ++# 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_TIMBERDALE is not set ++# CONFIG_MFD_TC3589X is not set ++# CONFIG_MFD_TMIO is not set ++# CONFIG_MFD_VX855 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_MFD_STW481X is not set ++CONFIG_REGULATOR=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_LTC3676 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MT6311 is not set ++# CONFIG_REGULATOR_PBIAS is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_PV88060 is not set ++# CONFIG_REGULATOR_PV88080 is not set ++# CONFIG_REGULATOR_PV88090 is not set ++# CONFIG_REGULATOR_QCOM_SPMI is not set ++# CONFIG_REGULATOR_STW481X_VMMC is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=y ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=y ++CONFIG_VIDEO_V4L2=y ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=y ++CONFIG_VIDEOBUF2_MEMOPS=y ++CONFIG_VIDEOBUF2_VMALLOC=y ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++CONFIG_MEDIA_USB_SUPPORT=y ++ ++# ++# Webcam devices ++# ++CONFIG_USB_VIDEO_CLASS=y ++CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y ++CONFIG_USB_GSPCA=m ++# CONFIG_USB_M5602 is not set ++# CONFIG_USB_STV06XX is not set ++# CONFIG_USB_GL860 is not set ++# CONFIG_USB_GSPCA_BENQ is not set ++# CONFIG_USB_GSPCA_CONEX is not set ++# CONFIG_USB_GSPCA_CPIA1 is not set ++# CONFIG_USB_GSPCA_DTCS033 is not set ++# CONFIG_USB_GSPCA_ETOMS is not set ++# CONFIG_USB_GSPCA_FINEPIX is not set ++# CONFIG_USB_GSPCA_JEILINJ is not set ++# CONFIG_USB_GSPCA_JL2005BCD is not set ++# CONFIG_USB_GSPCA_KINECT is not set ++# CONFIG_USB_GSPCA_KONICA is not set ++# CONFIG_USB_GSPCA_MARS is not set ++# CONFIG_USB_GSPCA_MR97310A is not set ++# CONFIG_USB_GSPCA_NW80X is not set ++# CONFIG_USB_GSPCA_OV519 is not set ++# CONFIG_USB_GSPCA_OV534 is not set ++# CONFIG_USB_GSPCA_OV534_9 is not set ++# CONFIG_USB_GSPCA_PAC207 is not set ++# CONFIG_USB_GSPCA_PAC7302 is not set ++# CONFIG_USB_GSPCA_PAC7311 is not set ++# CONFIG_USB_GSPCA_SE401 is not set ++# CONFIG_USB_GSPCA_SN9C2028 is not set ++# CONFIG_USB_GSPCA_SN9C20X is not set ++# CONFIG_USB_GSPCA_SONIXB is not set ++# CONFIG_USB_GSPCA_SONIXJ is not set ++# CONFIG_USB_GSPCA_SPCA500 is not set ++# CONFIG_USB_GSPCA_SPCA501 is not set ++# CONFIG_USB_GSPCA_SPCA505 is not set ++# CONFIG_USB_GSPCA_SPCA506 is not set ++# CONFIG_USB_GSPCA_SPCA508 is not set ++# CONFIG_USB_GSPCA_SPCA561 is not set ++# CONFIG_USB_GSPCA_SPCA1528 is not set ++# CONFIG_USB_GSPCA_SQ905 is not set ++# CONFIG_USB_GSPCA_SQ905C is not set ++# CONFIG_USB_GSPCA_SQ930X is not set ++# CONFIG_USB_GSPCA_STK014 is not set ++# CONFIG_USB_GSPCA_STK1135 is not set ++# CONFIG_USB_GSPCA_STV0680 is not set ++# CONFIG_USB_GSPCA_SUNPLUS is not set ++# CONFIG_USB_GSPCA_T613 is not set ++# CONFIG_USB_GSPCA_TOPRO is not set ++# CONFIG_USB_GSPCA_TOUPTEK is not set ++# CONFIG_USB_GSPCA_TV8532 is not set ++# CONFIG_USB_GSPCA_VC032X is not set ++# CONFIG_USB_GSPCA_VICAM is not set ++# CONFIG_USB_GSPCA_XIRLINK_CIT is not set ++# CONFIG_USB_GSPCA_ZC3XX is not set ++# CONFIG_USB_PWC is not set ++# CONFIG_VIDEO_CPIA2 is not set ++# CONFIG_USB_ZR364XX is not set ++# CONFIG_USB_STKWEBCAM is not set ++# CONFIG_USB_S2255 is not set ++ ++# ++# Webcam, TV (analog/digital) USB devices ++# ++# CONFIG_VIDEO_EM28XX is not set ++# CONFIG_MEDIA_PCI_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, spi, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# I2C Encoders, decoders, sensors and other helper chips ++# ++ ++# ++# Audio decoders, processors and mixers ++# ++# CONFIG_VIDEO_TVAUDIO is not set ++# CONFIG_VIDEO_TDA7432 is not set ++# CONFIG_VIDEO_TDA9840 is not set ++# CONFIG_VIDEO_TEA6415C is not set ++# CONFIG_VIDEO_TEA6420 is not set ++# CONFIG_VIDEO_MSP3400 is not set ++# CONFIG_VIDEO_CS3308 is not set ++# CONFIG_VIDEO_CS5345 is not set ++# CONFIG_VIDEO_CS53L32A is not set ++# CONFIG_VIDEO_TLV320AIC23B is not set ++# CONFIG_VIDEO_UDA1342 is not set ++# CONFIG_VIDEO_WM8775 is not set ++# CONFIG_VIDEO_WM8739 is not set ++# CONFIG_VIDEO_VP27SMPX is not set ++# CONFIG_VIDEO_SONY_BTF_MPX is not set ++ ++# ++# RDS decoders ++# ++# CONFIG_VIDEO_SAA6588 is not set ++ ++# ++# Video decoders ++# ++# CONFIG_VIDEO_ADV7183 is not set ++# CONFIG_VIDEO_BT819 is not set ++# CONFIG_VIDEO_BT856 is not set ++# CONFIG_VIDEO_BT866 is not set ++# CONFIG_VIDEO_KS0127 is not set ++# CONFIG_VIDEO_ML86V7667 is not set ++# CONFIG_VIDEO_SAA7110 is not set ++# CONFIG_VIDEO_SAA711X is not set ++# CONFIG_VIDEO_TVP514X is not set ++# CONFIG_VIDEO_TVP5150 is not set ++# CONFIG_VIDEO_TVP7002 is not set ++# CONFIG_VIDEO_TW2804 is not set ++# CONFIG_VIDEO_TW9903 is not set ++# CONFIG_VIDEO_TW9906 is not set ++# CONFIG_VIDEO_VPX3220 is not set ++ ++# ++# Video and audio decoders ++# ++# CONFIG_VIDEO_SAA717X is not set ++# CONFIG_VIDEO_CX25840 is not set ++ ++# ++# Video encoders ++# ++# CONFIG_VIDEO_SAA7127 is not set ++# CONFIG_VIDEO_SAA7185 is not set ++# CONFIG_VIDEO_ADV7170 is not set ++# CONFIG_VIDEO_ADV7175 is not set ++# CONFIG_VIDEO_ADV7343 is not set ++# CONFIG_VIDEO_ADV7393 is not set ++# CONFIG_VIDEO_AK881X is not set ++# CONFIG_VIDEO_THS8200 is not set ++ ++# ++# Camera sensor devices ++# ++# CONFIG_VIDEO_OV2659 is not set ++# CONFIG_VIDEO_OV7640 is not set ++# CONFIG_VIDEO_OV7670 is not set ++# CONFIG_VIDEO_VS6624 is not set ++# CONFIG_VIDEO_MT9M111 is not set ++# CONFIG_VIDEO_MT9V011 is not set ++# CONFIG_VIDEO_SR030PC30 is not set ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++# CONFIG_VIDEO_UPD64031A is not set ++# CONFIG_VIDEO_UPD64083 is not set ++ ++# ++# Audio/Video compression chips ++# ++# CONFIG_VIDEO_SAA6752HS is not set ++ ++# ++# Miscellaneous helper chips ++# ++# CONFIG_VIDEO_THS7303 is not set ++# CONFIG_VIDEO_M52790 is not set ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# SPI helper chips ++# ++ ++# ++# Customise DVB Frontends ++# ++# CONFIG_DVB_AU8522_V4L is not set ++# CONFIG_DVB_TUNER_DIB0070 is not set ++# CONFIG_DVB_TUNER_DIB0090 is not set ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++CONFIG_VGA_ARB=y ++CONFIG_VGA_ARB_MAX_GPUS=16 ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_CIRRUS is not set ++# CONFIG_FB_PM2 is not set ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CLPS711X is not set ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_NVIDIA is not set ++# CONFIG_FB_RIVA is not set ++# CONFIG_FB_I740 is not set ++# CONFIG_FB_MATROX is not set ++# CONFIG_FB_RADEON is not set ++# CONFIG_FB_ATY128 is not set ++# CONFIG_FB_ATY is not set ++# CONFIG_FB_S3 is not set ++# CONFIG_FB_SAVAGE is not set ++# CONFIG_FB_SIS is not set ++# CONFIG_FB_NEOMAGIC is not set ++# CONFIG_FB_KYRO is not set ++# CONFIG_FB_3DFX is not set ++# CONFIG_FB_VOODOO1 is not set ++# CONFIG_FB_VT8623 is not set ++# CONFIG_FB_TRIDENT is not set ++# CONFIG_FB_ARK is not set ++# CONFIG_FB_PM3 is not set ++# CONFIG_FB_CARMINE is not set ++# CONFIG_FB_TMIO is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_GOLDFISH is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_MB862XX is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_FB_SM712 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++CONFIG_DUMMY_CONSOLE_COLUMNS=80 ++CONFIG_DUMMY_CONSOLE_ROWS=25 ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++# CONFIG_HID_BETOP_FF is not set ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# 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 is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PCI=y ++CONFIG_USB_XHCI_PLATFORM=y ++# CONFIG_USB_XHCI_MTK is not set ++# CONFIG_USB_XHCI_MVEBU is not set ++# CONFIG_USB_XHCI_RCAR 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_UHCI_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 ++# CONFIG_USB_RENESAS_USBHS is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++# CONFIG_USB_WDM is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++# CONFIG_USBIP_CORE is not set ++# CONFIG_USB_MUSB_HDRC is not set ++CONFIG_USB_DWC3=y ++# CONFIG_USB_DWC3_HOST is not set ++CONFIG_USB_DWC3_GADGET=y ++# CONFIG_USB_DWC3_DUAL_ROLE is not set ++ ++# ++# Platform Glue Driver Support ++# ++CONFIG_USB_DWC3_EXYNOS=y ++CONFIG_USB_DWC3_PCI=y ++CONFIG_USB_DWC3_KEYSTONE=y ++CONFIG_USB_DWC3_OF_SIMPLE=y ++# CONFIG_USB_DWC2 is not set ++# CONFIG_USB_CHIPIDEA 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++# CONFIG_USB_GADGET_DEBUG_FS is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_RENESAS_USB3 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_BDC_UDC is not set ++# CONFIG_USB_AMD5536UDC is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_NET2280 is not set ++# CONFIG_USB_GOKU is not set ++# CONFIG_USB_EG20T is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_MASS_STORAGE=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM 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_ARMMMCI is not set ++CONFIG_MMC_SDHCI=y ++# CONFIG_MMC_SDHCI_PCI is not set ++CONFIG_MMC_SDHCI_PLTFM=y ++# CONFIG_MMC_SDHCI_OF_ARASAN is not set ++# CONFIG_MMC_SDHCI_OF_AT91 is not set ++CONFIG_MMC_SDHCI_HISI=y ++# CONFIG_MMC_SDHCI_PXAV3 is not set ++# CONFIG_MMC_SDHCI_PXAV2 is not set ++# CONFIG_MMC_SDHCI_F_SDH30 is not set ++# CONFIG_MMC_SDHCI_IPROC is not set ++# CONFIG_MMC_OMAP_HS is not set ++# CONFIG_MMC_TIFM_SD is not set ++# CONFIG_MMC_GOLDFISH is not set ++# CONFIG_MMC_SPI is not set ++# CONFIG_MMC_SDHI is not set ++# CONFIG_MMC_CB710 is not set ++# CONFIG_MMC_VIA_SDMMC is not set ++# CONFIG_MMC_DW is not set ++# CONFIG_MMC_SH_MMCIF is not set ++# CONFIG_MMC_VUB300 is not set ++# CONFIG_MMC_USHC is not set ++# CONFIG_MMC_USDHI6ROL0 is not set ++# CONFIG_MMC_TOSHIBA_PCI 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_INFINIBAND is not set ++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=y ++ ++# ++# SPI and I2C RTC drivers ++# ++# CONFIG_RTC_DRV_DS3232 is not set ++# CONFIG_RTC_DRV_PCF2127 is not set ++# CONFIG_RTC_DRV_RV3029C2 is not set ++ ++# ++# Platform RTC drivers ++# ++CONFIG_RTC_DRV_HIBVT=y ++# 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_SPEAR is not set ++# CONFIG_RTC_DRV_NUC900 is not set ++# CONFIG_RTC_DRV_ZYNQMP is not set ++ ++# ++# on-CPU RTC drivers ++# ++# CONFIG_RTC_DRV_ASM9260 is not set ++# CONFIG_RTC_DRV_DAVINCI is not set ++# CONFIG_RTC_DRV_DIGICOLOR is not set ++# CONFIG_RTC_DRV_OMAP is not set ++# CONFIG_RTC_DRV_S3C is not set ++# CONFIG_RTC_DRV_EP93XX is not set ++# CONFIG_RTC_DRV_VR41XX is not set ++# CONFIG_RTC_DRV_PL030 is not set ++# CONFIG_RTC_DRV_PL031 is not set ++# CONFIG_RTC_DRV_AT32AP700X is not set ++# CONFIG_RTC_DRV_AT91RM9200 is not set ++# CONFIG_RTC_DRV_AT91SAM9 is not set ++# CONFIG_RTC_DRV_GENERIC is not set ++# CONFIG_RTC_DRV_VT8500 is not set ++# CONFIG_RTC_DRV_SUNXI is not set ++# CONFIG_RTC_DRV_MV is not set ++# CONFIG_RTC_DRV_ARMADA38X is not set ++# CONFIG_RTC_DRV_GEMINI is not set ++# CONFIG_RTC_DRV_COH901331 is not set ++# CONFIG_RTC_DRV_STMP is not set ++# CONFIG_RTC_DRV_JZ4740 is not set ++# CONFIG_RTC_DRV_LPC24XX is not set ++# CONFIG_RTC_DRV_LPC32XX is not set ++# CONFIG_RTC_DRV_PM8XXX is not set ++# CONFIG_RTC_DRV_TEGRA is not set ++# CONFIG_RTC_DRV_SNVS is not set ++# CONFIG_RTC_DRV_MOXART is not set ++# CONFIG_RTC_DRV_MT6397 is not set ++# CONFIG_RTC_DRV_XGENE is not set ++ ++# ++# HID Sensor RTC drivers ++# ++# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set ++CONFIG_DMADEVICES=y ++# CONFIG_DMADEVICES_DEBUG is not set ++ ++# ++# DMA Devices ++# ++CONFIG_DMA_ENGINE=y ++CONFIG_DMA_VIRTUAL_CHANNELS=y ++CONFIG_DMA_OF=y ++# CONFIG_AMBA_PL08X is not set ++# CONFIG_AXI_DMAC is not set ++# CONFIG_COH901318 is not set ++# CONFIG_DMA_JZ4740 is not set ++# CONFIG_DMA_JZ4780 is not set ++# CONFIG_DMA_OMAP is not set ++# CONFIG_DMA_SA11X0 is not set ++# CONFIG_DMA_SUN6I is not set ++# CONFIG_EP93XX_DMA is not set ++# CONFIG_FSL_EDMA is not set ++# CONFIG_IMG_MDC_DMA is not set ++# CONFIG_INTEL_IDMA64 is not set ++# CONFIG_K3_DMA is not set ++# CONFIG_MMP_PDMA is not set ++# CONFIG_MMP_TDMA is not set ++# CONFIG_MV_XOR is not set ++# CONFIG_MV_XOR_V2 is not set ++# CONFIG_NBPFAXI_DMA is not set ++# CONFIG_PCH_DMA is not set ++# CONFIG_PL330_DMA is not set ++# CONFIG_STM32_DMA is not set ++# CONFIG_S3C24XX_DMAC is not set ++# CONFIG_TEGRA210_ADMA is not set ++# CONFIG_TIMB_DMA is not set ++# CONFIG_TI_EDMA is not set ++# CONFIG_XGENE_DMA is not set ++# CONFIG_XILINX_DMA is not set ++# CONFIG_XILINX_ZYNQMP_DMA is not set ++# CONFIG_ZX_DMA is not set ++CONFIG_HIEDMACV310=y ++# CONFIG_QCOM_HIDMA_MGMT is not set ++# CONFIG_QCOM_HIDMA is not set ++# CONFIG_DW_DMAC is not set ++# CONFIG_DW_DMAC_PCI is not set ++CONFIG_RENESAS_DMA=y ++CONFIG_SH_DMAE_BASE=y ++# CONFIG_SH_DMAE is not set ++# CONFIG_RCAR_DMAC is not set ++# CONFIG_RENESAS_USB_DMAC is not set ++# CONFIG_SUDMAC 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_PCI is not set ++# CONFIG_VIRTIO_MMIO is not set ++ ++# ++# Microsoft Hyper-V guest support ++# ++CONFIG_STAGING=y ++# CONFIG_COMEDI is not set ++# CONFIG_RTL8192U is not set ++# CONFIG_RTLLIB is not set ++# CONFIG_R8712U is not set ++# CONFIG_RTS5208 is not set ++# CONFIG_FB_SM750 is not set ++# CONFIG_FB_XGI is not set ++ ++# ++# Speakup console speech ++# ++# CONFIG_SPEAKUP is not set ++# CONFIG_STAGING_MEDIA is not set ++ ++# ++# Android ++# ++# CONFIG_ASHMEM is not set ++# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set ++CONFIG_ION=y ++# CONFIG_ION_TEST is not set ++# CONFIG_ION_DUMMY is not set ++# CONFIG_ION_OF is not set ++# CONFIG_STAGING_BOARD is not set ++# CONFIG_LTE_GDM724X is not set ++# CONFIG_MTD_SPINAND_MT29F is not set ++# CONFIG_LNET is not set ++# CONFIG_DGNC is not set ++# CONFIG_GS_FPGABOOT is not set ++# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set ++# CONFIG_FB_TFT is not set ++# CONFIG_FSL_MC_BUS is not set ++# CONFIG_MOST is not set ++# CONFIG_KS7010 is not set ++# CONFIG_GREYBUS 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_VERSATILE is not set ++# CONFIG_COMMON_CLK_SCPI is not set ++# 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_COMMON_CLK_AXI_CLKGEN is not set ++# CONFIG_CLK_QORIQ is not set ++# CONFIG_COMMON_CLK_XGENE is not set ++# CONFIG_COMMON_CLK_KEYSTONE is not set ++# CONFIG_COMMON_CLK_NXP is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++# CONFIG_COMMON_CLK_OXNAS is not set ++# CONFIG_CLK_BCM_63XX is not set ++# CONFIG_CLK_BCM_KONA is not set ++# CONFIG_COMMON_CLK_IPROC is not set ++# CONFIG_COMMON_CLK_HI3519 is not set ++# CONFIG_COMMON_CLK_HI3516A is not set ++# CONFIG_COMMON_CLK_HI3518EV20X is not set ++# CONFIG_COMMON_CLK_HI3536DV100 is not set ++CONFIG_COMMON_CLK_HI3559AV100=y ++CONFIG_COMMON_CLK_HI3521A=y ++CONFIG_COMMON_CLK_HI3531A=y ++# CONFIG_COMMON_CLK_HI6220 is not set ++CONFIG_RESET_HISI=y ++# CONFIG_COMMON_CLK_MT8135 is not set ++# CONFIG_COMMON_CLK_MT8173 is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++# CONFIG_COMMON_CLK_SAMSUNG is not set ++# CONFIG_S3C2410_COMMON_CLK is not set ++# CONFIG_S3C2412_COMMON_CLK is not set ++# CONFIG_S3C2443_COMMON_CLK is not set ++# CONFIG_SUNXI_CCU is not set ++# CONFIG_COMMON_CLK_TI_ADPLL is not set ++# CONFIG_CLK_UNIPHIER is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++# CONFIG_BCM2835_TIMER is not set ++# CONFIG_BCM_KONA_TIMER is not set ++# CONFIG_DIGICOLOR_TIMER is not set ++# CONFIG_DW_APB_TIMER is not set ++# CONFIG_ROCKCHIP_TIMER is not set ++# CONFIG_MESON6_TIMER is not set ++# CONFIG_SUN4I_TIMER is not set ++# CONFIG_SUN5I_HSTIMER is not set ++# CONFIG_VT8500_TIMER is not set ++# CONFIG_CADENCE_TTC_TIMER is not set ++# CONFIG_ASM9260_TIMER is not set ++# CONFIG_CLKSRC_DBX500_PRCMU is not set ++# CONFIG_CLPS711X_TIMER is not set ++# CONFIG_ATLAS7_TIMER is not set ++# CONFIG_MOXART_TIMER is not set ++# CONFIG_MXS_TIMER is not set ++# CONFIG_PRIMA2_TIMER is not set ++# CONFIG_NSPIRE_TIMER is not set ++# CONFIG_KEYSTONE_TIMER is not set ++# CONFIG_INTEGRATOR_AP_TIMER is not set ++# CONFIG_CLKSRC_PISTACHIO is not set ++# CONFIG_CLKSRC_TI_32K is not set ++# CONFIG_CLKSRC_MPS2 is not set ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set ++CONFIG_FSL_ERRATUM_A008585=y ++CONFIG_ARM_TIMER_SP804=y ++# CONFIG_TIMER_HISP804 is not set ++# CONFIG_ARMV7M_SYSTICK is not set ++# CONFIG_ATMEL_PIT is not set ++# CONFIG_ATMEL_ST is not set ++# CONFIG_CLKSRC_EXYNOS_MCT is not set ++# CONFIG_CLKSRC_SAMSUNG_PWM is not set ++# CONFIG_FSL_FTM_TIMER is not set ++# CONFIG_OXNAS_RPS_TIMER is not set ++# CONFIG_MTK_TIMER is not set ++# CONFIG_CLKSRC_JCORE_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_CLKSRC_VERSATILE is not set ++# CONFIG_CLKSRC_PXA is not set ++# CONFIG_H8300_TMR8 is not set ++# CONFIG_H8300_TMR16 is not set ++# CONFIG_H8300_TPU is not set ++# CONFIG_CLKSRC_ST_LPC 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_MTK_INFRACFG is not set ++# CONFIG_MTK_SCPSYS is not set ++# CONFIG_ROCKCHIP_PM_DOMAINS is not set ++# CONFIG_SOC_SAMSUNG is not set ++# CONFIG_SUNXI_SRAM is not set ++# CONFIG_SOC_TI is not set ++# CONFIG_UX500_SOC_ID is not set ++CONFIG_PM_DEVFREQ=y ++ ++# ++# DEVFREQ Governors ++# ++CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y ++# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set ++# CONFIG_DEVFREQ_GOV_POWERSAVE is not set ++# CONFIG_DEVFREQ_GOV_USERSPACE is not set ++# CONFIG_DEVFREQ_GOV_PASSIVE is not set ++ ++# ++# DEVFREQ Drivers ++# ++# CONFIG_ARM_EXYNOS_BUS_DEVFREQ is not set ++# CONFIG_PM_DEVFREQ_EVENT is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_NTB is not set ++# CONFIG_VME_BUS is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++CONFIG_ARM_GIC_V2M=y ++CONFIG_ARM_GIC_V3=y ++CONFIG_ARM_GIC_V3_ITS=y ++CONFIG_HISILICON_IRQ_MBIGEN=y ++# CONFIG_JCORE_AIC is not set ++# CONFIG_TS4800_IRQ is not set ++CONFIG_PARTITION_PERCPU=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_UNIPHIER is not set ++# CONFIG_RESET_ZYNQ is not set ++CONFIG_COMMON_RESET_HI6220=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_PHY_BCM_NS_USB2 is not set ++# CONFIG_PHY_BCM_NS_USB3 is not set ++CONFIG_ARMADA375_USBCLUSTER_PHY=y ++# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set ++# CONFIG_PHY_LPC18XX_USB_OTG is not set ++# CONFIG_PHY_PXA_28NM_HSIC is not set ++# CONFIG_PHY_PXA_28NM_USB2 is not set ++# CONFIG_OMAP_CONTROL_PHY is not set ++# CONFIG_PHY_EXYNOS_DP_VIDEO is not set ++# CONFIG_BCM_KONA_USB2_PHY is not set ++# CONFIG_PHY_HI6220_USB is not set ++# CONFIG_PHY_ROCKCHIP_INNO_USB2 is not set ++# CONFIG_PHY_ROCKCHIP_PCIE is not set ++# CONFIG_PHY_ROCKCHIP_TYPEC is not set ++# CONFIG_PHY_ST_SPEAR1310_MIPHY is not set ++# CONFIG_PHY_ST_SPEAR1340_MIPHY is not set ++# CONFIG_PHY_XGENE is not set ++# CONFIG_PHY_STIH407_USB is not set ++# CONFIG_PHY_BRCM_SATA is not set ++# CONFIG_PHY_CYGNUS_PCIE is not set ++CONFIG_HISI_PHY_USB3=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++ ++# ++# Performance monitor support ++# ++CONFIG_ARM_PMU=y ++# CONFIG_RAS is not set ++# CONFIG_THUNDERBOLT is not set ++ ++# ++# Android ++# ++CONFIG_ANDROID=y ++# CONFIG_ANDROID_BINDER_IPC is not set ++# CONFIG_LIBNVDIMM 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 ++# CONFIG_HI_DMAC is not set ++# CONFIG_HIVDMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE is not set ++ ++# ++# Firmware Drivers ++# ++CONFIG_ARM_PSCI_FW=y ++CONFIG_ARM_SCPI_POWER_DOMAIN=y ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++# CONFIG_MESON_SM is not set ++# CONFIG_ACPI is not set ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++CONFIG_FS_IOMAP=y ++CONFIG_EXT2_FS=y ++CONFIG_EXT2_FS_XATTR=y ++CONFIG_EXT2_FS_POSIX_ACL=y ++CONFIG_EXT2_FS_SECURITY=y ++CONFIG_EXT3_FS=y ++CONFIG_EXT3_FS_POSIX_ACL=y ++CONFIG_EXT3_FS_SECURITY=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_CHECK=y ++CONFIG_REISERFS_PROC_INFO=y ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_DEBUG=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++# CONFIG_XFS_WARN is not set ++# CONFIG_XFS_DEBUG is not set ++# CONFIG_GFS2_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_DAX is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_EXPORTFS=m ++# 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=y ++# CONFIG_QUOTA_NETLINK_INTERFACE is not set ++CONFIG_PRINT_QUOTA_WARNING=y ++# CONFIG_QUOTA_DEBUG is not set ++CONFIG_QUOTA_TREE=m ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_QUOTACTL=y ++CONFIG_AUTOFS4_FS=m ++CONFIG_FUSE_FS=y ++# CONFIG_CUSE is not set ++# CONFIG_OVERLAY_FS is not set ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=y ++# CONFIG_JOLIET is not set ++# CONFIG_ZISOFS is not set ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++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_KCORE is not set ++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=y ++CONFIG_TMPFS_XATTR=y ++# CONFIG_HUGETLBFS is not set ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_ARCH_HAS_GIGANTIC_PAGE=y ++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_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++CONFIG_SQUASHFS=y ++CONFIG_SQUASHFS_FILE_CACHE=y ++# CONFIG_SQUASHFS_FILE_DIRECT is not set ++CONFIG_SQUASHFS_DECOMP_SINGLE=y ++# CONFIG_SQUASHFS_DECOMP_MULTI is not set ++# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set ++# CONFIG_SQUASHFS_XATTR is not set ++CONFIG_SQUASHFS_ZLIB=y ++# CONFIG_SQUASHFS_LZ4 is not set ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set ++# CONFIG_SQUASHFS_EMBEDDED is not set ++CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 ++# 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFSD is not set ++CONFIG_GRACE_PERIOD=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=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=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=y ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++# 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 ++# CONFIG_VIRTUALIZATION is not set ++ ++# ++# Kernel hacking ++# ++ ++# ++# printk and dmesg options ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++# 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=2048 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++CONFIG_ARCH_WANT_FRAME_POINTERS=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++CONFIG_HAVE_ARCH_KASAN=y ++# CONFIG_KASAN is not set ++CONFIG_ARCH_HAS_KCOV=y ++# CONFIG_KCOV is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++CONFIG_LOCKUP_DETECTOR=y ++# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set ++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 ++# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set ++CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 ++# CONFIG_WQ_WATCHDOG is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++CONFIG_SCHED_INFO=y ++CONFIG_SCHEDSTATS=y ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_HAVE_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_PROVE_RCU is not set ++CONFIG_SPARSE_RCU_POINTER=y ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=21 ++CONFIG_RCU_TRACE=y ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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_TRACE_CLOCK=y ++CONFIG_TRACING_SUPPORT=y ++# CONFIG_FTRACE is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_LKDTM is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=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_ARM64_PTDUMP is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_DEBUG_ALIGN_RODATA is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS 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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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 is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++CONFIG_CRYPTO_NULL=m ++CONFIG_CRYPTO_NULL2=y ++# CONFIG_CRYPTO_PCRYPT is not set ++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=m ++# CONFIG_CRYPTO_GCM is not set ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# 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=y ++CONFIG_CRYPTO_HMAC=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# 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 is not set ++# 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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_CRYPTO_DEV_S5P is not set ++# CONFIG_CRYPTO_DEV_ATMEL_AES is not set ++# CONFIG_CRYPTO_DEV_CCP is not set ++# CONFIG_CRYPTO_DEV_QCE is not set ++# CONFIG_CRYPTO_DEV_IMGTEC_HASH is not set ++ ++# ++# Certificates for signature checking ++# ++# CONFIG_ARM64_CRYPTO is not set ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++CONFIG_HAVE_ARCH_BITREVERSE=y ++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=y ++CONFIG_CRC16=y ++# CONFIG_CRC_T10DIF is not set ++CONFIG_CRC_ITU_T=y ++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=m ++# CONFIG_CRC8 is not set ++CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y ++# CONFIG_RANDOM32_SELFTEST is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=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_GZIP=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_NLATTR=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=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y +diff --git a/arch/arm64/configs/hi3559av100_arm64_big_little_nand_defconfig b/arch/arm64/configs/hi3559av100_arm64_big_little_nand_defconfig +new file mode 100644 +index 0000000..21ac18f +--- /dev/null ++++ b/arch/arm64/configs/hi3559av100_arm64_big_little_nand_defconfig +@@ -0,0 +1,3847 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm64 4.9.37 Kernel Configuration ++# ++CONFIG_ARM64=y ++CONFIG_64BIT=y ++CONFIG_ARCH_PHYS_ADDR_T_64BIT=y ++CONFIG_MMU=y ++CONFIG_DEBUG_RODATA=y ++CONFIG_ARM64_PAGE_SHIFT=12 ++CONFIG_ARM64_CONT_SHIFT=4 ++CONFIG_ARCH_MMAP_RND_BITS_MIN=18 ++CONFIG_ARCH_MMAP_RND_BITS_MAX=24 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=y ++CONFIG_GENERIC_BUG=y ++CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CSUM=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_ZONE_DMA=y ++CONFIG_HAVE_GENERIC_RCU_GUP=y ++CONFIG_ARCH_DMA_ADDR_T_64BIT=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_NEED_SG_DMA_LENGTH=y ++CONFIG_SMP=y ++CONFIG_SWIOTLB=y ++CONFIG_IOMMU_HELPER=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_FIX_EARLYCON_MEM=y ++CONFIG_PGTABLE_LEVELS=3 ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++CONFIG_COMPILE_TEST=y ++CONFIG_LOCALVERSION="" ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_GENERIC_IRQ_MIGRATION=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_GENERIC_MSI_IRQ=y ++CONFIG_GENERIC_MSI_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++# CONFIG_IRQ_DOMAIN_DEBUG is not set ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_HZ_PERIODIC=y ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NO_HZ_FULL 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_TREE_RCU=y ++# CONFIG_RCU_EXPERT is not set ++CONFIG_SRCU=y ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++CONFIG_TREE_RCU_TRACE=y ++# CONFIG_RCU_EXPEDITE_BOOT is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=14 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y ++# CONFIG_CGROUPS is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++CONFIG_RELAY=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++# CONFIG_RD_LZ4 is not set ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_SYSCTL_EXCEPTION_TRACE=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_ALL is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y ++CONFIG_BPF_SYSCALL=y ++CONFIG_SHMEM=y ++CONFIG_AIO=y ++CONFIG_ADVISE_SYSCALLS=y ++CONFIG_USERFAULTFD=y ++CONFIG_PCI_QUIRKS=y ++CONFIG_MEMBARRIER=y ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++ ++# ++# Kernel Performance Events And Counters ++# ++CONFIG_PERF_EVENTS=y ++# CONFIG_DEBUG_PERF_USE_VMALLOC is not set ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_SLAB_FREELIST_RANDOM is not set ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_SYSTEM_DATA_VERIFICATION is not set ++# CONFIG_PROFILING is not set ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL is not set ++# CONFIG_UPROBES is not set ++# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set ++CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=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_HW_BREAKPOINT=y ++CONFIG_HAVE_PERF_REGS=y ++CONFIG_HAVE_PERF_USER_STACK_DUMP=y ++CONFIG_HAVE_ARCH_JUMP_LABEL=y ++CONFIG_HAVE_RCU_TABLE_FREE=y ++CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y ++CONFIG_HAVE_CMPXCHG_LOCAL=y ++CONFIG_HAVE_CMPXCHG_DOUBLE=y ++CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y ++CONFIG_HAVE_ARCH_SECCOMP_FILTER=y ++CONFIG_HAVE_GCC_PLUGINS=y ++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_ARCH_TRANSPARENT_HUGEPAGE=y ++CONFIG_HAVE_ARCH_HUGE_VMAP=y ++CONFIG_MODULES_USE_ELF_RELA=y ++CONFIG_ARCH_HAS_ELF_RANDOMIZE=y ++CONFIG_HAVE_ARCH_MMAP_RND_BITS=y ++CONFIG_ARCH_MMAP_RND_BITS=18 ++CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 ++# CONFIG_HAVE_ARCH_HASH is not set ++# CONFIG_ISA_BUS_API is not set ++CONFIG_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_COMPAT_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_SLABINFO=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_MODULES_TREE_LOOKUP=y ++CONFIG_BLOCK=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++CONFIG_BLOCK_COMPAT=y ++CONFIG_BLK_MQ_PCI=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_LOCK_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# Platform selection ++# ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_BCM2835 is not set ++# CONFIG_ARCH_BCM_IPROC is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_BRCMSTB is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_LAYERSCAPE is not set ++# CONFIG_ARCH_LG1K is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++CONFIG_ARCH_HI3559AV100=y ++# CONFIG_ACCESS_M7_DEV is not set ++# CONFIG_ARCH_HISI_BVT_AMP is not set ++# CONFIG_ARCH_MEDIATEK is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SEATTLE is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_STRATIX10 is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_SPRD is not set ++# CONFIG_ARCH_THUNDER is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_VULCAN is not set ++# CONFIG_ARCH_XGENE is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQMP is not set ++ ++# ++# Bus support ++# ++CONFIG_PCI=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_PCI_DOMAINS_GENERIC=y ++CONFIG_PCI_SYSCALL=y ++CONFIG_PCIEPORTBUS=y ++# CONFIG_PCIEAER is not set ++# CONFIG_PCIEASPM is not set ++# CONFIG_PCIE_PME is not set ++# CONFIG_PCIE_DPC is not set ++# CONFIG_PCIE_PTM is not set ++CONFIG_PCI_BUS_ADDR_T_64BIT=y ++CONFIG_PCI_MSI=y ++CONFIG_PCI_MSI_IRQ_DOMAIN=y ++# CONFIG_PCI_DEBUG is not set ++# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set ++# CONFIG_PCI_STUB is not set ++# CONFIG_PCI_IOV is not set ++# CONFIG_PCI_PRI is not set ++# CONFIG_PCI_PASID is not set ++# CONFIG_HOTPLUG_PCI is not set ++ ++# ++# PCI host controller drivers ++# ++# CONFIG_PCIE_DW_PLAT is not set ++# CONFIG_PCI_HOST_GENERIC is not set ++# CONFIG_PCI_HISI is not set ++# CONFIG_PCI_HOST_THUNDER_PEM is not set ++# CONFIG_PCI_HOST_THUNDER_ECAM is not set ++# CONFIG_HIPCIE is not set ++ ++# ++# Kernel Features ++# ++ ++# ++# ARM errata workarounds via the alternatives framework ++# ++CONFIG_ARM64_ERRATUM_826319=y ++CONFIG_ARM64_ERRATUM_827319=y ++CONFIG_ARM64_ERRATUM_824069=y ++CONFIG_ARM64_ERRATUM_819472=y ++CONFIG_ARM64_ERRATUM_832075=y ++CONFIG_ARM64_ERRATUM_845719=y ++CONFIG_ARM64_ERRATUM_843419=y ++CONFIG_CAVIUM_ERRATUM_22375=y ++CONFIG_CAVIUM_ERRATUM_23154=y ++CONFIG_CAVIUM_ERRATUM_27456=y ++CONFIG_QCOM_QDF2400_ERRATUM_0065=y ++CONFIG_ARM64_4K_PAGES=y ++# CONFIG_ARM64_16K_PAGES is not set ++# CONFIG_ARM64_64K_PAGES is not set ++CONFIG_ARM64_VA_BITS_39=y ++# CONFIG_ARM64_VA_BITS_48 is not set ++CONFIG_ARM64_VA_BITS=39 ++# CONFIG_CPU_BIG_ENDIAN is not set ++CONFIG_SCHED_MC=y ++# CONFIG_SCHED_SMT is not set ++CONFIG_NR_CPUS=64 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_NUMA is not set ++CONFIG_PREEMPT_NONE=y ++# CONFIG_PREEMPT_VOLUNTARY is not set ++# CONFIG_PREEMPT is not set ++# CONFIG_HZ_100 is not set ++# CONFIG_HZ_250 is not set ++# CONFIG_HZ_300 is not set ++CONFIG_HZ_1000=y ++CONFIG_HZ=1000 ++# CONFIG_SCHED_HRTICK is not set ++CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y ++CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y ++CONFIG_ARCH_SPARSEMEM_ENABLE=y ++CONFIG_ARCH_SPARSEMEM_DEFAULT=y ++CONFIG_ARCH_SELECT_MEMORY_MODEL=y ++CONFIG_HAVE_ARCH_PFN_VALID=y ++CONFIG_HW_PERF_EVENTS=y ++CONFIG_SYS_SUPPORTS_HUGETLBFS=y ++CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y ++CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_SPARSEMEM_MANUAL=y ++CONFIG_SPARSEMEM=y ++CONFIG_HAVE_MEMORY_PRESENT=y ++CONFIG_SPARSEMEM_EXTREME=y ++CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y ++CONFIG_SPARSEMEM_VMEMMAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=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=y ++CONFIG_BOUNCE=y ++CONFIG_KSM=y ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# CONFIG_TRANSPARENT_HUGEPAGE is not set ++# CONFIG_CLEANCACHE is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++# CONFIG_CMA_DEBUGFS is not set ++CONFIG_CMA_AREAS=7 ++# 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_FRAME_VECTOR=y ++# CONFIG_SECCOMP is not set ++# CONFIG_PARAVIRT is not set ++# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set ++# CONFIG_KEXEC is not set ++# CONFIG_XEN is not set ++CONFIG_FORCE_MAX_ZONEORDER=11 ++# CONFIG_ARMV8_DEPRECATED is not set ++ ++# ++# ARMv8.1 architectural features ++# ++CONFIG_ARM64_HW_AFDBM=y ++CONFIG_ARM64_PAN=y ++# CONFIG_ARM64_LSE_ATOMICS is not set ++CONFIG_ARM64_VHE=y ++ ++# ++# ARMv8.2 architectural features ++# ++CONFIG_ARM64_UAO=y ++CONFIG_ARM64_MODULE_CMODEL_LARGE=y ++# CONFIG_RANDOMIZE_BASE is not set ++ ++# ++# Boot options ++# ++CONFIG_CMDLINE="mem=128M console=ttyAMA0,115200 console=ttyMTD,blackbox" ++# CONFIG_CMDLINE_FORCE is not set ++# CONFIG_EFI is not set ++CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y ++CONFIG_IMG_GZ_DTB=y ++# CONFIG_IMG_DTB is not set ++CONFIG_BUILD_ARM64_APPENDED_KERNEL_IMAGE_NAME="Image.gz-dtb" ++CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES="hisilicon/hi3559av100-demb-flash" ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_COMPAT_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++CONFIG_COMPAT=y ++CONFIG_SYSVIPC_COMPAT=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_SUSPEND_SKIP_SYNC is not set ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++CONFIG_PM_CLK=y ++CONFIG_PM_GENERIC_DOMAINS=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_PM_GENERIC_DOMAINS_SLEEP=y ++CONFIG_PM_GENERIC_DOMAINS_OF=y ++CONFIG_CPU_PM=y ++CONFIG_ARCH_HIBERNATION_POSSIBLE=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Idle ++# ++# CONFIG_CPU_IDLE is not set ++# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_ATTR_SET=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_STAT_DETAILS=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set ++ ++# ++# CPU frequency scaling drivers ++# ++# CONFIG_CPUFREQ_DT is not set ++# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++CONFIG_NET=y ++CONFIG_NET_INGRESS=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 is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++CONFIG_NET_IP_TUNNEL=m ++# 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=m ++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=y ++# CONFIG_IPV6_ROUTE_INFO 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_IPV6_ILA is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# 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=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++CONFIG_NETFILTER_INGRESS=y ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_DUP_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_DUP_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_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_QRTR is not set ++# CONFIG_NET_NCSI is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_SOCK_CGROUP_DATA is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_EBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER=y ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++# CONFIG_DEVTMPFS is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_GENERIC_CPU_AUTOPROBE=y ++CONFIG_REGMAP=y ++CONFIG_REGMAP_I2C=y ++CONFIG_REGMAP_SPI=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=4 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_ARM_CCI400_PMU is not set ++# CONFIG_ARM_CCI5xx_PMU is not set ++# CONFIG_ARM_CCN is not set ++# CONFIG_QCOM_EBI2 is not set ++# CONFIG_SIMPLE_PM_BUS 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 ++# CONFIG_MTD_BCM63XX_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_TS5500 is not set ++# CONFIG_MTD_INTEL_VR_NOR is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_DATAFLASH is not set ++# 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=y ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOCG3 is not set ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_PCI is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_RICOH is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_VF610_NFC is not set ++# CONFIG_MTD_NAND_SH_FLCTL is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++# CONFIG_MTD_SPI_NAND_HISI_BVT is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++CONFIG_MTD_NAND_HIFMC100=y ++# CONFIG_HIFMC100_NAND_EDO_MODE is not set ++CONFIG_RW_H_WIDTH=10 ++CONFIG_R_L_WIDTH=10 ++CONFIG_W_L_WIDTH=10 ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# LPDDR & LPDDR2 PCM memory drivers ++# ++# CONFIG_MTD_LPDDR is not set ++# CONFIG_MTD_SPI_NOR is not set ++# CONFIG_MTD_UBI is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++# CONFIG_OF_UNITTEST is not set ++# CONFIG_OF_ALL_DTBS is not set ++CONFIG_OF_FLATTREE=y ++CONFIG_OF_EARLY_FLATTREE=y ++CONFIG_OF_ADDRESS=y ++CONFIG_OF_ADDRESS_PCI=y ++CONFIG_OF_IRQ=y ++CONFIG_OF_NET=y ++CONFIG_OF_MDIO=y ++CONFIG_OF_PCI=y ++CONFIG_OF_PCI_IRQ=y ++CONFIG_OF_RESERVED_MEM=y ++# CONFIG_OF_OVERLAY is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set ++# CONFIG_BLK_CPQ_CISS_DA is not set ++# CONFIG_BLK_DEV_DAC960 is not set ++# CONFIG_BLK_DEV_UMEM is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_SKD is not set ++# CONFIG_BLK_DEV_SX8 is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_BLK_DEV_RSXX is not set ++# CONFIG_BLK_DEV_NVME is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# CONFIG_SENSORS_LIS3LV02D is not set ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_DUMMY_IRQ is not set ++# CONFIG_PHANTOM is not set ++# CONFIG_INTEL_MID_PTI is not set ++# CONFIG_SGI_IOC4 is not set ++# CONFIG_TIFM_CORE is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ATMEL_SSC is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_HP_ILO is not set ++# CONFIG_QCOM_COINCELL 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_PCH_PHUB 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 ++# CONFIG_CB710_CORE 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_GENWQE is not set ++# 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=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_SCSI_CXGB3_ISCSI is not set ++# CONFIG_SCSI_CXGB4_ISCSI is not set ++# CONFIG_SCSI_BNX2_ISCSI is not set ++# CONFIG_BE2ISCSI is not set ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_HPSA is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_3W_SAS is not set ++# CONFIG_SCSI_ACARD is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX is not set ++# CONFIG_SCSI_AIC79XX is not set ++# CONFIG_SCSI_AIC94XX is not set ++# CONFIG_SCSI_HISI_SAS is not set ++# CONFIG_SCSI_MVSAS is not set ++# CONFIG_SCSI_MVUMI is not set ++# CONFIG_SCSI_ADVANSYS is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_SCSI_ESAS2R is not set ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++# CONFIG_SCSI_MPT3SAS is not set ++# CONFIG_SCSI_MPT2SAS is not set ++# CONFIG_SCSI_SMARTPQI is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_SCSI_HPTIOP is not set ++# CONFIG_SCSI_SNIC is not set ++# CONFIG_SCSI_DMX3191D is not set ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_IPS is not set ++# CONFIG_SCSI_INITIO is not set ++# CONFIG_SCSI_INIA100 is not set ++# CONFIG_SCSI_STEX is not set ++# CONFIG_SCSI_SYM53C8XX_2 is not set ++# CONFIG_SCSI_QLOGIC_1280 is not set ++# CONFIG_SCSI_QLA_ISCSI is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_AM53C974 is not set ++# CONFIG_SCSI_WD719X is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_PMCRAID is not set ++# CONFIG_SCSI_PM8001 is not set ++# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HAVE_PATA_PLATFORM=y ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++# CONFIG_FUSION is not set ++ ++# ++# IEEE 1394 (FireWire) support ++# ++# CONFIG_FIREWIRE is not set ++# CONFIG_FIREWIRE_NOSY is not set ++CONFIG_NETDEVICES=y ++CONFIG_NET_CORE=y ++# CONFIG_BONDING is not set ++# CONFIG_DUMMY is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC 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 ++# CONFIG_ARCNET is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++CONFIG_ETHERNET=y ++CONFIG_NET_VENDOR_3COM=y ++# CONFIG_VORTEX is not set ++# CONFIG_TYPHOON is not set ++CONFIG_NET_VENDOR_ADAPTEC=y ++# CONFIG_ADAPTEC_STARFIRE is not set ++CONFIG_NET_VENDOR_AGERE=y ++# CONFIG_ET131X is not set ++CONFIG_NET_VENDOR_ALTEON=y ++# CONFIG_ACENIC is not set ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_VENDOR_AMAZON is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC is not set ++CONFIG_NET_VENDOR_ATHEROS=y ++# CONFIG_ATL2 is not set ++# CONFIG_ATL1 is not set ++# CONFIG_ATL1E is not set ++# CONFIG_ATL1C is not set ++# CONFIG_ALX 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_BROCADE=y ++# CONFIG_BNA is not set ++# CONFIG_NET_CALXEDA_XGMAC is not set ++CONFIG_NET_VENDOR_CAVIUM=y ++# CONFIG_THUNDER_NIC_PF is not set ++# CONFIG_THUNDER_NIC_VF is not set ++# CONFIG_THUNDER_NIC_BGX is not set ++# CONFIG_THUNDER_NIC_RGX is not set ++# CONFIG_LIQUIDIO is not set ++CONFIG_NET_VENDOR_CHELSIO=y ++# CONFIG_CHELSIO_T1 is not set ++# CONFIG_CHELSIO_T3 is not set ++# CONFIG_CHELSIO_T4 is not set ++# CONFIG_CHELSIO_T4VF is not set ++CONFIG_NET_VENDOR_CISCO=y ++# CONFIG_ENIC is not set ++# CONFIG_CX_ECAT is not set ++# CONFIG_DNET is not set ++CONFIG_NET_VENDOR_DEC=y ++# CONFIG_NET_TULIP is not set ++CONFIG_NET_VENDOR_DLINK=y ++# CONFIG_DL2K is not set ++# CONFIG_SUNDANCE is not set ++CONFIG_NET_VENDOR_EMULEX=y ++# CONFIG_BE2NET is not set ++# CONFIG_NET_VENDOR_EZCHIP is not set ++CONFIG_NET_VENDOR_EXAR=y ++# CONFIG_S2IO is not set ++# CONFIG_VXGE is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DDR_64BIT=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++CONFIG_NET_VENDOR_HP=y ++# CONFIG_HP100 is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_JME is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++CONFIG_NET_VENDOR_MELLANOX=y ++# CONFIG_MLX4_EN is not set ++# CONFIG_MLX4_CORE is not set ++# CONFIG_MLX5_CORE is not set ++# CONFIG_MLXSW_CORE is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_MICROCHIP is not set ++CONFIG_NET_VENDOR_MYRI=y ++# CONFIG_MYRI10GE is not set ++# CONFIG_FEALNX is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NETRONOME is not set ++CONFIG_NET_VENDOR_NVIDIA=y ++# CONFIG_FORCEDETH is not set ++CONFIG_NET_VENDOR_OKI=y ++# CONFIG_PCH_GBE is not set ++# CONFIG_ETHOC is not set ++CONFIG_NET_PACKET_ENGINE=y ++# CONFIG_HAMACHI is not set ++# CONFIG_YELLOWFIN is not set ++CONFIG_NET_VENDOR_QLOGIC=y ++# CONFIG_QLA3XXX is not set ++# CONFIG_QLCNIC is not set ++# CONFIG_QLGE is not set ++# CONFIG_NETXEN_NIC is not set ++# CONFIG_QED is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++CONFIG_NET_VENDOR_REALTEK=y ++# CONFIG_8139CP is not set ++# CONFIG_8139TOO is not set ++# CONFIG_R8169 is not set ++# CONFIG_NET_VENDOR_RENESAS is not set ++CONFIG_NET_VENDOR_RDC=y ++# CONFIG_R6040 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_SILAN=y ++# CONFIG_SC92031 is not set ++CONFIG_NET_VENDOR_SIS=y ++# CONFIG_SIS900 is not set ++# CONFIG_SIS190 is not set ++# CONFIG_SFC is not set ++# CONFIG_NET_VENDOR_SMSC is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++CONFIG_NET_VENDOR_SUN=y ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++# CONFIG_NIU is not set ++# CONFIG_NET_VENDOR_SYNOPSYS is not set ++CONFIG_NET_VENDOR_TEHUTI=y ++# CONFIG_TEHUTI is not set ++CONFIG_NET_VENDOR_TI=y ++# CONFIG_TI_CPSW_ALE is not set ++# CONFIG_TLAN is not set ++# CONFIG_NET_VENDOR_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_FDDI is not set ++# CONFIG_HIPPI is not set ++CONFIG_PHYLIB=y ++CONFIG_SWPHY=y ++ ++# ++# MDIO bus device drivers ++# ++# CONFIG_MDIO_BCM_IPROC is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_BCM_IPROC 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 ++CONFIG_MDIO_HISI_GEMAC=y ++# CONFIG_MDIO_OCTEON is not set ++# CONFIG_MDIO_THUNDER is not set ++# CONFIG_MDIO_XGENE 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_IPHETH is not set ++CONFIG_WLAN=y ++CONFIG_WLAN_VENDOR_ADMTEK=y ++CONFIG_WLAN_VENDOR_ATH=y ++# CONFIG_ATH_DEBUG is not set ++# CONFIG_ATH5K_PCI is not set ++CONFIG_WLAN_VENDOR_ATMEL=y ++CONFIG_WLAN_VENDOR_BROADCOM=y ++CONFIG_WLAN_VENDOR_CISCO=y ++CONFIG_WLAN_VENDOR_INTEL=y ++CONFIG_WLAN_VENDOR_INTERSIL=y ++# CONFIG_HOSTAP is not set ++# CONFIG_PRISM54 is not set ++CONFIG_WLAN_VENDOR_MARVELL=y ++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 ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_VMXNET3 is not set ++# CONFIG_ISDN is not set ++# CONFIG_NVM is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++CONFIG_INPUT_FF_MEMLESS=y ++# CONFIG_INPUT_POLLDEV is not set ++# CONFIG_INPUT_SPARSEKMAP is not set ++# CONFIG_INPUT_MATRIXKMAP is not set ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_CLPS711X is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_GOLDFISH_EVENTS is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_ST_KEYSCAN is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_SH_KEYSC is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++CONFIG_INPUT_JOYSTICK=y ++# CONFIG_JOYSTICK_ANALOG is not set ++# CONFIG_JOYSTICK_A3D is not set ++# CONFIG_JOYSTICK_ADI is not set ++# CONFIG_JOYSTICK_COBRA is not set ++# CONFIG_JOYSTICK_GF2K is not set ++# CONFIG_JOYSTICK_GRIP is not set ++# CONFIG_JOYSTICK_GRIP_MP is not set ++# CONFIG_JOYSTICK_GUILLEMOT is not set ++# CONFIG_JOYSTICK_INTERACT is not set ++# CONFIG_JOYSTICK_SIDEWINDER is not set ++# CONFIG_JOYSTICK_TMDC is not set ++# CONFIG_JOYSTICK_IFORCE is not set ++# CONFIG_JOYSTICK_WARRIOR is not set ++# CONFIG_JOYSTICK_MAGELLAN is not set ++# CONFIG_JOYSTICK_SPACEORB is not set ++# CONFIG_JOYSTICK_SPACEBALL is not set ++# CONFIG_JOYSTICK_STINGER is not set ++# CONFIG_JOYSTICK_TWIDJOY is not set ++# CONFIG_JOYSTICK_ZHENHUA is not set ++# CONFIG_JOYSTICK_AS5011 is not set ++# CONFIG_JOYSTICK_JOYDUMP is not set ++# CONFIG_JOYSTICK_XPAD is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_GP2A is not set ++# CONFIG_INPUT_GPIO_BEEPER is not set ++# CONFIG_INPUT_GPIO_TILT_POLLED is not set ++# CONFIG_INPUT_GPIO_DECODER is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INPUT_CM109 is not set ++# CONFIG_INPUT_REGULATOR_HAPTIC is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV260X_HAPTICS is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_INPUT_HISI_POWERKEY is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_SERIO_OLPC_APSP is not set ++# CONFIG_SERIO_SUN4I_PS2 is not set ++# CONFIG_USERIO is not set ++CONFIG_GAMEPORT=y ++# CONFIG_GAMEPORT_NS558 is not set ++# CONFIG_GAMEPORT_L4 is not set ++# CONFIG_GAMEPORT_EMU10K1 is not set ++# CONFIG_GAMEPORT_FM801 is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_NOZOMI is not set ++# CONFIG_N_GSM is not set ++# CONFIG_TRACE_SINK is not set ++CONFIG_DEVMEM=y ++CONFIG_DEVKMEM=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_ATMEL is not set ++# CONFIG_SERIAL_CLPS711X is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X is not set ++# CONFIG_SERIAL_IMX is not set ++# CONFIG_SERIAL_UARTLITE is not set ++# CONFIG_SERIAL_SH_SCI is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_JSM is not set ++# CONFIG_SERIAL_SCCNXP is not set ++# CONFIG_SERIAL_SC16IS7XX is not set ++# CONFIG_SERIAL_TIMBERDALE is not set ++# CONFIG_SERIAL_BCM63XX is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_IFX6X60 is not set ++# CONFIG_SERIAL_PCH_UART is not set ++# CONFIG_SERIAL_MXS_AUART is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++# CONFIG_SERIAL_MPS2_UART is not set ++# CONFIG_SERIAL_ARC is not set ++# CONFIG_SERIAL_RP2 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_SERIAL_MVEBU_UART 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_APPLICOM is not set ++ ++# ++# PCMCIA character devices ++# ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_DEVPORT=y ++# 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=y ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set ++# CONFIG_I2C_MUX_GPIO is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PCA954x is not set ++# CONFIG_I2C_MUX_PINCTRL is not set ++# CONFIG_I2C_MUX_REG is not set ++# CONFIG_I2C_DEMUX_PINCTRL 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 ++# ++ ++# ++# PC SMBus host controller drivers ++# ++# CONFIG_I2C_ALI1535 is not set ++# CONFIG_I2C_ALI1563 is not set ++# CONFIG_I2C_ALI15X3 is not set ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++# CONFIG_I2C_HIX5HD2 is not set ++# CONFIG_I2C_I801 is not set ++# CONFIG_I2C_ISCH is not set ++# CONFIG_I2C_PIIX4 is not set ++# CONFIG_I2C_NFORCE2 is not set ++# CONFIG_I2C_SIS5595 is not set ++# CONFIG_I2C_SIS630 is not set ++# CONFIG_I2C_SIS96X is not set ++# CONFIG_I2C_VIA is not set ++# CONFIG_I2C_VIAPRO is not set ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_AXXIA is not set ++# CONFIG_I2C_BCM_IPROC is not set ++# CONFIG_I2C_BRCMSTB is not set ++# CONFIG_I2C_CADENCE is not set ++# CONFIG_I2C_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_DESIGNWARE_PCI is not set ++# CONFIG_I2C_EFM32 is not set ++# CONFIG_I2C_EG20T is not set ++# CONFIG_I2C_EMEV2 is not set ++# CONFIG_I2C_GPIO is not set ++CONFIG_I2C_HIBVT=y ++# CONFIG_I2C_IMG is not set ++# CONFIG_I2C_JZ4780 is not set ++# CONFIG_I2C_LPC2K is not set ++# CONFIG_I2C_MESON is not set ++# CONFIG_I2C_MT65XX is not set ++# CONFIG_I2C_NOMADIK 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_RIIC is not set ++# CONFIG_I2C_RK3X is not set ++# CONFIG_I2C_SH_MOBILE is not set ++# CONFIG_I2C_SIMTEC is not set ++# CONFIG_I2C_SUN6I_P2WI is not set ++# CONFIG_I2C_UNIPHIER is not set ++# CONFIG_I2C_UNIPHIER_F is not set ++# CONFIG_I2C_VERSATILE is not set ++# CONFIG_I2C_THUNDERX is not set ++# CONFIG_I2C_XILINX is not set ++# CONFIG_I2C_XLP9XX is not set ++# CONFIG_I2C_RCAR 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_DMA_MSG_MIN_LEN=5 ++CONFIG_DMA_MSG_MAX_LEN=4090 ++# 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_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_ATMEL is not set ++# CONFIG_SPI_AXI_SPI_ENGINE is not set ++# CONFIG_SPI_BCM2835 is not set ++# CONFIG_SPI_BCM2835AUX is not set ++# CONFIG_SPI_BCM63XX is not set ++# CONFIG_SPI_BCM63XX_HSSPI is not set ++# CONFIG_SPI_BCM_QSPI is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_CLPS711X is not set ++# CONFIG_SPI_DESIGNWARE is not set ++# CONFIG_SPI_EP93XX is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_IMG_SPFI is not set ++# CONFIG_SPI_IMX is not set ++# CONFIG_SPI_JCORE is not set ++# CONFIG_SPI_LP8841_RTC is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_FSL_DSPI is not set ++# CONFIG_SPI_MESON_SPIFC is not set ++# CONFIG_SPI_MT65XX is not set ++# CONFIG_SPI_OC_TINY is not set ++# CONFIG_SPI_OMAP24XX is not set ++# CONFIG_SPI_TI_QSPI is not set ++# CONFIG_SPI_OMAP_100K is not set ++# CONFIG_SPI_ORION is not set ++# CONFIG_SPI_PIC32 is not set ++# CONFIG_SPI_PIC32_SQI is not set ++CONFIG_SPI_PL022=y ++# CONFIG_SPI_PXA2XX is not set ++# CONFIG_SPI_PXA2XX_PCI is not set ++# CONFIG_SPI_ROCKCHIP is not set ++# CONFIG_SPI_RSPI is not set ++# CONFIG_SPI_SC18IS602 is not set ++# CONFIG_SPI_SH_MSIOF is not set ++# CONFIG_SPI_SH is not set ++# CONFIG_SPI_SH_HSPI is not set ++# CONFIG_SPI_ST_SSC4 is not set ++# CONFIG_SPI_SUN4I is not set ++# CONFIG_SPI_SUN6I is not set ++# CONFIG_SPI_TEGRA114 is not set ++# CONFIG_SPI_TEGRA20_SFLASH is not set ++# CONFIG_SPI_TEGRA20_SLINK is not set ++# CONFIG_SPI_THUNDERX is not set ++# CONFIG_SPI_TOPCLIFF_PCH is not set ++# CONFIG_SPI_TXX9 is not set ++# CONFIG_SPI_XCOMM is not set ++# CONFIG_SPI_XILINX is not set ++# CONFIG_SPI_XLP is not set ++# CONFIG_SPI_XTENSA_XTFPGA is not set ++# CONFIG_SPI_ZYNQMP_GQSPI is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_PTP_1588_CLOCK_PCH is not set ++CONFIG_PINCTRL=y ++ ++# ++# Pin controllers ++# ++CONFIG_PINMUX=y ++CONFIG_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++# CONFIG_PINCTRL_AMD is not set ++# CONFIG_PINCTRL_LPC18XX is not set ++CONFIG_PINCTRL_SINGLE=y ++# CONFIG_PINCTRL_ASPEED_G4 is not set ++# CONFIG_PINCTRL_ASPEED_G5 is not set ++# CONFIG_PINCTRL_BCM281XX is not set ++# CONFIG_PINCTRL_IPROC_GPIO is not set ++# CONFIG_PINCTRL_CYGNUS_MUX is not set ++# CONFIG_PINCTRL_NSP_GPIO is not set ++# CONFIG_PINCTRL_NS2_MUX is not set ++# CONFIG_PINCTRL_NSP_MUX is not set ++# CONFIG_PINCTRL_BERLIN_BG2 is not set ++# CONFIG_PINCTRL_BERLIN_BG2CD is not set ++# CONFIG_PINCTRL_BERLIN_BG2Q is not set ++# CONFIG_PINCTRL_BERLIN_BG4CT is not set ++# CONFIG_PINCTRL_PXA25X is not set ++# CONFIG_PINCTRL_PXA27X is not set ++# CONFIG_PINCTRL_APQ8064 is not set ++# CONFIG_PINCTRL_APQ8084 is not set ++# CONFIG_PINCTRL_IPQ4019 is not set ++# CONFIG_PINCTRL_IPQ8064 is not set ++# CONFIG_PINCTRL_MSM8660 is not set ++# CONFIG_PINCTRL_MSM8960 is not set ++# CONFIG_PINCTRL_MDM9615 is not set ++# CONFIG_PINCTRL_MSM8X74 is not set ++# CONFIG_PINCTRL_MSM8916 is not set ++# CONFIG_PINCTRL_MSM8996 is not set ++# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set ++# CONFIG_PINCTRL_STM32F429 is not set ++# CONFIG_PINCTRL_STM32F746 is not set ++# CONFIG_PINCTRL_UNIPHIER is not set ++# CONFIG_PINCTRL_MT2701 is not set ++# CONFIG_PINCTRL_MT7623 is not set ++# CONFIG_PINCTRL_MT8135 is not set ++# CONFIG_PINCTRL_MT8127 is not set ++# CONFIG_PINCTRL_MT8173 is not set ++# CONFIG_PINCTRL_MT6397 is not set ++CONFIG_GPIOLIB=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_GENERIC=y ++ ++# ++# Memory mapped GPIO drivers ++# ++# CONFIG_GPIO_74XX_MMIO is not set ++# CONFIG_GPIO_ALTERA is not set ++# CONFIG_GPIO_ASPEED is not set ++# CONFIG_GPIO_ATH79 is not set ++# CONFIG_GPIO_BCM_KONA is not set ++# CONFIG_GPIO_BRCMSTB is not set ++# CONFIG_GPIO_CLPS711X is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_ETRAXFS is not set ++CONFIG_GPIO_GENERIC_PLATFORM=y ++# CONFIG_GPIO_GRGPIO is not set ++# CONFIG_GPIO_IOP is not set ++# CONFIG_GPIO_LPC18XX is not set ++# CONFIG_GPIO_MB86S7X is not set ++# CONFIG_GPIO_MOCKUP is not set ++# CONFIG_GPIO_MOXART is not set ++# CONFIG_GPIO_MPC8XXX is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_RCAR is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_TEGRA is not set ++# CONFIG_GPIO_TS4800 is not set ++# CONFIG_GPIO_VX855 is not set ++# CONFIG_GPIO_XGENE is not set ++# CONFIG_GPIO_XILINX is not set ++# CONFIG_GPIO_XLP 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 ++# ++ ++# ++# PCI GPIO expanders ++# ++# CONFIG_GPIO_AMD8111 is not set ++# CONFIG_GPIO_BT8XX is not set ++# CONFIG_GPIO_ML_IOH is not set ++# CONFIG_GPIO_PCH is not set ++# CONFIG_GPIO_RDC321X 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++# CONFIG_POWER_RESET_HISI is not set ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_XGENE is not set ++# CONFIG_POWER_RESET_KEYSTONE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_POWER_RESET_RMOBILE is not set ++# CONFIG_POWER_RESET_ZX is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_ACT8945A is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_MANAGER is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24257 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_BQ25890 is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_BATTERY_GOLDFISH is not set ++# CONFIG_CHARGER_RT9455 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_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_MX25_TSADC is not set ++# CONFIG_MFD_HI6421_PMIC is not set ++# CONFIG_MFD_HI655X_PMIC is not set ++CONFIG_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_HTC_I2CPLD is not set ++# CONFIG_LPC_ICH is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_INTEL_SOC_PMIC is not set ++# CONFIG_MFD_JANZ_CMODIO 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_RDC321X is not set ++# CONFIG_MFD_RTSX_PCI 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=y ++# 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_TIMBERDALE is not set ++# CONFIG_MFD_TC3589X is not set ++# CONFIG_MFD_TMIO is not set ++# CONFIG_MFD_VX855 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_MFD_STW481X is not set ++CONFIG_REGULATOR=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_LTC3676 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MT6311 is not set ++# CONFIG_REGULATOR_PBIAS is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_PV88060 is not set ++# CONFIG_REGULATOR_PV88080 is not set ++# CONFIG_REGULATOR_PV88090 is not set ++# CONFIG_REGULATOR_QCOM_SPMI is not set ++# CONFIG_REGULATOR_STW481X_VMMC is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=y ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=y ++CONFIG_VIDEO_V4L2=y ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=y ++CONFIG_VIDEOBUF2_MEMOPS=y ++CONFIG_VIDEOBUF2_VMALLOC=y ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++CONFIG_MEDIA_USB_SUPPORT=y ++ ++# ++# Webcam devices ++# ++CONFIG_USB_VIDEO_CLASS=y ++CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y ++CONFIG_USB_GSPCA=m ++# CONFIG_USB_M5602 is not set ++# CONFIG_USB_STV06XX is not set ++# CONFIG_USB_GL860 is not set ++# CONFIG_USB_GSPCA_BENQ is not set ++# CONFIG_USB_GSPCA_CONEX is not set ++# CONFIG_USB_GSPCA_CPIA1 is not set ++# CONFIG_USB_GSPCA_DTCS033 is not set ++# CONFIG_USB_GSPCA_ETOMS is not set ++# CONFIG_USB_GSPCA_FINEPIX is not set ++# CONFIG_USB_GSPCA_JEILINJ is not set ++# CONFIG_USB_GSPCA_JL2005BCD is not set ++# CONFIG_USB_GSPCA_KINECT is not set ++# CONFIG_USB_GSPCA_KONICA is not set ++# CONFIG_USB_GSPCA_MARS is not set ++# CONFIG_USB_GSPCA_MR97310A is not set ++# CONFIG_USB_GSPCA_NW80X is not set ++# CONFIG_USB_GSPCA_OV519 is not set ++# CONFIG_USB_GSPCA_OV534 is not set ++# CONFIG_USB_GSPCA_OV534_9 is not set ++# CONFIG_USB_GSPCA_PAC207 is not set ++# CONFIG_USB_GSPCA_PAC7302 is not set ++# CONFIG_USB_GSPCA_PAC7311 is not set ++# CONFIG_USB_GSPCA_SE401 is not set ++# CONFIG_USB_GSPCA_SN9C2028 is not set ++# CONFIG_USB_GSPCA_SN9C20X is not set ++# CONFIG_USB_GSPCA_SONIXB is not set ++# CONFIG_USB_GSPCA_SONIXJ is not set ++# CONFIG_USB_GSPCA_SPCA500 is not set ++# CONFIG_USB_GSPCA_SPCA501 is not set ++# CONFIG_USB_GSPCA_SPCA505 is not set ++# CONFIG_USB_GSPCA_SPCA506 is not set ++# CONFIG_USB_GSPCA_SPCA508 is not set ++# CONFIG_USB_GSPCA_SPCA561 is not set ++# CONFIG_USB_GSPCA_SPCA1528 is not set ++# CONFIG_USB_GSPCA_SQ905 is not set ++# CONFIG_USB_GSPCA_SQ905C is not set ++# CONFIG_USB_GSPCA_SQ930X is not set ++# CONFIG_USB_GSPCA_STK014 is not set ++# CONFIG_USB_GSPCA_STK1135 is not set ++# CONFIG_USB_GSPCA_STV0680 is not set ++# CONFIG_USB_GSPCA_SUNPLUS is not set ++# CONFIG_USB_GSPCA_T613 is not set ++# CONFIG_USB_GSPCA_TOPRO is not set ++# CONFIG_USB_GSPCA_TOUPTEK is not set ++# CONFIG_USB_GSPCA_TV8532 is not set ++# CONFIG_USB_GSPCA_VC032X is not set ++# CONFIG_USB_GSPCA_VICAM is not set ++# CONFIG_USB_GSPCA_XIRLINK_CIT is not set ++# CONFIG_USB_GSPCA_ZC3XX is not set ++# CONFIG_USB_PWC is not set ++# CONFIG_VIDEO_CPIA2 is not set ++# CONFIG_USB_ZR364XX is not set ++# CONFIG_USB_STKWEBCAM is not set ++# CONFIG_USB_S2255 is not set ++ ++# ++# Webcam, TV (analog/digital) USB devices ++# ++# CONFIG_VIDEO_EM28XX is not set ++# CONFIG_MEDIA_PCI_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, spi, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# I2C Encoders, decoders, sensors and other helper chips ++# ++ ++# ++# Audio decoders, processors and mixers ++# ++# CONFIG_VIDEO_TVAUDIO is not set ++# CONFIG_VIDEO_TDA7432 is not set ++# CONFIG_VIDEO_TDA9840 is not set ++# CONFIG_VIDEO_TEA6415C is not set ++# CONFIG_VIDEO_TEA6420 is not set ++# CONFIG_VIDEO_MSP3400 is not set ++# CONFIG_VIDEO_CS3308 is not set ++# CONFIG_VIDEO_CS5345 is not set ++# CONFIG_VIDEO_CS53L32A is not set ++# CONFIG_VIDEO_TLV320AIC23B is not set ++# CONFIG_VIDEO_UDA1342 is not set ++# CONFIG_VIDEO_WM8775 is not set ++# CONFIG_VIDEO_WM8739 is not set ++# CONFIG_VIDEO_VP27SMPX is not set ++# CONFIG_VIDEO_SONY_BTF_MPX is not set ++ ++# ++# RDS decoders ++# ++# CONFIG_VIDEO_SAA6588 is not set ++ ++# ++# Video decoders ++# ++# CONFIG_VIDEO_ADV7183 is not set ++# CONFIG_VIDEO_BT819 is not set ++# CONFIG_VIDEO_BT856 is not set ++# CONFIG_VIDEO_BT866 is not set ++# CONFIG_VIDEO_KS0127 is not set ++# CONFIG_VIDEO_ML86V7667 is not set ++# CONFIG_VIDEO_SAA7110 is not set ++# CONFIG_VIDEO_SAA711X is not set ++# CONFIG_VIDEO_TVP514X is not set ++# CONFIG_VIDEO_TVP5150 is not set ++# CONFIG_VIDEO_TVP7002 is not set ++# CONFIG_VIDEO_TW2804 is not set ++# CONFIG_VIDEO_TW9903 is not set ++# CONFIG_VIDEO_TW9906 is not set ++# CONFIG_VIDEO_VPX3220 is not set ++ ++# ++# Video and audio decoders ++# ++# CONFIG_VIDEO_SAA717X is not set ++# CONFIG_VIDEO_CX25840 is not set ++ ++# ++# Video encoders ++# ++# CONFIG_VIDEO_SAA7127 is not set ++# CONFIG_VIDEO_SAA7185 is not set ++# CONFIG_VIDEO_ADV7170 is not set ++# CONFIG_VIDEO_ADV7175 is not set ++# CONFIG_VIDEO_ADV7343 is not set ++# CONFIG_VIDEO_ADV7393 is not set ++# CONFIG_VIDEO_AK881X is not set ++# CONFIG_VIDEO_THS8200 is not set ++ ++# ++# Camera sensor devices ++# ++# CONFIG_VIDEO_OV2659 is not set ++# CONFIG_VIDEO_OV7640 is not set ++# CONFIG_VIDEO_OV7670 is not set ++# CONFIG_VIDEO_VS6624 is not set ++# CONFIG_VIDEO_MT9M111 is not set ++# CONFIG_VIDEO_MT9V011 is not set ++# CONFIG_VIDEO_SR030PC30 is not set ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++# CONFIG_VIDEO_UPD64031A is not set ++# CONFIG_VIDEO_UPD64083 is not set ++ ++# ++# Audio/Video compression chips ++# ++# CONFIG_VIDEO_SAA6752HS is not set ++ ++# ++# Miscellaneous helper chips ++# ++# CONFIG_VIDEO_THS7303 is not set ++# CONFIG_VIDEO_M52790 is not set ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# SPI helper chips ++# ++ ++# ++# Customise DVB Frontends ++# ++# CONFIG_DVB_AU8522_V4L is not set ++# CONFIG_DVB_TUNER_DIB0070 is not set ++# CONFIG_DVB_TUNER_DIB0090 is not set ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++CONFIG_VGA_ARB=y ++CONFIG_VGA_ARB_MAX_GPUS=16 ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_CIRRUS is not set ++# CONFIG_FB_PM2 is not set ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CLPS711X is not set ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_NVIDIA is not set ++# CONFIG_FB_RIVA is not set ++# CONFIG_FB_I740 is not set ++# CONFIG_FB_MATROX is not set ++# CONFIG_FB_RADEON is not set ++# CONFIG_FB_ATY128 is not set ++# CONFIG_FB_ATY is not set ++# CONFIG_FB_S3 is not set ++# CONFIG_FB_SAVAGE is not set ++# CONFIG_FB_SIS is not set ++# CONFIG_FB_NEOMAGIC is not set ++# CONFIG_FB_KYRO is not set ++# CONFIG_FB_3DFX is not set ++# CONFIG_FB_VOODOO1 is not set ++# CONFIG_FB_VT8623 is not set ++# CONFIG_FB_TRIDENT is not set ++# CONFIG_FB_ARK is not set ++# CONFIG_FB_PM3 is not set ++# CONFIG_FB_CARMINE is not set ++# CONFIG_FB_TMIO is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_GOLDFISH is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_MB862XX is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_FB_SM712 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++CONFIG_DUMMY_CONSOLE_COLUMNS=80 ++CONFIG_DUMMY_CONSOLE_ROWS=25 ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++# CONFIG_HID_BETOP_FF is not set ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# 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 is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PCI=y ++CONFIG_USB_XHCI_PLATFORM=y ++# CONFIG_USB_XHCI_MTK is not set ++# CONFIG_USB_XHCI_MVEBU is not set ++# CONFIG_USB_XHCI_RCAR 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_UHCI_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 ++# CONFIG_USB_RENESAS_USBHS is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++# CONFIG_USB_WDM is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++# CONFIG_USBIP_CORE is not set ++# CONFIG_USB_MUSB_HDRC is not set ++CONFIG_USB_DWC3=y ++# CONFIG_USB_DWC3_HOST is not set ++CONFIG_USB_DWC3_GADGET=y ++# CONFIG_USB_DWC3_DUAL_ROLE is not set ++ ++# ++# Platform Glue Driver Support ++# ++CONFIG_USB_DWC3_EXYNOS=y ++CONFIG_USB_DWC3_PCI=y ++CONFIG_USB_DWC3_KEYSTONE=y ++CONFIG_USB_DWC3_OF_SIMPLE=y ++# CONFIG_USB_DWC2 is not set ++# CONFIG_USB_CHIPIDEA 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++# CONFIG_USB_GADGET_DEBUG_FS is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_RENESAS_USB3 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_BDC_UDC is not set ++# CONFIG_USB_AMD5536UDC is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_NET2280 is not set ++# CONFIG_USB_GOKU is not set ++# CONFIG_USB_EG20T is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_MASS_STORAGE=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM 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_ARMMMCI is not set ++CONFIG_MMC_SDHCI=y ++# CONFIG_MMC_SDHCI_PCI is not set ++CONFIG_MMC_SDHCI_PLTFM=y ++# CONFIG_MMC_SDHCI_OF_ARASAN is not set ++# CONFIG_MMC_SDHCI_OF_AT91 is not set ++CONFIG_MMC_SDHCI_HISI=y ++# CONFIG_MMC_SDHCI_PXAV3 is not set ++# CONFIG_MMC_SDHCI_PXAV2 is not set ++# CONFIG_MMC_SDHCI_F_SDH30 is not set ++# CONFIG_MMC_SDHCI_IPROC is not set ++# CONFIG_MMC_OMAP_HS is not set ++# CONFIG_MMC_TIFM_SD is not set ++# CONFIG_MMC_GOLDFISH is not set ++# CONFIG_MMC_SPI is not set ++# CONFIG_MMC_SDHI is not set ++# CONFIG_MMC_CB710 is not set ++# CONFIG_MMC_VIA_SDMMC is not set ++# CONFIG_MMC_DW is not set ++# CONFIG_MMC_SH_MMCIF is not set ++# CONFIG_MMC_VUB300 is not set ++# CONFIG_MMC_USHC is not set ++# CONFIG_MMC_USDHI6ROL0 is not set ++# CONFIG_MMC_TOSHIBA_PCI 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_INFINIBAND is not set ++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=y ++ ++# ++# SPI and I2C RTC drivers ++# ++# CONFIG_RTC_DRV_DS3232 is not set ++# CONFIG_RTC_DRV_PCF2127 is not set ++# CONFIG_RTC_DRV_RV3029C2 is not set ++ ++# ++# Platform RTC drivers ++# ++CONFIG_RTC_DRV_HIBVT=y ++# 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_SPEAR is not set ++# CONFIG_RTC_DRV_NUC900 is not set ++# CONFIG_RTC_DRV_ZYNQMP is not set ++ ++# ++# on-CPU RTC drivers ++# ++# CONFIG_RTC_DRV_ASM9260 is not set ++# CONFIG_RTC_DRV_DAVINCI is not set ++# CONFIG_RTC_DRV_DIGICOLOR is not set ++# CONFIG_RTC_DRV_OMAP is not set ++# CONFIG_RTC_DRV_S3C is not set ++# CONFIG_RTC_DRV_EP93XX is not set ++# CONFIG_RTC_DRV_VR41XX is not set ++# CONFIG_RTC_DRV_PL030 is not set ++# CONFIG_RTC_DRV_PL031 is not set ++# CONFIG_RTC_DRV_AT32AP700X is not set ++# CONFIG_RTC_DRV_AT91RM9200 is not set ++# CONFIG_RTC_DRV_AT91SAM9 is not set ++# CONFIG_RTC_DRV_GENERIC is not set ++# CONFIG_RTC_DRV_VT8500 is not set ++# CONFIG_RTC_DRV_SUNXI is not set ++# CONFIG_RTC_DRV_MV is not set ++# CONFIG_RTC_DRV_ARMADA38X is not set ++# CONFIG_RTC_DRV_GEMINI is not set ++# CONFIG_RTC_DRV_COH901331 is not set ++# CONFIG_RTC_DRV_STMP is not set ++# CONFIG_RTC_DRV_JZ4740 is not set ++# CONFIG_RTC_DRV_LPC24XX is not set ++# CONFIG_RTC_DRV_LPC32XX is not set ++# CONFIG_RTC_DRV_PM8XXX is not set ++# CONFIG_RTC_DRV_TEGRA is not set ++# CONFIG_RTC_DRV_SNVS is not set ++# CONFIG_RTC_DRV_MOXART is not set ++# CONFIG_RTC_DRV_MT6397 is not set ++# CONFIG_RTC_DRV_XGENE is not set ++ ++# ++# HID Sensor RTC drivers ++# ++# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set ++CONFIG_DMADEVICES=y ++# CONFIG_DMADEVICES_DEBUG is not set ++ ++# ++# DMA Devices ++# ++CONFIG_DMA_ENGINE=y ++CONFIG_DMA_VIRTUAL_CHANNELS=y ++CONFIG_DMA_OF=y ++# CONFIG_AMBA_PL08X is not set ++# CONFIG_AXI_DMAC is not set ++# CONFIG_COH901318 is not set ++# CONFIG_DMA_JZ4740 is not set ++# CONFIG_DMA_JZ4780 is not set ++# CONFIG_DMA_OMAP is not set ++# CONFIG_DMA_SA11X0 is not set ++# CONFIG_DMA_SUN6I is not set ++# CONFIG_EP93XX_DMA is not set ++# CONFIG_FSL_EDMA is not set ++# CONFIG_IMG_MDC_DMA is not set ++# CONFIG_INTEL_IDMA64 is not set ++# CONFIG_K3_DMA is not set ++# CONFIG_MMP_PDMA is not set ++# CONFIG_MMP_TDMA is not set ++# CONFIG_MV_XOR is not set ++# CONFIG_MV_XOR_V2 is not set ++# CONFIG_NBPFAXI_DMA is not set ++# CONFIG_PCH_DMA is not set ++# CONFIG_PL330_DMA is not set ++# CONFIG_STM32_DMA is not set ++# CONFIG_S3C24XX_DMAC is not set ++# CONFIG_TEGRA210_ADMA is not set ++# CONFIG_TIMB_DMA is not set ++# CONFIG_TI_EDMA is not set ++# CONFIG_XGENE_DMA is not set ++# CONFIG_XILINX_DMA is not set ++# CONFIG_XILINX_ZYNQMP_DMA is not set ++# CONFIG_ZX_DMA is not set ++CONFIG_HIEDMACV310=y ++# CONFIG_QCOM_HIDMA_MGMT is not set ++# CONFIG_QCOM_HIDMA is not set ++# CONFIG_DW_DMAC is not set ++# CONFIG_DW_DMAC_PCI is not set ++CONFIG_RENESAS_DMA=y ++CONFIG_SH_DMAE_BASE=y ++# CONFIG_SH_DMAE is not set ++# CONFIG_RCAR_DMAC is not set ++# CONFIG_RENESAS_USB_DMAC is not set ++# CONFIG_SUDMAC 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_PCI is not set ++# CONFIG_VIRTIO_MMIO is not set ++ ++# ++# Microsoft Hyper-V guest support ++# ++CONFIG_STAGING=y ++# CONFIG_COMEDI is not set ++# CONFIG_RTL8192U is not set ++# CONFIG_RTLLIB is not set ++# CONFIG_R8712U is not set ++# CONFIG_RTS5208 is not set ++# CONFIG_FB_SM750 is not set ++# CONFIG_FB_XGI is not set ++ ++# ++# Speakup console speech ++# ++# CONFIG_SPEAKUP is not set ++# CONFIG_STAGING_MEDIA is not set ++ ++# ++# Android ++# ++# CONFIG_ASHMEM is not set ++# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set ++CONFIG_ION=y ++# CONFIG_ION_TEST is not set ++# CONFIG_ION_DUMMY is not set ++# CONFIG_ION_OF is not set ++# CONFIG_STAGING_BOARD is not set ++# CONFIG_LTE_GDM724X is not set ++# CONFIG_MTD_SPINAND_MT29F is not set ++# CONFIG_LNET is not set ++# CONFIG_DGNC is not set ++# CONFIG_GS_FPGABOOT is not set ++# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set ++# CONFIG_FB_TFT is not set ++# CONFIG_FSL_MC_BUS is not set ++# CONFIG_MOST is not set ++# CONFIG_KS7010 is not set ++# CONFIG_GREYBUS 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_VERSATILE is not set ++# CONFIG_COMMON_CLK_SCPI is not set ++# 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_COMMON_CLK_AXI_CLKGEN is not set ++# CONFIG_CLK_QORIQ is not set ++# CONFIG_COMMON_CLK_XGENE is not set ++# CONFIG_COMMON_CLK_KEYSTONE is not set ++# CONFIG_COMMON_CLK_NXP is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++# CONFIG_COMMON_CLK_OXNAS is not set ++# CONFIG_CLK_BCM_63XX is not set ++# CONFIG_CLK_BCM_KONA is not set ++# CONFIG_COMMON_CLK_IPROC is not set ++# CONFIG_COMMON_CLK_HI3519 is not set ++# CONFIG_COMMON_CLK_HI3516A is not set ++# CONFIG_COMMON_CLK_HI3518EV20X is not set ++# CONFIG_COMMON_CLK_HI3536DV100 is not set ++CONFIG_COMMON_CLK_HI3559AV100=y ++CONFIG_COMMON_CLK_HI3521A=y ++CONFIG_COMMON_CLK_HI3531A=y ++# CONFIG_COMMON_CLK_HI6220 is not set ++CONFIG_RESET_HISI=y ++# CONFIG_COMMON_CLK_MT8135 is not set ++# CONFIG_COMMON_CLK_MT8173 is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++# CONFIG_COMMON_CLK_SAMSUNG is not set ++# CONFIG_S3C2410_COMMON_CLK is not set ++# CONFIG_S3C2412_COMMON_CLK is not set ++# CONFIG_S3C2443_COMMON_CLK is not set ++# CONFIG_SUNXI_CCU is not set ++# CONFIG_COMMON_CLK_TI_ADPLL is not set ++# CONFIG_CLK_UNIPHIER is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++# CONFIG_BCM2835_TIMER is not set ++# CONFIG_BCM_KONA_TIMER is not set ++# CONFIG_DIGICOLOR_TIMER is not set ++# CONFIG_DW_APB_TIMER is not set ++# CONFIG_ROCKCHIP_TIMER is not set ++# CONFIG_MESON6_TIMER is not set ++# CONFIG_SUN4I_TIMER is not set ++# CONFIG_SUN5I_HSTIMER is not set ++# CONFIG_VT8500_TIMER is not set ++# CONFIG_CADENCE_TTC_TIMER is not set ++# CONFIG_ASM9260_TIMER is not set ++# CONFIG_CLKSRC_DBX500_PRCMU is not set ++# CONFIG_CLPS711X_TIMER is not set ++# CONFIG_ATLAS7_TIMER is not set ++# CONFIG_MOXART_TIMER is not set ++# CONFIG_MXS_TIMER is not set ++# CONFIG_PRIMA2_TIMER is not set ++# CONFIG_NSPIRE_TIMER is not set ++# CONFIG_KEYSTONE_TIMER is not set ++# CONFIG_INTEGRATOR_AP_TIMER is not set ++# CONFIG_CLKSRC_PISTACHIO is not set ++# CONFIG_CLKSRC_TI_32K is not set ++# CONFIG_CLKSRC_MPS2 is not set ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set ++CONFIG_FSL_ERRATUM_A008585=y ++CONFIG_ARM_TIMER_SP804=y ++# CONFIG_TIMER_HISP804 is not set ++# CONFIG_ARMV7M_SYSTICK is not set ++# CONFIG_ATMEL_PIT is not set ++# CONFIG_ATMEL_ST is not set ++# CONFIG_CLKSRC_EXYNOS_MCT is not set ++# CONFIG_CLKSRC_SAMSUNG_PWM is not set ++# CONFIG_FSL_FTM_TIMER is not set ++# CONFIG_OXNAS_RPS_TIMER is not set ++# CONFIG_MTK_TIMER is not set ++# CONFIG_CLKSRC_JCORE_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_CLKSRC_VERSATILE is not set ++# CONFIG_CLKSRC_PXA is not set ++# CONFIG_H8300_TMR8 is not set ++# CONFIG_H8300_TMR16 is not set ++# CONFIG_H8300_TPU is not set ++# CONFIG_CLKSRC_ST_LPC 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_MTK_INFRACFG is not set ++# CONFIG_MTK_SCPSYS is not set ++# CONFIG_ROCKCHIP_PM_DOMAINS is not set ++# CONFIG_SOC_SAMSUNG is not set ++# CONFIG_SUNXI_SRAM is not set ++# CONFIG_SOC_TI is not set ++# CONFIG_UX500_SOC_ID is not set ++CONFIG_PM_DEVFREQ=y ++ ++# ++# DEVFREQ Governors ++# ++CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y ++# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set ++# CONFIG_DEVFREQ_GOV_POWERSAVE is not set ++# CONFIG_DEVFREQ_GOV_USERSPACE is not set ++# CONFIG_DEVFREQ_GOV_PASSIVE is not set ++ ++# ++# DEVFREQ Drivers ++# ++# CONFIG_ARM_EXYNOS_BUS_DEVFREQ is not set ++# CONFIG_PM_DEVFREQ_EVENT is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_NTB is not set ++# CONFIG_VME_BUS is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++CONFIG_ARM_GIC_V2M=y ++CONFIG_ARM_GIC_V3=y ++CONFIG_ARM_GIC_V3_ITS=y ++CONFIG_HISILICON_IRQ_MBIGEN=y ++# CONFIG_JCORE_AIC is not set ++# CONFIG_TS4800_IRQ is not set ++CONFIG_PARTITION_PERCPU=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_UNIPHIER is not set ++# CONFIG_RESET_ZYNQ is not set ++CONFIG_COMMON_RESET_HI6220=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_PHY_BCM_NS_USB2 is not set ++# CONFIG_PHY_BCM_NS_USB3 is not set ++CONFIG_ARMADA375_USBCLUSTER_PHY=y ++# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set ++# CONFIG_PHY_LPC18XX_USB_OTG is not set ++# CONFIG_PHY_PXA_28NM_HSIC is not set ++# CONFIG_PHY_PXA_28NM_USB2 is not set ++# CONFIG_OMAP_CONTROL_PHY is not set ++# CONFIG_PHY_EXYNOS_DP_VIDEO is not set ++# CONFIG_BCM_KONA_USB2_PHY is not set ++# CONFIG_PHY_HI6220_USB is not set ++# CONFIG_PHY_ROCKCHIP_INNO_USB2 is not set ++# CONFIG_PHY_ROCKCHIP_PCIE is not set ++# CONFIG_PHY_ROCKCHIP_TYPEC is not set ++# CONFIG_PHY_ST_SPEAR1310_MIPHY is not set ++# CONFIG_PHY_ST_SPEAR1340_MIPHY is not set ++# CONFIG_PHY_XGENE is not set ++# CONFIG_PHY_STIH407_USB is not set ++# CONFIG_PHY_BRCM_SATA is not set ++# CONFIG_PHY_CYGNUS_PCIE is not set ++CONFIG_HISI_PHY_USB3=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++ ++# ++# Performance monitor support ++# ++CONFIG_ARM_PMU=y ++# CONFIG_RAS is not set ++# CONFIG_THUNDERBOLT is not set ++ ++# ++# Android ++# ++CONFIG_ANDROID=y ++# CONFIG_ANDROID_BINDER_IPC is not set ++# CONFIG_LIBNVDIMM 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 ++# CONFIG_HI_DMAC is not set ++# CONFIG_HIVDMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE is not set ++ ++# ++# Firmware Drivers ++# ++CONFIG_ARM_PSCI_FW=y ++CONFIG_ARM_SCPI_POWER_DOMAIN=y ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++# CONFIG_MESON_SM is not set ++# CONFIG_ACPI is not set ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++CONFIG_FS_IOMAP=y ++CONFIG_EXT2_FS=y ++CONFIG_EXT2_FS_XATTR=y ++CONFIG_EXT2_FS_POSIX_ACL=y ++CONFIG_EXT2_FS_SECURITY=y ++CONFIG_EXT3_FS=y ++CONFIG_EXT3_FS_POSIX_ACL=y ++CONFIG_EXT3_FS_SECURITY=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_CHECK=y ++CONFIG_REISERFS_PROC_INFO=y ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_DEBUG=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++# CONFIG_XFS_WARN is not set ++# CONFIG_XFS_DEBUG is not set ++# CONFIG_GFS2_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_DAX is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_EXPORTFS=m ++# 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=y ++# CONFIG_QUOTA_NETLINK_INTERFACE is not set ++CONFIG_PRINT_QUOTA_WARNING=y ++# CONFIG_QUOTA_DEBUG is not set ++CONFIG_QUOTA_TREE=m ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_QUOTACTL=y ++CONFIG_AUTOFS4_FS=m ++CONFIG_FUSE_FS=y ++# CONFIG_CUSE is not set ++# CONFIG_OVERLAY_FS is not set ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=y ++# CONFIG_JOLIET is not set ++# CONFIG_ZISOFS is not set ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++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_KCORE is not set ++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=y ++CONFIG_TMPFS_XATTR=y ++# CONFIG_HUGETLBFS is not set ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_ARCH_HAS_GIGANTIC_PAGE=y ++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_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++CONFIG_SQUASHFS=y ++CONFIG_SQUASHFS_FILE_CACHE=y ++# CONFIG_SQUASHFS_FILE_DIRECT is not set ++CONFIG_SQUASHFS_DECOMP_SINGLE=y ++# CONFIG_SQUASHFS_DECOMP_MULTI is not set ++# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set ++# CONFIG_SQUASHFS_XATTR is not set ++CONFIG_SQUASHFS_ZLIB=y ++# CONFIG_SQUASHFS_LZ4 is not set ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set ++# CONFIG_SQUASHFS_EMBEDDED is not set ++CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 ++# 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFSD is not set ++CONFIG_GRACE_PERIOD=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=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=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=y ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++# 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 ++# CONFIG_VIRTUALIZATION is not set ++ ++# ++# Kernel hacking ++# ++ ++# ++# printk and dmesg options ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++# 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=2048 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++CONFIG_ARCH_WANT_FRAME_POINTERS=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++CONFIG_HAVE_ARCH_KASAN=y ++# CONFIG_KASAN is not set ++CONFIG_ARCH_HAS_KCOV=y ++# CONFIG_KCOV is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++CONFIG_LOCKUP_DETECTOR=y ++# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set ++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 ++# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set ++CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 ++# CONFIG_WQ_WATCHDOG is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++CONFIG_SCHED_INFO=y ++CONFIG_SCHEDSTATS=y ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_HAVE_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_PROVE_RCU is not set ++CONFIG_SPARSE_RCU_POINTER=y ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=21 ++CONFIG_RCU_TRACE=y ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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_TRACE_CLOCK=y ++CONFIG_TRACING_SUPPORT=y ++# CONFIG_FTRACE is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_LKDTM is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=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_ARM64_PTDUMP is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_DEBUG_ALIGN_RODATA is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS 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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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 is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++CONFIG_CRYPTO_NULL=m ++CONFIG_CRYPTO_NULL2=y ++# CONFIG_CRYPTO_PCRYPT is not set ++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=m ++# CONFIG_CRYPTO_GCM is not set ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# 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=y ++CONFIG_CRYPTO_HMAC=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# 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 is not set ++# 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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_CRYPTO_DEV_S5P is not set ++# CONFIG_CRYPTO_DEV_ATMEL_AES is not set ++# CONFIG_CRYPTO_DEV_CCP is not set ++# CONFIG_CRYPTO_DEV_QCE is not set ++# CONFIG_CRYPTO_DEV_IMGTEC_HASH is not set ++ ++# ++# Certificates for signature checking ++# ++# CONFIG_ARM64_CRYPTO is not set ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++CONFIG_HAVE_ARCH_BITREVERSE=y ++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=y ++CONFIG_CRC16=y ++# CONFIG_CRC_T10DIF is not set ++CONFIG_CRC_ITU_T=y ++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=m ++# CONFIG_CRC8 is not set ++CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y ++# CONFIG_RANDOM32_SELFTEST is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=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_GZIP=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_NLATTR=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=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y +diff --git a/arch/arm64/configs/hi3559av100_arm64_big_little_ufs_amp_defconfig b/arch/arm64/configs/hi3559av100_arm64_big_little_ufs_amp_defconfig +new file mode 100644 +index 0000000..52a9fa9 +--- /dev/null ++++ b/arch/arm64/configs/hi3559av100_arm64_big_little_ufs_amp_defconfig +@@ -0,0 +1,3852 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm64 4.9.37 Kernel Configuration ++# ++CONFIG_ARM64=y ++CONFIG_64BIT=y ++CONFIG_ARCH_PHYS_ADDR_T_64BIT=y ++CONFIG_MMU=y ++CONFIG_DEBUG_RODATA=y ++CONFIG_ARM64_PAGE_SHIFT=12 ++CONFIG_ARM64_CONT_SHIFT=4 ++CONFIG_ARCH_MMAP_RND_BITS_MIN=18 ++CONFIG_ARCH_MMAP_RND_BITS_MAX=24 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=y ++CONFIG_GENERIC_BUG=y ++CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CSUM=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_ZONE_DMA=y ++CONFIG_HAVE_GENERIC_RCU_GUP=y ++CONFIG_ARCH_DMA_ADDR_T_64BIT=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_NEED_SG_DMA_LENGTH=y ++CONFIG_SMP=y ++CONFIG_SWIOTLB=y ++CONFIG_IOMMU_HELPER=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_FIX_EARLYCON_MEM=y ++CONFIG_PGTABLE_LEVELS=3 ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++CONFIG_COMPILE_TEST=y ++CONFIG_LOCALVERSION="" ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_GENERIC_IRQ_MIGRATION=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_GENERIC_MSI_IRQ=y ++CONFIG_GENERIC_MSI_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++# CONFIG_IRQ_DOMAIN_DEBUG is not set ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_HZ_PERIODIC=y ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NO_HZ_FULL 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_TREE_RCU=y ++# CONFIG_RCU_EXPERT is not set ++CONFIG_SRCU=y ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++CONFIG_TREE_RCU_TRACE=y ++# CONFIG_RCU_EXPEDITE_BOOT is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=14 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y ++# CONFIG_CGROUPS is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++CONFIG_RELAY=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++# CONFIG_RD_LZ4 is not set ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_SYSCTL_EXCEPTION_TRACE=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_ALL is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y ++CONFIG_BPF_SYSCALL=y ++CONFIG_SHMEM=y ++CONFIG_AIO=y ++CONFIG_ADVISE_SYSCALLS=y ++CONFIG_USERFAULTFD=y ++CONFIG_PCI_QUIRKS=y ++CONFIG_MEMBARRIER=y ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++ ++# ++# Kernel Performance Events And Counters ++# ++CONFIG_PERF_EVENTS=y ++# CONFIG_DEBUG_PERF_USE_VMALLOC is not set ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_SLAB_FREELIST_RANDOM is not set ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_SYSTEM_DATA_VERIFICATION is not set ++# CONFIG_PROFILING is not set ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL is not set ++# CONFIG_UPROBES is not set ++# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set ++CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=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_HW_BREAKPOINT=y ++CONFIG_HAVE_PERF_REGS=y ++CONFIG_HAVE_PERF_USER_STACK_DUMP=y ++CONFIG_HAVE_ARCH_JUMP_LABEL=y ++CONFIG_HAVE_RCU_TABLE_FREE=y ++CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y ++CONFIG_HAVE_CMPXCHG_LOCAL=y ++CONFIG_HAVE_CMPXCHG_DOUBLE=y ++CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y ++CONFIG_HAVE_ARCH_SECCOMP_FILTER=y ++CONFIG_HAVE_GCC_PLUGINS=y ++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_ARCH_TRANSPARENT_HUGEPAGE=y ++CONFIG_HAVE_ARCH_HUGE_VMAP=y ++CONFIG_MODULES_USE_ELF_RELA=y ++CONFIG_ARCH_HAS_ELF_RANDOMIZE=y ++CONFIG_HAVE_ARCH_MMAP_RND_BITS=y ++CONFIG_ARCH_MMAP_RND_BITS=18 ++CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 ++# CONFIG_HAVE_ARCH_HASH is not set ++# CONFIG_ISA_BUS_API is not set ++CONFIG_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_COMPAT_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_SLABINFO=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_MODULES_TREE_LOOKUP=y ++CONFIG_BLOCK=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++CONFIG_BLOCK_COMPAT=y ++CONFIG_BLK_MQ_PCI=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_LOCK_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# Platform selection ++# ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_BCM2835 is not set ++# CONFIG_ARCH_BCM_IPROC is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_BRCMSTB is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_LAYERSCAPE is not set ++# CONFIG_ARCH_LG1K is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++CONFIG_ARCH_HI3559AV100=y ++# CONFIG_ACCESS_M7_DEV is not set ++CONFIG_ARCH_HISI_BVT_AMP=y ++# CONFIG_ARCH_MEDIATEK is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SEATTLE is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_STRATIX10 is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_SPRD is not set ++# CONFIG_ARCH_THUNDER is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_VULCAN is not set ++# CONFIG_ARCH_XGENE is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQMP is not set ++ ++# ++# Bus support ++# ++CONFIG_PCI=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_PCI_DOMAINS_GENERIC=y ++CONFIG_PCI_SYSCALL=y ++CONFIG_PCIEPORTBUS=y ++# CONFIG_PCIEAER is not set ++# CONFIG_PCIEASPM is not set ++# CONFIG_PCIE_PME is not set ++# CONFIG_PCIE_DPC is not set ++# CONFIG_PCIE_PTM is not set ++CONFIG_PCI_BUS_ADDR_T_64BIT=y ++CONFIG_PCI_MSI=y ++CONFIG_PCI_MSI_IRQ_DOMAIN=y ++# CONFIG_PCI_DEBUG is not set ++# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set ++# CONFIG_PCI_STUB is not set ++# CONFIG_PCI_IOV is not set ++# CONFIG_PCI_PRI is not set ++# CONFIG_PCI_PASID is not set ++# CONFIG_HOTPLUG_PCI is not set ++ ++# ++# PCI host controller drivers ++# ++# CONFIG_PCIE_DW_PLAT is not set ++# CONFIG_PCI_HOST_GENERIC is not set ++# CONFIG_PCI_HISI is not set ++# CONFIG_PCI_HOST_THUNDER_PEM is not set ++# CONFIG_PCI_HOST_THUNDER_ECAM is not set ++# CONFIG_HIPCIE is not set ++ ++# ++# Kernel Features ++# ++ ++# ++# ARM errata workarounds via the alternatives framework ++# ++CONFIG_ARM64_ERRATUM_826319=y ++CONFIG_ARM64_ERRATUM_827319=y ++CONFIG_ARM64_ERRATUM_824069=y ++CONFIG_ARM64_ERRATUM_819472=y ++CONFIG_ARM64_ERRATUM_832075=y ++CONFIG_ARM64_ERRATUM_845719=y ++CONFIG_ARM64_ERRATUM_843419=y ++CONFIG_CAVIUM_ERRATUM_22375=y ++CONFIG_CAVIUM_ERRATUM_23154=y ++CONFIG_CAVIUM_ERRATUM_27456=y ++CONFIG_QCOM_QDF2400_ERRATUM_0065=y ++CONFIG_ARM64_4K_PAGES=y ++# CONFIG_ARM64_16K_PAGES is not set ++# CONFIG_ARM64_64K_PAGES is not set ++CONFIG_ARM64_VA_BITS_39=y ++# CONFIG_ARM64_VA_BITS_48 is not set ++CONFIG_ARM64_VA_BITS=39 ++# CONFIG_CPU_BIG_ENDIAN is not set ++CONFIG_SCHED_MC=y ++# CONFIG_SCHED_SMT is not set ++CONFIG_NR_CPUS=64 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_NUMA is not set ++CONFIG_PREEMPT_NONE=y ++# CONFIG_PREEMPT_VOLUNTARY is not set ++# CONFIG_PREEMPT is not set ++# CONFIG_HZ_100 is not set ++# CONFIG_HZ_250 is not set ++# CONFIG_HZ_300 is not set ++CONFIG_HZ_1000=y ++CONFIG_HZ=1000 ++# CONFIG_SCHED_HRTICK is not set ++CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y ++CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y ++CONFIG_ARCH_SPARSEMEM_ENABLE=y ++CONFIG_ARCH_SPARSEMEM_DEFAULT=y ++CONFIG_ARCH_SELECT_MEMORY_MODEL=y ++CONFIG_HAVE_ARCH_PFN_VALID=y ++CONFIG_HW_PERF_EVENTS=y ++CONFIG_SYS_SUPPORTS_HUGETLBFS=y ++CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y ++CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_SPARSEMEM_MANUAL=y ++CONFIG_SPARSEMEM=y ++CONFIG_HAVE_MEMORY_PRESENT=y ++CONFIG_SPARSEMEM_EXTREME=y ++CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y ++CONFIG_SPARSEMEM_VMEMMAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=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=y ++CONFIG_BOUNCE=y ++CONFIG_KSM=y ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# CONFIG_TRANSPARENT_HUGEPAGE is not set ++# CONFIG_CLEANCACHE is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++# CONFIG_CMA_DEBUGFS is not set ++CONFIG_CMA_AREAS=7 ++# 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_FRAME_VECTOR=y ++# CONFIG_SECCOMP is not set ++# CONFIG_PARAVIRT is not set ++# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set ++# CONFIG_KEXEC is not set ++# CONFIG_XEN is not set ++CONFIG_FORCE_MAX_ZONEORDER=11 ++# CONFIG_ARMV8_DEPRECATED is not set ++ ++# ++# ARMv8.1 architectural features ++# ++CONFIG_ARM64_HW_AFDBM=y ++CONFIG_ARM64_PAN=y ++# CONFIG_ARM64_LSE_ATOMICS is not set ++CONFIG_ARM64_VHE=y ++ ++# ++# ARMv8.2 architectural features ++# ++CONFIG_ARM64_UAO=y ++CONFIG_ARM64_MODULE_CMODEL_LARGE=y ++# CONFIG_RANDOMIZE_BASE is not set ++ ++# ++# Boot options ++# ++CONFIG_CMDLINE="mem=128M console=ttyAMA0,115200 console=ttyMTD,blackbox" ++# CONFIG_CMDLINE_FORCE is not set ++# CONFIG_EFI is not set ++CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y ++CONFIG_IMG_GZ_DTB=y ++# CONFIG_IMG_DTB is not set ++CONFIG_BUILD_ARM64_APPENDED_KERNEL_IMAGE_NAME="Image.gz-dtb" ++CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES="hisilicon/hi3559av100-demb-ufs" ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_COMPAT_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++CONFIG_COMPAT=y ++CONFIG_SYSVIPC_COMPAT=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_SUSPEND_SKIP_SYNC is not set ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++CONFIG_PM_CLK=y ++CONFIG_PM_GENERIC_DOMAINS=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_PM_GENERIC_DOMAINS_SLEEP=y ++CONFIG_PM_GENERIC_DOMAINS_OF=y ++CONFIG_CPU_PM=y ++CONFIG_ARCH_HIBERNATION_POSSIBLE=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Idle ++# ++# CONFIG_CPU_IDLE is not set ++# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_ATTR_SET=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_STAT_DETAILS=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set ++ ++# ++# CPU frequency scaling drivers ++# ++# CONFIG_CPUFREQ_DT is not set ++# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++CONFIG_NET=y ++CONFIG_NET_INGRESS=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 is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++CONFIG_NET_IP_TUNNEL=m ++# 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=m ++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=y ++# CONFIG_IPV6_ROUTE_INFO 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_IPV6_ILA is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# 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=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++CONFIG_NETFILTER_INGRESS=y ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_DUP_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_DUP_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_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_QRTR is not set ++# CONFIG_NET_NCSI is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_SOCK_CGROUP_DATA is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_EBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER=y ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++# CONFIG_DEVTMPFS is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_GENERIC_CPU_AUTOPROBE=y ++CONFIG_REGMAP=y ++CONFIG_REGMAP_I2C=y ++CONFIG_REGMAP_SPI=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=4 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_ARM_CCI400_PMU is not set ++# CONFIG_ARM_CCI5xx_PMU is not set ++# CONFIG_ARM_CCN is not set ++# CONFIG_QCOM_EBI2 is not set ++# CONFIG_SIMPLE_PM_BUS 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 ++# CONFIG_MTD_BCM63XX_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_TS5500 is not set ++# CONFIG_MTD_INTEL_VR_NOR is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_DATAFLASH is not set ++# CONFIG_MTD_M25P80 is not set ++# 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=y ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOCG3 is not set ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_PCI is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_RICOH is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_VF610_NFC is not set ++# CONFIG_MTD_NAND_SH_FLCTL is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++CONFIG_MTD_SPI_NAND_HISI_BVT=y ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++CONFIG_MTD_SPI_NAND_HIFMC100=y ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# LPDDR & LPDDR2 PCM memory drivers ++# ++# CONFIG_MTD_LPDDR is not set ++CONFIG_MTD_SPI_NOR=y ++# CONFIG_MTD_MT81xx_NOR is not set ++# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set ++# CONFIG_SPI_FSL_QUADSPI is not set ++CONFIG_SPI_HISI_SFC=y ++# CONFIG_SPI_NXP_SPIFI is not set ++# CONFIG_MTD_SPI_IDS is not set ++# CONFIG_CLOSE_SPI_8PIN_4IO is not set ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++# CONFIG_MTD_UBI is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++# CONFIG_OF_UNITTEST is not set ++# CONFIG_OF_ALL_DTBS is not set ++CONFIG_OF_FLATTREE=y ++CONFIG_OF_EARLY_FLATTREE=y ++CONFIG_OF_ADDRESS=y ++CONFIG_OF_ADDRESS_PCI=y ++CONFIG_OF_IRQ=y ++CONFIG_OF_NET=y ++CONFIG_OF_MDIO=y ++CONFIG_OF_PCI=y ++CONFIG_OF_PCI_IRQ=y ++CONFIG_OF_RESERVED_MEM=y ++# CONFIG_OF_OVERLAY is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set ++# CONFIG_BLK_CPQ_CISS_DA is not set ++# CONFIG_BLK_DEV_DAC960 is not set ++# CONFIG_BLK_DEV_UMEM is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_SKD is not set ++# CONFIG_BLK_DEV_SX8 is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_BLK_DEV_RSXX is not set ++# CONFIG_BLK_DEV_NVME is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# CONFIG_SENSORS_LIS3LV02D is not set ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_DUMMY_IRQ is not set ++# CONFIG_PHANTOM is not set ++# CONFIG_INTEL_MID_PTI is not set ++# CONFIG_SGI_IOC4 is not set ++# CONFIG_TIFM_CORE is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ATMEL_SSC is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_HP_ILO is not set ++# CONFIG_QCOM_COINCELL 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_PCH_PHUB 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 ++# CONFIG_CB710_CORE 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_GENWQE is not set ++# 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=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_SCSI_CXGB3_ISCSI is not set ++# CONFIG_SCSI_CXGB4_ISCSI is not set ++# CONFIG_SCSI_BNX2_ISCSI is not set ++# CONFIG_BE2ISCSI is not set ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_HPSA is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_3W_SAS is not set ++# CONFIG_SCSI_ACARD is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX is not set ++# CONFIG_SCSI_AIC79XX is not set ++# CONFIG_SCSI_AIC94XX is not set ++# CONFIG_SCSI_HISI_SAS is not set ++# CONFIG_SCSI_MVSAS is not set ++# CONFIG_SCSI_MVUMI is not set ++# CONFIG_SCSI_ADVANSYS is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_SCSI_ESAS2R is not set ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++# CONFIG_SCSI_MPT3SAS is not set ++# CONFIG_SCSI_MPT2SAS is not set ++# CONFIG_SCSI_SMARTPQI is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_SCSI_HPTIOP is not set ++# CONFIG_SCSI_SNIC is not set ++# CONFIG_SCSI_DMX3191D is not set ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_IPS is not set ++# CONFIG_SCSI_INITIO is not set ++# CONFIG_SCSI_INIA100 is not set ++# CONFIG_SCSI_STEX is not set ++# CONFIG_SCSI_SYM53C8XX_2 is not set ++# CONFIG_SCSI_QLOGIC_1280 is not set ++# CONFIG_SCSI_QLA_ISCSI is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_AM53C974 is not set ++# CONFIG_SCSI_WD719X is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_PMCRAID is not set ++# CONFIG_SCSI_PM8001 is not set ++# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HAVE_PATA_PLATFORM=y ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++# CONFIG_FUSION is not set ++ ++# ++# IEEE 1394 (FireWire) support ++# ++# CONFIG_FIREWIRE is not set ++# CONFIG_FIREWIRE_NOSY is not set ++CONFIG_NETDEVICES=y ++CONFIG_NET_CORE=y ++# CONFIG_BONDING is not set ++# CONFIG_DUMMY is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC 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 ++# CONFIG_ARCNET is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++CONFIG_ETHERNET=y ++CONFIG_NET_VENDOR_3COM=y ++# CONFIG_VORTEX is not set ++# CONFIG_TYPHOON is not set ++CONFIG_NET_VENDOR_ADAPTEC=y ++# CONFIG_ADAPTEC_STARFIRE is not set ++CONFIG_NET_VENDOR_AGERE=y ++# CONFIG_ET131X is not set ++CONFIG_NET_VENDOR_ALTEON=y ++# CONFIG_ACENIC is not set ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_VENDOR_AMAZON is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC is not set ++CONFIG_NET_VENDOR_ATHEROS=y ++# CONFIG_ATL2 is not set ++# CONFIG_ATL1 is not set ++# CONFIG_ATL1E is not set ++# CONFIG_ATL1C is not set ++# CONFIG_ALX 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_BROCADE=y ++# CONFIG_BNA is not set ++# CONFIG_NET_CALXEDA_XGMAC is not set ++CONFIG_NET_VENDOR_CAVIUM=y ++# CONFIG_THUNDER_NIC_PF is not set ++# CONFIG_THUNDER_NIC_VF is not set ++# CONFIG_THUNDER_NIC_BGX is not set ++# CONFIG_THUNDER_NIC_RGX is not set ++# CONFIG_LIQUIDIO is not set ++CONFIG_NET_VENDOR_CHELSIO=y ++# CONFIG_CHELSIO_T1 is not set ++# CONFIG_CHELSIO_T3 is not set ++# CONFIG_CHELSIO_T4 is not set ++# CONFIG_CHELSIO_T4VF is not set ++CONFIG_NET_VENDOR_CISCO=y ++# CONFIG_ENIC is not set ++# CONFIG_CX_ECAT is not set ++# CONFIG_DNET is not set ++CONFIG_NET_VENDOR_DEC=y ++# CONFIG_NET_TULIP is not set ++CONFIG_NET_VENDOR_DLINK=y ++# CONFIG_DL2K is not set ++# CONFIG_SUNDANCE is not set ++CONFIG_NET_VENDOR_EMULEX=y ++# CONFIG_BE2NET is not set ++# CONFIG_NET_VENDOR_EZCHIP is not set ++CONFIG_NET_VENDOR_EXAR=y ++# CONFIG_S2IO is not set ++# CONFIG_VXGE is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DDR_64BIT=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++CONFIG_NET_VENDOR_HP=y ++# CONFIG_HP100 is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_JME is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++CONFIG_NET_VENDOR_MELLANOX=y ++# CONFIG_MLX4_EN is not set ++# CONFIG_MLX4_CORE is not set ++# CONFIG_MLX5_CORE is not set ++# CONFIG_MLXSW_CORE is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_MICROCHIP is not set ++CONFIG_NET_VENDOR_MYRI=y ++# CONFIG_MYRI10GE is not set ++# CONFIG_FEALNX is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NETRONOME is not set ++CONFIG_NET_VENDOR_NVIDIA=y ++# CONFIG_FORCEDETH is not set ++CONFIG_NET_VENDOR_OKI=y ++# CONFIG_PCH_GBE is not set ++# CONFIG_ETHOC is not set ++CONFIG_NET_PACKET_ENGINE=y ++# CONFIG_HAMACHI is not set ++# CONFIG_YELLOWFIN is not set ++CONFIG_NET_VENDOR_QLOGIC=y ++# CONFIG_QLA3XXX is not set ++# CONFIG_QLCNIC is not set ++# CONFIG_QLGE is not set ++# CONFIG_NETXEN_NIC is not set ++# CONFIG_QED is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++CONFIG_NET_VENDOR_REALTEK=y ++# CONFIG_8139CP is not set ++# CONFIG_8139TOO is not set ++# CONFIG_R8169 is not set ++# CONFIG_NET_VENDOR_RENESAS is not set ++CONFIG_NET_VENDOR_RDC=y ++# CONFIG_R6040 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_SILAN=y ++# CONFIG_SC92031 is not set ++CONFIG_NET_VENDOR_SIS=y ++# CONFIG_SIS900 is not set ++# CONFIG_SIS190 is not set ++# CONFIG_SFC is not set ++# CONFIG_NET_VENDOR_SMSC is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++CONFIG_NET_VENDOR_SUN=y ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++# CONFIG_NIU is not set ++# CONFIG_NET_VENDOR_SYNOPSYS is not set ++CONFIG_NET_VENDOR_TEHUTI=y ++# CONFIG_TEHUTI is not set ++CONFIG_NET_VENDOR_TI=y ++# CONFIG_TI_CPSW_ALE is not set ++# CONFIG_TLAN is not set ++# CONFIG_NET_VENDOR_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_FDDI is not set ++# CONFIG_HIPPI is not set ++CONFIG_PHYLIB=y ++CONFIG_SWPHY=y ++ ++# ++# MDIO bus device drivers ++# ++# CONFIG_MDIO_BCM_IPROC is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_BCM_IPROC 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 ++CONFIG_MDIO_HISI_GEMAC=y ++# CONFIG_MDIO_OCTEON is not set ++# CONFIG_MDIO_THUNDER is not set ++# CONFIG_MDIO_XGENE 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_IPHETH is not set ++CONFIG_WLAN=y ++CONFIG_WLAN_VENDOR_ADMTEK=y ++CONFIG_WLAN_VENDOR_ATH=y ++# CONFIG_ATH_DEBUG is not set ++# CONFIG_ATH5K_PCI is not set ++CONFIG_WLAN_VENDOR_ATMEL=y ++CONFIG_WLAN_VENDOR_BROADCOM=y ++CONFIG_WLAN_VENDOR_CISCO=y ++CONFIG_WLAN_VENDOR_INTEL=y ++CONFIG_WLAN_VENDOR_INTERSIL=y ++# CONFIG_HOSTAP is not set ++# CONFIG_PRISM54 is not set ++CONFIG_WLAN_VENDOR_MARVELL=y ++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 ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_VMXNET3 is not set ++# CONFIG_ISDN is not set ++# CONFIG_NVM is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++CONFIG_INPUT_FF_MEMLESS=y ++# CONFIG_INPUT_POLLDEV is not set ++# CONFIG_INPUT_SPARSEKMAP is not set ++# CONFIG_INPUT_MATRIXKMAP is not set ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_CLPS711X is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_GOLDFISH_EVENTS is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_ST_KEYSCAN is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_SH_KEYSC is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++CONFIG_INPUT_JOYSTICK=y ++# CONFIG_JOYSTICK_ANALOG is not set ++# CONFIG_JOYSTICK_A3D is not set ++# CONFIG_JOYSTICK_ADI is not set ++# CONFIG_JOYSTICK_COBRA is not set ++# CONFIG_JOYSTICK_GF2K is not set ++# CONFIG_JOYSTICK_GRIP is not set ++# CONFIG_JOYSTICK_GRIP_MP is not set ++# CONFIG_JOYSTICK_GUILLEMOT is not set ++# CONFIG_JOYSTICK_INTERACT is not set ++# CONFIG_JOYSTICK_SIDEWINDER is not set ++# CONFIG_JOYSTICK_TMDC is not set ++# CONFIG_JOYSTICK_IFORCE is not set ++# CONFIG_JOYSTICK_WARRIOR is not set ++# CONFIG_JOYSTICK_MAGELLAN is not set ++# CONFIG_JOYSTICK_SPACEORB is not set ++# CONFIG_JOYSTICK_SPACEBALL is not set ++# CONFIG_JOYSTICK_STINGER is not set ++# CONFIG_JOYSTICK_TWIDJOY is not set ++# CONFIG_JOYSTICK_ZHENHUA is not set ++# CONFIG_JOYSTICK_AS5011 is not set ++# CONFIG_JOYSTICK_JOYDUMP is not set ++# CONFIG_JOYSTICK_XPAD is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_GP2A is not set ++# CONFIG_INPUT_GPIO_BEEPER is not set ++# CONFIG_INPUT_GPIO_TILT_POLLED is not set ++# CONFIG_INPUT_GPIO_DECODER is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INPUT_CM109 is not set ++# CONFIG_INPUT_REGULATOR_HAPTIC is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV260X_HAPTICS is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_INPUT_HISI_POWERKEY is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_SERIO_OLPC_APSP is not set ++# CONFIG_SERIO_SUN4I_PS2 is not set ++# CONFIG_USERIO is not set ++CONFIG_GAMEPORT=y ++# CONFIG_GAMEPORT_NS558 is not set ++# CONFIG_GAMEPORT_L4 is not set ++# CONFIG_GAMEPORT_EMU10K1 is not set ++# CONFIG_GAMEPORT_FM801 is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_NOZOMI is not set ++# CONFIG_N_GSM is not set ++# CONFIG_TRACE_SINK is not set ++CONFIG_DEVMEM=y ++CONFIG_DEVKMEM=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_ATMEL is not set ++# CONFIG_SERIAL_CLPS711X is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X is not set ++# CONFIG_SERIAL_IMX is not set ++# CONFIG_SERIAL_UARTLITE is not set ++# CONFIG_SERIAL_SH_SCI is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_JSM is not set ++# CONFIG_SERIAL_SCCNXP is not set ++# CONFIG_SERIAL_SC16IS7XX is not set ++# CONFIG_SERIAL_TIMBERDALE is not set ++# CONFIG_SERIAL_BCM63XX is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_IFX6X60 is not set ++# CONFIG_SERIAL_PCH_UART is not set ++# CONFIG_SERIAL_MXS_AUART is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++# CONFIG_SERIAL_MPS2_UART is not set ++# CONFIG_SERIAL_ARC is not set ++# CONFIG_SERIAL_RP2 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_SERIAL_MVEBU_UART 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_APPLICOM is not set ++ ++# ++# PCMCIA character devices ++# ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_DEVPORT=y ++# 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=y ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set ++# CONFIG_I2C_MUX_GPIO is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PCA954x is not set ++# CONFIG_I2C_MUX_PINCTRL is not set ++# CONFIG_I2C_MUX_REG is not set ++# CONFIG_I2C_DEMUX_PINCTRL 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 ++# ++ ++# ++# PC SMBus host controller drivers ++# ++# CONFIG_I2C_ALI1535 is not set ++# CONFIG_I2C_ALI1563 is not set ++# CONFIG_I2C_ALI15X3 is not set ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++# CONFIG_I2C_HIX5HD2 is not set ++# CONFIG_I2C_I801 is not set ++# CONFIG_I2C_ISCH is not set ++# CONFIG_I2C_PIIX4 is not set ++# CONFIG_I2C_NFORCE2 is not set ++# CONFIG_I2C_SIS5595 is not set ++# CONFIG_I2C_SIS630 is not set ++# CONFIG_I2C_SIS96X is not set ++# CONFIG_I2C_VIA is not set ++# CONFIG_I2C_VIAPRO is not set ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_AXXIA is not set ++# CONFIG_I2C_BCM_IPROC is not set ++# CONFIG_I2C_BRCMSTB is not set ++# CONFIG_I2C_CADENCE is not set ++# CONFIG_I2C_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_DESIGNWARE_PCI is not set ++# CONFIG_I2C_EFM32 is not set ++# CONFIG_I2C_EG20T is not set ++# CONFIG_I2C_EMEV2 is not set ++# CONFIG_I2C_GPIO is not set ++CONFIG_I2C_HIBVT=y ++# CONFIG_I2C_IMG is not set ++# CONFIG_I2C_JZ4780 is not set ++# CONFIG_I2C_LPC2K is not set ++# CONFIG_I2C_MESON is not set ++# CONFIG_I2C_MT65XX is not set ++# CONFIG_I2C_NOMADIK 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_RIIC is not set ++# CONFIG_I2C_RK3X is not set ++# CONFIG_I2C_SH_MOBILE is not set ++# CONFIG_I2C_SIMTEC is not set ++# CONFIG_I2C_SUN6I_P2WI is not set ++# CONFIG_I2C_UNIPHIER is not set ++# CONFIG_I2C_UNIPHIER_F is not set ++# CONFIG_I2C_VERSATILE is not set ++# CONFIG_I2C_THUNDERX is not set ++# CONFIG_I2C_XILINX is not set ++# CONFIG_I2C_XLP9XX is not set ++# CONFIG_I2C_RCAR 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_DMA_MSG_MIN_LEN=5 ++CONFIG_DMA_MSG_MAX_LEN=4090 ++# 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_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_ATMEL is not set ++# CONFIG_SPI_AXI_SPI_ENGINE is not set ++# CONFIG_SPI_BCM2835 is not set ++# CONFIG_SPI_BCM2835AUX is not set ++# CONFIG_SPI_BCM63XX is not set ++# CONFIG_SPI_BCM63XX_HSSPI is not set ++# CONFIG_SPI_BCM_QSPI is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_CLPS711X is not set ++# CONFIG_SPI_DESIGNWARE is not set ++# CONFIG_SPI_EP93XX is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_IMG_SPFI is not set ++# CONFIG_SPI_IMX is not set ++# CONFIG_SPI_JCORE is not set ++# CONFIG_SPI_LP8841_RTC is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_FSL_DSPI is not set ++# CONFIG_SPI_MESON_SPIFC is not set ++# CONFIG_SPI_MT65XX is not set ++# CONFIG_SPI_OC_TINY is not set ++# CONFIG_SPI_OMAP24XX is not set ++# CONFIG_SPI_TI_QSPI is not set ++# CONFIG_SPI_OMAP_100K is not set ++# CONFIG_SPI_ORION is not set ++# CONFIG_SPI_PIC32 is not set ++# CONFIG_SPI_PIC32_SQI is not set ++CONFIG_SPI_PL022=y ++# CONFIG_SPI_PXA2XX is not set ++# CONFIG_SPI_PXA2XX_PCI is not set ++# CONFIG_SPI_ROCKCHIP is not set ++# CONFIG_SPI_RSPI is not set ++# CONFIG_SPI_SC18IS602 is not set ++# CONFIG_SPI_SH_MSIOF is not set ++# CONFIG_SPI_SH is not set ++# CONFIG_SPI_SH_HSPI is not set ++# CONFIG_SPI_ST_SSC4 is not set ++# CONFIG_SPI_SUN4I is not set ++# CONFIG_SPI_SUN6I is not set ++# CONFIG_SPI_TEGRA114 is not set ++# CONFIG_SPI_TEGRA20_SFLASH is not set ++# CONFIG_SPI_TEGRA20_SLINK is not set ++# CONFIG_SPI_THUNDERX is not set ++# CONFIG_SPI_TOPCLIFF_PCH is not set ++# CONFIG_SPI_TXX9 is not set ++# CONFIG_SPI_XCOMM is not set ++# CONFIG_SPI_XILINX is not set ++# CONFIG_SPI_XLP is not set ++# CONFIG_SPI_XTENSA_XTFPGA is not set ++# CONFIG_SPI_ZYNQMP_GQSPI is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_PTP_1588_CLOCK_PCH is not set ++CONFIG_PINCTRL=y ++ ++# ++# Pin controllers ++# ++CONFIG_PINMUX=y ++CONFIG_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++# CONFIG_PINCTRL_AMD is not set ++# CONFIG_PINCTRL_LPC18XX is not set ++CONFIG_PINCTRL_SINGLE=y ++# CONFIG_PINCTRL_ASPEED_G4 is not set ++# CONFIG_PINCTRL_ASPEED_G5 is not set ++# CONFIG_PINCTRL_BCM281XX is not set ++# CONFIG_PINCTRL_IPROC_GPIO is not set ++# CONFIG_PINCTRL_CYGNUS_MUX is not set ++# CONFIG_PINCTRL_NSP_GPIO is not set ++# CONFIG_PINCTRL_NS2_MUX is not set ++# CONFIG_PINCTRL_NSP_MUX is not set ++# CONFIG_PINCTRL_BERLIN_BG2 is not set ++# CONFIG_PINCTRL_BERLIN_BG2CD is not set ++# CONFIG_PINCTRL_BERLIN_BG2Q is not set ++# CONFIG_PINCTRL_BERLIN_BG4CT is not set ++# CONFIG_PINCTRL_PXA25X is not set ++# CONFIG_PINCTRL_PXA27X is not set ++# CONFIG_PINCTRL_APQ8064 is not set ++# CONFIG_PINCTRL_APQ8084 is not set ++# CONFIG_PINCTRL_IPQ4019 is not set ++# CONFIG_PINCTRL_IPQ8064 is not set ++# CONFIG_PINCTRL_MSM8660 is not set ++# CONFIG_PINCTRL_MSM8960 is not set ++# CONFIG_PINCTRL_MDM9615 is not set ++# CONFIG_PINCTRL_MSM8X74 is not set ++# CONFIG_PINCTRL_MSM8916 is not set ++# CONFIG_PINCTRL_MSM8996 is not set ++# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set ++# CONFIG_PINCTRL_STM32F429 is not set ++# CONFIG_PINCTRL_STM32F746 is not set ++# CONFIG_PINCTRL_UNIPHIER is not set ++# CONFIG_PINCTRL_MT2701 is not set ++# CONFIG_PINCTRL_MT7623 is not set ++# CONFIG_PINCTRL_MT8135 is not set ++# CONFIG_PINCTRL_MT8127 is not set ++# CONFIG_PINCTRL_MT8173 is not set ++# CONFIG_PINCTRL_MT6397 is not set ++CONFIG_GPIOLIB=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_GENERIC=y ++ ++# ++# Memory mapped GPIO drivers ++# ++# CONFIG_GPIO_74XX_MMIO is not set ++# CONFIG_GPIO_ALTERA is not set ++# CONFIG_GPIO_ASPEED is not set ++# CONFIG_GPIO_ATH79 is not set ++# CONFIG_GPIO_BCM_KONA is not set ++# CONFIG_GPIO_BRCMSTB is not set ++# CONFIG_GPIO_CLPS711X is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_ETRAXFS is not set ++CONFIG_GPIO_GENERIC_PLATFORM=y ++# CONFIG_GPIO_GRGPIO is not set ++# CONFIG_GPIO_IOP is not set ++# CONFIG_GPIO_LPC18XX is not set ++# CONFIG_GPIO_MB86S7X is not set ++# CONFIG_GPIO_MOCKUP is not set ++# CONFIG_GPIO_MOXART is not set ++# CONFIG_GPIO_MPC8XXX is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_RCAR is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_TEGRA is not set ++# CONFIG_GPIO_TS4800 is not set ++# CONFIG_GPIO_VX855 is not set ++# CONFIG_GPIO_XGENE is not set ++# CONFIG_GPIO_XILINX is not set ++# CONFIG_GPIO_XLP 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 ++# ++ ++# ++# PCI GPIO expanders ++# ++# CONFIG_GPIO_AMD8111 is not set ++# CONFIG_GPIO_BT8XX is not set ++# CONFIG_GPIO_ML_IOH is not set ++# CONFIG_GPIO_PCH is not set ++# CONFIG_GPIO_RDC321X 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++# CONFIG_POWER_RESET_HISI is not set ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_XGENE is not set ++# CONFIG_POWER_RESET_KEYSTONE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_POWER_RESET_RMOBILE is not set ++# CONFIG_POWER_RESET_ZX is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_ACT8945A is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_MANAGER is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24257 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_BQ25890 is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_BATTERY_GOLDFISH is not set ++# CONFIG_CHARGER_RT9455 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_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_MX25_TSADC is not set ++# CONFIG_MFD_HI6421_PMIC is not set ++# CONFIG_MFD_HI655X_PMIC is not set ++CONFIG_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_HTC_I2CPLD is not set ++# CONFIG_LPC_ICH is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_INTEL_SOC_PMIC is not set ++# CONFIG_MFD_JANZ_CMODIO 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_RDC321X is not set ++# CONFIG_MFD_RTSX_PCI 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=y ++# 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_TIMBERDALE is not set ++# CONFIG_MFD_TC3589X is not set ++# CONFIG_MFD_TMIO is not set ++# CONFIG_MFD_VX855 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_MFD_STW481X is not set ++CONFIG_REGULATOR=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_LTC3676 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MT6311 is not set ++# CONFIG_REGULATOR_PBIAS is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_PV88060 is not set ++# CONFIG_REGULATOR_PV88080 is not set ++# CONFIG_REGULATOR_PV88090 is not set ++# CONFIG_REGULATOR_QCOM_SPMI is not set ++# CONFIG_REGULATOR_STW481X_VMMC is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=y ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=y ++CONFIG_VIDEO_V4L2=y ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=y ++CONFIG_VIDEOBUF2_MEMOPS=y ++CONFIG_VIDEOBUF2_VMALLOC=y ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++CONFIG_MEDIA_USB_SUPPORT=y ++ ++# ++# Webcam devices ++# ++CONFIG_USB_VIDEO_CLASS=y ++CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y ++CONFIG_USB_GSPCA=m ++# CONFIG_USB_M5602 is not set ++# CONFIG_USB_STV06XX is not set ++# CONFIG_USB_GL860 is not set ++# CONFIG_USB_GSPCA_BENQ is not set ++# CONFIG_USB_GSPCA_CONEX is not set ++# CONFIG_USB_GSPCA_CPIA1 is not set ++# CONFIG_USB_GSPCA_DTCS033 is not set ++# CONFIG_USB_GSPCA_ETOMS is not set ++# CONFIG_USB_GSPCA_FINEPIX is not set ++# CONFIG_USB_GSPCA_JEILINJ is not set ++# CONFIG_USB_GSPCA_JL2005BCD is not set ++# CONFIG_USB_GSPCA_KINECT is not set ++# CONFIG_USB_GSPCA_KONICA is not set ++# CONFIG_USB_GSPCA_MARS is not set ++# CONFIG_USB_GSPCA_MR97310A is not set ++# CONFIG_USB_GSPCA_NW80X is not set ++# CONFIG_USB_GSPCA_OV519 is not set ++# CONFIG_USB_GSPCA_OV534 is not set ++# CONFIG_USB_GSPCA_OV534_9 is not set ++# CONFIG_USB_GSPCA_PAC207 is not set ++# CONFIG_USB_GSPCA_PAC7302 is not set ++# CONFIG_USB_GSPCA_PAC7311 is not set ++# CONFIG_USB_GSPCA_SE401 is not set ++# CONFIG_USB_GSPCA_SN9C2028 is not set ++# CONFIG_USB_GSPCA_SN9C20X is not set ++# CONFIG_USB_GSPCA_SONIXB is not set ++# CONFIG_USB_GSPCA_SONIXJ is not set ++# CONFIG_USB_GSPCA_SPCA500 is not set ++# CONFIG_USB_GSPCA_SPCA501 is not set ++# CONFIG_USB_GSPCA_SPCA505 is not set ++# CONFIG_USB_GSPCA_SPCA506 is not set ++# CONFIG_USB_GSPCA_SPCA508 is not set ++# CONFIG_USB_GSPCA_SPCA561 is not set ++# CONFIG_USB_GSPCA_SPCA1528 is not set ++# CONFIG_USB_GSPCA_SQ905 is not set ++# CONFIG_USB_GSPCA_SQ905C is not set ++# CONFIG_USB_GSPCA_SQ930X is not set ++# CONFIG_USB_GSPCA_STK014 is not set ++# CONFIG_USB_GSPCA_STK1135 is not set ++# CONFIG_USB_GSPCA_STV0680 is not set ++# CONFIG_USB_GSPCA_SUNPLUS is not set ++# CONFIG_USB_GSPCA_T613 is not set ++# CONFIG_USB_GSPCA_TOPRO is not set ++# CONFIG_USB_GSPCA_TOUPTEK is not set ++# CONFIG_USB_GSPCA_TV8532 is not set ++# CONFIG_USB_GSPCA_VC032X is not set ++# CONFIG_USB_GSPCA_VICAM is not set ++# CONFIG_USB_GSPCA_XIRLINK_CIT is not set ++# CONFIG_USB_GSPCA_ZC3XX is not set ++# CONFIG_USB_PWC is not set ++# CONFIG_VIDEO_CPIA2 is not set ++# CONFIG_USB_ZR364XX is not set ++# CONFIG_USB_STKWEBCAM is not set ++# CONFIG_USB_S2255 is not set ++ ++# ++# Webcam, TV (analog/digital) USB devices ++# ++# CONFIG_VIDEO_EM28XX is not set ++# CONFIG_MEDIA_PCI_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, spi, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# I2C Encoders, decoders, sensors and other helper chips ++# ++ ++# ++# Audio decoders, processors and mixers ++# ++# CONFIG_VIDEO_TVAUDIO is not set ++# CONFIG_VIDEO_TDA7432 is not set ++# CONFIG_VIDEO_TDA9840 is not set ++# CONFIG_VIDEO_TEA6415C is not set ++# CONFIG_VIDEO_TEA6420 is not set ++# CONFIG_VIDEO_MSP3400 is not set ++# CONFIG_VIDEO_CS3308 is not set ++# CONFIG_VIDEO_CS5345 is not set ++# CONFIG_VIDEO_CS53L32A is not set ++# CONFIG_VIDEO_TLV320AIC23B is not set ++# CONFIG_VIDEO_UDA1342 is not set ++# CONFIG_VIDEO_WM8775 is not set ++# CONFIG_VIDEO_WM8739 is not set ++# CONFIG_VIDEO_VP27SMPX is not set ++# CONFIG_VIDEO_SONY_BTF_MPX is not set ++ ++# ++# RDS decoders ++# ++# CONFIG_VIDEO_SAA6588 is not set ++ ++# ++# Video decoders ++# ++# CONFIG_VIDEO_ADV7183 is not set ++# CONFIG_VIDEO_BT819 is not set ++# CONFIG_VIDEO_BT856 is not set ++# CONFIG_VIDEO_BT866 is not set ++# CONFIG_VIDEO_KS0127 is not set ++# CONFIG_VIDEO_ML86V7667 is not set ++# CONFIG_VIDEO_SAA7110 is not set ++# CONFIG_VIDEO_SAA711X is not set ++# CONFIG_VIDEO_TVP514X is not set ++# CONFIG_VIDEO_TVP5150 is not set ++# CONFIG_VIDEO_TVP7002 is not set ++# CONFIG_VIDEO_TW2804 is not set ++# CONFIG_VIDEO_TW9903 is not set ++# CONFIG_VIDEO_TW9906 is not set ++# CONFIG_VIDEO_VPX3220 is not set ++ ++# ++# Video and audio decoders ++# ++# CONFIG_VIDEO_SAA717X is not set ++# CONFIG_VIDEO_CX25840 is not set ++ ++# ++# Video encoders ++# ++# CONFIG_VIDEO_SAA7127 is not set ++# CONFIG_VIDEO_SAA7185 is not set ++# CONFIG_VIDEO_ADV7170 is not set ++# CONFIG_VIDEO_ADV7175 is not set ++# CONFIG_VIDEO_ADV7343 is not set ++# CONFIG_VIDEO_ADV7393 is not set ++# CONFIG_VIDEO_AK881X is not set ++# CONFIG_VIDEO_THS8200 is not set ++ ++# ++# Camera sensor devices ++# ++# CONFIG_VIDEO_OV2659 is not set ++# CONFIG_VIDEO_OV7640 is not set ++# CONFIG_VIDEO_OV7670 is not set ++# CONFIG_VIDEO_VS6624 is not set ++# CONFIG_VIDEO_MT9M111 is not set ++# CONFIG_VIDEO_MT9V011 is not set ++# CONFIG_VIDEO_SR030PC30 is not set ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++# CONFIG_VIDEO_UPD64031A is not set ++# CONFIG_VIDEO_UPD64083 is not set ++ ++# ++# Audio/Video compression chips ++# ++# CONFIG_VIDEO_SAA6752HS is not set ++ ++# ++# Miscellaneous helper chips ++# ++# CONFIG_VIDEO_THS7303 is not set ++# CONFIG_VIDEO_M52790 is not set ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# SPI helper chips ++# ++ ++# ++# Customise DVB Frontends ++# ++# CONFIG_DVB_AU8522_V4L is not set ++# CONFIG_DVB_TUNER_DIB0070 is not set ++# CONFIG_DVB_TUNER_DIB0090 is not set ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++CONFIG_VGA_ARB=y ++CONFIG_VGA_ARB_MAX_GPUS=16 ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_CIRRUS is not set ++# CONFIG_FB_PM2 is not set ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CLPS711X is not set ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_NVIDIA is not set ++# CONFIG_FB_RIVA is not set ++# CONFIG_FB_I740 is not set ++# CONFIG_FB_MATROX is not set ++# CONFIG_FB_RADEON is not set ++# CONFIG_FB_ATY128 is not set ++# CONFIG_FB_ATY is not set ++# CONFIG_FB_S3 is not set ++# CONFIG_FB_SAVAGE is not set ++# CONFIG_FB_SIS is not set ++# CONFIG_FB_NEOMAGIC is not set ++# CONFIG_FB_KYRO is not set ++# CONFIG_FB_3DFX is not set ++# CONFIG_FB_VOODOO1 is not set ++# CONFIG_FB_VT8623 is not set ++# CONFIG_FB_TRIDENT is not set ++# CONFIG_FB_ARK is not set ++# CONFIG_FB_PM3 is not set ++# CONFIG_FB_CARMINE is not set ++# CONFIG_FB_TMIO is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_GOLDFISH is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_MB862XX is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_FB_SM712 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++CONFIG_DUMMY_CONSOLE_COLUMNS=80 ++CONFIG_DUMMY_CONSOLE_ROWS=25 ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++# CONFIG_HID_BETOP_FF is not set ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# 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 is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PCI=y ++CONFIG_USB_XHCI_PLATFORM=y ++# CONFIG_USB_XHCI_MTK is not set ++# CONFIG_USB_XHCI_MVEBU is not set ++# CONFIG_USB_XHCI_RCAR 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_UHCI_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 ++# CONFIG_USB_RENESAS_USBHS is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++# CONFIG_USB_WDM is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++# CONFIG_USBIP_CORE is not set ++# CONFIG_USB_MUSB_HDRC is not set ++CONFIG_USB_DWC3=y ++# CONFIG_USB_DWC3_HOST is not set ++CONFIG_USB_DWC3_GADGET=y ++# CONFIG_USB_DWC3_DUAL_ROLE is not set ++ ++# ++# Platform Glue Driver Support ++# ++CONFIG_USB_DWC3_EXYNOS=y ++CONFIG_USB_DWC3_PCI=y ++CONFIG_USB_DWC3_KEYSTONE=y ++CONFIG_USB_DWC3_OF_SIMPLE=y ++# CONFIG_USB_DWC2 is not set ++# CONFIG_USB_CHIPIDEA 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++# CONFIG_USB_GADGET_DEBUG_FS is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_RENESAS_USB3 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_BDC_UDC is not set ++# CONFIG_USB_AMD5536UDC is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_NET2280 is not set ++# CONFIG_USB_GOKU is not set ++# CONFIG_USB_EG20T is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_MASS_STORAGE=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM 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_ARMMMCI is not set ++CONFIG_MMC_SDHCI=y ++# CONFIG_MMC_SDHCI_PCI is not set ++CONFIG_MMC_SDHCI_PLTFM=y ++# CONFIG_MMC_SDHCI_OF_ARASAN is not set ++# CONFIG_MMC_SDHCI_OF_AT91 is not set ++CONFIG_MMC_SDHCI_HISI=y ++# CONFIG_MMC_SDHCI_PXAV3 is not set ++# CONFIG_MMC_SDHCI_PXAV2 is not set ++# CONFIG_MMC_SDHCI_F_SDH30 is not set ++# CONFIG_MMC_SDHCI_IPROC is not set ++# CONFIG_MMC_OMAP_HS is not set ++# CONFIG_MMC_TIFM_SD is not set ++# CONFIG_MMC_GOLDFISH is not set ++# CONFIG_MMC_SPI is not set ++# CONFIG_MMC_SDHI is not set ++# CONFIG_MMC_CB710 is not set ++# CONFIG_MMC_VIA_SDMMC is not set ++# CONFIG_MMC_DW is not set ++# CONFIG_MMC_SH_MMCIF is not set ++# CONFIG_MMC_VUB300 is not set ++# CONFIG_MMC_USHC is not set ++# CONFIG_MMC_USDHI6ROL0 is not set ++# CONFIG_MMC_TOSHIBA_PCI 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_INFINIBAND is not set ++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=y ++ ++# ++# SPI and I2C RTC drivers ++# ++# CONFIG_RTC_DRV_DS3232 is not set ++# CONFIG_RTC_DRV_PCF2127 is not set ++# CONFIG_RTC_DRV_RV3029C2 is not set ++ ++# ++# Platform RTC drivers ++# ++CONFIG_RTC_DRV_HIBVT=y ++# 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_SPEAR is not set ++# CONFIG_RTC_DRV_NUC900 is not set ++# CONFIG_RTC_DRV_ZYNQMP is not set ++ ++# ++# on-CPU RTC drivers ++# ++# CONFIG_RTC_DRV_ASM9260 is not set ++# CONFIG_RTC_DRV_DAVINCI is not set ++# CONFIG_RTC_DRV_DIGICOLOR is not set ++# CONFIG_RTC_DRV_OMAP is not set ++# CONFIG_RTC_DRV_S3C is not set ++# CONFIG_RTC_DRV_EP93XX is not set ++# CONFIG_RTC_DRV_VR41XX is not set ++# CONFIG_RTC_DRV_PL030 is not set ++# CONFIG_RTC_DRV_PL031 is not set ++# CONFIG_RTC_DRV_AT32AP700X is not set ++# CONFIG_RTC_DRV_AT91RM9200 is not set ++# CONFIG_RTC_DRV_AT91SAM9 is not set ++# CONFIG_RTC_DRV_GENERIC is not set ++# CONFIG_RTC_DRV_VT8500 is not set ++# CONFIG_RTC_DRV_SUNXI is not set ++# CONFIG_RTC_DRV_MV is not set ++# CONFIG_RTC_DRV_ARMADA38X is not set ++# CONFIG_RTC_DRV_GEMINI is not set ++# CONFIG_RTC_DRV_COH901331 is not set ++# CONFIG_RTC_DRV_STMP is not set ++# CONFIG_RTC_DRV_JZ4740 is not set ++# CONFIG_RTC_DRV_LPC24XX is not set ++# CONFIG_RTC_DRV_LPC32XX is not set ++# CONFIG_RTC_DRV_PM8XXX is not set ++# CONFIG_RTC_DRV_TEGRA is not set ++# CONFIG_RTC_DRV_SNVS is not set ++# CONFIG_RTC_DRV_MOXART is not set ++# CONFIG_RTC_DRV_MT6397 is not set ++# CONFIG_RTC_DRV_XGENE is not set ++ ++# ++# HID Sensor RTC drivers ++# ++# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set ++CONFIG_DMADEVICES=y ++# CONFIG_DMADEVICES_DEBUG is not set ++ ++# ++# DMA Devices ++# ++CONFIG_DMA_ENGINE=y ++CONFIG_DMA_VIRTUAL_CHANNELS=y ++CONFIG_DMA_OF=y ++# CONFIG_AMBA_PL08X is not set ++# CONFIG_AXI_DMAC is not set ++# CONFIG_COH901318 is not set ++# CONFIG_DMA_JZ4740 is not set ++# CONFIG_DMA_JZ4780 is not set ++# CONFIG_DMA_OMAP is not set ++# CONFIG_DMA_SA11X0 is not set ++# CONFIG_DMA_SUN6I is not set ++# CONFIG_EP93XX_DMA is not set ++# CONFIG_FSL_EDMA is not set ++# CONFIG_IMG_MDC_DMA is not set ++# CONFIG_INTEL_IDMA64 is not set ++# CONFIG_K3_DMA is not set ++# CONFIG_MMP_PDMA is not set ++# CONFIG_MMP_TDMA is not set ++# CONFIG_MV_XOR is not set ++# CONFIG_MV_XOR_V2 is not set ++# CONFIG_NBPFAXI_DMA is not set ++# CONFIG_PCH_DMA is not set ++# CONFIG_PL330_DMA is not set ++# CONFIG_STM32_DMA is not set ++# CONFIG_S3C24XX_DMAC is not set ++# CONFIG_TEGRA210_ADMA is not set ++# CONFIG_TIMB_DMA is not set ++# CONFIG_TI_EDMA is not set ++# CONFIG_XGENE_DMA is not set ++# CONFIG_XILINX_DMA is not set ++# CONFIG_XILINX_ZYNQMP_DMA is not set ++# CONFIG_ZX_DMA is not set ++CONFIG_HIEDMACV310=y ++# CONFIG_QCOM_HIDMA_MGMT is not set ++# CONFIG_QCOM_HIDMA is not set ++# CONFIG_DW_DMAC is not set ++# CONFIG_DW_DMAC_PCI is not set ++CONFIG_RENESAS_DMA=y ++CONFIG_SH_DMAE_BASE=y ++# CONFIG_SH_DMAE is not set ++# CONFIG_RCAR_DMAC is not set ++# CONFIG_RENESAS_USB_DMAC is not set ++# CONFIG_SUDMAC 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_PCI is not set ++# CONFIG_VIRTIO_MMIO is not set ++ ++# ++# Microsoft Hyper-V guest support ++# ++CONFIG_STAGING=y ++# CONFIG_COMEDI is not set ++# CONFIG_RTL8192U is not set ++# CONFIG_RTLLIB is not set ++# CONFIG_R8712U is not set ++# CONFIG_RTS5208 is not set ++# CONFIG_FB_SM750 is not set ++# CONFIG_FB_XGI is not set ++ ++# ++# Speakup console speech ++# ++# CONFIG_SPEAKUP is not set ++# CONFIG_STAGING_MEDIA is not set ++ ++# ++# Android ++# ++# CONFIG_ASHMEM is not set ++# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set ++CONFIG_ION=y ++# CONFIG_ION_TEST is not set ++# CONFIG_ION_DUMMY is not set ++# CONFIG_ION_OF is not set ++# CONFIG_STAGING_BOARD is not set ++# CONFIG_LTE_GDM724X is not set ++# CONFIG_MTD_SPINAND_MT29F is not set ++# CONFIG_LNET is not set ++# CONFIG_DGNC is not set ++# CONFIG_GS_FPGABOOT is not set ++# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set ++# CONFIG_FB_TFT is not set ++# CONFIG_FSL_MC_BUS is not set ++# CONFIG_MOST is not set ++# CONFIG_KS7010 is not set ++# CONFIG_GREYBUS 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_VERSATILE is not set ++# CONFIG_COMMON_CLK_SCPI is not set ++# 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_COMMON_CLK_AXI_CLKGEN is not set ++# CONFIG_CLK_QORIQ is not set ++# CONFIG_COMMON_CLK_XGENE is not set ++# CONFIG_COMMON_CLK_KEYSTONE is not set ++# CONFIG_COMMON_CLK_NXP is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++# CONFIG_COMMON_CLK_OXNAS is not set ++# CONFIG_CLK_BCM_63XX is not set ++# CONFIG_CLK_BCM_KONA is not set ++# CONFIG_COMMON_CLK_IPROC is not set ++# CONFIG_COMMON_CLK_HI3519 is not set ++# CONFIG_COMMON_CLK_HI3516A is not set ++# CONFIG_COMMON_CLK_HI3518EV20X is not set ++# CONFIG_COMMON_CLK_HI3536DV100 is not set ++CONFIG_COMMON_CLK_HI3559AV100=y ++CONFIG_COMMON_CLK_HI3521A=y ++CONFIG_COMMON_CLK_HI3531A=y ++# CONFIG_COMMON_CLK_HI6220 is not set ++CONFIG_RESET_HISI=y ++# CONFIG_COMMON_CLK_MT8135 is not set ++# CONFIG_COMMON_CLK_MT8173 is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++# CONFIG_COMMON_CLK_SAMSUNG is not set ++# CONFIG_S3C2410_COMMON_CLK is not set ++# CONFIG_S3C2412_COMMON_CLK is not set ++# CONFIG_S3C2443_COMMON_CLK is not set ++# CONFIG_SUNXI_CCU is not set ++# CONFIG_COMMON_CLK_TI_ADPLL is not set ++# CONFIG_CLK_UNIPHIER is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++# CONFIG_BCM2835_TIMER is not set ++# CONFIG_BCM_KONA_TIMER is not set ++# CONFIG_DIGICOLOR_TIMER is not set ++# CONFIG_DW_APB_TIMER is not set ++# CONFIG_ROCKCHIP_TIMER is not set ++# CONFIG_MESON6_TIMER is not set ++# CONFIG_SUN4I_TIMER is not set ++# CONFIG_SUN5I_HSTIMER is not set ++# CONFIG_VT8500_TIMER is not set ++# CONFIG_CADENCE_TTC_TIMER is not set ++# CONFIG_ASM9260_TIMER is not set ++# CONFIG_CLKSRC_DBX500_PRCMU is not set ++# CONFIG_CLPS711X_TIMER is not set ++# CONFIG_ATLAS7_TIMER is not set ++# CONFIG_MOXART_TIMER is not set ++# CONFIG_MXS_TIMER is not set ++# CONFIG_PRIMA2_TIMER is not set ++# CONFIG_NSPIRE_TIMER is not set ++# CONFIG_KEYSTONE_TIMER is not set ++# CONFIG_INTEGRATOR_AP_TIMER is not set ++# CONFIG_CLKSRC_PISTACHIO is not set ++# CONFIG_CLKSRC_TI_32K is not set ++# CONFIG_CLKSRC_MPS2 is not set ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set ++CONFIG_FSL_ERRATUM_A008585=y ++CONFIG_ARM_TIMER_SP804=y ++# CONFIG_TIMER_HISP804 is not set ++# CONFIG_ARMV7M_SYSTICK is not set ++# CONFIG_ATMEL_PIT is not set ++# CONFIG_ATMEL_ST is not set ++# CONFIG_CLKSRC_EXYNOS_MCT is not set ++# CONFIG_CLKSRC_SAMSUNG_PWM is not set ++# CONFIG_FSL_FTM_TIMER is not set ++# CONFIG_OXNAS_RPS_TIMER is not set ++# CONFIG_MTK_TIMER is not set ++# CONFIG_CLKSRC_JCORE_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_CLKSRC_VERSATILE is not set ++# CONFIG_CLKSRC_PXA is not set ++# CONFIG_H8300_TMR8 is not set ++# CONFIG_H8300_TMR16 is not set ++# CONFIG_H8300_TPU is not set ++# CONFIG_CLKSRC_ST_LPC 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_MTK_INFRACFG is not set ++# CONFIG_MTK_SCPSYS is not set ++# CONFIG_ROCKCHIP_PM_DOMAINS is not set ++# CONFIG_SOC_SAMSUNG is not set ++# CONFIG_SUNXI_SRAM is not set ++# CONFIG_SOC_TI is not set ++# CONFIG_UX500_SOC_ID is not set ++CONFIG_PM_DEVFREQ=y ++ ++# ++# DEVFREQ Governors ++# ++CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y ++# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set ++# CONFIG_DEVFREQ_GOV_POWERSAVE is not set ++# CONFIG_DEVFREQ_GOV_USERSPACE is not set ++# CONFIG_DEVFREQ_GOV_PASSIVE is not set ++ ++# ++# DEVFREQ Drivers ++# ++# CONFIG_ARM_EXYNOS_BUS_DEVFREQ is not set ++# CONFIG_PM_DEVFREQ_EVENT is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_NTB is not set ++# CONFIG_VME_BUS is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++CONFIG_ARM_GIC_V2M=y ++CONFIG_ARM_GIC_V3=y ++CONFIG_ARM_GIC_V3_ITS=y ++CONFIG_HISILICON_IRQ_MBIGEN=y ++# CONFIG_JCORE_AIC is not set ++# CONFIG_TS4800_IRQ is not set ++CONFIG_PARTITION_PERCPU=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_UNIPHIER is not set ++# CONFIG_RESET_ZYNQ is not set ++CONFIG_COMMON_RESET_HI6220=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_PHY_BCM_NS_USB2 is not set ++# CONFIG_PHY_BCM_NS_USB3 is not set ++CONFIG_ARMADA375_USBCLUSTER_PHY=y ++# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set ++# CONFIG_PHY_LPC18XX_USB_OTG is not set ++# CONFIG_PHY_PXA_28NM_HSIC is not set ++# CONFIG_PHY_PXA_28NM_USB2 is not set ++# CONFIG_OMAP_CONTROL_PHY is not set ++# CONFIG_PHY_EXYNOS_DP_VIDEO is not set ++# CONFIG_BCM_KONA_USB2_PHY is not set ++# CONFIG_PHY_HI6220_USB is not set ++# CONFIG_PHY_ROCKCHIP_INNO_USB2 is not set ++# CONFIG_PHY_ROCKCHIP_PCIE is not set ++# CONFIG_PHY_ROCKCHIP_TYPEC is not set ++# CONFIG_PHY_ST_SPEAR1310_MIPHY is not set ++# CONFIG_PHY_ST_SPEAR1340_MIPHY is not set ++# CONFIG_PHY_XGENE is not set ++# CONFIG_PHY_STIH407_USB is not set ++# CONFIG_PHY_BRCM_SATA is not set ++# CONFIG_PHY_CYGNUS_PCIE is not set ++CONFIG_HISI_PHY_USB3=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++ ++# ++# Performance monitor support ++# ++CONFIG_ARM_PMU=y ++# CONFIG_RAS is not set ++# CONFIG_THUNDERBOLT is not set ++ ++# ++# Android ++# ++CONFIG_ANDROID=y ++# CONFIG_ANDROID_BINDER_IPC is not set ++# CONFIG_LIBNVDIMM 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 ++# CONFIG_HI_DMAC is not set ++# CONFIG_HIVDMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE is not set ++ ++# ++# Firmware Drivers ++# ++CONFIG_ARM_PSCI_FW=y ++CONFIG_ARM_SCPI_POWER_DOMAIN=y ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++# CONFIG_MESON_SM is not set ++# CONFIG_ACPI is not set ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++CONFIG_FS_IOMAP=y ++CONFIG_EXT2_FS=y ++CONFIG_EXT2_FS_XATTR=y ++CONFIG_EXT2_FS_POSIX_ACL=y ++CONFIG_EXT2_FS_SECURITY=y ++CONFIG_EXT3_FS=y ++CONFIG_EXT3_FS_POSIX_ACL=y ++CONFIG_EXT3_FS_SECURITY=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_CHECK=y ++CONFIG_REISERFS_PROC_INFO=y ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_DEBUG=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++# CONFIG_XFS_WARN is not set ++# CONFIG_XFS_DEBUG is not set ++# CONFIG_GFS2_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_DAX is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_EXPORTFS=m ++# 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=y ++# CONFIG_QUOTA_NETLINK_INTERFACE is not set ++CONFIG_PRINT_QUOTA_WARNING=y ++# CONFIG_QUOTA_DEBUG is not set ++CONFIG_QUOTA_TREE=m ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_QUOTACTL=y ++CONFIG_AUTOFS4_FS=m ++CONFIG_FUSE_FS=y ++# CONFIG_CUSE is not set ++# CONFIG_OVERLAY_FS is not set ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=y ++# CONFIG_JOLIET is not set ++# CONFIG_ZISOFS is not set ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++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_KCORE is not set ++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=y ++CONFIG_TMPFS_XATTR=y ++# CONFIG_HUGETLBFS is not set ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_ARCH_HAS_GIGANTIC_PAGE=y ++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_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++CONFIG_SQUASHFS=y ++CONFIG_SQUASHFS_FILE_CACHE=y ++# CONFIG_SQUASHFS_FILE_DIRECT is not set ++CONFIG_SQUASHFS_DECOMP_SINGLE=y ++# CONFIG_SQUASHFS_DECOMP_MULTI is not set ++# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set ++# CONFIG_SQUASHFS_XATTR is not set ++CONFIG_SQUASHFS_ZLIB=y ++# CONFIG_SQUASHFS_LZ4 is not set ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set ++# CONFIG_SQUASHFS_EMBEDDED is not set ++CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 ++# 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFSD is not set ++CONFIG_GRACE_PERIOD=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=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=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=y ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++# 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 ++# CONFIG_VIRTUALIZATION is not set ++ ++# ++# Kernel hacking ++# ++ ++# ++# printk and dmesg options ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++# 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=2048 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++CONFIG_ARCH_WANT_FRAME_POINTERS=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++CONFIG_HAVE_ARCH_KASAN=y ++# CONFIG_KASAN is not set ++CONFIG_ARCH_HAS_KCOV=y ++# CONFIG_KCOV is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++CONFIG_LOCKUP_DETECTOR=y ++# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set ++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 ++# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set ++CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 ++# CONFIG_WQ_WATCHDOG is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++CONFIG_SCHED_INFO=y ++CONFIG_SCHEDSTATS=y ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_HAVE_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_PROVE_RCU is not set ++CONFIG_SPARSE_RCU_POINTER=y ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=21 ++CONFIG_RCU_TRACE=y ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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_TRACE_CLOCK=y ++CONFIG_TRACING_SUPPORT=y ++# CONFIG_FTRACE is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_LKDTM is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=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_ARM64_PTDUMP is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_DEBUG_ALIGN_RODATA is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS 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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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 is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++CONFIG_CRYPTO_NULL=m ++CONFIG_CRYPTO_NULL2=y ++# CONFIG_CRYPTO_PCRYPT is not set ++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=m ++# CONFIG_CRYPTO_GCM is not set ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# 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=y ++CONFIG_CRYPTO_HMAC=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# 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 is not set ++# 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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_CRYPTO_DEV_S5P is not set ++# CONFIG_CRYPTO_DEV_ATMEL_AES is not set ++# CONFIG_CRYPTO_DEV_CCP is not set ++# CONFIG_CRYPTO_DEV_QCE is not set ++# CONFIG_CRYPTO_DEV_IMGTEC_HASH is not set ++ ++# ++# Certificates for signature checking ++# ++# CONFIG_ARM64_CRYPTO is not set ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++CONFIG_HAVE_ARCH_BITREVERSE=y ++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=y ++CONFIG_CRC16=y ++# CONFIG_CRC_T10DIF is not set ++CONFIG_CRC_ITU_T=y ++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=m ++# CONFIG_CRC8 is not set ++CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y ++# CONFIG_RANDOM32_SELFTEST is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=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_GZIP=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_NLATTR=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=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y +diff --git a/arch/arm64/configs/hi3559av100_arm64_big_little_ufs_defconfig b/arch/arm64/configs/hi3559av100_arm64_big_little_ufs_defconfig +new file mode 100644 +index 0000000..caa2a03 +--- /dev/null ++++ b/arch/arm64/configs/hi3559av100_arm64_big_little_ufs_defconfig +@@ -0,0 +1,3852 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm64 4.9.37 Kernel Configuration ++# ++CONFIG_ARM64=y ++CONFIG_64BIT=y ++CONFIG_ARCH_PHYS_ADDR_T_64BIT=y ++CONFIG_MMU=y ++CONFIG_DEBUG_RODATA=y ++CONFIG_ARM64_PAGE_SHIFT=12 ++CONFIG_ARM64_CONT_SHIFT=4 ++CONFIG_ARCH_MMAP_RND_BITS_MIN=18 ++CONFIG_ARCH_MMAP_RND_BITS_MAX=24 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=y ++CONFIG_GENERIC_BUG=y ++CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CSUM=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_ZONE_DMA=y ++CONFIG_HAVE_GENERIC_RCU_GUP=y ++CONFIG_ARCH_DMA_ADDR_T_64BIT=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_NEED_SG_DMA_LENGTH=y ++CONFIG_SMP=y ++CONFIG_SWIOTLB=y ++CONFIG_IOMMU_HELPER=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_FIX_EARLYCON_MEM=y ++CONFIG_PGTABLE_LEVELS=3 ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++CONFIG_COMPILE_TEST=y ++CONFIG_LOCALVERSION="" ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_GENERIC_IRQ_MIGRATION=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_GENERIC_MSI_IRQ=y ++CONFIG_GENERIC_MSI_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++# CONFIG_IRQ_DOMAIN_DEBUG is not set ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_HZ_PERIODIC=y ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NO_HZ_FULL 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_TREE_RCU=y ++# CONFIG_RCU_EXPERT is not set ++CONFIG_SRCU=y ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++CONFIG_TREE_RCU_TRACE=y ++# CONFIG_RCU_EXPEDITE_BOOT is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=14 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y ++# CONFIG_CGROUPS is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++CONFIG_RELAY=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++# CONFIG_RD_LZ4 is not set ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_SYSCTL_EXCEPTION_TRACE=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_ALL is not set ++# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y ++CONFIG_BPF_SYSCALL=y ++CONFIG_SHMEM=y ++CONFIG_AIO=y ++CONFIG_ADVISE_SYSCALLS=y ++CONFIG_USERFAULTFD=y ++CONFIG_PCI_QUIRKS=y ++CONFIG_MEMBARRIER=y ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++ ++# ++# Kernel Performance Events And Counters ++# ++CONFIG_PERF_EVENTS=y ++# CONFIG_DEBUG_PERF_USE_VMALLOC is not set ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_SLAB_FREELIST_RANDOM is not set ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_SYSTEM_DATA_VERIFICATION is not set ++# CONFIG_PROFILING is not set ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL is not set ++# CONFIG_UPROBES is not set ++# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set ++CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=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_HW_BREAKPOINT=y ++CONFIG_HAVE_PERF_REGS=y ++CONFIG_HAVE_PERF_USER_STACK_DUMP=y ++CONFIG_HAVE_ARCH_JUMP_LABEL=y ++CONFIG_HAVE_RCU_TABLE_FREE=y ++CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y ++CONFIG_HAVE_CMPXCHG_LOCAL=y ++CONFIG_HAVE_CMPXCHG_DOUBLE=y ++CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y ++CONFIG_HAVE_ARCH_SECCOMP_FILTER=y ++CONFIG_HAVE_GCC_PLUGINS=y ++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_ARCH_TRANSPARENT_HUGEPAGE=y ++CONFIG_HAVE_ARCH_HUGE_VMAP=y ++CONFIG_MODULES_USE_ELF_RELA=y ++CONFIG_ARCH_HAS_ELF_RANDOMIZE=y ++CONFIG_HAVE_ARCH_MMAP_RND_BITS=y ++CONFIG_ARCH_MMAP_RND_BITS=18 ++CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 ++# CONFIG_HAVE_ARCH_HASH is not set ++# CONFIG_ISA_BUS_API is not set ++CONFIG_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_COMPAT_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_SLABINFO=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_MODULES_TREE_LOOKUP=y ++CONFIG_BLOCK=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++CONFIG_BLOCK_COMPAT=y ++CONFIG_BLK_MQ_PCI=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_LOCK_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# Platform selection ++# ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_ALPINE is not set ++# CONFIG_ARCH_BCM2835 is not set ++# CONFIG_ARCH_BCM_IPROC is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_BRCMSTB is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_LAYERSCAPE is not set ++# CONFIG_ARCH_LG1K is not set ++# CONFIG_ARCH_HISI is not set ++CONFIG_ARCH_HISI_BVT=y ++CONFIG_ARCH_HI3559AV100=y ++# CONFIG_ACCESS_M7_DEV is not set ++# CONFIG_ARCH_HISI_BVT_AMP is not set ++# CONFIG_ARCH_MEDIATEK is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SEATTLE is not set ++# CONFIG_ARCH_RENESAS is not set ++# CONFIG_ARCH_STRATIX10 is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_SPRD is not set ++# CONFIG_ARCH_THUNDER is not set ++# CONFIG_ARCH_UNIPHIER is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_VULCAN is not set ++# CONFIG_ARCH_XGENE is not set ++# CONFIG_ARCH_ZX is not set ++# CONFIG_ARCH_ZYNQMP is not set ++ ++# ++# Bus support ++# ++CONFIG_PCI=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_PCI_DOMAINS_GENERIC=y ++CONFIG_PCI_SYSCALL=y ++CONFIG_PCIEPORTBUS=y ++# CONFIG_PCIEAER is not set ++# CONFIG_PCIEASPM is not set ++# CONFIG_PCIE_PME is not set ++# CONFIG_PCIE_DPC is not set ++# CONFIG_PCIE_PTM is not set ++CONFIG_PCI_BUS_ADDR_T_64BIT=y ++CONFIG_PCI_MSI=y ++CONFIG_PCI_MSI_IRQ_DOMAIN=y ++# CONFIG_PCI_DEBUG is not set ++# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set ++# CONFIG_PCI_STUB is not set ++# CONFIG_PCI_IOV is not set ++# CONFIG_PCI_PRI is not set ++# CONFIG_PCI_PASID is not set ++# CONFIG_HOTPLUG_PCI is not set ++ ++# ++# PCI host controller drivers ++# ++# CONFIG_PCIE_DW_PLAT is not set ++# CONFIG_PCI_HOST_GENERIC is not set ++# CONFIG_PCI_HISI is not set ++# CONFIG_PCI_HOST_THUNDER_PEM is not set ++# CONFIG_PCI_HOST_THUNDER_ECAM is not set ++# CONFIG_HIPCIE is not set ++ ++# ++# Kernel Features ++# ++ ++# ++# ARM errata workarounds via the alternatives framework ++# ++CONFIG_ARM64_ERRATUM_826319=y ++CONFIG_ARM64_ERRATUM_827319=y ++CONFIG_ARM64_ERRATUM_824069=y ++CONFIG_ARM64_ERRATUM_819472=y ++CONFIG_ARM64_ERRATUM_832075=y ++CONFIG_ARM64_ERRATUM_845719=y ++CONFIG_ARM64_ERRATUM_843419=y ++CONFIG_CAVIUM_ERRATUM_22375=y ++CONFIG_CAVIUM_ERRATUM_23154=y ++CONFIG_CAVIUM_ERRATUM_27456=y ++CONFIG_QCOM_QDF2400_ERRATUM_0065=y ++CONFIG_ARM64_4K_PAGES=y ++# CONFIG_ARM64_16K_PAGES is not set ++# CONFIG_ARM64_64K_PAGES is not set ++CONFIG_ARM64_VA_BITS_39=y ++# CONFIG_ARM64_VA_BITS_48 is not set ++CONFIG_ARM64_VA_BITS=39 ++# CONFIG_CPU_BIG_ENDIAN is not set ++CONFIG_SCHED_MC=y ++# CONFIG_SCHED_SMT is not set ++CONFIG_NR_CPUS=64 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_NUMA is not set ++CONFIG_PREEMPT_NONE=y ++# CONFIG_PREEMPT_VOLUNTARY is not set ++# CONFIG_PREEMPT is not set ++# CONFIG_HZ_100 is not set ++# CONFIG_HZ_250 is not set ++# CONFIG_HZ_300 is not set ++CONFIG_HZ_1000=y ++CONFIG_HZ=1000 ++# CONFIG_SCHED_HRTICK is not set ++CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y ++CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y ++CONFIG_ARCH_SPARSEMEM_ENABLE=y ++CONFIG_ARCH_SPARSEMEM_DEFAULT=y ++CONFIG_ARCH_SELECT_MEMORY_MODEL=y ++CONFIG_HAVE_ARCH_PFN_VALID=y ++CONFIG_HW_PERF_EVENTS=y ++CONFIG_SYS_SUPPORTS_HUGETLBFS=y ++CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y ++CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_SPARSEMEM_MANUAL=y ++CONFIG_SPARSEMEM=y ++CONFIG_HAVE_MEMORY_PRESENT=y ++CONFIG_SPARSEMEM_EXTREME=y ++CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y ++CONFIG_SPARSEMEM_VMEMMAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=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=y ++CONFIG_BOUNCE=y ++CONFIG_KSM=y ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# CONFIG_TRANSPARENT_HUGEPAGE is not set ++# CONFIG_CLEANCACHE is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++# CONFIG_CMA_DEBUGFS is not set ++CONFIG_CMA_AREAS=7 ++# 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_FRAME_VECTOR=y ++# CONFIG_SECCOMP is not set ++# CONFIG_PARAVIRT is not set ++# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set ++# CONFIG_KEXEC is not set ++# CONFIG_XEN is not set ++CONFIG_FORCE_MAX_ZONEORDER=11 ++# CONFIG_ARMV8_DEPRECATED is not set ++ ++# ++# ARMv8.1 architectural features ++# ++CONFIG_ARM64_HW_AFDBM=y ++CONFIG_ARM64_PAN=y ++# CONFIG_ARM64_LSE_ATOMICS is not set ++CONFIG_ARM64_VHE=y ++ ++# ++# ARMv8.2 architectural features ++# ++CONFIG_ARM64_UAO=y ++CONFIG_ARM64_MODULE_CMODEL_LARGE=y ++# CONFIG_RANDOMIZE_BASE is not set ++ ++# ++# Boot options ++# ++CONFIG_CMDLINE="mem=128M console=ttyAMA0,115200 console=ttyMTD,blackbox" ++# CONFIG_CMDLINE_FORCE is not set ++# CONFIG_EFI is not set ++CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y ++CONFIG_IMG_GZ_DTB=y ++# CONFIG_IMG_DTB is not set ++CONFIG_BUILD_ARM64_APPENDED_KERNEL_IMAGE_NAME="Image.gz-dtb" ++CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES="hisilicon/hi3559av100-demb-ufs" ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_COMPAT_BINFMT_ELF=y ++CONFIG_ELFCORE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++CONFIG_COMPAT=y ++CONFIG_SYSVIPC_COMPAT=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_SUSPEND_SKIP_SYNC is not set ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++CONFIG_PM_CLK=y ++CONFIG_PM_GENERIC_DOMAINS=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_PM_GENERIC_DOMAINS_SLEEP=y ++CONFIG_PM_GENERIC_DOMAINS_OF=y ++CONFIG_CPU_PM=y ++CONFIG_ARCH_HIBERNATION_POSSIBLE=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Idle ++# ++# CONFIG_CPU_IDLE is not set ++# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_ATTR_SET=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_STAT_DETAILS=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set ++ ++# ++# CPU frequency scaling drivers ++# ++# CONFIG_CPUFREQ_DT is not set ++# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++CONFIG_NET=y ++CONFIG_NET_INGRESS=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 is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++CONFIG_NET_IP_TUNNEL=m ++# 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=m ++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=y ++# CONFIG_IPV6_ROUTE_INFO 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_IPV6_ILA is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# 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=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++CONFIG_NETFILTER_INGRESS=y ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_DUP_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_DUP_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_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_QRTR is not set ++# CONFIG_NET_NCSI is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_SOCK_CGROUP_DATA is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_EBPF_JIT=y ++ ++# ++# Device Drivers ++# ++CONFIG_ARM_AMBA=y ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER=y ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++# CONFIG_DEVTMPFS is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++CONFIG_GENERIC_CPU_AUTOPROBE=y ++CONFIG_REGMAP=y ++CONFIG_REGMAP_I2C=y ++CONFIG_REGMAP_SPI=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=4 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_ARM_CCI400_PMU is not set ++# CONFIG_ARM_CCI5xx_PMU is not set ++# CONFIG_ARM_CCN is not set ++# CONFIG_QCOM_EBI2 is not set ++# CONFIG_SIMPLE_PM_BUS 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 ++# CONFIG_MTD_BCM63XX_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_TS5500 is not set ++# CONFIG_MTD_INTEL_VR_NOR is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_DATAFLASH is not set ++# CONFIG_MTD_M25P80 is not set ++# 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=y ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOCG3 is not set ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI_PCI is not set ++# CONFIG_MTD_NAND_DENALI_DT is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_RICOH is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_BRCMNAND is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_MTD_NAND_VF610_NFC is not set ++# CONFIG_MTD_NAND_SH_FLCTL is not set ++# CONFIG_MTD_NAND_HISI504 is not set ++# CONFIG_MTD_NAND_MTK is not set ++CONFIG_MTD_SPI_NAND_HISI_BVT=y ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++CONFIG_MTD_SPI_NAND_HIFMC100=y ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# LPDDR & LPDDR2 PCM memory drivers ++# ++# CONFIG_MTD_LPDDR is not set ++CONFIG_MTD_SPI_NOR=y ++# CONFIG_MTD_MT81xx_NOR is not set ++# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set ++# CONFIG_SPI_FSL_QUADSPI is not set ++CONFIG_SPI_HISI_SFC=y ++# CONFIG_SPI_NXP_SPIFI is not set ++# CONFIG_MTD_SPI_IDS is not set ++# CONFIG_CLOSE_SPI_8PIN_4IO is not set ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++# CONFIG_MTD_UBI is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++# CONFIG_OF_UNITTEST is not set ++# CONFIG_OF_ALL_DTBS is not set ++CONFIG_OF_FLATTREE=y ++CONFIG_OF_EARLY_FLATTREE=y ++CONFIG_OF_ADDRESS=y ++CONFIG_OF_ADDRESS_PCI=y ++CONFIG_OF_IRQ=y ++CONFIG_OF_NET=y ++CONFIG_OF_MDIO=y ++CONFIG_OF_PCI=y ++CONFIG_OF_PCI_IRQ=y ++CONFIG_OF_RESERVED_MEM=y ++# CONFIG_OF_OVERLAY is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set ++# CONFIG_BLK_CPQ_CISS_DA is not set ++# CONFIG_BLK_DEV_DAC960 is not set ++# CONFIG_BLK_DEV_UMEM is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_SKD is not set ++# CONFIG_BLK_DEV_SX8 is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_BLK_DEV_RSXX is not set ++# CONFIG_BLK_DEV_NVME is not set ++# CONFIG_NVME_TARGET is not set ++ ++# ++# Misc devices ++# ++# CONFIG_SENSORS_LIS3LV02D is not set ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_DUMMY_IRQ is not set ++# CONFIG_PHANTOM is not set ++# CONFIG_INTEL_MID_PTI is not set ++# CONFIG_SGI_IOC4 is not set ++# CONFIG_TIFM_CORE is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ATMEL_SSC is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_HP_ILO is not set ++# CONFIG_QCOM_COINCELL 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_PCH_PHUB 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 ++# CONFIG_CB710_CORE 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_GENWQE is not set ++# 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=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_SCSI_CXGB3_ISCSI is not set ++# CONFIG_SCSI_CXGB4_ISCSI is not set ++# CONFIG_SCSI_BNX2_ISCSI is not set ++# CONFIG_BE2ISCSI is not set ++# CONFIG_BLK_DEV_3W_XXXX_RAID is not set ++# CONFIG_SCSI_HPSA is not set ++# CONFIG_SCSI_3W_9XXX is not set ++# CONFIG_SCSI_3W_SAS is not set ++# CONFIG_SCSI_ACARD is not set ++# CONFIG_SCSI_AACRAID is not set ++# CONFIG_SCSI_AIC7XXX is not set ++# CONFIG_SCSI_AIC79XX is not set ++# CONFIG_SCSI_AIC94XX is not set ++# CONFIG_SCSI_HISI_SAS is not set ++# CONFIG_SCSI_MVSAS is not set ++# CONFIG_SCSI_MVUMI is not set ++# CONFIG_SCSI_ADVANSYS is not set ++# CONFIG_SCSI_ARCMSR is not set ++# CONFIG_SCSI_ESAS2R is not set ++# CONFIG_MEGARAID_NEWGEN is not set ++# CONFIG_MEGARAID_LEGACY is not set ++# CONFIG_MEGARAID_SAS is not set ++# CONFIG_SCSI_MPT3SAS is not set ++# CONFIG_SCSI_MPT2SAS is not set ++# CONFIG_SCSI_SMARTPQI is not set ++# CONFIG_SCSI_UFSHCD is not set ++# CONFIG_SCSI_HPTIOP is not set ++# CONFIG_SCSI_SNIC is not set ++# CONFIG_SCSI_DMX3191D is not set ++# CONFIG_SCSI_FUTURE_DOMAIN is not set ++# CONFIG_SCSI_IPS is not set ++# CONFIG_SCSI_INITIO is not set ++# CONFIG_SCSI_INIA100 is not set ++# CONFIG_SCSI_STEX is not set ++# CONFIG_SCSI_SYM53C8XX_2 is not set ++# CONFIG_SCSI_QLOGIC_1280 is not set ++# CONFIG_SCSI_QLA_ISCSI is not set ++# CONFIG_SCSI_DC395x is not set ++# CONFIG_SCSI_AM53C974 is not set ++# CONFIG_SCSI_WD719X is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_PMCRAID is not set ++# CONFIG_SCSI_PM8001 is not set ++# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HAVE_PATA_PLATFORM=y ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++# CONFIG_FUSION is not set ++ ++# ++# IEEE 1394 (FireWire) support ++# ++# CONFIG_FIREWIRE is not set ++# CONFIG_FIREWIRE_NOSY is not set ++CONFIG_NETDEVICES=y ++CONFIG_NET_CORE=y ++# CONFIG_BONDING is not set ++# CONFIG_DUMMY is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC 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 ++# CONFIG_ARCNET is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++CONFIG_ETHERNET=y ++CONFIG_NET_VENDOR_3COM=y ++# CONFIG_VORTEX is not set ++# CONFIG_TYPHOON is not set ++CONFIG_NET_VENDOR_ADAPTEC=y ++# CONFIG_ADAPTEC_STARFIRE is not set ++CONFIG_NET_VENDOR_AGERE=y ++# CONFIG_ET131X is not set ++CONFIG_NET_VENDOR_ALTEON=y ++# CONFIG_ACENIC is not set ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_VENDOR_AMAZON is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC is not set ++CONFIG_NET_VENDOR_ATHEROS=y ++# CONFIG_ATL2 is not set ++# CONFIG_ATL1 is not set ++# CONFIG_ATL1E is not set ++# CONFIG_ATL1C is not set ++# CONFIG_ALX 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_BROCADE=y ++# CONFIG_BNA is not set ++# CONFIG_NET_CALXEDA_XGMAC is not set ++CONFIG_NET_VENDOR_CAVIUM=y ++# CONFIG_THUNDER_NIC_PF is not set ++# CONFIG_THUNDER_NIC_VF is not set ++# CONFIG_THUNDER_NIC_BGX is not set ++# CONFIG_THUNDER_NIC_RGX is not set ++# CONFIG_LIQUIDIO is not set ++CONFIG_NET_VENDOR_CHELSIO=y ++# CONFIG_CHELSIO_T1 is not set ++# CONFIG_CHELSIO_T3 is not set ++# CONFIG_CHELSIO_T4 is not set ++# CONFIG_CHELSIO_T4VF is not set ++CONFIG_NET_VENDOR_CISCO=y ++# CONFIG_ENIC is not set ++# CONFIG_CX_ECAT is not set ++# CONFIG_DNET is not set ++CONFIG_NET_VENDOR_DEC=y ++# CONFIG_NET_TULIP is not set ++CONFIG_NET_VENDOR_DLINK=y ++# CONFIG_DL2K is not set ++# CONFIG_SUNDANCE is not set ++CONFIG_NET_VENDOR_EMULEX=y ++# CONFIG_BE2NET is not set ++# CONFIG_NET_VENDOR_EZCHIP is not set ++CONFIG_NET_VENDOR_EXAR=y ++# CONFIG_S2IO is not set ++# CONFIG_VXGE is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++# CONFIG_HIP04_ETH is not set ++# CONFIG_HNS is not set ++# CONFIG_HNS_DSAF is not set ++# CONFIG_HNS_ENET is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DDR_64BIT=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++CONFIG_NET_VENDOR_HP=y ++# CONFIG_HP100 is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_JME is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++CONFIG_NET_VENDOR_MELLANOX=y ++# CONFIG_MLX4_EN is not set ++# CONFIG_MLX4_CORE is not set ++# CONFIG_MLX5_CORE is not set ++# CONFIG_MLXSW_CORE is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_MICROCHIP is not set ++CONFIG_NET_VENDOR_MYRI=y ++# CONFIG_MYRI10GE is not set ++# CONFIG_FEALNX is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NETRONOME is not set ++CONFIG_NET_VENDOR_NVIDIA=y ++# CONFIG_FORCEDETH is not set ++CONFIG_NET_VENDOR_OKI=y ++# CONFIG_PCH_GBE is not set ++# CONFIG_ETHOC is not set ++CONFIG_NET_PACKET_ENGINE=y ++# CONFIG_HAMACHI is not set ++# CONFIG_YELLOWFIN is not set ++CONFIG_NET_VENDOR_QLOGIC=y ++# CONFIG_QLA3XXX is not set ++# CONFIG_QLCNIC is not set ++# CONFIG_QLGE is not set ++# CONFIG_NETXEN_NIC is not set ++# CONFIG_QED is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++CONFIG_NET_VENDOR_REALTEK=y ++# CONFIG_8139CP is not set ++# CONFIG_8139TOO is not set ++# CONFIG_R8169 is not set ++# CONFIG_NET_VENDOR_RENESAS is not set ++CONFIG_NET_VENDOR_RDC=y ++# CONFIG_R6040 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_SILAN=y ++# CONFIG_SC92031 is not set ++CONFIG_NET_VENDOR_SIS=y ++# CONFIG_SIS900 is not set ++# CONFIG_SIS190 is not set ++# CONFIG_SFC is not set ++# CONFIG_NET_VENDOR_SMSC is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++CONFIG_NET_VENDOR_SUN=y ++# CONFIG_HAPPYMEAL is not set ++# CONFIG_SUNGEM is not set ++# CONFIG_CASSINI is not set ++# CONFIG_NIU is not set ++# CONFIG_NET_VENDOR_SYNOPSYS is not set ++CONFIG_NET_VENDOR_TEHUTI=y ++# CONFIG_TEHUTI is not set ++CONFIG_NET_VENDOR_TI=y ++# CONFIG_TI_CPSW_ALE is not set ++# CONFIG_TLAN is not set ++# CONFIG_NET_VENDOR_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_FDDI is not set ++# CONFIG_HIPPI is not set ++CONFIG_PHYLIB=y ++CONFIG_SWPHY=y ++ ++# ++# MDIO bus device drivers ++# ++# CONFIG_MDIO_BCM_IPROC is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_BCM_IPROC 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 ++CONFIG_MDIO_HISI_GEMAC=y ++# CONFIG_MDIO_OCTEON is not set ++# CONFIG_MDIO_THUNDER is not set ++# CONFIG_MDIO_XGENE 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_IPHETH is not set ++CONFIG_WLAN=y ++CONFIG_WLAN_VENDOR_ADMTEK=y ++CONFIG_WLAN_VENDOR_ATH=y ++# CONFIG_ATH_DEBUG is not set ++# CONFIG_ATH5K_PCI is not set ++CONFIG_WLAN_VENDOR_ATMEL=y ++CONFIG_WLAN_VENDOR_BROADCOM=y ++CONFIG_WLAN_VENDOR_CISCO=y ++CONFIG_WLAN_VENDOR_INTEL=y ++CONFIG_WLAN_VENDOR_INTERSIL=y ++# CONFIG_HOSTAP is not set ++# CONFIG_PRISM54 is not set ++CONFIG_WLAN_VENDOR_MARVELL=y ++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 ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_VMXNET3 is not set ++# CONFIG_ISDN is not set ++# CONFIG_NVM is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++CONFIG_INPUT_FF_MEMLESS=y ++# CONFIG_INPUT_POLLDEV is not set ++# CONFIG_INPUT_SPARSEKMAP is not set ++# CONFIG_INPUT_MATRIXKMAP is not set ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_CLPS711X is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_GOLDFISH_EVENTS is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_ST_KEYSCAN is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_SH_KEYSC is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP11XX is not set ++# CONFIG_KEYBOARD_BCM is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_BYD=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_PS2_FOCALTECH=y ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_ELAN_I2C is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB is not set ++CONFIG_INPUT_JOYSTICK=y ++# CONFIG_JOYSTICK_ANALOG is not set ++# CONFIG_JOYSTICK_A3D is not set ++# CONFIG_JOYSTICK_ADI is not set ++# CONFIG_JOYSTICK_COBRA is not set ++# CONFIG_JOYSTICK_GF2K is not set ++# CONFIG_JOYSTICK_GRIP is not set ++# CONFIG_JOYSTICK_GRIP_MP is not set ++# CONFIG_JOYSTICK_GUILLEMOT is not set ++# CONFIG_JOYSTICK_INTERACT is not set ++# CONFIG_JOYSTICK_SIDEWINDER is not set ++# CONFIG_JOYSTICK_TMDC is not set ++# CONFIG_JOYSTICK_IFORCE is not set ++# CONFIG_JOYSTICK_WARRIOR is not set ++# CONFIG_JOYSTICK_MAGELLAN is not set ++# CONFIG_JOYSTICK_SPACEORB is not set ++# CONFIG_JOYSTICK_SPACEBALL is not set ++# CONFIG_JOYSTICK_STINGER is not set ++# CONFIG_JOYSTICK_TWIDJOY is not set ++# CONFIG_JOYSTICK_ZHENHUA is not set ++# CONFIG_JOYSTICK_AS5011 is not set ++# CONFIG_JOYSTICK_JOYDUMP is not set ++# CONFIG_JOYSTICK_XPAD is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++CONFIG_INPUT_MISC=y ++# CONFIG_INPUT_AD714X is not set ++# CONFIG_INPUT_ATMEL_CAPTOUCH is not set ++# CONFIG_INPUT_BMA150 is not set ++# CONFIG_INPUT_E3X0_BUTTON is not set ++# CONFIG_INPUT_MMA8450 is not set ++# CONFIG_INPUT_MPU3050 is not set ++# CONFIG_INPUT_GP2A is not set ++# CONFIG_INPUT_GPIO_BEEPER is not set ++# CONFIG_INPUT_GPIO_TILT_POLLED is not set ++# CONFIG_INPUT_GPIO_DECODER is not set ++# CONFIG_INPUT_ATI_REMOTE2 is not set ++# CONFIG_INPUT_KEYSPAN_REMOTE is not set ++# CONFIG_INPUT_KXTJ9 is not set ++# CONFIG_INPUT_POWERMATE is not set ++# CONFIG_INPUT_YEALINK is not set ++# CONFIG_INPUT_CM109 is not set ++# CONFIG_INPUT_REGULATOR_HAPTIC is not set ++CONFIG_INPUT_UINPUT=y ++# CONFIG_INPUT_PCF8574 is not set ++# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set ++# CONFIG_INPUT_ADXL34X is not set ++# CONFIG_INPUT_CMA3000 is not set ++# CONFIG_INPUT_DRV260X_HAPTICS is not set ++# CONFIG_INPUT_DRV2665_HAPTICS is not set ++# CONFIG_INPUT_DRV2667_HAPTICS is not set ++# CONFIG_INPUT_HISI_POWERKEY is not set ++# CONFIG_RMI4_CORE is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_SERIO_OLPC_APSP is not set ++# CONFIG_SERIO_SUN4I_PS2 is not set ++# CONFIG_USERIO is not set ++CONFIG_GAMEPORT=y ++# CONFIG_GAMEPORT_NS558 is not set ++# CONFIG_GAMEPORT_L4 is not set ++# CONFIG_GAMEPORT_EMU10K1 is not set ++# CONFIG_GAMEPORT_FM801 is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=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_NOZOMI is not set ++# CONFIG_N_GSM is not set ++# CONFIG_TRACE_SINK is not set ++CONFIG_DEVMEM=y ++CONFIG_DEVKMEM=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_ATMEL is not set ++# CONFIG_SERIAL_CLPS711X is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X is not set ++# CONFIG_SERIAL_IMX is not set ++# CONFIG_SERIAL_UARTLITE is not set ++# CONFIG_SERIAL_SH_SCI is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_JSM is not set ++# CONFIG_SERIAL_SCCNXP is not set ++# CONFIG_SERIAL_SC16IS7XX is not set ++# CONFIG_SERIAL_TIMBERDALE is not set ++# CONFIG_SERIAL_BCM63XX is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_IFX6X60 is not set ++# CONFIG_SERIAL_PCH_UART is not set ++# CONFIG_SERIAL_MXS_AUART is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++# CONFIG_SERIAL_MPS2_UART is not set ++# CONFIG_SERIAL_ARC is not set ++# CONFIG_SERIAL_RP2 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_SERIAL_MVEBU_UART 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_APPLICOM is not set ++ ++# ++# PCMCIA character devices ++# ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_DEVPORT=y ++# 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=y ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set ++# CONFIG_I2C_MUX_GPIO is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PCA954x is not set ++# CONFIG_I2C_MUX_PINCTRL is not set ++# CONFIG_I2C_MUX_REG is not set ++# CONFIG_I2C_DEMUX_PINCTRL 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 ++# ++ ++# ++# PC SMBus host controller drivers ++# ++# CONFIG_I2C_ALI1535 is not set ++# CONFIG_I2C_ALI1563 is not set ++# CONFIG_I2C_ALI15X3 is not set ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++# CONFIG_I2C_HIX5HD2 is not set ++# CONFIG_I2C_I801 is not set ++# CONFIG_I2C_ISCH is not set ++# CONFIG_I2C_PIIX4 is not set ++# CONFIG_I2C_NFORCE2 is not set ++# CONFIG_I2C_SIS5595 is not set ++# CONFIG_I2C_SIS630 is not set ++# CONFIG_I2C_SIS96X is not set ++# CONFIG_I2C_VIA is not set ++# CONFIG_I2C_VIAPRO is not set ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_AXXIA is not set ++# CONFIG_I2C_BCM_IPROC is not set ++# CONFIG_I2C_BRCMSTB is not set ++# CONFIG_I2C_CADENCE is not set ++# CONFIG_I2C_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_DESIGNWARE_PCI is not set ++# CONFIG_I2C_EFM32 is not set ++# CONFIG_I2C_EG20T is not set ++# CONFIG_I2C_EMEV2 is not set ++# CONFIG_I2C_GPIO is not set ++CONFIG_I2C_HIBVT=y ++# CONFIG_I2C_IMG is not set ++# CONFIG_I2C_JZ4780 is not set ++# CONFIG_I2C_LPC2K is not set ++# CONFIG_I2C_MESON is not set ++# CONFIG_I2C_MT65XX is not set ++# CONFIG_I2C_NOMADIK 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_RIIC is not set ++# CONFIG_I2C_RK3X is not set ++# CONFIG_I2C_SH_MOBILE is not set ++# CONFIG_I2C_SIMTEC is not set ++# CONFIG_I2C_SUN6I_P2WI is not set ++# CONFIG_I2C_UNIPHIER is not set ++# CONFIG_I2C_UNIPHIER_F is not set ++# CONFIG_I2C_VERSATILE is not set ++# CONFIG_I2C_THUNDERX is not set ++# CONFIG_I2C_XILINX is not set ++# CONFIG_I2C_XLP9XX is not set ++# CONFIG_I2C_RCAR 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_DMA_MSG_MIN_LEN=5 ++CONFIG_DMA_MSG_MAX_LEN=4090 ++# 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_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_ATMEL is not set ++# CONFIG_SPI_AXI_SPI_ENGINE is not set ++# CONFIG_SPI_BCM2835 is not set ++# CONFIG_SPI_BCM2835AUX is not set ++# CONFIG_SPI_BCM63XX is not set ++# CONFIG_SPI_BCM63XX_HSSPI is not set ++# CONFIG_SPI_BCM_QSPI is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_CLPS711X is not set ++# CONFIG_SPI_DESIGNWARE is not set ++# CONFIG_SPI_EP93XX is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_IMG_SPFI is not set ++# CONFIG_SPI_IMX is not set ++# CONFIG_SPI_JCORE is not set ++# CONFIG_SPI_LP8841_RTC is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_FSL_DSPI is not set ++# CONFIG_SPI_MESON_SPIFC is not set ++# CONFIG_SPI_MT65XX is not set ++# CONFIG_SPI_OC_TINY is not set ++# CONFIG_SPI_OMAP24XX is not set ++# CONFIG_SPI_TI_QSPI is not set ++# CONFIG_SPI_OMAP_100K is not set ++# CONFIG_SPI_ORION is not set ++# CONFIG_SPI_PIC32 is not set ++# CONFIG_SPI_PIC32_SQI is not set ++CONFIG_SPI_PL022=y ++# CONFIG_SPI_PXA2XX is not set ++# CONFIG_SPI_PXA2XX_PCI is not set ++# CONFIG_SPI_ROCKCHIP is not set ++# CONFIG_SPI_RSPI is not set ++# CONFIG_SPI_SC18IS602 is not set ++# CONFIG_SPI_SH_MSIOF is not set ++# CONFIG_SPI_SH is not set ++# CONFIG_SPI_SH_HSPI is not set ++# CONFIG_SPI_ST_SSC4 is not set ++# CONFIG_SPI_SUN4I is not set ++# CONFIG_SPI_SUN6I is not set ++# CONFIG_SPI_TEGRA114 is not set ++# CONFIG_SPI_TEGRA20_SFLASH is not set ++# CONFIG_SPI_TEGRA20_SLINK is not set ++# CONFIG_SPI_THUNDERX is not set ++# CONFIG_SPI_TOPCLIFF_PCH is not set ++# CONFIG_SPI_TXX9 is not set ++# CONFIG_SPI_XCOMM is not set ++# CONFIG_SPI_XILINX is not set ++# CONFIG_SPI_XLP is not set ++# CONFIG_SPI_XTENSA_XTFPGA is not set ++# CONFIG_SPI_ZYNQMP_GQSPI is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_PTP_1588_CLOCK_PCH is not set ++CONFIG_PINCTRL=y ++ ++# ++# Pin controllers ++# ++CONFIG_PINMUX=y ++CONFIG_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++# CONFIG_PINCTRL_AMD is not set ++# CONFIG_PINCTRL_LPC18XX is not set ++CONFIG_PINCTRL_SINGLE=y ++# CONFIG_PINCTRL_ASPEED_G4 is not set ++# CONFIG_PINCTRL_ASPEED_G5 is not set ++# CONFIG_PINCTRL_BCM281XX is not set ++# CONFIG_PINCTRL_IPROC_GPIO is not set ++# CONFIG_PINCTRL_CYGNUS_MUX is not set ++# CONFIG_PINCTRL_NSP_GPIO is not set ++# CONFIG_PINCTRL_NS2_MUX is not set ++# CONFIG_PINCTRL_NSP_MUX is not set ++# CONFIG_PINCTRL_BERLIN_BG2 is not set ++# CONFIG_PINCTRL_BERLIN_BG2CD is not set ++# CONFIG_PINCTRL_BERLIN_BG2Q is not set ++# CONFIG_PINCTRL_BERLIN_BG4CT is not set ++# CONFIG_PINCTRL_PXA25X is not set ++# CONFIG_PINCTRL_PXA27X is not set ++# CONFIG_PINCTRL_APQ8064 is not set ++# CONFIG_PINCTRL_APQ8084 is not set ++# CONFIG_PINCTRL_IPQ4019 is not set ++# CONFIG_PINCTRL_IPQ8064 is not set ++# CONFIG_PINCTRL_MSM8660 is not set ++# CONFIG_PINCTRL_MSM8960 is not set ++# CONFIG_PINCTRL_MDM9615 is not set ++# CONFIG_PINCTRL_MSM8X74 is not set ++# CONFIG_PINCTRL_MSM8916 is not set ++# CONFIG_PINCTRL_MSM8996 is not set ++# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set ++# CONFIG_PINCTRL_STM32F429 is not set ++# CONFIG_PINCTRL_STM32F746 is not set ++# CONFIG_PINCTRL_UNIPHIER is not set ++# CONFIG_PINCTRL_MT2701 is not set ++# CONFIG_PINCTRL_MT7623 is not set ++# CONFIG_PINCTRL_MT8135 is not set ++# CONFIG_PINCTRL_MT8127 is not set ++# CONFIG_PINCTRL_MT8173 is not set ++# CONFIG_PINCTRL_MT6397 is not set ++CONFIG_GPIOLIB=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_GENERIC=y ++ ++# ++# Memory mapped GPIO drivers ++# ++# CONFIG_GPIO_74XX_MMIO is not set ++# CONFIG_GPIO_ALTERA is not set ++# CONFIG_GPIO_ASPEED is not set ++# CONFIG_GPIO_ATH79 is not set ++# CONFIG_GPIO_BCM_KONA is not set ++# CONFIG_GPIO_BRCMSTB is not set ++# CONFIG_GPIO_CLPS711X is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_ETRAXFS is not set ++CONFIG_GPIO_GENERIC_PLATFORM=y ++# CONFIG_GPIO_GRGPIO is not set ++# CONFIG_GPIO_IOP is not set ++# CONFIG_GPIO_LPC18XX is not set ++# CONFIG_GPIO_MB86S7X is not set ++# CONFIG_GPIO_MOCKUP is not set ++# CONFIG_GPIO_MOXART is not set ++# CONFIG_GPIO_MPC8XXX is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_RCAR is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_TEGRA is not set ++# CONFIG_GPIO_TS4800 is not set ++# CONFIG_GPIO_VX855 is not set ++# CONFIG_GPIO_XGENE is not set ++# CONFIG_GPIO_XILINX is not set ++# CONFIG_GPIO_XLP 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 ++# ++ ++# ++# PCI GPIO expanders ++# ++# CONFIG_GPIO_AMD8111 is not set ++# CONFIG_GPIO_BT8XX is not set ++# CONFIG_GPIO_ML_IOH is not set ++# CONFIG_GPIO_PCH is not set ++# CONFIG_GPIO_RDC321X 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_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++# CONFIG_POWER_RESET_HISI is not set ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_XGENE is not set ++# CONFIG_POWER_RESET_KEYSTONE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set ++# CONFIG_POWER_RESET_RMOBILE is not set ++# CONFIG_POWER_RESET_ZX is not set ++# CONFIG_SYSCON_REBOOT_MODE is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_ACT8945A is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27XXX is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_MANAGER is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24257 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_BQ25890 is not set ++# CONFIG_CHARGER_SMB347 is not set ++# CONFIG_BATTERY_GAUGE_LTC2941 is not set ++# CONFIG_BATTERY_GOLDFISH is not set ++# CONFIG_CHARGER_RT9455 is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_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_MX25_TSADC is not set ++# CONFIG_MFD_HI6421_PMIC is not set ++# CONFIG_MFD_HI655X_PMIC is not set ++CONFIG_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_HTC_I2CPLD is not set ++# CONFIG_LPC_ICH is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_INTEL_SOC_PMIC is not set ++# CONFIG_MFD_JANZ_CMODIO 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_RDC321X is not set ++# CONFIG_MFD_RTSX_PCI 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=y ++# 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_TIMBERDALE is not set ++# CONFIG_MFD_TC3589X is not set ++# CONFIG_MFD_TMIO is not set ++# CONFIG_MFD_VX855 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_MFD_STW481X is not set ++CONFIG_REGULATOR=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_LTC3676 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MT6311 is not set ++# CONFIG_REGULATOR_PBIAS is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_PV88060 is not set ++# CONFIG_REGULATOR_PV88080 is not set ++# CONFIG_REGULATOR_PV88090 is not set ++# CONFIG_REGULATOR_QCOM_SPMI is not set ++# CONFIG_REGULATOR_STW481X_VMMC is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=y ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=y ++CONFIG_VIDEO_V4L2=y ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=y ++CONFIG_VIDEOBUF2_MEMOPS=y ++CONFIG_VIDEOBUF2_VMALLOC=y ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++CONFIG_MEDIA_USB_SUPPORT=y ++ ++# ++# Webcam devices ++# ++CONFIG_USB_VIDEO_CLASS=y ++CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y ++CONFIG_USB_GSPCA=m ++# CONFIG_USB_M5602 is not set ++# CONFIG_USB_STV06XX is not set ++# CONFIG_USB_GL860 is not set ++# CONFIG_USB_GSPCA_BENQ is not set ++# CONFIG_USB_GSPCA_CONEX is not set ++# CONFIG_USB_GSPCA_CPIA1 is not set ++# CONFIG_USB_GSPCA_DTCS033 is not set ++# CONFIG_USB_GSPCA_ETOMS is not set ++# CONFIG_USB_GSPCA_FINEPIX is not set ++# CONFIG_USB_GSPCA_JEILINJ is not set ++# CONFIG_USB_GSPCA_JL2005BCD is not set ++# CONFIG_USB_GSPCA_KINECT is not set ++# CONFIG_USB_GSPCA_KONICA is not set ++# CONFIG_USB_GSPCA_MARS is not set ++# CONFIG_USB_GSPCA_MR97310A is not set ++# CONFIG_USB_GSPCA_NW80X is not set ++# CONFIG_USB_GSPCA_OV519 is not set ++# CONFIG_USB_GSPCA_OV534 is not set ++# CONFIG_USB_GSPCA_OV534_9 is not set ++# CONFIG_USB_GSPCA_PAC207 is not set ++# CONFIG_USB_GSPCA_PAC7302 is not set ++# CONFIG_USB_GSPCA_PAC7311 is not set ++# CONFIG_USB_GSPCA_SE401 is not set ++# CONFIG_USB_GSPCA_SN9C2028 is not set ++# CONFIG_USB_GSPCA_SN9C20X is not set ++# CONFIG_USB_GSPCA_SONIXB is not set ++# CONFIG_USB_GSPCA_SONIXJ is not set ++# CONFIG_USB_GSPCA_SPCA500 is not set ++# CONFIG_USB_GSPCA_SPCA501 is not set ++# CONFIG_USB_GSPCA_SPCA505 is not set ++# CONFIG_USB_GSPCA_SPCA506 is not set ++# CONFIG_USB_GSPCA_SPCA508 is not set ++# CONFIG_USB_GSPCA_SPCA561 is not set ++# CONFIG_USB_GSPCA_SPCA1528 is not set ++# CONFIG_USB_GSPCA_SQ905 is not set ++# CONFIG_USB_GSPCA_SQ905C is not set ++# CONFIG_USB_GSPCA_SQ930X is not set ++# CONFIG_USB_GSPCA_STK014 is not set ++# CONFIG_USB_GSPCA_STK1135 is not set ++# CONFIG_USB_GSPCA_STV0680 is not set ++# CONFIG_USB_GSPCA_SUNPLUS is not set ++# CONFIG_USB_GSPCA_T613 is not set ++# CONFIG_USB_GSPCA_TOPRO is not set ++# CONFIG_USB_GSPCA_TOUPTEK is not set ++# CONFIG_USB_GSPCA_TV8532 is not set ++# CONFIG_USB_GSPCA_VC032X is not set ++# CONFIG_USB_GSPCA_VICAM is not set ++# CONFIG_USB_GSPCA_XIRLINK_CIT is not set ++# CONFIG_USB_GSPCA_ZC3XX is not set ++# CONFIG_USB_PWC is not set ++# CONFIG_VIDEO_CPIA2 is not set ++# CONFIG_USB_ZR364XX is not set ++# CONFIG_USB_STKWEBCAM is not set ++# CONFIG_USB_S2255 is not set ++ ++# ++# Webcam, TV (analog/digital) USB devices ++# ++# CONFIG_VIDEO_EM28XX is not set ++# CONFIG_MEDIA_PCI_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, spi, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# I2C Encoders, decoders, sensors and other helper chips ++# ++ ++# ++# Audio decoders, processors and mixers ++# ++# CONFIG_VIDEO_TVAUDIO is not set ++# CONFIG_VIDEO_TDA7432 is not set ++# CONFIG_VIDEO_TDA9840 is not set ++# CONFIG_VIDEO_TEA6415C is not set ++# CONFIG_VIDEO_TEA6420 is not set ++# CONFIG_VIDEO_MSP3400 is not set ++# CONFIG_VIDEO_CS3308 is not set ++# CONFIG_VIDEO_CS5345 is not set ++# CONFIG_VIDEO_CS53L32A is not set ++# CONFIG_VIDEO_TLV320AIC23B is not set ++# CONFIG_VIDEO_UDA1342 is not set ++# CONFIG_VIDEO_WM8775 is not set ++# CONFIG_VIDEO_WM8739 is not set ++# CONFIG_VIDEO_VP27SMPX is not set ++# CONFIG_VIDEO_SONY_BTF_MPX is not set ++ ++# ++# RDS decoders ++# ++# CONFIG_VIDEO_SAA6588 is not set ++ ++# ++# Video decoders ++# ++# CONFIG_VIDEO_ADV7183 is not set ++# CONFIG_VIDEO_BT819 is not set ++# CONFIG_VIDEO_BT856 is not set ++# CONFIG_VIDEO_BT866 is not set ++# CONFIG_VIDEO_KS0127 is not set ++# CONFIG_VIDEO_ML86V7667 is not set ++# CONFIG_VIDEO_SAA7110 is not set ++# CONFIG_VIDEO_SAA711X is not set ++# CONFIG_VIDEO_TVP514X is not set ++# CONFIG_VIDEO_TVP5150 is not set ++# CONFIG_VIDEO_TVP7002 is not set ++# CONFIG_VIDEO_TW2804 is not set ++# CONFIG_VIDEO_TW9903 is not set ++# CONFIG_VIDEO_TW9906 is not set ++# CONFIG_VIDEO_VPX3220 is not set ++ ++# ++# Video and audio decoders ++# ++# CONFIG_VIDEO_SAA717X is not set ++# CONFIG_VIDEO_CX25840 is not set ++ ++# ++# Video encoders ++# ++# CONFIG_VIDEO_SAA7127 is not set ++# CONFIG_VIDEO_SAA7185 is not set ++# CONFIG_VIDEO_ADV7170 is not set ++# CONFIG_VIDEO_ADV7175 is not set ++# CONFIG_VIDEO_ADV7343 is not set ++# CONFIG_VIDEO_ADV7393 is not set ++# CONFIG_VIDEO_AK881X is not set ++# CONFIG_VIDEO_THS8200 is not set ++ ++# ++# Camera sensor devices ++# ++# CONFIG_VIDEO_OV2659 is not set ++# CONFIG_VIDEO_OV7640 is not set ++# CONFIG_VIDEO_OV7670 is not set ++# CONFIG_VIDEO_VS6624 is not set ++# CONFIG_VIDEO_MT9M111 is not set ++# CONFIG_VIDEO_MT9V011 is not set ++# CONFIG_VIDEO_SR030PC30 is not set ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++# CONFIG_VIDEO_UPD64031A is not set ++# CONFIG_VIDEO_UPD64083 is not set ++ ++# ++# Audio/Video compression chips ++# ++# CONFIG_VIDEO_SAA6752HS is not set ++ ++# ++# Miscellaneous helper chips ++# ++# CONFIG_VIDEO_THS7303 is not set ++# CONFIG_VIDEO_M52790 is not set ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# SPI helper chips ++# ++ ++# ++# Customise DVB Frontends ++# ++# CONFIG_DVB_AU8522_V4L is not set ++# CONFIG_DVB_TUNER_DIB0070 is not set ++# CONFIG_DVB_TUNER_DIB0090 is not set ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++CONFIG_VGA_ARB=y ++CONFIG_VGA_ARB_MAX_GPUS=16 ++# CONFIG_DRM is not set ++ ++# ++# ACP (Audio CoProcessor) Configuration ++# ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++CONFIG_FB_NOTIFY=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_CIRRUS is not set ++# CONFIG_FB_PM2 is not set ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CLPS711X is not set ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_NVIDIA is not set ++# CONFIG_FB_RIVA is not set ++# CONFIG_FB_I740 is not set ++# CONFIG_FB_MATROX is not set ++# CONFIG_FB_RADEON is not set ++# CONFIG_FB_ATY128 is not set ++# CONFIG_FB_ATY is not set ++# CONFIG_FB_S3 is not set ++# CONFIG_FB_SAVAGE is not set ++# CONFIG_FB_SIS is not set ++# CONFIG_FB_NEOMAGIC is not set ++# CONFIG_FB_KYRO is not set ++# CONFIG_FB_3DFX is not set ++# CONFIG_FB_VOODOO1 is not set ++# CONFIG_FB_VT8623 is not set ++# CONFIG_FB_TRIDENT is not set ++# CONFIG_FB_ARK is not set ++# CONFIG_FB_PM3 is not set ++# CONFIG_FB_CARMINE is not set ++# CONFIG_FB_TMIO is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_IBM_GXT4500 is not set ++# CONFIG_FB_GOLDFISH is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_MB862XX is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_FB_SM712 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++CONFIG_DUMMY_CONSOLE_COLUMNS=80 ++CONFIG_DUMMY_CONSOLE_ROWS=25 ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++# CONFIG_HID_BETOP_FF is not set ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CMEDIA is not set ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_GEMBIRD is not set ++# CONFIG_HID_GFRM is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PLANTRONICS is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++# CONFIG_HID_ALPS is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++# 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 is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PCI=y ++CONFIG_USB_XHCI_PLATFORM=y ++# CONFIG_USB_XHCI_MTK is not set ++# CONFIG_USB_XHCI_MVEBU is not set ++# CONFIG_USB_XHCI_RCAR 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_UHCI_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 ++# CONFIG_USB_RENESAS_USBHS is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++# CONFIG_USB_WDM is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++# CONFIG_USBIP_CORE is not set ++# CONFIG_USB_MUSB_HDRC is not set ++CONFIG_USB_DWC3=y ++# CONFIG_USB_DWC3_HOST is not set ++CONFIG_USB_DWC3_GADGET=y ++# CONFIG_USB_DWC3_DUAL_ROLE is not set ++ ++# ++# Platform Glue Driver Support ++# ++CONFIG_USB_DWC3_EXYNOS=y ++CONFIG_USB_DWC3_PCI=y ++CONFIG_USB_DWC3_KEYSTONE=y ++CONFIG_USB_DWC3_OF_SIMPLE=y ++# CONFIG_USB_DWC2 is not set ++# CONFIG_USB_CHIPIDEA 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++# CONFIG_USB_GADGET_DEBUG_FS is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_RENESAS_USB3 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_BDC_UDC is not set ++# CONFIG_USB_AMD5536UDC is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_NET2280 is not set ++# CONFIG_USB_GOKU is not set ++# CONFIG_USB_EG20T is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_MASS_STORAGE=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM 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_ARMMMCI is not set ++CONFIG_MMC_SDHCI=y ++# CONFIG_MMC_SDHCI_PCI is not set ++CONFIG_MMC_SDHCI_PLTFM=y ++# CONFIG_MMC_SDHCI_OF_ARASAN is not set ++# CONFIG_MMC_SDHCI_OF_AT91 is not set ++CONFIG_MMC_SDHCI_HISI=y ++# CONFIG_MMC_SDHCI_PXAV3 is not set ++# CONFIG_MMC_SDHCI_PXAV2 is not set ++# CONFIG_MMC_SDHCI_F_SDH30 is not set ++# CONFIG_MMC_SDHCI_IPROC is not set ++# CONFIG_MMC_OMAP_HS is not set ++# CONFIG_MMC_TIFM_SD is not set ++# CONFIG_MMC_GOLDFISH is not set ++# CONFIG_MMC_SPI is not set ++# CONFIG_MMC_SDHI is not set ++# CONFIG_MMC_CB710 is not set ++# CONFIG_MMC_VIA_SDMMC is not set ++# CONFIG_MMC_DW is not set ++# CONFIG_MMC_SH_MMCIF is not set ++# CONFIG_MMC_VUB300 is not set ++# CONFIG_MMC_USHC is not set ++# CONFIG_MMC_USDHI6ROL0 is not set ++# CONFIG_MMC_TOSHIBA_PCI 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_INFINIBAND is not set ++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=y ++ ++# ++# SPI and I2C RTC drivers ++# ++# CONFIG_RTC_DRV_DS3232 is not set ++# CONFIG_RTC_DRV_PCF2127 is not set ++# CONFIG_RTC_DRV_RV3029C2 is not set ++ ++# ++# Platform RTC drivers ++# ++CONFIG_RTC_DRV_HIBVT=y ++# 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_SPEAR is not set ++# CONFIG_RTC_DRV_NUC900 is not set ++# CONFIG_RTC_DRV_ZYNQMP is not set ++ ++# ++# on-CPU RTC drivers ++# ++# CONFIG_RTC_DRV_ASM9260 is not set ++# CONFIG_RTC_DRV_DAVINCI is not set ++# CONFIG_RTC_DRV_DIGICOLOR is not set ++# CONFIG_RTC_DRV_OMAP is not set ++# CONFIG_RTC_DRV_S3C is not set ++# CONFIG_RTC_DRV_EP93XX is not set ++# CONFIG_RTC_DRV_VR41XX is not set ++# CONFIG_RTC_DRV_PL030 is not set ++# CONFIG_RTC_DRV_PL031 is not set ++# CONFIG_RTC_DRV_AT32AP700X is not set ++# CONFIG_RTC_DRV_AT91RM9200 is not set ++# CONFIG_RTC_DRV_AT91SAM9 is not set ++# CONFIG_RTC_DRV_GENERIC is not set ++# CONFIG_RTC_DRV_VT8500 is not set ++# CONFIG_RTC_DRV_SUNXI is not set ++# CONFIG_RTC_DRV_MV is not set ++# CONFIG_RTC_DRV_ARMADA38X is not set ++# CONFIG_RTC_DRV_GEMINI is not set ++# CONFIG_RTC_DRV_COH901331 is not set ++# CONFIG_RTC_DRV_STMP is not set ++# CONFIG_RTC_DRV_JZ4740 is not set ++# CONFIG_RTC_DRV_LPC24XX is not set ++# CONFIG_RTC_DRV_LPC32XX is not set ++# CONFIG_RTC_DRV_PM8XXX is not set ++# CONFIG_RTC_DRV_TEGRA is not set ++# CONFIG_RTC_DRV_SNVS is not set ++# CONFIG_RTC_DRV_MOXART is not set ++# CONFIG_RTC_DRV_MT6397 is not set ++# CONFIG_RTC_DRV_XGENE is not set ++ ++# ++# HID Sensor RTC drivers ++# ++# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set ++CONFIG_DMADEVICES=y ++# CONFIG_DMADEVICES_DEBUG is not set ++ ++# ++# DMA Devices ++# ++CONFIG_DMA_ENGINE=y ++CONFIG_DMA_VIRTUAL_CHANNELS=y ++CONFIG_DMA_OF=y ++# CONFIG_AMBA_PL08X is not set ++# CONFIG_AXI_DMAC is not set ++# CONFIG_COH901318 is not set ++# CONFIG_DMA_JZ4740 is not set ++# CONFIG_DMA_JZ4780 is not set ++# CONFIG_DMA_OMAP is not set ++# CONFIG_DMA_SA11X0 is not set ++# CONFIG_DMA_SUN6I is not set ++# CONFIG_EP93XX_DMA is not set ++# CONFIG_FSL_EDMA is not set ++# CONFIG_IMG_MDC_DMA is not set ++# CONFIG_INTEL_IDMA64 is not set ++# CONFIG_K3_DMA is not set ++# CONFIG_MMP_PDMA is not set ++# CONFIG_MMP_TDMA is not set ++# CONFIG_MV_XOR is not set ++# CONFIG_MV_XOR_V2 is not set ++# CONFIG_NBPFAXI_DMA is not set ++# CONFIG_PCH_DMA is not set ++# CONFIG_PL330_DMA is not set ++# CONFIG_STM32_DMA is not set ++# CONFIG_S3C24XX_DMAC is not set ++# CONFIG_TEGRA210_ADMA is not set ++# CONFIG_TIMB_DMA is not set ++# CONFIG_TI_EDMA is not set ++# CONFIG_XGENE_DMA is not set ++# CONFIG_XILINX_DMA is not set ++# CONFIG_XILINX_ZYNQMP_DMA is not set ++# CONFIG_ZX_DMA is not set ++CONFIG_HIEDMACV310=y ++# CONFIG_QCOM_HIDMA_MGMT is not set ++# CONFIG_QCOM_HIDMA is not set ++# CONFIG_DW_DMAC is not set ++# CONFIG_DW_DMAC_PCI is not set ++CONFIG_RENESAS_DMA=y ++CONFIG_SH_DMAE_BASE=y ++# CONFIG_SH_DMAE is not set ++# CONFIG_RCAR_DMAC is not set ++# CONFIG_RENESAS_USB_DMAC is not set ++# CONFIG_SUDMAC 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_PCI is not set ++# CONFIG_VIRTIO_MMIO is not set ++ ++# ++# Microsoft Hyper-V guest support ++# ++CONFIG_STAGING=y ++# CONFIG_COMEDI is not set ++# CONFIG_RTL8192U is not set ++# CONFIG_RTLLIB is not set ++# CONFIG_R8712U is not set ++# CONFIG_RTS5208 is not set ++# CONFIG_FB_SM750 is not set ++# CONFIG_FB_XGI is not set ++ ++# ++# Speakup console speech ++# ++# CONFIG_SPEAKUP is not set ++# CONFIG_STAGING_MEDIA is not set ++ ++# ++# Android ++# ++# CONFIG_ASHMEM is not set ++# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set ++CONFIG_ION=y ++# CONFIG_ION_TEST is not set ++# CONFIG_ION_DUMMY is not set ++# CONFIG_ION_OF is not set ++# CONFIG_STAGING_BOARD is not set ++# CONFIG_LTE_GDM724X is not set ++# CONFIG_MTD_SPINAND_MT29F is not set ++# CONFIG_LNET is not set ++# CONFIG_DGNC is not set ++# CONFIG_GS_FPGABOOT is not set ++# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set ++# CONFIG_FB_TFT is not set ++# CONFIG_FSL_MC_BUS is not set ++# CONFIG_MOST is not set ++# CONFIG_KS7010 is not set ++# CONFIG_GREYBUS 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_VERSATILE is not set ++# CONFIG_COMMON_CLK_SCPI is not set ++# 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_COMMON_CLK_AXI_CLKGEN is not set ++# CONFIG_CLK_QORIQ is not set ++# CONFIG_COMMON_CLK_XGENE is not set ++# CONFIG_COMMON_CLK_KEYSTONE is not set ++# CONFIG_COMMON_CLK_NXP is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_PIC32 is not set ++# CONFIG_COMMON_CLK_OXNAS is not set ++# CONFIG_CLK_BCM_63XX is not set ++# CONFIG_CLK_BCM_KONA is not set ++# CONFIG_COMMON_CLK_IPROC is not set ++# CONFIG_COMMON_CLK_HI3519 is not set ++# CONFIG_COMMON_CLK_HI3516A is not set ++# CONFIG_COMMON_CLK_HI3518EV20X is not set ++# CONFIG_COMMON_CLK_HI3536DV100 is not set ++CONFIG_COMMON_CLK_HI3559AV100=y ++CONFIG_COMMON_CLK_HI3521A=y ++CONFIG_COMMON_CLK_HI3531A=y ++# CONFIG_COMMON_CLK_HI6220 is not set ++CONFIG_RESET_HISI=y ++# CONFIG_COMMON_CLK_MT8135 is not set ++# CONFIG_COMMON_CLK_MT8173 is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++# CONFIG_COMMON_CLK_SAMSUNG is not set ++# CONFIG_S3C2410_COMMON_CLK is not set ++# CONFIG_S3C2412_COMMON_CLK is not set ++# CONFIG_S3C2443_COMMON_CLK is not set ++# CONFIG_SUNXI_CCU is not set ++# CONFIG_COMMON_CLK_TI_ADPLL is not set ++# CONFIG_CLK_UNIPHIER is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_PROBE=y ++CONFIG_CLKSRC_MMIO=y ++# CONFIG_BCM2835_TIMER is not set ++# CONFIG_BCM_KONA_TIMER is not set ++# CONFIG_DIGICOLOR_TIMER is not set ++# CONFIG_DW_APB_TIMER is not set ++# CONFIG_ROCKCHIP_TIMER is not set ++# CONFIG_MESON6_TIMER is not set ++# CONFIG_SUN4I_TIMER is not set ++# CONFIG_SUN5I_HSTIMER is not set ++# CONFIG_VT8500_TIMER is not set ++# CONFIG_CADENCE_TTC_TIMER is not set ++# CONFIG_ASM9260_TIMER is not set ++# CONFIG_CLKSRC_DBX500_PRCMU is not set ++# CONFIG_CLPS711X_TIMER is not set ++# CONFIG_ATLAS7_TIMER is not set ++# CONFIG_MOXART_TIMER is not set ++# CONFIG_MXS_TIMER is not set ++# CONFIG_PRIMA2_TIMER is not set ++# CONFIG_NSPIRE_TIMER is not set ++# CONFIG_KEYSTONE_TIMER is not set ++# CONFIG_INTEGRATOR_AP_TIMER is not set ++# CONFIG_CLKSRC_PISTACHIO is not set ++# CONFIG_CLKSRC_TI_32K is not set ++# CONFIG_CLKSRC_MPS2 is not set ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set ++CONFIG_FSL_ERRATUM_A008585=y ++CONFIG_ARM_TIMER_SP804=y ++# CONFIG_TIMER_HISP804 is not set ++# CONFIG_ARMV7M_SYSTICK is not set ++# CONFIG_ATMEL_PIT is not set ++# CONFIG_ATMEL_ST is not set ++# CONFIG_CLKSRC_EXYNOS_MCT is not set ++# CONFIG_CLKSRC_SAMSUNG_PWM is not set ++# CONFIG_FSL_FTM_TIMER is not set ++# CONFIG_OXNAS_RPS_TIMER is not set ++# CONFIG_MTK_TIMER is not set ++# CONFIG_CLKSRC_JCORE_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_CLKSRC_VERSATILE is not set ++# CONFIG_CLKSRC_PXA is not set ++# CONFIG_H8300_TMR8 is not set ++# CONFIG_H8300_TMR16 is not set ++# CONFIG_H8300_TPU is not set ++# CONFIG_CLKSRC_ST_LPC 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_MTK_INFRACFG is not set ++# CONFIG_MTK_SCPSYS is not set ++# CONFIG_ROCKCHIP_PM_DOMAINS is not set ++# CONFIG_SOC_SAMSUNG is not set ++# CONFIG_SUNXI_SRAM is not set ++# CONFIG_SOC_TI is not set ++# CONFIG_UX500_SOC_ID is not set ++CONFIG_PM_DEVFREQ=y ++ ++# ++# DEVFREQ Governors ++# ++CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y ++# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set ++# CONFIG_DEVFREQ_GOV_POWERSAVE is not set ++# CONFIG_DEVFREQ_GOV_USERSPACE is not set ++# CONFIG_DEVFREQ_GOV_PASSIVE is not set ++ ++# ++# DEVFREQ Drivers ++# ++# CONFIG_ARM_EXYNOS_BUS_DEVFREQ is not set ++# CONFIG_PM_DEVFREQ_EVENT is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_NTB is not set ++# CONFIG_VME_BUS is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_MAX_NR=1 ++CONFIG_ARM_GIC_V2M=y ++CONFIG_ARM_GIC_V3=y ++CONFIG_ARM_GIC_V3_ITS=y ++CONFIG_HISILICON_IRQ_MBIGEN=y ++# CONFIG_JCORE_AIC is not set ++# CONFIG_TS4800_IRQ is not set ++CONFIG_PARTITION_PERCPU=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_RESET_ATH79 is not set ++# CONFIG_RESET_BERLIN is not set ++# CONFIG_RESET_LPC18XX is not set ++# CONFIG_RESET_MESON is not set ++# CONFIG_RESET_PISTACHIO is not set ++# CONFIG_RESET_SOCFPGA is not set ++# CONFIG_RESET_STM32 is not set ++# CONFIG_RESET_SUNXI is not set ++# CONFIG_TI_SYSCON_RESET is not set ++# CONFIG_RESET_UNIPHIER is not set ++# CONFIG_RESET_ZYNQ is not set ++CONFIG_COMMON_RESET_HI6220=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_PHY_BCM_NS_USB2 is not set ++# CONFIG_PHY_BCM_NS_USB3 is not set ++CONFIG_ARMADA375_USBCLUSTER_PHY=y ++# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set ++# CONFIG_PHY_LPC18XX_USB_OTG is not set ++# CONFIG_PHY_PXA_28NM_HSIC is not set ++# CONFIG_PHY_PXA_28NM_USB2 is not set ++# CONFIG_OMAP_CONTROL_PHY is not set ++# CONFIG_PHY_EXYNOS_DP_VIDEO is not set ++# CONFIG_BCM_KONA_USB2_PHY is not set ++# CONFIG_PHY_HI6220_USB is not set ++# CONFIG_PHY_ROCKCHIP_INNO_USB2 is not set ++# CONFIG_PHY_ROCKCHIP_PCIE is not set ++# CONFIG_PHY_ROCKCHIP_TYPEC is not set ++# CONFIG_PHY_ST_SPEAR1310_MIPHY is not set ++# CONFIG_PHY_ST_SPEAR1340_MIPHY is not set ++# CONFIG_PHY_XGENE is not set ++# CONFIG_PHY_STIH407_USB is not set ++# CONFIG_PHY_BRCM_SATA is not set ++# CONFIG_PHY_CYGNUS_PCIE is not set ++CONFIG_HISI_PHY_USB3=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++ ++# ++# Performance monitor support ++# ++CONFIG_ARM_PMU=y ++# CONFIG_RAS is not set ++# CONFIG_THUNDERBOLT is not set ++ ++# ++# Android ++# ++CONFIG_ANDROID=y ++# CONFIG_ANDROID_BINDER_IPC is not set ++# CONFIG_LIBNVDIMM 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 ++# CONFIG_HI_DMAC is not set ++# CONFIG_HIVDMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE is not set ++ ++# ++# Firmware Drivers ++# ++CONFIG_ARM_PSCI_FW=y ++CONFIG_ARM_SCPI_POWER_DOMAIN=y ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_FW_CFG_SYSFS is not set ++CONFIG_HAVE_ARM_SMCCC=y ++# CONFIG_MESON_SM is not set ++# CONFIG_ACPI is not set ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++CONFIG_FS_IOMAP=y ++CONFIG_EXT2_FS=y ++CONFIG_EXT2_FS_XATTR=y ++CONFIG_EXT2_FS_POSIX_ACL=y ++CONFIG_EXT2_FS_SECURITY=y ++CONFIG_EXT3_FS=y ++CONFIG_EXT3_FS_POSIX_ACL=y ++CONFIG_EXT3_FS_SECURITY=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++# CONFIG_EXT4_ENCRYPTION is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++CONFIG_REISERFS_FS=m ++CONFIG_REISERFS_CHECK=y ++CONFIG_REISERFS_PROC_INFO=y ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_REISERFS_FS_POSIX_ACL=y ++CONFIG_REISERFS_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_JFS_DEBUG=y ++CONFIG_JFS_STATISTICS=y ++CONFIG_XFS_FS=m ++CONFIG_XFS_QUOTA=y ++CONFIG_XFS_POSIX_ACL=y ++CONFIG_XFS_RT=y ++# CONFIG_XFS_WARN is not set ++# CONFIG_XFS_DEBUG is not set ++# CONFIG_GFS2_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_DAX is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_EXPORTFS=m ++# 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=y ++# CONFIG_QUOTA_NETLINK_INTERFACE is not set ++CONFIG_PRINT_QUOTA_WARNING=y ++# CONFIG_QUOTA_DEBUG is not set ++CONFIG_QUOTA_TREE=m ++CONFIG_QFMT_V1=m ++CONFIG_QFMT_V2=m ++CONFIG_QUOTACTL=y ++CONFIG_AUTOFS4_FS=m ++CONFIG_FUSE_FS=y ++# CONFIG_CUSE is not set ++# CONFIG_OVERLAY_FS is not set ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=y ++# CONFIG_JOLIET is not set ++# CONFIG_ZISOFS is not set ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++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_KCORE is not set ++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=y ++CONFIG_TMPFS_XATTR=y ++# CONFIG_HUGETLBFS is not set ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_ARCH_HAS_GIGANTIC_PAGE=y ++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_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++CONFIG_SQUASHFS=y ++CONFIG_SQUASHFS_FILE_CACHE=y ++# CONFIG_SQUASHFS_FILE_DIRECT is not set ++CONFIG_SQUASHFS_DECOMP_SINGLE=y ++# CONFIG_SQUASHFS_DECOMP_MULTI is not set ++# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set ++# CONFIG_SQUASHFS_XATTR is not set ++CONFIG_SQUASHFS_ZLIB=y ++# CONFIG_SQUASHFS_LZ4 is not set ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set ++# CONFIG_SQUASHFS_EMBEDDED is not set ++CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 ++# 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=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_SWAP is not set ++# CONFIG_NFSD is not set ++CONFIG_GRACE_PERIOD=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_ACL_SUPPORT=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=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=y ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++# 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 ++# CONFIG_VIRTUALIZATION is not set ++ ++# ++# Kernel hacking ++# ++ ++# ++# printk and dmesg options ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++# 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=2048 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_PAGE_OWNER is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++CONFIG_ARCH_WANT_FRAME_POINTERS=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_PAGE_EXTENSION is not set ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_PAGE_POISONING is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++CONFIG_HAVE_ARCH_KASAN=y ++# CONFIG_KASAN is not set ++CONFIG_ARCH_HAS_KCOV=y ++# CONFIG_KCOV is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++CONFIG_LOCKUP_DETECTOR=y ++# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set ++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 ++# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set ++CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 ++# CONFIG_WQ_WATCHDOG is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++CONFIG_SCHED_INFO=y ++CONFIG_SCHEDSTATS=y ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_DEBUG_TIMEKEEPING is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_HAVE_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_PROVE_RCU is not set ++CONFIG_SPARSE_RCU_POINTER=y ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_PERF_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=21 ++CONFIG_RCU_TRACE=y ++# CONFIG_RCU_EQS_DEBUG is not set ++# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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_TRACE_CLOCK=y ++CONFIG_TRACING_SUPPORT=y ++# CONFIG_FTRACE is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_LKDTM is not set ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST 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_KGDB is not set ++CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=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_ARM64_PTDUMP is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_DEBUG_ALIGN_RODATA is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS 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=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=m ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=m ++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 is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++CONFIG_CRYPTO_NULL=m ++CONFIG_CRYPTO_NULL2=y ++# CONFIG_CRYPTO_PCRYPT is not set ++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=m ++# CONFIG_CRYPTO_GCM is not set ++# CONFIG_CRYPTO_CHACHA20POLY1305 is not set ++CONFIG_CRYPTO_SEQIV=m ++CONFIG_CRYPTO_ECHAINIV=m ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=m ++# 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=y ++CONFIG_CRYPTO_HMAC=m ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# 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 is not set ++# 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 is not set ++# 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=y ++CONFIG_CRYPTO_LZO=y ++# 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=m ++CONFIG_CRYPTO_DRBG_HMAC=y ++# CONFIG_CRYPTO_DRBG_HASH is not set ++# CONFIG_CRYPTO_DRBG_CTR is not set ++CONFIG_CRYPTO_DRBG=m ++CONFIG_CRYPTO_JITTERENTROPY=m ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++# CONFIG_CRYPTO_USER_API_RNG is not set ++# CONFIG_CRYPTO_USER_API_AEAD is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_CRYPTO_DEV_S5P is not set ++# CONFIG_CRYPTO_DEV_ATMEL_AES is not set ++# CONFIG_CRYPTO_DEV_CCP is not set ++# CONFIG_CRYPTO_DEV_QCE is not set ++# CONFIG_CRYPTO_DEV_IMGTEC_HASH is not set ++ ++# ++# Certificates for signature checking ++# ++# CONFIG_ARM64_CRYPTO is not set ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++CONFIG_HAVE_ARCH_BITREVERSE=y ++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=y ++CONFIG_CRC16=y ++# CONFIG_CRC_T10DIF is not set ++CONFIG_CRC_ITU_T=y ++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=m ++# CONFIG_CRC8 is not set ++CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y ++# CONFIG_RANDOM32_SELFTEST is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=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_GZIP=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_NLATTR=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=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++CONFIG_SBITMAP=y +diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h +index 851290d..f907b63 100644 +--- a/arch/arm64/include/asm/assembler.h ++++ b/arch/arm64/include/asm/assembler.h +@@ -42,6 +42,18 @@ + .endm + + /* ++ * Save/disable and restore interrupts. ++ */ ++ .macro save_and_disable_irqs, olddaif ++ mrs \olddaif, daif ++ disable_irq ++ .endm ++ ++ .macro restore_irqs, olddaif ++ msr daif, \olddaif ++ .endm ++ ++/* + * Enable and disable debug exceptions. + */ + .macro disable_dbg +diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h +index 2e5fb97..5e1b7e3f 100644 +--- a/arch/arm64/include/asm/cacheflush.h ++++ b/arch/arm64/include/asm/cacheflush.h +@@ -40,6 +40,10 @@ + * the implementation assumes non-aliasing VIPT D-cache and (aliasing) + * VIPT or ASID-tagged VIVT I-cache. + * ++ * flush_cache_all() ++ * ++ * Unconditionally clean and invalidate the entire cache. ++ * + * flush_cache_mm(mm) + * + * Clean and invalidate all user space cache entries +@@ -65,6 +69,7 @@ + * - kaddr - page address + * - size - region size + */ ++extern void flush_cache_all(void); + extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); + extern void flush_icache_range(unsigned long start, unsigned long end); + extern void __flush_dcache_area(void *addr, size_t len); +diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h +index d14c478..24da4f2 100644 +--- a/arch/arm64/include/asm/esr.h ++++ b/arch/arm64/include/asm/esr.h +@@ -175,6 +175,12 @@ + #define ESR_ELx_SYS64_ISS_SYS_CTR_READ (ESR_ELx_SYS64_ISS_SYS_CTR | \ + ESR_ELx_SYS64_ISS_DIR_READ) + ++#define ESR_ELx_SYS64_ISS_SYS_CNTVCT (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \ ++ ESR_ELx_SYS64_ISS_DIR_READ) ++ ++#define ESR_ELx_SYS64_ISS_SYS_CNTFRQ (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 0, 14, 0) | \ ++ ESR_ELx_SYS64_ISS_DIR_READ) ++ + #ifndef __ASSEMBLY__ + #include + +diff --git a/arch/arm64/include/mach/platform-hi3559av100.h b/arch/arm64/include/mach/platform-hi3559av100.h +new file mode 100644 +index 0000000..c51e223 +--- /dev/null ++++ b/arch/arm64/include/mach/platform-hi3559av100.h +@@ -0,0 +1,7 @@ ++#ifndef __HI_CHIP_REGS_H__ ++#define __HI_CHIP_REGS_H__ ++ ++#define GET_SYS_BOOT_MODE(_reg) (((_reg) >> 4) & 0x3) ++#define BOOT_FROM_SPI 0 ++#define BOOT_FROM_NAND 1 ++#endif /* End of __HI_CHIP_REGS_H__ */ +diff --git a/arch/arm64/include/mach/platform.h b/arch/arm64/include/mach/platform.h +new file mode 100644 +index 0000000..9f8d559 +--- /dev/null ++++ b/arch/arm64/include/mach/platform.h +@@ -0,0 +1,8 @@ ++#ifndef __PLATFORM_H__ ++#define __PLATFORM_H__ ++ ++#ifdef CONFIG_ARCH_HI3559AV100 ++#include "platform-hi3559av100.h" ++#endif ++ ++#endif /* End of __PLATFORM_H__ */ +diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c +index 3a129d4..2787091 100644 +--- a/arch/arm64/kernel/cpufeature.c ++++ b/arch/arm64/kernel/cpufeature.c +@@ -108,9 +108,28 @@ static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = { + + static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = { + ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0), ++#ifdef CONFIG_ARCH_HISI_BVT ++ ++#ifdef CONFIG_ARM64_4K_PAGES ++ S_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI), ++#else ++ S_ARM64_FTR_BITS(FTR_NONSTRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI), ++#endif ++#ifdef CONFIG_ARM64_64K_PAGES ++ S_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI), ++#else ++ S_ARM64_FTR_BITS(FTR_NONSTRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI), ++#endif ++#ifdef CONFIG_ARM64_16K_PAGES ++ ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI), ++#else ++ ARM64_FTR_BITS(FTR_NONSTRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI), ++#endif ++#else/* CONFIG_ARCH_HISI_BVT */ + S_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI), + S_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI), + ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI), ++#endif /* CONFIG_ARCH_HISI_BVT */ + ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_BIGENDEL0_SHIFT, 4, 0), + /* Linux shouldn't care about secure memory */ + ARM64_FTR_BITS(FTR_NONSTRICT, FTR_EXACT, ID_AA64MMFR0_SNSMEM_SHIFT, 4, 0), +diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c +index f228261..cd94eda 100644 +--- a/arch/arm64/kernel/traps.c ++++ b/arch/arm64/kernel/traps.c +@@ -488,10 +488,29 @@ static void ctr_read_handler(unsigned int esr, struct pt_regs *regs) + { + int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; + +- regs->regs[rt] = arm64_ftr_reg_ctrel0.sys_val; ++ if (rt != 31) ++ regs->regs[rt] = arm64_ftr_reg_ctrel0.sys_val; + regs->pc += 4; + } + ++static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs) ++{ ++ int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; ++ ++ if (rt != 31) ++ regs->regs[rt] = arch_counter_get_cntvct(); ++ regs->pc += 4; ++} ++ ++static void cntfrq_read_handler(unsigned int esr, struct pt_regs *regs) ++{ ++ int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; ++ ++ if (rt != 31) ++ regs->regs[rt] = read_sysreg(cntfrq_el0); ++ regs->pc += 4; ++} ++ + struct sys64_hook { + unsigned int esr_mask; + unsigned int esr_val; +@@ -510,6 +529,18 @@ static struct sys64_hook sys64_hooks[] = { + .esr_val = ESR_ELx_SYS64_ISS_SYS_CTR_READ, + .handler = ctr_read_handler, + }, ++ { ++ /* Trap read access to CNTVCT_EL0 */ ++ .esr_mask = ESR_ELx_SYS64_ISS_SYS_OP_MASK, ++ .esr_val = ESR_ELx_SYS64_ISS_SYS_CNTVCT, ++ .handler = cntvct_read_handler, ++ }, ++ { ++ /* Trap read access to CNTFRQ_EL0 */ ++ .esr_mask = ESR_ELx_SYS64_ISS_SYS_OP_MASK, ++ .esr_val = ESR_ELx_SYS64_ISS_SYS_CNTFRQ, ++ .handler = cntfrq_read_handler, ++ }, + {}, + }; + +@@ -523,7 +554,12 @@ asmlinkage void __exception do_sysinstr(unsigned int esr, struct pt_regs *regs) + return; + } + +- force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0); ++ /* ++ * New SYS instructions may previously have been undefined at EL0. Fall ++ * back to our usual undefined instruction handler so that we handle ++ * these consistently. ++ */ ++ do_undefinstr(regs); + } + + long compat_arm_syscall(struct pt_regs *regs); +diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S +index 58b5a90..c42ca88 100644 +--- a/arch/arm64/mm/cache.S ++++ b/arch/arm64/mm/cache.S +@@ -23,6 +23,78 @@ + #include + #include + #include ++/* ++ * __flush_dcache_all() ++ * ++ * Flush the whole D-cache. ++ * ++ * Corrupted registers: x0-x7, x9-x11 ++ */ ++__flush_dcache_all: ++ dmb sy // ensure ordering with previous memory accesses ++ mrs x0, clidr_el1 // read clidr ++ and x3, x0, #0x7000000 // extract loc from clidr ++ lsr x3, x3, #23 // left align loc bit field ++ cbz x3, finished // if loc is 0, then no need to clean ++ mov x10, #0 // start clean at cache level 0 ++loop1: ++ add x2, x10, x10, lsr #1 // work out 3x current cache level ++ lsr x1, x0, x2 // extract cache type bits from clidr ++ and x1, x1, #7 // mask of the bits for current cache only ++ cmp x1, #2 // see what cache we have at this level ++ b.lt skip // skip if no cache, or just i-cache ++ save_and_disable_irqs x9 // make CSSELR and CCSIDR access atomic ++ msr csselr_el1, x10 // select current cache level in csselr ++ isb // isb to sych the new cssr&csidr ++ mrs x1, ccsidr_el1 // read the new ccsidr ++ restore_irqs x9 ++ and x2, x1, #7 // extract the length of the cache lines ++ add x2, x2, #4 // add 4 (line length offset) ++ mov x4, #0x3ff ++ and x4, x4, x1, lsr #3 // find maximum number on the way size ++ clz w5, w4 // find bit position of way size increment ++ mov x7, #0x7fff ++ and x7, x7, x1, lsr #13 // extract max number of the index size ++loop2: ++ mov x9, x4 // create working copy of max way size ++loop3: ++ lsl x6, x9, x5 ++ orr x11, x10, x6 // factor way and cache number into x11 ++ lsl x6, x7, x2 ++ orr x11, x11, x6 // factor index number into x11 ++ dc cisw, x11 // clean & invalidate by set/way ++ subs x9, x9, #1 // decrement the way ++ b.ge loop3 ++ subs x7, x7, #1 // decrement the index ++ b.ge loop2 ++skip: ++ add x10, x10, #2 // increment cache number ++ cmp x3, x10 ++ b.gt loop1 ++finished: ++ mov x10, #0 // swith back to cache level 0 ++ msr csselr_el1, x10 // select current cache level in csselr ++ dsb sy ++ isb ++ ret ++ENDPROC(__flush_dcache_all) ++ ++/* ++ * flush_cache_all() ++ * ++ * Flush the entire cache system. The data cache flush is now achieved ++ * using atomic clean / invalidates working outwards from L1 cache. This ++ * is done using Set/Way based cache maintainance instructions. The ++ * instruction cache can still be invalidated back to the point of ++ * unification in a single instruction. ++ */ ++ENTRY(flush_cache_all) ++ mov x12, lr ++ bl __flush_dcache_all ++ mov x0, #0 ++ ic ialluis // I+BTB cache invalidate ++ ret x12 ++ENDPROC(flush_cache_all) + + /* + * flush_icache_range(start,end) +diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c +index 8377329..024db34 100644 +--- a/arch/arm64/mm/flush.c ++++ b/arch/arm64/mm/flush.c +@@ -91,4 +91,5 @@ EXPORT_SYMBOL(flush_dcache_page); + /* + * Additional functions defined in assembly. + */ ++EXPORT_SYMBOL(flush_cache_all); + EXPORT_SYMBOL(flush_icache_range); +diff --git a/drivers/Kconfig b/drivers/Kconfig +index e1e2066..0525868 100644 +--- a/drivers/Kconfig ++++ b/drivers/Kconfig +@@ -202,4 +202,7 @@ source "drivers/hwtracing/intel_th/Kconfig" + + source "drivers/fpga/Kconfig" + ++source "drivers/hidmac/Kconfig" ++ ++source "drivers/hisilicon/Kconfig" + endmenu +diff --git a/drivers/Makefile b/drivers/Makefile +index 733bf0b..7677007 100644 +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -174,3 +174,6 @@ obj-$(CONFIG_STM) += hwtracing/stm/ + obj-$(CONFIG_ANDROID) += android/ + obj-$(CONFIG_NVMEM) += nvmem/ + obj-$(CONFIG_FPGA) += fpga/ ++obj-$(CONFIG_HI_DMAC) += hidmac/ ++ ++obj-$(CONFIG_ARCH_HISI_BVT) += hisilicon/ +diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig +index 2c8be74..9154bc8 100644 +--- a/drivers/ata/Kconfig ++++ b/drivers/ata/Kconfig +@@ -2,6 +2,8 @@ + # SATA/PATA driver configuration + # + ++source "drivers/ata/Kconfig.hiahci" ++ + config HAVE_PATA_PLATFORM + bool + help +diff --git a/drivers/ata/Kconfig.hiahci b/drivers/ata/Kconfig.hiahci +new file mode 100644 +index 0000000..ceb0796 +--- /dev/null ++++ b/drivers/ata/Kconfig.hiahci +@@ -0,0 +1,44 @@ ++menuconfig HISI_SATA ++ bool "Hisilicon sata device support" ++ depends on (ARCH_HI3536DV100 || ARCH_HI3521A || ARCH_HI3531A) ++ default n ++ select ATA ++ select ATA_VERBOSE_ERROR ++ select SATA_PMP ++ select SATA_AHCI_PLATFORM ++ ++if HISI_SATA ++config HISI_SATA_IOBASE ++ hex "Hisi sata IO address" ++ default "0x10030000" if ARCH_HI3536DV100 ++ default "0x11010000" if (ARCH_HI3521A || ARCH_HI3531A) ++ help ++ hisilicon sata io base address. ++ ++config HISI_SATA_FBS ++ int "Hisi sata FIS-Based switching" ++ default 1 ++ range 0 1 ++ help ++ Hisatav200 supports FBS. ++ FBS is FIS-Based switching. ++ Choose y if you want to use it. ++ ++config HISI_SATA_NCQ ++ int "Hisi sata Native Command Queuing" ++ default 1 ++ range 0 1 ++ help ++ Hisatav200 supports NCQ. ++ NCQ is Native Command Queuing. ++ Choose y if you want to use it. ++ ++config HISI_ESATA ++ bool "Support Hisi eSATA" ++ default n ++ help ++ Hisatav200 supports eSATA. ++ Choose y if you want to use it. ++ ++endif ++ +diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile +index a46e6b7..40ee545 100644 +--- a/drivers/ata/Makefile ++++ b/drivers/ata/Makefile +@@ -1,5 +1,6 @@ + + obj-$(CONFIG_ATA) += libata.o ++obj-$(CONFIG_HISI_SATA) += hisi_sata_dbg.o + + # non-SFF interface + obj-$(CONFIG_SATA_AHCI) += ahci.o libahci.o +diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h +index 0cc08f8..4fe8dc3 100644 +--- a/drivers/ata/ahci.h ++++ b/drivers/ata/ahci.h +@@ -240,6 +240,9 @@ enum { + error-handling stage) */ + AHCI_HFLAG_NO_DEVSLP = (1 << 17), /* no device sleep */ + AHCI_HFLAG_NO_FBS = (1 << 18), /* no FBS */ ++#ifdef CONFIG_HISI_SATA ++ AHCI_HFLAG_NO_SXS = (1 << 19), /* do not support External SATA */ ++#endif + + #ifdef CONFIG_PCI_MSI + AHCI_HFLAG_MULTI_MSI = (1 << 20), /* per-port MSI(-X) */ +@@ -344,6 +347,13 @@ struct ahci_host_priv { + bool got_runtime_pm; /* Did we do pm_runtime_get? */ + struct clk *clks[AHCI_MAX_CLKS]; /* Optional */ + struct regulator **target_pwrs; /* Optional */ ++ ++#ifdef CONFIG_HISI_SATA ++#define PCI_AHCI 0 ++#define ORI_AHCI 1 ++ u32 type; ++#endif ++ + /* + * If platform uses PHYs. There is a 1:1 relation between the port number and + * the PHY position in this array. +diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c +index 62a04c8..42938b4 100644 +--- a/drivers/ata/ahci_platform.c ++++ b/drivers/ata/ahci_platform.c +@@ -26,6 +26,16 @@ + + #define DRV_NAME "ahci" + ++#ifdef CONFIG_HISI_SATA_NCQ ++static unsigned int ncq_en = CONFIG_HISI_SATA_NCQ; ++module_param(ncq_en, uint, 0600); ++MODULE_PARM_DESC(ncq_en, "ahci ncq flag (default:1)"); ++#endif ++ ++#ifdef CONFIG_HISI_SATA ++extern unsigned int sata_port_map; ++#endif ++ + static const struct ata_port_info ahci_port_info = { + .flags = AHCI_FLAG_COMMON, + .pio_mask = ATA_PIO4, +@@ -54,8 +64,21 @@ static int ahci_probe(struct platform_device *pdev) + of_property_read_u32(dev->of_node, + "ports-implemented", &hpriv->force_port_map); + ++#ifdef CONFIG_HISI_SATA ++ hpriv->type = ORI_AHCI; ++ hpriv->force_port_map = sata_port_map; ++#ifndef CONFIG_HISI_ESATA ++ hpriv->flags |= AHCI_HFLAG_NO_SXS; ++#endif ++ ++#ifdef CONFIG_HISI_SATA_NCQ ++ if (!ncq_en) ++ hpriv->flags |= AHCI_HFLAG_NO_NCQ; ++#endif ++#else + if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci")) + hpriv->flags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ; ++#endif + + rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info, + &ahci_platform_sht); +diff --git a/drivers/ata/hisi_sata_dbg.c b/drivers/ata/hisi_sata_dbg.c +new file mode 100644 +index 0000000..45efc6b +--- /dev/null ++++ b/drivers/ata/hisi_sata_dbg.c +@@ -0,0 +1,158 @@ ++#include ++#include ++#include ++#include ++#include ++#include "ahci.h" ++#include "hisi_sata_dbg.h" ++ ++void hisi_sata_mem_dump(unsigned int *addr, unsigned int size) ++{ ++ int ix; ++ ++ for (ix = 0; ix < size; ix += 0x04, addr++) { ++ if (!(ix & 0x0F)) ++ pr_debug("\n0x%08X: ", ++ (unsigned int)virt_to_phys(addr)); ++ pr_debug("%08X ", *addr); ++ } ++} ++EXPORT_SYMBOL(hisi_sata_mem_dump); ++ ++void hisi_sata_phys_mem_dump(unsigned int addr, unsigned int size) ++{ ++ hisi_sata_mem_dump(phys_to_virt(addr), size); ++} ++EXPORT_SYMBOL(hisi_sata_phys_mem_dump); ++ ++void hisi_ahci_reg_dump(void) ++{ ++ int ix; ++ unsigned int regbase; ++ ++ regbase = CONFIG_HISI_SATA_IOBASE; ++ pr_debug("AHCI GHC Register dump:"); ++ for (ix = 0; ix <= 0x28; ix += 0x04) { ++ if (!(ix & 0x0F)) ++ pr_debug("\n0x%08X: ", (regbase + ix)); ++ pr_debug("%08X ", readl(__io_address(regbase + ix))); ++ } ++ pr_debug("\n"); ++ ++ regbase = CONFIG_HISI_SATA_IOBASE + 0x0100; ++ pr_debug("AHCI PORT 0 Register dump:"); ++ for (ix = 0; ix <= 0x7F; ix += 0x04) { ++ if (!(ix & 0x0F)) ++ pr_debug("\n0x%08X: ", (regbase + ix)); ++ pr_debug("%08X ", readl(__io_address(regbase + ix))); ++ } ++ pr_debug("\n"); ++} ++EXPORT_SYMBOL(hisi_ahci_reg_dump); ++ ++void hisi_ahci_rx_fis_dump(struct ata_link *link, int pmp_port_num) ++{ ++ struct ahci_port_priv *pp = NULL; ++ ++ pp = link->ap->private_data; ++ if (NULL == pp) { ++ pr_debug("Error: pp=NULL\n"); ++ return; ++ } ++ pr_debug("ACHI Received FIS:"); ++ hisi_sata_phys_mem_dump((unsigned int)(pp->rx_fis_dma), ++ AHCI_RX_FIS_SZ * pmp_port_num); ++ pr_debug("\n"); ++} ++EXPORT_SYMBOL_GPL(hisi_ahci_rx_fis_dump); ++ ++void hisi_ata_taskfile_dump(struct ata_taskfile *tf) ++{ ++ if (NULL == tf) { ++ pr_debug("Error: tf=NULL\n"); ++ return; ++ } ++ ++ pr_debug("Taskfile dump:\n"); ++ pr_debug("flags:0x%08lX, protocol:0x%02X, command:0x%02X, device:0x%02X, ctl:0x%02X\n", ++ tf->flags, tf->protocol, tf->command, tf->device, tf->ctl); ++ pr_debug("feature:0x%08X, nsect:0x%02X, lbal:0x%02X, lbam:0x%02X, lbah:0x%02X\n", ++ tf->feature, tf->nsect, tf->lbal, tf->lbam, tf->lbah); ++ pr_debug("hob_feature:0x%08X, hob_nsect:0x%02X, hob_lbal:0x%02X, hob_lbam:0x%02X, hob_lbah:0x%02X\n", ++ tf->hob_feature, tf->hob_nsect, tf->hob_lbal, ++ tf->hob_lbam, tf->hob_lbah); ++} ++EXPORT_SYMBOL_GPL(hisi_ata_taskfile_dump); ++ ++static void __hisi_ahci_st_md(void __iomem *addr) ++{ ++ unsigned int *addr_v; ++ unsigned int *tmp; ++ unsigned int i; ++ ++ addr_v = (unsigned int *)addr; ++ ++ pr_debug("\n\n"); ++ for (i = 0; i < 16; i++) { ++ tmp = addr_v + i * 4; ++ pr_debug("%8x: %8x %8x %8x %8x\n", ++ (unsigned int)(addr + i * 16), ++ *tmp, *(tmp + 1), *(tmp + 2), *(tmp + 3)); ++ } ++ ++ pr_debug("\n"); ++} ++ ++void hisi_ahci_st_dump(void __iomem *port_base) ++{ ++ unsigned int tmp; ++ ++ pr_debug("\n**********Dmac status**********\n"); ++ tmp = readl(port_base + 0x58); ++ pr_debug("txdmac_curr_st:0x%2x\n", (tmp>>24) & 0xf); ++ tmp = readl(port_base + 0x64); ++ pr_debug("rxdmac_curr_st:0x%2x\n", (tmp>>24) & 0xf); ++ tmp = readl(port_base + 0x70); ++ pr_debug("dmac tx fifo:count-0x%x-empty-%x-ful-%x\n", ++ (tmp>>0) & 0xff, ++ (tmp>>16) & 0x1, (tmp>>17) & 0x1); ++ pr_debug("dmac rx fifo:count-0x%x-empty-%x-ful-%x\n", ++ (tmp>>8) & 0xff, ++ (tmp>>18) & 0x1, (tmp>>19) & 0x1); ++ ++ pr_debug("\n"); ++ pr_debug("**********HBA status**********\n"); ++ tmp = readl(port_base + 0x50); ++ pr_debug("pxxx_curr_st:0x%2x ndrx_curr_st:0x%2x\n", ++ (tmp>>24) & 0xf, ++ (tmp>>16) & 0xff); ++ pr_debug("cfis_curr_st:0x%2x piox_curr_st:0x%2x\n", ++ (tmp>>12) & 0xf, ++ (tmp>>8) & 0xf); ++ pr_debug("pmxx_curr_st:0x%2x errx_curr_st:0x%2x\n", ++ (tmp>>4) & 0xf, ++ (tmp>>0) & 0xf); ++ ++ pr_debug("\n"); ++ pr_debug("**********Link status**********\n"); ++ tmp = readl(port_base + 0x54); ++ pr_debug("link_curr_st:0x%2x\n", (tmp>>24) & 0x1f); ++ pr_debug("link tx fifo:count-0x%x-empty-%x-ful-%x\n", ++ (tmp>>0) & 0x1f, ++ (tmp>>5) & 0x1, (tmp>>6) & 0x1); ++ pr_debug("link rx fifo:count-0x%x-empty-%x-ful-%x\n", ++ (tmp>>8) & 0x1f, ++ (tmp>>13) & 0x1, (tmp>>14) & 0x1); ++ pr_debug("link df fifo:count-0x%x-empty-%x-ful-%x\n\n", ++ (tmp>>16) & 0x1f, ++ (tmp>>21) & 0x1, (tmp>>22) & 0x1); ++ ++ pr_debug("**********CMD header**********\n"); ++ tmp = readl(port_base + 0x0); ++ __hisi_ahci_st_md(phys_to_virt(tmp)); ++ __hisi_ahci_st_md(phys_to_virt(tmp+0x100)); ++ __hisi_ahci_st_md(phys_to_virt(tmp+0x200)); ++ __hisi_ahci_st_md(phys_to_virt(tmp+0x300)); ++} ++EXPORT_SYMBOL_GPL(hisi_ahci_st_dump); ++ +diff --git a/drivers/ata/hisi_sata_dbg.h b/drivers/ata/hisi_sata_dbg.h +new file mode 100644 +index 0000000..27b14fe +--- /dev/null ++++ b/drivers/ata/hisi_sata_dbg.h +@@ -0,0 +1,47 @@ ++ ++#ifndef _HISI_SATA_DBG_H ++#define _HISI_SATA_DBG_H ++#include ++#include ++#include ++#include "ahci.h" ++ ++ ++void hisi_sata_mem_dump(unsigned int *addr, unsigned int size); ++void hisi_sata_phys_mem_dump(unsigned int addr, unsigned int size); ++void hisi_ahci_rx_fis_dump(struct ata_link *link, int pmp_port_num); ++void hisi_ata_taskfile_dump(struct ata_taskfile *tf); ++void hisi_ahci_st_dump(void __iomem *port_base); ++void hisi_ahci_reg_dump(void); ++ ++#define HISI_AHCI_REG_DUMP(X) \ ++do {\ ++ pr_debug("------------------[ Start ]--------------------\n"); \ ++ pr_debug("Dump AHCI registers at %s %d\n", __func__, __LINE__); \ ++ hisi_ahci_reg_dump(); \ ++ pr_debug("------------------[ End ]--------------------\n");\ ++} while (0) ++ ++#define hisi_sata_readl(addr) do {\ ++ unsigned int reg = readl((unsigned int)addr); \ ++ pr_debug("HI_AHCI(REG) %s:%d: readl(0x%08X) = 0x%08X\n",\ ++ __func__, __LINE__, (unsigned int)addr, reg); \ ++ reg;\ ++ } while (0) ++ ++#define hisi_sata_writel(v, addr) do { writel(v, (unsigned int)addr); \ ++ pr_debug("HI_AHCI(REG) %s:%d: writel(0x%08X) = 0x%08X\n",\ ++ __func__, __LINE__, (unsigned int)addr, \ ++ (unsigned int)(v)); \ ++ } while (0) ++ ++#undef HISI_DUMP_AHCI_REG_OPS ++#ifdef HISI_DUMP_AHCI_REG_OPS ++#define readl(addr) hisi_sata_readl(addr) ++#define write(v, addr) hisi_sata_writel(v, addr) ++#endif ++ ++#endif /* _HISI_SATA_DBG_H */ ++ ++ ++ +diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c +index 0d028ea..1b0814a 100644 +--- a/drivers/ata/libahci.c ++++ b/drivers/ata/libahci.c +@@ -57,6 +57,30 @@ MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip) + module_param_named(ignore_sss, ahci_ignore_sss, int, 0444); + MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)"); + ++#ifdef CONFIG_HISI_SATA_FBS ++static int fbs_en = CONFIG_HISI_SATA_FBS; ++module_param(fbs_en, uint, 0600); ++MODULE_PARM_DESC(fbs_en, "ahci fbs flags (default:1)"); ++ ++#define AHCI_TIMEOUT_COUNT 10 ++#define AHCI_POLL_TIMER (20 * HZ) ++ ++struct ata_fbs_ctrl { ++ unsigned int fbs_enable_ctrl; /* fbs enable or disable control switch */ ++ unsigned int fbs_mode_ctrl; /* 1.5G: fbs disable, 3G/6G: fbs enable */ ++ unsigned int fbs_enable_flag; ++ unsigned int fbs_disable_flag; ++ unsigned int fbs_cmd_issue_flag; ++ struct timer_list poll_timer; ++}; ++static struct ata_fbs_ctrl fbs_ctrl[4]; ++extern void hisi_sata_set_fifoth(void *mmio); ++#endif ++#ifdef CONFIG_HISI_SATA ++extern void hisi_sata_reset_rxtx_assert(unsigned int port_no); ++extern void hisi_sata_reset_rxtx_deassert(unsigned int port_no); ++#endif ++ + static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, + unsigned hints); + static ssize_t ahci_led_show(struct ata_port *ap, char *buf); +@@ -503,6 +527,13 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv) + cap &= ~HOST_CAP_FBS; + } + ++#ifdef CONFIG_HISI_SATA ++ if ((cap & HOST_CAP_SXS) && (hpriv->flags & AHCI_HFLAG_NO_SXS)) { ++ dev_info(dev, "controller can't support eSATA, turning off CAP_SXS\n"); ++ cap &= ~HOST_CAP_SXS; ++ } ++#endif ++ + if (hpriv->force_port_map && port_map != hpriv->force_port_map) { + dev_info(dev, "forcing port_map 0x%x -> 0x%x\n", + port_map, hpriv->force_port_map); +@@ -1380,8 +1411,28 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, + bool fbs_disabled = false; + int rc; + ++#ifdef CONFIG_HISI_SATA_FBS ++ unsigned int port_num = ap->port_no; ++#endif ++ + DPRINTK("ENTER\n"); + ++#ifdef CONFIG_HISI_SATA_FBS ++ if (fbs_ctrl[port_num].fbs_enable_ctrl && ++ (link->pmp == SATA_PMP_CTRL_PORT) && ++ (hpriv->type == ORI_AHCI)) { ++ struct ahci_port_priv *pp = ap->private_data; ++ ++ if (pp->fbs_enabled == false) ++ ahci_enable_fbs(ap); ++ ++ fbs_ctrl[port_num].fbs_enable_flag = 0; ++ fbs_ctrl[port_num].fbs_disable_flag = 0; ++ fbs_ctrl[port_num].fbs_cmd_issue_flag = 0; ++ ++ } ++#endif ++ + /* prepare for SRST (AHCI-1.1 10.4.1) */ + rc = ahci_kick_engine(ap); + if (rc && rc != -EOPNOTSUPP) +@@ -1410,6 +1461,10 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, + AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY, msecs)) { + rc = -EIO; + reason = "1st FIS failed"; ++#ifdef CONFIG_HISI_SATA ++ hisi_sata_reset_rxtx_assert(ap->port_no); ++ hisi_sata_reset_rxtx_deassert(ap->port_no); ++#endif + goto fail; + } + +@@ -1599,6 +1654,68 @@ static int ahci_pmp_qc_defer(struct ata_queued_cmd *qc) + struct ata_port *ap = qc->ap; + struct ahci_port_priv *pp = ap->private_data; + ++#ifdef CONFIG_HISI_SATA_FBS ++ struct ahci_host_priv *hpriv = ap->host->private_data; ++ int is_atapi = ata_is_atapi(qc->tf.protocol); ++ void __iomem *port_mmio = ahci_port_base(ap); ++ unsigned int port_num = ap->port_no; ++ unsigned int cmd_timeout_count; ++ ++ if (fbs_ctrl[port_num].fbs_enable_ctrl && ++ (ap->link.pmp == SATA_PMP_CTRL_PORT) && ++ (hpriv->type == ORI_AHCI)) { ++ if (is_atapi || fbs_ctrl[ap->port_no].fbs_cmd_issue_flag) { ++ mod_timer(&fbs_ctrl[port_num].poll_timer, ++ jiffies + AHCI_POLL_TIMER); ++ ++ if (!fbs_ctrl[port_num].fbs_disable_flag) { ++ cmd_timeout_count = 0; ++ while (readl(port_mmio + PORT_SCR_ACT) ++ || readl(port_mmio ++ + PORT_CMD_ISSUE) ++ || readl(port_mmio ++ + PORT_IRQ_STAT)) { ++ cmd_timeout_count++; ++ if (cmd_timeout_count >= ++ AHCI_TIMEOUT_COUNT) { ++ fbs_ctrl[ap->port_no]. ++ fbs_cmd_issue_flag = 1; ++ return ATA_DEFER_LINK; ++ } ++ } ++ ++ if (pp->fbs_enabled == true) ++ ahci_disable_fbs(ap); ++ ++ ap->excl_link = NULL; ++ ap->nr_active_links = 0; ++ fbs_ctrl[port_num].fbs_disable_flag = 1; ++ fbs_ctrl[port_num].fbs_enable_flag = 0; ++ fbs_ctrl[ap->port_no].fbs_cmd_issue_flag = 0; ++ } ++ } else { ++ if (fbs_ctrl[port_num].fbs_enable_flag) { ++ cmd_timeout_count = 0; ++ while (readl(port_mmio + PORT_SCR_ACT) ++ || readl(port_mmio ++ + PORT_CMD_ISSUE) ++ || readl(port_mmio ++ + PORT_IRQ_STAT)) { ++ cmd_timeout_count++; ++ if (cmd_timeout_count >= ++ AHCI_TIMEOUT_COUNT) { ++ return ATA_DEFER_LINK; ++ } ++ } ++ ++ if (pp->fbs_enabled == false) ++ ahci_enable_fbs(ap); ++ fbs_ctrl[port_num].fbs_enable_flag = 0; ++ fbs_ctrl[port_num].fbs_disable_flag = 0; ++ } ++ } ++ } ++#endif + if (!sata_pmp_attached(ap) || pp->fbs_enabled) + return ata_std_qc_defer(qc); + else +@@ -1643,6 +1760,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) + ahci_fill_cmd_slot(pp, qc->tag, opts); + } + ++#ifndef CONFIG_HISI_SATA_FBS + static void ahci_fbs_dec_intr(struct ata_port *ap) + { + struct ahci_port_priv *pp = ap->private_data; +@@ -1666,6 +1784,7 @@ static void ahci_fbs_dec_intr(struct ata_port *ap) + if (fbs & PORT_FBS_DEC) + dev_err(ap->host->dev, "failed to clear device error\n"); + } ++#endif + + static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) + { +@@ -1773,7 +1892,9 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) + ata_port_freeze(ap); + else if (fbs_need_dec) { + ata_link_abort(link); ++#ifndef CONFIG_HISI_SATA_FBS + ahci_fbs_dec_intr(ap); ++#endif + } else + ata_port_abort(ap); + } +@@ -2170,7 +2291,9 @@ static void ahci_enable_fbs(struct ata_port *ap) + writel(fbs | PORT_FBS_EN, port_mmio + PORT_FBS); + fbs = readl(port_mmio + PORT_FBS); + if (fbs & PORT_FBS_EN) { ++#ifndef CONFIG_HISI_SATA_FBS + dev_info(ap->host->dev, "FBS is enabled\n"); ++#endif + pp->fbs_enabled = true; + pp->fbs_last_dev = -1; /* initialization */ + } else +@@ -2210,6 +2333,9 @@ static void ahci_disable_fbs(struct ata_port *ap) + } + + hpriv->start_engine(ap); ++#ifdef CONFIG_HISI_SATA_FBS ++ hisi_sata_set_fifoth(port_mmio); ++#endif + } + + static void ahci_pmp_attach(struct ata_port *ap) +@@ -2218,12 +2344,24 @@ static void ahci_pmp_attach(struct ata_port *ap) + struct ahci_port_priv *pp = ap->private_data; + u32 cmd; + ++#ifdef CONFIG_HISI_SATA_FBS ++ struct ahci_host_priv *hpriv = ap->host->private_data; ++ unsigned int port_num = ap->port_no; ++#endif ++ + cmd = readl(port_mmio + PORT_CMD); + cmd |= PORT_CMD_PMP; + writel(cmd, port_mmio + PORT_CMD); + + ahci_enable_fbs(ap); + ++#ifdef CONFIG_HISI_SATA_FBS ++ if (hpriv->type == ORI_AHCI) { ++ if (!fbs_ctrl[port_num].fbs_enable_ctrl) ++ ahci_disable_fbs(ap); ++ } ++#endif ++ + pp->intr_mask |= PORT_IRQ_BAD_PMP; + + /* +@@ -2292,6 +2430,19 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg) + } + #endif + ++#ifdef CONFIG_HISI_SATA_FBS ++static void ahci_poll_func(unsigned long arg) ++{ ++ struct ata_port *ap = (struct ata_port *)arg; ++ unsigned int port_num = ap->port_no; ++ ++ if (ap->link.pmp == SATA_PMP_CTRL_PORT) { ++ fbs_ctrl[port_num].fbs_enable_flag = 1; ++ fbs_ctrl[port_num].fbs_disable_flag = 0; ++ } ++} ++#endif ++ + static int ahci_port_start(struct ata_port *ap) + { + struct ahci_host_priv *hpriv = ap->host->private_data; +@@ -2385,6 +2536,20 @@ static int ahci_port_start(struct ata_port *ap) + + ap->private_data = pp; + ++#ifdef CONFIG_HISI_SATA_FBS ++ if (hpriv->type == ORI_AHCI) { ++ fbs_ctrl[ap->port_no].fbs_enable_ctrl = fbs_en; ++ fbs_ctrl[ap->port_no].fbs_enable_flag = 0; ++ fbs_ctrl[ap->port_no].fbs_disable_flag = 0; ++ fbs_ctrl[ap->port_no].fbs_cmd_issue_flag = 0; ++ ++ init_timer(&fbs_ctrl[ap->port_no].poll_timer); ++ fbs_ctrl[ap->port_no].poll_timer.function = ahci_poll_func; ++ fbs_ctrl[ap->port_no].poll_timer.data = (unsigned long)ap; ++ fbs_ctrl[ap->port_no].poll_timer.expires = jiffies + AHCI_POLL_TIMER; ++ } ++#endif ++ + /* engage engines, captain */ + return ahci_port_resume(ap); + } +diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c +index e167a1e1..1f2e3b7 100644 +--- a/drivers/base/dma-contiguous.c ++++ b/drivers/base/dma-contiguous.c +@@ -104,6 +104,11 @@ static inline __maybe_unused phys_addr_t cma_early_percent_memory(void) + * has been activated and all other subsystems have already allocated/reserved + * memory. + */ ++#ifdef CONFIG_ARCH_HISI_BVT ++#ifdef CONFIG_64BIT ++extern __init int hisi_declare_heap_memory(void); ++#endif ++#endif + void __init dma_contiguous_reserve(phys_addr_t limit) + { + phys_addr_t selected_size = 0; +@@ -140,6 +145,11 @@ void __init dma_contiguous_reserve(phys_addr_t limit) + &dma_contiguous_default_area, + fixed); + } ++#ifdef CONFIG_ARCH_HISI_BVT ++#ifdef CONFIG_64BIT ++ hisi_declare_heap_memory(); ++#endif ++#endif + } + + /** +@@ -195,6 +205,7 @@ struct page *dma_alloc_from_contiguous(struct device *dev, size_t count, + + return cma_alloc(dev_get_cma_area(dev), count, align); + } ++EXPORT_SYMBOL(dma_alloc_from_contiguous); + + /** + * dma_release_from_contiguous() - release allocated pages +@@ -211,6 +222,12 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages, + { + return cma_release(dev_get_cma_area(dev), pages, count); + } ++EXPORT_SYMBOL(dma_release_from_contiguous); ++ ++#ifdef CONFIG_ARM64 ++#include ++EXPORT_SYMBOL(__flush_dcache_area); ++#endif + + /* + * Support for reserved memory regions defined in device tree +diff --git a/drivers/char/mem.c b/drivers/char/mem.c +index 593a881..2b2d986 100644 +--- a/drivers/char/mem.c ++++ b/drivers/char/mem.c +@@ -376,6 +376,46 @@ static int mmap_mem(struct file *file, struct vm_area_struct *vma) + return 0; + } + ++static int mmap_venc(struct file *file, struct vm_area_struct *vma) ++{ ++ size_t size = (vma->vm_end - vma->vm_start)>>1; ++ ++ if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size)) ++ return -EINVAL; ++ ++ if (!private_mapping_ok(vma)) ++ return -ENOSYS; ++ ++ if (!range_is_allowed(vma->vm_pgoff, size)) ++ return -EPERM; ++ ++ if (!phys_mem_access_prot_allowed(file, vma->vm_pgoff, size, ++ &vma->vm_page_prot)) ++ return -EINVAL; ++ ++ vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, ++ size, ++ vma->vm_page_prot); ++ ++ vma->vm_ops = &mmap_mem_ops; ++ ++ /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */ ++ if (remap_pfn_range(vma, ++ vma->vm_start, ++ vma->vm_pgoff, ++ size, ++ vma->vm_page_prot)) ++ return -EAGAIN; ++ ++ if (remap_pfn_range(vma, ++ vma->vm_start + size, ++ vma->vm_pgoff, ++ size, ++ vma->vm_page_prot)) ++ return -EAGAIN; ++ ++ return 0; ++} + static int mmap_kmem(struct file *file, struct vm_area_struct *vma) + { + unsigned long pfn; +@@ -784,6 +824,17 @@ static const struct file_operations __maybe_unused mem_fops = { + #endif + }; + ++static const struct file_operations venc_fops = { ++ .llseek = memory_lseek, ++ .read = read_mem, ++ .write = write_mem, ++ .mmap = mmap_venc, ++ .open = open_mem, ++#ifndef CONFIG_MMU ++ .get_unmapped_area = get_unmapped_area_mem, ++#endif ++}; ++ + static const struct file_operations __maybe_unused kmem_fops = { + .llseek = memory_lseek, + .read = read_kmem, +@@ -853,6 +904,7 @@ static const struct memdev { + #ifdef CONFIG_PRINTK + [11] = { "kmsg", 0644, &kmsg_fops, 0 }, + #endif ++ [13] = { "vencmem", 0, &venc_fops, FMODE_UNSIGNED_OFFSET }, + }; + + static int memory_open(struct inode *inode, struct file *filp) +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 08d1dd5..0551cf5 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -812,7 +812,7 @@ static int crng_fast_load(const char *cp, size_t len) + if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) { + crng_init = 1; + wake_up_interruptible(&crng_init_wait); +- pr_notice("random: fast init done\n"); ++ printk_once("random: fast init done\n"); + } + spin_unlock_irqrestore(&primary_crng.lock, flags); + return 1; +@@ -850,7 +850,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r) + crng_init = 2; + process_random_ready_list(); + wake_up_interruptible(&crng_init_wait); +- pr_notice("random: crng init done\n"); ++ printk_once("random: crng init done\n"); + } + spin_unlock_irqrestore(&primary_crng.lock, flags); + } +@@ -1744,7 +1744,7 @@ urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) + + if (!crng_ready() && maxwarn > 0) { + maxwarn--; +- printk(KERN_NOTICE "random: %s: uninitialized urandom read " ++ 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 42042c0..0a0c6d9 100644 +--- a/drivers/clk/Makefile ++++ b/drivers/clk/Makefile +@@ -57,6 +57,7 @@ obj-y += bcm/ + obj-$(CONFIG_ARCH_BERLIN) += berlin/ + obj-$(CONFIG_H8300) += h8300/ + obj-$(CONFIG_ARCH_HISI) += hisilicon/ ++obj-$(CONFIG_ARCH_HISI_BVT) += hisilicon/ + obj-$(CONFIG_ARCH_MXC) += imx/ + obj-$(CONFIG_MACH_INGENIC) += ingenic/ + obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ +diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig +index 3f537a0..d261deb 100644 +--- a/drivers/clk/hisilicon/Kconfig ++++ b/drivers/clk/hisilicon/Kconfig +@@ -6,6 +6,54 @@ config COMMON_CLK_HI3519 + help + Build the clock driver for hi3519. + ++config COMMON_CLK_HI3516A ++ tristate "Hi3516A Clock Driver" ++ depends on ARCH_HI3516A || COMPILE_TEST ++ select RESET_HISI ++ default ARCH_HISI ++ help ++ Build the clock driver for hi3516A. ++ ++config COMMON_CLK_HI3518EV20X ++ tristate "Hi3518EV20X Clock Driver" ++ depends on ARCH_HI3518EV20X || COMPILE_TEST ++ select RESET_HISI ++ default ARCH_HISI_BVT ++ help ++ Build the clock driver for hi3516A. ++ ++config COMMON_CLK_HI3536DV100 ++ tristate "Hi3536DV100 Clock Driver" ++ depends on ARCH_HI3536DV100 || COMPILE_TEST ++ select RESET_HISI ++ default ARCH_HISI ++ help ++ Build the clock driver for hi3536DV100. ++ ++config COMMON_CLK_HI3559AV100 ++ tristate "Hi3559AV100 Clock Driver" ++ depends on ARCH_Hi3559AV100 || COMPILE_TEST ++ select RESET_HISI ++ default ARCH_HISI ++ help ++ Build the clock driver for hi3559av100. ++ ++config COMMON_CLK_HI3521A ++ tristate "Hi3521A Clock Driver" ++ depends on ARCH_HI3521A || COMPILE_TEST ++ select RESET_HISI ++ default ARCH_HISI_BVT ++ help ++ Build the clock driver for hi3521A. ++ ++config COMMON_CLK_HI3531A ++ tristate "Hi3531A Clock Driver" ++ depends on ARCH_HI3531A || COMPILE_TEST ++ select RESET_HISI ++ default ARCH_HISI_BVT ++ help ++ Build the clock driver for hi3531A. ++ + config COMMON_CLK_HI6220 + bool "Hi6220 Clock Driver" + depends on ARCH_HISI || COMPILE_TEST +@@ -15,7 +63,7 @@ config COMMON_CLK_HI6220 + + config RESET_HISI + bool "HiSilicon Reset Controller Driver" +- depends on ARCH_HISI || COMPILE_TEST ++ depends on ARCH_HISI || COMPILE_TEST || ARCH_HISI_BVT + select RESET_CONTROLLER + help + Build reset controller driver for HiSilicon device chipsets. +diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile +index e169ec7..6887c1e 100644 +--- a/drivers/clk/hisilicon/Makefile ++++ b/drivers/clk/hisilicon/Makefile +@@ -8,6 +8,12 @@ obj-$(CONFIG_ARCH_HI3xxx) += clk-hi3620.o + obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o + obj-$(CONFIG_ARCH_HIX5HD2) += clk-hix5hd2.o + obj-$(CONFIG_COMMON_CLK_HI3519) += clk-hi3519.o ++obj-$(CONFIG_COMMON_CLK_HI3516A) += clk-hi3516a.o ++obj-$(CONFIG_COMMON_CLK_HI3518EV20X) += clk-hi3518ev20x.o ++obj-$(CONFIG_COMMON_CLK_HI3536DV100) += clk-hi3536dv100.o ++obj-$(CONFIG_COMMON_CLK_HI3521A) += clk-hi3521a.o ++obj-$(CONFIG_COMMON_CLK_HI3531A) += clk-hi3531a.o + obj-$(CONFIG_COMMON_CLK_HI6220) += clk-hi6220.o ++obj-$(CONFIG_COMMON_CLK_HI3559AV100) += clk-hi3559av100.o + obj-$(CONFIG_RESET_HISI) += reset.o + obj-$(CONFIG_STUB_CLK_HI6220) += clk-hi6220-stub.o +diff --git a/drivers/clk/hisilicon/clk-hi3516a.c b/drivers/clk/hisilicon/clk-hi3516a.c +new file mode 100644 +index 0000000..cb70430 +--- /dev/null ++++ b/drivers/clk/hisilicon/clk-hi3516a.c +@@ -0,0 +1,463 @@ ++/* ++ * Hi3516A Clock Driver ++ * ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "clk.h" ++#include "crg.h" ++#include "reset.h" ++ ++struct hi3516a_pll_clock { ++ u32 id; ++ const char *name; ++ const char *parent_name; ++ u32 ctrl_reg1; ++ u8 frac_shift; ++ u8 frac_width; ++ u8 postdiv1_shift; ++ u8 postdiv1_width; ++ u8 postdiv2_shift; ++ u8 postdiv2_width; ++ u32 ctrl_reg2; ++ u8 fbdiv_shift; ++ u8 fbdiv_width; ++ u8 refdiv_shift; ++ u8 refdiv_width; ++}; ++ ++struct hi3516a_clk_pll { ++ struct clk_hw hw; ++ u32 id; ++ void __iomem *ctrl_reg1; ++ u8 frac_shift; ++ u8 frac_width; ++ u8 postdiv1_shift; ++ u8 postdiv1_width; ++ u8 postdiv2_shift; ++ u8 postdiv2_width; ++ void __iomem *ctrl_reg2; ++ u8 fbdiv_shift; ++ u8 fbdiv_width; ++ u8 refdiv_shift; ++ u8 refdiv_width; ++}; ++ ++static const struct ++hisi_fixed_rate_clock hi3516a_fixed_rate_clks_crg[] __initconst = { ++ { HI3516A_FIXED_3M, "3m", NULL, 0, 3000000, }, ++ { HI3516A_FIXED_6M, "6m", NULL, 0, 6000000, }, ++ { HI3516A_FIXED_13P5M, "13.5m", NULL, 0, 13500000, }, ++ { HI3516A_FIXED_24M, "24m", NULL, 0, 24000000, }, ++ { HI3516A_FIXED_25M, "25m", NULL, 0, 25000000, }, ++ { HI3516A_FIXED_27M, "27m", NULL, 0, 27000000, }, ++ { HI3516A_FIXED_37P125M, "37.125m", NULL, 0, 37125000, }, ++ { HI3516A_FIXED_50M, "50m", NULL, 0, 50000000, }, ++ { HI3516A_FIXED_74P25M, "74.25m", NULL, 0, 74250000, }, ++ { HI3516A_FIXED_75M, "75m", NULL, 0, 75000000, }, ++ { HI3516A_FIXED_99M, "99m", NULL, 0, 99000000, }, ++ { HI3516A_FIXED_100M, "100m", NULL, 0, 100000000, }, ++ { HI3516A_FIXED_125M, "125m", NULL, 0, 125000000, }, ++ { HI3516A_FIXED_145M, "145m", NULL, 0, 145000000, }, ++ { HI3516A_FIXED_148P5M, "148.5m", NULL, 0, 148500000, }, ++ { HI3516A_FIXED_150M, "150m", NULL, 0, 150000000, }, ++ { HI3516A_FIXED_194M, "194m", NULL, 0, 194000000, }, ++ { HI3516A_FIXED_198M, "198m", NULL, 0, 198000000, }, ++ { HI3516A_FIXED_200M, "200m", NULL, 0, 200000000, }, ++ { HI3516A_FIXED_229M, "229m", NULL, 0, 229000000, }, ++ { HI3516A_FIXED_237M, "237m", NULL, 0, 237000000, }, ++ { HI3516A_FIXED_242M, "242m", NULL, 0, 242000000, }, ++ { HI3516A_FIXED_250M, "250m", NULL, 0, 250000000, }, ++ { HI3516A_FIXED_297M, "297m", NULL, 0, 297000000, }, ++ { HI3516A_FIXED_300M, "300m", NULL, 0, 300000000, }, ++ { HI3516A_FIXED_333M, "333m", NULL, 0, 333000000, }, ++ { HI3516A_FIXED_400M, "400m", NULL, 0, 400000000, }, ++ { HI3516A_FIXED_500M, "500m", NULL, 0, 500000000, }, ++ { HI3516A_FIXED_594M, "594m", NULL, 0, 594000000, }, ++ { HI3516A_FIXED_600M, "600m", NULL, 0, 600000000, }, ++ { HI3516A_FIXED_726P25M, "725.25m", NULL, 0, 726250000, }, ++ { HI3516A_FIXED_750M, "750m", NULL, 0, 750000000, }, ++ { HI3516A_FIXED_900M, "900m", NULL, 0, 900000000, }, ++ { HI3516A_FIXED_1000M, "1000m", NULL, 0, 1000000000UL, }, ++ { HI3516A_FIXED_1188M, "1188m", NULL, 0, 1188000000UL, }, ++}; ++ ++static const char *const sysaxi_mux_p[] __initconst = {"198m", "148.5m"}; ++static const char *const uart_mux_p[] __initconst = {"clk_sysapb", "6m"}; ++static const char *const snor_mux_p[] __initconst = {"24m", "75m", "125m"}; ++static const char *const snand_mux_p[] __initconst = {"24m", "75m", "125m"}; ++static const char *const nand_mux_p[] __initconst = {"24m", "198m"}; ++static const char *const eth_phy_mux_p[] __initconst = {"50m", "25m"}; ++static const char *const a7_mux_p[] __initconst = {"400m", "500m", "apll"}; ++static const char *const mmc_mux_p[] __initconst = {"50m", "100m", "25m", "75m"}; ++ ++static u32 sysaxi_mux_table[] __initdata = {0, 1}; ++static u32 uart_mux_table[] __initdata = {0, 1}; ++static u32 snor_mux_table[] __initdata = {0, 1, 2}; ++static u32 snand_mux_table[] __initdata = {0, 1, 2}; ++static u32 nand_mux_table[] __initdata = {0, 1}; ++static u32 eth_phy_mux_table[] __initdata = {0, 1}; ++static u32 a7_mux_table[] __initdata = {2, 1, 0}; ++static u32 mmc_mux_table[] __initdata = {0, 1, 2, 3}; ++ ++static const struct hisi_mux_clock hi3516a_mux_clks_crg[] __initconst = { ++ { HI3516A_SYSAXI_CLK, "sysaxi_mux", sysaxi_mux_p, ++ ARRAY_SIZE(sysaxi_mux_p), ++ CLK_SET_RATE_PARENT, 0x30, 3, 1, 0, sysaxi_mux_table, }, ++ { HI3516A_SNOR_MUX, "snor_mux", snor_mux_p, ARRAY_SIZE(snor_mux_p), ++ CLK_SET_RATE_PARENT, 0xc0, 2, 2, 0, snor_mux_table, }, ++ { HI3516A_SNAND_MUX, "snand_mux", snand_mux_p, ARRAY_SIZE(snand_mux_p), ++ CLK_SET_RATE_PARENT, 0xc0, 6, 2, 0, snand_mux_table, }, ++ { HI3516A_NAND_MUX, "nand_mux", nand_mux_p, ARRAY_SIZE(nand_mux_p), ++ CLK_SET_RATE_PARENT, 0xd0, 2, 1, 0, nand_mux_table, }, ++ { HI3516A_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 2, 2, 0, mmc_mux_table, }, ++ { HI3516A_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 10, 2, 0, mmc_mux_table, }, ++ { HI3516A_UART_MUX, "uart_mux", uart_mux_p, ++ ARRAY_SIZE(uart_mux_p), ++ CLK_SET_RATE_PARENT, 0xe4, 19, 1, 0, uart_mux_table, }, ++ { HI3516A_ETH_PHY_MUX, "eth_phy_mux", eth_phy_mux_p, ++ ARRAY_SIZE(eth_phy_mux_p), CLK_SET_RATE_PARENT, ++ 0xcc, 6, 1, 0, eth_phy_mux_table, }, ++ { HI3516A_A7_MUX, "a7_mux", a7_mux_p, ARRAY_SIZE(a7_mux_p), ++ CLK_SET_RATE_PARENT, 0x30, 8, 2, 0, a7_mux_table, }, ++}; ++ ++/* fixed factor clocks */ ++static struct hisi_fixed_factor_clock ++ hi3516a_fixed_factor_clks[] __initdata = { ++ { HI3516A_SYSAXI_CLK, "clk_sysapb", "sysaxi_mux", 1, 4, ++ CLK_SET_RATE_PARENT, }, ++}; ++ ++static const struct hisi_gate_clock hi3516a_gate_clks[] __initconst = { ++ /* spi nor */ ++ { HI3516A_SNOR_CLK, "clk_snor", "snor_mux", ++ CLK_SET_RATE_PARENT, 0xc0, 1, 0, }, ++ /* spi nand */ ++ { HI3516A_SNAND_CLK, "clk_snand", "snand_mux", ++ CLK_SET_RATE_PARENT, 0xc0, 5, 0, }, ++ /* nand */ ++ { HI3516A_NAND_CLK, "clk_nand", "nand_mux", ++ CLK_SET_RATE_PARENT, 0xd8, 1, 0, }, ++ /* mmc */ ++ { HI3516A_MMC0_CLK, "clk_mmc0", "mmc0_mux", ++ CLK_SET_RATE_PARENT, 0xc4, 1, 0, }, ++ { HI3516A_MMC1_CLK, "clk_mmc1", "mmc1_mux", ++ CLK_SET_RATE_PARENT, 0xc4, 9, 0, }, ++ ++ /* usb ctrl */ ++ { HI3516A_USB2_CTRL_UTMI0_REQ, "usb2_cttl_utmi0_req", NULL, ++ CLK_SET_RATE_PARENT, 0xb4, 5, 1, }, ++ { HI3516A_USB2_HRST_REQ, "usb2_hrst_req", NULL, ++ CLK_SET_RATE_PARENT, 0xb4, 0, 1, }, ++ ++ /* uart */ ++ { HI3516A_UART0_CLK, "clk_uart0", "50m", ++ CLK_SET_RATE_PARENT, 0xe4, 15, 0, }, ++ { HI3516A_UART1_CLK, "clk_uart1", "50m", ++ CLK_SET_RATE_PARENT, 0xe4, 16, 0, }, ++ { HI3516A_UART2_CLK, "clk_uart2", "50m", ++ CLK_SET_RATE_PARENT, 0xe4, 17, 0, }, ++ { HI3516A_UART3_CLK, "clk_uart3", "50m", ++ CLK_SET_RATE_PARENT, 0xe4, 18, 0, }, ++ /* ethernet mac */ ++ { HI3516A_ETH_CLK, "clk_eth", NULL, ++ CLK_SET_RATE_PARENT, 0xcc, 1, 0, }, ++ { HI3516A_ETH_MACIF_CLK, "clk_eth_macif", NULL, ++ CLK_SET_RATE_PARENT, 0xcc, 3, 0, }, ++ /* spi */ ++ { HI3516A_SPI0_CLK, "clk_spi0", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 13, 0, }, ++ { HI3516A_SPI1_CLK, "clk_spi1", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 14, 0, }, ++ /* dmac */ ++ { HI3516A_DMAC_CLK, "clk_dmac", "50m", ++ CLK_SET_RATE_PARENT, 0xd8, 5, 0, }, ++}; ++ ++static struct hi3516a_pll_clock hi3516a_pll_clks[] __initdata = { ++ { HI3516A_APLL_CLK, "apll", NULL, 0x0, 0, 24, 24, 3, 28, 3, ++ 0x4, 0, 12, 12, 6}, ++}; ++ ++#define to_pll_clk(_hw) container_of(_hw, struct hi3516a_clk_pll, hw) ++ ++static void __init hi3516a_calc_pll(u32 *frac_val, u32 *postdiv1_val, u32 *postdiv2_val, ++ u32 *fbdiv_val, u32 *refdiv_val, u64 rate) ++{ ++ u64 rem; ++ *frac_val = 0; ++ rem = do_div(rate, 1000000); ++ *fbdiv_val = rate; ++ *refdiv_val = 24; ++ rem = rem * (1 << 24); ++ do_div(rem, 1000000); ++ *frac_val = rem; ++} ++ ++static int __init clk_pll_set_rate(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct hi3516a_clk_pll *clk = to_pll_clk(hw); ++ u32 frac_val, postdiv1_val, postdiv2_val, fbdiv_val, refdiv_val; ++ u32 val; ++ ++ /*Fixme ignore postdives now because apll don't use them*/ ++ postdiv1_val = postdiv2_val = 0; ++ ++ hi3516a_calc_pll(&frac_val, &postdiv1_val, &postdiv2_val, ++ &fbdiv_val, &refdiv_val, (u64)rate); ++ ++ val = readl_relaxed(clk->ctrl_reg1); ++ val &= ~(((1 << clk->frac_width) - 1) << clk->frac_shift); ++ val &= ~(((1 << clk->postdiv1_width) - 1) << clk->postdiv1_shift); ++ val &= ~(((1 << clk->postdiv2_width) - 1) << clk->postdiv2_shift); ++ ++ val |= frac_val << clk->frac_shift; ++ val |= postdiv1_val << clk->postdiv1_shift; ++ val |= postdiv2_val << clk->postdiv2_shift; ++ writel_relaxed(val, clk->ctrl_reg1); ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val &= ~(((1 << clk->fbdiv_width) - 1) << clk->fbdiv_shift); ++ val &= ~(((1 << clk->refdiv_width) - 1) << clk->refdiv_shift); ++ ++ val |= fbdiv_val << clk->fbdiv_shift; ++ val |= refdiv_val << clk->refdiv_shift; ++ writel_relaxed(val, clk->ctrl_reg2); ++ ++ return 0; ++} ++ ++static unsigned long __init clk_pll_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct hi3516a_clk_pll *clk = to_pll_clk(hw); ++ u64 frac_val, fbdiv_val, refdiv_val; ++ u32 val; ++ u64 tmp, rate; ++ ++ val = readl_relaxed(clk->ctrl_reg1); ++ val = val >> clk->frac_shift; ++ val &= ((1 << clk->frac_width) - 1); ++ frac_val = val; ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val = val >> clk->fbdiv_shift; ++ val &= ((1 << clk->fbdiv_width) - 1); ++ fbdiv_val = val; ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val = val >> clk->refdiv_shift; ++ val &= ((1 << clk->refdiv_width) - 1) ; ++ refdiv_val = val; ++ ++ /* rate = 24000000 * (fbdiv + frac / (1<<24) ) / refdiv */ ++ rate = 0; ++ tmp = 24000000 * fbdiv_val; ++ rate += tmp; ++ do_div(rate, refdiv_val); ++ ++ return rate; ++} ++ ++static int __init clk_pll_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ return req->rate; ++} ++ ++static struct clk_ops clk_pll_ops __initdata = { ++ .set_rate = clk_pll_set_rate, ++ .determine_rate = clk_pll_determine_rate, ++ .recalc_rate = clk_pll_recalc_rate, ++}; ++ ++static int __init hi3516a_clk_register_pll(struct hi3516a_pll_clock *clks, ++ int nums, struct hisi_clock_data *data) ++{ ++ void __iomem *base = data->base; ++ int i; ++ ++ for (i = 0; i < nums; i++) { ++ struct hi3516a_clk_pll *p_clk; ++ struct clk *clk; ++ struct clk_init_data init; ++ ++ p_clk = kzalloc(sizeof(*p_clk), GFP_KERNEL); ++ if (!p_clk) ++ return -1; ++ ++ init.name = clks[i].name; ++ init.flags = CLK_IS_BASIC; ++ init.parent_names = ++ (clks[i].parent_name ? &clks[i].parent_name : NULL); ++ init.num_parents = (clks[i].parent_name ? 1 : 0); ++ init.ops = &clk_pll_ops; ++ ++ p_clk->ctrl_reg1 = base + clks[i].ctrl_reg1; ++ p_clk->frac_shift = clks[i].frac_shift; ++ p_clk->frac_width = clks[i].frac_width; ++ p_clk->postdiv1_shift = clks[i].postdiv1_shift; ++ p_clk->postdiv1_width = clks[i].postdiv1_width; ++ p_clk->postdiv2_shift = clks[i].postdiv2_shift; ++ p_clk->postdiv2_width = clks[i].postdiv2_width; ++ ++ p_clk->ctrl_reg2 = base + clks[i].ctrl_reg2; ++ p_clk->fbdiv_shift = clks[i].fbdiv_shift; ++ p_clk->fbdiv_width = clks[i].fbdiv_width; ++ p_clk->refdiv_shift = clks[i].refdiv_shift; ++ p_clk->refdiv_width = clks[i].refdiv_width; ++ p_clk->hw.init = &init; ++ ++ clk = clk_register(NULL, &p_clk->hw); ++ if (IS_ERR(clk)) { ++ kfree(p_clk); ++ pr_err("%s: failed to register clock %s\n", ++ __func__, clks[i].name); ++ continue; ++ } ++ ++ data->clk_data.clks[clks[i].id] = clk; ++ } ++ ++ return 0; ++} ++ ++static void __init hi3516a_clk_crg_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ unsigned int count = 0; ++ int ret; ++ ++ clk_data = hisi_clk_init(np, HI3516A_CRG_NR_CLKS); ++ if (!clk_data) { ++ pr_err("%s: failed to allocate CRG clock data\n", __func__); ++ return; ++ } ++ ++ ret = hisi_clk_register_fixed_rate(hi3516a_fixed_rate_clks_crg, ++ ARRAY_SIZE(hi3516a_fixed_rate_clks_crg), clk_data); ++ if (ret) ++ goto err; ++ ++ ret = hi3516a_clk_register_pll(hi3516a_pll_clks, ++ ARRAY_SIZE(hi3516a_pll_clks), clk_data); ++ if (ret) ++ goto unregister_fixed_rate; ++ ++ ret = hisi_clk_register_mux(hi3516a_mux_clks_crg, ++ ARRAY_SIZE(hi3516a_mux_clks_crg), clk_data); ++ if (ret) ++ goto unregister_fixed_rate; ++ ++ ret = hisi_clk_register_fixed_factor(hi3516a_fixed_factor_clks, ++ ARRAY_SIZE(hi3516a_fixed_factor_clks), clk_data); ++ if (ret) ++ goto unregister_mux; ++ ++ ret = hisi_clk_register_gate(hi3516a_gate_clks, ++ ARRAY_SIZE(hi3516a_gate_clks), clk_data); ++ if (ret) ++ goto unregister_factor; ++ ++ ret = of_clk_add_provider(np, ++ of_clk_src_onecell_get, &clk_data->clk_data); ++ if (ret) ++ goto unregister_gate; ++ ++ if (!of_property_read_u32(np, "#reset-cells", &count) && (count == 2)) ++ if (hibvt_reset_init(np, HI3516A_CRG_NR_RSTS)) ++ goto err; ++ ++ return; ++ ++unregister_gate: ++ hisi_clk_unregister_gate(hi3516a_gate_clks, ++ ARRAY_SIZE(hi3516a_gate_clks), clk_data); ++unregister_factor: ++ hisi_clk_unregister_fixed_factor(hi3516a_fixed_factor_clks, ++ ARRAY_SIZE(hi3516a_fixed_factor_clks), clk_data); ++unregister_mux: ++ hisi_clk_unregister_mux(hi3516a_mux_clks_crg, ++ ARRAY_SIZE(hi3516a_mux_clks_crg), clk_data); ++unregister_fixed_rate: ++ hisi_clk_unregister_fixed_rate(hi3516a_fixed_rate_clks_crg, ++ ARRAY_SIZE(hi3516a_fixed_rate_clks_crg), clk_data); ++err: ++ pr_err("%s: failed to init CRG clock\n", __func__); ++ return; ++} ++CLK_OF_DECLARE(hi3516a_clk_crg, "hisilicon,hi3516a-clock", ++ hi3516a_clk_crg_init); ++ ++/* clock in system control */ ++static const char *const timer_mux_p[] __initconst = {"3m", "clk_sysapb"}; ++static u32 timer_mux_table[] __initdata = {0, 1}; ++ ++static const struct hisi_mux_clock hi3516a_mux_clks_sc_clk[] __initconst = { ++ { HI3516A_TIME0_0_CLK, "timer00", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 16, 1, 0, timer_mux_table, }, ++ ++ { HI3516A_TIME0_1_CLK, "timer01", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 18, 1, 0, timer_mux_table, }, ++ ++ { HI3516A_TIME1_2_CLK, "timer12", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 20, 1, 0, timer_mux_table, }, ++ ++ { HI3516A_TIME1_3_CLK, "timer13", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 22, 1, 0, timer_mux_table, }, ++}; ++ ++static void __init hi3516a_sc_clk_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ int ret; ++ ++ clk_data = hisi_clk_init(np, HI3516A_SYS_NR_CLKS); ++ if (!clk_data) { ++ pr_err("%s: failed to allocate %s clock data\n", ++ __func__, np->name); ++ return; ++ } ++ ++ ret = hisi_clk_register_mux(hi3516a_mux_clks_sc_clk, ++ ARRAY_SIZE(hi3516a_mux_clks_sc_clk), clk_data); ++ if (ret) { ++ pr_err("%s: failed to register %s mux clock\n", ++ __func__, np->name); ++ return; ++ } ++} ++ ++CLK_OF_DECLARE(hi3516a_clk_sysctrl, "hisilicon,hi3516a-sysctrl", ++ hi3516a_sc_clk_init); ++ +diff --git a/drivers/clk/hisilicon/clk-hi3518ev20x.c b/drivers/clk/hisilicon/clk-hi3518ev20x.c +new file mode 100644 +index 0000000..b0f1ac6 +--- /dev/null ++++ b/drivers/clk/hisilicon/clk-hi3518ev20x.c +@@ -0,0 +1,245 @@ ++/* ++ * Hi3518ev20x Clock Driver ++ * ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "clk.h" ++#include "crg.h" ++#include "reset.h" ++ ++static const struct ++hisi_fixed_rate_clock hi3518ev20x_fixed_rate_clks_crg[] __initconst = { ++ { HI3518EV20X_FIXED_3M, "3m", NULL, 0, 3000000, }, ++ { HI3518EV20X_FIXED_6M, "6m", NULL, 0, 6000000, }, ++ { HI3518EV20X_FIXED_24M, "24m", NULL, 0, 24000000, }, ++ { HI3518EV20X_FIXED_25M, "25m", NULL, 0, 25000000, }, ++ { HI3518EV20X_FIXED_27M, "27m", NULL, 0, 27000000, }, ++ { HI3518EV20X_FIXED_37P125M, "37.125m", NULL, 0, 37125000, }, ++ { HI3518EV20X_FIXED_49P5M, "49.5m", NULL, 0, 49500000, }, ++ { HI3518EV20X_FIXED_50M, "50m", NULL, 0, 50000000, }, ++ { HI3518EV20X_FIXED_54M, "54m", NULL, 0, 54000000, }, ++ { HI3518EV20X_FIXED_74P25M, "74.25m", NULL, 0, 74250000, }, ++ { HI3518EV20X_FIXED_99M, "99m", NULL, 0, 99000000, }, ++ { HI3518EV20X_FIXED_125M, "125m", NULL, 0, 125000000, }, ++ { HI3518EV20X_FIXED_148P5M, "148.5m", NULL, 0, 148500000, }, ++ { HI3518EV20X_FIXED_198M, "198m", NULL, 0, 198000000, }, ++ { HI3518EV20X_FIXED_200M, "200m", NULL, 0, 200000000, }, ++ { HI3518EV20X_FIXED_250M, "250m", NULL, 0, 250000000, }, ++ { HI3518EV20X_FIXED_297M, "297m", NULL, 0, 297000000, }, ++ { HI3518EV20X_FIXED_300M, "300m", NULL, 0, 300000000, }, ++ { HI3518EV20X_FIXED_396M, "396m", NULL, 0, 396000000, }, ++ { HI3518EV20X_FIXED_540M, "540m", NULL, 0, 540000000, }, ++ { HI3518EV20X_FIXED_594M, "594m", NULL, 0, 594000000, }, ++ { HI3518EV20X_FIXED_600M, "600m", NULL, 0, 600000000, }, ++ { HI3518EV20X_FIXED_650M, "660m", NULL, 0, 660000000, }, ++ { HI3518EV20X_FIXED_750M, "750m", NULL, 0, 750000000, }, ++ { HI3518EV20X_FIXED_1188M, "1188m", NULL, 0, 1188000000UL, }, ++}; ++ ++static const char *const sysapb_mux_p[] __initconst = {"24m", "198m"}; ++static const char *const uart_mux_p[] __initconst = {"clk_sysapb", "24m", "6m"}; ++static const char *const fmc_mux_p[] __initconst = {"24m", "148.5m", "125m", "198m"}; ++static const char *const eth_mux_p[] __initconst = {"99m", "54m"}; ++static const char *const mmc0_mux_p[] __initconst = {"99m", "74.25m", "49.5m", "148.5m"}; ++static const char *const mmc1_mux_p[] __initconst = {"49.5m"}; ++ ++static u32 sysapb_mux_table[] = {0, 1}; ++static u32 uart_mux_table[] = {0, 1, 2}; ++static u32 fmc_mux_table[] = {0, 1, 2, 3}; ++static u32 eth_mux_table[] = {0, 1}; ++static u32 mmc0_mux_table[] = {0, 1, 2, 3}; ++static u32 mmc1_mux_table[] = {0}; ++ ++static const struct hisi_mux_clock hi3518ev20x_mux_clks_crg[] __initconst = { ++ { HI3518EV20X_SYSAPB_CLK, "sysapb_mux", sysapb_mux_p, ++ ARRAY_SIZE(sysapb_mux_p), ++ CLK_SET_RATE_PARENT, 0x30, 0, 1, 0, sysapb_mux_table, }, ++ { HI3518EV20X_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc0, 2, 2, 0, fmc_mux_table, }, ++ { HI3518EV20X_UART_MUX, "uart_mux", uart_mux_p, ++ ARRAY_SIZE(uart_mux_p), ++ CLK_SET_RATE_PARENT, 0xe4, 19, 1, 0, uart_mux_table, }, ++ /* ethernet clock select */ ++ { HI3518EV20X_ETH_MUX, "eth_mux", eth_mux_p, ARRAY_SIZE(eth_mux_p), ++ CLK_SET_RATE_PARENT, 0xec, 7, 0, 0, eth_mux_table, }, ++ /* MMC0 clock select */ ++ { HI3518EV20X_MMC0_MUX, "mmc0_mux", mmc0_mux_p, ARRAY_SIZE(mmc0_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 10, 2, 0, mmc0_mux_table, }, ++ /* MMC1 clock select */ ++ { HI3518EV20X_MMC1_MUX, "mmc1_mux", mmc1_mux_p, ARRAY_SIZE(mmc1_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 2, 2, 0, mmc1_mux_table, }, ++}; ++ ++/* fixed factor clocks */ ++static struct hisi_fixed_factor_clock ++ hi3518ev20x_fixed_factor_clks[] __initdata = { ++ { HI3518EV20X_SYSAPB_CLK, "sysapb", "sysapb_mux", 1, 4, ++ CLK_SET_RATE_PARENT, }, ++}; ++ ++static const struct hisi_gate_clock hi3518ev20x_gate_clks[] __initconst = { ++ /* fmc */ ++ { HI3518EV20X_FMC_CLK, "clk_fmc", "fmc_mux", ++ CLK_SET_RATE_PARENT, 0xc0, 1, 0, }, ++ ++ /* usb ctrl */ ++ { HI3518EV20X_USB2_CTRL_UTMI0_REQ, "usb2_cttl_utmi0_req", NULL, ++ CLK_SET_RATE_PARENT, 0xb4, 5, 1, }, ++ { HI3518EV20X_USB2_HRST_REQ, "usb2_hrst_req", NULL, ++ CLK_SET_RATE_PARENT, 0xb4, 0, 1, }, ++ ++ /* uart */ ++ { HI3518EV20X_UART0_CLK, "clk_uart0", "uart_mux", ++ CLK_SET_RATE_PARENT, 0xe4, 15, 0, }, ++ { HI3518EV20X_UART1_CLK, "clk_uart1", "uart_mux", ++ CLK_SET_RATE_PARENT, 0xe4, 16, 0, }, ++ { HI3518EV20X_UART2_CLK, "clk_uart2", "uart_mux", ++ CLK_SET_RATE_PARENT, 0xe4, 17, 0, }, ++ /* ethernet */ ++ { HI3518EV20X_ETH_CLK, "clk_eth", "eth_mux", ++ CLK_SET_RATE_PARENT, 0xec, 1, 0, }, ++ /* mmc0 */ ++ { HI3518EV20X_MMC0_CLK, "clk_mmc0", "mmc0_mux", ++ CLK_SET_RATE_PARENT, 0xc4, 9, 0, }, ++ /* mmc1 */ ++ { HI3518EV20X_MMC1_CLK, "clk_mmc1", "mmc1_mux", ++ CLK_SET_RATE_PARENT, 0xc4, 1, 0, }, ++ /* spi */ ++ { HI3518EV20X_SPI0_CLK, "clk_spi0", "sysapb_mux", ++ CLK_SET_RATE_PARENT, 0xe4, 13, 0, }, ++ { HI3518EV20X_SPI1_CLK, "clk_spi1", "sysapb_mux", ++ CLK_SET_RATE_PARENT, 0xe4, 14, 0, }, ++ /* dmac */ ++ { HI3518EV20X_DMAC_CLK, "clk_dmac", "50m", ++ CLK_SET_RATE_PARENT, 0xd8, 5, 0, }, ++}; ++ ++static void __init hi3518ev20x_clk_crg_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ unsigned int count = 0; ++ int ret; ++ ++ clk_data = hisi_clk_init(np, HI3518EV20X_CRG_NR_CLKS); ++ if (!clk_data) { ++ pr_err("%s: failed to allocate CRG clock data\n", __func__); ++ return; ++ } ++ ++ ret = hisi_clk_register_fixed_rate(hi3518ev20x_fixed_rate_clks_crg, ++ ARRAY_SIZE(hi3518ev20x_fixed_rate_clks_crg), clk_data); ++ if (ret) ++ goto err; ++ ++ ret = hisi_clk_register_mux(hi3518ev20x_mux_clks_crg, ++ ARRAY_SIZE(hi3518ev20x_mux_clks_crg), clk_data); ++ if (ret) ++ goto unregister_fixed_rate; ++ ++ ret = hisi_clk_register_fixed_factor(hi3518ev20x_fixed_factor_clks, ++ ARRAY_SIZE(hi3518ev20x_fixed_factor_clks), clk_data); ++ if (ret) ++ goto unregister_mux; ++ ++ ret = hisi_clk_register_gate(hi3518ev20x_gate_clks, ++ ARRAY_SIZE(hi3518ev20x_gate_clks), clk_data); ++ if (ret) ++ goto unregister_factor; ++ ++ ret = of_clk_add_provider(np, ++ of_clk_src_onecell_get, &clk_data->clk_data); ++ if (ret) ++ goto unregister_gate; ++ ++ if (!of_property_read_u32(np, "#reset-cells", &count) && (count == 2)) ++ if (hibvt_reset_init(np, HI3518EV20X_CRG_NR_RSTS)) ++ goto err; ++ ++ return; ++ ++unregister_gate: ++ hisi_clk_unregister_gate(hi3518ev20x_gate_clks, ++ ARRAY_SIZE(hi3518ev20x_gate_clks), clk_data); ++unregister_factor: ++ hisi_clk_unregister_fixed_factor(hi3518ev20x_fixed_factor_clks, ++ ARRAY_SIZE(hi3518ev20x_fixed_factor_clks), clk_data); ++unregister_mux: ++ hisi_clk_unregister_mux(hi3518ev20x_mux_clks_crg, ++ ARRAY_SIZE(hi3518ev20x_mux_clks_crg), clk_data); ++unregister_fixed_rate: ++ hisi_clk_unregister_fixed_rate(hi3518ev20x_fixed_rate_clks_crg, ++ ARRAY_SIZE(hi3518ev20x_fixed_rate_clks_crg), clk_data); ++err: ++ pr_err("%s: failed to init CRG clock\n", __func__); ++ return; ++} ++CLK_OF_DECLARE(hi3518ev20x_clk_crg, "hisilicon,hi3518ev20x-clock", ++ hi3518ev20x_clk_crg_init); ++ ++/* clock in system control */ ++static const char *const timer_mux_p[] __initconst = {"3m", "sysapb"}; ++static u32 timer_mux_table[] __initdata = {0, 1}; ++ ++static const struct hisi_mux_clock hi3518ev20x_mux_clks_sc_clk[] __initconst = { ++ { HI3518EV20X_TIME0_0_CLK, "timer00", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 16, 1, 0, timer_mux_table, }, ++ ++ { HI3518EV20X_TIME0_1_CLK, "timer01", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 18, 1, 0, timer_mux_table, }, ++ ++ { HI3518EV20X_TIME1_2_CLK, "timer12", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 20, 1, 0, timer_mux_table, }, ++ ++ { HI3518EV20X_TIME1_3_CLK, "timer13", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 22, 1, 0, timer_mux_table, }, ++}; ++ ++static void __init hi3518ev20x_sc_clk_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ int ret; ++ ++ clk_data = hisi_clk_init(np, HI3518EV20X_SC_NR_CLKS); ++ if (!clk_data) { ++ pr_err("%s: failed to allocate %s clock data\n", ++ __func__, np->name); ++ return; ++ } ++ ++ ret = hisi_clk_register_mux(hi3518ev20x_mux_clks_sc_clk, ++ ARRAY_SIZE(hi3518ev20x_mux_clks_sc_clk), clk_data); ++ if (ret) { ++ pr_err("%s: failed to register %s mux clock\n", ++ __func__, np->name); ++ return; ++ } ++} ++ ++CLK_OF_DECLARE(hi3518ev20x_clk_sysctrl, "hisilicon,hi3518ev20x-sysctrl", ++ hi3518ev20x_sc_clk_init); +diff --git a/drivers/clk/hisilicon/clk-hi3521a.c b/drivers/clk/hisilicon/clk-hi3521a.c +new file mode 100644 +index 0000000..08ba928 +--- /dev/null ++++ b/drivers/clk/hisilicon/clk-hi3521a.c +@@ -0,0 +1,246 @@ ++/* ++ * Hi3521a Clock Driver ++ * ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "clk.h" ++#include "crg.h" ++#include "reset.h" ++ ++static const struct ++hisi_fixed_rate_clock hi3521a_fixed_rate_clks_crg[] __initconst = { ++ { HI3521A_FIXED_2M, "2m", NULL, 0, 2000000, }, ++ { HI3521A_FIXED_2P2M, "2.2m", NULL, 0, 2200000, }, ++ { HI3521A_FIXED_2P5M, "2.5m", NULL, 0, 2500000, }, ++ { HI3521A_FIXED_2P5M, "3m", NULL, 0, 3000000, }, ++ { HI3521A_FIXED_24M, "24m", NULL, 0, 24000000, }, ++ { HI3521A_FIXED_25M, "25m", NULL, 0, 25000000, }, ++ { HI3521A_FIXED_27M, "27m", NULL, 0, 27000000, }, ++ { HI3521A_FIXED_50M, "50m", NULL, 0, 50000000, }, ++ { HI3521A_FIXED_54M, "54m", NULL, 0, 54000000, }, ++ { HI3521A_FIXED_60M, "60m", NULL, 0, 60000000, }, ++ { HI3521A_FIXED_62P5M, "62.5m", NULL, 0, 62500000, }, ++ { HI3521A_FIXED_75M, "75m", NULL, 0, 75000000, }, ++ { HI3521A_FIXED_83M, "83m", NULL, 0, 83000000, }, ++ { HI3521A_FIXED_100M, "100m", NULL, 0, 100000000, }, ++ { HI3521A_FIXED_125M, "125m", NULL, 0, 125000000, }, ++ { HI3521A_FIXED_150M, "150m", NULL, 0, 150000000, }, ++ { HI3521A_FIXED_162M, "162m", NULL, 0, 162000000, }, ++ { HI3521A_FIXED_187M, "187m", NULL, 0, 187000000, }, ++ { HI3521A_FIXED_187P5M, "187.5m", NULL, 0, 187500000, }, ++ { HI3521A_FIXED_202P5M, "202.5m", NULL, 0, 202500000, }, ++ { HI3521A_FIXED_250M, "250m", NULL, 0, 250000000, }, ++ { HI3521A_FIXED_270M, "270m", NULL, 0, 270000000, }, ++ { HI3521A_FIXED_300M, "300m", NULL, 0, 300000000, }, ++ { HI3521A_FIXED_324M, "324m", NULL, 0, 324000000, }, ++ { HI3521A_FIXED_375M, "375m", NULL, 0, 375000000, }, ++ { HI3521A_FIXED_400M, "400m", NULL, 0, 400000000, }, ++ { HI3521A_FIXED_405M, "405m", NULL, 0, 405000000, }, ++ { HI3521A_FIXED_500M, "500m", NULL, 0, 500000000, }, ++ { HI3521A_FIXED_750M, "750m", NULL, 0, 750000000, }, ++ { HI3521A_FIXED_800M, "800m", NULL, 0, 800000000, }, ++ { HI3521A_FIXED_810M, "810m", NULL, 0, 810000000, }, ++ { HI3521A_FIXED_1500M, "1500m", NULL, 0, 1500000000UL, }, ++ { HI3521A_FIXED_1620M, "1620m", NULL, 0, 1620000000UL, }, ++}; ++ ++static const char *const sysaxi_mux_p[] __initconst = {"24m", "250m", "202.5m"}; ++static const char *const uart_mux_p[] __initconst = {"clk_sysapb", "2m", "24m"}; ++static const char *const fmc_mux_p[] __initconst = {"24m", "83m", "150m"}; ++static const char *const eth_phy_mux_p[] __initconst = {"50m", "25m"}; ++ ++static u32 sysaxi_mux_table[] __initdata = {0, 1, 2}; ++static u32 uart_mux_table[] __initdata = {0, 1, 2}; ++static u32 fmc_mux_table[] __initdata = {0, 1, 2}; ++static u32 eth_phy_mux_table[] __initdata = {0, 1}; ++ ++static const struct hisi_mux_clock hi3521a_mux_clks_crg[] __initconst = { ++ { HI3521A_SYSAPB_CLK, "sysaxi_mux", sysaxi_mux_p, ++ ARRAY_SIZE(sysaxi_mux_p), ++ CLK_SET_RATE_PARENT, 0x34, 12, 2, 0, sysaxi_mux_table, }, ++ { HI3521A_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), ++ CLK_SET_RATE_PARENT, 0x74, 2, 2, 0, fmc_mux_table, }, ++ { HI3521A_UART_MUX, "uart_mux", uart_mux_p, ARRAY_SIZE(uart_mux_p), ++ CLK_SET_RATE_PARENT, 0x84, 18, 2, 0, uart_mux_table, }, ++ { HI3521A_ETH_PHY_MUX, "eth_phy_mux", eth_phy_mux_p, ++ ARRAY_SIZE(eth_phy_mux_p), ++ CLK_SET_RATE_PARENT, 0x78, 6, 1, 0, eth_phy_mux_table, }, ++}; ++ ++/* fixed factor clocks */ ++static struct hisi_fixed_factor_clock ++ hi3521a_fixed_factor_clks[] __initdata = { ++ { HI3521A_SYSAPB_CLK, "clk_sysapb", "sysaxi_mux", 1, 4, ++ CLK_SET_RATE_PARENT, }, ++}; ++ ++static const struct hisi_gate_clock hi3521a_gate_clks[] __initconst = { ++ /* fmc */ ++ { HI3521A_FMC_CLK, "clk_fmc", "fmc_mux", ++ CLK_SET_RATE_PARENT, 0x74, 1, 0, }, ++ ++ /* uart */ ++ { HI3521A_UART0_CLK, "clk_uart0", "uart_mux", ++ CLK_SET_RATE_PARENT, 0x84, 15, 0, }, ++ { HI3521A_UART1_CLK, "clk_uart1", "uart_mux", ++ CLK_SET_RATE_PARENT, 0x84, 16, 0, }, ++ { HI3521A_UART2_CLK, "clk_uart2", "uart_mux", ++ CLK_SET_RATE_PARENT, 0x84, 17, 0, }, ++ /* ethernet */ ++ { HI3521A_ETH_CLK, "clk_eth", NULL, ++ CLK_SET_RATE_PARENT, 0x78, 1, 0, }, ++ { HI3521A_ETH_MACIF_CLK, "clk_eth_macif", NULL, ++ CLK_SET_RATE_PARENT, 0x78, 3, 0, }, ++ /* spi */ ++ { HI3521A_SPI0_CLK, "clk_spi0", "sysaxi_mux", ++ CLK_SET_RATE_PARENT, 0x84, 13, 0, }, ++ /* dmac */ ++ { HI3521A_DMAC_CLK, "clk_dmac", "50m", ++ CLK_SET_RATE_PARENT, 0x80, 5, 0, }, ++}; ++ ++static void __init hi3521a_clk_crg_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ unsigned int count = 0; ++ int ret; ++ ++ clk_data = hisi_clk_init(np, HI3521A_CRG_NR_CLKS); ++ if (!clk_data) { ++ pr_err("%s: failed to allocate CRG clock data\n", __func__); ++ return; ++ } ++ ++ ret = hisi_clk_register_fixed_rate(hi3521a_fixed_rate_clks_crg, ++ ARRAY_SIZE(hi3521a_fixed_rate_clks_crg), clk_data); ++ if (ret) ++ goto err; ++ ++ ret = hisi_clk_register_mux(hi3521a_mux_clks_crg, ++ ARRAY_SIZE(hi3521a_mux_clks_crg), clk_data); ++ if (ret) ++ goto unregister_fixed_rate; ++ ++ ret = hisi_clk_register_fixed_factor(hi3521a_fixed_factor_clks, ++ ARRAY_SIZE(hi3521a_fixed_factor_clks), clk_data); ++ if (ret) ++ goto unregister_mux; ++ ++ ret = hisi_clk_register_gate(hi3521a_gate_clks, ++ ARRAY_SIZE(hi3521a_gate_clks), clk_data); ++ if (ret) ++ goto unregister_factor; ++ ++ ret = of_clk_add_provider(np, ++ of_clk_src_onecell_get, &clk_data->clk_data); ++ if (ret) ++ goto unregister_gate; ++ ++ if (!of_property_read_u32(np, "#reset-cells", &count) && (count == 2)) ++ if (hibvt_reset_init(np, HI3521A_CRG_NR_RSTS)) ++ goto err; ++ ++ return; ++ ++unregister_gate: ++ hisi_clk_unregister_gate(hi3521a_gate_clks, ++ ARRAY_SIZE(hi3521a_gate_clks), clk_data); ++unregister_factor: ++ hisi_clk_unregister_fixed_factor(hi3521a_fixed_factor_clks, ++ ARRAY_SIZE(hi3521a_fixed_factor_clks), clk_data); ++unregister_mux: ++ hisi_clk_unregister_mux(hi3521a_mux_clks_crg, ++ ARRAY_SIZE(hi3521a_mux_clks_crg), clk_data); ++unregister_fixed_rate: ++ hisi_clk_unregister_fixed_rate(hi3521a_fixed_rate_clks_crg, ++ ARRAY_SIZE(hi3521a_fixed_rate_clks_crg), clk_data); ++err: ++ pr_err("%s: failed to init CRG clock\n", __func__); ++ return; ++} ++CLK_OF_DECLARE(hi3521a_clk_crg, "hisilicon,hi3521a-clock", ++ hi3521a_clk_crg_init); ++ ++/* clock in system control */ ++static const char *const timer_mux_p[] __initconst = {"3m", "clk_sysapb"}; ++static u32 timer_mux_table[] __initdata = {0, 1}; ++ ++static const struct hisi_mux_clock hi3521a_mux_clks_sc_clk[] __initconst = { ++ { HI3521A_TIME0_0_CLK, "timer00", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 16, 1, 0, timer_mux_table, }, ++ ++ { HI3521A_TIME0_1_CLK, "timer01", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 18, 1, 0, timer_mux_table, }, ++ ++ { HI3521A_TIME1_2_CLK, "timer12", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 20, 1, 0, timer_mux_table, }, ++ ++ { HI3521A_TIME1_3_CLK, "timer13", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 22, 1, 0, timer_mux_table, }, ++ ++ { HI3521A_TIME2_4_CLK, "timer24", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 25, 1, 0, timer_mux_table, }, ++ ++ { HI3521A_TIME2_5_CLK, "timer25", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 27, 1, 0, timer_mux_table, }, ++ ++ { HI3521A_TIME3_6_CLK, "timer36", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 29, 1, 0, timer_mux_table, }, ++ ++ { HI3521A_TIME3_7_CLK, "timer37", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 31, 1, 0, timer_mux_table, }, ++}; ++ ++static void __init hi3521a_sc_clk_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ int ret; ++ ++ clk_data = hisi_clk_init(np, HI3521A_SC_NR_CLKS); ++ if (!clk_data) { ++ pr_err("%s: failed to allocate %s clock data\n", ++ __func__, np->name); ++ return; ++ } ++ ++ ret = hisi_clk_register_mux(hi3521a_mux_clks_sc_clk, ++ ARRAY_SIZE(hi3521a_mux_clks_sc_clk), clk_data); ++ if (ret) { ++ pr_err("%s: failed to register %s mux clock\n", ++ __func__, np->name); ++ return; ++ } ++} ++ ++CLK_OF_DECLARE(hi3521a_clk_sysctrl, "hisilicon,hi3521a-sysctrl", ++ hi3521a_sc_clk_init); +diff --git a/drivers/clk/hisilicon/clk-hi3531a.c b/drivers/clk/hisilicon/clk-hi3531a.c +new file mode 100644 +index 0000000..8853a53 +--- /dev/null ++++ b/drivers/clk/hisilicon/clk-hi3531a.c +@@ -0,0 +1,271 @@ ++/* ++ * Hi3531a Clock Driver ++ * ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "clk.h" ++#include "crg.h" ++#include "reset.h" ++ ++static const struct ++hisi_fixed_rate_clock hi3531a_fixed_rate_clks_crg[] __initconst = { ++ { HI3531A_FIXED_2M, "2m", NULL, 0, 2000000, }, ++ { HI3531A_FIXED_2P02M, "2.02m", NULL, 0, 2020000, }, ++ { HI3531A_FIXED_2P5M, "2.5m", NULL, 0, 2500000, }, ++ { HI3531A_FIXED_3M, "3m", NULL, 0, 3000000, }, ++ { HI3531A_FIXED_24M, "24m", NULL, 0, 24000000, }, ++ { HI3531A_FIXED_25M, "25m", NULL, 0, 25000000, }, ++ { HI3531A_FIXED_27M, "27m", NULL, 0, 27000000, }, ++ { HI3531A_FIXED_37P125M, "37.125m", NULL, 0, 37125000, }, ++ { HI3531A_FIXED_37P5M, "37.5m", NULL, 0, 37500000, }, ++ { HI3531A_FIXED_40P5M, "40.5m", NULL, 0, 40500000, }, ++ { HI3531A_FIXED_48M, "48m", NULL, 0, 48000000, }, ++ { HI3531A_FIXED_50M, "50m", NULL, 0, 50000000, }, ++ { HI3531A_FIXED_54M, "54m", NULL, 0, 54000000, }, ++ { HI3531A_FIXED_59P2M, "59.2m", NULL, 0, 59200000, }, ++ { HI3531A_FIXED_60M, "60m", NULL, 0, 60000000, }, ++ { HI3531A_FIXED_62P5M, "62.5m", NULL, 0, 62500000, }, ++ { HI3531A_FIXED_74P25M, "75.25m", NULL, 0, 74250000, }, ++ { HI3531A_FIXED_75M, "75m", NULL, 0, 75000000, }, ++ { HI3531A_FIXED_83P3M, "83.3m", NULL, 0, 83300000, }, ++ { HI3531A_FIXED_100M, "100m", NULL, 0, 100000000, }, ++ { HI3531A_FIXED_125M, "125m", NULL, 0, 125000000, }, ++ { HI3531A_FIXED_150M, "150m", NULL, 0, 150000000, }, ++ { HI3531A_FIXED_187P5M, "187.5m", NULL, 0, 187500000, }, ++ { HI3531A_FIXED_200M, "200m", NULL, 0, 200000000, }, ++ { HI3531A_FIXED_250M, "250m", NULL, 0, 250000000, }, ++ { HI3531A_FIXED_300M, "300m", NULL, 0, 300000000, }, ++ { HI3531A_FIXED_324M, "324m", NULL, 0, 324000000, }, ++ { HI3531A_FIXED_355M, "355m", NULL, 0, 355000000, }, ++ { HI3531A_FIXED_400M, "400m", NULL, 0, 400000000, }, ++ { HI3531A_FIXED_433M, "433m", NULL, 0, 433000000, }, ++ { HI3531A_FIXED_500M, "500m", NULL, 0, 500000000, }, ++ { HI3531A_FIXED_750M, "750m", NULL, 0, 750000000, }, ++ { HI3531A_FIXED_800M, "800m", NULL, 0, 800000000, }, ++ { HI3531A_FIXED_1000M, "1000m", NULL, 0, 1000000000UL, }, ++ { HI3531A_FIXED_1420M, "1420m", NULL, 0, 1420000000UL, }, ++ { HI3531A_FIXED_1500M, "1500m", NULL, 0, 1500000000UL, }, ++}; ++ ++static const char *const sysaxi_mux_p[] __initconst = {"24m", "300m", "250m"}; ++static const char *const periaxi_mux_p[] __initconst = {"24m", "250m", "200m"}; ++static const char *const uart_mux_p[] __initconst = {"clk_periaxi", "24m", "2m"}; ++static const char *const fmc_mux_p[] __initconst = {"24m", "83m", "150m"}; ++static const char *const nfc_mux_p[] __initconst = {"24m", "200m"}; ++static const char *const eth_phy_mux_p[] __initconst = {"50m", "25m"}; ++ ++static u32 sysaxi_mux_table[] __initdata = {0, 1, 2}; ++static u32 periaxi_mux_table[] __initdata = {0, 1, 2}; ++static u32 uart_mux_table[] __initdata = {0, 1, 2}; ++static u32 fmc_mux_table[] __initdata = {0, 1, 2}; ++static u32 nfc_mux_table[] __initdata = {0, 1}; ++static u32 eth_phy_mux_table[] __initdata = {0, 1}; ++ ++static const struct hisi_mux_clock hi3531a_mux_clks_crg[] __initconst = { ++ /* bus mux clock */ ++ { HI3531A_PERIAXI_CLK, "periaxi_mux", periaxi_mux_p, ++ ARRAY_SIZE(periaxi_mux_p), ++ CLK_SET_RATE_PARENT, 0x50, 0, 2, 0, periaxi_mux_table, }, ++ { HI3531A_SYSAXI_CLK, "sysaxi_mux", sysaxi_mux_p, ++ ARRAY_SIZE(sysaxi_mux_p), ++ CLK_SET_RATE_PARENT, 0x50, 2, 2, 0, sysaxi_mux_table, }, ++ /* fmc(spi nor and spi nand) mux clock */ ++ { HI3531A_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), ++ CLK_SET_RATE_PARENT, 0x148, 2, 2, 0, fmc_mux_table, }, ++ /* parallel nand mux clock */ ++ { HI3531A_NFC_MUX, "nfc_mux", nfc_mux_p, ARRAY_SIZE(nfc_mux_p), ++ CLK_SET_RATE_PARENT, 0x13c, 2, 1, 0, nfc_mux_table, }, ++ /* uart mux clock */ ++ { HI3531A_UART_MUX, "uart_mux", uart_mux_p, ARRAY_SIZE(uart_mux_p), ++ CLK_SET_RATE_PARENT, 0x154, 19, 2, 0, uart_mux_table, }, ++ /* ethernet PHY clock */ ++ { HI3531A_ETH_PHY_MUX, "eth_phy_mux", eth_phy_mux_p, ++ ARRAY_SIZE(eth_phy_mux_p), ++ CLK_SET_RATE_PARENT, 0x14c, 6, 1, 0, eth_phy_mux_table, }, ++}; ++ ++/* fixed factor clocks */ ++static struct hisi_fixed_factor_clock ++ hi3531a_fixed_factor_clks[] __initdata = { ++ { HI3531A_SYSAXI_CLK, "clk_sysapb", "sysaxi_mux", 1, 4, ++ CLK_SET_RATE_PARENT, }, ++ { HI3531A_PERIAXI_CLK, "clk_periaxi", "periaxi_mux", 1, 4, ++ CLK_SET_RATE_PARENT, }, ++}; ++ ++static const struct hisi_gate_clock hi3531a_gate_clks[] __initconst = { ++ /* fmc */ ++ { HI3531A_FMC_CLK, "clk_fmc", "fmc_mux", ++ CLK_SET_RATE_PARENT, 0x148, 1, 0, }, ++ ++ /* nfc */ ++ { HI3531A_NFC_CLK, "clk_nfc", "nfc_mux", ++ CLK_SET_RATE_PARENT, 0x13c, 1, 0, }, ++ ++ /* uart */ ++ { HI3531A_UART0_CLK, "clk_uart0", "uart_mux", ++ CLK_SET_RATE_PARENT, 0x154, 15, 0, }, ++ { HI3531A_UART1_CLK, "clk_uart1", "uart_mux", ++ CLK_SET_RATE_PARENT, 0x154, 16, 0, }, ++ { HI3531A_UART2_CLK, "clk_uart2", "uart_mux", ++ CLK_SET_RATE_PARENT, 0x154, 17, 0, }, ++ { HI3531A_UART2_CLK, "clk_uart3", "uart_mux", ++ CLK_SET_RATE_PARENT, 0x154, 18, 0, }, ++ /* ethernet */ ++ { HI3531A_ETH_CLK, "clk_eth", NULL, ++ CLK_SET_RATE_PARENT, 0x14c, 1, 0, }, ++ { HI3531A_ETH_MACIF_CLK, "clk_eth_macif", NULL, ++ CLK_SET_RATE_PARENT, 0x14c, 3, 0, }, ++ /* spi */ ++ { HI3531A_SPI0_CLK, "clk_spi0", "periaxi_mux", ++ CLK_SET_RATE_PARENT, 0x154, 13, 0, }, ++ /* dmac */ ++ { HI3531A_DMAC_CLK, "clk_dmac", "50m", ++ CLK_SET_RATE_PARENT, 0x144, 1, 0, }, ++}; ++ ++static void __init hi3531a_clk_crg_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ unsigned int count = 0; ++ int ret; ++ ++ clk_data = hisi_clk_init(np, HI3531A_CRG_NR_CLKS); ++ if (!clk_data) { ++ pr_err("%s: failed to allocate CRG clock data\n", __func__); ++ return; ++ } ++ ++ ret = hisi_clk_register_fixed_rate(hi3531a_fixed_rate_clks_crg, ++ ARRAY_SIZE(hi3531a_fixed_rate_clks_crg), clk_data); ++ if (ret) ++ goto err; ++ ++ ret = hisi_clk_register_mux(hi3531a_mux_clks_crg, ++ ARRAY_SIZE(hi3531a_mux_clks_crg), clk_data); ++ if (ret) ++ goto unregister_fixed_rate; ++ ++ ret = hisi_clk_register_fixed_factor(hi3531a_fixed_factor_clks, ++ ARRAY_SIZE(hi3531a_fixed_factor_clks), clk_data); ++ if (ret) ++ goto unregister_mux; ++ ++ ret = hisi_clk_register_gate(hi3531a_gate_clks, ++ ARRAY_SIZE(hi3531a_gate_clks), clk_data); ++ if (ret) ++ goto unregister_factor; ++ ++ ret = of_clk_add_provider(np, ++ of_clk_src_onecell_get, &clk_data->clk_data); ++ if (ret) ++ goto unregister_gate; ++ ++ if (!of_property_read_u32(np, "#reset-cells", &count) && (count == 2)) ++ if (hibvt_reset_init(np, HI3531A_CRG_NR_RSTS)) ++ goto err; ++ ++ return; ++ ++unregister_gate: ++ hisi_clk_unregister_gate(hi3531a_gate_clks, ++ ARRAY_SIZE(hi3531a_gate_clks), clk_data); ++unregister_factor: ++ hisi_clk_unregister_fixed_factor(hi3531a_fixed_factor_clks, ++ ARRAY_SIZE(hi3531a_fixed_factor_clks), clk_data); ++unregister_mux: ++ hisi_clk_unregister_mux(hi3531a_mux_clks_crg, ++ ARRAY_SIZE(hi3531a_mux_clks_crg), clk_data); ++unregister_fixed_rate: ++ hisi_clk_unregister_fixed_rate(hi3531a_fixed_rate_clks_crg, ++ ARRAY_SIZE(hi3531a_fixed_rate_clks_crg), clk_data); ++err: ++ pr_err("%s: failed to init CRG clock\n", __func__); ++ return; ++} ++CLK_OF_DECLARE(hi3531a_clk_crg, "hisilicon,hi3531a-clock", ++ hi3531a_clk_crg_init); ++ ++/* clock in system control */ ++static const char *const timer_mux_p[] __initconst = {"3m", "clk_periaxi"}; ++static u32 timer_mux_table[] __initdata = {0, 1}; ++ ++static const struct hisi_mux_clock hi3531a_mux_clks_sc_clk[] __initconst = { ++ { HI3531A_TIME0_0_CLK, "timer00", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 16, 1, 0, timer_mux_table, }, ++ ++ { HI3531A_TIME0_1_CLK, "timer01", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 18, 1, 0, timer_mux_table, }, ++ ++ { HI3531A_TIME1_2_CLK, "timer12", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 20, 1, 0, timer_mux_table, }, ++ ++ { HI3531A_TIME1_3_CLK, "timer13", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 22, 1, 0, timer_mux_table, }, ++ ++ { HI3531A_TIME2_4_CLK, "timer24", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 25, 1, 0, timer_mux_table, }, ++ ++ { HI3531A_TIME2_5_CLK, "timer25", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 27, 1, 0, timer_mux_table, }, ++ ++ { HI3531A_TIME3_6_CLK, "timer36", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 29, 1, 0, timer_mux_table, }, ++ ++ { HI3531A_TIME3_7_CLK, "timer37", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 31, 1, 0, timer_mux_table, }, ++}; ++ ++static void __init hi3531a_sc_clk_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ int ret; ++ ++ clk_data = hisi_clk_init(np, HI3531A_SYS_NR_CLKS); ++ if (!clk_data) { ++ pr_err("%s: failed to allocate %s clock data\n", ++ __func__, np->name); ++ return; ++ } ++ ++ ret = hisi_clk_register_mux(hi3531a_mux_clks_sc_clk, ++ ARRAY_SIZE(hi3531a_mux_clks_sc_clk), clk_data); ++ if (ret) { ++ pr_err("%s: failed to register %s mux clock\n", ++ __func__, np->name); ++ return; ++ } ++} ++ ++CLK_OF_DECLARE(hi3531a_clk_sysctrl, "hisilicon,hi3531a-sysctrl", ++ hi3531a_sc_clk_init); +diff --git a/drivers/clk/hisilicon/clk-hi3536dv100.c b/drivers/clk/hisilicon/clk-hi3536dv100.c +new file mode 100644 +index 0000000..23916da +--- /dev/null ++++ b/drivers/clk/hisilicon/clk-hi3536dv100.c +@@ -0,0 +1,229 @@ ++/* ++ * Hi3536DV100 Clock Driver ++ * ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "clk.h" ++#include "crg.h" ++#include "reset.h" ++ ++static const struct ++hisi_fixed_rate_clock hi3536dv100_fixed_rate_clks_crg[] __initconst = { ++ { HI3536DV100_FIXED_3M, "3m", NULL, 0, 3000000, }, ++ { HI3536DV100_FIXED_6M, "6m", NULL, 0, 6000000, }, ++ { HI3536DV100_FIXED_12M, "12m", NULL, 0, 12000000, }, ++ { HI3536DV100_FIXED_24M, "24m", NULL, 0, 24000000, }, ++ { HI3536DV100_FIXED_50M, "50m", NULL, 0, 50000000, }, ++ { HI3536DV100_FIXED_83P3M, "83.3m",NULL, 0, 83300000, }, ++ { HI3536DV100_FIXED_100M, "100m", NULL, 0, 100000000, }, ++ { HI3536DV100_FIXED_125M, "125m", NULL, 0, 125000000, }, ++ { HI3536DV100_FIXED_150M, "150m", NULL, 0, 150000000, }, ++ { HI3536DV100_FIXED_200M, "200m", NULL, 0, 200000000, }, ++ { HI3536DV100_FIXED_250M, "250m", NULL, 0, 250000000, }, ++ { HI3536DV100_FIXED_300M, "300m", NULL, 0, 300000000, }, ++ { HI3536DV100_FIXED_324M, "324m", NULL, 0, 324000000, }, ++ { HI3536DV100_FIXED_342M, "342m", NULL, 0, 342000000, }, ++ { HI3536DV100_FIXED_342M, "375m", NULL, 0, 375000000, }, ++ { HI3536DV100_FIXED_400M, "400m", NULL, 0, 400000000, }, ++ { HI3536DV100_FIXED_448M, "448m", NULL, 0, 448000000, }, ++ { HI3536DV100_FIXED_500M, "500m", NULL, 0, 500000000, }, ++ { HI3536DV100_FIXED_540M, "540m", NULL, 0, 540000000, }, ++ { HI3536DV100_FIXED_600M, "600m", NULL, 0, 600000000, }, ++ { HI3536DV100_FIXED_750M, "750m", NULL, 0, 750000000, }, ++ { HI3536DV100_FIXED_1500M, "1500m",NULL, 0, 1500000000UL, }, ++}; ++ ++static const char *const sysaxi_mux_p[] __initconst = { ++ "24m", "250m", "200m", "300m"}; ++static const char *const sysapb_mux_p[] __initconst = {"24m", "50m"}; ++static const char *const uart_mux_p[] __initconst = {"sysapb_mux", "24m", "2m"}; ++static const char *const fmc_mux_p[] __initconst = {"24m", "83.3m", "150m"}; ++ ++static u32 sysaxi_mux_table[] __initdata = {0, 1, 2, 3}; ++static u32 sysapb_mux_table[] __initdata = {0, 1}; ++static u32 uart_mux_table[] __initdata = {0, 1, 2}; ++static u32 fmc_mux_table[] __initdata = {0, 1, 2}; ++ ++static struct hisi_mux_clock hi3536dv100_mux_clks_crg[] __initdata = { ++ { HI3536DV100_SYSAXI_CLK, "sysaxi_mux", sysaxi_mux_p, ++ ARRAY_SIZE(sysaxi_mux_p), ++ CLK_SET_RATE_PARENT, 0x50, 2, 2, 0, sysaxi_mux_table, }, ++ { HI3536DV100_SYSAPB_CLK, "sysapb_mux", sysapb_mux_p, ++ ARRAY_SIZE(sysapb_mux_p), ++ CLK_SET_RATE_PARENT, 0x50, 0, 1, 0, sysapb_mux_table, }, ++ { HI3536DV100_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc0, 2, 2, 0, fmc_mux_table, }, ++ { HI3536DV100_UART_MUX, "uart_mux", uart_mux_p, ++ ARRAY_SIZE(uart_mux_p), ++ CLK_SET_RATE_PARENT, 0xcc, 18, 2, 0, uart_mux_table, }, ++}; ++ ++static struct hisi_fixed_factor_clock ++ hi3536dv100_fixed_factor_clks[] __initdata = { ++ { HI3536DV100_SYSAXI_CLK, "clk_sysaxi", "sysaxi_mux", 1, 4, ++ CLK_SET_RATE_PARENT}, ++}; ++ ++static struct hisi_gate_clock hi3536dv100_gate_clks[] __initdata = { ++ /* fmc */ ++ { HI3536DV100_FMC_CLK, "clk_fmc", "fmc_mux", ++ CLK_SET_RATE_PARENT, 0xc0, 1, 0, }, ++ /* uart */ ++ { HI3536DV100_UART0_CLK, "clk_uart0", "24m", ++ CLK_SET_RATE_PARENT, 0xcc, 15, 0, }, ++ { HI3536DV100_UART1_CLK, "clk_uart1", "24m", ++ CLK_SET_RATE_PARENT, 0xcc, 16, 0, }, ++ { HI3536DV100_UART2_CLK, "clk_uart2", "24m", ++ CLK_SET_RATE_PARENT, 0xcc, 17, 0, }, ++ /* ethernet mac */ ++ { HI3536DV100_ETH0_CLK, "clk_eth0", NULL, ++ CLK_SET_RATE_PARENT, 0xc4, 1, 0, }, ++ { HI3536DV100_ETH0_PHY_CLK, "clk_eth0_phy", NULL, ++ CLK_SET_RATE_PARENT, 0xc4, 10, 0, }, ++ { HI3536DV100_DMAC_CLK, "clk_dmac", "50m", ++ CLK_SET_RATE_PARENT, 0xc8, 5, 0, }, ++}; ++ ++static void __init hi3536dv100_clk_crg_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ unsigned int count = 0; ++ int ret; ++ ++ clk_data = hisi_clk_init(np, HI3536DV100_CRG_NR_CLKS); ++ if (!clk_data) { ++ pr_err("%s: failed to allocate CRG clock data\n", __func__); ++ return; ++ } ++ ++ ret = hisi_clk_register_fixed_rate(hi3536dv100_fixed_rate_clks_crg, ++ ARRAY_SIZE(hi3536dv100_fixed_rate_clks_crg), clk_data); ++ if (ret) ++ goto err; ++ ++ ret = hisi_clk_register_mux(hi3536dv100_mux_clks_crg, ++ ARRAY_SIZE(hi3536dv100_mux_clks_crg), clk_data); ++ if (ret) ++ goto unregister_fixed_rate; ++ ++ ret = hisi_clk_register_fixed_factor(hi3536dv100_fixed_factor_clks, ++ ARRAY_SIZE(hi3536dv100_fixed_factor_clks), clk_data); ++ if (ret) ++ goto unregister_mux; ++ ++ ret = hisi_clk_register_gate(hi3536dv100_gate_clks, ++ ARRAY_SIZE(hi3536dv100_gate_clks), clk_data); ++ if (ret) ++ goto unregister_factor; ++ ++ ret = of_clk_add_provider(np, ++ of_clk_src_onecell_get, &clk_data->clk_data); ++ if (ret) ++ goto unregister_gate; ++ ++ if (!of_property_read_u32(np, "#reset-cells", &count) && (count == 2)) ++ if (hibvt_reset_init(np, HI3536DV100_CRG_NR_RSTS)) ++ goto err; ++ ++ return; ++ ++unregister_gate: ++ hisi_clk_unregister_gate(hi3536dv100_gate_clks, ++ ARRAY_SIZE(hi3536dv100_gate_clks), clk_data); ++unregister_factor: ++ hisi_clk_unregister_fixed_factor(hi3536dv100_fixed_factor_clks, ++ ARRAY_SIZE(hi3536dv100_fixed_factor_clks), clk_data); ++unregister_mux: ++ hisi_clk_unregister_mux(hi3536dv100_mux_clks_crg, ++ ARRAY_SIZE(hi3536dv100_mux_clks_crg), clk_data); ++unregister_fixed_rate: ++ hisi_clk_unregister_fixed_rate(hi3536dv100_fixed_rate_clks_crg, ++ ARRAY_SIZE(hi3536dv100_fixed_rate_clks_crg), clk_data); ++err: ++ pr_err("%s: failed to init CRG clock\n", __func__); ++ return; ++} ++CLK_OF_DECLARE(hi3536dv100_clk_crg, "hisilicon,hi3536dv100-clock", ++ hi3536dv100_clk_crg_init); ++ ++/* clock in system control */ ++static const char *const timer_mux_p[] __initconst = {"3m", "sysapb_mux"}; ++static u32 timer_mux_table[] __initdata = {0, 1}; ++ ++static const struct hisi_mux_clock hi3536dv100_mux_clks_sc_clk[] __initconst = { ++ { HI3536DV100_TIME0_0_CLK, "timer00", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 16, 1, 0, timer_mux_table, }, ++ ++ { HI3536DV100_TIME0_1_CLK, "timer01", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 18, 1, 0, timer_mux_table, }, ++ ++ { HI3536DV100_TIME1_2_CLK, "timer12", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 20, 1, 0, timer_mux_table, }, ++ ++ { HI3536DV100_TIME1_3_CLK, "timer13", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 22, 1, 0, timer_mux_table, }, ++ ++ { HI3536DV100_TIME2_4_CLK, "timer24", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 25, 1, 0, timer_mux_table, }, ++ ++ { HI3536DV100_TIME2_5_CLK, "timer25", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 27, 1, 0, timer_mux_table, }, ++ ++ { HI3536DV100_TIME3_6_CLK, "timer36", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 29, 1, 0, timer_mux_table, }, ++ ++ { HI3536DV100_TIME3_7_CLK, "timer37", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 31, 1, 0, timer_mux_table, }, ++}; ++ ++static void __init hi3536dv100_sc_clk_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ int ret; ++ ++ clk_data = hisi_clk_init(np, HI3536DV100_SC_NR_CLKS); ++ if (!clk_data) { ++ pr_err("%s: failed to allocate %s clock data\n", ++ __func__, np->name); ++ return; ++ } ++ ++ ret = hisi_clk_register_mux(hi3536dv100_mux_clks_sc_clk, ++ ARRAY_SIZE(hi3536dv100_mux_clks_sc_clk), clk_data); ++ if (ret) { ++ pr_err("%s: failed to register %s mux clock\n", ++ __func__, np->name); ++ return; ++ } ++} ++ ++CLK_OF_DECLARE(hi3536dv100_clk_sysctrl, "hisilicon,hi3536dv100-sysctrl", ++ hi3536dv100_sc_clk_init); +diff --git a/drivers/clk/hisilicon/clk-hi3559av100.c b/drivers/clk/hisilicon/clk-hi3559av100.c +new file mode 100644 +index 0000000..5e23182 +--- /dev/null ++++ b/drivers/clk/hisilicon/clk-hi3559av100.c +@@ -0,0 +1,648 @@ ++/* ++ * Hi3559AV100 Clock Driver ++ * ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "clk.h" ++#include "crg.h" ++#include "reset.h" ++ ++struct hi3559av100_pll_clock { ++ u32 id; ++ const char *name; ++ const char *parent_name; ++ u32 ctrl_reg1; ++ u8 frac_shift; ++ u8 frac_width; ++ u8 postdiv1_shift; ++ u8 postdiv1_width; ++ u8 postdiv2_shift; ++ u8 postdiv2_width; ++ u32 ctrl_reg2; ++ u8 fbdiv_shift; ++ u8 fbdiv_width; ++ u8 refdiv_shift; ++ u8 refdiv_width; ++}; ++ ++struct hi3559av100_clk_pll { ++ struct clk_hw hw; ++ u32 id; ++ void __iomem *ctrl_reg1; ++ u8 frac_shift; ++ u8 frac_width; ++ u8 postdiv1_shift; ++ u8 postdiv1_width; ++ u8 postdiv2_shift; ++ u8 postdiv2_width; ++ void __iomem *ctrl_reg2; ++ u8 fbdiv_shift; ++ u8 fbdiv_width; ++ u8 refdiv_shift; ++ u8 refdiv_width; ++}; ++ ++/* soc clk config */ ++static const struct hisi_fixed_rate_clock hi3559av100_fixed_rate_clks_crg[] = { ++ { HI3559AV100_FIXED_1188M , "1188m", NULL, 0, 1188000000, }, ++ { HI3559AV100_FIXED_1000M , "1000m", NULL, 0, 1000000000, }, ++ { HI3559AV100_FIXED_842M , "842m", NULL, 0, 842000000, }, ++ { HI3559AV100_FIXED_792M , "792m", NULL, 0, 792000000, }, ++ { HI3559AV100_FIXED_750M , "750m", NULL, 0, 750000000, }, ++ { HI3559AV100_FIXED_710M , "710m", NULL, 0, 710000000, }, ++ { HI3559AV100_FIXED_680M , "680m", NULL, 0, 680000000, }, ++ { HI3559AV100_FIXED_667M , "667m", NULL, 0, 667000000, }, ++ { HI3559AV100_FIXED_631M , "631m", NULL, 0, 631000000, }, ++ { HI3559AV100_FIXED_600M , "600m", NULL, 0, 600000000, }, ++ { HI3559AV100_FIXED_568M , "568m", NULL, 0, 568000000, }, ++ { HI3559AV100_FIXED_500M , "500m", NULL, 0, 500000000, }, ++ { HI3559AV100_FIXED_475M , "475m", NULL, 0, 475000000, }, ++ { HI3559AV100_FIXED_428M , "428m", NULL, 0, 428000000, }, ++ { HI3559AV100_FIXED_400M , "400m", NULL, 0, 400000000, }, ++ { HI3559AV100_FIXED_396M , "396m", NULL, 0, 396000000, }, ++ { HI3559AV100_FIXED_300M , "300m", NULL, 0, 300000000, }, ++ { HI3559AV100_FIXED_250M , "250m", NULL, 0, 250000000, }, ++ { HI3559AV100_FIXED_200M , "200m", NULL, 0, 200000000, }, ++ { HI3559AV100_FIXED_198M , "198m", NULL, 0, 198000000, }, ++ { HI3559AV100_FIXED_187p5M , "187p5m", NULL, 0, 187500000, }, ++ { HI3559AV100_FIXED_150M , "150m", NULL, 0, 150000000, }, ++ { HI3559AV100_FIXED_148p5M , "148p5m", NULL, 0, 1485000000, }, ++ { HI3559AV100_FIXED_125M , "125m", NULL, 0, 125000000, }, ++ { HI3559AV100_FIXED_107M , "107m", NULL, 0, 107000000, }, ++ { HI3559AV100_FIXED_100M , "100m", NULL, 0, 100000000, }, ++ { HI3559AV100_FIXED_99M , "99m", NULL, 0, 99000000, }, ++ { HI3559AV100_FIXED_75M , "75m" , NULL, 0, 75000000, }, ++ { HI3559AV100_FIXED_74p25M , "74p25m", NULL, 0, 74250000, }, ++ { HI3559AV100_FIXED_72M , "72m", NULL, 0, 72000000, }, ++ { HI3559AV100_FIXED_60M , "60m", NULL, 0, 60000000, }, ++ { HI3559AV100_FIXED_54M , "54m", NULL, 0, 54000000, }, ++ { HI3559AV100_FIXED_50M , "50m", NULL, 0, 50000000, }, ++ { HI3559AV100_FIXED_49p5M , "49p5m", NULL, 0, 49500000, }, ++ { HI3559AV100_FIXED_37p125M, "37p125m", NULL, 0, 37125000, }, ++ { HI3559AV100_FIXED_36M , "36m", NULL, 0, 36000000, }, ++ { HI3559AV100_FIXED_32p4M , "32p4m", NULL, 0, 32400000, }, ++ { HI3559AV100_FIXED_27M , "27m", NULL, 0, 27000000, }, ++ { HI3559AV100_FIXED_25M , "25m", NULL, 0, 25000000, }, ++ { HI3559AV100_FIXED_24M , "24m", NULL, 0, 24000000, }, ++ { HI3559AV100_FIXED_12M , "12m", NULL, 0, 12000000, }, ++ { HI3559AV100_FIXED_3M , "3m", NULL, 0, 3000000, }, ++ { HI3559AV100_FIXED_1p6M , "1p6m", NULL, 0, 1600000, }, ++ { HI3559AV100_FIXED_400K , "400k", NULL, 0, 400000, }, ++ { HI3559AV100_FIXED_100K , "100k", NULL, 0, 100000, }, ++}; ++ ++ ++static const char *fmc_mux_p[] __initdata = { ++ "24m", "75m", "125m", "150m", "200m", "250m", "300m", "400m"}; ++static u32 fmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6, 7}; ++ ++static const char *mmc_mux_p[] __initdata = { ++ "100k", "25m", "49p5m", "99m", "187p5m", "150m", "198m", "400k"}; ++static u32 mmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6, 7}; ++ ++static const char *sysapb_mux_p[] __initdata = { ++ "24m", "50m",}; ++static u32 sysapb_mux_table[] = {0, 1}; ++ ++static const char *sysbus_mux_p[] __initdata = { ++ "24m", "300m"}; ++static u32 sysbus_mux_table[] = {0, 1}; ++ ++static const char *uart_mux_p[] __initdata = {"50m", "24m", "3m"}; ++static u32 uart_mux_table[] = {0, 1, 2}; ++ ++static const char *a73_clksel_mux_p[] __initdata = { ++ "24m", "apll", "1000m"}; ++static u32 a73_clksel_mux_table[] = {0, 1, 2}; ++ ++static struct hisi_mux_clock hi3559av100_mux_clks_crg[] __initdata = { ++ { HI3559AV100_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), ++ CLK_SET_RATE_PARENT, 0x170, 2, 3, 0, fmc_mux_table, }, ++ ++ { HI3559AV100_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0x1a8, 24, 3, 0, mmc_mux_table, }, ++ ++ { HI3559AV100_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0x1ec, 24, 3, 0, mmc_mux_table, }, ++ ++ { HI3559AV100_MMC2_MUX, "mmc2_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0x214, 24, 3, 0, mmc_mux_table, }, ++ ++ { HI3559AV100_MMC3_MUX, "mmc3_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0x23c, 24, 3, 0, mmc_mux_table, }, ++ ++ { HI3559AV100_SYSAPB_MUX, "sysapb_mux", sysapb_mux_p, ARRAY_SIZE(sysapb_mux_p), ++ CLK_SET_RATE_PARENT, 0xe8, 3, 1, 0, sysapb_mux_table}, ++ ++ { HI3559AV100_SYSBUS_MUX, "sysbus_mux", sysbus_mux_p, ARRAY_SIZE(sysbus_mux_p), ++ CLK_SET_RATE_PARENT, 0xe8, 0, 1, 0, sysbus_mux_table}, ++ ++ { HI3559AV100_UART_MUX, "uart_mux", uart_mux_p, ARRAY_SIZE(uart_mux_p), ++ CLK_SET_RATE_PARENT, 0x198, 28, 2, 0, uart_mux_table}, ++ ++ { HI3559AV100_A73_MUX, "a73_mux", a73_clksel_mux_p, ARRAY_SIZE(a73_clksel_mux_p), ++ CLK_SET_RATE_PARENT, 0xe4, 0, 2, 0, a73_clksel_mux_table}, ++}; ++ ++static struct hisi_fixed_factor_clock hi3559av100_fixed_factor_clks[] __initdata = { ++}; ++ ++static struct hisi_gate_clock hi3559av100_gate_clks[] __initdata = { ++ /* fmc */ ++ { HI3559AV100_FMC_CLK, "clk_fmc", "fmc_mux", ++ CLK_SET_RATE_PARENT, 0x170, 1, 0, }, ++ /* mmc */ ++ { HI3559AV100_MMC0_CLK, "clk_mmc0", "mmc0_mux", ++ CLK_SET_RATE_PARENT, 0x1a8, 28, 0, }, ++ { HI3559AV100_MMC1_CLK, "clk_mmc1", "mmc1_mux", ++ CLK_SET_RATE_PARENT, 0x1ec, 28, 0, }, ++ { HI3559AV100_MMC2_CLK, "clk_mmc2", "mmc2_mux", ++ CLK_SET_RATE_PARENT, 0x214, 28, 0, }, ++ { HI3559AV100_MMC3_CLK, "clk_mmc3", "mmc3_mux", ++ CLK_SET_RATE_PARENT, 0x23c, 28, 0, }, ++ /* uart */ ++ { HI3559AV100_UART0_CLK, "clk_uart0", "uart_mux", ++ CLK_SET_RATE_PARENT, 0x198, 23, 0, }, ++ { HI3559AV100_UART1_CLK, "clk_uart1", "uart_mux", ++ CLK_SET_RATE_PARENT, 0x198, 24, 0, }, ++ { HI3559AV100_UART2_CLK, "clk_uart2", "uart_mux", ++ CLK_SET_RATE_PARENT, 0x198, 25, 0, }, ++ { HI3559AV100_UART3_CLK, "clk_uart3", "uart_mux", ++ CLK_SET_RATE_PARENT, 0x198, 26, 0, }, ++ { HI3559AV100_UART4_CLK, "clk_uart4", "uart_mux", ++ CLK_SET_RATE_PARENT, 0x198, 27, 0, }, ++ /* ethernet mac */ ++ { HI3559AV100_ETH_CLK, "clk_eth", NULL, ++ CLK_SET_RATE_PARENT, 0x0174, 1, 0, }, ++ { HI3559AV100_ETH_MACIF_CLK, "clk_eth_macif", NULL, ++ CLK_SET_RATE_PARENT, 0x0174, 5, 0, }, ++ { HI3559AV100_ETH1_CLK, "clk_eth1", NULL, ++ CLK_SET_RATE_PARENT, 0x0174, 3, 0, }, ++ { HI3559AV100_ETH1_MACIF_CLK, "clk_eth1_macif", NULL, ++ CLK_SET_RATE_PARENT, 0x0174, 7, 0, }, ++ /* i2c */ ++ { HI3559AV100_I2C0_CLK, "clk_i2c0", "50m", ++ CLK_SET_RATE_PARENT, 0x01a0, 16, 0, }, ++ { HI3559AV100_I2C1_CLK, "clk_i2c1", "50m", ++ CLK_SET_RATE_PARENT, 0x01a0, 17, 0, }, ++ { HI3559AV100_I2C2_CLK, "clk_i2c2", "50m", ++ CLK_SET_RATE_PARENT, 0x01a0, 18, 0, }, ++ { HI3559AV100_I2C3_CLK, "clk_i2c3", "50m", ++ CLK_SET_RATE_PARENT, 0x01a0, 19, 0, }, ++ { HI3559AV100_I2C4_CLK, "clk_i2c4", "50m", ++ CLK_SET_RATE_PARENT, 0x01a0, 20, 0, }, ++ { HI3559AV100_I2C5_CLK, "clk_i2c5", "50m", ++ CLK_SET_RATE_PARENT, 0x01a0, 21, 0, }, ++ { HI3559AV100_I2C6_CLK, "clk_i2c6", "50m", ++ CLK_SET_RATE_PARENT, 0x01a0, 22, 0, }, ++ { HI3559AV100_I2C7_CLK, "clk_i2c7", "50m", ++ CLK_SET_RATE_PARENT, 0x01a0, 23, 0, }, ++ { HI3559AV100_I2C8_CLK, "clk_i2c8", "50m", ++ CLK_SET_RATE_PARENT, 0x01a0, 24, 0, }, ++ { HI3559AV100_I2C9_CLK, "clk_i2c9", "50m", ++ CLK_SET_RATE_PARENT, 0x01a0, 25, 0, }, ++ { HI3559AV100_I2C10_CLK, "clk_i2c10", "50m", ++ CLK_SET_RATE_PARENT, 0x01a0, 26, 0, }, ++ { HI3559AV100_I2C11_CLK, "clk_i2c11", "50m", ++ CLK_SET_RATE_PARENT, 0x01a0, 27, 0, }, ++ /* spi */ ++ { HI3559AV100_SPI0_CLK, "clk_spi0", "100m", ++ CLK_SET_RATE_PARENT, 0x0198, 16, 0, }, ++ { HI3559AV100_SPI1_CLK, "clk_spi1", "100m", ++ CLK_SET_RATE_PARENT, 0x0198, 17, 0, }, ++ { HI3559AV100_SPI2_CLK, "clk_spi2", "100m", ++ CLK_SET_RATE_PARENT, 0x0198, 18, 0, }, ++ { HI3559AV100_SPI3_CLK, "clk_spi3", "100m", ++ CLK_SET_RATE_PARENT, 0x0198, 19, 0, }, ++ { HI3559AV100_SPI4_CLK, "clk_spi4", "100m", ++ CLK_SET_RATE_PARENT, 0x0198, 20, 0, }, ++ { HI3559AV100_SPI5_CLK, "clk_spi5", "100m", ++ CLK_SET_RATE_PARENT, 0x0198, 21, 0, }, ++ { HI3559AV100_SPI6_CLK, "clk_spi6", "100m", ++ CLK_SET_RATE_PARENT, 0x0198, 22, 0, }, ++ /* edmac */ ++ { HI3559AV100_EDMAC_AXICLK, "axi_clk_edmac", NULL, ++ CLK_SET_RATE_PARENT, 0x16c, 6, 0, }, ++ { HI3559AV100_EDMAC_CLK, "clk_edmac", NULL, ++ CLK_SET_RATE_PARENT, 0x16c, 5, 0, }, ++ { HI3559AV100_EDMAC1_AXICLK, "axi_clk_edmac1", NULL, ++ CLK_SET_RATE_PARENT, 0x16c, 9, 0, }, ++ { HI3559AV100_EDMAC1_CLK, "clk_edmac1", NULL, ++ CLK_SET_RATE_PARENT, 0x16c, 8, 0, }, ++ /* vdmac */ ++ { HI3559AV100_VDMAC_CLK, "clk_vdmac", NULL, ++ CLK_SET_RATE_PARENT, 0x14c, 5, 0, }, ++}; ++ ++static struct hi3559av100_pll_clock hi3559av100_pll_clks[] __initdata = { ++ { HI3559AV100_APLL_CLK, "apll", NULL, 0x0, 0, 24, 24, 3, 28, 3, ++ 0x4, 0, 12, 12, 6}, ++ { HI3559AV100_GPLL_CLK, "gpll", NULL, 0x20, 0, 24, 24, 3, 28, 3, ++ 0x24, 0, 12, 12, 6}, ++}; ++ ++#define to_pll_clk(_hw) container_of(_hw, struct hi3559av100_clk_pll, hw) ++static void hi3559av100_calc_pll(u32 *frac_val, u32 *postdiv1_val, u32 *postdiv2_val, ++ u32 *fbdiv_val, u32 *refdiv_val, u64 rate) ++{ ++ u64 rem; ++ *frac_val = 0; ++ rem = do_div(rate, 1000000); ++ *fbdiv_val = rate; ++ *refdiv_val = 24; ++ rem = rem * (1 << 24); ++ do_div(rem, 1000000); ++ *frac_val = rem; ++} ++ ++static int clk_pll_set_rate(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct hi3559av100_clk_pll *clk = to_pll_clk(hw); ++ u32 frac_val, postdiv1_val, postdiv2_val, fbdiv_val, refdiv_val; ++ u32 val; ++ ++ /*Fixme ignore postdives now because apll don't use them*/ ++ postdiv1_val = postdiv2_val = 0; ++ ++ hi3559av100_calc_pll(&frac_val, &postdiv1_val, &postdiv2_val, ++ &fbdiv_val, &refdiv_val, (u64)rate); ++ ++ val = readl_relaxed(clk->ctrl_reg1); ++ val &= ~(((1 << clk->frac_width) - 1) << clk->frac_shift); ++ val &= ~(((1 << clk->postdiv1_width) - 1) << clk->postdiv1_shift); ++ val &= ~(((1 << clk->postdiv2_width) - 1) << clk->postdiv2_shift); ++ ++ val |= frac_val << clk->frac_shift; ++ val |= postdiv1_val << clk->postdiv1_shift; ++ val |= postdiv2_val << clk->postdiv2_shift; ++ writel_relaxed(val, clk->ctrl_reg1); ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val &= ~(((1 << clk->fbdiv_width) - 1) << clk->fbdiv_shift); ++ val &= ~(((1 << clk->refdiv_width) - 1) << clk->refdiv_shift); ++ ++ val |= fbdiv_val << clk->fbdiv_shift; ++ val |= refdiv_val << clk->refdiv_shift; ++ writel_relaxed(val, clk->ctrl_reg2); ++ ++ return 0; ++} ++ ++static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct hi3559av100_clk_pll *clk = to_pll_clk(hw); ++ u64 frac_val, fbdiv_val, refdiv_val; ++ u32 val; ++ u64 tmp, rate; ++ ++ val = readl_relaxed(clk->ctrl_reg1); ++ val = val >> clk->frac_shift; ++ val &= ((1 << clk->frac_width) - 1); ++ frac_val = val; ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val = val >> clk->fbdiv_shift; ++ val &= ((1 << clk->fbdiv_width) - 1); ++ fbdiv_val = val; ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val = val >> clk->refdiv_shift; ++ val &= ((1 << clk->refdiv_width) - 1); ++ refdiv_val = val; ++ ++ /* rate = 24000000 * (fbdiv + frac / (1<<24) ) / refdiv */ ++ rate = 0; ++ tmp = 24000000 * fbdiv_val; ++ rate += tmp; ++ do_div(rate, refdiv_val); ++ ++ return rate; ++} ++ ++static int clk_pll_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ return req->rate; ++} ++ ++static struct clk_ops clk_pll_ops = { ++ .set_rate = clk_pll_set_rate, ++ .determine_rate = clk_pll_determine_rate, ++ .recalc_rate = clk_pll_recalc_rate, ++}; ++ ++void hisi_clk_register_pll(struct hi3559av100_pll_clock *clks, ++ int nums, struct hisi_clock_data *data) ++{ ++ void __iomem *base = data->base; ++ int i; ++ ++ for (i = 0; i < nums; i++) { ++ struct hi3559av100_clk_pll *p_clk; ++ struct clk *clk; ++ struct clk_init_data init; ++ ++ p_clk = kzalloc(sizeof(*p_clk), GFP_KERNEL); ++ if (!p_clk) ++ return; ++ ++ init.name = clks[i].name; ++ init.flags = CLK_IS_BASIC; ++ init.parent_names = ++ (clks[i].parent_name ? &clks[i].parent_name : NULL); ++ init.num_parents = (clks[i].parent_name ? 1 : 0); ++ init.ops = &clk_pll_ops; ++ ++ p_clk->ctrl_reg1 = base + clks[i].ctrl_reg1; ++ p_clk->frac_shift = clks[i].frac_shift; ++ p_clk->frac_width = clks[i].frac_width; ++ p_clk->postdiv1_shift = clks[i].postdiv1_shift; ++ p_clk->postdiv1_width = clks[i].postdiv1_width; ++ p_clk->postdiv2_shift = clks[i].postdiv2_shift; ++ p_clk->postdiv2_width = clks[i].postdiv2_width; ++ ++ p_clk->ctrl_reg2 = base + clks[i].ctrl_reg2; ++ p_clk->fbdiv_shift = clks[i].fbdiv_shift; ++ p_clk->fbdiv_width = clks[i].fbdiv_width; ++ p_clk->refdiv_shift = clks[i].refdiv_shift; ++ p_clk->refdiv_width = clks[i].refdiv_width; ++ p_clk->hw.init = &init; ++ ++ clk = clk_register(NULL, &p_clk->hw); ++ if (IS_ERR(clk)) { ++ kfree(p_clk); ++ pr_err("%s: failed to register clock %s\n", ++ __func__, clks[i].name); ++ continue; ++ } ++ ++ data->clk_data.clks[clks[i].id] = clk; ++ } ++} ++ ++static __init struct hisi_clock_data *hi3559av100_clk_register( ++ struct platform_device *pdev) ++{ ++ struct hisi_clock_data *clk_data; ++ int ret; ++ ++ clk_data = hisi_clk_alloc(pdev, HI3559AV100_CRG_NR_CLKS); ++ if (!clk_data) ++ return ERR_PTR(-ENOMEM); ++ ++ ret = hisi_clk_register_fixed_rate(hi3559av100_fixed_rate_clks_crg, ++ ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), clk_data); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ hisi_clk_register_pll(hi3559av100_pll_clks, ++ ARRAY_SIZE(hi3559av100_pll_clks), clk_data); ++ ++ ret = hisi_clk_register_mux(hi3559av100_mux_clks_crg, ++ ARRAY_SIZE(hi3559av100_mux_clks_crg), clk_data); ++ if (ret) ++ goto unregister_fixed_rate; ++ ++ ret = hisi_clk_register_fixed_factor(hi3559av100_fixed_factor_clks, ++ ARRAY_SIZE(hi3559av100_fixed_factor_clks), clk_data); ++ if (ret) ++ goto unregister_mux; ++ ++ ret = hisi_clk_register_gate(hi3559av100_gate_clks, ++ ARRAY_SIZE(hi3559av100_gate_clks), clk_data); ++ if (ret) ++ goto unregister_factor; ++ ++ ret = of_clk_add_provider(pdev->dev.of_node, ++ of_clk_src_onecell_get, &clk_data->clk_data); ++ if (ret) ++ goto unregister_gate; ++ ++ return clk_data; ++ ++unregister_gate: ++ hisi_clk_unregister_gate(hi3559av100_gate_clks, ++ ARRAY_SIZE(hi3559av100_gate_clks), clk_data); ++unregister_factor: ++ hisi_clk_unregister_fixed_factor(hi3559av100_fixed_factor_clks, ++ ARRAY_SIZE(hi3559av100_fixed_factor_clks), clk_data); ++unregister_mux: ++ hisi_clk_unregister_mux(hi3559av100_mux_clks_crg, ++ ARRAY_SIZE(hi3559av100_mux_clks_crg), clk_data); ++unregister_fixed_rate: ++ hisi_clk_unregister_fixed_rate(hi3559av100_fixed_rate_clks_crg, ++ ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), clk_data); ++ return ERR_PTR(ret); ++} ++ ++static __init void hi3559av100_clk_unregister(struct platform_device *pdev) ++{ ++ struct hisi_crg_dev *crg = platform_get_drvdata(pdev); ++ ++ of_clk_del_provider(pdev->dev.of_node); ++ ++ hisi_clk_unregister_gate(hi3559av100_gate_clks, ++ ARRAY_SIZE(hi3559av100_gate_clks), crg->clk_data); ++ hisi_clk_unregister_mux(hi3559av100_mux_clks_crg, ++ ARRAY_SIZE(hi3559av100_mux_clks_crg), crg->clk_data); ++ hisi_clk_unregister_fixed_factor(hi3559av100_fixed_factor_clks, ++ ARRAY_SIZE(hi3559av100_fixed_factor_clks), crg->clk_data); ++ hisi_clk_unregister_fixed_rate(hi3559av100_fixed_rate_clks_crg, ++ ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), crg->clk_data); ++} ++ ++static const struct hisi_crg_funcs hi3559av100_crg_funcs = { ++ .register_clks = hi3559av100_clk_register, ++ .unregister_clks = hi3559av100_clk_unregister, ++}; ++ ++ ++static const struct of_device_id hi3559av100_crg_match_table[] = { ++ { ++ .compatible = "hisilicon,hi3559av100-clock", ++ .data = &hi3559av100_crg_funcs ++ }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, hi3559av100_crg_match_table); ++ ++static int hi3559av100_crg_probe(struct platform_device *pdev) ++{ ++ struct hisi_crg_dev *crg; ++ ++ crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL); ++ if (!crg) ++ return -ENOMEM; ++ ++ crg->funcs = of_device_get_match_data(&pdev->dev); ++ if (!crg->funcs) ++ return -ENOENT; ++ ++ crg->rstc = hisi_reset_init(pdev); ++ if (!crg->rstc) ++ return -ENOMEM; ++ ++ crg->clk_data = crg->funcs->register_clks(pdev); ++ if (IS_ERR(crg->clk_data)) { ++ hisi_reset_exit(crg->rstc); ++ return PTR_ERR(crg->clk_data); ++ } ++ ++ platform_set_drvdata(pdev, crg); ++ return 0; ++} ++ ++static int hi3559av100_crg_remove(struct platform_device *pdev) ++{ ++ struct hisi_crg_dev *crg = platform_get_drvdata(pdev); ++ ++ hisi_reset_exit(crg->rstc); ++ crg->funcs->unregister_clks(pdev); ++ return 0; ++} ++ ++static struct platform_driver hi3559av100_crg_driver = { ++ .probe = hi3559av100_crg_probe, ++ .remove = hi3559av100_crg_remove, ++ .driver = { ++ .name = "hi3559av100-clock", ++ .of_match_table = hi3559av100_crg_match_table, ++ }, ++}; ++ ++static int __init hi3559av100_crg_init(void) ++{ ++ return platform_driver_register(&hi3559av100_crg_driver); ++} ++core_initcall(hi3559av100_crg_init); ++ ++static void __exit hi3559av100_crg_exit(void) ++{ ++ platform_driver_unregister(&hi3559av100_crg_driver); ++} ++module_exit(hi3559av100_crg_exit); ++ ++#ifdef CONFIG_ACCESS_M7_DEV ++static struct hisi_fixed_rate_clock hi3559av100_shub_fixed_rate_clks[] __initdata = { ++ { HI3559AV100_SHUB_SOURCE_SOC_24M, "clk_source_24M", NULL, 0, 24000000UL, }, ++ { HI3559AV100_SHUB_SOURCE_SOC_200M, "clk_source_200M", NULL, 0, 200000000UL, }, ++ { HI3559AV100_SHUB_SOURCE_SOC_300M, "clk_source_300M", NULL, 0, 300000000UL, }, ++ { HI3559AV100_SHUB_SOURCE_PLL, "clk_source_PLL", NULL, 0, 192000000UL, }, ++ { HI3559AV100_SHUB_I2C0_CLK, "clk_shub_i2c0", NULL, 0, 48000000UL, }, ++ { HI3559AV100_SHUB_I2C1_CLK, "clk_shub_i2c1", NULL, 0, 48000000UL, }, ++ { HI3559AV100_SHUB_I2C2_CLK, "clk_shub_i2c2", NULL, 0, 48000000UL, }, ++ { HI3559AV100_SHUB_I2C3_CLK, "clk_shub_i2c3", NULL, 0, 48000000UL, }, ++ { HI3559AV100_SHUB_I2C4_CLK, "clk_shub_i2c4", NULL, 0, 48000000UL, }, ++ { HI3559AV100_SHUB_I2C5_CLK, "clk_shub_i2c5", NULL, 0, 48000000UL, }, ++ { HI3559AV100_SHUB_I2C6_CLK, "clk_shub_i2c6", NULL, 0, 48000000UL, }, ++ { HI3559AV100_SHUB_I2C7_CLK, "clk_shub_i2c7", NULL, 0, 48000000UL, }, ++ { HI3559AV100_SHUB_UART_CLK_32K , "clk_uart_32K", NULL, 0, 32000UL, }, ++}; ++ ++/* shub mux clk */ ++static u32 shub_source_clk_mux_table[] = {0, 1, 2, 3}; ++static const char *shub_source_clk_mux_p[] __initdata = { ++ "clk_source_24M", "clk_source_200M", "clk_source_300M", "clk_source_PLL" ++}; ++ ++static u32 shub_uart_source_clk_mux_table[] = {0, 1, 2, 3}; ++static const char *shub_uart_source_clk_mux_p[] __initdata = { ++ "clk_uart_32K", "clk_uart_div_clk", "clk_uart_div_clk", "clk_source_24M" ++}; ++ ++static struct hisi_mux_clock hi3559av100_shub_mux_clks[] __initdata = { ++ { HI3559AV100_SHUB_SOURCE_CLK, "shub_clk", shub_source_clk_mux_p, ARRAY_SIZE(shub_source_clk_mux_p), ++ 0, 0x0, 0, 2, 0, shub_source_clk_mux_table, }, ++ ++ { HI3559AV100_SHUB_UART_SOURCE_CLK, "shub_uart_source_clk", shub_uart_source_clk_mux_p , ARRAY_SIZE(shub_uart_source_clk_mux_p), ++ 0, 0x1c, 20, 2, 0, shub_uart_source_clk_mux_table, }, ++}; ++ ++ ++/* shub div clk */ ++struct clk_div_table shub_spi_clk_table[] = {{0, 8},{1, 4},{2, 2}}; ++struct clk_div_table shub_spi4_clk_table[] = {{0, 8},{1, 4},{2, 2},{3, 1}}; ++struct clk_div_table shub_uart_div_clk_table[] = {{1, 8},{2, 4}}; ++ ++struct hisi_divider_clock hi3559av100_shub_div_clks[] __initdata = { ++ { HI3559AV100_SHUB_SPI_SOURCE_CLK, "clk_spi_clk", "shub_clk", 0, 0x20, 24, 2, CLK_DIVIDER_ALLOW_ZERO, shub_spi_clk_table, }, ++ { HI3559AV100_SHUB_UART_DIV_CLK, "clk_uart_div_clk", "shub_clk", 0, 0x1c, 28, 2, CLK_DIVIDER_ALLOW_ZERO, shub_uart_div_clk_table, }, ++}; ++ ++ ++/* shub gate clk */ ++static struct hisi_gate_clock hi3559av100_shub_gate_clks[] __initdata = { ++ { HI3559AV100_SHUB_SPI0_CLK , "clk_shub_spi0", "clk_spi_clk", ++ 0, 0x20, 1, 0, }, ++ { HI3559AV100_SHUB_SPI1_CLK , "clk_shub_spi1", "clk_spi_clk", ++ 0, 0x20, 5, 0, }, ++ { HI3559AV100_SHUB_SPI2_CLK , "clk_shub_spi2", "clk_spi_clk", ++ 0, 0x20, 9, 0, }, ++ ++ { HI3559AV100_SHUB_UART0_CLK, "clk_shub_uart0", "shub_uart_source_clk", ++ 0, 0x1c, 1, 0, }, ++ { HI3559AV100_SHUB_UART1_CLK, "clk_shub_uart1", "shub_uart_source_clk", ++ 0, 0x1c, 5, 0, }, ++ { HI3559AV100_SHUB_UART2_CLK, "clk_shub_uart2", "shub_uart_source_clk", ++ 0, 0x1c, 9, 0, }, ++ { HI3559AV100_SHUB_UART3_CLK, "clk_shub_uart3", "shub_uart_source_clk", ++ 0, 0x1c, 13, 0, }, ++ { HI3559AV100_SHUB_UART4_CLK, "clk_shub_uart4", "shub_uart_source_clk", ++ 0, 0x1c, 17, 0, }, ++ { HI3559AV100_SHUB_UART5_CLK, "clk_shub_uart5", "shub_uart_source_clk", ++ 0, 0x1c, 21, 0, }, ++ { HI3559AV100_SHUB_UART6_CLK, "clk_shub_uart6", "shub_uart_source_clk", ++ 0, 0x1c, 25, 0, }, ++}; ++ ++static void __init hi3559av100_shub_clk_init(struct device_node *np) ++{ ++ ++ struct hisi_clock_data *clk_data; ++ ++ clk_data = hisi_clk_init(np, HI3559AV100_SHUB_NR_CLKS); ++ if (!clk_data) ++ return; ++ ++ hisi_clk_register_fixed_rate(hi3559av100_shub_fixed_rate_clks, ++ ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), ++ clk_data); ++ ++ hisi_clk_register_mux(hi3559av100_shub_mux_clks, ARRAY_SIZE(hi3559av100_shub_mux_clks), ++ clk_data); ++ ++ hisi_clk_register_divider(hi3559av100_shub_div_clks,ARRAY_SIZE(hi3559av100_shub_div_clks), ++ clk_data); ++ hisi_clk_register_gate(hi3559av100_shub_gate_clks, ++ ARRAY_SIZE(hi3559av100_shub_gate_clks), clk_data); ++} ++CLK_OF_DECLARE(hi3559av100_shub_clk, "hisilicon,hi3559av100-shub-clock", hi3559av100_shub_clk_init); ++#endif ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("HiSilicon Hi3559AV100 CRG Driver"); ++ +diff --git a/drivers/clk/hisilicon/crg.h b/drivers/clk/hisilicon/crg.h +new file mode 100644 +index 0000000..e073971 +--- /dev/null ++++ b/drivers/clk/hisilicon/crg.h +@@ -0,0 +1,34 @@ ++/* ++ * HiSilicon Clock and Reset Driver Header ++ * ++ * Copyright (c) 2016 HiSilicon Limited. ++ * ++ * 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 __HISI_CRG_H ++#define __HISI_CRG_H ++ ++struct hisi_clock_data; ++struct hisi_reset_controller; ++ ++struct hisi_crg_funcs { ++ struct hisi_clock_data* (*register_clks)(struct platform_device *pdev); ++ void (*unregister_clks)(struct platform_device *pdev); ++}; ++ ++struct hisi_crg_dev { ++ struct hisi_clock_data *clk_data; ++ struct hisi_reset_controller *rstc; ++ const struct hisi_crg_funcs *funcs; ++}; ++ ++#endif /* __HISI_CRG_H */ +diff --git a/drivers/clk/hisilicon/reset.c b/drivers/clk/hisilicon/reset.c +index 2a5015c..7e25ea9 100644 +--- a/drivers/clk/hisilicon/reset.c ++++ b/drivers/clk/hisilicon/reset.c +@@ -99,6 +99,34 @@ static const struct reset_control_ops hisi_reset_ops = { + .deassert = hisi_reset_deassert, + }; + ++#ifdef CONFIG_ARCH_HISI_BVT ++int __init hibvt_reset_init(struct device_node *np, ++ int nr_rsts) ++{ ++ struct hisi_reset_controller *rstc; ++ ++ rstc = kzalloc(sizeof(*rstc), GFP_KERNEL); ++ if (!rstc) ++ return -ENOMEM; ++ ++ rstc->membase = of_iomap(np, 0); ++ if (!rstc->membase) ++ return -EINVAL; ++ ++ spin_lock_init(&rstc->lock); ++ ++ rstc->rcdev.owner = THIS_MODULE; ++ rstc->rcdev.nr_resets = nr_rsts; ++ rstc->rcdev.ops = &hisi_reset_ops; ++ rstc->rcdev.of_node = np; ++ rstc->rcdev.of_reset_n_cells = 2; ++ rstc->rcdev.of_xlate = hisi_reset_of_xlate; ++ ++ return reset_controller_register(&rstc->rcdev); ++} ++EXPORT_SYMBOL_GPL(hibvt_reset_init); ++#endif ++ + struct hisi_reset_controller *hisi_reset_init(struct platform_device *pdev) + { + struct hisi_reset_controller *rstc; +diff --git a/drivers/clk/hisilicon/reset.h b/drivers/clk/hisilicon/reset.h +index 9a69374..d6faba7 100644 +--- a/drivers/clk/hisilicon/reset.h ++++ b/drivers/clk/hisilicon/reset.h +@@ -23,6 +23,9 @@ struct hisi_reset_controller; + + #ifdef CONFIG_RESET_CONTROLLER + struct hisi_reset_controller *hisi_reset_init(struct platform_device *pdev); ++#ifdef CONFIG_ARCH_HISI_BVT ++int __init hibvt_reset_init(struct device_node *np, int nr_rsts); ++#endif + void hisi_reset_exit(struct hisi_reset_controller *rstc); + #else + static inline +diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig +index e2c6e43..ae14e22 100644 +--- a/drivers/clocksource/Kconfig ++++ b/drivers/clocksource/Kconfig +@@ -305,6 +305,14 @@ config ARM_ARCH_TIMER_EVTSTREAM + This must be disabled for hardware validation purposes to detect any + hardware anomalies of missing events. + ++config ARM_ARCH_TIMER_VCT_ACCESS ++ bool "Support for ARM architected timer virtual counter access in userspace" ++ default !ARM64 ++ depends on ARM_ARCH_TIMER ++ help ++ This option enables support for reading the ARM architected timer's ++ virtual counter in userspace. ++ + config FSL_ERRATUM_A008585 + bool "Workaround for Freescale/NXP Erratum A-008585" + default y +@@ -328,6 +336,12 @@ config ARM_TIMER_SP804 + select CLKSRC_MMIO + select CLKSRC_OF if OF + ++config TIMER_HISP804 ++ bool "Support for hisilicon SP804 module" ++ depends on GENERIC_SCHED_CLOCK && CLKDEV_LOOKUP && SMP ++ select CLKSRC_MMIO ++ select CLKSRC_OF if OF ++ + config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK + bool + depends on ARM_GLOBAL_TIMER +diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile +index cf87f40..7d9c313 100644 +--- a/drivers/clocksource/Makefile ++++ b/drivers/clocksource/Makefile +@@ -55,6 +55,7 @@ obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o + obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o + obj-$(CONFIG_ARMV7M_SYSTICK) += armv7m_systick.o + obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp804.o ++obj-$(CONFIG_TIMER_HISP804) += timer-hisp804.o + obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o + obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o + obj-$(CONFIG_KEYSTONE_TIMER) += timer-keystone.o +diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c +index a2503db..e3bc592 100644 +--- a/drivers/clocksource/arm_arch_timer.c ++++ b/drivers/clocksource/arm_arch_timer.c +@@ -449,7 +449,10 @@ static void arch_counter_set_user_access(void) + | ARCH_TIMER_USR_PCT_ACCESS_EN); + + /* Enable user access to the virtual counter */ +- cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; ++ if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_VCT_ACCESS)) ++ cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; ++ else ++ cntkctl &= ~ARCH_TIMER_USR_VCT_ACCESS_EN; + + arch_timer_set_cntkctl(cntkctl); + } +diff --git a/drivers/clocksource/timer-hisp804.c b/drivers/clocksource/timer-hisp804.c +new file mode 100644 +index 0000000..c562bb5 +--- /dev/null ++++ b/drivers/clocksource/timer-hisp804.c +@@ -0,0 +1,370 @@ ++/****************************************************************************** ++ * Copyright (C) 2017 Hisilicon Technologies CO.,LTD. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++ * Create By Cai Zhiying 2017.2.4 ++ * ++******************************************************************************/ ++ ++#define pr_fmt(fmt) "hisp804: " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TIMER_LOAD 0x00 /* ACVR rw */ ++#define TIMER_VALUE 0x04 /* ACVR ro */ ++#define TIMER_CTRL 0x08 /* ACVR rw */ ++#define TIMER_CTRL_ONESHOT (1 << 0) /* CVR */ ++#define TIMER_CTRL_32BIT (1 << 1) /* CVR */ ++#define TIMER_CTRL_DIV1 (0 << 2) /* ACVR */ ++#define TIMER_CTRL_DIV16 (1 << 2) /* ACVR */ ++#define TIMER_CTRL_DIV256 (2 << 2) /* ACVR */ ++#define TIMER_CTRL_IE (1 << 5) /* VR */ ++#define TIMER_CTRL_PERIODIC (1 << 6) /* ACVR */ ++#define TIMER_CTRL_ENABLE (1 << 7) /* ACVR */ ++ ++#define TIMER_INTCLR 0x0c /* ACVR wo */ ++#define TIMER_RIS 0x10 /* CVR ro */ ++#define TIMER_MIS 0x14 /* CVR ro */ ++#define TIMER_BGLOAD 0x18 /* CVR rw */ ++ ++struct hisp804_clocksource { ++ void __iomem *base; ++ struct clocksource clksrc; ++}; ++ ++#define to_hiclksrc(e) \ ++ container_of(e, struct hisp804_clocksource, clksrc) ++ ++static struct hisp804_clocksource hisp804_clksrc; ++ ++static void __iomem *hisp804_sched_clock_base; ++ ++struct hisp804_clockevent_device { ++ struct clock_event_device clkevt; ++ struct irqaction action; ++ void __iomem *base; ++ unsigned long rate; ++ unsigned long reload; ++ char name[16]; ++}; ++ ++#define to_hiclkevt(e) \ ++ container_of(e, struct hisp804_clockevent_device, clkevt) ++ ++static struct hisp804_clockevent_device __percpu *hisp804_clkevt; ++ ++/******************************************************************************/ ++ ++static void hisp804_clocksource_enable(void __iomem *base) ++{ ++ writel(0, base + TIMER_CTRL); ++ writel(0xffffffff, base + TIMER_LOAD); ++ writel(0xffffffff, base + TIMER_VALUE); ++ writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, ++ base + TIMER_CTRL); ++} ++/******************************************************************************/ ++ ++static void hisp804_clocksource_resume(struct clocksource *cs) ++{ ++ hisp804_clocksource_enable(to_hiclksrc(cs)->base); ++} ++/******************************************************************************/ ++ ++static u64 notrace hisp804_sched_clock_read(void) ++{ ++ return ~readl_relaxed(hisp804_sched_clock_base + TIMER_VALUE); ++} ++/******************************************************************************/ ++ ++static cycle_t hisp804_clocksource_read(struct clocksource *cs) ++{ ++ return ~(cycle_t)readl_relaxed(to_hiclksrc(cs)->base + TIMER_VALUE); ++} ++/******************************************************************************/ ++ ++static void __init hisp804_clocksource_init(void __iomem *base, ++ unsigned long rate) ++{ ++ hisp804_clksrc.base = base; ++ hisp804_clksrc.clksrc.name = "hisp804"; ++ hisp804_clksrc.clksrc.rating = 499; ++ hisp804_clksrc.clksrc.read = hisp804_clocksource_read; ++ hisp804_clksrc.clksrc.resume = hisp804_clocksource_resume; ++ hisp804_clksrc.clksrc.mask = CLOCKSOURCE_MASK(32); ++ hisp804_clksrc.clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS; ++ ++ hisp804_clocksource_enable(base); ++ ++ clocksource_register_hz(&hisp804_clksrc.clksrc, rate); ++ ++ hisp804_sched_clock_base = base; ++ sched_clock_register(hisp804_sched_clock_read, 32, rate); ++} ++/******************************************************************************/ ++ ++static int hisp804_clockevent_shutdown(struct clock_event_device *clkevt) ++{ ++ struct hisp804_clockevent_device *hiclkevt = to_hiclkevt(clkevt); ++ ++ writel(0, hiclkevt->base + TIMER_CTRL); ++ ++ return 0; ++} ++/******************************************************************************/ ++ ++static int hisp804_clockevent_set_next_event(unsigned long next, ++ struct clock_event_device *clkevt) ++{ ++ unsigned long ctrl; ++ struct hisp804_clockevent_device *hiclkevt = to_hiclkevt(clkevt); ++ ++ writel(TIMER_CTRL_32BIT, hiclkevt->base + TIMER_CTRL); ++ ++ writel(next, hiclkevt->base + TIMER_LOAD); ++ writel(next, hiclkevt->base + TIMER_LOAD); ++ ++ ctrl = TIMER_CTRL_32BIT | ++ TIMER_CTRL_IE | ++ TIMER_CTRL_ONESHOT | ++ TIMER_CTRL_ENABLE; ++ writel(ctrl, hiclkevt->base + TIMER_CTRL); ++ ++ return 0; ++} ++/******************************************************************************/ ++ ++static int sp804_clockevent_set_periodic(struct clock_event_device *clkevt) ++{ ++ unsigned long ctrl; ++ struct hisp804_clockevent_device *hiclkevt = to_hiclkevt(clkevt); ++ ++ writel(TIMER_CTRL_32BIT, hiclkevt->base + TIMER_CTRL); ++ ++ writel(hiclkevt->reload, hiclkevt->base + TIMER_LOAD); ++ writel(hiclkevt->reload, hiclkevt->base + TIMER_LOAD); ++ ++ ctrl = TIMER_CTRL_32BIT | ++ TIMER_CTRL_IE | ++ TIMER_CTRL_PERIODIC | ++ TIMER_CTRL_ENABLE; ++ writel(ctrl, hiclkevt->base + TIMER_CTRL); ++ ++ return 0; ++} ++/******************************************************************************/ ++ ++static irqreturn_t hisp804_clockevent_timer_interrupt(int irq, void *dev_id) ++{ ++ struct clock_event_device *clkevt = dev_id; ++ struct hisp804_clockevent_device *hiclkevt = to_hiclkevt(clkevt); ++ ++ /* clear the interrupt */ ++ writel(1, hiclkevt->base + TIMER_INTCLR); ++ ++ clkevt->event_handler(clkevt); ++ ++ return IRQ_HANDLED; ++} ++/******************************************************************************/ ++ ++static int hisp804_clockevent_setup(struct hisp804_clockevent_device *hiclkevt) ++{ ++ struct clock_event_device *clkevt = &hiclkevt->clkevt; ++ ++ writel(0, hiclkevt->base + TIMER_CTRL); ++ ++ BUG_ON(setup_irq(clkevt->irq, &hiclkevt->action)); ++ ++ irq_force_affinity(clkevt->irq, clkevt->cpumask); ++ ++ clockevents_config_and_register(clkevt, hiclkevt->rate, 0xf, ++ 0x7fffffff); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static void hisp804_clockevent_stop(struct hisp804_clockevent_device *hiclkevt) ++{ ++ struct clock_event_device *clkevt = &hiclkevt->clkevt; ++ ++ pr_info("disable IRQ%d cpu #%d\n", clkevt->irq, smp_processor_id()); ++ ++ disable_irq(clkevt->irq); ++ ++ remove_irq(clkevt->irq, &hiclkevt->action); ++ ++ clkevt->set_state_shutdown(clkevt); ++} ++/******************************************************************************/ ++ ++static int hisp804_clockevent_cpu_notify(struct notifier_block *self, ++ unsigned long action, void *hcpu) ++{ ++ /* ++ * Grab cpu pointer in each case to avoid spurious ++ * preemptible warnings ++ */ ++ switch (action & ~CPU_TASKS_FROZEN) { ++ case CPU_ONLINE: ++ hisp804_clockevent_setup(this_cpu_ptr(hisp804_clkevt)); ++ break; ++ case CPU_DEAD: ++ hisp804_clockevent_stop(this_cpu_ptr(hisp804_clkevt)); ++ break; ++ } ++ ++ return NOTIFY_OK; ++} ++/*****************************************************************************/ ++ ++static struct notifier_block hisp804_clockevent_cpu_nb = { ++ .notifier_call = hisp804_clockevent_cpu_notify, ++}; ++/*****************************************************************************/ ++ ++static void __init clockevent_init(struct hisp804_clockevent_device *hiclkevt, ++ void __iomem *base, int irq, int cpu, ++ unsigned long rate, unsigned long reload) ++{ ++ struct irqaction *action; ++ struct clock_event_device *clkevt; ++ ++ hiclkevt->base = base; ++ hiclkevt->rate = rate; ++ hiclkevt->reload = reload; ++ snprintf(hiclkevt->name, sizeof(hiclkevt->name), "clockevent %d", cpu); ++ ++ clkevt = &hiclkevt->clkevt; ++ ++ clkevt->name = hiclkevt->name; ++ clkevt->cpumask = cpumask_of(cpu); ++ clkevt->irq = irq; ++ clkevt->set_next_event = hisp804_clockevent_set_next_event; ++ clkevt->set_state_shutdown = hisp804_clockevent_shutdown; ++ clkevt->set_state_periodic = sp804_clockevent_set_periodic; ++ clkevt->features = CLOCK_EVT_FEAT_PERIODIC | ++ CLOCK_EVT_FEAT_ONESHOT | ++ CLOCK_EVT_FEAT_DYNIRQ; ++ clkevt->rating = 400; ++ ++ action = &hiclkevt->action; ++ ++ action->name = hiclkevt->name; ++ action->dev_id = hiclkevt; ++ action->irq = irq; ++ action->flags = IRQF_TIMER | IRQF_NOBALANCING; ++ action->handler = hisp804_clockevent_timer_interrupt; ++} ++/******************************************************************************/ ++ ++static int __init hisp804_timer_init(struct device_node *node) ++{ ++ int ret, irq, ix, nr_cpus; ++ struct clk *clk1, *clk2; ++ void __iomem *base; ++ unsigned long rate1, rate2, reload1, reload2; ++ ++ hisp804_clkevt = alloc_percpu(struct hisp804_clockevent_device); ++ if (!hisp804_clkevt) { ++ pr_err("can't alloc memory.\n"); ++ goto out; ++ } ++ ++ clk1 = of_clk_get(node, 0); ++ if (IS_ERR(clk1)) ++ goto out_free; ++ ++ clk_prepare_enable(clk1); ++ ++ rate1 = clk_get_rate(clk1); ++ reload1 = DIV_ROUND_CLOSEST(rate1, HZ); ++ ++ /* Get the 2nd clock if the timer has 3 timer clocks */ ++ if (of_count_phandle_with_args(node, "clocks", "#clock-cells") == 3) { ++ clk2 = of_clk_get(node, 1); ++ if (IS_ERR(clk2)) { ++ pr_err("hisp804: %s clock not found: %d\n", node->name, ++ (int)PTR_ERR(clk2)); ++ goto out_free; ++ } ++ clk_prepare_enable(clk2); ++ rate2 = clk_get_rate(clk2); ++ reload2 = DIV_ROUND_CLOSEST(rate2, HZ); ++ } else { ++ /* clk2 = clk1; */ ++ rate2 = rate1; ++ reload2 = rate2; ++ } ++ ++ nr_cpus = of_irq_count(node); ++ if (nr_cpus > num_possible_cpus()) ++ nr_cpus = num_possible_cpus(); ++ ++ /* local timer for each CPU */ ++ for (ix = 0; ix < nr_cpus; ix++) { ++ irq = irq_of_parse_and_map(node, ix); ++ base = of_iomap(node, ix + 1); ++ if (!base) { ++ pr_err("can't iomap timer %d\n", ix); ++ while (--ix >= 0) ++ iounmap(per_cpu_ptr(hisp804_clkevt, ix)->base); ++ goto out_free; ++ } ++ ++ clockevent_init(per_cpu_ptr(hisp804_clkevt, ix), base, irq, ++ ix, rate2, reload2); ++ } ++ ++ base = of_iomap(node, 0); ++ if (!base) { ++ pr_err("can't iomap timer %d\n", 0); ++ goto out_unmap; ++ } ++ ++ hisp804_clocksource_init(base, rate1); ++ ++ ret = register_cpu_notifier(&hisp804_clockevent_cpu_nb); ++ if (ret) ++ goto out_notifier; ++ ++ hisp804_clockevent_setup(this_cpu_ptr(hisp804_clkevt)); ++ ++ return 0; ++ ++out_notifier: ++ iounmap(base); ++out_unmap: ++ for (ix = 0; ix < nr_irqs; ix++) ++ iounmap(per_cpu_ptr(hisp804_clkevt, ix)->base); ++out_free: ++ free_percpu(hisp804_clkevt); ++out: ++ return -ENODEV; ++} ++CLOCKSOURCE_OF_DECLARE(hisp804, "hisilicon,hisp804",hisp804_timer_init); ++ +diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c +index d078633..46e9055 100644 +--- a/drivers/clocksource/timer-sp804.c ++++ b/drivers/clocksource/timer-sp804.c +@@ -235,6 +235,10 @@ static int __init sp804_of_init(struct device_node *np) + writel(0, base + TIMER_CTRL); + writel(0, base + TIMER_2_BASE + TIMER_CTRL); + ++ /* Ensure timer interrupts are clear */ ++ writel(1, base + TIMER_INTCLR); ++ writel(1, base + TIMER_2_BASE + TIMER_INTCLR); ++ + if (initialized || !of_device_is_available(np)) { + ret = -EINVAL; + goto err; +diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig +index 7e48eb5..bc0cdf5 100644 +--- a/drivers/cpuidle/Kconfig ++++ b/drivers/cpuidle/Kconfig +@@ -27,10 +27,15 @@ config DT_IDLE_STATES + bool + + menu "ARM CPU Idle Drivers" +-depends on ARM || ARM64 ++depends on ARM + source "drivers/cpuidle/Kconfig.arm" + endmenu + ++menu "ARM64 CPU Idle Drivers" ++depends on ARM64 ++source "drivers/cpuidle/Kconfig.arm64" ++endmenu ++ + menu "MIPS CPU Idle Drivers" + depends on MIPS + source "drivers/cpuidle/Kconfig.mips" +diff --git a/drivers/cpuidle/Kconfig.arm64 b/drivers/cpuidle/Kconfig.arm64 +new file mode 100644 +index 0000000..6effb36 +--- /dev/null ++++ b/drivers/cpuidle/Kconfig.arm64 +@@ -0,0 +1,13 @@ ++# ++# ARM64 CPU Idle drivers ++# ++ ++config ARM64_CPUIDLE ++ bool "Generic ARM64 CPU idle Driver" ++ select DT_IDLE_STATES ++ help ++ Select this to enable generic cpuidle driver for ARM64. ++ It provides a generic idle driver whose idle states are configured ++ at run-time through DT nodes. The CPUidle suspend backend is ++ initialized by calling the CPU operations init idle hook ++ provided by architecture code. +diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile +index 3ba81b1..8418be2 100644 +--- a/drivers/cpuidle/Makefile ++++ b/drivers/cpuidle/Makefile +@@ -24,6 +24,10 @@ obj-$(CONFIG_ARM_CPUIDLE) += cpuidle-arm.o + obj-$(CONFIG_MIPS_CPS_CPUIDLE) += cpuidle-cps.o + + ############################################################################### ++# ARM64 drivers ++obj-$(CONFIG_ARM64_CPUIDLE) += cpuidle-arm64.o ++ ++############################################################################### + # POWERPC drivers + obj-$(CONFIG_PSERIES_CPUIDLE) += cpuidle-pseries.o + obj-$(CONFIG_POWERNV_CPUIDLE) += cpuidle-powernv.o +diff --git a/drivers/cpuidle/cpuidle-arm64.c b/drivers/cpuidle/cpuidle-arm64.c +new file mode 100644 +index 0000000..39b37d9 +--- /dev/null ++++ b/drivers/cpuidle/cpuidle-arm64.c +@@ -0,0 +1,241 @@ ++/* ++ * ARM64 generic CPU idle driver. ++ * ++ * Copyright (C) 2014 ARM Ltd. ++ * Author: Lorenzo Pieralisi ++ * ++ * 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. ++ */ ++ ++#define pr_fmt(fmt) "CPUidle arm64: " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "dt_idle_states.h" ++ ++//#define ARM64_PMC_PWRDN_DEBUG ++ ++#define CPU_PMC_BASE 0x1D820000 ++/* TODO: should be adapted for boot form cluster1(cpu2). should use mpidr. */ ++#define PMC_CORE_PWRDN_REQ(cpu) ((cpu) << 8) /* core power down request */ ++#define PMC_CORE_PWRDN_MODE(cpu) (((cpu) << 8) + 0x4) /* core power down mode */ ++#define PMC_CORE_PWRDN_PARAM(cpu) (((cpu) << 8) + 0x8) /* core power down param */ ++#define PMC_CORE_PWRDN_CNT_EN(cpu) (((cpu) << 8) + 0xc) /* core power down/on counter enable */ ++#define PMC_CORE_PWRDN_CNT(cpu) (((cpu) << 8) + 0x10) /* core power down time */ ++#define PMC_CORE_PWRON_CNT(cpu) (((cpu) << 8) + 0x14) /* core power on time */ ++#define PMC_CORE_PWRDN_DONE_CNT(cpu) (((cpu) << 8) + 0x18) /* core power off time */ ++#define PMC_CORE_PWR_STATUS(cpu) (((cpu) << 8) + 0x1c) /* core power status */ ++ ++#define PMC_CLUSTER_PWRDN_REQ(cls) (0x1000 + ((cls) << 8)) /* cluster power down request */ ++#define PMC_CLUSTER_PWRDN_MODE(cls) ((0x1000 + ((cls) << 8)) + 0x4) /* cluster power down mode */ ++#define PMC_CLUSTER_PWRDN_PARAM(cls) ((0x1000 + ((cls) << 8)) + 0x8) /* cluster power down param */ ++#define PMC_CLUSTER_PWR_STATUS(cls) ((0x1000 + ((cls) << 8)) + 0xc) /* cluster power status */ ++#define PMC_CLUSTER_PWRDN_CNT_EN(cls) ((0x1000 + ((cls) << 8)) + 0x10) /* cluster power down/on counter enable */ ++#define PMC_CLUSTER_PWRDN_CNT(cls) ((0x1000 + ((cls) << 8)) + 0x14) /* cluster power down time */ ++#define PMC_CLUSTER_PWRON_CNT(cls) ((0x1000 + ((cls) << 8)) + 0x18) /* cluster power on time */ ++#define PMC_CLUSTER_PWRDN_DONE_CNT(cls) ((0x1000 + ((cls) << 8)) + 0x1c) /* cluster power off time */ ++ ++#ifdef ARM64_PMC_PWRDN_DEBUG ++static void arm64_cpu_pmc_display_counter(void) ++{ ++ int cpu = smp_processor_id(); ++ unsigned int cluster = cpu >> 1; ++ unsigned int cpu_pwrdn_cnt; ++ unsigned int cpu_pwron_cnt; ++ unsigned int cpu_pwrdn_done_cnt; ++ unsigned int cluster_pwrdn_cnt = 0; ++ unsigned int cluster_pwron_cnt = 0; ++ unsigned int cluster_pwrdn_done_cnt = 0; ++ static int counter_cpu[4]; ++ static int counter_cluster[4]; ++ void __iomem *pmc_virt = ioremap(CPU_PMC_BASE, PAGE_SIZE * 2); ++ ++ writel(0x0, pmc_virt + PMC_CORE_PWRDN_CNT_EN(cpu)); /* disable cpu power on/down counter */ ++ ++ cpu_pwrdn_cnt = readl(pmc_virt + PMC_CORE_PWRDN_CNT(cpu)); ++ cpu_pwron_cnt = readl(pmc_virt + PMC_CORE_PWRON_CNT(cpu)); ++ cpu_pwrdn_done_cnt = readl(pmc_virt + PMC_CORE_PWRDN_DONE_CNT(cpu)); ++ ++ writel(0x0, pmc_virt + PMC_CORE_PWRDN_CNT(cpu)); /* clean counter */ ++ writel(0x0, pmc_virt + PMC_CORE_PWRON_CNT(cpu)); ++ writel(0x0, pmc_virt + PMC_CORE_PWRDN_DONE_CNT(cpu)); ++ ++ if (counter_cpu[cpu % 4] % 2000 == 0) { ++ printk("[%s][%d] cpu[%d] pwrdn_cnt[%8d]us pwron_cnt[%8d]us pwrdn_done_cnt[%8d]us count[%8d][%8d][%8d][%8d]\n", __func__, __LINE__, ++ cpu, cpu_pwrdn_cnt * 5, cpu_pwron_cnt * 5, cpu_pwrdn_done_cnt * 5, ++ counter_cpu[0], counter_cpu[1], counter_cpu[2], counter_cpu[3]); ++ } ++ counter_cpu[cpu % 4]++; ++ ++ if (readl(pmc_virt + PMC_CLUSTER_PWRDN_CNT_EN(cluster))) { ++ writel(0x0, pmc_virt + PMC_CLUSTER_PWRDN_CNT_EN(cluster)); /* disable cluster power on/down counter */ ++ cluster_pwrdn_cnt = readl(pmc_virt + PMC_CLUSTER_PWRDN_CNT(cluster)); ++ cluster_pwron_cnt = readl(pmc_virt + PMC_CLUSTER_PWRON_CNT(cluster)); ++ cluster_pwrdn_done_cnt = readl(pmc_virt + PMC_CLUSTER_PWRDN_DONE_CNT(cluster)); ++ ++ writel(0x0, pmc_virt + PMC_CLUSTER_PWRDN_CNT(cluster)); /* clean counter */ ++ writel(0x0, pmc_virt + PMC_CLUSTER_PWRON_CNT(cluster)); ++ writel(0x0, pmc_virt + PMC_CLUSTER_PWRDN_DONE_CNT(cluster)); ++ ++ if (counter_cluster[cluster % 2] % 2000 == 0) { ++ printk("[%s][%d] cluster[%d] pwrdn_cnt[%8d]us pwron_cnt[%8d]us pwrdn_done_cnt[%8d]us count[%8d][%8d]\n", __func__, __LINE__, ++ cluster, cluster_pwrdn_cnt * 5, cluster_pwron_cnt * 5, cluster_pwrdn_done_cnt * 5, ++ counter_cluster[0], counter_cluster[1]); ++ } ++ counter_cluster[cluster % 2]++; ++ } ++ ++ iounmap(pmc_virt); ++} ++#endif ++ ++ ++/* ++ * arm64_enter_idle_state - Programs CPU to enter the specified state ++ * ++ * dev: cpuidle device ++ * drv: cpuidle driver ++ * idx: state index ++ * ++ * Called from the CPUidle framework to program the device to the ++ * specified target state selected by the governor. ++ */ ++static int arm64_enter_idle_state(struct cpuidle_device *dev, ++ struct cpuidle_driver *drv, int idx) ++{ ++ int ret; ++ ++ if (!idx) { ++ cpu_do_idle(); ++ return idx; ++ } ++ ++ ret = cpu_pm_enter(); ++ if (!ret) { ++ /* ++ * Pass idle state index to cpu_suspend which in turn will ++ * call the CPU ops suspend protocol with idle index as a ++ * parameter. ++ */ ++ ret = arm_cpuidle_suspend(idx); ++ ++ cpu_pm_exit(); ++ ++#ifdef ARM64_PMC_PWRDN_DEBUG ++ arm64_cpu_pmc_display_counter(); ++#endif ++ } ++ ++ return ret ? -1 : idx; ++} ++ ++static struct cpuidle_driver arm64_idle_driver = { ++ .name = "arm64_idle", ++ .owner = THIS_MODULE, ++ /* ++ * State at index 0 is standby wfi and considered standard ++ * on all ARM platforms. If in some platforms simple wfi ++ * can't be used as "state 0", DT bindings must be implemented ++ * to work around this issue and allow installing a special ++ * handler for idle state index 0. ++ */ ++ .states[0] = { ++ .enter = arm64_enter_idle_state, ++ .exit_latency = 1, ++ .target_residency = 1, ++ .power_usage = UINT_MAX, ++ .flags = CPUIDLE_FLAG_TIME_VALID, ++ .name = "WFI", ++ .desc = "ARM64 WFI", ++ }, ++}; ++ ++static const struct of_device_id arm64_idle_state_match[] __initconst = { ++ { .compatible = "arm,idle-state", ++ .data = arm64_enter_idle_state }, ++ { }, ++}; ++ ++static void arm64_cpu_pmc_init(int cpu) ++{ ++ void __iomem *pmc_virt = ioremap(CPU_PMC_BASE, PAGE_SIZE * 2); ++ unsigned int cluster = cpu >> 1; ++ unsigned int cpu_param = readl(pmc_virt + PMC_CORE_PWRDN_PARAM(cpu)); ++ unsigned int cluster_param = readl(pmc_virt + PMC_CLUSTER_PWRDN_PARAM(cluster)); ++ ++ printk("%s cpu:%d enter\n", __func__, cpu); ++ ++ /* cpu */ ++ cpu_param = (cpu_param & 0xffff) | 0x80800000; ++ writel(cpu_param, pmc_virt + PMC_CORE_PWRDN_PARAM(cpu)); /* power down/on wait 128ns */ ++ writel(readl(pmc_virt + PMC_CORE_PWRDN_MODE(cpu)) | 0x1, pmc_virt + PMC_CORE_PWRDN_MODE(cpu)); /* cpu auto power off mode */ ++ ++ /* cluster */ ++ cluster_param = (cluster_param & 0xffff) | 0x01010000; ++ writel(cluster_param, pmc_virt + PMC_CLUSTER_PWRDN_PARAM(cluster)); /* power down/on wait 100ns */ ++ writel(0x0, pmc_virt + PMC_CLUSTER_PWRDN_CNT(cluster)); /* clean counter */ ++ writel(readl(pmc_virt + PMC_CLUSTER_PWRDN_MODE(cluster)) | 0x1, pmc_virt + PMC_CLUSTER_PWRDN_MODE(cluster)); /* cluster auto power off mode */ ++ ++ iounmap(pmc_virt); ++} ++ ++/* ++ * arm64_idle_init ++ * ++ * Registers the arm64 specific cpuidle driver with the cpuidle ++ * framework. It relies on core code to parse the idle states ++ * and initialize them using driver data structures accordingly. ++ */ ++static int __init arm64_idle_init(void) ++{ ++ int cpu, ret; ++ struct cpuidle_driver *drv = &arm64_idle_driver; ++ ++ /* ++ * Initialize idle states data, starting at index 1. ++ * This driver is DT only, if no DT idle states are detected (ret == 0) ++ * let the driver initialization fail accordingly since there is no ++ * reason to initialize the idle driver if only wfi is supported. ++ */ ++ ret = dt_init_idle_driver(drv, arm64_idle_state_match, 1); ++ if (ret <= 0) { ++ if (ret) ++ pr_err("failed to initialize idle states\n"); ++ return ret ? : -ENODEV; ++ } ++ ++ /* ++ * Call arch CPU operations in order to initialize ++ * idle states suspend back-end specific data ++ */ ++ for_each_possible_cpu(cpu) { ++ ++ ret = arm_cpuidle_init(cpu); ++ if (ret) { ++ pr_err("CPU %d failed to init idle CPU ops\n", cpu); ++ return ret; ++ } ++ ++ arm64_cpu_pmc_init(cpu); ++ } ++ ++ ret = cpuidle_register(drv, NULL); ++ if (ret) { ++ pr_err("failed to register cpuidle driver\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++device_initcall(arm64_idle_init); +diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig +index 141aefb..f8ff2e9 100644 +--- a/drivers/dma/Kconfig ++++ b/drivers/dma/Kconfig +@@ -564,6 +564,19 @@ config ZX_DMA + help + Support the DMA engine for ZTE ZX296702 platform devices. + ++config HIEDMACV310 ++ tristate "Hisilicon EDMAC Controller support" ++ depends on (ARCH_HISI || ARCH_HI3559AV100) ++ select DMA_ENGINE ++ select DMA_VIRTUAL_CHANNELS ++ help ++ The Direction Memory Access(EDMA) is a high-speed data transfer ++ operation. It supports data read/write between peripherals and ++ memories without using the CPU. ++ Hisilicon EDMA Controller(EDMAC) directly transfers data between ++ a memory and a peripheral, between peripherals, or between memories. ++ This avoids the CPU intervention and reduces the interrupt handling ++ overhead of the CPU. + + # driver files + source "drivers/dma/bestcomm/Kconfig" +diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile +index e4dc9ca..b6c8cca 100644 +--- a/drivers/dma/Makefile ++++ b/drivers/dma/Makefile +@@ -67,6 +67,7 @@ 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_HIEDMACV310) += hiedmacv310.o + + obj-y += qcom/ + obj-y += xilinx/ +diff --git a/drivers/dma/hiedmacv310.c b/drivers/dma/hiedmacv310.c +new file mode 100644 +index 0000000..c6f5c26 +--- /dev/null ++++ b/drivers/dma/hiedmacv310.c +@@ -0,0 +1,1256 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hiedmacv310.h" ++#include "dmaengine.h" ++#include "virt-dma.h" ++ ++#define DRIVER_NAME "hiedmacv310" ++ ++int hiedmacv310_trace_level = HIEDMACV310_TRACE_LEVEL; ++ ++typedef struct hiedmac_lli { ++ u64 next_lli; ++ u32 reserved[5]; ++ u32 count; ++ u64 src_addr; ++ u64 dest_addr; ++ u32 config; ++ u32 pad[3]; ++} hiedmac_lli; ++ ++struct hiedmac_sg { ++ dma_addr_t src_addr; ++ dma_addr_t dst_addr; ++ size_t len; ++ struct list_head node; ++}; ++ ++struct transfer_desc { ++ struct virt_dma_desc virt_desc; ++ ++ dma_addr_t llis_busaddr; ++ u32 *llis_vaddr; ++ u32 ccfg; ++ size_t size; ++ bool done; ++ bool cyclic; ++}; ++ ++enum edmac_dma_chan_state { ++ HIEDMAC_CHAN_IDLE, ++ HIEDMAC_CHAN_RUNNING, ++ HIEDMAC_CHAN_PAUSED, ++ HIEDMAC_CHAN_WAITING, ++}; ++ ++struct hiedmacv310_dma_chan { ++ bool slave; ++ int signal; ++ int id; ++ struct virt_dma_chan virt_chan; ++ struct hiedmacv310_phy_chan *phychan; ++ struct dma_slave_config cfg; ++ struct transfer_desc *at; ++ struct hiedmacv310_driver_data *host; ++ enum edmac_dma_chan_state state; ++}; ++ ++struct hiedmacv310_phy_chan { ++ unsigned int id; ++ void __iomem *base; ++ spinlock_t lock; ++ struct hiedmacv310_dma_chan *serving; ++}; ++ ++struct hiedmacv310_driver_data { ++ struct platform_device *dev; ++ struct dma_device slave; ++ struct dma_device memcpy; ++ void __iomem *base; ++ struct regmap *misc_regmap; ++ void __iomem *crg_ctrl; ++ struct hiedmacv310_phy_chan *phy_chans; ++ struct dma_pool *pool; ++ unsigned int misc_ctrl_base; ++ unsigned int irq; ++ unsigned int id; ++ struct clk *clk; ++ struct clk *axi_clk; ++ struct reset_control *rstc; ++ unsigned int channels; ++ unsigned int slave_requests; ++ unsigned int max_transfer_size; ++}; ++ ++#ifdef DEBUG_HIEDMAC ++void dump_lli(u32 *llis_vaddr, unsigned int num) ++{ ++ ++ hiedmac_lli *plli = (hiedmac_lli *)llis_vaddr; ++ unsigned int i; ++ ++ hiedmacv310_trace(3, "lli num = 0%d\n", num); ++ for (i = 0;i < num; i++) ++ { ++ printk("lli%d:lli_L: 0x%llx\n", i, plli[i].next_lli & 0xffffffff); ++ printk("lli%d:lli_H: 0x%llx\n", i, plli[i].next_lli >> 32 & 0xffffffff); ++ printk("lli%d:count: 0x%llx\n", i, plli[i].count); ++ printk("lli%d:src_addr_L: 0x%llx\n", i, plli[i].src_addr & 0xffffffff); ++ printk("lli%d:src_addr_H: 0x%llx\n", i, plli[i].src_addr >> 32 & 0xffffffff); ++ printk("lli%d:dst_addr_L: 0x%llx\n", i, plli[i].dest_addr & 0xffffffff); ++ printk("lli%d:dst_addr_H: 0x%llx\n", i, plli[i].dest_addr >> 32 & 0xffffffff); ++ printk("lli%d:CONFIG: 0x%llx\n", i, plli[i].config); ++ } ++} ++ ++#else ++void dump_lli(u32 *llis_vaddr, unsigned int num) ++{ ++} ++#endif ++ ++static inline struct hiedmacv310_dma_chan *to_edamc_chan(struct dma_chan *chan) ++{ ++ return container_of(chan, struct hiedmacv310_dma_chan, virt_chan.chan); ++} ++ ++static inline struct transfer_desc *to_edmac_transfer_desc(struct dma_async_tx_descriptor *tx) ++{ ++ return container_of(tx, struct transfer_desc, virt_desc.tx); ++} ++ ++static struct dma_chan *hiedmac_find_chan_id(struct hiedmacv310_driver_data *hiedmac, ++ int request_num) ++{ ++ struct hiedmacv310_dma_chan *edmac_dma_chan = NULL; ++ ++ list_for_each_entry(edmac_dma_chan, &hiedmac->slave.channels, virt_chan.chan.device_node) { ++ if (edmac_dma_chan->id == request_num) ++ return &edmac_dma_chan->virt_chan.chan; ++ } ++ return NULL; ++} ++ ++static struct dma_chan *hiedma_of_xlate(struct of_phandle_args *dma_spec, ++ struct of_dma *ofdma) ++{ ++ struct hiedmacv310_driver_data *hiedmac = ofdma->of_dma_data; ++ struct hiedmacv310_dma_chan *edmac_dma_chan = NULL; ++ struct dma_chan *dma_chan; ++ struct regmap *misc = hiedmac->misc_regmap; ++ unsigned int signal = 0, request_num = 0; ++ unsigned int reg = 0, offset = 0; ++ ++ if (!hiedmac) ++ return NULL; ++ ++ if (dma_spec->args_count != 2) { ++ hiedmacv310_error("args count not true!\n"); ++ return NULL; ++ } ++ ++ request_num = dma_spec->args[0]; ++ signal = dma_spec->args[1]; ++ ++ hiedmacv310_trace(3, "host->id = %d,signal = %d, request_num = %d\n",hiedmac->id, signal, request_num); ++ ++ offset = hiedmac->misc_ctrl_base + (request_num & (~0x3)); ++ regmap_read(misc, offset , ®); ++ reg &= ~(0x3f << ((request_num & 0x3) << 3)); ++ reg |= signal << ((request_num & 0x3) << 3); ++ regmap_write(misc, offset, reg); ++ ++ hiedmacv310_trace(3, "offset = 0x%x, reg = 0x%x\n", offset, reg); ++ ++ dma_chan = hiedmac_find_chan_id(hiedmac, request_num); ++ if (!dma_chan) { ++ hiedmacv310_error("DMA slave channel is not found!\n"); ++ return NULL; ++ } ++ ++ edmac_dma_chan = to_edamc_chan(dma_chan); ++ edmac_dma_chan->signal = request_num; ++ ++ return dma_get_slave_channel(dma_chan); ++} ++ ++static int get_of_probe(struct hiedmacv310_driver_data *hiedmac) ++{ ++ struct resource *res; ++ struct platform_device *platdev = hiedmac->dev; ++ struct device_node *np = platdev->dev.of_node; ++ int ret; ++ ++ ret = of_property_read_u32((&platdev->dev)->of_node, ++ "devid",&(hiedmac->id)); ++ if (ret) { ++ hiedmacv310_error("get hiedmac id fail\n"); ++ return -ENODEV; ++ } ++ ++ hiedmac->clk = devm_clk_get(&(platdev->dev), "apb_pclk"); ++ if (IS_ERR(hiedmac->clk)) { ++ return PTR_ERR(hiedmac->clk); ++ } ++ ++ hiedmac->axi_clk = devm_clk_get(&(platdev->dev), "axi_aclk"); ++ if (IS_ERR(hiedmac->axi_clk)) { ++ return PTR_ERR(hiedmac->axi_clk); ++ } ++ ++ hiedmac->rstc = devm_reset_control_get(&(platdev->dev), "dma-reset"); ++ if (IS_ERR(hiedmac->rstc)) ++ return PTR_ERR(hiedmac->rstc); ++ ++ res = platform_get_resource(platdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ hiedmacv310_error("no reg resource\n"); ++ return -ENODEV; ++ } ++ ++ hiedmac->base = devm_ioremap_resource(&(platdev->dev), res); ++ if (IS_ERR(hiedmac->base)) ++ return PTR_ERR(hiedmac->base); ++ ++ hiedmac->misc_regmap = syscon_regmap_lookup_by_phandle(np, "misc_regmap"); ++ if (IS_ERR(hiedmac->misc_regmap)) ++ return PTR_ERR(hiedmac->misc_regmap); ++ ++ ret = of_property_read_u32((&platdev->dev)->of_node, ++ "misc_ctrl_base",&(hiedmac->misc_ctrl_base)); ++ if (ret) { ++ hiedmacv310_error( "get dma-misc_ctrl_base fail\n"); ++ return -ENODEV; ++ } ++ ++ hiedmac->irq = platform_get_irq(platdev, 0); ++ if (unlikely(hiedmac->irq < 0)) ++ return -ENODEV; ++ ++ ret = of_property_read_u32((&platdev->dev)->of_node, ++ "dma-channels",&(hiedmac->channels)); ++ if (ret) { ++ hiedmacv310_error( "get dma-channels fail\n"); ++ return -ENODEV; ++ } ++ ret = of_property_read_u32((&platdev->dev)->of_node, ++ "dma-requests",&(hiedmac->slave_requests)); ++ if (ret) { ++ hiedmacv310_error( "get dma-requests fail\n"); ++ return -ENODEV; ++ } ++ hiedmacv310_trace(2,"dma-channels = %d, dma-requests = %d\n", ++ hiedmac->channels, hiedmac->slave_requests); ++ return of_dma_controller_register(platdev->dev.of_node, hiedma_of_xlate, hiedmac); ++} ++ ++static void hiedmac_free_chan_resources(struct dma_chan *chan) ++{ ++ vchan_free_chan_resources(to_virt_chan(chan)); ++} ++ ++static enum dma_status hiedmac_tx_status(struct dma_chan *chan, ++ dma_cookie_t cookie, struct dma_tx_state *txstate) ++{ ++ enum dma_status ret = DMA_COMPLETE; ++ struct hiedmacv310_dma_chan *edmac_dma_chan = to_edamc_chan(chan); ++ struct hiedmacv310_phy_chan *phychan = edmac_dma_chan->phychan; ++ struct hiedmacv310_driver_data *hiedmac = edmac_dma_chan->host; ++ struct virt_dma_desc *vd; ++ struct transfer_desc *tsf_desc; ++ unsigned long flags; ++ size_t bytes = 0; ++ u64 curr_lli = 0, curr_residue_bytes = 0, temp = 0; ++ hiedmac_lli *plli; ++ unsigned int i = 0, index = 0; ++ ++ ret = dma_cookie_status(chan, cookie, txstate); ++ if (ret == DMA_COMPLETE) { ++ return ret; ++ } ++ ++ spin_lock_irqsave(&edmac_dma_chan->virt_chan.lock, flags); ++ vd = vchan_find_desc(&edmac_dma_chan->virt_chan, cookie); ++ if (vd) { ++ /* no been trasfer */ ++ tsf_desc = to_edmac_transfer_desc(&vd->tx); ++ bytes = tsf_desc->size; ++ } else { ++ /* trasfering */ ++ tsf_desc = edmac_dma_chan->at; ++ ++ if (!phychan || !tsf_desc) { ++ bytes = 0; ++ spin_unlock_irqrestore(&edmac_dma_chan->virt_chan.lock, flags); ++ goto out; ++ } ++ curr_lli = (hiedmacv310_readl(hiedmac->base + HIEDMAC_Cx_LLI_L(phychan->id)) & (~(HIEDMAC_LLI_ALIGN-1))); ++ curr_lli |= (hiedmacv310_readl(hiedmac->base + HIEDMAC_Cx_LLI_H(phychan->id)) & 0xffffffff) << 32; ++ curr_residue_bytes = hiedmacv310_readl(hiedmac->base + HIEDMAC_Cx_CURR_CNT0(phychan->id)); ++ if (curr_lli == 0) { ++ /* It means non-lli mode */ ++ bytes = curr_residue_bytes; ++ } else { ++ /* It means lli mode */ ++ index = (curr_lli - tsf_desc->llis_busaddr) / sizeof(hiedmac_lli) - 1; ++ plli = (hiedmac_lli *)(tsf_desc->llis_vaddr); ++ for (i = 0; i < index; i++) { ++ temp += plli[i].count; ++ } ++ temp += plli[i].count - curr_residue_bytes; ++ bytes = tsf_desc->size - temp; ++ } ++ } ++ spin_unlock_irqrestore(&edmac_dma_chan->virt_chan.lock, flags); ++ ++ dma_set_residue(txstate, bytes); ++ ++ if (edmac_dma_chan->state == HIEDMAC_CHAN_PAUSED && ret == DMA_IN_PROGRESS) { ++ ret = DMA_PAUSED; ++ return ret; ++ } ++ ++out: ++ return ret; ++} ++ ++static struct hiedmacv310_phy_chan *hiedmac_get_phy_channel( ++ struct hiedmacv310_driver_data *hiedmac, ++ struct hiedmacv310_dma_chan *edmac_dma_chan) ++{ ++ struct hiedmacv310_phy_chan *ch = NULL; ++ unsigned long flags; ++ int i; ++ ++ for (i = 0; i < hiedmac->channels; i++) { ++ ch = &hiedmac->phy_chans[i]; ++ ++ spin_lock_irqsave(&ch->lock, flags); ++ ++ if (!ch->serving) { ++ ch->serving = edmac_dma_chan; ++ spin_unlock_irqrestore(&ch->lock, flags); ++ break; ++ } ++ spin_unlock_irqrestore(&ch->lock, flags); ++ } ++ ++ if (i == hiedmac->channels) { ++ return NULL; ++ } ++ ++ return ch; ++} ++ ++static void hiedmac_write_lli(struct hiedmacv310_driver_data *hiedmac, ++ struct hiedmacv310_phy_chan *phychan, ++ struct transfer_desc *tsf_desc) ++{ ++ ++ hiedmac_lli *plli = (hiedmac_lli *)tsf_desc->llis_vaddr; ++ ++ if (plli->next_lli != 0x0) ++ hiedmacv310_writel((plli->next_lli & 0xffffffff) | HIEDMAC_LLI_ENABLE , hiedmac->base + HIEDMAC_Cx_LLI_L(phychan->id)); ++ ++ else ++ hiedmacv310_writel((plli->next_lli & 0xffffffff) , hiedmac->base + HIEDMAC_Cx_LLI_L(phychan->id)); ++ ++ hiedmacv310_writel(((plli->next_lli >> 32) & 0xffffffff) , hiedmac->base + HIEDMAC_Cx_LLI_H(phychan->id)); ++ hiedmacv310_writel(plli->count, hiedmac->base + HIEDMAC_Cx_CNT0(phychan->id)); ++ hiedmacv310_writel(plli->src_addr & 0xffffffff , hiedmac->base + HIEDMAC_Cx_SRC_ADDR_L(phychan->id)); ++ hiedmacv310_writel((plli->src_addr >> 32) & 0xffffffff , hiedmac->base + HIEDMAC_Cx_SRC_ADDR_H(phychan->id)); ++ hiedmacv310_writel(plli->dest_addr & 0xffffffff , hiedmac->base + HIEDMAC_Cx_DEST_ADDR_L(phychan->id)); ++ hiedmacv310_writel((plli->dest_addr >> 32) & 0xffffffff , hiedmac->base + HIEDMAC_Cx_DEST_ADDR_H(phychan->id)); ++ hiedmacv310_writel(plli->config, hiedmac->base + HIEDMAC_Cx_CONFIG(phychan->id)); ++} ++ ++static void hiedmac_start_next_txd(struct hiedmacv310_dma_chan *edmac_dma_chan) ++{ ++ struct hiedmacv310_driver_data *hiedmac = edmac_dma_chan->host; ++ struct hiedmacv310_phy_chan *phychan = edmac_dma_chan->phychan; ++ struct virt_dma_desc *vd = vchan_next_desc(&edmac_dma_chan->virt_chan); ++ struct transfer_desc *tsf_desc = to_edmac_transfer_desc(&vd->tx); ++ unsigned int val = 0; ++ ++ list_del(&tsf_desc->virt_desc.node); ++ ++ edmac_dma_chan->at = tsf_desc; ++ ++ hiedmac_write_lli(hiedmac, phychan, tsf_desc); ++ ++ val = hiedmacv310_readl(hiedmac->base + HIEDMAC_Cx_CONFIG(phychan->id)); ++ ++ hiedmacv310_trace(2," HIEDMAC_Cx_CONFIG = 0x%x\n", val); ++ hiedmacv310_writel(val | HIEDMAC_CxCONFIG_LLI_START, hiedmac->base + HIEDMAC_Cx_CONFIG(phychan->id)); ++} ++ ++static void hiedmac_start(struct hiedmacv310_dma_chan * edmac_dma_chan) ++{ ++ struct hiedmacv310_driver_data *hiedmac = edmac_dma_chan->host; ++ struct hiedmacv310_phy_chan *ch; ++ ++ ch = hiedmac_get_phy_channel(hiedmac, edmac_dma_chan); ++ if (!ch) { ++ hiedmacv310_error("no phy channel available !\n"); ++ edmac_dma_chan->state = HIEDMAC_CHAN_WAITING; ++ return; ++ } ++ ++ edmac_dma_chan->phychan = ch; ++ edmac_dma_chan->state = HIEDMAC_CHAN_RUNNING; ++ ++ hiedmac_start_next_txd(edmac_dma_chan); ++} ++ ++static void hiedmac_issue_pending(struct dma_chan *chan) ++{ ++ struct hiedmacv310_dma_chan *edmac_dma_chan = to_edamc_chan(chan); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&edmac_dma_chan->virt_chan.lock, flags); ++ if (vchan_issue_pending(&edmac_dma_chan->virt_chan)) { ++ if (!edmac_dma_chan->phychan && edmac_dma_chan->state != HIEDMAC_CHAN_WAITING) { ++ hiedmac_start(edmac_dma_chan); ++ } ++ } ++ spin_unlock_irqrestore(&edmac_dma_chan->virt_chan.lock, flags); ++} ++ ++static void hiedmac_free_txd_list(struct hiedmacv310_dma_chan *edmac_dma_chan) ++{ ++ LIST_HEAD(head); ++ ++ vchan_get_all_descriptors(&edmac_dma_chan->virt_chan, &head); ++ vchan_dma_desc_free_list(&edmac_dma_chan->virt_chan, &head); ++} ++ ++static int hiedmac_config(struct dma_chan *chan, ++ struct dma_slave_config *config) ++{ ++ struct hiedmacv310_dma_chan *edmac_dma_chan = to_edamc_chan(chan); ++ ++ if (!edmac_dma_chan->slave) { ++ hiedmacv310_error("slave is null!"); ++ return -EINVAL; ++ } ++ ++ edmac_dma_chan->cfg = *config; ++ ++ return 0; ++} ++ ++static void hiedmac_pause_phy_chan(struct hiedmacv310_dma_chan *edmac_dma_chan) ++{ ++ struct hiedmacv310_driver_data *hiedmac = edmac_dma_chan->host; ++ struct hiedmacv310_phy_chan *phychan = edmac_dma_chan->phychan; ++ unsigned int val; ++ int timeout; ++ ++ ++ val = hiedmacv310_readl(hiedmac->base + HIEDMAC_Cx_CONFIG(phychan->id)); ++ val &= ~CCFG_EN; ++ hiedmacv310_writel(val, hiedmac->base + HIEDMAC_Cx_CONFIG(phychan->id)); ++ ++ /* Wait for channel inactive */ ++ for (timeout = 2000; timeout > 0; timeout--) { ++ if (!(0x1 << phychan->id & hiedmacv310_readl(hiedmac->base + HIEDMAC_CH_STAT))) ++ break; ++ hiedmacv310_writel(val, hiedmac->base + HIEDMAC_Cx_CONFIG(phychan->id)); ++ udelay(1); ++ } ++ ++ if (timeout == 0) { ++ hiedmacv310_error(":channel%u timeout waiting for pause, timeout:%d\n", ++ phychan->id, timeout); ++ } ++ return 0; ++} ++ ++static int hiedmac_pause(struct dma_chan *chan) ++{ ++ struct hiedmacv310_dma_chan *edmac_dma_chan = to_edamc_chan(chan); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&edmac_dma_chan->virt_chan.lock, flags); ++ ++ if (!edmac_dma_chan->phychan && !edmac_dma_chan->at) { ++ spin_unlock_irqrestore(&edmac_dma_chan->virt_chan.lock, flags); ++ return 0; ++ } ++ ++ hiedmac_pause_phy_chan(edmac_dma_chan); ++ edmac_dma_chan->state = HIEDMAC_CHAN_PAUSED; ++ spin_unlock_irqrestore(&edmac_dma_chan->virt_chan.lock, flags); ++ ++ return 0; ++} ++ ++static void hiedmac_resume_phy_chan(struct hiedmacv310_dma_chan *edmac_dma_chan) ++{ ++ struct hiedmacv310_driver_data *hiedmac = edmac_dma_chan->host; ++ struct hiedmacv310_phy_chan *phychan = edmac_dma_chan->phychan; ++ unsigned int val; ++ ++ val = hiedmacv310_readl(hiedmac->base + HIEDMAC_Cx_CONFIG(phychan->id)); ++ val |= CCFG_EN; ++ hiedmacv310_writel(val, hiedmac->base + HIEDMAC_Cx_CONFIG(phychan->id)); ++ ++ return 0; ++} ++ ++static int hiedmac_resume(struct dma_chan *chan) ++{ ++ struct hiedmacv310_dma_chan *edmac_dma_chan = to_edamc_chan(chan); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&edmac_dma_chan->virt_chan.lock, flags); ++ ++ if (!edmac_dma_chan->phychan && !edmac_dma_chan->at) { ++ spin_unlock_irqrestore(&edmac_dma_chan->virt_chan.lock, flags); ++ return 0; ++ } ++ ++ hiedmac_resume_phy_chan(edmac_dma_chan); ++ edmac_dma_chan->state = HIEDMAC_CHAN_RUNNING; ++ spin_unlock_irqrestore(&edmac_dma_chan->virt_chan.lock, flags); ++ ++ return 0; ++} ++ ++void hiedmac_phy_free(struct hiedmacv310_dma_chan *chan); ++static void hiedmac_desc_free(struct virt_dma_desc *vd); ++static int hiedmac_terminate_all(struct dma_chan *chan) ++{ ++ struct hiedmacv310_dma_chan *edmac_dma_chan = to_edamc_chan(chan); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&edmac_dma_chan->virt_chan.lock, flags); ++ if (!edmac_dma_chan->phychan && !edmac_dma_chan->at) { ++ spin_unlock_irqrestore(&edmac_dma_chan->virt_chan.lock, flags); ++ return 0; ++ } ++ ++ edmac_dma_chan->state = HIEDMAC_CHAN_IDLE; ++ ++ if (edmac_dma_chan->phychan) { ++ hiedmac_phy_free(edmac_dma_chan); ++ } ++ ++ if (edmac_dma_chan->at) { ++ hiedmac_desc_free(&edmac_dma_chan->at->virt_desc); ++ edmac_dma_chan->at = NULL; ++ } ++ hiedmac_free_txd_list(edmac_dma_chan); ++ ++ spin_unlock_irqrestore(&edmac_dma_chan->virt_chan.lock, flags); ++ ++ return 0; ++} ++ ++static struct transfer_desc *hiedmac_get_tsf_desc(struct hiedmacv310_driver_data *plchan) ++{ ++ struct transfer_desc *tsf_desc = kzalloc(sizeof(struct transfer_desc), GFP_NOWAIT); ++ ++ if (tsf_desc) { ++ tsf_desc->ccfg = 0; ++ } ++ ++ return tsf_desc; ++} ++ ++static void hiedmac_free_tsf_desc(struct hiedmacv310_driver_data *hiedmac, ++ struct transfer_desc *tsf_desc) ++{ ++ if (tsf_desc->llis_vaddr) { ++ dma_pool_free(hiedmac->pool, tsf_desc->llis_vaddr, tsf_desc->llis_busaddr); ++ } ++ ++ kfree(tsf_desc); ++} ++ ++static u32 get_width(enum dma_slave_buswidth width) ++{ ++ switch (width) { ++ case DMA_SLAVE_BUSWIDTH_1_BYTE: ++ return HIEDMAC_WIDTH_8BIT; ++ case DMA_SLAVE_BUSWIDTH_2_BYTES: ++ return HIEDMAC_WIDTH_16BIT; ++ case DMA_SLAVE_BUSWIDTH_4_BYTES: ++ return HIEDMAC_WIDTH_32BIT; ++ case DMA_SLAVE_BUSWIDTH_8_BYTES: ++ return HIEDMAC_WIDTH_64BIT; ++ default: ++ hiedmacv310_error("check here, width warning!\n"); ++ return ~0; ++ } ++} ++ ++struct transfer_desc *hiedmac_init_tsf_desc ( ++ struct dma_chan *chan, ++ enum dma_transfer_direction direction, ++ dma_addr_t *slave_addr) ++{ ++ struct hiedmacv310_dma_chan *edmac_dma_chan = to_edamc_chan(chan); ++ struct hiedmacv310_driver_data *hiedmac = edmac_dma_chan->host; ++ struct transfer_desc *tsf_desc; ++ unsigned int config = 0, burst = 0; ++ unsigned int addr_width = 0, maxburst = 0; ++ unsigned int width = 0; ++ ++ tsf_desc = hiedmac_get_tsf_desc(hiedmac); ++ if (!tsf_desc) { ++ hiedmacv310_error("get tsf desc fail!\n"); ++ return NULL; ++ } ++ ++ if (direction == DMA_MEM_TO_DEV) { ++ config = HIEDMAC_CONFIG_SRC_INC; ++ *slave_addr = edmac_dma_chan->cfg.dst_addr; ++ addr_width = edmac_dma_chan->cfg.dst_addr_width; ++ maxburst = edmac_dma_chan->cfg.dst_maxburst; ++ } else if (direction == DMA_DEV_TO_MEM){ ++ config = HIEDMAC_CONFIG_DST_INC; ++ *slave_addr = edmac_dma_chan->cfg.src_addr; ++ addr_width = edmac_dma_chan->cfg.src_addr_width; ++ maxburst = edmac_dma_chan->cfg.src_maxburst; ++ } else { ++ hiedmac_free_tsf_desc(hiedmac, tsf_desc); ++ hiedmacv310_error("direction unsupported!\n"); ++ return NULL; ++ } ++ ++ hiedmacv310_trace(3, "addr_width = 0x%x\n",addr_width); ++ width = get_width(addr_width); ++ hiedmacv310_trace(3, "width = 0x%x\n",width); ++ config |= width << HIEDMAC_CONFIG_SRC_WIDTH_SHIFT; ++ config |= width << HIEDMAC_CONFIG_DST_WIDTH_SHIFT; ++ hiedmacv310_trace(2, "tsf_desc->ccfg = 0x%x\n",config); ++ ++ hiedmacv310_trace(3, "maxburst = 0x%x\n", maxburst); ++ if (maxburst > (HIEDMAC_MAX_BURST_WIDTH)) ++ burst |= (HIEDMAC_MAX_BURST_WIDTH - 1); ++ else if (maxburst == 0) ++ burst |= HIEDMAC_MIN_BURST_WIDTH; ++ else ++ burst |= (maxburst - 1); ++ hiedmacv310_trace(3, "burst = 0x%x\n", burst); ++ config |= burst << HIEDMAC_CONFIG_SRC_BURST_SHIFT; ++ config |= burst << HIEDMAC_CONFIG_DST_BURST_SHIFT; ++ ++ if (edmac_dma_chan->signal >= 0) { ++ hiedmacv310_trace(2, "edmac_dma_chan->signal = %d\n", edmac_dma_chan->signal); ++ config |= edmac_dma_chan->signal << HIEDMAC_CXCONFIG_SIGNAL_SHIFT; ++ } ++ ++ config |= HIEDMAC_CXCONFIG_DEV_MEM_TYPE << HIEDMAC_CXCONFIG_TSF_TYPE_SHIFT; ++ tsf_desc->ccfg = config; ++ hiedmacv310_trace(2, "tsf_desc->ccfg = 0x%x\n",tsf_desc->ccfg); ++ ++ return tsf_desc; ++} ++ ++static void hiedmac_fill_desc(struct transfer_desc *tsf_desc, dma_addr_t src, ++ dma_addr_t dst, unsigned int length, unsigned int num) ++{ ++ hiedmac_lli *plli; ++ ++ plli = (hiedmac_lli *)(tsf_desc->llis_vaddr); ++ memset(&plli[num], 0x0, sizeof(hiedmac_lli)); ++ ++ plli[num].src_addr = src; ++ plli[num].dest_addr = dst; ++ plli[num].config = tsf_desc->ccfg; ++ plli[num].count = length; ++ tsf_desc->size += length; ++ ++ if (num > 0) ++ { ++ plli[num - 1].next_lli = (tsf_desc->llis_busaddr + (num)*sizeof(hiedmac_lli)) & (~(HIEDMAC_LLI_ALIGN-1)); ++ plli[num - 1].next_lli |= HIEDMAC_LLI_ENABLE; ++ } ++} ++ ++static struct dma_async_tx_descriptor *hiedmac_perp_slave_sg( ++ struct dma_chan *chan, struct scatterlist *sgl, ++ unsigned int sg_len, enum dma_transfer_direction direction, ++ unsigned long flags, void *context) ++{ ++ struct hiedmacv310_dma_chan *edmac_dma_chan = to_edamc_chan(chan); ++ struct hiedmacv310_driver_data *hiedmac = edmac_dma_chan->host; ++ struct transfer_desc *tsf_desc; ++ struct scatterlist *sg; ++ int tmp; ++ dma_addr_t src = 0, dst = 0, addr = 0, slave_addr = 0; ++ unsigned int length = 0, num = 0; ++ ++ hiedmac_lli *last_plli = NULL; ++ ++ if (sgl == NULL) { ++ hiedmacv310_error("sgl is null!\n"); ++ return NULL; ++ } ++ ++ tsf_desc = hiedmac_init_tsf_desc(chan, direction, &slave_addr); ++ if (!tsf_desc) { ++ hiedmacv310_error("desc init fail\n"); ++ return NULL; ++ } ++ ++ tsf_desc->llis_vaddr = dma_pool_alloc(hiedmac->pool, GFP_NOWAIT, &tsf_desc->llis_busaddr); ++ if (!tsf_desc->llis_vaddr) { ++ hiedmac_free_tsf_desc(hiedmac, tsf_desc); ++ hiedmacv310_error("malloc memory from pool fail !\n"); ++ return 0; ++ } ++ ++ for_each_sg(sgl, sg, sg_len, tmp) { ++ addr = sg_dma_address(sg); ++ length = sg_dma_len(sg); ++ if (direction == DMA_MEM_TO_DEV) { ++ src = addr; ++ dst = slave_addr; ++ } else if (direction == DMA_DEV_TO_MEM) { ++ src = slave_addr; ++ dst = addr; ++ } ++ hiedmac_fill_desc(tsf_desc, src, dst, length, num); ++ num++; ++ } ++ ++ last_plli = (hiedmac_lli *)(tsf_desc->llis_vaddr + (num - 1)*sizeof(hiedmac_lli)); ++ last_plli->next_lli |= HIEDMAC_LLI_DISABLE; ++ dump_lli(tsf_desc->llis_vaddr, num); ++ ++ return vchan_tx_prep(&edmac_dma_chan->virt_chan, &tsf_desc->virt_desc, flags); ++} ++ ++static struct dma_async_tx_descriptor *hiedmac_prep_dma_memcpy( ++ struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, ++ size_t len, unsigned long flags) ++{ ++ struct hiedmacv310_dma_chan *edmac_dma_chan = to_edamc_chan(chan); ++ struct hiedmacv310_driver_data *hiedmac = edmac_dma_chan->host; ++ struct transfer_desc *tsf_desc; ++ u32 config = 0; ++ size_t num = 0; ++ size_t length = 0; ++ hiedmac_lli *last_plli = NULL; ++ ++ if (!len) ++ return NULL; ++ ++ tsf_desc = hiedmac_get_tsf_desc(hiedmac); ++ if (!tsf_desc) { ++ hiedmacv310_error("get tsf desc fail!\n"); ++ return NULL; ++ } ++ ++ tsf_desc->llis_vaddr = dma_pool_alloc(hiedmac->pool, GFP_NOWAIT, &tsf_desc->llis_busaddr); ++ if (!tsf_desc->llis_vaddr) { ++ hiedmac_free_tsf_desc(hiedmac, tsf_desc); ++ hiedmacv310_error("malloc memory from pool fail !\n"); ++ return 0; ++ } ++ ++ config |= HIEDMAC_CONFIG_SRC_INC | HIEDMAC_CONFIG_DST_INC; ++ config |= HIEDMAC_CXCONFIG_MEM_TYPE << HIEDMAC_CXCONFIG_TSF_TYPE_SHIFT; ++ ++ /* max burst width is 16 ,but reg value set 0xf */ ++ config |= (HIEDMAC_MAX_BURST_WIDTH - 1) << HIEDMAC_CONFIG_SRC_BURST_SHIFT; ++ config |= (HIEDMAC_MAX_BURST_WIDTH - 1)<< HIEDMAC_CONFIG_DST_BURST_SHIFT; ++ ++ tsf_desc->ccfg = config; ++ ++ do { ++ length = min_t(size_t, len, MAX_TRANSFER_BYTES); ++ hiedmac_fill_desc(tsf_desc, src, dest, length, num); ++ ++ src += length; ++ dest += length; ++ len -= length; ++ num++; ++ } while(len); ++ ++ last_plli = (hiedmac_lli *)(tsf_desc->llis_vaddr + (num - 1)*sizeof(hiedmac_lli)); ++ last_plli->next_lli |= HIEDMAC_LLI_DISABLE; ++ dump_lli(tsf_desc->llis_vaddr, num); ++ ++ return vchan_tx_prep(&edmac_dma_chan->virt_chan, &tsf_desc->virt_desc, flags); ++} ++ ++ ++ ++static struct dma_async_tx_descriptor *hiemdac_prep_dma_cyclic( ++ struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, ++ size_t period_len, enum dma_transfer_direction direction, ++ unsigned long flags) ++{ ++ struct hiedmacv310_dma_chan *edmac_dma_chan = to_edamc_chan(chan); ++ struct hiedmacv310_driver_data *hiedmac = edmac_dma_chan->host; ++ struct transfer_desc *tsf_desc; ++ dma_addr_t src = 0, dst = 0, addr = 0, slave_addr = 0; ++ size_t length = 0, since = 0, total = 0, num = 0, len = 0; ++ hiedmac_lli *last_plli = NULL; ++ hiedmac_lli *plli = NULL; ++ ++ tsf_desc = hiedmac_init_tsf_desc(chan, direction, &slave_addr); ++ if (!tsf_desc) { ++ hiedmacv310_error("desc init fail\n"); ++ return NULL; ++ } ++ ++ tsf_desc->llis_vaddr = dma_pool_alloc(hiedmac->pool, GFP_NOWAIT, &tsf_desc->llis_busaddr); ++ if (!tsf_desc->llis_vaddr) { ++ hiedmacv310_error("malloc memory from pool fail !\n"); ++ return 0; ++ } ++ ++ tsf_desc->cyclic = true; ++ addr = buf_addr; ++ total = buf_len; ++ ++ if (period_len < MAX_TRANSFER_BYTES) ++ len = period_len; ++ do ++ { ++ length = min_t(size_t, total, len); ++ ++ if (direction == DMA_MEM_TO_DEV) { ++ src = addr; ++ dst = slave_addr; ++ } else if (direction == DMA_DEV_TO_MEM) { ++ src = slave_addr; ++ dst = addr; ++ } ++ ++ hiedmac_fill_desc(tsf_desc, src, dst, length, num); ++ ++ since += length; ++ if (since >= period_len) { ++ plli = (hiedmac_lli *)(tsf_desc->llis_vaddr + (num)*sizeof(hiedmac_lli)); ++ plli->config |= HIEDMAC_CXCONFIG_ITC_EN << HIEDMAC_CXCONFIG_ITC_EN_SHIFT; ++ since -= period_len; ++ } ++ addr += length; ++ total -= length; ++ num++; ++ } while(total); ++ ++ last_plli = (hiedmac_lli *)(tsf_desc->llis_vaddr + (num - 1)*sizeof(hiedmac_lli)); ++ ++ last_plli->next_lli = (u64)(tsf_desc->llis_vaddr); ++ ++ dump_lli(tsf_desc->llis_vaddr, num); ++ ++ return vchan_tx_prep(&edmac_dma_chan->virt_chan, &tsf_desc->virt_desc, flags); ++} ++ ++ ++static void hiedmac_phy_reassign(struct hiedmacv310_phy_chan *phy_chan, ++ struct hiedmacv310_dma_chan *chan) ++{ ++ phy_chan->serving = chan; ++ chan->phychan = phy_chan; ++ chan->state = HIEDMAC_CHAN_RUNNING; ++ ++ hiedmac_start_next_txd(chan); ++} ++ ++static void hiedmac_terminate_phy_chan(struct hiedmacv310_driver_data *hiedmac, ++ struct hiedmacv310_dma_chan *edmac_dma_chan) ++{ ++ unsigned int val; ++ struct hiedmacv310_phy_chan *phychan = edmac_dma_chan->phychan; ++ ++ hiedmac_pause_phy_chan(edmac_dma_chan); ++ ++ val = 0x1 << phychan->id; ++ ++ hiedmacv310_writel(val, hiedmac->base + HIEDMAC_INT_TC1_RAW); ++ hiedmacv310_writel(val, hiedmac->base + HIEDMAC_INT_ERR1_RAW); ++ hiedmacv310_writel(val, hiedmac->base + HIEDMAC_INT_ERR2_RAW); ++} ++ ++void hiedmac_phy_free(struct hiedmacv310_dma_chan *chan) ++{ ++ struct hiedmacv310_driver_data *hiedmac = chan->host; ++ struct hiedmacv310_dma_chan *p, *next = NULL; ++ ++ list_for_each_entry(p, &hiedmac->memcpy.channels, virt_chan.chan.device_node) { ++ if (p->state == HIEDMAC_CHAN_WAITING) { ++ next = p; ++ break; ++ } ++ } ++ ++ if (!next) { ++ list_for_each_entry(p, &hiedmac->slave.channels, virt_chan.chan.device_node) { ++ if (p->state == HIEDMAC_CHAN_WAITING) { ++ next = p; ++ break; ++ } ++ } ++ } ++ hiedmac_terminate_phy_chan(hiedmac, chan); ++ ++ if (next) { ++ spin_lock(&next->virt_chan.lock); ++ hiedmac_phy_reassign(chan->phychan, next); ++ spin_unlock(&next->virt_chan.lock); ++ } else { ++ chan->phychan->serving = NULL; ++ } ++ ++ chan->phychan = NULL; ++ chan->state = HIEDMAC_CHAN_IDLE; ++} ++ ++static irqreturn_t hiemdacv310_irq(int irq, void *dev) ++{ ++ struct hiedmacv310_driver_data *hiedmac = (struct hiedmacv310_driver_data *)dev; ++ struct hiedmacv310_dma_chan *chan = NULL; ++ struct hiedmacv310_phy_chan *phy_chan = NULL; ++ struct transfer_desc * tsf_desc = NULL; ++ ++ u32 mask = 0; ++ unsigned int channel_err_status[3]; ++ unsigned int channel_status = 0; ++ unsigned int temp = 0; ++ unsigned int channel_tc_status = -1; ++ int i = 0; ++ ++ channel_status = hiedmacv310_readl(hiedmac->base + HIEDMAC_INT_STAT); ++ ++ if (!channel_status) { ++ hiedmacv310_error("channel_status = 0x%x\n", channel_status); ++ return IRQ_NONE; ++ } ++ ++ for (i = 0; i < hiedmac->channels; i++) ++ { ++ temp = (channel_status >> i) & 0x1; ++ if (temp) { ++ phy_chan = &hiedmac->phy_chans[i]; ++ chan = phy_chan->serving; ++ tsf_desc = chan->at; ++ ++ channel_tc_status = hiedmacv310_readl(hiedmac->base + HIEDMAC_INT_TC1_RAW); ++ channel_tc_status = (channel_tc_status >> i) &0x01; ++ if (channel_tc_status) ++ hiedmacv310_writel(channel_tc_status << i, hiedmac->base + HIEDMAC_INT_TC1_RAW); ++ ++ channel_tc_status = hiedmacv310_readl(hiedmac->base + HIEDMAC_INT_TC2); ++ channel_tc_status = (channel_tc_status >> i) &0x01; ++ if (channel_tc_status) ++ hiedmacv310_writel(channel_tc_status << i, hiedmac->base + HIEDMAC_INT_TC2_RAW); ++ ++ if (!chan) { ++ hiedmacv310_error("error interrupt on chan: %d!\n",i); ++ continue; ++ } ++ ++ channel_err_status[0] = hiedmacv310_readl(hiedmac->base + HIEDMAC_INT_ERR1); ++ channel_err_status[0] = (channel_err_status[0] >> i) & 0x01; ++ channel_err_status[1] = hiedmacv310_readl(hiedmac->base + HIEDMAC_INT_ERR2); ++ channel_err_status[1] = (channel_err_status[1] >> i) & 0x01; ++ channel_err_status[2] = hiedmacv310_readl(hiedmac->base + HIEDMAC_INT_ERR3); ++ channel_err_status[2] = (channel_err_status[2] >> i) & 0x01; ++ if (channel_err_status[0] | channel_err_status[1] | channel_err_status[2]) { ++ hiedmacv310_error("Error in hiedmac %d finish!,ERR1 = 0x%x,ERR2 = 0x%x,ERR3 = 0x%x\n", ++ i, channel_err_status[0],channel_err_status[1],channel_err_status[2]); ++ hiedmacv310_writel(1<base + HIEDMAC_INT_ERR1_RAW); ++ hiedmacv310_writel(1<base + HIEDMAC_INT_ERR2_RAW); ++ hiedmacv310_writel(1<base + HIEDMAC_INT_ERR3_RAW); ++ } ++ ++ spin_lock(&chan->virt_chan.lock); ++ ++ if (tsf_desc->cyclic) { ++ vchan_cyclic_callback(&tsf_desc->virt_desc); ++ spin_unlock(&chan->virt_chan.lock); ++ continue; ++ } ++ chan->at = NULL; ++ tsf_desc->done = true; ++ vchan_cookie_complete(&tsf_desc->virt_desc); ++ ++ if (vchan_next_desc(&chan->virt_chan)) ++ hiedmac_start_next_txd(chan); ++ else ++ hiedmac_phy_free(chan); ++ ++ spin_unlock(&chan->virt_chan.lock); ++ mask |= (1 << i); ++ } ++ } ++ ++ return mask ? IRQ_HANDLED : IRQ_NONE; ++} ++ ++static void hiedmac_dma_slave_init(struct hiedmacv310_dma_chan *chan) ++{ ++ chan->slave = true; ++} ++ ++static void hiedmac_desc_free(struct virt_dma_desc *vd) ++{ ++ struct transfer_desc *tsf_desc = to_edmac_transfer_desc(&vd->tx); ++ struct hiedmacv310_dma_chan * edmac_dma_chan = to_edamc_chan(vd->tx.chan); ++ ++ dma_descriptor_unmap(&vd->tx); ++ hiedmac_free_tsf_desc(edmac_dma_chan->host, tsf_desc); ++} ++ ++static int hiedmac_init_virt_channels(struct hiedmacv310_driver_data *hiedmac, ++ struct dma_device *dmadev, unsigned int channels, bool slave) ++{ ++ struct hiedmacv310_dma_chan *chan; ++ int i; ++ INIT_LIST_HEAD(&dmadev->channels); ++ ++ for (i = 0; i < channels; i++) ++ { ++ chan = kzalloc(sizeof(struct hiedmacv310_dma_chan), GFP_KERNEL); ++ chan->host = hiedmac; ++ chan->state = HIEDMAC_CHAN_IDLE; ++ chan->signal = -1; ++ ++ if (slave) { ++ chan->id = i; ++ hiedmac_dma_slave_init(chan); ++ } ++ chan->virt_chan.desc_free = hiedmac_desc_free; ++ vchan_init(&chan->virt_chan, dmadev); ++ } ++ return 0; ++} ++ ++void hiedmac_free_virt_channels(struct dma_device *dmadev) ++{ ++ struct hiedmacv310_dma_chan *chan = NULL; ++ struct hiedmacv310_dma_chan *next; ++ ++ list_for_each_entry_safe(chan, ++ next, &dmadev->channels, virt_chan.chan.device_node) { ++ list_del(&chan->virt_chan.chan.device_node); ++ kfree(chan); ++ } ++} ++ ++ ++#define MAX_TSFR_LLIS 512 ++#define EDMACV300_LLI_WORDS 64 ++#define EDMACV300_POOL_ALIGN 64 ++ ++static int __init hiedmacv310_probe(struct platform_device *pdev) ++{ ++ ++ int ret = 0, i = 0; ++ struct hiedmacv310_driver_data *hiedmac = NULL; ++ size_t trasfer_size = 0; ++ ++ ret = dma_set_mask_and_coherent(&(pdev->dev), DMA_BIT_MASK(64)); ++ if (ret) ++ return ret; ++ ++ hiedmac = kzalloc(sizeof(*hiedmac), GFP_KERNEL); ++ if (!hiedmac) { ++ hiedmacv310_error("malloc for hiedmac fail!"); ++ ret = -ENOMEM; ++ return ret; ++ } ++ hiedmac->dev = pdev; ++ ++ ret = get_of_probe(hiedmac); ++ if (ret) { ++ hiedmacv310_error("get dts info fail!"); ++ goto free_hiedmac; ++ } ++ ++ ++ clk_prepare_enable(hiedmac->clk); ++ clk_prepare_enable(hiedmac->axi_clk); ++ ++ reset_control_deassert(hiedmac->rstc); ++ ++ dma_cap_set(DMA_MEMCPY, hiedmac->memcpy.cap_mask); ++ hiedmac->memcpy.dev = &pdev->dev; ++ hiedmac->memcpy.device_free_chan_resources = hiedmac_free_chan_resources; ++ hiedmac->memcpy.device_prep_dma_memcpy = hiedmac_prep_dma_memcpy; ++ hiedmac->memcpy.device_tx_status = hiedmac_tx_status; ++ hiedmac->memcpy.device_issue_pending = hiedmac_issue_pending; ++ hiedmac->memcpy.device_config = hiedmac_config; ++ hiedmac->memcpy.device_pause = hiedmac_pause; ++ hiedmac->memcpy.device_resume = hiedmac_resume; ++ hiedmac->memcpy.device_terminate_all = hiedmac_terminate_all; ++ hiedmac->memcpy.directions = BIT(DMA_MEM_TO_MEM); ++ hiedmac->memcpy.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; ++ ++ dma_cap_set(DMA_SLAVE, hiedmac->slave.cap_mask); ++ dma_cap_set(DMA_CYCLIC, hiedmac->slave.cap_mask); ++ hiedmac->slave.dev = &pdev->dev; ++ hiedmac->slave.device_free_chan_resources = hiedmac_free_chan_resources; ++ hiedmac->slave.device_tx_status = hiedmac_tx_status; ++ hiedmac->slave.device_issue_pending = hiedmac_issue_pending; ++ hiedmac->slave.device_prep_slave_sg = hiedmac_perp_slave_sg; ++ hiedmac->slave.device_prep_dma_cyclic = hiemdac_prep_dma_cyclic; ++ hiedmac->slave.device_config = hiedmac_config; ++ hiedmac->slave.device_resume = hiedmac_resume; ++ hiedmac->slave.device_pause = hiedmac_pause; ++ hiedmac->slave.device_terminate_all = hiedmac_terminate_all; ++ hiedmac->slave.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); ++ hiedmac->slave.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; ++ ++ hiedmac->max_transfer_size = MAX_TRANSFER_BYTES; ++ trasfer_size = MAX_TSFR_LLIS * EDMACV300_LLI_WORDS * sizeof(u32); ++ ++ hiedmac->pool = dma_pool_create(DRIVER_NAME, &(pdev->dev), ++ trasfer_size, EDMACV300_POOL_ALIGN, 0); ++ if (!hiedmac->pool) { ++ hiedmacv310_error("create pool fail!"); ++ ret = -ENOMEM; ++ goto free_hiedmac; ++ } ++ ++ hiedmacv310_writel(HIEDMAC_ALL_CHAN_CLR, hiedmac->base + HIEDMAC_INT_TC1_RAW); ++ hiedmacv310_writel(HIEDMAC_ALL_CHAN_CLR, hiedmac->base + HIEDMAC_INT_TC2_RAW); ++ hiedmacv310_writel(HIEDMAC_ALL_CHAN_CLR, hiedmac->base + HIEDMAC_INT_ERR1_RAW); ++ hiedmacv310_writel(HIEDMAC_ALL_CHAN_CLR, hiedmac->base + HIEDMAC_INT_ERR2_RAW); ++ hiedmacv310_writel(HIEDMAC_ALL_CHAN_CLR, hiedmac->base + HIEDMAC_INT_ERR3_RAW); ++ ++ hiedmacv310_writel(HIEDMAC_INT_ENABLE_ALL_CHAN , hiedmac->base + HIEDMAC_INT_TC1_MASK); ++ hiedmacv310_writel(HIEDMAC_INT_ENABLE_ALL_CHAN , hiedmac->base + HIEDMAC_INT_TC2_MASK); ++ hiedmacv310_writel(HIEDMAC_INT_ENABLE_ALL_CHAN , hiedmac->base + HIEDMAC_INT_ERR1_MASK); ++ hiedmacv310_writel(HIEDMAC_INT_ENABLE_ALL_CHAN , hiedmac->base + HIEDMAC_INT_ERR2_MASK); ++ hiedmacv310_writel(HIEDMAC_INT_ENABLE_ALL_CHAN , hiedmac->base + HIEDMAC_INT_ERR3_MASK); ++ ++ ret = request_irq(hiedmac->irq, hiemdacv310_irq, 0, DRIVER_NAME, hiedmac); ++ if (ret) { ++ hiedmacv310_error("fail to request irq"); ++ goto free_pool; ++ } ++ ++ hiedmac->phy_chans = kzalloc((hiedmac->channels * sizeof(struct hiedmacv310_phy_chan)), ++ GFP_KERNEL); ++ if (!hiedmac->phy_chans) { ++ hiedmacv310_error("malloc for phy chans fail!"); ++ ret = -ENOMEM; ++ goto free_irq_res; ++ } ++ ++ /* initialize the phy chan */ ++ for (i = 0; i < hiedmac->channels; i++) { ++ struct hiedmacv310_phy_chan* phy_ch = &hiedmac->phy_chans[i]; ++ phy_ch->id = i; ++ phy_ch->base = hiedmac->base + HIEDMAC_Cx_BASE(i); ++ spin_lock_init(&phy_ch->lock); ++ phy_ch->serving = NULL; ++ } ++ ++ /* initialize the memory virt chan */ ++ ret = hiedmac_init_virt_channels(hiedmac, &hiedmac->memcpy, hiedmac->channels, false); ++ if (ret) { ++ hiedmacv310_error("fail to init memory virt channels!"); ++ goto free_phychans; ++ } ++ ++ /* initialize the slave virt chan */ ++ ret = hiedmac_init_virt_channels(hiedmac, &hiedmac->slave, hiedmac->slave_requests, true); ++ if (ret) { ++ hiedmacv310_error("fail to init slave virt channels!"); ++ goto free_memory_virt_channels; ++ ++ } ++ ++ ret = dma_async_device_register(&hiedmac->memcpy); ++ if (ret) { ++ hiedmacv310_error( ++ "%s failed to register memcpy as an async device - %d\n", ++ __func__, ret); ++ goto free_slave_virt_channels; ++ } ++ ++ ret = dma_async_device_register(&hiedmac->slave); ++ if (ret) { ++ hiedmacv310_error( ++ "%s failed to register slave as an async device - %d\n", ++ __func__, ret); ++ goto free_memcpy_device; ++ } ++ ++ return 0; ++ ++free_memcpy_device: ++ dma_async_device_unregister(&hiedmac->memcpy); ++free_slave_virt_channels: ++ hiedmac_free_virt_channels(&hiedmac->slave); ++free_memory_virt_channels: ++ hiedmac_free_virt_channels(&hiedmac->memcpy); ++free_phychans: ++ kfree(hiedmac->phy_chans); ++free_irq_res: ++ free_irq(hiedmac->irq,hiedmac); ++free_pool: ++ dma_pool_destroy(hiedmac->pool); ++free_hiedmac: ++ kfree(hiedmac); ++ ++ return ret; ++} ++ ++ ++static int hiemda_remove(struct platform_device *pdev) ++{ ++ int err = 0; ++ return err; ++} ++ ++ ++static const struct of_device_id hiedmacv310_match[] = { ++ { .compatible = "hisilicon,hiedmacv310" }, ++ {}, ++}; ++ ++ ++static struct platform_driver hiedmacv310_driver = { ++ .remove = hiemda_remove, ++ .driver = { ++ .name = "hiedmacv310", ++ .of_match_table = hiedmacv310_match, ++ }, ++}; ++ ++static int __init hiedmacv310_init(void) ++{ ++ return platform_driver_probe(&hiedmacv310_driver, hiedmacv310_probe); ++} ++subsys_initcall(hiedmacv310_init); ++ ++static void __exit hiedmacv310_exit(void) ++{ ++ platform_driver_unregister(&hiedmacv310_driver); ++} ++module_exit(hiedmacv310_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Hisilicon"); +diff --git a/drivers/dma/hiedmacv310.h b/drivers/dma/hiedmacv310.h +new file mode 100644 +index 0000000..7243b92 +--- /dev/null ++++ b/drivers/dma/hiedmacv310.h +@@ -0,0 +1,128 @@ ++#ifndef __HIEDMACV310_H__ ++#define __HIEDMACV310_H__ ++ ++/* debug control */ ++extern int hiedmacv310_trace_level; ++#define HIEDMACV310_TRACE_LEVEL 5 ++ ++#define HIEDMACV310_TRACE_FMT KERN_INFO ++ ++//#define DEBUG_HIEDMAC ++#ifdef DEBUG_HIEDMAC ++ ++#define hiedmacv310_trace(level, msg...) do { \ ++ if ((level) >= hiedmacv310_trace_level) { \ ++ printk(HIEDMACV310_TRACE_FMT"%s:%d: ", __func__, __LINE__); \ ++ printk(msg); \ ++ printk("\n"); \ ++ } \ ++} while (0) ++ ++ ++#define hiedmacv310_assert(cond) do { \ ++ if (!(cond)) {\ ++ printk(KERN_ERR "Assert:hiedmacv310:%s:%d\n", \ ++ __func__, \ ++ __LINE__); \ ++ BUG(); \ ++ } \ ++} while (0) ++ ++#define hiedmacv310_error(s...) do { \ ++ printk(KERN_ERR "hiedmacv310:%s:%d: ", __func__, __LINE__); \ ++ printk(s); \ ++ printk("\n"); \ ++} while (0) ++ ++#else ++ ++#define hiedmacv310_trace(level, msg...) do {}while(0) ++#define hiedmacv310_assert(level, msg...) do {}while(0) ++#define hiedmacv310_error(level, msg...) do {}while(0) ++ ++#endif ++ ++#define hiedmacv310_readl(addr) ({unsigned int reg = readl((void *)(addr)); \ ++ reg; }) ++ ++#define hiedmacv310_writel(v, addr) do { writel(v, (void *)(addr)); \ ++} while (0) ++ ++ ++#define MAX_TRANSFER_BYTES 0xffff ++ ++/* reg offset */ ++#define HIEDMAC_INT_STAT (0x0) ++#define HIEDMAC_INT_TC1 (0x4) ++#define HIEDMAC_INT_TC2 (0x8) ++#define HIEDMAC_INT_ERR1 (0xc) ++#define HIEDMAC_INT_ERR2 (0x10) ++#define HIEDMAC_INT_ERR3 (0x14) ++ ++#define HIEDMAC_INT_TC1_MASK (0x18) ++#define HIEDMAC_INT_TC2_MASK (0x1c) ++#define HIEDMAC_INT_ERR1_MASK (0x20) ++#define HIEDMAC_INT_ERR2_MASK (0x24) ++#define HIEDMAC_INT_ERR3_MASK (0x28) ++ ++#define HIEDMAC_INT_TC1_RAW (0x600) ++#define HIEDMAC_INT_TC2_RAW (0x608) ++#define HIEDMAC_INT_ERR1_RAW (0x610) ++#define HIEDMAC_INT_ERR2_RAW (0x618) ++#define HIEDMAC_INT_ERR3_RAW (0x620) ++ ++#define HIEDMAC_Cx_CURR_CNT0(cn) (0x404+cn*0x20) ++#define HIEDMAC_Cx_CURR_SRC_ADDR_L(cn) (0x408+cn*0x20) ++#define HIEDMAC_Cx_CURR_SRC_ADDR_H(cn) (0x40c+cn*0x20) ++#define HIEDMAC_Cx_CURR_DEST_ADDR_L(cn) (0x410+cn*0x20) ++#define HIEDMAC_Cx_CURR_DEST_ADDR_H(cn) (0x414+cn*0x20) ++ ++#define HIEDMAC_CH_PRI (0x688) ++#define HIEDMAC_CH_STAT (0x690) ++#define HIEDMAC_DMA_CTRL (0x698) ++ ++#define HIEDMAC_Cx_BASE(cn) (0x800+cn*0x40) ++#define HIEDMAC_Cx_LLI_L(cn) (0x800+cn*0x40) ++#define HIEDMAC_Cx_LLI_H(cn) (0x804+cn*0x40) ++#define HIEDMAC_Cx_CNT0(cn) (0x81c+cn*0x40) ++#define HIEDMAC_Cx_SRC_ADDR_L(cn) (0x820+cn*0x40) ++#define HIEDMAC_Cx_SRC_ADDR_H(cn) (0x824+cn*0x40) ++#define HIEDMAC_Cx_DEST_ADDR_L(cn) (0x828+cn*0x40) ++#define HIEDMAC_Cx_DEST_ADDR_H(cn) (0x82c+cn*0x40) ++#define HIEDMAC_Cx_CONFIG(cn) (0x830+cn*0x40) ++ ++#define HIEDMAC_ALL_CHAN_CLR (0xff) ++#define HIEDMAC_INT_ENABLE_ALL_CHAN (0xff) ++ ++ ++#define HIEDMAC_CONFIG_SRC_INC (1<<31) ++#define HIEDMAC_CONFIG_DST_INC (1<<30) ++ ++#define HIEDMAC_CONFIG_SRC_WIDTH_SHIFT (16) ++#define HIEDMAC_CONFIG_DST_WIDTH_SHIFT (12) ++#define HIEDMAC_WIDTH_8BIT (0x0) ++#define HIEDMAC_WIDTH_16BIT (0x1) ++#define HIEDMAC_WIDTH_32BIT (0x10) ++#define HIEDMAC_WIDTH_64BIT (0x11) ++ ++#define HIEDMAC_MAX_BURST_WIDTH (16) ++#define HIEDMAC_MIN_BURST_WIDTH (1) ++#define HIEDMAC_CONFIG_SRC_BURST_SHIFT (24) ++#define HIEDMAC_CONFIG_DST_BURST_SHIFT (20) ++ ++#define HIEDMAC_LLI_ALIGN 0x40 ++#define HIEDMAC_LLI_DISABLE 0x0 ++#define HIEDMAC_LLI_ENABLE 0x2 ++ ++#define HIEDMAC_CXCONFIG_SIGNAL_SHIFT (0x4) ++#define HIEDMAC_CXCONFIG_MEM_TYPE (0x0) ++#define HIEDMAC_CXCONFIG_DEV_MEM_TYPE (0x1) ++#define HIEDMAC_CXCONFIG_TSF_TYPE_SHIFT (0x2) ++#define HIEDMAC_CxCONFIG_LLI_START (0x1) ++ ++#define HIEDMAC_CXCONFIG_ITC_EN (0x1) ++#define HIEDMAC_CXCONFIG_ITC_EN_SHIFT (0x1) ++ ++#define CCFG_EN 0x1 ++ ++#endif +diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c +index 6e3c143..1489e46 100644 +--- a/drivers/gpio/gpio-pl061.c ++++ b/drivers/gpio/gpio-pl061.c +@@ -208,6 +208,25 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) + return 0; + } + ++#ifdef CONFIG_ARCH_HISI_BVT ++static irqreturn_t pl061_irq_handler(int irq, void *data) ++{ ++ unsigned long pending; ++ int offset; ++ struct gpio_chip *gc = data; ++ struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); ++ ++ pending = readb(chip->base + GPIOMIS); ++ writeb(pending, chip->base + GPIOIC); ++ if (pending) { ++ for_each_set_bit(offset, &pending, PL061_GPIO_NR) ++ generic_handle_irq(irq_find_mapping(gc->irqdomain, ++ offset)); ++ } ++ ++ return IRQ_HANDLED; ++} ++#else + static void pl061_irq_handler(struct irq_desc *desc) + { + unsigned long pending; +@@ -227,6 +246,7 @@ static void pl061_irq_handler(struct irq_desc *desc) + + chained_irq_exit(irqchip, desc); + } ++#endif + + static void pl061_irq_mask(struct irq_data *d) + { +@@ -308,7 +328,17 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) + return -ENODEV; + } + } else { ++#ifdef CONFIG_ARCH_HISI_BVT ++ if (dev->of_node) { ++ i = of_alias_get_id(dev->of_node, "gpio"); ++ chip->gc.base = i * PL061_GPIO_NR; ++ } ++ ++ if (chip->gc.base < 0) ++ chip->gc.base = -1; ++#else + chip->gc.base = -1; ++#endif + irq_base = 0; + } + +@@ -353,8 +383,21 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) + dev_info(&adev->dev, "could not add irqchip\n"); + return ret; + } ++#ifdef CONFIG_ARCH_HISI_BVT ++ ret = devm_request_irq(dev, irq, pl061_irq_handler, IRQF_SHARED, ++ dev_name(dev), &chip->gc); ++ if (ret) { ++ dev_info(dev, "request irq failed: %d\n", ret); ++ return ret; ++ } ++ ++ /* Set the parent IRQ for all affected IRQs */ ++ for (i = 0; i < chip->gc.ngpio; i++) ++ irq_set_parent(irq_find_mapping(chip->gc.irqdomain, i), irq); ++#else + gpiochip_set_chained_irqchip(&chip->gc, &pl061_irqchip, + irq, pl061_irq_handler); ++#endif + + for (i = 0; i < PL061_GPIO_NR; i++) { + if (pdata) { +diff --git a/drivers/hidmac/Kconfig b/drivers/hidmac/Kconfig +new file mode 100644 +index 0000000..dcb3e08b +--- /dev/null ++++ b/drivers/hidmac/Kconfig +@@ -0,0 +1,21 @@ ++# ++# Sensor device configuration ++# ++ ++config HI_DMAC ++ tristate "Hisilicon DMAC Controller support" ++ depends on (ARCH_HISI_BVT) ++ help ++ The Direction Memory Access(DMA) is a high-speed data transfer ++ operation. It supports data read/write between peripherals and ++ memories without using the CPU. ++ Hisilicon DMA Controller(DMAC) directly transfers data between ++ a memory and a peripheral, between peripherals, or between memories. ++ This avoids the CPU intervention and reduces the interrupt handling ++ overhead of the CPU. ++ ++if HI_DMAC ++config HI_DMAC_CHANNEL_NUM ++ int "hi dmac channel num" ++ default "4" ++endif +diff --git a/drivers/hidmac/Makefile b/drivers/hidmac/Makefile +new file mode 100644 +index 0000000..7e41f4c +--- /dev/null ++++ b/drivers/hidmac/Makefile +@@ -0,0 +1,6 @@ ++# ++# Makefile for the hi dmac drivers. ++# ++ ++obj-$(CONFIG_HI_DMAC) += hi_pl08x.o ++ +diff --git a/drivers/hidmac/hi_pl08x.c b/drivers/hidmac/hi_pl08x.c +new file mode 100644 +index 0000000..bda05c0 +--- /dev/null ++++ b/drivers/hidmac/hi_pl08x.c +@@ -0,0 +1,1286 @@ ++/* ++ * ++ * Copyright (c) 2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hi_pl08x.h" ++ ++#ifdef CONFIG_ARCH_HI3536DV100 ++#include "hidmac_hi3536dv100.h" ++#endif ++ ++#ifdef CONFIG_ARCH_HI3518EV20X ++#include "hidmac_hi3518ev20x.h" ++#endif ++ ++#ifdef CONFIG_ARCH_HI3516A ++#include "hidmac_hi3516a.h" ++#endif ++ ++#ifdef CONFIG_ARCH_HI3521A ++#include "hidmac_hi3521a.h" ++#endif ++ ++#ifdef CONFIG_ARCH_HI3531A ++#include "hidmac_hi3531a.h" ++#endif ++ ++#define RX 0 ++#define TX 1 ++ ++static int dmac_channel[CHANNEL_NUM] = {0, 1, 2, 3}; ++ ++int g_channel_status[CHANNEL_NUM]; ++ ++/* #define DEBUG */ ++ ++#define DEBUG ++#ifdef DEBUG ++#define dma_err printk ++#else ++#define dma_err(fmt, ...) do {} while (0) ++#endif ++ ++/* ++ *Define Memory range ++ */ ++mem_addr mem_num[MEM_MAX_NUM] = { ++ {DDRAM_ADRS, DDRAM_SIZE}, ++ {FLASH_BASE, FLASH_SIZE} ++}; ++ ++typedef void REG_ISR(int *p_dma_chn, int *p_dma_status); ++REG_ISR *function[CHANNEL_NUM]; ++ ++struct hidmac_host { ++ struct clk *clk; ++ struct reset_control *rstc; ++ void __iomem *regbase; ++ ++ int irq; ++}; ++ ++void __iomem *dma_regbase; ++unsigned int pllihead[2]; ++ ++#define CLR_INT(i) ((*(unsigned int *)(dma_regbase+0x008)) = (1 << i)) ++ ++/* ++ * memory address validity check ++ * ++static int mem_check_valid(unsigned int addr) ++{ ++ unsigned int cnt; ++ ++ for (cnt = 0; cnt < MEM_MAX_NUM; cnt++) { ++ if ((addr >= mem_num[cnt].addr_base) && ++ (addr <= (mem_num[cnt].addr_base + mem_num[cnt].size))) ++ return 0; ++ } ++ ++ return -1; ++} */ ++ ++/* ++ * dmac interrupt handle function ++ */ ++irqreturn_t dmac_isr(int irq, void *dev_id) ++{ ++ struct hidmac_host *dma = dev_id; ++ unsigned int channel_status; ++ unsigned int channel_tc_status, channel_err_status; ++ unsigned int i; ++ ++ /*read the status of current interrupt */ ++ dmac_readw(dma->regbase + DMAC_INTSTATUS, channel_status); ++ ++ /*decide which channel has trigger the interrupt*/ ++ for (i = 0; i < DMAC_MAX_CHANNELS; i++) { ++ if ((((channel_status >> i) & 0x1) == 0x01)) { ++ /* [HSCP201306240006],l00181524,20130625 */ ++ /* The INT status should be read first then clear it */ ++ /* CLR_INT(i); */ ++ dmac_readw(dma->regbase + DMAC_INTTCSTATUS, channel_tc_status); ++ dmac_readw(dma->regbase + DMAC_INTERRORSTATUS, channel_err_status); ++ CLR_INT(i); ++ /*??HSCP201403110002?? l00183122 20140723*/ ++ if (g_channel_status[i] == DMAC_CHN_VACANCY ++ && (function[i]) == NULL) { ++ if ((0x01 == ((channel_tc_status >> i) & 0x01))) ++ dmac_writew(dma->regbase + DMAC_INTTCCLEAR, ++ (0x01 << i)); ++ else if ((0x01 == ((channel_err_status ++ >> i)&0x01))) ++ dmac_writew(dma->regbase + DMAC_INTERRCLR, ++ (0x01 << i)); ++ continue; ++ } ++ ++ /* save the current channel transfer */ ++ /* status to g_channel_status[i] */ ++ if ((0x01 == ((channel_tc_status >> i) & 0x01))) { ++ g_channel_status[i] = DMAC_CHN_SUCCESS; ++ dmac_writew(dma->regbase + DMAC_INTTCCLEAR, (0x01 << i)); ++ } else if ((0x01 == ((channel_err_status >> i)&0x01))) { ++ g_channel_status[i] = -DMAC_CHN_ERROR; ++ dmac_writew(dma->regbase + DMAC_INTERRCLR, (0x01 << i)); ++ } else { ++ pr_err("Isr Error in DMAC_IntHandeler"); ++ pr_err("%d! channel\n", i); ++ } ++ ++ if ((function[i]) != NULL) ++ function[i](&i, &g_channel_status[i]); ++ } ++ } ++ ++ return IRQ_RETVAL(1); ++} ++ ++/* ++ * update the state of channels ++ */ ++#define HI_DMA_UPDATE_TIMEOUT 5000000 ++static int dma_update_status(unsigned int channel) ++{ ++ ++ unsigned int channel_status; ++ unsigned int channel_tc_status[3]; ++ unsigned int channel_err_status[3]; ++ unsigned int i = channel, j, time = 0; ++ ++ ++ while (1) { ++ for (j = 0; j < 3; j++) { ++ dmac_readw(dma_regbase + DMAC_RAWINTTCSTATUS, channel_status); ++ channel_tc_status[j] = (channel_status >> i) & 0x01; ++ dmac_readw(dma_regbase + DMAC_RAWINTERRORSTATUS, channel_status); ++ channel_err_status[j] = (channel_status >> i) & 0x01; ++ } ++ ++ if ((channel_tc_status[0] == 0x1) && ++ (channel_tc_status[1] == 0x1) && ++ (channel_tc_status[2] == 0x1)) { ++ g_channel_status[i] = DMAC_CHN_SUCCESS; ++ dmac_writew(dma_regbase + DMAC_INTTCCLEAR, (0x01 << i)); ++ break; ++ } else if ((channel_err_status[0] == 0x1) && ++ (channel_err_status[1] == 0x1) && ++ (channel_err_status[2] == 0x1)) { ++ g_channel_status[i] = -DMAC_CHN_ERROR; ++ dma_err("Error in DMAC %d finish!\n", i); ++ dmac_writew(dma_regbase + DMAC_INTERRCLR, (0x01 << i)); ++ break; ++ } ++ ++ if (++time == HI_DMA_UPDATE_TIMEOUT) { ++ dma_err("Timeout in DMAC %d!\n", i); ++ g_channel_status[i] = -DMAC_CHN_TIMEOUT; ++ break; ++ } ++ } ++ ++ return g_channel_status[i]; ++} ++ ++ ++/* ++ * check the state of channels ++ */ ++static int dmac_check_over(unsigned int channel) ++{ ++ int status = 0; ++ ++ if (-DMAC_CHN_ERROR == g_channel_status[channel]) { ++ dma_err("Error transfer %d finished\n", channel); ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(channel), DMAC_CxDISABLE); ++ g_channel_status[channel] = DMAC_CHN_VACANCY; ++ status = -DMAC_CHN_ERROR; ++ } else if (DMAC_NOT_FINISHED == g_channel_status[channel]) ++ status = DMAC_NOT_FINISHED; ++ else if (DMAC_CHN_ALLOCAT == g_channel_status[channel]) ++ status = DMAC_CHN_ALLOCAT; ++ else if (DMAC_CHN_VACANCY == g_channel_status[channel]) ++ status = DMAC_CHN_VACANCY; ++ else if (-DMAC_CHN_TIMEOUT == g_channel_status[channel]) { ++ dma_err("transfer %d timeout!\n", channel); ++ status = -DMAC_CHN_TIMEOUT; ++ } else if (DMAC_CHN_SUCCESS == g_channel_status[channel]) ++ /*The transfer of Channel %d has finished successfully!*/ ++ status = DMAC_CHN_SUCCESS; ++ else { ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(channel), DMAC_CxDISABLE); ++ g_channel_status[channel] = DMAC_CHN_VACANCY; ++ status = -DMAC_CHN_ERROR; ++ } ++ return status; ++} ++ ++spinlock_t my_lcok = __SPIN_LOCK_UNLOCKED(old_style_spin_init); ++unsigned long flags; ++ ++/* ++ * allocate channel. ++ */ ++int dmac_channel_allocate(void *pisr) ++{ ++ unsigned int i, channelinfo, g_channelinfo; ++ ++ for (i = 0; i < CHANNEL_NUM; i++) ++ dmac_check_over(dmac_channel[i]); ++ ++ dmac_readw(dma_regbase + DMAC_ENBLDCHNS, g_channelinfo); ++ g_channelinfo = g_channelinfo & 0x00ff; ++ ++ for (i = 0; i < CHANNEL_NUM; i++) { ++ if (g_channel_status[dmac_channel[i]] == DMAC_CHN_VACANCY) { ++ channelinfo = g_channelinfo >> dmac_channel[i]; ++ if (0x00 == (channelinfo & 0x01)) { ++ /*clear the interrupt in this channel */ ++ dmac_writew(dma_regbase + DMAC_INTERRCLR, ++ (0x01 << dmac_channel[i])); ++ dmac_writew(dma_regbase + DMAC_INTTCCLEAR, ++ (0x01 << dmac_channel[i])); ++ ++ g_channel_status[dmac_channel[i]] ++ = DMAC_CHN_ALLOCAT; ++ return dmac_channel[i]; ++ } ++ } ++ } ++ ++ dma_err("no to alloc\n"); ++ return -EINVAL; ++} ++EXPORT_SYMBOL(dmac_channel_allocate); ++ ++int dmac_register_isr(unsigned int channel, void *pisr) ++{ ++ if (channel > CHANNEL_NUM - 1) { ++ dma_err("channel which choosed %d is error !\n", channel); ++ return -1; ++ } ++ ++ if (g_channel_status[channel] != DMAC_CHN_VACANCY) { ++ dma_err("dma chn %d is in used!\n", channel); ++ return -1; ++ } ++ ++ /*clear the interrupt in this channel */ ++ dmac_writew(dma_regbase + DMAC_INTERRCLR, (0x01 << channel)); ++ dmac_writew(dma_regbase + DMAC_INTTCCLEAR, (0x01 << channel)); ++ ++ function[channel] = (void *)pisr; ++ g_channel_status[channel] = DMAC_CHN_ALLOCAT; ++ ++ return 0; ++} ++EXPORT_SYMBOL(dmac_register_isr); ++ ++/* ++ * free channel ++ */ ++int dmac_channel_free(unsigned int channel) ++{ ++ if (channel >= DMAC_MAX_CHANNELS) { ++ dma_err("channel larger than total.\n"); ++ return -EINVAL; ++ } ++ ++ g_channel_status[channel] = DMAC_CHN_VACANCY; ++ return 0; ++} ++EXPORT_SYMBOL(dmac_channel_free); ++ ++static unsigned int dmac_check_request(unsigned int peripheral_addr, ++ int direction) ++{ ++ int i; ++ /* check request pipe with peripheral_addr */ ++ for (i = direction; i < DMAC_MAX_PERIPHERALS; i = i + 2) { ++ if (g_peripheral[i].peri_addr == peripheral_addr) ++ return i; ++ } ++ ++ dma_err("Invalid devaddr\n"); ++ ++ return -1; ++} ++ ++/* ++ * init dmac register ++ * clear interrupt flags ++ * called by dma_driver_init ++ */ ++int dmac_init(struct hidmac_host *dma) ++{ ++ unsigned int i, tempvalue; ++ int ret; ++ ++ clk_prepare_enable(dma->clk); ++ reset_control_deassert(dma->rstc); ++ ++ dmac_readw(dma->regbase + DMAC_CONFIG, tempvalue); ++ if (tempvalue == 0) { ++ dmac_writew(dma->regbase + DMAC_CONFIG, ++ DMAC_CONFIG_VAL); ++ dmac_writew(dma->regbase + DMAC_INTTCCLEAR, 0xFF); ++ dmac_writew(dma->regbase + DMAC_INTERRCLR, 0xFF); ++ for (i = 0; i < DMAC_MAX_CHANNELS; i++) { ++ dmac_writew(dma->regbase + DMAC_CxCONFIG(i), ++ DMAC_CxDISABLE); ++ function[i] = NULL; ++ } ++ } ++ ++ /* creat LLI */ ++ /* alloc space for dma lli, as the source is uncontinuous, so... */ ++ ret = allocate_dmalli_space(pllihead, 1); ++ if (ret < 0) ++ return -1; ++ ++ if (request_irq(dma->irq, dmac_isr, 0, "hi_dma", dma)) { ++ dma_err("DMA Irq %d request failed\n", dma->irq); ++ free_dmalli_space(pllihead, 1); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++ ++/* ++ * alloc_dma_lli_space ++ * output: ++ * ppheadlli[0]: memory physics address ++ * ppheadlli[1]: virtual address ++ * ++ */ ++int allocate_dmalli_space(unsigned int *ppheadlli, unsigned int page_num) ++{ ++ dma_addr_t dma_phys; ++ void *dma_virt; ++ ++ dma_virt = dma_alloc_coherent(NULL, page_num*PAGE_SIZE, ++ &dma_phys, GFP_DMA | GFP_KERNEL); ++ if (NULL == dma_virt) { ++ dma_err("can't get dma mem from system\n"); ++ return -1; ++ } ++ ++ ppheadlli[0] = (unsigned int)(dma_phys); ++ ppheadlli[1] = (unsigned int)(dma_virt); ++ ++ return 0; ++} ++EXPORT_SYMBOL(allocate_dmalli_space); ++ ++/* ++ * free_dma_lli_space ++ */ ++int free_dmalli_space(unsigned int *ppheadlli, unsigned int page_num) ++{ ++ dma_addr_t dma_phys; ++ unsigned int dma_virt; ++ ++ dma_phys = (dma_addr_t)(ppheadlli[0]); ++ dma_virt = ppheadlli[1]; ++ ++ dma_free_coherent(NULL, page_num*PAGE_SIZE, ++ (void *)dma_virt, dma_phys); ++ ++ ppheadlli[0] = 0; ++ ppheadlli[1] = 0; ++ return 0; ++} ++EXPORT_SYMBOL(free_dmalli_space); ++ ++/* ++ * config register for memory to memory DMA transfer without LLI ++ * note: ++ * it is necessary to call dmac_channelstart for channel enable ++ */ ++int dmac_start_m2m(unsigned int channel, unsigned int psource, ++ unsigned int pdest, unsigned int uwnumtransfers) ++{ ++ unsigned int uwchannel_num, tmp_trasnsfer; ++ ++ if (uwnumtransfers > (MAXTRANSFERSIZE << 2)) { ++ dma_err("Invalidate transfer size,size=%x\n", uwnumtransfers); ++ return -EINVAL; ++ } ++ ++ uwchannel_num = channel; ++ ++ if ((uwchannel_num == DMAC_CHANNEL_INVALID) ++ || (uwchannel_num > CHANNEL_NUM)) { ++ pr_err("failure of DMAC channel allocation in M2M function!\n"); ++ return -EFAULT; ++ } ++ ++ /* dmac_writew (DMAC_CxCONFIG(uwchannel_num), DMAC_CxDISABLE); */ ++ dmac_writew(dma_regbase + DMAC_CxSRCADDR(uwchannel_num), psource); ++ dmac_writew(dma_regbase + DMAC_CxDESTADDR(uwchannel_num), pdest); ++ dmac_writew(dma_regbase + DMAC_CxLLI(uwchannel_num), 0); ++ tmp_trasnsfer = (uwnumtransfers >> 2) & 0xfff; ++ tmp_trasnsfer = tmp_trasnsfer | (DMAC_CxCONTROL_M2M & (~0xfff)); ++ dmac_writew(dma_regbase + DMAC_CxCONTROL(uwchannel_num), tmp_trasnsfer); ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(uwchannel_num), DMAC_CxCONFIG_M2M); ++ ++ return 0; ++} ++EXPORT_SYMBOL(dmac_start_m2m); ++ ++/* ++ * channel enable ++ * start a dma transfer immediately ++ */ ++int dmac_channelstart(unsigned int u32channel) ++{ ++ ++ unsigned int reg_value; ++ ++ if (u32channel >= DMAC_MAX_CHANNELS) { ++ dma_err("channel larger %d\n", DMAC_MAX_CHANNELS); ++ return -EINVAL; ++ } ++ ++ g_channel_status[u32channel] = DMAC_NOT_FINISHED; ++ dmac_readw(dma_regbase + DMAC_CxCONFIG(u32channel), reg_value); ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(u32channel), ++ (reg_value | DMAC_CHANNEL_ENABLE)); ++ ++ return 0; ++} ++EXPORT_SYMBOL(dmac_channelstart); ++ ++/* ++ * wait for transfer end ++ */ ++int dmac_wait(int channel) ++{ ++ int ret_result, ret = 0; ++ ++ if (channel < 0) ++ return -1; ++ ++ while (1) { ++ ret_result = dma_update_status(channel); ++ if (ret_result == -DMAC_CHN_ERROR) { ++ dma_err("Transfer Error.\n"); ++ ret = -1; ++ goto end; ++ } else if (ret_result == DMAC_NOT_FINISHED) ++ udelay(10); ++ else if (ret_result == DMAC_CHN_SUCCESS) { ++ ret = DMAC_CHN_SUCCESS; ++ goto end; ++ } ++ else if (ret_result == DMAC_CHN_VACANCY) { ++ ret = DMAC_CHN_SUCCESS; ++ goto end; ++ } else if (ret_result == -DMAC_CHN_TIMEOUT) { ++ dma_err("Timeout.\n"); ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(channel), DMAC_CxDISABLE); ++ g_channel_status[channel] = DMAC_CHN_VACANCY; ++ ret = -1; ++ goto end; ++ } ++ } ++end: ++ dmac_channelclose(channel); ++ return ret; ++} ++EXPORT_SYMBOL(dmac_wait); ++ ++/* ++ * buile LLI for memory to memory DMA transfer ++ */ ++int dmac_buildllim2m_isp(unsigned int *ppheadlli, unsigned int *psource, ++ unsigned int *pdest, unsigned int *length, ++ unsigned int lli_num) ++{ ++ unsigned int address, phy_address; ++ unsigned int j; ++ ++ if (ppheadlli != NULL) { ++ phy_address = (unsigned int)(ppheadlli[0]); ++ dma_debug("phy_address: 0x%X\n",phy_address); ++ address = (unsigned int)(ppheadlli[1]); ++ dma_debug("address: 0x%X\n",address); ++ for (j = 0; j < lli_num; j++) { ++ dma_debug("psource[%d]: 0x%X\n", j, psource[j]); ++ dmac_writew(address, psource[j]); ++ address += 4; ++ phy_address += 4; ++ dma_debug("pdest[%d]: 0x%X\n", j, pdest[j]); ++ dmac_writew(address, pdest[j]); ++ address += 4; ++ phy_address += 4; ++ ++ /* if the last node, next_lli_addr = 0*/ ++ if (j == (lli_num - 1)) ++ dmac_writew(address, 0); ++ else ++ dmac_writew(address, ++ (((phy_address + 8) & (~0x03)) ++ | DMAC_CxLLI_LM)); ++ ++ address += 4; ++ phy_address += 4; ++ ++ if (j == (lli_num - 1)) { ++ dmac_writew(address, ((DMAC_CxCONTROL_LLIM2M_ISP ++ &(~0xfff)) | (length[j]) ++ | 0x80000000)); ++ } else { ++ dmac_writew(address, ++ (((DMAC_CxCONTROL_LLIM2M_ISP&(~0xfff)) | ++ (length[j])) & 0x7fffffff)); ++ } ++ ++ address += 4; ++ phy_address += 4; ++ } ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(dmac_buildllim2m_isp); ++ ++/* ++ * buile LLI for memory to memory DMA transfer ++ */ ++int dmac_buildllim2m(unsigned int *ppheadlli, unsigned int pdest, ++ unsigned int psource, unsigned int totaltransfersize, ++ unsigned int uwnumtransfers) ++{ ++ unsigned int lli_num = 0; ++ unsigned int last_lli = 0; ++ unsigned int address , phy_address, srcaddr, denstaddr; ++ unsigned int j; ++ ++ lli_num = (totaltransfersize / uwnumtransfers); ++ ++ if ((totaltransfersize % uwnumtransfers) != 0) ++ last_lli = 1, ++lli_num; ++ ++ if (ppheadlli != NULL) { ++ phy_address = (unsigned int)(ppheadlli[0]); ++ address = (unsigned int)(ppheadlli[1]); ++ for (j = 0; j < lli_num; j++) { ++ srcaddr = (psource + (j*uwnumtransfers)); ++ dmac_writew(address, srcaddr); ++ address += 4; ++ phy_address += 4; ++ denstaddr = (pdest + (j*uwnumtransfers)); ++ dmac_writew(address, denstaddr); ++ address += 4; ++ phy_address += 4; ++ if (j == (lli_num - 1)) ++ dmac_writew(address, 0); ++ else ++ dmac_writew(address, ++ (((phy_address + 8) & (~0x03)) ++ | DMAC_CxLLI_LM)); ++ ++ address += 4; ++ phy_address += 4; ++ ++ if ((j == (lli_num - 1)) && (last_lli == 0)) ++ dmac_writew(address, ((DMAC_CxCONTROL_LLIM2M ++ &(~0xfff)) | (uwnumtransfers >> 2) ++ | 0x80000000)); ++ else if ((j == (lli_num - 1)) && (last_lli == 1)) ++ dmac_writew(address, ((DMAC_CxCONTROL_LLIM2M ++ & (~0xfff)) | ((totaltransfersize ++ % uwnumtransfers) >> 2) | 0x80000000)); ++ else ++ dmac_writew(address, ++ (((DMAC_CxCONTROL_LLIM2M&(~0xfff)) | ++ (uwnumtransfers >> 2)) & 0x7fffffff)); ++ ++ address += 4; ++ phy_address += 4; ++ } ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(dmac_buildllim2m); ++ ++/* ++ * disable channel ++ * used before the operation of register configuration ++ */ ++int dmac_channelclose(unsigned int channel) ++{ ++ unsigned int reg_value, count; ++ ++ if (channel >= DMAC_MAX_CHANNELS) { ++ dma_err("channel larger than total.\n"); ++ return -EINVAL; ++ } ++ ++ dmac_readw(dma_regbase + DMAC_CxCONFIG(channel), reg_value); ++ ++#define CHANNEL_CLOSE_IMMEDIATE ++#ifdef CHANNEL_CLOSE_IMMEDIATE ++ reg_value &= 0xFFFFFFFE; ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(channel) , reg_value); ++#else ++ reg_value |= DMAC_CONFIGURATIONx_HALT_DMA_ENABLE; ++ /*ignore incoming dma request*/ ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(channel), reg_value); ++ dmac_readw(dma_regbase + DMAC_CxCONFIG(channel), reg_value); ++ /*if FIFO is empty*/ ++ while ((reg_value & DMAC_CONFIGURATIONx_ACTIVE) ++ == DMAC_CONFIGURATIONx_ACTIVE) ++ dmac_readw(dma_regbase + DMAC_CxCONFIG(channel), reg_value); ++ reg_value &= 0xFFFFFFFE; ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(channel), reg_value); ++#endif ++ ++ dmac_readw(dma_regbase + DMAC_ENBLDCHNS, reg_value); ++ reg_value = reg_value & 0x00ff; ++ count = 0; ++ while (((reg_value >> channel) & 0x1) == 1) { ++ dmac_readw(dma_regbase + DMAC_ENBLDCHNS, reg_value); ++ reg_value = reg_value & 0x00ff; ++ if (count++ > 10000) { ++ dma_err("close failure.\n"); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(dmac_channelclose); ++ ++/* ++ * load configuration from LLI for memory to memory ++ */ ++int dmac_start_llim2m(unsigned int channel, unsigned int *pfirst_lli) ++{ ++ unsigned int uwchannel_num; ++ dmac_lli plli; ++ unsigned int first_lli; ++ ++ if (NULL == pfirst_lli) { ++ dma_err("Invalidate LLI head!\n"); ++ return -EFAULT; ++ } ++ ++ uwchannel_num = channel; ++ if ((uwchannel_num == DMAC_CHANNEL_INVALID) || ++ (uwchannel_num > 7)) { ++ dma_err("failure of DMAC channel allocation in"); ++ dma_err("LLIM2M function,channel=%x!\n ", uwchannel_num); ++ return -EINVAL; ++ } ++ ++ memset(&plli, 0, sizeof(plli)); ++ first_lli = (unsigned int)pfirst_lli[1]; ++ dmac_readw(first_lli, plli.src_addr); ++ dmac_readw(first_lli+4, plli.dst_addr); ++ dmac_readw(first_lli+8, plli.next_lli); ++ dmac_readw(first_lli+12, plli.lli_transfer_ctrl); ++ ++ dmac_channelclose(uwchannel_num); ++ dmac_writew(dma_regbase + DMAC_INTTCCLEAR, (0x1 << uwchannel_num)); ++ dmac_writew(dma_regbase + DMAC_INTERRCLR, (0x1 << uwchannel_num)); ++ dmac_writew(dma_regbase + DMAC_SYNC, 0x0); ++ ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(uwchannel_num), ++ DMAC_CxDISABLE); ++ dmac_writew(dma_regbase + DMAC_CxSRCADDR(uwchannel_num), ++ (unsigned int)(plli.src_addr)); ++ dmac_writew(dma_regbase + DMAC_CxDESTADDR(uwchannel_num), ++ (unsigned int)(plli.dst_addr)); ++ dmac_writew(dma_regbase + DMAC_CxLLI(uwchannel_num), ++ (unsigned int)(plli.next_lli)); ++ dmac_writew(dma_regbase + DMAC_CxCONTROL(uwchannel_num), ++ (unsigned int)(plli.lli_transfer_ctrl)); ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(uwchannel_num), ++ DMAC_CxCONFIG_LLIM2M); ++ ++ return 0; ++} ++EXPORT_SYMBOL(dmac_start_llim2m); ++ ++/* ++ * load configuration from LLI for memory and peripheral ++ */ ++int dmac_start_llim2p(unsigned int channel, unsigned int *pfirst_lli, ++ unsigned int uwperipheralid) ++{ ++ unsigned int uwchannel_num; ++ dmac_lli plli; ++ unsigned int first_lli; ++ unsigned int temp = 0; ++ ++ if (NULL == pfirst_lli) { ++ dma_err("Invalidate LLI head!\n"); ++ return -EINVAL; ++ } ++ uwchannel_num = channel; ++ if ((uwchannel_num == DMAC_CHANNEL_INVALID) || ++ (uwchannel_num > CHANNEL_NUM)) { ++ dma_err("failure of DMAC channel allocation in"); ++ dma_err("LLIM2P function, channel=%x!\n ", uwchannel_num); ++ return -EINVAL; ++ } ++ ++ memset(&plli, 0, sizeof(plli)); ++ first_lli = (unsigned int)pfirst_lli[1]; ++ dmac_readw(first_lli, plli.src_addr); ++ dmac_readw(first_lli+4, plli.dst_addr); ++ dmac_readw(first_lli+8, plli.next_lli); ++ dmac_readw(first_lli+12, plli.lli_transfer_ctrl); ++ ++ dmac_channelclose(uwchannel_num); ++ dmac_writew(dma_regbase + DMAC_INTTCCLEAR, (0x1< 15)) { ++ dma_err("Invalid peripheral id%x\n", uwperipheralid); ++ return -EINVAL; ++ } ++ ++ uwchannel_num = (int)channel; ++ if ((uwchannel_num == DMAC_CHANNEL_INVALID) ++ || (uwchannel_num > CHANNEL_NUM) || (uwchannel_num < 0)) { ++ dma_err("failure alloc\n"); ++ return -EFAULT; ++ } ++ ++ /* must modified with different peripheral */ ++ uwwidth = g_peripheral[uwperipheralid].transfer_width; ++ ++ /* check transfer direction * ++ * even number-->TX, odd number-->RX*/ ++ uwsrc_addr = memaddr; ++ uwdst_addr = (unsigned int)(g_peripheral[uwperipheralid].peri_addr); ++ ++ tmp = uwnumtransfers >> uwwidth; ++ if (tmp & (~0x0fff)) { ++ dma_err("Invalidate size%x\n", uwnumtransfers); ++ return -EINVAL; ++ } ++ ++ tmp = tmp & 0xfff; ++ uwtrans_control = tmp | ++ (g_peripheral[uwperipheralid].transfer_ctrl & (~0xfff)); ++ dmac_writew(dma_regbase + DMAC_INTTCCLEAR, (0x1<<(unsigned int)uwchannel_num)); ++ dmac_writew(dma_regbase + DMAC_INTERRCLR, (0x1<<(unsigned int)uwchannel_num)); ++ dmac_writew(dma_regbase + DMAC_CxSRCADDR(uwchannel_num), (unsigned int)uwsrc_addr); ++ dmac_writew(dma_regbase + DMAC_CxDESTADDR(uwchannel_num), (unsigned int)uwdst_addr); ++ dmac_writew(dma_regbase + DMAC_CxCONTROL(uwchannel_num), ++ (unsigned int)uwtrans_control); ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(uwchannel_num), ++ (g_peripheral[uwperipheralid].transfer_cfg)); ++ ++ return 0; ++} ++ ++/* ++ * enable memory and peripheral dma transfer ++ * note: ++ * it is necessary to call dmac_channelstart to enable channel ++ */ ++int dmac_start_p2m(unsigned int channel, unsigned int memaddr, ++ unsigned int uwperipheralid, unsigned int uwnumtransfers, ++ unsigned int next_lli_addr) ++{ ++ unsigned int uwtrans_control = 0; ++ unsigned int addtmp, tmp; ++ unsigned int uwdst_addr = 0, uwsrc_addr = 0; ++ unsigned int uwwidth; ++ int uwchannel_num; ++ ++ addtmp = memaddr; ++ ++ if ((uwperipheralid > 15)) { ++ dma_err("Invalid peripheral id%x\n", uwperipheralid); ++ return -EINVAL; ++ } ++ ++ uwchannel_num = (int)channel; ++ if ((uwchannel_num == DMAC_CHANNEL_INVALID) ++ || (uwchannel_num > 3) || (uwchannel_num < 0)) { ++ dma_err("failure alloc\n"); ++ return -EFAULT; ++ } ++ ++ /* must modified with different peripheral */ ++ uwwidth = g_peripheral[uwperipheralid].transfer_width; ++ ++ /* check transfer direction * ++ * even number-->TX, odd number-->RX*/ ++ uwsrc_addr = (unsigned int)(g_peripheral[uwperipheralid].peri_addr); ++ uwdst_addr = memaddr; ++ ++ tmp = uwnumtransfers >> uwwidth; ++ if (tmp & (~0x0fff)) { ++ dma_err("Invalidate size%x\n", uwnumtransfers); ++ return -EINVAL; ++ } ++ ++ tmp = tmp & 0xfff; ++ uwtrans_control = tmp | ++ (g_peripheral[uwperipheralid].transfer_ctrl & (~0xfff)); ++ dmac_writew(dma_regbase + DMAC_INTTCCLEAR, (0x1<<(unsigned int)uwchannel_num)); ++ dmac_writew(dma_regbase + DMAC_INTERRCLR, (0x1<<(unsigned int)uwchannel_num)); ++ dmac_writew(dma_regbase + DMAC_CxSRCADDR(uwchannel_num), ++ (unsigned int)uwsrc_addr); ++ dmac_writew(dma_regbase + DMAC_CxDESTADDR(uwchannel_num), ++ (unsigned int)uwdst_addr); ++ dmac_writew(dma_regbase + DMAC_CxCONTROL(uwchannel_num), ++ (unsigned int)uwtrans_control); ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(uwchannel_num), ++ (g_peripheral[uwperipheralid].transfer_cfg)); ++ ++ return 0; ++} ++ ++/* ++ * execute memory to memory dma transfer without LLI ++ */ ++int dmac_m2m_transfer(unsigned int source, unsigned int dest, ++ unsigned int length) ++{ ++ unsigned int ulchnn, dma_size = 0; ++ unsigned int dma_count, left_size; ++ ++ left_size = length; ++ dma_count = 0; ++ ulchnn = dmac_channel_allocate(NULL); ++ ++ ulchnn = 2; ++ ++ dma_err("use channel %d\n", ulchnn); ++ ++ while ((left_size >> 2) >= 0xffc) { ++ dma_size = 0xffc; ++ left_size -= (dma_size << 2); ++ dma_err("left_size is %x.", left_size); ++ dmac_start_m2m(ulchnn, (unsigned int)(source ++ + dma_count * (dma_size << 2)), ++ (unsigned int)(dest + dma_count * (dma_size << 2)), ++ (dma_size << 2)); ++ if (dmac_channelstart(ulchnn) != 0) { ++ dma_err("start channel error...\n"); ++ return -1; ++ } ++ ++ if (dmac_wait(ulchnn) != DMAC_CHN_SUCCESS) { ++ dma_err("dma transfer error...\n"); ++ return -1; ++ } ++ ++ dma_count++; ++ } ++ ++ dmac_start_m2m(ulchnn, (source + dma_count * (dma_size << 2)), ++ (dest + dma_count * (dma_size << 2)), (left_size << 2)); ++ ++ if (dmac_channelstart(ulchnn) != 0) ++ return -1; ++ ++ if (dmac_wait(ulchnn) != DMAC_CHN_SUCCESS) ++ return -1; ++ ++ return 0; ++} ++EXPORT_SYMBOL(dmac_m2m_transfer); ++ ++/* ++ * execute memory to peripheral dma transfer without LLI ++ */ ++int dmac_m2p_transfer(unsigned int memaddr, unsigned int uwperipheralid, ++ unsigned int length) ++{ ++ unsigned int ulchnn, dma_size = 0; ++ unsigned int dma_count, left_size; ++ unsigned int uwwidth; ++ ++ left_size = length; ++ dma_count = 0; ++ ++ ulchnn = dmac_channel_allocate(NULL); ++ if (DMAC_CHANNEL_INVALID == ulchnn) ++ return -1; ++ ++ uwwidth = g_peripheral[uwperipheralid].transfer_width; ++ ++ while ((left_size >> uwwidth) >= 0xffc) { ++ dma_size = 0xffc; ++ left_size -= (dma_size << uwwidth); ++ ++ if (dmac_start_m2p(ulchnn, ++ (unsigned int)(memaddr + dma_count * dma_size), ++ uwperipheralid, (dma_size << uwwidth), 0) < 0) ++ return -1; ++ ++ if (dmac_channelstart(ulchnn) != 0) ++ return -1; ++ ++ if (dmac_wait(ulchnn) != DMAC_CHN_SUCCESS) { ++ dmac_channel_free(ulchnn); ++ return -1; ++ } ++ ++ dma_count++; ++ } ++ ++ pr_debug("memaddr=0x%x\n", (unsigned int)(memaddr ++ + dma_count * dma_size)); ++ ++ if (dmac_start_m2p(ulchnn, ++ (unsigned int)(memaddr + dma_count * dma_size), ++ uwperipheralid, left_size, 0) < 0) ++ return -1; ++ ++ if (dmac_channelstart(ulchnn) != 0) ++ return -1; ++ ++ return ulchnn; ++} ++ ++/* ++ * execute memory to peripheral dma transfer without LLI ++ */ ++int dmac_p2m_transfer(unsigned int memaddr, unsigned int uwperipheralid, ++ unsigned int length) ++{ ++ unsigned int ulchnn, dma_size = 0; ++ unsigned int dma_count, left_size; ++ unsigned int uwwidth; ++ ++ left_size = length; ++ dma_count = 0; ++ ++ ulchnn = dmac_channel_allocate(NULL); ++ if (DMAC_CHANNEL_INVALID == ulchnn) ++ return -1; ++ ++ uwwidth = g_peripheral[uwperipheralid].transfer_width; ++ ++ while ((left_size >> uwwidth) >= 0xffc) { ++ dma_size = 0xffc; ++ left_size -= (dma_size << uwwidth); ++ ++ if (dmac_start_p2m(ulchnn, ++ (unsigned int)(memaddr + dma_count * dma_size), ++ uwperipheralid, (dma_size << uwwidth), 0) < 0) ++ return -1; ++ ++ if (dmac_channelstart(ulchnn) != 0) ++ return -1; ++ ++ if (dmac_wait(ulchnn) != DMAC_CHN_SUCCESS) { ++ dmac_channel_free(ulchnn); ++ return -1; ++ } ++ ++ dma_count++; ++ } ++ ++ pr_debug("memaddr=0x%x\n", (unsigned int)(memaddr ++ + dma_count * dma_size)); ++ ++ if (dmac_start_p2m(ulchnn, ++ (unsigned int)(memaddr + dma_count * dma_size), ++ uwperipheralid, left_size, 0) < 0) ++ return -1; ++ ++ if (dmac_channelstart(ulchnn) != 0) ++ return -1; ++ ++ return ulchnn; ++} ++ ++/* ++ * memory to memory dma transfer with LLI ++ * ++ * @source ++ * @dest ++ * @length ++ * @num ++ * */ ++int do_dma_llim2m_isp(unsigned int *source, ++ unsigned int *dest, ++ unsigned int *length, ++ unsigned int num) ++{ ++ unsigned int chnn; ++ int ret = 0; ++ ++ /* the dma channel is default using 2 */ ++ chnn = 2; ++ ++ ret = dmac_buildllim2m_isp(pllihead, source, dest, length, num); ++ ++ if (ret) { ++ dma_err("build lli error...\n"); ++ return -1; ++ } ++ ++ /* dmac_register_isr(chnn, dmac_channel_close); */ ++ ret = dmac_start_llim2m(chnn, pllihead); ++ if (ret) ++ return -1; ++ ++ if (dmac_channelstart(chnn) != 0) { ++ dma_err("start channel error...\n"); ++ return -1; ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL(do_dma_llim2m_isp); ++ ++int do_dma_m2p(unsigned int memaddr, unsigned int peripheral_addr, ++ unsigned int length) ++{ ++ int ret = 0; ++ int uwperipheralid; ++ ++ uwperipheralid = dmac_check_request(peripheral_addr, TX); ++ if (uwperipheralid < 0) { ++ dma_err("m2p:Invalid devaddr\n"); ++ return -1; ++ } ++ ++ ret = dmac_m2p_transfer(memaddr, uwperipheralid, length); ++ if (ret == -1) { ++ dma_err("m2p:trans err\n"); ++ return -1; ++ } ++ ++ return ret; ++} ++ ++int do_dma_p2m(unsigned int memaddr, unsigned int peripheral_addr, ++ unsigned int length) ++{ ++ int ret = -1; ++ int uwperipheralid; ++ ++ uwperipheralid = dmac_check_request(peripheral_addr, RX); ++ if (uwperipheralid < 0) { ++ dma_err("p2m:Invalid devaddr.\n"); ++ return -1; ++ } ++ ++ ret = dmac_p2m_transfer(memaddr, uwperipheralid, length); ++ if (ret == -1) { ++ dma_err("p2m:trans err\n"); ++ return -1; ++ } ++ ++ return ret; ++} ++ ++/* ++ * Apply DMA interrupt resource ++ * init channel state ++ */ ++static int hi_dmac_probe(struct platform_device *platdev) ++{ ++ unsigned int i; ++ struct hidmac_host *dma; ++ struct resource *res; ++ int ret; ++ ++ dma = devm_kzalloc(&platdev->dev, sizeof(*dma), GFP_KERNEL); ++ if (!dma) ++ return -ENOMEM; ++ ++ res = platform_get_resource(platdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&platdev->dev, "no mmio resource\n"); ++ return -ENODEV; ++ } ++ ++ dma->regbase = devm_ioremap_resource(&platdev->dev, res); ++ if (IS_ERR(dma->regbase)) ++ return PTR_ERR(dma->regbase); ++ ++ dma->clk = devm_clk_get(&platdev->dev, NULL); ++ if (IS_ERR(dma->clk)) ++ return PTR_ERR(dma->clk); ++ ++ dma->rstc = devm_reset_control_get(&platdev->dev, "dma-reset"); ++ if (IS_ERR(dma->rstc)) ++ return PTR_ERR(dma->rstc); ++ ++ dma->irq = platform_get_irq(platdev, 0); ++ if (unlikely(dma->irq < 0)) ++ return -ENODEV; ++ ++ dma_regbase = dma->regbase; ++ ++ ret = dmac_init(dma); ++ if (ret) ++ return -ENODEV; ++ ++ platform_set_drvdata(platdev, dma); ++ ++ for (i = 0; i < DMAC_MAX_CHANNELS; i++) ++ g_channel_status[i] = DMAC_CHN_VACANCY; ++ ++ dev_info(&platdev->dev, "hidmac probe!\n"); ++ return ret; ++} ++ ++static int hi_dmac_remove(struct platform_device *platdev) ++{ ++ int i; ++ struct hidmac_host *dma = platform_get_drvdata(platdev); ++ ++ clk_disable_unprepare(dma->clk); ++ ++ for (i = 0; i < DMAC_MAX_CHANNELS; i++) ++ g_channel_status[i] = DMAC_CHN_VACANCY; ++ ++ free_dmalli_space(pllihead, 1); ++ ++ return 0; ++} ++ ++static int hi_dmac_suspend(struct platform_device *platdev, ++ pm_message_t state) ++{ ++ int i; ++ struct hidmac_host *dma = platform_get_drvdata(platdev); ++ ++ clk_prepare_enable(dma->clk); ++ ++ for (i = 0; i < DMAC_MAX_CHANNELS; i++) ++ g_channel_status[i] = DMAC_CHN_VACANCY; ++ ++ clk_disable_unprepare(dma->clk); ++ ++ return 0; ++} ++ ++static int hi_dmac_resume(struct platform_device *platdev) ++{ ++ int i; ++ struct hidmac_host *dma = platform_get_drvdata(platdev); ++ unsigned int tempvalue; ++ ++ clk_prepare_enable(dma->clk); ++ reset_control_deassert(dma->rstc); ++ ++ dmac_readw(dma->regbase + DMAC_CONFIG, tempvalue); ++ if (tempvalue == 0) { ++ dmac_writew(dma->regbase + DMAC_CONFIG, ++ DMAC_CONFIG_VAL); ++ dmac_writew(dma->regbase + DMAC_INTTCCLEAR, 0xFF); ++ dmac_writew(dma->regbase + DMAC_INTERRCLR, 0xFF); ++ for (i = 0; i < DMAC_MAX_CHANNELS; i++) { ++ dmac_writew(dma->regbase + DMAC_CxCONFIG(i), ++ DMAC_CxDISABLE); ++ function[i] = NULL; ++ } ++ } ++ ++ for (i = 0; i < DMAC_MAX_CHANNELS; i++) ++ g_channel_status[i] = DMAC_CHN_VACANCY; ++ ++ return 0; ++} ++ ++static const struct of_device_id hisi_dmac_dt_ids[] = { ++ { .compatible = "hisilicon,hisi-dmac"}, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, hisi_dmac_dt_ids); ++ ++static struct platform_driver hisi_dmac_driver = { ++ .driver = { ++ .name = "hisi-dmac", ++ .of_match_table = hisi_dmac_dt_ids, ++ }, ++ .probe = hi_dmac_probe, ++ .remove = hi_dmac_remove, ++ .suspend = hi_dmac_suspend, ++ .resume = hi_dmac_resume, ++}; ++ ++module_platform_driver(hisi_dmac_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Hisilicon"); ++MODULE_DESCRIPTION("HiSilicon DMA Controller driver"); +diff --git a/drivers/hidmac/hi_pl08x.h b/drivers/hidmac/hi_pl08x.h +new file mode 100644 +index 0000000..2213e3a +--- /dev/null ++++ b/drivers/hidmac/hi_pl08x.h +@@ -0,0 +1,79 @@ ++/* ./drivers/hidmac/hi_dmac.h ++ * ++ * ++ * History: ++ * 17-August-2006 create this file ++ */ ++#ifndef __HI_DMAC_H__ ++#define __HI_DMAC_H__ ++ ++#define dmac_writew(addr, value)\ ++ writel(value, (void *)(addr)) ++#define dmac_readw(addr, v)\ ++ v = readl((void *)(addr)) ++ ++/*#define DMA_DEBUG*/ ++#ifdef DMA_DEBUG ++#define dma_debug printk ++#else ++#define dma_debug(fmt, ...) do {} while (0); ++#endif ++ ++#define DMAC_CONFIGURATIONx_HALT_DMA_ENABLE (0x01L<<18) ++#define DMAC_CONFIGURATIONx_ACTIVE (0x01L<<17) ++#define DMAC_CONFIGURATIONx_CHANNEL_ENABLE 1 ++#define DMAC_CONFIGURATIONx_CHANNEL_DISABLE 0 ++ ++/*definition for the return value*/ ++#define DMAC_ERROR_BASE 100 ++#define DMAC_CHANNEL_INVALID (DMAC_ERROR_BASE+1) ++ ++#define DMAC_TRXFERSIZE_INVALID (DMAC_ERROR_BASE+2) ++#define DMAC_SOURCE_ADDRESS_INVALID (DMAC_ERROR_BASE+3) ++#define DMAC_DESTINATION_ADDRESS_INVALID (DMAC_ERROR_BASE+4) ++#define DMAC_MEMORY_ADDRESS_INVALID (DMAC_ERROR_BASE+5) ++#define DMAC_PERIPHERAL_ID_INVALID (DMAC_ERROR_BASE+6) ++#define DMAC_DIRECTION_ERROR (DMAC_ERROR_BASE+7) ++#define DMAC_TRXFER_ERROR (DMAC_ERROR_BASE+8) ++#define DMAC_LLIHEAD_ERROR (DMAC_ERROR_BASE+9) ++#define DMAC_SWIDTH_ERROR (DMAC_ERROR_BASE+0xa) ++#define DMAC_LLI_ADDRESS_INVALID (DMAC_ERROR_BASE+0xb) ++#define DMAC_TRANS_CONTROL_INVALID (DMAC_ERROR_BASE+0xc) ++#define DMAC_MEMORY_ALLOCATE_ERROR (DMAC_ERROR_BASE+0xd) ++#define DMAC_NOT_FINISHED (DMAC_ERROR_BASE+0xe) ++ ++#define DMAC_TIMEOUT (DMAC_ERROR_BASE+0xf) ++#define DMAC_CHN_SUCCESS (DMAC_ERROR_BASE+0x10) ++#define DMAC_CHN_ERROR (DMAC_ERROR_BASE+0x11) ++#define DMAC_CHN_TIMEOUT (DMAC_ERROR_BASE+0x12) ++#define DMAC_CHN_ALLOCAT (DMAC_ERROR_BASE+0x13) ++#define DMAC_CHN_VACANCY (DMAC_ERROR_BASE+0x14) ++ ++#define DMAC_CONFIGURATIONx_ACTIVE_NOT 0 ++ ++/*the means the bit in the channel control register*/ ++#define DMAC_TRANS_SIZE 0xff0 ++ ++/*DMAC peripheral structure*/ ++typedef struct dmac_peripheral { ++ /* peripherial ID*/ ++ unsigned int peri_id; ++ /*peripheral data register address*/ ++ unsigned int peri_addr; ++ /*default channel control word*/ ++ unsigned int transfer_ctrl; ++ /*default channel configuration word*/ ++ unsigned int transfer_cfg; ++ /*default channel configuration word*/ ++ unsigned int transfer_width; ++} dmac_peripheral; ++ ++typedef struct mem_addr { ++ unsigned int addr_base; ++ unsigned int size; ++} mem_addr; ++ ++typedef unsigned int dma_addr_t; ++/* #define PAGE_SIZE 0x1000 */ ++ ++#endif /* End of #ifndef __HI_INC_ECSDMACC_H__ */ +diff --git a/drivers/hidmac/hidmac_hi3516a.h b/drivers/hidmac/hidmac_hi3516a.h +new file mode 100644 +index 0000000..3becefb +--- /dev/null ++++ b/drivers/hidmac/hidmac_hi3516a.h +@@ -0,0 +1,159 @@ ++#ifndef __HI_DMAC_HI3516A_H__ ++#define __HI_DMAC_HI3516A_H__ ++ ++#define DDRAM_ADRS 0x80000000 /* fixed */ ++#define DDRAM_SIZE 0x1FFFFFFF /* 512M DDR. */ ++ ++#define FLASH_BASE 0x10000000 ++#define FLASH_SIZE 0x04000000 /* (32MB) */ ++ ++#define DMAC_INTSTATUS 0X00 ++#define DMAC_INTTCSTATUS 0X04 ++#define DMAC_INTTCCLEAR 0X08 ++#define DMAC_INTERRORSTATUS 0X0C ++ ++#define DMAC_INTERRCLR 0X10 ++#define DMAC_RAWINTTCSTATUS 0X14 ++#define DMAC_RAWINTERRORSTATUS 0X18 ++#define DMAC_ENBLDCHNS 0X1C ++#define DMAC_CONFIG 0X30 ++#define DMAC_SYNC 0X34 ++ ++#define DMAC_MAXTRANSFERSIZE 0x0fff /*the max length is denoted by 0-11bit*/ ++#define MAXTRANSFERSIZE DMAC_MAXTRANSFERSIZE ++#define DMAC_CxDISABLE 0x00 ++#define DMAC_CxENABLE 0x01 ++ ++/*the definition for DMAC channel register*/ ++#define DMAC_CxBASE(i) (0x100+i*0x20) ++#define DMAC_CxSRCADDR(i) DMAC_CxBASE(i) ++#define DMAC_CxDESTADDR(i) (DMAC_CxBASE(i)+0x04) ++#define DMAC_CxLLI(i) (DMAC_CxBASE(i)+0x08) ++#define DMAC_CxCONTROL(i) (DMAC_CxBASE(i)+0x0C) ++#define DMAC_CxCONFIG(i) (DMAC_CxBASE(i)+0x10) ++ ++/*the means the bit in the channel control register*/ ++#define DMAC_CxCONTROL_M2M 0x9d480000 /* Dwidth=32,burst size=4 */ ++#define DMAC_CxCONTROL_LLIM2M 0x0f480000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxCONTROL_LLIM2M_ISP 0x0b489000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxCONTROL_LLIP2M 0x0a000000 ++#define DMAC_CxCONTROL_LLIM2P 0x86089000 ++#define DMAC_CxLLI_LM 0x01 ++ ++#define NUM_HAL_INTERRUPT_DMAC (14 + 16) ++ ++#define DMAC_CxCONFIG_M2M 0xc000 ++#define DMAC_CxCONFIG_LLIM2M 0xc000 ++ ++/*#define DMAC_CxCONFIG_M2M 0x4001*/ ++#define DMAC_CHANNEL_ENABLE 1 ++#define DMAC_CHANNEL_DISABLE 0xfffffffe ++ ++#define DMAC_CxCONTROL_P2M 0x89409000 ++#define DMAC_CxCONFIG_P2M 0xd000 ++ ++#define DMAC_CxCONTROL_M2P 0x86089000 ++#define DMAC_CxCONFIG_M2P 0xc800 ++ ++#define DMAC_CxCONFIG_SIO_P2M 0x0000d000 ++#define DMAC_CxCONFIG_SIO_M2P 0x0000c800 ++ ++/*default the config and sync regsiter for DMAC controller*/ ++/*M1,M2 little endian, enable DMAC*/ ++#define DMAC_CONFIG_VAL 0x01 ++/*enable the sync logic for the 16 peripheral*/ ++#define DMAC_SYNC_VAL 0x0 ++ ++#define DMAC_MAX_PERIPHERALS 16 ++#define MEM_MAX_NUM 2 ++#define CHANNEL_NUM CONFIG_HI_DMAC_CHANNEL_NUM ++#define DMAC_MAX_CHANNELS CHANNEL_NUM ++ ++#define MMC_REG_BASE 0x10030000 ++#define MMC_RX_REG (MMC_REG_BASE+0x100) ++#define MMC_TX_REG (MMC_REG_BASE+0x100) ++ ++#define UART0_REG_BASE 0x20080000 ++#define UART0_DATA_REG (UART0_REG_BASE + 0x0) ++ ++#define UART1_REG_BASE 0x20090000 ++#define UART1_DATA_REG (UART1_REG_BASE + 0x0) ++ ++#define UART2_REG_BASE 0x200A0000 ++#define UART2_DATA_REG (UART2_REG_BASE + 0x0) ++ ++#define UART3_REG_BASE 0x200B0000 ++#define UART3_DATA_REG (UART3_REG_BASE + 0x0) ++ ++#define SPI0_REG_BASE 0x200c0000 ++#define SPI0_DATA_REG (SPI0_REG_BASE + 0x08) ++ ++#define SPI1_REG_BASE 0x200e0000 ++#define SPI1_DATA_REG (SPI1_REG_BASE + 0x08) ++ ++#define I2C0_REG_BASE 0x200d0000 ++#define I2C0_DATA_REG (I2C0_REG_BASE + 0x10) ++ ++#define I2C1_REG_BASE 0x20240000 ++#define I2C1_DATA_REG (I2C1_REG_BASE + 0x10) ++ ++#define PERI_8BIT_MODE 0 ++#define PERI_16BIT_MODE 1 ++#define PERI_32BIT_MODE 2 ++/*the transfer control and configuration value for different peripheral*/ ++ ++extern int g_channel_status[CHANNEL_NUM]; ++ ++/* ++ * DMA config array! ++ * DREQ, FIFO, CONTROL, CONFIG, BITWIDTH ++ */ ++dmac_peripheral g_peripheral[DMAC_MAX_PERIPHERALS] = { ++ /* DREQ, FIFO, CONTROL, CONFIG, WIDTH */ ++ /*periphal 0: I2C0/I2C1 RX*/ ++ { 0, I2C0_DATA_REG, 0x99000000, 0x1000, PERI_8BIT_MODE}, ++ /*periphal 1: I2C0/I2C1 TX*/ ++ { 1, I2C0_DATA_REG, 0x96000000, 0x0840, PERI_8BIT_MODE}, ++ /*periphal 2: I2C1/I2C2 RX*/ ++ { 2, I2C1_DATA_REG, 0x99000000, 0x1004, PERI_8BIT_MODE}, /* 8bit width */ ++ /*periphal 3: I2C1/I2C2 TX*/ ++ { 3, I2C1_DATA_REG, 0x96000000, 0x08c0, PERI_8BIT_MODE}, /* 8bit width */ ++ ++ /*periphal 4: UART0 RX*/ ++ { 4, UART0_DATA_REG, DMAC_CxCONTROL_LLIP2M, DMAC_CxCONFIG_P2M | (4 << 1), PERI_8BIT_MODE}, ++ ++ /*periphal 5: UART0 TX*/ ++ { 5, UART0_DATA_REG, DMAC_CxCONTROL_LLIM2P, DMAC_CxCONFIG_M2P | (5 << 1), PERI_8BIT_MODE}, ++ ++ /*periphal 6: UART1 RX*/ ++ { 6, UART1_DATA_REG, DMAC_CxCONTROL_LLIP2M, DMAC_CxCONFIG_P2M | (6 << 1), PERI_8BIT_MODE}, ++ ++ /*periphal 7: UART1 TX*/ ++ { 7, UART1_DATA_REG, DMAC_CxCONTROL_LLIM2P, DMAC_CxCONFIG_M2P | (7 << 1), PERI_8BIT_MODE}, ++ ++ /*periphal 8: UART2 RX*/ ++ { 8, UART2_DATA_REG, DMAC_CxCONTROL_LLIP2M, DMAC_CxCONFIG_P2M | (8 << 1), PERI_8BIT_MODE}, ++ ++ /*periphal 9: UART2 TX*/ ++ { 9, UART2_DATA_REG, DMAC_CxCONTROL_LLIM2P, DMAC_CxCONFIG_M2P | (9 << 1), PERI_8BIT_MODE}, ++ ++ /*periphal 10: UART3 RX*/ ++ { 10, UART3_DATA_REG, DMAC_CxCONTROL_LLIP2M, DMAC_CxCONFIG_P2M | (10 << 1), PERI_8BIT_MODE}, ++ ++ /*periphal 11: UART0 TX*/ ++ { 11, UART3_DATA_REG, DMAC_CxCONTROL_LLIM2P, DMAC_CxCONFIG_M2P | (11 << 1), PERI_8BIT_MODE}, ++ ++ /*periphal 12: SSP1 RX*/ ++ { 12, 0, 0, 0, 0}, ++ ++ /*periphal 13: SSP1 TX*/ ++ { 13, 0, 0, 0, 0}, ++ ++ /*periphal 14: SSP0 RX*/ ++ { 14, 0, 0, 0, 0}, ++ ++ /*periphal 15: SSP0 TX*/ ++ { 15, 0, 0, 0, 0}, ++}; ++ ++#endif +diff --git a/drivers/hidmac/hidmac_hi3518ev20x.h b/drivers/hidmac/hidmac_hi3518ev20x.h +new file mode 100644 +index 0000000..92d8db7 +--- /dev/null ++++ b/drivers/hidmac/hidmac_hi3518ev20x.h +@@ -0,0 +1,151 @@ ++#ifndef __HI_DMAC_HI3518EV200_H__ ++#define __HI_DMAC_HI3518EV200_H__ ++ ++#define DDRAM_ADRS 0x80000000 /* fixed */ ++#define DDRAM_SIZE 0x3FFFFFFF /* 1GB DDR. */ ++ ++#define FLASH_BASE 0x10000000 ++#define FLASH_SIZE 0x04000000 /* (32MB) */ ++ ++ ++#define DMAC_INTSTATUS 0X00 ++#define DMAC_INTTCSTATUS 0X04 ++#define DMAC_INTTCCLEAR 0X08 ++#define DMAC_INTERRORSTATUS 0X0C ++ ++#define DMAC_INTERRCLR 0X10 ++#define DMAC_RAWINTTCSTATUS 0X14 ++#define DMAC_RAWINTERRORSTATUS 0X18 ++#define DMAC_ENBLDCHNS 0X1C ++#define DMAC_CONFIG 0X30 ++#define DMAC_SYNC 0X34 ++ ++#define DMAC_MAXTRANSFERSIZE 0x0fff /*the max length is denoted by 0-11bit*/ ++#define MAXTRANSFERSIZE DMAC_MAXTRANSFERSIZE ++#define DMAC_CxDISABLE 0x00 ++#define DMAC_CxENABLE 0x01 ++ ++/*the definition for DMAC channel register*/ ++#define DMAC_CxBASE(i) (0x100+i*0x20) ++#define DMAC_CxSRCADDR(i) DMAC_CxBASE(i) ++#define DMAC_CxDESTADDR(i) (DMAC_CxBASE(i)+0x04) ++#define DMAC_CxLLI(i) (DMAC_CxBASE(i)+0x08) ++#define DMAC_CxCONTROL(i) (DMAC_CxBASE(i)+0x0C) ++#define DMAC_CxCONFIG(i) (DMAC_CxBASE(i)+0x10) ++ ++/*the means the bit in the channel control register*/ ++#define DMAC_CxCONTROL_M2M 0x9d480000 /* Dwidth=32,burst size=4 */ ++#define DMAC_CxCONTROL_LLIM2M 0x0f480000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxCONTROL_LLIM2M_ISP 0x0b489000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxLLI_LM 0x01 ++ ++#define DMAC_CxCONFIG_M2M 0xc000 ++#define DMAC_CxCONFIG_LLIM2M 0xc000 ++ ++/*#define DMAC_CxCONFIG_M2M 0x4001*/ ++#define DMAC_CHANNEL_ENABLE 1 ++#define DMAC_CHANNEL_DISABLE 0xfffffffe ++ ++#define DMAC_CxCONTROL_P2M 0x89409000 ++#define DMAC_CxCONFIG_P2M 0xd000 ++ ++#define DMAC_CxCONTROL_M2P 0x86089000 ++#define DMAC_CxCONFIG_M2P 0xc800 ++ ++#define DMAC_CxCONFIG_SIO_P2M 0x0000d000 ++#define DMAC_CxCONFIG_SIO_M2P 0x0000c800 ++ ++/*default the config and sync regsiter for DMAC controller*/ ++/*M1,M2 little endian, enable DMAC*/ ++#define DMAC_CONFIG_VAL 0x01 ++/*enable the sync logic for the 16 peripheral*/ ++#define DMAC_SYNC_VAL 0x0 ++ ++#define DMAC_MAX_PERIPHERALS 16 ++#define MEM_MAX_NUM 2 ++#define CHANNEL_NUM CONFIG_HI_DMAC_CHANNEL_NUM ++#define DMAC_MAX_CHANNELS CHANNEL_NUM ++ ++#define REG_BASE_UART0 0x20080000 ++#define UART0_DATA_REG (REG_BASE_UART0 + 0x0) ++ ++#define REG_BASE_UART1 0x20090000 ++#define UART1_DATA_REG (REG_BASE_UART1 + 0x0) ++ ++#define REG_BASE_UART2 0x200a0000 ++#define UART2_DATA_REG (REG_BASE_UART2 + 0x0) ++ ++#define REG_BASE_SPI0 0x200c0000 ++#define SPI0_DATA_REG (REG_BASE_SPI0 + 0x08) ++ ++#define REG_BASE_SPI1 0x200e0000 ++#define SPI1_DATA_REG (REG_BASE_SPI1 + 0x08) ++ ++#define REG_BASE_I2C0 0x200d0000 ++#define I2C0_DATA_REG (REG_BASE_I2C0 + 0x10) ++ ++#define REG_BASE_I2C1 0x20240000 ++#define I2C1_DATA_REG (REG_BASE_I2C1 + 0x10) ++ ++#define REG_BASE_I2C2 0x20250000 ++#define I2C2_DATA_REG (REG_BASE_I2C2 + 0x10) ++ ++/*the transfer control and configuration value for different peripheral*/ ++ ++extern int g_channel_status[CHANNEL_NUM]; ++ ++ ++/* ++ * DMA config array! ++ * DREQ, FIFO, CONTROL, CONFIG, BITWIDTH ++ */ ++dmac_peripheral g_peripheral[DMAC_MAX_PERIPHERALS] = { ++ /* periphal 0: I2C0 RX, 8bit width */ ++ {0, I2C0_DATA_REG, 0x99000000, 0x1000, 0}, ++ ++ /* periphal 1: I2C0 TX, 8bit width */ ++ {1, I2C0_DATA_REG, 0x96000000, 0x0840, 0}, ++ ++ /*periphal 2: I2C1 RX, 8bit width */ ++ {2, I2C1_DATA_REG, 0x99000000, 0x1004, 0}, ++ ++ /*periphal 3: I2C1 TX, 8bit width */ ++ {3, I2C1_DATA_REG, 0x96000000, 0x08c0, 0}, ++ ++ /*periphal 4: UART0 RX, 8bit width */ ++ {4, UART0_DATA_REG, 0x99000000, 0xd008, 0}, ++ ++ /*periphal 5: UART0 TX, 8bit width */ ++ {5, UART0_DATA_REG, 0x96000000, 0xc940, 0}, ++ ++ /*periphal 6: UART1 RX, 8bit width */ ++ {6, UART1_DATA_REG, 0x99000000, 0xd00c, 0}, ++ ++ /*periphal 7: UART1 TX, 8bit width */ ++ {7, UART1_DATA_REG, 0x96000000, 0xc9c0, 0}, ++ ++ /*periphal 8: UART2 RX, 8bit width */ ++ {8, UART2_DATA_REG, 0x99000000, 0xd010, 0}, ++ ++ /*periphal 9: UART2 TX, 8bit width */ ++ {9, UART2_DATA_REG, 0x96000000, 0xca40, 0}, ++ ++ /*periphal 10: I2C2 RX, 8bit width */ ++ {10, I2C2_DATA_REG, 0x99000000, 0x1014, 0}, ++ ++ /*periphal 11: I2C2 TX, 8bit width */ ++ {11, I2C2_DATA_REG, 0x96000000, 0x0ac0, 0}, ++ ++ /*periphal 12: SSP1 RX, 8bit width */ ++ {12, 0, 0x99000000, 0xd018, 0}, ++ ++ /*periphal 13: SSP1 TX, 8bit width */ ++ {13, 0, 0x96000000, 0xcb40, 0}, ++ ++ /*periphal 14: SSP0 RX, 8bit width */ ++ {14, 0, 0x99000000, 0xd01c, 0}, ++ ++ /*periphal 15: SSP0 TX, 8bit width */ ++ {15, 0, 0x96000000, 0xcbc0, 0}, ++}; ++#endif +diff --git a/drivers/hidmac/hidmac_hi3521a.h b/drivers/hidmac/hidmac_hi3521a.h +new file mode 100644 +index 0000000..f094b85 +--- /dev/null ++++ b/drivers/hidmac/hidmac_hi3521a.h +@@ -0,0 +1,135 @@ ++#ifndef __HI_DMAC_HI3521A_H__ ++#define __HI_DMAC_HI3521A_H__ ++ ++#define DDR_MEM_BASE 0x80000000 ++#define DDRAM_ADRS DDR_MEM_BASE ++#define DDRAM_SIZE 0x7FFFFFFF /* 2GB DDR. */ ++ ++#define FLASH_BASE 0x10000000 ++#define FLASH_SIZE 0x04000000 /* (32MB) */ ++ ++#define DMAC_INTSTATUS 0X00 ++#define DMAC_INTTCSTATUS 0X04 ++#define DMAC_INTTCCLEAR 0X08 ++#define DMAC_INTERRORSTATUS 0X0C ++ ++#define DMAC_INTERRCLR 0X10 ++#define DMAC_RAWINTTCSTATUS 0X14 ++#define DMAC_RAWINTERRORSTATUS 0X18 ++#define DMAC_ENBLDCHNS 0X1C ++#define DMAC_CONFIG 0X30 ++#define DMAC_SYNC 0X34 ++ ++#define DMAC_MAXTRANSFERSIZE 0x0fff /*the max length is denoted by 0-11bit*/ ++#define MAXTRANSFERSIZE DMAC_MAXTRANSFERSIZE ++#define DMAC_CxDISABLE 0x00 ++#define DMAC_CxENABLE 0x01 ++ ++/*the definition for DMAC channel register*/ ++#define DMAC_CxBASE(i) (0x100+i*0x20) ++#define DMAC_CxSRCADDR(i) DMAC_CxBASE(i) ++#define DMAC_CxDESTADDR(i) (DMAC_CxBASE(i)+0x04) ++#define DMAC_CxLLI(i) (DMAC_CxBASE(i)+0x08) ++#define DMAC_CxCONTROL(i) (DMAC_CxBASE(i)+0x0C) ++#define DMAC_CxCONFIG(i) (DMAC_CxBASE(i)+0x10) ++ ++/*the means the bit in the channel control register*/ ++#define DMAC_CxCONTROL_M2M 0x9d480000 /* Dwidth=32,burst size=4 */ ++#define DMAC_CxCONTROL_LLIM2M 0x0f480000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxCONTROL_LLIM2M_ISP 0x0b489000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxCONTROL_LLIP2M 0x0a000000 ++#define DMAC_CxCONTROL_LLIM2P 0x86089000 ++#define DMAC_CxLLI_LM 0x01 ++ ++#define DMAC_CxCONFIG_M2M 0xc000 ++#define DMAC_CxCONFIG_LLIM2M 0xc000 ++ ++/*#define DMAC_CxCONFIG_M2M 0x4001*/ ++#define DMAC_CHANNEL_ENABLE 1 ++#define DMAC_CHANNEL_DISABLE 0xfffffffe ++ ++#define DMAC_CxCONTROL_P2M 0x89409000 ++#define DMAC_CxCONFIG_P2M 0xd000 ++ ++#define DMAC_CxCONTROL_M2P 0x86089000 ++#define DMAC_CxCONFIG_M2P 0xc800 ++ ++#define DMAC_CxCONFIG_SIO_P2M 0x0000d000 ++#define DMAC_CxCONFIG_SIO_M2P 0x0000c800 ++ ++/*default the config and sync regsiter for DMAC controller*/ ++/*M1,M2 little endian, enable DMAC*/ ++#define DMAC_CONFIG_VAL 0x01 ++/*enable the sync logic for the 16 peripheral*/ ++#define DMAC_SYNC_VAL 0x0 ++ ++#define DMAC_MAX_PERIPHERALS 16 ++#define MEM_MAX_NUM 2 ++#define CHANNEL_NUM CONFIG_HI_DMAC_CHANNEL_NUM ++#define DMAC_MAX_CHANNELS CHANNEL_NUM ++ ++/* Uart data register address */ ++#define REG_BASE_UART0 0x12080000 ++#define REG_BASE_UART1 0x12090000 ++#define REG_BASE_UART2 0x120a0000 ++ ++#define REG_UART_DATA 0x0000 ++ ++#define UART0_DATA_REG (REG_BASE_UART0 + REG_UART_DATA) ++#define UART1_DATA_REG (REG_BASE_UART1 + REG_UART_DATA) ++#define UART2_DATA_REG (REG_BASE_UART2 + REG_UART_DATA) ++ ++/* SPI data register address */ ++#define SSP_REG_BASE 0x120d0000 ++#define REG_SSP_DATA 0x0008 ++ ++#define SSP_DATA_REG (SSP_REG_BASE + REG_SSP_DATA) ++ ++/* I2c data register address */ ++#define I2C_REG_BASE 0x120c0000 ++#define REG_I2C_DATA 0x0010 ++ ++#define I2C_DATA_REG (I2C_REG_BASE + REG_I2C_DATA) ++ ++/*the transfer control and configuration value for different peripheral*/ ++ ++extern int g_channel_status[CHANNEL_NUM]; ++extern dmac_peripheral g_peripheral[DMAC_MAX_PERIPHERALS]; ++ ++/* ++ * DMAC channel request default configure array ++ * Request ID, peripheral data register address, Control, Config, width ++ */ ++dmac_peripheral g_peripheral[DMAC_MAX_PERIPHERALS] = { ++ /* Request 0: UART0 Rx 8bit width */ ++ { 0, UART0_DATA_REG, 0x99000000, 0xd000, 0}, ++ ++ /* Request 1: UART0 Tx 8bit width */ ++ { 1, UART0_DATA_REG, 0x96000000, 0xc840, 0}, ++ ++ /* Request 2: UART1 Rx 8bit width */ ++ { 2, UART1_DATA_REG, 0x99000000, 0xd004, 0}, ++ ++ /* Request 3: UART1 Tx 8bit width */ ++ { 3, UART1_DATA_REG, 0x96000000, 0xc8c0, 0}, ++ ++ /* Request 4: UART2 Rx 8bit width */ ++ { 4, UART2_DATA_REG, 0x99000000, 0xd008, 0}, ++ ++ /* Request 5: UART2 Tx 8bit width */ ++ { 5, UART2_DATA_REG, 0x96000000, 0xc940, 0}, ++ ++ /* Request 6: SSP Rx */ ++ { 6, SSP_DATA_REG, 0x99000000, 0xd00c, 0}, ++ ++ /* Request 7: SSP Tx */ ++ { 7, SSP_DATA_REG, 0x96000000, 0xc9c0, 0}, ++ ++ /* Request 8: I2C Rx 8bit width */ ++ { 8, I2C_DATA_REG, 0x99000000, 0x1010, 0}, ++ ++ /* Request 9: I2C Tx 8bit width */ ++ { 9, I2C_DATA_REG, 0x96000000, 0x0a40, 0}, ++}; ++#endif /* End of __HI_DMAC_HI3521A_H__ */ ++ +diff --git a/drivers/hidmac/hidmac_hi3531a.h b/drivers/hidmac/hidmac_hi3531a.h +new file mode 100644 +index 0000000..3f024ee +--- /dev/null ++++ b/drivers/hidmac/hidmac_hi3531a.h +@@ -0,0 +1,150 @@ ++#ifndef __HI_DMAC_HI3531A_H__ ++#define __HI_DMAC_HI3531A_H__ ++ ++#define DDR_MEM_BASE 0x40000000 ++#define DDRAM_ADRS DDR_MEM_BASE ++#define DDRAM_SIZE 0xbFFFFFFF /* 3GB DDR. */ ++ ++#define FLASH_BASE 0x10000000 ++#define FLASH_SIZE 0x04000000 /* (32MB) */ ++ ++#define DMAC_INTSTATUS 0X00 ++#define DMAC_INTTCSTATUS 0X04 ++#define DMAC_INTTCCLEAR 0X08 ++#define DMAC_INTERRORSTATUS 0X0C ++ ++#define DMAC_INTERRCLR 0X10 ++#define DMAC_RAWINTTCSTATUS 0X14 ++#define DMAC_RAWINTERRORSTATUS 0X18 ++#define DMAC_ENBLDCHNS 0X1C ++#define DMAC_CONFIG 0X30 ++#define DMAC_SYNC 0X34 ++ ++#define DMAC_MAXTRANSFERSIZE 0x0fff /*the max length is denoted by 0-11bit*/ ++#define MAXTRANSFERSIZE DMAC_MAXTRANSFERSIZE ++#define DMAC_CxDISABLE 0x00 ++#define DMAC_CxENABLE 0x01 ++ ++/*the definition for DMAC channel register*/ ++#define DMAC_CxBASE(i) (0x100+i*0x20) ++#define DMAC_CxSRCADDR(i) DMAC_CxBASE(i) ++#define DMAC_CxDESTADDR(i) (DMAC_CxBASE(i)+0x04) ++#define DMAC_CxLLI(i) (DMAC_CxBASE(i)+0x08) ++#define DMAC_CxCONTROL(i) (DMAC_CxBASE(i)+0x0C) ++#define DMAC_CxCONFIG(i) (DMAC_CxBASE(i)+0x10) ++ ++/*the means the bit in the channel control register*/ ++#define DMAC_CxCONTROL_M2M 0x9d480000 /* Dwidth=32,burst size=4 */ ++#define DMAC_CxCONTROL_LLIM2M 0x0f480000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxCONTROL_LLIM2M_ISP 0x0b489000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxCONTROL_LLIP2M 0x0a000000 ++#define DMAC_CxCONTROL_LLIM2P 0x86089000 ++#define DMAC_CxLLI_LM 0x01 ++ ++#define DMAC_CxCONFIG_M2M 0xc000 ++#define DMAC_CxCONFIG_LLIM2M 0xc000 ++ ++/*#define DMAC_CxCONFIG_M2M 0x4001*/ ++#define DMAC_CHANNEL_ENABLE 1 ++#define DMAC_CHANNEL_DISABLE 0xfffffffe ++ ++#define DMAC_CxCONTROL_P2M 0x89409000 ++#define DMAC_CxCONFIG_P2M 0xd000 ++ ++#define DMAC_CxCONTROL_M2P 0x86089000 ++#define DMAC_CxCONFIG_M2P 0xc800 ++ ++#define DMAC_CxCONFIG_SIO_P2M 0x0000d000 ++#define DMAC_CxCONFIG_SIO_M2P 0x0000c800 ++ ++/*default the config and sync regsiter for DMAC controller*/ ++/*M1,M2 little endian, enable DMAC*/ ++#define DMAC_CONFIG_VAL 0x01 ++/*enable the sync logic for the 16 peripheral*/ ++#define DMAC_SYNC_VAL 0x0 ++ ++#define DMAC_MAX_PERIPHERALS 16 ++#define MEM_MAX_NUM 2 ++#define CHANNEL_NUM CONFIG_HI_DMAC_CHANNEL_NUM ++#define DMAC_MAX_CHANNELS CHANNEL_NUM ++ ++/* Uart data register address */ ++#define UART0_REG_BASE 0x12080000 ++#define UART1_REG_BASE 0x12090000 ++#define UART2_REG_BASE 0x120A0000 ++#define UART3_REG_BASE 0x12130000 ++ ++#define REG_UART_DATA 0x0000 ++ ++#define UART0_DATA_REG (UART0_REG_BASE + REG_UART_DATA) ++#define UART1_DATA_REG (UART1_REG_BASE + REG_UART_DATA) ++#define UART2_DATA_REG (UART2_REG_BASE + REG_UART_DATA) ++#define UART3_DATA_REG (UART3_REG_BASE + REG_UART_DATA) ++ ++/* SPI data register address */ ++#define SSP_REG_BASE 0x120d0000 ++#define REG_SSP_DATA 0x0008 ++#define SSP_DATA_REG (SSP_REG_BASE + REG_SSP_DATA) ++ ++/* I2c data register address */ ++#define I2C0_REG_BASE 0x120c0000 ++#define I2C1_REG_BASE 0x122e0000 ++ ++#define REG_I2C_DATA 0x0010 ++#define I2C0_DATA_REG (I2C0_REG_BASE + REG_I2C_DATA) ++#define I2C1_DATA_REG (I2C1_REG_BASE + REG_I2C_DATA) ++ ++/*the transfer control and configuration value for different peripheral*/ ++ ++extern int g_channel_status[CHANNEL_NUM]; ++extern dmac_peripheral g_peripheral[DMAC_MAX_PERIPHERALS]; ++ ++/* ++ * DMAC channel request default configure array ++ * Request ID, peripheral data register address, Control, Config, width ++ */ ++dmac_peripheral g_peripheral[DMAC_MAX_PERIPHERALS] = { ++ /* Request 0: UART0 Rx 8bit width */ ++ { 0, UART0_DATA_REG, 0x99000000, 0xd000, 0}, ++ ++ /* Request 1: UART0 Tx 8bit width */ ++ { 1, UART0_DATA_REG, 0x96000000, 0xc840, 0}, ++ ++ /* Request 2: UART1 Rx 8bit width */ ++ { 2, UART1_DATA_REG, 0x99000000, 0xd004, 0}, ++ ++ /* Request 3: UART1 Tx 8bit width */ ++ { 3, UART1_DATA_REG, 0x96000000, 0xc8c0, 0}, ++ ++ /* Request 4: UART2 Rx 8bit width */ ++ { 4, UART2_DATA_REG, 0x99000000, 0xd008, 0}, ++ ++ /* Request 5: UART2 Tx 8bit width */ ++ { 5, UART2_DATA_REG, 0x96000000, 0xc940, 0}, ++ ++ /* Request 6: SSP Rx */ ++ { 6, SSP_DATA_REG, 0x99000000, 0xd00c, 0}, ++ ++ /* Request 7: SSP Tx */ ++ { 7, SSP_DATA_REG, 0x96000000, 0xc9c0, 0}, ++ ++ /* Request 8: I2C0 Rx 8bit width */ ++ { 8, I2C0_DATA_REG, 0x99000000, 0x1010, 0}, ++ ++ /* Request 9: I2C0 Tx 8bit width */ ++ { 9, I2C0_DATA_REG, 0x96000000, 0x0a40, 0}, ++ ++ /* Request 10: UART3 Rx 8bit width */ ++ { 10, UART3_DATA_REG, 0x99000000, 0xd014, 0}, ++ ++ /* Request 11: UART3 Tx 8bit width */ ++ { 11, UART3_DATA_REG, 0x96000000, 0xcac0, 0}, ++ ++ /* Request 12: I2C1 Rx 8bit width */ ++ { 12, I2C1_DATA_REG, 0x99000000, 0x1018, 0}, ++ ++ /* Request 13: I2C0 Tx 8bit width */ ++ { 13, I2C1_DATA_REG, 0x96000000, 0x0b40, 0}, ++}; ++#endif ++ +diff --git a/drivers/hidmac/hidmac_hi3536dv100.h b/drivers/hidmac/hidmac_hi3536dv100.h +new file mode 100644 +index 0000000..51dd3c8 +--- /dev/null ++++ b/drivers/hidmac/hidmac_hi3536dv100.h +@@ -0,0 +1,114 @@ ++#ifndef __HI_DMAC_HI3516CV300_H__ ++#define __HI_DMAC_HI3516CV300_H__ ++ ++#define DDRAM_ADRS 0x80000000 /* fixed */ ++#define DDRAM_SIZE 0x1FFFFFFF /* 512M DDR. */ ++ ++#define FLASH_BASE 0x10000000 ++#define FLASH_SIZE 0x04000000 /* (32MB) */ ++ ++#define DMAC_INTSTATUS 0X00 ++#define DMAC_INTTCSTATUS 0X04 ++#define DMAC_INTTCCLEAR 0X08 ++#define DMAC_INTERRORSTATUS 0X0C ++ ++#define DMAC_INTERRCLR 0X10 ++#define DMAC_RAWINTTCSTATUS 0X14 ++#define DMAC_RAWINTERRORSTATUS 0X18 ++#define DMAC_ENBLDCHNS 0X1C ++#define DMAC_CONFIG 0X30 ++#define DMAC_SYNC 0X34 ++ ++#define DMAC_MAXTRANSFERSIZE 0x0fff /*the max length is denoted by 0-11bit*/ ++#define MAXTRANSFERSIZE DMAC_MAXTRANSFERSIZE ++#define DMAC_CxDISABLE 0x00 ++#define DMAC_CxENABLE 0x01 ++ ++/*the definition for DMAC channel register*/ ++#define DMAC_CxBASE(i) (0x100+i*0x20) ++#define DMAC_CxSRCADDR(i) DMAC_CxBASE(i) ++#define DMAC_CxDESTADDR(i) (DMAC_CxBASE(i)+0x04) ++#define DMAC_CxLLI(i) (DMAC_CxBASE(i)+0x08) ++#define DMAC_CxCONTROL(i) (DMAC_CxBASE(i)+0x0C) ++#define DMAC_CxCONFIG(i) (DMAC_CxBASE(i)+0x10) ++ ++/*the means the bit in the channel control register*/ ++#define DMAC_CxCONTROL_M2M 0x9d480000 /* Dwidth=32,burst size=4 */ ++#define DMAC_CxCONTROL_LLIM2M 0x0f480000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxCONTROL_LLIM2M_ISP 0x0b489000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxLLI_LM 0x01 ++ ++#define NUM_HAL_INTERRUPT_DMAC (14 + 16) ++ ++#define DMAC_CxCONFIG_M2M 0xc000 ++#define DMAC_CxCONFIG_LLIM2M 0xc000 ++ ++/*#define DMAC_CxCONFIG_M2M 0x4001*/ ++#define DMAC_CHANNEL_ENABLE 1 ++#define DMAC_CHANNEL_DISABLE 0xfffffffe ++ ++#define DMAC_CxCONTROL_P2M 0x89409000 ++#define DMAC_CxCONFIG_P2M 0xd000 ++ ++#define DMAC_CxCONTROL_M2P 0x86089000 ++#define DMAC_CxCONFIG_M2P 0xc800 ++ ++#define DMAC_CxCONFIG_SIO_P2M 0x0000d000 ++#define DMAC_CxCONFIG_SIO_M2P 0x0000c800 ++ ++/*default the config and sync regsiter for DMAC controller*/ ++/*M1,M2 little endian, enable DMAC*/ ++#define DMAC_CONFIG_VAL 0x01 ++/*enable the sync logic for the 16 peripheral*/ ++#define DMAC_SYNC_VAL 0x0 ++ ++#define DMAC_MAX_PERIPHERALS 16 ++#define MEM_MAX_NUM 2 ++#define CHANNEL_NUM CONFIG_HI_DMAC_CHANNEL_NUM ++#define DMAC_MAX_CHANNELS CHANNEL_NUM ++ ++#define REG_BASE_I2C0 0x120c0000 ++#define I2C0_DATA_RXF (REG_BASE_I2C0 + 0x24) ++#define I2C0_DATA_TXF (REG_BASE_I2C0 + 0x20) ++ ++ ++#define REG_BASE_UART0 0x12080000 ++#define UART0_DATA_REG (REG_BASE_UART0 + 0x0) ++ ++#define REG_BASE_UART1 0x12090000 ++#define UART1_DATA_REG (REG_BASE_UART1 + 0x0) ++ ++#define REG_BASE_UART2 0x120a0000 ++#define UART2_DATA_REG (REG_BASE_UART2 + 0x0) ++ ++/*the transfer control and configuration value for different peripheral*/ ++ ++extern int g_channel_status[CHANNEL_NUM]; ++ ++dmac_peripheral g_peripheral[DMAC_MAX_PERIPHERALS] = { ++ /*periphal 0: UART0 RX, 8bit width */ ++ {0, UART0_DATA_REG, 0x99000000, 0xd000, 0}, ++ ++ /*periphal 1: UART0 TX, 8bit width */ ++ {1, UART0_DATA_REG, 0x96000000, 0xc840, 0}, ++ ++ /*periphal 2: UART1 RX, 8bit width */ ++ {2, UART1_DATA_REG, 0x99000000, 0xd004, 0}, ++ ++ /*periphal 3: UART1 TX, 8bit width */ ++ {3, UART1_DATA_REG, 0x96000000, 0xc8c0, 0}, ++ ++ /*periphal 4: UART2 RX, 8bit width */ ++ {4, UART2_DATA_REG, 0x99000000, 0xd008, 0}, ++ ++ /*periphal 5: UART2 TX, 8bit width */ ++ {5, UART2_DATA_REG, 0x96000000, 0xc940, 0}, ++ ++ /*periphal 6: I2C0 RX, 8bit width */ ++ {6, I2C0_DATA_RXF, 0x99000000, 0x100c, 0}, ++ ++ /*periphal 7: I2C0 TX, 8bit width */ ++ {7, I2C0_DATA_TXF, 0x96000000, 0x9c0, 0}, ++}; ++ ++#endif +diff --git a/drivers/hisilicon/Kconfig b/drivers/hisilicon/Kconfig +new file mode 100644 +index 0000000..ab5884c +--- /dev/null ++++ b/drivers/hisilicon/Kconfig +@@ -0,0 +1,4 @@ ++menu "Hisilicon driver support" ++ ++source "drivers/hisilicon/cma/Kconfig" ++endmenu +diff --git a/drivers/hisilicon/Makefile b/drivers/hisilicon/Makefile +new file mode 100644 +index 0000000..0ba50a7 +--- /dev/null ++++ b/drivers/hisilicon/Makefile +@@ -0,0 +1 @@ ++obj-$(CONFIG_CMA) += cma/ +diff --git a/drivers/hisilicon/cma/Kconfig b/drivers/hisilicon/cma/Kconfig +new file mode 100644 +index 0000000..7472dcc +--- /dev/null ++++ b/drivers/hisilicon/cma/Kconfig +@@ -0,0 +1,16 @@ ++ ++config CMA_MEM_SHARED ++ bool "Support sharing CMA memory with the heap" ++ depends on CMA && DMA_CMA ++ default no ++ help ++ Support sharing CMA memory with the heap. ++ ++config CMA_ADVANCE_SHARE ++ bool "Support cma advance share" ++ depends on CMA && DMA_CMA ++ select CMA_MEM_SHARED ++ default no ++ help ++ Support advance sharing CMA memory with the heap. ++ CMA Multiplex Ratio will be improved when this macro defined. +diff --git a/drivers/hisilicon/cma/Makefile b/drivers/hisilicon/cma/Makefile +new file mode 100644 +index 0000000..eefda7f +--- /dev/null ++++ b/drivers/hisilicon/cma/Makefile +@@ -0,0 +1,2 @@ ++ ++obj-$(CONFIG_CMA) += hi_cma.o +diff --git a/drivers/hisilicon/cma/hi_cma.c b/drivers/hisilicon/cma/hi_cma.c +new file mode 100644 +index 0000000..d428b3a +--- /dev/null ++++ b/drivers/hisilicon/cma/hi_cma.c +@@ -0,0 +1,142 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define NAME_LEN_MAX 64 ++#define ZONE_MAX 64 ++ ++struct cma_zone { ++ struct device pdev; ++ char name[NAME_LEN_MAX]; ++ u32 gfp; ++ u32 phys_start; ++ u32 nbytes; ++ u32 alloc_type; ++ u32 block_align; ++}; ++ ++static u32 num_zones; ++static struct cma_zone hisi_zone[ZONE_MAX]; ++ ++static int use_bootargs; ++ ++unsigned int get_cma_size(void) ++{ ++ int i; ++ u64 total = 0; ++ ++ for (i = 0; i < num_zones; i++) ++ total += hisi_zone[i].nbytes; ++ ++ /* unit is M */ ++ return (unsigned int)(total >> 20); ++} ++ ++static int __init hisi_mmz_parse_cmdline(char *s) ++{ ++ char *line, *tmp; ++ char tmpline[256]; ++ ++ if (NULL == s) { ++ pr_info("There is no cma zone!\n"); ++ return 0; ++ } ++ strncpy(tmpline, s, sizeof(tmpline)); ++ tmpline[sizeof(tmpline)-1] = '\0'; ++ tmp = tmpline; ++ ++ while ((line = strsep(&tmp, ":")) != NULL) { ++ int i; ++ char *argv[6]; ++ ++ for (i = 0; (argv[i] = strsep(&line, ",")) != NULL;) ++ if (++i == ARRAY_SIZE(argv)) ++ break; ++ ++ hisi_zone[num_zones].pdev.coherent_dma_mask = DMA_BIT_MASK(64); ++ if (i == 4) { ++ strlcpy(hisi_zone[num_zones].name, argv[0], NAME_LEN_MAX); ++ hisi_zone[num_zones].gfp = memparse(argv[2], NULL); ++ hisi_zone[num_zones].phys_start = memparse(argv[2], NULL); ++ hisi_zone[num_zones].nbytes = memparse(argv[3], NULL); ++ } ++ ++ else if (i == 6) { ++ strlcpy(hisi_zone[num_zones].name, argv[0], NAME_LEN_MAX); ++ hisi_zone[num_zones].gfp = memparse(argv[1], NULL); ++ hisi_zone[num_zones].phys_start = memparse(argv[2], NULL); ++ hisi_zone[num_zones].nbytes = memparse(argv[3], NULL); ++ hisi_zone[num_zones].alloc_type = memparse(argv[4], NULL); ++ hisi_zone[num_zones].block_align = memparse(argv[5], NULL); ++ } else { ++ pr_err("hisi ion parameter is not correct\n"); ++ continue; ++ } ++ ++ num_zones++; ++ } ++ if (num_zones != 0) ++ use_bootargs = 1; ++ ++ return 0; ++} ++early_param("mmz", hisi_mmz_parse_cmdline); ++ ++struct cma_zone *hisi_get_cma_zone(const char *name) ++{ ++ int i = 0; ++ ++ for (i = 0; i < num_zones; i++) ++ if (strcmp(hisi_zone[i].name, name) == 0) ++ break; ++ ++ if (i == num_zones) ++ return NULL; ++ ++ return &hisi_zone[i]; ++} ++EXPORT_SYMBOL(hisi_get_cma_zone); ++ ++struct device *hisi_get_cma_device(const char *name) ++{ ++ int i = 0; ++ ++ for (i = 0; i < num_zones; i++) ++ if (strcmp(hisi_zone[i].name, name) == 0) ++ break; ++ ++ if (i == num_zones) ++ return NULL; ++ ++ return &hisi_zone[i].pdev; ++} ++EXPORT_SYMBOL(hisi_get_cma_device); ++ ++int __init hisi_declare_heap_memory(void) ++{ ++ int i; ++ int ret = 0; ++ ++ if (use_bootargs == 0) { ++ pr_info("cmz zone is not set!\n"); ++ return ret; ++ } ++ ++ for (i = 0; i < num_zones; i++) { ++ ret = dma_declare_contiguous(&hisi_zone[i].pdev, ++ hisi_zone[i].nbytes, hisi_zone[i].phys_start, 0); ++ if (ret) ++ panic("declare cma zone %s base: %u size:%uMB failed. ret:%d", ++ hisi_zone[i].name, hisi_zone[i].phys_start, ++ hisi_zone[i].nbytes>>20, ret); ++ hisi_zone[i].phys_start = cma_get_base(hisi_zone[i].pdev.cma_area); ++ hisi_zone[i].nbytes = cma_get_size(hisi_zone[i].pdev.cma_area); ++ ++ /*FIXME need to fix dma_declare_contiguous return value &&value type*/ ++ } ++ return ret; ++} ++EXPORT_SYMBOL(hisi_declare_heap_memory); +diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig +index d252276..a6473c8 100644 +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -555,6 +555,16 @@ config I2C_GPIO + This is a very simple bitbanging I2C driver utilizing the + arch-neutral GPIO API to control the SCL and SDA lines. + ++config I2C_HIBVT ++ tristate "Hisilicon BVT I2C Controller" ++ depends on ARCH_HISI_BVT ++ help ++ Say Y here to include support for Hisilicon BVT I2C controller in the ++ Hisilicon BVT SoCs. ++ ++ This driver can also be built as a module. If so, the module ++ will be called i2c-hibvt. ++ + config I2C_HIGHLANDER + tristate "Highlander FPGA SMBus interface" + depends on SH_HIGHLANDER +@@ -1214,4 +1224,28 @@ config I2C_OPAL + This driver can also be built as a module. If so, the module will be + called as i2c-opal. + ++config I2C_HISI ++ tristate "Hisilicon I2C Controller support" ++ depends on ARCH_HI3516A || ARCH_HI3518EV20X || ARCH_HI3521A || ARCH_HI3531A ++ help ++ Hisilicon I2C controller has 3 buses. ++ We can access some sensors though it. ++ This IP is used in HI3516A/HI3518EV20X/HI3521A/HI3531A chips. ++ ++config DMA_MSG_MIN_LEN ++ int "Hisilicon I2C support DMA minimum LEN" ++ depends on I2C_HIBVT ++ range 1 4090 ++ default 5 ++ help ++ The i2c_msg minimum LEN of i2c support DMA,range from 1 to 4091 ++ ++config DMA_MSG_MAX_LEN ++ int "Hisilicon I2C support DMA maximum LEN" ++ depends on I2C_HIBVT ++ range DMA_MSG_MIN_LEN 4090 ++ default 4090 ++ help ++ The i2c_msg maximum LEN of i2c support DMA,range from i2c_msg minimum LEN to 4090, ++ because DMA for 0xFFC one-time largest data transfers; + endmenu +diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile +index 29764cc..f96cde3 100644 +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -51,6 +51,7 @@ obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o + obj-$(CONFIG_I2C_EMEV2) += i2c-emev2.o + obj-$(CONFIG_I2C_EXYNOS5) += i2c-exynos5.o + obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o ++obj-$(CONFIG_I2C_HIBVT) += i2c-hibvt.o + obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o + obj-$(CONFIG_I2C_HIX5HD2) += i2c-hix5hd2.o + obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o +@@ -122,4 +123,6 @@ 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_HISI) += i2c-hisilicon.o ++ + ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG +diff --git a/drivers/i2c/busses/i2c-hibvt.c b/drivers/i2c/busses/i2c-hibvt.c +new file mode 100644 +index 0000000..ab43ef1 +--- /dev/null ++++ b/drivers/i2c/busses/i2c-hibvt.c +@@ -0,0 +1,1068 @@ ++/* ++ * Hisilicon BVT I2C Controller Driver ++ * ++ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd. ++ * ++ * Authors: wenpan@hisilicon.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, see . ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_HI_DMAC ++#include ++#endif ++/* ++ * I2C Registers offsets ++ */ ++#define HIBVT_I2C_GLB 0x0 ++#define HIBVT_I2C_SCL_H 0x4 ++#define HIBVT_I2C_SCL_L 0x8 ++#define HIBVT_I2C_DATA1 0x10 ++#define HIBVT_I2C_TXF 0x20 ++#define HIBVT_I2C_RXF 0x24 ++#define HIBVT_I2C_CMD_BASE 0x30 ++#define HIBVT_I2C_LOOP1 0xb0 ++#define HIBVT_I2C_DST1 0xb4 ++#define HIBVT_I2C_TX_WATER 0xc8 ++#define HIBVT_I2C_RX_WATER 0xcc ++#define HIBVT_I2C_CTRL1 0xd0 ++#define HIBVT_I2C_CTRL2 0xd4 ++#define HIBVT_I2C_STAT 0xd8 ++#define HIBVT_I2C_INTR_RAW 0xe0 ++#define HIBVT_I2C_INTR_EN 0xe4 ++#define HIBVT_I2C_INTR_STAT 0xe8 ++ ++/* ++ * I2C Global Config Register -- HIBVT_I2C_GLB ++ */ ++#define GLB_EN_MASK BIT(0) ++#define GLB_SDA_HOLD_MASK GENMASK(23, 8) ++#define GLB_SDA_HOLD_SHIFT (8) ++ ++/* ++ * I2C Timing CMD Register -- HIBVT_I2C_CMD_BASE + n * 4 (n = 0, 1, 2, ... 31) ++ */ ++#define CMD_EXIT 0x0 ++#define CMD_TX_S 0x1 ++#define CMD_TX_D1_2 0x4 ++#define CMD_TX_D1_1 0x5 ++#define CMD_TX_FIFO 0x9 ++#define CMD_RX_FIFO 0x12 ++#define CMD_RX_ACK 0x13 ++#define CMD_IGN_ACK 0x15 ++#define CMD_TX_ACK 0x16 ++#define CMD_TX_NACK 0x17 ++#define CMD_JMP1 0x18 ++#define CMD_UP_TXF 0x1d ++#define CMD_TX_RS 0x1e ++#define CMD_TX_P 0x1f ++ ++/* ++ * I2C Control Register 1 -- HIBVT_I2C_CTRL1 ++ */ ++#define CTRL1_CMD_START_MASK BIT(0) ++#define CTRL1_DMA_OP_MASK (0x3 << 8) ++#define CTRL1_DMA_R (0x3 << 8) ++#define CTRL1_DMA_W (0x2 << 8) ++ ++/* ++ * I2C Status Register -- HIBVT_I2C_STAT ++ */ ++#define STAT_RXF_NOE_MASK BIT(16) /* RX FIFO not empty flag */ ++#define STAT_TXF_NOF_MASK BIT(19) /* TX FIFO not full flag */ ++ ++ ++/* ++ * I2C Interrupt status and mask Register -- ++ * HIBVT_I2C_INTR_RAW, HIBVT_I2C_STAT, HIBVT_I2C_INTR_STAT ++ */ ++#define INTR_ABORT_MASK (BIT(0) | BIT(11)) ++#define INTR_RX_MASK BIT(2) ++#define INTR_TX_MASK BIT(4) ++#define INTR_CMD_DONE_MASK BIT(12) ++#define INTR_USE_MASK (INTR_ABORT_MASK \ ++ |INTR_RX_MASK \ ++ | INTR_TX_MASK \ ++ | INTR_CMD_DONE_MASK) ++#define INTR_ALL_MASK GENMASK(31, 0) ++ ++#define I2C_DEFAULT_FREQUENCY 100000 ++#define I2C_TXF_DEPTH 64 ++#define I2C_RXF_DEPTH 64 ++#define I2C_TXF_WATER 32 ++#define I2C_RXF_WATER 32 ++#define I2C_WAIT_TIMEOUT 0x10000 ++#define I2C_IRQ_TIMEOUT (msecs_to_jiffies(1000)) ++ ++ ++struct hibvt_i2c_dev { ++ struct device *dev; ++ struct i2c_adapter adap; ++ resource_size_t phybase; ++ void __iomem *base; ++ struct clk *clk; ++ int irq; ++ ++ unsigned int freq; ++ struct i2c_msg *msg; ++ unsigned int msg_num; ++ unsigned int msg_idx; ++ unsigned int msg_buf_ptr; ++ struct completion msg_complete; ++ ++ spinlock_t lock; ++ int status; ++}; ++static inline void hibvt_i2c_disable(struct hibvt_i2c_dev *i2c); ++static inline void hibvt_i2c_cfg_irq(struct hibvt_i2c_dev *i2c, ++ unsigned int flag); ++static inline unsigned int hibvt_i2c_clr_irq(struct hibvt_i2c_dev *i2c); ++static inline void hibvt_i2c_enable(struct hibvt_i2c_dev *i2c); ++ ++#define CHECK_SDA_IN_SHIFT (16) ++#define GPIO_MODE_SHIFT (8) ++#define FORCE_SCL_OEN_SHIFT (4) ++#define FORCE_SDA_OEN_SHIFT (0) ++ ++static void hibvt_i2c_rescue(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int val; ++ unsigned int time_cnt; ++ int index; ++ ++ hibvt_i2c_disable(i2c); ++ hibvt_i2c_cfg_irq(i2c, 0); ++ hibvt_i2c_clr_irq(i2c); ++ ++ val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT); ++ writel(val, i2c->base + HIBVT_I2C_CTRL2); ++ ++ time_cnt = 0; ++ do { ++ for (index = 0; index < 9; index++) { ++ val = (0x1 << GPIO_MODE_SHIFT) | 0x1; ++ writel(val, i2c->base + HIBVT_I2C_CTRL2); ++ ++ udelay(5); ++ ++ val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT); ++ writel(val, i2c->base + HIBVT_I2C_CTRL2); ++ ++ udelay(5); ++ } ++ ++ time_cnt++; ++ if (time_cnt > I2C_WAIT_TIMEOUT) { ++ dev_err(i2c->dev, "wait Timeout!\n"); ++ goto disable_rescue; ++ } ++ ++ val = readl(i2c->base + HIBVT_I2C_CTRL2); ++ } while(!(val & (0x1 << CHECK_SDA_IN_SHIFT))); ++ ++ ++ val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT); ++ writel(val, i2c->base + HIBVT_I2C_CTRL2); ++ ++ val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT); ++ writel(val, i2c->base + HIBVT_I2C_CTRL2); ++ ++ udelay(10); ++ ++ val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT); ++ writel(val, i2c->base + HIBVT_I2C_CTRL2); ++ ++disable_rescue: ++ val = (0x1 << FORCE_SCL_OEN_SHIFT) | 0x1; ++ writel(val, i2c->base + HIBVT_I2C_CTRL2); ++} ++ ++static inline void hibvt_i2c_disable(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int val; ++ ++ val = readl(i2c->base + HIBVT_I2C_GLB); ++ val &= ~GLB_EN_MASK; ++ writel(val, i2c->base + HIBVT_I2C_GLB); ++} ++ ++static inline void hibvt_i2c_enable(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int val; ++ ++ val = readl(i2c->base + HIBVT_I2C_GLB); ++ val |= GLB_EN_MASK; ++ writel(val, i2c->base + HIBVT_I2C_GLB); ++} ++ ++static inline void hibvt_i2c_cfg_irq(struct hibvt_i2c_dev *i2c, ++ unsigned int flag) ++{ ++ writel(flag, i2c->base + HIBVT_I2C_INTR_EN); ++} ++ ++static inline void hibvt_i2c_disable_irq(struct hibvt_i2c_dev *i2c, ++ unsigned int flag) ++{ ++ unsigned int val; ++ ++ val = readl(i2c->base + HIBVT_I2C_INTR_EN); ++ val &= ~flag; ++ writel(val, i2c->base + HIBVT_I2C_INTR_EN); ++} ++ ++static inline unsigned int hibvt_i2c_clr_irq(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int val; ++ ++ val = readl(i2c->base + HIBVT_I2C_INTR_STAT); ++ writel(INTR_ALL_MASK, i2c->base + HIBVT_I2C_INTR_RAW); ++ ++ return val; ++} ++ ++static inline void hibvt_i2c_cmdreg_set(struct hibvt_i2c_dev *i2c, ++ unsigned int cmd, unsigned int *offset) ++{ ++ dev_dbg(i2c->dev, "hii2c reg: offset=0x%x, cmd=0x%x...\n", ++ *offset * 4, cmd); ++ writel(cmd, i2c->base + HIBVT_I2C_CMD_BASE + *offset * 4); ++ (*offset)++; ++} ++ ++/* ++ * config i2c slave addr ++ */ ++static inline void hibvt_i2c_set_addr(struct hibvt_i2c_dev *i2c) ++{ ++ struct i2c_msg *msg = i2c->msg; ++ u16 addr; ++ ++ if (msg->flags & I2C_M_TEN) { ++ /* First byte is 11110XX0 where XX is upper 2 bits */ ++ addr = ((msg->addr & 0x300) << 1) | 0xf000; ++ if (msg->flags & I2C_M_RD) ++ addr |= 1 << 8; ++ ++ /* Second byte is the remaining 8 bits */ ++ addr |= msg->addr & 0xff; ++ } else { ++ addr = (msg->addr & 0x7f) << 1; ++ if (msg->flags & I2C_M_RD) ++ addr |= 1; ++ } ++ ++ writel(addr, i2c->base + HIBVT_I2C_DATA1); ++} ++ ++/* ++ * Start command sequence ++ */ ++static inline void hibvt_i2c_start_cmd(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int val; ++ ++ val = readl(i2c->base + HIBVT_I2C_CTRL1); ++ val |= CTRL1_CMD_START_MASK; ++ writel(val, i2c->base + HIBVT_I2C_CTRL1); ++} ++ ++static int hibvt_i2c_wait_rx_noempty(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int time_cnt = 0; ++ unsigned int val; ++ ++ do { ++ val = readl(i2c->base + HIBVT_I2C_STAT); ++ if (val & STAT_RXF_NOE_MASK) ++ return 0; ++ ++ udelay(50); ++ } while (time_cnt++ < I2C_WAIT_TIMEOUT); ++ ++ hibvt_i2c_rescue(i2c); ++ ++ dev_err(i2c->dev, "wait rx no empty timeout, RIS: 0x%x, SR: 0x%x\n", ++ readl(i2c->base + HIBVT_I2C_INTR_RAW), val); ++ return -EIO; ++} ++ ++static int hibvt_i2c_wait_tx_nofull(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int time_cnt = 0; ++ unsigned int val; ++ ++ do { ++ val = readl(i2c->base + HIBVT_I2C_STAT); ++ if (val & STAT_TXF_NOF_MASK) ++ return 0; ++ ++ udelay(50); ++ } while (time_cnt++ < I2C_WAIT_TIMEOUT); ++ ++ hibvt_i2c_rescue(i2c); ++ ++ dev_err(i2c->dev, "wait rx no empty timeout, RIS: 0x%x, SR: 0x%x\n", ++ readl(i2c->base + HIBVT_I2C_INTR_RAW), val); ++ return -EIO; ++} ++ ++static int hibvt_i2c_wait_idle(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int time_cnt = 0; ++ unsigned int val; ++ ++ do { ++ val = readl(i2c->base + HIBVT_I2C_INTR_RAW); ++ if (val & (INTR_ABORT_MASK)) { ++ dev_err(i2c->dev, "wait idle abort!, RIS: 0x%x\n", ++ val); ++ return -EIO; ++ } ++ ++ if (val & INTR_CMD_DONE_MASK) ++ return 0; ++ ++ udelay(50); ++ } while (time_cnt++ < I2C_WAIT_TIMEOUT); ++ ++ hibvt_i2c_rescue(i2c); ++ ++ dev_err(i2c->dev, "wait idle timeout, RIS: 0x%x, SR: 0x%x\n", ++ val, readl(i2c->base + HIBVT_I2C_STAT)); ++ ++ return -EIO; ++} ++ ++static void hibvt_i2c_set_freq(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int max_freq, freq; ++ unsigned int clk_rate; ++ unsigned int val; ++ ++ freq = i2c->freq; ++ clk_rate = clk_get_rate(i2c->clk); ++ max_freq = clk_rate >> 1; ++ ++ if (freq > max_freq) { ++ i2c->freq = max_freq; ++ freq = i2c->freq; ++ } ++ ++ if (!freq) { ++ pr_err("hibvt_i2c_set_freq:freq can't be zero!"); ++ return; ++ } ++ ++ if (freq <= 100000) { ++ val = clk_rate / (freq * 2); ++ writel(val, i2c->base + HIBVT_I2C_SCL_H); ++ writel(val, i2c->base + HIBVT_I2C_SCL_L); ++ } else { ++ val = (clk_rate * 36) / (freq * 100); ++ writel(val, i2c->base + HIBVT_I2C_SCL_H); ++ val = (clk_rate * 64) / (freq * 100); ++ writel(val, i2c->base + HIBVT_I2C_SCL_L); ++ } ++ ++ val = readl(i2c->base + HIBVT_I2C_GLB); ++ val &= ~GLB_SDA_HOLD_MASK; ++ val |= ((0xa << GLB_SDA_HOLD_SHIFT) & GLB_SDA_HOLD_MASK); ++ writel(val, i2c->base + HIBVT_I2C_GLB); ++} ++ ++/* ++ * set i2c controller TX and RX FIFO water ++ */ ++static inline void hibvt_i2c_set_water(struct hibvt_i2c_dev *i2c) ++{ ++ writel(I2C_TXF_WATER, i2c->base + HIBVT_I2C_TX_WATER); ++ writel(I2C_RXF_WATER, i2c->base + HIBVT_I2C_RX_WATER); ++} ++ ++/* ++ * initialise the controller, set i2c bus interface freq ++ */ ++static void hibvt_i2c_hw_init(struct hibvt_i2c_dev *i2c) ++{ ++ hibvt_i2c_disable(i2c); ++ hibvt_i2c_disable_irq(i2c, INTR_ALL_MASK); ++ hibvt_i2c_set_freq(i2c); ++ hibvt_i2c_set_water(i2c); ++} ++ ++/* ++ * hibvt_i2c_cfg_cmd - config i2c controller command sequence ++ * ++ * After all the timing command is configured, ++ * and then start the command, you can i2c communication, ++ * and then only need to read and write i2c fifo. ++ */ ++static void hibvt_i2c_cfg_cmd(struct hibvt_i2c_dev *i2c) ++{ ++ struct i2c_msg *msg = i2c->msg; ++ int offset = 0; ++ ++ if (i2c->msg_idx == 0) ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_S, &offset); ++ else ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_RS, &offset); ++ ++ if (msg->flags & I2C_M_TEN) { ++ if (i2c->msg_idx == 0) { ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_D1_2, &offset); ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_D1_1, &offset); ++ } else { ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_D1_2, &offset); ++ } ++ } else { ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_D1_1, &offset); ++ } ++ ++ if (msg->flags & I2C_M_IGNORE_NAK) ++ hibvt_i2c_cmdreg_set(i2c, CMD_IGN_ACK, &offset); ++ else ++ hibvt_i2c_cmdreg_set(i2c, CMD_RX_ACK, &offset); ++ ++ if (msg->flags & I2C_M_RD) { ++ if (msg->len >= 2) { ++ writel(offset, i2c->base + HIBVT_I2C_DST1); ++ writel(msg->len - 2, i2c->base + HIBVT_I2C_LOOP1); ++ hibvt_i2c_cmdreg_set(i2c, CMD_RX_FIFO, &offset); ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_ACK, &offset); ++ hibvt_i2c_cmdreg_set(i2c, CMD_JMP1, &offset); ++ } ++ hibvt_i2c_cmdreg_set(i2c, CMD_RX_FIFO, &offset); ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_NACK, &offset); ++ } else { ++ writel(offset, i2c->base + HIBVT_I2C_DST1); ++ writel(msg->len - 1, i2c->base + HIBVT_I2C_LOOP1); ++ hibvt_i2c_cmdreg_set(i2c, CMD_UP_TXF, &offset); ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_FIFO, &offset); ++ ++ if (msg->flags & I2C_M_IGNORE_NAK) ++ hibvt_i2c_cmdreg_set(i2c, CMD_IGN_ACK, &offset); ++ else ++ hibvt_i2c_cmdreg_set(i2c, CMD_RX_ACK, &offset); ++ ++ hibvt_i2c_cmdreg_set(i2c, CMD_JMP1, &offset); ++ } ++ ++ if ((i2c->msg_idx == (i2c->msg_num - 1)) || (msg->flags & I2C_M_STOP)) { ++ dev_dbg(i2c->dev, "run to %s %d...TX STOP\n", ++ __func__, __LINE__); ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_P, &offset); ++ } ++ ++ hibvt_i2c_cmdreg_set(i2c, CMD_EXIT, &offset); ++} ++ ++#ifdef CONFIG_HI_DMAC ++int dma_to_i2c(unsigned long src, unsigned int dst, unsigned int length) ++{ ++ int chan; ++ ++ chan = do_dma_m2p(src, dst, length); ++ if (chan == -1) ++ pr_err("dma_to_i2c error\n"); ++ ++ return chan; ++} ++ ++int i2c_to_dma(unsigned int src, unsigned long dst, ++ unsigned int length) ++{ ++ int chan; ++ ++ chan = do_dma_p2m(dst, src, length); ++ if (chan == -1) ++ pr_err("dma_p2m error...\n"); ++ ++ return chan; ++} ++ ++static int hibvt_i2c_do_dma_write(struct hibvt_i2c_dev *i2c, ++ unsigned long dma_dst_addr) ++{ ++ int chan, val, status = 0; ++ struct i2c_msg *msg = i2c->msg; ++ ++ hibvt_i2c_set_freq(i2c); ++ writel(0x1, i2c->base + HIBVT_I2C_TX_WATER); ++ hibvt_i2c_enable(i2c); ++ hibvt_i2c_clr_irq(i2c); ++ hibvt_i2c_set_addr(i2c); ++ hibvt_i2c_cfg_cmd(i2c); ++ ++ /* transmit DATA from DMAC to I2C in DMA mode */ ++ chan = dma_to_i2c(dma_dst_addr, (i2c->phybase + HIBVT_I2C_TXF), ++ msg->len); ++ if (chan == -1) { ++ status = -1; ++ goto fail_0; ++ } ++ ++ val = readl(i2c->base + HIBVT_I2C_CTRL1); ++ val &= ~CTRL1_DMA_OP_MASK; ++ val |= CTRL1_DMA_W | CTRL1_CMD_START_MASK; ++ writel(val, i2c->base + HIBVT_I2C_CTRL1); ++ ++ if (dmac_wait(chan) != DMAC_CHN_SUCCESS) { ++ status = -1; ++ goto fail_1; ++ } ++ ++ status = hibvt_i2c_wait_idle(i2c); ++ ++fail_1: ++ dmac_channel_free((unsigned int)chan); ++fail_0: ++ hibvt_i2c_disable(i2c); ++ ++ return status; ++} ++ ++static int hibvt_i2c_do_dma_read(struct hibvt_i2c_dev *i2c, ++ unsigned long dma_dst_addr) ++{ ++ int val, chan, status = 0; ++ struct i2c_msg *msg = i2c->msg; ++ ++ hibvt_i2c_set_freq(i2c); ++ writel(0x0, i2c->base + HIBVT_I2C_RX_WATER); ++ hibvt_i2c_enable(i2c); ++ hibvt_i2c_clr_irq(i2c); ++ hibvt_i2c_set_addr(i2c); ++ hibvt_i2c_cfg_cmd(i2c); ++ ++ /* transmit DATA from I2C to DMAC in DMA mode */ ++ chan = i2c_to_dma((i2c->phybase + HIBVT_I2C_RXF), ++ dma_dst_addr, msg->len); ++ if (chan == -1) { ++ status = -1; ++ goto fail_0; ++ } ++ ++ val = readl(i2c->base + HIBVT_I2C_CTRL1); ++ val &= ~CTRL1_DMA_OP_MASK; ++ val |= CTRL1_CMD_START_MASK | CTRL1_DMA_R; ++ writel(val, i2c->base + HIBVT_I2C_CTRL1); ++ ++ if (dmac_wait(chan) != DMAC_CHN_SUCCESS) { ++ status = -1; ++ goto fail_1; ++ } ++ ++ status = hibvt_i2c_wait_idle(i2c); ++ ++fail_1: ++ dmac_channel_free((unsigned int)chan); ++fail_0: ++ hibvt_i2c_disable(i2c); ++ ++ return status; ++} ++static int hibvt_i2c_dma_xfer_one_msg(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int status; ++ struct i2c_msg *msg = i2c->msg; ++ dma_addr_t dma_dst_addr; ++ ++ ++ dev_dbg(i2c->dev, "[%s,%d]msg->flags=0x%x, len=0x%x\n", ++ __func__, __LINE__, msg->flags, msg->len); ++ ++ if (msg->flags & I2C_M_RD){ ++ dma_dst_addr = dma_map_single(i2c->dev, msg->buf, ++ msg->len, DMA_FROM_DEVICE); ++ if (dma_mapping_error(i2c->dev, dma_dst_addr)) { ++ dev_err(i2c->dev, "DMA mapping failed\n"); ++ return -EINVAL; ++ } ++ ++ status = hibvt_i2c_do_dma_read(i2c, dma_dst_addr); ++ ++ dma_unmap_single(i2c->dev, dma_dst_addr, msg->len, DMA_FROM_DEVICE); ++ ++ } else { ++ dma_dst_addr = dma_map_single(i2c->dev, msg->buf, ++ msg->len, DMA_TO_DEVICE); ++ ++ if (dma_mapping_error(i2c->dev, dma_dst_addr)){ ++ dev_err(i2c->dev, "DMA mapping failed\n"); ++ return -EINVAL; ++ } ++ ++ status = hibvt_i2c_do_dma_write(i2c, dma_dst_addr); ++ dma_unmap_single(i2c->dev, dma_dst_addr, msg->len, DMA_TO_DEVICE); ++ } ++ status = hibvt_i2c_wait_idle(i2c); ++ hibvt_i2c_disable(i2c); ++ ++ return status; ++} ++#endif ++static int hibvt_i2c_polling_xfer_one_msg(struct hibvt_i2c_dev *i2c) ++{ ++ int status; ++ unsigned int val; ++ struct i2c_msg *msg = i2c->msg; ++ ++ dev_dbg(i2c->dev, "[%s,%d]msg->flags=0x%x, len=0x%x\n", ++ __func__, __LINE__, msg->flags, msg->len); ++ ++ hibvt_i2c_enable(i2c); ++ hibvt_i2c_clr_irq(i2c); ++ hibvt_i2c_set_addr(i2c); ++ hibvt_i2c_cfg_cmd(i2c); ++ hibvt_i2c_start_cmd(i2c); ++ ++ i2c->msg_buf_ptr = 0; ++ ++ if (msg->flags & I2C_M_RD) { ++ while (i2c->msg_buf_ptr < msg->len) { ++ status = hibvt_i2c_wait_rx_noempty(i2c); ++ if (status) ++ goto end; ++ ++ val = readl(i2c->base + HIBVT_I2C_RXF); ++ msg->buf[i2c->msg_buf_ptr] = val; ++ i2c->msg_buf_ptr++; ++ ++ } ++ } else { ++ while (i2c->msg_buf_ptr < msg->len) { ++ status = hibvt_i2c_wait_tx_nofull(i2c); ++ if (status) ++ goto end; ++ ++ val = msg->buf[i2c->msg_buf_ptr]; ++ writel(val, i2c->base + HIBVT_I2C_TXF); ++ i2c->msg_buf_ptr++; ++ } ++ } ++ ++ status = hibvt_i2c_wait_idle(i2c); ++end: ++ hibvt_i2c_disable(i2c); ++ ++ return status; ++} ++ ++static irqreturn_t hibvt_i2c_isr(int irq, void *dev_id) ++{ ++ struct hibvt_i2c_dev *i2c = dev_id; ++ unsigned int irq_status; ++ struct i2c_msg *msg = i2c->msg; ++ ++ spin_lock(&i2c->lock); ++ ++ irq_status = hibvt_i2c_clr_irq(i2c); ++ dev_dbg(i2c->dev, "%s RIS: 0x%x\n", __func__, irq_status); ++ ++ if (!irq_status) { ++ dev_dbg(i2c->dev, "no irq\n"); ++ goto end; ++ } ++ ++ if (irq_status & INTR_ABORT_MASK) { ++ dev_err(i2c->dev, "irq handle abort, RIS: 0x%x\n", ++ irq_status); ++ i2c->status = -EIO; ++ hibvt_i2c_disable_irq(i2c, INTR_ALL_MASK); ++ ++ complete(&i2c->msg_complete); ++ goto end; ++ } ++ ++ if (msg->flags & I2C_M_RD) { ++ while ((readl(i2c->base + HIBVT_I2C_STAT) & STAT_RXF_NOE_MASK) ++ && (i2c->msg_buf_ptr < msg->len)) { ++ msg->buf[i2c->msg_buf_ptr] = ++ readl(i2c->base + HIBVT_I2C_RXF); ++ i2c->msg_buf_ptr++; ++ } ++ } else { ++ while ((readl(i2c->base + HIBVT_I2C_STAT) & STAT_TXF_NOF_MASK) ++ && (i2c->msg_buf_ptr < msg->len)) { ++ writel(msg->buf[i2c->msg_buf_ptr], ++ i2c->base + HIBVT_I2C_TXF); ++ i2c->msg_buf_ptr++; ++ } ++ } ++ ++ if (i2c->msg_buf_ptr >= msg->len) ++ hibvt_i2c_disable_irq(i2c, INTR_TX_MASK | INTR_RX_MASK); ++ ++ if (irq_status & INTR_CMD_DONE_MASK) { ++ dev_dbg(i2c->dev, "cmd done\n"); ++ i2c->status = 0; ++ hibvt_i2c_disable_irq(i2c, INTR_ALL_MASK); ++ ++ complete(&i2c->msg_complete); ++ } ++ ++end: ++ spin_unlock(&i2c->lock); ++ ++ return IRQ_HANDLED; ++} ++ ++static int hibvt_i2c_interrupt_xfer_one_msg(struct hibvt_i2c_dev *i2c) ++{ ++ int status; ++ struct i2c_msg *msg = i2c->msg; ++ unsigned long timeout; ++ unsigned long flags; ++ ++ dev_dbg(i2c->dev, "[%s,%d]msg->flags=0x%x, len=0x%x\n", ++ __func__, __LINE__, msg->flags, msg->len); ++ ++ reinit_completion(&i2c->msg_complete); ++ i2c->msg_buf_ptr = 0; ++ i2c->status = -EIO; ++ ++ spin_lock_irqsave(&i2c->lock, flags); ++ hibvt_i2c_enable(i2c); ++ hibvt_i2c_clr_irq(i2c); ++ if (msg->flags & I2C_M_RD) ++ hibvt_i2c_cfg_irq(i2c, INTR_USE_MASK & ~INTR_TX_MASK); ++ else ++ hibvt_i2c_cfg_irq(i2c, INTR_USE_MASK & ~INTR_RX_MASK); ++ ++ hibvt_i2c_set_addr(i2c); ++ hibvt_i2c_cfg_cmd(i2c); ++ hibvt_i2c_start_cmd(i2c); ++ spin_unlock_irqrestore(&i2c->lock, flags); ++ ++ timeout = wait_for_completion_timeout(&i2c->msg_complete, ++ I2C_IRQ_TIMEOUT); ++ ++ if (timeout == 0) { ++ hibvt_i2c_disable_irq(i2c, INTR_ALL_MASK); ++ status = -EIO; ++ dev_err(i2c->dev, "%s timeout\n", ++ msg->flags & I2C_M_RD ? "rx" : "tx"); ++ } else { ++ status = i2c->status; ++ } ++ ++ hibvt_i2c_disable(i2c); ++ ++ return status; ++} ++ ++/* ++ * Master transfer function ++ */ ++static int hibvt_i2c_xfer(struct i2c_adapter *adap, ++ struct i2c_msg *msgs, int num) ++{ ++ struct hibvt_i2c_dev *i2c = i2c_get_adapdata(adap); ++ int status = -EINVAL; ++ unsigned long flags; ++ ++ if (!msgs || (num <= 0)) { ++ dev_err(i2c->dev, "msgs == NULL || num <= 0, Invalid argument!\n"); ++ return -EINVAL; ++ } ++ ++ spin_lock_irqsave(&i2c->lock, flags); ++ ++ i2c->msg = msgs; ++ i2c->msg_num = num; ++ i2c->msg_idx = 0; ++ ++ /* FIXME: The wait_for_completion_timeout in hibvt_i2c_interrupt_xfer_one_msg ++ * function can not be locked by spin_lock_irqsave. And actually I2C interrupt ++ * tranfer is rarely used, so we ignore the irq setting to limit the interrupt ++ * way. But we keep these codes below, reserve for future modifications */ ++ i2c->irq = -1; ++ ++ while (i2c->msg_idx < i2c->msg_num) { ++#ifdef CONFIG_HI_DMAC ++ if ((i2c->msg->len >= CONFIG_DMA_MSG_MIN_LEN) && (i2c->msg->len <= CONFIG_DMA_MSG_MAX_LEN)) { ++ status = hibvt_i2c_dma_xfer_one_msg(i2c); ++ if (status) ++ break; ++ } else if (i2c->irq >= 0) { ++#else ++ if (i2c->irq >= 0) { ++#endif ++ status = hibvt_i2c_interrupt_xfer_one_msg(i2c); ++ ++ if (status) ++ break; ++ } else { ++ status = hibvt_i2c_polling_xfer_one_msg(i2c); ++ if (status) ++ break; ++ } ++ i2c->msg++; ++ i2c->msg_idx++; ++ } ++ ++ if (!status || i2c->msg_idx > 0) ++ status = i2c->msg_idx; ++ ++ spin_unlock_irqrestore(&i2c->lock, flags); ++ ++ return status; ++} ++/* HI I2C READ * ++ * hi_i2c_master_recv - issue a single I2C message in master receive mode ++ * @client: Handle to slave device ++ * @buf: Where to store data read from slave ++ * @count: How many bytes to read, must be less than 64k since msg.len is u16 ++ * ++ * Returns negative errno, or else the number of bytes read. ++ */ ++int hi_i2c_master_recv(const struct i2c_client *client, char *buf, ++ int count) ++{ ++ printk("Wrong interface call." ++ "hi_i2c_transfer is the only interface to i2c read!!!\n"); ++ ++ return -EIO; ++} ++EXPORT_SYMBOL(hi_i2c_master_recv); ++ ++/*HI I2C WRITE* ++ * hi_i2c_master_send - issue a single I2C message in master transmit mode ++ * @client: Handle to slave device ++ * @buf: Data that will be written to the slave ++ * @count: How many bytes to write, must be less than 64k since msg.len is u16 ++ * ++ * Returns negative errno, or else the number of bytes written. ++ */ ++int hi_i2c_master_send(const struct i2c_client *client, ++ const char *buf, int count) ++{ ++ struct i2c_adapter *adap = client->adapter; ++ struct i2c_msg msg; ++ int msgs_count; ++ ++ if ((client->addr > 0x3ff) ++ || (((client->flags & I2C_M_TEN) == 0) && (client->addr > 0x7f))) { ++ printk(KERN_ERR "dev address out of range\n"); ++ return -EINVAL; ++ } ++ ++ msg.addr = client->addr; ++ msg.flags = client->flags; ++ msg.len = count; ++ ++ if (!buf) { ++ printk(KERN_ERR "Invalid buf == NULL!!!\n"); ++ return -EINVAL; ++ } ++ msg.buf = (__u8 *)buf; ++ ++ msgs_count = hibvt_i2c_xfer(adap, &msg, 1); ++ ++ return (msgs_count == 1) ? count : -EIO; ++} ++EXPORT_SYMBOL(hi_i2c_master_send); ++ ++/** ++ * hi_i2c_transfer - execute a single or combined I2C message ++ * @adap: Handle to I2C bus ++ * @msgs: One or more messages to execute before STOP is issued to ++ * terminate the operation; each message begins with a START. ++ * @num: Number of messages to be executed. ++ * ++ * Returns negative errno, else the number of messages executed. ++ * ++ * Note that there is no requirement that each message be sent to ++ * the same slave address, although that is the most common model. ++ */ ++int hi_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ++ int num) ++{ ++ int msgs_count; ++ ++ if ((msgs[0].addr > 0x3ff) ++ || (((msgs[0].flags & I2C_M_TEN) == 0) && (msgs[0].addr > 0x7f))) { ++ printk(KERN_ERR "msgs[0] dev address out of range\n"); ++ return -EINVAL; ++ } ++ ++ if ((msgs[1].addr > 0x3ff) ++ || (((msgs[1].flags & I2C_M_TEN) == 0) && (msgs[1].addr > 0x7f))) { ++ printk(KERN_ERR "msgs[1] dev address out of range\n"); ++ return -EINVAL; ++ } ++ ++ msgs_count = hibvt_i2c_xfer(adap, msgs, num); ++ ++ return msgs_count; ++} ++EXPORT_SYMBOL(hi_i2c_transfer); ++ ++static u32 hibvt_i2c_func(struct i2c_adapter *adap) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR ++ | I2C_FUNC_PROTOCOL_MANGLING; ++} ++ ++static const struct i2c_algorithm hibvt_i2c_algo = { ++ .master_xfer = hibvt_i2c_xfer, ++ .functionality = hibvt_i2c_func, ++}; ++ ++static int hibvt_i2c_probe(struct platform_device *pdev) ++{ ++ int status; ++ struct hibvt_i2c_dev *i2c; ++ struct i2c_adapter *adap; ++ struct resource *res; ++ ++ i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); ++ if (!i2c) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, i2c); ++ i2c->dev = &pdev->dev; ++ spin_lock_init(&i2c->lock); ++ init_completion(&i2c->msg_complete); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ i2c->phybase = res->start; ++ i2c->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(i2c->base)) { ++ dev_err(i2c->dev, "cannot ioremap resource\n"); ++ return -ENOMEM; ++ } ++ ++ i2c->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(i2c->clk)) { ++ dev_err(i2c->dev, "cannot get clock\n"); ++ return -ENOENT; ++ } ++ clk_prepare_enable(i2c->clk); ++ ++ if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", ++ &i2c->freq)) { ++ dev_warn(i2c->dev, "setting default clock-frequency@%dHz\n", ++ I2C_DEFAULT_FREQUENCY); ++ i2c->freq = I2C_DEFAULT_FREQUENCY; ++ } ++ ++ /* i2c controller initialization, disable interrupt */ ++ hibvt_i2c_hw_init(i2c); ++ ++ i2c->irq = platform_get_irq(pdev, 0); ++ status = devm_request_irq(&pdev->dev, i2c->irq, hibvt_i2c_isr, ++ IRQF_SHARED, dev_name(&pdev->dev), i2c); ++ if (status) { ++ dev_dbg(i2c->dev, "falling back to polling mode"); ++ i2c->irq = -1; ++ } ++ ++ adap = &i2c->adap; ++ i2c_set_adapdata(adap, i2c); ++ adap->owner = THIS_MODULE; ++ strlcpy(adap->name, "hibvt-i2c", sizeof(adap->name)); ++ adap->dev.parent = &pdev->dev; ++ adap->dev.of_node = pdev->dev.of_node; ++ adap->algo = &hibvt_i2c_algo; ++ ++ /* Add the i2c adapter */ ++ status = i2c_add_adapter(adap); ++ if (status) { ++ dev_err(i2c->dev, "failed to add bus to i2c core\n"); ++ goto err_add_adapter; ++ } ++ ++ dev_info(i2c->dev, "%s%d@%dhz registered\n", ++ adap->name, adap->nr, i2c->freq); ++ ++ return 0; ++ ++err_add_adapter: ++ clk_disable_unprepare(i2c->clk); ++ return status; ++} ++ ++static int hibvt_i2c_remove(struct platform_device *pdev) ++{ ++ struct hibvt_i2c_dev *i2c = platform_get_drvdata(pdev); ++ ++ clk_disable_unprepare(i2c->clk); ++ i2c_del_adapter(&i2c->adap); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int hibvt_i2c_suspend(struct device *dev) ++{ ++ struct hibvt_i2c_dev *i2c = dev_get_drvdata(dev); ++ ++ i2c_lock_adapter(&i2c->adap); ++ clk_disable_unprepare(i2c->clk); ++ i2c_unlock_adapter(&i2c->adap); ++ ++ return 0; ++} ++ ++static int hibvt_i2c_resume(struct device *dev) ++{ ++ struct hibvt_i2c_dev *i2c = dev_get_drvdata(dev); ++ ++ i2c_lock_adapter(&i2c->adap); ++ clk_prepare_enable(i2c->clk); ++ hibvt_i2c_hw_init(i2c); ++ i2c_unlock_adapter(&i2c->adap); ++ ++ return 0; ++} ++#endif ++ ++static SIMPLE_DEV_PM_OPS(hibvt_i2c_dev_pm, hibvt_i2c_suspend, ++ hibvt_i2c_resume); ++ ++static const struct of_device_id hibvt_i2c_match[] = { ++ { .compatible = "hisilicon,hibvt-i2c"}, ++ { .compatible = "hisilicon,hi3516cv300-i2c"}, ++ { .compatible = "hisilicon,hi3536dv100-i2c"}, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, hibvt_i2c_match); ++ ++static struct platform_driver hibvt_i2c_driver = { ++ .driver = { ++ .name = "hibvt-i2c", ++ .of_match_table = hibvt_i2c_match, ++ .pm = &hibvt_i2c_dev_pm, ++ }, ++ .probe = hibvt_i2c_probe, ++ .remove = hibvt_i2c_remove, ++}; ++ ++module_platform_driver(hibvt_i2c_driver); ++ ++MODULE_AUTHOR("Pan Wen, "); ++MODULE_DESCRIPTION("HISILICON BVT I2C Bus driver"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/i2c/busses/i2c-hisilicon.c b/drivers/i2c/busses/i2c-hisilicon.c +new file mode 100644 +index 0000000..697225c +--- /dev/null ++++ b/drivers/i2c/busses/i2c-hisilicon.c +@@ -0,0 +1,1155 @@ ++/* ++ * HiSilicon I2C-HISI-V100 Controller Driver ++ * ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "i2c-hisilicon.h" ++#include ++#include ++ ++#ifdef CONFIG_HI_DMAC ++#include ++#endif ++ ++#define I2C_HISI "hisi_i2c" ++ ++#ifdef CONFIG_ARCH_HI3516A ++#include ++#endif ++ ++#ifdef CONFIG_ARCH_HI3518EV20X ++#include ++#endif ++ ++#ifdef CONFIG_ARCH_HI3521A ++#include ++#endif ++ ++#ifdef CONFIG_ARCH_HI3531A ++#include ++#endif ++ ++#define hi_err(x...) \ ++ do { \ ++ pr_alert("%s->%d: ", __func__, __LINE__); \ ++ pr_alert(x); \ ++ pr_alert("\n"); \ ++ } while (0) ++ ++/* #define HI_I2C_DEBUG */ ++ ++#ifdef HI_I2C_DEBUG ++ ++#define hi_msg(x...) \ ++ do { \ ++ pr_alert("%s (line:%d) ", __func__, __LINE__); \ ++ pr_alert(x); \ ++ } while (0) ++#else ++#define hi_msg(args...) do { } while (0) ++#endif ++ ++#define I2C_WAIT_TIME_OUT 20000 ++ ++#define I2C_DFT_RATE (100000) ++ ++struct hi_i2c { ++ unsigned char __iomem *regbase; ++ struct device *dev; ++ struct resource *mem; ++ struct clk *clk; ++ unsigned int irq; ++ struct i2c_adapter adap; ++ struct i2c_msg *msg; ++ struct hi_platform_i2c *pdata; ++ unsigned int g_last_dev_addr; ++ unsigned int g_last_mode; ++ spinlock_t spinlock; ++}; ++ ++static int hi_i2c_abortprocess(struct hi_i2c *pinfo) ++{ ++ unsigned int auto_status; ++ unsigned int tx_src; ++ ++ tx_src = readl(pinfo->regbase + I2C_TX_ABRT_SRC); ++ hi_err("tx_abrt_src is %x.\n", tx_src); ++ ++ auto_status = readl(pinfo->regbase + I2C_AUTO_REG); ++ ++ /* clear 0xB0 err status */ ++ /* auto_mst_tx_abrt_clr ++ auto_tx_cmd_fifo_over_clr ++ auto_rx_cmd_fifo_under_clr ++ auto_rx_cmd_fifo_over_clr ++ */ ++ auto_status |= 0x0f000000; ++ writel(auto_status, pinfo->regbase + I2C_AUTO_REG); ++ writel(0x1, pinfo->regbase + I2C_CLR_INTR_REG); ++ ++ /* disable i2c */ ++ writel(0, pinfo->regbase + I2C_ENABLE_REG); ++ ++ /* enable i2c */ ++ writel(0x1, pinfo->regbase + I2C_ENABLE_REG); ++ ++ return 0; ++} ++ ++void hi_i2c_set_rate(struct hi_i2c *pinfo) ++{ ++ unsigned int apb_clk, scl_h, scl_l, hold; ++ ++ /* get apb bus clk for diff plat */ ++ apb_clk = clk_get_rate(pinfo->clk); ++ ++ /* set SCLH and SCLL depend on apb_clk and def_rate */ ++ if (pinfo->pdata->clk_limit <= I2C_DFT_RATE) { ++ /* in normal mode F_scl: def_rate ++ i2c_scl_hcnt = (F_i2c / F_scl) * 0.5 ++ i2c_scl_hcnt = (F_i2c / F_scl) * 0.5 ++ */ ++ scl_h = (apb_clk / I2C_DFT_RATE) / 2; ++ scl_l = scl_h; ++ } else { ++ /* in fast mode F_scl: def_rate ++ i2c_scl_hcnt = (F_i2c / F_scl) * 0.36 ++ i2c_scl_hcnt = (F_i2c / F_scl) * 0.64 ++ */ ++ scl_h = ((apb_clk / 100) * 36) / pinfo->pdata->clk_limit; ++ scl_l = ((apb_clk / 100) * 64) / pinfo->pdata->clk_limit; ++ } ++ ++ writel(scl_h, pinfo->regbase + I2C_SCL_H_REG); ++ writel(scl_l, pinfo->regbase + I2C_SCL_L_REG); ++ ++ /* set hi_i2c hold time */ ++ hold = scl_h / 2; ++ writel(hold, pinfo->regbase + I2C_SDA_HOLD_REG); ++} ++ ++void hi_i2c_hw_init(struct hi_i2c *pinfo) ++{ ++ unsigned int temp, rx_fifo, tx_fifo; ++ ++ /* unlock hi_i2c controller to access */ ++ writel(HI_I2C_UNLOCK_VALUE, pinfo->regbase + I2C_LOCK_REG); ++ ++ /* disable hi_i2c controller */ ++ temp = readl(pinfo->regbase + I2C_ENABLE_REG); ++ writel((temp & ~HI_I2C_ENABLE), pinfo->regbase + I2C_ENABLE_REG); ++ ++ /* disable hi_i2c auto_mode */ ++ writel(HI_I2C_AUTO_MODE_OFF, pinfo->regbase + I2C_AUTO_REG); ++ ++ /* set hi_i2c in fast mode */ ++ writel(HI_I2C_FAST_MODE, pinfo->regbase + I2C_CON_REG); ++ ++ /* set hi_i2c rate */ ++ hi_i2c_set_rate(pinfo); ++ ++ rx_fifo = HI_I2C_RX_FIFO; ++ tx_fifo = HI_I2C_TX_FIFO; ++ ++ /* set hi_i2c fifo */ ++ writel(rx_fifo, pinfo->regbase + I2C_RX_TL_REG); ++ writel(tx_fifo, pinfo->regbase + I2C_TX_TL_REG); ++ ++ /* enable interrupt mask */ ++ writel(DISABLE_ALL_INTERRUPTS, pinfo->regbase + I2C_INTR_MASK_REG); ++ ++ /* enable hi_i2c controller */ ++ temp = readl(pinfo->regbase + I2C_ENABLE_REG); ++ writel((temp | HI_I2C_ENABLE), pinfo->regbase + I2C_ENABLE_REG); ++ ++ pinfo->g_last_dev_addr = 0; ++ pinfo->g_last_mode = I2C_MODE_NONE; ++ ++ pinfo->msg = NULL; ++} ++ ++int hi_i2c_wait_idle(struct hi_i2c *pinfo) ++{ ++ unsigned int val; ++ unsigned int time_cnt; ++ ++ time_cnt = 0; ++ do { ++ val = readl(pinfo->regbase + I2C_INTR_RAW_REG); ++ if (val & I2C_RAW_TX_ABORT) { ++ hi_err("wait last i2c fifo is empty abort! "\ ++ "int_raw_status: %#x!\n", val); ++ return hi_i2c_abortprocess(pinfo); ++ } ++ ++ val = readl(pinfo->regbase + I2C_AUTO_REG); ++ if (!IS_RX_FIFO_EMPTY(val)) ++ readl(pinfo->regbase + I2C_TX_RX_REG); ++ ++ if (IS_FIFO_EMPTY(val)) ++ break; ++ ++ if (time_cnt > I2C_WAIT_TIME_OUT) { ++ hi_err("wait last i2c fifo is empty timeout! "\ ++ "auto_status: %#x\n", val); ++ return -EBUSY; ++ } ++ time_cnt++; ++ udelay(50); ++ } while (1); ++ ++ udelay(10); ++ ++ time_cnt = 0; ++ do { ++ val = readl(pinfo->regbase + I2C_INTR_RAW_REG); ++ if (val & I2C_RAW_TX_ABORT) { ++ hi_err("wait last i2c is idle abort! "\ ++ "int_raw_status: %#x!\n", val); ++ return hi_i2c_abortprocess(pinfo); ++ } ++ ++ val = readl(pinfo->regbase + I2C_STATUS_REG); ++ if (IS_I2C_IDLE(val)) ++ break; ++ ++ if (time_cnt > I2C_WAIT_TIME_OUT) { ++ hi_err("wait last i2c is idle timeout! "\ ++ "auto_status: %#x\n", val); ++ return -EBUSY; ++ } ++ time_cnt++; ++ udelay(50); ++ } while (1); ++ ++ return 0; ++} ++ ++/* wait until tx fifo is not full */ ++int hi_i2c_wait_txfifo_notfull(struct hi_i2c *pinfo) ++{ ++ unsigned int val; ++ unsigned int time_cnt; ++ ++ time_cnt = 0; ++ do { ++ val = readl(pinfo->regbase + I2C_INTR_RAW_REG); ++ if (val & I2C_RAW_TX_ABORT) { ++ hi_err("abort! last int_raw_status: %#x!\n", val); ++ return hi_i2c_abortprocess(pinfo); ++ } ++ ++ val = readl(pinfo->regbase + I2C_AUTO_REG); ++ if (!IS_RX_FIFO_EMPTY(val)) ++ readl(pinfo->regbase + I2C_TX_RX_REG); ++ ++ if (val & I2c_AUTO_TX_FIFO_NOT_FULL) ++ break; ++ ++ if (time_cnt > I2C_WAIT_TIME_OUT) { ++ hi_err("timeout! last auto_status: %#x\n", val); ++ return -EBUSY; ++ } ++ time_cnt++; ++ udelay(50); ++ } while (1); ++ ++ return 0; ++} ++ ++/* wait until tx fifo is not empty */ ++int hi_i2c_wait_rxfifo_notempty(struct hi_i2c *pinfo) ++{ ++ unsigned int val; ++ unsigned int time_cnt; ++ ++ time_cnt = 0; ++ do { ++ val = readl(pinfo->regbase + I2C_INTR_RAW_REG); ++ if ((val & I2C_RAW_TX_ABORT) == I2C_RAW_TX_ABORT) { ++ hi_err("abort! int_raw_status: %#x!\n", val); ++ hi_i2c_abortprocess(pinfo); ++ return -EIO; ++ } ++ ++ val = readl(pinfo->regbase + I2C_AUTO_REG); ++ if (!IS_RX_FIFO_EMPTY(val)) ++ break; ++ ++ if (time_cnt > I2C_WAIT_TIME_OUT) { ++ hi_err("timeout! auto_status: %#x\n", val); ++ hi_i2c_abortprocess(pinfo); ++ return -EBUSY; ++ } ++ time_cnt++; ++ udelay(50); ++ } while (1); ++ ++ return 0; ++} ++ ++static inline int hi_i2c_set_dev_addr_and_mode(struct hi_i2c *pinfo, ++ unsigned int work_mode) ++{ ++ unsigned int dev_addr = pinfo->msg->addr; ++ ++ if ((pinfo->g_last_dev_addr == dev_addr) ++ && (pinfo->g_last_mode == work_mode)) ++ return 0; ++ ++ /* wait until all cmd in fifo is finished and i2c is idle */ ++ if (hi_i2c_wait_idle(pinfo) < 0) ++ return -1; ++ ++ /* disable i2c */ ++ writel(0x0, pinfo->regbase + I2C_ENABLE_REG); ++ /* clear interrupt */ ++ writel(0x1, pinfo->regbase + I2C_CLR_INTR_REG); ++ /* enable interrupt mask */ ++ writel(DISABLE_ALL_INTERRUPTS, pinfo->regbase + I2C_INTR_MASK_REG); ++ /* clear err status */ ++ writel(0x0f000000, pinfo->regbase + I2C_AUTO_REG); ++ ++ /* different device, need to reinit i2c ctrl */ ++ if ((pinfo->g_last_dev_addr) != dev_addr) { ++ /* set slave dev addr */ ++ writel((dev_addr & 0xff)>>1, pinfo->regbase + I2C_TAR_REG); ++ pinfo->g_last_dev_addr = dev_addr; ++ } ++ ++ if (pinfo->g_last_mode != work_mode) { ++ ++ /* set auto mode */ ++ if (work_mode == I2C_MODE_AUTO) { ++ writel(0x0, pinfo->regbase + I2C_DMA_CMD0); ++ writel(0x80000000, pinfo->regbase + I2C_AUTO_REG); ++ pinfo->g_last_mode = work_mode; ++ } else if (work_mode == I2C_MODE_DMA) { ++ writel(0x0, pinfo->regbase + I2C_AUTO_REG); ++ pinfo->g_last_mode = work_mode; ++ } else { ++ hi_err("invalid i2c mode\n"); ++ return -1; ++ } ++ } ++ ++ /* enable i2c */ ++ writel(0x1, pinfo->regbase + I2C_ENABLE_REG); ++ ++ hi_msg("\n@@@@@@@@@@\n"); ++ ++ return 0; ++} ++ ++int hi_i2c_write(struct hi_i2c *pinfo) ++{ ++ unsigned int reg_val; ++ unsigned int temp_reg; ++ unsigned int temp_data; ++ unsigned int temp_auto_reg; ++ unsigned int min_msgs_len = 0; ++ struct i2c_msg *msg = pinfo->msg; ++ unsigned int msg_buf_ptr = 0; ++ ++ min_msgs_len = (msg->flags & I2C_M_16BIT_REG) ? 2 : 1; ++ min_msgs_len += (msg->flags & I2C_M_16BIT_DATA) ? 2 : 1; ++ if (msg->len < min_msgs_len){ ++ hi_err("Unsupported this length: %d!\n", msg->len); ++ return -1; ++ } ++ ++ if (hi_i2c_set_dev_addr_and_mode(pinfo, I2C_MODE_AUTO) < 0) ++ return -1; ++ ++ temp_auto_reg = HI_I2C_WRITE; ++ ++ if (msg->flags & I2C_M_16BIT_REG) { ++ /* 16bit reg addr */ ++ temp_auto_reg |= I2C_AUTO_ADDR; ++ ++ /* switch high byte and low byte */ ++ temp_reg = msg->buf[msg_buf_ptr] << 8; ++ ++ msg_buf_ptr++; ++ ++ temp_reg |= msg->buf[msg_buf_ptr]; ++ ++ msg_buf_ptr++; ++ } else { ++ temp_reg = msg->buf[msg_buf_ptr]; ++ msg_buf_ptr++; ++ } ++ ++ if (msg->flags & I2C_M_16BIT_DATA) { ++ /* 16bit data */ ++ temp_auto_reg |= I2C_AUTO_DATA; ++ ++ /* switch high byte and low byte */ ++ temp_data = msg->buf[msg_buf_ptr] << 8; ++ ++ msg_buf_ptr++; ++ ++ temp_data |= msg->buf[msg_buf_ptr]; ++ ++ msg_buf_ptr++; ++ } else { ++ temp_data = msg->buf[msg_buf_ptr]; ++ msg_buf_ptr++; ++ } ++ ++ writel(temp_auto_reg, pinfo->regbase + I2C_AUTO_REG); ++ hi_msg("temp_auto_reg: 0x%x\n", temp_auto_reg); ++ ++ /* set write reg&data */ ++ reg_val = (temp_reg << REG_SHIFT) | temp_data; ++ ++ /* wait until tx fifo not full */ ++ if (hi_i2c_wait_txfifo_notfull(pinfo) < 0) ++ return -1; ++ ++ hi_msg("reg_val = %x\n", reg_val); ++ ++ writel(reg_val, pinfo->regbase + I2C_TX_RX_REG); ++ ++ hi_msg("dev_addr =%x, reg_addr = %x, Data = %x\n", ++ pinfo->msg->addr, pinfo->msg->buf[0], pinfo->msg->buf[1]); ++ ++ return 0; ++} ++ ++unsigned int hi_i2c_read(struct hi_i2c *pinfo) ++{ ++ unsigned int reg_val; ++ unsigned int temp_reg; ++ unsigned int ret_data = 0xffff; ++ unsigned int temp_auto_reg; ++ unsigned int min_msgs_len = 0; ++ struct i2c_msg *msg = pinfo->msg; ++ ++ min_msgs_len = (msg->flags & I2C_M_16BIT_REG) ? 2 : 1; ++ if (msg->len < min_msgs_len){ ++ hi_err("Unsupported this length: %d!\n", msg->len); ++ return -1; ++ } ++ ++ if (hi_i2c_set_dev_addr_and_mode(pinfo, I2C_MODE_AUTO) < 0) ++ return -1; ++ ++ temp_auto_reg = HI_I2C_READ; ++ ++ if (msg->flags & I2C_M_16BIT_REG) { ++ /* 16bit reg addr */ ++ temp_auto_reg |= I2C_AUTO_ADDR; ++ ++ /* switch high byte and low byte */ ++ temp_reg = msg->buf[0] << 8; ++ temp_reg |= msg->buf[1]; ++ } else { ++ temp_reg = msg->buf[0]; ++ } ++ ++ if (msg->flags & I2C_M_16BIT_DATA) ++ /* 16bit data */ ++ temp_auto_reg |= I2C_AUTO_DATA; ++ ++ writel(temp_auto_reg, pinfo->regbase + I2C_AUTO_REG); ++ hi_msg("temp_auto_reg: 0x%x\n", temp_auto_reg); ++ ++ /* 1. write addr */ ++ reg_val = temp_reg << REG_SHIFT; ++ hi_msg("reg_val %x\n", reg_val); ++ ++ /* wait until tx fifo not full */ ++ if (hi_i2c_wait_txfifo_notfull(pinfo) < 0) ++ return -1; ++ ++ /* regaddr */ ++ writel(reg_val, pinfo->regbase + I2C_TX_RX_REG); ++ ++ /* 2. read return data */ ++ /* wait until rx fifo not empty */ ++ if (hi_i2c_wait_rxfifo_notempty(pinfo) < 0) ++ return -1; ++ ++ ret_data = readl(pinfo->regbase + I2C_TX_RX_REG) & DATA_16BIT_MASK; ++ hi_msg("ret_data = %x\n", ret_data); ++ ++ if (msg->flags & I2C_M_16BIT_DATA) { ++ pinfo->msg->buf[0] = ret_data & DATA_8BIT_MASK; ++ pinfo->msg->buf[1] = (ret_data >> 8) & DATA_8BIT_MASK; ++ } else { ++ pinfo->msg->buf[0] = ret_data & DATA_8BIT_MASK; ++ } ++ ++ writel(0x1, pinfo->regbase + I2C_CLR_INTR_REG); ++ ++ return 0; ++} ++ ++/************************************ ++ * dma functions * ++************************************/ ++#ifdef CONFIG_HI_DMAC ++void hi_i2c_dma_start(struct hi_i2c *pinfo, unsigned int dir) ++{ ++ writel((1 << dir), pinfo->regbase + I2C_DMA_CTRL_REG); ++} ++ ++void hi_i2c_dmac_config(struct hi_i2c *pinfo, unsigned int dir) ++{ ++ /* 1. enable RX(0) or TX(1) in DMA mode */ ++ hi_i2c_dma_start(pinfo, dir); ++ ++ /* 2. set dma fifo */ ++ writel(4, pinfo->regbase + I2C_DMA_TDLR); ++ writel(4, pinfo->regbase + I2C_DMA_RDLR); ++} ++ ++void hi_i2c_start_rx(struct hi_i2c *pinfo, unsigned int reg_addr, ++ unsigned int length) ++{ ++ unsigned int reg; ++ ++ writel(reg_addr, pinfo->regbase + I2C_DMA_CMD1); ++ writel(length, pinfo->regbase + I2C_DMA_CMD2); ++ ++ reg = readl(pinfo->regbase + I2C_DMA_CMD0); ++ ++ /*start tx*/ ++ reg &= ~0x40000000; ++ writel((0x80000000 | reg), pinfo->regbase + I2C_DMA_CMD0); ++} ++ ++void hi_i2c_start_tx(struct hi_i2c *pinfo, unsigned int reg_addr, ++ unsigned int length) ++{ ++ unsigned int reg; ++ ++ writel(reg_addr, pinfo->regbase + I2C_DMA_CMD1); ++ writel(length, pinfo->regbase + I2C_DMA_CMD2); ++ ++ reg = readl(pinfo->regbase + I2C_DMA_CMD0); ++ ++ /*start rx*/ ++ writel((0xc0000000 | reg), pinfo->regbase + I2C_DMA_CMD0); ++} ++ ++int dma_to_i2c(unsigned int src, unsigned int dst, unsigned int length) ++{ ++ int chan; ++ ++ chan = do_dma_m2p(src, dst, length); ++ if (chan == -1) ++ hi_err("dma_to_i2c error\n"); ++ ++ return chan; ++} ++ ++ ++int i2c_to_dma(unsigned int src, unsigned int dst, unsigned int length) ++{ ++ int chan; ++ ++ chan = do_dma_p2m(dst, src, length); ++ if (chan == -1) ++ hi_err("dma_p2m error...\n"); ++ ++ return chan; ++} ++ ++static int hi_i2c_do_dma_write(struct hi_i2c *pinfo, ++ unsigned int reg_addr, unsigned int reg_addr_num, ++ unsigned int dma_buf, unsigned int length) ++{ ++ unsigned int temp_reg = reg_addr; ++ int chan; ++ ++ /* 1. switch i2c devaddr and dma mode*/ ++ if (hi_i2c_set_dev_addr_and_mode(pinfo, I2C_MODE_DMA) < 0) ++ return -1; ++ ++ if (2 == reg_addr_num) { ++ /* switch high byte and low byte */ ++ temp_reg = REVERT_HL_BYTE(reg_addr); ++ writel(0x10000000, pinfo->regbase + I2C_DMA_CMD0); ++ } else { ++ writel(0x0, pinfo->regbase + I2C_DMA_CMD0); ++ } ++ ++ /* 2. config i2c into DMA mode */ ++ hi_i2c_dmac_config(pinfo, 0x1); ++ ++ /* 3. start i2c logic to write */ ++ hi_i2c_start_tx(pinfo, temp_reg, length - 1); ++ ++ /* 4. transmit DATA from DMAC to I2C in DMA mode */ ++ chan = dma_to_i2c(dma_buf, (pinfo->mem->start + I2C_DATA_CMD_REG), ++ length); ++ ++ if (dmac_wait(chan) != DMAC_CHN_SUCCESS) { ++ hi_err("dma wait failed\n"); ++ dmac_channel_free(chan); ++ return -1; ++ } ++ ++ dmac_channel_free(chan); ++ ++ return 0; ++} ++ ++static int hi_i2c_do_dma_read(struct hi_i2c *pinfo, ++ unsigned int reg_addr, unsigned int reg_addr_num, ++ unsigned int dma_buf, unsigned int length) ++{ ++ unsigned int temp_reg = reg_addr; ++ int chan; ++ ++ /* 1. switch i2c devaddr and dma mode*/ ++ if (hi_i2c_set_dev_addr_and_mode(pinfo, I2C_MODE_DMA) < 0) ++ return -1; ++ ++ if (2 == reg_addr_num) { ++ /* switch high byte and low byte */ ++ temp_reg = REVERT_HL_BYTE(reg_addr); ++ writel(0x10000000, pinfo->regbase + I2C_DMA_CMD0); ++ } else { ++ writel(0x0, pinfo->regbase + I2C_DMA_CMD0); ++ } ++ ++ /* 2. config i2c into DMA mode */ ++ hi_i2c_dmac_config(pinfo, 0x0); ++ ++ /* 3. transmit DATA from I2C to DMAC in DMA mode */ ++ chan = i2c_to_dma((pinfo->mem->start + I2C_DATA_CMD_REG), ++ dma_buf, length); ++ ++ /* 4. start i2c logic to read */ ++ hi_i2c_start_rx(pinfo, temp_reg, length - 1); ++ ++ if (dmac_wait(chan) != DMAC_CHN_SUCCESS) { ++ hi_err("dma wait failed\n"); ++ dmac_channel_free(chan); ++ return -1; ++ } ++ ++ dmac_channel_free(chan); ++ ++ return 0; ++} ++ ++#else ++static int hi_i2c_do_dma_write(struct hi_i2c *pinfo, ++ unsigned int reg_addr, unsigned int reg_addr_num, ++ unsigned int dma_buf, unsigned int length) ++{ ++ hi_err("DMA is not enabled!"); ++ return -1; ++} ++ ++static int hi_i2c_do_dma_read(struct hi_i2c *pinfo, ++ unsigned int reg_addr, unsigned int reg_addr_num, ++ unsigned int dma_buf, unsigned int length) ++{ ++ hi_err("DMA is not enabled!"); ++ return -1; ++} ++#endif ++ ++int hi_i2c_dma_write(const struct i2c_client *client, unsigned int dma_buf, ++ unsigned int reg_addr, unsigned int reg_addr_num, ++ unsigned int length) ++{ ++ struct i2c_adapter *adap = client->adapter; ++ struct hi_i2c *pinfo = (struct hi_i2c *)i2c_get_adapdata(adap); ++ struct i2c_msg msg; ++ int ret; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&adap->spinlock, flags); ++ ++ memset(&msg, 0x0, sizeof(struct i2c_msg)); ++ msg.addr = client->addr; ++ msg.flags = client->flags; ++ msg.len = length; ++ ++ pinfo->msg = &msg; ++ ++ ret = hi_i2c_do_dma_write(pinfo, reg_addr, reg_addr_num, dma_buf, ++ length); ++ ++ spin_unlock_irqrestore(&adap->spinlock, flags); ++ ++ return ret; ++} ++EXPORT_SYMBOL(hi_i2c_dma_write); ++ ++int hi_i2c_dma_read(const struct i2c_client *client, unsigned int dma_buf, ++ unsigned int reg_addr, unsigned int reg_addr_num, ++ unsigned int length) ++{ ++ struct i2c_adapter *adap = client->adapter; ++ struct hi_i2c *pinfo = (struct hi_i2c *)i2c_get_adapdata(adap); ++ struct i2c_msg msg; ++ int ret; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&adap->spinlock, flags); ++ ++ memset(&msg, 0x0, sizeof(struct i2c_msg)); ++ msg.addr = client->addr; ++ msg.flags = client->flags; ++ msg.flags |= I2C_M_RD; ++ msg.len = length; ++ ++ pinfo->msg = &msg; ++ ++ ret = hi_i2c_do_dma_read(pinfo, reg_addr, reg_addr_num, dma_buf, ++ length); ++ ++ spin_unlock_irqrestore(&adap->spinlock, flags); ++ ++ return ret; ++} ++EXPORT_SYMBOL(hi_i2c_dma_read); ++ ++static int hi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ++ int num) ++{ ++ struct hi_i2c *pinfo = (struct hi_i2c *)i2c_get_adapdata(adap); ++ unsigned int msg_idx; ++ dma_addr_t dma_buf; ++ __u16 len; ++ unsigned int reg_addr; ++ unsigned int reg_width; ++ int ret; ++ unsigned long flags; ++ ++ if (!msgs || (num <= 0)) { ++ hi_err("msgs == NULL || num <= 0, Invalid argument!\n"); ++ return -EINVAL; ++ } ++ ++ spin_lock_irqsave(&pinfo->spinlock, flags); ++ ++ pinfo->msg = msgs; ++ ++ for (msg_idx = 0; msg_idx < num; msg_idx++) { ++ len = pinfo->msg->len; ++ if (pinfo->msg->flags & I2C_M_16BIT_REG) { ++ reg_addr = pinfo->msg->buf[0]; ++ reg_addr |= pinfo->msg->buf[1] << 8; ++ reg_width = 2; ++ } else { ++ reg_addr = pinfo->msg->buf[0]; ++ reg_width = 1; ++ } ++ ++ if (pinfo->msg->flags & I2C_M_DMA) { ++ if (pinfo->msg->flags & I2C_M_16BIT_DATA) { ++ hi_err("I2C DMA no support I2C_M_16BIT_DATA\n"); ++ ret = -EINVAL; ++ goto end; ++ } ++ ++ if (((pinfo->msg->flags & I2C_M_RD) && (len <= 0)) || ++ (!(pinfo->msg->flags & I2C_M_RD) && ++ (len <= reg_width))) { ++ hi_err("msg->len == %d, Invalid argument!\n", ++ len); ++ ret = -EINVAL; ++ goto end; ++ } ++ ++ dma_buf = dma_map_single(pinfo->dev, ++ pinfo->msg->buf, len, ++ DMA_BIDIRECTIONAL); ++ if (dma_mapping_error(pinfo->dev, dma_buf)) { ++ hi_err("DMA mapping failed\n"); ++ ret = -EINVAL; ++ goto end; ++ } ++ ++ if (pinfo->msg->flags & I2C_M_RD) ++ ret = hi_i2c_do_dma_read(pinfo, reg_addr, ++ reg_width, dma_buf, len); ++ else ++ ret = hi_i2c_do_dma_write(pinfo, reg_addr, ++ reg_width, dma_buf + reg_width, ++ len - reg_width); ++ ++ dma_unmap_single(pinfo->dev, dma_buf, len, ++ DMA_BIDIRECTIONAL); ++ ++ if (ret) ++ break; ++ } else { ++ if (pinfo->msg->flags & I2C_M_RD) ++ ret = hi_i2c_read(pinfo); ++ else ++ ret = hi_i2c_write(pinfo); ++ ++ if (ret) ++ break; ++ } ++ pinfo->msg++; ++ } ++ ++ if (!ret || msg_idx > 0) ++ ret = msg_idx; ++ else ++ ret = -EIO; ++ ++end: ++ spin_unlock_irqrestore(&pinfo->spinlock, flags); ++ ++ /* ++ * If everything went ok (i.e. 1 msg transmitted), (ret = 1) means return #bytes ++ * transmitted, else return error code. see i2c-core.c ++ */ ++ return ret; ++} ++ ++/* HI I2C READ * ++ * hi_i2c_master_recv - issue a single I2C message in master receive mode ++ * @client: Handle to slave device ++ * @buf: Where to store data read from slave ++ * @count: How many bytes to read, must be less than 64k since msg.len is u16 ++ * ++ * Returns negative errno, or else the number of bytes read. ++ */ ++int hi_i2c_master_recv(const struct i2c_client *client, char *buf, ++ int count) ++{ ++ struct i2c_adapter *adap = client->adapter; ++ struct i2c_msg msgs; ++ unsigned int reg_width, data_width, max_width; ++ int msgs_count; ++ ++ memset(&msgs, 0x0, sizeof(struct i2c_msg)); ++ msgs.addr = client->addr; ++ msgs.flags = client->flags; ++ msgs.flags |= I2C_M_RD; ++ ++ if (client->flags & I2C_M_16BIT_REG) ++ reg_width = 2; ++ else ++ reg_width = 1; ++ ++ if (client->flags & I2C_M_16BIT_DATA) ++ data_width = 2; ++ else ++ data_width = 1; ++ ++ max_width = max_t(size_t, reg_width, data_width); ++ ++ if (count > max_width) { ++ msgs.flags |= I2C_M_DMA; ++ msgs.len = count; ++ } else if (count <= 0 ) { ++ hi_err("ERR. Invalid count: 0x%d!!!\n", count); ++ return -EINVAL; ++ } else ++ msgs.len = max_width; ++ ++ if (!buf) { ++ hi_err("ERR. Invalid buf == NULL!!!\n"); ++ return -EINVAL; ++ } ++ msgs.buf = buf; ++ ++ msgs_count = hi_i2c_xfer(adap, &msgs, 1); ++ ++ return (msgs_count == 1) ? count : -EIO; ++} ++EXPORT_SYMBOL(hi_i2c_master_recv); ++ ++/*HI I2C WRITE* ++ * hi_i2c_master_send - issue a single I2C message in master transmit mode ++ * @client: Handle to slave device ++ * @buf: Data that will be written to the slave ++ * @count: How many bytes to write, must be less than 64k since msg.len is u16 ++ * ++ * Returns negative errno, or else the number of bytes written. ++ */ ++int hi_i2c_master_send(const struct i2c_client *client, ++ const char *buf, int count) ++{ ++ struct i2c_adapter *adap = client->adapter; ++ struct i2c_msg msgs; ++ unsigned int reg_width, data_width; ++ int msgs_count; ++ ++ memset(&msgs, 0x0, sizeof(struct i2c_msg)); ++ msgs.addr = client->addr; ++ msgs.flags = client->flags; ++ ++ if (client->flags & I2C_M_16BIT_REG) ++ reg_width = 2; ++ else ++ reg_width = 1; ++ ++ if (client->flags & I2C_M_16BIT_DATA) ++ data_width = 2; ++ else ++ data_width = 1; ++ ++ if (count - reg_width > data_width) ++ msgs.flags |= I2C_M_DMA; ++ else if (count - reg_width < data_width) { ++ hi_err("ERR. Invalid count!!!\n"); ++ return -EINVAL; ++ } ++ ++ msgs.len = count; ++ ++ if (!buf) { ++ hi_err("ERR. Invalid buf! == NULL!!\n"); ++ return -EINVAL; ++ } ++ msgs.buf = (__u8 *)buf; ++ ++ msgs_count = hi_i2c_xfer(adap, &msgs, 1); ++ ++ return (msgs_count == 1) ? count : -EIO; ++} ++EXPORT_SYMBOL(hi_i2c_master_send); ++ ++/** ++ * hi_i2c_transfer - execute a single or combined I2C message ++ * @adap: Handle to I2C bus ++ * @msgs: One or more messages to execute before STOP is issued to ++ * terminate the operation; each message begins with a START. ++ * @num: Number of messages to be executed. ++ * ++ * Returns negative errno, else the number of messages executed. ++ * ++ * Note that there is no requirement that each message be sent to ++ * the same slave address, although that is the most common model. ++ */ ++int hi_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ++ int num) ++{ ++ printk("Wrong interface call." ++ "hi_i2c_master_recv is the only interface to i2c read!!!\n"); ++ ++ return -EIO; ++} ++EXPORT_SYMBOL(hi_i2c_transfer); ++/**************************************************************/ ++ ++static u32 hi_i2c_func(struct i2c_adapter *adap) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static const struct i2c_algorithm hi_i2c_algo = { ++ .master_xfer = hi_i2c_xfer, ++ .functionality = hi_i2c_func, ++}; ++ ++static int hi_i2c_probe(struct platform_device *pdev) ++{ ++ int errorcode; ++ struct hi_i2c *pinfo; ++ struct i2c_adapter *adap; ++ struct resource *mem; ++ struct hi_platform_i2c *platform_info; ++ int tmp = 0; ++ struct device *dev = &pdev->dev; ++ struct device_node *np = pdev->dev.of_node; ++ ++ pdev->name = I2C_HISI; ++ tmp = of_property_read_u32(np, "id", &pdev->id); ++ if (tmp) { ++ dev_err(&pdev->dev, "Get id failed!\n"); ++ errorcode = -EBADF; ++ goto i2c_errorcode_na; ++ } ++ ++ platform_info = devm_kzalloc(dev, sizeof(*platform_info), GFP_KERNEL); ++ if (!platform_info) ++ return -ENOMEM; ++ ++ mem = devm_kzalloc(dev, sizeof(*mem), GFP_KERNEL); ++ if (!mem) ++ return -ENOMEM; ++ ++ tmp = of_property_read_u32(np, "clock-frequency", &platform_info->clk_limit); ++ if (tmp) { ++ dev_err(&pdev->dev, "Get clock-frequency failed!\n"); ++ errorcode = -EBADF; ++ goto i2c_errorcode_na; ++ } ++ platform_info->i2c_class = I2C_CLASS_DDC; ++ ++ dev->platform_data = platform_info; ++ ++ pinfo = kzalloc(sizeof(struct hi_i2c), GFP_KERNEL); ++ if (pinfo == NULL) { ++ dev_err(&pdev->dev, "Out of memory!\n"); ++ errorcode = -ENOMEM; ++ goto i2c_errorcode_na; ++ } ++ ++ tmp = of_property_read_u32(np, "reg", &mem->start); ++ if (tmp) { ++ dev_err(&pdev->dev, "Get reg failed!\n"); ++ errorcode = -ENXIO; ++ goto i2c_errorcode_na; ++ } ++ ++ tmp = of_property_read_u32(np, "io-size", &mem->end); ++ if (tmp) { ++ dev_err(&pdev->dev, "Get io-size failed!\n"); ++ errorcode = -EBADF; ++ goto i2c_errorcode_na; ++ } ++ mem->end = mem->start + mem->end -1; ++ mem->flags = IORESOURCE_MEM; ++ pdev->resource = mem; ++ pinfo->regbase = (unsigned char __iomem *)IO_ADDRESS(mem->start); ++ pinfo->mem = mem; ++ /* find the clock and enable it */ ++ pinfo->clk = devm_clk_get(&pdev->dev, NULL); ++ pinfo->dev = &pdev->dev; ++ pinfo->pdata = platform_info; ++ pinfo->g_last_dev_addr = 0; ++ ++ spin_lock_init(&pinfo->spinlock); ++ ++ hi_i2c_hw_init(pinfo); ++ ++ platform_set_drvdata(pdev, pinfo); ++ ++ adap = &pinfo->adap; ++ i2c_set_adapdata(adap, pinfo); ++ adap->owner = THIS_MODULE; ++ adap->class = platform_info->i2c_class; ++ strlcpy(adap->name, pdev->name, sizeof(adap->name)); ++ adap->algo = &hi_i2c_algo; ++ adap->dev.parent = &pdev->dev; ++ adap->nr = pdev->id; ++ adap->retries = HI_I2C_RETRIES; ++ errorcode = i2c_add_numbered_adapter(adap); ++ if (errorcode) { ++ dev_err(&pdev->dev, ++ "%s: Adding I2C adapter failed!\n", __func__); ++ goto i2c_errorcode_free_irq; ++ } ++ dev_notice(&pdev->dev, ++ "Hisilicon [%s] probed!\n", ++ dev_name(&pinfo->adap.dev)); ++ ++ goto i2c_errorcode_na; ++ ++i2c_errorcode_free_irq: ++ free_irq(pinfo->irq, pinfo); ++ kfree(pinfo); ++ ++i2c_errorcode_na: ++ return errorcode; ++} ++ ++static int hi_i2c_remove(struct platform_device *pdev) ++{ ++ struct hi_i2c *pinfo = NULL; ++ int errorcode = 0; ++ ++ pinfo = platform_get_drvdata(pdev); ++ ++ if (pinfo) { ++ i2c_del_adapter(&pinfo->adap); ++ ++ free_irq(pinfo->irq, pinfo); ++ ++ kfree(pinfo); ++ } ++ ++ dev_notice(&pdev->dev, ++ "Remove Hisilicon Media Processor" ++ "I2C adapter [%d].\n", errorcode); ++ ++ return errorcode; ++} ++ ++#ifdef CONFIG_PM ++static int hi_i2c_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ struct hi_i2c *pinfo; ++ ++ pinfo = platform_get_drvdata(pdev); ++ ++ hi_i2c_abortprocess(pinfo); ++ ++ return 0; ++} ++ ++static int hi_i2c_resume(struct platform_device *pdev) ++{ ++ struct hi_i2c *pinfo; ++ ++ pinfo = platform_get_drvdata(pdev); ++ ++ hi_i2c_hw_init(pinfo); ++ ++ return 0; ++} ++#else ++#define hi_i2c_suspend NULL ++#define hi_i2c_resume NULL ++#endif ++ ++/******************************************************************************/ ++static const struct of_device_id hi_i2c_match[] = { ++ { .compatible = "hisilicon,hisi-i2c-hisilicon"}, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, hi_i2c_match); ++/******************************************************************************/ ++ ++static struct platform_driver hi_i2c_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "hisi-i2c-hisilicon", ++ .of_match_table = of_match_ptr(hi_i2c_match), ++ }, ++ .probe = hi_i2c_probe, ++ .remove = hi_i2c_remove, ++#ifdef CONFIG_PM ++ .suspend = hi_i2c_suspend, ++ .resume = hi_i2c_resume, ++#endif ++}; ++ ++module_platform_driver(hi_i2c_driver); ++ ++MODULE_DESCRIPTION("HISILICON I2C Bus driver"); ++MODULE_AUTHOR("BVT OSDRV"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/i2c/busses/i2c-hisilicon.h b/drivers/i2c/busses/i2c-hisilicon.h +new file mode 100644 +index 0000000..bb49513 +--- /dev/null ++++ b/drivers/i2c/busses/i2c-hisilicon.h +@@ -0,0 +1,112 @@ ++#ifndef __HI_I2C_H__ ++#define __HI_I2C_H__ ++ ++#define HI_I2C_RX_FIFO 0x8 ++#define HI_I2C_TX_FIFO 0x8 ++#define HI_I2C_RETRIES 0x1 ++ ++#define I2C_CON_REG 0x000 ++#define I2C_TAR_REG 0x004 ++#define I2C_DATA_CMD_REG 0x010 ++#define I2C_SCL_H_REG 0x01C ++#define I2C_SCL_L_REG 0x020 ++#define I2C_INTR_STAT_REG 0x02C ++#define I2C_INTR_MASK_REG 0x030 ++#define I2C_INTR_RAW_REG 0x034 ++#define I2C_RX_TL_REG 0x038 ++#define I2C_TX_TL_REG 0x03C ++#define I2C_CLR_INTR_REG 0x040 ++#define I2C_CLR_RX_OVER_REG 0x048 ++#define I2C_CLR_TX_OVER_REG 0x04C ++#define I2C_ENABLE_REG 0x06C ++#define I2C_STATUS_REG 0x070 ++#define I2C_TXFLR_REG 0x074 ++#define I2C_RXFLR_REG 0x078 ++#define I2C_SDA_HOLD_REG 0x07C ++#define I2C_TX_ABRT_SRC 0x080 ++#define I2C_DMA_CTRL_REG 0x088 ++#define I2C_DMA_TDLR 0x08C ++#define I2C_DMA_RDLR 0x090 ++#define I2C_LPIF_STATE 0x0A8 ++#define I2C_LOCK_REG 0x0AC ++#define I2C_AUTO_REG 0x0B0 ++#define I2C_TX_RX_REG 0x0B4 ++#define I2C_DMA_CMD0 0x0B8 ++#define I2C_DMA_CMD1 0x0BC ++#define I2C_DMA_CMD2 0x0C0 ++#define I2C_ENABLE_STATUS_REG 0x09C ++ ++#define HI_I2C_FAST_MODE 0x65 ++ ++#define HI_I2C_UNLOCK_VALUE 0x1ACCE551 ++ ++#define HI_I2C_ENABLE (1 << 0) ++ ++#define HI_I2C_AUTO_MODE_OFF 0x0f000000 ++ ++#define HI_I2C_WRITE 0x80000000 ++#define HI_I2C_READ 0xc0000000 ++ ++#define READ_OPERATION (1) ++#define WRITE_OPERATION 0xfe ++ ++#define CMD_I2C_WRITE 0x01 ++#define CMD_I2C_READ 0x03 ++ ++/* I2C_COM_REG */ ++#define I2C_SEND_ACK (~(1 << 4)) ++#define I2C_START (1 << 3) ++#define I2C_READ (1 << 2) ++#define I2C_WRITE (1 << 1) ++#define I2C_STOP (1 << 0) ++ ++/* I2C_ENABLE_REG */ ++#define I2C_ENABLE (1 << 0) ++ ++#define I2C_RAW_TX_ABORT (1 << 6) ++ ++/*I2C_INTR_STAT_REG */ ++#define I2C_AUTO_RX_FIFO_NOT_EMPTY (1 << 8) ++#define I2C_AUTO_TX_FIFO_EMPTRY (1 << 20) ++#define I2c_AUTO_TX_FIFO_NOT_FULL (1 << 21) ++#define I2C_TX_ABRT (1 << 23) ++#define I2C_AUTO_DATA (1 << 28) ++#define I2C_AUTO_ADDR (1 << 29) ++ ++/* I2C_STATUS */ ++#define I2C_STATUS_WORKING (1 << 0) ++ ++#define IS_TX_FIFO_EMPTY(status) (((status) &\ ++ I2C_AUTO_TX_FIFO_EMPTRY) == I2C_AUTO_TX_FIFO_EMPTRY) ++#define IS_RX_FIFO_EMPTY(status) (((status) &\ ++ I2C_AUTO_RX_FIFO_NOT_EMPTY) == 0) ++#define IS_FIFO_EMPTY(status) (IS_RX_FIFO_EMPTY(status) &&\ ++ IS_TX_FIFO_EMPTY(status)) ++#define IS_I2C_IDLE(status) (((status) & I2C_STATUS_WORKING) == 0) ++ ++#define REG_SHIFT 16 ++#define DATA_16BIT_MASK 0xFFFF ++#define DATA_8BIT_MASK 0xFFFF ++ ++#define REVERT_HL_BYTE(value) ((value >> 8) | ((value & 0xFF) << 8)) ++ ++/* ++ * I2C Interrupt related Macros ++ */ ++#define DEFAULT_I2C_REG_IMSC 0x0UL ++#define DISABLE_ALL_INTERRUPTS ((~DEFAULT_I2C_REG_IMSC) & 0xfff) ++#define ENABLE_ALL_INTERRUPTS DEFAULT_I2C_REG_IMSC ++ ++typedef enum i2c_mode_e { ++ I2C_MODE_AUTO, ++ I2C_MODE_DMA, ++ I2C_MODE_NONE, ++} i2c_mode_e; ++ ++struct hi_platform_i2c { ++ int clk_limit; ++ unsigned int i2c_class; ++ unsigned int clk_rate; ++}; ++ ++#endif +diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c +index 7484aac..ae05daf 100644 +--- a/drivers/i2c/i2c-core.c ++++ b/drivers/i2c/i2c-core.c +@@ -1098,8 +1098,13 @@ static int i2c_check_addr_validity(unsigned addr, unsigned short flags) + if (addr > 0x3ff) + return -EINVAL; + } else { ++ /* we always use dev+RD bit */ + /* 7-bit address, reject the general call address */ ++#ifdef CONFIG_I2C_HISI ++ if (addr == 0x00 || addr > 0xfe) ++#else + if (addr == 0x00 || addr > 0x7f) ++#endif + return -EINVAL; + } + return 0; +@@ -2574,10 +2579,8 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) + } else { + i2c_lock_bus(adap, I2C_LOCK_SEGMENT); + } +- + ret = __i2c_transfer(adap, msgs, num); + i2c_unlock_bus(adap, I2C_LOCK_SEGMENT); +- + return ret; + } else { + dev_dbg(&adap->dev, "I2C level transfers not supported\n"); +@@ -2601,7 +2604,11 @@ int i2c_master_send(const struct i2c_client *client, const char *buf, int count) + struct i2c_msg msg; + + msg.addr = client->addr; ++#ifdef CONFIG_I2C_HISI ++ msg.flags = client->flags; ++#else + msg.flags = client->flags & I2C_M_TEN; ++#endif + msg.len = count; + msg.buf = (char *)buf; + +@@ -2630,7 +2637,11 @@ int i2c_master_recv(const struct i2c_client *client, char *buf, int count) + int ret; + + msg.addr = client->addr; ++#ifdef CONFIG_I2C_HISI ++ msg.flags = client->flags; ++#else + msg.flags = client->flags & I2C_M_TEN; ++#endif + msg.flags |= I2C_M_RD; + msg.len = count; + msg.buf = buf; +diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c +index 6f638bb..d9cd820 100644 +--- a/drivers/i2c/i2c-dev.c ++++ b/drivers/i2c/i2c-dev.c +@@ -140,22 +140,74 @@ static ssize_t i2cdev_read(struct file *file, char __user *buf, size_t count, + { + char *tmp; + int ret; +- ++#ifdef CONFIG_I2C_HISI ++ unsigned reg_width; ++ unsigned data_width; ++#endif + struct i2c_client *client = file->private_data; + + if (count > 8192) + count = 8192; + ++#ifdef CONFIG_I2C_HISI ++ ++ if (client->flags & I2C_M_16BIT_REG) ++ reg_width = 2; ++ else ++ reg_width = 1; ++ ++ if (client->flags & I2C_M_16BIT_DATA) ++ data_width = 2; ++ else ++ data_width = 1; ++ ++ if (client->flags & I2C_M_DMA) ++ tmp = kmalloc(max_t(size_t, reg_width, count), ++ GFP_KERNEL); ++ else ++ tmp = kmalloc(max_t(size_t, reg_width, data_width), ++ GFP_KERNEL); ++ ++ if (tmp == NULL) ++ return -ENOMEM; ++ ++ if (copy_from_user(tmp, buf, reg_width)) ++ return -EFAULT; ++ ++#else + tmp = kmalloc(count, GFP_KERNEL); + if (tmp == NULL) + return -ENOMEM; ++#endif + + pr_debug("i2c-dev: i2c-%d reading %zu bytes.\n", + iminor(file_inode(file)), count); + ++#ifdef CONFIG_I2C_HISI ++ if (client->flags & I2C_M_DMA) ++ ret = i2c_master_recv(client, tmp, ++ max_t(size_t, reg_width, count)); ++ else ++ ret = i2c_master_recv(client, tmp, ++ max_t(size_t, reg_width, data_width)); ++#else + ret = i2c_master_recv(client, tmp, count); ++#endif ++#ifdef CONFIG_I2C_HISI ++ if (ret >= 0) { ++ if (client->flags & I2C_M_DMA) { ++ ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret; ++ } else { ++ if (client->flags & I2C_M_16BIT_DATA) ++ ret = copy_to_user(buf, tmp, 2) ? -EFAULT : ret; ++ else ++ ret = copy_to_user(buf, tmp, 1) ? -EFAULT : ret; ++ } ++ } ++#else + if (ret >= 0) + ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret; ++#endif + kfree(tmp); + return ret; + } +@@ -170,6 +222,9 @@ static ssize_t i2cdev_write(struct file *file, const char __user *buf, + if (count > 8192) + count = 8192; + ++ if (count == 0) ++ return -EINVAL; ++ + tmp = memdup_user(buf, count); + if (IS_ERR(tmp)) + return PTR_ERR(tmp); +@@ -274,6 +329,11 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, + break; + } + ++ if (rdwr_pa[i].len == 0) { ++ res = -EINVAL; ++ break; ++ } ++ + data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; + rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len); + if (IS_ERR(rdwr_pa[i].buf)) { +@@ -424,7 +484,11 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + case I2C_SLAVE: + case I2C_SLAVE_FORCE: + if ((arg > 0x3ff) || ++#ifdef CONFIG_I2C_HISI ++ (((client->flags & I2C_M_TEN) == 0) && arg > 0xfe)) ++#else + (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f)) ++#endif + return -EINVAL; + if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg)) + return -EBUSY; +@@ -450,6 +514,26 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + else + client->flags &= ~I2C_CLIENT_PEC; + return 0; ++#ifdef CONFIG_I2C_HISI ++ case I2C_16BIT_REG: ++ if (arg) ++ client->flags |= I2C_M_16BIT_REG; ++ else ++ client->flags &= ~I2C_M_16BIT_REG; ++ return 0; ++ case I2C_16BIT_DATA: ++ if (arg) ++ client->flags |= I2C_M_16BIT_DATA; ++ else ++ client->flags &= ~I2C_M_16BIT_DATA; ++ return 0; ++ case I2C_DMA: ++ if (arg) ++ client->flags |= I2C_M_DMA; ++ else ++ client->flags &= ~I2C_M_DMA; ++ return 0; ++#endif + case I2C_FUNCS: + funcs = i2c_get_functionality(client->adapter); + return put_user(funcs, (unsigned long __user *)arg); +diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c +index d6c404b..5963307 100644 +--- a/drivers/irqchip/irq-gic.c ++++ b/drivers/irqchip/irq-gic.c +@@ -1148,8 +1148,28 @@ static int gic_init_bases(struct gic_chip_data *gic, int irq_start, + ret = -ENODEV; + goto error; + } +- ++#ifndef CONFIG_ARCH_HISI_BVT_AMP + gic_dist_init(gic); ++#else ++ { ++ /* 0x47444946('G''D''I''F') is abbreviation of GIC_DIST_INIT_FLAG. */ ++ /* If the soc(such as hi3559/hi3556/hi3556av100/hi3559av100 ...) runs 2 OS, another */ ++ /* OS distributes the IRQ. When another OS has distributed the IRQ,*/ ++ /* sysctrl register(the offset address is 0x130) will be set to 0x47444946.*/ ++ /* If another OS did not distribute the IRQ, this OS will do it. */ ++#define GIC_DIST_INIT_FLAG 0x47444946 ++#define GIC_DIST_INIT_FLAG_OFFSET 0x0130 ++ struct device_node *np; ++ int gic_dist_init_flag; ++ ++ np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl"); ++ gic_dist_init_flag = readl(of_iomap(np, 0) + GIC_DIST_INIT_FLAG_OFFSET); ++ ++ if(gic_dist_init_flag != GIC_DIST_INIT_FLAG) { ++ gic_dist_init(gic); ++ } ++ } ++#endif + ret = gic_cpu_init(gic); + if (ret) + goto error; +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index c6df644..327bb5b 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -358,6 +358,17 @@ config MFD_HI655X_PMIC + help + Select this option to enable Hisilicon hi655x series pmic driver. + ++config MFD_HISI_FMC ++ tristate "HiSilicon Flash Memory Controller" ++ depends on OF ++ depends on ARCH_HISI_BVT ++ select MFD_CORE ++ select REGMAP_MMIO ++ help ++ Select this option to enable the HiSilicon Flash Memory ++ Controller(FMC) driver. ++ ++ + config HTC_PASIC3 + tristate "HTC PASIC3 LED/DS1WM chip support" + select MFD_CORE +diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile +index 9834e66..9c6d6ea 100644 +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -180,6 +180,7 @@ obj-$(CONFIG_MFD_TPS65090) += tps65090.o + obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o + obj-$(CONFIG_MFD_ATMEL_FLEXCOM) += atmel-flexcom.o + obj-$(CONFIG_MFD_ATMEL_HLCDC) += atmel-hlcdc.o ++obj-$(CONFIG_MFD_HISI_FMC) += hisi_fmc.o + obj-$(CONFIG_MFD_INTEL_LPSS) += intel-lpss.o + obj-$(CONFIG_MFD_INTEL_LPSS_PCI) += intel-lpss-pci.o + obj-$(CONFIG_MFD_INTEL_LPSS_ACPI) += intel-lpss-acpi.o +diff --git a/drivers/mfd/hisi_fmc.c b/drivers/mfd/hisi_fmc.c +new file mode 100644 +index 0000000..764776e +--- /dev/null ++++ b/drivers/mfd/hisi_fmc.c +@@ -0,0 +1,128 @@ ++/* HiSilicon Flash Memory Controller Driver ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++unsigned char hifmc_cs_user[HIFMC_MAX_CHIP_NUM]; ++ ++DEFINE_MUTEX(fmc_switch_mutex); ++EXPORT_SYMBOL_GPL(fmc_switch_mutex); ++ ++/* ------------------------------------------------------------------------ */ ++static const struct mfd_cell hisi_fmc_devs[] = { ++ { ++ .name = "hisi_spi_nor", ++ .of_compatible = "hisilicon,fmc-spi-nor", ++ }, ++ { ++ .name = "hisi_spi_nand", ++ .of_compatible = "hisilicon,fmc-spi-nand", ++ }, ++ { ++ .name = "hisi_nand", ++ .of_compatible = "hisilicon,fmc-nand", ++ }, ++}; ++ ++static int hisi_fmc_probe(struct platform_device *pdev) ++{ ++ struct hisi_fmc *fmc; ++ struct resource *res; ++ int ret; ++ ++ fmc = devm_kzalloc(&pdev->dev, sizeof(*fmc), GFP_KERNEL); ++ if (!fmc) ++ return -ENOMEM; ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control"); ++ fmc->regbase = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(fmc->regbase)) ++ return PTR_ERR(fmc->regbase); ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory"); ++ fmc->iobase = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(fmc->iobase)) ++ return PTR_ERR(fmc->iobase); ++ ++ fmc->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(fmc->clk)) ++ return PTR_ERR(fmc->clk); ++ ++ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); ++ if (ret) { ++ dev_warn(&pdev->dev, "Unable to set dma mask\n"); ++ return ret; ++ } ++ ++ fmc->buffer = dmam_alloc_coherent(&pdev->dev, HIFMC_DMA_MAX_LEN, ++ &fmc->dma_buffer, GFP_KERNEL); ++ if (IS_ERR(fmc->buffer)) ++ return PTR_ERR(fmc->buffer); ++ ++ mutex_init(&fmc->lock); ++ ++ platform_set_drvdata(pdev, fmc); ++ ++ ret = mfd_add_devices(&pdev->dev, 0, hisi_fmc_devs, ++ ARRAY_SIZE(hisi_fmc_devs), NULL, 0, NULL); ++ if (ret) { ++ dev_err(&pdev->dev, "add mfd devices failed: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int hisi_fmc_remove(struct platform_device *pdev) ++{ ++ struct hisi_fmc *fmc = platform_get_drvdata(pdev); ++ ++ dmam_free_coherent(&pdev->dev, HIFMC_DMA_MAX_LEN, ++ fmc->buffer, fmc->dma_buffer); ++ mfd_remove_devices(&pdev->dev); ++ mutex_destroy(&fmc->lock); ++ ++ return 0; ++} ++ ++static const struct of_device_id hisi_fmc_of_match_tbl[] = { ++ { .compatible = "hisilicon,hisi-fmc"}, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, hisi_fmc_of_match_tbl); ++ ++static struct platform_driver hisi_fmc_driver = { ++ .driver = { ++ .name = "hifmc", ++ .of_match_table = hisi_fmc_of_match_tbl, ++ }, ++ .probe = hisi_fmc_probe, ++ .remove = hisi_fmc_remove, ++}; ++module_platform_driver(hisi_fmc_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("HiSilicon Flash Memory Controller Driver"); +diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c +index f57700c..0bff200 100644 +--- a/drivers/mmc/core/mmc.c ++++ b/drivers/mmc/core/mmc.c +@@ -1318,6 +1318,9 @@ static int mmc_select_hs400es(struct mmc_card *card) + + /* Set host controller to HS400 timing and frequency */ + mmc_set_timing(host, MMC_TIMING_MMC_HS400); ++#ifdef CONFIG_MMC_SDHCI_HISI ++ mmc_set_bus_speed(card); ++#endif + + /* Controller enable enhanced strobe function */ + host->ios.enhanced_strobe = true; +@@ -1690,7 +1693,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, + err = mmc_select_hs400(card); + if (err) + goto free_card; +- } else { ++ } else if (!mmc_card_hs400es(card)) { + /* Select the desired bus width optionally */ + err = mmc_select_bus_width(card); + if (err > 0 && mmc_card_hs(card)) { +diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c +index bd44ba8..61ef3ea 100644 +--- a/drivers/mmc/core/sdio.c ++++ b/drivers/mmc/core/sdio.c +@@ -28,6 +28,10 @@ + #include "sdio_ops.h" + #include "sdio_cis.h" + ++#ifdef CONFIG_ARCH_HISI_BVT ++#include "host.h" ++#endif ++ + static int sdio_read_fbr(struct sdio_func *func) + { + int ret; +@@ -1173,3 +1177,40 @@ int mmc_attach_sdio(struct mmc_host *host) + return err; + } + ++#ifdef CONFIG_ARCH_HISI_BVT ++/* sdio_reset_comm has been fixed in latest kernel/msm.git for Linux ++ * 2.6.27. The implementation prior to that buggy, and needs broadcom's ++ * patch for it*/ ++int sdio_reset_comm(struct mmc_card *card) ++{ ++ struct mmc_host *host = card->host; ++ u32 ocr; ++ u32 rocr; ++ int err; ++ ++ mmc_claim_host(host); ++ mmc_retune_disable(host); ++ mmc_go_idle(host); ++ mmc_set_clock(host, host->f_min); ++ err = mmc_send_io_op_cond(host, 0, &ocr); ++ if (err) ++ goto err; ++ rocr = mmc_select_voltage(host, ocr); ++ if (!rocr) { ++ err = -EINVAL; ++ goto err; ++ } ++ err = mmc_sdio_init_card(host, rocr, card, 0); ++ if (err) ++ goto err; ++ mmc_release_host(host); ++ return 0; ++err: ++ printk("%s: Error resetting SDIO communications (%d)\n", ++ mmc_hostname(host), err); ++ mmc_release_host(host); ++ return err; ++} ++EXPORT_SYMBOL(sdio_reset_comm); ++#endif ++ +diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig +index 5274f50..ce3a274 100644 +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -176,6 +176,17 @@ config MMC_SDHCI_CNS3XXX + + If unsure, say N. + ++config MMC_SDHCI_HISI ++ tristate "SDHCI support on the Hisilicon Hi35xx SoC" ++ depends on ARCH_HI3559AV100 ++ depends on MMC_SDHCI_PLTFM ++ help ++ This selects the SDHCI support for Hi35xx System-on-Chip devices. ++ ++ If you have a controller with this interface, say Y or M here. ++ ++ If unsure, say N. ++ + config MMC_SDHCI_ESDHC_IMX + tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller" + depends on ARCH_MXC +@@ -798,3 +809,5 @@ config MMC_SDHCI_BRCMSTB + Broadcom STB SoCs. + + If unsure, say Y. ++ ++source "drivers/mmc/host/himci/Kconfig" +diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile +index e2bdaaf..4112382 100644 +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -70,6 +70,8 @@ obj-$(CONFIG_MMC_SDHCI_OF_ARASAN) += sdhci-of-arasan.o + obj-$(CONFIG_MMC_SDHCI_OF_AT91) += sdhci-of-at91.o + obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o + obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o ++obj-$(CONFIG_MMC_SDHCI_HISI) += sdhci-of-hisi.o ++sdhci-of-hisi-objs := sdhci-hisi.o mci_proc.o + obj-$(CONFIG_MMC_SDHCI_BCM_KONA) += sdhci-bcm-kona.o + obj-$(CONFIG_MMC_SDHCI_IPROC) += sdhci-iproc.o + obj-$(CONFIG_MMC_SDHCI_MSM) += sdhci-msm.o +@@ -80,3 +82,5 @@ obj-$(CONFIG_MMC_SDHCI_BRCMSTB) += sdhci-brcmstb.o + ifeq ($(CONFIG_CB710_DEBUG),y) + CFLAGS-cb710-mmc += -DDEBUG + endif ++ ++obj-$(CONFIG_HIMCI) += himci/ +diff --git a/drivers/mmc/host/himci/Kconfig b/drivers/mmc/host/himci/Kconfig +new file mode 100644 +index 0000000..4b7e3b1 +--- /dev/null ++++ b/drivers/mmc/host/himci/Kconfig +@@ -0,0 +1,23 @@ ++# ++# himci family SD/MMC device configuration ++# ++menuconfig HIMCI ++ tristate "himciv100 driver support" ++ depends on (ARCH_HI3516A || ARCH_HI3518EV20X) ++ default y ++ select MMC_UNSAFE_RESUME ++ select MMC_EMBEDDED_SDIO ++ select MMC_BLOCK ++ select MMC_BLOCK_BOUNCE ++ help ++ This selects the Hisilicon Synopsys MultiMedia Card Driver ++ support. If you want use SD/MMC/SDIO driver, ++ Say Y or M here. ++ ++ default is Y. ++ ++config SEND_AUTO_STOP ++ bool "Send Auto Stop to terminate data transfer between host and SD card" ++ depends on (ARCH_HI3516A || ARCH_HI3518EV20X) && HIMCI ++ default y ++ +diff --git a/drivers/mmc/host/himci/Makefile b/drivers/mmc/host/himci/Makefile +new file mode 100644 +index 0000000..6858bfce +--- /dev/null ++++ b/drivers/mmc/host/himci/Makefile +@@ -0,0 +1,2 @@ ++obj-$(CONFIG_HIMCI) += hisi_mci.o ++hisi_mci-y := himci.o himci_proc.o +diff --git a/drivers/mmc/host/himci/himci.c b/drivers/mmc/host/himci/himci.c +new file mode 100644 +index 0000000..54d0ab2 +--- /dev/null ++++ b/drivers/mmc/host/himci/himci.c +@@ -0,0 +1,1754 @@ ++/* ++ * himci.c - hisilicon MMC Host 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. ++ */ ++#define pr_fmt(fmt) "himci: " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "himci_reg.h" ++#include "himci.h" ++#include "himci_proc.h" ++ ++#ifdef CONFIG_ARCH_HI3516A ++#include "himci_hi3516a.c" ++#endif ++ ++#ifdef CONFIG_ARCH_HI3518EV20X ++#include "himci_hi3518ev20x.c" ++#endif ++ ++#define DRIVER_NAME "himci" ++#define CMD_DES_PAGE_SIZE (2 * PAGE_SIZE) ++ ++static unsigned int detect_time = HI_MCI_DETECT_TIMEOUT; ++static unsigned int retry_count = MAX_RETRY_COUNT; ++static unsigned int request_timeout = HI_MCI_REQUEST_TIMEOUT; ++int trace_level = HIMCI_TRACE_LEVEL; ++unsigned int slot_index = 0; ++struct himci_host *mci_host[HIMCI_SLOT_NUM] = {NULL}; ++ ++#ifdef MODULE ++ ++module_param(detect_time, uint, 0600); ++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, "HIMCI_TRACE_LEVEL"); ++ ++#endif ++ ++/* reset MMC host controller */ ++static void himci_sys_reset(struct himci_host *host) ++{ ++ unsigned int reg_value; ++ unsigned long flags; ++ ++ himci_trace(2, "reset"); ++ ++ local_irq_save(flags); ++ ++ reg_value = himci_readl(host->base + MCI_BMOD); ++ reg_value |= BMOD_SWR; ++ himci_writel(reg_value, host->base + MCI_BMOD); ++ mdelay(10); ++ ++ reg_value = himci_readl(host->base + MCI_BMOD); ++ reg_value |= BURST_16 | BURST_INCR; ++ himci_writel(reg_value, host->base + MCI_BMOD); ++ ++ reg_value = himci_readl(host->base + MCI_CTRL); ++ reg_value |= CTRL_RESET | FIFO_RESET | DMA_RESET; ++ himci_writel(reg_value, host->base + MCI_CTRL); ++ ++ local_irq_restore(flags); ++} ++ ++static void himci_ctrl_power(struct himci_host *host, ++ unsigned int flag, unsigned int force) ++{ ++ unsigned int port; ++ ++ himci_trace(2, "begin"); ++ ++ port = host->port; ++ ++ if (host->power_status != flag || force == FORCE_ENABLE) { ++ unsigned int reg_value; ++ ++ if (flag == POWER_OFF) { ++ reg_value = himci_readl(host->base + MCI_RESET_N); ++ reg_value &= ~(MMC_RST_N << port); ++ himci_writel(reg_value, host->base + MCI_RESET_N); ++ } ++ ++ reg_value = himci_readl(host->base + MCI_PWREN); ++ if (flag == POWER_OFF) ++ reg_value &= ~(0x1 << port); ++ else ++ reg_value |= (0x1 << port); ++ ++ himci_writel(reg_value, host->base + MCI_PWREN); ++ ++ if (flag == POWER_ON) { ++ reg_value = himci_readl(host->base + MCI_RESET_N); ++ reg_value |= (MMC_RST_N << port); ++ himci_writel(reg_value, host->base + MCI_RESET_N); ++ } ++ ++ if (in_interrupt()) ++ mdelay(100); ++ else ++ msleep(100); ++ ++ host->power_status = flag; ++ } ++} ++ ++/********************************************** ++ *1: card off ++ *0: card on ++ ***********************************************/ ++static unsigned int himci_sys_card_detect(struct himci_host *host) ++{ ++ unsigned int card_status; ++ ++ card_status = readl(host->base + MCI_CDETECT); ++ card_status &= (HIMCI_CARD0 << host->port); ++ if (card_status) ++ card_status = 1; ++ else ++ card_status = 0; ++ ++ return card_status; ++} ++ ++/********************************************** ++ *1: card readonly ++ *0: card read/write ++ ***********************************************/ ++static unsigned int himci_ctrl_card_readonly(struct himci_host *host) ++{ ++ unsigned int card_value = himci_readl(host->base + MCI_WRTPRT); ++ return card_value & (HIMCI_CARD0 << host->port); ++} ++ ++static int himci_wait_cmd(struct himci_host *host) ++{ ++ int wait_retry_count = 0; ++ unsigned int reg_data = 0; ++ unsigned long flags; ++ ++ himci_trace(2, "begin"); ++ himci_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 = himci_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 = himci_readl(host->base + MCI_RINTSTS); ++ if (reg_data & HLE_INT_STATUS) { ++ reg_data |= HLE_INT_STATUS; ++ himci_writel(reg_data, host->base + MCI_RINTSTS); ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ himci_trace(5, "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) { ++ himci_trace(5, "send cmd is timeout!"); ++ return -1; ++ } ++ } ++} ++ ++static void himci_control_cclk(struct himci_host *host, unsigned int flag) ++{ ++ unsigned int reg; ++ union cmd_arg_u cmd_reg; ++ ++ himci_trace(2, "begin"); ++ himci_assert(host); ++ ++ reg = himci_readl(host->base + MCI_CLKENA); ++ if (flag == ENABLE) { ++ reg |= (CCLK_ENABLE << host->port); ++ reg |= (CCLK_LOW_POWER << host->port); ++ } else { ++ reg &= ~(CCLK_ENABLE << host->port); ++ reg &= ~(CCLK_LOW_POWER << host->port); ++ } ++ himci_writel(reg, host->base + MCI_CLKENA); ++ ++ cmd_reg.cmd_arg = himci_readl(host->base + MCI_CMD); ++ cmd_reg.bits.start_cmd = 1; ++ cmd_reg.bits.card_number = host->port; ++ cmd_reg.bits.cmd_index = 0; ++ cmd_reg.bits.data_transfer_expected = 0; ++ cmd_reg.bits.update_clk_reg_only = 1; ++ cmd_reg.bits.response_expect = 0; ++ cmd_reg.bits.send_auto_stop = 0; ++ cmd_reg.bits.wait_prvdata_complete = 0; ++ cmd_reg.bits.check_response_crc = 0; ++ himci_writel(cmd_reg.cmd_arg, host->base + MCI_CMD); ++ if (himci_wait_cmd(host) != 0) ++ himci_trace(5, "disable or enable clk is timeout!"); ++} ++ ++static void himci_set_cclk(struct himci_host *host, unsigned int cclk) ++{ ++ unsigned int reg_value; ++ union cmd_arg_u clk_cmd; ++ unsigned int hclk; ++ ++ himci_trace(2, "begin"); ++ himci_assert(host); ++ himci_assert(cclk); ++ ++ hclk = cclk > MMC_CRG_MIN ? cclk : MMC_CRG_MIN; ++ clk_set_rate(host->clk, hclk); ++ ++ hclk = clk_get_rate(host->clk); ++ ++ /* ++ * set card clk divider value, ++ * clk_divider = Fmmcclk/(Fmmc_cclk * 2) ++ */ ++ reg_value = hclk / (cclk * 2); ++ if ((hclk % (cclk * 2)) && (hclk > cclk)) ++ reg_value++; ++ if (reg_value > 0xFF) ++ reg_value = 0xFF; ++ ++ host->hclk = hclk; ++ host->cclk = reg_value ? (hclk / (reg_value * 2)) : hclk; ++ himci_writel((reg_value << (host->port * 8)), ++ host->base + MCI_CLKDIV); ++ ++ clk_cmd.cmd_arg = himci_readl(host->base + MCI_CMD); ++ clk_cmd.bits.start_cmd = 1; ++ clk_cmd.bits.card_number = host->port; ++ clk_cmd.bits.update_clk_reg_only = 1; ++ clk_cmd.bits.cmd_index = 0; ++ clk_cmd.bits.data_transfer_expected = 0; ++ clk_cmd.bits.response_expect = 0; ++ himci_writel(clk_cmd.cmd_arg, host->base + MCI_CMD); ++ if (himci_wait_cmd(host) != 0) ++ himci_trace(5, "set card clk divider is failed!"); ++} ++ ++static void himci_init_host(struct himci_host *host) ++{ ++ unsigned int tmp_reg = 0; ++ unsigned long flags; ++ ++ himci_trace(2, "begin"); ++ himci_assert(host); ++ ++ himci_sys_reset(host); ++ ++#ifdef CONFIG_ARCH_HI3518EV20X ++ /* sd use clk0 emmc use clk1 */ ++ himci_writel(0x4, host->base + MCI_CLKSRC); ++#endif ++ ++ /* set drv/smpl phase shift */ ++ tmp_reg |= SMPL_PHASE_DFLT | DRV_PHASE_DFLT; ++ himci_writel(tmp_reg, host->base + MCI_UHS_REG_EXT); ++ ++ /* set card read threshold */ ++ himci_writel(RW_THRESHOLD_SIZE, host->base + MCI_CARDTHRCTL); ++ ++ /* clear MMC host intr */ ++ himci_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 all host intr */ ++ tmp_reg = himci_readl(host->base + MCI_INTMASK); ++ tmp_reg &= ~ALL_INT_MASK; ++ tmp_reg |= DATA_INT_MASK; ++ himci_writel(tmp_reg, host->base + MCI_INTMASK); ++ ++ /* enable inner DMA mode and close intr of MMC host controler */ ++ tmp_reg = himci_readl(host->base + MCI_CTRL); ++ tmp_reg &= ~INTR_EN; ++ tmp_reg |= USE_INTERNAL_DMA | INTR_EN; ++ himci_writel(tmp_reg, host->base + MCI_CTRL); ++ ++ /* set timeout param */ ++ himci_writel(DATA_TIMEOUT | RESPONSE_TIMEOUT, host->base + MCI_TIMEOUT); ++ ++ /* set FIFO param */ ++ tmp_reg = 0; ++ tmp_reg |= BURST_SIZE | RX_WMARK | TX_WMARK; ++ himci_writel(tmp_reg, host->base + MCI_FIFOTH); ++} ++ ++static void himci_detect_card(unsigned long arg) ++{ ++ struct himci_host *host = (struct himci_host *)arg; ++ unsigned int i, curr_status, status[5], detect_retry_count = 0; ++ ++ himci_assert(host); ++ ++ while (1) { ++ for (i = 0; i < 5; i++) { ++ status[i] = himci_sys_card_detect(host); ++ udelay(10); ++ } ++ if ((status[0] == status[1]) ++ && (status[0] == status[2]) ++ && (status[0] == status[3]) ++ && (status[0] == status[4])) ++ break; ++ ++ detect_retry_count++; ++ if (detect_retry_count >= retry_count) { ++ himci_error("this is a dithering, card detect error!"); ++ goto err; ++ } ++ } ++ curr_status = status[0]; ++ if (curr_status != host->card_status) { ++ himci_trace(2, "begin card_status = %d\n", host->card_status); ++ host->card_status = curr_status; ++ if (curr_status != CARD_UNPLUGED) { ++ himci_init_host(host); ++ pr_info("card connected!\n"); ++ } else { ++ pr_info("card disconnected!\n"); ++ } ++ ++ mmc_detect_change(host->mmc, 0); ++ } ++err: ++ mod_timer(&host->timer, jiffies + detect_time); ++} ++ ++static void himci_idma_start(struct himci_host *host) ++{ ++ unsigned int tmp; ++ ++ himci_trace(2, "begin"); ++ himci_writel(host->dma_paddr, host->base + MCI_DBADDR); ++ tmp = himci_readl(host->base + MCI_BMOD); ++ tmp |= BMOD_DMA_EN; ++ himci_writel(tmp, host->base + MCI_BMOD); ++} ++ ++static void himci_idma_stop(struct himci_host *host) ++{ ++ unsigned int tmp_reg; ++ ++ himci_trace(2, "begin"); ++ tmp_reg = himci_readl(host->base + MCI_BMOD); ++ tmp_reg &= ~BMOD_DMA_EN; ++ himci_writel(tmp_reg, host->base + MCI_BMOD); ++} ++ ++static int himci_setup_data(struct himci_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 himci_des *des; ++ ++ himci_trace(2, "begin"); ++ himci_assert(host); ++ himci_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); ++ himci_assert(host->dma_sg_num); ++ himci_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)) { ++ himci_error("mci request data_size is too big!\n"); ++ ret = -1; ++ goto out; ++ } ++ ++ himci_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 = (CMD_DES_PAGE_SIZE/sizeof(struct himci_des)); ++ des = (struct himci_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]); ++ himci_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 himci_des); ++ ++ /* buffer size <= 4k */ ++ if (sg_length >= 0x1000) { ++ des[des_cnt].idmac_des_buf_size = 0x1000; ++ sg_length -= 0x1000; ++ sg_phyaddr += 0x1000; ++ } else { ++ /* data alignment */ ++ des[des_cnt].idmac_des_buf_size = sg_length; ++ sg_length = 0; ++ } ++ ++ himci_trace(2, "des[%d] vaddr is 0x%08X", i, ++ (unsigned int)&des[i]); ++ himci_trace(2, "des[%d].idmac_des_ctrl is 0x%08X", ++ i, (unsigned int)des[i].idmac_des_ctrl); ++ himci_trace(2, "des[%d].idmac_des_buf_size is 0x%08X", ++ i, (unsigned int)des[i].idmac_des_buf_size); ++ himci_trace(2, "des[%d].idmac_des_buf_addr 0x%08X", ++ i, (unsigned int)des[i].idmac_des_buf_addr); ++ himci_trace(2, "des[%d].idmac_des_next_addr is 0x%08X", ++ i, (unsigned int)des[i].idmac_des_next_addr); ++ des_cnt++; ++ } ++ ++ himci_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 himci_exec_cmd(struct himci_host *host, ++ struct mmc_command *cmd, struct mmc_data *data) ++{ ++ volatile union cmd_arg_u cmd_regs; ++ ++ himci_trace(2, "begin"); ++ himci_assert(host); ++ himci_assert(cmd); ++ ++ host->cmd = cmd; ++ ++ himci_writel(cmd->arg, host->base + MCI_CMDARG); ++ himci_trace(4, "arg_reg 0x%x, val 0x%x", MCI_CMDARG, cmd->arg); ++ cmd_regs.cmd_arg = himci_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_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->opcode == MMC_STOP_TRANSMISSION) { ++ 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: ++ case MMC_RSP_R1 & (~MMC_RSP_CRC): ++ cmd_regs.bits.response_expect = 1; ++ cmd_regs.bits.response_length = 0; ++ cmd_regs.bits.check_response_crc = 0; ++ break; ++ default: ++ host->cmd->error = -EINVAL; ++ himci_error("himci: unhandled response type %02x\n", ++ mmc_resp_type(cmd)); ++ return -EINVAL; ++ } ++ ++ himci_trace(3, "cmd->opcode = %d cmd->arg = 0x%X\n", ++ cmd->opcode, cmd->arg); ++ 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 = host->port; ++ cmd_regs.bits.cmd_index = cmd->opcode; ++ cmd_regs.bits.start_cmd = 1; ++ cmd_regs.bits.update_clk_reg_only = 0; ++ ++ himci_writel(DATA_INT_MASK, host->base + MCI_RINTSTS); ++ himci_writel(cmd_regs.cmd_arg, host->base + MCI_CMD); ++ himci_trace(4, "cmd_reg 0x%x, val 0x%x\n", MCI_CMD, cmd_regs.cmd_arg); ++ ++ if (himci_wait_cmd(host) != 0) { ++ himci_trace(3, "send card cmd is failed!"); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static void himci_finish_request(struct himci_host *host, ++ struct mmc_request *mrq) ++{ ++ himci_trace(2, "begin"); ++ himci_assert(host); ++ himci_assert(mrq); ++ ++ host->mrq = NULL; ++ host->cmd = NULL; ++ host->data = NULL; ++ mmc_request_done(host->mmc, mrq); ++} ++ ++static void himci_cmd_done(struct himci_host *host, unsigned int stat) ++{ ++ unsigned int i; ++ struct mmc_command *cmd = host->cmd; ++ ++ himci_trace(2, "begin"); ++ himci_assert(host); ++ himci_assert(cmd); ++ ++ for (i = 0; i < 4; i++) { ++ if (mmc_resp_type(cmd) == MMC_RSP_R2) { ++ cmd->resp[i] = himci_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] = himci_readl(host->base + ++ MCI_RESP0 + i * 0x4); ++ } ++ ++ if (stat & RTO_INT_STATUS) { ++ cmd->error = -ETIMEDOUT; ++ himci_trace(3, "irq cmd status stat = 0x%x is timeout error!", ++ stat); ++ } else if (stat & (RCRC_INT_STATUS | RE_INT_STATUS)) { ++ cmd->error = -EILSEQ; ++ himci_trace(3, "irq cmd status stat = 0x%x is response error!", ++ stat); ++ } ++ ++ host->cmd = NULL; ++} ++ ++static void himci_data_done(struct himci_host *host, unsigned int stat) ++{ ++ struct mmc_data *data = host->data; ++ ++ himci_trace(2, "begin"); ++ himci_assert(host); ++ himci_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; ++ himci_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)) { ++ data->error = -EILSEQ; ++ himci_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 himci_wait_cmd_complete(struct himci_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; ++ ++ himci_trace(2, "begin"); ++ himci_assert(host); ++ himci_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) { ++ himci_writel((CD_INT_STATUS | RTO_INT_STATUS ++ | RCRC_INT_STATUS | RE_INT_STATUS), ++ host->base + MCI_RINTSTS); ++ spin_unlock_irqrestore(&host->lock, flags); ++ himci_cmd_done(host, cmd_irq_reg); ++ return 0; ++ } else if (cmd_irq_reg & VOLT_SWITCH_INT_STATUS) { ++ himci_writel(VOLT_SWITCH_INT_STATUS, ++ host->base + MCI_RINTSTS); ++ spin_unlock_irqrestore(&host->lock, flags); ++ himci_cmd_done(host, cmd_irq_reg); ++ 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) { ++ cmd->error = -ETIMEDOUT; ++ return -1; ++ } ++ ++ if (!time_before(jiffies, cmd_jiffies_timeout)) { ++ unsigned int i = 0; ++ for (i = 0; i < 4; i++) { ++ cmd->resp[i] = himci_readl(host->base ++ + MCI_RESP0 + i * 0x4); ++ pr_err("voltage switch read MCI_RESP"); ++ pr_err("%d : 0x%x\n", i, cmd->resp[i]); ++ } ++ cmd->error = -ETIMEDOUT; ++ himci_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 himci_wait_auto_stop_complete(struct himci_host *host) ++{ ++ unsigned int cmd_retry_count = 0; ++ unsigned long cmd_jiffies_timeout; ++ unsigned int cmd_irq_reg = 0; ++ unsigned long flags; ++ ++ himci_trace(2, "begin"); ++ himci_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) { ++ himci_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)) { ++ himci_trace(3, "wait auto stop complete is timeout!"); ++ return -1; ++ } ++ ++ schedule(); ++ } ++ ++} ++#endif ++ ++static int himci_wait_data_complete(struct himci_host *host) ++{ ++ unsigned int tmp_reg; ++ struct mmc_data *data = host->data; ++ long time = request_timeout; ++ unsigned long flags; ++ ++ himci_trace(2, "begin"); ++ himci_assert(host); ++ himci_assert(data); ++ ++ time = wait_event_timeout(host->intr_wait, ++ test_bit(HIMCI_PEND_DTO_B, ++ &host->pending_events), time); ++ ++ /* Mask MMC host data intr */ ++ spin_lock_irqsave(&host->lock, flags); ++ tmp_reg = himci_readl(host->base + MCI_INTMASK); ++ tmp_reg &= ~DATA_INT_MASK; ++ himci_writel(tmp_reg, host->base + MCI_INTMASK); ++ host->pending_events &= ~HIMCI_PEND_DTO_M; ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ if (((time <= 0) ++ && (!test_bit(HIMCI_PEND_DTO_B, &host->pending_events))) ++ || (host->card_status == CARD_UNPLUGED)) { ++ ++ data->error = -ETIMEDOUT; ++ himci_trace(5, "wait data request complete is timeout! 0x%08X", ++ host->irq_status); ++ himci_idma_stop(host); ++ himci_data_done(host, host->irq_status); ++ return -1; ++ } ++ ++ himci_idma_stop(host); ++ himci_data_done(host, host->irq_status); ++ return 0; ++} ++ ++static int himci_wait_card_complete(struct himci_host *host, ++ struct mmc_data *data) ++{ ++ unsigned int card_retry_count = 0; ++ unsigned long card_jiffies_timeout; ++ unsigned int card_status_reg = 0; ++ ++ himci_trace(2, "begin"); ++ himci_assert(host); ++ ++ card_jiffies_timeout = jiffies + request_timeout; ++ while (1) { ++ do { ++ card_status_reg = readl(host->base + MCI_STATUS); ++ if (!(card_status_reg & DATA_BUSY)) { ++ himci_trace(2, "end"); ++ return 0; ++ } ++ card_retry_count++; ++ } while (card_retry_count < retry_count); ++ ++ card_retry_count = 0; ++ ++ if (host->card_status == CARD_UNPLUGED) { ++ host->mrq->cmd->error = -ETIMEDOUT; ++ himci_trace(3, "card is unpluged!"); ++ return -1; ++ } ++ ++ if (!time_before(jiffies, card_jiffies_timeout)) { ++ host->mrq->cmd->error = -ETIMEDOUT; ++ himci_trace(3, "wait card ready complete is timeout!"); ++ return -1; ++ } ++ ++ schedule(); ++ } ++} ++ ++static void himci_request(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct himci_host *host = mmc_priv(mmc); ++ int byte_cnt = 0, fifo_count = 0, ret = 0, tmp_reg; ++ unsigned long flags; ++ ++ himci_trace(2, "begin"); ++ himci_assert(mmc); ++ himci_assert(mrq); ++ himci_assert(host); ++ ++ host->mrq = mrq; ++ host->irq_status = 0; ++ ++ if (host->card_status == CARD_UNPLUGED) { ++ mrq->cmd->error = -ENODEV; ++ goto request_end; ++ } ++ ++ ret = himci_wait_card_complete(host, mrq->data); ++ if (ret) { ++ mrq->cmd->error = ret; ++ goto request_end; ++ } ++ ++ /* prepare data */ ++ if (mrq->data) { ++ ret = himci_setup_data(host, mrq->data); ++ if (ret) { ++ mrq->data->error = ret; ++ himci_trace(3, "data setup is error!"); ++ goto request_end; ++ } ++ ++ byte_cnt = mrq->data->blksz * mrq->data->blocks; ++ himci_writel(byte_cnt, host->base + MCI_BYTCNT); ++ himci_writel(mrq->data->blksz, host->base + MCI_BLKSIZ); ++ ++ /* reset fifo */ ++ tmp_reg = himci_readl(host->base + MCI_CTRL); ++ tmp_reg |= FIFO_RESET; ++ himci_writel(tmp_reg, host->base + MCI_CTRL); ++ ++ do { ++ tmp_reg = himci_readl(host->base + MCI_CTRL); ++ fifo_count++; ++ if (fifo_count >= retry_count) { ++ pr_info("fifo reset is timeout!"); ++ return; ++ } ++ } while (tmp_reg & FIFO_RESET); ++ ++ /* start DMA */ ++ himci_idma_start(host); ++ } else { ++ himci_writel(0, host->base + MCI_BYTCNT); ++ himci_writel(0, host->base + MCI_BLKSIZ); ++ } ++ ++ /* send command */ ++ ret = himci_exec_cmd(host, mrq->cmd, mrq->data); ++ if (ret) { ++ mrq->cmd->error = ret; ++ himci_idma_stop(host); ++ himci_trace(3, "can't send card cmd! ret = %d", ret); ++ goto request_end; ++ } ++ ++ /* wait command send complete */ ++ himci_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 = himci_readl(host->base + MCI_INTMASK); ++ tmp_reg |= DATA_INT_MASK; ++ himci_writel(tmp_reg, host->base + MCI_INTMASK); ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ /* wait data transfer complete */ ++ himci_wait_data_complete(host); ++ } else { ++ /* CMD error in data command */ ++ himci_idma_stop(host); ++ } ++ ++ if (mrq->stop) { ++#ifdef CONFIG_SEND_AUTO_STOP ++ int trans_cnt; ++ ++ trans_cnt = himci_readl(host->base + MCI_TCBCNT); ++ /* send auto stop */ ++ if ((trans_cnt == byte_cnt) && (!(host->is_tuning))) { ++ himci_trace(3, "byte_cnt = %d, trans_cnt = %d", ++ byte_cnt, trans_cnt); ++ ret = himci_wait_auto_stop_complete(host); ++ if (ret) { ++ mrq->stop->error = -ETIMEDOUT; ++ goto request_end; ++ } ++ } else { ++#endif ++ /* send soft stop command */ ++ himci_trace(3, "this time, send soft stop"); ++ ret = himci_exec_cmd(host, host->mrq->stop, ++ host->data); ++ if (ret) { ++ mrq->stop->error = ret; ++ goto request_end; ++ } ++ ret = himci_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); ++ himci_writel(ALL_SD_INT_CLR, host->base + MCI_RINTSTS); ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ himci_finish_request(host, mrq); ++} ++ ++static int himci_do_voltage_switch(struct himci_host *host, ++ struct mmc_ios *ios) ++{ ++ 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 = himci_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 */ ++ himci_trace(3, "switch voltage 330"); ++ ctrl &= ~(HI_SDXC_CTRL_VDD_180 << host->port); ++ himci_writel(ctrl, host->base + MCI_UHS_REG); ++ ++ /* Wait for 5ms */ ++ usleep_range(5000, 5500); ++ ++ /* 3.3V regulator output should be stable within 5 ms */ ++ ctrl = himci_readl(host->base + MCI_UHS_REG); ++ if (!(ctrl & (HI_SDXC_CTRL_VDD_180 << host->port ))) { ++ /* config Pin drive capability */ ++ himci_set_drv_cap(host, 0); ++ return 0; ++ } else { ++ himci_error(": Switching to 3.3V "); ++ himci_error("signalling voltage failed\n"); ++ return -EIO; ++ } ++ } else if (!(ctrl & (HI_SDXC_CTRL_VDD_180 << host->port)) && ++ (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)) { ++ /* Stop SDCLK */ ++ himci_trace(3, "switch voltage 180"); ++ himci_control_cclk(host, DISABLE); ++ ++ ++ /* ++ * Enable 1.8V Signal Enable in the MCI_UHS_REG ++ */ ++ ctrl |= (HI_SDXC_CTRL_VDD_180 << host->port); ++ himci_writel(ctrl, host->base + MCI_UHS_REG); ++ ++ /* Wait for 5ms */ ++ usleep_range(8000, 8500); ++ ++ ctrl = himci_readl(host->base + MCI_UHS_REG); ++ if (ctrl & (HI_SDXC_CTRL_VDD_180 << host->port)) { ++ /* Provide SDCLK again and wait for 1ms */ ++ himci_control_cclk(host, ENABLE); ++ usleep_range(1000, 1500); ++ ++ if (host->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 = himci_readl(host->base + MCI_RINTSTS); ++ if ((ctrl & VOLT_SWITCH_INT_STATUS) ++ && (ctrl & CD_INT_STATUS)) { ++ himci_writel(VOLT_SWITCH_INT_STATUS | CD_INT_STATUS, ++ host->base + MCI_RINTSTS); ++ /* config Pin drive capability */ ++ himci_set_drv_cap(host, 1); ++ 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 &= ~(HI_SDXC_CTRL_VDD_180 << host->port); ++ himci_writel(ctrl, host->base + MCI_UHS_REG); ++ ++ /* Wait for 5ms */ ++ usleep_range(5000, 5500); ++ ++ himci_ctrl_power(host, POWER_OFF, FORCE_DISABLE); ++ /* Wait for 1ms as per the spec */ ++ usleep_range(1000, 1500); ++ himci_ctrl_power(host, POWER_ON, FORCE_DISABLE); ++ ++ himci_control_cclk(host, DISABLE); ++ ++ /* Wait for 1ms as per the spec */ ++ usleep_range(1000, 1500); ++ himci_control_cclk(host, ENABLE); ++ ++ himci_error(": Switching to 1.8V signalling "); ++ himci_error("voltage failed, retrying with S18R set to 0\n"); ++ return -EAGAIN; ++ } else ++ /* No signal voltage switch required */ ++ return 0; ++} ++ ++static int himci_start_signal_voltage_switch(struct mmc_host *mmc, ++ struct mmc_ios *ios) ++{ ++ struct himci_host *host = mmc_priv(mmc); ++ int err; ++ ++ err = himci_do_voltage_switch(host, ios); ++ return err; ++} ++ ++static int himci_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; ++} ++ ++static void himci_set_sap_phase(struct himci_host *host, u32 phase) ++{ ++ unsigned int reg_value; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ reg_value = himci_readl(host->base + MCI_UHS_REG_EXT); ++ reg_value &= ~CLK_SMPL_PHS_MASK; ++ reg_value |= (phase << CLK_SMPL_PHS_SHIFT); ++ himci_writel(reg_value, host->base + MCI_UHS_REG_EXT); ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ ++/* ++ * 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 himci_execute_tuning(struct mmc_host *mmc, u32 opcode) ++{ ++ struct himci_host *host; ++ unsigned int index, count; ++ unsigned int err = 0; ++ unsigned int found = 0; /* identify if we have found a valid phase */ ++ 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, ret; ++ ++ ++ start_point = TUNING_START_PHASE; ++ end_point = TUNING_END_PHASE; ++ ++ host = mmc_priv(mmc); ++ ++ himci_writel(0x1, host->base + MCI_CARDTHRCTL); ++ ++ himci_trace(3, "start sd3.0 phase tuning..."); ++ host->is_tuning = 1; ++ for (index = start_point; index <= end_point; index++) { ++ /* set sample clk phase shift */ ++ himci_set_sap_phase(host, index); ++ ++ count = 0; ++ do { ++ ret = mmc_send_tuning(mmc, opcode, NULL); ++ himci_send_stop(mmc); /* send soft_stop tail */ ++ ++ if (ret) { ++ himci_trace(3, "send tuning CMD%u fail! phase:%d err:%d\n", ++ opcode, index, ret); ++ err = 1; ++ break; ++ } ++ count++; ++ } while (count < 1); ++ ++ if (!err) ++ found = 1; /* found a valid phase */ ++ ++ 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: ++ host->is_tuning = 0; ++ if (!found) { ++ himci_trace(5, "%s: no valid phase shift! use default", ++ mmc_hostname(mmc)); ++ himci_writel(DEFAULT_PHASE, host->base + MCI_UHS_REG_EXT); ++ } else { ++ himci_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; ++ ++ himci_set_sap_phase(host, phase); ++ ++ pr_info("tuning %s: valid phase shift [%d, %d] Final Phase %d\n", ++ mmc_hostname(mmc), raise_point, fall_point, phase); ++ } ++ ++ himci_writel(RW_THRESHOLD_SIZE, host->base + MCI_CARDTHRCTL); ++ ++ return 0; ++} ++ ++static void himci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct himci_host *host = mmc_priv(mmc); ++ unsigned int tmp_reg; ++ u32 ctrl; ++ ++ himci_trace(2, "begin"); ++ himci_assert(mmc); ++ himci_assert(ios); ++ himci_assert(host); ++ ++ himci_trace(3, "ios->power_mode = %d ", ios->power_mode); ++ if (!ios->clock) ++ himci_control_cclk(host, DISABLE); ++ ++ switch (ios->power_mode) { ++ case MMC_POWER_OFF: ++ himci_ctrl_power(host, POWER_OFF, FORCE_DISABLE); ++ break; ++ case MMC_POWER_UP: ++ case MMC_POWER_ON: ++ himci_ctrl_power(host, POWER_ON, FORCE_DISABLE); ++ break; ++ } ++ himci_trace(3, "ios->clock = %d ", ios->clock); ++ if (ios->clock) { ++ himci_control_cclk(host, DISABLE); ++ himci_set_cclk(host, ios->clock); ++ himci_control_cclk(host, ENABLE); ++ ++ /* speed mode check, if it is DDR50 set DDR mode */ ++ if (ios->timing == MMC_TIMING_UHS_DDR50) { ++ ctrl = himci_readl(host->base + MCI_UHS_REG); ++ if (!((HI_SDXC_CTRL_DDR_REG << host->port) & ctrl)) { ++ ctrl |= (HI_SDXC_CTRL_DDR_REG << host->port); ++ himci_writel(ctrl, host->base + MCI_UHS_REG); ++ } ++ } ++ } else { ++ himci_control_cclk(host, DISABLE); ++ if (ios->timing != MMC_TIMING_UHS_DDR50) { ++ ctrl = himci_readl(host->base + MCI_UHS_REG); ++ if ((HI_SDXC_CTRL_DDR_REG << host->port) & ctrl) { ++ ctrl &= ~(HI_SDXC_CTRL_DDR_REG << host->port); ++ himci_writel(ctrl, host->base + MCI_UHS_REG); ++ } ++ } ++ } ++ ++ /* set bus_width */ ++ himci_trace(3, "ios->bus_width = %d ", ios->bus_width); ++ tmp_reg = himci_readl(host->base + MCI_CTYPE); ++ tmp_reg &= ~((CARD_WIDTH_0 | CARD_WIDTH_1) << host->port); ++ ++ if (ios->bus_width == MMC_BUS_WIDTH_8) { ++ tmp_reg |= (CARD_WIDTH_0 << host->port); ++ himci_writel(tmp_reg, host->base + MCI_CTYPE); ++ } else if (ios->bus_width == MMC_BUS_WIDTH_4) { ++ tmp_reg |= (CARD_WIDTH_1 << host->port); ++ himci_writel(tmp_reg, host->base + MCI_CTYPE); ++ } else ++ himci_writel(tmp_reg, host->base + MCI_CTYPE); ++} ++ ++static void himci_enable_sdio_irq(struct mmc_host *mmc, int enable) ++{ ++ struct himci_host *host = mmc_priv(mmc); ++ unsigned int reg_value; ++ ++ reg_value = himci_readl(host->base + MCI_INTMASK); ++ if (enable) ++ reg_value |= SDIO_INT_MASK; ++ else ++ reg_value &= ~SDIO_INT_MASK; ++ himci_writel(reg_value, host->base + MCI_INTMASK); ++} ++ ++static int himci_get_card_detect(struct mmc_host *mmc) ++{ ++ unsigned ret; ++ struct himci_host *host = mmc_priv(mmc); ++ ++ himci_trace(2, "begin"); ++ ret = himci_sys_card_detect(host); ++ ++ if (ret) ++ return 0; ++ else ++ return 1; ++} ++ ++static int himci_get_ro(struct mmc_host *mmc) ++{ ++ unsigned ret; ++ struct himci_host *host = mmc_priv(mmc); ++ ++ himci_trace(2, "begin"); ++ himci_assert(mmc); ++ ++ ret = himci_ctrl_card_readonly(host); ++ ++ return ret; ++} ++ ++static void himci_hw_reset(struct mmc_host *mmc) ++{ ++ unsigned int reg_value; ++ struct himci_host *host = mmc_priv(mmc); ++ unsigned int port = host->port; ++ ++ reg_value = himci_readl(host->base + MCI_RESET_N); ++ reg_value &= ~(MMC_RST_N << port); ++ himci_writel(reg_value, host->base + MCI_RESET_N); ++ ++ /* For eMMC, minimum is 1us but give it 10us for good measure */ ++ udelay(10); ++ reg_value = himci_readl(host->base + MCI_RESET_N); ++ reg_value |= (MMC_RST_N << port); ++ himci_writel(reg_value, host->base + MCI_RESET_N); ++ ++ /* For eMMC, minimum is 200us but give it 300us for good measure */ ++ usleep_range(300, 1000); ++} ++ ++static const struct mmc_host_ops himci_ops = { ++ .request = himci_request, ++ .set_ios = himci_set_ios, ++ .get_ro = himci_get_ro, ++ .start_signal_voltage_switch = himci_start_signal_voltage_switch, ++ .execute_tuning = himci_execute_tuning, ++ .enable_sdio_irq = himci_enable_sdio_irq, ++ .hw_reset = himci_hw_reset, ++ .get_cd = himci_get_card_detect, ++}; ++ ++static irqreturn_t hisd_irq(int irq, void *dev_id) ++{ ++ struct himci_host *host = dev_id; ++ u32 state = 0; ++ int handle = 0; ++ u32 mstate = 0; ++ ++ spin_lock(&host->lock); ++ state = himci_readl(host->base + MCI_RINTSTS); ++ spin_unlock(&host->lock); ++ ++ /* bugfix: when send soft stop to SD Card, Host will report ++ sdio interrupt, This situation needs to be avoided */ ++ if (host->mmc->caps & MMC_CAP_SDIO_IRQ) { ++ if ((host->mmc->card != NULL) ++ && (host->mmc->card->type == MMC_TYPE_SDIO)) { ++ mstate = himci_readl(host->base + MCI_INTMASK); ++ if ((state & SDIO_INT_STATUS) && ++ (mstate & SDIO_INT_MASK)) { ++ spin_lock(&host->lock); ++ himci_writel(SDIO_INT_STATUS, ++ host->base + MCI_RINTSTS); ++ spin_unlock(&host->lock); ++ handle = 1; ++ mmc_signal_sdio_irq(host->mmc); ++ } ++ } ++ } ++ ++ if (state & DATA_INT_MASK) { ++ handle = 1; ++ host->pending_events |= HIMCI_PEND_DTO_M; ++ ++ spin_lock(&host->lock); ++ host->irq_status = himci_readl(host->base + MCI_RINTSTS); ++ himci_writel(DATA_INT_MASK , host->base + MCI_RINTSTS); ++ spin_unlock(&host->lock); ++ ++ wake_up(&host->intr_wait); ++ } ++ ++ if (handle) ++ return IRQ_HANDLED; ++ ++ return IRQ_NONE; ++} ++ ++static int himci_of_parse(struct device_node *np, struct mmc_host *mmc) ++{ ++ struct himci_host *host = mmc_priv(mmc); ++ int ret = mmc_of_parse(mmc); ++ int len; ++ ++ if (ret) ++ return ret; ++ ++ if (of_property_read_u32(np, "min-frequency", &mmc->f_min)) ++ mmc->f_min = MMC_CCLK_MIN; ++ ++ if (of_property_read_u32(np, "devid", &host->devid)) ++ return -EINVAL; ++ ++ if (of_find_property(np, "cap-mmc-hw-reset", &len)) ++ mmc->caps |= MMC_CAP_HW_RESET; ++ ++ return 0; ++} ++ ++static int __init himci_probe(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc; ++ struct himci_host *host = NULL; ++ struct resource *host_ioaddr_res = NULL; ++ int ret = 0, irq; ++ struct device_node *np = pdev->dev.of_node; ++ ++ himci_trace(2, "begin"); ++ pr_info("mmc host probe\n"); ++ himci_assert(pdev); ++ ++ mmc = mmc_alloc_host(sizeof(struct himci_host), &pdev->dev); ++ if (!mmc) { ++ himci_error("no mem for hi mci host controller!\n"); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ platform_set_drvdata(pdev, mmc); ++ ++ mmc->ops = &himci_ops; ++ ++ host_ioaddr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (NULL == host_ioaddr_res) { ++ himci_error("no ioaddr rescources config!\n"); ++ ret = -ENODEV; ++ goto out; ++ } ++ ++ if (himci_of_parse(np, mmc)) { ++ himci_error("failed to parse mmc dts!\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* reload by this controller */ ++ mmc->max_blk_count = 2048; ++ mmc->max_segs = 1024; ++ 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; ++ ++ host = mmc_priv(mmc); ++ mci_host[slot_index++] = host; ++ pdev->id = host->devid; ++ host->pdev = pdev; ++ host->mmc = mmc; ++#ifdef CONFIG_ARCH_HI3518EV20X ++ if (host->mmc->caps & MMC_CAP_HW_RESET) ++ host->port = 1; ++ else ++ host->port = 0; ++#else ++ host->port = 0; ++#endif ++ host->dma_vaddr = dma_alloc_coherent(&pdev->dev, CMD_DES_PAGE_SIZE, ++ &host->dma_paddr, GFP_KERNEL); ++ if (!host->dma_vaddr) { ++ himci_error("no mem for himci dma!\n"); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ host->base = devm_ioremap_resource(&pdev->dev, host_ioaddr_res); ++ if (IS_ERR_OR_NULL(host->base)) { ++ himci_error("no mem for himci base!\n"); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ spin_lock_init(&host->lock); ++ ++ host->crg_rst = devm_reset_control_get(&pdev->dev, "mmc_reset"); ++ if (IS_ERR_OR_NULL(host->crg_rst)) { ++ himci_error("get rst fail.\n"); ++ ret = PTR_ERR(host->crg_rst); ++ goto out; ++ } ++ ++ reset_control_assert(host->crg_rst); ++ usleep_range(50, 60); ++ reset_control_deassert(host->crg_rst); ++ ++ host->clk = devm_clk_get(&pdev->dev, "mmc_clk"); ++ if (IS_ERR_OR_NULL(host->clk)) { ++ himci_error("get clock fail.\n"); ++ ret = PTR_ERR(host->clk); ++ goto out; ++ } ++ ++ clk_prepare_enable(host->clk); ++ ++ host->power_status = POWER_OFF; ++ ++ /* enable card */ ++ himci_init_host(host); ++ host->card_status = himci_sys_card_detect(host); ++ ++ init_timer(&host->timer); ++ host->timer.function = himci_detect_card; ++ host->timer.data = (unsigned long)host; ++ host->timer.expires = jiffies + detect_time; ++ add_timer(&host->timer); ++ ++ init_waitqueue_head(&host->intr_wait); ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ pr_err("no IRQ defined!\n"); ++ goto out; ++ } ++ ++ host->irq = irq; ++ ret = request_irq(irq, hisd_irq, 0, DRIVER_NAME, host); ++ if (ret) { ++ pr_err("request_irq error!\n"); ++ goto out; ++ } ++ ++ mmc_add_host(mmc); ++ return 0; ++out: ++ if (host) { ++ del_timer(&host->timer); ++ ++ if (host->base) ++ devm_iounmap(&pdev->dev, host->base); ++ ++ if (host->dma_vaddr) ++ dma_free_coherent(&pdev->dev, CMD_DES_PAGE_SIZE, ++ host->dma_vaddr, host->dma_paddr); ++ } ++ if (mmc) ++ mmc_free_host(mmc); ++ ++ return ret; ++} ++ ++static int __exit himci_remove(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc = platform_get_drvdata(pdev); ++ ++ himci_trace(2, "begin"); ++ himci_assert(pdev); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ if (mmc) { ++ struct himci_host *host = mmc_priv(mmc); ++ ++ mmc_remove_host(mmc); ++ free_irq(host->irq, host); ++ del_timer_sync(&host->timer); ++ himci_ctrl_power(host, POWER_OFF, FORCE_DISABLE); ++ himci_control_cclk(host, DISABLE); ++ devm_iounmap(&pdev->dev, host->base); ++ dma_free_coherent(&pdev->dev, CMD_DES_PAGE_SIZE, host->dma_vaddr, ++ host->dma_paddr); ++ mmc_free_host(mmc); ++ } ++ return 0; ++} ++ ++static void himci_shutdown(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc = platform_get_drvdata(pdev); ++ ++ himci_trace(3, "shutdown"); ++ if (mmc) { ++ unsigned int val; ++ struct himci_host *host = mmc_priv(mmc); ++ ++ /* bugfix: host reset can trigger error intr */ ++ himci_writel(0, host->base + MCI_IDINTEN); ++ himci_writel(0, host->base + MCI_INTMASK); ++ ++ val = himci_readl(host->base + MCI_CTRL); ++ val |= CTRL_RESET | FIFO_RESET | DMA_RESET; ++ himci_writel(val, host->base + MCI_CTRL); ++ } ++} ++ ++#ifdef CONFIG_PM ++static int himci_pltm_suspend(struct platform_device *pdev, ++ pm_message_t state) ++{ ++ struct mmc_host *mmc = platform_get_drvdata(pdev); ++ struct himci_host *host; ++ int ret = 0; ++ ++ if (mmc) { ++ host = mmc_priv(mmc); ++ del_timer_sync(&host->timer); ++ ++ if (__clk_is_enabled(host->clk)) ++ clk_disable_unprepare(host->clk); ++ } ++ ++ return ret; ++} ++ ++static int himci_pltm_resume(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc = platform_get_drvdata(pdev); ++ struct himci_host *host; ++ int ret = 0; ++ ++ if (mmc) { ++ host = mmc_priv(mmc); ++ ++ if (!__clk_is_enabled(host->clk)) ++ clk_prepare_enable(host->clk); ++ ++ himci_init_host(host); ++ ++ add_timer(&host->timer); ++ } ++ ++ return ret; ++} ++#else ++#define himci_pltm_suspend NULL ++#define himci_pltm_resume NULL ++#endif ++ ++void himci_mmc_rescan(int slot) ++{ ++ struct mmc_host *mmc; ++ struct himci_host *host; ++ ++ host = mci_host[slot]; ++ if (!host || !host->mmc) { ++ himci_trace(5, "mmc%d: invalid slot!\n", slot); ++ return; ++ } ++ ++ mmc = host->mmc; ++ del_timer_sync(&host->timer); ++ ++ mmc_remove_host(mmc); ++ ++ mmc_add_host(mmc); ++ ++ add_timer(&host->timer); ++} ++EXPORT_SYMBOL(himci_mmc_rescan); ++ ++static const struct of_device_id ++himci_match[] __maybe_unused = { ++ {.compatible = "hisilicon,hi3516a-himci"}, ++ {.compatible = "hisilicon,hi3518ev20x-himci"}, ++ {}, ++}; ++ ++static struct platform_driver himci_driver = { ++ .probe = himci_probe, ++ .remove = himci_remove, ++ .shutdown = himci_shutdown, ++ .suspend = himci_pltm_suspend, ++ .resume = himci_pltm_resume, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(himci_match), ++ }, ++}; ++ ++static int __init himci_init(void) ++{ ++ int ret; ++ ++ himci_trace(2, "begin"); ++ ++ /* ++ * We should register SDIO1 first to make sure that ++ * the eMMC device,which connected to SDIO1 is mmcblk0. ++ */ ++ ++ ret = platform_driver_register(&himci_driver); ++ if (ret) { ++ platform_driver_unregister(&himci_driver); ++ himci_error("Himci driver register failed!"); ++ return ret; ++ } ++ ++ /* device proc entry */ ++ ret = mci_proc_init(HIMCI_SLOT_NUM); ++ if (ret) ++ himci_error("device proc init is failed!"); ++ ++ return ret; ++} ++ ++static void __exit himci_exit(void) ++{ ++ himci_trace(2, "begin"); ++ ++ mci_proc_shutdown(); ++ ++ platform_driver_unregister(&himci_driver); ++} ++ ++module_init(himci_init); ++module_exit(himci_exit); ++ ++#ifdef MODULE ++MODULE_AUTHOR("Hisilicon Drive Group"); ++MODULE_DESCRIPTION("MMC/SD driver for the Hisilicon MMC/SD Host Controller"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/mmc/host/himci/himci.h b/drivers/mmc/host/himci/himci.h +new file mode 100644 +index 0000000..6dc5b7b +--- /dev/null ++++ b/drivers/mmc/host/himci/himci.h +@@ -0,0 +1,141 @@ ++#ifndef _HI_MCI_H_ ++#define _HI_MCI_H_ ++ ++#include ++ ++extern int trace_level; ++#define HIMCI_TRACE_LEVEL 5 ++/* ++ 0 - all message ++ 1 - dump all register read/write ++ 2 - flow trace ++ 3 - timeout err and protocol err ++ */ ++ ++#define HIMCI_TRACE_FMT KERN_INFO ++ ++#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 HI_MCI_DETECT_TIMEOUT (HZ/2) ++ ++#define HI_MCI_REQUEST_TIMEOUT (5 * HZ) ++ ++#define MAX_RETRY_COUNT 100 ++ ++#define MMC_CCLK_MIN 100000 ++ ++/* Base address of SD card register */ ++#define HI_MCI_INTR (49+32) ++ ++#define himci_trace(level, msg...) do { \ ++ if ((level) >= trace_level) { \ ++ printk(HIMCI_TRACE_FMT "%s:%d: ", __func__, __LINE__); \ ++ printk(msg); \ ++ printk("\n"); \ ++ } \ ++} while (0) ++ ++#define himci_assert(cond) do { \ ++ if (!(cond)) {\ ++ printk(KERN_ERR "Assert:himci:%s:%d\n", \ ++ __func__, \ ++ __LINE__); \ ++ BUG(); \ ++ } \ ++} while (0) ++ ++#define himci_error(s...) do { \ ++ printk(KERN_ERR "himci:%s:%d: ", __func__, __LINE__); \ ++ printk(s); \ ++ printk("\n"); \ ++} while (0) ++ ++#define himci_readl(addr) ({unsigned int reg = readl(IOMEM(addr)); \ ++ himci_trace(1, "readl(0x%04X) = 0x%08X", (unsigned int)addr, reg); \ ++ reg; }) ++ ++#define himci_writel(v, addr) do { writel(v, IOMEM(addr)); \ ++ himci_trace(1, "writel(0x%04X) = 0x%08X", (unsigned int)addr, \ ++ (unsigned int)(v)); \ ++} while (0) ++ ++struct himci_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 himci_host { ++ struct mmc_host *mmc; ++ struct platform_device *pdev; ++ spinlock_t lock; ++ struct mmc_request *mrq; ++ struct mmc_command *cmd; ++ struct mmc_data *data; ++ void __iomem *base; ++ struct scatterlist *dma_sg; ++ unsigned int dma_sg_num; ++ 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; ++#define HIMCI_PEND_DTO_B (0) ++#define HIMCI_PEND_DTO_M (1 << HIMCI_PEND_DTO_B) ++ unsigned long pending_events; ++ unsigned int power_status; ++ unsigned int card_status; ++ unsigned int devid; ++ unsigned int hclk; ++ unsigned int cclk; ++ struct clk *clk; ++ struct reset_control *crg_rst; ++ unsigned int port; ++}; ++ ++union cmd_arg_u { ++ 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; ++}; ++ ++struct mmc_host *get_mmchost(int hostid); ++#endif ++ +diff --git a/drivers/mmc/host/himci/himci_hi3516a.c b/drivers/mmc/host/himci/himci_hi3516a.c +new file mode 100644 +index 0000000..95fd86a +--- /dev/null ++++ b/drivers/mmc/host/himci/himci_hi3516a.c +@@ -0,0 +1,94 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++#define MMC_CRG_MIN 25000000 ++ ++#define TUNING_START_PHASE 0 ++#define TUNING_END_PHASE 7 ++#define HIMCI_PHASE_SCALE 8 ++#define DRV_PHASE_DFLT (0x2<<23) ++#define SMPL_PHASE_DFLT (0x3<<16) ++ ++#define REG_PAD_CTRL 0x200f0800 ++ ++#define REG_CTRL_SDIO0_CLK 0xcc ++#define REG_CTRL_SDIO0_CMD 0xdc ++#define REG_CTRL_SDIO0_DATA0 0xe0 ++#define REG_CTRL_SDIO0_DATA1 0xe4 ++#define REG_CTRL_SDIO0_DATA2 0xe8 ++#define REG_CTRL_SDIO0_DATA3 0xec ++ ++#define REG_CTRL_SDIO1_CLK 0x104 ++#define REG_CTRL_SDIO1_CMD 0x114 ++#define REG_CTRL_SDIO1_DATA0 0x118 ++#define REG_CTRL_SDIO1_DATA1 0x11c ++#define REG_CTRL_SDIO1_DATA2 0x120 ++#define REG_CTRL_SDIO1_DATA3 0x124 ++ ++#define SDIO_CLK_DS_3V3 0x60 ++#define SDIO_CMD_DS_3V3 0xe0 ++#define SDIO_DATA0_DS_3V3 0xe0 ++#define SDIO_DATA1_DS_3V3 0xe0 ++#define SDIO_DATA2_DS_3V3 0xe0 ++#define SDIO_DATA3_DS_3V3 0xe0 ++ ++#define SDIO_CLK_DS_1V8 0x40 ++#define SDIO_CMD_DS_1V8 0xd0 ++#define SDIO_DATA0_DS_1V8 0xd0 ++#define SDIO_DATA1_DS_1V8 0xd0 ++#define SDIO_DATA2_DS_1V8 0xd0 ++#define SDIO_DATA3_DS_1V8 0xd0 ++ ++struct sdio_drv_cap { ++ unsigned int reg_addr; ++ unsigned int ds_3v3; ++ unsigned int ds_1v8; ++}; ++ ++#define SDIO_DRV_CAP(ofst, v1, v2) { \ ++ .reg_addr = ofst, \ ++ .ds_3v3 = v1, \ ++ .ds_1v8 = v2} ++static struct sdio_drv_cap sdio_ds[] = { ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CLK, SDIO_CLK_DS_3V3, SDIO_CLK_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CMD, SDIO_CMD_DS_3V3, SDIO_CMD_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_DATA0, SDIO_DATA0_DS_3V3, SDIO_DATA0_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_DATA1, SDIO_DATA1_DS_3V3, SDIO_DATA1_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_DATA2, SDIO_DATA2_DS_3V3, SDIO_DATA2_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_DATA3, SDIO_DATA3_DS_3V3, SDIO_DATA3_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO1_CLK, SDIO_CLK_DS_3V3, SDIO_CLK_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO1_CMD, SDIO_CMD_DS_3V3, SDIO_CMD_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO1_DATA0, SDIO_DATA0_DS_3V3, SDIO_DATA0_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO1_DATA1, SDIO_DATA1_DS_3V3, SDIO_DATA1_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO1_DATA2, SDIO_DATA2_DS_3V3, SDIO_DATA2_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO1_DATA3, SDIO_DATA3_DS_3V3, SDIO_DATA3_DS_1V8), ++}; ++ ++static void himci_set_drv_cap(struct himci_host *host, unsigned int vdd_180) ++{ ++ unsigned int i, offset; ++ ++ offset = host->devid * 6; ++ for (i = 0; i < 6; i++) { ++ if (vdd_180) ++ himci_writel(sdio_ds[i + offset].ds_1v8, ++ IO_ADDRESS(REG_PAD_CTRL + sdio_ds[i + offset].reg_addr)); ++ else ++ himci_writel(sdio_ds[i + offset].ds_3v3, ++ IO_ADDRESS(REG_PAD_CTRL + sdio_ds[i + offset].reg_addr)); ++ } ++} +diff --git a/drivers/mmc/host/himci/himci_hi3518ev20x.c b/drivers/mmc/host/himci/himci_hi3518ev20x.c +new file mode 100644 +index 0000000..af2e3ff +--- /dev/null ++++ b/drivers/mmc/host/himci/himci_hi3518ev20x.c +@@ -0,0 +1,152 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++#define MMC_CRG_MIN 49500000 ++ ++#define TUNING_START_PHASE 0 ++#define TUNING_END_PHASE 7 ++#define HIMCI_PHASE_SCALE 8 ++#define DRV_PHASE_DFLT (0x2<<23) ++#define SMPL_PHASE_DFLT (0x2<<16) ++ ++#define REG_PAD_CTRL 0x200f0800 ++ ++/* sdio0:sdxc pad ctrl reg */ ++#define REG_CTRL_SDIO0_CLK 0xb4 ++#define REG_CTRL_SDIO0_CMD 0xb8 ++#define REG_CTRL_SDIO0_DATA0 0xbc ++#define REG_CTRL_SDIO0_DATA1 0xc0 ++#define REG_CTRL_SDIO0_DATA2 0xc4 ++#define REG_CTRL_SDIO0_DATA3 0xc8 ++ ++/* sdio0:eMMC pad ctrl reg */ ++#define REG_CTRL_EMMC_CLK 0xcc ++#define REG_CTRL_EMMC_CMD 0xd8 ++#define REG_CTRL_EMMC_DATA0 0xdc ++#define REG_CTRL_EMMC_DATA1 0xf8 ++#define REG_CTRL_EMMC_DATA2 0xfc ++#define REG_CTRL_EMMC_DATA3 0xd4 ++#define REG_CTRL_EMMC_DATA4 0xd0 ++#define REG_CTRL_EMMC_DATA5 0xec ++#define REG_CTRL_EMMC_DATA6 0xe8 ++#define REG_CTRL_EMMC_DATA7 0xf0 ++ ++/* sdio1 pad ctrl reg */ ++#define REG_CTRL_SDIO1_CLK 0x10 ++#define REG_CTRL_SDIO1_CMD 0x28 ++#define REG_CTRL_SDIO1_DATA0 0x20 ++#define REG_CTRL_SDIO1_DATA1 0x1c ++#define REG_CTRL_SDIO1_DATA2 0x34 ++#define REG_CTRL_SDIO1_DATA3 0x24 ++ ++/* sdio0:sdxc pad ctrl config */ ++#define SDIO_CLK_DS_3V3 0xe0 ++#define SDIO_CMD_DS_3V3 0xe0 ++#define SDIO_DATA0_DS_3V3 0xe0 ++#define SDIO_DATA1_DS_3V3 0xe0 ++#define SDIO_DATA2_DS_3V3 0xe0 ++#define SDIO_DATA3_DS_3V3 0xe0 ++ ++/* sdio0:emmc pad ctrl config */ ++#define SDIO_CLK_DS_1V8 0xb0 ++#define SDIO_CMD_DS_1V8 0xd0 ++#define SDIO_DATA0_DS_1V8 0xd0 ++#define SDIO_DATA1_DS_1V8 0xd0 ++#define SDIO_DATA2_DS_1V8 0xd0 ++#define SDIO_DATA3_DS_1V8 0xd0 ++ ++/* sdio0:emmc pad ctrl config */ ++#define EMMC_CLK_DS 0x40 ++#define EMMC_CMD_DS 0x20 ++#define EMMC_DATA0_DS 0x20 ++#define EMMC_DATA1_DS 0x20 ++#define EMMC_DATA2_DS 0x20 ++#define EMMC_DATA3_DS 0x20 ++#define EMMC_DATA4_DS 0x20 ++#define EMMC_DATA5_DS 0x20 ++#define EMMC_DATA6_DS 0x20 ++#define EMMC_DATA7_DS 0x20 ++ ++struct sdio_drv_cap { ++ unsigned int reg_addr; ++ unsigned int ds_3v3; ++ unsigned int ds_1v8; ++}; ++ ++ ++#define SDIO_DRV_CAP(ofst, v1, v2) { \ ++ .reg_addr = ofst, \ ++ .ds_3v3 = v1, \ ++ .ds_1v8 = v2} ++static struct sdio_drv_cap sdio_ds[] = { ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CLK, SDIO_CLK_DS_3V3, SDIO_CLK_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CMD, SDIO_CMD_DS_3V3, SDIO_CMD_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_DATA0, SDIO_DATA0_DS_3V3, SDIO_DATA0_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_DATA1, SDIO_DATA1_DS_3V3, SDIO_DATA1_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_DATA2, SDIO_DATA2_DS_3V3, SDIO_DATA2_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_DATA3, SDIO_DATA3_DS_3V3, SDIO_DATA3_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO1_CLK, SDIO_CLK_DS_3V3, SDIO_CLK_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO1_CMD, SDIO_CMD_DS_3V3, SDIO_CMD_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO1_DATA0, SDIO_DATA0_DS_3V3, SDIO_DATA0_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO1_DATA1, SDIO_DATA1_DS_3V3, SDIO_DATA1_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO1_DATA2, SDIO_DATA2_DS_3V3, SDIO_DATA2_DS_1V8), ++ SDIO_DRV_CAP(REG_CTRL_SDIO1_DATA3, SDIO_DATA3_DS_3V3, SDIO_DATA3_DS_1V8), ++}; ++ ++struct emmc_drv_cap { ++ unsigned int reg_addr; ++ unsigned int ds; ++}; ++ ++#define EMMC_DRV_CAP(ofst, v) { \ ++ .reg_addr = ofst, \ ++ .ds = v} ++static struct emmc_drv_cap emmc_ds[] = { ++ EMMC_DRV_CAP(REG_CTRL_EMMC_CLK, EMMC_CLK_DS), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_CMD, EMMC_CMD_DS), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA0, EMMC_DATA0_DS), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA1, EMMC_DATA1_DS), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA2, EMMC_DATA2_DS), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA3, EMMC_DATA3_DS), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA4, EMMC_DATA4_DS), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA5, EMMC_DATA5_DS), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA6, EMMC_DATA6_DS), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA7, EMMC_DATA7_DS), ++}; ++ ++static void himci_set_drv_cap(struct himci_host *host, unsigned int vdd_180) ++{ ++ unsigned int i, offset; ++ ++ if (host->mmc->caps & MMC_CAP_HW_RESET) { ++ /* EMMC */ ++ for (i = 0; i < 10; i++) ++ himci_writel(emmc_ds[i].ds, ++ IO_ADDRESS(REG_PAD_CTRL + emmc_ds[i].reg_addr)); ++ } else { ++ /* SD */ ++ offset = host->devid * 6; ++ for (i = 0; i < 6; i++) { ++ if (vdd_180) ++ himci_writel(sdio_ds[i + offset].ds_1v8, ++ IO_ADDRESS(REG_PAD_CTRL + sdio_ds[i + offset].reg_addr)); ++ else ++ himci_writel(sdio_ds[i + offset].ds_3v3, ++ IO_ADDRESS(REG_PAD_CTRL + sdio_ds[i + offset].reg_addr)); ++ } ++ } ++} +diff --git a/drivers/mmc/host/himci/himci_proc.c b/drivers/mmc/host/himci/himci_proc.c +new file mode 100644 +index 0000000..c60dd5b +--- /dev/null ++++ b/drivers/mmc/host/himci/himci_proc.c +@@ -0,0 +1,221 @@ ++/***************************************************************************** ++ * This is the driver for the host mci SOC. ++ * ++ * Copyright (C) Hisilicon. All rights reserved. ++ * ++ ******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include "himci.h" ++#include "himci_reg.h" ++#include "himci_proc.h" ++ ++#define MCI_PARENT "mci" ++#define MCI_STATS_PROC "mci_info" ++#define MAX_CLOCK_SCALE (4) ++ ++static struct proc_dir_entry *proc_mci_dir; ++static unsigned int mci_max_connections; ++static char *card_type[MAX_CARD_TYPE + 1] = { ++ "MMC card", ++ "SD card", ++ "SDIO card", ++ "SD combo (IO+mem) card", ++ "unknown" ++}; ++static char *clock_unit[MAX_CLOCK_SCALE] = { ++ "Hz", ++ "KHz", ++ "MHz", ++ "GHz" ++}; ++ ++static char *mci_get_card_type(unsigned int sd_type) ++{ ++ if (MAX_CARD_TYPE <= sd_type) ++ return card_type[MAX_CARD_TYPE]; ++ else ++ return card_type[sd_type]; ++} ++ ++static unsigned int analyze_clock_scale(unsigned int clock, ++ unsigned int *clock_val) ++{ ++ unsigned int scale = 0; ++ unsigned int tmp = clock; ++ ++ while (1) { ++ tmp = tmp / 1000; ++ if (0 < tmp) { ++ *clock_val = tmp; ++ scale++; ++ } else { ++ break; ++ } ++ } ++ return scale; ++} ++ ++static void mci_stats_seq_printout(struct seq_file *s) ++{ ++ unsigned int index_mci; ++ unsigned int clock; ++ unsigned int clock_scale; ++ unsigned int clock_value = 0; ++ const char *type; ++ struct mmc_host *mmc; ++ struct himci_host *host; ++ struct mmc_card *card; ++ ++ for (index_mci = 0; index_mci < HIMCI_SLOT_NUM; index_mci++) { ++ host = mci_host[index_mci]; ++ if (!host || !host->mmc) { ++ seq_printf(s, "MCI%d invalid\n", index_mci); ++ continue; ++ } else { ++ seq_printf(s, "MCI%d", index_mci); ++ } ++ ++ mmc = host->mmc; ++ card = mmc->card; ++ if (NULL == card) { ++ seq_puts(s, " disconnected\n"); ++ } else { ++ seq_puts(s, " connected\n"); ++ ++ seq_printf(s, ++ "\tType: %s", ++ mci_get_card_type(card->type) ++ ); ++ ++ if (mmc_card_blockaddr(card)) { ++ if (mmc_card_ext_capacity(card)) ++ type = "SDXC"; ++ else ++ type = "SDHC"; ++ seq_printf(s, "(%s)\n", type); ++ } ++ ++ clock = host->hclk; ++ clock_scale = analyze_clock_scale(clock, &clock_value); ++ seq_printf(s, "\tHost work clock %d%s\n", ++ clock_value, clock_unit[clock_scale]); ++ ++ clock = mmc->ios.clock; ++ clock_scale = analyze_clock_scale(clock, &clock_value); ++ seq_printf(s, "\tCard support clock %d%s\n", ++ clock_value, clock_unit[clock_scale]); ++ ++ clock = host->cclk; ++ clock_scale = analyze_clock_scale(clock, &clock_value); ++ seq_printf(s, "\tCard work clock %d%s\n", ++ clock_value, clock_unit[clock_scale]); ++ } ++ } ++} ++ ++/* proc interface setup */ ++static void *mci_seq_start(struct seq_file *s, loff_t *pos) ++{ ++ /* counter is used to tracking multi proc interfaces ++ * We have only one interface so return zero ++ * pointer to start the sequence. ++ */ ++ static unsigned long counter; ++ ++ if (*pos == 0) ++ return &counter; ++ ++ *pos = 0; ++ return NULL; ++} ++ ++/* proc interface next */ ++static void *mci_seq_next(struct seq_file *s, void *v, loff_t *pos) ++{ ++ (*pos)++; ++ if (*pos >= HIMCI_SLOT_NUM) ++ return NULL; ++ ++ return NULL; ++} ++ ++/* define parameters where showed in proc file */ ++static int mci_stats_seq_show(struct seq_file *s, void *v) ++{ ++ mci_stats_seq_printout(s); ++ return 0; ++} ++ ++/* proc interface stop */ ++static void mci_seq_stop(struct seq_file *s, void *v) ++{ ++} ++ ++/* proc interface operation */ ++static const struct seq_operations mci_stats_seq_ops = { ++ .start = mci_seq_start, ++ .next = mci_seq_next, ++ .stop = mci_seq_stop, ++ .show = mci_stats_seq_show ++}; ++ ++/* proc file open*/ ++static int mci_stats_proc_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &mci_stats_seq_ops); ++}; ++ ++/* proc file operation */ ++static const struct file_operations mci_stats_proc_ops = { ++ .owner = THIS_MODULE, ++ .open = mci_stats_proc_open, ++ .read = seq_read, ++ .release = seq_release ++}; ++ ++int mci_proc_init(unsigned int max_connections) ++{ ++ struct proc_dir_entry *proc_stats_entry; ++ ++ mci_max_connections = max_connections; ++ ++ proc_mci_dir = proc_mkdir(MCI_PARENT, NULL); ++ if (!proc_mci_dir) { ++ pr_err("%s: failed to create proc file %s\n", ++ __func__, MCI_PARENT); ++ return 1; ++ } ++ ++ proc_stats_entry = proc_create(MCI_STATS_PROC, ++ 0, proc_mci_dir, &mci_stats_proc_ops); ++ if (!proc_stats_entry) { ++ pr_err("%s: failed to create proc file %s\n", ++ __func__, MCI_STATS_PROC); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++int mci_proc_shutdown(void) ++{ ++ if (proc_mci_dir) { ++ if (mci_max_connections > 0) ++ remove_proc_entry(MCI_STATS_PROC, proc_mci_dir); ++ ++ remove_proc_entry(MCI_PARENT, NULL); ++ proc_mci_dir = NULL; ++ } ++ ++ return 0; ++} +diff --git a/drivers/mmc/host/himci/himci_proc.h b/drivers/mmc/host/himci/himci_proc.h +new file mode 100644 +index 0000000..23b4a22 +--- /dev/null ++++ b/drivers/mmc/host/himci/himci_proc.h +@@ -0,0 +1,18 @@ ++/* ++ * MCI connection table manager ++ */ ++#ifndef __MCI_PROC_H__ ++#define __MCI_PROC_H__ ++ ++#include ++ ++#define MAX_CARD_TYPE 4 ++#define MAX_SPEED_MODE 5 ++ ++#define HIMCI_SLOT_NUM 2 ++ ++extern struct himci_host *mci_host[HIMCI_SLOT_NUM]; ++int mci_proc_init(unsigned int max_connections); ++int mci_proc_shutdown(void); ++ ++#endif /* __MCI_PROC_H__ */ +diff --git a/drivers/mmc/host/himci/himci_reg.h b/drivers/mmc/host/himci/himci_reg.h +new file mode 100644 +index 0000000..0ba5f91 +--- /dev/null ++++ b/drivers/mmc/host/himci/himci_reg.h +@@ -0,0 +1,192 @@ ++#ifndef _HI_MCI_REG_H_ ++#define _HI_MCI_REG_H_ ++ ++#define HI_MCI_IO_SIZE 0x1000 ++ ++#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_RESET_N 0x78 ++#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_CARDTHRCTL 0x100 ++#define MCI_UHS_REG_EXT 0x108 ++ ++/* IDMAC DEST1 details */ ++#define DMA_BUFFER (0x2000) ++#define MAX_DMA_DES (20480) ++ ++/* 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_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) ++ ++/* MCI_CLKENA(0x10) details */ ++#define CCLK_ENABLE (0x1<<0) ++#define CCLK_LOW_POWER (0x1<<16) ++ ++/* 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 ++ ++/* MCI_CTYPE(0x18) details */ ++#define CARD_WIDTH_0 (0x1<<16) ++#define CARD_WIDTH_1 (0x1<<0) ++ ++/* MCI_INTMASK(0x24) details: ++ bit 16-1: mask MMC host controller each interrupt ++*/ ++#define ALL_INT_MASK 0x1ffff ++#define DTO_INT_MASK (0x1<<3) ++#define SDIO_INT_MASK (0x1<<16) ++ ++/* MCI_CMD(0x2c) details: ++ bit 31: cmd execute or load start param of interface clk bit ++*/ ++#define START_CMD (0x1<<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 CMD_INT_MASK (RTO_INT_STATUS | RCRC_INT_STATUS | RE_INT_STATUS) ++#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 ALL_SD_INT_CLR 0xefff ++ ++/* MCI_STATUS(0x48) details */ ++#define DATA_BUSY (0x1<<9) ++ ++/* MCI_FIFOTH(0x4c) details */ ++#define BURST_SIZE (0x6<<28) ++#define RX_WMARK (0x7f<<16) ++#define TX_WMARK (0x80) ++ ++/* MCI_CDETECT(0x50) details */ ++#define HIMCI_CARD0 (0x1<<0) ++ ++/* MCI_UHS_REG(0x74) details */ ++#define HI_SDXC_CTRL_VDD_180 (0x1<<0) ++#define HI_SDXC_CTRL_DDR_REG (0x1<<16) ++ ++/* MCI_RESET_N(0x78) details */ ++#define MMC_RST_N (0x1<<0) ++ ++/* MCI_BMOD(0x80) details */ ++#define BMOD_SWR (0x1<<0) ++#define BURST_INCR (0x1<<1) ++#define BMOD_DMA_EN (0x1<<7) ++#define BURST_8 (0x2<<8) ++#define BURST_16 (0x3<<8) ++ ++/* MCI_CARDTHRCTL(0x100) details */ ++#define RW_THRESHOLD_SIZE (0x2000001) ++ ++/* MCI_UHS_REG_EXT(0x108) details */ ++/* bit[19:16] sampling phase */ ++#define CLK_SMPL_PHS_SHIFT (16) ++#define CLK_SMPL_PHS_MASK (0x7<<16) ++ ++/* bit[26:23] drv phase */ ++#define CLK_DRV_PHS_SHIFT (23) ++#define CLK_DRV_PHS_MASK (0x7<<23) ++#define DEFAULT_PHASE 0x1050000 ++ ++#endif +diff --git a/drivers/mmc/host/mci_proc.c b/drivers/mmc/host/mci_proc.c +new file mode 100644 +index 0000000..9fa531a +--- /dev/null ++++ b/drivers/mmc/host/mci_proc.c +@@ -0,0 +1,325 @@ ++/***************************************************************************** ++ * This is the driver for the host mci SOC. ++ * ++ * Copyright (C) Hisilicon. All rights reserved. ++ * ++ ******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "sdhci.h" ++#include "mci_proc.h" ++ ++#define MCI_PARENT "mci" ++#define MCI_STATS_PROC "mci_info" ++#define MAX_CLOCK_SCALE (4) ++#define UNSTUFF_BITS(resp,start,size) \ ++ ({ \ ++ const int __size = size; \ ++ const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \ ++ const int __off = 3 - ((start) / 32); \ ++ const int __shft = (start) & 31; \ ++ u32 __res; \ ++ \ ++ __res = resp[__off] >> __shft; \ ++ if (__size + __shft > 32) \ ++ __res |= resp[__off-1] << ((32 - __shft) % 32); \ ++ __res & __mask; \ ++ }) ++ ++struct card_info { ++ unsigned int type; ++ unsigned int state; ++ unsigned int sd_bus_speed; ++ unsigned int raw_ssr[16]; ++}; ++ ++unsigned int slot_index = 0; ++struct mmc_host *mci_host[MCI_SLOT_NUM] = {NULL}; ++static struct proc_dir_entry *proc_mci_dir; ++ ++static char *card_type[MAX_CARD_TYPE + 1] = { ++ "MMC card", ++ "SD card", ++ "SDIO card", ++ "SD combo (IO+mem) card", ++ "unknown" ++}; ++static char *clock_unit[4] = { ++ "Hz", ++ "KHz", ++ "MHz", ++ "GHz" ++}; ++ ++static char *mci_get_card_type(unsigned int sd_type) ++{ ++ if (MAX_CARD_TYPE <= sd_type) ++ return card_type[MAX_CARD_TYPE]; ++ else ++ return card_type[sd_type]; ++} ++ ++static unsigned int analyze_clock_scale(unsigned int clock, ++ unsigned int *clock_val) ++{ ++ unsigned int scale = 0; ++ unsigned int tmp = clock; ++ ++ while (1) { ++ tmp = tmp / 1000; ++ if (0 < tmp) { ++ *clock_val = tmp; ++ scale++; ++ } else { ++ break; ++ } ++ } ++ return scale; ++} ++ ++static inline int mmc_in_uhs(struct mmc_host *host) ++{ ++ return host->ios.timing >= MMC_TIMING_UHS_SDR12 && ++ host->ios.timing <= MMC_TIMING_UHS_DDR50; ++}; ++ ++static inline int mmc_in_hs(struct mmc_host *host) ++{ ++ return host->ios.timing == MMC_TIMING_SD_HS || ++ host->ios.timing == MMC_TIMING_MMC_HS; ++}; ++ ++static inline int mmc_in_hs400(struct mmc_host *host) ++{ ++ return host->ios.timing == MMC_TIMING_MMC_HS400; ++}; ++ ++static inline int mmc_in_hs200(struct mmc_host *host) ++{ ++ return host->ios.timing == MMC_TIMING_MMC_HS200; ++}; ++ ++static inline int mmc_in_ddr52(struct mmc_host *host) ++{ ++ return host->ios.timing == MMC_TIMING_MMC_DDR52; ++}; ++ ++static void mci_stats_seq_printout(struct seq_file *s) ++{ ++ unsigned int index_mci; ++ unsigned int clock; ++ unsigned int clock_scale; ++ unsigned int clock_value = 0; ++ const char *type; ++ static struct mmc_host *mmc; ++ static struct mmc_card *card; ++ const char *uhs_bus_speed_mode = ""; ++ static const char *const uhs_speeds[] = { ++ [UHS_SDR12_BUS_SPEED] = "SDR12 ", ++ [UHS_SDR25_BUS_SPEED] = "SDR25 ", ++ [UHS_SDR50_BUS_SPEED] = "SDR50 ", ++ [UHS_SDR104_BUS_SPEED] = "SDR104 ", ++ [UHS_DDR50_BUS_SPEED] = "DDR50 ", ++ }; ++ unsigned int speed_class, grade_speed_uhs; ++ struct card_info info = {0}; ++ unsigned int present; ++ struct sdhci_host *host; ++ ++ for (index_mci = 0; index_mci < MCI_SLOT_NUM; index_mci++) { ++ mmc = mci_host[index_mci]; ++ if (NULL == mmc) { ++ seq_printf(s, "MCI%d invalid\n", index_mci); ++ continue; ++ } else { ++ seq_printf(s, "MCI%d", index_mci); ++ } ++ ++ present = mmc->ops->get_cd(mmc); ++ if (present) { ++ seq_puts(s, ": pluged"); ++ } else { ++ seq_puts(s, ": unplugged"); ++ } ++ ++ card = mmc->card; ++ if (NULL == card) { ++ seq_puts(s, "_disconnected\n"); ++ } else { ++ mmc_get_card(card); ++ if (mmc_card_removed(card)) { ++ mmc_put_card(card); ++ seq_puts(s, "_disconnected\n"); ++ continue; ++ } ++ info.type = card->type; ++ info.state = card->state; ++ info.sd_bus_speed = card->sd_bus_speed; ++ memcpy(info.raw_ssr, card->raw_ssr, 64); ++ mmc_put_card(card); ++ ++ seq_puts(s, "_connected\n"); ++ ++ seq_printf(s, ++ "\tType: %s", ++ mci_get_card_type(info.type) ++ ); ++ ++ if (mmc_card_blockaddr(&info)) { ++ if (mmc_card_ext_capacity(&info)) ++ type = "SDXC"; ++ else ++ type = "SDHC"; ++ seq_printf(s, "(%s)\n", type); ++ } ++ ++ if (mmc_in_uhs(mmc) && ++ (info.sd_bus_speed < ARRAY_SIZE(uhs_speeds))) ++ uhs_bus_speed_mode = uhs_speeds[info.sd_bus_speed]; ++ else ++ uhs_bus_speed_mode = ""; ++ ++ seq_printf(s, "\tMode: %s%s%s%s\n", ++ mmc_in_uhs(mmc) ? "UHS " : ++ (mmc_in_hs(mmc) ? "HS " : ""), ++ mmc_in_hs400(mmc) ? "HS400 " : ++ (mmc_in_hs200(mmc) ? "HS200 " : ""), ++ mmc_in_ddr52(mmc) ? "DDR " : "", ++ uhs_bus_speed_mode); ++ ++ speed_class = UNSTUFF_BITS(info.raw_ssr, 440 - 384, 8); ++ grade_speed_uhs = UNSTUFF_BITS(info.raw_ssr, 396 - 384, 4); ++ seq_printf(s, "\tSpeed Class: Class %s\n", ++ (0x00 == speed_class) ? "0": ++ (0x01 == speed_class) ? "2": ++ (0x02 == speed_class) ? "4": ++ (0x03 == speed_class) ? "6": ++ (0x04 == speed_class) ? "10": ++ "Reserved"); ++ seq_printf(s, "\tUhs Speed Grade: %s\n", ++ (0x00 == grade_speed_uhs)? ++ "Less than 10MB/sec(0h)" : ++ (0x01 == grade_speed_uhs)? ++ "10MB/sec and above(1h)": ++ "Reserved"); ++ ++ clock = mmc->ios.clock; ++ clock_scale = analyze_clock_scale(clock, &clock_value); ++ seq_printf(s, "\tHost work clock: %d%s\n", ++ clock_value, clock_unit[clock_scale]); ++ ++ clock = mmc->ios.clock; ++ clock_scale = analyze_clock_scale(clock, &clock_value); ++ seq_printf(s, "\tCard support clock: %d%s\n", ++ clock_value, clock_unit[clock_scale]); ++ clock = mmc->actual_clock; ++ clock_scale = analyze_clock_scale(clock, &clock_value); ++ seq_printf(s, "\tCard work clock: %d%s\n", ++ clock_value, clock_unit[clock_scale]); ++ ++ host = mmc_priv(mmc); ++ /* add card read/write error count */ ++ seq_printf(s, "\tCard error count: %d\n", ++ host->error_count); ++ } ++ } ++} ++ ++/* proc interface setup */ ++static void *mci_seq_start(struct seq_file *s, loff_t *pos) ++{ ++ /* counter is used to tracking multi proc interfaces ++ * We have only one interface so return zero ++ * pointer to start the sequence. ++ */ ++ static unsigned long counter; ++ ++ if (*pos == 0) ++ return &counter; ++ ++ *pos = 0; ++ return NULL; ++} ++ ++/* proc interface next */ ++static void *mci_seq_next(struct seq_file *s, void *v, loff_t *pos) ++{ ++ (*pos)++; ++ if (*pos >= MCI_SLOT_NUM) ++ return NULL; ++ ++ return NULL; ++} ++ ++/* define parameters where showed in proc file */ ++static int mci_stats_seq_show(struct seq_file *s, void *v) ++{ ++ mci_stats_seq_printout(s); ++ return 0; ++} ++ ++/* proc interface stop */ ++static void mci_seq_stop(struct seq_file *s, void *v) ++{ ++} ++ ++/* proc interface operation */ ++static const struct seq_operations mci_stats_seq_ops = { ++ .start = mci_seq_start, ++ .next = mci_seq_next, ++ .stop = mci_seq_stop, ++ .show = mci_stats_seq_show ++}; ++ ++/* proc file open*/ ++static int mci_stats_proc_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &mci_stats_seq_ops); ++}; ++ ++/* proc file operation */ ++static const struct file_operations mci_stats_proc_ops = { ++ .owner = THIS_MODULE, ++ .open = mci_stats_proc_open, ++ .read = seq_read, ++ .release = seq_release ++}; ++ ++int mci_proc_init(void) ++{ ++ struct proc_dir_entry *proc_stats_entry; ++ ++ proc_mci_dir = proc_mkdir(MCI_PARENT, NULL); ++ if (!proc_mci_dir) { ++ pr_err("%s: failed to create proc file %s\n", ++ __func__, MCI_PARENT); ++ return 1; ++ } ++ ++ proc_stats_entry = proc_create(MCI_STATS_PROC, ++ 0, proc_mci_dir, &mci_stats_proc_ops); ++ if (!proc_stats_entry) { ++ pr_err("%s: failed to create proc file %s\n", ++ __func__, MCI_STATS_PROC); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++int mci_proc_shutdown(void) ++{ ++ if (proc_mci_dir) { ++ remove_proc_entry(MCI_STATS_PROC, proc_mci_dir); ++ remove_proc_entry(MCI_PARENT, NULL); ++ proc_mci_dir = NULL; ++ } ++ ++ return 0; ++} +diff --git a/drivers/mmc/host/mci_proc.h b/drivers/mmc/host/mci_proc.h +new file mode 100644 +index 0000000..10717d8 +--- /dev/null ++++ b/drivers/mmc/host/mci_proc.h +@@ -0,0 +1,22 @@ ++/* ++ * MCI connection table manager ++ */ ++#ifndef __MCI_PROC_H__ ++#define __MCI_PROC_H__ ++ ++#include ++ ++#define MAX_CARD_TYPE 4 ++#define MAX_SPEED_MODE 5 ++ ++#ifdef CONFIG_ARCH_HI3559AV100 ++ #define MCI_SLOT_NUM 3 ++#endif ++ ++extern unsigned int slot_index; ++extern struct mmc_host *mci_host[MCI_SLOT_NUM]; ++ ++int mci_proc_init(void); ++int mci_proc_shutdown(void); ++ ++#endif /* __MCI_PROC_H__ */ +diff --git a/drivers/mmc/host/sdhci-hisi.c b/drivers/mmc/host/sdhci-hisi.c +new file mode 100644 +index 0000000..ae9a99f +--- /dev/null ++++ b/drivers/mmc/host/sdhci-hisi.c +@@ -0,0 +1,1053 @@ ++/* ++ * SDHCI support for hisi SoC ++ * ++ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "sdhci-pltfm.h" ++#include "mci_proc.h" ++ ++#define SDHCI_HISI_EDGE_TUNING ++ ++#define PHASE_SCALE 32 ++#define NOT_FOUND -1 ++#define MAX_TUNING_NUM 1 ++#define MAX_FREQ 200000000 ++ ++#define REG_EMMC_DRV_DLL_CTRL 0x1b0 ++#define REG_SDIO0_DRV_DLL_CTRL 0x1d4 ++#define REG_SDIO1_DRV_DLL_CTRL 0x1fc ++#define REG_SDIO2_DRV_DLL_CTRL 0x224 ++#define SDIO_DRV_PHASE_SEL_MASK (0x1f << 24) ++#define SDIO_DRV_SEL(phase) ((phase) << 24) ++ ++#define REG_EMMC_DRV_DLL_STATUS 0x1c4 ++#define REG_SDIO0_DRV_DLL_STATUS 0x1e8 ++#define REG_SDIO1_DRV_DLL_STATUS 0x210 ++#define REG_SDIO2_DRV_DLL_STATUS 0x238 ++#define SDIO_DRV_DLL_LOCK BIT(15) ++ ++#define REG_EMMC_SAMPL_DLL_STATUS 0x1bc ++#define REG_SDIO0_SAMPL_DLL_STATUS 0x1e0 ++#define REG_SDIO1_SAMPL_DLL_STATUS 0x208 ++#define REG_SDIO2_SAMPL_DLL_STATUS 0x230 ++#define SDIO_SAMPL_DLL_SLAVE_READY BIT(14) ++ ++#define REG_EMMC_SAMPL_DLL_CTRL 0x1a8 ++#define REG_SDIO0_SAMPL_DLL_CTRL 0x1ec ++#define REG_SDIO1_SAMPL_DLL_CTRL 0x214 ++#define REG_SDIO2_SAMPL_DLL_CTRL 0x23c ++#define SDIO_SAMPL_DLL_SLAVE_EN BIT(16) ++ ++#define REG_EMMC_SAMPLB_DLL_CTRL 0x1ac ++#define REG_SDIO0_SAMPLB_DLL_CTRL 0x1d0 ++#define REG_SDIO1_SAMPLB_DLL_CTRL 0x1f8 ++#define REG_SDIO2_SAMPLB_DLL_CTRL 0x220 ++#define SDIO_SAMPLB_DLL_CLK_MASK (0x1f << 24) ++#define SDIO_SAMPLB_SEL(phase) ((phase) << 24) ++ ++#define REG_EMMC_DS_DLL_CTRL 0x1b4 ++#define EMMC_DS_DLL_MODE_SSEL BIT(13) ++#define EMMC_DS_DLL_SSEL_MASK (0x1fff) ++#define REG_EMMC_DS180_DLL_CTRL 0x1b8 ++#define EMMC_DS180_DLL_BYPASS BIT(15) ++#define REG_EMMC_DS_DLL_STATUS 0x1c8 ++#define EMMC_DS_DLL_LOCK BIT(15) ++#define EMMC_DS_DLL_MDLY_TAP_MASK (0x1fff) ++ ++#define REG_MISC_CTRL18 0x48 ++#define SDIO0_PWRSW_SEL_1V8 BIT(5) ++#define SDIO0_PWR_EN BIT(4) ++#define SDIO1_IO_MODE_SEL_1V8 BIT(3) ++#define SDIO0_IO_MODE_SEL_1V8 BIT(1) ++#define SDIO0_PWR_CTRL_BY_MISC BIT(0) ++ ++#define REG_IOCTL_RONSEL_1_0 0x264 ++#define REG_IOCTL_OD_RONSEL_2 0x268 ++ ++#define REG_CTRL_SDIO0_CLK 0x104c ++#define REG_CTRL_SDIO0_CMD 0x1050 ++#define REG_CTRL_SDIO0_DATA0 0x1054 ++#define REG_CTRL_SDIO0_DATA1 0x1058 ++#define REG_CTRL_SDIO0_DATA2 0x105c ++#define REG_CTRL_SDIO0_DATA3 0x1060 ++#define REG_CTRL_SDIO1_CLK 0x106c ++#define REG_CTRL_SDIO1_CMD 0x1070 ++#define REG_CTRL_SDIO1_DATA0 0x1074 ++#define REG_CTRL_SDIO1_DATA1 0x1078 ++#define REG_CTRL_SDIO1_DATA2 0x107c ++#define REG_CTRL_SDIO1_DATA3 0x1080 ++#define REG_CTRL_SDIO2_CLK 0x10b0 ++#define REG_CTRL_SDIO2_CMD 0x10b8 ++#define REG_CTRL_SDIO2_DATA0 0x10ac ++#define REG_CTRL_SDIO2_DATA1 0x1084 ++#define REG_CTRL_SDIO2_DATA2 0x10a0 ++#define REG_CTRL_SDIO2_DATA3 0x10bc ++ ++static unsigned int sdio2_iocfg_reg[] = { ++ REG_CTRL_SDIO2_CLK, ++ REG_CTRL_SDIO2_CMD, ++ REG_CTRL_SDIO2_DATA0, ++ REG_CTRL_SDIO2_DATA1, ++ REG_CTRL_SDIO2_DATA2, ++ REG_CTRL_SDIO2_DATA3 ++}; ++ ++static unsigned int sdr104_drv[] = {0x60, 0x60, 0x60, 0x60, 0x60, 0x60}; ++static unsigned int sdrxx_drv[] = {0x40, 0x40, 0x40, 0x40, 0x40, 0x40}; ++static unsigned int hs_ds_drv[] = {0x70, 0x40, 0x40, 0x40, 0x40, 0x40}; ++ ++struct sdhci_hisi_priv { ++ struct reset_control *crg_rst; ++ struct reset_control *dll_rst; ++ struct reset_control *sampl_rst; ++ struct regmap *crg_regmap; ++ struct regmap *misc_regmap; ++ struct regmap *iocfg_regmap; ++ void __iomem *phy_addr; ++ unsigned int f_max; ++ unsigned int devid; ++ unsigned int drv_phase; ++ unsigned int sampl_phase; ++ unsigned int tuning_phase; ++}; ++ ++static inline void *sdhci_get_pltfm_priv(struct sdhci_host *host) ++{ ++ return sdhci_pltfm_priv(sdhci_priv(host)); ++} ++ ++static unsigned int sdhci_hisi_get_max_clk(struct sdhci_host *host) ++{ ++ struct sdhci_hisi_priv *hisi_priv = sdhci_get_pltfm_priv(host); ++ ++ return hisi_priv->f_max; ++} ++ ++static int sdhci_hisi_parse_dt(struct sdhci_host *host) ++{ ++ struct sdhci_hisi_priv *hisi_priv = sdhci_get_pltfm_priv(host); ++ struct device_node *np = host->mmc->parent->of_node; ++ int ret, len; ++ ++ ret = mmc_of_parse(host->mmc); ++ if (ret) ++ return ret; ++ ++ if (of_property_read_u32(np, "max-frequency", &hisi_priv->f_max)) ++ hisi_priv->f_max = MAX_FREQ; ++ ++ if (of_find_property(np, "mmc-broken-cmd23", &len)) ++ host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; ++ ++ return 0; ++} ++ ++static void hisi_mmc_crg_init(struct sdhci_host *host) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_hisi_priv *hisi_priv = sdhci_pltfm_priv(pltfm_host); ++ ++ clk_prepare_enable(pltfm_host->clk); ++ reset_control_assert(hisi_priv->crg_rst); ++ reset_control_assert(hisi_priv->dll_rst); ++ reset_control_assert(hisi_priv->sampl_rst); ++ udelay(25); ++ reset_control_deassert(hisi_priv->crg_rst); ++ udelay(10); ++} ++ ++static void sdhci_hisi_hs400_enhanced_strobe(struct mmc_host *mmc, ++ struct mmc_ios *ios) ++{ ++ u16 ctrl; ++ struct sdhci_host *host = mmc_priv(mmc); ++ ++ ctrl = sdhci_readw(host, SDHCI_EMMC_CTRL); ++ if (ios->enhanced_strobe) ++ ctrl |= SDHCI_ENH_STROBE_EN; ++ else ++ ctrl &= ~SDHCI_ENH_STROBE_EN; ++ ++ sdhci_writew(host, ctrl, SDHCI_EMMC_CTRL); ++} ++ ++static int sdhci_hisi_pltfm_init(struct platform_device *pdev, ++ struct sdhci_host *host) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_hisi_priv *hisi_priv = sdhci_pltfm_priv(pltfm_host); ++ struct device_node *np = pdev->dev.of_node; ++ struct clk *clk; ++ int ret; ++ ++ hisi_priv->crg_rst = devm_reset_control_get(&pdev->dev, "crg_reset"); ++ if (IS_ERR_OR_NULL(hisi_priv->crg_rst)) { ++ dev_err(&pdev->dev, "get crg_rst failed.\n"); ++ return PTR_ERR(hisi_priv->crg_rst);; ++ } ++ ++ hisi_priv->dll_rst = devm_reset_control_get(&pdev->dev, "dll_reset"); ++ if (IS_ERR_OR_NULL(hisi_priv->dll_rst)) { ++ dev_err(&pdev->dev, "get dll_rst failed.\n"); ++ return PTR_ERR(hisi_priv->dll_rst);; ++ } ++ ++ hisi_priv->sampl_rst = devm_reset_control_get(&pdev->dev, "sampl_reset"); ++ if (IS_ERR_OR_NULL(hisi_priv->sampl_rst)) { ++ dev_err(&pdev->dev, "get sampl_rst failed.\n"); ++ return PTR_ERR(hisi_priv->sampl_rst);; ++ } ++ ++ hisi_priv->crg_regmap = syscon_regmap_lookup_by_phandle(np, "crg_regmap"); ++ if (IS_ERR(hisi_priv->crg_regmap)) ++ return PTR_ERR(hisi_priv->crg_regmap); ++ ++ if (of_property_read_u32(np, "devid", &hisi_priv->devid)) ++ return -EINVAL; ++ ++ if (hisi_priv->devid == 0) { ++ struct resource *res; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (!res) ++ return -ENOMEM; ++ ++ hisi_priv->phy_addr = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(hisi_priv->phy_addr)) ++ return PTR_ERR(hisi_priv->phy_addr); ++ } else { ++ hisi_priv->misc_regmap = syscon_regmap_lookup_by_phandle(np, ++ "misc_regmap"); ++ if (IS_ERR(hisi_priv->misc_regmap)) ++ return PTR_ERR(hisi_priv->misc_regmap); ++ ++ hisi_priv->iocfg_regmap = syscon_regmap_lookup_by_phandle(np, ++ "iocfg_regmap"); ++ if (IS_ERR(hisi_priv->iocfg_regmap)) ++ return PTR_ERR(hisi_priv->iocfg_regmap); ++ } ++ ++ clk = devm_clk_get(mmc_dev(host->mmc), "mmc_clk"); ++ if (IS_ERR_OR_NULL(clk)) { ++ dev_err(mmc_dev(host->mmc), "get clk err\n"); ++ return -EINVAL; ++ } ++ ++ pltfm_host->clk = clk; ++ ++ hisi_mmc_crg_init(host); ++ ret = sdhci_hisi_parse_dt(host); ++ if (ret) ++ return ret; ++ ++ /* only eMMC has a hw reset, and now eMMC signaling ++ * is fixed to 180*/ ++ if (host->mmc->caps & MMC_CAP_HW_RESET) { ++ host->flags &= ~SDHCI_SIGNALING_330; ++ host->flags |= SDHCI_SIGNALING_180; ++ } ++ ++ /* we parse the support timings from dts, so we read the ++ * host capabilities early and clear the timing capabilities, ++ * SDHCI_QUIRK_MISSING_CAPS is set so that sdhci driver would ++ * not read it again */ ++ host->caps = sdhci_readl(host, SDHCI_CAPABILITIES); ++ host->caps &= ~SDHCI_CAN_DO_HISPD; ++ host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1); ++ host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 | ++ SDHCI_SUPPORT_DDR50 | SDHCI_CAN_DO_ADMA3); ++ host->caps1 |= SDHCI_USE_SDR50_TUNING; ++ host->quirks |= SDHCI_QUIRK_MISSING_CAPS; ++ ++ host->mmc_host_ops.hs400_enhanced_strobe = sdhci_hisi_hs400_enhanced_strobe; ++ ++ mci_host[slot_index++] = host->mmc; ++ ++ return 0; ++} ++ ++static void hisi_set_drv_phase(struct sdhci_host *host, unsigned int phase) ++{ ++ struct sdhci_hisi_priv *hisi_priv = sdhci_get_pltfm_priv(host); ++ unsigned int devid = hisi_priv->devid; ++ unsigned int offset[4] = {REG_EMMC_DRV_DLL_CTRL, ++ REG_SDIO0_DRV_DLL_CTRL, ++ REG_SDIO1_DRV_DLL_CTRL, ++ REG_SDIO2_DRV_DLL_CTRL}; ++ ++ regmap_write_bits(hisi_priv->crg_regmap, offset[devid], ++ SDIO_DRV_PHASE_SEL_MASK, SDIO_DRV_SEL(phase)); ++} ++ ++static void hisi_set_sampl_phase(struct sdhci_host *host, ++ unsigned int phase) ++{ ++ unsigned int reg; ++ ++ reg = sdhci_readl(host, SDHCI_AT_STAT); ++ reg &= ~SDHCI_PHASE_SEL_MASK; ++ reg |= phase; ++ sdhci_writel(host, reg, SDHCI_AT_STAT); ++} ++ ++static void hisi_disable_card_clk(struct sdhci_host *host) ++{ ++ u16 clk; ++ ++ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); ++ clk &= ~SDHCI_CLOCK_CARD_EN; ++ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); ++} ++ ++static void hisi_enable_card_clk(struct sdhci_host *host) ++{ ++ u16 clk; ++ ++ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); ++ clk |= SDHCI_CLOCK_CARD_EN; ++ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); ++} ++ ++static void hisi_disable_inter_clk(struct sdhci_host *host) ++{ ++ u16 clk; ++ ++ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); ++ clk &= ~SDHCI_CLOCK_INT_EN; ++ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); ++} ++ ++static void hisi_enable_sampl_dll_slave(struct sdhci_host *host) ++{ ++ struct sdhci_hisi_priv *hisi_priv = sdhci_get_pltfm_priv(host); ++ unsigned int devid = hisi_priv->devid; ++ unsigned int offset[4] = {REG_EMMC_SAMPL_DLL_CTRL, ++ REG_SDIO0_SAMPL_DLL_CTRL, ++ REG_SDIO1_SAMPL_DLL_CTRL, ++ REG_SDIO2_SAMPL_DLL_CTRL}; ++ ++ regmap_write_bits(hisi_priv->crg_regmap, offset[devid], ++ SDIO_SAMPL_DLL_SLAVE_EN, SDIO_SAMPL_DLL_SLAVE_EN); ++} ++ ++static void hisi_wait_drv_dll_lock(struct sdhci_host *host) ++{ ++ struct sdhci_hisi_priv *hisi_priv = sdhci_get_pltfm_priv(host); ++ unsigned int devid = hisi_priv->devid; ++ unsigned int reg, timeout = 20; ++ unsigned int offset[4] = {REG_EMMC_DRV_DLL_STATUS, ++ REG_SDIO0_DRV_DLL_STATUS, ++ REG_SDIO1_DRV_DLL_STATUS, ++ REG_SDIO2_DRV_DLL_STATUS}; ++ ++ do { ++ reg = 0; ++ regmap_read(hisi_priv->crg_regmap, offset[devid], ®); ++ if (reg & SDIO_DRV_DLL_LOCK) ++ return; ++ ++ mdelay(1); ++ timeout--; ++ } while (timeout > 0); ++ ++ pr_err("%s: DRV DLL master not locked.\n", mmc_hostname(host->mmc)); ++} ++ ++static void hisi_wait_sampl_dll_slave_ready(struct sdhci_host *host) ++{ ++ struct sdhci_hisi_priv *hisi_priv = sdhci_get_pltfm_priv(host); ++ unsigned int devid = hisi_priv->devid; ++ unsigned int reg, timeout = 20; ++ unsigned int offset[4] = {REG_EMMC_SAMPL_DLL_STATUS, ++ REG_SDIO0_SAMPL_DLL_STATUS, ++ REG_SDIO1_SAMPL_DLL_STATUS, ++ REG_SDIO2_SAMPL_DLL_STATUS}; ++ ++ do { ++ reg = 0; ++ regmap_read(hisi_priv->crg_regmap, offset[devid], ®); ++ if (reg & SDIO_SAMPL_DLL_SLAVE_READY) ++ return; ++ ++ mdelay(1); ++ timeout--; ++ } while (timeout > 0); ++ ++ pr_err("%s: SAMPL DLL slave not ready.\n", mmc_hostname(host->mmc)); ++} ++ ++static void hisi_wait_ds_dll_lock(struct sdhci_host *host) ++{ ++ struct sdhci_hisi_priv *hisi_priv = sdhci_get_pltfm_priv(host); ++ unsigned int reg, timeout = 20; ++ ++ do { ++ reg = 0; ++ regmap_read(hisi_priv->crg_regmap, REG_EMMC_DS_DLL_STATUS, ®); ++ if (reg & EMMC_DS_DLL_LOCK) ++ return; ++ ++ mdelay(1); ++ timeout--; ++ } while (timeout > 0); ++ ++ pr_err("%s: DS DLL master not locked.\n", mmc_hostname(host->mmc)); ++} ++ ++static void hisi_set_ds_dll_delay(struct sdhci_host *host) ++{ ++ struct sdhci_hisi_priv *hisi_priv = sdhci_get_pltfm_priv(host); ++ unsigned int reg, mdly_tap; ++ ++ regmap_read(hisi_priv->crg_regmap, REG_EMMC_DS_DLL_STATUS, ®); ++ mdly_tap = reg & EMMC_DS_DLL_MDLY_TAP_MASK; ++ ++ regmap_write_bits(hisi_priv->crg_regmap, REG_EMMC_DS_DLL_CTRL, ++ (EMMC_DS_DLL_SSEL_MASK | EMMC_DS_DLL_MODE_SSEL), ++ ((mdly_tap / 4 + 12) | EMMC_DS_DLL_MODE_SSEL)); ++ ++ regmap_write_bits(hisi_priv->crg_regmap, REG_EMMC_DS180_DLL_CTRL, ++ EMMC_DS180_DLL_BYPASS, EMMC_DS180_DLL_BYPASS); ++} ++ ++static void hisi_get_phase(struct sdhci_host *host) ++{ ++ struct sdhci_hisi_priv *hisi_priv = sdhci_get_pltfm_priv(host); ++ ++ if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 ++ || host->mmc->ios.timing == MMC_TIMING_MMC_DDR52 ++ || host->mmc->ios.timing == MMC_TIMING_UHS_DDR50) ++ hisi_priv->drv_phase = 8; /*90 degree*/ ++ else if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200) ++ hisi_priv->drv_phase = 20; /*225 degree*/ ++ else ++ hisi_priv->drv_phase = 16; /*180 degree */ ++ ++ if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400) ++ hisi_priv->sampl_phase = hisi_priv->tuning_phase; ++ else if (host->mmc->ios.timing == MMC_TIMING_MMC_DDR52 ++ || host->mmc->ios.timing == MMC_TIMING_UHS_DDR50) ++ hisi_priv->sampl_phase = 4; ++ else ++ hisi_priv->sampl_phase = 0; ++} ++ ++static void hisi_enable_sample(struct sdhci_host *host) ++{ ++ unsigned int reg; ++ ++ reg = sdhci_readl(host, SDHCI_AT_CTRL); ++ reg |= SDHCI_SAMPLE_EN; ++ sdhci_writel(host, reg, SDHCI_AT_CTRL); ++} ++ ++static void sdhci_hisi_set_clock(struct sdhci_host *host, unsigned int clock) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_hisi_priv *hisi_priv = sdhci_pltfm_priv(pltfm_host); ++ unsigned long timeout; ++ u16 clk = 0; ++ ++ host->mmc->actual_clock = 0; ++ hisi_disable_card_clk(host); ++ udelay(25); ++ hisi_disable_inter_clk(host); ++ if (clock == 0) ++ return; ++ ++ reset_control_assert(hisi_priv->dll_rst); ++ reset_control_assert(hisi_priv->sampl_rst); ++ udelay(25); ++ ++ clk_set_rate(pltfm_host->clk, clock); ++ host->mmc->actual_clock = clk_get_rate(pltfm_host->clk); ++ ++ hisi_get_phase(host); ++ hisi_set_drv_phase(host, hisi_priv->drv_phase); ++ hisi_enable_sample(host); ++ hisi_set_sampl_phase(host, hisi_priv->sampl_phase); ++ udelay(25); ++ ++ if (host->mmc->actual_clock > MMC_HIGH_52_MAX_DTR) { ++ hisi_enable_sampl_dll_slave(host); ++ reset_control_deassert(hisi_priv->dll_rst); ++ reset_control_deassert(hisi_priv->sampl_rst); ++ } ++ ++ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); ++ clk |= SDHCI_CLOCK_INT_EN | SDHCI_CLOCK_PLL_EN; ++ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); ++ timeout = 20; ++ while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) ++ & SDHCI_CLOCK_INT_STABLE)) { ++ if (timeout == 0) { ++ pr_err("%s: Internal clock never " ++ "stabilised.\n", mmc_hostname(host->mmc)); ++ return; ++ } ++ timeout--; ++ mdelay(1); ++ } ++ ++ if (host->mmc->actual_clock > MMC_HIGH_52_MAX_DTR) { ++ hisi_wait_drv_dll_lock(host); ++ hisi_wait_sampl_dll_slave_ready(host); ++ } ++ ++ clk |= SDHCI_CLOCK_CARD_EN; ++ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); ++ udelay(100); ++ ++ if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400) { ++ hisi_wait_ds_dll_lock(host); ++ hisi_set_ds_dll_delay(host); ++ } ++} ++ ++static void hisi_select_sampl_phase(struct sdhci_host *host, ++ unsigned int phase) ++{ ++ hisi_disable_card_clk(host); ++ hisi_set_sampl_phase(host, phase); ++ hisi_wait_sampl_dll_slave_ready(host); ++ hisi_enable_card_clk(host); ++ udelay(1); ++} ++ ++static int hisi_send_tuning(struct sdhci_host *host, u32 opcode) ++{ ++ int count, err; ++ ++ count = 0; ++ do { ++ err = mmc_send_tuning(host->mmc, opcode, NULL); ++ if (err) ++ break; ++ ++ count++; ++ } while (count < MAX_TUNING_NUM); ++ ++ return err; ++} ++ ++static void hisi_pre_tuning(struct sdhci_host *host) ++{ ++ sdhci_writel(host, host->ier | SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE); ++ sdhci_writel(host, host->ier | SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE); ++ ++ hisi_wait_drv_dll_lock(host); ++ hisi_enable_sampl_dll_slave(host); ++ hisi_enable_sample(host); ++ host->is_tuning = 1; ++} ++ ++static void hisi_post_tuning(struct sdhci_host *host) ++{ ++ unsigned short ctrl; ++ ++ ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); ++ ctrl |= SDHCI_CTRL_TUNED_CLK; ++ sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); ++ ++ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); ++ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); ++ host->is_tuning = 0; ++} ++ ++#ifndef SDHCI_HISI_EDGE_TUNING ++static int hisi_get_best_sampl(u32 candidates) ++{ ++ int rise = NOT_FOUND, fall = NOT_FOUND; ++ int win_max_r = NOT_FOUND, win_max_f = NOT_FOUND; ++ int end_fall = NOT_FOUND, found = NOT_FOUND; ++ int i, win, win_max = 0; ++ ++ for (i = 0; i < 32; i++) { ++ if ((candidates & 0x3) == 0x2) ++ rise = (i + 1) % 32; ++ ++ if ((candidates & 0x3) == 0x1) { ++ fall = i; ++ if (rise != NOT_FOUND) { ++ win = fall - rise + 1; ++ if (win > win_max) { ++ win_max = win; ++ found = (fall + rise) / 2; ++ win_max_r = rise; ++ win_max_f = fall; ++ rise = NOT_FOUND; ++ fall = NOT_FOUND; ++ } ++ } else ++ end_fall = fall; ++ } ++ candidates = ror32(candidates, 1); ++ } ++ ++ if (end_fall != NOT_FOUND && rise != NOT_FOUND) { ++ fall = end_fall; ++ if (end_fall < rise) ++ end_fall += 32; ++ ++ win = end_fall - rise + 1; ++ if (win > win_max) { ++ found = (rise + (win / 2)) % 32; ++ win_max_r = rise; ++ win_max_f = fall; ++ } ++ } ++ ++ if (found != NOT_FOUND) ++ printk("valid phase shift [%d, %d] Final Phase:%d\n", ++ win_max_r, win_max_f, found); ++ ++ return found; ++} ++ ++static int sdhci_hisi_exec_tuning(struct sdhci_host *host, u32 opcode) ++{ ++ struct sdhci_hisi_priv *hisi_priv = sdhci_get_pltfm_priv(host); ++ unsigned int sampl; ++ unsigned int candidates = 0; ++ int phase, err; ++ ++ hisi_pre_tuning(host); ++ ++ for (sampl = 0; sampl < PHASE_SCALE; sampl++) { ++ hisi_select_sampl_phase(host, sampl); ++ ++ err = hisi_send_tuning(host, opcode); ++ if (err) ++ pr_debug("send tuning CMD%u fail! phase:%d err:%d\n", ++ opcode, sampl, err); ++ else ++ candidates |= (0x1 << sampl); ++ } ++ ++ pr_info("%s: tuning done! candidates 0x%X: ", ++ mmc_hostname(host->mmc), candidates); ++ ++ phase = hisi_get_best_sampl(candidates); ++ if (phase == NOT_FOUND) { ++ phase = hisi_priv->sampl_phase; ++ printk("no valid phase shift! use default %d\n", phase); ++ } ++ ++ hisi_priv->tuning_phase = phase; ++ hisi_select_sampl_phase(host, phase); ++ hisi_post_tuning(host); ++ ++ return 0; ++} ++ ++#else ++static void hisi_enable_edge_tuning(struct sdhci_host *host) ++{ ++ struct sdhci_hisi_priv *hisi_priv = sdhci_get_pltfm_priv(host); ++ unsigned int devid = hisi_priv->devid; ++ unsigned int samplb_offset[4] = {REG_EMMC_SAMPLB_DLL_CTRL, ++ REG_SDIO0_SAMPLB_DLL_CTRL, ++ REG_SDIO1_SAMPLB_DLL_CTRL, ++ REG_SDIO2_SAMPLB_DLL_CTRL}; ++ unsigned int reg; ++ ++ regmap_write_bits(hisi_priv->crg_regmap, samplb_offset[devid], ++ SDIO_SAMPLB_DLL_CLK_MASK, SDIO_SAMPLB_SEL(8)); ++ ++ reg = sdhci_readl(host, SDHCI_MULTI_CYCLE); ++ reg |= SDHCI_EDGE_DETECT_EN; ++ sdhci_writel(host, reg, SDHCI_MULTI_CYCLE); ++} ++ ++static void hisi_disable_edge_tuning(struct sdhci_host *host) ++{ ++ unsigned int reg; ++ ++ reg = sdhci_readl(host, SDHCI_MULTI_CYCLE); ++ reg &= ~SDHCI_EDGE_DETECT_EN; ++ sdhci_writel(host, reg, SDHCI_MULTI_CYCLE); ++} ++ ++static int sdhci_hisi_exec_edge_tuning(struct sdhci_host *host, u32 opcode) ++{ ++ struct sdhci_hisi_priv *hisi_priv = sdhci_get_pltfm_priv(host); ++ unsigned int index, val; ++ unsigned int found = 0, prev_found = 0; ++ unsigned int edge_p2f, edge_f2p, start, end; ++ unsigned int phase, fall = NOT_FOUND, rise = NOT_FOUND; ++ int err, prev_err = 0; ++ ++ hisi_pre_tuning(host); ++ hisi_enable_edge_tuning(host); ++ ++ start = 0; ++ end = PHASE_SCALE / 4; ++ ++ edge_p2f = start; ++ edge_f2p = end; ++ for (index = 0; index < end; index++) { ++ hisi_select_sampl_phase(host, index * 4); ++ ++ err = mmc_send_tuning(host->mmc, opcode, NULL); ++ if (!err) { ++ val = sdhci_readl(host, SDHCI_MULTI_CYCLE); ++ found = val & SDHCI_FOUND_EDGE; ++ } else ++ found = 1; ++ ++ if (prev_found && !found) ++ edge_f2p = index; ++ else if (!prev_found && found) ++ edge_p2f = index; ++ ++ if ((edge_p2f != start) && (edge_f2p != end)) ++ break; ++ ++ prev_found = found; ++ found = 0; ++ } ++ ++ if ((edge_p2f == start) && (edge_f2p == end)) { ++ pr_err("%s: tuning failed! can not found edge!\n", ++ mmc_hostname(host->mmc)); ++ return -1; ++ } ++ ++ hisi_disable_edge_tuning(host); ++ ++ start = edge_p2f * 4; ++ end = edge_f2p * 4; ++ if (end <= start) ++ end += PHASE_SCALE; ++ ++ fall = start; ++ rise = end; ++ for (index = start; index < end; index++) { ++ hisi_select_sampl_phase(host, index % PHASE_SCALE); ++ ++ err = hisi_send_tuning(host, opcode); ++ if (err) ++ pr_debug("send tuning CMD%u fail! phase:%d err:%d\n", ++ opcode, index, err); ++ ++ if (!prev_err && err) ++ fall = index; ++ ++ if (prev_err && !err) ++ rise = index; ++ ++ prev_err = err; ++ } ++ ++ phase = ((fall + rise) / 2 + 16) % PHASE_SCALE; ++ ++ pr_info("%s: tuning done! valid phase shift [%d, %d] Final Phase:%d\n", ++ mmc_hostname(host->mmc), rise % PHASE_SCALE, ++ fall % PHASE_SCALE, phase); ++ ++ hisi_priv->tuning_phase = phase; ++ hisi_select_sampl_phase(host, phase); ++ hisi_post_tuning(host); ++ ++ return 0; ++} ++#endif ++ ++static int hisi_set_signal_voltage_3v3(struct sdhci_host *host) ++{ ++ struct sdhci_hisi_priv *hisi_priv = sdhci_get_pltfm_priv(host); ++ struct regmap *misc = hisi_priv->misc_regmap; ++ unsigned int ctrl; ++ ++ /* sdio2: it is fixed to 1v8, so we fake that 3v3 is ok */ ++ if (hisi_priv->devid == 3) ++ return 0; ++ ++ pr_debug("%s: set voltage to 330\n", mmc_hostname(host->mmc)); ++ ++ if (hisi_priv->devid == 1) { ++ regmap_read(misc, REG_MISC_CTRL18, &ctrl); ++ ctrl |= SDIO0_PWR_CTRL_BY_MISC | SDIO0_PWR_EN; ++ ctrl &= ~(SDIO0_IO_MODE_SEL_1V8 | SDIO0_PWRSW_SEL_1V8); ++ regmap_write(misc, REG_MISC_CTRL18, ctrl); ++ ++ /* Wait for 5ms */ ++ usleep_range(5000, 5500); ++ ++ regmap_read(misc, REG_MISC_CTRL18, &ctrl); ++ if ((ctrl & SDIO0_PWR_CTRL_BY_MISC) ++ && (ctrl & SDIO0_PWR_EN) ++ && !(ctrl & SDIO0_IO_MODE_SEL_1V8) && ++ !(ctrl & SDIO0_PWRSW_SEL_1V8)) ++ return 0; ++ } ++ ++ if (hisi_priv->devid == 2) { ++ regmap_read(misc, REG_MISC_CTRL18, &ctrl); ++ ctrl &= ~SDIO1_IO_MODE_SEL_1V8; ++ regmap_write(misc, REG_MISC_CTRL18, ctrl); ++ ++ /* Wait for 5ms */ ++ usleep_range(5000, 5500); ++ ++ regmap_read(misc, REG_MISC_CTRL18, &ctrl); ++ if (!(ctrl & SDIO1_IO_MODE_SEL_1V8)) ++ return 0; ++ } ++ ++ pr_warn("%s: 3.3V output did not became stable\n", ++ mmc_hostname(host->mmc)); ++ ++ return -EAGAIN; ++} ++ ++static int hisi_set_signal_voltage_1v8(struct sdhci_host *host) ++{ ++ struct sdhci_hisi_priv *hisi_priv = sdhci_get_pltfm_priv(host); ++ struct regmap *misc = hisi_priv->misc_regmap; ++ unsigned int ctrl; ++ ++ pr_debug("%s: set voltage to 180\n", mmc_hostname(host->mmc)); ++ ++ if (hisi_priv->devid == 0 || hisi_priv->devid == 3) ++ return 0; ++ ++ if (hisi_priv->devid == 1) { ++ regmap_read(misc, REG_MISC_CTRL18, &ctrl); ++ ctrl |= SDIO0_IO_MODE_SEL_1V8; ++ regmap_write(misc, REG_MISC_CTRL18, ctrl); ++ ++ usleep_range(1000, 2000); ++ ++ ctrl |= SDIO0_PWRSW_SEL_1V8; ++ regmap_write(misc, REG_MISC_CTRL18, ctrl); ++ ++ regmap_read(misc, REG_MISC_CTRL18, &ctrl); ++ if ((ctrl & SDIO0_PWRSW_SEL_1V8) && (ctrl & SDIO0_IO_MODE_SEL_1V8)) ++ return 0; ++ } ++ ++ pr_warn("%s: 1.8V output did not became stable\n", ++ mmc_hostname(host->mmc)); ++ ++ return -EAGAIN; ++} ++ ++static int sdhci_hisi_start_signal_voltage_switch(struct sdhci_host *host, ++ struct mmc_ios *ios) ++{ ++ switch (ios->signal_voltage) { ++ case MMC_SIGNAL_VOLTAGE_330: ++ if (!(host->flags & SDHCI_SIGNALING_330)) ++ return -EINVAL; ++ return hisi_set_signal_voltage_3v3(host); ++ case MMC_SIGNAL_VOLTAGE_180: ++ if (!(host->flags & SDHCI_SIGNALING_180)) ++ return -EINVAL; ++ return hisi_set_signal_voltage_1v8(host); ++ default: ++ /* No signal voltage switch required */ ++ return 0; ++ } ++} ++ ++static void hisi_set_io_config(struct sdhci_host *host) ++{ ++ struct sdhci_hisi_priv *hisi_priv = sdhci_get_pltfm_priv(host); ++ unsigned int devid = hisi_priv->devid; ++ void* phy_addr = hisi_priv->phy_addr; ++ void* iocfg_regmap = hisi_priv->iocfg_regmap; ++ unsigned int reg_addr, start, end; ++ unsigned int *pin_drv_cap; ++ unsigned short reg; ++ ++ if (devid == 0) { ++ if (host->timing == MMC_TIMING_MMC_HS200 ++ || host->timing == MMC_TIMING_MMC_HS400) { ++ reg = sdhci_readw(host, SDHCI_EMMC_CTRL); ++ reg |= SDHCI_CARD_IS_EMMC; ++ sdhci_writew(host, reg, SDHCI_EMMC_CTRL); ++ ++ /* set drv strength to 50ohm */ ++ writel(0x0, phy_addr + REG_IOCTL_RONSEL_1_0); ++ writel(0x6ff, phy_addr + REG_IOCTL_OD_RONSEL_2); ++ } ++ } else { ++ if (host->timing == MMC_TIMING_UHS_SDR104) ++ pin_drv_cap = sdr104_drv; ++ else if (host->timing == MMC_TIMING_UHS_SDR50 || ++ host->timing == MMC_TIMING_UHS_SDR25 || ++ host->timing == MMC_TIMING_UHS_SDR12) ++ pin_drv_cap = sdrxx_drv; ++ else ++ pin_drv_cap = hs_ds_drv; ++ ++ if (devid == 3) { ++ unsigned int i; ++ ++ for (i = 0; i < 6; i++) { ++ regmap_write_bits(iocfg_regmap, sdio2_iocfg_reg[i], ++ 0xf0, *pin_drv_cap); ++ pin_drv_cap++; ++ } ++ ++ return; ++ } ++ ++ start = devid == 1 ? REG_CTRL_SDIO0_CLK : REG_CTRL_SDIO1_CLK; ++ end = devid == 1 ? REG_CTRL_SDIO0_DATA3 : REG_CTRL_SDIO1_DATA3; ++ for (reg_addr = start; reg_addr <= end; reg_addr += 4) { ++ regmap_write_bits(iocfg_regmap, reg_addr, 0xf0, *pin_drv_cap); ++ pin_drv_cap++; ++ } ++ } ++} ++ ++static void sdhci_hisi_set_uhs_signaling(struct sdhci_host *host, unsigned timing) ++{ ++ sdhci_set_uhs_signaling(host, timing); ++ host->timing = timing; ++ ++ hisi_set_io_config(host); ++} ++ ++static void sdhci_hisi_hw_reset(struct sdhci_host *host) ++{ ++ sdhci_writel(host, 0x0, SDHCI_EMMC_HW_RESET); ++ udelay(10); ++ sdhci_writel(host, 0x1, SDHCI_EMMC_HW_RESET); ++ udelay(200); ++} ++ ++/* This api is for wifi driver rescan the sdio device, ++ * ugly but it is needed */ ++int hisi_sdio_rescan(int slot) ++{ ++ struct mmc_host *mmc = mci_host[slot]; ++ ++ if (!mmc) { ++ pr_err("invalid mmc, please check the argument\n"); ++ return -EINVAL; ++ } ++ ++ mmc_detect_change(mmc, 0); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(hisi_sdio_rescan); ++ ++static const struct sdhci_ops sdhci_hisi_ops = { ++ .get_max_clock = sdhci_hisi_get_max_clk, ++ .set_clock = sdhci_hisi_set_clock, ++ .set_bus_width = sdhci_set_bus_width, ++ .reset = sdhci_reset, ++ .set_uhs_signaling = sdhci_hisi_set_uhs_signaling, ++ .hw_reset = sdhci_hisi_hw_reset, ++ .start_signal_voltage_switch = ++ sdhci_hisi_start_signal_voltage_switch, ++#ifdef SDHCI_HISI_EDGE_TUNING ++ .platform_execute_tuning = sdhci_hisi_exec_edge_tuning, ++#else ++ .platform_execute_tuning = sdhci_hisi_exec_tuning, ++#endif ++ .pre_init = hisi_mmc_crg_init, ++}; ++ ++static const struct sdhci_pltfm_data sdhci_hisi_pdata = { ++ .ops = &sdhci_hisi_ops, ++ .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | ++ SDHCI_QUIRK_INVERTED_WRITE_PROTECT | ++ SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | ++ SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, ++ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, ++}; ++static int sdhci_hisi_probe(struct platform_device *pdev) ++{ ++ struct sdhci_host *host; ++ struct sdhci_pltfm_host *pltfm_host; ++ int ret; ++ ++ host = sdhci_pltfm_init(pdev, &sdhci_hisi_pdata, ++ sizeof(struct sdhci_hisi_priv)); ++ if (IS_ERR(host)) ++ return PTR_ERR(host); ++ ++ ret = sdhci_hisi_pltfm_init(pdev, host); ++ if (ret) ++ goto err_sdhci_add; ++ ++ ret = sdhci_add_host(host); ++ if (ret) { ++ goto err_sdhci_add; ++ } ++ ++ return 0; ++ ++err_sdhci_add: ++ pltfm_host = sdhci_priv(host); ++ clk_disable_unprepare(pltfm_host->clk); ++ sdhci_pltfm_free(pdev); ++ return ret; ++} ++ ++static int sdhci_hisi_remove(struct platform_device *pdev) ++{ ++ return sdhci_pltfm_unregister(pdev); ++} ++ ++static const struct of_device_id sdhci_hisi_match[] = { ++ { .compatible = "hisi-sdhci" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, sdhci_hisi_match); ++ ++static struct platform_driver sdhci_hisi_driver = { ++ .driver = { ++ .name = "sdhci-hisi", ++ .of_match_table = sdhci_hisi_match, ++ .pm = &sdhci_pltfm_pmops, ++ }, ++ .probe = sdhci_hisi_probe, ++ .remove = sdhci_hisi_remove, ++}; ++ ++static int __init sdhci_hisi_init(void) ++{ ++ int ret; ++ ++ ret = platform_driver_register(&sdhci_hisi_driver); ++ if (ret) ++ return ret; ++ ++ ret = mci_proc_init(); ++ if (ret) ++ platform_driver_unregister(&sdhci_hisi_driver); ++ ++ return ret; ++} ++ ++static void __exit sdhci_hisi_exit(void) ++{ ++ mci_proc_shutdown(); ++ ++ platform_driver_unregister(&sdhci_hisi_driver); ++} ++ ++module_init(sdhci_hisi_init); ++module_exit(sdhci_hisi_exit); ++ ++MODULE_DESCRIPTION("SDHCI driver for hisi"); ++MODULE_AUTHOR("HiSilicon Technologies Co., Ltd.."); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c +index 7d275e7..db5f38f 100644 +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c +@@ -76,8 +76,8 @@ static void sdhci_dumpregs(struct sdhci_host *host) + pr_err(DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n", + sdhci_readl(host, SDHCI_INT_ENABLE), + sdhci_readl(host, SDHCI_SIGNAL_ENABLE)); +- pr_err(DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n", +- sdhci_readw(host, SDHCI_ACMD12_ERR), ++ pr_err(DRIVER_NAME ": ACMD err: 0x%08x | Slot int: 0x%08x\n", ++ sdhci_readw(host, SDHCI_AUTO_CMD_ERR), + sdhci_readw(host, SDHCI_SLOT_INT_STATUS)); + pr_err(DRIVER_NAME ": Caps: 0x%08x | Caps_1: 0x%08x\n", + sdhci_readl(host, SDHCI_CAPABILITIES), +@@ -227,7 +227,7 @@ static void sdhci_init(struct sdhci_host *host, int soft) + SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | + SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC | + SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END | +- SDHCI_INT_RESPONSE; ++ SDHCI_INT_RESPONSE | SDHCI_INT_ACMD_ERR; + + if (host->tuning_mode == SDHCI_TUNING_MODE_2 || + host->tuning_mode == SDHCI_TUNING_MODE_3) +@@ -240,11 +240,33 @@ static void sdhci_init(struct sdhci_host *host, int soft) + /* force clock reconfiguration */ + host->clock = 0; + mmc->ops->set_ios(mmc, &mmc->ios); ++ } else { ++ unsigned short ctrl; ++ unsigned int mbiiu_ctrl, val; ++ ++ ctrl = sdhci_readw(host, SDHCI_MSHC_CTRL); ++ ctrl &= ~SDHCI_CMD_CONFLIT_CHECK; ++ sdhci_writew(host, ctrl, SDHCI_MSHC_CTRL); ++ ++ mbiiu_ctrl = sdhci_readl(host, SDHCI_AXI_MBIIU_CTRL); ++ mbiiu_ctrl &= ~(SDHCI_GM_WR_OSRC_LMT_MASK ++ | SDHCI_GM_RD_OSRC_LMT_MASK); ++ mbiiu_ctrl |= (SDHCI_GM_WR_OSRC_LMT_SEL(3) ++ | SDHCI_GM_RD_OSRC_LMT_SEL(3)); ++ sdhci_writel(host, mbiiu_ctrl, SDHCI_AXI_MBIIU_CTRL); ++ ++ val = sdhci_readl(host, SDHCI_MULTI_CYCLE); ++ val &= ~(SDHCI_DATA_DLY_EN | SDHCI_CMD_DLY_EN); ++ sdhci_writel(host, val, SDHCI_MULTI_CYCLE); ++ host->error_count = 0; + } + } + + static void sdhci_reinit(struct sdhci_host *host) + { ++ if (host->ops->pre_init) ++ host->ops->pre_init(host); ++ + sdhci_init(host, 0); + sdhci_enable_card_detection(host); + } +@@ -522,6 +544,58 @@ static void sdhci_adma_write_desc(struct sdhci_host *host, void *desc, + dma_desc->addr_hi = cpu_to_le32((u64)addr >> 32); + } + ++static void sdhci_write_cmd_table(u8 *desc, u32 reg, u32 attr) ++{ ++ __le32 *reg_addr = (__le32 __force *)(desc + 4); ++ __le32 *attr_addr = (__le32 __force *)desc; ++ ++ attr_addr[0] = cpu_to_le32(attr); ++ reg_addr[0] = cpu_to_le32(reg); ++} ++ ++static void sdhci_write_adma3_desc(struct sdhci_host *host, u8 *desc, ++ dma_addr_t addr, unsigned int attr) ++{ ++ __le32 *attr_addr = (__le32 __force *)desc; ++ ++ attr_addr[0] = cpu_to_le32(attr); ++ ++ if (host->flags & SDHCI_USE_64_BIT_DMA) { ++ __le64 *cmd_ddr = (__le64 __force *)(desc + 4); ++ cmd_ddr[0] = cpu_to_le64(addr); ++ } else { ++ __le32 *cmd_ddr = (__le32 __force *)(desc + 4); ++ cmd_ddr[0] = cpu_to_le32(addr); ++ } ++} ++ ++static void sdhci_prep_adma3_desc(struct sdhci_host *host, ++ struct mmc_command *cmd, int flags) ++{ ++ struct mmc_data *data = cmd->data; ++ unsigned int ctrl_2, cmd_xfer, blksz; ++ u16 mode; ++ ++ blksz = SDHCI_MAKE_BLKSZ(0, data->blksz); ++ mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); ++ cmd_xfer = (SDHCI_MAKE_CMD(cmd->opcode, flags) << 16) | mode; ++ ++ sdhci_write_cmd_table(host->cmd_table, data->blocks, ADMA3_CMD_VALID); ++ sdhci_write_cmd_table(host->cmd_table + 0x8, blksz, ADMA3_CMD_VALID); ++ sdhci_write_cmd_table(host->cmd_table + 0x10, cmd->arg, ADMA3_CMD_VALID); ++ sdhci_write_cmd_table(host->cmd_table + 0x18, cmd_xfer, ADMA3_CMD_VALID); ++ sdhci_adma_write_desc(host, host->cmd_table + 0x20, ++ host->adma_addr, 0x0, ADMA2_LINK_VALID); ++ ++ sdhci_write_adma3_desc(host, host->adma3_table, host->cmd_addr, ADMA3_END); ++ ++ ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); ++ ctrl_2 |= SDHCI_CTRL_HOST_VER4_ENABLE; ++ if (host->flags & SDHCI_USE_64_BIT_DMA) ++ ctrl_2 |= SDHCI_CTRL_ADDRESSING_64BIT; ++ sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); ++} ++ + static void sdhci_adma_mark_end(void *desc) + { + struct sdhci_adma2_64_desc *dma_desc = desc; +@@ -589,6 +663,17 @@ static void sdhci_adma_table_pre(struct sdhci_host *host, + BUG_ON(len > 65536); + + if (len) { ++ /* work around for buffer across 128M boundary, split the buffer */ ++ if (((addr & (SDHCI_DMA_BOUNDARY_SIZE - 1)) + len) > ++ SDHCI_DMA_BOUNDARY_SIZE) { ++ offset = SDHCI_DMA_BOUNDARY_SIZE - ++ (addr & (SDHCI_DMA_BOUNDARY_SIZE - 1)); ++ sdhci_adma_write_desc(host, desc, addr, offset, ++ ADMA2_TRAN_VALID); ++ desc += host->desc_sz; ++ addr += offset; ++ len -= offset; ++ } + /* tran, valid */ + sdhci_adma_write_desc(host, desc, addr, len, + ADMA2_TRAN_VALID); +@@ -855,10 +940,14 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) + ctrl &= ~SDHCI_CTRL_DMA_MASK; + if ((host->flags & SDHCI_REQ_USE_DMA) && + (host->flags & SDHCI_USE_ADMA)) { +- if (host->flags & SDHCI_USE_64_BIT_DMA) +- ctrl |= SDHCI_CTRL_ADMA64; +- else +- ctrl |= SDHCI_CTRL_ADMA32; ++ if (host->flags & SDHCI_USE_ADMA3) ++ ctrl |= SDHCI_CTRL_ADMA3; ++ else { ++ if (host->flags & SDHCI_USE_64_BIT_DMA) ++ ctrl |= SDHCI_CTRL_ADMA64; ++ else ++ ctrl |= SDHCI_CTRL_ADMA32; ++ } + } else { + ctrl |= SDHCI_CTRL_SDMA; + } +@@ -1121,7 +1210,8 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) + + sdhci_prepare_data(host, cmd); + +- sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); ++ if (!(host->flags & SDHCI_USE_ADMA3) || !cmd->data) ++ sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); + + sdhci_set_transfer_mode(host, cmd); + +@@ -1152,7 +1242,15 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) + cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200) + flags |= SDHCI_CMD_DATA; + +- sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); ++ if (host->flags & SDHCI_USE_ADMA3 && cmd->data) { ++ sdhci_prep_adma3_desc(host, cmd, flags); ++ ++ sdhci_writel(host, (u32)host->adma3_addr, SDHCI_ADMA3_ID_ADDR_LOW); ++ if (host->flags & SDHCI_USE_64_BIT_DMA) ++ sdhci_writel(host, (u32)((u64)host->adma3_addr >> 32), ++ SDHCI_ADMA3_ID_ADDR_HI); ++ } else ++ sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); + } + EXPORT_SYMBOL_GPL(sdhci_send_command); + +@@ -1710,7 +1808,9 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + } + + /* Re-enable SD Clock */ +- host->ops->set_clock(host, host->clock); ++ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); ++ clk |= SDHCI_CLOCK_CARD_EN; ++ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); + } else + sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); + +@@ -1846,6 +1946,9 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, + u16 ctrl; + int ret; + ++ if (host->ops->start_signal_voltage_switch) ++ return host->ops->start_signal_voltage_switch(host, ios); ++ + /* + * Signal Voltage Switching is only applicable for Host Controllers + * v3.00 and above. +@@ -2370,6 +2473,9 @@ static bool sdhci_request_done(struct sdhci_host *host) + host->pending_reset = false; + } + ++ if (mrq->data && mrq->data->error && !host->is_tuning) ++ host->error_count++; ++ + if (!sdhci_has_requests(host)) + sdhci_led_deactivate(host); + +@@ -2460,17 +2566,29 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) + */ + if (host->pending_reset) + return; +- pr_err("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n", ++ /*pr_err("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n", + mmc_hostname(host->mmc), (unsigned)intmask); +- sdhci_dumpregs(host); ++ sdhci_dumpregs(host);*/ + return; + } + + if (intmask & (SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | +- SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) { ++ SDHCI_INT_END_BIT | SDHCI_INT_INDEX | SDHCI_INT_ACMD_ERR)) { + if (intmask & SDHCI_INT_TIMEOUT) + host->cmd->error = -ETIMEDOUT; +- else ++ else if (intmask & SDHCI_INT_ACMD_ERR) { ++ u16 acmd_stat = sdhci_readw(host, SDHCI_AUTO_CMD_ERR); ++ ++ if (acmd_stat & (SDHCI_AUTO_CMD12_NOT_EXEC | ++ SDHCI_AUTO_CMD_INDEX_ERR | ++ SDHCI_AUTO_CMD12_NOT_ISSUED)) ++ host->cmd->error = -EIO; ++ else if (acmd_stat & SDHCI_AUTO_CMD_TIMEOUT_ERR) ++ host->cmd->error = -ETIMEDOUT; ++ else ++ host->cmd->error = -EILSEQ; ++ ++ } else + host->cmd->error = -EILSEQ; + + /* +@@ -3093,7 +3211,7 @@ int sdhci_setup_host(struct sdhci_host *host) + + override_timeout_clk = host->timeout_clk; + +- if (host->version > SDHCI_SPEC_300) { ++ if (host->version > SDHCI_SPEC_420) { + pr_err("%s: Unknown controller version (%d). You may experience problems.\n", + mmc_hostname(mmc), host->version); + } +@@ -3121,6 +3239,15 @@ int sdhci_setup_host(struct sdhci_host *host) + host->flags &= ~SDHCI_USE_ADMA; + } + ++ if ((host->version >= SDHCI_SPEC_400) && ++ (host->caps1 & SDHCI_CAN_DO_ADMA3)) ++ host->flags |= SDHCI_USE_ADMA3 | SDHCI_HOST_VER4_ENABLE; ++ ++ if ((host->quirks2 & SDHCI_QUIRK2_BROKEN_ADMA3) && ++ (host->flags & SDHCI_USE_ADMA3)) { ++ DBG("Disabling ADMA3 as it is marked broken\n"); ++ host->flags &= ~(SDHCI_USE_ADMA3 | SDHCI_HOST_VER4_ENABLE); ++ } + /* + * It is assumed that a 64-bit capable device has set a 64-bit DMA mask + * and *must* do 64-bit DMA. A driver has the opportunity to change +@@ -3161,14 +3288,14 @@ int sdhci_setup_host(struct sdhci_host *host) + * all multipled by the descriptor size. + */ + if (host->flags & SDHCI_USE_64_BIT_DMA) { +- host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) * +- SDHCI_ADMA2_64_DESC_SZ; +- host->desc_sz = SDHCI_ADMA2_64_DESC_SZ; +- } else { +- host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) * +- SDHCI_ADMA2_32_DESC_SZ; ++ if (host->flags & SDHCI_HOST_VER4_ENABLE) ++ host->desc_sz = 16; ++ else ++ host->desc_sz = SDHCI_ADMA2_64_DESC_SZ; ++ } else + host->desc_sz = SDHCI_ADMA2_32_DESC_SZ; +- } ++ ++ host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) * host->desc_sz; + + host->align_buffer_sz = SDHCI_MAX_SEGS * SDHCI_ADMA2_ALIGN; + buf = dma_alloc_coherent(mmc_dev(mmc), host->align_buffer_sz + +@@ -3191,6 +3318,36 @@ int sdhci_setup_host(struct sdhci_host *host) + host->adma_table = buf + host->align_buffer_sz; + host->adma_addr = dma + host->align_buffer_sz; + } ++ ++ if (!(host->flags & SDHCI_USE_ADMA)) ++ host->flags &= ~SDHCI_USE_ADMA3; ++ ++ if (host->flags & SDHCI_USE_ADMA3) { ++#define MAX_CMD_NUM 32 ++#define SDHCI_CMD_DESC_SZ 16 ++ if (host->flags & SDHCI_USE_64_BIT_DMA) ++ host->adma3_desc_sz = SDHCI_ADMA3_64_DESC_SZ; ++ else ++ host->adma3_desc_sz = SDHCI_ADMA3_32_DESC_SZ; ++ ++ host->adma3_table_sz = MAX_CMD_NUM * host->adma3_desc_sz; ++ host->cmd_table_sz = MAX_CMD_NUM * ++ (SDHCI_CMD_DESC_SZ + 16); ++ buf = dma_alloc_coherent(mmc_dev(mmc), host->adma3_table_sz + ++ host->cmd_table_sz, &dma, GFP_KERNEL); ++ if (!buf) { ++ pr_warn("%s: Unable to allocate ADMA3 buffers - falling back to standard DMA\n", ++ mmc_hostname(mmc)); ++ host->flags &= ~SDHCI_USE_ADMA3; ++ } else { ++ host->adma3_table = buf; ++ host->adma3_addr = dma; ++ ++ host->cmd_table = buf + host->adma3_desc_sz; ++ host->cmd_addr = dma + host->adma3_desc_sz; ++ } ++ } ++ + } + + /* +@@ -3557,6 +3714,14 @@ int sdhci_setup_host(struct sdhci_host *host) + host->adma_table = NULL; + host->align_buffer = NULL; + ++ if (host->adma3_table) ++ dma_free_coherent(mmc_dev(mmc), host->adma3_table_sz + ++ host->cmd_table_sz, host->adma3_table, ++ host->adma3_addr); ++ ++ host->adma3_table = NULL; ++ host->cmd_table = NULL; ++ + return ret; + } + EXPORT_SYMBOL_GPL(sdhci_setup_host); +@@ -3607,6 +3772,7 @@ int __sdhci_add_host(struct sdhci_host *host) + + pr_info("%s: SDHCI controller on %s [%s] using %s\n", + mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), ++ (host->flags & SDHCI_USE_ADMA3) ? "ADMA3" : + (host->flags & SDHCI_USE_ADMA) ? + (host->flags & SDHCI_USE_64_BIT_DMA) ? "ADMA 64-bit" : "ADMA" : + (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO"); +@@ -3635,6 +3801,14 @@ int __sdhci_add_host(struct sdhci_host *host) + host->adma_table = NULL; + host->align_buffer = NULL; + ++ if (host->adma3_table) ++ dma_free_coherent(mmc_dev(mmc), host->adma3_table_sz + ++ host->cmd_table_sz, host->adma3_table, ++ host->adma3_addr); ++ ++ host->adma3_table = NULL; ++ host->cmd_table = NULL; ++ + return ret; + } + EXPORT_SYMBOL_GPL(__sdhci_add_host); +@@ -3698,6 +3872,14 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) + + host->adma_table = NULL; + host->align_buffer = NULL; ++ ++ if (host->adma3_table) ++ dma_free_coherent(mmc_dev(mmc), host->adma3_table_sz + ++ host->cmd_table_sz, host->adma3_table, ++ host->adma3_addr); ++ ++ host->adma3_table = NULL; ++ host->cmd_table = NULL; + } + + EXPORT_SYMBOL_GPL(sdhci_remove_host); +diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h +index 2570455..4475761 100644 +--- a/drivers/mmc/host/sdhci.h ++++ b/drivers/mmc/host/sdhci.h +@@ -84,6 +84,7 @@ + #define SDHCI_CTRL_ADMA1 0x08 + #define SDHCI_CTRL_ADMA32 0x10 + #define SDHCI_CTRL_ADMA64 0x18 ++#define SDHCI_CTRL_ADMA3 0x18 + #define SDHCI_CTRL_8BITBUS 0x20 + #define SDHCI_CTRL_CDTEST_INS 0x40 + #define SDHCI_CTRL_CDTEST_EN 0x80 +@@ -108,6 +109,7 @@ + #define SDHCI_DIV_MASK_LEN 8 + #define SDHCI_DIV_HI_MASK 0x300 + #define SDHCI_PROG_CLOCK_MODE 0x0020 ++#define SDHCI_CLOCK_PLL_EN 0x0008 + #define SDHCI_CLOCK_CARD_EN 0x0004 + #define SDHCI_CLOCK_INT_STABLE 0x0002 + #define SDHCI_CLOCK_INT_EN 0x0001 +@@ -132,6 +134,7 @@ + #define SDHCI_INT_CARD_REMOVE 0x00000080 + #define SDHCI_INT_CARD_INT 0x00000100 + #define SDHCI_INT_RETUNE 0x00001000 ++#define SDHCI_INT_CQE 0x00004000 + #define SDHCI_INT_ERROR 0x00008000 + #define SDHCI_INT_TIMEOUT 0x00010000 + #define SDHCI_INT_CRC 0x00020000 +@@ -141,14 +144,16 @@ + #define SDHCI_INT_DATA_CRC 0x00200000 + #define SDHCI_INT_DATA_END_BIT 0x00400000 + #define SDHCI_INT_BUS_POWER 0x00800000 +-#define SDHCI_INT_ACMD12ERR 0x01000000 ++#define SDHCI_INT_ACMD_ERR 0x01000000 + #define SDHCI_INT_ADMA_ERROR 0x02000000 + + #define SDHCI_INT_NORMAL_MASK 0x00007FFF + #define SDHCI_INT_ERROR_MASK 0xFFFF8000 + + #define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \ +- SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX) ++ SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX | \ ++ SDHCI_INT_ACMD_ERR) ++ + #define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \ + SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ + SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ +@@ -156,7 +161,13 @@ + SDHCI_INT_BLK_GAP) + #define SDHCI_INT_ALL_MASK ((unsigned int)-1) + +-#define SDHCI_ACMD12_ERR 0x3C ++#define SDHCI_AUTO_CMD_ERR 0x3C ++#define SDHCI_AUTO_CMD12_NOT_EXEC 0x0001 ++#define SDHCI_AUTO_CMD_TIMEOUT_ERR 0x0002 ++#define SDHCI_AUTO_CMD_CRC_ERR 0x0004 ++#define SDHCI_AUTO_CMD_ENDBIT_ERR 0x0008 ++#define SDHCI_AUTO_CMD_INDEX_ERR 0x0010 ++#define SDHCI_AUTO_CMD12_NOT_ISSUED 0x0080 + + #define SDHCI_HOST_CONTROL2 0x3E + #define SDHCI_CTRL_UHS_MASK 0x0007 +@@ -165,7 +176,7 @@ + #define SDHCI_CTRL_UHS_SDR50 0x0002 + #define SDHCI_CTRL_UHS_SDR104 0x0003 + #define SDHCI_CTRL_UHS_DDR50 0x0004 +-#define SDHCI_CTRL_HS400 0x0005 /* Non-standard */ ++#define SDHCI_CTRL_HS400 0x0007 /* Non-standard */ + #define SDHCI_CTRL_VDD_180 0x0008 + #define SDHCI_CTRL_DRV_TYPE_MASK 0x0030 + #define SDHCI_CTRL_DRV_TYPE_B 0x0000 +@@ -174,6 +185,9 @@ + #define SDHCI_CTRL_DRV_TYPE_D 0x0030 + #define SDHCI_CTRL_EXEC_TUNING 0x0040 + #define SDHCI_CTRL_TUNED_CLK 0x0080 ++#define SDHCI_CTRL_HOST_VER4_ENABLE 0x1000 ++#define SDHCI_CTRL_ADDRESSING_64BIT 0x2000 ++#define SDHCI_CTRL_ASYNC_INT_ENABLE 0x4000 + #define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000 + + #define SDHCI_CAPABILITIES 0x40 +@@ -195,6 +209,7 @@ + #define SDHCI_CAN_VDD_300 0x02000000 + #define SDHCI_CAN_VDD_180 0x04000000 + #define SDHCI_CAN_64BIT 0x10000000 ++#define SDHCI_CAN_ASYNC_INT 0x20000000 + + #define SDHCI_SUPPORT_SDR50 0x00000001 + #define SDHCI_SUPPORT_SDR104 0x00000002 +@@ -209,6 +224,7 @@ + #define SDHCI_RETUNING_MODE_SHIFT 14 + #define SDHCI_CLOCK_MUL_MASK 0x00FF0000 + #define SDHCI_CLOCK_MUL_SHIFT 16 ++#define SDHCI_CAN_DO_ADMA3 0x08000000 + #define SDHCI_SUPPORT_HS400 0x80000000 /* Non-standard */ + + #define SDHCI_CAPABILITIES_1 0x44 +@@ -250,6 +266,9 @@ + #define SDHCI_PRESET_SDCLK_FREQ_MASK 0x3FF + #define SDHCI_PRESET_SDCLK_FREQ_SHIFT 0 + ++#define SDHCI_ADMA3_ID_ADDR_LOW 0x78 ++#define SDHCI_ADMA3_ID_ADDR_HI 0x7C ++ + #define SDHCI_SLOT_INT_STATUS 0xFC + + #define SDHCI_HOST_VERSION 0xFE +@@ -260,7 +279,36 @@ + #define SDHCI_SPEC_100 0 + #define SDHCI_SPEC_200 1 + #define SDHCI_SPEC_300 2 ++#define SDHCI_SPEC_400 3 ++#define SDHCI_SPEC_410 4 ++#define SDHCI_SPEC_420 5 ++ ++#define SDHCI_MSHC_CTRL 0x508 ++#define SDHCI_CMD_CONFLIT_CHECK 0x01 ++ ++#define SDHCI_AXI_MBIIU_CTRL 0x510 ++#define SDHCI_GM_WR_OSRC_LMT_MASK (0x7 << 24) ++#define SDHCI_GM_WR_OSRC_LMT_SEL(x) ((x) << 24) ++#define SDHCI_GM_RD_OSRC_LMT_MASK (0x7 << 16) ++#define SDHCI_GM_RD_OSRC_LMT_SEL(x) ((x) << 16) ++ ++#define SDHCI_EMMC_CTRL 0x52c ++#define SDHCI_CARD_IS_EMMC 0x00000001 ++#define SDHCI_ENH_STROBE_EN 0x00000100 + ++#define SDHCI_EMMC_HW_RESET 0x534 ++ ++#define SDHCI_AT_CTRL 0x540 ++#define SDHCI_SAMPLE_EN 0x00000010 ++ ++#define SDHCI_AT_STAT 0x544 ++#define SDHCI_PHASE_SEL_MASK 0x000000ff ++ ++#define SDHCI_MULTI_CYCLE 0x54c ++#define SDHCI_FOUND_EDGE (0x1 << 11) ++#define SDHCI_EDGE_DETECT_EN (0x1 << 8) ++#define SDHCI_DATA_DLY_EN (0x1 << 3) ++#define SDHCI_CMD_DLY_EN (0x1 << 2) + /* + * End of controller registers. + */ +@@ -273,6 +321,7 @@ + */ + #define SDHCI_DEFAULT_BOUNDARY_SIZE (512 * 1024) + #define SDHCI_DEFAULT_BOUNDARY_ARG (ilog2(SDHCI_DEFAULT_BOUNDARY_SIZE) - 12) ++#define SDHCI_DMA_BOUNDARY_SIZE (0x1 << 27) + + /* ADMA2 32-bit DMA descriptor size */ + #define SDHCI_ADMA2_32_DESC_SZ 8 +@@ -298,6 +347,12 @@ struct sdhci_adma2_32_desc { + /* ADMA2 64-bit DMA descriptor size */ + #define SDHCI_ADMA2_64_DESC_SZ 12 + ++/* ADMA3 32-bit DMA descriptor size */ ++#define SDHCI_ADMA3_32_DESC_SZ 8 ++ ++/* ADMA3 64-bit DMA descriptor size */ ++#define SDHCI_ADMA3_64_DESC_SZ 16 ++ + /* + * ADMA2 64-bit descriptor. Note 12-byte descriptor can't always be 8-byte + * aligned. +@@ -312,6 +367,9 @@ struct sdhci_adma2_64_desc { + #define ADMA2_TRAN_VALID 0x21 + #define ADMA2_NOP_END_VALID 0x3 + #define ADMA2_END 0x2 ++#define ADMA2_LINK_VALID 0x31 ++#define ADMA3_CMD_VALID 0x9 ++#define ADMA3_END 0x3b + + /* + * Maximum segments assuming a 512KiB maximum requisition size and a minimum +@@ -425,6 +483,7 @@ struct sdhci_host { + #define SDHCI_QUIRK2_ACMD23_BROKEN (1<<14) + /* Broken Clock divider zero in controller */ + #define SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN (1<<15) ++#define SDHCI_QUIRK2_BROKEN_ADMA3 (1<<16) + + int irq; /* Device IRQ */ + void __iomem *ioaddr; /* Mapped address */ +@@ -458,6 +517,8 @@ struct sdhci_host { + #define SDHCI_SIGNALING_330 (1<<14) /* Host is capable of 3.3V signaling */ + #define SDHCI_SIGNALING_180 (1<<15) /* Host is capable of 1.8V signaling */ + #define SDHCI_SIGNALING_120 (1<<16) /* Host is capable of 1.2V signaling */ ++#define SDHCI_USE_ADMA3 (1<<17) /* Host is ADMA3 capable */ ++#define SDHCI_HOST_VER4_ENABLE (1<<18) /* Host version 4 enable */ + + unsigned int version; /* SDHCI spec. version */ + +@@ -486,14 +547,21 @@ struct sdhci_host { + + void *adma_table; /* ADMA descriptor table */ + void *align_buffer; /* Bounce buffer */ ++ void *adma3_table; /* ADMA3 integrated descriptor table */ ++ void *cmd_table; /* ADMA3 command descriptor table */ + + size_t adma_table_sz; /* ADMA descriptor table size */ + size_t align_buffer_sz; /* Bounce buffer size */ ++ size_t adma3_table_sz; /* ADMA3 integrated descriptor table size */ ++ size_t cmd_table_sz; /* ADMA3 command descriptor table size */ + + dma_addr_t adma_addr; /* Mapped ADMA descr. table */ + dma_addr_t align_addr; /* Mapped bounce buffer */ ++ dma_addr_t adma3_addr; /* Mapped ADMA3 integrated descr. table */ ++ dma_addr_t cmd_addr; /* Mapped ADMA3 command descr. table */ + + unsigned int desc_sz; /* ADMA descriptor size */ ++ unsigned int adma3_desc_sz; /* ADMA3 integrated descriptor size */ + + struct tasklet_struct finish_tasklet; /* Tasklet structures */ + +@@ -525,6 +593,8 @@ struct sdhci_host { + #define SDHCI_TUNING_MODE_2 1 + #define SDHCI_TUNING_MODE_3 2 + ++ unsigned int is_tuning; ++ unsigned int error_count; + unsigned long private[0] ____cacheline_aligned; + }; + +@@ -564,6 +634,9 @@ struct sdhci_ops { + struct mmc_card *card, + unsigned int max_dtr, int host_drv, + int card_drv, int *drv_type); ++ int (*start_signal_voltage_switch)(struct sdhci_host *host, ++ struct mmc_ios *ios); ++ void (*pre_init)(struct sdhci_host *host); + }; + + #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS +diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile +index 99bb9a1..f46b1cc 100644 +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile +@@ -30,7 +30,7 @@ obj-$(CONFIG_MTD_SWAP) += mtdswap.o + nftl-objs := nftlcore.o nftlmount.o + inftl-objs := inftlcore.o inftlmount.o + ++obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/ + obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/ + +-obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/ + obj-$(CONFIG_MTD_UBI) += ubi/ +diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile +index 7912d3a..9e7da47 100644 +--- a/drivers/mtd/devices/Makefile ++++ b/drivers/mtd/devices/Makefile +@@ -18,5 +18,4 @@ obj-$(CONFIG_MTD_BCM47XXSFLASH) += bcm47xxsflash.o + obj-$(CONFIG_MTD_ST_SPI_FSM) += st_spi_fsm.o + obj-$(CONFIG_MTD_POWERNV_FLASH) += powernv_flash.o + +- + CFLAGS_docg3.o += -I$(src) +diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig +index b254090..5f4768c 100644 +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -569,4 +569,31 @@ config MTD_NAND_MTK + Enables support for NAND controller on MTK SoCs. + This controller is found on mt27xx, mt81xx, mt65xx SoCs. + ++config MTD_SPI_NAND_HISI_BVT ++ tristate "Support for SPI NAND controller on Hisilicon SoCs" ++ depends on MTD_NAND ++ help ++ Enables support for the SPI NAND device drivers. ++ ++config HISI_NAND_ECC_STATUS_REPORT ++ tristate "Report the ecc status to MTD for HiSilicon Nand Driver" ++ depends on MFD_HISI_FMC ++ default n ++ help ++ Flash Memory Controller V100 reports the ecc status include ECC error ++ and ECC corrected to MTD to monitor the aging of devices. ++ ++config HISI_NAND_FS_MAY_NO_YAFFS2 ++ bool "Remove the restraintion of 16bit ecc type on yaffs2 to HiSilicon" ++ depends on MFD_HISI_FMC ++ default n ++ help ++ The ecc type: 16bit is limited by the HiSilicon flash memory controller, ++ as the yaffs2 tag of hisi rootfs limits the min size of CTRL len is 28. ++ ++source "drivers/mtd/nand/hifmc100/Kconfig" ++source "drivers/mtd/nand/hisnfc100/Kconfig" ++source "drivers/mtd/nand/hinfc610/Kconfig" ++source "drivers/mtd/nand/hifmc100_nand/Kconfig" ++ + endif # MTD_NAND +diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile +index cafde6f..84f9a3f 100644 +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -8,6 +8,10 @@ obj-$(CONFIG_MTD_NAND_BCH) += nand_bch.o + obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o + obj-$(CONFIG_MTD_SM_COMMON) += sm_common.o + ++obj-$(CONFIG_MTD_NAND_HIFMC100) += hifmc100_nand/ ++obj-$(CONFIG_MTD_SPI_NAND_HIFMC100) += hifmc100/ ++obj-$(CONFIG_MTD_NAND_HISNFC100) += hisnfc100/ ++obj-$(CONFIG_MTD_NAND_HINFC610) += hinfc610/ + obj-$(CONFIG_MTD_NAND_CAFE) += cafe_nand.o + obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o + obj-$(CONFIG_MTD_NAND_DENALI) += denali.o +@@ -59,4 +63,4 @@ obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/ + obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o + obj-$(CONFIG_MTD_NAND_MTK) += mtk_nand.o mtk_ecc.o + +-nand-objs := nand_base.o nand_bbt.o nand_timings.o ++nand-objs := nand_base.o nand_bbt.o nand_timings.o hinfc_gen.o hinfc_spl_ids.o match_table.o +diff --git a/drivers/mtd/nand/hifmc100/Kconfig b/drivers/mtd/nand/hifmc100/Kconfig +new file mode 100644 +index 0000000..5b15bc8 +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100/Kconfig +@@ -0,0 +1,17 @@ ++# ++# hisilicon flash memory controller SPI nand device driver version 100 ++# drivers/mtd/nand/hifmc100/Kconfig ++# add by hisilicon 2017.8.7 ++# ++ ++config MTD_SPI_NAND_HIFMC100 ++ bool "Hisilicon Flash Memory Controller v100 SPI Nand devices support" ++ depends on MFD_HISI_FMC && MTD_SPI_NAND_HISI_BVT ++ select MISC_FILESYSTEMS ++ select MTD_BLOCK ++ select YAFFS_FS ++ select YAFFS_YAFFS2 ++ help ++ Hisilicon Flash Memory Controller version 100 is called hifmc100 for ++ short. The controller driver support registers and DMA transfers ++ while reading or writing the SPI nand flash. +diff --git a/drivers/mtd/nand/hifmc100/Makefile b/drivers/mtd/nand/hifmc100/Makefile +new file mode 100644 +index 0000000..b1fda5d +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100/Makefile +@@ -0,0 +1,26 @@ ++# ++# The Flash Memory Controller v100 Device Driver for hisilicon ++# ++# Copyright (c) 2016-2017 HiSilicon Technologies 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. ++# ++# 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, see . ++# ++# ++ ++# ++# drivers/mtd/nand/hifmc100/Makefile ++# ++ ++obj-y += hifmc_spi_nand_ids.o ++obj-y += hifmc100.o hifmc100_os.o +diff --git a/drivers/mtd/nand/hifmc100/hifmc100.c b/drivers/mtd/nand/hifmc100/hifmc100.c +new file mode 100644 +index 0000000..c2f882f +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100/hifmc100.c +@@ -0,0 +1,1175 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../hinfc_gen.h" ++#include "hifmc100_os.h" ++#include "hifmc100.h" ++#include ++ ++/*****************************************************************************/ ++static void hifmc100_switch_to_spi_nand(struct hifmc_host *host) ++{ ++ int reg; ++ ++ reg = hifmc_readl(host, FMC_CFG); ++ reg &= ~FLASH_TYPE_SEL_MASK; ++ reg |= FMC_CFG_FLASH_SEL(FLASH_TYPE_SPI_NAND); ++ hifmc_writel(host, FMC_CFG, reg); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_operation_config(struct hifmc_host *host, int op) ++{ ++ int ret, clkrate = 0; ++ struct hifmc_spi *spi = host->spi; ++ ++ hifmc100_switch_to_spi_nand(host); ++ clk_prepare_enable(host->clk); ++ switch (op) { ++ case OP_STYPE_WRITE: ++ clkrate = min((u_long)host->clkrate, ++ (u_long)CLK_FMC_TO_CRG_MHZ(spi->write->clock)); ++ break; ++ case OP_STYPE_READ: ++ clkrate = min((u_long)host->clkrate, ++ (u_long)CLK_FMC_TO_CRG_MHZ(spi->read->clock)); ++ break; ++ case OP_STYPE_ERASE: ++ clkrate = min((u_long)host->clkrate, ++ (u_long)CLK_FMC_TO_CRG_MHZ(spi->erase->clock)); ++ break; ++ default: ++ break; ++ } ++ ++ ret = clk_set_rate(host->clk, clkrate); ++ if (WARN_ON(ret)) ++ pr_err("clk_set_rate failed: %d\n", ret); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_write(struct hifmc_host *host) ++{ ++ unsigned char pages_per_block_shift; ++ unsigned int reg, block_num, block_num_h, page_num; ++ struct hifmc_spi *spi = host->spi; ++ struct nand_chip *chip = host->chip; ++#ifdef HIFMC100_SPI_NAND_SUPPORT_REG_WRITE ++ const char *op = "Reg"; ++#else ++ const char *op = "Dma"; ++#endif ++ ++ if (WR_DBG) ++ pr_info("\n"); ++ FMC_PR(WR_DBG, "*-Start send %s page write command\n", op); ++ ++ mutex_lock(host->lock); ++ hifmc100_operation_config(host, OP_STYPE_WRITE); ++ ++ reg = spi->driver->wait_ready(spi); ++ if (reg) { ++ DB_MSG("Error: %s program wait ready failed! status: %#x\n", ++ op, reg); ++ goto end; ++ } ++ ++ reg = spi->driver->write_enable(spi); ++ if (reg) { ++ DB_MSG("Error: %s program write enable failed! reg: %#x\n", ++ op, reg); ++ goto end; ++ } ++ ++ reg = FMC_INT_CLR_ALL; ++ hifmc_writel(host, FMC_INT_CLR, reg); ++ FMC_PR(WR_DBG, "|-Set INT_CLR[%#x]%#x\n", FMC_INT_CLR, reg); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) ++ | OP_CFG_MEM_IF_TYPE(spi->write->iftype) ++ | OP_CFG_OEN_EN; ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(WR_DBG, "|-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ pages_per_block_shift = chip->phys_erase_shift - chip->page_shift; ++ block_num = host->addr_value[1] >> pages_per_block_shift; ++ block_num_h = block_num >> REG_CNT_HIGH_BLOCK_NUM_SHIFT; ++ reg = FMC_ADDRH_SET(block_num_h); ++ hifmc_writel(host, FMC_ADDRH, reg); ++ FMC_PR(WR_DBG, "|-Set ADDRH[%#x]%#x\n", FMC_ADDRH, reg); ++ ++ page_num = host->addr_value[1] - (block_num << pages_per_block_shift); ++ reg = ((block_num & REG_CNT_BLOCK_NUM_MASK) << REG_CNT_BLOCK_NUM_SHIFT) ++ | ((page_num & REG_CNT_PAGE_NUM_MASK) << REG_CNT_PAGE_NUM_SHIFT); ++ hifmc_writel(host, FMC_ADDRL, reg); ++ FMC_PR(WR_DBG, "|-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg); ++ ++ *host->epm = 0x0000; ++ ++#ifndef HIFMC100_SPI_NAND_SUPPORT_REG_WRITE ++ reg = host->dma_buffer; ++ hifmc_writel(host, FMC_DMA_SADDR_D0, reg); ++ FMC_PR(WR_DBG, "|-Set DMA_SADDR_D[0x40]%#x\n", reg); ++ ++#ifdef CONFIG_64BIT ++ reg = (host->dma_buffer & FMC_DMA_SADDRH_MASK) >> 32; ++ hifmc_writel(host, FMC_DMA_SADDRH_D0, reg); ++ FMC_PR(WR_DBG, "\t|-Set DMA_SADDRH_D0[%#x]%#x\n", FMC_DMA_SADDRH_D0, reg); ++#endif ++ ++ reg = host->dma_oob; ++ hifmc_writel(host, FMC_DMA_SADDR_OOB, reg); ++ FMC_PR(WR_DBG, "|-Set DMA_SADDR_OOB[%#x]%#x\n", FMC_DMA_SADDR_OOB, reg); ++#ifdef CONFIG_64BIT ++ reg = (host->dma_oob & FMC_DMA_SADDRH_MASK) >> 32; ++ hifmc_writel(host, FMC_DMA_SADDRH_OOB, reg); ++ FMC_PR(WR_DBG, "\t|-Set DMA_SADDRH_OOB[%#x]%#x\n", FMC_DMA_SADDRH_OOB, ++ reg); ++#endif ++#endif ++ ++ reg = OP_CTRL_WR_OPCODE(spi->write->cmd) ++#ifdef HIFMC100_SPI_NAND_SUPPORT_REG_WRITE ++ | OP_CTRL_DMA_OP(OP_TYPE_REG) ++#else ++ | OP_CTRL_DMA_OP(OP_TYPE_DMA) ++#endif ++ | OP_CTRL_RW_OP(RW_OP_WRITE) ++ | OP_CTRL_DMA_OP_READY; ++ hifmc_writel(host, FMC_OP_CTRL, reg); ++ FMC_PR(WR_DBG, "|-Set OP_CTRL[%#x]%#x\n", FMC_OP_CTRL, reg); ++ ++ FMC_DMA_WAIT_INT_FINISH(host); ++ ++end: ++ mutex_unlock(host->lock); ++ FMC_PR(WR_DBG, "*-End %s page program!\n", op); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_status(struct hifmc_host *host) ++{ ++ unsigned char status, addr = STATUS_ADDR; ++ struct hifmc_spi *spi = host->spi; ++ ++ if (host->cmd_op.l_cmd == NAND_CMD_GET_FEATURES) ++ addr = PROTECT_ADDR; ++ ++ status = spi_nand_feature_op(spi, GET_OP, addr, 0); ++ FMC_PR((ER_DBG || WR_DBG), "\t*-Get status[%#x]: %#x\n", addr, status); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_read(struct hifmc_host *host) ++{ ++ unsigned char pages_per_block_shift, only_oob = 0; ++ unsigned short wrap = 0; ++ unsigned int reg, block_num, block_num_h, page_num, addr_of = 0; ++ struct hifmc_spi *spi = host->spi; ++ struct nand_chip *chip = host->chip; ++#ifdef HIFMC100_SPI_NAND_SUPPORT_REG_READ ++ char *op = "Reg"; ++#else ++ char *op = "Dma"; ++#endif ++ ++ if (RD_DBG) ++ pr_info("\n"); ++ FMC_PR(RD_DBG, "\t*-Start %s page read\n", op); ++ ++ if ((host->addr_value[0] == host->cache_addr_value[0]) ++ && (host->addr_value[1] == host->cache_addr_value[1])) { ++ FMC_PR(RD_DBG, "\t*-%s read cache hit, addr[%#x %#x]\n", ++ op, host->addr_value[1], host->addr_value[0]); ++ return; ++ } ++ ++ mutex_lock(host->lock); ++ hifmc100_operation_config(host, OP_STYPE_READ); ++ ++ FMC_PR(RD_DBG, "\t|-Wait ready before %s page read\n", op); ++ reg = spi->driver->wait_ready(spi); ++ if (reg) { ++ DB_MSG("Error: %s read wait ready fail! reg: %#x\n", op, reg); ++ goto end; ++ } ++ ++ reg = FMC_INT_CLR_ALL; ++ hifmc_writel(host, FMC_INT_CLR, reg); ++ FMC_PR(RD_DBG, "\t|-Set INT_CLR[%#x]%#x\n", FMC_INT_CLR, reg); ++ ++ if (host->cmd_op.l_cmd == NAND_CMD_READOOB) { ++ only_oob = 1; ++ host->cmd_op.op_cfg = OP_CTRL_RD_OP_SEL(RD_OP_READ_OOB); ++ } else ++ host->cmd_op.op_cfg = OP_CTRL_RD_OP_SEL(RD_OP_READ_ALL_PAGE); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) ++ | OP_CFG_MEM_IF_TYPE(spi->read->iftype) ++ | OP_CFG_DUMMY_NUM(spi->read->dummy) ++ | OP_CFG_OEN_EN; ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(RD_DBG, "\t|-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ pages_per_block_shift = chip->phys_erase_shift - chip->page_shift; ++ block_num = host->addr_value[1] >> pages_per_block_shift; ++ block_num_h = block_num >> REG_CNT_HIGH_BLOCK_NUM_SHIFT; ++ ++ reg = FMC_ADDRH_SET(block_num_h); ++ hifmc_writel(host, FMC_ADDRH, reg); ++ FMC_PR(RD_DBG, "\t|-Set ADDRH[%#x]%#x\n", FMC_ADDRH, reg); ++ ++ page_num = host->addr_value[1] - (block_num << pages_per_block_shift); ++ if (only_oob) ++ switch (host->ecctype) { ++ case NAND_ECC_8BIT: ++ addr_of = REG_CNT_ECC_8BIT_OFFSET; ++ break; ++ case NAND_ECC_16BIT: ++ addr_of = REG_CNT_ECC_16BIT_OFFSET; ++ break; ++ case NAND_ECC_24BIT: ++ addr_of = REG_CNT_ECC_24BIT_OFFSET; ++ break; ++ case NAND_ECC_0BIT: ++ default: ++ break; ++ } ++ ++ reg = ((block_num & REG_CNT_BLOCK_NUM_MASK) << REG_CNT_BLOCK_NUM_SHIFT) ++ | ((page_num & REG_CNT_PAGE_NUM_MASK) << REG_CNT_PAGE_NUM_SHIFT) ++ | ((wrap & REG_CNT_WRAP_MASK) << REG_CNT_WRAP_SHIFT) ++ | (addr_of & REG_CNT_ECC_OFFSET_MASK); ++ hifmc_writel(host, FMC_ADDRL, reg); ++ FMC_PR(RD_DBG, "\t|-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg); ++ ++#ifndef HIFMC100_SPI_NAND_SUPPORT_REG_READ ++ reg = host->dma_buffer; ++ hifmc_writel(host, FMC_DMA_SADDR_D0, reg); ++ FMC_PR(RD_DBG, "\t|-Set DMA_SADDR_D0[%#x]%#x\n", FMC_DMA_SADDR_D0, reg); ++ ++#ifdef CONFIG_64BIT ++ reg = (host->dma_buffer & FMC_DMA_SADDRH_MASK) >> 32; ++ hifmc_writel(host, FMC_DMA_SADDRH_D0, reg); ++ FMC_PR(RD_DBG, "\t|-Set DMA_SADDRH_D0[%#x]%#x\n", FMC_DMA_SADDRH_D0, reg); ++#endif ++ ++ reg = host->dma_oob; ++ hifmc_writel(host, FMC_DMA_SADDR_OOB, reg); ++ FMC_PR(RD_DBG, "\t|-Set DMA_SADDR_OOB[%#x]%#x\n", FMC_DMA_SADDR_OOB, ++ reg); ++ ++#ifdef CONFIG_64BIT ++ reg = (host->dma_oob & FMC_DMA_SADDRH_MASK) >> 32; ++ hifmc_writel(host, FMC_DMA_SADDRH_OOB, reg); ++ FMC_PR(RD_DBG, "\t|-Set DMA_SADDRH_OOB[%#x]%#x\n", FMC_DMA_SADDRH_OOB, ++ reg); ++#endif ++#endif ++ ++ reg = OP_CTRL_RD_OPCODE(spi->read->cmd) | host->cmd_op.op_cfg ++#ifdef HIFMC100_SPI_NAND_SUPPORT_REG_READ ++ | OP_CTRL_DMA_OP(OP_TYPE_REG) ++#else ++ | OP_CTRL_DMA_OP(OP_TYPE_DMA) ++#endif ++ | OP_CTRL_RW_OP(RW_OP_READ) | OP_CTRL_DMA_OP_READY; ++ hifmc_writel(host, FMC_OP_CTRL, reg); ++ FMC_PR(RD_DBG, "\t|-Set OP_CTRL[%#x]%#x\n", FMC_OP_CTRL, reg); ++ ++ FMC_DMA_WAIT_INT_FINISH(host); ++ ++ host->cache_addr_value[0] = host->addr_value[0]; ++ host->cache_addr_value[1] = host->addr_value[1]; ++ ++end: ++ mutex_unlock(host->lock); ++ FMC_PR(RD_DBG, "\t*-End %s page read\n", op); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_erase(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ struct hifmc_spi *spi = host->spi; ++ ++ if (ER_DBG) ++ pr_info("\n"); ++ FMC_PR(ER_DBG, "\t*-Start send cmd erase!\n"); ++ ++ mutex_lock(host->lock); ++ hifmc100_operation_config(host, OP_STYPE_ERASE); ++ ++ reg = spi->driver->wait_ready(spi); ++ FMC_PR(ER_DBG, "\t|-Erase wait ready, reg: %#x\n", reg); ++ if (reg) { ++ DB_MSG("Error: Erase wait ready fail! status: %#x\n", reg); ++ goto end; ++ } ++ ++ reg = spi->driver->write_enable(spi); ++ if (reg) { ++ DB_MSG("Error: Erase write enable failed! reg: %#x\n", reg); ++ goto end; ++ } ++ ++ reg = FMC_INT_CLR_ALL; ++ hifmc_writel(host, FMC_INT_CLR, reg); ++ FMC_PR(ER_DBG, "\t|-Set INT_CLR[%#x]%#x\n", FMC_INT_CLR, reg); ++ ++ reg = spi->erase->cmd; ++ hifmc_writel(host, FMC_CMD, FMC_CMD_CMD1(reg)); ++ FMC_PR(ER_DBG, "\t|-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ reg = FMC_ADDRL_BLOCK_H_MASK(host->addr_value[1]) ++ | FMC_ADDRL_BLOCK_L_MASK(host->addr_value[0]); ++ hifmc_writel(host, FMC_ADDRL, reg); ++ FMC_PR(ER_DBG, "\t|-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) ++ | OP_CFG_MEM_IF_TYPE(spi->erase->iftype) ++ | OP_CFG_ADDR_NUM(STD_OP_ADDR_NUM) ++ | OP_CFG_DUMMY_NUM(spi->erase->dummy) ++ | OP_CFG_OEN_EN; ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(ER_DBG, "\t|-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ reg = FMC_OP_CMD1_EN ++ | FMC_OP_ADDR_EN ++ | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(ER_DBG, "\t|-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++end: ++ mutex_unlock(host->lock); ++ FMC_PR(ER_DBG, "\t*-End send cmd erase!\n"); ++} ++ ++/*****************************************************************************/ ++void hifmc100_ecc0_switch(struct hifmc_host *host, unsigned char op) ++{ ++ unsigned int config; ++#if EC_DBG ++ unsigned int cmp_cfg; ++ ++ config = hifmc_readl(host, FMC_CFG); ++ FMC_PR(EC_DBG, "\t *-Get CFG[%#x]%#x\n", FMC_CFG, config); ++ ++ if (op) ++ cmp_cfg = host->fmc_cfg; ++ else ++ cmp_cfg = host->fmc_cfg_ecc0; ++ ++ if (cmp_cfg != config) ++ DB_MSG("Warning: FMC config[%#x] is different.\n", ++ cmp_cfg); ++#endif ++ ++ if (op == ENABLE) ++ config = host->fmc_cfg_ecc0; ++ else if (op == DISABLE) ++ config = host->fmc_cfg; ++ else { ++ DB_MSG("Error: Invalid opcode: %d\n", op); ++ return; ++ } ++ ++ hifmc_writel(host, FMC_CFG, config); ++ FMC_PR(EC_DBG, "\t *-Set CFG[%#x]%#x\n", FMC_CFG, config); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_readid(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ FMC_PR(BT_DBG, "\t|*-Start send cmd read ID\n"); ++ ++ hifmc100_ecc0_switch(host, ENABLE); ++ ++ reg = FMC_CMD_CMD1(SPI_CMD_RDID); ++ hifmc_writel(host, FMC_CMD, reg); ++ FMC_PR(BT_DBG, "\t||-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ reg = READ_ID_ADDR; ++ hifmc_writel(host, FMC_ADDRL, reg); ++ FMC_PR(BT_DBG, "\t||-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) ++ | OP_CFG_ADDR_NUM(READ_ID_ADDR_NUM) ++ | OP_CFG_OEN_EN; ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(BT_DBG, "\t||-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ reg = FMC_DATA_NUM_CNT(MAX_SPI_NAND_ID_LEN); ++ hifmc_writel(host, FMC_DATA_NUM, reg); ++ FMC_PR(BT_DBG, "\t||-Set DATA_NUM[%#x]%#x\n", FMC_DATA_NUM, reg); ++ ++ reg = FMC_OP_CMD1_EN ++ | FMC_OP_ADDR_EN ++ | FMC_OP_READ_DATA_EN ++ | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(BT_DBG, "\t||-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ host->addr_cycle = 0x0; ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++ hifmc100_ecc0_switch(host, DISABLE); ++ ++ FMC_PR(BT_DBG, "\t|*-End read flash ID\n"); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_reset(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ FMC_PR(BT_DBG, "\t|*-Start send cmd reset\n"); ++ ++ reg = FMC_CMD_CMD1(SPI_CMD_RESET); ++ hifmc_writel(host, FMC_CMD, reg); ++ FMC_PR(BT_DBG, "\t||-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) | OP_CFG_OEN_EN; ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(BT_DBG, "\t||-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ reg = FMC_OP_CMD1_EN | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(BT_DBG, "\t||-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++ FMC_PR(BT_DBG, "\t|*-End send cmd reset\n"); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_host_init(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ FMC_PR(BT_DBG, "\t||*-Start SPI Nand host init\n"); ++ ++ reg = hifmc_readl(host, FMC_CFG); ++ if ((reg & FMC_CFG_OP_MODE_MASK) == FMC_CFG_OP_MODE_BOOT) { ++ reg |= FMC_CFG_OP_MODE(FMC_CFG_OP_MODE_NORMAL); ++ hifmc_writel(host, FMC_CFG, reg); ++ FMC_PR(BT_DBG, "\t|||-Set CFG[%#x]%#x\n", FMC_CFG, reg); ++ } ++ ++ host->fmc_cfg = reg; ++ host->fmc_cfg_ecc0 = (reg & ~ECC_TYPE_MASK) | ECC_TYPE_0BIT; ++ ++ reg = hifmc_readl(host, FMC_GLOBAL_CFG); ++ if (reg & FMC_GLOBAL_CFG_WP_ENABLE) { ++ reg &= ~FMC_GLOBAL_CFG_WP_ENABLE; ++ hifmc_writel(host, FMC_GLOBAL_CFG, reg); ++ } ++ ++ host->addr_cycle = 0; ++ host->addr_value[0] = 0; ++ host->addr_value[1] = 0; ++ host->cache_addr_value[0] = ~0; ++ host->cache_addr_value[1] = ~0; ++ ++ host->send_cmd_write = hifmc100_send_cmd_write; ++ host->send_cmd_status = hifmc100_send_cmd_status; ++ host->send_cmd_read = hifmc100_send_cmd_read; ++ host->send_cmd_erase = hifmc100_send_cmd_erase; ++ host->send_cmd_readid = hifmc100_send_cmd_readid; ++ host->send_cmd_reset = hifmc100_send_cmd_reset; ++#ifdef CONFIG_PM ++ host->suspend = hifmc100_suspend; ++ host->resume = hifmc100_resume; ++#endif ++ ++ reg = TIMING_CFG_TCSH(CS_HOLD_TIME) ++ | TIMING_CFG_TCSS(CS_SETUP_TIME) ++ | TIMING_CFG_TSHSL(CS_DESELECT_TIME); ++ hifmc_writel(host, FMC_SPI_TIMING_CFG, reg); ++ ++ reg = ALL_BURST_ENABLE; ++ hifmc_writel(host, FMC_DMA_AHB_CTRL, reg); ++ ++ FMC_PR(BT_DBG, "\t||*-End SPI Nand host init\n"); ++} ++ ++/*****************************************************************************/ ++static unsigned char hifmc100_read_byte(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ unsigned char value, ret_val = 0; ++ ++ if (host->cmd_op.l_cmd == NAND_CMD_READID) { ++ value = hifmc_readb(host->iobase + host->offset); ++ host->offset++; ++ if (host->cmd_op.data_no == host->offset) ++ host->cmd_op.l_cmd = 0; ++ return value; ++ } ++ ++ if (host->cmd_op.cmd == NAND_CMD_STATUS) { ++ value = hifmc_readl(host, FMC_STATUS); ++ if (host->cmd_op.l_cmd == NAND_CMD_GET_FEATURES) { ++ FMC_PR((ER_DBG || WR_DBG), "\t\tRead BP status:%#x\n", ++ value); ++ if (ANY_BP_ENABLE(value)) ++ ret_val |= NAND_STATUS_WP; ++ ++ host->cmd_op.l_cmd = NAND_CMD_STATUS; ++ } ++ ++ if (!(value & STATUS_OIP_MASK)) ++ ret_val |= NAND_STATUS_READY; ++ ++ if (value & STATUS_E_FAIL_MASK) { ++ FMC_PR(ER_DBG, "\t\tGet erase status: %#x\n", value); ++ ret_val |= NAND_STATUS_FAIL; ++ } ++ ++ if (value & STATUS_P_FAIL_MASK) { ++ FMC_PR(WR_DBG, "\t\tGet write status: %#x\n", value); ++ ret_val |= NAND_STATUS_FAIL; ++ } ++ ++ return ret_val; ++ } ++ ++ if (host->cmd_op.l_cmd == NAND_CMD_READOOB) { ++ value = hifmc_readb(host->buffer + host->pagesize + host->offset); ++ host->offset++; ++ return value; ++ } ++ ++ host->offset++; ++ ++ return hifmc_readb(host->buffer + host->column + host->offset - 1); ++} ++ ++/*****************************************************************************/ ++static unsigned short hifmc100_read_word(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ ++ host->offset += 2; ++ return hifmc_readw(host->buffer + host->column + host->offset - 2); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_write_buf(struct mtd_info *mtd, ++ const u_char *buf, int len) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ ++#ifdef HIFMC100_SPI_NAND_SUPPORT_REG_WRITE ++ if (buf == chip->oob_poi) ++ memcpy((char *)host->iobase + host->pagesize, buf, len); ++ else ++ memcpy((char *)host->iobase, buf, len); ++#else ++ if (buf == chip->oob_poi) ++ memcpy((char *)(host->buffer + host->pagesize), buf, len); ++ else ++ memcpy((char *)host->buffer, buf, len); ++#endif ++ return; ++} ++ ++/*****************************************************************************/ ++static void hifmc100_read_buf(struct mtd_info *mtd, u_char *buf, int len) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ ++#ifdef HIFMC100_SPI_NAND_SUPPORT_REG_READ ++ if (buf == chip->oob_poi) ++ memcpy(buf, (char *)host->iobase + host->pagesize, len); ++ else ++ memcpy(buf, (char *)host->iobase, len); ++#else ++ if (buf == chip->oob_poi) ++ memcpy(buf, (char *)host->buffer + host->pagesize, len); ++ else ++ memcpy(buf, (char *)host->buffer, len); ++#endif ++ ++#ifdef CONFIG_HISI_NAND_ECC_STATUS_REPORT ++ if (buf != chip->oob_poi) { ++ u_int reg, ecc_step = host->pagesize >> 10; ++ ++ reg = hifmc_readl(host, HIFMC100_ECC_ERR_NUM0_BUF0); ++ while (ecc_step) { ++ u_char err_num; ++ ++ err_num = GET_ECC_ERR_NUM(--ecc_step, reg); ++ if (err_num == 0xff) ++ mtd->ecc_stats.failed++; ++ else ++ mtd->ecc_stats.corrected += err_num; ++ } ++ } ++#endif ++ ++ return; ++} ++ ++/*****************************************************************************/ ++static void hifmc100_select_chip(struct mtd_info *mtd, int chipselect) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ ++ if (chipselect < 0) { ++ mutex_unlock(&fmc_switch_mutex); ++ return; ++ } ++ ++ mutex_lock(&fmc_switch_mutex); ++ ++ if (chipselect > CONFIG_SPI_NAND_MAX_CHIP_NUM) ++ DB_BUG("Error: Invalid chipselect: %d\n", chipselect); ++ ++ if (host->mtd != mtd) { ++ host->mtd = mtd; ++ host->cmd_op.cs = chipselect; ++ } ++ ++ if (!(chip->options & NAND_BROKEN_XD)) { ++ if ((chip->state == FL_ERASING) || (chip->state == FL_WRITING)) ++ host->cmd_op.l_cmd = NAND_CMD_GET_FEATURES; ++ } ++} ++ ++/*****************************************************************************/ ++static void hifmc100_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned ctrl) ++{ ++ unsigned char cmd; ++ int is_cache_invalid = 1; ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ ++ if (ctrl & NAND_ALE) { ++ unsigned int addr_value = 0; ++ unsigned int addr_offset = 0; ++ ++ if (ctrl & NAND_CTRL_CHANGE) { ++ host->addr_cycle = 0x0; ++ host->addr_value[0] = 0x0; ++ host->addr_value[1] = 0x0; ++ } ++ addr_offset = host->addr_cycle << 3; ++ ++ if (host->addr_cycle >= HIFMC100_ADDR_CYCLE_MASK) { ++ addr_offset = (host->addr_cycle - ++ HIFMC100_ADDR_CYCLE_MASK) << 3; ++ addr_value = 1; ++ } ++ ++ host->addr_value[addr_value] |= ++ ((dat & 0xff) << addr_offset); ++ ++ host->addr_cycle++; ++ } ++ ++ if ((ctrl & NAND_CLE) && (ctrl & NAND_CTRL_CHANGE)) { ++ cmd = dat & 0xff; ++ host->cmd_op.cmd = cmd; ++ switch (cmd) { ++ case NAND_CMD_PAGEPROG: ++ host->offset = 0; ++ host->send_cmd_write(host); ++ break; ++ ++ case NAND_CMD_READSTART: ++ is_cache_invalid = 0; ++ if (host->addr_value[0] == host->pagesize) ++ host->cmd_op.l_cmd = NAND_CMD_READOOB; ++ host->send_cmd_read(host); ++ break; ++ ++ case NAND_CMD_ERASE2: ++ host->send_cmd_erase(host); ++ break; ++ ++ case NAND_CMD_READID: ++ memset((u_char *)(host->iobase), 0, ++ MAX_SPI_NAND_ID_LEN); ++ host->cmd_op.l_cmd = cmd; ++ host->cmd_op.data_no = MAX_SPI_NAND_ID_LEN; ++ host->send_cmd_readid(host); ++ break; ++ ++ case NAND_CMD_STATUS: ++ host->send_cmd_status(host); ++ break; ++ ++ case NAND_CMD_READ0: ++ host->cmd_op.l_cmd = cmd; ++ break; ++ ++ case NAND_CMD_RESET: ++ host->send_cmd_reset(host); ++ break; ++ ++ case NAND_CMD_SEQIN: ++ case NAND_CMD_ERASE1: ++ default: ++ break; ++ } ++ } ++ ++ if ((dat == NAND_CMD_NONE) && host->addr_cycle) { ++ if (host->cmd_op.cmd == NAND_CMD_SEQIN ++ || host->cmd_op.cmd == NAND_CMD_READ0 ++ || host->cmd_op.cmd == NAND_CMD_READID) { ++ host->offset = 0x0; ++ host->column = (host->addr_value[0] & 0xffff); ++ } ++ } ++ ++ if (is_cache_invalid) { ++ host->cache_addr_value[0] = ~0; ++ host->cache_addr_value[1] = ~0; ++ } ++} ++ ++/*****************************************************************************/ ++static int hifmc100_dev_ready(struct mtd_info *mtd) ++{ ++ unsigned int reg; ++ unsigned long deadline = jiffies + FMC_MAX_READY_WAIT_JIFFIES; ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ ++ do { ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) | OP_CFG_OEN_EN; ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ ++ reg = FMC_OP_READ_STATUS_EN | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++ reg = hifmc_readl(host, FMC_STATUS); ++ ++ if (!(reg & STATUS_OIP_MASK)) ++ return NAND_STATUS_READY; ++ ++ cond_resched(); ++ ++ } while (!time_after_eq(jiffies, deadline)); ++ ++ if (!(chip->options & NAND_SCAN_SILENT_NODEV)) ++ pr_warn("Wait SPI nand ready timeout, status: %#x\n", reg); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++/* ++ * 'host->epm' only use the first oobfree[0] field, it looks very simple, But... ++ */ ++/* Default OOB area layout */ ++static int hifmc_ooblayout_ecc_default(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->length = 32; ++ oobregion->offset = 32; ++ ++ return 0; ++} ++ ++static int hifmc_ooblayout_free_default(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->length = 30; ++ oobregion->offset = 2; ++ ++ return 0; ++} ++ ++static struct mtd_ooblayout_ops hifmc_ooblayout_default_ops = { ++ .ecc = hifmc_ooblayout_ecc_default, ++ .free = hifmc_ooblayout_free_default, ++}; ++ ++#ifdef CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 ++static int hifmc_ooblayout_ecc_4k16bit(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->length = 14; ++ oobregion->offset = 14; ++ ++ return 0; ++} ++ ++static int hifmc_ooblayout_free_4k16bit(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->length = 14; ++ oobregion->offset = 2; ++ ++ return 0; ++} ++ ++static struct mtd_ooblayout_ops hifmc_ooblayout_4k16bit_ops = { ++ .ecc = hifmc_ooblayout_ecc_4k16bit, ++ .free = hifmc_ooblayout_free_4k16bit, ++}; ++ ++static int hifmc_ooblayout_ecc_2k16bit(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->length = 6; ++ oobregion->offset = 6; ++ ++ return 0; ++} ++ ++static int hifmc_ooblayout_free_2k16bit(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->length = 6; ++ oobregion->offset = 2; ++ ++ return 0; ++} ++ ++static struct mtd_ooblayout_ops hifmc_ooblayout_2k16bit_ops = { ++ .ecc = hifmc_ooblayout_ecc_2k16bit, ++ .free = hifmc_ooblayout_free_2k16bit, ++}; ++#endif ++ ++/*****************************************************************************/ ++static struct nand_config_info hifmc_spi_nand_config_table[] = { ++ {NAND_PAGE_4K, NAND_ECC_24BIT, 24, 200, &hifmc_ooblayout_default_ops}, ++#ifdef CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 ++ {NAND_PAGE_4K, NAND_ECC_16BIT, 16, 128, &hifmc_ooblayout_4k16bit_ops}, ++#endif ++ {NAND_PAGE_4K, NAND_ECC_8BIT, 8, 88, &hifmc_ooblayout_default_ops}, ++ {NAND_PAGE_4K, NAND_ECC_0BIT, 0, 32, &hifmc_ooblayout_default_ops}, ++ ++ {NAND_PAGE_2K, NAND_ECC_24BIT, 24, 128, &hifmc_ooblayout_default_ops}, ++#ifdef CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 ++ {NAND_PAGE_2K, NAND_ECC_16BIT, 16, 64, &hifmc_ooblayout_2k16bit_ops}, ++#endif ++ {NAND_PAGE_2K, NAND_ECC_8BIT, 8, 64, &hifmc_ooblayout_default_ops}, ++ {NAND_PAGE_2K, NAND_ECC_0BIT, 0, 32, &hifmc_ooblayout_default_ops}, ++ ++ {0, 0, 0, 0, NULL}, ++}; ++ ++/* ++ * Auto-sensed the page size and ecc type value. driver will try each of page ++ * size and ecc type one by one till flash can be read and wrote accurately. ++ * so the page size and ecc type is match adaptively without switch on the board ++ */ ++static struct nand_config_info *hifmc100_get_config_type_info( ++ struct mtd_info *mtd, struct nand_dev_t *nand_dev) ++{ ++ struct nand_config_info *best = NULL; ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct nand_config_info *info = hifmc_spi_nand_config_table; ++ ++ nand_dev->start_type = "Auto"; ++ ++ for (; info->ooblayout_ops; info++) { ++ if (match_page_type_to_size(info->pagetype) != mtd->writesize) ++ continue; ++ ++ if (mtd->oobsize < info->oobsize) ++ continue; ++ ++ if (!best || (best->ecctype < info->ecctype)) ++ best = info; ++ } ++ ++ /* All SPI NAND are small-page, SLC */ ++ chip->bits_per_cell = 1; ++ ++ return best; ++} ++ ++/*****************************************************************************/ ++static void hifmc100_chip_init(struct nand_chip *chip) ++{ ++ chip->read_byte = hifmc100_read_byte; ++ chip->read_word = hifmc100_read_word; ++ chip->write_buf = hifmc100_write_buf; ++ chip->read_buf = hifmc100_read_buf; ++ ++ chip->select_chip = hifmc100_select_chip; ++ ++ chip->cmd_ctrl = hifmc100_cmd_ctrl; ++ chip->dev_ready = hifmc100_dev_ready; ++ ++ chip->chip_delay = FMC_CHIP_DELAY; ++ ++ chip->options = NAND_SKIP_BBTSCAN | NAND_BROKEN_XD ++ | NAND_SCAN_SILENT_NODEV; ++ ++ chip->ecc.mode = NAND_ECC_NONE; ++} ++ ++/*****************************************************************************/ ++static void hifmc100_set_oob_info(struct mtd_info *mtd, ++ struct nand_config_info *info, struct nand_dev_t *nand_dev) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ struct mtd_oob_region hifmc_oobregion = {0, 0}; ++ ++ if (info->ecctype != NAND_ECC_0BIT) ++ mtd->oobsize = info->oobsize; ++ ++ host->oobsize = mtd->oobsize; ++ nand_dev->oobsize = host->oobsize; ++ ++ host->dma_oob = host->dma_buffer + host->pagesize; ++ host->bbm = (u_char *)(host->buffer + host->pagesize ++ + HIFMC_BAD_BLOCK_POS); ++ ++ info->ooblayout_ops->free(mtd, 0, &hifmc_oobregion); ++ ++ mtd_set_ooblayout(mtd, info->ooblayout_ops); ++ ++ /* EB bits locate in the bottom two of CTRL(30) */ ++ host->epm = (u_short *)(host->buffer + host->pagesize ++ + hifmc_oobregion.offset + 28); ++ ++#ifdef CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 ++ if (best->ecctype == NAND_ECC_16BIT) { ++ if (host->pagesize == _2K) { ++ /* EB bits locate in the bottom two of CTRL(4) */ ++ host->epm = (u_short *)(host->buffer + host->pagesize ++ + hifmc_oobregion.offset + 4); ++ } else if (host->pagesize == _4K) { ++ /* EB bit locate in the bottom two of CTRL(14) */ ++ host->epm = (u_short *)(host->buffer + host->pagesize ++ + hifmc_oobregion.offset + 12); ++ } ++ } ++#endif ++} ++ ++/*****************************************************************************/ ++static unsigned int hifmc100_get_ecc_reg(struct hifmc_host *host, ++ struct nand_config_info *info, struct nand_dev_t *nand_dev) ++{ ++ host->ecctype = info->ecctype; ++ nand_dev->ecctype = host->ecctype; ++ ++ return FMC_CFG_ECC_TYPE(match_ecc_type_to_reg(info->ecctype)); ++} ++ ++/*****************************************************************************/ ++static unsigned int hifmc100_get_page_reg(struct hifmc_host *host, ++ struct nand_config_info *info) ++{ ++ host->pagesize = match_page_type_to_size(info->pagetype); ++ ++ return FMC_CFG_PAGE_SIZE(match_page_type_to_reg(info->pagetype)); ++} ++ ++/*****************************************************************************/ ++static unsigned int hifmc100_get_block_reg(struct hifmc_host *host, ++ struct nand_config_info *info) ++{ ++ unsigned int block_reg = 0, page_per_block; ++ struct mtd_info *mtd = host->mtd; ++ ++ host->block_page_mask = ((mtd->erasesize / mtd->writesize) - 1); ++ page_per_block = mtd->erasesize / match_page_type_to_size(info->pagetype); ++ switch (page_per_block) { ++ case 64: ++ block_reg = BLOCK_SIZE_64_PAGE; ++ break; ++ case 128: ++ block_reg = BLOCK_SIZE_128_PAGE; ++ break; ++ case 256: ++ block_reg = BLOCK_SIZE_256_PAGE; ++ break; ++ case 512: ++ block_reg = BLOCK_SIZE_512_PAGE; ++ break; ++ default: ++ DB_MSG("Can't support block %#x and page %#x size\n", ++ mtd->erasesize, mtd->writesize); ++ } ++ ++ return FMC_CFG_BLOCK_SIZE(block_reg); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_set_fmc_cfg_reg(struct hifmc_host *host, ++ struct nand_config_info *type_info, struct nand_dev_t *nand_dev) ++{ ++ unsigned int page_reg, ecc_reg, block_reg, reg_fmc_cfg; ++ ++ ecc_reg = hifmc100_get_ecc_reg(host, type_info, nand_dev); ++ page_reg = hifmc100_get_page_reg(host, type_info); ++ block_reg = hifmc100_get_block_reg(host, type_info); ++ ++ reg_fmc_cfg = hifmc_readl(host, FMC_CFG); ++ reg_fmc_cfg &= ~(PAGE_SIZE_MASK | ECC_TYPE_MASK | BLOCK_SIZE_MASK); ++ reg_fmc_cfg |= ecc_reg | page_reg | block_reg; ++ hifmc_writel(host, FMC_CFG, reg_fmc_cfg); ++ ++ /* Save value of FMC_CFG and FMC_CFG_ECC0 to turn on/off ECC */ ++ host->fmc_cfg = reg_fmc_cfg; ++ host->fmc_cfg_ecc0 = (host->fmc_cfg & ~ECC_TYPE_MASK) | ECC_TYPE_0BIT; ++ FMC_PR(BT_DBG, "\t|-Save FMC_CFG[%#x]: %#x and FMC_CFG_ECC0: %#x\n", ++ FMC_CFG, host->fmc_cfg, host->fmc_cfg_ecc0); ++} ++ ++/*****************************************************************************/ ++static int hifmc100_set_config_info(struct mtd_info *mtd, ++ struct nand_chip *chip, struct nand_dev_t *nand_dev) ++{ ++ struct hifmc_host *host = chip->priv; ++ struct nand_config_info *type_info = NULL; ++ ++ FMC_PR(BT_DBG, "\t*-Start config Block Page OOB and Ecc\n"); ++ ++ type_info = hifmc100_get_config_type_info(mtd, nand_dev); ++ BUG_ON(!type_info); ++ ++ FMC_PR(BT_DBG, "\t|-%s Config, PageSize %s EccType %s OOBSize %d\n", ++ nand_dev->start_type, nand_page_name(type_info->pagetype), ++ nand_ecc_name(type_info->ecctype), type_info->oobsize); ++ ++ /* Set the page_size, ecc_type, block_size of FMC_CFG[0x0] register */ ++ hifmc100_set_fmc_cfg_reg(host, type_info, nand_dev); ++ ++ hifmc100_set_oob_info(mtd, type_info, nand_dev); ++ ++ FMC_PR(BT_DBG, "\t*-End config Block Page Oob and Ecc\n"); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++int hifmc100_spi_nand_init(struct nand_chip *chip) ++{ ++ struct hifmc_host *host = chip->priv; ++ ++ FMC_PR(BT_DBG, "\t|*-Start hifmc100 SPI Nand init\n"); ++ ++ /* Set system clock and enable controller */ ++ clk_prepare_enable(host->clk); ++ ++ /* Switch SPI type to SPI nand */ ++ hifmc100_switch_to_spi_nand(host); ++ ++ /* Hifmc host init */ ++ hifmc100_host_init(host); ++ host->chip = chip; ++ ++ /* Hifmc nand_chip struct init */ ++ hifmc100_chip_init(chip); ++ ++ hifmc_spi_nand_ids_register(); ++ hinfc_param_adjust = hifmc100_set_config_info; ++ ++ FMC_PR(BT_DBG, "\t|*-End hifmc100 SPI Nand init\n"); ++ ++ return 0; ++} ++#ifdef CONFIG_PM ++/*****************************************************************************/ ++int hifmc100_suspend(struct platform_device *pltdev, pm_message_t state) ++{ ++ unsigned int ret; ++ struct hifmc_host *host = platform_get_drvdata(pltdev); ++ struct hifmc_spi *spi = host->spi; ++ ++ mutex_lock(host->lock); ++ hifmc100_switch_to_spi_nand(host); ++ ++ ret = spi->driver->wait_ready(spi); ++ if (ret) { ++ DB_MSG("Error: wait ready failed!"); ++ return 0; ++ } ++ ++ clk_disable_unprepare(host->clk); ++ mutex_unlock(host->lock); ++ ++ return 0; ++} ++/*****************************************************************************/ ++int hifmc100_resume(struct platform_device *pltdev) ++{ ++ int cs; ++ struct hifmc_host *host = platform_get_drvdata(pltdev); ++ struct nand_chip *chip = host->chip; ++ ++ mutex_lock(host->lock); ++ hifmc100_switch_to_spi_nand(host); ++ clk_prepare_enable(host->clk); ++ ++ for (cs = 0; cs < chip->numchips; cs++) ++ host->send_cmd_reset(host); ++ ++ hifmc100_spi_nand_config(host); ++ ++ mutex_unlock(host->lock); ++ return 0; ++} ++#endif ++ +diff --git a/drivers/mtd/nand/hifmc100/hifmc100.h b/drivers/mtd/nand/hifmc100/hifmc100.h +new file mode 100644 +index 0000000..2f7f5a8 +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100/hifmc100.h +@@ -0,0 +1,391 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef __HIFMC100_H__ ++#define __HIFMC100_H__ ++ ++/*****************************************************************************/ ++#include ++#include ++ ++/*****************************************************************************/ ++#define INFINITE (0xFFFFFFFF) ++ ++/*****************************************************************************/ ++#define SPI_IF_READ_STD (0x01) ++#define SPI_IF_READ_FAST (0x02) ++#define SPI_IF_READ_DUAL (0x04) ++#define SPI_IF_READ_DUAL_ADDR (0x08) ++#define SPI_IF_READ_QUAD (0x10) ++#define SPI_IF_READ_QUAD_ADDR (0x20) ++ ++#define SPI_IF_WRITE_STD (0x01) ++#define SPI_IF_WRITE_DUAL (0x02) ++#define SPI_IF_WRITE_DUAL_ADDR (0x04) ++#define SPI_IF_WRITE_QUAD (0x08) ++#define SPI_IF_WRITE_QUAD_ADDR (0x10) ++ ++#define SPI_IF_ERASE_SECTOR_4K (0x01) ++#define SPI_IF_ERASE_SECTOR_32K (0x02) ++#define SPI_IF_ERASE_SECTOR_64K (0x04) ++#define SPI_IF_ERASE_SECTOR_128K (0x08) ++#define SPI_IF_ERASE_SECTOR_256K (0x10) ++ ++/******************************************************************************/ ++#define HIFMC_SPI_NAND_SUPPORT_READ (SPI_IF_READ_STD \ ++ | SPI_IF_READ_FAST \ ++ | SPI_IF_READ_DUAL \ ++ | SPI_IF_READ_DUAL_ADDR \ ++ | SPI_IF_READ_QUAD \ ++ | SPI_IF_READ_QUAD_ADDR) ++ ++#define HIFMC_SPI_NAND_SUPPORT_WRITE (SPI_IF_WRITE_STD | SPI_IF_WRITE_QUAD) ++ ++#define HIFMC_SPI_NAND_SUPPORT_MAX_DUMMY 8 ++ ++/*****************************************************************************/ ++#define SPI_CMD_READ_STD 0x03 /* Standard read cache */ ++#define SPI_CMD_READ_FAST 0x0B /* Higher speed read cache */ ++#define SPI_CMD_READ_DUAL 0x3B /* 2 IO read cache only date */ ++#define SPI_CMD_READ_DUAL_ADDR 0xBB /* 2 IO read cache date&addr */ ++#define SPI_CMD_READ_QUAD 0x6B /* 4 IO read cache only date */ ++#define SPI_CMD_READ_QUAD_ADDR 0xEB /* 4 IO read cache date&addr */ ++ ++#define SPI_CMD_WRITE_STD 0x02 /* Standard page program */ ++#define SPI_CMD_WRITE_DUAL 0xA2 /* 2 IO program only date */ ++#define SPI_CMD_WRITE_DUAL_ADDR 0xD2 /* 2 IO program date&addr */ ++#define SPI_CMD_WRITE_QUAD 0x32 /* 4 IO program only date */ ++#define SPI_CMD_WRITE_QUAD_ADDR 0x12 /* 4 IO program date&addr */ ++ ++#define SPI_CMD_SE_4K 0x20 /* 4KB sector Erase */ ++#define SPI_CMD_SE_32K 0x52 /* 32KB sector Erase */ ++#define SPI_CMD_SE_64K 0xD8 /* 64KB sector Erase */ ++#define SPI_CMD_SE_128K 0xD8 /* 128KB sector Erase */ ++#define SPI_CMD_SE_256K 0xD8 /* 256KB sector Erase */ ++ ++/*****************************************************************************/ ++#define SET_READ_STD(_dummy_, _size_, _clk_) \ ++ static struct spi_op read_std_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_STD, SPI_CMD_READ_STD, _dummy_, _size_, _clk_ } ++ ++#define SET_READ_FAST(_dummy_, _size_, _clk_) \ ++ static struct spi_op read_fast_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_FAST, SPI_CMD_READ_FAST, _dummy_, _size_, _clk_ } ++ ++#define SET_READ_DUAL(_dummy_, _size_, _clk_) \ ++ static struct spi_op read_dual_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_DUAL, SPI_CMD_READ_DUAL, _dummy_, _size_, _clk_ } ++ ++#define SET_READ_DUAL_ADDR(_dummy_, _size_, _clk_) \ ++ static struct spi_op read_dual_addr_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_DUAL_ADDR, SPI_CMD_READ_DUAL_ADDR, _dummy_, _size_, _clk_ } ++ ++#define SET_READ_QUAD(_dummy_, _size_, _clk_) \ ++ static struct spi_op read_quad_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_QUAD, SPI_CMD_READ_QUAD, _dummy_, _size_, _clk_ } ++ ++#define SET_READ_QUAD_ADDR(_dummy_, _size_, _clk_) \ ++ static struct spi_op read_quad_addr_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_QUAD_ADDR, SPI_CMD_READ_QUAD_ADDR, _dummy_, _size_, _clk_ } ++ ++/*****************************************************************************/ ++#define SET_WRITE_STD(_dummy_, _size_, _clk_) \ ++ static struct spi_op write_std_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_WRITE_STD, SPI_CMD_WRITE_STD, _dummy_, _size_, _clk_ } ++ ++#define SET_WRITE_DUAL(_dummy_, _size_, _clk_) \ ++ static struct spi_op write_dual_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_WRITE_DUAL, SPI_CMD_WRITE_DUAL, _dummy_, _size_, _clk_ } ++ ++#define SET_WRITE_DUAL_ADDR(_dummy_, _size_, _clk_) \ ++ static struct spi_op write_dual_addr_##_dummy_##_size_##_clk_ = { \ ++SPI_IF_WRITE_DUAL_ADDR, SPI_CMD_WRITE_DUAL_ADDR, _dummy_, _size_, _clk_ } ++ ++#define SET_WRITE_QUAD(_dummy_, _size_, _clk_) \ ++ static struct spi_op write_quad_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_WRITE_QUAD, SPI_CMD_WRITE_QUAD, _dummy_, _size_, _clk_ } ++ ++#define SET_WRITE_QUAD_ADDR(_dummy_, _size_, _clk_) \ ++ static struct spi_op write_quad_addr_##_dummy_##_size_##_clk_ = { \ ++SPI_IF_WRITE_QUAD_ADDR, SPI_CMD_WRITE_QUAD_ADDR, _dummy_, _size_, _clk_ } ++ ++/*****************************************************************************/ ++#define SET_ERASE_SECTOR_4K(_dummy_, _size_, _clk_) \ ++ static struct spi_op erase_sector_4k_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_ERASE_SECTOR_4K, SPI_CMD_SE_4K, _dummy_, _size_, _clk_ } ++ ++#define SET_ERASE_SECTOR_32K(_dummy_, _size_, _clk_) \ ++ static struct spi_op erase_sector_32k_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_ERASE_SECTOR_32K, SPI_CMD_SE_32K, _dummy_, _size_, _clk_ } ++ ++#define SET_ERASE_SECTOR_64K(_dummy_, _size_, _clk_) \ ++ static struct spi_op erase_sector_64k_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_ERASE_SECTOR_64K, SPI_CMD_SE_64K, _dummy_, _size_, _clk_ } ++ ++#define SET_ERASE_SECTOR_128K(_dummy_, _size_, _clk_) \ ++ static struct spi_op erase_sector_128k_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_ERASE_SECTOR_128K, SPI_CMD_SE_128K, _dummy_, _size_, _clk_ } ++ ++#define SET_ERASE_SECTOR_256K(_dummy_, _size_, _clk_) \ ++ static struct spi_op erase_sector_256k_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_ERASE_SECTOR_256K, SPI_CMD_SE_256K, _dummy_, _size_, _clk_ } ++ ++/*****************************************************************************/ ++#define READ_STD(_dummy_, _size_, _clk_) read_std_##_dummy_##_size_##_clk_ ++#define READ_FAST(_dummy_, _size_, _clk_) read_fast_##_dummy_##_size_##_clk_ ++#define READ_DUAL(_dummy_, _size_, _clk_) read_dual_##_dummy_##_size_##_clk_ ++#define READ_DUAL_ADDR(_dummy_, _size_, _clk_) \ ++ read_dual_addr_##_dummy_##_size_##_clk_ ++#define READ_QUAD(_dummy_, _size_, _clk_) read_quad_##_dummy_##_size_##_clk_ ++#define READ_QUAD_ADDR(_dummy_, _size_, _clk_) \ ++ read_quad_addr_##_dummy_##_size_##_clk_ ++ ++/*****************************************************************************/ ++#define WRITE_STD(_dummy_, _size_, _clk_) write_std_##_dummy_##_size_##_clk_ ++#define WRITE_DUAL(_dummy_, _size_, _clk_) write_dual_##_dummy_##_size_##_clk_ ++#define WRITE_DUAL_ADDR(_dummy_, _size_, _clk_) \ ++ write_dual_addr_##_dummy_##_size_##_clk_ ++#define WRITE_QUAD(_dummy_, _size_, _clk_) write_quad_##_dummy_##_size_##_clk_ ++#define WRITE_QUAD_ADDR(_dummy_, _size_, _clk_) \ ++ write_quad_addr_##_dummy_##_size_##_clk_ ++ ++/*****************************************************************************/ ++#define ERASE_SECTOR_4K(_dummy_, _size_, _clk_) \ ++ erase_sector_4k_##_dummy_##_size_##_clk_ ++#define ERASE_SECTOR_32K(_dummy_, _size_, _clk_) \ ++ erase_sector_32k_##_dummy_##_size_##_clk_ ++#define ERASE_SECTOR_64K(_dummy_, _size_, _clk_) \ ++ erase_sector_64k_##_dummy_##_size_##_clk_ ++#define ERASE_SECTOR_128K(_dummy_, _size_, _clk_) \ ++ erase_sector_128k_##_dummy_##_size_##_clk_ ++#define ERASE_SECTOR_256K(_dummy_, _size_, _clk_) \ ++ erase_sector_256k_##_dummy_##_size_##_clk_ ++ ++/*****************************************************************************/ ++#define SPI_CMD_WREN 0x06 /* Write Enable */ ++#define SPI_CMD_WRDI 0x04 /* Write Disable */ ++ ++#define SPI_CMD_RDID 0x9F /* Read Identification */ ++ ++/*****************************************************************************/ ++#define SPI_CMD_GET_FEATURES 0x0F /* Get Features */ ++#define SPI_CMD_SET_FEATURE 0x1F /* Set Feature */ ++ ++#define SPI_CMD_PAGE_READ 0x13 /* Page Read to Cache */ ++ ++#define SPI_CMD_RESET 0xff /* Reset the device */ ++ ++/*****************************************************************************/ ++/* These macroes are for debug only, reg option is slower then dma option */ ++#undef HIFMC100_SPI_NAND_SUPPORT_REG_READ ++/* #define HIFMC100_SPI_NAND_SUPPORT_REG_READ */ ++ ++#undef HIFMC100_SPI_NAND_SUPPORT_REG_WRITE ++/* #define HIFMC100_SPI_NAND_SUPPORT_REG_WRITE */ ++ ++#ifdef CONFIG_HISI_NAND_ECC_STATUS_REPORT ++/*****************************************************************************/ ++#define HIFMC100_ECC_ERR_NUM0_BUF0 0xc0 ++ ++#define GET_ECC_ERR_NUM(_i, _reg) (((_reg) >> ((_i) * 8)) & 0xff) ++#endif ++/*****************************************************************************/ ++#define REG_CNT_HIGH_BLOCK_NUM_SHIFT 10 ++ ++#define REG_CNT_BLOCK_NUM_MASK 0x3ff ++#define REG_CNT_BLOCK_NUM_SHIFT 22 ++ ++#define REG_CNT_PAGE_NUM_MASK 0x3f ++#define REG_CNT_PAGE_NUM_SHIFT 16 ++ ++#define REG_CNT_WRAP_MASK 0xf ++#define REG_CNT_WRAP_SHIFT 12 ++ ++#define REG_CNT_ECC_OFFSET_MASK 0xfff ++#define REG_CNT_ECC_8BIT_OFFSET 1054 ++#define REG_CNT_ECC_16BIT_OFFSET 1056 ++#define REG_CNT_ECC_24BIT_OFFSET 1082 ++ ++#define ERR_STR_DRIVER "Driver does not support this configure " ++#define ERR_STR_CHECK "Please make sure the hardware configuration is correct" ++ ++/*****************************************************************************/ ++#define HIFMC100_ADDR_CYCLE_MASK 0x2 ++ ++/*****************************************************************************/ ++#define OP_STYPE_NONE 0x0 ++#define OP_STYPE_READ 0x01 ++#define OP_STYPE_WRITE 0x02 ++#define OP_STYPE_ERASE 0x04 ++#define CLK_FMC_TO_CRG_MHZ(_clk) ((_clk) * 2000000) ++ ++/*****************************************************************************/ ++#define MAX_SPI_OP 8 ++ ++/*****************************************************************************/ ++/* SPI general operation parameter */ ++struct spi_op { ++ unsigned char iftype; ++ unsigned char cmd; ++ unsigned char dummy; ++ unsigned int size; ++ unsigned int clock; ++}; ++ ++struct spi_drv; ++ ++/* SPI interface all operation */ ++struct hifmc_spi { ++ char *name; ++ int chipselect; ++ unsigned long long chipsize; ++ unsigned int erasesize; ++#define SPI_NOR_3BYTE_ADDR_LEN 3 /* address len 3Bytes */ ++#define SPI_NOR_4BYTE_ADDR_LEN 4 /* address len 4Bytes for 32MB */ ++ unsigned int addrcycle; ++ ++ struct spi_op read[1]; ++ struct spi_op write[1]; ++ struct spi_op erase[MAX_SPI_OP]; ++ ++ void *host; ++ ++ struct spi_drv *driver; ++}; ++ ++/* SPI interface special operation function hook */ ++struct spi_drv { ++ int (*wait_ready)(struct hifmc_spi *spi); ++ int (*write_enable)(struct hifmc_spi *spi); ++ int (*qe_enable)(struct hifmc_spi *spi); ++ int (*bus_prepare)(struct hifmc_spi *spi, int op); ++ int (*entry_4addr)(struct hifmc_spi *spi, int en); ++}; ++ ++struct spi_nand_info { ++ char *name; ++ unsigned char id[MAX_SPI_NAND_ID_LEN]; ++ unsigned char id_len; ++ unsigned long long chipsize; ++ unsigned int erasesize; ++ unsigned int pagesize; ++ unsigned int oobsize; ++#define BBP_LAST_PAGE 0x01 ++#define BBP_FIRST_PAGE 0x02 ++ unsigned int badblock_pos; ++ struct spi_op *read[MAX_SPI_OP]; ++ struct spi_op *write[MAX_SPI_OP]; ++ struct spi_op *erase[MAX_SPI_OP]; ++ struct spi_drv *driver; ++}; ++ ++/*****************************************************************************/ ++extern u_char spi_nand_feature_op(struct hifmc_spi *spi, u_char op, u_char addr, ++ u_char val); ++ ++/*****************************************************************************/ ++struct hifmc_host { ++ struct mtd_info *mtd; ++ struct nand_chip *chip; ++ struct hifmc_spi spi[CONFIG_SPI_NAND_MAX_CHIP_NUM]; ++ struct hifmc_cmd_op cmd_op; ++ ++ void __iomem *iobase; ++ void __iomem *regbase; ++ struct clk *clk; ++ u32 clkrate; ++ ++ unsigned int fmc_cfg; ++ unsigned int fmc_cfg_ecc0; ++ ++ unsigned int offset; ++ ++ struct device *dev; ++ struct mutex *lock; ++ ++ /* This is maybe an un-aligment address, only for malloc or free */ ++ char *buforg; ++ char *buffer; ++ ++#ifdef CONFIG_64BIT ++ unsigned long long dma_buffer; ++ unsigned long long dma_oob; ++#else ++ unsigned int dma_buffer; ++ unsigned int dma_oob; ++#endif ++ ++ unsigned int addr_cycle; ++ unsigned int addr_value[2]; ++ unsigned int cache_addr_value[2]; ++ ++ unsigned int column; ++ unsigned int block_page_mask; ++ ++ unsigned int ecctype; ++ unsigned int pagesize; ++ unsigned int oobsize; ++ ++ int add_partition; ++ ++ int need_rr_data; ++#define HIFMC100_READ_RETRY_DATA_LEN 128 ++ char rr_data[HIFMC100_READ_RETRY_DATA_LEN]; ++ struct read_retry_t *read_retry; ++ ++ int version; ++ ++ /* BOOTROM read two bytes to detect the bad block flag */ ++#define HIFMC_BAD_BLOCK_POS 0 ++ unsigned char *bbm; /* nand bad block mark */ ++ unsigned short *epm; /* nand empty page mark */ ++ ++ unsigned int uc_er; ++ ++ void (*send_cmd_write)(struct hifmc_host *host); ++ void (*send_cmd_status)(struct hifmc_host *host); ++ void (*send_cmd_read)(struct hifmc_host *host); ++ void (*send_cmd_erase)(struct hifmc_host *host); ++ void (*send_cmd_readid)(struct hifmc_host *host); ++ void (*send_cmd_reset)(struct hifmc_host *host); ++#ifdef CONFIG_PM ++ int (*suspend)(struct platform_device *pltdev, pm_message_t state); ++ int (*resume)(struct platform_device *pltdev); ++#endif ++}; ++ ++/*****************************************************************************/ ++void hifmc100_ecc0_switch(struct hifmc_host *host, unsigned char op); ++ ++int hifmc100_spi_nand_init(struct nand_chip *chip); ++ ++/*****************************************************************************/ ++extern void hifmc_spi_nand_ids_register(void); ++ ++extern void hifmc_set_nand_system_clock(struct spi_op *op, int clk_en); ++ ++/*****************************************************************************/ ++#ifdef CONFIG_PM ++int hifmc100_suspend(struct platform_device *pltdev, pm_message_t state); ++int hifmc100_resume(struct platform_device *pltdev); ++void hifmc100_spi_nand_config(struct hifmc_host *host); ++#endif ++ ++#endif /* End of __HIFMC100_H__ */ +diff --git a/drivers/mtd/nand/hifmc100/hifmc100_os.c b/drivers/mtd/nand/hifmc100/hifmc100_os.c +new file mode 100644 +index 0000000..8ded188 +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100/hifmc100_os.c +@@ -0,0 +1,233 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "../../mtdcore.h" ++#include "hifmc100.h" ++#include "hifmc100_os.h" ++ ++/*****************************************************************************/ ++static int hifmc100_spi_nand_pre_probe(struct nand_chip *chip) ++{ ++ uint8_t nand_maf_id; ++ struct hifmc_host *host = chip->priv; ++ ++ /* Reset the chip first */ ++ host->send_cmd_reset(host); ++ udelay(1000); ++ ++ /* Check the ID */ ++ host->offset = 0; ++ memset((unsigned char *)(chip->IO_ADDR_R), 0, 0x10); ++ host->send_cmd_readid(host); ++ nand_maf_id = hifmc_readb(chip->IO_ADDR_R); ++ ++ if (nand_maf_id == 0x00 || nand_maf_id == 0xff) { ++ printk("Cannot found a valid SPI Nand Device\n"); ++ return 1; ++ } ++ ++ return 0; ++} ++/*****************************************************************************/ ++static int hifmc_nand_scan(struct mtd_info *mtd) ++{ ++ int result = 0; ++ unsigned char cs, chip_num = CONFIG_SPI_NAND_MAX_CHIP_NUM; ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ ++ for (cs = 0; chip_num && (cs < HIFMC_MAX_CHIP_NUM); cs++) { ++ if (hifmc_cs_user[cs]) { ++ FMC_PR(BT_DBG, "\t\t*-Current CS(%d) is occupied.\n", ++ cs); ++ continue; ++ } ++ ++ host->cmd_op.cs = cs; ++ ++ if (hifmc100_spi_nand_pre_probe(chip)) ++ return -ENODEV; ++ ++ FMC_PR(BT_DBG, "\t\t*-Scan SPI nand flash on CS: %d\n", cs); ++ if (nand_scan(mtd, chip_num)) ++ continue; ++ chip_num--; ++ } ++ ++ if (chip_num == CONFIG_SPI_NAND_MAX_CHIP_NUM) ++ result = -ENXIO; ++ else ++ result = 0; ++ ++ return result; ++} ++ ++/*****************************************************************************/ ++static int hisi_spi_nand_probe(struct platform_device *pltdev) ++{ ++ int len, result = 0; ++ struct hifmc_host *host; ++ struct nand_chip *chip; ++ struct mtd_info *mtd; ++ struct device *dev = &pltdev->dev; ++ struct device_node *np = NULL; ++ struct hisi_fmc *fmc = dev_get_drvdata(dev->parent); ++ ++ FMC_PR(BT_DBG, "\t*-Start SPI Nand flash driver probe\n"); ++ ++ if (!fmc) { ++ dev_err(dev, "get mfd fmc devices failed\n"); ++ return -ENXIO; ++ } ++ ++ len = sizeof(struct hifmc_host) + sizeof(struct nand_chip) ++ + sizeof(struct mtd_info); ++ host = devm_kzalloc(dev, len, GFP_KERNEL); ++ if (!host) ++ return -ENOMEM; ++ memset((char *)host, 0, len); ++ ++ platform_set_drvdata(pltdev, host); ++ host->dev = &pltdev->dev; ++ ++ host->chip = chip = (struct nand_chip *)&host[1]; ++ host->mtd = mtd = nand_to_mtd(chip); ++ ++ host->regbase = fmc->regbase; ++ host->iobase = fmc->iobase; ++ host->clk = fmc->clk; ++ host->lock = &fmc->lock; ++ host->buffer = fmc->buffer; ++ host->dma_buffer = fmc->dma_buffer; ++ ++ memset((char *)host->iobase, 0xff, SPI_NAND_BUFFER_LEN); ++ chip->IO_ADDR_R = chip->IO_ADDR_W = host->iobase; ++ ++ chip->priv = host; ++ result = hifmc100_spi_nand_init(chip); ++ if (result) { ++ FMC_PR(BT_DBG, "\t|-SPI Nand init failed, ret: %d\n", result); ++ result = -ENODEV; ++ goto fail; ++ } ++ ++ np = of_get_next_available_child(dev->of_node, NULL); ++ mtd->name = np->name; ++ mtd->type = MTD_NANDFLASH; ++ mtd->priv = chip; ++ mtd->owner = THIS_MODULE; ++ ++ result = of_property_read_u32(np, "spi-max-frequency", &host->clkrate); ++ if (result) ++ goto fail; ++ ++ result = hifmc_nand_scan(mtd); ++ if (result) { ++ FMC_PR(BT_DBG, "\t|-Scan SPI Nand failed.\n"); ++ goto fail; ++ } ++ ++ result = mtd_device_register(mtd, NULL, 0); ++ if (!result) { ++ FMC_PR(BT_DBG, "\t*-End driver probe !!\n"); ++ return 0; ++ } ++ ++ result = -ENODEV; ++fail: ++ clk_disable_unprepare(host->clk); ++ nand_release(mtd); ++ ++ DB_MSG("Error: driver probe, result: %d\n", result); ++ return result; ++} ++ ++/*****************************************************************************/ ++static int hisi_spi_nand_remove(struct platform_device *pltdev) ++{ ++ struct hifmc_host *host = platform_get_drvdata(pltdev); ++ ++ clk_disable_unprepare(host->clk); ++ nand_release(host->mtd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++/*****************************************************************************/ ++static int hifmc100_os_suspend(struct platform_device *pltdev, ++ pm_message_t state) ++{ ++ struct hifmc_host *host = platform_get_drvdata(pltdev); ++ ++ if (host && host->suspend) ++ return (host->suspend)(pltdev, state); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++static int hifmc100_os_resume(struct platform_device *pltdev) ++{ ++ struct hifmc_host *host = platform_get_drvdata(pltdev); ++ ++ if (host && host->resume) ++ return (host->resume)(pltdev); ++ ++ return 0; ++} ++#endif /* End of CONFIG_PM */ ++/*****************************************************************************/ ++static const struct of_device_id hisi_spi_nand_dt_ids[] = { ++ { .compatible = "hisilicon,hisi-spi-nand"}, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, hisi_spi_nand_dt_ids); ++ ++static struct platform_driver hisi_spi_nand_driver = { ++ .driver = { ++ .name = "hisi_spi_nand", ++ .of_match_table = hisi_spi_nand_dt_ids, ++ }, ++ .probe = hisi_spi_nand_probe, ++ .remove = hisi_spi_nand_remove, ++#ifdef CONFIG_PM ++ .suspend = hifmc100_os_suspend, ++ .resume = hifmc100_os_resume, ++#endif ++}; ++module_platform_driver(hisi_spi_nand_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("BVT_BSP"); ++MODULE_DESCRIPTION("Hisilicon Flash Memory Controller V100 SPI Nand Driver"); +diff --git a/drivers/mtd/nand/hifmc100/hifmc100_os.h b/drivers/mtd/nand/hifmc100/hifmc100_os.h +new file mode 100644 +index 0000000..22199dc +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100/hifmc100_os.h +@@ -0,0 +1,30 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef __HIFMC100_OS_H__ ++#define __HIFMC100_OS_H__ ++ ++/*****************************************************************************/ ++#define SPI_NAND_MAX_PAGESIZE 4096 ++#define SPI_NAND_MAX_OOBSIZE 256 ++ ++#define SPI_NAND_BUFFER_LEN (SPI_NAND_MAX_PAGESIZE + SPI_NAND_MAX_OOBSIZE) ++ ++#endif /* End of __HIFMC100_OS_H__ */ +diff --git a/drivers/mtd/nand/hifmc100/hifmc100_spi_general.c b/drivers/mtd/nand/hifmc100/hifmc100_spi_general.c +new file mode 100644 +index 0000000..ee4d08f +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100/hifmc100_spi_general.c +@@ -0,0 +1,254 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/* ++ Send set/get features command to SPI Nand flash ++*/ ++u_char spi_nand_feature_op(struct hifmc_spi *spi, u_char op, u_char addr, ++ u_char val) ++{ ++ unsigned int reg; ++ const char *str[] = {"Get", "Set"}; ++ struct hifmc_host *host = (struct hifmc_host *)spi->host; ++ ++ if ((GET_OP == op) && (STATUS_ADDR == addr)) { ++ if (SR_DBG) ++ pr_info("\n"); ++ FMC_PR(SR_DBG, "\t\t|*-Start Get Status\n"); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) | OP_CFG_OEN_EN; ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(SR_DBG, "\t\t||-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ reg = FMC_OP_READ_STATUS_EN | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(SR_DBG, "\t\t||-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++ val = hifmc_readl(host, FMC_STATUS); ++ FMC_PR(SR_DBG, "\t\t|*-End Get Status, result: %#x\n", val); ++ ++ return val; ++ } ++ ++ FMC_PR(FT_DBG, "\t|||*-Start %s feature, addr[%#x]\n", str[op], addr); ++ ++ hifmc100_ecc0_switch(host, ENABLE); ++ ++ reg = FMC_CMD_CMD1(op ? SPI_CMD_SET_FEATURE : SPI_CMD_GET_FEATURES); ++ hifmc_writel(host, FMC_CMD, reg); ++ FMC_PR(FT_DBG, "\t||||-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ hifmc_writel(host, FMC_ADDRL, addr); ++ FMC_PR(FT_DBG, "\t||||-Set ADDRL[%#x]%#x\n", FMC_ADDRL, addr); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) ++ | OP_CFG_ADDR_NUM(FEATURES_OP_ADDR_NUM) ++ | OP_CFG_OEN_EN; ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(FT_DBG, "\t||||-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ reg = FMC_DATA_NUM_CNT(FEATURES_DATA_LEN); ++ hifmc_writel(host, FMC_DATA_NUM, reg); ++ FMC_PR(FT_DBG, "\t||||-Set DATA_NUM[%#x]%#x\n", FMC_DATA_NUM, reg); ++ ++ reg = FMC_OP_CMD1_EN ++ | FMC_OP_ADDR_EN ++ | FMC_OP_REG_OP_START; ++ ++ if (SET_OP == op) { ++ reg |= FMC_OP_WRITE_DATA_EN; ++ hifmc_writeb(val, host->iobase); ++ FMC_PR(FT_DBG, "\t||||-Write IO[%#lx]%#x\n", (long)host->iobase, ++ *(u_char *)host->iobase); ++ } else ++ reg |= FMC_OP_READ_DATA_EN; ++ ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(FT_DBG, "\t||||-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++ if (GET_OP == op) { ++ val = hifmc_readb(host->iobase); ++ FMC_PR(FT_DBG, "\t||||-Read IO[%#lx]%#x\n", (long)host->iobase, ++ *(u_char *)host->iobase); ++ } ++ ++ hifmc100_ecc0_switch(host, DISABLE); ++ ++ FMC_PR(FT_DBG, "\t|||*-End %s Feature[%#x]:%#x\n", str[op], addr, val); ++ ++ return val; ++} ++ ++/*****************************************************************************/ ++/* ++ Read status[C0H]:[0]bit OIP, judge whether the device is busy or not ++*/ ++static int spi_general_wait_ready(struct hifmc_spi *spi) ++{ ++ unsigned char status; ++ unsigned long deadline = jiffies + FMC_MAX_READY_WAIT_JIFFIES; ++ struct hifmc_host *host = (struct hifmc_host *)spi->host; ++ ++ do { ++ status = spi_nand_feature_op(spi, GET_OP, STATUS_ADDR, 0); ++ if (!(status & STATUS_OIP_MASK)) { ++ if ((host->cmd_op.l_cmd == NAND_CMD_ERASE2) ++ && (status & STATUS_E_FAIL_MASK)) ++ return status; ++ if ((host->cmd_op.l_cmd == NAND_CMD_PAGEPROG) ++ && (status & STATUS_P_FAIL_MASK)) ++ return status; ++ return 0; ++ } ++ ++ cond_resched(); ++ ++ } while (!time_after_eq(jiffies, deadline)); ++ ++ DB_MSG("Error: SPI Nand wait ready timeout, status: %#x\n", status); ++ ++ return 1; ++} ++ ++/*****************************************************************************/ ++/* ++ Send write enable cmd to SPI Nand, status[C0H]:[2]bit WEL must be set 1 ++*/ ++static int spi_general_write_enable(struct hifmc_spi *spi) ++{ ++ unsigned int reg; ++ struct hifmc_host *host = (struct hifmc_host *)spi->host; ++ ++ if (WE_DBG) ++ pr_info("\n"); ++ FMC_PR(WE_DBG, "\t|*-Start Write Enable\n"); ++ ++ reg = spi_nand_feature_op(spi, GET_OP, STATUS_ADDR, 0); ++ if (reg & STATUS_WEL_MASK) { ++ FMC_PR(WE_DBG, "\t||-Write Enable was opened! reg: %#x\n", ++ reg); ++ return 0; ++ } ++ ++ reg = hifmc_readl(host, FMC_GLOBAL_CFG); ++ FMC_PR(WE_DBG, "\t||-Get GLOBAL_CFG[%#x]%#x\n", FMC_GLOBAL_CFG, reg); ++ if (reg & FMC_GLOBAL_CFG_WP_ENABLE) { ++ reg &= ~FMC_GLOBAL_CFG_WP_ENABLE; ++ hifmc_writel(host, FMC_GLOBAL_CFG, reg); ++ FMC_PR(WE_DBG, "\t||-Set GLOBAL_CFG[%#x]%#x\n", ++ FMC_GLOBAL_CFG, reg); ++ } ++ ++ reg = FMC_CMD_CMD1(SPI_CMD_WREN); ++ hifmc_writel(host, FMC_CMD, reg); ++ FMC_PR(WE_DBG, "\t||-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) | OP_CFG_OEN_EN; ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(WE_DBG, "\t||-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ reg = FMC_OP_CMD1_EN | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(WE_DBG, "\t||-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++#if WE_DBG ++ spi->driver->wait_ready(spi); ++ ++ reg = spi_nand_feature_op(spi, GET_OP, STATUS_ADDR, 0); ++ if (reg & STATUS_WEL_MASK) ++ FMC_PR(WE_DBG, "\t||-Write Enable success. reg: %#x\n", reg); ++ else { ++ DB_MSG("Error: Write Enable failed! reg: %#x\n", reg); ++ return reg; ++ } ++#endif ++ ++ FMC_PR(WE_DBG, "\t|*-End Write Enable\n"); ++ return 0; ++} ++ ++/*****************************************************************************/ ++/* ++ judge whether SPI Nand support QUAD read/write or not ++*/ ++static int spi_is_quad(struct hifmc_spi *spi) ++{ ++ const char *if_str[] = {"STD", "DUAL", "DIO", "QUAD", "QIO"}; ++ ++ FMC_PR(QE_DBG, "\t\t|||*-SPI read iftype: %s write iftype: %s\n", ++ if_str[spi->read->iftype], if_str[spi->write->iftype]); ++ ++ if ((IF_TYPE_QUAD == spi->read->iftype) ++ || (IF_TYPE_QIO == spi->read->iftype) ++ || (IF_TYPE_QUAD == spi->write->iftype) ++ || (IF_TYPE_QIO == spi->write->iftype)) ++ return 1; ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++/* ++ Send set features cmd to SPI Nand, feature[B0H]:[0]bit QE would be set ++*/ ++static int spi_general_qe_enable(struct hifmc_spi *spi) ++{ ++ unsigned int reg, op; ++ const char *str[] = {"Disable", "Enable"}; ++ ++ FMC_PR(QE_DBG, "\t||*-Start SPI Nand flash QE\n"); ++ ++ op = spi_is_quad(spi); ++ ++ FMC_PR(QE_DBG, "\t|||*-End Quad check, SPI Nand %s Quad.\n", str[op]); ++ ++ reg = spi_nand_feature_op(spi, GET_OP, FEATURE_ADDR, 0); ++ FMC_PR(QE_DBG, "\t|||-Get [%#x]feature: %#x\n", FEATURE_ADDR, reg); ++ if ((reg & FEATURE_QE_ENABLE) == op) { ++ FMC_PR(QE_DBG, "\t||*-SPI Nand quad was %sd!\n", str[op]); ++ return op; ++ } ++ ++ if (op == ENABLE) ++ reg |= FEATURE_QE_ENABLE; ++ else ++ reg &= ~FEATURE_QE_ENABLE; ++ ++ spi_nand_feature_op(spi, SET_OP, FEATURE_ADDR, reg); ++ FMC_PR(QE_DBG, "\t|||-SPI Nand %s Quad\n", str[op]); ++ ++ spi->driver->wait_ready(spi); ++ ++ reg = spi_nand_feature_op(spi, GET_OP, FEATURE_ADDR, 0); ++ if ((reg & FEATURE_QE_ENABLE) == op) ++ FMC_PR(QE_DBG, "\t|||-SPI Nand %s Quad succeed!\n", str[op]); ++ else ++ DB_MSG("Error: %s Quad failed! reg: %#x\n", str[op], reg); ++ ++ FMC_PR(QE_DBG, "\t||*-End SPI Nand %s Quad.\n", str[op]); ++ ++ return op; ++} +diff --git a/drivers/mtd/nand/hifmc100/hifmc_spi_nand_ids.c b/drivers/mtd/nand/hifmc100/hifmc_spi_nand_ids.c +new file mode 100644 +index 0000000..6b35086 +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100/hifmc_spi_nand_ids.c +@@ -0,0 +1,1490 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../hinfc_gen.h" ++#include "hifmc100.h" ++ ++/*****************************************************************************/ ++SET_READ_STD(1, INFINITE, 24); ++ ++SET_READ_FAST(1, INFINITE, 80); ++SET_READ_FAST(1, INFINITE, 104); ++SET_READ_FAST(1, INFINITE, 108); ++SET_READ_FAST(1, INFINITE, 120); ++ ++SET_READ_DUAL(1, INFINITE, 80); ++SET_READ_DUAL(1, INFINITE, 104); ++SET_READ_DUAL(1, INFINITE, 108); ++SET_READ_DUAL(1, INFINITE, 120); ++ ++SET_READ_DUAL_ADDR(1, INFINITE, 80); ++SET_READ_DUAL_ADDR(1, INFINITE, 104); ++SET_READ_DUAL_ADDR(1, INFINITE, 108); ++SET_READ_DUAL_ADDR(1, INFINITE, 120); ++ ++SET_READ_QUAD(1, INFINITE, 80); ++SET_READ_QUAD(1, INFINITE, 104); ++SET_READ_QUAD(1, INFINITE, 108); ++SET_READ_QUAD(1, INFINITE, 120); ++ ++SET_READ_QUAD_ADDR(1, INFINITE, 80); ++SET_READ_QUAD_ADDR(2, INFINITE, 80); ++SET_READ_QUAD_ADDR(1, INFINITE, 104); ++SET_READ_QUAD_ADDR(2, INFINITE, 104); ++SET_READ_QUAD_ADDR(1, INFINITE, 108); ++SET_READ_QUAD_ADDR(1, INFINITE, 120); ++ ++/*****************************************************************************/ ++SET_WRITE_STD(0, 256, 24); ++SET_WRITE_STD(0, 256, 75); ++SET_WRITE_STD(0, 256, 80); ++SET_WRITE_STD(0, 256, 104); ++ ++SET_WRITE_QUAD(0, 256, 80); ++SET_WRITE_QUAD(0, 256, 104); ++SET_WRITE_QUAD(0, 256, 108); ++SET_WRITE_QUAD(0, 256, 120); ++ ++/*****************************************************************************/ ++SET_ERASE_SECTOR_128K(0, _128K, 24); ++SET_ERASE_SECTOR_128K(0, _128K, 75); ++SET_ERASE_SECTOR_128K(0, _128K, 80); ++SET_ERASE_SECTOR_128K(0, _128K, 104); ++ ++SET_ERASE_SECTOR_256K(0, _256K, 24); ++SET_ERASE_SECTOR_256K(0, _256K, 75); ++SET_ERASE_SECTOR_256K(0, _256K, 80); ++SET_ERASE_SECTOR_256K(0, _256K, 104); ++ ++/*****************************************************************************/ ++#include "hifmc100_spi_general.c" ++static struct spi_drv spi_driver_general = { ++ .wait_ready = spi_general_wait_ready, ++ .write_enable = spi_general_write_enable, ++ .qe_enable = spi_general_qe_enable, ++}; ++ ++/* some spi nand flash default QUAD enable, needn't to set qe enable */ ++static struct spi_drv spi_driver_no_qe = { ++ .wait_ready = spi_general_wait_ready, ++ .write_enable = spi_general_write_enable, ++}; ++ ++/*****************************************************************************/ ++#define SPI_NAND_ID_TAB_VER "2.6" ++ ++/******* SPI Nand ID Table *************************************************** ++* Version Manufacturer Chip Name Size Operation ++* 1.0 ESMT F50L512M41A 64MB Add 5 chip ++* GD 5F1GQ4UAYIG 128MB ++* GD 5F2GQ4UAYIG 256MB ++* GD 5F4GQ4UAYIG 512MB ++* GD 5F4GQ4UBYIG 512MB ++* 1.1 ESMT F50L1G41A 128MB Add 2 chip ++* Winbond W25N01GV 128MB ++* 1.2 GD 5F1GQ4UBYIG 128MB Add 2 chip ++* GD 5F2GQ4UBYIG 256MB ++* 1.3 ATO ATO25D1GA 128MB Add 1 chip ++* 1.4 MXIC MX35LF1GE4AB 128MB Add 2 chip ++* MXIC MX35LF2GE4AB 256MB (SOP-16Pin) ++* 1.5 Paragon PN26G01A 128MB Add 1 chip ++* 1.6 All-flash AFS1GQ4UAC 128MB Add 1 chip ++* 1.7 TOSHIBA TC58CVG0S3H 128MB Add 2 chip ++* TOSHIBA TC58CVG2S0H 512MB ++* 1.8 ALL-flash AFS2GQ4UAD 256MB Add 2 chip ++* Paragon PN26G02A 256MB ++* 1.9 TOSHIBA TC58CVG1S3H 256MB Add 1 chip ++* 2.0 HeYangTek HYF1GQ4UAACAE 128MB Add 3 chip ++* HeYangTek HYF2GQ4UAACAE 256MB ++* HeYangTek HYF4GQ4UAACBE 512MB ++* 2.1 Micron MT29F1G01ABA 128MB Add 6 chip ++ Paragon 1.8V PN26Q01AWSIUG 128MB ++ TOSHIBA 1.8V TC58CYG0S3H 128MB ++ TOSHIBA 1.8V TC58CYG1S3H 256MB ++ TOSHIBA 1.8V TC58CYG2S0H 512MB ++ Winbond 1.8V W25N01GWZEIG 128MB ++* 2.2 Micron MT29F2G01ABA 256MB Add 1 chip ++* 2.3 MXIC MX35LF2G14AC 256MB Add 1 chip ++* 2.4 GD 1.8V 5F4GQ4RAYIG 512MB Add 1 chip ++* 2.5 GD 1.8V 5F2GQ4RB9IGR 256MB Add 1 chip ++* 2.6 MXIC 1.8V MX35UF1G14AC 128MB Add 4 chip ++* MXIC 1.8V MX35UF2G14AC 256MB ++* Micron 1.8V MT29F1G01ABB 128MB ++* Micron 1.8V MT29F2G01ABB 256MB ++******************************************************************************/ ++struct spi_nand_info hifmc_spi_nand_flash_table[] = { ++ /* Micron MT29F1G01ABA 1GBit */ ++ { ++ .name = "MT29F1G01ABA", ++ .id = {0x2C, 0x14}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(2, INFINITE, 80), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 80), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* Micron MT29F1G01ABB 1GBit 1.8V */ ++ { ++ .name = "MT29F1G01ABB", ++ .id = {0x2C, 0x15}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(2, INFINITE, 80), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 80), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* Micron MT29F2G01ABA 2GBit */ ++ { ++ .name = "MT29F2G01ABA", ++ .id = {0x2C, 0x24}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 108), ++ &READ_DUAL(1, INFINITE, 108), ++ &READ_DUAL_ADDR(1, INFINITE, 108), ++ &READ_QUAD(1, INFINITE, 108), ++ &READ_QUAD_ADDR(2, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 108), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 80), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* Micron MT29F2G01ABB 2GBit 1.8V */ ++ { ++ .name = "MT29F2G01ABB", ++ .id = {0x2C, 0x25}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(2, INFINITE, 80), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 80), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* ESMT F50L512M41A 512Mbit */ ++ { ++ .name = "F50L512M41A", ++ .id = {0xC8, 0x20}, ++ .id_len = 2, ++ .chipsize = _64M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* ESMT F50L1G41A 1Gbit */ ++ { ++ .name = "F50L1G41A", ++ .id = {0xC8, 0x21}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* GD 5F1GQ4UAYIG 1Gbit */ ++ { ++ .name = "5F1GQ4UAYIG", ++ .id = {0xc8, 0xf1}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 120), ++ &READ_DUAL(1, INFINITE, 120), ++ &READ_DUAL_ADDR(1, INFINITE, 120), ++ &READ_QUAD(1, INFINITE, 120), ++ &READ_QUAD_ADDR(1, INFINITE, 120), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 120), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* GD 5F1GQ4UBYIG 1Gbit */ ++ { ++ .name = "5F1GQ4UBYIG", ++ .id = {0xc8, 0xd1}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 120), ++ &READ_DUAL(1, INFINITE, 120), ++ &READ_DUAL_ADDR(1, INFINITE, 120), ++ &READ_QUAD(1, INFINITE, 120), ++ &READ_QUAD_ADDR(1, INFINITE, 120), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 120), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* GD 5F2GQ4UAYIG 2Gbit */ ++ { ++ .name = "5F2GQ4UAYIG", ++ .id = {0xc8, 0xf2}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 120), ++ &READ_DUAL(1, INFINITE, 120), ++ &READ_DUAL_ADDR(1, INFINITE, 120), ++ &READ_QUAD(1, INFINITE, 120), ++ &READ_QUAD_ADDR(1, INFINITE, 120), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 120), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* GD 5F2GQ4UBYIG 2Gbit */ ++ { ++ .name = "5F2GQ4UBYIG", ++ .id = {0xc8, 0xd2}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 120), ++ &READ_DUAL(1, INFINITE, 120), ++ &READ_DUAL_ADDR(1, INFINITE, 120), ++ &READ_QUAD(1, INFINITE, 120), ++ &READ_QUAD_ADDR(1, INFINITE, 120), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 120), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* GD 5F4GQ4UAYIG 4Gbit */ ++ { ++ .name = "5F4GQ4UAYIG", ++ .id = {0xc8, 0xf4}, ++ .id_len = 2, ++ .chipsize = _512M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 120), ++ &READ_DUAL(1, INFINITE, 120), ++ &READ_DUAL_ADDR(1, INFINITE, 120), ++ &READ_QUAD(1, INFINITE, 120), ++ &READ_QUAD_ADDR(1, INFINITE, 120), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 120), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* GD 5F4GQ4UBYIG 4Gbit */ ++ { ++ .name = "5F4GQ4UBYIG", ++ .id = {0xc8, 0xd4}, ++ .id_len = 2, ++ .chipsize = _512M, ++ .erasesize = _256K, ++ .pagesize = _4K, ++ .oobsize = 256, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 120), ++ &READ_DUAL(1, INFINITE, 120), ++ &READ_DUAL_ADDR(1, INFINITE, 120), ++ &READ_QUAD(1, INFINITE, 120), ++ &READ_QUAD_ADDR(1, INFINITE, 120), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 120), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_256K(0, _256K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* GD 1.8V GD5F2GQ4RB9IGR 2Gbit */ ++ { ++ .name = "5F2GQ4RB9IGR", ++ .id = {0xc8, 0xc2}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_DUAL_ADDR(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ &READ_QUAD_ADDR(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* GD 1.8V 5F4GQ4RAYIG 4Gbit */ ++ { ++ .name = "5F4GQ4RAYIG", ++ .id = {0xc8, 0xe4}, ++ .id_len = 2, ++ .chipsize = _512M, ++ .erasesize = _256K, ++ .pagesize = _4K, ++ .oobsize = 256, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_DUAL_ADDR(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ &READ_QUAD_ADDR(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_256K(0, _256K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* Winbond W25N01GV 1Gbit */ ++ { ++ .name = "W25N01GV", ++ .id = {0xef, 0xaa, 0x21}, ++ .id_len = 3, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_DUAL_ADDR(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ &READ_QUAD_ADDR(2, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* Winbond W25N01GWZEIG 1Gbit 1.8V */ ++ { ++ .name = "W25N01GWZEIG", ++ .id = {0xef, 0xba, 0x21}, ++ .id_len = 3, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_DUAL_ADDR(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ &READ_QUAD_ADDR(2, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* ATO ATO25D1GA 1Gbit */ ++ { ++ .name = "ATO25D1GA", ++ .id = {0x9b, 0x12}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* MXIC MX35LF1GE4AB 1Gbit */ ++ { ++ .name = "MX35LF1GE4AB", ++ .id = {0xc2, 0x12}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* MXIC MX35UF1G14AC 1Gbit 1.8V */ ++ { ++ .name = "MX35UF1G14AC", ++ .id = {0xc2, 0x90}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 104), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* MXIC MX35LF2GE4AB 2Gbit SOP-16Pin */ ++ { ++ .name = "MX35LF2GE4AB", ++ .id = {0xc2, 0x22}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* MXIC MX35LF2G14AC 2GBit */ ++ { ++ .name = "MX35LF2G14AC", ++ .id = {0xc2, 0x20}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* MXIC MX35UF2G14AC 2Gbit 1.8V */ ++ { ++ .name = "MX35UF2G14AC", ++ .id = {0xc2, 0xa0}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 104), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* Paragon PN26G01AWSIUG 1Gbit 1.8V */ ++ { ++ .name = "PN26G01AW", ++ .id = {0xa1, 0xc1}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_DUAL_ADDR(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ &READ_QUAD_ADDR(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 75), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* Paragon PN26G01A 1Gbit */ ++ { ++ .name = "PN26G01A", ++ .id = {0xa1, 0xe1}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 108), ++ &READ_DUAL(1, INFINITE, 108), ++ &READ_DUAL_ADDR(1, INFINITE, 108), ++ &READ_QUAD(1, INFINITE, 108), ++ &READ_QUAD_ADDR(1, INFINITE, 108), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 108), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* Paragon PN26G02A 2Gbit */ ++ { ++ .name = "PN26G02A", ++ .id = {0xa1, 0xe2}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 108), ++ &READ_DUAL(1, INFINITE, 108), ++ &READ_DUAL_ADDR(1, INFINITE, 108), ++ &READ_QUAD(1, INFINITE, 108), ++ &READ_QUAD_ADDR(1, INFINITE, 108), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 108), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* All-flash AFS1GQ4UAC 1Gbit */ ++ { ++ .name = "AFS1GQ4UAC", ++ .id = {0xc1, 0x51}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(1, INFINITE, 80), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* All-flash AFS2GQ4UAD 2Gbit */ ++ { ++ .name = "AFS2GQ4UAD", ++ .id = {0xc1, 0x52}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(1, INFINITE, 80), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* TOSHIBA TC58CVG0S3H 1Gbit */ ++ { ++ .name = "TC58CVG0S3H", ++ .id = {0x98, 0xc2}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 104), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* TOSHIBA TC58CYG0S3H 1.8V 1Gbit */ ++ { ++ .name = "TC58CYG0S3H", ++ .id = {0x98, 0xb2}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 104), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* TOSHIBA TC58CVG1S3H 2Gbit */ ++ { ++ .name = "TC58CVG1S3H", ++ .id = {0x98, 0xcb}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 104), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* TOSHIBA TC58CYG1S3H 1.8V 2Gbit */ ++ { ++ .name = "TC58CYG1S3H", ++ .id = {0x98, 0xbb}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 75), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 75), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* TOSHIBA TC58CVG2S0H 4Gbit */ ++ { ++ .name = "TC58CVG2S0H", ++ .id = {0x98, 0xcd}, ++ .id_len = 2, ++ .chipsize = _512M, ++ .erasesize = _256K, ++ .pagesize = _4K, ++ .oobsize = 256, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_256K(0, _256K, 104), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* TOSHIBA TC58CYG2S0H 1.8V 4Gbit */ ++ { ++ .name = "TC58CYG2S0H", ++ .id = {0x98, 0xbd}, ++ .id_len = 2, ++ .chipsize = _512M, ++ .erasesize = _256K, ++ .pagesize = _4K, ++ .oobsize = 256, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 75), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_256K(0, _256K, 75), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* HeYangTek HYF1GQ4UAACAE 1Gbit */ ++ { ++ .name = "HYF1GQ4UAACAE", ++ .id = {0xc9, 0x51}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(1, INFINITE, 80), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 80), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* HeYangTek HYF2GQ4UAACAE 2Gbit */ ++ { ++ .name = "HYF2GQ4UAACAE", ++ .id = {0xc9, 0x52}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(1, INFINITE, 80), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 80), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* HeYangTek HYF4GQ4UAACBE 4Gbit */ ++ { ++ .name = "HYF4GQ4UAACBE", ++ .id = {0xc9, 0xd4}, ++ .id_len = 2, ++ .chipsize = _512M, ++ .erasesize = _256K, ++ .pagesize = _4K, ++ .oobsize = 256, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(1, INFINITE, 80), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_256K(0, _256K, 80), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ { .id_len = 0, }, ++}; ++ ++/*****************************************************************************/ ++static void hifmc100_spi_nand_search_rw(struct spi_nand_info *spiinfo, ++ struct spi_op *spiop_rw, u_int iftype, u_int max_dummy, int rw_type) ++{ ++ int ix = 0; ++ struct spi_op **spiop, **fitspiop; ++ ++ for (fitspiop = spiop = (rw_type ? spiinfo->write : spiinfo->read); ++ (*spiop) && ix < MAX_SPI_OP; spiop++, ix++) { ++ if (((*spiop)->iftype & iftype) ++ && ((*spiop)->dummy <= max_dummy) ++ && (*fitspiop)->iftype < (*spiop)->iftype) ++ fitspiop = spiop; ++ } ++ memcpy(spiop_rw, (*fitspiop), sizeof(struct spi_op)); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_spi_nand_get_erase(struct spi_nand_info *spiinfo, ++ struct spi_op *spiop_erase) ++{ ++ int ix; ++ ++ spiop_erase->size = 0; ++ for (ix = 0; ix < MAX_SPI_OP; ix++) { ++ if (spiinfo->erase[ix] == NULL) ++ break; ++ if (spiinfo->erasesize == spiinfo->erase[ix]->size) { ++ memcpy(&spiop_erase[ix], spiinfo->erase[ix], ++ sizeof(struct spi_op)); ++ break; ++ } ++ } ++} ++ ++/*****************************************************************************/ ++static void hifmc100_map_spi_op(struct hifmc_spi *spi) ++{ ++ unsigned char ix; ++ const int iftype_read[] = { ++ SPI_IF_READ_STD, IF_TYPE_STD, ++ SPI_IF_READ_FAST, IF_TYPE_STD, ++ SPI_IF_READ_DUAL, IF_TYPE_DUAL, ++ SPI_IF_READ_DUAL_ADDR, IF_TYPE_DIO, ++ SPI_IF_READ_QUAD, IF_TYPE_QUAD, ++ SPI_IF_READ_QUAD_ADDR, IF_TYPE_QIO, ++ 0, 0, ++ }; ++ const int iftype_write[] = { ++ SPI_IF_WRITE_STD, IF_TYPE_STD, ++ SPI_IF_WRITE_QUAD, IF_TYPE_QUAD, ++ 0, 0, ++ }; ++ const char *if_str[] = {"STD", "DUAL", "DIO", "QUAD", "QIO"}; ++ ++ FMC_PR(BT_DBG, "\t||*-Start Get SPI operation iftype\n"); ++ ++ for (ix = 0; iftype_write[ix]; ix += 2) { ++ if (spi->write->iftype == iftype_write[ix]) { ++ spi->write->iftype = iftype_write[ix + 1]; ++ break; ++ } ++ } ++ FMC_PR(BT_DBG, "\t|||-Get best write iftype: %s \n", ++ if_str[spi->write->iftype]); ++ ++ for (ix = 0; iftype_read[ix]; ix += 2) { ++ if (spi->read->iftype == iftype_read[ix]) { ++ spi->read->iftype = iftype_read[ix + 1]; ++ break; ++ } ++ } ++ FMC_PR(BT_DBG, "\t|||-Get best read iftype: %s \n", ++ if_str[spi->read->iftype]); ++ ++ spi->erase->iftype = IF_TYPE_STD; ++ FMC_PR(BT_DBG, "\t|||-Get best erase iftype: %s \n", ++ if_str[spi->erase->iftype]); ++ ++ FMC_PR(BT_DBG, "\t||*-End Get SPI operation iftype \n"); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_spi_ids_probe(struct mtd_info *mtd, ++ struct spi_nand_info *spi_dev) ++{ ++ unsigned int reg; ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ struct hifmc_spi *spi = host->spi; ++ ++ FMC_PR(BT_DBG, "\t|*-Start match SPI operation & chip init\n"); ++ ++ spi->host = host; ++ spi->name = spi_dev->name; ++ spi->driver = spi_dev->driver; ++ ++ hifmc100_spi_nand_search_rw(spi_dev, spi->read, ++ HIFMC_SPI_NAND_SUPPORT_READ, ++ HIFMC_SPI_NAND_SUPPORT_MAX_DUMMY, RW_OP_READ); ++ FMC_PR(BT_DBG, "\t||-Save spi->read op cmd:%#x\n", spi->read->cmd); ++ ++ hifmc100_spi_nand_search_rw(spi_dev, spi->write, ++ HIFMC_SPI_NAND_SUPPORT_WRITE, ++ HIFMC_SPI_NAND_SUPPORT_MAX_DUMMY, RW_OP_WRITE); ++ FMC_PR(BT_DBG, "\t||-Save spi->write op cmd:%#x\n", spi->write->cmd); ++ ++ hifmc100_spi_nand_get_erase(spi_dev, spi->erase); ++ FMC_PR(BT_DBG, "\t||-Save spi->erase op cmd:%#x\n", spi->erase->cmd); ++ ++ hifmc100_map_spi_op(spi); ++ ++ if (spi->driver->qe_enable) ++ spi->driver->qe_enable(spi); ++ ++ /* Disable write protection */ ++ reg = spi_nand_feature_op(spi, GET_OP, PROTECT_ADDR, 0); ++ FMC_PR(BT_DBG, "\t||-Get protect status[%#x]: %#x\n", PROTECT_ADDR, ++ reg); ++ if (ANY_BP_ENABLE(reg)) { ++ reg &= ~ALL_BP_MASK; ++ spi_nand_feature_op(spi, SET_OP, PROTECT_ADDR, reg); ++ FMC_PR(BT_DBG, "\t||-Set [%#x]FT %#x\n", PROTECT_ADDR, reg); ++ ++ spi->driver->wait_ready(spi); ++ ++ reg = spi_nand_feature_op(spi, GET_OP, PROTECT_ADDR, 0); ++ FMC_PR(BT_DBG, "\t||-Check BP disable result: %#x\n", reg); ++ if (ANY_BP_ENABLE(reg)) ++ DB_MSG("Error: Write protection disable failed!\n"); ++ } ++ ++ /* Disable chip internal ECC */ ++ reg = spi_nand_feature_op(spi, GET_OP, FEATURE_ADDR, 0); ++ FMC_PR(BT_DBG, "\t||-Get feature status[%#x]: %#x\n", FEATURE_ADDR, ++ reg); ++ if (reg & FEATURE_ECC_ENABLE) { ++ reg &= ~FEATURE_ECC_ENABLE; ++ spi_nand_feature_op(spi, SET_OP, FEATURE_ADDR, reg); ++ FMC_PR(BT_DBG, "\t||-Set [%#x]FT: %#x\n", FEATURE_ADDR, reg); ++ ++ spi->driver->wait_ready(spi); ++ ++ reg = spi_nand_feature_op(spi, GET_OP, FEATURE_ADDR, 0); ++ FMC_PR(BT_DBG, "\t||-Check internal ECC disable result: %#x\n", ++ reg); ++ if (reg & FEATURE_ECC_ENABLE) ++ DB_MSG("Error: Chip internal ECC disable failed!\n"); ++ } ++ ++ hifmc_cs_user[host->cmd_op.cs]++; ++ ++ FMC_PR(BT_DBG, "\t|*-End match SPI operation & chip init\n"); ++} ++ ++static struct nand_flash_dev spi_nand_dev; ++/*****************************************************************************/ ++static struct nand_flash_dev *spi_nand_get_flash_info(struct mtd_info *mtd, ++ unsigned char *id) ++{ ++ unsigned char ix, len = 0; ++ char buffer[100]; ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ struct spi_nand_info *spi_dev = hifmc_spi_nand_flash_table; ++ struct nand_flash_dev *type = &spi_nand_dev; ++ ++ FMC_PR(BT_DBG, "\t*-Start find SPI Nand flash\n"); ++ ++ len = sprintf(buffer, "SPI Nand(cs %d) ID: %#x %#x", ++ host->cmd_op.cs, id[0], id[1]); ++ ++ for (; spi_dev->id_len; spi_dev++) { ++ if (memcmp(id, spi_dev->id, spi_dev->id_len)) ++ continue; ++ ++ for (ix = 2; ix < spi_dev->id_len; ix++) ++ len += sprintf(buffer + len, " %#x", id[ix]); ++ pr_info("%s\n", buffer); ++ ++ FMC_PR(BT_DBG, "\t||-CS(%d) found SPI Nand: %s\n", ++ host->cmd_op.cs, spi_dev->name); ++ ++ type->name = spi_dev->name; ++ memcpy(type->id, spi_dev->id, spi_dev->id_len); ++ type->pagesize = spi_dev->pagesize; ++ type->chipsize = spi_dev->chipsize >> 20; ++ type->erasesize = spi_dev->erasesize; ++ type->id_len = spi_dev->id_len; ++ type->oobsize = spi_dev->oobsize; ++ FMC_PR(BT_DBG, "\t|-Save struct nand_flash_dev info\n"); ++ ++ mtd->oobsize = spi_dev->oobsize; ++ mtd->erasesize = spi_dev->erasesize; ++ mtd->writesize = spi_dev->pagesize; ++ chip->chipsize = spi_dev->chipsize; ++ ++ hifmc100_spi_ids_probe(mtd, spi_dev); ++ ++ FMC_PR(BT_DBG, "\t*-Found SPI nand: %s\n", spi_dev->name); ++ ++ return type; ++ } ++ ++ FMC_PR(BT_DBG, "\t*-Not found SPI nand flash, %s\n", buffer); ++ ++ return NULL; ++} ++ ++/*****************************************************************************/ ++void hifmc_spi_nand_ids_register(void) ++{ ++ pr_info("SPI Nand ID Table Version %s\n", SPI_NAND_ID_TAB_VER); ++ get_spi_nand_flash_type_hook = spi_nand_get_flash_info; ++} ++ ++#ifdef CONFIG_PM ++/*****************************************************************************/ ++void hifmc100_spi_nand_config(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ struct hifmc_spi *spi = host->spi; ++ static const char const *str[] = {"STD", "DUAL", "DIO", "QUAD", "QIO"}; ++ ++ /* judge whether support QUAD read/write or not, set it if yes */ ++ FMC_PR(PM_DBG, "\t|-SPI read iftype: %s write iftype: %s\n", ++ str[spi->read->iftype], str[spi->write->iftype]); ++ ++ if (spi->driver->qe_enable) ++ spi->driver->qe_enable(spi); ++ ++ /* Disable write protection */ ++ reg = spi_nand_feature_op(spi, GET_OP, PROTECT_ADDR, 0); ++ FMC_PR(PM_DBG, "\t|-Get protect status[%#x]: %#x\n", PROTECT_ADDR, ++ reg); ++ if (ANY_BP_ENABLE(reg)) { ++ reg &= ~ALL_BP_MASK; ++ spi_nand_feature_op(spi, SET_OP, PROTECT_ADDR, reg); ++ FMC_PR(PM_DBG, "\t|-Set [%#x]FT %#x\n", PROTECT_ADDR, reg); ++ ++ spi->driver->wait_ready(spi); ++ ++ reg = spi_nand_feature_op(spi, GET_OP, PROTECT_ADDR, 0); ++ FMC_PR(PM_DBG, "\t|-Check BP disable result: %#x\n", reg); ++ if (ANY_BP_ENABLE(reg)) ++ DB_MSG("Error: Write protection disable failed!\n"); ++ } ++ ++ /* Disable chip internal ECC */ ++ reg = spi_nand_feature_op(spi, GET_OP, FEATURE_ADDR, 0); ++ FMC_PR(PM_DBG, "\t|-Get feature status[%#x]: %#x\n", FEATURE_ADDR, ++ reg); ++ if (reg & FEATURE_ECC_ENABLE) { ++ reg &= ~FEATURE_ECC_ENABLE; ++ spi_nand_feature_op(spi, SET_OP, FEATURE_ADDR, reg); ++ FMC_PR(PM_DBG, "\t|-Set [%#x]FT: %#x\n", FEATURE_ADDR, reg); ++ ++ spi->driver->wait_ready(spi); ++ ++ reg = spi_nand_feature_op(spi, GET_OP, FEATURE_ADDR, 0); ++ FMC_PR(PM_DBG, "\t|-Check internal ECC disable result: %#x\n", ++ reg); ++ if (reg & FEATURE_ECC_ENABLE) ++ DB_MSG("Error: Chip internal ECC disable failed!\n"); ++ } ++} ++/*****************************************************************************/ ++#endif /* CONFIG_PM */ +diff --git a/drivers/mtd/nand/hifmc100_nand/Kconfig b/drivers/mtd/nand/hifmc100_nand/Kconfig +new file mode 100644 +index 0000000..7775208 +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100_nand/Kconfig +@@ -0,0 +1,50 @@ ++# ++# drivers/mtd/nand/hifmc100_nand/Kconfig ++# add by hisilicon 2017.10.26 ++# ++ ++menuconfig MTD_NAND_HIFMC100 ++ bool "Hisilicon Flash Memory Controller v100 Nand devices support" ++ depends on MFD_HISI_FMC && !MTD_SPI_NAND_HISI_BVT ++ select MISC_FILESYSTEMS ++ select MTD_BLOCK ++ select YAFFS_FS ++ select YAFFS_YAFFS2 ++ help ++ Hisilicon Flash Memory Controller version 100 is called hifmc100 for ++ short. The controller support DMA transfers while reading or writing ++ the Nand flash. ++ ++if MTD_NAND_HIFMC100 ++ ++config HIFMC100_NAND_EDO_MODE ++ bool "the Extended Data Out(EDO) mode" ++ help ++ In Extended data out (EDO), a new data cycle is started while the data ++ output of the previous cycle is still active. This process of cycle ++ overlapping, called pipelining, increases processing speed by about ++ 10 nanoseconds per cycle,increasing computer performance by about 5 ++ percent compared to performance using FMP. ++ ++config RW_H_WIDTH ++ int "the width of Read/Write HIGH Hold Time (0 to 15)" ++ range 0 15 ++ default 10 if ARCH_HI3559AV100 ++ help ++ the Read/Write HIGH Hold Time of nand flash ++ ++config R_L_WIDTH ++ int "the Read pulse width (0 to 15)" ++ range 0 15 ++ default 10 if ARCH_HI3559AV100 ++ help ++ the Read/Write LOW Hold Time of nand flash ++ ++config W_L_WIDTH ++ int "the Write pulse width (0 to 15)" ++ range 0 15 ++ default 10 if ARCH_HI3559AV100 ++ help ++ the Read/Write LOW Hold Time of nand flash ++ ++endif # End of MTD_NAND_HIFMC100 +diff --git a/drivers/mtd/nand/hifmc100_nand/Makefile b/drivers/mtd/nand/hifmc100_nand/Makefile +new file mode 100644 +index 0000000..623363c +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100_nand/Makefile +@@ -0,0 +1,26 @@ ++# ++# The Flash Memory Controller v100 Device Driver for hisilicon ++# ++# Copyright (c) 2016 HiSilicon Technologies 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. ++# ++# 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, see . ++# ++# ++ ++# ++# drivers/mtd/nand/hifmc100_nand/Makefile ++# ++ ++obj-y += hifmc_nand_spl_ids.o ++obj-y += hifmc100_nand.o hifmc100_nand_os.o +diff --git a/drivers/mtd/nand/hifmc100_nand/hifmc100_nand.c b/drivers/mtd/nand/hifmc100_nand/hifmc100_nand.c +new file mode 100644 +index 0000000..38cf81e +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100_nand/hifmc100_nand.c +@@ -0,0 +1,1125 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../hinfc_gen.h" ++#include "hifmc100_nand_os.h" ++#include "hifmc100_nand.h" ++ ++#include ++/*****************************************************************************/ ++static void hifmc100_dma_transfer(struct hifmc_host *host, int todev) ++{ ++ unsigned int reg = (unsigned int)host->dma_buffer; ++ char *op = todev ? "write" : "read"; ++ ++ FMC_PR(DMA_DB, "\t\t *-Start %s page dma transfer\n", op); ++ ++ hifmc_writel(host, FMC_DMA_SADDR_D0, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set ADDR0[%#x]%#x\n", FMC_DMA_SADDR_D0, reg); ++ ++#ifdef CONFIG_64BIT ++ reg = (host->dma_buffer & FMC_DMA_SADDRH_MASK) >> 32; ++ hifmc_writel(host, FMC_DMA_SADDRH_D0, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set ADDRH0[%#x]%#x\n", FMC_DMA_SADDRH_D0, reg); ++#endif ++ ++ reg += FMC_DMA_ADDR_OFFSET; ++ hifmc_writel(host, FMC_DMA_SADDR_D1, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set ADDR1[%#x]%#x\n", FMC_DMA_SADDR_D1, reg); ++ ++ reg += FMC_DMA_ADDR_OFFSET; ++ hifmc_writel(host, FMC_DMA_SADDR_D2, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set ADDR2[%#x]%#x\n", FMC_DMA_SADDR_D2, reg); ++ ++ reg += FMC_DMA_ADDR_OFFSET; ++ hifmc_writel(host, FMC_DMA_SADDR_D3, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set ADDR3[%#x]%#x\n", FMC_DMA_SADDR_D3, reg); ++ ++ reg = host->dma_oob; ++ hifmc_writel(host, FMC_DMA_SADDR_OOB, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set OOB[%#x]%#x\n", FMC_DMA_SADDR_OOB, reg); ++ ++#ifdef CONFIG_64BIT ++ reg = (host->dma_oob & FMC_DMA_SADDRH_MASK) >> 32; ++ hifmc_writel(host, FMC_DMA_SADDRH_OOB, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set ADDRH0[%#x]%#x\n", FMC_DMA_SADDRH_OOB, reg); ++#endif ++ ++ if (host->ecctype == NAND_ECC_0BIT) { ++ hifmc_writel(host, FMC_DMA_LEN, FMC_DMA_LEN_SET(host->oobsize)); ++ FMC_PR(DMA_DB, "\t\t |-Set LEN[%#x]%#x\n", FMC_DMA_LEN, reg); ++ } ++ reg = FMC_OP_READ_DATA_EN | FMC_OP_WRITE_DATA_EN; ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ reg = FMC_DMA_AHB_CTRL_DMA_PP_EN ++ | FMC_DMA_AHB_CTRL_BURST16_EN ++ | FMC_DMA_AHB_CTRL_BURST8_EN ++ | FMC_DMA_AHB_CTRL_BURST4_EN; ++ hifmc_writel(host, FMC_DMA_AHB_CTRL, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set AHBCTRL[%#x]%#x\n", FMC_DMA_AHB_CTRL, reg); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) ++ | OP_CFG_ADDR_NUM(host->addr_cycle); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ reg = OP_CTRL_DMA_OP_READY; ++ if (todev) ++ reg |= OP_CTRL_RW_OP(todev); ++ hifmc_writel(host, FMC_OP_CTRL, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set OP_CTRL[%#x]%#x\n", FMC_OP_CTRL, reg); ++ ++ FMC_DMA_WAIT_CPU_FINISH(host); ++ ++ FMC_PR(DMA_DB, "\t\t *-End %s page dma transfer\n", op); ++ ++ return; ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_write(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ FMC_PR(WR_DBG, "\t|*-Start send page programme cmd\n"); ++ ++ if (*host->bbm != 0xFF && *host->bbm != 0x00) ++ pr_info("WARNING: attempt to write an invalid bbm. " \ ++ "page: 0x%08x, mark: 0x%02x,\n", ++ GET_PAGE_INDEX(host), *host->bbm); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ reg = host->addr_value[1]; ++ hifmc_writel(host, FMC_ADDRH, reg); ++ FMC_PR(WR_DBG, "\t||-Set ADDRH[%#x]%#x\n", FMC_ADDRH, reg); ++ ++ reg = host->addr_value[0] & 0xffff0000; ++ hifmc_writel(host, FMC_ADDRL, reg); ++ FMC_PR(WR_DBG, "\t||-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg); ++ ++ reg = FMC_CMD_CMD2(NAND_CMD_PAGEPROG) | FMC_CMD_CMD1(NAND_CMD_SEQIN); ++ hifmc_writel(host, FMC_CMD, reg); ++ FMC_PR(WR_DBG, "\t||-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ *host->epm = 0x0000; ++ ++ hifmc100_dma_transfer(host, RW_OP_WRITE); ++ ++ FMC_PR(WR_DBG, "\t|*-End send page read cmd\n"); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_read(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ FMC_PR(RD_DBG, "\t*-Start send page read cmd\n"); ++ ++ if ((host->addr_value[0] == host->cache_addr_value[0]) ++ && (host->addr_value[1] == host->cache_addr_value[1])) { ++ FMC_PR(RD_DBG, "\t*-Cache hit! addr1[%#x], addr0[%#x]\n", ++ host->addr_value[1], host->addr_value[0]); ++ return; ++ } ++ ++ host->page_status = 0; ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ reg = FMC_INT_CLR_ALL; ++ hifmc_writel(host, FMC_INT_CLR, reg); ++ FMC_PR(RD_DBG, "\t|-Set INT_CLR[%#x]%#x\n", FMC_INT_CLR, reg); ++ ++ reg = host->nand_cfg; ++ hifmc_writel(host, FMC_CFG, reg); ++ FMC_PR(RD_DBG, "\t|-Set CFG[%#x]%#x\n", FMC_CFG, reg); ++ ++ reg = host->addr_value[1]; ++ hifmc_writel(host, FMC_ADDRH, reg); ++ FMC_PR(RD_DBG, "\t|-Set ADDRH[%#x]%#x\n", FMC_ADDRH, reg); ++ ++ reg = host->addr_value[0] & 0xffff0000; ++ hifmc_writel(host, FMC_ADDRL, reg); ++ FMC_PR(RD_DBG, "\t|-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg); ++ ++ reg = FMC_CMD_CMD2(NAND_CMD_READSTART) | FMC_CMD_CMD1(NAND_CMD_READ0); ++ hifmc_writel(host, FMC_CMD, reg); ++ FMC_PR(RD_DBG, "\t|-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ hifmc100_dma_transfer(host, RW_OP_READ); ++ ++ if (hifmc_readl(host, FMC_INT) & FMC_INT_ERR_INVALID) ++ host->page_status |= HIFMC100_PS_UC_ECC; ++ ++ host->cache_addr_value[0] = host->addr_value[0]; ++ host->cache_addr_value[1] = host->addr_value[1]; ++ ++ FMC_PR(RD_DBG, "\t*-End send page read cmd\n"); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_erase(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ FMC_PR(ER_DBG, "\t *-Start send cmd erase\n"); ++ ++ /* Don't case the read retry config */ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ reg = host->addr_value[0]; ++ hifmc_writel(host, FMC_ADDRL, reg); ++ FMC_PR(ER_DBG, "\t |-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg); ++ ++ reg = FMC_CMD_CMD2(NAND_CMD_ERASE2) | FMC_CMD_CMD1(NAND_CMD_ERASE1); ++ hifmc_writel(host, FMC_CMD, reg); ++ FMC_PR(ER_DBG, "\t |-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) ++ | OP_CFG_ADDR_NUM(host->addr_cycle); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(ER_DBG, "\t |-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ /* need to config WAIT_READY_EN */ ++ reg = FMC_OP_WAIT_READY_EN ++ | FMC_OP_CMD1_EN ++ | FMC_OP_CMD2_EN ++ | FMC_OP_ADDR_EN ++ | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(ER_DBG, "\t |-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++ FMC_PR(ER_DBG, "\t |*-End send cmd erase\n"); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_ecc_randomizer(struct hifmc_host *host, int ecc_en, ++ int randomizer_en) ++{ ++ unsigned int old_reg, reg, change = 0; ++ char *ecc_op = ecc_en ? "Quit" : "Enter"; ++ char *rand_op = randomizer_en ? "Enable" : "Disable"; ++ ++ if (IS_NAND_RANDOM(host)) { ++ reg = old_reg = hifmc_readl(host, FMC_GLOBAL_CFG); ++ if (randomizer_en) ++ reg |= FMC_GLOBAL_CFG_RANDOMIZER_EN; ++ else ++ reg &= ~FMC_GLOBAL_CFG_RANDOMIZER_EN; ++ ++ if (old_reg != reg) { ++ FMC_PR(EC_DBG, "\t |*-Start %s randomizer\n", rand_op); ++ FMC_PR(EC_DBG, "\t ||-Get global CFG[%#x]%#x\n", ++ FMC_GLOBAL_CFG, old_reg); ++ hifmc_writel(host, FMC_GLOBAL_CFG, reg); ++ FMC_PR(EC_DBG, "\t ||-Set global CFG[%#x]%#x\n", ++ FMC_GLOBAL_CFG, reg); ++ change++; ++ } ++ } ++ ++ old_reg = hifmc_readl(host, FMC_CFG); ++ reg = (ecc_en ? host->nand_cfg : host->nand_cfg_ecc0); ++ ++ if (old_reg != reg) { ++ FMC_PR(EC_DBG, "\t |%s-Start %s ECC0 mode\n", change ? "|":"*", ++ ecc_op); ++ FMC_PR(EC_DBG, "\t ||-Get CFG[%#x]%#x\n", FMC_CFG, old_reg); ++ hifmc_writel(host, FMC_CFG, reg); ++ FMC_PR(EC_DBG, "\t ||-Set CFG[%#x]%#x\n", FMC_CFG, reg); ++ change++; ++ } ++ ++ if (EC_DBG && change) ++ FMC_PR(EC_DBG, "\t |*-End randomizer and ECC0 mode config\n"); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_status(struct hifmc_host *host) ++{ ++ unsigned int regval; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ regval = OP_CFG_FM_CS(host->cmd_op.cs); ++ hifmc_writel(host, FMC_OP_CFG, regval); ++ ++ regval = FMC_OP_READ_STATUS_EN | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, regval); ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_readid(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ FMC_PR(BT_DBG, "\t *-Start read nand flash ID\n"); ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ reg = FMC_DATA_NUM_CNT(host->cmd_op.data_no); ++ hifmc_writel(host, FMC_DATA_NUM, reg); ++ FMC_PR(BT_DBG, "\t |-Set DATA_NUM[%#x]%#x\n", FMC_DATA_NUM, reg); ++ ++ reg = FMC_CMD_CMD1(NAND_CMD_READID); ++ hifmc_writel(host, FMC_CMD, reg); ++ FMC_PR(BT_DBG, "\t |-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ reg = 0; ++ hifmc_writel(host, FMC_ADDRL, reg); ++ FMC_PR(BT_DBG, "\t |-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) ++ | OP_CFG_ADDR_NUM(READ_ID_ADDR_NUM); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(BT_DBG, "\t |-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ reg = FMC_OP_CMD1_EN ++ | FMC_OP_ADDR_EN ++ | FMC_OP_READ_DATA_EN ++ | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(BT_DBG, "\t |-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ host->addr_cycle = 0x0; ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++ FMC_PR(BT_DBG, "\t *-End read nand flash ID\n"); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_reset(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ FMC_PR(BT_DBG, "\t *-Start reset nand flash\n"); ++ ++ reg = FMC_CMD_CMD1(NAND_CMD_RESET); ++ hifmc_writel(host, FMC_CMD, reg); ++ FMC_PR(BT_DBG, "\t |-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(BT_DBG, "\t |-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ reg = FMC_OP_CMD1_EN ++ | FMC_OP_WAIT_READY_EN ++ | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(BT_DBG, "\t |-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++ FMC_PR(BT_DBG, "\t *-End reset nand flash\n"); ++} ++ ++/*****************************************************************************/ ++static unsigned char hifmc100_read_byte(struct mtd_info *mtd) ++{ ++ unsigned char value = 0; ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ ++ if (host->cmd_op.l_cmd == NAND_CMD_READID) { ++ value = hifmc_readb((void __iomem *)(chip->IO_ADDR_R + host->offset)); ++ host->offset++; ++ if (host->cmd_op.data_no == host->offset) ++ host->cmd_op.l_cmd = 0; ++ return value; ++ } ++ ++ if (host->cmd_op.cmd == NAND_CMD_STATUS) { ++ value = hifmc_readl(host, FMC_STATUS); ++ if (host->cmd_op.l_cmd == NAND_CMD_ERASE1) ++ FMC_PR(ER_DBG, "\t*-Erase WP status: %#x\n", value); ++ if (host->cmd_op.l_cmd == NAND_CMD_PAGEPROG) ++ FMC_PR(WR_DBG, "\t*-Write WP status: %#x\n", value); ++ return value; ++ } ++ ++ if (host->cmd_op.l_cmd == NAND_CMD_READOOB) { ++ value = hifmc_readb((void __iomem *)(host->buffer + host->pagesize ++ + host->offset)); ++ host->offset++; ++ return value; ++ } ++ ++ host->offset++; ++ ++ return hifmc_readb((void __iomem *)(host->buffer + host->column \ ++ + host->offset - 1)); ++} ++ ++/*****************************************************************************/ ++static unsigned short hifmc100_read_word(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ ++ host->offset += 2; ++ return hifmc_readw(host->buffer + host->column + host->offset - 2); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_write_buf(struct mtd_info *mtd, ++ const u_char *buf, int len) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ ++#ifdef HIFMC100_NAND_SUPPORT_REG_WRITE ++ if (buf == chip->oob_poi) ++ memcpy((char *)host->iobase + host->pagesize, buf, len); ++ else ++ memcpy((char *)host->iobase, buf, len); ++#else ++ if (buf == chip->oob_poi) ++ memcpy((char *)host->buffer + host->pagesize, buf, len); ++ else ++ memcpy((char *)host->buffer, buf, len); ++#endif ++ return; ++} ++ ++/*****************************************************************************/ ++static void hifmc100_ecc_err_num_count(struct mtd_info *mtd, ++ u_int ecc_st, u_int reg) ++{ ++ u_char err_num; ++ ++ if (ecc_st > 4) ++ ecc_st = 4; ++ ++ while (ecc_st) { ++ err_num = GET_ECC_ERR_NUM(--ecc_st, reg); ++ if (err_num == 0xff) ++ mtd->ecc_stats.failed++; ++ else ++ mtd->ecc_stats.corrected += err_num; ++ } ++} ++ ++/*****************************************************************************/ ++static void hifmc100_read_buf(struct mtd_info *mtd, u_char *buf, int len) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ ++#ifdef HIFMC100_NAND_SUPPORT_REG_READ ++ if (buf == chip->oob_poi) ++ memcpy(buf, (char *)host->iobase + host->pagesize, len); ++ else ++ memcpy(buf, (char *)host->iobase, len); ++#else ++ if (buf == chip->oob_poi) ++ memcpy(buf, (char *)host->buffer + host->pagesize, len); ++ else ++ memcpy(buf, (char *)host->buffer, len); ++#endif ++ if (buf != chip->oob_poi) { ++ u_int reg, ecc_step = host->pagesize >> 10; ++ ++ /* 2K or 4K or 8K(1) or 16K(1-1) pagesize */ ++ reg = hifmc_readl(host, HIFMC100_ECC_ERR_NUM0_BUF0); ++ hifmc100_ecc_err_num_count(mtd, ecc_step, reg); ++ ++ if (ecc_step > 4) { ++ /* 8K(2) or 16K(1-2) pagesize */ ++ reg = hifmc_readl(host, HIFMC100_ECC_ERR_NUM1_BUF0); ++ hifmc100_ecc_err_num_count(mtd, ecc_step, reg); ++ if (ecc_step > 8) { ++ /* 16K(2-1) pagesize */ ++ reg = hifmc_readl(host, ++ HIFMC100_ECC_ERR_NUM0_BUF1); ++ hifmc100_ecc_err_num_count(mtd, ecc_step, reg); ++ /* 16K(2-2) pagesize */ ++ reg = hifmc_readl(host, ++ HIFMC100_ECC_ERR_NUM1_BUF1); ++ hifmc100_ecc_err_num_count(mtd, ecc_step, reg); ++ } ++ } ++ } ++ ++ return; ++} ++ ++/*****************************************************************************/ ++static void hifmc100_select_chip(struct mtd_info *mtd, int chipselect) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ ++ if (chipselect < 0) { ++ mutex_unlock(&fmc_switch_mutex); ++ return; ++ } ++ ++ mutex_lock(&fmc_switch_mutex); ++ ++ if (chipselect > CONFIG_HIFMC100_MAX_NAND_CHIP) ++ DB_BUG("Error: Invalid chip select: %d\n", chipselect); ++ ++ host->cmd_op.cs = chipselect; ++ if (host->mtd != mtd) ++ host->mtd = mtd; ++ ++ switch (chip->state) { ++ case FL_ERASING: ++ host->cmd_op.l_cmd = NAND_CMD_ERASE1; ++ if (ER_DBG) ++ pr_info("\n"); ++ FMC_PR(ER_DBG, "\t*-Erase chip: %d\n", chipselect); ++ break; ++ case FL_WRITING: ++ host->cmd_op.l_cmd = NAND_CMD_PAGEPROG; ++ if (WR_DBG) ++ pr_info("\n"); ++ FMC_PR(WR_DBG, "\t*-Write chip: %d\n", chipselect); ++ break; ++ case FL_READING: ++ host->cmd_op.l_cmd = NAND_CMD_READ0; ++ if (RD_DBG) ++ pr_info("\n"); ++ FMC_PR(RD_DBG, "\t*-Read chip: %d\n", chipselect); ++ break; ++ default: ++ break; ++ } ++} ++ ++/*****************************************************************************/ ++static void hifmc100_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned ctrl) ++{ ++ unsigned char cmd; ++ int is_cache_invalid = 1; ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ ++ if (ctrl & NAND_ALE) { ++ unsigned int addr_value = 0; ++ unsigned int addr_offset = 0; ++ ++ if (ctrl & NAND_CTRL_CHANGE) { ++ host->addr_cycle = 0x0; ++ host->addr_value[0] = 0x0; ++ host->addr_value[1] = 0x0; ++ } ++ addr_offset = host->addr_cycle << 3; ++ ++ if (host->addr_cycle >= HIFMC100_ADDR_CYCLE_MASK) { ++ addr_offset = (host->addr_cycle - ++ HIFMC100_ADDR_CYCLE_MASK) << 3; ++ addr_value = 1; ++ } ++ ++ host->addr_value[addr_value] |= ++ ((dat & 0xff) << addr_offset); ++ ++ host->addr_cycle++; ++ } ++ ++ if ((ctrl & NAND_CLE) && (ctrl & NAND_CTRL_CHANGE)) { ++ cmd = dat & 0xff; ++ host->cmd_op.cmd = cmd; ++ switch (cmd) { ++ case NAND_CMD_PAGEPROG: ++ host->offset = 0; ++ host->send_cmd_pageprog(host); ++ break; ++ ++ case NAND_CMD_READSTART: ++ is_cache_invalid = 0; ++ if (host->addr_value[0] == host->pagesize) ++ host->cmd_op.l_cmd = NAND_CMD_READOOB; ++ host->send_cmd_readstart(host); ++ break; ++ ++ case NAND_CMD_ERASE2: ++ host->cmd_op.l_cmd = cmd; ++ host->send_cmd_erase(host); ++ break; ++ ++ case NAND_CMD_READID: ++ memset((u_char *)(chip->IO_ADDR_R), 0, MAX_NAND_ID_LEN); ++ host->cmd_op.l_cmd = cmd; ++ host->cmd_op.data_no = MAX_NAND_ID_LEN; ++ host->send_cmd_readid(host); ++ break; ++ ++ case NAND_CMD_STATUS: ++ host->send_cmd_status(host); ++ break; ++ ++ case NAND_CMD_READ0: ++ host->cmd_op.l_cmd = cmd; ++ break; ++ ++ case NAND_CMD_RESET: ++ host->send_cmd_reset(host); ++ break; ++ ++ case NAND_CMD_SEQIN: ++ case NAND_CMD_ERASE1: ++ default: ++ break; ++ } ++ } ++ ++ /* pass pagesize and ecctype to kernel when startup. */ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ if ((dat == NAND_CMD_NONE) && host->addr_cycle) { ++ if (host->cmd_op.cmd == NAND_CMD_SEQIN ++ || host->cmd_op.cmd == NAND_CMD_READ0 ++ || host->cmd_op.cmd == NAND_CMD_READID) { ++ host->offset = 0x0; ++ host->column = (host->addr_value[0] & 0xffff); ++ } ++ } ++ ++ if (is_cache_invalid) { ++ host->cache_addr_value[0] = ~0; ++ host->cache_addr_value[1] = ~0; ++ } ++} ++ ++/*****************************************************************************/ ++static int hifmc100_dev_ready(struct mtd_info *mtd) ++{ ++ return 0x1; ++} ++ ++/*****************************************************************************/ ++/* ++ * 'host->epm' only use the first oobfree[0] field, it looks very simple, But... ++ */ ++static int hifmc_ooblayout_ecc_default(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->length = 32; ++ oobregion->offset = 32; ++ ++ return 0; ++} ++ ++static int hifmc_ooblayout_free_default(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->length = 30; ++ oobregion->offset = 2; ++ ++ return 0; ++} ++ ++static struct mtd_ooblayout_ops hifmc_ooblayout_default_ops = { ++ .ecc = hifmc_ooblayout_ecc_default, ++ .free = hifmc_ooblayout_free_default, ++}; ++ ++#ifdef CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 ++static int hifmc_ooblayout_ecc_4k16bit(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->length = 14; ++ oobregion->offset = 14; ++ ++ return 0; ++} ++ ++static int hifmc_ooblayout_free_4k16bit(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->length = 14; ++ oobregion->offset = 2; ++ ++ return 0; ++} ++tatic struct mtd_ooblayout_ops hifmc_ooblayout_4k16bit_ops = { ++ .ecc = hifmc_ooblayout_ecc_4k16bit, ++ .free = hifmc_ooblayout_free_4k16bit, ++}; ++ ++static int hifmc_ooblayout_ecc_2k16bit(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->length = 6; ++ oobregion->offset = 6; ++ ++ return 0; ++} ++ ++static int hifmc_ooblayout_free_2k16bit(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->length = 6; ++ oobregion->offset = 2; ++ ++ return 0; ++} ++ ++static struct mtd_ooblayout_ops hifmc_ooblayout_2k16bit_ops = { ++ .ecc = hifmc_ooblayout_ecc_2k16bit, ++ .free = hifmc_ooblayout_free_2k16bit, ++}; ++#endif ++/*****************************************************************************/ ++/* ecc/pagesize get from NAND controller */ ++static struct nand_config_info hifmc100_nand_hw_auto_config_table[] = { ++ {NAND_PAGE_16K, NAND_ECC_64BIT, 64, 1824/*1824*/, &hifmc_ooblayout_default_ops}, ++ {NAND_PAGE_16K, NAND_ECC_40BIT, 40, 1200/*1152*/, &hifmc_ooblayout_default_ops}, ++ {NAND_PAGE_16K, NAND_ECC_0BIT, 0, 32 , &hifmc_ooblayout_default_ops}, ++ ++ {NAND_PAGE_8K, NAND_ECC_64BIT, 64, 928 /*928*/, &hifmc_ooblayout_default_ops}, ++ {NAND_PAGE_8K, NAND_ECC_40BIT, 40, 600 /*592*/, &hifmc_ooblayout_default_ops}, ++ {NAND_PAGE_8K, NAND_ECC_24BIT, 24, 368 /*368*/, &hifmc_ooblayout_default_ops}, ++ {NAND_PAGE_8K, NAND_ECC_0BIT, 0, 32, &hifmc_ooblayout_default_ops}, ++ ++ {NAND_PAGE_4K, NAND_ECC_24BIT, 24, 200 /*200*/, &hifmc_ooblayout_default_ops}, ++#ifdef CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 ++ {NAND_PAGE_4K, NAND_ECC_16BIT, 16, 128 /*128*/, &hifmc_ooblayout_4k16bit_ops}, ++#endif ++ {NAND_PAGE_4K, NAND_ECC_8BIT, 8, 128 /*88*/, &hifmc_ooblayout_default_ops}, ++ {NAND_PAGE_4K, NAND_ECC_0BIT, 0, 32, &hifmc_ooblayout_default_ops}, ++ ++ {NAND_PAGE_2K, NAND_ECC_24BIT, 24, 128 /*116*/, &hifmc_ooblayout_default_ops}, ++#ifdef CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 ++ {NAND_PAGE_2K, NAND_ECC_16BIT, 16, 64 /*64*/, &hifmc_ooblayout_2k16bit_ops}, ++#endif ++ {NAND_PAGE_2K, NAND_ECC_8BIT, 8, 64 /*60*/, &hifmc_ooblayout_default_ops}, ++ {NAND_PAGE_2K, NAND_ECC_0BIT, 0, 32, &hifmc_ooblayout_default_ops}, ++ ++ {0, 0, 0, 0, NULL}, ++}; ++ ++/*****************************************************************************/ ++/* ++ * 0 - This NAND NOT support randomizer ++ * 1 - This NAND support randomizer. ++ */ ++static int hifmc100_nand_support_randomizer(u_int pageisze, u_int ecctype) ++{ ++ switch (pageisze) { ++ case _8K: ++ return (ecctype >= NAND_ECC_24BIT && ecctype <= NAND_ECC_80BIT); ++ case _16K: ++ return (ecctype >= NAND_ECC_40BIT && ecctype <= NAND_ECC_80BIT); ++ case _32K: ++ return (ecctype >= NAND_ECC_40BIT && ecctype <= NAND_ECC_80BIT); ++ default: ++ return 0; ++ } ++} ++ ++/*****************************************************************************/ ++/* used the best correct arithmetic. */ ++static struct nand_config_info *hifmc100_get_config_type_info( ++ struct mtd_info *mtd, struct nand_dev_t *nand_dev) ++{ ++ struct nand_config_info *best = NULL; ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ struct nand_config_info *info = hifmc100_nand_hw_auto_config_table; ++ ++ nand_dev->start_type = "Auto"; ++ nand_dev->flags |= (IS_NANDC_HW_AUTO(host) | IS_NANDC_CONFIG_DONE(host)); ++ ++ for (; info->ooblayout_ops; info++) { ++ if (match_page_type_to_size(info->pagetype) != mtd->writesize) ++ continue; ++ ++ if (mtd->oobsize < info->oobsize) ++ continue; ++ ++ if (!best || (best->ecctype < info->ecctype)) ++ best = info; ++ } ++ ++ return best; ++} ++ ++/*****************************************************************************/ ++static unsigned int hifmc100_get_ecc_reg(struct hifmc_host *host, ++ struct nand_config_info *info, struct nand_dev_t *nand_dev) ++{ ++ host->ecctype = info->ecctype; ++ FMC_PR(BT_DBG, "\t |-Save best EccType %d(%s)\n", host->ecctype, ++ match_ecc_type_to_str(info->ecctype)); ++ ++ nand_dev->ecctype = host->ecctype; ++ ++ return FMC_CFG_ECC_TYPE(match_ecc_type_to_reg(info->ecctype)); ++} ++ ++/*****************************************************************************/ ++static unsigned int hifmc100_get_page_reg(struct hifmc_host *host, ++ struct nand_config_info *info) ++{ ++ host->pagesize = match_page_type_to_size(info->pagetype); ++ FMC_PR(BT_DBG, "\t |-Save best PageSize %d(%s)\n", host->pagesize, ++ match_page_type_to_str(info->pagetype)); ++ ++ return FMC_CFG_PAGE_SIZE(match_page_type_to_reg(info->pagetype)); ++} ++ ++/*****************************************************************************/ ++static unsigned int hifmc100_get_block_reg(struct hifmc_host *host, ++ struct nand_config_info *info) ++{ ++ unsigned int block_reg = 0, page_per_block; ++ struct mtd_info *mtd = host->mtd; ++ ++ host->block_page_mask = ((mtd->erasesize / mtd->writesize) - 1); ++ page_per_block = mtd->erasesize / match_page_type_to_size(info->pagetype); ++ switch (page_per_block) { ++ case 64: ++ block_reg = BLOCK_SIZE_64_PAGE; ++ break; ++ case 128: ++ block_reg = BLOCK_SIZE_128_PAGE; ++ break; ++ case 256: ++ block_reg = BLOCK_SIZE_256_PAGE; ++ break; ++ case 512: ++ block_reg = BLOCK_SIZE_512_PAGE; ++ break; ++ default: ++ DB_MSG("Can't support block %#x and page %#x size\n", ++ mtd->erasesize, mtd->writesize); ++ } ++ ++ return FMC_CFG_BLOCK_SIZE(block_reg); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_set_fmc_cfg_reg(struct hifmc_host *host, ++ struct nand_config_info *type_info, struct nand_dev_t *nand_dev) ++{ ++ unsigned int page_reg, ecc_reg, block_reg, reg_fmc_cfg; ++ ++ ecc_reg = hifmc100_get_ecc_reg(host, type_info, nand_dev); ++ page_reg = hifmc100_get_page_reg(host, type_info); ++ block_reg = hifmc100_get_block_reg(host, type_info); ++ ++ if (hifmc100_nand_support_randomizer(host->pagesize, host->ecctype)) ++ host->flags |= IS_NAND_RANDOM(nand_dev); ++ ++ /* ++ * Check if hardware enable randomizer PIN, But NAND does not need ++ * randomizer. We will notice user. ++ */ ++ if (IS_NAND_RANDOM(host) && ++ !hifmc100_nand_support_randomizer(host->pagesize, host->ecctype)) ++ DB_BUG(ERSTR_HARDWARE ++ "This NAND flash does not support `randomizer`, " ++ "Please don't configure hardware randomizer PIN."); ++ ++ /* Save value of FMC_CFG and FMC_CFG_ECC0 to turn on/off ECC */ ++ reg_fmc_cfg = hifmc_readl(host, FMC_CFG); ++ reg_fmc_cfg &= ~(PAGE_SIZE_MASK | ECC_TYPE_MASK | BLOCK_SIZE_MASK); ++ reg_fmc_cfg |= ecc_reg | page_reg | block_reg; ++ host->nand_cfg = reg_fmc_cfg; ++ host->nand_cfg_ecc0 = (host->nand_cfg & ~ECC_TYPE_MASK) | ECC_TYPE_0BIT; ++ FMC_PR(BT_DBG, "\t|-Save FMC_CFG[%#x]: %#x and FMC_CFG_ECC0: %#x\n", ++ FMC_CFG, host->nand_cfg, host->nand_cfg_ecc0); ++ ++ /* pass pagesize and ecctype to kernel when spiflash startup. */ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ /* ++ * If it want to support the 'read retry' feature, the 'randomizer' ++ * feature must be support first. ++ */ ++ host->read_retry = NULL; ++ ++ if (host->read_retry && !IS_NAND_RANDOM(host)) { ++ DB_BUG(ERSTR_HARDWARE ++ "This Nand flash need to enable 'randomizer' feature. " ++ "Please configure hardware randomizer PIN."); ++ } ++} ++ ++/*****************************************************************************/ ++static void hifmc100_set_oob_info(struct mtd_info *mtd, ++ struct nand_config_info *info, struct nand_dev_t *nand_dev) ++{ ++ int buffer_len; ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hifmc_host *host = chip->priv; ++ struct mtd_oob_region hifmc_oobregion = {0, 0}; ++ ++ if (info->ecctype != NAND_ECC_0BIT) ++ mtd->oobsize = info->oobsize; ++ mtd->oobavail = HIFMC100_NAND_OOBSIZE_FOR_YAFFS; ++ ++ host->oobsize = mtd->oobsize; ++ ++ buffer_len = host->pagesize + host->oobsize; ++ ++ memset(host->buffer, 0xff, buffer_len); ++ host->dma_oob = host->dma_buffer + host->pagesize; ++ ++ host->bbm = (unsigned char *)(host->buffer + host->pagesize ++ + HIFMC100_BAD_BLOCK_POS); ++ ++ info->ooblayout_ops->free(mtd, 0, &hifmc_oobregion); ++ ++ mtd_set_ooblayout(mtd, info->ooblayout_ops); ++ ++ /* EB bits locate in the bottom two of CTRL(30) */ ++ host->epm = (u_short *)(host->buffer + host->pagesize ++ + hifmc_oobregion.offset + 28); ++ ++#ifdef CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 ++ if (best->ecctype == NAND_ECC_16BIT) { ++ if (host->pagesize == _2K) { ++ /* EB bits locate in the bottom two of CTRL(4) */ ++ host->epm = (u_short *)(host->buffer + host->pagesize ++ + hifmc_oobregion.offset + 4); ++ } else if (host->pagesize == _4K) { ++ /* EB bit locate in the bottom two of CTRL(14) */ ++ host->epm = (u_short *)(host->buffer + host->pagesize ++ + hifmc_oobregion.offset + 12); ++ } ++ } ++#endif ++} ++/*****************************************************************************/ ++static int hifmc100_set_config_info(struct mtd_info *mtd, ++ struct nand_chip *chip, struct nand_dev_t *dev) ++{ ++ struct hifmc_host *host = chip->priv; ++ struct nand_dev_t *nand_dev = &g_nand_dev; ++ struct nand_config_info *type_info = NULL; ++ ++ FMC_PR(BT_DBG, "\t*-Start config Block Page OOB and Ecc\n"); ++ ++ type_info = hifmc100_get_config_type_info(mtd, nand_dev); ++ BUG_ON(!type_info); ++ ++ FMC_PR(BT_DBG, "\t|-%s Config, PageSize %s EccType %s OobSize %d\n", ++ nand_dev->start_type, nand_page_name(type_info->pagetype), ++ nand_ecc_name(type_info->ecctype), type_info->oobsize); ++ ++ /* Set the page_size, ecc_type, block_size of FMC_CFG[0x0] register */ ++ hifmc100_set_fmc_cfg_reg(host, type_info, nand_dev); ++ ++ hifmc100_set_oob_info(mtd, type_info, nand_dev); ++ ++ if (mtd->writesize > NAND_MAX_PAGESIZE ++ || mtd->oobsize > NAND_MAX_OOBSIZE) { ++ DB_BUG(ERSTR_DRIVER ++ "Driver does not support this Nand Flash. Please " \ ++ "increase NAND_MAX_PAGESIZE and NAND_MAX_OOBSIZE.\n"); ++ } ++ ++ /* Some Nand Flash devices have subpage structure */ ++ if (mtd->writesize != host->pagesize) { ++ unsigned int shift = 0; ++ unsigned int writesize = mtd->writesize; ++ ++ while (writesize > host->pagesize) { ++ writesize >>= 1; ++ shift++; ++ } ++ chip->chipsize = chip->chipsize >> shift; ++ mtd->erasesize = mtd->erasesize >> shift; ++ mtd->writesize = host->pagesize; ++ pr_info("Nand divide into 1/%u\n", (1 << shift)); ++ } ++ ++ FMC_PR(BT_DBG, "\t*-End config Block Page Oob and Ecc\n"); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++static void hifmc100_chip_init(struct nand_chip *chip) ++{ ++ memset((char *)chip->IO_ADDR_R, 0xff, NAND_BUFFER_LEN); ++ ++ chip->read_byte = hifmc100_read_byte; ++ chip->read_word = hifmc100_read_word; ++ chip->write_buf = hifmc100_write_buf; ++ chip->read_buf = hifmc100_read_buf; ++ ++ chip->select_chip = hifmc100_select_chip; ++ ++ chip->cmd_ctrl = hifmc100_cmd_ctrl; ++ chip->dev_ready = hifmc100_dev_ready; ++ ++ chip->chip_delay = FMC_CHIP_DELAY; ++ ++ chip->options = NAND_NEED_READRDY | NAND_BROKEN_XD ++ | NAND_SKIP_BBTSCAN; ++ ++ chip->ecc.mode = NAND_ECC_NONE; ++} ++ ++/*****************************************************************************/ ++static int hifmc100_host_init(struct hifmc_host *host) ++{ ++ unsigned int reg, flash_type; ++ ++ FMC_PR(BT_DBG, "\t *-Start nand host init\n"); ++ ++ reg = hifmc_readl(host, FMC_CFG); ++ FMC_PR(BT_DBG, "\t |-Read FMC CFG[%#x]%#x\n", FMC_CFG, reg); ++ flash_type = GET_SPI_FLASH_TYPE(reg); ++ if (flash_type != FLASH_TYPE_NAND) { ++ DB_MSG("Error: Flash type isn't Nand flash. reg[%#x]\n", reg); ++ reg |= FMC_CFG_FLASH_SEL(FLASH_TYPE_NAND); ++ FMC_PR(BT_DBG, "\t |-Change flash type to Nand flash\n"); ++ } ++ ++ if ((reg & FMC_CFG_OP_MODE_MASK) == FMC_CFG_OP_MODE_BOOT) { ++ reg |= FMC_CFG_OP_MODE(FMC_CFG_OP_MODE_NORMAL); ++ FMC_PR(BT_DBG, "\t |-Controller enter normal mode\n"); ++ } ++ hifmc_writel(host, FMC_CFG, reg); ++ FMC_PR(BT_DBG, "\t |-Set CFG[%#x]%#x\n", FMC_CFG, reg); ++ ++ host->nand_cfg = reg; ++ host->nand_cfg_ecc0 = (reg & ~ECC_TYPE_MASK) | ECC_TYPE_0BIT; ++ ++ reg = hifmc_readl(host, FMC_GLOBAL_CFG); ++ FMC_PR(BT_DBG, "\t |-Read global CFG[%#x]%#x\n", FMC_GLOBAL_CFG, reg); ++ if (reg & FMC_GLOBAL_CFG_RANDOMIZER_EN) { ++ host->flags &= ~NAND_RANDOMIZER; ++ FMC_PR(BT_DBG, "\t |-Default disable randomizer\n"); ++ reg &= ~FMC_GLOBAL_CFG_RANDOMIZER_EN; ++ hifmc_writel(host, FMC_GLOBAL_CFG, reg); ++ FMC_PR(BT_DBG, "\t |-Set global CFG[%#x]%#x\n", FMC_GLOBAL_CFG, reg); ++ } ++ ++#ifdef CONFIG_HIFMC100_NAND_EDO_MODE ++ /* enable EDO node */ ++ reg = hifmc_readl(host, FMC_GLOBAL_CFG); ++ hifmc_writel(host, FMC_GLOBAL_CFG, SET_NAND_EDO_MODE_EN(reg)); ++#endif ++ ++ host->addr_cycle = 0; ++ host->addr_value[0] = 0; ++ host->addr_value[1] = 0; ++ host->cache_addr_value[0] = ~0; ++ host->cache_addr_value[1] = ~0; ++ ++ host->send_cmd_pageprog = hifmc100_send_cmd_write; ++ host->send_cmd_status = hifmc100_send_cmd_status; ++ host->send_cmd_readstart = hifmc100_send_cmd_read; ++ host->send_cmd_erase = hifmc100_send_cmd_erase; ++ host->send_cmd_readid = hifmc100_send_cmd_readid; ++ host->send_cmd_reset = hifmc100_send_cmd_reset; ++ ++ /* ++ * check if start from nand. ++ * This register REG_SYSSTAT is set in start.S ++ * When start in NAND (Auto), the ECC/PAGESIZE driver don't detect. ++ */ ++ host->flags |= NANDC_HW_AUTO; ++ ++ if (GET_SYS_BOOT_MODE(reg) == BOOT_FROM_NAND) { ++ host->flags |= NANDC_CONFIG_DONE; ++ FMC_PR(BT_DBG, "\t |-Auto config pagesize and ecctype\n"); ++ } ++ ++ host->enable_ecc_randomizer = hifmc100_ecc_randomizer; ++ ++ FMC_PR(BT_DBG, "\t *-End nand host init\n"); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++int hifmc100_nand_init(struct nand_chip *chip) ++{ ++ struct hifmc_host *host = chip->priv; ++ ++ /* enable and set system clock */ ++ clk_prepare_enable(host->clk); ++ ++ /* fmc ip version check */ ++ host->version = hifmc_readl(host, FMC_VERSION); ++ if (host->version != HIFMC_VER_100) ++ return -EFAULT; ++ pr_info("Found Flash Memory Controller v100 Nand Driver\n"); ++ ++ /* hifmc host init */ ++ if (hifmc100_host_init(host)) { ++ DB_MSG("Error: Nand host init failed!\n"); ++ return -EFAULT; ++ } ++ host->chip = chip; ++ ++ hifmc_writel(host, FMC_PND_PWIDTH_CFG, PWIDTH_CFG_RW_HCNT(CONFIG_RW_H_WIDTH) ++ | PWIDTH_CFG_R_LCNT(CONFIG_R_L_WIDTH) ++ | PWIDTH_CFG_W_LCNT(CONFIG_W_L_WIDTH)); ++ ++ /* hifmc nand_chip struct init */ ++ hifmc100_chip_init(chip); ++ ++ hifmc_spl_ids_register(); ++ hinfc_param_adjust = hifmc100_set_config_info; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++/*****************************************************************************/ ++void hifmc100_nand_config(struct hifmc_host *host) ++{ ++ /* enable system clock */ ++ clk_prepare_enable(host->clk); ++ FMC_PR(PM_DBG, "\t |-enable system clock\n"); ++} ++#endif /* CONFIG_PM */ +diff --git a/drivers/mtd/nand/hifmc100_nand/hifmc100_nand.h b/drivers/mtd/nand/hifmc100_nand/hifmc100_nand.h +new file mode 100644 +index 0000000..9f7bbb9 +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100_nand/hifmc100_nand.h +@@ -0,0 +1,164 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef __HIFMC100_NAND_H__ ++#define __HIFMC100_NAND_H__ ++ ++#include ++ ++/******************************************************************************/ ++/* These macroes are for debug only, reg option is slower then dma option */ ++#undef HIFMC100_NAND_SUPPORT_REG_READ ++/* #define HIFMC100_NAND_SUPPORT_REG_READ */ ++ ++#undef HIFMC100_NAND_SUPPORT_REG_WRITE ++/* #define HIFMC100_NAND_SUPPORT_REG_WRITE */ ++ ++/*****************************************************************************/ ++#define HIFMC100_ECC_ERR_NUM0_BUF0 0xc0 ++#define HIFMC100_ECC_ERR_NUM1_BUF0 0xc4 ++#define HIFMC100_ECC_ERR_NUM0_BUF1 0xc8 ++#define HIFMC100_ECC_ERR_NUM1_BUF1 0xcc ++ ++#define GET_ECC_ERR_NUM(_i, _reg) (((_reg) >> ((_i) * 8)) & 0xff) ++ ++/*****************************************************************************/ ++#define NAND_MAX_PAGESIZE 32768 ++#define NAND_MAX_OOBSIZE 4800 ++ ++#define CONFIG_SUPPORT_YAFFS ++#define HIFMC100_NAND_OOBSIZE_FOR_YAFFS 32 ++ ++/*****************************************************************************/ ++#define REG_CNT_HIGH_BLOCK_NUM_SHIFT 10 ++ ++#define REG_CNT_BLOCK_NUM_MASK 0x3ff ++#define REG_CNT_BLOCK_NUM_SHIFT 22 ++ ++#define REG_CNT_PAGE_NUM_MASK 0x3f ++#define REG_CNT_PAGE_NUM_SHIFT 16 ++ ++#define REG_CNT_WRAP_MASK 0xf ++#define REG_CNT_WRAP_SHIFT 12 ++ ++#define REG_CNT_ECC_OFFSET_MASK 0xfff ++#define REG_CNT_ECC_8BIT_OFFSET 1054 ++#define REG_CNT_ECC_16BIT_OFFSET 1056 ++#define REG_CNT_ECC_24BIT_OFFSET 1082 ++ ++/*****************************************************************************/ ++#define HIFMC100_ADDR_CYCLE_MASK 0x4 ++ ++#define NAND_EDO_MODE_SHIFT 9 ++#define NAND_EDO_MODE_MASK (1<. ++ * ++ */ ++ ++#include ++ ++#include "hifmc100_nand_os.h" ++#include "hifmc100_nand.h" ++#include ++ ++/*****************************************************************************/ ++static inline int mtd_has_partitions(void) { return 1; } ++ ++/*****************************************************************************/ ++static int hisi_nand_os_probe(struct platform_device *pltdev) ++{ ++ int len, result = 0; ++ struct hifmc_host *host; ++ struct nand_chip *chip; ++ struct mtd_info *mtd; ++ int nr_parts = 0; ++ struct mtd_partition *parts = NULL; ++ struct device *dev = &pltdev->dev; ++ struct device_node *np = NULL; ++ struct hisi_fmc *fmc = dev_get_drvdata(dev->parent); ++ ++ if (!fmc) { ++ dev_err(dev, "get mfd fmc devices failed\n"); ++ return -ENXIO; ++ } ++ ++ len = sizeof(struct hifmc_host) + sizeof(struct nand_chip) ++ + sizeof(struct mtd_info); ++ host = devm_kzalloc(dev, len, GFP_KERNEL); ++ if (!host) ++ return -ENOMEM; ++ memset((char *)host, 0, len); ++ platform_set_drvdata(pltdev, host); ++ ++ host->dev = &pltdev->dev; ++ host->chip = chip = (struct nand_chip *)&host[1]; ++ host->mtd = mtd = nand_to_mtd(chip); ++ host->regbase = fmc->regbase; ++ host->iobase = fmc->iobase; ++ host->clk = fmc->clk; ++ chip->IO_ADDR_R = chip->IO_ADDR_W = host->iobase; ++ host->buffer = fmc->buffer; ++ host->dma_buffer = fmc->dma_buffer; ++ ++ /* hifmc Nand host init */ ++ chip->priv = host; ++ result = hifmc100_nand_init(chip); ++ if (result) { ++ DB_MSG("Error: host init failed! result: %d\n", result); ++ goto fail; ++ } ++ ++ np = of_get_next_available_child(dev->of_node, NULL); ++ mtd->name = np->name; ++ mtd->type = MTD_NANDFLASH; ++ mtd->priv = chip; ++ mtd->flags = MTD_CAP_NANDFLASH; ++ mtd->owner = THIS_MODULE; ++ ++ if (nand_scan(mtd, CONFIG_HIFMC100_MAX_NAND_CHIP)) { ++ result = -ENXIO; ++ goto fail; ++ } ++ ++ result = mtd_device_register(host->mtd, parts, nr_parts); ++ if (result) { ++ kfree(parts); ++ parts = NULL; ++ } ++ ++ return (1 == result) ? -ENODEV : 0; ++ ++fail: ++ clk_disable_unprepare(host->clk); ++ nand_release(mtd); ++ return result; ++} ++ ++/*****************************************************************************/ ++static int hisi_nand_os_remove(struct platform_device *pltdev) ++{ ++ struct hifmc_host *host = platform_get_drvdata(pltdev); ++ ++ clk_disable_unprepare(host->clk); ++ nand_release(host->mtd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++/*****************************************************************************/ ++static int hifmc100_nand_os_suspend(struct platform_device *pltdev, ++ pm_message_t state) ++{ ++ struct hifmc_host *host = platform_get_drvdata(pltdev); ++ if (!host) ++ return 0; ++ ++ while ((hifmc_readl(host, FMC_OP) & FMC_OP_REG_OP_START)) ++ _cond_resched(); ++ ++ while ((hifmc_readl(host, FMC_OP_CTRL) & OP_CTRL_DMA_OP_READY)) ++ _cond_resched(); ++ ++ clk_disable_unprepare(host->clk); ++ FMC_PR(PM_DBG, "\t|-disable system clock\n"); ++ return 0; ++} ++ ++/*****************************************************************************/ ++static int hifmc100_nand_os_resume(struct platform_device *pltdev) ++{ ++ int cs; ++ struct hifmc_host *host = platform_get_drvdata(pltdev); ++ struct nand_chip *chip = host->chip; ++ ++ if (!host) ++ return 0; ++ ++ for (cs = 0; cs < chip->numchips; cs++) ++ host->send_cmd_reset(host); ++ ++ hifmc100_nand_config(host); ++ return 0; ++} ++#endif /* CONFIG_PM */ ++ ++/*****************************************************************************/ ++static const struct of_device_id hisi_nand_dt_ids[] = { ++ { .compatible = "hisilicon,hisi_nand" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, hisi_nand_dt_ids); ++ ++static struct platform_driver hisi_nand_driver = { ++ .driver = { ++ .name = "hisi_nand", ++ .of_match_table = hisi_nand_dt_ids, ++ }, ++ .probe = hisi_nand_os_probe, ++ .remove = hisi_nand_os_remove, ++#ifdef CONFIG_PM ++ .suspend = hifmc100_nand_os_suspend, ++ .resume = hifmc100_nand_os_resume, ++#endif ++}; ++module_platform_driver(hisi_nand_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("BVT_BSP"); ++MODULE_DESCRIPTION("Hisilicon Flash Memory Controller V100 Nand Driver"); +diff --git a/drivers/mtd/nand/hifmc100_nand/hifmc100_nand_os.h b/drivers/mtd/nand/hifmc100_nand/hifmc100_nand_os.h +new file mode 100644 +index 0000000..b6d9807 +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100_nand/hifmc100_nand_os.h +@@ -0,0 +1,74 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef __HIFMC100_NAND_OS_H__ ++#define __HIFMC100_NAND_OS_H__ ++ ++/*****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 5)) ++ #include "../../mtdcore.h" ++#endif ++ ++/*****************************************************************************/ ++#define DEFAULT_NAND_PAGESIZE 2048 ++#define DEFAULT_NAND_OOBSIZE 64 ++ ++#define NAND_BUFFER_LEN (DEFAULT_NAND_PAGESIZE + DEFAULT_NAND_OOBSIZE) ++ ++/*****************************************************************************/ ++#ifndef CONFIG_RW_H_WIDTH ++ #define CONFIG_RW_H_WIDTH (10) ++ #warning NOT config CONFIG_RW_H_WIDTH, used default value, maybe invalid. ++#endif ++ ++#ifndef CONFIG_R_L_WIDTH ++ #define CONFIG_R_L_WIDTH (10) ++ #warning NOT config CONFIG_R_L_WIDTH, used default value, maybe invalid. ++#endif ++ ++#ifndef CONFIG_W_L_WIDTH ++ #define CONFIG_W_L_WIDTH (10) ++ #warning NOT config CONFIG_W_L_WIDTH, used default value, maybe invalid. ++#endif ++ ++extern void hifmc100_nand_controller_enable(int enable); ++ ++#endif /* End of __HIFMC100_NAND_OS_H__ */ +diff --git a/drivers/mtd/nand/hifmc100_nand/hifmc_nand_spl_ids.c b/drivers/mtd/nand/hifmc100_nand/hifmc_nand_spl_ids.c +new file mode 100644 +index 0000000..e0d7a39 +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100_nand/hifmc_nand_spl_ids.c +@@ -0,0 +1,942 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++ ++#include "../hinfc_gen.h" ++#include "hifmc100_nand.h" ++ ++/*****************************************************************************/ ++#define _768K (_256K + _512K) ++ ++/*****************************************************************************/ ++struct nand_flash_special_dev { ++ unsigned char id[8]; ++ int length; /* length of id. */ ++ unsigned long long chipsize; ++ struct nand_flash_dev *(*probe)(unsigned char *id); ++ char *name; ++ ++ unsigned long pagesize; ++ unsigned long erasesize; ++ unsigned long oobsize; ++ unsigned long options; ++ unsigned int read_retry_type; ++ ++#define BBP_LAST_PAGE 0x01 ++#define BBP_FIRST_PAGE 0x02 ++ unsigned int badblock_pos; ++ int flags; ++}; ++ ++/*****************************************************************************/ ++/* this is nand probe function. */ ++/*****************************************************************************/ ++ ++static struct nand_flash_dev *hynix_probe_v02(unsigned char *id) ++{ ++ struct nand_flash_dev *type = &g_nand_dev.flash_dev; ++ ++ int pagesizes[] = {_2K, _4K, _8K, 0}; ++ int oobsizes[] = {128, 224, 448, 0, 0, 0, 0, 0}; ++ int blocksizes[] = {_128K, _256K, _512K, _768K, _1M, _2M, 0, 0}; ++ ++ int blocktype = (((id[3] >> 5) & 0x04) | ((id[3] >> 4) & 0x03)); ++ int oobtype = (((id[3] >> 2) & 0x03) | ((id[3] >> 4) & 0x04)); ++ ++ type->options = 0; ++ type->pagesize = pagesizes[(id[3] & 0x03)]; ++ type->erasesize = blocksizes[blocktype]; ++ type->oobsize = oobsizes[oobtype]; ++ ++ return type; ++} ++ ++/*****************************************************************************/ ++static struct nand_flash_dev *samsung_probe_v02(unsigned char *id) ++{ ++ struct nand_flash_dev *type = &g_nand_dev.flash_dev; ++ ++ int pagesizes[] = {_2K, _4K, _8K, 0}; ++ int oobsizes[] = {0, 128, 218, 400, 436, 0, 0, 0}; ++ int blocksizes[] = {_128K, _256K, _512K, _1M, 0, 0, 0, 0}; ++ ++ int blocktype = (((id[3] >> 5) & 0x04) | ((id[3] >> 4) & 0x03)); ++ int oobtype = (((id[3] >> 4) & 0x04) | ((id[3] >> 2) & 0x03)); ++ ++ type->options = 0; ++ type->pagesize = pagesizes[(id[3] & 0x03)]; ++ type->erasesize = blocksizes[blocktype]; ++ type->oobsize = oobsizes[oobtype]; ++ ++ return type; ++} ++ ++/*****************************************************************************/ ++ ++#define DRV_VERSION "1.39" ++ ++/*****************************************************************************/ ++/* ++ * samsung: 27nm need randomizer, 21nm need read retry; ++ * micron: 25nm need read retry, datasheet will explain read retry. ++ * toshaba 32nm need randomizer, 24nm need read retry. ++ * hynix: 2xnm need read retry. ++ * ++ * The special nand flash ID table version 1.39 ++ * ++ * manufactory | type | name | ecc_type | version_tag ++ * Micron | MLC | MT29F64G08CBABA | 40bit/1k | 1.36 ++ * Micron | MLC | MT29F32G08CBADA | 40bit/1k | ++ * Micron | SLC | MT29F8G08ABxBA | 4bit/512 | ++ * Micron | MLC | MT29F16G08CBABx | 12bit/512 | ++ * Micron | MLC | MT29F16G08CBACA | 24bit/1k | ++ * Micron | MLC | MT29F32G08CBACA | 24bit/1k | ++ * Micron | MLC | MT29F64G08CxxAA | 24bit/1k | ++ * Micron | MLC | MT29F256G08CJAAA | 24bit/1k | 2CE ++ * Micron | MLC | MT29F256G08CMCBB | 24bit/1k | ++ * Micron | SLC | MT29F8G08ABACA | 8bit/512 | ++ * Micron | SLC | MT29F4G08ABAEA | 8bit/512 | ++ * Micron | SLC | MT29F2G08ABAFA | 8bit/512 | ++ * Micron | SLC | MT29F16G08ABACA | 8bit/512 | ++ * Toshiba | MLC | TC58NVG4D2FTA00 | 24bit/1k | ++ * Toshiba | MLC | TH58NVG6D2FTA20 | 24bit/1k | 2CE ++ * Toshiba | MLC | TC58NVG5D2HTA00 | 40bit/1k | ++ * Toshiba | MLC | TC58NVG6D2GTA00 | 40bit/1k | ++ * Toshiba | MLC | TC58NVG6DCJTA00 | | ++ * Toshiba | MLC | TC58TEG5DCJTA00 | | ++ * Toshiba | SLC | TC58NVG0S3HTA00 | 8bit/512 | ++ * Toshiba | SLC | TC58NVG1S3HTA00 | 8bit/512 | ++ * Toshiba | SLC | TC58NVG1S3ETA00 | 4bit/512 | ++ * Toshiba | SLC | TC58NVG3S0FTA00 | 4bit/512 | ++ * Toshiba | SLC | TC58NVG2S0FTA00 | 4bit/512 | ++ * Toshiba | SLC | TH58NVG2S3HTA00 | 4bit/512 | ++ * Toshiba | TLC | TC58NVG5T2JTA00 | 60bit/1k | ++ * Toshiba | TLC | TC58TEG5DCKTAx0 | 60bit/1k | ++ * Toshiba | MLC | Tx58TEGxDDKTAx0 | | ++ * Samsung | MLC | K9LB(HC/PD/MD)G08U0(1)D | 8bit/512B | ++ * Samsung | MLC | K9GAG08U0E | 24bit/1KB | ++ * Samsung | MLC | K9LBG08U0E | 24bit/1KB | ++ * Samsung | MLC | K9G8G08U0C | 24bit/1KB | ++ * Samsung | MLC | K9GAG08U0F | 24bit/1KB | ++ * Samsung | MLC | K9LBG08U0M | | ++ * Samsung | MLC | K9GBG08U0A | 24bit/1KB | ++ * Samsung | MLC | K9GBG08U0B | 40bit/1KB | ++ * Hynix | MLC | H27UAG8T2A | | ++ * Hynix | MLC | H27UAG8T2B | | ++ * Hynix | MLC | H27UBG8T2A | | ++ * Hynix | MLC | H27UBG8T2BTR | 24bit/1KB | ++ * Hynix | MLC | H27UCG8T2A | 40bit/1KB | ++ * Hynix | MLC | H27UBG8T2C | 40bit/1KB | ++ * MISC | MLC | P1UAGA30AT-GCA | 8bit/512 | ++ * MISC | MLC | PSU8GA30AT-GIA/ASU8GA30IT-G30CA | 4bit/512 | ++ * MISC | SLC | PSU2GA30AT | 1bit/512 | 1.36 ++ * Toshiba | SLC | TC58NVG2S0HTA00 | 24bit/1K | 1.37 ++ * Toshiba | SLC | TC58NVG3S0HTA00 | 24bit/1K | 1.37 ++ * Micron | SLC | MT29F2G08ABAEA | 4bit/512 | ++ * Spansion | SLC | S34ML02G200TFI000 | 24bit/1K | ++ * Spansion | SLC | S34ML04G200TFI000 | 24bit/1K | 1.38 ++ * MXIC Macronix| SLC | MX30UF2G18AC 1.8V | 4bit/512 | 1.39 ++ * ++ */ ++static struct nand_flash_special_dev nand_flash_special_table[] = { ++ ++ /************************* 1.8V MXIC Macronix **************************/ ++ { /* SLC 4bit/512 1.8V */ ++ .name = "MX30UF2G18AC", ++ .id = {0xC2, 0xAA, 0x90, 0x15, 0x06}, ++ .length = 5, ++ .chipsize = _256M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 64, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ ++ /****************************** Spansion *******************************/ ++ ++ { /* SLC S34ML02G200TFI000 */ ++ .name = "S34ML02G200TFI000", ++ .id = {0x01, 0xDA, 0x90, 0x95, 0x46, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _256M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ ++ { /* SLC S34ML04G200TFI000 */ ++ .name = "S34ML04G200TFI000", ++ .id = {0x01, 0xDC, 0x90, 0x95, 0x56, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _512M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ ++ /****************************** Micron *******************************/ ++ ++ { /* MLC 40bit/1k */ ++ .name = "MT29F64G08CBABA", ++ .id = {0x2C, 0x64, 0x44, 0x4B, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _2M, ++ .oobsize = 744, ++ .options = 0, ++ .read_retry_type = NAND_RR_MICRON, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = NAND_RANDOMIZER | NAND_CHIP_MICRON, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "MT29F32G08CBADA", ++ .id = {0x2C, 0x44, 0x44, 0x4B, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _2M, ++ .oobsize = 744, ++ .options = 0, ++ .read_retry_type = NAND_RR_MICRON, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "MT29F8G08ABxBA", ++ .id = {0x2C, 0x38, 0x00, 0x26, 0x85, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _1G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _512K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 12bit/512 */ ++ .name = "MT29F16G08CBABx", ++ .id = {0x2C, 0x48, 0x04, 0x46, 0x85, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _2G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _1M, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "MT29F16G08CBACA", ++ .id = {0x2C, 0x48, 0x04, 0x4A, 0xA5, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _2G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _1M, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "MT29F32G08CBACA", ++ .id = {0x2C, 0x68, 0x04, 0x4A, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _1M, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "MT29F64G08CxxAA", ++ .id = {0x2C, 0x88, 0x04, 0x4B, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _2M, ++ .oobsize = 448, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 24bit/1k 2CE */ ++ .name = "MT29F256G08CJAAA", ++ .id = {0x2C, 0xA8, 0x05, 0xCB, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _16G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _2M, ++ .oobsize = 448, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "MT29F256G08CMCBB", ++ .id = {0x2C, 0x64, 0x44, 0x4B, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _2M, ++ .oobsize = 744, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "MT29F8G08ABACA", ++ .id = {0x2C, 0xD3, 0x90, 0xA6, 0x64, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _1G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _256K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "MT29F4G08ABAEA", ++ .id = {0x2C, 0xDC, 0x90, 0xA6, 0x54, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _512M, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _256K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "MT29F2G08ABAFA", ++ .id = {0x2C, 0xDA, 0x90, 0x95, 0x04, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _256M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC MT29F2G08ABAEA */ ++ .name = "MT29F2G08ABAEA", ++ .id = {0x2C, 0xDA, 0x90, 0x95, 0x06, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _256M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 64, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "MT29F16G08ABACA", ++ .id = {0x2C, 0x48, 0x00, 0x26, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _2G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _512K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ ++ /****************************** Toshaba *******************************/ ++ ++ { /* MLC 24bit/1k 32nm */ ++ .name = "TC58NVG4D2FTA00", ++ .id = {0x98, 0xD5, 0x94, 0x32, 0x76, 0x55, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _2G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _1M, ++ .oobsize = 448, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k 32nm 2CE*/ ++ .name = "TH58NVG6D2FTA20", ++ .id = {0x98, 0xD7, 0x94, 0x32, 0x76, 0x55, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _1M, ++ .oobsize = 448, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 40bit/1k 24nm */ ++ .name = "TC58NVG5D2HTA00 24nm", ++ .id = {0x98, 0xD7, 0x94, 0x32, 0x76, 0x56, 0x08, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _1M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_24nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "TC58NVG6D2GTA00", ++ .id = {0x98, 0xDE, 0x94, 0x82, 0x76, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _2M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 19nm */ ++ .name = "TC58NVG6DCJTA00 19nm", ++ .id = {0x98, 0xDE, 0x84, 0x93, 0x72, 0x57, 0x08, 0x04}, ++ .length = 8, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = _16K, ++ .erasesize = _4M, ++ .oobsize = 1280, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_24nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 19nm */ ++ .name = "TC58TEG5DCJTA00 19nm", ++ .id = {0x98, 0xD7, 0x84, 0x93, 0x72, 0x57, 0x08, 0x04}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _16K, ++ .erasesize = _4M, ++ .oobsize = 1280, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_24nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER | NAND_CHIP_TOSHIBA_TOGGLE_10, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "TC58NVG0S3HTA00", ++ .id = {0x98, 0xF1, 0x80, 0x15, 0x72, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _128M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ /* ++ * Datasheet: read one column of any page in each block. If the ++ * data of the column is 00 (Hex), define the block as a bad ++ * block. ++ */ ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "TC58NVG1S3HTA00", ++ .id = {0x98, 0xDA, 0x90, 0x15, 0x76, 0x16, 0x08, 0x00}, ++ .length = 7, ++ .chipsize = _256M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "TC58NVG1S3ETA00", ++ .id = {0x98, 0xDA, 0x90, 0x15, 0x76, 0x14, 0x03, 0x00}, ++ .length = 7, ++ .chipsize = _256M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 64, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "TC58NVG3S0FTA00", ++ .id = {0x98, 0xD3, 0x90, 0x26, 0x76, 0x15, 0x02, 0x08}, ++ .length = 8, ++ .chipsize = _1G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _256K, ++ .oobsize = 232, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 24bit/1k */ ++ .name = "TC58NVG3S0HTA00", ++ .id = {0x98, 0xD3, 0x91, 0x26, 0x76, 0x16, 0x08, 0x00}, ++ .length = 8, ++ .chipsize = _1G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _256K, ++ .oobsize = 256, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 24bit/1k */ ++ .name = "TC58NVG2S0HTA00", ++ .id = {0x98, 0xDC, 0x90, 0x26, 0x76, 0x16, 0x08, 0x00}, ++ .length = 8, ++ .chipsize = _512M, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _256K, ++ .oobsize = 256, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "TC58NVG2S0FTA00", ++ .id = {0x98, 0xDC, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08}, ++ .length = 8, ++ .chipsize = _512M, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _256K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "TH58NVG2S3HTA00", ++ .id = {0x98, 0xDC, 0x91, 0x15, 0x76}, ++ .length = 5, ++ .chipsize = _512M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* TLC 60bit/1k 19nm */ ++ .name = "TC58NVG5T2JTA00 19nm TLC", ++ /* datasheet says 6 ids id data, but really has 8 ids. */ ++ .id = {0x98, 0xD7, 0x98, 0x92, 0x72, 0x57, 0x08, 0x10}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _4M, ++ .oobsize = 1024, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_24nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* TLC 60bit/1k 19nm */ ++ .name = "TC58TEG5DCKTAx0 19nm MLC", ++ /* datasheet says 6 ids id data, but really has 8 ids. */ ++ .id = {0x98, 0xD7, 0x84, 0x93, 0x72, 0x50, 0x08, 0x04}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _16K, ++ .erasesize = _4M, ++ .oobsize = 1280, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_19nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { ++ .name = "Tx58TEGxDDKTAx0 19nm MLC", ++ .id = {0x98, 0xDE, 0x94, 0x93, 0x76, 0x50}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _16K, ++ .erasesize = _4M, ++ .oobsize = 1280, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_19nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ /******************************* Samsung ******************************/ ++ { /* MLC 8bit/512B */ ++ .name = "K9LB(HC/PD/MD)G08U0(1)D", ++ .id = {0xEC, 0xD7, 0xD5, 0x29, 0x38, 0x41, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = samsung_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1KB */ ++ .name = "K9GAG08U0E", ++ .id = {0xEC, 0xD5, 0x84, 0x72, 0x50, 0x42, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _2G, ++ .probe = samsung_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1KB */ ++ .name = "K9LBG08U0E", ++ .id = {0xEC, 0xD7, 0xC5, 0x72, 0x54, 0x42, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = samsung_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1KB */ ++ .name = "K9G8G08U0C", ++ .id = {0xEC, 0xD3, 0x84, 0x72, 0x50, 0x42, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _1G, ++ .probe = samsung_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "K9GAG08U0F", ++ .id = {0xEC, 0xD5, 0x94, 0x76, 0x54, 0x43, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _2G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _1M, ++ .oobsize = 512, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC */ ++ .name = "K9LBG08U0M", ++ .id = {0xEC, 0xD7, 0x55, 0xB6, 0x78, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _512K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "K9GBG08U0A 20nm", ++ .id = {0xEC, 0xD7, 0x94, 0x7A, 0x54, 0x43, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _1M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_SAMSUNG, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "K9GBG08U0B", ++ .id = {0xEC, 0xD7, 0x94, 0x7E, 0x64, 0x44, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _1M, ++ .oobsize = 1024, ++ .options = 0, ++ .read_retry_type = NAND_RR_SAMSUNG, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ ++ /*********************************** Hynix ****************************/ ++ { /* MLC */ ++ .name = "H27UAG8T2A", ++ .id = {0xAD, 0xD5, 0x94, 0x25, 0x44, 0x41, }, ++ .length = 6, ++ .chipsize = _2G, ++ .probe = hynix_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC */ ++ .name = "H27UAG8T2B", ++ .id = {0xAD, 0xD5, 0x94, 0x9A, 0x74, 0x42, }, ++ .length = 6, ++ .chipsize = _2G, ++ .probe = hynix_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC */ ++ .name = "H27UBG8T2A", ++ .id = {0xAD, 0xD7, 0x94, 0x9A, 0x74, 0x42, }, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = hynix_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1K, 26nm TODO: Need read retry, chip is EOS */ ++ .name = "H27UBG8T2BTR 26nm", ++ .id = {0xAD, 0xD7, 0x94, 0xDA, 0x74, 0xC3, }, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _2M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_HYNIX_BG_BDIE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "H27UCG8T2A", ++ .id = {0xAD, 0xDE, 0x94, 0xDA, 0x74, 0xC4, }, ++ .length = 6, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _2M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_HYNIX_CG_ADIE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "H27UBG8T2C", ++ .id = {0xAD, 0xD7, 0x94, 0x91, 0x60, 0x44, }, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _2M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_HYNIX_BG_CDIE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ ++ /********************** MISC ******************************************/ ++ { /* MLC 8bit/512 */ ++ .name = "P1UAGA30AT-GCA", ++ .id = {0xC8, 0xD5, 0x14, 0x29, 0x34, 0x01, }, ++ .length = 6, ++ .chipsize = _2G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _512K, ++ .oobsize = 218, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 4bit/512 */ ++ /* ++ * PowerFlash ASU8GA30IT-G30CA ID and MIRA PSU8GA30AT-GIA ID are ++ * the same ID ++ */ ++ .name = "PSU8GA30AT-GIA/ASU8GA30IT-G30CA", ++ .id = {0xC8, 0xD3, 0x90, 0x19, 0x34, 0x01, }, ++ .length = 6, ++ .chipsize = _1G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _256K, ++ .oobsize = 218, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 1bit/512 */ ++ .name = "PSU2GA30AT", ++ .id = {0x7F, 0x7F, 0x7F, 0x7F, 0xC8, 0xDA, 0x00, 0x15, }, ++ .length = 8, ++ .chipsize = _256M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 64, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ {{0}, 0, 0, 0, 0, 0, 0, 0, 0}, ++}; ++ ++struct nand_dev_t g_nand_dev; ++/*****************************************************************************/ ++struct nand_flash_dev *hifmc_get_spl_flash_type(struct mtd_info *mtd, ++ unsigned char *id) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct nand_flash_special_dev *spl_dev = nand_flash_special_table; ++ struct nand_flash_dev *type = &g_nand_dev.flash_dev; ++ struct nand_dev_t *nand_dev = &g_nand_dev; ++ ++ FMC_PR(BT_DBG, "\t *-Start find special nand flash\n"); ++ ++ pr_info("Nand ID: %#X %#X %#X %#X %#X %#X %#X %#X\n", id[0], id[1], ++ id[2], id[3], id[4], id[5], id[6], id[7]); ++ ++ for (; spl_dev->length; spl_dev++) { ++ if (memcmp(id, spl_dev->id, spl_dev->length)) ++ continue; ++ ++ FMC_PR(BT_DBG, "\t |-Found special Nand flash: %s\n", ++ spl_dev->name); ++ ++ if (spl_dev->probe) { ++ type = spl_dev->probe(id); ++ } else { ++ type->options = spl_dev->options; ++ type->pagesize = spl_dev->pagesize; ++ type->erasesize = spl_dev->erasesize; ++ type->oobsize = spl_dev->oobsize; ++ } ++ ++ type->name = spl_dev->name; ++ type->id_len = spl_dev->length; ++ memcpy(type->id, id, type->id_len); ++ type->chipsize = (unsigned int)(spl_dev->chipsize >> 20); ++ FMC_PR(BT_DBG, "\t |-Save struct nand_flash_dev info\n"); ++ ++ memcpy(nand_dev->ids, id, MAX_NAND_ID_LEN); ++ nand_dev->oobsize = type->oobsize; ++ nand_dev->flags = spl_dev->flags; ++ nand_dev->read_retry_type = spl_dev->read_retry_type; ++ FMC_PR(BT_DBG, "\t |-Save struct nand_dev_t information\n"); ++ ++ mtd->size = spl_dev->chipsize; ++ ++ return type; ++ } ++ nand_dev->read_retry_type = NAND_RR_NONE; ++ ++ chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); ++ chip->read_byte(mtd); ++ chip->read_byte(mtd); ++ ++ FMC_PR(BT_DBG, "\t *-Not found special nand flash\n"); ++ ++ return NULL; ++} ++ ++/*****************************************************************************/ ++void hifmc_spl_ids_register(void) ++{ ++ pr_info("Special NAND id table Version %s\n", DRV_VERSION); ++ get_spi_nand_flash_type_hook = hifmc_get_spl_flash_type; ++} +diff --git a/drivers/mtd/nand/hinfc610/Kconfig b/drivers/mtd/nand/hinfc610/Kconfig +new file mode 100644 +index 0000000..e59d7fe +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/Kconfig +@@ -0,0 +1,94 @@ ++menuconfig MTD_NAND_HINFC610 ++ tristate "Hisilicon NAND Controller v610 Nand devices Support" ++ depends on !MTD_SPI_NAND_HISI_BVT && (ARCH_HI3516A || ARCH_HI3531A) ++ select YAFFS_FS ++ select MISC_FILESYSTEMS ++ select MTD_BLOCK ++ select YAFFS_YAFFS2 ++ help ++ When the config is set, the kernel will support Hisilicon ++ NAND Controller v610 devices. It means that the kernel would ++ control the nand flash with the nand controller v610 device ++ in operation. ++ ++if MTD_NAND_HINFC610 ++ ++config HINFC610_MAX_CHIP ++ int "number of nand flash chip (1,4)" ++ range 1 4 ++ default 1 ++ help ++ nand controller v610 device only support 1 or 2 nand flash chip, ++ your should not config other value. ++ ++config HINFC610_DBG_NAND_DEBUG ++ bool "Debug: create debug file to control debug type" ++ default y ++ help ++ When the config is set, the kernel will add the "debug" file ++ to control debug type. When the config is set, we could choose ++ the debugging type to display the informations of the nand controller ++ v610 device in operation. ++ ++config HINFC610_DBG_NAND_DUMP ++ bool "Debug: display read/write/erase process nand data" ++ depends on HINFC610_DBG_NAND_DEBUG ++ default y ++ default n if (ARCH_HI3516A) ++ help ++ When the config is set, the kernel will add "dump" file to ++ display all nand operation and data.When the "HINFC610_DBG_NAND_DEBUG" ++ has been set, the nand controller v610 device will display ++ all the operations and data. ++ ++config HINFC610_DBG_NAND_ERASE_COUNT ++ bool "Debug: display last erase count" ++ depends on HINFC610_DBG_NAND_DEBUG ++ default y ++ default n if (ARCH_HI3516A) ++ help ++ When the config is set, the kernel will add "erase_count" file ++ to display last erase count. When the "HINFC610_DBG_NAND_DEBUG" ++ has been set, the nand controller v610 device will display ++ the last erase count. ++ ++config HINFC610_DBG_NAND_ECC_COUNT ++ bool "Debug: display last ecc count." ++ depends on HINFC610_DBG_NAND_DEBUG ++ default y ++ default n if (ARCH_HI3516A) ++ help ++ When the config is set, the kernel will add "ecc_count" ++ to display last ecc count. When the "HINFC610_DBG_NAND_DEBUG" ++ has been set, the nand controller v610 device will display ++ the last ecc count. ++ ++config HINFC610_DBG_NAND_READ_RETRY ++ bool "Debug: display read_retry process" ++ depends on HINFC610_DBG_NAND_DEBUG ++ default y ++ default n if (ARCH_HI3516A) ++ help ++ When the config is set, the kernel will add read_retry file ++ to display read_retry process. ++ ++choice ++ prompt "Pagesize and Ecc Type Select" ++ default HINFC610_AUTO_PAGESIZE_ECC if ARCH_HI3516A ++ ++config HINFC610_AUTO_PAGESIZE_ECC ++ bool "Auto" ++ help ++ When the config is set, pagesize and ecc type will use ++ hardware config. When we replace the flash, the ++ controller will identify the pagesize and ecc type of ++ the flash. ++ ++config HINFC610_PAGESIZE_AUTO_ECC_NONE ++ bool "Pagesize Auto, Ecc None" ++ help ++ select pagesize 2K, ecc none. ++ ++endchoice ++ ++endif # MTD_NAND_HINFC610 +diff --git a/drivers/mtd/nand/hinfc610/Makefile b/drivers/mtd/nand/hinfc610/Makefile +new file mode 100644 +index 0000000..9ef9acd +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/Makefile +@@ -0,0 +1,19 @@ ++ ++obj-$(CONFIG_MTD_NAND_HINFC610) += hinfc610.o hinfc610_os.o hinfc610_gen.o \ ++ hinfc620_gen.o hinfc610_dbg_inf.o \ ++ hinfc610_read_retry_hynix_bg_cdie.o \ ++ hinfc610_read_retry_hynix_bg_bdie.o \ ++ hinfc610_read_retry_hynix_cg_adie.o \ ++ hinfc610_read_retry_micron.o \ ++ hinfc610_read_retry_samsung.o \ ++ hinfc610_read_retry_toshiba.o \ ++ hinfc610_read_retry.o \ ++ hinfc610_sync.o \ ++ hinfc610_sync_onfi_23.o \ ++ hinfc610_sync_toggle.o ++ ++obj-$(CONFIG_HINFC610_DBG_NAND_DEBUG) += hinfc610_dbg.o hinfc610_dbg_ecc_dump.o ++obj-$(CONFIG_HINFC610_DBG_NAND_DUMP) += hinfc610_dbg_dump.o ++obj-$(CONFIG_HINFC610_DBG_NAND_ERASE_COUNT) += hinfc610_dbg_erase_count.o ++obj-$(CONFIG_HINFC610_DBG_NAND_ECC_COUNT) += hinfc610_dbg_ecc_count.o ++obj-$(CONFIG_HINFC610_DBG_NAND_READ_RETRY) += hinfc610_dbg_read_retry.o +diff --git a/drivers/mtd/nand/hinfc610/hinfc610.c b/drivers/mtd/nand/hinfc610/hinfc610.c +new file mode 100644 +index 0000000..eb8cb7f +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610.c +@@ -0,0 +1,1196 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#define pr_fmt(fmt) "hinfc610: " fmt ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++#include "hinfc610_dbg_inf.h" ++#include "hinfc610_gen.h" ++#include "hinfc620_gen.h" ++#include "hinfc610_sync.h" ++#include "hinfc610_read_retry.h" ++ ++/*****************************************************************************/ ++static unsigned int get_8bits(unsigned char byte) ++{ ++ int ix = 0; ++ int num = 0; ++ ++ if (byte == 0xFF) ++ return 8; ++ if (!byte) ++ return 0; ++ ++ while (ix++ < 8) { ++ if ((byte & 1)) ++ num++; ++ byte = (byte >> 1); ++ } ++ return num; ++} ++/*****************************************************************************/ ++ ++static unsigned int get_16bits(unsigned short byte) ++{ ++ int ix = 0; ++ int num = 0; ++ ++ if (byte == 0xFFFF) ++ return 16; ++ if (!byte) ++ return 0; ++ ++ while (ix++ < 16) { ++ if ((byte & 1)) ++ num++; ++ byte = (byte >> 1); ++ } ++ return num; ++} ++/*****************************************************************************/ ++ ++static void hinfc610_dma_transfer(struct hinfc_host *host, int todev) ++{ ++ unsigned long reg_val; ++ unsigned int dma_addr = (unsigned int)host->dma_buffer; ++ ++ hinfc_write(host, dma_addr, HINFC610_DMA_ADDR_DATA); ++ ++ dma_addr += HINFC610_DMA_ADDR_OFFSET; ++ hinfc_write(host, dma_addr, HINFC610_DMA_ADDR_DATA1); ++ ++ dma_addr += HINFC610_DMA_ADDR_OFFSET; ++ hinfc_write(host, dma_addr, HINFC610_DMA_ADDR_DATA2); ++ ++ dma_addr += HINFC610_DMA_ADDR_OFFSET; ++ hinfc_write(host, dma_addr, HINFC610_DMA_ADDR_DATA3); ++ ++ /* 32K PAGESIZE need below. */ ++ dma_addr += HINFC610_DMA_ADDR_OFFSET; ++ hinfc_write(host, dma_addr, HINFC610_DMA_ADDR_DATA4); ++ ++ dma_addr += HINFC610_DMA_ADDR_OFFSET; ++ hinfc_write(host, dma_addr, HINFC610_DMA_ADDR_DATA5); ++ ++ dma_addr += HINFC610_DMA_ADDR_OFFSET; ++ hinfc_write(host, dma_addr, HINFC610_DMA_ADDR_DATA6); ++ ++ dma_addr += HINFC610_DMA_ADDR_OFFSET; ++ hinfc_write(host, dma_addr, HINFC610_DMA_ADDR_DATA7); ++ ++ hinfc_write(host, host->dma_oob, HINFC610_DMA_ADDR_OOB); ++ ++ if (host->ecctype == NAND_ECC_NONE) { ++ hinfc_write(host, ++ ((host->oobsize & HINFC610_DMA_LEN_OOB_MASK) ++ << HINFC610_DMA_LEN_OOB_SHIFT), ++ HINFC610_DMA_LEN); ++ ++ hinfc_write(host, ++ HINFC610_DMA_PARA_DATA_RW_EN ++ | HINFC610_DMA_PARA_OOB_RW_EN, ++ HINFC610_DMA_PARA); ++ } else ++ hinfc_write(host, ++ HINFC610_DMA_PARA_DATA_RW_EN ++ | HINFC610_DMA_PARA_OOB_RW_EN ++ | HINFC610_DMA_PARA_DATA_EDC_EN ++ | HINFC610_DMA_PARA_OOB_EDC_EN, ++ HINFC610_DMA_PARA); ++ ++ reg_val = (HINFC610_DMA_CTRL_DMA_START ++ | HINFC610_DMA_CTRL_BURST4_EN ++ | HINFC610_DMA_CTRL_BURST8_EN ++ | HINFC610_DMA_CTRL_BURST16_EN ++ | ((host->addr_cycle == 4 ? 1 : 0) ++ << HINFC610_DMA_CTRL_ADDR_NUM_SHIFT) ++ | (((unsigned int)host->chipselect & HINFC610_DMA_CTRL_CS_MASK) ++ << HINFC610_DMA_CTRL_CS_SHIFT)); ++ ++ if (todev) ++ reg_val |= HINFC610_DMA_CTRL_WE; ++ ++ hinfc_write(host, reg_val, HINFC610_DMA_CTRL); ++ ++ do { ++ unsigned int timeout = 0xF0000000; ++ ++ while ((hinfc_read(host, HINFC610_DMA_CTRL)) ++ & HINFC610_DMA_CTRL_DMA_START && timeout) { ++ _cond_resched(); ++ timeout--; ++ } ++ if (!timeout) ++ PR_BUG("Wait DMA finish timeout.\n"); ++ } while (0); ++} ++/*****************************************************************************/ ++ ++static void hinfc610_sync_entry(struct hinfc_host *host) ++{ ++ struct nand_sync *sync = host->sync; ++ struct nand_chip *chip = host->chip; ++ ++ if (!sync) { ++ PR_BUG("this NAND not support sync feature.\n"); ++ return; ++ } ++ ++ if (HINFC610_IS_SYNC(host)) { ++ PR_BUG("this NAND not support sync feature.\n"); ++ return; ++ } ++ ++ if (sync->enable) ++ sync->enable(chip); ++ ++ clk_prepare_enable(host->clk); ++ ++ switch (sync->type) { ++ case NAND_TYPE_TOGGLE_10: ++ host->NFC_CON |= HINFC610_CON_NF_MODE_TOGGLE; ++ host->NFC_CON_ECC_NONE |= HINFC610_CON_NF_MODE_TOGGLE; ++ break; ++ ++ case NAND_TYPE_ONFI_23: ++ host->NFC_CON |= HINFC610_CON_NF_MODE_ONFI_23; ++ host->NFC_CON_ECC_NONE |= HINFC610_CON_NF_MODE_ONFI_23; ++ break; ++ ++ case NAND_TYPE_ONFI_30: ++ host->NFC_CON |= HINFC610_CON_NF_MODE_ONFI_30; ++ host->NFC_CON_ECC_NONE |= HINFC610_CON_NF_MODE_ONFI_30; ++ break; ++ ++ default: ++ PR_BUG("Unsupport sync type 0x%08X.\n", sync->type); ++ break; ++ } ++} ++/*****************************************************************************/ ++ ++static void hinfc610_sync_exit(struct hinfc_host *host) ++{ ++ struct nand_sync *sync = host->sync; ++ struct nand_chip *chip = host->chip; ++ ++ if (!HINFC610_IS_SYNC(host)) { ++ PR_BUG("Current already exit from sync feature.\n"); ++ return; ++ } ++ ++ if (sync->disable) ++ sync->disable(chip); ++ ++ host->NFC_CON &= ~HINFC610_CON_NF_MODE_MASK; ++ host->NFC_CON_ECC_NONE &= ~HINFC610_CON_NF_MODE_MASK; ++ ++ clk_disable_unprepare(host->clk); ++} ++/*****************************************************************************/ ++ ++void hinfc610_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) ++{ ++ int is_cache_invalid = 1; ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hinfc_host *host = chip->priv; ++ ++ if (ctrl & NAND_ALE) { ++ unsigned int addr_value = 0; ++ unsigned int addr_offset = 0; ++ ++ if (ctrl & NAND_CTRL_CHANGE) { ++ host->addr_cycle = 0x0; ++ host->addr_value[0] = 0x0; ++ host->addr_value[1] = 0x0; ++ } ++ addr_offset = host->addr_cycle << 3; ++ ++ if (host->addr_cycle >= HINFC610_ADDR_CYCLE_MASK) { ++ addr_offset = ++ (host->addr_cycle - HINFC610_ADDR_CYCLE_MASK) << 3; ++ addr_value = 1; ++ } ++ ++ host->addr_value[addr_value] |= ++ ((dat & 0xff) << addr_offset); ++ ++ host->addr_cycle++; ++ } ++ ++ if ((ctrl & NAND_CLE) && (ctrl & NAND_CTRL_CHANGE)) { ++ host->command = dat & 0xff; ++ switch (host->command) { ++ case NAND_CMD_PAGEPROG: ++ host->send_cmd_pageprog(host); ++ hinfc610_dbg_write(host); ++ break; ++ ++ case NAND_CMD_READSTART: ++ is_cache_invalid = 0; ++ host->send_cmd_readstart(host); ++ hinfc610_dbg_read(host); ++ ++ break; ++ ++ case NAND_CMD_ERASE2: ++ host->send_cmd_erase(host); ++ hinfc610_dbg_erase(host); ++ ++ break; ++ ++ case NAND_CMD_READID: ++ memset((unsigned char *)(chip->IO_ADDR_R), 0, 0x10); ++ host->send_cmd_readid(host); ++ break; ++ ++ case NAND_CMD_STATUS: ++ host->send_cmd_status(host); ++ break; ++ ++ case NAND_CMD_SEQIN: ++ case NAND_CMD_ERASE1: ++ case NAND_CMD_READ0: ++ break; ++ case NAND_CMD_RESET: ++ host->send_cmd_reset(host, host->chipselect); ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ if ((dat == NAND_CMD_NONE) && host->addr_cycle) { ++ if (host->command == NAND_CMD_SEQIN || ++ host->command == NAND_CMD_READ0 || ++ host->command == NAND_CMD_READID) { ++ host->offset = 0x0; ++ host->column = (host->addr_value[0] & 0xffff); ++ } ++ } ++ ++ if (is_cache_invalid) { ++ host->cache_addr_value[0] = ~0; ++ host->cache_addr_value[1] = ~0; ++ } ++} ++/*****************************************************************************/ ++ ++static int hinfc610_send_cmd_pageprog(struct hinfc_host *host) ++{ ++ if (*host->bbm != 0xFF && *host->bbm != 0x00) ++ pr_warn("Attempt to write an invalid bbm. page: 0x%08x, mark: 0x%02x, current process(pid): %s(%d).\n", ++ GET_PAGE_INDEX(host), *host->bbm, ++ current->comm, current->pid); ++ ++ if (IS_NAND_SYNC_ASYNC(host)) ++ hinfc610_sync_entry(host); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ hinfc_write(host, host->addr_value[0] & 0xffff0000, HINFC610_ADDRL); ++ hinfc_write(host, host->addr_value[1], HINFC610_ADDRH); ++ hinfc_write(host, ++ ((NAND_CMD_STATUS << 16) | (NAND_CMD_PAGEPROG << 8) | ++ NAND_CMD_SEQIN), ++ HINFC610_CMD); ++ ++ *host->epm = 0x0000; ++ ++ hinfc610_dma_transfer(host, 1); ++ ++ if (IS_NAND_SYNC_ASYNC(host)) ++ hinfc610_sync_exit(host); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_get_data_status(struct hinfc_host *host) ++{ ++ unsigned int page_status = 0; ++ ++ if (IS_PS_UN_ECC(host)) ++ page_status = HINFC610_PS_UC_ECC; ++ ++ /* this is block start address */ ++ if (!((host->addr_value[0] >> 16) & host->block_page_mask)) { ++ ++ /* it is a bad block */ ++ if (*host->bbm == 0x00) { ++ page_status |= HINFC610_PS_BAD_BLOCK; ++ goto out; ++ } ++ ++ if (*host->bbm != 0xFF) { ++ page_status |= HINFC610_PS_BBM_ERROR; ++ ++ /* ++ * if there are more than 2 bits flipping, it is ++ * maybe a bad block ++ */ ++ if (!IS_PS_UN_ECC(host) || get_8bits(*host->bbm) < 6) { ++ page_status |= HINFC610_PS_BAD_BLOCK; ++ goto out; ++ } ++ } ++ } ++ ++ if (*host->epm == 0x0000) ++ goto out; ++ ++ if (*host->epm == 0xFFFF) { ++ page_status |= HINFC610_PS_EMPTY_PAGE; ++ goto out; ++ } ++ ++ page_status |= HINFC610_PS_EPM_ERROR; ++ ++ if (IS_PS_UN_ECC(host) && get_16bits(*host->epm) > 12) { ++ page_status |= HINFC610_PS_EMPTY_PAGE; ++ goto out; ++ } ++ ++out: ++ return page_status; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_do_read_retry(struct hinfc_host *host) ++{ ++ int ix; ++ ++ for (ix = 1; IS_PS_UN_ECC(host) && ix < host->read_retry->count; ix++) { ++ ++ hinfc_write(host, HINFC610_INTCLR_UE | HINFC610_INTCLR_CE, ++ HINFC610_INTCLR); ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ host->read_retry->set_rr_param(host, ix); ++ ++ /* enable ecc and randomizer */ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ hinfc_write(host, HINFC610_INTCLR_UE | HINFC610_INTCLR_CE, ++ HINFC610_INTCLR); ++ hinfc_write(host, host->NFC_CON, HINFC610_CON); ++ hinfc_write(host, host->addr_value[0] & 0xffff0000, ++ HINFC610_ADDRL); ++ hinfc_write(host, host->addr_value[1], HINFC610_ADDRH); ++ hinfc_write(host, ++ HINFC_CMD_SEQ(NAND_CMD_READ0, NAND_CMD_READSTART), ++ HINFC610_CMD); ++ ++ hinfc610_dma_transfer(host, 0); ++ ++ if (hinfc_read(host, HINFC610_INTS) & HINFC610_INTS_UE) ++ host->page_status |= HINFC610_PS_UC_ECC; ++ else ++ host->page_status &= ~HINFC610_PS_UC_ECC; ++ } ++ ++ host->page_status = hinfc610_get_data_status(host); ++ ++ hinfc610_dbg_read_retry(host, ix); ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ host->read_retry->reset_rr_param(host); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_send_cmd_readstart(struct hinfc_host *host) ++{ ++ if ((host->addr_value[0] == host->cache_addr_value[0]) && ++ (host->addr_value[1] == host->cache_addr_value[1])) ++ return 0; ++ ++ if (IS_NAND_SYNC_ASYNC(host)) ++ hinfc610_sync_entry(host); ++ ++ host->page_status = 0; ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ hinfc_write(host, HINFC610_INTCLR_UE | HINFC610_INTCLR_CE, ++ HINFC610_INTCLR); ++ hinfc_write(host, host->NFC_CON, HINFC610_CON); ++ hinfc_write(host, host->addr_value[0] & 0xffff0000, HINFC610_ADDRL); ++ hinfc_write(host, host->addr_value[1], HINFC610_ADDRH); ++ hinfc_write(host, NAND_CMD_READSTART << 8 | NAND_CMD_READ0, ++ HINFC610_CMD); ++ ++ hinfc610_dma_transfer(host, 0); ++ ++ if (hinfc_read(host, HINFC610_INTS) & HINFC610_INTS_UE) ++ host->page_status |= HINFC610_PS_UC_ECC; ++ ++ if (host->read_retry || IS_NAND_RANDOM(host)) { ++ host->page_status |= hinfc610_get_data_status(host); ++ ++ if (IS_PS_EMPTY_PAGE(host)) { ++ /* ++ * oob area used by yaffs2 only 32 bytes, ++ * so we only fill 32 bytes. ++ */ ++ if (IS_NAND_RANDOM(host)) ++ memset(host->buffer, 0xFF, ++ host->pagesize + host->oobsize); ++ ++ } else if (!IS_PS_BAD_BLOCK(host)) { ++ /* if NAND chip support read retry */ ++ if (IS_PS_UN_ECC(host) && host->read_retry) ++ hinfc610_do_read_retry(host); ++ ++ } /* 'else' NAND have a bad block, do nothing. */ ++ } ++ ++ if (IS_NAND_SYNC_ASYNC(host)) ++ hinfc610_sync_exit(host); ++ ++ host->cache_addr_value[0] = host->addr_value[0]; ++ host->cache_addr_value[1] = host->addr_value[1]; ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_send_cmd_erase(struct hinfc_host *host) ++{ ++ unsigned int regval; ++ ++ /* Don't case the read retry config */ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, host->addr_value[0], HINFC610_ADDRL); ++ hinfc_write(host, (NAND_CMD_ERASE2 << 8) | NAND_CMD_ERASE1, ++ HINFC610_CMD); ++ ++ regval = HINFC610_OP_WAIT_READY_EN ++ | HINFC610_OP_CMD2_EN ++ | HINFC610_OP_CMD1_EN ++ | HINFC610_OP_ADDR_EN ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) ++ << HINFC610_OP_NF_CS_SHIFT) ++ | ((host->addr_cycle & HINFC610_OP_ADDR_CYCLE_MASK) ++ << HINFC610_OP_ADDR_CYCLE_SHIFT); ++ ++ hinfc_write(host, regval, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_send_cmd_sync_readid(struct hinfc_host *host) ++{ ++ unsigned int regval; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, HINFC610_NANDINFO_LEN, HINFC610_DATA_NUM); ++ hinfc_write(host, NAND_CMD_READID, HINFC610_CMD); ++ hinfc_write(host, 0, HINFC610_ADDRL); ++ ++ /* no need to config HINFC610_OP_WAIT_READY_EN, here not config. */ ++ regval = HINFC610_OP_CMD1_EN ++ | HINFC610_OP_ADDR_EN ++ | HINFC610_OP_READ_DATA_EN ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) ++ << HINFC610_OP_NF_CS_SHIFT) ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT) ++ | HINFC610_OP_READID_EN ++ | HINFC610_OP_RW_REG_EN; ++ ++ hinfc_write(host, regval, HINFC610_OP); ++ ++ host->addr_cycle = 0x0; ++ ++ WAIT_CONTROLLER_FINISH(); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_send_cmd_async_readid(struct hinfc_host *host) ++{ ++ unsigned int regval; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, HINFC610_NANDINFO_LEN, HINFC610_DATA_NUM); ++ hinfc_write(host, NAND_CMD_READID, HINFC610_CMD); ++ hinfc_write(host, 0, HINFC610_ADDRL); ++ ++ /* no need to config HINFC610_OP_WAIT_READY_EN, here not config. */ ++ regval = HINFC610_OP_CMD1_EN ++ | HINFC610_OP_ADDR_EN ++ | HINFC610_OP_READ_DATA_EN ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) ++ << HINFC610_OP_NF_CS_SHIFT) ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT); ++ ++ hinfc_write(host, regval, HINFC610_OP); ++ ++ host->addr_cycle = 0x0; ++ ++ WAIT_CONTROLLER_FINISH(); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_send_cmd_readid(struct hinfc_host *host) ++{ ++ if (HINFC610_IS_SYNC(host)) ++ return hinfc610_send_cmd_sync_readid(host); ++ else ++ return hinfc610_send_cmd_async_readid(host); ++} ++/*****************************************************************************/ ++ ++static int hinfc610_enable_ecc_randomizer(struct hinfc_host *host, int ecc_en, ++ int randomizer_en) ++{ ++ unsigned int nfc_con; ++ ++ if (IS_NAND_RANDOM(host)) { ++ if (randomizer_en) { ++ host->NFC_CON |= HINFC610_CON_RANDOMIZER_EN; ++ host->NFC_CON_ECC_NONE |= HINFC610_CON_RANDOMIZER_EN; ++ } else { ++ host->NFC_CON &= ~HINFC610_CON_RANDOMIZER_EN; ++ host->NFC_CON_ECC_NONE &= ~HINFC610_CON_RANDOMIZER_EN; ++ } ++ } ++ ++ nfc_con = (ecc_en ? host->NFC_CON : host->NFC_CON_ECC_NONE); ++ ++ hinfc_write(host, nfc_con, HINFC610_CON); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_send_cmd_status(struct hinfc_host *host) ++{ ++ unsigned int regval; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, HINFC610_NANDINFO_LEN, HINFC610_DATA_NUM); ++ hinfc_write(host, NAND_CMD_STATUS, HINFC610_CMD); ++ ++ /* no need config HINFC610_OP_WAIT_READY_EN, here not config */ ++ regval = HINFC610_OP_CMD1_EN ++ | HINFC610_OP_READ_DATA_EN ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) ++ << HINFC610_OP_NF_CS_SHIFT); ++ ++ hinfc_write(host, regval, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++static int hinfc610_send_cmd_async_reset(struct hinfc_host *host, ++ int chipselect) ++{ ++ unsigned int regval; ++ ++ hinfc_write(host, NAND_CMD_RESET, HINFC610_CMD); ++ ++ /* need to config HINFC610_OP_WAIT_READY_EN */ ++ regval = HINFC610_OP_CMD1_EN ++ | ((((unsigned int)chipselect & HINFC610_OP_NF_CS_MASK) ++ << HINFC610_OP_NF_CS_SHIFT) ++ | HINFC610_OP_WAIT_READY_EN); ++ ++ hinfc_write(host, regval, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_send_cmd_sync_reset(struct hinfc_host *host, ++ int chipselect) ++{ ++ unsigned int regval; ++ ++ /* ++ * Regarding the ONFI chip sync mode, ++ * NAND_CMD_SYNC_RESET make chip remain sync mode. ++ * But NAND_CMD_RESET will change chip mode to async mode. ++ */ ++ hinfc_write(host, NAND_CMD_SYNC_RESET, HINFC610_CMD); ++ ++ /* need to config HINFC610_OP_WAIT_READY_EN */ ++ regval = HINFC610_OP_CMD1_EN ++ | (((unsigned int)chipselect & HINFC610_OP_NF_CS_MASK) ++ << HINFC610_OP_NF_CS_SHIFT) ++ | HINFC610_OP_WAIT_READY_EN; ++ ++ hinfc_write(host, regval, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_send_cmd_reset(struct hinfc_host *host, int chipselect) ++{ ++ if (HINFC610_IS_SYNC(host)) ++ return hinfc610_send_cmd_sync_reset(host, chipselect); ++ else ++ return hinfc610_send_cmd_async_reset(host, chipselect); ++} ++/*****************************************************************************/ ++ ++int hinfc610_dev_ready(struct mtd_info *mtd) ++{ ++ return 0x1; ++} ++/*****************************************************************************/ ++ ++void hinfc610_select_chip(struct mtd_info *mtd, int chipselect) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hinfc_host *host = chip->priv; ++ ++ if (chipselect < 0) ++ return; ++ ++ if (chipselect > CONFIG_HINFC610_MAX_CHIP) ++ PR_BUG("invalid chipselect: %d\n", chipselect); ++ ++ host->chipselect = chipselect; ++} ++/*****************************************************************************/ ++ ++uint8_t hinfc610_read_byte(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hinfc_host *host = chip->priv; ++ ++ if (host->command == NAND_CMD_STATUS) ++ return readb(chip->IO_ADDR_R); ++ ++ host->offset++; ++ ++ if (host->command == NAND_CMD_READID) ++ return readb(chip->IO_ADDR_R + host->offset - 1); ++ ++ return readb(host->buffer + host->column + host->offset - 1); ++} ++/*****************************************************************************/ ++ ++u16 hinfc610_read_word(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hinfc_host *host = chip->priv; ++ ++ host->offset += 2; ++ return readw(host->buffer + host->column + host->offset - 2); ++} ++/*****************************************************************************/ ++ ++void hinfc610_write_buf(struct mtd_info *mtd, const uint8_t *buf, ++ int len) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hinfc_host *host = chip->priv; ++ ++ memcpy(host->buffer + host->column + host->offset, buf, len); ++ host->offset += len; ++} ++/*****************************************************************************/ ++static void hinfc610_ecc_err_num_count(struct mtd_info *mtd, ++ uint8_t ecc_st, int reg) ++{ ++ u_char err_num; ++ ++ if (ecc_st > 4) ++ ecc_st = 4; ++ ++ while (ecc_st) { ++ err_num = GET_ECC_ERR_NUM(--ecc_st, reg); ++ if (err_num == 0xff) ++ mtd->ecc_stats.failed++; ++ else ++ mtd->ecc_stats.corrected += err_num; ++ } ++} ++ ++/*****************************************************************************/ ++ ++void hinfc610_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hinfc_host *host = chip->priv; ++ int reg; ++ uint8_t ecc_step = host->pagesize >> 10; ++ ++ memcpy(buf, host->buffer + host->column + host->offset, len); ++ host->offset += len; ++ ++ /* 2K or 4K or 8K(1) or 16K(1-1) pagesize */ ++ reg = hinfc_read(host, HINFC_ECC_ERR_NUM0_BUF0); ++ hinfc610_ecc_err_num_count(mtd, ecc_step, reg); ++ ++ if (ecc_step > 4) { ++ /* 8K(2) or 16K(1-2) pagesize */ ++ reg = hinfc_read(host, HINFC_ECC_ERR_NUM1_BUF0); ++ hinfc610_ecc_err_num_count(mtd, ecc_step, reg); ++ if (ecc_step > 8) { ++ /* 16K(2-1) pagesize */ ++ reg = hinfc_read(host, HINFC_ECC_ERR_NUM0_BUF1); ++ hinfc610_ecc_err_num_count(mtd, ecc_step, reg); ++ /* 16K(2-2) pagesize */ ++ reg = hinfc_read(host, HINFC_ECC_ERR_NUM1_BUF1); ++ hinfc610_ecc_err_num_count(mtd, ecc_step, reg); ++ } ++ } ++} ++/*****************************************************************************/ ++/* ++ * 'host->epm' only use the first oobfree[0] field, it looks very simple, But... ++ */ ++ ++/* Default OOB area layout */ ++static int hinfc_ooblayout_ecc_64(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->length = 32; ++ oobregion->offset = 32; ++ ++ return 0; ++} ++ ++static int hinfc_ooblayout_free_64(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->length = 30; ++ oobregion->offset = 2; ++ ++ return 0; ++} ++ ++static struct mtd_ooblayout_ops hinfc_ooblayout_64_ops = { ++ .ecc = hinfc_ooblayout_ecc_64, ++ .free = hinfc_ooblayout_free_64, ++}; ++ ++/*****************************************************************************/ ++ ++static struct nand_config_info hinfc610_soft_auto_config_table[] = { ++ {NAND_PAGE_16K, NAND_ECC_64BIT, 60, 1824/*1824*/, &hinfc_ooblayout_64_ops}, ++ {NAND_PAGE_16K, NAND_ECC_40BIT, 40, 1200/*1152*/, &hinfc_ooblayout_64_ops}, ++ {NAND_PAGE_16K, NAND_ECC_NONE, 0, 32, &hinfc_ooblayout_64_ops}, ++ ++ {NAND_PAGE_8K, NAND_ECC_64BIT, 60, 928 /*928*/, &hinfc_ooblayout_64_ops}, ++ {NAND_PAGE_8K, NAND_ECC_40BIT, 40, 600 /*592*/, &hinfc_ooblayout_64_ops}, ++ {NAND_PAGE_8K, NAND_ECC_24BIT, 24, 368 /*368*/, &hinfc_ooblayout_64_ops}, ++ {NAND_PAGE_8K, NAND_ECC_NONE, 0, 32, &hinfc_ooblayout_64_ops}, ++ ++ {NAND_PAGE_4K, NAND_ECC_24BIT, 24, 200 /*200*/, &hinfc_ooblayout_64_ops}, ++ {NAND_PAGE_4K, NAND_ECC_4BIT_512, 8, 128 /*88*/, &hinfc_ooblayout_64_ops}, ++ {NAND_PAGE_4K, NAND_ECC_NONE, 0, 32, &hinfc_ooblayout_64_ops}, ++ ++ {NAND_PAGE_2K, NAND_ECC_24BIT, 24, 128 /*116*/, &hinfc_ooblayout_64_ops}, ++ {NAND_PAGE_2K, NAND_ECC_4BIT_512, 8, 64 /*60*/, &hinfc_ooblayout_64_ops}, ++ {NAND_PAGE_2K, NAND_ECC_NONE, 0, 32, &hinfc_ooblayout_64_ops}, ++ ++ {0, 0, 0, 0, NULL}, ++}; ++/*****************************************************************************/ ++/* used the best correct arithmetic. */ ++struct nand_config_info *hinfc610_get_best_ecc(struct mtd_info *mtd) ++{ ++ struct nand_config_info *best = NULL; ++ struct nand_config_info *config = hinfc610_soft_auto_config_table; ++ ++ for (; config->ooblayout_ops; config++) { ++ if (nandpage_type2size(config->pagetype) != mtd->writesize) ++ continue; ++ ++ if (mtd->oobsize < config->oobsize) ++ continue; ++ ++ if (!best || (best->ecctype < config->ecctype)) ++ best = config; ++ } ++ ++ if (!best) ++ PR_BUG(ERSTR_DRIVER ++ "Driver does not support the pagesize(%d) " ++ "and oobsize(%d).\n", ++ mtd->writesize, mtd->oobsize); ++ ++ return best; ++} ++/*****************************************************************************/ ++/* force the pagesize and ecctype */ ++struct nand_config_info *hinfc610_force_ecc(struct mtd_info *mtd, int pagetype, ++ int oobsize, char *cfgmsg, ++ int allow_pagediv) ++{ ++ struct nand_config_info *fit = NULL; ++ struct nand_config_info *config = hinfc610_soft_auto_config_table; ++ ++ for (; config->ooblayout_ops; config++) { ++ if (config->pagetype == pagetype ++ && config->oobsize <= oobsize) { ++ fit = config; ++ break; ++ } ++ } ++ ++ if (!fit) { ++ PR_BUG(ERSTR_DRIVER ++ "Driver(%s mode) does not support this Nand Flash " ++ "pagesize:%s, oobsize:%d\n", ++ cfgmsg, ++ nand_page_name(pagetype), ++ oobsize); ++ return NULL; ++ } ++ return fit; ++} ++/*****************************************************************************/ ++static unsigned int nand_otp_len; ++static unsigned char nand_otp[128] = {0}; ++ ++/* Get NAND parameter table. */ ++static int __init parse_nand_param(const struct tag *tag) ++{ ++ if (tag->hdr.size <= 2) ++ return 0; ++ ++ nand_otp_len = ((tag->hdr.size << 2) - sizeof(struct tag_header)); ++ ++ if (nand_otp_len > sizeof(nand_otp)) { ++ pr_warn("%s(%d): Get Nand OTP from tag fail.\n", ++ __func__, __LINE__); ++ return 0; ++ } ++ memcpy(nand_otp, &tag->u, nand_otp_len); ++ return 0; ++} ++/* 0x48694E77 equal to fastoot ATAG_NAND_PARAM */ ++__tagtable(0x48694E77, parse_nand_param); ++ ++/*****************************************************************************/ ++int hinfc610_ecc_type2reg_intf(int type, struct hinfc_host *host) ++{ ++ if (HINFC_VER_620 == host->version) ++ return hinfc620_ecc_type2reg(type); ++ else ++ return hinfc610_ecc_type2reg(type); ++} ++/*****************************************************************************/ ++int hinfc610_ecc_reg2type_intf(int reg, struct hinfc_host *host) ++{ ++ if (HINFC_VER_620 == host->version) ++ return hinfc620_ecc_reg2type(reg); ++ else ++ return hinfc610_ecc_reg2type(reg); ++} ++ ++/*****************************************************************************/ ++static int hinfc610_param_adjust(struct mtd_info *mtd, struct nand_chip *chip, ++ struct nand_dev_t *nand_dev) ++{ ++ int pagetype; ++ int oobsize; ++ int regval; ++ char *start_type = "unknown"; ++ struct nand_config_info *best = NULL; ++ struct hinfc_host *host = chip->priv; ++ struct mtd_oob_region *hinfc_oobregion; ++ ++ hinfc_oobregion = kmalloc(sizeof(struct mtd_oob_region), GFP_KERNEL); ++ if (!hinfc_oobregion) { ++ PR_BUG("failed to allocate hinfc_oobregion structure.\n"); ++ return -ENOMEM; ++ } ++ ++ if (IS_NANDC_HW_AUTO(host)) ++ start_type = "HW-Auto"; ++ else ++ start_type = "HW-Reg"; ++ ++ if ((mtd->writesize == SZ_8K) ++ || (mtd->writesize == SZ_16K) ++ || (mtd->writesize == SZ_32K)) ++ host->flags |= NAND_RANDOMIZER; ++ ++ pagetype = nandpage_size2type(mtd->writesize); ++ oobsize = mtd->oobsize; ++ ++ best = hinfc610_force_ecc(mtd, pagetype, oobsize, ++ start_type, 0); ++ ++#ifdef CONFIG_HINFC610_PAGESIZE_AUTO_ECC_NONE ++# ifdef CONFIG_HINFC610_AUTO_PAGESIZE_ECC ++# error you SHOULD NOT define CONFIG_HINFC610_PAGESIZE_AUTO_ECC_NONE \ ++ and CONFIG_HINFC610_AUTO_PAGESIZE_ECC at the same time ++# endif ++# ifdef CONFIG_HINFC610_HARDWARE_PAGESIZE_ECC ++# error you SHOULD NOT define CONFIG_HINFC610_PAGESIZE_AUTO_ECC_NONE \ ++ and CONFIG_HINFC610_HARDWARE_PAGESIZE_ECC at the same time ++# endif ++ ++ pagetype = nandpage_size2type(mtd->writesize); ++ oobsize = 32; ++ best = hinfc610_force_ecc(mtd, pagetype, oobsize, ++ "force config", 0); ++ start_type = "AutoForce"; ++ ++#endif /* CONFIG_HINFC610_PAGESIZE_AUTO_ECC_NONE */ ++ ++ if (!best) { ++ kfree(hinfc_oobregion); ++ PR_BUG(ERSTR_HARDWARE ++ "Please configure Nand Flash pagesize and ecctype!\n"); ++ return -1; ++ } ++ ++ /* only in case fastboot check randomizer failed. ++ * Update fastboot or configure hardware randomizer pin ++ * fix this problem. ++ */ ++ if (IS_NAND_RANDOM(nand_dev) && !(IS_NAND_RANDOM(host))) ++ PR_BUG(ERSTR_HARDWARE ++ "Hardware is not configure randomizer, " ++ "but it is more suitable for this Nand Flash. " ++ "1. Please configure hardware randomizer PIN." ++ "2. Please updata fastboot.\n"); ++ ++ host->flags |= (IS_NAND_RANDOM(nand_dev) | ++ IS_NAND_SYNC_ASYNC(nand_dev) | ++ IS_NAND_ONLY_SYNC(nand_dev) | ++ IS_NAND_ONFI(nand_dev)); ++ ++ /* only for print nand info. */ ++ nand_dev->flags |= (IS_NANDC_HW_AUTO(host) | ++ IS_NANDC_SYNC_BOOT(host)); ++ ++ /* only in case fastboot check sync boot pin failed. ++ * Update fastboot or configure hardware sync boot pin fix this problem. ++ */ ++ if (IS_NANDC_SYNC_BOOT(host)) { ++ /* But NAND do not support sync mode, warning ! */ ++ if (!IS_NAND_ONLY_SYNC(nand_dev)) ++ PR_BUG(ERSTR_HARDWARE ++ "Hardware SYNC BOOT PIN has configured sync mode, " ++ "but the Nand Flash is async mode.\n" ++ "1. DO NOT configure SYNC BOOT PIN. " ++ "2. Update fastboot.\n"); ++ } else { ++ if (IS_NAND_ONLY_SYNC(nand_dev)) ++ PR_BUG(ERSTR_HARDWARE ++ "Hardware SYNC BOOT PIN has configured async mode, " ++ "but the Nand Flash only support sync mode.\n" ++ "1. Please configure SYNC BOOT PIN." ++ "2. Update fastboot.\n"); ++ } ++ ++ if (IS_NAND_SYNC_ASYNC(nand_dev)) ++ hinfc610_get_sync_info(host); ++ ++ if (best->ecctype != NAND_ECC_NONE) ++ mtd->oobsize = best->oobsize; ++ ++ if (best->ooblayout_ops->free) ++ best->ooblayout_ops->free(mtd, 0, hinfc_oobregion); ++ ++ host->ecctype = best->ecctype; ++ host->pagesize = nandpage_type2size(best->pagetype); ++ host->oobsize = mtd->oobsize; ++ host->block_page_mask = ((mtd->erasesize / mtd->writesize) - 1); ++ ++ host->buffer = dma_alloc_coherent(host->dev, ++ (host->pagesize + host->oobsize), ++ &host->dma_buffer, GFP_KERNEL); ++ if (!host->buffer) { ++ kfree(hinfc_oobregion); ++ PR_BUG("Can't malloc memory for NAND driver."); ++ return -EIO; ++ } ++ memset(host->buffer, 0xff, (host->pagesize + host->oobsize)); ++ ++ host->dma_oob = host->dma_buffer + host->pagesize; ++ host->bbm = (unsigned char *)(host->buffer ++ + host->pagesize + HINFC_BAD_BLOCK_POS); ++ ++ host->epm = (unsigned short *)(host->buffer ++ + host->pagesize + hinfc_oobregion->offset + 28); ++ ++ regval = ~(HINFC610_CON_PAGESIZE_MASK << HINFC610_CON_PAGEISZE_SHIFT); ++ host->NFC_CON &= regval; ++ host->NFC_CON_ECC_NONE &= regval; ++ regval = (hinfc610_page_type2reg(best->pagetype) ++ & HINFC610_CON_PAGESIZE_MASK) << HINFC610_CON_PAGEISZE_SHIFT; ++ host->NFC_CON |= regval; ++ host->NFC_CON_ECC_NONE |= regval; ++ ++ regval = ~(HINFC610_CON_ECCTYPE_MASK << HINFC610_CON_ECCTYPE_SHIFT); ++ host->NFC_CON &= regval; ++ host->NFC_CON_ECC_NONE &= regval; ++ regval = (hinfc610_ecc_type2reg_intf(best->ecctype, host) ++ & HINFC610_CON_ECCTYPE_MASK) << HINFC610_CON_ECCTYPE_SHIFT; ++ host->NFC_CON |= regval; ++ ++ if (mtd->writesize > NAND_MAX_PAGESIZE || ++ mtd->oobsize > NAND_MAX_OOBSIZE) { ++ PR_BUG(ERSTR_DRIVER ++ "Driver does not support this Nand Flash. " ++ "Please increase NAND_MAX_PAGESIZE and NAND_MAX_OOBSIZE.\n"); ++ } ++ ++ if (mtd->writesize != host->pagesize) { ++ unsigned int shift = 0; ++ unsigned int writesize = mtd->writesize; ++ ++ while (writesize > host->pagesize) { ++ writesize >>= 1; ++ shift++; ++ } ++ chip->chipsize = chip->chipsize >> shift; ++ mtd->erasesize = mtd->erasesize >> shift; ++ mtd->writesize = host->pagesize; ++ PR_MSG("Nand divide into 1/%u\n", (1 << shift)); ++ } ++ ++ nand_dev->start_type = start_type; ++ nand_dev->ecctype = host->ecctype; ++ nand_dev->oobsize = mtd->oobsize; ++ ++ host->read_retry = NULL; ++ if (nand_dev->read_retry_type != NAND_RR_NONE) { ++ host->read_retry ++ = hinfc610_find_read_retry(nand_dev->read_retry_type); ++ if (!host->read_retry) { ++ PR_BUG(ERSTR_DRIVER ++ "This Nand Flash need to enable the " ++ "'read retry' feature. " ++ "but the driver dose not offer the feature"); ++ } ++ ++ if (nand_otp_len) ++ memcpy(host->rr_data, nand_otp, nand_otp_len); ++ } ++ ++ /* ++ * If it want to support the 'read retry' feature, the 'randomizer' ++ * feature must be support first. ++ */ ++ if (host->read_retry && !IS_NAND_RANDOM(host)) { ++ PR_BUG(ERSTR_HARDWARE ++ "This Nand flash need to enable 'randomizer' feature. " ++ "Please configure hardware randomizer PIN."); ++ } ++ ++ ++ mtd_set_ooblayout(mtd, &hinfc_ooblayout_64_ops); ++ hinfc610_dbg_init(host); ++ ++ kfree(hinfc_oobregion); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++int hinfc610_nand_init(struct hinfc_host *host, struct nand_chip *chip) ++{ ++ unsigned int regval; ++ ++ host->version = hinfc_read(host, HINFC610_VERSION); ++ ++ host->addr_cycle = 0; ++ host->addr_value[0] = 0; ++ host->addr_value[1] = 0; ++ host->cache_addr_value[0] = ~0; ++ host->cache_addr_value[1] = ~0; ++ host->chipselect = 0; ++ ++ host->send_cmd_pageprog = hinfc610_send_cmd_pageprog; ++ host->send_cmd_readstart = hinfc610_send_cmd_readstart; ++ host->send_cmd_erase = hinfc610_send_cmd_erase; ++ host->send_cmd_readid = hinfc610_send_cmd_readid; ++ host->send_cmd_status = hinfc610_send_cmd_status; ++ host->send_cmd_reset = hinfc610_send_cmd_reset; ++ ++ host->flags = 0; ++ ++ regval = hinfc_read(host, HINFC610_CON); ++ ++ host->NFC_CON = (regval ++ | HINFC610_CON_OP_MODE_NORMAL ++ | HINFC610_CON_READY_BUSY_SEL); ++ ++ host->NFC_CON_ECC_NONE = host->NFC_CON ++ & (~(HINFC610_CON_ECCTYPE_MASK ++ << HINFC610_CON_ECCTYPE_SHIFT)) ++ & (~HINFC610_CON_RANDOMIZER_EN); ++ ++ hinfc_write(host, ++ (SET_HINFC610_PWIDTH(CONFIG_HINFC610_W_LATCH, ++ CONFIG_HINFC610_R_LATCH, ++ CONFIG_HINFC610_RW_LATCH)), ++ HINFC610_PWIDTH); ++ ++ host->flags |= NANDC_HW_AUTO; ++ ++ /* check if chip is sync mode. */ ++ if (regval & HINFC610_BOOT_CFG_SYC_NAND_PAD) { ++ host->flags |= NANDC_IS_SYNC_BOOT; ++ ++ /* ++ * NAND default is sync mode, and read id, reset in sync mode. ++ */ ++ host->NFC_CON |= HINFC610_CON_NF_MODE_TOGGLE; ++ host->NFC_CON_ECC_NONE |= HINFC610_CON_NF_MODE_TOGGLE; ++ ++ /* set synchronous clock and timing. */ ++ clk_prepare_enable(host->clk); ++ } ++ ++ memset((char *)chip->IO_ADDR_R, ++ 0xff, HINFC610_BUFFER_BASE_ADDRESS_LEN); ++ ++ host->enable_ecc_randomizer = hinfc610_enable_ecc_randomizer; ++ hinfc_param_adjust = hinfc610_param_adjust; ++ ++ return 0; ++} +diff --git a/drivers/mtd/nand/hinfc610/hinfc610.h b/drivers/mtd/nand/hinfc610/hinfc610.h +new file mode 100644 +index 0000000..18d90fd +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610.h +@@ -0,0 +1,512 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef HINFCV610H ++#define HINFCV610H ++/******************************************************************************/ ++ ++#ifndef CONFIG_HINFC610_W_LATCH ++ #define CONFIG_HINFC610_W_LATCH (5) ++#endif /* CONFIG_HINFC610_W_LATCH */ ++ ++#ifndef CONFIG_HINFC610_R_LATCH ++ #define CONFIG_HINFC610_R_LATCH (7) ++#endif /* CONFIG_HINFC610_R_LATCH */ ++ ++#ifndef CONFIG_HINFC610_RW_LATCH ++ #define CONFIG_HINFC610_RW_LATCH (3) ++#endif /* CONFIG_HINFC610_RW_LATCH */ ++ ++#ifndef CONFIG_HINFC610_MAX_CHIP ++ #define CONFIG_HINFC610_MAX_CHIP (1) ++ #warning NOT config CONFIG_HINFC610_MAX_CHIP, \ ++ used default value, maybe invalid. ++#endif /* CONFIG_HINFC610_MAX_CHIP */ ++/*****************************************************************************/ ++#define HINFC_ECC_ERR_NUM0_BUF0 0xa0 ++#define HINFC_ECC_ERR_NUM1_BUF0 0xa4 ++#define HINFC_ECC_ERR_NUM0_BUF1 0xa8 ++#define HINFC_ECC_ERR_NUM1_BUF1 0xcc ++ ++#define GET_ECC_ERR_NUM(_i, _reg) (((_reg) >> ((_i) * 8)) & 0xff) ++ ++/*****************************************************************************/ ++#define HINFC610_REG_BASE_ADDRESS_LEN (0x100) ++#define HINFC610_BUFFER_BASE_ADDRESS_LEN (2048 + 128) ++ ++#define HINFC610_CHIP_DELAY (25) ++ ++#define HINFC610_ADDR_CYCLE_MASK 0x4 ++#define HINFC610_DMA_ADDR_OFFSET 4096 ++/*****************************************************************************/ ++#define HINFC610_CON 0x00 ++#define HINFC610_CON_OP_MODE_NORMAL (1U << 0) ++#define HINFC610_CON_PAGEISZE_SHIFT (1) ++#define HINFC610_CON_PAGESIZE_MASK (0x07) ++#define HINFC610_CON_BUS_WIDTH (1U << 4) ++#define HINFC610_CON_READY_BUSY_SEL (1U << 8) ++#define HINFC610_CON_ECCTYPE_SHIFT (9) ++#define HINFC610_CON_ECCTYPE_MASK (0x0f) ++#define HINFC610_CON_RANDOMIZER_EN (1 << 14) ++#define HINFC610_CON_NF_MODE_SHIFT 15 ++#define HINFC610_CON_NF_MODE_MASK (3 << HINFC610_CON_NF_MODE_SHIFT) ++#define HINFC610_CON_NF_MODE_TOGGLE (1 << HINFC610_CON_NF_MODE_SHIFT) ++#define HINFC610_CON_NF_MODE_ONFI_23 (2 << HINFC610_CON_NF_MODE_SHIFT) ++#define HINFC610_CON_NF_MODE_ONFI_30 (3 << HINFC610_CON_NF_MODE_SHIFT) ++ ++#define HINFC610_PWIDTH 0x04 ++#define SET_HINFC610_PWIDTH(_w_lcnt, _r_lcnt, _rw_hcnt) \ ++ ((_w_lcnt) | (((_r_lcnt) & 0x0F) << 4) | (((_rw_hcnt) & 0x0F) << 8)) ++ ++#define HINFC610_CMD 0x0C ++#define HINFC610_ADDRL 0x10 ++#define HINFC610_ADDRH 0x14 ++#define HINFC610_DATA_NUM 0x18 ++ ++#define HINFC610_OP 0x1C ++#define HINFC610_OP_READ_STATUS_EN (1U << 0) ++#define HINFC610_OP_READ_DATA_EN (1U << 1) ++#define HINFC610_OP_WAIT_READY_EN (1U << 2) ++#define HINFC610_OP_CMD2_EN (1U << 3) ++#define HINFC610_OP_WRITE_DATA_EN (1U << 4) ++#define HINFC610_OP_ADDR_EN (1U << 5) ++#define HINFC610_OP_CMD1_EN (1U << 6) ++#define HINFC610_OP_NF_CS_SHIFT (7) ++#define HINFC610_OP_NF_CS_MASK (3) ++#define HINFC610_OP_ADDR_CYCLE_SHIFT (9) ++#define HINFC610_OP_ADDR_CYCLE_MASK (7) ++#define HINFC610_OP_READID_EN (1U << 12) ++#define HINFC610_OP_RW_REG_EN (1U << 13) ++ ++#define HINFC610_STATUS 0x20 ++ ++#define HINFC610_INTS 0x28 ++#define HINFC610_INTS_UE (1U << 6) ++#define HINFC610_INTCLR 0x2C ++#define HINFC610_INTCLR_UE (1U << 6) ++#define HINFC610_INTCLR_CE (1U << 5) ++ ++#define HINFC610_DMA_CTRL 0x60 ++#define HINFC610_DMA_CTRL_DMA_START (1U << 0) ++#define HINFC610_DMA_CTRL_WE (1U << 1) ++#define HINFC610_DMA_CTRL_BURST4_EN (1U << 4) ++#define HINFC610_DMA_CTRL_BURST8_EN (1U << 5) ++#define HINFC610_DMA_CTRL_BURST16_EN (1U << 6) ++#define HINFC610_DMA_CTRL_ADDR_NUM_SHIFT (7) ++#define HINFC610_DMA_CTRL_ADDR_NUM_MASK (1) ++#define HINFC610_DMA_CTRL_CS_SHIFT (8) ++#define HINFC610_DMA_CTRL_CS_MASK (0x03) ++ ++#define HINFC610_DMA_ADDR_DATA 0x64 ++#define HINFC610_DMA_ADDR_OOB 0x68 ++#define HINFC610_DMA_ADDR_DATA1 0xB4 ++#define HINFC610_DMA_ADDR_DATA2 0xB8 ++#define HINFC610_DMA_ADDR_DATA3 0xBC ++#define HINFC610_DMA_ADDR_DATA4 0xEC ++#define HINFC610_DMA_ADDR_DATA5 0xF0 ++#define HINFC610_DMA_ADDR_DATA6 0xF4 ++#define HINFC610_DMA_ADDR_DATA7 0xF8 ++ ++#define HINFC610_DMA_LEN 0x6C ++#define HINFC610_DMA_LEN_OOB_SHIFT (16) ++#define HINFC610_DMA_LEN_OOB_MASK (0x1FFF) ++ ++#define HINFC610_DMA_PARA 0x70 ++#define HINFC610_DMA_PARA_DATA_RW_EN (1U << 0) ++#define HINFC610_DMA_PARA_OOB_RW_EN (1U << 1) ++#define HINFC610_DMA_PARA_DATA_EDC_EN (1U << 2) ++#define HINFC610_DMA_PARA_OOB_EDC_EN (1U << 3) ++#define HINFC610_DMA_PARA_EXT_LEN_SHIFT (6) ++#define HINFC610_DMA_PARA_EXT_LEN_MASK (0x03) ++ ++#define HINFC610_VERSION 0x74 ++#define HINFC610_LOG_READ_ADDR 0x7C ++#define HINFC610_LOG_READ_LEN 0x80 ++ ++#define HINFC610_ECC_REG0 0xA0 ++#define HINFC610_ECC_REG1 0xA4 ++#define HINFC610_ECC_REG2 0xA8 ++#define HINFC610_ECC_REG3 0xAC ++ ++#define HINFC610_RANDOMIZER 0xC0 ++#define HINFC610_RANDOMIZER_PAD 0x02 ++#define HINFC610_RANDOMIZER_ENABLE 0x01 ++/* read nand id or nand status, return from nand data length */ ++#define HINFC610_NANDINFO_LEN 0x10 ++ ++#define HINFC610_BOOT_CFG 0xC4 ++#define HINFC610_BOOT_CFG_RANDOMIZER_PAD 0x01 ++#define HINFC610_BOOT_CFG_SAVE_PIN_MODE_SHIFT 13 ++#define HINFC610_BOOT_CFG_SAVE_PIN_MODE \ ++ (1U << HINFC610_BOOT_CFG_SAVE_PIN_MODE_SHIFT) ++#define HINFC610_BOOT_CFG_SYC_NAND_PAD_SHIFT 12 ++#define HINFC610_BOOT_CFG_SYC_NAND_PAD \ ++ (1U << HINFC610_BOOT_CFG_SYC_NAND_PAD_SHIFT) ++ ++#define HINFC610_SYNC_TIMING 0xD0 ++ ++/* ONFI: sync nand timing config */ ++#define HINFC610_SYNC_ONFI_T_CAD (0xF << 24) ++#define HINFC610_SYNC_ONFI_T_DQZ (0xF << 20) ++ ++/* TOGGLE: sync nand timing config */ ++#define HINFC610_SYNC_TOGGLE_PRE_RDQS (0xF << 16) ++#define HINFC610_SYNC_TOGGLE_POST_RDQS (0xF << 12) ++#define HINFC610_SYNC_TOGGLE_PRE_WDQS (0xF << 8) ++#define HINFC610_SYNC_TOGGLE_POST_WDQS (0xF << 4) ++#define HINFC610_SYNC_TOGGLE_RW_PSTH (0xF << 0) ++ ++/*****************************************************************************/ ++/* ++ * This constant declares the max. oobsize / page, which ++ * is supported now. If you add a chip with bigger oobsize/page ++ * adjust this accordingly. ++ */ ++#define NAND_MAX_OOBSIZE 4800 ++#define NAND_MAX_PAGESIZE 32768 ++ ++/* DMA address align with 32 bytes. */ ++#define HINFC610_DMA_ALIGN 64 ++/*****************************************************************************/ ++#include "../hinfc_gen.h" ++ ++#undef READ ++#define READ 1 ++ ++#undef WRITE ++#define WRITE 0 ++ ++#undef FALSE ++#define FALSE 0 ++ ++#undef TRUE ++#define TRUE 1 ++ ++#undef ENABLE ++#define ENABLE 1 ++ ++#undef DISABLE ++#define DISABLE 0 ++/*****************************************************************************/ ++ ++struct hinfc_host { ++ struct nand_chip *chip; ++ struct mtd_info *mtd; ++ void __iomem *iobase; ++ struct device *dev; ++ ++ unsigned int offset; ++ unsigned int command; ++ ++ int chipselect; ++ ++ unsigned int n24bit_ext_len; ++ int ecctype; ++ ++/* Current system has already gone to sync mode */ ++#define HINFC610_IS_SYNC(_host) ((_host)->NFC_CON & HINFC610_CON_NF_MODE_MASK) ++ unsigned long NFC_CON; ++ unsigned long NFC_CON_ECC_NONE; ++ ++ unsigned int addr_cycle; ++ unsigned int addr_value[2]; ++ unsigned int cache_addr_value[2]; ++ unsigned int column; ++ unsigned int block_page_mask; ++ ++ unsigned int dma_oob; ++ unsigned int dma_buffer; ++ unsigned int pagesize; ++ unsigned int oobsize; ++ /* This is maybe an un-aligment address, only for malloc or free */ ++ char *buforg; ++ char *buffer; ++ ++ int need_rr_data; ++#define HINFC_READ_RETRY_DATA_LEN 128 ++ char rr_data[HINFC_READ_RETRY_DATA_LEN]; ++ int version; ++ int add_partition; ++ ++ /* BOOTROM read two bytes to detect the bad block flag */ ++#define HINFC_BAD_BLOCK_POS 0 ++ unsigned char *bbm; /* nand bad block mark */ ++ unsigned short *epm; /* nand empty page mark */ ++ unsigned int flags; ++ ++#define HINFC610_PS_UC_ECC 0x01 /* page has ecc error */ ++#define HINFC610_PS_BAD_BLOCK 0x02 /* bad block */ ++#define HINFC610_PS_EMPTY_PAGE 0x04 /* page is empty */ ++#define HINFC610_PS_EPM_ERROR 0x0100 /* empty page mark word has ecc error*/ ++#define HINFC610_PS_BBM_ERROR 0x0200 /* bad block mark word has ecc error*/ ++ unsigned int page_status; ++ ++ struct clk *clk; ++ ++ int (*send_cmd_pageprog)(struct hinfc_host *host); ++ int (*send_cmd_status)(struct hinfc_host *host); ++ int (*send_cmd_readstart)(struct hinfc_host *host); ++ int (*send_cmd_erase)(struct hinfc_host *host); ++ int (*send_cmd_readid)(struct hinfc_host *host); ++ int (*send_cmd_reset)(struct hinfc_host *host, int chipselect); ++ int (*enable)(struct hinfc_host *host, int enable); ++ ++ int (*enable_ecc_randomizer)(struct hinfc_host *host, ++ int ecc_en, int randomizer_en); ++ ++ struct read_retry_t *read_retry; ++ struct nand_sync *sync; ++}; ++ ++#define HINFC610_UC_ECC 0x01 ++#define HINFC610_BAD_BLOCK 0x02 ++#define HINFC610_EMPTY_PAGE 0x04 ++ ++#define IS_PS_EMPTY_PAGE(_host) ((_host)->page_status & HINFC610_PS_EMPTY_PAGE) ++#define IS_PS_BAD_BLOCK(_host) ((_host)->page_status & HINFC610_PS_BAD_BLOCK) ++#define IS_PS_UN_ECC(_host) ((_host)->page_status & HINFC610_PS_UC_ECC) ++#define IS_PS_EPM_ERR(_host) ((_host)->page_status & HINFC610_PS_EPM_ERROR) ++#define IS_PS_BBM_ERR(_host) ((_host)->page_status & HINFC610_PS_BBM_ERROR) ++ ++/*****************************************************************************/ ++ ++#define HINFC610_READ_1CMD_0ADD_NODATA \ ++ (HINFC610_OP_CMD1_EN \ ++ | ((host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT)) ++ ++#define HINFC610_READ_1CMD_1ADD_DATA \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_READ_DATA_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_READ_1CMD_1ADD_DATA_WAIT_READY \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_READ_DATA_EN \ ++ | HINFC610_OP_WAIT_READY_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_READ_1CMD_1ADD_DATA_SYNC \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_READ_DATA_EN \ ++ | HINFC610_OP_WAIT_READY_EN \ ++ | HINFC610_OP_RW_REG_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_READ_2CMD_5ADD \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_CMD2_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_READ_DATA_EN \ ++ | HINFC610_OP_WAIT_READY_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (5 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_0CMD_1ADD_DATA \ ++ (HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_0CMD_1ADD_DATA_WAIT_READY \ ++ (HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | HINFC610_OP_WAIT_READY_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_0CMD_1ADD_DATA_SYNC \ ++ (HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | HINFC610_OP_RW_REG_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_0CMD_1ADD_DATA_SYNC_WAIT_READY \ ++ (HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | HINFC610_OP_RW_REG_EN \ ++ | HINFC610_OP_WAIT_READY_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_1CMD_1ADD_DATA \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_1CMD_1ADD_DATA_WAIT_READY \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | HINFC610_OP_WAIT_READY_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_1CMD_1ADD_DATA_SYNC \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | HINFC610_OP_RW_REG_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_1CMD_1ADD_DATA_SYNC_WAIT_READY \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | HINFC610_OP_WAIT_READY_EN \ ++ | HINFC610_OP_RW_REG_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_1CMD_2ADD_DATA \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (2 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_1CMD_2ADD_DATA_SYNC \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | HINFC610_OP_RW_REG_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (2 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_2CMD_0ADD_NODATA \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_CMD2_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT)) ++ ++#define HINFC610_WRITE_2CMD_0ADD_NODATA_SYNC \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_CMD2_EN \ ++ | HINFC610_OP_RW_REG_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT)) ++ ++#define HINFC610_WRITE_1CMD_0ADD_NODATA \ ++ (HINFC610_OP_CMD1_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT)) ++ ++#define HINFC610_WRITE_1CMD_0ADD_NODATA_WAIT_READY \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_WAIT_READY_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT)) ++ ++/*****************************************************************************/ ++ ++#define WAIT_CONTROLLER_FINISH() \ ++do { \ ++ unsigned int timeout = 0x800000; \ ++ while ((hinfc_read(host, HINFC610_STATUS) & 0x1) == 0x0 && timeout) \ ++ timeout--; \ ++ if (!timeout) \ ++ PR_ERR("Wait NAND controller finish timeout.\n"); \ ++} while (0) ++ ++/*****************************************************************************/ ++ ++#define hinfc_read(_host, _reg) \ ++ readl((char *)_host->iobase + (_reg)) ++ ++#define hinfc_write(_host, _value, _reg) \ ++ writel((_value), (char *)_host->iobase + (_reg)) ++ ++#define HINFC_CMD_SEQ(_cmd0, _cmd1) \ ++ (((_cmd0) & 0xFF) | ((_cmd1) & 0xFF) << 8) ++/*****************************************************************************/ ++ ++#define GET_PAGE_INDEX(host) \ ++ ((host->addr_value[0] >> 16) | (host->addr_value[1] << 16)) ++ ++/*****************************************************************************/ ++ ++void hinfc610_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl); ++int hinfc610_dev_ready(struct mtd_info *mtd); ++void hinfc610_select_chip(struct mtd_info *mtd, int chipselect); ++uint8_t hinfc610_read_byte(struct mtd_info *mtd); ++u16 hinfc610_read_word(struct mtd_info *mtd); ++void hinfc610_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len); ++void hinfc610_read_buf(struct mtd_info *mtd, uint8_t *buf, int len); ++int hinfc610_nand_init(struct hinfc_host *host, struct nand_chip *chip); ++/******************************************************************************/ ++ ++extern struct nand_sync hinfc610_sync_onfi_23; ++extern struct nand_sync hinfc610_sync_onfi_30; ++extern struct nand_sync hinfc610_sync_toggle_10; ++extern struct read_retry_t hinfc610_hynix_bg_cdie_read_retry; ++extern struct read_retry_t hinfc610_hynix_bg_bdie_read_retry; ++extern struct read_retry_t hinfc610_hynix_cg_adie_read_retry; ++extern struct read_retry_t hinfc610_micron_read_retry; ++extern struct read_retry_t hinfc610_toshiba_24nm_read_retry; ++extern struct read_retry_t hinfc610_samsung_read_retry; ++ ++#if 0 ++#ifdef CONFIG_MTD_PART_CHANGE ++extern int register_mtd_partdev(struct mtd_info *mtd); ++extern int unregister_mtd_partdev(struct mtd_info *mtd); ++#else ++int register_mtd_partdev(struct mtd_info *mtd) ++{ ++ return 0; ++}; ++ ++int unregister_mtd_partdev(struct mtd_info *mtd) ++{ ++ return 0; ++}; ++#endif ++ ++void hinfc610_controller_enable(struct hinfc_host *host, int enable); ++#endif ++ ++extern int hinfc610_dbgfs_debug_init(struct hinfc_host *host); ++ ++#ifdef CONFIG_HINFC610_DBG_NAND_DEBUG ++extern struct hinfc610_dbg_inf_t *hinfc610_dbg_inf[]; ++#endif ++ ++#endif /* HINFCV610H */ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_dbg.c b/drivers/mtd/nand/hinfc610/hinfc610_dbg.c +new file mode 100644 +index 0000000..ee25956 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_dbg.c +@@ -0,0 +1,294 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++#include "hinfc610_dbg.h" ++ ++struct hinfc610_dbg_inf_t *hinfc610_dbg_inf[] = { ++ &hinfc610_dbg_inf_ecc_notice, ++ &hinfc610_dbg_inf_read_retry_notice, ++#ifdef CONFIG_HINFC610_DBG_NAND_DUMP ++ &hinfc610_dbg_inf_dump, ++#endif ++#ifdef CONFIG_HINFC610_DBG_NAND_ERASE_COUNT ++ &hinfc610_dbg_inf_erase_count, ++#endif ++#ifdef CONFIG_HINFC610_DBG_NAND_ECC_COUNT ++ &hinfc610_dbg_inf_ecc_count, ++#endif ++#ifdef CONFIG_HINFC610_DBG_NAND_READ_RETRY ++ &hinfc610_dbg_inf_read_retry, ++#endif ++ NULL, ++}; ++ ++static struct dentry *dbgfs_root; ++static struct hinfc_host *dbgfs_host; ++ ++/*****************************************************************************/ ++static ssize_t dbgfs_debug_read(struct file *filp, char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ char *msg, *p; ++ struct hinfc610_dbg_inf_t **inf; ++ ++ if (*ppos != 0) ++ return 0; ++ ++ msg = (char *)__get_free_page(GFP_TEMPORARY); ++ if (!msg) ++ return -ENOMEM; ++ ++ p = msg; ++ if (count > PAGE_SIZE) ++ count = PAGE_SIZE; ++ ++ for (inf = hinfc610_dbg_inf; *inf; inf++) { ++ if ((p - msg) + MAX_OPTION_SIZE + 2 > count) { ++ PR_ERR("Not enough memory.\n"); ++ break; ++ } ++ p += snprintf(p, (MAX_OPTION_SIZE + 2), "%c%s,", ++ ((*inf)->enable ? '+' : '-'), ++ (*inf)->name); ++ } ++ ++ p += sprintf(p, "\n"); ++ count = (p - msg); ++ if (copy_to_user(buffer, msg, count)) { ++ free_page((unsigned long) msg); ++ return -EFAULT; ++ } ++ ++ free_page((unsigned long) msg); ++ ++ *ppos += count; ++ return count; ++} ++/*****************************************************************************/ ++ ++static void dbgfs_debug_do_cmd(struct hinfc610_dbg_inf_t **dbg_inf, ++ const char *cmd, unsigned int length, int enable) ++{ ++ int ret = 0; ++ struct hinfc610_dbg_inf_t **inf; ++ ++ if (length >= sizeof((*inf)->name)) ++ return; ++ ++ for (inf = dbg_inf; *inf; inf++) { ++ if (!(*inf)->name[length] && ++ !memcmp((*inf)->name, cmd, length)) ++ break; ++ } ++ ++ if (!(*inf) || (*inf)->enable == enable) ++ return; ++ ++ if (enable) { ++ if ((*inf)->init) ++ ret = (*inf)->init(dbgfs_root, dbgfs_host); ++ } else { ++ if ((*inf)->uninit) ++ ret = (*inf)->uninit(); ++ } ++ ++ if (!ret) ++ (*inf)->enable = enable; ++} ++/*****************************************************************************/ ++ ++static void dbgfs_debug_ops(const char *options, ++ struct hinfc610_dbg_inf_t **dbg_inf) ++{ ++ int enable; ++ const char *pos, *cmd; ++ ++ pos = options; ++ ++ while (*pos) { ++ ++ while (*pos && *pos != '+' && *pos != '-') ++ pos++; ++ ++ switch (*pos++) { ++ case '+': ++ enable = 1; ++ break; ++ case '-': ++ enable = 0; ++ break; ++ default: ++ return; ++ } ++ ++ cmd = pos; ++ while (*pos == '_' || isalpha(*pos)) ++ pos++; ++ ++ if (*cmd && pos > cmd) ++ dbgfs_debug_do_cmd(dbg_inf, cmd, (pos - cmd), enable); ++ ++ while (isspace(*pos) || *pos == ',' || *pos == ';') ++ pos++; ++ } ++} ++/*****************************************************************************/ ++/* ++ * echo "+dump, +read_retry, +ecc_count, +erase_count" > debug ++ */ ++static ssize_t dbgfs_debug_write(struct file *filp, const char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ char *options; ++ size_t num = count; ++ ++ if (count > PAGE_SIZE) ++ num = (PAGE_SIZE - 1); ++ ++ options = (char *)__get_free_page(GFP_TEMPORARY); ++ if (!options) ++ return -ENOMEM; ++ ++ if (copy_from_user(options, buffer, num)) { ++ free_page((unsigned long) options); ++ return -EFAULT; ++ } ++ ++ options[num] = 0; ++ ++ dbgfs_debug_ops(options, hinfc610_dbg_inf); ++ ++ free_page((unsigned long) options); ++ ++ *ppos += count; ++ return count; ++} ++/*****************************************************************************/ ++ ++static const struct file_operations dbgfs_debug_fops = { ++ .owner = THIS_MODULE, ++ .read = dbgfs_debug_read, ++ .write = dbgfs_debug_write, ++}; ++/*****************************************************************************/ ++ ++int hinfc610_dbgfs_debug_init(struct hinfc_host *host) ++{ ++ struct dentry *dentry; ++ ++ if (dbgfs_root) ++ return 0; ++ ++ dbgfs_root = debugfs_create_dir("nand", NULL); ++ if (!dbgfs_root) { ++ PR_ERR("Can't create 'nand' dir.\n"); ++ return -ENOENT; ++ } ++ ++ dentry = debugfs_create_file("debug", S_IFREG | S_IRUSR | S_IWUSR, ++ dbgfs_root, NULL, &dbgfs_debug_fops); ++ if (!dentry) { ++ PR_ERR("Can't create 'debug' file.\n"); ++ goto fail; ++ } ++ ++ dbgfs_host = host; ++ ++ if (nand_dbgfs_options) ++ dbgfs_debug_ops(nand_dbgfs_options, hinfc610_dbg_inf); ++ ++ return 0; ++ ++fail: ++ debugfs_remove_recursive(dbgfs_root); ++ dbgfs_root = NULL; ++ ++ return -ENOENT; ++} ++/*****************************************************************************/ ++ ++static int dbgfs_read_retry_notice_init(struct dentry *root, ++ struct hinfc_host *host) ++{ ++ if (!host->read_retry) { ++ pr_warn("read_retry_notice: The NAND not support this interface.\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static void hinfc610_dbg_read_retry_notice(struct hinfc_host *host, int index) ++{ ++ pr_warn("Page 0x%08x do read retry (%d/%d) %s.\n", ++ GET_PAGE_INDEX(host), index, host->read_retry->count, ++ (IS_PS_UN_ECC(host) ? "Fail" : "Success")); ++} ++ ++struct hinfc610_dbg_inf_t hinfc610_dbg_inf_read_retry_notice = { ++ "read_retry_notice", 0, ++ dbgfs_read_retry_notice_init, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ hinfc610_dbg_read_retry_notice, ++}; ++/*****************************************************************************/ ++ ++static void hinfc610_dbg_ecc_notice_read(struct hinfc_host *host) ++{ ++ unsigned int pageindex = GET_PAGE_INDEX(host); ++ ++ if (IS_PS_BAD_BLOCK(host) || IS_PS_EMPTY_PAGE(host)) { ++ if (IS_PS_BBM_ERR(host)) ++ pr_warn("page 0x%08x bbm is corruption, bbm: 0x%x.\n", ++ pageindex, *host->bbm); ++ ++ if (IS_PS_EPM_ERR(host)) ++ pr_warn("page 0x%08x epm is corruption, epm: 0x%x.\n", ++ pageindex, *host->epm); ++ ++ return; ++ } ++ ++ if (IS_PS_UN_ECC(host)) ++ pr_warn("page 0x%08x has uncorrect ecc.\n", pageindex); ++} ++ ++struct hinfc610_dbg_inf_t hinfc610_dbg_inf_ecc_notice = { ++ "ecc_notice", 0, ++ NULL, ++ NULL, ++ hinfc610_dbg_ecc_notice_read, ++ NULL, ++ NULL, ++ NULL, ++}; ++/*****************************************************************************/ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_dbg.h b/drivers/mtd/nand/hinfc610/hinfc610_dbg.h +new file mode 100644 +index 0000000..8fd4deb +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_dbg.h +@@ -0,0 +1,63 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++ ++#ifndef HINFC610_DBGH ++#define HINFC610_DBGH ++/******************************************************************************/ ++ ++#define MAX_OPTION_SIZE 20 ++ ++struct hinfc610_dbg_inf_t { ++ const char name[MAX_OPTION_SIZE]; ++ int enable; ++ int (*init)(struct dentry *root, struct hinfc_host *host); ++ int (*uninit)(void); ++ ++ void (*read)(struct hinfc_host *host); ++ void (*write)(struct hinfc_host *host); ++ void (*erase)(struct hinfc_host *host); ++ ++ void (*read_retry)(struct hinfc_host *host, int index); ++}; ++ ++#define CMD_WORD_OFFSET "offset=" ++#define CMD_WORD_LENGTH "length=" ++#define CMD_WORD_CLEAN "clear" ++#define CMD_WORD_ON "on" ++#define CMD_WORD_OFF "off" ++ ++struct hinfc610_ecc_inf_t { ++ int pagesize; ++ int ecctype; ++ int section; ++ void (*ecc_inf)(struct hinfc_host *host, unsigned char ecc[]); ++}; ++ ++struct hinfc610_ecc_inf_t *hinfc610_get_ecc_inf(struct hinfc_host *host, ++ int pagesize, int ecctype); ++ ++extern struct hinfc610_dbg_inf_t hinfc610_dbg_inf_dump; ++extern struct hinfc610_dbg_inf_t hinfc610_dbg_inf_erase_count; ++extern struct hinfc610_dbg_inf_t hinfc610_dbg_inf_ecc_count; ++extern struct hinfc610_dbg_inf_t hinfc610_dbg_inf_read_retry; ++extern struct hinfc610_dbg_inf_t hinfc610_dbg_inf_read_retry_notice; ++extern struct hinfc610_dbg_inf_t hinfc610_dbg_inf_ecc_notice; ++ ++/******************************************************************************/ ++#endif /* HINFC610_DBGH */ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_dbg_dump.c b/drivers/mtd/nand/hinfc610/hinfc610_dbg_dump.c +new file mode 100644 +index 0000000..e330bb5 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_dbg_dump.c +@@ -0,0 +1,448 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++#include "hinfc610_dbg.h" ++ ++#ifndef CONFIG_HINFC610_DBG_NAND_NUM_OF_LOGS ++# define CONFIG_HINFC610_DBG_NAND_NUM_OF_LOGS (80) ++#endif /* CONFIG_HINFC610_DBG_NAND_NUM_OF_LOGS */ ++ ++#ifndef CONFIG_HINFC610_DBG_NAND_LOG_LENGTH ++# define CONFIG_HINFC610_DBG_NAND_LOG_LENGTH (40) ++#endif /* CONFIG_HINFC610_DBG_NAND_LOG_LENGTH */ ++ ++struct hinfc610_dbg_dump_item_t { ++ unsigned short hour; ++ unsigned short min; ++ unsigned short sec; ++ unsigned short msec; ++ ++ unsigned int cycle; ++ ++ unsigned long page; ++ unsigned long offset; ++ unsigned long length; ++ ++ char page_status[4]; ++ char op; ++ ++ unsigned char data[CONFIG_HINFC610_DBG_NAND_LOG_LENGTH]; ++}; ++ ++struct hinfc610_dbg_dump_t { ++ ++ struct dentry *dentry; ++ unsigned int index; /* current logs index */ ++ int count; /* number of logs */ ++ ++ unsigned long offset; ++ unsigned long length; ++ ++ struct hinfc610_dbg_dump_item_t ++ logs[CONFIG_HINFC610_DBG_NAND_NUM_OF_LOGS]; ++ ++ unsigned int read_index; ++}; ++ ++static DEFINE_MUTEX(dbg_dump_mutex); ++static struct hinfc610_dbg_dump_t *dbg_dump; ++ ++/*****************************************************************************/ ++ ++static void do_gettime(unsigned short *hour, unsigned short *min, ++ unsigned short *sec, unsigned short *msec) ++{ ++ long val; ++ struct timeval tv; ++ ++ do_gettimeofday(&tv); ++ val = tv.tv_sec % 86400; /* the second form 0 hour */ ++ ++ if (hour) ++ *hour = val / 3600; ++ val %= 3600; ++ if (min) ++ *min = val / 60; ++ if (sec) ++ *sec = val % 60; ++ if (msec) ++ *msec = tv.tv_usec / 1000; ++} ++/*****************************************************************************/ ++/* ++ * ++# cat ./debugfs/nand/dump ++Print parameter: "offset=0 length=8" ++UTC Clock op cylce page-offset data ++00:00:33.0321 W 5 0x0000258F-0000 31 18 10 06 18 EF FE 11 ++00:00:33.0325 W 5 0x00002740-0000 31 18 10 06 7C D4 B3 0C ++* ++*/ ++static ssize_t dbgfs_dump_read(struct file *filp, char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ int len = 0; ++ char buf[128] = {0}; ++ unsigned int read_index; ++ char __user *pusrbuf = buffer; ++ struct hinfc610_dbg_dump_item_t *logs; ++ ++ if (*ppos == 0) { ++ ++ if (dbg_dump->count ++ < CONFIG_HINFC610_DBG_NAND_NUM_OF_LOGS) ++ dbg_dump->read_index = 0; ++ else ++ dbg_dump->read_index ++ = (dbg_dump->index + 1); ++ ++ len = snprintf(buf, sizeof(buf), ++ "Print parameter: \"offset=%ld length=%ld\"\n", ++ dbg_dump->offset, dbg_dump->length); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ ++ pusrbuf += len; ++ ++ len += snprintf(buf, sizeof(buf), ++ " UTC Clock op cylce page-offset data\n"); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ ++ pusrbuf += len; ++ ++ } else if (dbg_dump->read_index == dbg_dump->index) ++ return 0; ++ ++ for (read_index = dbg_dump->read_index; ++ (read_index != dbg_dump->index); ++ ++read_index) { ++ ++ if (read_index >= CONFIG_HINFC610_DBG_NAND_NUM_OF_LOGS) ++ read_index = 0; ++ ++ logs = &dbg_dump->logs[read_index]; ++ ++ if ((count - (pusrbuf - buffer)) < (50 + logs->length * 3)) ++ break; ++ ++ len = snprintf(buf, sizeof(buf), ++ "%02d:%02d:%02d.%04d %c %-2u 0x%08lX-%04lX", ++ logs->hour, logs->min, logs->sec, logs->msec, ++ logs->op, logs->cycle, ++ logs->page, logs->offset); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ ++ pusrbuf += len; ++ ++ if (logs->op == 'E') { ++ ++ len = snprintf(buf, sizeof(buf), " ---"); ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ ++ } else { ++ ++ int ix; ++ ++ len = snprintf(buf, sizeof(buf), "%s", ++ logs->page_status); ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ ++ for (ix = 0; ix < logs->length; ix++) { ++ if ((ix % 16) == 15) { ++ len = snprintf(buf, sizeof(buf), ++ "%02X-", ++ logs->data[ix]); ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ } else { ++ len = snprintf(buf, sizeof(buf), ++ "%02X ", ++ logs->data[ix]); ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ } ++ } ++ } ++ len = snprintf(buf, sizeof(buf), "\n"); ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ } ++ ++ dbg_dump->read_index = read_index; ++ ++ *ppos += (pusrbuf - buffer); ++ return pusrbuf - buffer; ++} ++/*****************************************************************************/ ++ ++static ssize_t dbgfs_dump_write(struct file *filp, const char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ char *p; ++ int ret; ++ unsigned long value = 0; ++ char buf[128] = {0}; ++ unsigned long pos = 0; ++ ++ if (count > sizeof(buf)) ++ count = sizeof(buf); ++ ++ if (copy_from_user(buf, buffer, count)) ++ return -EFAULT; ++ ++ while (pos < count) { ++ ++ while (pos < count ++ && (buf[pos] == ' ' || ++ buf[pos] == ',' || buf[pos] == ';')) ++ pos++; ++ ++ if (pos >= count) ++ break; ++ ++ switch (buf[pos]) { ++ case 'o': ++ if (!memcmp(&buf[pos], CMD_WORD_OFFSET, ++ sizeof(CMD_WORD_OFFSET) - 1)) { ++ ++ pos += sizeof(CMD_WORD_OFFSET) - 1; ++ p = (char *)(buf + pos); ++ ret = kstrtoul(p, 10, &value); ++ if (ret < 0) ++ value = 0; ++ dbg_dump->offset = value; ++ } ++ break; ++ ++ case 'l': ++ if (!memcmp(&buf[pos], CMD_WORD_LENGTH, ++ sizeof(CMD_WORD_LENGTH) - 1)) { ++ ++ pos += sizeof(CMD_WORD_LENGTH) - 1; ++ p = (char *)(buf + pos); ++ ret = kstrtoul(p, 10, &value); ++ if (ret < 0) ++ value = 0; ++ dbg_dump->length = value; ++ } ++ break; ++ } ++ ++ while (pos < count && ++ (buf[pos] != ' ' && buf[pos] != ',' && buf[pos] != ';')) ++ pos++; ++ } ++ ++ *ppos += count; ++ return count; ++} ++/*****************************************************************************/ ++ ++static const struct file_operations dbgfs_dump_fops = { ++ .owner = THIS_MODULE, ++ .read = dbgfs_dump_read, ++ .write = dbgfs_dump_write, ++}; ++/*****************************************************************************/ ++ ++static int dbgfs_dump_init(struct dentry *root, struct hinfc_host *host) ++{ ++ struct hinfc610_dbg_dump_t *dump; ++ ++ if (dbg_dump) ++ return 0; ++ ++ dump = vmalloc(sizeof(struct hinfc610_dbg_dump_t)); ++ if (!dump) { ++ PR_ERR("Can't allocate memory.\n"); ++ return -ENOMEM; ++ } ++ memset(dump, 0, sizeof(struct hinfc610_dbg_dump_t)); ++ ++ dump->dentry = debugfs_create_file("dump", ++ S_IFREG | S_IRUSR | S_IWUSR, ++ root, NULL, &dbgfs_dump_fops); ++ if (!dump->dentry) { ++ PR_ERR("Can't create 'dump' file.\n"); ++ vfree(dump); ++ return -ENOENT; ++ } ++ ++ dump->length = 8; ++ ++ dbg_dump = dump; ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int dbgfs_dump_uninit(void) ++{ ++ if (!dbg_dump) ++ return 0; ++ ++ mutex_lock(&dbg_dump_mutex); ++ ++ debugfs_remove(dbg_dump->dentry); ++ ++ vfree(dbg_dump); ++ dbg_dump = NULL; ++ ++ mutex_unlock(&dbg_dump_mutex); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static void dbg_dump_rw(struct hinfc_host *host, char op) ++{ ++ unsigned long buflen; ++ struct hinfc610_dbg_dump_item_t *logs; ++ ++ mutex_lock(&dbg_dump_mutex); ++ ++ if (!dbg_dump) ++ goto exit; ++ ++ buflen = (host->pagesize + host->oobsize); ++ logs = &dbg_dump->logs[dbg_dump->index]; ++ ++ dbg_dump->count++; ++ ++ do_gettime(&logs->hour, &logs->min, &logs->sec, &logs->msec); ++ ++ memcpy(logs->page_status, "\x20\x20\x20\x00", 4); ++ ++ if (host->page_status) { ++ if (IS_PS_BAD_BLOCK(host)) ++ logs->page_status[0] = 'B'; ++ else if (IS_PS_EMPTY_PAGE(host)) ++ logs->page_status[0] = 'E'; ++ ++ if (IS_PS_UN_ECC(host)) ++ logs->page_status[1] = '*'; ++ ++ if (IS_PS_EPM_ERR(host) || IS_PS_BBM_ERR(host)) ++ logs->page_status[2] = '?'; ++ } ++ ++ logs->op = op; ++ logs->cycle = host->addr_cycle; ++ logs->length = dbg_dump->length; ++ logs->offset = (host->addr_value[0] & 0xFFFF); ++ logs->page = GET_PAGE_INDEX(host); ++ ++ if (!logs->offset) ++ logs->offset = dbg_dump->offset; ++ ++ if (logs->offset >= buflen) ++ logs->offset = 0; ++ ++ if (logs->length > (buflen - logs->offset)) ++ logs->length = (buflen - logs->offset); ++ ++ if (logs->length > CONFIG_HINFC610_DBG_NAND_LOG_LENGTH) ++ logs->length = CONFIG_HINFC610_DBG_NAND_LOG_LENGTH; ++ ++ memcpy(logs->data, (host->buffer + logs->offset), logs->length); ++ ++ if (++dbg_dump->index >= CONFIG_HINFC610_DBG_NAND_NUM_OF_LOGS) ++ dbg_dump->index = 0; ++ ++exit: ++ mutex_unlock(&dbg_dump_mutex); ++} ++/*****************************************************************************/ ++ ++static void dbg_dump_read(struct hinfc_host *host) ++{ ++ dbg_dump_rw(host, 'R'); ++} ++/*****************************************************************************/ ++ ++static void dbg_dump_write(struct hinfc_host *host) ++{ ++ dbg_dump_rw(host, 'W'); ++} ++/*****************************************************************************/ ++ ++static void dbg_dump_erase(struct hinfc_host *host) ++{ ++ struct hinfc610_dbg_dump_item_t *logs; ++ ++ mutex_lock(&dbg_dump_mutex); ++ ++ if (!dbg_dump) ++ goto exit; ++ ++ dbg_dump->count++; ++ logs = &dbg_dump->logs[dbg_dump->index]; ++ ++ do_gettime(&logs->hour, &logs->min, &logs->sec, &logs->msec); ++ ++ memcpy(logs->page_status, "\x20\x20\x20\x00", 4); ++ ++ logs->op = 'E'; ++ logs->cycle = host->addr_cycle; ++ logs->length = dbg_dump->length; ++ ++ logs->offset = 0; ++ logs->page = host->addr_value[0]; ++ logs->length = 0; ++ ++ if (++dbg_dump->index >= CONFIG_HINFC610_DBG_NAND_NUM_OF_LOGS) ++ dbg_dump->index = 0; ++ ++exit: ++ mutex_unlock(&dbg_dump_mutex); ++} ++/*****************************************************************************/ ++ ++struct hinfc610_dbg_inf_t hinfc610_dbg_inf_dump = { ++ "dump", 0, ++ dbgfs_dump_init, ++ dbgfs_dump_uninit, ++ dbg_dump_read, ++ dbg_dump_write, ++ dbg_dump_erase, ++ NULL, ++}; ++/*****************************************************************************/ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_dbg_ecc_count.c b/drivers/mtd/nand/hinfc610/hinfc610_dbg_ecc_count.c +new file mode 100644 +index 0000000..b7174ab +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_dbg_ecc_count.c +@@ -0,0 +1,401 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++#include "hinfc610_dbg.h" ++ ++#ifndef CONFIG_HINFC610_DBG_ECC_COUNT_NUM ++# define CONFIG_HINFC610_DBG_ECC_COUNT_NUM (100) ++#endif /* CONFIG_HINFC610_DBG_ECC_COUNT_NUM */ ++ ++struct hinfc610_dbg_ecc_count_item_t { ++ unsigned int page; ++ unsigned int page_status; /* the same as host->page_status */ ++ unsigned short hour; ++ unsigned short min; ++ unsigned short sec; ++ unsigned short msec; ++ ++ unsigned char ecc[4]; ++}; ++ ++struct hinfc610_dbg_ecc_count_t { ++ ++ struct dentry *dentry; ++ unsigned int index; /* current logs index */ ++ int count; /* number of logs */ ++ ++ struct hinfc610_ecc_inf_t *ecc_inf; ++ unsigned int offset; ++ unsigned int length; ++ unsigned int pagecount; ++ ++ unsigned char *item; ++ ++ unsigned int read_index; ++}; ++ ++#define GET_ITEM(_ecc_count, _index) \ ++ ((struct hinfc610_dbg_ecc_count_item_t *)((_ecc_count)->item + \ ++ ((sizeof(struct hinfc610_dbg_ecc_count_item_t) + \ ++ (_ecc_count)->ecc_inf->section) * (_index)))) ++ ++static DEFINE_MUTEX(dbg_ecc_count_mutex); ++static struct hinfc610_dbg_ecc_count_t *dbg_ecc_count; ++/*****************************************************************************/ ++ ++static void do_gettime(unsigned short *hour, unsigned short *min, ++ unsigned short *sec, unsigned short *msec) ++{ ++ long val; ++ struct timeval tv; ++ ++ do_gettimeofday(&tv); ++ val = tv.tv_sec % 86400; /* the second form 0 hour */ ++ ++ if (hour) ++ *hour = val / 3600; ++ val %= 3600; ++ if (min) ++ *min = val / 60; ++ if (sec) ++ *sec = val % 60; ++ if (msec) ++ *msec = tv.tv_usec / 1000; ++} ++/*****************************************************************************/ ++ ++static ssize_t dbgfs_ecc_count_read(struct file *filp, char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ int len = 0; ++ char buf[128] = {0}; ++ unsigned int read_index; ++ char __user *pusrbuf = buffer; ++ struct hinfc610_dbg_ecc_count_item_t *item; ++ ++ if (*ppos == 0) { ++ ++ if (dbg_ecc_count->count ++ < CONFIG_HINFC610_DBG_ECC_COUNT_NUM) ++ dbg_ecc_count->read_index = 0; ++ else ++ dbg_ecc_count->read_index ++ = (dbg_ecc_count->index + 1); ++ ++ len = snprintf(buf, sizeof(buf), ++ "Print parameter: \"offset=%d length=%d\"\n", ++ dbg_ecc_count->offset, ++ dbg_ecc_count->length); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ ++ pusrbuf += len; ++ ++ len = snprintf(buf, sizeof(buf), ++ " UTC Clock page ecc data\n"); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ ++ pusrbuf += len; ++ ++ } else if (dbg_ecc_count->read_index == dbg_ecc_count->index) ++ return 0; ++ ++ for (read_index = dbg_ecc_count->read_index; ++ (read_index != dbg_ecc_count->index); ++read_index) { ++ ++ if (read_index >= CONFIG_HINFC610_DBG_ECC_COUNT_NUM) ++ read_index = 0; ++ ++ item = GET_ITEM(dbg_ecc_count, read_index); ++ ++ if ((count - (pusrbuf - buffer)) < 80) ++ break; ++ ++ len = snprintf(buf, sizeof(buf), ++ "%02d:%02d:%02d.%04d 0x%08X ", ++ item->hour, item->min, item->sec, item->msec, ++ item->page); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ ++ pusrbuf += len; ++ ++ if (IS_PS_BAD_BLOCK(item) || IS_PS_EMPTY_PAGE(item) || ++ IS_PS_UN_ECC(item)) { ++ char *ptr = buf; ++ ++ if (IS_PS_BAD_BLOCK(item)) ++ ptr += snprintf(ptr, 16, "bb "); ++ else if (IS_PS_EMPTY_PAGE(item)) ++ ptr += snprintf(ptr, 16, "ep "); ++ ++ if (IS_PS_UN_ECC(item)) ++ ptr += snprintf(ptr, 16, "ecc "); ++ ++ if (IS_PS_EPM_ERR(item) || IS_PS_BBM_ERR(item)) ++ ptr += snprintf(ptr, 16, "? "); ++ ++ ptr += snprintf(ptr, 16, "\n"); ++ len = (ptr - buf); ++ ++ } else { ++ int ix; ++ char *ptr = buf; ++ ++ for (ix = 0; ix < dbg_ecc_count->ecc_inf->section; ix++) ++ ptr += snprintf(ptr, 16, "%d/", item->ecc[ix]); ++ ++ if (IS_PS_EPM_ERR(item)) ++ ptr += snprintf(ptr, 16, " ?"); ++ ++ ptr += snprintf(ptr, 16, "\n"); ++ len = (ptr - buf); ++ } ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ } ++ ++ dbg_ecc_count->read_index = read_index; ++ ++ *ppos += (pusrbuf - buffer); ++ return pusrbuf - buffer; ++} ++/******************************************************************************/ ++/* ++ * echo "offset=8192,length=102400" > ecc_count ++ * ++ */ ++static ssize_t dbgfs_ecc_count_write(struct file *filp, ++ const char __user *buffer, size_t count, ++ loff_t *ppos) ++{ ++ char *str; ++ char buf[128] = {0}; ++ int ret; ++ unsigned long value = 0; ++ unsigned long pos = 0; ++ ++ if (count > sizeof(buf)) ++ count = sizeof(buf); ++ ++ if (copy_from_user(buf, buffer, count)) ++ return -EFAULT; ++ ++ while (pos < count) { ++ while (pos < count && ++ (buf[pos] == ' ' || buf[pos] == ',' || buf[pos] == ';')) ++ pos++; ++ ++ if (pos >= count) ++ break; ++ ++ switch (buf[pos]) { ++ ++ case 'o': ++ ++ if (memcmp(&buf[pos], CMD_WORD_OFFSET, ++ sizeof(CMD_WORD_OFFSET) - 1)) ++ break; ++ ++ pos += sizeof(CMD_WORD_OFFSET) - 1; ++ str = (char *)(buf + pos); ++ ret = kstrtoul(str, 10, &value); ++ ++ if (ret < 0) ++ value = 0; ++ if (value >= dbg_ecc_count->pagecount) ++ value = 0; ++ ++ dbg_ecc_count->offset = (value & ~7); ++ ++ break; ++ ++ case 'l': ++ if (memcmp(&buf[pos], CMD_WORD_LENGTH, ++ sizeof(CMD_WORD_LENGTH) - 1)) ++ break; ++ ++ pos += sizeof(CMD_WORD_LENGTH) - 1; ++ str = (char *)(buf + pos); ++ ret = kstrtoul(str, 10, &value); ++ ++ if (ret < 0) ++ value = dbg_ecc_count->pagecount; ++ ++ value = ((value + 7) & ~7); ++ ++ if (dbg_ecc_count->offset + value > ++ dbg_ecc_count->pagecount) ++ value = dbg_ecc_count->pagecount ++ - dbg_ecc_count->offset; ++ ++ dbg_ecc_count->length = value; ++ ++ break; ++ } ++ ++ while (pos < count && ++ (buf[pos] != ' ' && buf[pos] != ',' && buf[pos] != ';')) ++ pos++; ++ } ++ ++ return count; ++} ++/******************************************************************************/ ++ ++static const struct file_operations dbgfs_ecc_count_fops = { ++ .owner = THIS_MODULE, ++ .read = dbgfs_ecc_count_read, ++ .write = dbgfs_ecc_count_write, ++}; ++/*****************************************************************************/ ++ ++static int dbgfs_ecc_count_init(struct dentry *root, struct hinfc_host *host) ++{ ++ unsigned int size; ++ unsigned int pagesize; ++ unsigned int chipsize; ++ struct hinfc610_ecc_inf_t *ecc_inf; ++ struct hinfc610_dbg_ecc_count_t *ecc_count; ++ ++ if (dbg_ecc_count) ++ return 0; ++ ++ ecc_inf = hinfc610_get_ecc_inf(host, host->pagesize, host->ecctype); ++ if (!ecc_inf) { ++ pr_warn("ecc_count: The NAND not support this interface.\n"); ++ return -1; ++ } ++ ++ size = sizeof(struct hinfc610_dbg_ecc_count_t); ++ size += CONFIG_HINFC610_DBG_ECC_COUNT_NUM * ++ (sizeof(struct hinfc610_dbg_ecc_count_item_t) ++ + ecc_inf->section); ++ ++ ecc_count = vmalloc(size); ++ if (!ecc_count) { ++ PR_ERR("Can't allocate memory.\n"); ++ return -ENOMEM; ++ } ++ memset(ecc_count, 0, size); ++ ++ ecc_count->item = (char *)ecc_count + ++ sizeof(struct hinfc610_dbg_ecc_count_t); ++ ecc_count->ecc_inf = ecc_inf; ++ ++ pagesize = (host->pagesize >> 10); ++ chipsize = (unsigned int)(host->chip->chipsize >> 10); ++ ecc_count->pagecount = (chipsize / pagesize); ++ ecc_count->length = ecc_count->pagecount; ++ ++ ecc_count->dentry = debugfs_create_file("ecc_count", ++ S_IFREG | S_IRUSR | S_IWUSR, ++ root, NULL, &dbgfs_ecc_count_fops); ++ if (!ecc_count->dentry) { ++ PR_ERR("Can't create 'ecc_count' file.\n"); ++ vfree(ecc_count); ++ return -ENOENT; ++ } ++ ++ dbg_ecc_count = ecc_count; ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int dbgfs_ecc_count_uninit(void) ++{ ++ if (!dbg_ecc_count) ++ return 0; ++ ++ mutex_lock(&dbg_ecc_count_mutex); ++ ++ debugfs_remove(dbg_ecc_count->dentry); ++ ++ vfree(dbg_ecc_count); ++ dbg_ecc_count = NULL; ++ ++ mutex_unlock(&dbg_ecc_count_mutex); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static void dbg_ecc_count_read(struct hinfc_host *host) ++{ ++ unsigned int page; ++ struct hinfc610_dbg_ecc_count_item_t *item; ++ ++ mutex_lock(&dbg_ecc_count_mutex); ++ ++ if (!dbg_ecc_count) ++ goto exit; ++ ++ page = GET_PAGE_INDEX(host); ++ ++ if (page < dbg_ecc_count->offset || ++ page > (dbg_ecc_count->offset + dbg_ecc_count->length)) ++ goto exit; ++ ++ item = GET_ITEM(dbg_ecc_count, dbg_ecc_count->index); ++ ++ dbg_ecc_count->count++; ++ ++ do_gettime(&item->hour, &item->min, &item->sec, &item->msec); ++ ++ item->page = page; ++ item->page_status = host->page_status; ++ ++ if (!IS_PS_UN_ECC(host)) ++ dbg_ecc_count->ecc_inf->ecc_inf(host, item->ecc); ++ ++ if (++dbg_ecc_count->index >= CONFIG_HINFC610_DBG_ECC_COUNT_NUM) ++ dbg_ecc_count->index = 0; ++ ++exit: ++ mutex_unlock(&dbg_ecc_count_mutex); ++} ++/*****************************************************************************/ ++ ++struct hinfc610_dbg_inf_t hinfc610_dbg_inf_ecc_count = { ++ "ecc_count", 0, ++ dbgfs_ecc_count_init, ++ dbgfs_ecc_count_uninit, ++ dbg_ecc_count_read, ++ NULL, ++ NULL, ++ NULL, ++}; ++/*****************************************************************************/ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_dbg_ecc_dump.c b/drivers/mtd/nand/hinfc610/hinfc610_dbg_ecc_dump.c +new file mode 100644 +index 0000000..a1b7eda +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_dbg_ecc_dump.c +@@ -0,0 +1,141 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++#include "hinfc610_dbg.h" ++ ++/*****************************************************************************/ ++static inline void hinfc610_detect_ecc(unsigned char ecc[], int begin, ++ int end, unsigned int reg) ++{ ++ while (begin < end) { ++ ecc[begin] = (reg & 0xff); ++ reg = (reg >> 8); ++ begin++; ++ } ++} ++/*****************************************************************************/ ++ ++static void hinfc610_ecc_32k(struct hinfc_host *host, unsigned char ecc[]) ++{ ++ int ix, jx, kx; ++ ++ for (ix = 0, jx = 0; ix < 4; ix ++, jx += 4) ++ hinfc610_detect_ecc(ecc, jx, jx + 4, ++ hinfc_read(host, 0xA0 + jx)); ++ kx = jx; ++ for (ix = 0, jx = 0; ix < 4; ix ++, jx += 4) ++ hinfc610_detect_ecc(ecc, kx, kx + 4, ++ hinfc_read(host, 0xDC + jx)); ++} ++/*****************************************************************************/ ++ ++static void hinfc610_ecc_16k(struct hinfc_host *host, unsigned char ecc[]) ++{ ++ int ix, jx; ++ ++ for (ix = 0, jx = 0; ix < 4; ix ++, jx += 4) ++ hinfc610_detect_ecc(ecc, jx, jx + 4, ++ hinfc_read(host, 0xA0 + jx)); ++} ++/*****************************************************************************/ ++ ++static void hinfc610_ecc_8k(struct hinfc_host *host, unsigned char ecc[]) ++{ ++ int ix, jx; ++ ++ for (ix = 0, jx = 0; ix < 2; ix ++, jx += 4) ++ hinfc610_detect_ecc(ecc, jx, jx + 4, ++ hinfc_read(host, 0xA0 + jx)); ++} ++/*****************************************************************************/ ++ ++static void hinfc610_ecc_4k(struct hinfc_host *host, unsigned char ecc[]) ++{ ++ hinfc610_detect_ecc(ecc, 0, 4, hinfc_read(host, 0xA0)); ++} ++/*****************************************************************************/ ++ ++static void hinfc610_ecc_2k(struct hinfc_host *host, unsigned char ecc[]) ++{ ++ hinfc610_detect_ecc(ecc, 0, 2, hinfc_read(host, 0xA0)); ++} ++/*****************************************************************************/ ++ ++static struct hinfc610_ecc_inf_t hinfc610_ecc_inf[] = { ++ ++ {32768, NAND_ECC_80BIT, 32, hinfc610_ecc_32k}, ++ {32768, NAND_ECC_72BIT, 32, hinfc610_ecc_32k}, ++ {32768, NAND_ECC_60BIT, 32, hinfc610_ecc_32k}, ++ {32768, NAND_ECC_48BIT, 32, hinfc610_ecc_32k}, ++ {32768, NAND_ECC_41BIT, 32, hinfc610_ecc_32k}, ++ ++ {16384, NAND_ECC_80BIT, 16, hinfc610_ecc_16k}, ++ {16384, NAND_ECC_72BIT, 16, hinfc610_ecc_16k}, ++ {16384, NAND_ECC_60BIT, 16, hinfc610_ecc_16k}, ++ {16384, NAND_ECC_48BIT, 16, hinfc610_ecc_16k}, ++ {16384, NAND_ECC_41BIT, 16, hinfc610_ecc_16k}, ++ ++ {8192, NAND_ECC_80BIT, 8, hinfc610_ecc_8k}, ++ {8192, NAND_ECC_72BIT, 8, hinfc610_ecc_8k}, ++ {8192, NAND_ECC_60BIT, 8, hinfc610_ecc_8k}, ++ {8192, NAND_ECC_48BIT, 8, hinfc610_ecc_8k}, ++ {8192, NAND_ECC_41BIT, 8, hinfc610_ecc_8k}, ++ {8192, NAND_ECC_32BIT, 8, hinfc610_ecc_8k}, ++ {8192, NAND_ECC_27BIT, 8, hinfc610_ecc_8k}, ++ {8192, NAND_ECC_24BIT, 8, hinfc610_ecc_8k}, ++ ++ ++ ++ {4096, NAND_ECC_32BIT, 4, hinfc610_ecc_4k}, ++ {4096, NAND_ECC_27BIT, 4, hinfc610_ecc_4k}, ++ {4096, NAND_ECC_24BIT, 4, hinfc610_ecc_4k}, ++ {4096, NAND_ECC_18BIT, 4, hinfc610_ecc_4k}, ++ {4096, NAND_ECC_13BIT, 4, hinfc610_ecc_4k}, ++ {4096, NAND_ECC_8BIT, 4, hinfc610_ecc_4k}, ++ ++ {2048, NAND_ECC_32BIT, 2, hinfc610_ecc_2k}, ++ {2048, NAND_ECC_27BIT, 2, hinfc610_ecc_2k}, ++ {2048, NAND_ECC_24BIT, 2, hinfc610_ecc_2k}, ++ {2048, NAND_ECC_18BIT, 2, hinfc610_ecc_2k}, ++ {2048, NAND_ECC_13BIT, 2, hinfc610_ecc_2k}, ++ {2048, NAND_ECC_8BIT, 2, hinfc610_ecc_2k}, ++ {0, 0, 0}, ++}; ++/*****************************************************************************/ ++ ++struct hinfc610_ecc_inf_t *hinfc610_get_ecc_inf(struct hinfc_host *host, ++ int pagesize, int ecctype) ++{ ++ struct hinfc610_ecc_inf_t *inf; ++ ++ for (inf = hinfc610_ecc_inf; inf->pagesize; inf++) ++ if (inf->pagesize == pagesize && inf->ecctype == ecctype) ++ return inf; ++ ++ return NULL; ++} +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_dbg_erase_count.c b/drivers/mtd/nand/hinfc610/hinfc610_dbg_erase_count.c +new file mode 100644 +index 0000000..eedbd2b +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_dbg_erase_count.c +@@ -0,0 +1,317 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++#include "hinfc610_dbg.h" ++ ++struct hinfc610_dbg_erase_count_t { ++ ++ unsigned int index; /* display pos */ ++ unsigned int offset; /* display offset */ ++ unsigned int length; /* display length */ ++ ++ struct dentry *dentry; ++ ++ unsigned int blocknum; ++ unsigned int page_per_block; ++ ++ unsigned int pe[1]; ++}; ++ ++static DEFINE_MUTEX(dbg_erase_count_mutex); ++static struct hinfc610_dbg_erase_count_t *dbg_erase_count; ++ ++/*****************************************************************************/ ++ ++static int dbgfs_erase_count_read(struct file *filp, char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ int len = 0; ++ int value = 0; ++ unsigned int *pe; ++ unsigned int index; ++ char buf[128] = {0}; ++ char __user *pusrbuf = buffer; ++ ++ if (*ppos == 0) { ++ dbg_erase_count->index = dbg_erase_count->offset; ++ ++ len = snprintf(buf, sizeof(buf), ++ "Print parameter: \"offset=%d length=%d\"\n", ++ dbg_erase_count->offset, ++ dbg_erase_count->length); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ ++ len = snprintf(buf, sizeof(buf), ++ "Block Index ---------------- " ++ "Erase count from system startup ----------------\n"); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ } ++ ++ for (index = dbg_erase_count->index; ++ index < (dbg_erase_count->offset + dbg_erase_count->length) && ++ ((pusrbuf - buffer) < (count - 100)); ++ index += 8) { ++ ++ pe = &dbg_erase_count->pe[index]; ++ ++ len = snprintf(buf, sizeof(buf), ++ "%4d: %8u %8u %8u %8u %8u %8u %8u %8u\n", ++ index, ++ pe[0], pe[1], pe[2], pe[3], ++ pe[4], pe[5], pe[6], pe[7]); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ } ++ ++ dbg_erase_count->index = index; ++ ++ *ppos += (pusrbuf - buffer); ++ value = pusrbuf - buffer; ++ return value; ++} ++/*****************************************************************************/ ++/* ++ * echo "offset=48,length=78" > /sys/kernel/debug/nand/erase_count ++ * echo "clear" > /sys/kernel/debug/nand/erase_count ++ * ++ ++ # cat ./debugfs/nand/erase_count ++ Print parameter: "offset=0 length=1024" ++ Block Index ---------------- Erase count from system startup ---------------- ++ 0: 0 0 0 0 0 0 0 0 ++ 8: 0 0 0 0 0 0 0 0 ++ 16: 0 0 0 0 0 0 0 0 ++ 24: 0 0 0 0 0 0 0 0 ++ 32: 0 0 0 0 0 0 0 0 ++ 40: 0 0 0 0 0 0 0 0 ++ 48: 0 0 0 0 0 0 0 0 ++ 56: 0 0 0 0 0 0 0 0 ++ 64: 0 0 0 0 0 0 0 0 ++ 72: 0 0 0 0 0 0 0 0 ++ 80: 0 0 0 0 0 0 0 0 ++ ++ */ ++static int dbgfs_erase_count_write(struct file *filp, ++ const char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ char *str; ++ char buf[128] = {0}; ++ int ret; ++ unsigned long value = 0; ++ unsigned long pos = 0; ++ ++ if (count > sizeof(buf)) ++ count = sizeof(buf); ++ ++ if (copy_from_user(buf, buffer, count)) ++ return -EFAULT; ++ ++ while (pos < count) { ++ while (pos < count && ++ (buf[pos] == ' ' || buf[pos] == ',' || buf[pos] == ';')) ++ pos++; ++ ++ if (pos >= count) ++ break; ++ ++ switch (buf[pos]) { ++ ++ case 'o': ++ ++ if (memcmp(&buf[pos], CMD_WORD_OFFSET, ++ sizeof(CMD_WORD_OFFSET) - 1)) ++ break; ++ ++ pos += sizeof(CMD_WORD_OFFSET) - 1; ++ str = (char *)(buf + pos); ++ ret = kstrtoul(str, 10, &value); ++ if (ret < 0) ++ value = 0; ++ if (value >= dbg_erase_count->blocknum) ++ value = 0; ++ ++ dbg_erase_count->offset = (value & ~7); ++ ++ break; ++ ++ case 'l': ++ if (memcmp(&buf[pos], CMD_WORD_LENGTH, ++ sizeof(CMD_WORD_LENGTH) - 1)) ++ break; ++ ++ pos += sizeof(CMD_WORD_LENGTH) - 1; ++ str = (char *)(buf + pos); ++ ret = kstrtoul(str, 10, &value); ++ if (ret < 0) ++ value = dbg_erase_count->blocknum; ++ ++ value = ((value + 7) & ~7); ++ ++ if (dbg_erase_count->offset + value ++ > dbg_erase_count->blocknum) ++ value = dbg_erase_count->blocknum ++ - dbg_erase_count->offset; ++ ++ dbg_erase_count->length = value; ++ ++ break; ++ ++ case 'c': ++ if (memcmp(&buf[pos], CMD_WORD_CLEAN, ++ sizeof(CMD_WORD_CLEAN) - 1)) ++ break; ++ ++ memset(dbg_erase_count->pe, 0, ++ dbg_erase_count->blocknum * ++ sizeof(struct hinfc610_dbg_erase_count_t)); ++ ++ return count; ++ } ++ ++ while (pos < count && ++ (buf[pos] != ' ' && buf[pos] != ',' && buf[pos] != ';')) ++ pos++; ++ } ++ ++ return count; ++} ++/*****************************************************************************/ ++ ++static const struct file_operations dbgfs_erase_count_fops = { ++ .owner = THIS_MODULE, ++ .read = dbgfs_erase_count_read, ++ .write = dbgfs_erase_count_write, ++}; ++/*****************************************************************************/ ++ ++static int dbgfs_erase_count_init(struct dentry *root, struct hinfc_host *host) ++{ ++ unsigned int size; ++ unsigned int blocknum; ++ unsigned int pagesize; ++ unsigned int blocksize; ++ unsigned int chipsize; ++ struct hinfc610_dbg_erase_count_t *erase_count; ++ ++ if (dbg_erase_count) ++ return 0; ++ ++ pagesize = (host->pagesize >> 10); ++ blocksize = (host->mtd->erasesize >> 10); ++ chipsize = (unsigned int)(host->chip->chipsize >> 10); ++ ++ blocknum = chipsize / blocksize; ++ size = sizeof(int) * blocknum ++ + sizeof(struct hinfc610_dbg_erase_count_t); ++ ++ erase_count = vmalloc(size); ++ if (!erase_count) { ++ PR_ERR("Can't allocate memory.\n"); ++ return -ENOMEM; ++ } ++ memset(erase_count, 0, size); ++ ++ erase_count->blocknum = blocknum; ++ erase_count->page_per_block = blocksize / pagesize; ++ erase_count->length = blocknum; ++ ++ erase_count->dentry = debugfs_create_file("erase_count", ++ S_IFREG | S_IRUSR | S_IWUSR, ++ root, NULL, &dbgfs_erase_count_fops); ++ if (!erase_count->dentry) { ++ PR_ERR("Can't create 'erase_count' file.\n"); ++ vfree(erase_count); ++ return -ENOENT; ++ } ++ ++ dbg_erase_count = erase_count; ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int dbgfs_erase_count_uninit(void) ++{ ++ if (!dbg_erase_count) ++ return 0; ++ ++ mutex_lock(&dbg_erase_count_mutex); ++ ++ debugfs_remove(dbg_erase_count->dentry); ++ ++ vfree(dbg_erase_count); ++ dbg_erase_count = NULL; ++ ++ mutex_unlock(&dbg_erase_count_mutex); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static void dbg_erase_count_erase(struct hinfc_host *host) ++{ ++ unsigned int block_index; ++ ++ mutex_lock(&dbg_erase_count_mutex); ++ ++ if (!dbg_erase_count) ++ goto exit; ++ ++ block_index = (host->addr_value[0] / dbg_erase_count->page_per_block); ++ ++ if (block_index > dbg_erase_count->blocknum) { ++ PR_ERR("Block out of range.\n"); ++ return; ++ } ++ ++ dbg_erase_count->pe[block_index]++; ++ ++exit: ++ mutex_unlock(&dbg_erase_count_mutex); ++} ++/*****************************************************************************/ ++ ++struct hinfc610_dbg_inf_t hinfc610_dbg_inf_erase_count = { ++ "erase_count", 0, ++ dbgfs_erase_count_init, ++ dbgfs_erase_count_uninit, ++ NULL, ++ NULL, ++ dbg_erase_count_erase, ++ NULL, ++}; +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_dbg_inf.c b/drivers/mtd/nand/hinfc610/hinfc610_dbg_inf.c +new file mode 100644 +index 0000000..f3e7140 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_dbg_inf.c +@@ -0,0 +1,81 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++#include "hinfc610_dbg.h" ++ ++void hinfc610_dbg_write(struct hinfc_host *host) ++{ ++#ifdef CONFIG_HINFC610_DBG_NAND_DEBUG ++ struct hinfc610_dbg_inf_t **inf; ++ ++ for (inf = hinfc610_dbg_inf; *inf; inf++) ++ if ((*inf)->enable && (*inf)->write) ++ (*inf)->write(host); ++#endif ++} ++ ++void hinfc610_dbg_erase(struct hinfc_host *host) ++{ ++#ifdef CONFIG_HINFC610_DBG_NAND_DEBUG ++ struct hinfc610_dbg_inf_t **inf; ++ ++ for (inf = hinfc610_dbg_inf; *inf; inf++) ++ if ((*inf)->enable && (*inf)->erase) ++ (*inf)->erase(host); ++#endif ++} ++ ++void hinfc610_dbg_read(struct hinfc_host *host) ++{ ++#ifdef CONFIG_HINFC610_DBG_NAND_DEBUG ++ struct hinfc610_dbg_inf_t **inf; ++ ++ for (inf = hinfc610_dbg_inf; *inf; inf++) ++ if ((*inf)->enable && (*inf)->read) ++ (*inf)->read(host); ++#endif ++} ++ ++void hinfc610_dbg_read_retry(struct hinfc_host *host, int index) ++{ ++#ifdef CONFIG_HINFC610_DBG_NAND_DEBUG ++ struct hinfc610_dbg_inf_t **inf; ++ ++ for (inf = hinfc610_dbg_inf; *inf; inf++) ++ if ((*inf)->enable && (*inf)->read_retry) ++ (*inf)->read_retry(host, index); ++#endif ++} ++ ++int hinfc610_dbg_init(struct hinfc_host *host) ++{ ++#ifdef CONFIG_HINFC610_DBG_NAND_DEBUG ++ return hinfc610_dbgfs_debug_init(host); ++#endif ++ return 0; ++} +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_dbg_inf.h b/drivers/mtd/nand/hinfc610/hinfc610_dbg_inf.h +new file mode 100644 +index 0000000..10ac797 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_dbg_inf.h +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef HINFC610_DBG_INFH ++#define HINFC610_DBG_INFH ++/******************************************************************************/ ++ ++int hinfc610_dbg_init(struct hinfc_host *host); ++ ++void hinfc610_dbg_write(struct hinfc_host *host); ++ ++void hinfc610_dbg_erase(struct hinfc_host *host); ++ ++void hinfc610_dbg_read(struct hinfc_host *host); ++ ++void hinfc610_dbg_read_retry(struct hinfc_host *host, int index); ++ ++/******************************************************************************/ ++#endif /* HINFC610_DBG_INFH */ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_dbg_read_retry.c b/drivers/mtd/nand/hinfc610/hinfc610_dbg_read_retry.c +new file mode 100644 +index 0000000..176d9c1 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_dbg_read_retry.c +@@ -0,0 +1,385 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++#include "hinfc610_dbg.h" ++ ++#ifndef CONFIG_HINFC610_DBG_READ_RETRY_NUM ++# define CONFIG_HINFC610_DBG_READ_RETRY_NUM (100) ++#endif /* CONFIG_HINFC610_DBG_READ_RETRY_NUM */ ++ ++struct hinfc610_dbg_read_retry_item_t { ++ unsigned int page; ++ ++ unsigned short hour; ++ unsigned short min; ++ unsigned short sec; ++ unsigned short msec; ++ ++ unsigned short retry; /* success retry */ ++ unsigned short ecc_err; ++}; ++ ++struct hinfc610_dbg_read_retry_t { ++ ++ struct dentry *dentry; ++ unsigned int index; /* current logs index */ ++ int count; /* number of logs */ ++ ++ unsigned int offset; ++ unsigned int length; ++ unsigned int pagecount; ++ ++ unsigned int read_index; ++ ++ unsigned int max_retry; /* the max read retry times */ ++ unsigned int retry[16]; ++ ++ struct hinfc610_dbg_read_retry_item_t ++ item[CONFIG_HINFC610_DBG_READ_RETRY_NUM]; ++}; ++ ++static DEFINE_MUTEX(dbg_read_retry_mutex); ++static struct hinfc610_dbg_read_retry_t *dbg_read_retry; ++/*****************************************************************************/ ++ ++static void do_gettime(unsigned short *hour, unsigned short *min, ++ unsigned short *sec, unsigned short *msec) ++{ ++ long val; ++ struct timeval tv; ++ ++ do_gettimeofday(&tv); ++ val = tv.tv_sec % 86400; /* the second form 0 hour */ ++ ++ if (hour) ++ *hour = val / 3600; ++ val %= 3600; ++ if (min) ++ *min = val / 60; ++ if (sec) ++ *sec = val % 60; ++ if (msec) ++ *msec = tv.tv_usec / 1000; ++} ++/*****************************************************************************/ ++ ++static ssize_t dbgfs_read_retry_read(struct file *filp, char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ int ix; ++ char *ptr; ++ int len = 0; ++ char buf[128] = {0}; ++ unsigned int read_index; ++ char __user *pusrbuf = buffer; ++ struct hinfc610_dbg_read_retry_item_t *item; ++ ++ if (*ppos == 0) { ++ ++ if (dbg_read_retry->count ++ < CONFIG_HINFC610_DBG_READ_RETRY_NUM) ++ dbg_read_retry->read_index = 0; ++ else ++ dbg_read_retry->read_index ++ = (dbg_read_retry->index + 1); ++ ++ len = snprintf(buf, sizeof(buf), ++ "Print parameter: \"offset=%d length=%d\"\n", ++ dbg_read_retry->offset, ++ dbg_read_retry->length); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ ++ len = snprintf(buf, sizeof(buf), ++ " UTC Clock page read retry (max: %d)\n", ++ dbg_read_retry->max_retry); ++ ++ ptr = buf; ++ ptr += sprintf(ptr, "Read retry: "); ++ for (ix = 1; ix <= dbg_read_retry->max_retry; ix++) ++ ptr += sprintf(ptr, "%d, ", dbg_read_retry->retry[ix]); ++ ptr += sprintf(ptr, "\n"); ++ ++ len = (ptr - buf); ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ ++ ++ len = snprintf(buf, sizeof(buf), ++ " UTC Clock page read retry (max: %d)\n", ++ dbg_read_retry->max_retry); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ ++ } else if (dbg_read_retry->read_index == dbg_read_retry->index) ++ return 0; ++ ++ for (read_index = dbg_read_retry->read_index; ++ (read_index != dbg_read_retry->index); ++read_index) { ++ ++ if (read_index >= CONFIG_HINFC610_DBG_READ_RETRY_NUM) ++ read_index = 0; ++ ++ item = &dbg_read_retry->item[read_index]; ++ ++ if ((count - (pusrbuf - buffer)) < 80) ++ break; ++ ++ len = snprintf(buf, sizeof(buf), ++ "%02d:%02d:%02d.%04d 0x%08X ", ++ item->hour, item->min, item->sec, item->msec, ++ item->page); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ ++ if (!item->ecc_err) ++ len = sprintf(buf, "%d\n", item->retry); ++ else ++ len = sprintf(buf, "fail\n"); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ } ++ ++ dbg_read_retry->read_index = read_index; ++ ++ *ppos += (pusrbuf - buffer); ++ return pusrbuf - buffer; ++} ++/******************************************************************************/ ++/* ++ * echo "offset=8192,length=102400" > read_retry ++ * ++ */ ++static ssize_t dbgfs_read_retry_write(struct file *filp, ++ const char __user *buffer, size_t count, ++ loff_t *ppos) ++{ ++ char *str; ++ char buf[128] = {0}; ++ int ret; ++ unsigned long value = 0; ++ unsigned long pos = 0; ++ ++ if (count > sizeof(buf)) ++ count = sizeof(buf); ++ ++ if (copy_from_user(buf, buffer, count)) ++ return -EFAULT; ++ ++ while (pos < count) { ++ while (pos < count && ++ (buf[pos] == ' ' || buf[pos] == ',' || buf[pos] == ';')) ++ pos++; ++ ++ if (pos >= count) ++ break; ++ ++ switch (buf[pos]) { ++ ++ case 'o': ++ ++ if (memcmp(&buf[pos], CMD_WORD_OFFSET, ++ sizeof(CMD_WORD_OFFSET) - 1)) ++ break; ++ ++ pos += sizeof(CMD_WORD_OFFSET) - 1; ++ str = (char *)(buf + pos); ++ ret = kstrtoul(str, 10, &value); ++ ++ if (ret < 0) ++ value = 0; ++ if (value >= dbg_read_retry->pagecount) ++ value = 0; ++ ++ dbg_read_retry->offset = (value & ~7); ++ ++ break; ++ ++ case 'l': ++ if (memcmp(&buf[pos], CMD_WORD_LENGTH, ++ sizeof(CMD_WORD_LENGTH) - 1)) ++ break; ++ ++ pos += sizeof(CMD_WORD_LENGTH) - 1; ++ str = (char *)(buf + pos); ++ ret = kstrtoul(str, 10, &value); ++ ++ if (ret < 0) ++ value = dbg_read_retry->pagecount; ++ ++ value = ((value + 7) & ~7); ++ ++ if (dbg_read_retry->offset + value > ++ dbg_read_retry->pagecount) ++ value = dbg_read_retry->pagecount ++ - dbg_read_retry->offset; ++ ++ dbg_read_retry->length = value; ++ ++ break; ++ } ++ ++ while (pos < count && ++ (buf[pos] != ' ' && buf[pos] != ',' && buf[pos] != ';')) ++ pos++; ++ } ++ ++ return count; ++} ++/******************************************************************************/ ++ ++static const struct file_operations dbgfs_read_retry_fops = { ++ .owner = THIS_MODULE, ++ .read = dbgfs_read_retry_read, ++ .write = dbgfs_read_retry_write, ++}; ++/*****************************************************************************/ ++ ++static int dbgfs_read_retry_init(struct dentry *root, struct hinfc_host *host) ++{ ++ unsigned int pagesize; ++ unsigned int chipsize; ++ struct hinfc610_dbg_read_retry_t *read_retry; ++ ++ if (dbg_read_retry) ++ return 0; ++ ++ if (!host->read_retry) { ++ pr_warn("read_retry: The NAND not support this interface.\n"); ++ return -1; ++ } ++ ++ read_retry = vmalloc(sizeof(struct hinfc610_dbg_read_retry_t)); ++ if (!read_retry) { ++ PR_ERR("Can't allocate memory.\n"); ++ return -ENOMEM; ++ } ++ memset(read_retry, 0, sizeof(struct hinfc610_dbg_read_retry_t)); ++ ++ pagesize = (host->pagesize >> 10); ++ chipsize = (unsigned int)(host->chip->chipsize >> 10); ++ read_retry->pagecount = (chipsize / pagesize); ++ read_retry->length = read_retry->pagecount; ++ read_retry->max_retry = host->read_retry->count; ++ ++ if (read_retry->max_retry > 16) { ++ vfree(read_retry); ++ PR_ERR("Bug, max_retry too small.\n"); ++ return -EFAULT; ++ } ++ ++ read_retry->dentry = debugfs_create_file("read_retry", ++ S_IFREG | S_IRUSR | S_IWUSR, ++ root, NULL, &dbgfs_read_retry_fops); ++ if (!read_retry->dentry) { ++ PR_ERR("Can't create 'read_retry' file.\n"); ++ vfree(read_retry); ++ return -ENOENT; ++ } ++ ++ dbg_read_retry = read_retry; ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int dbgfs_read_retry_uninit(void) ++{ ++ if (!dbg_read_retry) ++ return 0; ++ ++ mutex_lock(&dbg_read_retry_mutex); ++ ++ debugfs_remove(dbg_read_retry->dentry); ++ ++ vfree(dbg_read_retry); ++ dbg_read_retry = NULL; ++ ++ mutex_unlock(&dbg_read_retry_mutex); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static void hinfc610_dbg_read_retry_rr(struct hinfc_host *host, int index) ++{ ++ unsigned int page; ++ struct hinfc610_dbg_read_retry_item_t *item; ++ ++ mutex_lock(&dbg_read_retry_mutex); ++ ++ if (!dbg_read_retry) ++ goto exit; ++ ++ page = GET_PAGE_INDEX(host); ++ ++ if (page < dbg_read_retry->offset || ++ page > (dbg_read_retry->offset + dbg_read_retry->length)) ++ goto exit; ++ ++ item = &dbg_read_retry->item[dbg_read_retry->index]; ++ ++ dbg_read_retry->count++; ++ ++ do_gettime(&item->hour, &item->min, &item->sec, &item->msec); ++ ++ item->page = page; ++ item->retry = index; ++ ++ item->ecc_err = IS_PS_UN_ECC(host) ? 1 : 0; ++ if (!item->ecc_err) ++ dbg_read_retry->retry[index]++; ++ ++ if (++dbg_read_retry->index >= CONFIG_HINFC610_DBG_READ_RETRY_NUM) ++ dbg_read_retry->index = 0; ++ ++exit: ++ mutex_unlock(&dbg_read_retry_mutex); ++} ++/*****************************************************************************/ ++ ++struct hinfc610_dbg_inf_t hinfc610_dbg_inf_read_retry = { ++ "read_retry", 0, ++ dbgfs_read_retry_init, ++ dbgfs_read_retry_uninit, ++ NULL, ++ NULL, ++ NULL, ++ hinfc610_dbg_read_retry_rr, ++}; ++/*****************************************************************************/ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_gen.c b/drivers/mtd/nand/hinfc610/hinfc610_gen.c +new file mode 100644 +index 0000000..2b43cf9 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_gen.c +@@ -0,0 +1,85 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "../match_table.h" ++#include "hinfc610_gen.h" ++ ++/*****************************************************************************/ ++ ++static struct match_reg_type page_type2reg[] = { ++ { ++ hinfc610_pagesize_2K, NAND_PAGE_2K, ++ }, { ++ hinfc610_pagesize_4K, NAND_PAGE_4K, ++ }, { ++ hinfc610_pagesize_8K, NAND_PAGE_8K, ++ }, { ++ hinfc610_pagesize_16K, NAND_PAGE_16K, ++ }, { ++ hinfc610_pagesize_32K, NAND_PAGE_32K, ++ } ++}; ++ ++enum hinfc610_page_reg hinfc610_page_type2reg(int type) ++{ ++ return type2reg(page_type2reg, ARRAY_SIZE(page_type2reg), type, 0); ++} ++ ++int hinfc610_page_reg2type(enum hinfc610_page_reg reg) ++{ ++ return reg2type(page_type2reg, ARRAY_SIZE(page_type2reg), reg, 0); ++} ++/*****************************************************************************/ ++ ++static struct match_reg_type ecc_type2reg[] = { ++ { ++ hinfc610_ecc_none, NAND_ECC_NONE, ++ }, { ++ hinfc610_ecc_8bit, NAND_ECC_8BIT, ++ }, { ++ hinfc610_ecc_13bit, NAND_ECC_13BIT, ++ }, { ++ hinfc610_ecc_18bit, NAND_ECC_18BIT, ++ }, { ++ hinfc610_ecc_24bit, NAND_ECC_24BIT, ++ }, { ++ hinfc610_ecc_27bit, NAND_ECC_27BIT, ++ }, { ++ hinfc610_ecc_32bit, NAND_ECC_32BIT, ++ }, { ++ hinfc610_ecc_41bit, NAND_ECC_41BIT, ++ }, { ++ hinfc610_ecc_48bit, NAND_ECC_48BIT, ++ }, { ++ hinfc610_ecc_60bit, NAND_ECC_60BIT, ++ }, { ++ hinfc610_ecc_72bit, NAND_ECC_72BIT, ++ }, { ++ hinfc610_ecc_80bit, NAND_ECC_80BIT, ++ } ++}; ++ ++enum hinfc610_ecc_reg hinfc610_ecc_type2reg(int type) ++{ ++ return type2reg(ecc_type2reg, ARRAY_SIZE(ecc_type2reg), type, 0); ++} ++ ++int hinfc610_ecc_reg2type(enum hinfc610_ecc_reg reg) ++{ ++ return reg2type(ecc_type2reg, ARRAY_SIZE(ecc_type2reg), reg, 0); ++} +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_gen.h b/drivers/mtd/nand/hinfc610/hinfc610_gen.h +new file mode 100644 +index 0000000..c41ff6f +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_gen.h +@@ -0,0 +1,57 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef HINFC610_GENH ++#define HINFC610_GENH ++/******************************************************************************/ ++ ++#include "../hinfc_gen.h" ++ ++enum hinfc610_ecc_reg { ++ hinfc610_ecc_none = 0x00, ++ hinfc610_ecc_8bit = 0x01, ++ hinfc610_ecc_13bit = 0x02, ++ hinfc610_ecc_18bit = 0x03, ++ hinfc610_ecc_24bit = 0x04, ++ hinfc610_ecc_27bit = 0x05, ++ hinfc610_ecc_32bit = 0x06, ++ hinfc610_ecc_41bit = 0x07, ++ hinfc610_ecc_48bit = 0x08, ++ hinfc610_ecc_60bit = 0x09, ++ hinfc610_ecc_72bit = 0x0a, ++ hinfc610_ecc_80bit = 0x0b, ++}; ++ ++enum hinfc610_page_reg { ++ hinfc610_pagesize_2K = 0x01, ++ hinfc610_pagesize_4K = 0x02, ++ hinfc610_pagesize_8K = 0x03, ++ hinfc610_pagesize_16K = 0x04, ++ hinfc610_pagesize_32K = 0x05, ++}; ++ ++enum hinfc610_page_reg hinfc610_page_type2reg(int type); ++ ++int hinfc610_page_reg2type(enum hinfc610_page_reg reg); ++ ++enum hinfc610_ecc_reg hinfc610_ecc_type2reg(int type); ++ ++int hinfc610_ecc_reg2type(enum hinfc610_ecc_reg reg); ++ ++/******************************************************************************/ ++#endif /* HINFC610_GENH */ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_os.c b/drivers/mtd/nand/hinfc610/hinfc610_os.c +new file mode 100644 +index 0000000..9682000 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_os.c +@@ -0,0 +1,245 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++ ++/*****************************************************************************/ ++ ++static int hinfc610_nand_pre_probe(struct nand_chip *chip) ++{ ++ uint8_t nand_maf_id; ++ struct hinfc_host *host = chip->priv; ++ ++ /* Reset the chip first */ ++ host->send_cmd_reset(host, 0); ++ ++ /* Check the ID */ ++ host->offset = 0; ++ memset((unsigned char *)(chip->IO_ADDR_R), 0, 0x10); ++ host->send_cmd_readid(host); ++ nand_maf_id = readb(chip->IO_ADDR_R); ++ ++ if (nand_maf_id == 0x00 || nand_maf_id == 0xff) { ++ PR_BUG("\nCannot found a valid Nand Device\n"); ++ return 1; ++ } ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_os_probe(struct platform_device *pltdev) ++{ ++ int size; ++ int result = 0; ++ struct hinfc_host *host; ++ struct nand_chip *chip; ++ struct mtd_info *mtd; ++ struct resource *rs_reg, *rs_io = NULL; ++ struct device *dev = &pltdev->dev; ++ struct device_node *np = NULL; ++ ++ size = sizeof(struct hinfc_host) + sizeof(struct nand_chip) ++ + sizeof(struct mtd_info); ++ host = kmalloc(size, GFP_KERNEL); ++ if (!host) { ++ PR_BUG("failed to allocate device structure.\n"); ++ return -ENOMEM; ++ } ++ memset((char *)host, 0, size); ++ platform_set_drvdata(pltdev, host); ++ ++ host->dev = dev; ++ host->chip = chip = (struct nand_chip *)&host[1]; ++ host->mtd = mtd = (struct mtd_info *)&chip[1]; ++ ++ host->clk = devm_clk_get(dev, NULL); ++ if (IS_ERR(host->clk)) ++ return PTR_ERR(host->clk); ++ /* enable and set system clock */ ++ clk_prepare_enable(host->clk); ++ ++ rs_reg = platform_get_resource_byname(pltdev, IORESOURCE_MEM, ++ "control"); ++ host->iobase = devm_ioremap_resource(dev, rs_reg); ++ if (IS_ERR(host->iobase)) { ++ PR_BUG("Error: Can't get resource for reg address.\n"); ++ result = -EIO; ++ goto fail; ++ } ++ ++ np = of_get_next_available_child(dev->of_node, NULL); ++ ++ mtd->type = MTD_NANDFLASH; ++ mtd = nand_to_mtd(chip); ++ mtd->flags = MTD_CAP_NANDFLASH; ++ mtd->owner = THIS_MODULE; ++ mtd->name = np->name; ++ ++ rs_io = platform_get_resource_byname(pltdev, IORESOURCE_MEM, ++ "memory"); ++ chip->IO_ADDR_R = chip->IO_ADDR_W = devm_ioremap_resource(dev, rs_io); ++ if (IS_ERR(chip->IO_ADDR_R)) { ++ PR_BUG("Error: Can't get resource for buffer address.\n"); ++ result = -EIO; ++ goto fail; ++ } ++ ++ host->buffer = dma_alloc_coherent(host->dev, ++ (NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE), ++ &host->dma_buffer, GFP_KERNEL); ++ if (!host->buffer) { ++ PR_BUG("Can't malloc memory for NAND driver."); ++ result = -EIO; ++ goto fail; ++ } ++ ++ chip->priv = host; ++ host->chip = chip; ++ chip->cmd_ctrl = hinfc610_cmd_ctrl; ++ chip->dev_ready = hinfc610_dev_ready; ++ chip->select_chip = hinfc610_select_chip; ++ chip->read_byte = hinfc610_read_byte; ++ chip->read_word = hinfc610_read_word; ++ chip->write_buf = hinfc610_write_buf; ++ chip->read_buf = hinfc610_read_buf; ++ ++ chip->chip_delay = HINFC610_CHIP_DELAY; ++ chip->options = NAND_NEED_READRDY ++ | NAND_BROKEN_XD ++ | NAND_SKIP_BBTSCAN; ++ chip->ecc.mode = NAND_ECC_NONE; ++ ++ if (hinfc610_nand_init(host, chip)) { ++ PR_BUG("failed to allocate device buffer.\n"); ++ result = -EIO; ++ goto fail; ++ } ++ ++ if (hinfc610_nand_pre_probe(chip)) { ++ result = -EXDEV; ++ goto fail; ++ } ++ ++ if (nand_scan(mtd, CONFIG_HINFC610_MAX_CHIP)) { ++ result = -ENXIO; ++ goto fail; ++ } ++ ++ result = mtd_device_register(mtd, NULL, 0); ++ if (result) ++ goto fail; ++ ++ return result; ++ ++fail: ++ if (host->buffer) { ++ dma_free_coherent(host->dev, ++ (NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE), ++ host->buffer, ++ host->dma_buffer); ++ host->buffer = NULL; ++ } ++ nand_release(host->mtd); ++ kfree(host); ++ platform_set_drvdata(pltdev, NULL); ++ ++ return result; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_os_remove(struct platform_device *pltdev) ++{ ++ struct hinfc_host *host = platform_get_drvdata(pltdev); ++ ++ clk_disable_unprepare(host->clk); ++ ++ nand_release(host->mtd); ++ ++ dma_free_coherent(host->dev, ++ (NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE), ++ host->buffer, ++ host->dma_buffer); ++ kfree(host); ++ platform_set_drvdata(pltdev, NULL); ++ ++ return 0; ++} ++/*****************************************************************************/ ++#ifdef CONFIG_PM ++static int hinfc610_os_suspend(struct platform_device *pltdev, ++ pm_message_t state) ++{ ++ struct hinfc_host *host = platform_get_drvdata(pltdev); ++ ++ while ((hinfc_read(host, HINFC610_STATUS) & 0x1) == 0x0) ++ ; ++ ++ while ((hinfc_read(host, HINFC610_DMA_CTRL)) ++ & HINFC610_DMA_CTRL_DMA_START) ++ _cond_resched(); ++ ++ clk_disable_unprepare(host->clk); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_os_resume(struct platform_device *pltdev) ++{ ++ int cs; ++ struct hinfc_host *host = platform_get_drvdata(pltdev); ++ struct nand_chip *chip = host->chip; ++ ++ clk_prepare_enable(host->clk); ++ for (cs = 0; cs < chip->numchips; cs++) ++ host->send_cmd_reset(host, cs); ++ hinfc_write(host, ++ SET_HINFC610_PWIDTH(CONFIG_HINFC610_W_LATCH, ++ CONFIG_HINFC610_R_LATCH, CONFIG_HINFC610_RW_LATCH), ++ HINFC610_PWIDTH); ++ ++ return 0; ++} ++#endif /* CONFIG_PM */ ++/*****************************************************************************/ ++static const struct of_device_id hisi_nand_dt_ids[] = { ++ { .compatible = "hisilicon,hisi-parallel-nand" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, hisi_nand_dt_ids); ++ ++static struct platform_driver hisi_nand_driver = { ++ .driver = { ++ .name = "hisi-nand", ++ .of_match_table = hisi_nand_dt_ids, ++ }, ++ .probe = hinfc610_os_probe, ++ .remove = hinfc610_os_remove, ++#ifdef CONFIG_PM ++ .suspend = hinfc610_os_suspend, ++ .resume = hinfc610_os_resume, ++#endif ++}; ++module_platform_driver(hisi_nand_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("BVT_BSP"); ++MODULE_DESCRIPTION("Hisilicon Flash Memory Controller NFC610 Nand Driver"); +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_os.h b/drivers/mtd/nand/hinfc610/hinfc610_os.h +new file mode 100644 +index 0000000..1dafd9e +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_os.h +@@ -0,0 +1,78 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++ ++#ifndef HINFC610_OSH ++#define HINFC610_OSH ++/******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../../mtdcore.h" ++ ++/*****************************************************************************/ ++ ++#define DUMP_DATA(_p, _n) do { \ ++ int ix; \ ++ unsigned char *rr = (unsigned char *)(_p); \ ++ for (ix = 0; ix < _n; ix++) { \ ++ pr_info("%02X ", rr[ix]); \ ++ if (!((ix + 1) % 16)) \ ++ pr_info("\n"); \ ++ } \ ++} while (0) ++ ++#define DBG_OUT(fmt, args...)\ ++ pr_warn("%s(%d): " fmt, __FILE__, __LINE__, ##args) \ ++ ++#if 1 ++# define DBG_MSG(_fmt, arg...) ++#else ++# define DBG_MSG(_fmt, arg...) \ ++ pr_info("%s(%d): " _fmt, __FILE__, __LINE__, ##arg) ++#endif ++ ++#define PR_BUG(fmt, args...) do {\ ++ pr_debug("%s(%d): bug " fmt, __FILE__, __LINE__, ##args); \ ++ asm("b ."); \ ++} while (0) ++ ++#define PR_ERR(fmt, args...)\ ++ pr_err("%s(%d): " fmt, __FILE__, __LINE__, ##args) \ ++ ++#define PR_MSG(_fmt, arg...) \ ++ printk(_fmt, ##arg) ++ ++/******************************************************************************/ ++#endif /* HINFC610_OSH */ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_read_retry.c b/drivers/mtd/nand/hinfc610/hinfc610_read_retry.c +new file mode 100644 +index 0000000..3f1a9f2 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_read_retry.c +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hinfc610_gen.h" ++#include "hinfc610.h" ++#include "hinfc610_read_retry.h" ++ ++static struct read_retry_t *read_retry_table[] = { ++ &hinfc610_hynix_bg_bdie_read_retry, ++ &hinfc610_hynix_bg_cdie_read_retry, ++ &hinfc610_hynix_cg_adie_read_retry, ++ &hinfc610_micron_read_retry, ++ &hinfc610_toshiba_24nm_read_retry, ++ &hinfc610_samsung_read_retry, ++ NULL, ++}; ++ ++struct read_retry_t *hinfc610_find_read_retry(int type) ++{ ++ struct read_retry_t **rr; ++ ++ for (rr = read_retry_table; rr; rr++) { ++ if ((*rr)->type == type) ++ return *rr; ++ } ++ ++ return NULL; ++} +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_read_retry.h b/drivers/mtd/nand/hinfc610/hinfc610_read_retry.h +new file mode 100644 +index 0000000..cfd8880 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_read_retry.h +@@ -0,0 +1,25 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef HINFC610_READ_RETRY_H ++#define HINFC610_READ_RETRY_H ++ ++struct read_retry_t *hinfc610_find_read_retry(int type); ++ ++#endif /* HINFC610_READ_RETRY_H */ ++ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_read_retry_hynix_bg_bdie.c b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_hynix_bg_bdie.c +new file mode 100644 +index 0000000..b6fb1a8 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_hynix_bg_bdie.c +@@ -0,0 +1,136 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++ ++/*****************************************************************************/ ++ ++static int hynix_bg_bdie_rr_org_exist; ++static char hynix_bg_bdie_rr_org[4] = {0}; ++ ++/*****************************************************************************/ ++ ++static int hinfc610_hynix_bg_bdie_set_rr_reg(struct hinfc_host *host, int index) ++{ ++ int ix; ++ char HYNIX_BG_BDIE_RR_REG[4] = {0xA7, 0xAD, 0xAE, 0xAF}; ++ char value_offset[7][4] = { ++ {0x00, 0x00, 0x00, 0x00}, ++ {0x00, 0x06, 0x0A, 0x06}, ++ {0x7F, -0x03, -0x07, -0x08}, ++ {0x7F, -0x06, -0x0D, -0x0F}, ++ {0x7F, -0x09, -0x14, -0x17}, ++ {0x7F, 0x7F, -0x1A, -0x1E}, ++ {0x7F, 0x7F, -0x20, -0x25} ++ }; ++ char *value = &value_offset[index][0]; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ hinfc_write(host, 1, HINFC610_DATA_NUM); ++ ++ if (!hynix_bg_bdie_rr_org_exist) { ++ ++ for (ix = 0; ix < 4; ix++) { ++ ++ memset(host->chip->IO_ADDR_R, 0xff, 32); ++ ++ hinfc_write(host, 0x37, HINFC610_CMD); ++ hinfc_write(host, HYNIX_BG_BDIE_RR_REG[ix], ++ HINFC610_ADDRL); ++ /* ++ * according to hynix doc, no need to config ++ * HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, HINFC610_READ_1CMD_1ADD_DATA, ++ HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ hynix_bg_bdie_rr_org[ix] ++ = (char)(readl(host->chip->IO_ADDR_R) & 0xff); ++ } ++ hynix_bg_bdie_rr_org_exist = 1; ++ } ++ ++ for (ix = 0; ix < 4; ix++) { ++ if (value[ix] == 0x7F) ++ value[ix] = 0x00; ++ else ++ value[ix] += hynix_bg_bdie_rr_org[ix]; ++ } ++ ++ writel(value[0], host->chip->IO_ADDR_W); ++ hinfc_write(host, HYNIX_BG_BDIE_RR_REG[0], HINFC610_ADDRL); ++ hinfc_write(host, 0x36, HINFC610_CMD); ++ /* ++ * according to hynix doc, no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ for (ix = 1; ix < 4; ix++) { ++ writel(value[ix], host->chip->IO_ADDR_W); ++ hinfc_write(host, HYNIX_BG_BDIE_RR_REG[ix], HINFC610_ADDRL); ++ /* ++ * according to hynix doc, no need to config ++ * HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ } ++ ++ hinfc_write(host, 0x16, HINFC610_CMD); ++ /* ++ * according to hynix doc, only 1 cmd: 0x16. ++ * And no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, HINFC610_WRITE_1CMD_0ADD_NODATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_hynix_bg_bdie_set_rr_param(struct hinfc_host *host, ++ int param) ++{ ++ if (!param) ++ return 0; ++ return hinfc610_hynix_bg_bdie_set_rr_reg(host, param); ++} ++/*****************************************************************************/ ++ ++static int hinfc610_hynix_bg_bdie_reset_rr_param(struct hinfc_host *host) ++{ ++ return hinfc610_hynix_bg_bdie_set_rr_param(host, 0); ++} ++/*****************************************************************************/ ++ ++struct read_retry_t hinfc610_hynix_bg_bdie_read_retry = { ++ .type = NAND_RR_HYNIX_BG_BDIE, ++ .count = 7, ++ .set_rr_param = hinfc610_hynix_bg_bdie_set_rr_param, ++ .get_rr_param = NULL, ++ .reset_rr_param = hinfc610_hynix_bg_bdie_reset_rr_param, ++}; +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_read_retry_hynix_bg_cdie.c b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_hynix_bg_cdie.c +new file mode 100644 +index 0000000..fc39d70 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_hynix_bg_cdie.c +@@ -0,0 +1,225 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++ ++/*****************************************************************************/ ++ ++static char *hinfc610_hynix_bg_cdie_otp_check(char *otp) ++{ ++ int index = 0; ++ int ix, jx; ++ char *ptr = NULL; ++ int min, cur; ++ char *otp_origin, *otp_inverse; ++ ++ min = 64; ++ for (ix = 0; ix < 8; ix++, otp += 128) { ++ ++ otp_origin = otp; ++ otp_inverse = otp + 64; ++ cur = 0; ++ ++ for (jx = 0; jx < 64; jx++, otp_origin++, otp_inverse++) { ++ if (((*otp_origin) ^ (*otp_inverse)) == 0xFF) ++ continue; ++ cur++; ++ } ++ ++ if (cur < min) { ++ min = cur; ++ index = ix; ++ ptr = otp; ++ if (!cur) ++ break; ++ } ++ } ++ ++ pr_info("RR select parameter %d from %d, error %d\n", ++ index, ix, min); ++ return ptr; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_hynix_bg_cdie_get_rr_param(struct hinfc_host *host) ++{ ++ char *otp; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ /* step1: reset the chip */ ++ host->send_cmd_reset(host, host->chipselect); ++ ++ /* step2: cmd: 0x36, address: 0xAE, data: 0x00 */ ++ hinfc_write(host, 1, HINFC610_DATA_NUM);/* data length 1 */ ++ writel(0x00, host->chip->IO_ADDR_R); /* data: 0x00 */ ++ hinfc_write(host, 0xAE, HINFC610_ADDRL);/* address: 0xAE */ ++ hinfc_write(host, 0x36, HINFC610_CMD); /* cmd: 0x36 */ ++ /* according to hynix doc, no need to config ++ * HINFC610_OP_WAIT_READY_EN */ ++ hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /* step3: address: 0xB0, data: 0x4D */ ++ hinfc_write(host, 1, HINFC610_DATA_NUM);/* data length 1 */ ++ writel(0x4D, host->chip->IO_ADDR_R); /* data: 0x4d */ ++ hinfc_write(host, 0xB0, HINFC610_ADDRL);/* address: 0xB0 */ ++ /* only address and data, without cmd */ ++ /* according to hynix doc, no need to config ++ * HINFC610_OP_WAIT_READY_EN */ ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /* step4: cmd: 0x16, 0x17, 0x04, 0x19 */ ++ hinfc_write(host, 0x17 << 8 | 0x16, HINFC610_CMD); ++ /* according to hynix doc, no need to config ++ * HINFC610_OP_WAIT_READY_EN */ ++ hinfc_write(host, HINFC610_WRITE_2CMD_0ADD_NODATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ hinfc_write(host, 0x19 << 8 | 0x04, HINFC610_CMD); ++ /* according to hynix doc, no need to config ++ * HINFC610_OP_WAIT_READY_EN */ ++ hinfc_write(host, HINFC610_WRITE_2CMD_0ADD_NODATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /* step5: cmd: 0x00 0x30, address: 0x02 00 00 00 */ ++ hinfc_write(host, 0x2000000, HINFC610_ADDRL); ++ hinfc_write(host, 0x00, HINFC610_ADDRH); ++ hinfc_write(host, 0x30 << 8 | 0x00, HINFC610_CMD); ++ hinfc_write(host, 0x800, HINFC610_DATA_NUM); ++ /* according to hynix doc, need to config ++ * HINFC610_OP_WAIT_READY_EN */ ++ hinfc_write(host, HINFC610_READ_2CMD_5ADD, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /*step6 save otp read retry table to mem*/ ++ otp = hinfc610_hynix_bg_cdie_otp_check(host->chip->IO_ADDR_R + 2); ++ if (!otp) { ++ pr_err("Read Retry select parameter failed, this Nand Chip maybe invalidation.\n"); ++ return -1; ++ } ++ memcpy(host->rr_data, otp, 64); ++ host->need_rr_data = 1; ++ ++ /* step7: reset the chip */ ++ host->send_cmd_reset(host, host->chipselect); ++ ++ /* step8: cmd: 0x38 */ ++ hinfc_write(host, 0x38, HINFC610_CMD); ++ /* according to hynix doc, need to config HINFC610_OP_WAIT_READY_EN */ ++ hinfc_write(host, HINFC610_WRITE_1CMD_0ADD_NODATA_WAIT_READY, ++ HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ /* get hynix otp table finish */ ++ return 0; ++} ++/*****************************************************************************/ ++static char hinfc610_hynix_bg_cdie_rr_reg[8] = { ++ 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7}; ++ ++static int hinfc610_hynix_bg_cdie_set_rr_reg(struct hinfc_host *host, ++ char *val) ++{ ++ int i; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ hinfc_write(host, 1, HINFC610_DATA_NUM);/* data length 1 */ ++ ++ for (i = 0; i <= 8; i++) { ++ switch (i) { ++ case 0: ++ writel(val[i], host->chip->IO_ADDR_R); ++ hinfc_write(host, ++ hinfc610_hynix_bg_cdie_rr_reg[i], ++ HINFC610_ADDRL); ++ hinfc_write(host, ++ 0x36, HINFC610_CMD); ++ /* ++ * no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, ++ HINFC610_WRITE_1CMD_1ADD_DATA, ++ HINFC610_OP); ++ break; ++ case 8: ++ hinfc_write(host, ++ 0x16, HINFC610_CMD); ++ /* ++ * according to hynix doc, only 1 cmd: 0x16. ++ * And no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, ++ HINFC610_WRITE_1CMD_0ADD_NODATA, ++ HINFC610_OP); ++ break; ++ default: ++ writel(val[i], host->chip->IO_ADDR_R); ++ hinfc_write(host, ++ hinfc610_hynix_bg_cdie_rr_reg[i], ++ HINFC610_ADDRL); ++ /* ++ * no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, ++ HINFC610_WRITE_0CMD_1ADD_DATA, ++ HINFC610_OP); ++ break; ++ } ++ WAIT_CONTROLLER_FINISH(); ++ } ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ return 0; ++} ++ ++/*****************************************************************************/ ++ ++static int hinfc610_hynix_bg_cdie_set_rr_param(struct hinfc_host *host, ++ int param) ++{ ++ unsigned char *rr; ++ ++ if (!(host->rr_data[0] | host->rr_data[1] ++ | host->rr_data[2] | host->rr_data[3]) || !param) ++ return -1; ++ ++ rr = (unsigned char *)&host->rr_data[((param & 0x07) << 3)]; ++ ++ /* set the read retry regs to adjust reading level */ ++ return hinfc610_hynix_bg_cdie_set_rr_reg(host, (char *)rr); ++} ++/*****************************************************************************/ ++ ++static int hinfc610_hynix_bg_cdie_reset_rr_param(struct hinfc_host *host) ++{ ++ return hinfc610_hynix_bg_cdie_set_rr_param(host, 0); ++} ++/*****************************************************************************/ ++ ++struct read_retry_t hinfc610_hynix_bg_cdie_read_retry = { ++ .type = NAND_RR_HYNIX_BG_CDIE, ++ .count = 8, ++ .set_rr_param = hinfc610_hynix_bg_cdie_set_rr_param, ++ .get_rr_param = hinfc610_hynix_bg_cdie_get_rr_param, ++ .reset_rr_param = hinfc610_hynix_bg_cdie_reset_rr_param, ++}; +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_read_retry_hynix_cg_adie.c b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_hynix_cg_adie.c +new file mode 100644 +index 0000000..b7444b8 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_hynix_cg_adie.c +@@ -0,0 +1,234 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++ ++/*****************************************************************************/ ++static char *hinfc610_hynix_cg_adie_otp_check(char *otp) ++{ ++ int index = 0; ++ int ix, jx; ++ char *ptr = NULL; ++ int min, cur; ++ char *otp_origin, *otp_inverse; ++ ++ min = 64; ++ for (ix = 0; ix < 8; ix++, otp += 128) { ++ ++ otp_origin = otp; ++ otp_inverse = otp + 64; ++ cur = 0; ++ ++ for (jx = 0; jx < 64; jx++, otp_origin++, otp_inverse++) { ++ if (((*otp_origin) ^ (*otp_inverse)) == 0xFF) ++ continue; ++ cur++; ++ } ++ ++ if (cur < min) { ++ min = cur; ++ index = ix; ++ ptr = otp; ++ if (!cur) ++ break; ++ } ++ } ++ ++ pr_info("RR select parameter %d from %d, error %d\n", ++ index, ix, min); ++ return ptr; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_hynix_cg_adie_get_rr_param(struct hinfc_host *host) ++{ ++ char *otp; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ /* step1: reset the chip */ ++ host->send_cmd_reset(host, host->chipselect); ++ ++ /* step2: cmd: 0x36, address: 0xFF, data: 0x40 */ ++ hinfc_write(host, 1, HINFC610_DATA_NUM);/* data length 1 */ ++ writel(0x40, host->chip->IO_ADDR_R); /* data: 0x00 */ ++ hinfc_write(host, 0xFF, HINFC610_ADDRL);/* address: 0xAE */ ++ hinfc_write(host, 0x36, HINFC610_CMD); /* cmd: 0x36 */ ++ /* ++ * no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /* step3: address: 0xCC, data: 0x4D */ ++ hinfc_write(host, 1, HINFC610_DATA_NUM);/* data length 1 */ ++ writel(0x4D, host->chip->IO_ADDR_R); /* data: 0x4d */ ++ hinfc_write(host, 0xCC, HINFC610_ADDRL);/* address: 0xB0 */ ++ /* ++ * no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ * only address and data, without cmd ++ */ ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /* step4: cmd: 0x16, 0x17, 0x04, 0x19 */ ++ hinfc_write(host, 0x17 << 8 | 0x16, HINFC610_CMD); ++ /* ++ * no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, HINFC610_WRITE_2CMD_0ADD_NODATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ hinfc_write(host, 0x19 << 8 | 0x04, HINFC610_CMD); ++ /* ++ * no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, HINFC610_WRITE_2CMD_0ADD_NODATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /* step5: cmd: 0x00 0x30, address: 0x02 00 00 00 */ ++ hinfc_write(host, 0x2000000, HINFC610_ADDRL); ++ hinfc_write(host, 0x00, HINFC610_ADDRH); ++ hinfc_write(host, 0x30 << 8 | 0x00, HINFC610_CMD); ++ hinfc_write(host, 0x800, HINFC610_DATA_NUM); ++ /* ++ * need to config HINFC610_OP_WAIT_READY_EN, here config this bit. ++ */ ++ hinfc_write(host, HINFC610_READ_2CMD_5ADD, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /*step6 save otp read retry table to mem*/ ++ otp = hinfc610_hynix_cg_adie_otp_check(host->chip->IO_ADDR_R + 2); ++ if (!otp) { ++ pr_err("Read Retry select parameter failed, this Nand Chip maybe invalidation.\n"); ++ return -1; ++ } ++ memcpy(host->rr_data, otp, 64); ++ host->need_rr_data = 1; ++ ++ /* step7: reset the chip */ ++ host->send_cmd_reset(host, host->chipselect); ++ ++ /* step8: cmd: 0x38 */ ++ hinfc_write(host, 0x38, HINFC610_CMD); ++ /* ++ * need to config HINFC610_OP_WAIT_READY_EN, here config this bit. ++ */ ++ hinfc_write(host, HINFC610_WRITE_1CMD_0ADD_NODATA_WAIT_READY, ++ HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ /* get hynix otp table finish */ ++ return 0; ++} ++/*****************************************************************************/ ++static char hinfc610_hynix_cg_adie__rr_reg[8] = { ++ 0xCC, 0xBF, 0xAA, 0xAB, 0xCD, 0xAD, 0xAE, 0xAF}; ++ ++static int hinfc610_hynix_cg_adie_set_rr_reg(struct hinfc_host *host, char *val) ++{ ++ int i; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ hinfc_write(host, 1, HINFC610_DATA_NUM);/* data length 1 */ ++ ++ for (i = 0; i <= 8; i++) { ++ switch (i) { ++ case 0: ++ writel(val[i], host->chip->IO_ADDR_R); ++ hinfc_write(host, ++ hinfc610_hynix_cg_adie__rr_reg[i], ++ HINFC610_ADDRL); ++ hinfc_write(host, ++ 0x36, HINFC610_CMD); ++ /* ++ * no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, ++ HINFC610_WRITE_1CMD_1ADD_DATA, ++ HINFC610_OP); ++ break; ++ case 8: ++ hinfc_write(host, ++ 0x16, HINFC610_CMD); ++ /* ++ * only have 1 cmd: 0x16 ++ * no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, ++ HINFC610_WRITE_1CMD_0ADD_NODATA, ++ HINFC610_OP); ++ break; ++ default: ++ writel(val[i], host->chip->IO_ADDR_R); ++ hinfc_write(host, ++ hinfc610_hynix_cg_adie__rr_reg[i], ++ HINFC610_ADDRL); ++ /* ++ * no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, ++ HINFC610_WRITE_0CMD_1ADD_DATA, ++ HINFC610_OP); ++ break; ++ } ++ WAIT_CONTROLLER_FINISH(); ++ } ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ return 0; ++} ++ ++/*****************************************************************************/ ++ ++static int hinfc610_hynix_cg_adie_set_rr_param(struct hinfc_host *host, ++ int param) ++{ ++ unsigned char *rr; ++ ++ if (!(host->rr_data[0] | host->rr_data[1] ++ | host->rr_data[2] | host->rr_data[3]) || !param) ++ return -1; ++ ++ rr = (unsigned char *)&host->rr_data[((param & 0x07) << 3)]; ++ ++ /* set the read retry regs to adjust reading level */ ++ return hinfc610_hynix_cg_adie_set_rr_reg(host, (char *)rr); ++} ++/*****************************************************************************/ ++ ++static int hinfc610_hynix_cg_adie_reset_rr_param(struct hinfc_host *host) ++{ ++ return hinfc610_hynix_cg_adie_set_rr_param(host, 0); ++} ++/*****************************************************************************/ ++ ++struct read_retry_t hinfc610_hynix_cg_adie_read_retry = { ++ .type = NAND_RR_HYNIX_CG_ADIE, ++ .count = 8, ++ .set_rr_param = hinfc610_hynix_cg_adie_set_rr_param, ++ .get_rr_param = hinfc610_hynix_cg_adie_get_rr_param, ++ .reset_rr_param = hinfc610_hynix_cg_adie_reset_rr_param, ++}; +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_read_retry_micron.c b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_micron.c +new file mode 100644 +index 0000000..c4c0716 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_micron.c +@@ -0,0 +1,74 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++ ++/*****************************************************************************/ ++ ++#define MICRON_RR_ADDR 0x89 ++ ++static int hinfc610_micron_set_rr_reg(struct hinfc_host *host, int rr) ++{ ++ int regval; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, 1, HINFC610_DATA_NUM); ++ ++ writel(rr, host->chip->IO_ADDR_W); ++ hinfc_write(host, MICRON_RR_ADDR, HINFC610_ADDRL); ++ /* set read retry */ ++ hinfc_write(host, 0xEF, HINFC610_CMD); ++ ++ /* need to config WAIT_READY_EN, here config WAIT_READY_EN bit. */ ++ regval = (HINFC610_IS_SYNC(host) ? ++ HINFC610_WRITE_1CMD_1ADD_DATA_SYNC_WAIT_READY : ++ HINFC610_WRITE_1CMD_1ADD_DATA_WAIT_READY); ++ ++ hinfc_write(host, regval, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ return 0; ++} ++/*****************************************************************************/ ++#undef MICRON_RR_ADDR ++/*****************************************************************************/ ++ ++static int hinfc610_micron_set_rr_param(struct hinfc_host *host, int rr_option) ++{ ++ return hinfc610_micron_set_rr_reg(host, rr_option); ++} ++/*****************************************************************************/ ++ ++static int hinfc610_micron_reset_rr_param(struct hinfc_host *host) ++{ ++ return hinfc610_micron_set_rr_reg(host, 0); ++} ++/*****************************************************************************/ ++ ++struct read_retry_t hinfc610_micron_read_retry = { ++ .type = NAND_RR_MICRON, ++ .count = 8, ++ .set_rr_param = hinfc610_micron_set_rr_param, ++ .get_rr_param = NULL, ++ .reset_rr_param = hinfc610_micron_reset_rr_param, ++}; +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_read_retry_samsung.c b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_samsung.c +new file mode 100644 +index 0000000..6d9adcb +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_samsung.c +@@ -0,0 +1,109 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++ ++/*****************************************************************************/ ++ ++static int hinfc610_samsung_set_rr_reg(struct hinfc_host *host, int param) ++{ ++#define SAMSUNG_RR_CMD 0xA1 ++ int opval; ++ ++ unsigned char samsung_rr_params[15][4] = { ++ {0x00, 0x00, 0x00, 0x00}, ++ {0x05, 0x0A, 0x00, 0x00}, ++ {0x28, 0x00, 0xEC, 0xD8}, ++ {0xED, 0xF5, 0xED, 0xE6}, ++ {0x0A, 0x0F, 0x05, 0x00}, ++ {0x0F, 0x0A, 0xFB, 0xEC}, ++ {0xE8, 0xEF, 0xE8, 0xDC}, ++ {0xF1, 0xFB, 0xFE, 0xF0}, ++ {0x0A, 0x00, 0xFB, 0xEC}, ++ {0xD0, 0xE2, 0xD0, 0xC2}, ++ {0x14, 0x0F, 0xFB, 0xEC}, ++ {0xE8, 0xFB, 0xE8, 0xDC}, ++ {0x1E, 0x14, 0xFB, 0xEC}, ++ {0xFB, 0xFF, 0xFB, 0xF8}, ++ {0x07, 0x0C, 0x02, 0x00} ++ }; ++ ++ if (param >= 15) ++ param = (param % 15); ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ /* no need to config WAIT_READY_EN, here not config WAIT_READY_EN bit */ ++ opval = (HINFC610_IS_SYNC(host) ? HINFC610_WRITE_1CMD_2ADD_DATA_SYNC ++ : HINFC610_WRITE_1CMD_2ADD_DATA); ++ ++ hinfc_write(host, 1, HINFC610_DATA_NUM); ++ ++ writel(samsung_rr_params[param][0], host->chip->IO_ADDR_R); ++ hinfc_write(host, 0xA700, HINFC610_ADDRL); ++ hinfc_write(host, SAMSUNG_RR_CMD, HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(samsung_rr_params[param][1], host->chip->IO_ADDR_R); ++ hinfc_write(host, 0xA400, HINFC610_ADDRL); ++ hinfc_write(host, SAMSUNG_RR_CMD, HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(samsung_rr_params[param][2], host->chip->IO_ADDR_R); ++ hinfc_write(host, 0xA500, HINFC610_ADDRL); ++ hinfc_write(host, SAMSUNG_RR_CMD, HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(samsung_rr_params[param][3], host->chip->IO_ADDR_R); ++ hinfc_write(host, 0xA600, HINFC610_ADDRL); ++ hinfc_write(host, SAMSUNG_RR_CMD, HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ return 0; ++ ++#undef SAMSUNG_RR_CMD ++} ++/*****************************************************************************/ ++ ++static int hinfc610_samsung_set_rr_param(struct hinfc_host *host, int param) ++{ ++ return hinfc610_samsung_set_rr_reg(host, param); ++} ++/*****************************************************************************/ ++ ++static int hinfc610_samsung_reset_rr_param(struct hinfc_host *host) ++{ ++ return hinfc610_samsung_set_rr_reg(host, 0); ++} ++/*****************************************************************************/ ++ ++struct read_retry_t hinfc610_samsung_read_retry = { ++ .type = NAND_RR_SAMSUNG, ++ .count = 15, ++ .set_rr_param = hinfc610_samsung_set_rr_param, ++ .get_rr_param = NULL, ++ .reset_rr_param = hinfc610_samsung_reset_rr_param, ++}; ++ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_read_retry_toshiba.c b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_toshiba.c +new file mode 100644 +index 0000000..0a1a87e +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_toshiba.c +@@ -0,0 +1,113 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++ ++/*****************************************************************************/ ++ ++static int hinfc610_toshiba_24nm_set_rr_reg(struct hinfc_host *host, int param) ++{ ++#define TOSHIBA_RR_CMD 0x55 ++ int opval; ++ static char toshiba_rr_param[] = {0x00, 0x04, 0x7c, 0x78, 0x74, 0x08}; ++ ++ if (!param) { ++ host->send_cmd_reset(host, host->chipselect); ++ return 0; ++ } ++ ++ if (param >= 6) ++ param = (param % 6); ++ ++ /* ++ * no need to config WAIT_READY_EN, here not config WAIT_READY_EN ++ */ ++ opval = (HINFC610_IS_SYNC(host) ? HINFC610_WRITE_1CMD_1ADD_DATA_SYNC ++ : HINFC610_WRITE_1CMD_1ADD_DATA); ++ ++ hinfc_write(host, 1, HINFC610_DATA_NUM); ++ ++ writel(toshiba_rr_param[param], host->chip->IO_ADDR_R); ++ hinfc_write(host, 0x4, HINFC610_ADDRL); ++ hinfc_write(host, TOSHIBA_RR_CMD, HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(toshiba_rr_param[param], host->chip->IO_ADDR_R); ++ hinfc_write(host, 0x5, HINFC610_ADDRL); ++ hinfc_write(host, TOSHIBA_RR_CMD, HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(toshiba_rr_param[param], host->chip->IO_ADDR_R); ++ hinfc_write(host, 0x6, HINFC610_ADDRL); ++ hinfc_write(host, TOSHIBA_RR_CMD, HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(toshiba_rr_param[param], host->chip->IO_ADDR_R); ++ hinfc_write(host, 0x7, HINFC610_ADDRL); ++ hinfc_write(host, TOSHIBA_RR_CMD, HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ return 0; ++ ++#undef TOSHIBA_RR_CMD ++} ++/*****************************************************************************/ ++ ++static int hinfc610_toshiba_24nm_set_rr_param(struct hinfc_host *host, ++ int param) ++{ ++ int opval; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ opval = (HINFC610_IS_SYNC(host) ? HINFC610_WRITE_2CMD_0ADD_NODATA_SYNC ++ : HINFC610_WRITE_2CMD_0ADD_NODATA); ++ ++ hinfc_write(host, HINFC_CMD_SEQ(0x5C, 0xC5), HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ hinfc610_toshiba_24nm_set_rr_reg(host, param); ++ ++ hinfc_write(host, HINFC_CMD_SEQ(0x26, 0x5D), HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_toshiba_24nm_reset_rr_param(struct hinfc_host *host) ++{ ++ return hinfc610_toshiba_24nm_set_rr_reg(host, 0); ++} ++/*****************************************************************************/ ++struct read_retry_t hinfc610_toshiba_24nm_read_retry = { ++ .type = NAND_RR_TOSHIBA_24nm, ++ .count = 6, ++ .set_rr_param = hinfc610_toshiba_24nm_set_rr_param, ++ .get_rr_param = NULL, ++ .reset_rr_param = hinfc610_toshiba_24nm_reset_rr_param, ++}; +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_sync.c b/drivers/mtd/nand/hinfc610/hinfc610_sync.c +new file mode 100644 +index 0000000..c389d98 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_sync.c +@@ -0,0 +1,187 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hinfc610_os.h" ++#include "hinfc610_gen.h" ++#include "hinfc610.h" ++#include "hinfc610_sync.h" ++ ++static struct nand_sync *nand_sync_table[] = { ++ &hinfc610_sync_onfi_23, ++ &hinfc610_sync_onfi_30, ++ &hinfc610_sync_toggle_10, ++ NULL, ++}; ++ ++static struct nand_sync *hinfc610_find_sync_type(int type) ++{ ++ struct nand_sync **sync; ++ ++ for (sync = nand_sync_table; sync; sync++) { ++ if ((*sync)->type == type) ++ return *sync; ++ } ++ ++ return NULL; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_onfi_support_sync(struct hinfc_host *host) ++{ ++ char buf[6] = {0}; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, sizeof(buf), HINFC610_DATA_NUM); ++ hinfc_write(host, NAND_CMD_READID, HINFC610_CMD); ++ hinfc_write(host, 0x20, HINFC610_ADDRL); ++ hinfc_write(host, HINFC610_READ_1CMD_1ADD_DATA, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ memcpy(buf, host->chip->IO_ADDR_R, sizeof(buf)); ++ ++ if (memcmp(buf, "ONFI", 4)) ++ return 0; ++ ++ hinfc_write(host, sizeof(buf), HINFC610_DATA_NUM); ++ hinfc_write(host, NAND_CMD_READID, HINFC610_CMD); ++ hinfc_write(host, 0x40, HINFC610_ADDRL); ++ hinfc_write(host, HINFC610_READ_1CMD_1ADD_DATA, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ memcpy(buf, host->chip->IO_ADDR_R, sizeof(buf)); ++ ++ if (memcmp(buf, "JEDEC", 5)) ++ return 0; ++ ++ return (buf[5] == 0x05); ++} ++/*****************************************************************************/ ++ ++static int hinfc610_get_onfi_info(struct hinfc_host *host, int *type) ++{ ++ char buf[6] = {0}; ++ ++ *type = 0; ++ ++ if (!hinfc610_onfi_support_sync(host)) ++ return 0; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, sizeof(buf), HINFC610_DATA_NUM); ++ hinfc_write(host, NAND_CMD_PARAM, HINFC610_CMD); ++ hinfc_write(host, 0x00, HINFC610_ADDRL); ++ hinfc_write(host, HINFC610_READ_1CMD_1ADD_DATA, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ memcpy(buf, host->chip->IO_ADDR_R, sizeof(buf)); ++ ++ if (memcmp(buf, "ONFI", 4)) ++ return 0; ++ ++ if (buf[4] & (1 << 6)) ++ *type = NAND_TYPE_ONFI_30; ++ else if (buf[4] & (1 << 5) || ++ buf[4] & (1 << 4) || ++ buf[4] & (1 << 3) || ++ buf[4] & (1 << 2)) ++ *type = NAND_TYPE_ONFI_23; ++ ++ return 1; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_toggle_support_sync(struct hinfc_host *host) ++{ ++ char buf[6] = {0}; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, sizeof(buf), HINFC610_DATA_NUM); ++ hinfc_write(host, NAND_CMD_READID, HINFC610_CMD); ++ hinfc_write(host, 0x40, HINFC610_ADDRL); ++ hinfc_write(host, HINFC610_READ_1CMD_1ADD_DATA, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ ++ memcpy(buf, host->chip->IO_ADDR_R, sizeof(buf)); ++ ++ if (memcmp(buf, "JEDEC", 5)) ++ return 0; ++ ++ return 1; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_get_toggle_info(struct hinfc_host *host, int *type) ++{ ++ char buf[8] = {0}; ++ ++ *type = 0; ++ ++ if (!hinfc610_toggle_support_sync(host)) ++ return 0; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, sizeof(buf), HINFC610_DATA_NUM); ++ hinfc_write(host, NAND_CMD_PARAM, HINFC610_CMD); ++ hinfc_write(host, 0x40, HINFC610_ADDRL); ++ hinfc_write(host, HINFC610_READ_1CMD_1ADD_DATA, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ ++ memcpy(buf, host->chip->IO_ADDR_R, sizeof(buf)); ++ ++ if (memcmp(buf, "JESD", 4)) ++ return 0; ++ ++ if (buf[4] & (1 << 1)) ++ /* supports revision 1.0 */ ++ *type = NAND_TYPE_TOGGLE_10; ++ else ++ pr_warn("sync NAND has unknown toggle revision.\n"); ++ ++ return 1; ++} ++/*****************************************************************************/ ++ ++int hinfc610_get_sync_info(struct hinfc_host *host) ++{ ++ int type = 0; ++ ++ if (IS_NAND_ONFI(host)) ++ hinfc610_get_onfi_info(host, &type); ++ else ++ hinfc610_get_toggle_info(host, &type); ++ ++ if (!type) { ++ host->flags &= ~NAND_MODE_SYNC_ASYNC; ++ return 0; ++ } ++ ++ host->sync = hinfc610_find_sync_type(type); ++ if (!host->sync) ++ PR_BUG(ERSTR_DRIVER ++ "This Nand Flash need to enable the 'synchronous' feature. " ++ "but the driver dose not offer the feature"); ++ ++ return 0; ++} ++/*****************************************************************************/ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_sync.h b/drivers/mtd/nand/hinfc610/hinfc610_sync.h +new file mode 100644 +index 0000000..906fd10 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_sync.h +@@ -0,0 +1,25 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef HINFC610_SYNC_H ++#define HINFC610_SYNC_H ++ ++int hinfc610_get_sync_info(struct hinfc_host *host); ++ ++#endif /* HINFC610_SYNC_H */ ++ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_sync_onfi_23.c b/drivers/mtd/nand/hinfc610/hinfc610_sync_onfi_23.c +new file mode 100644 +index 0000000..8fba306 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_sync_onfi_23.c +@@ -0,0 +1,107 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++ ++/*****************************************************************************/ ++ ++static int hinfc610_onfi_enable_sync(struct nand_chip *chip) ++{ ++ struct hinfc_host *host = chip->priv; ++ unsigned char micron_sync_param[4] = { ++ 0x14, /* set sync mode timing */ 0x00, 0x00, 0x00, ++ }; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, 1, HINFC610_DATA_NUM); ++ hinfc_write(host, 0xEF, HINFC610_CMD); ++ hinfc_write(host, 0x01, HINFC610_ADDRL); ++ writel(micron_sync_param[0], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(micron_sync_param[1], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(micron_sync_param[2], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /* need to config WAIT_READY_EN, here config this bit. */ ++ writel(micron_sync_param[3], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_WAIT_READY, ++ HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++ ++static int hinfc610_onfi_disable_sync(struct nand_chip *chip) ++{ ++ struct hinfc_host *host = chip->priv; ++ unsigned char micron_sync_param[4] = { ++ 0x00, 0x00, 0x00, 0x00, ++ }; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, 1, HINFC610_DATA_NUM); ++ hinfc_write(host, 0xEF, HINFC610_CMD); ++ hinfc_write(host, 0x01, HINFC610_ADDRL); ++ writel(micron_sync_param[0], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA_SYNC, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(micron_sync_param[1], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_SYNC, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(micron_sync_param[2], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_SYNC, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(micron_sync_param[3], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_SYNC_WAIT_READY, ++ HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++struct nand_sync hinfc610_sync_onfi_23 = { ++ .type = NAND_TYPE_ONFI_23, ++ .enable = hinfc610_onfi_enable_sync, ++ .disable = hinfc610_onfi_disable_sync, ++}; ++ ++struct nand_sync hinfc610_sync_onfi_30 = { ++ .type = NAND_TYPE_ONFI_30, ++ .enable = hinfc610_onfi_enable_sync, ++ .disable = hinfc610_onfi_disable_sync, ++}; +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_sync_toggle.c b/drivers/mtd/nand/hinfc610/hinfc610_sync_toggle.c +new file mode 100644 +index 0000000..918b210 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_sync_toggle.c +@@ -0,0 +1,101 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++ ++/*****************************************************************************/ ++ ++static int hinfc610_toggle_enable_sync(struct nand_chip *chip) ++{ ++ struct hinfc_host *host = chip->priv; ++ unsigned char toshiba_sync_param[4] = { ++ 0x00, 0x00, 0x00, 0x00, ++ }; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, 1, HINFC610_DATA_NUM); ++ hinfc_write(host, 0xEF, HINFC610_CMD); ++ hinfc_write(host, 0x80, HINFC610_ADDRL); ++ writel(toshiba_sync_param[0], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(toshiba_sync_param[1], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(toshiba_sync_param[2], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /* need to config WAIT_READY_EN. */ ++ writel(toshiba_sync_param[3], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_WAIT_READY, ++ HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_toggle_disable_sync(struct nand_chip *chip) ++{ ++ struct hinfc_host *host = chip->priv; ++ unsigned char toshiba_sync_param[4] = { ++ 0x01, 0x00, 0x00, 0x00, ++ }; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, 1, HINFC610_DATA_NUM); ++ hinfc_write(host, 0xEF, HINFC610_CMD); ++ hinfc_write(host, 0x80, HINFC610_ADDRL); ++ writel(toshiba_sync_param[0], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA_SYNC, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(toshiba_sync_param[1], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_SYNC, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(toshiba_sync_param[2], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_SYNC, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /* need to config WAIT_READY_EN */ ++ writel(toshiba_sync_param[3], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_SYNC_WAIT_READY, ++ HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++struct nand_sync hinfc610_sync_toggle_10 = { ++ .type = NAND_TYPE_TOGGLE_10, ++ .enable = hinfc610_toggle_enable_sync, ++ .disable = hinfc610_toggle_disable_sync, ++}; +diff --git a/drivers/mtd/nand/hinfc610/hinfc620_gen.c b/drivers/mtd/nand/hinfc610/hinfc620_gen.c +new file mode 100644 +index 0000000..a1e68f8 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc620_gen.c +@@ -0,0 +1,78 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "../match_table.h" ++#include "hinfc620_gen.h" ++ ++/*****************************************************************************/ ++ ++static struct match_reg_type page_type2reg[] = { ++ { ++ hinfc620_pagesize_2K, NAND_PAGE_2K, ++ }, { ++ hinfc620_pagesize_4K, NAND_PAGE_4K, ++ }, { ++ hinfc620_pagesize_8K, NAND_PAGE_8K, ++ }, { ++ hinfc620_pagesize_16K, NAND_PAGE_16K, ++ }, { ++ hinfc620_pagesize_32K, NAND_PAGE_32K, ++ } ++}; ++ ++enum hinfc620_page_reg hinfc620_page_type2reg(int type) ++{ ++ return type2reg(page_type2reg, ARRAY_SIZE(page_type2reg), type, 0); ++} ++ ++int hinfc620_page_reg2type(enum hinfc620_page_reg reg) ++{ ++ return reg2type(page_type2reg, ARRAY_SIZE(page_type2reg), reg, 0); ++} ++/*****************************************************************************/ ++ ++static struct match_reg_type ecc_type2reg[] = { ++ { ++ hinfc620_ecc_none, NAND_ECC_NONE, ++ }, { ++ hinfc620_ecc_8bit, NAND_ECC_4BIT_512, ++ }, { ++ hinfc620_ecc_16bit, NAND_ECC_8BIT_512, ++ }, { ++ hinfc620_ecc_24bit, NAND_ECC_24BIT, ++ }, { ++ hinfc620_ecc_40bit, NAND_ECC_40BIT, ++ }, { ++ hinfc620_ecc_64bit, NAND_ECC_64BIT, ++ }, { ++ hinfc620_ecc_28bit, NAND_ECC_28BIT, ++ }, { ++ hinfc620_ecc_42bit, NAND_ECC_42BIT, ++ } ++}; ++ ++enum hinfc620_ecc_reg hinfc620_ecc_type2reg(int type) ++{ ++ return type2reg(ecc_type2reg, ARRAY_SIZE(ecc_type2reg), type, 0); ++} ++ ++int hinfc620_ecc_reg2type(enum hinfc620_ecc_reg reg) ++{ ++ return reg2type(ecc_type2reg, ARRAY_SIZE(ecc_type2reg), reg, 0); ++} ++ +diff --git a/drivers/mtd/nand/hinfc610/hinfc620_gen.h b/drivers/mtd/nand/hinfc610/hinfc620_gen.h +new file mode 100644 +index 0000000..88fb1e4 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc620_gen.h +@@ -0,0 +1,53 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef HINFC620_GENH ++#define HINFC620_GENH ++/******************************************************************************/ ++ ++#include "../hinfc_gen.h" ++ ++enum hinfc620_ecc_reg { ++ hinfc620_ecc_none = 0x00, ++ hinfc620_ecc_8bit = 0x02, ++ hinfc620_ecc_16bit = 0x03, ++ hinfc620_ecc_24bit = 0x04, ++ hinfc620_ecc_40bit = 0x05, ++ hinfc620_ecc_64bit = 0x06, ++ hinfc620_ecc_28bit = 0x07, ++ hinfc620_ecc_42bit = 0x08, ++}; ++ ++enum hinfc620_page_reg { ++ hinfc620_pagesize_2K = 0x01, ++ hinfc620_pagesize_4K = 0x02, ++ hinfc620_pagesize_8K = 0x03, ++ hinfc620_pagesize_16K = 0x04, ++ hinfc620_pagesize_32K = 0x05, ++}; ++ ++enum hinfc620_page_reg hinfc620_page_type2reg(int type); ++ ++int hinfc620_page_reg2type(enum hinfc620_page_reg reg); ++ ++enum hinfc620_ecc_reg hinfc620_ecc_type2reg(int type); ++ ++int hinfc620_ecc_reg2type(enum hinfc620_ecc_reg reg); ++ ++/******************************************************************************/ ++#endif /* HINFC620_GENH */ +diff --git a/drivers/mtd/nand/hinfc_gen.c b/drivers/mtd/nand/hinfc_gen.c +new file mode 100644 +index 0000000..d899ff4 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc_gen.c +@@ -0,0 +1,244 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include "match_table.h" ++#include "hinfc_gen.h" ++ ++/*****************************************************************************/ ++struct nand_flash_dev *(*get_spi_nand_flash_type_hook)(struct mtd_info *mtd, ++ unsigned char *id) = NULL; ++ ++/*****************************************************************************/ ++static struct match_t match_ecc[] = { ++ MATCH_SET_TYPE_DATA(NAND_ECC_NONE, "none"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_0BIT, "none"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_1BIT_512, "1bit/512"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_4BIT, "4bit/512"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_4BIT_512, "4bit/512"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_4BYTE, "4byte/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_8BIT, "4bit/512"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_8BIT_512, "8bit/512"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_8BYTE, "8byte/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_13BIT, "13bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_16BIT, "8bit/512"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_18BIT, "18bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_24BIT, "24bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_27BIT, "27bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_32BIT, "32bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_40BIT, "40bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_41BIT, "41bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_48BIT, "48bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_60BIT, "60bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_72BIT, "72bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_80BIT, "80bit/1k"), ++}; ++ ++const char *nand_ecc_name(int type) ++{ ++ return (char *)match_type_to_data(match_ecc, ARRAY_SIZE(match_ecc), ++ type, "unknown"); ++} ++ ++char *get_ecctype_str(enum ecc_type ecctype) ++{ ++ static char *ecctype_string[] = { ++ "None", "1bit/512Byte", "4bits/512Byte", "8bits/512Byte", ++ "24bits/1K", "40bits/1K", "unknown", "unknown"}; ++ return ecctype_string[(ecctype & 0x07)]; ++} ++ ++/*****************************************************************************/ ++static struct match_type_str page2name[] = { ++ { NAND_PAGE_512B, "512" }, ++ { NAND_PAGE_2K, "2K" }, ++ { NAND_PAGE_4K, "4K" }, ++ { NAND_PAGE_8K, "8K" }, ++ { NAND_PAGE_16K, "16K" }, ++ { NAND_PAGE_32K, "32K" }, ++}; ++ ++const char *nand_page_name(int type) ++{ ++ return type2str(page2name, ARRAY_SIZE(page2name), type, "unknown"); ++} ++ ++char *get_pagesize_str(enum page_type pagetype) ++{ ++ static char *pagesize_str[] = { ++ "512", "2K", "4K", "8K", "16K", "unknown", ++ "unknown", "unknown"}; ++ return pagesize_str[(pagetype & 0x07)]; ++} ++ ++/*****************************************************************************/ ++static struct match_reg_type page2size[] = { ++ { _512B, NAND_PAGE_512B }, ++ { _2K, NAND_PAGE_2K }, ++ { _4K, NAND_PAGE_4K }, ++ { _8K, NAND_PAGE_8K }, ++ { _16K, NAND_PAGE_16K }, ++ { _32K, NAND_PAGE_32K }, ++}; ++ ++unsigned int get_pagesize(enum page_type pagetype) ++{ ++ unsigned int pagesize[] = { ++ _512B, _2K, _4K, _8K, _16K, 0, 0, 0}; ++ return pagesize[(pagetype & 0x07)]; ++} ++ ++int nandpage_size2type(int size) ++{ ++ return reg2type(page2size, ARRAY_SIZE(page2size), size, NAND_PAGE_2K); ++} ++ ++int nandpage_type2size(int size) ++{ ++ return type2reg(page2size, ARRAY_SIZE(page2size), size, NAND_PAGE_2K); ++} ++ ++char *nand_dbgfs_options; ++ ++static int __init dbgfs_options_setup(char *s) ++{ ++ nand_dbgfs_options = s; ++ return 1; ++} ++__setup("nanddbgfs=", dbgfs_options_setup); ++ ++/*****************************************************************************/ ++ ++int get_bits(unsigned int n) ++{ ++ int loop; ++ int ret = 0; ++ ++ if (!n) ++ return 0; ++ ++ if (n > 0xFFFF) ++ loop = n > 0xFFFFFF ? 32 : 24; ++ else ++ loop = n > 0xFF ? 16 : 8; ++ ++ while (loop-- > 0 && n) { ++ if (n & 1) ++ ret++; ++ n >>= 1; ++ } ++ return ret; ++} ++ ++/*****************************************************************************/ ++#define et_ecc_none 0x00 ++#define et_ecc_4bit 0x02 ++#define et_ecc_8bit 0x03 ++#define et_ecc_24bit1k 0x04 ++#define et_ecc_40bit1k 0x05 ++#define et_ecc_64bit1k 0x06 ++ ++static struct match_reg_type ecc_yaffs_type_t[] = { ++ {et_ecc_none, NAND_ECC_0BIT}, ++ {et_ecc_4bit, NAND_ECC_8BIT}, ++ {et_ecc_8bit, NAND_ECC_16BIT}, ++ {et_ecc_24bit1k, NAND_ECC_24BIT}, ++ {et_ecc_40bit1k, NAND_ECC_40BIT}, ++ {et_ecc_64bit1k, NAND_ECC_64BIT} ++}; ++ ++unsigned char match_ecc_type_to_yaffs(unsigned char type) ++{ ++ return type2reg(ecc_yaffs_type_t, ARRAY_SIZE(ecc_yaffs_type_t), type, ++ et_ecc_4bit); ++} ++ ++/*****************************************************************************/ ++static struct match_t page_table[] = { ++ {NAND_PAGE_2K, PAGE_SIZE_2KB, "2K"}, ++ {NAND_PAGE_4K, PAGE_SIZE_4KB, "4K"}, ++ {NAND_PAGE_8K, PAGE_SIZE_8KB, "8K"}, ++ {NAND_PAGE_16K, PAGE_SIZE_16KB, "16K"}, ++}; ++ ++unsigned char match_page_reg_to_type(unsigned char reg) ++{ ++ return match_reg_to_type(page_table, ARRAY_SIZE(page_table), reg, ++ NAND_PAGE_2K); ++} ++ ++unsigned char match_page_type_to_reg(unsigned char type) ++{ ++ return match_type_to_reg(page_table, ARRAY_SIZE(page_table), type, ++ PAGE_SIZE_2KB); ++} ++ ++const char *match_page_type_to_str(unsigned char type) ++{ ++ return match_type_to_data(page_table, ARRAY_SIZE(page_table), type, ++ "unknown"); ++} ++ ++/*****************************************************************************/ ++static struct match_t ecc_table[] = { ++ {NAND_ECC_0BIT, ECC_TYPE_0BIT, "none"}, ++ {NAND_ECC_8BIT, ECC_TYPE_8BIT, "4bit/512"}, ++ {NAND_ECC_16BIT, ECC_TYPE_16BIT, "8bit/512"}, ++ {NAND_ECC_24BIT, ECC_TYPE_24BIT, "24bit/1K"}, ++ {NAND_ECC_28BIT, ECC_TYPE_28BIT, "28bit/1K"}, ++ {NAND_ECC_40BIT, ECC_TYPE_40BIT, "40bit/1K"}, ++ {NAND_ECC_64BIT, ECC_TYPE_64BIT, "64bit/1K"}, ++}; ++ ++unsigned char match_ecc_reg_to_type(unsigned char reg) ++{ ++ return match_reg_to_type(ecc_table, ARRAY_SIZE(ecc_table), reg, ++ NAND_ECC_8BIT); ++} ++ ++unsigned char match_ecc_type_to_reg(unsigned char type) ++{ ++ return match_type_to_reg(ecc_table, ARRAY_SIZE(ecc_table), type, ++ ECC_TYPE_8BIT); ++} ++ ++const char *match_ecc_type_to_str(unsigned char type) ++{ ++ return match_type_to_data(ecc_table, ARRAY_SIZE(ecc_table), type, ++ "unknown"); ++} ++ ++/*****************************************************************************/ ++static struct match_t page_type_size_table[] = { ++ {NAND_PAGE_2K, _2K, NULL}, ++ {NAND_PAGE_4K, _4K, NULL}, ++ {NAND_PAGE_8K, _8K, NULL}, ++ {NAND_PAGE_16K, _16K, NULL}, ++}; ++ ++unsigned char match_page_size_to_type(unsigned int size) ++{ ++ return match_reg_to_type(page_type_size_table, ++ ARRAY_SIZE(page_type_size_table), size, NAND_PAGE_2K); ++} ++ ++unsigned int match_page_type_to_size(unsigned char type) ++{ ++ return match_type_to_reg(page_type_size_table, ++ ARRAY_SIZE(page_type_size_table), type, _2K); ++} +diff --git a/drivers/mtd/nand/hinfc_gen.h b/drivers/mtd/nand/hinfc_gen.h +new file mode 100644 +index 0000000..3d08c70 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc_gen.h +@@ -0,0 +1,294 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef __HINFC_GEN_H__ ++#define __HINFC_GEN_H__ ++ ++/*****************************************************************************/ ++#include ++#include ++#include ++#include ++#include ++ ++/*****************************************************************************/ ++#define HINFC_VER_300 (0x300) ++#define HINFC_VER_301 (0x301) ++#define HINFC_VER_310 (0x310) ++#define HINFC_VER_504 (0x504) ++#define HINFC_VER_505 (0x505) ++#define HINFC_VER_600 (0x600) ++#define HINFC_VER_610 (0x610) ++#define HINFC_VER_620 (0x620) ++ ++#define HISNFC_VER_100 (0x400) ++ ++/*****************************************************************************/ ++#define NAND_PAGE_512B 0 ++#define NAND_PAGE_1K 1 ++#define NAND_PAGE_2K 2 ++#define NAND_PAGE_4K 3 ++#define NAND_PAGE_8K 4 ++#define NAND_PAGE_16K 5 ++#define NAND_PAGE_32K 6 ++ ++/*****************************************************************************/ ++#define NAND_ECC_NONE 0 ++#define NAND_ECC_0BIT 0 ++#define NAND_ECC_1BIT 1 ++#define NAND_ECC_1BIT_512 1 ++#define NAND_ECC_4BIT 2 ++#define NAND_ECC_4BIT_512 2 ++#define NAND_ECC_4BYTE 2 ++#define NAND_ECC_8BIT 2 ++#define NAND_ECC_8BIT_512 3 ++#define NAND_ECC_8BYTE 3 ++#define NAND_ECC_13BIT 4 ++#define NAND_ECC_16BIT 5 ++#define NAND_ECC_18BIT 6 ++#define NAND_ECC_24BIT 7 ++#define NAND_ECC_27BIT 8 ++#define NAND_ECC_28BIT 9 ++#define NAND_ECC_32BIT 10 ++#define NAND_ECC_40BIT 11 ++#define NAND_ECC_41BIT 12 ++#define NAND_ECC_42BIT 13 ++#define NAND_ECC_48BIT 14 ++#define NAND_ECC_60BIT 15 ++#define NAND_ECC_64BIT 16 ++#define NAND_ECC_72BIT 17 ++#define NAND_ECC_80BIT 18 ++ ++enum ecc_type { ++ et_ecc_none = 0x00, ++ et_ecc_1bit = 0x01, ++ et_ecc_4bit = 0x02, ++ et_ecc_8bit = 0x03, ++ et_ecc_24bit1k = 0x04, ++ et_ecc_40bit1k = 0x05, ++ et_ecc_64bit1k = 0x06, ++}; ++ ++enum page_type { ++ pt_pagesize_512 = 0x00, ++ pt_pagesize_2K = 0x01, ++ pt_pagesize_4K = 0x02, ++ pt_pagesize_8K = 0x03, ++ pt_pagesize_16K = 0x04, ++}; ++ ++/*****************************************************************************/ ++struct nand_config_info { ++ unsigned int pagetype; ++ unsigned int ecctype; ++ unsigned int ecc_strength; ++ unsigned int oobsize; ++ struct mtd_ooblayout_ops *ooblayout_ops; ++}; ++ ++struct hinfc_host; ++ ++struct nand_sync { ++ ++#define SET_NAND_SYNC_TYPE(_mfr, _onfi, _version) \ ++ ((((_mfr) & 0xFF) << 16) | (((_version) & 0xFF) << 8) \ ++ | ((_onfi) & 0xFF)) ++ ++#define GET_NAND_SYNC_TYPE_MFR(_type) (((_type) >> 16) & 0xFF) ++#define GET_NAND_SYNC_TYPE_VER(_type) (((_type) >> 8) & 0xFF) ++#define GET_NAND_SYNC_TYPE_INF(_type) ((_type) & 0xFF) ++ ++#define NAND_TYPE_ONFI_23_MICRON \ ++ SET_NAND_SYNC_TYPE(NAND_MFR_MICRON, NAND_IS_ONFI, 0x23) ++#define NAND_TYPE_ONFI_30_MICRON \ ++ SET_NAND_SYNC_TYPE(NAND_MFR_MICRON, NAND_IS_ONFI, 0x30) ++#define NAND_TYPE_TOGGLE_TOSHIBA \ ++ SET_NAND_SYNC_TYPE(NAND_MFR_TOSHIBA, 0, 0) ++#define NAND_TYPE_TOGGLE_SAMSUNG \ ++ SET_NAND_SYNC_TYPE(NAND_MFR_SAMSUNG, 0, 0) ++ ++#define NAND_TYPE_TOGGLE_10 SET_NAND_SYNC_TYPE(0, 0, 0x10) ++#define NAND_TYPE_ONFI_30 SET_NAND_SYNC_TYPE(0, NAND_IS_ONFI, 0x30) ++#define NAND_TYPE_ONFI_23 SET_NAND_SYNC_TYPE(0, NAND_IS_ONFI, 0x23) ++ ++ int type; ++ int (*enable)(struct nand_chip *chip); ++ int (*disable)(struct nand_chip *chip); ++}; ++ ++struct read_retry_t { ++ int type; ++ int count; ++ int (*set_rr_param)(struct hinfc_host *host, int param); ++ int (*get_rr_param)(struct hinfc_host *host); ++ int (*reset_rr_param)(struct hinfc_host *host); ++}; ++ ++struct ecc_info_t { ++ int pagesize; ++ int ecctype; ++ int threshold; ++ int section; ++ void (*dump)(struct hinfc_host *host, unsigned char ecc[], ++ int *max_bitsflag); ++}; ++ ++struct nand_dev_t { ++ struct nand_flash_dev flash_dev; ++ ++ char *start_type; ++ unsigned char ids[8]; ++ int oobsize; ++ int ecctype; ++ ++ /* (Controller) support ecc/page detect, driver don't need detect */ ++#define NANDC_HW_AUTO 0x01 ++ /* (Controller) support ecc/page detect, ++ * and current ecc/page config finish */ ++#define NANDC_CONFIG_DONE 0x02 ++ /* (Controller) is sync, default is async */ ++#define NANDC_IS_SYNC_BOOT 0x04 ++ ++/* (NAND) need randomizer */ ++#define NAND_RANDOMIZER 0x10 ++/* (NAND) is ONFI interface, combine with sync/async symble */ ++#define NAND_IS_ONFI 0x20 ++/* (NAND) support async and sync, such micron onfi, toshiba toggle 1.0 */ ++#define NAND_MODE_SYNC_ASYNC 0x40 ++/* (NAND) support only sync, such samsung sync. */ ++#define NAND_MODE_ONLY_SYNC 0x80 ++ ++#define NAND_CHIP_MICRON (NAND_MODE_SYNC_ASYNC | NAND_IS_ONFI) ++/* This NAND is async, or sync/async, default is async mode, ++ * toggle1.0 interface */ ++#define NAND_CHIP_TOSHIBA_TOGGLE_10 (NAND_MODE_SYNC_ASYNC) ++/* This NAND is only sync mode, toggle2.0 interface */ ++#define NAND_CHIP_TOSHIBA_TOGGLE_20 (NAND_MODE_ONLY_SYNC) ++/* This NAND is only sync mode */ ++#define NAND_CHIP_SAMSUNG (NAND_MODE_ONLY_SYNC) ++ ++ unsigned int flags; ++ ++#define NAND_RR_NONE 0x00 ++#define NAND_RR_HYNIX_BG_BDIE 0x10 ++#define NAND_RR_HYNIX_BG_CDIE 0x11 ++#define NAND_RR_HYNIX_CG_ADIE 0x12 ++#define NAND_RR_MICRON 0x20 ++#define NAND_RR_SAMSUNG 0x30 ++#define NAND_RR_TOSHIBA_24nm 0x40 ++#define NAND_RR_TOSHIBA_19nm 0x41 ++ int read_retry_type; ++}; ++ ++/*****************************************************************************/ ++ ++#define IS_NANDC_HW_AUTO(_host) ((_host)->flags & NANDC_HW_AUTO) ++#define IS_NANDC_CONFIG_DONE(_host) ((_host)->flags & NANDC_CONFIG_DONE) ++#define IS_NANDC_SYNC_BOOT(_host) ((_host)->flags & NANDC_IS_SYNC_BOOT) ++ ++#define IS_NAND_RANDOM(_dev) ((_dev)->flags & NAND_RANDOMIZER) ++#define IS_NAND_ONLY_SYNC(_dev) ((_dev)->flags & NAND_MODE_ONLY_SYNC) ++#define IS_NAND_SYNC_ASYNC(_dev) ((_dev)->flags & NAND_MODE_SYNC_ASYNC) ++#define IS_NAND_ONFI(_dev) ((_dev)->flags & NAND_IS_ONFI) ++ ++#define ERSTR_HARDWARE "Hardware configuration error. " ++#define ERSTR_DRIVER "Driver does not support. " ++ ++#define ENABLE 1 ++#define DISABLE 0 ++ ++/*****************************************************************************/ ++ ++char *get_ecctype_str(enum ecc_type ecctype); ++ ++char *get_pagesize_str(enum page_type pagetype); ++ ++unsigned int get_pagesize(enum page_type pagetype); ++ ++const char *nand_ecc_name(int type); ++ ++const char *nand_page_name(int type); ++ ++int nandpage_size2type(int size); ++ ++int nandpage_type2size(int size); ++ ++/*****************************************************************************/ ++extern int (*hinfc_param_adjust)(struct mtd_info *mtd, struct nand_chip *chip, ++ struct nand_dev_t *nand_dev); ++ ++extern struct nand_flash_dev *(*nand_get_flash_type_func)(struct mtd_info *mtd, ++ struct nand_chip *chip, struct nand_dev_t *spinand_dev_t); ++ ++extern struct nand_flash_dev *(*get_spi_nand_flash_type_hook) ++ (struct mtd_info *mtd, unsigned char *id); ++ ++extern int (*hinfc_param_adjust)(struct mtd_info *, ++ struct nand_chip *, struct nand_dev_t *); ++ ++/*****************************************************************************/ ++struct nand_flash_dev *hinfc_get_flash_type(struct mtd_info *mtd, ++ struct nand_chip *chip, u8 *id_data, int *busw); ++ ++extern struct nand_flash_dev *(*get_spi_nand_flash_type_hook) ++ (struct mtd_info *mtd, unsigned char *id); ++ ++void hinfc_nand_param_adjust(struct mtd_info *mtd, struct nand_chip *chip); ++ ++void hinfc_show_info(struct mtd_info *mtd, char *vendor, char *chipname); ++ ++void hinfc_show_chipsize(struct nand_chip *chip); ++ ++int get_bits(unsigned int n); ++ ++/*****************************************************************************/ ++#define hinfc_pr_msg(_fmt, arg...) printk(_fmt, ##arg) ++ ++#define hinfc_pr_bug(fmt, args...) do { \ ++ printk("%s(%d): bug " fmt, __FILE__, __LINE__, ##args); \ ++ while (1) \ ++ ; \ ++} while (0) ++ ++#define PR_MSG(_fmt, arg...) \ ++ printk(_fmt, ##arg) ++ ++extern char *nand_dbgfs_options; ++/*****************************************************************************/ ++extern unsigned char match_page_reg_to_type(unsigned char reg); ++ ++extern unsigned char match_page_type_to_reg(unsigned char type); ++ ++extern const char *match_page_type_to_str(unsigned char type); ++ ++/*****************************************************************************/ ++extern unsigned char match_ecc_reg_to_type(unsigned char reg); ++ ++extern unsigned char match_ecc_type_to_reg(unsigned char type); ++ ++extern const char *match_ecc_type_to_str(unsigned char type); ++ ++/*****************************************************************************/ ++extern unsigned char match_page_size_to_type(unsigned int size); ++ ++extern unsigned int match_page_type_to_size(unsigned char type); ++ ++const char *nand_ecc_name(int type); ++/*****************************************************************************/ ++ ++#endif /* End of __HINFC_GEN_H__ */ +diff --git a/drivers/mtd/nand/hinfc_spl_ids.c b/drivers/mtd/nand/hinfc_spl_ids.c +new file mode 100644 +index 0000000..ccc15de +--- /dev/null ++++ b/drivers/mtd/nand/hinfc_spl_ids.c +@@ -0,0 +1,979 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include "hinfc_gen.h" ++ ++/*****************************************************************************/ ++ ++struct nand_flash_special_dev { ++ unsigned char id[8]; ++ int length; /* length of id. */ ++ unsigned long long chipsize; ++ struct nand_flash_dev *(*probe)(struct nand_dev_t *nand_dev); ++ char *name; ++ ++ unsigned long pagesize; ++ unsigned long erasesize; ++ unsigned long oobsize; ++ unsigned long options; ++ unsigned int read_retry_type; ++ ++#define BBP_LAST_PAGE 0x01 ++#define BBP_FIRST_PAGE 0x02 ++ unsigned int badblock_pos; ++ unsigned int flags; ++}; ++ ++/*****************************************************************************/ ++/* this is nand probe function. */ ++/*****************************************************************************/ ++ ++static struct nand_flash_dev *hynix_probe_v02( ++ struct nand_dev_t *nand_dev) ++{ ++ unsigned char *id = nand_dev->ids; ++ struct nand_flash_dev *type = &nand_dev->flash_dev; ++ ++ int pagesizes[] = {SZ_2K, SZ_4K, SZ_8K, 0}; ++ int oobsizes[] = {128, 224, 448, 0, 0, 0, 0, 0}; ++ int blocksizes[] = {SZ_128K, SZ_256K, SZ_512K, ++ (SZ_256K + SZ_512K), SZ_1M, SZ_2M, 0, 0}; ++ ++ int blocktype = (((id[3] >> 5) & 0x04) | ((id[3] >> 4) & 0x03)); ++ int oobtype = (((id[3] >> 2) & 0x03) | ((id[3] >> 4) & 0x04)); ++ ++ type->options = 0; ++ type->pagesize = pagesizes[(id[3] & 0x03)]; ++ type->erasesize = blocksizes[blocktype]; ++ nand_dev->oobsize = oobsizes[oobtype]; ++ ++ return type; ++} ++/*****************************************************************************/ ++ ++static struct nand_flash_dev *samsung_probe_v02( ++ struct nand_dev_t *nand_dev) ++{ ++ unsigned char *id = nand_dev->ids; ++ struct nand_flash_dev *type = &nand_dev->flash_dev; ++ ++ int pagesizes[] = {SZ_2K, SZ_4K, SZ_8K, 0}; ++ int oobsizes[] = {0, 128, 218, 400, 436, 0, 0, 0}; ++ int blocksizes[] = {SZ_128K, SZ_256K, SZ_512K, SZ_1M, 0, 0, 0, 0}; ++ ++ int blocktype = (((id[3] >> 5) & 0x04) | ((id[3] >> 4) & 0x03)); ++ int oobtype = (((id[3] >> 4) & 0x04) | ((id[3] >> 2) & 0x03)); ++ ++ type->options = 0; ++ type->pagesize = pagesizes[(id[3] & 0x03)]; ++ type->erasesize = blocksizes[blocktype]; ++ nand_dev->oobsize = oobsizes[oobtype]; ++ ++ return type; ++} ++/*****************************************************************************/ ++ ++#define DRV_VERSION "1.38" ++ ++/*****************************************************************************/ ++/* ++ * samsung: 27nm need randomizer, 21nm need read retry; ++ * micron: 25nm need read retry, datasheet will explain read retry. ++ * toshaba 32nm need randomizer, 24nm need read retry. ++ * hynix: 2xnm need read retry. ++ * ++ * The special nand flash ID table version 1.37 ++ * ++ * manufactory | type | name | ecc_type | version_tag ++ * Micron | MLC | MT29F64G08CBABA | 40bit/1k | 1.36 ++ * Micron | MLC | MT29F32G08CBADA | 40bit/1k | ++ * Micron | SLC | MT29F8G08ABxBA | 4bit/512 | ++ * Micron | MLC | MT29F16G08CBABx | 12bit/512 | ++ * Micron | MLC | MT29F16G08CBACA | 24bit/1k | ++ * Micron | MLC | MT29F32G08CBACA | 24bit/1k | ++ * Micron | MLC | MT29F64G08CxxAA | 24bit/1k | ++ * Micron | MLC | MT29F256G08CJAAA | 24bit/1k | 2CE ++ * Micron | MLC | MT29F256G08CMCBB | 24bit/1k | ++ * Micron | SLC | MT29F8G08ABACA | 8bit/512 | ++ * Micron | SLC | MT29F4G08ABAEA | 8bit/512 | ++ * Micron | SLC | MT29F2G08ABAFA | 8bit/512 | ++ * Micron | SLC | MT29F16G08ABACA | 8bit/512 | ++ * Toshiba | MLC | TC58NVG4D2FTA00 | 24bit/1k | ++ * Toshiba | MLC | TH58NVG6D2FTA20 | 24bit/1k | 2CE ++ * Toshiba | MLC | TC58NVG5D2HTA00 | 40bit/1k | ++ * Toshiba | MLC | TC58NVG6D2GTA00 | 40bit/1k | ++ * Toshiba | MLC | TC58NVG6DCJTA00 | | ++ * Toshiba | MLC | TC58TEG5DCJTA00 | | ++ * Toshiba | SLC | TC58NVG0S3HTA00 | 8bit/512 | ++ * Toshiba | SLC | TC58NVG1S3HTA00 | 8bit/512 | ++ * Toshiba | SLC | TC58NVG1S3ETA00 | 4bit/512 | ++ * Toshiba | SLC | TC58NVG3S0FTA00 | 4bit/512 | ++ * Toshiba | SLC | TC58NVG2S0FTA00 | 4bit/512 | ++ * Toshiba | SLC | TH58NVG2S3HTA00 | 4bit/512 | ++ * Toshiba | TLC | TC58NVG5T2JTA00 | 60bit/1k | ++ * Toshiba | TLC | TC58TEG5DCKTAx0 | 60bit/1k | ++ * Toshiba | MLC | Tx58TEGxDDKTAx0 | | ++ * Samsung | MLC | K9LB(HC/PD/MD)G08U0(1)D | 8bit/512B | ++ * Samsung | MLC | K9GAG08U0E | 24bit/1KB | ++ * Samsung | MLC | K9LBG08U0E | 24bit/1KB | ++ * Samsung | MLC | K9G8G08U0C | 24bit/1KB | ++ * Samsung | MLC | K9GAG08U0F | 24bit/1KB | ++ * Samsung | MLC | K9LBG08U0M | | ++ * Samsung | MLC | K9GBG08U0A | 24bit/1KB | ++ * Samsung | MLC | K9GBG08U0B | 40bit/1KB | ++ * Hynix | MLC | H27UAG8T2A | | ++ * Hynix | MLC | H27UAG8T2B | | ++ * Hynix | MLC | H27UBG8T2A | | ++ * Hynix | MLC | H27UBG8T2BTR | 24bit/1KB | ++ * Hynix | MLC | H27UCG8T2A | 40bit/1KB | ++ * Hynix | MLC | H27UBG8T2C | 40bit/1KB | ++ * MISC | MLC | P1UAGA30AT-GCA | 8bit/512 | ++ * MISC | MLC | PSU8GA30AT-GIA/ASU8GA30IT-G30CA | 4bit/512 | ++ * MISC | SLC | PSU2GA30AT | 1bit/512 | 1.36 ++ * Toshiba | SLC | TC58NVG2S0HTA00 | 24bit/1K | 1.37 ++ * Toshiba | SLC | TC58NVG3S0HTA00 | 24bit/1K | 1.37 ++ * Micron | SLC | MT29F2G08ABAEA | 4bit/512 | ++ * Spansion | SLC | S34ML02G200TFI000 | 24bit/1K | ++ * Spansion | SLC | S34ML04G200TFI000 | 24bit/1K | 1.38 ++ * ++ */ ++ ++static struct nand_flash_special_dev nand_flash_special_dev[] = { ++ ++/****************************** Spansion *******************************/ ++ ++ { /* SLC S34ML02G200TFI000 */ ++ .name = "S34ML02G200TFI000", ++ .id = {0x01, 0xDA, 0x90, 0x95, 0x46, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _256M, ++ .probe = NULL, ++ .pagesize = SZ_2K, ++ .erasesize = SZ_128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ ++ { /* SLC S34ML04G200TFI000 */ ++ .name = "S34ML04G200TFI000", ++ .id = {0x01, 0xDC, 0x90, 0x95, 0x56, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _512M, ++ .probe = NULL, ++ .pagesize = SZ_2K, ++ .erasesize = SZ_128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ ++/****************************** Micron *******************************/ ++ { /* MLC 40bit/1k */ ++ .name = "MT29F64G08CBABA", ++ .id = {0x2C, 0x64, 0x44, 0x4B, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_2M, ++ .oobsize = 744, ++ .options = 0, ++ .read_retry_type = NAND_RR_MICRON, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = NAND_RANDOMIZER | NAND_CHIP_MICRON, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "MT29F32G08CBADA", ++ .id = {0x2C, 0x44, 0x44, 0x4B, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_2M, ++ .oobsize = 744, ++ .options = 0, ++ .read_retry_type = NAND_RR_MICRON, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "MT29F8G08ABxBA", ++ .id = {0x2C, 0x38, 0x00, 0x26, 0x85, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = SZ_1G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_512K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 12bit/512 */ ++ .name = "MT29F16G08CBABx", ++ .id = {0x2C, 0x48, 0x04, 0x46, 0x85, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = SZ_2G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_1M, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "MT29F16G08CBACA", ++ .id = {0x2C, 0x48, 0x04, 0x4A, 0xA5, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = SZ_2G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_1M, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "MT29F32G08CBACA", ++ .id = {0x2C, 0x68, 0x04, 0x4A, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_1M, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "MT29F64G08CxxAA", ++ .id = {0x2C, 0x88, 0x04, 0x4B, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_2M, ++ .oobsize = 448, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k 2CE */ ++ .name = "MT29F256G08CJAAA", ++ .id = {0x2C, 0xA8, 0x05, 0xCB, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _16G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_2M, ++ .oobsize = 448, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "MT29F256G08CMCBB", ++ .id = {0x2C, 0x64, 0x44, 0x4B, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_2M, ++ .oobsize = 744, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "MT29F8G08ABACA", ++ .id = {0x2C, 0xD3, 0x90, 0xA6, 0x64, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = SZ_1G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_256K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "MT29F4G08ABAEA", ++ .id = {0x2C, 0xDC, 0x90, 0xA6, 0x54, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = SZ_512M, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_256K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "MT29F2G08ABAFA", ++ .id = {0x2C, 0xDA, 0x90, 0x95, 0x04, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = SZ_256M, ++ .probe = NULL, ++ .pagesize = SZ_2K, ++ .erasesize = SZ_128K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC MT29F2G08ABAEA */ ++ .name = "MT29F2G08ABAEA", ++ .id = {0x2C, 0xDA, 0x90, 0x95, 0x06, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _256M, ++ .probe = NULL, ++ .pagesize = SZ_2K, ++ .erasesize = SZ_128K, ++ .oobsize = 64, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "MT29F16G08ABACA", ++ .id = {0x2C, 0x48, 0x00, 0x26, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = SZ_2G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_512K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ ++/****************************** Toshaba *******************************/ ++ ++ { /* MLC 24bit/1k 32nm */ ++ .name = "TC58NVG4D2FTA00", ++ .id = {0x98, 0xD5, 0x94, 0x32, 0x76, 0x55, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = SZ_2G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_1M, ++ .oobsize = 448, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k 32nm 2CE*/ ++ .name = "TH58NVG6D2FTA20", ++ .id = {0x98, 0xD7, 0x94, 0x32, 0x76, 0x55, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_1M, ++ .oobsize = 448, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 40bit/1k 24nm */ ++ .name = "TC58NVG5D2HTA00 24nm", ++ .id = {0x98, 0xD7, 0x94, 0x32, 0x76, 0x56, 0x08, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_1M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_24nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "TC58NVG6D2GTA00", ++ .id = {0x98, 0xDE, 0x94, 0x82, 0x76, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_2M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 19nm */ ++ .name = "TC58NVG6DCJTA00 19nm", ++ .id = {0x98, 0xDE, 0x84, 0x93, 0x72, 0x57, 0x08, 0x04}, ++ .length = 8, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = SZ_16K, ++ .erasesize = SZ_4M, ++ .oobsize = 1280, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_24nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 19nm */ ++ .name = "TC58TEG5DCJTA00 19nm", ++ .id = {0x98, 0xD7, 0x84, 0x93, 0x72, 0x57, 0x08, 0x04}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_16K, ++ .erasesize = SZ_4M, ++ .oobsize = 1280, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_24nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER | NAND_CHIP_TOSHIBA_TOGGLE_10, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "TC58NVG0S3HTA00", ++ .id = {0x98, 0xF1, 0x80, 0x15, 0x72, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = SZ_128M, ++ .probe = NULL, ++ .pagesize = SZ_2K, ++ .erasesize = SZ_128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ /* ++ * Datasheet: read one column of any page in each block. If the ++ * data of the column is 00 (Hex), define the block as a bad ++ * block. ++ */ ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "TC58NVG1S3HTA00", ++ .id = {0x98, 0xDA, 0x90, 0x15, 0x76, 0x16, 0x08, 0x00}, ++ .length = 7, ++ .chipsize = SZ_256M, ++ .probe = NULL, ++ .pagesize = SZ_2K, ++ .erasesize = SZ_128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "TC58NVG1S3ETA00", ++ .id = {0x98, 0xDA, 0x90, 0x15, 0x76, 0x14, 0x03, 0x00}, ++ .length = 7, ++ .chipsize = SZ_256M, ++ .probe = NULL, ++ .pagesize = SZ_2K, ++ .erasesize = SZ_128K, ++ .oobsize = 64, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "TC58NVG3S0FTA00", ++ .id = {0x98, 0xD3, 0x90, 0x26, 0x76, 0x15, 0x02, 0x08}, ++ .length = 8, ++ .chipsize = SZ_1G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_256K, ++ .oobsize = 232, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "TC58NVG3S0HTA00", ++ .id = {0x98, 0xD3, 0x91, 0x26, 0x76, 0x16, 0x08, 0x00}, ++ .length = 8, ++ .chipsize = SZ_1G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_256K, ++ .oobsize = 256, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 24bit/1k */ ++ .name = "TC58NVG2S0HTA00", ++ .id = {0x98, 0xDC, 0x90, 0x26, 0x76, 0x16, 0x08, 0x00}, ++ .length = 8, ++ .chipsize = SZ_512M, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_256K, ++ .oobsize = 256, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "TC58NVG2S0FTA00", ++ .id = {0x98, 0xDC, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08}, ++ .length = 8, ++ .chipsize = SZ_512M, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_256K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "TH58NVG2S3HTA00", ++ .id = {0x98, 0xDC, 0x91, 0x15, 0x76}, ++ .length = 5, ++ .chipsize = SZ_512M, ++ .probe = NULL, ++ .pagesize = SZ_2K, ++ .erasesize = SZ_128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* TLC 60bit/1k 19nm */ ++ .name = "TC58NVG5T2JTA00 19nm TLC", ++ .id = {0x98, 0xD7, 0x98, 0x92, 0x72, 0x57, 0x08, 0x10}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_4M, ++ .oobsize = 1024, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_24nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* TLC 60bit/1k 19nm */ ++ .name = "TC58TEG5DCKTAx0 19nm MLC", ++ /* datasheet says 6 ids id data, but really has 8 ids. */ ++ .id = {0x98, 0xD7, 0x84, 0x93, 0x72, 0x50, 0x08, 0x04}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_16K, ++ .erasesize = SZ_4M, ++ .oobsize = 1280, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_19nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { ++ .name = "Tx58TEGxDDKTAx0 19nm MLC", ++ .id = {0x98, 0xDE, 0x94, 0x93, 0x76, 0x50}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_16K, ++ .erasesize = SZ_4M, ++ .oobsize = 1280, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_19nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++/******************************* Samsung ******************************/ ++ { /* MLC 8bit/512B */ ++ .name = "K9LB(HC/PD/MD)G08U0(1)D", ++ .id = {0xEC, 0xD7, 0xD5, 0x29, 0x38, 0x41, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = samsung_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1KB */ ++ .name = "K9GAG08U0E", ++ .id = {0xEC, 0xD5, 0x84, 0x72, 0x50, 0x42, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = SZ_2G, ++ .probe = samsung_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1KB */ ++ .name = "K9LBG08U0E", ++ .id = {0xEC, 0xD7, 0xC5, 0x72, 0x54, 0x42, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = samsung_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1KB */ ++ .name = "K9G8G08U0C", ++ .id = {0xEC, 0xD3, 0x84, 0x72, 0x50, 0x42, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = SZ_1G, ++ .probe = samsung_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "K9GAG08U0F", ++ .id = {0xEC, 0xD5, 0x94, 0x76, 0x54, 0x43, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = SZ_2G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_1M, ++ .oobsize = 512, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC */ ++ .name = "K9LBG08U0M", ++ .id = {0xEC, 0xD7, 0x55, 0xB6, 0x78, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_512K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "K9GBG08U0A 20nm", ++ .id = {0xEC, 0xD7, 0x94, 0x7A, 0x54, 0x43, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_1M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_SAMSUNG, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "K9GBG08U0B", ++ .id = {0xEC, 0xD7, 0x94, 0x7E, 0x64, 0x44, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_1M, ++ .oobsize = 1024, ++ .options = 0, ++ .read_retry_type = NAND_RR_SAMSUNG, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ ++/*********************************** Hynix ****************************/ ++ { /* MLC */ ++ .name = "H27UAG8T2A", ++ .id = {0xAD, 0xD5, 0x94, 0x25, 0x44, 0x41, }, ++ .length = 6, ++ .chipsize = SZ_2G, ++ .probe = hynix_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC */ ++ .name = "H27UAG8T2B", ++ .id = {0xAD, 0xD5, 0x94, 0x9A, 0x74, 0x42, }, ++ .length = 6, ++ .chipsize = SZ_2G, ++ .probe = hynix_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC */ ++ .name = "H27UBG8T2A", ++ .id = {0xAD, 0xD7, 0x94, 0x9A, 0x74, 0x42, }, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = hynix_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1K, 26nm TODO: Need read retry, chip is EOS */ ++ .name = "H27UBG8T2BTR 26nm", ++ .id = {0xAD, 0xD7, 0x94, 0xDA, 0x74, 0xC3, }, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_2M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_HYNIX_BG_BDIE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "H27UCG8T2A", ++ .id = {0xAD, 0xDE, 0x94, 0xDA, 0x74, 0xC4, }, ++ .length = 6, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_2M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_HYNIX_CG_ADIE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "H27UBG8T2C", ++ .id = {0xAD, 0xD7, 0x94, 0x91, 0x60, 0x44, }, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_2M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_HYNIX_BG_CDIE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ ++/********************** MISC ******************************************/ ++ { /* MLC 8bit/512 */ ++ .name = "P1UAGA30AT-GCA", ++ .id = {0xC8, 0xD5, 0x14, 0x29, 0x34, 0x01, }, ++ .length = 6, ++ .chipsize = SZ_2G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_512K, ++ .oobsize = 218, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 4bit/512 */ ++ /* ++ * PowerFlash ASU8GA30IT-G30CA ID and MIRA PSU8GA30AT-GIA ID are ++ * the same ID ++ */ ++ .name = "PSU8GA30AT-GIA/ASU8GA30IT-G30CA", ++ .id = {0xC8, 0xD3, 0x90, 0x19, 0x34, 0x01, }, ++ .length = 6, ++ .chipsize = SZ_1G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_256K, ++ .oobsize = 218, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 1bit/512 */ ++ .name = "PSU2GA30AT", ++ .id = {0x7F, 0x7F, 0x7F, 0x7F, 0xC8, 0xDA, 0x00, 0x15, }, ++ .length = 8, ++ .chipsize = SZ_256M, ++ .probe = NULL, ++ .pagesize = SZ_2K, ++ .erasesize = SZ_128K, ++ .oobsize = 64, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ {{0}, 0, 0, 0, 0, 0, 0, 0, 0}, ++}; ++ ++#define NUM_OF_SPECIAL_DEVICE \ ++ (sizeof(nand_flash_special_dev)/sizeof(struct nand_flash_special_dev)) ++ ++int (*hinfc_param_adjust)(struct mtd_info *, struct nand_chip *, ++ struct nand_dev_t *) = NULL; ++ ++static struct nand_dev_t __nand_dev; ++/*****************************************************************************/ ++ ++static struct nand_flash_dev *hinfc_nand_probe(struct mtd_info *mtd, ++ struct nand_chip *chip, ++ struct nand_dev_t *nand_dev) ++{ ++ struct nand_flash_special_dev *spl_dev; ++ unsigned char *byte = nand_dev->ids; ++ struct nand_flash_dev *type = &nand_dev->flash_dev; ++ ++ hinfc_pr_msg("Nand ID: 0x%02X 0x%02X 0x%02X 0x%02X", ++ byte[0], byte[1], byte[2], byte[3]); ++ hinfc_pr_msg(" 0x%02X 0x%02X 0x%02X 0x%02X\n", ++ byte[4], byte[5], byte[6], byte[7]); ++ ++ for (spl_dev = nand_flash_special_dev; spl_dev->length; spl_dev++) { ++ if (memcmp(byte, spl_dev->id, spl_dev->length)) ++ continue; ++ ++ hinfc_pr_msg("The Special NAND id table Version: %s\n", DRV_VERSION); ++ ++ if (spl_dev->probe) { ++ type = spl_dev->probe(nand_dev); ++ } else { ++ type->options = spl_dev->options; ++ type->pagesize = spl_dev->pagesize; ++ type->erasesize = spl_dev->erasesize; ++ nand_dev->oobsize = spl_dev->oobsize; ++ } ++ ++ nand_dev->read_retry_type = spl_dev->read_retry_type; ++ nand_dev->flags = spl_dev->flags; ++ ++ type->id[1] = byte[1]; ++ type->chipsize = (unsigned long)(spl_dev->chipsize >> 20); ++ type->name = spl_dev->name; ++ return type; ++ } ++ nand_dev->read_retry_type = NAND_RR_NONE; ++ ++ return NULL; ++} ++/*****************************************************************************/ ++ ++struct nand_flash_dev *hinfc_get_flash_type(struct mtd_info *mtd, ++ struct nand_chip *chip, ++ u8 *id_data, int *busw) ++{ ++ struct nand_flash_dev *type; ++ struct nand_dev_t *nand_dev = &__nand_dev; ++ ++ memset(nand_dev, 0, sizeof(struct nand_dev_t)); ++ memcpy(nand_dev->ids, id_data, 8); ++ ++ if (!hinfc_nand_probe(mtd, chip, nand_dev)) ++ return NULL; ++ ++ type = &nand_dev->flash_dev; ++ ++ if (!mtd->name) ++ mtd->name = type->name; ++ ++ chip->chipsize = (uint64_t)type->chipsize << 20; ++ mtd->erasesize = type->erasesize; ++ mtd->writesize = type->pagesize; ++ mtd->oobsize = nand_dev->oobsize; ++ *busw = (type->options & NAND_BUSWIDTH_16); ++ ++ return type; ++} ++/*****************************************************************************/ ++ ++void hinfc_nand_param_adjust(struct mtd_info *mtd, struct nand_chip *chip) ++{ ++ struct nand_dev_t *nand_dev = &__nand_dev; ++ ++ if (!nand_dev->oobsize) ++ nand_dev->oobsize = mtd->oobsize; ++ ++ if (hinfc_param_adjust) ++ hinfc_param_adjust(mtd, chip, nand_dev); ++} ++/*****************************************************************************/ ++ ++void hinfc_show_info(struct mtd_info *mtd, char *vendor, char *chipname) ++{ ++ /* char buf[20]; */ ++ struct nand_dev_t *nand_dev = &__nand_dev; ++ ++ /* hinfc_pr_msg("Nand: %s %s ", vendor, chipname); */ ++ ++ if (IS_NAND_RANDOM(nand_dev)) ++ hinfc_pr_msg("Randomizer \n"); ++ ++ if (nand_dev->read_retry_type != NAND_RR_NONE) ++ hinfc_pr_msg("Read-Retry \n"); ++ ++ if (nand_dev->start_type) ++ hinfc_pr_msg("Nand(%s): ", nand_dev->start_type); ++ else ++ hinfc_pr_msg("Nand: "); ++ ++ hinfc_pr_msg("OOB:%dB ", nand_dev->oobsize); ++ hinfc_pr_msg("ECC:%s ", nand_ecc_name(nand_dev->ecctype)); ++} ++/*****************************************************************************/ ++ ++void hinfc_show_chipsize(struct nand_chip *chip) ++{ ++ /*char buf[20];*/ ++ ++ /*hinfc_pr_msg("Chip:%sB*%d\n", ++ ultohstr(chip->chipsize, buf, sizeof(buf)), ++ chip->numchips);*/ ++} +diff --git a/drivers/mtd/nand/hisnfc100/Kconfig b/drivers/mtd/nand/hisnfc100/Kconfig +new file mode 100644 +index 0000000..bde6a76 +--- /dev/null ++++ b/drivers/mtd/nand/hisnfc100/Kconfig +@@ -0,0 +1,55 @@ ++# ++# drivers/mtd/nand/hisnfc100/Kconfig ++# add by hisilicon 2017.10.26 ++# ++ ++menuconfig MTD_NAND_HISNFC100 ++ tristate "Hisilicon SPI Nand Controller v100 SPI Nand devices support" ++ depends on MTD_SPI_NAND_HISI_BVT && (ARCH_HI3516A) ++ select YAFFS_FS ++ select MISC_FILESYSTEMS ++ select MTD_BLOCK ++ select YAFFS_YAFFS2 ++ help ++ Hisilicon SPI Nand Controller version 100 is called HISNFC100 for ++ short. The controller support registers and DMA transfers while ++ reading or writing the spi nand flash. ++ ++if MTD_NAND_HISNFC100 ++ ++config HISNFC100_MAX_CHIP ++ int "number of spi nand flash chip (1, 2)" ++ range 1 2 ++ default 1 ++ help ++ spi nand controller v100 device only support 1 or 2 spi nand ++ flash chip, your should not config other value. ++ ++choice ++ prompt "Pagesize and Ecc Type Select" ++ ++config HISNFC100_HARDWARE_PAGESIZE_ECC ++ bool "Hardware" ++ help ++ the configure of page size and ecc type lie on switch ++ on the board. ++ so the page size and ecc type is controlled by Hardware ++ see demo board of SOC. ++ ++config HISNFC100_AUTO_PAGESIZE_ECC ++ bool "Auto" ++ help ++ auto-sensed the page size and ecc type value. driver will ++ try each of page size and ecc type one by one till flash ++ can be read and wrote accurately. ++ so the page size and ecc type is match adaptively without ++ switch on the board ++ ++config HISNFC100_PAGESIZE_AUTO_ECC_NONE ++ bool "Pagesize Auto, Ecc None" ++ help ++ select pagesize 2K, ecc none. ++ ++endchoice ++ ++endif # MTD_NAND_HISNFC100 +diff --git a/drivers/mtd/nand/hisnfc100/Makefile b/drivers/mtd/nand/hisnfc100/Makefile +new file mode 100644 +index 0000000..4ed5f59 +--- /dev/null ++++ b/drivers/mtd/nand/hisnfc100/Makefile +@@ -0,0 +1,7 @@ ++# ++# drivers/mtd/nand/hisnfc100/Makefile ++# ++ ++obj-$(CONFIG_MTD_NAND_HISNFC100) += hisnfc100.o hisnfc100_os.o hisnfc100_spi_ids.o ++ ++ +diff --git a/drivers/mtd/nand/hisnfc100/hisnfc100.c b/drivers/mtd/nand/hisnfc100/hisnfc100.c +new file mode 100644 +index 0000000..e1d59d4 +--- /dev/null ++++ b/drivers/mtd/nand/hisnfc100/hisnfc100.c +@@ -0,0 +1,989 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hisnfc100_os.h" ++#include "hisnfc100_spi_ids.h" ++#include "hisnfc100.h" ++ ++#ifdef CONFIG_ARCH_HI3516A ++ #include "hisnfc100_hi3516a.c" ++#endif ++ ++#define DEBUG_ERASE 0 ++#define DEBUG_WRITE 0 ++#define DEBUG_READ 0 ++ ++/*****************************************************************************/ ++static void hisnfc100_send_cmd_pageprog(struct hisnfc_host *host) ++{ ++ unsigned char pages_per_block_shift; ++ unsigned val, block_num, block_num_h, page_num; ++ struct hisnfc_op *spi = host->spi; ++ struct nand_chip *chip = host->chip; ++#ifdef HISNFC100_SUPPORT_REG_WRITE ++ const char *op_type = "reg"; ++#else ++ const char *op_type = "dma"; ++#endif ++ ++ if (DEBUG_WRITE) ++ pr_info("* Enter %s page program!\n", op_type); ++ ++ val = spi->driver->wait_ready(spi); ++ if (val) { ++ pr_info("%s: %s page program wait ready fail! status[%#x]\n", ++ __func__, op_type, val); ++ return; ++ } ++ ++ if (spi->driver->write_enable(spi)) { ++ pr_info("%s %s page program write enable failed!\n", __func__, ++ op_type); ++ return; ++ } ++ ++ host->set_system_clock(spi->write, ENABLE); ++ ++ val = HISNFC100_INT_CLR_ALL; ++ hisfc_write(host, HISNFC100_INT_CLR, val); ++ if (DEBUG_WRITE) ++ pr_info(" Set REG INT_CLR[0x14]%#x\n", val); ++ ++ val = HISNFC100_OP_CFG_MEM_IF_TYPE(spi->write->iftype); ++ hisfc_write(host, HISNFC100_OP_CFG, val); ++ if (DEBUG_WRITE) ++ pr_info(" Set REG OP_CFG[0x28]%#x\n", val); ++ ++ pages_per_block_shift = chip->phys_erase_shift - chip->page_shift; ++ block_num = host->addr_value[1] >> pages_per_block_shift; ++ block_num_h = block_num >> REG_CNT_HIGH_BLOCK_NUM_SHIFT; ++ val = HISNFC100_ADDRH_SET(block_num_h); ++ hisfc_write(host, HISNFC100_ADDRH, val); ++ if (DEBUG_WRITE) ++ pr_info(" Set REG ADDRH[0x2c]%#x\n", val); ++ ++ page_num = host->addr_value[1] - (block_num << pages_per_block_shift); ++ val = ((block_num & REG_CNT_BLOCK_NUM_MASK) << REG_CNT_BLOCK_NUM_SHIFT) ++ | ((page_num & REG_CNT_PAGE_NUM_MASK) << REG_CNT_PAGE_NUM_SHIFT); ++ hisfc_write(host, HISNFC100_ADDRL, val); ++ if (DEBUG_WRITE) ++ pr_info(" Set REG ADDRL[0x30]%#x\n", val); ++ ++#ifndef HISNFC100_SUPPORT_REG_WRITE ++ val = HISNFC100_DMA_CTRL_ALL_ENABLE; ++ hisfc_write(host, HISNFC100_DMA_CTRL, val); ++ if (DEBUG_WRITE) ++ pr_info(" Set REG DMA_CTRL[0x3c]%#x\n", val); ++ ++ val = host->dma_buffer; ++ hisfc_write(host, HISNFC100_DMA_SADDR_D, val); ++ if (DEBUG_WRITE) ++ pr_info(" Set REG DMA_SADDR_D[0x40]%#x\n", val); ++ ++ val = host->dma_oob; ++ hisfc_write(host, HISNFC100_DMA_SADDR_OOB, val); ++ if (DEBUG_WRITE) ++ pr_info(" Set REG DMA_SADDR_OOB[%#x]%#x\n", ++ HISNFC100_DMA_SADDR_OOB, val); ++#endif ++ ++ val = HISNFC100_OP_CTRL_WR_OPCODE(spi->write->cmd) ++ | HISNFC100_OP_CTRL_CS_OP(host->cmd_option.chipselect) ++#ifdef HISNFC100_SUPPORT_REG_WRITE ++ | HISNFC100_OP_CTRL_OP_TYPE(OP_TYPE_REG) ++#else ++ | HISNFC100_OP_CTRL_OP_TYPE(OP_TYPE_DMA) ++#endif ++ | HISNFC100_OP_CTRL_RW_OP(RW_OP_WRITE) ++ | HISNFC100_OP_CTRL_OP_READY; ++ hisfc_write(host, HISNFC100_OP_CTRL, val); ++ if (DEBUG_WRITE) ++ pr_info(" Set REG OP_CTRL[0x34]%#x\n", val); ++ ++ HISNFC100_DMA_WAIT_INT_FINISH(host); ++ ++ if (DEBUG_WRITE) { ++ val = spi->driver->wait_ready(spi); ++ if (val & STATUS_P_FAIL_MASK) ++ pr_info("hisnfc100: %s page program failed!" \ ++ " status[%#x]\n", op_type, val); ++ } ++ ++ if (DEBUG_WRITE) ++ pr_info("* End %s page program!\n", op_type); ++} ++ ++/*****************************************************************************/ ++static void hisnfc100_send_cmd_readstart(struct hisnfc_host *host) ++{ ++ unsigned char pages_per_block_shift, only_oob = 0; ++ unsigned short wrap = 0; ++ unsigned val, block_num, block_num_h, page_num, addr_of = 0; ++ struct hisnfc_op *spi = host->spi; ++ struct nand_chip *chip = host->chip; ++#ifdef HISNFC100_SUPPORT_REG_READ ++ char *op_type = "reg"; ++#else ++ char *op_type = "dma"; ++#endif ++ ++ if (DEBUG_READ) ++ pr_info("* Enter %s page read start!\n", op_type); ++ ++ if ((host->addr_value[0] == host->cache_addr_value[0]) ++ && (host->addr_value[1] == host->cache_addr_value[1])) { ++ if (DEBUG_READ) ++ pr_info("* %s page read cache hit! addr1[%#x], " \ ++ "addr0[%#x]\n", op_type, host->addr_value[1], ++ host->addr_value[0]); ++ return; ++ } ++ ++ val = spi->driver->wait_ready(spi); ++ if (val) { ++ pr_info("%s: %s read wait ready fail! status[%#x]\n", __func__, ++ op_type, val); ++ return; ++ } ++ ++ host->set_system_clock(spi->read, ENABLE); ++ ++ val = HISNFC100_INT_CLR_ALL; ++ hisfc_write(host, HISNFC100_INT_CLR, val); ++ if (DEBUG_READ) ++ pr_info(" Set REG INT_CLR[0x14]%#x\n", val); ++ ++ if (host->cmd_option.last_cmd == NAND_CMD_READOOB) { ++ only_oob = 1; ++ host->cmd_option.op_config = ++ HISNFC100_OP_CFG_RD_OP_SEL(RD_OP_READ_OOB); ++ } else ++ host->cmd_option.op_config = ++ HISNFC100_OP_CFG_RD_OP_SEL(RD_OP_READ_PAGE); ++ ++ val = host->cmd_option.op_config ++ | HISNFC100_OP_CFG_MEM_IF_TYPE(spi->read->iftype) ++ | HISNFC100_OP_CFG_DUMMY_ADDR_NUM(spi->read->dummy); ++ hisfc_write(host, HISNFC100_OP_CFG, val); ++ if (DEBUG_READ) ++ pr_info(" Set REG OP_CFG[0x28]%#x\n", val); ++ ++ pages_per_block_shift = chip->phys_erase_shift - chip->page_shift; ++ block_num = host->addr_value[1] >> pages_per_block_shift; ++ block_num_h = block_num >> REG_CNT_HIGH_BLOCK_NUM_SHIFT; ++ ++ val = HISNFC100_ADDRH_SET(block_num_h); ++ hisfc_write(host, HISNFC100_ADDRH, val); ++ if (DEBUG_READ) ++ pr_info(" Set REG ADDRH[0x2c]%#x\n", val); ++ ++ page_num = host->addr_value[1] - (block_num << pages_per_block_shift); ++ if (only_oob) ++ switch (host->ecctype) { ++ case NAND_ECC_8BIT: ++ addr_of = REG_CNT_ECC_8BIT_OFFSET; ++ break; ++ case NAND_ECC_16BIT: ++ addr_of = REG_CNT_ECC_16BIT_OFFSET; ++ break; ++ case NAND_ECC_24BIT: ++ addr_of = REG_CNT_ECC_24BIT_OFFSET; ++ break; ++ case NAND_ECC_0BIT: ++ default: ++ break; ++ } ++ ++ val = (((block_num & REG_CNT_BLOCK_NUM_MASK) << REG_CNT_BLOCK_NUM_SHIFT) ++ | ((page_num & REG_CNT_PAGE_NUM_MASK) << REG_CNT_PAGE_NUM_SHIFT) ++ | ((wrap & REG_CNT_WRAP_MASK) << REG_CNT_WRAP_SHIFT) ++ | (addr_of & REG_CNT_ECC_OFFSET_MASK)); ++ hisfc_write(host, HISNFC100_ADDRL, val); ++ if (DEBUG_READ) ++ pr_info(" Set REG ADDRL[0x30]%#x\n", val); ++ ++#ifndef HISNFC100_SUPPORT_REG_READ ++ val = HISNFC100_DMA_CTRL_ALL_ENABLE; ++ hisfc_write(host, HISNFC100_DMA_CTRL, val); ++ if (DEBUG_READ) ++ pr_info(" Set REG DMA_CTRL[0x3c]%#x\n", val); ++ ++ val = host->dma_buffer; ++ hisfc_write(host, HISNFC100_DMA_SADDR_D, val); ++ if (DEBUG_READ) ++ pr_info(" Set REG DMA_SADDR_D[0x40]%#x\n", val); ++ ++ val = host->dma_oob; ++ hisfc_write(host, HISNFC100_DMA_SADDR_OOB, val); ++ if (DEBUG_READ) ++ pr_info(" Set REG DMA_SADDR_OOB[%#x]%#x\n", ++ HISNFC100_DMA_SADDR_OOB, val); ++#endif ++ ++ val = HISNFC100_OP_CTRL_RD_OPCODE(spi->read->cmd) ++ | HISNFC100_OP_CTRL_CS_OP(host->cmd_option.chipselect) ++#ifdef HISNFC100_SUPPORT_REG_READ ++ | HISNFC100_OP_CTRL_OP_TYPE(OP_TYPE_REG) ++#else ++ | HISNFC100_OP_CTRL_OP_TYPE(OP_TYPE_DMA) ++#endif ++ | HISNFC100_OP_CTRL_RW_OP(RW_OP_READ) ++ | HISNFC100_OP_CTRL_OP_READY; ++ hisfc_write(host, HISNFC100_OP_CTRL, val); ++ if (DEBUG_READ) ++ pr_info(" Set REG OP_CTRL[0x34]%#x\n", val); ++ ++ HISNFC100_DMA_WAIT_INT_FINISH(host); ++ ++ host->cache_addr_value[0] = host->addr_value[0]; ++ host->cache_addr_value[1] = host->addr_value[1]; ++ ++ if (DEBUG_READ) ++ pr_info("* End %s page read start!\n", op_type); ++} ++ ++/*****************************************************************************/ ++static void hisnfc100_send_cmd_erase(struct hisnfc_host *host) ++{ ++ unsigned val; ++ struct hisnfc_op *spi = host->spi; ++ ++ if (DEBUG_ERASE) ++ pr_info("* Enter send cmd erase!\n"); ++ ++ val = spi->driver->wait_ready(spi); ++ if (val) { ++ pr_info("hisnfc: erase wait ready fail! status[%#x]\n", val); ++ return; ++ } ++ ++ if (spi->driver->write_enable(spi)) { ++ pr_info("%s erase write enable failed!\n", __func__); ++ return; ++ } ++ ++ if (DEBUG_ERASE) { ++ spi_feature_op(host, GET_OP, STATUS_ADDR, &val); ++ pr_info(" Get feature addr[0xC0], val[%#x]\n", val); ++ } ++ ++ host->set_system_clock(spi->erase, ENABLE); ++ ++ val = HISNFC100_INT_CLR_ALL; ++ hisfc_write(host, HISNFC100_INT_CLR, val); ++ if (DEBUG_ERASE) ++ pr_info(" Set REG INT_CLR[0x14]%#x\n", val); ++ ++ val = spi->erase->cmd; ++ hisfc_write(host, HISNFC100_OPCODE, val); ++ if (DEBUG_ERASE) ++ pr_info(" Set REG OPCODE[0x18]%#x\n", val); ++ ++ val = HISNFC100_OP_ADDRH_BLOCK_MASK(host->addr_value[1]) ++ | HISNFC100_OP_ADDRL_BLOCK_MASK(host->addr_value[0]); ++ hisfc_write(host, HISNFC100_OP_ADDR, val); ++ if (DEBUG_ERASE) ++ pr_info(" Set REG OP_ADDR[0x18]%#x\n", val); ++ ++ val = HISNFC100_OP_CFG_DIR_TRANS_ENABLE; ++ hisfc_write(host, HISNFC100_OP_CFG, val); ++ if (DEBUG_ERASE) ++ pr_info(" Set REG OP_CFG[0x28]%#x\n", val); ++ ++ val = HISNFC100_OP_SEL_CS(host->cmd_option.chipselect) ++ | HISNFC100_OP_ADDR_NUM(STD_OP_ADDR_NUM) ++ | HISNFC100_OP_OPCODE_EN(ENABLE) ++ | HISNFC100_OP_ADDR_EN(ENABLE) ++ | HISNFC100_OP_START; ++ hisfc_write(host, HISNFC100_OP, val); ++ if (DEBUG_ERASE) ++ pr_info(" Set REG OP[0x20]%#x\n", val); ++ ++ HISNFC100_CMD_WAIT_CPU_FINISH(host); ++ ++ if (DEBUG_ERASE) { ++ val = spi->driver->wait_ready(spi); ++ if (val & STATUS_E_FAIL_MASK) ++ pr_info("hisnfc100: erase failed! status[%#x]\n", val); ++ } ++ ++ if (DEBUG_ERASE) ++ pr_info("* End send cmd erase!\n"); ++} ++ ++/*****************************************************************************/ ++static void hisnfc100_send_cmd_status(struct hisnfc_host *host) ++{ ++ unsigned regval, addr = 0; ++ ++ if ((host->cmd_option.last_cmd == NAND_CMD_ERASE1) ++ || (host->cmd_option.last_cmd == NAND_CMD_PAGEPROG)) ++ addr = PROTECTION_ADDR; ++ else ++ addr = STATUS_ADDR; ++ ++ spi_feature_op(host, GET_OP, addr, ®val); ++ ++ if (DEBUG_ERASE || DEBUG_WRITE) ++ pr_info("hisnfc100: %s get %#x status[%#x]\n", ++ ((host->cmd_option.last_cmd == NAND_CMD_ERASE1) ++ ? "erase" : "write"), addr, regval); ++} ++ ++/*****************************************************************************/ ++static void hisnfc100_send_cmd_readid(struct hisnfc_host *host) ++{ ++ hisfc_write(host, HISNFC100_INT_CLR, HISNFC100_INT_CLR_OP_DONE); ++ hisfc_write(host, HISNFC100_OPCODE, SPI_CMD_RDID); ++ hisfc_write(host, HISNFC100_OP_ADDR, READ_ID_ADDR); ++ hisfc_write(host, HISNFC100_DATA_NUM, ++ HISNFC100_DATA_NUM_CNT(MAX_ID_LEN)); ++ hisfc_write(host, HISNFC100_OP_CFG, HISNFC100_OP_CFG_DIR_TRANS_ENABLE); ++ ++ hisfc_write(host, HISNFC100_OP, ++ HISNFC100_OP_SEL_CS(host->cmd_option.chipselect) ++ | HISNFC100_OP_ADDR_NUM(READ_ID_ADDR_NUM) ++ | HISNFC100_OP_OPCODE_EN(ENABLE) ++ | HISNFC100_OP_ADDR_EN(ENABLE) ++ | HISNFC100_OP_DATE_READ_EN(ENABLE) ++ | HISNFC100_OP_START); ++ ++ HISNFC100_CMD_WAIT_CPU_FINISH(host); ++} ++ ++/*****************************************************************************/ ++static void hisnfc100_send_cmd_reset(struct hisnfc_host *host) ++{ ++ hisfc_write(host, HISNFC100_INT_CLR, HISNFC100_INT_CLR_OP_DONE); ++ hisfc_write(host, HISNFC100_OPCODE, SPI_CMD_RESET); ++ hisfc_write(host, HISNFC100_OP_CFG, HISNFC100_OP_CFG_DIR_TRANS_ENABLE); ++ hisfc_write(host, HISNFC100_OP, ++ HISNFC100_OP_SEL_CS(host->cmd_option.chipselect) ++ | HISNFC100_OP_OPCODE_EN(ENABLE) ++ | HISNFC100_OP_START); ++ ++ HISNFC100_CMD_WAIT_CPU_FINISH(host); ++} ++ ++/*****************************************************************************/ ++static uint8_t hisnfc100_read_byte(struct mtd_info *mtd) ++{ ++ unsigned char value = 0, ret_val = 0; ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hisnfc_host *host = chip->priv; ++ ++ if (host->cmd_option.last_cmd == NAND_CMD_READID) { ++ value = readb(chip->IO_ADDR_R + host->offset); ++ host->offset++; ++ if (host->cmd_option.date_num == host->offset) ++ host->cmd_option.last_cmd = 0; ++ return value; ++ } ++ ++ if ((host->cmd_option.last_cmd == NAND_CMD_ERASE1) ++ || (host->cmd_option.last_cmd == NAND_CMD_PAGEPROG)) { ++ value = hisfc_read(host, HISNFC100_STATUS); ++ if (ANY_BP_ENABLE(value)) ++ value &= ~NAND_STATUS_WP; ++ else ++ value |= NAND_STATUS_WP; ++ ++ host->cmd_option.last_cmd = 0; ++ ++ return value; ++ } ++ ++ if (host->cmd_option.last_cmd == NAND_CMD_ERASE2) { ++ value = hisfc_read(host, HISNFC100_STATUS); ++ if (!(value & STATUS_OIP_MASK)) ++ ret_val |= NAND_STATUS_READY; ++ ++ if (value & STATUS_E_FAIL_MASK) ++ ret_val |= NAND_STATUS_FAIL; ++ ++ return ret_val; ++ } ++ ++ if (host->cmd_option.command == NAND_CMD_STATUS) { ++ value = hisfc_read(host, HISNFC100_STATUS); ++ ++ if (!(value & STATUS_OIP_MASK)) ++ ret_val |= NAND_STATUS_READY; ++ ++ if (value & STATUS_P_FAIL_MASK) ++ ret_val |= NAND_STATUS_FAIL; ++ ++ return ret_val; ++ } ++ ++ if (host->cmd_option.last_cmd == NAND_CMD_READOOB) { ++ value = readb(host->buffer + host->pagesize + host->offset); ++ host->offset++; ++ return value; ++ } ++ ++ host->offset++; ++ ++ return readb(host->buffer + host->column + host->offset - 1); ++} ++ ++/*****************************************************************************/ ++static u16 hisnfc100_read_word(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hisnfc_host *host = chip->priv; ++ ++ host->offset += 2; ++ return readw(host->buffer + host->column + host->offset - 2); ++} ++ ++/*****************************************************************************/ ++static void hisnfc100_write_buf(struct mtd_info *mtd, ++ const uint8_t *buf, int len) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hisnfc_host *host = chip->priv; ++ ++#ifdef HISNFC100_SUPPORT_REG_WRITE ++ if (buf == chip->oob_poi) ++ memcpy((char *)host->iobase + host->pagesize, buf, len); ++ else ++ memcpy((char *)host->iobase, buf, len); ++#else ++ if (buf == chip->oob_poi) ++ memcpy((char *)(host->buffer + host->pagesize), buf, len); ++ else ++ memcpy((char *)host->buffer, buf, len); ++#endif ++ return; ++} ++ ++/*****************************************************************************/ ++static void hisnfc100_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hisnfc_host *host = chip->priv; ++ ++#ifdef HISNFC100_SUPPORT_REG_READ ++ if (buf == chip->oob_poi) ++ memcpy(buf, (char *)host->iobase + host->pagesize, len); ++ else ++ memcpy(buf, (char *)host->iobase, len); ++#else ++ if (buf == chip->oob_poi) ++ memcpy(buf, (char *)(host->buffer + host->pagesize), len); ++ else ++ memcpy(buf, (char *)host->buffer, len); ++#endif ++ ++ if (buf != chip->oob_poi) { ++ u_int reg, ecc_step = host->pagesize >> 10; ++ ++ reg = hisfc_read(host, HISNFC100_ECC_ERR_NUM); ++ while (ecc_step) { ++ u_char err_num; ++ ++ err_num = GET_ECC_ERR_NUM(--ecc_step, reg); ++ if (err_num == 0xff) ++ mtd->ecc_stats.failed++; ++ else ++ mtd->ecc_stats.corrected += err_num; ++ } ++ } ++ ++ return; ++} ++ ++/*****************************************************************************/ ++static void hisnfc100_select_chip(struct mtd_info *mtd, int chipselect) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hisnfc_host *host = chip->priv; ++ ++ if (chipselect < 0) ++ return; ++ ++ if (chipselect > CONFIG_HISNFC100_MAX_CHIP) ++ DBG_BUG("invalid chipselect: %d\n", chipselect); ++ ++ host->cmd_option.chipselect = chipselect + 1; ++ ++ switch (chip->state) { ++ case FL_ERASING: ++ host->cmd_option.last_cmd = NAND_CMD_ERASE1; ++ break; ++ ++ case FL_WRITING: ++ host->cmd_option.last_cmd = NAND_CMD_PAGEPROG; ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++/*****************************************************************************/ ++static void hisnfc100_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned ctrl) ++{ ++ unsigned char cmd; ++ int is_cache_invalid = 1; ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hisnfc_host *host = chip->priv; ++ ++ if (ctrl & NAND_ALE) { ++ unsigned int addr_value = 0; ++ unsigned int addr_offset = 0; ++ ++ if (ctrl & NAND_CTRL_CHANGE) { ++ host->addr_cycle = 0x0; ++ host->addr_value[0] = 0x0; ++ host->addr_value[1] = 0x0; ++ } ++ addr_offset = host->addr_cycle << 3; ++ ++ if (host->addr_cycle >= HISNFC100_ADDR_CYCLE_MASK) { ++ addr_offset = (host->addr_cycle - ++ HISNFC100_ADDR_CYCLE_MASK) << 3; ++ addr_value = 1; ++ } ++ ++ host->addr_value[addr_value] |= ++ ((dat & 0xff) << addr_offset); ++ ++ host->addr_cycle++; ++ } ++ ++ if ((ctrl & NAND_CLE) && (ctrl & NAND_CTRL_CHANGE)) { ++ cmd = dat & 0xff; ++ host->cmd_option.command = cmd; ++ switch (cmd) { ++ case NAND_CMD_PAGEPROG: ++ host->offset = 0; ++ host->send_cmd_pageprog(host); ++ break; ++ ++ case NAND_CMD_READSTART: ++ is_cache_invalid = 0; ++ if (host->addr_value[0] == host->pagesize) ++ host->cmd_option.last_cmd = NAND_CMD_READOOB; ++ host->send_cmd_readstart(host); ++ break; ++ ++ case NAND_CMD_ERASE2: ++ host->cmd_option.last_cmd = cmd; ++ host->send_cmd_erase(host); ++ break; ++ ++ case NAND_CMD_READID: ++ memset((unsigned char *)(chip->IO_ADDR_R), 0, ++ MAX_ID_LEN); ++ host->cmd_option.last_cmd = cmd; ++ host->cmd_option.date_num = MAX_ID_LEN; ++ host->send_cmd_readid(host); ++ break; ++ ++ case NAND_CMD_STATUS: ++ host->send_cmd_status(host); ++ break; ++ ++ case NAND_CMD_SEQIN: ++ break; ++ ++ case NAND_CMD_ERASE1: ++ break; ++ ++ case NAND_CMD_READ0: ++ host->cmd_option.last_cmd = cmd; ++ break; ++ ++ case NAND_CMD_RESET: ++ host->send_cmd_reset(host); ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ if ((dat == NAND_CMD_NONE) && host->addr_cycle) { ++ if (host->cmd_option.command == NAND_CMD_SEQIN ++ || host->cmd_option.command == NAND_CMD_READ0 ++ || host->cmd_option.command == NAND_CMD_READID) { ++ host->offset = 0x0; ++ host->column = (host->addr_value[0] & 0xffff); ++ } ++ } ++ ++ if (is_cache_invalid) { ++ host->cache_addr_value[0] = ~0; ++ host->cache_addr_value[1] = ~0; ++ } ++} ++ ++/*****************************************************************************/ ++static int hisnfc100_dev_ready(struct mtd_info *mtd) ++{ ++ unsigned regval; ++ unsigned deadline = 0; ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hisnfc_host *host = chip->priv; ++ ++ do { ++ spi_feature_op(host, GET_OP, STATUS_ADDR, ®val); ++ if (!(regval & STATUS_OIP_MASK)) ++ return 1; ++ udelay(1); ++ } while (deadline++ < (40 << 20)); ++ ++ pr_info("Wait spi nand flash ready timeout.\n"); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++/* ++ * 'host->epm' only use the first oobfree[0] field, it looks very simple, But... ++ */ ++/* Default OOB area layout */ ++static int hisnfc_ooblayout_ecc_64(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->length = 32; ++ oobregion->offset = 32; ++ ++ return 0; ++} ++ ++static int hisnfc_ooblayout_free_64(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section) ++ return -ERANGE; ++ ++ oobregion->length = 30; ++ oobregion->offset = 2; ++ ++ return 0; ++} ++ ++static struct mtd_ooblayout_ops hisnfc_ooblayout_64_ops = { ++ .ecc = hisnfc_ooblayout_ecc_64, ++ .free = hisnfc_ooblayout_free_64, ++}; ++ ++/*****************************************************************************/ ++static struct nand_config_info hisnfc_spi_nand_config_table[] = { ++ {NAND_PAGE_4K, NAND_ECC_24BIT, 24, 200, &hisnfc_ooblayout_64_ops}, ++ {NAND_PAGE_4K, NAND_ECC_16BIT, 16, 144, &hisnfc_ooblayout_64_ops}, ++ {NAND_PAGE_4K, NAND_ECC_8BIT, 8, 128/*88*/, &hisnfc_ooblayout_64_ops}, ++ {NAND_PAGE_4K, NAND_ECC_0BIT, 0, 32, &hisnfc_ooblayout_64_ops}, ++ ++ {NAND_PAGE_2K, NAND_ECC_24BIT, 24, 128/*116*/, &hisnfc_ooblayout_64_ops}, ++ {NAND_PAGE_2K, NAND_ECC_16BIT, 16, 88, &hisnfc_ooblayout_64_ops}, ++ {NAND_PAGE_2K, NAND_ECC_8BIT, 8, 64/*60*/, &hisnfc_ooblayout_64_ops}, ++ {NAND_PAGE_2K, NAND_ECC_0BIT, 0, 32, &hisnfc_ooblayout_64_ops}, ++ ++ {0, 0, 0, 0, NULL}, ++}; ++ ++/*****************************************************************************/ ++/* used the best correct arithmetic. */ ++struct nand_config_info *hisnfc100_get_best_ecc(struct mtd_info *mtd) ++{ ++ struct nand_config_info *best = NULL; ++ struct nand_config_info *info = hisnfc_spi_nand_config_table; ++ ++ for (; info->ooblayout_ops; info++) { ++ if (nandpage_type2size(info->pagetype) != mtd->writesize) ++ continue; ++ ++ if (mtd->oobsize < info->oobsize) ++ continue; ++ ++ if (!best || (best->ecctype < info->ecctype)) ++ best = info; ++ } ++ ++ if (!best) ++ DBG_BUG(ERSTR_DRIVER "Driver does not support the pagesize" \ ++ "(%d) and oobsize(%d).\n", mtd->writesize, mtd->oobsize); ++ ++ return best; ++} ++ ++/*****************************************************************************/ ++/* force the pagesize and ecctype */ ++struct nand_config_info *hisnfc100_force_ecc(struct mtd_info *mtd, int pagetype, ++ int ecctype, char *cfgmsg, int allow_pagediv) ++{ ++ int pagesize; ++ struct nand_config_info *fit = NULL; ++ struct nand_config_info *info = hisnfc_spi_nand_config_table; ++ ++ for (; info->ooblayout_ops; info++) { ++ if (info->pagetype == pagetype && info->ecctype == ecctype) { ++ fit = info; ++ break; ++ } ++ } ++ ++ if (!fit) { ++ DBG_BUG(ERSTR_DRIVER "Driver(%s mode) does not support this" \ ++ " Nand Flash pagesize:%s, ecctype:%s\n", cfgmsg, ++ nand_page_name(pagetype), nand_ecc_name(ecctype)); ++ return NULL; ++ } ++ ++ pagesize = nandpage_type2size(pagetype); ++ if ((pagesize != mtd->writesize) ++ && (pagesize > mtd->writesize || !allow_pagediv)) { ++ DBG_BUG(ERSTR_HARDWARE "Hardware (%s mode) configure pagesize" \ ++ " %d, but the Nand Flash pageszie is %d\n", cfgmsg, ++ pagesize, mtd->writesize); ++ return NULL; ++ } ++ ++ if (fit->oobsize > mtd->oobsize) { ++ DBG_BUG(ERSTR_HARDWARE "(%s mode) The Nand Flash offer space" \ ++ " area is %d bytes, but the controller request %d" \ ++ "bytes in ecc %s. Please make sure the hardware ECC " \ ++ "configuration is correct.", cfgmsg, mtd->oobsize, ++ fit->oobsize, nand_ecc_name(ecctype)); ++ return NULL; ++ } ++ ++ return fit; ++} ++ ++/*****************************************************************************/ ++int hisnfc100_ecc_probe(struct mtd_info *mtd, struct nand_chip *chip, ++ struct nand_dev_t *nand_dev) ++{ ++ char *start_type = "unknown"; ++ struct nand_config_info *best = NULL; ++ struct hisnfc_host *host = chip->priv; ++ struct mtd_oob_region *hisnfc_oobregion; ++ unsigned reg_pagetype, reg_ecctype, pagetype, ecctype; ++ ++ hisnfc_oobregion = kmalloc(sizeof(struct mtd_oob_region), GFP_KERNEL); ++ if (!hisnfc_oobregion) { ++ PR_BUG("failed to allocate hinfc_oobregion structure.\n"); ++ return -ENOMEM; ++ } ++ ++#ifdef CONFIG_HISNFC100_AUTO_PAGESIZE_ECC ++ best = hisnfc100_get_best_ecc(mtd); ++ start_type = "Auto"; ++#endif /* CONFIG_HISNFC100_AUTO_PAGESIZE_ECC */ ++ ++#ifdef CONFIG_HISNFC100_HARDWARE_PAGESIZE_ECC ++# ifdef CONFIG_HISNFC100_AUTO_PAGESIZE_ECC ++# error you SHOULD NOT define CONFIG_HISNFC100_AUTO_PAGESIZE_ECC \ ++ and CONFIG_HISNFC100_HARDWARE_PAGESIZE_ECC at the same time ++# endif ++ ++ reg_pagetype = (host->NFC_CFG & PAGE_SIZE_MASK) >> PAGE_SIZE_SHIFT; ++ switch (reg_pagetype) { ++ case 0: ++ pagetype = NAND_PAGE_2K; ++ break; ++ case 1: ++ pagetype = NAND_PAGE_4K; ++ break; ++ default: ++ pagetype = NAND_PAGE_2K; ++ } ++ ++ reg_ecctype = (host->NFC_CFG & ECC_TYPE_MASK) >> ECC_TYPE_SHIFT; ++ switch (reg_ecctype) { ++ case 0x01: ++ ecctype = NAND_ECC_8BIT; ++ break; ++ case 0x02: ++ ecctype = NAND_ECC_16BIT; ++ break; ++ case 0x03: ++ ecctype = NAND_ECC_24BIT; ++ break; ++ case 0: ++ default: ++ ecctype = NAND_ECC_8BIT; ++ } ++ best = hisnfc100_force_ecc(mtd, pagetype, ecctype, ++ "hardware config", 0); ++ start_type = "Hardware"; ++ ++#endif /* CONFIG_HISNFC100_HARDWARE_PAGESIZE_ECC */ ++ ++#ifdef CONFIG_HISNFC100_PAGESIZE_AUTO_ECC_NONE ++# ifdef CONFIG_HISNFC100_AUTO_PAGESIZE_ECC ++# error you SHOULD NOT define CONFIG_HISNFC100_PAGESIZE_AUTO_ECC_NONE \ ++ and CONFIG_HISNFC100_AUTO_PAGESIZE_ECC at the same time ++# endif ++# ifdef CONFIG_HISNFC100_HARDWARE_PAGESIZE_ECC ++# error you SHOULD NOT define CONFIG_HISNFC100_PAGESIZE_AUTO_ECC_NONE \ ++ and CONFIG_HISNFC100_HARDWARE_PAGESIZE_ECC at the same time ++# endif ++ ++ { ++ int pagetype; ++ ++ switch (mtd->writesize) { ++ case _2K: ++ pagetype = NAND_PAGE_2K; ++ break; ++ case _4K: ++ pagetype = NAND_PAGE_4K; ++ break; ++ default: ++ pagetype = NAND_PAGE_2K; ++ break; ++ } ++ best = hisnfc100_force_ecc(mtd, pagetype, NAND_ECC_0BIT, ++ "force config", 0); ++ start_type = "AutoForce"; ++ } ++#endif /* CONFIG_HISNFC100_PAGESIZE_AUTO_ECC_NONE */ ++ ++ if (!best) ++ DBG_BUG(ERSTR_HARDWARE ++ "Please configure SPI Nand Flash pagesize and ecctype!\n"); ++ ++ if (best->ecctype != NAND_ECC_0BIT) ++ mtd->oobsize = best->oobsize; ++ ++ host->ecctype = best->ecctype; ++ host->pagesize = nandpage_type2size(best->pagetype); ++ host->oobsize = mtd->oobsize; ++ host->block_page_mask = ((mtd->erasesize / mtd->writesize) - 1); ++ ++ host->dma_oob = host->dma_buffer + host->pagesize; ++ ++ host->bbm = (unsigned char *)(host->buffer + host->pagesize ++ + HINFC_BAD_BLOCK_POS); ++ ++ if (best->ooblayout_ops->free) ++ best->ooblayout_ops->free(mtd, 0, hisnfc_oobregion); ++ ++ host->epm = (unsigned short *)(host->buffer + host->pagesize ++ + hisnfc_oobregion->offset + 28); ++ ++ mtd_set_ooblayout(mtd, &hisnfc_ooblayout_64_ops); ++ ++ host->NFC_CFG |= (HISNFC100_CFG_ECC_TYPE(best->ecctype) ++ | HISNFC100_CFG_PAGE_SIZE(best->pagetype) ++ | HISNFC100_CFG_OP_MODE(OP_MODE_NORMAL)); ++ ++ if (mtd->writesize > SPI_NAND_MAX_PAGESIZE ++ || mtd->oobsize > SPI_NAND_MAX_OOBSIZE) { ++ DBG_BUG(ERSTR_DRIVER "Driver does not support this Nand " \ ++ "Flash. Please increase SPI_NAND_MAX_PAGESIZE and " \ ++ "SPI_NAND_MAX_OOBSIZE.\n"); ++ } ++ ++ if (mtd->writesize != host->pagesize) { ++ unsigned int shift = 0; ++ unsigned int writesize = mtd->writesize; ++ while (writesize > host->pagesize) { ++ writesize >>= 1; ++ shift++; ++ } ++ chip->chipsize = chip->chipsize >> shift; ++ mtd->erasesize = mtd->erasesize >> shift; ++ mtd->writesize = host->pagesize; ++ pr_info("Nand divide into 1/%u\n", (1 << shift)); ++ } ++ ++ nand_dev->start_type = start_type; ++ nand_dev->ecctype = host->ecctype; ++ nand_dev->oobsize = host->oobsize; ++ ++ /* All SPI NAND are small-page, SLC */ ++ chip->bits_per_cell = 1; ++ ++ kfree(hisnfc_oobregion); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++void hisnfc100_nand_init(struct nand_chip *chip) ++{ ++ chip->read_byte = hisnfc100_read_byte; ++ chip->read_word = hisnfc100_read_word; ++ chip->write_buf = hisnfc100_write_buf; ++ chip->read_buf = hisnfc100_read_buf; ++ ++ chip->select_chip = hisnfc100_select_chip; ++ ++ chip->cmd_ctrl = hisnfc100_cmd_ctrl; ++ chip->dev_ready = hisnfc100_dev_ready; ++ ++ chip->chip_delay = HISNFC100_CHIP_DELAY; ++ ++ chip->options = NAND_SKIP_BBTSCAN; ++ ++ chip->ecc.mode = NAND_ECC_NONE; ++} ++ ++/*****************************************************************************/ ++int hisnfc100_host_init(struct hisnfc_host *host) ++{ ++ unsigned regval; ++ ++ regval = hisfc_read(host, HISNFC100_CFG); ++ if (((regval & DEVICE_TYPE_MASK) >> DEVICE_TYPE_SHIFT) ++ != DEVICE_TYPE_NAND_FLASH) { ++ pr_info("%s: Device type(SPI nor flash) error.\n", __func__); ++ return -ENXIO; ++ } ++ ++ if ((regval & OP_MODE_MASK) == OP_MODE_BOOT) ++ regval |= HISNFC100_CFG_OP_MODE(OP_MODE_NORMAL); ++ ++ if (!(regval & HISNFC100_CFG_DEVICE_INTERNAL_ECC_ENABLE)) ++ regval &= ~HISNFC100_CFG_DEVICE_INTERNAL_ECC_ENABLE; ++ ++ hisfc_write(host, HISNFC100_CFG, regval); ++ ++ host->NFC_CFG = regval; ++ ++ host->addr_cycle = 0; ++ host->addr_value[0] = 0; ++ host->addr_value[1] = 0; ++ host->cache_addr_value[0] = ~0; ++ host->cache_addr_value[1] = ~0; ++ ++ host->send_cmd_pageprog = hisnfc100_send_cmd_pageprog; ++ host->send_cmd_status = hisnfc100_send_cmd_status; ++ host->send_cmd_readstart = hisnfc100_send_cmd_readstart; ++ host->send_cmd_erase = hisnfc100_send_cmd_erase; ++ host->send_cmd_readid = hisnfc100_send_cmd_readid; ++ host->send_cmd_reset = hisnfc100_send_cmd_reset; ++ host->set_system_clock = hisnfc100_set_system_clock; ++ ++ hisfc_write(host, HISNFC100_TIMING_CFG, ++ HISNFC100_TIMING_CFG_TCSH(CS_HOLD_TIME) ++ | HISNFC100_TIMING_CFG_TCSS(CS_SETUP_TIME) ++ | HISNFC100_TIMING_CFG_TSHSL(CS_DESELECT_TIME)); ++ return 0; ++} ++ +diff --git a/drivers/mtd/nand/hisnfc100/hisnfc100.h b/drivers/mtd/nand/hisnfc100/hisnfc100.h +new file mode 100644 +index 0000000..ae74408 +--- /dev/null ++++ b/drivers/mtd/nand/hisnfc100/hisnfc100.h +@@ -0,0 +1,375 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef HISNFC100H ++#define HISNFC100H ++ ++#include "../hinfc_gen.h" ++ ++/******************************************************************************/ ++/* These macroes are for debug only, reg option is slower then dma option */ ++#undef HISNFC100_SUPPORT_REG_READ ++/* #define HISNFC100_SUPPORT_REG_READ */ ++ ++#undef HISNFC100_SUPPORT_REG_WRITE ++/* #define HISNFC100_SUPPORT_REG_WRITE */ ++ ++/*****************************************************************************/ ++#define HISNFC100_CFG 0x00 ++#define HISNFC100_CFG_BOOT_MODE(_mode) ((_mode) << 17) ++#define HISNFC100_CFG_DEVICE_INTERNAL_ECC_ENABLE (1 << 16) ++#define HISNFC100_CFG_FLASH_SIZE_CS1(_size) (((_size) & 0xf) << 10) ++#define HISNFC100_CFG_FLASH_SIZE_CS0(_size) (((_size) & 0xf) << 6) ++#define HISNFC100_CFG_ADDR_MODE(_mode) ((_mode) << 5) ++#define HISNFC100_CFG_ECC_TYPE(type) (((type) & 0x3) << 3) ++#define HISNFC100_CFG_PAGE_SIZE(size) ((size) << 2) ++#define HISNFC100_CFG_DEVICE_TYPE(_type) ((_type) << 1) ++#define HISNFC100_CFG_OP_MODE(_mode) ((_mode) << 0) ++ ++#define BOOT_MODE_MASK (0x1 << 17) ++ ++#define FLASH_SIZE_CS1_SHIFT 10 ++#define FLASH_SIZE_CS1_MASK (0xf << 10) ++ ++#define FLASH_SIZE_CS0_SHIFT 6 ++#define FLASH_SIZE_CS0_MASK (0xf << 6) ++ ++#define ECC_TYPE_SHIFT 3 ++#define ECC_TYPE_MASK (0x3 << 3) ++ ++#define PAGE_SIZE_SHIFT 2 ++#define PAGE_SIZE_MASK (0x1 << 2) ++ ++#define DEVICE_TYPE_SHIFT 1 ++#define DEVICE_TYPE_MASK (0x1 << 1) ++#define DEVICE_TYPE_NOR_FLASH 0 ++#define DEVICE_TYPE_NAND_FLASH 1 ++ ++#define OP_MODE_MASK (0x1 << 0) ++#define OP_MODE_BOOT 0 ++#define OP_MODE_NORMAL 1 ++ ++/*****************************************************************************/ ++#define HISNFC100_GLOBAL_CFG 0x04 ++#define HISNFC100_GLOBAL_CFG_WP_ENABLE (1 << 5) ++ ++/*****************************************************************************/ ++#define HISNFC100_TIMING_CFG 0x08 ++#define HISNFC100_TIMING_CFG_TCSH(_n) (((_n) & 0xf) << 8) ++#define HISNFC100_TIMING_CFG_TCSS(_n) (((_n) & 0xf) << 4) ++#define HISNFC100_TIMING_CFG_TSHSL(_n) ((_n) & 0xf) ++ ++#define CS_HOLD_TIME 0x6 ++#define CS_SETUP_TIME 0x6 ++#define CS_DESELECT_TIME 0xf ++ ++/*****************************************************************************/ ++#define HISNFC100_INT 0x0c ++#define HISNFC100_INT_OP_DONE (1 << 0) ++ ++/*****************************************************************************/ ++#define HISNFC100_INT_CLR 0x14 ++#define HISNFC100_INT_CLR_DMA_ERR (1 << 5) ++#define HISNFC100_INT_CLR_OP_FAIL (1 << 2) ++#define HISNFC100_INT_CLR_OP_DONE (1 << 0) ++ ++#define HISNFC100_INT_CLR_ALL 0x7f ++ ++/*****************************************************************************/ ++#define HISNFC100_OPCODE 0x18 ++ ++/*****************************************************************************/ ++#define HISNFC100_OP_ADDR 0x1c ++#define HISNFC100_OP_ADDRH_BLOCK_MASK(_page) (((_page) & 0xffff) << 16) ++#define HISNFC100_OP_ADDRL_BLOCK_MASK(_page) ((_page) & 0xffc0) ++ ++#define READ_ID_ADDR 0x00 ++#define PROTECTION_ADDR 0xa0 ++#define FEATURE_ADDR 0xb0 ++#define STATUS_ADDR 0xc0 ++ ++/*****************************************************************************/ ++#define HISNFC100_OP 0x20 ++#define HISNFC100_OP_SEL_CS(_cs) ((_cs) << 11) ++#define HISNFC100_OP_ADDR_NUM(_n) (((_n) & 0x7) << 8) ++#define HISNFC100_OP_DUMMY_CMD_EN(_en) ((_en) << 7) ++#define HISNFC100_OP_DUMMY_ADDR_EN(_en) ((_en) << 6) ++#define HISNFC100_OP_OPCODE_EN(_en) ((_en) << 5) ++#define HISNFC100_OP_ADDR_EN(_en) ((_en) << 4) ++#define HISNFC100_OP_DATE_WRITE_EN(_en) ((_en) << 3) ++#define HISNFC100_OP_DATE_READ_EN(_en) ((_en) << 2) ++#define HISNFC100_OP_STATUS_READ_EN(_en) ((_en) << 1) ++#define HISNFC100_OP_START (1 << 0) ++ ++#define STD_OP_ADDR_NUM 3 ++#define READ_ID_ADDR_NUM 1 ++ ++#define FEATURES_OP_ADDR_NUM 1 ++ ++/*****************************************************************************/ ++#define HISNFC100_DATA_NUM 0x24 ++#define HISNFC100_DATA_NUM_CNT(_n) ((_n) & 0x1fff) ++ ++#define FEATURES_DATE_NUM 1 ++ ++#define READ_OOB_BB_LEN 1 ++ ++/*****************************************************************************/ ++#define HISNFC100_OP_CFG 0x28 ++#define HISNFC100_OP_CFG_DIR_TRANS_ENABLE (1 << 11) ++#define HISNFC100_OP_CFG_RD_OP_SEL(_type) (((_type) & 0x3) << 9) ++#define HISNFC100_OP_CFG_MEM_IF_TYPE(_type) (((_type) & 0x7) << 6) ++#define HISNFC100_OP_CFG_DUMMY_CMD_NUM(_no) (((_no) & 0x7) << 3) ++#define HISNFC100_OP_CFG_DUMMY_ADDR_NUM(_no) (((_no) & 0x7) << 0) ++ ++#define RD_OP_READ_PAGE 0x0 ++#define RD_OP_READ_DATE 0x1 ++#define RD_OP_READ_OOB 0x2 ++ ++/*****************************************************************************/ ++#define HISNFC100_ADDRH 0x2c ++#define HISNFC100_ADDRH_SET(_addr) ((_addr) & 0xff) ++ ++/*****************************************************************************/ ++#define HISNFC100_ADDRL 0x30 ++ ++/*****************************************************************************/ ++#define HISNFC100_OP_CTRL 0x34 ++#define HISNFC100_OP_CTRL_RD_OPCODE(_code) (((_code) & 0xff) << 16) ++#define HISNFC100_OP_CTRL_WR_OPCODE(_code) (((_code) & 0xff) << 8) ++#define HISNFC100_OP_CTRL_CS_OP(_cs) ((_cs) << 3) ++#define HISNFC100_OP_CTRL_OP_TYPE(_type) ((_type) << 2) ++#define HISNFC100_OP_CTRL_RW_OP(_op) ((_op) << 1) ++#define HISNFC100_OP_CTRL_OP_READY (1 << 0) ++ ++#define OP_TYPE_REG 0 ++#define OP_TYPE_DMA 1 ++ ++#define RW_OP_READ 0 ++#define RW_OP_WRITE 1 ++ ++/*****************************************************************************/ ++#define HISNFC100_DMA_CTRL 0x3c ++ ++#define HISNFC100_DMA_CTRL_ALL_ENABLE 0x7 ++ ++/*****************************************************************************/ ++#define HISNFC100_DMA_SADDR_D 0x40 ++ ++/*****************************************************************************/ ++#define HISNFC100_DMA_SADDR_OOB 0x44 ++ ++/*****************************************************************************/ ++#define HISNFC100_DMA_LEN 0x48 ++#define HISNFC100_DMA_LEN_SET(_len) ((_len) & 0xfffffff) ++ ++/*****************************************************************************/ ++#define HISNFC100_STATUS 0x54 ++ ++#define GET_OP 0 ++#define SET_OP 1 ++ ++#define PROTECTION_BRWD_MASK (1 << 7) ++#define PROTECTION_BP3_MASK (1 << 6) ++#define PROTECTION_BP2_MASK (1 << 5) ++#define PROTECTION_BP1_MASK (1 << 4) ++#define PROTECTION_BP0_MASK (1 << 3) ++ ++#define ANY_BP_ENABLE(_val) ((PROTECTION_BP3_MASK & _val) \ ++ || (PROTECTION_BP2_MASK & _val) \ ++ || (PROTECTION_BP1_MASK & _val) \ ++ || (PROTECTION_BP0_MASK & _val)) ++ ++#define ALL_BP_MASK (PROTECTION_BP3_MASK \ ++ | PROTECTION_BP2_MASK \ ++ | PROTECTION_BP1_MASK \ ++ | PROTECTION_BP0_MASK) ++ ++#define FEATURE_ECC_ENABLE (1 << 4) ++#define FEATURE_QE_ENABLE (1 << 0) ++ ++#define STATUS_ECC_MASK (0x3 << 4) ++#define STATUS_P_FAIL_MASK (1 << 3) ++#define STATUS_E_FAIL_MASK (1 << 2) ++#define STATUS_WEL_MASK (1 << 1) ++#define STATUS_OIP_MASK (1 << 0) ++ ++/*****************************************************************************/ ++#define HISNFC100_VERSION 0x68 ++ ++/*****************************************************************************/ ++#define HISNFC100_ECC_ERR_NUM 0x6c ++ ++#define GET_ECC_ERR_NUM(_i, _reg) (((_reg) >> ((_i) * 8)) & 0xff) ++ ++/*****************************************************************************/ ++#define REG_CNT_HIGH_BLOCK_NUM_SHIFT 10 ++ ++#define REG_CNT_BLOCK_NUM_MASK 0x3ff ++#define REG_CNT_BLOCK_NUM_SHIFT 22 ++ ++#define REG_CNT_PAGE_NUM_MASK 0x3f ++#define REG_CNT_PAGE_NUM_SHIFT 16 ++ ++#define REG_CNT_WRAP_MASK 0xf ++#define REG_CNT_WRAP_SHIFT 12 ++ ++#define REG_CNT_ECC_OFFSET_MASK 0xfff ++#define REG_CNT_ECC_8BIT_OFFSET 1054 ++#define REG_CNT_ECC_16BIT_OFFSET 1056 ++#define REG_CNT_ECC_24BIT_OFFSET 1082 ++ ++/*****************************************************************************/ ++#define SPI_NAND_MAX_PAGESIZE 4096 ++#define SPI_NAND_MAX_OOBSIZE 256 ++ ++#define HISNFC100_BUFFER_LEN (SPI_NAND_MAX_PAGESIZE + SPI_NAND_MAX_OOBSIZE) ++ ++/* DMA address align with 32 bytes. */ ++#define HISNFC100_DMA_ALIGN 32 ++ ++#define HISNFC100_CHIP_DELAY 25 ++ ++#define HISNFC100_ADDR_CYCLE_MASK 0x2 ++ ++/*****************************************************************************/ ++struct hisfc_cmd_option { ++ unsigned char chipselect; ++ unsigned char command; ++ unsigned char last_cmd; ++ unsigned char address_h; ++ unsigned int address_l; ++ unsigned int date_num; ++ unsigned short option; ++ unsigned short op_config; ++}; ++ ++struct hisnfc_host; ++ ++struct hisnfc_host { ++ struct nand_chip *chip; ++ struct mtd_info *mtd; ++ struct hisnfc_op spi[CONFIG_HISNFC100_MAX_CHIP]; ++ struct hisfc_cmd_option cmd_option; ++ ++ void __iomem *iobase; ++ void __iomem *regbase; ++ ++ unsigned int NFC_CFG; ++ ++ unsigned int offset; ++ ++ struct device *dev; ++ struct clk *clk; ++ ++ unsigned int addr_cycle; ++ unsigned int addr_value[2]; ++ unsigned int cache_addr_value[2]; ++ unsigned int column; ++ unsigned int block_page_mask; ++ ++ unsigned int dma_buffer; ++ unsigned int dma_oob; ++ ++ unsigned int ecctype; ++ unsigned int pagesize; ++ unsigned int oobsize; ++ ++ /* This is maybe an un-aligment address, only for malloc or free */ ++ char *buforg; ++ char *buffer; ++ ++ int add_partition; ++ ++ /* BOOTROM read two bytes to detect the bad block flag */ ++#define HINFC_BAD_BLOCK_POS 0 ++ unsigned char *bbm; /* nand bad block mark */ ++ unsigned short *epm; /* nand empty page mark */ ++ ++ unsigned int uc_er; ++ ++ void (*set_system_clock)(struct spi_op_info *op, int clk_en); ++ ++ void (*send_cmd_pageprog)(struct hisnfc_host *host); ++ void (*send_cmd_status)(struct hisnfc_host *host); ++ void (*send_cmd_readstart)(struct hisnfc_host *host); ++ void (*send_cmd_erase)(struct hisnfc_host *host); ++ void (*send_cmd_readid)(struct hisnfc_host *host); ++ void (*send_cmd_reset)(struct hisnfc_host *host); ++}; ++ ++/*****************************************************************************/ ++#define hisfc_read(_host, _reg) \ ++ readl(_host->regbase + (_reg)) ++ ++#define hisfc_write(_host, _reg, _value) \ ++ writel((_value), _host->regbase + (_reg)) ++ ++/*****************************************************************************/ ++#define DBG_BUG(fmt, args...) do { \ ++ pr_info("%s(%d): BUG: " fmt, __FILE__, __LINE__, ##args); \ ++ while (1) \ ++ ; \ ++} while (0) ++ ++/*****************************************************************************/ ++#define HISNFC100_WAIT_TIMEOUT 10000000 ++ ++#define HISNFC100_CMD_WAIT_CPU_FINISH(_host) do { \ ++ unsigned regval, timeout = HISNFC100_WAIT_TIMEOUT; \ ++ do { \ ++ regval = hisfc_read((_host), HISNFC100_OP); \ ++ --timeout; \ ++ } while ((regval & HISNFC100_OP_START) && timeout); \ ++ if (!timeout) \ ++ DBG_BUG("hisnfc100 wait cmd cpu finish timeout!\n"); \ ++} while (0) ++ ++/*****************************************************************************/ ++#define HISNFC100_DMA_WAIT_INT_FINISH(_host) do { \ ++ unsigned regval, timeout = HISNFC100_WAIT_TIMEOUT; \ ++ do { \ ++ regval = hisfc_read((_host), HISNFC100_INT); \ ++ --timeout; \ ++ } while ((!(regval & HISNFC100_INT_OP_DONE) && timeout)); \ ++ if (!timeout) \ ++ DBG_BUG("hisnfc100 wait dma int finish timeout!\n"); \ ++} while (0) ++ ++/*****************************************************************************/ ++#define HISNFC100_DMA_WAIT_CPU_FINISH(_host) do { \ ++ unsigned regval, timeout = HISNFC100_WAIT_TIMEOUT; \ ++ do { \ ++ regval = hisfc_read((_host), HISNFC100_OP_CTRL); \ ++ --timeout; \ ++ } while ((regval & HISNFC100_OP_CTRL_OP_READY) && timeout); \ ++ if (!timeout) \ ++ DBG_BUG("dma wait cpu finish timeout\n"); \ ++} while (0) ++ ++/*****************************************************************************/ ++int hisnfc100_host_init(struct hisnfc_host *host); ++ ++void hisnfc100_nand_init(struct nand_chip *chip); ++ ++int hisnfc100_ecc_probe(struct mtd_info *mtd, struct nand_chip *chip, ++ struct nand_dev_t *nand_dev); ++ ++/******************************************************************************/ ++#endif /* HISNFC100H */ ++ +diff --git a/drivers/mtd/nand/hisnfc100/hisnfc100_hi3516a.c b/drivers/mtd/nand/hisnfc100/hisnfc100_hi3516a.c +new file mode 100644 +index 0000000..b0e79aa +--- /dev/null ++++ b/drivers/mtd/nand/hisnfc100/hisnfc100_hi3516a.c +@@ -0,0 +1,89 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++ ++#include "hisnfc100_os.h" ++#include "hisnfc100.h" ++ ++/*****************************************************************************/ ++#define HISNFC100_CRG48 0xc0 ++#define HISNFC100_CRG48_SPI_NAND_CLK_SEL(_clk) (((_clk) & 0x3) << 6) ++#define HISNFC100_CRG48_SPI_NAND_CLK_EN (1 << 5) ++#define HISNFC100_CRG48_SPI_NAND_SOFT_RST_REQ (1 << 4) ++ ++#define SPI_NAND_CLK_SEL_MASK (0x3 << 6) ++ ++#define CLK_24M 0 ++#define CLK_75M 1 ++#define CLK_125M 2 ++ ++#define CRG_REG_BASE (0x20030000) ++ ++#define SPI_NAND_CLK_SEL_24M HISNFC100_CRG48_SPI_NAND_CLK_SEL(CLK_24M) ++#define SPI_NAND_CLK_SEL_75M HISNFC100_CRG48_SPI_NAND_CLK_SEL(CLK_75M) ++#define SPI_NAND_CLK_SEL_125M HISNFC100_CRG48_SPI_NAND_CLK_SEL(CLK_125M) ++ ++/*****************************************************************************/ ++void hisnfc100_set_system_clock(struct spi_op_info *op, int clk_en) ++{ ++ unsigned int base = IO_ADDRESS(CRG_REG_BASE); ++ unsigned int regval, old_val; ++ ++ old_val = regval = readl((void *)(base + HISNFC100_CRG48)); ++ ++ regval &= ~SPI_NAND_CLK_SEL_MASK; ++ ++ if (op && op->clock) ++ regval |= op->clock & SPI_NAND_CLK_SEL_MASK; ++ else ++ regval |= SPI_NAND_CLK_SEL_24M; ++ ++ if (clk_en) ++ regval |= HISNFC100_CRG48_SPI_NAND_CLK_EN; ++ else ++ regval &= ~HISNFC100_CRG48_SPI_NAND_CLK_EN; ++ ++ if (regval != old_val) ++ writel(regval, (void *)(base + HISNFC100_CRG48)); ++} ++ ++/*****************************************************************************/ ++void hisnfc100_get_best_clock(unsigned int *clock) ++{ ++ int ix; ++ int clk_reg; ++#define CLK_2X(_clk) (((_clk) + 1) >> 1) ++ unsigned int sysclk[] = { ++ CLK_2X(24), SPI_NAND_CLK_SEL_24M, ++ CLK_2X(75), SPI_NAND_CLK_SEL_75M, ++ CLK_2X(125), SPI_NAND_CLK_SEL_125M, ++ 0, 0, ++ }; ++#undef CLK_2X ++ ++ clk_reg = SPI_NAND_CLK_SEL_24M; ++ for (ix = 0; sysclk[ix]; ix += 2) { ++ if (*clock < sysclk[ix]) ++ break; ++ clk_reg = sysclk[ix + 1]; ++ } ++ ++ *clock = clk_reg; ++} ++ +diff --git a/drivers/mtd/nand/hisnfc100/hisnfc100_os.c b/drivers/mtd/nand/hisnfc100/hisnfc100_os.c +new file mode 100644 +index 0000000..f16ba47 +--- /dev/null ++++ b/drivers/mtd/nand/hisnfc100/hisnfc100_os.c +@@ -0,0 +1,179 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include "hisnfc100_os.h" ++#include "hisnfc100_spi_ids.h" ++#include "hisnfc100.h" ++ ++/*****************************************************************************/ ++static int hisnfc100_os_probe(struct platform_device *pltdev) ++{ ++ int size, result = 0; ++ struct hisnfc_host *host; ++ struct nand_chip *chip; ++ struct mtd_info *mtd; ++ struct resource *res1, *res2 = NULL; ++ struct device *dev = &pltdev->dev; ++ struct device_node *np = NULL; ++ ++ size = sizeof(struct hisnfc_host) + sizeof(struct nand_chip) ++ + sizeof(struct mtd_info); ++ host = kmalloc(size, GFP_KERNEL); ++ if (!host) { ++ PR_BUG("failed to allocate device structure.\n"); ++ return -ENOMEM; ++ } ++ memset((char *)host, 0, size); ++ platform_set_drvdata(pltdev, host); ++ ++ host->dev = dev; ++ host->chip = chip = (struct nand_chip *)&host[1]; ++ host->mtd = mtd = nand_to_mtd(chip);; ++ ++ host->clk = devm_clk_get(dev, NULL); ++ if (IS_ERR(host->clk)) ++ return PTR_ERR(host->clk); ++ /* enable and set system clock */ ++ clk_prepare_enable(host->clk); ++ ++ res1 = platform_get_resource_byname(pltdev, IORESOURCE_MEM, "control"); ++ host->regbase = devm_ioremap_resource(dev, res1); ++ if (IS_ERR(host->iobase)) { ++ PR_BUG("Error: Can't get resource for reg address.\n"); ++ result = -EIO; ++ goto fail; ++ } ++ ++ res2 = platform_get_resource_byname(pltdev, IORESOURCE_MEM, "memory"); ++ host->iobase = devm_ioremap_resource(dev, res2); ++ if (IS_ERR(host->iobase)) { ++ PR_BUG("Error: Can't get resource for buffer address.\n"); ++ result = -EIO; ++ goto fail; ++ } ++ ++ memset((char *)host->iobase, 0xff, HISNFC100_BUFFER_BASE_ADDRESS_LEN); ++ chip->IO_ADDR_R = chip->IO_ADDR_W = host->iobase; ++ ++ host->buffer = dma_alloc_coherent(host->dev, HISNFC100_BUFFER_LEN, ++ &host->dma_buffer, GFP_KERNEL); ++ if (!host->buffer) { ++ PR_BUG("Can't malloc memory for SPI Nand driver."); ++ result = -ENOMEM; ++ goto fail; ++ } ++ memset(host->buffer, 0xff, HISNFC100_BUFFER_LEN); ++ ++ np = of_get_next_available_child(dev->of_node, NULL); ++ mtd->priv = chip; ++ mtd->owner = THIS_MODULE; ++ mtd->type = MTD_NANDFLASH; ++ mtd->name = np->name; ++ ++ result = hisnfc100_host_init(host); ++ if (result) ++ return result; ++ ++ chip->priv = host; ++ hisnfc100_nand_init(chip); ++ ++ spi_nand_ids_register(); ++ hinfc_param_adjust = hisnfc100_ecc_probe; ++ ++ if (nand_scan(mtd, CONFIG_HISNFC100_MAX_CHIP)) { ++ result = -ENXIO; ++ goto fail; ++ } ++ ++ result = mtd_device_register(mtd, NULL, 0); ++ if (result) ++ goto fail; ++ ++ return result; ++ ++fail: ++ if (host->buffer) { ++ dma_free_coherent(host->dev, HISNFC100_BUFFER_LEN, ++ host->buffer, host->dma_buffer); ++ host->buffer = NULL; ++ } ++ nand_release(host->mtd); ++ kfree(host); ++ platform_set_drvdata(pltdev, NULL); ++ ++ return result; ++} ++/*****************************************************************************/ ++ ++static int hisnfc100_os_remove(struct platform_device *pltdev) ++{ ++ struct hisnfc_host *host = platform_get_drvdata(pltdev); ++ ++ clk_disable_unprepare(host->clk); ++ ++ nand_release(host->mtd); ++ dma_free_coherent(host->dev, ++ (SPI_NAND_MAX_PAGESIZE + SPI_NAND_MAX_OOBSIZE), ++ host->buffer, host->dma_buffer); ++ kfree(host); ++ platform_set_drvdata(pltdev, NULL); ++ ++ return 0; ++} ++/*****************************************************************************/ ++#ifdef CONFIG_PM ++/*****************************************************************************/ ++static int hisnfc100_os_suspend(struct platform_device *pltdev, ++ pm_message_t state) ++{ ++ return 0; ++} ++ ++/*****************************************************************************/ ++static int hisnfc100_os_resume(struct platform_device *pltdev) ++{ ++ return 0; ++} ++#endif /* CONFIG_PM */ ++ ++/*****************************************************************************/ ++static const struct of_device_id hisi_spi_nand_dt_ids[] = { ++ { .compatible = "hisilicon,hisi-spi-nand" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, hisi_spi_nand_dt_ids); ++ ++static struct platform_driver hisi_nand_driver = { ++ .driver = { ++ .name = "hisi-nand", ++ .of_match_table = hisi_spi_nand_dt_ids, ++ }, ++ .probe = hisnfc100_os_probe, ++ .remove = hisnfc100_os_remove, ++#ifdef CONFIG_PM ++ .suspend = hisnfc100_os_suspend, ++ .resume = hisnfc100_os_resume, ++#endif ++}; ++module_platform_driver(hisi_nand_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("BVT_BSP"); ++MODULE_DESCRIPTION("Hisilicon snfc Device Driver, Version 100"); ++ +diff --git a/drivers/mtd/nand/hisnfc100/hisnfc100_os.h b/drivers/mtd/nand/hisnfc100/hisnfc100_os.h +new file mode 100644 +index 0000000..e8daeb4 +--- /dev/null ++++ b/drivers/mtd/nand/hisnfc100/hisnfc100_os.h +@@ -0,0 +1,74 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef HISNFC100_OSH ++#define HISNFC100_OSH ++ ++/*****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 5)) ++ #include "../../mtdcore.h" ++#endif ++ ++#define HISNFC100_BUFFER_BASE_ADDRESS_LEN (2048 + 256) ++ ++/*****************************************************************************/ ++#ifndef CONFIG_HISNFC100_MAX_CHIP ++# define CONFIG_HISNFC100_MAX_CHIP (1) ++# warning NOT config CONFIG_HISNFC100_MAX_CHIP, \ ++ used default value, maybe invalid. ++#endif /* CONFIG_HISNFC100_MAX_CHIP */ ++ ++/*****************************************************************************/ ++#define PR_BUG(fmt, args...) do { \ ++ pr_info("%s(%d): bug " fmt, __FILE__, __LINE__, ##args); \ ++ asm("b ."); \ ++} while (0) ++ ++#if 1 ++# define DBG_MSG(_fmt, arg...) ++#else ++# define DBG_MSG(_fmt, arg...) \ ++ printk(KERN_INFO "%s(%d): " _fmt, __FILE__, __LINE__, ##arg); ++#endif ++ ++#endif /* HISNFC100_OSH */ ++ +diff --git a/drivers/mtd/nand/hisnfc100/hisnfc100_spi_general.c b/drivers/mtd/nand/hisnfc100/hisnfc100_spi_general.c +new file mode 100644 +index 0000000..af8c06e +--- /dev/null ++++ b/drivers/mtd/nand/hisnfc100/hisnfc100_spi_general.c +@@ -0,0 +1,200 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hisnfc100_os.h" ++#include "hisnfc100.h" ++ ++#define DEBUG_SPI_NAND_DRV 0 ++ ++/*****************************************************************************/ ++/* ++ Send set/get features command to SPI Nand flash ++*/ ++void spi_feature_op(struct hisnfc_host *host, int op, int addr, unsigned *val) ++{ ++ unsigned regval = 0; ++ struct nand_chip *chip = host->chip; ++ ++ hisfc_write(host, HISNFC100_INT_CLR, HISNFC100_INT_CLR_OP_DONE); ++ ++ hisfc_write(host, HISNFC100_OPCODE, ++ (op ? SPI_CMD_SET_FEATURE : SPI_CMD_GET_FEATURES)); ++ hisfc_write(host, HISNFC100_OP_ADDR, addr); ++ ++ hisfc_write(host, HISNFC100_OP_CFG, HISNFC100_OP_CFG_DIR_TRANS_ENABLE); ++ ++ regval = (HISNFC100_OP_SEL_CS(host->cmd_option.chipselect) ++ | HISNFC100_OP_ADDR_NUM(FEATURES_OP_ADDR_NUM) ++ | HISNFC100_OP_OPCODE_EN(ENABLE) ++ | HISNFC100_OP_ADDR_EN(ENABLE) ++ | HISNFC100_OP_START); ++ ++ if (SET_OP == op) { ++ hisfc_write(host, HISNFC100_DATA_NUM, FEATURES_DATE_NUM); ++ regval |= HISNFC100_OP_DATE_WRITE_EN(ENABLE); ++ writeb(*val, chip->IO_ADDR_W); ++ if (DEBUG_SPI_NAND_DRV) ++ pr_info("hisnfc: set feature [%#x]==>[%#x]\n", addr, ++ *val); ++ } else ++ regval |= HISNFC100_OP_STATUS_READ_EN(ENABLE); ++ ++ hisfc_write(host, HISNFC100_OP, regval); ++ ++ HISNFC100_CMD_WAIT_CPU_FINISH(host); ++ ++ if (GET_OP == op) { ++ *val = hisfc_read(host, HISNFC100_STATUS); ++ if (DEBUG_SPI_NAND_DRV && (addr != STATUS_ADDR)) ++ pr_info("hisnfc: get feature [%#x]<==[%#x]\n", addr, ++ *val); ++ } ++} ++ ++/*****************************************************************************/ ++/* ++ Read status[C0H]:[0]bit OIP, judge whether the device is busy or not ++*/ ++static int spi_general_wait_ready(struct hisnfc_op *spi) ++{ ++ unsigned regval = 0; ++ unsigned deadline = 0; ++ struct hisnfc_host *host = (struct hisnfc_host *)spi->host; ++ ++ do { ++ spi_feature_op(host, GET_OP, STATUS_ADDR, ®val); ++ if (!(regval & STATUS_OIP_MASK)) { ++ if ((host->cmd_option.last_cmd == NAND_CMD_ERASE2) ++ && (regval & STATUS_E_FAIL_MASK)) ++ return regval; ++ if ((host->cmd_option.last_cmd == NAND_CMD_PAGEPROG) ++ && (regval & STATUS_P_FAIL_MASK)) ++ return regval; ++ return 0; ++ } ++ udelay(1); ++ } while (deadline++ < (40 << 20)); ++ ++ pr_info("hisnfc: wait ready timeout.\n"); ++ ++ return 1; ++} ++ ++/*****************************************************************************/ ++/* ++ Send write enable command to SPI Nand, status[C0H]:[2]bit WEL must be set 1 ++*/ ++static int spi_general_write_enable(struct hisnfc_op *spi) ++{ ++ unsigned val; ++ struct hisnfc_host *host = (struct hisnfc_host *)spi->host; ++ ++ hisfc_write(host, HISNFC100_INT_CLR, HISNFC100_INT_CLR_OP_DONE); ++ ++ val = hisfc_read(host, HISNFC100_GLOBAL_CFG); ++ if (val & HISNFC100_GLOBAL_CFG_WP_ENABLE) { ++ val &= ~HISNFC100_GLOBAL_CFG_WP_ENABLE; ++ hisfc_write(host, HISNFC100_GLOBAL_CFG, val); ++ } ++ ++ hisfc_write(host, HISNFC100_OPCODE, SPI_CMD_WREN); ++ ++ hisfc_write(host, HISNFC100_OP_CFG, ++ HISNFC100_OP_CFG_DIR_TRANS_ENABLE); ++ ++ hisfc_write(host, HISNFC100_OP, ++ HISNFC100_OP_SEL_CS(host->cmd_option.chipselect) ++ | HISNFC100_OP_OPCODE_EN(ENABLE) ++ | HISNFC100_OP_START); ++ ++ HISNFC100_CMD_WAIT_CPU_FINISH(host); ++ ++ spi_feature_op(host, GET_OP, STATUS_ADDR, &val); ++ if (!(val & STATUS_WEL_MASK)) { ++ pr_info("hisnfc: write enable failed! val[%#x]\n", val); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++/* ++ judge whether SPI Nand support QUAD read/write or not ++*/ ++static int spi_is_quad(struct hisnfc_op *spi) ++{ ++ if (DEBUG_SPI_NAND_DRV) { ++ pr_info("hisnfc: SPI write iftype:%d\n", spi->write->iftype); ++ pr_info("hisnfc: SPI read iftype:%d\n", spi->read->iftype); ++ } ++ ++ if (HISNFC100_IFCYCLE_QUAD == spi->write->iftype ++ || HISNFC100_IFCYCLE_QUAD == spi->read->iftype ++ || HISNFC100_IFCYCLE_QUAD_ADDR == spi->read->iftype) ++ return 1; ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++/* ++ Send set features command to SPI Nand, feature[B0H]:[0]bit QE would be set ++*/ ++static int spi_general_qe_enable(struct hisnfc_op *spi) ++{ ++ unsigned val, op; ++ const char *str[] = {"Disable", "Enable"}; ++ struct hisnfc_host *host = (struct hisnfc_host *)spi->host; ++ ++ if (DEBUG_SPI_NAND_DRV) ++ pr_info("* SPI Quad-Enable start.\n"); ++ ++ if (spi_is_quad(spi)) ++ op = ENABLE; ++ else ++ op = DISABLE; ++ ++ if (DEBUG_SPI_NAND_DRV) ++ pr_info(" Read Quad status.\n"); ++ spi_feature_op(host, GET_OP, FEATURE_ADDR, &val); ++ if ((val & FEATURE_QE_ENABLE) == op) { ++ if (DEBUG_SPI_NAND_DRV) ++ pr_info("* Quad is %s!\n", str[op]); ++ return 0; ++ } ++ ++ if (op == ENABLE) ++ val |= FEATURE_QE_ENABLE; ++ else ++ val &= ~FEATURE_QE_ENABLE; ++ if (DEBUG_SPI_NAND_DRV) ++ pr_info(" %s Quad\n", str[op]); ++ spi_feature_op(host, SET_OP, FEATURE_ADDR, &val); ++ ++ spi->driver->wait_ready(spi); ++ ++ spi_feature_op(host, GET_OP, FEATURE_ADDR, &val); ++ if ((val & FEATURE_QE_ENABLE) != op) { ++ pr_info("hisnfc: %s Quad failed! val[%#x]\n", str[op], val); ++ return 1; ++ } else if (DEBUG_SPI_NAND_DRV) ++ pr_info("* %s Quad succeed!\n", str[op]); ++ ++ return 0; ++} +diff --git a/drivers/mtd/nand/hisnfc100/hisnfc100_spi_ids.c b/drivers/mtd/nand/hisnfc100/hisnfc100_spi_ids.c +new file mode 100644 +index 0000000..48e009e +--- /dev/null ++++ b/drivers/mtd/nand/hisnfc100/hisnfc100_spi_ids.c +@@ -0,0 +1,1131 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hisnfc100_os.h" ++#include "hisnfc100_spi_ids.h" ++#include "hisnfc100.h" ++ ++#include "hisnfc100_spi_general.c" ++ ++/*****************************************************************************/ ++#define SET_READ_STD(_dummy_, _size_, _clk_) \ ++ static struct spi_op_info read_std_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_STD, SPI_CMD_READ_STD, _dummy_, _size_, _clk_ } ++ ++#define READ_STD(_dummy_, _size_, _clk_) read_std_##_dummy_##_size_##_clk_ ++ ++/*****************************************************************************/ ++#define SET_READ_FAST(_dummy_, _size_, _clk_) \ ++ static struct spi_op_info read_fast_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_FAST, SPI_CMD_READ_FAST, _dummy_, _size_, _clk_ } ++ ++#define READ_FAST(_dummy_, _size_, _clk_) read_fast_##_dummy_##_size_##_clk_ ++ ++/*****************************************************************************/ ++#define SET_READ_DUAL(_dummy_, _size_, _clk_) \ ++ static struct spi_op_info read_dual_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_DUAL, SPI_CMD_READ_DUAL, _dummy_, _size_, _clk_ } ++ ++#define READ_DUAL(_dummy_, _size_, _clk_) read_dual_##_dummy_##_size_##_clk_ ++ ++/*****************************************************************************/ ++#define SET_READ_DUAL_ADDR(_dummy_, _size_, _clk_) \ ++ static struct spi_op_info read_dual_addr_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_DUAL_ADDR, SPI_CMD_READ_DUAL_ADDR, _dummy_, _size_, _clk_ } ++ ++#define READ_DUAL_ADDR(_dummy_, _size_, _clk_) \ ++ read_dual_addr_##_dummy_##_size_##_clk_ ++ ++/*****************************************************************************/ ++#define SET_READ_QUAD(_dummy_, _size_, _clk_) \ ++ static struct spi_op_info read_quad_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_QUAD, SPI_CMD_READ_QUAD, _dummy_, _size_, _clk_ } ++ ++#define READ_QUAD(_dummy_, _size_, _clk_) read_quad_##_dummy_##_size_##_clk_ ++ ++/*****************************************************************************/ ++#define SET_READ_QUAD_ADDR(_dummy_, _size_, _clk_) \ ++ static struct spi_op_info read_quad_addr_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_QUAD_ADDR, SPI_CMD_READ_QUAD_ADDR, _dummy_, _size_, _clk_ } ++ ++#define READ_QUAD_ADDR(_dummy_, _size_, _clk_) \ ++ read_quad_addr_##_dummy_##_size_##_clk_ ++ ++/*****************************************************************************/ ++#define SET_WRITE_STD(_dummy_, _size_, _clk_) \ ++ static struct spi_op_info write_std_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_WRITE_STD, SPI_CMD_WRITE_STD, _dummy_, _size_, _clk_ } ++ ++#define WRITE_STD(_dummy_, _size_, _clk_) write_std_##_dummy_##_size_##_clk_ ++ ++/*****************************************************************************/ ++#define SET_WRITE_QUAD(_dummy_, _size_, _clk_) \ ++ static struct spi_op_info write_quad_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_WRITE_QUAD, SPI_CMD_WRITE_QUAD, _dummy_, _size_, _clk_ } ++ ++#define WRITE_QUAD(_dummy_, _size_, _clk_) \ ++ write_quad_##_dummy_##_size_##_clk_ ++ ++/*****************************************************************************/ ++#define SET_ERASE_SECTOR_128K(_dummy_, _size_, _clk_) \ ++ static struct spi_op_info erase_sector_128k_##_dummy_##_size_##_clk_ \ ++ = { SPI_IF_ERASE_SECTOR_128K, SPI_CMD_SE_128K, _dummy_, _size_, _clk_ } ++ ++#define ERASE_SECTOR_128K(_dummy_, _size_, _clk_) \ ++ erase_sector_128k_##_dummy_##_size_##_clk_ ++ ++#define SET_ERASE_SECTOR_256K(_dummy_, _size_, _clk_) \ ++ static struct spi_op_info erase_sector_256k_##_dummy_##_size_##_clk_ \ ++ = { SPI_IF_ERASE_SECTOR_256K, SPI_CMD_SE_256K, _dummy_, _size_, _clk_ } ++ ++#define ERASE_SECTOR_256K(_dummy_, _size_, _clk_) \ ++ erase_sector_256k_##_dummy_##_size_##_clk_ ++ ++/*****************************************************************************/ ++SET_READ_STD(1, INFINITE, 24); ++ ++SET_READ_FAST(1, INFINITE, 50); ++SET_READ_FAST(1, INFINITE, 80); ++SET_READ_FAST(1, INFINITE, 104); ++SET_READ_FAST(1, INFINITE, 108); ++SET_READ_FAST(1, INFINITE, 120); ++ ++SET_READ_DUAL(1, INFINITE, 50); ++SET_READ_DUAL(1, INFINITE, 80); ++SET_READ_DUAL(1, INFINITE, 104); ++SET_READ_DUAL(1, INFINITE, 108); ++SET_READ_DUAL(1, INFINITE, 120); ++ ++SET_READ_DUAL_ADDR(1, INFINITE, 60); ++SET_READ_DUAL_ADDR(1, INFINITE, 80); ++SET_READ_DUAL_ADDR(1, INFINITE, 104); ++SET_READ_DUAL_ADDR(1, INFINITE, 108); ++SET_READ_DUAL_ADDR(1, INFINITE, 120); ++ ++SET_READ_QUAD(1, INFINITE, 50); ++SET_READ_QUAD(1, INFINITE, 80); ++SET_READ_QUAD(1, INFINITE, 104); ++SET_READ_QUAD(1, INFINITE, 108); ++SET_READ_QUAD(1, INFINITE, 120); ++ ++SET_READ_QUAD_ADDR(1, INFINITE, 60); ++SET_READ_QUAD_ADDR(1, INFINITE, 104); ++SET_READ_QUAD_ADDR(2, INFINITE, 80); ++SET_READ_QUAD_ADDR(2, INFINITE, 104); ++SET_READ_QUAD_ADDR(1, INFINITE, 108); ++SET_READ_QUAD_ADDR(1, INFINITE, 120); ++ ++/*****************************************************************************/ ++SET_WRITE_STD(0, 256, 24); ++SET_WRITE_STD(0, 256, 80); ++SET_WRITE_STD(0, 256, 104); ++ ++SET_WRITE_QUAD(0, 256, 80); ++SET_WRITE_QUAD(0, 256, 104); ++SET_WRITE_QUAD(0, 256, 108); ++SET_WRITE_QUAD(0, 256, 120); ++ ++/*****************************************************************************/ ++SET_ERASE_SECTOR_128K(0, SZ_128K, 24); ++SET_ERASE_SECTOR_128K(0, SZ_128K, 80); ++SET_ERASE_SECTOR_128K(0, SZ_128K, 104); ++ ++SET_ERASE_SECTOR_256K(0, SZ_256K, 24); ++SET_ERASE_SECTOR_256K(0, SZ_256K, 80); ++SET_ERASE_SECTOR_256K(0, SZ_256K, 104); ++ ++/*****************************************************************************/ ++static struct spi_nand_driver spi_nand_driver_general = { ++ .wait_ready = spi_general_wait_ready, ++ .write_enable = spi_general_write_enable, ++ .qe_enable = spi_general_qe_enable, ++}; ++ ++/* ++ * Some spi nand don't need set QE bit enable. ++ */ ++static struct spi_nand_driver spi_nand_driver_no_qe = { ++ .wait_ready = spi_general_wait_ready, ++ .write_enable = spi_general_write_enable, ++}; ++ ++/*****************************************************************************/ ++#define SPI_NAND_ID_TAB_VER "2.2" ++ ++/******* SPI Nand ID Table *************************************************** ++* Version Manufacturer Chip Name Size Operation ++* 1.0 ESMT F50L512M41A 64MB Add 5 chip ++* GD 5F1GQ4UAYIG 128MB ++* GD 5F2GQ4UAYIG 256MB ++* GD 5F4GQ4UAYIG 512MB ++* GD 5F4GQ4UBYIG 512MB ++* 1.1 ESMT F50L1G41A 128MB Add 2 chip ++* Winbond W25N01GV 128MB ++* 1.2 GD 5F1GQ4UBYIG 128MB Add 2 chip ++* GD 5F2GQ4UBYIG 256MB ++* 1.3 ATO ATO25D1GA 128MB Add 1 chip ++* Micron MT29F1G01 128MB Add 3 chip ++* Micron MT29F2G01 256MB ++* Micron MT29F4G01 512MB ++* 1.4 MXIC MX35LF1GE4AB 128MB Add 2 chip ++* 1.5 Paragon PN26G01A 128MB Add 1 chip ++* 1.6 All-flash AFS1GQ4UAC 128MB Add 1 chip ++* 1.7 TOSHIBA TC58CVG0S3H 128MB Add 2 chip ++* TOSHIBA TC58CVG2S0H 512MB ++* 1.8 ALL-flash AFS2GQ4UAD 256MB Add 2 chip ++* Paragon PN26G02A 256MB ++* 1.9 TOSHIBA TC58CVG1S3H 256MB Add 1 chip ++* 2.0 HeYangTek HYF1GQ4UAACAE 128MB Add 3 chip ++* HeYangTek HYF2GQ4UAACAE 256MB ++* HeYangTek HYF4GQ4UAACBE 512MB ++* 2.1 Micron MT29F1G01ABA 128MB Add 1 chip ++* 2.2 Micron MT29F2G01ABA 256MB Add 1 chip ++******************************************************************************/ ++struct hisnfc_chip_info hisnfc_spi_nand_flash_table[] = { ++ /* Micron MT29F1G01ABA 1GBit */ ++ { ++ .name = "MT29F1G01ABA", ++ .id = {0x2C, 0x14}, ++ .id_len = 2, ++ .chipsize = SZ_128M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(2, INFINITE, 80), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 80), ++ 0 ++ }, ++ .driver = &spi_nand_driver_no_qe, ++ }, ++ ++ /* Micron MT29F2G01ABA 2GBit */ ++ { ++ .name = "MT29F2G01ABA", ++ .id = {0x2C, 0x24}, ++ .id_len = 2, ++ .chipsize = SZ_256M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 108), ++ &READ_DUAL(1, INFINITE, 108), ++ &READ_DUAL_ADDR(1, INFINITE, 108), ++ &READ_QUAD(1, INFINITE, 108), ++ &READ_QUAD_ADDR(2, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 108), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 80), ++ 0 ++ }, ++ .driver = &spi_nand_driver_no_qe, ++ }, ++ ++ /* ESMT F50L512M41A 512Mbit */ ++ { ++ .name = "F50L512M41A", ++ .id = {0xC8, 0x20}, ++ .id_len = 2, ++ .chipsize = SZ_64M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 24), ++ 0 ++ }, ++ .driver = &spi_nand_driver_no_qe, ++ }, ++ ++ /* ESMT F50L1G41A 1Gbit */ ++ { ++ .name = "F50L1G41A", ++ .id = {0xC8, 0x21}, ++ .id_len = 2, ++ .chipsize = SZ_128M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 24), ++ 0 ++ }, ++ .driver = &spi_nand_driver_no_qe, ++ }, ++ ++ /* GD 5F1GQ4UAYIG 1Gbit */ ++ { ++ .name = "5F1GQ4UAYIG", ++ .id = {0xc8, 0xf1}, ++ .id_len = 2, ++ .chipsize = SZ_128M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 120), ++ &READ_DUAL(1, INFINITE, 120), ++ &READ_DUAL_ADDR(1, INFINITE, 120), ++ &READ_QUAD(1, INFINITE, 120), ++ &READ_QUAD_ADDR(1, INFINITE, 120), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 120), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 24), ++ 0 ++ }, ++ .driver = &spi_nand_driver_general, ++ }, ++ ++ /* GD 5F1GQ4UBYIG 1Gbit */ ++ { ++ .name = "5F1GQ4UBYIG", ++ .id = {0xc8, 0xd1}, ++ .id_len = 2, ++ .chipsize = SZ_128M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 120), ++ &READ_DUAL(1, INFINITE, 120), ++ &READ_DUAL_ADDR(1, INFINITE, 120), ++ &READ_QUAD(1, INFINITE, 120), ++ &READ_QUAD_ADDR(1, INFINITE, 120), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 120), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 24), ++ 0 ++ }, ++ .driver = &spi_nand_driver_general, ++ }, ++ ++ /* GD 5F2GQ4UAYIG 2Gbit */ ++ { ++ .name = "5F2GQ4UAYIG", ++ .id = {0xc8, 0xf2}, ++ .id_len = 2, ++ .chipsize = SZ_256M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 120), ++ &READ_DUAL(1, INFINITE, 120), ++ &READ_DUAL_ADDR(1, INFINITE, 120), ++ &READ_QUAD(1, INFINITE, 120), ++ &READ_QUAD_ADDR(1, INFINITE, 120), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 120), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 24), ++ 0 ++ }, ++ .driver = &spi_nand_driver_general, ++ }, ++ ++ /* GD 5F2GQ4UBYIG 2Gbit */ ++ { ++ .name = "5F2GQ4UBYIG", ++ .id = {0xc8, 0xd2}, ++ .id_len = 2, ++ .chipsize = SZ_256M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 120), ++ &READ_DUAL(1, INFINITE, 120), ++ &READ_DUAL_ADDR(1, INFINITE, 120), ++ &READ_QUAD(1, INFINITE, 120), ++ &READ_QUAD_ADDR(1, INFINITE, 120), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 120), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 24), ++ 0 ++ }, ++ .driver = &spi_nand_driver_general, ++ }, ++ ++ /* GD 5F4GQ4UAYIG 4Gbit */ ++ { ++ .name = "5F4GQ4UAYIG", ++ .id = {0xc8, 0xf4}, ++ .id_len = 2, ++ .chipsize = SZ_512M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 120), ++ &READ_DUAL(1, INFINITE, 120), ++ &READ_DUAL_ADDR(1, INFINITE, 120), ++ &READ_QUAD(1, INFINITE, 120), ++ &READ_QUAD_ADDR(1, INFINITE, 120), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 120), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 24), ++ 0 ++ }, ++ .driver = &spi_nand_driver_general, ++ }, ++ ++ /* GD 5F4GQ4UBYIG 4Gbit */ ++ { ++ .name = "5F4GQ4UBYIG", ++ .id = {0xc8, 0xd4}, ++ .id_len = 2, ++ .chipsize = SZ_512M, ++ .erasesize = SZ_256K, ++ .pagesize = SZ_4K, ++ .oobsize = 256, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 120), ++ &READ_DUAL(1, INFINITE, 120), ++ &READ_DUAL_ADDR(1, INFINITE, 120), ++ &READ_QUAD(1, INFINITE, 120), ++ &READ_QUAD_ADDR(1, INFINITE, 120), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 120), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_256K(0, SZ_256K, 24), ++ 0 ++ }, ++ .driver = &spi_nand_driver_general, ++ }, ++ ++ /* Winbond W25N01GV 1Gbit */ ++ { ++ .name = "W25N01GV", ++ .id = {0xef, 0xaa, 0x21}, ++ .id_len = 3, ++ .chipsize = SZ_128M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_DUAL_ADDR(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ &READ_QUAD_ADDR(2, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 24), ++ 0 ++ }, ++ .driver = &spi_nand_driver_no_qe, ++ }, ++ ++ /* ATO ATO25D1GA 1Gbit */ ++ { ++ .name = "ATO25D1GA", ++ .id = {0x9b, 0x12}, ++ .id_len = 2, ++ .chipsize = SZ_128M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 24), ++ 0 ++ }, ++ .driver = &spi_nand_driver_general, ++ }, ++ ++ /* Micron MT29F1G01 */ ++ { ++ .name = "MT29F1G01", ++ .id = {0x2c, 0x12}, ++ .id_len = 2, ++ .chipsize = SZ_128M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 50), ++ &READ_DUAL(1, INFINITE, 50), ++ &READ_QUAD(1, INFINITE, 50), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 24), ++ 0 ++ }, ++ .driver = &spi_nand_driver_no_qe, ++ }, ++ ++ /* Micron MT29F2G01 */ ++ { ++ .name = "MT29F2G01", ++ .id = {0x2c, 0x22}, ++ .id_len = 2, ++ .chipsize = SZ_256M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 50), ++ &READ_DUAL(1, INFINITE, 50), ++ &READ_QUAD(1, INFINITE, 50), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 24), ++ 0 ++ }, ++ .driver = &spi_nand_driver_no_qe, ++ }, ++ ++ /* Micron MT29F4G01 */ ++ { ++ .name = "MT29F4G01", ++ .id = {0x2c, 0x32}, ++ .id_len = 2, ++ .chipsize = SZ_512M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 50), ++ &READ_DUAL(1, INFINITE, 50), ++ &READ_QUAD(1, INFINITE, 50), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 24), ++ 0 ++ }, ++ .driver = &spi_nand_driver_no_qe, ++ }, ++ ++ /* MXIC MX35LF1GE4AB 1Gbit */ ++ { ++ .name = "MX35LF1GE4AB", ++ .id = {0xc2, 0x12}, ++ .id_len = 2, ++ .chipsize = SZ_128M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 24), ++ 0 ++ }, ++ .driver = &spi_nand_driver_general, ++ }, ++ ++ /* Paragon PN26G01A 1Gbit */ ++ { ++ .name = "PN26G01A", ++ .id = {0xa1, 0xe1}, ++ .id_len = 2, ++ .chipsize = SZ_128M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 108), ++ &READ_DUAL(1, INFINITE, 108), ++ &READ_DUAL_ADDR(1, INFINITE, 108), ++ &READ_QUAD(1, INFINITE, 108), ++ &READ_QUAD_ADDR(1, INFINITE, 108), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 108), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 24), ++ 0 ++ }, ++ .driver = &spi_nand_driver_general, ++ }, ++ ++ /* Paragon PN26G02A 2Gbit */ ++ { ++ .name = "PN26G02A", ++ .id = {0xa1, 0xe2}, ++ .id_len = 2, ++ .chipsize = SZ_256M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 108), ++ &READ_DUAL(1, INFINITE, 108), ++ &READ_DUAL_ADDR(1, INFINITE, 108), ++ &READ_QUAD(1, INFINITE, 108), ++ &READ_QUAD_ADDR(1, INFINITE, 108), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 108), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 24), ++ 0 ++ }, ++ .driver = &spi_nand_driver_general, ++ }, ++ ++ /* All-flash AFS1GQ4UAC 1Gbit */ ++ { ++ .name = "AFS1GQ4UAC", ++ .id = {0xc1, 0x51}, ++ .id_len = 2, ++ .chipsize = SZ_128M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_DUAL_ADDR(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ &READ_QUAD_ADDR(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 24), ++ 0 ++ }, ++ .driver = &spi_nand_driver_general, ++ }, ++ ++ /* All-flash AFS2GQ4UAD 2Gbit */ ++ { ++ .name = "AFS2GQ4UAD", ++ .id = {0xc1, 0x52}, ++ .id_len = 2, ++ .chipsize = SZ_256M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_DUAL_ADDR(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ &READ_QUAD_ADDR(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 24), ++ 0 ++ }, ++ .driver = &spi_nand_driver_general, ++ }, ++ ++ /* TOSHIBA TC58CVG0S3H 1Gbit */ ++ { ++ .name = "TC58CVG0S3H", ++ .id = {0x98, 0xc2}, ++ .id_len = 2, ++ .chipsize = SZ_128M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 104), ++ 0 ++ }, ++ .driver = &spi_nand_driver_no_qe, ++ }, ++ ++ /* TOSHIBA TC58CVG2S0H 4Gbit */ ++ { ++ .name = "TC58CVG2S0H", ++ .id = {0x98, 0xcd}, ++ .id_len = 2, ++ .chipsize = SZ_512M, ++ .erasesize = SZ_256K, ++ .pagesize = SZ_4K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_256K(0, SZ_256K, 104), ++ 0 ++ }, ++ .driver = &spi_nand_driver_no_qe, ++ }, ++ ++ /* HeYangTek HYF1GQ4UAACAE 1Gbit */ ++ { ++ .name = "HYF1GQ4UAACAE", ++ .id = {0xc9, 0x51}, ++ .id_len = 2, ++ .chipsize = SZ_128M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 50), ++ &READ_DUAL(1, INFINITE, 50), ++ &READ_DUAL_ADDR(1, INFINITE, 60), ++ &READ_QUAD(1, INFINITE, 50), ++ &READ_QUAD_ADDR(1, INFINITE, 60), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 80), ++ 0 ++ }, ++ .driver = &spi_nand_driver_general, ++ }, ++ ++ /* HeYangTek HYF2GQ4UAACAE 2Gbit */ ++ { ++ .name = "HYF2GQ4UAACAE", ++ .id = {0xc9, 0x52}, ++ .id_len = 2, ++ .chipsize = SZ_256M, ++ .erasesize = SZ_128K, ++ .pagesize = SZ_2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 50), ++ &READ_DUAL(1, INFINITE, 50), ++ &READ_DUAL_ADDR(1, INFINITE, 60), ++ &READ_QUAD(1, INFINITE, 50), ++ &READ_QUAD_ADDR(1, INFINITE, 60), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, SZ_128K, 80), ++ 0 ++ }, ++ .driver = &spi_nand_driver_general, ++ }, ++ ++ /* HeYangTek HYF4GQ4UAACBE 4Gbit */ ++ { ++ .name = "HYF4GQ4UAACBE", ++ .id = {0xc9, 0xd4}, ++ .id_len = 2, ++ .chipsize = SZ_512M, ++ .erasesize = SZ_256K, ++ .pagesize = SZ_4K, ++ .oobsize = 256, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 50), ++ &READ_DUAL(1, INFINITE, 50), ++ &READ_DUAL_ADDR(1, INFINITE, 60), ++ &READ_QUAD(1, INFINITE, 50), ++ &READ_QUAD_ADDR(1, INFINITE, 60), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_256K(0, SZ_256K, 80), ++ 0 ++ }, ++ .driver = &spi_nand_driver_general, ++ }, ++ ++ { .id_len = 0, }, ++}; ++ ++/*****************************************************************************/ ++static void hisnfc100_spi_search_rw(struct hisnfc_chip_info *spiinfo, ++ struct spi_op_info *spiop_rw, unsigned iftype, ++ unsigned max_dummy, int rw_type) ++{ ++ int ix = 0; ++ struct spi_op_info **spiop, **fitspiop; ++ ++ for (fitspiop = spiop = (rw_type ? spiinfo->write : spiinfo->read); ++ (*spiop) && ix < MAX_SPI_NAND_OP; spiop++, ix++) ++ if (((*spiop)->iftype & iftype) ++ && ((*spiop)->dummy <= max_dummy) ++ && (*fitspiop)->iftype < (*spiop)->iftype) { ++ fitspiop = spiop; ++ } ++ ++ memcpy(spiop_rw, (*fitspiop), sizeof(struct spi_op_info)); ++} ++ ++/*****************************************************************************/ ++static void hisnfc100_spi_get_erase(struct hisnfc_chip_info *spiinfo, ++ struct spi_op_info *spiop_erase) ++{ ++ int ix; ++ ++ spiop_erase->size = 0; ++ for (ix = 0; ix < MAX_SPI_NAND_OP; ix++) { ++ if (spiinfo->erase[ix] == NULL) ++ break; ++ if (spiinfo->erasesize == spiinfo->erase[ix]->size) { ++ memcpy(&spiop_erase[ix], spiinfo->erase[ix], ++ sizeof(struct spi_op_info)); ++ break; ++ } ++ } ++} ++ ++/*****************************************************************************/ ++static void hisnfc100_map_iftype_and_clock(struct hisnfc_op *spi) ++{ ++ int ix; ++ const int iftype_read[] = { ++ SPI_IF_READ_STD, HISNFC100_IFCYCLE_STD, ++ SPI_IF_READ_FAST, HISNFC100_IFCYCLE_STD, ++ SPI_IF_READ_DUAL, HISNFC100_IFCYCLE_DUAL, ++ SPI_IF_READ_DUAL_ADDR, HISNFC100_IFCYCLE_DUAL_ADDR, ++ SPI_IF_READ_QUAD, HISNFC100_IFCYCLE_QUAD, ++ SPI_IF_READ_QUAD_ADDR, HISNFC100_IFCYCLE_QUAD_ADDR, ++ 0, 0, ++ }; ++ const int iftype_write[] = { ++ SPI_IF_WRITE_STD, HISNFC100_IFCYCLE_STD, ++ SPI_IF_WRITE_QUAD, HISNFC100_IFCYCLE_QUAD, ++ 0, 0, ++ }; ++ ++ for (ix = 0; iftype_write[ix]; ix += 2) { ++ if (spi->write->iftype == iftype_write[ix]) { ++ spi->write->iftype = iftype_write[ix + 1]; ++ break; ++ } ++ } ++ hisnfc100_get_best_clock(&spi->write->clock); ++ ++ for (ix = 0; iftype_read[ix]; ix += 2) { ++ if (spi->read->iftype == iftype_read[ix]) { ++ spi->read->iftype = iftype_read[ix + 1]; ++ break; ++ } ++ } ++ hisnfc100_get_best_clock(&spi->read->clock); ++ ++ hisnfc100_get_best_clock(&spi->erase->clock); ++ spi->erase->iftype = HISNFC100_IFCYCLE_STD; ++} ++ ++/*****************************************************************************/ ++static void hisnfc100_spi_probe(struct hisnfc_host *host, ++ struct hisnfc_chip_info *spi_dev) ++{ ++ unsigned regval; ++ struct hisnfc_op *spi = host->spi; ++ ++ spi->host = host; ++ spi->driver = spi_dev->driver; ++ ++ hisnfc100_spi_search_rw(spi_dev, spi->read, HISNFC100_SUPPORT_READ, ++ HISNFC100_SUPPORT_MAX_DUMMY, SPI_NAND_READ); ++ ++ hisnfc100_spi_search_rw(spi_dev, spi->write, HISNFC100_SUPPORT_WRITE, ++ HISNFC100_SUPPORT_MAX_DUMMY, SPI_NAND_WRITE); ++ ++ hisnfc100_spi_get_erase(spi_dev, spi->erase); ++ hisnfc100_map_iftype_and_clock(spi); ++ ++ if (spi->driver->qe_enable) { ++ if (spi->driver->qe_enable(spi)) ++ pr_err("%s set feature QE failed!\n", __func__); ++ } ++ ++ spi_feature_op(host, GET_OP, PROTECTION_ADDR, ®val); ++ if (ANY_BP_ENABLE(regval)) { ++ regval &= ~ALL_BP_MASK; ++ spi_feature_op(host, SET_OP, PROTECTION_ADDR, ®val); ++ ++ spi->driver->wait_ready(spi); ++ ++ spi_feature_op(host, GET_OP, PROTECTION_ADDR, ®val); ++ if (ANY_BP_ENABLE(regval)) ++ pr_err("%s write protection disable fail! val[%#x]\n", ++ __func__, regval); ++ } ++ ++ spi_feature_op(host, GET_OP, FEATURE_ADDR, ®val); ++ if (regval & FEATURE_ECC_ENABLE) { ++ regval &= ~FEATURE_ECC_ENABLE; ++ spi_feature_op(host, SET_OP, FEATURE_ADDR, ®val); ++ ++ spi->driver->wait_ready(spi); ++ ++ spi_feature_op(host, GET_OP, FEATURE_ADDR, ®val); ++ if (regval & FEATURE_ECC_ENABLE) ++ pr_err("%s Internal ECC disable fail! val[%#x]\n", ++ __func__, regval); ++ } ++} ++ ++static struct nand_flash_dev spi_nand_dev; ++/*****************************************************************************/ ++static struct nand_flash_dev *spi_nand_get_flash_info(struct mtd_info *mtd, ++ unsigned char *id) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ struct hisnfc_host *host = chip->priv; ++ struct hisnfc_chip_info *spi_dev = hisnfc_spi_nand_flash_table; ++ unsigned char ix = 0, len = 0, buffer[100]; ++ struct nand_flash_dev *flash_type = &spi_nand_dev; ++ ++ len = sprintf(buffer, "SPI Nand(cs %d) ID: %#x %#x", ++ host->cmd_option.chipselect, id[0], id[1]); ++ ++ for (; spi_dev->id_len; spi_dev++) { ++ if (memcmp(id, spi_dev->id, spi_dev->id_len)) ++ continue; ++ ++ for (ix = 2; ix < spi_dev->id_len; ix++) ++ len += sprintf(buffer + len, " %#x", id[ix]); ++ pr_info("%s\n", buffer); ++ ++ flash_type->name = spi_dev->name; ++ memcpy(flash_type->id, spi_dev->id, spi_dev->id_len); ++ flash_type->pagesize = spi_dev->pagesize; ++ flash_type->chipsize = spi_dev->chipsize >> 20; ++ flash_type->erasesize = spi_dev->erasesize; ++ flash_type->oobsize = spi_dev->oobsize; ++ ++ mtd->size = spi_dev->chipsize; ++ mtd->oobsize = spi_dev->oobsize; ++ mtd->erasesize = spi_dev->erasesize; ++ mtd->writesize = spi_dev->pagesize; ++ chip->chipsize = spi_dev->chipsize; ++ ++ if (host->mtd != mtd) ++ host->mtd = mtd; ++ hisnfc100_spi_probe(host, spi_dev); ++ ++ return flash_type; ++ } ++ ++ return NULL; ++} ++ ++/*****************************************************************************/ ++void spi_nand_ids_register(void) ++{ ++ pr_info("SPI Nand ID Table Version %s\n", SPI_NAND_ID_TAB_VER); ++ get_spi_nand_flash_type_hook = spi_nand_get_flash_info; ++} ++ +diff --git a/drivers/mtd/nand/hisnfc100/hisnfc100_spi_ids.h b/drivers/mtd/nand/hisnfc100/hisnfc100_spi_ids.h +new file mode 100644 +index 0000000..77cdcc3 +--- /dev/null ++++ b/drivers/mtd/nand/hisnfc100/hisnfc100_spi_ids.h +@@ -0,0 +1,148 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef HISFC_SPI_IDSH ++#define HISFC_SPI_IDSH ++ ++/*****************************************************************************/ ++#define INFINITE (0xFFFFFFFF) ++ ++#define DEFAULT_ID_LEN 2 ++#define MAX_ID_LEN 3 ++#define MAX_SPI_NAND_OP 8 ++ ++#define BBP_LAST_PAGE 0x01 ++#define BBP_FIRST_PAGE 0x02 ++ ++/*****************************************************************************/ ++#define SPI_IF_READ_STD (0x01) ++#define SPI_IF_READ_FAST (0x02) ++#define SPI_IF_READ_DUAL (0x04) ++#define SPI_IF_READ_DUAL_ADDR (0x08) ++#define SPI_IF_READ_QUAD (0x10) ++#define SPI_IF_READ_QUAD_ADDR (0x20) ++ ++#define SPI_IF_WRITE_STD (0x01) ++#define SPI_IF_WRITE_DUAL (0x02) ++#define SPI_IF_WRITE_DUAL_ADDR (0x04) ++#define SPI_IF_WRITE_QUAD (0x08) ++#define SPI_IF_WRITE_QUAD_ADDR (0x10) ++ ++#define SPI_IF_ERASE_SECTOR_128K (0x08) /* 128K */ ++#define SPI_IF_ERASE_SECTOR_256K (0x10) /* 256K */ ++ ++/******************************************************************************/ ++#define HISNFC100_SUPPORT_READ (SPI_IF_READ_STD \ ++ | SPI_IF_READ_FAST \ ++ | SPI_IF_READ_DUAL \ ++ | SPI_IF_READ_DUAL_ADDR \ ++ | SPI_IF_READ_QUAD \ ++ | SPI_IF_READ_QUAD_ADDR) ++ ++#define HISNFC100_SUPPORT_WRITE (SPI_IF_WRITE_STD | SPI_IF_WRITE_QUAD) ++ ++#define HISNFC100_SUPPORT_MAX_DUMMY 8 ++ ++#define SPI_NAND_READ 0 ++#define SPI_NAND_WRITE 1 ++ ++#define HISNFC100_IFCYCLE_STD 0 ++#define HISNFC100_IFCYCLE_DUAL 1 ++#define HISNFC100_IFCYCLE_DUAL_ADDR 2 ++#define HISNFC100_IFCYCLE_QUAD 3 ++#define HISNFC100_IFCYCLE_QUAD_ADDR 4 ++ ++/*****************************************************************************/ ++#define SPI_CMD_WREN 0x06 /* Write Enable */ ++#define SPI_CMD_WRDI 0x04 /* Write Disable */ ++ ++#define SPI_CMD_GET_FEATURES 0x0F /* Get Features */ ++#define SPI_CMD_SET_FEATURE 0x1F /* Set Feature */ ++ ++#define SPI_CMD_PAGE_READ 0x13 /* Page Read to Cache */ ++#define SPI_CMD_READ_STD 0x03 /* Read From Cache at Standard Speed */ ++#define SPI_CMD_READ_FAST 0x0B /* Read From Cache at Higher Speed */ ++#define SPI_CMD_READ_DUAL 0x3B /* Read From Cache at Dual Output */ ++#define SPI_CMD_READ_QUAD 0x6B /* Read From Cache at Quad Output */ ++#define SPI_CMD_READ_DUAL_ADDR 0xBB /* Read From Cache at Dual I/O */ ++#define SPI_CMD_READ_QUAD_ADDR 0xEB /* Read From Cache at Quad I/O */ ++ ++#define SPI_CMD_RDID 0x9F /* Read Identification */ ++ ++#define SPI_CMD_WRITE_STD 0x02 /* Page Load at Standard Input */ ++#define SPI_CMD_WRITE_QUAD 0x32 /* Page Load at Quad Input */ ++ ++#define SPI_CMD_SE_128K 0xD8 /* 128KB sector Erase */ ++#define SPI_CMD_SE_256K 0xD8 /* 256KB sector Erase */ ++ ++#define SPI_CMD_RESET 0xff /* Reset the device */ ++ ++/*****************************************************************************/ ++/* SPI operation information */ ++struct spi_op_info { ++ unsigned char iftype; ++ unsigned char cmd; ++ unsigned char dummy; ++ unsigned int size; ++ unsigned int clock; ++}; ++ ++struct spi_nand_driver; ++ ++struct hisnfc_op { ++ void *host; ++ struct spi_nand_driver *driver; ++ struct spi_op_info read[1]; ++ struct spi_op_info write[1]; ++ struct spi_op_info erase[MAX_SPI_NAND_OP]; ++}; ++ ++struct spi_nand_driver { ++ int (*wait_ready)(struct hisnfc_op *spi); ++ int (*write_enable)(struct hisnfc_op *spi); ++ int (*qe_enable)(struct hisnfc_op *spi); ++}; ++ ++struct hisnfc_chip_info { ++ char *name; ++ unsigned char id[MAX_ID_LEN]; ++ unsigned char id_len; ++ unsigned long long chipsize; ++ unsigned int erasesize; ++ unsigned int pagesize; ++ unsigned int oobsize; ++ unsigned int badblock_pos; ++ struct spi_op_info *read[MAX_SPI_NAND_OP]; ++ struct spi_op_info *write[MAX_SPI_NAND_OP]; ++ struct spi_op_info *erase[MAX_SPI_NAND_OP]; ++ struct spi_nand_driver *driver; ++}; ++ ++/*****************************************************************************/ ++void spi_nand_ids_register(void); ++ ++void hisnfc100_get_best_clock(unsigned int *clock); ++ ++struct hisnfc_host; ++ ++void spi_feature_op(struct hisnfc_host *host, int op, int addr, unsigned *val); ++ ++/******************************************************************************/ ++ ++#endif /* HISFC_SPI_IDSH */ ++ +diff --git a/drivers/mtd/nand/match_table.c b/drivers/mtd/nand/match_table.c +new file mode 100644 +index 0000000..271da05 +--- /dev/null ++++ b/drivers/mtd/nand/match_table.c +@@ -0,0 +1,96 @@ ++/****************************************************************************** ++ * COPYRIGHT (C) Hisilicon.2013 ++ * All rights reserved. ++ * *** ++ * Create by Hisilicon 2013-08-15 ++ * ++ *****************************************************************************/ ++ ++/*****************************************************************************/ ++#include ++#include "match_table.h" ++ ++/*****************************************************************************/ ++int reg2type(struct match_reg_type *table, int length, int reg, int def) ++{ ++ while (length-- > 0) { ++ if (table->reg == reg) ++ return table->type; ++ table++; ++ } ++ return def; ++} ++ ++int type2reg(struct match_reg_type *table, int length, int type, int def) ++{ ++ while (length-- > 0) { ++ if (table->type == type) ++ return table->reg; ++ table++; ++ } ++ return def; ++} ++ ++int str2type(struct match_type_str *table, int length, const char *str, ++ int size, int def) ++{ ++ while (length-- > 0) { ++ if (!strncmp(table->str, str, size)) ++ return table->type; ++ table++; ++ } ++ return def; ++} ++ ++const char *type2str(struct match_type_str *table, int length, int type, ++ const char *def) ++{ ++ while (length-- > 0) { ++ if (table->type == type) ++ return table->str; ++ table++; ++ } ++ return def; ++} ++ ++int match_reg_to_type(struct match_t *table, int nr_table, int reg, int def) ++{ ++ while (nr_table-- > 0) { ++ if (table->reg == reg) ++ return table->type; ++ table++; ++ } ++ return def; ++} ++ ++int match_type_to_reg(struct match_t *table, int nr_table, int type, int def) ++{ ++ while (nr_table-- > 0) { ++ if (table->type == type) ++ return table->reg; ++ table++; ++ } ++ return def; ++} ++ ++int match_data_to_type(struct match_t *table, int nr_table, char *data, ++ int size, int def) ++{ ++ while (nr_table-- > 0) { ++ if (!memcmp(table->data, data, size)) ++ return table->type; ++ table++; ++ } ++ return def; ++} ++ ++void *match_type_to_data(struct match_t *table, int nr_table, int type, ++ void *def) ++{ ++ while (nr_table-- > 0) { ++ if (table->type == type) ++ return table->data; ++ table++; ++ } ++ return def; ++} +diff --git a/drivers/mtd/nand/match_table.h b/drivers/mtd/nand/match_table.h +new file mode 100644 +index 0000000..6fb55cf +--- /dev/null ++++ b/drivers/mtd/nand/match_table.h +@@ -0,0 +1,56 @@ ++/****************************************************************************** ++ * COPYRIGHT (C) Hisilicon 2013 ++ * All rights reserved. ++ * *** ++ * Create by Hisilicon 2013-08-15 ++ * ++ *****************************************************************************/ ++#ifndef __MATCH_TABLE_H__ ++#define __MATCH_TABLE_H__ ++ ++/*****************************************************************************/ ++struct match_reg_type { ++ int reg; ++ int type; ++}; ++ ++struct match_type_str { ++ int type; ++ const char *str; ++}; ++ ++struct match_t { ++ int type; ++ int reg; ++ void *data; ++}; ++ ++/*****************************************************************************/ ++#define MATCH_SET_TYPE_REG(_type, _reg) {(_type), (_reg), (void *)0} ++#define MATCH_SET_TYPE_DATA(_type, _data) {(_type), 0, (void *)(_data)} ++#define MATCH_SET(_type, _reg, _data) {(_type), (_reg), (void *)(_data)} ++ ++/*****************************************************************************/ ++int reg2type(struct match_reg_type *table, int length, int reg, int def); ++ ++int type2reg(struct match_reg_type *table, int length, int type, int def); ++ ++int str2type(struct match_type_str *table, int length, const char *str, ++ int size, int def); ++ ++const char *type2str(struct match_type_str *table, int length, int type, ++ const char *def); ++ ++int match_reg_to_type(struct match_t *table, int nr_table, int reg, int def); ++ ++int match_type_to_reg(struct match_t *table, int nr_table, int type, int def); ++ ++int match_data_to_type(struct match_t *table, int nr_table, char *data, ++ int size, int def); ++ ++void *match_type_to_data(struct match_t *table, int nr_table, int type, ++ void *def); ++ ++/*****************************************************************************/ ++ ++#endif /* End of __MATCH_TABLE_H__ */ +diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c +index f222f8a..8a5e25d0 100644 +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -47,6 +47,8 @@ + #include + #include + ++#include "hinfc_gen.h" ++ + static int nand_get_device(struct mtd_info *mtd, int new_state); + + static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, +@@ -4058,7 +4060,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, + int *maf_id, int *dev_id, + struct nand_flash_dev *type) + { +- int busw; ++ int busw = 0; + int i, maf_idx; + u8 id_data[8]; + +@@ -4097,6 +4099,30 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, + return ERR_PTR(-ENODEV); + } + ++#if defined(CONFIG_MTD_NAND_HISNFC100) || defined(CONFIG_MTD_SPI_NAND_HIFMC100) ++ /* SPI Nand Flash*/ ++ if (get_spi_nand_flash_type_hook) ++ type = get_spi_nand_flash_type_hook(mtd, id_data); ++ ++ /* SPI Nand Flash only can support the devices on id table */ ++ if (!type) { ++ pr_info("This device[%02x,%02x] cannot found in spi nand id table!!\n", ++ *maf_id, *dev_id); ++ return ERR_PTR(-ENODEV); ++ } else ++ goto ident_done; ++ ++#elif defined(CONFIG_MTD_NAND_HINFC610) || defined(CONFIG_MTD_NAND_HIFMC100) ++ /* Parallel Nand Flash */ ++ ++ /* The 3rd id byte holds MLC / multichip data */ ++ chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]); ++ ++ type = hinfc_get_flash_type(mtd, chip, id_data, &busw); ++ if (type) ++ goto ident_done; ++#endif ++ + if (!type) + type = nand_flash_ids; + +@@ -4144,6 +4170,9 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, + if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize) + chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; + ident_done: ++#ifdef CONFIG_ARCH_HISI_BVT ++ hinfc_nand_param_adjust(mtd, chip); ++#endif + + /* Try to identify manufacturer */ + for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { +@@ -4205,9 +4234,13 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, + pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, + type->name); + +- pr_info("%d MiB, %s, erase size: %d KiB, page size: %d, OOB size: %d\n", ++ pr_info("%dMiB, %s, page size: %d\n", + (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC", +- mtd->erasesize >> 10, mtd->writesize, mtd->oobsize); ++ mtd->writesize); ++ ++ /* Print ecc type and ecc mode about hisilicon flash controller */ ++ hinfc_show_info(mtd, nand_manuf_ids[maf_idx].name, type->name); ++ + return type; + } + +@@ -4727,7 +4760,7 @@ int nand_scan_tail(struct mtd_info *mtd) + break; + + case NAND_ECC_NONE: +- pr_warn("NAND_ECC_NONE selected by board driver. This is not recommended!\n"); ++ pr_warn(" ECC provided by Flash Memory Controller\n"); + ecc->read_page = nand_read_page_raw; + ecc->write_page = nand_write_page_raw; + ecc->read_oob = nand_read_oob_std; +@@ -4814,8 +4847,13 @@ int nand_scan_tail(struct mtd_info *mtd) + break; + } + ++#ifdef CONFIG_MTD_UBI ++ /* mtd->type = MTD_MLCNANDFLASH isn't support by mtd_util ubi tools jet */ ++ mtd->type = MTD_NANDFLASH; ++#else + /* Fill in remaining MTD driver data */ + mtd->type = nand_is_slc(chip) ? MTD_NANDFLASH : MTD_MLCNANDFLASH; ++#endif + mtd->flags = (chip->options & NAND_ROM) ? MTD_CAP_ROM : + MTD_CAP_NANDFLASH; + mtd->_erase = nand_erase; +diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c +index 2af9869..eae2460 100644 +--- a/drivers/mtd/nand/nand_ids.c ++++ b/drivers/mtd/nand/nand_ids.c +@@ -168,7 +168,7 @@ struct nand_flash_dev nand_flash_ids[] = { + /* Manufacturer IDs */ + struct nand_manufacturers nand_manuf_ids[] = { + {NAND_MFR_TOSHIBA, "Toshiba"}, +- {NAND_MFR_ESMT, "ESMT"}, ++ {NAND_MFR_GD_ESMT, "GD/ESMT"}, + {NAND_MFR_SAMSUNG, "Samsung"}, + {NAND_MFR_FUJITSU, "Fujitsu"}, + {NAND_MFR_NATIONAL, "National"}, +@@ -179,9 +179,15 @@ struct nand_manufacturers nand_manuf_ids[] = { + {NAND_MFR_AMD, "AMD/Spansion"}, + {NAND_MFR_MACRONIX, "Macronix"}, + {NAND_MFR_EON, "Eon"}, ++ {NAND_MFR_WINBOND, "Winbond"}, ++ {NAND_MFR_ATO, "ATO"}, ++ {NAND_MFR_MXIC, "MXIC"}, ++ {NAND_MFR_ALL_FLASH, "All-flash"}, ++ {NAND_MFR_PARAGON, "Paragon"}, + {NAND_MFR_SANDISK, "SanDisk"}, + {NAND_MFR_INTEL, "Intel"}, + {NAND_MFR_ATO, "ATO"}, ++ {NAND_MFR_HEYANGTEK, "HeYangTek"}, + {0x0, "Unknown"} + }; + +diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig +index 4a682ee..b72cf27 100644 +--- a/drivers/mtd/spi-nor/Kconfig ++++ b/drivers/mtd/spi-nor/Kconfig +@@ -59,11 +59,12 @@ config SPI_FSL_QUADSPI + SPI NOR. + + config SPI_HISI_SFC +- tristate "Hisilicon SPI-NOR Flash Controller(SFC)" +- depends on ARCH_HISI || COMPILE_TEST ++ tristate "Hisilicon FMCV100 SPI-NOR Flash Controller(SFC)" ++ depends on ARCH_HISI || ARCH_HISI_BVT || COMPILE_TEST + depends on HAS_IOMEM && HAS_DMA + help +- This enables support for hisilicon SPI-NOR flash controller. ++ This enables support for hisilicon flash memory contrller ver100 ++ (FMCV100)- SPI-NOR flash controller. + + config SPI_NXP_SPIFI + tristate "NXP SPI Flash Interface (SPIFI)" +@@ -76,4 +77,34 @@ config SPI_NXP_SPIFI + Flash. Enable this option if you have a device with a SPIFI + controller and want to access the Flash as a mtd device. + ++config MTD_SPI_IDS ++ bool "SPI Flash Timing Cycles Probe Function" ++ default n ++ help ++ This option enables hisfc300/hisfc350 used spi flash timing cylces ++ probe function. ++ If your use hisfc300 and hisfc350, this function should be select. ++ ++config CLOSE_SPI_8PIN_4IO ++ bool "Close SPI device Quad SPI mode for some 8PIN chip" ++ default y if ARCH_HISI_BVT ++ help ++ Hifmcv100 and Hisfcv350 support Quad SPI mode and Quad&addr SPI mode. ++ But some 8PIN chip does not support this mode when HOLD/IO3 PIN ++ was used by reset operation. ++ Usually, your should not config this option. ++ ++config HISI_SPI_BLOCK_PROTECT ++ bool "Hisilicon Spi Nor Device BP(Block Protect) Support" ++ depends on SPI_HISI_SFC ++ default y if SPI_HISI_SFC ++ help ++ HISI SFC supports BP(Block Protect) feature to preestablish a series ++ area to avoid writing and erasing, except to reading. With this macro ++ definition we can get the BP info which was setted before. The ++ BOTTOM/TOP bit is setted to BOTTOM, it means the lock area starts ++ from 0 address. ++ ++source "drivers/mtd/spi-nor/hisfc350/Kconfig" ++ + endif # MTD_SPI_NOR +diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile +index 121695e..ac5d355 100644 +--- a/drivers/mtd/spi-nor/Makefile ++++ b/drivers/mtd/spi-nor/Makefile +@@ -5,3 +5,6 @@ obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o + obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o + obj-$(CONFIG_MTD_MT81xx_NOR) += mtk-quadspi.o + obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o ++ ++obj-$(CONFIG_MTD_SPI_IDS) += spi_ids.o ++obj-$(CONFIG_MTD_HISFC350) += hisfc350/ +diff --git a/drivers/mtd/spi-nor/hisfc350/Kconfig b/drivers/mtd/spi-nor/hisfc350/Kconfig +new file mode 100644 +index 0000000..a999c92 +--- /dev/null ++++ b/drivers/mtd/spi-nor/hisfc350/Kconfig +@@ -0,0 +1,51 @@ ++# ++# hisilicon spi flash controller device version 350 ++# ++ ++menuconfig MTD_HISFC350 ++ tristate "hisilicon spi flash controller device version 350 driver" ++ depends on (ARCH_HI3516A) ++ default y if (ARCH_HI3516A) ++ select MTD_SPI_IDS ++ help ++ Hisilicon spi flash controller device version 350. ++ Hisilicon spi flash controller version 350 support ++ DMA transfers while reading and write the spi flash, ++ which will improve the performace very much. ++ ++if MTD_HISFC350 ++ ++config HISFC350_SYSCTRL_ADDRESS ++ hex "cpu system control register base address" ++ default "0x20030000" if (ARCH_HI3516A) ++ ++config HISFC350_CHIP_NUM ++ int "hisfc350 spi chip number" ++ default 2 if (ARCH_HI3516A) ++ ++config HISFC350_SHOW_CYCLE_TIMING ++ bool "show spi read/write/erase cycle timing" ++ default n if (ARCH_HI3516A) ++ help ++ Show spi read/write/erase cycle timing, command, clock. ++ This is a debug option. When enabled, some command and ++ cycles uesed on operations will show for you. ++ If unsure, say no. ++ ++config HISFC350_ENABLE_CHIPSELECT_0 ++ bool "use spi device on chipselect 0" ++ default n if (ARCH_HI3516A) ++ ++config HISFC350_ENABLE_CHIPSELECT_1 ++ bool "use spi device on chipselect 1" ++ default y if (ARCH_HI3516A) ++ ++config HISFC350_ENABLE_INTR_DMA ++ bool "use the IRQ mode of spi device R/W" ++ default n if (ARCH_HI3516A) ++ ++config CMD_SPI_BLOCK_PROTECTION ++ bool "enable the SPI nor flash block protection" ++ default y if (ARCH_HI3516A) ++ ++endif # MTD_HISFC350 +diff --git a/drivers/mtd/spi-nor/hisfc350/Makefile b/drivers/mtd/spi-nor/hisfc350/Makefile +new file mode 100644 +index 0000000..bc5f400 +--- /dev/null ++++ b/drivers/mtd/spi-nor/hisfc350/Makefile +@@ -0,0 +1,7 @@ ++# ++# drivers/devices/hisfc350/Makefile ++# ++ ++obj-$(CONFIG_MTD_HISFC350) += hisfc350_spi_ids.o hisfc350.o ++ ++ +diff --git a/drivers/mtd/spi-nor/hisfc350/hisfc350.c b/drivers/mtd/spi-nor/hisfc350/hisfc350.c +new file mode 100644 +index 0000000..0e7f82c +--- /dev/null ++++ b/drivers/mtd/spi-nor/hisfc350/hisfc350.c +@@ -0,0 +1,1555 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/*****************************************************************************/ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../../mtdcore.h" ++#include "../spi_ids.h" ++#include "hisfc350.h" ++ ++#define THREE_BYTE_ADDR_BOOT 0 ++ ++#ifdef CONFIG_ARCH_HI3516A ++#include "hisfc350_hi3516a.c" ++#endif ++ ++#ifndef GET_SFC_ADDR_MODE ++#define GET_SFC_ADDR_MODE (0) ++#endif ++ ++/* Don't change the follow config */ ++#define HISFC350_SUPPORT_READ (SPI_IF_READ_STD \ ++ | SPI_IF_READ_FAST \ ++ | SPI_IF_READ_DUAL \ ++ | SPI_IF_READ_DUAL_ADDR \ ++ | SPI_IF_READ_QUAD \ ++ | SPI_IF_READ_QUAD_ADDR) ++ ++#define HISFC350_SUPPORT_WRITE (SPI_IF_WRITE_STD \ ++ | SPI_IF_WRITE_DUAL \ ++ | SPI_IF_WRITE_DUAL_ADDR \ ++ | SPI_IF_WRITE_QUAD \ ++ | SPI_IF_WRITE_QUAD_ADDR) ++ ++#define HISFC350_SUPPORT_MAX_DUMMY (7) ++ ++#ifdef CONFIG_HISFC350_ENABLE_INTR_DMA ++static loff_t sfc_ft; ++static size_t sfc_length; ++static int sfc_num; ++static unsigned char *sfc_offset; ++static unsigned int sfc_rw; ++#endif ++ ++static int start_up_mode; ++ ++static char *ultohstr(unsigned long long size) ++{ ++ int ix; ++ static char buffer[20]; ++ char *fmt[] = {"%u", "%uK", "%uM", "%uG", "%uT", "%uT"}; ++ ++ for (ix = 0; (ix < 5) && !(size & 0x3FF) && size; ix++) ++ size = (size >> 10); ++ ++ sprintf(buffer, fmt[ix], size); ++ return buffer; ++} ++ ++#ifdef CONFIG_HISFC350_SHOW_CYCLE_TIMING ++static char *hisfc350_get_ifcycle_str(int ifcycle) ++{ ++ static char *ifcycle_str[] = { ++ "single", ++ "dual", ++ "dual-addr", ++ "dual-cmd", ++ "reserve", ++ "quad", ++ "quad-addr", ++ "quad-cmd", ++ }; ++ ++ return ifcycle_str[(ifcycle & 0x07)]; ++} ++#endif ++ ++static void hisfc350_set_host_addr_mode(struct hisfc_host *host, int enable) ++{ ++ unsigned int regval; ++ regval = hisfc_read(host, HISFC350_GLOBAL_CONFIG); ++ if (enable) ++ regval |= HISFC350_GLOBAL_CONFIG_ADDR_MODE_4B; ++ else ++ regval &= ~HISFC350_GLOBAL_CONFIG_ADDR_MODE_4B; ++ ++ hisfc_write(host, HISFC350_GLOBAL_CONFIG, regval); ++} ++ ++static void hisfc350_spi_nor_shutdown(struct platform_device *pdev) ++{ ++ if (start_up_mode == THREE_BYTE_ADDR_BOOT) { ++ int ix; ++ ++ struct hisfc_host *host = platform_get_drvdata(pdev); ++ struct hisfc_spi *spi = host->spi; ++ ++ for (ix = 0; ix < host->num_chip; ix++, spi++) { ++ if (spi->addrcycle == SPI_4BYTE_ADDR_LEN) { ++ spi->driver->wait_ready(spi); ++ spi->driver->entry_4addr(spi, 0); ++ } ++ } ++ } ++} ++static void hisfc350_map_iftype_and_clock(struct hisfc_spi *spi) ++{ ++ int ix; ++ const int iftype_read[] = { ++ SPI_IF_READ_STD, HISFC350_IFCYCLE_STD, ++ SPI_IF_READ_FAST, HISFC350_IFCYCLE_STD, ++ SPI_IF_READ_DUAL, HISFC350_IFCYCLE_DUAL, ++ SPI_IF_READ_DUAL_ADDR, HISFC350_IFCYCLE_DUAL_ADDR, ++ SPI_IF_READ_QUAD, HISFC350_IFCYCLE_QUAD, ++ SPI_IF_READ_QUAD_ADDR, HISFC350_IFCYCLE_QUAD_ADDR, ++ 0, 0, ++ }; ++ const int iftype_write[] = { ++ SPI_IF_WRITE_STD, HISFC350_IFCYCLE_STD, ++ SPI_IF_WRITE_DUAL, HISFC350_IFCYCLE_DUAL, ++ SPI_IF_WRITE_DUAL_ADDR, HISFC350_IFCYCLE_DUAL_ADDR, ++ SPI_IF_WRITE_QUAD, HISFC350_IFCYCLE_QUAD, ++ SPI_IF_WRITE_QUAD_ADDR, HISFC350_IFCYCLE_QUAD_ADDR, ++ 0, 0, ++ }; ++ ++ for (ix = 0; iftype_write[ix]; ix += 2) { ++ if (spi->write->iftype == iftype_write[ix]) { ++ spi->write->iftype = iftype_write[ix + 1]; ++ break; ++ } ++ } ++ hisfc350_get_best_clock(&spi->write->clock); ++ ++ for (ix = 0; iftype_read[ix]; ix += 2) { ++ if (spi->read->iftype == iftype_read[ix]) { ++ spi->read->iftype = iftype_read[ix + 1]; ++ break; ++ } ++ } ++ hisfc350_get_best_clock(&spi->read->clock); ++ ++ hisfc350_get_best_clock(&spi->erase->clock); ++ spi->erase->iftype = HISFC350_IFCYCLE_STD; ++} ++ ++static void hisfc350_dma_transfer(struct hisfc_host *host, ++ loff_t spi_start_addr, unsigned char *dma_buffer, ++ unsigned char is_read, size_t size, unsigned char chipselect) ++{ ++ hisfc_write(host, HISFC350_BUS_DMA_MEM_SADDR, dma_buffer); ++ ++ hisfc_write(host, HISFC350_BUS_DMA_FLASH_SADDR, ++ (u32)spi_start_addr); ++ ++ hisfc_write(host, HISFC350_BUS_DMA_LEN, ++ HISFC350_BUS_DMA_LEN_DATA_CNT(size)); ++ ++ hisfc_write(host, HISFC350_BUS_DMA_AHB_CTRL, ++ HISFC350_BUS_DMA_AHB_CTRL_INCR4_EN ++ | HISFC350_BUS_DMA_AHB_CTRL_INCR8_EN ++ | HISFC350_BUS_DMA_AHB_CTRL_INCR16_EN); ++ ++ hisfc_write(host, HISFC350_BUS_DMA_CTRL, ++ HISFC350_BUS_DMA_CTRL_RW(is_read) ++ | HISFC350_BUS_DMA_CTRL_CS(chipselect) ++ | HISFC350_BUS_DMA_CTRL_START); ++ ++#ifndef CONFIG_HISFC350_ENABLE_INTR_DMA ++ HISFC350_DMA_WAIT_CPU_FINISH(host); ++#endif ++} ++ ++#ifdef HISFCV350_SUPPORT_REG_READ ++static char *hisfc350_reg_read_buf(struct hisfc_host *host, ++ struct hisfc_spi *spi, loff_t spi_start_addr, ++ unsigned int size, unsigned char *buffer) ++{ ++ int index = 0; ++ ++ if (size > HISFC350_REG_BUF_SIZE) ++ DBG_BUG("reg read out of reg range.\n"); ++ ++ hisfc_write(host, HISFC350_CMD_INS, spi->read->cmd); ++ hisfc_write(host, HISFC350_CMD_ADDR, ++ ((u32)spi_start_addr & HISFC350_CMD_ADDR_MASK)); ++ hisfc_write(host, HISFC350_CMD_CONFIG, ++ HISFC350_CMD_CONFIG_MEM_IF_TYPE(spi->read->iftype) ++ | HISFC350_CMD_CONFIG_DATA_CNT(size) ++ | HISFC350_CMD_CONFIG_RW_READ ++ | HISFC350_CMD_CONFIG_DATA_EN ++ | HISFC350_CMD_CONFIG_DUMMY_CNT(spi->read->dummy) ++ | HISFC350_CMD_CONFIG_ADDR_EN ++ | HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect) ++ | HISFC350_CMD_CONFIG_START); ++ ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++ ++ while (index < size) { ++ *(unsigned int *)(host->reg_buffer + index) = hisfc_read(host, ++ HISFC350_CMD_DATABUF0 + index); ++ index += 4; ++ } ++ ++ memcpy(buffer, host->reg_buffer, size); ++ ++ return buffer; ++} ++ ++static int hisfc350_reg_read(struct mtd_info *mtd, loff_t from, size_t len, ++ size_t *retlen, u_char *buf) ++{ ++ int num; ++ int result = -EIO; ++ unsigned char *ptr = buf; ++ struct hisfc_host *host = MTD_TO_HOST(mtd); ++ struct hisfc_spi *spi = host->spi; ++ ++ if ((from + len) > mtd->size) { ++ DBG_MSG("read area out of range.\n"); ++ return -EINVAL; ++ } ++ ++ *retlen = 0; ++ if (!len) { ++ DBG_MSG("read length is 0.\n"); ++ return 0; ++ } ++ mutex_lock(&host->lock); ++ ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ host->set_system_clock(host, spi->read, TRUE); ++ ++ while (len > 0) { ++ while (from >= spi->chipsize) { ++ from -= spi->chipsize; ++ spi++; ++ if (!spi->name) ++ DBG_BUG("read memory out of range.\n"); ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ host->set_system_clock(host, spi->read, TRUE); ++ } ++ ++ num = ((from + len) >= spi->chipsize) ++ ? (spi->chipsize - from) : len; ++ ++ while (num >= HISFC350_REG_BUF_SIZE) { ++ hisfc350_reg_read_buf(host, spi, ++ from, HISFC350_REG_BUF_SIZE, ptr); ++ ptr += HISFC350_REG_BUF_SIZE; ++ from += HISFC350_REG_BUF_SIZE; ++ len -= HISFC350_REG_BUF_SIZE; ++ num -= HISFC350_REG_BUF_SIZE; ++ } ++ ++ if (num) { ++ hisfc350_reg_read_buf(host, spi, ++ from, num, ptr); ++ from += num; ++ ptr += num; ++ len -= num; ++ } ++ } ++ result = 0; ++ *retlen = (size_t)(ptr - buf); ++fail: ++ mutex_unlock(&host->lock); ++ return result; ++} ++#endif /* HISFCV350_SUPPORT_REG_READ */ ++ ++#ifdef CONFIG_HISFC350_ENABLE_INTR_DMA ++static int hisfc350_dma_intr_read(struct mtd_info *mtd, loff_t from, size_t len, ++ size_t *retlen, u_char *buf) ++{ ++ int result = -EIO; ++ struct hisfc_host *host = MTD_TO_HOST(mtd); ++ struct hisfc_spi *spi = host->spi; ++ ++ if ((from + len) > mtd->size) { ++ DBG_MSG("read area out of range.\n"); ++ return -EINVAL; ++ } ++ ++ *retlen = 0; ++ if (!len) { ++ DBG_MSG("read length is 0.\n"); ++ return 0; ++ } ++ ++ mutex_lock(&host->lock); ++ ++ sfc_offset = (unsigned char *)buf; ++ sfc_ft = from; ++ sfc_length = len; ++ sfc_rw = READ; ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ spi->driver->bus_prepare(spi, READ); ++ ++ if (sfc_ft & HISFC350_DMA_ALIGN_MASK) { ++ sfc_num = HISFC350_DMA_ALIGN_SIZE - ++ (sfc_ft & HISFC350_DMA_ALIGN_MASK); ++ if (sfc_num > sfc_length) ++ sfc_num = sfc_length; ++ while (sfc_ft >= spi->chipsize) { ++ sfc_ft -= spi->chipsize; ++ spi++; ++ if (!spi->name) ++ DBG_BUG("write memory out of range.\n"); ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ spi->driver->bus_prepare(spi, sfc_rw); ++ } ++ } else{ ++ while (sfc_ft >= spi->chipsize) { ++ sfc_ft -= spi->chipsize; ++ spi++; ++ if (!spi->name) ++ DBG_BUG("read memory out of range.\n"); ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ spi->driver->bus_prepare(spi, sfc_rw); ++ } ++ if ((sfc_ft + sfc_length) >= spi->chipsize) { ++ sfc_num = spi->chipsize - sfc_ft; ++ if (sfc_num >= HISFC350_DMA_MAX_SIZE) ++ sfc_num = HISFC350_DMA_MAX_SIZE; ++ } else{ ++ sfc_num = sfc_length; ++ if (sfc_num >= HISFC350_DMA_MAX_SIZE) ++ sfc_num = HISFC350_DMA_MAX_SIZE; ++ } ++ } ++ ++ hisfc350_dma_transfer(host, sfc_ft, ++ (unsigned char *)host->dma_buffer, sfc_rw, ++ sfc_num, spi->chipselect); ++ wait_event(host->intr_wait, host->wait_fg == SFC_WAIT_FLAG_R); ++ host->wait_fg = 0; ++ result = 0; ++ *retlen = (size_t)(sfc_offset - buf); ++fail: ++ mutex_unlock(&host->lock); ++ return result; ++} ++#else ++static int hisfc350_dma_read(struct mtd_info *mtd, loff_t from, size_t len, ++ size_t *retlen, u_char *buf) ++{ ++ int num; ++ int result = -EIO; ++ unsigned char *ptr = buf; ++ struct hisfc_host *host = MTD_TO_HOST(mtd); ++ struct hisfc_spi *spi = host->spi; ++ ++ if ((from + len) > mtd->size) { ++ DBG_MSG("read area out of range.\n"); ++ return -EINVAL; ++ } ++ ++ *retlen = 0; ++ if (!len) { ++ DBG_MSG("read length is 0.\n"); ++ return 0; ++ } ++ ++ mutex_lock(&host->lock); ++ ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ spi->driver->bus_prepare(spi, READ); ++ host->set_system_clock(host, spi->read, TRUE); ++ ++ if (from & HISFC350_DMA_ALIGN_MASK) { ++ num = HISFC350_DMA_ALIGN_SIZE - ++ (from & HISFC350_DMA_ALIGN_MASK); ++ if (num > len) ++ num = len; ++ while (from >= spi->chipsize) { ++ from -= spi->chipsize; ++ spi++; ++ if (!spi->name) ++ DBG_BUG("write memory out of range.\n"); ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ spi->driver->bus_prepare(spi, READ); ++ host->set_system_clock(host, spi->read, TRUE); ++ } ++ hisfc350_dma_transfer(host, from, ++ (unsigned char *)host->dma_buffer, READ, ++ num, spi->chipselect); ++ memcpy(ptr, host->buffer, num); ++ from += num; ++ ptr += num; ++ len -= num; ++ } ++ ++ while (len > 0) { ++ while (from >= spi->chipsize) { ++ from -= spi->chipsize; ++ spi++; ++ if (!spi->name) ++ DBG_BUG("read memory out of range.\n"); ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ spi->driver->bus_prepare(spi, READ); ++ host->set_system_clock(host, spi->read, TRUE); ++ } ++ ++ num = ((from + len) >= spi->chipsize) ++ ? (spi->chipsize - from) : len; ++ while (num >= HISFC350_DMA_MAX_SIZE) { ++ hisfc350_dma_transfer(host, from, ++ (unsigned char *)host->dma_buffer, READ, ++ HISFC350_DMA_MAX_SIZE, spi->chipselect); ++ memcpy(ptr, host->buffer, HISFC350_DMA_MAX_SIZE); ++ ptr += HISFC350_DMA_MAX_SIZE; ++ from += HISFC350_DMA_MAX_SIZE; ++ len -= HISFC350_DMA_MAX_SIZE; ++ num -= HISFC350_DMA_MAX_SIZE; ++ } ++ ++ if (num) { ++ hisfc350_dma_transfer(host, from, ++ (unsigned char *)host->dma_buffer, READ, ++ num, spi->chipselect); ++ memcpy(ptr, host->buffer, num); ++ from += num; ++ ptr += num; ++ len -= num; ++ } ++ } ++ result = 0; ++ *retlen = (size_t)(ptr - buf); ++fail: ++ mutex_unlock(&host->lock); ++ return result; ++} ++#endif ++ ++static unsigned char *hisfc350_read_ids(struct hisfc_host *host, ++ int chipselect, unsigned char *buffer) ++{ ++ int regindex = 0; ++ int numread = 8; ++ unsigned int *ptr = (unsigned int *)buffer; ++ ++ if (numread > HISFC350_REG_BUF_SIZE) ++ numread = HISFC350_REG_BUF_SIZE; ++ ++ hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_RDID); ++ hisfc_write(host, HISFC350_CMD_CONFIG, ++ HISFC350_CMD_CONFIG_SEL_CS(chipselect) ++ | HISFC350_CMD_CONFIG_RW_READ ++ | HISFC350_CMD_CONFIG_DATA_EN ++ | HISFC350_CMD_CONFIG_DATA_CNT(numread) ++ | HISFC350_CMD_CONFIG_START); ++ ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++ ++ while (numread) { ++ *ptr = hisfc_read(host, ++ HISFC350_CMD_DATABUF0 + regindex); ++ ptr += 1; ++ regindex += 4; ++ numread -= 4; ++ } ++ ++ return buffer; ++} ++ ++static int hisfc350_reg_erase_one_block(struct hisfc_host *host, ++ struct hisfc_spi *spi, unsigned int offset) ++{ ++ if (spi->driver->wait_ready(spi)) ++ return 1; ++ ++ spi->driver->write_enable(spi); ++ host->set_system_clock(host, spi->erase, TRUE); ++ ++ hisfc_write(host, HISFC350_CMD_INS, spi->erase->cmd); ++ ++ hisfc_write(host, HISFC350_CMD_ADDR, ++ (offset & HISFC350_CMD_ADDR_MASK)); ++ ++ hisfc_write(host, HISFC350_CMD_CONFIG, ++ HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect) ++ | HISFC350_CMD_CONFIG_MEM_IF_TYPE(spi->erase->iftype) ++ | HISFC350_CMD_CONFIG_DUMMY_CNT(spi->erase->dummy) ++ | HISFC350_CMD_CONFIG_ADDR_EN ++ | HISFC350_CMD_CONFIG_START); ++ ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_HISFC350_ENABLE_INTR_DMA ++static int hisfc350_dma_intr_write(struct mtd_info *mtd, loff_t to, size_t len, ++ size_t *retlen, const u_char *buf) ++{ ++ int result = -EIO; ++ struct hisfc_host *host = MTD_TO_HOST(mtd); ++ struct hisfc_spi *spi = host->spi; ++ ++ if ((to + len) > mtd->size) { ++ DBG_MSG("write data out of range.\n"); ++ return -EINVAL; ++ } ++ ++ *retlen = 0; ++ if (!len) { ++ DBG_MSG("write length is 0.\n"); ++ return 0; ++ } ++ ++#ifdef CONFIG_CMD_SPI_BLOCK_PROTECTION ++ if ((BP_CMP_TOP == host->cmp) && ((to + len) > host->start_addr)) { ++ DBG_MSG("write area to[%#x => %#x] is locked, please " \ ++ "unlock these blocks on u-boot.\n", ++ host->start_addr, (to + len)); ++ return -EINVAL; ++ } ++ ++ if ((BP_CMP_BOTTOM == host->cmp) && (to <= host->end_addr)) { ++ unsigned end = ((to + len) > host->end_addr) \ ++ ? host->end_addr : (to + len); ++ ++ DBG_MSG("write area to[%#x => %#x] is locked, please " \ ++ "unlock these blocks on u-boot.\n", to, end); ++ return -EINVAL; ++ } ++#endif /* CONFIG_CMD_SPI_BLOCK_PROTECTION */ ++ ++ mutex_lock(&host->lock); ++ ++ sfc_offset = (unsigned char *)buf; ++ sfc_ft = to; ++ sfc_length = len; ++ sfc_rw = WRITE; ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ ++ spi->driver->write_enable(spi); ++ spi->driver->bus_prepare(spi, sfc_rw); ++ ++ if (sfc_ft & HISFC350_DMA_ALIGN_MASK) { ++ sfc_num = HISFC350_DMA_ALIGN_SIZE ++ - (sfc_ft & HISFC350_DMA_ALIGN_MASK); ++ if (sfc_num > sfc_length) ++ sfc_num = sfc_length; ++ while (sfc_ft >= spi->chipsize) { ++ sfc_ft -= spi->chipsize; ++ spi++; ++ if (!spi->name) ++ DBG_BUG("write memory out of range.\n"); ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ spi->driver->write_enable(spi); ++ spi->driver->bus_prepare(spi, sfc_rw); ++ } ++ } else{ ++ while (sfc_ft >= spi->chipsize) { ++ sfc_ft -= spi->chipsize; ++ spi++; ++ if (!spi->name) ++ DBG_BUG("read memory out of range.\n"); ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ spi->driver->write_enable(spi); ++ spi->driver->bus_prepare(spi, sfc_rw); ++ } ++ if ((sfc_ft + sfc_length) >= spi->chipsize) { ++ sfc_num = spi->chipsize - sfc_ft; ++ if (sfc_num >= HISFC350_DMA_MAX_SIZE) ++ sfc_num = HISFC350_DMA_MAX_SIZE; ++ } else{ ++ sfc_num = sfc_length; ++ if (sfc_num >= HISFC350_DMA_MAX_SIZE) ++ sfc_num = HISFC350_DMA_MAX_SIZE; ++ } ++ } ++ ++ memcpy(host->buffer, sfc_offset, sfc_num); ++ hisfc350_dma_transfer(host, sfc_ft, ++ (unsigned char *)host->dma_buffer, sfc_rw, ++ sfc_num, spi->chipselect); ++ wait_event(host->intr_wait, host->wait_fg == SFC_WAIT_FLAG_W); ++ host->wait_fg = 0; ++ *retlen = (size_t)(sfc_offset - buf); ++ result = 0; ++fail: ++ mutex_unlock(&host->lock); ++ return result; ++} ++#else ++static int hisfc350_dma_write(struct mtd_info *mtd, loff_t to, size_t len, ++ size_t *retlen, const u_char *buf) ++{ ++ int num; ++ int result = -EIO; ++ ++ unsigned char *ptr = (unsigned char *)buf; ++ struct hisfc_host *host = MTD_TO_HOST(mtd); ++ struct hisfc_spi *spi = host->spi; ++ ++ if ((to + len) > mtd->size) { ++ DBG_MSG("write data out of range.\n"); ++ return -EINVAL; ++ } ++ ++ *retlen = 0; ++ if (!len) { ++ DBG_MSG("write length is 0.\n"); ++ return 0; ++ } ++ ++#ifdef CONFIG_CMD_SPI_BLOCK_PROTECTION ++ if (host->level) { ++ if ((BP_CMP_TOP == host->cmp) ++ && ((to + len) > host->start_addr)) { ++ DBG_MSG("write area to[%#x => %#x] is locked, please " \ ++ "unlock these blocks on u-boot.\n", ++ host->start_addr, (unsigned)(to + len)); ++ return -EINVAL; ++ } ++ ++ if ((BP_CMP_BOTTOM == host->cmp) && (to < host->end_addr)) { ++ unsigned end = ((to + len) > host->end_addr) \ ++ ? host->end_addr : (to + len); ++ ++ DBG_MSG("write area to[%#x => %#x] is locked, please " \ ++ "unlock these blocks on u-boot.\n", ++ (unsigned)to, end); ++ return -EINVAL; ++ } ++ } ++#endif /* CONFIG_CMD_SPI_BLOCK_PROTECTION */ ++ ++ mutex_lock(&host->lock); ++ ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ ++ spi->driver->write_enable(spi); ++ spi->driver->bus_prepare(spi, WRITE); ++ host->set_system_clock(host, spi->write, TRUE); ++ ++ if (to & HISFC350_DMA_ALIGN_MASK) { ++ num = HISFC350_DMA_ALIGN_SIZE - (to & HISFC350_DMA_ALIGN_MASK); ++ if (num > len) ++ num = len; ++ while (to >= spi->chipsize) { ++ to -= spi->chipsize; ++ spi++; ++ if (!spi->name) ++ DBG_BUG("write memory out of range.\n"); ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ spi->driver->write_enable(spi); ++ spi->driver->bus_prepare(spi, WRITE); ++ host->set_system_clock(host, spi->write, TRUE); ++ } ++ memcpy(host->buffer, ptr, num); ++ hisfc350_dma_transfer(host, to, ++ (unsigned char *)host->dma_buffer, WRITE, ++ num, spi->chipselect); ++ ++ to += num; ++ ptr += num; ++ len -= num; ++ } ++ ++ while (len > 0) { ++ num = ((len >= HISFC350_DMA_MAX_SIZE) ++ ? HISFC350_DMA_MAX_SIZE : len); ++ while (to >= spi->chipsize) { ++ to -= spi->chipsize; ++ spi++; ++ if (!spi->name) ++ DBG_BUG("write memory out of range.\n"); ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ spi->driver->write_enable(spi); ++ spi->driver->bus_prepare(spi, WRITE); ++ host->set_system_clock(host, spi->write, TRUE); ++ } ++ ++ memcpy(host->buffer, ptr, num); ++ hisfc350_dma_transfer(host, to, ++ (unsigned char *)host->dma_buffer, WRITE, ++ num, spi->chipselect); ++ ++ to += num; ++ ptr += num; ++ len -= num; ++ } ++ *retlen = (size_t)(ptr - buf); ++ result = 0; ++fail: ++ mutex_unlock(&host->lock); ++ return result; ++} ++#endif ++ ++#ifdef HISFCV350_SUPPORT_REG_WRITE ++static int hisfc350_reg_write_buf(struct hisfc_host *host, ++ struct hisfc_spi *spi, unsigned int spi_start_addr, ++ unsigned int size, unsigned char *buffer) ++{ ++ int index = 0; ++ ++ if (size > HISFC350_REG_BUF_SIZE) ++ DBG_BUG("reg read out of reg range.\n"); ++ ++ if (spi->driver->wait_ready(spi)) ++ return 1; ++ ++ memcpy(host->reg_buffer, buffer, size); ++ ++ while (index < size) { ++ hisfc_write(host, HISFC350_CMD_DATABUF0 + index, ++ *(unsigned int *)(host->reg_buffer + index)); ++ index += 4; ++ } ++ ++ spi->driver->write_enable(spi); ++ ++ hisfc_write(host, HISFC350_CMD_INS, spi->write->cmd); ++ hisfc_write(host, HISFC350_CMD_ADDR, ++ ((u32)spi_start_addr & HISFC350_CMD_ADDR_MASK)); ++ hisfc_write(host, HISFC350_CMD_CONFIG, ++ HISFC350_CMD_CONFIG_MEM_IF_TYPE(spi->write->iftype) ++ | HISFC350_CMD_CONFIG_DATA_CNT(size) ++ | HISFC350_CMD_CONFIG_DATA_EN ++ | HISFC350_CMD_CONFIG_DUMMY_CNT(spi->write->dummy) ++ | HISFC350_CMD_CONFIG_ADDR_EN ++ | HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect) ++ | HISFC350_CMD_CONFIG_START); ++ ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++ ++ return 0; ++} ++ ++static int hisfc350_reg_write(struct mtd_info *mtd, loff_t to, size_t len, ++ size_t *retlen, const u_char *buf) ++{ ++ int num; ++ int result = -EIO; ++ unsigned char *ptr = (unsigned char *)buf; ++ struct hisfc_host *host = MTD_TO_HOST(mtd); ++ struct hisfc_spi *spi = host->spi; ++ ++ if ((to + len) > mtd->size) { ++ DBG_MSG("write data out of range.\n"); ++ return -EINVAL; ++ } ++ ++ *retlen = 0; ++ if (!len) { ++ DBG_MSG("write length is 0.\n"); ++ return 0; ++ } ++ ++#ifdef CONFIG_CMD_SPI_BLOCK_PROTECTION ++ if (host->level) { ++ if ((BP_CMP_TOP == host->cmp) ++ && ((to + len) > host->start_addr)) { ++ DBG_MSG("write area to[%#x => %#x] is locked, please " \ ++ "unlock these blocks on u-boot.\n", ++ host->start_addr, (to + len)); ++ return -EINVAL; ++ } ++ ++ if ((BP_CMP_BOTTOM == host->cmp) && (to < host->end_addr)) { ++ unsigned end = ((to + len) > host->end_addr) \ ++ ? host->end_addr : (to + len); ++ ++ DBG_MSG("write area to[%#x => %#x] is locked, please " \ ++ "unlock these blocks on u-boot.\n", to, end); ++ return -EINVAL; ++ } ++ } ++#endif /* CONFIG_CMD_SPI_BLOCK_PROTECTION */ ++ ++ mutex_lock(&host->lock); ++ ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ ++ host->set_system_clock(host, spi->write, TRUE); ++ ++ if (to & HISFC350_REG_BUF_MASK) { ++ num = HISFC350_REG_BUF_SIZE - (to & HISFC350_REG_BUF_MASK); ++ if (num > (int)len) ++ num = (int)len; ++ ++ while (to >= spi->chipsize) { ++ to -= spi->chipsize; ++ spi++; ++ if (!spi->name) ++ DBG_BUG("write memory out of range.\n"); ++ ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ ++ host->set_system_clock(host, spi->write, TRUE); ++ } ++ if (hisfc350_reg_write_buf(host, spi, to, num, ptr)) ++ goto fail; ++ to += num; ++ ptr += num; ++ len -= num; ++ } ++ ++ while (len > 0) { ++ num = ((len >= HISFC350_REG_BUF_SIZE) ? ++ HISFC350_REG_BUF_SIZE : len); ++ while (to >= spi->chipsize) { ++ to -= spi->chipsize; ++ spi++; ++ if (!spi->name) ++ DBG_BUG("write memory out of range.\n"); ++ ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ ++ host->set_system_clock(host, spi->write, TRUE); ++ } ++ if (hisfc350_reg_write_buf(host, spi, to, num, ptr)) ++ goto fail; ++ to += num; ++ ptr += num; ++ len -= num; ++ } ++ *retlen = (size_t)(ptr - buf); ++ result = 0; ++fail: ++ mutex_unlock(&host->lock); ++ return result; ++} ++#endif /* HISFCV350_SUPPORT_REG_WRITE */ ++ ++static int hisfc350_reg_erase(struct mtd_info *mtd, struct erase_info *instr) ++{ ++ struct hisfc_host *host = MTD_TO_HOST(mtd); ++ struct hisfc_spi *spi = host->spi; ++ ++ unsigned long long offset = instr->addr; ++ unsigned long long length = instr->len; ++ ++ if (offset + length > mtd->size) { ++ DBG_MSG("erase area out of range of mtd.\n"); ++ return -EINVAL; ++ } ++ ++ if ((unsigned int)offset & (mtd->erasesize-1)) { ++ DBG_MSG("erase start address is not alignment.\n"); ++ return -EINVAL; ++ } ++ ++ if ((unsigned int)length & (mtd->erasesize-1)) { ++ DBG_MSG("erase length is not alignment.\n"); ++ return -EINVAL; ++ } ++ ++#ifdef CONFIG_CMD_SPI_BLOCK_PROTECTION ++ if (host->level) { ++ if ((BP_CMP_TOP == host->cmp) ++ && ((offset + length) > host->start_addr)) { ++ DBG_MSG("erase area offset[%#x => %#x] is locked," \ ++ " please unlock these blocks on u-boot.\n", ++ host->start_addr, (unsigned)(offset + length)); ++ return -EINVAL; ++ } ++ ++ if ((BP_CMP_BOTTOM == host->cmp) && (offset < host->end_addr)) { ++ unsigned end = ((offset + length) > host->end_addr) \ ++ ? host->end_addr : (offset + length); ++ ++ DBG_MSG("erase area offset[%#x => %#x] is locked," \ ++ " please unlock these blocks on u-boot.\n", ++ (unsigned)offset, end); ++ return -EINVAL; ++ } ++ } ++#endif /* CONFIG_CMD_SPI_BLOCK_PROTECTION */ ++ ++ mutex_lock(&host->lock); ++ while (length) { ++ if (spi->chipsize <= offset) { ++ offset -= spi->chipsize; ++ spi++; ++ if (!spi->name) ++ DBG_BUG("erase memory out of range.\n"); ++ } ++ ++ if (hisfc350_reg_erase_one_block(host, spi, offset)) { ++ instr->state = MTD_ERASE_FAILED; ++ mutex_unlock(&host->lock); ++ return -EIO; ++ } ++ ++ offset += spi->erase->size; ++ length -= spi->erase->size; ++ } ++ ++ instr->state = MTD_ERASE_DONE; ++ mutex_unlock(&host->lock); ++ mtd_erase_callback(instr); ++ return 0; ++} ++ ++#ifdef HISFCV350_SUPPORT_BUS_READ ++static int hisfc350_bus_read(struct mtd_info *mtd, loff_t from, size_t len, ++ size_t *retlen, u_char *buf) ++{ ++ int num; ++ int result = -EIO; ++ unsigned char *ptr = buf; ++ struct hisfc_host *host = MTD_TO_HOST(mtd); ++ struct hisfc_spi *spi = host->spi; ++ ++ if ((from + len) > mtd->size) { ++ DBG_MSG("read area out of range.\n"); ++ return -EINVAL; ++ } ++ ++ *retlen = 0; ++ if (!len) { ++ DBG_MSG("read length is 0.\n"); ++ return 0; ++ } ++ ++ mutex_lock(&host->lock); ++ ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ spi->driver->bus_prepare(spi, READ); ++ ++ while (len > 0) { ++ while (from >= spi->chipsize) { ++ from -= spi->chipsize; ++ spi++; ++ if (!spi->name) ++ DBG_BUG("read memory out of range.\n"); ++ ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ spi->driver->bus_prepare(spi, READ); ++ } ++ ++ num = ((from + len) >= spi->chipsize) ++ ? (spi->chipsize - from) : len; ++ ++ if (num) { ++ memcpy(ptr, (char *)spi->iobase + from, num); ++ from += num; ++ ptr += num; ++ len -= num; ++ } ++ } ++ *retlen = (size_t)(ptr - buf); ++ result = 0; ++fail: ++ mutex_unlock(&host->lock); ++ return result; ++} ++#endif /* HISFCV350_SUPPORT_BUS_READ */ ++ ++#ifdef HISFCV350_SUPPORT_BUS_WRITE ++static int hisfc350_bus_write(struct mtd_info *mtd, loff_t to, size_t len, ++ size_t *retlen, u_char *buf) ++{ ++ int num; ++ int result = -EIO; ++ unsigned char *ptr = buf; ++ struct hisfc_host *host = MTD_TO_HOST(mtd); ++ struct hisfc_spi *spi = host->spi; ++ ++ if ((to + len) > mtd->size) { ++ DBG_MSG("write data out of range.\n"); ++ return -EINVAL; ++ } ++ ++ *retlen = 0; ++ if (!len) { ++ DBG_MSG("write length is 0.\n"); ++ return 0; ++ } ++ ++#ifdef CONFIG_CMD_SPI_BLOCK_PROTECTION ++ if (host->level) { ++ if ((BP_CMP_TOP == host->cmp) ++ && ((to + len) > host->start_addr)) { ++ DBG_MSG("write area to[%#x => %#x] is locked, please " \ ++ "unlock these blocks on u-boot.\n", ++ host->start_addr, (to + len)); ++ return -EINVAL; ++ } ++ ++ if ((BP_CMP_BOTTOM == host->cmp) && (to < host->end_addr)) { ++ unsigned end = ((to + len) > host->end_addr) \ ++ ? host->end_addr : (to + len); ++ ++ DBG_MSG("write area to[%#x => %#x] is locked, please " \ ++ "unlock these blocks on u-boot.\n", to, end); ++ return -EINVAL; ++ } ++ } ++#endif /* CONFIG_CMD_SPI_BLOCK_PROTECTION */ ++ ++ mutex_lock(&host->lock); ++ ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ ++ spi->driver->bus_prepare(spi, WRITE); ++ ++ while (len > 0) { ++ while (to >= spi->chipsize) { ++ to -= spi->chipsize; ++ spi++; ++ if (!spi->name) ++ DBG_BUG("write spi space out of range.\n"); ++ ++ if (spi->driver->wait_ready(spi)) ++ goto fail; ++ spi->driver->bus_prepare(spi, WRITE); ++ } ++ ++ num = ((to + len) >= spi->chipsize) ++ ? (spi->chipsize - to) : len; ++ ++ if (num) { ++ memcpy((char *)spi->iobase + to, ptr, num); ++ ptr += num; ++ to += num; ++ len -= num; ++ } ++ } ++ ++ *retlen = (size_t)(ptr - buf); ++ result = 0; ++fail: ++ mutex_unlock(&host->lock); ++ return result; ++} ++#endif ++ ++static int hisfc350_map_chipsize(unsigned long long chipsize) ++{ ++ int shift = 0; ++ chipsize >>= (19 - 3); /* 19: 512K; 3: Bytes -> bit */ ++ ++ while (chipsize) { ++ chipsize >>= 1; ++ shift++; ++ } ++ return shift; ++} ++ ++#ifdef CONFIG_HISFC350_ENABLE_INTR_DMA ++static irqreturn_t hisfc_irq(int irq, void *dev_id) ++{ ++ struct hisfc_host *host = dev_id; ++ struct hisfc_spi *spi = host->spi; ++ u32 state = 0; ++ unsigned int tmp_reg = 0; ++ ++ state = hisfc_read(host, SFC_RINTSTS); ++ /* clear interrupt */ ++ tmp_reg = hisfc_read(host, SFC_INTCLR); ++ tmp_reg |= ALL_INT_CLR; ++ hisfc_write(host , SFC_INTCLR , tmp_reg); ++ ++ if (sfc_rw == READ) ++ memcpy(sfc_offset, host->buffer, sfc_num); ++ ++ sfc_ft += sfc_num; ++ sfc_offset += sfc_num; ++ sfc_length -= sfc_num; ++ ++ if (state & SFC_DMA_INT_STATUS) { ++ if (sfc_length > 0) { ++ while (sfc_ft >= spi->chipsize) { ++ sfc_ft -= spi->chipsize; ++ spi++; ++ if (sfc_rw == WRITE) ++ spi->driver->write_enable(spi); ++ spi->driver->bus_prepare(spi, sfc_rw); ++ } ++ if ((sfc_ft + sfc_length) >= spi->chipsize) { ++ sfc_num = spi->chipsize - sfc_ft; ++ if (sfc_num >= HISFC350_DMA_MAX_SIZE) ++ sfc_num = HISFC350_DMA_MAX_SIZE; ++ } else{ ++ sfc_num = sfc_length; ++ if (sfc_num >= HISFC350_DMA_MAX_SIZE) ++ sfc_num = HISFC350_DMA_MAX_SIZE; ++ } ++ if (sfc_rw == WRITE) ++ memcpy(host->buffer, sfc_offset, sfc_num); ++ hisfc350_dma_transfer(host, sfc_ft, ++ (unsigned char *)host->dma_buffer, sfc_rw, ++ sfc_num, spi->chipselect); ++ } else{ ++ if (sfc_rw == READ) ++ host->wait_fg = SFC_WAIT_FLAG_R; ++ else if (sfc_rw == WRITE) ++ host->wait_fg = SFC_WAIT_FLAG_W; ++ wake_up(&host->intr_wait); ++ } ++ } ++ return IRQ_HANDLED; ++} ++#endif ++ ++static int hisfc350_spi_probe(struct hisfc_host *host) ++{ ++ unsigned int regval = 0; ++ unsigned int total = 0; ++ unsigned char ids[8]; ++ struct spi_info *spiinfo; ++ struct hisfc_spi *spi = host->spi; ++ int chipselect = (CONFIG_HISFC350_CHIP_NUM - 1); ++ ++ host->num_chip = 0; ++ ++ for (; chipselect >= 0; chipselect--) { ++ ++ hisfc350_read_ids(host, chipselect, ids); ++ ++ /* can't find spi flash device. */ ++ if (!(ids[0] | ids[1] | ids[2]) ++ || ((ids[0] & ids[1] & ids[2]) == 0xFF)) ++ continue; ++ ++ printk(KERN_INFO "Spi(cs%d) ID: 0x%02X 0x%02X 0x%02X" ++ " 0x%02X 0x%02X 0x%02X\n", ++ chipselect, ++ ids[0], ids[1], ids[2], ids[3], ids[4], ids[5]); ++ ++ spiinfo = spi_serach_ids(ids); ++ ++ if (spiinfo) { ++ spi->name = spiinfo->name; ++ spi->chipselect = chipselect; ++ spi->chipsize = spiinfo->chipsize; ++ spi->erasesize = spiinfo->erasesize; ++ spi->addrcycle = spiinfo->addrcycle; ++ spi->driver = spiinfo->driver; ++ spi->host = host; ++ ++ spi_search_rw(spiinfo, spi->read, ++ HISFC350_SUPPORT_READ, ++ HISFC350_SUPPORT_MAX_DUMMY, READ); ++ hisfc350_map_iftype_and_clock(spi); ++ ++ spi->driver->qe_enable(spi); ++ ++ spi_search_rw(spiinfo, spi->read, ++ HISFC350_SUPPORT_READ, ++ HISFC350_SUPPORT_MAX_DUMMY, READ); ++ ++ spi_search_rw(spiinfo, spi->write, ++ HISFC350_SUPPORT_WRITE, ++ HISFC350_SUPPORT_MAX_DUMMY, WRITE); ++ ++ spi_get_erase(spiinfo, spi->erase); ++ hisfc350_map_iftype_and_clock(spi); ++ ++ regval = hisfc_read(host, HISFC350_BUS_FLASH_SIZE); ++ regval &= ~(HISFC350_BUS_FLASH_SIZE_CS0_MASK ++ << (chipselect << 3)); ++ regval |= (hisfc350_map_chipsize(spi->chipsize) ++ << (chipselect << 3)); ++ hisfc_write(host, HISFC350_BUS_FLASH_SIZE, regval); ++ ++ hisfc_write(host, ++ (HISFC350_BUS_BASE_ADDR_CS0 ++ + (chipselect << 2)), ++ (host->iobase + total)); ++ ++ spi->iobase = (char *)host->iobase + total; ++ ++ /* auto check sfc_addr_mode 3 bytes or 4 bytes */ ++ start_up_mode = GET_SFC_ADDR_MODE; ++ ++ if (start_up_mode == THREE_BYTE_ADDR_BOOT) { ++ printk(KERN_INFO "SPI nor flash boot mode is" \ ++ " 3 Bytes\n"); ++ spi->driver->entry_4addr(spi, TRUE); ++ } else ++ printk(KERN_INFO "SPI nor flash boot mode is" \ ++ " 4 Bytes\n"); ++ ++ printk(KERN_INFO "Spi(cs%d): ", spi->chipselect); ++ printk(KERN_INFO "Block:%sB", ultohstr(spi->erasesize)); ++ printk(KERN_INFO "Chip:%sB ", ultohstr(spi->chipsize)); ++ printk(KERN_INFO "Name:\"%s\"\n", spi->name); ++ ++#ifdef CONFIG_HISFC350_SHOW_CYCLE_TIMING ++ ++ printk(KERN_INFO "Spi(cs%d): ", spi->chipselect); ++ if (spi->addrcycle == SPI_4BYTE_ADDR_LEN) ++ printk(KERN_INFO "4 addrcycle "); ++ printk(KERN_INFO "read:%s,%02X,%s ", ++ hisfc350_get_ifcycle_str(spi->read->iftype), ++ spi->read->cmd, ++ hisfc350_get_clock_str(spi->read->clock)); ++ printk(KERN_INFO "write:%s,%02X,%s ", ++ hisfc350_get_ifcycle_str(spi->write->iftype), ++ spi->write->cmd, ++ hisfc350_get_clock_str(spi->write->clock)); ++ printk(KERN_INFO "erase:%s,%02X,%s\n", ++ hisfc350_get_ifcycle_str(spi->erase[0].iftype), ++ spi->erase[0].cmd, ++ hisfc350_get_clock_str(spi->erase[0].clock)); ++ ++#endif /* CONFIG_HISFC350_SHOW_CYCLE_TIMING */ ++ host->num_chip++; ++ total += spi->chipsize; ++ spi++; ++ } else ++ printk(KERN_ERR"Spi(cs%d): find unrecognized spi flash.\n", ++ chipselect); ++ } ++ ++ return host->num_chip; ++} ++ ++static void hisfc_probe_spi_size(struct hisfc_host *host) ++{ ++ int ix = 1; ++ struct mtd_info *mtd = host->mtd; ++ struct hisfc_spi *spi = host->spi; ++ ++ int total = spi->chipsize; ++ int erasesize = spi->erasesize; ++ ++ for (++spi; ix < host->num_chip; ix++, spi++) ++ total += spi->chipsize; ++ ++ mtd->size = total; ++ mtd->erasesize = erasesize; ++ ++ printk(KERN_INFO "spi size: %sB\n", ultohstr(mtd->size)); ++ printk(KERN_INFO "chip num: %x\n", host->num_chip); ++} ++ ++static int hisfc350_probe(struct hisfc_host *host) ++{ ++ struct device *dev = host->dev; ++ struct mtd_info *mtd = host->mtd; ++ struct device_node *np = NULL; ++ int ret = 0; ++ ++ np = of_get_next_available_child(dev->of_node, NULL); ++ ret = hisfc350_spi_probe(host); ++ if (!ret) ++ return -1; ++ ++ hisfc_probe_spi_size(host); ++ mtd->type = MTD_NORFLASH; ++ mtd->writesize = 1; ++ mtd->flags = MTD_CAP_NORFLASH; ++ mtd->owner = THIS_MODULE; ++ mtd->name = np->name; ++ ++ mtd->_erase = hisfc350_reg_erase; ++#ifdef HISFCV350_SUPPORT_REG_WRITE ++ mtd->_write = hisfc350_reg_write; ++#elif defined HISFCV350_SUPPORT_BUS_WRITE ++ mtd->_write = hisfc350_bus_write; ++#elif defined CONFIG_HISFC350_ENABLE_INTR_DMA ++ mtd->_write = hisfc350_dma_intr_write; ++#else ++ mtd->_write = hisfc350_dma_write; ++#endif ++#ifdef HISFCV350_SUPPORT_REG_READ ++ mtd->_read = hisfc350_reg_read; ++#elif defined HISFCV350_SUPPORT_BUS_READ ++ mtd->_read = hisfc350_bus_read; ++#elif defined CONFIG_HISFC350_ENABLE_INTR_DMA ++ mtd->_read = hisfc350_dma_intr_read; ++#else ++ mtd->_read = hisfc350_dma_read; ++#endif ++ return 0; ++} ++ ++static void hisfc350_spi_nor_init(struct hisfc_host *host) ++{ ++ clk_prepare_enable(host->clk); ++ ++ hisfc_write(host, HISFC350_TIMING, HISFC350_TIMING_TCSS(0x6) ++ | HISFC350_TIMING_TCSH(0x6) ++ | HISFC350_TIMING_TSHSL(0xf)); ++ ++} ++ ++static int hisfc350_spi_nor_probe(struct platform_device *pdev) ++{ ++ int result = -EIO; ++ struct hisfc_host *host; ++ struct mtd_info *mtd = NULL; ++ struct device *dev = &pdev->dev; ++ struct resource *res; ++#ifdef CONFIG_HISFC350_ENABLE_INTR_DMA ++ int irq; ++ unsigned int tmp_reg = 0; ++#endif ++ ++ host = devm_kmalloc(dev, sizeof(struct hisfc_host), GFP_KERNEL); ++ if (!host) ++ return -ENOMEM; ++ memset(host, 0, sizeof(struct hisfc_host)); ++ ++ platform_set_drvdata(pdev, host); ++ host->dev = dev; ++ ++ host->sysreg = ioremap_nocache(CONFIG_HISFC350_SYSCTRL_ADDRESS, ++ HISFC350_SYSCTRL_LENGTH); ++ if (!host->sysreg) { ++ printk(KERN_ERR "spi system reg ioremap failed.\n"); ++ result = -EFAULT; ++ goto fail; ++ } ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control"); ++ host->regbase = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(host->regbase)) ++ return PTR_ERR(host->regbase); ++ ++ host->set_system_clock = hisfc350_set_system_clock; ++ host->set_host_addr_mode = hisfc350_set_host_addr_mode; ++ ++#ifdef HISFCV350_SUPPORT_BUS_READ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory"); ++ host->iobase = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(hostt->iobase)) ++ return PTR_ERR(fmc->iobase); ++#endif ++ ++ host->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(host->clk)) ++ return PTR_ERR(host->clk); ++ ++ result = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); ++ if (result) { ++ dev_warn(dev, "Unable to set dma mask\n"); ++ goto fail; ++ } ++ ++ host->buffer = dma_alloc_coherent(host->dev, HISFC350_DMA_MAX_SIZE, ++ &host->dma_buffer, GFP_KERNEL); ++ if (host->buffer == NULL) { ++ printk(KERN_ERR "spi alloc dma buffer failed.\n"); ++ result = -ENOMEM; ++ goto fail; ++ } ++ ++ mutex_init(&host->lock); ++ hisfc350_spi_nor_init(host); ++ ++ mtd = host->mtd; ++ if (hisfc350_probe(host)) { ++ result = -ENODEV; ++ goto fail; ++ } ++ ++ result = mtd_device_register(mtd, NULL, 0); ++ if (result) ++ goto fail; ++ ++#ifdef CONFIG_CMD_SPI_BLOCK_PROTECTION ++ hisfc350_spi_lock_init(host); ++#endif ++ ++#ifdef CONFIG_HISFC350_ENABLE_INTR_DMA ++ host->wait_fg = 0; ++ init_waitqueue_head(&host->intr_wait); ++ ++ /* clear SFC intr */ ++ tmp_reg |= ALL_INT_CLR; ++ hisfc_write(host , SFC_INTCLR , tmp_reg); ++ /* MASK SFC host intr */ ++ tmp_reg = hisfc_read(host , SFC_INTMASK); ++ tmp_reg |= SFC_DMA_INT_MASK; ++ tmp_reg &= ~SFC_CMD_INT_MASK; ++ hisfc_write(host , SFC_INTMASK , tmp_reg); ++ ++ irq = platform_get_irq(pdev, 0); ++ if (unlikely(irq < 0)) ++ goto fail; ++ result = request_irq(irq, hisfc_irq, IRQF_SHARED, "hisfc", host); ++ if (result) { ++ printk(KERN_ERR "request_irq error!\n"); ++ goto fail; ++ } ++#endif ++ return result; ++ ++fail: ++ if (host->buffer) ++ dma_free_coherent(host->dev, HISFC350_DMA_MAX_SIZE, ++ host->buffer, host->dma_buffer); ++ if (host->sysreg) ++ iounmap(host->sysreg); ++ mutex_destroy(&host->lock); ++ clk_disable_unprepare(host->clk); ++ if (mtd) ++ mtd_device_unregister(mtd); ++ platform_set_drvdata(pdev, NULL); ++ return result; ++} ++ ++static int hisfc350_spi_nor_remove(struct platform_device *pdev) ++{ ++ struct hisfc_host *host = platform_get_drvdata(pdev); ++#ifdef CONFIG_HISFC350_ENABLE_INTR_DMA ++ int irq = SFC_IRQ_NUM; ++ free_irq(irq, host); ++#endif ++ ++ mtd_device_unregister(host->mtd); ++ ++ if (host->buffer) ++ dma_free_coherent(host->dev, HISFC350_DMA_MAX_SIZE, ++ host->buffer, host->dma_buffer); ++ if (host->sysreg) ++ iounmap(host->sysreg); ++ ++ mutex_destroy(&host->lock); ++ clk_disable_unprepare(host->clk); ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_CMD_SPI_BLOCK_PROTECTION ++void hisfc350_spi_lock_init(struct hisfc_host *host) ++{ ++ unsigned char cmp, level, status, config; ++ unsigned int lock_len = 0; ++ struct hisfc_spi *spi = host->spi; ++ ++ spi->driver->wait_ready(spi); ++ ++ status = spi_general_get_flash_register(spi, SPI_CMD_RDSR); ++ level = (status & SPI_NOR_SR_BP_MASK) >> SPI_NOR_SR_BP0_SHIFT; ++ ++ config = spi_general_get_flash_register(spi, SPI_CMD_RDCR); ++ cmp = (config & SPI_NOR_SR_TB_MASK) >> SPI_NOR_SR_TB_SHIFT; ++ ++ host->start_addr = 0; ++ host->end_addr = spi->chipsize; ++ ++ if (level) { ++ lock_len = spi->erasesize << (level - 1); ++ if (lock_len > spi->chipsize) ++ lock_len = spi->chipsize; ++ ++ if (BP_CMP_BOTTOM == cmp) ++ host->end_addr = lock_len; ++ else if (BP_CMP_TOP == cmp) ++ host->start_addr = spi->chipsize - lock_len; ++ ++ printk(KERN_INFO "Spi is locked. lock address[%#x => %#x]\n", ++ host->start_addr, host->end_addr); ++ } else { ++ if (BP_CMP_BOTTOM == cmp) ++ host->end_addr = 0; ++ else if (BP_CMP_TOP == cmp) ++ host->start_addr = spi->chipsize; ++ } ++ ++ host->cmp = cmp; ++ host->level = level; ++} ++#endif /* CONFIG_CMD_SPI_BLOCK_PROTECTION */ ++ ++#ifdef CONFIG_PM ++ ++static int hisfc350_driver_suspend(struct platform_device *dev, ++ pm_message_t state) ++{ ++ return 0; ++} ++static int hisfc350_driver_resume(struct platform_device *dev) ++{ ++ return 0; ++} ++ ++#endif ++ ++static const struct of_device_id hisi_spi_nor_dt_ids[] = { ++ { .compatible = "hisilicon,hisi-spi-nor"}, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, hisi_spi_nor_dt_ids); ++ ++static struct platform_driver hisi_spi_nor_driver = { ++ .driver = { ++ .name = "hisilicon,hisfc350", ++ .of_match_table = hisi_spi_nor_dt_ids, ++ }, ++ .probe = hisfc350_spi_nor_probe, ++ .remove = hisfc350_spi_nor_remove, ++ .shutdown = hisfc350_spi_nor_shutdown, ++#ifdef CONFIG_PM ++ .suspend = hisfc350_driver_suspend, ++ .resume = hisfc350_driver_resume, ++#endif ++}; ++module_platform_driver(hisi_spi_nor_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("Hisfc350 Device Driver, Version 1.00"); +diff --git a/drivers/mtd/spi-nor/hisfc350/hisfc350.h b/drivers/mtd/spi-nor/hisfc350/hisfc350.h +new file mode 100644 +index 0000000..92ad588 +--- /dev/null ++++ b/drivers/mtd/spi-nor/hisfc350/hisfc350.h +@@ -0,0 +1,325 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef HISFC350H ++#define HISFC350H ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/*****************************************************************************/ ++#ifndef CONFIG_HISFC350_CHIP_NUM ++#define CONFIG_HISFC350_CHIP_NUM (2) ++# warning NOT config CONFIG_HISFC350_CHIP_NUM,\ ++ used default value, maybe invalid. ++#endif /* CONFIG_HISFC350_CHIP_NUM */ ++ ++#define HISFC350_SYSCTRL_LENGTH (0x100) ++/*****************************************************************************/ ++#define HISFC350_MAX_READY_WAIT_JIFFIES (40 * HZ) ++ ++/*****************************************************************************/ ++#define HISFC350_REG_BASE_LEN (0x500) ++#define HISFC350_DMA_ALIGN_SIZE (256) ++#define HISFC350_DMA_ALIGN_MASK (HISFC350_DMA_ALIGN_SIZE-1) ++#define HISFC350_DMA_MAX_SIZE (4096) ++#define HISFC350_DMA_MAX_MASK (HISFC350_DMA_MAX_SIZE-1) ++#define HISFC350_BUFFER_BASE_LEN (0x4000000) /* 64MB */ ++ ++/*****************************************************************************/ ++ ++/* These macroes are for debug only,reg read is slower then dma read */ ++#undef HISFCV350_SUPPORT_REG_READ ++/* #define HISFCV350_SUPPORT_REG_READ */ ++#undef HISFCV350_SUPPORT_REG_WRITE ++/* #define HISFCV350_SUPPORT_REG_WRITE */ ++#undef HISFCV350_SUPPORT_BUS_READ ++/* #define HISFCV350_SUPPORT_BUS_READ */ ++#undef HISFCV350_SUPPORT_BUS_WRITE ++/* #define HISFCV350_SUPPORT_BUS_WRITE */ ++ ++#ifdef CONFIG_HISFC350_ENABLE_INTR_DMA ++#define SFC_IRQ_NUM 49 ++#define SFC_WAIT_FLAG_R 1 ++#define SFC_WAIT_FLAG_W 2 ++#define SFC_INTMASK 0x128 ++#define SFC_MINTSTS 0x124 ++#define SFC_RINTSTS 0x120 ++#define SFC_INTCLR 0x12c ++#define SFC_DMA_INT_STATUS (1<<1) ++#define SFC_CMD_INT_STATUS (1<<0) ++#define SFC_DMA_INT_MASK (1<<1) ++#define SFC_CMD_INT_MASK (1<<0) ++#define ALL_INT_CLR 0x2 ++#endif ++ ++#define HISFC350_GLOBAL_CONFIG 0x0100 ++#define HISFC350_GLOBAL_CONFIG_READ_DELAY(_n) (((_n) & 0x03) << 3) ++#define HISFC350_GLOBAL_CONFIG_ADDR_MODE_4B (1 << 2) ++#define HISFC350_GLOBAL_CONFIG_ADDR_MODE_DIS_4B (0 << 2) ++#define HISFC350_GLOBAL_CONFIG_WRITE_PROTECT (1 << 1) ++#define HISFC350_GLOBAL_CONFIG_SPI_MODE3 (1 << 0) ++ ++#define HISFC350_TIMING 0x0110 ++#define HISFC350_TIMING_TSHSL(_n) ((_n) & 0xF) ++#define HISFC350_TIMING_TCSS(_n) (((_n) & 0x7) << 8) ++#define HISFC350_TIMING_TCSH(_n) (((_n) & 0x7) << 12) ++ ++#define HISFC350_INT_RAW_STATUS 0x0120 ++#define HISFC350_INT_RAW_STATUS_DMA_DONE (1<<1) ++#define HISFC350_INT_STATUS 0x0124 ++#define HISFC350_INT_MASK 0x0128 ++#define HISFC350_INT_CLEAR 0x012C ++#define HISFC350_INT_CLEAR_DMA_DONE (1<<1) ++ ++#define HISFC350_BUS_CONFIG1 0x0200 ++#define HISFC350_BUS_CONFIG1_READ_EN (1<<31) ++#define HISFC350_BUS_CONFIG1_WRITE_EN (1<<30) ++#define HISFC350_BUS_CONFIG1_WRITE_INS(_n) ((_n & 0xFF) << 22) ++#define HISFC350_BUS_CONFIG1_WRITE_DUMMY_CNT(_n) ((_n & 0x7) << 19) ++#define HISFC350_BUS_CONFIG1_WRITE_IF_TYPE(_n) ((_n & 0x7) << 16) ++#define HISFC350_BUS_CONFIG1_READ_INS(_n) ((_n & 0xFF) << 8) ++#define HISFC350_BUS_CONFIG1_READ_PREF_CNT(_n) ((_n & 0x3) << 6) ++#define HISFC350_BUS_CONFIG1_READ_DUMMY_CNT(_n) ((_n & 0x7) << 3) ++#define HISFC350_BUS_CONFIG1_READ_IF_TYPE(_n) (_n & 0x7) ++ ++#define HISFC350_BUS_CONFIG2 0x0204 ++#define HISFC350_BUS_CONFIG2_WIP_LOCATE(_n) (_n & 0x7) ++ ++#define HISFC350_BUS_FLASH_SIZE 0x0210 ++#define HISFC350_BUS_FLASH_SIZE_CS0_MASK 0x0F ++#define HISFC350_BUS_FLASH_SIZE_CS1_MASK (0x0F << 8) ++#define HISFC350_BUS_BASE_ADDR_CS0 0x0214 ++#define HISFC350_BUS_BASE_ADDR_CS1 0x0218 ++#define HISFC350_BUS_ALIAS_ADDR 0x021C ++#define HISFC350_BUS_ALIAS_CS 0x0220 ++#define HISFC350_BUS_DMA_CTRL 0x0240 ++#define HISFC350_BUS_DMA_CTRL_START (1 << 0) ++#define HISFC350_BUS_DMA_CTRL_RW(_rw) ((_rw)<<1) ++#define HISFC350_BUS_DMA_CTRL_CS(_cs) (((_cs) & 0x01) << 4) ++ ++#define HISFC350_BUS_DMA_MEM_SADDR 0x0244 ++#define HISFC350_BUS_DMA_FLASH_SADDR 0x0248 ++#define HISFC350_BUS_DMA_LEN 0x024C ++#define HISFC350_BUS_DMA_LEN_DATA_CNT(_n) ((_n - 1) & 0x0FFFFFFF) ++#define HISFC350_BUS_DMA_AHB_CTRL 0x0250 ++#define HISFC350_BUS_DMA_AHB_CTRL_INCR4_EN (1<<0) ++#define HISFC350_BUS_DMA_AHB_CTRL_INCR8_EN (1<<1) ++#define HISFC350_BUS_DMA_AHB_CTRL_INCR16_EN (1<<2) ++ ++#define HISFC350_CMD_CONFIG 0x0300 ++#define HISFC350_CMD_CONFIG_MEM_IF_TYPE(_n) (((_n) & 0x07) << 17) ++#define HISFC350_CMD_CONFIG_DATA_CNT(_n) (((_n-1) & 0x3F) << 9) ++#define HISFC350_CMD_CONFIG_RW_READ (1<<8) ++#define HISFC350_CMD_CONFIG_DATA_EN (1<<7) ++#define HISFC350_CMD_CONFIG_DUMMY_CNT(_n) (((_n) & 0x07) << 4) ++#define HISFC350_CMD_CONFIG_ADDR_EN (1<<3) ++#define HISFC350_CMD_CONFIG_SEL_CS(_cs) (((_cs) & 0x01) << 1) ++#define HISFC350_CMD_CONFIG_START (1<<0) ++ ++#define HISFC350_CMD_INS 0x0308 ++#define HISFC350_CMD_ADDR 0x030C ++#define HISFC350_CMD_ADDR_MASK 0x3FFFFFFF ++#define HISFC350_CMD_DATABUF0 0x0400 ++#define HISFC350_CMD_DATABUF15 0x043C ++ ++#define HISFC350_IFCYCLE_STD 0 ++#define HISFC350_IFCYCLE_DUAL 1 ++#define HISFC350_IFCYCLE_DUAL_ADDR 2 ++#define HISFC350_IFCYCLE_DUAL_CMD 3 ++#define HISFC350_IFCYCLE_QUAD 5 ++#define HISFC350_IFCYCLE_QUAD_ADDR 6 ++#define HISFC350_IFCYCLE_QUAD_CMD 7 ++ ++#define HISFC350_REG_BUF_SIZE \ ++ (HISFC350_CMD_DATABUF15 - HISFC350_CMD_DATABUF0 + 0x04) ++#define HISFC350_REG_BUF_MASK (HISFC350_REG_BUF_SIZE - 1) ++ ++#undef READ ++#define READ 1 ++ ++#undef WRITE ++#define WRITE 0 ++ ++#undef FALSE ++#define FALSE 0 ++ ++#undef TRUE ++#define TRUE 1 ++ ++#define SPI_NOR_SR_LEN 1 /* Status Register length(byte) */ ++#define SPI_NOR_CR_LEN 1 /* Config Register length(byte) */ ++ ++#define SPI_NOR_CR_SHIFT 8 /* Config Register shift(bit) */ ++ ++#define SPI_NOR_CR_QE_SHIFT 1 ++#define SPI_NOR_CR_QE_MASK (1 << SPI_NOR_CR_QE_SHIFT) ++ ++#ifdef CONFIG_CMD_SPI_BLOCK_PROTECTION ++#define DEBUG_SPI_NOR_BP 0 ++ ++#define SPI_NOR_SR_SRWD_SHIFT 7 ++#define SPI_NOR_SR_SRWD_MASK (1 << SPI_NOR_SR_SRWD_SHIFT) ++ ++#define SPI_NOR_SR_BP0_SHIFT 2 ++#define SPI_NOR_SR_BP_WIDTH 0xf ++#define SPI_NOR_SR_BP_MASK (SPI_NOR_SR_BP_WIDTH << SPI_NOR_SR_BP0_SHIFT) ++ ++#define SPI_NOR_SR_TB_SHIFT 3 ++#define SPI_NOR_SR_TB_MASK (1 << SPI_NOR_SR_TB_SHIFT) ++ ++#define SPI_NOR_SR_WIP_MASK (1 << 0) ++ ++#define BP_OP_SET 0 ++#define BP_OP_GET 1 ++ ++#define BP_CMP_TOP 0 ++#define BP_CMP_BOTTOM 1 ++ ++enum block_protection_level { ++ BP_LEVEL_0 = 0, ++ BP_LEVEL_1 = 1, ++ BP_LEVEL_2 = 2, ++ BP_LEVEL_3 = 3, ++ BP_LEVEL_4 = 4, ++ BP_LEVEL_5 = 5, ++ BP_LEVEL_6 = 6, ++ BP_LEVEL_7 = 7, ++ BP_LEVEL_8 = 8, ++ BP_LEVEL_9 = 9, ++ BP_LEVEL_10 = 10, ++ BP_LEVEL_END, ++}; ++ ++#define BP_LEVEL_MAX (BP_LEVEL_END - 1) ++#endif /* CONFIG_CMD_SPI_BLOCK_PROTECTION */ ++ ++/*****************************************************************************/ ++struct hisfc_spi; ++ ++struct spi_driver { ++ int (*wait_ready)(struct hisfc_spi *spi); ++ int (*write_enable)(struct hisfc_spi *spi); ++ int (*entry_4addr)(struct hisfc_spi *spi, int enable); ++ int (*bus_prepare)(struct hisfc_spi *spi, int op); ++ int (*qe_enable)(struct hisfc_spi *spi); ++}; ++ ++struct hisfc_spi { ++ char *name; ++ int chipselect; ++ unsigned long long chipsize; ++ unsigned int erasesize; ++ void __iomem *iobase; ++ ++ unsigned int addrcycle; ++ struct spi_operation read[1]; ++ struct spi_operation write[1]; ++ struct spi_operation erase[MAX_SPI_OP]; ++ void *host; ++ struct spi_driver *driver; ++}; ++ ++struct hisfc_host { ++ struct mtd_info mtd[1]; ++ void __iomem *iobase; ++ void __iomem *regbase; ++ struct device *dev; ++ struct mutex lock; ++ void __iomem *sysreg; ++ struct clk *clk; ++#ifdef CONFIG_HISFC350_ENABLE_INTR_DMA ++ wait_queue_head_t intr_wait; ++ unsigned int wait_fg; ++#endif ++ void (*set_system_clock)(struct hisfc_host *host, ++ struct spi_operation *op, int clk_en); ++ ++ void (*set_host_addr_mode)(struct hisfc_host *host, int enable); ++ char *buffer; ++ unsigned int dma_buffer; ++ int add_partition; ++ int num_chip; ++ struct hisfc_spi spi[CONFIG_HISFC350_CHIP_NUM+1]; ++ char reg_buffer[HISFC350_REG_BUF_SIZE]; ++ ++ int (*suspend)(struct platform_device *pltdev, pm_message_t state); ++ int (*resume)(struct platform_device *pltdev); ++#ifdef CONFIG_CMD_SPI_BLOCK_PROTECTION ++ unsigned int start_addr; ++ unsigned int end_addr; ++ unsigned char cmp; ++ unsigned char level; ++#endif ++}; ++ ++#ifdef CONFIG_CMD_SPI_BLOCK_PROTECTION ++void hisfc350_spi_lock_init(struct hisfc_host *host); ++extern u_char spi_general_get_flash_register(struct hisfc_spi *spi, u_char cmd); ++#endif ++ ++#define MTD_TO_HOST(_mtd) ((struct hisfc_host *)(_mtd)) ++/*****************************************************************************/ ++#define hisfc_read(_host, _reg) \ ++ readl(_host->regbase + (_reg)) ++ ++#define hisfc_write(_host, _reg, _value) \ ++ writel((_value), _host->regbase + (_reg)) ++ ++#define HISFC350_CMD_WAIT_CPU_FINISH(_host) do {\ ++ unsigned int timeout = 0x10000000; \ ++ while (((hisfc_read((_host), HISFC350_CMD_CONFIG) \ ++ & HISFC350_CMD_CONFIG_START)) && timeout) \ ++ --timeout; \ ++ if (!timeout) \ ++ DBG_BUG("cmd wait cpu finish timeout\n"); \ ++} while (0) ++ ++#define HISFC350_DMA_WAIT_CPU_FINISH(_host) do {\ ++ unsigned int timeout = 0x10000000; \ ++ while (((hisfc_read((_host), HISFC350_BUS_DMA_CTRL) \ ++ & HISFC350_BUS_DMA_CTRL_START)) && timeout) { \ ++ --timeout; cond_resched(); } \ ++ if (!timeout) \ ++ DBG_BUG("dma wait cpu finish timeout\n"); \ ++} while (0) ++ ++/*****************************************************************************/ ++#if 0 ++# define DBG_MSG(_fmt, arg...) ++#else ++# define DBG_MSG(_fmt, arg...) \ ++ printk(KERN_INFO "%s(%d): " _fmt, __FILE__, __LINE__, ##arg); ++#endif ++ ++#define DBG_WARN(_fmt, arg...) \ ++ printk(KERN_INFO "%s(%d): " _fmt, __FILE__, __LINE__, ##arg); ++ ++#define DBG_BUG(fmt, args...) do { \ ++ printk(KERN_ERR "%s(%d): BUG: " fmt, __FILE__, __LINE__, ##args); \ ++ asm("b ."); \ ++} while (0) ++/*****************************************************************************/ ++#ifndef NULL ++# define NULL (void *)0 ++#endif ++/*****************************************************************************/ ++#endif /* HISFC350H */ +diff --git a/drivers/mtd/spi-nor/hisfc350/hisfc350_hi3516a.c b/drivers/mtd/spi-nor/hisfc350/hisfc350_hi3516a.c +new file mode 100644 +index 0000000..c2847a1 +--- /dev/null ++++ b/drivers/mtd/spi-nor/hisfc350/hisfc350_hi3516a.c +@@ -0,0 +1,102 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include "../spi_ids.h" ++#include "hisfc350.h" ++ ++#define HISFC350_CRG48 (0x00C0) ++#define HISFC350_CRG48_RST (1 << 0) ++#define HISFC350_CRG48_CLKEN (1 << 1) ++#define HISFC350_CRG48_CLK_24M (0 << 2) ++#define HISFC350_CRG48_CLK_75M ((0 << 3) | (1 << 2)) ++#define HISFC350_CRG48_CLK_125M ((1 << 2) | (1 << 3)) ++#define SYS_CTRL_BASE (0x20050000) ++#define SFC_ADDR_MODE_REG (0x8C) ++#define SFC_ADDR_MODE_MASK (0x80) ++#define SFC_CLSEL_MASK (0xC) ++#define SFC_PERI_CLKDIV1_SHIFT (28) ++#define SFC_PERI_CLKDIV1_MASK (0xF) ++/*****************************************************************************/ ++#define GET_SFC_ADDR_MODE ({\ ++ int start_up_mode = 0;\ ++ start_up_mode = readl((void *)IO_ADDRESS(SYS_CTRL_BASE + SFC_ADDR_MODE_REG));\ ++ start_up_mode &= SFC_ADDR_MODE_MASK;\ ++ start_up_mode; }) ++/*****************************************************************************/ ++void hisfc350_set_system_clock(struct hisfc_host *host, ++ struct spi_operation *op, int clk_en) ++{ ++ unsigned int regval = readl(host->sysreg + HISFC350_CRG48); ++ ++ regval = regval & (~SFC_CLSEL_MASK); ++ ++ if (op && op->clock) { ++ regval &= ~SFC_CLSEL_MASK; ++ regval |= op->clock & SFC_CLSEL_MASK; ++ } else { ++ regval &= ~SFC_CLSEL_MASK; ++ regval |= HISFC350_CRG48_CLK_24M; /* Default Clock */ ++ } ++ ++ if (clk_en) ++ regval |= HISFC350_CRG48_CLKEN; ++ ++ if (regval != readl(host->sysreg + HISFC350_CRG48)) ++ writel(regval, (host->sysreg + HISFC350_CRG48)); ++} ++ ++/*****************************************************************************/ ++void hisfc350_get_best_clock(unsigned int *clock) ++{ ++ int ix; ++ int clk_reg; ++ ++#define CLK_2X(_clk) (((_clk) + 1) >> 1) ++ unsigned int sysclk[] = { ++ CLK_2X(24), HISFC350_CRG48_CLK_24M, ++ CLK_2X(75), HISFC350_CRG48_CLK_75M, ++ CLK_2X(125), HISFC350_CRG48_CLK_125M, ++ 0, 0, ++ }; ++#undef CLK_2X ++ ++ clk_reg = HISFC350_CRG48_CLK_24M; ++ for (ix = 0; sysclk[ix]; ix += 2) { ++ if (*clock < sysclk[ix]) ++ break; ++ clk_reg = sysclk[ix + 1]; ++ } ++ ++ *clock = clk_reg; ++} ++ ++/*****************************************************************************/ ++#ifdef CONFIG_HISFC350_SHOW_CYCLE_TIMING ++char *hisfc350_get_clock_str(unsigned int clk_reg) ++{ ++ static char buffer[40]; ++ ++ /* calculate reference PERI_CLKDIV1[31:28] */ ++ clk_reg = 216 / ((clk_reg >> SFC_PERI_CLKDIV1_SHIFT) ++ & SFC_PERI_CLKDIV1_MASK); ++ sprintf(buffer, "%dM", clk_reg); ++ ++ return buffer; ++} ++#endif /* CONFIG_HISFC350_SHOW_CYCLE_TIMING */ +diff --git a/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_en25q64.c b/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_en25q64.c +new file mode 100644 +index 0000000..0db4bc8 +--- /dev/null ++++ b/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_en25q64.c +@@ -0,0 +1,29 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include "../spi_ids.h" ++#include "hisfc350.h" ++ ++static int spi_en25q64_qe_enable(struct hisfc_spi *spi) ++{ ++ return 0; ++} +diff --git a/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_gd25qxxx.c b/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_gd25qxxx.c +new file mode 100644 +index 0000000..65b5a0d +--- /dev/null ++++ b/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_gd25qxxx.c +@@ -0,0 +1,110 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++ ++#include "../spi_ids.h" ++#include "hisfc350.h" ++ ++#define SPI_BRWR 0x17 ++#define SPI_EN4B 0x80 ++#define SPI_EX4B 0x00 ++ ++#define GD_SPI_CMD_SR_QE (0x2) ++#define GD_SPI_CMD_SR_DISQE (0x0) ++#define SPI_CMD_WRSR1 (0x1) ++ ++static int spi_gd25qxxx_qe_enable(struct hisfc_spi *spi) ++{ ++ struct hisfc_host *host = (struct hisfc_host *)spi->host; ++ unsigned int regval = 0; ++ unsigned int qe_op1 = 0; ++ unsigned int qe_op2 = 0; ++ ++ if (hisfc350_is_quad(spi)) { ++ qe_op1 = SPI_CMD_SR_QE; ++ qe_op2 = GD_SPI_CMD_SR_QE; ++ } else { ++ qe_op1 = SPI_CMD_SR_XQE; ++ qe_op2 = GD_SPI_CMD_SR_DISQE; ++ } ++ ++ spi->driver->write_enable(spi); ++ ++ /* First, we enable QE(4bit r&w) for 16pin gd flash */ ++ hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_WRSR1); ++ hisfc_write(host, HISFC350_CMD_DATABUF0, qe_op1); ++ ++ hisfc_write(host, HISFC350_CMD_CONFIG, ++ HISFC350_CMD_CONFIG_MEM_IF_TYPE(spi-> ++ write->iftype) ++ | HISFC350_CMD_CONFIG_DATA_CNT(2) ++ | HISFC350_CMD_CONFIG_DATA_EN ++ | HISFC350_CMD_CONFIG_DUMMY_CNT(spi-> ++ write->dummy) ++ | HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect) ++ | HISFC350_CMD_CONFIG_START); ++ ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++ ++ spi->driver->wait_ready(spi); ++ ++ /* Second, we enable QE for 8 pin gd flash. This will not affect ++ 16pin gd spi, if the QE bit has been set 1. ++ */ ++ spi->driver->write_enable(spi); ++ ++ hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_WRSR2); ++ hisfc_write(host, HISFC350_CMD_DATABUF0, qe_op2); ++ ++ hisfc_write(host, HISFC350_CMD_CONFIG, ++ HISFC350_CMD_CONFIG_MEM_IF_TYPE(spi-> ++ write->iftype) ++ | HISFC350_CMD_CONFIG_DATA_CNT(1) ++ | HISFC350_CMD_CONFIG_DATA_EN ++ | HISFC350_CMD_CONFIG_DUMMY_CNT(spi-> ++ write->dummy) ++ | HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect) ++ | HISFC350_CMD_CONFIG_START); ++ ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++ ++ spi->driver->wait_ready(spi); ++ ++ if (DEBUG_SPI) { ++ hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_RDSR2); ++ ++ hisfc_write(host, HISFC350_CMD_CONFIG, ++ HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect) ++ | HISFC350_CMD_CONFIG_DATA_CNT(1) ++ | HISFC350_CMD_CONFIG_DATA_EN ++ | HISFC350_CMD_CONFIG_RW_READ ++ | HISFC350_CMD_CONFIG_START); ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++ regval = hisfc_read(host, HISFC350_CMD_DATABUF0); ++ printk(KERN_INFO "QEbit = 0x2? : 0x%x\n", regval); ++ if ((regval & GD_SPI_CMD_SR_QE)) ++ printk(KERN_INFO "QE bit enable success\n"); ++ else ++ printk(KERN_INFO "QE bit enable failed\n"); ++ } ++ return 0; ++} ++ +diff --git a/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_general.c b/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_general.c +new file mode 100644 +index 0000000..8ad3545 +--- /dev/null ++++ b/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_general.c +@@ -0,0 +1,266 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "../spi_ids.h" ++#include "hisfc350.h" ++ ++#define DEBUG_SPI 0 ++#define DEBUG_GET_SR 0 ++#define DEBUG_SPI_QE 0 ++ ++/*****************************************************************************/ ++u_char spi_general_get_flash_register(struct hisfc_spi *spi, u_char cmd) ++{ ++ unsigned char status; ++ unsigned int regval; ++ struct hisfc_host *host = (struct hisfc_host *)spi->host; ++ ++ if (DEBUG_GET_SR) ++ printk(KERN_INFO "* Start get flash Register %#x.\n", cmd); ++ ++ hisfc_write(host, HISFC350_CMD_INS, cmd); ++ if (DEBUG_GET_SR) ++ printk(KERN_INFO " Set INS[%#x]%#x\n", HISFC350_CMD_INS, cmd); ++ ++ regval = HISFC350_CMD_CONFIG_DATA_CNT(SPI_NOR_SR_LEN) ++ | HISFC350_CMD_CONFIG_RW_READ ++ | HISFC350_CMD_CONFIG_DATA_EN ++ | HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect) ++ | HISFC350_CMD_CONFIG_START; ++ ++ hisfc_write(host, HISFC350_CMD_CONFIG, regval); ++ if (DEBUG_GET_SR) ++ printk(KERN_INFO " Set CONFIG[%#x]%#x\n", HISFC350_CMD_CONFIG, ++ regval); ++ ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++ ++ status = hisfc_read(host, HISFC350_CMD_DATABUF0); ++ if (DEBUG_GET_SR) ++ printk(KERN_INFO "* Get flash Register %#x, val[%#x]\n", cmd, ++ status); ++ ++ return status; ++} ++ ++/*****************************************************************************/ ++static int spi_general_wait_ready(struct hisfc_spi *spi) ++{ ++ unsigned long status; ++ unsigned long deadline = jiffies + HISFC350_MAX_READY_WAIT_JIFFIES; ++ ++ do { ++ status = spi_general_get_flash_register(spi, SPI_CMD_RDSR); ++ if (!(status & SPI_CMD_SR_WIP)) ++ return 0; ++ ++ cond_resched(); ++ ++ } while (!time_after_eq(jiffies, deadline)); ++ ++ printk(KERN_ERR "Wait spi flash ready timeout.\n"); ++ ++ return 1; ++} ++ ++/*****************************************************************************/ ++static int spi_general_write_enable(struct hisfc_spi *spi) ++{ ++ struct hisfc_host *host = (struct hisfc_host *)spi->host; ++ ++ spi->driver->wait_ready(spi); ++ ++ hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_WREN); ++ ++ hisfc_write(host, HISFC350_CMD_CONFIG, ++ HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect) ++ | HISFC350_CMD_CONFIG_START); ++ ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++/* ++ enable 4byte adress for SPI which memory more than 16M ++*/ ++static int spi_general_entry_4addr(struct hisfc_spi *spi, int enable) ++{ ++ struct hisfc_host *host = (struct hisfc_host *)spi->host; ++ ++ spi->driver->wait_ready(spi); ++ ++ if (spi->addrcycle != SPI_4BYTE_ADDR_LEN) ++ return 0; ++ ++ if (enable) ++ hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_EN4B); ++ else ++ hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_EX4B); ++ ++ hisfc_write(host, HISFC350_CMD_CONFIG, ++ HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect) ++ | HISFC350_CMD_CONFIG_START); ++ ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++ ++ host->set_host_addr_mode(host, enable); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++/* ++ configure prepared for dma or bus read or write mode ++*/ ++static int spi_general_bus_prepare(struct hisfc_spi *spi, int op) ++{ ++ unsigned int regval = 0; ++ struct hisfc_host *host = (struct hisfc_host *)spi->host; ++ ++#ifdef HISFCV350_SUPPORT_BUS_WRITE ++ regval |= HISFC350_BUS_CONFIG1_WRITE_EN; ++#endif ++ regval |= HISFC350_BUS_CONFIG1_WRITE_INS(spi->write->cmd); ++ regval |= HISFC350_BUS_CONFIG1_WRITE_DUMMY_CNT(spi->write->dummy); ++ regval |= HISFC350_BUS_CONFIG1_WRITE_IF_TYPE(spi->write->iftype); ++ ++#ifdef HISFCV350_SUPPORT_BUS_READ ++ regval |= HISFC350_BUS_CONFIG1_READ_EN; ++#endif ++ regval |= HISFC350_BUS_CONFIG1_READ_PREF_CNT(0); ++ regval |= HISFC350_BUS_CONFIG1_READ_INS(spi->read->cmd); ++ regval |= HISFC350_BUS_CONFIG1_READ_DUMMY_CNT(spi->read->dummy); ++ regval |= HISFC350_BUS_CONFIG1_READ_IF_TYPE(spi->read->iftype); ++ ++ hisfc_write(host, HISFC350_BUS_CONFIG1, regval); ++ hisfc_write(host, HISFC350_BUS_CONFIG2, ++ HISFC350_BUS_CONFIG2_WIP_LOCATE(0)); ++ if (op == READ) ++ host->set_system_clock(host, spi->read, TRUE); ++ else if (op == WRITE) ++ host->set_system_clock(host, spi->write, TRUE); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++/* ++ judge whether SPI support QUAD read write or not ++*/ ++static int hisfc350_is_quad(struct hisfc_spi *spi) ++{ ++ if (DEBUG_SPI_QE) ++ printk(KERN_INFO "SPI read if[%d] write if[%d]\n", ++ spi->read->iftype, spi->write->iftype); ++ ++ if (spi->write->iftype == 5 || spi->write->iftype == 6 ++ || spi->write->iftype == 7 || spi->read->iftype == 5 ++ || spi->read->iftype == 6 || spi->read->iftype == 7) ++ return 1; ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++/* ++ enable QE bit if QUAD read write is supported by SPI ++*/ ++static int spi_general_qe_enable(struct hisfc_spi *spi) ++{ ++ unsigned char status, config, op; ++ unsigned int reg; ++ const char *str[] = {"Disable", "Enable"}; ++ struct hisfc_host *host = (struct hisfc_host *)spi->host; ++ ++ op = hisfc350_is_quad(spi); ++ ++ if (DEBUG_SPI_QE) ++ printk(KERN_INFO "* Start SPI Nor %s Quad.\n", str[op]); ++ ++ config = spi_general_get_flash_register(spi, SPI_CMD_RDCR); ++ if (DEBUG_SPI_QE) ++ printk(KERN_INFO " Read config %#x, val[%#x]\n", SPI_CMD_RDCR, ++ config); ++ if (((config & SPI_NOR_CR_QE_MASK) >> SPI_NOR_CR_QE_SHIFT) == op) { ++ if (DEBUG_SPI_QE) ++ printk(KERN_INFO "* Quad was %sd!\n", str[op]); ++ return op; ++ } ++ ++ status = spi_general_get_flash_register(spi, SPI_CMD_RDSR); ++ reg = (config << SPI_NOR_CR_SHIFT) | status; ++ if (DEBUG_SPI_QE) ++ printk(KERN_INFO " Read CR/SR[%#x]\n", reg); ++ ++ spi->driver->write_enable(spi); ++ ++ if (op) ++ reg |= (SPI_NOR_CR_QE_MASK << SPI_NOR_CR_SHIFT); ++ else ++ reg &= ~(SPI_NOR_CR_QE_MASK << SPI_NOR_CR_SHIFT); ++ hisfc_write(host, HISFC350_CMD_DATABUF0, reg); ++ if (DEBUG_SPI_QE) ++ printk(KERN_INFO " Set DATA[%#x]%#x\n", HISFC350_CMD_DATABUF0, ++ reg); ++ ++ hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_WRSR); ++ if (DEBUG_SPI_QE) ++ printk(KERN_INFO " Set INS[%#x]%#x\n", HISFC350_CMD_INS, ++ SPI_CMD_WRSR); ++ ++ reg = HISFC350_CMD_CONFIG_DATA_CNT(SPI_NOR_SR_LEN + SPI_NOR_CR_LEN) ++ | HISFC350_CMD_CONFIG_DATA_EN ++ | HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect) ++ | HISFC350_CMD_CONFIG_START; ++ hisfc_write(host, HISFC350_CMD_CONFIG, reg); ++ if (DEBUG_SPI_QE) ++ printk(KERN_INFO " Set CONFIG[%#x]%#x\n", HISFC350_CMD_CONFIG, ++ reg); ++ ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++ ++ if (DEBUG_SPI_QE) { ++ spi->driver->wait_ready(spi); ++ ++ config = spi_general_get_flash_register(spi, SPI_CMD_RDCR); ++ if (((config & SPI_NOR_CR_QE_MASK) >> SPI_NOR_CR_QE_SHIFT) ++ == op) ++ printk(KERN_INFO "* SPI Quad %s succeed. [%#x]\n", ++ str[op], config); ++ else ++ DBG_MSG("%s Quad failed! [%#x]\n", str[op], config); ++ } ++ ++ return op; ++} ++ ++/*****************************************************************************/ ++/* ++ some chip don't QUAD enable ++*/ ++static int spi_do_not_qe_enable(struct hisfc_spi *spi) ++{ ++ return 0; ++} +\ No newline at end of file +diff --git a/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_ids.c b/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_ids.c +new file mode 100644 +index 0000000..a08e40f +--- /dev/null ++++ b/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_ids.c +@@ -0,0 +1,2208 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "../spi_ids.h" ++ ++/*****************************************************************************/ ++ ++#define SET_READ_STD(_dummy_, _size_, _clk_) \ ++ static struct spi_operation read_std_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_STD, SPI_CMD_READ, _dummy_, _size_, _clk_ } ++ ++#define READ_STD(_dummy_, _size_, _clk_) read_std_##_dummy_##_size_##_clk_ ++ ++#define SET_READ_FAST(_dummy_, _size_, _clk_) \ ++ static struct spi_operation read_fast_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_FAST, SPI_CMD_FAST_READ, _dummy_, _size_, _clk_ } ++ ++#define READ_FAST(_dummy_, _size_, _clk_) read_fast_##_dummy_##_size_##_clk_ ++ ++#define SET_READ_DUAL(_dummy_, _size_, _clk_) \ ++ static struct spi_operation read_dual_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_DUAL, SPI_CMD_READ_DUAL, _dummy_, _size_, _clk_ } ++ ++#define READ_DUAL(_dummy_, _size_, _clk_) read_dual_##_dummy_##_size_##_clk_ ++ ++#define SET_READ_QUAD(_dummy_, _size_, _clk_) \ ++ static struct spi_operation read_quad_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_QUAD, SPI_CMD_READ_QUAD, _dummy_, _size_, _clk_ } ++ ++#define READ_QUAD(_dummy_, _size_, _clk_) read_quad_##_dummy_##_size_##_clk_ ++ ++#define SET_READ_DUAL_ADDR(_dummy_, _size_, _clk_) \ ++ static struct spi_operation \ ++ read_dual_addr_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_DUAL_ADDR, SPI_CMD_READ_DUAL_ADDR, _dummy_, _size_, _clk_ } ++ ++#define READ_DUAL_ADDR(_dummy_, _size_, _clk_) \ ++ read_dual_addr_##_dummy_##_size_##_clk_ ++ ++#define SET_READ_QUAD_ADDR(_dummy_, _size_, _clk_) \ ++ static struct spi_operation \ ++ read_quad_addr_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_QUAD_ADDR, SPI_CMD_READ_QUAD_ADDR, _dummy_, _size_, _clk_ } ++ ++#define READ_QUAD_ADDR(_dummy_, _size_, _clk_) \ ++ read_quad_addr_##_dummy_##_size_##_clk_ ++ ++#define SET_WRITE_STD(_dummy_, _size_, _clk_) \ ++ static struct spi_operation write_std_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_WRITE_STD, SPI_CMD_PP, _dummy_, _size_, _clk_ } ++ ++#define WRITE_STD(_dummy_, _size_, _clk_) write_std_##_dummy_##_size_##_clk_ ++ ++#define SET_WRITE_DUAL(_dummy_, _size_, _clk_) \ ++ static struct spi_operation write_dual_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_WRITE_DUAL, SPI_CMD_WRITE_DUAL, _dummy_, _size_, _clk_ } ++ ++#define WRITE_DUAL(_dummy_, _size_, _clk_) write_dual_##_dummy_##_size_##_clk_ ++ ++#define SET_WRITE_QUAD(_dummy_, _size_, _clk_) \ ++ static struct spi_operation write_quad_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_WRITE_QUAD, SPI_CMD_WRITE_QUAD, _dummy_, _size_, _clk_ } ++ ++#define WRITE_QUAD(_dummy_, _size_, _clk_) \ ++ write_quad_##_dummy_##_size_##_clk_ ++ ++#define SET_WRITE_DUAL_ADDR(_dummy_, _size_, _clk_) \ ++ static struct spi_operation \ ++ write_dual_addr_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_WRITE_DUAL_ADDR, SPI_CMD_WRITE_DUAL_ADDR,\ ++ _dummy_, _size_, _clk_ } ++ ++#define WRITE_DUAL_ADDR(_dummy_, _size_, _clk_) \ ++ write_dual_addr_##_dummy_##_size_##_clk_ ++ ++#define SET_WRITE_QUAD_ADDR(_dummy_, _size_, _clk_) \ ++ static struct spi_operation \ ++ write_quad_addr_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_WRITE_QUAD_ADDR, SPI_CMD_WRITE_QUAD_ADDR, \ ++ _dummy_, _size_, _clk_ } ++ ++#define WRITE_QUAD_ADDR(_dummy_, _size_, _clk_) \ ++ write_quad_addr_##_dummy_##_size_##_clk_ ++ ++#define SET_ERASE_SECTOR_4K(_dummy_, _size_, _clk_) \ ++ static struct spi_operation \ ++ erase_sector_4k_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_ERASE_SECTOR_4K, SPI_CMD_SE_4K, _dummy_, _size_, _clk_ } ++ ++#define ERASE_SECTOR_4K(_dummy_, _size_, _clk_) \ ++ erase_sector_4k_##_dummy_##_size_##_clk_ ++/*****************************************************************************/ ++ ++#define SET_ERASE_SECTOR_32K(_dummy_, _size_, _clk_) \ ++ static struct spi_operation \ ++ erase_sector_32k_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_ERASE_SECTOR_32K, SPI_CMD_SE_32K, _dummy_, _size_, _clk_ } ++ ++#define ERASE_SECTOR_32K(_dummy_, _size_, _clk_) \ ++ erase_sector_32k_##_dummy_##_size_##_clk_ ++/*****************************************************************************/ ++ ++#define SET_ERASE_SECTOR_64K(_dummy_, _size_, _clk_) \ ++ static struct spi_operation \ ++ erase_sector_64k_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_ERASE_SECTOR_64K, SPI_CMD_SE_64K, _dummy_, _size_, _clk_ } ++ ++#define ERASE_SECTOR_64K(_dummy_, _size_, _clk_) \ ++ erase_sector_64k_##_dummy_##_size_##_clk_ ++ ++/*****************************************************************************/ ++ ++#define SET_ERASE_SECTOR_256K(_dummy_, _size_, _clk_) \ ++ static struct spi_operation \ ++ erase_sector_256k_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_ERASE_SECTOR_256K, SPI_CMD_SE_256K, _dummy_, _size_, _clk_ } ++ ++#define ERASE_SECTOR_256K(_dummy_, _size_, _clk_) \ ++ erase_sector_256k_##_dummy_##_size_##_clk_ ++/*****************************************************************************/ ++SET_READ_STD(0, INFINITE, 0); ++SET_READ_STD(0, INFINITE, 20); ++SET_READ_STD(0, INFINITE, 32); ++SET_READ_STD(0, INFINITE, 33); ++SET_READ_STD(0, INFINITE, 40); ++SET_READ_STD(0, INFINITE, 50); ++SET_READ_STD(0, INFINITE, 54); ++SET_READ_STD(0, INFINITE, 55); ++SET_READ_STD(0, INFINITE, 66); ++ ++SET_READ_FAST(1, INFINITE, 50); ++SET_READ_FAST(1, INFINITE, 64); ++SET_READ_FAST(1, INFINITE, 66); ++SET_READ_FAST(1, INFINITE, 75); ++SET_READ_FAST(1, INFINITE, 80); ++SET_READ_FAST(1, INFINITE, 86); ++SET_READ_FAST(1, INFINITE, 100); ++SET_READ_FAST(1, INFINITE, 104); ++SET_READ_FAST(1, INFINITE, 108); ++SET_READ_FAST(1, INFINITE, 133); ++ ++SET_READ_DUAL(1, INFINITE, 64); ++SET_READ_DUAL(1, INFINITE, 75); ++SET_READ_DUAL(1, INFINITE, 80); ++SET_READ_DUAL(1, INFINITE, 84); ++SET_READ_DUAL(1, INFINITE, 104); ++SET_READ_DUAL(2, INFINITE, 104); ++SET_READ_DUAL(1, INFINITE, 108); ++SET_READ_DUAL(1, INFINITE, 133); ++ ++SET_READ_DUAL_ADDR(2, INFINITE, 64); ++SET_READ_DUAL_ADDR(0, INFINITE, 80); ++SET_READ_DUAL_ADDR(1, INFINITE, 80); ++SET_READ_DUAL_ADDR(1, INFINITE, 84); ++SET_READ_DUAL_ADDR(2, INFINITE, 84); ++SET_READ_DUAL_ADDR(1, INFINITE, 104); ++SET_READ_DUAL_ADDR(1, INFINITE, 108); ++SET_READ_DUAL_ADDR(2, INFINITE, 133); ++ ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++SET_READ_QUAD(1, INFINITE, 64); ++SET_READ_QUAD(1, INFINITE, 80); ++SET_READ_QUAD(1, INFINITE, 84); ++SET_READ_QUAD(1, INFINITE, 104); ++SET_READ_QUAD(1, INFINITE, 108); ++SET_READ_QUAD(1, INFINITE, 133); ++ ++SET_READ_QUAD_ADDR(2, INFINITE, 80); ++/* SET_READ_QUAD_ADDR(3, INFINITE, 50); */ ++SET_READ_QUAD_ADDR(3, INFINITE, 75); ++SET_READ_QUAD_ADDR(3, INFINITE, 80); ++SET_READ_QUAD_ADDR(5, INFINITE, 64); ++SET_READ_QUAD_ADDR(5, INFINITE, 84); ++SET_READ_QUAD_ADDR(3, INFINITE, 104); ++SET_READ_QUAD_ADDR(3, INFINITE, 108); ++SET_READ_QUAD_ADDR(5, INFINITE, 125); ++#endif ++/*****************************************************************************/ ++SET_WRITE_STD(0, 256, 0); ++SET_WRITE_STD(0, 256, 33); ++SET_WRITE_STD(0, 256, 50); ++SET_WRITE_STD(0, 256, 64); ++SET_WRITE_STD(0, 256, 66); ++SET_WRITE_STD(0, 256, 75); ++SET_WRITE_STD(0, 256, 80); ++SET_WRITE_STD(0, 256, 86); ++SET_WRITE_STD(0, 256, 100); ++SET_WRITE_STD(0, 256, 104); ++SET_WRITE_STD(0, 256, 108); ++SET_WRITE_STD(0, 256, 133); ++ ++SET_WRITE_DUAL(0, 256, 64); ++SET_WRITE_DUAL(0, 256, 75); ++SET_WRITE_DUAL(0, 256, 108); ++SET_WRITE_DUAL(0, 256, 133); ++ ++SET_WRITE_DUAL_ADDR(0, 256, 64); ++SET_WRITE_DUAL_ADDR(0, 256, 75); ++SET_WRITE_DUAL_ADDR(0, 256, 108); ++SET_WRITE_DUAL_ADDR(0, 256, 133); ++ ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++SET_WRITE_QUAD(0, 256, 64); ++SET_WRITE_QUAD(0, 256, 80); ++SET_WRITE_QUAD(0, 256, 108); ++SET_WRITE_QUAD(0, 256, 133); ++ ++/* FIXME: As Micron MT25Q(and MIXC) and N25Q have different QUAD I/O write code, ++ * but they have the same ID, so we cannot compatiable it. User can open ++ * by theirselves. */ ++SET_WRITE_QUAD_ADDR(0, 256, 33); ++/* SET_WRITE_QUAD_ADDR(0, 256, 64); */ ++SET_WRITE_QUAD_ADDR(0, 256, 104); ++/* SET_WRITE_QUAD_ADDR(0, 256, 133); */ ++#endif ++/*****************************************************************************/ ++SET_ERASE_SECTOR_32K(0, _32K, 0); ++ ++SET_ERASE_SECTOR_64K(0, _64K, 0); ++SET_ERASE_SECTOR_64K(0, _64K, 33); ++SET_ERASE_SECTOR_64K(0, _64K, 50); ++SET_ERASE_SECTOR_64K(0, _64K, 64); ++SET_ERASE_SECTOR_64K(0, _64K, 66); ++SET_ERASE_SECTOR_64K(0, _64K, 75); ++SET_ERASE_SECTOR_64K(0, _64K, 80); ++SET_ERASE_SECTOR_64K(0, _64K, 86); ++SET_ERASE_SECTOR_64K(0, _64K, 100); ++SET_ERASE_SECTOR_64K(0, _64K, 104); ++SET_ERASE_SECTOR_64K(0, _64K, 108); ++SET_ERASE_SECTOR_64K(0, _64K, 133); ++ ++SET_ERASE_SECTOR_256K(0, _256K, 50); ++SET_ERASE_SECTOR_256K(0, _256K, 104); ++ ++/*****************************************************************************/ ++#include "hisfc350_spi_general.c" ++static struct spi_driver spi_driver_general = { ++ .wait_ready = spi_general_wait_ready, ++ .write_enable = spi_general_write_enable, ++ .entry_4addr = spi_general_entry_4addr, ++ .bus_prepare = spi_general_bus_prepare, ++ .qe_enable = spi_general_qe_enable, ++}; ++ ++static struct spi_driver spi_driver_no_qe = { ++ .wait_ready = spi_general_wait_ready, ++ .write_enable = spi_general_write_enable, ++ .entry_4addr = spi_general_entry_4addr, ++ .bus_prepare = spi_general_bus_prepare, ++ .qe_enable = spi_do_not_qe_enable, ++}; ++ ++#include "hisfc350_spi_s25fl256s.c" ++static struct spi_driver spi_driver_s25fl256s = { ++ .wait_ready = spi_general_wait_ready, ++ .write_enable = spi_general_write_enable, ++ .entry_4addr = spi_s25fl256s_entry_4addr, ++ .bus_prepare = spi_general_bus_prepare, ++ .qe_enable = spi_general_qe_enable, ++}; ++ ++#include "hisfc350_spi_w25q256fv.c" ++static struct spi_driver spi_driver_w25q256fv = { ++ .wait_ready = spi_general_wait_ready, ++ .write_enable = spi_general_write_enable, ++ .entry_4addr = spi_w25q256fv_entry_4addr, ++ .bus_prepare = spi_general_bus_prepare, ++ .qe_enable = spi_general_qe_enable, ++}; ++ ++#include "hisfc350_spi_mx25l25635e.c" ++static struct spi_driver spi_driver_mx25l25635e = { ++ .wait_ready = spi_general_wait_ready, ++ .write_enable = spi_general_write_enable, ++ .entry_4addr = spi_general_entry_4addr, ++ .bus_prepare = spi_general_bus_prepare, ++ .qe_enable = spi_mx25l25635e_qe_enable, ++}; ++ ++static struct spi_driver spi_driver_f25l64q = { ++ .wait_ready = spi_general_wait_ready, ++ .write_enable = spi_general_write_enable, ++ .entry_4addr = spi_general_entry_4addr, ++ .bus_prepare = spi_general_bus_prepare, ++ .qe_enable = spi_mx25l25635e_qe_enable, ++}; ++ ++#include "hisfc350_spi_gd25qxxx.c" ++static struct spi_driver spi_driver_gd25qxxx = { ++ .wait_ready = spi_general_wait_ready, ++ .write_enable = spi_general_write_enable, ++ .entry_4addr = spi_general_entry_4addr, ++ .bus_prepare = spi_general_bus_prepare, ++ .qe_enable = spi_gd25qxxx_qe_enable, ++}; ++ ++#include "hisfc350_spi_micron.c" ++static struct spi_driver spi_driver_micron = { ++ .wait_ready = spi_general_wait_ready, ++ .write_enable = spi_general_write_enable, ++ .entry_4addr = spi_micron_entry_4addr, ++ .bus_prepare = spi_general_bus_prepare, ++ .qe_enable = spi_do_not_qe_enable, ++}; ++ ++/*****************************************************************************/ ++struct spi_info spi_info_table[] = { ++ /* name id id_len chipsize(Bytes) erasesize */ ++ { ++ "at25fs010", {0x1f, 0x66, 0x01}, 3, _128K, _32K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_32K(0, _32K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "at25fs040", {0x1f, 0x66, 0x04}, 3, _512K, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "at25df041a", {0x1f, 0x44, 0x01}, 3, _512K, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "at25df641", {0x1f, 0x48, 0x00}, 3, _8M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "at26f004", {0x1f, 0x04, 0x00}, 3, _512K, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "at26df081a", {0x1f, 0x45, 0x01}, 3, _1M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "at26df161a", {0x1f, 0x46, 0x01}, 3, _2M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "at26df321", {0x1f, 0x47, 0x01}, 3, _4M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ /* Macronix/MXIC */ ++ { ++ "mx25l4005a", {0xc2, 0x20, 0x13}, 3, _512K, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "MX25L8006E", {0xc2, 0x20, 0x14}, 3, _1M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 33), ++ &READ_FAST(1, INFINITE, 86), ++ &READ_DUAL(1, INFINITE, 80), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 86), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 86), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "MX25L1606E", {0xc2, 0x20, 0x15}, 3, _2M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 33), ++ &READ_FAST(1, INFINITE, 86), ++ &READ_DUAL(1, INFINITE, 80), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 86), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 86), ++ 0 ++ }, ++ &spi_driver_no_qe, ++ }, ++ ++ { ++ "mx25l3205d", {0xc2, 0x20, 0x16}, 3, _4M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ /* MX25L6406E and MX25L6436F have the same ID, but different I/O wire */ ++ { ++ "MX25L6406E", {0xc2, 0x20, 0x17}, 3, _8M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 50), ++ &READ_FAST(1, INFINITE, 86), ++ &READ_DUAL(1, INFINITE, 80), ++/* ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 133), ++ &READ_QUAD_ADDR(3, INFINITE, 133), ++#endif ++*/ ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 86), ++/* ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD_ADDR(0, 256, 133), ++#endif ++*/ ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 86), ++ 0 ++ }, ++ &spi_driver_mx25l25635e, ++ }, ++ ++ /* MX25R6435F Wide Voltage Range 1.65~3.6V */ ++ { ++ "MX25R6435F", {0xc2, 0x28, 0x17}, 3, _8M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 33), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(3, INFINITE, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 33), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD_ADDR(0, 256, 33), ++#endif ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 33), ++ 0 ++ }, ++ &spi_driver_mx25l25635e, ++ }, ++ ++ { ++ "MX25L128XX", {0xc2, 0x20, 0x18}, 3, _16M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 50), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_DUAL_ADDR(1, INFINITE, 104), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 104), ++ &READ_QUAD_ADDR(3, INFINITE, 104), ++#endif ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 104), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD_ADDR(0, 256, 104), ++#endif ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 104), ++ 0 ++ }, ++ &spi_driver_mx25l25635e, ++ }, ++ /* ++ The follow chips have the same chipid, but command have some difference ++ ++ {"MX25L12836E", {0xc2, 0x20, 0x18}, 3, _16M, _64K, 3, ++ {&READ_STD(0, INFINITE, 50), &READ_FAST(1, INFINITE, 108), 0}, ++ {&WRITE_STD(0, 256, 108), 0}, ++ {&ERASE_SECTOR_64K(0, _64K, 108), 0}}, ++ ++ {"MX25L12845E", {0xc2, 0x20, 0x18}, 3, _16M, _64K, 3, ++ {&READ_STD(0, INFINITE, 50), &READ_FAST(1, INFINITE, 108), 0}, ++ {&WRITE_STD(0, 256, 108), 0}, ++ {&ERASE_SECTOR_64K(0, _64K, 108), 0}}, ++ ++ {"MX25L12835F", {0xc2, 0x20, 0x18}, 3, _16M, _64K, 3, ++ {&READ_STD(0, INFINITE, 50), &READ_FAST(1, INFINITE, 108), 0}, ++ {&WRITE_STD(0, 256, 108), 0}, ++ {&ERASE_SECTOR_64K(0, _64K, 108), 0}}, ++ */ ++ ++ { ++ "MX25L(256/257)XX", ++ {0xc2, 0x20, 0x19}, 3, _32M, _64K, 4, ++ { ++ &READ_STD(0, INFINITE, 40/*50*/), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(2, INFINITE, 104), ++ &READ_DUAL_ADDR(1, INFINITE, 84), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD_ADDR(3, INFINITE, 75), ++#endif ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 75), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD_ADDR(0, 256, 104), ++#endif ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 80), ++ 0 ++ }, ++ &spi_driver_mx25l25635e, ++ }, ++ ++ { ++ "mx25l1655d", {0xc2, 0x26, 0x15}, 3, _2M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "mx25l12855e", {0xc2, 0x26, 0x18}, 3, _16M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "s25sl004a", {0x01, 0x02, 0x12}, 3, (_64K * 8), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "s25sl008a", {0x01, 0x02, 0x13}, 3, (_64K * 16), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "s25sl016a", {0x01, 0x02, 0x14}, 3, (_64K * 32), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "S25FL064P", {0x01, 0x02, 0x16, 0x4d}, 4, (_64K * 128), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 40), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 80), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 104), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 104), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "s25sl064a", {0x01, 0x02, 0x16}, 3, (_64K * 128), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ /* Spansion */ ++ ++ { ++ "S25FL032P", {0x01, 0x02, 0x15, 0x4d}, 4, (_64K * 64), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 40), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(0, INFINITE, 80), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(2, INFINITE, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 104), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 104), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "S25FL032A", {0x01, 0x02, 0x15}, 3, (_64K * 64), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 33), ++ &READ_FAST(1, INFINITE, 50), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 50), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 50), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "S25FL128P-0", ++ {0x01, 0x20, 0x18, 0x03, 0x00}, 5, (_256K * 64), _256K, 3, ++ { ++ &READ_STD(0, INFINITE, 40), ++ &READ_FAST(1, INFINITE, 104), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 104), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_256K(0, _256K, 104), ++ 0 ++ }, ++ &spi_driver_no_qe, ++ }, ++ ++ { ++ "S25FL128P-1", ++ {0x01, 0x20, 0x18, 0x03, 0x01}, 5, (_64K * 256), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 40), ++ &READ_FAST(1, INFINITE, 104), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 104), 0}, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 104), ++ 0 ++ }, ++ &spi_driver_no_qe, ++ }, ++ ++ { ++ "S25FL129P0", ++ {0x01, 0x20, 0x18, 0x4d, 0x00}, 5, (_256K * 64), _256K, 3, ++ { ++ &READ_STD(0, INFINITE, 40), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(0, INFINITE, 80), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(2, INFINITE, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 104), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_256K(0, _256K, 104), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "S25FL129P1/127S", ++ {0x01, 0x20, 0x18, 0x4d, 0x01}, 5, (_64K * 256), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 40), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 64), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(3, INFINITE, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 104), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 104), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "S25FL256S", {0x01, 0x02, 0x19, 0x4d, 0x01}, 5, _32M, _64K, 4, ++ { ++ &READ_STD(0, INFINITE, 40), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 64), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(3, INFINITE, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 104), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 104), ++ 0 ++ }, ++ &spi_driver_s25fl256s, ++ }, ++ ++ /* ++ The chip and chip W25Q16B have the same chipid, ++ but clock frequency have some difference ++ ++ {"S25FL016K", {0xef, 0x40, 0x15}, 3, (_64K * 32), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 50), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 104), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 104), ++ 0 ++ } ++ }, ++ */ ++ ++ /* SST -- large erase sizes are "overlays", "sectors" are 4K */ ++ { ++ "sst25vf040b", {0xbf, 0x25, 0x8d}, 3, (_64K * 8), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "sst25vf080b", {0xbf, 0x25, 0x8e}, 3, (_64K * 16), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "sst25vf016b", {0xbf, 0x25, 0x41}, 3, (_64K * 32), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "sst25vf032b", {0xbf, 0x25, 0x4a}, 3, (_64K * 64), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "sst25wf512", {0xbf, 0x25, 0x01}, 3, (_64K * 1), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "sst25wf010", {0xbf, 0x25, 0x02}, 3, (_64K * 2), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "sst25wf020", {0xbf, 0x25, 0x03}, 3, (_64K * 4), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "sst25wf040", {0xbf, 0x25, 0x04}, 3, (_64K * 8), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ /* ST Microelectronics -- newer production may have feature updates */ ++ { ++ "m25p05", {0x20, 0x20, 0x10}, 3, (_32K * 2), _32K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_32K(0, _32K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "m25p10", {0x20, 0x20, 0x11}, 3, (_32K * 4), _32K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_32K(0, _32K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "m25p20", {0x20, 0x20, 0x12}, 3, (_64K * 4), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "m25p40", {0x20, 0x20, 0x13}, 3, (_64K * 8), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "m25p80", {0x20, 0x20, 0x14}, 3, (_64K * 16), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "m25p16", {0x20, 0x20, 0x15}, 3, (_64K * 32), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "M25P32", {0x20, 0x20, 0x16, 0x10}, 4, _4M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 33), ++ &READ_FAST(1, INFINITE, 75), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 75), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 75), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "m25p64", {0x20, 0x20, 0x17}, 3, (_64K * 128), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "M25P128", {0x20, 0x20, 0x18}, 3, _16M, _256K, 3, ++ { ++ &READ_STD(0, INFINITE, 20), ++ &READ_FAST(1, INFINITE, 50), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 50), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_256K(0, _256K, 50), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "m45pe10", {0x20, 0x40, 0x11}, 3, (_64K * 2), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "m45pe80", {0x20, 0x40, 0x14}, 3, (_64K * 16), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "m45pe16", {0x20, 0x40, 0x15}, 3, (_64K * 32), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "m25pe80", {0x20, 0x80, 0x14}, 3, (_64K * 16), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "m25pe16", {0x20, 0x80, 0x15}, 3, (_64K * 32), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "N25Q032", {0x20, 0xba, 0x16}, 3, (_64K * 64), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 32/*54*/), ++ &READ_FAST(1, INFINITE, 64/*108*/), ++ &READ_DUAL(1, INFINITE, 64/*108*/), ++ &READ_DUAL_ADDR(2, INFINITE, 64/*108*/), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 64/*108*/), ++ &READ_QUAD_ADDR(5, INFINITE, 64/*108*/), ++#endif ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 64/*108*/), ++ &WRITE_DUAL(0, 256, 64/*108*/), ++ &WRITE_DUAL_ADDR(0, 256, 64/*108*/), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, 64/*108*/), ++ /* &WRITE_QUAD_ADDR(0, 256, 64), */ ++#endif ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 64/*108*/), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ /* Micron N25QL064A 3.3V */ ++ { ++ "N25QL064A", {0x20, 0xba, 0x17}, 3, (_64K * 128), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 54), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(2, INFINITE, 84), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(5, INFINITE, 84), ++#endif ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_DUAL(0, 256, 75), ++ &WRITE_DUAL_ADDR(0, 256, 75), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 50), ++ 0 ++ }, ++ &spi_driver_micron, ++ }, ++ ++ /* Micron MT(N)25QL128A 3.3V */ ++ { ++ "N25QL128A", {0x20, 0xba, 0x18}, 3, (_64K * 256), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 54), ++ &READ_FAST(1, INFINITE, 108), ++ &READ_DUAL(1, INFINITE, 84), ++ &READ_DUAL_ADDR(2, INFINITE, 84), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 84), ++ &READ_QUAD_ADDR(5, INFINITE, 84), ++#endif ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 108), ++ &WRITE_DUAL(0, 256, 108), ++ &WRITE_DUAL_ADDR(0, 256, 108), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, 108), ++#endif ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 108), ++ 0 ++ }, ++ &spi_driver_micron, ++ }, ++ ++ /* Micron MT25QL256A 3.3V */ ++ { ++ "MT25QL256A", {0x20, 0xba, 0x19}, 3, (_64K * 512), _64K, 4, ++ { ++ &READ_STD(0, INFINITE, 54), ++ &READ_FAST(1, INFINITE, 133), ++ &READ_DUAL(1, INFINITE, 133), ++ &READ_DUAL_ADDR(2, INFINITE, 133), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 133), ++ &READ_QUAD_ADDR(5, INFINITE, 125), ++#endif ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 133), ++ &WRITE_DUAL(0, 256, 133), ++ &WRITE_DUAL_ADDR(0, 256, 133), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, 133), ++ /* &WRITE_QUAD_ADDR(0, 256, 133), */ ++#endif ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 133), ++ 0 ++ }, ++ &spi_driver_micron, ++ }, ++ ++ { ++ "M25PX16", {0x20, 0x71, 0x15}, 3, (_64K * 32), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 33), ++ &READ_FAST(1, INFINITE, 75), ++ &READ_DUAL(1, INFINITE, 75), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 75), ++ &WRITE_DUAL(0, 256, 75), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 75), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "M25PX32", {0x20, 0x71, 0x16}, 3, (_64K * 64), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 33), ++ &READ_FAST(1, INFINITE, 75), ++ &READ_DUAL(1, INFINITE, 75), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 75), ++ &WRITE_DUAL(0, 256, 75), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 75), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "m25px64", {0x20, 0x71, 0x17}, 3, (_64K * 128), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ ++ { ++ "w25x10", {0xef, 0x30, 0x11}, 3, (_64K * 2), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "w25x20", {0xef, 0x30, 0x12}, 3, (_64K * 4), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "w25x40", {0xef, 0x30, 0x13}, 3, (_64K * 8), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "w25x80", {0xef, 0x30, 0x14}, 3, (_64K * 16), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "w25x16", {0xef, 0x30, 0x15}, 3, (_64K * 32), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "w25x32", {0xef, 0x30, 0x16}, 3, (_64K * 64), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), 0}, ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "w25x64", {0xef, 0x30, 0x17}, 3, (_64K * 128), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 0), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 0), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 0), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "W25Q80BV", {0xef, 0x40, 0x14}, 3, (_64K * 16), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 50), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 80), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 80), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "W25Q16(B/C)V/S25FL016K", ++ {0xef, 0x40, 0x15}, 3, (_64K * 32), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 50), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 80), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 80), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ /* ++ The follow chips have the same chipid, but command have some difference ++ { ++ "W25Q16BV", {0xef, 0x40, 0x15}, 3, (_64K * 32), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 50), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_QUAD(1, INFINITE, 80), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 80), ++ 0 ++ } ++ }, ++ ++ { ++ "W25Q16CV", {0xef, 0x40, 0x15}, 3, (_64K * 32), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 50), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_QUAD(1, INFINITE, 80), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 80), ++ 0 ++ } ++ }, ++ ++ */ ++ { ++ "W25Q32BV", {0xef, 0x40, 0x16}, 3, (_64K * 64), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 50), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 80), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 80), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "W25Q64FV", {0xef, 0x40, 0x17}, 3, _8M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 50), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 80), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 80), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "W25Q128(B/F)V", {0xEF, 0x40, 0x18}, 3, _16M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 33), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, /*70*/80), ++#endif ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 104), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, /*70*/80), ++#endif ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 104), ++ 0 ++ }, ++ &spi_driver_w25q256fv, ++ }, ++ ++ { ++ "W25Q256FV", {0xEF, 0x40, 0x19}, 3, _32M, _64K, 4, ++ { ++ &READ_STD(0, INFINITE, 50), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 104), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, 80), ++#endif ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 104), ++ 0 ++ }, ++ &spi_driver_w25q256fv, ++ }, ++ ++ /* Eon -- fit clock frequency of RDSR instruction*/ ++ { ++ "EN25F80", {0x1c, 0x31, 0x14}, 3, (_64K * 16), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 66), ++ &READ_FAST(1, INFINITE, 66/*100*/), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 66/*100*/), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 66/*100*/), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "EN25F16", {0x1c, 0x31, 0x15}, 3, _2M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 66), ++ &READ_FAST(1, INFINITE, 66/*100*/), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 66/*100*/), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 66/*100*/), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "EN25Q32B", {0x1c, 0x30, 0x16}, 3, (_64K * 64), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 50), ++ &READ_FAST(1, INFINITE, 80/*104*/), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++ /*&READ_QUAD(3, INFINITE, 80), */ ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 80/*104*/), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 80/*104*/), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "EN25Q64", {0x1c, 0x30, 0x17}, 3, (_64K * 128), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 50), ++ &READ_FAST(1, INFINITE, 100), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 80), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 104), ++ 0 ++ }, ++ &spi_driver_no_qe, ++ }, ++ ++ { ++ "EN25Q128", {0x1c, 0x30, 0x18}, 3, (_64K * 256), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 50), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++ 0 ++ }, ++ ++ { ++ &WRITE_STD(0, 256, 104), ++ 0 ++ }, ++ ++ { ++ &ERASE_SECTOR_64K(0, _64K, 104), ++ 0 ++ }, ++ &spi_driver_no_qe, ++ }, ++ ++ /* ESMT */ ++ { ++ "F25L64QA", {0x8C, 0x41, 0x17}, 3, (_64K * 128), _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 66), ++ &READ_FAST(1, INFINITE, /*66*/100), ++ &READ_DUAL(1, INFINITE, /*66*/80), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 80), ++#endif ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, /*66*/100), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, 80), ++#endif ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, /*66*/100), ++ 0 ++ }, ++ &spi_driver_f25l64q, ++ }, ++ ++ { ++ "GD25Q128", {0xC8, 0x40, 0x18}, 3, _16M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 66), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 80), ++#endif ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 100), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, 80), ++#endif ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 100), ++ 0 ++ }, ++ &spi_driver_gd25qxxx, ++ }, ++ ++ { ++ "GD25Q64", {0xC8, 0x40, 0x17}, 3, _8M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 66), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 80), ++#endif ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 100), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, 80), ++#endif ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 100), ++ 0 ++ }, ++ &spi_driver_gd25qxxx, ++ }, ++ { ++ "GD25Q32", {0xC8, 0x40, 0x16}, 3, _4M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 66), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 80), ++#endif ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 100), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &WRITE_QUAD(0, 256, 80), ++#endif ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 100), ++ 0 ++ }, ++ &spi_driver_gd25qxxx, ++ }, ++ ++ /* Paragon 3.3V */ ++ { ++ "PN25F16S", {0xe0, 0x40, 0x15}, 3, _2M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 55), ++ &READ_FAST(1, INFINITE, 108), ++ &READ_DUAL(1, INFINITE, 108), ++ &READ_DUAL_ADDR(1, INFINITE, 108), ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 108), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 108), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ { ++ "PN25F32S", {0xe0, 0x40, 0x16}, 3, _4M, _64K, 3, ++ { ++ &READ_STD(0, INFINITE, 55), ++ &READ_FAST(1, INFINITE, 108), ++ &READ_DUAL(1, INFINITE, 108), ++ &READ_DUAL_ADDR(1, INFINITE, 108), ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ &READ_QUAD(1, INFINITE, 108), ++ &READ_QUAD_ADDR(3, INFINITE, 108), ++#endif ++ 0 ++ }, ++ { ++ &WRITE_STD(0, 256, 108), ++ 0 ++ }, ++ { ++ &ERASE_SECTOR_64K(0, _64K, 108), ++ 0 ++ }, ++ &spi_driver_general, ++ }, ++ ++ {0, {0}, 0, 0, 0, 0, {0}, {0}, {0}, NULL}, ++}; +diff --git a/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_micron.c b/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_micron.c +new file mode 100644 +index 0000000..70ff1b6 +--- /dev/null ++++ b/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_micron.c +@@ -0,0 +1,98 @@ ++/* ++ * The SPI NOR Controller v350 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/*****************************************************************************/ ++#define SPI_CMD_FIRST_RESET_4ADDR (0x66) ++#define SPI_CMD_SECOND_RESET_4ADDR (0x99) ++ ++#define SPI_CMD_FLAG_SR_MICRON 0x70 /* READ FLAG STATUS REGISTER */ ++#define SPI_CMD_RD_RDCR_MICRON 0xB5 /* READ NONVOLATILE CONFIGURATION ++ REGISTER*/ ++#define SPI_CMD_WR_RDCR_MICRON 0xB1 /* WRITE NONVOLATILE CONFIGURATION ++ REGISTER*/ ++#define SPI_NOR_ADS_MASK 0x1 ++#define SPI_NOR_GET_4BYTE_BY_FLAG_SR(sr) ((sr) & SPI_NOR_ADS_MASK) ++ ++#define SPI_NOR_ADS_SET_4BYTE(cr) ((cr) & (~SPI_NOR_ADS_MASK)) ++#define SPI_NOR_ADS_GET_4BYTE(cr) ((cr) & SPI_NOR_ADS_MASK) ++/****************************************************************************/ ++static int spi_micron_entry_4addr(struct hisfc_spi *spi, int enable) ++{ ++ unsigned char status; ++ unsigned int reg; ++ const char *str[] = {"Disable", "Enable"}; ++ struct hisfc_host *host = (struct hisfc_host *)spi->host; ++ ++ if (spi->addrcycle != SPI_4BYTE_ADDR_LEN) ++ return 0; ++ ++ status = spi_general_get_flash_register(spi, SPI_CMD_FLAG_SR_MICRON); ++ if (DEBUG_SPI) ++ printk(KERN_INFO"\t Read flag status register[%#x]:%#x\n", ++ SPI_CMD_FLAG_SR_MICRON, status); ++ ++ if (SPI_NOR_GET_4BYTE_BY_FLAG_SR(status) == enable) { ++ if (DEBUG_SPI) ++ printk(KERN_INFO"\t* 4-byte was %sd, reg:%#x\n", str[enable], ++ status); ++ return 0; ++ } ++ ++ spi->driver->write_enable(spi); ++ ++ if (enable) ++ reg = SPI_CMD_EN4B; ++ else ++ reg = SPI_CMD_EX4B; ++ ++ hisfc_write(host, HISFC350_CMD_INS, reg); ++ if (DEBUG_SPI) ++ printk(KERN_INFO"\t Set CMD[%#x]%#x\n", HISFC350_CMD_INS, reg); ++ ++ reg = HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect) ++ | HISFC350_CMD_CONFIG_START; ++ hisfc_write(host, HISFC350_CMD_CONFIG, reg); ++ ++ if (DEBUG_SPI) ++ printk(KERN_INFO"\t Set OP_CFG[%#x]%#x\n", HISFC350_CMD_CONFIG, reg); ++ ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++ ++ host->set_host_addr_mode(host, enable); ++ ++ spi->driver->wait_ready(spi); ++ ++ status = spi_general_get_flash_register(spi, ++ SPI_CMD_FLAG_SR_MICRON); ++ if (DEBUG_SPI) ++ printk(KERN_INFO"\t Read flag status register[%#x]:%#x\n", ++ SPI_CMD_FLAG_SR_MICRON, status); ++ if (SPI_NOR_GET_4BYTE_BY_FLAG_SR(status) != enable) { ++ printk(KERN_INFO"Error: %s 4-byte failed! SR3:%#x\n", ++ str[enable], status); ++ return status; ++ } ++ ++ if (DEBUG_SPI) { ++ printk(KERN_INFO"\t %s 4-byte success, SR3:%#x\n", str[enable], status); ++ printk(KERN_INFO"\t* End SPI Nor flash %s 4-byte mode.\n", str[enable]); ++ } ++ return 0; ++} +diff --git a/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_mx25l25635e.c b/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_mx25l25635e.c +new file mode 100644 +index 0000000..0ba254a +--- /dev/null ++++ b/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_mx25l25635e.c +@@ -0,0 +1,99 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++ ++#include "../spi_ids.h" ++#include "hisfc350.h" ++ ++/* MXIC QE(bit) include in Status Register */ ++#define MX_SPI_NOR_SR_QE_SHIFT 6 ++#define MX_SPI_NOR_SR_QE_MASK (1 << MX_SPI_NOR_SR_QE_SHIFT) ++ ++/*****************************************************************************/ ++/* ++ enable QE bit if QUAD read write is supported by SPI ++*/ ++static int spi_mx25l25635e_qe_enable(struct hisfc_spi *spi) ++{ ++ unsigned char status, op; ++ unsigned int reg; ++ const char *str[] = {"Disable", "Enable"}; ++ struct hisfc_host *host = (struct hisfc_host *)spi->host; ++ ++ op = hisfc350_is_quad(spi); ++ ++ if (DEBUG_SPI_QE) ++ printk(KERN_INFO "* Start SPI Nor %s Quad.\n", str[op]); ++ ++ spi->driver->wait_ready(spi); ++ ++ status = spi_general_get_flash_register(spi, SPI_CMD_RDSR); ++ if (DEBUG_SPI_QE) ++ printk(KERN_INFO " Read status %#x, val[%#x]\n", SPI_CMD_RDSR, ++ status); ++ if (((status & MX_SPI_NOR_SR_QE_MASK) >> MX_SPI_NOR_SR_QE_SHIFT) ++ == op) { ++ if (DEBUG_SPI_QE) ++ printk(KERN_INFO "* Quad was %sd!\n", str[op]); ++ return op; ++ } ++ ++ spi->driver->write_enable(spi); ++ ++ if (op) ++ status |= MX_SPI_NOR_SR_QE_MASK; ++ else ++ status &= ~MX_SPI_NOR_SR_QE_MASK; ++ hisfc_write(host, HISFC350_CMD_DATABUF0, status); ++ if (DEBUG_SPI_QE) ++ printk(KERN_INFO " Set DATA[%#x]%#x\n", HISFC350_CMD_DATABUF0, ++ status); ++ ++ hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_WRSR); ++ if (DEBUG_SPI_QE) ++ printk(KERN_INFO " Set INS[%#x]%#x\n", HISFC350_CMD_INS, ++ SPI_CMD_WRSR); ++ ++ reg = HISFC350_CMD_CONFIG_DATA_CNT(SPI_NOR_SR_LEN) ++ | HISFC350_CMD_CONFIG_DATA_EN ++ | HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect) ++ | HISFC350_CMD_CONFIG_START; ++ hisfc_write(host, HISFC350_CMD_CONFIG, reg); ++ if (DEBUG_SPI_QE) ++ printk(KERN_INFO " Set CONFIG[%#x]%#x\n", HISFC350_CMD_CONFIG, ++ reg); ++ ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++ ++ if (DEBUG_SPI_QE) { ++ spi->driver->wait_ready(spi); ++ ++ status = spi_general_get_flash_register(spi, SPI_CMD_RDSR); ++ if (((status & MX_SPI_NOR_SR_QE_MASK) >> MX_SPI_NOR_SR_QE_SHIFT) ++ == op) ++ printk(KERN_INFO "* SPI %s Quad succeed.\n", str[op]); ++ else ++ DBG_MSG("%s Quad failed! [%#x]\n", str[op], status); ++ } ++ ++ return op; ++} ++ +diff --git a/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_n25q256a.c b/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_n25q256a.c +new file mode 100644 +index 0000000..b5a7d28 +--- /dev/null ++++ b/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_n25q256a.c +@@ -0,0 +1,53 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include "../spi_ids.h" ++#include "hisfc350.h" ++ ++static int spi_n25q256a_entry_4addr(struct hisfc_spi *spi, int enable) ++{ ++ struct hisfc_host *host = (struct hisfc_host *)spi->host; ++ ++ if (spi->addrcycle != 4) ++ return 0; ++ ++ spi->driver->wait_ready(spi); ++ ++ if (enable) { ++ spi->driver->write_enable(spi); ++ hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_EN4B); ++ } else { ++ spi->driver->write_enable(spi); ++ hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_EX4B); ++ } ++ ++ hisfc_write(host, HISFC350_CMD_CONFIG, ++ HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect) ++ | HISFC350_CMD_CONFIG_START); ++ ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++ ++ host->set_host_addr_mode(host, enable); ++ ++ return 0; ++} ++ +diff --git a/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_s25fl256s.c b/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_s25fl256s.c +new file mode 100644 +index 0000000..bec3f23 +--- /dev/null ++++ b/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_s25fl256s.c +@@ -0,0 +1,68 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include "../spi_ids.h" ++#include "hisfc350.h" ++ ++#define SPI_BRWR 0x17 ++#define SPI_EN4B 0x80 ++#define SPI_EX4B 0x00 ++ ++static int spi_s25fl256s_entry_4addr(struct hisfc_spi *spi, int enable) ++{ ++ struct hisfc_host *host = (struct hisfc_host *)spi->host; ++ unsigned int regval = 0; ++ ++ if (spi->addrcycle != SPI_4BYTE_ADDR_LEN) ++ return 0; ++ ++ spi->driver->wait_ready(spi); ++ ++ if (enable) { ++ hisfc_write(host, HISFC350_CMD_INS, SPI_BRWR); ++ hisfc_write(host, HISFC350_CMD_DATABUF0, SPI_EN4B); ++ } else { ++ hisfc_write(host, HISFC350_CMD_INS, SPI_BRWR); ++ hisfc_write(host, HISFC350_CMD_DATABUF0, SPI_EX4B); ++ } ++ ++ hisfc_write(host, HISFC350_CMD_CONFIG, ++ HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect) ++ | HISFC350_CMD_CONFIG_DATA_CNT(1) ++ | HISFC350_CMD_CONFIG_DATA_EN ++ | HISFC350_CMD_CONFIG_START); ++ ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++ if (DEBUG_SPI) { ++ regval = hisfc_read(host, HISFC350_CMD_DATABUF0); ++ if (!(regval & SPI_EN4B)) { ++ printk(KERN_INFO "now is 3-byte address mode\n"); ++ printk(KERN_INFO "regval_read_SPI : 0x%x\n", regval); ++ } else ++ printk(KERN_INFO "now is 4-byte address mode\n"); ++ ++ } ++ host->set_host_addr_mode(host, enable); ++ ++ return 0; ++} ++ +diff --git a/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_w25q256fv.c b/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_w25q256fv.c +new file mode 100644 +index 0000000..ce1f368 +--- /dev/null ++++ b/drivers/mtd/spi-nor/hisfc350/hisfc350_spi_w25q256fv.c +@@ -0,0 +1,82 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++ ++#include "../spi_ids.h" ++#include "hisfc350.h" ++ ++#define SPI_CMD_FIRST_RESET_4ADDR (0x66) ++#define SPI_CMD_SECOND_RESET_4ADDR (0x99) ++ ++static int spi_w25q256fv_entry_4addr(struct hisfc_spi *spi, int enable) ++{ ++ struct hisfc_host *host = (struct hisfc_host *)spi->host; ++ ++ if (spi->addrcycle != SPI_4BYTE_ADDR_LEN) ++ return 0; ++ ++ spi->driver->wait_ready(spi); ++ /* This chip should not enable write here, ++ * we have confirmed with the WINBOND */ ++ /* spi->driver->write_enable(spi); */ ++ if (enable) { ++ hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_EN4B); ++ if (DEBUG_SPI) ++ printk(KERN_INFO "now w25q256fv is 4-byte address mode\n"); ++ ++ hisfc_write(host, HISFC350_CMD_CONFIG, ++ HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect) ++ | HISFC350_CMD_CONFIG_START); ++ ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++ } else { ++ hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_FIRST_RESET_4ADDR); ++ hisfc_write(host, HISFC350_CMD_CONFIG, ++ HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect) ++ | HISFC350_CMD_CONFIG_START); ++ ++ ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++ ++ ++ hisfc_write(host, HISFC350_CMD_INS, SPI_CMD_SECOND_RESET_4ADDR); ++ hisfc_write(host, HISFC350_CMD_CONFIG, ++ HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect) ++ | HISFC350_CMD_CONFIG_START); ++ ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++ if (DEBUG_SPI) ++ printk(KERN_INFO "now W25Q256FV 6699 cmd\n"); ++ } ++/* ++ hisfc_write(host, HISFC350_CMD_CONFIG, ++ HISFC350_CMD_CONFIG_SEL_CS(spi->chipselect) ++ | HISFC350_CMD_CONFIG_DATA_CNT(1) ++ | HISFC350_CMD_CONFIG_DATA_EN ++ | HISFC350_CMD_CONFIG_START); ++ ++ HISFC350_CMD_WAIT_CPU_FINISH(host); ++*/ ++ host->set_host_addr_mode(host, enable); ++ ++ return 0; ++} ++ +diff --git a/drivers/mtd/spi-nor/hisi-sfc.c b/drivers/mtd/spi-nor/hisi-sfc.c +index 20378b0..74422e4 100644 +--- a/drivers/mtd/spi-nor/hisi-sfc.c ++++ b/drivers/mtd/spi-nor/hisi-sfc.c +@@ -16,80 +16,21 @@ + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +-#include + #include + #include + #include + #include ++#include + #include + #include ++#include + #include + #include + #include + +-/* Hardware register offsets and field definitions */ +-#define FMC_CFG 0x00 +-#define FMC_CFG_OP_MODE_MASK BIT_MASK(0) +-#define FMC_CFG_OP_MODE_BOOT 0 +-#define FMC_CFG_OP_MODE_NORMAL 1 +-#define FMC_CFG_FLASH_SEL(type) (((type) & 0x3) << 1) +-#define FMC_CFG_FLASH_SEL_MASK 0x6 +-#define FMC_ECC_TYPE(type) (((type) & 0x7) << 5) +-#define FMC_ECC_TYPE_MASK GENMASK(7, 5) +-#define SPI_NOR_ADDR_MODE_MASK BIT_MASK(10) +-#define SPI_NOR_ADDR_MODE_3BYTES (0x0 << 10) +-#define SPI_NOR_ADDR_MODE_4BYTES (0x1 << 10) +-#define FMC_GLOBAL_CFG 0x04 +-#define FMC_GLOBAL_CFG_WP_ENABLE BIT(6) +-#define FMC_SPI_TIMING_CFG 0x08 +-#define TIMING_CFG_TCSH(nr) (((nr) & 0xf) << 8) +-#define TIMING_CFG_TCSS(nr) (((nr) & 0xf) << 4) +-#define TIMING_CFG_TSHSL(nr) ((nr) & 0xf) +-#define CS_HOLD_TIME 0x6 +-#define CS_SETUP_TIME 0x6 +-#define CS_DESELECT_TIME 0xf +-#define FMC_INT 0x18 +-#define FMC_INT_OP_DONE BIT(0) +-#define FMC_INT_CLR 0x20 +-#define FMC_CMD 0x24 +-#define FMC_CMD_CMD1(cmd) ((cmd) & 0xff) +-#define FMC_ADDRL 0x2c +-#define FMC_OP_CFG 0x30 +-#define OP_CFG_FM_CS(cs) ((cs) << 11) +-#define OP_CFG_MEM_IF_TYPE(type) (((type) & 0x7) << 7) +-#define OP_CFG_ADDR_NUM(addr) (((addr) & 0x7) << 4) +-#define OP_CFG_DUMMY_NUM(dummy) ((dummy) & 0xf) +-#define FMC_DATA_NUM 0x38 +-#define FMC_DATA_NUM_CNT(cnt) ((cnt) & GENMASK(13, 0)) +-#define FMC_OP 0x3c +-#define FMC_OP_DUMMY_EN BIT(8) +-#define FMC_OP_CMD1_EN BIT(7) +-#define FMC_OP_ADDR_EN BIT(6) +-#define FMC_OP_WRITE_DATA_EN BIT(5) +-#define FMC_OP_READ_DATA_EN BIT(2) +-#define FMC_OP_READ_STATUS_EN BIT(1) +-#define FMC_OP_REG_OP_START BIT(0) +-#define FMC_DMA_LEN 0x40 +-#define FMC_DMA_LEN_SET(len) ((len) & GENMASK(27, 0)) +-#define FMC_DMA_SADDR_D0 0x4c +-#define HIFMC_DMA_MAX_LEN (4096) +-#define HIFMC_DMA_MASK (HIFMC_DMA_MAX_LEN - 1) ++#include "../mtdcore.h" ++ + #define FMC_OP_DMA 0x68 +-#define OP_CTRL_RD_OPCODE(code) (((code) & 0xff) << 16) +-#define OP_CTRL_WR_OPCODE(code) (((code) & 0xff) << 8) +-#define OP_CTRL_RW_OP(op) ((op) << 1) +-#define OP_CTRL_DMA_OP_READY BIT(0) +-#define FMC_OP_READ 0x0 +-#define FMC_OP_WRITE 0x1 +-#define FMC_WAIT_TIMEOUT 1000000 +- +-enum hifmc_iftype { +- IF_TYPE_STD, +- IF_TYPE_DUAL, +- IF_TYPE_DIO, +- IF_TYPE_QUAD, +- IF_TYPE_QIO, +-}; + + struct hifmc_priv { + u32 chipselect; +@@ -97,10 +38,9 @@ struct hifmc_priv { + struct hifmc_host *host; + }; + +-#define HIFMC_MAX_CHIP_NUM 2 + struct hifmc_host { + struct device *dev; +- struct mutex lock; ++ struct mutex *lock; + + void __iomem *regbase; + void __iomem *iobase; +@@ -109,9 +49,11 @@ struct hifmc_host { + dma_addr_t dma_buffer; + + struct spi_nor *nor[HIFMC_MAX_CHIP_NUM]; ++ struct hifmc_priv priv[HIFMC_MAX_CHIP_NUM]; + u32 num_chip; + }; + ++/******************************************************************************/ + static inline int wait_op_finish(struct hifmc_host *host) + { + u32 reg; +@@ -120,19 +62,24 @@ static inline int wait_op_finish(struct hifmc_host *host) + (reg & FMC_INT_OP_DONE), 0, FMC_WAIT_TIMEOUT); + } + +-static int get_if_type(enum read_mode flash_read) ++static int get_if_type(enum spi_nor_protocol mode) + { + enum hifmc_iftype if_type; + +- switch (flash_read) { +- case SPI_NOR_DUAL: ++ switch (mode) { ++ case SNOR_PROTO_1_1_2: + if_type = IF_TYPE_DUAL; + break; +- case SPI_NOR_QUAD: ++ case SNOR_PROTO_1_2_2: ++ if_type = IF_TYPE_DIO; ++ break; ++ case SNOR_PROTO_1_1_4: + if_type = IF_TYPE_QUAD; + break; +- case SPI_NOR_NORMAL: +- case SPI_NOR_FAST: ++ case SNOR_PROTO_1_4_4: ++ if_type = IF_TYPE_QIO; ++ break; ++ case SNOR_PROTO_1_1_1: + default: + if_type = IF_TYPE_STD; + break; +@@ -141,23 +88,53 @@ static int get_if_type(enum read_mode flash_read) + return if_type; + } + ++/******************************************************************************/ ++static void spi_nor_switch_spi_type(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ reg = hifmc_readl(host, FMC_CFG); ++ reg &= ~FLASH_TYPE_SEL_MASK; ++ reg |= FMC_CFG_FLASH_SEL(0); ++ hifmc_writel(host, FMC_CFG, reg); ++} ++ ++/******************************************************************************/ + static void hisi_spi_nor_init(struct hifmc_host *host) + { +- u32 reg; ++ unsigned int reg; ++ ++ /* switch the flash type to spi nor */ ++ spi_nor_switch_spi_type(host); ++ ++ /* set the boot mode to normal */ ++ reg = hifmc_readl(host, FMC_CFG); ++ if ((reg & FMC_CFG_OP_MODE_MASK) == FMC_CFG_OP_MODE_BOOT) { ++ reg |= FMC_CFG_OP_MODE(FMC_CFG_OP_MODE_NORMAL); ++ hifmc_writel(host, FMC_CFG, reg); ++ } ++ ++ /* hold on STR mode */ ++ reg = hifmc_readl(host, FMC_GLOBAL_CFG); ++ reg &= (~FMC_GLOBAL_CFG_DTR_MODE); ++ hifmc_writel(host, FMC_GLOBAL_CFG, reg); + ++ /* set timming */ + reg = TIMING_CFG_TCSH(CS_HOLD_TIME) + | TIMING_CFG_TCSS(CS_SETUP_TIME) + | TIMING_CFG_TSHSL(CS_DESELECT_TIME); +- writel(reg, host->regbase + FMC_SPI_TIMING_CFG); ++ hifmc_writel(host, FMC_SPI_TIMING_CFG, reg); + } + ++/******************************************************************************/ + static int hisi_spi_nor_prep(struct spi_nor *nor, enum spi_nor_ops ops) + { + struct hifmc_priv *priv = nor->priv; + struct hifmc_host *host = priv->host; + int ret; + +- mutex_lock(&host->lock); ++ mutex_lock(&fmc_switch_mutex); ++ mutex_lock(host->lock); + + ret = clk_set_rate(host->clk, priv->clkrate); + if (ret) +@@ -167,22 +144,27 @@ static int hisi_spi_nor_prep(struct spi_nor *nor, enum spi_nor_ops ops) + if (ret) + goto out; + ++ spi_nor_switch_spi_type(host); ++ + return 0; + + out: +- mutex_unlock(&host->lock); ++ mutex_unlock(host->lock); + return ret; + } + ++/******************************************************************************/ + static void hisi_spi_nor_unprep(struct spi_nor *nor, enum spi_nor_ops ops) + { + struct hifmc_priv *priv = nor->priv; + struct hifmc_host *host = priv->host; + + clk_disable_unprepare(host->clk); +- mutex_unlock(&host->lock); ++ mutex_unlock(host->lock); ++ mutex_unlock(&fmc_switch_mutex); + } + ++/******************************************************************************/ + static int hisi_spi_nor_op_reg(struct spi_nor *nor, + u8 opcode, int len, u8 optype) + { +@@ -191,21 +173,22 @@ static int hisi_spi_nor_op_reg(struct spi_nor *nor, + u32 reg; + + reg = FMC_CMD_CMD1(opcode); +- writel(reg, host->regbase + FMC_CMD); ++ hifmc_writel(host, FMC_CMD, reg); + + reg = FMC_DATA_NUM_CNT(len); +- writel(reg, host->regbase + FMC_DATA_NUM); ++ hifmc_writel(host, FMC_DATA_NUM, reg); + +- reg = OP_CFG_FM_CS(priv->chipselect); +- writel(reg, host->regbase + FMC_OP_CFG); ++ reg = OP_CFG_FM_CS(priv->chipselect) | OP_CFG_OEN_EN; ++ hifmc_writel(host, FMC_OP_CFG, reg); + +- writel(0xff, host->regbase + FMC_INT_CLR); ++ hifmc_writel(host, FMC_INT_CLR, 0xff); + reg = FMC_OP_CMD1_EN | FMC_OP_REG_OP_START | optype; +- writel(reg, host->regbase + FMC_OP); ++ hifmc_writel(host, FMC_OP, reg); + + return wait_op_finish(host); + } + ++/******************************************************************************/ + static int hisi_spi_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, + int len) + { +@@ -221,6 +204,7 @@ static int hisi_spi_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, + return 0; + } + ++/******************************************************************************/ + static int hisi_spi_nor_write_reg(struct spi_nor *nor, u8 opcode, + u8 *buf, int len) + { +@@ -233,38 +217,52 @@ static int hisi_spi_nor_write_reg(struct spi_nor *nor, u8 opcode, + return hisi_spi_nor_op_reg(nor, opcode, len, FMC_OP_WRITE_DATA_EN); + } + ++/******************************************************************************/ + static int hisi_spi_nor_dma_transfer(struct spi_nor *nor, loff_t start_off, + dma_addr_t dma_buf, size_t len, u8 op_type) + { + struct hifmc_priv *priv = nor->priv; + struct hifmc_host *host = priv->host; +- u8 if_type = 0; ++ u8 if_type = 0, dummy = 0; + u32 reg; + +- reg = readl(host->regbase + FMC_CFG); ++ reg = hifmc_readl(host, FMC_CFG); + reg &= ~(FMC_CFG_OP_MODE_MASK | SPI_NOR_ADDR_MODE_MASK); + reg |= FMC_CFG_OP_MODE_NORMAL; + reg |= (nor->addr_width == 4) ? SPI_NOR_ADDR_MODE_4BYTES + : SPI_NOR_ADDR_MODE_3BYTES; +- writel(reg, host->regbase + FMC_CFG); ++ hifmc_writel(host, FMC_CFG, reg); ++ ++ hifmc_writel(host, FMC_ADDRL, start_off); ++ ++ reg = (unsigned int)dma_buf; ++ hifmc_writel(host, FMC_DMA_SADDR_D0, reg); + +- writel(start_off, host->regbase + FMC_ADDRL); +- writel(dma_buf, host->regbase + FMC_DMA_SADDR_D0); +- writel(FMC_DMA_LEN_SET(len), host->regbase + FMC_DMA_LEN); ++#ifdef CONFIG_64BIT ++ reg = (dma_buf & FMC_DMA_SADDRH_MASK) >> 32; ++ hifmc_writel(host, FMC_DMA_SADDRH_D0, reg); ++#endif ++ ++ hifmc_writel(host, FMC_DMA_LEN, FMC_DMA_LEN_SET(len)); + + reg = OP_CFG_FM_CS(priv->chipselect); +- if_type = get_if_type(nor->flash_read); +- reg |= OP_CFG_MEM_IF_TYPE(if_type); +- if (op_type == FMC_OP_READ) +- reg |= OP_CFG_DUMMY_NUM(nor->read_dummy >> 3); +- writel(reg, host->regbase + FMC_OP_CFG); ++ if (op_type == FMC_OP_READ) { ++ if_type = get_if_type(nor->read_proto); ++ dummy = nor->read_dummy >> 3; ++ } else { ++ if_type = get_if_type(nor->write_proto); ++ } ++ reg |= OP_CFG_MEM_IF_TYPE(if_type) ++ | OP_CFG_DUMMY_NUM(dummy) ++ | OP_CFG_OEN_EN; ++ hifmc_writel(host, FMC_OP_CFG, reg); + +- writel(0xff, host->regbase + FMC_INT_CLR); ++ hifmc_writel(host, FMC_INT_CLR, 0xff); + reg = OP_CTRL_RW_OP(op_type) | OP_CTRL_DMA_OP_READY; + reg |= (op_type == FMC_OP_READ) + ? OP_CTRL_RD_OPCODE(nor->read_opcode) + : OP_CTRL_WR_OPCODE(nor->program_opcode); +- writel(reg, host->regbase + FMC_OP_DMA); ++ hifmc_writel(host, FMC_OP_DMA, reg); + + return wait_op_finish(host); + } +@@ -316,6 +314,26 @@ static ssize_t hisi_spi_nor_write(struct spi_nor *nor, loff_t to, + } + + /** ++ * parse partitions info and register spi flash device as mtd device. ++ */ ++static int hisi_snor_device_register(struct mtd_info *mtd) ++{ ++ int ret; ++ struct mtd_partitions parsed; ++ ++ /* ++ * We do not add the whole spi flash as a mtdblock device, ++ * To avoid the number of nand partition +1. ++ */ ++ memset(&parsed, 0, sizeof(parsed)); ++ ret = parse_mtd_partitions(mtd, NULL, &parsed, NULL); ++ if (ret) ++ return ret; ++ ++ return parsed.nr_parts ? mtd_device_register(mtd, NULL, 0) : parsed.nr_parts; ++} ++ ++/** + * Get spi flash device information and register it as a mtd device. + */ + static int hisi_spi_nor_register(struct device_node *np, +@@ -323,9 +341,13 @@ static int hisi_spi_nor_register(struct device_node *np, + { + struct device *dev = host->dev; + struct spi_nor *nor; +- struct hifmc_priv *priv; ++ struct hifmc_priv *priv = &host->priv[host->num_chip]; + struct mtd_info *mtd; + int ret; ++ struct spi_nor_modes modes = { ++ .rd_modes = SNOR_MODE_SLOW, ++ .wr_modes = SNOR_MODE_1_1_1, ++ }; + + nor = devm_kzalloc(dev, sizeof(*nor), GFP_KERNEL); + if (!nor) +@@ -345,6 +367,13 @@ static int hisi_spi_nor_register(struct device_node *np, + return ret; + } + ++ if (priv->chipselect != host->num_chip) { ++ dev_warn(dev, " The CS: %d states in device trees isn't real " \ ++ "chipselect on board\n, using CS: %d instead. ", ++ priv->chipselect, host->num_chip); ++ priv->chipselect = host->num_chip; ++ } ++ + ret = of_property_read_u32(np, "spi-max-frequency", + &priv->clkrate); + if (ret) { +@@ -361,19 +390,27 @@ static int hisi_spi_nor_register(struct device_node *np, + nor->write_reg = hisi_spi_nor_write_reg; + nor->read = hisi_spi_nor_read; + nor->write = hisi_spi_nor_write; +- nor->erase = NULL; +- ret = spi_nor_scan(nor, NULL, SPI_NOR_QUAD); ++ ++ modes.rd_modes |= SNOR_MODE_1_1_1 ++ | SNOR_MODE_1_1_2 ++ | SNOR_MODE_1_2_2; ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ modes.rd_modes |= SNOR_MODE_1_1_4 | SNOR_MODE_1_4_4; ++ modes.wr_modes |= SNOR_MODE_1_1_4 | SNOR_MODE_1_4_4; ++#endif ++ ret = spi_nor_scan(nor, NULL, &modes); + if (ret) + return ret; + + mtd = &nor->mtd; + mtd->name = np->name; +- ret = mtd_device_register(mtd, NULL, 0); ++ ret = hisi_snor_device_register(mtd); + if (ret) + return ret; + ++ /* current chipselect has scanned, to detect next chipselect */ ++ hifmc_cs_user[host->num_chip]++; + host->nor[host->num_chip] = nor; +- host->num_chip++; + return 0; + } + +@@ -388,18 +425,27 @@ static void hisi_spi_nor_unregister_all(struct hifmc_host *host) + static int hisi_spi_nor_register_all(struct hifmc_host *host) + { + struct device *dev = host->dev; +- struct device_node *np; ++ struct device_node *np = NULL; + int ret; + + for_each_available_child_of_node(dev->of_node, np) { ++ if (hifmc_cs_user[host->num_chip]) { ++ dev_warn(dev, "Current CS(%d) is occupied.\n", ++ host->num_chip); ++ continue; ++ } + ret = hisi_spi_nor_register(np, host); + if (ret) + goto fail; + + if (host->num_chip == HIFMC_MAX_CHIP_NUM) { +- dev_warn(dev, "Flash device number exceeds the maximum chipselect number\n"); ++ dev_warn(dev, "Flash device number exceeds the " ++ "maximum chipselect number\n"); + break; + } ++ ++ host->num_chip++; ++ + } + + return 0; +@@ -409,13 +455,19 @@ static int hisi_spi_nor_register_all(struct hifmc_host *host) + return ret; + } + ++/******************************************************************************/ + static int hisi_spi_nor_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +- struct resource *res; ++ struct hisi_fmc *fmc = dev_get_drvdata(dev->parent); + struct hifmc_host *host; + int ret; + ++ if (!fmc) { ++ dev_err(&pdev->dev, "get mfd fmc devices failed\n"); ++ return -ENXIO; ++ } ++ + host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); + if (!host) + return -ENOMEM; +@@ -423,65 +475,123 @@ static int hisi_spi_nor_probe(struct platform_device *pdev) + platform_set_drvdata(pdev, host); + host->dev = dev; + +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control"); +- host->regbase = devm_ioremap_resource(dev, res); +- if (IS_ERR(host->regbase)) +- return PTR_ERR(host->regbase); +- +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory"); +- host->iobase = devm_ioremap_resource(dev, res); +- if (IS_ERR(host->iobase)) +- return PTR_ERR(host->iobase); +- +- host->clk = devm_clk_get(dev, NULL); +- if (IS_ERR(host->clk)) +- return PTR_ERR(host->clk); +- +- ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); +- if (ret) { +- dev_warn(dev, "Unable to set dma mask\n"); +- return ret; +- } +- +- host->buffer = dmam_alloc_coherent(dev, HIFMC_DMA_MAX_LEN, +- &host->dma_buffer, GFP_KERNEL); +- if (!host->buffer) +- return -ENOMEM; ++ host->regbase = fmc->regbase; ++ host->iobase = fmc->iobase; ++ host->clk = fmc->clk; ++ host->lock = &fmc->lock; ++ host->buffer = fmc->buffer; ++ host->dma_buffer = fmc->dma_buffer; + +- mutex_init(&host->lock); + clk_prepare_enable(host->clk); + hisi_spi_nor_init(host); + ret = hisi_spi_nor_register_all(host); + if (ret) +- mutex_destroy(&host->lock); ++ dev_warn(dev, "spi nor register fail!\n"); + + clk_disable_unprepare(host->clk); ++ + return ret; + } + ++/******************************************************************************/ + static int hisi_spi_nor_remove(struct platform_device *pdev) + { + struct hifmc_host *host = platform_get_drvdata(pdev); + + hisi_spi_nor_unregister_all(host); +- mutex_destroy(&host->lock); + clk_disable_unprepare(host->clk); + return 0; + } + ++/******************************************************************************/ ++static void hisi_spi_nor_driver_shutdown(struct platform_device *pdev) ++{ ++ int i; ++ struct hifmc_host *host = platform_get_drvdata(pdev); ++ ++ if (!host) ++ return; ++ ++ mutex_lock(host->lock); ++ clk_prepare_enable(host->clk); ++ ++ spi_nor_switch_spi_type(host); ++ for (i = 0; i < host->num_chip; i++) ++ spi_nor_driver_shutdown(host->nor[i]); ++ ++ clk_disable_unprepare(host->clk); ++ mutex_unlock(host->lock); ++ dev_dbg(host->dev, "End of driver shutdown\n"); ++} ++ ++#ifdef CONFIG_PM ++/******************************************************************************/ ++static int hisi_spi_nor_driver_suspend(struct platform_device *pdev, ++ pm_message_t state) ++{ ++ int i; ++ struct hifmc_host *host = platform_get_drvdata(pdev); ++ ++ if (!host) ++ return 0; ++ ++ mutex_lock(host->lock); ++ clk_prepare_enable(host->clk); ++ ++ spi_nor_switch_spi_type(host); ++ for (i = 0; i < host->num_chip; i++) ++ spi_nor_suspend(host->nor[i], state); ++ ++ clk_disable_unprepare(host->clk); ++ mutex_unlock(host->lock); ++ dev_dbg(host->dev, "End of suspend\n"); ++ ++ return 0; ++} ++ ++/******************************************************************************/ ++static int hisi_spi_nor_driver_resume(struct platform_device *pdev) ++{ ++ int i; ++ struct hifmc_host *host = platform_get_drvdata(pdev); ++ ++ if (!host) ++ return 0; ++ ++ mutex_lock(host->lock); ++ clk_prepare_enable(host->clk); ++ ++ spi_nor_switch_spi_type(host); ++ for (i = 0; i < host->num_chip; i++) ++ spi_nor_resume(host->nor[i]); ++ ++ mutex_unlock(host->lock); ++ dev_dbg(host->dev, "End of resume\n"); ++ ++ return 0; ++} ++#endif /* End of CONFIG_PM */ ++ ++/******************************************************************************/ + static const struct of_device_id hisi_spi_nor_dt_ids[] = { + { .compatible = "hisilicon,fmc-spi-nor"}, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, hisi_spi_nor_dt_ids); + ++/******************************************************************************/ + static struct platform_driver hisi_spi_nor_driver = { + .driver = { + .name = "hisi-sfc", + .of_match_table = hisi_spi_nor_dt_ids, + }, +- .probe = hisi_spi_nor_probe, +- .remove = hisi_spi_nor_remove, ++ .probe = hisi_spi_nor_probe, ++ .remove = hisi_spi_nor_remove, ++ .shutdown = hisi_spi_nor_driver_shutdown, ++#ifdef CONFIG_PM ++ .suspend = hisi_spi_nor_driver_suspend, ++ .resume = hisi_spi_nor_driver_resume, ++#endif + }; + module_platform_driver(hisi_spi_nor_driver); + +diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c +index 21dde52..79bd7c7 100644 +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -75,6 +75,12 @@ struct flash_info { + * bit. Must be used with + * SPI_NOR_HAS_LOCK. + */ ++#define SPI_NOR_4B_OPCODES BIT(10) /* ++ * Use dedicated 4byte address op codes ++ * to support memory size above 128Mib. ++ */ ++ ++ const struct spi_nor_basic_flash_parameter *params; + }; + + #define JEDEC_MFR(info) ((info)->id[0]) +@@ -139,24 +145,6 @@ static int read_cr(struct spi_nor *nor) + } + + /* +- * Dummy Cycle calculation for different type of read. +- * It can be used to support more commands with +- * different dummy cycle requirements. +- */ +-static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor) +-{ +- switch (nor->flash_read) { +- case SPI_NOR_FAST: +- case SPI_NOR_DUAL: +- case SPI_NOR_QUAD: +- return 8; +- case SPI_NOR_NORMAL: +- return 0; +- } +- return 0; +-} +- +-/* + * Write status register 1 byte + * Returns negative if error occurred. + */ +@@ -188,6 +176,80 @@ static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd) + return mtd->priv; + } + ++struct spi_nor_address_entry { ++ u8 src_opcode; ++ u8 dst_opcode; ++}; ++ ++static u8 spi_nor_convert_opcode(u8 opcode, ++ const struct spi_nor_address_entry *entries, ++ size_t num_entries) ++{ ++ int min, max; ++ ++ min = 0; ++ max = num_entries - 1; ++ while (min <= max) { ++ int mid = (min + max) >> 1; ++ const struct spi_nor_address_entry *entry = &entries[mid]; ++ ++ if (opcode == entry->src_opcode) ++ return entry->dst_opcode; ++ ++ if (opcode < entry->src_opcode) ++ max = mid - 1; ++ else ++ min = mid + 1; ++ } ++ ++ /* No conversion found */ ++ return opcode; ++} ++ ++static u8 spi_nor_3to4_opcode(u8 opcode) ++{ ++ /* MUST be sorted by 3byte opcode */ ++#define ENTRY_3TO4(_opcode) { _opcode, _opcode##_4B } ++ static const struct spi_nor_address_entry spi_nor_3to4_table[] = { ++ ENTRY_3TO4(SPINOR_OP_PP), /* 0x02 */ ++ ENTRY_3TO4(SPINOR_OP_READ), /* 0x03 */ ++ ENTRY_3TO4(SPINOR_OP_READ_FAST), /* 0x0b */ ++ ENTRY_3TO4(SPINOR_OP_BE_4K), /* 0x20 */ ++ ENTRY_3TO4(SPINOR_OP_PP_1_1_4), /* 0x32 */ ++ ENTRY_3TO4(SPINOR_OP_PP_1_4_4), /* 0x38 */ ++ ENTRY_3TO4(SPINOR_OP_READ_1_1_2), /* 0x3b */ ++ ENTRY_3TO4(SPINOR_OP_BE_32K), /* 0x52 */ ++ ENTRY_3TO4(SPINOR_OP_READ_1_1_4), /* 0x6b */ ++ ENTRY_3TO4(SPINOR_OP_READ_1_2_2), /* 0xbb */ ++ ENTRY_3TO4(SPINOR_OP_SE), /* 0xd8 */ ++ ENTRY_3TO4(SPINOR_OP_READ_1_4_4), /* 0xeb */ ++ }; ++#undef ENTRY_3TO4 ++ ++ return spi_nor_convert_opcode(opcode, spi_nor_3to4_table, ++ ARRAY_SIZE(spi_nor_3to4_table)); ++} ++ ++static void spi_nor_set_4byte_opcodes(struct spi_nor *nor, ++ const struct flash_info *info) ++{ ++ /* Do some manufacturer fixups first */ ++ switch (JEDEC_MFR(info)) { ++ case SNOR_MFR_SPANSION: ++ /* No small sector erase for 4-byte command set */ ++ nor->erase_opcode = SPINOR_OP_SE; ++ nor->mtd.erasesize = info->sector_size; ++ break; ++ ++ default: ++ break; ++ } ++ ++ nor->read_opcode = spi_nor_3to4_opcode(nor->read_opcode); ++ nor->program_opcode = spi_nor_3to4_opcode(nor->program_opcode); ++ nor->erase_opcode = spi_nor_3to4_opcode(nor->erase_opcode); ++} ++ + /* Enable/disable 4-byte addressing mode. */ + static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info, + int enable) +@@ -201,16 +263,26 @@ static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info, + /* Some Micron need WREN command; all will accept it */ + need_wren = true; + case SNOR_MFR_MACRONIX: +- case SNOR_MFR_WINBOND: + if (need_wren) + write_enable(nor); + + cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B; + status = nor->write_reg(nor, cmd, NULL, 0); ++ + if (need_wren) + write_disable(nor); + + return status; ++ case SNOR_MFR_WINBOND: ++ if (enable) ++ return nor->write_reg(nor, SPINOR_OP_EN4B, NULL, 0); ++ else { ++ /* w25q256fvfg must send reset to disable 4 byte mode */ ++ nor->write_reg(nor, SPINOR_ENABLE_RESET, NULL, 0); ++ nor->write_reg(nor, SPINOR_OP_RESET, NULL, 0); ++ udelay(30); ++ } ++ return 0; + default: + /* Spansion style */ + nor->cmd_buf[0] = enable << 7; +@@ -220,6 +292,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 +302,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 +312,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; +@@ -367,6 +442,12 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) + if (ret) + return ret; + ++#ifdef CONFIG_HISI_SPI_BLOCK_PROTECT ++ if ((nor->level) && (addr < nor->end_addr)) { ++ dev_err(nor->dev, "Error: The erase area was locked\n"); ++ return -EINVAL; ++ } ++#endif + /* whole-chip erase? */ + if (len == mtd->size) { + unsigned long timeout; +@@ -745,6 +826,203 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) + return ret; + } + ++#define SNOR_RD_MODES \ ++ (SNOR_MODE_SLOW | \ ++ SNOR_MODE_1_1_1 | \ ++ SNOR_MODE_1_1_2 | \ ++ SNOR_MODE_1_2_2 | \ ++ SNOR_MODE_1_1_4 | \ ++ SNOR_MODE_1_4_4) ++ ++#define SNOR_WR_MODES \ ++ (SNOR_MODE_1_1_1 | \ ++ SNOR_MODE_1_1_4) ++ ++static int spansion_quad_enable(struct spi_nor *nor); ++static int macronix_quad_enable(struct spi_nor *nor); ++static int gd_quad_enable(struct spi_nor *nor); ++ ++#define SNOR_EON_RD_MODES \ ++ (SNOR_MODE_SLOW | \ ++ SNOR_MODE_1_1_1 | \ ++ SNOR_MODE_1_1_2 | \ ++ SNOR_MODE_1_2_2) ++ ++#define SNOR_EON_WR_MODES \ ++ (SNOR_MODE_1_1_1) ++ ++static const struct spi_nor_basic_flash_parameter eon_params = { ++ .rd_modes = SNOR_EON_RD_MODES, ++ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ), ++ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST), ++ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2), ++ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(8, 0, SPINOR_OP_READ_1_2_2), ++ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4), ++ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4), ++ ++ .wr_modes = SNOR_EON_WR_MODES, ++ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP, ++ ++ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE), ++ ++}; ++ ++static const struct spi_nor_basic_flash_parameter esmt_params = { ++ .rd_modes = SNOR_RD_MODES, ++ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ), ++ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST), ++ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2), ++ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(8, 0, SPINOR_OP_READ_1_2_2), ++ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4), ++ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4), ++ ++ .wr_modes = SNOR_WR_MODES, ++ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP, ++ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4, ++ ++ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE), ++ ++ .enable_quad_io = macronix_quad_enable, ++ ++}; ++ ++#define SNOR_PARAGON_WR_MODES \ ++ (SNOR_MODE_1_1_1) ++ ++static const struct spi_nor_basic_flash_parameter paragon_params = { ++ .rd_modes = SNOR_RD_MODES, ++ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ), ++ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST), ++ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2), ++ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(8, 0, SPINOR_OP_READ_1_2_2), ++ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4), ++ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4), ++ ++ .wr_modes = SNOR_PARAGON_WR_MODES, ++ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP, ++ ++ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE), ++ ++ .enable_quad_io = spansion_quad_enable, ++ ++}; ++ ++static const struct spi_nor_basic_flash_parameter gd_params = { ++ .rd_modes = SNOR_RD_MODES, ++ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ), ++ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST), ++ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2), ++ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(8, 0, SPINOR_OP_READ_1_2_2), ++ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4), ++ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4), ++ ++ .wr_modes = SNOR_WR_MODES, ++ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP, ++ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4, ++ ++ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE), ++ ++ .enable_quad_io = gd_quad_enable, ++ ++}; ++ ++static const struct spi_nor_basic_flash_parameter winbond_params = { ++ .rd_modes = SNOR_RD_MODES, ++ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ), ++ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST), ++ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2), ++ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(8, 0, SPINOR_OP_READ_1_2_2), ++ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4), ++ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4), ++ ++ .wr_modes = SNOR_WR_MODES, ++ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP, ++ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4, ++ ++ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE), ++ ++ .enable_quad_io = spansion_quad_enable, ++ ++}; ++ ++static const struct spi_nor_basic_flash_parameter spansion_params = { ++ .rd_modes = SNOR_RD_MODES, ++ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ), ++ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST), ++ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2), ++ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_2_2), ++ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4), ++ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4), ++ ++ .wr_modes = SNOR_WR_MODES, ++ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP, ++ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4, ++ ++ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE), ++ ++ .enable_quad_io = spansion_quad_enable, ++ ++}; ++ ++#define SNOR_MXIC_WR_MODES \ ++ (SNOR_MODE_1_1_1 | \ ++ SNOR_MODE_1_4_4) ++ ++static const struct spi_nor_basic_flash_parameter mxic_params = { ++ .rd_modes = SNOR_RD_MODES, ++ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ), ++ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST), ++ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2), ++ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_2_2), ++ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4), ++ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4), ++ ++ .wr_modes = SNOR_MXIC_WR_MODES, ++ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP, ++ .page_programs[SNOR_MIDX_1_4_4] = SPINOR_OP_PP_1_4_4, ++ ++ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE), ++ ++ .enable_quad_io = macronix_quad_enable, ++ ++}; ++ ++static const struct spi_nor_basic_flash_parameter micron_params = { ++ .rd_modes = SNOR_RD_MODES, ++ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ), ++ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST), ++ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2), ++ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(8, 8, SPINOR_OP_READ_1_2_2), ++ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(1, 7, SPINOR_OP_READ_1_1_4), ++ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(0, 40, SPINOR_OP_READ_1_4_4), ++ ++ .wr_modes = SNOR_WR_MODES, ++ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP, ++ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4, ++ ++ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE), ++ ++}; ++ ++static const struct spi_nor_basic_flash_parameter micron_4k_params = { ++ .rd_modes = SNOR_RD_MODES, ++ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ), ++ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST), ++ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2), ++ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(1, 7, SPINOR_OP_READ_1_2_2), ++ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(1, 7, SPINOR_OP_READ_1_1_4), ++ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(1, 9, SPINOR_OP_READ_1_4_4), ++ ++ .wr_modes = SNOR_WR_MODES, ++ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP, ++ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4, ++ ++ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE), ++ .erase_types[1] = SNOR_OP_ERASE_4K(SPINOR_OP_BE_4K), ++}; ++ ++#define PARAMS(_name) .params = &_name##_params ++ + /* Used when the "_ext_id" is two bytes at most */ + #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ + .id = { \ +@@ -758,7 +1036,7 @@ 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) + + #define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ + .id = { \ +@@ -793,6 +1071,47 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) + * For historical (and compatibility) reasons (before we got above config) some + * old entries may be missing 4K flag. + */ ++#define SPI_NOR_IDS_VER "1.0" ++ ++/******* SPI Nor ID Table ************************************************** ++ * Version Manufacturer Chip Name Chipsize Block Vol Operation ++ * 1.0 Macronix/MXIC MX25L1606E 2M 64K 3V3 ++ * Macronix/MXIC MX25L6436F 8M 64K 3V3 ++ * Macronix/MXIC MX25R6435F 8M 64K 1V8/3V3 Add 14chips ++ * Macronix/MXIC MX25U6435F 8M 64K 1V8 ++ * Macronix/MXIC MX25U12835F 16M 64K 1V8 ++ * Macronix/MXIC MX25F128XXX 16M 64K 3V3 ++ * Macronix/MXIC MX25U25635F/45G 32M 64K 1V8 25645G-DTR ++ * Macronix/MXIC MX25L(256/257) 32M 64K 3V3 25645G-DTR ++ * Macronix/MXIC MX25U51245G 64M 64K 1V8 51245G-DTR ++ * Spansion S25FL129P1 16M 64K 3V3 ++ * Spansion S25FL256S 32M 64K 3V3 ++ * Micron N25Q064A 8M 64K 3V3 ++ * Micron N25QL064A 8M 64K 3V3 ++ * Micron N25Q128A11/MT25QU128AB 16M 64K 1V8 ++ * Micron N25QL128A 16M 64K 3V3 ++ * Micron MT25QU256A 32M 64K 1V8 ++ * Micron MT25Q256A 32M 64K 3V3 ++ * Winbond W25Q16(B/C)V/S25FL016K 2M 64K 3V3 ++ * Winbond W25Q32(B/F)V 4M 64K 3V3 ++ * Winbond W25Q32FW 4M 64K 1V8 ++ * Winbond W25Q64FW 8M 64K 1V8 ++ * Winbond W25Q64FV 8M 64K 3V3 ++ * Winbond W25Q128FW 16M 64K 1V8 ++ * Winbond W25Q128(B/F)V 16M 64K 3V3 ++ * Winbond W25Q128JV 16M 64K 3V3 DTR ++ * ESMT/CFEON EN25Q32B 4M 64K 3V3 ++ * ESMT/CFEON EN25Q64 8M 64K 3V3 ++ * ESMT/CFEON EN25Q128 16M 64K 3V3 ++ * ESMT/CFEON F25L64QA 8M 64K 3V3 ++ * GD GD25Q64 8M 64K 3V3 ++ * GD GD25LQ128 16M 64K 1V8 ++ * GD GD25Q128 16M 64K 3V3 ++ * GD GD25LQ64C 8M 64K 1V8 ++ * GD GD25Q32 4M 64K 3V3 ++ * Paragon PN25F16S 2M 64K 3V3 ++ * Paragon PN25F32S 4M 64K 3V3 ++ *****************************************************************************/ + static const struct flash_info spi_nor_ids[] = { + /* Atmel -- some are (confusingly) marketed as "DataFlash" */ + { "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4, SECT_4K) }, +@@ -812,44 +1131,36 @@ static const struct flash_info spi_nor_ids[] = { + /* 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) }, ++ { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0), PARAMS(eon) }, + { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, +- { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, ++ { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K), ++ PARAMS(eon) }, ++ { "en25q128", INFO(0x1c3018, 0, 64 * 1024, 256, 0), PARAMS(eon) }, + { "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) }, + + /* ESMT */ + { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K) }, ++ { "f25l64qa", INFO(0x8c4117, 0, 64 * 1024, 128, 0), PARAMS(esmt) }, + + /* 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) }, ++ { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE ++ | SPI_NOR_NO_FR) }, + + /* Fujitsu */ + { "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1, SPI_NOR_NO_ERASE) }, + +- /* 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) +- }, ++ /* GigaDevice 3.3V */ ++ { "gd25q16c", INFO(0xc84015, 0, 64 * 1024, 32, SECT_4K), PARAMS(gd) }, ++ { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K), PARAMS(gd) }, ++ { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K), PARAMS(gd) }, ++ { "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, SECT_4K), PARAMS(gd) }, ++ /* GigaDevice 1.8V */ ++ { "gd25lq64", INFO(0xc86017, 0, 64 * 1024, 128, SECT_4K), PARAMS(gd) }, ++ { "gd25lq128", INFO(0xc86018, 0, 64 * 1024, 256, SECT_4K), PARAMS(gd) }, + + /* Intel/Numonyx -- xxxs33b */ + { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, +@@ -859,68 +1170,107 @@ static const struct flash_info spi_nor_ids[] = { + /* ISSI */ + { "is25cd512", INFO(0x7f9d20, 0, 32 * 1024, 2, SECT_4K) }, + +- /* Macronix */ ++ /* Macronix/MXIC 3.3V */ + { "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) }, ++ { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K ++ | SPI_NOR_DUAL_READ) }, ++ { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) }, + { "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) }, ++ { "mx25l6436f", INFO(0xc22017, 0, 64 * 1024, 128, 0), PARAMS(mxic) }, ++ { "mx25l12835f", INFO(0xc22018, 0, 64 * 1024, 256, 0), PARAMS(mxic) }, + { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, +- { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, ++ { "mx25l25635f", INFO(0xc22019, 0, 64 * 1024, 512, 0), PARAMS(mxic) }, ++ { "mx25l25673g", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_QUAD_READ ++ | SPI_NOR_4B_OPCODES) }, + { "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) }, +- +- /* 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) }, ++ { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_QUAD_READ)}, ++ { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ)}, ++ { "mx25v1635f", INFO(0xc22315, 0, 64 * 1024, 32 , 0), PARAMS(mxic) }, ++ /* Macronix/MXIC Wide Voltage Range 1.65~3.6V */ ++ { "mx25r6435f", INFO(0xc22817, 0, 64 * 1024, 128, SPI_NOR_DUAL_READ ++ | SPI_NOR_QUAD_READ) }, ++ /* Macronix/MXIC 1.8V */ ++ { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, ++ SECT_4K), PARAMS(mxic) }, ++ { "mx25u12835f", INFO(0xc22538, 0, 64 * 1024, 256, 0), PARAMS(mxic) }, ++ { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, ++ SPI_NOR_4B_OPCODES), PARAMS(mxic) }, ++ { "mx25u51245g", INFO(0xc2253a, 0, 64 * 1024, 1024, ++ SPI_NOR_4B_OPCODES), PARAMS(mxic) }, ++ ++ /* Micron 3.3V */ ++ { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0), ++ PARAMS(micron) }, ++ { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0), ++ PARAMS(micron_4k) }, ++ { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0), ++ PARAMS(micron) }, ++ { "mt25ql256a/n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, 0), ++ PARAMS(micron) }, ++ { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR), ++ PARAMS(micron_4k) }, ++ { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR), ++ PARAMS(micron_4k) }, ++ /* Micron 1.8V */ ++ { "n25q032a", INFO(0x20bb16, 0, 64 * 1024, 64, 0), ++ PARAMS(micron) }, ++ { "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128, 0), ++ PARAMS(micron) }, ++ { "mt25qu128a/n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0), ++ PARAMS(micron) }, ++ { "mt25qu256a", INFO(0x20bb19, 0, 64 * 1024, 512, 0), ++ PARAMS(micron) }, ++ { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, USE_FSR), ++ PARAMS(micron_4k) }, + + /* 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) }, ++ { "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) }, ++ { "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64, SECT_4K) }, + + /* 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) }, ++ { "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) }, ++ { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, ++ SPI_NOR_4B_OPCODES), PARAMS(spansion) }, ++ { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, ++ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, ++ { "s25fl127s/129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, ++ SECT_4K), PARAMS(spansion) }, + { "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) }, ++ { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K ++ |SPI_NOR_DUAL_READ | 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) }, ++ { "w25x16/s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, ++ SECT_4K), PARAMS(winbond) }, ++ /* { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, 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) }, + + /* SST -- large erase sizes are "overlays", "sectors" are 4K */ + { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, +@@ -972,43 +1322,56 @@ static const struct flash_info spi_nor_ids[] = { + { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) }, + { "m25px80", INFO(0x207114, 0, 64 * 1024, 16, 0) }, + +- /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ ++ /* Winbond 3.3V-- 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) }, ++ { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K ++ | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "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) +- }, ++ { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, ++ SECT_4K), PARAMS(winbond) }, + { "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) +- }, ++ { "w25q64/s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, ++ SECT_4K), PARAMS(winbond) }, + { "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) }, ++ { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, ++ SECT_4K), PARAMS(winbond) }, ++ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, ++ SECT_4K), PARAMS(winbond) }, ++ /* Winbond 1.8V */ ++ { "w25q32fw", INFO(0xef6016, 0, 64 * 1024, 64, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | ++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB), PARAMS(winbond) }, ++ { "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), PARAMS(winbond) }, ++ { "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), PARAMS(winbond) }, ++ { "w25q256jw", INFO(0xef8019, 0, 64 * 1024, 512, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | ++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4B_OPCODES), ++ PARAMS(winbond) }, + + /* 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) }, ++ { "cat25c03", CAT25_INFO(32, 8, 16, 2, SPI_NOR_NO_ERASE ++ | SPI_NOR_NO_FR) }, ++ { "cat25c09", CAT25_INFO(28, 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) }, ++ /* Paragon 3.3V */ ++ { "pn25f16s", INFO(0xe04015, 0, 64 * 1024, 32, 0), PARAMS(paragon) }, ++ { "pn25f32s", INFO(0xe04016, 0, 64 * 1024, 64, 0), PARAMS(paragon) }, ++ + { }, + }; + +@@ -1024,6 +1387,11 @@ static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) + return ERR_PTR(tmp); + } + ++ if ((id[0] == 0xff) || (id[0] == 0x00)) { ++ dev_err(nor->dev, "unrecognized Manufacturer ID\n"); ++ return ERR_PTR(-ENODEV); ++ } ++ + for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { + info = &spi_nor_ids[tmp]; + if (info->id_len) { +@@ -1167,14 +1535,22 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, + ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE); + if (ret) + return ret; ++#ifdef CONFIG_HISI_SPI_BLOCK_PROTECT ++ if (nor->level && (to < nor->end_addr)) { ++ dev_err(nor->dev, "Error: The DMA write area was locked\n"); ++ return -EINVAL; ++ } ++#endif + + for (i = 0; i < len; ) { + ssize_t written; + + page_offset = (to + i) & (nor->page_size - 1); ++#ifndef CONFIG_SPI_HISI_SFC + 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); ++#endif + /* the size of data remaining on the first page */ + page_remain = min_t(size_t, + nor->page_size - page_offset, len - i); +@@ -1211,15 +1587,22 @@ static int macronix_quad_enable(struct spi_nor *nor) + val = read_sr(nor); + if (val < 0) + return val; ++ ++ if ((unsigned int)val & SR_QUAD_EN_MX) ++ return 0; ++ ++ /* Update the Quad Enable bit. */ ++ dev_dbg(nor->dev, "setting Macronix Quad Enable (non-volatile) bit\n"); ++ + write_enable(nor); + +- write_sr(nor, val | SR_QUAD_EN_MX); ++ write_sr(nor, (u8)val | SR_QUAD_EN_MX); + + if (spi_nor_wait_till_ready(nor)) + return 1; + + ret = read_sr(nor); +- if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) { ++ if (!(ret > 0 && ((unsigned int)ret & SR_QUAD_EN_MX))) { + dev_err(nor->dev, "Macronix Quad bit not set\n"); + return -EINVAL; + } +@@ -1244,28 +1627,131 @@ static int write_sr_cr(struct spi_nor *nor, u16 val) + static int spansion_quad_enable(struct spi_nor *nor) + { + int ret; +- int quad_en = CR_QUAD_EN_SPAN << 8; ++ u16 val; ++ ++ ret = read_cr(nor); ++ if (ret & CR_QUAD_EN_SPAN) ++ return 0; ++ ++ /* Update the Quad Enable bit. */ ++ dev_dbg(nor->dev, "setting Quad Enable (non-volatile) bit\n"); ++ ++ val = ((ret & 0xff) | CR_QUAD_EN_SPAN) << 8; ++ ++ ret = read_sr(nor); ++ val |= (ret & 0xff); + + write_enable(nor); + +- ret = write_sr_cr(nor, quad_en); ++ ret = write_sr_cr(nor, val); + if (ret < 0) { + dev_err(nor->dev, + "error while writing configuration register\n"); + return -EINVAL; + } + ++ if (spi_nor_wait_till_ready(nor)) ++ return 1; ++ ++ /* read back and check it */ ++ ret = read_cr(nor); ++ if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) { ++ dev_err(nor->dev, "Spansion Quad bit not set\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int micron_quad_enable(struct spi_nor *nor) ++{ ++ int ret; ++ u8 val; ++ ++ ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1); ++ if (ret < 0) { ++ dev_err(nor->dev, "error %d reading EVCR\n", ret); ++ return ret; ++ } ++ ++ write_enable(nor); ++ ++ /* set EVCR, enable quad I/O */ ++ nor->cmd_buf[0] = val & ~EVCR_QUAD_EN_MICRON; ++ ret = nor->write_reg(nor, SPINOR_OP_WD_EVCR, nor->cmd_buf, 1); ++ if (ret < 0) { ++ dev_err(nor->dev, "error while writing EVCR register\n"); ++ return ret; ++ } ++ + ret = spi_nor_wait_till_ready(nor); +- if (ret) { ++ if (ret) ++ return ret; ++ ++ /* read EVCR and check it */ ++ ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1); ++ if (ret < 0) { ++ dev_err(nor->dev, "error %d reading EVCR\n", ret); ++ return ret; ++ } ++ if (val & EVCR_QUAD_EN_MICRON) { ++ dev_err(nor->dev, "Micron EVCR Quad bit not clear\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int gd_quad_enable(struct spi_nor *nor) ++{ ++ int ret; ++ u16 val; ++ ++ /* First, Quad Enable for 16-Pin GD flash, use WRSR[01h] cmd */ ++ ret = read_cr(nor); ++ val = ((ret & 0xff) | CR_QUAD_EN_SPAN) << 8; ++ ++ ret = read_sr(nor); ++ val |= (ret & 0xff); ++ ++ write_enable(nor); ++ ++ ret = write_sr_cr(nor, val); ++ if (ret < 0) { + dev_err(nor->dev, +- "timeout while writing configuration register\n"); ++ "error while writing config and status register\n"); ++ return -EINVAL; ++ } ++ ++ if (spi_nor_wait_till_ready(nor)) ++ return 1; ++ ++ /* read back and check it */ ++ ret = read_cr(nor); ++ if (ret & CR_QUAD_EN_SPAN) ++ return 0; ++ ++ /* Second, Quad Enable for 8-Pin GD flash, use WRCR[31h] cmd */ ++ ret = read_sr(nor); ++ if (!(ret & SR_WEL)) ++ write_enable(nor); ++ ++ ret = read_cr(nor); ++ nor->cmd_buf[0] = (ret & 0xff) | CR_QUAD_EN_SPAN; ++ ++ ret = nor->write_reg(nor, SPINOR_OP_WRCR, nor->cmd_buf, 1); ++ if (ret < 0) { ++ dev_err(nor->dev, "error while writing config register\n"); + return ret; + } + ++ if (spi_nor_wait_till_ready(nor)) ++ return 1; ++ + /* read back and check it */ + ret = read_cr(nor); + if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) { +- dev_err(nor->dev, "Spansion Quad bit not set\n"); ++ dev_err(nor->dev, "GigaDevice Quad bit not set\n"); + return -EINVAL; + } + +@@ -1277,6 +1763,7 @@ static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info) + int status; + + switch (JEDEC_MFR(info)) { ++ case SNOR_MFR_ESMT: + case SNOR_MFR_MACRONIX: + status = macronix_quad_enable(nor); + if (status) { +@@ -1285,7 +1772,19 @@ static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info) + } + return status; + case SNOR_MFR_MICRON: +- return 0; ++ status = micron_quad_enable(nor); ++ if (status) { ++ dev_err(nor->dev, "Micron quad-read not enabled\n"); ++ return -EINVAL; ++ } ++ return status; ++ case SNOR_MFR_GD: ++ status = gd_quad_enable(nor); ++ if (status) { ++ dev_err(nor->dev, "GD quad-read not enabled\n"); ++ return -EINVAL; ++ } ++ return status; + default: + status = spansion_quad_enable(nor); + if (status) { +@@ -1307,8 +1806,350 @@ static int spi_nor_check(struct spi_nor *nor) + return 0; + } + +-int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) ++#ifdef CONFIG_HISI_SPI_BLOCK_PROTECT ++static void spi_lock_update_address(struct spi_nor *nor, const struct flash_info *info) ++{ ++ unsigned int lock_level_max, sectorsize, chipsize; ++ ++ if (!nor->level) { ++ nor->end_addr = 0; ++ dev_warn(nor->dev, "all blocks is unlocked.\n"); ++ return; ++ } ++ ++ sectorsize = info->sector_size; ++ chipsize = sectorsize * info->n_sectors; ++ lock_level_max = nor->lock_level_max; ++ ++ switch (JEDEC_MFR(info)) { ++ case SNOR_MFR_MACRONIX: ++ if (chipsize == _2M) { ++ if ((nor->level != lock_level_max) ++ && (nor->level != 1)) ++ nor->end_addr = chipsize - (sectorsize << ++ (lock_level_max - nor->level - 1)); ++ else ++ nor->end_addr = chipsize; ++ return; ++ } ++ ++ if (chipsize != _8M) ++ break; ++ case SNOR_MFR_ESMT: ++ /* this case is for ESMT and MXIC 8M devices */ ++ if (nor->level != lock_level_max) ++ nor->end_addr = chipsize - (sectorsize ++ << (lock_level_max - nor->level)); ++ else ++ nor->end_addr = chipsize; ++ return; ++ case SNOR_MFR_EON: ++ if (nor->level != lock_level_max) ++ nor->end_addr = chipsize - (sectorsize ++ << (nor->level - 1)); ++ else ++ nor->end_addr = chipsize; ++ return; ++ default: ++ break; ++ } ++ ++ /* general case */ ++ nor->end_addr = chipsize >> (lock_level_max - nor->level); ++} ++ ++static unsigned char hisi_bp_to_level(struct spi_nor *nor, ++ const struct flash_info *info, unsigned int bp_num) ++{ ++ int ret; ++ unsigned char val; ++ unsigned char level; ++ unsigned int chipsize; ++ ++ ret = spi_nor_wait_till_ready(nor); ++ BUG_ON(ret); ++ ++ ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val, 1); ++ if (ret < 0) { ++ dev_err(nor->dev, "error %d reading SR\n", ret); ++ return ret; ++ } ++ ++ if (bp_num == BP_NUM_3) ++ level = (val & SPI_NOR_SR_BP_MASK_3) >> SPI_NOR_SR_BP0_SHIFT; ++ else ++ level = (val & SPI_NOR_SR_BP_MASK_4) >> SPI_NOR_SR_BP0_SHIFT; ++ ++ dev_dbg(nor->dev, "the current level[%d]\n", level); ++ ++ if (bp_num == BP_NUM_4) { ++ nor->lock_level_max = LOCK_LEVEL_MAX(bp_num) - 5; ++ chipsize = info->sector_size * info->n_sectors; ++ if ((JEDEC_MFR(info) == SNOR_MFR_MACRONIX) ++ && (chipsize == _16M)) ++ nor->lock_level_max--; ++ } else ++ nor->lock_level_max = LOCK_LEVEL_MAX(bp_num); ++ dev_dbg(nor->dev, "Get the max bp level: [%d]\n", ++ nor->lock_level_max); ++ ++ return level; ++} ++ ++static void hisi_get_spi_lock_info(struct spi_nor *nor, const struct flash_info *info) ++{ ++ unsigned int chipsize; ++ struct device *dev = nor->dev; ++ ++ chipsize = info->sector_size * info->n_sectors; ++ ++ /* read the BP bit in RDSR to check whether nor is lock or not */ ++ switch (JEDEC_MFR(info)) { ++ case SNOR_MFR_GD: ++ case SNOR_MFR_ESMT: ++ case SNOR_MFR_EON: ++ case SNOR_MFR_SPANSION: ++ /* BP bit convert to lock level */ ++ nor->level = hisi_bp_to_level(nor, info, BP_NUM_3); ++ break; ++ case SNOR_MFR_WINBOND: ++ /* BP bit convert to lock level */ ++ if (chipsize <= _16M) ++ nor->level = hisi_bp_to_level(nor, info, BP_NUM_3); ++ else ++ nor->level = hisi_bp_to_level(nor, info, BP_NUM_4); ++ break; ++ case SNOR_MFR_MACRONIX: ++ /* BP bit convert to lock level */ ++ if (chipsize <= _8M) ++ nor->level = hisi_bp_to_level(nor, info, BP_NUM_3); ++ else ++ nor->level = hisi_bp_to_level(nor, info, BP_NUM_4); ++ break; ++ default: ++ goto usage; ++ } ++ ++ spi_lock_update_address(nor, info); ++ if (nor->end_addr) ++ dev_info(dev, "Address range [0 => %#x] is locked.\n", ++ nor->end_addr); ++ return; ++usage: ++ dev_err(dev, "The ID: %#x isn't in the BP table," ++ " Current device can't not protect\n", ++ JEDEC_MFR(info)); ++} ++#endif/* CONFIG_HISI_SPI_BLOCK_PROTECT */ ++ ++static int spi_nor_midx2proto(int midx, enum spi_nor_protocol *proto) ++{ ++ switch (midx) { ++ case SNOR_MIDX_SLOW: ++ case SNOR_MIDX_1_1_1: ++ *proto = SNOR_PROTO_1_1_1; ++ break; ++ ++ case SNOR_MIDX_1_1_2: ++ *proto = SNOR_PROTO_1_1_2; ++ break; ++ ++ case SNOR_MIDX_1_2_2: ++ *proto = SNOR_PROTO_1_2_2; ++ break; ++ case SNOR_MIDX_1_1_4: ++ *proto = SNOR_PROTO_1_1_4; ++ break; ++ ++ case SNOR_MIDX_1_4_4: ++ *proto = SNOR_PROTO_1_4_4; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int spi_nor_sr3_to_reset(struct spi_nor *nor) + { ++ int ret; ++ unsigned char val; ++ ++ ret = nor->read_reg(nor, SPINOR_OP_RDSR3, &val, 1); ++ if (ret < 0) { ++ dev_err(nor->dev, "error %d reading Status Reg 3.\n", ret); ++ return ret; ++ } ++ ++ if (SPI_NOR_GET_RST(val)) { ++ dev_dbg(nor->dev, "Device has worked on RESET#.\n"); ++ return 0; ++ } ++ ++ dev_dbg(nor->dev, "Start to enable RESET# function.\n"); ++ val = SPI_NOR_SET_RST(val); ++ ++ nor->write_reg(nor, SPINOR_OP_WRSR3, &val, 1); ++ if (ret < 0) { ++ dev_err(nor->dev, "error while writing Status Reg 3.\n"); ++ return ret; ++ } ++ ++ dev_dbg(nor->dev, "Enable RESET# function success.\n"); ++ ++ return 0; ++} ++ ++static int spi_nor_reset_pin_enable(struct spi_nor *nor, ++ const struct flash_info *info) ++{ ++ switch (JEDEC_MFR(info)) { ++ case SNOR_MFR_WINBOND: ++ case SNOR_MFR_GD: ++ return spi_nor_sr3_to_reset(nor); ++ default: ++ return 0; ++ } ++} ++ ++static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info, ++ const struct spi_nor_basic_flash_parameter *params, ++ const struct spi_nor_modes *modes) ++{ ++ bool enable_quad_io; ++ u32 rd_modes, wr_modes; ++ const struct spi_nor_erase_type *erase_type; ++ const struct spi_nor_read_op *read; ++ int rd_midx, wr_midx, err = 0; ++ ++ rd_modes = modes->rd_modes; ++ wr_modes = modes->wr_modes; ++ ++ /* Setup read operation. */ ++ rd_midx = fls(params->rd_modes & rd_modes) - 1; ++ if (spi_nor_midx2proto(rd_midx, &nor->read_proto)) { ++ dev_err(nor->dev, "invalid (fast) read\n"); ++ return -EINVAL; ++ } ++ read = ¶ms->reads[rd_midx]; ++ nor->read_opcode = read->opcode; ++ nor->read_dummy = read->num_mode_clocks + read->num_wait_states; ++ ++ /* Set page program op code and protocol. */ ++ wr_midx = fls(params->wr_modes & wr_modes) - 1; ++ if (spi_nor_midx2proto(wr_midx, &nor->write_proto)) { ++ dev_err(nor->dev, "invalid page program\n"); ++ return -EINVAL; ++ } ++ nor->program_opcode = params->page_programs[wr_midx]; ++ ++ /* Set sector erase op code and size. */ ++ erase_type = ¶ms->erase_types[0]; ++#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS ++ for (i = 1; i < SNOR_MAX_ERASE_TYPES; ++i) ++ if (params->erase_types[i].size == 0x0c) ++ erase_type = ¶ms->erase_types[i]; ++#endif ++ nor->erase_opcode = erase_type->opcode; ++ nor->mtd.erasesize = (1 << erase_type->size); ++ ++ enable_quad_io = (SNOR_PROTO_DATA_FROM_PROTO(nor->read_proto) == 4 || ++ SNOR_PROTO_DATA_FROM_PROTO(nor->write_proto) == 4); ++ ++ /* Enable Quad I/O if needed. */ ++ if (enable_quad_io && params->enable_quad_io) { ++ err = params->enable_quad_io(nor); ++ if (err) { ++ dev_err(nor->dev, ++ "failed to enable the Quad I/O mode\n"); ++ return err; ++ } ++ } ++ ++ /* ++ * Fix erase protocol if needed, read and write protocols should ++ * already be valid. ++ */ ++ nor->erase_proto = SNOR_PROTO_1_1_1; ++ ++ dev_dbg(nor->dev, ++ "(Fast) Read: opcode=%02Xh, protocol=%03x, mode=%u, wait=%u\n", ++ nor->read_opcode, nor->read_proto, ++ read->num_mode_clocks, read->num_wait_states); ++ dev_dbg(nor->dev, ++ "Page Program: opcode=%02Xh, protocol=%03x\n", ++ nor->program_opcode, nor->write_proto); ++ dev_dbg(nor->dev, ++ "Sector Erase: opcode=%02Xh, protocol=%03x, sector size=%zu\n", ++ nor->erase_opcode, nor->erase_proto, (size_t)nor->mtd.erasesize); ++ ++ return 0; ++} ++ ++static int spi_nor_config(struct spi_nor *nor, const struct flash_info *info, ++ const struct spi_nor_basic_flash_parameter *params, ++ struct spi_nor_modes *modes) ++{ ++ int ret; ++ ++ if (params) { ++ ret = spi_nor_setup(nor, info, params, modes); ++ if (ret) ++ return ret; ++ } else if (modes->rd_modes & SNOR_MODE_1_1_4 && ++ info->flags & SPI_NOR_QUAD_READ) { ++ /* ++ * This branch is spcially for some devices which can ++ * not be stated by params, but only SPI_NOR_QUAD_READ, ++ * it just supports the protocol 1_1_4. ++ */ ++ if (spi_nor_wait_till_ready(nor)) ++ return 1; ++ ++ ret = set_quad_mode(nor, info); ++ if (ret) { ++ dev_err(nor->dev, "quad mode not supported\n"); ++ return ret; ++ } ++ nor->read_proto = SNOR_PROTO_1_1_4; ++ nor->read_opcode = SPINOR_OP_READ_1_1_4; ++ nor->read_dummy = 8; ++ } else if (modes->rd_modes & SNOR_MODE_1_1_2 && ++ info->flags & SPI_NOR_DUAL_READ) { ++ /* ++ * This branch is spcially for some devices which can ++ * not be stated by params, but only SPI_NOR_DUAL_READ, ++ * it just supports the protocol 1_1_2. ++ */ ++ nor->read_proto = SNOR_PROTO_1_1_2; ++ nor->read_opcode = SPINOR_OP_READ_1_1_2; ++ nor->read_dummy = 8; ++ } else { ++ if (modes->rd_modes & SNOR_MODE_1_1_1) { ++ nor->read_opcode = SPINOR_OP_READ_FAST; ++ nor->read_dummy = 8; ++ } else { ++ nor->read_opcode = SPINOR_OP_READ; ++ nor->read_dummy = 0; ++ } ++ } ++ ++ if (!(modes->rd_modes & (SNOR_MODE_1_1_4 | SNOR_MODE_1_4_4))) { ++ ret = spi_nor_reset_pin_enable(nor, info); ++ if (ret < 0) { ++ dev_err(nor->dev, "Enable RESET# fail.\n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++int spi_nor_scan(struct spi_nor *nor, const char *name, ++ struct spi_nor_modes *modes) ++{ ++ const struct spi_nor_basic_flash_parameter *params = NULL; + const struct flash_info *info = NULL; + struct device *dev = nor->dev; + struct mtd_info *mtd = &nor->mtd; +@@ -1320,11 +2161,19 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) + if (ret) + return ret; + ++ /* Reset SPI protocol for all commands */ ++ nor->erase_proto = SNOR_PROTO_1_1_1; ++ nor->read_proto = SNOR_PROTO_1_1_1; ++ nor->write_proto = SNOR_PROTO_1_1_1; ++ + if (name) + info = spi_nor_match_id(name); + /* Try to auto-detect if chip name wasn't specified or not found */ +- if (!info) ++ if (!info) { ++ dev_info(dev, "SPI Nor ID Table Version %s\n", SPI_NOR_IDS_VER); + info = spi_nor_read_id(nor); ++ } ++ + if (IS_ERR_OR_NULL(info)) + return -ENOENT; + +@@ -1351,9 +2200,15 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) + info = jinfo; + } + } ++ if (info->params) ++ params = info->params; + + mutex_init(&nor->lock); + ++#ifdef CONFIG_HISI_SPI_BLOCK_PROTECT ++ /* NOR block protection support */ ++ hisi_get_spi_lock_info(nor, info); ++#else + /* + * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up + * with the software protection bits set +@@ -1367,6 +2222,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) + write_sr(nor, 0); + spi_nor_wait_till_ready(nor); + } ++#endif + + if (!mtd->name) + mtd->name = dev_name(dev); +@@ -1380,7 +2236,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) + + /* NOR protection support for STmicro/Micron chips and similar */ + if (JEDEC_MFR(info) == SNOR_MFR_MICRON || +- info->flags & SPI_NOR_HAS_LOCK) { ++ JEDEC_MFR(info) == SNOR_MFR_WINBOND || ++ info->flags & SPI_NOR_HAS_LOCK) { + nor->flash_lock = stm_lock; + nor->flash_unlock = stm_unlock; + nor->flash_is_locked = stm_is_locked; +@@ -1428,77 +2285,40 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) + if (np) { + /* If we were instantiated by DT, use it */ + if (of_property_read_bool(np, "m25p,fast-read")) +- nor->flash_read = SPI_NOR_FAST; ++ modes->rd_modes |= SNOR_MODE_1_1_1; + else +- nor->flash_read = SPI_NOR_NORMAL; ++ modes->rd_modes &= ~SNOR_MODE_1_1_1; + } else { + /* If we weren't instantiated by DT, default to fast-read */ +- nor->flash_read = SPI_NOR_FAST; ++ modes->rd_modes |= SNOR_MODE_1_1_1; + } + + /* Some devices cannot do fast-read, no matter what DT tells us */ + if (info->flags & SPI_NOR_NO_FR) +- nor->flash_read = SPI_NOR_NORMAL; +- +- /* Quad/Dual-read mode takes precedence over fast/normal */ +- if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) { +- ret = set_quad_mode(nor, info); +- if (ret) { +- dev_err(dev, "quad mode not supported\n"); +- return ret; +- } +- nor->flash_read = SPI_NOR_QUAD; +- } else if (mode == SPI_NOR_DUAL && info->flags & SPI_NOR_DUAL_READ) { +- nor->flash_read = SPI_NOR_DUAL; +- } +- +- /* Default commands */ +- switch (nor->flash_read) { +- case SPI_NOR_QUAD: +- nor->read_opcode = SPINOR_OP_READ_1_1_4; +- break; +- case SPI_NOR_DUAL: +- nor->read_opcode = SPINOR_OP_READ_1_1_2; +- break; +- case SPI_NOR_FAST: +- nor->read_opcode = SPINOR_OP_READ_FAST; +- break; +- case SPI_NOR_NORMAL: +- nor->read_opcode = SPINOR_OP_READ; +- break; +- default: +- dev_err(dev, "No Read opcode defined\n"); +- return -EINVAL; +- } ++ modes->rd_modes &= ~SNOR_MODE_1_1_1; + + nor->program_opcode = SPINOR_OP_PP; + ++ /* ++ * Configure the SPI memory: ++ * - select op codes for (Fast) Read, Page Program and Sector Erase. ++ * - set the number of dummy cycles (mode cycles + wait states). ++ * - set the SPI protocols for register and memory accesses. ++ * - set the Quad Enable bit if needed (required by SPI x-y-4 protos). ++ */ ++ ret = spi_nor_config(nor, info, params, modes); ++ if (ret) ++ return ret; ++ + if (info->addr_width) + nor->addr_width = info->addr_width; + else if (mtd->size > 0x1000000) { + /* enable 4-byte addressing if the device exceeds 16MiB */ + nor->addr_width = 4; +- if (JEDEC_MFR(info) == SNOR_MFR_SPANSION) { +- /* Dedicated 4-byte command set */ +- switch (nor->flash_read) { +- case SPI_NOR_QUAD: +- nor->read_opcode = SPINOR_OP_READ4_1_1_4; +- break; +- case SPI_NOR_DUAL: +- nor->read_opcode = SPINOR_OP_READ4_1_1_2; +- break; +- case SPI_NOR_FAST: +- nor->read_opcode = SPINOR_OP_READ4_FAST; +- break; +- case SPI_NOR_NORMAL: +- nor->read_opcode = SPINOR_OP_READ4; +- break; +- } +- nor->program_opcode = SPINOR_OP_PP_4B; +- /* No small sector erase for 4-byte command set */ +- nor->erase_opcode = SPINOR_OP_SE_4B; +- mtd->erasesize = info->sector_size; +- } else ++ if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || ++ info->flags & SPI_NOR_4B_OPCODES) ++ spi_nor_set_4byte_opcodes(nor, info); ++ else + set_4byte(nor, info, 1); + } else { + nor->addr_width = 3; +@@ -1510,10 +2330,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) + return -EINVAL; + } + +- nor->read_dummy = spi_nor_read_dummy_cycles(nor); +- +- dev_info(dev, "%s (%lld Kbytes)\n", info->name, +- (long long)mtd->size >> 10); ++ dev_info(dev, "%s (Chipsize %lld Mbytes, Blocksize %uKiB)\n", ++ info->name, (long long)mtd->size >> 20, mtd->erasesize / 1024); + + dev_dbg(dev, + "mtd .name = %s, .size = 0x%llx (%lldMiB), " +@@ -1547,6 +2365,64 @@ static const struct flash_info *spi_nor_match_id(const char *name) + return NULL; + } + ++/******************************************************************************/ ++void spi_nor_driver_shutdown(struct spi_nor *nor) ++{ ++ /* disable 4-byte addressing if the device exceeds 16MiB */ ++ if (nor->addr_width == 4) { ++ const struct flash_info *info = NULL; ++ ++ info = spi_nor_read_id(nor); ++ set_4byte(nor, info, 0); ++ } ++ return; ++} ++ ++#ifdef CONFIG_PM ++/******************************************************************************/ ++int spi_nor_suspend(struct spi_nor *nor, pm_message_t state) ++{ ++ return spi_nor_wait_till_ready(nor); ++} ++ ++/******************************************************************************/ ++int spi_nor_resume(struct spi_nor *nor) ++{ ++ int ret; ++ const struct flash_info *info = NULL; ++ const struct spi_nor_basic_flash_parameter *params = NULL; ++ struct spi_nor_modes modes = { ++ .rd_modes = SNOR_MODE_SLOW, ++ .wr_modes = SNOR_MODE_1_1_1, ++ }; ++ ++ modes.rd_modes |= SNOR_MODE_1_1_1 ++ | SNOR_MODE_1_1_2 ++ | SNOR_MODE_1_2_2; ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ modes.rd_modes |= SNOR_MODE_1_1_4 | SNOR_MODE_1_4_4; ++ modes.wr_modes |= SNOR_MODE_1_1_4 | SNOR_MODE_1_4_4; ++#endif ++ ++ if (!info) ++ info = spi_nor_read_id(nor); ++ ++ /* Quad mode takes precedence over fast/normal */ ++ if (info->params) ++ params = info->params; ++ ++ ret = spi_nor_config(nor, info, params, &modes); ++ if (ret) ++ return ret; ++ ++ /* enable 4-byte addressing if the device exceeds 16MiB */ ++ if (nor->addr_width == 4 && JEDEC_MFR(info) != SNOR_MFR_SPANSION) ++ set_4byte(nor, info, 1); ++ ++ return 0; ++} ++#endif /* End of CONFIG_PM */ ++ + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Huang Shijie "); + MODULE_AUTHOR("Mike Lavender"); +diff --git a/drivers/mtd/spi-nor/spi_ids.c b/drivers/mtd/spi-nor/spi_ids.c +new file mode 100644 +index 0000000..de56dab +--- /dev/null ++++ b/drivers/mtd/spi-nor/spi_ids.c +@@ -0,0 +1,254 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++ ++#include ++#include ++#include ++ ++#include "spi_ids.h" ++ ++#define SPI_DRV_VERSION "1.22" ++/*****************************************************************************/ ++ ++#if 1 ++# define DBG_MSG(_fmt, arg...) ++#else ++# define DBG_MSG(_fmt, arg...) \ ++ printk(KERN_DEBUG "%s(%d): " _fmt, __FILE__, __LINE__, ##arg); ++#endif ++ ++#define DBG_BUG(fmt, args...) do {\ ++ printk(KERN_DEBUG "%s(%d): BUG !!! " fmt, __FILE__, __LINE__, ##args); \ ++ while (1)\ ++ ;\ ++} while (0) ++ ++/*****************************************************************************/ ++static char *int_to_size(unsigned long long size) ++{ ++ int ix; ++ static char buffer[20]; ++ char *fmt[] = {"%u", "%uK", "%uM", "%uG", "%uT", "%uT"}; ++ ++ for (ix = 0; (ix < 5) && !(size & 0x3FF) && size; ix++) ++ size = (size >> 10); ++ ++ sprintf(buffer, fmt[ix], size); ++ return buffer; ++} ++/*****************************************************************************/ ++ ++struct spi_info *spi_serach_ids(unsigned char ids[8]) ++{ ++ struct spi_info *info; ++ struct spi_info *fit_info = NULL; ++ ++ for (info = spi_info_table; info->name; info++) { ++ if (memcmp(info->id, ids, info->id_len)) ++ continue; ++ ++ if ((fit_info == NULL) || (fit_info->id_len < info->id_len)) ++ fit_info = info; ++ } ++ return fit_info; ++} ++/*****************************************************************************/ ++ ++void spi_search_rw(struct spi_info *spiinfo, struct spi_operation *spiop_rw, ++ unsigned int iftype, unsigned int max_dummy, int is_read) ++{ ++ int ix = 0; ++ struct spi_operation **spiop, **fitspiop; ++ ++ for (fitspiop = spiop = (is_read ? spiinfo->read : spiinfo->write); ++ (*spiop) && ix < MAX_SPI_OP; spiop++, ix++) { ++ DBG_MSG("dump[%d] %s iftype:0x%02X\n", ix, ++ (is_read ? "read" : "write"), ++ (*spiop)->iftype); ++ ++ if (((*spiop)->iftype & iftype) ++ && ((*spiop)->dummy <= max_dummy) ++ && (*fitspiop)->iftype < (*spiop)->iftype) { ++ fitspiop = spiop; ++ } ++ } ++ memcpy(spiop_rw, (*fitspiop), sizeof(struct spi_operation)); ++} ++/*****************************************************************************/ ++#ifndef CONFIG_MTD_HISFC300 ++void spi_get_erase(struct spi_info *spiinfo, struct spi_operation *spiop_erase) ++{ ++ int ix; ++ ++ spiop_erase->size = 0; ++ for (ix = 0; ix < MAX_SPI_OP; ix++) { ++ if (spiinfo->erase[ix] == NULL) ++ break; ++ if (spiinfo->erasesize == spiinfo->erase[ix]->size) { ++ memcpy(&spiop_erase[ix], spiinfo->erase[ix], ++ sizeof(struct spi_operation)); ++ ++ break; ++ } ++ } ++} ++#endif ++/*****************************************************************************/ ++ ++struct spi_tag { ++ char name[16]; ++ ++ unsigned char id[8]; ++ unsigned int id_len; ++ ++ unsigned long chipsize; ++ unsigned int erasesize; ++ unsigned int addrcycle; ++ ++ struct spi_operation read[MAX_SPI_OP]; ++ struct spi_operation write[MAX_SPI_OP]; ++ struct spi_operation erase[MAX_SPI_OP]; ++}; ++/*****************************************************************************/ ++ ++static int __init parse_spi_id(const struct tag *tag) ++{ ++ int ix; ++ static struct spi_tag spitag[1]; ++ struct spi_info *spiinfo = spi_info_table; ++ ++ if (tag->hdr.size < ((sizeof(struct tag_header) + ++ sizeof(struct spi_tag)) >> 2)) { ++ printk(KERN_ERR "%s(%d):tag->hdr.size(%d) too small.\n", ++ __func__, __LINE__, tag->hdr.size); ++ return 0; ++ } ++ memset(spiinfo, 0, sizeof(struct spi_info)); ++ memcpy(spitag, &tag->u, sizeof(struct spi_tag)); ++ ++ spiinfo->name = spitag->name; ++ ++ memcpy(spiinfo->id, spitag->id, 8); ++ spiinfo->id_len = spitag->id_len; ++ ++ spiinfo->chipsize = spitag->chipsize; ++ spiinfo->erasesize = spitag->erasesize; ++ spiinfo->addrcycle = spitag->addrcycle; ++ ++ for (ix = 0; ix < MAX_SPI_OP; ix++) { ++ if (spitag->read[ix].iftype) ++ spiinfo->read[ix] = &spitag->read[ix]; ++ } ++ for (ix = 0; ix < MAX_SPI_OP; ix++) { ++ if (spitag->write[ix].iftype) ++ spiinfo->write[ix] = &spitag->write[ix]; ++ } ++ for (ix = 0; ix < MAX_SPI_OP; ix++) { ++ if (spitag->erase[ix].iftype) ++ spiinfo->erase[ix] = &spitag->erase[ix]; ++ } ++ ++ printk(KERN_NOTICE "SPI TAG: hdr.tag: 0x%08X, hdr.size: %d\n", ++ tag->hdr.tag, tag->hdr.size); ++ printk(KERN_NOTICE "(%dByte): 0x%02X 0x%02X 0x%02X 0x%02X " ++ "0x%02X 0x%02X 0x%02X 0x%02X\n", ++ spitag->id_len, ++ spitag->id[0], spitag->id[1], spitag->id[2], spitag->id[3], ++ spitag->id[4], spitag->id[5], spitag->id[6], spitag->id[7]); ++ printk(KERN_NOTICE "Block:%sB ", int_to_size(spitag->erasesize)); ++ printk(KERN_NOTICE "Chip:%sB ", int_to_size(spitag->chipsize)); ++ printk(KERN_NOTICE "AddrCycle:%d ", spitag->addrcycle); ++ printk(KERN_NOTICE "Name:(%s)", spitag->name); ++ printk(KERN_NOTICE "\n"); ++ for (ix = 0; ix < MAX_SPI_OP; ix++) { ++ if (spitag->read[ix].iftype) { ++ printk(KERN_NOTICE "R %d: ", ix + 1); ++ printk(KERN_NOTICE "IF Type:0x%02X ", ++ spitag->read[ix].iftype); ++ printk(KERN_NOTICE "CMD:0x%02X ", ++ spitag->read[ix].cmd); ++ printk(KERN_NOTICE "Dummy:%d ", ++ spitag->read[ix].dummy); ++ if (spitag->read[ix].size == INFINITE) ++ printk(KERN_NOTICE "Size:-1 "); ++ else ++ printk(KERN_NOTICE "Size:%6sB ", ++ int_to_size(spitag->read[ix].size)); ++ printk(KERN_NOTICE "Clock:%dMHz ", ++ spitag->read[ix].clock); ++ printk(KERN_NOTICE "\n"); ++ } ++ } ++ for (ix = 0; ix < MAX_SPI_OP; ix++) { ++ if (spitag->write[ix].iftype) { ++ printk(KERN_NOTICE "W %d: ", ix + 1); ++ printk(KERN_NOTICE "IF Type:0x%02X ", ++ spitag->write[ix].iftype); ++ printk(KERN_NOTICE "CMD:0x%02X ", ++ spitag->write[ix].cmd); ++ printk(KERN_NOTICE "Dummy:%d ", ++ spitag->write[ix].dummy); ++ printk(KERN_NOTICE "Size:%6sB ", ++ int_to_size(spitag->write[ix].size)); ++ printk(KERN_NOTICE "Clock:%dMHz ", ++ spitag->write[ix].clock); ++ printk(KERN_NOTICE "\n"); ++ } ++ } ++ for (ix = 0; ix < MAX_SPI_OP; ix++) { ++ if (spitag->erase[ix].iftype) { ++ printk(KERN_NOTICE "E %d: ", ix + 1); ++ printk(KERN_NOTICE "IF Type:0x%02X ", ++ spitag->erase[ix].iftype); ++ printk(KERN_NOTICE "CMD:0x%02X ", ++ spitag->erase[ix].cmd); ++ printk(KERN_NOTICE "Dummy:%d ", ++ spitag->erase[ix].dummy); ++ printk(KERN_NOTICE "Size:0x%02X ", ++ spitag->erase[ix].size); ++ printk(KERN_NOTICE "Clock:%dMHz ", ++ spitag->erase[ix].clock); ++ printk(KERN_NOTICE "\n"); ++ } ++ } ++ ++ return 0; ++} ++ ++/* turn to ascii is "S_ID" */ ++__tagtable(0x535F4944, parse_spi_id); ++/*****************************************************************************/ ++ ++static int __init spi_ids_init(void) ++{ ++ printk(KERN_INFO "Spi id table Version %s\n", SPI_DRV_VERSION); ++ return 0; ++} ++/*****************************************************************************/ ++ ++static void __exit spi_ids_exit(void) ++{ ++} ++/*****************************************************************************/ ++ ++module_init(spi_ids_init); ++module_exit(spi_ids_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("Spi id table"); +diff --git a/drivers/mtd/spi-nor/spi_ids.h b/drivers/mtd/spi-nor/spi_ids.h +new file mode 100644 +index 0000000..89fd8d9 +--- /dev/null ++++ b/drivers/mtd/spi-nor/spi_ids.h +@@ -0,0 +1,171 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef SPI_IDSH ++#define SPI_IDSH ++ ++/*****************************************************************************/ ++ ++#define _1K (0x400) ++#define _2K (0x800) ++ ++#define _4K (0x1000) ++#define _8K (0x2000) ++#define _16K (0x4000) ++#define _32K (0x8000) ++ ++#define _64K (0x10000) ++#define _128K (0x20000) ++#define _256K (0x40000) ++#define _512K (0x80000) ++ ++#define _1M (0x100000) ++#define _2M (0x200000) ++#define _4M (0x400000) ++#define _8M (0x800000) ++ ++#define _16M (0x1000000) ++#define _32M (0x2000000) ++#define _64M (0x4000000) ++ ++#define INFINITE (0xFFFFFFFF) ++/*****************************************************************************/ ++ ++#define SPI_IF_READ_STD (0x01) ++#define SPI_IF_READ_FAST (0x02) ++#define SPI_IF_READ_DUAL (0x04) ++#define SPI_IF_READ_DUAL_ADDR (0x08) ++#define SPI_IF_READ_QUAD (0x10) ++#define SPI_IF_READ_QUAD_ADDR (0x20) ++ ++#define SPI_IF_WRITE_STD (0x01) ++#define SPI_IF_WRITE_DUAL (0x02) ++#define SPI_IF_WRITE_DUAL_ADDR (0x04) ++#define SPI_IF_WRITE_QUAD (0x08) ++#define SPI_IF_WRITE_QUAD_ADDR (0x10) ++ ++#define SPI_IF_ERASE_SECTOR (0x01) /* sector erase, 64K */ ++#define SPI_IF_ERASE_CHIP (0x02) /* chip erase */ ++#define SPI_IF_ERASE_4K (0x04) /* 4K */ ++#define SPI_IF_ERASE_8K (0x08) /* 8K */ ++ ++#define SPI_IF_ERASE_SECTOR_4K (0x01) /* 4K */ ++#define SPI_IF_ERASE_SECTOR_32K (0x02) /* 32K */ ++#define SPI_IF_ERASE_SECTOR_64K (0x04) /* 64K */ ++#define SPI_IF_ERASE_SECTOR_128K (0x08) /* 128K */ ++#define SPI_IF_ERASE_SECTOR_256K (0x10) /* 256K */ ++/*****************************************************************************/ ++#define SPI_CMD_BRWR (0x17) /*write value to BAR*/ ++#define SPI_EN4B_VALUE (0x80) /*the enable 4Byte addr len value*/ ++#define SPI_EX4B_VALUE (0x00) /*the disable 4Byte addr len value*/ ++#define SPI_4BYTE_ADDR_LEN (4) /*address len 4Byte*/ ++/*****************************************************************************/ ++ ++#define SPI_CMD_WREN 0x06 /* Write Enable */ ++#define SPI_CMD_WRDI 0x04 /* Write Disable */ ++/*****************************************************************************/ ++#define SPI_CMD_SE_4K 0x20 /* 4KB sector Erase */ ++#define SPI_CMD_SE_32K 0x52 /* 32KB sector Erase */ ++ ++#define SPI_CMD_SE_64K 0xD8 /* 64KB sector Erase */ ++#define SPI_CMD_SE_128K 0xD8 /* 128KB sector Erase */ ++#define SPI_CMD_SE_256K 0xD8 /* 256KB sector Erase */ ++ ++#define SPI_CMD_SE 0xD8 /* 64KB Sector Erase */ ++#define SPI_CMD_BE 0xC7 /* chip erase */ ++/*****************************************************************************/ ++#define SPI_CMD_WRSR 0x01 /* Write Status Register */ ++#define SPI_CMD_WRSR2 0x31 /* Write Status Register-2 */ ++#define SPI_CMD_WRSR3 0x11 /* Write Status Register-3 */ ++ ++#define SPI_CMD_RDSR 0x05 /* Read Status Register */ ++#define SPI_CMD_RDSR2 0x35 /* Read Status Register-2 */ ++#define SPI_CMD_RDSR3 0x15 /* Read Status Register-3 */ ++ ++#define SPI_CMD_RDCR 0x35 /* Read Config Register */ ++ ++#define SPI_CMD_RDID 0x9F /* Read Identification */ ++/*****************************************************************************/ ++#define SPI_CMD_PP 0x02 /* Page Programming */ ++#define SPI_CMD_WRITE_DUAL 0xA2 /* fast program dual input */ ++#define SPI_CMD_WRITE_QUAD 0x32 /* fast program quad input */ ++#define SPI_CMD_WRITE_DUAL_ADDR 0xD2 /* Dual I/O High Performance Write */ ++#define SPI_CMD_WRITE_QUAD_ADDR 0x38 /* Quad I/O High Performance Write */ ++/* #define SPI_CMD_WRITE_QUAD_ADDR 0x12 Quad I/O High Performance Write */ ++/*****************************************************************************/ ++#define SPI_CMD_READ 0x03 /* Read Data bytes */ ++#define SPI_CMD_FAST_READ 0x0B /* Read Data Bytes at Higher Speed */ ++#define SPI_CMD_READ_DUAL 0x3B /* fast read dual output */ ++#define SPI_CMD_READ_QUAD 0x6B /* fast read quad output */ ++#define SPI_CMD_READ_DUAL_ADDR 0xBB /* Dual I/O High Performance Read */ ++#define SPI_CMD_READ_QUAD_ADDR 0xEB /* Quad I/O High Performance Read */ ++/*****************************************************************************/ ++#define SPI_CMD_SR_WIP 1 /* Write in Progress */ ++#define SPI_CMD_SR_WEL 2 /* Write Enable Latch */ ++ ++#define SPI_CMD_SR_QE (1 << 9) /* quad enable */ ++#define SPI_CMD_SR_XQE (0 << 9) /* quad disable */ ++/*****************************************************************************/ ++#define SPI_CMD_EN4B 0xB7 /* enter to 4 bytes mode and ++ set 4 byte bit as '1' */ ++#define SPI_CMD_EX4B 0xE9 /* exit 4 bytes mode and ++ clear 4 byte bit as '0' */ ++ ++/*****************************************************************************/ ++ ++struct spi_operation { ++ unsigned char iftype; ++ unsigned char cmd; ++ unsigned char dummy; ++ unsigned int size; ++ unsigned int clock; ++}; ++ ++struct spi_info { ++ char *name; ++ ++ unsigned char id[8]; ++ unsigned int id_len; ++ ++ unsigned long chipsize; ++ unsigned int erasesize; ++ unsigned int addrcycle; ++ ++#define MAX_SPI_OP (8) ++ struct spi_operation *read[8]; ++ struct spi_operation *write[8]; ++ struct spi_operation *erase[8]; ++#ifndef CONFIG_MTD_HISFC300 ++ struct spi_driver *driver; ++#endif ++}; ++/*****************************************************************************/ ++ ++struct spi_info *spi_serach_ids(unsigned char ids[8]); ++ ++void spi_search_rw(struct spi_info *spiinfo, struct spi_operation *spiop_rw, ++ unsigned int iftype, unsigned int max_dummy, int is_read); ++ ++#ifndef CONFIG_MTD_HISFC300 ++void spi_get_erase(struct spi_info *spiinfo, struct spi_operation *spiop_erase); ++#endif ++/******************************************************************************/ ++ ++extern struct spi_info spi_info_table[]; ++/******************************************************************************/ ++#endif /* SPI_IDSH */ +diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig +index d11287e..59133db 100644 +--- a/drivers/net/ethernet/hisilicon/Kconfig ++++ b/drivers/net/ethernet/hisilicon/Kconfig +@@ -76,4 +76,6 @@ config HNS_ENET + This selects the general ethernet driver for HNS. This module make + use of any HNS AE driver, such as HNS_DSAF + ++source "drivers/net/ethernet/hisilicon/higmac/Kconfig" ++ + endif # NET_VENDOR_HISILICON +diff --git a/drivers/net/ethernet/hisilicon/Makefile b/drivers/net/ethernet/hisilicon/Makefile +index 8661695..44e0c6b 100644 +--- a/drivers/net/ethernet/hisilicon/Makefile ++++ b/drivers/net/ethernet/hisilicon/Makefile +@@ -6,4 +6,5 @@ obj-$(CONFIG_HIX5HD2_GMAC) += hix5hd2_gmac.o + obj-$(CONFIG_HIP04_ETH) += hip04_eth.o + obj-$(CONFIG_HNS_MDIO) += hns_mdio.o + obj-$(CONFIG_HNS) += hns/ +-obj-$(CONFIG_HISI_FEMAC) += hisi_femac.o ++obj-$(CONFIG_HISI_FEMAC) += hisi-femac/ ++obj-$(CONFIG_HIETH_GMAC) += higmac/ +diff --git a/drivers/net/ethernet/hisilicon/higmac/Kconfig b/drivers/net/ethernet/hisilicon/higmac/Kconfig +new file mode 100644 +index 0000000..bda6f74 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/Kconfig +@@ -0,0 +1,96 @@ ++# ++# higmac family network device configuration ++# ++ ++menuconfig HIETH_GMAC ++ tristate "hieth gmac family network device support" ++ select PHYLIB ++ select RESET_CONTROLLER ++ help ++ This selects the hieth gmac family network device. ++ The gigabit switch fabric (GSF) receives and transmits data over Ethernet ++ ports at 10/100/1000 Mbit/s in full-duplex or half-duplex mode. ++ The Ethernet port exchanges data with the CPU port, and supports ++ the energy efficient Ethernet (EEE) and wake on LAN (WoL) functions. ++ ++if HIETH_GMAC ++ ++config HIGMAC_DESC_4WORD ++ bool "higmac descriptor size is 4 words" ++ default y ++ help ++ This define the size of higmac descriptor structure. ++ In the newest version, descriptor size is 4 words. ++ But in some old version, the size is 8 words. ++ The default value is true. ++ ++config HIGMAC_RXCSUM ++ bool "higmac Receive checksumming offload supported" ++ default y ++ help ++ This indicate MAC support Receive checksumming offload. ++ Support IPv4 and IPv6, tcp and udp. ++ The default value is enabled. ++ If old version MAC does not support, disable this option please. ++ ++config RX_FLOW_CTRL_SUPPORT ++ bool "rx flow ctrl supported" ++ default y ++ help ++ Rx flow ctrl supported, default is enabled. ++ When we received pause frame, ++ we will stop transmiting data frame for some time. ++ The stopping time is the time filled in pause frame. ++ ++config TX_FLOW_CTRL_SUPPORT ++ bool "tx flow ctrl supported" ++ default y ++ help ++ Tx flow ctrl supported, default is enabled. ++ When we has no buffer to receive packet, ++ we will send pause frame. ++ When buffer is available, we will send zero-quanta pause frame. ++ ++config TX_FLOW_CTRL_PAUSE_TIME ++ hex "tx flow ctrl pause time" ++ default "0xFFFF" ++ help ++ The pause time filled in the sending pause frame. ++ The unit is the time for transmiting 512 bit data. ++ This value is 16 bit, so its value is 0x0000~0xFFFF. ++ The default value is 0xFFFF. ++ ++config TX_FLOW_CTRL_PAUSE_INTERVAL ++ hex "tx flow ctrl pause interval" ++ default "0xFFFF" ++ help ++ The interval time for sending pause frame. ++ When the remainint amount of receive queue is below tx flow ctrl active threshold, ++ we will wait this time to transmiting pause frame. ++ The unit is the time for transmiting 512 bit data. ++ This value is 16 bit, so its value is 0x0000~0xFFFF. ++ The default value is 0xFFFF. ++ ++config TX_FLOW_CTRL_ACTIVE_THRESHOLD ++ int "tx flow ctrl active threshold" ++ default "16" ++ range 1 127 ++ help ++ The threshold for activing tx flow ctrl. ++ When the left amount of receive queue descriptors is below this threshold, ++ hardware will send pause frame immediately. ++ We advise this value is set smaller than 64. Too bigger is not a good choice. ++ This value must be smaller than tx flow ctrl deactive threshold. ++ ++config TX_FLOW_CTRL_DEACTIVE_THRESHOLD ++ int "tx flow ctrl deactive threshold" ++ default "32" ++ range 1 127 ++ help ++ The threshold for deactiving tx flow ctrl. ++ When the left amount of receive queue descriptors is above or equal with this threshold, ++ hardware will exit flow control state. ++ We advise this value is set smaller than 64. Too bigger is not a good choice. ++ This value must be larger than tx flow ctrl active threshold. ++ ++endif # HIETH_GMAC +diff --git a/drivers/net/ethernet/hisilicon/higmac/Makefile b/drivers/net/ethernet/hisilicon/higmac/Makefile +new file mode 100644 +index 0000000..e3d9c53 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/Makefile +@@ -0,0 +1,2 @@ ++obj-$(CONFIG_HIETH_GMAC) += hieth-gmac.o ++hieth-gmac-objs := board.o higmac.o autoeee/autoeee.o autoeee/phy_id_table.o +diff --git a/drivers/net/ethernet/hisilicon/higmac/autoeee/autoeee.c b/drivers/net/ethernet/hisilicon/higmac/autoeee/autoeee.c +new file mode 100644 +index 0000000..be12244 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/autoeee/autoeee.c +@@ -0,0 +1,125 @@ ++#include ++#include ++#include "../higmac.h" ++#include "autoeee.h" ++ ++void init_autoeee(struct higmac_netdev_local *ld) ++{ ++ int phy_id = ld->phy->phy_id; ++ struct phy_info *phy_info; ++ ++ if (ld->eee_init) ++ goto eee_init; ++ ++ phy_info = phy_search_ids(phy_id); ++ if (phy_info) { ++ int eee_available, lp_eee_capable, v; ++ u32 link_stat = 0; ++ ++ eee_available = phy_info->eee_available; ++ if (netif_msg_wol(ld)) ++ pr_info("fit phy_id:0x%x, phy_name:%s, eee:%d\n", ++ phy_info->phy_id, phy_info->name, ++ eee_available); ++ ++ if (!eee_available) ++ goto not_support; ++ ++ if (eee_available == PHY_EEE) { ++ if (netif_msg_wol(ld)) ++ pr_info("enter phy-EEE mode\n"); ++ ++ v = readl(ld->gmac_iobase + EEE_ENABLE); ++ v &= ~BIT_EEE_ENABLE; /* disable auto-EEE */ ++ writel(v, ld->gmac_iobase + EEE_ENABLE); ++ return; ++ } ++ ++ ld->eee_init = phy_info->eee_init; ++eee_init: ++ switch (ld->phy->speed) { ++ case SPEED_10: ++ link_stat |= HIGMAC_SPD_10M; ++ break; ++ case SPEED_100: ++ link_stat |= HIGMAC_SPD_100M; ++ break; ++ case SPEED_1000: ++ link_stat |= HIGMAC_SPD_1000M; ++ break; ++ default: ++ break; ++ } ++ ++ lp_eee_capable = ld->eee_init(ld->phy); ++ if (lp_eee_capable < 0) ++ return; ++ ++ if (ld->phy->link) { ++ if (((u32)lp_eee_capable) & link_stat) { ++ if ((phy_id & REALTEK_PHY_MASK) == ++ REALTEK_PHY_ID_8211E) { ++ v = readl(ld->gmac_iobase + EEE_CLK); ++ v &= ~MASK_EEE_CLK; ++ v |= BIT_DISABLE_TX_CLK; ++ writel(v, ld->gmac_iobase + EEE_CLK); ++ } else if ((phy_id & MICREL_PHY_ID_MASK) == ++ PHY_ID_KSZ9031) { ++ v = readl(ld->gmac_iobase + EEE_CLK); ++ v &= ~MASK_EEE_CLK; ++ v |= (BIT_DISABLE_TX_CLK | ++ BIT_PHY_KSZ9031); ++ writel(v, ld->gmac_iobase + EEE_CLK); ++ } ++ ++ /* EEE_1us: 0x7c for 125M */ ++ writel(0x7c, ld->gmac_iobase + ++ EEE_TIME_CLK_CNT); ++ writel(0x1e0400, ld->gmac_iobase + ++ EEE_TIMER);/* FIXME */ ++ ++ v = readl(ld->gmac_iobase + EEE_LINK_STATUS); ++ v |= 0x3 << 1; /* auto EEE and ... */ ++ v |= BIT_PHY_LINK_STATUS; /* phy linkup */ ++ writel(v, ld->gmac_iobase + EEE_LINK_STATUS); ++ ++ v = readl(ld->gmac_iobase + EEE_ENABLE); ++ v |= BIT_EEE_ENABLE; /* enable EEE */ ++ writel(v, ld->gmac_iobase + EEE_ENABLE); ++ ++ if (netif_msg_wol(ld)) ++ pr_info("enter auto-EEE mode\n"); ++ } else { ++ if (netif_msg_wol(ld)) ++ pr_info("link partner not support EEE\n"); ++ } ++ } else { ++ v = readl(ld->gmac_iobase + EEE_LINK_STATUS); ++ v &= ~(BIT_PHY_LINK_STATUS); /* phy linkdown */ ++ writel(v, ld->gmac_iobase + EEE_LINK_STATUS); ++ } ++ ++ return; ++ } ++ ++not_support: ++ ld->eee_init = NULL; ++ if (netif_msg_wol(ld)) ++ pr_info("non-EEE mode\n"); ++} ++ ++void eee_phy_linkdown(struct higmac_netdev_local *ld) ++{ ++ int v = readl(ld->gmac_iobase + EEE_LINK_STATUS); ++ /* update phy link state */ ++ v &= ~BIT_PHY_LINK_STATUS; ++ writel(v, ld->gmac_iobase + EEE_LINK_STATUS); ++} ++ ++void eee_phy_linkup(struct higmac_netdev_local *ld) ++{ ++ int v = readl(ld->gmac_iobase + EEE_LINK_STATUS); ++ /* update phy link state */ ++ v |= BIT_PHY_LINK_STATUS; ++ writel(v, ld->gmac_iobase + EEE_LINK_STATUS); ++} +diff --git a/drivers/net/ethernet/hisilicon/higmac/autoeee/autoeee.h b/drivers/net/ethernet/hisilicon/higmac/autoeee/autoeee.h +new file mode 100644 +index 0000000..8f75a7a +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/autoeee/autoeee.h +@@ -0,0 +1,42 @@ ++#ifndef _AUTO_EEE_H ++ ++#define NO_EEE 0 ++#define MAC_EEE 1 ++#define PHY_EEE 2 ++#define PARTNER_EEE 2 ++ ++struct phy_info { ++ char *name; ++ int phy_id; ++ char eee_available; /* eee support by this phy */ ++ int (*eee_init)(struct phy_device *phy_dev); ++}; ++ ++/* GMAC register definition */ ++#define EEE_CLK 0x800 ++#define MASK_EEE_CLK (0x3 << 20) ++#define BIT_DISABLE_TX_CLK BIT(21) ++#define BIT_PHY_KSZ9031 BIT(20) ++#define EEE_ENABLE 0x808 ++#define BIT_EEE_ENABLE BIT(0) ++#define EEE_TIMER 0x80C ++#define EEE_LINK_STATUS 0x810 ++#define BIT_PHY_LINK_STATUS BIT(0) ++#define EEE_TIME_CLK_CNT 0x814 ++ ++/* ----------------------------phy register-------------------------------*/ ++/* MMD: MDIO Manageable Device */ ++#define MACR 0x0D ++#define MAADR 0x0E ++#define EEE_DEV 0x3 ++#define EEE_CAPABILITY 0x14 ++#define EEELPAR_DEV 0x7 ++#define EEELPAR 0x3D /* EEE link partner ability register */ ++#define EEE_ADVERTISE 0x3c ++#define LP_1000BASE_EEE BIT(2) ++#define LP_100BASE_EEE BIT(1) ++ ++struct phy_info *phy_search_ids(int phy_id); ++void init_autoeee(struct higmac_netdev_local *ld); ++ ++#endif +diff --git a/drivers/net/ethernet/hisilicon/higmac/autoeee/phy_id_table.c b/drivers/net/ethernet/hisilicon/higmac/autoeee/phy_id_table.c +new file mode 100644 +index 0000000..8ffaf2a +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/autoeee/phy_id_table.c +@@ -0,0 +1,177 @@ ++#include ++#include ++#include ++#include "../higmac.h" ++#include "autoeee.h" ++ ++struct phy_info phy_info_table[]; ++ ++struct phy_info *phy_search_ids(int phy_id) ++{ ++ int i; ++ struct phy_info *fit_info = NULL; ++ ++ for (i = 0; phy_info_table[i].name; i++) { ++ if (phy_id == phy_info_table[i].phy_id) ++ fit_info = &phy_info_table[i]; ++ } ++ ++ return fit_info; ++} ++ ++static inline int phy_mmd_read(struct phy_device *phy_dev, ++ u32 mmd_device, u32 regnum) ++{ ++ phy_write(phy_dev, MACR, mmd_device); /* function = 00 address */ ++ phy_write(phy_dev, MAADR, regnum); ++ phy_write(phy_dev, MACR, 0x4000 | mmd_device); /* function = 01 data */ ++ ++ return phy_read(phy_dev, MAADR); ++} ++ ++static inline int phy_mmd_write(struct phy_device *phy_dev, u32 mmd_device, ++ u32 regnum, u16 val) ++{ ++ phy_write(phy_dev, MACR, mmd_device); /* function = 00 address */ ++ phy_write(phy_dev, MAADR, regnum); ++ phy_write(phy_dev, MACR, 0x4000 | mmd_device); /* function = 01 data */ ++ ++ return phy_write(phy_dev, MAADR, val); ++} ++ ++static int smsc_lan8740_init(struct phy_device *phy_dev) ++{ ++ static int first_time; ++ int v, eee_type = 0; ++ ++ if (!first_time) { ++ /* Realtek LAN 8740 start to enable eee */ ++ int eee_lan; ++ ++ eee_lan = phy_read(phy_dev, 0x10); ++ if (eee_lan < 0) ++ return eee_lan; ++ eee_lan |= 0x4; ++ phy_write(phy_dev, 0x10, eee_lan); ++ eee_lan = phy_read(phy_dev, 0x10); ++ if (eee_lan < 0) ++ return eee_lan; ++ /* auto negotiate after enable eee */ ++ eee_lan = phy_read(phy_dev, 0x0); ++ if (eee_lan < 0) ++ return eee_lan; ++ eee_lan |= 0x200; ++ phy_write(phy_dev, 0x0, eee_lan); ++ first_time = 1; ++ } ++ ++ v = phy_mmd_read(phy_dev, EEELPAR_DEV, EEELPAR); ++ ++ if (v & LP_1000BASE_EEE) ++ eee_type |= HIGMAC_SPD_1000M; ++ if (v & LP_100BASE_EEE) ++ eee_type |= HIGMAC_SPD_100M; ++ ++ return eee_type; ++} ++ ++#define RTL8211EG_MAC 0 ++#if RTL8211EG_MAC ++static int rtl8211EG_mac_init(struct phy_device *phy_dev) ++{ ++ static int first_time; ++ /* Realtek 8211EG start reset to change eee to mac */ ++ int v, eee_type = 0; ++ ++ if (!first_time) { ++ int tmp = 0; ++ ++ phy_write(phy_dev, 0x1f, 0x0); ++ phy_write(phy_dev, MII_BMCR, BMCR_RESET); /* reset phy */ ++ do { /* wait phy restart over */ ++ udelay(1); ++ tmp = phy_read(phy_dev, MII_BMSR); ++ /* no need to wait AN finished */ ++ tmp &= (BMSR_ANEGCOMPLETE | BMSR_ANEGCAPABLE); ++ } while (!tmp); ++ ++ phy_write(phy_dev, 0x1f, 0x7); ++ phy_write(phy_dev, 0x1e, 0x20); ++ phy_write(phy_dev, 0x1b, 0xa03a); ++ phy_write(phy_dev, 0x1f, 0x0); ++ ++ first_time = 1; ++ } ++ ++ v = phy_mmd_read(phy_dev, EEELPAR_DEV, EEELPAR); ++ ++ if (v & LP_1000BASE_EEE) ++ eee_type |= HIGMAC_SPD_1000M; ++ if (v & LP_100BASE_EEE) ++ eee_type |= HIGMAC_SPD_100M; ++ ++ return eee_type; ++} ++#else ++static int rtl8211EG_init(struct phy_device *phy_dev) ++{ ++ int eee_type = 0, v; ++ ++ v = phy_mmd_read(phy_dev, EEELPAR_DEV, EEELPAR); ++ ++ if (v & LP_1000BASE_EEE) ++ eee_type |= HIGMAC_SPD_1000M; ++ if (v & LP_100BASE_EEE) ++ eee_type |= HIGMAC_SPD_100M; ++ ++ return eee_type; ++} ++#endif ++ ++static int festa_v200_init(struct phy_device *phy_dev) ++{ ++ static int first_time_init; ++ int v, eee_type = 0; ++ ++ if (!first_time_init) { ++ /* EEE_CAPABILITY register: support 100M-BaseT */ ++ v = phy_mmd_read(phy_dev, EEE_DEV, EEE_CAPABILITY); ++ phy_mmd_write(phy_dev, EEE_DEV, EEE_CAPABILITY, ++ ((u32)v) | BIT(1)); ++ ++ /* EEE_ADVERTISEMENT register: advertising 100M-BaseT */ ++ v = phy_mmd_read(phy_dev, EEELPAR_DEV, EEE_ADVERTISE); ++ phy_mmd_write(phy_dev, EEELPAR_DEV, EEE_ADVERTISE, ++ ((u32)v) | BIT(1)); ++ ++ v = phy_read(phy_dev, MII_BMCR); ++ if (v < 0) ++ return v; ++ v |= (BMCR_ANENABLE | BMCR_ANRESTART); ++ phy_write(phy_dev, MII_BMCR, v); /* auto-neg restart */ ++ ++ first_time_init = 1; ++ } ++ ++ v = phy_mmd_read(phy_dev, EEELPAR_DEV, EEELPAR); ++ ++ if (v & LP_1000BASE_EEE) ++ eee_type |= HIGMAC_SPD_1000M; ++ if (v & LP_100BASE_EEE) ++ eee_type |= HIGMAC_SPD_100M; ++ ++ return eee_type; ++} ++ ++struct phy_info phy_info_table[] = { ++ /* phy_name phy_id eee_available phy_driver */ ++/* SMSC */ ++ {"SMSC LAN8740", 0x0007c110, MAC_EEE, &smsc_lan8740_init}, ++/* Realtek */ ++#if RTL8211EG_MAC ++ {"Realtek 8211EG", 0x001cc915, MAC_EEE, &rtl8211EG_mac_init}, ++#else ++ {"Realtek 8211EG", 0x001cc915, PHY_EEE, &rtl8211EG_init}, ++#endif ++ {"Festa V200", HISILICON_PHY_ID_FESTAV200, MAC_EEE, &festa_v200_init}, ++}; +diff --git a/drivers/net/ethernet/hisilicon/higmac/board.c b/drivers/net/ethernet/hisilicon/higmac/board.c +new file mode 100644 +index 0000000..89b9d16 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/board.c +@@ -0,0 +1,96 @@ ++#include ++#include ++#include ++#include "higmac.h" ++ ++void higmac_mac_core_reset(struct higmac_netdev_local *priv) ++{ ++ /* undo reset */ ++ reset_control_deassert(priv->port_rst); ++ usleep_range(50, 60); ++ ++ /* soft reset mac port */ ++ reset_control_assert(priv->port_rst); ++ usleep_range(50, 60); ++ /* undo reset */ ++ reset_control_deassert(priv->port_rst); ++} ++ ++void higmac_hw_internal_phy_reset(struct higmac_netdev_local *priv) ++{ ++} ++ ++void higmac_hw_phy_reset(struct higmac_netdev_local *priv) ++{ ++ if (priv->internal_phy) ++ higmac_hw_internal_phy_reset(priv); ++ else ++ higmac_hw_external_phy_reset(priv); ++} ++ ++void higmac_hw_external_phy_reset(struct higmac_netdev_local *priv) ++{ ++ if (priv->phy_rst) { ++ /* write 0 to cancel reset */ ++ reset_control_deassert(priv->phy_rst); ++ msleep(50); ++ ++ /* HIFONE or 98cv200 use CRG register to reset phy */ ++ /* RST_BIT, write 0 to reset phy, write 1 to cancel reset */ ++ reset_control_assert(priv->phy_rst); ++ ++ /* delay some time to ensure reset ok, ++ * this depends on PHY hardware feature ++ */ ++ msleep(50); ++ ++ /* write 0 to cancel reset */ ++ reset_control_deassert(priv->phy_rst); ++ /* delay some time to ensure later MDIO access */ ++ msleep(50); ++ } ++} ++ ++void higmac_internal_phy_clk_disable(struct higmac_netdev_local *priv) ++{ ++} ++ ++void higmac_internal_phy_clk_enable(struct higmac_netdev_local *priv) ++{ ++} ++ ++void higmac_hw_all_clk_disable(struct higmac_netdev_local *priv) ++{ ++ /* If macif clock is enabled when suspend, we should ++ * disable it here. ++ * Because when resume, PHY will link up again and ++ * macif clock will be enabled too. If we don't disable ++ * macif clock in suspend, macif clock will be enabled twice. ++ */ ++ if (priv->netdev->flags & IFF_UP) ++ clk_disable_unprepare(priv->macif_clk); ++ ++ /* This is called in suspend, when net device is down, ++ * MAC clk is disabled. ++ * So we need to judge whether MAC clk is enabled, ++ * otherwise kernel will WARNING if clk disable twice. ++ */ ++ if (priv->netdev->flags & IFF_UP) ++ clk_disable_unprepare(priv->clk); ++ ++ if (priv->internal_phy) ++ higmac_internal_phy_clk_disable(priv); ++} ++ ++void higmac_hw_all_clk_enable(struct higmac_netdev_local *priv) ++{ ++ if (priv->internal_phy) ++ higmac_internal_phy_clk_enable(priv); ++ ++ if (priv->netdev->flags & IFF_UP) ++ clk_prepare_enable(priv->macif_clk); ++ ++ /* If net device is down when suspend, we should not enable MAC clk. */ ++ if (priv->netdev->flags & IFF_UP) ++ clk_prepare_enable(priv->clk); ++} +diff --git a/drivers/net/ethernet/hisilicon/higmac/higmac.c b/drivers/net/ethernet/hisilicon/higmac/higmac.c +new file mode 100644 +index 0000000..ad218fed +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/higmac.c +@@ -0,0 +1,3073 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "util.h" ++#include "higmac.h" ++#include "autoeee/autoeee.h" ++#include "sockioctl.h" ++ ++#define HAS_TSO_CAP(hw_cap) ((((hw_cap) >> 28) & 0x3) == VER_TSO) ++#define HAS_RXHASH_CAP(hw_cap) ((hw_cap) & BIT(30)) ++#define HAS_RSS_CAP(hw_cap) ((hw_cap) & BIT(31)) ++ ++#define RGMII_SPEED_1000 0x2c ++#define RGMII_SPEED_100 0x2f ++#define RGMII_SPEED_10 0x2d ++#define MII_SPEED_100 0x0f ++#define MII_SPEED_10 0x0d ++#define RMII_SPEED_100 0x8f ++#define RMII_SPEED_10 0x8d ++#define GMAC_FULL_DUPLEX BIT(4) ++ ++static unsigned int flow_ctrl_en = FLOW_OFF; ++static int tx_flow_ctrl_pause_time = CONFIG_TX_FLOW_CTRL_PAUSE_TIME; ++static int tx_flow_ctrl_pause_interval = CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL; ++static int tx_flow_ctrl_active_threshold = CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD; ++static int tx_flow_ctrl_deactive_threshold = ++ CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD; ++ ++#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK) ++static int debug = -1; ++module_param(debug, int, 0000); ++MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); ++ ++static void higmac_config_port(struct net_device *dev, u32 speed, u32 duplex) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(dev); ++ u32 val; ++ ++ switch (priv->phy_mode) { ++ case PHY_INTERFACE_MODE_RGMII: ++ if (speed == SPEED_1000) ++ val = RGMII_SPEED_1000; ++ else if (speed == SPEED_100) ++ val = RGMII_SPEED_100; ++ else ++ val = RGMII_SPEED_10; ++ break; ++ case PHY_INTERFACE_MODE_MII: ++ if (speed == SPEED_100) ++ val = MII_SPEED_100; ++ else ++ val = MII_SPEED_10; ++ break; ++ case PHY_INTERFACE_MODE_RMII: ++ if (speed == SPEED_100) ++ val = RMII_SPEED_100; ++ else ++ val = RMII_SPEED_10; ++ break; ++ default: ++ netdev_warn(dev, "not supported mode\n"); ++ val = MII_SPEED_10; ++ break; ++ } ++ ++ if (duplex) ++ val |= GMAC_FULL_DUPLEX; ++ ++ reset_control_assert(priv->macif_rst); ++ writel_relaxed(val, priv->macif_base); ++ reset_control_deassert(priv->macif_rst); ++ ++ writel_relaxed(BIT_MODE_CHANGE_EN, priv->gmac_iobase + MODE_CHANGE_EN); ++ if (speed == SPEED_1000) ++ val = GMAC_SPEED_1000; ++ else if (speed == SPEED_100) ++ val = GMAC_SPEED_100; ++ else ++ val = GMAC_SPEED_10; ++ writel_relaxed(val, priv->gmac_iobase + PORT_MODE); ++ writel_relaxed(0, priv->gmac_iobase + MODE_CHANGE_EN); ++ writel_relaxed(duplex, priv->gmac_iobase + MAC_DUPLEX_HALF_CTRL); ++} ++ ++static void higmac_set_desc_depth(struct higmac_netdev_local *priv, ++ u32 rx, u32 tx) ++{ ++ u32 reg; ++ int i; ++ ++ writel(BITS_RX_FQ_DEPTH_EN, priv->gmac_iobase + RX_FQ_REG_EN); ++ writel(rx << DESC_WORD_SHIFT, priv->gmac_iobase + RX_FQ_DEPTH); ++ writel(0, priv->gmac_iobase + RX_FQ_REG_EN); ++ ++ writel(BITS_RX_BQ_DEPTH_EN, priv->gmac_iobase + RX_BQ_REG_EN); ++ writel(rx << DESC_WORD_SHIFT, priv->gmac_iobase + RX_BQ_DEPTH); ++ for (i = 1; i < priv->num_rxqs; i++) { ++ reg = RX_BQ_DEPTH_QUEUE(i); ++ writel(rx << DESC_WORD_SHIFT, priv->gmac_iobase + reg); ++ } ++ writel(0, priv->gmac_iobase + RX_BQ_REG_EN); ++ ++ writel(BITS_TX_BQ_DEPTH_EN, priv->gmac_iobase + TX_BQ_REG_EN); ++ writel(tx << DESC_WORD_SHIFT, priv->gmac_iobase + TX_BQ_DEPTH); ++ writel(0, priv->gmac_iobase + TX_BQ_REG_EN); ++ ++ writel(BITS_TX_RQ_DEPTH_EN, priv->gmac_iobase + TX_RQ_REG_EN); ++ writel(tx << DESC_WORD_SHIFT, priv->gmac_iobase + TX_RQ_DEPTH); ++ writel(0, priv->gmac_iobase + TX_RQ_REG_EN); ++} ++ ++static void higmac_set_rx_fq(struct higmac_netdev_local *priv, ++ dma_addr_t phy_addr) ++{ ++ writel(BITS_RX_FQ_START_ADDR_EN, priv->gmac_iobase + RX_FQ_REG_EN); ++ writel(phy_addr, priv->gmac_iobase + RX_FQ_START_ADDR); ++ writel(0, priv->gmac_iobase + RX_FQ_REG_EN); ++} ++ ++static void higmac_set_rx_bq(struct higmac_netdev_local *priv, ++ dma_addr_t phy_addr) ++{ ++ writel(BITS_RX_BQ_START_ADDR_EN, priv->gmac_iobase + RX_BQ_REG_EN); ++ writel(phy_addr, priv->gmac_iobase + RX_BQ_START_ADDR); ++ writel(0, priv->gmac_iobase + RX_BQ_REG_EN); ++} ++ ++static void higmac_set_tx_bq(struct higmac_netdev_local *priv, ++ dma_addr_t phy_addr) ++{ ++ writel(BITS_TX_BQ_START_ADDR_EN, priv->gmac_iobase + TX_BQ_REG_EN); ++ writel(phy_addr, priv->gmac_iobase + TX_BQ_START_ADDR); ++ writel(0, priv->gmac_iobase + TX_BQ_REG_EN); ++} ++ ++static void higmac_set_tx_rq(struct higmac_netdev_local *priv, ++ dma_addr_t phy_addr) ++{ ++ writel(BITS_TX_RQ_START_ADDR_EN, priv->gmac_iobase + TX_RQ_REG_EN); ++ writel(phy_addr, priv->gmac_iobase + TX_RQ_START_ADDR); ++ writel(0, priv->gmac_iobase + TX_RQ_REG_EN); ++} ++ ++static void higmac_hw_set_desc_addr(struct higmac_netdev_local *priv) ++{ ++ u32 reg; ++ int i; ++ ++ higmac_set_rx_fq(priv, priv->rx_fq.phys_addr); ++ higmac_set_rx_bq(priv, priv->rx_bq.phys_addr); ++ higmac_set_tx_rq(priv, priv->tx_rq.phys_addr); ++ higmac_set_tx_bq(priv, priv->tx_bq.phys_addr); ++ ++ for (i = 1; i < priv->num_rxqs; i++) { ++ reg = RX_BQ_START_ADDR_QUEUE(i); ++ writel(BITS_RX_BQ_START_ADDR_EN, ++ priv->gmac_iobase + RX_BQ_REG_EN); ++ writel(priv->pool[3 + i].phys_addr, priv->gmac_iobase + reg); ++ writel(0, priv->gmac_iobase + RX_BQ_REG_EN); ++ } ++} ++ ++static void higmac_set_rss_cap(struct higmac_netdev_local *priv) ++{ ++ u32 val = 0; ++ ++ if (priv->has_rxhash_cap) ++ val |= BIT_RXHASH_CAP; ++ if (priv->has_rss_cap) ++ val |= BIT_RSS_CAP; ++ writel(val, priv->gmac_iobase + HW_CAP_EN); ++} ++ ++/* config AXI bus burst and outstanding for better performance */ ++static void higmac_axi_bus_cfg(struct higmac_netdev_local *priv) ++{ ++ if (!priv->axi_bus_cfg_base) ++ return; ++ ++#if defined(CONFIG_ARCH_HI3519) || defined(CONFIG_ARCH_HI3519V101) || \ ++ defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) || \ ++ defined(CONFIG_ARCH_HI3516AV200) ++ if (!(readl(priv->axi_bus_cfg_base) >> BURST_OUTSTANDING_OFFSET)) ++ writel(BURST4_OUTSTANDING1, priv->axi_bus_cfg_base); ++#elif defined(CONFIG_ARCH_HI3521A) || defined(CONFIG_ARCH_HI3531A) ++ writel(BURST4_OUTSTANDING1, priv->axi_bus_cfg_base); ++#endif ++} ++ ++static void higmac_hw_init(struct higmac_netdev_local *priv) ++{ ++ u32 val; ++ u32 reg; ++ int i; ++ ++ higmac_axi_bus_cfg(priv); ++ ++ /* disable and clear all interrupts */ ++ writel(0, priv->gmac_iobase + ENA_PMU_INT); ++ writel(~0, priv->gmac_iobase + RAW_PMU_INT); ++ ++ for (i = 1; i < priv->num_rxqs; i++) { ++ reg = RSS_ENA_INT_QUEUE(i); ++ writel(0, priv->gmac_iobase + reg); ++ } ++ writel(~0, priv->gmac_iobase + RSS_RAW_PMU_INT); ++ ++ /* enable CRC erro packets filter */ ++ val = readl(priv->gmac_iobase + REC_FILT_CONTROL); ++ val |= BIT_CRC_ERR_PASS; ++ writel(val, priv->gmac_iobase + REC_FILT_CONTROL); ++ ++ /* set tx min packet length */ ++ val = readl(priv->gmac_iobase + CRF_MIN_PACKET); ++ val &= ~BIT_MASK_TX_MIN_LEN; ++ val |= ETH_HLEN << BIT_OFFSET_TX_MIN_LEN; ++ writel(val, priv->gmac_iobase + CRF_MIN_PACKET); ++ ++ /* fix bug for udp and ip error check */ ++ writel(CONTROL_WORD_CONFIG, priv->gmac_iobase + CONTROL_WORD); ++ ++ writel(0, priv->gmac_iobase + COL_SLOT_TIME); ++ ++ writel(DUPLEX_HALF, priv->gmac_iobase + MAC_DUPLEX_HALF_CTRL); ++ ++ /* FIXME: interrupt when rcv packets >= RX_BQ_INT_THRESHOLD */ ++ val = RX_BQ_INT_THRESHOLD | ++ (TX_RQ_INT_THRESHOLD << BITS_OFFSET_TX_RQ_IN_TH); ++ writel(val, priv->gmac_iobase + IN_QUEUE_TH); ++ ++ /* FIXME: rx_bq/tx_rq in timeout threshold */ ++ writel(0x10000, priv->gmac_iobase + RX_BQ_IN_TIMEOUT_TH); ++ ++ writel(0x18000, priv->gmac_iobase + TX_RQ_IN_TIMEOUT_TH); ++ ++ higmac_set_desc_depth(priv, RX_DESC_NUM, TX_DESC_NUM); ++} ++ ++static inline void higmac_irq_enable(struct higmac_netdev_local *ld) ++{ ++ writel(RX_BQ_IN_INT | RX_BQ_IN_TIMEOUT_INT ++ | TX_RQ_IN_INT | TX_RQ_IN_TIMEOUT_INT, ++ ld->gmac_iobase + ENA_PMU_INT); ++} ++ ++static inline void higmac_irq_enable_queue(struct higmac_netdev_local *ld, ++ int rxq_id) ++{ ++ if (rxq_id) { ++ u32 reg; ++ ++ reg = RSS_ENA_INT_QUEUE(rxq_id); ++ writel(~0, ld->gmac_iobase + reg); ++ } else { ++ higmac_irq_enable(ld); ++ } ++} ++ ++static inline void higmac_irq_enable_all_queue(struct higmac_netdev_local *ld) ++{ ++ int i; ++ ++ for (i = 0; i < ld->num_rxqs; i++) ++ higmac_irq_enable_queue(ld, i); ++} ++ ++static inline void higmac_irq_disable(struct higmac_netdev_local *ld) ++{ ++ writel(0, ld->gmac_iobase + ENA_PMU_INT); ++} ++ ++static inline void higmac_irq_disable_queue(struct higmac_netdev_local *ld, ++ int rxq_id) ++{ ++ if (rxq_id) { ++ u32 reg; ++ ++ reg = RSS_ENA_INT_QUEUE(rxq_id); ++ writel(0, ld->gmac_iobase + reg); ++ } else { ++ higmac_irq_disable(ld); ++ } ++} ++ ++static inline void higmac_irq_disable_all_queue(struct higmac_netdev_local *ld) ++{ ++ int i; ++ ++ for (i = 0; i < ld->num_rxqs; i++) ++ higmac_irq_disable_queue(ld, i); ++} ++ ++static inline bool higmac_queue_irq_disabled(struct higmac_netdev_local *ld, ++ int rxq_id) ++{ ++ u32 reg, val; ++ ++ if (rxq_id) ++ reg = RSS_ENA_INT_QUEUE(rxq_id); ++ else ++ reg = ENA_PMU_INT; ++ val = readl(ld->gmac_iobase + reg); ++ ++ return !val; ++} ++ ++static inline void higmac_hw_desc_enable(struct higmac_netdev_local *ld) ++{ ++ writel(0xF, ld->gmac_iobase + DESC_WR_RD_ENA); ++} ++ ++static inline void higmac_hw_desc_disable(struct higmac_netdev_local *ld) ++{ ++ writel(0, ld->gmac_iobase + DESC_WR_RD_ENA); ++} ++ ++static inline void higmac_port_enable(struct higmac_netdev_local *ld) ++{ ++ writel(BITS_TX_EN | BITS_RX_EN, ld->gmac_iobase + PORT_EN); ++} ++ ++static inline void higmac_port_disable(struct higmac_netdev_local *ld) ++{ ++ writel(0, ld->gmac_iobase + PORT_EN); ++} ++ ++void higmac_set_flow_ctrl_params(struct higmac_netdev_local *ld) ++{ ++ unsigned int rx_fq_empty_th; ++ unsigned int rx_fq_full_th; ++ unsigned int rx_bq_empty_th; ++ unsigned int rx_bq_full_th; ++ unsigned int rec_filter; ++ ++ writel(ld->pause, ld->gmac_iobase + FC_TX_TIMER); ++ writel(ld->pause_interval, ld->gmac_iobase + PAUSE_THR); ++ ++ rx_fq_empty_th = readl(ld->gmac_iobase + RX_FQ_ALEMPTY_TH); ++ rx_fq_empty_th &= ~(BITS_Q_PAUSE_TH_MASK << BITS_Q_PAUSE_TH_OFFSET); ++ rx_fq_empty_th |= (ld->flow_ctrl_active_threshold << ++ BITS_Q_PAUSE_TH_OFFSET); ++ writel(rx_fq_empty_th, ld->gmac_iobase + RX_FQ_ALEMPTY_TH); ++ ++ rx_fq_full_th = readl(ld->gmac_iobase + RX_FQ_ALFULL_TH); ++ rx_fq_full_th &= ~(BITS_Q_PAUSE_TH_MASK << BITS_Q_PAUSE_TH_OFFSET); ++ rx_fq_full_th |= (ld->flow_ctrl_deactive_threshold << ++ BITS_Q_PAUSE_TH_OFFSET); ++ writel(rx_fq_full_th, ld->gmac_iobase + RX_FQ_ALFULL_TH); ++ ++ rx_bq_empty_th = readl(ld->gmac_iobase + RX_BQ_ALEMPTY_TH); ++ rx_bq_empty_th &= ~(BITS_Q_PAUSE_TH_MASK << BITS_Q_PAUSE_TH_OFFSET); ++ rx_bq_empty_th |= (ld->flow_ctrl_active_threshold << ++ BITS_Q_PAUSE_TH_OFFSET); ++ writel(rx_bq_empty_th, ld->gmac_iobase + RX_BQ_ALEMPTY_TH); ++ ++ rx_bq_full_th = readl(ld->gmac_iobase + RX_BQ_ALFULL_TH); ++ rx_bq_full_th &= ~(BITS_Q_PAUSE_TH_MASK << BITS_Q_PAUSE_TH_OFFSET); ++ rx_bq_full_th |= (ld->flow_ctrl_deactive_threshold << ++ BITS_Q_PAUSE_TH_OFFSET); ++ writel(rx_bq_full_th, ld->gmac_iobase + RX_BQ_ALFULL_TH); ++ ++ writel(0, ld->gmac_iobase + CRF_TX_PAUSE); ++ ++ rec_filter = readl(ld->gmac_iobase + REC_FILT_CONTROL); ++ rec_filter |= BIT_PAUSE_FRM_PASS; ++ writel(rec_filter, ld->gmac_iobase + REC_FILT_CONTROL); ++} ++ ++void higmac_set_flow_ctrl_state(struct higmac_netdev_local *ld, int pause) ++{ ++ unsigned int flow_rx_q_en; ++ unsigned int flow; ++ ++ flow_rx_q_en = readl(ld->gmac_iobase + RX_PAUSE_EN); ++ flow_rx_q_en &= ~(BIT_RX_FQ_PAUSE_EN | BIT_RX_BQ_PAUSE_EN); ++ if (pause && (ld->flow_ctrl & FLOW_TX)) ++ flow_rx_q_en |= (BIT_RX_FQ_PAUSE_EN | BIT_RX_BQ_PAUSE_EN); ++ writel(flow_rx_q_en, ld->gmac_iobase + RX_PAUSE_EN); ++ ++ flow = readl(ld->gmac_iobase + PAUSE_EN); ++ flow &= ~(BIT_RX_FDFC | BIT_TX_FDFC); ++ if (pause) { ++ if (ld->flow_ctrl & FLOW_RX) ++ flow |= BIT_RX_FDFC; ++ if (ld->flow_ctrl & FLOW_TX) ++ flow |= BIT_TX_FDFC; ++ } ++ writel(flow, ld->gmac_iobase + PAUSE_EN); ++} ++ ++static void higmac_set_flow_ctrl_args(struct higmac_netdev_local *ld) ++{ ++ ld->flow_ctrl = flow_ctrl_en; ++ ld->pause = tx_flow_ctrl_pause_time; ++ ld->pause_interval = tx_flow_ctrl_pause_interval; ++ ld->flow_ctrl_active_threshold = tx_flow_ctrl_active_threshold; ++ ld->flow_ctrl_deactive_threshold = tx_flow_ctrl_deactive_threshold; ++} ++ ++/* set gmac's multicast list, here we setup gmac's mc filter */ ++static void higmac_gmac_multicast_list(struct net_device *dev) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(dev); ++ unsigned int rec_filter; ++ ++ rec_filter = readl(ld->gmac_iobase + REC_FILT_CONTROL); ++ /* when set gmac in promisc mode ++ * a. dev in IFF_PROMISC mode ++ */ ++ if ((dev->flags & IFF_PROMISC)) { ++ /* promisc mode.received all pkgs. */ ++ rec_filter &= ~(BIT_BC_DROP_EN | BIT_MC_MATCH_EN | ++ BIT_UC_MATCH_EN); ++ } else { ++ /* drop uc pkgs with field 'DA' not match our's */ ++ rec_filter |= BIT_UC_MATCH_EN; ++ ++ if (dev->flags & IFF_BROADCAST) /* no broadcast */ ++ rec_filter &= ~BIT_BC_DROP_EN; ++ else ++ rec_filter |= BIT_BC_DROP_EN; ++ ++ if (netdev_mc_empty(dev) || !(dev->flags & IFF_MULTICAST)) { ++ /* haven't join any mc group */ ++ writel(0, ld->gmac_iobase + PORT_MC_ADDR_LOW); ++ writel(0, ld->gmac_iobase + PORT_MC_ADDR_HIGH); ++ rec_filter |= BIT_MC_MATCH_EN; ++ } else if (netdev_mc_count(dev) == 1 && ++ (dev->flags & IFF_MULTICAST)) { ++ struct netdev_hw_addr *ha; ++ unsigned int d = 0; ++ ++ netdev_for_each_mc_addr(ha, dev) { ++ d = (ha->addr[0] << 8) | (ha->addr[1]); ++ writel(d, ld->gmac_iobase + PORT_MC_ADDR_HIGH); ++ ++ d = (ha->addr[2] << 24) | (ha->addr[3] << 16) ++ | (ha->addr[4] << 8) | (ha->addr[5]); ++ writel(d, ld->gmac_iobase + PORT_MC_ADDR_LOW); ++ } ++ rec_filter |= BIT_MC_MATCH_EN; ++ } else { ++ rec_filter &= ~BIT_MC_MATCH_EN; ++ } ++ } ++ writel(rec_filter, ld->gmac_iobase + REC_FILT_CONTROL); ++} ++ ++/* the func stop the hw desc and relaim the software skb resource ++ * before reusing the gmac, you'd better reset the gmac ++ */ ++void higmac_reclaim_rx_tx_resource(struct higmac_netdev_local *ld) ++{ ++ unsigned long rxflags, txflags; ++ int rd_offset, wr_offset; ++ int i; ++ ++ higmac_irq_disable_all_queue(ld); ++ higmac_hw_desc_disable(ld); ++ writel(STOP_RX_TX, ld->gmac_iobase + STOP_CMD); ++ ++ spin_lock_irqsave(&ld->rxlock, rxflags); ++ /* rx_bq: logic write pointer */ ++ wr_offset = readl(ld->gmac_iobase + RX_BQ_WR_ADDR); ++ /* rx_bq: software read pointer */ ++ rd_offset = readl(ld->gmac_iobase + RX_BQ_RD_ADDR); ++ /* FIXME: prevent to reclaim skb in rx bottom half */ ++ writel(wr_offset, ld->gmac_iobase + RX_BQ_RD_ADDR); ++ ++ for (i = 1; i < ld->num_rxqs; i++) { ++ u32 rx_bq_wr_reg, rx_bq_rd_reg; ++ ++ rx_bq_wr_reg = RX_BQ_WR_ADDR_QUEUE(i); ++ rx_bq_rd_reg = RX_BQ_RD_ADDR_QUEUE(i); ++ ++ wr_offset = readl(ld->gmac_iobase + rx_bq_wr_reg); ++ writel(wr_offset, ld->gmac_iobase + rx_bq_rd_reg); ++ } ++ ++ /* rx_fq: software write pointer */ ++ wr_offset = readl(ld->gmac_iobase + RX_FQ_WR_ADDR); ++ /* rx_fq: logic read pointer */ ++ rd_offset = readl(ld->gmac_iobase + RX_FQ_RD_ADDR); ++ if (!rd_offset) ++ rd_offset = (RX_DESC_NUM - 1) << DESC_BYTE_SHIFT; ++ else ++ rd_offset -= DESC_SIZE; ++ /* FIXME: stop to feed hw desc */ ++ writel(rd_offset, ld->gmac_iobase + RX_FQ_WR_ADDR); ++ ++ for (i = 0; i < ld->rx_fq.count; i++) { ++ if (!ld->rx_fq.skb[i]) ++ ld->rx_fq.skb[i] = SKB_MAGIC; ++ } ++ spin_unlock_irqrestore(&ld->rxlock, rxflags); ++ ++ /* no need to wait pkts in tx_rq finish to free all skb, ++ * because higmac_xmit_reclaim is in the tx_lock, ++ */ ++ spin_lock_irqsave(&ld->txlock, txflags); ++ /* tx_rq: logic write */ ++ wr_offset = readl(ld->gmac_iobase + TX_RQ_WR_ADDR); ++ /* tx_rq: software read */ ++ rd_offset = readl(ld->gmac_iobase + TX_RQ_RD_ADDR); ++ /* FIXME: stop to reclaim tx skb */ ++ writel(wr_offset, ld->gmac_iobase + TX_RQ_RD_ADDR); ++ ++ /* tx_bq: logic read */ ++ rd_offset = readl(ld->gmac_iobase + TX_BQ_RD_ADDR); ++ if (!rd_offset) ++ rd_offset = (TX_DESC_NUM - 1) << DESC_BYTE_SHIFT; ++ else ++ rd_offset -= DESC_SIZE; ++ /* FIXME: stop software tx skb */ ++ writel(rd_offset, ld->gmac_iobase + TX_BQ_WR_ADDR); ++ ++ for (i = 0; i < ld->tx_bq.count; i++) { ++ if (!ld->tx_bq.skb[i]) ++ ld->tx_bq.skb[i] = SKB_MAGIC; ++ } ++ spin_unlock_irqrestore(&ld->txlock, txflags); ++} ++ ++static void higmac_monitor_func(unsigned long arg); ++static void higmac_set_multicast_list(struct net_device *dev); ++ ++static void higmac_hw_set_mac_addr(struct net_device *dev) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(dev); ++ unsigned char *mac = dev->dev_addr; ++ u32 val; ++ ++ val = mac[1] | (mac[0] << 8); ++ writel(val, priv->gmac_iobase + STATION_ADDR_HIGH); ++ ++ val = mac[5] | (mac[4] << 8) | (mac[3] << 16) | (mac[2] << 24); ++ writel(val, priv->gmac_iobase + STATION_ADDR_LOW); ++} ++ ++static void higmac_rx_refill(struct higmac_netdev_local *priv); ++ ++static void higmac_free_rx_skb(struct higmac_netdev_local *ld) ++{ ++ struct sk_buff *skb = NULL; ++ int i; ++ ++ for (i = 0; i < ld->rx_fq.count; i++) { ++ skb = ld->rx_fq.skb[i]; ++ if (skb) { ++ ld->rx_skb[i] = NULL; ++ ld->rx_fq.skb[i] = NULL; ++ if (skb == SKB_MAGIC) ++ continue; ++ dev_kfree_skb_any(skb); ++ /* TODO: need to unmap the skb here ++ * but there is no way to get the dma_addr here, ++ * and unmap(TO_DEVICE) ops do nothing in fact, ++ * so we ignore to call ++ * dma_unmap_single(dev, dma_addr, skb->len, ++ * DMA_TO_DEVICE) ++ */ ++ } ++ } ++} ++ ++static void higmac_free_tx_skb(struct higmac_netdev_local *ld) ++{ ++ struct sk_buff *skb = NULL; ++ int i; ++ ++ for (i = 0; i < ld->tx_bq.count; i++) { ++ skb = ld->tx_bq.skb[i]; ++ if (skb) { ++ ld->tx_skb[i] = NULL; ++ ld->tx_bq.skb[i] = NULL; ++ if (skb == SKB_MAGIC) ++ continue; ++ dev_kfree_skb_any(skb); ++ /* TODO: unmap the skb */ ++ } ++ } ++} ++ ++/* reset and re-config gmac */ ++void higmac_restart(struct higmac_netdev_local *ld) ++{ ++ unsigned long rxflags, txflags; ++ ++ /* restart hw engine now */ ++ higmac_mac_core_reset(ld); ++ ++ spin_lock_irqsave(&ld->rxlock, rxflags); ++ spin_lock_irqsave(&ld->txlock, txflags); ++ ++ higmac_free_rx_skb(ld); ++ higmac_free_tx_skb(ld); ++ ++ pmt_reg_restore(ld); ++ higmac_hw_init(ld); ++ higmac_hw_set_mac_addr(ld->netdev); ++ higmac_hw_set_desc_addr(ld); ++ ++ /* we don't set macif here, it will be set in adjust_link */ ++ if (ld->netdev->flags & IFF_UP) { ++ /* when resume, only do the following operations ++ * when dev is up before suspend. ++ */ ++ higmac_rx_refill(ld); ++ higmac_set_multicast_list(ld->netdev); ++ ++ higmac_hw_desc_enable(ld); ++ higmac_port_enable(ld); ++ higmac_irq_enable_all_queue(ld); ++ } ++ spin_unlock_irqrestore(&ld->txlock, txflags); ++ spin_unlock_irqrestore(&ld->rxlock, rxflags); ++} ++ ++static int higmac_net_set_mac_address(struct net_device *dev, void *p) ++{ ++ int ret; ++ ++ ret = eth_mac_addr(dev, p); ++ if (!ret) ++ higmac_hw_set_mac_addr(dev); ++ ++ return ret; ++} ++ ++#define HIGMAC_LINK_CHANGE_PROTECT ++ ++#ifdef HIGMAC_LINK_CHANGE_PROTECT ++#define HIGMAC_MS_TO_NS (1000000ULL) ++#define HIGMAC_FLUSH_WAIT_TIME (100*HIGMAC_MS_TO_NS) ++/* protect code */ ++static void higmac_linkup_flush(struct higmac_netdev_local *ld) ++{ ++ int tx_bq_wr_offset, tx_bq_rd_offset; ++ unsigned long long time_limit, time_now; ++ ++ time_now = sched_clock(); ++ time_limit = time_now + HIGMAC_FLUSH_WAIT_TIME; ++ ++ do { ++ tx_bq_wr_offset = readl(ld->gmac_iobase + TX_BQ_WR_ADDR); ++ tx_bq_rd_offset = readl(ld->gmac_iobase + TX_BQ_RD_ADDR); ++ ++ time_now = sched_clock(); ++ if (unlikely((long long)time_now - ++ (long long)time_limit >= 0)) ++ break; ++ } while (tx_bq_rd_offset != tx_bq_wr_offset); ++ ++ mdelay(1); ++} ++#endif ++ ++static void higmac_adjust_link(struct net_device *dev) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(dev); ++ struct phy_device *phy = priv->phy; ++ bool link_status_changed = false; ++ ++ if (phy->link) { ++ if ((priv->old_speed != phy->speed) || ++ (priv->old_duplex != phy->duplex)) { ++#ifdef HIGMAC_LINK_CHANGE_PROTECT ++ unsigned long txflags; ++ ++ spin_lock_irqsave(&priv->txlock, txflags); ++ ++ higmac_linkup_flush(priv); ++#endif ++ higmac_config_port(dev, phy->speed, phy->duplex); ++#ifdef HIGMAC_LINK_CHANGE_PROTECT ++ spin_unlock_irqrestore(&priv->txlock, txflags); ++#endif ++ higmac_set_flow_ctrl_state(priv, phy->pause); ++ ++ if (priv->autoeee) ++ init_autoeee(priv); ++ ++ link_status_changed = true; ++ priv->old_link = 1; ++ priv->old_speed = phy->speed; ++ priv->old_duplex = phy->duplex; ++ } ++ } else if (priv->old_link) { ++ link_status_changed = true; ++ priv->old_link = 0; ++ priv->old_speed = SPEED_UNKNOWN; ++ priv->old_duplex = DUPLEX_UNKNOWN; ++ } ++ ++ if (link_status_changed && netif_msg_link(priv)) ++ phy_print_status(phy); ++} ++ ++int higmac_tx_avail(struct higmac_netdev_local *ld) ++{ ++ int tx_bq_wr_offset, tx_bq_rd_offset; ++ ++ tx_bq_wr_offset = readl(ld->gmac_iobase + TX_BQ_WR_ADDR); ++ tx_bq_rd_offset = readl(ld->gmac_iobase + TX_BQ_RD_ADDR); ++ ++ return (tx_bq_rd_offset >> DESC_BYTE_SHIFT) + TX_DESC_NUM ++ - (tx_bq_wr_offset >> DESC_BYTE_SHIFT) - 1; ++} ++ ++static int higmac_init_sg_desc_queue(struct higmac_netdev_local *ld) ++{ ++ ld->sg_count = ld->tx_bq.count + HIGMAC_SG_DESC_ADD; ++ if (HAS_CAP_CCI(ld->hw_cap)) { ++ ld->dma_sg_desc = kmalloc_array(ld->sg_count, ++ sizeof(struct sg_desc), ++ GFP_KERNEL); ++ if (ld->dma_sg_desc) ++ ld->dma_sg_phy = virt_to_phys(ld->dma_sg_desc); ++ } else { ++ ld->dma_sg_desc = (struct sg_desc *)dma_alloc_coherent(ld->dev, ++ ld->sg_count * sizeof(struct sg_desc), ++ &ld->dma_sg_phy, GFP_KERNEL); ++ } ++ ++ if (!ld->dma_sg_desc) { ++ pr_err("alloc sg desc dma error!\n"); ++ return -ENOMEM; ++ } ++#ifdef HIGMAC_TSO_DEBUG ++ pr_info("Higmac dma_sg_phy: 0x%p\n", (void *)ld->dma_sg_phy); ++#endif ++ ++ ld->sg_head = 0; ++ ld->sg_tail = 0; ++ ++ return 0; ++} ++ ++static void higmac_destroy_sg_desc_queue(struct higmac_netdev_local *ld) ++{ ++ if (ld->dma_sg_desc) { ++ if (HAS_CAP_CCI(ld->hw_cap)) ++ kfree(ld->dma_sg_desc); ++ else ++ dma_free_coherent(ld->dev, ++ ld->sg_count * sizeof(struct sg_desc), ++ ld->dma_sg_desc, ld->dma_sg_phy); ++ ld->dma_sg_desc = NULL; ++ } ++} ++ ++static void higmac_monitor_func(unsigned long arg) ++{ ++ struct net_device *dev = (struct net_device *)arg; ++ struct higmac_netdev_local *ld = netdev_priv(dev); ++ ++ if (!ld || !netif_running(dev)) { ++ higmac_trace(7, "network driver is stopped."); ++ return; ++ } ++ ++ spin_lock(&ld->rxlock); ++ higmac_rx_refill(ld); ++ spin_unlock(&ld->rxlock); ++ ++ ld->monitor.expires = jiffies + HIGMAC_MONITOR_TIMER; ++ mod_timer(&ld->monitor, ld->monitor.expires); ++} ++ ++static void higmac_rx_refill(struct higmac_netdev_local *priv) ++{ ++ struct higmac_desc *desc; ++ struct sk_buff *skb; ++ u32 start, end, num, pos, i; ++ u32 len = HIETH_MAX_FRAME_SIZE; ++ dma_addr_t addr; ++ ++ /* software write pointer */ ++ start = dma_cnt(readl(priv->gmac_iobase + RX_FQ_WR_ADDR)); ++ /* logic read pointer */ ++ end = dma_cnt(readl(priv->gmac_iobase + RX_FQ_RD_ADDR)); ++ num = CIRC_SPACE(start, end, RX_DESC_NUM); ++ ++ for (i = 0, pos = start; i < num; i++) { ++ if (priv->rx_fq.skb[pos] || priv->rx_skb[pos]) ++ break; ++ ++ skb = netdev_alloc_skb_ip_align(priv->netdev, len); ++ if (unlikely(!skb)) ++ break; ++ ++ if (!HAS_CAP_CCI(priv->hw_cap)) { ++ addr = dma_map_single(priv->dev, skb->data, len, ++ DMA_FROM_DEVICE); ++ if (dma_mapping_error(priv->dev, addr)) { ++ dev_kfree_skb_any(skb); ++ break; ++ } ++ } else { ++ addr = virt_to_phys(skb->data); ++ } ++ ++ desc = priv->rx_fq.desc + pos; ++ desc->data_buff_addr = addr; ++ priv->rx_fq.skb[pos] = skb; ++ priv->rx_skb[pos] = skb; ++ ++ desc->buffer_len = len - 1; ++ desc->data_len = 0; ++ desc->fl = 0; ++ desc->descvid = DESC_VLD_FREE; ++ desc->skb_id = pos; ++ ++ pos = dma_ring_incr(pos, RX_DESC_NUM); ++ } ++ ++ /* This barrier is important here. It is required to ensure ++ * the ARM CPU flushes it's DMA write buffers before proceeding ++ * to the next instruction, to ensure that GMAC will see ++ * our descriptor changes in memory ++ */ ++ HIGMAC_SYNC_BARRIER(); ++ ++ if (pos != start) ++ writel(dma_byte(pos), priv->gmac_iobase + RX_FQ_WR_ADDR); ++} ++ ++static int higmac_rx(struct net_device *dev, int limit, int rxq_id) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(dev); ++ struct sk_buff *skb; ++ struct higmac_desc *desc; ++ dma_addr_t addr; ++ u32 start, end, num, pos, i, len; ++ u32 rx_bq_rd_reg, rx_bq_wr_reg; ++ u16 skb_id; ++ ++ rx_bq_rd_reg = RX_BQ_RD_ADDR_QUEUE(rxq_id); ++ rx_bq_wr_reg = RX_BQ_WR_ADDR_QUEUE(rxq_id); ++ ++ /* software read pointer */ ++ start = dma_cnt(readl(ld->gmac_iobase + rx_bq_rd_reg)); ++ /* logic write pointer */ ++ end = dma_cnt(readl(ld->gmac_iobase + rx_bq_wr_reg)); ++ num = CIRC_CNT(end, start, RX_DESC_NUM); ++ if (num > limit) ++ num = limit; ++ ++ /* ensure get updated desc */ ++ rmb(); ++ for (i = 0, pos = start; i < num; i++) { ++ if (rxq_id) ++ desc = ld->pool[3 + rxq_id].desc + pos; ++ else ++ desc = ld->rx_bq.desc + pos; ++ skb_id = desc->skb_id; ++ ++ spin_lock(&ld->rxlock); ++ skb = ld->rx_skb[skb_id]; ++ if (unlikely(!skb)) { ++ spin_unlock(&ld->rxlock); ++ netdev_err(dev, "inconsistent rx_skb\n"); ++ break; ++ } ++ ++ /* data consistent check */ ++ if (unlikely(skb != ld->rx_fq.skb[skb_id])) { ++ netdev_err(dev, "desc->skb(0x%p),rx_fq.skb[%d](0x%p)\n", ++ skb, skb_id, ld->rx_fq.skb[skb_id]); ++ if (ld->rx_fq.skb[skb_id] == SKB_MAGIC) { ++ spin_unlock(&ld->rxlock); ++ goto next; ++ } ++ WARN_ON(1); ++ } else { ++ ld->rx_fq.skb[skb_id] = NULL; ++ } ++ spin_unlock(&ld->rxlock); ++ ++ len = desc->data_len; ++ ++ if (!HAS_CAP_CCI(ld->hw_cap)) { ++ addr = desc->data_buff_addr; ++ dma_unmap_single(ld->dev, addr, HIETH_MAX_FRAME_SIZE, ++ DMA_FROM_DEVICE); ++ } ++ ++ skb_put(skb, len); ++ if (skb->len > HIETH_MAX_FRAME_SIZE) { ++ netdev_err(dev, "rcv len err, len = %d\n", skb->len); ++ dev->stats.rx_errors++; ++ dev->stats.rx_length_errors++; ++ dev_kfree_skb_any(skb); ++ goto next; ++ } ++ ++ skb->protocol = eth_type_trans(skb, dev); ++ skb->ip_summed = CHECKSUM_NONE; ++#if defined(CONFIG_HIGMAC_RXCSUM) ++ if (dev->features & NETIF_F_RXCSUM) { ++ int hdr_csum_done = ++ desc->header_csum_done; ++ int payload_csum_done = ++ desc->payload_csum_done; ++ int hdr_csum_err = ++ desc->header_csum_err; ++ int payload_csum_err = ++ desc->payload_csum_err; ++ ++ if (hdr_csum_done && payload_csum_done) { ++ if (unlikely(hdr_csum_err || ++ payload_csum_err)) { ++ dev->stats.rx_errors++; ++ dev->stats.rx_crc_errors++; ++ dev_kfree_skb_any(skb); ++ goto next; ++ } else { ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ } ++ } ++ } ++#endif ++ if ((dev->features & NETIF_F_RXHASH) && desc->has_hash) ++ skb_set_hash(skb, desc->rxhash, desc->l3_hash ? ++ PKT_HASH_TYPE_L3 : PKT_HASH_TYPE_L4); ++ ++ skb_record_rx_queue(skb, rxq_id); ++ ++ napi_gro_receive(&ld->q_napi[rxq_id].napi, skb); ++ dev->stats.rx_packets++; ++ dev->stats.rx_bytes += len; ++ dev->last_rx = jiffies; ++next: ++ spin_lock(&ld->rxlock); ++ ld->rx_skb[skb_id] = NULL; ++ spin_unlock(&ld->rxlock); ++ pos = dma_ring_incr(pos, RX_DESC_NUM); ++ } ++ ++ if (pos != start) ++ writel(dma_byte(pos), ld->gmac_iobase + rx_bq_rd_reg); ++ ++ spin_lock(&ld->rxlock); ++ higmac_rx_refill(ld); ++ spin_unlock(&ld->rxlock); ++ ++ return num; ++} ++ ++#ifdef HIGMAC_TSO_DEBUG ++unsigned int id_send; ++unsigned int id_free; ++struct send_pkt_info pkt_rec[MAX_RECORD]; ++#endif ++ ++static int higmac_check_tx_err(struct higmac_netdev_local *ld, ++ struct higmac_tso_desc *tx_bq_desc, ++ unsigned int desc_pos) ++{ ++ unsigned int tx_err = tx_bq_desc->tx_err; ++ ++ if (unlikely(tx_err & ERR_ALL)) { ++ struct sg_desc *desc_cur; ++ int *sg_word; ++ int i; ++ ++ WARN((tx_err & ERR_ALL), ++ "TX ERR: desc1=0x%x, desc2=0x%x, desc5=0x%x\n", ++ tx_bq_desc->data_buff_addr, ++ tx_bq_desc->desc1.val, tx_bq_desc->tx_err); ++ ++ desc_cur = ld->dma_sg_desc + ld->tx_bq.sg_desc_offset[desc_pos]; ++ sg_word = (int *)desc_cur; ++ for (i = 0; i < sizeof(struct sg_desc) / sizeof(int); i++) ++ pr_err("%s,%d: sg_desc word[%d]=0x%x\n", ++ __func__, __LINE__, i, sg_word[i]); ++ ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int higmac_xmit_release_gso(struct higmac_netdev_local *ld, ++ struct higmac_tso_desc *tx_rq_desc, ++ unsigned int desc_pos) ++{ ++ int pkt_type; ++ int nfrags = tx_rq_desc->desc1.tx.nfrags_num; ++ dma_addr_t addr; ++ size_t len; ++ ++ if (unlikely(higmac_check_tx_err(ld, tx_rq_desc, desc_pos) < 0)) { ++ /* dev_close */ ++ higmac_irq_disable_all_queue(ld); ++ higmac_hw_desc_disable(ld); ++ ++ netif_carrier_off(ld->netdev); ++ netif_stop_queue(ld->netdev); ++ ++ phy_stop(ld->phy); ++ del_timer_sync(&ld->monitor); ++ return -1; ++ } ++ ++ if (tx_rq_desc->desc1.tx.tso_flag || nfrags) ++ pkt_type = PKT_SG; ++ else ++ pkt_type = PKT_NORMAL; ++ ++ if (pkt_type == PKT_NORMAL) { ++ if (!HAS_CAP_CCI(ld->hw_cap)) { ++ addr = tx_rq_desc->data_buff_addr; ++ len = tx_rq_desc->desc1.tx.data_len; ++ dma_unmap_single(ld->dev, addr, len, DMA_TO_DEVICE); ++ } ++ } else { ++ if (!HAS_CAP_CCI(ld->hw_cap)) { ++ struct sg_desc *desc_cur; ++ unsigned int desc_offset; ++ int i; ++ ++ desc_offset = ld->tx_bq.sg_desc_offset[desc_pos]; ++ WARN_ON(desc_offset != ld->sg_tail); ++ desc_cur = ld->dma_sg_desc + desc_offset; ++ ++ addr = desc_cur->linear_addr; ++ len = desc_cur->linear_len; ++ dma_unmap_single(ld->dev, addr, len, DMA_TO_DEVICE); ++ for (i = 0; i < nfrags; i++) { ++ addr = desc_cur->frags[i].addr; ++ len = desc_cur->frags[i].size; ++ dma_unmap_page(ld->dev, addr, len, ++ DMA_TO_DEVICE); ++ } ++ } ++ ++ ld->sg_tail = (ld->sg_tail + 1) % ld->sg_count; ++ } ++ ++#ifdef HIGMAC_TSO_DEBUG ++ pkt_rec[id_free].status = 0; ++ id_free++; ++ if (id_free == MAX_RECORD) ++ id_free = 0; ++#endif ++ ++ return 0; ++} ++ ++static void higmac_xmit_reclaim(struct net_device *dev) ++{ ++ struct sk_buff *skb; ++ struct higmac_desc *desc; ++ struct higmac_tso_desc *tso_desc; ++ struct higmac_netdev_local *priv = netdev_priv(dev); ++ unsigned int bytes_compl = 0, pkts_compl = 0; ++ u32 start, end, num, pos, i; ++ dma_addr_t addr; ++ int ret; ++ ++ spin_lock(&priv->txlock); ++ ++ /* software read */ ++ start = dma_cnt(readl(priv->gmac_iobase + TX_RQ_RD_ADDR)); ++ /* logic write */ ++ end = dma_cnt(readl(priv->gmac_iobase + TX_RQ_WR_ADDR)); ++ num = CIRC_CNT(end, start, TX_DESC_NUM); ++ ++ for (i = 0, pos = start; i < num; i++) { ++ skb = priv->tx_skb[pos]; ++ if (unlikely(!skb)) { ++ netdev_err(dev, "inconsistent tx_skb\n"); ++ break; ++ } ++ ++ if (skb != priv->tx_bq.skb[pos]) { ++ netdev_err(dev, "wired, tx skb[%d](%p) != skb(%p)\n", ++ pos, priv->tx_bq.skb[pos], skb); ++ if (priv->tx_bq.skb[pos] == SKB_MAGIC) ++ goto next; ++ } ++ ++ pkts_compl++; ++ bytes_compl += skb->len; ++ desc = priv->tx_rq.desc + pos; ++ if (priv->tso_supported) { ++ tso_desc = (struct higmac_tso_desc *)desc; ++ ret = higmac_xmit_release_gso(priv, tso_desc, pos); ++ if (ret < 0) ++ break; ++ } else if (!HAS_CAP_CCI(priv->hw_cap)) { ++ addr = desc->data_buff_addr; ++ dma_unmap_single(priv->dev, addr, skb->len, ++ DMA_TO_DEVICE); ++ } ++ priv->tx_bq.skb[pos] = NULL; ++next: ++ priv->tx_skb[pos] = NULL; ++ dev_consume_skb_any(skb); ++ pos = dma_ring_incr(pos, TX_DESC_NUM); ++ } ++ ++ if (pos != start) ++ writel(dma_byte(pos), priv->gmac_iobase + TX_RQ_RD_ADDR); ++ ++ if (pkts_compl || bytes_compl) ++ netdev_completed_queue(dev, pkts_compl, bytes_compl); ++ ++ if (unlikely(netif_queue_stopped(priv->netdev)) && pkts_compl) ++ netif_wake_queue(priv->netdev); ++ ++ spin_unlock(&priv->txlock); ++} ++ ++static int higmac_poll(struct napi_struct *napi, int budget) ++{ ++ struct higmac_napi *q_napi = container_of(napi, ++ struct higmac_napi, napi); ++ struct higmac_netdev_local *priv = q_napi->ndev_priv; ++ struct net_device *dev = priv->netdev; ++ int work_done = 0, task = budget; ++ u32 ints, num; ++ u32 raw_int_reg, raw_int_mask; ++ ++ if (q_napi->rxq_id) { ++ raw_int_reg = RSS_RAW_PMU_INT; ++ raw_int_mask = DEF_INT_MASK_QUEUE(q_napi->rxq_id); ++ } else { ++ raw_int_reg = RAW_PMU_INT; ++ raw_int_mask = DEF_INT_MASK; ++ } ++ ++ do { ++ if (!q_napi->rxq_id) ++ higmac_xmit_reclaim(dev); ++ num = higmac_rx(dev, task, q_napi->rxq_id); ++ work_done += num; ++ task -= num; ++ if (work_done >= budget) ++ break; ++ ++ ints = readl(priv->gmac_iobase + raw_int_reg); ++ ints &= raw_int_mask; ++ writel(ints, priv->gmac_iobase + raw_int_reg); ++ } while (ints); ++ ++ if (work_done < budget) { ++ napi_complete(napi); ++ higmac_irq_enable_queue(priv, q_napi->rxq_id); ++ } ++ ++ return work_done; ++} ++ ++static irqreturn_t higmac_interrupt(int irq, void *dev_id) ++{ ++ struct higmac_napi *q_napi = (struct higmac_napi *)dev_id; ++ struct higmac_netdev_local *ld = q_napi->ndev_priv; ++ u32 ints; ++ u32 raw_int_reg, raw_int_mask; ++ ++ if (higmac_queue_irq_disabled(ld, q_napi->rxq_id)) ++ return IRQ_NONE; ++ ++ if (q_napi->rxq_id) { ++ raw_int_reg = RSS_RAW_PMU_INT; ++ raw_int_mask = DEF_INT_MASK_QUEUE(q_napi->rxq_id); ++ } else { ++ raw_int_reg = RAW_PMU_INT; ++ raw_int_mask = DEF_INT_MASK; ++ } ++ ++ ints = readl(ld->gmac_iobase + raw_int_reg); ++ ints &= raw_int_mask; ++ writel(ints, ld->gmac_iobase + raw_int_reg); ++ ++ if (likely(ints)) { ++ higmac_irq_disable_queue(ld, q_napi->rxq_id); ++ napi_schedule(&q_napi->napi); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static inline __be16 higmac_get_l3_proto(struct sk_buff *skb) ++{ ++ __be16 l3_proto; ++ ++ l3_proto = skb->protocol; ++ if (skb->protocol == htons(ETH_P_8021Q)) ++ l3_proto = vlan_get_protocol(skb); ++ ++ return l3_proto; ++} ++ ++static inline unsigned int higmac_get_l4_proto(struct sk_buff *skb) ++{ ++ __be16 l3_proto; ++ unsigned int l4_proto = IPPROTO_MAX; ++ ++ l3_proto = higmac_get_l3_proto(skb); ++ if (l3_proto == htons(ETH_P_IP)) ++ l4_proto = ip_hdr(skb)->protocol; ++ else if (l3_proto == htons(ETH_P_IPV6)) ++ l4_proto = ipv6_hdr(skb)->nexthdr; ++ ++ return l4_proto; ++} ++ ++static inline bool higmac_skb_is_ipv6(struct sk_buff *skb) ++{ ++ return (higmac_get_l3_proto(skb) == htons(ETH_P_IPV6)); ++} ++ ++static inline bool higmac_skb_is_udp(struct sk_buff *skb) ++{ ++ return (higmac_get_l4_proto(skb) == IPPROTO_UDP); ++} ++ ++static int higmac_check_hw_capability_for_udp(struct sk_buff *skb) ++{ ++ struct ethhdr *eth; ++ ++ /* hardware can't dea with UFO broadcast packet */ ++ eth = (struct ethhdr *)(skb->data); ++ if (skb_is_gso(skb) && is_broadcast_ether_addr(eth->h_dest)) ++ return -ENOTSUPP; ++ ++ return 0; ++} ++ ++static int higmac_check_hw_capability_for_ipv6(struct sk_buff *skb) ++{ ++ unsigned int l4_proto = IPPROTO_MAX; ++ ++ l4_proto = ipv6_hdr(skb)->nexthdr; ++ ++ if ((l4_proto != IPPROTO_TCP) && (l4_proto != IPPROTO_UDP)) { ++ /* when IPv6 next header is not tcp or udp, ++ * it means that IPv6 next header is extension header. ++ * Hardware can't deal with this case, ++ * so do checksumming by software or do GSO by software. ++ */ ++ if (skb_is_gso(skb)) ++ return -ENOTSUPP; ++ ++ if (skb->ip_summed == CHECKSUM_PARTIAL && ++ skb_checksum_help(skb)) ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++static inline bool higmac_skb_is_ipv4_with_options(struct sk_buff *skb) ++{ ++ return ((higmac_get_l3_proto(skb) == htons(ETH_P_IP)) && ++ (ip_hdr(skb)->ihl > 5)); ++} ++ ++static int higmac_check_hw_capability(struct sk_buff *skb) ++{ ++ int ret = 0; ++ ++ /* if tcp_mtu_probe() use (2 * tp->mss_cache) as probe_size, ++ * the linear data length will be larger than 2048, ++ * the MAC can't handle it, so let the software do it. ++ */ ++ if (skb_is_gso(skb) && (skb_headlen(skb) > 2048)) ++ return -ENOTSUPP; ++ ++ if (higmac_skb_is_ipv6(skb)) { ++ ret = higmac_check_hw_capability_for_ipv6(skb); ++ if (ret) ++ return ret; ++ } ++ ++ if (higmac_skb_is_udp(skb)) { ++ ret = higmac_check_hw_capability_for_udp(skb); ++ if (ret) ++ return ret; ++ } ++ ++ if (((skb->ip_summed == CHECKSUM_PARTIAL) || skb_is_gso(skb)) && ++ higmac_skb_is_ipv4_with_options(skb)) ++ return -ENOTSUPP; ++ ++ return 0; ++} ++ ++static void higmac_do_udp_checksum(struct sk_buff *skb) ++{ ++ int offset; ++ __wsum csum; ++ __sum16 udp_csum; ++ ++ offset = skb_checksum_start_offset(skb); ++ WARN_ON(offset >= skb_headlen(skb)); ++ csum = skb_checksum(skb, offset, skb->len - offset, 0); ++ ++ offset += skb->csum_offset; ++ WARN_ON(offset + sizeof(__sum16) > skb_headlen(skb)); ++ udp_csum = csum_fold(csum); ++ if (udp_csum == 0) ++ udp_csum = CSUM_MANGLED_0; ++ ++ *(__sum16 *)(skb->data + offset) = udp_csum; ++ ++ skb->ip_summed = CHECKSUM_NONE; ++} ++ ++static void higmac_get_pkt_info(struct higmac_netdev_local *ld, ++ struct sk_buff *skb, ++ struct higmac_tso_desc *tx_bq_desc) ++{ ++ int nfrags = skb_shinfo(skb)->nr_frags; ++ ++ __be16 l3_proto; /* level 3 protocol */ ++ unsigned int l4_proto = IPPROTO_MAX; ++ unsigned int max_mss = ETH_DATA_LEN; ++ unsigned char coe_enable = 0; ++ int max_data_len = skb->len - ETH_HLEN; ++ ++ if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) ++ coe_enable = 1; ++ ++ tx_bq_desc->desc1.val = 0; ++ ++ if (skb_is_gso(skb)) { ++ tx_bq_desc->desc1.tx.tso_flag = 1; ++ tx_bq_desc->desc1.tx.sg_flag = 1; ++ } else if (nfrags) { ++ tx_bq_desc->desc1.tx.sg_flag = 1; ++ } ++ ++ l3_proto = skb->protocol; ++ if (skb->protocol == htons(ETH_P_8021Q)) { ++ l3_proto = vlan_get_protocol(skb); ++ tx_bq_desc->desc1.tx.vlan_flag = 1; ++ max_data_len -= VLAN_HLEN; ++ } ++ ++ if (l3_proto == htons(ETH_P_IP)) { ++ struct iphdr *iph; ++ ++ iph = ip_hdr(skb); ++ tx_bq_desc->desc1.tx.ip_ver = PKT_IPV4; ++ tx_bq_desc->desc1.tx.ip_hdr_len = iph->ihl; ++ ++ if ((max_data_len >= GSO_MAX_SIZE) && ++ (ntohs(iph->tot_len) <= (iph->ihl << 2))) ++ iph->tot_len = htons(GSO_MAX_SIZE - 1); ++ ++ max_mss -= iph->ihl * WORD_TO_BYTE; ++ l4_proto = iph->protocol; ++ } else if (l3_proto == htons(ETH_P_IPV6)) { ++ tx_bq_desc->desc1.tx.ip_ver = PKT_IPV6; ++ tx_bq_desc->desc1.tx.ip_hdr_len = PKT_IPV6_HDR_LEN; ++ max_mss -= PKT_IPV6_HDR_LEN * WORD_TO_BYTE; ++ l4_proto = ipv6_hdr(skb)->nexthdr; ++ } else { ++ coe_enable = 0; ++ } ++ ++ if (l4_proto == IPPROTO_TCP) { ++ tx_bq_desc->desc1.tx.prot_type = PKT_TCP; ++ tx_bq_desc->desc1.tx.prot_hdr_len = tcp_hdr(skb)->doff; ++ max_mss -= tcp_hdr(skb)->doff * WORD_TO_BYTE; ++ } else if (l4_proto == IPPROTO_UDP) { ++ tx_bq_desc->desc1.tx.prot_type = PKT_UDP; ++ tx_bq_desc->desc1.tx.prot_hdr_len = PKT_UDP_HDR_LEN; ++ if (l3_proto == htons(ETH_P_IPV6)) ++ max_mss -= sizeof(struct frag_hdr); ++ } else { ++ coe_enable = 0; ++ } ++ ++ if (skb_is_gso(skb)) ++ tx_bq_desc->desc1.tx.data_len = ++ (skb_shinfo(skb)->gso_size > max_mss) ? max_mss : ++ skb_shinfo(skb)->gso_size; ++ else ++ tx_bq_desc->desc1.tx.data_len = skb->len; ++ ++ if (coe_enable && skb_is_gso(skb) && (l4_proto == IPPROTO_UDP)) ++ higmac_do_udp_checksum(skb); ++ ++ if (coe_enable) ++ tx_bq_desc->desc1.tx.coe_flag = 1; ++ ++ tx_bq_desc->desc1.tx.nfrags_num = nfrags; ++ ++ tx_bq_desc->desc1.tx.hw_own = DESC_VLD_BUSY; ++} ++ ++static int higmac_xmit_gso(struct higmac_netdev_local *ld, struct sk_buff *skb, ++ struct higmac_tso_desc *tx_bq_desc, ++ unsigned int desc_pos) ++{ ++ int pkt_type = PKT_NORMAL; ++ int nfrags = skb_shinfo(skb)->nr_frags; ++ dma_addr_t addr; ++ int ret; ++ ++ if (skb_is_gso(skb) || nfrags) { ++ /* TSO pkt or SG pkt */ ++ pkt_type = PKT_SG; ++ } else { /* Normal pkt */ ++ pkt_type = PKT_NORMAL; ++ } ++ ++ ret = higmac_check_hw_capability(skb); ++ if (unlikely(ret)) ++ return ret; ++ ++ higmac_get_pkt_info(ld, skb, tx_bq_desc); ++ ++ if (pkt_type == PKT_NORMAL) { ++ if (!HAS_CAP_CCI(ld->hw_cap)) { ++ addr = dma_map_single(ld->dev, skb->data, skb->len, ++ DMA_TO_DEVICE); ++ ret = dma_mapping_error(ld->dev, addr); ++ if (unlikely(ret)) { ++ pr_err("Normal Packet DMA Mapping fail.\n"); ++ return -EFAULT; ++ } ++ tx_bq_desc->data_buff_addr = addr; ++ } else { ++ tx_bq_desc->data_buff_addr = virt_to_phys(skb->data); ++ } ++ } else { ++ struct sg_desc *desc_cur; ++ int i; ++ ++ if (unlikely(((ld->sg_head + 1) % ld->sg_count) == ++ ld->sg_tail)) { ++ /* SG pkt, but sg desc all used */ ++ pr_err("WARNING: sg desc all used.\n"); ++ return -EBUSY; ++ } ++ ++ desc_cur = ld->dma_sg_desc + ld->sg_head; ++ ++ /* TODO: deal with ipv6_id */ ++ if (tx_bq_desc->desc1.tx.tso_flag && ++ tx_bq_desc->desc1.tx.ip_ver == PKT_IPV6 && ++ tx_bq_desc->desc1.tx.prot_type == PKT_UDP) { ++ desc_cur->ipv6_id = ntohl(skb_shinfo(skb)->ip6_frag_id); ++ } ++ ++ desc_cur->total_len = skb->len; ++ desc_cur->linear_len = skb_headlen(skb); ++ if (!HAS_CAP_CCI(ld->hw_cap)) { ++ addr = dma_map_single(ld->dev, skb->data, ++ desc_cur->linear_len, ++ DMA_TO_DEVICE); ++ ret = dma_mapping_error(ld->dev, addr); ++ if (unlikely(ret)) { ++ pr_err("DMA Mapping fail."); ++ return -EFAULT; ++ } ++ desc_cur->linear_addr = addr; ++ } else { ++ desc_cur->linear_addr = virt_to_phys(skb->data); ++ } ++ ++ for (i = 0; i < nfrags; i++) { ++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ++ int len = frag->size; ++ ++ if (!HAS_CAP_CCI(ld->hw_cap)) { ++ addr = skb_frag_dma_map(ld->dev, frag, 0, len, ++ DMA_TO_DEVICE); ++ ret = dma_mapping_error(ld->dev, addr); ++ if (unlikely(ret)) { ++ pr_err("skb frag DMA Mapping fail."); ++ return -EFAULT; ++ } ++ desc_cur->frags[i].addr = addr; ++ } else { ++ desc_cur->frags[i].addr = ++ page_to_phys(skb_frag_page(frag)) + ++ frag->page_offset; ++ } ++ desc_cur->frags[i].size = len; ++ } ++ tx_bq_desc->data_buff_addr = ld->dma_sg_phy + ++ ld->sg_head * sizeof(struct sg_desc); ++ ld->tx_bq.sg_desc_offset[desc_pos] = ld->sg_head; ++ ++ ld->sg_head = (ld->sg_head + 1) % ld->sg_count; ++ } ++ ++#ifdef HIGMAC_TSO_DEBUG ++ memcpy(&pkt_rec[id_send].desc, tx_bq_desc, ++ sizeof(struct higmac_tso_desc)); ++ pkt_rec[id_send].status = 1; ++ id_send++; ++ if (id_send == MAX_RECORD) ++ id_send = 0; ++#endif ++ return 0; ++} ++ ++static netdev_tx_t higmac_net_xmit(struct sk_buff *skb, struct net_device *dev); ++ ++static netdev_tx_t higmac_sw_gso(struct higmac_netdev_local *ld, ++ struct sk_buff *skb) ++{ ++ struct sk_buff *segs, *curr_skb; ++ int gso_segs = skb_shinfo(skb)->gso_segs; ++ ++ if (gso_segs == 0 && skb_shinfo(skb)->gso_size != 0) ++ gso_segs = DIV_ROUND_UP(skb->len, skb_shinfo(skb)->gso_size); ++ ++ /* Estimate the number of fragments in the worst case */ ++ if (unlikely(higmac_tx_avail(ld) < gso_segs)) { ++ netif_stop_queue(ld->netdev); ++ if (higmac_tx_avail(ld) < gso_segs) { ++ ld->netdev->stats.tx_dropped++; ++ ld->netdev->stats.tx_fifo_errors++; ++ return NETDEV_TX_BUSY; ++ } ++ ++ netif_wake_queue(ld->netdev); ++ } ++ ++ segs = skb_gso_segment(skb, ld->netdev->features & ~(NETIF_F_CSUM_MASK | ++ NETIF_F_SG | NETIF_F_GSO_SOFTWARE)); ++ ++ if (IS_ERR_OR_NULL(segs)) ++ goto drop; ++ ++ do { ++ curr_skb = segs; ++ segs = segs->next; ++ curr_skb->next = NULL; ++ higmac_net_xmit(curr_skb, ld->netdev); ++ } while (segs); ++ ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++ ++drop: ++ dev_kfree_skb_any(skb); ++ ld->netdev->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++} ++ ++static netdev_tx_t higmac_net_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(dev); ++ struct higmac_desc *desc; ++ dma_addr_t addr; ++ unsigned long txflags; ++ int ret; ++ u32 pos; ++ ++ if (skb->len < ETH_HLEN) { ++ dev_kfree_skb_any(skb); ++ dev->stats.tx_errors++; ++ dev->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++ } ++ ++ /* if adding higmac_xmit_reclaim here, iperf tcp client ++ * performance will be affected, from 550M(avg) to 513M~300M ++ */ ++ ++ /* software write pointer */ ++ pos = dma_cnt(readl(ld->gmac_iobase + TX_BQ_WR_ADDR)); ++ ++ spin_lock_irqsave(&ld->txlock, txflags); ++ ++ if (unlikely(ld->tx_skb[pos] || ld->tx_bq.skb[pos])) { ++ dev->stats.tx_dropped++; ++ dev->stats.tx_fifo_errors++; ++ netif_stop_queue(dev); ++ spin_unlock_irqrestore(&ld->txlock, txflags); ++ ++ return NETDEV_TX_BUSY; ++ } ++ ++ ld->tx_bq.skb[pos] = skb; ++ ld->tx_skb[pos] = skb; ++ ++ desc = ld->tx_bq.desc + pos; ++ ++ if (ld->tso_supported) { ++ ret = higmac_xmit_gso(ld, skb, ++ (struct higmac_tso_desc *)desc, ++ pos); ++ if (unlikely(ret < 0)) { ++ ld->tx_skb[pos] = NULL; ++ ld->tx_bq.skb[pos] = NULL; ++ spin_unlock_irqrestore(&ld->txlock, txflags); ++ ++ if (ret == -ENOTSUPP) ++ return higmac_sw_gso(ld, skb); ++ ++ dev_kfree_skb_any(skb); ++ dev->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++ } ++ } else { ++ if (!HAS_CAP_CCI(ld->hw_cap)) { ++ addr = dma_map_single(ld->dev, skb->data, skb->len, ++ DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(ld->dev, addr))) { ++ dev_kfree_skb_any(skb); ++ dev->stats.tx_dropped++; ++ ld->tx_skb[pos] = NULL; ++ ld->tx_bq.skb[pos] = NULL; ++ spin_unlock_irqrestore(&ld->txlock, txflags); ++ return NETDEV_TX_OK; ++ } ++ desc->data_buff_addr = addr; ++ } else { ++ desc->data_buff_addr = virt_to_phys(skb->data); ++ } ++ desc->buffer_len = HIETH_MAX_FRAME_SIZE - 1; ++ desc->data_len = skb->len; ++ desc->fl = DESC_FL_FULL; ++ desc->descvid = DESC_VLD_BUSY; ++ } ++ ++ /* This barrier is important here. It is required to ensure ++ * the ARM CPU flushes it's DMA write buffers before proceeding ++ * to the next instruction, to ensure that GMAC will see ++ * our descriptor changes in memory ++ */ ++ HIGMAC_SYNC_BARRIER(); ++ ++ pos = dma_ring_incr(pos, TX_DESC_NUM); ++ writel(dma_byte(pos), ld->gmac_iobase + TX_BQ_WR_ADDR); ++ ++ netif_trans_update(dev); ++ dev->stats.tx_packets++; ++ dev->stats.tx_bytes += skb->len; ++ netdev_sent_queue(dev, skb->len); ++ ++ spin_unlock_irqrestore(&ld->txlock, txflags); ++ ++ return NETDEV_TX_OK; ++} ++ ++void higmac_enable_napi(struct higmac_netdev_local *priv) ++{ ++ struct higmac_napi *q_napi; ++ int i; ++ ++ for (i = 0; i < priv->num_rxqs; i++) { ++ q_napi = &priv->q_napi[i]; ++ napi_enable(&q_napi->napi); ++ } ++} ++ ++void higmac_disable_napi(struct higmac_netdev_local *priv) ++{ ++ struct higmac_napi *q_napi; ++ int i; ++ ++ for (i = 0; i < priv->num_rxqs; i++) { ++ q_napi = &priv->q_napi[i]; ++ napi_disable(&q_napi->napi); ++ } ++} ++ ++static int higmac_net_open(struct net_device *dev) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(dev); ++ unsigned long flags; ++ ++ clk_prepare_enable(ld->macif_clk); ++ clk_prepare_enable(ld->clk); ++ ++ /* If we configure mac address by ++ * "ifconfig ethX hw ether XX:XX:XX:XX:XX:XX", ++ * the ethX must be down state and mac core clock is disabled ++ * which results the mac address has not been configured ++ * in mac core register. ++ * So we must set mac address again here, ++ * because mac core clock is enabled at this time ++ * and we can configure mac address to mac core register. ++ */ ++ higmac_hw_set_mac_addr(dev); ++ ++ /* We should use netif_carrier_off() here, ++ * because the default state should be off. ++ * And this call should before phy_start(). ++ */ ++ netif_carrier_off(dev); ++ higmac_enable_napi(ld); ++ phy_start(ld->phy); ++ ++ higmac_hw_desc_enable(ld); ++ higmac_port_enable(ld); ++ higmac_irq_enable_all_queue(ld); ++ ++ spin_lock_irqsave(&ld->rxlock, flags); ++ higmac_rx_refill(ld); ++ spin_unlock_irqrestore(&ld->rxlock, flags); ++ ++ ld->monitor.expires = jiffies + HIGMAC_MONITOR_TIMER; ++ mod_timer(&ld->monitor, ld->monitor.expires); ++ ++ netif_start_queue(dev); ++ ++ return 0; ++} ++ ++static int higmac_net_close(struct net_device *dev) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(dev); ++ ++ higmac_irq_disable_all_queue(ld); ++ higmac_hw_desc_disable(ld); ++ ++ higmac_disable_napi(ld); ++ ++ netif_carrier_off(dev); ++ netif_stop_queue(dev); ++ ++ phy_stop(ld->phy); ++ del_timer_sync(&ld->monitor); ++ ++ clk_disable_unprepare(ld->clk); ++ clk_disable_unprepare(ld->macif_clk); ++ ++ return 0; ++} ++ ++static void higmac_net_timeout(struct net_device *dev) ++{ ++ dev->stats.tx_errors++; ++ ++ pr_err("tx timeout!\n"); ++} ++ ++static void higmac_set_multicast_list(struct net_device *dev) ++{ ++ higmac_gmac_multicast_list(dev); ++} ++ ++static inline void higmac_enable_rxcsum_drop(struct higmac_netdev_local *ld, ++ bool drop) ++{ ++ unsigned int v; ++ ++ v = readl(ld->gmac_iobase + TSO_COE_CTRL); ++ if (drop) ++ v |= COE_ERR_DROP; ++ else ++ v &= ~COE_ERR_DROP; ++ writel(v, ld->gmac_iobase + TSO_COE_CTRL); ++} ++ ++static int higmac_set_features(struct net_device *dev, ++ netdev_features_t features) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(dev); ++ netdev_features_t changed = dev->features ^ features; ++ ++ if (changed & NETIF_F_RXCSUM) { ++ if (features & NETIF_F_RXCSUM) ++ higmac_enable_rxcsum_drop(ld, true); ++ else ++ higmac_enable_rxcsum_drop(ld, false); ++ } ++ ++ return 0; ++} ++ ++static struct net_device_stats *higmac_net_get_stats(struct net_device *dev) ++{ ++ return &dev->stats; ++} ++ ++static void higmac_get_drvinfo(struct net_device *net_dev, ++ struct ethtool_drvinfo *info) ++{ ++ strncpy(info->driver, "higmac driver", 15); ++ strncpy(info->version, "higmac v200", 15); ++ strncpy(info->bus_info, "platform", 15); ++} ++ ++static unsigned int higmac_get_link(struct net_device *net_dev) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(net_dev); ++ ++ return ld->phy->link ? HIGMAC_LINKED : 0; ++} ++ ++static int higmac_get_settings(struct net_device *net_dev, ++ struct ethtool_cmd *cmd) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(net_dev); ++ ++ if (ld->phy) ++ return phy_ethtool_gset(ld->phy, cmd); ++ ++ return -EINVAL; ++} ++ ++static int higmac_set_settings(struct net_device *net_dev, ++ struct ethtool_cmd *cmd) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(net_dev); ++ ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ ++ if (ld->phy) ++ return phy_ethtool_sset(ld->phy, cmd); ++ ++ return -EINVAL; ++} ++ ++static void higmac_get_pauseparam(struct net_device *net_dev, ++ struct ethtool_pauseparam *pause) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(net_dev); ++ ++ pause->rx_pause = 0; ++ pause->tx_pause = 0; ++ pause->autoneg = ld->phy->autoneg; ++ ++ if (ld->flow_ctrl & FLOW_RX) ++ pause->rx_pause = 1; ++ if (ld->flow_ctrl & FLOW_TX) ++ pause->tx_pause = 1; ++} ++ ++static int higmac_set_pauseparam(struct net_device *net_dev, ++ struct ethtool_pauseparam *pause) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(net_dev); ++ struct phy_device *phy = ld->phy; ++ int new_pause = FLOW_OFF; ++ int ret = 0; ++ ++ if (pause->rx_pause) ++ new_pause |= FLOW_RX; ++ if (pause->tx_pause) ++ new_pause |= FLOW_TX; ++ ++ if (new_pause != ld->flow_ctrl) ++ ld->flow_ctrl = new_pause; ++ ++ higmac_set_flow_ctrl_state(ld, phy->pause); ++ phy->advertising &= ~SUPPORTED_Pause; ++ if (ld->flow_ctrl) ++ phy->advertising |= SUPPORTED_Pause; ++ ++ if (phy->autoneg) { ++ if (netif_running(net_dev)) ++ return phy_start_aneg(phy); ++ } ++ ++ return ret; ++} ++ ++static u32 higmac_ethtool_getmsglevel(struct net_device *ndev) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ ++ return priv->msg_enable; ++} ++ ++static void higmac_ethtool_setmsglevel(struct net_device *ndev, u32 level) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ ++ priv->msg_enable = level; ++} ++ ++static u32 higmac_get_rxfh_key_size(struct net_device *ndev) ++{ ++ return RSS_HASH_KEY_SIZE; ++} ++ ++static u32 higmac_get_rxfh_indir_size(struct net_device *ndev) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ ++ return priv->rss_info.ind_tbl_size; ++} ++ ++static int higmac_get_rxfh(struct net_device *ndev, u32 *indir, u8 *hkey, ++ u8 *hfunc) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ struct higmac_rss_info *rss = &priv->rss_info; ++ ++ if (hfunc) ++ *hfunc = ETH_RSS_HASH_TOP; ++ ++ if (hkey) ++ memcpy(hkey, rss->key, RSS_HASH_KEY_SIZE); ++ ++ if (indir) { ++ int i; ++ ++ for (i = 0; i < rss->ind_tbl_size; i++) ++ indir[i] = rss->ind_tbl[i]; ++ } ++ ++ return 0; ++} ++ ++static void higmac_get_rss_key(struct higmac_netdev_local *priv) ++{ ++ struct higmac_rss_info *rss = &priv->rss_info; ++ u32 hkey; ++ ++ hkey = readl(priv->gmac_iobase + RSS_HASH_KEY); ++ *((u32 *)rss->key) = hkey; ++} ++ ++static void higmac_set_rss_key(struct higmac_netdev_local *priv) ++{ ++ struct higmac_rss_info *rss = &priv->rss_info; ++ ++ writel(*((u32 *)rss->key), priv->gmac_iobase + RSS_HASH_KEY); ++} ++ ++static int higmac_wait_rss_ready(struct higmac_netdev_local *priv) ++{ ++ void __iomem *base = priv->gmac_iobase; ++ int i, timeout = 10000; ++ ++ for (i = 0; !(readl(base + RSS_IND_TBL) & BIT_IND_TBL_READY); i++) { ++ if (i == timeout) { ++ netdev_err(priv->netdev, "wait rss ready timeout!\n"); ++ return -ETIMEDOUT; ++ } ++ usleep_range(10, 20); ++ } ++ ++ return 0; ++} ++ ++static void higmac_config_rss(struct higmac_netdev_local *priv) ++{ ++ struct higmac_rss_info *rss = &priv->rss_info; ++ u32 rss_val; ++ int i; ++ ++ for (i = 0; i < rss->ind_tbl_size; i++) { ++ if (higmac_wait_rss_ready(priv)) ++ break; ++ rss_val = BIT_IND_TLB_WR | (rss->ind_tbl[i] << 8) | i; ++ writel(rss_val, priv->gmac_iobase + RSS_IND_TBL); ++ } ++} ++ ++static void higmac_get_rss(struct higmac_netdev_local *priv) ++{ ++ struct higmac_rss_info *rss = &priv->rss_info; ++ u32 rss_val; ++ int i; ++ ++ for (i = 0; i < rss->ind_tbl_size; i++) { ++ if (higmac_wait_rss_ready(priv)) ++ break; ++ writel(i, priv->gmac_iobase + RSS_IND_TBL); ++ if (higmac_wait_rss_ready(priv)) ++ break; ++ rss_val = readl(priv->gmac_iobase + RSS_IND_TBL); ++ rss->ind_tbl[i] = (rss_val >> 10) & 0x3; ++ } ++} ++ ++static int higmac_set_rxfh(struct net_device *ndev, const u32 *indir, ++ const u8 *hkey, const u8 hfunc) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ struct higmac_rss_info *rss = &priv->rss_info; ++ ++ if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) ++ return -EOPNOTSUPP; ++ ++ if (indir) { ++ int i; ++ ++ for (i = 0; i < rss->ind_tbl_size; i++) ++ rss->ind_tbl[i] = indir[i]; ++ } ++ ++ if (hkey) { ++ memcpy(rss->key, hkey, RSS_HASH_KEY_SIZE); ++ higmac_set_rss_key(priv); ++ } ++ ++ higmac_config_rss(priv); ++ ++ return 0; ++} ++ ++static int higmac_get_rss_hash_opts(struct higmac_netdev_local *priv, ++ struct ethtool_rxnfc *info) ++{ ++ u32 hash_cfg = priv->rss_info.hash_cfg; ++ ++ info->data = 0; ++ ++ switch (info->flow_type) { ++ case TCP_V4_FLOW: ++ if (hash_cfg & TCPV4_L3_HASH_EN) ++ info->data |= RXH_IP_SRC | RXH_IP_DST; ++ if (hash_cfg & TCPV4_L4_HASH_EN) ++ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; ++ if (hash_cfg & TCPV4_VLAN_HASH_EN) ++ info->data |= RXH_VLAN; ++ break; ++ case TCP_V6_FLOW: ++ if (hash_cfg & TCPV6_L3_HASH_EN) ++ info->data |= RXH_IP_SRC | RXH_IP_DST; ++ if (hash_cfg & TCPV6_L4_HASH_EN) ++ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; ++ if (hash_cfg & TCPV6_VLAN_HASH_EN) ++ info->data |= RXH_VLAN; ++ break; ++ case UDP_V4_FLOW: ++ if (hash_cfg & UDPV4_L3_HASH_EN) ++ info->data |= RXH_IP_SRC | RXH_IP_DST; ++ if (hash_cfg & UDPV4_L4_HASH_EN) ++ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; ++ if (hash_cfg & UDPV4_VLAN_HASH_EN) ++ info->data |= RXH_VLAN; ++ break; ++ case UDP_V6_FLOW: ++ if (hash_cfg & UDPV6_L3_HASH_EN) ++ info->data |= RXH_IP_SRC | RXH_IP_DST; ++ if (hash_cfg & UDPV6_L4_HASH_EN) ++ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; ++ if (hash_cfg & UDPV6_VLAN_HASH_EN) ++ info->data |= RXH_VLAN; ++ break; ++ case IPV4_FLOW: ++ if (hash_cfg & IPV4_L3_HASH_EN) ++ info->data |= RXH_IP_SRC | RXH_IP_DST; ++ if (hash_cfg & IPV4_VLAN_HASH_EN) ++ info->data |= RXH_VLAN; ++ break; ++ case IPV6_FLOW: ++ if (hash_cfg & IPV6_L3_HASH_EN) ++ info->data |= RXH_IP_SRC | RXH_IP_DST; ++ if (hash_cfg & IPV6_VLAN_HASH_EN) ++ info->data |= RXH_VLAN; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int higmac_get_rxnfc(struct net_device *ndev, ++ struct ethtool_rxnfc *info, u32 *rules) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ int ret = -EOPNOTSUPP; ++ ++ switch (info->cmd) { ++ case ETHTOOL_GRXRINGS: ++ info->data = priv->num_rxqs; ++ ret = 0; ++ break; ++ case ETHTOOL_GRXFH: ++ return higmac_get_rss_hash_opts(priv, info); ++ default: ++ break; ++ } ++ return ret; ++} ++ ++static void higmac_config_hash_policy(struct higmac_netdev_local *priv) ++{ ++ writel(priv->rss_info.hash_cfg, priv->gmac_iobase + RSS_HASH_CONFIG); ++} ++ ++static int higmac_set_rss_hash_opts(struct higmac_netdev_local *priv, ++ struct ethtool_rxnfc *info) ++{ ++ u32 hash_cfg = priv->rss_info.hash_cfg; ++ ++ netdev_info(priv->netdev, "Set RSS flow type = %d, data = %lld\n", ++ info->flow_type, info->data); ++ ++ if (!(info->data & RXH_IP_SRC) || !(info->data & RXH_IP_DST)) ++ return -EINVAL; ++ ++ switch (info->flow_type) { ++ case TCP_V4_FLOW: ++ switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { ++ case 0: ++ hash_cfg &= ~TCPV4_L4_HASH_EN; ++ break; ++ case (RXH_L4_B_0_1 | RXH_L4_B_2_3): ++ hash_cfg |= TCPV4_L4_HASH_EN; ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (info->data & RXH_VLAN) ++ hash_cfg |= TCPV4_VLAN_HASH_EN; ++ else ++ hash_cfg &= ~TCPV4_VLAN_HASH_EN; ++ break; ++ case TCP_V6_FLOW: ++ switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { ++ case 0: ++ hash_cfg &= ~TCPV6_L4_HASH_EN; ++ break; ++ case (RXH_L4_B_0_1 | RXH_L4_B_2_3): ++ hash_cfg |= TCPV6_L4_HASH_EN; ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (info->data & RXH_VLAN) ++ hash_cfg |= TCPV6_VLAN_HASH_EN; ++ else ++ hash_cfg &= ~TCPV6_VLAN_HASH_EN; ++ break; ++ case UDP_V4_FLOW: ++ switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { ++ case 0: ++ hash_cfg &= ~UDPV4_L4_HASH_EN; ++ break; ++ case (RXH_L4_B_0_1 | RXH_L4_B_2_3): ++ hash_cfg |= UDPV4_L4_HASH_EN; ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (info->data & RXH_VLAN) ++ hash_cfg |= UDPV4_VLAN_HASH_EN; ++ else ++ hash_cfg &= ~UDPV4_VLAN_HASH_EN; ++ break; ++ case UDP_V6_FLOW: ++ switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { ++ case 0: ++ hash_cfg &= ~UDPV6_L4_HASH_EN; ++ break; ++ case (RXH_L4_B_0_1 | RXH_L4_B_2_3): ++ hash_cfg |= UDPV6_L4_HASH_EN; ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (info->data & RXH_VLAN) ++ hash_cfg |= UDPV6_VLAN_HASH_EN; ++ else ++ hash_cfg &= ~UDPV6_VLAN_HASH_EN; ++ break; ++ case IPV4_FLOW: ++ if (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) ++ return -EINVAL; ++ if (info->data & RXH_VLAN) ++ hash_cfg |= IPV4_VLAN_HASH_EN; ++ else ++ hash_cfg &= ~IPV4_VLAN_HASH_EN; ++ break; ++ case IPV6_FLOW: ++ if (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) ++ return -EINVAL; ++ if (info->data & RXH_VLAN) ++ hash_cfg |= IPV6_VLAN_HASH_EN; ++ else ++ hash_cfg &= ~IPV6_VLAN_HASH_EN; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ priv->rss_info.hash_cfg = hash_cfg; ++ higmac_config_hash_policy(priv); ++ ++ return 0; ++} ++ ++static int higmac_set_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *info) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ ++ switch (info->cmd) { ++ case ETHTOOL_SRXFH: ++ return higmac_set_rss_hash_opts(priv, info); ++ default: ++ break; ++ } ++ return -EOPNOTSUPP; ++} ++ ++static const struct ethtool_ops hieth_ethtools_ops = { ++ .get_drvinfo = higmac_get_drvinfo, ++ .get_link = higmac_get_link, ++ .get_settings = higmac_get_settings, ++ .set_settings = higmac_set_settings, ++ .get_pauseparam = higmac_get_pauseparam, ++ .set_pauseparam = higmac_set_pauseparam, ++ .get_msglevel = higmac_ethtool_getmsglevel, ++ .set_msglevel = higmac_ethtool_setmsglevel, ++ .get_rxfh_key_size = higmac_get_rxfh_key_size, ++ .get_rxfh_indir_size = higmac_get_rxfh_indir_size, ++ .get_rxfh = higmac_get_rxfh, ++ .set_rxfh = higmac_set_rxfh, ++ .get_rxnfc = higmac_get_rxnfc, ++ .set_rxnfc = higmac_set_rxnfc, ++}; ++ ++static const struct net_device_ops hieth_netdev_ops = { ++ .ndo_open = higmac_net_open, ++ .ndo_stop = higmac_net_close, ++ .ndo_start_xmit = higmac_net_xmit, ++ .ndo_tx_timeout = higmac_net_timeout, ++ .ndo_set_rx_mode = higmac_set_multicast_list, ++ .ndo_set_features = higmac_set_features, ++ .ndo_do_ioctl = higmac_ioctl, ++ .ndo_set_mac_address = higmac_net_set_mac_address, ++ .ndo_change_mtu = eth_change_mtu, ++ .ndo_get_stats = higmac_net_get_stats, ++}; ++ ++static int higmac_of_get_param(struct higmac_netdev_local *ld, ++ struct device_node *node) ++{ ++ /* get auto eee */ ++ ld->autoeee = of_property_read_bool(node, "autoeee"); ++ /* get internal flag */ ++ ld->internal_phy = ++ of_property_read_bool(node, "internal-phy"); ++ ++ return 0; ++} ++ ++static int KSZ8051MNL_phy_fix(struct phy_device *phy_dev) ++{ ++ u32 v; ++ int ret; ++ ++ if (phy_dev->interface != PHY_INTERFACE_MODE_RMII) ++ return 0; ++ ++ ret = phy_read(phy_dev, 0x1F); ++ if (ret < 0) ++ return ret; ++ v = ret; ++ v |= (1 << 7); /* set phy RMII 50MHz clk; */ ++ phy_write(phy_dev, 0x1F, v); ++ ++ ret = phy_read(phy_dev, 0x16); ++ if (ret < 0) ++ return ret; ++ v = ret; ++ v |= (1 << 1); /* set phy RMII override; */ ++ phy_write(phy_dev, 0x16, v); ++ ++ return 0; ++} ++ ++static int KSZ8081RNB_phy_fix(struct phy_device *phy_dev) ++{ ++ u32 v; ++ int ret; ++ ++ if (phy_dev->interface != PHY_INTERFACE_MODE_RMII) ++ return 0; ++ ++ ret = phy_read(phy_dev, 0x1F); ++ if (ret < 0) ++ return ret; ++ v = ret; ++ v |= (1 << 7); /* set phy RMII 50MHz clk; */ ++ phy_write(phy_dev, 0x1F, v); ++ ++ return 0; ++} ++ ++static int rtl8211e_phy_fix(struct phy_device *phy_dev) ++{ ++ u32 v; ++ int ret; ++ ++ /* select Extension page */ ++ phy_write(phy_dev, 0x1f, 0x7); ++ /* switch ExtPage 164 */ ++ phy_write(phy_dev, 0x1e, 0xa4); ++ ++ /* config RGMII rx pin io driver max */ ++ ret = phy_read(phy_dev, 0x1c); ++ if (ret < 0) ++ return ret; ++ v = ret; ++ v = (v & 0xff03) | 0xfc; ++ phy_write(phy_dev, 0x1c, v); ++ ++ /* select to page 0 */ ++ phy_write(phy_dev, 0x1f, 0); ++ ++ return 0; ++} ++ ++static void phy_register_fixups(void) ++{ ++ phy_register_fixup_for_uid(PHY_ID_KSZ8051MNL, DEFAULT_PHY_MASK, ++ KSZ8051MNL_phy_fix); ++ phy_register_fixup_for_uid(PHY_ID_KSZ8081RNB, DEFAULT_PHY_MASK, ++ KSZ8081RNB_phy_fix); ++ phy_register_fixup_for_uid(REALTEK_PHY_ID_8211E, REALTEK_PHY_MASK, ++ rtl8211e_phy_fix); ++} ++ ++static void phy_unregister_fixups(void) ++{ ++ phy_unregister_fixup_for_uid(PHY_ID_KSZ8051MNL, DEFAULT_PHY_MASK); ++ phy_unregister_fixup_for_uid(PHY_ID_KSZ8081RNB, DEFAULT_PHY_MASK); ++ phy_unregister_fixup_for_uid(REALTEK_PHY_ID_8211E, REALTEK_PHY_MASK); ++} ++ ++static void higmac_verify_flow_ctrl_args(void) ++{ ++#if defined(CONFIG_TX_FLOW_CTRL_SUPPORT) ++ flow_ctrl_en |= FLOW_TX; ++#endif ++#if defined(CONFIG_RX_FLOW_CTRL_SUPPORT) ++ flow_ctrl_en |= FLOW_RX; ++#endif ++ if (tx_flow_ctrl_active_threshold < FC_ACTIVE_MIN || ++ tx_flow_ctrl_active_threshold > FC_ACTIVE_MAX) ++ tx_flow_ctrl_active_threshold = FC_ACTIVE_DEFAULT; ++ ++ if (tx_flow_ctrl_deactive_threshold < FC_DEACTIVE_MIN || ++ tx_flow_ctrl_deactive_threshold > FC_DEACTIVE_MAX) ++ tx_flow_ctrl_deactive_threshold = FC_DEACTIVE_DEFAULT; ++ ++ if (tx_flow_ctrl_active_threshold >= tx_flow_ctrl_deactive_threshold) { ++ tx_flow_ctrl_active_threshold = FC_ACTIVE_DEFAULT; ++ tx_flow_ctrl_deactive_threshold = FC_DEACTIVE_DEFAULT; ++ } ++ ++ if (tx_flow_ctrl_pause_time < 0 || ++ tx_flow_ctrl_pause_time > FC_PAUSE_TIME_MAX) ++ tx_flow_ctrl_pause_time = FC_PAUSE_TIME_DEFAULT; ++ ++ if (tx_flow_ctrl_pause_interval < 0 || ++ tx_flow_ctrl_pause_interval > FC_PAUSE_TIME_MAX) ++ tx_flow_ctrl_pause_interval = FC_PAUSE_INTERVAL_DEFAULT; ++ ++ /* pause interval should not bigger than pause time, ++ * but should not too smaller to avoid sending too many pause frame. ++ */ ++ if ((tx_flow_ctrl_pause_interval > tx_flow_ctrl_pause_time) || ++ (tx_flow_ctrl_pause_interval < (tx_flow_ctrl_pause_time >> 1))) ++ tx_flow_ctrl_pause_interval = tx_flow_ctrl_pause_time; ++} ++ ++static void higmac_destroy_hw_desc_queue(struct higmac_netdev_local *priv) ++{ ++ int i; ++ ++ for (i = 0; i < QUEUE_NUMS + RSS_NUM_RXQS - 1; i++) { ++ if (priv->pool[i].desc) { ++ if (HAS_CAP_CCI(priv->hw_cap)) ++ kfree(priv->pool[i].desc); ++ else ++ dma_free_coherent(priv->dev, priv->pool[i].size, ++ priv->pool[i].desc, ++ priv->pool[i].phys_addr); ++ priv->pool[i].desc = NULL; ++ } ++ } ++ ++ kfree(priv->rx_fq.skb); ++ kfree(priv->tx_bq.skb); ++ priv->rx_fq.skb = NULL; ++ priv->tx_bq.skb = NULL; ++ ++ if (priv->tso_supported) { ++ kfree(priv->tx_bq.sg_desc_offset); ++ priv->tx_bq.sg_desc_offset = NULL; ++ } ++ ++ kfree(priv->tx_skb); ++ priv->tx_skb = NULL; ++ ++ kfree(priv->rx_skb); ++ priv->rx_skb = NULL; ++} ++ ++static int higmac_init_hw_desc_queue(struct higmac_netdev_local *priv) ++{ ++ struct device *dev = priv->dev; ++ struct higmac_desc *virt_addr; ++ dma_addr_t phys_addr = 0; ++ int size, i; ++ ++ priv->rx_fq.count = RX_DESC_NUM; ++ priv->rx_bq.count = RX_DESC_NUM; ++ priv->tx_bq.count = TX_DESC_NUM; ++ priv->tx_rq.count = TX_DESC_NUM; ++ ++ for (i = 1; i < RSS_NUM_RXQS; i++) ++ priv->pool[3 + i].count = RX_DESC_NUM; ++ ++ for (i = 0; i < (QUEUE_NUMS + RSS_NUM_RXQS - 1); i++) { ++ size = priv->pool[i].count * sizeof(struct higmac_desc); ++ if (HAS_CAP_CCI(priv->hw_cap)) { ++ virt_addr = kmalloc(size, GFP_KERNEL); ++ if (virt_addr) ++ phys_addr = virt_to_phys(virt_addr); ++ } else { ++ virt_addr = dma_alloc_coherent(dev, size, &phys_addr, ++ GFP_KERNEL); ++ } ++ if (!virt_addr) ++ goto error_free_pool; ++ ++ memset(virt_addr, 0, size); ++ priv->pool[i].size = size; ++ priv->pool[i].desc = virt_addr; ++ priv->pool[i].phys_addr = phys_addr; ++ } ++ priv->rx_fq.skb = kzalloc(priv->rx_fq.count ++ * sizeof(struct sk_buff *), GFP_KERNEL); ++ if (!priv->rx_fq.skb) ++ goto error_free_pool; ++ ++ priv->rx_skb = kzalloc(priv->rx_fq.count ++ * sizeof(struct sk_buff *), GFP_KERNEL); ++ if (!priv->rx_skb) ++ goto error_free_pool; ++ ++ priv->tx_bq.skb = kzalloc(priv->tx_bq.count ++ * sizeof(struct sk_buff *), GFP_KERNEL); ++ if (!priv->tx_bq.skb) ++ goto error_free_pool; ++ ++ priv->tx_skb = kzalloc(priv->tx_bq.count ++ * sizeof(struct sk_buff *), GFP_KERNEL); ++ if (!priv->tx_skb) ++ goto error_free_pool; ++ ++ if (priv->tso_supported) { ++ priv->tx_bq.sg_desc_offset = kzalloc(priv->tx_bq.count ++ * sizeof(int), GFP_KERNEL); ++ if (!priv->tx_bq.sg_desc_offset) ++ goto error_free_pool; ++ } ++ ++ higmac_hw_set_desc_addr(priv); ++ if (HAS_CAP_CCI(priv->hw_cap)) ++ pr_info("higmac: ETH MAC supporte CCI.\n"); ++ ++ return 0; ++ ++error_free_pool: ++ higmac_destroy_hw_desc_queue(priv); ++ ++ return -ENOMEM; ++} ++ ++void higmac_init_napi(struct higmac_netdev_local *priv) ++{ ++ struct higmac_napi *q_napi; ++ int i; ++ ++ for (i = 0; i < priv->num_rxqs; i++) { ++ q_napi = &priv->q_napi[i]; ++ q_napi->rxq_id = i; ++ q_napi->ndev_priv = priv; ++ netif_napi_add(priv->netdev, &q_napi->napi, higmac_poll, ++ NAPI_POLL_WEIGHT); ++ } ++} ++ ++void higmac_destroy_napi(struct higmac_netdev_local *priv) ++{ ++ struct higmac_napi *q_napi; ++ int i; ++ ++ for (i = 0; i < priv->num_rxqs; i++) { ++ q_napi = &priv->q_napi[i]; ++ netif_napi_del(&q_napi->napi); ++ } ++} ++ ++int higmac_request_irqs(struct platform_device *pdev, ++ struct higmac_netdev_local *priv) ++{ ++ struct device *dev = priv->dev; ++ int ret; ++ int i; ++ ++ for (i = 0; i < priv->num_rxqs; i++) { ++ ret = platform_get_irq(pdev, i); ++ if (ret < 0) { ++ dev_err(dev, "No irq[%d] resource, ret=%d\n", i, ret); ++ return ret; ++ } ++ priv->irq[i] = ret; ++ ++ ret = devm_request_irq(dev, priv->irq[i], higmac_interrupt, ++ IRQF_SHARED, pdev->name, ++ &priv->q_napi[i]); ++ if (ret) { ++ dev_err(dev, "devm_request_irq failed, ret=%d\n", ret); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static int higmac_dev_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *node = dev->of_node; ++ struct net_device *ndev; ++ struct higmac_netdev_local *priv; ++ struct resource *res; ++ const char *mac_addr; ++ unsigned int hw_cap; ++ int ret; ++ int num_rxqs; ++ ++ higmac_verify_flow_ctrl_args(); ++ ++ if (of_device_is_compatible(node, "hisilicon,higmac-v5")) ++ num_rxqs = RSS_NUM_RXQS; ++ else ++ num_rxqs = 1; ++ ++ ndev = alloc_etherdev_mqs(sizeof(struct higmac_netdev_local), 1, ++ num_rxqs); ++ if (!ndev) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, ndev); ++ SET_NETDEV_DEV(ndev, dev); ++ ++ priv = netdev_priv(ndev); ++ priv->dev = dev; ++ priv->netdev = ndev; ++ priv->num_rxqs = num_rxqs; ++ ++ if (of_device_is_compatible(node, "hisilicon,higmac-v3")) ++ priv->hw_cap |= HW_CAP_CCI; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, MEM_GMAC_IOBASE); ++ priv->gmac_iobase = devm_ioremap_resource(dev, res); ++ if (IS_ERR(priv->gmac_iobase)) { ++ ret = PTR_ERR(priv->gmac_iobase); ++ goto out_free_netdev; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, ++ MEM_MACIF_IOBASE); ++ priv->macif_base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(priv->macif_base)) { ++ ret = PTR_ERR(priv->macif_base); ++ goto out_free_netdev; ++ } ++ ++ /* only for some chip to fix AXI bus burst and outstanding config */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, ++ MEM_AXI_BUS_CFG_IOBASE); ++ priv->axi_bus_cfg_base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(priv->axi_bus_cfg_base)) ++ priv->axi_bus_cfg_base = NULL; ++ ++ priv->port_rst = devm_reset_control_get(dev, HIGMAC_PORT_RST_NAME); ++ if (IS_ERR(priv->port_rst)) { ++ ret = PTR_ERR(priv->port_rst); ++ goto out_free_netdev; ++ } ++ ++ priv->macif_rst = devm_reset_control_get(dev, HIGMAC_MACIF_RST_NAME); ++ if (IS_ERR(priv->macif_rst)) { ++ ret = PTR_ERR(priv->macif_rst); ++ goto out_free_netdev; ++ } ++ ++ priv->phy_rst = devm_reset_control_get(dev, HIGMAC_PHY_RST_NAME); ++ if (IS_ERR(priv->phy_rst)) ++ priv->phy_rst = NULL; ++ ++ priv->clk = devm_clk_get(&pdev->dev, HIGMAC_MAC_CLK_NAME); ++ if (IS_ERR(priv->clk)) { ++ netdev_err(ndev, "failed to get clk\n"); ++ ret = -ENODEV; ++ goto out_free_netdev; ++ } ++ ++ ret = clk_prepare_enable(priv->clk); ++ if (ret < 0) { ++ netdev_err(ndev, "failed to enable clk %d\n", ret); ++ goto out_free_netdev; ++ } ++ ++ priv->macif_clk = devm_clk_get(&pdev->dev, HIGMAC_MACIF_CLK_NAME); ++ if (IS_ERR(priv->macif_clk)) ++ priv->macif_clk = NULL; ++ ++ if (priv->macif_clk) { ++ ret = clk_prepare_enable(priv->macif_clk); ++ if (ret < 0) { ++ netdev_err(ndev, "failed enable macif_clk %d\n", ret); ++ goto out_clk_disable; ++ } ++ } ++ ++ higmac_mac_core_reset(priv); ++ ++ /* phy reset, should be early than "of_mdiobus_register". ++ * becausue "of_mdiobus_register" will read PHY register by MDIO. ++ */ ++ higmac_hw_phy_reset(priv); ++ ++ higmac_of_get_param(priv, node); ++ ++ ret = of_get_phy_mode(node); ++ if (ret < 0) { ++ netdev_err(ndev, "not find phy-mode\n"); ++ goto out_macif_clk_disable; ++ } ++ priv->phy_mode = ret; ++ ++ priv->phy_node = of_parse_phandle(node, "phy-handle", 0); ++ if (!priv->phy_node) { ++ netdev_err(ndev, "not find phy-handle\n"); ++ ret = -EINVAL; ++ goto out_macif_clk_disable; ++ } ++ ++ mac_addr = of_get_mac_address(node); ++ if (mac_addr) ++ ether_addr_copy(ndev->dev_addr, mac_addr); ++ if (!is_valid_ether_addr(ndev->dev_addr)) { ++ eth_hw_addr_random(ndev); ++ netdev_warn(ndev, "using random MAC address %pM\n", ++ ndev->dev_addr); ++ } ++ ++ higmac_hw_set_mac_addr(ndev); ++ ++ hw_cap = readl(priv->gmac_iobase + CRF_MIN_PACKET); ++ priv->tso_supported = HAS_TSO_CAP(hw_cap); ++ priv->has_rxhash_cap = HAS_RXHASH_CAP(hw_cap); ++ priv->has_rss_cap = HAS_RSS_CAP(hw_cap); ++ ++ higmac_set_rss_cap(priv); ++ higmac_get_rss_key(priv); ++ if (priv->has_rss_cap) { ++ priv->rss_info.ind_tbl_size = RSS_INDIRECTION_TABLE_SIZE; ++ higmac_get_rss(priv); ++ } ++ ++ if (priv->has_rxhash_cap) { ++ priv->rss_info.hash_cfg = DEF_HASH_CFG; ++ higmac_config_hash_policy(priv); ++ } ++ ++ /* init hw controller */ ++ higmac_hw_init(priv); ++ ++ /* TODO: phy fix here?? other way ??? */ ++ phy_register_fixups(); ++ ++ priv->phy = of_phy_connect(ndev, priv->phy_node, ++ &higmac_adjust_link, 0, priv->phy_mode); ++ if (!priv->phy) { ++ ret = -ENODEV; ++ goto out_phy_node; ++ } ++ ++ /* If the phy_id is mostly Fs, there is no device there */ ++ if ((priv->phy->phy_id & 0x1fffffff) == 0x1fffffff || ++ priv->phy->phy_id == 0) { ++ pr_info("phy %d not found\n", priv->phy->mdio.addr); ++ ret = -ENODEV; ++ goto out_phy_disconnect; ++ } ++ ++ pr_info("attached PHY %d to driver %s, PHY_ID=0x%x\n", ++ priv->phy->mdio.addr, priv->phy->drv->name, priv->phy->phy_id); ++ ++ /* Stop Advertising 1000BASE Capability if interface is not RGMII */ ++ if ((priv->phy_mode == PHY_INTERFACE_MODE_MII) || ++ (priv->phy_mode == PHY_INTERFACE_MODE_RMII)) { ++ priv->phy->advertising &= ~(SUPPORTED_1000baseT_Half | ++ SUPPORTED_1000baseT_Full); ++ ++ /* Internal FE phy's reg BMSR bit8 is wrong, make the kernel ++ * believe it has the 1000base Capability, so fix it here ++ */ ++ if (priv->phy->phy_id == HISILICON_PHY_ID_FESTAV200) ++ priv->phy->supported &= ~(ADVERTISED_1000baseT_Full | ++ ADVERTISED_1000baseT_Half); ++ } ++ ++ higmac_set_flow_ctrl_args(priv); ++ higmac_set_flow_ctrl_params(priv); ++ priv->phy->supported |= SUPPORTED_Pause; ++ if (priv->flow_ctrl) ++ priv->phy->advertising |= SUPPORTED_Pause; ++ ++ if (priv->autoeee) ++ init_autoeee(priv); ++ ++ ret = higmac_request_irqs(pdev, priv); ++ if (ret) ++ goto out_phy_disconnect; ++ ++ higmac_init_napi(priv); ++ spin_lock_init(&priv->rxlock); ++ spin_lock_init(&priv->txlock); ++ spin_lock_init(&priv->pmtlock); ++ ++ /* init netdevice */ ++ ndev->irq = priv->irq[0]; ++ ndev->watchdog_timeo = 3 * HZ; ++ ndev->netdev_ops = &hieth_netdev_ops; ++ ndev->ethtool_ops = &hieth_ethtools_ops; ++ ++ if (priv->has_rxhash_cap) ++ ndev->hw_features |= NETIF_F_RXHASH; ++ if (priv->has_rss_cap) ++ ndev->hw_features |= NETIF_F_NTUPLE; ++ if (priv->tso_supported) { ++ ndev->hw_features |= NETIF_F_SG | ++ NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | ++ NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO; ++ } ++#if defined(CONFIG_HIGMAC_RXCSUM) ++ ndev->hw_features |= NETIF_F_RXCSUM; ++ higmac_enable_rxcsum_drop(priv, true); ++#endif ++ ++ ndev->features |= ndev->hw_features; ++ ndev->features |= NETIF_F_HIGHDMA | NETIF_F_GSO; ++ ndev->vlan_features |= ndev->features; ++ ++ init_timer(&priv->monitor); ++ priv->monitor.function = higmac_monitor_func; ++ priv->monitor.data = (unsigned long)ndev; ++ priv->monitor.expires = jiffies + HIGMAC_MONITOR_TIMER; ++ ++ device_set_wakeup_capable(priv->dev, 1); ++ /* TODO: when we can let phy powerdown? ++ * In some mode, we don't want phy powerdown, ++ * so I set wakeup enable all the time ++ */ ++ device_set_wakeup_enable(priv->dev, 1); ++ ++ priv->wol_enable = false; ++ ++ priv->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); ++ ++ /* init hw desc queue */ ++ ret = higmac_init_hw_desc_queue(priv); ++ if (ret) ++ goto _error_hw_desc_queue; ++ ++ if (priv->tso_supported) { ++ ret = higmac_init_sg_desc_queue(priv); ++ if (ret) ++ goto _error_sg_desc_queue; ++ } ++ ++ /* register netdevice */ ++ ret = register_netdev(priv->netdev); ++ if (ret) { ++ pr_err("register_ndev failed!"); ++ goto _error_sg_desc_queue; ++ } ++ ++ /* reset queue here to make BQL only reset once. ++ * if we put netdev_reset_queue() in higmac_net_open(), ++ * the BQL will be reset when ifconfig eth0 down and up, ++ * but the tx ring is not cleared before. ++ * As a result, the NAPI poll will call netdev_completed_queue() ++ * and BQL throw a bug. ++ */ ++ netdev_reset_queue(ndev); ++ ++ clk_disable_unprepare(priv->clk); ++ if (priv->macif_clk) ++ clk_disable_unprepare(priv->macif_clk); ++ ++ pr_info("ETH: %s, phy_addr=%d\n", ++ phy_modes(priv->phy_mode), priv->phy->mdio.addr); ++ ++ return ret; ++ ++_error_sg_desc_queue: ++ if (priv->tso_supported) ++ higmac_destroy_sg_desc_queue(priv); ++ ++_error_hw_desc_queue: ++ higmac_destroy_hw_desc_queue(priv); ++ higmac_destroy_napi(priv); ++out_phy_disconnect: ++ phy_disconnect(priv->phy); ++out_phy_node: ++ of_node_put(priv->phy_node); ++out_macif_clk_disable: ++ if (priv->macif_clk) ++ clk_disable_unprepare(priv->macif_clk); ++out_clk_disable: ++ clk_disable_unprepare(priv->clk); ++out_free_netdev: ++ free_netdev(ndev); ++ ++ return ret; ++} ++ ++static int higmac_dev_remove(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ ++ /* TODO: stop the gmac and free all resource */ ++ del_timer_sync(&priv->monitor); ++ higmac_destroy_napi(priv); ++ ++ unregister_netdev(ndev); ++ ++ higmac_reclaim_rx_tx_resource(priv); ++ higmac_free_rx_skb(priv); ++ higmac_free_tx_skb(priv); ++ ++ if (priv->tso_supported) ++ higmac_destroy_sg_desc_queue(priv); ++ higmac_destroy_hw_desc_queue(priv); ++ ++ phy_disconnect(priv->phy); ++ of_node_put(priv->phy_node); ++ ++ free_netdev(ndev); ++ ++ phy_unregister_fixups(); ++ ++ return 0; ++} ++ ++#include "pm.c" ++#ifdef CONFIG_PM ++ ++static void higmac_disable_irq(struct higmac_netdev_local *priv) ++{ ++ int i; ++ ++ for (i = 0; i < priv->num_rxqs; i++) ++ disable_irq(priv->irq[i]); ++} ++ ++static void higmac_enable_irq(struct higmac_netdev_local *priv) ++{ ++ int i; ++ ++ for (i = 0; i < priv->num_rxqs; i++) ++ enable_irq(priv->irq[i]); ++} ++ ++int higmac_dev_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ ++ higmac_disable_irq(priv); ++ /* If support Wake on LAN, we should not disconnect phy ++ * because it will call phy_suspend to power down phy. ++ */ ++ if (!priv->wol_enable) ++ phy_disconnect(priv->phy); ++ del_timer_sync(&priv->monitor); ++ /* If suspend when netif is not up, the napi_disable will run into ++ * dead loop and dpm_drv_timeout will give warning. ++ */ ++ if (netif_running(ndev)) ++ higmac_disable_napi(priv); ++ netif_device_detach(ndev); ++ ++ netif_carrier_off(ndev); ++ ++ /* If netdev is down, MAC clock is disabled. ++ * So if we want to reclaim MAC rx and tx resource, ++ * we must first enable MAC clock and then disable it. ++ */ ++ if (!(ndev->flags & IFF_UP)) ++ clk_prepare_enable(priv->clk); ++ ++ higmac_reclaim_rx_tx_resource(priv); ++ ++ if (!(ndev->flags & IFF_UP)) ++ clk_disable_unprepare(priv->clk); ++ ++ pmt_enter(priv); ++ ++ if (!priv->wol_enable) { /* if no WOL, then poweroff */ ++ /* pr_info("power off gmac.\n"); */ ++ /* no need to call genphy_resume() in resume, ++ * because we reset everything ++ */ ++ genphy_suspend(priv->phy); /* power down phy */ ++ msleep(20); ++ higmac_hw_all_clk_disable(priv); ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(higmac_dev_suspend); ++ ++int higmac_dev_resume(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ int ret = 0; ++ ++ /* If we support Wake on LAN, we doesn't call clk_disable. ++ * But when we resume, the uboot may off mac clock and reset phy ++ * by re-write the mac CRG register. ++ * So we first call clk_disable, and then clk_enable. ++ */ ++ if (priv->wol_enable) ++ higmac_hw_all_clk_disable(priv); ++ ++ higmac_hw_all_clk_enable(priv); ++ /* internal FE_PHY: enable clk and reset */ ++ higmac_hw_phy_reset(priv); ++ ++ /* If netdev is down, MAC clock is disabled. ++ * So if we want to restart MAC and re-initialize it, ++ * we must first enable MAC clock and then disable it. ++ */ ++ if (!(ndev->flags & IFF_UP)) ++ clk_prepare_enable(priv->clk); ++ ++ /* power on gmac */ ++ higmac_restart(priv); ++ ++ /* If support WoL, we didn't disconnect phy. ++ * But when we resume, we reset PHY, so we want to ++ * call phy_connect to make phy_fixup excuted. ++ * This is important for internal PHY fix. ++ */ ++ if (priv->wol_enable) ++ phy_disconnect(priv->phy); ++ ++ ret = phy_connect_direct(ndev, priv->phy, higmac_adjust_link, ++ priv->phy_mode); ++ if (ret) ++ return ret; ++ ++ /* If we suspend and resume when net device is down, ++ * some operations are unnecessary. ++ */ ++ if (ndev->flags & IFF_UP) { ++ priv->monitor.expires = jiffies + HIGMAC_MONITOR_TIMER; ++ mod_timer(&priv->monitor, priv->monitor.expires); ++ priv->old_link = 0; ++ priv->old_speed = SPEED_UNKNOWN; ++ priv->old_duplex = DUPLEX_UNKNOWN; ++ } ++ if (netif_running(ndev)) ++ higmac_enable_napi(priv); ++ netif_device_attach(ndev); ++ if (ndev->flags & IFF_UP) ++ phy_start(priv->phy); ++ higmac_enable_irq(priv); ++ ++ pmt_exit(priv); ++ ++ if (!(ndev->flags & IFF_UP)) ++ clk_disable_unprepare(priv->clk); ++ ++ return 0; ++} ++EXPORT_SYMBOL(higmac_dev_resume); ++#else ++#define higmac_dev_suspend NULL ++#define higmac_dev_resume NULL ++#endif ++ ++static const struct of_device_id higmac_of_match[] = { ++ {.compatible = "hisilicon,higmac",}, ++ {.compatible = "hisilicon,higmac-v1",}, ++ {.compatible = "hisilicon,higmac-v2",}, ++ {.compatible = "hisilicon,higmac-v3",}, ++ {.compatible = "hisilicon,higmac-v4",}, ++ {.compatible = "hisilicon,higmac-v5",}, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(of, higmac_of_match); ++ ++static struct platform_driver higmac_dev_driver = { ++ .probe = higmac_dev_probe, ++ .remove = higmac_dev_remove, ++ .suspend = higmac_dev_suspend, ++ .resume = higmac_dev_resume, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = HIGMAC_DRIVER_NAME, ++ .of_match_table = higmac_of_match, ++ }, ++}; ++ ++#include "proc-dev.c" ++ ++static int __init higmac_init(void) ++{ ++ int ret = 0; ++ ++ ret = platform_driver_register(&higmac_dev_driver); ++ if (ret) ++ return ret; ++ ++ higmac_proc_create(); ++ ++ return ret; ++} ++ ++static void __exit higmac_exit(void) ++{ ++ platform_driver_unregister(&higmac_dev_driver); ++ ++ higmac_proc_destroy(); ++} ++ ++module_init(higmac_init); ++module_exit(higmac_exit); ++ ++MODULE_AUTHOR("ZMJUN"); ++MODULE_DESCRIPTION("Hisilicon double GMAC driver, base on driver higmacv200 by CHH"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/net/ethernet/hisilicon/higmac/higmac.h b/drivers/net/ethernet/hisilicon/higmac/higmac.h +new file mode 100644 +index 0000000..a616ebf +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/higmac.h +@@ -0,0 +1,615 @@ ++#ifndef __HIGMAC_H__ ++#define __HIGMAC_H__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define STATION_ADDR_LOW 0x0000 ++#define STATION_ADDR_HIGH 0x0004 ++#define MAC_DUPLEX_HALF_CTRL 0x0008 ++ ++#define PORT_MODE 0x0040 ++ ++#define PORT_EN 0x0044 ++#define BITS_TX_EN BIT(2) ++#define BITS_RX_EN BIT(1) ++ ++#define FC_TX_TIMER 0x001C ++ ++#define PAUSE_THR 0x0038 ++ ++#define PAUSE_EN 0x0048 ++#define BIT_RX_FDFC BIT(0) ++#define BIT_TX_FDFC BIT(1) ++ ++#define RX_PAUSE_EN 0x02A4 ++#define BIT_RX_FQ_PAUSE_EN BIT(0) ++#define BIT_RX_BQ_PAUSE_EN BIT(1) ++ ++#define CRF_TX_PAUSE 0x0340 ++ ++#define BITS_Q_PAUSE_TH_OFFSET 16 ++#define BITS_Q_PAUSE_TH_MASK 0xFFFF ++ ++#define REC_FILT_CONTROL 0x0064 ++#define BIT_CRC_ERR_PASS BIT(5) ++#define BIT_PAUSE_FRM_PASS BIT(4) ++#define BIT_VLAN_DROP_EN BIT(3) ++#define BIT_BC_DROP_EN BIT(2) ++#define BIT_MC_MATCH_EN BIT(1) ++#define BIT_UC_MATCH_EN BIT(0) ++ ++#define PORT_MC_ADDR_LOW 0x0068 ++#define PORT_MC_ADDR_HIGH 0x006C ++ ++#define MODE_CHANGE_EN 0x01b4 ++#define BIT_MODE_CHANGE_EN BIT(0) ++ ++#define COL_SLOT_TIME 0x01c0 ++ ++#define CRF_MIN_PACKET 0x0210 ++#define BIT_OFFSET_TX_MIN_LEN 8 ++#define BIT_MASK_TX_MIN_LEN GENMASK(13, 8) ++ ++#define CONTROL_WORD 0x0214 ++#define CONTROL_WORD_CONFIG 0x640 ++ ++#define TSO_COE_CTRL 0x02e8 ++#define BIT_COE_IPHDR_DROP BIT(4) ++#define BIT_COE_PAYLOAD_DROP BIT(5) ++#define BIT_COE_IPV6_UDP_ZERO_DROP BIT(6) ++#define COE_ERR_DROP (BIT_COE_IPHDR_DROP | \ ++ BIT_COE_PAYLOAD_DROP | \ ++ BIT_COE_IPV6_UDP_ZERO_DROP) ++ ++#define RX_FQ_START_ADDR 0x0500 ++#define RX_FQ_DEPTH 0x0504 ++#define RX_FQ_WR_ADDR 0x0508 ++#define BITS_RX_FQ_WR_ADDR MK_BITS(0, 21) ++#define RX_FQ_RD_ADDR 0x050c ++#define BITS_RX_FQ_RD_ADDR MK_BITS(0, 21) ++#define RX_FQ_VLDDESC_CNT 0x0510 ++#define BITS_RX_FQ_VLDDESC_CNT MK_BITS(0, 16) ++#define RX_FQ_ALEMPTY_TH 0x0514 ++#define BITS_RX_FQ_ALEMPTY_TH MK_BITS(0, 16) ++#define RX_FQ_REG_EN 0x0518 ++#define BITS_RX_FQ_START_ADDR_EN BIT(2) ++#define BITS_RX_FQ_DEPTH_EN BIT(1) ++#define BITS_RX_FQ_RD_ADDR_EN MK_BITS(0, 1) ++#define RX_FQ_ALFULL_TH 0x051c ++#define BITS_RX_FQ_ALFULL_TH MK_BITS(0, 16) ++ ++#define RX_BQ_START_ADDR 0x0520 ++#define RX_BQ_DEPTH 0x0524 ++#define RX_BQ_WR_ADDR 0x0528 ++#define RX_BQ_RD_ADDR 0x052c ++#define RX_BQ_FREE_DESC_CNT 0x0530 ++#define BITS_RX_BQ_FREE_DESC_CNT MK_BITS(0, 16) ++#define RX_BQ_ALEMPTY_TH 0x0534 ++#define BITS_RX_BQ_ALEMPTY_TH MK_BITS(0, 16) ++#define RX_BQ_REG_EN 0x0538 ++#define BITS_RX_BQ_START_ADDR_EN BIT(2) ++#define BITS_RX_BQ_DEPTH_EN BIT(1) ++#define BITS_RX_BQ_WR_ADDR_EN MK_BITS(0, 1) ++#define RX_BQ_ALFULL_TH 0x053c ++#define BITS_RX_BQ_ALFULL_TH MK_BITS(0, 16) ++ ++#define TX_BQ_START_ADDR 0x0580 ++#define TX_BQ_DEPTH 0x0584 ++#define TX_BQ_WR_ADDR 0x0588 ++#define BITS_TX_BQ_WR_ADDR MK_BITS(0, 21) ++#define TX_BQ_RD_ADDR 0x058c ++#define BITS_TX_BQ_RD_ADDR MK_BITS(0, 21) ++#define TX_BQ_VLDDESC_CNT 0x0590 ++#define BITS_TX_BQ_VLDDESC_CNT MK_BITS(0, 16) ++#define TX_BQ_ALEMPTY_TH 0x0594 ++#define BITS_TX_BQ_ALEMPTY_TH MK_BITS(0, 16) ++#define TX_BQ_REG_EN 0x0598 ++#define BITS_TX_BQ_START_ADDR_EN BIT(2) ++#define BITS_TX_BQ_DEPTH_EN BIT(1) ++#define BITS_TX_BQ_RD_ADDR_EN MK_BITS(0, 1) ++#define TX_BQ_ALFULL_TH 0x059c ++#define BITS_TX_BQ_ALFULL_TH MK_BITS(0, 16) ++ ++#define TX_RQ_START_ADDR 0x05a0 ++#define TX_RQ_DEPTH 0x05a4 ++#define TX_RQ_WR_ADDR 0x05a8 ++#define BITS_TX_RQ_WR_ADDR MK_BITS(0, 21) ++#define TX_RQ_RD_ADDR 0x05ac ++#define BITS_TX_RQ_RD_ADDR MK_BITS(0, 21) ++#define TX_RQ_FREE_DESC_CNT 0x05b0 ++#define BITS_TX_RQ_FREE_DESC_CNT MK_BITS(0, 16) ++#define TX_RQ_ALEMPTY_TH 0x05b4 ++#define BITS_TX_RQ_ALEMPTY_TH MK_BITS(0, 16) ++#define TX_RQ_REG_EN 0x05b8 ++#define BITS_TX_RQ_START_ADDR_EN BIT(2) ++#define BITS_TX_RQ_DEPTH_EN BIT(1) ++#define BITS_TX_RQ_WR_ADDR_EN MK_BITS(0, 1) ++#define TX_RQ_ALFULL_TH 0x05bc ++#define BITS_TX_RQ_ALFULL_TH MK_BITS(0, 16) ++ ++#define RAW_PMU_INT 0x05c0 ++#define ENA_PMU_INT 0x05c4 ++ ++#define DESC_WR_RD_ENA 0x05CC ++ ++#define IN_QUEUE_TH 0x05d8 ++#define BITS_OFFSET_TX_RQ_IN_TH 16 ++ ++#define RX_BQ_IN_TIMEOUT_TH 0x05E0 ++ ++#define TX_RQ_IN_TIMEOUT_TH 0x05e4 ++ ++#define STOP_CMD 0x05e8 ++#define BITS_TX_STOP_EN BIT(1) ++#define BITS_RX_STOP_EN BIT(0) ++#define STOP_RX_TX (BITS_TX_STOP_EN | BITS_RX_STOP_EN) ++ ++#define HW_CAP_EN 0x0c00 ++#define BIT_RSS_CAP BIT(0) ++#define BIT_RXHASH_CAP BIT(1) ++#define RSS_HASH_KEY 0x0c04 ++#define RSS_HASH_CONFIG 0x0c08 ++#define TCPV4_L3_HASH_EN BIT(0) ++#define TCPV4_L4_HASH_EN BIT(1) ++#define TCPV4_VLAN_HASH_EN BIT(2) ++#define UDPV4_L3_HASH_EN BIT(4) ++#define UDPV4_L4_HASH_EN BIT(5) ++#define UDPV4_VLAN_HASH_EN BIT(6) ++#define IPV4_L3_HASH_EN BIT(8) ++#define IPV4_VLAN_HASH_EN BIT(9) ++#define TCPV6_L3_HASH_EN BIT(12) ++#define TCPV6_L4_HASH_EN BIT(13) ++#define TCPV6_VLAN_HASH_EN BIT(14) ++#define UDPV6_L3_HASH_EN BIT(16) ++#define UDPV6_L4_HASH_EN BIT(17) ++#define UDPV6_VLAN_HASH_EN BIT(18) ++#define IPV6_L3_HASH_EN BIT(20) ++#define IPV6_VLAN_HASH_EN BIT(21) ++#define DEF_HASH_CFG 0x377377 ++ ++#define RSS_IND_TBL 0x0c0c ++#define BIT_IND_TBL_READY BIT(13) ++#define BIT_IND_TLB_WR BIT(12) ++#define RSS_RAW_PMU_INT 0x0c10 ++#define RSS_QUEUE1_START_ADDR 0x0c20 ++#define RX_BQ_START_ADDR_QUEUE(i) (RSS_QUEUE1_START_ADDR + \ ++ ((i) - 1) * 0x10) ++#define RSS_QUEUE1_DEPTH 0x0c24 ++#define RX_BQ_WR_ADDR_QUEUE1 0x0c28 ++#define RX_BQ_RD_ADDR_QUEUE1 0x0c2c ++#define RSS_QUEUE1_ENA_INT 0x0c90 ++#define RSS_ENA_INT_QUEUE(i) (RSS_QUEUE1_ENA_INT + ((i) - 1) * 0x4) ++#define RX_BQ_DEPTH_QUEUE(i) (RSS_QUEUE1_DEPTH + ((i) - 1) * 0x10) ++#define RX_BQ_WR_ADDR_QUEUE(i) ((i) ? (RX_BQ_WR_ADDR_QUEUE1 + \ ++ ((i) - 1) * 0x10) : RX_BQ_WR_ADDR) ++#define RX_BQ_RD_ADDR_QUEUE(i) ((i) ? (RX_BQ_RD_ADDR_QUEUE1 + \ ++ ((i) - 1) * 0x10) : RX_BQ_RD_ADDR) ++ ++#define DEF_INT_MASK_QUEUE(i) (0x3 << (2 * ((i) - 1))) ++ ++/* AXI burst and outstanding config */ ++#define BURST_OUTSTANDING_REG 0x3014 ++#define BURST4_OUTSTANDING1 0x81ff ++#define BURST_OUTSTANDING_OFFSET 16 ++ ++#define GMAC_SPEED_1000 0x05 ++#define GMAC_SPEED_100 0x01 ++#define GMAC_SPEED_10 0x00 ++ ++enum higmac_tx_err { ++ ERR_NONE = 0, ++ ERR_DESC_CFG = (1 << 0), ++ ERR_DATA_LEN = (1 << 1), ++ ERR_DESC_NFRAG_NUM = (1 << 2), ++ ERR_DESC_IP_HDR_LEN = (1 << 3), ++ ERR_DESC_PROT_HDR_LEN = (1 << 4), ++ ERR_DESC_MTU = (1 << 5), ++ ERR_LINK_SGPKT_LEN = (1 << 8), ++ ERR_LINK_TSOPKT_LINEAR = (1 << 9), ++ ERR_LINK_NFRAG_LEN = (1 << 10), ++ ERR_LINK_TOTAL_LEN = (1 << 11), ++ ERR_HDR_TCP_BCMC = (1 << 12), ++ ERR_HDR_UDP_BC = (1 << 13), ++ ERR_HDR_VLAN_IP_TYPE = (1 << 14), ++ ERR_HDR_IP_TYPE = (1 << 15), ++ ERR_HDR_IP_VERSION = (1 << 16), ++ ERR_HDR_IP_HDR_LEN = (1 << 17), ++ ERR_HDR_IP_TOTAL_LEN = (1 << 18), ++ ERR_HDR_IPV6_TTL_PROT = (1 << 19), ++ ERR_HDR_IPV4_OFFSET = (1 << 20), ++ ERR_HDR_IPV4_TTL_PROT = (1 << 21), ++ ERR_HDR_UDP_LEN = (1 << 22), ++ ERR_HDR_TCP_LEN = (1 << 23), ++ ERR_DESC = (ERR_DESC_CFG | ERR_DATA_LEN | ++ ERR_DESC_NFRAG_NUM | ERR_DESC_IP_HDR_LEN | ++ ERR_DESC_PROT_HDR_LEN | ERR_DESC_MTU), ++ ERR_LINK = (ERR_LINK_SGPKT_LEN | ERR_LINK_TSOPKT_LINEAR | ++ ERR_LINK_NFRAG_LEN | ERR_LINK_TOTAL_LEN), ++ ERR_HDR = (ERR_HDR_TCP_BCMC | ERR_HDR_UDP_BC | ++ ERR_HDR_VLAN_IP_TYPE | ERR_HDR_IP_TYPE | ++ ERR_HDR_IP_VERSION | ERR_HDR_IP_HDR_LEN | ++ ERR_HDR_IP_TOTAL_LEN | ERR_HDR_IPV6_TTL_PROT | ++ ERR_HDR_IPV4_OFFSET | ERR_HDR_IPV4_TTL_PROT | ++ ERR_HDR_UDP_LEN | ERR_HDR_TCP_LEN), ++ ERR_ALL = (ERR_DESC | ERR_LINK | ERR_HDR), ++}; ++ ++#define HIGMAC_DRIVER_NAME "hi_gmac_v200" ++ ++#define HIGMAC_MAC_CLK_NAME "higmac_clk" ++#define HIGMAC_MACIF_CLK_NAME "macif_clk" ++ ++#define HIGMAC_PORT_RST_NAME "port_reset" ++#define HIGMAC_MACIF_RST_NAME "macif_reset" ++#define HIGMAC_PHY_RST_NAME "phy_reset" ++ ++#define HIGMAC_TSO_DEBUG ++ ++#include "tso.h" ++ ++#if defined(CONFIG_ARCH_HI3519) || defined(CONFIG_ARCH_HI3519V101) || \ ++ defined(CONFIG_ARCH_HI3516AV200) ++#ifdef readl ++#undef readl ++#undef readl_relaxed ++#undef writel ++#undef writel_relaxed ++#define readl hi_readl ++#define readl_relaxed hi_readl_relaxed ++#define writel hi_writel ++#define writel_relaxed hi_writel_relaxed ++#endif /* readl */ ++#endif /* defined(CONFIG_ARCH_HI3519) || defined(CONFIG_HI3519V101) */ ++ ++#define HIGMAC_IOSIZE (0x1000) ++#define HIGMAC_OFFSET (HIGMAC_IOSIZE) ++ ++#define RX_BQ_IN_INT BIT(17) ++#define TX_RQ_IN_INT BIT(19) ++#define RX_BQ_IN_TIMEOUT_INT BIT(28) ++#define TX_RQ_IN_TIMEOUT_INT BIT(29) ++ ++#define DEF_INT_MASK (RX_BQ_IN_INT | RX_BQ_IN_TIMEOUT_INT | \ ++ TX_RQ_IN_INT | TX_RQ_IN_TIMEOUT_INT) ++ ++/* write or read descriptor need memory barrier */ ++#define HIGMAC_SYNC_BARRIER() do { isb(); smp_mb(); } while (0) ++ ++#define HISILICON_PHY_ID_FESTAV200 (0x20669823) ++#define PHY_ID_KSZ8051MNL (0x00221550) ++#define PHY_ID_KSZ8081RNB (0x00221560) ++#define DEFAULT_PHY_MASK (0xfffffff0) ++#define REALTEK_PHY_ID_8211E (0x001cc915) ++#define REALTEK_PHY_MASK (0x001fffff) ++ ++enum { ++ GMAC_PORT0, ++ GMAC_PORT1, ++ GMAC_MAX_PORT, ++}; ++ ++enum { ++ MEM_GMAC_IOBASE, ++ MEM_MACIF_IOBASE, ++ MEM_AXI_BUS_CFG_IOBASE, ++ MEM_FWD_IOBASE, ++ MEM_CTRL_IOBASE, ++}; ++ ++#define HIGMAC_LINKED BIT(0) ++#define HIGMAC_DUP_FULL BIT(1) ++#define HIGMAC_SPD_10M BIT(2) ++#define HIGMAC_SPD_100M BIT(3) ++#define HIGMAC_SPD_1000M BIT(4) ++/* Flow Control defines */ ++#define FLOW_OFF 0 ++#define FLOW_RX 1 ++#define FLOW_TX 2 ++#define FLOW_AUTO (FLOW_TX | FLOW_RX) ++ ++#define FC_ACTIVE_MIN 1 ++#define FC_ACTIVE_DEFAULT 16 ++#define FC_ACTIVE_MAX 127 ++#define FC_DEACTIVE_MIN 1 ++#define FC_DEACTIVE_DEFAULT 32 ++#define FC_DEACTIVE_MAX 127 ++ ++#define FC_PAUSE_TIME_DEFAULT 0xFFFF ++#define FC_PAUSE_INTERVAL_DEFAULT 0xFFFF ++#define FC_PAUSE_TIME_MAX 0xFFFF ++ ++#define RX_BQ_INT_THRESHOLD 0x40 /* TODO: */ ++#define TX_RQ_INT_THRESHOLD 0x20 /* TODO: */ ++ ++#define HIGMAC_MONITOR_TIMER (msecs_to_jiffies(200)) ++ ++#define HIETH_MAX_FRAME_SIZE (1600 + 128) ++#define SKB_SIZE (HIETH_MAX_FRAME_SIZE) ++ ++#define DESC_VLD_FREE 0 ++#define DESC_VLD_BUSY 1 ++ ++#define DESC_FL_FIRST 2 ++#define DESC_FL_MID 0 ++#define DESC_FL_LAST 1 ++#define DESC_FL_FULL 3 ++ ++#if defined(CONFIG_HIGMAC_DESC_4WORD) ++#define DESC_WORD_SHIFT 2 ++#else ++#define DESC_WORD_SHIFT 3 ++#endif ++#define DESC_BYTE_SHIFT (DESC_WORD_SHIFT + 2) ++#define DESC_WORD_CNT (1 << DESC_WORD_SHIFT) ++#define DESC_SIZE (1 << DESC_BYTE_SHIFT) ++ ++#define RX_DESC_NUM 1024 ++#define TX_DESC_NUM 1024 ++ ++/* DMA descriptor ring helpers */ ++#define dma_ring_incr(n, s) (((n) + 1) & ((s) - 1)) ++#define dma_cnt(n) ((n) >> DESC_BYTE_SHIFT) ++#define dma_byte(n) ((n) << DESC_BYTE_SHIFT) ++ ++#define RSS_HASH_KEY_SIZE 4 ++#define RSS_INDIRECTION_TABLE_SIZE 128 ++#define RSS_NUM_RXQS 4 ++ ++#define HW_CAP_TSO BIT(0) ++#define HW_CAP_RXCSUM BIT(1) ++#define HW_CAP_CCI BIT(2) ++#define HAS_CAP_TSO(hw_cap) ((hw_cap) & HW_CAP_TSO) ++#define HAS_CAP_RXCSUM(hw_cap) ((hw_cap) & HW_CAP_RXCSUM) ++#define HAS_CAP_CCI(hw_cap) ((hw_cap) & HW_CAP_CCI) ++ ++#if defined(CONFIG_HIGMAC_DESC_4WORD) ++struct higmac_desc { ++ unsigned int data_buff_addr; ++ ++ unsigned int buffer_len:11; ++#if defined(CONFIG_HIGMAC_RXCSUM) ++ unsigned int reserve2:1; ++ unsigned int payload_csum_err:1; ++ unsigned int header_csum_err:1; ++ unsigned int payload_csum_done:1; ++ unsigned int header_csum_done:1; ++#else ++ unsigned int reserve2:5; ++#endif ++ unsigned int data_len:11; ++ unsigned int reserve1:2; ++ unsigned int fl:2; ++ unsigned int descvid:1; ++ ++ unsigned int rxhash; ++ unsigned int reserve3:8; ++ unsigned int l3_hash:1; ++ unsigned int has_hash:1; ++ unsigned int skb_id:14; ++ unsigned int reserve31:8; ++}; ++ ++struct higmac_tso_desc { ++ unsigned int data_buff_addr; ++ union { ++ struct { ++ unsigned int prot_hdr_len:4; ++ unsigned int ip_hdr_len:4; ++ unsigned int prot_type:1; ++ unsigned int ip_ver:1; ++ unsigned int vlan_flag:1; ++ unsigned int nfrags_num:5; ++ unsigned int data_len:11; ++ unsigned int reservel:1; ++ unsigned int tso_flag:1; ++ unsigned int coe_flag:1; ++ unsigned int sg_flag:1; ++ unsigned int hw_own:1; ++ } tx; ++ unsigned int val; ++ } desc1; ++ unsigned int reserve_desc2; ++ unsigned int tx_err; ++}; ++#else ++struct higmac_desc { ++ unsigned int data_buff_addr; ++ ++ unsigned int buffer_len:11; ++#if defined(CONFIG_HIGMAC_RXCSUM) ++ unsigned int reserve2:1; ++ unsigned int payload_csum_err:1; ++ unsigned int header_csum_err:1; ++ unsigned int payload_csum_done:1; ++#else ++ unsigned int reserve2:5; ++#endif ++ unsigned int data_len:11; ++ unsigned int reserve1:2; ++ unsigned int fl:2; ++ unsigned int descvid:1; ++ ++ unsigned int rxhash; ++ unsigned int reserve3:8; ++ unsigned int l3_hash:1; ++ unsigned int has_hash:1; ++ unsigned int skb_id:14; ++ unsigned int reserve31:8; ++ ++ unsigned int reserve4; ++ unsigned int reserve5; ++ unsigned int reserve6; ++ unsigned int reserve7; ++}; ++ ++struct higmac_tso_desc { ++ unsigned int data_buff_addr; ++ union { ++ struct { ++ unsigned int prot_hdr_len:4; ++ unsigned int ip_hdr_len:4; ++ unsigned int prot_type:1; ++ unsigned int ip_ver:1; ++ unsigned int vlan_flag:1; ++ unsigned int nfrags_num:5; ++ unsigned int data_len:11; ++ unsigned int reservel:1; ++ unsigned int tso_flag:1; ++ unsigned int coe_flag:1; ++ unsigned int sg_flag:1; ++ unsigned int hw_own:1; ++ } tx; ++ unsigned int val; ++ } desc1; ++ unsigned int reserve_desc2; ++ unsigned int reserve3; ++ ++ unsigned int tx_err; ++ unsigned int reserve5; ++ unsigned int reserve6; ++ unsigned int reserve7; ++}; ++#endif ++ ++#define SKB_MAGIC ((struct sk_buff *)0x5a) ++ ++struct higmac_napi { ++ struct napi_struct napi; ++ struct higmac_netdev_local *ndev_priv; ++ int rxq_id; ++}; ++ ++struct higmac_rss_info { ++ u32 hash_cfg; ++ u32 ind_tbl_size; ++ u8 ind_tbl[RSS_INDIRECTION_TABLE_SIZE]; ++ u8 key[RSS_HASH_KEY_SIZE]; ++}; ++ ++#define QUEUE_NUMS (4) ++struct higmac_netdev_local { ++#define HIGMAC_SG_DESC_ADD (64U) ++ struct sg_desc *dma_sg_desc ____cacheline_aligned; ++ dma_addr_t dma_sg_phy; ++ unsigned int sg_head; ++ unsigned int sg_tail; ++ unsigned int sg_count; ++ ++ void __iomem *gmac_iobase; ++ void __iomem *macif_base; ++ void __iomem *axi_bus_cfg_base; ++ int index; /* 0 -- mac0, 1 -- mac1 */ ++ ++ u32 hw_cap; ++ bool tso_supported; ++ bool has_rxhash_cap; ++ bool has_rss_cap; ++ int num_rxqs; ++ struct higmac_napi q_napi[RSS_NUM_RXQS]; ++ int irq[RSS_NUM_RXQS]; ++ struct higmac_rss_info rss_info; ++ ++ struct reset_control *port_rst; ++ struct reset_control *macif_rst; ++ struct reset_control *phy_rst; ++ ++ struct { ++ struct higmac_desc *desc; ++ dma_addr_t phys_addr; ++ int *sg_desc_offset; ++ ++ /* how many desc in the desc pool */ ++ unsigned int count; ++ struct sk_buff **skb; ++ ++ /* sizeof(desc) * count */ ++ unsigned int size; ++ } pool[QUEUE_NUMS + RSS_NUM_RXQS - 1]; ++#define rx_fq pool[0] ++#define rx_bq pool[1] ++#define tx_bq pool[2] ++#define tx_rq pool[3] ++ ++ struct sk_buff **tx_skb; ++ struct sk_buff **rx_skb; ++ ++ struct device *dev; ++ struct net_device *netdev; ++ struct clk *clk; ++ struct clk *macif_clk; ++ ++ struct higmac_adapter *adapter; ++ ++ struct timer_list monitor; ++ ++ char phy_name[MII_BUS_ID_SIZE]; ++ struct phy_device *phy; ++ struct device_node *phy_node; ++ phy_interface_t phy_mode; ++ bool autoeee; ++ bool internal_phy; ++ int (*eee_init)(struct phy_device *phy_dev); ++ ++ unsigned int flow_ctrl; ++ unsigned int pause; ++ unsigned int pause_interval; ++ unsigned int flow_ctrl_active_threshold; ++ unsigned int flow_ctrl_deactive_threshold; ++ ++ int old_link; ++ int old_speed; ++ int old_duplex; ++ ++ /* receive packet lock */ ++ spinlock_t rxlock; ++ /* transmit packet lock */ ++ spinlock_t txlock; ++ /* power management lock */ ++ spinlock_t pmtlock; ++ ++ int dev_state; /* INIT/OPEN/CLOSE */ ++ char pm_state; ++ bool wol_enable; ++ u32 msg_enable; ++#define INIT (0) /* power off gmac */ ++#define OPEN (1) /* power on gmac */ ++#define CLOSE (2) /* power off gmac */ ++}; ++ ++enum tso_version { ++ VER_NO_TSO = 0x0, ++ VER_BYTE_SPLICE = 0x1, ++ VER_SG_COE = 0x2, ++ VER_TSO = 0x3, ++}; ++ ++#ifdef HIGMAC_TSO_DEBUG ++#define MAX_RECORD (100) ++struct send_pkt_info { ++ struct higmac_tso_desc desc; ++ int status; ++}; ++#endif ++ ++int higmac_tx_avail(struct higmac_netdev_local *ld); ++ ++/* board related func */ ++void higmac_mac_core_reset(struct higmac_netdev_local *priv); ++void higmac_hw_internal_phy_reset(struct higmac_netdev_local *priv); ++void higmac_hw_external_phy_reset(struct higmac_netdev_local *priv); ++void higmac_internal_phy_clk_disable(struct higmac_netdev_local *priv); ++void higmac_internal_phy_clk_enable(struct higmac_netdev_local *priv); ++void higmac_hw_all_clk_disable(struct higmac_netdev_local *priv); ++void higmac_hw_all_clk_enable(struct higmac_netdev_local *priv); ++ ++/* board independent func */ ++void higmac_hw_phy_reset(struct higmac_netdev_local *priv); ++ ++void pmt_reg_restore(struct higmac_netdev_local *ld); ++#endif +diff --git a/drivers/net/ethernet/hisilicon/higmac/pm.c b/drivers/net/ethernet/hisilicon/higmac/pm.c +new file mode 100644 +index 0000000..7620abe +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/pm.c +@@ -0,0 +1,359 @@ ++#include ++#include "higmac.h" ++ ++#define N (31) ++#define FILTERS (4) ++struct pm_config { ++ unsigned char index; /* bit0--eth0 bit1--eth1 */ ++ unsigned char uc_pkts_enable; ++ unsigned char magic_pkts_enable; ++ unsigned char wakeup_pkts_enable; ++ struct { ++ unsigned int mask_bytes:N; ++ unsigned int reserved:1; /* userspace ignore this bit */ ++ unsigned char offset; /* >= 12 */ ++ unsigned char value[N]; /* byte string */ ++ unsigned char valid; /* valid filter */ ++ } filter[FILTERS]; ++}; ++ ++struct pm_reg_config { ++ unsigned int pmt_ctrl; ++ unsigned int pmt_mask0; ++ unsigned int pmt_mask1; ++ unsigned int pmt_mask2; ++ unsigned int pmt_mask3; ++ unsigned int pmt_cmd; ++ unsigned int pmt_offset; ++ unsigned int pmt_crc1_0; ++ unsigned int pmt_crc3_2; ++}; ++ ++struct pm_reg_config pm_reg_config_backup; ++ ++#define PMT_CTRL 0xa00 ++#define PMT_MASK0 0xa04 ++#define PMT_MASK1 0xa08 ++#define PMT_MASK2 0xa0c ++#define PMT_MASK3 0xa10 ++#define PMT_CMD 0xa14 ++#define PMT_OFFSET 0xa18 ++#define PMT_CRC1_0 0xa1c ++#define PMT_CRC3_2 0xa20 ++#define MASK_INVALID_BIT BIT(31) ++ ++static void init_crc_table(void); ++static unsigned short compute_crc(char *message, int nbytes); ++static unsigned short calculate_crc16(char *buf, unsigned int mask) ++{ ++ char data[N]; ++ int i, len = 0; ++ ++ memset(data, 0, sizeof(data)); ++ ++ for (i = 0; i < N; i++) { ++ if (mask & 0x1) ++ data[len++] = buf[i]; ++ ++ mask >>= 1; ++ } ++ ++ return compute_crc(data, len); ++} ++ ++/* use this func in config pm func */ ++void _pmt_reg_backup(struct higmac_netdev_local *ld) ++{ ++ pm_reg_config_backup.pmt_ctrl = readl(ld->gmac_iobase + PMT_CTRL); ++ pm_reg_config_backup.pmt_mask0 = readl(ld->gmac_iobase + PMT_MASK0); ++ pm_reg_config_backup.pmt_mask1 = readl(ld->gmac_iobase + PMT_MASK1); ++ pm_reg_config_backup.pmt_mask2 = readl(ld->gmac_iobase + PMT_MASK2); ++ pm_reg_config_backup.pmt_mask3 = readl(ld->gmac_iobase + PMT_MASK3); ++ pm_reg_config_backup.pmt_cmd = readl(ld->gmac_iobase + PMT_CMD); ++ pm_reg_config_backup.pmt_offset = readl(ld->gmac_iobase + PMT_OFFSET); ++ pm_reg_config_backup.pmt_crc1_0 = readl(ld->gmac_iobase + PMT_CRC1_0); ++ pm_reg_config_backup.pmt_crc3_2 = readl(ld->gmac_iobase + PMT_CRC3_2); ++} ++ ++#define PM_SET (1) ++#define PM_CLEAR (0) ++ ++int pmt_config_gmac(struct pm_config *config, struct higmac_netdev_local *ld) ++{ ++ unsigned int v = 0, cmd = 0, offset = 0; ++ unsigned short crc[FILTERS] = { 0 }; ++ unsigned long flags; ++ int reg_mask = 0; ++ int i; ++ ++ if (!ld) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&ld->pmtlock, flags); ++ if (config->wakeup_pkts_enable) { ++ /* disable wakeup_pkts_enable before reconfig? */ ++ v = readl(ld->gmac_iobase + PMT_CTRL); ++ v &= ~BIT(2); ++ writel(v, ld->gmac_iobase + PMT_CTRL); /* any side effect? */ ++ } else { ++ goto config_ctrl; ++ } ++ ++/* filter.valid mask.valid mask_bytes effect ++ * 0 * * no use the filter ++ * 1 0 * all pkts can wake-up(non-exist) ++ * 1 1 0 all pkts can wake-up ++ * 1 1 !0 normal filter ++ */ ++ /* setup filter */ ++ for (i = 0; i < FILTERS; i++) { ++ if (config->filter[i].valid) { ++ if (config->filter[i].offset < 12) ++ continue; ++ /* offset and valid bit */ ++ offset |= config->filter[i].offset << (i * 8); ++ cmd |= BIT(i * 8); /* valid bit */ ++ /* mask */ ++ reg_mask = PMT_MASK0 + (i * 4); ++ ++ /* for logic, mask valid bit(bit31) must set to 0, ++ * 0 is enable ++ */ ++ v = config->filter[i].mask_bytes; ++ v &= ~BIT(31); ++ writel(v, ld->gmac_iobase + reg_mask); ++ ++ /* crc */ ++ crc[i] = calculate_crc16(config->filter[i].value, v); ++ if (i <= 1) { /* for filter0 and filter 1 */ ++ v = readl(ld->gmac_iobase + PMT_CRC1_0); ++ v &= ~(0xFFFF << (16 * i)); ++ v |= crc[i] << (16 * i); ++ writel(v, ld->gmac_iobase + PMT_CRC1_0); ++ } else { /* filter2 and filter3 */ ++ v = readl(ld->gmac_iobase + PMT_CRC3_2); ++ v &= ~(0xFFFF << (16 * (i - 2))); ++ v |= crc[i] << (16 * (i - 2)); ++ writel(v, ld->gmac_iobase + PMT_CRC3_2); ++ } ++ } ++ } ++ ++ if (cmd) { ++ writel(offset, ld->gmac_iobase + PMT_OFFSET); ++ writel(cmd, ld->gmac_iobase + PMT_CMD); ++ } ++ ++config_ctrl: ++ v = 0; ++ if (config->uc_pkts_enable) ++ v |= BIT(9); /* uc pkts wakeup */ ++ if (config->wakeup_pkts_enable) ++ v |= BIT(2); /* use filter framework */ ++ if (config->magic_pkts_enable) ++ v |= BIT(1); /* magic pkts wakeup */ ++ ++ v |= 3 << 5; /* clear irq status */ ++ writel(v, ld->gmac_iobase + PMT_CTRL); ++ ++ _pmt_reg_backup(ld); ++ ++ spin_unlock_irqrestore(&ld->pmtlock, flags); ++ ++ return 0; ++} ++ ++/* pmt_config will overwrite pre-config */ ++int pmt_config(struct net_device *ndev, struct pm_config *config) ++{ ++ static int init; ++ int ret = -EINVAL; ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ ++ if (!init) ++ init_crc_table(); ++ ++ ret = pmt_config_gmac(config, priv); ++ if (ret) ++ return ret; ++ ++ priv->pm_state = PM_SET; ++ priv->wol_enable = true; ++ device_set_wakeup_enable(priv->dev, 1); ++ ++ return ret; ++} ++ ++inline bool pmt_enter(struct higmac_netdev_local *ld) ++{ ++ int pm = false; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ld->pmtlock, flags); ++ if (ld->pm_state == PM_SET) { ++ int v; ++ ++ v = readl(ld->gmac_iobase + PMT_CTRL); ++ v |= BIT(0); /* enter power down */ ++ v |= BIT(3); /* enable wakeup irq */ ++ v |= 3 << 5; /* clear irq status */ ++ writel(v, ld->gmac_iobase + PMT_CTRL); ++ ++ ld->pm_state = PM_CLEAR; ++ pm = true; ++ } ++ spin_unlock_irqrestore(&ld->pmtlock, flags); ++ return pm; ++} ++ ++inline void pmt_exit(struct higmac_netdev_local *ld) ++{ ++ int v; ++ unsigned long flags; ++ ++ /* logic auto exit power down mode */ ++ spin_lock_irqsave(&ld->pmtlock, flags); ++ ++ v = readl(ld->gmac_iobase + PMT_CTRL); ++ v &= ~BIT(0); /* enter power down */ ++ v &= ~BIT(3); /* enable wakeup irq */ ++ ++ v |= 3 << 5; /* clear irq status */ ++ writel(v, ld->gmac_iobase + PMT_CTRL); ++ ++ spin_unlock_irqrestore(&ld->pmtlock, flags); ++ ++ ld->wol_enable = false; ++ /* device_set_wakeup_enable(ld->dev, 0); */ ++} ++ ++void pmt_reg_restore(struct higmac_netdev_local *ld) ++{ ++ unsigned int v; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ld->pmtlock, flags); ++ v = pm_reg_config_backup.pmt_mask0; ++ writel(v, ld->gmac_iobase + PMT_MASK0); ++ ++ v = pm_reg_config_backup.pmt_mask1; ++ writel(v, ld->gmac_iobase + PMT_MASK1); ++ ++ v = pm_reg_config_backup.pmt_mask2; ++ writel(v, ld->gmac_iobase + PMT_MASK2); ++ ++ v = pm_reg_config_backup.pmt_mask3; ++ writel(v, ld->gmac_iobase + PMT_MASK3); ++ ++ v = pm_reg_config_backup.pmt_cmd; ++ writel(v, ld->gmac_iobase + PMT_CMD); ++ ++ v = pm_reg_config_backup.pmt_offset; ++ writel(v, ld->gmac_iobase + PMT_OFFSET); ++ ++ v = pm_reg_config_backup.pmt_crc1_0; ++ writel(v, ld->gmac_iobase + PMT_CRC1_0); ++ ++ v = pm_reg_config_backup.pmt_crc3_2; ++ writel(v, ld->gmac_iobase + PMT_CRC3_2); ++ ++ v = pm_reg_config_backup.pmt_ctrl; ++ writel(v, ld->gmac_iobase + PMT_CTRL); ++ spin_unlock_irqrestore(&ld->pmtlock, flags); ++} ++ ++/* ========the following code copy from Synopsys DWC_gmac_crc_example.c====== */ ++#define CRC16 /* Change it to CRC16 for CRC16 Computation */ ++ ++#if defined(CRC16) ++#define CRC_NAME "CRC-16" ++#define POLYNOMIAL 0x8005 ++#define INITIAL_REMAINDER 0xFFFF ++#define FINAL_XOR_VALUE 0x0000 ++#define REVERSE_DATA ++#undef REVERSE_REMAINDER ++#endif ++ ++#define WIDTH (8 * sizeof(unsigned short)) ++#define TOPBIT BIT(WIDTH - 1) ++ ++#ifdef REVERSE_DATA ++#undef REVERSE_DATA ++#define REVERSE_DATA(X) ((unsigned char)reverse((X), 8)) ++#else ++#undef REVERSE_DATA ++#define REVERSE_DATA(X) (X) ++#endif ++ ++#ifdef REVERSE_REMAINDER ++#undef REVERSE_REMAINDER ++#define REVERSE_REMAINDER(X) ((unsigned short)reverse((X), WIDTH)) ++#else ++#undef REVERSE_REMAINDER ++#define REVERSE_REMAINDER(X) (X) ++#endif ++ ++static unsigned short crc_table[256]; ++ ++/* Reverse the data ++ * Input1: Data to be reversed ++ * Input2: number of bits in the data ++ * Output: The reversed data ++ */ ++static unsigned int reverse(unsigned int data, unsigned char nbits) ++{ ++ unsigned int reversed = 0x00000000; ++ unsigned char bit; ++ ++ /* Reverse the data about the center bit. */ ++ for (bit = 0; bit < nbits; ++bit) { ++ /* If the LSB bit is set, set the reflection of it. */ ++ if (data & 0x01) ++ reversed |= BIT((nbits - 1) - bit); ++ ++ data = (data >> 1); ++ } ++ return reversed; ++} ++ ++/* This Initializes the partial CRC look up table */ ++static void init_crc_table(void) ++{ ++ unsigned short remainder; ++ int dividend; ++ unsigned char bit; ++ ++ /* Compute the remainder of each possible dividend. */ ++ for (dividend = 0; dividend < 256; ++dividend) { ++ /* Start with the dividend followed by zeros. */ ++ remainder = (unsigned short)(dividend << (WIDTH - 8)); ++ ++ /* Perform modulo-2 division, a bit at a time. */ ++ for (bit = 8; bit > 0; --bit) { ++ /* Try to divide the current data bit. */ ++ if (remainder & TOPBIT) ++ remainder = (remainder << 1) ^ POLYNOMIAL; ++ else ++ remainder = (remainder << 1); ++ } ++ ++ /* Store the result into the table. */ ++ crc_table[dividend] = remainder; ++ } ++} ++ ++static unsigned short compute_crc(char *message, int nbytes) ++{ ++ unsigned short remainder = INITIAL_REMAINDER; ++ int byte; ++ unsigned char data; ++ ++ /* Divide the message by the polynomial, a byte at a time. */ ++ for (byte = 0; byte < nbytes; ++byte) { ++ data = REVERSE_DATA(message[byte]) ^ (remainder >> (WIDTH - 8)); ++ remainder = crc_table[data] ^ (remainder << 8); ++ } ++ ++ /* The final remainder is the CRC. */ ++ return (REVERSE_REMAINDER(remainder) ^ FINAL_XOR_VALUE); ++} +diff --git a/drivers/net/ethernet/hisilicon/higmac/proc-dev.c b/drivers/net/ethernet/hisilicon/higmac/proc-dev.c +new file mode 100644 +index 0000000..d522565 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/proc-dev.c +@@ -0,0 +1,111 @@ ++#include "sockioctl.h" ++ ++/* debug code */ ++static int set_suspend(int eth_n) ++{ ++ return 0; ++} ++ ++/* debug code */ ++static int set_resume(int eth_n) ++{ ++ /* higmac_dev_driver.resume(&higmac_platform_device); */ ++ return 0; ++} ++ ++static int hw_states_read(struct seq_file *m, void *v) ++{ ++ return 0; ++} ++ ++static struct proc_dir_entry *higmac_proc_root; ++ ++#define proc_open(name) \ ++static int proc_open_##name(struct inode *inode, struct file *file) \ ++{ \ ++ return single_open(file, name, PDE_DATA(inode)); \ ++} \ ++ ++proc_open(hw_states_read); ++ ++static struct proc_file { ++ char *name; ++ const struct file_operations ops; ++ ++} proc_file[] = { ++ { ++ .name = "hw_stats", ++ .ops = { ++ .open = proc_open_hw_states_read, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ }, ++ } ++}; ++ ++/* /proc/higmac/ ++ * |---hw_stats ++ * |---skb_pools ++ */ ++void higmac_proc_create(void) ++{ ++ int i; ++ ++ higmac_proc_root = proc_mkdir("higmac", NULL); ++ if (!higmac_proc_root) ++ return; ++ ++ for (i = 0; i < ARRAY_SIZE(proc_file); i++) { ++ struct proc_dir_entry *entry; ++ ++ entry = proc_create(proc_file[i].name, 0000, higmac_proc_root, ++ &proc_file[i].ops); ++ if (!entry) ++ pr_err("failed to create %s\n", proc_file[i].name); ++ } ++} ++ ++void higmac_proc_destroy(void) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(proc_file); i++) ++ remove_proc_entry(proc_file[i].name, higmac_proc_root); ++ ++ remove_proc_entry("higmac", NULL); ++} ++ ++int higmac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ struct pm_config pm_config; ++ int val = 0; ++ ++ switch (cmd) { ++ case SIOCSETPM: ++ if (copy_from_user(&pm_config, rq->ifr_data, sizeof(pm_config))) ++ return -EFAULT; ++ return pmt_config(ndev, &pm_config); ++ ++ case SIOCSETSUSPEND: ++ if (copy_from_user(&val, rq->ifr_data, sizeof(val))) ++ return -EFAULT; ++ return set_suspend(val); ++ ++ case SIOCSETRESUME: ++ if (copy_from_user(&val, rq->ifr_data, sizeof(val))) ++ return -EFAULT; ++ return set_resume(val); ++ ++ default: ++ if (!netif_running(ndev)) ++ return -EINVAL; ++ ++ if (!priv->phy) ++ return -EINVAL; ++ ++ return phy_mii_ioctl(priv->phy, rq, cmd); ++ } ++ return 0; ++} +diff --git a/drivers/net/ethernet/hisilicon/higmac/sockioctl.h b/drivers/net/ethernet/hisilicon/higmac/sockioctl.h +new file mode 100644 +index 0000000..571c71a +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/sockioctl.h +@@ -0,0 +1,12 @@ ++#ifndef _SOCKIOCTL_H_ ++#define _SOCKIOCTL_H_ ++ ++#include ++ ++#define SIOCSETPM (SIOCDEVPRIVATE + 4) /* set pmt wake up config */ ++#define SIOCSETSUSPEND (SIOCDEVPRIVATE + 5) /* call dev->suspend, debug */ ++#define SIOCSETRESUME (SIOCDEVPRIVATE + 6) /* call dev->resume, debug */ ++ ++int higmac_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd); ++ ++#endif +diff --git a/drivers/net/ethernet/hisilicon/higmac/tso.h b/drivers/net/ethernet/hisilicon/higmac/tso.h +new file mode 100644 +index 0000000..6416eef +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/tso.h +@@ -0,0 +1,53 @@ ++#ifndef __HIETH_TSO_H ++#define __HIETH_TSO_H ++ ++#define SG_FLAG BIT(30) ++#define COE_FLAG BIT(29) ++#define TSO_FLAG BIT(28) ++#define VLAN_FLAG BIT(10) ++#define IPV6_FLAG BIT(9) ++#define UDP_FLAG BIT(8) ++ ++#define PKT_IPV6_HDR_LEN 10 ++#define PKT_UDP_HDR_LEN 2 ++#define WORD_TO_BYTE 4 ++enum { ++ PKT_NORMAL, ++ PKT_SG ++}; ++ ++enum { ++ PKT_IPV4, ++ PKT_IPV6 ++}; ++ ++enum { ++ PKT_TCP, ++ PKT_UDP ++}; ++ ++struct frags_info { ++ /* Word(2*i+2) */ ++ u32 addr; ++ /* Word(2*i+3) */ ++ u32 size:16; ++ u32 reserved:16; ++}; ++ ++struct sg_desc { ++ /* Word0 */ ++ u32 total_len:17; ++ u32 reserv:15; ++ /* Word1 */ ++ u32 ipv6_id; ++ /* Word2 */ ++ u32 linear_addr; ++ /* Word3 */ ++ u32 linear_len:16; ++ u32 reserv3:16; ++ /* MAX_SKB_FRAGS = 17 */ ++ struct frags_info frags[18]; ++ /* struct frags_info frags[MAX_SKB_FRAGS]; */ ++}; ++ ++#endif +diff --git a/drivers/net/ethernet/hisilicon/higmac/util.h b/drivers/net/ethernet/hisilicon/higmac/util.h +new file mode 100644 +index 0000000..f08cbf6 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/util.h +@@ -0,0 +1,29 @@ ++#ifndef __HIGMAC_UTIL_H__ ++#define __HIGMAC_UTIL_H__ ++ ++#define HIGMAC_TRACE_LEVEL 10 ++ ++#define higmac_trace(level, msg...) do { \ ++ if ((level) >= HIGMAC_TRACE_LEVEL) { \ ++ pr_info("higmac_trace:%s:%d: ", __FILE__, __LINE__); \ ++ printk(msg); \ ++ printk("\n"); \ ++ } \ ++} while (0) ++ ++#define higmac_error(args...) do { \ ++ pr_err("higmac:%s:%d: ", __FILE__, __LINE__); \ ++ printk(args); \ ++ printk("\n"); \ ++} while (0) ++ ++#define higmac_assert(cond) do { \ ++ if (!(cond)) \ ++ pr_alert("Assert:higmac:%s:%d\n", \ ++ __FILE__, \ ++ __LINE__);\ ++} while (0) ++ ++#define MK_BITS(shift, nbits) ((((shift) & 0x1F) << 16) | ((nbits) & 0x3F)) ++ ++#endif +diff --git a/drivers/net/ethernet/hisilicon/hisi-femac/Makefile b/drivers/net/ethernet/hisilicon/hisi-femac/Makefile +new file mode 100644 +index 0000000..266ca3b +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hisi-femac/Makefile +@@ -0,0 +1,6 @@ ++# ++# Makefile for the HISILICON Fast Ethernet network device drivers. ++# ++ ++obj-$(CONFIG_HISI_FEMAC) += hisi-femac.o ++hisi-femac-objs := hisi_femac.o phy_fix.o +diff --git a/drivers/net/ethernet/hisilicon/hisi-femac/festa_v272_2723.h b/drivers/net/ethernet/hisilicon/hisi-femac/festa_v272_2723.h +new file mode 100644 +index 0000000..c12bc41 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hisi-femac/festa_v272_2723.h +@@ -0,0 +1,102 @@ ++0x33f9, 0xbd, ++0x33fa, 0x34, ++0x33fb, 0x00, ++0x33fc, 0x39, ++0x3400, 0x39, ++0x3401, 0xCC, ++0x3402, 0x27, ++0x3403, 0x23, ++0x3404, 0xFD, ++0x3405, 0xFF, ++0x3406, 0xF0, ++0x3407, 0x20, ++0x3408, 0x00, ++0x3409, 0x3C, ++0x340A, 0x3C, ++0x340B, 0x30, ++0x340C, 0xF6, ++0x340D, 0x00, ++0x340E, 0x4A, ++0x340F, 0xC4, ++0x3410, 0x7F, ++0x3411, 0xE7, ++0x3412, 0x01, ++0x3413, 0xF6, ++0x3414, 0x01, ++0x3415, 0xBE, ++0x3416, 0xC1, ++0x3417, 0x02, ++0x3418, 0x27, ++0x3419, 0x0E, ++0x341A, 0xE6, ++0x341B, 0x01, ++0x341C, 0xC1, ++0x341D, 0x14, ++0x341E, 0x27, ++0x341F, 0x08, ++0x3420, 0xC1, ++0x3421, 0x18, ++0x3422, 0x25, ++0x3423, 0x09, ++0x3424, 0xC1, ++0x3425, 0x1B, ++0x3426, 0x22, ++0x3427, 0x05, ++0x3428, 0xC6, ++0x3429, 0x5C, ++0x342A, 0xF7, ++0x342B, 0x20, ++0x342C, 0xA1, ++0x342D, 0xF6, ++0x342E, 0x01, ++0x342F, 0xBF, ++0x3430, 0xC1, ++0x3431, 0x01, ++0x3432, 0x26, ++0x3433, 0x29, ++0x3434, 0xF6, ++0x3435, 0x30, ++0x3436, 0x55, ++0x3437, 0xC0, ++0x3438, 0x05, ++0x3439, 0xE7, ++0x343A, 0x01, ++0x343B, 0xC1, ++0x343C, 0x13, ++0x343D, 0x23, ++0x343E, 0x04, ++0x343F, 0xC6, ++0x3440, 0x13, ++0x3441, 0xE7, ++0x3442, 0x01, ++0x3443, 0x18, ++0x3444, 0xFE, ++0x3445, 0x30, ++0x3446, 0x4C, ++0x3447, 0x18, ++0x3448, 0x3A, ++0x3449, 0x18, ++0x344A, 0xE6, ++0x344B, 0x00, ++0x344C, 0x58, ++0x344D, 0x58, ++0x344E, 0x58, ++0x344F, 0x58, ++0x3450, 0x58, ++0x3451, 0xE7, ++0x3452, 0x00, ++0x3453, 0xF6, ++0x3454, 0x20, ++0x3455, 0x04, ++0x3456, 0xC4, ++0x3457, 0x1F, ++0x3458, 0xEA, ++0x3459, 0x00, ++0x345A, 0xF7, ++0x345B, 0x20, ++0x345C, 0x04, ++0x345D, 0x38, ++0x345E, 0x38, ++0x345F, 0x39, ++0x3400, 0x01, ++0x33f8, 0x01 +diff --git a/drivers/net/ethernet/hisilicon/hisi-femac/hisi_femac.c b/drivers/net/ethernet/hisilicon/hisi-femac/hisi_femac.c +new file mode 100644 +index 0000000..067288c +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hisi-femac/hisi_femac.c +@@ -0,0 +1,1693 @@ ++/* ++ * Hisilicon Fast Ethernet MAC Driver ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "phy_fix.h" ++ ++/* MAC control register list */ ++#define MAC_PORTSEL 0x0200 ++#define MAC_PORTSEL_STAT_CPU BIT(0) ++#define MAC_PORTSEL_RMII BIT(1) ++#define MAC_PORTSET 0x0208 ++#define MAC_PORTSET_DUPLEX_FULL BIT(0) ++#define MAC_PORTSET_LINKED BIT(1) ++#define MAC_PORTSET_SPEED_100M BIT(2) ++#define MAC_SET 0x0210 ++#define MAX_FRAME_SIZE 1600 ++#define MAX_FRAME_SIZE_MASK GENMASK(10, 0) ++#define BIT_PAUSE_EN BIT(18) ++#define RX_COALESCE_SET 0x0340 ++#define RX_COALESCED_FRAME_OFFSET 24 ++#define RX_COALESCED_FRAMES 8 ++#define RX_COALESCED_TIMER 0x74 ++#define QLEN_SET 0x0344 ++#define RX_DEPTH_OFFSET 8 ++#define MAX_HW_FIFO_DEPTH 64 ++#define HW_TX_FIFO_DEPTH 12 ++#define HW_RX_FIFO_DEPTH (MAX_HW_FIFO_DEPTH - HW_TX_FIFO_DEPTH) ++#define FC_LEVEL 0x0348 ++#define BITS_FC_ACTIVE_THR_OFFSET 8 ++#define FC_DEACTIVE_THR_MASK GENMASK(5, 0) ++#define FC_ACTIVE_THR_MASK GENMASK(13, 8) ++#define BIT_FC_EN BIT(14) ++#define IQFRM_DES 0x0354 ++#define RX_FRAME_LEN_MASK GENMASK(11, 0) ++#define BITS_PAYLOAD_ERR_OFFSET 28 ++#define BITS_PAYLOAD_ERR_MASK 0x1 ++#define BITS_HEADER_ERR_OFFSET 29 ++#define BITS_HEADER_ERR_MASK 0x1 ++#define BITS_PAYLOAD_DONE_OFFSET 30 ++#define BITS_PAYLOAD_DONE_MASK 0x1 ++#define BITS_HEADER_DONE_OFFSET 31 ++#define BITS_HEADER_DONE_MASK 0x1 ++#define IQ_ADDR 0x0358 ++#define EQ_ADDR 0x0360 ++#define EQFRM_LEN 0x0364 ++#define ADDRQ_STAT 0x036C ++#define TX_CNT_INUSE_MASK GENMASK(5, 0) ++#define BIT_TX_READY BIT(24) ++#define BIT_RX_READY BIT(25) ++#define RX_COE_CTRL 0x0380 ++#define BIT_COE_IPV6_UDP_ZERO_DROP BIT(13) ++#define BIT_COE_PAYLOAD_DROP BIT(14) ++#define BIT_COE_IPHDR_DROP BIT(15) ++#define COE_ERR_DROP (BIT_COE_IPHDR_DROP | \ ++ BIT_COE_PAYLOAD_DROP | \ ++ BIT_COE_IPV6_UDP_ZERO_DROP) ++#define TSO_DBG_EN 0x03A4 ++#define BITS_TSO_DBG_EN BIT(31) ++#define TSO_DBG_STATE 0x03A8 ++#define TSO_DBG_ADDR 0x03AC ++#define TSO_DBG_TX_INFO 0x03B0 ++#define TSO_DBG_TX_ERR 0x03B4 ++/* global control register list */ ++#define GLB_HOSTMAC_L32 0x0000 ++#define GLB_HOSTMAC_H16 0x0004 ++#define GLB_SOFT_RESET 0x0008 ++#define SOFT_RESET_ALL BIT(0) ++#define GLB_FWCTRL 0x0010 ++#define FWCTRL_VLAN_ENABLE BIT(0) ++#define FWCTRL_FW2CPU_ENA BIT(5) ++#define FWCTRL_FWALL2CPU BIT(7) ++#define GLB_MACTCTRL 0x0014 ++#define MACTCTRL_UNI2CPU BIT(1) ++#define MACTCTRL_MULTI2CPU BIT(3) ++#define MACTCTRL_BROAD2CPU BIT(5) ++#define MACTCTRL_MACT_ENA BIT(7) ++#define GLB_IRQ_STAT 0x0030 ++#define GLB_IRQ_ENA 0x0034 ++#define IRQ_ENA_PORT0_MASK GENMASK(7, 0) ++#define IRQ_ENA_PORT0 BIT(18) ++#define IRQ_ENA_ALL BIT(19) ++#define GLB_IRQ_RAW 0x0038 ++#define IRQ_INT_RX_RDY BIT(0) ++#define IRQ_INT_TX_PER_PACKET BIT(1) ++#define IRQ_INT_TX_FIFO_EMPTY BIT(6) ++#define IRQ_INT_MULTI_RXRDY BIT(7) ++#define INT_TX_ERR BIT(8) ++#define DEF_INT_MASK (IRQ_INT_MULTI_RXRDY | \ ++ IRQ_INT_TX_PER_PACKET | \ ++ IRQ_INT_TX_FIFO_EMPTY) ++#define GLB_MAC_L32_BASE 0x0100 ++#define GLB_MAC_H16_BASE 0x0104 ++#define MACFLT_HI16_MASK GENMASK(15, 0) ++#define BIT_MACFLT_ENA BIT(17) ++#define BIT_MACFLT_FW2CPU BIT(21) ++#define GLB_MAC_H16(reg) (GLB_MAC_H16_BASE + ((reg) * 0x8)) ++#define GLB_MAC_L32(reg) (GLB_MAC_L32_BASE + ((reg) * 0x8)) ++#define MAX_MAC_FILTER_NUM 8 ++#define MAX_UNICAST_ADDRESSES 2 ++#define MAX_MULTICAST_ADDRESSES (MAX_MAC_FILTER_NUM - \ ++ MAX_UNICAST_ADDRESSES) ++/* software tx and rx queue number, should be power of 2 */ ++#define TXQ_NUM 64 ++#define RXQ_NUM 128 ++#define FEMAC_POLL_WEIGHT 16 ++#define HW_CAP_TSO BIT(0) ++#define HW_CAP_RXCSUM BIT(1) ++#define HAS_TSO_CAP(hw_cap) ((hw_cap) & HW_CAP_TSO) ++#define HAS_RXCSUM_CAP(hw_cap) ((hw_cap) & HW_CAP_RXCSUM) ++#define RXBUF_ADDR_ALIGN_SIZE 64UL ++/* UDP header len is 2 word */ ++#define UDP_HDR_LEN 2 ++/* IPv6 header len is 10 word */ ++#define IPV6_HDR_LEN 10 ++#define WORD_TO_BYTE 4 ++ ++#define BIT_OFFSET_NFRAGS_NUM 11 ++#define BIT_OFFSET_PROT_HEADER_LEN 16 ++#define BIT_OFFSET_IP_HEADER_LEN 20 ++#define BIT_FLAG_SG BIT(26) ++#define BIT_FLAG_TXCSUM BIT(27) ++#define BIT_FLAG_UDP BIT(28) ++#define BIT_FLAG_IPV6 BIT(29) ++#define BIT_FLAG_VLAN BIT(30) ++#define BIT_FLAG_TSO BIT(31) ++ ++#define PHY_RESET_DELAYS_PROPERTY "hisilicon,phy-reset-delays-us" ++ ++/* The threshold for activing tx flow ctrl. ++ * When the left amount of receive queue descriptors is below this threshold, ++ * hardware will send pause frame immediately. ++ * We advise this value is set between 1 and 10. ++ * Too bigger is not a good choice. ++ * This value must be smaller than tx flow ctrl deactive threshold. ++ */ ++#define TX_FLOW_CTRL_ACTIVE_THRESHOLD 3 ++/* The threshold for deactiving tx flow ctrl. ++ * When the left amount of receive queue descriptors is ++ * above or equal with this threshold, ++ * hardware will exit flow control state. ++ * We advise this value is set between 1 and 10. ++ * Too bigger is not a good choice. ++ * This value must be larger than tx flow ctrl active threshold. ++ */ ++#define TX_FLOW_CTRL_DEACTIVE_THRESHOLD 5 ++#define FC_ACTIVE_MIN 1 ++#define FC_ACTIVE_DEFAULT 3 ++#define FC_ACTIVE_MAX 31 ++#define FC_DEACTIVE_MIN 1 ++#define FC_DEACTIVE_DEFAULT 5 ++#define FC_DEACTIVE_MAX 31 ++ ++enum phy_reset_delays { ++ PRE_DELAY, ++ PULSE, ++ POST_DELAY, ++ DELAYS_NUM, ++}; ++ ++struct hisi_femac_queue { ++ struct sk_buff **skb; ++ dma_addr_t *dma_phys; ++ int num; ++ unsigned int head; ++ unsigned int tail; ++}; ++ ++struct hisi_femac_tx_desc_ring { ++ struct tx_desc *desc; ++ dma_addr_t dma_phys; ++}; ++ ++struct hisi_femac_priv { ++ void __iomem *port_base; ++ void __iomem *glb_base; ++ struct clk *clk; ++ struct reset_control *mac_rst; ++ struct reset_control *phy_rst; ++ u32 phy_reset_delays[DELAYS_NUM]; ++ u32 link_status; ++ ++ struct device *dev; ++ struct net_device *ndev; ++ ++ u32 hw_cap; ++ struct hisi_femac_queue txq; ++ struct hisi_femac_queue rxq; ++ struct hisi_femac_tx_desc_ring tx_ring; ++ u32 tx_fifo_used_cnt; ++ struct napi_struct napi; ++ ++ /* 802.3x flow control */ ++ bool tx_pause_en; ++ u32 tx_pause_active_thresh; ++ u32 tx_pause_deactive_thresh; ++}; ++ ++struct frags_info { ++ /* Word(2*i+2) */ ++ u32 addr; ++ /* Word(2*i+3) */ ++ u32 size:16; ++ u32 reserved:16; ++}; ++ ++struct tx_desc { ++ /* Word0 */ ++ u32 total_len:17; ++ u32 reserv:15; ++ /* Word1 */ ++ u32 ipv6_id; ++ /* Word2 */ ++ u32 linear_addr; ++ /* Word3 */ ++ u32 linear_len:16; ++ u32 reserv3:16; ++ /* MAX_SKB_FRAGS = 17 */ ++ struct frags_info frags[30]; ++ /* struct frags_info frags[MAX_SKB_FRAGS]; */ ++}; ++ ++static void hisi_femac_irq_enable(struct hisi_femac_priv *priv, u32 irqs) ++{ ++ u32 val; ++ ++ val = readl(priv->glb_base + GLB_IRQ_ENA); ++ writel(val | irqs, priv->glb_base + GLB_IRQ_ENA); ++} ++ ++static void hisi_femac_irq_disable(struct hisi_femac_priv *priv, u32 irqs) ++{ ++ u32 val; ++ ++ val = readl(priv->glb_base + GLB_IRQ_ENA); ++ writel(val & (~irqs), priv->glb_base + GLB_IRQ_ENA); ++} ++ ++static void hisi_femac_set_flow_ctrl(struct hisi_femac_priv *priv) ++{ ++ unsigned int pause_en; ++ unsigned int tx_flow_ctrl; ++ ++ tx_flow_ctrl = readl(priv->port_base + FC_LEVEL); ++ tx_flow_ctrl &= ~FC_DEACTIVE_THR_MASK; ++ tx_flow_ctrl |= priv->tx_pause_deactive_thresh; ++ tx_flow_ctrl &= ~FC_ACTIVE_THR_MASK; ++ tx_flow_ctrl |= priv->tx_pause_active_thresh << ++ BITS_FC_ACTIVE_THR_OFFSET; ++ ++ pause_en = readl(priv->port_base + MAC_SET); ++ ++ if (priv->tx_pause_en) { ++ tx_flow_ctrl |= BIT_FC_EN; ++ pause_en |= BIT_PAUSE_EN; ++ } else { ++ tx_flow_ctrl &= ~BIT_FC_EN; ++ pause_en &= ~BIT_PAUSE_EN; ++ } ++ ++ writel(tx_flow_ctrl, priv->port_base + FC_LEVEL); ++ ++ writel(pause_en, priv->port_base + MAC_SET); ++} ++ ++static void hisi_femac_tx_sg_dma_unmap(struct hisi_femac_priv *priv, ++ struct sk_buff *skb, unsigned int pos) ++{ ++ struct tx_desc *desc_cur; ++ dma_addr_t addr; ++ u32 len; ++ int i; ++ ++ desc_cur = priv->tx_ring.desc + pos; ++ ++ addr = desc_cur->linear_addr; ++ len = desc_cur->linear_len; ++ dma_unmap_single(priv->dev, addr, len, DMA_TO_DEVICE); ++ ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { ++ addr = desc_cur->frags[i].addr; ++ len = desc_cur->frags[i].size; ++ dma_unmap_page(priv->dev, addr, len, DMA_TO_DEVICE); ++ } ++} ++ ++static void hisi_femac_tx_dma_unmap(struct hisi_femac_priv *priv, ++ struct sk_buff *skb, unsigned int pos) ++{ ++ if (!(skb_is_gso(skb) || skb_shinfo(skb)->nr_frags)) { ++ dma_addr_t dma_addr; ++ ++ dma_addr = priv->txq.dma_phys[pos]; ++ dma_unmap_single(priv->dev, dma_addr, skb->len, DMA_TO_DEVICE); ++ } else { ++ hisi_femac_tx_sg_dma_unmap(priv, skb, pos); ++ } ++} ++ ++static void hisi_femac_xmit_reclaim(struct net_device *dev) ++{ ++ struct sk_buff *skb; ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ struct hisi_femac_queue *txq = &priv->txq; ++ unsigned int bytes_compl = 0, pkts_compl = 0; ++ u32 val; ++ ++ netif_tx_lock(dev); ++ ++ val = readl(priv->port_base + ADDRQ_STAT) & TX_CNT_INUSE_MASK; ++ while (val < priv->tx_fifo_used_cnt) { ++ skb = txq->skb[txq->tail]; ++ if (unlikely(!skb)) { ++ netdev_err(dev, "xmitq_cnt_inuse=%d, tx_fifo_used=%d\n", ++ val, priv->tx_fifo_used_cnt); ++ break; ++ } ++ hisi_femac_tx_dma_unmap(priv, skb, txq->tail); ++ pkts_compl++; ++ bytes_compl += skb->len; ++ dev_kfree_skb_any(skb); ++ ++ priv->tx_fifo_used_cnt--; ++ ++ val = readl(priv->port_base + ADDRQ_STAT) & TX_CNT_INUSE_MASK; ++ txq->skb[txq->tail] = NULL; ++ txq->tail = (txq->tail + 1) % txq->num; ++ } ++ ++ netdev_completed_queue(dev, pkts_compl, bytes_compl); ++ ++ if (unlikely(netif_queue_stopped(dev)) && pkts_compl) ++ netif_wake_queue(dev); ++ ++ netif_tx_unlock(dev); ++} ++ ++static void hisi_femac_get_tso_err_info(struct hisi_femac_priv *priv) ++{ ++ unsigned int reg_addr, reg_tx_info, reg_tx_err; ++ unsigned int sg_index; ++ struct tx_desc *sg_desc; ++ int *sg_word; ++ int i; ++ ++ reg_addr = readl(priv->port_base + TSO_DBG_ADDR); ++ reg_tx_info = readl(priv->port_base + TSO_DBG_TX_INFO); ++ reg_tx_err = readl(priv->port_base + TSO_DBG_TX_ERR); ++ ++ WARN(1, "tx err=0x%x, tx_info=0x%x, addr=0x%x\n", ++ reg_tx_err, reg_tx_info, reg_addr); ++ ++ sg_index = (reg_addr - priv->tx_ring.dma_phys) / sizeof(struct tx_desc); ++ sg_desc = priv->tx_ring.desc + sg_index; ++ sg_word = (int *)sg_desc; ++ for (i = 0; i < sizeof(struct tx_desc) / sizeof(int); i++) ++ pr_err("%s,%d: sg_desc word[%d]=0x%x\n", ++ __func__, __LINE__, i, sg_word[i]); ++ ++ /* restart MAC to transmit next packet */ ++ hisi_femac_irq_disable(priv, INT_TX_ERR); ++ /* The following is recovery code, ++ * allow netcard transmit packet again. ++ * But now we disable it for error debug. ++ * ++ * readl(priv->port_base + TSO_DBG_STATE)); ++ * hisi_femac_irq_enable(priv, INT_TX_ERR); ++ */ ++} ++ ++static netdev_tx_t hisi_femac_net_xmit(struct sk_buff *skb, ++ struct net_device *dev); ++ ++static netdev_tx_t hisi_femac_sw_gso(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ struct sk_buff *segs, *curr_skb; ++ netdev_features_t features = dev->features; ++ ++ features &= ~(NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | ++ NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO); ++ segs = skb_gso_segment(skb, features); ++ if (IS_ERR_OR_NULL(segs)) ++ goto drop; ++ ++ do { ++ curr_skb = segs; ++ segs = segs->next; ++ curr_skb->next = NULL; ++ if (hisi_femac_net_xmit(curr_skb, dev)) { ++ dev_kfree_skb(curr_skb); ++ while (segs) { ++ curr_skb = segs; ++ segs = segs->next; ++ curr_skb->next = NULL; ++ dev_kfree_skb_any(curr_skb); ++ } ++ goto drop; ++ } ++ } while (segs); ++ ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++ ++drop: ++ dev_kfree_skb_any(skb); ++ dev->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++} ++ ++static void hisi_femac_do_udp_checksum(struct sk_buff *skb) ++{ ++ int offset; ++ __wsum csum; ++ __sum16 udp_csum; ++ ++ offset = skb_checksum_start_offset(skb); ++ WARN_ON(offset >= skb_headlen(skb)); ++ csum = skb_checksum(skb, offset, skb->len - offset, 0); ++ ++ offset += skb->csum_offset; ++ WARN_ON(offset + sizeof(__sum16) > skb_headlen(skb)); ++ ++ udp_csum = csum_fold(csum); ++ if (udp_csum == 0) ++ udp_csum = CSUM_MANGLED_0; ++ ++ *(__sum16 *)(skb->data + offset) = udp_csum; ++ ++ skb->ip_summed = CHECKSUM_NONE; ++} ++ ++static inline __be16 hisi_femac_get_l3_proto(struct sk_buff *skb) ++{ ++ __be16 l3_proto; ++ ++ l3_proto = skb->protocol; ++ if (skb->protocol == htons(ETH_P_8021Q)) ++ l3_proto = vlan_get_protocol(skb); ++ ++ return l3_proto; ++} ++ ++static inline bool hisi_femac_skb_is_ipv6(struct sk_buff *skb) ++{ ++ return (hisi_femac_get_l3_proto(skb) == htons(ETH_P_IPV6)); ++} ++ ++static int hisi_femac_check_hw_capability_for_ipv6(struct sk_buff *skb) ++{ ++ unsigned int l4_proto = IPPROTO_MAX; ++ ++ l4_proto = ipv6_hdr(skb)->nexthdr; ++ ++ if ((l4_proto != IPPROTO_TCP) && (l4_proto != IPPROTO_UDP)) { ++ /* when IPv6 next header is not tcp or udp, ++ * it means that IPv6 next header is extension header. ++ * Hardware can't deal with this case, ++ * so do checksumming by software or do GSO by software. ++ */ ++ if (skb_is_gso(skb)) ++ return -ENOTSUPP; ++ ++ if (skb->ip_summed == CHECKSUM_PARTIAL && ++ skb_checksum_help(skb)) ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int hisi_femac_check_hw_capability(struct sk_buff *skb) ++{ ++ /* if tcp_mtu_probe() use (2 * tp->mss_cache) as probe_size, ++ * the linear data length will be larger than 2048, ++ * the MAC can't handle it, so let the software do it. ++ */ ++ if (skb_is_gso(skb) && (skb_headlen(skb) > 2048)) ++ return -ENOTSUPP; ++ ++ if (hisi_femac_skb_is_ipv6(skb)) ++ return hisi_femac_check_hw_capability_for_ipv6(skb); ++ ++ return 0; ++} ++ ++static u32 hisi_femac_get_pkt_info(struct sk_buff *skb) ++{ ++ __be16 l3_proto; ++ unsigned int l4_proto = IPPROTO_MAX; ++ bool do_txcsum = false; ++ int max_data_len = skb->len - ETH_HLEN; ++ unsigned int max_mss = ETH_DATA_LEN; ++ u32 pkt_info = 0; ++ ++ if (skb->ip_summed == CHECKSUM_PARTIAL) ++ do_txcsum = true; ++ ++ l3_proto = skb->protocol; ++ if (skb->protocol == htons(ETH_P_8021Q)) { ++ l3_proto = vlan_get_protocol(skb); ++ max_data_len -= VLAN_HLEN; ++ pkt_info |= BIT_FLAG_VLAN; ++ } ++ ++ if (l3_proto == htons(ETH_P_IP)) { ++ struct iphdr *iph = ip_hdr(skb); ++ ++ if ((max_data_len >= GSO_MAX_SIZE) && ++ (ntohs(iph->tot_len) <= (iph->ihl << 2))) ++ iph->tot_len = htons(GSO_MAX_SIZE - 1); ++ ++ max_mss -= iph->ihl * WORD_TO_BYTE; ++ pkt_info |= (iph->ihl << BIT_OFFSET_IP_HEADER_LEN); ++ l4_proto = iph->protocol; ++ } else if (l3_proto == htons(ETH_P_IPV6)) { ++ max_mss -= IPV6_HDR_LEN * WORD_TO_BYTE; ++ pkt_info |= BIT_FLAG_IPV6; ++ pkt_info |= (IPV6_HDR_LEN << BIT_OFFSET_IP_HEADER_LEN); ++ l4_proto = ipv6_hdr(skb)->nexthdr; ++ } else { ++ do_txcsum = false; ++ } ++ ++ if (l4_proto == IPPROTO_TCP) { ++ max_mss -= tcp_hdr(skb)->doff * WORD_TO_BYTE; ++ pkt_info |= (tcp_hdr(skb)->doff << BIT_OFFSET_PROT_HEADER_LEN); ++ } else if (l4_proto == IPPROTO_UDP) { ++ if (l3_proto == htons(ETH_P_IPV6)) ++ max_mss -= sizeof(struct frag_hdr); ++ pkt_info |= (BIT_FLAG_UDP | ++ (UDP_HDR_LEN << BIT_OFFSET_PROT_HEADER_LEN)); ++ } else { ++ do_txcsum = false; ++ } ++ ++ /* Although netcard support UFO feature, it can't deal with ++ * UDP header checksum. ++ * So the driver will do UDP header checksum and netcard will just ++ * fragment the packet. ++ */ ++ if (do_txcsum && skb_is_gso(skb) && (l4_proto == IPPROTO_UDP)) { ++ hisi_femac_do_udp_checksum(skb); ++ do_txcsum = false; ++ } ++ ++ if (do_txcsum) ++ pkt_info |= BIT_FLAG_TXCSUM; ++ ++ if (skb_is_gso(skb)) ++ pkt_info |= (BIT_FLAG_SG | BIT_FLAG_TSO); ++ else if (skb_shinfo(skb)->nr_frags) ++ pkt_info |= BIT_FLAG_SG; ++ ++ pkt_info |= (skb_shinfo(skb)->nr_frags << BIT_OFFSET_NFRAGS_NUM); ++ pkt_info |= (skb_is_gso(skb) ? ++ ((skb_shinfo(skb)->gso_size > max_mss) ? max_mss : ++ skb_shinfo(skb)->gso_size) : (skb->len + ETH_FCS_LEN)); ++ ++ return pkt_info; ++} ++ ++static int hisi_femac_fill_sg_desc(struct hisi_femac_priv *priv, ++ struct sk_buff *skb, unsigned int pos) ++{ ++ struct tx_desc *desc_cur; ++ dma_addr_t addr; ++ int ret; ++ int i; ++ ++ desc_cur = priv->tx_ring.desc + pos; ++ ++ desc_cur->ipv6_id = ntohl(skb_shinfo(skb)->ip6_frag_id); ++ ++ desc_cur->total_len = skb->len; ++ addr = dma_map_single(priv->dev, skb->data, skb_headlen(skb), ++ DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(priv->dev, addr))) ++ return -EINVAL; ++ desc_cur->linear_addr = addr; ++ desc_cur->linear_len = skb_headlen(skb); ++ ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { ++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ++ int len = frag->size; ++ ++ addr = skb_frag_dma_map(priv->dev, frag, 0, len, DMA_TO_DEVICE); ++ ret = dma_mapping_error(priv->dev, addr); ++ if (unlikely(ret)) ++ return -EINVAL; ++ desc_cur->frags[i].addr = addr; ++ desc_cur->frags[i].size = len; ++ } ++ ++ return 0; ++} ++ ++static void hisi_femac_adjust_link(struct net_device *dev) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ struct phy_device *phy = dev->phydev; ++ u32 status = 0; ++ ++ if (phy->link) ++ status |= MAC_PORTSET_LINKED; ++ if (phy->duplex == DUPLEX_FULL) ++ status |= MAC_PORTSET_DUPLEX_FULL; ++ if (phy->speed == SPEED_100) ++ status |= MAC_PORTSET_SPEED_100M; ++ ++ if ((status != priv->link_status) && ++ ((status | priv->link_status) & MAC_PORTSET_LINKED)) { ++ writel(status, priv->port_base + MAC_PORTSET); ++ priv->link_status = status; ++ phy_print_status(phy); ++ ++ priv->tx_pause_en = phy->pause; ++ hisi_femac_set_flow_ctrl(priv); ++ } ++} ++ ++static void hisi_femac_rx_refill(struct hisi_femac_priv *priv) ++{ ++ struct hisi_femac_queue *rxq = &priv->rxq; ++ struct sk_buff *skb; ++ u32 pos; ++ u32 len = MAX_FRAME_SIZE; ++ dma_addr_t addr; ++ u32 alloc_rxbuf_align = 0; ++ int reserve_room = 0; ++ ++ pos = rxq->head; ++ while (readl(priv->port_base + ADDRQ_STAT) & BIT_RX_READY) { ++ if (!CIRC_SPACE(pos, rxq->tail, rxq->num)) ++ break; ++ if (unlikely(rxq->skb[pos])) { ++ netdev_err(priv->ndev, "err skb[%d]=%p\n", ++ pos, rxq->skb[pos]); ++ break; ++ } ++ len = MAX_FRAME_SIZE + RXBUF_ADDR_ALIGN_SIZE; ++ skb = netdev_alloc_skb_ip_align(priv->ndev, len); ++ if (unlikely(!skb)) ++ break; ++ ++ alloc_rxbuf_align = ((unsigned long)skb->data - NET_IP_ALIGN) & ++ (RXBUF_ADDR_ALIGN_SIZE - 1); ++ if (alloc_rxbuf_align) { ++ reserve_room = RXBUF_ADDR_ALIGN_SIZE - ++ alloc_rxbuf_align; ++ len -= reserve_room; ++ skb_reserve(skb, reserve_room); ++ } ++ ++ addr = dma_map_single(priv->dev, skb->data, len, ++ DMA_FROM_DEVICE); ++ if (dma_mapping_error(priv->dev, addr)) { ++ dev_kfree_skb_any(skb); ++ break; ++ } ++ rxq->dma_phys[pos] = addr; ++ rxq->skb[pos] = skb; ++ writel(addr, priv->port_base + IQ_ADDR); ++ pos = (pos + 1) % rxq->num; ++ } ++ rxq->head = pos; ++} ++ ++static u32 hisi_femac_rx(struct net_device *dev, int limit) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ struct hisi_femac_queue *rxq = &priv->rxq; ++ struct sk_buff *skb; ++ dma_addr_t addr; ++ u32 rx_pkt_info, pos, len, rx_pkts_num = 0; ++ int hdr_csum_done, hdr_csum_err; ++ int payload_csum_done, payload_csum_err; ++ ++ pos = rxq->tail; ++ while (readl(priv->glb_base + GLB_IRQ_RAW) & IRQ_INT_RX_RDY) { ++ rx_pkt_info = readl(priv->port_base + IQFRM_DES); ++ len = rx_pkt_info & RX_FRAME_LEN_MASK; ++ len -= ETH_FCS_LEN; ++ ++ /* tell hardware we will deal with this packet */ ++ writel(IRQ_INT_RX_RDY, priv->glb_base + GLB_IRQ_RAW); ++ ++ rx_pkts_num++; ++ ++ skb = rxq->skb[pos]; ++ if (unlikely(!skb)) { ++ netdev_err(dev, "rx skb NULL. pos=%d\n", pos); ++ break; ++ } ++ rxq->skb[pos] = NULL; ++ ++ addr = rxq->dma_phys[pos]; ++ dma_unmap_single(priv->dev, addr, MAX_FRAME_SIZE, ++ DMA_FROM_DEVICE); ++ skb_put(skb, len); ++ if (unlikely(skb->len > MAX_FRAME_SIZE)) { ++ netdev_err(dev, "rcv len err, len = %d\n", skb->len); ++ dev->stats.rx_errors++; ++ dev->stats.rx_length_errors++; ++ dev_kfree_skb_any(skb); ++ goto next; ++ } ++ ++ skb->ip_summed = CHECKSUM_NONE; ++ if (dev->features & NETIF_F_RXCSUM) { ++ hdr_csum_done = ++ (rx_pkt_info >> BITS_HEADER_DONE_OFFSET) & ++ BITS_HEADER_DONE_MASK; ++ payload_csum_done = ++ (rx_pkt_info >> BITS_PAYLOAD_DONE_OFFSET) & ++ BITS_PAYLOAD_DONE_MASK; ++ hdr_csum_err = ++ (rx_pkt_info >> BITS_HEADER_ERR_OFFSET) & ++ BITS_HEADER_ERR_MASK; ++ payload_csum_err = ++ (rx_pkt_info >> BITS_PAYLOAD_ERR_OFFSET) & ++ BITS_PAYLOAD_ERR_MASK; ++ ++ if (hdr_csum_done && payload_csum_done) { ++ if (unlikely(hdr_csum_err)) { ++ dev->stats.rx_errors++; ++ dev->stats.rx_crc_errors++; ++ dev_kfree_skb_any(skb); ++ goto next; ++ } else if (!payload_csum_err) { ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ } ++ } ++ } ++ ++ skb->protocol = eth_type_trans(skb, dev); ++ napi_gro_receive(&priv->napi, skb); ++ dev->stats.rx_packets++; ++ dev->stats.rx_bytes += len; ++next: ++ pos = (pos + 1) % rxq->num; ++ if (rx_pkts_num >= limit) ++ break; ++ } ++ rxq->tail = pos; ++ ++ hisi_femac_rx_refill(priv); ++ ++ return rx_pkts_num; ++} ++ ++static int hisi_femac_poll(struct napi_struct *napi, int budget) ++{ ++ struct hisi_femac_priv *priv = container_of(napi, ++ struct hisi_femac_priv, napi); ++ struct net_device *dev = priv->ndev; ++ int work_done = 0, task = budget; ++ u32 ints, num; ++ ++ do { ++ hisi_femac_xmit_reclaim(dev); ++ num = hisi_femac_rx(dev, task); ++ work_done += num; ++ task -= num; ++ if (work_done >= budget) ++ break; ++ ++ ints = readl(priv->glb_base + GLB_IRQ_RAW); ++ writel(ints & DEF_INT_MASK, ++ priv->glb_base + GLB_IRQ_RAW); ++ } while (ints & DEF_INT_MASK); ++ ++ if (work_done < budget) { ++ napi_complete(napi); ++ hisi_femac_irq_enable(priv, DEF_INT_MASK & ++ (~IRQ_INT_TX_PER_PACKET)); ++ } ++ ++ return work_done; ++} ++ ++static irqreturn_t hisi_femac_interrupt(int irq, void *dev_id) ++{ ++ u32 ints; ++ struct net_device *dev = (struct net_device *)dev_id; ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ ++ ints = readl(priv->glb_base + GLB_IRQ_RAW); ++ ++ if (likely(ints & DEF_INT_MASK)) { ++ writel(ints & DEF_INT_MASK, ++ priv->glb_base + GLB_IRQ_RAW); ++ hisi_femac_irq_disable(priv, DEF_INT_MASK); ++ napi_schedule(&priv->napi); ++ } ++ ++ if (HAS_TSO_CAP(priv->hw_cap) && ++ unlikely(ints & INT_TX_ERR)) ++ hisi_femac_get_tso_err_info(priv); ++ ++ return IRQ_HANDLED; ++} ++ ++static int hisi_femac_init_tx_descriptor_ring(struct hisi_femac_priv *priv) ++{ ++ priv->tx_ring.desc = (struct tx_desc *)dma_zalloc_coherent(priv->dev, ++ TXQ_NUM * sizeof(struct tx_desc), ++ &priv->tx_ring.dma_phys, ++ GFP_KERNEL); ++ if (!priv->tx_ring.desc) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++static void hisi_femac_destroy_tx_descriptor_ring(struct hisi_femac_priv *priv) ++{ ++ if (priv->tx_ring.desc) ++ dma_free_coherent(priv->dev, ++ TXQ_NUM * sizeof(struct tx_desc), ++ priv->tx_ring.desc, priv->tx_ring.dma_phys); ++ priv->tx_ring.desc = NULL; ++} ++ ++static int hisi_femac_init_queue(struct device *dev, ++ struct hisi_femac_queue *queue, ++ unsigned int num) ++{ ++ queue->skb = devm_kcalloc(dev, num, sizeof(struct sk_buff *), ++ GFP_KERNEL); ++ if (!queue->skb) ++ return -ENOMEM; ++ ++ queue->dma_phys = devm_kcalloc(dev, num, sizeof(dma_addr_t), ++ GFP_KERNEL); ++ if (!queue->dma_phys) ++ return -ENOMEM; ++ ++ queue->num = num; ++ queue->head = 0; ++ queue->tail = 0; ++ ++ return 0; ++} ++ ++static int hisi_femac_init_tx_and_rx_queues(struct hisi_femac_priv *priv) ++{ ++ int ret; ++ ++ ret = hisi_femac_init_queue(priv->dev, &priv->txq, TXQ_NUM); ++ if (ret) ++ return ret; ++ ++ ret = hisi_femac_init_queue(priv->dev, &priv->rxq, RXQ_NUM); ++ if (ret) ++ return ret; ++ ++ priv->tx_fifo_used_cnt = 0; ++ ++ return 0; ++} ++ ++static void hisi_femac_free_skb_rings(struct hisi_femac_priv *priv) ++{ ++ struct hisi_femac_queue *txq = &priv->txq; ++ struct hisi_femac_queue *rxq = &priv->rxq; ++ struct sk_buff *skb; ++ dma_addr_t dma_addr; ++ u32 pos; ++ ++ pos = rxq->tail; ++ while (pos != rxq->head) { ++ skb = rxq->skb[pos]; ++ if (unlikely(!skb)) { ++ netdev_err(priv->ndev, "NULL rx skb. pos=%d, head=%d\n", ++ pos, rxq->head); ++ continue; ++ } ++ ++ dma_addr = rxq->dma_phys[pos]; ++ dma_unmap_single(priv->dev, dma_addr, MAX_FRAME_SIZE, ++ DMA_FROM_DEVICE); ++ ++ dev_kfree_skb_any(skb); ++ rxq->skb[pos] = NULL; ++ pos = (pos + 1) % rxq->num; ++ } ++ rxq->tail = pos; ++ ++ pos = txq->tail; ++ while (pos != txq->head) { ++ skb = txq->skb[pos]; ++ if (unlikely(!skb)) { ++ netdev_err(priv->ndev, "NULL tx skb. pos=%d, head=%d\n", ++ pos, txq->head); ++ continue; ++ } ++ hisi_femac_tx_dma_unmap(priv, skb, pos); ++ dev_kfree_skb_any(skb); ++ txq->skb[pos] = NULL; ++ pos = (pos + 1) % txq->num; ++ } ++ txq->tail = pos; ++ priv->tx_fifo_used_cnt = 0; ++} ++ ++static int hisi_femac_set_hw_mac_addr(struct hisi_femac_priv *priv, ++ unsigned char *mac) ++{ ++ u32 reg; ++ ++ reg = mac[1] | (mac[0] << 8); ++ writel(reg, priv->glb_base + GLB_HOSTMAC_H16); ++ ++ reg = mac[5] | (mac[4] << 8) | (mac[3] << 16) | (mac[2] << 24); ++ writel(reg, priv->glb_base + GLB_HOSTMAC_L32); ++ ++ return 0; ++} ++ ++static int hisi_femac_port_reset(struct hisi_femac_priv *priv) ++{ ++ u32 val; ++ ++ val = readl(priv->glb_base + GLB_SOFT_RESET); ++ val |= SOFT_RESET_ALL; ++ writel(val, priv->glb_base + GLB_SOFT_RESET); ++ ++ usleep_range(500, 800); ++ ++ val &= ~SOFT_RESET_ALL; ++ writel(val, priv->glb_base + GLB_SOFT_RESET); ++ ++ return 0; ++} ++ ++static int hisi_femac_net_open(struct net_device *dev) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ ++ hisi_femac_set_hw_mac_addr(priv, dev->dev_addr); ++ /* clear interrupts will drop the first packet MAC have received, ++ * so do it before refill the rx free skbs. ++ */ ++ writel(IRQ_ENA_PORT0_MASK, priv->glb_base + GLB_IRQ_RAW); ++ hisi_femac_rx_refill(priv); ++ ++ netif_carrier_off(dev); ++ netdev_reset_queue(dev); ++ netif_start_queue(dev); ++ napi_enable(&priv->napi); ++ ++ priv->link_status = 0; ++ if (dev->phydev) ++ phy_start(dev->phydev); ++ ++ hisi_femac_irq_enable(priv, IRQ_ENA_ALL | IRQ_ENA_PORT0 | DEF_INT_MASK); ++ if (HAS_TSO_CAP(priv->hw_cap)) ++ hisi_femac_irq_enable(priv, INT_TX_ERR); ++ ++ return 0; ++} ++ ++static void hisi_femac_port_init(struct hisi_femac_priv *priv); ++ ++static int hisi_femac_net_close(struct net_device *dev) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ ++ hisi_femac_irq_disable(priv, IRQ_ENA_PORT0); ++ ++ if (dev->phydev) ++ phy_stop(dev->phydev); ++ ++ netif_stop_queue(dev); ++ napi_disable(&priv->napi); ++ ++ /* reset MAC port first before free skb rings ++ * to prevent potential risk of use-after-free. ++ */ ++ hisi_femac_port_reset(priv); ++ hisi_femac_port_init(priv); ++ ++ priv->tx_pause_en = false; ++ hisi_femac_set_flow_ctrl(priv); ++ hisi_femac_free_skb_rings(priv); ++ ++ return 0; ++} ++ ++static netdev_tx_t hisi_femac_net_xmit(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ struct hisi_femac_queue *txq = &priv->txq; ++ dma_addr_t addr; ++ int ret; ++ u32 pkt_info; ++ u32 val; ++ ++ val = readl(priv->port_base + ADDRQ_STAT); ++ val &= BIT_TX_READY; ++ if (!val) { ++ hisi_femac_irq_enable(priv, IRQ_INT_TX_PER_PACKET); ++ dev->stats.tx_dropped++; ++ dev->stats.tx_fifo_errors++; ++ netif_stop_queue(dev); ++ return NETDEV_TX_BUSY; ++ } ++ ++ if (unlikely(!CIRC_SPACE(txq->head, txq->tail, ++ txq->num))) { ++ hisi_femac_irq_enable(priv, IRQ_INT_TX_PER_PACKET); ++ dev->stats.tx_dropped++; ++ dev->stats.tx_fifo_errors++; ++ netif_stop_queue(dev); ++ return NETDEV_TX_BUSY; ++ } ++ ++ ret = hisi_femac_check_hw_capability(skb); ++ if (unlikely(ret)) { ++ if (ret == -ENOTSUPP) ++ return hisi_femac_sw_gso(skb, dev); ++ ++ dev_kfree_skb_any(skb); ++ dev->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++ } ++ ++ pkt_info = hisi_femac_get_pkt_info(skb); ++ ++ if (!(skb_is_gso(skb) || skb_shinfo(skb)->nr_frags)) { ++ addr = dma_map_single(priv->dev, skb->data, ++ skb->len, DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(priv->dev, addr))) { ++ dev_kfree_skb_any(skb); ++ dev->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++ } ++ } else { ++ ret = hisi_femac_fill_sg_desc(priv, skb, txq->head); ++ if (unlikely(ret)) { ++ dev_kfree_skb_any(skb); ++ dev->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++ } ++ ++ addr = priv->tx_ring.dma_phys + ++ txq->head * sizeof(struct tx_desc); ++ ++ /* Ensure desc info writen to memory before config hardware */ ++ wmb(); ++ } ++ txq->dma_phys[txq->head] = addr; ++ ++ txq->skb[txq->head] = skb; ++ txq->head = (txq->head + 1) % txq->num; ++ ++ writel(addr, priv->port_base + EQ_ADDR); ++ writel(pkt_info, priv->port_base + EQFRM_LEN); ++ ++ priv->tx_fifo_used_cnt++; ++ ++ dev->stats.tx_packets++; ++ dev->stats.tx_bytes += skb->len; ++ netdev_sent_queue(dev, skb->len); ++ ++ return NETDEV_TX_OK; ++} ++ ++static int hisi_femac_set_mac_address(struct net_device *dev, void *p) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ struct sockaddr *skaddr = p; ++ ++ if (!is_valid_ether_addr(skaddr->sa_data)) ++ return -EADDRNOTAVAIL; ++ ++ memcpy(dev->dev_addr, skaddr->sa_data, dev->addr_len); ++ dev->addr_assign_type &= ~NET_ADDR_RANDOM; ++ ++ hisi_femac_set_hw_mac_addr(priv, dev->dev_addr); ++ ++ return 0; ++} ++ ++static void hisi_femac_enable_hw_addr_filter(struct hisi_femac_priv *priv, ++ unsigned int reg_n, bool enable) ++{ ++ u32 val; ++ ++ val = readl(priv->glb_base + GLB_MAC_H16(reg_n)); ++ if (enable) ++ val |= BIT_MACFLT_ENA; ++ else ++ val &= ~BIT_MACFLT_ENA; ++ writel(val, priv->glb_base + GLB_MAC_H16(reg_n)); ++} ++ ++static void hisi_femac_set_hw_addr_filter(struct hisi_femac_priv *priv, ++ unsigned char *addr, ++ unsigned int reg_n) ++{ ++ unsigned int high, low; ++ u32 val; ++ ++ high = GLB_MAC_H16(reg_n); ++ low = GLB_MAC_L32(reg_n); ++ ++ val = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | addr[5]; ++ writel(val, priv->glb_base + low); ++ ++ val = readl(priv->glb_base + high); ++ val &= ~MACFLT_HI16_MASK; ++ val |= ((addr[0] << 8) | addr[1]); ++ val |= (BIT_MACFLT_ENA | BIT_MACFLT_FW2CPU); ++ writel(val, priv->glb_base + high); ++} ++ ++static void hisi_femac_set_promisc_mode(struct hisi_femac_priv *priv, ++ bool promisc_mode) ++{ ++ u32 val; ++ ++ val = readl(priv->glb_base + GLB_FWCTRL); ++ if (promisc_mode) ++ val |= FWCTRL_FWALL2CPU; ++ else ++ val &= ~FWCTRL_FWALL2CPU; ++ writel(val, priv->glb_base + GLB_FWCTRL); ++} ++ ++/* Handle multiple multicast addresses (perfect filtering)*/ ++static void hisi_femac_set_mc_addr_filter(struct hisi_femac_priv *priv) ++{ ++ struct net_device *dev = priv->ndev; ++ u32 val; ++ ++ val = readl(priv->glb_base + GLB_MACTCTRL); ++ if ((netdev_mc_count(dev) > MAX_MULTICAST_ADDRESSES) || ++ (dev->flags & IFF_ALLMULTI)) { ++ val |= MACTCTRL_MULTI2CPU; ++ } else { ++ int reg = MAX_UNICAST_ADDRESSES; ++ int i; ++ struct netdev_hw_addr *ha; ++ ++ for (i = reg; i < MAX_MAC_FILTER_NUM; i++) ++ hisi_femac_enable_hw_addr_filter(priv, i, false); ++ ++ netdev_for_each_mc_addr(ha, dev) { ++ hisi_femac_set_hw_addr_filter(priv, ha->addr, reg); ++ reg++; ++ } ++ val &= ~MACTCTRL_MULTI2CPU; ++ } ++ writel(val, priv->glb_base + GLB_MACTCTRL); ++} ++ ++/* Handle multiple unicast addresses (perfect filtering)*/ ++static void hisi_femac_set_uc_addr_filter(struct hisi_femac_priv *priv) ++{ ++ struct net_device *dev = priv->ndev; ++ u32 val; ++ ++ val = readl(priv->glb_base + GLB_MACTCTRL); ++ if (netdev_uc_count(dev) > MAX_UNICAST_ADDRESSES) { ++ val |= MACTCTRL_UNI2CPU; ++ } else { ++ int reg = 0; ++ int i; ++ struct netdev_hw_addr *ha; ++ ++ for (i = reg; i < MAX_UNICAST_ADDRESSES; i++) ++ hisi_femac_enable_hw_addr_filter(priv, i, false); ++ ++ netdev_for_each_uc_addr(ha, dev) { ++ hisi_femac_set_hw_addr_filter(priv, ha->addr, reg); ++ reg++; ++ } ++ val &= ~MACTCTRL_UNI2CPU; ++ } ++ writel(val, priv->glb_base + GLB_MACTCTRL); ++} ++ ++static void hisi_femac_net_set_rx_mode(struct net_device *dev) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ ++ if (dev->flags & IFF_PROMISC) { ++ hisi_femac_set_promisc_mode(priv, true); ++ } else { ++ hisi_femac_set_promisc_mode(priv, false); ++ hisi_femac_set_mc_addr_filter(priv); ++ hisi_femac_set_uc_addr_filter(priv); ++ } ++} ++ ++static int hisi_femac_net_ioctl(struct net_device *dev, ++ struct ifreq *ifreq, int cmd) ++{ ++ if (!netif_running(dev)) ++ return -EINVAL; ++ ++ if (!dev->phydev) ++ return -EINVAL; ++ ++ return phy_mii_ioctl(dev->phydev, ifreq, cmd); ++} ++ ++static void hisi_femac_get_pauseparam(struct net_device *dev, ++ struct ethtool_pauseparam *pause) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ ++ pause->autoneg = dev->phydev->autoneg; ++ pause->rx_pause = 1; ++ if (priv->tx_pause_en) ++ pause->tx_pause = 1; ++} ++ ++static int hisi_femac_set_pauseparam(struct net_device *dev, ++ struct ethtool_pauseparam *pause) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ struct phy_device *phy = dev->phydev; ++ int ret = 0; ++ ++ if (pause->rx_pause == 0) ++ return -EINVAL; ++ ++ if (pause->tx_pause != priv->tx_pause_en) { ++ priv->tx_pause_en = pause->tx_pause; ++ hisi_femac_set_flow_ctrl(priv); ++ } ++ ++ if (phy->autoneg) { ++ if (netif_running(dev)) { ++ struct ethtool_cmd cmd; ++ /* auto-negotiation automatically restarted */ ++ cmd.cmd = ETHTOOL_NWAY_RST; ++ cmd.supported = phy->supported; ++ cmd.advertising = phy->advertising; ++ cmd.autoneg = phy->autoneg; ++ cmd.speed = phy->speed; ++ cmd.duplex = phy->duplex; ++ cmd.phy_address = phy->mdio.addr; ++ ret = phy_ethtool_sset(phy, &cmd); ++ } ++ } ++ ++ return ret; ++} ++ ++static void hisi_femac_enable_rxcsum_drop(struct hisi_femac_priv *priv, ++ bool drop) ++{ ++ unsigned int val; ++ ++ val = readl(priv->port_base + RX_COE_CTRL); ++ val &= ~COE_ERR_DROP; ++ if (drop) ++ val |= (BIT_COE_IPHDR_DROP | BIT_COE_IPV6_UDP_ZERO_DROP); ++ writel(val, priv->port_base + RX_COE_CTRL); ++} ++ ++static int hisi_femac_set_features(struct net_device *dev, ++ netdev_features_t features) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ netdev_features_t changed = dev->features ^ features; ++ ++ if (changed & NETIF_F_RXCSUM) { ++ if (features & NETIF_F_RXCSUM) ++ hisi_femac_enable_rxcsum_drop(priv, true); ++ else ++ hisi_femac_enable_rxcsum_drop(priv, false); ++ } ++ ++ return 0; ++} ++ ++static const struct ethtool_ops hisi_femac_ethtools_ops = { ++ .get_link = ethtool_op_get_link, ++ .get_link_ksettings = phy_ethtool_get_link_ksettings, ++ .set_link_ksettings = phy_ethtool_set_link_ksettings, ++ .get_pauseparam = hisi_femac_get_pauseparam, ++ .set_pauseparam = hisi_femac_set_pauseparam, ++}; ++ ++static const struct net_device_ops hisi_femac_netdev_ops = { ++ .ndo_open = hisi_femac_net_open, ++ .ndo_stop = hisi_femac_net_close, ++ .ndo_start_xmit = hisi_femac_net_xmit, ++ .ndo_do_ioctl = hisi_femac_net_ioctl, ++ .ndo_set_mac_address = hisi_femac_set_mac_address, ++ .ndo_set_rx_mode = hisi_femac_net_set_rx_mode, ++ .ndo_change_mtu = eth_change_mtu, ++ .ndo_set_features = hisi_femac_set_features, ++}; ++ ++static void hisi_femac_verify_flow_ctrl_args(struct hisi_femac_priv *priv) ++{ ++ if (priv->tx_pause_active_thresh < FC_ACTIVE_MIN || ++ priv->tx_pause_active_thresh > FC_ACTIVE_MAX) ++ priv->tx_pause_active_thresh = FC_ACTIVE_DEFAULT; ++ ++ if (priv->tx_pause_deactive_thresh < FC_DEACTIVE_MIN || ++ priv->tx_pause_deactive_thresh > FC_DEACTIVE_MAX) ++ priv->tx_pause_deactive_thresh = FC_DEACTIVE_DEFAULT; ++ ++ if (priv->tx_pause_active_thresh >= priv->tx_pause_deactive_thresh) { ++ priv->tx_pause_active_thresh = FC_ACTIVE_DEFAULT; ++ priv->tx_pause_deactive_thresh = FC_DEACTIVE_DEFAULT; ++ } ++} ++ ++static void hisi_femac_core_reset(struct hisi_femac_priv *priv) ++{ ++ reset_control_assert(priv->mac_rst); ++ reset_control_deassert(priv->mac_rst); ++} ++ ++static void hisi_femac_sleep_us(u32 time_us) ++{ ++ u32 time_ms; ++ ++ if (!time_us) ++ return; ++ ++ time_ms = DIV_ROUND_UP(time_us, 1000); ++ if (time_ms < 20) ++ usleep_range(time_us, time_us + 500); ++ else ++ msleep(time_ms); ++} ++ ++static void hisi_femac_phy_reset(struct hisi_femac_priv *priv) ++{ ++ /* To make sure PHY hardware reset success, ++ * we must keep PHY in deassert state first and ++ * then complete the hardware reset operation ++ */ ++ reset_control_deassert(priv->phy_rst); ++ hisi_femac_sleep_us(priv->phy_reset_delays[PRE_DELAY]); ++ ++ reset_control_assert(priv->phy_rst); ++ /* delay some time to ensure reset ok, ++ * this depends on PHY hardware feature ++ */ ++ hisi_femac_sleep_us(priv->phy_reset_delays[PULSE]); ++ reset_control_deassert(priv->phy_rst); ++ /* delay some time to ensure later MDIO access */ ++ hisi_femac_sleep_us(priv->phy_reset_delays[POST_DELAY]); ++} ++ ++static void hisi_femac_port_init(struct hisi_femac_priv *priv) ++{ ++ u32 val; ++ ++ /* MAC gets link status info and phy mode by software config */ ++ val = MAC_PORTSEL_STAT_CPU; ++ if (priv->ndev->phydev->interface == PHY_INTERFACE_MODE_RMII) ++ val |= MAC_PORTSEL_RMII; ++ writel(val, priv->port_base + MAC_PORTSEL); ++ ++ /*clear all interrupt status */ ++ writel(IRQ_ENA_PORT0_MASK, priv->glb_base + GLB_IRQ_RAW); ++ hisi_femac_irq_disable(priv, IRQ_ENA_PORT0_MASK | IRQ_ENA_PORT0); ++ ++ if (HAS_TSO_CAP(priv->hw_cap)) { ++ /* enable TSO debug for error handle */ ++ val = readl(priv->port_base + TSO_DBG_EN); ++ val |= BITS_TSO_DBG_EN; ++ writel(val, priv->port_base + TSO_DBG_EN); ++ } ++ ++ val = readl(priv->glb_base + GLB_FWCTRL); ++ val &= ~(FWCTRL_VLAN_ENABLE | FWCTRL_FWALL2CPU); ++ val |= FWCTRL_FW2CPU_ENA; ++ writel(val, priv->glb_base + GLB_FWCTRL); ++ ++ val = readl(priv->glb_base + GLB_MACTCTRL); ++ val |= (MACTCTRL_BROAD2CPU | MACTCTRL_MACT_ENA); ++ writel(val, priv->glb_base + GLB_MACTCTRL); ++ ++ val = readl(priv->port_base + MAC_SET); ++ val &= ~MAX_FRAME_SIZE_MASK; ++ val |= MAX_FRAME_SIZE; ++ writel(val, priv->port_base + MAC_SET); ++ ++ val = RX_COALESCED_TIMER | ++ (RX_COALESCED_FRAMES << RX_COALESCED_FRAME_OFFSET); ++ writel(val, priv->port_base + RX_COALESCE_SET); ++ ++ val = (HW_RX_FIFO_DEPTH << RX_DEPTH_OFFSET) | HW_TX_FIFO_DEPTH; ++ writel(val, priv->port_base + QLEN_SET); ++ ++ hisi_femac_set_flow_ctrl(priv); ++} ++ ++static int hisi_femac_drv_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *node = dev->of_node; ++ struct resource *res; ++ struct net_device *ndev; ++ struct hisi_femac_priv *priv; ++ struct phy_device *phy; ++ const char *mac_addr; ++ int ret; ++ ++ ndev = alloc_etherdev(sizeof(*priv)); ++ if (!ndev) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, ndev); ++ SET_NETDEV_DEV(ndev, &pdev->dev); ++ ++ priv = netdev_priv(ndev); ++ priv->dev = dev; ++ priv->ndev = ndev; ++ ++ if (of_device_is_compatible(node, "hisilicon,hisi-femac-v2")) ++ priv->hw_cap |= HW_CAP_TSO | HW_CAP_RXCSUM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ priv->port_base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(priv->port_base)) { ++ ret = PTR_ERR(priv->port_base); ++ goto out_free_netdev; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ priv->glb_base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(priv->glb_base)) { ++ ret = PTR_ERR(priv->glb_base); ++ goto out_free_netdev; ++ } ++ ++ priv->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(priv->clk)) { ++ dev_err(dev, "failed to get clk\n"); ++ ret = -ENODEV; ++ goto out_free_netdev; ++ } ++ ++ ret = clk_prepare_enable(priv->clk); ++ if (ret) { ++ dev_err(dev, "failed to enable clk %d\n", ret); ++ goto out_free_netdev; ++ } ++ ++ priv->mac_rst = devm_reset_control_get(dev, "mac"); ++ if (IS_ERR(priv->mac_rst)) { ++ ret = PTR_ERR(priv->mac_rst); ++ goto out_disable_clk; ++ } ++ hisi_femac_core_reset(priv); ++ ++ priv->phy_rst = devm_reset_control_get(dev, "phy"); ++ if (IS_ERR(priv->phy_rst)) { ++ priv->phy_rst = NULL; ++ } else { ++ ret = of_property_read_u32_array(node, ++ PHY_RESET_DELAYS_PROPERTY, ++ priv->phy_reset_delays, ++ DELAYS_NUM); ++ if (ret) ++ goto out_disable_clk; ++ hisi_femac_phy_reset(priv); ++ } ++ ++ phy_register_fixups(); ++ ++ phy = of_phy_get_and_connect(ndev, node, hisi_femac_adjust_link); ++ if (!phy) { ++ dev_err(dev, "connect to PHY failed!\n"); ++ ret = -ENODEV; ++ goto out_disable_clk; ++ } ++ ++ phy->advertising |= ADVERTISED_Pause; ++ phy->supported |= ADVERTISED_Pause; ++ ++ phy->advertising &= ~(ADVERTISED_1000baseT_Full | ++ ADVERTISED_1000baseT_Half); ++ ++ phy_attached_print(phy, "phy_id=0x%.8lx, phy_mode=%s\n", ++ (unsigned long)phy->phy_id, ++ phy_modes(phy->interface)); ++ ++ mac_addr = of_get_mac_address(node); ++ if (mac_addr) ++ ether_addr_copy(ndev->dev_addr, mac_addr); ++ if (!is_valid_ether_addr(ndev->dev_addr)) { ++ eth_hw_addr_random(ndev); ++ dev_warn(dev, "using random MAC address %pM\n", ++ ndev->dev_addr); ++ } ++ ++ ndev->watchdog_timeo = 6 * HZ; ++ ndev->priv_flags |= IFF_UNICAST_FLT; ++ ndev->netdev_ops = &hisi_femac_netdev_ops; ++ ndev->ethtool_ops = &hisi_femac_ethtools_ops; ++ netif_napi_add(ndev, &priv->napi, hisi_femac_poll, FEMAC_POLL_WEIGHT); ++ ++ if (HAS_TSO_CAP(priv->hw_cap)) ++ ndev->hw_features |= NETIF_F_SG | ++ NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | ++ NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO; ++ ++ if (HAS_RXCSUM_CAP(priv->hw_cap)) ++ ndev->hw_features |= NETIF_F_RXCSUM; ++ ndev->features |= ndev->hw_features; ++ ndev->vlan_features |= ndev->features; ++ ++ device_set_wakeup_capable(priv->dev, true); ++ device_set_wakeup_enable(priv->dev, true); ++ ++ priv->tx_pause_en = true; ++ priv->tx_pause_active_thresh = TX_FLOW_CTRL_ACTIVE_THRESHOLD; ++ priv->tx_pause_deactive_thresh = TX_FLOW_CTRL_DEACTIVE_THRESHOLD; ++ ++ hisi_femac_verify_flow_ctrl_args(priv); ++ ++ hisi_femac_port_init(priv); ++ ++ if (HAS_RXCSUM_CAP(priv->hw_cap)) ++ hisi_femac_enable_rxcsum_drop(priv, true); ++ ++ ret = hisi_femac_init_tx_and_rx_queues(priv); ++ if (ret) ++ goto out_disconnect_phy; ++ ++ if (HAS_TSO_CAP(priv->hw_cap)) { ++ ret = hisi_femac_init_tx_descriptor_ring(priv); ++ if (ret) ++ goto out_disconnect_phy; ++ } ++ ++ ndev->irq = platform_get_irq(pdev, 0); ++ if (ndev->irq <= 0) { ++ dev_err(dev, "No irq resource\n"); ++ ret = -ENODEV; ++ goto out_destroy_descriptor; ++ } ++ ++ ret = devm_request_irq(dev, ndev->irq, hisi_femac_interrupt, ++ IRQF_SHARED, pdev->name, ndev); ++ if (ret) { ++ dev_err(dev, "devm_request_irq %d failed!\n", ndev->irq); ++ goto out_destroy_descriptor; ++ } ++ ++ ret = register_netdev(ndev); ++ if (ret) { ++ dev_err(dev, "register_netdev failed!\n"); ++ goto out_destroy_descriptor; ++ } ++ ++ return ret; ++ ++out_destroy_descriptor: ++ if (HAS_TSO_CAP(priv->hw_cap)) ++ hisi_femac_destroy_tx_descriptor_ring(priv); ++out_disconnect_phy: ++ netif_napi_del(&priv->napi); ++ phy_disconnect(phy); ++out_disable_clk: ++ clk_disable_unprepare(priv->clk); ++out_free_netdev: ++ free_netdev(ndev); ++ ++ return ret; ++} ++ ++static int hisi_femac_drv_remove(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct hisi_femac_priv *priv = netdev_priv(ndev); ++ ++ netif_napi_del(&priv->napi); ++ unregister_netdev(ndev); ++ if (HAS_TSO_CAP(priv->hw_cap)) ++ hisi_femac_destroy_tx_descriptor_ring(priv); ++ ++ phy_disconnect(ndev->phydev); ++ clk_disable_unprepare(priv->clk); ++ free_netdev(ndev); ++ ++ phy_unregister_fixups(); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++static int hisi_femac_drv_suspend(struct platform_device *pdev, ++ pm_message_t state) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct hisi_femac_priv *priv = netdev_priv(ndev); ++ ++ disable_irq(ndev->irq); ++ if (netif_running(ndev)) { ++ hisi_femac_net_close(ndev); ++ netif_device_detach(ndev); ++ } ++ ++ clk_disable_unprepare(priv->clk); ++ ++ return 0; ++} ++ ++static int hisi_femac_drv_resume(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct hisi_femac_priv *priv = netdev_priv(ndev); ++ ++ clk_prepare_enable(priv->clk); ++ if (priv->phy_rst) ++ hisi_femac_phy_reset(priv); ++ ++ if (netif_running(ndev)) { ++ hisi_femac_port_init(priv); ++ hisi_femac_net_open(ndev); ++ netif_device_attach(ndev); ++ } ++ enable_irq(ndev->irq); ++ ++ return 0; ++} ++#endif ++ ++static const struct of_device_id hisi_femac_match[] = { ++ {.compatible = "hisilicon,hisi-femac-v1",}, ++ {.compatible = "hisilicon,hisi-femac-v2",}, ++ {.compatible = "hisilicon,hi3516cv300-femac",}, ++ {.compatible = "hisilicon,hi3536dv100-femac",}, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, hisi_femac_match); ++ ++static struct platform_driver hisi_femac_driver = { ++ .driver = { ++ .name = "hisi-femac", ++ .of_match_table = hisi_femac_match, ++ }, ++ .probe = hisi_femac_drv_probe, ++ .remove = hisi_femac_drv_remove, ++#ifdef CONFIG_PM ++ .suspend = hisi_femac_drv_suspend, ++ .resume = hisi_femac_drv_resume, ++#endif ++}; ++ ++module_platform_driver(hisi_femac_driver); ++ ++MODULE_DESCRIPTION("Hisilicon Fast Ethernet MAC driver"); ++MODULE_AUTHOR("Dongpo Li "); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:hisi-femac"); +diff --git a/drivers/net/ethernet/hisilicon/hisi-femac/phy_fix.c b/drivers/net/ethernet/hisilicon/hisi-femac/phy_fix.c +new file mode 100644 +index 0000000..6a6e246 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hisi-femac/phy_fix.c +@@ -0,0 +1,58 @@ ++#include ++#include "phy_fix.h" ++ ++static const u32 phy_v272_fix_param[] = { ++#include "festa_v272_2723.h" ++}; ++ ++static int phy_expanded_write_bulk(struct phy_device *phy_dev, ++ const u32 reg_and_val[], int count) ++{ ++ int i, v, ret = 0; ++ u32 reg_addr; ++ u16 val; ++ ++ v = phy_read(phy_dev, MII_BMCR); ++ v |= BMCR_PDOWN; ++ phy_write(phy_dev, MII_BMCR, v); ++ ++ for (i = 0; i < (2 * count); i += 2) { ++ reg_addr = reg_and_val[i]; ++ val = (u16)reg_and_val[i + 1]; ++ phy_write(phy_dev, MII_EXPMA, reg_addr); ++ ret = phy_write(phy_dev, MII_EXPMD, val); ++ } ++ ++ v = phy_read(phy_dev, MII_BMCR); ++ v &= (~BMCR_PDOWN); ++ phy_write(phy_dev, MII_BMCR, v); ++ ++ return ret; ++} ++ ++static int hisilicon_fephy_v272_fix(struct phy_device *phy_dev) ++{ ++ int count; ++ ++ count = ARRAY_SIZE(phy_v272_fix_param); ++ if (count % 2) ++ pr_warn("internal FEPHY fix register count is not right.\n"); ++ count /= 2; ++ ++ phy_expanded_write_bulk(phy_dev, phy_v272_fix_param, count); ++ ++ return 0; ++} ++ ++void phy_register_fixups(void) ++{ ++ phy_register_fixup_for_uid(HISILICON_PHY_ID_FESTAV272, ++ HISILICON_PHY_MASK, ++ hisilicon_fephy_v272_fix); ++} ++ ++void phy_unregister_fixups(void) ++{ ++ phy_unregister_fixup_for_uid(HISILICON_PHY_ID_FESTAV272, ++ HISILICON_PHY_MASK); ++} +diff --git a/drivers/net/ethernet/hisilicon/hisi-femac/phy_fix.h b/drivers/net/ethernet/hisilicon/hisi-femac/phy_fix.h +new file mode 100644 +index 0000000..1e3d59e +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hisi-femac/phy_fix.h +@@ -0,0 +1,8 @@ ++#define HISILICON_PHY_ID_FESTAV272 0x20669901 ++#define HISILICON_PHY_MASK 0xfffffff0 ++ ++#define MII_EXPMD 0x1d ++#define MII_EXPMA 0x1e ++ ++void phy_register_fixups(void); ++void phy_unregister_fixups(void); +diff --git a/drivers/net/ethernet/hisilicon/hisi_femac.c b/drivers/net/ethernet/hisilicon/hisi_femac.c +deleted file mode 100644 +index ced1859..0000000 +--- a/drivers/net/ethernet/hisilicon/hisi_femac.c ++++ /dev/null +@@ -1,1007 +0,0 @@ +-/* +- * Hisilicon Fast Ethernet MAC Driver +- * +- * Copyright (c) 2016 HiSilicon Technologies 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. +- * +- * 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, see . +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-/* MAC control register list */ +-#define MAC_PORTSEL 0x0200 +-#define MAC_PORTSEL_STAT_CPU BIT(0) +-#define MAC_PORTSEL_RMII BIT(1) +-#define MAC_PORTSET 0x0208 +-#define MAC_PORTSET_DUPLEX_FULL BIT(0) +-#define MAC_PORTSET_LINKED BIT(1) +-#define MAC_PORTSET_SPEED_100M BIT(2) +-#define MAC_SET 0x0210 +-#define MAX_FRAME_SIZE 1600 +-#define MAX_FRAME_SIZE_MASK GENMASK(10, 0) +-#define BIT_PAUSE_EN BIT(18) +-#define RX_COALESCE_SET 0x0340 +-#define RX_COALESCED_FRAME_OFFSET 24 +-#define RX_COALESCED_FRAMES 8 +-#define RX_COALESCED_TIMER 0x74 +-#define QLEN_SET 0x0344 +-#define RX_DEPTH_OFFSET 8 +-#define MAX_HW_FIFO_DEPTH 64 +-#define HW_TX_FIFO_DEPTH 12 +-#define HW_RX_FIFO_DEPTH (MAX_HW_FIFO_DEPTH - HW_TX_FIFO_DEPTH) +-#define IQFRM_DES 0x0354 +-#define RX_FRAME_LEN_MASK GENMASK(11, 0) +-#define IQ_ADDR 0x0358 +-#define EQ_ADDR 0x0360 +-#define EQFRM_LEN 0x0364 +-#define ADDRQ_STAT 0x036C +-#define TX_CNT_INUSE_MASK GENMASK(5, 0) +-#define BIT_TX_READY BIT(24) +-#define BIT_RX_READY BIT(25) +-/* global control register list */ +-#define GLB_HOSTMAC_L32 0x0000 +-#define GLB_HOSTMAC_H16 0x0004 +-#define GLB_SOFT_RESET 0x0008 +-#define SOFT_RESET_ALL BIT(0) +-#define GLB_FWCTRL 0x0010 +-#define FWCTRL_VLAN_ENABLE BIT(0) +-#define FWCTRL_FW2CPU_ENA BIT(5) +-#define FWCTRL_FWALL2CPU BIT(7) +-#define GLB_MACTCTRL 0x0014 +-#define MACTCTRL_UNI2CPU BIT(1) +-#define MACTCTRL_MULTI2CPU BIT(3) +-#define MACTCTRL_BROAD2CPU BIT(5) +-#define MACTCTRL_MACT_ENA BIT(7) +-#define GLB_IRQ_STAT 0x0030 +-#define GLB_IRQ_ENA 0x0034 +-#define IRQ_ENA_PORT0_MASK GENMASK(7, 0) +-#define IRQ_ENA_PORT0 BIT(18) +-#define IRQ_ENA_ALL BIT(19) +-#define GLB_IRQ_RAW 0x0038 +-#define IRQ_INT_RX_RDY BIT(0) +-#define IRQ_INT_TX_PER_PACKET BIT(1) +-#define IRQ_INT_TX_FIFO_EMPTY BIT(6) +-#define IRQ_INT_MULTI_RXRDY BIT(7) +-#define DEF_INT_MASK (IRQ_INT_MULTI_RXRDY | \ +- IRQ_INT_TX_PER_PACKET | \ +- IRQ_INT_TX_FIFO_EMPTY) +-#define GLB_MAC_L32_BASE 0x0100 +-#define GLB_MAC_H16_BASE 0x0104 +-#define MACFLT_HI16_MASK GENMASK(15, 0) +-#define BIT_MACFLT_ENA BIT(17) +-#define BIT_MACFLT_FW2CPU BIT(21) +-#define GLB_MAC_H16(reg) (GLB_MAC_H16_BASE + ((reg) * 0x8)) +-#define GLB_MAC_L32(reg) (GLB_MAC_L32_BASE + ((reg) * 0x8)) +-#define MAX_MAC_FILTER_NUM 8 +-#define MAX_UNICAST_ADDRESSES 2 +-#define MAX_MULTICAST_ADDRESSES (MAX_MAC_FILTER_NUM - \ +- MAX_UNICAST_ADDRESSES) +-/* software tx and rx queue number, should be power of 2 */ +-#define TXQ_NUM 64 +-#define RXQ_NUM 128 +-#define FEMAC_POLL_WEIGHT 16 +- +-#define PHY_RESET_DELAYS_PROPERTY "hisilicon,phy-reset-delays-us" +- +-enum phy_reset_delays { +- PRE_DELAY, +- PULSE, +- POST_DELAY, +- DELAYS_NUM, +-}; +- +-struct hisi_femac_queue { +- struct sk_buff **skb; +- dma_addr_t *dma_phys; +- int num; +- unsigned int head; +- unsigned int tail; +-}; +- +-struct hisi_femac_priv { +- void __iomem *port_base; +- void __iomem *glb_base; +- struct clk *clk; +- struct reset_control *mac_rst; +- struct reset_control *phy_rst; +- u32 phy_reset_delays[DELAYS_NUM]; +- u32 link_status; +- +- struct device *dev; +- struct net_device *ndev; +- +- struct hisi_femac_queue txq; +- struct hisi_femac_queue rxq; +- u32 tx_fifo_used_cnt; +- struct napi_struct napi; +-}; +- +-static void hisi_femac_irq_enable(struct hisi_femac_priv *priv, int irqs) +-{ +- u32 val; +- +- val = readl(priv->glb_base + GLB_IRQ_ENA); +- writel(val | irqs, priv->glb_base + GLB_IRQ_ENA); +-} +- +-static void hisi_femac_irq_disable(struct hisi_femac_priv *priv, int irqs) +-{ +- u32 val; +- +- val = readl(priv->glb_base + GLB_IRQ_ENA); +- writel(val & (~irqs), priv->glb_base + GLB_IRQ_ENA); +-} +- +-static void hisi_femac_tx_dma_unmap(struct hisi_femac_priv *priv, +- struct sk_buff *skb, unsigned int pos) +-{ +- dma_addr_t dma_addr; +- +- dma_addr = priv->txq.dma_phys[pos]; +- dma_unmap_single(priv->dev, dma_addr, skb->len, DMA_TO_DEVICE); +-} +- +-static void hisi_femac_xmit_reclaim(struct net_device *dev) +-{ +- struct sk_buff *skb; +- struct hisi_femac_priv *priv = netdev_priv(dev); +- struct hisi_femac_queue *txq = &priv->txq; +- unsigned int bytes_compl = 0, pkts_compl = 0; +- u32 val; +- +- netif_tx_lock(dev); +- +- val = readl(priv->port_base + ADDRQ_STAT) & TX_CNT_INUSE_MASK; +- while (val < priv->tx_fifo_used_cnt) { +- skb = txq->skb[txq->tail]; +- if (unlikely(!skb)) { +- netdev_err(dev, "xmitq_cnt_inuse=%d, tx_fifo_used=%d\n", +- val, priv->tx_fifo_used_cnt); +- break; +- } +- hisi_femac_tx_dma_unmap(priv, skb, txq->tail); +- pkts_compl++; +- bytes_compl += skb->len; +- dev_kfree_skb_any(skb); +- +- priv->tx_fifo_used_cnt--; +- +- val = readl(priv->port_base + ADDRQ_STAT) & TX_CNT_INUSE_MASK; +- txq->skb[txq->tail] = NULL; +- txq->tail = (txq->tail + 1) % txq->num; +- } +- +- netdev_completed_queue(dev, pkts_compl, bytes_compl); +- +- if (unlikely(netif_queue_stopped(dev)) && pkts_compl) +- netif_wake_queue(dev); +- +- netif_tx_unlock(dev); +-} +- +-static void hisi_femac_adjust_link(struct net_device *dev) +-{ +- struct hisi_femac_priv *priv = netdev_priv(dev); +- struct phy_device *phy = dev->phydev; +- u32 status = 0; +- +- if (phy->link) +- status |= MAC_PORTSET_LINKED; +- if (phy->duplex == DUPLEX_FULL) +- status |= MAC_PORTSET_DUPLEX_FULL; +- if (phy->speed == SPEED_100) +- status |= MAC_PORTSET_SPEED_100M; +- +- if ((status != priv->link_status) && +- ((status | priv->link_status) & MAC_PORTSET_LINKED)) { +- writel(status, priv->port_base + MAC_PORTSET); +- priv->link_status = status; +- phy_print_status(phy); +- } +-} +- +-static void hisi_femac_rx_refill(struct hisi_femac_priv *priv) +-{ +- struct hisi_femac_queue *rxq = &priv->rxq; +- struct sk_buff *skb; +- u32 pos; +- u32 len = MAX_FRAME_SIZE; +- dma_addr_t addr; +- +- pos = rxq->head; +- while (readl(priv->port_base + ADDRQ_STAT) & BIT_RX_READY) { +- if (!CIRC_SPACE(pos, rxq->tail, rxq->num)) +- break; +- if (unlikely(rxq->skb[pos])) { +- netdev_err(priv->ndev, "err skb[%d]=%p\n", +- pos, rxq->skb[pos]); +- break; +- } +- skb = netdev_alloc_skb_ip_align(priv->ndev, len); +- if (unlikely(!skb)) +- break; +- +- addr = dma_map_single(priv->dev, skb->data, len, +- DMA_FROM_DEVICE); +- if (dma_mapping_error(priv->dev, addr)) { +- dev_kfree_skb_any(skb); +- break; +- } +- rxq->dma_phys[pos] = addr; +- rxq->skb[pos] = skb; +- writel(addr, priv->port_base + IQ_ADDR); +- pos = (pos + 1) % rxq->num; +- } +- rxq->head = pos; +-} +- +-static int hisi_femac_rx(struct net_device *dev, int limit) +-{ +- struct hisi_femac_priv *priv = netdev_priv(dev); +- struct hisi_femac_queue *rxq = &priv->rxq; +- struct sk_buff *skb; +- dma_addr_t addr; +- u32 rx_pkt_info, pos, len, rx_pkts_num = 0; +- +- pos = rxq->tail; +- while (readl(priv->glb_base + GLB_IRQ_RAW) & IRQ_INT_RX_RDY) { +- rx_pkt_info = readl(priv->port_base + IQFRM_DES); +- len = rx_pkt_info & RX_FRAME_LEN_MASK; +- len -= ETH_FCS_LEN; +- +- /* tell hardware we will deal with this packet */ +- writel(IRQ_INT_RX_RDY, priv->glb_base + GLB_IRQ_RAW); +- +- rx_pkts_num++; +- +- skb = rxq->skb[pos]; +- if (unlikely(!skb)) { +- netdev_err(dev, "rx skb NULL. pos=%d\n", pos); +- break; +- } +- rxq->skb[pos] = NULL; +- +- addr = rxq->dma_phys[pos]; +- dma_unmap_single(priv->dev, addr, MAX_FRAME_SIZE, +- DMA_FROM_DEVICE); +- skb_put(skb, len); +- if (unlikely(skb->len > MAX_FRAME_SIZE)) { +- netdev_err(dev, "rcv len err, len = %d\n", skb->len); +- dev->stats.rx_errors++; +- dev->stats.rx_length_errors++; +- dev_kfree_skb_any(skb); +- goto next; +- } +- +- skb->protocol = eth_type_trans(skb, dev); +- napi_gro_receive(&priv->napi, skb); +- dev->stats.rx_packets++; +- dev->stats.rx_bytes += skb->len; +-next: +- pos = (pos + 1) % rxq->num; +- if (rx_pkts_num >= limit) +- break; +- } +- rxq->tail = pos; +- +- hisi_femac_rx_refill(priv); +- +- return rx_pkts_num; +-} +- +-static int hisi_femac_poll(struct napi_struct *napi, int budget) +-{ +- struct hisi_femac_priv *priv = container_of(napi, +- struct hisi_femac_priv, napi); +- struct net_device *dev = priv->ndev; +- int work_done = 0, task = budget; +- int ints, num; +- +- do { +- hisi_femac_xmit_reclaim(dev); +- num = hisi_femac_rx(dev, task); +- work_done += num; +- task -= num; +- if (work_done >= budget) +- break; +- +- ints = readl(priv->glb_base + GLB_IRQ_RAW); +- writel(ints & DEF_INT_MASK, +- priv->glb_base + GLB_IRQ_RAW); +- } while (ints & DEF_INT_MASK); +- +- if (work_done < budget) { +- napi_complete(napi); +- hisi_femac_irq_enable(priv, DEF_INT_MASK & +- (~IRQ_INT_TX_PER_PACKET)); +- } +- +- return work_done; +-} +- +-static irqreturn_t hisi_femac_interrupt(int irq, void *dev_id) +-{ +- int ints; +- struct net_device *dev = (struct net_device *)dev_id; +- struct hisi_femac_priv *priv = netdev_priv(dev); +- +- ints = readl(priv->glb_base + GLB_IRQ_RAW); +- +- if (likely(ints & DEF_INT_MASK)) { +- writel(ints & DEF_INT_MASK, +- priv->glb_base + GLB_IRQ_RAW); +- hisi_femac_irq_disable(priv, DEF_INT_MASK); +- napi_schedule(&priv->napi); +- } +- +- return IRQ_HANDLED; +-} +- +-static int hisi_femac_init_queue(struct device *dev, +- struct hisi_femac_queue *queue, +- unsigned int num) +-{ +- queue->skb = devm_kcalloc(dev, num, sizeof(struct sk_buff *), +- GFP_KERNEL); +- if (!queue->skb) +- return -ENOMEM; +- +- queue->dma_phys = devm_kcalloc(dev, num, sizeof(dma_addr_t), +- GFP_KERNEL); +- if (!queue->dma_phys) +- return -ENOMEM; +- +- queue->num = num; +- queue->head = 0; +- queue->tail = 0; +- +- return 0; +-} +- +-static int hisi_femac_init_tx_and_rx_queues(struct hisi_femac_priv *priv) +-{ +- int ret; +- +- ret = hisi_femac_init_queue(priv->dev, &priv->txq, TXQ_NUM); +- if (ret) +- return ret; +- +- ret = hisi_femac_init_queue(priv->dev, &priv->rxq, RXQ_NUM); +- if (ret) +- return ret; +- +- priv->tx_fifo_used_cnt = 0; +- +- return 0; +-} +- +-static void hisi_femac_free_skb_rings(struct hisi_femac_priv *priv) +-{ +- struct hisi_femac_queue *txq = &priv->txq; +- struct hisi_femac_queue *rxq = &priv->rxq; +- struct sk_buff *skb; +- dma_addr_t dma_addr; +- u32 pos; +- +- pos = rxq->tail; +- while (pos != rxq->head) { +- skb = rxq->skb[pos]; +- if (unlikely(!skb)) { +- netdev_err(priv->ndev, "NULL rx skb. pos=%d, head=%d\n", +- pos, rxq->head); +- continue; +- } +- +- dma_addr = rxq->dma_phys[pos]; +- dma_unmap_single(priv->dev, dma_addr, MAX_FRAME_SIZE, +- DMA_FROM_DEVICE); +- +- dev_kfree_skb_any(skb); +- rxq->skb[pos] = NULL; +- pos = (pos + 1) % rxq->num; +- } +- rxq->tail = pos; +- +- pos = txq->tail; +- while (pos != txq->head) { +- skb = txq->skb[pos]; +- if (unlikely(!skb)) { +- netdev_err(priv->ndev, "NULL tx skb. pos=%d, head=%d\n", +- pos, txq->head); +- continue; +- } +- hisi_femac_tx_dma_unmap(priv, skb, pos); +- dev_kfree_skb_any(skb); +- txq->skb[pos] = NULL; +- pos = (pos + 1) % txq->num; +- } +- txq->tail = pos; +- priv->tx_fifo_used_cnt = 0; +-} +- +-static int hisi_femac_set_hw_mac_addr(struct hisi_femac_priv *priv, +- unsigned char *mac) +-{ +- u32 reg; +- +- reg = mac[1] | (mac[0] << 8); +- writel(reg, priv->glb_base + GLB_HOSTMAC_H16); +- +- reg = mac[5] | (mac[4] << 8) | (mac[3] << 16) | (mac[2] << 24); +- writel(reg, priv->glb_base + GLB_HOSTMAC_L32); +- +- return 0; +-} +- +-static int hisi_femac_port_reset(struct hisi_femac_priv *priv) +-{ +- u32 val; +- +- val = readl(priv->glb_base + GLB_SOFT_RESET); +- val |= SOFT_RESET_ALL; +- writel(val, priv->glb_base + GLB_SOFT_RESET); +- +- usleep_range(500, 800); +- +- val &= ~SOFT_RESET_ALL; +- writel(val, priv->glb_base + GLB_SOFT_RESET); +- +- return 0; +-} +- +-static int hisi_femac_net_open(struct net_device *dev) +-{ +- struct hisi_femac_priv *priv = netdev_priv(dev); +- +- hisi_femac_port_reset(priv); +- hisi_femac_set_hw_mac_addr(priv, dev->dev_addr); +- hisi_femac_rx_refill(priv); +- +- netif_carrier_off(dev); +- netdev_reset_queue(dev); +- netif_start_queue(dev); +- napi_enable(&priv->napi); +- +- priv->link_status = 0; +- if (dev->phydev) +- phy_start(dev->phydev); +- +- writel(IRQ_ENA_PORT0_MASK, priv->glb_base + GLB_IRQ_RAW); +- hisi_femac_irq_enable(priv, IRQ_ENA_ALL | IRQ_ENA_PORT0 | DEF_INT_MASK); +- +- return 0; +-} +- +-static int hisi_femac_net_close(struct net_device *dev) +-{ +- struct hisi_femac_priv *priv = netdev_priv(dev); +- +- hisi_femac_irq_disable(priv, IRQ_ENA_PORT0); +- +- if (dev->phydev) +- phy_stop(dev->phydev); +- +- netif_stop_queue(dev); +- napi_disable(&priv->napi); +- +- hisi_femac_free_skb_rings(priv); +- +- return 0; +-} +- +-static netdev_tx_t hisi_femac_net_xmit(struct sk_buff *skb, +- struct net_device *dev) +-{ +- struct hisi_femac_priv *priv = netdev_priv(dev); +- struct hisi_femac_queue *txq = &priv->txq; +- dma_addr_t addr; +- u32 val; +- +- val = readl(priv->port_base + ADDRQ_STAT); +- val &= BIT_TX_READY; +- if (!val) { +- hisi_femac_irq_enable(priv, IRQ_INT_TX_PER_PACKET); +- dev->stats.tx_dropped++; +- dev->stats.tx_fifo_errors++; +- netif_stop_queue(dev); +- return NETDEV_TX_BUSY; +- } +- +- if (unlikely(!CIRC_SPACE(txq->head, txq->tail, +- txq->num))) { +- hisi_femac_irq_enable(priv, IRQ_INT_TX_PER_PACKET); +- dev->stats.tx_dropped++; +- dev->stats.tx_fifo_errors++; +- netif_stop_queue(dev); +- return NETDEV_TX_BUSY; +- } +- +- addr = dma_map_single(priv->dev, skb->data, +- skb->len, DMA_TO_DEVICE); +- if (unlikely(dma_mapping_error(priv->dev, addr))) { +- dev_kfree_skb_any(skb); +- dev->stats.tx_dropped++; +- return NETDEV_TX_OK; +- } +- txq->dma_phys[txq->head] = addr; +- +- txq->skb[txq->head] = skb; +- txq->head = (txq->head + 1) % txq->num; +- +- writel(addr, priv->port_base + EQ_ADDR); +- writel(skb->len + ETH_FCS_LEN, priv->port_base + EQFRM_LEN); +- +- priv->tx_fifo_used_cnt++; +- +- dev->stats.tx_packets++; +- dev->stats.tx_bytes += skb->len; +- netdev_sent_queue(dev, skb->len); +- +- return NETDEV_TX_OK; +-} +- +-static int hisi_femac_set_mac_address(struct net_device *dev, void *p) +-{ +- struct hisi_femac_priv *priv = netdev_priv(dev); +- struct sockaddr *skaddr = p; +- +- if (!is_valid_ether_addr(skaddr->sa_data)) +- return -EADDRNOTAVAIL; +- +- memcpy(dev->dev_addr, skaddr->sa_data, dev->addr_len); +- dev->addr_assign_type &= ~NET_ADDR_RANDOM; +- +- hisi_femac_set_hw_mac_addr(priv, dev->dev_addr); +- +- return 0; +-} +- +-static void hisi_femac_enable_hw_addr_filter(struct hisi_femac_priv *priv, +- unsigned int reg_n, bool enable) +-{ +- u32 val; +- +- val = readl(priv->glb_base + GLB_MAC_H16(reg_n)); +- if (enable) +- val |= BIT_MACFLT_ENA; +- else +- val &= ~BIT_MACFLT_ENA; +- writel(val, priv->glb_base + GLB_MAC_H16(reg_n)); +-} +- +-static void hisi_femac_set_hw_addr_filter(struct hisi_femac_priv *priv, +- unsigned char *addr, +- unsigned int reg_n) +-{ +- unsigned int high, low; +- u32 val; +- +- high = GLB_MAC_H16(reg_n); +- low = GLB_MAC_L32(reg_n); +- +- val = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | addr[5]; +- writel(val, priv->glb_base + low); +- +- val = readl(priv->glb_base + high); +- val &= ~MACFLT_HI16_MASK; +- val |= ((addr[0] << 8) | addr[1]); +- val |= (BIT_MACFLT_ENA | BIT_MACFLT_FW2CPU); +- writel(val, priv->glb_base + high); +-} +- +-static void hisi_femac_set_promisc_mode(struct hisi_femac_priv *priv, +- bool promisc_mode) +-{ +- u32 val; +- +- val = readl(priv->glb_base + GLB_FWCTRL); +- if (promisc_mode) +- val |= FWCTRL_FWALL2CPU; +- else +- val &= ~FWCTRL_FWALL2CPU; +- writel(val, priv->glb_base + GLB_FWCTRL); +-} +- +-/* Handle multiple multicast addresses (perfect filtering)*/ +-static void hisi_femac_set_mc_addr_filter(struct hisi_femac_priv *priv) +-{ +- struct net_device *dev = priv->ndev; +- u32 val; +- +- val = readl(priv->glb_base + GLB_MACTCTRL); +- if ((netdev_mc_count(dev) > MAX_MULTICAST_ADDRESSES) || +- (dev->flags & IFF_ALLMULTI)) { +- val |= MACTCTRL_MULTI2CPU; +- } else { +- int reg = MAX_UNICAST_ADDRESSES; +- int i; +- struct netdev_hw_addr *ha; +- +- for (i = reg; i < MAX_MAC_FILTER_NUM; i++) +- hisi_femac_enable_hw_addr_filter(priv, i, false); +- +- netdev_for_each_mc_addr(ha, dev) { +- hisi_femac_set_hw_addr_filter(priv, ha->addr, reg); +- reg++; +- } +- val &= ~MACTCTRL_MULTI2CPU; +- } +- writel(val, priv->glb_base + GLB_MACTCTRL); +-} +- +-/* Handle multiple unicast addresses (perfect filtering)*/ +-static void hisi_femac_set_uc_addr_filter(struct hisi_femac_priv *priv) +-{ +- struct net_device *dev = priv->ndev; +- u32 val; +- +- val = readl(priv->glb_base + GLB_MACTCTRL); +- if (netdev_uc_count(dev) > MAX_UNICAST_ADDRESSES) { +- val |= MACTCTRL_UNI2CPU; +- } else { +- int reg = 0; +- int i; +- struct netdev_hw_addr *ha; +- +- for (i = reg; i < MAX_UNICAST_ADDRESSES; i++) +- hisi_femac_enable_hw_addr_filter(priv, i, false); +- +- netdev_for_each_uc_addr(ha, dev) { +- hisi_femac_set_hw_addr_filter(priv, ha->addr, reg); +- reg++; +- } +- val &= ~MACTCTRL_UNI2CPU; +- } +- writel(val, priv->glb_base + GLB_MACTCTRL); +-} +- +-static void hisi_femac_net_set_rx_mode(struct net_device *dev) +-{ +- struct hisi_femac_priv *priv = netdev_priv(dev); +- +- if (dev->flags & IFF_PROMISC) { +- hisi_femac_set_promisc_mode(priv, true); +- } else { +- hisi_femac_set_promisc_mode(priv, false); +- hisi_femac_set_mc_addr_filter(priv); +- hisi_femac_set_uc_addr_filter(priv); +- } +-} +- +-static int hisi_femac_net_ioctl(struct net_device *dev, +- struct ifreq *ifreq, int cmd) +-{ +- if (!netif_running(dev)) +- return -EINVAL; +- +- if (!dev->phydev) +- return -EINVAL; +- +- return phy_mii_ioctl(dev->phydev, ifreq, cmd); +-} +- +-static const struct ethtool_ops hisi_femac_ethtools_ops = { +- .get_link = ethtool_op_get_link, +- .get_link_ksettings = phy_ethtool_get_link_ksettings, +- .set_link_ksettings = phy_ethtool_set_link_ksettings, +-}; +- +-static const struct net_device_ops hisi_femac_netdev_ops = { +- .ndo_open = hisi_femac_net_open, +- .ndo_stop = hisi_femac_net_close, +- .ndo_start_xmit = hisi_femac_net_xmit, +- .ndo_do_ioctl = hisi_femac_net_ioctl, +- .ndo_set_mac_address = hisi_femac_set_mac_address, +- .ndo_set_rx_mode = hisi_femac_net_set_rx_mode, +- .ndo_change_mtu = eth_change_mtu, +-}; +- +-static void hisi_femac_core_reset(struct hisi_femac_priv *priv) +-{ +- reset_control_assert(priv->mac_rst); +- reset_control_deassert(priv->mac_rst); +-} +- +-static void hisi_femac_sleep_us(u32 time_us) +-{ +- u32 time_ms; +- +- if (!time_us) +- return; +- +- time_ms = DIV_ROUND_UP(time_us, 1000); +- if (time_ms < 20) +- usleep_range(time_us, time_us + 500); +- else +- msleep(time_ms); +-} +- +-static void hisi_femac_phy_reset(struct hisi_femac_priv *priv) +-{ +- /* To make sure PHY hardware reset success, +- * we must keep PHY in deassert state first and +- * then complete the hardware reset operation +- */ +- reset_control_deassert(priv->phy_rst); +- hisi_femac_sleep_us(priv->phy_reset_delays[PRE_DELAY]); +- +- reset_control_assert(priv->phy_rst); +- /* delay some time to ensure reset ok, +- * this depends on PHY hardware feature +- */ +- hisi_femac_sleep_us(priv->phy_reset_delays[PULSE]); +- reset_control_deassert(priv->phy_rst); +- /* delay some time to ensure later MDIO access */ +- hisi_femac_sleep_us(priv->phy_reset_delays[POST_DELAY]); +-} +- +-static void hisi_femac_port_init(struct hisi_femac_priv *priv) +-{ +- u32 val; +- +- /* MAC gets link status info and phy mode by software config */ +- val = MAC_PORTSEL_STAT_CPU; +- if (priv->ndev->phydev->interface == PHY_INTERFACE_MODE_RMII) +- val |= MAC_PORTSEL_RMII; +- writel(val, priv->port_base + MAC_PORTSEL); +- +- /*clear all interrupt status */ +- writel(IRQ_ENA_PORT0_MASK, priv->glb_base + GLB_IRQ_RAW); +- hisi_femac_irq_disable(priv, IRQ_ENA_PORT0_MASK | IRQ_ENA_PORT0); +- +- val = readl(priv->glb_base + GLB_FWCTRL); +- val &= ~(FWCTRL_VLAN_ENABLE | FWCTRL_FWALL2CPU); +- val |= FWCTRL_FW2CPU_ENA; +- writel(val, priv->glb_base + GLB_FWCTRL); +- +- val = readl(priv->glb_base + GLB_MACTCTRL); +- val |= (MACTCTRL_BROAD2CPU | MACTCTRL_MACT_ENA); +- writel(val, priv->glb_base + GLB_MACTCTRL); +- +- val = readl(priv->port_base + MAC_SET); +- val &= ~MAX_FRAME_SIZE_MASK; +- val |= MAX_FRAME_SIZE; +- writel(val, priv->port_base + MAC_SET); +- +- val = RX_COALESCED_TIMER | +- (RX_COALESCED_FRAMES << RX_COALESCED_FRAME_OFFSET); +- writel(val, priv->port_base + RX_COALESCE_SET); +- +- val = (HW_RX_FIFO_DEPTH << RX_DEPTH_OFFSET) | HW_TX_FIFO_DEPTH; +- writel(val, priv->port_base + QLEN_SET); +-} +- +-static int hisi_femac_drv_probe(struct platform_device *pdev) +-{ +- struct device *dev = &pdev->dev; +- struct device_node *node = dev->of_node; +- struct resource *res; +- struct net_device *ndev; +- struct hisi_femac_priv *priv; +- struct phy_device *phy; +- const char *mac_addr; +- int ret; +- +- ndev = alloc_etherdev(sizeof(*priv)); +- if (!ndev) +- return -ENOMEM; +- +- platform_set_drvdata(pdev, ndev); +- +- priv = netdev_priv(ndev); +- priv->dev = dev; +- priv->ndev = ndev; +- +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- priv->port_base = devm_ioremap_resource(dev, res); +- if (IS_ERR(priv->port_base)) { +- ret = PTR_ERR(priv->port_base); +- goto out_free_netdev; +- } +- +- res = platform_get_resource(pdev, IORESOURCE_MEM, 1); +- priv->glb_base = devm_ioremap_resource(dev, res); +- if (IS_ERR(priv->glb_base)) { +- ret = PTR_ERR(priv->glb_base); +- goto out_free_netdev; +- } +- +- priv->clk = devm_clk_get(&pdev->dev, NULL); +- if (IS_ERR(priv->clk)) { +- dev_err(dev, "failed to get clk\n"); +- ret = -ENODEV; +- goto out_free_netdev; +- } +- +- ret = clk_prepare_enable(priv->clk); +- if (ret) { +- dev_err(dev, "failed to enable clk %d\n", ret); +- goto out_free_netdev; +- } +- +- priv->mac_rst = devm_reset_control_get(dev, "mac"); +- if (IS_ERR(priv->mac_rst)) { +- ret = PTR_ERR(priv->mac_rst); +- goto out_disable_clk; +- } +- hisi_femac_core_reset(priv); +- +- priv->phy_rst = devm_reset_control_get(dev, "phy"); +- if (IS_ERR(priv->phy_rst)) { +- priv->phy_rst = NULL; +- } else { +- ret = of_property_read_u32_array(node, +- PHY_RESET_DELAYS_PROPERTY, +- priv->phy_reset_delays, +- DELAYS_NUM); +- if (ret) +- goto out_disable_clk; +- hisi_femac_phy_reset(priv); +- } +- +- phy = of_phy_get_and_connect(ndev, node, hisi_femac_adjust_link); +- if (!phy) { +- dev_err(dev, "connect to PHY failed!\n"); +- ret = -ENODEV; +- goto out_disable_clk; +- } +- +- phy_attached_print(phy, "phy_id=0x%.8lx, phy_mode=%s\n", +- (unsigned long)phy->phy_id, +- phy_modes(phy->interface)); +- +- mac_addr = of_get_mac_address(node); +- if (mac_addr) +- ether_addr_copy(ndev->dev_addr, mac_addr); +- if (!is_valid_ether_addr(ndev->dev_addr)) { +- eth_hw_addr_random(ndev); +- dev_warn(dev, "using random MAC address %pM\n", +- ndev->dev_addr); +- } +- +- ndev->watchdog_timeo = 6 * HZ; +- ndev->priv_flags |= IFF_UNICAST_FLT; +- ndev->netdev_ops = &hisi_femac_netdev_ops; +- ndev->ethtool_ops = &hisi_femac_ethtools_ops; +- netif_napi_add(ndev, &priv->napi, hisi_femac_poll, FEMAC_POLL_WEIGHT); +- SET_NETDEV_DEV(ndev, &pdev->dev); +- +- hisi_femac_port_init(priv); +- +- ret = hisi_femac_init_tx_and_rx_queues(priv); +- if (ret) +- goto out_disconnect_phy; +- +- ndev->irq = platform_get_irq(pdev, 0); +- if (ndev->irq <= 0) { +- dev_err(dev, "No irq resource\n"); +- ret = -ENODEV; +- goto out_disconnect_phy; +- } +- +- ret = devm_request_irq(dev, ndev->irq, hisi_femac_interrupt, +- IRQF_SHARED, pdev->name, ndev); +- if (ret) { +- dev_err(dev, "devm_request_irq %d failed!\n", ndev->irq); +- goto out_disconnect_phy; +- } +- +- ret = register_netdev(ndev); +- if (ret) { +- dev_err(dev, "register_netdev failed!\n"); +- goto out_disconnect_phy; +- } +- +- return ret; +- +-out_disconnect_phy: +- netif_napi_del(&priv->napi); +- phy_disconnect(phy); +-out_disable_clk: +- clk_disable_unprepare(priv->clk); +-out_free_netdev: +- free_netdev(ndev); +- +- return ret; +-} +- +-static int hisi_femac_drv_remove(struct platform_device *pdev) +-{ +- struct net_device *ndev = platform_get_drvdata(pdev); +- struct hisi_femac_priv *priv = netdev_priv(ndev); +- +- netif_napi_del(&priv->napi); +- unregister_netdev(ndev); +- +- phy_disconnect(ndev->phydev); +- clk_disable_unprepare(priv->clk); +- free_netdev(ndev); +- +- return 0; +-} +- +-#ifdef CONFIG_PM +-static int hisi_femac_drv_suspend(struct platform_device *pdev, +- pm_message_t state) +-{ +- struct net_device *ndev = platform_get_drvdata(pdev); +- struct hisi_femac_priv *priv = netdev_priv(ndev); +- +- disable_irq(ndev->irq); +- if (netif_running(ndev)) { +- hisi_femac_net_close(ndev); +- netif_device_detach(ndev); +- } +- +- clk_disable_unprepare(priv->clk); +- +- return 0; +-} +- +-static int hisi_femac_drv_resume(struct platform_device *pdev) +-{ +- struct net_device *ndev = platform_get_drvdata(pdev); +- struct hisi_femac_priv *priv = netdev_priv(ndev); +- +- clk_prepare_enable(priv->clk); +- if (priv->phy_rst) +- hisi_femac_phy_reset(priv); +- +- if (netif_running(ndev)) { +- hisi_femac_port_init(priv); +- hisi_femac_net_open(ndev); +- netif_device_attach(ndev); +- } +- enable_irq(ndev->irq); +- +- return 0; +-} +-#endif +- +-static const struct of_device_id hisi_femac_match[] = { +- {.compatible = "hisilicon,hisi-femac-v1",}, +- {.compatible = "hisilicon,hisi-femac-v2",}, +- {.compatible = "hisilicon,hi3516cv300-femac",}, +- {}, +-}; +- +-MODULE_DEVICE_TABLE(of, hisi_femac_match); +- +-static struct platform_driver hisi_femac_driver = { +- .driver = { +- .name = "hisi-femac", +- .of_match_table = hisi_femac_match, +- }, +- .probe = hisi_femac_drv_probe, +- .remove = hisi_femac_drv_remove, +-#ifdef CONFIG_PM +- .suspend = hisi_femac_drv_suspend, +- .resume = hisi_femac_drv_resume, +-#endif +-}; +- +-module_platform_driver(hisi_femac_driver); +- +-MODULE_DESCRIPTION("Hisilicon Fast Ethernet MAC driver"); +-MODULE_AUTHOR("Dongpo Li "); +-MODULE_LICENSE("GPL v2"); +-MODULE_ALIAS("platform:hisi-femac"); +diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig +index 2651c8d..0c4b93a 100644 +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -105,6 +105,13 @@ config MDIO_HISI_FEMAC + This module provides a driver for the MDIO busses found in the + Hisilicon SoC that have an Fast Ethernet MAC. + ++config MDIO_HISI_GEMAC ++ tristate "Hisilicon GEMAC MDIO bus controller" ++ depends on HAS_IOMEM && OF_MDIO ++ help ++ This module provides a driver for the MDIO busses found in the ++ Hisilicon SoC that have an Gigabit Ethernet MAC. ++ + config MDIO_MOXART + tristate "MOXA ART MDIO interface support" + depends on ARCH_MOXART +diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile +index e58667d..a6ae694 100644 +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -15,6 +15,7 @@ obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o + obj-$(CONFIG_MDIO_CAVIUM) += mdio-cavium.o + obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o + obj-$(CONFIG_MDIO_HISI_FEMAC) += mdio-hisi-femac.o ++obj-$(CONFIG_MDIO_HISI_GEMAC) += mdio-hisi-gemac.o + obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o + obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o + obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o +diff --git a/drivers/net/phy/mdio-hisi-femac.c b/drivers/net/phy/mdio-hisi-femac.c +index b03fedd..9035579 100644 +--- a/drivers/net/phy/mdio-hisi-femac.c ++++ b/drivers/net/phy/mdio-hisi-femac.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + #define MDIO_RWCTRL 0x00 + #define MDIO_RO_DATA 0x04 +@@ -32,16 +33,55 @@ + #define BIT_PHY_ADDR_OFFSET 8 + #define BIT_WR_DATA_OFFSET 16 + ++#define BIT_MASK_FEPHY_ADDR GENMASK(4, 0) ++#define BIT_FEPHY_SEL BIT(5) ++ ++#define BIT_OFFSET_LD_SET 0 ++#define BIT_OFFSET_LDO_SET 5 ++#define BIT_OFFSET_R_TUNING 8 ++ ++#define MII_EXPMD 0x1d ++#define MII_EXPMA 0x1e ++ ++#define REG_LD_AM 0x3050 ++#define BIT_MASK_LD_SET GENMASK(4, 0) ++#define REG_LDO_AM 0x3051 ++#define BIT_MASK_LDO_SET GENMASK(2, 0) ++#define REG_R_TUNING 0x3052 ++#define BIT_MASK_R_TUNING GENMASK(5, 0) ++#define REG_WR_DONE 0x3053 ++#define BIT_CFG_DONE BIT(0) ++#define BIT_CFG_ACK BIT(1) ++#define REG_DEF_ATE 0x3057 ++#define BIT_AUTOTRIM_DONE BIT(0) ++ ++#define PHY_RESET_DELAYS_PROPERTY "hisilicon,phy-reset-delays-us" ++ ++enum phy_reset_delays { ++ PRE_DELAY, ++ PULSE, ++ POST_DELAY, ++ DELAYS_NUM, ++}; ++ + struct hisi_femac_mdio_data { + struct clk *clk; ++ struct clk *fephy_clk; ++ struct reset_control *phy_rst; ++ struct reset_control *fephy_rst; ++ u32 phy_reset_delays[DELAYS_NUM]; + void __iomem *membase; ++ void __iomem *fephy_iobase; ++ void __iomem *fephy_trim_iobase; ++ struct mii_bus *bus; ++ u32 phy_addr; + }; + + static int hisi_femac_mdio_wait_ready(struct hisi_femac_mdio_data *data) + { + u32 val; + +- return readl_poll_timeout(data->membase + MDIO_RWCTRL, ++ return readl_poll_timeout_atomic(data->membase + MDIO_RWCTRL, + val, val & MDIO_RW_FINISH, 20, 10000); + } + +@@ -54,8 +94,8 @@ static int hisi_femac_mdio_read(struct mii_bus *bus, int mii_id, int regnum) + if (ret) + return ret; + +- writel((mii_id << BIT_PHY_ADDR_OFFSET) | regnum, +- data->membase + MDIO_RWCTRL); ++ writel((mii_id << BIT_PHY_ADDR_OFFSET) | ((u32)regnum), ++ data->membase + MDIO_RWCTRL); + + ret = hisi_femac_mdio_wait_ready(data); + if (ret) +@@ -75,12 +115,215 @@ static int hisi_femac_mdio_write(struct mii_bus *bus, int mii_id, int regnum, + return ret; + + writel(MDIO_WRITE | (value << BIT_WR_DATA_OFFSET) | +- (mii_id << BIT_PHY_ADDR_OFFSET) | regnum, ++ (mii_id << BIT_PHY_ADDR_OFFSET) | ((u32)regnum), + data->membase + MDIO_RWCTRL); + + return hisi_femac_mdio_wait_ready(data); + } + ++static void hisi_femac_sleep_us(u32 time_us) ++{ ++ u32 time_ms; ++ ++ if (!time_us) ++ return; ++ ++ time_ms = DIV_ROUND_UP(time_us, 1000); ++ if (time_ms < 20) ++ usleep_range(time_us, time_us + 500); ++ else ++ msleep(time_ms); ++} ++ ++static void hisi_femac_phy_reset(struct hisi_femac_mdio_data *data) ++{ ++ /* To make sure PHY hardware reset success, ++ * we must keep PHY in deassert state first and ++ * then complete the hardware reset operation ++ */ ++ reset_control_deassert(data->phy_rst); ++ hisi_femac_sleep_us(data->phy_reset_delays[PRE_DELAY]); ++ ++ reset_control_assert(data->phy_rst); ++ /* delay some time to ensure reset ok, ++ * this depends on PHY hardware feature ++ */ ++ hisi_femac_sleep_us(data->phy_reset_delays[PULSE]); ++ reset_control_deassert(data->phy_rst); ++ /* delay some time to ensure later MDIO access */ ++ hisi_femac_sleep_us(data->phy_reset_delays[POST_DELAY]); ++} ++ ++static void hisi_femac_get_phy_addr(struct hisi_femac_mdio_data *data, ++ struct device_node *np) ++{ ++ struct device_node *child = NULL; ++ int addr; ++ ++ child = of_get_next_available_child(np, NULL); ++ if (!child) { ++ pr_err("%s: No valid PHY device node!\n", __func__); ++ return; ++ } ++ ++ addr = of_mdio_parse_addr(&data->bus->dev, child); ++ if (addr < 0) { ++ pr_err("%s: get PHY address failed!\n", __func__); ++ return; ++ } ++ ++ data->phy_addr = addr; ++} ++ ++static inline bool hisi_femac_use_fephy(struct hisi_femac_mdio_data *data) ++{ ++ /*return false;*/ ++ return (data->fephy_iobase ? ++ !(readl(data->fephy_iobase) & BIT_FEPHY_SEL) : false); ++} ++ ++static void hisi_femac_fephy_reset(struct hisi_femac_mdio_data *data) ++{ ++ u32 val; ++ ++ /* disable MDCK clock to make sure FEPHY reset success */ ++ clk_disable_unprepare(data->clk); ++ ++ val = readl(data->fephy_iobase); ++ val &= ~BIT_MASK_FEPHY_ADDR; ++ val |= data->phy_addr; ++ writel(val, data->fephy_iobase); ++ ++ clk_prepare_enable(data->fephy_clk); ++ udelay(10); ++ ++ reset_control_assert(data->fephy_rst); ++ udelay(10); ++ reset_control_deassert(data->fephy_rst); ++ /* delay at least 15ms for MDIO operation */ ++ msleep(20); ++ ++ clk_prepare_enable(data->clk); ++ /* delay 5ms after enable MDCK to make sure FEPHY trim safe */ ++ mdelay(5); ++} ++ ++static inline int fephy_expanded_read(struct mii_bus *bus, int phy_addr, ++ u32 reg_addr) ++{ ++ int ret; ++ ++ hisi_femac_mdio_write(bus, phy_addr, MII_EXPMA, reg_addr); ++ ret = hisi_femac_mdio_read(bus, phy_addr, MII_EXPMD); ++ ++ return ret; ++} ++ ++static inline int fephy_expanded_write(struct mii_bus *bus, int phy_addr, ++ u32 reg_addr, u16 val) ++{ ++ int ret; ++ ++ hisi_femac_mdio_write(bus, phy_addr, MII_EXPMA, reg_addr); ++ ret = hisi_femac_mdio_write(bus, phy_addr, MII_EXPMD, val); ++ ++ return ret; ++} ++ ++void hisi_femac_fephy_use_default_trim(struct hisi_femac_mdio_data *data) ++{ ++ unsigned short val; ++ int timeout = 3; ++ ++ pr_info("No OTP data, festa PHY use default ATE parameters!\n"); ++ ++ do { ++ msleep(250); ++ val = fephy_expanded_read(data->bus, data->phy_addr, ++ REG_DEF_ATE); ++ val &= BIT_AUTOTRIM_DONE; ++ } while (!val && --timeout); ++ ++ if (!timeout) ++ pr_err("festa PHY wait autotrim done timeout!\n"); ++ ++ mdelay(5); ++} ++ ++static void hisi_femac_fephy_trim(struct hisi_femac_mdio_data *data) ++{ ++ struct mii_bus *bus = data->bus; ++ u32 phy_addr = data->phy_addr; ++ int timeout = 3000; ++ u32 val; ++ u8 ld_set; ++ u8 ldo_set; ++ u8 r_tuning; ++ ++ val = readl(data->fephy_trim_iobase); ++ ld_set = (val >> BIT_OFFSET_LD_SET) & BIT_MASK_LD_SET; ++ ldo_set = (val >> BIT_OFFSET_LDO_SET) & BIT_MASK_LDO_SET; ++ r_tuning = (val >> BIT_OFFSET_R_TUNING) & BIT_MASK_R_TUNING; ++ ++ if (!ld_set && !ldo_set && !r_tuning) { ++ hisi_femac_fephy_use_default_trim(data); ++ return; ++ } ++ ++ val = fephy_expanded_read(bus, phy_addr, REG_LD_AM); ++ val = (val & ~BIT_MASK_LD_SET) | (ld_set & BIT_MASK_LD_SET); ++ fephy_expanded_write(bus, phy_addr, REG_LD_AM, val); ++ ++ val = fephy_expanded_read(bus, phy_addr, REG_LDO_AM); ++ val = (val & ~BIT_MASK_LDO_SET) | (ldo_set & BIT_MASK_LDO_SET); ++ fephy_expanded_write(bus, phy_addr, REG_LDO_AM, val); ++ ++ val = fephy_expanded_read(bus, phy_addr, REG_R_TUNING); ++ val = (val & ~BIT_MASK_R_TUNING) | (r_tuning & BIT_MASK_R_TUNING); ++ fephy_expanded_write(bus, phy_addr, REG_R_TUNING, val); ++ ++ val = fephy_expanded_read(bus, phy_addr, REG_WR_DONE); ++ if (val & BIT_CFG_ACK) ++ pr_err("festa PHY 0x3053 bit CFG_ACK value: 1\n"); ++ val = val | BIT_CFG_DONE; ++ fephy_expanded_write(bus, phy_addr, REG_WR_DONE, val); ++ ++ do { ++ usleep_range(100, 150); ++ val = fephy_expanded_read(bus, phy_addr, REG_WR_DONE); ++ val &= BIT_CFG_ACK; ++ } while (!val && --timeout); ++ if (!timeout) ++ pr_err("festa PHY 0x3053 wait bit CFG_ACK timeout!\n"); ++ ++ mdelay(5); ++ ++ pr_info("FEPHY:addr=%d, la_am=0x%x, ldo_am=0x%x, r_tuning=0x%x\n", ++ phy_addr, ++ fephy_expanded_read(bus, phy_addr, REG_LD_AM), ++ fephy_expanded_read(bus, phy_addr, REG_LDO_AM), ++ fephy_expanded_read(bus, phy_addr, REG_R_TUNING)); ++} ++ ++static void hisi_femac_fephy_reset_and_trim(struct hisi_femac_mdio_data *data) ++{ ++ hisi_femac_fephy_reset(data); ++ hisi_femac_fephy_trim(data); ++} ++ ++static void hisi_femac_fephy_set_phy_addr(struct hisi_femac_mdio_data *data) ++{ ++ u32 val; ++ ++ if (!data->fephy_iobase) ++ return; ++ ++ val = readl(data->fephy_iobase); ++ val &= ~BIT_MASK_FEPHY_ADDR; ++ val |= (data->phy_addr + 1); ++ writel(val, data->fephy_iobase); ++} ++ + static int hisi_femac_mdio_probe(struct platform_device *pdev) + { + struct device_node *np = pdev->dev.of_node; +@@ -100,6 +343,7 @@ static int hisi_femac_mdio_probe(struct platform_device *pdev) + bus->parent = &pdev->dev; + + data = bus->priv; ++ data->bus = bus; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + data->membase = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(data->membase)) { +@@ -107,16 +351,66 @@ static int hisi_femac_mdio_probe(struct platform_device *pdev) + goto err_out_free_mdiobus; + } + +- data->clk = devm_clk_get(&pdev->dev, NULL); ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (res) { ++ data->fephy_iobase = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(data->fephy_iobase)) { ++ ret = PTR_ERR(data->fephy_iobase); ++ goto err_out_free_mdiobus; ++ } ++ } else { ++ data->fephy_iobase = NULL; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 2); ++ if (res) { ++ data->fephy_trim_iobase = devm_ioremap_resource(&pdev->dev, ++ res); ++ if (IS_ERR(data->fephy_trim_iobase)) { ++ ret = PTR_ERR(data->fephy_trim_iobase); ++ goto err_out_free_mdiobus; ++ } ++ } else { ++ data->fephy_trim_iobase = NULL; ++ } ++ ++ data->clk = devm_clk_get(&pdev->dev, "mdio"); + if (IS_ERR(data->clk)) { + ret = PTR_ERR(data->clk); + goto err_out_free_mdiobus; + } + ++ data->fephy_clk = devm_clk_get(&pdev->dev, "phy"); ++ if (IS_ERR(data->fephy_clk)) ++ data->fephy_clk = NULL; ++ + ret = clk_prepare_enable(data->clk); + if (ret) + goto err_out_free_mdiobus; + ++ data->phy_rst = devm_reset_control_get(&pdev->dev, "external-phy"); ++ if (IS_ERR(data->phy_rst)) { ++ data->phy_rst = NULL; ++ } else { ++ ret = of_property_read_u32_array(np, ++ PHY_RESET_DELAYS_PROPERTY, ++ data->phy_reset_delays, ++ DELAYS_NUM); ++ if (ret) ++ goto err_out_disable_clk; ++ hisi_femac_phy_reset(data); ++ } ++ ++ data->fephy_rst = devm_reset_control_get(&pdev->dev, "internal-phy"); ++ if (IS_ERR(data->fephy_rst)) ++ data->fephy_rst = NULL; ++ ++ hisi_femac_get_phy_addr(data, np); ++ if (hisi_femac_use_fephy(data)) ++ hisi_femac_fephy_reset_and_trim(data); ++ else ++ hisi_femac_fephy_set_phy_addr(data); ++ + ret = of_mdiobus_register(bus, np); + if (ret) + goto err_out_disable_clk; +@@ -126,6 +420,7 @@ static int hisi_femac_mdio_probe(struct platform_device *pdev) + return 0; + + err_out_disable_clk: ++ clk_disable_unprepare(data->fephy_clk); + clk_disable_unprepare(data->clk); + err_out_free_mdiobus: + mdiobus_free(bus); +diff --git a/drivers/net/phy/mdio-hisi-gemac.c b/drivers/net/phy/mdio-hisi-gemac.c +new file mode 100644 +index 0000000..e34941d5e +--- /dev/null ++++ b/drivers/net/phy/mdio-hisi-gemac.c +@@ -0,0 +1,249 @@ ++/* ++ * Hisilicon Gigabit Ethernet MDIO Bus Driver ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(CONFIG_ARCH_HI3519) || defined(CONFIG_ARCH_HI3519V101) || \ ++ defined(CONFIG_ARCH_HI3516AV200) ++#ifdef readl ++#undef readl ++#undef writel ++#define readl hi_readl ++#define writel hi_writel ++#endif ++#endif ++ ++#define MDIO_SINGLE_CMD 0x00 ++#define MDIO_SINGLE_DATA 0x04 ++#define MDIO_RDATA_STATUS 0x10 ++#define BIT_PHY_ADDR_OFFSET 8 ++#define MDIO_WRITE BIT(16) ++#define MDIO_READ BIT(17) ++#define MDIO_START BIT(20) ++#define MDIO_START_READ (MDIO_START | MDIO_READ) ++#define MDIO_START_WRITE (MDIO_START | MDIO_WRITE) ++ ++struct hisi_gemac_mdio_data { ++ struct clk *clk; ++ struct reset_control *phy_rst; ++ void __iomem *membase; ++}; ++ ++static int hisi_gemac_mdio_wait_ready(struct hisi_gemac_mdio_data *data) ++{ ++ u32 val; ++ ++ return readl_poll_timeout(data->membase + MDIO_SINGLE_CMD, ++ val, !(val & MDIO_START), 20, 10000); ++} ++ ++static int hisi_gemac_mdio_read(struct mii_bus *bus, int mii_id, int regnum) ++{ ++ struct hisi_gemac_mdio_data *data = bus->priv; ++ int ret; ++ ++ ret = hisi_gemac_mdio_wait_ready(data); ++ if (ret) ++ return ret; ++ ++ writel(MDIO_START_READ | ((u32)mii_id << BIT_PHY_ADDR_OFFSET) | ++ ((u32)regnum), ++ data->membase + MDIO_SINGLE_CMD); ++ ++ ret = hisi_gemac_mdio_wait_ready(data); ++ if (ret) ++ return ret; ++ ++ /* if read data is invalid, we just return 0 instead of -EAGAIN. ++ * This can make MDIO more robust when reading PHY status. ++ */ ++ if (readl(data->membase + MDIO_RDATA_STATUS)) ++ return 0; ++ ++ return readl(data->membase + MDIO_SINGLE_DATA) >> 16; ++} ++ ++static int hisi_gemac_mdio_write(struct mii_bus *bus, int mii_id, int regnum, ++ u16 value) ++{ ++ struct hisi_gemac_mdio_data *data = bus->priv; ++ int ret; ++ ++ ret = hisi_gemac_mdio_wait_ready(data); ++ if (ret) ++ return ret; ++ ++ writel(value, data->membase + MDIO_SINGLE_DATA); ++ writel(MDIO_START_WRITE | ((u32)mii_id << BIT_PHY_ADDR_OFFSET) | ++ ((u32)regnum), ++ data->membase + MDIO_SINGLE_CMD); ++ ++ return hisi_gemac_mdio_wait_ready(data); ++} ++ ++static void hisi_gemac_external_phy_reset(struct hisi_gemac_mdio_data *data) ++{ ++ if (data->phy_rst) { ++ /* write 0 to cancel reset */ ++ reset_control_deassert(data->phy_rst); ++ msleep(50); ++ ++ /* HIFONE or 98cv200 use CRG register to reset phy */ ++ /* RST_BIT, write 0 to reset phy, write 1 to cancel reset */ ++ reset_control_assert(data->phy_rst); ++ ++ /* delay some time to ensure reset ok, ++ * this depends on PHY hardware feature ++ */ ++ msleep(50); ++ ++ /* write 0 to cancel reset */ ++ reset_control_deassert(data->phy_rst); ++ /* delay some time to ensure later MDIO access */ ++ msleep(50); ++ } else { ++#if defined(CONFIG_ARCH_HI3516A) ++#include ++#define GPIO_BASE_ETH_PHY_RESET 0x20140000 ++#define GPIO_BIT_ETH_PHY_RESET 1 ++ void __iomem *gpio_base; ++ u32 val; ++ ++ gpio_base = (void __iomem *)IO_ADDRESS(GPIO_BASE_ETH_PHY_RESET); ++ /* use GPIO to do hardware PHY reset */ ++ /* set direction */ ++ val = readl(gpio_base + 0x400); ++ val |= (1 << GPIO_BIT_ETH_PHY_RESET); ++ writel(val, gpio_base + 0x400); ++ ++ /* Firstly, set to 1 regardless of the value of this pin */ ++ writel(0xFF, gpio_base + (4 << GPIO_BIT_ETH_PHY_RESET)); ++ msleep(20); ++ ++ /* Set to 0 to reset, then sleep 200ms */ ++ writel(0x0, gpio_base + (4 << GPIO_BIT_ETH_PHY_RESET)); ++ msleep(20); ++ ++ /* then, cancel reset, and should sleep 50ms */ ++ writel(0xFF, gpio_base + (4 << GPIO_BIT_ETH_PHY_RESET)); ++ msleep(200); ++#endif ++ } ++} ++ ++static int hisi_gemac_mdio_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct mii_bus *bus; ++ struct hisi_gemac_mdio_data *data; ++ struct resource *res; ++ int ret; ++ ++ bus = mdiobus_alloc_size(sizeof(*data)); ++ if (!bus) ++ return -ENOMEM; ++ ++ bus->name = "hisi_gemac_mii_bus"; ++ bus->read = &hisi_gemac_mdio_read; ++ bus->write = &hisi_gemac_mdio_write; ++ snprintf(bus->id, MII_BUS_ID_SIZE, "%s", pdev->name); ++ bus->parent = &pdev->dev; ++ ++ data = bus->priv; ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ ret = -ENXIO; ++ goto err_out_free_mdiobus; ++ } ++ data->membase = devm_ioremap(&pdev->dev, res->start, ++ resource_size(res)); ++ if (!data->membase) { ++ ret = -ENOMEM; ++ goto err_out_free_mdiobus; ++ } ++ ++ data->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(data->clk)) { ++ ret = PTR_ERR(data->clk); ++ goto err_out_free_mdiobus; ++ } ++ ++ ret = clk_prepare_enable(data->clk); ++ if (ret) ++ goto err_out_free_mdiobus; ++ ++ data->phy_rst = devm_reset_control_get(&pdev->dev, "phy_reset"); ++ if (IS_ERR(data->phy_rst)) ++ data->phy_rst = NULL; ++ hisi_gemac_external_phy_reset(data); ++ ++ ret = of_mdiobus_register(bus, np); ++ if (ret) ++ goto err_out_disable_clk; ++ ++ platform_set_drvdata(pdev, bus); ++ ++ return 0; ++ ++err_out_disable_clk: ++ clk_disable_unprepare(data->clk); ++err_out_free_mdiobus: ++ mdiobus_free(bus); ++ return ret; ++} ++ ++static int hisi_gemac_mdio_remove(struct platform_device *pdev) ++{ ++ struct mii_bus *bus = platform_get_drvdata(pdev); ++ struct hisi_gemac_mdio_data *data = bus->priv; ++ ++ mdiobus_unregister(bus); ++ clk_disable_unprepare(data->clk); ++ mdiobus_free(bus); ++ ++ return 0; ++} ++ ++static const struct of_device_id hisi_gemac_mdio_dt_ids[] = { ++ { .compatible = "hisilicon,hisi-gemac-mdio" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, hisi_gemac_mdio_dt_ids); ++ ++static struct platform_driver hisi_gemac_mdio_driver = { ++ .probe = hisi_gemac_mdio_probe, ++ .remove = hisi_gemac_mdio_remove, ++ .driver = { ++ .name = "hisi-gemac-mdio", ++ .of_match_table = hisi_gemac_mdio_dt_ids, ++ }, ++}; ++ ++module_platform_driver(hisi_gemac_mdio_driver); ++ ++MODULE_DESCRIPTION("Hisilicon Gigabit Ethernet MAC MDIO interface driver"); ++MODULE_AUTHOR("Dongpo Li "); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c +index 32b555a..f02a86e 100644 +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -234,6 +234,53 @@ int phy_register_fixup_for_id(const char *bus_id, + } + EXPORT_SYMBOL(phy_register_fixup_for_id); + ++/** ++ * phy_unregister_fixup - remove a phy_fixup from the list ++ * @bus_id: A string matches fixup->bus_id (or PHY_ANY_ID) in phy_fixup_list ++ * @phy_uid: A phy id matches fixup->phy_id (or PHY_ANY_UID) in phy_fixup_list ++ * @phy_uid_mask: Applied to phy_uid and fixup->phy_uid before comparison ++ */ ++int phy_unregister_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask) ++{ ++ struct list_head *pos, *n; ++ struct phy_fixup *fixup; ++ int ret; ++ ++ ret = -ENODEV; ++ ++ mutex_lock(&phy_fixup_lock); ++ list_for_each_safe(pos, n, &phy_fixup_list) { ++ fixup = list_entry(pos, struct phy_fixup, list); ++ ++ if ((!strcmp(fixup->bus_id, bus_id)) && ++ ((fixup->phy_uid & phy_uid_mask) == ++ (phy_uid & phy_uid_mask))) { ++ list_del(&fixup->list); ++ kfree(fixup); ++ ret = 0; ++ break; ++ } ++ } ++ mutex_unlock(&phy_fixup_lock); ++ ++ return ret; ++} ++EXPORT_SYMBOL(phy_unregister_fixup); ++ ++/* Unregisters a fixup of any PHY with the UID in phy_uid */ ++int phy_unregister_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask) ++{ ++ return phy_unregister_fixup(PHY_ANY_ID, phy_uid, phy_uid_mask); ++} ++EXPORT_SYMBOL(phy_unregister_fixup_for_uid); ++ ++/* Unregisters a fixup of the PHY with id string bus_id */ ++int phy_unregister_fixup_for_id(const char *bus_id) ++{ ++ return phy_unregister_fixup(bus_id, PHY_ANY_UID, 0xffffffff); ++} ++EXPORT_SYMBOL(phy_unregister_fixup_for_id); ++ + /* Returns 1 if fixup matches phydev in bus_id and phy_uid. + * Fixups can be set to match any in one or more fields. + */ +diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig +index 6555eb7..51ad4a4 100644 +--- a/drivers/pci/Kconfig ++++ b/drivers/pci/Kconfig +@@ -133,3 +133,4 @@ config PCI_HYPERV + + source "drivers/pci/hotplug/Kconfig" + source "drivers/pci/host/Kconfig" ++source "drivers/pci/hipcie/Kconfig" +diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile +index 8db5079..955b899 100644 +--- a/drivers/pci/Makefile ++++ b/drivers/pci/Makefile +@@ -68,3 +68,4 @@ ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG + + # PCI host controller drivers + obj-y += host/ ++obj-$(CONFIG_HIPCIE) += hipcie/ +diff --git a/drivers/pci/hipcie/Kconfig b/drivers/pci/hipcie/Kconfig +new file mode 100644 +index 0000000..91ea72a +--- /dev/null ++++ b/drivers/pci/hipcie/Kconfig +@@ -0,0 +1,28 @@ ++menuconfig HIPCIE ++ bool "Hisilicon PCI Express support" ++ depends on PCI && (ARCH_HI3559AV100 || ARCH_HI3531A) ++ default y if PCI ++ default n if ! PCI ++ help ++ Hisilicon PCI Express support ++ Choose this selection to support PCI Express uses. ++ ++if HIPCIE ++ ++menu "PCI Express configs" ++ ++ ++config LIMIT_MAX_RD_REQ_SIZE ++ bool "limit pcie max read request size" ++ default y ++ depends on PCI && (ARCH_HI3559AV100 || ARCH_HI3531A) ++ help ++ The default max read request size of pcie device is 512 Byte. When pcie use ++ the card of pcie-to-sata to connect to the sata disk, with the default max read ++ request size value of 512 byte, would cause the low bandwidth of VDP. If you enable ++ the LIMIT_MAX_RD_REQ_SIZE config, the max read request size of pcie device would be ++ set to 128 byte, and the problem of VDP low band width also be avoided. ++ ++endmenu ++ ++endif +diff --git a/drivers/pci/hipcie/Makefile b/drivers/pci/hipcie/Makefile +new file mode 100644 +index 0000000..0455420 +--- /dev/null ++++ b/drivers/pci/hipcie/Makefile +@@ -0,0 +1,8 @@ ++ ++obj-$(CONFIG_HIPCIE) += hipcie.o ++ ++hipcie-objs := pcie.o ++ ++ifeq ($(CONFIG_PCI_DEBUG),y) ++ EXTRA_CFLAGS += -DPCIE_DEBUG ++endif +diff --git a/drivers/pci/hipcie/pci.h b/drivers/pci/hipcie/pci.h +new file mode 100644 +index 0000000..40a88b7 +--- /dev/null ++++ b/drivers/pci/hipcie/pci.h +@@ -0,0 +1,80 @@ ++/* ++ * arch/arm/include/asm/mach/pci.h ++ * ++ * Copyright (C) 2000 Russell King ++ * ++ * 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 __ASM_MACH_PCI_H ++#define __ASM_MACH_PCI_H ++ ++#include ++ ++struct pci_sys_data; ++struct pci_ops; ++struct pci_bus; ++struct device; ++ ++struct hw_pci { ++#ifdef CONFIG_PCI_DOMAINS ++ int domain; ++#endif ++ struct pci_ops *ops; ++ int nr_controllers; ++ void **private_data; ++ int (*setup)(int nr, struct pci_sys_data *); ++ struct pci_bus *(*scan)(int nr, struct pci_sys_data *); ++ void (*preinit)(void); ++ void (*postinit)(void); ++ u8 (*swizzle)(struct pci_dev *dev, u8 *pin); ++ int (*map_irq)(const struct pci_dev *dev, u8 slot, u8 pin); ++ resource_size_t (*align_resource)(struct pci_dev *dev, ++ const struct resource *res, ++ resource_size_t start, ++ resource_size_t size, ++ resource_size_t align); ++ void (*add_bus)(struct pci_bus *bus); ++ void (*remove_bus)(struct pci_bus *bus); ++}; ++ ++/* ++ * Per-controller structure ++ */ ++struct pci_sys_data { ++#ifdef CONFIG_PCI_DOMAINS ++ int domain; ++#endif ++ struct list_head node; ++ int busnr; /* primary bus number */ ++ u64 mem_offset; /* bus->cpu memory mapping offset */ ++ unsigned long io_offset; /* bus->cpu IO mapping offset */ ++ struct pci_bus *bus; /* PCI bus */ ++ struct list_head resources; /* root bus resources (apertures) */ ++ struct resource io_res; ++ char io_res_name[12]; ++ /* Bridge swizzling */ ++ u8 (*swizzle)(struct pci_dev *, u8 *); ++ /* IRQ mapping */ ++ int (*map_irq)(const struct pci_dev *, u8, u8); ++ /* Resource alignement requirements */ ++ resource_size_t (*align_resource)(struct pci_dev *dev, ++ const struct resource *res, ++ resource_size_t start, ++ resource_size_t size, ++ resource_size_t align); ++ void (*add_bus)(struct pci_bus *bus); ++ void (*remove_bus)(struct pci_bus *bus); ++ void *private_data; /* platform controller private data */ ++}; ++ ++void __weak pcibios_update_irq(struct pci_dev *dev, int irq) ++{ ++ dev_dbg(&dev->dev, "assigning IRQ %02d\n", irq); ++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); ++} ++ ++ ++#endif /* __ASM_MACH_PCI_H */ +diff --git a/drivers/pci/hipcie/pcie.c b/drivers/pci/hipcie/pcie.c +new file mode 100644 +index 0000000..c549f30 +--- /dev/null ++++ b/drivers/pci/hipcie/pcie.c +@@ -0,0 +1,640 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "pci.h" ++ ++#define PCIE_DBG_REG 1 ++#define PCIE_DBG_FUNC 2 ++#define PCIE_DBG_MODULE 3 ++ ++#define PCIE_DEBUG_LEVEL PCIE_DBG_MODULE ++ ++/*#define PCIE_DEBUG*/ ++#ifdef PCIE_DEBUG ++#define pcie_debug(level, str, arg...)\ ++ do {\ ++ if ((level) <= PCIE_DEBUG_LEVEL) {\ ++ pr_debug("%s->%d," str "\n", \ ++ __func__, __LINE__, ##arg);\ ++ } \ ++ } while (0) ++#else ++#define pcie_debug(level, str, arg...) ++#endif ++ ++#define pcie_assert(con)\ ++ do {\ ++ if (!(con)) {\ ++ pr_err("%s->%d,assert fail!\n", \ ++ __func__, __LINE__);\ ++ } \ ++ } while (0) ++ ++#define pcie_error(str, arg...)\ ++ pr_err("%s->%d" str "\n", __func__, __LINE__, ##arg) ++ ++ ++#define __256MB__ 0x10000000 ++#define __128MB__ 0x8000000 ++#define __4KB__ 0x1000 ++#define __8KB__ 0x2000 ++ ++enum pcie_sel { ++ /* ++ * No controller selected. ++ */ ++ pcie_sel_none, ++ /* ++ * PCIE0 selected. ++ */ ++ pcie0_x1_sel, ++ /* ++ * PCIE1 selected. ++ */ ++ pcie1_x1_sel ++}; ++ ++enum pcie_rc_sel { ++ pcie_controller_unselected, ++ pcie_controller_selected ++}; ++ ++enum pcie_controller { ++ pcie_controller_none = -1, ++ pcie_controller_0 = 0, ++ pcie_controller_1 = 1 ++}; ++ ++struct pcie_iatu { ++ unsigned int viewport; /* iATU Viewport Register */ ++ unsigned int region_ctrl_1; /* Region Control 1 Register */ ++ unsigned int region_ctrl_2; /* Region Control 2 Register */ ++ unsigned int lbar; /* Lower Base Address Register */ ++ unsigned int ubar; /* Upper Base Address Register */ ++ unsigned int lar; /* Limit Address Register */ ++ unsigned int ltar; /* Lower Target Address Register */ ++ unsigned int utar; /* Upper Target Address Register */ ++}; ++ ++#define MAX_IATU_PER_CTRLLER (6) ++ ++struct pcie_info { ++ /* ++ * Root bus number ++ */ ++ u8 root_bus_nr; ++ enum pcie_controller controller; ++ ++ /* ++ * Devices configuration space base ++ */ ++ unsigned long base_addr; ++ ++ /* ++ * RC configuration space base ++ */ ++ unsigned long conf_base_addr; ++}; ++ ++static struct pcie_info pcie_info[2] = { ++ {.root_bus_nr = -1,}, ++ {.root_bus_nr = -1,} ++}; ++ ++static int pcie_controllers_nr; ++ ++static unsigned int pcie0_sel = pcie_controller_unselected; ++static unsigned int pcie0_mem_space_size = 0x0; ++ ++static unsigned int pcie_errorvalue; ++ ++struct device_node *g_of_node = NULL; ++ ++static DEFINE_SPINLOCK(cw_lock); ++ ++#define PCIE0_MODE_SEL (1 << 0) ++#define PCIE1_MODE_SEL (1 << 1) ++ ++ ++#if defined(CONFIG_ARCH_HI3559AV100) ++#include "pcie_hi3559av100.c" ++#elif defined(CONFIG_ARCH_HI3531A) ++#include "pcie_hi3531a.c" ++#else ++#error You must have defined CONFIG_ARCH_HI35xx... ++#endif ++ ++/* ++ * PCIE memory size bootargs: pcie0_mem_size=0xa00000;pcie1_mem_size=0xa00000 ++ */ ++static int __init pcie0_mem_size_parser(char *str) ++{ ++ unsigned int size; ++ ++ if (kstrtoul(str, 16, (long *)&size) < 0) ++ return 0; ++ ++ /* if size >= 256MB, set default 256MB */ ++ if (size >= 0x10000000) ++ size = 0x10000000; ++ pcie0_mem_space_size = size; ++ ++ return 1; ++} ++__setup("pcie0_mem_size=", pcie0_mem_size_parser); ++ ++/* ++ * PCIE sel bootargs: pcie0_sel=x1 pcie1=x1 or pcie1=x2 ++ * Any other value after "pcieX_sel=" prefix ++ * will be treated as none controller selected. ++ * e.g. "pcie0_sel=none" will be treated as no PCIE0 selected. ++ */ ++static int __init pcie0_sel_parser(char *str) ++{ ++ if (strncasecmp(str, "x1", 2) == 0) ++ pcie0_sel = pcie0_x1_sel; ++ else ++ pcie0_sel = pcie_sel_none; ++ ++ return 1; ++} ++__setup("pcie0_sel=", pcie0_sel_parser); ++ ++static struct pcie_info *bus_to_info(int busnr) ++{ ++ int i = pcie_controllers_nr; ++ for (; i >= 0; i--) { ++ if (pcie_info[i].controller != pcie_controller_none ++ && pcie_info[i].root_bus_nr <= busnr ++ && pcie_info[i].root_bus_nr != -1) ++ return &pcie_info[i]; ++ } ++ ++ return NULL; ++} ++ ++ ++#define PCIE_CFG_BUS(busnr) ((busnr & 0xff) << 20) ++#define PCIE_CFG_DEV(devfn) ((devfn & 0xff) << 12) ++#define PCIE_CFG_REG(reg) (reg & 0xffc) /*set dword align*/ ++ ++static inline unsigned long to_pcie_address(struct pci_bus *bus, ++ unsigned int devfn, int where) ++{ ++ struct pcie_info *info = bus_to_info(bus->number); ++ unsigned long address = 0; ++ ++ if (unlikely(!info)) { ++ pcie_error( ++ "%s:Cannot find corresponding controller for appointed device!", __func__); ++ BUG(); ++ } ++ ++ address = info->base_addr + (PCIE_CFG_BUS(bus->number) ++ | PCIE_CFG_DEV(devfn) | PCIE_CFG_REG(where)); ++ ++ return address; ++} ++ ++static inline int is_pcie_link_up(struct pcie_info *info) ++{ ++ int i; ++ ++ for (i = 0; i < 10000; i++) { ++ if (__arch_check_pcie_link(info)) ++ break; ++ udelay(100); ++ } ++ ++ return (i < 10000); ++} ++ ++static int pcie_read_from_device(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 *value) ++{ ++ struct pcie_info *info = bus_to_info(bus->number); ++ unsigned int val; ++ void __iomem *addr; ++ int i = 0; ++ ++ if (unlikely(!info)) { ++ pcie_error( ++ "%s:Cannot find corresponding controller for appointed device!", __func__); ++ BUG(); ++ } ++ if (!is_pcie_link_up(info)) { ++ pcie_debug(PCIE_DBG_MODULE, "pcie %d not link up!", ++ info->controller); ++ return -1; ++ } ++ ++ addr = (void __iomem *)to_pcie_address(bus, devfn, where); ++ ++ val = readl(addr); ++ ++ i = 0; ++ while (i < 2000) { ++ __asm__ __volatile__("nop\n"); ++ i++; ++ } ++ ++ if (pcie_errorvalue == 1) { ++ pcie_errorvalue = 0; ++ val = 0xffffffff; ++ } ++ ++ if (size == 1) ++ *value = ((val >> ((where & 0x3) << 3)) & 0xff); ++ else if (size == 2) ++ *value = ((val >> ((where & 0x3) << 3)) & 0xffff); ++ else if (size == 4) ++ *value = val; ++ else{ ++ pcie_error("Unknown size(%d) for read ops", size); ++ BUG(); ++ } ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int pcie_read_from_dbi(struct pcie_info *info, unsigned int devfn, ++ int where, int size, u32 *value) ++{ ++ unsigned int val; ++ ++ /* ++ * For host-side config space read, ignore device func nr. ++ */ ++ if (devfn > 0) ++ return -EIO; ++ ++ val = (u32)readl((void *)(info->conf_base_addr + (where & (~0x3)))); ++ ++ if (1 == size) ++ *value = (val >> ((where & 0x3) << 3)) & 0xff; ++ else if (2 == size) ++ *value = (val >> ((where & 0x3) << 3)) & 0xffff; ++ else if (4 == size) ++ *value = val; ++ else { ++ pcie_error("Unknown size for config read operation!"); ++ BUG(); ++ } ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int pcie_read_conf(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 *value) ++{ ++ struct pcie_info *info = bus_to_info(bus->number); ++ int ret; ++ ++ if (unlikely(!info)) { ++ pcie_error( ++ "%s:Cannot find corresponding controller for appointed device!", __func__); ++ BUG(); ++ } ++ ++ if (bus->number == info->root_bus_nr) ++ ret = pcie_read_from_dbi(info, devfn, where, size, value); ++ else ++ ret = pcie_read_from_device(bus, devfn, where, size, value); ++ ++ pcie_debug(PCIE_DBG_REG, ++ "bus %d, devfn %d, where 0x%x, size 0x%x, value 0x%x", ++ bus->number & 0xff, devfn, where, size, *value); ++ ++ return ret; ++} ++ ++static int pcie_write_to_device(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 value) ++{ ++ struct pcie_info *info = bus_to_info(bus->number); ++ void __iomem *addr; ++ unsigned int org; ++ unsigned long flag; ++ ++ if (unlikely(!info)) { ++ pcie_error( ++ "%s:Cannot find corresponding controller for appointed device!", __func__); ++ BUG(); ++ } ++ ++ if (!is_pcie_link_up(info)) { ++ pcie_debug(PCIE_DBG_MODULE, "pcie %d not link up!", ++ info->controller); ++ return -1; ++ } ++ ++ spin_lock_irqsave(&cw_lock, flag); ++ ++ pcie_read_from_device(bus, devfn, where, 4, &org); ++ ++ addr = (void __iomem *)to_pcie_address(bus, devfn, where); ++ ++ if (size == 1) { ++ org &= (~(0xff << ((where & 0x3) << 3))); ++ org |= (value << ((where & 0x3) << 3)); ++ } else if (size == 2) { ++ org &= (~(0xffff << ((where & 0x3) << 3))); ++ org |= (value << ((where & 0x3) << 3)); ++ } else if (size == 4) { ++ org = value; ++ } else { ++ pcie_error("Unknown size(%d) for read ops", size); ++ BUG(); ++ } ++ writel(org, addr); ++ ++ spin_unlock_irqrestore(&cw_lock, flag); ++ ++ return PCIBIOS_SUCCESSFUL; ++ ++} ++ ++static int pcie_write_to_dbi(struct pcie_info *info, unsigned int devfn, ++ int where, int size, u32 value) ++{ ++ unsigned long flag; ++ unsigned int org; ++ ++ spin_lock_irqsave(&cw_lock, flag); ++ ++ if (pcie_read_from_dbi(info, devfn, where, 4, &org)) { ++ pcie_error("Cannot read from dbi! 0x%x:0x%x:0x%x!", ++ 0, devfn, where); ++ spin_unlock_irqrestore(&cw_lock, flag); ++ return -EIO; ++ } ++ if (size == 1) { ++ org &= (~(0xff << ((where & 0x3) << 3))); ++ org |= (value << ((where & 0x3) << 3)); ++ } else if (size == 2) { ++ org &= (~(0xffff << ((where & 0x3) << 3))); ++ org |= (value << ((where & 0x3) << 3)); ++ } else if (size == 4) { ++ org = value; ++ } else { ++ pcie_error("Unknown size(%d) for read ops", size); ++ BUG(); ++ } ++ writel(org, ((void __iomem *)info->conf_base_addr + (where & (~0x3)))); ++ ++ spin_unlock_irqrestore(&cw_lock, flag); ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int pcie_write_conf(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 value) ++{ ++ struct pcie_info *info = bus_to_info(bus->number); ++ ++ pcie_debug(PCIE_DBG_REG, ++ "bus %d, devfn %d, where 0x%x, size 0x%x, value 0x%x", ++ bus->number & 0xff, devfn, where, size, value); ++ ++ if (unlikely(!info)) { ++ pcie_error( ++ "%s:Cannot find corresponding controller for appointed device!", __func__); ++ BUG(); ++ } ++ ++ if (bus->number == info->root_bus_nr) ++ return pcie_write_to_dbi(info, devfn, where, size, value); ++ else ++ return pcie_write_to_device(bus, devfn, where, size, value); ++} ++ ++static struct pci_ops pcie_ops = { ++ .read = pcie_read_conf, ++ .write = pcie_write_conf, ++}; ++ ++void pci_set_max_rd_req_size(const struct pci_bus *bus) ++{ ++ struct pci_dev *dev; ++ struct pci_bus *child; ++ int pos; ++ unsigned short dev_contrl_reg_val = 0; ++ unsigned int max_rd_req_size = 0; ++ ++ list_for_each_entry(dev, &bus->devices, bus_list) { ++ ++ /* set device max read requset size*/ ++ pos = pci_find_capability(dev, PCI_CAP_ID_EXP); ++ if (pos) { ++ pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ++ &dev_contrl_reg_val); ++ max_rd_req_size = (dev_contrl_reg_val >> 12) & 0x7; ++ if (max_rd_req_size > 0x0) { ++ dev_contrl_reg_val &= ~(max_rd_req_size << 12); ++ pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, ++ dev_contrl_reg_val); ++ } ++ ++ } ++ } ++ ++ list_for_each_entry(dev, &bus->devices, bus_list) { ++ BUG_ON(!dev->is_added); ++ child = dev->subordinate; ++ if (child) ++ pci_set_max_rd_req_size(child); ++ } ++} ++ ++static struct hw_pci hipcie __initdata = { ++ .nr_controllers = 1, ++}; ++#ifdef CONFIG_ARM64 ++ ++static int pci_common_init(struct platform_device *pdev, struct hw_pci *hipcie) ++{ ++ struct device_node *dn = pdev->dev.of_node; ++ struct pcie_info *info; ++ struct pci_bus *bus; ++ resource_size_t io_addr; ++ int ret; ++ int pcie_contrl; ++ LIST_HEAD(res); ++ ++ of_property_read_u32(dn, "pcie_controller", &pcie_contrl); ++ ret = of_pci_get_host_bridge_resources(dn, 0, 0xff, &res, &io_addr); ++ if (ret) ++ return ret; ++ ++ ++ bus = pci_create_root_bus(&pdev->dev, 0, &pcie_ops, hipcie, &res); ++ if (!bus) ++ return -ENOMEM; ++ ++#ifdef CONFIG_LIMIT_MAX_RD_REQ_SIZE ++ pci_set_max_rd_req_size(bus); ++#endif ++ ++ pcie_info[pcie_contrl].root_bus_nr = bus->number; ++ info = bus_to_info(bus->number); ++ if (info != NULL) ++ __arch_config_iatu_tbl(info, NULL); ++ ++ pci_scan_child_bus(bus); ++ pci_assign_unassigned_bus_resources(bus); ++ pci_bus_add_devices(bus); ++ ++ platform_set_drvdata(pdev, hipcie); ++ ++ return 0; ++} ++#else ++static int pci_common_init_bvt(struct platform_device *pdev, struct hw_pci *hipcie) ++{ ++ struct device_node *dn = pdev->dev.of_node; ++ struct pcie_info *info; ++ struct pci_bus *bus; ++ resource_size_t io_addr; ++ int ret; ++ int bus_start; ++ int pcie_contrl; ++ ++ LIST_HEAD(res); ++ ++ of_property_read_u32(dn, "pcie_controller", &pcie_contrl); ++ if (pcie_contrl == 0) ++ bus_start = 0; ++ else ++ bus_start = 2; ++ ++ ret = of_pci_get_host_bridge_resources(dn, bus_start, 0xff, &res, &io_addr); ++ if (ret) ++ return ret; ++ ++ bus = pci_create_root_bus(&pdev->dev, bus_start, &pcie_ops, hipcie, &res); ++ if (!bus) ++ return -ENOMEM; ++ ++#ifdef CONFIG_LIMIT_MAX_RD_REQ_SIZE ++ pci_set_max_rd_req_size(bus); ++#endif ++ ++ pcie_info[pcie_contrl].root_bus_nr = bus->number; ++ info = bus_to_info(bus->number); ++ if (info != NULL) { ++ __arch_config_iatu_tbl(info, NULL); ++ } ++ ++ pci_scan_child_bus(bus); ++ pci_assign_unassigned_bus_resources(bus); ++ pci_bus_add_devices(bus); ++ ++ platform_set_drvdata(pdev, hipcie); ++ ++ return 0; ++ ++} ++#endif ++ ++static int __init pcie_init(struct platform_device *pdev) ++{ ++ g_of_node = pdev->dev.of_node; ++ if (!g_of_node) { ++ pr_err("get node from dts failed! controller:%d\n", pcie_controllers_nr); ++ return -EIO; ++ } ++ ++ of_property_read_u32(g_of_node, "pcie_controller", &pcie_controllers_nr); ++ ++ if (__arch_pcie_info_setup(pcie_info, &pcie_controllers_nr)) ++ return -EIO; ++ ++ if (__arch_pcie_sys_init(pcie_info)) ++ goto pcie_init_err; ++ hipcie.nr_controllers = pcie_controllers_nr; ++ pr_err("Number of PCIe controllers: %d\n", ++ hipcie.nr_controllers); ++ ++#ifdef CONFIG_ARM64 ++ pci_common_init(pdev, &hipcie); ++#else ++ pci_common_init_bvt(pdev, &hipcie); ++#endif ++ return 0; ++pcie_init_err: ++ __arch_pcie_info_release(pcie_info); ++ ++ return -EIO; ++} ++ ++static int __exit pcie_uinit(struct platform_device *pdev) ++{ ++ __arch_pcie_info_release(pcie_info); ++ return 0; ++} ++ ++#include ++#include ++ ++int hisi_pcie_plat_driver_probe(struct platform_device *pdev) ++{ ++ return 0; ++} ++int hisi_pcie_plat_driver_remove(struct platform_device *pdev) ++{ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++int hisi_pcie_plat_driver_suspend(struct device *dev) ++{ ++ __arch_pcie_sys_exit(); ++ return 0; ++} ++ ++int hisi_pcie_plat_driver_resume(struct device *dev) ++{ ++ return __arch_pcie_sys_init(pcie_info); ++} ++ ++const struct dev_pm_ops hisi_pcie_pm_ops = { ++ .suspend = NULL, ++ .suspend_noirq = hisi_pcie_plat_driver_suspend, ++ .resume = NULL, ++ .resume_noirq = hisi_pcie_plat_driver_resume ++}; ++ ++#define HISI_PCIE_PM_OPS (&hisi_pcie_pm_ops) ++#else ++#define HISI_PCIE_PM_OPS NULL ++#endif ++ ++#define PCIE_RC_DRV_NAME "hisi pcie root complex" ++ ++ ++static const struct of_device_id hisi_pcie_match_table[] = { ++ {.compatible = "hisilicon,hisi-pcie",}, ++ {}, ++}; ++ ++static struct platform_driver hisi_pcie_driver = { ++ .driver = { ++ .name = "hisi-pcie", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(hisi_pcie_match_table), ++ }, ++ .probe = pcie_init, ++}; ++module_platform_driver(hisi_pcie_driver); ++ ++MODULE_DESCRIPTION("Hisilicon PCI-Express Root Complex driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/pci/hipcie/pcie_hi3531a.c b/drivers/pci/hipcie/pcie_hi3531a.c +new file mode 100644 +index 0000000..d62a4a9 +--- /dev/null ++++ b/drivers/pci/hipcie/pcie_hi3531a.c +@@ -0,0 +1,606 @@ ++ ++#include "pcie_hi3531a.h" ++ ++static void * __iomem misc_ctrl_virt; ++static int __arch_pcie_info_setup(struct pcie_info *info, int *controllers_nr); ++static int __arch_pcie_sys_init(struct pcie_info *info); ++static void __arch_pcie_info_release(struct pcie_info *info); ++ ++struct pcie_iatu pcie0_iatu_table[] = { ++ { ++ .viewport = 0, ++ .region_ctrl_1 = 0x00000004, ++ .region_ctrl_2 = 0x90000000, ++ .lbar = PCIE0_EP_CONF_BASE + (1<<20), ++ .ubar = 0x0, ++ .lar = PCIE0_EP_CONF_BASE + (2<<20) - 1, ++ .ltar = 0x01000000, ++ .utar = 0x00000000, ++ }, ++ { ++ .viewport = 1, ++ .region_ctrl_1 = 0x00000005, ++ .region_ctrl_2 = 0x90000000, ++ .lbar = PCIE0_EP_CONF_BASE + (2<<20), ++ .ubar = 0x0, ++ .lar = PCIE0_EP_CONF_BASE + (__128MB__ - 1), ++ .ltar = 0x02000000, ++ .utar = 0x00000000, ++ }, ++}; ++ ++struct pcie_iatu pcie1_iatu_table[] = { ++ { ++ .viewport = 0, ++ .region_ctrl_1 = 0x00000004, ++ .region_ctrl_2 = 0x90000000, ++ .lbar = PCIE1_EP_CONF_BASE, ++ .ubar = 0x0, ++ .lar = PCIE1_EP_CONF_BASE + (1<<20) - 1, ++ .ltar = 0x01000000, ++ .utar = 0x00000000, ++ }, ++ { ++ .viewport = 1, ++ .region_ctrl_1 = 0x00000005, ++ .region_ctrl_2 = 0x90000000, ++ .lbar = PCIE1_EP_CONF_BASE, ++ .ubar = 0x0, ++ .lar = PCIE1_EP_CONF_BASE + (__128MB__ - 1), ++ .ltar = 0x02000000, ++ .utar = 0x00000000, ++ }, ++}; ++ ++static void __arch_config_iatu_tbl(struct pcie_info *info, ++ struct pci_sys_data *sys) ++{ ++ int i; ++ void __iomem *config_base; ++ struct pcie_iatu *ptable; ++ int table_size; ++ unsigned int ctl1_lbar_offset; ++ ++ config_base = (void __iomem *)info->conf_base_addr; ++ if (pcie_controller_0 == info->controller) { ++ ptable = pcie0_iatu_table; ++ table_size = ARRAY_SIZE(pcie0_iatu_table); ++ } ++ ++ if (pcie_controller_1 == info->controller) { ++ ptable = pcie1_iatu_table; ++ table_size = ARRAY_SIZE(pcie1_iatu_table); ++ ++ ++ ctl1_lbar_offset = (info->root_bus_nr + 1) << 20; ++ ptable->lbar |= ctl1_lbar_offset; ++ ptable->lar |= ctl1_lbar_offset; ++ ++ ctl1_lbar_offset = (info->root_bus_nr + 2) << 20; ++ (ptable + 1)->lbar |= ctl1_lbar_offset; ++ } ++ ++ for (i = 0; i < table_size; i++) { ++ writel((ptable + i)->viewport, config_base + 0x900); ++ writel((ptable + i)->lbar, config_base + 0x90c); ++ writel((ptable + i)->ubar, config_base + 0x910); ++ writel((ptable + i)->lar, config_base + 0x914); ++ writel((ptable + i)->ltar, config_base + 0x918); ++ writel((ptable + i)->utar, config_base + 0x91c); ++ writel((ptable + i)->region_ctrl_1, config_base + 0x904); ++ writel((ptable + i)->region_ctrl_2, config_base + 0x908); ++ } ++ ++} ++ ++static inline int __arch_check_pcie_link(struct pcie_info *info) ++{ ++ int val; ++ ++ if (pcie_controller_0 == info->controller) { ++ val = readl(misc_ctrl_virt + PCIE0_SYS_STATE0); ++ return ((val & (1 << PCIE_XMLH_LINK_UP)) ++ && (val & (1 << PCIE_RDLH_LINK_UP))) ? 1 : 0; ++ } ++ ++ if (pcie_controller_1 == info->controller) { ++ val = readl(misc_ctrl_virt + PCIE1_SYS_STATE0); ++ return ((val & (1 << PCIE_XMLH_LINK_UP)) ++ && (val & (1 << PCIE_RDLH_LINK_UP))) ? 1 : 0; ++ } ++ ++ return 0; ++} ++ ++/* ++ * ret: ++ */ ++static int __arch_pcie_info_set(struct pcie_info *info, int controller) ++{ ++ unsigned int pcie_mem_size; ++ unsigned int pcie_cfg_size; ++ unsigned int pcie_dbi_base; ++ unsigned int pcie_ep_conf_base; ++ unsigned int pcie_contrl; ++ ++ /* Get pcie deice memory size */ ++ of_property_read_u32(g_of_node, "dev_mem_size", &pcie_mem_size); ++ ++ /* Get pcie config space size*/ ++ of_property_read_u32(g_of_node, "dev_conf_size", &pcie_cfg_size); ++ ++ /* Get pcie dib base address */ ++ of_property_read_u32(g_of_node, "pcie_dbi_base", &pcie_dbi_base); ++ ++ /* Get pcie device config base address */ ++ of_property_read_u32(g_of_node, "ep_conf_base", &pcie_ep_conf_base); ++ ++ if ((pcie_mem_size > __128MB__) || (pcie_cfg_size > __128MB__)) { ++ pcie_error( ++ "Invalid parameter: pcie mem size[0x%x], pcie cfg size[0x%x]!", ++ pcie_mem_size, pcie_cfg_size); ++ return -EINVAL; ++ } ++ ++ of_property_read_u32(g_of_node, "pcie_controller", &pcie_contrl); ++ info->controller = pcie_contrl; ++ ++ /* RC configuration space */ ++ info->conf_base_addr = (unsigned int)ioremap_nocache(pcie_dbi_base, ++ __4KB__); ++ if (!info->conf_base_addr) { ++ pcie_error("Address mapping for RC dbi failed!"); ++ return -EIO; ++ } ++ ++ /* Configuration space for all EPs */ ++ info->base_addr = (unsigned int)ioremap_nocache(pcie_ep_conf_base, ++ pcie_cfg_size); ++ if (!info->base_addr) { ++ iounmap((void *)info->conf_base_addr); ++ pcie_error("Address mapping for EPs cfg failed!"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static void __arch_pcie_info_clr(struct pcie_info *info) ++{ ++ if (info->base_addr) ++ iounmap((void *)info->base_addr); ++ ++ if (info->conf_base_addr) ++ iounmap((void *)info->conf_base_addr); ++} ++ ++static int __arch_get_port_nr(void) ++{ ++ unsigned int val, mode; ++ int nr; ++ ++ val = readl((void *)PCIE_SYS_STAT); ++ mode = (val >> 12) & 0xf; ++ switch (mode) { ++ case 0x1: ++ case 0x2: ++ case 0x9: ++ case 0xa: ++ nr = 1; ++ break; ++ ++ case 0x3: ++ case 0x4: ++ case 0xb: ++ case 0xc: ++ nr = 2; ++ break; ++ ++ default: ++ nr = 0; ++ break; ++ } ++ ++ return nr; ++} ++ ++static int __arch_pcie_info_setup(struct pcie_info *info, int *controllers_nr) ++{ ++ int nr; ++ ++ misc_ctrl_virt = (void *)IO_ADDRESS(MISC_CTRL_BASE); ++ ++ nr = __arch_get_port_nr(); ++ if (!nr) { ++ pr_err("Pcie port number: 0\n"); ++ return -EINVAL; ++ } ++ ++ /* If only one pcie, it couldn't be pcie1, so don't init pcie1 */ ++ if (nr == 1 && *controllers_nr == 1) ++ return -EINVAL; ++ ++ if (__arch_pcie_info_set(&info[*controllers_nr], *controllers_nr)) { ++ pr_err("__arch_pcie_info_set failed, func:%s, line:%d\n", __func__, __LINE__); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static void __arch_pcie_info_release(struct pcie_info *info) ++{ ++ int nr; ++ for (nr = 0; nr < pcie_controllers_nr; nr++) ++ __arch_pcie_info_clr(&info[nr]); ++} ++ ++void set_pcie_phy0_porta(void *crg_base) ++{ ++ unsigned int val; ++ ++ writel(0x41a, misc_ctrl_virt + MISC_CTRL77); ++ writel(0x45a, misc_ctrl_virt + MISC_CTRL77); ++ writel(0x41a, misc_ctrl_virt + MISC_CTRL77); ++ writel(0x0, misc_ctrl_virt + MISC_CTRL77); ++ ++ ++ writel(0x303, misc_ctrl_virt + MISC_CTRL77); ++ writel(0x343, misc_ctrl_virt + MISC_CTRL77); ++ writel(0x303, misc_ctrl_virt + MISC_CTRL77); ++ writel(0x0, misc_ctrl_virt + MISC_CTRL77); ++ ++ val = readl(crg_base + REG_CRG72); ++ val &= ~(0x1 << 2); ++ writel(val, crg_base + REG_CRG72); ++} ++ ++void set_pice_phy0_portb(void *crg_base) ++{ ++ unsigned int val; ++ ++ writel(0x43a, misc_ctrl_virt + MISC_CTRL77); ++ writel(0x47a, misc_ctrl_virt + MISC_CTRL77); ++ writel(0x43a, misc_ctrl_virt + MISC_CTRL77); ++ writel(0x0, misc_ctrl_virt + MISC_CTRL77); ++ ++ ++ writel(0x323, misc_ctrl_virt + MISC_CTRL77); ++ writel(0x363, misc_ctrl_virt + MISC_CTRL77); ++ writel(0x323, misc_ctrl_virt + MISC_CTRL77); ++ writel(0x0, misc_ctrl_virt + MISC_CTRL77); ++ ++ val = readl(crg_base + REG_CRG72); ++ val &= ~(0x1 << 3); ++ writel(val, crg_base + REG_CRG72); ++} ++ ++void set_pcie_phy1_porta(void *crg_base) ++{ ++ unsigned int val; ++ ++ writel(0x41a, misc_ctrl_virt + MISC_CTRL78); ++ writel(0x45a, misc_ctrl_virt + MISC_CTRL78); ++ writel(0x41a, misc_ctrl_virt + MISC_CTRL78); ++ writel(0x0, misc_ctrl_virt + MISC_CTRL78); ++ ++ writel(0x303, misc_ctrl_virt + MISC_CTRL78); ++ writel(0x343, misc_ctrl_virt + MISC_CTRL78); ++ writel(0x303, misc_ctrl_virt + MISC_CTRL78); ++ writel(0x0, misc_ctrl_virt + MISC_CTRL78); ++ ++ val = readl(crg_base + REG_CRG72); ++ val &= ~(0x1 << 10); ++ writel(val, crg_base + REG_CRG72); ++} ++ ++void set_pcie_phy1_portb(void *crg_base) ++{ ++ unsigned int val; ++ ++ writel(0x43a, misc_ctrl_virt + MISC_CTRL78); ++ writel(0x47a, misc_ctrl_virt + MISC_CTRL78); ++ writel(0x43a, misc_ctrl_virt + MISC_CTRL78); ++ writel(0x0, misc_ctrl_virt + MISC_CTRL78); ++ ++ writel(0x323, misc_ctrl_virt + MISC_CTRL78); ++ writel(0x363, misc_ctrl_virt + MISC_CTRL78); ++ writel(0x323, misc_ctrl_virt + MISC_CTRL78); ++ writel(0x0, misc_ctrl_virt + MISC_CTRL78); ++ ++ val = readl(crg_base + REG_CRG72); ++ val &= ~(0x1 << 11); ++ writel(val, crg_base + REG_CRG72); ++} ++ ++void set_pcie0_para(void *crg_base) ++{ ++ unsigned int val; ++ unsigned int flag; ++ ++ val = readl((void *)PCIE_SYS_STAT); ++ flag = (val >> 12) & 0xf; ++ ++ switch(flag) { ++ case 0x1: ++ case 0x3: ++ case 0x9: ++ case 0xb: ++ set_pcie_phy0_porta(crg_base); ++ ++ val = readl(crg_base + REG_CRG73); ++ val |= (0x1 << 7); ++ writel(val, crg_base + REG_CRG73); ++ ++ break; ++ case 0x2: ++ case 0xa: ++ case 0xc: ++ case 0x4: ++ set_pcie_phy0_porta(crg_base); ++ set_pice_phy0_portb(crg_base); ++ ++ val = readl(crg_base + REG_CRG73); ++ val |= (0x1 << 7); ++ writel(val, crg_base + REG_CRG73); ++ ++ break; ++ default: ++ break; ++ ++ } ++} ++ ++void set_pcie1_para(void *crg_base) ++{ ++ unsigned int val; ++ unsigned int flag; ++ ++ val = readl((void *)PCIE_SYS_STAT); ++ flag = (val >> 12) & 0xf; ++ ++ switch(flag) { ++ case 0x3: ++ case 0xb: ++ set_pice_phy0_portb(crg_base); ++ ++ val = readl(crg_base + REG_CRG73); ++ val |= (0x1 << 15); ++ writel(val, crg_base + REG_CRG73); ++ ++ break; ++ case 0xc: ++ set_pcie_phy1_porta(crg_base); ++ ++ val = readl(crg_base + REG_CRG73); ++ val |= (0x1 << 15); ++ writel(val, crg_base + REG_CRG73); ++ ++ break; ++ ++ case 0x4: ++ set_pcie_phy1_porta(crg_base); ++ set_pcie_phy1_portb(crg_base); ++ ++ val = readl(crg_base + REG_CRG73); ++ val |= (0x1 << 15); ++ writel(val, crg_base + REG_CRG73); ++ ++ break; ++ default: ++ break; ++ ++ } ++} ++ ++static void __arch_pcie_sys_config(struct pcie_info *info) ++{ ++ unsigned int val; ++ void *dbi_base = (void *)info->conf_base_addr; ++ void *crg_base = (void *)IO_ADDRESS(PERI_CRG_BASE); ++ ++ if (pcie_controller_0 == info->controller) { ++ /* ++ * Disable PCIE ++ */ ++ val = readl(misc_ctrl_virt + PCIE0_SYS_CTRL7); ++ val &= (~(1 << PCIE_APP_LTSSM_ENBALE)); ++ writel(val, misc_ctrl_virt + PCIE0_SYS_CTRL7); ++ ++ /* ++ * Reset ++ */ ++ val = readl(crg_base + PERI_CRG73); ++ val |= (1 << PCIE0_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG73); ++ ++ /* ++ * Retreat from the reset state ++ */ ++ udelay(500); ++ val = readl(crg_base + PERI_CRG73); ++ val &= ~(1 << PCIE0_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG73); ++ mdelay(10); ++ ++ /* Set pcie phy0 parameter */ ++ set_pcie0_para(crg_base); ++ mdelay(10); ++ ++ /* ++ * PCIE RC work mode ++ */ ++ val = readl(misc_ctrl_virt + PCIE0_SYS_CTRL0); ++ val &= (~(0xf << PCIE_DEVICE_TYPE)); ++ val |= (PCIE_WM_RC << PCIE_DEVICE_TYPE); ++ writel(val, misc_ctrl_virt + PCIE0_SYS_CTRL0); ++ ++ /* ++ * Enable clk ++ */ ++ val = readl(crg_base + PERI_CRG73); ++ val |= ((1 << PCIE0_X2_BUS_CKEN) ++ | (1 << PCIE0_X2_SYS_CKEN) ++ | (1 << PCIE0_X2_PIPE_CKEN) ++ | (1 << PCIE0_X2_AUX_CKEN)); ++ writel(val, crg_base + PERI_CRG73); ++ mdelay(10); ++ ++ val = readl(dbi_base + LINK_CTRL2_STATUS2); ++ val &= ~((0xF << 12) | (0x7 << 7) | (0x1 << 6)); ++ val |= ((0x1 << 12) | (0x1 << 7) | (0x1 << 6)); ++ writel(val, dbi_base + LINK_CTRL2_STATUS2); ++ ++ /* ++ * Enable controller ++ */ ++ val = readl(misc_ctrl_virt + PCIE0_SYS_CTRL7); ++ val |= (1 << PCIE_APP_LTSSM_ENBALE); ++ writel(val, misc_ctrl_virt + PCIE0_SYS_CTRL7); ++ udelay(1000); ++ ++ } ++ ++ if (pcie_controller_1 == info->controller) { ++ /* ++ * Disable PCIE ++ */ ++ val = readl(misc_ctrl_virt + PCIE1_SYS_CTRL7); ++ val &= (~(1 << PCIE_APP_LTSSM_ENBALE)); ++ writel(val, misc_ctrl_virt + PCIE1_SYS_CTRL7); ++ ++ /* ++ * Reset ++ */ ++ val = readl(crg_base + PERI_CRG73); ++ val |= (1 << PCIE1_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG73); ++ ++ /* ++ * Retreat from the reset state ++ */ ++ udelay(500); ++ val = readl(crg_base + PERI_CRG73); ++ val &= ~(1 << PCIE1_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG73); ++ mdelay(10); ++ ++ /* Set pcie phy1 parameter */ ++ set_pcie1_para(crg_base); ++ mdelay(10); ++ ++ /* ++ * PCIE RC work mode ++ */ ++ val = readl(misc_ctrl_virt + PCIE1_SYS_CTRL0); ++ val &= (~(0xf << PCIE_DEVICE_TYPE)); ++ val |= (PCIE_WM_RC << PCIE_DEVICE_TYPE); ++ writel(val, misc_ctrl_virt + PCIE1_SYS_CTRL0); ++ ++ /* ++ * Enable clk ++ */ ++ val = readl(crg_base + PERI_CRG73); ++ val |= ((1 << PCIE1_X2_BUS_CKEN) ++ | (1 << PCIE1_X2_SYS_CKEN) ++ | (1 << PCIE1_X2_PIPE_CKEN) ++ | (1 << PCIE1_X2_AUX_CKEN)); ++ writel(val, crg_base + PERI_CRG73); ++ ++ val = readl(dbi_base + LINK_CTRL2_STATUS2); ++ val &= ~((0xF << 12) | (0x7 << 7) | (0x1 << 6)); ++ val |= ((0x1 << 12) | (0x1 << 7) | (0x1 << 6)); ++ writel(val, dbi_base + LINK_CTRL2_STATUS2); ++ ++ /* ++ * Enable controller ++ */ ++ val = readl(misc_ctrl_virt + PCIE1_SYS_CTRL7); ++ val |= (1 << PCIE_APP_LTSSM_ENBALE); ++ writel(val, misc_ctrl_virt + PCIE1_SYS_CTRL7); ++ udelay(1000); ++ } ++ ++ /* ++ * Set PCIE controller class code to be PCI-PCI bridge device ++ */ ++ val = readl(dbi_base + PCI_CLASS_REVISION); ++ val &= ~(0xffffff00); ++ val |= (0x60400 << 8); ++ writel(val, dbi_base + PCI_CLASS_REVISION); ++ udelay(1000); ++ ++ val = readl(dbi_base + PCI_COMMAND); ++ val |= 7; ++ writel(val, dbi_base + PCI_COMMAND); ++} ++ ++static int __arch_pcie_sys_init(struct pcie_info *info) ++{ ++ __arch_pcie_sys_config(&info[pcie_controllers_nr]); ++ ++ return 0; ++} ++ ++static void __arch_pcie_sys_exit(void) ++{ ++ void *crg_base = (void *)IO_ADDRESS(PERI_CRG_BASE); ++ unsigned int val; ++ ++ /* ++ * Disable PCIE0 ++ */ ++ val = readl(misc_ctrl_virt + PCIE0_SYS_CTRL7); ++ val &= (~(1 << PCIE_APP_LTSSM_ENBALE)); ++ writel(val, misc_ctrl_virt + PCIE0_SYS_CTRL7); ++ ++ /* ++ * Reset PCIE0 ++ */ ++ val = readl(crg_base + PERI_CRG73); ++ val |= (1 << PCIE0_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG73); ++ ++ udelay(1000); ++ ++ /* ++ * Disable clk of PCIE0 ++ */ ++ val = readl(crg_base + PERI_CRG73); ++ val &= (~(1 << PCIE0_X2_AUX_CKEN)); ++ val &= (~(1 << PCIE0_X2_PIPE_CKEN)); ++ val &= (~(1 << PCIE0_X2_SYS_CKEN)); ++ val &= (~(1 << PCIE0_X2_BUS_CKEN)); ++ writel(val, crg_base + PERI_CRG73); ++ ++ udelay(1000); ++ ++ /* ++ * Disable PCIE1 ++ */ ++ val = readl(misc_ctrl_virt + PCIE1_SYS_CTRL7); ++ val &= (~(1 << PCIE_APP_LTSSM_ENBALE)); ++ writel(val, misc_ctrl_virt + PCIE1_SYS_CTRL7); ++ ++ /* ++ * Reset PCIE1 ++ */ ++ val = readl(crg_base + PERI_CRG73); ++ val |= (1 << PCIE1_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG73); ++ ++ udelay(1000); ++ ++ /* ++ * Disable clk of PCIE1 ++ */ ++ val = readl(crg_base + PERI_CRG73); ++ val &= (~(1 << PCIE1_X2_AUX_CKEN)); ++ val &= (~(1 << PCIE1_X2_PIPE_CKEN)); ++ val &= (~(1 << PCIE1_X2_SYS_CKEN)); ++ val &= (~(1 << PCIE1_X2_BUS_CKEN)); ++ writel(val, crg_base + PERI_CRG73); ++ ++ udelay(1000); ++} ++ +diff --git a/drivers/pci/hipcie/pcie_hi3531a.h b/drivers/pci/hipcie/pcie_hi3531a.h +new file mode 100644 +index 0000000..8223514 +--- /dev/null ++++ b/drivers/pci/hipcie/pcie_hi3531a.h +@@ -0,0 +1,79 @@ ++#ifndef __HISI_PCIE_H__ ++#define __HISI_PCIE_H__ ++ ++#define MISC_CTRL_BASE 0x12120000 ++#define PERI_CRG_BASE 0x12040000 ++#define PCIE_SYS_STAT IO_ADDRESS(0x1205008C) ++ ++#define PCIE0_PARA_REG IO_ADDRESS(0x12120134) ++#define PCIE1_PARA_REG IO_ADDRESS(0x12120138) ++ ++#define PCIE0_MEM_BASE 0x28000000 ++#define PCIE0_EP_CONF_BASE 0x20000000 ++#define PCIE0_DBI_BASE 0x11020000 ++#define PCIE_DBI_BASE PCIE0_MEM_BASE ++ ++#define PCIE1_MEM_BASE 0x38000000 ++#define PCIE1_EP_CONF_BASE 0x30000000 ++#define PCIE1_DBI_BASE 0x11030000 ++ ++#define PERI_CRG73 0x124 ++ ++#define PCIE0_X2_SRST_REQ 6 ++#define PCIE0_X2_AUX_CKEN 3 ++#define PCIE0_X2_PIPE_CKEN 2 ++#define PCIE0_X2_SYS_CKEN 1 ++#define PCIE0_X2_BUS_CKEN 0 ++ ++#define PCIE1_X2_SRST_REQ 14 ++#define PCIE1_X2_AUX_CKEN 11 ++#define PCIE1_X2_PIPE_CKEN 10 ++#define PCIE1_X2_SYS_CKEN 9 ++#define PCIE1_X2_BUS_CKEN 8 ++ ++#define PCIE0_SYS_CTRL0 0xA0 ++#define PCIE1_SYS_CTRL0 0xE4 ++#define PCIE_DEVICE_TYPE 28 ++#define PCIE_WM_EP 0x0 ++#define PCIE_WM_LEGACY 0x1 ++#define PCIE_WM_RC 0x4 ++ ++#define PCIE0_SYS_CTRL7 0xBC ++#define PCIE1_SYS_CTRL7 0x100 ++#define PCIE_APP_LTSSM_ENBALE 11 ++ ++#define PCIE0_SYS_STATE0 0xD0 ++#define PCIE1_SYS_STATE0 0x114 ++#define PCIE_XMLH_LINK_UP 15 ++#define PCIE_RDLH_LINK_UP 5 ++ ++#define PCIE0_IRQ_INTA 94 ++#define PCIE0_IRQ_INTB 95 ++#define PCIE0_IRQ_INTC 96 ++#define PCIE0_IRQ_INTD 97 ++#define PCIE0_IRQ_EDMA 98 ++#define PCIE0_IRQ_MSI 99 ++#define PCIE0_IRQ_LINK_DOWN 100 ++ ++#define PCIE1_IRQ_INTA 101 ++#define PCIE1_IRQ_INTB 102 ++#define PCIE1_IRQ_INTC 103 ++#define PCIE1_IRQ_INTD 104 ++#define PCIE1_IRQ_EDMA 105 ++#define PCIE1_IRQ_MSI 106 ++#define PCIE1_IRQ_LINK_DOWN 107 ++ ++#define PCIE_INTA_PIN 1 ++#define PCIE_INTB_PIN 2 ++#define PCIE_INTC_PIN 3 ++#define PCIE_INTD_PIN 4 ++ ++#define LINK_CTRL2_STATUS2 0xA0 ++ ++#define MISC_CTRL77 0x0134 ++#define MISC_CTRL78 0x0138 ++ ++#define REG_CRG72 0x0120 ++#define REG_CRG73 0x0124 ++ ++#endif +diff --git a/drivers/pci/hipcie/pcie_hi3559av100.c b/drivers/pci/hipcie/pcie_hi3559av100.c +new file mode 100644 +index 0000000..4b2fa5b +--- /dev/null ++++ b/drivers/pci/hipcie/pcie_hi3559av100.c +@@ -0,0 +1,304 @@ ++#ifndef CONFIG_ARM64 ++#include ++#endif ++#include ++#include "pcie_hi3559av100.h" ++ ++static void *dbi_base; ++static int __arch_pcie_info_setup(struct pcie_info *info, int *controllers_nr); ++static int __arch_pcie_sys_init(struct pcie_info *info); ++static void __arch_pcie_info_release(struct pcie_info *info); ++ ++struct pcie_iatu iatu_table[] = { ++ { ++ .viewport = 0, ++ .region_ctrl_1 = 0x00000004, ++ .region_ctrl_2 = 0x90000000, ++ .lbar = PCIE_EP_CONF_BASE + (1<<20), ++ .ubar = 0x0, ++ .lar = PCIE_EP_CONF_BASE + (2<<20) - 1, ++ .ltar = 0x01000000, ++ .utar = 0x00000000, ++ }, ++ { ++ .viewport = 1, ++ .region_ctrl_1 = 0x00000005, ++ .region_ctrl_2 = 0x90000000, ++ .lbar = PCIE_EP_CONF_BASE + (2<<20), ++ .ubar = 0x0, ++ .lar = PCIE_EP_CONF_BASE + (__128MB__ - 1), ++ .ltar = 0x02000000, ++ .utar = 0x00000000, ++ }, ++}; ++ ++static void __arch_config_iatu_tbl(struct pcie_info *info, ++ struct pci_sys_data *sys) ++{ ++ int i; ++ void __iomem *config_base = (void __iomem *)info->conf_base_addr; ++ struct pcie_iatu *ptable = iatu_table; ++ int table_size = ARRAY_SIZE(iatu_table); ++ ++ for (i = 0; i < table_size; i++) { ++ writel((ptable + i)->viewport, config_base + 0x900); ++ writel((ptable + i)->lbar, config_base + 0x90c); ++ writel((ptable + i)->ubar, config_base + 0x910); ++ writel((ptable + i)->lar, config_base + 0x914); ++ writel((ptable + i)->ltar, config_base + 0x918); ++ writel((ptable + i)->utar, config_base + 0x91c); ++ writel((ptable + i)->region_ctrl_1, config_base + 0x904); ++ writel((ptable + i)->region_ctrl_2, config_base + 0x908); ++ } ++ ++} ++ ++static inline int __arch_check_pcie_link(struct pcie_info *info) ++{ ++ int val; ++ ++ val = readl(dbi_base + PCIE_SYS_STATE0); ++ return ((val & (1 << PCIE_XMLH_LINK_UP)) ++ && (val & (1 << PCIE_RDLH_LINK_UP))) ? 1 : 0; ++} ++ ++static int __arch_get_port_nr(void) ++{ ++ unsigned int val, mode; ++ int nr; ++ void *pcie_sys_stat; ++ unsigned int sys_ctrl_base; ++ ++ /* Get sys ctrl base address */ ++ of_property_read_u32(g_of_node, "sys_ctrl_base", &sys_ctrl_base); ++ ++ pcie_sys_stat = ioremap_nocache(sys_ctrl_base + REG_SC_STAT, sizeof(int)); ++ if (!pcie_sys_stat) { ++ pr_err("ioremap pcie sys status register failed!\n"); ++ return 0; ++ } ++ ++ val = readl(pcie_sys_stat); ++ mode = (val >> 12) & 0x3; ++ switch (mode) { ++ case 0x1: ++ nr = 1; ++ break; ++ ++ case 0x0: ++ nr = 2; ++ break; ++ ++ default: ++ nr = 0; ++ break; ++ } ++ ++ iounmap(pcie_sys_stat); ++ ++ return nr; ++} ++ ++/* ++ * ret: ++ */ ++static int __arch_pcie_info_setup(struct pcie_info *info, int *controllers_nr) ++{ ++ unsigned int mem_size; ++ unsigned int cfg_size; ++ int nr; ++ ++ /* Get pcie deice memory size */ ++ of_property_read_u32(g_of_node, "dev_mem_size", &mem_size); ++ ++ /* Get pcie config space size*/ ++ of_property_read_u32(g_of_node, "dev_conf_size", &cfg_size); ++ ++ nr = __arch_get_port_nr(); ++ if (!nr) { ++ pr_err("Pcie port number: 0\n"); ++ *controllers_nr = 0; ++ return -EINVAL; ++ } ++ ++ if ((mem_size > __256MB__) || (cfg_size > __256MB__)) { ++ pcie_error( ++ "Invalid parameter: pcie mem size[0x%x], pcie cfg size[0x%x]!", ++ mem_size, cfg_size); ++ return -EINVAL; ++ } ++ ++ info->controller = 0; ++ ++ /* RC configuration space */ ++ info->conf_base_addr = (unsigned long)ioremap_nocache(PCIE_DBI_BASE, ++ __8KB__); ++ if (!info->conf_base_addr) { ++ pcie_error("Address mapping for RC dbi failed!"); ++ return -EIO; ++ } ++ ++ /* Configuration space for all EPs */ ++ info->base_addr = (unsigned long)ioremap_nocache(PCIE_EP_CONF_BASE, ++ cfg_size); ++ if (!info->base_addr) { ++ iounmap((void *)info->conf_base_addr); ++ pcie_error("Address mapping for EPs cfg failed!"); ++ return -EIO; ++ } ++ ++ return 0; ++ ++} ++ ++static void __arch_pcie_info_release(struct pcie_info *info) ++{ ++ if (info->base_addr) ++ iounmap((void *)info->base_addr); ++ ++ if (info->conf_base_addr) ++ iounmap((void *)info->conf_base_addr); ++} ++ ++static int __arch_pcie_sys_init(struct pcie_info *info) ++{ ++ unsigned int val; ++ void *crg_base = (void *)ioremap_nocache(PERI_CRG_BASE, __8KB__); ++ void *misc_base = (void *)ioremap_nocache(MISC_CTRL_BASE,__4KB__); ++ ++ dbi_base = (void *)info->conf_base_addr; ++ ++ /* ++ * split_cp_dis ++ * */ ++ writel(0xd11, misc_base + MISC_CTRL5); ++ writel(0xd51, misc_base + MISC_CTRL5); ++ writel(0xd11, misc_base + MISC_CTRL5); ++ writel(0x0, misc_base + MISC_CTRL5); ++ writel(0xd31, misc_base + MISC_CTRL5); ++ writel(0xd71, misc_base + MISC_CTRL5); ++ writel(0xd31, misc_base + MISC_CTRL5); ++ writel(0xd0, misc_base + MISC_CTRL5); ++ mdelay(10); ++ ++ /* ++ * Disable PCIE ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL7); ++ val &= (~(1 << PCIE_APP_LTSSM_ENBALE)); ++ writel(val, dbi_base + PCIE_SYS_CTRL7); ++ ++ /* ++ * Reset ++ */ ++ val = readl(crg_base + PERI_CRG44); ++ val |= (1 << PCIE_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG44); ++ ++ /* ++ * Retreat from the reset state ++ */ ++ udelay(500); ++ val = readl(crg_base + PERI_CRG44); ++ val &= ~(1 << PCIE_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG44); ++ mdelay(10); ++ ++ ++ /* ++ * PCIE RC work mode ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL0); ++ val &= (~(0xf << PCIE_DEVICE_TYPE)); ++ val |= (PCIE_WM_RC << PCIE_DEVICE_TYPE); ++ writel(val, dbi_base + PCIE_SYS_CTRL0); ++ ++ /* ++ * Enable clk ++ */ ++ val = readl(crg_base + PERI_CRG44); ++ val |= ((1 << PCIE_X2_BUS_CKEN) ++ | (1 << PCIE_X2_SYS_CKEN) ++ | (1 << PCIE_X2_PIPE_CKEN) ++ | (1 << PCIE_X2_AUX_CKEN)); ++ writel(val, crg_base + PERI_CRG44); ++ ++ mdelay(10); ++ ++ /* ++ * * Set PCIe support the identification Board card ++ */ ++ val = readl(dbi_base + PCI_CARD); ++ val |= (1<<3); ++ writel(val,dbi_base + PCI_CARD); ++ mdelay(10); ++ ++ /* ++ * Set PCIE controller class code to be PCI-PCI bridge device ++ */ ++ val = readl(dbi_base + PCI_CLASS_REVISION); ++ val &= ~(0xffffff00); ++ val |= (0x60400 << 8); ++ writel(val, dbi_base + PCI_CLASS_REVISION); ++ udelay(1000); ++ ++ /* ++ * Enable controller ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL7); ++ val |= (1 << PCIE_APP_LTSSM_ENBALE); ++ writel(val, dbi_base + PCIE_SYS_CTRL7); ++ udelay(1000); ++ ++ val = readl(dbi_base + PCI_COMMAND); ++ val |= 7; ++ writel(val, dbi_base + PCI_COMMAND); ++ ++#ifdef CONFIG_ENABLE_PCIE_1 ++ /* set pcie to gen 1*/ ++ writel(0x1, dbi_base + 0x8BC); ++ val = readl(dbi_base + 0x7C); ++ val = ((val >> 4) << 4) | 0x1; ++ writel(val, dbi_base + 0x7C); ++#endif ++ ++ iounmap(misc_base); ++ iounmap(crg_base); ++ return 0; ++} ++ ++static void __arch_pcie_sys_exit(void) ++{ ++ unsigned int val; ++ void *crg_base = (void *)ioremap_nocache(PERI_CRG_BASE, __8KB__); ++ ++ /* ++ * Disable PCIE ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL7); ++ val &= (~(1 << PCIE_APP_LTSSM_ENBALE)); ++ writel(val, dbi_base + PCIE_SYS_CTRL7); ++ ++ /* ++ * Reset ++ */ ++ val = readl(crg_base + PERI_CRG44); ++ val |= (1 << PCIE_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG44); ++ ++ udelay(1000); ++ ++ /* ++ * Disable clk ++ */ ++ val = readl(crg_base + PERI_CRG44); ++ val &= (~(1 << PCIE_X2_AUX_CKEN)); ++ val &= (~(1 << PCIE_X2_PIPE_CKEN)); ++ val &= (~(1 << PCIE_X2_SYS_CKEN)); ++ val &= (~(1 << PCIE_X2_BUS_CKEN)); ++ writel(val, crg_base + PERI_CRG44); ++ ++ iounmap(crg_base); ++ ++ udelay(1000); ++} +diff --git a/drivers/pci/hipcie/pcie_hi3559av100.h b/drivers/pci/hipcie/pcie_hi3559av100.h +new file mode 100644 +index 0000000..28988d8 +--- /dev/null ++++ b/drivers/pci/hipcie/pcie_hi3559av100.h +@@ -0,0 +1,52 @@ ++#ifndef __HISI_PCIE_H__ ++#define __HISI_PCIE_H__ ++ ++#define MISC_CTRL_BASE 0x12030000 ++#define PCIE_MEM_BASE 0x30000000 ++#define PCIE_EP_CONF_BASE 0x20000000 ++#define PCIE_DBI_BASE 0x12200000 ++#define PERI_CRG_BASE 0x12010000 ++ ++#define PERI_CRG44 0x18c ++#define PCIE_X2_SRST_REQ 2 ++ ++#define PCIE_X2_AUX_CKEN 7 ++#define PCIE_X2_PIPE_CKEN 6 ++#define PCIE_X2_SYS_CKEN 5 ++#define PCIE_X2_BUS_CKEN 4 ++#define PCIE_PAD_OE_MASK (0x7 << 8) ++ ++#define PCIE_SYS_CTRL0 0xc00 ++#define PCIE_DEVICE_TYPE 28 ++#define PCIE_WM_EP 0x0 ++#define PCIE_WM_LEGACY 0x1 ++#define PCIE_WM_RC 0x4 ++ ++#define PCIE_SYS_CTRL7 0xc1C ++#define PCIE_APP_LTSSM_ENBALE 11 ++ ++#define PCIE_SYS_STATE0 0xf00 ++#define PCIE_XMLH_LINK_UP 15 ++#define PCIE_RDLH_LINK_UP 5 ++ ++#define PCIE_IRQ_INTA 160 ++#define PCIE_IRQ_INTB 161 ++#define PCIE_IRQ_INTC 162 ++#define PCIE_IRQ_INTD 163 ++#define PCIE_IRQ_EDMA 164 ++#define PCIE_IRQ_MSI 165 ++#define PCIE_IRQ_LINK_DOWN 166 ++ ++#define PCIE_INTA_PIN 1 ++#define PCIE_INTB_PIN 2 ++#define PCIE_INTC_PIN 3 ++#define PCIE_INTD_PIN 4 ++ ++#define MISC_CTRL33 0x128 ++#define COM_PHY_TEST_VAL1 ((0x1 << 11) | (0x1)) ++#define COM_PHY_TEST_VAL2 ((0x1 << 6) | (0x1 << 11) | (0x1)) ++ ++#define REG_SC_STAT 0x008c ++#define PCI_CARD 0x44 ++#define MISC_CTRL5 0x14 ++#endif +diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c +index 1ccce1c..2638d29 100644 +--- a/drivers/pci/pci-driver.c ++++ b/drivers/pci/pci-driver.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include "pci.h" + + struct pci_dynid { +@@ -389,6 +390,9 @@ static int __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev) + + int __weak pcibios_alloc_irq(struct pci_dev *dev) + { ++#ifdef CONFIG_ARCH_HISI_BVT ++ dev->irq = of_irq_parse_and_map_pci(dev, 0, 0); ++#endif + return 0; + } + +diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig +index 7ce7763..76a0f09 100644 +--- a/drivers/pci/pcie/Kconfig ++++ b/drivers/pci/pcie/Kconfig +@@ -30,7 +30,7 @@ source "drivers/pci/pcie/aer/Kconfig" + config PCIEASPM + bool "PCI Express ASPM control" if EXPERT + depends on PCI && PCIEPORTBUS +- default y ++ default n + help + This enables OS control over PCI Express ASPM (Active State + Power Management) and Clock Power Management. ASPM supports +@@ -79,7 +79,7 @@ config PCIEASPM_PERFORMANCE + endchoice + + config PCIE_PME +- def_bool y ++ def_bool n + depends on PCIEPORTBUS && PM + + config PCIE_DPC +diff --git a/drivers/pci/pcie/aer/Kconfig b/drivers/pci/pcie/aer/Kconfig +index 7d1437b..3cada58 100644 +--- a/drivers/pci/pcie/aer/Kconfig ++++ b/drivers/pci/pcie/aer/Kconfig +@@ -6,7 +6,7 @@ config PCIEAER + bool "Root Port Advanced Error Reporting support" + depends on PCIEPORTBUS + select RAS +- default y ++ default n + help + This enables PCI Express Root Port Advanced Error Reporting + (AER) driver support. Error reporting messages sent to Root +diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig +index 7dc726d..17bc054 100644 +--- a/drivers/phy/Kconfig ++++ b/drivers/phy/Kconfig +@@ -481,6 +481,7 @@ config PHY_CYGNUS_PCIE + If unsure, say N. + + source "drivers/phy/tegra/Kconfig" ++source "drivers/phy/hibvt/Kconfig" + + config PHY_NS2_PCIE + tristate "Broadcom Northstar2 PCIe PHY driver" +diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile +index a534cf5..b69cc4b 100644 +--- a/drivers/phy/Makefile ++++ b/drivers/phy/Makefile +@@ -59,4 +59,5 @@ obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o + obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o + obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o + obj-$(CONFIG_ARCH_TEGRA) += tegra/ ++obj-$(CONFIG_ARCH_HISI_BVT) += hibvt/ + obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o +diff --git a/drivers/phy/hibvt/Kconfig b/drivers/phy/hibvt/Kconfig +new file mode 100644 +index 0000000..6a32725 +--- /dev/null ++++ b/drivers/phy/hibvt/Kconfig +@@ -0,0 +1,39 @@ ++config PHY_HISI_SATA ++ tristate "Hisilicon sata phy support" ++ depends on (ARCH_HI3536DV100 || ARCH_HI3521A || ARCH_HI3531A) && OF && HAS_IOMEM ++ default n ++ select GENERIC_PHY ++ help ++ Enable this to support the sata phy that is part of ++ sata driver for hisilicon ++ ++config HISI_SATA_MODE ++ int "Hisi sata interworking speed mode(1.5G:0/3G:1/6G:2)" ++ depends on PHY_HISI_SATA ++ range 0 1 if ARCH_HI3536DV100 ++ range 0 2 if (ARCH_HI3521A || ARCH_HI3531A) ++ default "1" if (ARCH_HI3536DV100 || ARCH_HI3521A || ARCH_HI3531A) ++ help ++ Hisilicon sata interworking speed mode ++ ++config PHY_HISI_USB2 ++ tristate "HISI USB2 PHY Driver" ++ depends on ARCH_HISI_BVT ++ default y ++ select GENERIC_PHY ++ help ++ Support for PHY on Hisilicon Socs. This Phy supports ++ USB 1.5Mb/s, USB 12Mb/s, USB 480Mb/s speeds. It suppots one ++ USB host port to accept one USB device. Support init the phy ++ and adjust phy Eye Diagram. ++ ++config PHY_HISI_USB3 ++ tristate "HISI USB3 PHY Driver" ++ depends on ARCH_HI3531A ++ default y ++ select GENERIC_PHY ++ help ++ Support for PHY on Hisilicon Socs. This Phy supports ++ USB3.0 and Compatible with USB2.0. It suppots one ++ USB host port to accept one USB device. Support init the phy ++ and adjust phy Eye Diagram. +diff --git a/drivers/phy/hibvt/Makefile b/drivers/phy/hibvt/Makefile +new file mode 100644 +index 0000000..1d72d44 +--- /dev/null ++++ b/drivers/phy/hibvt/Makefile +@@ -0,0 +1,9 @@ ++obj-$(CONFIG_PHY_HISI_SATA) += phy-hisi-sata.o ++obj-$(CONFIG_PHY_HISI_USB2) += phy-hisi-usb.o ++obj-$(CONFIG_PHY_HISI_USB3) += phy-hisi-usb3.o ++obj-$(CONFIG_ARCH_HI3516A) += phy-hi3516a-usb.o ++obj-$(CONFIG_ARCH_HI3536DV100) += phy-hi3536d-usb.o ++obj-$(CONFIG_ARCH_HI3518EV20X) += phy-hi3518ev20x-usb.o ++obj-$(CONFIG_ARCH_HI3521A) += phy-hi3521a-usb.o ++obj-$(CONFIG_ARCH_HI3531A) += hiusb-ehci-hi3531a.o ++obj-$(CONFIG_ARCH_HI3531A) += hiusb-xhci-hi3531a.o +diff --git a/drivers/phy/hibvt/hiusb-ehci-hi3531a.c b/drivers/phy/hibvt/hiusb-ehci-hi3531a.c +new file mode 100644 +index 0000000..d10c529 +--- /dev/null ++++ b/drivers/phy/hibvt/hiusb-ehci-hi3531a.c +@@ -0,0 +1,158 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include "phy-hisi-usb.h" ++ ++#define IO_REG_USB2_CTRL 0x0130 ++#define USB2_BUS_CKEN (1 << 0) ++#define USB2_OHCI48M_CKEN (1 << 1) ++#define USB2_OHCI12M_CKEN (1 << 2) ++#define USB2_HST_PHY_CKEN (1 << 4) ++#define USB2_UTMI0_CKEN (1 << 5) ++#define USB2_BUS_SRST_REQ (1 << 12) ++#define USB2_UTMI0_SRST_REQ (1 << 13) ++#define USB2_HST_PHY_SYST_REQ (1 << 16) ++ ++#define IO_REG_USB2_PHY0 0x0134 ++#define USB_PHY0_REF_CKEN (1 << 0) ++#define USB_PHY0_SRST_REQ (1 << 8) ++#define USB_PHY0_SRST_TREQ (1 << 9) ++#define USB_PHY0_REFCLK_SEL (1 << 16) ++ ++#define IO_REG_USB2_CTRL0 0x0090 ++#define WORDINTERFACE (1 << 0) ++#define SS_BURST4_EN (1 << 7) ++#define SS_BURST8_EN (1 << 8) ++#define SS_BURST16_EN (1 << 9) ++ ++#define IO_REG_USB2_CTRL1 0x0094 ++/* write(0x1 << 5) 0x6 to addr 0x4 */ ++#define CONFIG_CLK ((0x1 << 5) | (0x6 << 0) | (0x4 << 8)) ++ ++void hisi_usb_phy_on(struct phy *phy) ++{ ++ int reg; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ /* reset enable */ ++ reg = readl(priv->peri_ctrl + IO_REG_USB2_CTRL); ++ reg |= (USB2_BUS_SRST_REQ ++ | USB2_UTMI0_SRST_REQ ++ | USB2_HST_PHY_SYST_REQ); ++ ++ writel(reg, priv->peri_ctrl + IO_REG_USB2_CTRL); ++ udelay(200); ++ ++ reg = readl(priv->peri_ctrl + IO_REG_USB2_PHY0); ++ reg |= (USB_PHY0_SRST_REQ ++ | USB_PHY0_SRST_TREQ); ++ writel(reg, priv->peri_ctrl + IO_REG_USB2_PHY0); ++ udelay(200); ++ ++ reg = readl(priv->misc_ctrl + IO_REG_USB2_CTRL0); ++ reg &= ~(WORDINTERFACE); /* 8bit */ ++ reg &= ~(SS_BURST16_EN); /* 16 bit burst disable */ ++ writel(reg, priv->misc_ctrl + IO_REG_USB2_CTRL0); ++ udelay(100); ++ ++ /* for ssk usb storage ok */ ++ msleep(20); ++ ++ /* open ref clock */ ++ reg = readl(priv->peri_ctrl + IO_REG_USB2_PHY0); ++ reg |= (USB_PHY0_REF_CKEN); ++ writel(reg, priv->peri_ctrl + IO_REG_USB2_PHY0); ++ udelay(100); ++ ++ /* cancel power on reset */ ++ reg = readl(priv->peri_ctrl + IO_REG_USB2_PHY0); ++ reg &= ~(USB_PHY0_SRST_REQ); ++ writel(reg , priv->peri_ctrl + IO_REG_USB2_PHY0); ++ udelay(300); ++ ++ /* config clock */ ++ writel(0x0, priv->misc_ctrl + IO_REG_USB2_CTRL1); ++ mdelay(200); ++ reg = readl(priv->misc_ctrl + IO_REG_USB2_CTRL1); ++ reg |= CONFIG_CLK; ++ writel(reg, priv->misc_ctrl + IO_REG_USB2_CTRL1); ++ udelay(100); ++ ++ /* writel(0x0, IO_REG_USB2_CTRL1); */ ++ /* mdelay(2); */ ++ ++ /* config u2 eye diagram */ ++ /* close HS pre-emphasis */ ++ writel(0x0, priv->misc_ctrl + IO_REG_USB2_CTRL1); ++ udelay(10); ++ writel(0x1820, priv->misc_ctrl + IO_REG_USB2_CTRL1); ++ udelay(100); ++ ++ /* cancel port reset */ ++ reg = readl(priv->peri_ctrl + IO_REG_USB2_PHY0); ++ reg &= ~(USB_PHY0_SRST_TREQ); ++ writel(reg, priv->peri_ctrl + IO_REG_USB2_PHY0); ++ udelay(300); ++ ++ /* cancel control reset */ ++ reg = readl(priv->peri_ctrl + IO_REG_USB2_CTRL); ++ reg &= ~(USB2_BUS_SRST_REQ ++ | USB2_UTMI0_SRST_REQ ++ | USB2_HST_PHY_SYST_REQ); ++ ++ reg |= (USB2_BUS_CKEN ++ | USB2_OHCI48M_CKEN ++ | USB2_OHCI12M_CKEN ++ | USB2_HST_PHY_CKEN ++ | USB2_UTMI0_CKEN); ++ writel(reg, priv->peri_ctrl + IO_REG_USB2_CTRL); ++ udelay(200); ++} ++ ++EXPORT_SYMBOL(hisi_usb_phy_on); ++ ++void hisi_usb_phy_off(struct phy *phy) ++{ ++ int reg; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ reg = readl(priv->peri_ctrl + IO_REG_USB2_PHY0); ++ reg |= (USB_PHY0_SRST_REQ ++ | USB_PHY0_SRST_TREQ); ++ writel(reg, priv->peri_ctrl + IO_REG_USB2_PHY0); ++ udelay(100); ++ ++ /* close clock */ ++ reg = readl(priv->peri_ctrl + IO_REG_USB2_PHY0); ++ reg &= ~(USB_PHY0_REFCLK_SEL ++ | USB_PHY0_REF_CKEN); ++ writel(reg, priv->peri_ctrl + IO_REG_USB2_PHY0); ++ udelay(300); ++ ++ /* close clock */ ++ reg = readl(priv->peri_ctrl + IO_REG_USB2_CTRL); ++ reg &= ~(USB2_BUS_CKEN ++ | USB2_OHCI48M_CKEN ++ | USB2_OHCI12M_CKEN ++ | USB2_HST_PHY_CKEN ++ | USB2_UTMI0_CKEN); ++ writel(reg, priv->peri_ctrl + IO_REG_USB2_CTRL); ++ udelay(200); ++} ++EXPORT_SYMBOL(hisi_usb_phy_off); +diff --git a/drivers/phy/hibvt/hiusb-xhci-hi3531a.c b/drivers/phy/hibvt/hiusb-xhci-hi3531a.c +new file mode 100644 +index 0000000..1141ea1 +--- /dev/null ++++ b/drivers/phy/hibvt/hiusb-xhci-hi3531a.c +@@ -0,0 +1,123 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include "phy-hisi-usb.h" ++ ++#define PERI_CRG91 0x16C ++#define usb2_phy1_ref_cken (1 << 0) ++#define usb2_phy1_srst_req (1 << 8) ++#define usb2_phy1_srst_treq (1 << 9) ++ ++#define PERI_CRG72 0x120 ++#define combphy1_refclk1_sel (3 <<14) ++#define combphy1_lane1_srst_req (1 <<11) ++#define combphy1_ref1_cken (1 << 9) ++ ++#define PERI_CRG75 0x12c ++#define usb3_vcc_srst_req (1 <<13) ++ ++ ++void hisi_usb3_phy_on(struct phy *phy) ++{ ++ int reg; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ /* reset enable */ ++ reg = readl(priv->peri_ctrl + PERI_CRG75); ++ reg |= (usb3_vcc_srst_req); ++ writel_relaxed(reg, priv->peri_ctrl + PERI_CRG75); ++ udelay(200); ++ reg = readl(priv->peri_ctrl + PERI_CRG72); ++ reg |= (combphy1_lane1_srst_req); ++ writel_relaxed(reg, priv->peri_ctrl + PERI_CRG72); ++ udelay(200); ++ reg = readl(priv->peri_ctrl + PERI_CRG91); ++ reg |= (usb2_phy1_srst_treq | usb2_phy1_srst_req); ++ writel_relaxed(reg, priv->peri_ctrl + PERI_CRG91); ++ udelay(200); ++ reg = readl(priv->peri_ctrl + PERI_CRG91); ++ reg &= ~(usb2_phy1_ref_cken); ++ writel_relaxed(reg, priv->peri_ctrl + PERI_CRG91); ++ udelay(200); ++ ++ /*open usb2.0 bus clock*/ ++ reg = readl(priv->peri_ctrl + PERI_CRG91); ++ reg |= usb2_phy1_ref_cken; ++ writel_relaxed(reg, priv->peri_ctrl + PERI_CRG91); ++ udelay(200); ++ ++ reg = readl(priv->peri_ctrl + PERI_CRG91); ++ reg &= ~(usb2_phy1_srst_req); ++ writel_relaxed(reg, priv->peri_ctrl + PERI_CRG91); ++ mdelay(2); ++ ++ reg = readl(priv->peri_ctrl + PERI_CRG91); ++ reg &= ~(usb2_phy1_srst_treq); ++ writel_relaxed(reg, priv->peri_ctrl + PERI_CRG91); ++ udelay(200); ++ ++ reg = readl(priv->peri_ctrl + PERI_CRG72); ++ reg &= ~(combphy1_refclk1_sel); ++ writel_relaxed(reg, priv->peri_ctrl + PERI_CRG72); ++ udelay(200); ++ ++ reg = readl(priv->peri_ctrl + PERI_CRG72); ++ reg |= combphy1_ref1_cken; ++ writel_relaxed(reg, priv->peri_ctrl + PERI_CRG72); ++ udelay(200); ++ /* cancel reset */ ++ reg = readl(priv->peri_ctrl + PERI_CRG72); ++ reg &= ~(combphy1_lane1_srst_req); ++ writel_relaxed(reg, priv->peri_ctrl + PERI_CRG72); ++ udelay(100); ++ ++ reg = readl(priv->peri_ctrl + PERI_CRG75); ++ reg &= ~(usb3_vcc_srst_req); ++ writel_relaxed(reg, priv->peri_ctrl + PERI_CRG75); ++ udelay(200); ++} ++EXPORT_SYMBOL(hisi_usb3_phy_on); ++ ++ ++void hisi_usb3_phy_off(struct phy *phy) ++{ ++ int reg; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ /* reset enable */ ++ reg = readl(priv->peri_ctrl + PERI_CRG75); ++ reg |= (usb3_vcc_srst_req); ++ writel_relaxed(reg, priv->peri_ctrl + PERI_CRG75); ++ udelay(200); ++ reg = readl(priv->peri_ctrl + PERI_CRG72); ++ reg |= (combphy1_lane1_srst_req); ++ writel_relaxed(reg, priv->peri_ctrl + PERI_CRG72); ++ udelay(200); ++ reg = readl(priv->peri_ctrl + PERI_CRG91); ++ reg |= (usb2_phy1_srst_treq | usb2_phy1_srst_req); ++ writel_relaxed(reg, priv->peri_ctrl + PERI_CRG91); ++ udelay(200); ++ reg = readl(priv->peri_ctrl + PERI_CRG91); ++ reg &= ~(usb2_phy1_ref_cken); ++ writel_relaxed(reg, priv->peri_ctrl + PERI_CRG91); ++ udelay(200); ++ ++} ++EXPORT_SYMBOL(hisi_usb3_phy_off); +diff --git a/drivers/phy/hibvt/phy-hi3516a-usb.c b/drivers/phy/hibvt/phy-hi3516a-usb.c +new file mode 100644 +index 0000000..85a5c06 +--- /dev/null ++++ b/drivers/phy/hibvt/phy-hi3516a-usb.c +@@ -0,0 +1,143 @@ ++#include ++#include ++#include ++#include "phy-hisi-usb.h" ++ ++#define USB2_SWITCH_OFFSET 0x130 ++#define PERI_CRG46 0xb8 ++#define USB_CKEN (1 << 7) ++#define USB_CTRL_UTMI0_REG (1 << 5) ++#define USB_CTRL_HUB_REG (1 << 4) ++#define USBPHY_PORT0_TREQ (1 << 2) ++#define USBPHY_REQ (1 << 1) ++#define USB_AHB_SRST_REQ (1 << 0) ++ ++#define PERI_USB 0x78 ++#define WORDINTERFACE (1 << 0) ++#define SS_BURST4_EN (1 << 7) ++#define SS_BURST8_EN (1 << 8) ++#define SS_BURST16_EN (1 << 9) ++#define USBOVR_P_CTRL (1 << 17) ++#define MISC_USB 0x80 ++ ++static int *usb2_switch_base; ++ ++void hisi_switch_func(int otg) ++{ ++ int reg; ++ ++ reg = readl(usb2_switch_base); ++ if (otg) { ++ reg |= 0x1; ++ writel(reg, usb2_switch_base); ++ } else { ++ reg &= ~(0x1); ++ writel(reg, usb2_switch_base); ++ } ++} ++EXPORT_SYMBOL(hisi_switch_func); ++ ++void hisi_usb_phy_on(struct phy *phy) ++{ ++ int reg; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ usb2_switch_base = priv->switch_base + USB2_SWITCH_OFFSET; ++ /* enable phy ref clk to enable phy */ ++ reg = readl(priv->peri_ctrl + PERI_CRG46); ++ reg |= USB_CKEN; ++ writel(reg, priv->peri_ctrl + PERI_CRG46); ++ udelay(100); ++ ++ /* config controller */ ++ reg = readl(priv->misc_ctrl + PERI_USB); ++ reg &= ~(WORDINTERFACE); /* 8bit */ ++ /* disable ehci burst16 mode*/ ++ reg &= ~(SS_BURST16_EN); ++ reg |= USBOVR_P_CTRL; ++ writel(reg, priv->misc_ctrl + PERI_USB); ++ udelay(100); ++ ++ /* de-assert phy port */ ++ reg = readl(priv->peri_ctrl + PERI_CRG46); ++ reg &= ~(USBPHY_REQ); ++ writel(reg, priv->peri_ctrl + PERI_CRG46); ++ udelay(100); ++ ++ writel(0x908, priv->misc_ctrl + MISC_USB); ++ udelay(10); ++ writel(0x928, priv->misc_ctrl + MISC_USB); ++ mdelay(1); ++ ++ /* open phy clk */ ++ writel(0xc06, priv->misc_ctrl + MISC_USB); ++ udelay(10); ++ writel(0xc26, priv->misc_ctrl + MISC_USB); ++ mdelay(5); ++ ++ writel(0x108, priv->misc_ctrl + MISC_USB); ++ udelay(10); ++ writel(0x128, priv->misc_ctrl + MISC_USB); ++ mdelay(2); ++ ++ /* usb2.0 phy eye pattern */ ++ writel(0x1c00, priv->misc_ctrl + MISC_USB); ++ udelay(10); ++ writel(0x1c20, priv->misc_ctrl + MISC_USB); ++ mdelay(5); ++ ++ writel(0x0c09, priv->misc_ctrl + MISC_USB); ++ udelay(10); ++ writel(0x0c29, priv->misc_ctrl + MISC_USB); ++ mdelay(5); ++ ++ writel(0x1a0a, priv->misc_ctrl + MISC_USB); ++ udelay(10); ++ writel(0x1a2a, priv->misc_ctrl + MISC_USB); ++ mdelay(5); ++ ++ /* cancel phy utmi reset */ ++ reg = readl(priv->peri_ctrl + PERI_CRG46); ++ reg &= ~(USBPHY_PORT0_TREQ); ++ writel(reg, priv->peri_ctrl + PERI_CRG46); ++ udelay(300); ++ ++ /* de-assert all the rsts of ctrl */ ++ reg = readl(priv->peri_ctrl + PERI_CRG46); ++ reg &= ~(USB_CTRL_UTMI0_REG); ++ reg &= ~(USB_CTRL_HUB_REG); ++ reg &= ~(USB_AHB_SRST_REQ); ++ writel(reg, priv->peri_ctrl + PERI_CRG46); ++ udelay(200); ++ ++ /* decrease the threshold value from 650 to 550*/ ++ writel(0xa, priv->misc_ctrl + MISC_USB); ++ udelay(10); ++ writel(0x092a, priv->misc_ctrl + MISC_USB); ++ mdelay(5); ++} ++EXPORT_SYMBOL(hisi_usb_phy_on); ++ ++void hisi_usb_phy_off(struct phy *phy) ++{ ++ int reg; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ reg = readl(priv->peri_ctrl + PERI_CRG46); ++ reg &= ~(USB_CKEN); ++ reg |= (USB_CTRL_UTMI0_REG); ++ reg |= (USB_CTRL_HUB_REG); ++ reg |= (USBPHY_PORT0_TREQ); ++ reg |= (USBPHY_REQ); ++ reg |= (USB_AHB_SRST_REQ); ++ writel(reg, priv->peri_ctrl + PERI_CRG46); ++ udelay(100); ++ ++ /* enable phy */ ++ reg = readl(priv->misc_ctrl + PERI_USB); ++ reg |= (WORDINTERFACE); ++ reg |= (SS_BURST16_EN); ++ reg |= (USBOVR_P_CTRL); ++ writel(reg, priv->misc_ctrl + PERI_USB); ++} ++EXPORT_SYMBOL(hisi_usb_phy_off); +diff --git a/drivers/phy/hibvt/phy-hi3518ev20x-usb.c b/drivers/phy/hibvt/phy-hi3518ev20x-usb.c +new file mode 100644 +index 0000000..6683b64 +--- /dev/null ++++ b/drivers/phy/hibvt/phy-hi3518ev20x-usb.c +@@ -0,0 +1,133 @@ ++#include ++#include ++#include ++#include "phy-hisi-usb.h" ++ ++#define USB2_SWITCH_OFFSET 0x130 ++#define PERI_CRG46 0xb8 ++#define USB_CKEN (1 << 7) ++#define USB_CTRL_UTMI0_REG (1 << 5) ++#define USB_CTRL_HUB_REG (1 << 4) ++#define USBPHY_PORT0_TREQ (1 << 2) ++#define USBPHY_REQ (1 << 1) ++#define USB_AHB_SRST_REQ (1 << 0) ++ ++#define PERI_USB 0x78 ++#define WORDINTERFACE (1 << 0) ++#define SS_BURST4_EN (1 << 7) ++#define SS_BURST8_EN (1 << 8) ++#define SS_BURST16_EN (1 << 9) ++#define USBOVR_P_CTRL (1 << 17) ++#define MISC_USB 0x80 ++ ++static int *usb2_switch_base; ++ ++void hisi_switch_func(int otg) ++{ ++ int reg; ++ ++ reg = readl(usb2_switch_base); ++ if (otg) { ++ reg |= 0x1; ++ writel(reg, usb2_switch_base); ++ } else { ++ reg &= ~(0x1); ++ writel(reg, usb2_switch_base); ++ } ++} ++EXPORT_SYMBOL(hisi_switch_func); ++ ++void hisi_usb_phy_on(struct phy *phy) ++{ ++ int reg; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ usb2_switch_base = priv->switch_base + USB2_SWITCH_OFFSET; ++ /* enable phy ref clk to enable phy */ ++ reg = readl(priv->peri_ctrl + PERI_CRG46); ++ reg |= USB_CKEN; ++ writel(reg, priv->peri_ctrl + PERI_CRG46); ++ udelay(100); ++ ++ /* config controller */ ++ reg = readl(priv->misc_ctrl + PERI_USB); ++ reg &= ~(WORDINTERFACE); /* 8bit */ ++ /* disable ehci burst16 mode*/ ++ reg &= ~(SS_BURST16_EN); ++ reg |= USBOVR_P_CTRL; ++ writel(reg, priv->misc_ctrl + PERI_USB); ++ udelay(100); ++ ++ /* de-assert phy port */ ++ reg = readl(priv->peri_ctrl + PERI_CRG46); ++ reg &= ~(USBPHY_REQ); ++ writel(reg, priv->peri_ctrl + PERI_CRG46); ++ udelay(100); ++ ++ /* open phy clk */ ++ writel(0xc06, priv->misc_ctrl + MISC_USB); ++ udelay(10); ++ writel(0xc26, priv->misc_ctrl + MISC_USB); ++ mdelay(5); ++ ++ /* usb2.0 phy eye pattern */ ++ writel(0x1c00, priv->misc_ctrl + MISC_USB); ++ udelay(10); ++ writel(0x1c20, priv->misc_ctrl + MISC_USB); ++ mdelay(5); ++ ++ writel(0x0c09, priv->misc_ctrl + MISC_USB); ++ udelay(10); ++ writel(0x0c29, priv->misc_ctrl + MISC_USB); ++ mdelay(5); ++ ++ writel(0x1a0a, priv->misc_ctrl + MISC_USB); ++ udelay(10); ++ writel(0x1a2a, priv->misc_ctrl + MISC_USB); ++ mdelay(5); ++ ++ /* cancel phy utmi reset */ ++ reg = readl(priv->peri_ctrl + PERI_CRG46); ++ reg &= ~(USBPHY_PORT0_TREQ); ++ writel(reg, priv->peri_ctrl + PERI_CRG46); ++ udelay(300); ++ ++ /* de-assert all the rsts of ctrl */ ++ reg = readl(priv->peri_ctrl + PERI_CRG46); ++ reg &= ~(USB_CTRL_UTMI0_REG); ++ reg &= ~(USB_CTRL_HUB_REG); ++ reg &= ~(USB_AHB_SRST_REQ); ++ writel(reg, priv->peri_ctrl + PERI_CRG46); ++ udelay(200); ++ ++ /* decrease the threshold value from 650 to 550*/ ++ writel(0xa, priv->misc_ctrl + MISC_USB); ++ udelay(10); ++ writel(0x092a, priv->misc_ctrl + MISC_USB); ++ mdelay(5); ++} ++EXPORT_SYMBOL(hisi_usb_phy_on); ++ ++void hisi_usb_phy_off(struct phy *phy) ++{ ++ int reg; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ reg = readl(priv->peri_ctrl + PERI_CRG46); ++ reg &= ~(USB_CKEN); ++ reg |= (USB_CTRL_UTMI0_REG); ++ reg |= (USB_CTRL_HUB_REG); ++ reg |= (USBPHY_PORT0_TREQ); ++ reg |= (USBPHY_REQ); ++ reg |= (USB_AHB_SRST_REQ); ++ writel(reg, priv->peri_ctrl + PERI_CRG46); ++ udelay(100); ++ ++ /* enable phy */ ++ reg = readl(priv->misc_ctrl + PERI_USB); ++ reg |= (WORDINTERFACE); ++ reg |= (SS_BURST16_EN); ++ reg |= (USBOVR_P_CTRL); ++ writel(reg, priv->misc_ctrl + PERI_USB); ++} ++EXPORT_SYMBOL(hisi_usb_phy_off); +diff --git a/drivers/phy/hibvt/phy-hi3521a-sata.c b/drivers/phy/hibvt/phy-hi3521a-sata.c +new file mode 100644 +index 0000000..ff8601f +--- /dev/null ++++ b/drivers/phy/hibvt/phy-hi3521a-sata.c +@@ -0,0 +1,241 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "phy-hisi-sata.h" ++ ++enum { ++ HISI_SATA_PERI_CTRL = IO_ADDRESS(REG_CRG_BASE), ++ HISI_SATA_PERI_CRG26 = (HISI_SATA_PERI_CTRL + 0x68), ++ HISI_PHY1_REFCLK_SEL_24M = BIT(3), ++ HISI_PHY1_REFCLK_SEL_100M = (0 << 3), ++ HISI_PHY1_REFCKEN = BIT(2), ++ HISI_PHY0_REFCLK_SEL_24M = BIT(1), ++ HISI_PHY0_REFCLK_SEL_100M = (0 << 1), ++ HISI_PHY0_REFCKEN = BIT(0), ++ ++ HISI_SATA_PERI_CRG27 = (HISI_SATA_PERI_CTRL + 0x6C), ++ HISI_SATA_PORT1_REFCLK_CKEN = BIT(17), ++ HISI_SATA_PORT1_MPLL_CKEN = BIT(16), ++ HISI_SATA_CKO_ALIVE_SRST_REQ = BIT(13), ++ HISI_SATA_BUS_SRST_REQ = BIT(12), ++ HISI_SATA_PORT0_REFCLK_CKEN = BIT(10), ++ HISI_SATA_PORT0_MPLL_CKEN = BIT(9), ++ HISI_SATA_CKO_ALIVE_CKEN = BIT(8), ++ HISI_SATA_RX1_CKEN = BIT(6), ++ HISI_SATA_RX0_CKEN = BIT(5), ++ HISI_SATA_BUS_CKEN = BIT(4), ++ HISI_SATA_PORT01_CLK_EN = HISI_SATA_BUS_CKEN ++ | HISI_SATA_RX0_CKEN ++ | HISI_SATA_RX1_CKEN ++ | HISI_SATA_CKO_ALIVE_CKEN ++ | HISI_SATA_PORT0_MPLL_CKEN ++ | HISI_SATA_PORT0_REFCLK_CKEN ++ | HISI_SATA_PORT1_MPLL_CKEN ++ | HISI_SATA_PORT1_REFCLK_CKEN, ++ ++ FIFOTH_VALUE = 0x66d9f24, ++ PHY_VALUE = 0x4900003d, ++ PHYCTL2_VALUE = 0x60555, ++ ++ PORT_BIGENDINE = 0x82e5cb8, ++ ++ PX_TX_AMPLITUDE = 0x8377eb8, ++ PX_TX_PREEMPH = 0x14451, ++ ++ PHY_SG_1_5G = 0x0e180000, ++ PHY_SG_3G = 0x0e390000, ++ PHY_SG_6G = 0x0e5a0000, ++ ++ PHY_FORCE_1_5G = 0x2f180000, ++ PHY_FORCE_3G = 0x2f390000, ++ PHY_FORCE_6G = 0x2f5a0000, ++}; ++ ++static void hisi_sata_poweron(void) ++{ ++} ++ ++static void hisi_sata_poweroff(void) ++{ ++} ++ ++void hisi_sata_reset_rxtx_assert(unsigned int port_no) ++{ ++} ++EXPORT_SYMBOL(hisi_sata_reset_rxtx_assert); ++ ++void hisi_sata_reset_rxtx_deassert(unsigned int port_no) ++{ ++} ++EXPORT_SYMBOL(hisi_sata_reset_rxtx_deassert); ++ ++static void hisi_sata_reset(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG27); ++ tmp_val |= HISI_SATA_BUS_SRST_REQ | HISI_SATA_CKO_ALIVE_SRST_REQ; ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG27); ++} ++ ++static void hisi_sata_unreset(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG27); ++ tmp_val &= ~(HISI_SATA_BUS_SRST_REQ | HISI_SATA_CKO_ALIVE_SRST_REQ); ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG27); ++} ++ ++static void hisi_sata_phy_reset(void) ++{ ++} ++ ++static void hisi_sata_phy_unreset(void) ++{ ++} ++ ++static void hisi_sata_clk_enable(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG27); ++ tmp_val |= HISI_SATA_PORT01_CLK_EN; ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG27); ++} ++ ++static void hisi_sata_clk_disable(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG27); ++ tmp_val &= ~(HISI_SATA_PORT01_CLK_EN); ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG27); ++} ++ ++static void hisi_sata_clk_reset(void) ++{ ++} ++ ++static void hisi_sata_phy_clk_sel(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG26); ++ tmp_val |= HISI_PHY1_REFCLK_SEL_100M ++ | HISI_PHY0_REFCLK_SEL_100M ++ | HISI_PHY1_REFCKEN ++ | HISI_PHY0_REFCKEN; ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG26); ++} ++ ++void hisi_sata_set_fifoth(void *mmio) ++{ ++ int i; ++ ++ for (i = 0; i < ports_num; i++) ++ writel(FIFOTH_VALUE, (mmio + 0x100 + i*0x80 ++ + HISI_SATA_PORT_FIFOTH)); ++} ++EXPORT_SYMBOL(hisi_sata_set_fifoth); ++ ++static void hisi_sata_phy_config(void *mmio, int phy_mode) ++{ ++ unsigned int i, tmp_val, phy_config; ++ ++ hisi_sata_set_fifoth(mmio); ++ ++ if ((ports_num < 1) || (ports_num > 2)) ++ pr_err("ERROR: PORT num you set is WRONG!!!\n"); ++ ++ writel(PHY_VALUE, (mmio + HISI_SATA_PHY0_CTLL)); ++ writel(PHY_VALUE, (mmio + HISI_SATA_PHY1_CTLL)); ++ ++ for (i = 0; i < ports_num; i++) ++ writel(PHYCTL2_VALUE, (mmio + 0x100 + i*0x80 ++ + HISI_SATA_PORT_PHYCTL2)); ++ ++ tmp_val = readl(mmio + HISI_SATA_PHY0_CTLL); ++ tmp_val |= HISI_SATA_PHY_REV_CLK; ++ writel(tmp_val, (mmio + HISI_SATA_PHY0_CTLL)); ++ tmp_val = readl(mmio + HISI_SATA_PHY1_CTLL); ++ tmp_val |= HISI_SATA_PHY_REV_CLK; ++ writel(tmp_val, (mmio + HISI_SATA_PHY1_CTLL)); ++ ++ for (i = 0; i < ports_num; i++) { ++ tmp_val = readl(mmio + 0x100 + i*0x80 ++ + HISI_SATA_PORT_PHYCTL2); ++ tmp_val &= ~HISI_SATA_LANE0_RESET; ++ writel(tmp_val, (mmio + 0x100 + i*0x80 ++ + HISI_SATA_PORT_PHYCTL2)); ++ } ++ ++ tmp_val = readl(mmio + HISI_SATA_PHY0_CTLL); ++ tmp_val &= ~HISI_SATA_PHY_RESET; ++ writel(tmp_val, (mmio + HISI_SATA_PHY0_CTLL)); ++ tmp_val = readl(mmio + HISI_SATA_PHY1_CTLL); ++ tmp_val &= ~HISI_SATA_PHY_RESET; ++ writel(tmp_val, (mmio + HISI_SATA_PHY1_CTLL)); ++ ++ tmp_val = readl(mmio + HISI_SATA_PHY0_CTLH); ++ tmp_val |= HISI_SATA_BIGENDINE; ++ writel(tmp_val, (mmio + HISI_SATA_PHY0_CTLH)); ++ tmp_val = readl(mmio + HISI_SATA_PHY1_CTLH); ++ tmp_val |= HISI_SATA_BIGENDINE; ++ writel(tmp_val, (mmio + HISI_SATA_PHY1_CTLH)); ++ ++ /* set phy PX TX amplitude */ ++ for (i = 0; i < ports_num; i++) { ++ tmp_val = PX_TX_AMPLITUDE; ++ writel(tmp_val, (mmio + 0x100 + i*0x80 ++ + HISI_SATA_PORT_PHYCTL1)); ++ } ++ ++ /* set phy PX TX pre-emphasis */ ++ for (i = 0; i < ports_num; i++) { ++ tmp_val = PX_TX_PREEMPH; ++ writel(tmp_val, (mmio + 0x100 + i*0x80 ++ + HISI_SATA_PORT_PHYCTL2)); ++ } ++ ++ for (i = 0; i < ports_num; i++) ++ writel(PHY_FORCE_1_5G, (mmio + 0x100 + i*0x80 ++ + HISI_SATA_PORT_PHYCTL)); ++ for (i = 0; i < ports_num; i++) ++ writel(PHY_FORCE_3G, (mmio + 0x100 + i*0x80 ++ + HISI_SATA_PORT_PHYCTL)); ++ for (i = 0; i < ports_num; i++) ++ writel(PHY_FORCE_6G, (mmio + 0x100 + i*0x80 ++ + HISI_SATA_PORT_PHYCTL)); ++ ++ if (phy_mode == PHY_MODE_1_5G) ++ phy_config = PHY_SG_1_5G; ++ if (phy_mode == PHY_MODE_3G) ++ phy_config = PHY_SG_3G; ++ if (phy_mode == PHY_MODE_6G) ++ phy_config = PHY_SG_6G; ++ ++ for (i = 0; i < ports_num; i++) ++ writel(phy_config, (mmio + 0x100 + i*0x80 ++ + HISI_SATA_PORT_PHYCTL)); ++} +diff --git a/drivers/phy/hibvt/phy-hi3521a-usb.c b/drivers/phy/hibvt/phy-hi3521a-usb.c +new file mode 100644 +index 0000000..4d40df2 +--- /dev/null ++++ b/drivers/phy/hibvt/phy-hi3521a-usb.c +@@ -0,0 +1,101 @@ ++#include ++#include ++#include ++#include "phy-hisi-usb.h" ++ ++#define PERI_CRG28 0x70 ++#define USB_CKEN (1 << 7) ++#define USB_CTRL_UTMI1_REG (1 << 6) ++#define USB_CTRL_UTMI0_REG (1 << 5) ++#define USB_CTRL_HUB_REG (1 << 4) ++#define USBPHY_PORT1_TREQ (1 << 3) ++#define USBPHY_PORT0_TREQ (1 << 2) ++#define USBPHY_REQ (1 << 1) ++#define USB_AHB_SRST_REQ (1 << 0) ++ ++ ++#define PERI_USB 0x50 ++#define WORDINTERFACE (1 << 0) ++#define SS_BURST4_EN (1 << 7) ++#define SS_BURST8_EN (1 << 8) ++#define SS_BURST16_EN (1 << 9) ++#define USBOVR_P_CTRL (1 << 17) ++#define MISC_USB 0x54 ++ ++ ++void hisi_usb_phy_on(struct phy *phy) ++{ ++ int reg; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ /* enable phy ref clk to enable phy */ ++ reg = readl(priv->peri_ctrl + PERI_CRG28); ++ reg |= USB_CKEN; ++ writel(reg, priv->peri_ctrl + PERI_CRG28); ++ udelay(100); ++ ++ /* config controller */ ++ reg = readl(priv->misc_ctrl + PERI_USB); ++ reg &= ~(WORDINTERFACE); /* 8bit */ ++ /* disable ehci burst16 mode*/ ++ reg &= ~(SS_BURST16_EN); ++ reg |= USBOVR_P_CTRL; ++ writel(reg, priv->misc_ctrl + PERI_USB); ++ udelay(100); ++ ++ /* de-assert phy port */ ++ reg = readl(priv->peri_ctrl + PERI_CRG28); ++ reg &= ~(USBPHY_REQ); ++ writel(reg, priv->peri_ctrl + PERI_CRG28); ++ udelay(300); ++ ++ /* open phy clk */ ++ writel(0x406, priv->misc_ctrl + MISC_USB); ++ udelay(10); ++ writel(0x426, priv->misc_ctrl + MISC_USB); ++ mdelay(8); ++ ++ /* cancel phy utmi reset */ ++ reg = readl(priv->peri_ctrl + PERI_CRG28); ++ reg &= ~(USBPHY_PORT0_TREQ); ++ reg &= ~(USBPHY_PORT1_TREQ); ++ writel(reg, priv->peri_ctrl + PERI_CRG28); ++ udelay(300); ++ ++ /* de-assert all the rsts of ctrl */ ++ reg = readl(priv->peri_ctrl + PERI_CRG28); ++ reg &= ~(USB_CTRL_UTMI0_REG); ++ reg &= ~(USB_CTRL_UTMI1_REG); ++ reg &= ~(USB_CTRL_HUB_REG); ++ reg &= ~(USB_AHB_SRST_REQ); ++ writel(reg, priv->peri_ctrl + PERI_CRG28); ++ udelay(200); ++} ++EXPORT_SYMBOL(hisi_usb_phy_on); ++ ++void hisi_usb_phy_off(struct phy *phy) ++{ ++ int reg; ++ /* Disable EHCI clock. ++ If the HS PHY is unused disable it too. */ ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ reg = readl(priv->peri_ctrl + PERI_CRG28); ++ reg &= ~(USB_CKEN); ++ reg |= (USB_CTRL_UTMI0_REG); ++ reg |= (USB_CTRL_UTMI1_REG); ++ reg |= (USB_CTRL_HUB_REG); ++ reg |= (USBPHY_PORT0_TREQ); ++ reg |= (USBPHY_PORT1_TREQ); ++ reg |= (USBPHY_REQ); ++ reg |= (USB_AHB_SRST_REQ); ++ writel(reg, priv->peri_ctrl + PERI_CRG28); ++ udelay(100); ++ /* enable phy */ ++ reg = readl(priv->misc_ctrl + PERI_USB); ++ reg |= (WORDINTERFACE); ++ reg |= (SS_BURST16_EN); ++ reg |= (USBOVR_P_CTRL); ++ writel(reg, priv->misc_ctrl + PERI_USB); ++ udelay(100); ++} ++EXPORT_SYMBOL(hisi_usb_phy_off); +diff --git a/drivers/phy/hibvt/phy-hi3531a-sata.c b/drivers/phy/hibvt/phy-hi3531a-sata.c +new file mode 100644 +index 0000000..ef59cc8 +--- /dev/null ++++ b/drivers/phy/hibvt/phy-hi3531a-sata.c +@@ -0,0 +1,539 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "phy-hisi-sata.h" ++ ++enum { ++ HISI_SATA_PERI_CTRL = IO_ADDRESS(CRG_REG_BASE), ++ HISI_SATA_PERI_CRG72 = (HISI_SATA_PERI_CTRL + 0x120), ++ HISI_SATA_PHY0_REF0_CKEN = BIT(0), ++ HISI_SATA_PHY0_REF1_CKEN = BIT(1), ++ HISI_SATA_PHY0_REFCK0_SEL_100M = (0x2 << 4), ++ HISI_SATA_PHY0_REFCK0_SEL_25M = (0x1 << 4), ++ HISI_SATA_PHY0_REFCK0_SEL_24M = (0x0 << 4), ++ HISI_SATA_PHY0_REFCK1_SEL_100M = (0x2 << 6), ++ HISI_SATA_PHY0_REFCK1_SEL_25M = (0x1 << 6), ++ HISI_SATA_PHY0_REFCK1_SEL_24M = (0x0 << 6), ++ HISI_SATA_PHY1_REF0_CKEN = BIT(8), ++ HISI_SATA_PHY1_REF1_CKEN = BIT(9), ++ HISI_SATA_PHY1_REFCK0_SEL_100M = (0x2 << 12), ++ HISI_SATA_PHY1_REFCK0_SEL_25M = (0x1 << 12), ++ HISI_SATA_PHY1_REFCK0_SEL_24M = (0x0 << 12), ++ HISI_SATA_PHY1_REFCK1_SEL_100M = (0x2 << 14), ++ HISI_SATA_PHY1_REFCK1_SEL_25M = (0x1 << 14), ++ HISI_SATA_PHY1_REFCK1_SEL_24M = (0x0 << 14), ++ HISI_SATA_CLK_VALUE = HISI_SATA_PHY0_REF0_CKEN ++ | HISI_SATA_PHY0_REF1_CKEN ++ | HISI_SATA_PHY0_REFCK0_SEL_100M ++ | HISI_SATA_PHY0_REFCK1_SEL_100M ++ | HISI_SATA_PHY1_REF0_CKEN ++ | HISI_SATA_PHY1_REF1_CKEN ++ | HISI_SATA_PHY1_REFCK0_SEL_100M ++ | HISI_SATA_PHY1_REFCK1_SEL_100M, ++ ++ HISI_SATA_PHY0A_RST = BIT(2), ++ HISI_SATA_PHY0B_RST = BIT(3), ++ HISI_SATA_PHY1A_RST = BIT(10), ++ HISI_SATA_PHY1B_RST = BIT(11), ++ HISI_SATA_PHY0_RST = HISI_SATA_PHY0A_RST ++ | HISI_SATA_PHY0B_RST, ++ HISI_SATA_PHY1_RST = HISI_SATA_PHY1A_RST ++ | HISI_SATA_PHY1B_RST, ++ ++ HISI_SATA_PHY0A_RST_MASK = BIT(7), ++ HISI_SATA_PHY0B_RST_MASK = BIT(6), ++ HISI_SATA_PHY1A_RST_MASK = BIT(5), ++ HISI_SATA_PHY1B_RST_MASK = BIT(4), ++ HISI_SATA_PHY0_RST_MASK = HISI_SATA_PHY0A_RST_MASK ++ | HISI_SATA_PHY0B_RST_MASK, ++ HISI_SATA_PHY1_RST_MASK = HISI_SATA_PHY1A_RST_MASK ++ | HISI_SATA_PHY1B_RST_MASK, ++ ++ HISI_SATA_PERI_CRG74 = (HISI_SATA_PERI_CTRL + 0x128), ++ ++ HISI_SATA_BUS_CKEN = BIT(0), ++ HISI_SATA_BUS_SRST_REQ = BIT(8), ++ HISI_SATA_CKO_ALIVE_CKEN = BIT(2), ++ HISI_SATA_CKO_ALIVE_SRST_REQ = BIT(9), ++ HISI_SATA_RX0_CKEN = BIT(1), ++ HISI_SATA_TX0_CKEN = BIT(3), ++ HISI_SATA_RX0_SRST_REQ = BIT(10), ++ HISI_SATA0_SRST_REQ = BIT(11), ++ HISI_SATA_RX1_CKEN = BIT(12), ++ HISI_SATA_TX1_CKEN = BIT(13), ++ HISI_SATA_RX1_SRST_REQ = BIT(14), ++ HISI_SATA1_SRST_REQ = BIT(15), ++ HISI_SATA_RX2_CKEN = BIT(16), ++ HISI_SATA_TX2_CKEN = BIT(17), ++ HISI_SATA_RX2_SRST_REQ = BIT(18), ++ HISI_SATA2_SRST_REQ = BIT(19), ++ HISI_SATA_RX3_CKEN = BIT(20), ++ HISI_SATA_TX3_CKEN = BIT(21), ++ HISI_SATA_RX3_SRST_REQ = BIT(22), ++ HISI_SATA3_SRST_REQ = BIT(23), ++ ++ HISI_SATA_SYS_CTRL = IO_ADDRESS(SYS_CTRL_REG_BASE + 0x8C), ++ HISI_SATA_PCIE_MODE_SHIFT = 12, ++ ++ PHY_CONFIG_1_5G = 0x0e180000, ++ PHY_CONFIG_3G = 0x0e390000, ++ PHY_CONFIG_6G = 0x0e5a0000, ++ ++ PHY_SG_1_5G = 0x61438, ++ PHY_SG_3G = 0x61438, ++ PHY_SG_6G = 0x61438, ++}; ++ ++#define HISI_SATA_MISC_CTRL IO_ADDRESS(MISC_CTRL_REG_BASE) ++#define HISI_SATA_MISC_COMB_PHY0 (HISI_SATA_MISC_CTRL + 0x134) ++#define HISI_SATA_MISC_COMB_PHY1 (HISI_SATA_MISC_CTRL + 0x138) ++ ++static unsigned int mplx_port0; ++ ++static void hisi_sata_get_port_info(void) ++{ ++ unsigned int tmp_val, mode; ++ ++ tmp_val = readl((void *)HISI_SATA_SYS_CTRL); ++ ++ mode = (tmp_val >> HISI_SATA_PCIE_MODE_SHIFT) & 0xf; ++ ++ switch (mode) { ++ case 0x0: ++ ports_num = 4; ++ sata_port_map = 0xf; ++ break; ++ ++ case 0x1: ++ ports_num = 3; ++ sata_port_map = 0x7; ++ break; ++ ++ case 0x8: ++ ports_num = 3; ++ sata_port_map = 0xe; ++ break; ++ ++ case 0x2: ++ case 0x3: ++ ports_num = 2; ++ sata_port_map = 0x3; ++ break; ++ ++ case 0x9: ++ ports_num = 2; ++ sata_port_map = 0x6; ++ break; ++ ++ case 0xa: ++ case 0xb: ++ ports_num = 1; ++ sata_port_map = 0x2; ++ break; ++ ++ default: ++ ports_num = 0; ++ sata_port_map = 0x0; ++ break; ++ } ++ ++ mplx_port0 = (mode & 0x8) ? 1 : 0; ++} ++ ++static void hisi_sata_poweron(void) ++{ ++} ++ ++static void hisi_sata_poweroff(void) ++{ ++} ++ ++void hisi_sata_reset_rxtx_assert(unsigned int port_no) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG74); ++ ++ if (port_no == 0) { ++ tmp_val |= HISI_SATA_RX0_SRST_REQ ++ | HISI_SATA0_SRST_REQ; ++ } else if (port_no == 1) { ++ tmp_val |= HISI_SATA_RX1_SRST_REQ ++ | HISI_SATA1_SRST_REQ; ++ } else if (port_no == 2) { ++ tmp_val |= HISI_SATA_RX2_SRST_REQ ++ | HISI_SATA2_SRST_REQ; ++ } else if (port_no == 3) { ++ tmp_val |= HISI_SATA_RX3_SRST_REQ ++ | HISI_SATA3_SRST_REQ; ++ } ++ ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG74); ++} ++EXPORT_SYMBOL(hisi_sata_reset_rxtx_assert); ++ ++void hisi_sata_reset_rxtx_deassert(unsigned int port_no) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG74); ++ ++ if (port_no == 0) { ++ tmp_val &= ~(HISI_SATA_RX0_SRST_REQ ++ | HISI_SATA0_SRST_REQ); ++ } else if (port_no == 1) { ++ tmp_val &= ~(HISI_SATA_RX1_SRST_REQ ++ | HISI_SATA1_SRST_REQ); ++ } else if (port_no == 2) { ++ tmp_val &= ~(HISI_SATA_RX2_SRST_REQ ++ | HISI_SATA2_SRST_REQ); ++ } else if (port_no == 3) { ++ tmp_val &= ~(HISI_SATA_RX3_SRST_REQ ++ | HISI_SATA3_SRST_REQ); ++ } ++ ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG74); ++} ++EXPORT_SYMBOL(hisi_sata_reset_rxtx_deassert); ++ ++static void hisi_sata_reset(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG74); ++ ++ tmp_val |= HISI_SATA_BUS_SRST_REQ | HISI_SATA_CKO_ALIVE_SRST_REQ; ++ ++ if (ports_num == 4) { ++ tmp_val |= HISI_SATA_RX0_SRST_REQ ++ | HISI_SATA0_SRST_REQ ++ | HISI_SATA_RX1_SRST_REQ ++ | HISI_SATA1_SRST_REQ ++ | HISI_SATA_RX2_SRST_REQ ++ | HISI_SATA2_SRST_REQ ++ | HISI_SATA_RX3_SRST_REQ ++ | HISI_SATA3_SRST_REQ; ++ } else if (ports_num == 3) { ++ if (mplx_port0) { ++ tmp_val |= HISI_SATA_RX1_SRST_REQ ++ | HISI_SATA1_SRST_REQ ++ | HISI_SATA_RX2_SRST_REQ ++ | HISI_SATA2_SRST_REQ ++ | HISI_SATA_RX3_SRST_REQ ++ | HISI_SATA3_SRST_REQ; ++ } else { ++ tmp_val |= HISI_SATA_RX0_SRST_REQ ++ | HISI_SATA0_SRST_REQ ++ | HISI_SATA_RX1_SRST_REQ ++ | HISI_SATA1_SRST_REQ ++ | HISI_SATA_RX2_SRST_REQ ++ | HISI_SATA2_SRST_REQ; ++ } ++ } else if (ports_num == 2) { ++ if (mplx_port0) { ++ tmp_val |= HISI_SATA_RX1_SRST_REQ ++ | HISI_SATA1_SRST_REQ ++ | HISI_SATA_RX2_SRST_REQ ++ | HISI_SATA2_SRST_REQ; ++ } else { ++ tmp_val |= HISI_SATA_RX0_SRST_REQ ++ | HISI_SATA0_SRST_REQ ++ | HISI_SATA_RX1_SRST_REQ ++ | HISI_SATA1_SRST_REQ; ++ } ++ } else if (ports_num == 1) { ++ tmp_val |= HISI_SATA_RX1_SRST_REQ ++ | HISI_SATA1_SRST_REQ; ++ } ++ ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG74); ++} ++ ++static void hisi_sata_unreset(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG74); ++ ++ tmp_val &= ~(HISI_SATA_BUS_SRST_REQ | HISI_SATA_CKO_ALIVE_SRST_REQ); ++ ++ if (ports_num == 4) { ++ tmp_val &= ~(HISI_SATA_RX0_SRST_REQ ++ | HISI_SATA0_SRST_REQ ++ | HISI_SATA_RX1_SRST_REQ ++ | HISI_SATA1_SRST_REQ ++ | HISI_SATA_RX2_SRST_REQ ++ | HISI_SATA2_SRST_REQ ++ | HISI_SATA_RX3_SRST_REQ ++ | HISI_SATA3_SRST_REQ); ++ } else if (ports_num == 3) { ++ if (mplx_port0) { ++ tmp_val &= ~(HISI_SATA_RX1_SRST_REQ ++ | HISI_SATA1_SRST_REQ ++ | HISI_SATA_RX2_SRST_REQ ++ | HISI_SATA2_SRST_REQ ++ | HISI_SATA_RX3_SRST_REQ ++ | HISI_SATA3_SRST_REQ); ++ } else { ++ tmp_val &= ~(HISI_SATA_RX0_SRST_REQ ++ | HISI_SATA0_SRST_REQ ++ | HISI_SATA_RX1_SRST_REQ ++ | HISI_SATA1_SRST_REQ ++ | HISI_SATA_RX2_SRST_REQ ++ | HISI_SATA2_SRST_REQ); ++ } ++ } else if (ports_num == 2) { ++ if (mplx_port0) { ++ tmp_val &= ~(HISI_SATA_RX1_SRST_REQ ++ | HISI_SATA1_SRST_REQ ++ | HISI_SATA_RX2_SRST_REQ ++ | HISI_SATA2_SRST_REQ); ++ } else { ++ tmp_val &= ~(HISI_SATA_RX0_SRST_REQ ++ | HISI_SATA0_SRST_REQ ++ | HISI_SATA_RX1_SRST_REQ ++ | HISI_SATA1_SRST_REQ); ++ } ++ } else if (ports_num == 1) { ++ tmp_val &= ~(HISI_SATA_RX1_SRST_REQ ++ | HISI_SATA1_SRST_REQ); ++ } ++ ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG74); ++} ++ ++static void hisi_sata_phy_reset(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG72); ++ ++ if (ports_num == 4) ++ tmp_val |= HISI_SATA_PHY0_RST | HISI_SATA_PHY1_RST; ++ if (ports_num == 3) { ++ if (mplx_port0) ++ tmp_val |= HISI_SATA_PHY1A_RST | HISI_SATA_PHY0_RST; ++ else ++ tmp_val |= HISI_SATA_PHY1_RST | HISI_SATA_PHY0B_RST; ++ } ++ if (ports_num == 2) { ++ if (mplx_port0) ++ tmp_val |= HISI_SATA_PHY1A_RST | HISI_SATA_PHY0B_RST; ++ else ++ tmp_val |= HISI_SATA_PHY1_RST; ++ } ++ if (ports_num == 1) ++ tmp_val |= HISI_SATA_PHY1A_RST; ++ ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG72); ++} ++ ++static void hisi_sata_phy_unreset(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG72); ++ ++ if (ports_num == 4) ++ tmp_val &= ~(HISI_SATA_PHY0_RST | HISI_SATA_PHY1_RST); ++ if (ports_num == 3) { ++ if (mplx_port0) ++ tmp_val &= ~(HISI_SATA_PHY1A_RST | HISI_SATA_PHY0_RST); ++ else ++ tmp_val &= ~(HISI_SATA_PHY1_RST | HISI_SATA_PHY0B_RST); ++ } ++ if (ports_num == 2) { ++ if (mplx_port0) ++ tmp_val &= ~(HISI_SATA_PHY1A_RST | HISI_SATA_PHY0B_RST); ++ else ++ tmp_val &= ~HISI_SATA_PHY1_RST; ++ } ++ if (ports_num == 1) ++ tmp_val &= ~HISI_SATA_PHY1A_RST; ++ ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG72); ++} ++ ++static void hisi_sata_clk_enable(void) ++{ ++} ++static void hisi_sata_clk_disable(void) ++{ ++} ++ ++static void hisi_sata_clk_reset(void) ++{ ++} ++ ++static void hisi_sata_phy_clk_sel(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG72); ++ tmp_val |= HISI_SATA_CLK_VALUE; ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG72); ++} ++ ++void hisi_sata_set_fifoth(void *mmio) ++{ ++ int i, port_no; ++ ++ for (i = 0; i < ports_num; i++) { ++ port_no = i; ++ if (mplx_port0) ++ port_no++; ++ ++ writel(HISI_SATA_FIFOTH_VALUE, (mmio + 0x100 + port_no*0x80 ++ + HISI_SATA_PORT_FIFOTH)); ++ } ++} ++EXPORT_SYMBOL(hisi_sata_set_fifoth); ++ ++void hisi_sata_phy_config(void *mmio, int phy_mode) ++{ ++ unsigned int tmp, phy_config = PHY_CONFIG_3G; ++ unsigned int phy_sg = PHY_SG_3G; ++ int i, port_no; ++ ++ hisi_sata_set_fifoth(mmio); ++ ++ tmp = readl(mmio + HISI_SATA_PHY_CTL1); ++ tmp |= HISI_SATA_BIGENDINE; ++ writel(tmp, (mmio + HISI_SATA_PHY_CTL1)); ++ tmp = readl(mmio + HISI_SATA_PHY_CTL2); ++ tmp |= HISI_SATA_BIGENDINE; ++ writel(tmp, (mmio + HISI_SATA_PHY_CTL2)); ++ ++ tmp = readl(mmio + HISI_SATA_RST_PHY_MASK); ++ tmp &= 0xffffff0f; ++ if (ports_num == 1) ++ tmp |= HISI_SATA_PHY0_RST_MASK | HISI_SATA_PHY1B_RST_MASK; ++ if (ports_num == 2) { ++ if (mplx_port0) ++ tmp |= HISI_SATA_PHY1B_RST_MASK | HISI_SATA_PHY0A_RST_MASK; ++ else ++ tmp |= HISI_SATA_PHY0_RST_MASK; /* mode:2,3 */ ++ } ++ if (ports_num == 3) { ++ if (mplx_port0) ++ tmp |= HISI_SATA_PHY1B_RST_MASK; /* mode:8 */ ++ else ++ tmp |= HISI_SATA_PHY0A_RST_MASK; /* mode:1 */ ++ } ++ writel(tmp, (mmio + HISI_SATA_RST_PHY_MASK)); ++ ++ if (phy_mode == PHY_MODE_1_5G) { ++ phy_config = PHY_CONFIG_1_5G; ++ phy_sg = PHY_SG_1_5G; ++ } ++ ++ if (phy_mode == PHY_MODE_3G) { ++ phy_config = PHY_CONFIG_3G; ++ phy_sg = PHY_SG_3G; ++ } ++ ++ if (phy_mode == PHY_MODE_6G) { ++ phy_config = PHY_CONFIG_6G; ++ phy_sg = PHY_SG_6G; ++ } ++ ++ for (i = 0; i < ports_num; i++) { ++ port_no = i; ++ if (mplx_port0) ++ port_no++; ++ ++ if (port_no == 0) { ++ writel(0x439, (void *)HISI_SATA_MISC_COMB_PHY1); ++ writel(0x479, (void *)HISI_SATA_MISC_COMB_PHY1); ++ writel(0x439, (void *)HISI_SATA_MISC_COMB_PHY1); ++ writel(0x0, (void *)HISI_SATA_MISC_COMB_PHY1); ++ ++ writel(0x822, (void *)HISI_SATA_MISC_COMB_PHY1); ++ writel(0x862, (void *)HISI_SATA_MISC_COMB_PHY1); ++ writel(0x822, (void *)HISI_SATA_MISC_COMB_PHY1); ++ writel(0x0, (void *)HISI_SATA_MISC_COMB_PHY1); ++ ++ writel(0x421, (void *)HISI_SATA_MISC_COMB_PHY1); ++ writel(0x461, (void *)HISI_SATA_MISC_COMB_PHY1); ++ writel(0x421, (void *)HISI_SATA_MISC_COMB_PHY1); ++ writel(0x0, (void *)HISI_SATA_MISC_COMB_PHY1); ++ } else if (port_no == 1) { ++ writel(0x419, (void *)HISI_SATA_MISC_COMB_PHY1); ++ writel(0x459, (void *)HISI_SATA_MISC_COMB_PHY1); ++ writel(0x419, (void *)HISI_SATA_MISC_COMB_PHY1); ++ writel(0x0, (void *)HISI_SATA_MISC_COMB_PHY1); ++ ++ writel(0x802, (void *)HISI_SATA_MISC_COMB_PHY1); ++ writel(0x842, (void *)HISI_SATA_MISC_COMB_PHY1); ++ writel(0x802, (void *)HISI_SATA_MISC_COMB_PHY1); ++ writel(0x0, (void *)HISI_SATA_MISC_COMB_PHY1); ++ ++ writel(0x401, (void *)HISI_SATA_MISC_COMB_PHY1); ++ writel(0x441, (void *)HISI_SATA_MISC_COMB_PHY1); ++ writel(0x401, (void *)HISI_SATA_MISC_COMB_PHY1); ++ writel(0x0, (void *)HISI_SATA_MISC_COMB_PHY1); ++ } else if (port_no == 2) { ++ writel(0x439, (void *)HISI_SATA_MISC_COMB_PHY0); ++ writel(0x479, (void *)HISI_SATA_MISC_COMB_PHY0); ++ writel(0x439, (void *)HISI_SATA_MISC_COMB_PHY0); ++ writel(0x0, (void *)HISI_SATA_MISC_COMB_PHY0); ++ ++ writel(0x822, (void *)HISI_SATA_MISC_COMB_PHY0); ++ writel(0x862, (void *)HISI_SATA_MISC_COMB_PHY0); ++ writel(0x822, (void *)HISI_SATA_MISC_COMB_PHY0); ++ writel(0x0, (void *)HISI_SATA_MISC_COMB_PHY0); ++ ++ writel(0x421, (void *)HISI_SATA_MISC_COMB_PHY0); ++ writel(0x461, (void *)HISI_SATA_MISC_COMB_PHY0); ++ writel(0x421, (void *)HISI_SATA_MISC_COMB_PHY0); ++ writel(0x0, (void *)HISI_SATA_MISC_COMB_PHY0); ++ } else if (port_no == 3) { ++ writel(0x419, (void *)HISI_SATA_MISC_COMB_PHY0); ++ writel(0x459, (void *)HISI_SATA_MISC_COMB_PHY0); ++ writel(0x419, (void *)HISI_SATA_MISC_COMB_PHY0); ++ writel(0x0, (void *)HISI_SATA_MISC_COMB_PHY0); ++ ++ writel(0x802, (void *)HISI_SATA_MISC_COMB_PHY0); ++ writel(0x842, (void *)HISI_SATA_MISC_COMB_PHY0); ++ writel(0x802, (void *)HISI_SATA_MISC_COMB_PHY0); ++ writel(0x0, (void *)HISI_SATA_MISC_COMB_PHY0); ++ ++ writel(0x401, (void *)HISI_SATA_MISC_COMB_PHY0); ++ writel(0x441, (void *)HISI_SATA_MISC_COMB_PHY0); ++ writel(0x401, (void *)HISI_SATA_MISC_COMB_PHY0); ++ writel(0x0, (void *)HISI_SATA_MISC_COMB_PHY0); ++ } ++ } ++ ++ for (i = 0; i < ports_num; i++) { ++ port_no = i; ++ if (mplx_port0) ++ port_no++; ++ ++ writel(phy_config, (mmio + 0x100 + port_no*0x80 ++ + HISI_SATA_PORT_PHYCTL)); ++ ++ writel(phy_sg, (mmio + 0x100 + port_no*0x80 ++ + HISI_SATA_PORT_PHYCTL1)); ++ } ++} +diff --git a/drivers/phy/hibvt/phy-hi3536d-usb.c b/drivers/phy/hibvt/phy-hi3536d-usb.c +new file mode 100644 +index 0000000..ffd1b58 +--- /dev/null ++++ b/drivers/phy/hibvt/phy-hi3536d-usb.c +@@ -0,0 +1,210 @@ ++#include ++#include ++#include ++#include "phy-hisi-usb.h" ++ ++#define USB2_CTRL 0xb8 ++#define USB2_BUS_CKEN (1 << 0) ++#define USB2_OHCI48M_CKEN (1 << 1) ++#define USB2_OHCI12M_CKEN (1 << 2) ++#define USB2_HST_PHY_CKEN (1 << 4) ++#define USB2_UTMI0_CKEN (1 << 5) ++#define USB2_UTMI1_CKEN (1 << 6) ++#define USB2_BUS_SRST_REQ (1 << 12) ++#define USB2_UTMI0_SRST_REQ (1 << 13) ++#define USB2_UTMI1_SRST_REQ (1 << 14) ++#define USB2_HST_PHY_SYST_REQ (1 << 16) ++ ++#define REG_USB2_PHY0 0xbc ++#define USB_PHY0_REF_CKEN (1 << 0) ++#define USB_PHY0_SRST_REQ (1 << 1) ++#define USB_PHY0_SRST_TREQ (1 << 2) ++#define USB_PHY1_SRST_TREQ (1 << 3) ++#define USB_PHY0_TEST_SRST_REQ (1 << 4) ++ ++#define MISC_CTRL_TRIM 0x50 ++#define USB_R_TUNING_1 0x800c ++#define USB_R_TUNING_2 0x840c ++#define MISC_CTRL20_23 (1 << 23) ++#define MISC_CTRL20_24 (1 << 24) ++#define MISC_CTRL20_25 (1 << 25) ++#define MISC_CTRL20_26 (1 << 26) ++#define MISC_CTRL20_27 (1 << 27) ++#define TRIM_CONFIG_2 (1 << 2) ++#define TRIM_CONFIG_3 (1 << 3) ++#define TRIM_CONFIG_4 (1 << 4) ++#define TRIM_CONFIG_5 (1 << 5) ++#define TRIM_CONFIG_6 (1 << 6) ++ ++#define MISC_CTRL (1 << 22) ++#define REG_USB2_CFG 0x8018 ++#define USB2_CFG_VAL 0x05 ++#define USB2_PHY0_CTLL 0x54 ++ ++/* param config */ ++#define EYE_HEIGHT_CFG 0x8008 ++#define EYE_HEIGHT_RECFG 0x8408 ++#define EYE_HEIGHT_VAL 0x5c ++ ++#define PRE_OPEN_CFG 0x8000 ++#define PRE_OPEN_RECFG 0x8400 ++#define PRE_OPEN_VAL 0x1c ++ ++#define PRE_IMP_CFG 0x8014 ++#define PRE_IMP_RECFG 0x8414 ++#define PRE_IMP_VAL 0x80 ++ ++#define DISC_CFG 0x8010 ++#define DISC_RECFG 0x8410 ++#define DISC_CFG_VAL 0x17 ++ ++ ++void hisi_usb_phy_on(struct phy *phy) ++{ ++ int reg, trim_reg; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ /* misc ctrl */ ++ reg = readl(priv->misc_ctrl + USB2_PHY0_CTLL); ++ reg |= MISC_CTRL; ++ writel_relaxed(reg, priv->misc_ctrl + USB2_PHY0_CTLL); ++ udelay(200); ++ ++ /* reset enable */ ++ reg = readl(priv->peri_ctrl + USB2_CTRL); ++ reg |= (USB2_BUS_SRST_REQ ++ | USB2_UTMI0_SRST_REQ ++ | USB2_HST_PHY_SYST_REQ ++ | USB2_UTMI1_SRST_REQ); ++ writel(reg, priv->peri_ctrl + USB2_CTRL); ++ udelay(200); ++ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg |= (USB_PHY0_SRST_REQ ++ | USB_PHY0_SRST_TREQ ++ | USB_PHY1_SRST_TREQ); ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(200); ++ ++ /* open ref clock */ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg |= (USB_PHY0_REF_CKEN); ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(100); ++ ++ /* cancel power on reset */ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg &= ~(USB_PHY0_SRST_REQ); ++ reg &= ~(USB_PHY0_TEST_SRST_REQ); ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(300); ++ ++ writel(USB2_CFG_VAL, priv->misc_ctrl + REG_USB2_CFG); ++ udelay(200); ++ ++ /* cancel port reset */ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg &= ~(USB_PHY0_SRST_TREQ); ++ reg &= ~(USB_PHY1_SRST_TREQ); ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(300); ++ ++ /* cancel control reset */ ++ reg = readl(priv->peri_ctrl + USB2_CTRL); ++ reg &= ~(USB2_BUS_SRST_REQ ++ | USB2_UTMI0_SRST_REQ ++ | USB2_HST_PHY_SYST_REQ ++ | USB2_UTMI1_SRST_REQ); ++ reg |= (USB2_BUS_CKEN ++ | USB2_OHCI48M_CKEN ++ | USB2_OHCI12M_CKEN ++ | USB2_HST_PHY_CKEN ++ | USB2_UTMI0_CKEN ++ | USB2_UTMI1_CKEN); ++ writel(reg, priv->peri_ctrl + USB2_CTRL); ++ udelay(200); ++ ++ /* Trim config */ ++ reg = readl(priv->misc_ctrl + MISC_CTRL_TRIM); ++ reg &= (MISC_CTRL20_23 ++ | MISC_CTRL20_24 ++ | MISC_CTRL20_25 ++ | MISC_CTRL20_26 ++ | MISC_CTRL20_27); ++ reg = reg >> 21; ++ if(reg){ ++ trim_reg = readl(priv->misc_ctrl + USB_R_TUNING_1); ++ trim_reg &= ~(TRIM_CONFIG_2 ++ | TRIM_CONFIG_3 ++ | TRIM_CONFIG_4 ++ | TRIM_CONFIG_5 ++ | TRIM_CONFIG_6); ++ trim_reg |= reg; ++ writel(trim_reg, priv->misc_ctrl + USB_R_TUNING_1); ++ ++ trim_reg = readl(priv->misc_ctrl + USB_R_TUNING_2); ++ trim_reg &= ~(TRIM_CONFIG_2 ++ | TRIM_CONFIG_3 ++ | TRIM_CONFIG_4 ++ | TRIM_CONFIG_5 ++ | TRIM_CONFIG_6); ++ trim_reg |= reg; ++ writel(trim_reg, priv->misc_ctrl + USB_R_TUNING_2); ++ } ++ ++ /* eye height config */ ++ writel_relaxed(EYE_HEIGHT_VAL, priv->misc_ctrl + EYE_HEIGHT_CFG); ++ udelay(100); ++ writel_relaxed(EYE_HEIGHT_VAL, priv->misc_ctrl + EYE_HEIGHT_RECFG); ++ udelay(100); ++ ++ /* pre open */ ++ writel_relaxed(PRE_OPEN_VAL, priv->misc_ctrl + PRE_OPEN_CFG); ++ udelay(100); ++ writel_relaxed(PRE_OPEN_VAL, priv->misc_ctrl + PRE_OPEN_RECFG); ++ udelay(100); ++ ++ /* pre improve */ ++ writel_relaxed(PRE_IMP_VAL, priv->misc_ctrl + PRE_IMP_CFG); ++ udelay(100); ++ writel_relaxed(PRE_IMP_VAL, priv->misc_ctrl + PRE_IMP_RECFG); ++ udelay(100); ++ ++ /* disconnects */ ++ writel_relaxed(DISC_CFG_VAL, priv->misc_ctrl + DISC_CFG); ++ udelay(100); ++ writel_relaxed(DISC_CFG_VAL, priv->misc_ctrl + DISC_RECFG); ++ udelay(100); ++} ++EXPORT_SYMBOL(hisi_usb_phy_on); ++ ++void hisi_usb_phy_off(struct phy *phy) ++{ ++ int reg; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg |= (USB_PHY0_SRST_REQ ++ | USB_PHY0_SRST_TREQ ++ | USB_PHY1_SRST_TREQ); ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(100); ++ ++ /* close clock */ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg &= ~USB_PHY0_REF_CKEN; ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(300); ++ ++ /* close clock */ ++ reg = readl(priv->peri_ctrl + USB2_CTRL); ++ reg &= ~(USB2_BUS_CKEN ++ | USB2_OHCI48M_CKEN ++ | USB2_OHCI12M_CKEN ++ | USB2_HST_PHY_CKEN ++ | USB2_UTMI0_CKEN ++ | USB2_UTMI1_CKEN); ++ writel(reg, priv->peri_ctrl + USB2_CTRL); ++ udelay(200); ++} ++EXPORT_SYMBOL(hisi_usb_phy_off); +diff --git a/drivers/phy/hibvt/phy-hi3536dv100-sata.c b/drivers/phy/hibvt/phy-hi3536dv100-sata.c +new file mode 100644 +index 0000000..06f20d4 +--- /dev/null ++++ b/drivers/phy/hibvt/phy-hi3536dv100-sata.c +@@ -0,0 +1,208 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++ ++#include "phy-hisi-sata.h" ++ ++enum { ++ HISI_SATA_PERI_CTRL = IO_ADDRESS(REG_CRG_BASE), ++ HISI_SATA_PERI_CRG44 = (HISI_SATA_PERI_CTRL + 0xB0), ++ HISI_SATA_PERI_CRG45 = (HISI_SATA_PERI_CTRL + 0xB4), ++ HISI_SATAPHY_MISC_CTRL = IO_ADDRESS(REG_MISC_CTRL_BASE), ++ HISI_SATAPHY_MISC_CTRL22 = (HISI_SATAPHY_MISC_CTRL + 0x58), ++ ++ HISI_SATA_PHY0_CLK_EN = (1 << 0), ++ HISI_SATA_PHY0_RST = (1 << 1), ++ HISI_SATA_PHY0_REFCLK_SEL_MASK = (0x3 << 2), ++ HISI_SATA_PHY0_REFCLK_SEL = (0x2 << 2), ++ ++ HISI_SATA_BUS_CKEN = (1 << 0), ++ HISI_SATA_RX0_CKEN = (1 << 1), ++ HISI_SATA_CKO_ALIVE_CKEN = (1 << 2), ++ HISI_SATA_TX0_CKEN = (1 << 3), ++ HISI_SATA_BUS_SRST_REQ = (1 << 8), ++ HISI_SATA_CKO_ALIVE_SRST_REQ = (1 << 9), ++ HISI_SATA_RX0_SRST_REQ = (1 << 10), ++ HISI_SATA0_SRST_REQ = (1 << 11), ++ ++ FIFOTH_VALUE = 0xFEED9F24, ++ PHY_CONFIG_1_5G = 0x0e180000, ++ PHY_CONFIG_3G = 0x0e390000, ++ ++ PHY_SG_1_5G = 0x50438, ++ PHY_SG_3G = 0x50438, ++}; ++ ++static void hisi_sata_poweron(void) ++{ ++} ++ ++static void hisi_sata_poweroff(void) ++{ ++} ++ ++void hisi_sata_reset_rxtx_assert(unsigned int port_no) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG45); ++ ++ tmp_val |= HISI_SATA_RX0_SRST_REQ | HISI_SATA0_SRST_REQ; ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG45); ++} ++EXPORT_SYMBOL(hisi_sata_reset_rxtx_assert); ++ ++void hisi_sata_reset_rxtx_deassert(unsigned int port_no) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG45); ++ ++ tmp_val &= ~(HISI_SATA_RX0_SRST_REQ | HISI_SATA0_SRST_REQ); ++ ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG45); ++} ++EXPORT_SYMBOL(hisi_sata_reset_rxtx_deassert); ++ ++static void hisi_sata_reset(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG45); ++ ++ tmp_val |= HISI_SATA_BUS_SRST_REQ | HISI_SATA_CKO_ALIVE_SRST_REQ ++ | HISI_SATA_RX0_SRST_REQ | HISI_SATA0_SRST_REQ; ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG45); ++} ++ ++static void hisi_sata_unreset(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG45); ++ ++ tmp_val &= ~(HISI_SATA_BUS_SRST_REQ | HISI_SATA_CKO_ALIVE_SRST_REQ ++ | HISI_SATA_RX0_SRST_REQ | HISI_SATA0_SRST_REQ); ++ ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG45); ++} ++ ++static void hisi_sata_phy_reset(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG44); ++ tmp_val |= HISI_SATA_PHY0_RST; ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG44); ++} ++ ++static void hisi_sata_phy_unreset(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG44); ++ tmp_val &= ~HISI_SATA_PHY0_RST; ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG44); ++} ++ ++static void hisi_sata_clk_enable(void) ++{ ++ unsigned int tmp_val, tmp_reg; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG44); ++ tmp_reg = readl((void *)HISI_SATA_PERI_CRG45); ++ tmp_val |= HISI_SATA_PHY0_CLK_EN; ++ tmp_reg |= HISI_SATA_RX0_CKEN | HISI_SATA_TX0_CKEN; ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG44); ++ writel(tmp_reg, (void *)HISI_SATA_PERI_CRG45); ++ ++} ++ ++static void hisi_sata_clk_disable(void) ++{ ++} ++ ++static void hisi_sata_clk_reset(void) ++{ ++} ++ ++static void hisi_sata_phy_clk_sel(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HISI_SATA_PERI_CRG44); ++ tmp_val &= ~HISI_SATA_PHY0_REFCLK_SEL_MASK; ++ tmp_val |= HISI_SATA_PHY0_REFCLK_SEL; ++ writel(tmp_val, (void *)HISI_SATA_PERI_CRG44); ++} ++ ++void hisi_sata_set_fifoth(void *mmio) ++{ ++ writel(FIFOTH_VALUE, (mmio + 0x100 + PORT_FIFOTH)); ++} ++EXPORT_SYMBOL(hisi_sata_set_fifoth); ++ ++static void hisi_sata_phy_config(void *mmio, int phy_mode) ++{ ++ unsigned int tmp_val, phy_config = PHY_CONFIG_3G; ++ unsigned int phy_sg = PHY_SG_3G; ++ ++ hisi_sata_set_fifoth(mmio); ++ ++ tmp_val = readl(mmio + PHY_CTL1); ++ tmp_val |= PHY_DATA_INVERT; ++ writel(tmp_val, (mmio + PHY_CTL1)); ++ tmp_val = readl(mmio + PHY_CTL2); ++ tmp_val |= PHY_DATA_INVERT; ++ writel(tmp_val, (mmio + PHY_CTL2)); ++ ++ tmp_val = readl(mmio + PHY_RST_BACK_MASK); ++ tmp_val |= PHY_RST_MASK_ALL; ++ tmp_val &= ~PHY0_RST_MASK; ++ writel(tmp_val, (mmio + PHY_RST_BACK_MASK)); ++ ++ if (phy_mode == PHY_MODE_1_5G) { ++ phy_config = PHY_CONFIG_1_5G; ++ phy_sg = PHY_SG_1_5G; ++ } ++ ++ if (phy_mode == PHY_MODE_3G) { ++ phy_config = PHY_CONFIG_3G; ++ phy_sg = PHY_SG_3G; ++ } ++ ++ writel(phy_config, (mmio + 0x100 + PORT_PHYCTL)); ++ writel(phy_sg, (mmio + 0x100 + PORT_PHYCTL1)); ++ ++ /* force pll always work at 6Gbps, force cdr at 3Gbps ++ * for gen1 and at 6Gbps for gen2 ++ */ ++ writel(0x70f, (void *)HISI_SATAPHY_MISC_CTRL22); ++ writel(0x74f, (void *)HISI_SATAPHY_MISC_CTRL22); ++ writel(0x70f, (void *)HISI_SATAPHY_MISC_CTRL22); ++ writel(0x0, (void *)HISI_SATAPHY_MISC_CTRL22); ++ ++ /* disable SSC*/ ++ writel(0x802, (void *)HISI_SATAPHY_MISC_CTRL22); ++ writel(0x842, (void *)HISI_SATAPHY_MISC_CTRL22); ++ writel(0x802, (void *)HISI_SATAPHY_MISC_CTRL22); ++ writel(0x0, (void *)HISI_SATAPHY_MISC_CTRL22); ++} +diff --git a/drivers/phy/hibvt/phy-hisi-sata.c b/drivers/phy/hibvt/phy-hisi-sata.c +new file mode 100644 +index 0000000..86bedbe +--- /dev/null ++++ b/drivers/phy/hibvt/phy-hisi-sata.c +@@ -0,0 +1,171 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static unsigned int phy_mode = CONFIG_HISI_SATA_MODE; ++static unsigned int ports_num; ++unsigned int sata_port_map; ++ ++#ifdef MODULE ++module_param(mode_3g, uint, 0600); ++MODULE_PARM_DESC(phy_mode, "sata phy mode (0:1.5G;1:3G(default);2:6G)"); ++#endif ++ ++#ifdef CONFIG_ARCH_HI3536DV100 ++#include "phy-hi3536dv100-sata.c" ++#endif ++ ++#ifdef CONFIG_ARCH_HI3521A ++#include "phy-hi3521a-sata.c" ++#endif ++ ++#ifdef CONFIG_ARCH_HI3531A ++#include "phy-hi3531a-sata.c" ++#endif ++ ++static int hisi_sata_phy_init(struct phy *phy) ++{ ++ void __iomem *mmio = phy_get_drvdata(phy); ++ ++#ifdef CONFIG_ARCH_HI3531A ++ hisi_sata_get_port_info(); ++ if ((ports_num < 1) || (ports_num > 4)) { ++ pr_err("sata ports number:%d WRONG!!!\n", ports_num); ++ return -EINVAL; ++ } ++#endif ++ ++ hisi_sata_poweron(); ++ hisi_sata_reset(); ++ hisi_sata_phy_reset(); ++ hisi_sata_phy_clk_sel(); ++ hisi_sata_clk_enable(); ++ msleep(20); ++ hisi_sata_phy_unreset(); ++ msleep(20); ++ hisi_sata_unreset(); ++ msleep(20); ++ hisi_sata_phy_config(mmio, phy_mode); ++ ++ return 0; ++} ++ ++static int hisi_sata_phy_exit(struct phy *phy) ++{ ++ hisi_sata_phy_reset(); ++ msleep(20); ++ hisi_sata_reset(); ++ msleep(20); ++ hisi_sata_clk_reset(); ++ msleep(20); ++ hisi_sata_clk_disable(); ++ hisi_sata_poweroff(); ++ msleep(20); ++ ++ return 0; ++} ++ ++static struct phy_ops hisi_sata_phy_ops = { ++ .init = hisi_sata_phy_init, ++ .exit = hisi_sata_phy_exit, ++ .owner = THIS_MODULE, ++}; ++ ++static int hisi_sata_phy_probe(struct platform_device *pdev) ++{ ++ struct phy_provider *phy_provider; ++ struct device *dev = &pdev->dev; ++ struct resource *res; ++ struct phy *phy; ++ void __iomem *mmio; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(dev, "failed to get reg base\n"); ++ return -ENOENT; ++ } ++ ++ mmio = devm_ioremap(dev, res->start, resource_size(res)); ++ if (!mmio) ++ return -ENOMEM; ++ ++ phy = devm_phy_create(dev, NULL, &hisi_sata_phy_ops); ++ if (IS_ERR(phy)) { ++ dev_err(dev, "failed to create PHY\n"); ++ return PTR_ERR(phy); ++ } ++ ++ of_property_read_u32(dev->of_node, "ports_num_max", &ports_num); ++ ++ phy_set_drvdata(phy, mmio); ++ ++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ if (IS_ERR(phy_provider)) ++ return PTR_ERR(phy_provider); ++ ++ return 0; ++} ++ ++static int hisi_sata_phy_suspend(struct platform_device *pdev, ++ pm_message_t state) ++{ ++ struct device *dev = &pdev->dev; ++ struct phy *phy = to_phy(dev); ++ ++ hisi_sata_phy_exit(phy); ++ ++ return 0; ++} ++ ++static int hisi_sata_phy_resume(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct phy *phy = to_phy(dev); ++ ++ hisi_sata_phy_init(phy); ++ ++ return 0; ++} ++ ++static const struct of_device_id hisi_sata_phy_of_match[] = { ++ {.compatible = "hisilicon,hisi-sata-phy",}, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, hisi_sata_phy_of_match); ++ ++static struct platform_driver hisi_sata_phy_driver = { ++ .probe = hisi_sata_phy_probe, ++ .suspend = hisi_sata_phy_suspend, ++ .resume = hisi_sata_phy_resume, ++ .driver = { ++ .name = "hisi-sata-phy", ++ .of_match_table = hisi_sata_phy_of_match, ++ } ++}; ++module_platform_driver(hisi_sata_phy_driver); ++ ++MODULE_AUTHOR("HiSilicon BVT"); ++MODULE_DESCRIPTION("HISILICON SATA PHY driver"); ++MODULE_ALIAS("platform:hisi-sata-phy"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/phy/hibvt/phy-hisi-sata.h b/drivers/phy/hibvt/phy-hisi-sata.h +new file mode 100644 +index 0000000..a767c68 +--- /dev/null ++++ b/drivers/phy/hibvt/phy-hisi-sata.h +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++enum { ++ /* hisi extended global controller registers */ ++ PHY_CTL0 = 0xA0, ++ PHY_CTL1 = 0xA4, ++ PHY_RST_BACK_MASK = 0xAC, ++ PHY_CTL2 = 0xB0, ++ ++#define PHY_DATA_INVERT (0x1 << 3) ++#define PHY0_RST_MASK (0x1 << 4) ++#define PHY_RST_MASK_ALL (0xF << 4) ++ ++ /* hisi extended registers for each SATA port */ ++ PORT_FIFOTH = 0x44, ++ PORT_PHYCTL1 = 0x48, ++ PORT_PHYCTL = 0x74, ++ ++#define PHY_MODE_1_5G 0 ++#define PHY_MODE_3G 1 ++#define PHY_MODE_6G 2 ++}; +diff --git a/drivers/phy/hibvt/phy-hisi-usb.c b/drivers/phy/hibvt/phy-hisi-usb.c +new file mode 100644 +index 0000000..fa67598 +--- /dev/null ++++ b/drivers/phy/hibvt/phy-hisi-usb.c +@@ -0,0 +1,108 @@ ++/* ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "phy-hisi-usb.h" ++ ++static int hisi_usb_phy_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct phy *phy; ++ struct hisi_priv *priv; ++ struct device_node *np = pdev->dev.of_node; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->peri_ctrl = of_iomap(np, 0); ++ if (IS_ERR(priv->peri_ctrl)) ++ priv->peri_ctrl = NULL; ++ ++ priv->misc_ctrl = of_iomap(np, 1); ++ if (IS_ERR(priv->misc_ctrl)) ++ priv->misc_ctrl = NULL; ++ ++ priv->switch_base = of_iomap(np, 2); ++ if (IS_ERR(priv->switch_base)) ++ priv->switch_base = NULL; ++ ++ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); ++ if (!phy) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, phy); ++ phy_set_drvdata(phy, priv); ++ hisi_usb_phy_on(phy); ++ ++ return 0; ++} ++ ++static int hisi_usb_phy_remove(struct platform_device *pdev) ++{ ++ struct phy *phy = dev_get_drvdata(&pdev->dev); ++ ++ hisi_usb_phy_off(phy); ++ return 0; ++} ++ ++static const struct of_device_id hisi_usb_phy_of_match[] = { ++ {.compatible = "hisilicon,hisi-usb-phy",}, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, hisi_usb_phy_of_match); ++ ++#ifdef CONFIG_PM_SLEEP ++static int hisi_usb_phy_suspend(struct device *dev) ++{ ++ struct phy *phy = dev_get_drvdata(dev); ++ ++ hisi_usb_phy_off(phy); ++ return 0; ++} ++ ++static int hisi_usb_phy_resume(struct device *dev) ++{ ++ struct phy *phy = dev_get_drvdata(dev); ++ ++ hisi_usb_phy_on(phy); ++ return 0; ++} ++#endif /* CONFIG_PM_SLEEP */ ++ ++static SIMPLE_DEV_PM_OPS(hisi_usb2_pm_ops, hisi_usb_phy_suspend, ++ hisi_usb_phy_resume); ++ ++static struct platform_driver hisi_usb_phy_driver = { ++ .probe = hisi_usb_phy_probe, ++ .remove = hisi_usb_phy_remove, ++ .driver = { ++ .name = "hisi-usb-phy", ++ .pm = &hisi_usb2_pm_ops, ++ .of_match_table = hisi_usb_phy_of_match, ++ } ++}; ++module_platform_driver(hisi_usb_phy_driver); ++ ++MODULE_AUTHOR("Pengcheng Li "); ++MODULE_DESCRIPTION("HISILICON USB PHY driver"); ++MODULE_ALIAS("platform:hisi-usb-phy"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/phy/hibvt/phy-hisi-usb.h b/drivers/phy/hibvt/phy-hisi-usb.h +new file mode 100644 +index 0000000..e2c7e3c +--- /dev/null ++++ b/drivers/phy/hibvt/phy-hisi-usb.h +@@ -0,0 +1,11 @@ ++extern void hisi_usb_phy_on(struct phy *phy); ++extern void hisi_usb_phy_off(struct phy *phy); ++extern void hisi_usb3_phy_on(struct phy *phy); ++extern void hisi_usb3_phy_off(struct phy *phy); ++ ++struct hisi_priv { ++ void __iomem *base; ++ void __iomem *peri_ctrl; ++ void __iomem *misc_ctrl; ++ void __iomem *switch_base; ++}; +diff --git a/drivers/phy/hibvt/phy-hisi-usb3.c b/drivers/phy/hibvt/phy-hisi-usb3.c +new file mode 100644 +index 0000000..7d698bb +--- /dev/null ++++ b/drivers/phy/hibvt/phy-hisi-usb3.c +@@ -0,0 +1,110 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "phy-hisi-usb.h" ++ ++static int hisi_usb3_phy_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct phy *phy; ++ struct hisi_priv *priv; ++ struct device_node *np = pdev->dev.of_node; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->peri_ctrl = of_iomap(np, 0); ++ if (IS_ERR(priv->peri_ctrl)) ++ priv->peri_ctrl = NULL; ++ ++ priv->misc_ctrl = of_iomap(np, 1); ++ if (IS_ERR(priv->misc_ctrl)) ++ priv->misc_ctrl = NULL; ++ ++ priv->switch_base = of_iomap(np, 2); ++ if (IS_ERR(priv->switch_base)) ++ priv->switch_base = NULL; ++ ++ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); ++ if (!phy) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, phy); ++ phy_set_drvdata(phy, priv); ++ hisi_usb3_phy_on(phy); ++ ++ return 0; ++} ++ ++static int hisi_usb3_phy_remove(struct platform_device *pdev) ++{ ++ struct phy *phy = dev_get_drvdata(&pdev->dev); ++ ++ hisi_usb3_phy_off(phy); ++ return 0; ++} ++ ++static const struct of_device_id hisi_usb3_phy_of_match[] = { ++ {.compatible = "hisilicon,hisi-usb3-phy",}, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, hisi_usb3_phy_of_match); ++ ++#ifdef CONFIG_PM_SLEEP ++static int hisi_usb3_phy_suspend(struct device *dev) ++{ ++ struct phy *phy = dev_get_drvdata(dev); ++ ++ hisi_usb3_phy_off(phy); ++ return 0; ++} ++ ++static int hisi_usb3_phy_resume(struct device *dev) ++{ ++ struct phy *phy = dev_get_drvdata(dev); ++ ++ hisi_usb3_phy_on(phy); ++ return 0; ++} ++#endif /* CONFIG_PM_SLEEP */ ++ ++static SIMPLE_DEV_PM_OPS(hisi_usb3_pm_ops, hisi_usb3_phy_suspend, ++ hisi_usb3_phy_resume); ++ ++static struct platform_driver hisi_usb3_phy_driver = { ++ .probe = hisi_usb3_phy_probe, ++ .remove = hisi_usb3_phy_remove, ++ .driver = { ++ .name = "hisi-usb3-phy", ++ .pm = &hisi_usb3_pm_ops, ++ .of_match_table = hisi_usb3_phy_of_match, ++ } ++}; ++ ++module_platform_driver(hisi_usb3_phy_driver); ++ ++MODULE_AUTHOR("Chen zequn "); ++MODULE_DESCRIPTION("HISILICON USB PHY driver"); ++MODULE_ALIAS("platform:hisi-usb3-phy"); ++MODULE_LICENSE("GPL v2"); ++ +diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile +index 2142a5d..4001811 100644 +--- a/drivers/regulator/Makefile ++++ b/drivers/regulator/Makefile +@@ -5,6 +5,7 @@ + + obj-$(CONFIG_REGULATOR) += core.o dummy.o fixed-helper.o helpers.o devres.o + obj-$(CONFIG_OF) += of_regulator.o ++obj-$(CONFIG_ARCH_HI3559AV100) += hi3559av100-regulator.o + obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o + obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o + obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o +diff --git a/drivers/regulator/hi3559av100-regulator.c b/drivers/regulator/hi3559av100-regulator.c +new file mode 100644 +index 0000000..0154127 +--- /dev/null ++++ b/drivers/regulator/hi3559av100-regulator.c +@@ -0,0 +1,180 @@ ++/* ++ * Device driver for regulators in hi3559a IC ++ * ++ * Copyright (c) <2011-2015> HiSilicon Technologies Co., Ltd. ++ * http://www.hisilicon.com ++ * ++ * 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. ++ */ ++ ++ ++#define DRVNAME "hi3559a-regulator" ++#define pr_fmt(fmt) DRVNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define HISI_GPU_REGULATOR_MIN 0x19f ++#define HISI_GPU_REGULATOR_MAX 0x01 ++#define PWM_DUTY_MASK 0xffff0000 ++#define PWM_PERIOD_MASK 0xffff ++ ++struct hi3559a_gpu_regulator { ++ struct regulator_desc desc; ++ struct regulator_dev *regdev; ++ void __iomem *base; ++ int min_uV; ++ int max_uV; ++}; ++ ++static int hi3559a_gpu_regulator_get_voltage(struct regulator_dev *regdev) ++{ ++ struct hi3559a_gpu_regulator *reg = rdev_get_drvdata(regdev); ++ u32 duty, volt; ++ unsigned int vmax, vmin; ++ ++ vmax = reg->max_uV / 1000; ++ vmin = reg->min_uV / 1000; ++ ++ duty = readl(reg->base); ++ duty = (duty >> 16); ++ ++ if (duty > HISI_GPU_REGULATOR_MIN || duty < HISI_GPU_REGULATOR_MAX) ++ return 0; ++ ++ volt = reg->max_uV - (duty * 1000 * (vmax - vmin) + (vmax - vmin)/2) / 416 ; ++ ++ return volt; ++} ++ ++static int hi3559a_gpu_regulator_set_voltage(struct regulator_dev *regdev, ++ int min_uV, int max_uV, ++ unsigned *selector) ++{ ++ struct hi3559a_gpu_regulator *reg = rdev_get_drvdata(regdev); ++ u32 duty, value, mask; ++ unsigned int vmax, vmin; ++ ++ vmax = reg->max_uV / 1000; ++ vmin = reg->min_uV / 1000; ++ ++ duty = ((vmax - min_uV/1000) * 416 - (vmax - vmin)/2) / (vmax - vmin); ++ ++ value = readl(reg->base); ++ mask = PWM_DUTY_MASK; ++ value &= ~mask; ++ value |= (duty << 16); ++ ++ writel(value, reg->base); ++ ++ udelay(1000); ++ return 0; ++} ++ ++static struct regulator_ops hi3559a_gpu_regulator_ops = { ++ .get_voltage = hi3559a_gpu_regulator_get_voltage, ++ .set_voltage = hi3559a_gpu_regulator_set_voltage, ++}; ++ ++static int hi3559a_regulator_probe(struct platform_device *pdev) ++{ ++ struct hi3559a_gpu_regulator *reg; ++ struct regulator_init_data *init_data; ++ struct regulator_config config = {0}; ++ struct resource *res; ++ char *pname; ++ ++ reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL); ++ if (!reg) { ++ dev_err(&pdev->dev, "Unable to malloc memory\n"); ++ return -ENOMEM; ++ } ++ ++ pname = "base-address"; ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname); ++ if (!res) { ++ dev_err(&pdev->dev, "get resource %s failed\n", pname); ++ return -ENODEV; ++ } ++ ++ reg->base = devm_ioremap_nocache(&pdev->dev, res->start, ++ resource_size(res)); ++ if (!reg->base) { ++ devm_kfree(&pdev->dev, reg); ++ dev_err(&pdev->dev, "Unable to map '%s'\n", pname); ++ return -ENOMEM; ++ } ++ ++ reg->desc.name = dev_name(&pdev->dev); ++ reg->desc.type = REGULATOR_VOLTAGE; ++ reg->desc.owner = THIS_MODULE; ++ reg->desc.continuous_voltage_range = true; ++ ++ init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node, ®->desc); ++ if (!init_data) { ++ devm_iounmap(&pdev->dev, reg->base); ++ devm_kfree(&pdev->dev, reg); ++ return -EINVAL; ++ } ++ ++ init_data->constraints.apply_uV = 0; ++ reg->min_uV = init_data->constraints.min_uV; ++ reg->max_uV = init_data->constraints.max_uV; ++ ++ if (reg->min_uV >= reg->max_uV) { ++ devm_iounmap(&pdev->dev, reg->base); ++ devm_kfree(&pdev->dev, reg); ++ dev_err(&pdev->dev, "max_uV(%d) should bigger than min_uV(%d)\n", reg->max_uV, reg->min_uV); ++ return -EINVAL; ++ } ++ ++ reg->desc.ops = &hi3559a_gpu_regulator_ops; ++ ++ config.dev = &pdev->dev; ++ config.init_data = init_data; ++ config.driver_data = reg; ++ config.of_node = pdev->dev.of_node; ++ ++ reg->regdev = devm_regulator_register(&pdev->dev, ®->desc, &config); ++ if (IS_ERR(reg->regdev)) { ++ devm_iounmap(&pdev->dev, reg->base); ++ devm_kfree(&pdev->dev, reg); ++ dev_err(&pdev->dev, "devm_regulator_register failed\n"); ++ return PTR_ERR(reg->regdev); ++ } ++ ++ platform_set_drvdata(pdev, reg); ++ ++ return 0; ++} ++ ++static const struct of_device_id hi3559a_regulator_of_match[] = { ++ { .compatible = "hisilicon,hi3559a-volt", }, ++ { } ++}; ++ ++static struct platform_driver hi3559a_regulator_driver = { ++ .probe = hi3559a_regulator_probe, ++ .driver = { ++ .name = DRVNAME, ++ .owner = THIS_MODULE, ++ .of_match_table = hi3559a_regulator_of_match, ++ }, ++}; ++ ++module_platform_driver(hi3559a_regulator_driver); ++ ++MODULE_AUTHOR("Hisilicon GPU Team"); ++MODULE_DESCRIPTION("hi3559a regulator"); ++MODULE_LICENSE("GPLv2"); ++MODULE_ALIAS("platform:hi3559a-regulator"); +diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig +index 0723c97..71c40b1 100644 +--- a/drivers/rtc/Kconfig ++++ b/drivers/rtc/Kconfig +@@ -3,7 +3,7 @@ + # + + config RTC_LIB +- bool ++ bool "Real Time Clock LIB" + + config RTC_MC146818_LIB + bool +@@ -824,6 +824,14 @@ comment "Platform RTC drivers" + # requires defining CMOS_READ/CMOS_WRITE, and a + # global rtc_lock ... it's not yet just another platform_device. + ++config RTC_DRV_HIBVT ++ tristate "HiSilicon BVT RTC support" ++ help ++ Generic RTC framework driver for HiSilicon BVT SoCs. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called rtc-hibvt. ++ + config RTC_DRV_CMOS + tristate "PC-style 'CMOS'" + depends on X86 || ARM || M32R || PPC || MIPS || SPARC64 || MN10300 +diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile +index 1ac694a..c308468 100644 +--- a/drivers/rtc/Makefile ++++ b/drivers/rtc/Makefile +@@ -21,6 +21,7 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o + + # Keep the list ordered. + ++obj-$(CONFIG_RTC_DRV_HIBVT) += rtc-hibvt.o + obj-$(CONFIG_RTC_DRV_88PM80X) += rtc-88pm80x.o + obj-$(CONFIG_RTC_DRV_88PM860X) += rtc-88pm860x.o + obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o +diff --git a/drivers/rtc/rtc-hibvt.c b/drivers/rtc/rtc-hibvt.c +new file mode 100644 +index 0000000..86803ef +--- /dev/null ++++ b/drivers/rtc/rtc-hibvt.c +@@ -0,0 +1,581 @@ ++/* ++ * RTC driver for Hisilicon BVT ++ * Copyright (C) 2016 HiSilicon Technologies 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. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++union u_spi_rw { ++ struct { ++ unsigned int spi_wdata : 8; /* [7:0] */ ++ unsigned int spi_rdata : 8; /* [15:8] */ ++ unsigned int spi_addr : 7; /* [22:16] */ ++ unsigned int spi_rw : 1; /* [23] */ ++ unsigned int spi_start : 1; /* [24] */ ++ unsigned int reserved : 6; /* [30:25] */ ++ unsigned int spi_busy : 1; /* [31] */ ++ } bits; ++ unsigned int u32; ++}; ++ ++#define SPI_CLK_DIV (0x000) ++#define SPI_RW (0x004) ++ ++#define SPI_WRITE (0) ++#define SPI_READ (1) ++ ++/* RTC REG */ ++#define RTC_10MS_COUN 0x00 ++#define RTC_S_COUNT 0x01 ++#define RTC_M_COUNT 0x02 ++#define RTC_H_COUNT 0x03 ++#define RTC_D_COUNT_L 0x04 ++#define RTC_D_COUNT_H 0x05 ++ ++#define RTC_MR_10MS 0x06 ++#define RTC_MR_S 0x07 ++#define RTC_MR_M 0x08 ++#define RTC_MR_H 0x09 ++#define RTC_MR_D_L 0x0A ++#define RTC_MR_D_H 0x0B ++ ++#define RTC_LR_10MS 0x0C ++#define RTC_LR_S 0x0D ++#define RTC_LR_M 0x0E ++#define RTC_LR_H 0x0F ++#define RTC_LR_D_L 0x10 ++#define RTC_LR_D_H 0x11 ++ ++#define RTC_LORD 0x12 ++ ++#define RTC_IMSC 0x13 ++#define RTC_INT_CLR 0x14 ++#define RTC_INT 0x15 ++#define RTC_INT_RAW 0x16 ++ ++#define RTC_CLK 0x17 ++#define RTC_POR_N 0x18 ++#define RTC_SAR_CTRL 0x1A ++#define RTC_CLK_CFG 0x1B ++ ++#define RTC_FREQ_H 0x51 ++#define RTC_FREQ_L 0x52 ++ ++#define FREQ_H_DEFAULT 0x8 ++#define FREQ_L_DEFAULT 0x1B ++ ++#define LV_CTL_DEFAULT 0x20 ++#define CLK_DIV_DEFAULT 0x4 ++#define INT_RST_DEFAULT 0x0 ++#define INT_MSK_DEFAULT 0x4 ++ ++#define AIE_INT_MASK BIT(0) ++#define LV_INT_MASK BIT(1) ++#define REG_LOAD_STAT BIT(0) ++#define REG_LOCK_STAT BIT(1) ++#define REG_LOCK_BYPASS BIT(2) ++ ++#define RETRY_CNT 500 ++ ++#define DATE_TO_SEC(d, h, m, s) (s + m*60 + h*60*60 + d*24*60*60) ++#define SEC_TO_DAY(s) (s/(60*60*24)) ++ ++struct hibvt_rtc { ++ struct rtc_device *rtc_dev; ++ void __iomem *regs; ++ int rtc_irq; ++}; ++ ++static int hibvt_spi_write(void *spi_reg, unsigned char reg, ++ unsigned char val) ++{ ++ union u_spi_rw w_data, r_data; ++ int cnt = RETRY_CNT; ++ ++ r_data.u32 = 0; ++ w_data.u32 = 0; ++ ++ w_data.bits.spi_wdata = val; ++ w_data.bits.spi_addr = reg; ++ w_data.bits.spi_rw = SPI_WRITE; ++ w_data.bits.spi_start = 0x1; ++ ++ writel(w_data.u32, (spi_reg+SPI_RW)); ++ ++ do ++ r_data.u32 = readl(spi_reg+SPI_RW); ++ while (r_data.bits.spi_busy && (--cnt)); ++ ++ if (r_data.bits.spi_busy) ++ return -EIO; ++ ++ return 0; ++} ++ ++ ++static int hibvt_spi_rtc_write(void *spi_reg, unsigned char reg, ++ unsigned char val) ++{ ++ return hibvt_spi_write(spi_reg, reg, val); ++} ++ ++static int hibvt_spi_read(void *spi_reg, unsigned char reg, ++ unsigned char *val) ++{ ++ union u_spi_rw w_data, r_data; ++ int cnt = RETRY_CNT; ++ ++ r_data.u32 = 0; ++ w_data.u32 = 0; ++ w_data.bits.spi_addr = reg; ++ w_data.bits.spi_rw = SPI_READ; ++ w_data.bits.spi_start = 0x1; ++ ++ writel(w_data.u32, (spi_reg+SPI_RW)); ++ ++ do ++ r_data.u32 = readl(spi_reg+SPI_RW); ++ while (r_data.bits.spi_busy && (--cnt)); ++ ++ if (r_data.bits.spi_busy) ++ return -EIO; ++ ++ *val = r_data.bits.spi_rdata; ++ ++ return 0; ++} ++ ++static int hibvt_spi_rtc_read(void *spi_reg, unsigned char reg, ++ unsigned char *val) ++{ ++ return hibvt_spi_read(spi_reg, reg, val); ++} ++ ++static int hibvt_rtc_read_time(struct device *dev, struct rtc_time *time) ++{ ++ struct hibvt_rtc *rtc = dev_get_drvdata(dev); ++ unsigned char dayl, dayh; ++ unsigned char second, minute, hour; ++ unsigned long seconds = 0; ++ unsigned int day; ++ unsigned char raw_value; ++ int cnt = RETRY_CNT; ++ int ret = 0; ++ ++ ret = hibvt_spi_rtc_read(rtc->regs, RTC_INT_RAW, &raw_value); ++ if (ret) { ++ dev_err(dev, "IO err.\n"); ++ return ret; ++ } ++ ++ if (raw_value & LV_INT_MASK) { ++ //dev_err(dev, ++ // "low voltage detected, date/time is not reliable.\n"); ++ hibvt_spi_write(rtc->regs, RTC_INT_CLR, 1); ++ //return -EINVAL; ++ } ++ ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_LORD, &raw_value); ++ if (raw_value & REG_LOCK_BYPASS) ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LORD, ++ (~(REG_LOCK_BYPASS)) & raw_value); ++ ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_LORD, &raw_value); ++ /* lock the time */ ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LORD, ++ (REG_LOCK_STAT) | raw_value); ++ /* wait rtc load flag */ ++ do { ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_LORD, &raw_value); ++ msleep(20); ++ } while ((ret || (raw_value & REG_LOCK_STAT)) && (--cnt)); ++ ++ if (!ret && (raw_value & REG_LOCK_STAT)) ++ return -EBUSY; ++ ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_S_COUNT, &second); ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_M_COUNT, &minute); ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_H_COUNT, &hour); ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_D_COUNT_L, &dayl); ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_D_COUNT_H, &dayh); ++ ++ if (ret) { ++ dev_err(dev, "IO err.\n"); ++ return ret; ++ } ++ ++ day = (dayl | (dayh << 8)); ++ seconds = DATE_TO_SEC(day, hour, minute, second); ++ ++ rtc_time_to_tm(seconds, time); ++ ++ return rtc_valid_tm(time); ++} ++ ++static int hibvt_rtc_set_time(struct device *dev, struct rtc_time *time) ++{ ++ struct hibvt_rtc *rtc = dev_get_drvdata(dev); ++ unsigned char ret = 0; ++ unsigned int days; ++ unsigned long seconds = 0; ++ unsigned int cnt = RETRY_CNT; ++ unsigned char raw_value = 0; ++ ++ ret = rtc_tm_to_time(time, &seconds); ++ if (ret) ++ return ret; ++ days = SEC_TO_DAY(seconds); ++ ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LR_10MS, 0); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LR_S, time->tm_sec); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LR_M, time->tm_min); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LR_H, time->tm_hour); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LR_D_L, (days & 0xFF)); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LR_D_H, (days >> 8)); ++ ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LORD, ++ (raw_value | REG_LOAD_STAT)); ++ /* wait rtc load flag */ ++ do { ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_LORD, &raw_value); ++ msleep(20); ++ } while ((ret || (raw_value & REG_LOAD_STAT)) && (--cnt)); ++ ++ if (!ret && (raw_value & REG_LOAD_STAT)) ++ return -EBUSY; ++ ++ if (ret) ++ dev_err(dev, "IO err.\n"); ++ ++ return ret; ++} ++ ++static int hibvt_rtc_read_alarm(struct device *dev, ++ struct rtc_wkalrm *alrm) ++{ ++ struct hibvt_rtc *rtc = dev_get_drvdata(dev); ++ unsigned char dayl, dayh; ++ unsigned char second, minute, hour; ++ unsigned long seconds = 0; ++ unsigned int day; ++ unsigned char int_state = 0; ++ int ret = 0; ++ ++ memset(alrm, 0, sizeof(struct rtc_wkalrm)); ++ ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_MR_S, &second); ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_MR_M, &minute); ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_MR_H, &hour); ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_MR_D_L, &dayl); ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_MR_D_H, &dayh); ++ ++ day = (unsigned int)(dayl | (dayh << 8)); ++ seconds = DATE_TO_SEC(day, hour, minute, second); ++ ++ rtc_time_to_tm(seconds, &alrm->time); ++ ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_IMSC, &int_state); ++ if (ret) { ++ dev_err(dev, "IO err.\n"); ++ return ret; ++ } ++ ++ alrm->enabled = !!(int_state & AIE_INT_MASK); ++ alrm->pending = alrm->enabled; ++ ++ return 0; ++} ++ ++static int hibvt_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ++{ ++ struct hibvt_rtc *rtc = dev_get_drvdata(dev); ++ unsigned int days; ++ unsigned long seconds = 0; ++ unsigned char val = 0; ++ int ret = 0; ++ ++ rtc_tm_to_time(&alrm->time, &seconds); ++ ++ days = SEC_TO_DAY(seconds); ++ ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_MR_10MS, 0); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_MR_S, alrm->time.tm_sec); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_MR_M, alrm->time.tm_min); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_MR_H, alrm->time.tm_hour); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_MR_D_L, (days & 0xFF)); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_MR_D_H, (days >> 8)); ++ ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_IMSC, &val); ++ if (alrm->enabled) ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_IMSC, ++ val | AIE_INT_MASK); ++ else ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_IMSC, ++ val & ~AIE_INT_MASK); ++ ++ if (ret) { ++ dev_err(dev, "IO err.\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int hibvt_rtc_alarm_irq_enable(struct device *dev, ++ unsigned int enabled) ++{ ++ struct hibvt_rtc *rtc = dev_get_drvdata(dev); ++ unsigned char val = 0; ++ int ret = 0; ++ ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_IMSC, &val); ++ if (enabled) ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_IMSC, ++ val | AIE_INT_MASK); ++ else ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_IMSC, ++ val & ~AIE_INT_MASK); ++ ++ if (ret) { ++ dev_err(dev, "IO err.\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++ ++/* ++ * interrupt function ++ * do nothing. left for future ++ */ ++static irqreturn_t hibvt_rtc_alm_interrupt(int irq, void *data) ++{ ++ struct hibvt_rtc *rtc = (struct hibvt_rtc *)data; ++ unsigned char val = 0; ++ int ret = 0; ++ ++ ret |= hibvt_spi_read(rtc->regs, RTC_INT, &val); ++ ret |= hibvt_spi_write(rtc->regs, RTC_INT_CLR, AIE_INT_MASK); ++ ++ if (ret) { ++ dev_err(&rtc->rtc_dev->dev, "IO err.\n"); ++ return ret; ++ } ++ ++ if (val & AIE_INT_MASK) ++ rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); ++ ++ return IRQ_HANDLED; ++} ++ ++#define FREQ_MAX_VAL 3277000 ++#define FREQ_MIN_VAL 3276000 ++ ++static int hibvt_rtc_ioctl(struct device *dev, ++ unsigned int cmd, unsigned long arg) ++{ ++ struct hibvt_rtc *rtc = dev_get_drvdata(dev); ++ int ret = 0; ++ ++ switch (cmd) { ++ case RTC_PLL_SET: ++ { ++ char freq_l, freq_h; ++ struct rtc_pll_info pll_info; ++ ++ if (copy_from_user(&pll_info, (struct rtc_pll_info *)arg, ++ sizeof(struct rtc_pll_info))) ++ return -EFAULT; ++ ++ /* freq = 32700 + (freq /3052)*100 */ ++ if (pll_info.pll_value > FREQ_MAX_VAL ++ || pll_info.pll_value < FREQ_MIN_VAL) ++ return -EINVAL; ++ ++ pll_info.pll_value = (pll_info.pll_value - 3270000) ++ * 3052 / 10000; ++ ++ freq_l = (char)(pll_info.pll_value & 0xff); ++ freq_h = (char)((pll_info.pll_value >> 8) & 0xf); ++ ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_FREQ_H, freq_h); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_FREQ_L, freq_l); ++ ++ if (ret) { ++ dev_err(dev, "IO err.\n"); ++ return ret; ++ } ++ ++ return 0; ++ } ++ case RTC_PLL_GET: ++ { ++ char freq_l, freq_h; ++ struct rtc_pll_info pll_info; ++ ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_FREQ_H, &freq_h); ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_FREQ_L, &freq_l); ++ ++ if (ret) { ++ dev_err(dev, "IO err.\n"); ++ return ret; ++ } ++ ++ pll_info.pll_value = ((freq_h & 0xf) << 8) + freq_l; ++ pll_info.pll_value = 3270000 ++ + (pll_info.pll_value * 10000) / 3052; ++ ++ pll_info.pll_max = FREQ_MAX_VAL; ++ pll_info.pll_min = FREQ_MIN_VAL; ++ ++ if (copy_to_user((void __user *)arg, ++ &pll_info, sizeof(struct rtc_pll_info))) ++ return -EFAULT; ++ ++ return 0; ++ } ++ default: ++ return -ENOIOCTLCMD; ++ } ++} ++ ++static const struct rtc_class_ops hibvt_rtc_ops = { ++ .read_time = hibvt_rtc_read_time, ++ .set_time = hibvt_rtc_set_time, ++ .read_alarm = hibvt_rtc_read_alarm, ++ .set_alarm = hibvt_rtc_set_alarm, ++ .alarm_irq_enable = hibvt_rtc_alarm_irq_enable, ++ .ioctl = hibvt_rtc_ioctl, ++}; ++ ++static int hibvt_rtc_init(struct hibvt_rtc *rtc) ++{ ++ void *spi_reg = rtc->regs; ++ int ret = 0; ++ unsigned char val = 0; ++ /* ++ * clk div value = (apb_clk/spi_clk)/2-1, ++ * apb clk = 100MHz, spi_clk = 10MHz,so value= 0x4 ++ */ ++ writel(CLK_DIV_DEFAULT, (spi_reg+SPI_CLK_DIV)); ++ ++ ret |= hibvt_spi_rtc_write(spi_reg, RTC_IMSC, INT_MSK_DEFAULT); ++ ret |= hibvt_spi_rtc_write(spi_reg, RTC_SAR_CTRL, LV_CTL_DEFAULT); ++ ++ ++ ret |= hibvt_spi_rtc_write(spi_reg, RTC_CLK_CFG, 0x01); ++ ++ /* default FREQ COEF */ ++ ret |= hibvt_spi_rtc_write(spi_reg, RTC_FREQ_H, FREQ_H_DEFAULT); ++ ret |= hibvt_spi_rtc_write(spi_reg, RTC_FREQ_L, FREQ_L_DEFAULT); ++ ++ ret |= hibvt_spi_rtc_read(spi_reg, RTC_INT_RAW, &val); ++ //ret |= hibvt_spi_rtc_read(spi_reg, RTC_CLK_CFG, &val2); ++ if (ret) { ++ dev_err(&rtc->rtc_dev->dev, "IO err.\n"); ++ return ret; ++ } ++ ++ if (val & LV_INT_MASK) { ++ //dev_err(&rtc->rtc_dev->dev, ++ // "low voltage detected, date/time is not reliable.\n"); ++ hibvt_spi_write(rtc->regs, RTC_INT_CLR, 1); ++ } ++ ++ return ret; ++} ++ ++static int hibvt_rtc_probe(struct platform_device *pdev) ++{ ++ struct resource *mem; ++ struct hibvt_rtc *rtc; ++ int ret; ++ ++ rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); ++ if (!rtc) ++ return -ENOMEM; ++ ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ rtc->regs = devm_ioremap_resource(&pdev->dev, mem); ++ if (IS_ERR((const void *)rtc->regs)) { ++ dev_err(&pdev->dev, "could not map I/O memory\n"); ++ return PTR_ERR((const void *)rtc->regs); ++ } ++ ++ rtc->rtc_irq = platform_get_irq(pdev, 0); ++ ret = devm_request_irq(&pdev->dev, rtc->rtc_irq, ++ hibvt_rtc_alm_interrupt, 0, pdev->name, rtc); ++ if (ret) { ++ dev_err(&pdev->dev, "could not request irq %d\n", rtc->rtc_irq); ++ return ret; ++ } ++ ++ platform_set_drvdata(pdev, rtc); ++ rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name, ++ &hibvt_rtc_ops, THIS_MODULE); ++ if (IS_ERR(rtc->rtc_dev)) { ++ dev_err(&pdev->dev, "could not register rtc device\n"); ++ return PTR_ERR(rtc->rtc_dev); ++ } ++ ++ if (hibvt_rtc_init(rtc)) { ++ dev_err(&pdev->dev, "hibvt_rtc_init failed.\n"); ++ return -EIO; ++ } ++ ++ dev_info(&pdev->dev, "RTC driver for hibvt enabled\n"); ++ ++ return 0; ++} ++ ++static int hibvt_rtc_remove(struct platform_device *pdev) ++{ ++ return 0; ++} ++ ++static const struct of_device_id hibvt_rtc_match[] = { ++ { .compatible = "hisilicon,hi35xx-rtc" }, ++ {}, ++}; ++ ++static struct platform_driver hibvt_rtc_driver = { ++ .probe = hibvt_rtc_probe, ++ .remove = hibvt_rtc_remove, ++ .driver = { .name = "hibvt_rtc", ++ .of_match_table = hibvt_rtc_match, ++ }, ++}; ++ ++module_platform_driver(hibvt_rtc_driver); ++ ++#define OSDRV_MODULE_VERSION_STRING "HISI_rtc @HiMPP" ++ ++MODULE_AUTHOR("Hisilicon"); ++MODULE_DESCRIPTION("Hisilicon RTC driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_VERSION("HI_VERSION=" OSDRV_MODULE_VERSION_STRING); ++ +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index d8099c7..62bb8ad 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -1420,7 +1420,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q, + if (scsi_host_in_recovery(shost)) + return 0; + +- busy = atomic_inc_return(&shost->host_busy) - 1; ++ busy = atomic_read(&shost->host_busy); + if (atomic_read(&shost->host_blocked) > 0) { + if (busy) + goto starved; +@@ -1429,7 +1429,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q, + * unblock after host_blocked iterates to zero + */ + if (atomic_dec_return(&shost->host_blocked) > 0) +- goto out_dec; ++ goto out; + + SCSI_LOG_MLQUEUE(3, + shost_printk(KERN_INFO, shost, +@@ -1449,6 +1449,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q, + spin_unlock_irq(shost->host_lock); + } + ++ atomic_inc(&shost->host_busy); + return 1; + + starved: +@@ -1456,8 +1457,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q, + if (list_empty(&sdev->starved_entry)) + list_add_tail(&sdev->starved_entry, &shost->starved_list); + spin_unlock_irq(shost->host_lock); +-out_dec: +- atomic_dec(&shost->host_busy); ++out: + return 0; + } + +diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig +index e27b4d4..51cd0f9 100644 +--- a/drivers/scsi/ufs/Kconfig ++++ b/drivers/scsi/ufs/Kconfig +@@ -80,6 +80,14 @@ config SCSI_UFSHCD_PLATFORM + + If unsure, say N. + ++config SCSI_UFS_HI3559AV100 ++ tristate "Hi3559av100 Platform Support Using A Test Chip" ++ depends on SCSI_UFSHCD_PLATFORM ++ ---help--- ++ Synopsys Test Chip is a PHY for prototyping purposes. ++ ++ If unsure, say N. ++ + config SCSI_UFS_DWC_TC_PLATFORM + tristate "DesignWare platform support using a G210 Test Chip" + depends on SCSI_UFSHCD_PLATFORM +diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile +index 6e77cb0..72961fc 100644 +--- a/drivers/scsi/ufs/Makefile ++++ b/drivers/scsi/ufs/Makefile +@@ -5,3 +5,4 @@ obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o + obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o + obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o + obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o ++obj-$(CONFIG_SCSI_UFS_HI3559AV100) += hi3559av100_ufs.o +diff --git a/drivers/scsi/ufs/hi3559av100_ufs.c b/drivers/scsi/ufs/hi3559av100_ufs.c +new file mode 100644 +index 0000000..b84edf4 +--- /dev/null ++++ b/drivers/scsi/ufs/hi3559av100_ufs.c +@@ -0,0 +1,1055 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include "ufshcd.h" ++#include "unipro.h" ++#include "ufshcd-pltfrm.h" ++#include "hi3559av100_ufs.h" ++ ++#define UFS_PRINT printk ++#define UFS_AHIT_AH8ITV_MASK (0x3FF) ++#define UFS_AHIT_AUTOH8_TIMER (0x1001) ++ ++#define UFS_AHIT_OFF 0x18 ++#define UFS_UTRLRSR_OFF 0x60 ++#define UFS_UTMRLRSR_OFF 0x80 ++#define UFS_BUSTHRTL_OFF 0xC0 ++ ++#define HIBERNATE_TIMER_VALUE_MASK (~(BIT(9))) ++#define HIBERNATE_TIMER_SCALE_SHIFT (10) ++#define LP_AH8_PGE (BIT(17)) ++#define LP_PGE (BIT(16)) ++#define ULP_ULP_CTRLMODE (BIT(3)) ++ ++#define TX_SLEEP_CONTROL 0x00c80000 ++#define RX_SLEEP_CONTROL 0x00c60000 ++/* config the pll */ ++#define RG_PLL_PRE_DIV 0x00c20000 ++#define RG_PLL_SWC_EN 0x00c90000 ++#define RG_PLL_FBK_S 0x00c40000 ++#define RG_PLL_FBK_P 0x00c30000 ++#define RG_PLL_TXHSGR 0x00cf0000 ++#define RG_PLL_RXHSGR 0x00cd0000 ++ ++#define RG_PLL_TXLSGR 0x00d00000 ++#define RG_PLL_RXLSGR 0x00ce0000 ++ ++ ++/* power mode specific define */ ++struct pwrModeParams { ++ uint8_t txGear; ++ uint8_t rxGear; ++ uint8_t hsSeries; ++ uint8_t txLanes; ++ uint8_t rxLanes; ++ uint8_t pwrMode; ++}; ++struct ufs_phy_remap_add ++{ ++ void __iomem *crg_base; ++ void __iomem *misc_base; ++}; ++struct ufs_phy_remap_add remap_vir_add; ++ ++extern void ufs_dump(struct ufs_hba *hba); ++void setup_snps_mphy_tc(struct ufs_hba *hba) ++{ ++ uint32_t retry = 10; ++ uint32_t value = 0; ++ ++ do { ++ ufshcd_dme_get(hba, 0xD0100000, &value); ++ if (1 == value) ++ break; ++ mdelay(1); ++ } while (retry--); ++ ++ /* DME layer enable */ ++ ufshcd_dme_set_attr(hba, 0xd0000000, 0x00, 0x01, DME_LOCAL); ++} ++static void hiufs_pltfm_clk_init(void __iomem *crg_base) ++{ ++ uint32_t reg; ++#ifndef UFS_FPGA ++ reg = readl(crg_base); ++ reg |= BIT_UFS_CLK_EN | BIT_UFS_SRST_REQ; ++ writel(reg, crg_base); ++ udelay(1); ++ reg = readl(crg_base); ++ reg &= ~BIT_UFS_SRST_REQ; ++ writel(reg, crg_base); ++#else ++ reg = readl(crg_base); ++ reg |= UFS_SRST_REQ; ++ writel(reg, crg_base); ++ udelay(1); ++ ++ reg = readl(crg_base); ++ reg &= ~UFS_SRST_REQ; ++ writel(reg, crg_base); ++ udelay(1); ++ ++ reg = readl(crg_base); ++ reg &= ~UFS_RST_DEVICE; ++ writel(reg, crg_base); ++ udelay(1); ++ ++ reg = readl(crg_base); ++ reg |= UFS_RST_DEVICE; ++ writel(reg, crg_base); ++ udelay(1); ++#endif ++} ++static void hiufs_pltfm_hardware_init(void __iomem *misc_base) ++{ ++ uint32_t reg; ++ reg = readl(misc_base); ++ reg |= BIT_UFS_ENABLE; ++ writel(reg, misc_base); ++ udelay(1); ++ reg = readl(misc_base); ++ reg &= ~BIT_DA_UFS_REFCLK_OEN; ++ reg &= ~MASK_DA_UFS_REFCLK_DS; ++ reg |= (BIT_DA_UFS_REFCLK_DS0| ++ BIT_DA_UFS_REFCLK_DS1| ++ BIT_DA_UFS_REFCLK_SL); ++ writel(reg, misc_base); ++ udelay(1); ++ ++ reg = readl(misc_base); ++ reg &= ~(BIT_DA_UFS_RESET_OEN | ++ MASK_DA_UFS_RESET_DS | ++ BIT_UFS_PAD_RESET); ++ reg |= BIT_DA_UFS_RESET_SL; ++ writel(reg, misc_base); ++ udelay(10); ++ ++ reg = readl(misc_base); ++ reg |= BIT_UFS_PAD_RESET; ++ writel(reg, misc_base); ++ ++} ++static void hiufs_clk_hardware_init_notify(void) ++{ ++ hiufs_pltfm_clk_init(remap_vir_add.crg_base); ++ hiufs_pltfm_hardware_init(remap_vir_add.misc_base); ++} ++static int hiufs_phy_init(struct ufs_hba *hba, u32 hs_rate) ++{ ++ uint32_t val; ++ ++#ifdef COMBO_PHY_V120 ++ /*Rx SKP_DET_SEL, lane0 */ ++ ufshcd_dme_set_attr(hba, ATTR_MRX0(SKP_DET_SEL), 0x00, ++ SKP_DET_SEL_EN, DME_LOCAL); ++ /*Rx SKP_DET_SEL, lane1 */ ++ ufshcd_dme_set_attr(hba, ATTR_MRX1(SKP_DET_SEL), 0x00, ++ SKP_DET_SEL_EN, DME_LOCAL); ++ ++ /*VCO_AUTO_CHG */ ++ ufshcd_dme_set_attr(hba, 0xdf0000, 0x00, ++ (VCO_AUTO_CHG_EN | VCO_FORCE_ON_EN), DME_LOCAL); ++ ++ /*RX_SQ_VREF, lane0 */ ++ ufshcd_dme_set_attr(hba, ATTR_MRX0(RX_SQ_VREF), 0x00, ++ RX_SQ_VREF_175mv, DME_LOCAL); ++ /*RX_SQ_VREF, lane1 */ ++ ufshcd_dme_set_attr(hba, ATTR_MRX1(RX_SQ_VREF), 0x00, ++ RX_SQ_VREF_175mv, DME_LOCAL); ++ ++ /*Dif_N debouse*/ ++ ufshcd_dme_set_attr(hba, ATTR_MRX0(0xeb), 0x00, 0x60, DME_LOCAL); ++ /*Dif_N debouse*/ ++ ufshcd_dme_set_attr(hba, ATTR_MRX1(0xeb), 0x00, 0x60, DME_LOCAL); ++ ++ /*dvalid timer*/ ++ ufshcd_dme_set_attr(hba, ATTR_MRX0(0x0e), 0x00, 0x64, DME_LOCAL); ++ /*dvalid timer*/ ++ ufshcd_dme_set_attr(hba, ATTR_MRX1(0x0e), 0x00, 0x64, DME_LOCAL); ++ /*RX LINE RESET DETECT TIME*/ ++ ufshcd_dme_set_attr(hba, ATTR_MRX0(0xef), 0x00, 0xfa, DME_LOCAL); ++ /*RX LINE RESET DETECT TIME*/ ++ ufshcd_dme_set_attr(hba, ATTR_MRX1(0xef), 0x00, 0xfa, DME_LOCAL); ++ ++ /*AD_DIF_P_LS_TIMEOUT_VAL, lane0 */ ++ ufshcd_dme_set_attr(hba, ATTR_MRX0(AD_DIF_P_LS_TIMEOUT_VAL), ++ 0x00, PWM_PREPARE_TO, DME_LOCAL); ++ /*AD_DIF_P_LS_TIMEOUT_VAL, lane1 */ ++ ufshcd_dme_set_attr(hba, ATTR_MRX1(AD_DIF_P_LS_TIMEOUT_VAL), ++ 0x00, PWM_PREPARE_TO, DME_LOCAL); ++ /*RX_EQ_SEL_R, lane0 */ ++ ufshcd_dme_set_attr(hba, 0x00F40004, 0x00, 0x1, DME_LOCAL); ++ /*RX_EQ_SEL_R, lane1 */ ++ ufshcd_dme_set_attr(hba, 0x00F40005, 0x00, 0x1, DME_LOCAL); ++ ++ /*RX_EQ_SEL_C, lane0 */ ++ ufshcd_dme_set_attr(hba, 0x00F20004, 0x00, 0x3, DME_LOCAL); ++ /*RX_EQ_SEL_C, lane1 */ ++ ufshcd_dme_set_attr(hba, 0x00F20005, 0x00, 0x3, DME_LOCAL); ++ ++ /*RX_VSEL, lane0 */ ++ ufshcd_dme_set_attr(hba, 0x00FB0004, 0x00, 0x3, DME_LOCAL); ++ /*RX_VSEL, lane1 */ ++ ufshcd_dme_set_attr(hba, 0x00FB0005, 0x00, 0x3, DME_LOCAL); ++ ++ /* RX_DLF, lane0 */ ++ ufshcd_dme_set_attr(hba, 0x00f60004, 0x00, 0x3, DME_LOCAL); ++ /* RX_DLF, lane1 */ ++ ufshcd_dme_set_attr(hba, 0x00f60005, 0x00, 0x3, DME_LOCAL); ++ ++ //modefy ++ /* RX H8_TIMEOUT_VAL, lane0 */ ++ //ufshcd_dme_set_attr(hba, 0x000a0004, 0x00, 0x3, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x000a0004, 0x00, 0x1e, DME_LOCAL); ++ /* RX H8_TIMEOUT_VAL, lane1 */ ++ //ufshcd_dme_set_attr(hba, 0x000a0005, 0x00, 0x3, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x000a0005, 0x00, 0x1e, DME_LOCAL); ++ //modefy ++ ++ /* RG_PLL_DMY0 */ ++ ufshcd_dme_set_attr(hba, 0x00d40000, 0x00, 0x31, DME_LOCAL); ++ //new add ++ ufshcd_dme_set_attr(hba, 0x00730000, 0x00, 0x00000004, DME_LOCAL);/* TX_PHY_CONFIG II */ ++ ufshcd_dme_set_attr(hba, 0x00730001, 0x00, 0x00000004, DME_LOCAL);/* TX_PHY_CONFIG II */ ++ //new add ++#else ++ /* in low temperature to solve the PLL's starting of oscillation */ ++ /* RG_PLL_CP */ ++ ufshcd_dme_set_attr(hba, 0x00c10000, 0x00, 0x01, DME_LOCAL); ++ /* RG_PLL_DMY0 */ ++ ufshcd_dme_set_attr(hba, 0x00d40000, 0x00, 0x51, DME_LOCAL); ++ /* rate A->B 's VCO stable time */ ++ /*ufshcd_dme_set_attr(hba, 0x00db0000, 0x00, 0x05, DME_LOCAL);*/ ++ #ifdef COMBO_PHY_V110 ++ /* H8's workaround */ ++ /*RX_SQ_VREF, lane0 */ ++ ufshcd_dme_set_attr(hba, 0x00f10004, 0x00, 0x07, DME_LOCAL); ++ /*RX_SQ_VREF, lane1 */ ++ ufshcd_dme_set_attr(hba, 0x00f10005, 0x00, 0x07, DME_LOCAL); ++ #endif ++#endif /*end of COMBO_PHY_V120*/ ++ ++ /*RX enable, lane0 */ ++ ufshcd_dme_set_attr(hba, ATTR_MRX0(MRX_EN), 0x00, ++ MRX_ENABLE, DME_LOCAL); ++ /*RX enable, lane1 */ ++ ufshcd_dme_set_attr(hba, ATTR_MRX1(MRX_EN), 0x00, ++ MRX_ENABLE, DME_LOCAL); ++ ++ ++#if 0 ++ /* disable auto H8 */ ++ reg = ufshcd_readl(hba, UFS_AHIT_OFF); ++ reg = reg & (~UFS_AHIT_AH8ITV_MASK); ++ ufshcd_writel(hba, reg, UFS_AHIT_OFF); ++#endif ++ ++ setup_snps_mphy_tc(hba); ++ ++#if !defined(COMBO_PHY_V120) ++ /*RX_MC_PRESENT */ ++ ufshcd_dme_set_attr(hba, 0x00c20004, 0x00, 0x01, DME_LOCAL); ++ /*RX_MC_PRESENT */ ++ ufshcd_dme_set_attr(hba, 0x00c20005, 0x00, 0x01, DME_LOCAL); ++#endif ++ ++ /* disable Vswing change */ ++ /* measure the power, can close it */ ++ ufshcd_dme_set_attr(hba, 0x00C70000, 0x0, 0x3, DME_LOCAL); ++ /* measure the power, can close it */ ++ ufshcd_dme_set_attr(hba, 0x00C80000, 0x0, 0x3, DME_LOCAL); ++#if !defined(COMBO_PHY_V120) ++ ufshcd_dme_set_attr(hba, 0x007A0000, 0x0, 0x1c, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007A0001, 0x0, 0x1c, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007C0000, 0x0, 0xd4, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007C0001, 0x0, 0xd4, DME_LOCAL); ++#endif ++ /* no need to exitH8 before linkup anymore */ ++ /*exit TX_HIBERNATE_CONTROL */ ++ /*ufshcd_dme_set_attr(hba, 0x802b0000, 0x00, 0x00, DME_LOCAL);*/ ++ /*exit TX_HIBERNATE_CONTROL */ ++ /*ufshcd_dme_set_attr(hba, 0x802b0001, 0x00, 0x00, DME_LOCAL);*/ ++ /* ufs_waitms(20); */ ++#ifdef CLOSE_CLK_GATING ++ /*RX_STALL*/ ++ ufshcd_dme_set_attr(hba, 0x00cf0004, 0x00, 0x02, DME_LOCAL); ++ /*RX_STALL*/ ++ ufshcd_dme_set_attr(hba, 0x00cf0005, 0x00, 0x02, DME_LOCAL); ++ /*RX_SLEEP*/ ++ ufshcd_dme_set_attr(hba, 0x00d00004, 0x00, 0x02, DME_LOCAL); ++ /*RX_SLEEP*/ ++ ufshcd_dme_set_attr(hba, 0x00d00005, 0x00, 0x02, DME_LOCAL); ++ ++ /*RX_HS_CLK_EN*/ ++ ufshcd_dme_set_attr(hba, 0x00cc0004, 0x00, 0x03, DME_LOCAL); ++ /*RX_HS_CLK_EN*/ ++ ufshcd_dme_set_attr(hba, 0x00cc0005, 0x00, 0x03, DME_LOCAL); ++ /*RX_LS_CLK_EN*/ ++ ufshcd_dme_set_attr(hba, 0x00cd0004, 0x00, 0x03, DME_LOCAL); ++ /*RX_LS_CLK_EN*/ ++ ufshcd_dme_set_attr(hba, 0x00cd0005, 0x00, 0x03, DME_LOCAL); ++#endif ++ ++#if defined(COMBO_PHY_V120) ++ /*RG_PLL_RXHS_EN*/ ++ ufshcd_dme_set_attr(hba, 0x00c50000, 0x00, 0x03, DME_LOCAL); ++ /*RG_PLL_RXLS_EN*/ ++ ufshcd_dme_set_attr(hba, 0x00c60000, 0x00, 0x03, DME_LOCAL); ++ /*RX_HS_DATA_VALID_TIMER_VAL0*/ ++ ufshcd_dme_set_attr(hba, 0x00E90004, 0x00, 0x00, DME_LOCAL); ++ /*RX_HS_DATA_VALID_TIMER_VAL0*/ ++ ufshcd_dme_set_attr(hba, 0x00E90005, 0x00, 0x00, DME_LOCAL); ++ /*RX_HS_DATA_VALID_TIMER_VAL1*/ ++ ufshcd_dme_set_attr(hba, 0x00EA0004, 0x00, 0x10, DME_LOCAL); ++ /*RX_HS_DATA_VALID_TIMER_VAL1*/ ++ ufshcd_dme_set_attr(hba, 0x00EA0005, 0x00, 0x10, DME_LOCAL); ++#else ++ /*enhance the accuracy of squelch detection*/ ++ /*RX_H8_EXIT*/ ++ ufshcd_dme_set_attr(hba, 0x00ce0004, 0x00, 0x03, DME_LOCAL); ++ /*RX_H8_EXIT*/ ++ ufshcd_dme_set_attr(hba, 0x00ce0005, 0x00, 0x03, DME_LOCAL); ++ ++/* try to solve the OCS=5 */ ++ /*RX_HS_DATA_VALID_TIMER_VAL0*/ ++ ufshcd_dme_set_attr(hba, 0x00E90004, 0x00, 0x20, DME_LOCAL); ++ /*RX_HS_DATA_VALID_TIMER_VAL0*/ ++ ufshcd_dme_set_attr(hba, 0x00E90005, 0x00, 0x20, DME_LOCAL); ++ /*RX_HS_DATA_VALID_TIMER_VAL1*/ ++ ufshcd_dme_set_attr(hba, 0x00EA0004, 0x00, 0x01, DME_LOCAL); ++ /*RX_HS_DATA_VALID_TIMER_VAL1*/ ++ ufshcd_dme_set_attr(hba, 0x00EA0005, 0x00, 0x01, DME_LOCAL); ++#endif ++#if 1 ++ /* set the HS-prepare length and sync length to MAX value, ++ try to solve the data check error problem, the device ++ seems not receive the write cmd. */ ++ /* PA_TxHsG1SyncLength , can not set MPHY's register directly */ ++ ufshcd_dme_set_attr(hba, 0x15520000, 0x00, 0x4F, DME_LOCAL); ++ /* PA_TxHsG2SyncLength , can not set MPHY's register directly */ ++ ufshcd_dme_set_attr(hba, 0x15540000, 0x00, 0x4F, DME_LOCAL); ++ /* PA_TxHsG3SyncLength , can not set MPHY's register directly */ ++ ufshcd_dme_set_attr(hba, 0x15560000, 0x00, 0x4F, DME_LOCAL); ++ ++ /*enlarge TX_LS_PREPARE_LENGTH*/ ++ /*enable override*/ ++/* ++ temp = uic_cmd_read(0x1, 0xd0f00000); ++ temp |= (1<<3); ++ ufshcd_dme_set_attr(hba, 0xd0f00000, 0x00, temp); ++*/ ++ /*Set to max value 0xf*/ ++/* ufshcd_dme_set_attr(hba, 0xd0f40000, 0x00, 0x0f, DME_LOCAL);*/ ++#endif ++#if defined(OCS_5_WORKAROUND) ++ ufshcd_dme_set_attr(hba, 0x00FF0004, 0x00, 0x2, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x00FF0005, 0x00, 0x2, DME_LOCAL); ++#endif ++#if defined(NOISE_PROOF) ++ ufshcd_dme_set_attr(hba, 0x00F40004, 0x00, 0x2, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x00F40005, 0x00, 0x2, DME_LOCAL); ++ ++ ufshcd_dme_set_attr(hba, 0x00F20004, 0x00, 0x2, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x00F20005, 0x00, 0x2, DME_LOCAL); ++ ++ ufshcd_dme_set_attr(hba, 0x00FC0004, 0x00, 0x1F, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x00FC0005, 0x00, 0x1F, DME_LOCAL); ++ ++ ufshcd_dme_set_attr(hba, 0x00FB0004, 0x00, 0x0, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x00FB0005, 0x00, 0x0, DME_LOCAL); ++#endif ++ ++ /* pll always on*/ ++ ufshcd_dme_set_attr(hba, 0x00ca0000, 0x0, 0x3, DME_LOCAL); ++ /* update */ ++ ufshcd_dme_set_attr(hba, 0xD0850000, 0x0, 0x1, DME_LOCAL); ++ ++ /* to check if the unipro have to close the LCC */ ++ /* Unipro PA_Local_TX_LCC_Enable */ ++ ufshcd_dme_set_attr(hba, 0x155E0000, 0x0, 0x0, DME_LOCAL); ++ /* close Unipro VS_Mk2ExtnSupport */ ++ ufshcd_dme_set_attr(hba, 0xD0AB0000, 0x0, 0x0, DME_LOCAL); ++ ++ ufshcd_dme_get(hba, 0xD0AB0000, &val); ++ if (0 != val) { ++ /* Ensure close success */ ++ UFS_PRINT("Warring!!! close VS_Mk2ExtnSupport failed\n"); ++ } ++ ++ return 0; ++} ++ ++static void hiufs_program_clk_div(struct ufs_hba *hba, u32 divider_val) ++{ ++ ufshcd_writel(hba, divider_val, DWC_UFS_REG_HCLKDIV); ++} ++ ++static int hiufs_link_is_up(struct ufs_hba *hba) ++{ ++ int dme_result = 0; ++ ++ ufshcd_dme_get(hba, UIC_ARG_MIB(VS_POWERSTATE), &dme_result); ++ ++ if (dme_result == UFSHCD_LINK_IS_UP) { ++ ufshcd_set_link_active(hba); ++ return 0; ++ } ++ ++ return 1; ++} ++ ++static int hiufs_connection_setup(struct ufs_hba *hba) ++{ ++ u32 regv; ++ ++ ufshcd_dme_set_attr(hba, 0x20440000, 0, 0x0, DME_LOCAL); ++ /* Unipro DL_AFC0CreditThreshold */ ++ ufshcd_dme_set_attr(hba, 0x20450000, 0, 0x0, DME_LOCAL); ++ /* Unipro DL_TC0OutAckThreshold */ ++ ufshcd_dme_set_attr(hba, 0x20400000, 0, 0x9, DME_LOCAL); ++ /* Unipro DL_TC0TXFCThreshold */ ++ ++ ++ /*set the PA_Granularity to 2. need to check in ASIC...*/ ++ /*send_uic_command(0x02, 0x15aa0000, 0x00, 4, DME_LOCAL);*/ ++ ufshcd_dme_set_attr(hba, 0x15aa0000, 0, 0x2, DME_LOCAL); ++ /* Unipro DL_TC0TXFCThreshold */ ++ /*PA_Hibern8Time*/ ++ ufshcd_dme_set_attr(hba, 0x15a70000, 0x00, 0x80, DME_LOCAL); ++ /*set the PA_TActivate to 128. need to check in ASIC...*/ ++ /*send_uic_command(0x02, 0x15a80000, 0x00, 9);*/ ++ ++ //delete ++ //ufshcd_dme_set_attr(hba, 0x80da0000, 0, 0x2d, DME_LOCAL); ++ //delete ++ ufshcd_dme_set_attr(hba, 0xd0ab0000, 0, 0x0, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0xd0a00000, 0, 0xc, DME_LOCAL); ++/* ++ ufshcd_writel(hba, UFS_UTP_RUN_BIT, UFS_UTRLRSR_OFF); ++ ufshcd_writel(hba, UFS_UTP_RUN_BIT, UFS_UTMRLRSR_OFF); ++*/ ++ ++#if 1 ++/*#ifdef UFS_AUTO_H8_ENABLE*/ ++ ++ /* disable auto H8 Power-Gating */ ++ regv = ufshcd_readl(hba, UFS_BUSTHRTL_OFF); ++ regv &= (uint32_t)(~LP_AH8_PGE); ++ ufshcd_writel(hba, regv, UFS_BUSTHRTL_OFF); ++ ++ /* enable auto H8 */ ++ /*ufshcd_writel(hba, UFS_AHIT_AUTOH8_TIMER, UFS_AHIT_OFF);*/ ++#endif ++ ++ return 0; ++} ++ ++static int hiufs_link_startup_notify(struct ufs_hba *hba, ++ enum ufs_notify_change_status status) ++{ ++ int err = 0; ++ ++ if (status == PRE_CHANGE) { ++ hiufs_program_clk_div(hba, UFS_HCLKDIV_NORMAL_VALUE); ++ err = hiufs_phy_init(hba, PA_HS_MODE_B); ++ if (err) { ++ dev_err(hba->dev, "Phy setup failed (%d)\n", err); ++ goto out; ++ } ++ } else { /* POST_CHANGE */ ++ err = hiufs_link_is_up(hba); ++ if (err) { ++ dev_err(hba->dev, "Link is not up\n"); ++ goto out; ++ } ++ ++ err = hiufs_connection_setup(hba); ++ if (err) ++ dev_err(hba->dev, "Connection setup failed (%d)\n", err); ++ } ++ ++out: ++ return err; ++} ++ ++int do_mode_change(struct ufs_hba *hba, ++ const struct pwrModeParams *pmp, ++ int scramble, int termination) ++{ ++ ++ /*RX enable, lane0 */ ++ /*ufshcd_dme_set_attr(hba, 0x00f00004, 0x00, 0x01, DME_LOCAL);*/ ++ /*ufshcd_dme_set_attr(hba, 0xD0850000, 0x0, 0x1, DME_LOCAL);*/ ++ ++ /* PA_TxSkip */ ++ ufshcd_dme_set_attr(hba, 0x155c0000, 0x0, 0x0, DME_LOCAL); ++ /* PA_TxGear */ ++ ufshcd_dme_set_attr(hba, 0x15680000, 0x0, pmp->txGear, DME_LOCAL); ++ /* PA_RxGear */ ++ ufshcd_dme_set_attr(hba, 0x15830000, 0x0, pmp->rxGear, DME_LOCAL); ++ ++ if (pmp->pwrMode == FAST_MODE || pmp->pwrMode == FASTAUTO_MODE) { ++ /* PA_HSSeries */ ++ ufshcd_dme_set_attr(hba, 0x156a0000, 0x0, pmp->hsSeries, DME_LOCAL); ++ if (termination) { ++ /* PA_TxTermination */ ++ ufshcd_dme_set_attr(hba, 0x15690000, 0x0, 0x1, DME_LOCAL); ++ /* PA_RxTermination */ ++ ufshcd_dme_set_attr(hba, 0x15840000, 0x0, 0x1, DME_LOCAL); ++ } else { ++ /* PA_TxTermination */ ++ ufshcd_dme_set_attr(hba, 0x15690000, 0x0, 0x0, DME_LOCAL); ++ /* PA_RxTermination */ ++ ufshcd_dme_set_attr(hba, 0x15840000, 0x0, 0x0, DME_LOCAL); ++ } ++ ++ if (scramble) ++ /* PA_Scrambling */ ++ ufshcd_dme_set_attr(hba, 0x15850000, 0x0, 0x1, DME_LOCAL); ++ else ++ /* PA_Scrambling */ ++ ufshcd_dme_set_attr(hba, 0x15850000, 0x0, 0x0, DME_LOCAL); ++ ++ } else if (pmp->pwrMode == SLOW_MODE || pmp->pwrMode == SLOWAUTO_MODE) { ++ ufshcd_dme_set_attr(hba, 0x15690000, 0x0, 0x0, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x15840000, 0x0, 0x0, DME_LOCAL); ++ /* PA_Scrambling */ ++ ufshcd_dme_set_attr(hba, 0x15850000, 0x0, 0x0, DME_LOCAL); ++ } ++ ++ /* PA_ActiveTxDataLanes */ ++ ufshcd_dme_set_attr(hba, 0x15600000, 0x0, pmp->txLanes, DME_LOCAL); ++ /* PA_ActiveRxDataLanes */ ++ ufshcd_dme_set_attr(hba, 0x15800000, 0x0, pmp->rxLanes, DME_LOCAL); ++ ++ /*PA_PWRModeUserData0 = 8191, default is 0*/ ++ ufshcd_dme_set_attr(hba, 0x15b00000, 0x0, 8191, DME_LOCAL); ++ /*PA_PWRModeUserData1 = 65535, default is 0*/ ++ ufshcd_dme_set_attr(hba, 0x15b10000, 0x0, 65535, DME_LOCAL); ++ /*PA_PWRModeUserData2 = 32767, default is 0*/ ++ ufshcd_dme_set_attr(hba, 0x15b20000, 0x0, 32767, DME_LOCAL); ++ /*DME_FC0ProtectionTimeOutVal = 8191, default is 0*/ ++ ufshcd_dme_set_attr(hba, 0xd0410000, 0x0, 8191, DME_LOCAL); ++ /*DME_TC0ReplayTimeOutVal = 65535, default is 0*/ ++ ufshcd_dme_set_attr(hba, 0xd0420000, 0x0, 65535, DME_LOCAL); ++ /*DME_AFC0ReqTimeOutVal = 32767, default is 0*/ ++ ufshcd_dme_set_attr(hba, 0xd0430000, 0x0, 32767, DME_LOCAL); ++ ++ /*PA_PWRModeUserData3 = 8191, default is 0*/ ++ ufshcd_dme_set_attr(hba, 0x15b30000, 0x0, 8191, DME_LOCAL); ++ /*PA_PWRModeUserData4 = 65535, default is 0*/ ++ ufshcd_dme_set_attr(hba, 0x15b40000, 0x0, 65535, DME_LOCAL); ++ /*PA_PWRModeUserData5 = 32767, default is 0*/ ++ ufshcd_dme_set_attr(hba, 0x15b50000, 0x0, 32767, DME_LOCAL); ++ /*DME_FC1ProtectionTimeOutVal = 8191, default is 0*/ ++ ufshcd_dme_set_attr(hba, 0xd0440000, 0x0, 8191, DME_LOCAL); ++ /*DME_TC1ReplayTimeOutVal = 65535, default is 0*/ ++ ufshcd_dme_set_attr(hba, 0xd0450000, 0x0, 65535, DME_LOCAL); ++ /*DME_AFC1ReqTimeOutVal = 32767, default is 0*/ ++ ufshcd_dme_set_attr(hba, 0xd0460000, 0x0, 32767, DME_LOCAL); ++ ++ /*VS_DebugCounter0Mask*/ ++ ufshcd_dme_set_attr(hba, 0xd09a0000, 0x0, 0x80000000, DME_LOCAL); ++ /*ufshcd_dme_set_attr(hba, 0xd09a0000, 0x0, 0x80000000);*/ ++ /*UFS_PRINT("Set VS_DebugCounter0Mask to 0x%x\n", ++ uic_cmd_read(DME_GET, 0xd09a0000));*/ ++ ++ /*VS_DebugCounter1Mask*/ ++ ufshcd_dme_set_attr(hba, 0xd09b0000, 0x0, 0x78000000, DME_LOCAL); ++ /*ufshcd_dme_set_attr(hba, 0xd09b0000, 0x0, 0x78000000);*/ ++ /*UFS_PRINT("Set VS_DebugCounter1Mask to 0x%x\n", ++ uic_cmd_read(DME_GET, 0xd09b0000));*/ ++ ++ /* PA_PWRMode */ ++ ufshcd_dme_set_attr(hba, 0x15710000, 0x0, ++ (pmp->pwrMode<<4|pmp->pwrMode), DME_LOCAL); ++ /*FUNC_EXIT();*/ ++ return 0; ++} ++ ++static void adapt_pll_to_power_mode(struct ufs_hba *hba, ++ uint8_t pwrmode, uint8_t gear, uint8_t rate, uint32_t line) ++{ ++#ifdef COMBO_PHY_V100 ++ uint32_t value; ++ if (FAST_MODE == pwrmode || SLOW_MODE == pwrmode) ++ /*don't change PLL in fast and slow mode*/ ++ return 0; ++#endif ++ ++#ifdef COMBO_PHY_V100 ++ /*Note that CB registers for PLL can only be set at SAVE (Stall/Sleep) state*/ ++ while (1) { ++ value = uic_cmd_read(0x1, 0x00410000); ++ PRINT_ERROR("value is %d \n", value); ++ if ((3 == value) || (2 == value)) break; ++ } ++#endif ++#if 1 ++ if (FAST_MODE == pwrmode || FASTAUTO_MODE == pwrmode) { ++ if (UFS_HS_G1 == gear) { ++ if (PA_HS_MODE_A == rate) { ++ ufshcd_dme_set_attr(hba, RG_PLL_PRE_DIV, 0x00, 0x00, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_SWC_EN, 0x00, 0x00, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_FBK_S, 0x00, 0x01, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_FBK_P, 0x00, 0x41, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_TXHSGR, 0x00, 0x02, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_RXHSGR, 0x00, 0x02, DME_LOCAL); ++ } else if (PA_HS_MODE_B == rate) { ++ ufshcd_dme_set_attr(hba, RG_PLL_PRE_DIV, 0x00, 0x00, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_SWC_EN, 0x00, 0x00, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_FBK_S, 0x00, 0x01, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_FBK_P, 0x00, 0x4c, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_TXHSGR, 0x00, 0x02, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_RXHSGR, 0x00, 0x02, DME_LOCAL); ++ } ++ ++ } else if (UFS_HS_G2 == gear) { ++ if (PA_HS_MODE_A == rate) { ++ ufshcd_dme_set_attr(hba, RG_PLL_PRE_DIV, 0x00, 0x00, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_SWC_EN, 0x00, 0x00, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_FBK_S, 0x00, 0x01, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_FBK_P, 0x00, 0x41, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_TXHSGR, 0x00, 0x01, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_RXHSGR, 0x00, 0x01, DME_LOCAL); ++ } else if (PA_HS_MODE_B == rate) { ++ ufshcd_dme_set_attr(hba, RG_PLL_PRE_DIV, 0x00, 0x00, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_SWC_EN, 0x00, 0x00, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_FBK_S, 0x00, 0x01, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_FBK_P, 0x00, 0x4C, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_TXHSGR, 0x00, 0x01, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_RXHSGR, 0x00, 0x01, DME_LOCAL); ++ } ++ } else if (UFS_HS_G3 == gear) { ++ if (PA_HS_MODE_A == rate) { ++ ufshcd_dme_set_attr(hba, RG_PLL_PRE_DIV, 0x00, 0x00, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_SWC_EN, 0x00, 0x00, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_FBK_S, 0x00, 0x01, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_FBK_P, 0x00, 0x41, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_TXHSGR, 0x00, 0x00, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_RXHSGR, 0x00, 0x00, DME_LOCAL); ++ } else if (PA_HS_MODE_B == rate) { ++ ufshcd_dme_set_attr(hba, RG_PLL_PRE_DIV, 0x00, 0x00, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_SWC_EN, 0x00, 0x00, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_FBK_S, 0x00, 0x01, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_FBK_P, 0x00, 0x4c, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_TXHSGR, 0x00, 0x00, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_RXHSGR, 0x00, 0x00, DME_LOCAL); ++ } ++ } ++ } ++ #endif ++ ++ /*the PWM's clk is been derived from the pll above*/ ++ if (SLOW_MODE == pwrmode || SLOWAUTO_MODE == pwrmode) { ++ if (UFS_PWM_G1 == gear) { ++ ufshcd_dme_set_attr(hba, RG_PLL_TXLSGR, 0x00, 0x07, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_RXLSGR, 0x00, 0x06, DME_LOCAL); ++ } else if (UFS_PWM_G2 == gear) { ++ ufshcd_dme_set_attr(hba, RG_PLL_TXLSGR, 0x00, 0x06, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_RXLSGR, 0x00, 0x05, DME_LOCAL); ++ } else if (UFS_PWM_G3 == gear) { ++ ufshcd_dme_set_attr(hba, RG_PLL_TXLSGR, 0x00, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_RXLSGR, 0x00, 0x04, DME_LOCAL); ++ } else if (UFS_PWM_G4 == gear) { ++ ufshcd_dme_set_attr(hba, RG_PLL_TXLSGR, 0x00, 0x04, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, RG_PLL_RXLSGR, 0x00, 0x03, DME_LOCAL); ++ } ++ } ++ ++ #ifdef COMBO_PHY_V100 ++ /* just for test begin */ ++ ufshcd_dme_set_attr(hba, 0x00f50004, 0x00, 0x01, DME_LOCAL); ++ /* mphy config update */ ++ ufshcd_dme_set_attr(hba, 0xd0850000, 0x00, 0x01, DME_LOCAL); ++ /* just for test end */ ++ #endif ++ ++ /*ufs_waitms(50);*/ ++ /*exit TX_HIBERNATE_CONTROL */ ++ /*ufshcd_dme_set_attr(hba, 0x002b0000, 0x00, 0x00);*/ ++ ++ ++ /* mphy config update */ ++ /*ufshcd_dme_set_attr(hba, 0xd0850000, 0x00, 0x01, DME_LOCAL);*/ ++} ++ ++static void ufsphy_eye_configuration(struct ufs_hba *hba, ++ uint8_t pwrmode, uint8_t gear, uint8_t rate, uint32_t line) ++{ ++ ++ if (FAST_MODE == pwrmode || FASTAUTO_MODE == pwrmode) { ++ if (UFS_HS_G1 == gear) { ++ if (PA_HS_MODE_A == rate) { ++ ufshcd_dme_set_attr(hba, 0x007e0000, 0x00, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007f0000, 0x00, 0x11, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x00370000, 0x00, 0xf, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007b0000, 0x00, 0x6f, DME_LOCAL); ++ if (line == 2) { ++ ufshcd_dme_set_attr(hba, 0x007e0001, 0x00, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007f0001, 0x00, 0x11, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x00370001, 0x00, 0xf, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007b0001, 0x00, 0x6f, DME_LOCAL); ++ } ++ } else if (PA_HS_MODE_B == rate) { ++ ufshcd_dme_set_attr(hba, 0x007e0000, 0x00, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007f0000, 0x00, 0x11, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x00370000, 0x00, 0xf, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007b0000, 0x00, 0x6f, DME_LOCAL); ++ if (line == 2) { ++ ufshcd_dme_set_attr(hba, 0x007e0001, 0x00, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007f0001, 0x00, 0x11, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x00370001, 0x00, 0xf, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007b0001, 0x00, 0x6f, DME_LOCAL); ++ } ++ } ++ ++ } else if (UFS_HS_G2 == gear) { ++ if (PA_HS_MODE_A == rate) { ++ ufshcd_dme_set_attr(hba, 0x007e0000, 0x00, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007f0000, 0x00, 0x1a, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x00370000, 0x00, 0x02, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007b0000, 0x00, 0x22, DME_LOCAL); ++ if (line == 2) { ++ ufshcd_dme_set_attr(hba, 0x007e0001, 0x00, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007f0001, 0x00, 0x1a, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x00370001, 0x00, 0x02, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007b0001, 0x00, 0x22, DME_LOCAL); ++ } ++ } else if (PA_HS_MODE_B == rate) { ++ ufshcd_dme_set_attr(hba, 0x007e0000, 0x00, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007f0000, 0x00, 0x1e, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x00370000, 0x00, 0x03, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007b0000, 0x00, 0x23, DME_LOCAL); ++ if (line == 2) { ++ ufshcd_dme_set_attr(hba, 0x007e0001, 0x00, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007f0001, 0x00, 0x1e, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x00370001, 0x00, 0x03, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007b0001, 0x00, 0x23, DME_LOCAL); ++ } ++ } ++ } else if (UFS_HS_G3 == gear) { ++ if (PA_HS_MODE_A == rate) { ++ ufshcd_dme_set_attr(hba, 0x007e0000, 0x00, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007f0000, 0x00, 0x20, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x00370000, 0x00, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007b0000, 0x00, 0x25, DME_LOCAL); ++ if (line == 2) { ++ ufshcd_dme_set_attr(hba, 0x007e0001, 0x00, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007f0001, 0x00, 0x20, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x00370001, 0x00, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007b0001, 0x00, 0x25, DME_LOCAL); ++ } ++ } else if (PA_HS_MODE_B == rate) { ++ ufshcd_dme_set_attr(hba, 0x007e0000, 0x00, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007f0000, 0x00, 0x20, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x00370000, 0x00, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007b0000, 0x00, 0x25, DME_LOCAL); ++ if (line == 2) { ++ ufshcd_dme_set_attr(hba, 0x007e0001, 0x00, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007f0001, 0x00, 0x20, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x00370001, 0x00, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007b0001, 0x00, 0x25, DME_LOCAL); ++ } ++ } ++ } ++ } ++} ++ ++static int change_power_mode(struct ufs_hba *hba, uint8_t pwrmode, ++ uint8_t gear, uint8_t rate, ++ int line, int scramble, int termination) ++{ ++ int err; ++ u32 set; ++ uint32_t value; ++ struct pwrModeParams pmp; ++ uint32_t tx_lane_num; ++ uint32_t rx_lane_num; ++ int retry = 1000; ++ u32 auto_chg = 0; ++ ++ tx_lane_num = line; ++ rx_lane_num = line; ++ ++ if (3 == gear) { ++ value = 0x26; /* 4.44 dB */ ++ /*value = 0x20;*/ ++ /* HS-G3- 0 dB, other configuration is the same*/ ++ ufshcd_dme_set_attr(hba, 0x007e0000, 0x0, 0x05, DME_LOCAL); ++ //modefy begin ++ //ufshcd_dme_set_attr(hba, 0x00250000, 0x0, 0x22, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007f0000, 0x0, 0x22, DME_LOCAL); ++ //modefy end ++ ufshcd_dme_set_attr(hba, 0x007d0000, 0x0, 0x22, DME_LOCAL); ++ //modefy begin ++ ufshcd_dme_set_attr(hba, 0x00fc0004, 0x0, 0x1f, DME_LOCAL);/*RX_S*/ ++ ufshcd_dme_set_attr(hba, 0x00fd0004, 0x0, 0x00, DME_LOCAL);/*RX_GEAR1_SET*/ ++ //modefy end ++ if ((tx_lane_num > 1) && (rx_lane_num > 1)) { ++ ufshcd_dme_set_attr(hba, 0x007e0001, 0x0, 0x05, DME_LOCAL); ++ //modefy begin ++ //ufshcd_dme_set_attr(hba, 0x00250000, 0x0, 0x22, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007f0001, 0x0, 0x22, DME_LOCAL); ++ //modefy end ++ ufshcd_dme_set_attr(hba, 0x007d0001, 0x0, 0x22, DME_LOCAL); ++ //modefy add ++ ufshcd_dme_set_attr(hba, 0x00fc0005, 0x0, 0x1f, DME_LOCAL);/*RX_S*/ ++ ufshcd_dme_set_attr(hba, 0x00fd0005, 0x0, 0x00, DME_LOCAL);/*RX_GEAR1_SET*/ ++ //modefy add ++ } ++ } else { ++ value = 0x6F; /* 6.85 dB */ ++ ufshcd_dme_set_attr(hba, 0x007e0000, 0x0, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007f0000, 0x0, 0x15, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007d0000, 0x0, 0x15, DME_LOCAL); ++ if ((tx_lane_num > 1) && (rx_lane_num > 1)) { ++ ufshcd_dme_set_attr(hba, 0x007e0001, 0x0, 0x05, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007f0001, 0x0, 0x15, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007d0001, 0x0, 0x15, DME_LOCAL); ++ } ++ //modefy add ++ ufshcd_dme_set_attr(hba, 0x00fc0004, 0x0, 0x1b, DME_LOCAL);/*RX_S*/ ++ if ((tx_lane_num > 1) && (rx_lane_num > 1)) ++ { ++ ufshcd_dme_set_attr(hba, 0x00fc0005, 0x0, 0x1b, DME_LOCAL);/*RX_S*/ ++ } ++ if(1 == gear) ++ { ++ ufshcd_dme_set_attr(hba, 0x00fd0004, 0x0, 0x01, DME_LOCAL);/*RX_GEAR1_SET*/ ++ if ((tx_lane_num > 1) && (rx_lane_num > 1)) ++ { ++ ufshcd_dme_set_attr(hba, 0x00fd0005, 0x0, 0x01, DME_LOCAL);/*RX_GEAR1_SET*/ ++ } ++ } ++ else if(2 == gear) ++ { ++ ufshcd_dme_set_attr(hba, 0x00fd0004, 0x0, 0x00, DME_LOCAL);/*RX_GEAR1_SET*/ ++ if ((tx_lane_num > 1) && (rx_lane_num > 1)) ++ { ++ ufshcd_dme_set_attr(hba, 0x00fd0005, 0x0, 0x00, DME_LOCAL);/*RX_GEAR1_SET*/ ++ } ++ } ++ //modefy add ++ } ++ ++ ufshcd_dme_set_attr(hba, 0x00370000, 0x0, value, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007b0000, 0x0, value, DME_LOCAL); ++ if ((tx_lane_num > 1) && (rx_lane_num > 1)) { ++ ufshcd_dme_set_attr(hba, 0x00370001, 0x0, value, DME_LOCAL); ++ ufshcd_dme_set_attr(hba, 0x007b0001, 0x0, value, DME_LOCAL); ++ } ++ ++ /* PaTactive */ ++ /*ufshcd_dme_set_attr(hba, 0x15A80000, 0x0, 0x7, DME_LOCAL);*/ ++ ++ if (1 == line) { ++ tx_lane_num = 1; ++ rx_lane_num = 1; ++ } else { ++ /* PA_ConnectedTxDataLanes */ ++ ufshcd_dme_get_attr(hba, 0x15610000, (u32 *)&tx_lane_num, DME_LOCAL); ++ /* PA_ConnectedRxDataLanes */ ++ ufshcd_dme_get_attr(hba, 0x15810000, (u32 *)&rx_lane_num, DME_LOCAL); ++ } ++ ++ pmp.txLanes = tx_lane_num; /* Tx One Lane */ ++ pmp.rxLanes = rx_lane_num; /* Rx One Lane */ ++ pmp.txGear = gear; ++ pmp.rxGear = gear; ++ pmp.hsSeries = rate; ++ pmp.pwrMode = pwrmode; ++ ++ set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE); ++ set &= ~UFS_IS_UPMS_BIT; ++ ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE); ++ ++#ifdef UFS_USE_HISI_MPHY_TC ++ /*RX mc, lane0 */ ++ /*ufshcd_dme_set_attr(hba, 0x00C20004, 0x00, 0x00, DME_LOCAL);*/ ++ /*RX MC, lane1 */ ++ /*ufshcd_dme_set_attr(hba, 0x00C20005, 0x00, 0x00, DME_LOCAL);*/ ++ ++ ufshcd_dme_get_attr(hba, 0xdf0000, &auto_chg, DME_LOCAL); ++ printk("auto_chg = %#x\n", auto_chg); ++ if ( !auto_chg & VCO_AUTO_CHG_EN ) ++ adapt_pll_to_power_mode(hba, pwrmode, gear, rate, rx_lane_num); ++#endif ++ ufsphy_eye_configuration(hba, pwrmode, gear, rate, rx_lane_num); ++ err = do_mode_change(hba, &pmp, scramble, termination); ++ if (err) { ++ UFS_PRINT("do_mode_change failed\n"); ++ return err; ++ } ++ ++ while (--retry) { ++ value = ufshcd_readl(hba, REG_INTERRUPT_STATUS); ++ if (value & UFS_IS_UPMS_BIT) { ++ /*ufshcd_writel(hba, ++ UFS_IS_UPMS_BIT, ++ REG_INTERRUPT_STATUS);*/ ++ ufshcd_writel(hba, value, REG_INTERRUPT_STATUS); ++ break; ++ } ++ msleep(1); ++ } ++ set |= UFS_IS_UPMS_BIT; ++ ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE); ++ ++ if (retry <= 0) ++ UFS_PRINT("\nwait IS.UPMS time out value:%#X\n", value); ++ ++ value = ufshcd_readl(hba, REG_CONTROLLER_STATUS); ++ if (((value & UFS_HCS_UPMCRS_MASK) >> UFS_HCS_UPMCRS_OFF) != 0x1) { ++ UFS_PRINT("check HCS.UPMCRS error, HCS = 0x%x\n", value); ++ return -1; ++ } ++ UFS_PRINT("power mode change success\n"); ++ ++ UFS_PRINT("UFS %s Gear-%d Rate-%c Lanes-%d Scrmbl-%d Termn-%d\n", ++ ((SLOW_MODE == pwrmode)?"Slow" : ++ ((SLOWAUTO_MODE == pwrmode)?"SlowAuto" : ++ ((FAST_MODE == pwrmode)?"Fast" : "FastAuto"))), ++ gear, (rate == 1)?'A' : 'B', rx_lane_num, ++ scramble, termination); ++ /* RX_ERR_STATUS */ ++ ufshcd_dme_set_attr(hba, 0x00c40004, 0x0, 0x80, DME_LOCAL); ++ /* RX_ERR_STATUS */ ++ ufshcd_dme_set_attr(hba, 0x00c50004, 0x0, 0x01, DME_LOCAL); ++ ++ if (rx_lane_num == 2) { ++ /* RX_ERR_STATUS */ ++ ufshcd_dme_set_attr(hba, 0x00c40005, 0x0, 0x80, DME_LOCAL); ++ /* RX_ERR_STATUS */ ++ ufshcd_dme_set_attr(hba, 0x00c50005, 0x0, 0x01, DME_LOCAL); ++ } ++ ++ return SUCCESS; ++} ++ ++static int hiufs_config_power_mode(struct ufs_hba *hba, ++ struct ufs_pa_layer_attr *dev_max_params) ++{ ++ uint32_t gear = dev_max_params->gear_rx; ++ uint32_t rate = dev_max_params->hs_rate; ++ uint32_t pwrmode = dev_max_params->pwr_rx; ++ uint32_t lane = dev_max_params->lane_rx; ++ ++ //ufshcd_dme_set_attr(hba, 0x00370000, 0x0, 0x1, DME_LOCAL); ++ change_power_mode(hba, pwrmode, gear, rate, lane, 0, 1); ++ ++ return 0; ++} ++ ++static int hiufs_pwr_change_notify(struct ufs_hba *hba, ++ enum ufs_notify_change_status status, ++ struct ufs_pa_layer_attr *dev_max_params, ++ struct ufs_pa_layer_attr *dev_req_params) ++{ ++ int err = 0; ++ ++ if (status == PRE_CHANGE) { ++ err = hiufs_config_power_mode(hba, dev_max_params); ++ memcpy(dev_req_params, dev_max_params, ++ sizeof(struct ufs_pa_layer_attr)); ++ memcpy(&hba->pwr_info, dev_max_params, ++ sizeof(struct ufs_pa_layer_attr)); ++ } ++ ++ return err; ++} ++ ++static int hiufs_pltfm_init(struct ufs_hba *hba) ++{ ++ hba->clk_gating.state = CLKS_ON; ++ hba->caps &= ~UFSHCD_CAP_CLK_GATING; ++ return 0; ++} ++ ++static struct ufs_hba_variant_ops hiufs_pltfm_hba_vops = { ++ .name = "hiufs_pltfm", ++ .init = hiufs_pltfm_init, ++ .link_startup_notify = hiufs_link_startup_notify, ++ .pwr_change_notify = hiufs_pwr_change_notify, ++ .clk_hareware_init_notify = hiufs_clk_hardware_init_notify, ++}; ++ ++static const struct of_device_id hiufs_pltfm_pm_match[] = { ++ { ++ .compatible = "hiufs,hiufs_pltfm", ++ .data = &hiufs_pltfm_hba_vops, ++ }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, hiufs_pltfm_pm_match); ++ ++static int hiufs_pltfm_probe(struct platform_device *pdev) ++{ ++ int err; ++ void __iomem *crg_base; ++ void __iomem *misc_base; ++ struct resource *mem_res; ++ const struct of_device_id *of_id; ++ struct ufs_hba_variant_ops *vops; ++ struct device *dev = &pdev->dev; ++ ++ of_id = of_match_node(hiufs_pltfm_pm_match, dev->of_node); ++ vops = (struct ufs_hba_variant_ops *)of_id->data; ++ ++ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ crg_base = devm_ioremap_resource(dev, mem_res); ++ if (IS_ERR(*(void **)&crg_base)) ++ return PTR_ERR(*(void **)&crg_base); ++ remap_vir_add.crg_base = crg_base; ++ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 2); ++ misc_base = devm_ioremap_resource(dev, mem_res); ++ if (IS_ERR(*(void **)&misc_base)) ++ return PTR_ERR(*(void **)&misc_base); ++ remap_vir_add.misc_base = misc_base; ++ hiufs_pltfm_clk_init(crg_base); ++ hiufs_pltfm_hardware_init(misc_base); ++ ++ /* Perform generic probe */ ++ err = ufshcd_pltfrm_init(pdev, vops); ++ if (err) ++ dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err); ++ ++ return err; ++} ++ ++static int hiufs_pltfm_remove(struct platform_device *pdev) ++{ ++ struct ufs_hba *hba = platform_get_drvdata(pdev); ++ ++ pm_runtime_get_sync(&(pdev)->dev); ++ ufshcd_remove(hba); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops hiufs_pltfm_pm_ops = { ++ .suspend = ufshcd_pltfrm_suspend, ++ .resume = ufshcd_pltfrm_resume, ++ .runtime_suspend = ufshcd_pltfrm_runtime_suspend, ++ .runtime_resume = ufshcd_pltfrm_runtime_resume, ++ .runtime_idle = ufshcd_pltfrm_runtime_idle, ++}; ++ ++static struct platform_driver hiufs_pltfm_driver = { ++ .probe = hiufs_pltfm_probe, ++ .remove = hiufs_pltfm_remove, ++ .shutdown = ufshcd_pltfrm_shutdown, ++ .driver = { ++ .name = "hiufs_pltfm", ++ .pm = &hiufs_pltfm_pm_ops, ++ .of_match_table = of_match_ptr(hiufs_pltfm_pm_match), ++ }, ++}; ++ ++module_platform_driver(hiufs_pltfm_driver); ++ ++MODULE_AUTHOR("Shengjun Liang"); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/scsi/ufs/hi3559av100_ufs.h b/drivers/scsi/ufs/hi3559av100_ufs.h +new file mode 100644 +index 0000000..f79cce3 +--- /dev/null ++++ b/drivers/scsi/ufs/hi3559av100_ufs.h +@@ -0,0 +1,133 @@ ++#ifndef HI3559AV100_UFS_H ++#define HI3559AV100_UFS_H ++ ++#define UFS_USE_HISI_MPHY_TC ++//#define UFS_FPGA ++#define COMBO_PHY_V120 ++ ++#define BIT_UFS_SRST_REQ (0x1 << 12) ++#define BIT_UFS_CLK_EN (0x1 << 13) ++ ++#define UFS_SRST_REQ (0x1 << 0) ++#define UFS_RST_DEVICE (0x1 << 31) ++ ++#define BIT_UFS_PAD_RESET (0x1 << 15) ++#define BIT_DA_UFS_RESET_DS2 (0x1 << 14) ++#define BIT_DA_UFS_RESET_DS1 (0x1 << 13) ++#define BIT_DA_UFS_RESET_DS0 (0x1 << 12) ++#define BIT_DA_UFS_RESET_SL (0x1 << 11) ++#define BIT_DA_UFS_RESET_OEN (0x1 << 10) ++#define BIT_DA_UFS_RESET_PS (0x1 << 9) ++#define BIT_DA_UFS_RESET_PE (0x1 << 8) ++#define BIT_DA_UFS_REFCLK_DS2 (0x1 << 7) ++#define BIT_DA_UFS_REFCLK_DS1 (0x1 << 6) ++#define BIT_DA_UFS_REFCLK_DS0 (0x1 << 5) ++#define BIT_DA_UFS_REFCLK_SL (0x1 << 4) ++#define BIT_DA_UFS_REFCLK_OEN (0x1 << 3) ++#define BIT_DA_UFS_REFCLK_PS (0x1 << 2) ++#define BIT_DA_UFS_REFCLK_PE (0x1 << 1) ++#define BIT_UFS_ENABLE (0x1 << 0) ++ ++#define MASK_DA_UFS_RESET_DS (0x7 << 12) ++#define MASK_DA_UFS_REFCLK_DS (0x7 << 5) ++ ++ ++#define UFS_AUTO_HIBERNATE_BIT BIT(23) ++#define UFS_CAPS_64AS_BIT BIT(24) ++#define UFS_HCE_RESET_BIT BIT(0) ++#define UFS_HCS_DP_BIT BIT(0) ++#define UFS_HCS_UCRDY_BIT BIT(3) ++#define UFS_HCS_UPMCRS_OFF (8) ++#define UFS_HCS_UPMCRS_MASK (0x3 << UFS_HCS_UPMCRS_OFF) ++#define UFS_IS_UE_BIT BIT(2) ++#define UFS_IS_UPMS_BIT BIT(4) ++#define UFS_IS_UHXS_BIT BIT(5) ++#define UFS_IS_UHES_BIT BIT(6) ++#define UFS_IS_ULSS_BIT BIT(8) ++#define UFS_IS_UCCS_BIT BIT(10) ++#define UFS_UTP_RUN_BIT BIT(0) ++#define UFS_LBMCFG_DEFAULT_VALUE 0xb01 ++#define UFS_HCLKDIV_NORMAL_VALUE 0xFA ++#define UFS_HCLKDIV_SLOW_VALUE 0x14 ++#define UFS_HCLKDIV_FPGA_VALUE 0x28 ++ ++#define MTX_L0 0x0000 /*GenSelectorIndex for TX lane 0*/ ++#define MTX_L1 0x0001 /*GenSelectorIndex for TX lane 1*/ ++#define MRX_L0 0x0004 /*GenSelectorIndex for RX lane 0*/ ++#define MRX_L1 0x0005 /*GenSelectorIndex for RX lane 1*/ ++ ++#define ATTR_M_SHIFT 16 ++#define ATTR_UNIPRO_SHIFT ATTR_M_SHIFT ++ ++#define ATTR_MTX0(x) ((x << ATTR_M_SHIFT) | MTX_L0) ++#define ATTR_MTX1(x) ((x << ATTR_M_SHIFT) | MTX_L1) ++#define ATTR_MRX0(x) ((x << ATTR_M_SHIFT) | MRX_L0) ++#define ATTR_MRX1(x) ((x << ATTR_M_SHIFT) | MRX_L1) ++#define ATTR_MCB(x) (x << ATTR_M_SHIFT) ++#define ATTR_UNIPRO(x) (x << ATTR_UNIPRO_SHIFT) ++/*SYNOPSYS UniPro register*/ ++#define UNIPRO_DME_RESET 0xD010 ++#define UNIPRO_DME_LAYBER_ENABLE 0xD000 ++/*MPHY registers addr*/ ++/*RX*/ ++#define AD_DIF_P_LS_TIMEOUT_VAL 0x0003 ++#define PWM_PREPARE_TO 0x0000000A ++#define SKP_DET_SEL 0x0009 ++#define SKP_DET_SEL_EN 0x00000001 ++ ++#define MRX_EN 0x00F0 ++#define MRX_ENABLE (0x01 << 0) ++#define RX_SQ_VREF 0x00F1 ++#define RX_SQ_VREF_175mv 0x00000002 ++#define VCO_AUTO_CHG 0x00DF ++#define VCO_AUTO_CHG_EN (0x01 << 0) ++#define VCO_FORCE_ON_EN (0x01 << 1) ++ ++#define PG_PLL_SWC_ENABLE 0x01 ++ ++ ++#define HS_R_A_FBK_P 0x41 ++#define HS_R_B_FBK_P 0x4C ++#define HS_G_1_TXRXHSGR 0x02 ++#define HS_G_2_TXRXHSGR 0x01 ++#define HS_G_3_TXRXHSGR 0x00 ++ ++ ++/*PHY CB*/ ++#define RG_PLL_TXHS_EN 0x00C7 ++#define RG_PLL_TXHS_ENANBLE (0x01 << 0) ++#define RG_PLL_TXHS_EN_CONTROL (0x01 << 1) ++ ++#define RG_PLL_TXLS_EN 0x00C8 ++#define RG_PLL_TXLS_ENABLE (0x01 << 0) ++#define RG_PLL_TXLS_EN_CONTROL (0x01 << 1) ++ ++ ++ ++struct ufshcd_dme_attr_val { ++ u32 attr_sel; ++ u32 mib_val; ++ u8 peer; ++}; ++ ++ ++/* DWC HC UFSHCI specific Registers */ ++enum dwc_specific_registers { ++ DWC_UFS_REG_HCLKDIV = 0xFC, ++}; ++ ++/* Clock Divider Values: Hex equivalent of frequency in MHz */ ++enum clk_div_values { ++ DWC_UFS_REG_HCLKDIV_DIV_62_5 = 0x3e, ++ DWC_UFS_REG_HCLKDIV_DIV_125 = 0x7d, ++ DWC_UFS_REG_HCLKDIV_DIV_200 = 0xc8, ++}; ++ ++/* Selector Index */ ++enum selector_index { ++ SELIND_LN0_TX = 0x00, ++ SELIND_LN1_TX = 0x01, ++ SELIND_LN0_RX = 0x04, ++ SELIND_LN1_RX = 0x05, ++}; ++#endif +diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h +index 845b874..4852b74 100644 +--- a/drivers/scsi/ufs/ufs.h ++++ b/drivers/scsi/ufs/ufs.h +@@ -138,6 +138,7 @@ enum flag_idn { + enum attr_idn { + QUERY_ATTR_IDN_ACTIVE_ICC_LVL = 0x03, + QUERY_ATTR_IDN_BKOPS_STATUS = 0x05, ++ QUERY_ATTR_IDN_REFCLK_FREQ = 0x0A, + QUERY_ATTR_IDN_EE_CONTROL = 0x0D, + QUERY_ATTR_IDN_EE_STATUS = 0x0E, + }; +diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c +index db53f38..9729f0f 100644 +--- a/drivers/scsi/ufs/ufshcd-pltfrm.c ++++ b/drivers/scsi/ufs/ufshcd-pltfrm.c +@@ -41,7 +41,9 @@ + #include "ufshcd-pltfrm.h" + + #define UFSHCD_DEFAULT_LANES_PER_DIRECTION 2 +- ++#define UFSHCD_DEFAULT_PWM FAST_MODE ++#define UFSHCD_DEFAULT_GEAR UFS_HS_G1 ++#define UFSHCD_DEFAULT_RATE PA_HS_MODE_B + static int ufshcd_parse_clock_info(struct ufs_hba *hba) + { + int ret = 0; +@@ -209,6 +211,9 @@ static int ufshcd_parse_regulator_info(struct ufs_hba *hba) + struct device *dev = hba->dev; + struct ufs_vreg_info *info = &hba->vreg_info; + ++ if (hba->info_skip) ++ return 0; ++ + err = ufshcd_populate_vreg(dev, "vdd-hba", &info->vdd_hba); + if (err) + goto out; +@@ -279,6 +284,51 @@ void ufshcd_pltfrm_shutdown(struct platform_device *pdev) + } + EXPORT_SYMBOL_GPL(ufshcd_pltfrm_shutdown); + ++static void ufshcd_init_skip_info(struct ufs_hba *hba) ++{ ++ struct device *dev = hba->dev; ++ int ret; ++ ++ ret = of_property_read_u32(dev->of_node, "skip-info", ++ &hba->info_skip); ++ if (ret) { ++ dev_dbg(hba->dev, ++ "%s: failed to info skip ret=%d\n", ++ __func__, ret); ++ hba->info_skip = 0; ++ } ++} ++static void ufshcd_init_powermode(struct ufs_hba *hba) ++{ ++ struct device *dev = hba->dev; ++ int ret; ++ ++ ret = of_property_read_u32(dev->of_node, "power-mode", ++ &hba->hc_pwm); ++ if (ret) { ++ dev_dbg(hba->dev, ++ "%s: failed to powermode, ret=%d\n", ++ __func__, ret); ++ hba->hc_pwm = UFSHCD_DEFAULT_PWM; ++ } ++ ret = of_property_read_u32(dev->of_node, "gear", ++ &hba->hc_gear); ++ if (ret) { ++ dev_dbg(hba->dev, ++ "%s: failed to gear, ret=%d\n", ++ __func__, ret); ++ hba->hc_gear = UFSHCD_DEFAULT_GEAR; ++ } ++ ret = of_property_read_u32(dev->of_node, "rate", ++ &hba->hc_rate); ++ if (ret) { ++ dev_dbg(hba->dev, ++ "%s: failed to rate ret=%d\n", ++ __func__, ret); ++ hba->hc_rate = UFSHCD_DEFAULT_RATE; ++ } ++} ++ + static void ufshcd_init_lanes_per_dir(struct ufs_hba *hba) + { + struct device *dev = hba->dev; +@@ -309,7 +359,6 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, + struct resource *mem_res; + int irq, err; + struct device *dev = &pdev->dev; +- + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mmio_base = devm_ioremap_resource(dev, mem_res); + if (IS_ERR(*(void **)&mmio_base)) { +@@ -331,6 +380,7 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, + } + + hba->vops = vops; ++ ufshcd_init_skip_info(hba); + + err = ufshcd_parse_clock_info(hba); + if (err) { +@@ -349,7 +399,7 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, + pm_runtime_enable(&pdev->dev); + + ufshcd_init_lanes_per_dir(hba); +- ++ ufshcd_init_powermode(hba); + err = ufshcd_init(hba, mmio_base, irq); + if (err) { + dev_err(dev, "Initialization failed\n"); +diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c +index edb06e4..83b7b5b 100644 +--- a/drivers/scsi/ufs/ufshcd.c ++++ b/drivers/scsi/ufs/ufshcd.c +@@ -59,7 +59,7 @@ + /* Query request retries */ + #define QUERY_REQ_RETRIES 10 + /* Query request timeout */ +-#define QUERY_REQ_TIMEOUT 30 /* msec */ ++#define QUERY_REQ_TIMEOUT 3000 /* msec */ + /* + * Query request timeout for fDeviceInit flag + * fDeviceInit query response time for some devices is too large that default +@@ -232,6 +232,222 @@ static int ufshcd_config_pwr_mode(struct ufs_hba *hba, + struct ufs_pa_layer_attr *desired_pwr_mode); + static int ufshcd_change_power_mode(struct ufs_hba *hba, + struct ufs_pa_layer_attr *pwr_mode); ++void printf_layer_1_5(struct ufs_hba *hba) ++{ ++ int i = 0; ++ int value = 0; ++ ++ printk("------this for kernel layer_1_5------\n"); ++ ufshcd_dme_get(hba,0x15000000,&value); ++ printk("0x15000000: 0x%08x\n",value); ++ ++ ufshcd_dme_get(hba,0x15200000,&value); ++ printk("0x15200000: 0x%08x\n",value); ++ ++ ufshcd_dme_get(hba,0x15400000,&value); ++ printk("0x15400000: 0x%08x\n",value); ++ ++ ufshcd_dme_get(hba,0x15430000,&value); ++ printk("0x15430000: 0x%08x\n",value); ++ ++ for(i = 0x52;i<=0x57;i++) ++ { ++ ufshcd_dme_get(hba,0x15000000+i*0x10000,&value); ++ printk("0x15%02x0000: 0x%08x\n",i,value); ++ } ++ for(i = 0x5a;i<=0x61;i++) ++ { ++ ufshcd_dme_get(hba,0x15000000+i*0x10000,&value); ++ printk("0x15%02x0000: 0x%08x\n",i,value); ++ } ++ ++ ufshcd_dme_get(hba,0x15640000,&value); ++ printk("0x15640000: 0x%08x\n",value); ++ ++ for(i = 0x67;i<=0x6a;i++) ++ { ++ ufshcd_dme_get(hba,0x15000000+i*0x10000,&value); ++ printk("0x15%02x0000: 0x%08x\n",i,value); ++ } ++ ++ ufshcd_dme_get(hba,0x15710000,&value); ++ printk("0x15710000: 0x%08x\n",value); ++ ++ for(i = 0x80;i<=0x87;i++) ++ { ++ ufshcd_dme_get(hba,0x15000000+i*0x10000,&value); ++ printk("0x15%02x0000: 0x%08x\n",i,value); ++ } ++ for(i = 0x90;i<=0x91;i++) ++ { ++ ufshcd_dme_get(hba,0x15000000+i*0x10000,&value); ++ printk("0x15%02x0000: 0x%08x\n",i,value); ++ } ++ for(i = 0xa0;i<=0xab;i++) ++ { ++ ufshcd_dme_get(hba,0x15000000+i*0x10000,&value); ++ printk("0x15%02x0000: 0x%08x\n",i,value); ++ } ++ for(i = 0xb0;i<=0xbb;i++) ++ { ++ ufshcd_dme_get(hba,0x15000000+i*0x10000,&value); ++ printk("0x15%02x0000: 0x%08x\n",i,value); ++ } ++ for(i = 0xc0;i<=0xc2;i++) ++ { ++ ufshcd_dme_get(hba,0x15000000+i*0x10000,&value); ++ printk("0x15%02x0000: 0x%08x\n",i,value); ++ } ++ ++} ++void printf_layer_2(struct ufs_hba *hba) ++{ ++ int i = 0; ++ int value = 0; ++ printk("------this for kernel layer_2------\n"); ++ for(i = 0x00;i<=0x06;i++) ++ { ++ ufshcd_dme_get(hba,0x20000000+i*0x10000,&value); ++ printk("0x20%02x0000: 0x%08x\n",i,value); ++ } ++ for(i = 0x40;i<=0x47;i++) ++ { ++ ufshcd_dme_get(hba,0x20000000+i*0x10000,&value); ++ printk("0x20%02x0000: 0x%08x\n",i,value); ++ } ++ for(i = 0x60;i<=0x67;i++) ++ { ++ ufshcd_dme_get(hba,0x20000000+i*0x10000,&value); ++ printk("0x20%02x0000: 0x%08x\n",i,value); ++ } ++ ufshcd_dme_get(hba,0x21000000,&value); ++ printk("0x21000000: 0x%08x\n",value); ++} ++void printf_layer_3(struct ufs_hba *hba) ++{ ++ int i = 0; ++ int value = 0; ++ printk("------this for kernel layer_3------\n"); ++ for(i = 0x00;i<=0x01;i++) ++ { ++ ufshcd_dme_get(hba,0x30000000+i*0x10000,&value); ++ printk("0x30%02x0000: 0x%08x\n",i,value); ++ } ++ for(i = 0x20;i<=0x21;i++) ++ { ++ ufshcd_dme_get(hba,0x30000000+i*0x10000,&value); ++ printk("0x30%02x0000: 0x%08x\n",i,value); ++ } ++} ++void printf_layer_4(struct ufs_hba *hba) ++{ ++ int i = 0; ++ int value = 0; ++ printk("------this for kernel layer_4------\n"); ++ for(i = 0x00;i<=0x01;i++) ++ { ++ ufshcd_dme_get(hba,0x40000000+i*0x10000,&value); ++ printk("0x40%02x0000: 0x%08x\n",i,value); ++ } ++ for(i = 0x20;i<=0x2b;i++) ++ { ++ ufshcd_dme_get(hba,0x40000000+i*0x10000,&value); ++ printk("0x40%02x0000: 0x%08x\n",i,value); ++ } ++ for(i = 0x60;i<=0x61;i++) ++ { ++ ufshcd_dme_get(hba,0x40000000+i*0x10000,&value); ++ printk("0x40%02x0000: 0x%08x\n",i,value); ++ } ++ for(i = 0x80;i<=0x86;i++) ++ { ++ ufshcd_dme_get(hba,0x40000000+i*0x10000,&value); ++ printk("0x40%02x0000: 0x%08x\n",i,value); ++ } ++ for(i = 0xa1;i<=0xab;i++) ++ { ++ ufshcd_dme_get(hba,0x40000000+i*0x10000,&value); ++ printk("0x40%02x0000: 0x%08x\n",i,value); ++ } ++} ++void ufs_dump(struct ufs_hba *hba) ++{ ++ dev_err(hba->dev,"===== UFSHCI REGISTER DUMP ======\n"); ++ dev_err(hba->dev,"CAP: 0x%08x||",ufshcd_readl(hba,REG_CONTROLLER_CAPABILITIES)); ++ dev_err(hba->dev,"VER: 0x%08x\n",ufshcd_readl(hba,REG_UFS_VERSION)); ++ dev_err(hba->dev,"HCPID: 0x%08x||",ufshcd_readl(hba,REG_CONTROLLER_DEV_ID)); ++ dev_err(hba->dev,"HCMID: 0x%08x\n",ufshcd_readl(hba,REG_CONTROLLER_PROD_ID)); ++ dev_err(hba->dev,"AHIT: 0x%08x||",ufshcd_readl(hba,0x18)); ++ dev_err(hba->dev,"IS: 0x%08x\n",ufshcd_readl(hba,REG_INTERRUPT_STATUS)); ++ dev_err(hba->dev,"IE: 0x%08x||",ufshcd_readl(hba,REG_INTERRUPT_ENABLE)); ++ dev_err(hba->dev,"HCS: 0x%08x\n",ufshcd_readl(hba,REG_CONTROLLER_STATUS)); ++ dev_err(hba->dev,"HCE: 0x%08x||",ufshcd_readl(hba,REG_CONTROLLER_ENABLE)); ++ dev_err(hba->dev,"UECPA: 0x%08x\n",ufshcd_readl(hba,REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER)); ++ dev_err(hba->dev,"UECDL: 0x%08x||",ufshcd_readl(hba,REG_UIC_ERROR_CODE_DATA_LINK_LAYER)); ++ dev_err(hba->dev,"UECN: 0x%08x\n",ufshcd_readl(hba,REG_UIC_ERROR_CODE_NETWORK_LAYER)); ++ dev_err(hba->dev,"UECT: 0x%08x||",ufshcd_readl(hba,REG_UIC_ERROR_CODE_TRANSPORT_LAYER)); ++ dev_err(hba->dev,"UECDME: 0x%08x\n",ufshcd_readl(hba,REG_UIC_ERROR_CODE_DME)); ++ dev_err(hba->dev,"UTRIACR: 0x%08x||",ufshcd_readl(hba,REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL)); ++ dev_err(hba->dev,"UTRLBA: 0x%08x\n",ufshcd_readl(hba,REG_UTP_TRANSFER_REQ_LIST_BASE_L)); ++ dev_err(hba->dev,"UTRLBAU: 0x%08x||",ufshcd_readl(hba,REG_UTP_TRANSFER_REQ_LIST_BASE_H)); ++ dev_err(hba->dev,"UTRLDBR: 0x%08x\n",ufshcd_readl(hba,REG_UTP_TRANSFER_REQ_DOOR_BELL)); ++ dev_err(hba->dev,"UTRLCLR: 0x%08x||",ufshcd_readl(hba,REG_UTP_TRANSFER_REQ_LIST_CLEAR)); ++ dev_err(hba->dev,"UTRLRSR: 0x%08x\n",ufshcd_readl(hba,REG_UTP_TRANSFER_REQ_LIST_RUN_STOP)); ++ dev_err(hba->dev,"UTMRLBA: 0x%08x||",ufshcd_readl(hba,REG_UTP_TASK_REQ_LIST_BASE_L)); ++ dev_err(hba->dev,"UTMRLBAU: 0x%08x\n",ufshcd_readl(hba,REG_UTP_TASK_REQ_LIST_BASE_H)); ++ dev_err(hba->dev,"UTMRLDBR: 0x%08x||",ufshcd_readl(hba,REG_UTP_TASK_REQ_DOOR_BELL)); ++ dev_err(hba->dev,"UTMRLCLR: 0x%08x\n",ufshcd_readl(hba,REG_UTP_TASK_REQ_LIST_CLEAR)); ++ dev_err(hba->dev,"UTMRLRSR: 0x%08x||",ufshcd_readl(hba,REG_UTP_TASK_REQ_LIST_RUN_STOP)); ++ dev_err(hba->dev,"UICCMD: 0x%08x\n",ufshcd_readl(hba,REG_UIC_COMMAND)); ++ dev_err(hba->dev,"UICCMDARG1: 0x%08x||",ufshcd_readl(hba,REG_UIC_COMMAND_ARG_1)); ++ dev_err(hba->dev,"UICCMDARG2: 0x%08x\n",ufshcd_readl(hba,REG_UIC_COMMAND_ARG_2)); ++ dev_err(hba->dev,"UICCMDARG3: 0x%08x||",ufshcd_readl(hba,REG_UIC_COMMAND_ARG_3)); ++ dev_err(hba->dev,"============================\n"); ++} ++ ++void printf_req_upiu(struct utp_upiu_req *ucd_req_ptr) ++{ ++ uint8_t *ptr_b; ++ int i = 0; ++ ptr_b = (uint8_t *)ucd_req_ptr; ++ printk("The byte array dump of req upiu(0x%p) is\n",ptr_b); ++ for (i = 0; (i < (sizeof(struct utp_upiu_req))); i += 4) ++ printk("0x%x 0x%x 0x%x 0x%x\n",ptr_b[i], ptr_b[i + 1], ptr_b[i + 2], ptr_b[i + 3]); ++ ++} ++void printf_res_upiu(struct ufs_query_res * ucd_res_ptr) ++{ ++ uint8_t *ptr_b; ++ int i = 0; ++ ptr_b = (uint8_t *)ucd_res_ptr; ++ printk("The byte array dump of res upiu(0x%p) is\n",ptr_b); ++ for (i = 0; (i < (sizeof(struct ufs_query_res))); i += 4) ++ printk("0x%x 0x%x 0x%x 0x%x\n",ptr_b[i], ptr_b[i + 1], ptr_b[i + 2], ptr_b[i + 3]); ++ ++} ++void printf_prd_table(struct ufshcd_sg_entry *ucd_prdt_ptr) ++{ ++ //int i = 0; ++ uint32_t *ptr_dw; ++ ptr_dw = (uint32_t *)ucd_prdt_ptr; ++ printk("The byte array dump of PRD Table(0x%p) is\n", ptr_dw); ++ //for (i = 0; i < 4; i++) ++ //printk("0x%x\n", ptr_dw[i]); ++} ++void printf_utrd_table(struct utp_transfer_req_desc * ucd_utrd_ptr) ++{ ++ int i = 0; ++ uint8_t *ptr_b; ++ ptr_b = (uint8_t *)ucd_utrd_ptr; ++ printk("The byte array dump of UTRD Table(0x%p) is\n", ptr_b); ++ for (i = 0; i < (sizeof(struct utp_transfer_req_desc)); i += 4) ++ printk("0x%x 0x%x 0x%x 0x%x\n",ptr_b[i], ptr_b[i + 1], ptr_b[i + 2], ptr_b[i + 3]); ++} ++ ++ ++ ++ ++ + static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag) + { + return tag >= 0 && tag < hba->nutrs; +@@ -2090,12 +2306,14 @@ static int ufshcd_read_desc_param(struct ufs_hba *hba, + (desc_buf[QUERY_DESC_LENGTH_OFFSET] != + ufs_query_desc_max_size[desc_id]) + || (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id)) { ++/* + dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d param_offset %d buff_len %d ret %d", + __func__, desc_id, param_offset, buff_len, ret); + if (!ret) + ret = -EINVAL; + + goto out; ++*/ + } + + if (is_kmalloc) +@@ -2751,7 +2969,7 @@ static void ufshcd_init_pwr_info(struct ufs_hba *hba) + hba->pwr_info.lane_tx = 1; + hba->pwr_info.pwr_rx = SLOWAUTO_MODE; + hba->pwr_info.pwr_tx = SLOWAUTO_MODE; +- hba->pwr_info.hs_rate = 0; ++ hba->pwr_info.hs_rate = 2; + } + + /** +@@ -2761,13 +2979,14 @@ static void ufshcd_init_pwr_info(struct ufs_hba *hba) + static int ufshcd_get_max_pwr_mode(struct ufs_hba *hba) + { + struct ufs_pa_layer_attr *pwr_info = &hba->max_pwr_info.info; +- + if (hba->max_pwr_info.is_valid) + return 0; + +- pwr_info->pwr_tx = FASTAUTO_MODE; +- pwr_info->pwr_rx = FASTAUTO_MODE; +- pwr_info->hs_rate = PA_HS_MODE_B; ++ pwr_info->gear_rx = 0; ++ pwr_info->gear_tx = 0; ++ pwr_info->pwr_rx = hba->hc_pwm; ++ pwr_info->pwr_tx = hba->hc_pwm; ++ pwr_info->hs_rate = hba->hc_rate; + + /* Get the connected lane count */ + ufshcd_dme_get(hba, UIC_ARG_MIB(PA_CONNECTEDRXDATALANES), +@@ -2782,13 +3001,20 @@ static int ufshcd_get_max_pwr_mode(struct ufs_hba *hba) + pwr_info->lane_tx); + return -EINVAL; + } ++ pwr_info->lane_rx = min_t(u32, pwr_info->lane_rx, hba->lanes_per_direction); ++ pwr_info->lane_tx = min_t(u32, pwr_info->lane_tx, hba->lanes_per_direction); + + /* + * First, get the maximum gears of HS speed. + * If a zero value, it means there is no HSGEAR capability. + * Then, get the maximum gears of PWM speed. + */ +- ufshcd_dme_get(hba, UIC_ARG_MIB(PA_MAXRXHSGEAR), &pwr_info->gear_rx); ++ /*get gear_tx in fast mode*/ ++ if(( FAST_MODE == pwr_info->pwr_rx) || ( FASTAUTO_MODE == pwr_info->pwr_rx)) ++ { ++ ufshcd_dme_get(hba, UIC_ARG_MIB(PA_MAXRXHSGEAR), &pwr_info->gear_rx); ++ } ++ + if (!pwr_info->gear_rx) { + ufshcd_dme_get(hba, UIC_ARG_MIB(PA_MAXRXPWMGEAR), + &pwr_info->gear_rx); +@@ -2797,11 +3023,12 @@ static int ufshcd_get_max_pwr_mode(struct ufs_hba *hba) + __func__, pwr_info->gear_rx); + return -EINVAL; + } +- pwr_info->pwr_rx = SLOWAUTO_MODE; + } +- +- ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_MAXRXHSGEAR), +- &pwr_info->gear_tx); ++ /*get gear_tx in fast mode*/ ++ if(( FAST_MODE == pwr_info->pwr_tx) || ( FASTAUTO_MODE == pwr_info->pwr_tx)) ++ { ++ ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_MAXRXHSGEAR),&pwr_info->gear_tx); ++ } + if (!pwr_info->gear_tx) { + ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_MAXRXPWMGEAR), + &pwr_info->gear_tx); +@@ -2810,8 +3037,9 @@ static int ufshcd_get_max_pwr_mode(struct ufs_hba *hba) + __func__, pwr_info->gear_tx); + return -EINVAL; + } +- pwr_info->pwr_tx = SLOWAUTO_MODE; + } ++ pwr_info->gear_rx = min_t(u32, pwr_info->gear_rx, hba->hc_gear); ++ pwr_info->gear_tx = min_t(u32, pwr_info->gear_tx, hba->hc_gear); + + hba->max_pwr_info.is_valid = true; + return 0; +@@ -3843,6 +4071,52 @@ static int ufshcd_bkops_ctrl(struct ufs_hba *hba, + return err; + } + ++static int ufshcd_set_refclk(struct ufs_hba *hba) ++{ ++ int ret = 0; ++ u32 value = 0; ++ u32 target_ref_clk; ++ ++ if (0) /*IF_FPGA()*/ ++ target_ref_clk = 1; /* 26MHz */ ++ else ++ target_ref_clk = 0; /* 19.2MHz */ ++ ++ ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR, ++ QUERY_ATTR_IDN_REFCLK_FREQ, 0, 0, &value); ++ if (ret) { ++ dev_err(hba->dev, "%s: read attr fail %d\n", ++ __func__, ret); ++ return ret; ++ } ++ ++ if (target_ref_clk == value) { ++ return 0; ++ } ++ ++ ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR, ++ QUERY_ATTR_IDN_REFCLK_FREQ, 0, 0, &target_ref_clk); ++ if (ret) { ++ dev_err(hba->dev, "%s: write attr fail %d\n", ++ __func__, ret); ++ return ret; ++ } ++ ++ value = 0xff; ++ ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR, ++ QUERY_ATTR_IDN_REFCLK_FREQ, 0, 0, &value); ++ if (ret) { ++ dev_err(hba->dev, "%s: read attr fail %d\n", ++ __func__, ret); ++ return ret; ++ } ++ ++ if (target_ref_clk == value) { ++ return 0; ++ } ++ dev_err(hba->dev, "%s: fail \n", __func__); ++ return -1; ++} + /** + * ufshcd_urgent_bkops - handle urgent bkops exception event + * @hba: per-adapter instance +@@ -4590,6 +4864,8 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba) + ufshcd_hba_stop(hba, false); + spin_unlock_irqrestore(hba->host->host_lock, flags); + ++ hba->vops->clk_hareware_init_notify(); ++ + err = ufshcd_hba_enable(hba); + if (err) + goto out; +@@ -5120,7 +5396,6 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) + ret = ufshcd_link_startup(hba); + if (ret) + goto out; +- + ufshcd_init_pwr_info(hba); + + /* set the default level for urgent bkops */ +@@ -5150,7 +5425,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) + ufshcd_set_ufs_dev_active(hba); + ufshcd_force_reset_auto_bkops(hba); + hba->wlun_dev_clr_ua = true; +- ++ ufshcd_set_refclk(hba); + if (ufshcd_get_max_pwr_mode(hba)) { + dev_err(hba->dev, + "%s: Failed getting max supported power mode\n", +@@ -6522,7 +6797,6 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) + int err; + struct Scsi_Host *host = hba->host; + struct device *dev = hba->dev; +- + if (!mmio_base) { + dev_err(hba->dev, + "Invalid memory reference for mmio_base is NULL\n"); +@@ -6532,7 +6806,6 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) + + hba->mmio_base = mmio_base; + hba->irq = irq; +- + err = ufshcd_hba_init(hba); + if (err) + goto out_error; +diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h +index 0450982..272ca7c 100644 +--- a/drivers/scsi/ufs/ufshcd.h ++++ b/drivers/scsi/ufs/ufshcd.h +@@ -289,6 +289,7 @@ struct ufs_hba_variant_ops { + int (*resume)(struct ufs_hba *, enum ufs_pm_op); + void (*dbg_register_dump)(struct ufs_hba *hba); + int (*phy_initialization)(struct ufs_hba *); ++ void (*clk_hareware_init_notify)(void); + }; + + /* clock gating state */ +@@ -549,6 +550,11 @@ struct ufs_hba { + */ + #define UFSHCD_CAP_INTR_AGGR (1 << 4) + ++ u32 hc_pwm; ++ u32 hc_gear; ++ u32 hc_rate; ++ u32 info_skip; ++ + struct devfreq *devfreq; + struct ufs_clk_scaling clk_scaling; + bool is_sys_suspended; +diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c +index f7f7ba1..15aeded 100644 +--- a/drivers/spi/spi-pl022.c ++++ b/drivers/spi/spi-pl022.c +@@ -43,6 +43,7 @@ + #include + #include + #include ++#include + + /* + * This macro is used to define some register default values. +@@ -136,6 +137,18 @@ + /* This one is only in the PL023 variant */ + #define SSP_CR1_MASK_FBCLKDEL_ST (0x7UL << 13) + ++#ifdef CONFIG_ARCH_HISI_BVT ++/* ++ * The Hisilicon version of this block adds some bits ++ * in SSP_CR1 ++ */ ++#define SSP_CR1_MASK_BIGEND_HISI (0x1UL << 4) ++#define SSP_CR1_MASK_ALTASENS_HISI (0x1UL << 6) ++ ++#define SSP_TX_FIFO_CR(r) (r + 0x28) ++#define SSP_RX_FIFO_CR(r) (r + 0x2C) ++#endif ++ + /* + * SSP Status Register - SSP_SR + */ +@@ -296,6 +309,10 @@ + + #define SPI_POLLING_TIMEOUT 1000 + ++#ifdef CONFIG_ARCH_HISI_BVT ++#define PL022_IDS_INDEX_HISI 4 ++#endif ++ + /* + * The type of reading going on on this chip + */ +@@ -337,6 +354,15 @@ struct vendor_data { + bool internal_cs_ctrl; + }; + ++#ifdef CONFIG_ARCH_HISI_BVT ++struct cs_data { ++ struct resource res; ++ void __iomem *virt_addr; ++ unsigned int cs_sb; ++ unsigned int cs_mask_bit; ++}; ++#endif ++ + /** + * struct pl022 - This is the private SSP driver data structure + * @adev: AMBA device model hookup +@@ -346,6 +372,13 @@ struct vendor_data { + * @clk: outgoing clock "SPICLK" for the SPI bus + * @master: SPI framework hookup + * @master_info: controller-specific data from machine setup ++ * @kworker: thread struct for message pump ++ * @kworker_task: pointer to task for message pump kworker thread ++ * @pump_messages: work struct for scheduling work to the message pump ++ * @queue_lock: spinlock to syncronise access to message queue ++ * @queue: message queue ++ * @busy: message pump is busy ++ * @running: message pump is running + * @pump_transfers: Tasklet used in Interrupt Transfer mode + * @cur_msg: Pointer to current spi_message being processed + * @cur_transfer: Pointer to current spi_transfer +@@ -403,6 +436,9 @@ struct pl022 { + #endif + int cur_cs; + int *chipselects; ++#ifdef CONFIG_ARCH_HISI_BVT ++ struct cs_data *cs_data; ++#endif + }; + + /** +@@ -459,13 +495,41 @@ static void null_cs_control(u32 command) + static void internal_cs_control(struct pl022 *pl022, u32 command) + { + u32 tmp; ++#ifdef CONFIG_ARCH_HISI_BVT ++ struct amba_device *adev = pl022->adev; ++ struct amba_driver *adrv = container_of(adev->dev.driver, ++ struct amba_driver, drv); ++ ++ if (pl022->vendor->extended_cr && (adev->periphid == ++ adrv->id_table[PL022_IDS_INDEX_HISI].id)) { ++ if (pl022->cs_data) { ++ tmp = readl(pl022->cs_data->virt_addr); ++ tmp &= ~(pl022->cs_data->cs_mask_bit); ++ tmp |= ((u32)pl022->cur_cs) << pl022->cs_data->cs_sb; ++ writel(tmp, pl022->cs_data->virt_addr); ++ } + ++ if (command == SSP_CHIP_SELECT) ++ /* Enable SSP */ ++ writew((readw(SSP_CR1(pl022->virtbase)) | ++ SSP_CR1_MASK_SSE), ++ SSP_CR1(pl022->virtbase)); ++ else ++ /* disable SSP */ ++ writew((readw(SSP_CR1(pl022->virtbase)) & ++ (~SSP_CR1_MASK_SSE)), ++ SSP_CR1(pl022->virtbase)); ++ } else { ++#endif + tmp = readw(SSP_CSR(pl022->virtbase)); + if (command == SSP_CHIP_SELECT) +- tmp &= ~BIT(pl022->cur_cs); ++ tmp &= ~BIT((u32)pl022->cur_cs); + else +- tmp |= BIT(pl022->cur_cs); ++ tmp |= BIT((u32)pl022->cur_cs); + writew(tmp, SSP_CSR(pl022->virtbase)); ++#ifdef CONFIG_ARCH_HISI_BVT ++ } ++#endif + } + + static void pl022_cs_control(struct pl022 *pl022, u32 command) +@@ -566,8 +630,16 @@ static int flush(struct pl022 *pl022) + static void restore_state(struct pl022 *pl022) + { + struct chip_data *chip = pl022->cur_chip; ++#ifdef CONFIG_ARCH_HISI_BVT ++ struct amba_device *adev = pl022->adev; ++ struct amba_driver *adrv = container_of(adev->dev.driver, ++ struct amba_driver, drv); + ++ if (pl022->vendor->extended_cr && (adev->periphid != ++ adrv->id_table[PL022_IDS_INDEX_HISI].id)) ++#else + if (pl022->vendor->extended_cr) ++#endif + writel(chip->cr0, SSP_CR0(pl022->virtbase)); + else + writew(chip->cr0, SSP_CR0(pl022->virtbase)); +@@ -640,6 +712,15 @@ static void restore_state(struct pl022 *pl022) + GEN_MASK_BITS(SSP_FEEDBACK_CLK_DELAY_NONE, SSP_CR1_MASK_FBCLKDEL_ST, 13) \ + ) + ++#ifdef CONFIG_ARCH_HISI_BVT ++/* Hisilicon versions extend this register to use all 16 bits */ ++#define DEFAULT_SSP_REG_CR1_HISI ( \ ++ DEFAULT_SSP_REG_CR1 | \ ++ GEN_MASK_BITS(SSP_RX_MSB, SSP_CR1_MASK_BIGEND_HISI, 4) | \ ++ GEN_MASK_BITS(0x1, SSP_CR1_MASK_ALTASENS_HISI, 6) \ ++) ++#endif ++ + #define DEFAULT_SSP_REG_CPSR ( \ + GEN_MASK_BITS(SSP_DEFAULT_PRESCALE, SSP_CPSR_MASK_CPSDVSR, 0) \ + ) +@@ -659,8 +740,22 @@ static void load_ssp_default_config(struct pl022 *pl022) + writel(DEFAULT_SSP_REG_CR0_ST_PL023, SSP_CR0(pl022->virtbase)); + writew(DEFAULT_SSP_REG_CR1_ST_PL023, SSP_CR1(pl022->virtbase)); + } else if (pl022->vendor->extended_cr) { ++#ifdef CONFIG_ARCH_HISI_BVT ++ struct amba_device *adev = pl022->adev; ++ struct amba_driver *adrv = container_of(adev->dev.driver, ++ struct amba_driver, drv); ++ ++ if (adev->periphid == adrv->id_table[PL022_IDS_INDEX_HISI].id) { ++ writew(DEFAULT_SSP_REG_CR0, SSP_CR0(pl022->virtbase)); ++ writew(DEFAULT_SSP_REG_CR1_HISI, ++ SSP_CR1(pl022->virtbase)); ++ } else { ++#endif + writel(DEFAULT_SSP_REG_CR0_ST, SSP_CR0(pl022->virtbase)); + writew(DEFAULT_SSP_REG_CR1_ST, SSP_CR1(pl022->virtbase)); ++#ifdef CONFIG_ARCH_HISI_BVT ++ } ++#endif + } else { + writew(DEFAULT_SSP_REG_CR0, SSP_CR0(pl022->virtbase)); + writew(DEFAULT_SSP_REG_CR1, SSP_CR1(pl022->virtbase)); +@@ -1289,7 +1384,6 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id) + if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RFF) + dev_err(&pl022->adev->dev, + "RXFIFO is full\n"); +- + /* + * Disable and clear interrupts, disable SSP, + * mark message with bad status so it can be +@@ -1835,6 +1929,13 @@ static int pl022_setup(struct spi_device *spi) + unsigned int bits = spi->bits_per_word; + u32 tmp; + struct device_node *np = spi->dev.of_node; ++#ifdef CONFIG_ARCH_HISI_BVT ++ struct amba_device *adev = pl022->adev; ++ struct amba_driver *adrv = container_of(adev->dev.driver, ++ struct amba_driver, drv); ++ writel(0, SSP_TX_FIFO_CR(pl022->virtbase)); ++ writel(0, SSP_RX_FIFO_CR(pl022->virtbase)); ++#endif + + if (!spi->max_speed_hz) + return -EINVAL; +@@ -1977,7 +2078,12 @@ static int pl022_setup(struct spi_device *spi) + chip->cpsr = clk_freq.cpsdvsr; + + /* Special setup for the ST micro extended control registers */ ++#ifdef CONFIG_ARCH_HISI_BVT ++ if (pl022->vendor->extended_cr && (adev->periphid != ++ adrv->id_table[PL022_IDS_INDEX_HISI].id)) { ++#else + if (pl022->vendor->extended_cr) { ++#endif + u32 etx; + + if (pl022->vendor->pl023) { +@@ -2011,6 +2117,22 @@ static int pl022_setup(struct spi_device *spi) + SSP_CR1_MASK_RXIFLSEL_ST, 7); + SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig, + SSP_CR1_MASK_TXIFLSEL_ST, 10); ++#ifdef CONFIG_ARCH_HISI_BVT ++ } else if (pl022->vendor->extended_cr && (adev->periphid == ++ adrv->id_table[PL022_IDS_INDEX_HISI].id)) { ++ SSP_WRITE_BITS(chip->cr0, bits - 1, ++ SSP_CR0_MASK_DSS, 0); ++ SSP_WRITE_BITS(chip->cr0, chip_info->iface, ++ SSP_CR0_MASK_FRF, 4); ++ ++ if (spi->mode & SPI_LSB_FIRST) ++ tmp = !!SPI_LSB_FIRST; ++ else ++ tmp = !SPI_LSB_FIRST; ++ ++ SSP_WRITE_BITS(chip->cr1, tmp, SSP_CR1_MASK_BIGEND_HISI, 4); ++ SSP_WRITE_BITS(chip->cr1, 0x1, SSP_CR1_MASK_ALTASENS_HISI, 6); ++#endif + } else { + SSP_WRITE_BITS(chip->cr0, bits - 1, + SSP_CR0_MASK_DSS, 0); +@@ -2042,7 +2164,7 @@ static int pl022_setup(struct spi_device *spi) + } + SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1); + SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2); +- SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, ++ SSP_WRITE_BITS(chip->cr1, (unsigned int)chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, + 3); + + /* Save controller_state */ +@@ -2074,7 +2196,7 @@ pl022_platform_data_dt_get(struct device *dev) + { + struct device_node *np = dev->of_node; + struct pl022_ssp_controller *pd; +- u32 tmp; ++ u32 tmp = 0; + + if (!np) { + dev_err(dev, "no dt node defined\n"); +@@ -2099,6 +2221,8 @@ pl022_platform_data_dt_get(struct device *dev) + static int pl022_probe(struct amba_device *adev, const struct amba_id *id) + { + struct device *dev = &adev->dev; ++ struct amba_driver *adrv = container_of(adev->dev.driver, ++ struct amba_driver, drv); + struct pl022_ssp_controller *platform_info = + dev_get_platdata(&adev->dev); + struct spi_master *master; +@@ -2162,6 +2286,43 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) + } else if (pl022->vendor->internal_cs_ctrl) { + for (i = 0; i < num_cs; i++) + pl022->chipselects[i] = i; ++ ++#ifdef CONFIG_ARCH_HISI_BVT ++ if ((adev->periphid == adrv->id_table[PL022_IDS_INDEX_HISI].id) ++ && pl022->vendor->extended_cr ++ && (num_cs > 1)) { ++ pl022->cs_data = devm_kzalloc(dev, ++ sizeof(struct cs_data), ++ GFP_KERNEL); ++ if (!pl022->cs_data) { ++ status = -ENOMEM; ++ goto err_no_mem; ++ } ++ ++ if (of_address_to_resource(np, 1, ++ &pl022->cs_data->res)) { ++ status = -EPROBE_DEFER; ++ goto err_no_gpio; ++ } ++ ++ if (of_property_read_u32(np, "hisi,spi_cs_sb", ++ &pl022->cs_data->cs_sb)) { ++ status = -EPROBE_DEFER; ++ goto err_no_gpio; ++ } ++ ++ if (of_property_read_u32(np, "hisi,spi_cs_mask_bit", ++ &pl022->cs_data->cs_mask_bit)) { ++ status = -EPROBE_DEFER; ++ goto err_no_gpio; ++ } ++ ++ pl022->cs_data->virt_addr = devm_ioremap(dev, ++ pl022->cs_data->res.start, ++ resource_size(&adev->res)); ++ } else ++ pl022->cs_data = NULL; ++#endif + } else if (IS_ENABLED(CONFIG_OF)) { + for (i = 0; i < num_cs; i++) { + int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); +@@ -2288,6 +2449,11 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) + err_no_ioremap: + amba_release_regions(adev); + err_no_ioregion: ++#ifdef CONFIG_ARCH_HISI_BVT ++ if (pl022->cs_data) ++ release_mem_region(pl022->cs_data->res.start, ++ resource_size(&pl022->cs_data->res)); ++#endif + err_no_gpio: + err_no_mem: + spi_master_put(master); +@@ -2314,6 +2480,11 @@ pl022_remove(struct amba_device *adev) + + clk_disable_unprepare(pl022->clk); + amba_release_regions(adev); ++#ifdef CONFIG_ARCH_HISI_BVT ++ if (pl022->cs_data) ++ release_mem_region(pl022->cs_data->res.start, ++ resource_size(&pl022->cs_data->res)); ++#endif + tasklet_disable(&pl022->pump_transfers); + return 0; + } +@@ -2429,6 +2600,18 @@ static struct vendor_data vendor_lsi = { + .internal_cs_ctrl = true, + }; + ++#ifdef CONFIG_ARCH_HISI_BVT ++static struct vendor_data vendor_hisi = { ++ .fifodepth = 256, ++ .max_bpw = 16, ++ .unidir = false, ++ .extended_cr = true, ++ .pl023 = false, ++ .loopback = true, ++ .internal_cs_ctrl = true, ++}; ++#endif ++ + static struct amba_id pl022_ids[] = { + { + /* +@@ -2469,6 +2652,17 @@ static struct amba_id pl022_ids[] = { + .mask = 0x000fffff, + .data = &vendor_lsi, + }, ++#ifdef CONFIG_ARCH_HISI_BVT ++ { ++ /* ++ * Hisilicon derivative, this has a 16bit wide ++ * and 256 locations deep TX/RX FIFO ++ */ ++ .id = 0x00800022, ++ .mask = 0xffffffff, ++ .data = &vendor_hisi, ++ }, ++#endif + { 0, 0 }, + }; + +diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c +index 6db8063..ce94584 100644 +--- a/drivers/spi/spi.c ++++ b/drivers/spi/spi.c +@@ -323,11 +323,125 @@ static int spi_uevent(struct device *dev, struct kobj_uevent_env *env) + return 0; + } + ++#ifdef CONFIG_PM_SLEEP ++static int spi_legacy_suspend(struct device *dev, pm_message_t message) ++{ ++ int value = 0; ++ struct spi_driver *drv = to_spi_driver(dev->driver); ++ ++ /* suspend will stop irqs and dma; no more i/o */ ++ if (drv) { ++ if (drv->suspend) ++ value = drv->suspend(to_spi_device(dev), message); ++ else ++ dev_dbg(dev, "... can't suspend\n"); ++ } ++ return value; ++} ++ ++static int spi_legacy_resume(struct device *dev) ++{ ++ int value = 0; ++ struct spi_driver *drv = to_spi_driver(dev->driver); ++ ++ /* resume may restart the i/o queue */ ++ if (drv) { ++ if (drv->resume) ++ value = drv->resume(to_spi_device(dev)); ++ else ++ dev_dbg(dev, "... can't resume\n"); ++ } ++ return value; ++} ++ ++static int spi_pm_suspend(struct device *dev) ++{ ++ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; ++ ++ if (pm) ++ return pm_generic_suspend(dev); ++ else ++ return spi_legacy_suspend(dev, PMSG_SUSPEND); ++} ++ ++static int spi_pm_resume(struct device *dev) ++{ ++ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; ++ ++ if (pm) ++ return pm_generic_resume(dev); ++ else ++ return spi_legacy_resume(dev); ++} ++ ++static int spi_pm_freeze(struct device *dev) ++{ ++ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; ++ ++ if (pm) ++ return pm_generic_freeze(dev); ++ else ++ return spi_legacy_suspend(dev, PMSG_FREEZE); ++} ++ ++static int spi_pm_thaw(struct device *dev) ++{ ++ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; ++ ++ if (pm) ++ return pm_generic_thaw(dev); ++ else ++ return spi_legacy_resume(dev); ++} ++ ++static int spi_pm_poweroff(struct device *dev) ++{ ++ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; ++ ++ if (pm) ++ return pm_generic_poweroff(dev); ++ else ++ return spi_legacy_suspend(dev, PMSG_HIBERNATE); ++} ++ ++static int spi_pm_restore(struct device *dev) ++{ ++ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; ++ ++ if (pm) ++ return pm_generic_restore(dev); ++ else ++ return spi_legacy_resume(dev); ++} ++#else ++#define spi_pm_suspend NULL ++#define spi_pm_resume NULL ++#define spi_pm_freeze NULL ++#define spi_pm_thaw NULL ++#define spi_pm_poweroff NULL ++#define spi_pm_restore NULL ++#endif ++ ++static const struct dev_pm_ops spi_pm = { ++ .suspend = spi_pm_suspend, ++ .resume = spi_pm_resume, ++ .freeze = spi_pm_freeze, ++ .thaw = spi_pm_thaw, ++ .poweroff = spi_pm_poweroff, ++ .restore = spi_pm_restore, ++ SET_RUNTIME_PM_OPS( ++ pm_generic_runtime_suspend, ++ pm_generic_runtime_resume, ++ NULL ++ ) ++}; ++ + struct bus_type spi_bus_type = { + .name = "spi", + .dev_groups = spi_dev_groups, + .match = spi_match_device, + .uevent = spi_uevent, ++ .pm = &spi_pm, + }; + EXPORT_SYMBOL_GPL(spi_bus_type); + +diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c +index e2c33b9..e242371 100644 +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -109,12 +109,20 @@ struct vendor_data { + + static unsigned int get_fifosize_arm(struct amba_device *dev) + { ++#ifdef CONFIG_ARCH_HISI_BVT ++ return 64; ++#else + return amba_rev(dev) < 3 ? 16 : 32; ++#endif + } + + static struct vendor_data vendor_arm = { + .reg_offset = pl011_std_offsets, ++#ifdef CONFIG_ARCH_HISI_BVT ++ .ifls = UART011_IFLS_RX1_8|UART011_IFLS_TX1_8, ++#else + .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, ++#endif + .fr_busy = UART01x_FR_BUSY, + .fr_dsr = UART01x_FR_DSR, + .fr_cts = UART01x_FR_CTS, +@@ -405,7 +413,11 @@ static void pl011_dma_probe(struct uart_amba_port *uap) + pl011_reg_to_offset(uap, REG_DR), + .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, + .direction = DMA_MEM_TO_DEV, ++#ifdef CONFIG_ARCH_HISI_BVT ++ .dst_maxburst = 7, ++#else + .dst_maxburst = uap->fifosize >> 1, ++#endif + .device_fc = false, + }; + struct dma_chan *chan; +@@ -461,7 +473,11 @@ static void pl011_dma_probe(struct uart_amba_port *uap) + pl011_reg_to_offset(uap, REG_DR), + .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, + .direction = DMA_DEV_TO_MEM, ++#ifdef CONFIG_ARCH_HISI_BVT ++ .src_maxburst = 7, ++#else + .src_maxburst = uap->fifosize >> 2, ++#endif + .device_fc = false, + }; + struct dma_slave_caps caps; +diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c +index baa7cdc..6acd0ba 100644 +--- a/drivers/usb/gadget/composite.c ++++ b/drivers/usb/gadget/composite.c +@@ -24,6 +24,13 @@ + + #include "u_os_desc.h" + ++#if defined(CONFIG_ARCH_HI3516A) || defined(CONFIG_ARCH_HI3518EV20X) ++#define USB2_BASE_REG 0x20120000 ++#define DWC_OTG_EN (1 << 31) ++#define USB2_PHY_DPPULL_DOWN (0x3 << 26) ++#define USB2_OTG_BASE 0x78 ++#endif ++ + /** + * struct usb_os_string - represents OS String to be reported by a gadget + * @bLength: total length of the entire descritor, always 0x12 +@@ -2185,6 +2192,10 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev) + static int composite_bind(struct usb_gadget *gadget, + struct usb_gadget_driver *gdriver) + { ++#if defined(CONFIG_ARCH_HI3516A) || defined(CONFIG_ARCH_HI3518EV20X) ++ void __iomem *usb2_base_reg = ioremap_nocache(USB2_BASE_REG, 0x1000); ++ int usb2_reg; ++#endif + struct usb_composite_dev *cdev; + struct usb_composite_driver *composite = to_cdriver(gdriver); + int status = -ENOMEM; +@@ -2223,6 +2234,13 @@ static int composite_bind(struct usb_gadget *gadget, + if (composite->needs_serial && !cdev->desc.iSerialNumber) + WARNING(cdev, "userspace failed to provide iSerialNumber\n"); + ++#if defined(CONFIG_ARCH_HI3516A) || defined(CONFIG_ARCH_HI3518EV20X) ++ usb2_reg = readl(usb2_base_reg + USB2_OTG_BASE); ++ usb2_reg &= ~(USB2_PHY_DPPULL_DOWN); ++ usb2_reg |= DWC_OTG_EN; ++ writel(usb2_reg, usb2_base_reg + USB2_OTG_BASE); ++ iounmap(usb2_base_reg); ++#endif + INFO(cdev, "%s ready\n", composite->name); + return 0; + +@@ -2347,6 +2365,16 @@ EXPORT_SYMBOL_GPL(usb_composite_probe); + */ + void usb_composite_unregister(struct usb_composite_driver *driver) + { ++#if defined(CONFIG_ARCH_HI3516A) || defined(CONFIG_ARCH_HI3518EV20X) ++ void __iomem *usb2_base_reg = ioremap_nocache(USB2_BASE_REG, 0x1000); ++ int usb2_reg; ++ ++ usb2_reg = readl(usb2_base_reg + USB2_OTG_BASE); ++ usb2_reg |= USB2_PHY_DPPULL_DOWN; ++ usb2_reg &= ~DWC_OTG_EN; ++ writel(usb2_reg, usb2_base_reg + USB2_OTG_BASE); ++ iounmap(usb2_base_reg); ++#endif + usb_gadget_unregister_driver(&driver->gadget_driver); + } + EXPORT_SYMBOL_GPL(usb_composite_unregister); +diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c +index ccd93c9..64d9728 100644 +--- a/drivers/usb/gadget/function/f_mass_storage.c ++++ b/drivers/usb/gadget/function/f_mass_storage.c +@@ -253,6 +253,7 @@ static struct usb_gadget_strings *fsg_strings_array[] = { + + struct fsg_dev; + struct fsg_common; ++extern void hisi_switch_func(int otg); + + /* Data shared by all the FSG instances. */ + struct fsg_common { +@@ -1954,6 +1955,9 @@ static int do_scsi_command(struct fsg_common *common) + "READ CAPACITY"); + if (reply == 0) + reply = do_read_capacity(common, bh); ++ ++ hisi_switch_func(1); ++ + break; + + case READ_HEADER: +@@ -1997,6 +2001,9 @@ static int do_scsi_command(struct fsg_common *common) + "REQUEST SENSE"); + if (reply == 0) + reply = do_request_sense(common, bh); ++ ++ hisi_switch_func(1); ++ + break; + + case START_STOP: +diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig +index 658b8da..66c7431 100644 +--- a/drivers/usb/gadget/udc/Kconfig ++++ b/drivers/usb/gadget/udc/Kconfig +@@ -232,6 +232,26 @@ config USB_MV_UDC + USB2.0 OTG controller, which can be configured as high speed or + full speed USB peripheral. + ++menuconfig HIUSB_DEVICE2_0 ++ bool "Hisilicon USB2.0 Device Controller SUPPORT" ++ help ++ This selects the usb(ehci/ohci) family usb device. ++ Say Y to enable hisi usb2.0 controller driver. ++ IF you do not use usb2.0 device in your board, ++ say N to get a smaller uImage. Mostly you need it. ++ ++if HIUSB_DEVICE2_0 ++ config USB_HISI_UDC ++ tristate "hisilicon highspeed device controller version 3.00a driver" ++ help ++ You can select device mode by the option. ++ Enable hisi ehci controller driver. ++ Say Y to enable hisi usb2.0 ehci controller driver. ++ IF you do not use usb2.0 ehci device in your board, say N to get a ++ smaller uImage. Mostly you need it. ++ ++endif ++ + config USB_MV_U3D + depends on HAS_DMA + tristate "MARVELL PXA2128 USB 3.0 controller" +diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile +index 98e74ed..ecd9036 100644 +--- a/drivers/usb/gadget/udc/Makefile ++++ b/drivers/usb/gadget/udc/Makefile +@@ -1,8 +1,10 @@ + # define_trace.h needs to know how to find our header + CFLAGS_trace.o := -I$(src) ++#ifndef CONFIG_USB_HISI_UDC + + udc-core-y := core.o trace.o + ++#endif + # + # USB peripheral controller drivers + # +@@ -37,3 +39,4 @@ obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o + obj-$(CONFIG_USB_GR_UDC) += gr_udc.o + obj-$(CONFIG_USB_GADGET_XILINX) += udc-xilinx.o + obj-$(CONFIG_USB_BDC_UDC) += bdc/ ++obj-$(CONFIG_USB_HISI_UDC) += hiudc/ +diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c +index d685d82..a849216 100644 +--- a/drivers/usb/gadget/udc/core.c ++++ b/drivers/usb/gadget/udc/core.c +@@ -904,11 +904,6 @@ int usb_gadget_ep_match_desc(struct usb_gadget *gadget, + type = usb_endpoint_type(desc); + max = 0x7ff & usb_endpoint_maxp(desc); + +- if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in) +- return 0; +- if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out) +- return 0; +- + if (max > ep->maxpacket_limit) + return 0; + +@@ -928,8 +923,6 @@ int usb_gadget_ep_match_desc(struct usb_gadget *gadget, + return 0; + break; + case USB_ENDPOINT_XFER_BULK: +- if (!ep->caps.type_bulk) +- return 0; + if (ep_comp && gadget_is_superspeed(gadget)) { + /* Get the number of required streams from the + * EP companion descriptor and see if the EP +@@ -966,15 +959,6 @@ static void usb_gadget_state_work(struct work_struct *work) + if (udc) + sysfs_notify(&udc->dev.kobj, NULL, "state"); + } +- +-void usb_gadget_set_state(struct usb_gadget *gadget, +- enum usb_device_state state) +-{ +- gadget->state = state; +- schedule_work(&gadget->work); +-} +-EXPORT_SYMBOL_GPL(usb_gadget_set_state); +- + /* ------------------------------------------------------------------------- */ + + static void usb_udc_connect_control(struct usb_udc *udc) +@@ -985,6 +969,24 @@ static void usb_udc_connect_control(struct usb_udc *udc) + usb_gadget_disconnect(udc->gadget); + } + ++/* should be called with udc_lock held */ ++static int check_pending_gadget_drivers(struct usb_udc *udc) ++{ ++ struct usb_gadget_driver *driver; ++ int ret = 0; ++ ++ list_for_each_entry(driver, &gadget_driver_pending_list, pending) ++ if (!driver->udc_name || strcmp(driver->udc_name, ++ dev_name(&udc->dev)) == 0) { ++ ret = udc_bind_to_driver(udc, driver); ++ if (ret != -EPROBE_DEFER) ++ list_del(&driver->pending); ++ break; ++ } ++ ++ return ret; ++} ++ + /** + * usb_udc_vbus_handler - updates the udc core vbus status, and try to + * connect or disconnect gadget +@@ -1005,6 +1007,15 @@ void usb_udc_vbus_handler(struct usb_gadget *gadget, bool status) + } + EXPORT_SYMBOL_GPL(usb_udc_vbus_handler); + ++/* ------------------------------------------------------------------------- */ ++void usb_gadget_set_state(struct usb_gadget *gadget, ++ enum usb_device_state state) ++{ ++ gadget->state = state; ++} ++EXPORT_SYMBOL_GPL(usb_gadget_set_state); ++/* ------------------------------------------------------------------------- */ ++ + /** + * usb_gadget_udc_reset - notifies the udc core that bus reset occurs + * @gadget: The gadget which bus reset occurs +@@ -1080,24 +1091,6 @@ static void usb_udc_nop_release(struct device *dev) + dev_vdbg(dev, "%s\n", __func__); + } + +-/* should be called with udc_lock held */ +-static int check_pending_gadget_drivers(struct usb_udc *udc) +-{ +- struct usb_gadget_driver *driver; +- int ret = 0; +- +- list_for_each_entry(driver, &gadget_driver_pending_list, pending) +- if (!driver->udc_name || strcmp(driver->udc_name, +- dev_name(&udc->dev)) == 0) { +- ret = udc_bind_to_driver(udc, driver); +- if (ret != -EPROBE_DEFER) +- list_del(&driver->pending); +- break; +- } +- +- return ret; +-} +- + /** + * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list + * @parent: the parent device to this udc. Usually the controller driver's +@@ -1310,87 +1303,6 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri + udc->gadget->dev.driver = NULL; + return ret; + } +- +-int usb_gadget_probe_driver(struct usb_gadget_driver *driver) +-{ +- struct usb_udc *udc = NULL; +- int ret = -ENODEV; +- +- if (!driver || !driver->bind || !driver->setup) +- return -EINVAL; +- +- mutex_lock(&udc_lock); +- if (driver->udc_name) { +- list_for_each_entry(udc, &udc_list, list) { +- ret = strcmp(driver->udc_name, dev_name(&udc->dev)); +- if (!ret) +- break; +- } +- if (ret) +- ret = -ENODEV; +- else if (udc->driver) +- ret = -EBUSY; +- else +- goto found; +- } else { +- list_for_each_entry(udc, &udc_list, list) { +- /* For now we take the first one */ +- if (!udc->driver) +- goto found; +- } +- } +- +- if (!driver->match_existing_only) { +- list_add_tail(&driver->pending, &gadget_driver_pending_list); +- pr_info("udc-core: couldn't find an available UDC - added [%s] to list of pending drivers\n", +- driver->function); +- ret = 0; +- } +- +- mutex_unlock(&udc_lock); +- return ret; +-found: +- ret = udc_bind_to_driver(udc, driver); +- mutex_unlock(&udc_lock); +- return ret; +-} +-EXPORT_SYMBOL_GPL(usb_gadget_probe_driver); +- +-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) +-{ +- struct usb_udc *udc = NULL; +- int ret = -ENODEV; +- +- if (!driver || !driver->unbind) +- return -EINVAL; +- +- mutex_lock(&udc_lock); +- list_for_each_entry(udc, &udc_list, list) { +- if (udc->driver == driver) { +- usb_gadget_remove_driver(udc); +- usb_gadget_set_state(udc->gadget, +- USB_STATE_NOTATTACHED); +- +- /* Maybe there is someone waiting for this UDC? */ +- check_pending_gadget_drivers(udc); +- /* +- * For now we ignore bind errors as probably it's +- * not a valid reason to fail other's gadget unbind +- */ +- ret = 0; +- break; +- } +- } +- +- if (ret) { +- list_del(&driver->pending); +- ret = 0; +- } +- mutex_unlock(&udc_lock); +- return ret; +-} +-EXPORT_SYMBOL_GPL(usb_gadget_unregister_driver); +- + /* ------------------------------------------------------------------------- */ + + static ssize_t usb_udc_srp_store(struct device *dev, +diff --git a/drivers/usb/gadget/udc/hiudc/Makefile b/drivers/usb/gadget/udc/hiudc/Makefile +new file mode 100644 +index 0000000..28dd23c +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/Makefile +@@ -0,0 +1,21 @@ ++# ++# USB peripheral controller drivers ++# ++# Use the BUS_INTERFACE variable to compile the software for either ++# PCI(PCI_INTERFACE) or LM(LM_INTERFACE) bus. ++# Use one of the following flags to compile the software in host-only or ++# device-only mode. ++EXTRA_CFLAGS += -DDWC_DEVICE_ONLY ++EXTRA_CFLAGS += -DDWC_LINUX ++EXTRA_CFLAGS += -DLM_INTERFACE ++ ++obj-$(CONFIG_USB_HISI_UDC) += udc-hisi.o ++#obj-y += udc-hisi.o ++udc-hisi-objs := dwc_otg_driver.o dwc_otg_attr.o ++udc-hisi-objs += dwc_otg_cil.o dwc_otg_cil_intr.o ++udc-hisi-objs += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o ++udc-hisi-objs += dwc_otg_hcd.o dwc_otg_hcd_linux.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o dwc_otg_hcd_ddma.o ++udc-hisi-objs += dwc_otg_adp.o ++udc-hisi-objs += dwc_cc.o dwc_modpow.o dwc_dh.o \ ++ dwc_crypto.o dwc_notifier.o \ ++ dwc_common_linux.o dwc_mem.o +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_cc.c b/drivers/usb/gadget/udc/hiudc/dwc_cc.c +new file mode 100644 +index 0000000..a757f4f +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_cc.c +@@ -0,0 +1,532 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.c $ ++ * $Revision: #4 $ ++ * $Date: 2010/11/04 $ ++ * $Change: 1621692 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS 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. ++ * ========================================================================= */ ++#ifdef DWC_CCLIB ++ ++#include "dwc_cc.h" ++ ++typedef struct dwc_cc ++{ ++ uint32_t uid; ++ uint8_t chid[16]; ++ uint8_t cdid[16]; ++ uint8_t ck[16]; ++ uint8_t *name; ++ uint8_t length; ++ DWC_CIRCLEQ_ENTRY(dwc_cc) list_entry; ++} dwc_cc_t; ++ ++DWC_CIRCLEQ_HEAD(context_list, dwc_cc); ++ ++/** The main structure for CC management. */ ++struct dwc_cc_if ++{ ++ dwc_mutex_t *mutex; ++ char *filename; ++ ++ unsigned is_host:1; ++ ++ dwc_notifier_t *notifier; ++ ++ struct context_list list; ++}; ++ ++#ifdef DEBUG ++static inline void dump_bytes(char *name, uint8_t *bytes, int len) ++{ ++ int i; ++ DWC_PRINTF("%s: ", name); ++ for (i=0; ilength = length; ++ cc->name = dwc_alloc(mem_ctx, length); ++ if (!cc->name) { ++ dwc_free(mem_ctx, cc); ++ return NULL; ++ } ++ ++ DWC_MEMCPY(cc->name, name, length); ++ } ++ ++ return cc; ++} ++ ++static void free_cc(void *mem_ctx, dwc_cc_t *cc) ++{ ++ if (cc->name) { ++ dwc_free(mem_ctx, cc->name); ++ } ++ dwc_free(mem_ctx, cc); ++} ++ ++static uint32_t next_uid(dwc_cc_if_t *cc_if) ++{ ++ uint32_t uid = 0; ++ dwc_cc_t *cc; ++ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ if (cc->uid > uid) { ++ uid = cc->uid; ++ } ++ } ++ ++ if (uid == 0) { ++ uid = 255; ++ } ++ ++ return uid + 1; ++} ++ ++static dwc_cc_t *cc_find(dwc_cc_if_t *cc_if, uint32_t uid) ++{ ++ dwc_cc_t *cc; ++ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ if (cc->uid == uid) { ++ return cc; ++ } ++ } ++ return NULL; ++} ++ ++static unsigned int cc_data_size(dwc_cc_if_t *cc_if) ++{ ++ unsigned int size = 0; ++ dwc_cc_t *cc; ++ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ size += (48 + 1); ++ if (cc->name) { ++ size += cc->length; ++ } ++ } ++ return size; ++} ++ ++static uint32_t cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid) ++{ ++ uint32_t uid = 0; ++ dwc_cc_t *cc; ++ ++ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ if (DWC_MEMCMP(cc->chid, chid, 16) == 0) { ++ uid = cc->uid; ++ break; ++ } ++ } ++ return uid; ++} ++static uint32_t cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid) ++{ ++ uint32_t uid = 0; ++ dwc_cc_t *cc; ++ ++ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ if (DWC_MEMCMP(cc->cdid, cdid, 16) == 0) { ++ uid = cc->uid; ++ break; ++ } ++ } ++ return uid; ++} ++ ++/* Internal cc_add */ ++static int32_t cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) ++{ ++ dwc_cc_t *cc; ++ uint32_t uid; ++ ++ if (cc_if->is_host) { ++ uid = cc_match_cdid(cc_if, cdid); ++ } ++ else { ++ uid = cc_match_chid(cc_if, chid); ++ } ++ ++ if (uid) { ++ DWC_DEBUG("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length); ++ cc = cc_find(cc_if, uid); ++ } ++ else { ++ cc = alloc_cc(mem_ctx, name, length); ++ cc->uid = next_uid(cc_if); ++ DWC_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry); ++ } ++ ++ DWC_MEMCPY(&(cc->chid[0]), chid, 16); ++ DWC_MEMCPY(&(cc->cdid[0]), cdid, 16); ++ DWC_MEMCPY(&(cc->ck[0]), ck, 16); ++ ++ DWC_DEBUG("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length); ++ dump_bytes("CHID", cc->chid, 16); ++ dump_bytes("CDID", cc->cdid, 16); ++ dump_bytes("CK", cc->ck, 16); ++ return cc->uid; ++} ++ ++/* Internal cc_clear */ ++static void cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if) ++{ ++ while (!DWC_CIRCLEQ_EMPTY(&cc_if->list)) { ++ dwc_cc_t *cc = DWC_CIRCLEQ_FIRST(&cc_if->list); ++ DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry); ++ free_cc(mem_ctx, cc); ++ } ++} ++ ++dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx, ++ dwc_notifier_t *notifier, unsigned is_host) ++{ ++ dwc_cc_if_t *cc_if = NULL; ++ ++ /* Allocate a common_cc_if structure */ ++ cc_if = dwc_alloc(mem_ctx, sizeof(dwc_cc_if_t)); ++ ++ if (!cc_if) ++ return NULL; ++ ++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++ DWC_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex); ++#else ++ cc_if->mutex = dwc_mutex_alloc(mtx_ctx); ++#endif ++ if (!cc_if->mutex) { ++ dwc_free(mem_ctx, cc_if); ++ return NULL; ++ } ++ ++ DWC_CIRCLEQ_INIT(&cc_if->list); ++ cc_if->is_host = is_host; ++ cc_if->notifier = notifier; ++ return cc_if; ++} ++ ++void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if) ++{ ++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++ DWC_MUTEX_FREE(cc_if->mutex); ++#else ++ dwc_mutex_free(mtx_ctx, cc_if->mutex); ++#endif ++ cc_clear(mem_ctx, cc_if); ++ dwc_free(mem_ctx, cc_if); ++} ++ ++static void cc_changed(dwc_cc_if_t *cc_if) ++{ ++ if (cc_if->notifier) { ++ dwc_notify(cc_if->notifier, DWC_CC_LIST_CHANGED_NOTIFICATION, cc_if); ++ } ++} ++ ++void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if) ++{ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc_clear(mem_ctx, cc_if); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ cc_changed(cc_if); ++} ++ ++int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) ++{ ++ uint32_t uid; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ uid = cc_add(mem_ctx, cc_if, chid, cdid, ck, name, length); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ cc_changed(cc_if); ++ ++ return uid; ++} ++ ++void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) ++{ ++ dwc_cc_t* cc; ++ ++ DWC_DEBUG("Change connection context %d", id); ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (!cc) { ++ DWC_ERROR("Uid %d not found in cc list\n", id); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return; ++ } ++ ++ if (chid) { ++ DWC_MEMCPY(&(cc->chid[0]), chid, 16); ++ } ++ if (cdid) { ++ DWC_MEMCPY(&(cc->cdid[0]), cdid, 16); ++ } ++ if (ck) { ++ DWC_MEMCPY(&(cc->ck[0]), ck, 16); ++ } ++ ++ if (name) { ++ if (cc->name) { ++ dwc_free(mem_ctx, cc->name); ++ } ++ cc->name = dwc_alloc(mem_ctx, length); ++ if (!cc->name) { ++ DWC_ERROR("Out of memory in dwc_cc_change()\n"); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return; ++ } ++ cc->length = length; ++ DWC_MEMCPY(cc->name, name, length); ++ } ++ ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ cc_changed(cc_if); ++ ++ DWC_DEBUG("Changed connection context id=%d\n", id); ++ dump_bytes("New CHID", cc->chid, 16); ++ dump_bytes("New CDID", cc->cdid, 16); ++ dump_bytes("New CK", cc->ck, 16); ++} ++ ++void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id) ++{ ++ dwc_cc_t *cc; ++ ++ DWC_DEBUG("Removing connection context %d", id); ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (!cc) { ++ DWC_ERROR("Uid %d not found in cc list\n", id); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return; ++ } ++ ++ DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ free_cc(mem_ctx, cc); ++ ++ cc_changed(cc_if); ++} ++ ++uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, unsigned int *length) ++{ ++ uint8_t *buf, *x; ++ uint8_t zero = 0; ++ dwc_cc_t *cc; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ *length = cc_data_size(cc_if); ++ if (!(*length)) { ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return NULL; ++ } ++ ++ DWC_DEBUG("Creating data for saving (length=%d)", *length); ++ ++ buf = dwc_alloc(mem_ctx, *length); ++ if (!buf) { ++ *length = 0; ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return NULL; ++ } ++ ++ x = buf; ++ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ DWC_MEMCPY(x, cc->chid, 16); ++ x += 16; ++ DWC_MEMCPY(x, cc->cdid, 16); ++ x += 16; ++ DWC_MEMCPY(x, cc->ck, 16); ++ x += 16; ++ if (cc->name) { ++ DWC_MEMCPY(x, &cc->length, 1); ++ x += 1; ++ DWC_MEMCPY(x, cc->name, cc->length); ++ x += cc->length; ++ } ++ else { ++ DWC_MEMCPY(x, &zero, 1); ++ x += 1; ++ } ++ } ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return buf; ++} ++ ++void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length) ++{ ++ uint8_t name_length; ++ uint8_t *name; ++ uint8_t *chid; ++ uint8_t *cdid; ++ uint8_t *ck; ++ uint32_t i = 0; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc_clear(mem_ctx, cc_if); ++ ++ while (i < length) { ++ chid = &data[i]; ++ i += 16; ++ cdid = &data[i]; ++ i += 16; ++ ck = &data[i]; ++ i += 16; ++ ++ name_length = data[i]; ++ i ++; ++ ++ if (name_length) { ++ name = &data[i]; ++ i += name_length; ++ } ++ else { ++ name = NULL; ++ } ++ ++ /* check to see if we haven't overflown the buffer */ ++ if (i > length) { ++ DWC_ERROR("Data format error while attempting to load CCs " ++ "(nlen=%d, iter=%d, buflen=%d).\n", name_length, i, length); ++ break; ++ } ++ ++ cc_add(mem_ctx, cc_if, chid, cdid, ck, name, name_length); ++ } ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ cc_changed(cc_if); ++} ++ ++uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid) ++{ ++ uint32_t uid = 0; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ uid = cc_match_chid(cc_if, chid); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return uid; ++} ++uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid) ++{ ++ uint32_t uid = 0; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ uid = cc_match_cdid(cc_if, cdid); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return uid; ++} ++ ++uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id) ++{ ++ uint8_t *ck = NULL; ++ dwc_cc_t *cc; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (cc) { ++ ck = cc->ck; ++ } ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return ck; ++ ++} ++ ++uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id) ++{ ++ uint8_t *retval = NULL; ++ dwc_cc_t *cc; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (cc) { ++ retval = cc->chid; ++ } ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return retval; ++} ++ ++uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id) ++{ ++ uint8_t *retval = NULL; ++ dwc_cc_t *cc; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (cc) { ++ retval = cc->cdid; ++ } ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return retval; ++} ++ ++uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length) ++{ ++ uint8_t *retval = NULL; ++ dwc_cc_t *cc; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ *length = 0; ++ cc = cc_find(cc_if, id); ++ if (cc) { ++ *length = cc->length; ++ retval = cc->name; ++ } ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return retval; ++} ++ ++#endif /* DWC_CCLIB */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_cc.h b/drivers/usb/gadget/udc/hiudc/dwc_cc.h +new file mode 100644 +index 0000000..f86e6f2 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_cc.h +@@ -0,0 +1,224 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.h $ ++ * $Revision: #4 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS 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 _DWC_CC_H_ ++#define _DWC_CC_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ * ++ * This file defines the Context Context library. ++ * ++ * The main data structure is dwc_cc_if_t which is returned by either the ++ * dwc_cc_if_alloc function or returned by the module to the user via a provided ++ * function. The data structure is opaque and should only be manipulated via the ++ * functions provied in this API. ++ * ++ * It manages a list of connection contexts and operations can be performed to ++ * add, remove, query, search, and change, those contexts. Additionally, ++ * a dwc_notifier_t object can be requested from the manager so that ++ * the user can be notified whenever the context list has changed. ++ */ ++ ++#include "dwc_os.h" ++#include "dwc_list.h" ++#include "dwc_notifier.h" ++ ++ ++/* Notifications */ ++#define DWC_CC_LIST_CHANGED_NOTIFICATION "DWC_CC_LIST_CHANGED_NOTIFICATION" ++ ++struct dwc_cc_if; ++typedef struct dwc_cc_if dwc_cc_if_t; ++ ++ ++/** @name Connection Context Operations */ ++/** @{ */ ++ ++/** This function allocates memory for a dwc_cc_if_t structure, initializes ++ * fields to default values, and returns a pointer to the structure or NULL on ++ * error. */ ++extern dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx, ++ dwc_notifier_t *notifier, unsigned is_host); ++ ++/** Frees the memory for the specified CC structure allocated from ++ * dwc_cc_if_alloc(). */ ++extern void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if); ++ ++/** Removes all contexts from the connection context list */ ++extern void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if); ++ ++/** Adds a connection context (CHID, CK, CDID, Name) to the connection context list. ++ * If a CHID already exists, the CK and name are overwritten. Statistics are ++ * not overwritten. ++ * ++ * @param cc_if The cc_if structure. ++ * @param chid A pointer to the 16-byte CHID. This value will be copied. ++ * @param ck A pointer to the 16-byte CK. This value will be copied. ++ * @param cdid A pointer to the 16-byte CDID. This value will be copied. ++ * @param name An optional host friendly name as defined in the association model ++ * spec. Must be a UTF16-LE unicode string. Can be NULL to indicated no name. ++ * @param length The length othe unicode string. ++ * @return A unique identifier used to refer to this context that is valid for ++ * as long as this context is still in the list. */ ++extern int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, ++ uint8_t length); ++ ++/** Changes the CHID, CK, CDID, or Name values of a connection context in the ++ * list, preserving any accumulated statistics. This would typically be called ++ * if the host decideds to change the context with a SET_CONNECTION request. ++ * ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context. ++ * @param chid A pointer to the 16-byte CHID. This value will be copied. NULL ++ * indicates no change. ++ * @param cdid A pointer to the 16-byte CDID. This value will be copied. NULL ++ * indicates no change. ++ * @param ck A pointer to the 16-byte CK. This value will be copied. NULL ++ * indicates no change. ++ * @param name Host friendly name UTF16-LE. NULL indicates no change. ++ * @param length Length of name. */ ++extern void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, ++ uint8_t *chid, uint8_t *cdid, uint8_t *ck, ++ uint8_t *name, uint8_t length); ++ ++/** Remove the specified connection context. ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context to remove. */ ++extern void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id); ++ ++/** Get a binary block of data for the connection context list and attributes. ++ * This data can be used by the OS specific driver to save the connection ++ * context list into non-volatile memory. ++ * ++ * @param cc_if The cc_if structure. ++ * @param length Return the length of the data buffer. ++ * @return A pointer to the data buffer. The memory for this buffer should be ++ * freed with DWC_FREE() after use. */ ++extern uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, ++ unsigned int *length); ++ ++/** Restore the connection context list from the binary data that was previously ++ * returned from a call to dwc_cc_data_for_save. This can be used by the OS specific ++ * driver to load a connection context list from non-volatile memory. ++ * ++ * @param cc_if The cc_if structure. ++ * @param data The data bytes as returned from dwc_cc_data_for_save. ++ * @param length The length of the data. */ ++extern void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, ++ uint8_t *data, unsigned int length); ++ ++/** Find the connection context from the specified CHID. ++ * ++ * @param cc_if The cc_if structure. ++ * @param chid A pointer to the CHID data. ++ * @return A non-zero identifier of the connection context if the CHID matches. ++ * Otherwise returns 0. */ ++extern uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid); ++ ++/** Find the connection context from the specified CDID. ++ * ++ * @param cc_if The cc_if structure. ++ * @param cdid A pointer to the CDID data. ++ * @return A non-zero identifier of the connection context if the CHID matches. ++ * Otherwise returns 0. */ ++extern uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid); ++ ++/** Retrieve the CK from the specified connection context. ++ * ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context. ++ * @return A pointer to the CK data. The memory does not need to be freed. */ ++extern uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id); ++ ++/** Retrieve the CHID from the specified connection context. ++ * ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context. ++ * @return A pointer to the CHID data. The memory does not need to be freed. */ ++extern uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id); ++ ++/** Retrieve the CDID from the specified connection context. ++ * ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context. ++ * @return A pointer to the CDID data. The memory does not need to be freed. */ ++extern uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id); ++ ++extern uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length); ++ ++/** Checks a buffer for non-zero. ++ * @param id A pointer to a 16 byte buffer. ++ * @return true if the 16 byte value is non-zero. */ ++static inline unsigned dwc_assoc_is_not_zero_id(uint8_t *id) { ++ int i; ++ for (i=0; i<16; i++) { ++ if (id[i]) return 1; ++ } ++ return 0; ++} ++ ++/** Checks a buffer for zero. ++ * @param id A pointer to a 16 byte buffer. ++ * @return true if the 16 byte value is zero. */ ++static inline unsigned dwc_assoc_is_zero_id(uint8_t *id) { ++ return !dwc_assoc_is_not_zero_id(id); ++} ++ ++/** Prints an ASCII representation for the 16-byte chid, cdid, or ck, into ++ * buffer. */ ++static inline int dwc_print_id_string(char *buffer, uint8_t *id) { ++ char *ptr = buffer; ++ int i; ++ for (i=0; i<16; i++) { ++ ptr += DWC_SPRINTF(ptr, "%02x", id[i]); ++ if (i < 15) { ++ ptr += DWC_SPRINTF(ptr, " "); ++ } ++ } ++ return ptr - buffer; ++} ++ ++/** @} */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_CC_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_common_linux.c b/drivers/usb/gadget/udc/hiudc/dwc_common_linux.c +new file mode 100644 +index 0000000..426a2ca +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_common_linux.c +@@ -0,0 +1,1307 @@ ++#include ++#include ++#include ++#include ++ ++#ifdef DWC_CCLIB ++# include "dwc_cc.h" ++#endif ++ ++#ifdef DWC_CRYPTOLIB ++# include "dwc_modpow.h" ++# include "dwc_dh.h" ++# include "dwc_crypto.h" ++#endif ++ ++#ifdef DWC_NOTIFYLIB ++# include "dwc_notifier.h" ++#endif ++ ++/* OS-Level Implementations */ ++ ++/* This is the Linux kernel implementation of the DWC platform library. */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) ++# include ++#else ++# include ++#endif ++ ++#include ++#include ++#include ++#include ++ ++#include "dwc_os.h" ++#include "dwc_list.h" ++ ++ ++/* MISC */ ++ ++void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size) ++{ ++ return memset(dest, byte, size); ++} ++ ++void *DWC_MEMCPY(void *dest, void const *src, uint32_t size) ++{ ++ return memcpy(dest, src, size); ++} ++ ++void *DWC_MEMMOVE(void *dest, void *src, uint32_t size) ++{ ++ return memmove(dest, src, size); ++} ++ ++int DWC_MEMCMP(void *m1, void *m2, uint32_t size) ++{ ++ return memcmp(m1, m2, size); ++} ++ ++int DWC_STRNCMP(void *s1, void *s2, uint32_t size) ++{ ++ return strncmp(s1, s2, size); ++} ++ ++int DWC_STRCMP(void *s1, void *s2) ++{ ++ return strcmp(s1, s2); ++} ++ ++int DWC_STRLEN(char const *str) ++{ ++ return strlen(str); ++} ++ ++char *DWC_STRCPY(char *to, char const *from) ++{ ++ return strcpy(to, from); ++} ++ ++char *DWC_STRDUP(char const *str) ++{ ++ int len = DWC_STRLEN(str) + 1; ++ char *new = DWC_ALLOC_ATOMIC(len); ++ ++ if (!new) { ++ return NULL; ++ } ++ ++ DWC_MEMCPY(new, str, len); ++ return new; ++} ++ ++int DWC_ATOI(const char *str, int32_t *value) ++{ ++ char *end = NULL; ++ ++ *value = simple_strtol(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++int DWC_ATOUI(const char *str, uint32_t *value) ++{ ++ char *end = NULL; ++ ++ *value = simple_strtoul(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++ ++#ifdef DWC_UTFLIB ++/* From usbstring.c */ ++ ++int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len) ++{ ++ int count = 0; ++ u8 c; ++ u16 uchar; ++ ++ /* this insists on correct encodings, though not minimal ones. ++ * BUT it currently rejects legit 4-byte UTF-8 code points, ++ * which need surrogate pairs. (Unicode 3.1 can use them.) ++ */ ++ while (len != 0 && (c = (u8) *s++) != 0) { ++ if (unlikely(c & 0x80)) { ++ // 2-byte sequence: ++ // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx ++ if ((c & 0xe0) == 0xc0) { ++ uchar = (c & 0x1f) << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ // 3-byte sequence (most CJKV characters): ++ // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx ++ } else if ((c & 0xf0) == 0xe0) { ++ uchar = (c & 0x0f) << 12; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ /* no bogus surrogates */ ++ if (0xd800 <= uchar && uchar <= 0xdfff) ++ goto fail; ++ ++ // 4-byte sequence (surrogate pairs, currently rare): ++ // 11101110wwwwzzzzyy + 110111yyyyxxxxxx ++ // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx ++ // (uuuuu = wwww + 1) ++ // FIXME accept the surrogate code points (only) ++ } else ++ goto fail; ++ } else ++ uchar = c; ++ put_unaligned (cpu_to_le16 (uchar), cp++); ++ count++; ++ len--; ++ } ++ return count; ++fail: ++ return -1; ++} ++#endif /* DWC_UTFLIB */ ++ ++ ++/* dwc_debug.h */ ++ ++dwc_bool_t DWC_IN_IRQ(void) ++{ ++ return in_irq(); ++} ++ ++dwc_bool_t DWC_IN_BH(void) ++{ ++ return in_softirq(); ++} ++ ++void DWC_VPRINTF(char *format, va_list args) ++{ ++ vprintk(format, args); ++} ++ ++int DWC_VSNPRINTF(char *str, int size, char *format, va_list args) ++{ ++ return vsnprintf(str, size, format, args); ++} ++ ++void DWC_PRINTF(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++int DWC_SPRINTF(char *buffer, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsprintf(buffer, format, args); ++ va_end(args); ++ return retval; ++} ++ ++int DWC_SNPRINTF(char *buffer, int size, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsnprintf(buffer, size, format, args); ++ va_end(args); ++ return retval; ++} ++ ++void __DWC_WARN(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_PRINTF(KERN_WARNING); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void __DWC_ERROR(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_PRINTF(KERN_ERR); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void DWC_EXCEPTION(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_PRINTF(KERN_ERR); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++ BUG_ON(1); ++} ++ ++#ifdef DEBUG ++void __DWC_DEBUG(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_PRINTF(KERN_DEBUG); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++#endif ++ ++void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) ++{ ++#ifdef xxCOSIM /* Only works for 32-bit cosim */ ++ void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL); ++#else ++// void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL | GFP_DMA32); ++ void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC); ++#endif ++ if (!buf) { ++ return NULL; ++ } ++ ++ memset(buf, 0, (size_t)size); ++ return buf; ++} ++ ++void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) ++{ ++ void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC); ++ if (!buf) { ++ return NULL; ++ } ++ memset(buf, 0, (size_t)size); ++ return buf; ++} ++ ++void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr) ++{ ++ dma_free_coherent(dma_ctx, size, virt_addr, dma_addr); ++} ++ ++void *__DWC_ALLOC(void *mem_ctx, uint32_t size) ++{ ++ return kzalloc(size, GFP_KERNEL); ++} ++ ++void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size) ++{ ++ return kzalloc(size, GFP_ATOMIC); ++} ++ ++void __DWC_FREE(void *mem_ctx, void *addr) ++{ ++ kfree(addr); ++} ++ ++ ++#ifdef DWC_CRYPTOLIB ++/* dwc_crypto.h */ ++ ++void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length) ++{ ++ get_random_bytes(buffer, length); ++} ++ ++int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out) ++{ ++ struct crypto_blkcipher *tfm; ++ struct blkcipher_desc desc; ++ struct scatterlist sgd; ++ struct scatterlist sgs; ++ ++ tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); ++ if (tfm == NULL) { ++ printk("failed to load transform for aes CBC\n"); ++ return -1; ++ } ++ ++ crypto_blkcipher_setkey(tfm, key, keylen); ++ crypto_blkcipher_set_iv(tfm, iv, 16); ++ ++ sg_init_one(&sgd, out, messagelen); ++ sg_init_one(&sgs, message, messagelen); ++ ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) { ++ crypto_free_blkcipher(tfm); ++ DWC_ERROR("AES CBC encryption failed"); ++ return -1; ++ } ++ ++ crypto_free_blkcipher(tfm); ++ return 0; ++} ++ ++int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ DWC_ERROR("Failed to load transform for sha256: %ld\n", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, len); ++ crypto_hash_digest(&desc, &sg, len, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++ ++int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, ++ uint8_t *key, uint32_t keylen, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ DWC_ERROR("Failed to load transform for hmac(sha256): %ld\n", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, messagelen); ++ crypto_hash_setkey(tfm, key, keylen); ++ crypto_hash_digest(&desc, &sg, messagelen, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++#endif /* DWC_CRYPTOLIB */ ++ ++ ++/* Byte Ordering Conversions */ ++ ++uint32_t DWC_CPU_TO_LE32(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_CPU_TO_BE32(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_LE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_BE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint16_t DWC_CPU_TO_LE16(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_CPU_TO_BE16(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_LE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_BE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++ ++/* Registers */ ++ ++uint32_t DWC_READ_REG32(uint32_t volatile *reg) ++{ ++ return readl(reg); ++} ++ ++void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value) ++{ ++ writel(value, reg); ++} ++ ++void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask) ++{ ++ writel((readl(reg) & ~clear_mask) | set_mask, reg); ++} ++ ++/* Locking */ ++ ++dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void) ++{ ++ spinlock_t *sl = (spinlock_t *)1; ++ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ sl = DWC_ALLOC(sizeof(*sl)); ++ if (!sl) { ++ DWC_ERROR("Cannot allocate memory for spinlock\n"); ++ return NULL; ++ } ++ ++ spin_lock_init(sl); ++#endif ++ return (dwc_spinlock_t *)sl; ++} ++ ++void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock) ++{ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ DWC_FREE(lock); ++#endif ++} ++ ++void DWC_SPINLOCK(dwc_spinlock_t *lock) ++{ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ spin_lock((spinlock_t *)lock); ++#endif ++} ++ ++void DWC_SPINUNLOCK(dwc_spinlock_t *lock) ++{ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ spin_unlock((spinlock_t *)lock); ++#endif ++} ++ ++void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags) ++{ ++ dwc_irqflags_t f; ++ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ spin_lock_irqsave((spinlock_t *)lock, f); ++#else ++ local_irq_save(f); ++#endif ++ *flags = f; ++} ++ ++void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags) ++{ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ spin_unlock_irqrestore((spinlock_t *)lock, flags); ++#else ++ local_irq_restore(flags); ++#endif ++} ++ ++dwc_mutex_t *DWC_MUTEX_ALLOC(void) ++{ ++ struct mutex *m; ++ dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); ++ ++ if (!mutex) { ++ DWC_ERROR("Cannot allocate memory for mutex\n"); ++ return NULL; ++ } ++ ++ m = (struct mutex *)mutex; ++ mutex_init(m); ++ return mutex; ++} ++ ++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++#else ++void DWC_MUTEX_FREE(dwc_mutex_t *mutex) ++{ ++ mutex_destroy((struct mutex *)mutex); ++ DWC_FREE(mutex); ++} ++#endif ++ ++void DWC_MUTEX_LOCK(dwc_mutex_t *mutex) ++{ ++ struct mutex *m = (struct mutex *)mutex; ++ mutex_lock(m); ++} ++ ++int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex) ++{ ++ struct mutex *m = (struct mutex *)mutex; ++ return mutex_trylock(m); ++} ++ ++void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex) ++{ ++ struct mutex *m = (struct mutex *)mutex; ++ mutex_unlock(m); ++} ++ ++ ++/* Timing */ ++ ++void DWC_UDELAY(uint32_t usecs) ++{ ++ udelay(usecs); ++} ++ ++void DWC_MDELAY(uint32_t msecs) ++{ ++ if (in_interrupt()) ++ mdelay(msecs); ++ else ++ msleep(msecs); ++} ++ ++void DWC_MSLEEP(uint32_t msecs) ++{ ++ msleep(msecs); ++} ++ ++uint32_t DWC_TIME(void) ++{ ++ return jiffies_to_msecs(jiffies); ++} ++ ++ ++/* Timers */ ++ ++struct dwc_timer { ++ struct timer_list *t; ++ char *name; ++ dwc_timer_callback_t cb; ++ void *data; ++ uint8_t scheduled; ++ dwc_spinlock_t *lock; ++}; ++ ++void DWC_TIMER_FREE(dwc_timer_t *timer) ++{ ++ dwc_irqflags_t flags; ++ ++ DWC_SPINLOCK_IRQSAVE(timer->lock, &flags); ++ ++ if (timer->scheduled) { ++ del_timer(timer->t); ++ timer->scheduled = 0; ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags); ++ DWC_SPINLOCK_FREE(timer->lock); ++ DWC_FREE(timer->t); ++ DWC_FREE(timer->name); ++ DWC_FREE(timer); ++} ++ ++void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time) ++{ ++ dwc_irqflags_t flags; ++ ++ DWC_SPINLOCK_IRQSAVE(timer->lock, &flags); ++ ++ if (!timer->scheduled) { ++ timer->scheduled = 1; ++ DWC_DEBUG("Scheduling timer %s to expire in +%d msec", timer->name, time); ++ timer->t->expires = jiffies + msecs_to_jiffies(time); ++ add_timer(timer->t); ++ } else { ++ DWC_DEBUG("Modifying timer %s to expire in +%d msec", timer->name, time); ++ mod_timer(timer->t, jiffies + msecs_to_jiffies(time)); ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags); ++} ++ ++void DWC_TIMER_CANCEL(dwc_timer_t *timer) ++{ ++ del_timer(timer->t); ++} ++ ++ ++/* Wait Queues */ ++ ++struct dwc_waitq { ++ wait_queue_head_t queue; ++ int abort; ++}; ++ ++dwc_waitq_t *DWC_WAITQ_ALLOC(void) ++{ ++ dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ DWC_ERROR("Cannot allocate memory for waitqueue\n"); ++ return NULL; ++ } ++ ++ init_waitqueue_head(&wq->queue); ++ wq->abort = 0; ++ return wq; ++} ++ ++void DWC_WAITQ_FREE(dwc_waitq_t *wq) ++{ ++ DWC_FREE(wq); ++} ++ ++int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data) ++{ ++ int result = wait_event_interruptible(wq->queue, ++ cond(data) || wq->abort); ++ if (result == -ERESTARTSYS) { ++ wq->abort = 0; ++ return -DWC_E_RESTART; ++ } ++ ++ if (wq->abort == 1) { ++ wq->abort = 0; ++ return -DWC_E_ABORT; ++ } ++ ++ wq->abort = 0; ++ ++ if (result == 0) { ++ return 0; ++ } ++ ++ return -DWC_E_UNKNOWN; ++} ++ ++int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, ++ void *data, int32_t msecs) ++{ ++ int32_t tmsecs; ++ int result = wait_event_interruptible_timeout(wq->queue, ++ cond(data) || wq->abort, ++ msecs_to_jiffies(msecs)); ++ if (result == -ERESTARTSYS) { ++ wq->abort = 0; ++ return -DWC_E_RESTART; ++ } ++ ++ if (wq->abort == 1) { ++ wq->abort = 0; ++ return -DWC_E_ABORT; ++ } ++ ++ wq->abort = 0; ++ ++ if (result > 0) { ++ tmsecs = jiffies_to_msecs(result); ++ if (!tmsecs) { ++ return 1; ++ } ++ ++ return tmsecs; ++ } ++ ++ if (result == 0) { ++ return -DWC_E_TIMEOUT; ++ } ++ ++ return -DWC_E_UNKNOWN; ++} ++ ++void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq) ++{ ++ wq->abort = 0; ++ wake_up_interruptible(&wq->queue); ++} ++ ++void DWC_WAITQ_ABORT(dwc_waitq_t *wq) ++{ ++ wq->abort = 1; ++ wake_up_interruptible(&wq->queue); ++} ++ ++ ++/* Threading */ ++ ++dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data) ++{ ++ struct task_struct *thread = kthread_run(func, data, name); ++ ++ if (thread == ERR_PTR(-ENOMEM)) { ++ return NULL; ++ } ++ ++ return (dwc_thread_t *)thread; ++} ++ ++int DWC_THREAD_STOP(dwc_thread_t *thread) ++{ ++ return kthread_stop((struct task_struct *)thread); ++} ++ ++dwc_bool_t DWC_THREAD_SHOULD_STOP(void) ++{ ++ return kthread_should_stop(); ++} ++ ++ ++/* tasklets ++ - run in interrupt context (cannot sleep) ++ - each tasklet runs on a single CPU ++ - different tasklets can be running simultaneously on different CPUs ++ */ ++struct dwc_tasklet { ++ struct tasklet_struct t; ++ dwc_tasklet_callback_t cb; ++ void *data; ++}; ++ ++static void tasklet_callback(unsigned long data) ++{ ++ dwc_tasklet_t *t = (dwc_tasklet_t *)data; ++ t->cb(t->data); ++} ++ ++dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data) ++{ ++ dwc_tasklet_t *t = DWC_ALLOC(sizeof(*t)); ++ ++ if (t) { ++ t->cb = cb; ++ t->data = data; ++ tasklet_init(&t->t, tasklet_callback, (unsigned long)t); ++ } else { ++ DWC_ERROR("Cannot allocate memory for tasklet\n"); ++ } ++ ++ return t; ++} ++ ++void DWC_TASK_FREE(dwc_tasklet_t *task) ++{ ++ DWC_FREE(task); ++} ++ ++void DWC_TASK_SCHEDULE(dwc_tasklet_t *task) ++{ ++ tasklet_schedule(&task->t); ++} ++ ++ ++/* workqueues ++ - run in process context (can sleep) ++ */ ++typedef struct work_container { ++ dwc_work_callback_t cb; ++ void *data; ++ dwc_workq_t *wq; ++ char *name; ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_ENTRY(work_container) entry; ++#endif ++ struct delayed_work work; ++} work_container_t; ++ ++#ifdef DEBUG ++DWC_CIRCLEQ_HEAD(work_container_queue, work_container); ++#endif ++ ++struct dwc_workq { ++ struct workqueue_struct *wq; ++ dwc_spinlock_t *lock; ++ dwc_waitq_t *waitq; ++ int pending; ++ ++#ifdef DEBUG ++ struct work_container_queue entries; ++#endif ++}; ++ ++static void do_work(struct work_struct *work) ++{ ++ dwc_irqflags_t flags; ++ struct delayed_work *dw = container_of(work, struct delayed_work, work); ++ work_container_t *container = container_of(dw, struct work_container, work); ++ dwc_workq_t *wq = container->wq; ++ ++ container->cb(container->data); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry); ++#endif ++ DWC_DEBUG("Work done: %s, container=%p", container->name, container); ++ if (container->name) { ++ DWC_FREE(container->name); ++ } ++ DWC_FREE(container); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending--; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++} ++ ++static int work_done(void *data) ++{ ++ dwc_workq_t *workq = (dwc_workq_t *)data; ++ return workq->pending == 0; ++} ++ ++int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout) ++{ ++ return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout); ++} ++ ++dwc_workq_t *DWC_WORKQ_ALLOC(char *name) ++{ ++ dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ return NULL; ++ } ++ ++ wq->wq = create_singlethread_workqueue(name); ++ if (!wq->wq) { ++ goto no_wq; ++ } ++ ++ wq->pending = 0; ++ ++ wq->lock = DWC_SPINLOCK_ALLOC(); ++ if (!wq->lock) { ++ goto no_lock; ++ } ++ ++ wq->waitq = DWC_WAITQ_ALLOC(); ++ if (!wq->waitq) { ++ goto no_waitq; ++ } ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_INIT(&wq->entries); ++#endif ++ return wq; ++ ++ no_waitq: ++ DWC_SPINLOCK_FREE(wq->lock); ++ no_lock: ++ destroy_workqueue(wq->wq); ++ no_wq: ++ DWC_FREE(wq); ++ ++ return NULL; ++} ++ ++void DWC_WORKQ_FREE(dwc_workq_t *wq) ++{ ++#ifdef DEBUG ++ if (wq->pending != 0) { ++ struct work_container *wc; ++ DWC_ERROR("Destroying work queue with pending work"); ++ DWC_CIRCLEQ_FOREACH(wc, &wq->entries, entry) { ++ DWC_ERROR("Work %s still pending", wc->name); ++ } ++ } ++#endif ++ destroy_workqueue(wq->wq); ++ DWC_SPINLOCK_FREE(wq->lock); ++ DWC_WAITQ_FREE(wq->waitq); ++ DWC_FREE(wq); ++} ++ ++void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data, ++ char *format, ...) ++{ ++ dwc_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++ ++ container = DWC_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ DWC_ERROR("Cannot allocate memory for container\n"); ++ return; ++ } ++ ++ container->name = DWC_STRDUP(name); ++ if (!container->name) { ++ DWC_ERROR("Cannot allocate memory for container->name\n"); ++ DWC_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ DWC_DEBUG("Queueing work: %s, container=%p", container->name, container); ++ INIT_WORK(&container->work.work, do_work); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); ++#endif ++ queue_work(wq->wq, &container->work.work); ++} ++ ++void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb, ++ void *data, uint32_t time, char *format, ...) ++{ ++ dwc_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++ ++ container = DWC_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ DWC_ERROR("Cannot allocate memory for container\n"); ++ return; ++ } ++ ++ container->name = DWC_STRDUP(name); ++ if (!container->name) { ++ DWC_ERROR("Cannot allocate memory for container->name\n"); ++ DWC_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ DWC_DEBUG("Queueing work: %s, container=%p", container->name, container); ++ INIT_DELAYED_WORK(&container->work, do_work); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); ++#endif ++ queue_delayed_work(wq->wq, &container->work, msecs_to_jiffies(time)); ++} ++ ++int DWC_WORKQ_PENDING(dwc_workq_t *wq) ++{ ++ return wq->pending; ++} ++ ++ ++#ifdef DWC_LIBMODULE ++ ++#ifdef DWC_CCLIB ++/* CC */ ++EXPORT_SYMBOL(dwc_cc_if_alloc); ++EXPORT_SYMBOL(dwc_cc_if_free); ++EXPORT_SYMBOL(dwc_cc_clear); ++EXPORT_SYMBOL(dwc_cc_add); ++EXPORT_SYMBOL(dwc_cc_remove); ++EXPORT_SYMBOL(dwc_cc_change); ++EXPORT_SYMBOL(dwc_cc_data_for_save); ++EXPORT_SYMBOL(dwc_cc_restore_from_data); ++EXPORT_SYMBOL(dwc_cc_match_chid); ++EXPORT_SYMBOL(dwc_cc_match_cdid); ++EXPORT_SYMBOL(dwc_cc_ck); ++EXPORT_SYMBOL(dwc_cc_chid); ++EXPORT_SYMBOL(dwc_cc_cdid); ++EXPORT_SYMBOL(dwc_cc_name); ++#endif /* DWC_CCLIB */ ++ ++#ifdef DWC_CRYPTOLIB ++# ifndef CONFIG_MACH_IPMATE ++/* Modpow */ ++EXPORT_SYMBOL(dwc_modpow); ++ ++/* DH */ ++EXPORT_SYMBOL(dwc_dh_modpow); ++EXPORT_SYMBOL(dwc_dh_derive_keys); ++EXPORT_SYMBOL(dwc_dh_pk); ++# endif /* CONFIG_MACH_IPMATE */ ++ ++/* Crypto */ ++EXPORT_SYMBOL(dwc_wusb_aes_encrypt); ++EXPORT_SYMBOL(dwc_wusb_cmf); ++EXPORT_SYMBOL(dwc_wusb_prf); ++EXPORT_SYMBOL(dwc_wusb_fill_ccm_nonce); ++EXPORT_SYMBOL(dwc_wusb_gen_nonce); ++EXPORT_SYMBOL(dwc_wusb_gen_key); ++EXPORT_SYMBOL(dwc_wusb_gen_mic); ++#endif /* DWC_CRYPTOLIB */ ++ ++/* Notification */ ++#ifdef DWC_NOTIFYLIB ++EXPORT_SYMBOL(dwc_alloc_notification_manager); ++EXPORT_SYMBOL(dwc_free_notification_manager); ++EXPORT_SYMBOL(dwc_register_notifier); ++EXPORT_SYMBOL(dwc_unregister_notifier); ++EXPORT_SYMBOL(dwc_add_observer); ++EXPORT_SYMBOL(dwc_remove_observer); ++EXPORT_SYMBOL(dwc_notify); ++#endif ++ ++/* Memory Debugging Routines */ ++#ifdef DWC_DEBUG_MEMORY ++EXPORT_SYMBOL(dwc_alloc_debug); ++EXPORT_SYMBOL(dwc_alloc_atomic_debug); ++EXPORT_SYMBOL(dwc_free_debug); ++EXPORT_SYMBOL(dwc_dma_alloc_debug); ++EXPORT_SYMBOL(dwc_dma_free_debug); ++#endif ++ ++EXPORT_SYMBOL(DWC_MEMSET); ++EXPORT_SYMBOL(DWC_MEMCPY); ++EXPORT_SYMBOL(DWC_MEMMOVE); ++EXPORT_SYMBOL(DWC_MEMCMP); ++EXPORT_SYMBOL(DWC_STRNCMP); ++EXPORT_SYMBOL(DWC_STRCMP); ++EXPORT_SYMBOL(DWC_STRLEN); ++EXPORT_SYMBOL(DWC_STRCPY); ++EXPORT_SYMBOL(DWC_STRDUP); ++EXPORT_SYMBOL(DWC_ATOI); ++EXPORT_SYMBOL(DWC_ATOUI); ++ ++#ifdef DWC_UTFLIB ++EXPORT_SYMBOL(DWC_UTF8_TO_UTF16LE); ++#endif /* DWC_UTFLIB */ ++ ++EXPORT_SYMBOL(DWC_IN_IRQ); ++EXPORT_SYMBOL(DWC_IN_BH); ++EXPORT_SYMBOL(DWC_VPRINTF); ++EXPORT_SYMBOL(DWC_VSNPRINTF); ++EXPORT_SYMBOL(DWC_PRINTF); ++EXPORT_SYMBOL(DWC_SPRINTF); ++EXPORT_SYMBOL(DWC_SNPRINTF); ++EXPORT_SYMBOL(__DWC_WARN); ++EXPORT_SYMBOL(__DWC_ERROR); ++EXPORT_SYMBOL(DWC_EXCEPTION); ++ ++#ifdef DEBUG ++EXPORT_SYMBOL(__DWC_DEBUG); ++#endif ++ ++EXPORT_SYMBOL(__DWC_DMA_ALLOC); ++EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC); ++EXPORT_SYMBOL(__DWC_DMA_FREE); ++EXPORT_SYMBOL(__DWC_ALLOC); ++EXPORT_SYMBOL(__DWC_ALLOC_ATOMIC); ++EXPORT_SYMBOL(__DWC_FREE); ++ ++#ifdef DWC_CRYPTOLIB ++EXPORT_SYMBOL(DWC_RANDOM_BYTES); ++EXPORT_SYMBOL(DWC_AES_CBC); ++EXPORT_SYMBOL(DWC_SHA256); ++EXPORT_SYMBOL(DWC_HMAC_SHA256); ++#endif ++ ++EXPORT_SYMBOL(DWC_CPU_TO_LE32); ++EXPORT_SYMBOL(DWC_CPU_TO_BE32); ++EXPORT_SYMBOL(DWC_LE32_TO_CPU); ++EXPORT_SYMBOL(DWC_BE32_TO_CPU); ++EXPORT_SYMBOL(DWC_CPU_TO_LE16); ++EXPORT_SYMBOL(DWC_CPU_TO_BE16); ++EXPORT_SYMBOL(DWC_LE16_TO_CPU); ++EXPORT_SYMBOL(DWC_BE16_TO_CPU); ++EXPORT_SYMBOL(DWC_READ_REG32); ++EXPORT_SYMBOL(DWC_WRITE_REG32); ++EXPORT_SYMBOL(DWC_MODIFY_REG32); ++ ++EXPORT_SYMBOL(DWC_SPINLOCK_ALLOC); ++EXPORT_SYMBOL(DWC_SPINLOCK_FREE); ++EXPORT_SYMBOL(DWC_SPINLOCK); ++EXPORT_SYMBOL(DWC_SPINUNLOCK); ++EXPORT_SYMBOL(DWC_SPINLOCK_IRQSAVE); ++EXPORT_SYMBOL(DWC_SPINUNLOCK_IRQRESTORE); ++EXPORT_SYMBOL(DWC_MUTEX_ALLOC); ++ ++#if (!defined(DWC_LINUX) || !defined(CONFIG_DEBUG_MUTEXES)) ++EXPORT_SYMBOL(DWC_MUTEX_FREE); ++#endif ++ ++EXPORT_SYMBOL(DWC_MUTEX_LOCK); ++EXPORT_SYMBOL(DWC_MUTEX_TRYLOCK); ++EXPORT_SYMBOL(DWC_MUTEX_UNLOCK); ++EXPORT_SYMBOL(DWC_UDELAY); ++EXPORT_SYMBOL(DWC_MDELAY); ++EXPORT_SYMBOL(DWC_MSLEEP); ++EXPORT_SYMBOL(DWC_TIME); ++EXPORT_SYMBOL(DWC_TIMER_ALLOC); ++EXPORT_SYMBOL(DWC_TIMER_FREE); ++EXPORT_SYMBOL(DWC_TIMER_SCHEDULE); ++EXPORT_SYMBOL(DWC_TIMER_CANCEL); ++EXPORT_SYMBOL(DWC_WAITQ_ALLOC); ++EXPORT_SYMBOL(DWC_WAITQ_FREE); ++EXPORT_SYMBOL(DWC_WAITQ_WAIT); ++EXPORT_SYMBOL(DWC_WAITQ_WAIT_TIMEOUT); ++EXPORT_SYMBOL(DWC_WAITQ_TRIGGER); ++EXPORT_SYMBOL(DWC_WAITQ_ABORT); ++EXPORT_SYMBOL(DWC_THREAD_RUN); ++EXPORT_SYMBOL(DWC_THREAD_STOP); ++EXPORT_SYMBOL(DWC_THREAD_SHOULD_STOP); ++EXPORT_SYMBOL(DWC_TASK_ALLOC); ++EXPORT_SYMBOL(DWC_TASK_FREE); ++EXPORT_SYMBOL(DWC_TASK_SCHEDULE); ++EXPORT_SYMBOL(DWC_WORKQ_WAIT_WORK_DONE); ++EXPORT_SYMBOL(DWC_WORKQ_ALLOC); ++EXPORT_SYMBOL(DWC_WORKQ_FREE); ++EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE); ++EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE_DELAYED); ++EXPORT_SYMBOL(DWC_WORKQ_PENDING); ++ ++static int dwc_common_port_init_module(void) ++{ ++ int result = 0; ++ ++ printk(KERN_DEBUG "Module dwc_common_port init\n" ); ++ ++#ifdef DWC_DEBUG_MEMORY ++ result = dwc_memory_debug_start(NULL); ++ if (result) { ++ printk(KERN_ERR ++ "dwc_memory_debug_start() failed with error %d\n", ++ result); ++ return result; ++ } ++#endif ++ ++#ifdef DWC_NOTIFYLIB ++ result = dwc_alloc_notification_manager(NULL, NULL); ++ if (result) { ++ printk(KERN_ERR ++ "dwc_alloc_notification_manager() failed with error %d\n", ++ result); ++ return result; ++ } ++#endif ++ return result; ++} ++ ++static void dwc_common_port_exit_module(void) ++{ ++ printk(KERN_DEBUG "Module dwc_common_port exit\n" ); ++ ++#ifdef DWC_NOTIFYLIB ++ dwc_free_notification_manager(); ++#endif ++ ++#ifdef DWC_DEBUG_MEMORY ++ dwc_memory_debug_stop(); ++#endif ++} ++ ++module_init(dwc_common_port_init_module); ++module_exit(dwc_common_port_exit_module); ++ ++MODULE_DESCRIPTION("DWC Common Library - Portable version"); ++MODULE_AUTHOR("Synopsys Inc."); ++MODULE_LICENSE ("GPL"); ++ ++#endif /* DWC_LIBMODULE */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_crypto.c b/drivers/usb/gadget/udc/hiudc/dwc_crypto.c +new file mode 100644 +index 0000000..3b03532 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_crypto.c +@@ -0,0 +1,308 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.c $ ++ * $Revision: #5 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS 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. ++ * ========================================================================= */ ++ ++/** @file ++ * This file contains the WUSB cryptographic routines. ++ */ ++ ++#ifdef DWC_CRYPTOLIB ++ ++#include "dwc_crypto.h" ++#include "usb.h" ++ ++#ifdef DEBUG ++static inline void dump_bytes(char *name, uint8_t *bytes, int len) ++{ ++ int i; ++ DWC_PRINTF("%s: ", name); ++ for (i=0; idst == src, then the bytes will be encrypted ++ * in-place. ++ * ++ * @return 0 on success, negative error code on error. ++ */ ++int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst) ++{ ++ u8 block_t[16]; ++ DWC_MEMSET(block_t, 0, 16); ++ ++ return DWC_AES_CBC(src, 16, key, 16, block_t, dst); ++} ++ ++/** ++ * The CCM-MAC-FUNCTION described in section 6.5 of the WUSB spec. ++ * This function takes a data string and returns the encrypted CBC ++ * Counter-mode MIC. ++ * ++ * @param key The 128-bit symmetric key. ++ * @param nonce The CCM nonce. ++ * @param label The unique 14-byte ASCII text label. ++ * @param bytes The byte array to be encrypted. ++ * @param len Length of the byte array. ++ * @param result Byte array to receive the 8-byte encrypted MIC. ++ */ ++void dwc_wusb_cmf(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ u8 block_m[16]; ++ u8 block_x[16]; ++ u8 block_t[8]; ++ int idx, blkNum; ++ u16 la = (u16)(len + 14); ++ ++ /* Set the AES-128 key */ ++ //dwc_aes_setkey(tfm, key, 16); ++ ++ /* Fill block B0 from flags = 0x59, N, and l(m) = 0 */ ++ block_m[0] = 0x59; ++ for (idx = 0; idx < 13; idx++) ++ block_m[idx + 1] = nonce[idx]; ++ block_m[14] = 0; ++ block_m[15] = 0; ++ ++ /* Produce the CBC IV */ ++ dwc_wusb_aes_encrypt(block_m, key, block_x); ++ show_block(block_m, "CBC IV in: ", "\n", 0); ++ show_block(block_x, "CBC IV out:", "\n", 0); ++ ++ /* Fill block B1 from l(a) = Blen + 14, and A */ ++ block_x[0] ^= (u8)(la >> 8); ++ block_x[1] ^= (u8)la; ++ for (idx = 0; idx < 14; idx++) ++ block_x[idx + 2] ^= label[idx]; ++ show_block(block_x, "After xor: ", "b1\n", 16); ++ ++ dwc_wusb_aes_encrypt(block_x, key, block_x); ++ show_block(block_x, "After AES: ", "b1\n", 16); ++ ++ idx = 0; ++ blkNum = 0; ++ ++ /* Fill remaining blocks with B */ ++ while (len-- > 0) { ++ block_x[idx] ^= *bytes++; ++ if (++idx >= 16) { ++ idx = 0; ++ show_block(block_x, "After xor: ", "\n", blkNum); ++ dwc_wusb_aes_encrypt(block_x, key, block_x); ++ show_block(block_x, "After AES: ", "\n", blkNum); ++ blkNum++; ++ } ++ } ++ ++ /* Handle partial last block */ ++ if (idx > 0) { ++ show_block(block_x, "After xor: ", "\n", blkNum); ++ dwc_wusb_aes_encrypt(block_x, key, block_x); ++ show_block(block_x, "After AES: ", "\n", blkNum); ++ } ++ ++ /* Save the MIC tag */ ++ DWC_MEMCPY(block_t, block_x, 8); ++ show_block(block_t, "MIC tag : ", NULL, 8); ++ ++ /* Fill block A0 from flags = 0x01, N, and counter = 0 */ ++ block_m[0] = 0x01; ++ block_m[14] = 0; ++ block_m[15] = 0; ++ ++ /* Encrypt the counter */ ++ dwc_wusb_aes_encrypt(block_m, key, block_x); ++ show_block(block_x, "CTR[MIC] : ", NULL, 8); ++ ++ /* XOR with MIC tag */ ++ for (idx = 0; idx < 8; idx++) { ++ block_t[idx] ^= block_x[idx]; ++ } ++ ++ /* Return result to caller */ ++ DWC_MEMCPY(result, block_t, 8); ++ show_block(result, "CCM-MIC : ", NULL, 8); ++ ++} ++ ++/** ++ * The PRF function described in section 6.5 of the WUSB spec. This function ++ * concatenates MIC values returned from dwc_cmf() to create a value of ++ * the requested length. ++ * ++ * @param prf_len Length of the PRF function in bits (64, 128, or 256). ++ * @param key, nonce, label, bytes, len Same as for dwc_cmf(). ++ * @param result Byte array to receive the result. ++ */ ++void dwc_wusb_prf(int prf_len, u8 *key, ++ u8 *nonce, char *label, u8 *bytes, int len, u8 *result) ++{ ++ int i; ++ ++ nonce[0] = 0; ++ for (i = 0; i < prf_len >> 6; i++, nonce[0]++) { ++ dwc_wusb_cmf(key, nonce, label, bytes, len, result); ++ result += 8; ++ } ++} ++ ++/** ++ * Fills in CCM Nonce per the WUSB spec. ++ * ++ * @param[in] haddr Host address. ++ * @param[in] daddr Device address. ++ * @param[in] tkid Session Key(PTK) identifier. ++ * @param[out] nonce Pointer to where the CCM Nonce output is to be written. ++ */ ++void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid, ++ uint8_t *nonce) ++{ ++ ++ DWC_DEBUG("%s %x %x\n", __func__, daddr, haddr); ++ ++ DWC_MEMSET(&nonce[0], 0, 16); ++ ++ DWC_MEMCPY(&nonce[6], tkid, 3); ++ nonce[9] = daddr & 0xFF; ++ nonce[10] = (daddr >> 8) & 0xFF; ++ nonce[11] = haddr & 0xFF; ++ nonce[12] = (haddr >> 8) & 0xFF; ++ ++ dump_bytes("CCM nonce", nonce, 16); ++} ++ ++/** ++ * Generates a 16-byte cryptographic-grade random number for the Host/Device ++ * Nonce. ++ */ ++void dwc_wusb_gen_nonce(uint16_t addr, uint8_t *nonce) ++{ ++ uint8_t inonce[16]; ++ uint32_t temp[4]; ++ ++ /* Fill in the Nonce */ ++ DWC_MEMSET(&inonce[0], 0, sizeof(inonce)); ++ inonce[9] = addr & 0xFF; ++ inonce[10] = (addr >> 8) & 0xFF; ++ inonce[11] = inonce[9]; ++ inonce[12] = inonce[10]; ++ ++ /* Collect "randomness samples" */ ++ DWC_RANDOM_BYTES((uint8_t *)temp, 16); ++ ++ dwc_wusb_prf_128((uint8_t *)temp, nonce, ++ "Random Numbers", (uint8_t *)temp, sizeof(temp), ++ nonce); ++} ++ ++/** ++ * Generates the Session Key (PTK) and Key Confirmation Key (KCK) per the ++ * WUSB spec. ++ * ++ * @param[in] ccm_nonce Pointer to CCM Nonce. ++ * @param[in] mk Master Key to derive the session from ++ * @param[in] hnonce Pointer to Host Nonce. ++ * @param[in] dnonce Pointer to Device Nonce. ++ * @param[out] kck Pointer to where the KCK output is to be written. ++ * @param[out] ptk Pointer to where the PTK output is to be written. ++ */ ++void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, uint8_t *hnonce, ++ uint8_t *dnonce, uint8_t *kck, uint8_t *ptk) ++{ ++ uint8_t idata[32]; ++ uint8_t odata[32]; ++ ++ dump_bytes("ck", mk, 16); ++ dump_bytes("hnonce", hnonce, 16); ++ dump_bytes("dnonce", dnonce, 16); ++ ++ /* The data is the HNonce and DNonce concatenated */ ++ DWC_MEMCPY(&idata[0], hnonce, 16); ++ DWC_MEMCPY(&idata[16], dnonce, 16); ++ ++ dwc_wusb_prf_256(mk, ccm_nonce, "Pair-wise keys", idata, 32, odata); ++ ++ /* Low 16 bytes of the result is the KCK, high 16 is the PTK */ ++ DWC_MEMCPY(kck, &odata[0], 16); ++ DWC_MEMCPY(ptk, &odata[16], 16); ++ ++ dump_bytes("kck", kck, 16); ++ dump_bytes("ptk", ptk, 16); ++} ++ ++/** ++ * Generates the Message Integrity Code over the Handshake data per the ++ * WUSB spec. ++ * ++ * @param ccm_nonce Pointer to CCM Nonce. ++ * @param kck Pointer to Key Confirmation Key. ++ * @param data Pointer to Handshake data to be checked. ++ * @param mic Pointer to where the MIC output is to be written. ++ */ ++void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t *kck, ++ uint8_t *data, uint8_t *mic) ++{ ++ ++ dwc_wusb_prf_64(kck, ccm_nonce, "out-of-bandMIC", ++ data, WUSB_HANDSHAKE_LEN_FOR_MIC, mic); ++} ++ ++#endif /* DWC_CRYPTOLIB */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_crypto.h b/drivers/usb/gadget/udc/hiudc/dwc_crypto.h +new file mode 100644 +index 0000000..26fcddc +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_crypto.h +@@ -0,0 +1,111 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.h $ ++ * $Revision: #3 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS 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 _DWC_CRYPTO_H_ ++#define _DWC_CRYPTO_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ * ++ * This file contains declarations for the WUSB Cryptographic routines as ++ * defined in the WUSB spec. They are only to be used internally by the DWC UWB ++ * modules. ++ */ ++ ++#include "dwc_os.h" ++ ++int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst); ++ ++void dwc_wusb_cmf(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result); ++void dwc_wusb_prf(int prf_len, u8 *key, ++ u8 *nonce, char *label, u8 *bytes, int len, u8 *result); ++ ++/** ++ * The PRF-64 function described in section 6.5 of the WUSB spec. ++ * ++ * @param key, nonce, label, bytes, len, result Same as for dwc_prf(). ++ */ ++static inline void dwc_wusb_prf_64(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ dwc_wusb_prf(64, key, nonce, label, bytes, len, result); ++} ++ ++/** ++ * The PRF-128 function described in section 6.5 of the WUSB spec. ++ * ++ * @param key, nonce, label, bytes, len, result Same as for dwc_prf(). ++ */ ++static inline void dwc_wusb_prf_128(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ dwc_wusb_prf(128, key, nonce, label, bytes, len, result); ++} ++ ++/** ++ * The PRF-256 function described in section 6.5 of the WUSB spec. ++ * ++ * @param key, nonce, label, bytes, len, result Same as for dwc_prf(). ++ */ ++static inline void dwc_wusb_prf_256(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ dwc_wusb_prf(256, key, nonce, label, bytes, len, result); ++} ++ ++ ++void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid, ++ uint8_t *nonce); ++void dwc_wusb_gen_nonce(uint16_t addr, ++ uint8_t *nonce); ++ ++void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, ++ uint8_t *hnonce, uint8_t *dnonce, ++ uint8_t *kck, uint8_t *ptk); ++ ++ ++void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t ++ *kck, uint8_t *data, uint8_t *mic); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_CRYPTO_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_dh.c b/drivers/usb/gadget/udc/hiudc/dwc_dh.c +new file mode 100644 +index 0000000..2b429a3 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_dh.c +@@ -0,0 +1,291 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.c $ ++ * $Revision: #3 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS 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. ++ * ========================================================================= */ ++#ifdef DWC_CRYPTOLIB ++ ++#ifndef CONFIG_MACH_IPMATE ++ ++#include "dwc_dh.h" ++#include "dwc_modpow.h" ++ ++#ifdef DEBUG ++/* This function prints out a buffer in the format described in the Association ++ * Model specification. */ ++static void dh_dump(char *str, void *_num, int len) ++{ ++ uint8_t *num = _num; ++ int i; ++ DWC_PRINTF("%s\n", str); ++ for (i = 0; i < len; i ++) { ++ DWC_PRINTF("%02x", num[i]); ++ if (((i + 1) % 2) == 0) DWC_PRINTF(" "); ++ if (((i + 1) % 26) == 0) DWC_PRINTF("\n"); ++ } ++ ++ DWC_PRINTF("\n"); ++} ++#else ++#define dh_dump(_x...) do {; } while(0) ++#endif ++ ++/* Constant g value */ ++static __u32 dh_g[] = { ++ 0x02000000, ++}; ++ ++/* Constant p value */ ++static __u32 dh_p[] = { ++ 0xFFFFFFFF, 0xFFFFFFFF, 0xA2DA0FC9, 0x34C26821, 0x8B62C6C4, 0xD11CDC80, 0x084E0229, 0x74CC678A, ++ 0xA6BE0B02, 0x229B133B, 0x79084A51, 0xDD04348E, 0xB31995EF, 0x1B433ACD, 0x6D0A2B30, 0x37145FF2, ++ 0x6D35E14F, 0x45C2516D, 0x76B585E4, 0xC67E5E62, 0xE9424CF4, 0x6BED37A6, 0xB65CFF0B, 0xEDB706F4, ++ 0xFB6B38EE, 0xA59F895A, 0x11249FAE, 0xE61F4B7C, 0x51662849, 0x3D5BE4EC, 0xB87C00C2, 0x05BF63A1, ++ 0x3648DA98, 0x9AD3551C, 0xA83F1669, 0x5FCF24FD, 0x235D6583, 0x96ADA3DC, 0x56F3621C, 0xBB528520, ++ 0x0729D59E, 0x6D969670, 0x4E350C67, 0x0498BC4A, 0x086C74F1, 0x7C2118CA, 0x465E9032, 0x3BCE362E, ++ 0x2C779EE3, 0x03860E18, 0xA283279B, 0x8FA207EC, 0xF05DC5B5, 0xC9524C6F, 0xF6CB2BDE, 0x18175895, ++ 0x7C499539, 0xE56A95EA, 0x1826D215, 0x1005FA98, 0x5A8E7215, 0x2DC4AA8A, 0x0D1733AD, 0x337A5004, ++ 0xAB2155A8, 0x64BA1CDF, 0x0485FBEC, 0x0AEFDB58, 0x5771EA8A, 0x7D0C065D, 0x850F97B3, 0xC7E4E1A6, ++ 0x8CAEF5AB, 0xD73309DB, 0xE0948C1E, 0x9D61254A, 0x26D2E3CE, 0x6BEED21A, 0x06FA2FF1, 0x64088AD9, ++ 0x730276D8, 0x646AC83E, 0x182B1F52, 0x0C207B17, 0x5717E1BB, 0x6C5D617A, 0xC0880977, 0xE246D9BA, ++ 0xA04FE208, 0x31ABE574, 0xFC5BDB43, 0x8E10FDE0, 0x20D1824B, 0xCAD23AA9, 0xFFFFFFFF, 0xFFFFFFFF, ++}; ++ ++static void dh_swap_bytes(void *_in, void *_out, uint32_t len) ++{ ++ uint8_t *in = _in; ++ uint8_t *out = _out; ++ int i; ++ for (i=0; inext = (link); \ ++ (link)->prev = (link); \ ++} while (0) ++ ++#define DWC_LIST_FIRST(link) ((link)->next) ++#define DWC_LIST_LAST(link) ((link)->prev) ++#define DWC_LIST_END(link) (link) ++#define DWC_LIST_NEXT(link) ((link)->next) ++#define DWC_LIST_PREV(link) ((link)->prev) ++#define DWC_LIST_EMPTY(link) \ ++ (DWC_LIST_FIRST(link) == DWC_LIST_END(link)) ++#define DWC_LIST_ENTRY(link, type, field) \ ++ (type *)((uint8_t *)(link) - (size_t)(&((type *)0)->field)) ++ ++#define DWC_LIST_INSERT_HEAD(list, link) do { \ ++ dwc_list_link_t *__next__ = (list)->next; \ ++ __next__->prev = (link); \ ++ (link)->next = __next__; \ ++ (link)->prev = (list); \ ++ (list)->next = (link); \ ++} while (0) ++ ++#define DWC_LIST_INSERT_TAIL(list, link) do { \ ++ dwc_list_link_t *__prev__ = (list)->prev; \ ++ (list)->prev = (link); \ ++ (link)->next = (list); \ ++ (link)->prev = __prev__; \ ++ __prev__->next = (link); \ ++} while (0) ++ ++#define DWC_LIST_REMOVE(link) do { \ ++ (link)->next->prev = (link)->prev; \ ++ (link)->prev->next = (link)->next; \ ++} while (0) ++ ++#define DWC_LIST_REMOVE_INIT(link) do { \ ++ DWC_LIST_REMOVE(link); \ ++ DWC_LIST_INIT(link); \ ++} while (0) ++ ++#define DWC_LIST_MOVE_HEAD(list, link) do { \ ++ DWC_LIST_REMOVE(link); \ ++ DWC_LIST_INSERT_HEAD(list, link); \ ++} while (0) ++ ++#define DWC_LIST_MOVE_TAIL(list, link) do { \ ++ DWC_LIST_REMOVE(link); \ ++ DWC_LIST_INSERT_TAIL(list, link); \ ++} while (0) ++ ++#define DWC_LIST_FOREACH(var, list) \ ++ for((var) = DWC_LIST_FIRST(list); \ ++ (var) != DWC_LIST_END(list); \ ++ (var) = DWC_LIST_NEXT(var)) ++ ++#define DWC_LIST_FOREACH_SAFE(var, var2, list) \ ++ for((var) = DWC_LIST_FIRST(list), (var2) = DWC_LIST_NEXT(var); \ ++ (var) != DWC_LIST_END(list); \ ++ (var) = (var2), (var2) = DWC_LIST_NEXT(var2)) ++ ++#define DWC_LIST_FOREACH_REVERSE(var, list) \ ++ for((var) = DWC_LIST_LAST(list); \ ++ (var) != DWC_LIST_END(list); \ ++ (var) = DWC_LIST_PREV(var)) ++ ++/* ++ * Singly-linked List definitions. ++ */ ++#define DWC_SLIST_HEAD(name, type) \ ++struct name { \ ++ struct type *slh_first; /* first element */ \ ++} ++ ++#define DWC_SLIST_HEAD_INITIALIZER(head) \ ++ { NULL } ++ ++#define DWC_SLIST_ENTRY(type) \ ++struct { \ ++ struct type *sle_next; /* next element */ \ ++} ++ ++/* ++ * Singly-linked List access methods. ++ */ ++#define DWC_SLIST_FIRST(head) ((head)->slh_first) ++#define DWC_SLIST_END(head) NULL ++#define DWC_SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) ++#define DWC_SLIST_NEXT(elm, field) ((elm)->field.sle_next) ++ ++#define DWC_SLIST_FOREACH(var, head, field) \ ++ for((var) = SLIST_FIRST(head); \ ++ (var) != SLIST_END(head); \ ++ (var) = SLIST_NEXT(var, field)) ++ ++#define DWC_SLIST_FOREACH_PREVPTR(var, varp, head, field) \ ++ for((varp) = &SLIST_FIRST((head)); \ ++ ((var) = *(varp)) != SLIST_END(head); \ ++ (varp) = &SLIST_NEXT((var), field)) ++ ++/* ++ * Singly-linked List functions. ++ */ ++#define DWC_SLIST_INIT(head) { \ ++ SLIST_FIRST(head) = SLIST_END(head); \ ++} ++ ++#define DWC_SLIST_INSERT_AFTER(slistelm, elm, field) do { \ ++ (elm)->field.sle_next = (slistelm)->field.sle_next; \ ++ (slistelm)->field.sle_next = (elm); \ ++} while (0) ++ ++#define DWC_SLIST_INSERT_HEAD(head, elm, field) do { \ ++ (elm)->field.sle_next = (head)->slh_first; \ ++ (head)->slh_first = (elm); \ ++} while (0) ++ ++#define DWC_SLIST_REMOVE_NEXT(head, elm, field) do { \ ++ (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ ++} while (0) ++ ++#define DWC_SLIST_REMOVE_HEAD(head, field) do { \ ++ (head)->slh_first = (head)->slh_first->field.sle_next; \ ++} while (0) ++ ++#define DWC_SLIST_REMOVE(head, elm, type, field) do { \ ++ if ((head)->slh_first == (elm)) { \ ++ SLIST_REMOVE_HEAD((head), field); \ ++ } \ ++ else { \ ++ struct type *curelm = (head)->slh_first; \ ++ while( curelm->field.sle_next != (elm) ) \ ++ curelm = curelm->field.sle_next; \ ++ curelm->field.sle_next = \ ++ curelm->field.sle_next->field.sle_next; \ ++ } \ ++} while (0) ++ ++/* ++ * Simple queue definitions. ++ */ ++#define DWC_SIMPLEQ_HEAD(name, type) \ ++struct name { \ ++ struct type *sqh_first; /* first element */ \ ++ struct type **sqh_last; /* addr of last next element */ \ ++} ++ ++#define DWC_SIMPLEQ_HEAD_INITIALIZER(head) \ ++ { NULL, &(head).sqh_first } ++ ++#define DWC_SIMPLEQ_ENTRY(type) \ ++struct { \ ++ struct type *sqe_next; /* next element */ \ ++} ++ ++/* ++ * Simple queue access methods. ++ */ ++#define DWC_SIMPLEQ_FIRST(head) ((head)->sqh_first) ++#define DWC_SIMPLEQ_END(head) NULL ++#define DWC_SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) ++#define DWC_SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) ++ ++#define DWC_SIMPLEQ_FOREACH(var, head, field) \ ++ for((var) = SIMPLEQ_FIRST(head); \ ++ (var) != SIMPLEQ_END(head); \ ++ (var) = SIMPLEQ_NEXT(var, field)) ++ ++/* ++ * Simple queue functions. ++ */ ++#define DWC_SIMPLEQ_INIT(head) do { \ ++ (head)->sqh_first = NULL; \ ++ (head)->sqh_last = &(head)->sqh_first; \ ++} while (0) ++ ++#define DWC_SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ ++ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ ++ (head)->sqh_last = &(elm)->field.sqe_next; \ ++ (head)->sqh_first = (elm); \ ++} while (0) ++ ++#define DWC_SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ ++ (elm)->field.sqe_next = NULL; \ ++ *(head)->sqh_last = (elm); \ ++ (head)->sqh_last = &(elm)->field.sqe_next; \ ++} while (0) ++ ++#define DWC_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ ++ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ ++ (head)->sqh_last = &(elm)->field.sqe_next; \ ++ (listelm)->field.sqe_next = (elm); \ ++} while (0) ++ ++#define DWC_SIMPLEQ_REMOVE_HEAD(head, field) do { \ ++ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ ++ (head)->sqh_last = &(head)->sqh_first; \ ++} while (0) ++ ++/* ++ * Tail queue definitions. ++ */ ++#define DWC_TAILQ_HEAD(name, type) \ ++struct name { \ ++ struct type *tqh_first; /* first element */ \ ++ struct type **tqh_last; /* addr of last next element */ \ ++} ++ ++#define DWC_TAILQ_HEAD_INITIALIZER(head) \ ++ { NULL, &(head).tqh_first } ++ ++#define DWC_TAILQ_ENTRY(type) \ ++struct { \ ++ struct type *tqe_next; /* next element */ \ ++ struct type **tqe_prev; /* address of previous next element */ \ ++} ++ ++/* ++ * tail queue access methods ++ */ ++#define DWC_TAILQ_FIRST(head) ((head)->tqh_first) ++#define DWC_TAILQ_END(head) NULL ++#define DWC_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) ++#define DWC_TAILQ_LAST(head, headname) \ ++ (*(((struct headname *)((head)->tqh_last))->tqh_last)) ++/* XXX */ ++#define DWC_TAILQ_PREV(elm, headname, field) \ ++ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) ++#define DWC_TAILQ_EMPTY(head) \ ++ (TAILQ_FIRST(head) == TAILQ_END(head)) ++ ++#define DWC_TAILQ_FOREACH(var, head, field) \ ++ for((var) = TAILQ_FIRST(head); \ ++ (var) != TAILQ_END(head); \ ++ (var) = TAILQ_NEXT(var, field)) ++ ++#define DWC_TAILQ_FOREACH_REVERSE(var, head, headname, field) \ ++ for((var) = TAILQ_LAST(head, headname); \ ++ (var) != TAILQ_END(head); \ ++ (var) = TAILQ_PREV(var, headname, field)) ++ ++/* ++ * Tail queue functions. ++ */ ++#define DWC_TAILQ_INIT(head) do { \ ++ (head)->tqh_first = NULL; \ ++ (head)->tqh_last = &(head)->tqh_first; \ ++} while (0) ++ ++#define DWC_TAILQ_INSERT_HEAD(head, elm, field) do { \ ++ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ ++ (head)->tqh_first->field.tqe_prev = \ ++ &(elm)->field.tqe_next; \ ++ else \ ++ (head)->tqh_last = &(elm)->field.tqe_next; \ ++ (head)->tqh_first = (elm); \ ++ (elm)->field.tqe_prev = &(head)->tqh_first; \ ++} while (0) ++ ++#define DWC_TAILQ_INSERT_TAIL(head, elm, field) do { \ ++ (elm)->field.tqe_next = NULL; \ ++ (elm)->field.tqe_prev = (head)->tqh_last; \ ++ *(head)->tqh_last = (elm); \ ++ (head)->tqh_last = &(elm)->field.tqe_next; \ ++} while (0) ++ ++#define DWC_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ ++ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ ++ (elm)->field.tqe_next->field.tqe_prev = \ ++ &(elm)->field.tqe_next; \ ++ else \ ++ (head)->tqh_last = &(elm)->field.tqe_next; \ ++ (listelm)->field.tqe_next = (elm); \ ++ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ ++} while (0) ++ ++#define DWC_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ ++ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ ++ (elm)->field.tqe_next = (listelm); \ ++ *(listelm)->field.tqe_prev = (elm); \ ++ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ ++} while (0) ++ ++#define DWC_TAILQ_REMOVE(head, elm, field) do { \ ++ if (((elm)->field.tqe_next) != NULL) \ ++ (elm)->field.tqe_next->field.tqe_prev = \ ++ (elm)->field.tqe_prev; \ ++ else \ ++ (head)->tqh_last = (elm)->field.tqe_prev; \ ++ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ ++} while (0) ++ ++#define DWC_TAILQ_REPLACE(head, elm, elm2, field) do { \ ++ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ ++ (elm2)->field.tqe_next->field.tqe_prev = \ ++ &(elm2)->field.tqe_next; \ ++ else \ ++ (head)->tqh_last = &(elm2)->field.tqe_next; \ ++ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ ++ *(elm2)->field.tqe_prev = (elm2); \ ++} while (0) ++ ++/* ++ * Circular queue definitions. ++ */ ++#define DWC_CIRCLEQ_HEAD(name, type) \ ++struct name { \ ++ struct type *cqh_first; /* first element */ \ ++ struct type *cqh_last; /* last element */ \ ++} ++ ++#define DWC_CIRCLEQ_HEAD_INITIALIZER(head) \ ++ { DWC_CIRCLEQ_END(&head), DWC_CIRCLEQ_END(&head) } ++ ++#define DWC_CIRCLEQ_ENTRY(type) \ ++struct { \ ++ struct type *cqe_next; /* next element */ \ ++ struct type *cqe_prev; /* previous element */ \ ++} ++ ++/* ++ * Circular queue access methods ++ */ ++#define DWC_CIRCLEQ_FIRST(head) ((head)->cqh_first) ++#define DWC_CIRCLEQ_LAST(head) ((head)->cqh_last) ++#define DWC_CIRCLEQ_END(head) ((void *)(head)) ++#define DWC_CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) ++#define DWC_CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) ++#define DWC_CIRCLEQ_EMPTY(head) \ ++ (DWC_CIRCLEQ_FIRST(head) == DWC_CIRCLEQ_END(head)) ++ ++#define DWC_CIRCLEQ_EMPTY_ENTRY(elm, field) (((elm)->field.cqe_next == NULL) && ((elm)->field.cqe_prev == NULL)) ++ ++#define DWC_CIRCLEQ_FOREACH(var, head, field) \ ++ for((var) = DWC_CIRCLEQ_FIRST(head); \ ++ (var) != DWC_CIRCLEQ_END(head); \ ++ (var) = DWC_CIRCLEQ_NEXT(var, field)) ++ ++#define DWC_CIRCLEQ_FOREACH_SAFE(var, var2, head, field) \ ++ for((var) = DWC_CIRCLEQ_FIRST(head), var2 = DWC_CIRCLEQ_NEXT(var, field); \ ++ (var) != DWC_CIRCLEQ_END(head); \ ++ (var) = var2, var2 = DWC_CIRCLEQ_NEXT(var, field)) ++ ++#define DWC_CIRCLEQ_FOREACH_REVERSE(var, head, field) \ ++ for((var) = DWC_CIRCLEQ_LAST(head); \ ++ (var) != DWC_CIRCLEQ_END(head); \ ++ (var) = DWC_CIRCLEQ_PREV(var, field)) ++ ++/* ++ * Circular queue functions. ++ */ ++#define DWC_CIRCLEQ_INIT(head) do { \ ++ (head)->cqh_first = DWC_CIRCLEQ_END(head); \ ++ (head)->cqh_last = DWC_CIRCLEQ_END(head); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INIT_ENTRY(elm, field) do { \ ++ (elm)->field.cqe_next = NULL; \ ++ (elm)->field.cqe_prev = NULL; \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ ++ (elm)->field.cqe_next = (listelm)->field.cqe_next; \ ++ (elm)->field.cqe_prev = (listelm); \ ++ if ((listelm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_last = (elm); \ ++ else \ ++ (listelm)->field.cqe_next->field.cqe_prev = (elm); \ ++ (listelm)->field.cqe_next = (elm); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ ++ (elm)->field.cqe_next = (listelm); \ ++ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ ++ if ((listelm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_first = (elm); \ ++ else \ ++ (listelm)->field.cqe_prev->field.cqe_next = (elm); \ ++ (listelm)->field.cqe_prev = (elm); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ ++ (elm)->field.cqe_next = (head)->cqh_first; \ ++ (elm)->field.cqe_prev = DWC_CIRCLEQ_END(head); \ ++ if ((head)->cqh_last == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_last = (elm); \ ++ else \ ++ (head)->cqh_first->field.cqe_prev = (elm); \ ++ (head)->cqh_first = (elm); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ ++ (elm)->field.cqe_next = DWC_CIRCLEQ_END(head); \ ++ (elm)->field.cqe_prev = (head)->cqh_last; \ ++ if ((head)->cqh_first == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_first = (elm); \ ++ else \ ++ (head)->cqh_last->field.cqe_next = (elm); \ ++ (head)->cqh_last = (elm); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_REMOVE(head, elm, field) do { \ ++ if ((elm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_last = (elm)->field.cqe_prev; \ ++ else \ ++ (elm)->field.cqe_next->field.cqe_prev = \ ++ (elm)->field.cqe_prev; \ ++ if ((elm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_first = (elm)->field.cqe_next; \ ++ else \ ++ (elm)->field.cqe_prev->field.cqe_next = \ ++ (elm)->field.cqe_next; \ ++} while (0) ++ ++#define DWC_CIRCLEQ_REMOVE_INIT(head, elm, field) do { \ ++ DWC_CIRCLEQ_REMOVE(head, elm, field); \ ++ DWC_CIRCLEQ_INIT_ENTRY(elm, field); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ ++ if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ ++ DWC_CIRCLEQ_END(head)) \ ++ (head).cqh_last = (elm2); \ ++ else \ ++ (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ ++ if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ ++ DWC_CIRCLEQ_END(head)) \ ++ (head).cqh_first = (elm2); \ ++ else \ ++ (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ ++} while (0) ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_LIST_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_mem.c b/drivers/usb/gadget/udc/hiudc/dwc_mem.c +new file mode 100644 +index 0000000..ad645ff +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_mem.c +@@ -0,0 +1,245 @@ ++/* Memory Debugging */ ++#ifdef DWC_DEBUG_MEMORY ++ ++#include "dwc_os.h" ++#include "dwc_list.h" ++ ++struct allocation { ++ void *addr; ++ void *ctx; ++ char *func; ++ int line; ++ uint32_t size; ++ int dma; ++ DWC_CIRCLEQ_ENTRY(allocation) entry; ++}; ++ ++DWC_CIRCLEQ_HEAD(allocation_queue, allocation); ++ ++struct allocation_manager { ++ void *mem_ctx; ++ struct allocation_queue allocations; ++ ++ /* statistics */ ++ int num; ++ int num_freed; ++ int num_active; ++ uint32_t total; ++ uint32_t cur; ++ uint32_t max; ++}; ++ ++static struct allocation_manager *manager = NULL; ++ ++static int add_allocation(void *ctx, uint32_t size, char const *func, int line, void *addr, ++ int dma) ++{ ++ struct allocation *a; ++ ++ DWC_ASSERT(manager != NULL, "manager not allocated"); ++ ++ a = __DWC_ALLOC_ATOMIC(manager->mem_ctx, sizeof(*a)); ++ if (!a) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ a->func = __DWC_ALLOC_ATOMIC(manager->mem_ctx, DWC_STRLEN(func) + 1); ++ if (!a->func) { ++ __DWC_FREE(manager->mem_ctx, a); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ DWC_MEMCPY(a->func, func, DWC_STRLEN(func) + 1); ++ a->addr = addr; ++ a->ctx = ctx; ++ a->line = line; ++ a->size = size; ++ a->dma = dma; ++ DWC_CIRCLEQ_INSERT_TAIL(&manager->allocations, a, entry); ++ ++ /* Update stats */ ++ manager->num++; ++ manager->num_active++; ++ manager->total += size; ++ manager->cur += size; ++ ++ if (manager->max < manager->cur) { ++ manager->max = manager->cur; ++ } ++ ++ return 0; ++} ++ ++static struct allocation *find_allocation(void *ctx, void *addr) ++{ ++ struct allocation *a; ++ ++ DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { ++ if (a->ctx == ctx && a->addr == addr) { ++ return a; ++ } ++ } ++ ++ return NULL; ++} ++ ++static void free_allocation(void *ctx, void *addr, char const *func, int line) ++{ ++ struct allocation *a = find_allocation(ctx, addr); ++ ++ if (!a) { ++ DWC_ASSERT(0, ++ "Free of address %p that was never allocated or already freed %s:%d", ++ addr, func, line); ++ return; ++ } ++ ++ DWC_CIRCLEQ_REMOVE(&manager->allocations, a, entry); ++ ++ manager->num_active--; ++ manager->num_freed++; ++ manager->cur -= a->size; ++ __DWC_FREE(manager->mem_ctx, a->func); ++ __DWC_FREE(manager->mem_ctx, a); ++} ++ ++int dwc_memory_debug_start(void *mem_ctx) ++{ ++ DWC_ASSERT(manager == NULL, "Memory debugging has already started\n"); ++ ++ if (manager) { ++ return -DWC_E_BUSY; ++ } ++ ++ manager = __DWC_ALLOC(mem_ctx, sizeof(*manager)); ++ if (!manager) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ DWC_CIRCLEQ_INIT(&manager->allocations); ++ manager->mem_ctx = mem_ctx; ++ manager->num = 0; ++ manager->num_freed = 0; ++ manager->num_active = 0; ++ manager->total = 0; ++ manager->cur = 0; ++ manager->max = 0; ++ ++ return 0; ++} ++ ++void dwc_memory_debug_stop(void) ++{ ++ struct allocation *a; ++ ++ dwc_memory_debug_report(); ++ ++ DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { ++ DWC_ERROR("Memory leaked from %s:%d\n", a->func, a->line); ++ free_allocation(a->ctx, a->addr, NULL, -1); ++ } ++ ++ __DWC_FREE(manager->mem_ctx, manager); ++} ++ ++void dwc_memory_debug_report(void) ++{ ++ struct allocation *a; ++ ++ DWC_PRINTF("\n\n\n----------------- Memory Debugging Report -----------------\n\n"); ++ DWC_PRINTF("Num Allocations = %d\n", manager->num); ++ DWC_PRINTF("Freed = %d\n", manager->num_freed); ++ DWC_PRINTF("Active = %d\n", manager->num_active); ++ DWC_PRINTF("Current Memory Used = %d\n", manager->cur); ++ DWC_PRINTF("Total Memory Used = %d\n", manager->total); ++ DWC_PRINTF("Maximum Memory Used at Once = %d\n", manager->max); ++ DWC_PRINTF("Unfreed allocations:\n"); ++ ++ DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { ++ DWC_PRINTF(" addr=%p, size=%d from %s:%d, DMA=%d\n", ++ a->addr, a->size, a->func, a->line, a->dma); ++ } ++} ++ ++/* The replacement functions */ ++void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line) ++{ ++ void *addr = __DWC_ALLOC(mem_ctx, size); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(mem_ctx, size, func, line, addr, 0)) { ++ __DWC_FREE(mem_ctx, addr); ++ return NULL; ++ } ++ ++ return addr; ++} ++ ++void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, ++ int line) ++{ ++ void *addr = __DWC_ALLOC_ATOMIC(mem_ctx, size); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(mem_ctx, size, func, line, addr, 0)) { ++ __DWC_FREE(mem_ctx, addr); ++ return NULL; ++ } ++ ++ return addr; ++} ++ ++void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line) ++{ ++ free_allocation(mem_ctx, addr, func, line); ++ __DWC_FREE(mem_ctx, addr); ++} ++ ++void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr, ++ char const *func, int line) ++{ ++ void *addr = __DWC_DMA_ALLOC(dma_ctx, size, dma_addr); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(dma_ctx, size, func, line, addr, 1)) { ++ __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr); ++ return NULL; ++ } ++ ++ return addr; ++} ++ ++void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, ++ dwc_dma_t *dma_addr, char const *func, int line) ++{ ++ void *addr = __DWC_DMA_ALLOC_ATOMIC(dma_ctx, size, dma_addr); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(dma_ctx, size, func, line, addr, 1)) { ++ __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr); ++ return NULL; ++ } ++ ++ return addr; ++} ++ ++void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr, ++ dwc_dma_t dma_addr, char const *func, int line) ++{ ++ free_allocation(dma_ctx, virt_addr, func, line); ++ __DWC_DMA_FREE(dma_ctx, size, virt_addr, dma_addr); ++} ++ ++#endif /* DWC_DEBUG_MEMORY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_modpow.c b/drivers/usb/gadget/udc/hiudc/dwc_modpow.c +new file mode 100644 +index 0000000..307dbdf +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_modpow.c +@@ -0,0 +1,633 @@ ++/* Bignum routines adapted from PUTTY sources. PuTTY copyright notice follows. ++ * ++ * PuTTY is copyright 1997-2007 Simon Tatham. ++ * ++ * Portions copyright Robert de Bath, Joris van Rantwijk, Delian ++ * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, ++ * Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus ++ * Kuhn, and CORE SDI S.A. ++ * ++ * Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation files ++ * (the "Software"), to deal in the Software without restriction, ++ * including without limitation the rights to use, copy, modify, merge, ++ * publish, distribute, sublicense, and/or sell copies of the Software, ++ * and to permit persons to whom the Software is furnished to do so, ++ * subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE ++ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF ++ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ * ++ */ ++#ifdef DWC_CRYPTOLIB ++ ++#ifndef CONFIG_MACH_IPMATE ++ ++#include "dwc_modpow.h" ++ ++#define BIGNUM_INT_MASK 0xFFFFFFFFUL ++#define BIGNUM_TOP_BIT 0x80000000UL ++#define BIGNUM_INT_BITS 32 ++ ++ ++static void *snmalloc(void *mem_ctx, size_t n, size_t size) ++{ ++ void *p; ++ size *= n; ++ if (size == 0) size = 1; ++ p = dwc_alloc(mem_ctx, size); ++ return p; ++} ++ ++#define snewn(ctx, n, type) ((type *)snmalloc((ctx), (n), sizeof(type))) ++#define sfree dwc_free ++ ++/* ++ * Usage notes: ++ * * Do not call the DIVMOD_WORD macro with expressions such as array ++ * subscripts, as some implementations object to this (see below). ++ * * Note that none of the division methods below will cope if the ++ * quotient won't fit into BIGNUM_INT_BITS. Callers should be careful ++ * to avoid this case. ++ * If this condition occurs, in the case of the x86 DIV instruction, ++ * an overflow exception will occur, which (according to a correspondent) ++ * will manifest on Windows as something like ++ * 0xC0000095: Integer overflow ++ * The C variant won't give the right answer, either. ++ */ ++ ++#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2) ++ ++#if defined __GNUC__ && defined __i386__ ++#define DIVMOD_WORD(q, r, hi, lo, w) \ ++ __asm__("div %2" : \ ++ "=d" (r), "=a" (q) : \ ++ "r" (w), "d" (hi), "a" (lo)) ++#else ++#define DIVMOD_WORD(q, r, hi, lo, w) do { \ ++ BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \ ++ q = n / w; \ ++ r = n % w; \ ++} while (0) ++#endif ++ ++#define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8) ++ ++#define BIGNUM_INTERNAL ++ ++static Bignum newbn(void *mem_ctx, int length) ++{ ++ Bignum b = snewn(mem_ctx, length + 1, BignumInt); ++ //if (!b) ++ //abort(); /* FIXME */ ++ DWC_MEMSET(b, 0, (length + 1) * sizeof(*b)); ++ b[0] = length; ++ return b; ++} ++ ++void freebn(void *mem_ctx, Bignum b) ++{ ++ /* ++ * Burn the evidence, just in case. ++ */ ++ DWC_MEMSET(b, 0, sizeof(b[0]) * (b[0] + 1)); ++ sfree(mem_ctx, b); ++} ++ ++/* ++ * Compute c = a * b. ++ * Input is in the first len words of a and b. ++ * Result is returned in the first 2*len words of c. ++ */ ++static void internal_mul(BignumInt *a, BignumInt *b, ++ BignumInt *c, int len) ++{ ++ int i, j; ++ BignumDblInt t; ++ ++ for (j = 0; j < 2 * len; j++) ++ c[j] = 0; ++ ++ for (i = len - 1; i >= 0; i--) { ++ t = 0; ++ for (j = len - 1; j >= 0; j--) { ++ t += MUL_WORD(a[i], (BignumDblInt) b[j]); ++ t += (BignumDblInt) c[i + j + 1]; ++ c[i + j + 1] = (BignumInt) t; ++ t = t >> BIGNUM_INT_BITS; ++ } ++ c[i] = (BignumInt) t; ++ } ++} ++ ++static void internal_add_shifted(BignumInt *number, ++ unsigned n, int shift) ++{ ++ int word = 1 + (shift / BIGNUM_INT_BITS); ++ int bshift = shift % BIGNUM_INT_BITS; ++ BignumDblInt addend; ++ ++ addend = (BignumDblInt)n << bshift; ++ ++ while (addend) { ++ addend += number[word]; ++ number[word] = (BignumInt) addend & BIGNUM_INT_MASK; ++ addend >>= BIGNUM_INT_BITS; ++ word++; ++ } ++} ++ ++/* ++ * Compute a = a % m. ++ * Input in first alen words of a and first mlen words of m. ++ * Output in first alen words of a ++ * (of which first alen-mlen words will be zero). ++ * The MSW of m MUST have its high bit set. ++ * Quotient is accumulated in the `quotient' array, which is a Bignum ++ * rather than the internal bigendian format. Quotient parts are shifted ++ * left by `qshift' before adding into quot. ++ */ ++static void internal_mod(BignumInt *a, int alen, ++ BignumInt *m, int mlen, ++ BignumInt *quot, int qshift) ++{ ++ BignumInt m0, m1; ++ unsigned int h; ++ int i, k; ++ ++ m0 = m[0]; ++ if (mlen > 1) ++ m1 = m[1]; ++ else ++ m1 = 0; ++ ++ for (i = 0; i <= alen - mlen; i++) { ++ BignumDblInt t; ++ unsigned int q, r, c, ai1; ++ ++ if (i == 0) { ++ h = 0; ++ } else { ++ h = a[i - 1]; ++ a[i - 1] = 0; ++ } ++ ++ if (i == alen - 1) ++ ai1 = 0; ++ else ++ ai1 = a[i + 1]; ++ ++ /* Find q = h:a[i] / m0 */ ++ if (h >= m0) { ++ /* ++ * Special case. ++ * ++ * To illustrate it, suppose a BignumInt is 8 bits, and ++ * we are dividing (say) A1:23:45:67 by A1:B2:C3. Then ++ * our initial division will be 0xA123 / 0xA1, which ++ * will give a quotient of 0x100 and a divide overflow. ++ * However, the invariants in this division algorithm ++ * are not violated, since the full number A1:23:... is ++ * _less_ than the quotient prefix A1:B2:... and so the ++ * following correction loop would have sorted it out. ++ * ++ * In this situation we set q to be the largest ++ * quotient we _can_ stomach (0xFF, of course). ++ */ ++ q = BIGNUM_INT_MASK; ++ } else { ++ /* Macro doesn't want an array subscript expression passed ++ * into it (see definition), so use a temporary. */ ++ BignumInt tmplo = a[i]; ++ DIVMOD_WORD(q, r, h, tmplo, m0); ++ ++ /* Refine our estimate of q by looking at ++ h:a[i]:a[i+1] / m0:m1 */ ++ t = MUL_WORD(m1, q); ++ if (t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) { ++ q--; ++ t -= m1; ++ r = (r + m0) & BIGNUM_INT_MASK; /* overflow? */ ++ if (r >= (BignumDblInt) m0 && ++ t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) q--; ++ } ++ } ++ ++ /* Subtract q * m from a[i...] */ ++ c = 0; ++ for (k = mlen - 1; k >= 0; k--) { ++ t = MUL_WORD(q, m[k]); ++ t += c; ++ c = (unsigned)(t >> BIGNUM_INT_BITS); ++ if ((BignumInt) t > a[i + k]) ++ c++; ++ a[i + k] -= (BignumInt) t; ++ } ++ ++ /* Add back m in case of borrow */ ++ if (c != h) { ++ t = 0; ++ for (k = mlen - 1; k >= 0; k--) { ++ t += m[k]; ++ t += a[i + k]; ++ a[i + k] = (BignumInt) t; ++ t = t >> BIGNUM_INT_BITS; ++ } ++ q--; ++ } ++ if (quot) ++ internal_add_shifted(quot, q, qshift + BIGNUM_INT_BITS * (alen - mlen - i)); ++ } ++} ++ ++/* ++ * Compute p % mod. ++ * The most significant word of mod MUST be non-zero. ++ * We assume that the result array is the same size as the mod array. ++ * We optionally write out a quotient if `quotient' is non-NULL. ++ * We can avoid writing out the result if `result' is NULL. ++ */ ++void bigdivmod(void *mem_ctx, Bignum p, Bignum mod, Bignum result, Bignum quotient) ++{ ++ BignumInt *n, *m; ++ int mshift; ++ int plen, mlen, i, j; ++ ++ /* Allocate m of size mlen, copy mod to m */ ++ /* We use big endian internally */ ++ mlen = mod[0]; ++ m = snewn(mem_ctx, mlen, BignumInt); ++ //if (!m) ++ //abort(); /* FIXME */ ++ for (j = 0; j < mlen; j++) ++ m[j] = mod[mod[0] - j]; ++ ++ /* Shift m left to make msb bit set */ ++ for (mshift = 0; mshift < BIGNUM_INT_BITS-1; mshift++) ++ if ((m[0] << mshift) & BIGNUM_TOP_BIT) ++ break; ++ if (mshift) { ++ for (i = 0; i < mlen - 1; i++) ++ m[i] = (m[i] << mshift) | (m[i + 1] >> (BIGNUM_INT_BITS - mshift)); ++ m[mlen - 1] = m[mlen - 1] << mshift; ++ } ++ ++ plen = p[0]; ++ /* Ensure plen > mlen */ ++ if (plen <= mlen) ++ plen = mlen + 1; ++ ++ /* Allocate n of size plen, copy p to n */ ++ n = snewn(mem_ctx, plen, BignumInt); ++ //if (!n) ++ //abort(); /* FIXME */ ++ for (j = 0; j < plen; j++) ++ n[j] = 0; ++ for (j = 1; j <= (int)p[0]; j++) ++ n[plen - j] = p[j]; ++ ++ /* Main computation */ ++ internal_mod(n, plen, m, mlen, quotient, mshift); ++ ++ /* Fixup result in case the modulus was shifted */ ++ if (mshift) { ++ for (i = plen - mlen - 1; i < plen - 1; i++) ++ n[i] = (n[i] << mshift) | (n[i + 1] >> (BIGNUM_INT_BITS - mshift)); ++ n[plen - 1] = n[plen - 1] << mshift; ++ internal_mod(n, plen, m, mlen, quotient, 0); ++ for (i = plen - 1; i >= plen - mlen; i--) ++ n[i] = (n[i] >> mshift) | (n[i - 1] << (BIGNUM_INT_BITS - mshift)); ++ } ++ ++ /* Copy result to buffer */ ++ if (result) { ++ for (i = 1; i <= (int)result[0]; i++) { ++ int j = plen - i; ++ result[i] = j >= 0 ? n[j] : 0; ++ } ++ } ++ ++ /* Free temporary arrays */ ++ for (i = 0; i < mlen; i++) ++ m[i] = 0; ++ sfree(mem_ctx, m); ++ for (i = 0; i < plen; i++) ++ n[i] = 0; ++ sfree(mem_ctx, n); ++} ++ ++/* ++ * Simple remainder. ++ */ ++Bignum bigmod(void *mem_ctx, Bignum a, Bignum b) ++{ ++ Bignum r = newbn(mem_ctx, b[0]); ++ bigdivmod(mem_ctx, a, b, r, NULL); ++ return r; ++} ++ ++/* ++ * Compute (base ^ exp) % mod. ++ */ ++Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod) ++{ ++ BignumInt *a, *b, *n, *m; ++ int mshift; ++ int mlen, i, j; ++ Bignum base, result; ++ ++ /* ++ * The most significant word of mod needs to be non-zero. It ++ * should already be, but let's make sure. ++ */ ++ //assert(mod[mod[0]] != 0); ++ ++ /* ++ * Make sure the base is smaller than the modulus, by reducing ++ * it modulo the modulus if not. ++ */ ++ base = bigmod(mem_ctx, base_in, mod); ++ ++ /* Allocate m of size mlen, copy mod to m */ ++ /* We use big endian internally */ ++ mlen = mod[0]; ++ m = snewn(mem_ctx, mlen, BignumInt); ++ //if (!m) ++ //abort(); /* FIXME */ ++ for (j = 0; j < mlen; j++) ++ m[j] = mod[mod[0] - j]; ++ ++ /* Shift m left to make msb bit set */ ++ for (mshift = 0; mshift < BIGNUM_INT_BITS - 1; mshift++) ++ if ((m[0] << mshift) & BIGNUM_TOP_BIT) ++ break; ++ if (mshift) { ++ for (i = 0; i < mlen - 1; i++) ++ m[i] = ++ (m[i] << mshift) | (m[i + 1] >> ++ (BIGNUM_INT_BITS - mshift)); ++ m[mlen - 1] = m[mlen - 1] << mshift; ++ } ++ ++ /* Allocate n of size mlen, copy base to n */ ++ n = snewn(mem_ctx, mlen, BignumInt); ++ //if (!n) ++ //abort(); /* FIXME */ ++ i = mlen - base[0]; ++ for (j = 0; j < i; j++) ++ n[j] = 0; ++ for (j = 0; j < base[0]; j++) ++ n[i + j] = base[base[0] - j]; ++ ++ /* Allocate a and b of size 2*mlen. Set a = 1 */ ++ a = snewn(mem_ctx, 2 * mlen, BignumInt); ++ //if (!a) ++ //abort(); /* FIXME */ ++ b = snewn(mem_ctx, 2 * mlen, BignumInt); ++ //if (!b) ++ //abort(); /* FIXME */ ++ for (i = 0; i < 2 * mlen; i++) ++ a[i] = 0; ++ a[2 * mlen - 1] = 1; ++ ++ /* Skip leading zero bits of exp. */ ++ i = 0; ++ j = BIGNUM_INT_BITS - 1; ++ while (i < exp[0] && (exp[exp[0] - i] & (1 << j)) == 0) { ++ j--; ++ if (j < 0) { ++ i++; ++ j = BIGNUM_INT_BITS - 1; ++ } ++ } ++ ++ /* Main computation */ ++ while (i < exp[0]) { ++ while (j >= 0) { ++ internal_mul(a + mlen, a + mlen, b, mlen); ++ internal_mod(b, mlen * 2, m, mlen, NULL, 0); ++ if ((exp[exp[0] - i] & (1 << j)) != 0) { ++ internal_mul(b + mlen, n, a, mlen); ++ internal_mod(a, mlen * 2, m, mlen, NULL, 0); ++ } else { ++ BignumInt *t; ++ t = a; ++ a = b; ++ b = t; ++ } ++ j--; ++ } ++ i++; ++ j = BIGNUM_INT_BITS - 1; ++ } ++ ++ /* Fixup result in case the modulus was shifted */ ++ if (mshift) { ++ for (i = mlen - 1; i < 2 * mlen - 1; i++) ++ a[i] = ++ (a[i] << mshift) | (a[i + 1] >> ++ (BIGNUM_INT_BITS - mshift)); ++ a[2 * mlen - 1] = a[2 * mlen - 1] << mshift; ++ internal_mod(a, mlen * 2, m, mlen, NULL, 0); ++ for (i = 2 * mlen - 1; i >= mlen; i--) ++ a[i] = ++ (a[i] >> mshift) | (a[i - 1] << ++ (BIGNUM_INT_BITS - mshift)); ++ } ++ ++ /* Copy result to buffer */ ++ result = newbn(mem_ctx, mod[0]); ++ for (i = 0; i < mlen; i++) ++ result[result[0] - i] = a[i + mlen]; ++ while (result[0] > 1 && result[result[0]] == 0) ++ result[0]--; ++ ++ /* Free temporary arrays */ ++ for (i = 0; i < 2 * mlen; i++) ++ a[i] = 0; ++ sfree(mem_ctx, a); ++ for (i = 0; i < 2 * mlen; i++) ++ b[i] = 0; ++ sfree(mem_ctx, b); ++ for (i = 0; i < mlen; i++) ++ m[i] = 0; ++ sfree(mem_ctx, m); ++ for (i = 0; i < mlen; i++) ++ n[i] = 0; ++ sfree(mem_ctx, n); ++ ++ freebn(mem_ctx, base); ++ ++ return result; ++} ++ ++ ++#ifdef UNITTEST ++ ++static __u32 dh_p[] = { ++ 96, ++ 0xFFFFFFFF, ++ 0xFFFFFFFF, ++ 0xA93AD2CA, ++ 0x4B82D120, ++ 0xE0FD108E, ++ 0x43DB5BFC, ++ 0x74E5AB31, ++ 0x08E24FA0, ++ 0xBAD946E2, ++ 0x770988C0, ++ 0x7A615D6C, ++ 0xBBE11757, ++ 0x177B200C, ++ 0x521F2B18, ++ 0x3EC86A64, ++ 0xD8760273, ++ 0xD98A0864, ++ 0xF12FFA06, ++ 0x1AD2EE6B, ++ 0xCEE3D226, ++ 0x4A25619D, ++ 0x1E8C94E0, ++ 0xDB0933D7, ++ 0xABF5AE8C, ++ 0xA6E1E4C7, ++ 0xB3970F85, ++ 0x5D060C7D, ++ 0x8AEA7157, ++ 0x58DBEF0A, ++ 0xECFB8504, ++ 0xDF1CBA64, ++ 0xA85521AB, ++ 0x04507A33, ++ 0xAD33170D, ++ 0x8AAAC42D, ++ 0x15728E5A, ++ 0x98FA0510, ++ 0x15D22618, ++ 0xEA956AE5, ++ 0x3995497C, ++ 0x95581718, ++ 0xDE2BCBF6, ++ 0x6F4C52C9, ++ 0xB5C55DF0, ++ 0xEC07A28F, ++ 0x9B2783A2, ++ 0x180E8603, ++ 0xE39E772C, ++ 0x2E36CE3B, ++ 0x32905E46, ++ 0xCA18217C, ++ 0xF1746C08, ++ 0x4ABC9804, ++ 0x670C354E, ++ 0x7096966D, ++ 0x9ED52907, ++ 0x208552BB, ++ 0x1C62F356, ++ 0xDCA3AD96, ++ 0x83655D23, ++ 0xFD24CF5F, ++ 0x69163FA8, ++ 0x1C55D39A, ++ 0x98DA4836, ++ 0xA163BF05, ++ 0xC2007CB8, ++ 0xECE45B3D, ++ 0x49286651, ++ 0x7C4B1FE6, ++ 0xAE9F2411, ++ 0x5A899FA5, ++ 0xEE386BFB, ++ 0xF406B7ED, ++ 0x0BFF5CB6, ++ 0xA637ED6B, ++ 0xF44C42E9, ++ 0x625E7EC6, ++ 0xE485B576, ++ 0x6D51C245, ++ 0x4FE1356D, ++ 0xF25F1437, ++ 0x302B0A6D, ++ 0xCD3A431B, ++ 0xEF9519B3, ++ 0x8E3404DD, ++ 0x514A0879, ++ 0x3B139B22, ++ 0x020BBEA6, ++ 0x8A67CC74, ++ 0x29024E08, ++ 0x80DC1CD1, ++ 0xC4C6628B, ++ 0x2168C234, ++ 0xC90FDAA2, ++ 0xFFFFFFFF, ++ 0xFFFFFFFF, ++}; ++ ++static __u32 dh_a[] = { ++ 8, ++ 0xdf367516, ++ 0x86459caa, ++ 0xe2d459a4, ++ 0xd910dae0, ++ 0x8a8b5e37, ++ 0x67ab31c6, ++ 0xf0b55ea9, ++ 0x440051d6, ++}; ++ ++static __u32 dh_b[] = { ++ 8, ++ 0xded92656, ++ 0xe07a048a, ++ 0x6fa452cd, ++ 0x2df89d30, ++ 0xc75f1b0f, ++ 0x8ce3578f, ++ 0x7980a324, ++ 0x5daec786, ++}; ++ ++static __u32 dh_g[] = { ++ 1, ++ 2, ++}; ++ ++int main(void) ++{ ++ int i; ++ __u32 *k; ++ k = dwc_modpow(NULL, dh_g, dh_a, dh_p); ++ ++ printf("\n\n"); ++ for (i=0; i> 16; ++ printf("%04x %04x ", m, l); ++ if (!((i + 1)%13)) printf("\n"); ++ } ++ printf("\n\n"); ++ ++ if ((k[0] == 0x60) && (k[1] == 0x28e490e5) && (k[0x60] == 0x5a0d3d4e)) { ++ printf("PASS\n\n"); ++ } ++ else { ++ printf("FAIL\n\n"); ++ } ++ ++} ++ ++#endif /* UNITTEST */ ++ ++#endif /* CONFIG_MACH_IPMATE */ ++ ++#endif /*DWC_CRYPTOLIB */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_modpow.h b/drivers/usb/gadget/udc/hiudc/dwc_modpow.h +new file mode 100644 +index 0000000..64f00c2 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_modpow.h +@@ -0,0 +1,34 @@ ++/* ++ * dwc_modpow.h ++ * See dwc_modpow.c for license and changes ++ */ ++#ifndef _DWC_MODPOW_H ++#define _DWC_MODPOW_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "dwc_os.h" ++ ++/** @file ++ * ++ * This file defines the module exponentiation function which is only used ++ * internally by the DWC UWB modules for calculation of PKs during numeric ++ * association. The routine is taken from the PUTTY, an open source terminal ++ * emulator. The PUTTY License is preserved in the dwc_modpow.c file. ++ * ++ */ ++ ++typedef uint32_t BignumInt; ++typedef uint64_t BignumDblInt; ++typedef BignumInt *Bignum; ++ ++/* Compute modular exponentiaion */ ++extern Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _LINUX_BIGNUM_H */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_notifier.c b/drivers/usb/gadget/udc/hiudc/dwc_notifier.c +new file mode 100644 +index 0000000..d3dadce +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_notifier.c +@@ -0,0 +1,319 @@ ++#ifdef DWC_NOTIFYLIB ++ ++#include "dwc_notifier.h" ++#include "dwc_list.h" ++ ++typedef struct dwc_observer { ++ void *observer; ++ dwc_notifier_callback_t callback; ++ void *data; ++ char *notification; ++ DWC_CIRCLEQ_ENTRY(dwc_observer) list_entry; ++} observer_t; ++ ++DWC_CIRCLEQ_HEAD(observer_queue, dwc_observer); ++ ++typedef struct dwc_notifier { ++ void *mem_ctx; ++ void *object; ++ struct observer_queue observers; ++ DWC_CIRCLEQ_ENTRY(dwc_notifier) list_entry; ++} notifier_t; ++ ++DWC_CIRCLEQ_HEAD(notifier_queue, dwc_notifier); ++ ++typedef struct manager { ++ void *mem_ctx; ++ void *wkq_ctx; ++ dwc_workq_t *wq; ++// dwc_mutex_t *mutex; ++ struct notifier_queue notifiers; ++} manager_t; ++ ++static manager_t *manager = NULL; ++ ++static int create_manager(void *mem_ctx, void *wkq_ctx) ++{ ++ manager = dwc_alloc(mem_ctx, sizeof(manager_t)); ++ if (!manager) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ DWC_CIRCLEQ_INIT(&manager->notifiers); ++ ++ manager->wq = dwc_workq_alloc(wkq_ctx, "DWC Notification WorkQ"); ++ if (!manager->wq) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ return 0; ++} ++ ++static void free_manager(void) ++{ ++ dwc_workq_free(manager->wq); ++ ++ /* All notifiers must have unregistered themselves before this module ++ * can be removed. Hitting this assertion indicates a programmer ++ * error. */ ++ DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&manager->notifiers), ++ "Notification manager being freed before all notifiers have been removed"); ++ dwc_free(manager->mem_ctx, manager); ++} ++ ++#ifdef DEBUG ++static void dump_manager(void) ++{ ++ notifier_t *n; ++ observer_t *o; ++ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ ++ DWC_DEBUG("List of all notifiers and observers:\n"); ++ DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) { ++ DWC_DEBUG("Notifier %p has observers:\n", n->object); ++ DWC_CIRCLEQ_FOREACH(o, &n->observers, list_entry) { ++ DWC_DEBUG(" %p watching %s\n", o->observer, o->notification); ++ } ++ } ++} ++#else ++#define dump_manager(...) ++#endif ++ ++static observer_t *alloc_observer(void *mem_ctx, void *observer, char *notification, ++ dwc_notifier_callback_t callback, void *data) ++{ ++ observer_t *new_observer = dwc_alloc(mem_ctx, sizeof(observer_t)); ++ ++ if (!new_observer) { ++ return NULL; ++ } ++ ++ DWC_CIRCLEQ_INIT_ENTRY(new_observer, list_entry); ++ new_observer->observer = observer; ++ new_observer->notification = notification; ++ new_observer->callback = callback; ++ new_observer->data = data; ++ return new_observer; ++} ++ ++static void free_observer(void *mem_ctx, observer_t *observer) ++{ ++ dwc_free(mem_ctx, observer); ++} ++ ++static notifier_t *alloc_notifier(void *mem_ctx, void *object) ++{ ++ notifier_t *notifier; ++ ++ if (!object) { ++ return NULL; ++ } ++ ++ notifier = dwc_alloc(mem_ctx, sizeof(notifier_t)); ++ if (!notifier) { ++ return NULL; ++ } ++ ++ DWC_CIRCLEQ_INIT(¬ifier->observers); ++ DWC_CIRCLEQ_INIT_ENTRY(notifier, list_entry); ++ ++ notifier->mem_ctx = mem_ctx; ++ notifier->object = object; ++ return notifier; ++} ++ ++static void free_notifier(notifier_t *notifier) ++{ ++ observer_t *observer; ++ ++ DWC_CIRCLEQ_FOREACH(observer, ¬ifier->observers, list_entry) { ++ free_observer(notifier->mem_ctx, observer); ++ } ++ ++ dwc_free(notifier->mem_ctx, notifier); ++} ++ ++static notifier_t *find_notifier(void *object) ++{ ++ notifier_t *notifier; ++ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ ++ if (!object) { ++ return NULL; ++ } ++ ++ DWC_CIRCLEQ_FOREACH(notifier, &manager->notifiers, list_entry) { ++ if (notifier->object == object) { ++ return notifier; ++ } ++ } ++ ++ return NULL; ++} ++ ++int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx) ++{ ++ return create_manager(mem_ctx, wkq_ctx); ++} ++ ++void dwc_free_notification_manager(void) ++{ ++ free_manager(); ++} ++ ++dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object) ++{ ++ notifier_t *notifier; ++ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ ++ notifier = find_notifier(object); ++ if (notifier) { ++ DWC_ERROR("Notifier %p is already registered\n", object); ++ return NULL; ++ } ++ ++ notifier = alloc_notifier(mem_ctx, object); ++ if (!notifier) { ++ return NULL; ++ } ++ ++ DWC_CIRCLEQ_INSERT_TAIL(&manager->notifiers, notifier, list_entry); ++ ++ DWC_INFO("Notifier %p registered", object); ++ dump_manager(); ++ ++ return notifier; ++} ++ ++void dwc_unregister_notifier(dwc_notifier_t *notifier) ++{ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ ++ if (!DWC_CIRCLEQ_EMPTY(¬ifier->observers)) { ++ observer_t *o; ++ ++ DWC_ERROR("Notifier %p has active observers when removing\n", notifier->object); ++ DWC_CIRCLEQ_FOREACH(o, ¬ifier->observers, list_entry) { ++ DWC_DEBUG(" %p watching %s\n", o->observer, o->notification); ++ } ++ ++ DWC_ASSERT(DWC_CIRCLEQ_EMPTY(¬ifier->observers), ++ "Notifier %p has active observers when removing", notifier); ++ } ++ ++ DWC_CIRCLEQ_REMOVE_INIT(&manager->notifiers, notifier, list_entry); ++ free_notifier(notifier); ++ ++ DWC_INFO("Notifier unregistered"); ++ dump_manager(); ++} ++ ++/* Add an observer to observe the notifier for a particular state, event, or notification. */ ++int dwc_add_observer(void *observer, void *object, char *notification, ++ dwc_notifier_callback_t callback, void *data) ++{ ++ notifier_t *notifier = find_notifier(object); ++ observer_t *new_observer; ++ ++ if (!notifier) { ++ DWC_ERROR("Notifier %p is not found when adding observer\n", object); ++ return -DWC_E_INVALID; ++ } ++ ++ new_observer = alloc_observer(notifier->mem_ctx, observer, notification, callback, data); ++ if (!new_observer) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ DWC_CIRCLEQ_INSERT_TAIL(¬ifier->observers, new_observer, list_entry); ++ ++ DWC_INFO("Added observer %p to notifier %p observing notification %s, callback=%p, data=%p", ++ observer, object, notification, callback, data); ++ ++ dump_manager(); ++ return 0; ++} ++ ++int dwc_remove_observer(void *observer) ++{ ++ notifier_t *n; ++ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ ++ DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) { ++ observer_t *o; ++ observer_t *o2; ++ ++ DWC_CIRCLEQ_FOREACH_SAFE(o, o2, &n->observers, list_entry) { ++ if (o->observer == observer) { ++ DWC_CIRCLEQ_REMOVE_INIT(&n->observers, o, list_entry); ++ DWC_INFO("Removing observer %p from notifier %p watching notification %s:", ++ o->observer, n->object, o->notification); ++ free_observer(n->mem_ctx, o); ++ } ++ } ++ } ++ ++ dump_manager(); ++ return 0; ++} ++ ++typedef struct callback_data { ++ void *mem_ctx; ++ dwc_notifier_callback_t cb; ++ void *observer; ++ void *data; ++ void *object; ++ char *notification; ++ void *notification_data; ++} cb_data_t; ++ ++static void cb_task(void *data) ++{ ++ cb_data_t *cb = (cb_data_t *)data; ++ ++ cb->cb(cb->object, cb->notification, cb->observer, cb->notification_data, cb->data); ++ dwc_free(cb->mem_ctx, cb); ++} ++ ++void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data) ++{ ++ observer_t *o; ++ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ ++ DWC_CIRCLEQ_FOREACH(o, ¬ifier->observers, list_entry) { ++ int len = DWC_STRLEN(notification); ++ ++ if (DWC_STRLEN(o->notification) != len) { ++ continue; ++ } ++ ++ if (DWC_STRNCMP(o->notification, notification, len) == 0) { ++ cb_data_t *cb_data = dwc_alloc(notifier->mem_ctx, sizeof(cb_data_t)); ++ ++ if (!cb_data) { ++ DWC_ERROR("Failed to allocate callback data\n"); ++ return; ++ } ++ ++ cb_data->mem_ctx = notifier->mem_ctx; ++ cb_data->cb = o->callback; ++ cb_data->observer = o->observer; ++ cb_data->data = o->data; ++ cb_data->object = notifier->object; ++ cb_data->notification = notification; ++ cb_data->notification_data = notification_data; ++ DWC_DEBUG("Observer found %p for notification %s\n", o->observer, notification); ++ DWC_WORKQ_SCHEDULE(manager->wq, cb_task, cb_data, ++ "Notify callback from %p for Notification %s, to observer %p", ++ cb_data->object, notification, cb_data->observer); ++ } ++ } ++} ++ ++#endif /* DWC_NOTIFYLIB */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_notifier.h b/drivers/usb/gadget/udc/hiudc/dwc_notifier.h +new file mode 100644 +index 0000000..4a8cdfe +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_notifier.h +@@ -0,0 +1,122 @@ ++ ++#ifndef __DWC_NOTIFIER_H__ ++#define __DWC_NOTIFIER_H__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "dwc_os.h" ++ ++/** @file ++ * ++ * A simple implementation of the Observer pattern. Any "module" can ++ * register as an observer or notifier. The notion of "module" is abstract and ++ * can mean anything used to identify either an observer or notifier. Usually ++ * it will be a pointer to a data structure which contains some state, ie an ++ * object. ++ * ++ * Before any notifiers can be added, the global notification manager must be ++ * brought up with dwc_alloc_notification_manager(). ++ * dwc_free_notification_manager() will bring it down and free all resources. ++ * These would typically be called upon module load and unload. The ++ * notification manager is a single global instance that handles all registered ++ * observable modules and observers so this should be done only once. ++ * ++ * A module can be observable by using Notifications to publicize some general ++ * information about it's state or operation. It does not care who listens, or ++ * even if anyone listens, or what they do with the information. The observable ++ * modules do not need to know any information about it's observers or their ++ * interface, or their state or data. ++ * ++ * Any module can register to emit Notifications. It should publish a list of ++ * notifications that it can emit and their behavior, such as when they will get ++ * triggered, and what information will be provided to the observer. Then it ++ * should register itself as an observable module. See dwc_register_notifier(). ++ * ++ * Any module can observe any observable, registered module, provided it has a ++ * handle to the other module and knows what notifications to observe. See ++ * dwc_add_observer(). ++ * ++ * A function of type dwc_notifier_callback_t is called whenever a notification ++ * is triggered with one or more observers observing it. This function is ++ * called in it's own process so it may sleep or block if needed. It is ++ * guaranteed to be called sometime after the notification has occurred and will ++ * be called once per each time the notification is triggered. It will NOT be ++ * called in the same process context used to trigger the notification. ++ * ++ * @section Limitiations ++ * ++ * Keep in mind that Notifications that can be triggered in rapid sucession may ++ * schedule too many processes too handle. Be aware of this limitation when ++ * designing to use notifications, and only add notifications for appropriate ++ * observable information. ++ * ++ * Also Notification callbacks are not synchronous. If you need to synchronize ++ * the behavior between module/observer you must use other means. And perhaps ++ * that will mean Notifications are not the proper solution. ++ */ ++ ++struct dwc_notifier; ++typedef struct dwc_notifier dwc_notifier_t; ++ ++/** The callback function must be of this type. ++ * ++ * @param object This is the object that is being observed. ++ * @param notification This is the notification that was triggered. ++ * @param observer This is the observer ++ * @param notification_data This is notification-specific data that the notifier ++ * has included in this notification. The value of this should be published in ++ * the documentation of the observable module with the notifications. ++ * @param user_data This is any custom data that the observer provided when ++ * adding itself as an observer to the notification. */ ++typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer, ++ void *notification_data, void *user_data); ++ ++/** Brings up the notification manager. */ ++extern int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx); ++/** Brings down the notification manager. */ ++extern void dwc_free_notification_manager(void); ++ ++/** This function registers an observable module. A dwc_notifier_t object is ++ * returned to the observable module. This is an opaque object that is used by ++ * the observable module to trigger notifications. This object should only be ++ * accessible to functions that are authorized to trigger notifications for this ++ * module. Observers do not need this object. */ ++extern dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object); ++ ++/** This function unregisters an observable module. All observers have to be ++ * removed prior to unregistration. */ ++extern void dwc_unregister_notifier(dwc_notifier_t *notifier); ++ ++/** Add a module as an observer to the observable module. The observable module ++ * needs to have previously registered with the notification manager. ++ * ++ * @param observer The observer module ++ * @param object The module to observe ++ * @param notification The notification to observe ++ * @param callback The callback function to call ++ * @param user_data Any additional user data to pass into the callback function */ ++extern int dwc_add_observer(void *observer, void *object, char *notification, ++ dwc_notifier_callback_t callback, void *user_data); ++ ++/** Removes the specified observer from all notifications that it is currently ++ * observing. */ ++extern int dwc_remove_observer(void *observer); ++ ++/** This function triggers a Notification. It should be called by the ++ * observable module, or any module or library which the observable module ++ * allows to trigger notification on it's behalf. Such as the dwc_cc_t. ++ * ++ * dwc_notify is a non-blocking function. Callbacks are scheduled called in ++ * their own process context for each trigger. Callbacks can be blocking. ++ * dwc_notify can be called from interrupt context if needed. ++ * ++ */ ++void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __DWC_NOTIFIER_H__ */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_os.h b/drivers/usb/gadget/udc/hiudc/dwc_os.h +new file mode 100644 +index 0000000..0d0b1ed +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_os.h +@@ -0,0 +1,1200 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_os.h $ ++ * $Revision: #14 $ ++ * $Date: 2010/11/04 $ ++ * $Change: 1621695 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS 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 _DWC_OS_H_ ++#define _DWC_OS_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ * ++ * DWC portability library, low level os-wrapper functions ++ * ++ */ ++ ++/* These basic types need to be defined by some OS header file or custom header ++ * file for your specific target architecture. ++ * ++ * uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t ++ * ++ * Any custom or alternate header file must be added and enabled here. ++ */ ++ ++#ifdef DWC_LINUX ++# include ++# ifdef CONFIG_DEBUG_MUTEXES ++# include ++# endif ++# include ++# include ++#endif ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++# include ++#endif ++ ++ ++/** @name Primitive Types and Values */ ++ ++/** We define a boolean type for consistency. Can be either YES or NO */ ++typedef uint8_t dwc_bool_t; ++#define YES 1 ++#define NO 0 ++ ++#ifdef DWC_LINUX ++ ++/** @name Error Codes */ ++#define DWC_E_INVALID EINVAL ++#define DWC_E_NO_MEMORY ENOMEM ++#define DWC_E_NO_DEVICE ENODEV ++#define DWC_E_NOT_SUPPORTED EOPNOTSUPP ++#define DWC_E_TIMEOUT ETIMEDOUT ++#define DWC_E_BUSY EBUSY ++#define DWC_E_AGAIN EAGAIN ++#define DWC_E_RESTART ERESTART ++#define DWC_E_ABORT ECONNABORTED ++#define DWC_E_SHUTDOWN ESHUTDOWN ++#define DWC_E_NO_DATA ENODATA ++#define DWC_E_DISCONNECT ECONNRESET ++#define DWC_E_UNKNOWN EINVAL ++#define DWC_E_NO_STREAM_RES ENOSR ++#define DWC_E_COMMUNICATION ECOMM ++#define DWC_E_OVERFLOW EOVERFLOW ++#define DWC_E_PROTOCOL EPROTO ++#define DWC_E_IN_PROGRESS EINPROGRESS ++#define DWC_E_PIPE EPIPE ++#define DWC_E_IO EIO ++#define DWC_E_NO_SPACE ENOSPC ++ ++#else ++ ++/** @name Error Codes */ ++#define DWC_E_INVALID 1001 ++#define DWC_E_NO_MEMORY 1002 ++#define DWC_E_NO_DEVICE 1003 ++#define DWC_E_NOT_SUPPORTED 1004 ++#define DWC_E_TIMEOUT 1005 ++#define DWC_E_BUSY 1006 ++#define DWC_E_AGAIN 1007 ++#define DWC_E_RESTART 1008 ++#define DWC_E_ABORT 1009 ++#define DWC_E_SHUTDOWN 1010 ++#define DWC_E_NO_DATA 1011 ++#define DWC_E_DISCONNECT 2000 ++#define DWC_E_UNKNOWN 3000 ++#define DWC_E_NO_STREAM_RES 4001 ++#define DWC_E_COMMUNICATION 4002 ++#define DWC_E_OVERFLOW 4003 ++#define DWC_E_PROTOCOL 4004 ++#define DWC_E_IN_PROGRESS 4005 ++#define DWC_E_PIPE 4006 ++#define DWC_E_IO 4007 ++#define DWC_E_NO_SPACE 4008 ++ ++#endif ++ ++ ++/** @name Tracing/Logging Functions ++ * ++ * These function provide the capability to add tracing, debugging, and error ++ * messages, as well exceptions as assertions. The WUDEV uses these ++ * extensively. These could be logged to the main console, the serial port, an ++ * internal buffer, etc. These functions could also be no-op if they are too ++ * expensive on your system. By default undefining the DEBUG macro already ++ * no-ops some of these functions. */ ++ ++/** Returns non-zero if in interrupt context. */ ++extern dwc_bool_t DWC_IN_IRQ(void); ++#define dwc_in_irq DWC_IN_IRQ ++ ++/** Returns "IRQ" if DWC_IN_IRQ is true. */ ++static inline char *dwc_irq(void) { ++ return DWC_IN_IRQ() ? "IRQ" : ""; ++} ++ ++/** Returns non-zero if in bottom-half context. */ ++extern dwc_bool_t DWC_IN_BH(void); ++#define dwc_in_bh DWC_IN_BH ++ ++/** Returns "BH" if DWC_IN_BH is true. */ ++static inline char *dwc_bh(void) { ++ return DWC_IN_BH() ? "BH" : ""; ++} ++ ++/** ++ * A vprintf() clone. Just call vprintf if you've got it. ++ */ ++extern void DWC_VPRINTF(char *format, va_list args); ++#define dwc_vprintf DWC_VPRINTF ++ ++/** ++ * A vsnprintf() clone. Just call vprintf if you've got it. ++ */ ++extern int DWC_VSNPRINTF(char *str, int size, char *format, va_list args); ++#define dwc_vsnprintf DWC_VSNPRINTF ++ ++/** ++ * printf() clone. Just call printf if you've go it. ++ */ ++extern void DWC_PRINTF(char *format, ...) ++/* This provides compiler level static checking of the parameters if you're ++ * using GCC. */ ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++#define dwc_printf DWC_PRINTF ++ ++/** ++ * sprintf() clone. Just call sprintf if you've got it. ++ */ ++extern int DWC_SPRINTF(char *string, char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 2, 3))); ++#else ++ ; ++#endif ++#define dwc_sprintf DWC_SPRINTF ++ ++/** ++ * snprintf() clone. Just call snprintf if you've got it. ++ */ ++extern int DWC_SNPRINTF(char *string, int size, char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 3, 4))); ++#else ++ ; ++#endif ++#define dwc_snprintf DWC_SNPRINTF ++ ++/** ++ * Prints a WARNING message. On systems that don't differentiate between ++ * warnings and regular log messages, just print it. Indicates that something ++ * may be wrong with the driver. Works like printf(). ++ * ++ * Use the DWC_WARN macro to call this function. ++ */ ++extern void __DWC_WARN(char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++ ++/** ++ * Prints an error message. On systems that don't differentiate between errors ++ * and regular log messages, just print it. Indicates that something went wrong ++ * with the driver. Works like printf(). ++ * ++ * Use the DWC_ERROR macro to call this function. ++ */ ++extern void __DWC_ERROR(char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++ ++/** ++ * Prints an exception error message and takes some user-defined action such as ++ * print out a backtrace or trigger a breakpoint. Indicates that something went ++ * abnormally wrong with the driver such as programmer error, or other ++ * exceptional condition. It should not be ignored so even on systems without ++ * printing capability, some action should be taken to notify the developer of ++ * it. Works like printf(). ++ */ ++extern void DWC_EXCEPTION(char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++#define dwc_exception DWC_EXCEPTION ++ ++#ifdef DEBUG ++/** ++ * Prints out a debug message. Used for logging/trace messages. ++ * ++ * Use the DWC_DEBUG macro to call this function ++ */ ++extern void __DWC_DEBUG(char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++#else ++#define __DWC_DEBUG(...) ++#endif ++ ++/** ++ * Prints out a Debug message. ++ */ ++#define DWC_DEBUG(_format, _args...) __DWC_DEBUG("DEBUG:%s:%s: " _format "\n", \ ++ __func__, dwc_irq(), ## _args) ++#define dwc_debug DWC_DEBUG ++/** ++ * Prints out an informative message. ++ */ ++#define DWC_INFO(_format, _args...) DWC_PRINTF("INFO:%s: " _format "\n", \ ++ dwc_irq(), ## _args) ++#define dwc_info DWC_INFO ++/** ++ * Prints out a warning message. ++ */ ++#define DWC_WARN(_format, _args...) __DWC_WARN("WARN:%s:%s:%d: " _format "\n", \ ++ dwc_irq(), __func__, __LINE__, ## _args) ++#define dwc_warn DWC_WARN ++/** ++ * Prints out an error message. ++ */ ++#define DWC_ERROR(_format, _args...) __DWC_ERROR("ERROR:%s:%s:%d: " _format "\n", \ ++ dwc_irq(), __func__, __LINE__, ## _args) ++#define dwc_error DWC_ERROR ++ ++#define DWC_PROTO_ERROR(_format, _args...) __DWC_WARN("ERROR:%s:%s:%d: " _format "\n", \ ++ dwc_irq(), __func__, __LINE__, ## _args) ++#define dwc_proto_error DWC_PROTO_ERROR ++ ++#ifdef DEBUG ++/** Prints out a exception error message if the _expr expression fails. Disabled ++ * if DEBUG is not enabled. */ ++#define DWC_ASSERT(_expr, _format, _args...) do { \ ++ if (!(_expr)) { DWC_EXCEPTION("%s:%s:%d: " _format "\n", dwc_irq(), \ ++ __FILE__, __LINE__, ## _args); } \ ++ } while (0) ++#else ++#define DWC_ASSERT(_x...) ++#endif ++#define dwc_assert DWC_ASSERT ++ ++ ++/** @name Byte Ordering ++ * The following functions are for conversions between processor's byte ordering ++ * and specific ordering you want. ++ */ ++ ++/** Converts 32 bit data in CPU byte ordering to little endian. */ ++extern uint32_t DWC_CPU_TO_LE32(uint32_t *p); ++#define dwc_cpu_to_le32 DWC_CPU_TO_LE32 ++ ++/** Converts 32 bit data in CPU byte orderint to big endian. */ ++extern uint32_t DWC_CPU_TO_BE32(uint32_t *p); ++#define dwc_cpu_to_be32 DWC_CPU_TO_BE32 ++ ++/** Converts 32 bit little endian data to CPU byte ordering. */ ++extern uint32_t DWC_LE32_TO_CPU(uint32_t *p); ++#define dwc_le32_to_cpu DWC_LE32_TO_CPU ++ ++/** Converts 32 bit big endian data to CPU byte ordering. */ ++extern uint32_t DWC_BE32_TO_CPU(uint32_t *p); ++#define dwc_be32_to_cpu DWC_BE32_TO_CPU ++ ++/** Converts 16 bit data in CPU byte ordering to little endian. */ ++extern uint16_t DWC_CPU_TO_LE16(uint16_t *p); ++#define dwc_cpu_to_le16 DWC_CPU_TO_LE16 ++ ++/** Converts 16 bit data in CPU byte orderint to big endian. */ ++extern uint16_t DWC_CPU_TO_BE16(uint16_t *p); ++#define dwc_cpu_to_be16 DWC_CPU_TO_BE16 ++ ++/** Converts 16 bit little endian data to CPU byte ordering. */ ++extern uint16_t DWC_LE16_TO_CPU(uint16_t *p); ++#define dwc_le16_to_cpu DWC_LE16_TO_CPU ++ ++/** Converts 16 bit bi endian data to CPU byte ordering. */ ++extern uint16_t DWC_BE16_TO_CPU(uint16_t *p); ++#define dwc_be16_to_cpu DWC_BE16_TO_CPU ++ ++ ++/** @name Register Read/Write ++ * ++ * The following six functions should be implemented to read/write registers of ++ * 32-bit and 64-bit sizes. All modules use this to read/write register values. ++ * The reg value is a pointer to the register calculated from the void *base ++ * variable passed into the driver when it is started. */ ++ ++#ifdef DWC_LINUX ++/* Linux doesn't need any extra parameters for register read/write, so we ++ * just throw away the IO context parameter. ++ */ ++/** Reads the content of a 32-bit register. */ ++extern uint32_t DWC_READ_REG32(uint32_t volatile *reg); ++#define dwc_read_reg32(_ctx_,_reg_) DWC_READ_REG32(_reg_) ++ ++/** Reads the content of a 64-bit register. */ ++extern uint64_t DWC_READ_REG64(uint64_t volatile *reg); ++#define dwc_read_reg64(_ctx_,_reg_) DWC_READ_REG64(_reg_) ++ ++/** Writes to a 32-bit register. */ ++extern void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value); ++#define dwc_write_reg32(_ctx_,_reg_,_val_) DWC_WRITE_REG32(_reg_, _val_) ++ ++/** Writes to a 64-bit register. */ ++extern void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value); ++#define dwc_write_reg64(_ctx_,_reg_,_val_) DWC_WRITE_REG64(_reg_, _val_) ++ ++/** ++ * Modify bit values in a register. Using the ++ * algorithm: (reg_contents & ~clear_mask) | set_mask. ++ */ ++extern void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask); ++#define dwc_modify_reg32(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG32(_reg_,_cmsk_,_smsk_) ++extern void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask); ++#define dwc_modify_reg64(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG64(_reg_,_cmsk_,_smsk_) ++ ++#endif /* DWC_LINUX */ ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++typedef struct dwc_ioctx { ++ struct device *dev; ++ bus_space_tag_t iot; ++ bus_space_handle_t ioh; ++} dwc_ioctx_t; ++ ++/** BSD needs two extra parameters for register read/write, so we pass ++ * them in using the IO context parameter. ++ */ ++/** Reads the content of a 32-bit register. */ ++extern uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg); ++#define dwc_read_reg32 DWC_READ_REG32 ++ ++/** Reads the content of a 64-bit register. */ ++extern uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg); ++#define dwc_read_reg64 DWC_READ_REG64 ++ ++/** Writes to a 32-bit register. */ ++extern void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value); ++#define dwc_write_reg32 DWC_WRITE_REG32 ++ ++/** Writes to a 64-bit register. */ ++extern void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value); ++#define dwc_write_reg64 DWC_WRITE_REG64 ++ ++/** ++ * Modify bit values in a register. Using the ++ * algorithm: (reg_contents & ~clear_mask) | set_mask. ++ */ ++extern void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask); ++#define dwc_modify_reg32 DWC_MODIFY_REG32 ++extern void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask); ++#define dwc_modify_reg64 DWC_MODIFY_REG64 ++ ++#endif /* DWC_FREEBSD || DWC_NETBSD */ ++ ++/** @cond */ ++ ++/** @name Some convenience MACROS used internally. Define DWC_DEBUG_REGS to log the ++ * register writes. */ ++ ++#ifdef DWC_LINUX ++ ++# ifdef DWC_DEBUG_REGS ++ ++#define dwc_define_read_write_reg_n(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \ ++ return DWC_READ_REG32(&container->regs->_reg[num]); \ ++} \ ++static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \ ++ DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \ ++ &(((uint32_t*)container->regs->_reg)[num]), data); \ ++ DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \ ++} ++ ++#define dwc_define_read_write_reg(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg(_container_type *container) { \ ++ return DWC_READ_REG32(&container->regs->_reg); \ ++} \ ++static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \ ++ DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \ ++ DWC_WRITE_REG32(&container->regs->_reg, data); \ ++} ++ ++# else /* DWC_DEBUG_REGS */ ++ ++#define dwc_define_read_write_reg_n(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \ ++ return DWC_READ_REG32(&container->regs->_reg[num]); \ ++} \ ++static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \ ++ DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \ ++} ++ ++#define dwc_define_read_write_reg(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg(_container_type *container) { \ ++ return DWC_READ_REG32(&container->regs->_reg); \ ++} \ ++static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \ ++ DWC_WRITE_REG32(&container->regs->_reg, data); \ ++} ++ ++# endif /* DWC_DEBUG_REGS */ ++ ++#endif /* DWC_LINUX */ ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++ ++# ifdef DWC_DEBUG_REGS ++ ++#define dwc_define_read_write_reg_n(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \ ++ return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \ ++} \ ++static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \ ++ DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \ ++ &(((uint32_t*)container->regs->_reg)[num]), data); \ ++ DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \ ++} ++ ++#define dwc_define_read_write_reg(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \ ++ return DWC_READ_REG32(io_ctx, &container->regs->_reg); \ ++} \ ++static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \ ++ DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \ ++ DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \ ++} ++ ++# else /* DWC_DEBUG_REGS */ ++ ++#define dwc_define_read_write_reg_n(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \ ++ return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \ ++} \ ++static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \ ++ DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \ ++} ++ ++#define dwc_define_read_write_reg(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \ ++ return DWC_READ_REG32(io_ctx, &container->regs->_reg); \ ++} \ ++static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \ ++ DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \ ++} ++ ++# endif /* DWC_DEBUG_REGS */ ++ ++#endif /* DWC_FREEBSD || DWC_NETBSD */ ++ ++/** @endcond */ ++ ++ ++#ifdef DWC_CRYPTOLIB ++/** @name Crypto Functions ++ * ++ * These are the low-level cryptographic functions used by the driver. */ ++ ++/** Perform AES CBC */ ++extern int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out); ++#define dwc_aes_cbc DWC_AES_CBC ++ ++/** Fill the provided buffer with random bytes. These should be cryptographic grade random numbers. */ ++extern void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length); ++#define dwc_random_bytes DWC_RANDOM_BYTES ++ ++/** Perform the SHA-256 hash function */ ++extern int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out); ++#define dwc_sha256 DWC_SHA256 ++ ++/** Calculated the HMAC-SHA256 */ ++extern int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t *out); ++#define dwc_hmac_sha256 DWC_HMAC_SHA256 ++ ++#endif /* DWC_CRYPTOLIB */ ++ ++ ++/** @name Memory Allocation ++ * ++ * These function provide access to memory allocation. There are only 2 DMA ++ * functions and 3 Regular memory functions that need to be implemented. None ++ * of the memory debugging routines need to be implemented. The allocation ++ * routines all ZERO the contents of the memory. ++ * ++ * Defining DWC_DEBUG_MEMORY turns on memory debugging and statistic gathering. ++ * This checks for memory leaks, keeping track of alloc/free pairs. It also ++ * keeps track of how much memory the driver is using at any given time. */ ++ ++#define DWC_PAGE_SIZE 4096 ++#define DWC_PAGE_OFFSET(addr) (((uint32_t)addr) & 0xfff) ++#define DWC_PAGE_ALIGNED(addr) ((((uint32_t)addr) & 0xfff) == 0) ++ ++#define DWC_INVALID_DMA_ADDR 0x0 ++ ++#ifdef DWC_LINUX ++/** Type for a DMA address */ ++typedef dma_addr_t dwc_dma_t; ++#endif ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++typedef bus_addr_t dwc_dma_t; ++#endif ++ ++#ifdef DWC_FREEBSD ++typedef struct dwc_dmactx { ++ struct device *dev; ++ bus_dma_tag_t dma_tag; ++ bus_dmamap_t dma_map; ++ bus_addr_t dma_paddr; ++ void *dma_vaddr; ++} dwc_dmactx_t; ++#endif ++ ++#ifdef DWC_NETBSD ++typedef struct dwc_dmactx { ++ struct device *dev; ++ bus_dma_tag_t dma_tag; ++ bus_dmamap_t dma_map; ++ bus_dma_segment_t segs[1]; ++ int nsegs; ++ bus_addr_t dma_paddr; ++ void *dma_vaddr; ++} dwc_dmactx_t; ++#endif ++ ++/** Allocates a DMA capable buffer and zeroes its contents. */ ++extern void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr); ++ ++/** Allocates a DMA capable buffer and zeroes its contents in atomic contest */ ++extern void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr); ++ ++/** Frees a previously allocated buffer. */ ++extern void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr); ++ ++/** Allocates a block of memory and zeroes its contents. */ ++extern void *__DWC_ALLOC(void *mem_ctx, uint32_t size); ++ ++/** Allocates a block of memory and zeroes its contents, in an atomic manner ++ * which can be used inside interrupt context. The size should be sufficiently ++ * small, a few KB at most, such that failures are not likely to occur. Can just call ++ * __DWC_ALLOC if it is atomic. */ ++extern void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size); ++ ++/** Frees a previously allocated buffer. */ ++extern void __DWC_FREE(void *mem_ctx, void *addr); ++ ++#ifndef DWC_DEBUG_MEMORY ++ ++#define DWC_ALLOC(_size_) __DWC_ALLOC(NULL, _size_) ++#define DWC_ALLOC_ATOMIC(_size_) __DWC_ALLOC_ATOMIC(NULL, _size_) ++#define DWC_FREE(_addr_) __DWC_FREE(NULL, _addr_) ++ ++# ifdef DWC_LINUX ++#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(NULL, _size_, _dma_) ++#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(NULL, _size_,_dma_) ++#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(NULL, _size_, _virt_, _dma_) ++# endif ++ ++# if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++#define DWC_DMA_ALLOC __DWC_DMA_ALLOC ++#define DWC_DMA_FREE __DWC_DMA_FREE ++# endif ++ ++#else /* DWC_DEBUG_MEMORY */ ++ ++extern void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line); ++extern void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, int line); ++extern void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line); ++extern void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr, ++ char const *func, int line); ++extern void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr, ++ char const *func, int line); ++extern void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr, ++ dwc_dma_t dma_addr, char const *func, int line); ++ ++extern int dwc_memory_debug_start(void *mem_ctx); ++extern void dwc_memory_debug_stop(void); ++extern void dwc_memory_debug_report(void); ++ ++#define DWC_ALLOC(_size_) dwc_alloc_debug(NULL, _size_, __func__, __LINE__) ++#define DWC_ALLOC_ATOMIC(_size_) dwc_alloc_atomic_debug(NULL, _size_, \ ++ __func__, __LINE__) ++#define DWC_FREE(_addr_) dwc_free_debug(NULL, _addr_, __func__, __LINE__) ++ ++# ifdef DWC_LINUX ++#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(NULL, _size_, \ ++ _dma_, __func__, __LINE__) ++#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(NULL, _size_, \ ++ _dma_, __func__, __LINE__) ++#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(NULL, _size_, \ ++ _virt_, _dma_, __func__, __LINE__) ++# endif ++ ++# if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++#define DWC_DMA_ALLOC(_ctx_,_size_,_dma_) dwc_dma_alloc_debug(_ctx_, _size_, \ ++ _dma_, __func__, __LINE__) ++#define DWC_DMA_FREE(_ctx_,_size_,_virt_,_dma_) dwc_dma_free_debug(_ctx_, _size_, \ ++ _virt_, _dma_, __func__, __LINE__) ++# endif ++ ++#endif /* DWC_DEBUG_MEMORY */ ++ ++#define dwc_alloc(_ctx_,_size_) DWC_ALLOC(_size_) ++#define dwc_alloc_atomic(_ctx_,_size_) DWC_ALLOC_ATOMIC(_size_) ++#define dwc_free(_ctx_,_addr_) DWC_FREE(_addr_) ++ ++#ifdef DWC_LINUX ++/* Linux doesn't need any extra parameters for DMA buffer allocation, so we ++ * just throw away the DMA context parameter. ++ */ ++#define dwc_dma_alloc(_ctx_,_size_,_dma_) DWC_DMA_ALLOC(_size_, _dma_) ++#define dwc_dma_alloc_atomic(_ctx_,_size_,_dma_) DWC_DMA_ALLOC_ATOMIC(_size_, _dma_) ++#define dwc_dma_free(_ctx_,_size_,_virt_,_dma_) DWC_DMA_FREE(_size_, _virt_, _dma_) ++#endif ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++/** BSD needs several extra parameters for DMA buffer allocation, so we pass ++ * them in using the DMA context parameter. ++ */ ++#define dwc_dma_alloc DWC_DMA_ALLOC ++#define dwc_dma_free DWC_DMA_FREE ++#endif ++ ++ ++/** @name Memory and String Processing */ ++ ++/** memset() clone */ ++extern void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size); ++#define dwc_memset DWC_MEMSET ++ ++/** memcpy() clone */ ++extern void *DWC_MEMCPY(void *dest, void const *src, uint32_t size); ++#define dwc_memcpy DWC_MEMCPY ++ ++/** memmove() clone */ ++extern void *DWC_MEMMOVE(void *dest, void *src, uint32_t size); ++#define dwc_memmove DWC_MEMMOVE ++ ++/** memcmp() clone */ ++extern int DWC_MEMCMP(void *m1, void *m2, uint32_t size); ++#define dwc_memcmp DWC_MEMCMP ++ ++/** strcmp() clone */ ++extern int DWC_STRCMP(void *s1, void *s2); ++#define dwc_strcmp DWC_STRCMP ++ ++/** strncmp() clone */ ++extern int DWC_STRNCMP(void *s1, void *s2, uint32_t size); ++#define dwc_strncmp DWC_STRNCMP ++ ++/** strlen() clone, for NULL terminated ASCII strings */ ++extern int DWC_STRLEN(char const *str); ++#define dwc_strlen DWC_STRLEN ++ ++/** strcpy() clone, for NULL terminated ASCII strings */ ++extern char *DWC_STRCPY(char *to, const char *from); ++#define dwc_strcpy DWC_STRCPY ++ ++/** strdup() clone. If you wish to use memory allocation debugging, this ++ * implementation of strdup should use the DWC_* memory routines instead of ++ * calling a predefined strdup. Otherwise the memory allocated by this routine ++ * will not be seen by the debugging routines. */ ++extern char *DWC_STRDUP(char const *str); ++#define dwc_strdup(_ctx_,_str_) DWC_STRDUP(_str_) ++ ++/** NOT an atoi() clone. Read the description carefully. Returns an integer ++ * converted from the string str in base 10 unless the string begins with a "0x" ++ * in which case it is base 16. String must be a NULL terminated sequence of ++ * ASCII characters and may optionally begin with whitespace, a + or -, and a ++ * "0x" prefix if base 16. The remaining characters must be valid digits for ++ * the number and end with a NULL character. If any invalid characters are ++ * encountered or it returns with a negative error code and the results of the ++ * conversion are undefined. On sucess it returns 0. Overflow conditions are ++ * undefined. An example implementation using atoi() can be referenced from the ++ * Linux implementation. */ ++extern int DWC_ATOI(const char *str, int32_t *value); ++#define dwc_atoi DWC_ATOI ++ ++/** Same as above but for unsigned. */ ++extern int DWC_ATOUI(const char *str, uint32_t *value); ++#define dwc_atoui DWC_ATOUI ++ ++#ifdef DWC_UTFLIB ++/** This routine returns a UTF16LE unicode encoded string from a UTF8 string. */ ++extern int DWC_UTF8_TO_UTF16LE(uint8_t const *utf8string, uint16_t *utf16string, unsigned len); ++#define dwc_utf8_to_utf16le DWC_UTF8_TO_UTF16LE ++#endif ++ ++ ++/** @name Wait queues ++ * ++ * Wait queues provide a means of synchronizing between threads or processes. A ++ * process can block on a waitq if some condition is not true, waiting for it to ++ * become true. When the waitq is triggered all waiting process will get ++ * unblocked and the condition will be check again. Waitqs should be triggered ++ * every time a condition can potentially change.*/ ++struct dwc_waitq; ++ ++/** Type for a waitq */ ++typedef struct dwc_waitq dwc_waitq_t; ++ ++/** The type of waitq condition callback function. This is called every time ++ * condition is evaluated. */ ++typedef int (*dwc_waitq_condition_t)(void *data); ++ ++/** Allocate a waitq */ ++extern dwc_waitq_t *DWC_WAITQ_ALLOC(void); ++#define dwc_waitq_alloc(_ctx_) DWC_WAITQ_ALLOC() ++ ++/** Free a waitq */ ++extern void DWC_WAITQ_FREE(dwc_waitq_t *wq); ++#define dwc_waitq_free DWC_WAITQ_FREE ++ ++/** Check the condition and if it is false, block on the waitq. When unblocked, check the ++ * condition again. The function returns when the condition becomes true. The return value ++ * is 0 on condition true, DWC_WAITQ_ABORTED on abort or killed, or DWC_WAITQ_UNKNOWN on error. */ ++extern int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data); ++#define dwc_waitq_wait DWC_WAITQ_WAIT ++ ++/** Check the condition and if it is false, block on the waitq. When unblocked, ++ * check the condition again. The function returns when the condition become ++ * true or the timeout has passed. The return value is 0 on condition true or ++ * DWC_TIMED_OUT on timeout, or DWC_WAITQ_ABORTED, or DWC_WAITQ_UNKNOWN on ++ * error. */ ++extern int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, ++ void *data, int32_t msecs); ++#define dwc_waitq_wait_timeout DWC_WAITQ_WAIT_TIMEOUT ++ ++/** Trigger a waitq, unblocking all processes. This should be called whenever a condition ++ * has potentially changed. */ ++extern void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq); ++#define dwc_waitq_trigger DWC_WAITQ_TRIGGER ++ ++/** Unblock all processes waiting on the waitq with an ABORTED result. */ ++extern void DWC_WAITQ_ABORT(dwc_waitq_t *wq); ++#define dwc_waitq_abort DWC_WAITQ_ABORT ++ ++ ++/** @name Threads ++ * ++ * A thread must be explicitly stopped. It must check DWC_THREAD_SHOULD_STOP ++ * whenever it is woken up, and then return. The DWC_THREAD_STOP function ++ * returns the value from the thread. ++ */ ++ ++struct dwc_thread; ++ ++/** Type for a thread */ ++typedef struct dwc_thread dwc_thread_t; ++ ++/** The thread function */ ++typedef int (*dwc_thread_function_t)(void *data); ++ ++/** Create a thread and start it running the thread_function. Returns a handle ++ * to the thread */ ++extern dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data); ++#define dwc_thread_run(_ctx_,_func_,_name_,_data_) DWC_THREAD_RUN(_func_, _name_, _data_) ++ ++/** Stops a thread. Return the value returned by the thread. Or will return ++ * DWC_ABORT if the thread never started. */ ++extern int DWC_THREAD_STOP(dwc_thread_t *thread); ++#define dwc_thread_stop DWC_THREAD_STOP ++ ++/** Signifies to the thread that it must stop. */ ++#ifdef DWC_LINUX ++/* Linux doesn't need any parameters for kthread_should_stop() */ ++extern dwc_bool_t DWC_THREAD_SHOULD_STOP(void); ++#define dwc_thread_should_stop(_thrd_) DWC_THREAD_SHOULD_STOP() ++ ++/* No thread_exit function in Linux */ ++#define dwc_thread_exit(_thrd_) ++#endif ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++/** BSD needs the thread pointer for kthread_suspend_check() */ ++extern dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread); ++#define dwc_thread_should_stop DWC_THREAD_SHOULD_STOP ++ ++/** The thread must call this to exit. */ ++extern void DWC_THREAD_EXIT(dwc_thread_t *thread); ++#define dwc_thread_exit DWC_THREAD_EXIT ++#endif ++ ++ ++/** @name Work queues ++ * ++ * Workqs are used to queue a callback function to be called at some later time, ++ * in another thread. */ ++struct dwc_workq; ++ ++/** Type for a workq */ ++typedef struct dwc_workq dwc_workq_t; ++ ++/** The type of the callback function to be called. */ ++typedef void (*dwc_work_callback_t)(void *data); ++ ++/** Allocate a workq */ ++extern dwc_workq_t *DWC_WORKQ_ALLOC(char *name); ++#define dwc_workq_alloc(_ctx_,_name_) DWC_WORKQ_ALLOC(_name_) ++ ++/** Free a workq. All work must be completed before being freed. */ ++extern void DWC_WORKQ_FREE(dwc_workq_t *workq); ++#define dwc_workq_free DWC_WORKQ_FREE ++ ++/** Schedule a callback on the workq, passing in data. The function will be ++ * scheduled at some later time. */ ++extern void DWC_WORKQ_SCHEDULE(dwc_workq_t *workq, dwc_work_callback_t cb, ++ void *data, char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 4, 5))); ++#else ++ ; ++#endif ++#define dwc_workq_schedule DWC_WORKQ_SCHEDULE ++ ++/** Schedule a callback on the workq, that will be called until at least ++ * given number miliseconds have passed. */ ++extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t cb, ++ void *data, uint32_t time, char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 5, 6))); ++#else ++ ; ++#endif ++#define dwc_workq_schedule_delayed DWC_WORKQ_SCHEDULE_DELAYED ++ ++/** The number of processes in the workq */ ++extern int DWC_WORKQ_PENDING(dwc_workq_t *workq); ++#define dwc_workq_pending DWC_WORKQ_PENDING ++ ++/** Blocks until all the work in the workq is complete or timed out. Returns < ++ * 0 on timeout. */ ++extern int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout); ++#define dwc_workq_wait_work_done DWC_WORKQ_WAIT_WORK_DONE ++ ++ ++/** @name Tasklets ++ * ++ */ ++struct dwc_tasklet; ++ ++/** Type for a tasklet */ ++typedef struct dwc_tasklet dwc_tasklet_t; ++ ++/** The type of the callback function to be called */ ++typedef void (*dwc_tasklet_callback_t)(void *data); ++ ++/** Allocates a tasklet */ ++extern dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data); ++#define dwc_task_alloc(_ctx_,_name_,_cb_,_data_) DWC_TASK_ALLOC(_name_, _cb_, _data_) ++ ++/** Frees a tasklet */ ++extern void DWC_TASK_FREE(dwc_tasklet_t *task); ++#define dwc_task_free DWC_TASK_FREE ++ ++/** Schedules a tasklet to run */ ++extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task); ++#define dwc_task_schedule DWC_TASK_SCHEDULE ++ ++ ++/** @name Timer ++ * ++ * Callbacks must be small and atomic. ++ */ ++struct dwc_timer; ++ ++/** Type for a timer */ ++typedef struct dwc_timer dwc_timer_t; ++ ++/** The type of the callback function to be called */ ++typedef void (*dwc_timer_callback_t)(void *data); ++ ++/** Allocates a timer */ ++extern dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data); ++#define dwc_timer_alloc(_ctx_,_name_,_cb_,_data_) DWC_TIMER_ALLOC(_name_,_cb_,_data_) ++ ++/** Frees a timer */ ++extern void DWC_TIMER_FREE(dwc_timer_t *timer); ++#define dwc_timer_free DWC_TIMER_FREE ++ ++/** Schedules the timer to run at time ms from now. And will repeat at every ++ * repeat_interval msec therafter ++ * ++ * Modifies a timer that is still awaiting execution to a new expiration time. ++ * The mod_time is added to the old time. */ ++extern void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time); ++#define dwc_timer_schedule DWC_TIMER_SCHEDULE ++ ++/** Disables the timer from execution. */ ++extern void DWC_TIMER_CANCEL(dwc_timer_t *timer); ++#define dwc_timer_cancel DWC_TIMER_CANCEL ++ ++ ++/** @name Spinlocks ++ * ++ * These locks are used when the work between the lock/unlock is atomic and ++ * short. Interrupts are also disabled during the lock/unlock and thus they are ++ * suitable to lock between interrupt/non-interrupt context. They also lock ++ * between processes if you have multiple CPUs or Preemption. If you don't have ++ * multiple CPUS or Preemption, then the you can simply implement the ++ * DWC_SPINLOCK and DWC_SPINUNLOCK to disable and enable interrupts. Because ++ * the work between the lock/unlock is atomic, the process context will never ++ * change, and so you never have to lock between processes. */ ++ ++struct dwc_spinlock; ++ ++/** Type for a spinlock */ ++typedef struct dwc_spinlock dwc_spinlock_t; ++ ++/** Type for the 'flags' argument to spinlock funtions */ ++typedef unsigned long dwc_irqflags_t; ++ ++/** Returns an initialized lock variable. This function should allocate and ++ * initialize the OS-specific data structure used for locking. This data ++ * structure is to be used for the DWC_LOCK and DWC_UNLOCK functions and should ++ * be freed by the DWC_FREE_LOCK when it is no longer used. */ ++extern dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void); ++#define dwc_spinlock_alloc(_ctx_) DWC_SPINLOCK_ALLOC() ++ ++/** Frees an initialized lock variable. */ ++extern void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock); ++#define dwc_spinlock_free(_ctx_,_lock_) DWC_SPINLOCK_FREE(_lock_) ++ ++/** Disables interrupts and blocks until it acquires the lock. ++ * ++ * @param lock Pointer to the spinlock. ++ * @param flags Unsigned long for irq flags storage. ++ */ ++extern void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags); ++#define dwc_spinlock_irqsave DWC_SPINLOCK_IRQSAVE ++ ++/** Re-enables the interrupt and releases the lock. ++ * ++ * @param lock Pointer to the spinlock. ++ * @param flags Unsigned long for irq flags storage. Must be the same as was ++ * passed into DWC_LOCK. ++ */ ++extern void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags); ++#define dwc_spinunlock_irqrestore DWC_SPINUNLOCK_IRQRESTORE ++ ++/** Blocks until it acquires the lock. ++ * ++ * @param lock Pointer to the spinlock. ++ */ ++extern void DWC_SPINLOCK(dwc_spinlock_t *lock); ++#define dwc_spinlock DWC_SPINLOCK ++ ++/** Releases the lock. ++ * ++ * @param lock Pointer to the spinlock. ++ */ ++extern void DWC_SPINUNLOCK(dwc_spinlock_t *lock); ++#define dwc_spinunlock DWC_SPINUNLOCK ++ ++ ++/** @name Mutexes ++ * ++ * Unlike spinlocks Mutexes lock only between processes and the work between the ++ * lock/unlock CAN block, therefore it CANNOT be called from interrupt context. ++ */ ++ ++struct dwc_mutex; ++ ++/** Type for a mutex */ ++typedef struct dwc_mutex dwc_mutex_t; ++ ++/* For Linux Mutex Debugging make it inline because the debugging routines use ++ * the symbol to determine recursive locking. This makes it falsely think ++ * recursive locking occurs. */ ++#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES) ++#define DWC_MUTEX_ALLOC_LINUX_DEBUG(__mutexp) ({ \ ++ __mutexp = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); \ ++ mutex_init((struct mutex *)__mutexp); \ ++}) ++#endif ++ ++/** Allocate a mutex */ ++extern dwc_mutex_t *DWC_MUTEX_ALLOC(void); ++#define dwc_mutex_alloc(_ctx_) DWC_MUTEX_ALLOC() ++ ++/* For memory leak debugging when using Linux Mutex Debugging */ ++#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES) ++#define DWC_MUTEX_FREE(__mutexp) do { \ ++ mutex_destroy((struct mutex *)__mutexp); \ ++ DWC_FREE(__mutexp); \ ++} while(0) ++#else ++/** Free a mutex */ ++extern void DWC_MUTEX_FREE(dwc_mutex_t *mutex); ++#define dwc_mutex_free(_ctx_,_mutex_) DWC_MUTEX_FREE(_mutex_) ++#endif ++ ++/** Lock a mutex */ ++extern void DWC_MUTEX_LOCK(dwc_mutex_t *mutex); ++#define dwc_mutex_lock DWC_MUTEX_LOCK ++ ++/** Non-blocking lock returns 1 on successful lock. */ ++extern int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex); ++#define dwc_mutex_trylock DWC_MUTEX_TRYLOCK ++ ++/** Unlock a mutex */ ++extern void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex); ++#define dwc_mutex_unlock DWC_MUTEX_UNLOCK ++ ++ ++/** @name Time */ ++ ++/** Microsecond delay. ++ * ++ * @param usecs Microseconds to delay. ++ */ ++extern void DWC_UDELAY(uint32_t usecs); ++#define dwc_udelay DWC_UDELAY ++ ++/** Millisecond delay. ++ * ++ * @param msecs Milliseconds to delay. ++ */ ++extern void DWC_MDELAY(uint32_t msecs); ++#define dwc_mdelay DWC_MDELAY ++ ++/** Non-busy waiting. ++ * Sleeps for specified number of milliseconds. ++ * ++ * @param msecs Milliseconds to sleep. ++ */ ++extern void DWC_MSLEEP(uint32_t msecs); ++#define dwc_msleep DWC_MSLEEP ++ ++/** ++ * Returns number of milliseconds since boot. ++ */ ++extern uint32_t DWC_TIME(void); ++#define dwc_time DWC_TIME ++ ++ ++ ++ ++/* @mainpage DWC Portability and Common Library ++ * ++ * This is the documentation for the DWC Portability and Common Library. ++ * ++ * @section intro Introduction ++ * ++ * The DWC Portability library consists of wrapper calls and data structures to ++ * all low-level functions which are typically provided by the OS. The WUDEV ++ * driver uses only these functions. In order to port the WUDEV driver, only ++ * the functions in this library need to be re-implemented, with the same ++ * behavior as documented here. ++ * ++ * The Common library consists of higher level functions, which rely only on ++ * calling the functions from the DWC Portability library. These common ++ * routines are shared across modules. Some of the common libraries need to be ++ * used directly by the driver programmer when porting WUDEV. Such as the ++ * parameter and notification libraries. ++ * ++ * @section low Portability Library OS Wrapper Functions ++ * ++ * Any function starting with DWC and in all CAPS is a low-level OS-wrapper that ++ * needs to be implemented when porting, for example DWC_MUTEX_ALLOC(). All of ++ * these functions are included in the dwc_os.h file. ++ * ++ * There are many functions here covering a wide array of OS services. Please ++ * see dwc_os.h for details, and implementation notes for each function. ++ * ++ * @section common Common Library Functions ++ * ++ * Any function starting with dwc and in all lowercase is a common library ++ * routine. These functions have a portable implementation and do not need to ++ * be reimplemented when porting. The common routines can be used by any ++ * driver, and some must be used by the end user to control the drivers. For ++ * example, you must use the Parameter common library in order to set the ++ * parameters in the WUDEV module. ++ * ++ * The common libraries consist of the following: ++ * ++ * - Connection Contexts - Used internally and can be used by end-user. See dwc_cc.h ++ * - Parameters - Used internally and can be used by end-user. See dwc_params.h ++ * - Notifications - Used internally and can be used by end-user. See dwc_notifier.h ++ * - Lists - Used internally and can be used by end-user. See dwc_list.h ++ * - Memory Debugging - Used internally and can be used by end-user. See dwc_os.h ++ * - Modpow - Used internally only. See dwc_modpow.h ++ * - DH - Used internally only. See dwc_dh.h ++ * - Crypto - Used internally only. See dwc_crypto.h ++ * ++ * ++ * @section prereq Prerequistes For dwc_os.h ++ * @subsection types Data Types ++ * ++ * The dwc_os.h file assumes that several low-level data types are pre defined for the ++ * compilation environment. These data types are: ++ * ++ * - uint8_t - unsigned 8-bit data type ++ * - int8_t - signed 8-bit data type ++ * - uint16_t - unsigned 16-bit data type ++ * - int16_t - signed 16-bit data type ++ * - uint32_t - unsigned 32-bit data type ++ * - int32_t - signed 32-bit data type ++ * - uint64_t - unsigned 64-bit data type ++ * - int64_t - signed 64-bit data type ++ * ++ * Ensure that these are defined before using dwc_os.h. The easiest way to do ++ * that is to modify the top of the file to include the appropriate header. ++ * This is already done for the Linux environment. If the DWC_LINUX macro is ++ * defined, the correct header will be added. A standard header is ++ * also used for environments where standard C headers are available. ++ * ++ * @subsection stdarg Variable Arguments ++ * ++ * Variable arguments are provided by a standard C header . it is ++ * available in Both the Linux and ANSI C enviornment. An equivalent must be ++ * provided in your enviornment in order to use dwc_os.h with the debug and ++ * tracing message functionality. ++ * ++ * @subsection thread Threading ++ * ++ * WUDEV Core must be run on an operating system that provides for multiple ++ * threads/processes. Threading can be implemented in many ways, even in ++ * embedded systems without an operating system. At the bare minimum, the ++ * system should be able to start any number of processes at any time to handle ++ * special work. It need not be a pre-emptive system. Process context can ++ * change upon a call to a blocking function. The hardware interrupt context ++ * that calls the module's ISR() function must be differentiable from process ++ * context, even if your processes are impemented via a hardware interrupt. ++ * Further locking mechanism between process must exist (or be implemented), and ++ * process context must have a way to disable interrupts for a period of time to ++ * lock them out. If all of this exists, the functions in dwc_os.h related to ++ * threading should be able to be implemented with the defined behavior. ++ * ++ */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_OS_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_adp.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_adp.c +new file mode 100644 +index 0000000..fdf4f6e +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_adp.c +@@ -0,0 +1,718 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $ ++ * $Revision: #16 $ ++ * $Date: 2013/04/22 $ ++ * $Change: 2211149 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++#include "dwc_os.h" ++#include "dwc_otg_regs.h" ++#include "dwc_otg_cil.h" ++#include "dwc_otg_adp.h" ++ ++/** @file ++ * ++ * This file contains the most of the Attach Detect Protocol implementation for ++ * the driver to support OTG Rev2.0. ++ * ++ */ ++ ++void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value) ++{ ++ adpctl_data_t adpctl; ++ ++ adpctl.d32 = value; ++ adpctl.b.ar = 0x2; ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32); ++ ++ while (adpctl.b.ar) { ++ adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl); ++ } ++ ++} ++ ++/** ++ * Function is called to read ADP registers ++ */ ++uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ adpctl.d32 = 0; ++ adpctl.b.ar = 0x1; ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32); ++ ++ while (adpctl.b.ar) { ++ adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl); ++ } ++ ++ return adpctl.d32; ++} ++ ++/** ++ * Function is called to read ADPCTL register and filter Write-clear bits ++ */ ++uint32_t dwc_otg_adp_read_reg_filter(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ adpctl.b.adp_tmout_int = 0; ++ adpctl.b.adp_prb_int = 0; ++ adpctl.b.adp_tmout_int = 0; ++ ++ return adpctl.d32; ++} ++ ++/** ++ * Function is called to write ADP registers ++ */ ++void dwc_otg_adp_modify_reg(dwc_otg_core_if_t * core_if, uint32_t clr, ++ uint32_t set) ++{ ++ dwc_otg_adp_write_reg(core_if, ++ (dwc_otg_adp_read_reg(core_if) & (~clr)) | set); ++} ++ ++/** ++ * Start the ADP Initial Probe timer to detect if Port Connected interrupt is ++ * not asserted within 1.1 seconds. ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++void dwc_otg_adp_vbuson_timer_start(dwc_otg_core_if_t * core_if) ++{ ++ core_if->adp.vbuson_timer_started = 1; ++ if (core_if->adp.vbuson_timer) ++ { ++ DWC_PRINTF("SCHEDULING VBUSON TIMER\n"); ++ /* 1.1 secs + 60ms necessary for cil_hcd_start*/ ++ DWC_TIMER_SCHEDULE(core_if->adp.vbuson_timer, 1160); ++ } else { ++ DWC_WARN("VBUSON_TIMER = %p\n",core_if->adp.vbuson_timer); ++ } ++} ++ ++/** ++ * Starts the ADP Probing ++ * ++ * @param core_if the pointer to core_if structure. ++ */ ++uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if) ++{ ++ ++ adpctl_data_t adpctl = {.d32 = 0}; ++ gpwrdn_data_t gpwrdn; ++ ++ if (core_if->stop_adpprb) { ++ core_if->stop_adpprb = 0; ++ return 0; ++ } ++ ++ dwc_otg_disable_global_interrupts(core_if); ++ DWC_DEBUGPL(DBG_ANY, "ADP Probe Start\n"); ++ core_if->adp.probe_enabled = 1; ++ ++ adpctl.b.adpres = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ while (adpctl.b.adpres) { ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ } ++ ++ adpctl.d32 = 0; ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ /* In Host mode unmask SRP detected interrupt also change the ++ * probe preiod accordingly */ ++ if (!gpwrdn.b.idsts) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ adpctl.b.prb_per = 0; ++ } ++ else { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ gpwrdn.d32 = 0; ++ gpwrdn.b.sts_chngint_msk = 1; ++ adpctl.b.prb_per = 1; ++ } ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ ++ adpctl.b.adp_tmout_int_msk = 1; ++ adpctl.b.adp_prb_int_msk = 1; ++ adpctl.b.prb_dschg = 1; ++ adpctl.b.prb_delta = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ adpctl.b.adpen = 1; ++ adpctl.b.enaprb = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ DWC_DEBUGPL(DBG_ANY, "ADP Probe Finish\n"); ++ ++ return 0; ++} ++ ++/** ++ * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted ++ * within 3 seconds. ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++void dwc_otg_adp_sense_timer_start(dwc_otg_core_if_t * core_if) ++{ ++ core_if->adp.sense_timer_started = 1; ++ DWC_TIMER_SCHEDULE(core_if->adp.sense_timer, 3300 /* 3.3 secs */ ); ++} ++ ++/** ++ * Starts the ADP Sense ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ DWC_DEBUGPL(DBG_PCD, "ADP Sense Start\n"); ++ ++ /* Set ADP reset bit*/ ++ adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if); ++ adpctl.b.adpres = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ while (adpctl.b.adpres) { ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ } ++ ++ /* Unmask ADP sense interrupt and mask all other from the core */ ++ adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if); ++ adpctl.b.adp_sns_int_msk = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ dwc_otg_disable_global_interrupts(core_if); ++ ++ adpctl.b.adpres = 0; ++ adpctl.b.adpen = 1; ++ adpctl.b.enasns = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ dwc_otg_adp_sense_timer_start(core_if); ++ ++ return 0; ++} ++ ++/** ++ * Stops the ADP Probing ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if) ++{ ++ ++ adpctl_data_t adpctl; ++ DWC_DEBUGPL(DBG_ANY, "Stop ADP probe\n"); ++ core_if->adp.probe_enabled = 0; ++ //core_if->adp.probe_counter = 0; ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ ++ adpctl.b.adpen = 0; ++ adpctl.b.adp_prb_int = 1; ++ adpctl.b.adp_tmout_int = 1; ++ adpctl.b.adp_sns_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * Stops the ADP Sensing ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ core_if->adp.sense_enabled = 0; ++ ++ adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if); ++ adpctl.b.enasns = 0; ++ adpctl.b.adp_sns_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * Called to turn on the VBUS after initial ADP probe in host mode. ++ * If port power was already enabled in cil_hcd_start function then ++ * only schedule a timer. ++ * ++ * @param core_if the pointer to core_if structure. ++ */ ++void dwc_otg_adp_turnon_vbus(dwc_otg_core_if_t * core_if) ++{ ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ DWC_PRINTF("Turn on VBUS for 1.1s, port power is %d\n", hprt0.b.prtpwr); ++ ++ if (hprt0.b.prtpwr == 0) { ++ hprt0.b.prtpwr = 1; ++ //DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } ++ ++ dwc_otg_adp_vbuson_timer_start(core_if); ++} ++ ++/** ++ * Called right after driver is loaded ++ * to perform initial actions for ADP ++ * ++ * @param core_if the pointer to core_if structure. ++ * @param is_host - flag for current mode of operation either from GINTSTS or GPWRDN ++ */ ++void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host) ++{ ++ gpwrdn_data_t gpwrdn; ++ ++ DWC_DEBUGPL(DBG_ANY, "ADP Initial Start\n"); ++ core_if->adp.adp_started = 1; ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ dwc_otg_disable_global_interrupts(core_if); ++ if (is_host) { ++ DWC_PRINTF("HOST MODE\n"); ++ //core_if->op_state = A_HOST; - vahrama, modified checking in hcd_start() ++ /* Enable Power Down Logic Interrupt*/ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ /* Initialize first ADP probe to obtain Ramp Time value */ ++ core_if->adp.initial_probe = 1; ++ dwc_otg_adp_probe_start(core_if); ++ } else { ++ gotgctl_data_t gotgctl; ++ gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ DWC_DEBUGPL(DBG_ANY, "DEVICE MODE\n"); ++ //dwc_otg_core_init(core_if); ++ if (gotgctl.b.bsesvld == 0) { ++ /* Enable Power Down Logic Interrupt*/ ++ gpwrdn.d32 = 0; ++ DWC_DEBUGPL(DBG_ANY, "VBUS is not valid - start ADP probe\n"); ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ /* Do not need to return to inital probe if we are coming back to ++ * the device mode after HNP */ ++ if (core_if->op_state != B_HOST) ++ core_if->adp.initial_probe = 1; ++ dwc_otg_adp_probe_start(core_if); ++ } else { ++ DWC_PRINTF("VBUS is valid - initialize core as a Device\n"); ++ core_if->op_state = B_PERIPHERAL; ++ //dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ dwc_otg_dump_global_registers(core_if); ++ dwc_otg_dump_dev_registers(core_if); ++ } ++ } ++} ++ ++void dwc_otg_adp_init(dwc_otg_core_if_t * core_if) ++{ ++ core_if->adp.adp_started = 0; ++ core_if->adp.initial_probe = 0; ++ core_if->adp.probe_timer_values[0] = -1; ++ core_if->adp.probe_timer_values[1] = -1; ++ core_if->adp.probe_enabled = 0; ++ core_if->adp.sense_enabled = 0; ++ core_if->adp.sense_timer_started = 0; ++ core_if->adp.vbuson_timer_started = 0; ++ core_if->adp.probe_counter = 0; ++ core_if->adp.gpwrdn = 0; ++ core_if->adp.attached = DWC_OTG_ADP_UNKOWN; ++} ++ ++void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = { .d32 = 0 }; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ if (core_if->adp.probe_enabled) ++ dwc_otg_adp_probe_stop(core_if); ++ if (core_if->adp.sense_enabled) ++ dwc_otg_adp_sense_stop(core_if); ++ if (core_if->adp.sense_timer_started) ++ DWC_TIMER_CANCEL(core_if->adp.sense_timer); ++ if (core_if->adp.vbuson_timer_started) ++ DWC_TIMER_CANCEL(core_if->adp.vbuson_timer); ++ DWC_TIMER_FREE(core_if->adp.sense_timer); ++ DWC_TIMER_FREE(core_if->adp.vbuson_timer); ++} ++ ++///////////////////////////////////////////////////////////////////// ++////////////// ADP Interrupt Handlers /////////////////////////////// ++///////////////////////////////////////////////////////////////////// ++/** ++ * This function sets Ramp Timer values ++ */ ++static uint32_t set_timer_value(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ if (core_if->adp.probe_timer_values[0] == -1) { ++ core_if->adp.probe_timer_values[0] = val; ++ core_if->adp.probe_timer_values[1] = -1; ++ return 1; ++ } else { ++ core_if->adp.probe_timer_values[1] = ++ core_if->adp.probe_timer_values[0]; ++ core_if->adp.probe_timer_values[0] = val; ++ return 0; ++ } ++} ++ ++/** ++ * This function compares Ramp Timer values ++ */ ++static uint32_t compare_timer_values(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t diff; ++ uint32_t thres; ++ gpwrdn_data_t gpwrdn; ++ ++ /* RTIM difference thresold differs for host and device modes */ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (!gpwrdn.b.idsts) ++ thres = HOST_RTIM_THRESHOLD; ++ else ++ thres = DEVICE_RTIM_THRESHOLD; ++ ++ DWC_DEBUGPL(DBG_ANY, "timer value 0 %d timer value 1 %d\n", ++ core_if->adp.probe_timer_values[0], core_if->adp.probe_timer_values[1]); ++ if (core_if->adp.probe_timer_values[0] >= core_if->adp.probe_timer_values[1]) ++ diff = core_if->adp.probe_timer_values[0] - core_if->adp.probe_timer_values[1]; ++ else ++ diff = core_if->adp.probe_timer_values[1] - core_if->adp.probe_timer_values[0]; ++ if (diff < thres) ++ return 0; ++ else ++ return 1; ++} ++ ++/** ++ * This function handles ADP Probe Interrupts ++ */ ++static int32_t dwc_otg_adp_handle_prb_intr(dwc_otg_core_if_t * core_if, ++ uint32_t val) ++{ ++ adpctl_data_t adpctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn, temp; ++ adpctl.d32 = val; ++ ++ temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ core_if->adp.gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (adpctl.b.rtim == 0 /*&& !temp.b.idsts*/){ ++ DWC_PRINTF("RTIM value is 0\n"); ++ goto exit; ++ } ++ core_if->adp.probe_counter++; ++ ++ if (set_timer_value(core_if, adpctl.b.rtim) && ++ core_if->adp.initial_probe) { ++ core_if->adp.initial_probe = 0; ++ dwc_otg_adp_probe_stop(core_if); ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* check which value is for device mode and which for Host mode */ ++ if (!temp.b.idsts) { /* considered host mode value is 0 */ ++ /* Choose right op_state depending on previous one */ ++ if (core_if->op_state == B_PERIPHERAL) ++ core_if->op_state = B_HOST; ++ else ++ core_if->op_state = A_HOST; ++ dwc_otg_enable_global_interrupts(core_if); ++ /* ++ * Turn on VBUS after initial ADP probe. ++ */ ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_hcd_start(core_if); ++ dwc_otg_adp_turnon_vbus(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ } else { ++ /* ++ * Initiate SRP after initial ADP probe. ++ */ ++ dwc_otg_enable_global_interrupts(core_if); ++ dwc_otg_initiate_srp(core_if); ++ } ++ } else if (core_if->adp.probe_counter > 2){ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (compare_timer_values(core_if)) { ++ DWC_PRINTF("Difference in timer values !!! \n"); ++// core_if->adp.attached = DWC_OTG_ADP_ATTACHED; ++ dwc_otg_adp_probe_stop(core_if); ++ ++ /* Power on the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ /* check which value is for device mode and which for Host mode */ ++ if (!temp.b.idsts) { /* considered host mode value is 0 */ ++ /* Disable Interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Host mode. ++ * Choose right op_state depending on previous one ++ */ ++ if (core_if->op_state == B_PERIPHERAL) ++ core_if->op_state = B_HOST; ++ else ++ core_if->op_state = A_HOST; ++ ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ dwc_otg_adp_turnon_vbus(core_if); ++ } else { ++ gotgctl_data_t gotgctl; ++ /* Mask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* Disable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Device mode. ++ */ ++ core_if->op_state = B_PERIPHERAL; ++ //dwc_otg_core_init(core_if); ++ cil_pcd_start(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ ++ gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ if (!gotgctl.b.bsesvld) ++ dwc_otg_initiate_srp(core_if); ++ } ++ } ++ if (core_if->power_down == 2) { ++ if (gpwrdn.b.bsessvld) { ++ /* Mask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Disable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Device mode. ++ */ ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } ++ } ++ } ++exit: ++ /* Clear interrupt */ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ adpctl.b.adp_prb_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * This function hadles ADP Sense Interrupt ++ */ ++static int32_t dwc_otg_adp_handle_sns_intr(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ /* Stop ADP Sense timer */ ++ DWC_TIMER_CANCEL(core_if->adp.sense_timer); ++ ++ /* Restart ADP Sense timer */ ++ dwc_otg_adp_sense_timer_start(core_if); ++ ++ /* Clear interrupt */ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ adpctl.b.adp_sns_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * This function handles ADP Probe Interrupts ++ */ ++static int32_t dwc_otg_adp_handle_prb_tmout_intr(dwc_otg_core_if_t * core_if, ++ uint32_t val) ++{ ++ adpctl_data_t adpctl = {.d32 = 0 }; ++ adpctl.d32 = val; ++ set_timer_value(core_if, adpctl.b.rtim); ++ ++ /* Clear interrupt */ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ adpctl.b.adp_tmout_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * ADP Interrupt handler. ++ * ++ */ ++int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if) ++{ ++ int retval = 0; ++ adpctl_data_t adpctl = {.d32 = 0}; ++ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ DWC_DEBUGPL(DBG_ANY, "ADPCTL = %08x RAMP TIME = %d\n", adpctl.d32, adpctl.b.rtim); ++ ++ if (adpctl.b.adp_sns_int & adpctl.b.adp_sns_int_msk) { ++ DWC_DEBUGPL(DBG_ANY, "ADP Sense interrupt\n"); ++ retval |= dwc_otg_adp_handle_sns_intr(core_if); ++ } ++ if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) { ++ DWC_DEBUGPL(DBG_ANY, "ADP timeout interrupt\n"); ++ retval |= dwc_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32); ++ } ++ if (adpctl.b.adp_prb_int & adpctl.b.adp_prb_int_msk) { ++ DWC_DEBUGPL(DBG_ANY, "ADP Probe interrupt\n"); ++ adpctl.b.adp_prb_int = 1; ++ retval |= dwc_otg_adp_handle_prb_intr(core_if, adpctl.d32); ++ } ++ ++// dwc_otg_adp_modify_reg(core_if, adpctl.d32, 0); ++ //dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ DWC_DEBUGPL(DBG_ANY, "RETURN FROM ADP ISR\n"); ++ ++ return retval; ++} ++ ++/** ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if) ++{ ++ ++#ifndef DWC_HOST_ONLY ++ hprt0_data_t hprt0; ++ gpwrdn_data_t gpwrdn; ++ DWC_DEBUGPL(DBG_ANY, "++ Power Down Logic Session Request Interrupt++\n"); ++ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ /* check which value is for device mode and which for Host mode */ ++ if (!gpwrdn.b.idsts) { /* considered host mode value is 0 */ ++ DWC_PRINTF("SRP: Host mode\n"); ++ ++ if (core_if->adp_enable) { ++ dwc_otg_adp_probe_stop(core_if); ++ ++ /* Power on the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++ ++ /* Turn on the port power bit. */ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* Start the Connection timer. So a message can be displayed ++ * if connect does not occur within 10 seconds. */ ++ cil_hcd_session_start(core_if); ++ } else { ++ DWC_DEBUGPL(DBG_PCD, "SRP: Device mode %s\n", __FUNCTION__); ++ if (core_if->adp_enable) { ++ dwc_otg_adp_probe_stop(core_if); ++ ++ /* Power on the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 0; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, ++ gpwrdn.d32); ++ ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } ++ } ++#endif ++ return 1; ++} +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_adp.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_adp.h +new file mode 100644 +index 0000000..c21b2f0 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_adp.h +@@ -0,0 +1,82 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.h $ ++ * $Revision: #8 $ ++ * $Date: 2013/04/09 $ ++ * $Change: 2201932 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 __DWC_OTG_ADP_H__ ++#define __DWC_OTG_ADP_H__ ++ ++/** ++ * @file ++ * ++ * This file contains the Attach Detect Protocol interfaces and defines ++ * (functions) and structures for Linux. ++ * ++ */ ++ ++#define DWC_OTG_ADP_UNATTACHED 0 ++#define DWC_OTG_ADP_ATTACHED 1 ++#define DWC_OTG_ADP_UNKOWN 2 ++#define HOST_RTIM_THRESHOLD 5 ++#define DEVICE_RTIM_THRESHOLD 3 ++ ++typedef struct dwc_otg_adp { ++ uint32_t adp_started; ++ uint32_t initial_probe; ++ int32_t probe_timer_values[2]; ++ uint32_t probe_enabled; ++ uint32_t sense_enabled; ++ dwc_timer_t *sense_timer; ++ uint32_t sense_timer_started; ++ dwc_timer_t *vbuson_timer; ++ uint32_t vbuson_timer_started; ++ uint32_t attached; ++ uint32_t probe_counter; ++ uint32_t gpwrdn; ++} dwc_otg_adp_t; ++ ++/** ++ * Attach Detect Protocol functions ++ */ ++ ++extern void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value); ++extern uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if); ++extern uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if); ++extern uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if); ++extern uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if); ++extern uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host); ++extern void dwc_otg_adp_init(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if); ++extern int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if); ++extern int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if); ++ ++#endif //__DWC_OTG_ADP_H__ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_attr.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_attr.c +new file mode 100644 +index 0000000..73fc330 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_attr.c +@@ -0,0 +1,1311 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.c $ ++ * $Revision: #46 $ ++ * $Date: 2012/12/12 $ ++ * $Change: 2124654 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ * The diagnostic interface will provide access to the controller for ++ * bringing up the hardware and testing. The Linux driver attributes ++ * feature will be used to provide the Linux Diagnostic ++ * Interface. These attributes are accessed through sysfs. ++ */ ++ ++/** @page "Linux Module Attributes" ++ * ++ * The Linux module attributes feature is used to provide the Linux ++ * Diagnostic Interface. These attributes are accessed through sysfs. ++ * The diagnostic interface will provide access to the controller for ++ * bringing up the hardware and testing. ++ ++ The following table shows the attributes. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
Name Description Access
mode Returns the current mode: 0 for device mode, 1 for host mode Read
hnpcapable Gets or sets the "HNP-capable" bit in the Core USB Configuraton Register. ++ Read returns the current value. Read/Write
srpcapable Gets or sets the "SRP-capable" bit in the Core USB Configuraton Register. ++ Read returns the current value. Read/Write
hsic_connect Gets or sets the "HSIC-Connect" bit in the GLPMCFG Register. ++ Read returns the current value. Read/Write
inv_sel_hsic Gets or sets the "Invert Select HSIC" bit in the GLPMFG Register. ++ Read returns the current value. Read/Write
hnp Initiates the Host Negotiation Protocol. Read returns the status. Read/Write
srp Initiates the Session Request Protocol. Read returns the status. Read/Write
buspower Gets or sets the Power State of the bus (0 - Off or 1 - On) Read/Write
bussuspend Suspends the USB bus. Read/Write
busconnected Gets the connection status of the bus Read
gotgctl Gets or sets the Core Control Status Register. Read/Write
gusbcfg Gets or sets the Core USB Configuration Register Read/Write
grxfsiz Gets or sets the Receive FIFO Size Register Read/Write
gnptxfsiz Gets or sets the non-periodic Transmit Size Register Read/Write
gpvndctl Gets or sets the PHY Vendor Control Register Read/Write
ggpio Gets the value in the lower 16-bits of the General Purpose IO Register ++ or sets the upper 16 bits. Read/Write
guid Gets or sets the value of the User ID Register Read/Write
gsnpsid Gets the value of the Synopsys ID Regester Read
devspeed Gets or sets the device speed setting in the DCFG register Read/Write
enumspeed Gets the device enumeration Speed. Read
hptxfsiz Gets the value of the Host Periodic Transmit FIFO Read
hprt0 Gets or sets the value in the Host Port Control and Status Register Read/Write
regoffset Sets the register offset for the next Register Access Read/Write
regvalue Gets or sets the value of the register at the offset in the regoffset attribute. Read/Write
remote_wakeup On read, shows the status of Remote Wakeup. On write, initiates a remote ++ wakeup of the host. When bit 0 is 1 and Remote Wakeup is enabled, the Remote ++ Wakeup signalling bit in the Device Control Register is set for 1 ++ milli-second. Read/Write
rem_wakeup_pwrdn On read, shows the status core - hibernated or not. On write, initiates ++ a remote wakeup of the device from Hibernation. Read/Write
mode_ch_tim_en This bit is used to enable or disable the host core to wait for 200 PHY ++ clock cycles at the end of Resume to change the opmode signal to the PHY to 00 ++ after Suspend or LPM. Read/Write
fr_interval On read, shows the value of HFIR Frame Interval. On write, dynamically ++ reload HFIR register during runtime. The application can write a value to this ++ register only after the Port Enable bit of the Host Port Control and Status ++ register (HPRT.PrtEnaPort) has been set Read/Write
disconnect_us On read, shows the status of disconnect_device_us. On write, sets disconnect_us ++ which causes soft disconnect for 100us. Applicable only for device mode of operation. Read/Write
regdump Dumps the contents of core registers. Read
spramdump Dumps the contents of core registers. Read
hcddump Dumps the current HCD state. Read
hcd_frrem Shows the average value of the Frame Remaining ++ field in the Host Frame Number/Frame Remaining register when an SOF interrupt ++ occurs. This can be used to determine the average interrupt latency. Also ++ shows the average Frame Remaining value for start_transfer and the "a" and ++ "b" sample points. The "a" and "b" sample points may be used during debugging ++ bto determine how long it takes to execute a section of the HCD code. Read
rd_reg_test Displays the time required to read the GNPTXFSIZ register many times ++ (the output shows the number of times the register is read). ++ Read
wr_reg_test Displays the time required to write the GNPTXFSIZ register many times ++ (the output shows the number of times the register is written). ++ Read
lpm_response Gets or sets lpm_response mode. Applicable only in device mode. ++ Write
sleep_status Shows sleep status of device. ++ Read
hird_thres Gets or sets the "HIRD_Thres[3:0]" bits in the Core LPM Configuration Register. ++ Read/Write
besl_reject Gets or sets the "besl_reject" bit in the Device Control Register. ++ Read/Write
++ ++ Example usage: ++ To get the current mode: ++ cat /sys/devices/lm0/mode ++ ++ To power down the USB: ++ echo 0 > /sys/devices/lm0/buspower ++ */ ++ ++#include "dwc_otg_os_dep.h" ++#include "dwc_os.h" ++#include "dwc_otg_driver.h" ++#include "dwc_otg_attr.h" ++#include "dwc_otg_core_if.h" ++#include "dwc_otg_pcd_if.h" ++#include "dwc_otg_hcd_if.h" ++ ++/* ++ * MACROs for defining sysfs attribute ++ */ ++ ++ ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); \ ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); \ ++ uint32_t val; \ ++ val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ ++ return sprintf (buf, "%s = 0x%x\n", _string_, val); \ ++} ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); \ ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); \ ++ uint32_t set = simple_strtoul(buf, NULL, 16); \ ++ dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\ ++ return count; \ ++} ++ ++ ++/* ++ * MACROs for defining sysfs attribute for 32-bit registers ++ */ ++#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); \ ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); \ ++ uint32_t val; \ ++ val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ ++ return sprintf (buf, "%s = 0x%08x\n", _string_, val); \ ++} ++#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); \ ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); \ ++ uint32_t val = simple_strtoul(buf, NULL, 16); \ ++ dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \ ++ return count; \ ++} ++ ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_,_string_) \ ++DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ ++DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \ ++DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store); ++ ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_,_string_) \ ++DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ ++DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL); ++ ++#define DWC_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_,_addr_,_string_) \ ++DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ ++DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \ ++DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store); ++ ++#define DWC_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_,_addr_,_string_) \ ++DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ ++DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL); ++ ++/** @name Functions for Show/Store of Attributes */ ++/**@{*/ ++ ++/** ++ * Show the register offset of the Register Access. ++ */ ++static ssize_t regoffset_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ return snprintf(buf, sizeof("0xFFFFFFFF\n") + 1, "0x%08x\n", ++ otg_dev->os_dep.reg_offset); ++} ++ ++/** ++ * Set the register offset for the next Register Access Read/Write ++ */ ++static ssize_t regoffset_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ uint32_t offset = simple_strtoul(buf, NULL, 16); ++ if (offset < SZ_256K) { ++ otg_dev->os_dep.reg_offset = offset; ++ } else { ++ dev_err(_dev, "invalid offset\n"); ++ } ++ ++ return count; ++} ++ ++DEVICE_ATTR(regoffset, S_IRUGO | S_IWUSR, regoffset_show, regoffset_store); ++ ++/** ++ * Show the value of the register at the offset in the reg_offset ++ * attribute. ++ */ ++static ssize_t regvalue_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ uint32_t val; ++ volatile uint32_t *addr; ++ ++ if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) { ++ /* Calculate the address */ ++ addr = (uint32_t *) (otg_dev->os_dep.reg_offset + ++ (uint8_t *) otg_dev->os_dep.base); ++ val = DWC_READ_REG32(addr); ++ return snprintf(buf, ++ sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n") + 1, ++ "Reg@0x%06x = 0x%08x\n", otg_dev->os_dep.reg_offset, ++ val); ++ } else { ++ dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->os_dep.reg_offset); ++ return sprintf(buf, "invalid offset\n"); ++ } ++} ++ ++/** ++ * Store the value in the register at the offset in the reg_offset ++ * attribute. ++ * ++ */ ++static ssize_t regvalue_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ volatile uint32_t *addr; ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ //dev_dbg(_dev, "Offset=0x%08x Val=0x%08x\n", otg_dev->reg_offset, val); ++ if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) { ++ /* Calculate the address */ ++ addr = (uint32_t *) (otg_dev->os_dep.reg_offset + ++ (uint8_t *) otg_dev->os_dep.base); ++ DWC_WRITE_REG32(addr, val); ++ } else { ++ dev_err(_dev, "Invalid Register Offset (0x%08x)\n", ++ otg_dev->os_dep.reg_offset); ++ } ++ return count; ++} ++ ++DEVICE_ATTR(regvalue, S_IRUGO | S_IWUSR, regvalue_show, regvalue_store); ++ ++/* ++ * Attributes ++ */ ++DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode, "Mode"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable, "HNPCapable"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, "SRPCapable"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hsic_connect, "HSIC Connect"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(inv_sel_hsic, "Invert Select HSIC"); ++ ++//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(buspower,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode"); ++//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(bussuspend,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected, "Bus Connected"); ++ ++DWC_OTG_DEVICE_ATTR_REG32_RW(gotgctl, 0, "GOTGCTL"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(gusbcfg, ++ &(otg_dev->core_if->core_global_regs->gusbcfg), ++ "GUSBCFG"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(grxfsiz, ++ &(otg_dev->core_if->core_global_regs->grxfsiz), ++ "GRXFSIZ"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz, ++ &(otg_dev->core_if->core_global_regs->gnptxfsiz), ++ "GNPTXFSIZ"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(gpvndctl, ++ &(otg_dev->core_if->core_global_regs->gpvndctl), ++ "GPVNDCTL"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(ggpio, ++ &(otg_dev->core_if->core_global_regs->ggpio), ++ "GGPIO"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(guid, &(otg_dev->core_if->core_global_regs->guid), ++ "GUID"); ++DWC_OTG_DEVICE_ATTR_REG32_RO(gsnpsid, ++ &(otg_dev->core_if->core_global_regs->gsnpsid), ++ "GSNPSID"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed, "Device Speed"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed, "Device Enumeration Speed"); ++ ++DWC_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz, ++ &(otg_dev->core_if->core_global_regs->hptxfsiz), ++ "HPTXFSIZ"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(hprt0, otg_dev->core_if->host_if->hprt0, "HPRT0"); ++ ++/** ++ * @todo Add code to initiate the HNP. ++ */ ++/** ++ * Show the HNP status bit ++ */ ++static ssize_t hnp_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ return sprintf(buf, "HstNegScs = 0x%x\n", ++ dwc_otg_get_hnpstatus(otg_dev->core_if)); ++} ++ ++/** ++ * Set the HNP Request bit ++ */ ++static ssize_t hnp_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ uint32_t in = simple_strtoul(buf, NULL, 16); ++ dwc_otg_set_hnpreq(otg_dev->core_if, in); ++ return count; ++} ++ ++DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store); ++ ++/** ++ * @todo Add code to initiate the SRP. ++ */ ++/** ++ * Show the SRP status bit ++ */ ++static ssize_t srp_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef DWC_HOST_ONLY ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ return sprintf(buf, "SesReqScs = 0x%x\n", ++ dwc_otg_get_srpstatus(otg_dev->core_if)); ++#else ++ return sprintf(buf, "Host Only Mode!\n"); ++#endif ++} ++ ++/** ++ * Set the SRP Request bit ++ */ ++static ssize_t srp_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifndef DWC_HOST_ONLY ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ dwc_otg_pcd_initiate_srp(otg_dev->pcd); ++#endif ++ return count; ++} ++ ++DEVICE_ATTR(srp, 0644, srp_show, srp_store); ++ ++/** ++ * @todo Need to do more for power on/off? ++ */ ++/** ++ * Show the Bus Power status ++ */ ++static ssize_t buspower_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ return sprintf(buf, "Bus Power = 0x%x\n", ++ dwc_otg_get_prtpower(otg_dev->core_if)); ++} ++ ++/** ++ * Set the Bus Power status ++ */ ++static ssize_t buspower_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ uint32_t on = simple_strtoul(buf, NULL, 16); ++ dwc_otg_set_prtpower(otg_dev->core_if, on); ++ return count; ++} ++ ++DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store); ++ ++/** ++ * @todo Need to do more for suspend? ++ */ ++/** ++ * Show the Bus Suspend status ++ */ ++static ssize_t bussuspend_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ return sprintf(buf, "Bus Suspend = 0x%x\n", ++ dwc_otg_get_prtsuspend(otg_dev->core_if)); ++} ++ ++/** ++ * Set the Bus Suspend status ++ */ ++static ssize_t bussuspend_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ uint32_t in = simple_strtoul(buf, NULL, 16); ++ dwc_otg_set_prtsuspend(otg_dev->core_if, in); ++ return count; ++} ++ ++DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store); ++ ++/** ++ * Show the Mode Change Ready Timer status ++ */ ++static ssize_t mode_ch_tim_en_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ return sprintf(buf, "Mode Change Ready Timer Enable = 0x%x\n", ++ dwc_otg_get_mode_ch_tim(otg_dev->core_if)); ++} ++ ++/** ++ * Set the Mode Change Ready Timer status ++ */ ++static ssize_t mode_ch_tim_en_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ uint32_t in = simple_strtoul(buf, NULL, 16); ++ dwc_otg_set_mode_ch_tim(otg_dev->core_if, in); ++ return count; ++} ++ ++DEVICE_ATTR(mode_ch_tim_en, 0644, mode_ch_tim_en_show, mode_ch_tim_en_store); ++ ++/** ++ * Show the value of HFIR Frame Interval bitfield ++ */ ++static ssize_t fr_interval_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ return sprintf(buf, "Frame Interval = 0x%x\n", ++ dwc_otg_get_fr_interval(otg_dev->core_if)); ++} ++ ++/** ++ * Set the HFIR Frame Interval value ++ */ ++static ssize_t fr_interval_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ uint32_t in = simple_strtoul(buf, NULL, 10); ++ dwc_otg_set_fr_interval(otg_dev->core_if, in); ++ return count; ++} ++ ++DEVICE_ATTR(fr_interval, 0644, fr_interval_show, fr_interval_store); ++ ++/** ++ * Show the status of Remote Wakeup. ++ */ ++static ssize_t remote_wakeup_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef DWC_HOST_ONLY ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev =platform_get_drvdata(lm_dev); ++ ++ ++ return sprintf(buf, ++ "Remote Wakeup Sig = %d Enabled = %d LPM Remote Wakeup = %d\n", ++ dwc_otg_get_remotewakesig(otg_dev->core_if), ++ dwc_otg_pcd_get_rmwkup_enable(otg_dev->pcd), ++ dwc_otg_get_lpm_remotewakeenabled(otg_dev->core_if)); ++#else ++ return sprintf(buf, "Host Only Mode!\n"); ++#endif /* DWC_HOST_ONLY */ ++} ++ ++/** ++ * Initiate a remote wakeup of the host. The Device control register ++ * Remote Wakeup Signal bit is written if the PCD Remote wakeup enable ++ * flag is set. ++ * ++ */ ++static ssize_t remote_wakeup_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifndef DWC_HOST_ONLY ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ ++ if (val & 1) { ++ dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 1); ++ } else { ++ dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 0); ++ } ++#endif /* DWC_HOST_ONLY */ ++ return count; ++} ++ ++DEVICE_ATTR(remote_wakeup, S_IRUGO | S_IWUSR, remote_wakeup_show, ++ remote_wakeup_store); ++ ++/** ++ * Show the whether core is hibernated or not. ++ */ ++static ssize_t rem_wakeup_pwrdn_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef DWC_HOST_ONLY ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ if (dwc_otg_get_core_state(otg_dev->core_if)) { ++ DWC_PRINTF("Core is in hibernation\n"); ++ } else { ++ DWC_PRINTF("Core is not in hibernation\n"); ++ } ++#endif /* DWC_HOST_ONLY */ ++ return 0; ++} ++ ++extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int rem_wakeup, int reset); ++ ++/** ++ * Initiate a remote wakeup of the device to exit from hibernation. ++ */ ++static ssize_t rem_wakeup_pwrdn_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifndef DWC_HOST_ONLY ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ dwc_otg_device_hibernation_restore(otg_dev->core_if, 1, 0); ++#endif ++ return count; ++} ++ ++DEVICE_ATTR(rem_wakeup_pwrdn, S_IRUGO | S_IWUSR, rem_wakeup_pwrdn_show, ++ rem_wakeup_pwrdn_store); ++ ++static ssize_t disconnect_us(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++#ifndef DWC_HOST_ONLY ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ DWC_PRINTF("The Passed value is %04x\n", val); ++ ++ dwc_otg_pcd_disconnect_us(otg_dev->pcd, 50); ++ ++#endif /* DWC_HOST_ONLY */ ++ return count; ++} ++ ++DEVICE_ATTR(disconnect_us, S_IWUSR, 0, disconnect_us); ++ ++/** ++ * Dump global registers and either host or device registers (depending on the ++ * current mode of the core). ++ */ ++static ssize_t regdump_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ dwc_otg_dump_global_registers(otg_dev->core_if); ++ if (dwc_otg_is_host_mode(otg_dev->core_if)) { ++ dwc_otg_dump_host_registers(otg_dev->core_if); ++ } else { ++ dwc_otg_dump_dev_registers(otg_dev->core_if); ++ ++ } ++ return sprintf(buf, "Register Dump\n"); ++} ++ ++DEVICE_ATTR(regdump, S_IRUGO | S_IWUSR, regdump_show, 0); ++ ++/** ++ * Dump global registers and either host or device registers (depending on the ++ * current mode of the core). ++ */ ++static ssize_t spramdump_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ dwc_otg_dump_spram(otg_dev->core_if); ++ ++ return sprintf(buf, "SPRAM Dump\n"); ++} ++ ++DEVICE_ATTR(spramdump, S_IRUGO | S_IWUSR, spramdump_show, 0); ++ ++/** ++ * Dump the current hcd state. ++ */ ++static ssize_t hcddump_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef DWC_DEVICE_ONLY ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev =platform_get_drvdata(lm_dev); ++ ++ ++ dwc_otg_hcd_dump_state(otg_dev->hcd); ++#endif /* DWC_DEVICE_ONLY */ ++ return sprintf(buf, "HCD Dump\n"); ++} ++ ++DEVICE_ATTR(hcddump, S_IRUGO | S_IWUSR, hcddump_show, 0); ++ ++/** ++ * Dump the average frame remaining at SOF. This can be used to ++ * determine average interrupt latency. Frame remaining is also shown for ++ * start transfer and two additional sample points. ++ */ ++static ssize_t hcd_frrem_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef DWC_DEVICE_ONLY ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ dwc_otg_hcd_dump_frrem(otg_dev->hcd); ++#endif /* DWC_DEVICE_ONLY */ ++ return sprintf(buf, "HCD Dump Frame Remaining\n"); ++} ++ ++DEVICE_ATTR(hcd_frrem, S_IRUGO | S_IWUSR, hcd_frrem_show, 0); ++ ++/** ++ * Displays the time required to read the GNPTXFSIZ register many times (the ++ * output shows the number of times the register is read). ++ */ ++#define RW_REG_COUNT 10000000 ++#define MSEC_PER_JIFFIE 1000/HZ ++static ssize_t rd_reg_test_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ int i; ++ int time; ++ int start_jiffies; ++ ++ printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n", ++ HZ, MSEC_PER_JIFFIE, loops_per_jiffy); ++ start_jiffies = jiffies; ++ for (i = 0; i < RW_REG_COUNT; i++) { ++ dwc_otg_get_gnptxfsiz(otg_dev->core_if); ++ } ++ time = jiffies - start_jiffies; ++ return sprintf(buf, ++ "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n", ++ RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); ++} ++ ++DEVICE_ATTR(rd_reg_test, S_IRUGO | S_IWUSR, rd_reg_test_show, 0); ++ ++/** ++ * Displays the time required to write the GNPTXFSIZ register many times (the ++ * output shows the number of times the register is written). ++ */ ++static ssize_t wr_reg_test_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ uint32_t reg_val; ++ int i; ++ int time; ++ int start_jiffies; ++ ++ printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n", ++ HZ, MSEC_PER_JIFFIE, loops_per_jiffy); ++ reg_val = dwc_otg_get_gnptxfsiz(otg_dev->core_if); ++ start_jiffies = jiffies; ++ for (i = 0; i < RW_REG_COUNT; i++) { ++ dwc_otg_set_gnptxfsiz(otg_dev->core_if, reg_val); ++ } ++ time = jiffies - start_jiffies; ++ return sprintf(buf, ++ "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n", ++ RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); ++} ++ ++DEVICE_ATTR(wr_reg_test, S_IRUGO | S_IWUSR, wr_reg_test_show, 0); ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ ++/** ++* Show the lpm_response attribute. ++*/ ++static ssize_t lpmresp_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) ++ return sprintf(buf, "** LPM is DISABLED **\n"); ++ ++ if (!dwc_otg_is_device_mode(otg_dev->core_if)) { ++ return sprintf(buf, "** Current mode is not device mode\n"); ++ } ++ return sprintf(buf, "lpm_response = %d\n", ++ dwc_otg_get_lpmresponse(otg_dev->core_if)); ++} ++ ++/** ++* Store the lpm_response attribute. ++*/ ++static ssize_t lpmresp_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ ++ if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ if (!dwc_otg_is_device_mode(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ dwc_otg_set_lpmresponse(otg_dev->core_if, val); ++ return count; ++} ++ ++DEVICE_ATTR(lpm_response, S_IRUGO | S_IWUSR, lpmresp_show, lpmresp_store); ++ ++/** ++* Show the besl_reject attribute. ++*/ ++static ssize_t beslreject_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) ++ return sprintf(buf, "** LPM is DISABLED **\n"); ++ if (!dwc_otg_get_param_besl_enable(otg_dev->core_if)) ++ return sprintf(buf, "** EnBesl is DISABLED **\n"); ++ ++ if (!dwc_otg_is_device_mode(otg_dev->core_if)) { ++ return sprintf(buf, "** Current mode is not device mode\n"); ++ } ++ ++ return sprintf(buf, "besl_reject = %d\n", ++ dwc_otg_get_beslreject(otg_dev->core_if)); ++} ++ ++/** ++* Store the besl_reject attribute. ++*/ ++static ssize_t beslreject_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ ++ if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ if (!dwc_otg_get_param_besl_enable(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ if (!dwc_otg_is_device_mode(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ dwc_otg_set_beslreject(otg_dev->core_if,val); ++ ++ return count; ++} ++ ++DEVICE_ATTR(besl_reject, S_IRUGO | S_IWUSR, beslreject_show, beslreject_store); ++ ++/** ++* Show the hird_thresh attribute. ++*/ ++static ssize_t hirdthresh_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) ++ return sprintf(buf, "** LPM is DISABLED **\n"); ++ ++ if (!dwc_otg_is_device_mode(otg_dev->core_if)) { ++ return sprintf(buf, "** Current mode is not device mode\n"); ++ } ++ ++ return sprintf(buf, "hirdthresh = 0x%x\n", ++ dwc_otg_get_hirdthresh(otg_dev->core_if)); ++} ++ ++/** ++* Store the hird_thresh attribute. ++*/ ++static ssize_t hirdthresh_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ ++ if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ if (!dwc_otg_is_device_mode(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ dwc_otg_set_hirdthresh(otg_dev->core_if,val); ++ ++ return count; ++} ++ ++DEVICE_ATTR(hird_thres, S_IRUGO | S_IWUSR, hirdthresh_show, hirdthresh_store); ++ ++/** ++* Show the sleep_status attribute. ++*/ ++static ssize_t sleepstatus_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ return sprintf(buf, "Sleep Status = %d\n", ++ dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)); ++} ++ ++/** ++ * Store the sleep_status attribure. ++ */ ++static ssize_t sleepstatus_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ dwc_otg_core_if_t *core_if = otg_dev->core_if; ++ ++ if (dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)) { ++ if (dwc_otg_is_host_mode(core_if)) { ++ ++ DWC_PRINTF("Host initiated resume\n"); ++ dwc_otg_set_prtresume(otg_dev->core_if, 1); ++ } ++ } ++ ++ return count; ++} ++ ++DEVICE_ATTR(sleep_status, S_IRUGO | S_IWUSR, sleepstatus_show, ++ sleepstatus_store); ++ ++#endif /* CONFIG_USB_DWC_OTG_LPM_ENABLE */ ++ ++/**@}*/ ++ ++/** ++ * Create the device files ++ */ ++void dwc_otg_attr_create(struct platform_device *dev) ++{ ++ int error; ++ ++ error = device_create_file(&dev->dev, &dev_attr_regoffset); ++ error = device_create_file(&dev->dev, &dev_attr_regvalue); ++ error = device_create_file(&dev->dev, &dev_attr_mode); ++ error = device_create_file(&dev->dev, &dev_attr_hnpcapable); ++ error = device_create_file(&dev->dev, &dev_attr_srpcapable); ++ error = device_create_file(&dev->dev, &dev_attr_hsic_connect); ++ error = device_create_file(&dev->dev, &dev_attr_inv_sel_hsic); ++ error = device_create_file(&dev->dev, &dev_attr_hnp); ++ error = device_create_file(&dev->dev, &dev_attr_srp); ++ error = device_create_file(&dev->dev, &dev_attr_buspower); ++ error = device_create_file(&dev->dev, &dev_attr_bussuspend); ++ error = device_create_file(&dev->dev, &dev_attr_mode_ch_tim_en); ++ error = device_create_file(&dev->dev, &dev_attr_fr_interval); ++ error = device_create_file(&dev->dev, &dev_attr_busconnected); ++ error = device_create_file(&dev->dev, &dev_attr_gotgctl); ++ error = device_create_file(&dev->dev, &dev_attr_gusbcfg); ++ error = device_create_file(&dev->dev, &dev_attr_grxfsiz); ++ error = device_create_file(&dev->dev, &dev_attr_gnptxfsiz); ++ error = device_create_file(&dev->dev, &dev_attr_gpvndctl); ++ error = device_create_file(&dev->dev, &dev_attr_ggpio); ++ error = device_create_file(&dev->dev, &dev_attr_guid); ++ error = device_create_file(&dev->dev, &dev_attr_gsnpsid); ++ error = device_create_file(&dev->dev, &dev_attr_devspeed); ++ error = device_create_file(&dev->dev, &dev_attr_enumspeed); ++ error = device_create_file(&dev->dev, &dev_attr_hptxfsiz); ++ error = device_create_file(&dev->dev, &dev_attr_hprt0); ++ error = device_create_file(&dev->dev, &dev_attr_remote_wakeup); ++ error = device_create_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn); ++ error = device_create_file(&dev->dev, &dev_attr_disconnect_us); ++ error = device_create_file(&dev->dev, &dev_attr_regdump); ++ error = device_create_file(&dev->dev, &dev_attr_spramdump); ++ error = device_create_file(&dev->dev, &dev_attr_hcddump); ++ error = device_create_file(&dev->dev, &dev_attr_hcd_frrem); ++ error = device_create_file(&dev->dev, &dev_attr_rd_reg_test); ++ error = device_create_file(&dev->dev, &dev_attr_wr_reg_test); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ error = device_create_file(&dev->dev, &dev_attr_lpm_response); ++ error = device_create_file(&dev->dev, &dev_attr_sleep_status); ++ error = device_create_file(&dev->dev, &dev_attr_besl_reject); ++ error = device_create_file(&dev->dev, &dev_attr_hird_thres); ++#endif ++} ++ ++/** ++ * Remove the device files ++ */ ++void dwc_otg_attr_remove(struct platform_device *dev ++ ++ ) ++{ ++ device_remove_file(&dev->dev, &dev_attr_regoffset); ++ device_remove_file(&dev->dev, &dev_attr_regvalue); ++ device_remove_file(&dev->dev, &dev_attr_mode); ++ device_remove_file(&dev->dev, &dev_attr_hnpcapable); ++ device_remove_file(&dev->dev, &dev_attr_srpcapable); ++ device_remove_file(&dev->dev, &dev_attr_hsic_connect); ++ device_remove_file(&dev->dev, &dev_attr_inv_sel_hsic); ++ device_remove_file(&dev->dev, &dev_attr_hnp); ++ device_remove_file(&dev->dev, &dev_attr_srp); ++ device_remove_file(&dev->dev, &dev_attr_buspower); ++ device_remove_file(&dev->dev, &dev_attr_bussuspend); ++ device_remove_file(&dev->dev, &dev_attr_mode_ch_tim_en); ++ device_remove_file(&dev->dev, &dev_attr_fr_interval); ++ device_remove_file(&dev->dev, &dev_attr_busconnected); ++ device_remove_file(&dev->dev, &dev_attr_gotgctl); ++ device_remove_file(&dev->dev, &dev_attr_gusbcfg); ++ device_remove_file(&dev->dev, &dev_attr_grxfsiz); ++ device_remove_file(&dev->dev, &dev_attr_gnptxfsiz); ++ device_remove_file(&dev->dev, &dev_attr_gpvndctl); ++ device_remove_file(&dev->dev, &dev_attr_ggpio); ++ device_remove_file(&dev->dev, &dev_attr_guid); ++ device_remove_file(&dev->dev, &dev_attr_gsnpsid); ++ device_remove_file(&dev->dev, &dev_attr_devspeed); ++ device_remove_file(&dev->dev, &dev_attr_enumspeed); ++ device_remove_file(&dev->dev, &dev_attr_hptxfsiz); ++ device_remove_file(&dev->dev, &dev_attr_hprt0); ++ device_remove_file(&dev->dev, &dev_attr_remote_wakeup); ++ device_remove_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn); ++ device_remove_file(&dev->dev, &dev_attr_disconnect_us); ++ device_remove_file(&dev->dev, &dev_attr_regdump); ++ device_remove_file(&dev->dev, &dev_attr_spramdump); ++ device_remove_file(&dev->dev, &dev_attr_hcddump); ++ device_remove_file(&dev->dev, &dev_attr_hcd_frrem); ++ device_remove_file(&dev->dev, &dev_attr_rd_reg_test); ++ device_remove_file(&dev->dev, &dev_attr_wr_reg_test); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ device_remove_file(&dev->dev, &dev_attr_lpm_response); ++ device_remove_file(&dev->dev, &dev_attr_sleep_status); ++ device_remove_file(&dev->dev, &dev_attr_besl_reject); ++ device_remove_file(&dev->dev, &dev_attr_hird_thres); ++#endif ++} +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_attr.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_attr.h +new file mode 100644 +index 0000000..4d43296 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_attr.h +@@ -0,0 +1,78 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.h $ ++ * $Revision: #13 $ ++ * $Date: 2010/06/21 $ ++ * $Change: 1532021 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++#if !defined(__DWC_OTG_ATTR_H__) ++#define __DWC_OTG_ATTR_H__ ++ ++#include ++ ++/** @file ++ * This file contains the interface to the Linux device attributes. ++ */ ++extern struct device_attribute dev_attr_regoffset; ++extern struct device_attribute dev_attr_regvalue; ++ ++extern struct device_attribute dev_attr_mode; ++extern struct device_attribute dev_attr_hnpcapable; ++extern struct device_attribute dev_attr_srpcapable; ++extern struct device_attribute dev_attr_hnp; ++extern struct device_attribute dev_attr_srp; ++extern struct device_attribute dev_attr_buspower; ++extern struct device_attribute dev_attr_bussuspend; ++extern struct device_attribute dev_attr_mode_ch_tim_en; ++extern struct device_attribute dev_attr_fr_interval; ++extern struct device_attribute dev_attr_busconnected; ++extern struct device_attribute dev_attr_gotgctl; ++extern struct device_attribute dev_attr_gusbcfg; ++extern struct device_attribute dev_attr_grxfsiz; ++extern struct device_attribute dev_attr_gnptxfsiz; ++extern struct device_attribute dev_attr_gpvndctl; ++extern struct device_attribute dev_attr_ggpio; ++extern struct device_attribute dev_attr_guid; ++extern struct device_attribute dev_attr_gsnpsid; ++extern struct device_attribute dev_attr_devspeed; ++extern struct device_attribute dev_attr_enumspeed; ++extern struct device_attribute dev_attr_hptxfsiz; ++extern struct device_attribute dev_attr_hprt0; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++extern struct device_attribute dev_attr_lpm_response; ++extern struct device_attribute devi_attr_sleep_status; ++#endif ++ ++void dwc_otg_attr_create(struct platform_device *dev ++ ); ++ ++void dwc_otg_attr_remove(struct platform_device *dev ++ ++ ); ++#endif +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_cfi.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_cfi.c +new file mode 100644 +index 0000000..530a661 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_cfi.c +@@ -0,0 +1,1869 @@ ++/* ========================================================================== ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ * This file contains the most of the CFI(Core Feature Interface) ++ * implementation for the OTG. ++ */ ++ ++#ifdef DWC_UTE_CFI ++ ++#include "dwc_otg_pcd.h" ++#include "dwc_otg_cfi.h" ++ ++/** This definition should actually migrate to the Portability Library */ ++#define DWC_CONSTANT_CPU_TO_LE16(x) (x) ++ ++extern dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex); ++ ++static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen); ++static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen, ++ struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *ctrl_req); ++static int cfi_set_feature_value(struct dwc_otg_pcd *pcd); ++static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req); ++static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req); ++static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req); ++static int cfi_preproc_reset(struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req); ++static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep); ++ ++static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if); ++static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue); ++static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue); ++ ++static uint8_t resize_fifos(dwc_otg_core_if_t * core_if); ++ ++/** This is the header of the all features descriptor */ ++static cfi_all_features_header_t all_props_desc_header = { ++ .wVersion = DWC_CONSTANT_CPU_TO_LE16(0x100), ++ .wCoreID = DWC_CONSTANT_CPU_TO_LE16(CFI_CORE_ID_OTG), ++ .wNumFeatures = DWC_CONSTANT_CPU_TO_LE16(9), ++}; ++ ++/** This is an array of statically allocated feature descriptors */ ++static cfi_feature_desc_header_t prop_descs[] = { ++ ++ /* FT_ID_DMA_MODE */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_MODE), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(1), ++ }, ++ ++ /* FT_ID_DMA_BUFFER_SETUP */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFFER_SETUP), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6), ++ }, ++ ++ /* FT_ID_DMA_BUFF_ALIGN */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFF_ALIGN), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2), ++ }, ++ ++ /* FT_ID_DMA_CONCAT_SETUP */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CONCAT_SETUP), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ //.wDataLength = DWC_CONSTANT_CPU_TO_LE16(6), ++ }, ++ ++ /* FT_ID_DMA_CIRCULAR */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CIRCULAR), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6), ++ }, ++ ++ /* FT_ID_THRESHOLD_SETUP */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_THRESHOLD_SETUP), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6), ++ }, ++ ++ /* FT_ID_DFIFO_DEPTH */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DFIFO_DEPTH), ++ .bmAttributes = CFI_FEATURE_ATTR_RO, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2), ++ }, ++ ++ /* FT_ID_TX_FIFO_DEPTH */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_TX_FIFO_DEPTH), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2), ++ }, ++ ++ /* FT_ID_RX_FIFO_DEPTH */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_RX_FIFO_DEPTH), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2), ++ } ++}; ++ ++/** The table of feature names */ ++cfi_string_t prop_name_table[] = { ++ {FT_ID_DMA_MODE, "dma_mode"}, ++ {FT_ID_DMA_BUFFER_SETUP, "buffer_setup"}, ++ {FT_ID_DMA_BUFF_ALIGN, "buffer_align"}, ++ {FT_ID_DMA_CONCAT_SETUP, "concat_setup"}, ++ {FT_ID_DMA_CIRCULAR, "buffer_circular"}, ++ {FT_ID_THRESHOLD_SETUP, "threshold_setup"}, ++ {FT_ID_DFIFO_DEPTH, "dfifo_depth"}, ++ {FT_ID_TX_FIFO_DEPTH, "txfifo_depth"}, ++ {FT_ID_RX_FIFO_DEPTH, "rxfifo_depth"}, ++ {} ++}; ++ ++/************************************************************************/ ++ ++/** ++ * Returns the name of the feature by its ID ++ * or NULL if no featute ID matches. ++ * ++ */ ++const uint8_t *get_prop_name(uint16_t prop_id, int *len) ++{ ++ cfi_string_t *pstr; ++ *len = 0; ++ ++ for (pstr = prop_name_table; pstr && pstr->s; pstr++) { ++ if (pstr->id == prop_id) { ++ *len = DWC_STRLEN(pstr->s); ++ return pstr->s; ++ } ++ } ++ return NULL; ++} ++ ++/** ++ * This function handles all CFI specific control requests. ++ * ++ * Return a negative value to stall the DCE. ++ */ ++int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl) ++{ ++ int retval = 0; ++ dwc_otg_pcd_ep_t *ep = NULL; ++ cfiobject_t *cfi = pcd->cfi; ++ struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd); ++ uint16_t wLen = DWC_LE16_TO_CPU(&ctrl->wLength); ++ uint16_t wValue = DWC_LE16_TO_CPU(&ctrl->wValue); ++ uint16_t wIndex = DWC_LE16_TO_CPU(&ctrl->wIndex); ++ uint32_t regaddr = 0; ++ uint32_t regval = 0; ++ ++ /* Save this Control Request in the CFI object. ++ * The data field will be assigned in the data stage completion CB function. ++ */ ++ cfi->ctrl_req = *ctrl; ++ cfi->ctrl_req.data = NULL; ++ ++ cfi->need_gadget_att = 0; ++ cfi->need_status_in_complete = 0; ++ ++ switch (ctrl->bRequest) { ++ case VEN_CORE_GET_FEATURES: ++ retval = cfi_core_features_buf(cfi->buf_in.buf, CFI_IN_BUF_LEN); ++ if (retval >= 0) { ++ //dump_msg(cfi->buf_in.buf, retval); ++ ep = &pcd->ep0; ++ ++ retval = min((uint16_t) retval, wLen); ++ /* Transfer this buffer to the host through the EP0-IN EP */ ++ ep->dwc_ep.dma_addr = cfi->buf_in.addr; ++ ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf; ++ ep->dwc_ep.xfer_buff = cfi->buf_in.buf; ++ ep->dwc_ep.xfer_len = retval; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); ++ } ++ retval = 0; ++ break; ++ ++ case VEN_CORE_GET_FEATURE: ++ CFI_INFO("VEN_CORE_GET_FEATURE\n"); ++ retval = cfi_get_feature_value(cfi->buf_in.buf, CFI_IN_BUF_LEN, ++ pcd, ctrl); ++ if (retval >= 0) { ++ ep = &pcd->ep0; ++ ++ retval = min((uint16_t) retval, wLen); ++ /* Transfer this buffer to the host through the EP0-IN EP */ ++ ep->dwc_ep.dma_addr = cfi->buf_in.addr; ++ ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf; ++ ep->dwc_ep.xfer_buff = cfi->buf_in.buf; ++ ep->dwc_ep.xfer_len = retval; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); ++ } ++ CFI_INFO("VEN_CORE_GET_FEATURE=%d\n", retval); ++ dump_msg(cfi->buf_in.buf, retval); ++ break; ++ ++ case VEN_CORE_SET_FEATURE: ++ CFI_INFO("VEN_CORE_SET_FEATURE\n"); ++ /* Set up an XFER to get the data stage of the control request, ++ * which is the new value of the feature to be modified. ++ */ ++ ep = &pcd->ep0; ++ ep->dwc_ep.is_in = 0; ++ ep->dwc_ep.dma_addr = cfi->buf_out.addr; ++ ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf; ++ ep->dwc_ep.xfer_buff = cfi->buf_out.buf; ++ ep->dwc_ep.xfer_len = wLen; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ /* Read the control write's data stage */ ++ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); ++ retval = 0; ++ break; ++ ++ case VEN_CORE_RESET_FEATURES: ++ CFI_INFO("VEN_CORE_RESET_FEATURES\n"); ++ cfi->need_gadget_att = 1; ++ cfi->need_status_in_complete = 1; ++ retval = cfi_preproc_reset(pcd, ctrl); ++ CFI_INFO("VEN_CORE_RESET_FEATURES = (%d)\n", retval); ++ break; ++ ++ case VEN_CORE_ACTIVATE_FEATURES: ++ CFI_INFO("VEN_CORE_ACTIVATE_FEATURES\n"); ++ break; ++ ++ case VEN_CORE_READ_REGISTER: ++ CFI_INFO("VEN_CORE_READ_REGISTER\n"); ++ /* wValue optionally contains the HI WORD of the register offset and ++ * wIndex contains the LOW WORD of the register offset ++ */ ++ if (wValue == 0) { ++ /* @TODO - MAS - fix the access to the base field */ ++ regaddr = 0; ++ //regaddr = (uint32_t) pcd->otg_dev->os_dep.base; ++ //GET_CORE_IF(pcd)->co ++ regaddr |= wIndex; ++ } else { ++ regaddr = (wValue << 16) | wIndex; ++ } ++ ++ /* Read a 32-bit value of the memory at the regaddr */ ++ regval = DWC_READ_REG32((uint32_t *) regaddr); ++ ++ ep = &pcd->ep0; ++ dwc_memcpy(cfi->buf_in.buf, ®val, sizeof(uint32_t)); ++ ep->dwc_ep.is_in = 1; ++ ep->dwc_ep.dma_addr = cfi->buf_in.addr; ++ ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf; ++ ep->dwc_ep.xfer_buff = cfi->buf_in.buf; ++ ep->dwc_ep.xfer_len = wLen; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); ++ cfi->need_gadget_att = 0; ++ retval = 0; ++ break; ++ ++ case VEN_CORE_WRITE_REGISTER: ++ CFI_INFO("VEN_CORE_WRITE_REGISTER\n"); ++ /* Set up an XFER to get the data stage of the control request, ++ * which is the new value of the register to be modified. ++ */ ++ ep = &pcd->ep0; ++ ep->dwc_ep.is_in = 0; ++ ep->dwc_ep.dma_addr = cfi->buf_out.addr; ++ ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf; ++ ep->dwc_ep.xfer_buff = cfi->buf_out.buf; ++ ep->dwc_ep.xfer_len = wLen; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ /* Read the control write's data stage */ ++ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); ++ retval = 0; ++ break; ++ ++ default: ++ retval = -DWC_E_NOT_SUPPORTED; ++ break; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function prepares the core features descriptors and copies its ++ * raw representation into the buffer . ++ * ++ * The buffer structure is as follows: ++ * all_features_header (8 bytes) ++ * features_#1 (8 bytes + feature name string length) ++ * features_#2 (8 bytes + feature name string length) ++ * ..... ++ * features_#n - where n=the total count of feature descriptors ++ */ ++static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen) ++{ ++ cfi_feature_desc_header_t *prop_hdr = prop_descs; ++ cfi_feature_desc_header_t *prop; ++ cfi_all_features_header_t *all_props_hdr = &all_props_desc_header; ++ cfi_all_features_header_t *tmp; ++ uint8_t *tmpbuf = buf; ++ const uint8_t *pname = NULL; ++ int i, j, namelen = 0, totlen; ++ ++ /* Prepare and copy the core features into the buffer */ ++ CFI_INFO("%s:\n", __func__); ++ ++ tmp = (cfi_all_features_header_t *) tmpbuf; ++ *tmp = *all_props_hdr; ++ tmpbuf += CFI_ALL_FEATURES_HDR_LEN; ++ ++ j = sizeof(prop_descs) / sizeof(cfi_all_features_header_t); ++ for (i = 0; i < j; i++, prop_hdr++) { ++ pname = get_prop_name(prop_hdr->wFeatureID, &namelen); ++ prop = (cfi_feature_desc_header_t *) tmpbuf; ++ *prop = *prop_hdr; ++ ++ prop->bNameLen = namelen; ++ prop->wLength = ++ DWC_CONSTANT_CPU_TO_LE16(CFI_FEATURE_DESC_HDR_LEN + ++ namelen); ++ ++ tmpbuf += CFI_FEATURE_DESC_HDR_LEN; ++ dwc_memcpy(tmpbuf, pname, namelen); ++ tmpbuf += namelen; ++ } ++ ++ totlen = tmpbuf - buf; ++ ++ if (totlen > 0) { ++ tmp = (cfi_all_features_header_t *) buf; ++ tmp->wTotalLen = DWC_CONSTANT_CPU_TO_LE16(totlen); ++ } ++ ++ return totlen; ++} ++ ++/** ++ * This function releases all the dynamic memory in the CFI object. ++ */ ++static void cfi_release(cfiobject_t * cfiobj) ++{ ++ cfi_ep_t *cfiep; ++ dwc_list_link_t *tmp; ++ ++ CFI_INFO("%s\n", __func__); ++ ++ if (cfiobj->buf_in.buf) { ++ DWC_DMA_FREE(CFI_IN_BUF_LEN, cfiobj->buf_in.buf, ++ cfiobj->buf_in.addr); ++ cfiobj->buf_in.buf = NULL; ++ } ++ ++ if (cfiobj->buf_out.buf) { ++ DWC_DMA_FREE(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf, ++ cfiobj->buf_out.addr); ++ cfiobj->buf_out.buf = NULL; ++ } ++ ++ /* Free the Buffer Setup values for each EP */ ++ //list_for_each_entry(cfiep, &cfiobj->active_eps, lh) { ++ DWC_LIST_FOREACH(tmp, &cfiobj->active_eps) { ++ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ cfi_free_ep_bs_dyn_data(cfiep); ++ } ++} ++ ++/** ++ * This function frees the dynamically allocated EP buffer setup data. ++ */ ++static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep) ++{ ++ if (cfiep->bm_sg) { ++ DWC_FREE(cfiep->bm_sg); ++ cfiep->bm_sg = NULL; ++ } ++ ++ if (cfiep->bm_align) { ++ DWC_FREE(cfiep->bm_align); ++ cfiep->bm_align = NULL; ++ } ++ ++ if (cfiep->bm_concat) { ++ if (NULL != cfiep->bm_concat->wTxBytes) { ++ DWC_FREE(cfiep->bm_concat->wTxBytes); ++ cfiep->bm_concat->wTxBytes = NULL; ++ } ++ DWC_FREE(cfiep->bm_concat); ++ cfiep->bm_concat = NULL; ++ } ++} ++ ++/** ++ * This function initializes the default values of the features ++ * for a specific endpoint and should be called only once when ++ * the EP is enabled first time. ++ */ ++static int cfi_ep_init_defaults(struct dwc_otg_pcd *pcd, cfi_ep_t * cfiep) ++{ ++ int retval = 0; ++ ++ cfiep->bm_sg = DWC_ALLOC(sizeof(ddma_sg_buffer_setup_t)); ++ if (NULL == cfiep->bm_sg) { ++ CFI_INFO("Failed to allocate memory for SG feature value\n"); ++ return -DWC_E_NO_MEMORY; ++ } ++ dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t)); ++ ++ /* For the Concatenation feature's default value we do not allocate ++ * memory for the wTxBytes field - it will be done in the set_feature_value ++ * request handler. ++ */ ++ cfiep->bm_concat = DWC_ALLOC(sizeof(ddma_concat_buffer_setup_t)); ++ if (NULL == cfiep->bm_concat) { ++ CFI_INFO ++ ("Failed to allocate memory for CONCATENATION feature value\n"); ++ DWC_FREE(cfiep->bm_sg); ++ return -DWC_E_NO_MEMORY; ++ } ++ dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t)); ++ ++ cfiep->bm_align = DWC_ALLOC(sizeof(ddma_align_buffer_setup_t)); ++ if (NULL == cfiep->bm_align) { ++ CFI_INFO ++ ("Failed to allocate memory for Alignment feature value\n"); ++ DWC_FREE(cfiep->bm_sg); ++ DWC_FREE(cfiep->bm_concat); ++ return -DWC_E_NO_MEMORY; ++ } ++ dwc_memset(cfiep->bm_align, 0, sizeof(ddma_align_buffer_setup_t)); ++ ++ return retval; ++} ++ ++/** ++ * The callback function that notifies the CFI on the activation of ++ * an endpoint in the PCD. The following steps are done in this function: ++ * ++ * Create a dynamically allocated cfi_ep_t object (a CFI wrapper to the PCD's ++ * active endpoint) ++ * Create MAX_DMA_DESCS_PER_EP count DMA Descriptors for the EP ++ * Set the Buffer Mode to standard ++ * Initialize the default values for all EP modes (SG, Circular, Concat, Align) ++ * Add the cfi_ep_t object to the list of active endpoints in the CFI object ++ */ ++static int cfi_ep_enable(struct cfiobject *cfi, struct dwc_otg_pcd *pcd, ++ struct dwc_otg_pcd_ep *ep) ++{ ++ cfi_ep_t *cfiep; ++ int retval = -DWC_E_NOT_SUPPORTED; ++ ++ CFI_INFO("%s: epname=%s; epnum=0x%02x\n", __func__, ++ "EP_" /*ep->ep.name */ , ep->desc->bEndpointAddress); ++ /* MAS - Check whether this endpoint already is in the list */ ++ cfiep = get_cfi_ep_by_pcd_ep(cfi, ep); ++ ++ if (NULL == cfiep) { ++ /* Allocate a cfi_ep_t object */ ++ cfiep = DWC_ALLOC(sizeof(cfi_ep_t)); ++ if (NULL == cfiep) { ++ CFI_INFO ++ ("Unable to allocate memory for in function %s\n", ++ __func__); ++ return -DWC_E_NO_MEMORY; ++ } ++ dwc_memset(cfiep, 0, sizeof(cfi_ep_t)); ++ ++ /* Save the dwc_otg_pcd_ep pointer in the cfiep object */ ++ cfiep->ep = ep; ++ ++ /* Allocate the DMA Descriptors chain of MAX_DMA_DESCS_PER_EP count */ ++ ep->dwc_ep.descs = ++ DWC_DMA_ALLOC(MAX_DMA_DESCS_PER_EP * ++ sizeof(dwc_otg_dma_desc_t), ++ &ep->dwc_ep.descs_dma_addr); ++ ++ if (NULL == ep->dwc_ep.descs) { ++ DWC_FREE(cfiep); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ DWC_LIST_INIT(&cfiep->lh); ++ ++ /* Set the buffer mode to BM_STANDARD. It will be modified ++ * when building descriptors for a specific buffer mode */ ++ ep->dwc_ep.buff_mode = BM_STANDARD; ++ ++ /* Create and initialize the default values for this EP's Buffer modes */ ++ if ((retval = cfi_ep_init_defaults(pcd, cfiep)) < 0) ++ return retval; ++ ++ /* Add the cfi_ep_t object to the CFI object's list of active endpoints */ ++ DWC_LIST_INSERT_TAIL(&cfi->active_eps, &cfiep->lh); ++ retval = 0; ++ } else { /* The sought EP already is in the list */ ++ CFI_INFO("%s: The sought EP already is in the list\n", ++ __func__); ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function is called when the data stage of a 3-stage Control Write request ++ * is complete. ++ * ++ */ ++static int cfi_ctrl_write_complete(struct cfiobject *cfi, ++ struct dwc_otg_pcd *pcd) ++{ ++ uint32_t addr, reg_value; ++ uint16_t wIndex, wValue; ++ uint8_t bRequest; ++ uint8_t *buf = cfi->buf_out.buf; ++ //struct usb_ctrlrequest *ctrl_req = &cfi->ctrl_req_saved; ++ struct cfi_usb_ctrlrequest *ctrl_req = &cfi->ctrl_req; ++ int retval = -DWC_E_NOT_SUPPORTED; ++ ++ CFI_INFO("%s\n", __func__); ++ ++ bRequest = ctrl_req->bRequest; ++ wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex); ++ wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue); ++ ++ /* ++ * Save the pointer to the data stage in the ctrl_req's field. ++ * The request should be already saved in the command stage by now. ++ */ ++ ctrl_req->data = cfi->buf_out.buf; ++ cfi->need_status_in_complete = 0; ++ cfi->need_gadget_att = 0; ++ ++ switch (bRequest) { ++ case VEN_CORE_WRITE_REGISTER: ++ /* The buffer contains raw data of the new value for the register */ ++ reg_value = *((uint32_t *) buf); ++ if (wValue == 0) { ++ addr = 0; ++ //addr = (uint32_t) pcd->otg_dev->os_dep.base; ++ addr += wIndex; ++ } else { ++ addr = (wValue << 16) | wIndex; ++ } ++ ++ //writel(reg_value, addr); ++ ++ retval = 0; ++ cfi->need_status_in_complete = 1; ++ break; ++ ++ case VEN_CORE_SET_FEATURE: ++ /* The buffer contains raw data of the new value of the feature */ ++ retval = cfi_set_feature_value(pcd); ++ if (retval < 0) ++ return retval; ++ ++ cfi->need_status_in_complete = 1; ++ break; ++ ++ default: ++ break; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function builds the DMA descriptors for the SG buffer mode. ++ */ ++static void cfi_build_sg_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, ++ dwc_otg_pcd_request_t * req) ++{ ++ struct dwc_otg_pcd_ep *ep = cfiep->ep; ++ ddma_sg_buffer_setup_t *sgval = cfiep->bm_sg; ++ struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs; ++ struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs; ++ dma_addr_t buff_addr = req->dma; ++ int i; ++ uint32_t txsize, off; ++ ++ txsize = sgval->wSize; ++ off = sgval->bOffset; ++ ++// CFI_INFO("%s: %s TXSIZE=0x%08x; OFFSET=0x%08x\n", ++// __func__, cfiep->ep->ep.name, txsize, off); ++ ++ for (i = 0; i < sgval->bCount; i++) { ++ desc->status.b.bs = BS_HOST_BUSY; ++ desc->buf = buff_addr; ++ desc->status.b.l = 0; ++ desc->status.b.ioc = 0; ++ desc->status.b.sp = 0; ++ desc->status.b.bytes = txsize; ++ desc->status.b.bs = BS_HOST_READY; ++ ++ /* Set the next address of the buffer */ ++ buff_addr += txsize + off; ++ desc_last = desc; ++ desc++; ++ } ++ ++ /* Set the last, ioc and sp bits on the Last DMA Descriptor */ ++ desc_last->status.b.l = 1; ++ desc_last->status.b.ioc = 1; ++ desc_last->status.b.sp = ep->dwc_ep.sent_zlp; ++ /* Save the last DMA descriptor pointer */ ++ cfiep->dma_desc_last = desc_last; ++ cfiep->desc_count = sgval->bCount; ++} ++ ++/** ++ * This function builds the DMA descriptors for the Concatenation buffer mode. ++ */ ++static void cfi_build_concat_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, ++ dwc_otg_pcd_request_t * req) ++{ ++ struct dwc_otg_pcd_ep *ep = cfiep->ep; ++ ddma_concat_buffer_setup_t *concatval = cfiep->bm_concat; ++ struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs; ++ struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs; ++ dma_addr_t buff_addr = req->dma; ++ int i; ++ uint16_t *txsize; ++ ++ txsize = concatval->wTxBytes; ++ ++ for (i = 0; i < concatval->hdr.bDescCount; i++) { ++ desc->buf = buff_addr; ++ desc->status.b.bs = BS_HOST_BUSY; ++ desc->status.b.l = 0; ++ desc->status.b.ioc = 0; ++ desc->status.b.sp = 0; ++ desc->status.b.bytes = *txsize; ++ desc->status.b.bs = BS_HOST_READY; ++ ++ txsize++; ++ /* Set the next address of the buffer */ ++ buff_addr += UGETW(ep->desc->wMaxPacketSize); ++ desc_last = desc; ++ desc++; ++ } ++ ++ /* Set the last, ioc and sp bits on the Last DMA Descriptor */ ++ desc_last->status.b.l = 1; ++ desc_last->status.b.ioc = 1; ++ desc_last->status.b.sp = ep->dwc_ep.sent_zlp; ++ cfiep->dma_desc_last = desc_last; ++ cfiep->desc_count = concatval->hdr.bDescCount; ++} ++ ++/** ++ * This function builds the DMA descriptors for the Circular buffer mode ++ */ ++static void cfi_build_circ_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, ++ dwc_otg_pcd_request_t * req) ++{ ++ /* @todo: MAS - add implementation when this feature needs to be tested */ ++} ++ ++/** ++ * This function builds the DMA descriptors for the Alignment buffer mode ++ */ ++static void cfi_build_align_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, ++ dwc_otg_pcd_request_t * req) ++{ ++ struct dwc_otg_pcd_ep *ep = cfiep->ep; ++ ddma_align_buffer_setup_t *alignval = cfiep->bm_align; ++ struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs; ++ dma_addr_t buff_addr = req->dma; ++ ++ desc->status.b.bs = BS_HOST_BUSY; ++ desc->status.b.l = 1; ++ desc->status.b.ioc = 1; ++ desc->status.b.sp = ep->dwc_ep.sent_zlp; ++ desc->status.b.bytes = req->length; ++ /* Adjust the buffer alignment */ ++ desc->buf = (buff_addr + alignval->bAlign); ++ desc->status.b.bs = BS_HOST_READY; ++ cfiep->dma_desc_last = desc; ++ cfiep->desc_count = 1; ++} ++ ++/** ++ * This function builds the DMA descriptors chain for different modes of the ++ * buffer setup of an endpoint. ++ */ ++static void cfi_build_descriptors(struct cfiobject *cfi, ++ struct dwc_otg_pcd *pcd, ++ struct dwc_otg_pcd_ep *ep, ++ dwc_otg_pcd_request_t * req) ++{ ++ cfi_ep_t *cfiep; ++ ++ /* Get the cfiep by the dwc_otg_pcd_ep */ ++ cfiep = get_cfi_ep_by_pcd_ep(cfi, ep); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Unable to find a matching active endpoint\n", ++ __func__); ++ return; ++ } ++ ++ cfiep->xfer_len = req->length; ++ ++ /* Iterate through all the DMA descriptors */ ++ switch (cfiep->ep->dwc_ep.buff_mode) { ++ case BM_SG: ++ cfi_build_sg_descs(cfi, cfiep, req); ++ break; ++ ++ case BM_CONCAT: ++ cfi_build_concat_descs(cfi, cfiep, req); ++ break; ++ ++ case BM_CIRCULAR: ++ cfi_build_circ_descs(cfi, cfiep, req); ++ break; ++ ++ case BM_ALIGN: ++ cfi_build_align_descs(cfi, cfiep, req); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++/** ++ * Allocate DMA buffer for different Buffer modes. ++ */ ++static void *cfi_ep_alloc_buf(struct cfiobject *cfi, struct dwc_otg_pcd *pcd, ++ struct dwc_otg_pcd_ep *ep, dma_addr_t * dma, ++ unsigned size, gfp_t flags) ++{ ++ return DWC_DMA_ALLOC(size, dma); ++} ++ ++/** ++ * This function initializes the CFI object. ++ */ ++int init_cfi(cfiobject_t * cfiobj) ++{ ++ CFI_INFO("%s\n", __func__); ++ ++ /* Allocate a buffer for IN XFERs */ ++ cfiobj->buf_in.buf = ++ DWC_DMA_ALLOC(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr); ++ if (NULL == cfiobj->buf_in.buf) { ++ CFI_INFO("Unable to allocate buffer for INs\n"); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ /* Allocate a buffer for OUT XFERs */ ++ cfiobj->buf_out.buf = ++ DWC_DMA_ALLOC(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr); ++ if (NULL == cfiobj->buf_out.buf) { ++ CFI_INFO("Unable to allocate buffer for OUT\n"); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ /* Initialize the callback function pointers */ ++ cfiobj->ops.release = cfi_release; ++ cfiobj->ops.ep_enable = cfi_ep_enable; ++ cfiobj->ops.ctrl_write_complete = cfi_ctrl_write_complete; ++ cfiobj->ops.build_descriptors = cfi_build_descriptors; ++ cfiobj->ops.ep_alloc_buf = cfi_ep_alloc_buf; ++ ++ /* Initialize the list of active endpoints in the CFI object */ ++ DWC_LIST_INIT(&cfiobj->active_eps); ++ ++ return 0; ++} ++ ++/** ++ * This function reads the required feature's current value into the buffer ++ * ++ * @retval: Returns negative as error, or the data length of the feature ++ */ ++static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen, ++ struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *ctrl_req) ++{ ++ int retval = -DWC_E_NOT_SUPPORTED; ++ struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd); ++ uint16_t dfifo, rxfifo, txfifo; ++ ++ switch (ctrl_req->wIndex) { ++ /* Whether the DDMA is enabled or not */ ++ case FT_ID_DMA_MODE: ++ *buf = (coreif->dma_enable && coreif->dma_desc_enable) ? 1 : 0; ++ retval = 1; ++ break; ++ ++ case FT_ID_DMA_BUFFER_SETUP: ++ retval = cfi_ep_get_sg_val(buf, pcd, ctrl_req); ++ break; ++ ++ case FT_ID_DMA_BUFF_ALIGN: ++ retval = cfi_ep_get_align_val(buf, pcd, ctrl_req); ++ break; ++ ++ case FT_ID_DMA_CONCAT_SETUP: ++ retval = cfi_ep_get_concat_val(buf, pcd, ctrl_req); ++ break; ++ ++ case FT_ID_DMA_CIRCULAR: ++ CFI_INFO("GetFeature value (FT_ID_DMA_CIRCULAR)\n"); ++ break; ++ ++ case FT_ID_THRESHOLD_SETUP: ++ CFI_INFO("GetFeature value (FT_ID_THRESHOLD_SETUP)\n"); ++ break; ++ ++ case FT_ID_DFIFO_DEPTH: ++ dfifo = get_dfifo_size(coreif); ++ *((uint16_t *) buf) = dfifo; ++ retval = sizeof(uint16_t); ++ break; ++ ++ case FT_ID_TX_FIFO_DEPTH: ++ retval = get_txfifo_size(pcd, ctrl_req->wValue); ++ if (retval >= 0) { ++ txfifo = retval; ++ *((uint16_t *) buf) = txfifo; ++ retval = sizeof(uint16_t); ++ } ++ break; ++ ++ case FT_ID_RX_FIFO_DEPTH: ++ retval = get_rxfifo_size(coreif, ctrl_req->wValue); ++ if (retval >= 0) { ++ rxfifo = retval; ++ *((uint16_t *) buf) = rxfifo; ++ retval = sizeof(uint16_t); ++ } ++ break; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function resets the SG for the specified EP to its default value ++ */ ++static int cfi_reset_sg_val(cfi_ep_t * cfiep) ++{ ++ dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t)); ++ return 0; ++} ++ ++/** ++ * This function resets the Alignment for the specified EP to its default value ++ */ ++static int cfi_reset_align_val(cfi_ep_t * cfiep) ++{ ++ dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t)); ++ return 0; ++} ++ ++/** ++ * This function resets the Concatenation for the specified EP to its default value ++ * This function will also set the value of the wTxBytes field to NULL after ++ * freeing the memory previously allocated for this field. ++ */ ++static int cfi_reset_concat_val(cfi_ep_t * cfiep) ++{ ++ /* First we need to free the wTxBytes field */ ++ if (cfiep->bm_concat->wTxBytes) { ++ DWC_FREE(cfiep->bm_concat->wTxBytes); ++ cfiep->bm_concat->wTxBytes = NULL; ++ } ++ ++ dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t)); ++ return 0; ++} ++ ++/** ++ * This function resets all the buffer setups of the specified endpoint ++ */ ++static int cfi_ep_reset_all_setup_vals(cfi_ep_t * cfiep) ++{ ++ cfi_reset_sg_val(cfiep); ++ cfi_reset_align_val(cfiep); ++ cfi_reset_concat_val(cfiep); ++ return 0; ++} ++ ++static int cfi_handle_reset_fifo_val(struct dwc_otg_pcd *pcd, uint8_t ep_addr, ++ uint8_t rx_rst, uint8_t tx_rst) ++{ ++ int retval = -DWC_E_INVALID; ++ uint16_t tx_siz[15]; ++ uint16_t rx_siz = 0; ++ dwc_otg_pcd_ep_t *ep = NULL; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params; ++ ++ if (rx_rst) { ++ rx_siz = params->dev_rx_fifo_size; ++ params->dev_rx_fifo_size = GET_CORE_IF(pcd)->init_rxfsiz; ++ } ++ ++ if (tx_rst) { ++ if (ep_addr == 0) { ++ int i; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ tx_siz[i] = ++ core_if->core_params->dev_tx_fifo_size[i]; ++ core_if->core_params->dev_tx_fifo_size[i] = ++ core_if->init_txfsiz[i]; ++ } ++ } else { ++ ++ ep = get_ep_by_addr(pcd, ep_addr); ++ ++ if (NULL == ep) { ++ CFI_INFO ++ ("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, ep_addr); ++ return -DWC_E_INVALID; ++ } ++ ++ tx_siz[0] = ++ params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - ++ 1]; ++ params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = ++ GET_CORE_IF(pcd)->init_txfsiz[ep-> ++ dwc_ep.tx_fifo_num - ++ 1]; ++ } ++ } ++ ++ if (resize_fifos(GET_CORE_IF(pcd))) { ++ retval = 0; ++ } else { ++ CFI_INFO ++ ("%s: Error resetting the feature Reset All(FIFO size)\n", ++ __func__); ++ if (rx_rst) { ++ params->dev_rx_fifo_size = rx_siz; ++ } ++ ++ if (tx_rst) { ++ if (ep_addr == 0) { ++ int i; ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++ i++) { ++ core_if-> ++ core_params->dev_tx_fifo_size[i] = ++ tx_siz[i]; ++ } ++ } else { ++ params->dev_tx_fifo_size[ep-> ++ dwc_ep.tx_fifo_num - ++ 1] = tx_siz[0]; ++ } ++ } ++ retval = -DWC_E_INVALID; ++ } ++ return retval; ++} ++ ++static int cfi_handle_reset_all(struct dwc_otg_pcd *pcd, uint8_t addr) ++{ ++ int retval = 0; ++ cfi_ep_t *cfiep; ++ cfiobject_t *cfi = pcd->cfi; ++ dwc_list_link_t *tmp; ++ ++ retval = cfi_handle_reset_fifo_val(pcd, addr, 1, 1); ++ if (retval < 0) { ++ return retval; ++ } ++ ++ /* If the EP address is known then reset the features for only that EP */ ++ if (addr) { ++ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Error getting the EP address 0x%02x\n", ++ __func__, addr); ++ return -DWC_E_INVALID; ++ } ++ retval = cfi_ep_reset_all_setup_vals(cfiep); ++ cfiep->ep->dwc_ep.buff_mode = BM_STANDARD; ++ } ++ /* Otherwise (wValue == 0), reset all features of all EP's */ ++ else { ++ /* Traverse all the active EP's and reset the feature(s) value(s) */ ++ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { ++ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { ++ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ retval = cfi_ep_reset_all_setup_vals(cfiep); ++ cfiep->ep->dwc_ep.buff_mode = BM_STANDARD; ++ if (retval < 0) { ++ CFI_INFO ++ ("%s: Error resetting the feature Reset All\n", ++ __func__); ++ return retval; ++ } ++ } ++ } ++ return retval; ++} ++ ++static int cfi_handle_reset_dma_buff_setup(struct dwc_otg_pcd *pcd, ++ uint8_t addr) ++{ ++ int retval = 0; ++ cfi_ep_t *cfiep; ++ cfiobject_t *cfi = pcd->cfi; ++ dwc_list_link_t *tmp; ++ ++ /* If the EP address is known then reset the features for only that EP */ ++ if (addr) { ++ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Error getting the EP address 0x%02x\n", ++ __func__, addr); ++ return -DWC_E_INVALID; ++ } ++ retval = cfi_reset_sg_val(cfiep); ++ } ++ /* Otherwise (wValue == 0), reset all features of all EP's */ ++ else { ++ /* Traverse all the active EP's and reset the feature(s) value(s) */ ++ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { ++ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { ++ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ retval = cfi_reset_sg_val(cfiep); ++ if (retval < 0) { ++ CFI_INFO ++ ("%s: Error resetting the feature Buffer Setup\n", ++ __func__); ++ return retval; ++ } ++ } ++ } ++ return retval; ++} ++ ++static int cfi_handle_reset_concat_val(struct dwc_otg_pcd *pcd, uint8_t addr) ++{ ++ int retval = 0; ++ cfi_ep_t *cfiep; ++ cfiobject_t *cfi = pcd->cfi; ++ dwc_list_link_t *tmp; ++ ++ /* If the EP address is known then reset the features for only that EP */ ++ if (addr) { ++ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Error getting the EP address 0x%02x\n", ++ __func__, addr); ++ return -DWC_E_INVALID; ++ } ++ retval = cfi_reset_concat_val(cfiep); ++ } ++ /* Otherwise (wValue == 0), reset all features of all EP's */ ++ else { ++ /* Traverse all the active EP's and reset the feature(s) value(s) */ ++ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { ++ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { ++ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ retval = cfi_reset_concat_val(cfiep); ++ if (retval < 0) { ++ CFI_INFO ++ ("%s: Error resetting the feature Concatenation Value\n", ++ __func__); ++ return retval; ++ } ++ } ++ } ++ return retval; ++} ++ ++static int cfi_handle_reset_align_val(struct dwc_otg_pcd *pcd, uint8_t addr) ++{ ++ int retval = 0; ++ cfi_ep_t *cfiep; ++ cfiobject_t *cfi = pcd->cfi; ++ dwc_list_link_t *tmp; ++ ++ /* If the EP address is known then reset the features for only that EP */ ++ if (addr) { ++ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Error getting the EP address 0x%02x\n", ++ __func__, addr); ++ return -DWC_E_INVALID; ++ } ++ retval = cfi_reset_align_val(cfiep); ++ } ++ /* Otherwise (wValue == 0), reset all features of all EP's */ ++ else { ++ /* Traverse all the active EP's and reset the feature(s) value(s) */ ++ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { ++ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { ++ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ retval = cfi_reset_align_val(cfiep); ++ if (retval < 0) { ++ CFI_INFO ++ ("%s: Error resetting the feature Aliignment Value\n", ++ __func__); ++ return retval; ++ } ++ } ++ } ++ return retval; ++ ++} ++ ++static int cfi_preproc_reset(struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req) ++{ ++ int retval = 0; ++ ++ switch (req->wIndex) { ++ case 0: ++ /* Reset all features */ ++ retval = cfi_handle_reset_all(pcd, req->wValue & 0xff); ++ break; ++ ++ case FT_ID_DMA_BUFFER_SETUP: ++ /* Reset the SG buffer setup */ ++ retval = ++ cfi_handle_reset_dma_buff_setup(pcd, req->wValue & 0xff); ++ break; ++ ++ case FT_ID_DMA_CONCAT_SETUP: ++ /* Reset the Concatenation buffer setup */ ++ retval = cfi_handle_reset_concat_val(pcd, req->wValue & 0xff); ++ break; ++ ++ case FT_ID_DMA_BUFF_ALIGN: ++ /* Reset the Alignment buffer setup */ ++ retval = cfi_handle_reset_align_val(pcd, req->wValue & 0xff); ++ break; ++ ++ case FT_ID_TX_FIFO_DEPTH: ++ retval = ++ cfi_handle_reset_fifo_val(pcd, req->wValue & 0xff, 0, 1); ++ pcd->cfi->need_gadget_att = 0; ++ break; ++ ++ case FT_ID_RX_FIFO_DEPTH: ++ retval = cfi_handle_reset_fifo_val(pcd, 0, 1, 0); ++ pcd->cfi->need_gadget_att = 0; ++ break; ++ default: ++ break; ++ } ++ return retval; ++} ++ ++/** ++ * This function sets a new value for the SG buffer setup. ++ */ ++static int cfi_ep_set_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd) ++{ ++ uint8_t inaddr, outaddr; ++ cfi_ep_t *epin, *epout; ++ ddma_sg_buffer_setup_t *psgval; ++ uint32_t desccount, size; ++ ++ CFI_INFO("%s\n", __func__); ++ ++ psgval = (ddma_sg_buffer_setup_t *) buf; ++ desccount = (uint32_t) psgval->bCount; ++ size = (uint32_t) psgval->wSize; ++ ++ /* Check the DMA descriptor count */ ++ if ((desccount > MAX_DMA_DESCS_PER_EP) || (desccount == 0)) { ++ CFI_INFO ++ ("%s: The count of DMA Descriptors should be between 1 and %d\n", ++ __func__, MAX_DMA_DESCS_PER_EP); ++ return -DWC_E_INVALID; ++ } ++ ++ /* Check the DMA descriptor count */ ++ ++ if (size == 0) { ++ ++ CFI_INFO("%s: The transfer size should be at least 1 byte\n", ++ __func__); ++ ++ return -DWC_E_INVALID; ++ ++ } ++ ++ inaddr = psgval->bInEndpointAddress; ++ outaddr = psgval->bOutEndpointAddress; ++ ++ epin = get_cfi_ep_by_addr(pcd->cfi, inaddr); ++ epout = get_cfi_ep_by_addr(pcd->cfi, outaddr); ++ ++ if (NULL == epin || NULL == epout) { ++ CFI_INFO ++ ("%s: Unable to get the endpoints inaddr=0x%02x outaddr=0x%02x\n", ++ __func__, inaddr, outaddr); ++ return -DWC_E_INVALID; ++ } ++ ++ epin->ep->dwc_ep.buff_mode = BM_SG; ++ dwc_memcpy(epin->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t)); ++ ++ epout->ep->dwc_ep.buff_mode = BM_SG; ++ dwc_memcpy(epout->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t)); ++ ++ return 0; ++} ++ ++/** ++ * This function sets a new value for the buffer Alignment setup. ++ */ ++static int cfi_ep_set_alignment_val(uint8_t * buf, struct dwc_otg_pcd *pcd) ++{ ++ cfi_ep_t *ep; ++ uint8_t addr; ++ ddma_align_buffer_setup_t *palignval; ++ ++ palignval = (ddma_align_buffer_setup_t *) buf; ++ addr = palignval->bEndpointAddress; ++ ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, addr); ++ return -DWC_E_INVALID; ++ } ++ ++ ep->ep->dwc_ep.buff_mode = BM_ALIGN; ++ dwc_memcpy(ep->bm_align, palignval, sizeof(ddma_align_buffer_setup_t)); ++ ++ return 0; ++} ++ ++/** ++ * This function sets a new value for the Concatenation buffer setup. ++ */ ++static int cfi_ep_set_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd) ++{ ++ uint8_t addr; ++ cfi_ep_t *ep; ++ struct _ddma_concat_buffer_setup_hdr *pConcatValHdr; ++ uint16_t *pVals; ++ uint32_t desccount; ++ int i; ++ uint16_t mps; ++ ++ pConcatValHdr = (struct _ddma_concat_buffer_setup_hdr *)buf; ++ desccount = (uint32_t) pConcatValHdr->bDescCount; ++ pVals = (uint16_t *) (buf + BS_CONCAT_VAL_HDR_LEN); ++ ++ /* Check the DMA descriptor count */ ++ if (desccount > MAX_DMA_DESCS_PER_EP) { ++ CFI_INFO("%s: Maximum DMA Descriptor count should be %d\n", ++ __func__, MAX_DMA_DESCS_PER_EP); ++ return -DWC_E_INVALID; ++ } ++ ++ addr = pConcatValHdr->bEndpointAddress; ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, addr); ++ return -DWC_E_INVALID; ++ } ++ ++ mps = UGETW(ep->ep->desc->wMaxPacketSize); ++ ++ /* Check the wTxSizes to be less than or equal to the mps */ ++ for (i = 0; i < desccount; i++) { ++ if (pVals[i] > mps) { ++ CFI_INFO ++ ("%s: ERROR - the wTxSize[%d] should be <= MPS (wTxSize=%d)\n", ++ __func__, i, pVals[i]); ++ return -DWC_E_INVALID; ++ } ++ } ++ ++ ep->ep->dwc_ep.buff_mode = BM_CONCAT; ++ dwc_memcpy(ep->bm_concat, pConcatValHdr, BS_CONCAT_VAL_HDR_LEN); ++ ++ /* Free the previously allocated storage for the wTxBytes */ ++ if (ep->bm_concat->wTxBytes) { ++ DWC_FREE(ep->bm_concat->wTxBytes); ++ } ++ ++ /* Allocate a new storage for the wTxBytes field */ ++ ep->bm_concat->wTxBytes = ++ DWC_ALLOC(sizeof(uint16_t) * pConcatValHdr->bDescCount); ++ if (NULL == ep->bm_concat->wTxBytes) { ++ CFI_INFO("%s: Unable to allocate memory\n", __func__); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ /* Copy the new values into the wTxBytes filed */ ++ dwc_memcpy(ep->bm_concat->wTxBytes, buf + BS_CONCAT_VAL_HDR_LEN, ++ sizeof(uint16_t) * pConcatValHdr->bDescCount); ++ ++ return 0; ++} ++ ++/** ++ * This function calculates the total of all FIFO sizes ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ * @return The total of data FIFO sizes. ++ * ++ */ ++static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_params_t *params = core_if->core_params; ++ uint16_t dfifo_total = 0; ++ int i; ++ ++ /* The shared RxFIFO size */ ++ dfifo_total = ++ params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size; ++ ++ /* Add up each TxFIFO size to the total */ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ dfifo_total += params->dev_tx_fifo_size[i]; ++ } ++ ++ return dfifo_total; ++} ++ ++/** ++ * This function returns Rx FIFO size ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ * @return The total of data FIFO sizes. ++ * ++ */ ++static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue) ++{ ++ switch (wValue >> 8) { ++ case 0: ++ return (core_if->pwron_rxfsiz < ++ 32768) ? core_if->pwron_rxfsiz : 32768; ++ break; ++ case 1: ++ return core_if->core_params->dev_rx_fifo_size; ++ break; ++ default: ++ return -DWC_E_INVALID; ++ break; ++ } ++} ++ ++/** ++ * This function returns Tx FIFO size for IN EP ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ * @return The total of data FIFO sizes. ++ * ++ */ ++static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ ++ ep = get_ep_by_addr(pcd, wValue & 0xff); ++ ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, wValue & 0xff); ++ return -DWC_E_INVALID; ++ } ++ ++ if (!ep->dwc_ep.is_in) { ++ CFI_INFO ++ ("%s: No Tx FIFO assingned to the Out endpoint addr=0x%02x\n", ++ __func__, wValue & 0xff); ++ return -DWC_E_INVALID; ++ } ++ ++ switch (wValue >> 8) { ++ case 0: ++ return (GET_CORE_IF(pcd)->pwron_txfsiz ++ [ep->dwc_ep.tx_fifo_num - 1] < ++ 768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep-> ++ dwc_ep.tx_fifo_num ++ - 1] : 32768; ++ break; ++ case 1: ++ return GET_CORE_IF(pcd)->core_params-> ++ dev_tx_fifo_size[ep->dwc_ep.num - 1]; ++ break; ++ default: ++ return -DWC_E_INVALID; ++ break; ++ } ++} ++ ++/** ++ * This function checks if the submitted combination of ++ * device mode FIFO sizes is possible or not. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ * @return 1 if possible, 0 otherwise. ++ * ++ */ ++static uint8_t check_fifo_sizes(dwc_otg_core_if_t * core_if) ++{ ++ uint16_t dfifo_actual = 0; ++ dwc_otg_core_params_t *params = core_if->core_params; ++ uint16_t start_addr = 0; ++ int i; ++ ++ dfifo_actual = ++ params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ dfifo_actual += params->dev_tx_fifo_size[i]; ++ } ++ ++ if (dfifo_actual > core_if->total_fifo_size) { ++ return 0; ++ } ++ ++ if (params->dev_rx_fifo_size > 32768 || params->dev_rx_fifo_size < 16) ++ return 0; ++ ++ if (params->dev_nperio_tx_fifo_size > 32768 ++ || params->dev_nperio_tx_fifo_size < 16) ++ return 0; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ ++ if (params->dev_tx_fifo_size[i] > 768 ++ || params->dev_tx_fifo_size[i] < 4) ++ return 0; ++ } ++ ++ if (params->dev_rx_fifo_size > core_if->pwron_rxfsiz) ++ return 0; ++ start_addr = params->dev_rx_fifo_size; ++ ++ if (params->dev_nperio_tx_fifo_size > core_if->pwron_gnptxfsiz) ++ return 0; ++ start_addr += params->dev_nperio_tx_fifo_size; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ ++ if (params->dev_tx_fifo_size[i] > core_if->pwron_txfsiz[i]) ++ return 0; ++ start_addr += params->dev_tx_fifo_size[i]; ++ } ++ ++ return 1; ++} ++ ++/** ++ * This function resizes Device mode FIFOs ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ * @return 1 if successful, 0 otherwise ++ * ++ */ ++static uint8_t resize_fifos(dwc_otg_core_if_t * core_if) ++{ ++ int i = 0; ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ dwc_otg_core_params_t *params = core_if->core_params; ++ uint32_t rx_fifo_size; ++ fifosize_data_t nptxfifosize; ++ fifosize_data_t txfifosize[15]; ++ ++ uint32_t rx_fsz_bak; ++ uint32_t nptxfsz_bak; ++ uint32_t txfsz_bak[15]; ++ ++ uint16_t start_address; ++ uint8_t retval = 1; ++ ++ if (!check_fifo_sizes(core_if)) { ++ return 0; ++ } ++ ++ /* Configure data FIFO sizes */ ++ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { ++ rx_fsz_bak = DWC_READ_REG32(&global_regs->grxfsiz); ++ rx_fifo_size = params->dev_rx_fifo_size; ++ DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size); ++ ++ /* ++ * Tx FIFOs These FIFOs are numbered from 1 to 15. ++ * Indexes of the FIFO size module parameters in the ++ * dev_tx_fifo_size array and the FIFO size registers in ++ * the dtxfsiz array run from 0 to 14. ++ */ ++ ++ /* Non-periodic Tx FIFO */ ++ nptxfsz_bak = DWC_READ_REG32(&global_regs->gnptxfsiz); ++ nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; ++ start_address = params->dev_rx_fifo_size; ++ nptxfifosize.b.startaddr = start_address; ++ ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32); ++ ++ start_address += nptxfifosize.b.depth; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ txfsz_bak[i] = DWC_READ_REG32(&global_regs->dtxfsiz[i]); ++ ++ txfifosize[i].b.depth = params->dev_tx_fifo_size[i]; ++ txfifosize[i].b.startaddr = start_address; ++ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], ++ txfifosize[i].d32); ++ ++ start_address += txfifosize[i].b.depth; ++ } ++ ++ /** Check if register values are set correctly */ ++ if (rx_fifo_size != DWC_READ_REG32(&global_regs->grxfsiz)) { ++ retval = 0; ++ } ++ ++ if (nptxfifosize.d32 != DWC_READ_REG32(&global_regs->gnptxfsiz)) { ++ retval = 0; ++ } ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ if (txfifosize[i].d32 != ++ DWC_READ_REG32(&global_regs->dtxfsiz[i])) { ++ retval = 0; ++ } ++ } ++ ++ /** If register values are not set correctly, reset old values */ ++ if (retval == 0) { ++ DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fsz_bak); ++ ++ /* Non-periodic Tx FIFO */ ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfsz_bak); ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], ++ txfsz_bak[i]); ++ } ++ } ++ } else { ++ return 0; ++ } ++ ++ /* Flush the FIFOs */ ++ dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ ++ dwc_otg_flush_rx_fifo(core_if); ++ ++ return retval; ++} ++ ++/** ++ * This function sets a new value for the buffer Alignment setup. ++ */ ++static int cfi_ep_set_tx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd) ++{ ++ int retval; ++ uint32_t fsiz; ++ uint16_t size; ++ uint16_t ep_addr; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params; ++ tx_fifo_size_setup_t *ptxfifoval; ++ ++ ptxfifoval = (tx_fifo_size_setup_t *) buf; ++ ep_addr = ptxfifoval->bEndpointAddress; ++ size = ptxfifoval->wDepth; ++ ++ ep = get_ep_by_addr(pcd, ep_addr); ++ ++ CFI_INFO ++ ("%s: Set Tx FIFO size: endpoint addr=0x%02x, depth=%d, FIFO Num=%d\n", ++ __func__, ep_addr, size, ep->dwc_ep.tx_fifo_num); ++ ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, ep_addr); ++ return -DWC_E_INVALID; ++ } ++ ++ fsiz = params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1]; ++ params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = size; ++ ++ if (resize_fifos(GET_CORE_IF(pcd))) { ++ retval = 0; ++ } else { ++ CFI_INFO ++ ("%s: Error setting the feature Tx FIFO Size for EP%d\n", ++ __func__, ep_addr); ++ params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = fsiz; ++ retval = -DWC_E_INVALID; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function sets a new value for the buffer Alignment setup. ++ */ ++static int cfi_set_rx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd) ++{ ++ int retval; ++ uint32_t fsiz; ++ uint16_t size; ++ dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params; ++ rx_fifo_size_setup_t *prxfifoval; ++ ++ prxfifoval = (rx_fifo_size_setup_t *) buf; ++ size = prxfifoval->wDepth; ++ ++ fsiz = params->dev_rx_fifo_size; ++ params->dev_rx_fifo_size = size; ++ ++ if (resize_fifos(GET_CORE_IF(pcd))) { ++ retval = 0; ++ } else { ++ CFI_INFO("%s: Error setting the feature Rx FIFO Size\n", ++ __func__); ++ params->dev_rx_fifo_size = fsiz; ++ retval = -DWC_E_INVALID; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function reads the SG of an EP's buffer setup into the buffer buf ++ */ ++static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req) ++{ ++ int retval = -DWC_E_INVALID; ++ uint8_t addr; ++ cfi_ep_t *ep; ++ ++ /* The Low Byte of the wValue contains a non-zero address of the endpoint */ ++ addr = req->wValue & 0xFF; ++ if (addr == 0) /* The address should be non-zero */ ++ return retval; ++ ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n", ++ __func__, addr); ++ return retval; ++ } ++ ++ dwc_memcpy(buf, ep->bm_sg, BS_SG_VAL_DESC_LEN); ++ retval = BS_SG_VAL_DESC_LEN; ++ return retval; ++} ++ ++/** ++ * This function reads the Concatenation value of an EP's buffer mode into ++ * the buffer buf ++ */ ++static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req) ++{ ++ int retval = -DWC_E_INVALID; ++ uint8_t addr; ++ cfi_ep_t *ep; ++ uint8_t desc_count; ++ ++ /* The Low Byte of the wValue contains a non-zero address of the endpoint */ ++ addr = req->wValue & 0xFF; ++ if (addr == 0) /* The address should be non-zero */ ++ return retval; ++ ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n", ++ __func__, addr); ++ return retval; ++ } ++ ++ /* Copy the header to the buffer */ ++ dwc_memcpy(buf, ep->bm_concat, BS_CONCAT_VAL_HDR_LEN); ++ /* Advance the buffer pointer by the header size */ ++ buf += BS_CONCAT_VAL_HDR_LEN; ++ ++ desc_count = ep->bm_concat->hdr.bDescCount; ++ /* Copy alll the wTxBytes to the buffer */ ++ dwc_memcpy(buf, ep->bm_concat->wTxBytes, sizeof(uid16_t) * desc_count); ++ ++ retval = BS_CONCAT_VAL_HDR_LEN + sizeof(uid16_t) * desc_count; ++ return retval; ++} ++ ++/** ++ * This function reads the buffer Alignment value of an EP's buffer mode into ++ * the buffer buf ++ * ++ * @return The total number of bytes copied to the buffer or negative error code. ++ */ ++static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req) ++{ ++ int retval = -DWC_E_INVALID; ++ uint8_t addr; ++ cfi_ep_t *ep; ++ ++ /* The Low Byte of the wValue contains a non-zero address of the endpoint */ ++ addr = req->wValue & 0xFF; ++ if (addr == 0) /* The address should be non-zero */ ++ return retval; ++ ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n", ++ __func__, addr); ++ return retval; ++ } ++ ++ dwc_memcpy(buf, ep->bm_align, BS_ALIGN_VAL_HDR_LEN); ++ retval = BS_ALIGN_VAL_HDR_LEN; ++ ++ return retval; ++} ++ ++/** ++ * This function sets a new value for the specified feature ++ * ++ * @param pcd A pointer to the PCD object ++ * ++ * @return 0 if successful, negative error code otherwise to stall the DCE. ++ */ ++static int cfi_set_feature_value(struct dwc_otg_pcd *pcd) ++{ ++ int retval = -DWC_E_NOT_SUPPORTED; ++ uint16_t wIndex, wValue; ++ uint8_t bRequest; ++ struct dwc_otg_core_if *coreif; ++ cfiobject_t *cfi = pcd->cfi; ++ struct cfi_usb_ctrlrequest *ctrl_req; ++ uint8_t *buf; ++ ctrl_req = &cfi->ctrl_req; ++ ++ buf = pcd->cfi->ctrl_req.data; ++ ++ coreif = GET_CORE_IF(pcd); ++ bRequest = ctrl_req->bRequest; ++ wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex); ++ wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue); ++ ++ /* See which feature is to be modified */ ++ switch (wIndex) { ++ case FT_ID_DMA_BUFFER_SETUP: ++ /* Modify the feature */ ++ if ((retval = cfi_ep_set_sg_val(buf, pcd)) < 0) ++ return retval; ++ ++ /* And send this request to the gadget */ ++ cfi->need_gadget_att = 1; ++ break; ++ ++ case FT_ID_DMA_BUFF_ALIGN: ++ if ((retval = cfi_ep_set_alignment_val(buf, pcd)) < 0) ++ return retval; ++ cfi->need_gadget_att = 1; ++ break; ++ ++ case FT_ID_DMA_CONCAT_SETUP: ++ /* Modify the feature */ ++ if ((retval = cfi_ep_set_concat_val(buf, pcd)) < 0) ++ return retval; ++ cfi->need_gadget_att = 1; ++ break; ++ ++ case FT_ID_DMA_CIRCULAR: ++ CFI_INFO("FT_ID_DMA_CIRCULAR\n"); ++ break; ++ ++ case FT_ID_THRESHOLD_SETUP: ++ CFI_INFO("FT_ID_THRESHOLD_SETUP\n"); ++ break; ++ ++ case FT_ID_DFIFO_DEPTH: ++ CFI_INFO("FT_ID_DFIFO_DEPTH\n"); ++ break; ++ ++ case FT_ID_TX_FIFO_DEPTH: ++ CFI_INFO("FT_ID_TX_FIFO_DEPTH\n"); ++ if ((retval = cfi_ep_set_tx_fifo_val(buf, pcd)) < 0) ++ return retval; ++ cfi->need_gadget_att = 0; ++ break; ++ ++ case FT_ID_RX_FIFO_DEPTH: ++ CFI_INFO("FT_ID_RX_FIFO_DEPTH\n"); ++ if ((retval = cfi_set_rx_fifo_val(buf, pcd)) < 0) ++ return retval; ++ cfi->need_gadget_att = 0; ++ break; ++ } ++ ++ return retval; ++} ++ ++#endif //DWC_UTE_CFI +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_cfi.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_cfi.h +new file mode 100644 +index 0000000..55fd337 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_cfi.h +@@ -0,0 +1,320 @@ ++/* ========================================================================== ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++#if !defined(__DWC_OTG_CFI_H__) ++#define __DWC_OTG_CFI_H__ ++ ++#include "dwc_otg_pcd.h" ++#include "dwc_cfi_common.h" ++ ++/** ++ * @file ++ * This file contains the CFI related OTG PCD specific common constants, ++ * interfaces(functions and macros) and data structures.The CFI Protocol is an ++ * optional interface for internal testing purposes that a DUT may implement to ++ * support testing of configurable features. ++ * ++ */ ++ ++struct dwc_otg_pcd; ++struct dwc_otg_pcd_ep; ++ ++/** OTG CFI Features (properties) ID constants */ ++/** This is a request for all Core Features */ ++#define FT_ID_DMA_MODE 0x0001 ++#define FT_ID_DMA_BUFFER_SETUP 0x0002 ++#define FT_ID_DMA_BUFF_ALIGN 0x0003 ++#define FT_ID_DMA_CONCAT_SETUP 0x0004 ++#define FT_ID_DMA_CIRCULAR 0x0005 ++#define FT_ID_THRESHOLD_SETUP 0x0006 ++#define FT_ID_DFIFO_DEPTH 0x0007 ++#define FT_ID_TX_FIFO_DEPTH 0x0008 ++#define FT_ID_RX_FIFO_DEPTH 0x0009 ++ ++/**********************************************************/ ++#define CFI_INFO_DEF ++ ++#ifdef CFI_INFO_DEF ++#define CFI_INFO(fmt...) DWC_PRINTF("CFI: " fmt); ++#else ++#define CFI_INFO(fmt...) ++#endif ++ ++#define min(x,y) ({ \ ++ x < y ? x : y; }) ++ ++#define max(x,y) ({ \ ++ x > y ? x : y; }) ++ ++/** ++ * Descriptor DMA SG Buffer setup structure (SG buffer). This structure is ++ * also used for setting up a buffer for Circular DDMA. ++ */ ++struct _ddma_sg_buffer_setup { ++#define BS_SG_VAL_DESC_LEN 6 ++ /* The OUT EP address */ ++ uint8_t bOutEndpointAddress; ++ /* The IN EP address */ ++ uint8_t bInEndpointAddress; ++ /* Number of bytes to put between transfer segments (must be DWORD boundaries) */ ++ uint8_t bOffset; ++ /* The number of transfer segments (a DMA descriptors per each segment) */ ++ uint8_t bCount; ++ /* Size (in byte) of each transfer segment */ ++ uint16_t wSize; ++} __attribute__ ((packed)); ++typedef struct _ddma_sg_buffer_setup ddma_sg_buffer_setup_t; ++ ++/** Descriptor DMA Concatenation Buffer setup structure */ ++struct _ddma_concat_buffer_setup_hdr { ++#define BS_CONCAT_VAL_HDR_LEN 4 ++ /* The endpoint for which the buffer is to be set up */ ++ uint8_t bEndpointAddress; ++ /* The count of descriptors to be used */ ++ uint8_t bDescCount; ++ /* The total size of the transfer */ ++ uint16_t wSize; ++} __attribute__ ((packed)); ++typedef struct _ddma_concat_buffer_setup_hdr ddma_concat_buffer_setup_hdr_t; ++ ++/** Descriptor DMA Concatenation Buffer setup structure */ ++struct _ddma_concat_buffer_setup { ++ /* The SG header */ ++ ddma_concat_buffer_setup_hdr_t hdr; ++ ++ /* The XFER sizes pointer (allocated dynamically) */ ++ uint16_t *wTxBytes; ++} __attribute__ ((packed)); ++typedef struct _ddma_concat_buffer_setup ddma_concat_buffer_setup_t; ++ ++/** Descriptor DMA Alignment Buffer setup structure */ ++struct _ddma_align_buffer_setup { ++#define BS_ALIGN_VAL_HDR_LEN 2 ++ uint8_t bEndpointAddress; ++ uint8_t bAlign; ++} __attribute__ ((packed)); ++typedef struct _ddma_align_buffer_setup ddma_align_buffer_setup_t; ++ ++/** Transmit FIFO Size setup structure */ ++struct _tx_fifo_size_setup { ++ uint8_t bEndpointAddress; ++ uint16_t wDepth; ++} __attribute__ ((packed)); ++typedef struct _tx_fifo_size_setup tx_fifo_size_setup_t; ++ ++/** Transmit FIFO Size setup structure */ ++struct _rx_fifo_size_setup { ++ uint16_t wDepth; ++} __attribute__ ((packed)); ++typedef struct _rx_fifo_size_setup rx_fifo_size_setup_t; ++ ++/** ++ * struct cfi_usb_ctrlrequest - the CFI implementation of the struct usb_ctrlrequest ++ * This structure encapsulates the standard usb_ctrlrequest and adds a pointer ++ * to the data returned in the data stage of a 3-stage Control Write requests. ++ */ ++struct cfi_usb_ctrlrequest { ++ uint8_t bRequestType; ++ uint8_t bRequest; ++ uint16_t wValue; ++ uint16_t wIndex; ++ uint16_t wLength; ++ uint8_t *data; ++} UPACKED; ++ ++/*---------------------------------------------------------------------------*/ ++ ++/** ++ * The CFI wrapper of the enabled and activated dwc_otg_pcd_ep structures. ++ * This structure is used to store the buffer setup data for any ++ * enabled endpoint in the PCD. ++ */ ++struct cfi_ep { ++ /* Entry for the list container */ ++ dwc_list_link_t lh; ++ /* Pointer to the active PCD endpoint structure */ ++ struct dwc_otg_pcd_ep *ep; ++ /* The last descriptor in the chain of DMA descriptors of the endpoint */ ++ struct dwc_otg_dma_desc *dma_desc_last; ++ /* The SG feature value */ ++ ddma_sg_buffer_setup_t *bm_sg; ++ /* The Circular feature value */ ++ ddma_sg_buffer_setup_t *bm_circ; ++ /* The Concatenation feature value */ ++ ddma_concat_buffer_setup_t *bm_concat; ++ /* The Alignment feature value */ ++ ddma_align_buffer_setup_t *bm_align; ++ /* XFER length */ ++ uint32_t xfer_len; ++ /* ++ * Count of DMA descriptors currently used. ++ * The total should not exceed the MAX_DMA_DESCS_PER_EP value ++ * defined in the dwc_otg_cil.h ++ */ ++ uint32_t desc_count; ++}; ++typedef struct cfi_ep cfi_ep_t; ++ ++typedef struct cfi_dma_buff { ++#define CFI_IN_BUF_LEN 1024 ++#define CFI_OUT_BUF_LEN 1024 ++ dma_addr_t addr; ++ uint8_t *buf; ++} cfi_dma_buff_t; ++ ++struct cfiobject; ++ ++/** ++ * This is the interface for the CFI operations. ++ * ++ * @param ep_enable Called when any endpoint is enabled and activated. ++ * @param release Called when the CFI object is released and it needs to correctly ++ * deallocate the dynamic memory ++ * @param ctrl_write_complete Called when the data stage of the request is complete ++ */ ++typedef struct cfi_ops { ++ int (*ep_enable) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd, ++ struct dwc_otg_pcd_ep * ep); ++ void *(*ep_alloc_buf) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd, ++ struct dwc_otg_pcd_ep * ep, dma_addr_t * dma, ++ unsigned size, gfp_t flags); ++ void (*release) (struct cfiobject * cfi); ++ int (*ctrl_write_complete) (struct cfiobject * cfi, ++ struct dwc_otg_pcd * pcd); ++ void (*build_descriptors) (struct cfiobject * cfi, ++ struct dwc_otg_pcd * pcd, ++ struct dwc_otg_pcd_ep * ep, ++ dwc_otg_pcd_request_t * req); ++} cfi_ops_t; ++ ++struct cfiobject { ++ cfi_ops_t ops; ++ struct dwc_otg_pcd *pcd; ++ struct usb_gadget *gadget; ++ ++ /* Buffers used to send/receive CFI-related request data */ ++ cfi_dma_buff_t buf_in; ++ cfi_dma_buff_t buf_out; ++ ++ /* CFI specific Control request wrapper */ ++ struct cfi_usb_ctrlrequest ctrl_req; ++ ++ /* The list of active EP's in the PCD of type cfi_ep_t */ ++ dwc_list_link_t active_eps; ++ ++ /* This flag shall control the propagation of a specific request ++ * to the gadget's processing routines. ++ * 0 - no gadget handling ++ * 1 - the gadget needs to know about this request (w/o completing a status ++ * phase - just return a 0 to the _setup callback) ++ */ ++ uint8_t need_gadget_att; ++ ++ /* Flag indicating whether the status IN phase needs to be ++ * completed by the PCD ++ */ ++ uint8_t need_status_in_complete; ++}; ++typedef struct cfiobject cfiobject_t; ++ ++#define DUMP_MSG ++ ++#if defined(DUMP_MSG) ++static inline void dump_msg(const u8 * buf, unsigned int length) ++{ ++ unsigned int start, num, i; ++ char line[52], *p; ++ ++ if (length >= 512) ++ return; ++ ++ start = 0; ++ while (length > 0) { ++ num = min(length, 16u); ++ p = line; ++ for (i = 0; i < num; ++i) { ++ if (i == 8) ++ *p++ = ' '; ++ DWC_SPRINTF(p, " %02x", buf[i]); ++ p += 3; ++ } ++ *p = 0; ++ DWC_DEBUG("%6x: %s\n", start, line); ++ buf += num; ++ start += num; ++ length -= num; ++ } ++} ++#else ++static inline void dump_msg(const u8 * buf, unsigned int length) ++{ ++} ++#endif ++ ++/** ++ * This function returns a pointer to cfi_ep_t object with the addr address. ++ */ ++static inline struct cfi_ep *get_cfi_ep_by_addr(struct cfiobject *cfi, ++ uint8_t addr) ++{ ++ struct cfi_ep *pcfiep; ++ dwc_list_link_t *tmp; ++ ++ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { ++ pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ ++ if (pcfiep->ep->desc->bEndpointAddress == addr) { ++ return pcfiep; ++ } ++ } ++ ++ return NULL; ++} ++ ++/** ++ * This function returns a pointer to cfi_ep_t object that matches ++ * the dwc_otg_pcd_ep object. ++ */ ++static inline struct cfi_ep *get_cfi_ep_by_pcd_ep(struct cfiobject *cfi, ++ struct dwc_otg_pcd_ep *ep) ++{ ++ struct cfi_ep *pcfiep = NULL; ++ dwc_list_link_t *tmp; ++ ++ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { ++ pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ if (pcfiep->ep == ep) { ++ return pcfiep; ++ } ++ } ++ return NULL; ++} ++ ++int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl); ++ ++#endif /* (__DWC_OTG_CFI_H__) */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_cil.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_cil.c +new file mode 100644 +index 0000000..6403349 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_cil.c +@@ -0,0 +1,7302 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $ ++ * $Revision: #203 $ ++ * $Date: 2013/05/16 $ ++ * $Change: 2231774 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ * The Core Interface Layer provides basic services for accessing and ++ * managing the DWC_otg hardware. These services are used by both the ++ * Host Controller Driver and the Peripheral Controller Driver. ++ * ++ * The CIL manages the memory map for the core so that the HCD and PCD ++ * don't have to do this separately. It also handles basic tasks like ++ * reading/writing the registers and data FIFOs in the controller. ++ * Some of the data access functions provide encapsulation of several ++ * operations required to perform a task, such as writing multiple ++ * registers to start a transfer. Finally, the CIL performs basic ++ * services that are not specific to either the host or device modes ++ * of operation. These services include management of the OTG Host ++ * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A ++ * Diagnostic API is also provided to allow testing of the controller ++ * hardware. ++ * ++ * The Core Interface Layer has the following requirements: ++ * - Provides basic controller operations. ++ * - Minimal use of OS services. ++ * - The OS services used will be abstracted by using inline functions ++ * or macros. ++ * ++ */ ++ ++#include "dwc_os.h" ++#include "dwc_otg_regs.h" ++#include "dwc_otg_cil.h" ++ ++static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if); ++ ++/** ++ * This function is called to initialize the DWC_otg CSR data ++ * structures. The register addresses in the device and host ++ * structures are initialized from the base address supplied by the ++ * caller. The calling function must make the OS calls to get the ++ * base address of the DWC_otg controller registers. The core_params ++ * argument holds the parameters that specify how the core should be ++ * configured. ++ * ++ * @param reg_base_addr Base address of DWC_otg core registers ++ * ++ */ ++dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr) ++{ ++ dwc_otg_core_if_t *core_if = 0; ++ dwc_otg_dev_if_t *dev_if = 0; ++ dwc_otg_host_if_t *host_if = 0; ++ uint8_t *reg_base = (uint8_t *) reg_base_addr; ++ int i = 0; ++ ++ DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, reg_base_addr); ++ ++ core_if = DWC_ALLOC(sizeof(dwc_otg_core_if_t)); ++ ++ if (core_if == NULL) { ++ DWC_DEBUGPL(DBG_CIL, ++ "Allocation of dwc_otg_core_if_t failed\n"); ++ return 0; ++ } ++ core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base; ++ ++ /* ++ * Allocate the Device Mode structures. ++ */ ++ dev_if = DWC_ALLOC(sizeof(dwc_otg_dev_if_t)); ++ ++ if (dev_if == NULL) { ++ DWC_DEBUGPL(DBG_CIL, "Allocation of dwc_otg_dev_if_t failed\n"); ++ DWC_FREE(core_if); ++ return 0; ++ } ++ ++ dev_if->dev_global_regs = ++ (dwc_otg_device_global_regs_t *) (reg_base + ++ DWC_DEV_GLOBAL_REG_OFFSET); ++ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ dev_if->in_ep_regs[i] = (dwc_otg_dev_in_ep_regs_t *) ++ (reg_base + DWC_DEV_IN_EP_REG_OFFSET + ++ (i * DWC_EP_REG_OFFSET)); ++ ++ dev_if->out_ep_regs[i] = (dwc_otg_dev_out_ep_regs_t *) ++ (reg_base + DWC_DEV_OUT_EP_REG_OFFSET + ++ (i * DWC_EP_REG_OFFSET)); ++ DWC_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p\n", ++ i, &dev_if->in_ep_regs[i]->diepctl); ++ DWC_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p\n", ++ i, &dev_if->out_ep_regs[i]->doepctl); ++ } ++ ++ dev_if->speed = 0; // unknown ++ ++ core_if->dev_if = dev_if; ++ ++ /* ++ * Allocate the Host Mode structures. ++ */ ++ host_if = DWC_ALLOC(sizeof(dwc_otg_host_if_t)); ++ ++ if (host_if == NULL) { ++ DWC_DEBUGPL(DBG_CIL, ++ "Allocation of dwc_otg_host_if_t failed\n"); ++ DWC_FREE(dev_if); ++ DWC_FREE(core_if); ++ return 0; ++ } ++ ++ host_if->host_global_regs = (dwc_otg_host_global_regs_t *) ++ (reg_base + DWC_OTG_HOST_GLOBAL_REG_OFFSET); ++ ++ host_if->hprt0 = ++ (uint32_t *) (reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET); ++ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ host_if->hc_regs[i] = (dwc_otg_hc_regs_t *) ++ (reg_base + DWC_OTG_HOST_CHAN_REGS_OFFSET + ++ (i * DWC_OTG_CHAN_REGS_OFFSET)); ++ DWC_DEBUGPL(DBG_CILV, "hc_reg[%d]->hcchar=%p\n", ++ i, &host_if->hc_regs[i]->hcchar); ++ } ++ ++ host_if->num_host_channels = MAX_EPS_CHANNELS; ++ core_if->host_if = host_if; ++ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ core_if->data_fifo[i] = ++ (uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET + ++ (i * DWC_OTG_DATA_FIFO_SIZE)); ++ DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08lx\n", ++ i, (unsigned long)core_if->data_fifo[i]); ++ } ++ ++ core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET); ++ ++ /* Initiate lx_state to L3 disconnected state */ ++ core_if->lx_state = DWC_OTG_L3; ++ /* ++ * Store the contents of the hardware configuration registers here for ++ * easy access later. ++ */ ++ core_if->hwcfg1.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->ghwcfg1); ++ core_if->hwcfg2.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2); ++ core_if->hwcfg3.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->ghwcfg3); ++ core_if->hwcfg4.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4); ++ ++ /* Force host mode to get HPTXFSIZ exact power on value */ ++ { ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gusbcfg.b.force_host_mode = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ dwc_mdelay(10); ++ core_if->hptxfsiz.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz); ++ gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gusbcfg.b.force_host_mode = 0; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ dwc_mdelay(10); ++ ++ gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gusbcfg.b.force_dev_mode = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ dwc_mdelay(10); ++ } ++ ++ DWC_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32); ++ DWC_DEBUGPL(DBG_CILV, "hwcfg2=%08x\n", core_if->hwcfg2.d32); ++ DWC_DEBUGPL(DBG_CILV, "hwcfg3=%08x\n", core_if->hwcfg3.d32); ++ DWC_DEBUGPL(DBG_CILV, "hwcfg4=%08x\n", core_if->hwcfg4.d32); ++ ++ core_if->hcfg.d32 = ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ core_if->dcfg.d32 = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ ++ DWC_DEBUGPL(DBG_CILV, "hcfg=%08x\n", core_if->hcfg.d32); ++ DWC_DEBUGPL(DBG_CILV, "dcfg=%08x\n", core_if->dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_CILV, "op_mode=%0x\n", core_if->hwcfg2.b.op_mode); ++ DWC_DEBUGPL(DBG_CILV, "arch=%0x\n", core_if->hwcfg2.b.architecture); ++ DWC_DEBUGPL(DBG_CILV, "num_dev_ep=%d\n", core_if->hwcfg2.b.num_dev_ep); ++ DWC_DEBUGPL(DBG_CILV, "num_host_chan=%d\n", ++ core_if->hwcfg2.b.num_host_chan); ++ DWC_DEBUGPL(DBG_CILV, "nonperio_tx_q_depth=0x%0x\n", ++ core_if->hwcfg2.b.nonperio_tx_q_depth); ++ DWC_DEBUGPL(DBG_CILV, "host_perio_tx_q_depth=0x%0x\n", ++ core_if->hwcfg2.b.host_perio_tx_q_depth); ++ DWC_DEBUGPL(DBG_CILV, "dev_token_q_depth=0x%0x\n", ++ core_if->hwcfg2.b.dev_token_q_depth); ++ ++ DWC_DEBUGPL(DBG_CILV, "Total FIFO SZ=%d\n", ++ core_if->hwcfg3.b.dfifo_depth); ++ DWC_DEBUGPL(DBG_CILV, "xfer_size_cntr_width=%0x\n", ++ core_if->hwcfg3.b.xfer_size_cntr_width); ++ ++ /* ++ * Set the SRP sucess bit for FS-I2c ++ */ ++ core_if->srp_success = 0; ++ core_if->srp_timer_started = 0; ++ ++ /* ++ * Create new workqueue and init works ++ */ ++ core_if->wq_otg = DWC_WORKQ_ALLOC("dwc_otg"); ++ if (core_if->wq_otg == 0) { ++ DWC_WARN("DWC_WORKQ_ALLOC failed\n"); ++ DWC_FREE(host_if); ++ DWC_FREE(dev_if); ++ DWC_FREE(core_if); ++ return 0; ++ } ++ ++ core_if->snpsid = DWC_READ_REG32(&core_if->core_global_regs->gsnpsid); ++ ++ DWC_PRINTF("Core Release: %x.%x%x%x\n", ++ (core_if->snpsid >> 12 & 0xF), ++ (core_if->snpsid >> 8 & 0xF), ++ (core_if->snpsid >> 4 & 0xF), (core_if->snpsid & 0xF)); ++ ++ if (dwc_otg_setup_params(core_if)) { ++ DWC_WARN("Error while setting core params\n"); ++ } ++ ++ core_if->hibernation_suspend = 0; ++ if (core_if->otg_ver) ++ core_if->test_mode = 0; ++ ++ /** ADP initialization */ ++ dwc_otg_adp_init(core_if); ++ ++ return core_if; ++} ++ ++/** ++ * This function frees the structures allocated by dwc_otg_cil_init(). ++ * ++ * @param core_if The core interface pointer returned from ++ * dwc_otg_cil_init(). ++ * ++ */ ++void dwc_otg_cil_remove(dwc_otg_core_if_t * core_if) ++{ ++ dctl_data_t dctl = {.d32 = 0 }; ++ /* Disable all interrupts */ ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 1, 0); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0); ++ ++ dctl.b.sftdiscon = 1; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, ++ dctl.d32); ++ } ++ ++ if (core_if->wq_otg) { ++ DWC_WORKQ_WAIT_WORK_DONE(core_if->wq_otg, 500); ++ DWC_WORKQ_FREE(core_if->wq_otg); ++ } ++ if (core_if->dev_if) { ++ DWC_FREE(core_if->dev_if); ++ } ++ if (core_if->host_if) { ++ DWC_FREE(core_if->host_if); ++ } ++ ++ /** Remove ADP Stuff */ ++ dwc_otg_adp_remove(core_if); ++ if (core_if->core_params) { ++ DWC_FREE(core_if->core_params); ++ } ++ if (core_if->wkp_timer) { ++ DWC_TIMER_FREE(core_if->wkp_timer); ++ } ++ if (core_if->srp_timer) { ++ DWC_TIMER_FREE(core_if->srp_timer); ++ } ++ DWC_FREE(core_if); ++} ++ ++/** ++ * This function enables the controller's Global Interrupt in the AHB Config ++ * register. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ gahbcfg_data_t ahbcfg = {.d32 = 0 }; ++ ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32); ++} ++ ++/** ++ * This function disables the controller's Global Interrupt in the AHB Config ++ * register. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ gahbcfg_data_t ahbcfg = {.d32 = 0 }; ++ ahbcfg.b.glblintrmsk = 1; /* Disable interrupts */ ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0); ++} ++ ++/** ++ * This function initializes the commmon interrupts, used in both ++ * device and host modes. ++ * ++ * @param core_if Programming view of the DWC_otg controller ++ * ++ */ ++static void dwc_otg_enable_common_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ /* Clear any pending OTG Interrupts */ ++ DWC_WRITE_REG32(&global_regs->gotgint, 0xFFFFFFFF); ++ ++ /* Clear any pending interrupts */ ++ DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* ++ * Enable the interrupts in the GINTMSK. ++ */ ++ if (!core_if->core_params->otg_ver) ++ /* To avoid system hang during OTG 2.0 role switch */ ++ intr_mask.b.modemismatch = 1; ++ intr_mask.b.otgintr = 1; ++ ++ if (!core_if->dma_enable) { ++ intr_mask.b.rxstsqlvl = 1; ++ } ++ ++ intr_mask.b.conidstschng = 1; ++ intr_mask.b.wkupintr = 1; ++ intr_mask.b.disconnect = 0; ++ intr_mask.b.usbsuspend = 1; ++ intr_mask.b.sessreqintr = 1; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ if (core_if->core_params->lpm_enable) { ++ intr_mask.b.lpmtranrcvd = 1; ++ } ++#endif ++ DWC_WRITE_REG32(&global_regs->gintmsk, intr_mask.d32); ++} ++ ++/* ++ * The restore operation is modified to support Synopsys Emulated Powerdown and ++ * Hibernation. This function is for exiting from Device mode hibernation by ++ * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup. ++ * @param core_if Programming view of DWC_otg controller. ++ * @param rem_wakeup - indicates whether resume is initiated by Device or Host. ++ * @param reset - indicates whether resume is initiated by Reset. ++ */ ++int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int rem_wakeup, int reset) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ ++ int timeout = 2000; ++ ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "%s called\n", __FUNCTION__); ++ /* Switch-on voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Assert Restore signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ if (rem_wakeup) { ++ dwc_udelay(70); ++ } ++ ++ /* Deassert Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Mask interrupts from gpwrdn */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.connect_det_msk = 1; ++ gpwrdn.b.srp_det_msk = 1; ++ gpwrdn.b.disconn_det_msk = 1; ++ gpwrdn.b.rst_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Indicates that we are going out from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* ++ * Set Restore Essential Regs bit in PCGCCTL register, restore_mode = 1 ++ * indicates restore from remote_wakeup ++ */ ++ restore_essential_regs(core_if, rem_wakeup, 0); ++ ++ /* ++ * Wait a little for seeing new value of variable hibernation_suspend if ++ * Restore done interrupt received before polling ++ */ ++ dwc_udelay(10); ++ ++ if (core_if->hibernation_suspend == 0) { ++ /* ++ * Wait For Restore_done Interrupt. This mechanism of polling the ++ * interrupt is introduced to avoid any possible race conditions ++ */ ++ do { ++ gintsts_data_t gintsts; ++ gintsts.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (gintsts.b.restoredone) { ++ gintsts.d32 = 0; ++ gintsts.b.restoredone = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, gintsts.d32); ++ DWC_PRINTF("Restore Done Interrupt seen\n"); ++ break; ++ } ++ dwc_udelay(10); ++ } while (--timeout); ++ if (!timeout) { ++ DWC_PRINTF("Restore Done interrupt wasn't generated here\n"); ++ } ++ } ++ /* Clear all pending interupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* De-assert Restore */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ if (!rem_wakeup) { ++ pcgcctl.d32 = 0; ++ pcgcctl.b.rstpdwnmodule = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ } ++ ++ /* Restore GUSBCFG and DCFG */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, ++ core_if->gr_backup->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, ++ core_if->dr_backup->dcfg); ++ ++ /* De-assert Wakeup Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ if (!rem_wakeup) { ++ /* Set Device programming done bit */ ++ dctl.b.pwronprgdone = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } else { ++ /* Start Remote Wakeup Signaling */ ++ dctl.d32 = core_if->dr_backup->dctl; ++ dctl.b.rmtwkupsig = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++ } ++ ++ dwc_mdelay(2); ++ /* Clear all pending interupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Restore global registers */ ++ dwc_otg_restore_global_regs(core_if); ++ /* Restore device global registers */ ++ dwc_otg_restore_dev_regs(core_if, rem_wakeup); ++ ++ if (rem_wakeup) { ++ dwc_mdelay(7); ++ dctl.d32 = 0; ++ dctl.b.rmtwkupsig = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); ++ } ++ ++ core_if->hibernation_suspend = 0; ++ /* The core will be in ON STATE */ ++ core_if->lx_state = DWC_OTG_L0; ++ DWC_PRINTF("Hibernation recovery completes here\n"); ++ ++ return 1; ++} ++ ++/* ++ * The restore operation is modified to support Synopsys Emulated Powerdown and ++ * Hibernation. This function is for exiting from Host mode hibernation by ++ * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup. ++ * @param core_if Programming view of DWC_otg controller. ++ * @param rem_wakeup - indicates whether resume is initiated by Device or Host. ++ * @param reset - indicates whether resume is initiated by Reset. ++ */ ++int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int rem_wakeup, int reset) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ ++ int timeout = 2000; ++ ++ DWC_DEBUGPL(DBG_HCD, "%s called\n", __FUNCTION__); ++ /* Switch-on voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Assert Restore signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ if (!rem_wakeup) { ++ dwc_udelay(50); ++ } ++ ++ /* Deassert Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.connect_det_msk = 1; ++ gpwrdn.b.srp_det_msk = 1; ++ gpwrdn.b.disconn_det_msk = 1; ++ gpwrdn.b.rst_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Indicates that we are going out from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Set Restore Essential Regs bit in PCGCCTL register */ ++ restore_essential_regs(core_if, rem_wakeup, 1); ++ ++ /* Wait a little for seeing new value of variable hibernation_suspend if ++ * Restore done interrupt received before polling */ ++ dwc_udelay(10); ++ ++ if (core_if->hibernation_suspend == 0) { ++ /* Wait For Restore_done Interrupt. This mechanism of polling the ++ * interrupt is introduced to avoid any possible race conditions ++ */ ++ do { ++ gintsts_data_t gintsts; ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (gintsts.b.restoredone) { ++ gintsts.d32 = 0; ++ gintsts.b.restoredone = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ DWC_DEBUGPL(DBG_HCD,"Restore Done Interrupt seen\n"); ++ break; ++ } ++ dwc_udelay(10); ++ } while (--timeout); ++ if (!timeout) { ++ DWC_WARN("Restore Done interrupt wasn't generated\n"); ++ } ++ } ++ ++ /* Set the flag's value to 0 again after receiving restore done interrupt */ ++ core_if->hibernation_suspend = 0; ++ ++ /* This step is not described in functional spec but if not wait for this ++ * delay, mismatch interrupts occurred because just after restore core is ++ * in Device mode(gintsts.curmode == 0) */ ++ dwc_mdelay(100); ++ ++ /* Clear all pending interrupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* De-assert Restore */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Restore GUSBCFG and HCFG */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, ++ core_if->gr_backup->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, ++ core_if->hr_backup->hcfg_local); ++ ++ /* De-assert Wakeup Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Start the Resume operation by programming HPRT0 */ ++ hprt0.d32 = core_if->hr_backup->hprt0_local; ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtena = 0; ++ hprt0.b.prtsusp = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ DWC_PRINTF("Resume Starts Now\n"); ++ if (!reset) { // Indicates it is Resume Operation ++ hprt0.d32 = core_if->hr_backup->hprt0_local; ++ hprt0.b.prtres = 1; ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtena = 0; ++ hprt0.b.prtsusp = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ if (!rem_wakeup) ++ hprt0.b.prtres = 0; ++ /* Wait for Resume time and then program HPRT again */ ++ dwc_mdelay(100); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ } else { // Indicates it is Reset Operation ++ hprt0.d32 = core_if->hr_backup->hprt0_local; ++ hprt0.b.prtrst = 1; ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtena = 0; ++ hprt0.b.prtsusp = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ /* Wait for Reset time and then program HPRT again */ ++ dwc_mdelay(60); ++ hprt0.b.prtrst = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } ++ /* Clear all interrupt status */ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtconndet = 1; ++ hprt0.b.prtenchng = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* Clear all pending interupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Restore global registers */ ++ dwc_otg_restore_global_regs(core_if); ++ /* Restore host global registers */ ++ dwc_otg_restore_host_regs(core_if, reset); ++ ++ /* The core will be in ON STATE */ ++ core_if->lx_state = DWC_OTG_L0; ++ DWC_PRINTF("Hibernation recovery is complete here\n"); ++ return 0; ++} ++ ++/** Saves some register values into system memory. */ ++int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ int i; ++ ++ gr = core_if->gr_backup; ++ if (!gr) { ++ gr = DWC_ALLOC(sizeof(*gr)); ++ if (!gr) { ++ return -DWC_E_NO_MEMORY; ++ } ++ core_if->gr_backup = gr; ++ } ++ ++ gr->gotgctl_local = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ gr->gahbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg); ++ gr->gusbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gr->grxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); ++ gr->gnptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz); ++ gr->hptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ gr->glpmcfg_local = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++#endif ++ gr->gi2cctl_local = DWC_READ_REG32(&core_if->core_global_regs->gi2cctl); ++ gr->pcgcctl_local = DWC_READ_REG32(core_if->pcgcctl); ++ gr->gdfifocfg_local = ++ DWC_READ_REG32(&core_if->core_global_regs->gdfifocfg); ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ gr->dtxfsiz_local[i] = ++ DWC_READ_REG32(&(core_if->core_global_regs->dtxfsiz[i])); ++ } ++ ++ DWC_DEBUGPL(DBG_ANY, "===========Backing Global registers==========\n"); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gotgctl = %08x\n", gr->gotgctl_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk = %08x\n", gr->gintmsk_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gahbcfg = %08x\n", gr->gahbcfg_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gusbcfg = %08x\n", gr->gusbcfg_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up grxfsiz = %08x\n", gr->grxfsiz_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gnptxfsiz = %08x\n", ++ gr->gnptxfsiz_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up hptxfsiz = %08x\n", ++ gr->hptxfsiz_local); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ DWC_DEBUGPL(DBG_ANY, "Backed up glpmcfg = %08x\n", gr->glpmcfg_local); ++#endif ++ DWC_DEBUGPL(DBG_ANY, "Backed up gi2cctl = %08x\n", gr->gi2cctl_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up pcgcctl = %08x\n", gr->pcgcctl_local); ++ DWC_DEBUGPL(DBG_ANY,"Backed up gdfifocfg = %08x\n",gr->gdfifocfg_local); ++ ++ return 0; ++} ++ ++/** Saves GINTMSK register before setting the msk bits. */ ++int dwc_otg_save_gintmsk_reg(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ ++ gr = core_if->gr_backup; ++ if (!gr) { ++ gr = DWC_ALLOC(sizeof(*gr)); ++ if (!gr) { ++ return -DWC_E_NO_MEMORY; ++ } ++ core_if->gr_backup = gr; ++ } ++ ++ gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ ++ DWC_DEBUGPL(DBG_ANY,"=============Backing GINTMSK registers============\n"); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk = %08x\n", gr->gintmsk_local); ++ ++ return 0; ++} ++ ++int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_dev_regs_backup *dr; ++ int i; ++ ++ dr = core_if->dr_backup; ++ if (!dr) { ++ dr = DWC_ALLOC(sizeof(*dr)); ++ if (!dr) { ++ return -DWC_E_NO_MEMORY; ++ } ++ core_if->dr_backup = dr; ++ } ++ ++ dr->dcfg = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ dr->dctl = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ dr->daintmsk = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk); ++ dr->diepmsk = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->diepmsk); ++ dr->doepmsk = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->doepmsk); ++ ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ dr->diepctl[i] = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl); ++ dr->dieptsiz[i] = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz); ++ dr->diepdma[i] = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma); ++ } ++ ++ DWC_DEBUGPL(DBG_ANY, ++ "=============Backing Host registers==============\n"); ++ DWC_DEBUGPL(DBG_ANY, "Backed up dcfg = %08x\n", dr->dcfg); ++ DWC_DEBUGPL(DBG_ANY, "Backed up dctl = %08x\n", dr->dctl); ++ DWC_DEBUGPL(DBG_ANY, "Backed up daintmsk = %08x\n", ++ dr->daintmsk); ++ DWC_DEBUGPL(DBG_ANY, "Backed up diepmsk = %08x\n", dr->diepmsk); ++ DWC_DEBUGPL(DBG_ANY, "Backed up doepmsk = %08x\n", dr->doepmsk); ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ DWC_DEBUGPL(DBG_ANY, "Backed up diepctl[%d] = %08x\n", i, ++ dr->diepctl[i]); ++ DWC_DEBUGPL(DBG_ANY, "Backed up dieptsiz[%d] = %08x\n", ++ i, dr->dieptsiz[i]); ++ DWC_DEBUGPL(DBG_ANY, "Backed up diepdma[%d] = %08x\n", i, ++ dr->diepdma[i]); ++ } ++ ++ return 0; ++} ++ ++int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_host_regs_backup *hr; ++ int i; ++ ++ hr = core_if->hr_backup; ++ if (!hr) { ++ hr = DWC_ALLOC(sizeof(*hr)); ++ if (!hr) { ++ return -DWC_E_NO_MEMORY; ++ } ++ core_if->hr_backup = hr; ++ } ++ ++ hr->hcfg_local = ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ hr->haintmsk_local = ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk); ++ for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) { ++ hr->hcintmsk_local[i] = ++ DWC_READ_REG32(&core_if->host_if->hc_regs[i]->hcintmsk); ++ } ++ hr->hprt0_local = DWC_READ_REG32(core_if->host_if->hprt0); ++ hr->hfir_local = ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir); ++ ++ DWC_DEBUGPL(DBG_ANY, ++ "=============Backing Host registers===============\n"); ++ DWC_DEBUGPL(DBG_ANY, "Backed up hcfg = %08x\n", ++ hr->hcfg_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up haintmsk = %08x\n", hr->haintmsk_local); ++ for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) { ++ DWC_DEBUGPL(DBG_ANY, "Backed up hcintmsk[%02d]=%08x\n", i, ++ hr->hcintmsk_local[i]); ++ } ++ DWC_DEBUGPL(DBG_ANY, "Backed up hprt0 = %08x\n", ++ hr->hprt0_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up hfir = %08x\n", ++ hr->hfir_local); ++ ++ return 0; ++} ++ ++int dwc_otg_restore_global_regs(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ int i; ++ ++ gr = core_if->gr_backup; ++ if (!gr) { ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, gr->gotgctl_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gr->gintmsk_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gr->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gr->gahbcfg_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, gr->grxfsiz_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, ++ gr->gnptxfsiz_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->hptxfsiz, ++ gr->hptxfsiz_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gdfifocfg, ++ gr->gdfifocfg_local); ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ DWC_WRITE_REG32(&core_if->core_global_regs->dtxfsiz[i], ++ gr->dtxfsiz_local[i]); ++ } ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, 0x0000100A); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, ++ (gr->gahbcfg_local)); ++ return 0; ++} ++ ++int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, int rem_wakeup) ++{ ++ struct dwc_otg_dev_regs_backup *dr; ++ int i; ++ ++ dr = core_if->dr_backup; ++ ++ if (!dr) { ++ return -DWC_E_INVALID; ++ } ++ ++ if (!rem_wakeup) { ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ dr->dctl); ++ } ++ ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, dr->daintmsk); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, dr->diepmsk); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, dr->doepmsk); ++ ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz, dr->dieptsiz[i]); ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma, dr->diepdma[i]); ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl, dr->diepctl[i]); ++ } ++ ++ return 0; ++} ++ ++int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset) ++{ ++ struct dwc_otg_host_regs_backup *hr; ++ int i; ++ hr = core_if->hr_backup; ++ ++ if (!hr) { ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hr->hcfg_local); ++ //if (!reset) ++ //{ ++ // DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hr->hfir_local); ++ //} ++ ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, ++ hr->haintmsk_local); ++ for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) { ++ DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, ++ hr->hcintmsk_local[i]); ++ } ++ ++ return 0; ++} ++ ++int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ ++ gr = core_if->gr_backup; ++ ++ /* Restore values for LPM and I2C */ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, gr->glpmcfg_local); ++#endif ++ DWC_WRITE_REG32(&core_if->core_global_regs->gi2cctl, gr->gi2cctl_local); ++ ++ return 0; ++} ++ ++int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode, int is_host) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gahbcfg_data_t gahbcfg = {.d32 = 0 }; ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ /* Restore LPM and I2C registers */ ++ restore_lpm_i2c_regs(core_if); ++ ++ /* Set PCGCCTL to 0 */ ++ DWC_WRITE_REG32(core_if->pcgcctl, 0x00000000); ++ ++ gr = core_if->gr_backup; ++ /* Load restore values for [31:14] bits */ ++ DWC_WRITE_REG32(core_if->pcgcctl, ++ ((gr->pcgcctl_local & 0xffffc000) | 0x00020000)); ++ ++ /* Umnask global Interrupt in GAHBCFG and restore it */ ++ gahbcfg.d32 = gr->gahbcfg_local; ++ gahbcfg.b.glblintrmsk = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32); ++ ++ /* Clear all pending interupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Unmask restore done interrupt */ ++ gintmsk.b.restoredone = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32); ++ ++ /* Restore GUSBCFG and HCFG/DCFG */ ++ gusbcfg.d32 = core_if->gr_backup->gusbcfg_local; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ ++ if (is_host) { ++ hcfg_data_t hcfg = {.d32 = 0 }; ++ hcfg.d32 = core_if->hr_backup->hcfg_local; ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, ++ hcfg.d32); ++ ++ /* Load restore values for [31:14] bits */ ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local | 0x00020000; ++ ++ if (rmode) ++ pcgcctl.b.restoremode = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ dwc_udelay(10); ++ ++ /* Load restore values for [31:14] bits and set EssRegRestored bit */ ++ pcgcctl.d32 = gr->pcgcctl_local | 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.b.ess_reg_restored = 1; ++ if (rmode) ++ pcgcctl.b.restoremode = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ } else { ++ dcfg_data_t dcfg = {.d32 = 0 }; ++ dcfg.d32 = core_if->dr_backup->dcfg; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ /* Load restore values for [31:14] bits */ ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local | 0x00020000; ++ if (!rmode) { ++ pcgcctl.d32 |= 0x208; ++ } ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ dwc_udelay(10); ++ ++ /* Load restore values for [31:14] bits */ ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local | 0x00020000; ++ pcgcctl.b.ess_reg_restored = 1; ++ if (!rmode) ++ pcgcctl.d32 |= 0x208; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ } ++ ++ return 0; ++} ++ ++/** ++ * Initializes the FSLSPClkSel field of the HCFG register depending on the PHY ++ * type. ++ */ ++static void init_fslspclksel(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t val; ++ hcfg_data_t hcfg; ++ ++ if (((core_if->hwcfg2.b.hs_phy_type == 2) && ++ (core_if->hwcfg2.b.fs_phy_type == 1) && ++ (core_if->core_params->ulpi_fs_ls)) || ++ (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) { ++ /* Full speed PHY */ ++ val = DWC_HCFG_48_MHZ; ++ } else { ++ /* High speed PHY running at full speed or high speed */ ++ val = DWC_HCFG_30_60_MHZ; ++ } ++ ++ DWC_DEBUGPL(DBG_CIL, "Initializing HCFG.FSLSPClkSel to 0x%1x\n", val); ++ hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ hcfg.b.fslspclksel = val; ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++} ++ ++/** ++ * Initializes the DevSpd field of the DCFG register depending on the PHY type ++ * and the enumeration speed of the device. ++ */ ++static void init_devspd(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t val; ++ dcfg_data_t dcfg; ++ ++ if (((core_if->hwcfg2.b.hs_phy_type == 2) && ++ (core_if->hwcfg2.b.fs_phy_type == 1) && ++ (core_if->core_params->ulpi_fs_ls)) || ++ (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) { ++ /* Full speed PHY */ ++ val = 0x3; ++ } else if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) { ++ /* High speed PHY running at full speed */ ++ val = 0x1; ++ } else { ++ /* High speed PHY running at high speed */ ++ val = 0x0; ++ } ++ ++ DWC_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val); ++ ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ dcfg.b.devspd = val; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); ++} ++ ++/** ++ * This function calculates the number of IN EPS ++ * using GHWCFG1 and GHWCFG2 registers values ++ * ++ * @param core_if Programming view of the DWC_otg controller ++ */ ++static uint32_t calc_num_in_eps(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t num_in_eps = 0; ++ uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep; ++ uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 3; ++ uint32_t num_tx_fifos = core_if->hwcfg4.b.num_in_eps; ++ int i; ++ ++ for (i = 0; i < num_eps; ++i) { ++ if (!(hwcfg1 & 0x1)) ++ num_in_eps++; ++ ++ hwcfg1 >>= 2; ++ } ++ ++ if (core_if->hwcfg4.b.ded_fifo_en) { ++ num_in_eps = ++ (num_in_eps > num_tx_fifos) ? num_tx_fifos : num_in_eps; ++ } ++ ++ return num_in_eps; ++} ++ ++/** ++ * This function calculates the number of OUT EPS ++ * using GHWCFG1 and GHWCFG2 registers values ++ * ++ * @param core_if Programming view of the DWC_otg controller ++ */ ++static uint32_t calc_num_out_eps(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t num_out_eps = 0; ++ uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep; ++ uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 2; ++ int i; ++ ++ for (i = 0; i < num_eps; ++i) { ++ if (!(hwcfg1 & 0x1)) ++ num_out_eps++; ++ ++ hwcfg1 >>= 2; ++ } ++ return num_out_eps; ++} ++ ++/** ++ * This function initializes the DWC_otg controller registers and ++ * prepares the core for device mode or host mode operation. ++ * ++ * @param core_if Programming view of the DWC_otg controller ++ * ++ */ ++void dwc_otg_core_init(dwc_otg_core_if_t * core_if) ++{ ++ int i = 0; ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ gahbcfg_data_t ahbcfg = {.d32 = 0 }; ++ gusbcfg_data_t usbcfg = {.d32 = 0 }; ++ gi2cctl_data_t i2cctl = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_CILV, "dwc_otg_core_init(%p)\n", core_if); ++ ++ /* Common Initialization */ ++ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); ++ ++ /* Program the ULPI External VBUS bit if needed */ ++ usbcfg.b.ulpi_ext_vbus_drv = ++ (core_if->core_params->phy_ulpi_ext_vbus == ++ DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0; ++ ++ /* Set external TS Dline pulsing */ ++ usbcfg.b.term_sel_dl_pulse = ++ (core_if->core_params->ts_dline == 1) ? 1 : 0; ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ ++ /* Reset the Controller */ ++ dwc_otg_core_reset(core_if); ++ ++ core_if->adp_enable = core_if->core_params->adp_supp_enable; ++ core_if->power_down = core_if->core_params->power_down; ++ ++ /* Initialize parameters from Hardware configuration registers. */ ++ dev_if->num_in_eps = calc_num_in_eps(core_if); ++ dev_if->num_out_eps = calc_num_out_eps(core_if); ++ ++ DWC_DEBUGPL(DBG_CIL, "num_dev_perio_in_ep=%d\n", ++ core_if->hwcfg4.b.num_dev_perio_in_ep); ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { ++ dev_if->perio_tx_fifo_size[i] = ++ DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16; ++ DWC_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n", ++ i, dev_if->perio_tx_fifo_size[i]); ++ } ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ dev_if->tx_fifo_size[i] = ++ DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16; ++ DWC_DEBUGPL(DBG_CIL, "Tx FIFO SZ #%d=0x%0x\n", ++ i, dev_if->tx_fifo_size[i]); ++ } ++ ++ core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth; ++ core_if->rx_fifo_size = DWC_READ_REG32(&global_regs->grxfsiz); ++ core_if->nperio_tx_fifo_size = ++ DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16; ++ ++ DWC_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", core_if->total_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", core_if->rx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO SZ=%d\n", ++ core_if->nperio_tx_fifo_size); ++ ++ /* This programming sequence needs to happen in FS mode before any other ++ * programming occurs */ ++ if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) && ++ (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) { ++ /* If FS mode with FS PHY */ ++ ++ /* core_init() is now called on every switch so only call the ++ * following for the first time through. */ ++ if (!core_if->phy_init_done) { ++ core_if->phy_init_done = 1; ++ DWC_DEBUGPL(DBG_CIL, "FS_PHY detected\n"); ++ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); ++ usbcfg.b.physel = 1; ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ ++ /* Reset after a PHY select */ ++ dwc_otg_core_reset(core_if); ++ } ++ ++ /* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also ++ * do this on HNP Dev/Host mode switches (done in dev_init and ++ * host_init). */ ++ if (dwc_otg_is_host_mode(core_if)) { ++ init_fslspclksel(core_if); ++ } else { ++ init_devspd(core_if); ++ } ++ ++ if (core_if->core_params->i2c_enable) { ++ DWC_DEBUGPL(DBG_CIL, "FS_PHY Enabling I2c\n"); ++ /* Program GUSBCFG.OtgUtmifsSel to I2C */ ++ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); ++ usbcfg.b.otgutmifssel = 1; ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ ++ /* Program GI2CCTL.I2CEn */ ++ i2cctl.d32 = DWC_READ_REG32(&global_regs->gi2cctl); ++ i2cctl.b.i2cdevaddr = 1; ++ i2cctl.b.i2cen = 0; ++ DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32); ++ i2cctl.b.i2cen = 1; ++ DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32); ++ } ++ ++ } /* endif speed == DWC_SPEED_PARAM_FULL */ ++ else { ++ /* High speed PHY. */ ++ if (!core_if->phy_init_done) { ++ core_if->phy_init_done = 1; ++ /* HS PHY parameters. These parameters are preserved ++ * during soft reset so only program the first time. Do ++ * a soft reset immediately after setting phyif. */ ++ ++ if (core_if->core_params->phy_type == 2) { ++ /* ULPI interface */ ++ usbcfg.b.ulpi_utmi_sel = 1; ++ usbcfg.b.phyif = 0; ++ usbcfg.b.ddrsel = ++ core_if->core_params->phy_ulpi_ddr; ++ } else if (core_if->core_params->phy_type == 1) { ++ /* UTMI+ interface */ ++ usbcfg.b.ulpi_utmi_sel = 0; ++ if (core_if->core_params->phy_utmi_width == 16) { ++ usbcfg.b.phyif = 1; ++ ++ } else { ++ usbcfg.b.phyif = 0; ++ } ++ } else { ++ DWC_ERROR("FS PHY TYPE\n"); ++ } ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ /* Reset after setting the PHY parameters */ ++ dwc_otg_core_reset(core_if); ++ } ++ } ++ ++ if ((core_if->hwcfg2.b.hs_phy_type == 2) && ++ (core_if->hwcfg2.b.fs_phy_type == 1) && ++ (core_if->core_params->ulpi_fs_ls)) { ++ DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS\n"); ++ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); ++ usbcfg.b.ulpi_fsls = 1; ++ usbcfg.b.ulpi_clk_sus_m = 1; ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ } else { ++ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); ++ usbcfg.b.ulpi_fsls = 0; ++ usbcfg.b.ulpi_clk_sus_m = 0; ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ } ++ ++ /* Program the GAHBCFG Register. */ ++ switch (core_if->hwcfg2.b.architecture) { ++ ++ case DWC_SLAVE_ONLY_ARCH: ++ DWC_DEBUGPL(DBG_CIL, "Slave Only Mode\n"); ++ ahbcfg.b.nptxfemplvl_txfemplvl = ++ DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY; ++ ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY; ++ core_if->dma_enable = 0; ++ core_if->dma_desc_enable = 0; ++ break; ++ ++ case DWC_EXT_DMA_ARCH: ++ DWC_DEBUGPL(DBG_CIL, "External DMA Mode\n"); ++ { ++ uint8_t brst_sz = core_if->core_params->dma_burst_size; ++ ahbcfg.b.hburstlen = 0; ++ while (brst_sz > 1) { ++ ahbcfg.b.hburstlen++; ++ brst_sz >>= 1; ++ } ++ } ++ core_if->dma_enable = (core_if->core_params->dma_enable != 0); ++ core_if->dma_desc_enable = ++ (core_if->core_params->dma_desc_enable != 0); ++ break; ++ ++ case DWC_INT_DMA_ARCH: ++ DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n"); ++ /* Old value was DWC_GAHBCFG_INT_DMA_BURST_INCR - done for ++ Host mode ISOC in issue fix - vahrama */ ++ ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR4; ++ core_if->dma_enable = (core_if->core_params->dma_enable != 0); ++ core_if->dma_desc_enable = ++ (core_if->core_params->dma_desc_enable != 0); ++ break; ++ ++ } ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ DWC_PRINTF("Using Descriptor DMA mode\n"); ++ } else { ++ DWC_PRINTF("Using Buffer DMA mode\n"); ++ } ++ } else { ++ DWC_PRINTF("Using Slave mode\n"); ++ core_if->dma_desc_enable = 0; ++ } ++ ++ if (core_if->core_params->ahb_single) { ++ ahbcfg.b.ahbsingle = 1; ++ } ++ ++ ahbcfg.b.dmaenable = core_if->dma_enable; ++ DWC_WRITE_REG32(&global_regs->gahbcfg, ahbcfg.d32); ++ ++ core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en; ++ ++ core_if->pti_enh_enable = core_if->core_params->pti_enable != 0; ++ core_if->multiproc_int_enable = core_if->core_params->mpi_enable; ++ ++ /* ++ * Program the GUSBCFG register. ++ */ ++ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); ++ ++ switch (core_if->hwcfg2.b.op_mode) { ++ case DWC_MODE_HNP_SRP_CAPABLE: ++ usbcfg.b.hnpcap = (core_if->core_params->otg_cap == ++ DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE); ++ usbcfg.b.srpcap = (core_if->core_params->otg_cap != ++ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ break; ++ ++ case DWC_MODE_SRP_ONLY_CAPABLE: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = (core_if->core_params->otg_cap != ++ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ break; ++ ++ case DWC_MODE_NO_HNP_SRP_CAPABLE: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = 0; ++ break; ++ ++ case DWC_MODE_SRP_CAPABLE_DEVICE: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = (core_if->core_params->otg_cap != ++ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ break; ++ ++ case DWC_MODE_NO_SRP_CAPABLE_DEVICE: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = 0; ++ break; ++ ++ case DWC_MODE_SRP_CAPABLE_HOST: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = (core_if->core_params->otg_cap != ++ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ break; ++ ++ case DWC_MODE_NO_SRP_CAPABLE_HOST: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = 0; ++ break; ++ } ++ ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ if (core_if->core_params->lpm_enable) { ++ glpmcfg_data_t lpmcfg = {.d32 = 0 }; ++ ++ /* To enable LPM support set lpm_cap_en bit */ ++ lpmcfg.b.lpm_cap_en = 1; ++ ++ /* Make AppL1Res ACK */ ++ lpmcfg.b.appl_resp = 1; ++ ++ /* Retry 3 times */ ++ lpmcfg.b.retry_count = 3; ++ ++ DWC_MODIFY_REG32(&core_if->core_global_regs->glpmcfg, ++ 0, lpmcfg.d32); ++ ++ } ++#endif ++ if (core_if->core_params->ic_usb_cap) { ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ gusbcfg.b.ic_usb_cap = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gusbcfg, ++ 0, gusbcfg.d32); ++ } ++ { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gotgctl.b.otgver = core_if->core_params->otg_ver; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, 0, ++ gotgctl.d32); ++ /* Set OTG version supported */ ++ core_if->otg_ver = core_if->core_params->otg_ver; ++ } ++ ++ /* Enable common interrupts */ ++ dwc_otg_enable_common_interrupts(core_if); ++ ++ /* Do device or host intialization based on mode during PCD ++ * and HCD initialization */ ++ if (dwc_otg_is_host_mode(core_if)) { ++ DWC_DEBUGPL(DBG_ANY, "Host Mode\n"); ++ core_if->op_state = A_HOST; ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "Device Mode\n"); ++ core_if->op_state = B_PERIPHERAL; ++#ifdef DWC_DEVICE_ONLY ++ dwc_otg_core_dev_init(core_if); ++#endif ++ } ++} ++ ++/** ++ * This function enables the Device mode interrupts. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ */ ++void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ ++ DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__); ++ ++ /* Disable all interrupts. */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* Clear any pending interrupts */ ++ DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Enable the common interrupts */ ++ dwc_otg_enable_common_interrupts(core_if); ++ ++ /* Enable interrupts */ ++ intr_mask.b.usbreset = 1; ++ intr_mask.b.enumdone = 1; ++ /* Disable Disconnect interrupt in Device mode */ ++ intr_mask.b.disconnect = 0; ++ ++ if (!core_if->multiproc_int_enable) { ++ intr_mask.b.inepintr = 1; ++ intr_mask.b.outepintr = 1; ++ } ++ ++ intr_mask.b.erlysuspend = 1; ++ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.epmismatch = 1; ++ } ++ ++ /* intr_mask.b.incomplisoout = 1; */ ++ if (!core_if->dma_desc_enable) ++ intr_mask.b.incomplisoin = 1; ++#ifdef DWC_EN_ISOC ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ if (core_if->pti_enh_enable) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.b.ifrmnum = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dctl, ++ 0, dctl.d32); ++ } else { ++ intr_mask.b.incomplisoin = 1; ++ intr_mask.b.incomplisoout = 1; ++ } ++ } ++ } else { ++ intr_mask.b.incomplisoin = 1; ++ intr_mask.b.incomplisoout = 1; ++ } ++#endif /* DWC_EN_ISOC */ ++ ++ /** @todo NGS: Should this be a module parameter? */ ++#ifdef USE_PERIODIC_EP ++ intr_mask.b.isooutdrop = 1; ++ intr_mask.b.eopframe = 1; ++ intr_mask.b.incomplisoin = 1; ++ intr_mask.b.incomplisoout = 1; ++#endif ++ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); ++ ++ DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__, ++ DWC_READ_REG32(&global_regs->gintmsk)); ++} ++ ++/** ++ * This function initializes the DWC_otg controller registers for ++ * device mode. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ */ ++void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if) ++{ ++ int i; ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dwc_otg_core_params_t *params = core_if->core_params; ++ dcfg_data_t dcfg = {.d32 = 0 }; ++ depctl_data_t diepctl = {.d32 = 0 }; ++ grstctl_t resetctl = {.d32 = 0 }; ++ uint32_t rx_fifo_size; ++ fifosize_data_t nptxfifosize; ++ fifosize_data_t txfifosize; ++ dthrctl_data_t dthrctl; ++ fifosize_data_t ptxfifosize; ++ uint16_t rxfsiz, nptxfsiz; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ hwcfg3_data_t hwcfg3 = {.d32 = 0 }; ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ ++ /* Restart the Phy Clock */ ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ /* Restart the Phy Clock */ ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ dwc_udelay(10); ++ ++ /* Device configuration register */ ++ init_devspd(core_if); ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.descdma = (core_if->dma_desc_enable) ? 1 : 0; ++ dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80; ++ /* Enable Device OUT NAK in case of DDMA mode */ ++ if (core_if->core_params->dev_out_nak) { ++ dcfg.b.endevoutnak = 1; ++ } ++ ++ if (core_if->core_params->cont_on_bna) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.b.encontonbna = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } ++ /** should be done before every reset */ ++ if (core_if->otg_ver) { ++ core_if->otg_sts = 0; ++ gotgctl.b.devhnpen = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, gotgctl.d32, 0); ++ } ++ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ /* Configure data FIFO sizes */ ++ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { ++ DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n", ++ core_if->total_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n", ++ params->dev_rx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n", ++ params->dev_nperio_tx_fifo_size); ++ ++ /* Rx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->grxfsiz)); ++ ++#ifdef DWC_UTE_CFI ++ core_if->pwron_rxfsiz = DWC_READ_REG32(&global_regs->grxfsiz); ++ core_if->init_rxfsiz = params->dev_rx_fifo_size; ++#endif ++ rx_fifo_size = params->dev_rx_fifo_size; ++ DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size); ++ ++ DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->grxfsiz)); ++ ++ /** Set Periodic Tx FIFO Mask all bits 0 */ ++ core_if->p_tx_msk = 0; ++ ++ /** Set Tx FIFO Mask all bits 0 */ ++ core_if->tx_msk = 0; ++ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ /* Non-periodic Tx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); ++ ++ nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; ++ nptxfifosize.b.startaddr = params->dev_rx_fifo_size; ++ ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, ++ nptxfifosize.d32); ++ ++ DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); ++ ++ /**@todo NGS: Fix Periodic FIFO Sizing! */ ++ /* ++ * Periodic Tx FIFOs These FIFOs are numbered from 1 to 15. ++ * Indexes of the FIFO size module parameters in the ++ * dev_perio_tx_fifo_size array and the FIFO size registers in ++ * the dptxfsiz array run from 0 to 14. ++ */ ++ /** @todo Finish debug of this */ ++ ptxfifosize.b.startaddr = ++ nptxfifosize.b.startaddr + nptxfifosize.b.depth; ++ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { ++ ptxfifosize.b.depth = ++ params->dev_perio_tx_fifo_size[i]; ++ DWC_DEBUGPL(DBG_CIL, ++ "initial dtxfsiz[%d]=%08x\n", i, ++ DWC_READ_REG32(&global_regs->dtxfsiz ++ [i])); ++ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], ++ ptxfifosize.d32); ++ DWC_DEBUGPL(DBG_CIL, "new dtxfsiz[%d]=%08x\n", ++ i, ++ DWC_READ_REG32(&global_regs->dtxfsiz ++ [i])); ++ ptxfifosize.b.startaddr += ptxfifosize.b.depth; ++ } ++ } else { ++ /* ++ * Tx FIFOs These FIFOs are numbered from 1 to 15. ++ * Indexes of the FIFO size module parameters in the ++ * dev_tx_fifo_size array and the FIFO size registers in ++ * the dtxfsiz array run from 0 to 14. ++ */ ++ ++ /* Non-periodic Tx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); ++ ++#ifdef DWC_UTE_CFI ++ core_if->pwron_gnptxfsiz = ++ (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16); ++ core_if->init_gnptxfsiz = ++ params->dev_nperio_tx_fifo_size; ++#endif ++ nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; ++ nptxfifosize.b.startaddr = params->dev_rx_fifo_size; ++ ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, ++ nptxfifosize.d32); ++ ++ DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); ++ ++ txfifosize.b.startaddr = ++ nptxfifosize.b.startaddr + nptxfifosize.b.depth; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ ++ txfifosize.b.depth = ++ params->dev_tx_fifo_size[i]; ++ ++ DWC_DEBUGPL(DBG_CIL, ++ "initial dtxfsiz[%d]=%08x\n", ++ i, ++ DWC_READ_REG32(&global_regs->dtxfsiz ++ [i])); ++ ++#ifdef DWC_UTE_CFI ++ core_if->pwron_txfsiz[i] = ++ (DWC_READ_REG32 ++ (&global_regs->dtxfsiz[i]) >> 16); ++ core_if->init_txfsiz[i] = ++ params->dev_tx_fifo_size[i]; ++#endif ++ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], ++ txfifosize.d32); ++ ++ DWC_DEBUGPL(DBG_CIL, ++ "new dtxfsiz[%d]=%08x\n", ++ i, ++ DWC_READ_REG32(&global_regs->dtxfsiz ++ [i])); ++ ++ txfifosize.b.startaddr += txfifosize.b.depth; ++ } ++ ++ /* Calculating DFIFOCFG for Device mode to include RxFIFO and NPTXFIFO ++ * Before 3.00a EpInfoBase was being configured in ep enable/disable ++ * routine as well. Starting from 3.00a it will be set to the end of ++ * allocated FIFO space here due to ep 0 OUT always keeping enabled ++ */ ++ gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg); ++ hwcfg3.d32 = DWC_READ_REG32(&global_regs->ghwcfg3); ++ gdfifocfg.b.gdfifocfg = (DWC_READ_REG32(&global_regs->ghwcfg3) >> 16); ++ DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) { ++ rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff); ++ nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16); ++ gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz; ++ } else { ++ gdfifocfg.b.epinfobase = txfifosize.b.startaddr; ++ } ++ DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); ++ } ++ } ++ ++ /* Flush the FIFOs */ ++ dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ ++ dwc_otg_flush_rx_fifo(core_if); ++ ++ /* Flush the Learning Queue. */ ++ resetctl.b.intknqflsh = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); ++ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) { ++ core_if->start_predict = 0; ++ for (i = 0; i <= core_if->dev_if->num_in_eps; ++i) { ++ core_if->nextep_seq[i] = 0xff; // 0xff - EP not active ++ } ++ core_if->nextep_seq[0] = 0; ++ core_if->first_in_nextep_seq = 0; ++ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); ++ diepctl.b.nextep = 0; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); ++ ++ /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */ ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt = 2; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_CILV, ++ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_CILV, "%2d ", core_if->nextep_seq[i]); ++ } ++ DWC_DEBUGPL(DBG_CILV, "\n"); ++ } ++ ++ /* Clear all pending Device Interrupts */ ++ /** @todo - if the condition needed to be checked ++ * or in any case all pending interrutps should be cleared? ++ */ ++ if (core_if->multiproc_int_enable) { ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ DWC_WRITE_REG32(&dev_if->dev_global_regs-> ++ diepeachintmsk[i], 0); ++ } ++ ++ for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { ++ DWC_WRITE_REG32(&dev_if->dev_global_regs-> ++ doepeachintmsk[i], 0); ++ } ++ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->deachint, 0xFFFFFFFF); ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, 0); ++ } else { ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, 0); ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, 0); ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF); ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, 0); ++ } ++ ++ for (i = 0; i <= dev_if->num_in_eps; i++) { ++ depctl_data_t depctl; ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (depctl.b.epena) { ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ } else { ++ depctl.d32 = 0; ++ depctl.b.snak = 1; ++ } ++ ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); ++ ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, 0); ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, 0); ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepint, 0xFF); ++ } ++ ++ for (i = 1; i <= dev_if->num_out_eps; i++) { ++ depctl_data_t depctl; ++ depctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); ++ if (depctl.b.epena) { ++ int j = 0; ++ dctl_data_t dctl = {.d32 = 0 }; ++ gintmsk_data_t gintsts = {.d32 = 0 }; ++ doepint_data_t doepint = {.d32 = 0 }; ++ device_grxsts_data_t status; ++ dctl.b.sgoutnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ if (!core_if->dma_enable) { ++ do { ++ j++; ++ dwc_udelay(10); ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (j == 100000) { ++ DWC_ERROR("SNAK is not set during 10s\n"); ++ break; ++ } ++ } while (!gintsts.b.rxstsqlvl); ++ status.d32 = DWC_READ_REG32(&global_regs->grxstsp); ++ if (status.b.pktsts == DWC_DSTS_GOUT_NAK) ++ DWC_DEBUGPL(DBG_PCDV, "Global OUT NAK\n"); ++ gintsts.d32 = 0; ++ gintsts.b.rxstsqlvl = 1; ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ } ++ j = 0; ++ do { ++ j++; ++ dwc_udelay(10); ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (j == 100000) { ++ DWC_ERROR("SNAK is not set during 10s\n"); ++ break; ++ } ++ } while (!gintsts.b.goutnakeff); ++ gintsts.d32 = 0; ++ gintsts.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ j = 0; ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepctl, depctl.d32); ++ do { ++ dwc_udelay(10); ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[i]->doepint); ++ if (j == 100000) { ++ DWC_ERROR("EPDIS was not set during 10s\n"); ++ break; ++ } ++ } while (!doepint.b.epdisabled); ++ ++ doepint.b.epdisabled = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepint, doepint.d32); ++ ++ dctl.d32 = 0; ++ dctl.b.cgoutnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } else { ++ depctl.d32 = 0; ++ depctl.b.snak = 1; ++ } ++ ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32); ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doeptsiz, 0); ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepdma, 0); ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepint, 0xFF); ++ } ++ ++ if (core_if->en_multiple_tx_fifo && core_if->dma_enable) { ++ dev_if->non_iso_tx_thr_en = params->thr_ctl & 0x1; ++ dev_if->iso_tx_thr_en = (params->thr_ctl >> 1) & 0x1; ++ dev_if->rx_thr_en = (params->thr_ctl >> 2) & 0x1; ++ ++ dev_if->rx_thr_length = params->rx_thr_length; ++ dev_if->tx_thr_length = params->tx_thr_length; ++ ++ dev_if->setup_desc_index = 0; ++ ++ dthrctl.d32 = 0; ++ dthrctl.b.non_iso_thr_en = dev_if->non_iso_tx_thr_en; ++ dthrctl.b.iso_thr_en = dev_if->iso_tx_thr_en; ++ dthrctl.b.tx_thr_len = dev_if->tx_thr_length; ++ dthrctl.b.rx_thr_en = dev_if->rx_thr_en; ++ dthrctl.b.rx_thr_len = dev_if->rx_thr_length; ++ dthrctl.b.ahb_thr_ratio = params->ahb_thr_ratio; ++ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dtknqr3_dthrctl, ++ dthrctl.d32); ++ ++ DWC_DEBUGPL(DBG_CIL, ++ "Non ISO Tx Thr - %d\nISO Tx Thr - %d\nRx Thr - %d\nTx Thr Len - %d\nRx Thr Len - %d\n", ++ dthrctl.b.non_iso_thr_en, dthrctl.b.iso_thr_en, ++ dthrctl.b.rx_thr_en, dthrctl.b.tx_thr_len, ++ dthrctl.b.rx_thr_len); ++ ++ } ++ ++ dwc_otg_enable_device_interrupts(core_if); ++ ++ { ++ diepmsk_data_t msk = {.d32 = 0 }; ++ msk.b.txfifoundrn = 1; ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs-> ++ diepeachintmsk[0], msk.d32, msk.d32); ++ } else { ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, ++ msk.d32, msk.d32); ++ } ++ } ++ ++ if (core_if->multiproc_int_enable) { ++ /* Set NAK on Babble */ ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.b.nakonbble = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } ++ ++ if (core_if->snpsid >= OTG_CORE_REV_2_94a) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl); ++ dctl.b.sftdiscon = 0; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32); ++ } ++} ++ ++/** ++ * This function enables the Host mode interrupts. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ */ ++void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__); ++ ++ /* Disable all interrupts. */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* Clear any pending interrupts. */ ++ DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Enable the common interrupts */ ++ dwc_otg_enable_common_interrupts(core_if); ++ ++ /* ++ * Enable host mode interrupts without disturbing common ++ * interrupts. ++ */ ++ ++ intr_mask.b.disconnect = 1; ++ intr_mask.b.portintr = 1; ++ intr_mask.b.hcintr = 1; ++ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); ++} ++ ++/** ++ * This function disables the Host Mode interrupts. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ */ ++void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_CILV, "%s()\n", __func__); ++ ++ /* ++ * Disable host mode interrupts without disturbing common ++ * interrupts. ++ */ ++ intr_mask.b.sofintr = 1; ++ intr_mask.b.portintr = 1; ++ intr_mask.b.hcintr = 1; ++ intr_mask.b.ptxfempty = 1; ++ intr_mask.b.nptxfempty = 1; ++ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, 0); ++} ++ ++/** ++ * This function initializes the DWC_otg controller registers for ++ * host mode. ++ * ++ * This function flushes the Tx and Rx FIFOs and it flushes any entries in the ++ * request queues. Host channels are reset to ensure that they are ready for ++ * performing transfers. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ */ ++void dwc_otg_core_host_init(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ dwc_otg_host_if_t *host_if = core_if->host_if; ++ dwc_otg_core_params_t *params = core_if->core_params; ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ fifosize_data_t nptxfifosize; ++ fifosize_data_t ptxfifosize; ++ uint16_t rxfsiz, nptxfsiz, hptxfsiz; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ int i; ++ hcchar_data_t hcchar; ++ hcfg_data_t hcfg; ++ hfir_data_t hfir; ++ dwc_otg_hc_regs_t *hc_regs; ++ int num_channels; ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if); ++ ++ /* Restart the Phy Clock */ ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ dwc_udelay(10); ++ ++ if ((core_if->otg_ver == 1) && (core_if->op_state == A_HOST)) { ++ DWC_PRINTF("Init: Port Power? op_state=%d\n", core_if->op_state); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ DWC_PRINTF("Init: Power Port (%d)\n", hprt0.b.prtpwr); ++ if (hprt0.b.prtpwr == 0) { ++ hprt0.b.prtpwr = 1; ++ DWC_WRITE_REG32(host_if->hprt0, hprt0.d32); ++ } ++ } ++ ++ /* Initialize Host Configuration Register */ ++ init_fslspclksel(core_if); ++ if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) { ++ hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg); ++ hcfg.b.fslssupp = 1; ++ DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32); ++ ++ } ++ ++ /* This bit allows dynamic reloading of the HFIR register ++ * during runtime. This bit needs to be programmed during ++ * initial configuration and its value must not be changed ++ * during runtime.*/ ++ if (core_if->core_params->reload_ctl == 1) { ++ hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir); ++ hfir.b.hfirrldctrl = 1; ++ DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32); ++ } ++ ++ if (core_if->core_params->dma_desc_enable) { ++ uint8_t op_mode = core_if->hwcfg2.b.op_mode; ++ if (! ++ (core_if->hwcfg4.b.desc_dma ++ && (core_if->snpsid >= OTG_CORE_REV_2_90a) ++ && ((op_mode == DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ++ || (op_mode == DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) ++ || (op_mode == ++ DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG) ++ || (op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST) ++ || (op_mode == ++ DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST)))) { ++ ++ DWC_ERROR("Host can't operate in Descriptor DMA mode.\n" ++ "Either core version is below 2.90a or " ++ "GHWCFG2, GHWCFG4 registers' values do not allow Descriptor DMA in host mode.\n" ++ "To run the driver in Buffer DMA host mode set dma_desc_enable " ++ "module parameter to 0.\n"); ++ return; ++ } ++ hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg); ++ hcfg.b.descdma = 1; ++ DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32); ++ } ++ ++ /* Configure data FIFO sizes */ ++ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { ++ DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n", ++ core_if->total_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n", ++ params->host_rx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n", ++ params->host_nperio_tx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "P Tx FIFO Size=%d\n", ++ params->host_perio_tx_fifo_size); ++ ++ /* Rx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->grxfsiz)); ++ DWC_WRITE_REG32(&global_regs->grxfsiz, ++ params->host_rx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->grxfsiz)); ++ ++ /* Non-periodic Tx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); ++ nptxfifosize.b.depth = params->host_nperio_tx_fifo_size; ++ nptxfifosize.b.startaddr = params->host_rx_fifo_size; ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32); ++ DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); ++ ++ /* Periodic Tx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial hptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->hptxfsiz)); ++ ptxfifosize.b.depth = params->host_perio_tx_fifo_size; ++ ptxfifosize.b.startaddr = ++ nptxfifosize.b.startaddr + nptxfifosize.b.depth; ++ DWC_WRITE_REG32(&global_regs->hptxfsiz, ptxfifosize.d32); ++ DWC_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->hptxfsiz)); ++ ++ if (core_if->en_multiple_tx_fifo) { ++ /* Global DFIFOCFG calculation for Host mode - include RxFIFO, NPTXFIFO and HPTXFIFO */ ++ gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg); ++ rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff); ++ nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16); ++ hptxfsiz = (DWC_READ_REG32(&global_regs->hptxfsiz) >> 16); ++ gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz + hptxfsiz; ++ DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); ++ } ++ } ++ ++ /* TODO - check this */ ++ /* Clear Host Set HNP Enable in the OTG Control Register */ ++ gotgctl.b.hstsethnpen = 1; ++ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ /* Make sure the FIFOs are flushed. */ ++ dwc_otg_flush_tx_fifo(core_if, 0x10 /* all TX FIFOs */ ); ++ dwc_otg_flush_rx_fifo(core_if); ++ ++ /* Clear Host Set HNP Enable in the OTG Control Register */ ++ gotgctl.b.hstsethnpen = 1; ++ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ ++ if (!core_if->core_params->dma_desc_enable) { ++ /* Flush out any leftover queued requests. */ ++ num_channels = core_if->core_params->host_channels; ++ ++ for (i = 0; i < num_channels; i++) { ++ hc_regs = core_if->host_if->hc_regs[i]; ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.chen = 0; ++ hcchar.b.chdis = 1; ++ hcchar.b.epdir = 0; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ } ++ ++ /* Halt all channels to put them into a known state. */ ++ for (i = 0; i < num_channels; i++) { ++ int count = 0; ++ hc_regs = core_if->host_if->hc_regs[i]; ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 1; ++ hcchar.b.epdir = 0; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ DWC_DEBUGPL(DBG_HCDV, "%s: Halt channel %d\n", __func__, i); ++ do { ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (++count > 1000) { ++ DWC_ERROR ++ ("%s: Unable to clear halt on channel %d\n", ++ __func__, i); ++ break; ++ } ++ dwc_udelay(1); ++ } while (hcchar.b.chen); ++ } ++ } ++ ++ /* Turn on the vbus power. */ ++ if ((core_if->otg_ver == 0) && (core_if->op_state == A_HOST)) { ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ DWC_PRINTF("Init: Power Port (%d)\n", hprt0.b.prtpwr); ++ if (hprt0.b.prtpwr == 0) { ++ hprt0.b.prtpwr = 1; ++ DWC_WRITE_REG32(host_if->hprt0, hprt0.d32); ++ } ++ } ++ ++ dwc_otg_enable_host_interrupts(core_if); ++} ++ ++/** ++ * Prepares a host channel for transferring packets to/from a specific ++ * endpoint. The HCCHARn register is set up with the characteristics specified ++ * in _hc. Host channel interrupts that may need to be serviced while this ++ * transfer is in progress are enabled. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * @param hc Information needed to initialize the host channel ++ */ ++void dwc_otg_hc_init(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ uint32_t intr_enable; ++ hcintmsk_data_t hc_intr_mask; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ hcchar_data_t hcchar; ++ hcsplt_data_t hcsplt; ++ ++ uint8_t hc_num = hc->hc_num; ++ dwc_otg_host_if_t *host_if = core_if->host_if; ++ dwc_otg_hc_regs_t *hc_regs = host_if->hc_regs[hc_num]; ++ ++ /* Clear old interrupt conditions for this host channel. */ ++ hc_intr_mask.d32 = 0xFFFFFFFF; ++ hc_intr_mask.b.reserved14_31 = 0; ++ DWC_WRITE_REG32(&hc_regs->hcint, hc_intr_mask.d32); ++ ++ /* Enable channel interrupts required for this transfer. */ ++ hc_intr_mask.d32 = 0; ++ hc_intr_mask.b.chhltd = 1; ++ if (core_if->dma_enable) { ++ /* For Descriptor DMA mode core halts the channel on AHB error. Interrupt is not required */ ++ if (!core_if->dma_desc_enable) ++ hc_intr_mask.b.ahberr = 1; ++ else { ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) ++ hc_intr_mask.b.xfercompl = 1; ++ } ++ ++ if (hc->error_state && !hc->do_split && ++ hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { ++ hc_intr_mask.b.ack = 1; ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.datatglerr = 1; ++ if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) { ++ hc_intr_mask.b.nak = 1; ++ } ++ } ++ } ++ } else { ++ switch (hc->ep_type) { ++ case DWC_OTG_EP_TYPE_CONTROL: ++ case DWC_OTG_EP_TYPE_BULK: ++ hc_intr_mask.b.xfercompl = 1; ++ hc_intr_mask.b.stall = 1; ++ hc_intr_mask.b.xacterr = 1; ++ hc_intr_mask.b.datatglerr = 1; ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.bblerr = 1; ++ } else { ++ hc_intr_mask.b.nak = 1; ++ hc_intr_mask.b.nyet = 1; ++ if (hc->do_ping) { ++ hc_intr_mask.b.ack = 1; ++ } ++ } ++ ++ if (hc->do_split) { ++ hc_intr_mask.b.nak = 1; ++ if (hc->complete_split) { ++ hc_intr_mask.b.nyet = 1; ++ } else { ++ hc_intr_mask.b.ack = 1; ++ } ++ } ++ ++ if (hc->error_state) { ++ hc_intr_mask.b.ack = 1; ++ } ++ break; ++ case DWC_OTG_EP_TYPE_INTR: ++ hc_intr_mask.b.xfercompl = 1; ++ hc_intr_mask.b.nak = 1; ++ hc_intr_mask.b.stall = 1; ++ hc_intr_mask.b.xacterr = 1; ++ hc_intr_mask.b.datatglerr = 1; ++ hc_intr_mask.b.frmovrun = 1; ++ ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.bblerr = 1; ++ } ++ if (hc->error_state) { ++ hc_intr_mask.b.ack = 1; ++ } ++ if (hc->do_split) { ++ if (hc->complete_split) { ++ hc_intr_mask.b.nyet = 1; ++ } else { ++ hc_intr_mask.b.ack = 1; ++ } ++ } ++ break; ++ case DWC_OTG_EP_TYPE_ISOC: ++ hc_intr_mask.b.xfercompl = 1; ++ hc_intr_mask.b.frmovrun = 1; ++ hc_intr_mask.b.ack = 1; ++ ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.xacterr = 1; ++ hc_intr_mask.b.bblerr = 1; ++ } ++ break; ++ } ++ } ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, hc_intr_mask.d32); ++ ++ /* Enable the top level host channel interrupt. */ ++ intr_enable = (1 << hc_num); ++ DWC_MODIFY_REG32(&host_if->host_global_regs->haintmsk, 0, intr_enable); ++ ++ /* Make sure host channel interrupts are enabled. */ ++ gintmsk.b.hcintr = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32); ++ ++ /* ++ * Program the HCCHARn register with the endpoint characteristics for ++ * the current transfer. ++ */ ++ hcchar.d32 = 0; ++ hcchar.b.devaddr = hc->dev_addr; ++ hcchar.b.epnum = hc->ep_num; ++ hcchar.b.epdir = hc->ep_is_in; ++ hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW); ++ hcchar.b.eptype = hc->ep_type; ++ hcchar.b.mps = hc->max_packet; ++ ++ DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32); ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " Dev Addr: %d\n", hcchar.b.devaddr); ++ DWC_DEBUGPL(DBG_HCDV, " Ep Num: %d\n", hcchar.b.epnum); ++ DWC_DEBUGPL(DBG_HCDV, " Is In: %d\n", hcchar.b.epdir); ++ DWC_DEBUGPL(DBG_HCDV, " Is Low Speed: %d\n", hcchar.b.lspddev); ++ DWC_DEBUGPL(DBG_HCDV, " Ep Type: %d\n", hcchar.b.eptype); ++ DWC_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n", hcchar.b.mps); ++ DWC_DEBUGPL(DBG_HCDV, " Multi Cnt: %d\n", hcchar.b.multicnt); ++ ++ /* ++ * Program the HCSPLIT register for SPLITs ++ */ ++ hcsplt.d32 = 0; ++ if (hc->do_split) { ++ DWC_DEBUGPL(DBG_HCDV, "Programming HC %d with split --> %s\n", ++ hc->hc_num, ++ hc->complete_split ? "CSPLIT" : "SSPLIT"); ++ hcsplt.b.compsplt = hc->complete_split; ++ hcsplt.b.xactpos = hc->xact_pos; ++ hcsplt.b.hubaddr = hc->hub_addr; ++ hcsplt.b.prtaddr = hc->port_addr; ++ DWC_DEBUGPL(DBG_HCDV, " comp split %d\n", hc->complete_split); ++ DWC_DEBUGPL(DBG_HCDV, " xact pos %d\n", hc->xact_pos); ++ DWC_DEBUGPL(DBG_HCDV, " hub addr %d\n", hc->hub_addr); ++ DWC_DEBUGPL(DBG_HCDV, " port addr %d\n", hc->port_addr); ++ DWC_DEBUGPL(DBG_HCDV, " is_in %d\n", hc->ep_is_in); ++ DWC_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n", hcchar.b.mps); ++ DWC_DEBUGPL(DBG_HCDV, " xferlen: %d\n", hc->xfer_len); ++ } ++ DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32); ++ ++} ++ ++/** ++ * Attempts to halt a host channel. This function should only be called in ++ * Slave mode or to abort a transfer in either Slave mode or DMA mode. Under ++ * normal circumstances in DMA mode, the controller halts the channel when the ++ * transfer is complete or a condition occurs that requires application ++ * intervention. ++ * ++ * In slave mode, checks for a free request queue entry, then sets the Channel ++ * Enable and Channel Disable bits of the Host Channel Characteristics ++ * register of the specified channel to intiate the halt. If there is no free ++ * request queue entry, sets only the Channel Disable bit of the HCCHARn ++ * register to flush requests for this channel. In the latter case, sets a ++ * flag to indicate that the host channel needs to be halted when a request ++ * queue slot is open. ++ * ++ * In DMA mode, always sets the Channel Enable and Channel Disable bits of the ++ * HCCHARn register. The controller ensures there is space in the request ++ * queue before submitting the halt request. ++ * ++ * Some time may elapse before the core flushes any posted requests for this ++ * host channel and halts. The Channel Halted interrupt handler completes the ++ * deactivation of the host channel. ++ * ++ * @param core_if Controller register interface. ++ * @param hc Host channel to halt. ++ * @param halt_status Reason for halting the channel. ++ */ ++void dwc_otg_hc_halt(dwc_otg_core_if_t * core_if, ++ dwc_hc_t * hc, dwc_otg_halt_status_e halt_status) ++{ ++ gnptxsts_data_t nptxsts; ++ hptxsts_data_t hptxsts; ++ hcchar_data_t hcchar; ++ dwc_otg_hc_regs_t *hc_regs; ++ dwc_otg_core_global_regs_t *global_regs; ++ dwc_otg_host_global_regs_t *host_global_regs; ++ ++ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ global_regs = core_if->core_global_regs; ++ host_global_regs = core_if->host_if->host_global_regs; ++ ++ DWC_ASSERT(!(halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS), ++ "halt_status = %d\n", halt_status); ++ ++ if (halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE || ++ halt_status == DWC_OTG_HC_XFER_AHB_ERR) { ++ /* ++ * Disable all channel interrupts except Ch Halted. The QTD ++ * and QH state associated with this transfer has been cleared ++ * (in the case of URB_DEQUEUE), so the channel needs to be ++ * shut down carefully to prevent crashes. ++ */ ++ hcintmsk_data_t hcintmsk; ++ hcintmsk.d32 = 0; ++ hcintmsk.b.chhltd = 1; ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, hcintmsk.d32); ++ ++ /* ++ * Make sure no other interrupts besides halt are currently ++ * pending. Handling another interrupt could cause a crash due ++ * to the QTD and QH state. ++ */ ++ DWC_WRITE_REG32(&hc_regs->hcint, ~hcintmsk.d32); ++ ++ /* ++ * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR ++ * even if the channel was already halted for some other ++ * reason. ++ */ ++ hc->halt_status = halt_status; ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen == 0) { ++ /* ++ * The channel is either already halted or it hasn't ++ * started yet. In DMA mode, the transfer may halt if ++ * it finishes normally or a condition occurs that ++ * requires driver intervention. Don't want to halt ++ * the channel again. In either Slave or DMA mode, ++ * it's possible that the transfer has been assigned ++ * to a channel, but not started yet when an URB is ++ * dequeued. Don't want to halt a channel that hasn't ++ * started yet. ++ */ ++ return; ++ } ++ } ++ if (hc->halt_pending) { ++ /* ++ * A halt has already been issued for this channel. This might ++ * happen when a transfer is aborted by a higher level in ++ * the stack. ++ */ ++#ifdef DEBUG ++ DWC_PRINTF ++ ("*** %s: Channel %d, _hc->halt_pending already set ***\n", ++ __func__, hc->hc_num); ++ ++#endif ++ return; ++ } ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* No need to set the bit in DDMA for disabling the channel */ ++ //TODO check it everywhere channel is disabled ++ if (!core_if->core_params->dma_desc_enable) ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 1; ++ ++ if (!core_if->dma_enable) { ++ /* Check for space in the request queue to issue the halt. */ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || ++ hc->ep_type == DWC_OTG_EP_TYPE_BULK) { ++ nptxsts.d32 = DWC_READ_REG32(&global_regs->gnptxsts); ++ if (nptxsts.b.nptxqspcavail == 0) { ++ hcchar.b.chen = 0; ++ } ++ } else { ++ hptxsts.d32 = ++ DWC_READ_REG32(&host_global_regs->hptxsts); ++ if ((hptxsts.b.ptxqspcavail == 0) ++ || (core_if->queuing_high_bandwidth)) { ++ hcchar.b.chen = 0; ++ } ++ } ++ } ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ hc->halt_status = halt_status; ++ ++ if (hcchar.b.chen) { ++ hc->halt_pending = 1; ++ hc->halt_on_queue = 0; ++ } else { ++ hc->halt_on_queue = 1; ++ } ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " hcchar: 0x%08x\n", hcchar.d32); ++ DWC_DEBUGPL(DBG_HCDV, " halt_pending: %d\n", hc->halt_pending); ++ DWC_DEBUGPL(DBG_HCDV, " halt_on_queue: %d\n", hc->halt_on_queue); ++ DWC_DEBUGPL(DBG_HCDV, " halt_status: %d\n", hc->halt_status); ++ ++ return; ++} ++ ++/** ++ * Clears the transfer state for a host channel. This function is normally ++ * called after a transfer is done and the host channel is being released. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param hc Identifies the host channel to clean up. ++ */ ++void dwc_otg_hc_cleanup(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ dwc_otg_hc_regs_t *hc_regs; ++ ++ hc->xfer_started = 0; ++ ++ /* ++ * Clear channel interrupt enables and any unhandled channel interrupt ++ * conditions. ++ */ ++ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0); ++ DWC_WRITE_REG32(&hc_regs->hcint, 0xFFFFFFFF); ++#ifdef DEBUG ++ DWC_TIMER_CANCEL(core_if->hc_xfer_timer[hc->hc_num]); ++#endif ++} ++ ++/** ++ * Sets the channel property that indicates in which frame a periodic transfer ++ * should occur. This is always set to the _next_ frame. This function has no ++ * effect on non-periodic transfers. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param hc Identifies the host channel to set up and its properties. ++ * @param hcchar Current value of the HCCHAR register for the specified host ++ * channel. ++ */ ++static inline void hc_set_even_odd_frame(dwc_otg_core_if_t * core_if, ++ dwc_hc_t * hc, hcchar_data_t * hcchar) ++{ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ hfnum_data_t hfnum; ++ hfnum.d32 = ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->hfnum); ++ ++ /* 1 if _next_ frame is odd, 0 if it's even */ ++ hcchar->b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1; ++#ifdef DEBUG ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR && hc->do_split ++ && !hc->complete_split) { ++ switch (hfnum.b.frnum & 0x7) { ++ case 7: ++ core_if->hfnum_7_samples++; ++ core_if->hfnum_7_frrem_accum += hfnum.b.frrem; ++ break; ++ case 0: ++ core_if->hfnum_0_samples++; ++ core_if->hfnum_0_frrem_accum += hfnum.b.frrem; ++ break; ++ default: ++ core_if->hfnum_other_samples++; ++ core_if->hfnum_other_frrem_accum += ++ hfnum.b.frrem; ++ break; ++ } ++ } ++#endif ++ } ++} ++ ++#ifdef DEBUG ++void hc_xfer_timeout(void *ptr) ++{ ++ hc_xfer_info_t *xfer_info = NULL; ++ int hc_num = 0; ++ ++ if (ptr) ++ xfer_info = (hc_xfer_info_t *) ptr; ++ ++ if (!xfer_info->hc) { ++ DWC_ERROR("xfer_info->hc = %p\n", xfer_info->hc); ++ return; ++ } ++ ++ hc_num = xfer_info->hc->hc_num; ++ DWC_WARN("%s: timeout on channel %d\n", __func__, hc_num); ++ DWC_WARN(" start_hcchar_val 0x%08x\n", ++ xfer_info->core_if->start_hcchar_val[hc_num]); ++} ++#endif ++ ++void ep_xfer_timeout(void *ptr) ++{ ++ ep_xfer_info_t *xfer_info = NULL; ++ int ep_num = 0; ++ dctl_data_t dctl = {.d32 = 0 }; ++ gintsts_data_t gintsts = {.d32 = 0 }; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ if (ptr) ++ xfer_info = (ep_xfer_info_t *) ptr; ++ ++ if (!xfer_info->ep) { ++ DWC_ERROR("xfer_info->ep = %p\n", xfer_info->ep); ++ return; ++ } ++ ++ ep_num = xfer_info->ep->num; ++ DWC_WARN("%s: timeout on endpoit %d\n", __func__, ep_num); ++ /* Put the sate to 2 as it was time outed */ ++ xfer_info->state = 2; ++ ++ dctl.d32 = ++ DWC_READ_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl); ++ gintsts.d32 = ++ DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintsts); ++ gintmsk.d32 = ++ DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintmsk); ++ ++ if (!gintmsk.b.goutnakeff) { ++ /* Unmask it */ ++ gintmsk.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&xfer_info->core_if->core_global_regs->gintmsk, ++ gintmsk.d32); ++ ++ } ++ ++ if (!gintsts.b.goutnakeff) { ++ dctl.b.sgoutnak = 1; ++ } ++ DWC_WRITE_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ ++} ++ ++void set_pid_isoc(dwc_hc_t * hc) ++{ ++ /* Set up the initial PID for the transfer. */ ++ if (hc->speed == DWC_OTG_EP_SPEED_HIGH) { ++ if (hc->ep_is_in) { ++ if (hc->multi_count == 1) { ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA0; ++ } else if (hc->multi_count == 2) { ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA1; ++ } else { ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA2; ++ } ++ } else { ++ if (hc->multi_count == 1) { ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA0; ++ } else { ++ hc->data_pid_start = DWC_OTG_HC_PID_MDATA; ++ } ++ } ++ } else { ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA0; ++ } ++} ++ ++/** ++ * This function does the setup for a data transfer for a host channel and ++ * starts the transfer. May be called in either Slave mode or DMA mode. In ++ * Slave mode, the caller must ensure that there is sufficient space in the ++ * request queue and Tx Data FIFO. ++ * ++ * For an OUT transfer in Slave mode, it loads a data packet into the ++ * appropriate FIFO. If necessary, additional data packets will be loaded in ++ * the Host ISR. ++ * ++ * For an IN transfer in Slave mode, a data packet is requested. The data ++ * packets are unloaded from the Rx FIFO in the Host ISR. If necessary, ++ * additional data packets are requested in the Host ISR. ++ * ++ * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ ++ * register along with a packet count of 1 and the channel is enabled. This ++ * causes a single PING transaction to occur. Other fields in HCTSIZ are ++ * simply set to 0 since no data transfer occurs in this case. ++ * ++ * For a PING transfer in DMA mode, the HCTSIZ register is initialized with ++ * all the information required to perform the subsequent data transfer. In ++ * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the ++ * controller performs the entire PING protocol, then starts the data ++ * transfer. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param hc Information needed to initialize the host channel. The xfer_len ++ * value may be reduced to accommodate the max widths of the XferSize and ++ * PktCnt fields in the HCTSIZn register. The multi_count value may be changed ++ * to reflect the final xfer_len value. ++ */ ++void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ uint16_t num_packets; ++ uint32_t max_hc_xfer_size = core_if->core_params->max_transfer_size; ++ uint16_t max_hc_pkt_count = core_if->core_params->max_packet_count; ++ dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ ++ hctsiz.d32 = 0; ++ ++ if (hc->do_ping) { ++ if (!core_if->dma_enable) { ++ dwc_otg_hc_do_ping(core_if, hc); ++ hc->xfer_started = 1; ++ return; ++ } else { ++ hctsiz.b.dopng = 1; ++ } ++ } ++ ++ if (hc->do_split) { ++ num_packets = 1; ++ ++ if (hc->complete_split && !hc->ep_is_in) { ++ /* For CSPLIT OUT Transfer, set the size to 0 so the ++ * core doesn't expect any data written to the FIFO */ ++ hc->xfer_len = 0; ++ } else if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) { ++ hc->xfer_len = hc->max_packet; ++ } else if (!hc->ep_is_in && (hc->xfer_len > 188)) { ++ hc->xfer_len = 188; ++ } ++ ++ hctsiz.b.xfersize = hc->xfer_len; ++ } else { ++ /* ++ * Ensure that the transfer length and packet count will fit ++ * in the widths allocated for them in the HCTSIZn register. ++ */ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * Make sure the transfer size is no larger than one ++ * (micro)frame's worth of data. (A check was done ++ * when the periodic transfer was accepted to ensure ++ * that a (micro)frame's worth of data can be ++ * programmed into a channel.) ++ */ ++ uint32_t max_periodic_len = ++ hc->multi_count * hc->max_packet; ++ if (hc->xfer_len > max_periodic_len) { ++ hc->xfer_len = max_periodic_len; ++ } else { ++ } ++ } else if (hc->xfer_len > max_hc_xfer_size) { ++ /* Make sure that xfer_len is a multiple of max packet size. */ ++ hc->xfer_len = max_hc_xfer_size - hc->max_packet + 1; ++ } ++ ++ if (hc->xfer_len > 0) { ++ num_packets = ++ (hc->xfer_len + hc->max_packet - ++ 1) / hc->max_packet; ++ if (num_packets > max_hc_pkt_count) { ++ num_packets = max_hc_pkt_count; ++ hc->xfer_len = num_packets * hc->max_packet; ++ } ++ } else { ++ /* Need 1 packet for transfer length of 0. */ ++ num_packets = 1; ++ } ++ ++ if (hc->ep_is_in) { ++ /* Always program an integral # of max packets for IN transfers. */ ++ hc->xfer_len = num_packets * hc->max_packet; ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * Make sure that the multi_count field matches the ++ * actual transfer length. ++ */ ++ hc->multi_count = num_packets; ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) ++ set_pid_isoc(hc); ++ ++ hctsiz.b.xfersize = hc->xfer_len; ++ } ++ ++ hc->start_pkt_count = num_packets; ++ hctsiz.b.pktcnt = num_packets; ++ hctsiz.b.pid = hc->data_pid_start; ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " Xfer Size: %d\n", hctsiz.b.xfersize); ++ DWC_DEBUGPL(DBG_HCDV, " Num Pkts: %d\n", hctsiz.b.pktcnt); ++ DWC_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid); ++ ++ if (core_if->dma_enable) { ++ dwc_dma_t dma_addr; ++ if (hc->align_buff) { ++ dma_addr = hc->align_buff; ++ } else { ++ dma_addr = ((unsigned long)hc->xfer_buff & 0xffffffff); ++ } ++ DWC_WRITE_REG32(&hc_regs->hcdma, dma_addr); ++ } ++ ++ /* Start the split */ ++ if (hc->do_split) { ++ hcsplt_data_t hcsplt; ++ hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt); ++ hcsplt.b.spltena = 1; ++ DWC_WRITE_REG32(&hc_regs->hcsplt, hcsplt.d32); ++ } ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.multicnt = hc->multi_count; ++ hc_set_even_odd_frame(core_if, hc, &hcchar); ++#ifdef DEBUG ++ core_if->start_hcchar_val[hc->hc_num] = hcchar.d32; ++ if (hcchar.b.chdis) { ++ DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n", ++ __func__, hc->hc_num, hcchar.d32); ++ } ++#endif ++ ++ /* Set host channel enable after all other setup is complete. */ ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 0; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ hc->xfer_started = 1; ++ hc->requests++; ++ ++ if (!core_if->dma_enable && !hc->ep_is_in && hc->xfer_len > 0) { ++ /* Load OUT packet into the appropriate Tx FIFO. */ ++ dwc_otg_hc_write_packet(core_if, hc); ++ } ++#ifdef DEBUG ++ if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) { ++ core_if->hc_xfer_info[hc->hc_num].core_if = core_if; ++ core_if->hc_xfer_info[hc->hc_num].hc = hc; ++ ++ /* Start a timer for this transfer. */ ++ DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000); ++ } ++#endif ++} ++ ++/** ++ * This function does the setup for a data transfer for a host channel ++ * and starts the transfer in Descriptor DMA mode. ++ * ++ * Initializes HCTSIZ register. For a PING transfer the Do Ping bit is set. ++ * Sets PID and NTD values. For periodic transfers ++ * initializes SCHED_INFO field with micro-frame bitmap. ++ * ++ * Initializes HCDMA register with descriptor list address and CTD value ++ * then starts the transfer via enabling the channel. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param hc Information needed to initialize the host channel. ++ */ ++void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ hcdma_data_t hcdma; ++ ++ hctsiz.d32 = 0; ++ ++ if (hc->do_ping) ++ hctsiz.b_ddma.dopng = 1; ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) ++ set_pid_isoc(hc); ++ ++ /* Packet Count and Xfer Size are not used in Descriptor DMA mode */ ++ hctsiz.b_ddma.pid = hc->data_pid_start; ++ hctsiz.b_ddma.ntd = hc->ntd - 1; /* 0 - 1 descriptor, 1 - 2 descriptors, etc. */ ++ hctsiz.b_ddma.schinfo = hc->schinfo; /* Non-zero only for high-speed interrupt endpoints */ ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid); ++ DWC_DEBUGPL(DBG_HCDV, " NTD: %d\n", hctsiz.b_ddma.ntd); ++ ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ hcdma.d32 = 0; ++ hcdma.b.dma_addr = ((uint32_t) hc->desc_list_addr) >> 11; ++ ++ /* Always start from first descriptor. */ ++ hcdma.b.ctd = 0; ++ DWC_WRITE_REG32(&hc_regs->hcdma, hcdma.d32); ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.multicnt = hc->multi_count; ++ ++#ifdef DEBUG ++ core_if->start_hcchar_val[hc->hc_num] = hcchar.d32; ++ if (hcchar.b.chdis) { ++ DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n", ++ __func__, hc->hc_num, hcchar.d32); ++ } ++#endif ++ ++ /* Set host channel enable after all other setup is complete. */ ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 0; ++ ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ hc->xfer_started = 1; ++ hc->requests++; ++ ++#ifdef DEBUG ++ if ((hc->ep_type != DWC_OTG_EP_TYPE_INTR) ++ && (hc->ep_type != DWC_OTG_EP_TYPE_ISOC)) { ++ core_if->hc_xfer_info[hc->hc_num].core_if = core_if; ++ core_if->hc_xfer_info[hc->hc_num].hc = hc; ++ /* Start a timer for this transfer. */ ++ DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000); ++ } ++#endif ++ ++} ++ ++/** ++ * This function continues a data transfer that was started by previous call ++ * to dwc_otg_hc_start_transfer. The caller must ensure there is ++ * sufficient space in the request queue and Tx Data FIFO. This function ++ * should only be called in Slave mode. In DMA mode, the controller acts ++ * autonomously to complete transfers programmed to a host channel. ++ * ++ * For an OUT transfer, a new data packet is loaded into the appropriate FIFO ++ * if there is any data remaining to be queued. For an IN transfer, another ++ * data packet is always requested. For the SETUP phase of a control transfer, ++ * this function does nothing. ++ * ++ * @return 1 if a new request is queued, 0 if no more requests are required ++ * for this transfer. ++ */ ++int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ ++ if (hc->do_split) { ++ /* SPLITs always queue just once per channel */ ++ return 0; ++ } else if (hc->data_pid_start == DWC_OTG_HC_PID_SETUP) { ++ /* SETUPs are queued only once since they can't be NAKed. */ ++ return 0; ++ } else if (hc->ep_is_in) { ++ /* ++ * Always queue another request for other IN transfers. If ++ * back-to-back INs are issued and NAKs are received for both, ++ * the driver may still be processing the first NAK when the ++ * second NAK is received. When the interrupt handler clears ++ * the NAK interrupt for the first NAK, the second NAK will ++ * not be seen. So we can't depend on the NAK interrupt ++ * handler to requeue a NAKed request. Instead, IN requests ++ * are issued each time this function is called. When the ++ * transfer completes, the extra requests for the channel will ++ * be flushed. ++ */ ++ hcchar_data_t hcchar; ++ dwc_otg_hc_regs_t *hc_regs = ++ core_if->host_if->hc_regs[hc->hc_num]; ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hc_set_even_odd_frame(core_if, hc, &hcchar); ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 0; ++ DWC_DEBUGPL(DBG_HCDV, " IN xfer: hcchar = 0x%08x\n", ++ hcchar.d32); ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ hc->requests++; ++ return 1; ++ } else { ++ /* OUT transfers. */ ++ if (hc->xfer_count < hc->xfer_len) { ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ hcchar_data_t hcchar; ++ dwc_otg_hc_regs_t *hc_regs; ++ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hc_set_even_odd_frame(core_if, hc, &hcchar); ++ } ++ ++ /* Load OUT packet into the appropriate Tx FIFO. */ ++ dwc_otg_hc_write_packet(core_if, hc); ++ hc->requests++; ++ return 1; ++ } else { ++ return 0; ++ } ++ } ++} ++ ++/** ++ * Starts a PING transfer. This function should only be called in Slave mode. ++ * The Do Ping bit is set in the HCTSIZ register, then the channel is enabled. ++ */ ++void dwc_otg_hc_do_ping(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ ++ hctsiz.d32 = 0; ++ hctsiz.b.dopng = 1; ++ hctsiz.b.pktcnt = 1; ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 0; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++} ++ ++/* ++ * This function writes a packet into the Tx FIFO associated with the Host ++ * Channel. For a channel associated with a non-periodic EP, the non-periodic ++ * Tx FIFO is written. For a channel associated with a periodic EP, the ++ * periodic Tx FIFO is written. This function should only be called in Slave ++ * mode. ++ * ++ * Upon return the xfer_buff and xfer_count fields in _hc are incremented by ++ * then number of bytes written to the Tx FIFO. ++ */ ++void dwc_otg_hc_write_packet(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ uint32_t i; ++ uint32_t remaining_count; ++ uint32_t byte_count; ++ uint32_t dword_count; ++ ++ uint32_t *data_buff = (uint32_t *) (hc->xfer_buff); ++ uint32_t *data_fifo = core_if->data_fifo[hc->hc_num]; ++ ++ remaining_count = hc->xfer_len - hc->xfer_count; ++ if (remaining_count > hc->max_packet) { ++ byte_count = hc->max_packet; ++ } else { ++ byte_count = remaining_count; ++ } ++ ++ dword_count = (byte_count + 3) / 4; ++ ++ if ((((unsigned long)data_buff) & 0x3) == 0) { ++ /* xfer_buff is DWORD aligned. */ ++ for (i = 0; i < dword_count; i++, data_buff++) { ++ DWC_WRITE_REG32(data_fifo, *data_buff); ++ } ++ } else { ++ /* xfer_buff is not DWORD aligned. */ ++ for (i = 0; i < dword_count; i++, data_buff++) { ++ uint32_t data; ++ data = ++ (data_buff[0] | data_buff[1] << 8 | data_buff[2] << ++ 16 | data_buff[3] << 24); ++ DWC_WRITE_REG32(data_fifo, data); ++ } ++ } ++ ++ hc->xfer_count += byte_count; ++ hc->xfer_buff += byte_count; ++} ++ ++/** ++ * Gets the current USB frame number. This is the frame number from the last ++ * SOF packet. ++ */ ++uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * core_if) ++{ ++ dsts_data_t dsts; ++ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ /* read current frame/microframe number from DSTS register */ ++ return dsts.b.soffn; ++} ++ ++/** ++ * Calculates and gets the frame Interval value of HFIR register according PHY ++ * type and speed.The application can modify a value of HFIR register only after ++ * the Port Enable bit of the Host Port Control and Status register ++ * (HPRT.PrtEnaPort) has been set. ++*/ ++ ++uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if) ++{ ++ gusbcfg_data_t usbcfg; ++ hwcfg2_data_t hwcfg2; ++ hprt0_data_t hprt0; ++ int clock = 60; // default value ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ hwcfg2.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2); ++ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); ++ if (!usbcfg.b.physel && usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif) ++ clock = 60; ++ if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 3) ++ clock = 48; ++ if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel && ++ !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif) ++ clock = 30; ++ if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel && ++ !usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif) ++ clock = 60; ++ if (usbcfg.b.phylpwrclksel && !usbcfg.b.physel && ++ !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif) ++ clock = 48; ++ if (usbcfg.b.physel && !usbcfg.b.phyif && hwcfg2.b.fs_phy_type == 2) ++ clock = 48; ++ if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 1) ++ clock = 48; ++ if (hprt0.b.prtspd == 0) ++ /* High speed case */ ++ return 125 * clock; ++ else ++ /* FS/LS case */ ++ return 1000 * clock; ++} ++ ++/** ++ * This function reads a setup packet from the Rx FIFO into the destination ++ * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl) ++ * Interrupt routine when a SETUP packet has been received in Slave mode. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param dest Destination buffer for packet data. ++ */ ++void dwc_otg_read_setup_packet(dwc_otg_core_if_t * core_if, uint32_t * dest) ++{ ++ device_grxsts_data_t status; ++ /* Get the 8 bytes of a setup transaction data */ ++ ++ /* Pop 2 DWORDS off the receive data FIFO into memory */ ++ dest[0] = DWC_READ_REG32(core_if->data_fifo[0]); ++ dest[1] = DWC_READ_REG32(core_if->data_fifo[0]); ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ status.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->grxstsp); ++ DWC_DEBUGPL(DBG_ANY, ++ "EP:%d BCnt:%d " "pktsts:%x Frame:%d(0x%0x)\n", ++ status.b.epnum, status.b.bcnt, status.b.pktsts, ++ status.b.fn, status.b.fn); ++ } ++} ++ ++/** ++ * This function enables EP0 OUT to receive SETUP packets and configures EP0 ++ * IN for transmitting packets. It is normally called when the ++ * "Enumeration Done" interrupt occurs. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP0 data. ++ */ ++void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dsts_data_t dsts; ++ depctl_data_t diepctl; ++ depctl_data_t doepctl; ++ dctl_data_t dctl = {.d32 = 0 }; ++ ++ ep->stp_rollover = 0; ++ /* Read the Device Status and Endpoint 0 Control registers */ ++ dsts.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dsts); ++ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); ++ doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl); ++ ++ /* Set the MPS of the IN EP based on the enumeration speed */ ++ switch (dsts.b.enumspd) { ++ case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: ++ case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: ++ case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ: ++ diepctl.b.mps = DWC_DEP0CTL_MPS_64; ++ break; ++ case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ: ++ diepctl.b.mps = DWC_DEP0CTL_MPS_8; ++ break; ++ } ++ ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); ++ ++ /* Enable OUT EP for receive */ ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) { ++ doepctl.b.epena = 1; ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); ++ } ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n", ++ DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl)); ++ DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n", ++ DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl)); ++#endif ++ dctl.b.cgnpinnak = 1; ++ ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ DWC_DEBUGPL(DBG_PCDV, "dctl=%0x\n", ++ DWC_READ_REG32(&dev_if->dev_global_regs->dctl)); ++ ++} ++ ++/** ++ * This function activates an EP. The Device EP control register for ++ * the EP is configured as defined in the ep structure. Note: This ++ * function is not used for EP0. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to activate. ++ */ ++void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ depctl_data_t depctl; ++ volatile uint32_t *addr; ++ daint_data_t daintmsk = {.d32 = 0 }; ++ dcfg_data_t dcfg; ++ uint8_t i; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s() EP%d-%s\n", __func__, ep->num, ++ (ep->is_in ? "IN" : "OUT")); ++ ++#ifdef DWC_UTE_PER_IO ++ ep->xiso_frame_num = 0xFFFFFFFF; ++ ep->xiso_active_xfers = 0; ++ ep->xiso_queued_xfers = 0; ++#endif ++ /* Read DEPCTLn register */ ++ if (ep->is_in == 1) { ++ addr = &dev_if->in_ep_regs[ep->num]->diepctl; ++ daintmsk.ep.in = 1 << ep->num; ++ } else { ++ addr = &dev_if->out_ep_regs[ep->num]->doepctl; ++ daintmsk.ep.out = 1 << ep->num; ++ } ++ ++ /* If the EP is already active don't change the EP Control ++ * register. */ ++ depctl.d32 = DWC_READ_REG32(addr); ++ if (!depctl.b.usbactep) { ++ depctl.b.mps = ep->maxpacket; ++ depctl.b.eptype = ep->type; ++ depctl.b.txfnum = ep->tx_fifo_num; ++ ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ depctl.b.setd0pid = 1; // ??? ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ depctl.b.usbactep = 1; ++ ++ /* Update nextep_seq array and EPMSCNT in DCFG */ ++ if (!(depctl.b.eptype & 1) && (ep->is_in == 1)) { // NP IN EP ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ if (core_if->nextep_seq[i] == core_if->first_in_nextep_seq) ++ break; ++ } ++ core_if->nextep_seq[i] = ep->num; ++ core_if->nextep_seq[ep->num] = core_if->first_in_nextep_seq; ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt++; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_PCDV, "%2d\n", ++ core_if->nextep_seq[i]); ++ } ++ ++ } ++ ++ ++ DWC_WRITE_REG32(addr, depctl.d32); ++ DWC_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", DWC_READ_REG32(addr)); ++ } ++ ++ /* Enable the Interrupt for this EP */ ++ if (core_if->multiproc_int_enable) { ++ if (ep->is_in == 1) { ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ diepmsk.b.xfercompl = 1; ++ diepmsk.b.timeout = 1; ++ diepmsk.b.epdisabled = 1; ++ diepmsk.b.ahberr = 1; ++ diepmsk.b.intknepmis = 1; ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) ++ diepmsk.b.intknepmis = 0; ++ diepmsk.b.txfifoundrn = 1; //????? ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ diepmsk.b.nak = 1; ++ } ++ ++/* ++ if (core_if->dma_desc_enable) { ++ diepmsk.b.bna = 1; ++ } ++*/ ++/* ++ if (core_if->dma_enable) { ++ doepmsk.b.nak = 1; ++ } ++*/ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs-> ++ diepeachintmsk[ep->num], diepmsk.d32); ++ ++ } else { ++ doepmsk_data_t doepmsk = {.d32 = 0 }; ++ doepmsk.b.xfercompl = 1; ++ doepmsk.b.ahberr = 1; ++ doepmsk.b.epdisabled = 1; ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) ++ doepmsk.b.outtknepdis = 1; ++ ++/* ++ ++ if (core_if->dma_desc_enable) { ++ doepmsk.b.bna = 1; ++ } ++*/ ++/* ++ doepmsk.b.babble = 1; ++ doepmsk.b.nyet = 1; ++ doepmsk.b.nak = 1; ++*/ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs-> ++ doepeachintmsk[ep->num], doepmsk.d32); ++ } ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->deachintmsk, ++ 0, daintmsk.d32); ++ } else { ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (ep->is_in) { ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ diepmsk.b.nak = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32); ++ } else { ++ doepmsk_data_t doepmsk = {.d32 = 0 }; ++ doepmsk.b.outtknepdis = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->doepmsk, 0, doepmsk.d32); ++ } ++ } ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->daintmsk, ++ 0, daintmsk.d32); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "DAINTMSK=%0x\n", ++ DWC_READ_REG32(&dev_if->dev_global_regs->daintmsk)); ++ ++ ep->stall_clear_flag = 0; ++ ++ return; ++} ++ ++/** ++ * This function deactivates an EP. This is done by clearing the USB Active ++ * EP bit in the Device EP control register. Note: This function is not used ++ * for EP0. EP0 cannot be deactivated. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to deactivate. ++ */ ++void dwc_otg_ep_deactivate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ daint_data_t daintmsk = {.d32 = 0 }; ++ dcfg_data_t dcfg; ++ uint8_t i = 0; ++ ++#ifdef DWC_UTE_PER_IO ++ ep->xiso_frame_num = 0xFFFFFFFF; ++ ep->xiso_active_xfers = 0; ++ ep->xiso_queued_xfers = 0; ++#endif ++ ++ /* Read DEPCTLn register */ ++ if (ep->is_in == 1) { ++ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; ++ daintmsk.ep.in = 1 << ep->num; ++ } else { ++ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; ++ daintmsk.ep.out = 1 << ep->num; ++ } ++ ++ depctl.d32 = DWC_READ_REG32(addr); ++ ++ depctl.b.usbactep = 0; ++ ++ /* Update nextep_seq array and EPMSCNT in DCFG */ ++ if (!(depctl.b.eptype & 1) && ep->is_in == 1) { // NP EP IN ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ if (core_if->nextep_seq[i] == ep->num) ++ break; ++ } ++ core_if->nextep_seq[i] = core_if->nextep_seq[ep->num]; ++ if (core_if->first_in_nextep_seq == ep->num) ++ core_if->first_in_nextep_seq = i; ++ core_if->nextep_seq[ep->num] = 0xff; ++ depctl.b.nextep = 0; ++ dcfg.d32 = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt--; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, ++ dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); ++ } ++ } ++ ++ if (ep->is_in == 1) ++ depctl.b.txfnum = 0; ++ ++ if (core_if->dma_desc_enable) ++ depctl.b.epdis = 1; ++ ++ DWC_WRITE_REG32(addr, depctl.d32); ++ depctl.d32 = DWC_READ_REG32(addr); ++ if (core_if->dma_enable && depctl.b.epena) { ++ depctl_data_t depctl = {.d32 = 0 }; ++ if (ep->is_in) { ++ diepint_data_t diepint = {.d32 = 0 }; ++ ++ depctl.b.snak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepctl, depctl.d32); ++/* do { */ ++ dwc_udelay(10); ++ diepint.d32 = ++ DWC_READ_REG32(&core_if-> ++ dev_if->in_ep_regs[ep->num]-> ++ diepint); ++/* } while (!diepint.b.inepnakeff); */ ++ diepint.b.inepnakeff = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepint, diepint.d32); ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepctl, depctl.d32); ++/* do { */ ++ dwc_udelay(10); ++ diepint.d32 = ++ DWC_READ_REG32(&core_if-> ++ dev_if->in_ep_regs[ep->num]-> ++ diepint); ++/* } while (!diepint.b.epdisabled); */ ++ diepint.b.epdisabled = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepint, diepint.d32); ++ } else if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ dctl_data_t dctl = {.d32 = 0}; ++ gintmsk_data_t gintsts = {.d32 = 0}; ++ doepint_data_t doepint = {.d32 = 0}; ++ dctl.b.sgoutnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, 0, dctl.d32); ++ do { ++ dwc_udelay(10); ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ } while (!gintsts.b.goutnakeff); ++ gintsts.d32 = 0; ++ gintsts.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepctl, depctl.d32); ++ do ++ { ++ dwc_udelay(10); ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->num]->doepint); ++ } while (!doepint.b.epdisabled); ++ ++ doepint.b.epdisabled = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepint, doepint.d32); ++ ++ dctl.d32 = 0; ++ dctl.b.cgoutnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } ++ } ++ ++ /* Disable the Interrupt for this EP */ ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->deachintmsk, ++ daintmsk.d32, 0); ++ ++ if (ep->is_in == 1) { ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs-> ++ diepeachintmsk[ep->num], 0); ++ } else { ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[ep->num], 0); ++ } ++ } else { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->daintmsk, ++ daintmsk.d32, 0); ++ } ++ ++} ++ ++/** ++ * This function initializes dma descriptor chain. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++static void init_dma_desc_chain(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ uint32_t offset; ++ uint32_t xfer_est; ++ int i; ++ unsigned maxxfer_local, total_len; ++ ++ if (!ep->is_in && ep->type == DWC_OTG_EP_TYPE_INTR && ++ (ep->maxpacket % 4)) { ++ maxxfer_local = ep->maxpacket; ++ total_len = ep->xfer_len; ++ } else { ++ maxxfer_local = ep->maxxfer; ++ total_len = ep->total_len; ++ } ++ ++ ep->desc_cnt = (total_len / maxxfer_local) + ++ ((total_len % maxxfer_local) ? 1 : 0); ++ ++ if (!ep->desc_cnt) ++ ep->desc_cnt = 1; ++ ++ if (ep->desc_cnt > MAX_DMA_DESC_CNT) ++ ep->desc_cnt = MAX_DMA_DESC_CNT; ++ ++ dma_desc = ep->desc_addr; ++ if (maxxfer_local == ep->maxpacket) { ++ if ((total_len % maxxfer_local) && ++ (total_len / maxxfer_local < MAX_DMA_DESC_CNT)) { ++ xfer_est = (ep->desc_cnt - 1) * maxxfer_local + ++ (total_len % maxxfer_local); ++ } else ++ xfer_est = ep->desc_cnt * maxxfer_local; ++ } else ++ xfer_est = total_len; ++ offset = 0; ++ for (i = 0; i < ep->desc_cnt; ++i) { ++ /** DMA Descriptor Setup */ ++ if (xfer_est > maxxfer_local) { ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 0; ++ dma_desc->status.b.ioc = 0; ++ dma_desc->status.b.sp = 0; ++ dma_desc->status.b.bytes = maxxfer_local; ++ dma_desc->buf = ep->dma_addr + offset; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ xfer_est -= maxxfer_local; ++ offset += maxxfer_local; ++ } else { ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ if (ep->is_in) { ++ dma_desc->status.b.sp = ++ (xfer_est % ++ ep->maxpacket) ? 1 : ((ep-> ++ sent_zlp) ? 1 : 0); ++ dma_desc->status.b.bytes = xfer_est; ++ } else { ++ if (maxxfer_local == ep->maxpacket) ++ dma_desc->status.b.bytes = xfer_est; ++ else ++ dma_desc->status.b.bytes = ++ xfer_est + ((4 - (xfer_est & 0x3)) & 0x3); ++ } ++ ++ dma_desc->buf = ep->dma_addr + offset; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ } ++ dma_desc++; ++ } ++} ++ ++/** ++ * This function is called when to write ISOC data into appropriate dedicated ++ * periodic FIFO. ++ */ ++static int32_t write_isoc_tx_fifo(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep) ++{ ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dwc_otg_dev_in_ep_regs_t *ep_regs; ++ dtxfsts_data_t txstatus = {.d32 = 0 }; ++ uint32_t len = 0; ++ int epnum = dwc_ep->num; ++ int dwords; ++ ++ DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum); ++ ++ ep_regs = core_if->dev_if->in_ep_regs[epnum]; ++ ++ len = dwc_ep->xfer_len - dwc_ep->xfer_count; ++ ++ if (len > dwc_ep->maxpacket) { ++ len = dwc_ep->maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ ++ /* While there is space in the queue and space in the FIFO and ++ * More data to tranfer, Write packets to the Tx FIFO */ ++ txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32); ++ ++ while (txstatus.b.txfspcavail >= dwords && ++ dwc_ep->xfer_count < dwc_ep->xfer_len && dwc_ep->xfer_len != 0) { ++ /* Write the FIFO */ ++ dwc_otg_ep_write_packet(core_if, dwc_ep, 0); ++ ++ len = dwc_ep->xfer_len - dwc_ep->xfer_count; ++ if (len > dwc_ep->maxpacket) { ++ len = dwc_ep->maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ txstatus.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum, ++ txstatus.d32); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts)); ++ ++ return 1; ++} ++ ++/** ++ * This function does the setup for a data transfer for an EP and ++ * starts the transfer. For an IN transfer, the packets will be ++ * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers, ++ * the packets are unloaded from the Rx FIFO in the ISR. the ISR. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++ ++void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ deptsiz_data_t deptsiz; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__); ++ DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d " ++ "xfer_buff=%p start_xfer_buff=%p, total_len = %d\n", ++ ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len, ++ ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff, ++ ep->total_len); ++ /* IN endpoint */ ++ if (ep->is_in == 1) { ++ dwc_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[ep->num]; ++ ++ gnptxsts_data_t gtxstatus; ++ ++ gtxstatus.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gnptxsts); ++ ++ if (core_if->en_multiple_tx_fifo == 0 ++ && gtxstatus.b.nptxqspcavail == 0 && !core_if->dma_enable) { ++#ifdef DEBUG ++ DWC_PRINTF("TX Queue Full (0x%0x)\n", gtxstatus.d32); ++#endif ++ return; ++ } ++ ++ depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl)); ++ deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz)); ++ ++ if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT) ++ ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? ++ ep->maxxfer : (ep->total_len - ep->xfer_len); ++ else ++ ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ? ++ MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len); ++ ++ ++ /* Zero Length Packet? */ ++ if ((ep->xfer_len - ep->xfer_count) == 0) { ++ deptsiz.b.xfersize = 0; ++ deptsiz.b.pktcnt = 1; ++ } else { ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count; ++ deptsiz.b.pktcnt = ++ (ep->xfer_len - ep->xfer_count - 1 + ++ ep->maxpacket) / ep->maxpacket; ++ if (deptsiz.b.pktcnt > MAX_PKT_CNT) { ++ deptsiz.b.pktcnt = MAX_PKT_CNT; ++ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; ++ } ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) ++ deptsiz.b.mc = deptsiz.b.pktcnt; ++ } ++ ++ /* Write the DMA register */ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ if (ep->type != DWC_OTG_EP_TYPE_ISOC) ++ deptsiz.b.mc = 1; ++ DWC_WRITE_REG32(&in_regs->dieptsiz, ++ deptsiz.d32); ++ DWC_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } else { ++#ifdef DWC_UTE_CFI ++ /* The descriptor chain should be already initialized by now */ ++ if (ep->buff_mode != BM_STANDARD) { ++ DWC_WRITE_REG32(&in_regs->diepdma, ++ ep->descs_dma_addr); ++ } else { ++#endif ++ init_dma_desc_chain(core_if, ep); ++ /** DIEPDMAn Register write */ ++ DWC_WRITE_REG32(&in_regs->diepdma, ++ ep->dma_desc_addr); ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ } ++ } else { ++ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); ++ if (ep->type != DWC_OTG_EP_TYPE_ISOC) { ++ /** ++ * Enable the Non-Periodic Tx FIFO empty interrupt, ++ * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode, ++ * the data will be written into the fifo by the ISR. ++ */ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32 ++ (&core_if->core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } else { ++ /* Enable the Tx FIFO Empty Interrupt for this EP */ ++ if (ep->xfer_len > 0) { ++ uint32_t fifoemptymsk = 0; ++ fifoemptymsk = 1 << ep->num; ++ DWC_MODIFY_REG32 ++ (&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ 0, fifoemptymsk); ++ ++ } ++ } ++ } ++ } ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ dsts_data_t dsts = {.d32 = 0 }; ++ if (ep->bInterval == 1) { ++ dsts.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dsts); ++ ep->frame_num = dsts.b.soffn + ep->bInterval; ++ if (ep->frame_num > 0x3FFF) { ++ ep->frm_overrun = 1; ++ ep->frame_num &= 0x3FFF; ++ } else ++ ep->frm_overrun = 0; ++ if (ep->frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ } ++ } ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); ++ ++ if (!core_if->dma_enable && ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ write_isoc_tx_fifo(core_if, ep); ++ } ++ ++ } else { ++ /* OUT endpoint */ ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[ep->num]; ++ ++ depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl)); ++ deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz)); ++ ++ if (!core_if->dma_desc_enable) { ++ if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT) ++ ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? ++ ep->maxxfer : (ep->total_len - ep->xfer_len); ++ else ++ ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len ++ - ep->xfer_len)) ? MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len); ++ } ++ ++ /* Program the transfer size and packet count as follows: ++ * ++ * pktcnt = N ++ * xfersize = N * maxpacket ++ */ ++ if ((ep->xfer_len - ep->xfer_count) == 0) { ++ /* Zero Length Packet */ ++ deptsiz.b.xfersize = ep->maxpacket; ++ deptsiz.b.pktcnt = 1; ++ } else { ++ deptsiz.b.pktcnt = ++ (ep->xfer_len - ep->xfer_count + ++ (ep->maxpacket - 1)) / ep->maxpacket; ++ if (deptsiz.b.pktcnt > MAX_PKT_CNT) { ++ deptsiz.b.pktcnt = MAX_PKT_CNT; ++ } ++ if (!core_if->dma_desc_enable) { ++ ep->xfer_len = ++ deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count; ++ } ++ deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count; ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "ep%d xfersize=%d pktcnt=%d\n", ++ ep->num, deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ ++ if (core_if->dma_enable) { ++ if (!core_if->dma_desc_enable) { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, ++ deptsiz.d32); ++ ++ DWC_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) ep->dma_addr); ++ } else { ++#ifdef DWC_UTE_CFI ++ /* The descriptor chain should be already initialized by now */ ++ if (ep->buff_mode != BM_STANDARD) { ++ DWC_WRITE_REG32(&out_regs->doepdma, ++ ep->descs_dma_addr); ++ } else { ++#endif ++ /** This is used for interrupt out transfers*/ ++ if (!ep->xfer_len) ++ ep->xfer_len = ep->total_len; ++ init_dma_desc_chain(core_if, ep); ++ ++ if (core_if->core_params->dev_out_nak) { ++ if (ep->type == DWC_OTG_EP_TYPE_BULK) { ++ deptsiz.b.pktcnt = (ep->total_len + ++ (ep->maxpacket - 1)) / ep->maxpacket; ++ deptsiz.b.xfersize = ep->total_len; ++ /* Remember initial value of doeptsiz */ ++ core_if->start_doeptsiz_val[ep->num] = deptsiz.d32; ++ DWC_WRITE_REG32(&out_regs->doeptsiz, ++ deptsiz.d32); ++ } ++ } ++ /** DOEPDMAn Register write */ ++ DWC_WRITE_REG32(&out_regs->doepdma, ++ ep->dma_desc_addr); ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ } ++ } else { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); ++ } ++ ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ dsts_data_t dsts = {.d32 = 0 }; ++ if (ep->bInterval == 1) { ++ dsts.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dsts); ++ ep->frame_num = dsts.b.soffn + ep->bInterval; ++ if (ep->frame_num > 0x3FFF) { ++ ep->frm_overrun = 1; ++ ep->frame_num &= 0x3FFF; ++ } else ++ ep->frm_overrun = 0; ++ ++ if (ep->frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ } ++ } ++ ++ /* EP enable */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ ++ DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32); ++ ++ DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n", ++ DWC_READ_REG32(&out_regs->doepctl), ++ DWC_READ_REG32(&out_regs->doeptsiz)); ++ DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n", ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs-> ++ daintmsk), ++ DWC_READ_REG32(&core_if->core_global_regs-> ++ gintmsk)); ++ ++ /* Timer is scheduling only for out bulk transfers for ++ * "Device DDMA OUT NAK Enhancement" feature to inform user ++ * about received data payload in case of timeout ++ */ ++ if (core_if->core_params->dev_out_nak) { ++ if (ep->type == DWC_OTG_EP_TYPE_BULK) { ++ core_if->ep_xfer_info[ep->num].core_if = core_if; ++ core_if->ep_xfer_info[ep->num].ep = ep; ++ core_if->ep_xfer_info[ep->num].state = 1; ++ ++ /* Start a timer for this transfer. */ ++ DWC_TIMER_SCHEDULE(core_if->ep_xfer_timer[ep->num], 10000); ++ } ++ } ++ } ++} ++ ++/** ++ * This function setup a zero length transfer in Buffer DMA and ++ * Slave modes for usb requests with zero field set ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ ++ depctl_data_t depctl; ++ deptsiz_data_t deptsiz; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__); ++ DWC_PRINTF("zero length transfer is called\n"); ++ ++ /* IN endpoint */ ++ if (ep->is_in == 1) { ++ dwc_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[ep->num]; ++ ++ depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl)); ++ deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz)); ++ ++ deptsiz.b.xfersize = 0; ++ deptsiz.b.pktcnt = 1; ++ ++ /* Write the DMA register */ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ deptsiz.b.mc = 1; ++ DWC_WRITE_REG32(&in_regs->dieptsiz, ++ deptsiz.d32); ++ DWC_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ } else { ++ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); ++ /** ++ * Enable the Non-Periodic Tx FIFO empty interrupt, ++ * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode, ++ * the data will be written into the fifo by the ISR. ++ */ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } else { ++ /* Enable the Tx FIFO Empty Interrupt for this EP */ ++ if (ep->xfer_len > 0) { ++ uint32_t fifoemptymsk = 0; ++ fifoemptymsk = 1 << ep->num; ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ 0, fifoemptymsk); ++ } ++ } ++ } ++ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); ++ ++ } else { ++ /* OUT endpoint */ ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[ep->num]; ++ ++ depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl)); ++ deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz)); ++ ++ /* Zero Length Packet */ ++ deptsiz.b.xfersize = ep->maxpacket; ++ deptsiz.b.pktcnt = 1; ++ ++ if (core_if->dma_enable) { ++ if (!core_if->dma_desc_enable) { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, ++ deptsiz.d32); ++ ++ DWC_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ } else { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); ++ } ++ ++ /* EP enable */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ ++ DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32); ++ ++ } ++} ++ ++/** ++ * This function does the setup for a data transfer for EP0 and starts ++ * the transfer. For an IN transfer, the packets will be loaded into ++ * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are ++ * unloaded from the Rx FIFO in the ISR. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP0 data. ++ */ ++void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ deptsiz0_data_t deptsiz; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ ++ DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d " ++ "xfer_buff=%p start_xfer_buff=%p \n", ++ ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len, ++ ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff); ++ ++ ep->total_len = ep->xfer_len; ++ ++ /* IN endpoint */ ++ if (ep->is_in == 1) { ++ dwc_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[0]; ++ ++ gnptxsts_data_t gtxstatus; ++ ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ depctl.d32 = DWC_READ_REG32(&in_regs->diepctl); ++ if (depctl.b.epena) ++ return; ++ } ++ ++ gtxstatus.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gnptxsts); ++ ++ /* If dedicated FIFO every time flush fifo before enable ep*/ ++ if (core_if->en_multiple_tx_fifo && core_if->snpsid >= OTG_CORE_REV_3_00a) ++ dwc_otg_flush_tx_fifo(core_if, ep->tx_fifo_num); ++ ++ dwc_otg_flush_tx_fifo(core_if, 0x10); ++ ++ if (core_if->en_multiple_tx_fifo == 0 ++ && gtxstatus.b.nptxqspcavail == 0 ++ && !core_if->dma_enable) { ++#ifdef DEBUG ++ deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz); ++ DWC_DEBUGPL(DBG_PCD, "DIEPCTL0=%0x\n", ++ DWC_READ_REG32(&in_regs->diepctl)); ++ DWC_DEBUGPL(DBG_PCD, "DIEPTSIZ0=%0x (sz=%d, pcnt=%d)\n", ++ deptsiz.d32, ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ DWC_PRINTF("TX Queue or FIFO Full (0x%0x)\n", ++ gtxstatus.d32); ++#endif ++ return; ++ } ++ ++ depctl.d32 = DWC_READ_REG32(&in_regs->diepctl); ++ deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz); ++ ++ /* Zero Length Packet? */ ++ if (ep->xfer_len == 0) { ++ deptsiz.b.xfersize = 0; ++ deptsiz.b.pktcnt = 1; ++ } else { ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ if (ep->xfer_len > ep->maxpacket) { ++ ep->xfer_len = ep->maxpacket; ++ deptsiz.b.xfersize = ep->maxpacket; ++ } else { ++ deptsiz.b.xfersize = ep->xfer_len; ++ } ++ deptsiz.b.pktcnt = 1; ++ ++ } ++ DWC_DEBUGPL(DBG_PCDV, ++ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", ++ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, ++ deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ DWC_WRITE_REG32(&in_regs->dieptsiz, ++ deptsiz.d32); ++ ++ DWC_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } else { ++ dma_desc = core_if->dev_if->in_desc_addr; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.sp = ++ (ep->xfer_len == ep->maxpacket) ? 0 : 1; ++ dma_desc->status.b.bytes = ep->xfer_len; ++ dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DIEPDMA0 Register write */ ++ DWC_WRITE_REG32(&in_regs->diepdma, ++ core_if-> ++ dev_if->dma_in_desc_addr); ++ } ++ } else { ++ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); ++ } ++ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); ++ ++ /** ++ * Enable the Non-Periodic Tx FIFO empty interrupt, the ++ * data will be written into the fifo by the ISR. ++ */ ++ if (!core_if->dma_enable) { ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } else { ++ /* Enable the Tx FIFO Empty Interrupt for this EP */ ++ if (ep->xfer_len > 0) { ++ uint32_t fifoemptymsk = 0; ++ fifoemptymsk |= 1 << ep->num; ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ 0, fifoemptymsk); ++ } ++ } ++ } ++ } else { ++ /* OUT endpoint */ ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[0]; ++ ++ depctl.d32 = DWC_READ_REG32(&out_regs->doepctl); ++ deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz); ++ ++ /* Program the transfer size and packet count as follows: ++ * xfersize = N * (maxpacket + 4 - (maxpacket % 4)) ++ * pktcnt = N */ ++ /* Zero Length Packet */ ++ deptsiz.b.xfersize = ep->maxpacket; ++ deptsiz.b.pktcnt = 1; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) ++ deptsiz.b.supcnt = 3; ++ ++ DWC_DEBUGPL(DBG_PCDV, "len=%d xfersize=%d pktcnt=%d\n", ++ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ ++ if (core_if->dma_enable) { ++ if (!core_if->dma_desc_enable) { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, ++ deptsiz.d32); ++ ++ DWC_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) ep->dma_addr); ++ } else { ++ dma_desc = core_if->dev_if->out_desc_addr; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ dma_desc->status.b.mtrf = 0; ++ dma_desc->status.b.sr = 0; ++ } ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.bytes = ep->maxpacket; ++ dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DOEPDMA0 Register write */ ++ DWC_WRITE_REG32(&out_regs->doepdma, ++ core_if->dev_if-> ++ dma_out_desc_addr); ++ } ++ } else { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); ++ } ++ ++ /* EP enable */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ DWC_WRITE_REG32(&(out_regs->doepctl), depctl.d32); ++ } ++} ++ ++/** ++ * This function continues control IN transfers started by ++ * dwc_otg_ep0_start_transfer, when the transfer does not fit in a ++ * single packet. NOTE: The DIEPCTL0/DOEPCTL0 registers only have one ++ * bit for the packet count. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP0 data. ++ */ ++void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ deptsiz0_data_t deptsiz; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ ++ if (ep->is_in == 1) { ++ dwc_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[0]; ++ gnptxsts_data_t tx_status = {.d32 = 0 }; ++ ++ tx_status.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gnptxsts); ++ /** @todo Should there be check for room in the Tx ++ * Status Queue. If not remove the code above this comment. */ ++ ++ depctl.d32 = DWC_READ_REG32(&in_regs->diepctl); ++ deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz); ++ ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ ++ if (core_if->dma_desc_enable == 0) { ++ deptsiz.b.xfersize = ++ (ep->total_len - ep->xfer_count) > ++ ep->maxpacket ? ep->maxpacket : (ep->total_len - ++ ep->xfer_count); ++ deptsiz.b.pktcnt = 1; ++ if (core_if->dma_enable == 0) { ++ ep->xfer_len += deptsiz.b.xfersize; ++ } else { ++ ep->xfer_len = deptsiz.b.xfersize; ++ } ++ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); ++ } else { ++ ep->xfer_len = ++ (ep->total_len - ep->xfer_count) > ++ ep->maxpacket ? ep->maxpacket : (ep->total_len - ++ ep->xfer_count); ++ ++ dma_desc = core_if->dev_if->in_desc_addr; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.sp = ++ (ep->xfer_len == ep->maxpacket) ? 0 : 1; ++ dma_desc->status.b.bytes = ep->xfer_len; ++ dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DIEPDMA0 Register write */ ++ DWC_WRITE_REG32(&in_regs->diepdma, ++ core_if->dev_if->dma_in_desc_addr); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", ++ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, ++ deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) { ++ if (core_if->dma_desc_enable == 0) ++ DWC_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); ++ ++ /** ++ * Enable the Non-Periodic Tx FIFO empty interrupt, the ++ * data will be written into the fifo by the ISR. ++ */ ++ if (!core_if->dma_enable) { ++ if (core_if->en_multiple_tx_fifo == 0) { ++ /* First clear it from GINTSTS */ ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ ++ } else { ++ /* Enable the Tx FIFO Empty Interrupt for this EP */ ++ if (ep->xfer_len > 0) { ++ uint32_t fifoemptymsk = 0; ++ fifoemptymsk |= 1 << ep->num; ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ 0, fifoemptymsk); ++ } ++ } ++ } ++ } else { ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[0]; ++ ++ depctl.d32 = DWC_READ_REG32(&out_regs->doepctl); ++ deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz); ++ ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ deptsiz.b.xfersize = ep->maxpacket; ++ deptsiz.b.pktcnt = 1; ++ ++ if (core_if->dma_desc_enable == 0) { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); ++ } else { ++ dma_desc = core_if->dev_if->out_desc_addr; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.bytes = ep->maxpacket; ++ dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DOEPDMA0 Register write */ ++ DWC_WRITE_REG32(&out_regs->doepdma, ++ core_if->dev_if->dma_out_desc_addr); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", ++ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, ++ deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) { ++ if (core_if->dma_desc_enable == 0) ++ DWC_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) ep->dma_addr); ++ ++ } ++ ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32); ++ ++ } ++} ++ ++#ifdef DEBUG ++void dump_msg(const u8 * buf, unsigned int length) ++{ ++ unsigned int start, num, i; ++ char line[52], *p; ++ ++ if (length >= 512) ++ return; ++ start = 0; ++ while (length > 0) { ++ num = length < 16u ? length : 16u; ++ p = line; ++ for (i = 0; i < num; ++i) { ++ if (i == 8) ++ *p++ = ' '; ++ DWC_SPRINTF(p, " %02x", buf[i]); ++ p += 3; ++ } ++ *p = 0; ++ DWC_PRINTF("%6x: %s\n", start, line); ++ buf += num; ++ start += num; ++ length -= num; ++ } ++} ++#else ++static inline void dump_msg(const u8 * buf, unsigned int length) ++{ ++} ++#endif ++ ++/** ++ * This function writes a packet into the Tx FIFO associated with the ++ * EP. For non-periodic EPs the non-periodic Tx FIFO is written. For ++ * periodic EPs the periodic Tx FIFO associated with the EP is written ++ * with all packets for the next micro-frame. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to write packet for. ++ * @param dma Indicates if DMA is being used. ++ */ ++void dwc_otg_ep_write_packet(dwc_otg_core_if_t * core_if, dwc_ep_t * ep, ++ int dma) ++{ ++ /** ++ * The buffer is padded to DWORD on a per packet basis in ++ * slave/dma mode if the MPS is not DWORD aligned. The last ++ * packet, if short, is also padded to a multiple of DWORD. ++ * ++ * ep->xfer_buff always starts DWORD aligned in memory and is a ++ * multiple of DWORD in length ++ * ++ * ep->xfer_len can be any number of bytes ++ * ++ * ep->xfer_count is a multiple of ep->maxpacket until the last ++ * packet ++ * ++ * FIFO access is DWORD */ ++ ++ uint32_t i; ++ uint32_t byte_count; ++ uint32_t dword_count; ++ uint32_t *fifo; ++ uint32_t *data_buff = (uint32_t *) ep->xfer_buff; ++ ++ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p)\n", __func__, core_if, ++ ep); ++ if (ep->xfer_count >= ep->xfer_len) { ++ DWC_WARN("%s() No data for EP%d!!!\n", __func__, ep->num); ++ return; ++ } ++ ++ /* Find the byte length of the packet either short packet or MPS */ ++ if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket) { ++ byte_count = ep->xfer_len - ep->xfer_count; ++ } else { ++ byte_count = ep->maxpacket; ++ } ++ ++ /* Find the DWORD length, padded by extra bytes as neccessary if MPS ++ * is not a multiple of DWORD */ ++ dword_count = (byte_count + 3) / 4; ++ ++#ifdef VERBOSE ++ dump_msg(ep->xfer_buff, byte_count); ++#endif ++ ++ /**@todo NGS Where are the Periodic Tx FIFO addresses ++ * intialized? What should this be? */ ++ ++ fifo = core_if->data_fifo[ep->num]; ++ ++ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "fifo=%p buff=%p *p=%08x bc=%d\n", ++ fifo, data_buff, *data_buff, byte_count); ++ ++ if (!dma) { ++ for (i = 0; i < dword_count; i++, data_buff++) { ++ DWC_WRITE_REG32(fifo, *data_buff); ++ } ++ } ++ ++ ep->xfer_count += byte_count; ++ ep->xfer_buff += byte_count; ++ ep->dma_addr += byte_count; ++} ++ ++/** ++ * Set the EP STALL. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to set the stall on. ++ */ ++void dwc_otg_ep_set_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ volatile uint32_t *depctl_addr; ++ ++ DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num, ++ (ep->is_in ? "IN" : "OUT")); ++ ++ if (ep->is_in == 1) { ++ depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl); ++ depctl.d32 = DWC_READ_REG32(depctl_addr); ++ ++ /* set the disable and stall bits */ ++ if (depctl.b.epena) { ++ depctl.b.epdis = 1; ++ } ++ depctl.b.stall = 1; ++ DWC_WRITE_REG32(depctl_addr, depctl.d32); ++ } else { ++ depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl); ++ depctl.d32 = DWC_READ_REG32(depctl_addr); ++ ++ /* set the stall bit */ ++ depctl.b.stall = 1; ++ DWC_WRITE_REG32(depctl_addr, depctl.d32); ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr)); ++ ++ return; ++} ++ ++/** ++ * Clear the EP STALL. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to clear stall from. ++ */ ++void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ volatile uint32_t *depctl_addr; ++ ++ DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num, ++ (ep->is_in ? "IN" : "OUT")); ++ ++ if (ep->is_in == 1) { ++ depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl); ++ } else { ++ depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl); ++ } ++ ++ depctl.d32 = DWC_READ_REG32(depctl_addr); ++ ++ /* clear the stall bits */ ++ depctl.b.stall = 0; ++ ++ /* ++ * USB Spec 9.4.5: For endpoints using data toggle, regardless ++ * of whether an endpoint has the Halt feature set, a ++ * ClearFeature(ENDPOINT_HALT) request always results in the ++ * data toggle being reinitialized to DATA0. ++ */ ++ if (ep->type == DWC_OTG_EP_TYPE_INTR || ++ ep->type == DWC_OTG_EP_TYPE_BULK) { ++ depctl.b.setd0pid = 1; /* DATA0 */ ++ } ++ ++ DWC_WRITE_REG32(depctl_addr, depctl.d32); ++ DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr)); ++ return; ++} ++ ++/** ++ * This function reads a packet from the Rx FIFO into the destination ++ * buffer. To read SETUP data use dwc_otg_read_setup_packet. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param dest Destination buffer for the packet. ++ * @param bytes Number of bytes to copy to the destination. ++ */ ++void dwc_otg_read_packet(dwc_otg_core_if_t * core_if, ++ uint8_t * dest, uint16_t bytes) ++{ ++ int i; ++ int word_count = (bytes + 3) / 4; ++ ++ volatile uint32_t *fifo = core_if->data_fifo[0]; ++ uint32_t *data_buff = (uint32_t *) dest; ++ ++ /** ++ * @todo Account for the case where _dest is not dword aligned. This ++ * requires reading data from the FIFO into a uint32_t temp buffer, ++ * then moving it into the data buffer. ++ */ ++ ++ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p,%d)\n", __func__, ++ core_if, dest, bytes); ++ ++ for (i = 0; i < word_count; i++, data_buff++) { ++ *data_buff = DWC_READ_REG32(fifo); ++ } ++ ++ return; ++} ++ ++/** ++ * This functions reads the device registers and prints them ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * core_if) ++{ ++ int i; ++ volatile uint32_t *addr; ++ ++ DWC_PRINTF("Device Global Registers\n"); ++ addr = &core_if->dev_if->dev_global_regs->dcfg; ++ DWC_PRINTF("DCFG @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->dctl; ++ DWC_PRINTF("DCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->dsts; ++ DWC_PRINTF("DSTS @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->diepmsk; ++ DWC_PRINTF("DIEPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->doepmsk; ++ DWC_PRINTF("DOEPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->daint; ++ DWC_PRINTF("DAINT @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->daintmsk; ++ DWC_PRINTF("DAINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->dtknqr1; ++ DWC_PRINTF("DTKNQR1 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ if (core_if->hwcfg2.b.dev_token_q_depth > 6) { ++ addr = &core_if->dev_if->dev_global_regs->dtknqr2; ++ DWC_PRINTF("DTKNQR2 @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } ++ ++ addr = &core_if->dev_if->dev_global_regs->dvbusdis; ++ DWC_PRINTF("DVBUSID @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ ++ addr = &core_if->dev_if->dev_global_regs->dvbuspulse; ++ DWC_PRINTF("DVBUSPULSE @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ ++ addr = &core_if->dev_if->dev_global_regs->dtknqr3_dthrctl; ++ DWC_PRINTF("DTKNQR3_DTHRCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ ++ if (core_if->hwcfg2.b.dev_token_q_depth > 22) { ++ addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk; ++ DWC_PRINTF("DTKNQR4 @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } ++ ++ addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk; ++ DWC_PRINTF("FIFOEMPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ ++ if (core_if->hwcfg2.b.multi_proc_int) { ++ ++ addr = &core_if->dev_if->dev_global_regs->deachint; ++ DWC_PRINTF("DEACHINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->deachintmsk; ++ DWC_PRINTF("DEACHINTMSK @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ addr = ++ &core_if->dev_if-> ++ dev_global_regs->diepeachintmsk[i]; ++ DWC_PRINTF("DIEPEACHINTMSK[%d] @0x%08lX : 0x%08X\n", ++ i, (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ } ++ ++ for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { ++ addr = ++ &core_if->dev_if-> ++ dev_global_regs->doepeachintmsk[i]; ++ DWC_PRINTF("DOEPEACHINTMSK[%d] @0x%08lX : 0x%08X\n", ++ i, (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ } ++ } ++ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_PRINTF("Device IN EP %d Registers\n", i); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepctl; ++ DWC_PRINTF("DIEPCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepint; ++ DWC_PRINTF("DIEPINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->dieptsiz; ++ DWC_PRINTF("DIETSIZ @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepdma; ++ DWC_PRINTF("DIEPDMA @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->dtxfsts; ++ DWC_PRINTF("DTXFSTS @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepdmab; ++ DWC_PRINTF("DIEPDMAB @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, 0 /*DWC_READ_REG32(addr) */ ); ++ } ++ ++ for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { ++ DWC_PRINTF("Device OUT EP %d Registers\n", i); ++ addr = &core_if->dev_if->out_ep_regs[i]->doepctl; ++ DWC_PRINTF("DOEPCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->out_ep_regs[i]->doepint; ++ DWC_PRINTF("DOEPINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->out_ep_regs[i]->doeptsiz; ++ DWC_PRINTF("DOETSIZ @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->out_ep_regs[i]->doepdma; ++ DWC_PRINTF("DOEPDMA @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ if (core_if->dma_enable) { /* Don't access this register in SLAVE mode */ ++ addr = &core_if->dev_if->out_ep_regs[i]->doepdmab; ++ DWC_PRINTF("DOEPDMAB @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } ++ ++ } ++} ++ ++/** ++ * This functions reads the SPRAM and prints its content ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_dump_spram(dwc_otg_core_if_t * core_if) ++{ ++ volatile uint8_t *addr, *start_addr, *end_addr; ++ ++ DWC_PRINTF("SPRAM Data:\n"); ++ start_addr = (void *)core_if->core_global_regs; ++ DWC_PRINTF("Base Address: 0x%8lX\n", (unsigned long)start_addr); ++ start_addr += 0x00028000; ++ end_addr = (void *)core_if->core_global_regs; ++ end_addr += 0x000280e0; ++ ++ for (addr = start_addr; addr < end_addr; addr += 16) { ++ DWC_PRINTF ++ ("0x%8lX:\t%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\n", ++ (unsigned long)addr, addr[0], addr[1], addr[2], addr[3], ++ addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], ++ addr[10], addr[11], addr[12], addr[13], addr[14], addr[15] ++ ); ++ } ++ ++ return; ++} ++ ++/** ++ * This function reads the host registers and prints them ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_dump_host_registers(dwc_otg_core_if_t * core_if) ++{ ++ int i; ++ volatile uint32_t *addr; ++ ++ DWC_PRINTF("Host Global Registers\n"); ++ addr = &core_if->host_if->host_global_regs->hcfg; ++ DWC_PRINTF("HCFG @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->hfir; ++ DWC_PRINTF("HFIR @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->hfnum; ++ DWC_PRINTF("HFNUM @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->hptxsts; ++ DWC_PRINTF("HPTXSTS @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->haint; ++ DWC_PRINTF("HAINT @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->haintmsk; ++ DWC_PRINTF("HAINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ if (core_if->dma_desc_enable) { ++ addr = &core_if->host_if->host_global_regs->hflbaddr; ++ DWC_PRINTF("HFLBADDR @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } ++ ++ addr = core_if->host_if->hprt0; ++ DWC_PRINTF("HPRT0 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ ++ for (i = 0; i < core_if->core_params->host_channels; i++) { ++ DWC_PRINTF("Host Channel %d Specific Registers\n", i); ++ addr = &core_if->host_if->hc_regs[i]->hcchar; ++ DWC_PRINTF("HCCHAR @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcsplt; ++ DWC_PRINTF("HCSPLT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcint; ++ DWC_PRINTF("HCINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcintmsk; ++ DWC_PRINTF("HCINTMSK @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hctsiz; ++ DWC_PRINTF("HCTSIZ @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcdma; ++ DWC_PRINTF("HCDMA @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ if (core_if->dma_desc_enable) { ++ addr = &core_if->host_if->hc_regs[i]->hcdmab; ++ DWC_PRINTF("HCDMAB @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } ++ ++ } ++ return; ++} ++ ++/** ++ * This function reads the core global registers and prints them ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_dump_global_registers(dwc_otg_core_if_t * core_if) ++{ ++ int i, ep_num; ++ volatile uint32_t *addr; ++ char *txfsiz; ++ ++ DWC_PRINTF("Core Global Registers\n"); ++ addr = &core_if->core_global_regs->gotgctl; ++ DWC_PRINTF("GOTGCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gotgint; ++ DWC_PRINTF("GOTGINT @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gahbcfg; ++ DWC_PRINTF("GAHBCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gusbcfg; ++ DWC_PRINTF("GUSBCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->grstctl; ++ DWC_PRINTF("GRSTCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gintsts; ++ DWC_PRINTF("GINTSTS @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gintmsk; ++ DWC_PRINTF("GINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->grxstsr; ++ DWC_PRINTF("GRXSTSR @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->grxfsiz; ++ DWC_PRINTF("GRXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gnptxfsiz; ++ DWC_PRINTF("GNPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gnptxsts; ++ DWC_PRINTF("GNPTXSTS @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gi2cctl; ++ DWC_PRINTF("GI2CCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gpvndctl; ++ DWC_PRINTF("GPVNDCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ggpio; ++ DWC_PRINTF("GGPIO @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->guid; ++ DWC_PRINTF("GUID @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gsnpsid; ++ DWC_PRINTF("GSNPSID @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg1; ++ DWC_PRINTF("GHWCFG1 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg2; ++ DWC_PRINTF("GHWCFG2 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg3; ++ DWC_PRINTF("GHWCFG3 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg4; ++ DWC_PRINTF("GHWCFG4 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->glpmcfg; ++ DWC_PRINTF("GLPMCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gpwrdn; ++ DWC_PRINTF("GPWRDN @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gdfifocfg; ++ DWC_PRINTF("GDFIFOCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->adpctl; ++ DWC_PRINTF("ADPCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ dwc_otg_adp_read_reg(core_if)); ++ addr = &core_if->core_global_regs->hptxfsiz; ++ DWC_PRINTF("HPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ ep_num = core_if->hwcfg4.b.num_dev_perio_in_ep; ++ txfsiz = "DPTXFSIZ"; ++ } else { ++ ep_num = core_if->hwcfg4.b.num_in_eps; ++ txfsiz = "DIENPTXF"; ++ } ++ for (i = 0; i < ep_num; i++) { ++ addr = &core_if->core_global_regs->dtxfsiz[i]; ++ DWC_PRINTF("%s[%d] @0x%08lX : 0x%08X\n", txfsiz, i + 1, ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } ++ addr = core_if->pcgcctl; ++ DWC_PRINTF("PCGCCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++} ++ ++/** ++ * Flush a Tx FIFO. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param num Tx FIFO to flush. ++ */ ++void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * core_if, const int num) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ volatile grstctl_t greset = {.d32 = 0 }; ++ int count = 0; ++ ++ DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "Flush Tx FIFO %d\n", num); ++ ++ greset.b.txfflsh = 1; ++ greset.b.txfnum = num; ++ DWC_WRITE_REG32(&global_regs->grstctl, greset.d32); ++ ++ do { ++ greset.d32 = DWC_READ_REG32(&global_regs->grstctl); ++ if (++count > 10000) { ++ DWC_WARN("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n", ++ __func__, greset.d32, ++ DWC_READ_REG32(&global_regs->gnptxsts)); ++ break; ++ } ++ dwc_udelay(1); ++ } while (greset.b.txfflsh == 1); ++ ++ /* Wait for 3 PHY Clocks */ ++ dwc_udelay(1); ++} ++ ++/** ++ * Flush Rx FIFO. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ volatile grstctl_t greset = {.d32 = 0 }; ++ int count = 0; ++ ++ DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "%s\n", __func__); ++ /* ++ * ++ */ ++ greset.b.rxfflsh = 1; ++ DWC_WRITE_REG32(&global_regs->grstctl, greset.d32); ++ ++ do { ++ greset.d32 = DWC_READ_REG32(&global_regs->grstctl); ++ if (++count > 10000) { ++ DWC_WARN("%s() HANG! GRSTCTL=%0x\n", __func__, ++ greset.d32); ++ break; ++ } ++ dwc_udelay(1); ++ } while (greset.b.rxfflsh == 1); ++ ++ /* Wait for 3 PHY Clocks */ ++ dwc_udelay(1); ++} ++ ++/** ++ * Do core a soft reset of the core. Be careful with this because it ++ * resets all the internal state machines of the core. ++ */ ++void dwc_otg_core_reset(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ volatile grstctl_t greset = {.d32 = 0 }; ++ int count = 0; ++ ++ DWC_DEBUGPL(DBG_CILV, "%s\n", __func__); ++ /* Wait for AHB master IDLE state. */ ++ do { ++ dwc_udelay(10); ++ greset.d32 = DWC_READ_REG32(&global_regs->grstctl); ++ if (++count > 100000) { ++ DWC_WARN("%s() HANG! AHB Idle GRSTCTL=%0x\n", __func__, ++ greset.d32); ++ return; ++ } ++ } ++ while (greset.b.ahbidle == 0); ++ ++ /* Core Soft Reset */ ++ count = 0; ++ greset.b.csftrst = 1; ++ DWC_WRITE_REG32(&global_regs->grstctl, greset.d32); ++ do { ++ greset.d32 = DWC_READ_REG32(&global_regs->grstctl); ++ if (++count > 10000) { ++ DWC_WARN("%s() HANG! Soft Reset GRSTCTL=%0x\n", ++ __func__, greset.d32); ++ break; ++ } ++ dwc_udelay(1); ++ } ++ while (greset.b.csftrst == 1); ++ ++ /* Wait for 3 PHY Clocks */ ++ dwc_mdelay(100); ++} ++ ++uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if) ++{ ++ return (dwc_otg_mode(_core_if) != DWC_HOST_MODE); ++} ++ ++uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if) ++{ ++ return (dwc_otg_mode(_core_if) == DWC_HOST_MODE); ++} ++ ++/** ++ * Register HCD callbacks. The callbacks are used to start and stop ++ * the HCD for interrupt processing. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param cb the HCD callback structure. ++ * @param p pointer to be passed to callback function (usb_hcd*). ++ */ ++void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * core_if, ++ dwc_otg_cil_callbacks_t * cb, void *p) ++{ ++ core_if->hcd_cb = cb; ++ cb->p = p; ++} ++ ++/** ++ * Register PCD callbacks. The callbacks are used to start and stop ++ * the PCD for interrupt processing. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param cb the PCD callback structure. ++ * @param p pointer to be passed to callback function (pcd*). ++ */ ++void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * core_if, ++ dwc_otg_cil_callbacks_t * cb, void *p) ++{ ++ core_if->pcd_cb = cb; ++ cb->p = p; ++} ++ ++#ifdef DWC_EN_ISOC ++ ++/** ++ * This function writes isoc data per 1 (micro)frame into tx fifo ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void write_isoc_frame_data(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ dwc_otg_dev_in_ep_regs_t *ep_regs; ++ dtxfsts_data_t txstatus = {.d32 = 0 }; ++ uint32_t len = 0; ++ uint32_t dwords; ++ ++ ep->xfer_len = ep->data_per_frame; ++ ep->xfer_count = 0; ++ ++ ep_regs = core_if->dev_if->in_ep_regs[ep->num]; ++ ++ len = ep->xfer_len - ep->xfer_count; ++ ++ if (len > ep->maxpacket) { ++ len = ep->maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ ++ /* While there is space in the queue and space in the FIFO and ++ * More data to tranfer, Write packets to the Tx FIFO */ ++ txstatus.d32 = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", ep->num, txstatus.d32); ++ ++ while (txstatus.b.txfspcavail > dwords && ++ ep->xfer_count < ep->xfer_len && ep->xfer_len != 0) { ++ /* Write the FIFO */ ++ dwc_otg_ep_write_packet(core_if, ep, 0); ++ ++ len = ep->xfer_len - ep->xfer_count; ++ if (len > ep->maxpacket) { ++ len = ep->maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ txstatus.d32 = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", ep->num, ++ txstatus.d32); ++ } ++} ++ ++/** ++ * This function initializes a descriptor chain for Isochronous transfer ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * ep) ++{ ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dsts_data_t dsts = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ ++ if (ep->is_in) { ++ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; ++ } else { ++ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; ++ } ++ ++ ep->xfer_len = ep->data_per_frame; ++ ep->xfer_count = 0; ++ ep->xfer_buff = ep->cur_pkt_addr; ++ ep->dma_addr = ep->cur_pkt_dma_addr; ++ ++ if (ep->is_in) { ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ deptsiz.b.xfersize = ep->xfer_len; ++ deptsiz.b.pktcnt = ++ (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; ++ deptsiz.b.mc = deptsiz.b.pktcnt; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz, ++ deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->dma_enable) { ++ DWC_WRITE_REG32(& ++ (core_if->dev_if->in_ep_regs[ep->num]-> ++ diepdma), (uint32_t) ep->dma_addr); ++ } ++ } else { ++ deptsiz.b.pktcnt = ++ (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket; ++ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; ++ ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->num]->doeptsiz, deptsiz.d32); ++ ++ if (core_if->dma_enable) { ++ DWC_WRITE_REG32(& ++ (core_if->dev_if-> ++ out_ep_regs[ep->num]->doepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ } ++ ++ /** Enable endpoint, clear nak */ ++ ++ depctl.d32 = 0; ++ if (ep->bInterval == 1) { ++ dsts.d32 = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ep->next_frame = dsts.b.soffn + ep->bInterval; ++ ++ if (ep->next_frame & 0x1) { ++ depctl.b.setd1pid = 1; ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ } else { ++ ep->next_frame += ep->bInterval; ++ ++ if (ep->next_frame & 0x1) { ++ depctl.b.setd1pid = 1; ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ } ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ ++ DWC_MODIFY_REG32(addr, 0, depctl.d32); ++ depctl.d32 = DWC_READ_REG32(addr); ++ ++ if (ep->is_in && core_if->dma_enable == 0) { ++ write_isoc_frame_data(core_if, ep); ++ } ++ ++} ++#endif /* DWC_EN_ISOC */ ++ ++static void dwc_otg_set_uninitialized(int32_t * p, int size) ++{ ++ int i; ++ for (i = 0; i < size; i++) { ++ p[i] = -1; ++ } ++} ++ ++static int dwc_otg_param_initialized(int32_t val) ++{ ++ return val != -1; ++} ++ ++static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if) ++{ ++ int i; ++ gintsts_data_t gintsts; ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ ++ core_if->core_params = DWC_ALLOC(sizeof(*core_if->core_params)); ++ if (!core_if->core_params) { ++ return -DWC_E_NO_MEMORY; ++ } ++ dwc_otg_set_uninitialized((int32_t *) core_if->core_params, ++ sizeof(*core_if->core_params) / ++ sizeof(int32_t)); ++ DWC_PRINTF("Setting default values for core params\n"); ++ dwc_otg_set_param_otg_cap(core_if, dwc_param_otg_cap_default); ++ dwc_otg_set_param_dma_enable(core_if, dwc_param_dma_enable_default); ++ dwc_otg_set_param_dma_desc_enable(core_if, ++ dwc_param_dma_desc_enable_default); ++ dwc_otg_set_param_opt(core_if, dwc_param_opt_default); ++ dwc_otg_set_param_dma_burst_size(core_if, ++ dwc_param_dma_burst_size_default); ++ dwc_otg_set_param_host_support_fs_ls_low_power(core_if, ++ dwc_param_host_support_fs_ls_low_power_default); ++ dwc_otg_set_param_enable_dynamic_fifo(core_if, ++ dwc_param_enable_dynamic_fifo_default); ++ dwc_otg_set_param_data_fifo_size(core_if, ++ dwc_param_data_fifo_size_default); ++ dwc_otg_set_param_dev_rx_fifo_size(core_if, ++ dwc_param_dev_rx_fifo_size_default); ++ dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if, ++ dwc_param_dev_nperio_tx_fifo_size_default); ++ dwc_otg_set_param_host_rx_fifo_size(core_if, ++ dwc_param_host_rx_fifo_size_default); ++ dwc_otg_set_param_host_nperio_tx_fifo_size(core_if, ++ dwc_param_host_nperio_tx_fifo_size_default); ++ dwc_otg_set_param_host_perio_tx_fifo_size(core_if, ++ dwc_param_host_perio_tx_fifo_size_default); ++ dwc_otg_set_param_max_transfer_size(core_if, ++ dwc_param_max_transfer_size_default); ++ dwc_otg_set_param_max_packet_count(core_if, ++ dwc_param_max_packet_count_default); ++ dwc_otg_set_param_host_channels(core_if, ++ dwc_param_host_channels_default); ++ dwc_otg_set_param_dev_endpoints(core_if, ++ dwc_param_dev_endpoints_default); ++ dwc_otg_set_param_phy_type(core_if, dwc_param_phy_type_default); ++ dwc_otg_set_param_speed(core_if, dwc_param_speed_default); ++ dwc_otg_set_param_host_ls_low_power_phy_clk(core_if, ++ dwc_param_host_ls_low_power_phy_clk_default); ++ dwc_otg_set_param_phy_ulpi_ddr(core_if, dwc_param_phy_ulpi_ddr_default); ++ dwc_otg_set_param_phy_ulpi_ext_vbus(core_if, ++ dwc_param_phy_ulpi_ext_vbus_default); ++ dwc_otg_set_param_phy_utmi_width(core_if, ++ dwc_param_phy_utmi_width_default); ++ dwc_otg_set_param_ts_dline(core_if, dwc_param_ts_dline_default); ++ dwc_otg_set_param_i2c_enable(core_if, dwc_param_i2c_enable_default); ++ dwc_otg_set_param_ulpi_fs_ls(core_if, dwc_param_ulpi_fs_ls_default); ++ dwc_otg_set_param_en_multiple_tx_fifo(core_if, ++ dwc_param_en_multiple_tx_fifo_default); ++ ++ if (gintsts.b.curmode) { ++ /* Force device mode to get power-on values of device FIFOs */ ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gusbcfg.b.force_dev_mode = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ dwc_mdelay(100); ++ for (i = 0; i < 15; i++) { ++ dwc_otg_set_param_dev_perio_tx_fifo_size(core_if, ++ dwc_param_dev_perio_tx_fifo_size_default, i); ++ } ++ for (i = 0; i < 15; i++) { ++ dwc_otg_set_param_dev_tx_fifo_size(core_if, ++ dwc_param_dev_tx_fifo_size_default, i); ++ } ++ gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gusbcfg.b.force_dev_mode = 0; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ dwc_mdelay(100); ++ } else { ++ for (i = 0; i < 15; i++) { ++ dwc_otg_set_param_dev_perio_tx_fifo_size(core_if, ++ dwc_param_dev_perio_tx_fifo_size_default, i); ++ } ++ for (i = 0; i < 15; i++) { ++ dwc_otg_set_param_dev_tx_fifo_size(core_if, ++ dwc_param_dev_tx_fifo_size_default, i); ++ } ++ } ++ ++ dwc_otg_set_param_thr_ctl(core_if, dwc_param_thr_ctl_default); ++ dwc_otg_set_param_mpi_enable(core_if, dwc_param_mpi_enable_default); ++ dwc_otg_set_param_pti_enable(core_if, dwc_param_pti_enable_default); ++ dwc_otg_set_param_lpm_enable(core_if, dwc_param_lpm_enable_default); ++ ++ dwc_otg_set_param_besl_enable(core_if, dwc_param_besl_enable_default); ++ dwc_otg_set_param_baseline_besl(core_if, dwc_param_baseline_besl_default); ++ dwc_otg_set_param_deep_besl(core_if, dwc_param_deep_besl_default); ++ ++ dwc_otg_set_param_ic_usb_cap(core_if, dwc_param_ic_usb_cap_default); ++ dwc_otg_set_param_tx_thr_length(core_if, ++ dwc_param_tx_thr_length_default); ++ dwc_otg_set_param_rx_thr_length(core_if, ++ dwc_param_rx_thr_length_default); ++ dwc_otg_set_param_ahb_thr_ratio(core_if, ++ dwc_param_ahb_thr_ratio_default); ++ dwc_otg_set_param_power_down(core_if, dwc_param_power_down_default); ++ dwc_otg_set_param_reload_ctl(core_if, dwc_param_reload_ctl_default); ++ dwc_otg_set_param_dev_out_nak(core_if, dwc_param_dev_out_nak_default); ++ dwc_otg_set_param_cont_on_bna(core_if, dwc_param_cont_on_bna_default); ++ dwc_otg_set_param_ahb_single(core_if, dwc_param_ahb_single_default); ++ dwc_otg_set_param_otg_ver(core_if, dwc_param_otg_ver_default); ++ dwc_otg_set_param_adp_enable(core_if, dwc_param_adp_enable_default); ++ return 0; ++} ++ ++uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->dma_enable; ++} ++ ++/* Checks if the parameter is outside of its valid range of values */ ++#define DWC_OTG_PARAM_TEST(_param_, _low_, _high_) \ ++ (((_param_) < (_low_)) || \ ++ ((_param_) > (_high_))) ++ ++/* Parameter access functions */ ++int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int valid; ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 2)) { ++ DWC_WARN("Wrong value for otg_cap parameter\n"); ++ DWC_WARN("otg_cap parameter must be 0,1 or 2\n"); ++ retval = -DWC_E_INVALID; ++ goto out; ++ } ++ ++ valid = 1; ++ switch (val) { ++ case DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE: ++ if (core_if->hwcfg2.b.op_mode != ++ DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ++ valid = 0; ++ break; ++ case DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE: ++ if ((core_if->hwcfg2.b.op_mode != ++ DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ++ && (core_if->hwcfg2.b.op_mode != ++ DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) ++ && (core_if->hwcfg2.b.op_mode != ++ DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE) ++ && (core_if->hwcfg2.b.op_mode != ++ DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) { ++ valid = 0; ++ } ++ break; ++ case DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE: ++ /* always valid */ ++ break; ++ } ++ if (!valid) { ++ if (dwc_otg_param_initialized(core_if->core_params->otg_cap)) { ++ DWC_ERROR ++ ("%d invalid for otg_cap paremter. Check HW configuration.\n", ++ val); ++ } ++ val = ++ (((core_if->hwcfg2.b.op_mode == ++ DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ++ || (core_if->hwcfg2.b.op_mode == ++ DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) ++ || (core_if->hwcfg2.b.op_mode == ++ DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE) ++ || (core_if->hwcfg2.b.op_mode == ++ DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) ? ++ DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE : ++ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->otg_cap = val; ++out: ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->otg_cap; ++} ++ ++int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong value for opt parameter\n"); ++ return -DWC_E_INVALID; ++ } ++ core_if->core_params->opt = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->opt; ++} ++ ++int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong value for dma enable\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && (core_if->hwcfg2.b.architecture == 0)) { ++ if (dwc_otg_param_initialized(core_if->core_params->dma_enable)) { ++ DWC_ERROR ++ ("%d invalid for dma_enable paremter. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->dma_enable = val; ++ if (val == 0) { ++ dwc_otg_set_param_dma_desc_enable(core_if, 0); ++ } ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dma_enable; ++} ++ ++int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong value for dma_enable\n"); ++ DWC_WARN("dma_desc_enable must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) ++ && ((dwc_otg_get_param_dma_enable(core_if) == 0) ++ || (core_if->hwcfg4.b.desc_dma == 0))) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->dma_desc_enable)) { ++ DWC_ERROR ++ ("%d invalid for dma_desc_enable paremter. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++ core_if->core_params->dma_desc_enable = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dma_desc_enable; ++} ++ ++int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong value for host_support_fs_low_power\n"); ++ DWC_WARN("host_support_fs_low_power must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ core_if->core_params->host_support_fs_ls_low_power = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t * ++ core_if) ++{ ++ return core_if->core_params->host_support_fs_ls_low_power; ++} ++ ++int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong value for enable_dynamic_fifo\n"); ++ DWC_WARN("enable_dynamic_fifo must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && (core_if->hwcfg2.b.dynamic_fifo == 0)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->enable_dynamic_fifo)) { ++ DWC_ERROR ++ ("%d invalid for enable_dynamic_fifo paremter. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++ core_if->core_params->enable_dynamic_fifo = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->enable_dynamic_fifo; ++} ++ ++int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 32, 32768)) { ++ DWC_WARN("Wrong value for data_fifo_size\n"); ++ DWC_WARN("data_fifo_size must be 32-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > core_if->hwcfg3.b.dfifo_depth) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->data_fifo_size)) { ++ DWC_ERROR ++ ("%d invalid for data_fifo_size parameter. Check HW configuration.\n", ++ val); ++ } ++ val = core_if->hwcfg3.b.dfifo_depth; ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->data_fifo_size = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->data_fifo_size; ++} ++ ++int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) { ++ DWC_WARN("Wrong value for dev_rx_fifo_size\n"); ++ DWC_WARN("dev_rx_fifo_size must be 16-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) { ++ if (dwc_otg_param_initialized(core_if->core_params->dev_rx_fifo_size)) { ++ DWC_WARN("%d invalid for dev_rx_fifo_size parameter\n", val); ++ } ++ val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->dev_rx_fifo_size = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dev_rx_fifo_size; ++} ++ ++int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) { ++ DWC_WARN("Wrong value for dev_nperio_tx_fifo\n"); ++ DWC_WARN("dev_nperio_tx_fifo must be 16-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->dev_nperio_tx_fifo_size)) { ++ DWC_ERROR ++ ("%d invalid for dev_nperio_tx_fifo_size. Check HW configuration.\n", ++ val); ++ } ++ val = ++ (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> ++ 16); ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->dev_nperio_tx_fifo_size = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dev_nperio_tx_fifo_size; ++} ++ ++int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) { ++ DWC_WARN("Wrong value for host_rx_fifo_size\n"); ++ DWC_WARN("host_rx_fifo_size must be 16-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->host_rx_fifo_size)) { ++ DWC_ERROR ++ ("%d invalid for host_rx_fifo_size. Check HW configuration.\n", ++ val); ++ } ++ val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->host_rx_fifo_size = val; ++ return retval; ++ ++} ++ ++int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->host_rx_fifo_size; ++} ++ ++int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) { ++ DWC_WARN("Wrong value for host_nperio_tx_fifo_size\n"); ++ DWC_WARN("host_nperio_tx_fifo_size must be 16-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->host_nperio_tx_fifo_size)) { ++ DWC_ERROR ++ ("%d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n", ++ val); ++ } ++ val = ++ (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> ++ 16); ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->host_nperio_tx_fifo_size = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->host_nperio_tx_fifo_size; ++} ++ ++int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) { ++ DWC_WARN("Wrong value for host_perio_tx_fifo_size\n"); ++ DWC_WARN("host_perio_tx_fifo_size must be 16-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > ((core_if->hptxfsiz.d32) >> 16)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->host_perio_tx_fifo_size)) { ++ DWC_ERROR ++ ("%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n", ++ val); ++ } ++ val = (core_if->hptxfsiz.d32) >> 16; ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->host_perio_tx_fifo_size = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->host_perio_tx_fifo_size; ++} ++ ++int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 2047, 524288)) { ++ DWC_WARN("Wrong value for max_transfer_size\n"); ++ DWC_WARN("max_transfer_size must be 2047-524288\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val >= (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11))) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->max_transfer_size)) { ++ DWC_ERROR ++ ("%d invalid for max_transfer_size. Check HW configuration.\n", ++ val); ++ } ++ val = ++ ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 11)) - ++ 1); ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->max_transfer_size = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->max_transfer_size; ++} ++ ++int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 15, 511)) { ++ DWC_WARN("Wrong value for max_packet_count\n"); ++ DWC_WARN("max_packet_count must be 15-511\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4))) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->max_packet_count)) { ++ DWC_ERROR ++ ("%d invalid for max_packet_count. Check HW configuration.\n", ++ val); ++ } ++ val = ++ ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1); ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->max_packet_count = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->max_packet_count; ++} ++ ++int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 1, 16)) { ++ DWC_WARN("Wrong value for host_channels\n"); ++ DWC_WARN("host_channels must be 1-16\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > (core_if->hwcfg2.b.num_host_chan + 1)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->host_channels)) { ++ DWC_ERROR ++ ("%d invalid for host_channels. Check HW configurations.\n", ++ val); ++ } ++ val = (core_if->hwcfg2.b.num_host_chan + 1); ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->host_channels = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->host_channels; ++} ++ ++int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 1, 15)) { ++ DWC_WARN("Wrong value for dev_endpoints\n"); ++ DWC_WARN("dev_endpoints must be 1-15\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > (core_if->hwcfg2.b.num_dev_ep)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->dev_endpoints)) { ++ DWC_ERROR ++ ("%d invalid for dev_endpoints. Check HW configurations.\n", ++ val); ++ } ++ val = core_if->hwcfg2.b.num_dev_ep; ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->dev_endpoints = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dev_endpoints; ++} ++ ++int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 2)) { ++ DWC_WARN("Wrong value for phy_type\n"); ++ DWC_WARN("phy_type must be 0,1 or 2\n"); ++ return -DWC_E_INVALID; ++ } ++#ifndef NO_FS_PHY_HW_CHECKS ++ if ((val == DWC_PHY_TYPE_PARAM_UTMI) && ++ ((core_if->hwcfg2.b.hs_phy_type == 1) || ++ (core_if->hwcfg2.b.hs_phy_type == 3))) { ++ valid = 1; ++ } else if ((val == DWC_PHY_TYPE_PARAM_ULPI) && ++ ((core_if->hwcfg2.b.hs_phy_type == 2) || ++ (core_if->hwcfg2.b.hs_phy_type == 3))) { ++ valid = 1; ++ } else if ((val == DWC_PHY_TYPE_PARAM_FS) && ++ (core_if->hwcfg2.b.fs_phy_type == 1)) { ++ valid = 1; ++ } ++ if (!valid) { ++ if (dwc_otg_param_initialized(core_if->core_params->phy_type)) { ++ DWC_ERROR ++ ("%d invalid for phy_type. Check HW configurations.\n", ++ val); ++ } ++ if (core_if->hwcfg2.b.hs_phy_type) { ++ if ((core_if->hwcfg2.b.hs_phy_type == 3) || ++ (core_if->hwcfg2.b.hs_phy_type == 1)) { ++ val = DWC_PHY_TYPE_PARAM_UTMI; ++ } else { ++ val = DWC_PHY_TYPE_PARAM_ULPI; ++ } ++ } ++ retval = -DWC_E_INVALID; ++ } ++#endif ++ core_if->core_params->phy_type = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->phy_type; ++} ++ ++int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong value for speed parameter\n"); ++ DWC_WARN("max_speed parameter must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ if ((val == 0) ++ && dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS) { ++ if (dwc_otg_param_initialized(core_if->core_params->speed)) { ++ DWC_ERROR ++ ("%d invalid for speed paremter. Check HW configuration.\n", ++ val); ++ } ++ val = ++ (dwc_otg_get_param_phy_type(core_if) == ++ DWC_PHY_TYPE_PARAM_FS ? 1 : 0); ++ retval = -DWC_E_INVALID; ++ } ++ core_if->core_params->speed = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->speed; ++} ++ ++int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN ++ ("Wrong value for host_ls_low_power_phy_clk parameter\n"); ++ DWC_WARN("host_ls_low_power_phy_clk must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ) ++ && (dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->host_ls_low_power_phy_clk)) { ++ DWC_ERROR ++ ("%d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n", ++ val); ++ } ++ val = ++ (dwc_otg_get_param_phy_type(core_if) == ++ DWC_PHY_TYPE_PARAM_FS) ? ++ DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ : ++ DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ; ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->host_ls_low_power_phy_clk = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->host_ls_low_power_phy_clk; ++} ++ ++int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong value for phy_ulpi_ddr\n"); ++ DWC_WARN("phy_upli_ddr must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->phy_ulpi_ddr = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->phy_ulpi_ddr; ++} ++ ++int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong valaue for phy_ulpi_ext_vbus\n"); ++ DWC_WARN("phy_ulpi_ext_vbus must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->phy_ulpi_ext_vbus = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->phy_ulpi_ext_vbus; ++} ++ ++int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 8, 8) && DWC_OTG_PARAM_TEST(val, 16, 16)) { ++ DWC_WARN("Wrong valaue for phy_utmi_width\n"); ++ DWC_WARN("phy_utmi_width must be 8 or 16\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->phy_utmi_width = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->phy_utmi_width; ++} ++ ++int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong valaue for ulpi_fs_ls\n"); ++ DWC_WARN("ulpi_fs_ls must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->ulpi_fs_ls = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->ulpi_fs_ls; ++} ++ ++int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong valaue for ts_dline\n"); ++ DWC_WARN("ts_dline must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->ts_dline = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->ts_dline; ++} ++ ++int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong valaue for i2c_enable\n"); ++ DWC_WARN("i2c_enable must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++#ifndef NO_FS_PHY_HW_CHECK ++ if (val == 1 && core_if->hwcfg3.b.i2c == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->i2c_enable)) { ++ DWC_ERROR ++ ("%d invalid for i2c_enable. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++#endif ++ ++ core_if->core_params->i2c_enable = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->i2c_enable; ++} ++ ++int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if, ++ int32_t val, int fifo_num) ++{ ++ int retval = 0; ++ gintsts_data_t gintsts; ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ ++ if (DWC_OTG_PARAM_TEST(val, 4, 768)) { ++ DWC_WARN("Wrong value for dev_perio_tx_fifo_size\n"); ++ DWC_WARN("dev_perio_tx_fifo_size must be 4-768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > ++ (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]) >> 16)) { ++ DWC_WARN("Value is larger then power-on FIFO size\n"); ++ if (dwc_otg_param_initialized ++ (core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) { ++ DWC_ERROR ++ ("`%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n", ++ val, fifo_num); ++ } ++ val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]) >> 16); ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->dev_perio_tx_fifo_size[fifo_num] = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if, ++ int fifo_num) ++{ ++ return core_if->core_params->dev_perio_tx_fifo_size[fifo_num]; ++} ++ ++int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong valaue for en_multiple_tx_fifo,\n"); ++ DWC_WARN("en_multiple_tx_fifo must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val == 1 && core_if->hwcfg4.b.ded_fifo_en == 0) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->en_multiple_tx_fifo)) { ++ DWC_ERROR ++ ("%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->en_multiple_tx_fifo = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->en_multiple_tx_fifo; ++} ++ ++int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val, ++ int fifo_num) ++{ ++ int retval = 0; ++ fifosize_data_t txfifosize; ++ txfifosize.d32 = DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]); ++ ++ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) { ++ DWC_WARN("Wrong value for dev_tx_fifo_size\n"); ++ DWC_WARN("dev_tx_fifo_size must be 16-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > txfifosize.b.depth) { ++ DWC_WARN("Value is larger then power-on FIFO size\n"); ++ if (dwc_otg_param_initialized ++ (core_if->core_params->dev_tx_fifo_size[fifo_num])) { ++ DWC_ERROR ++ ("`%d' invalid for parameter `dev_tx_fifo_size_%d'. Check HW configuration.\n", ++ val, fifo_num); ++ } ++ val = txfifosize.b.depth; ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->dev_tx_fifo_size[fifo_num] = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if, ++ int fifo_num) ++{ ++ return core_if->core_params->dev_tx_fifo_size[fifo_num]; ++} ++ ++int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 7)) { ++ DWC_WARN("Wrong value for thr_ctl\n"); ++ DWC_WARN("thr_ctl must be 0-7\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val != 0) && ++ (!dwc_otg_get_param_dma_enable(core_if) || ++ !core_if->hwcfg4.b.ded_fifo_en)) { ++ if (dwc_otg_param_initialized(core_if->core_params->thr_ctl)) { ++ DWC_ERROR ++ ("%d invalid for parameter thr_ctl. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->thr_ctl = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_thr_ctl(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->thr_ctl; ++} ++ ++int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong value for lpm_enable\n"); ++ DWC_WARN("lpm_enable must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val && !core_if->hwcfg3.b.otg_lpm_en) { ++ if (dwc_otg_param_initialized(core_if->core_params->lpm_enable)) { ++ DWC_ERROR ++ ("%d invalid for parameter lpm_enable. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->lpm_enable = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->lpm_enable; ++} ++ ++int dwc_otg_set_param_besl_enable(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong value for besl_enable\n"); ++ DWC_WARN("besl_enable must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->besl_enable = val; ++ ++ if(val) ++ { ++ retval += dwc_otg_set_param_lpm_enable(core_if,val); ++ } ++ ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_besl_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->besl_enable; ++} ++ ++int dwc_otg_set_param_baseline_besl(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 15)) { ++ DWC_WARN("Wrong value for baseline_besl\n"); ++ DWC_WARN("baseline_besl must be 0-15\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->baseline_besl = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_baseline_besl(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->baseline_besl; ++} ++ ++int dwc_otg_set_param_deep_besl(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 15)) { ++ DWC_WARN("Wrong value for deep_besl\n"); ++ DWC_WARN("deep_besl must be 0-15\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->deep_besl = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_deep_besl(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->deep_besl; ++} ++ ++int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 8, 128)) { ++ DWC_WARN("Wrong valaue for tx_thr_length\n"); ++ DWC_WARN("tx_thr_length must be 8 - 128\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->tx_thr_length = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_tx_thr_length(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->tx_thr_length; ++} ++ ++int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 8, 128)) { ++ DWC_WARN("Wrong valaue for rx_thr_length\n"); ++ DWC_WARN("rx_thr_length must be 8 - 128\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->rx_thr_length = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_rx_thr_length(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->rx_thr_length; ++} ++ ++int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 1, 1) && ++ DWC_OTG_PARAM_TEST(val, 4, 4) && ++ DWC_OTG_PARAM_TEST(val, 8, 8) && ++ DWC_OTG_PARAM_TEST(val, 16, 16) && ++ DWC_OTG_PARAM_TEST(val, 32, 32) && ++ DWC_OTG_PARAM_TEST(val, 64, 64) && ++ DWC_OTG_PARAM_TEST(val, 128, 128) && ++ DWC_OTG_PARAM_TEST(val, 256, 256)) { ++ DWC_WARN("`%d' invalid for parameter `dma_burst_size'\n", val); ++ return -DWC_E_INVALID; ++ } ++ core_if->core_params->dma_burst_size = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dma_burst_size; ++} ++ ++int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `pti_enable'\n", val); ++ return -DWC_E_INVALID; ++ } ++ if (val && (core_if->snpsid < OTG_CORE_REV_2_72a)) { ++ if (dwc_otg_param_initialized(core_if->core_params->pti_enable)) { ++ DWC_ERROR ++ ("%d invalid for parameter pti_enable. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->pti_enable = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->pti_enable; ++} ++ ++int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `mpi_enable'\n", val); ++ return -DWC_E_INVALID; ++ } ++ if (val && (core_if->hwcfg2.b.multi_proc_int == 0)) { ++ if (dwc_otg_param_initialized(core_if->core_params->mpi_enable)) { ++ DWC_ERROR ++ ("%d invalid for parameter mpi_enable. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->mpi_enable = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->mpi_enable; ++} ++ ++int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `adp_enable'\n", val); ++ return -DWC_E_INVALID; ++ } ++ if (val && (core_if->hwcfg3.b.adp_supp == 0)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->adp_supp_enable)) { ++ DWC_ERROR ++ ("%d invalid for parameter adp_enable. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->adp_supp_enable = val; ++ /* Set OTG version 2.0 in case of enabling ADP */ ++ if (val) ++ dwc_otg_set_param_otg_ver(core_if, 1); ++ ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->adp_supp_enable; ++} ++ ++int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `ic_usb_cap'\n", val); ++ DWC_WARN("ic_usb_cap must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val && (core_if->hwcfg2.b.otg_enable_ic_usb == 0)) { ++ if (dwc_otg_param_initialized(core_if->core_params->ic_usb_cap)) { ++ DWC_ERROR ++ ("%d invalid for parameter ic_usb_cap. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->ic_usb_cap = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->ic_usb_cap; ++} ++ ++int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 3)) { ++ DWC_WARN("`%d' invalid for parameter `ahb_thr_ratio'\n", val); ++ DWC_WARN("ahb_thr_ratio must be 0 - 3\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val ++ && (core_if->snpsid < OTG_CORE_REV_2_81a ++ || !dwc_otg_get_param_thr_ctl(core_if))) { ++ valid = 0; ++ } else if (val ++ && ((dwc_otg_get_param_tx_thr_length(core_if) / (1 << val)) < ++ 4)) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->ahb_thr_ratio)) { ++ DWC_ERROR ++ ("%d invalid for parameter ahb_thr_ratio. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ ++ core_if->core_params->ahb_thr_ratio = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->ahb_thr_ratio; ++} ++ ++int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ hwcfg4_data_t hwcfg4 = {.d32 = 0 }; ++ hwcfg4.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4); ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 3)) { ++ DWC_WARN("`%d' invalid for parameter `power_down'\n", val); ++ DWC_WARN("power_down must be 0 - 2\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 2) && (core_if->snpsid < OTG_CORE_REV_2_91a)) { ++ valid = 0; ++ } ++ if ((val == 3) ++ && ((core_if->snpsid < OTG_CORE_REV_3_00a) ++ || (hwcfg4.b.xhiber == 0))) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->power_down)) { ++ DWC_ERROR ++ ("%d invalid for parameter power_down. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->power_down = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->power_down; ++} ++ ++int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `reload_ctl'\n", val); ++ DWC_WARN("reload_ctl must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_92a)) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->reload_ctl)) { ++ DWC_ERROR("%d invalid for parameter reload_ctl." ++ "Check HW configuration.\n", val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->reload_ctl = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->reload_ctl; ++} ++ ++int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `dev_out_nak'\n", val); ++ DWC_WARN("dev_out_nak must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_93a) || ++ !(core_if->core_params->dma_desc_enable))) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->dev_out_nak)) { ++ DWC_ERROR("%d invalid for parameter dev_out_nak." ++ "Check HW configuration.\n", val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->dev_out_nak = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dev_out_nak; ++} ++ ++int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `cont_on_bna'\n", val); ++ DWC_WARN("cont_on_bna must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_94a) || ++ !(core_if->core_params->dma_desc_enable))) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->cont_on_bna)) { ++ DWC_ERROR("%d invalid for parameter cont_on_bna." ++ "Check HW configuration.\n", val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->cont_on_bna = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->cont_on_bna; ++} ++ ++int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `ahb_single'\n", val); ++ DWC_WARN("ahb_single must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_94a)) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->ahb_single)) { ++ DWC_ERROR("%d invalid for parameter ahb_single." ++ "Check HW configuration.\n", val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->ahb_single = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->ahb_single; ++} ++ ++int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `otg_ver'\n", val); ++ DWC_WARN ++ ("otg_ver must be 0(for OTG 1.3 support) or 1(for OTG 2.0 support)\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->otg_ver = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->otg_ver; ++} ++ ++uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if) ++{ ++ gotgctl_data_t otgctl; ++ otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ return otgctl.b.hstnegscs; ++} ++ ++uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if) ++{ ++ gotgctl_data_t otgctl; ++ otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ return otgctl.b.sesreqscs; ++} ++ ++void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ if(core_if->otg_ver == 0) { ++ gotgctl_data_t otgctl; ++ otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ otgctl.b.hnpreq = val; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, otgctl.d32); ++ } else { ++ core_if->otg_sts = val; ++ } ++} ++ ++uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->snpsid; ++} ++ ++uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ return gintsts.b.curmode; ++} ++ ++uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if) ++{ ++ gusbcfg_data_t usbcfg; ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ return usbcfg.b.hnpcap; ++} ++ ++void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ gusbcfg_data_t usbcfg; ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ usbcfg.b.hnpcap = val; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32); ++} ++ ++uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if) ++{ ++ gusbcfg_data_t usbcfg; ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ return usbcfg.b.srpcap; ++} ++ ++void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ gusbcfg_data_t usbcfg; ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ usbcfg.b.srpcap = val; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32); ++} ++ ++uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if) ++{ ++ dcfg_data_t dcfg; ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ return dcfg.b.devspd; ++} ++ ++void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ dcfg_data_t dcfg; ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ dcfg.b.devspd = val; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); ++} ++ ++uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); ++ return hprt0.b.prtconnsts; ++} ++ ++uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if) ++{ ++ dsts_data_t dsts; ++ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ return dsts.b.enumspd; ++} ++ ++uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); ++ return hprt0.b.prtpwr; ++ ++} ++ ++uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->hibernation_suspend; ++} ++ ++void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = val; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++} ++ ++uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); ++ return hprt0.b.prtsusp; ++ ++} ++ ++void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = val; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++} ++ ++uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if) ++{ ++ hfir_data_t hfir; ++ hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir); ++ return hfir.b.frint; ++ ++} ++ ++void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ hfir_data_t hfir; ++ uint32_t fram_int; ++ fram_int = calc_frame_interval(core_if); ++ hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir); ++ if (!core_if->core_params->reload_ctl) { ++ DWC_WARN("\nCannot reload HFIR register.HFIR.HFIRRldCtrl bit is" ++ "not set to 1.\nShould load driver with reload_ctl=1" ++ " module parameter\n"); ++ return; ++ } ++ switch (fram_int) { ++ case 3750: ++ if ((val < 3350) || (val > 4150)) { ++ DWC_WARN("HFIR interval for HS core and 30 MHz" ++ "clock freq should be from 3350 to 4150\n"); ++ return; ++ } ++ break; ++ case 30000: ++ if ((val < 26820) || (val > 33180)) { ++ DWC_WARN("HFIR interval for FS/LS core and 30 MHz" ++ "clock freq should be from 26820 to 33180\n"); ++ return; ++ } ++ break; ++ case 6000: ++ if ((val < 5360) || (val > 6640)) { ++ DWC_WARN("HFIR interval for HS core and 48 MHz" ++ "clock freq should be from 5360 to 6640\n"); ++ return; ++ } ++ break; ++ case 48000: ++ if ((val < 42912) || (val > 53088)) { ++ DWC_WARN("HFIR interval for FS/LS core and 48 MHz" ++ "clock freq should be from 42912 to 53088\n"); ++ return; ++ } ++ break; ++ case 7500: ++ if ((val < 6700) || (val > 8300)) { ++ DWC_WARN("HFIR interval for HS core and 60 MHz" ++ "clock freq should be from 6700 to 8300\n"); ++ return; ++ } ++ break; ++ case 60000: ++ if ((val < 53640) || (val > 65536)) { ++ DWC_WARN("HFIR interval for FS/LS core and 60 MHz" ++ "clock freq should be from 53640 to 65536\n"); ++ return; ++ } ++ break; ++ default: ++ DWC_WARN("Unknown frame interval\n"); ++ return; ++ break; ++ ++ } ++ hfir.b.frint = val; ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hfir.d32); ++} ++ ++uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if) ++{ ++ hcfg_data_t hcfg; ++ hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ return hcfg.b.modechtimen; ++ ++} ++ ++void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ hcfg_data_t hcfg; ++ hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ hcfg.b.modechtimen = val; ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++} ++ ++void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtres = val; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++} ++ ++uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if) ++{ ++ dctl_data_t dctl; ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ return dctl.b.rmtwkupsig; ++} ++ ++uint32_t dwc_otg_get_beslreject(dwc_otg_core_if_t * core_if) ++{ ++ dctl_data_t dctl; ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ return dctl.b.besl_reject; ++} ++ ++void dwc_otg_set_beslreject(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ dctl_data_t dctl; ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ dctl.b.besl_reject = val; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++} ++uint32_t dwc_otg_get_hirdthresh(dwc_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ return lpmcfg.b.hird_thres; ++} ++ ++void dwc_otg_set_hirdthresh(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ glpmcfg_data_t lpmcfg; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 15)) { ++ DWC_WARN("Wrong valaue for hird_thres\n"); ++ DWC_WARN("hird_thres must be 0-f\n"); ++ return ; ++ } ++ ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.hird_thres &= (1<<4); ++ lpmcfg.b.hird_thres |= val; ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++} ++ ++uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ ++ DWC_ASSERT(! ++ ((core_if->lx_state == DWC_OTG_L1) ^ lpmcfg.b.prt_sleep_sts), ++ "lx_state = %d, lmpcfg.prt_sleep_sts = %d\n", ++ core_if->lx_state, lpmcfg.b.prt_sleep_sts); ++ ++ return lpmcfg.b.prt_sleep_sts; ++} ++ ++uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ return lpmcfg.b.rem_wkup_en; ++} ++ ++uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ return lpmcfg.b.appl_resp; ++} ++ ++void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.appl_resp = val; ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++} ++ ++uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ return lpmcfg.b.hsic_connect; ++} ++ ++void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.hsic_connect = val; ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++} ++ ++uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ return lpmcfg.b.inv_sel_hsic; ++ ++} ++ ++void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.inv_sel_hsic = val; ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++} ++ ++uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if) ++{ ++ return DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++} ++ ++void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, val); ++} ++ ++uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if) ++{ ++ return DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++} ++ ++void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, val); ++} ++ ++uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if) ++{ ++ return DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); ++} ++ ++void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, val); ++} ++ ++uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if) ++{ ++ return DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz); ++} ++ ++void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, val); ++} ++ ++uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if) ++{ ++ return DWC_READ_REG32(&core_if->core_global_regs->gpvndctl); ++} ++ ++void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gpvndctl, val); ++} ++ ++uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if) ++{ ++ return DWC_READ_REG32(&core_if->core_global_regs->ggpio); ++} ++ ++void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, val); ++} ++ ++uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if) ++{ ++ return DWC_READ_REG32(core_if->host_if->hprt0); ++ ++} ++ ++void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ DWC_WRITE_REG32(core_if->host_if->hprt0, val); ++} ++ ++uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if) ++{ ++ return DWC_READ_REG32(&core_if->core_global_regs->guid); ++} ++ ++void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ DWC_WRITE_REG32(&core_if->core_global_regs->guid, val); ++} ++ ++uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if) ++{ ++ return DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz); ++} ++ ++uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if) ++{ ++ return ((core_if->otg_ver == 1) ? (uint16_t)0x0200 : (uint16_t)0x0103); ++} ++ ++/** ++ * Start the SRP timer to detect when the SRP does not complete within ++ * 6 seconds. ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++void dwc_otg_pcd_start_srp_timer(dwc_otg_core_if_t * core_if) ++{ ++ core_if->srp_timer_started = 1; ++ DWC_TIMER_SCHEDULE(core_if->srp_timer, 6000 /* 6 secs */ ); ++} ++ ++void dwc_otg_initiate_srp(void * p) ++{ ++ dwc_otg_core_if_t * core_if = p; ++ uint32_t *addr = (uint32_t *) & (core_if->core_global_regs->gotgctl); ++ gotgctl_data_t mem; ++ gotgctl_data_t val; ++ ++ val.d32 = DWC_READ_REG32(addr); ++ if (val.b.sesreq) { ++ DWC_ERROR("Session Request Already active!\n"); ++ return; ++ } ++ ++ DWC_INFO("Session Request Initated\n"); //NOTICE ++ mem.d32 = DWC_READ_REG32(addr); ++ mem.b.sesreq = 1; ++ DWC_WRITE_REG32(addr, mem.d32); ++ ++ /* Start the SRP timer */ ++ dwc_otg_pcd_start_srp_timer(core_if); ++ return; ++} ++ ++int dwc_otg_check_haps_status(dwc_otg_core_if_t * core_if) ++{ ++ int retval = 0; ++ ++ if(DWC_READ_REG32(&core_if->core_global_regs->gsnpsid) == 0xffffffff) ++ { ++ return -1; ++ } else { ++ return retval; ++ } ++ ++} +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_cil.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_cil.h +new file mode 100644 +index 0000000..b52a280 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_cil.h +@@ -0,0 +1,1498 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $ ++ * $Revision: #128 $ ++ * $Date: 2013/05/16 $ ++ * $Change: 2231774 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++#if !defined(__DWC_CIL_H__) ++#define __DWC_CIL_H__ ++ ++#include "dwc_list.h" ++#include "dwc_otg_dbg.h" ++#include "dwc_otg_regs.h" ++ ++#include "dwc_otg_core_if.h" ++#include "dwc_otg_adp.h" ++ ++/** ++ * @file ++ * This file contains the interface to the Core Interface Layer. ++ */ ++ ++#ifdef DWC_UTE_CFI ++ ++#define MAX_DMA_DESCS_PER_EP 256 ++ ++/** ++ * Enumeration for the data buffer mode ++ */ ++typedef enum _data_buffer_mode { ++ BM_STANDARD = 0, /* data buffer is in normal mode */ ++ BM_SG = 1, /* data buffer uses the scatter/gather mode */ ++ BM_CONCAT = 2, /* data buffer uses the concatenation mode */ ++ BM_CIRCULAR = 3, /* data buffer uses the circular DMA mode */ ++ BM_ALIGN = 4 /* data buffer is in buffer alignment mode */ ++} data_buffer_mode_e; ++#endif //DWC_UTE_CFI ++ ++/** Macros defined for DWC OTG HW Release version */ ++ ++#define OTG_CORE_REV_2_60a 0x4F54260A ++#define OTG_CORE_REV_2_71a 0x4F54271A ++#define OTG_CORE_REV_2_72a 0x4F54272A ++#define OTG_CORE_REV_2_80a 0x4F54280A ++#define OTG_CORE_REV_2_81a 0x4F54281A ++#define OTG_CORE_REV_2_90a 0x4F54290A ++#define OTG_CORE_REV_2_91a 0x4F54291A ++#define OTG_CORE_REV_2_92a 0x4F54292A ++#define OTG_CORE_REV_2_93a 0x4F54293A ++#define OTG_CORE_REV_2_94a 0x4F54294A ++#define OTG_CORE_REV_3_00a 0x4F54300A ++#define OTG_CORE_REV_3_10a 0x4F54310A ++ ++/** ++ * Information for each ISOC packet. ++ */ ++typedef struct iso_pkt_info { ++ uint32_t offset; ++ uint32_t length; ++ int32_t status; ++} iso_pkt_info_t; ++ ++/** ++ * The dwc_ep structure represents the state of a single ++ * endpoint when acting in device mode. It contains the data items ++ * needed for an endpoint to be activated and transfer packets. ++ */ ++typedef struct dwc_ep { ++ /** EP number used for register address lookup */ ++ uint8_t num; ++ /** EP direction 0 = OUT */ ++ unsigned is_in:1; ++ /** EP active. */ ++ unsigned active:1; ++ ++ /** ++ * Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic ++ * Tx FIFO. If dedicated Tx FIFOs are enabled Tx FIFO # FOR IN EPs*/ ++ unsigned tx_fifo_num:4; ++ /** EP type: 0 - Control, 1 - ISOC, 2 - BULK, 3 - INTR */ ++ unsigned type:2; ++#define DWC_OTG_EP_TYPE_CONTROL 0 ++#define DWC_OTG_EP_TYPE_ISOC 1 ++#define DWC_OTG_EP_TYPE_BULK 2 ++#define DWC_OTG_EP_TYPE_INTR 3 ++ ++ /** DATA start PID for INTR and BULK EP */ ++ unsigned data_pid_start:1; ++ /** Frame (even/odd) for ISOC EP */ ++ unsigned even_odd_frame:1; ++ /** Max Packet bytes */ ++ unsigned maxpacket:11; ++ ++ /** Max Transfer size */ ++ uint32_t maxxfer; ++ ++ /** @name Transfer state */ ++ /** @{ */ ++ ++ /** ++ * Pointer to the beginning of the transfer buffer -- do not modify ++ * during transfer. ++ */ ++ dwc_dma_t dma_addr; ++ ++ dwc_dma_t dma_desc_addr; ++ dwc_otg_dev_dma_desc_t *desc_addr; ++ ++ /* Additional desc chain for ISO transfers */ ++ dwc_dma_t dma_desc_addr1; ++ dwc_otg_dev_dma_desc_t *desc_addr1; ++ /* Flag indicating which one of two ISO desc chains currently is in use */ ++ uint8_t use_add_buf; ++ ++ uint8_t *start_xfer_buff; ++ /** pointer to the transfer buffer */ ++ uint8_t *xfer_buff; ++ /** Number of bytes to transfer */ ++ unsigned xfer_len:19; ++ /** Number of bytes transferred. */ ++ unsigned xfer_count:19; ++ /** Sent ZLP */ ++ unsigned sent_zlp:1; ++ /** Total len for control transfer */ ++ unsigned total_len:19; ++ ++ /** stall clear flag */ ++ unsigned stall_clear_flag:1; ++ ++ /** SETUP pkt cnt rollover flag for EP0 out*/ ++ unsigned stp_rollover; ++ ++#ifdef DWC_UTE_CFI ++ /* The buffer mode */ ++ data_buffer_mode_e buff_mode; ++ ++ /* The chain of DMA descriptors. ++ * MAX_DMA_DESCS_PER_EP will be allocated for each active EP. ++ */ ++ dwc_otg_dma_desc_t *descs; ++ ++ /* The DMA address of the descriptors chain start */ ++ dma_addr_t descs_dma_addr; ++ /** This variable stores the length of the last enqueued request */ ++ uint32_t cfi_req_len; ++#endif //DWC_UTE_CFI ++ ++/** Max DMA Descriptor count for any EP */ ++#define MAX_DMA_DESC_CNT 256 ++ /** Allocated DMA Desc count */ ++ uint32_t desc_cnt; ++ ++ /** First ISO Desc in use in the first chain*/ ++ uint32_t iso_desc_first; ++ /** Last ISO Desc in use in the second chain */ ++ uint32_t iso_desc_second; ++ /** Flag indicated that iso transfers were started */ ++ uint8_t iso_transfer_started; ++ ++ /** bInterval */ ++ uint32_t bInterval; ++ /** Next frame num to setup next ISOC transfer */ ++ uint32_t frame_num; ++ /** Indicates SOF number overrun in DSTS */ ++ uint8_t frm_overrun; ++ ++#ifdef DWC_UTE_PER_IO ++ /** Next frame num for which will be setup DMA Desc */ ++ uint32_t xiso_frame_num; ++ /** bInterval */ ++ uint32_t xiso_bInterval; ++ /** Count of currently active transfers - shall be either 0 or 1 */ ++ int xiso_active_xfers; ++ int xiso_queued_xfers; ++#endif ++#ifdef DWC_EN_ISOC ++ /** ++ * Variables specific for ISOC EPs ++ * ++ */ ++ /** DMA addresses of ISOC buffers */ ++ dwc_dma_t dma_addr0; ++ dwc_dma_t dma_addr1; ++ ++ dwc_dma_t iso_dma_desc_addr; ++ dwc_otg_dev_dma_desc_t *iso_desc_addr; ++ ++ /** pointer to the transfer buffers */ ++ uint8_t *xfer_buff0; ++ uint8_t *xfer_buff1; ++ ++ /** number of ISOC Buffer is processing */ ++ uint32_t proc_buf_num; ++ /** Interval of ISOC Buffer processing */ ++ uint32_t buf_proc_intrvl; ++ /** Data size for regular frame */ ++ uint32_t data_per_frame; ++ ++ /* todo - pattern data support is to be implemented in the future */ ++ /** Data size for pattern frame */ ++ uint32_t data_pattern_frame; ++ /** Frame number of pattern data */ ++ uint32_t sync_frame; ++ ++ /** bInterval */ ++ uint32_t bInterval; ++ /** ISO Packet number per frame */ ++ uint32_t pkt_per_frm; ++ /** Next frame num for which will be setup DMA Desc */ ++ uint32_t next_frame; ++ /** Number of packets per buffer processing */ ++ uint32_t pkt_cnt; ++ /** Info for all isoc packets */ ++ iso_pkt_info_t *pkt_info; ++ /** current pkt number */ ++ uint32_t cur_pkt; ++ /** current pkt number */ ++ uint8_t *cur_pkt_addr; ++ /** current pkt number */ ++ uint32_t cur_pkt_dma_addr; ++#endif /* DWC_EN_ISOC */ ++ ++/** @} */ ++} dwc_ep_t; ++ ++/* ++ * Reasons for halting a host channel. ++ */ ++typedef enum dwc_otg_halt_status { ++ DWC_OTG_HC_XFER_NO_HALT_STATUS, ++ DWC_OTG_HC_XFER_COMPLETE, ++ DWC_OTG_HC_XFER_URB_COMPLETE, ++ DWC_OTG_HC_XFER_ACK, ++ DWC_OTG_HC_XFER_NAK, ++ DWC_OTG_HC_XFER_NYET, ++ DWC_OTG_HC_XFER_STALL, ++ DWC_OTG_HC_XFER_XACT_ERR, ++ DWC_OTG_HC_XFER_FRAME_OVERRUN, ++ DWC_OTG_HC_XFER_BABBLE_ERR, ++ DWC_OTG_HC_XFER_DATA_TOGGLE_ERR, ++ DWC_OTG_HC_XFER_AHB_ERR, ++ DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE, ++ DWC_OTG_HC_XFER_URB_DEQUEUE ++} dwc_otg_halt_status_e; ++ ++/** ++ * Host channel descriptor. This structure represents the state of a single ++ * host channel when acting in host mode. It contains the data items needed to ++ * transfer packets to an endpoint via a host channel. ++ */ ++typedef struct dwc_hc { ++ /** Host channel number used for register address lookup */ ++ uint8_t hc_num; ++ ++ /** Device to access */ ++ unsigned dev_addr:7; ++ ++ /** EP to access */ ++ unsigned ep_num:4; ++ ++ /** EP direction. 0: OUT, 1: IN */ ++ unsigned ep_is_in:1; ++ ++ /** ++ * EP speed. ++ * One of the following values: ++ * - DWC_OTG_EP_SPEED_LOW ++ * - DWC_OTG_EP_SPEED_FULL ++ * - DWC_OTG_EP_SPEED_HIGH ++ */ ++ unsigned speed:2; ++#define DWC_OTG_EP_SPEED_LOW 0 ++#define DWC_OTG_EP_SPEED_FULL 1 ++#define DWC_OTG_EP_SPEED_HIGH 2 ++ ++ /** ++ * Endpoint type. ++ * One of the following values: ++ * - DWC_OTG_EP_TYPE_CONTROL: 0 ++ * - DWC_OTG_EP_TYPE_ISOC: 1 ++ * - DWC_OTG_EP_TYPE_BULK: 2 ++ * - DWC_OTG_EP_TYPE_INTR: 3 ++ */ ++ unsigned ep_type:2; ++ ++ /** Max packet size in bytes */ ++ unsigned max_packet:11; ++ ++ /** ++ * PID for initial transaction. ++ * 0: DATA0,
++ * 1: DATA2,
++ * 2: DATA1,
++ * 3: MDATA (non-Control EP), ++ * SETUP (Control EP) ++ */ ++ unsigned data_pid_start:2; ++#define DWC_OTG_HC_PID_DATA0 0 ++#define DWC_OTG_HC_PID_DATA2 1 ++#define DWC_OTG_HC_PID_DATA1 2 ++#define DWC_OTG_HC_PID_MDATA 3 ++#define DWC_OTG_HC_PID_SETUP 3 ++ ++ /** Number of periodic transactions per (micro)frame */ ++ unsigned multi_count:2; ++ ++ /** @name Transfer State */ ++ /** @{ */ ++ ++ /** Pointer to the current transfer buffer position. */ ++ uint8_t *xfer_buff; ++ /** ++ * In Buffer DMA mode this buffer will be used ++ * if xfer_buff is not DWORD aligned. ++ */ ++ dwc_dma_t align_buff; ++ /** Total number of bytes to transfer. */ ++ uint32_t xfer_len; ++ /** Number of bytes transferred so far. */ ++ uint32_t xfer_count; ++ /** Packet count at start of transfer.*/ ++ uint16_t start_pkt_count; ++ ++ /** ++ * Flag to indicate whether the transfer has been started. Set to 1 if ++ * it has been started, 0 otherwise. ++ */ ++ uint8_t xfer_started; ++ ++ /** ++ * Set to 1 to indicate that a PING request should be issued on this ++ * channel. If 0, process normally. ++ */ ++ uint8_t do_ping; ++ ++ /** ++ * Set to 1 to indicate that the error count for this transaction is ++ * non-zero. Set to 0 if the error count is 0. ++ */ ++ uint8_t error_state; ++ ++ /** ++ * Set to 1 to indicate that this channel should be halted the next ++ * time a request is queued for the channel. This is necessary in ++ * slave mode if no request queue space is available when an attempt ++ * is made to halt the channel. ++ */ ++ uint8_t halt_on_queue; ++ ++ /** ++ * Set to 1 if the host channel has been halted, but the core is not ++ * finished flushing queued requests. Otherwise 0. ++ */ ++ uint8_t halt_pending; ++ ++ /** ++ * Reason for halting the host channel. ++ */ ++ dwc_otg_halt_status_e halt_status; ++ ++ /* ++ * Split settings for the host channel ++ */ ++ uint8_t do_split; /**< Enable split for the channel */ ++ uint8_t complete_split; /**< Enable complete split */ ++ uint8_t hub_addr; /**< Address of high speed hub */ ++ ++ uint8_t port_addr; /**< Port of the low/full speed device */ ++ /** Split transaction position ++ * One of the following values: ++ * - DWC_HCSPLIT_XACTPOS_MID ++ * - DWC_HCSPLIT_XACTPOS_BEGIN ++ * - DWC_HCSPLIT_XACTPOS_END ++ * - DWC_HCSPLIT_XACTPOS_ALL */ ++ uint8_t xact_pos; ++ ++ /** Set when the host channel does a short read. */ ++ uint8_t short_read; ++ ++ /** ++ * Number of requests issued for this channel since it was assigned to ++ * the current transfer (not counting PINGs). ++ */ ++ uint8_t requests; ++ ++ /** ++ * Queue Head for the transfer being processed by this channel. ++ */ ++ struct dwc_otg_qh *qh; ++ ++ /** @} */ ++ ++ /** Entry in list of host channels. */ ++ DWC_CIRCLEQ_ENTRY(dwc_hc) hc_list_entry; ++ ++ /** @name Descriptor DMA support */ ++ /** @{ */ ++ ++ /** Number of Transfer Descriptors */ ++ uint16_t ntd; ++ ++ /** Descriptor List DMA address */ ++ dwc_dma_t desc_list_addr; ++ ++ /** Scheduling micro-frame bitmap. */ ++ uint8_t schinfo; ++ ++ /** @} */ ++} dwc_hc_t; ++ ++/** ++ * The following parameters may be specified when starting the module. These ++ * parameters define how the DWC_otg controller should be configured. ++ */ ++typedef struct dwc_otg_core_params { ++ int32_t opt; ++ ++ /** ++ * Specifies the OTG capabilities. The driver will automatically ++ * detect the value for this parameter if none is specified. ++ * 0 - HNP and SRP capable (default) ++ * 1 - SRP Only capable ++ * 2 - No HNP/SRP capable ++ */ ++ int32_t otg_cap; ++ ++ /** ++ * Specifies whether to use slave or DMA mode for accessing the data ++ * FIFOs. The driver will automatically detect the value for this ++ * parameter if none is specified. ++ * 0 - Slave ++ * 1 - DMA (default, if available) ++ */ ++ int32_t dma_enable; ++ ++ /** ++ * When DMA mode is enabled specifies whether to use address DMA or DMA ++ * Descriptor mode for accessing the data FIFOs in device mode. The driver ++ * will automatically detect the value for this if none is specified. ++ * 0 - address DMA ++ * 1 - DMA Descriptor(default, if available) ++ */ ++ int32_t dma_desc_enable; ++ /** The DMA Burst size (applicable only for External DMA ++ * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32) ++ */ ++ int32_t dma_burst_size; /* Translate this to GAHBCFG values */ ++ ++ /** ++ * Specifies the maximum speed of operation in host and device mode. ++ * The actual speed depends on the speed of the attached device and ++ * the value of phy_type. The actual speed depends on the speed of the ++ * attached device. ++ * 0 - High Speed (default) ++ * 1 - Full Speed ++ */ ++ int32_t speed; ++ /** Specifies whether low power mode is supported when attached ++ * to a Full Speed or Low Speed device in host mode. ++ * 0 - Don't support low power mode (default) ++ * 1 - Support low power mode ++ */ ++ int32_t host_support_fs_ls_low_power; ++ ++ /** Specifies the PHY clock rate in low power mode when connected to a ++ * Low Speed device in host mode. This parameter is applicable only if ++ * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS ++ * then defaults to 6 MHZ otherwise 48 MHZ. ++ * ++ * 0 - 48 MHz ++ * 1 - 6 MHz ++ */ ++ int32_t host_ls_low_power_phy_clk; ++ ++ /** ++ * 0 - Use cC FIFO size parameters ++ * 1 - Allow dynamic FIFO sizing (default) ++ */ ++ int32_t enable_dynamic_fifo; ++ ++ /** Total number of 4-byte words in the data FIFO memory. This ++ * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic ++ * Tx FIFOs. ++ * 32 to 32768 (default 8192) ++ * Note: The total FIFO memory depth in the FPGA configuration is 8192. ++ */ ++ int32_t data_fifo_size; ++ ++ /** Number of 4-byte words in the Rx FIFO in device mode when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1064) ++ */ ++ int32_t dev_rx_fifo_size; ++ ++ /** Number of 4-byte words in the non-periodic Tx FIFO in device mode ++ * when dynamic FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++ int32_t dev_nperio_tx_fifo_size; ++ ++ /** Number of 4-byte words in each of the periodic Tx FIFOs in device ++ * mode when dynamic FIFO sizing is enabled. ++ * 4 to 768 (default 256) ++ */ ++ uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS]; ++ ++ /** Number of 4-byte words in the Rx FIFO in host mode when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++ int32_t host_rx_fifo_size; ++ ++ /** Number of 4-byte words in the non-periodic Tx FIFO in host mode ++ * when Dynamic FIFO sizing is enabled in the core. ++ * 16 to 32768 (default 1024) ++ */ ++ int32_t host_nperio_tx_fifo_size; ++ ++ /** Number of 4-byte words in the host periodic Tx FIFO when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++ int32_t host_perio_tx_fifo_size; ++ ++ /** The maximum transfer size supported in bytes. ++ * 2047 to 65,535 (default 65,535) ++ */ ++ int32_t max_transfer_size; ++ ++ /** The maximum number of packets in a transfer. ++ * 15 to 511 (default 511) ++ */ ++ int32_t max_packet_count; ++ ++ /** The number of host channel registers to use. ++ * 1 to 16 (default 12) ++ * Note: The FPGA configuration supports a maximum of 12 host channels. ++ */ ++ int32_t host_channels; ++ ++ /** The number of endpoints in addition to EP0 available for device ++ * mode operations. ++ * 1 to 15 (default 6 IN and OUT) ++ * Note: The FPGA configuration supports a maximum of 6 IN and OUT ++ * endpoints in addition to EP0. ++ */ ++ int32_t dev_endpoints; ++ ++ /** ++ * Specifies the type of PHY interface to use. By default, the driver ++ * will automatically detect the phy_type. ++ * ++ * 0 - Full Speed PHY ++ * 1 - UTMI+ (default) ++ * 2 - ULPI ++ */ ++ int32_t phy_type; ++ ++ /** ++ * Specifies the UTMI+ Data Width. This parameter is ++ * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI ++ * PHY_TYPE, this parameter indicates the data width between ++ * the MAC and the ULPI Wrapper.) Also, this parameter is ++ * applicable only if the OTG_HSPHY_WIDTH cC parameter was set ++ * to "8 and 16 bits", meaning that the core has been ++ * configured to work at either data path width. ++ * ++ * 8 or 16 bits (default 16) ++ */ ++ int32_t phy_utmi_width; ++ ++ /** ++ * Specifies whether the ULPI operates at double or single ++ * data rate. This parameter is only applicable if PHY_TYPE is ++ * ULPI. ++ * ++ * 0 - single data rate ULPI interface with 8 bit wide data ++ * bus (default) ++ * 1 - double data rate ULPI interface with 4 bit wide data ++ * bus ++ */ ++ int32_t phy_ulpi_ddr; ++ ++ /** ++ * Specifies whether to use the internal or external supply to ++ * drive the vbus with a ULPI phy. ++ */ ++ int32_t phy_ulpi_ext_vbus; ++ ++ /** ++ * Specifies whether to use the I2Cinterface for full speed PHY. This ++ * parameter is only applicable if PHY_TYPE is FS. ++ * 0 - No (default) ++ * 1 - Yes ++ */ ++ int32_t i2c_enable; ++ ++ int32_t ulpi_fs_ls; ++ ++ int32_t ts_dline; ++ ++ /** ++ * Specifies whether dedicated transmit FIFOs are ++ * enabled for non periodic IN endpoints in device mode ++ * 0 - No ++ * 1 - Yes ++ */ ++ int32_t en_multiple_tx_fifo; ++ ++ /** Number of 4-byte words in each of the Tx FIFOs in device ++ * mode when dynamic FIFO sizing is enabled. ++ * 4 to 768 (default 256) ++ */ ++ uint32_t dev_tx_fifo_size[MAX_TX_FIFOS]; ++ ++ /** Thresholding enable flag- ++ * bit 0 - enable non-ISO Tx thresholding ++ * bit 1 - enable ISO Tx thresholding ++ * bit 2 - enable Rx thresholding ++ */ ++ uint32_t thr_ctl; ++ ++ /** Thresholding length for Tx ++ * FIFOs in 32 bit DWORDs ++ */ ++ uint32_t tx_thr_length; ++ ++ /** Thresholding length for Rx ++ * FIFOs in 32 bit DWORDs ++ */ ++ uint32_t rx_thr_length; ++ ++ /** ++ * Specifies whether LPM (Link Power Management) support is enabled ++ */ ++ int32_t lpm_enable; ++ ++ /** ++ * Specifies whether LPM Errata (Link Power Management) support is enabled ++ */ ++ int32_t besl_enable; ++ ++ /** ++ * Specifies the baseline besl value ++ */ ++ int32_t baseline_besl; ++ ++ /** ++ * Specifies the deep besl value ++ */ ++ int32_t deep_besl; ++ /** Per Transfer Interrupt ++ * mode enable flag ++ * 1 - Enabled ++ * 0 - Disabled ++ */ ++ int32_t pti_enable; ++ ++ /** Multi Processor Interrupt ++ * mode enable flag ++ * 1 - Enabled ++ * 0 - Disabled ++ */ ++ int32_t mpi_enable; ++ ++ /** IS_USB Capability ++ * 1 - Enabled ++ * 0 - Disabled ++ */ ++ int32_t ic_usb_cap; ++ ++ /** AHB Threshold Ratio ++ * 2'b00 AHB Threshold = MAC Threshold ++ * 2'b01 AHB Threshold = 1/2 MAC Threshold ++ * 2'b10 AHB Threshold = 1/4 MAC Threshold ++ * 2'b11 AHB Threshold = 1/8 MAC Threshold ++ */ ++ int32_t ahb_thr_ratio; ++ ++ /** ADP Support ++ * 1 - Enabled ++ * 0 - Disabled ++ */ ++ int32_t adp_supp_enable; ++ ++ /** HFIR Reload Control ++ * 0 - The HFIR cannot be reloaded dynamically. ++ * 1 - Allow dynamic reloading of the HFIR register during runtime. ++ */ ++ int32_t reload_ctl; ++ ++ /** DCFG: Enable device Out NAK ++ * 0 - The core does not set NAK after Bulk Out transfer complete. ++ * 1 - The core sets NAK after Bulk OUT transfer complete. ++ */ ++ int32_t dev_out_nak; ++ ++ /** DCFG: Enable Continue on BNA ++ * After receiving BNA interrupt the core disables the endpoint,when the ++ * endpoint is re-enabled by the application the core starts processing ++ * 0 - from the DOEPDMA descriptor ++ * 1 - from the descriptor which received the BNA. ++ */ ++ int32_t cont_on_bna; ++ ++ /** GAHBCFG: AHB Single Support ++ * This bit when programmed supports SINGLE transfers for remainder ++ * data in a transfer for DMA mode of operation. ++ * 0 - in this case the remainder data will be sent using INCR burst size. ++ * 1 - in this case the remainder data will be sent using SINGLE burst size. ++ */ ++ int32_t ahb_single; ++ ++ /** Core Power down mode ++ * 0 - No Power Down is enabled ++ * 1 - Reserved ++ * 2 - Complete Power Down (Hibernation) ++ */ ++ int32_t power_down; ++ ++ /** OTG revision supported ++ * 0 - OTG 1.3 revision ++ * 1 - OTG 2.0 revision ++ */ ++ int32_t otg_ver; ++ ++} dwc_otg_core_params_t; ++ ++#ifdef DEBUG ++struct dwc_otg_core_if; ++typedef struct hc_xfer_info { ++ struct dwc_otg_core_if *core_if; ++ dwc_hc_t *hc; ++} hc_xfer_info_t; ++#endif ++ ++typedef struct ep_xfer_info { ++ struct dwc_otg_core_if *core_if; ++ dwc_ep_t *ep; ++ uint8_t state; ++} ep_xfer_info_t; ++/* ++ * Device States ++ */ ++typedef enum dwc_otg_lx_state { ++ /** On state */ ++ DWC_OTG_L0, ++ /** LPM sleep state*/ ++ DWC_OTG_L1, ++ /** USB suspend state*/ ++ DWC_OTG_L2, ++ /** Off state*/ ++ DWC_OTG_L3 ++} dwc_otg_lx_state_e; ++ ++struct dwc_otg_global_regs_backup { ++ uint32_t gotgctl_local; ++ uint32_t gintmsk_local; ++ uint32_t gahbcfg_local; ++ uint32_t gusbcfg_local; ++ uint32_t grxfsiz_local; ++ uint32_t gnptxfsiz_local; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ uint32_t glpmcfg_local; ++#endif ++ uint32_t gi2cctl_local; ++ uint32_t hptxfsiz_local; ++ uint32_t pcgcctl_local; ++ uint32_t gdfifocfg_local; ++ uint32_t dtxfsiz_local[MAX_EPS_CHANNELS]; ++ uint32_t gpwrdn_local; ++ uint32_t xhib_pcgcctl; ++ uint32_t xhib_gpwrdn; ++}; ++ ++struct dwc_otg_host_regs_backup { ++ uint32_t hcfg_local; ++ uint32_t haintmsk_local; ++ uint32_t hcintmsk_local[MAX_EPS_CHANNELS]; ++ uint32_t hprt0_local; ++ uint32_t hfir_local; ++}; ++ ++struct dwc_otg_dev_regs_backup { ++ uint32_t dcfg; ++ uint32_t dctl; ++ uint32_t daintmsk; ++ uint32_t diepmsk; ++ uint32_t doepmsk; ++ uint32_t diepctl[MAX_EPS_CHANNELS]; ++ uint32_t dieptsiz[MAX_EPS_CHANNELS]; ++ uint32_t diepdma[MAX_EPS_CHANNELS]; ++}; ++/** ++ * The dwc_otg_core_if structure contains information needed to manage ++ * the DWC_otg controller acting in either host or device mode. It ++ * represents the programming view of the controller as a whole. ++ */ ++struct dwc_otg_core_if { ++ /** Parameters that define how the core should be configured.*/ ++ dwc_otg_core_params_t *core_params; ++ ++ /** Core Global registers starting at offset 000h. */ ++ dwc_otg_core_global_regs_t *core_global_regs; ++ ++ /** Device-specific information */ ++ dwc_otg_dev_if_t *dev_if; ++ /** Host-specific information */ ++ dwc_otg_host_if_t *host_if; ++ ++ /** Value from SNPSID register */ ++ uint32_t snpsid; ++ ++ /* ++ * Set to 1 if the core PHY interface bits in USBCFG have been ++ * initialized. ++ */ ++ uint8_t phy_init_done; ++ ++ /* ++ * SRP Success flag, set by srp success interrupt in FS I2C mode ++ */ ++ uint8_t srp_success; ++ uint8_t srp_timer_started; ++ /** Timer for SRP. If it expires before SRP is successful ++ * clear the SRP. */ ++ dwc_timer_t *srp_timer; ++ ++#ifdef DWC_DEV_SRPCAP ++ /* This timer is needed to power on the hibernated host core if SRP is not ++ * initiated on connected SRP capable device for limited period of time ++ */ ++ uint8_t pwron_timer_started; ++ dwc_timer_t *pwron_timer; ++#endif ++ /* Common configuration information */ ++ /** Power and Clock Gating Control Register */ ++ volatile uint32_t *pcgcctl; ++#define DWC_OTG_PCGCCTL_OFFSET 0xE00 ++ ++ /** Push/pop addresses for endpoints or host channels.*/ ++ uint32_t *data_fifo[MAX_EPS_CHANNELS]; ++#define DWC_OTG_DATA_FIFO_OFFSET 0x1000 ++#define DWC_OTG_DATA_FIFO_SIZE 0x1000 ++ ++ /** Total RAM for FIFOs (Bytes) */ ++ uint16_t total_fifo_size; ++ /** Size of Rx FIFO (Bytes) */ ++ uint16_t rx_fifo_size; ++ /** Size of Non-periodic Tx FIFO (Bytes) */ ++ uint16_t nperio_tx_fifo_size; ++ ++ /** 1 if DMA is enabled, 0 otherwise. */ ++ uint8_t dma_enable; ++ ++ /** 1 if DMA descriptor is enabled, 0 otherwise. */ ++ uint8_t dma_desc_enable; ++ ++ /** 1 if PTI Enhancement mode is enabled, 0 otherwise. */ ++ uint8_t pti_enh_enable; ++ ++ /** 1 if MPI Enhancement mode is enabled, 0 otherwise. */ ++ uint8_t multiproc_int_enable; ++ ++ /** 1 if dedicated Tx FIFOs are enabled, 0 otherwise. */ ++ uint8_t en_multiple_tx_fifo; ++ ++ /** Set to 1 if multiple packets of a high-bandwidth transfer is in ++ * process of being queued */ ++ uint8_t queuing_high_bandwidth; ++ ++ /** Hardware Configuration -- stored here for convenience.*/ ++ hwcfg1_data_t hwcfg1; ++ hwcfg2_data_t hwcfg2; ++ hwcfg3_data_t hwcfg3; ++ hwcfg4_data_t hwcfg4; ++ fifosize_data_t hptxfsiz; ++ ++ /** Host and Device Configuration -- stored here for convenience.*/ ++ hcfg_data_t hcfg; ++ dcfg_data_t dcfg; ++ ++ /** The operational State, during transations ++ * (a_host>>a_peripherial and b_device=>b_host) this may not ++ * match the core but allows the software to determine ++ * transitions. ++ */ ++ uint8_t op_state; ++ ++ /** Test mode for PET testing */ ++ uint8_t test_mode; ++ ++ /** ++ * Set to 1 if the HCD needs to be restarted on a session request ++ * interrupt. This is required if no connector ID status change has ++ * occurred since the HCD was last disconnected. ++ */ ++ uint8_t restart_hcd_on_session_req; ++ ++ /** HCD callbacks */ ++ /** A-Device is a_host */ ++#define A_HOST (1) ++ /** A-Device is a_suspend */ ++#define A_SUSPEND (2) ++ /** A-Device is a_peripherial */ ++#define A_PERIPHERAL (3) ++ /** B-Device is operating as a Peripheral. */ ++#define B_PERIPHERAL (4) ++ /** B-Device is operating as a Host. */ ++#define B_HOST (5) ++ ++ /** HCD callbacks */ ++ struct dwc_otg_cil_callbacks *hcd_cb; ++ /** PCD callbacks */ ++ struct dwc_otg_cil_callbacks *pcd_cb; ++ ++ /** Device mode Periodic Tx FIFO Mask */ ++ uint32_t p_tx_msk; ++ /** Device mode Periodic Tx FIFO Mask */ ++ uint32_t tx_msk; ++ ++ /** Workqueue object used for handling several interrupts */ ++ dwc_workq_t *wq_otg; ++ ++ /** Timer object used for handling "Wakeup Detected" Interrupt */ ++ dwc_timer_t *wkp_timer; ++ /** This arrays used for debug purposes for DEV OUT NAK enhancement */ ++ uint32_t start_doeptsiz_val[MAX_EPS_CHANNELS]; ++ ep_xfer_info_t ep_xfer_info[MAX_EPS_CHANNELS]; ++ dwc_timer_t *ep_xfer_timer[MAX_EPS_CHANNELS]; ++#ifdef DEBUG ++ uint32_t start_hcchar_val[MAX_EPS_CHANNELS]; ++ ++ hc_xfer_info_t hc_xfer_info[MAX_EPS_CHANNELS]; ++ dwc_timer_t *hc_xfer_timer[MAX_EPS_CHANNELS]; ++ ++ uint32_t hfnum_7_samples; ++ uint64_t hfnum_7_frrem_accum; ++ uint32_t hfnum_0_samples; ++ uint64_t hfnum_0_frrem_accum; ++ uint32_t hfnum_other_samples; ++ uint64_t hfnum_other_frrem_accum; ++#endif ++ ++#ifdef DWC_UTE_CFI ++ uint16_t pwron_rxfsiz; ++ uint16_t pwron_gnptxfsiz; ++ uint16_t pwron_txfsiz[15]; ++ ++ uint16_t init_rxfsiz; ++ uint16_t init_gnptxfsiz; ++ uint16_t init_txfsiz[15]; ++#endif ++ ++ /** Lx state of device */ ++ dwc_otg_lx_state_e lx_state; ++ ++ /** Saved Core Global registers */ ++ struct dwc_otg_global_regs_backup *gr_backup; ++ /** Saved Host registers */ ++ struct dwc_otg_host_regs_backup *hr_backup; ++ /** Saved Device registers */ ++ struct dwc_otg_dev_regs_backup *dr_backup; ++ ++ /** Power Down Enable */ ++ uint32_t power_down; ++ ++ /** ADP support Enable */ ++ uint32_t adp_enable; ++ ++ /** ADP structure object */ ++ dwc_otg_adp_t adp; ++ ++ /** hibernation/suspend flag */ ++ int hibernation_suspend; ++ ++ /** Device mode extended hibernation flag */ ++ int xhib; ++ ++ /** OTG revision supported */ ++ uint32_t otg_ver; ++ ++ /** OTG status flag used for HNP polling */ ++ uint8_t otg_sts; ++ ++ /** Pointer to either hcd->lock or pcd->lock */ ++ dwc_spinlock_t *lock; ++ ++ /** Start predict NextEP based on Learning Queue if equal 1, ++ * also used as counter of disabled NP IN EP's */ ++ uint8_t start_predict; ++ ++ /** NextEp sequence, including EP0: nextep_seq[] = EP if non-periodic and ++ * active, 0xff otherwise */ ++ uint8_t nextep_seq[MAX_EPS_CHANNELS]; ++ ++ /** Index of fisrt EP in nextep_seq array which should be re-enabled **/ ++ uint8_t first_in_nextep_seq; ++ ++ /** Frame number while entering to ISR - needed for ISOCs **/ ++ uint32_t frame_num; ++ ++ /** Flag to not perform ADP probing if IDSTS event happened */ ++ uint8_t stop_adpprb; ++ ++}; ++ ++#ifdef DEBUG ++/* ++ * This function is called when transfer is timed out. ++ */ ++extern void hc_xfer_timeout(void *ptr); ++#endif ++ ++/* ++ * This function is called when transfer is timed out on endpoint. ++ */ ++extern void ep_xfer_timeout(void *ptr); ++ ++/* ++ * The following functions are functions for works ++ * using during handling some interrupts ++ */ ++extern void w_conn_id_status_change(void *p); ++ ++extern void w_wakeup_detected(void *p); ++ ++/** Saves global register values into system memory. */ ++extern int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if); ++/** Saves device register values into system memory. */ ++extern int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if); ++/** Saves host register values into system memory. */ ++extern int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if); ++/** Restore global register values. */ ++extern int dwc_otg_restore_global_regs(dwc_otg_core_if_t * core_if); ++/** Restore host register values. */ ++extern int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset); ++/** Restore device register values. */ ++extern int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, ++ int rem_wakeup); ++extern int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if); ++extern int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode, ++ int is_host); ++ ++extern int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int restore_mode, int reset); ++extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int rem_wakeup, int reset); ++ ++/* ++ * The following functions support initialization of the CIL driver component ++ * and the DWC_otg controller. ++ */ ++extern void dwc_otg_core_host_init(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_core_dev_init(dwc_otg_core_if_t * _core_if); ++ ++/** @name Device CIL Functions ++ * The following functions support managing the DWC_otg controller in device ++ * mode. ++ */ ++/**@{*/ ++extern void dwc_otg_wakeup(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_read_setup_packet(dwc_otg_core_if_t * _core_if, ++ uint32_t * _dest); ++extern uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_ep0_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep); ++extern void dwc_otg_ep_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep); ++extern void dwc_otg_ep_deactivate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep); ++extern void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * _core_if, ++ dwc_ep_t * _ep); ++extern void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * _core_if, ++ dwc_ep_t * _ep); ++extern void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * _core_if, ++ dwc_ep_t * _ep); ++extern void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * _core_if, ++ dwc_ep_t * _ep); ++extern void dwc_otg_ep_write_packet(dwc_otg_core_if_t * _core_if, ++ dwc_ep_t * _ep, int _dma); ++extern void dwc_otg_ep_set_stall(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep); ++extern void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * _core_if, ++ dwc_ep_t * _ep); ++extern void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * _core_if); ++ ++#ifdef DWC_EN_ISOC ++extern void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * ep); ++extern void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * ep); ++#endif /* DWC_EN_ISOC */ ++/**@}*/ ++ ++/** @name Host CIL Functions ++ * The following functions support managing the DWC_otg controller in host ++ * mode. ++ */ ++/**@{*/ ++extern void dwc_otg_hc_init(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc); ++extern void dwc_otg_hc_halt(dwc_otg_core_if_t * _core_if, ++ dwc_hc_t * _hc, dwc_otg_halt_status_e _halt_status); ++extern void dwc_otg_hc_cleanup(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc); ++extern void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * _core_if, ++ dwc_hc_t * _hc); ++extern int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * _core_if, ++ dwc_hc_t * _hc); ++extern void dwc_otg_hc_do_ping(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc); ++extern void dwc_otg_hc_write_packet(dwc_otg_core_if_t * _core_if, ++ dwc_hc_t * _hc); ++extern void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * _core_if); ++ ++extern void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, ++ dwc_hc_t * hc); ++ ++extern uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if); ++extern int dwc_otg_check_haps_status(dwc_otg_core_if_t * core_if); ++ ++/* Macro used to clear one channel interrupt */ ++#define clear_hc_int(_hc_regs_, _intr_) \ ++do { \ ++ hcint_data_t hcint_clear = {.d32 = 0}; \ ++ hcint_clear.b._intr_ = 1; \ ++ DWC_WRITE_REG32(&(_hc_regs_)->hcint, hcint_clear.d32); \ ++} while (0) ++ ++/* ++ * Macro used to disable one channel interrupt. Channel interrupts are ++ * disabled when the channel is halted or released by the interrupt handler. ++ * There is no need to handle further interrupts of that type until the ++ * channel is re-assigned. In fact, subsequent handling may cause crashes ++ * because the channel structures are cleaned up when the channel is released. ++ */ ++#define disable_hc_int(_hc_regs_, _intr_) \ ++do { \ ++ hcintmsk_data_t hcintmsk = {.d32 = 0}; \ ++ hcintmsk.b._intr_ = 1; \ ++ DWC_MODIFY_REG32(&(_hc_regs_)->hcintmsk, hcintmsk.d32, 0); \ ++} while (0) ++ ++/** ++ * This function Reads HPRT0 in preparation to modify. It keeps the ++ * WC bits 0 so that if they are read as 1, they won't clear when you ++ * write it back ++ */ ++static inline uint32_t dwc_otg_read_hprt0(dwc_otg_core_if_t * _core_if) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = DWC_READ_REG32(_core_if->host_if->hprt0); ++ hprt0.b.prtena = 0; ++ hprt0.b.prtconndet = 0; ++ hprt0.b.prtenchng = 0; ++ hprt0.b.prtovrcurrchng = 0; ++ return hprt0.d32; ++} ++ ++/**@}*/ ++ ++/** @name Common CIL Functions ++ * The following functions support managing the DWC_otg controller in either ++ * device or host mode. ++ */ ++/**@{*/ ++ ++extern void dwc_otg_read_packet(dwc_otg_core_if_t * core_if, ++ uint8_t * dest, uint16_t bytes); ++ ++extern void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * _core_if, const int _num); ++extern void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_core_reset(dwc_otg_core_if_t * _core_if); ++ ++/** ++ * This function returns the Core Interrupt register. ++ */ ++static inline uint32_t dwc_otg_read_core_intr(dwc_otg_core_if_t * core_if) ++{ ++ return (DWC_READ_REG32(&core_if->core_global_regs->gintsts) & ++ DWC_READ_REG32(&core_if->core_global_regs->gintmsk)); ++} ++ ++/** ++ * This function returns the OTG Interrupt register. ++ */ ++static inline uint32_t dwc_otg_read_otg_intr(dwc_otg_core_if_t * core_if) ++{ ++ return (DWC_READ_REG32(&core_if->core_global_regs->gotgint)); ++} ++ ++/** ++ * This function reads the Device All Endpoints Interrupt register and ++ * returns the IN endpoint interrupt bits. ++ */ ++static inline uint32_t dwc_otg_read_dev_all_in_ep_intr(dwc_otg_core_if_t * ++ core_if) ++{ ++ ++ uint32_t v; ++ ++ if (core_if->multiproc_int_enable) { ++ v = DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->deachint) & ++ DWC_READ_REG32(&core_if-> ++ dev_if->dev_global_regs->deachintmsk); ++ } else { ++ v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) & ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk); ++ } ++ return (v & 0xffff); ++} ++ ++/** ++ * This function reads the Device All Endpoints Interrupt register and ++ * returns the OUT endpoint interrupt bits. ++ */ ++static inline uint32_t dwc_otg_read_dev_all_out_ep_intr(dwc_otg_core_if_t * ++ core_if) ++{ ++ uint32_t v; ++ ++ if (core_if->multiproc_int_enable) { ++ v = DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->deachint) & ++ DWC_READ_REG32(&core_if-> ++ dev_if->dev_global_regs->deachintmsk); ++ } else { ++ v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) & ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk); ++ } ++ ++ return ((v & 0xffff0000) >> 16); ++} ++ ++/** ++ * This function returns the Device IN EP Interrupt register ++ */ ++static inline uint32_t dwc_otg_read_dev_in_ep_intr(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * ep) ++{ ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ uint32_t v, msk, emp; ++ ++ if (core_if->multiproc_int_enable) { ++ msk = ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->diepeachintmsk[ep->num]); ++ emp = ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->dtknqr4_fifoemptymsk); ++ msk |= ((emp >> ep->num) & 0x1) << 7; ++ v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk; ++ } else { ++ msk = DWC_READ_REG32(&dev_if->dev_global_regs->diepmsk); ++ emp = ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->dtknqr4_fifoemptymsk); ++ msk |= ((emp >> ep->num) & 0x1) << 7; ++ v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk; ++ } ++ ++ return v; ++} ++ ++/** ++ * This function returns the Device OUT EP Interrupt register ++ */ ++static inline uint32_t dwc_otg_read_dev_out_ep_intr(dwc_otg_core_if_t * ++ _core_if, dwc_ep_t * _ep) ++{ ++ dwc_otg_dev_if_t *dev_if = _core_if->dev_if; ++ uint32_t v; ++ doepmsk_data_t msk = {.d32 = 0 }; ++ ++ if (_core_if->multiproc_int_enable) { ++ msk.d32 = ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->doepeachintmsk[_ep->num]); ++ if (_core_if->pti_enh_enable) { ++ msk.b.pktdrpsts = 1; ++ } ++ v = DWC_READ_REG32(&dev_if-> ++ out_ep_regs[_ep->num]->doepint) & msk.d32; ++ } else { ++ msk.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->doepmsk); ++ if (_core_if->pti_enh_enable) { ++ msk.b.pktdrpsts = 1; ++ } ++ v = DWC_READ_REG32(&dev_if-> ++ out_ep_regs[_ep->num]->doepint) & msk.d32; ++ } ++ return v; ++} ++ ++/** ++ * This function returns the Host All Channel Interrupt register ++ */ ++static inline uint32_t dwc_otg_read_host_all_channels_intr(dwc_otg_core_if_t * ++ _core_if) ++{ ++ return (DWC_READ_REG32(&_core_if->host_if->host_global_regs->haint)); ++} ++ ++static inline uint32_t dwc_otg_read_host_channel_intr(dwc_otg_core_if_t * ++ _core_if, dwc_hc_t * _hc) ++{ ++ return (DWC_READ_REG32 ++ (&_core_if->host_if->hc_regs[_hc->hc_num]->hcint)); ++} ++ ++/** ++ * This function returns the mode of the operation, host or device. ++ * ++ * @return 0 - Device Mode, 1 - Host Mode ++ */ ++static inline uint32_t dwc_otg_mode(dwc_otg_core_if_t * _core_if) ++{ ++ return (DWC_READ_REG32(&_core_if->core_global_regs->gintsts) & 0x1); ++} ++ ++/**@}*/ ++ ++/** ++ * DWC_otg CIL callback structure. This structure allows the HCD and ++ * PCD to register functions used for starting and stopping the PCD ++ * and HCD for role change on for a DRD. ++ */ ++typedef struct dwc_otg_cil_callbacks { ++ /** Start function for role change */ ++ int (*start) (void *_p); ++ /** Stop Function for role change */ ++ int (*stop) (void *_p); ++ /** Disconnect Function for role change */ ++ int (*disconnect) (void *_p); ++ /** Resume/Remote wakeup Function */ ++ int (*resume_wakeup) (void *_p); ++ /** Suspend function */ ++ int (*suspend) (void *_p); ++ /** Session Start (SRP) */ ++ int (*session_start) (void *_p); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ /** Sleep (switch to L0 state) */ ++ int (*sleep) (void *_p); ++#endif ++ /** Pointer passed to start() and stop() */ ++ void *p; ++} dwc_otg_cil_callbacks_t; ++ ++extern void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * _core_if, ++ dwc_otg_cil_callbacks_t * _cb, ++ void *_p); ++extern void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * _core_if, ++ dwc_otg_cil_callbacks_t * _cb, ++ void *_p); ++ ++void dwc_otg_initiate_srp(void * core_if); ++ ++////////////////////////////////////////////////////////////////////// ++/** Start the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_start(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->start) { ++ core_if->hcd_cb->start(core_if->hcd_cb->p); ++ } ++} ++ ++/** Stop the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_stop(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->stop) { ++ core_if->hcd_cb->stop(core_if->hcd_cb->p); ++ } ++} ++ ++/** Disconnect the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_disconnect(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->disconnect) { ++ core_if->hcd_cb->disconnect(core_if->hcd_cb->p); ++ } ++} ++ ++/** Inform the HCD the a New Session has begun. Helper function for ++ * using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_session_start(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->session_start) { ++ core_if->hcd_cb->session_start(core_if->hcd_cb->p); ++ } ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++/** ++ * Inform the HCD about LPM sleep. ++ * Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_sleep(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->sleep) { ++ core_if->hcd_cb->sleep(core_if->hcd_cb->p); ++ } ++} ++#endif ++ ++/** Resume the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_resume(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->resume_wakeup) { ++ core_if->hcd_cb->resume_wakeup(core_if->hcd_cb->p); ++ } ++} ++ ++/** Start the PCD. Helper function for using the PCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_pcd_start(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->start) { ++ core_if->pcd_cb->start(core_if->pcd_cb->p); ++ } ++} ++ ++/** Stop the PCD. Helper function for using the PCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_pcd_stop(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->stop) { ++ core_if->pcd_cb->stop(core_if->pcd_cb->p); ++ } ++} ++ ++/** Suspend the PCD. Helper function for using the PCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_pcd_suspend(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->suspend) { ++ core_if->pcd_cb->suspend(core_if->pcd_cb->p); ++ } ++} ++ ++/** Resume the PCD. Helper function for using the PCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_pcd_resume(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); ++ } ++} ++ ++////////////////////////////////////////////////////////////////////// ++ ++#endif +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_cil_intr.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_cil_intr.c +new file mode 100644 +index 0000000..3f0d01f +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_cil_intr.c +@@ -0,0 +1,1731 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $ ++ * $Revision: #37 $ ++ * $Date: 2013/04/16 $ ++ * $Change: 2207267 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ * The Core Interface Layer provides basic services for accessing and ++ * managing the DWC_otg hardware. These services are used by both the ++ * Host Controller Driver and the Peripheral Controller Driver. ++ * ++ * This file contains the Common Interrupt handlers. ++ */ ++#include "dwc_os.h" ++#include "dwc_otg_regs.h" ++#include "dwc_otg_cil.h" ++#include "dwc_otg_driver.h" ++#include "dwc_otg_pcd.h" ++#include "dwc_otg_hcd.h" ++ ++#ifdef DEBUG ++inline const char *op_state_str(dwc_otg_core_if_t * core_if) ++{ ++ return (core_if->op_state == A_HOST ? "a_host" : ++ (core_if->op_state == A_SUSPEND ? "a_suspend" : ++ (core_if->op_state == A_PERIPHERAL ? "a_peripheral" : ++ (core_if->op_state == B_PERIPHERAL ? "b_peripheral" : ++ (core_if->op_state == B_HOST ? "b_host" : "unknown"))))); ++} ++#endif ++ ++/** This function will log a debug message ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_handle_mode_mismatch_intr(dwc_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ DWC_WARN("Mode Mismatch Interrupt: currently in %s mode\n", ++ dwc_otg_mode(core_if) ? "Host" : "Device"); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.modemismatch = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This function handles the OTG Interrupts. It reads the OTG ++ * Interrupt Register (GOTGINT) to determine what interrupt has ++ * occurred. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gotgint_data_t gotgint; ++ gotgctl_data_t gotgctl; ++ gintmsk_data_t gintmsk; ++ gpwrdn_data_t gpwrdn; ++ ++ gotgint.d32 = DWC_READ_REG32(&global_regs->gotgint); ++ gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); ++ DWC_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32, ++ op_state_str(core_if)); ++ ++ if (gotgint.b.sesenddet) { ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "Session End Detected++ (%s)\n", ++ op_state_str(core_if)); ++ gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); ++ ++ if (core_if->op_state == B_HOST) { ++ if (core_if->adp_enable && DWC_WORKQ_PENDING(core_if->wq_otg)) { ++ ++ /* During ST_B_ADP test after HNP HSOTG tries to go to B_HOST ++ * mode but PET is not expecting fully functional host at that ++ * point and switches off the VBUS expecting immediate ADP probe */ ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_mdelay(20); ++ dwc_otg_adp_probe_start(core_if); ++ goto exit_interrupt; ++ } ++ cil_pcd_start(core_if); ++ core_if->op_state = B_PERIPHERAL; ++ } else { ++ /* If not B_HOST and Device HNP still set. HNP ++ * Did not succeed!*/ ++ if (gotgctl.b.devhnpen) { ++ DWC_DEBUGPL(DBG_ANY, "Session End Detected\n"); ++ __DWC_ERROR("Device Not Connected/Responding!\n"); ++ } ++ ++ /* If Session End Detected the B-Cable has ++ * been disconnected. */ ++ /* Reset PCD and Gadget driver to a ++ * clean state. */ ++ core_if->lx_state = DWC_OTG_L0; ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ ++ if (core_if->otg_ver) { ++ /** PET testing*/ ++ gotgctl.d32 = 0; ++ gotgctl.b.devhnpen = 1; ++ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ if (core_if->test_mode == 6) { ++ DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg, dwc_otg_initiate_srp, ++ core_if, 3000, "initate SRP"); //manukz: old value was 50 ++ core_if->test_mode = 0; ++ } else if (core_if->adp_enable) { ++ if (core_if->power_down == 2) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ } ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_otg_adp_sense_start(core_if); ++ } ++ } ++ } ++exit_interrupt: ++ if (core_if->otg_ver == 0) { ++ gotgctl.d32 = 0; ++ gotgctl.b.devhnpen = 1; ++ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ } ++ } ++ if (gotgint.b.sesreqsucstschng) { ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "Session Reqeust Success Status Change++\n"); ++ gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); ++ if (gotgctl.b.sesreqscs) { ++ ++ if ((core_if->core_params->phy_type == ++ DWC_PHY_TYPE_PARAM_FS) && (core_if->core_params->i2c_enable)) { ++ core_if->srp_success = 1; ++ } else { ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_resume(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ /* Clear Session Request */ ++ gotgctl.d32 = 0; ++ gotgctl.b.sesreq = 1; ++ DWC_MODIFY_REG32(&global_regs->gotgctl, ++ gotgctl.d32, 0); ++ } ++ } ++ } ++ if (gotgint.b.hstnegsucstschng) { ++ /* Print statements during the HNP interrupt handling ++ * can cause it to fail.*/ ++ gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); ++ /* WA for 3.00a- HW is not setting cur_mode, even sometimes ++ * this does not help*/ ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) ++ dwc_udelay(100); ++ if (gotgctl.b.hstnegscs) { ++ if (dwc_otg_is_host_mode(core_if)) { ++ core_if->op_state = B_HOST; ++ /* ++ * Need to disable SOF interrupt immediately. ++ * When switching from device to host, the PCD ++ * interrupt handler won't handle the ++ * interrupt if host mode is already set. The ++ * HCD interrupt handler won't get called if ++ * the HCD state is HALT. This means that the ++ * interrupt does not get handled and Linux ++ * complains loudly. ++ */ ++ gintmsk.d32 = 0; ++ gintmsk.b.sofintr = 1; ++ /* To avoid multiple USB Suspend interrupts during ++ * OTG 2.0 role change */ ++ if (core_if->otg_ver) ++ gintmsk.b.usbsuspend = 1; ++ DWC_MODIFY_REG32(&global_regs->gintmsk, ++ gintmsk.d32, 0); ++ /* Call callback function with spin lock released */ ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ /* ++ * Initialize the Core for Host mode. ++ */ ++ if (core_if->otg_ver) { ++ dwc_mdelay(100); ++ cil_hcd_start(core_if); ++ cil_hcd_session_start(core_if); ++ } else { ++ cil_hcd_start(core_if); ++ } ++ DWC_SPINLOCK(core_if->lock); ++ } ++ } else { ++ gotgctl.d32 = 0; ++ gotgctl.b.hnpreq = 1; ++ gotgctl.b.devhnpen = 1; ++ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ DWC_DEBUGPL(DBG_ANY, "HNP Failed\n"); ++ __DWC_ERROR("Device Not Connected/Responding\n"); ++ } ++ } ++ if (gotgint.b.hstnegdet) { ++ /* The disconnect interrupt is set at the same time as ++ * Host Negotiation Detected. During the mode ++ * switch all interrupts are cleared so the disconnect ++ * interrupt handler will not get executed. ++ */ ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "Host Negotiation Detected++ (%s)\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : ++ "Device")); ++ if (dwc_otg_is_device_mode(core_if)) { ++ DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n", ++ core_if->op_state); ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_hcd_disconnect(core_if); ++ cil_pcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ core_if->op_state = A_PERIPHERAL; ++ } else { ++ /* ++ * Need to disable SOF interrupt immediately. When ++ * switching from device to host, the PCD interrupt ++ * handler won't handle the interrupt if host mode is ++ * already set. The HCD interrupt handler won't get ++ * called if the HCD state is HALT. This means that ++ * the interrupt does not get handled and Linux ++ * complains loudly. ++ */ ++ gintmsk.d32 = 0; ++ gintmsk.b.sofintr = 1; ++ DWC_MODIFY_REG32(&global_regs->gintmsk, gintmsk.d32, 0); ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ cil_hcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ core_if->op_state = A_HOST; ++ } ++ } ++ if (gotgint.b.adevtoutchng) { ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "A-Device Timeout Change++\n"); ++ } ++ if (gotgint.b.debdone) { ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " "Debounce Done++\n"); ++ /* Need to power off VBUS after 10s if OTG2 non-hnp capable host*/ ++ if (core_if->otg_ver && core_if->op_state == A_PERIPHERAL) { ++ DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n"); ++ /* Clear the a_peripheral flag, back to a_host. */ ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ cil_hcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ core_if->op_state = A_HOST; ++ } ++ ++ if(core_if->otg_ver == 1) ++ cil_hcd_session_start(core_if); ++ } ++ ++ /* Clear GOTGINT */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, gotgint.d32); ++ ++ return 1; ++} ++ ++void w_conn_id_status_change(void *p) ++{ ++ dwc_otg_core_if_t *core_if = p; ++ uint32_t count = 0; ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ ++ gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32); ++ DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts); ++ ++ /* B-Device connector (Device Mode) */ ++ if (gotgctl.b.conidsts) { ++ gotgctl_data_t gotgctl_local; ++ /* Wait for switch to device mode. */ ++ while (!dwc_otg_is_device_mode(core_if)) { ++ gotgctl_local.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ DWC_DEBUGPL(DBG_ANY, "Waiting for Peripheral Mode, Mode=%s count = %d gotgctl=%08x\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : ++ "Peripheral"), count, gotgctl_local.d32); ++ dwc_mdelay(1); //vahrama previous value was 100 ++ if(!gotgctl_local.b.conidsts) ++ goto host; ++ if (++count > 10000) ++ break; ++ } ++ DWC_ASSERT(++count < 10000, ++ "Connection id status change timed out"); ++ core_if->op_state = B_PERIPHERAL; ++ if(core_if->otg_ver == 0) ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } else { ++host: ++ /* A-Device connector (Host Mode) */ ++ while (!dwc_otg_is_host_mode(core_if)) { ++ DWC_DEBUGPL(DBG_ANY,"Waiting for Host Mode, Mode=%s\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : ++ "Peripheral")); ++ dwc_mdelay(1); //vahrama previously was 100 ++ if (++count > 10000) ++ break; ++ } ++ DWC_ASSERT(++count < 10000, ++ "Connection id status change timed out"); ++ core_if->op_state = A_HOST; ++ /* ++ * Initialize the Core for Host mode. ++ */ ++ if (core_if->otg_ver) ++ /* To power off the bus in 10s from the beginning ++ * of test while denounce has not come yet */ ++ cil_hcd_session_start(core_if); ++ else ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++} ++ ++/** ++ * This function handles the Connector ID Status Change Interrupt. It ++ * reads the OTG Interrupt Register (GOTCTL) to determine whether this ++ * is a Device to Host Mode transition or a Host Mode to Device ++ * Transition. ++ * ++ * This only occurs when the cable is connected/removed from the PHY ++ * connector. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t * core_if) ++{ ++ ++ /* ++ * Need to disable SOF interrupt immediately. If switching from device ++ * to host, the PCD interrupt handler won't handle the interrupt if ++ * host mode is already set. The HCD interrupt handler won't get ++ * called if the HCD state is HALT. This means that the interrupt does ++ * not get handled and Linux complains loudly. ++ */ ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ gintsts_data_t gintsts = {.d32 = 0 }; ++ ++ gintmsk.b.sofintr = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0); ++ ++ DWC_DEBUGPL(DBG_CIL, ++ " ++Connector ID Status Change Interrupt++ (%s)\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : "Device")); ++ ++ DWC_SPINUNLOCK(core_if->lock); ++ ++ /* Needed to avoit conn_id_status change duplication */ ++ //if (core_if->otg_ver) ++ //dwc_mdelay(50); ++ /* ++ * Need to schedule a work, as there are possible DELAY function calls ++ * Release lock before scheduling workq as it holds spinlock during scheduling ++ */ ++ ++ DWC_WORKQ_SCHEDULE(core_if->wq_otg, w_conn_id_status_change, ++ core_if, "connection id status change"); ++ DWC_SPINLOCK(core_if->lock); ++ ++ /* Set flag and clear interrupt */ ++ gintsts.b.conidstschng = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that a device is initiating the Session ++ * Request Protocol to request the host to turn on bus power so a new ++ * session can begin. The handler responds by turning on bus power. If ++ * the DWC_otg controller is in low power mode, the handler brings the ++ * controller out of low power mode before turning on bus power. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ ++#ifndef DWC_HOST_ONLY ++ DWC_DEBUGPL(DBG_ANY, "++Session Request Interrupt++\n"); ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ DWC_DEBUGPL(DBG_PCD, "SRP: Device mode\n"); ++ gotgctl.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ if (gotgctl.b.sesreqscs) ++ DWC_PRINTF("SRP Success\n"); ++ else ++ DWC_PRINTF("SRP Fail\n"); ++ if (core_if->otg_ver) { ++ gotgctl.d32 = 0 ; ++ gotgctl.b.devhnpen = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, gotgctl.d32, 0); ++ } ++ } else { ++ hprt0_data_t hprt0; ++ DWC_PRINTF("SRP: Host mode\n"); ++ ++ /* Turn on the port power bit. */ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* Start the Connection timer. So a message can be displayed ++ * if connect does not occur within 10 seconds. */ ++ cil_hcd_session_start(core_if); ++ } ++#endif ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.sessreqintr = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++void w_wakeup_detected(void *p) ++{ ++ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) p; ++ /* ++ * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms ++ * so that OPT tests pass with all PHYs). ++ */ ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ DWC_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32); ++ hprt0.b.prtres = 0; /* Resume */ ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ DWC_DEBUGPL(DBG_ANY, "Clear Resume: HPRT0=%0x\n", ++ DWC_READ_REG32(core_if->host_if->hprt0)); ++ ++ cil_hcd_resume(core_if); ++ ++ /** Change to L0 state*/ ++ core_if->lx_state = DWC_OTG_L0; ++} ++ ++/** ++ * This interrupt indicates that the DWC_otg controller has detected a ++ * resume or remote wakeup sequence. If the DWC_otg controller is in ++ * low power mode, the handler must brings the controller out of low ++ * power mode. The controller automatically begins resume ++ * signaling. The handler schedules a time to stop resume signaling. ++ */ ++int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ ++ DWC_DEBUGPL(DBG_ANY, ++ "++Resume and Remote Wakeup Detected Interrupt++\n"); ++ ++ DWC_PRINTF("%s lxstate = %d\n", __func__, core_if->lx_state); ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs-> ++ dsts)); ++ if (core_if->lx_state == DWC_OTG_L2) { ++#ifdef PARTIAL_POWER_DOWN ++ if (core_if->hwcfg4.b.power_optimiz) { ++ pcgcctl_data_t power = {.d32 = 0 }; ++ ++ power.d32 = DWC_READ_REG32(core_if->pcgcctl); ++ DWC_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n", ++ power.d32); ++ ++ power.b.stoppclk = 0; ++ DWC_WRITE_REG32(core_if->pcgcctl, power.d32); ++ ++ power.b.pwrclmp = 0; ++ DWC_WRITE_REG32(core_if->pcgcctl, power.d32); ++ ++ power.b.rstpdwnmodule = 0; ++ DWC_WRITE_REG32(core_if->pcgcctl, power.d32); ++ } ++#endif ++ /* Clear the Remote Wakeup Signaling */ ++ dctl.b.rmtwkupsig = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, dctl.d32, 0); ++ ++ DWC_SPINUNLOCK(core_if->lock); ++ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); ++ } ++ DWC_SPINLOCK(core_if->lock); ++ } else { ++ glpmcfg_data_t lpmcfg; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ ++ lpmcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.hird_thres &= (~(1 << 4)); ++ lpmcfg.b.en_utmi_sleep = 0; ++ ++ /* Clear Enbl_L1Gating bit. */ ++ pcgcctl.b.enbl_sleep_gating = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,0); ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, ++ lpmcfg.d32); ++ } ++ /** Change to L0 state*/ ++ core_if->lx_state = DWC_OTG_L0; ++ } else { ++ if (core_if->lx_state != DWC_OTG_L1) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ ++ /* Restart the Phy Clock */ ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ DWC_TIMER_SCHEDULE(core_if->wkp_timer, 71); ++ } else { ++ /** Change to L0 state*/ ++ core_if->lx_state = DWC_OTG_L0; ++ } ++ } ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.wkupintr = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * Device disconnect. ++ */ ++static int32_t dwc_otg_handle_pwrdn_disconnect_intr(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn_temp = {.d32 = 0 }; ++ gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ DWC_PRINTF("%s called\n", __FUNCTION__); ++ ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ if (gpwrdn_temp.b.idsts) { ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } else { ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * remote wakeup sequence. ++ */ ++static int32_t dwc_otg_handle_pwrdn_wakeup_detected_intr(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ DWC_DEBUGPL(DBG_ANY, ++ "++Powerdown Remote Wakeup Detected Interrupt++\n"); ++ ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (gpwrdn.b.idsts) { // Device Mode ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ dwc_otg_device_hibernation_restore(core_if, 0, 0); ++ } ++ } else { ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ dwc_otg_host_hibernation_restore(core_if, 1, 0); ++ } ++ } ++ return 1; ++} ++ ++static int32_t dwc_otg_handle_pwrdn_idsts_change(dwc_otg_device_t * otg_dev) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn_temp = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if = otg_dev->core_if; ++ ++ DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); ++ gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (core_if->power_down == 2) { ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ DWC_DEBUGPL(DBG_ANY, "Exit from hibernation on ID sts change\n"); ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /*Indicates that we are exiting from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ gpwrdn.d32 = core_if->gr_backup->gpwrdn_local; ++ if (gpwrdn.b.dis_vbus == 1) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ } ++ ++ if (gpwrdn_temp.b.idsts) { ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } else { ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++ } ++ ++ if (core_if->adp_enable) { ++ uint8_t is_host = 0; ++ DWC_SPINUNLOCK(core_if->lock); ++ /* Change the core_if's lock to hcd/pcd lock depend on mode? */ ++#ifndef DWC_HOST_ONLY ++ if (gpwrdn_temp.b.idsts) ++ core_if->lock = otg_dev->pcd->lock; ++#endif ++#ifndef DWC_DEVICE_ONLY ++ if (!gpwrdn_temp.b.idsts) { ++ core_if->lock = otg_dev->hcd->lock; ++ is_host = 1; ++ } ++#endif ++ DWC_DEBUGPL(DBG_ANY, "RESTART ADP\n"); ++ if (core_if->adp.probe_enabled) ++ dwc_otg_adp_probe_stop(core_if); ++ if (core_if->adp.sense_enabled) ++ dwc_otg_adp_sense_stop(core_if); ++ if (core_if->adp.sense_timer_started) ++ DWC_TIMER_CANCEL(core_if->adp.sense_timer); ++ if (core_if->adp.vbuson_timer_started) ++ DWC_TIMER_CANCEL(core_if->adp.vbuson_timer); ++ /* Do not need to reset ADP if we are coming back ++ * to the device mode after HNP. This is needed ++ * not to perform SRP after reverse, just do ADP ++ * probe and compare the RTIM values with the one ++ * before HNP */ ++ if (core_if->op_state != B_HOST) { ++ core_if->adp.probe_timer_values[0] = -1; ++ core_if->adp.probe_timer_values[1] = -1; ++ core_if->adp.probe_counter = 0; ++ core_if->adp.gpwrdn = 0; ++ } ++ core_if->adp.sense_timer_started = 0; ++ core_if->adp.vbuson_timer_started = 0; ++ ++ /* Disable PMU and restart ADP */ ++ gpwrdn_temp.d32 = 0; ++ gpwrdn_temp.b.pmuactv = 1; ++ gpwrdn_temp.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_mdelay(110); ++ dwc_otg_adp_start(core_if, is_host); ++ DWC_SPINLOCK(core_if->lock); ++ } ++ ++ return 1; ++} ++ ++static int32_t dwc_otg_handle_pwrdn_session_change(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ int32_t otg_cap_param = core_if->core_params->otg_cap; ++ DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); ++ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (core_if->power_down == 2) { ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ if ((otg_cap_param != DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE || ++ otg_cap_param != DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) && ++ gpwrdn.b.bsessvld == 0) { ++ /* Save gpwrdn register for further usage if stschng interrupt */ ++ core_if->gr_backup->gpwrdn_local = ++ DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ /*Exit from ISR and wait for stschng interrupt with bsessvld = 1 */ ++ return 1; ++ } ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /*Indicates that we are exiting from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ ++ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE || ++ otg_cap_param == DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) { ++ /* ++ * Initiate SRP after initial ADP probe. ++ */ ++ dwc_otg_initiate_srp(core_if); ++ } ++ } else if (core_if->adp_enable && core_if->op_state != A_HOST){ ++ dwc_otg_adp_probe_stop(core_if); ++ if (DWC_WORKQ_PENDING(core_if->wq_otg)) ++ core_if->stop_adpprb = 1; ++ /* Disable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Device mode. ++ */ ++ core_if->op_state = B_PERIPHERAL; ++ cil_pcd_start(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ } ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * status change either on IDDIG or BSessVld. ++ */ ++static uint32_t dwc_otg_handle_pwrdn_stschng_intr(dwc_otg_device_t * otg_dev) ++{ ++ int retval; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn_temp = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if = otg_dev->core_if; ++ ++ DWC_DEBUGPL(DBG_CIL, "%s called\n", __FUNCTION__); ++ ++ if (core_if->power_down == 2) { ++ if (core_if->hibernation_suspend <= 0) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } else ++ gpwrdn_temp.d32 = core_if->gr_backup->gpwrdn_local; ++ ++ } else { ++ gpwrdn_temp.d32 = core_if->adp.gpwrdn; ++ } ++ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ if (gpwrdn.b.idsts ^ gpwrdn_temp.b.idsts) { ++ retval = dwc_otg_handle_pwrdn_idsts_change(otg_dev); ++ } else if (gpwrdn.b.bsessvld ^ gpwrdn_temp.b.bsessvld) { ++ retval = dwc_otg_handle_pwrdn_session_change(core_if); ++ } ++ ++ return retval; ++} ++ ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * SRP. ++ */ ++static int32_t dwc_otg_handle_pwrdn_srp_intr(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ ++ DWC_PRINTF("%s called\n", __FUNCTION__); ++ ++ if (core_if->power_down == 2) { ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++#ifdef DWC_DEV_SRPCAP ++ if (core_if->pwron_timer_started) { ++ core_if->pwron_timer_started = 0; ++ DWC_TIMER_CANCEL(core_if->pwron_timer); ++ } ++#endif ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Indicates that we are exiting from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Programm Disable VBUS to 0 */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /*Initialize the core as Host */ ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++ /* Do not need to du anything if this is "old" SRP and we are already ++ * in the normal mode of operation */ ++ if(core_if->adp_enable) { ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (!gpwrdn.b.pmuactv) { ++ return 1; ++ } ++ ++ dwc_otg_adp_probe_stop(core_if); ++ /* Disable Interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Host mode. ++ */ ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ /* Start the Connection timer. So a message can be displayed ++ * if connect does not occur within 10 seconds. */ ++ cil_hcd_session_start(core_if); ++ } ++ ++ return 1; ++} ++ ++/** This interrupt indicates that restore command after Hibernation ++ * was completed by the core. */ ++int32_t dwc_otg_handle_restore_done_intr(dwc_otg_core_if_t * core_if) ++{ ++ pcgcctl_data_t pcgcctl; ++ DWC_DEBUGPL(DBG_ANY, "++Restore Done Interrupt++\n"); ++ ++ //TODO De-assert restore signal. 8.a ++ pcgcctl.d32 = DWC_READ_REG32(core_if->pcgcctl); ++ if (pcgcctl.b.restoremode == 1) { ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ /* ++ * If restore mode is Remote Wakeup, ++ * unmask Remote Wakeup interrupt. ++ */ ++ gintmsk.b.wkupintr = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, ++ 0, gintmsk.d32); ++ } ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that a device has been disconnected from ++ * the root port. ++ */ ++int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ ++ DWC_DEBUGPL(DBG_ANY, "++Disconnect Detected Interrupt++ (%s) %s\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"), ++ op_state_str(core_if)); ++ ++/** @todo Consolidate this if statement. */ ++#ifndef DWC_HOST_ONLY ++ if (core_if->op_state == B_HOST) { ++ /* If in device mode Disconnect and stop the HCD, then ++ * start the PCD. */ ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_hcd_disconnect(core_if); ++ cil_pcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ core_if->op_state = B_PERIPHERAL; ++ } else if (dwc_otg_is_device_mode(core_if)) { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gotgctl.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ if (gotgctl.b.hstsethnpen == 1) { ++ /* Do nothing, if HNP in process the OTG ++ * interrupt "Host Negotiation Detected" ++ * interrupt will do the mode switch. ++ */ ++ } else if (gotgctl.b.devhnpen == 0) { ++ /* If in device mode Disconnect and stop the HCD, then ++ * start the PCD. */ ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_hcd_disconnect(core_if); ++ cil_pcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ core_if->op_state = B_PERIPHERAL; ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n"); ++ } ++ } else { ++ if (core_if->op_state == A_HOST) { ++ /* A-Cable still connected but device disconnected. */ ++ cil_hcd_disconnect(core_if); ++ if (core_if->adp_enable) { ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ cil_hcd_stop(core_if); ++ /* Enable Power Down Logic */ ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_otg_adp_probe_start(core_if); ++ ++ /* Power off the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32 ++ (&core_if->core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ } ++ } ++ } ++ } ++#endif ++ /* Change to L3(OFF) state */ ++ core_if->lx_state = DWC_OTG_L3; ++ ++ gintsts.d32 = 0; ++ gintsts.b.disconnect = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that SUSPEND state has been detected on ++ * the USB. ++ * ++ * For HNP the USB Suspend interrupt signals the change from ++ * "a_peripheral" to "a_host". ++ * ++ * When power management is enabled the core will be put in low power ++ * mode. ++ */ ++int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if) ++{ ++ dsts_data_t dsts; ++ gintsts_data_t gintsts; ++ dcfg_data_t dcfg; ++ ++ DWC_DEBUGPL(DBG_ANY, "USB SUSPEND\n"); ++ ++ if ((core_if->otg_ver == 1) && (core_if->op_state == A_PERIPHERAL)) { ++ core_if->lx_state = DWC_OTG_L2; ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.usbsuspend = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++ } ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ /* Check the Device status register to determine if the Suspend ++ * state is active. */ ++ dsts.d32 = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32); ++ DWC_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d " ++ "HWCFG4.power Optimize=%d\n", ++ dsts.b.suspsts, core_if->hwcfg4.b.power_optimiz); ++ ++#ifdef PARTIAL_POWER_DOWN ++/** @todo Add a module parameter for power management. */ ++ ++ if (dsts.b.suspsts && core_if->hwcfg4.b.power_optimiz) { ++ pcgcctl_data_t power = {.d32 = 0 }; ++ DWC_DEBUGPL(DBG_CIL, "suspend\n"); ++ ++ power.b.pwrclmp = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, power.d32); ++ ++ power.b.rstpdwnmodule = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32); ++ ++ power.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32); ++ ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "disconnect?\n"); ++ } ++#endif ++ /* PCD callback for suspend. Release the lock inside of callback function */ ++ cil_pcd_suspend(core_if); ++ if (core_if->power_down == 2) { ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ DWC_DEBUGPL(DBG_ANY,"lx_state = %08x\n",core_if->lx_state); ++ DWC_DEBUGPL(DBG_ANY," device address = %08d\n",dcfg.b.devaddr); ++ ++ if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ ++ /* Change to L2(suspend) state */ ++ core_if->lx_state = DWC_OTG_L2; ++ ++ /* Clear interrupt in gintsts */ ++ gintsts.d32 = 0; ++ gintsts.b.usbsuspend = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, gintsts.d32); ++ DWC_PRINTF("Start of hibernation completed\n"); ++ dwc_otg_save_global_regs(core_if); ++ dwc_otg_save_dev_regs(core_if); ++ ++ gusbcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs-> ++ gusbcfg); ++ if (gusbcfg.b.ulpi_utmi_sel == 1) { ++ /* ULPI interface */ ++ /* Suspend the Phy Clock */ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ dwc_udelay(10); ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } else { ++ /* UTMI+ Interface */ ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ dwc_udelay(10); ++ } ++ ++ /* Set flag to indicate that we are in hibernation */ ++ core_if->hibernation_suspend = 1; ++ /* Enable interrupts from wake up logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Unmask device mode interrupts in GPWRDN */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.rst_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ gpwrdn.b.sts_chngint_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Enable Power Down Clamp */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Switch off VDD */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++ /* Save gpwrdn register for further usage if stschng interrupt */ ++ core_if->gr_backup->gpwrdn_local = ++ DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ DWC_PRINTF("Hibernation completed\n"); ++ ++ return 1; ++ } ++ } else if (core_if->power_down == 3) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ DWC_DEBUGPL(DBG_ANY, "lx_state = %08x\n",core_if->lx_state); ++ DWC_DEBUGPL(DBG_ANY, " device address = %08d\n",dcfg.b.devaddr); ++ ++ if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) { ++ DWC_DEBUGPL(DBG_ANY, "Start entering to extended hibernation\n"); ++ core_if->xhib = 1; ++ ++ /* Clear interrupt in gintsts */ ++ gintsts.d32 = 0; ++ gintsts.b.usbsuspend = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, gintsts.d32); ++ ++ dwc_otg_save_global_regs(core_if); ++ dwc_otg_save_dev_regs(core_if); ++ ++ /* Wait for 10 PHY clocks */ ++ dwc_udelay(10); ++ ++ /* Program GPIO register while entering to xHib */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x1); ++ ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.extnd_hiber_pwrclmp = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.extnd_hiber_switch = 1; ++ core_if->gr_backup->xhib_gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ core_if->gr_backup->xhib_pcgcctl = DWC_READ_REG32(core_if->pcgcctl) | pcgcctl.d32; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ DWC_DEBUGPL(DBG_ANY, "Finished entering to extended hibernation\n"); ++ ++ return 1; ++ } ++ } ++ if ((core_if->otg_ver == 1) && (core_if->core_params->otg_cap == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE)) { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ if (gotgctl.b.devhnpen && core_if->otg_ver == 1){ ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ dwc_mdelay(5); ++ /**@todo Is the gotgctl.devhnpen cleared ++ * by a USB Reset? */ ++ gotgctl.b.devhnpen = 1; ++ gotgctl.b.hnpreq = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, ++ gotgctl.d32); ++ } ++ } ++ } else { ++ if (core_if->op_state == A_PERIPHERAL) { ++ DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n"); ++ /* Clear the a_peripheral flag, back to a_host. */ ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ cil_hcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ core_if->op_state = A_HOST; ++ } ++ } ++ ++ /* Change to L2(suspend) state */ ++ core_if->lx_state = DWC_OTG_L2; ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.usbsuspend = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++static int32_t dwc_otg_handle_xhib_exit_intr(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gahbcfg_data_t gahbcfg = {.d32 = 0 }; ++ ++ dwc_udelay(10); ++ ++ /* Program GPIO register while entering to xHib */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x0); ++ ++ pcgcctl.d32 = core_if->gr_backup->xhib_pcgcctl; ++ pcgcctl.b.extnd_hiber_pwrclmp = 0; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ dwc_udelay(10); ++ ++ gpwrdn.d32 = core_if->gr_backup->xhib_gpwrdn; ++ gpwrdn.b.restore = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ restore_lpm_i2c_regs(core_if); ++ ++ pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14); ++ pcgcctl.b.max_xcvrselect = 1; ++ pcgcctl.b.ess_reg_restored = 0; ++ pcgcctl.b.extnd_hiber_switch = 0; ++ pcgcctl.b.extnd_hiber_pwrclmp = 0; ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ ++ gahbcfg.d32 = core_if->gr_backup->gahbcfg_local; ++ gahbcfg.b.glblintrmsk = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32); ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0x1 << 16); ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, ++ core_if->gr_backup->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, ++ core_if->dr_backup->dcfg); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14); ++ pcgcctl.b.max_xcvrselect = 1; ++ pcgcctl.d32 |= 0x608; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ dwc_udelay(10); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14); ++ pcgcctl.b.max_xcvrselect = 1; ++ pcgcctl.b.ess_reg_restored = 1; ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ pcgcctl.b.rstpdwnmodule = 1; ++ pcgcctl.b.restoremode = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ ++ DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); ++ ++ return 1; ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++/** ++ * This function hadles LPM transaction received interrupt. ++ */ ++static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ gintsts_data_t gintsts; ++ ++ if (!core_if->core_params->lpm_enable) { ++ DWC_PRINTF("Unexpected LPM interrupt\n"); ++ } ++ ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ DWC_PRINTF("LPM config register = 0x%08x\n", lpmcfg.d32); ++ ++ if (dwc_otg_is_host_mode(core_if)) { ++ cil_hcd_sleep(core_if); ++ } else { ++ ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ ++ lpmcfg.b.hird_thres |= (1 << 4); ++ lpmcfg.b.en_utmi_sleep = 1; ++ ++ pcgcctl.b.enbl_sleep_gating = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl,0,pcgcctl.d32); ++ ++ if(dwc_otg_get_param_besl_enable(core_if)) { ++ lpmcfg.b.en_besl = 1; ++ } ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, ++ lpmcfg.d32); ++ } ++ ++ /* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */ ++ dwc_udelay(10); ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ if (lpmcfg.b.prt_sleep_sts) { ++ /* Save the current state */ ++ core_if->lx_state = DWC_OTG_L1; ++ } ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.lpmtranrcvd = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ return 1; ++} ++#endif /* CONFIG_USB_DWC_OTG_LPM */ ++ ++/** ++ * This function returns the Core Interrupt register. ++ */ ++static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if) ++{ ++ gahbcfg_data_t gahbcfg = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ gintmsk_data_t gintmsk; ++ gintmsk_data_t gintmsk_common = {.d32 = 0 }; ++ gintmsk_common.b.wkupintr = 1; ++ gintmsk_common.b.sessreqintr = 1; ++ gintmsk_common.b.conidstschng = 1; ++ gintmsk_common.b.otgintr = 1; ++ gintmsk_common.b.modemismatch = 1; ++ gintmsk_common.b.disconnect = 1; ++ gintmsk_common.b.usbsuspend = 1; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ gintmsk_common.b.lpmtranrcvd = 1; ++#endif ++ gintmsk_common.b.restoredone = 1; ++ /** @todo: The port interrupt occurs while in device ++ * mode. Added code to CIL to clear the interrupt for now! ++ */ ++ gintmsk_common.b.portintr = 1; ++ ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg); ++ ++#ifdef DEBUG ++ /* if any common interrupts set */ ++ if (gintsts.d32 & gintmsk_common.d32) { ++ DWC_DEBUGPL(DBG_ANY, "gintsts=%08x gintmsk=%08x\n", ++ gintsts.d32, gintmsk.d32); ++ } ++#endif ++ if (gahbcfg.b.glblintrmsk) ++ return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32); ++ else ++ return 0; ++ ++} ++ ++/* MACRO for clearing interupt bits in GPWRDN register */ ++#define CLEAR_GPWRDN_INTR(__core_if,__intr) \ ++do { \ ++ gpwrdn_data_t gpwrdn = {.d32=0}; \ ++ gpwrdn.b.__intr = 1; \ ++ DWC_MODIFY_REG32(&__core_if->core_global_regs->gpwrdn, \ ++ 0, gpwrdn.d32); \ ++} while (0) ++ ++/** ++ * Common interrupt handler. ++ * ++ * The common interrupts are those that occur in both Host and Device mode. ++ * This handler handles the following interrupts: ++ * - Mode Mismatch Interrupt ++ * - Disconnect Interrupt ++ * - OTG Interrupt ++ * - Connector ID Status Change Interrupt ++ * - Session Request Interrupt. ++ * - Resume / Remote Wakeup Detected Interrupt. ++ * - LPM Transaction Received Interrupt ++ * - ADP Transaction Received Interrupt ++ * ++ */ ++int32_t dwc_otg_handle_common_intr(void *dev) ++{ ++ int retval = 0; ++ gintsts_data_t gintsts; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ dwc_otg_device_t *otg_dev = dev; ++ dwc_otg_core_if_t *core_if = otg_dev->core_if; ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ if (dwc_otg_check_haps_status(core_if) == -1 ) { ++ DWC_WARN("HAPS is disconnected"); ++ return retval; ++ } ++ ++ if (dwc_otg_is_device_mode(core_if)) ++ core_if->frame_num = dwc_otg_get_frame_number(core_if); ++ ++ if (core_if->lock) ++ DWC_SPINLOCK(core_if->lock); ++ ++ if (core_if->power_down == 3 && core_if->xhib == 1) { ++ DWC_DEBUGPL(DBG_ANY, "Exiting from xHIB state\n"); ++ retval |= dwc_otg_handle_xhib_exit_intr(core_if); ++ core_if->xhib = 2; ++ if (core_if->lock) ++ DWC_SPINUNLOCK(core_if->lock); ++ ++ return retval; ++ } ++ ++ if (core_if->hibernation_suspend <= 0) { ++ gintsts.d32 = dwc_otg_read_common_intr(core_if); ++ ++ if (gintsts.b.modemismatch) { ++ retval |= dwc_otg_handle_mode_mismatch_intr(core_if); ++ } ++ if (gintsts.b.otgintr) { ++ retval |= dwc_otg_handle_otg_intr(core_if); ++ } ++ if (gintsts.b.conidstschng) { ++ retval |= ++ dwc_otg_handle_conn_id_status_change_intr(core_if); ++ } ++ if (gintsts.b.disconnect) { ++ retval |= dwc_otg_handle_disconnect_intr(core_if); ++ } ++ if (gintsts.b.sessreqintr) { ++ retval |= dwc_otg_handle_session_req_intr(core_if); ++ } ++ if (gintsts.b.wkupintr) { ++ retval |= dwc_otg_handle_wakeup_detected_intr(core_if); ++ } ++ if (gintsts.b.usbsuspend) { ++ retval |= dwc_otg_handle_usb_suspend_intr(core_if); ++ } ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ if (gintsts.b.lpmtranrcvd) { ++ retval |= dwc_otg_handle_lpm_intr(core_if); ++ } ++#endif ++ if (gintsts.b.restoredone) { ++ gintsts.d32 = 0; ++ if (core_if->power_down == 2) ++ core_if->hibernation_suspend = -1; ++ else if (core_if->power_down == 3 && core_if->xhib == 2) { ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, 0xFFFFFFFF); ++ ++ DWC_DEBUGPL(DBG_ANY, ++ "RESTORE DONE generated\n"); ++ ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ pcgcctl.b.rstpdwnmodule = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, core_if->gr_backup->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, core_if->dr_backup->dcfg); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, core_if->dr_backup->dctl); ++ dwc_udelay(50); ++ ++ dctl.b.pwronprgdone = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ dwc_udelay(10); ++ ++ dwc_otg_restore_global_regs(core_if); ++ dwc_otg_restore_dev_regs(core_if, 0); ++ ++ dctl.d32 = 0; ++ dctl.b.pwronprgdone = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); ++ dwc_udelay(10); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ ++ /* The core will be in ON STATE */ ++ core_if->lx_state = DWC_OTG_L0; ++ core_if->xhib = 0; ++ ++ DWC_SPINUNLOCK(core_if->lock); ++ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); ++ } ++ DWC_SPINLOCK(core_if->lock); ++ ++ } ++ ++ gintsts.b.restoredone = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32); ++ DWC_PRINTF(" --Restore done interrupt received-- \n"); ++ retval |= 1; ++ } ++ if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) { ++ /* The port interrupt occurs while in device mode with HPRT0 ++ * Port Enable/Disable. ++ */ ++ gintsts.d32 = 0; ++ gintsts.b.portintr = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32); ++ retval |= 1; ++ ++ } ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32); ++ ++ if (gpwrdn.b.disconn_det && gpwrdn.b.disconn_det_msk) { ++ CLEAR_GPWRDN_INTR(core_if, disconn_det); ++ if (gpwrdn.b.linestate == 0) { ++ dwc_otg_handle_pwrdn_disconnect_intr(core_if); ++ } else { ++ DWC_PRINTF("Disconnect detected while linestate is not 0\n"); ++ } ++ ++ retval |= 1; ++ } ++ if (gpwrdn.b.lnstschng && gpwrdn.b.lnstchng_msk) { ++ CLEAR_GPWRDN_INTR(core_if, lnstschng); ++ /* remote wakeup from hibernation */ ++ if (gpwrdn.b.linestate == 2 || gpwrdn.b.linestate == 1) { ++ dwc_otg_handle_pwrdn_wakeup_detected_intr(core_if); ++ } else { ++ DWC_PRINTF("gpwrdn.linestate = %d\n", gpwrdn.b.linestate); ++ } ++ retval |= 1; ++ } ++ if (gpwrdn.b.rst_det && gpwrdn.b.rst_det_msk) { ++ CLEAR_GPWRDN_INTR(core_if, rst_det); ++ if (gpwrdn.b.linestate == 0) { ++ DWC_PRINTF("Reset detected\n"); ++ retval |= dwc_otg_device_hibernation_restore(core_if, 0, 1); ++ } ++ } ++ if (gpwrdn.b.srp_det && gpwrdn.b.srp_det_msk) { ++ CLEAR_GPWRDN_INTR(core_if, srp_det); ++ dwc_otg_handle_pwrdn_srp_intr(core_if); ++ retval |= 1; ++ } ++ } ++ /* Handle ADP interrupt here */ ++ if (gpwrdn.b.adp_int) { ++ CLEAR_GPWRDN_INTR(core_if, adp_int); ++ dwc_otg_adp_handle_intr(core_if); ++ retval |= 1; ++ } ++ if (gpwrdn.b.sts_chngint && gpwrdn.b.sts_chngint_msk) { ++ CLEAR_GPWRDN_INTR(core_if, sts_chngint); ++ dwc_otg_handle_pwrdn_stschng_intr(otg_dev); ++ ++ retval |= 1; ++ } ++ if (gpwrdn.b.srp_det && gpwrdn.b.srp_det_msk) { ++ CLEAR_GPWRDN_INTR(core_if, srp_det); ++ dwc_otg_handle_pwrdn_srp_intr(core_if); ++ retval |= 1; ++ } ++ if (core_if->lock) ++ DWC_SPINUNLOCK(core_if->lock); ++ ++ return retval; ++} +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_core_if.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_core_if.h +new file mode 100644 +index 0000000..c9ab2e5 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_core_if.h +@@ -0,0 +1,743 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $ ++ * $Revision: #15 $ ++ * $Date: 2012/12/10 $ ++ * $Change: 2123206 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++#if !defined(__DWC_CORE_IF_H__) ++#define __DWC_CORE_IF_H__ ++ ++#include "dwc_os.h" ++ ++/** @file ++ * This file defines DWC_OTG Core API ++ */ ++ ++struct dwc_otg_core_if; ++typedef struct dwc_otg_core_if dwc_otg_core_if_t; ++ ++/** Maximum number of Periodic FIFOs */ ++#define MAX_PERIO_FIFOS 15 ++/** Maximum number of Periodic FIFOs */ ++#define MAX_TX_FIFOS 15 ++ ++/** Maximum number of Endpoints/HostChannels */ ++#define MAX_EPS_CHANNELS 16 ++ ++extern dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * _reg_base_addr); ++extern void dwc_otg_core_init(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_cil_remove(dwc_otg_core_if_t * _core_if); ++ ++extern void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * _core_if); ++ ++extern uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if); ++extern uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if); ++ ++extern uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if); ++ ++/** This function should be called on every hardware interrupt. */ ++extern int32_t dwc_otg_handle_common_intr(void *otg_dev); ++ ++/** @name OTG Core Parameters */ ++/** @{ */ ++ ++/** ++ * Specifies the OTG capabilities. The driver will automatically ++ * detect the value for this parameter if none is specified. ++ * 0 - HNP and SRP capable (default) ++ * 1 - SRP Only capable ++ * 2 - No HNP/SRP capable ++ */ ++extern int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val); ++extern int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if); ++#define DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE 0 ++#define DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE 1 ++#define DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE 2 ++#define dwc_param_otg_cap_default DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ++ ++extern int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val); ++extern int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if); ++#define dwc_param_opt_default 1 ++ ++/** ++ * Specifies whether to use slave or DMA mode for accessing the data ++ * FIFOs. The driver will automatically detect the value for this ++ * parameter if none is specified. ++ * 0 - Slave ++ * 1 - DMA (default, if available) ++ */ ++extern int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if); ++#define dwc_param_dma_enable_default 1 ++ ++/** ++ * When DMA mode is enabled specifies whether to use ++ * address DMA or DMA Descritor mode for accessing the data ++ * FIFOs in device mode. The driver will automatically detect ++ * the value for this parameter if none is specified. ++ * 0 - address DMA ++ * 1 - DMA Descriptor(default, if available) ++ */ ++extern int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if); ++#define dwc_param_dma_desc_enable_default 1 ++ ++/** The DMA Burst size (applicable only for External DMA ++ * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32) ++ */ ++extern int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if); ++#define dwc_param_dma_burst_size_default 32 ++ ++/** ++ * Specifies the maximum speed of operation in host and device mode. ++ * The actual speed depends on the speed of the attached device and ++ * the value of phy_type. The actual speed depends on the speed of the ++ * attached device. ++ * 0 - High Speed (default) ++ * 1 - Full Speed ++ */ ++extern int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val); ++extern int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if); ++#define dwc_param_speed_default 0 ++#define DWC_SPEED_PARAM_HIGH 0 ++#define DWC_SPEED_PARAM_FULL 1 ++ ++/** Specifies whether low power mode is supported when attached ++ * to a Full Speed or Low Speed device in host mode. ++ * 0 - Don't support low power mode (default) ++ * 1 - Support low power mode ++ */ ++extern int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t * ++ core_if, int32_t val); ++extern int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t ++ * core_if); ++#define dwc_param_host_support_fs_ls_low_power_default 0 ++ ++/** Specifies the PHY clock rate in low power mode when connected to a ++ * Low Speed device in host mode. This parameter is applicable only if ++ * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS ++ * then defaults to 6 MHZ otherwise 48 MHZ. ++ * ++ * 0 - 48 MHz ++ * 1 - 6 MHz ++ */ ++extern int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * ++ core_if, int32_t val); ++extern int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * ++ core_if); ++#define dwc_param_host_ls_low_power_phy_clk_default 0 ++#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0 ++#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1 ++ ++/** ++ * 0 - Use cC FIFO size parameters ++ * 1 - Allow dynamic FIFO sizing (default) ++ */ ++extern int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t * ++ core_if); ++#define dwc_param_enable_dynamic_fifo_default 1 ++ ++/** Total number of 4-byte words in the data FIFO memory. This ++ * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic ++ * Tx FIFOs. ++ * 32 to 32768 (default 8192) ++ * Note: The total FIFO memory depth in the FPGA configuration is 8192. ++ */ ++extern int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if); ++#define dwc_param_data_fifo_size_default 8192 ++ ++/** Number of 4-byte words in the Rx FIFO in device mode when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1064) ++ */ ++extern int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if); ++#define dwc_param_dev_rx_fifo_size_default 1064 ++ ++/** Number of 4-byte words in the non-periodic Tx FIFO in device mode ++ * when dynamic FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++extern int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * ++ core_if, int32_t val); ++extern int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * ++ core_if); ++#define dwc_param_dev_nperio_tx_fifo_size_default 1024 ++ ++/** Number of 4-byte words in each of the periodic Tx FIFOs in device ++ * mode when dynamic FIFO sizing is enabled. ++ * 4 to 768 (default 256) ++ */ ++extern int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if, ++ int32_t val, int fifo_num); ++extern int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * ++ core_if, int fifo_num); ++#define dwc_param_dev_perio_tx_fifo_size_default 256 ++ ++/** Number of 4-byte words in the Rx FIFO in host mode when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++extern int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if); ++#define dwc_param_host_rx_fifo_size_default 1024 ++ ++/** Number of 4-byte words in the non-periodic Tx FIFO in host mode ++ * when Dynamic FIFO sizing is enabled in the core. ++ * 16 to 32768 (default 1024) ++ */ ++extern int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * ++ core_if, int32_t val); ++extern int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * ++ core_if); ++#define dwc_param_host_nperio_tx_fifo_size_default 1024 ++ ++/** Number of 4-byte words in the host periodic Tx FIFO when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++extern int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * ++ core_if, int32_t val); ++extern int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * ++ core_if); ++#define dwc_param_host_perio_tx_fifo_size_default 1024 ++ ++/** The maximum transfer size supported in bytes. ++ * 2047 to 65,535 (default 65,535) ++ */ ++extern int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if); ++#define dwc_param_max_transfer_size_default 65535 ++ ++/** The maximum number of packets in a transfer. ++ * 15 to 511 (default 511) ++ */ ++extern int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if); ++#define dwc_param_max_packet_count_default 511 ++ ++/** The number of host channel registers to use. ++ * 1 to 16 (default 12) ++ * Note: The FPGA configuration supports a maximum of 12 host channels. ++ */ ++extern int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if); ++#define dwc_param_host_channels_default 12 ++ ++/** The number of endpoints in addition to EP0 available for device ++ * mode operations. ++ * 1 to 15 (default 6 IN and OUT) ++ * Note: The FPGA configuration supports a maximum of 6 IN and OUT ++ * endpoints in addition to EP0. ++ */ ++extern int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if); ++#define dwc_param_dev_endpoints_default 6 ++ ++/** ++ * Specifies the type of PHY interface to use. By default, the driver ++ * will automatically detect the phy_type. ++ * ++ * 0 - Full Speed PHY ++ * 1 - UTMI+ (default) ++ * 2 - ULPI ++ */ ++extern int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val); ++extern int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if); ++#define DWC_PHY_TYPE_PARAM_FS 0 ++#define DWC_PHY_TYPE_PARAM_UTMI 1 ++#define DWC_PHY_TYPE_PARAM_ULPI 2 ++#define dwc_param_phy_type_default DWC_PHY_TYPE_PARAM_UTMI ++ ++/** ++ * Specifies the UTMI+ Data Width. This parameter is ++ * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI ++ * PHY_TYPE, this parameter indicates the data width between ++ * the MAC and the ULPI Wrapper.) Also, this parameter is ++ * applicable only if the OTG_HSPHY_WIDTH cC parameter was set ++ * to "8 and 16 bits", meaning that the core has been ++ * configured to work at either data path width. ++ * ++ * 8 or 16 bits (default 16) ++ */ ++extern int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if); ++#define dwc_param_phy_utmi_width_default 16 ++ ++/** ++ * Specifies whether the ULPI operates at double or single ++ * data rate. This parameter is only applicable if PHY_TYPE is ++ * ULPI. ++ * ++ * 0 - single data rate ULPI interface with 8 bit wide data ++ * bus (default) ++ * 1 - double data rate ULPI interface with 4 bit wide data ++ * bus ++ */ ++extern int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if); ++#define dwc_param_phy_ulpi_ddr_default 0 ++ ++/** ++ * Specifies whether to use the internal or external supply to ++ * drive the vbus with a ULPI phy. ++ */ ++extern int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if); ++#define DWC_PHY_ULPI_INTERNAL_VBUS 0 ++#define DWC_PHY_ULPI_EXTERNAL_VBUS 1 ++#define dwc_param_phy_ulpi_ext_vbus_default DWC_PHY_ULPI_INTERNAL_VBUS ++ ++/** ++ * Specifies whether to use the I2Cinterface for full speed PHY. This ++ * parameter is only applicable if PHY_TYPE is FS. ++ * 0 - No (default) ++ * 1 - Yes ++ */ ++extern int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if); ++#define dwc_param_i2c_enable_default 0 ++ ++extern int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if); ++#define dwc_param_ulpi_fs_ls_default 0 ++ ++extern int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val); ++extern int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if); ++#define dwc_param_ts_dline_default 0 ++ ++/** ++ * Specifies whether dedicated transmit FIFOs are ++ * enabled for non periodic IN endpoints in device mode ++ * 0 - No ++ * 1 - Yes ++ */ ++extern int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t * ++ core_if); ++#define dwc_param_en_multiple_tx_fifo_default 1 ++ ++/** Number of 4-byte words in each of the Tx FIFOs in device ++ * mode when dynamic FIFO sizing is enabled. ++ * 4 to 768 (default 256) ++ */ ++extern int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if, ++ int fifo_num, int32_t val); ++extern int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if, ++ int fifo_num); ++#define dwc_param_dev_tx_fifo_size_default 256 ++ ++/** Thresholding enable flag- ++ * bit 0 - enable non-ISO Tx thresholding ++ * bit 1 - enable ISO Tx thresholding ++ * bit 2 - enable Rx thresholding ++ */ ++extern int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val); ++extern int32_t dwc_otg_get_thr_ctl(dwc_otg_core_if_t * core_if, int fifo_num); ++#define dwc_param_thr_ctl_default 0 ++ ++/** Thresholding length for Tx ++ * FIFOs in 32 bit DWORDs ++ */ ++extern int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_tx_thr_length(dwc_otg_core_if_t * core_if); ++#define dwc_param_tx_thr_length_default 64 ++ ++/** Thresholding length for Rx ++ * FIFOs in 32 bit DWORDs ++ */ ++extern int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_rx_thr_length(dwc_otg_core_if_t * core_if); ++#define dwc_param_rx_thr_length_default 64 ++ ++/** ++ * Specifies whether LPM (Link Power Management) support is enabled ++ */ ++extern int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if); ++#define dwc_param_lpm_enable_default 1 ++ ++/** ++ * Specifies whether LPM Errata (Link Power Management) support is enabled ++ */ ++extern int dwc_otg_set_param_besl_enable(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_besl_enable(dwc_otg_core_if_t * core_if); ++#define dwc_param_besl_enable_default 0 ++ ++/** ++ * Specifies baseline_besl default value ++ */ ++extern int dwc_otg_set_param_baseline_besl(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_baseline_besl(dwc_otg_core_if_t * core_if); ++#define dwc_param_baseline_besl_default 0 ++ ++/** ++ * Specifies deep_besl default value ++ */ ++extern int dwc_otg_set_param_deep_besl(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_deep_besl(dwc_otg_core_if_t * core_if); ++#define dwc_param_deep_besl_default 15 ++ ++/** ++ * Specifies whether PTI enhancement is enabled ++ */ ++extern int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if); ++#define dwc_param_pti_enable_default 0 ++ ++/** ++ * Specifies whether MPI enhancement is enabled ++ */ ++extern int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if); ++#define dwc_param_mpi_enable_default 0 ++ ++/** ++ * Specifies whether ADP capability is enabled ++ */ ++extern int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if); ++#define dwc_param_adp_enable_default 0 ++ ++/** ++ * Specifies whether IC_USB capability is enabled ++ */ ++ ++extern int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if); ++#define dwc_param_ic_usb_cap_default 0 ++ ++extern int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if); ++#define dwc_param_ahb_thr_ratio_default 0 ++ ++extern int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if); ++#define dwc_param_power_down_default 0 ++ ++extern int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if); ++#define dwc_param_reload_ctl_default 0 ++ ++extern int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if); ++#define dwc_param_dev_out_nak_default 0 ++ ++extern int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if); ++#define dwc_param_cont_on_bna_default 0 ++ ++extern int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if); ++#define dwc_param_ahb_single_default 0 ++ ++extern int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val); ++extern int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if); ++#define dwc_param_otg_ver_default 0 ++ ++/** @} */ ++ ++/** @name Access to registers and bit-fields */ ++ ++/** ++ * Dump core registers and SPRAM ++ */ ++extern void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_dump_spram(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_dump_host_registers(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_dump_global_registers(dwc_otg_core_if_t * _core_if); ++ ++/** ++ * Get host negotiation status. ++ */ ++extern uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Get srp status ++ */ ++extern uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Set hnpreq bit in the GOTGCTL register. ++ */ ++extern void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get Content of SNPSID register. ++ */ ++extern uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Get current mode. ++ * Returns 0 if in device mode, and 1 if in host mode. ++ */ ++extern uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Get value of hnpcapable field in the GUSBCFG register ++ */ ++extern uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of hnpcapable field in the GUSBCFG register ++ */ ++extern void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of srpcapable field in the GUSBCFG register ++ */ ++extern uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of srpcapable field in the GUSBCFG register ++ */ ++extern void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of devspeed field in the DCFG register ++ */ ++extern uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of devspeed field in the DCFG register ++ */ ++extern void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get the value of busconnected field from the HPRT0 register ++ */ ++extern uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Gets the device enumeration Speed. ++ */ ++extern uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Get value of prtpwr field from the HPRT0 register ++ */ ++extern uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Get value of flag indicating core state - hibernated or not ++ */ ++extern uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Set value of prtpwr field from the HPRT0 register ++ */ ++extern void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of prtsusp field from the HPRT0 regsiter ++ */ ++extern uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of prtpwr field from the HPRT0 register ++ */ ++extern void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of ModeChTimEn field from the HCFG regsiter ++ */ ++extern uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of ModeChTimEn field from the HCFG regsiter ++ */ ++extern void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of Fram Interval field from the HFIR regsiter ++ */ ++extern uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of Frame Interval field from the HFIR regsiter ++ */ ++extern void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Set value of prtres field from the HPRT0 register ++ *FIXME Remove? ++ */ ++extern void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of rmtwkupsig bit in DCTL register ++ */ ++extern uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Get value of besl_reject bit in DCTL register ++ */ ++ ++extern uint32_t dwc_otg_get_beslreject(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Set value of besl_reject bit in DCTL register ++ */ ++ ++extern void dwc_otg_set_beslreject(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of prt_sleep_sts field from the GLPMCFG register ++ */ ++extern uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Get value of rem_wkup_en field from the GLPMCFG register ++ */ ++extern uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Get value of appl_resp field from the GLPMCFG register ++ */ ++extern uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of appl_resp field from the GLPMCFG register ++ */ ++extern void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of hsic_connect field from the GLPMCFG register ++ */ ++extern uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of hsic_connect field from the GLPMCFG register ++ */ ++extern void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of inv_sel_hsic field from the GLPMCFG register. ++ */ ++extern uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of inv_sel_hsic field from the GLPMFG register. ++ */ ++extern void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val); ++/** ++ * Set value of hird_thresh field from the GLPMFG register. ++ */ ++extern void dwc_otg_set_hirdthresh(dwc_otg_core_if_t * core_if, uint32_t val); ++/** ++ * Get value of hird_thresh field from the GLPMFG register. ++ */ ++extern uint32_t dwc_otg_get_hirdthresh(dwc_otg_core_if_t * core_if); ++ ++ ++/* ++ * Some functions for accessing registers ++ */ ++ ++/** ++ * GOTGCTL register ++ */ ++extern uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * GUSBCFG register ++ */ ++extern uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * GRXFSIZ register ++ */ ++extern uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * GNPTXFSIZ register ++ */ ++extern uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++extern uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * GGPIO register ++ */ ++extern uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * GUID register ++ */ ++extern uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * HPRT0 register ++ */ ++extern uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * GHPTXFSIZE ++ */ ++extern uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if); ++ ++/** @} */ ++ ++#endif /* __DWC_CORE_IF_H__ */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_dbg.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_dbg.h +new file mode 100644 +index 0000000..32c7d10 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_dbg.h +@@ -0,0 +1,113 @@ ++/* ========================================================================== ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 __DWC_OTG_DBG_H__ ++#define __DWC_OTG_DBG_H__ ++ ++/** @file ++ * This file defines debug levels. ++ * Debugging support vanishes in non-debug builds. ++ */ ++ ++/** ++ * The Debug Level bit-mask variable. ++ */ ++extern uint32_t g_dbg_lvl; ++/** ++ * Set the Debug Level variable. ++ */ ++static inline uint32_t SET_DEBUG_LEVEL(const uint32_t new) ++{ ++ uint32_t old = g_dbg_lvl; ++ g_dbg_lvl = new; ++ return old; ++} ++ ++/** When debug level has the DBG_CIL bit set, display CIL Debug messages. */ ++#define DBG_CIL (0x2) ++/** When debug level has the DBG_CILV bit set, display CIL Verbose debug ++ * messages */ ++#define DBG_CILV (0x20) ++/** When debug level has the DBG_PCD bit set, display PCD (Device) debug ++ * messages */ ++#define DBG_PCD (0x4) ++/** When debug level has the DBG_PCDV set, display PCD (Device) Verbose debug ++ * messages */ ++#define DBG_PCDV (0x40) ++/** When debug level has the DBG_HCD bit set, display Host debug messages */ ++#define DBG_HCD (0x8) ++/** When debug level has the DBG_HCDV bit set, display Verbose Host debug ++ * messages */ ++#define DBG_HCDV (0x80) ++/** When debug level has the DBG_HCD_URB bit set, display enqueued URBs in host ++ * mode. */ ++#define DBG_HCD_URB (0x800) ++ ++/** When debug level has any bit set, display debug messages */ ++#define DBG_ANY (0xFF) ++ ++/** All debug messages off */ ++#define DBG_OFF 0 ++ ++/** Prefix string for DWC_DEBUG print macros. */ ++#define USB_DWC "DWC_otg: " ++ ++/** ++ * Print a debug message when the Global debug level variable contains ++ * the bit defined in lvl. ++ * ++ * @param[in] lvl - Debug level, use one of the DBG_ constants above. ++ * @param[in] x - like printf ++ * ++ * Example:

++ * ++ * DWC_DEBUGPL( DBG_ANY, "%s(%p)\n", __func__, _reg_base_addr); ++ * ++ *
++ * results in:
++ * ++ * usb-DWC_otg: dwc_otg_cil_init(ca867000) ++ * ++ */ ++#ifdef DEBUG ++ ++# define DWC_DEBUGPL(lvl, x...) do{ if ((lvl)&g_dbg_lvl)__DWC_DEBUG(USB_DWC x ); }while(0) ++# define DWC_DEBUGP(x...) DWC_DEBUGPL(DBG_ANY, x ) ++ ++# define CHK_DEBUG_LEVEL(level) ((level) & g_dbg_lvl) ++ ++#else ++ ++# define DWC_DEBUGPL(lvl, x...) do{}while(0) ++# define DWC_DEBUGP(x...) ++ ++# define CHK_DEBUG_LEVEL(level) (0) ++ ++#endif /*DEBUG*/ ++#endif +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_driver.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_driver.c +new file mode 100644 +index 0000000..2ca6dcc +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_driver.c +@@ -0,0 +1,802 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $ ++ * $Revision: #96 $ ++ * $Date: 2013/05/20 $ ++ * $Change: 2234037 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++/** @file ++ * The dwc_otg_driver module provides the initialization and cleanup entry ++ * points for the DWC_otg driver. This module will be dynamically installed ++ * after Linux is booted using the insmod command. When the module is ++ * installed, the dwc_otg_driver_init function is called. When the module is ++ * removed (using rmmod), the dwc_otg_driver_cleanup function is called. ++ * ++ * This module also defines a data structure for the dwc_otg_driver, which is ++ * used in conjunction with the standard ARM lm_device structure. These ++ * structures allow the OTG driver to comply with the standard Linux driver ++ * model in which devices and drivers are registered with a bus driver. This ++ * has the benefit that Linux can expose attributes of the driver and device ++ * in its special sysfs file system. Users can then read or write files in ++ * this file system to perform diagnostics on the driver components or the ++ * device. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dwc_otg_os_dep.h" ++#include "dwc_os.h" ++#include "dwc_otg_dbg.h" ++#include "dwc_otg_driver.h" ++#include "dwc_otg_attr.h" ++#include "dwc_otg_core_if.h" ++#include "dwc_otg_pcd_if.h" ++#include "dwc_otg_hcd_if.h" ++ ++ ++#define DWC_DRIVER_VERSION "3.00a 10-AUG-2012" ++ ++static const char driver_name[] = "hiudc"; ++ ++extern int pcd_init( struct platform_device *_dev , int irqnum); ++extern int hcd_init( struct platform_device *_dev ); ++extern int pcd_remove( struct platform_device *_dev ); ++extern void hcd_remove( struct platform_device *_dev ); ++extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host); ++ ++/******************************************************************************/ ++ ++/* Encapsulate the module parameter settings */ ++ ++struct dwc_otg_driver_module_params { ++ int32_t opt; ++ int32_t otg_cap; ++ int32_t dma_enable; ++ int32_t dma_desc_enable; ++ int32_t dma_burst_size; ++ int32_t speed; ++ int32_t host_support_fs_ls_low_power; ++ int32_t host_ls_low_power_phy_clk; ++ int32_t enable_dynamic_fifo; ++ int32_t data_fifo_size; ++ int32_t dev_rx_fifo_size; ++ int32_t dev_nperio_tx_fifo_size; ++ uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS]; ++ int32_t host_rx_fifo_size; ++ int32_t host_nperio_tx_fifo_size; ++ int32_t host_perio_tx_fifo_size; ++ int32_t max_transfer_size; ++ int32_t max_packet_count; ++ int32_t host_channels; ++ int32_t dev_endpoints; ++ int32_t phy_type; ++ int32_t phy_utmi_width; ++ int32_t phy_ulpi_ddr; ++ int32_t phy_ulpi_ext_vbus; ++ int32_t i2c_enable; ++ int32_t ulpi_fs_ls; ++ int32_t ts_dline; ++ int32_t en_multiple_tx_fifo; ++ uint32_t dev_tx_fifo_size[MAX_TX_FIFOS]; ++ uint32_t thr_ctl; ++ uint32_t tx_thr_length; ++ uint32_t rx_thr_length; ++ int32_t pti_enable; ++ int32_t mpi_enable; ++ int32_t lpm_enable; ++ int32_t besl_enable; ++ int32_t baseline_besl; ++ int32_t deep_besl; ++ int32_t ic_usb_cap; ++ int32_t ahb_thr_ratio; ++ int32_t power_down; ++ int32_t reload_ctl; ++ int32_t dev_out_nak; ++ int32_t cont_on_bna; ++ int32_t ahb_single; ++ int32_t otg_ver; ++ int32_t adp_enable; ++}; ++/******************************************************************************/ ++ ++static struct dwc_otg_driver_module_params dwc_otg_module_params = { ++ .opt = -1, ++ .otg_cap = 2, /*non-hnp/srp-capable*/ ++ .dma_enable = 1, /* enable */ ++ .dma_desc_enable = 1, ++ .dma_burst_size = -1, ++ .speed = -1,/*high-speed*/ ++ .host_support_fs_ls_low_power = -1, /* lowpower mode isn't supported */ ++ .host_ls_low_power_phy_clk = -1, ++ .enable_dynamic_fifo = -1, /* use coreconsultant fifo size */ ++ .data_fifo_size = -1, ++ .dev_rx_fifo_size = -1, ++ .dev_nperio_tx_fifo_size = -1, ++ .dev_perio_tx_fifo_size = { ++ /* dev_perio_tx_fifo_size_1 */ ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1 ++ /* 15 */ ++ }, ++ .host_rx_fifo_size = -1, ++ .host_nperio_tx_fifo_size = -1, ++ .host_perio_tx_fifo_size = -1, ++ .max_transfer_size = -1, ++ .max_packet_count = -1, ++ .host_channels = -1, ++ .dev_endpoints = -1, ++ .phy_type = -1,/*utmi+*/ ++ .phy_utmi_width = 8, ++ .phy_ulpi_ddr = -1, ++ .phy_ulpi_ext_vbus = -1, ++ .i2c_enable = -1, ++ .ulpi_fs_ls = -1, ++ .ts_dline = -1, ++ .en_multiple_tx_fifo = -1, ++ .dev_tx_fifo_size = { ++ /* dev_tx_fifo_size */ ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1 ++ /* 15 */ ++ }, ++ .thr_ctl = -1, ++ .tx_thr_length = -1, ++ .rx_thr_length = -1, ++ .pti_enable = -1, ++ .mpi_enable = -1, ++ .lpm_enable = -1, ++ .besl_enable = -1, ++ .baseline_besl = -1, ++ .deep_besl = -1, ++ .ic_usb_cap = -1, ++ .ahb_thr_ratio = -1, ++ .power_down = -1, ++ .reload_ctl = -1, ++ .dev_out_nak = -1, ++ .cont_on_bna = -1, ++ .ahb_single = -1, ++ .otg_ver = -1, ++ .adp_enable = -1, ++}; ++/******************************************************************************/ ++ ++/** ++ * This function is called during module intialization ++ * to pass module parameters to the DWC_OTG CORE. ++ */ ++static int set_parameters(dwc_otg_core_if_t * core_if) ++{ ++ int retval = 0; ++ int i; ++ ++ if (dwc_otg_module_params.otg_cap != -1) { ++ retval += ++ dwc_otg_set_param_otg_cap(core_if, ++ dwc_otg_module_params.otg_cap); ++ } ++ if (dwc_otg_module_params.dma_enable != -1) { ++ retval += ++ dwc_otg_set_param_dma_enable(core_if, ++ dwc_otg_module_params. ++ dma_enable); ++ } ++ if (dwc_otg_module_params.dma_desc_enable != -1) { ++ retval += ++ dwc_otg_set_param_dma_desc_enable(core_if, ++ dwc_otg_module_params. ++ dma_desc_enable); ++ } ++ if (dwc_otg_module_params.opt != -1) { ++ retval += ++ dwc_otg_set_param_opt(core_if, dwc_otg_module_params.opt); ++ } ++ if (dwc_otg_module_params.dma_burst_size != -1) { ++ retval += ++ dwc_otg_set_param_dma_burst_size(core_if, ++ dwc_otg_module_params. ++ dma_burst_size); ++ } ++ if (dwc_otg_module_params.host_support_fs_ls_low_power != -1) { ++ retval += ++ dwc_otg_set_param_host_support_fs_ls_low_power(core_if, ++ dwc_otg_module_params. ++ host_support_fs_ls_low_power); ++ } ++ if (dwc_otg_module_params.enable_dynamic_fifo != -1) { ++ retval += ++ dwc_otg_set_param_enable_dynamic_fifo(core_if, ++ dwc_otg_module_params. ++ enable_dynamic_fifo); ++ } ++ if (dwc_otg_module_params.data_fifo_size != -1) { ++ retval += ++ dwc_otg_set_param_data_fifo_size(core_if, ++ dwc_otg_module_params. ++ data_fifo_size); ++ } ++ if (dwc_otg_module_params.dev_rx_fifo_size != -1) { ++ retval += ++ dwc_otg_set_param_dev_rx_fifo_size(core_if, ++ dwc_otg_module_params. ++ dev_rx_fifo_size); ++ } ++ if (dwc_otg_module_params.dev_nperio_tx_fifo_size != -1) { ++ retval += ++ dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if, ++ dwc_otg_module_params. ++ dev_nperio_tx_fifo_size); ++ } ++ if (dwc_otg_module_params.host_rx_fifo_size != -1) { ++ retval += ++ dwc_otg_set_param_host_rx_fifo_size(core_if, ++ dwc_otg_module_params.host_rx_fifo_size); ++ } ++ if (dwc_otg_module_params.host_nperio_tx_fifo_size != -1) { ++ retval += ++ dwc_otg_set_param_host_nperio_tx_fifo_size(core_if, ++ dwc_otg_module_params. ++ host_nperio_tx_fifo_size); ++ } ++ if (dwc_otg_module_params.host_perio_tx_fifo_size != -1) { ++ retval += ++ dwc_otg_set_param_host_perio_tx_fifo_size(core_if, ++ dwc_otg_module_params. ++ host_perio_tx_fifo_size); ++ } ++ if (dwc_otg_module_params.max_transfer_size != -1) { ++ retval += ++ dwc_otg_set_param_max_transfer_size(core_if, ++ dwc_otg_module_params. ++ max_transfer_size); ++ } ++ if (dwc_otg_module_params.max_packet_count != -1) { ++ retval += ++ dwc_otg_set_param_max_packet_count(core_if, ++ dwc_otg_module_params. ++ max_packet_count); ++ } ++ if (dwc_otg_module_params.host_channels != -1) { ++ retval += ++ dwc_otg_set_param_host_channels(core_if, ++ dwc_otg_module_params. ++ host_channels); ++ } ++ if (dwc_otg_module_params.dev_endpoints != -1) { ++ retval += ++ dwc_otg_set_param_dev_endpoints(core_if, ++ dwc_otg_module_params. ++ dev_endpoints); ++ } ++ if (dwc_otg_module_params.phy_type != -1) { ++ retval += ++ dwc_otg_set_param_phy_type(core_if, ++ dwc_otg_module_params.phy_type); ++ } ++ if (dwc_otg_module_params.speed != -1) { ++ retval += ++ dwc_otg_set_param_speed(core_if, ++ dwc_otg_module_params.speed); ++ } ++ if (dwc_otg_module_params.host_ls_low_power_phy_clk != -1) { ++ retval += ++ dwc_otg_set_param_host_ls_low_power_phy_clk(core_if, ++ dwc_otg_module_params. ++ host_ls_low_power_phy_clk); ++ } ++ if (dwc_otg_module_params.phy_ulpi_ddr != -1) { ++ retval += ++ dwc_otg_set_param_phy_ulpi_ddr(core_if, ++ dwc_otg_module_params. ++ phy_ulpi_ddr); ++ } ++ if (dwc_otg_module_params.phy_ulpi_ext_vbus != -1) { ++ retval += ++ dwc_otg_set_param_phy_ulpi_ext_vbus(core_if, ++ dwc_otg_module_params. ++ phy_ulpi_ext_vbus); ++ } ++ if (dwc_otg_module_params.phy_utmi_width != -1) { ++ retval += ++ dwc_otg_set_param_phy_utmi_width(core_if, ++ dwc_otg_module_params. ++ phy_utmi_width); ++ } ++ if (dwc_otg_module_params.ulpi_fs_ls != -1) { ++ retval += ++ dwc_otg_set_param_ulpi_fs_ls(core_if, ++ dwc_otg_module_params.ulpi_fs_ls); ++ } ++ if (dwc_otg_module_params.ts_dline != -1) { ++ retval += ++ dwc_otg_set_param_ts_dline(core_if, ++ dwc_otg_module_params.ts_dline); ++ } ++ if (dwc_otg_module_params.i2c_enable != -1) { ++ retval += ++ dwc_otg_set_param_i2c_enable(core_if, ++ dwc_otg_module_params. ++ i2c_enable); ++ } ++ if (dwc_otg_module_params.en_multiple_tx_fifo != -1) { ++ retval += ++ dwc_otg_set_param_en_multiple_tx_fifo(core_if, ++ dwc_otg_module_params. ++ en_multiple_tx_fifo); ++ } ++ for (i = 0; i < 15; i++) { ++ if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] != -1) { ++ retval += ++ dwc_otg_set_param_dev_perio_tx_fifo_size(core_if, ++ dwc_otg_module_params. ++ dev_perio_tx_fifo_size ++ [i], i); ++ } ++ } ++ ++ for (i = 0; i < 15; i++) { ++ if (dwc_otg_module_params.dev_tx_fifo_size[i] != -1) { ++ retval += dwc_otg_set_param_dev_tx_fifo_size(core_if, ++ dwc_otg_module_params. ++ dev_tx_fifo_size ++ [i], i); ++ } ++ } ++ if (dwc_otg_module_params.thr_ctl != -1) { ++ retval += ++ dwc_otg_set_param_thr_ctl(core_if, ++ dwc_otg_module_params.thr_ctl); ++ } ++ if (dwc_otg_module_params.mpi_enable != -1) { ++ retval += ++ dwc_otg_set_param_mpi_enable(core_if, ++ dwc_otg_module_params. ++ mpi_enable); ++ } ++ if (dwc_otg_module_params.pti_enable != -1) { ++ retval += ++ dwc_otg_set_param_pti_enable(core_if, ++ dwc_otg_module_params. ++ pti_enable); ++ } ++ if (dwc_otg_module_params.lpm_enable != -1) { ++ retval += ++ dwc_otg_set_param_lpm_enable(core_if, ++ dwc_otg_module_params. ++ lpm_enable); ++ } ++ if (dwc_otg_module_params.besl_enable != -1) { ++ retval += ++ dwc_otg_set_param_besl_enable(core_if, ++ dwc_otg_module_params. ++ besl_enable); ++ } ++ if (dwc_otg_module_params.baseline_besl != -1) { ++ retval += ++ dwc_otg_set_param_baseline_besl(core_if, ++ dwc_otg_module_params. ++ baseline_besl); ++ } ++ if (dwc_otg_module_params.deep_besl != -1) { ++ retval += ++ dwc_otg_set_param_deep_besl(core_if, ++ dwc_otg_module_params. ++ deep_besl); ++ } ++ if (dwc_otg_module_params.ic_usb_cap != -1) { ++ retval += ++ dwc_otg_set_param_ic_usb_cap(core_if, ++ dwc_otg_module_params. ++ ic_usb_cap); ++ } ++ if (dwc_otg_module_params.tx_thr_length != -1) { ++ retval += ++ dwc_otg_set_param_tx_thr_length(core_if, ++ dwc_otg_module_params.tx_thr_length); ++ } ++ if (dwc_otg_module_params.rx_thr_length != -1) { ++ retval += ++ dwc_otg_set_param_rx_thr_length(core_if, ++ dwc_otg_module_params. ++ rx_thr_length); ++ } ++ if (dwc_otg_module_params.ahb_thr_ratio != -1) { ++ retval += ++ dwc_otg_set_param_ahb_thr_ratio(core_if, ++ dwc_otg_module_params.ahb_thr_ratio); ++ } ++ if (dwc_otg_module_params.power_down != -1) { ++ retval += ++ dwc_otg_set_param_power_down(core_if, ++ dwc_otg_module_params.power_down); ++ } ++ if (dwc_otg_module_params.reload_ctl != -1) { ++ retval += ++ dwc_otg_set_param_reload_ctl(core_if, ++ dwc_otg_module_params.reload_ctl); ++ } ++ ++ if (dwc_otg_module_params.dev_out_nak != -1) { ++ retval += ++ dwc_otg_set_param_dev_out_nak(core_if, ++ dwc_otg_module_params.dev_out_nak); ++ } ++ ++ if (dwc_otg_module_params.cont_on_bna != -1) { ++ retval += ++ dwc_otg_set_param_cont_on_bna(core_if, ++ dwc_otg_module_params.cont_on_bna); ++ } ++ ++ if (dwc_otg_module_params.ahb_single != -1) { ++ retval += ++ dwc_otg_set_param_ahb_single(core_if, ++ dwc_otg_module_params.ahb_single); ++ } ++ ++ if (dwc_otg_module_params.otg_ver != -1) { ++ retval += ++ dwc_otg_set_param_otg_ver(core_if, ++ dwc_otg_module_params.otg_ver); ++ } ++ if (dwc_otg_module_params.adp_enable != -1) { ++ retval += ++ dwc_otg_set_param_adp_enable(core_if, ++ dwc_otg_module_params. ++ adp_enable); ++ } ++ return retval; ++} ++/******************************************************************************/ ++ ++/** ++ * This function is the top level interrupt handler for the Common ++ * (Device and host modes) interrupts. ++ */ ++static irqreturn_t dwc_otg_common_irq(int irq, void *dev) ++{ ++ int32_t retval = IRQ_NONE; ++ ++ retval = dwc_otg_handle_common_intr(dev); ++ ++ return IRQ_RETVAL(retval); ++} ++/******************************************************************************/ ++ ++static int hisi_udc_remove( struct platform_device *_dev) ++{ ++ ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); ++ ++ DWC_DEBUGPL(DBG_ANY, "%s(%p)\n", __func__, _dev); ++ ++ if (!otg_dev) { ++ /* Memory allocation for the dwc_otg_device failed. */ ++ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__); ++ return -1; ++ } ++ ++ if (otg_dev->pcd) { ++ pcd_remove(_dev); ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->pcd NULL!\n", __func__); ++ return -1; ++ } ++ ++ /* ++ * Free the IRQ ++ */ ++ if (otg_dev->common_irq_installed) { ++ free_irq(_dev->resource[1].start, otg_dev); ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__); ++ return -1; ++ } ++ ++ if (otg_dev->core_if) { ++ dwc_otg_cil_remove(otg_dev->core_if); ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->core_if NULL!\n", __func__); ++ return -1; ++ } ++ ++ /* ++ * Return the memory. ++ */ ++ if (otg_dev->os_dep.base) { ++ iounmap(otg_dev->os_dep.base); ++ } ++ DWC_FREE(otg_dev); ++ ++ clk_disable_unprepare(otg_dev->clk); ++ /* ++ * Clear the drvdata pointer. ++ */ ++ platform_set_drvdata(_dev, NULL); ++ ++ return 0; ++ ++} ++/******************************************************************************/ ++ ++static int hisi_udc_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ dwc_otg_device_t *dwc_otg_device; ++ int irq; ++ int ret; ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(&pdev->dev, "no irq provided"); ++ return irq; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "no memory resource provided"); ++ return -ENXIO; ++ } ++ ++ dwc_otg_device = DWC_ALLOC(sizeof(dwc_otg_device_t)); ++ ++ if (!dwc_otg_device) { ++ dev_err(&pdev->dev, "kmalloc of dwc_otg_device failed\n"); ++ return -ENOMEM; ++ } ++ ++ memset(dwc_otg_device, 0, sizeof(*dwc_otg_device)); ++ dwc_otg_device->os_dep.reg_offset = 0xFFFFFFFF; ++ ++ /* ++ * Map the DWC_otg Core memory into virtual address space. ++ */ ++ dwc_otg_device->os_dep.res_start = res->start; ++ dwc_otg_device->os_dep.base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(dwc_otg_device->os_dep.base)) { ++ DWC_FREE(dwc_otg_device); ++ return -ENOMEM; ++ } ++ ++ dev_dbg(&pdev->dev, "base=0x%08x\n",(unsigned)dwc_otg_device->os_dep.base); ++ ++ /* ++ * Initialize driver data to point to the global DWC_otg ++ * Device structure. ++ */ ++ platform_set_drvdata(pdev, dwc_otg_device); ++ ++ ++ dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->os_dep.base); ++ if (!dwc_otg_device->core_if) { ++ dev_err(&pdev->dev, "CIL initialization failed!\n"); ++ ret = -ENOMEM; ++ goto fail; ++ ++ } ++ ++ /* ++ * Attempt to ensure this device is really a DWC_otg Controller. ++ * Read and verify the SNPSID register contents. The value should be ++ * 0x45F42XXX or 0x45F42XXX, which corresponds to either "OT2" or "OTG3", ++ * as in "OTG version 2.XX" or "OTG version 3.XX". ++ */ ++ ++ if (((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F542000) && ++ ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) { ++ dev_err(&pdev->dev, "Bad value for SNPSID: 0x%08x\n", ++ dwc_otg_get_gsnpsid(dwc_otg_device->core_if)); ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ /* ++ * Validate parameter values. ++ */ ++ if (set_parameters(dwc_otg_device->core_if)) { ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ ++ /* ++ * Disable the global interrupt until all the interrupt ++ * handlers are installed. ++ */ ++ dwc_otg_disable_global_interrupts(dwc_otg_device->core_if); ++ ++ ++ /* ++ * Install the interrupt handler for the common interrupts before ++ * enabling common interrupts in core_init below. ++ */ ++ DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n", ++ pdev->resource[1].start); ++ ret = request_irq(irq, dwc_otg_common_irq, ++ IRQF_SHARED | IRQ_LEVEL, "dwc_otg", ++ dwc_otg_device); ++ if (ret) { ++ dev_err(&pdev->dev,"request of irq%d failed\n",irq); ++ ret = -EBUSY; ++ goto fail; ++ } else { ++ dwc_otg_device->common_irq_installed = 1; ++ } ++ ++ ++ /* ++ * Initialize the DWC_otg core. ++ */ ++ dwc_otg_core_init(dwc_otg_device->core_if); ++ ++ /* ++ * Initialize the PCD ++ */ ++ ret = pcd_init(pdev, irq); ++ if (ret != 0) { ++ dev_err(&pdev->dev,"pcd_init failed\n"); ++ dwc_otg_device->pcd = NULL; ++ goto fail; ++ } ++ ++ ++ /* ++ * Enable the global interrupt after all the interrupt ++ * handlers are installed if there is no ADP support else ++ * perform initial actions required for Internal ADP logic. ++ */ ++ if (!dwc_otg_get_param_adp_enable(dwc_otg_device->core_if)) ++ dwc_otg_enable_global_interrupts(dwc_otg_device->core_if); ++ else ++ dwc_otg_adp_start(dwc_otg_device->core_if, ++ dwc_otg_is_host_mode(dwc_otg_device->core_if)); ++ ++ return 0; ++ ++fail: ++ hisi_udc_remove(pdev); ++ return ret; ++} ++/******************************************************************************/ ++ ++#ifdef CONFIG_PM ++static int hisi_udc_suspend(struct device *dev) ++{ ++ dwc_otg_device_t *dwc_otg_device = dev_get_drvdata(dev); ++ int rc = 0; ++ ++ dwc_otg_disable_global_interrupts(dwc_otg_device->core_if); ++ clk_disable_unprepare(dwc_otg_device->clk); ++ ++ return rc; ++} ++/******************************************************************************/ ++ ++static int hisi_udc_resume(struct device *dev) ++{ ++ dwc_otg_device_t *dwc_otg_device = dev_get_drvdata(dev); ++ ++ clk_prepare_enable(dwc_otg_device->clk); ++ dwc_otg_core_init(dwc_otg_device->core_if); ++ dwc_otg_enable_global_interrupts(dwc_otg_device->core_if); ++ return 0; ++} ++#else ++#define hisi_udc_suspend NULL; ++#define hisi_udc_resume NULL; ++#endif ++/******************************************************************************/ ++ ++static const struct dev_pm_ops hisi_udc_pmops = { ++ .suspend = hisi_udc_suspend, ++ .resume = hisi_udc_resume, ++#if defined(CONFIG_PM_HIBERNATE) || defined(CONFIG_HISI_SNAPSHOT_BOOT) ++ .freeze = hisi_udc_suspend, ++ .thaw = hisi_udc_resume, ++ .poweroff = hisi_udc_suspend, ++ .restore = hisi_udc_resume, ++#endif ++}; ++ ++static const struct of_device_id hisi_udc_ids[] = { ++ { .compatible = "hiudc", }, ++ { /* null */ } ++}; ++MODULE_DEVICE_TABLE(of, hisi_udc_ids); ++ ++static struct platform_driver hisi_udc_pltfrm_driver = { ++ .probe = hisi_udc_probe, ++ .remove = hisi_udc_remove, ++ .driver = { ++ .name = (char *)driver_name, ++ .owner = THIS_MODULE, ++ .of_match_table = hisi_udc_ids, ++ .pm = &hisi_udc_pmops, ++ }, ++}; ++/******************************************************************************/ ++ ++static int __init hisi_udc_module_init(void) ++{ ++ int ret; ++ ++ printk(KERN_INFO "%s: version %s\n", driver_name, ++ DWC_DRIVER_VERSION); ++ ++ ret = platform_driver_register(&hisi_udc_pltfrm_driver); ++ ++ return ret; ++} ++module_init(hisi_udc_module_init); ++/******************************************************************************/ ++ ++static void __exit hisi_udc_module_exit (void) ++{ ++ ++ platform_driver_unregister(&hisi_udc_pltfrm_driver); ++ ++ printk(KERN_INFO "%s module removed\n", driver_name); ++} ++module_exit(hisi_udc_module_exit); ++ ++MODULE_AUTHOR("Hisilicon"); ++MODULE_DESCRIPTION("Hisilcon USB Device Controller driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_driver.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_driver.h +new file mode 100644 +index 0000000..63df919 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_driver.h +@@ -0,0 +1,89 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $ ++ * $Revision: #19 $ ++ * $Date: 2010/11/15 $ ++ * $Change: 1627671 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 __DWC_OTG_DRIVER_H__ ++#define __DWC_OTG_DRIVER_H__ ++ ++/** @file ++ * This file contains the interface to the Linux driver. ++ */ ++#include "dwc_otg_os_dep.h" ++#include "dwc_otg_core_if.h" ++#include ++ ++/* Type declarations */ ++struct dwc_otg_pcd; ++struct dwc_otg_hcd; ++ ++/** ++ * This structure is a wrapper that encapsulates the driver components used to ++ * manage a single DWC_otg controller. ++ */ ++typedef struct dwc_otg_device { ++ /** Structure containing OS-dependent stuff. KEEP THIS STRUCT AT THE ++ * VERY BEGINNING OF THE DEVICE STRUCT. OSes such as FreeBSD and NetBSD ++ * require this. */ ++ struct os_dependent os_dep; ++ ++ /** Pointer to the core interface structure. */ ++ dwc_otg_core_if_t *core_if; ++ ++ /** Pointer to the PCD structure. */ ++ struct dwc_otg_pcd *pcd; ++ ++ /** Pointer to the HCD structure. */ ++ struct dwc_otg_hcd *hcd; ++ ++ struct clk *clk; ++ ++ /** Flag to indicate whether the common IRQ handler is installed. */ ++ uint8_t common_irq_installed; ++ ++} dwc_otg_device_t; ++ ++/*We must clear S3C24XX_EINTPEND external interrupt register ++ * because after clearing in this register trigerred IRQ from ++ * H/W core in kernel interrupt can be occured again before OTG ++ * handlers clear all IRQ sources of Core registers because of ++ * timing latencies and Low Level IRQ Type. ++ */ ++#ifdef CONFIG_MACH_IPMATE ++#define S3C2410X_CLEAR_EINTPEND() \ ++do { \ ++ __raw_writel(1UL << 11,S3C24XX_EINTPEND); \ ++} while (0) ++#else ++#define S3C2410X_CLEAR_EINTPEND() do { } while (0) ++#endif ++ ++#endif +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd.c +new file mode 100644 +index 0000000..3402e12 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd.c +@@ -0,0 +1,3331 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $ ++ * $Revision: #110 $ ++ * $Date: 2013/05/19 $ ++ * $Change: 2234022 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_DEVICE_ONLY ++ ++/** @file ++ * This file implements HCD Core. All code in this file is portable and doesn't ++ * use any OS specific functions. ++ * Interface provided by HCD Core is defined in ++ * header file. ++ */ ++ ++#include "dwc_otg_hcd.h" ++#include "dwc_otg_regs.h" ++ ++dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void) ++{ ++ return DWC_ALLOC(sizeof(dwc_otg_hcd_t)); ++} ++ ++/** ++ * Connection timeout function. An OTG host is required to display a ++ * message if the device does not connect within 10 seconds. ++ */ ++void dwc_otg_hcd_connect_timeout(void *ptr) ++{ ++ dwc_otg_hcd_t *hcd; ++ gpwrdn_data_t gpwrdn; ++ DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, ptr); ++ DWC_PRINTF("Connect Timeout\n"); ++ __DWC_ERROR("Device Not Connected/Responding\n"); ++ /** Remove buspower after 10s */ ++ hcd = ptr; ++ if (hcd->core_if->otg_ver) ++ dwc_otg_set_prtpower(hcd->core_if, 0); ++ if (hcd->core_if->adp_enable && !hcd->core_if->adp.probe_enabled) { ++ cil_hcd_disconnect(hcd->core_if); ++ gpwrdn.d32 = 0; ++ /* Enable Power Down Logic */ ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ ++ /* Unmask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ ++ dwc_mdelay(220); ++ dwc_otg_adp_probe_start(hcd->core_if); ++ } ++} ++ ++#ifdef DEBUG ++static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ if (qh->channel != NULL) { ++ dwc_hc_t *hc = qh->channel; ++ dwc_list_link_t *item; ++ dwc_otg_qh_t *qh_item; ++ int num_channels = hcd->core_if->core_params->host_channels; ++ int i; ++ ++ dwc_otg_hc_regs_t *hc_regs; ++ hcchar_data_t hcchar; ++ hcsplt_data_t hcsplt; ++ hctsiz_data_t hctsiz; ++ uint32_t hcdma; ++ ++ hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num]; ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt); ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ hcdma = DWC_READ_REG32(&hc_regs->hcdma); ++ ++ DWC_PRINTF(" Assigned to channel %p:\n", hc); ++ DWC_PRINTF(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, ++ hcsplt.d32); ++ DWC_PRINTF(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, ++ hcdma); ++ DWC_PRINTF(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n", ++ hc->dev_addr, hc->ep_num, hc->ep_is_in); ++ DWC_PRINTF(" ep_type: %d\n", hc->ep_type); ++ DWC_PRINTF(" max_packet: %d\n", hc->max_packet); ++ DWC_PRINTF(" data_pid_start: %d\n", hc->data_pid_start); ++ DWC_PRINTF(" xfer_started: %d\n", hc->xfer_started); ++ DWC_PRINTF(" halt_status: %d\n", hc->halt_status); ++ DWC_PRINTF(" xfer_buff: %p\n", hc->xfer_buff); ++ DWC_PRINTF(" xfer_len: %d\n", hc->xfer_len); ++ DWC_PRINTF(" qh: %p\n", hc->qh); ++ DWC_PRINTF(" NP inactive sched:\n"); ++ DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_inactive) { ++ qh_item = ++ DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry); ++ DWC_PRINTF(" %p\n", qh_item); ++ } ++ DWC_PRINTF(" NP active sched:\n"); ++ DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_active) { ++ qh_item = ++ DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry); ++ DWC_PRINTF(" %p\n", qh_item); ++ } ++ DWC_PRINTF(" Channels: \n"); ++ for (i = 0; i < num_channels; i++) { ++ dwc_hc_t *hc = hcd->hc_ptr_array[i]; ++ DWC_PRINTF(" %2d: %p\n", i, hc); ++ } ++ } ++} ++#endif /* DEBUG */ ++ ++/** ++ * Work queue function for starting the HCD when A-Cable is connected. ++ * The hcd_start() must be called in a process context. ++ */ ++static void hcd_start_func(void *_vp) ++{ ++ dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) _vp; ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, hcd); ++ if (hcd) { ++ hcd->fops->start(hcd); ++ } ++} ++ ++static void del_xfer_timers(dwc_otg_hcd_t * hcd) ++{ ++#ifdef DEBUG ++ int i; ++ int num_channels = hcd->core_if->core_params->host_channels; ++ for (i = 0; i < num_channels; i++) { ++ DWC_TIMER_CANCEL(hcd->core_if->hc_xfer_timer[i]); ++ } ++#endif ++} ++ ++static void del_timers(dwc_otg_hcd_t * hcd) ++{ ++ del_xfer_timers(hcd); ++ DWC_TIMER_CANCEL(hcd->conn_timer); ++} ++ ++/** ++ * Processes all the URBs in a single list of QHs. Completes them with ++ * -ETIMEDOUT and frees the QTD. ++ */ ++static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list) ++{ ++ dwc_list_link_t *qh_item; ++ dwc_otg_qh_t *qh; ++ dwc_otg_qtd_t *qtd, *qtd_tmp; ++ ++ DWC_LIST_FOREACH(qh_item, qh_list) { ++ qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry); ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, ++ &qh->qtd_list, qtd_list_entry) { ++ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); ++ if (qtd->urb != NULL) { ++ if(!qtd->urb->priv) { ++ DWC_ERROR("urb->priv is NULL !!!!\n"); ++ return; ++ } ++ if(!hcd->fops) ++ DWC_ERROR("hcd->fops is NULL !!!!!\n"); ++ if(!hcd->fops->complete) ++ DWC_ERROR("fops->complete is NULL !!!!\n"); ++ hcd->fops->complete(hcd, qtd->urb->priv, ++ qtd->urb, -DWC_E_TIMEOUT); ++ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ } ++ ++ } ++ } ++} ++ ++/** ++ * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic ++ * and periodic schedules. The QTD associated with each URB is removed from ++ * the schedule and freed. This function may be called when a disconnect is ++ * detected or when the HCD is being stopped. ++ */ ++static void kill_all_urbs(dwc_otg_hcd_t * hcd) ++{ ++ kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive); ++ kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued); ++} ++ ++/** ++ * Start the connection timer. An OTG host is required to display a ++ * message if the device does not connect within 10 seconds. The ++ * timer is deleted if a port connect interrupt occurs before the ++ * timer expires. ++ */ ++static void dwc_otg_hcd_start_connect_timer(dwc_otg_hcd_t * hcd) ++{ ++ DWC_TIMER_SCHEDULE(hcd->conn_timer, 10000 /* 10 secs */ ); ++} ++ ++/** ++ * HCD Callback function for disconnect of the HCD. ++ * ++ * @param p void pointer to the struct usb_hcd ++ */ ++static int32_t dwc_otg_hcd_session_start_cb(void *p) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd; ++ DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p); ++ dwc_otg_hcd = p; ++ dwc_otg_hcd_start_connect_timer(dwc_otg_hcd); ++ return 1; ++} ++ ++/** ++ * HCD Callback function for starting the HCD when A-Cable is ++ * connected. ++ * ++ * @param p void pointer to the struct usb_hcd ++ */ ++static int32_t dwc_otg_hcd_start_cb(void *p) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = p; ++ dwc_otg_core_if_t *core_if; ++ hprt0_data_t hprt0; ++ uint32_t timeout = 50; ++ ++ core_if = dwc_otg_hcd->core_if; ++ /**@todo vahrama: Check the timeout value for OTG 2.0 */ ++ if (core_if->otg_ver) ++ timeout = 25; ++ if (core_if->op_state == B_HOST) { ++ /* ++ * Reset the port. During a HNP mode switch the reset ++ * needs to occur within 1ms and have a duration of at ++ * least 50ms. ++ */ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtrst = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ if (core_if->otg_ver) { ++ dwc_mdelay(60); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtrst = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } ++ } ++ DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg, ++ hcd_start_func, dwc_otg_hcd, timeout, ++ "start hcd"); ++ ++ return 1; ++} ++ ++/** ++ * HCD Callback function for disconnect of the HCD. ++ * ++ * @param p void pointer to the struct usb_hcd ++ */ ++static int32_t dwc_otg_hcd_disconnect_cb(void *p) ++{ ++ gintsts_data_t intr; ++ dwc_otg_hcd_t *dwc_otg_hcd = p; ++ ++ /* ++ * Set status flags for the hub driver. ++ */ ++ dwc_otg_hcd->flags.b.port_connect_status_change = 1; ++ dwc_otg_hcd->flags.b.port_connect_status = 0; ++ ++ /* ++ * Shutdown any transfers in process by clearing the Tx FIFO Empty ++ * interrupt mask and status bits and disabling subsequent host ++ * channel interrupts. ++ */ ++ intr.d32 = 0; ++ intr.b.nptxfempty = 1; ++ intr.b.ptxfempty = 1; ++ intr.b.hcintr = 1; ++ DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, ++ intr.d32, 0); ++ DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintsts, ++ intr.d32, 0); ++ ++ /* ++ * Turn off the vbus power only if the core has transitioned to device ++ * mode. If still in host mode, need to keep power on to detect a ++ * reconnection. ++ */ ++ if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) { ++ if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) { ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ DWC_PRINTF("Disconnect: PortPower off\n"); ++ hprt0.b.prtpwr = 0; ++ DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, ++ hprt0.d32); ++ } ++ /** Delete timers if become device */ ++ del_timers(dwc_otg_hcd); ++ dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if); ++ } ++ ++ /* Respond with an error status to all URBs in the schedule. */ ++ kill_all_urbs(dwc_otg_hcd); ++ ++ if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) { ++ /* Clean up any host channels that were in use. */ ++ int num_channels; ++ int i; ++ dwc_hc_t *channel; ++ dwc_otg_hc_regs_t *hc_regs; ++ hcchar_data_t hcchar; ++ ++ if (dwc_otg_hcd->core_if->otg_ver == 1) ++ del_xfer_timers(dwc_otg_hcd); ++ else ++ del_timers(dwc_otg_hcd); ++ ++ num_channels = dwc_otg_hcd->core_if->core_params->host_channels; ++ ++ if (!dwc_otg_hcd->core_if->dma_enable) { ++ /* Flush out any channel requests in slave mode. */ ++ for (i = 0; i < num_channels; i++) { ++ channel = dwc_otg_hcd->hc_ptr_array[i]; ++ if (DWC_CIRCLEQ_EMPTY_ENTRY ++ (channel, hc_list_entry)) { ++ hc_regs = ++ dwc_otg_hcd->core_if-> ++ host_if->hc_regs[i]; ++ hcchar.d32 = ++ DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chen = 0; ++ hcchar.b.chdis = 1; ++ hcchar.b.epdir = 0; ++ DWC_WRITE_REG32 ++ (&hc_regs->hcchar, ++ hcchar.d32); ++ } ++ } ++ } ++ } ++ ++ for (i = 0; i < num_channels; i++) { ++ channel = dwc_otg_hcd->hc_ptr_array[i]; ++ if (DWC_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) { ++ hc_regs = ++ dwc_otg_hcd->core_if->host_if->hc_regs[i]; ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ /* Halt the channel. */ ++ hcchar.b.chdis = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, ++ hcchar.d32); ++ } ++ ++ dwc_otg_hc_cleanup(dwc_otg_hcd->core_if, ++ channel); ++ DWC_CIRCLEQ_INSERT_TAIL ++ (&dwc_otg_hcd->free_hc_list, channel, ++ hc_list_entry); ++ /* ++ * Added for Descriptor DMA to prevent channel double cleanup ++ * in release_channel_ddma(). Which called from ep_disable ++ * when device disconnect. ++ */ ++ channel->qh = NULL; ++ } ++ } ++ } ++ ++ if (dwc_otg_hcd->fops->disconnect) { ++ dwc_otg_hcd->fops->disconnect(dwc_otg_hcd); ++ } ++ ++ return 1; ++} ++ ++/** ++ * HCD Callback function for stopping the HCD. ++ * ++ * @param p void pointer to the struct usb_hcd ++ */ ++static int32_t dwc_otg_hcd_stop_cb(void *p) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = p; ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p); ++ dwc_otg_hcd_stop(dwc_otg_hcd); ++ return 1; ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++/** ++ * HCD Callback function for sleep of HCD. ++ * ++ * @param p void pointer to the struct usb_hcd ++ */ ++static int dwc_otg_hcd_sleep_cb(void *p) ++{ ++ dwc_otg_hcd_t *hcd = p; ++ ++ dwc_otg_hcd_free_hc_from_lpm(hcd); ++ ++ return 0; ++} ++#endif ++ ++/** ++ * HCD Callback function for Remote Wakeup. ++ * ++ * @param p void pointer to the struct usb_hcd ++ */ ++static int dwc_otg_hcd_rem_wakeup_cb(void *p) ++{ ++ dwc_otg_hcd_t *hcd = p; ++ ++ if (hcd->core_if->lx_state == DWC_OTG_L2) { ++ hcd->flags.b.port_suspend_change = 1; ++ } ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ else { ++ hcd->flags.b.port_l1_change = 1; ++ } ++#endif ++ return 0; ++} ++ ++/** ++ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are ++ * stopped. ++ */ ++void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd) ++{ ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n"); ++ ++ /* ++ * The root hub should be disconnected before this function is called. ++ * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue) ++ * and the QH lists (via ..._hcd_endpoint_disable). ++ */ ++ ++ /* Turn off all host-specific interrupts. */ ++ dwc_otg_disable_host_interrupts(hcd->core_if); ++ ++ /* Turn off the vbus power */ ++ DWC_PRINTF("PortPower off\n"); ++ hprt0.b.prtpwr = 0; ++ DWC_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32); ++ dwc_mdelay(1); ++} ++ ++int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd, ++ dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle, ++ int atomic_alloc) ++{ ++ dwc_irqflags_t flags; ++ int retval = 0; ++ dwc_otg_qtd_t *qtd; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ if (!hcd->flags.b.port_connect_status) { ++ /* No longer connected. */ ++ DWC_ERROR("Not connected\n"); ++ return -DWC_E_NO_DEVICE; ++ } ++ ++ qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc); ++ if (qtd == NULL) { ++ DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n"); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ retval = ++ dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc); ++ if (retval < 0) { ++ DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. " ++ "Error status %d\n", retval); ++ dwc_otg_hcd_qtd_free(qtd); ++ } else { ++ qtd->qh = *ep_handle; ++ } ++ intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk); ++ if (!intr_mask.b.sofintr && retval == 0) { ++ dwc_otg_transaction_type_e tr_type; ++ if ((qtd->qh->ep_type == UE_BULK) ++ && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) { ++ /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */ ++ return 0; ++ } ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ tr_type = dwc_otg_hcd_select_transactions(hcd); ++ if (tr_type != DWC_OTG_TRANSACTION_NONE) { ++ dwc_otg_hcd_queue_transactions(hcd, tr_type); ++ } ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ } ++ ++ return retval; ++} ++ ++int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd, ++ dwc_otg_hcd_urb_t * dwc_otg_urb) ++{ ++ dwc_otg_qh_t *qh; ++ dwc_otg_qtd_t *urb_qtd; ++ ++ urb_qtd = dwc_otg_urb->qtd; ++ qh = urb_qtd->qh; ++#ifdef DEBUG ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ if (urb_qtd->in_process) { ++ dump_channel_info(hcd, qh); ++ } ++ } ++#endif ++ if (urb_qtd->in_process && qh->channel) { ++ /* The QTD is in process (it has been assigned to a channel). */ ++ if (hcd->flags.b.port_connect_status) { ++ /* ++ * If still connected (i.e. in host mode), halt the ++ * channel so it can be used for other transfers. If ++ * no longer connected, the host registers can't be ++ * written to halt the channel since the core is in ++ * device mode. ++ */ ++ dwc_otg_hc_halt(hcd->core_if, qh->channel, ++ DWC_OTG_HC_XFER_URB_DEQUEUE); ++ } ++ } ++ ++ /* ++ * Free the QTD and clean up the associated QH. Leave the QH in the ++ * schedule if it has any remaining QTDs. ++ */ ++ ++ if (!hcd->core_if->dma_desc_enable) { ++ uint8_t b = urb_qtd->in_process; ++ dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh); ++ if (b) { ++ dwc_otg_hcd_qh_deactivate(hcd, qh, 0); ++ qh->channel = NULL; ++ } else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ } ++ } else { ++ dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh); ++ } ++ return 0; ++} ++ ++int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle, ++ int retry) ++{ ++ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; ++ int retval = 0; ++ dwc_irqflags_t flags; ++ ++ if (retry < 0) { ++ retval = -DWC_E_INVALID; ++ goto done; ++ } ++ ++ if (!qh) { ++ retval = -DWC_E_INVALID; ++ goto done; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ ++ while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) { ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ retry--; ++ dwc_msleep(5); ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ } ++ ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ /* ++ * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove ++ * and qh_free to prevent stack dump on DWC_DMA_FREE() with ++ * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free() ++ * and dwc_otg_hcd_frame_list_alloc(). ++ */ ++ dwc_otg_hcd_qh_free(hcd, qh); ++ ++done: ++ return retval; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle) ++{ ++ int retval = 0; ++ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; ++ if (!qh) ++ return -DWC_E_INVALID; ++ ++ qh->data_toggle = DWC_OTG_HC_PID_DATA0; ++ return retval; ++} ++#endif ++ ++/** ++ * HCD Callback structure for handling mode switching. ++ */ ++static dwc_otg_cil_callbacks_t hcd_cil_callbacks = { ++ .start = dwc_otg_hcd_start_cb, ++ .stop = dwc_otg_hcd_stop_cb, ++ .disconnect = dwc_otg_hcd_disconnect_cb, ++ .session_start = dwc_otg_hcd_session_start_cb, ++ .resume_wakeup = dwc_otg_hcd_rem_wakeup_cb, ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ .sleep = dwc_otg_hcd_sleep_cb, ++#endif ++ .p = 0, ++}; ++ ++/** ++ * Reset tasklet function ++ */ ++static void reset_tasklet_func(void *data) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *) data; ++ dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; ++ hprt0_data_t hprt0; ++ ++ DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n"); ++ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtrst = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ dwc_mdelay(60); ++ ++ hprt0.b.prtrst = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ dwc_otg_hcd->flags.b.port_reset_change = 1; ++} ++ ++static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list) ++{ ++ dwc_list_link_t *item; ++ dwc_otg_qh_t *qh; ++ dwc_irqflags_t flags; ++ ++ if (!qh_list->next) { ++ /* The list hasn't been initialized yet. */ ++ return; ++ } ++ /* ++ * Hold spinlock here. Not needed in that case if bellow ++ * function is being called from ISR ++ */ ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ /* Ensure there are no QTDs or URBs left. */ ++ kill_urbs_in_qh_list(hcd, qh_list); ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ ++ DWC_LIST_FOREACH(item, qh_list) { ++ qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry); ++ dwc_otg_hcd_qh_remove_and_free(hcd, qh); ++ } ++} ++ ++/** ++ * Exit from Hibernation if Host did not detect SRP from connected SRP capable ++ * Device during SRP time by host power up. ++ */ ++void dwc_otg_hcd_power_up(void *ptr) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; ++ ++ DWC_PRINTF("%s called\n", __FUNCTION__); ++ ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return; ++ } ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Enable VBUS */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++} ++ ++/** ++ * Frees secondary storage associated with the dwc_otg_hcd structure contained ++ * in the struct usb_hcd field. ++ */ ++static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ int i; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n"); ++ ++ del_timers(dwc_otg_hcd); ++ ++ /* Free memory for QH/QTD lists */ ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued); ++ ++ /* Free memory for the host channels. */ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ dwc_hc_t *hc = dwc_otg_hcd->hc_ptr_array[i]; ++ ++#ifdef DEBUG ++ if (dwc_otg_hcd->core_if->hc_xfer_timer[i]) { ++ DWC_TIMER_FREE(dwc_otg_hcd->core_if->hc_xfer_timer[i]); ++ } ++#endif ++ if (hc != NULL) { ++ DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n", ++ i, hc); ++ DWC_FREE(hc); ++ } ++ } ++ ++ if (dwc_otg_hcd->core_if->dma_enable) { ++ if (dwc_otg_hcd->status_buf_dma) { ++ DWC_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE, ++ dwc_otg_hcd->status_buf, ++ dwc_otg_hcd->status_buf_dma); ++ } ++ } else if (dwc_otg_hcd->status_buf != NULL) { ++ DWC_FREE(dwc_otg_hcd->status_buf); ++ } ++ DWC_SPINLOCK_FREE(dwc_otg_hcd->lock); ++ /* Set core_if's lock pointer to NULL */ ++ dwc_otg_hcd->core_if->lock = NULL; ++ ++ DWC_TIMER_FREE(dwc_otg_hcd->conn_timer); ++ DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet); ++ ++#ifdef DWC_DEV_SRPCAP ++ if (dwc_otg_hcd->core_if->power_down == 2 && ++ dwc_otg_hcd->core_if->pwron_timer) { ++ DWC_TIMER_FREE(dwc_otg_hcd->core_if->pwron_timer); ++ } ++#endif ++ DWC_FREE(dwc_otg_hcd); ++} ++ ++int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) ++{ ++ int retval = 0; ++ int num_channels; ++ int i; ++ dwc_hc_t *channel; ++ ++ hcd->lock = DWC_SPINLOCK_ALLOC(); ++ if (!hcd->lock) { ++ DWC_ERROR("Could not allocate lock for pcd"); ++ DWC_FREE(hcd); ++ retval = -DWC_E_NO_MEMORY; ++ goto out; ++ } ++ hcd->core_if = core_if; ++ ++ /* Register the HCD CIL Callbacks */ ++ dwc_otg_cil_register_hcd_callbacks(hcd->core_if, ++ &hcd_cil_callbacks, hcd); ++ ++ /* Initialize the non-periodic schedule. */ ++ DWC_LIST_INIT(&hcd->non_periodic_sched_inactive); ++ DWC_LIST_INIT(&hcd->non_periodic_sched_active); ++ ++ /* Initialize the periodic schedule. */ ++ DWC_LIST_INIT(&hcd->periodic_sched_inactive); ++ DWC_LIST_INIT(&hcd->periodic_sched_ready); ++ DWC_LIST_INIT(&hcd->periodic_sched_assigned); ++ DWC_LIST_INIT(&hcd->periodic_sched_queued); ++ ++ /* ++ * Create a host channel descriptor for each host channel implemented ++ * in the controller. Initialize the channel descriptor array. ++ */ ++ DWC_CIRCLEQ_INIT(&hcd->free_hc_list); ++ num_channels = hcd->core_if->core_params->host_channels; ++ DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array)); ++ for (i = 0; i < num_channels; i++) { ++ channel = DWC_ALLOC(sizeof(dwc_hc_t)); ++ if (channel == NULL) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR("%s: host channel allocation failed\n", ++ __func__); ++ dwc_otg_hcd_free(hcd); ++ goto out; ++ } ++ channel->hc_num = i; ++ hcd->hc_ptr_array[i] = channel; ++#ifdef DEBUG ++ hcd->core_if->hc_xfer_timer[i] = ++ DWC_TIMER_ALLOC("hc timer", hc_xfer_timeout, ++ &hcd->core_if->hc_xfer_info[i]); ++#endif ++ DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i, ++ channel); ++ } ++ ++ /* Initialize the Connection timeout timer. */ ++ hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer", ++ dwc_otg_hcd_connect_timeout, hcd); ++ ++ /* Initialize reset tasklet. */ ++ hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd); ++#ifdef DWC_DEV_SRPCAP ++ if (hcd->core_if->power_down == 2) { ++ /* Initialize Power on timer for Host power up in case hibernation */ ++ hcd->core_if->pwron_timer = DWC_TIMER_ALLOC("PWRON TIMER", ++ dwc_otg_hcd_power_up, core_if); ++ } ++#endif ++ ++ /* ++ * Allocate space for storing data on status transactions. Normally no ++ * data is sent, but this space acts as a bit bucket. This must be ++ * done after usb_add_hcd since that function allocates the DMA buffer ++ * pool. ++ */ ++ if (hcd->core_if->dma_enable) { ++ hcd->status_buf = ++ DWC_DMA_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE, ++ &hcd->status_buf_dma); ++ } else { ++ hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE); ++ } ++ if (!hcd->status_buf) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR("%s: status_buf allocation failed\n", __func__); ++ dwc_otg_hcd_free(hcd); ++ goto out; ++ } ++ ++ hcd->otg_port = 1; ++ hcd->frame_list = NULL; ++ hcd->frame_list_dma = 0; ++ hcd->periodic_qh_count = 0; ++out: ++ return retval; ++} ++ ++void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd) ++{ ++ /* Turn off all host-specific interrupts. */ ++ dwc_otg_disable_host_interrupts(hcd->core_if); ++ ++ dwc_otg_hcd_free(hcd); ++} ++ ++/** ++ * Initializes dynamic portions of the DWC_otg HCD state. ++ */ ++static void dwc_otg_hcd_reinit(dwc_otg_hcd_t * hcd) ++{ ++ int num_channels; ++ int i; ++ dwc_hc_t *channel; ++ dwc_hc_t *channel_tmp; ++ ++ hcd->flags.d32 = 0; ++ ++ hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active; ++ hcd->non_periodic_channels = 0; ++ hcd->periodic_channels = 0; ++ ++ /* ++ * Put all channels in the free channel list and clean up channel ++ * states. ++ */ ++ DWC_CIRCLEQ_FOREACH_SAFE(channel, channel_tmp, ++ &hcd->free_hc_list, hc_list_entry) { ++ DWC_CIRCLEQ_REMOVE(&hcd->free_hc_list, channel, hc_list_entry); ++ } ++ ++ num_channels = hcd->core_if->core_params->host_channels; ++ for (i = 0; i < num_channels; i++) { ++ channel = hcd->hc_ptr_array[i]; ++ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, channel, ++ hc_list_entry); ++ dwc_otg_hc_cleanup(hcd->core_if, channel); ++ } ++ ++ /* Initialize the DWC core for host mode operation. */ ++ dwc_otg_core_host_init(hcd->core_if); ++ ++ /* Set core_if's lock pointer to the hcd->lock */ ++ hcd->core_if->lock = hcd->lock; ++} ++ ++/** ++ * Assigns transactions from a QTD to a free host channel and initializes the ++ * host channel to perform the transactions. The host channel is removed from ++ * the free list. ++ * ++ * @param hcd The HCD state structure. ++ * @param qh Transactions from the first QTD for this QH are selected and ++ * assigned to a free host channel. ++ */ ++static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ dwc_hc_t *hc = NULL; ++ dwc_otg_qtd_t *qtd; ++ dwc_otg_hcd_urb_t *urb; ++ void* ptr = NULL; ++ hcchar_data_t hcchar; ++ int num_channels; ++ int i; ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p)\n", __func__, hcd, qh); ++ ++ num_channels = hcd->core_if->core_params->host_channels; ++ ++ /* WA to not select channel with chdis bit set, this was ++ * observed after role switch as part of OTG 2.0 HNP ++ */ ++ for (i = 0; i < num_channels; i++) { ++ hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list); ++ hcchar.d32 = DWC_READ_REG32(&hcd->core_if->host_if->hc_regs[hc->hc_num]->hcchar); ++ DWC_DEBUGPL(DBG_HCDV, "HC num = %d HCCHAR %08x\n", hc->hc_num, hcchar.d32); ++ if(!hcchar.b.chdis && !hcchar.b.chen) ++ break; ++ DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry); ++ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); ++ hc = NULL; ++ } ++ if (!hc) { ++ DWC_ERROR("No free channel with en and dis bits 0\n"); ++ return; ++ } ++ ++ ++ ++ /* Remove the host channel from the free list. */ ++ DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry); ++ ++ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); ++ ++ urb = qtd->urb; ++ qh->channel = hc; ++ ++ qtd->in_process = 1; ++ ++ /* ++ * Use usb_pipedevice to determine device address. This address is ++ * 0 before the SET_ADDRESS command and the correct address afterward. ++ */ ++ hc->dev_addr = dwc_otg_hcd_get_dev_addr(&urb->pipe_info); ++ hc->ep_num = dwc_otg_hcd_get_ep_num(&urb->pipe_info); ++ hc->speed = qh->dev_speed; ++ hc->max_packet = dwc_max_packet(qh->maxp); ++ ++ hc->xfer_started = 0; ++ hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS; ++ hc->error_state = (qtd->error_count > 0); ++ hc->halt_on_queue = 0; ++ hc->halt_pending = 0; ++ hc->requests = 0; ++ ++ /* ++ * The following values may be modified in the transfer type section ++ * below. The xfer_len value may be reduced when the transfer is ++ * started to accommodate the max widths of the XferSize and PktCnt ++ * fields in the HCTSIZn register. ++ */ ++ ++ hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0); ++ if (hc->ep_is_in) { ++ hc->do_ping = 0; ++ } else { ++ hc->do_ping = qh->ping_state; ++ } ++ ++ hc->data_pid_start = qh->data_toggle; ++ hc->multi_count = 1; ++ ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length; ++ ++ /* For non-dword aligned case */ ++ if (((unsigned long)hc->xfer_buff & 0x3) ++ && !hcd->core_if->dma_desc_enable) { ++ ptr = (uint8_t *) urb->buf + urb->actual_length; ++ } ++ } else { ++ hc->xfer_buff = (uint8_t *) urb->buf + urb->actual_length; ++ } ++ hc->xfer_len = urb->length - urb->actual_length; ++ hc->xfer_count = 0; ++ ++ /* ++ * Set the split attributes ++ */ ++ hc->do_split = 0; ++ if (qh->do_split) { ++ uint32_t hub_addr, port_addr; ++ hc->do_split = 1; ++ hc->xact_pos = qtd->isoc_split_pos; ++ hc->complete_split = qtd->complete_split; ++ hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr); ++ hc->hub_addr = (uint8_t) hub_addr; ++ hc->port_addr = (uint8_t) port_addr; ++ } ++ ++ switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) { ++ case UE_CONTROL: ++ hc->ep_type = DWC_OTG_EP_TYPE_CONTROL; ++ switch (qtd->control_phase) { ++ case DWC_OTG_CONTROL_SETUP: ++ DWC_DEBUGPL(DBG_HCDV, " Control setup transaction\n"); ++ hc->do_ping = 0; ++ hc->ep_is_in = 0; ++ hc->data_pid_start = DWC_OTG_HC_PID_SETUP; ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = (uint8_t *) urb->setup_dma; ++ } else { ++ hc->xfer_buff = (uint8_t *) urb->setup_packet; ++ } ++ hc->xfer_len = 8; ++ ptr = NULL; ++ break; ++ case DWC_OTG_CONTROL_DATA: ++ DWC_DEBUGPL(DBG_HCDV, " Control data transaction\n"); ++ hc->data_pid_start = qtd->data_toggle; ++ break; ++ case DWC_OTG_CONTROL_STATUS: ++ /* ++ * Direction is opposite of data direction or IN if no ++ * data. ++ */ ++ DWC_DEBUGPL(DBG_HCDV, " Control status transaction\n"); ++ if (urb->length == 0) { ++ hc->ep_is_in = 1; ++ } else { ++ hc->ep_is_in = ++ dwc_otg_hcd_is_pipe_out(&urb->pipe_info); ++ } ++ if (hc->ep_is_in) { ++ hc->do_ping = 0; ++ } ++ ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA1; ++ ++ hc->xfer_len = 0; ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = (uint8_t *) hcd->status_buf_dma; ++ } else { ++ hc->xfer_buff = (uint8_t *) hcd->status_buf; ++ } ++ ptr = NULL; ++ break; ++ } ++ break; ++ case UE_BULK: ++ hc->ep_type = DWC_OTG_EP_TYPE_BULK; ++ break; ++ case UE_INTERRUPT: ++ hc->ep_type = DWC_OTG_EP_TYPE_INTR; ++ break; ++ case UE_ISOCHRONOUS: ++ { ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc; ++ ++ hc->ep_type = DWC_OTG_EP_TYPE_ISOC; ++ ++ if (hcd->core_if->dma_desc_enable) ++ break; ++ ++ frame_desc = &urb->iso_descs[qtd->isoc_frame_index]; ++ ++ frame_desc->status = 0; ++ ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = (uint8_t *) urb->dma; ++ } else { ++ hc->xfer_buff = (uint8_t *) urb->buf; ++ } ++ hc->xfer_buff += ++ frame_desc->offset + qtd->isoc_split_offset; ++ hc->xfer_len = ++ frame_desc->length - qtd->isoc_split_offset; ++ ++ /* For non-dword aligned buffers */ ++ if (((unsigned long)hc->xfer_buff & 0x3) ++ && hcd->core_if->dma_enable) { ++ ptr = ++ (uint8_t *) urb->buf + frame_desc->offset + ++ qtd->isoc_split_offset; ++ } else ++ ptr = NULL; ++ ++ if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) { ++ if (hc->xfer_len <= 188) { ++ hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL; ++ } else { ++ hc->xact_pos = ++ DWC_HCSPLIT_XACTPOS_BEGIN; ++ } ++ } ++ } ++ break; ++ } ++ /* non DWORD-aligned buffer case */ ++ if (ptr) { ++ uint32_t buf_size; ++ if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { ++ buf_size = hcd->core_if->core_params->max_transfer_size; ++ } else { ++ buf_size = 4096; ++ } ++ if (!qh->dw_align_buf) { ++ qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(buf_size, ++ &qh->dw_align_buf_dma); ++ if (!qh->dw_align_buf) { ++ DWC_ERROR ++ ("%s: Failed to allocate memory to handle " ++ "non-dword aligned buffer case\n", ++ __func__); ++ return; ++ } ++ } ++ if (!hc->ep_is_in) { ++ dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len); ++ } ++ hc->align_buff = qh->dw_align_buf_dma; ++ } else { ++ hc->align_buff = 0; ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * This value may be modified when the transfer is started to ++ * reflect the actual transfer length. ++ */ ++ hc->multi_count = dwc_hb_mult(qh->maxp); ++ } ++ ++ if (hcd->core_if->dma_desc_enable) ++ hc->desc_list_addr = qh->desc_list_dma; ++ ++ dwc_otg_hc_init(hcd->core_if, hc); ++ hc->qh = qh; ++} ++ ++/** ++ * This function selects transactions from the HCD transfer schedule and ++ * assigns them to available host channels. It is called from HCD interrupt ++ * handler functions. ++ * ++ * @param hcd The HCD state structure. ++ * ++ * @return The types of new transactions that were assigned to host channels. ++ */ ++dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) ++{ ++ dwc_list_link_t *qh_ptr; ++ dwc_otg_qh_t *qh; ++ int num_channels; ++ dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE; ++ ++#ifdef DEBUG_SOF ++ DWC_DEBUGPL(DBG_HCD, " Select Transactions\n"); ++#endif ++ ++ /* Process entries in the periodic ready list. */ ++ qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready); ++ ++ while (qh_ptr != &hcd->periodic_sched_ready && ++ !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { ++ ++ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); ++ assign_and_init_hc(hcd, qh); ++ ++ /* ++ * Move the QH from the periodic ready schedule to the ++ * periodic assigned schedule. ++ */ ++ qh_ptr = DWC_LIST_NEXT(qh_ptr); ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, ++ &qh->qh_list_entry); ++ ++ ret_val = DWC_OTG_TRANSACTION_PERIODIC; ++ } ++ ++ /* ++ * Process entries in the inactive portion of the non-periodic ++ * schedule. Some free host channels may not be used if they are ++ * reserved for periodic transfers. ++ */ ++ qh_ptr = hcd->non_periodic_sched_inactive.next; ++ num_channels = hcd->core_if->core_params->host_channels; ++ while (qh_ptr != &hcd->non_periodic_sched_inactive && ++ (hcd->non_periodic_channels < ++ num_channels - hcd->periodic_channels) && ++ !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { ++ ++ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); ++ ++ assign_and_init_hc(hcd, qh); ++ ++ /* ++ * Move the QH from the non-periodic inactive schedule to the ++ * non-periodic active schedule. ++ */ ++ qh_ptr = DWC_LIST_NEXT(qh_ptr); ++ DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active, ++ &qh->qh_list_entry); ++ ++ if (ret_val == DWC_OTG_TRANSACTION_NONE) { ++ ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC; ++ } else { ++ ret_val = DWC_OTG_TRANSACTION_ALL; ++ } ++ ++ hcd->non_periodic_channels++; ++ } ++ ++ return ret_val; ++} ++ ++/** ++ * Attempts to queue a single transaction request for a host channel ++ * associated with either a periodic or non-periodic transfer. This function ++ * assumes that there is space available in the appropriate request queue. For ++ * an OUT transfer or SETUP transaction in Slave mode, it checks whether space ++ * is available in the appropriate Tx FIFO. ++ * ++ * @param hcd The HCD state structure. ++ * @param hc Host channel descriptor associated with either a periodic or ++ * non-periodic transfer. ++ * @param fifo_dwords_avail Number of DWORDs available in the periodic Tx ++ * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic ++ * transfers. ++ * ++ * @return 1 if a request is queued and more requests may be needed to ++ * complete the transfer, 0 if no more requests are required for this ++ * transfer, -1 if there is insufficient space in the Tx FIFO. ++ */ ++static int queue_transaction(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, uint16_t fifo_dwords_avail) ++{ ++ int retval; ++ ++ if (hcd->core_if->dma_enable) { ++ if (hcd->core_if->dma_desc_enable) { ++ if (!hc->xfer_started ++ || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) { ++ dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh); ++ hc->qh->ping_state = 0; ++ } ++ } else if (!hc->xfer_started) { ++ dwc_otg_hc_start_transfer(hcd->core_if, hc); ++ hc->qh->ping_state = 0; ++ } ++ retval = 0; ++ } else if (hc->halt_pending) { ++ /* Don't queue a request if the channel has been halted. */ ++ retval = 0; ++ } else if (hc->halt_on_queue) { ++ dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status); ++ retval = 0; ++ } else if (hc->do_ping) { ++ if (!hc->xfer_started) { ++ dwc_otg_hc_start_transfer(hcd->core_if, hc); ++ } ++ retval = 0; ++ } else if (!hc->ep_is_in || hc->data_pid_start == DWC_OTG_HC_PID_SETUP) { ++ if ((fifo_dwords_avail * 4) >= hc->max_packet) { ++ if (!hc->xfer_started) { ++ dwc_otg_hc_start_transfer(hcd->core_if, hc); ++ retval = 1; ++ } else { ++ retval = ++ dwc_otg_hc_continue_transfer(hcd->core_if, ++ hc); ++ } ++ } else { ++ retval = -1; ++ } ++ } else { ++ if (!hc->xfer_started) { ++ dwc_otg_hc_start_transfer(hcd->core_if, hc); ++ retval = 1; ++ } else { ++ retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc); ++ } ++ } ++ ++ return retval; ++} ++ ++/** ++ * Processes periodic channels for the next frame and queues transactions for ++ * these channels to the DWC_otg controller. After queueing transactions, the ++ * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions ++ * to queue as Periodic Tx FIFO or request queue space becomes available. ++ * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled. ++ */ ++static void process_periodic_channels(dwc_otg_hcd_t * hcd) ++{ ++ hptxsts_data_t tx_status; ++ dwc_list_link_t *qh_ptr; ++ dwc_otg_qh_t *qh; ++ int status; ++ int no_queue_space = 0; ++ int no_fifo_space = 0; ++ ++ dwc_otg_host_global_regs_t *host_regs; ++ host_regs = hcd->core_if->host_if->host_global_regs; ++ ++ DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n"); ++#ifdef DEBUG ++ tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts); ++ DWC_DEBUGPL(DBG_HCDV, ++ " P Tx Req Queue Space Avail (before queue): %d\n", ++ tx_status.b.ptxqspcavail); ++ DWC_DEBUGPL(DBG_HCDV, " P Tx FIFO Space Avail (before queue): %d\n", ++ tx_status.b.ptxfspcavail); ++#endif ++ ++ qh_ptr = hcd->periodic_sched_assigned.next; ++ while (qh_ptr != &hcd->periodic_sched_assigned) { ++ tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts); ++ if (tx_status.b.ptxqspcavail == 0) { ++ no_queue_space = 1; ++ break; ++ } ++ ++ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); ++ ++ /* ++ * Set a flag if we're queuing high-bandwidth in slave mode. ++ * The flag prevents any halts to get into the request queue in ++ * the middle of multiple high-bandwidth packets getting queued. ++ */ ++ if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) { ++ hcd->core_if->queuing_high_bandwidth = 1; ++ } ++ status = ++ queue_transaction(hcd, qh->channel, ++ tx_status.b.ptxfspcavail); ++ if (status < 0) { ++ no_fifo_space = 1; ++ break; ++ } ++ ++ /* ++ * In Slave mode, stay on the current transfer until there is ++ * nothing more to do or the high-bandwidth request count is ++ * reached. In DMA mode, only need to queue one request. The ++ * controller automatically handles multiple packets for ++ * high-bandwidth transfers. ++ */ ++ if (hcd->core_if->dma_enable || status == 0 || ++ qh->channel->requests == qh->channel->multi_count) { ++ qh_ptr = qh_ptr->next; ++ /* ++ * Move the QH from the periodic assigned schedule to ++ * the periodic queued schedule. ++ */ ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_queued, ++ &qh->qh_list_entry); ++ ++ /* done queuing high bandwidth */ ++ hcd->core_if->queuing_high_bandwidth = 0; ++ } ++ } ++ ++ if (!hcd->core_if->dma_enable) { ++ dwc_otg_core_global_regs_t *global_regs; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ global_regs = hcd->core_if->core_global_regs; ++ intr_mask.b.ptxfempty = 1; ++#ifdef DEBUG ++ tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts); ++ DWC_DEBUGPL(DBG_HCDV, ++ " P Tx Req Queue Space Avail (after queue): %d\n", ++ tx_status.b.ptxqspcavail); ++ DWC_DEBUGPL(DBG_HCDV, ++ " P Tx FIFO Space Avail (after queue): %d\n", ++ tx_status.b.ptxfspcavail); ++#endif ++ if (!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned) || ++ no_queue_space || no_fifo_space) { ++ /* ++ * May need to queue more transactions as the request ++ * queue or Tx FIFO empties. Enable the periodic Tx ++ * FIFO empty interrupt. (Always use the half-empty ++ * level to ensure that new requests are loaded as ++ * soon as possible.) ++ */ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, ++ intr_mask.d32); ++ } else { ++ /* ++ * Disable the Tx FIFO empty interrupt since there are ++ * no more transactions that need to be queued right ++ * now. This function is called from interrupt ++ * handlers to queue more transactions as transfer ++ * states change. ++ */ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, ++ 0); ++ } ++ } ++} ++ ++/** ++ * Processes active non-periodic channels and queues transactions for these ++ * channels to the DWC_otg controller. After queueing transactions, the NP Tx ++ * FIFO Empty interrupt is enabled if there are more transactions to queue as ++ * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx ++ * FIFO Empty interrupt is disabled. ++ */ ++static void process_non_periodic_channels(dwc_otg_hcd_t * hcd) ++{ ++ gnptxsts_data_t tx_status; ++ dwc_list_link_t *orig_qh_ptr; ++ dwc_otg_qh_t *qh; ++ int status; ++ int no_queue_space = 0; ++ int no_fifo_space = 0; ++ int more_to_do = 0; ++ ++ dwc_otg_core_global_regs_t *global_regs = ++ hcd->core_if->core_global_regs; ++ ++ DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n"); ++#ifdef DEBUG ++ tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts); ++ DWC_DEBUGPL(DBG_HCDV, ++ " NP Tx Req Queue Space Avail (before queue): %d\n", ++ tx_status.b.nptxqspcavail); ++ DWC_DEBUGPL(DBG_HCDV, " NP Tx FIFO Space Avail (before queue): %d\n", ++ tx_status.b.nptxfspcavail); ++#endif ++ /* ++ * Keep track of the starting point. Skip over the start-of-list ++ * entry. ++ */ ++ if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) { ++ hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; ++ } ++ orig_qh_ptr = hcd->non_periodic_qh_ptr; ++ ++ /* ++ * Process once through the active list or until no more space is ++ * available in the request queue or the Tx FIFO. ++ */ ++ do { ++ tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts); ++ if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) { ++ no_queue_space = 1; ++ break; ++ } ++ ++ qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t, ++ qh_list_entry); ++ status = ++ queue_transaction(hcd, qh->channel, ++ tx_status.b.nptxfspcavail); ++ ++ if (status > 0) { ++ more_to_do = 1; ++ } else if (status < 0) { ++ no_fifo_space = 1; ++ break; ++ } ++ ++ /* Advance to next QH, skipping start-of-list entry. */ ++ hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; ++ if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) { ++ hcd->non_periodic_qh_ptr = ++ hcd->non_periodic_qh_ptr->next; ++ } ++ ++ } while (hcd->non_periodic_qh_ptr != orig_qh_ptr); ++ ++ if (!hcd->core_if->dma_enable) { ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ intr_mask.b.nptxfempty = 1; ++ ++#ifdef DEBUG ++ tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts); ++ DWC_DEBUGPL(DBG_HCDV, ++ " NP Tx Req Queue Space Avail (after queue): %d\n", ++ tx_status.b.nptxqspcavail); ++ DWC_DEBUGPL(DBG_HCDV, ++ " NP Tx FIFO Space Avail (after queue): %d\n", ++ tx_status.b.nptxfspcavail); ++#endif ++ if (more_to_do || no_queue_space || no_fifo_space) { ++ /* ++ * May need to queue more transactions as the request ++ * queue or Tx FIFO empties. Enable the non-periodic ++ * Tx FIFO empty interrupt. (Always use the half-empty ++ * level to ensure that new requests are loaded as ++ * soon as possible.) ++ */ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, ++ intr_mask.d32); ++ } else { ++ /* ++ * Disable the Tx FIFO empty interrupt since there are ++ * no more transactions that need to be queued right ++ * now. This function is called from interrupt ++ * handlers to queue more transactions as transfer ++ * states change. ++ */ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, ++ 0); ++ } ++ } ++} ++ ++/** ++ * This function processes the currently active host channels and queues ++ * transactions for these channels to the DWC_otg controller. It is called ++ * from HCD interrupt handler functions. ++ * ++ * @param hcd The HCD state structure. ++ * @param tr_type The type(s) of transactions to queue (non-periodic, ++ * periodic, or both). ++ */ ++void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd, ++ dwc_otg_transaction_type_e tr_type) ++{ ++#ifdef DEBUG_SOF ++ DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n"); ++#endif ++ /* Process host channels associated with periodic transfers. */ ++ if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC || ++ tr_type == DWC_OTG_TRANSACTION_ALL) && ++ !DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) { ++ ++ process_periodic_channels(hcd); ++ } ++ ++ /* Process host channels associated with non-periodic transfers. */ ++ if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC || ++ tr_type == DWC_OTG_TRANSACTION_ALL) { ++ if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) { ++ process_non_periodic_channels(hcd); ++ } else { ++ /* ++ * Ensure NP Tx FIFO empty interrupt is disabled when ++ * there are no non-periodic transfers to process. ++ */ ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ gintmsk.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&hcd->core_if-> ++ core_global_regs->gintmsk, gintmsk.d32, ++ 0); ++ } ++ } ++} ++ ++#ifdef DWC_HS_ELECT_TST ++/* ++ * Quick and dirty hack to implement the HS Electrical Test ++ * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature. ++ * ++ * This code was copied from our userspace app "hset". It sends a ++ * Get Device Descriptor control sequence in two parts, first the ++ * Setup packet by itself, followed some time later by the In and ++ * Ack packets. Rather than trying to figure out how to add this ++ * functionality to the normal driver code, we just hijack the ++ * hardware, using these two function to drive the hardware ++ * directly. ++ */ ++ ++static dwc_otg_core_global_regs_t *global_regs; ++static dwc_otg_host_global_regs_t *hc_global_regs; ++static dwc_otg_hc_regs_t *hc_regs; ++static uint32_t *data_fifo; ++ ++static void do_setup(void) ++{ ++ gintsts_data_t gintsts; ++ hctsiz_data_t hctsiz; ++ hcchar_data_t hcchar; ++ haint_data_t haint; ++ hcint_data_t hcint; ++ ++ /* Enable HAINTs */ ++ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001); ++ ++ /* Enable HCINTs */ ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* ++ * Send Setup packet (Get Device Descriptor) ++ */ ++ ++ /* Make sure channel is disabled */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chdis = 1; ++// hcchar.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ //sleep(1); ++ dwc_mdelay(1000); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ } ++ ++ /* Set HCTSIZ */ ++ hctsiz.d32 = 0; ++ hctsiz.b.xfersize = 8; ++ hctsiz.b.pktcnt = 1; ++ hctsiz.b.pid = DWC_OTG_HC_PID_SETUP; ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ /* Set HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; ++ hcchar.b.epdir = 0; ++ hcchar.b.epnum = 0; ++ hcchar.b.mps = 8; ++ hcchar.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ /* Fill FIFO with Setup data for Get Device Descriptor */ ++ data_fifo = (uint32_t *) ((char *)global_regs + 0x1000); ++ DWC_WRITE_REG32(data_fifo++, 0x01000680); ++ DWC_WRITE_REG32(data_fifo++, 0x00080000); ++ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for host channel interrupt */ ++ do { ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.hcintr == 0); ++ ++ /* Disable HCINTs */ ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000); ++ ++ /* Disable HAINTs */ ++ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++} ++ ++static void do_in_ack(void) ++{ ++ gintsts_data_t gintsts; ++ hctsiz_data_t hctsiz; ++ hcchar_data_t hcchar; ++ haint_data_t haint; ++ hcint_data_t hcint; ++ host_grxsts_data_t grxsts; ++ ++ /* Enable HAINTs */ ++ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001); ++ ++ /* Enable HCINTs */ ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* ++ * Receive Control In packet ++ */ ++ ++ /* Make sure channel is disabled */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chdis = 1; ++ hcchar.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ //sleep(1); ++ dwc_mdelay(1000); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ } ++ ++ /* Set HCTSIZ */ ++ hctsiz.d32 = 0; ++ hctsiz.b.xfersize = 8; ++ hctsiz.b.pktcnt = 1; ++ hctsiz.b.pid = DWC_OTG_HC_PID_DATA1; ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ /* Set HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; ++ hcchar.b.epdir = 1; ++ hcchar.b.epnum = 0; ++ hcchar.b.mps = 8; ++ hcchar.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for receive status queue interrupt */ ++ do { ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.rxstsqlvl == 0); ++ ++ /* Read RXSTS */ ++ grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp); ++ ++ /* Clear RXSTSQLVL in GINTSTS */ ++ gintsts.d32 = 0; ++ gintsts.b.rxstsqlvl = 1; ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ switch (grxsts.b.pktsts) { ++ case DWC_GRXSTS_PKTSTS_IN: ++ /* Read the data into the host buffer */ ++ if (grxsts.b.bcnt > 0) { ++ int i; ++ int word_count = (grxsts.b.bcnt + 3) / 4; ++ ++ data_fifo = (uint32_t *) ((char *)global_regs + 0x1000); ++ ++ for (i = 0; i < word_count; i++) { ++ (void)DWC_READ_REG32(data_fifo++); ++ } ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for receive status queue interrupt */ ++ do { ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.rxstsqlvl == 0); ++ ++ /* Read RXSTS */ ++ grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp); ++ ++ /* Clear RXSTSQLVL in GINTSTS */ ++ gintsts.d32 = 0; ++ gintsts.b.rxstsqlvl = 1; ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ switch (grxsts.b.pktsts) { ++ case DWC_GRXSTS_PKTSTS_IN_XFER_COMP: ++ break; ++ ++ default: ++ break; ++ } ++ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for host channel interrupt */ ++ do { ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.hcintr == 0); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++// usleep(100000); ++// mdelay(100); ++ dwc_mdelay(1); ++ ++ /* ++ * Send handshake packet ++ */ ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Make sure channel is disabled */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chdis = 1; ++ hcchar.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ //sleep(1); ++ dwc_mdelay(1000); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ } ++ ++ /* Set HCTSIZ */ ++ hctsiz.d32 = 0; ++ hctsiz.b.xfersize = 0; ++ hctsiz.b.pktcnt = 1; ++ hctsiz.b.pid = DWC_OTG_HC_PID_DATA1; ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ /* Set HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; ++ hcchar.b.epdir = 0; ++ hcchar.b.epnum = 0; ++ hcchar.b.mps = 8; ++ hcchar.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for host channel interrupt */ ++ do { ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.hcintr == 0); ++ ++ /* Disable HCINTs */ ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000); ++ ++ /* Disable HAINTs */ ++ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++} ++#endif ++ ++/** Handles hub class-specific requests. */ ++int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, ++ uint16_t typeReq, ++ uint16_t wValue, ++ uint16_t wIndex, uint8_t * buf, uint16_t wLength) ++{ ++ int retval = 0; ++ ++ dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; ++ usb_hub_descriptor_t *hub_desc; ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ ++ uint32_t port_status; ++ ++ switch (typeReq) { ++ case UCR_CLEAR_HUB_FEATURE: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearHubFeature 0x%x\n", wValue); ++ switch (wValue) { ++ case UHF_C_HUB_LOCAL_POWER: ++ case UHF_C_HUB_OVER_CURRENT: ++ /* Nothing required here */ ++ break; ++ default: ++ retval = -DWC_E_INVALID; ++ DWC_ERROR("DWC OTG HCD - " ++ "ClearHubFeature request %xh unknown\n", ++ wValue); ++ } ++ break; ++ case UCR_CLEAR_PORT_FEATURE: ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ if (wValue != UHF_PORT_L1) ++#endif ++ if (!wIndex || wIndex > 1) ++ goto error; ++ ++ switch (wValue) { ++ case UHF_PORT_ENABLE: ++ DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_ENABLE\n"); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtena = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ break; ++ case UHF_PORT_SUSPEND: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_SUSPEND\n"); ++ ++ if (core_if->power_down == 2) { ++ dwc_otg_host_hibernation_restore(core_if, 0, 0); ++ } else { ++ DWC_WRITE_REG32(core_if->pcgcctl, 0); ++ dwc_mdelay(5); ++ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtres = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ hprt0.b.prtsusp = 0; ++ /* Clear Resume bit */ ++ dwc_mdelay(100); ++ hprt0.b.prtres = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } ++ break; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ case UHF_PORT_L1: ++ { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ glpmcfg_data_t lpmcfg = {.d32 = 0 }; ++ ++ lpmcfg.d32 = ++ DWC_READ_REG32(&core_if-> ++ core_global_regs->glpmcfg); ++ lpmcfg.b.en_utmi_sleep = 0; ++ lpmcfg.b.hird_thres &= (~(1 << 4)); ++ lpmcfg.b.prt_sleep_sts = 1; ++ DWC_WRITE_REG32(&core_if-> ++ core_global_regs->glpmcfg, ++ lpmcfg.d32); ++ ++ /* Clear Enbl_L1Gating bit. */ ++ pcgcctl.b.enbl_sleep_gating = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, ++ 0); ++ ++ dwc_mdelay(5); ++ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtres = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, ++ hprt0.d32); ++ /* This bit will be cleared in wakeup interrupt handle */ ++ break; ++ } ++#endif ++ case UHF_PORT_POWER: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_POWER\n"); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ break; ++ case UHF_PORT_INDICATOR: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_INDICATOR\n"); ++ /* Port inidicator not supported */ ++ break; ++ case UHF_C_PORT_CONNECTION: ++ /* Clears drivers internal connect status change ++ * flag */ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n"); ++ dwc_otg_hcd->flags.b.port_connect_status_change = 0; ++ break; ++ case UHF_C_PORT_RESET: ++ /* Clears the driver's internal Port Reset Change ++ * flag */ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_RESET\n"); ++ dwc_otg_hcd->flags.b.port_reset_change = 0; ++ break; ++ case UHF_C_PORT_ENABLE: ++ /* Clears the driver's internal Port ++ * Enable/Disable Change flag */ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n"); ++ dwc_otg_hcd->flags.b.port_enable_change = 0; ++ break; ++ case UHF_C_PORT_SUSPEND: ++ /* Clears the driver's internal Port Suspend ++ * Change flag, which is set when resume signaling on ++ * the host port is complete */ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n"); ++ dwc_otg_hcd->flags.b.port_suspend_change = 0; ++ break; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ case UHF_C_PORT_L1: ++ dwc_otg_hcd->flags.b.port_l1_change = 0; ++ break; ++#endif ++ case UHF_C_PORT_OVER_CURRENT: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n"); ++ dwc_otg_hcd->flags.b.port_over_current_change = 0; ++ break; ++ default: ++ retval = -DWC_E_INVALID; ++ DWC_ERROR("DWC OTG HCD - " ++ "ClearPortFeature request %xh " ++ "unknown or unsupported\n", wValue); ++ } ++ break; ++ case UCR_GET_HUB_DESCRIPTOR: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "GetHubDescriptor\n"); ++ hub_desc = (usb_hub_descriptor_t *) buf; ++ hub_desc->bDescLength = 9; ++ hub_desc->bDescriptorType = 0x29; ++ hub_desc->bNbrPorts = 1; ++ USETW(hub_desc->wHubCharacteristics, 0x08); ++ hub_desc->bPwrOn2PwrGood = 1; ++ hub_desc->bHubContrCurrent = 0; ++ hub_desc->DeviceRemovable[0] = 0; ++ hub_desc->DeviceRemovable[1] = 0xff; ++ break; ++ case UCR_GET_HUB_STATUS: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "GetHubStatus\n"); ++ DWC_MEMSET(buf, 0, 4); ++ break; ++ case UCR_GET_PORT_STATUS: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "GetPortStatus wIndex = 0x%04x FLAGS=0x%08x\n", ++ wIndex, dwc_otg_hcd->flags.d32); ++ if (!wIndex || wIndex > 1) ++ goto error; ++ ++ port_status = 0; ++ ++ if (dwc_otg_hcd->flags.b.port_connect_status_change) ++ port_status |= (1 << UHF_C_PORT_CONNECTION); ++ ++ if (dwc_otg_hcd->flags.b.port_enable_change) ++ port_status |= (1 << UHF_C_PORT_ENABLE); ++ ++ if (dwc_otg_hcd->flags.b.port_suspend_change) ++ port_status |= (1 << UHF_C_PORT_SUSPEND); ++ ++ if (dwc_otg_hcd->flags.b.port_l1_change) ++ port_status |= (1 << UHF_C_PORT_L1); ++ ++ if (dwc_otg_hcd->flags.b.port_reset_change) { ++ port_status |= (1 << UHF_C_PORT_RESET); ++ } ++ ++ if (dwc_otg_hcd->flags.b.port_over_current_change) { ++ DWC_WARN("Overcurrent change detected\n"); ++ port_status |= (1 << UHF_C_PORT_OVER_CURRENT); ++ } ++ ++ if (!dwc_otg_hcd->flags.b.port_connect_status) { ++ /* ++ * The port is disconnected, which means the core is ++ * either in device mode or it soon will be. Just ++ * return 0's for the remainder of the port status ++ * since the port register can't be read if the core ++ * is in device mode. ++ */ ++ *((__le32 *) buf) = dwc_cpu_to_le32(&port_status); ++ break; ++ } ++ ++ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); ++ DWC_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32); ++ ++ if (hprt0.b.prtconnsts) ++ port_status |= (1 << UHF_PORT_CONNECTION); ++ ++ if (hprt0.b.prtena) ++ port_status |= (1 << UHF_PORT_ENABLE); ++ ++ if (hprt0.b.prtsusp) ++ port_status |= (1 << UHF_PORT_SUSPEND); ++ ++ if (hprt0.b.prtovrcurract) ++ port_status |= (1 << UHF_PORT_OVER_CURRENT); ++ ++ if (hprt0.b.prtrst) ++ port_status |= (1 << UHF_PORT_RESET); ++ ++ if (hprt0.b.prtpwr) ++ port_status |= (1 << UHF_PORT_POWER); ++ ++ if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) ++ port_status |= (1 << UHF_PORT_HIGH_SPEED); ++ else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED) ++ port_status |= (1 << UHF_PORT_LOW_SPEED); ++ ++ if (hprt0.b.prttstctl) ++ port_status |= (1 << UHF_PORT_TEST); ++ if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) { ++ port_status |= (1 << UHF_PORT_L1); ++ } ++ /* ++ For Synopsys HW emulation of Power down wkup_control asserts the ++ hreset_n and prst_n on suspned. This causes the HPRT0 to be zero. ++ We intentionally tell the software that port is in L2Suspend state. ++ Only for STE. ++ */ ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ port_status |= (1 << UHF_PORT_SUSPEND); ++ } ++ /* USB_PORT_FEAT_INDICATOR unsupported always 0 */ ++ ++ *((__le32 *) buf) = dwc_cpu_to_le32(&port_status); ++ ++ break; ++ case UCR_SET_HUB_FEATURE: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "SetHubFeature\n"); ++ /* No HUB features supported */ ++ break; ++ case UCR_SET_PORT_FEATURE: ++ if (wValue != UHF_PORT_TEST && (!wIndex || wIndex > 1)) ++ goto error; ++ ++ if (!dwc_otg_hcd->flags.b.port_connect_status) { ++ /* ++ * The port is disconnected, which means the core is ++ * either in device mode or it soon will be. Just ++ * return without doing anything since the port ++ * register can't be written if the core is in device ++ * mode. ++ */ ++ break; ++ } ++ ++ switch (wValue) { ++ case UHF_PORT_SUSPEND: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_SUSPEND\n"); ++ if (dwc_otg_hcd_otg_port(dwc_otg_hcd) != wIndex) { ++ goto error; ++ } ++ if (core_if->power_down == 2) { ++ int timeout = 300; ++ dwc_irqflags_t flags; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++#ifdef DWC_DEV_SRPCAP ++ int32_t otg_cap_param = core_if->core_params->otg_cap; ++#endif ++ DWC_PRINTF("Preparing for complete power-off\n"); ++ ++ /* Save registers before hibernation */ ++ dwc_otg_save_global_regs(core_if); ++ dwc_otg_save_host_regs(core_if); ++ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 1; ++ hprt0.b.prtena = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ /* Spin hprt0.b.prtsusp to became 1 */ ++ do { ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ if (hprt0.b.prtsusp) { ++ break; ++ } ++ dwc_mdelay(1); ++ } while (--timeout); ++ if (!timeout) { ++ DWC_WARN("Suspend wasn't genereted\n"); ++ } ++ dwc_udelay(10); ++ ++ /* ++ * We need to disable interrupts to prevent servicing of any IRQ ++ * during going to hibernation ++ */ ++ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); ++ core_if->lx_state = DWC_OTG_L2; ++#ifdef DWC_DEV_SRPCAP ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 0; ++ hprt0.b.prtena = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, ++ hprt0.d32); ++#endif ++ gusbcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs-> ++ gusbcfg); ++ if (gusbcfg.b.ulpi_utmi_sel == 1) { ++ /* ULPI interface */ ++ /* Suspend the Phy Clock */ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ dwc_udelay(10); ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } else { ++ /* UTMI+ Interface */ ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ dwc_udelay(10); ++ } ++#ifdef DWC_DEV_SRPCAP ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++#endif ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ gpwrdn.d32 = 0; ++#ifdef DWC_DEV_SRPCAP ++ gpwrdn.b.srp_det_msk = 1; ++#endif ++ gpwrdn.b.disconn_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ gpwrdn.b.sts_chngint_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Enable Power Down Clamp and all interrupts in GPWRDN */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Switch off VDD */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++#ifdef DWC_DEV_SRPCAP ++ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) ++ { ++ core_if->pwron_timer_started = 1; ++ DWC_TIMER_SCHEDULE(core_if->pwron_timer, 6000 /* 6 secs */ ); ++ } ++#endif ++ /* Save gpwrdn register for further usage if stschng interrupt */ ++ core_if->gr_backup->gpwrdn_local = ++ DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ /* Set flag to indicate that we are in hibernation */ ++ core_if->hibernation_suspend = 1; ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock,flags); ++ ++ DWC_PRINTF("Host hibernation completed\n"); ++ // Exit from case statement ++ break; ++ ++ } ++ if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex && ++ dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gotgctl.b.hstsethnpen = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gotgctl, 0, gotgctl.d32); ++ core_if->op_state = A_SUSPEND; ++ } ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ { ++ dwc_irqflags_t flags; ++ /* Update lx_state */ ++ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); ++ core_if->lx_state = DWC_OTG_L2; ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); ++ } ++ /* Suspend the Phy Clock */ ++ if (core_if->otg_ver == 0) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ dwc_udelay(10); ++ } ++ ++ /* For HNP the bus must be suspended for at least 200ms. */ ++ if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) { ++ if (core_if->otg_ver) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ } ++ dwc_mdelay(200); ++ } ++ ++ break; ++ case UHF_PORT_POWER: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_POWER\n"); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ break; ++ case UHF_PORT_RESET: ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ /* If we are going to exit from Hibernated ++ * state via USB RESET. ++ */ ++ dwc_otg_host_hibernation_restore(core_if, 0, 1); ++ } else { ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ ++ DWC_DEBUGPL(DBG_HCD, ++ "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_RESET\n"); ++ { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ pcgcctl.b.enbl_sleep_gating = 1; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ DWC_WRITE_REG32(core_if->pcgcctl, 0); ++ } ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ { ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ if (lpmcfg.b.prt_sleep_sts) { ++ lpmcfg.b.en_utmi_sleep = 0; ++ lpmcfg.b.hird_thres &= (~(1 << 4)); ++ DWC_WRITE_REG32 ++ (&core_if->core_global_regs->glpmcfg, ++ lpmcfg.d32); ++ dwc_mdelay(1); ++ } ++ } ++#endif ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ /* Clear suspend bit if resetting from suspended state. */ ++ hprt0.b.prtsusp = 0; ++ /* When B-Host the Port reset bit is set in ++ * the Start HCD Callback function, so that ++ * the reset is started within 1ms of the HNP ++ * success interrupt. */ ++ if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) { ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtrst = 1; ++ DWC_PRINTF("Indeed it is in host mode hprt0 = %08x\n",hprt0.d32); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, ++ hprt0.d32); ++ } ++ /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */ ++ dwc_mdelay(60); ++ hprt0.b.prtrst = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ core_if->lx_state = DWC_OTG_L0; /* Now back to the on state */ ++ } ++ break; ++#ifdef DWC_HS_ELECT_TST ++ case UHF_PORT_TEST: ++ { ++ uint32_t t; ++ gintmsk_data_t gintmsk; ++ ++ t = (wIndex >> 8); /* MSB wIndex USB */ ++ DWC_DEBUGPL(DBG_HCD, ++ "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_TEST %d\n", ++ t); ++ DWC_WARN("USB_PORT_FEAT_TEST %d\n", t); ++ if (t < 6) { ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prttstctl = t; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, ++ hprt0.d32); ++ } else { ++ /* Setup global vars with reg addresses (quick and ++ * dirty hack, should be cleaned up) ++ */ ++ global_regs = core_if->core_global_regs; ++ hc_global_regs = ++ core_if->host_if->host_global_regs; ++ hc_regs = ++ (dwc_otg_hc_regs_t *) ((char *) ++ global_regs + ++ 0x500); ++ data_fifo = ++ (uint32_t *) ((char *)global_regs + ++ 0x1000); ++ ++ if (t == 6) { /* HS_HOST_PORT_SUSPEND_RESUME */ ++ /* Save current interrupt mask */ ++ gintmsk.d32 = ++ DWC_READ_REG32 ++ (&global_regs->gintmsk); ++ ++ /* Disable all interrupts while we muck with ++ * the hardware directly ++ */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* 15 second delay per the test spec */ ++ dwc_mdelay(15000); ++ ++ /* Drive suspend on the root port */ ++ hprt0.d32 = ++ dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 1; ++ hprt0.b.prtres = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* 15 second delay per the test spec */ ++ dwc_mdelay(15000); ++ ++ /* Drive resume on the root port */ ++ hprt0.d32 = ++ dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 0; ++ hprt0.b.prtres = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ dwc_mdelay(100); ++ ++ /* Clear the resume bit */ ++ hprt0.b.prtres = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* Restore interrupts */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32); ++ } else if (t == 7) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */ ++ /* Save current interrupt mask */ ++ gintmsk.d32 = ++ DWC_READ_REG32 ++ (&global_regs->gintmsk); ++ ++ /* Disable all interrupts while we muck with ++ * the hardware directly ++ */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* 15 second delay per the test spec */ ++ dwc_mdelay(15000); ++ ++ /* Send the Setup packet */ ++ do_setup(); ++ ++ /* 15 second delay so nothing else happens for awhile */ ++ dwc_mdelay(15000); ++ ++ /* Restore interrupts */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32); ++ } else if (t == 8) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */ ++ /* Save current interrupt mask */ ++ gintmsk.d32 = ++ DWC_READ_REG32 ++ (&global_regs->gintmsk); ++ ++ /* Disable all interrupts while we muck with ++ * the hardware directly ++ */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* Send the Setup packet */ ++ do_setup(); ++ ++ /* 15 second delay so nothing else happens for awhile */ ++ dwc_mdelay(15000); ++ ++ /* Send the In and Ack packets */ ++ do_in_ack(); ++ ++ /* 15 second delay so nothing else happens for awhile */ ++ dwc_mdelay(15000); ++ ++ /* Restore interrupts */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32); ++ } ++ } ++ break; ++ } ++#endif /* DWC_HS_ELECT_TST */ ++ ++ case UHF_PORT_INDICATOR: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_INDICATOR\n"); ++ /* Not supported */ ++ break; ++ default: ++ retval = -DWC_E_INVALID; ++ DWC_ERROR("DWC OTG HCD - " ++ "SetPortFeature request %xh " ++ "unknown or unsupported\n", wValue); ++ break; ++ } ++ break; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ case UCR_SET_AND_TEST_PORT_FEATURE: ++ if (wValue != UHF_PORT_L1) { ++ goto error; ++ } ++ { ++ int portnum, hird, devaddr, remwake; ++ glpmcfg_data_t lpmcfg; ++ uint32_t time_usecs; ++ gintsts_data_t gintsts; ++ gintmsk_data_t gintmsk; ++ ++ if (!dwc_otg_get_param_lpm_enable(core_if)) { ++ goto error; ++ } ++ if (wValue != UHF_PORT_L1 || wLength != 1) { ++ goto error; ++ } ++ /* Check if the port currently is in SLEEP state */ ++ lpmcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ if (lpmcfg.b.prt_sleep_sts) { ++ DWC_INFO("Port is already in sleep mode\n"); ++ buf[0] = 0; /* Return success */ ++ break; ++ } ++ ++ portnum = wIndex & 0xf; ++ hird = (wIndex >> 4) & 0xf; ++ devaddr = (wIndex >> 8) & 0x7f; ++ remwake = (wIndex >> 15); ++ ++ if (portnum != 1) { ++ retval = -DWC_E_INVALID; ++ DWC_WARN ++ ("Wrong port number(%d) in SetandTestPortFeature request\n", ++ portnum); ++ break; ++ } ++ ++ DWC_PRINTF ++ ("SetandTestPortFeature request: portnum = %d, hird = %d, devaddr = %d, rewake = %d\n", ++ portnum, hird, devaddr, remwake); ++ /* Disable LPM interrupt */ ++ gintmsk.d32 = 0; ++ gintmsk.b.lpmtranrcvd = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, ++ gintmsk.d32, 0); ++ ++ if (dwc_otg_hcd_send_lpm ++ (dwc_otg_hcd, devaddr, hird, remwake)) { ++ retval = -DWC_E_INVALID; ++ break; ++ } ++ ++ time_usecs = 10 * (lpmcfg.b.retry_count + 1); ++ /* We will consider timeout if time_usecs microseconds pass, ++ * and we don't receive LPM transaction status. ++ * After receiving non-error responce(ACK/NYET/STALL) from device, ++ * core will set lpmtranrcvd bit. ++ */ ++ do { ++ gintsts.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (gintsts.b.lpmtranrcvd) { ++ break; ++ } ++ dwc_udelay(1); ++ } while (--time_usecs); ++ /* lpm_int bit will be cleared in LPM interrupt handler */ ++ ++ /* Now fill status ++ * 0x00 - Success ++ * 0x10 - NYET ++ * 0x11 - Timeout ++ */ ++ if (!gintsts.b.lpmtranrcvd) { ++ buf[0] = 0x3; /* Completion code is Timeout */ ++ dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd); ++ } else { ++ lpmcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ if (lpmcfg.b.lpm_resp == 0x3) { ++ /* ACK responce from the device */ ++ buf[0] = 0x00; /* Success */ ++ } else if (lpmcfg.b.lpm_resp == 0x2) { ++ /* NYET responce from the device */ ++ buf[0] = 0x2; ++ } else { ++ /* Otherwise responce with Timeout */ ++ buf[0] = 0x3; ++ } ++ } ++ DWC_PRINTF("Device responce to LPM trans is %x\n", ++ lpmcfg.b.lpm_resp); ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, ++ gintmsk.d32); ++ ++ break; ++ } ++#endif /* CONFIG_USB_DWC_OTG_LPM */ ++ default: ++error: ++ retval = -DWC_E_INVALID; ++ DWC_WARN("DWC OTG HCD - " ++ "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n", ++ typeReq, wIndex, wValue); ++ break; ++ } ++ ++ return retval; ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++/** Returns index of host channel to perform LPM transaction. */ ++int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, uint8_t devaddr) ++{ ++ dwc_otg_core_if_t *core_if = hcd->core_if; ++ dwc_hc_t *hc; ++ hcchar_data_t hcchar; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ if (DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { ++ DWC_PRINTF("No free channel to select for LPM transaction\n"); ++ return -1; ++ } ++ ++ hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list); ++ ++ /* Mask host channel interrupts. */ ++ gintmsk.b.hcintr = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0); ++ ++ /* Fill fields that core needs for LPM transaction */ ++ hcchar.b.devaddr = devaddr; ++ hcchar.b.epnum = 0; ++ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; ++ hcchar.b.mps = 64; ++ hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW); ++ hcchar.b.epdir = 0; /* OUT */ ++ DWC_WRITE_REG32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar, ++ hcchar.d32); ++ ++ /* Remove the host channel from the free list. */ ++ DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry); ++ ++ DWC_PRINTF("hcnum = %d devaddr = %d\n", hc->hc_num, devaddr); ++ ++ return hc->hc_num; ++} ++ ++/** Release hc after performing LPM transaction */ ++void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd) ++{ ++ dwc_hc_t *hc; ++ glpmcfg_data_t lpmcfg; ++ uint8_t hc_num; ++ ++ lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg); ++ hc_num = lpmcfg.b.lpm_chan_index; ++ ++ hc = hcd->hc_ptr_array[hc_num]; ++ ++ DWC_PRINTF("Freeing channel %d after LPM\n", hc_num); ++ /* Return host channel to free list */ ++ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); ++} ++ ++int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, uint8_t hird, ++ uint8_t bRemoteWake) ++{ ++ glpmcfg_data_t lpmcfg; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ int channel; ++ ++ channel = dwc_otg_hcd_get_hc_for_lpm_tran(hcd, devaddr); ++ if (channel < 0) { ++ return channel; ++ } ++ ++ pcgcctl.b.enbl_sleep_gating = 1; ++ DWC_MODIFY_REG32(hcd->core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ /* Read LPM config register */ ++ lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg); ++ ++ /* Program LPM transaction fields */ ++ lpmcfg.b.rem_wkup_en = bRemoteWake; ++ lpmcfg.b.hird = hird; ++ ++ if(dwc_otg_get_param_besl_enable(hcd->core_if)) { ++ lpmcfg.b.hird_thres = 0x16; ++ lpmcfg.b.en_besl = 1; ++ } else { ++ lpmcfg.b.hird_thres = 0x1c; ++ } ++ ++ lpmcfg.b.lpm_chan_index = channel; ++ lpmcfg.b.en_utmi_sleep = 1; ++ /* Program LPM config register */ ++ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++ ++ /* Send LPM transaction */ ++ lpmcfg.b.send_lpm = 1; ++ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++ ++ return 0; ++} ++ ++#endif /* CONFIG_USB_DWC_OTG_LPM */ ++ ++int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port) ++{ ++ int retval; ++ ++ if (port != 1) { ++ return -DWC_E_INVALID; ++ } ++ ++ retval = (hcd->flags.b.port_connect_status_change || ++ hcd->flags.b.port_reset_change || ++ hcd->flags.b.port_enable_change || ++ hcd->flags.b.port_suspend_change || ++ hcd->flags.b.port_over_current_change); ++#ifdef DEBUG ++ if (retval) { ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:" ++ " Root port status changed\n"); ++ DWC_DEBUGPL(DBG_HCDV, " port_connect_status_change: %d\n", ++ hcd->flags.b.port_connect_status_change); ++ DWC_DEBUGPL(DBG_HCDV, " port_reset_change: %d\n", ++ hcd->flags.b.port_reset_change); ++ DWC_DEBUGPL(DBG_HCDV, " port_enable_change: %d\n", ++ hcd->flags.b.port_enable_change); ++ DWC_DEBUGPL(DBG_HCDV, " port_suspend_change: %d\n", ++ hcd->flags.b.port_suspend_change); ++ DWC_DEBUGPL(DBG_HCDV, " port_over_current_change: %d\n", ++ hcd->flags.b.port_over_current_change); ++ } ++#endif ++ return retval; ++} ++ ++int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ hfnum_data_t hfnum; ++ hfnum.d32 = ++ DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs-> ++ hfnum); ++ ++#ifdef DEBUG_SOF ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n", ++ hfnum.b.frnum); ++#endif ++ return hfnum.b.frnum; ++} ++ ++int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd, ++ struct dwc_otg_hcd_function_ops *fops) ++{ ++ int retval = 0; ++ hprt0_data_t hprt0; ++ ++ hcd->fops = fops; ++ if (!dwc_otg_is_device_mode(hcd->core_if) && ++ (!hcd->core_if->adp_enable || hcd->core_if->adp.adp_started)) { ++ dwc_otg_hcd_reinit(hcd); ++ } else { ++ if (hcd->core_if->adp_enable) { ++ /* Clear any interrupt pending in the HPRT, sometimes ++ * Port Connect Detected is not being cleared*/ ++ hprt0.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0); ++ DWC_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32); ++ } ++ retval = -DWC_E_NO_DEVICE; ++ } ++ ++ return retval; ++} ++ ++void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd) ++{ ++ return hcd->priv; ++} ++ ++void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data) ++{ ++ hcd->priv = priv_data; ++} ++ ++uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd) ++{ ++ return hcd->otg_port; ++} ++ ++uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd) ++{ ++ uint32_t is_b_host; ++ if (hcd->core_if->op_state == B_HOST) { ++ is_b_host = 1; ++ } else { ++ is_b_host = 0; ++ } ++ ++ return is_b_host; ++} ++ ++dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd, ++ int iso_desc_count, int atomic_alloc) ++{ ++ dwc_otg_hcd_urb_t *dwc_otg_urb; ++ uint32_t size; ++ ++ size = ++ sizeof(*dwc_otg_urb) + ++ iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc); ++ if (atomic_alloc) ++ dwc_otg_urb = DWC_ALLOC_ATOMIC(size); ++ else ++ dwc_otg_urb = DWC_ALLOC(size); ++ ++ dwc_otg_urb->packet_count = iso_desc_count; ++ ++ return dwc_otg_urb; ++} ++ ++void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * dwc_otg_urb, ++ uint8_t dev_addr, uint8_t ep_num, ++ uint8_t ep_type, uint8_t ep_dir, uint16_t mps) ++{ ++ dwc_otg_hcd_fill_pipe(&dwc_otg_urb->pipe_info, dev_addr, ep_num, ++ ep_type, ep_dir, mps); ++} ++ ++void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * dwc_otg_urb, ++ void *urb_handle, void *buf, dwc_dma_t dma, ++ uint32_t buflen, void *setup_packet, ++ dwc_dma_t setup_dma, uint32_t flags, ++ uint16_t interval) ++{ ++ dwc_otg_urb->priv = urb_handle; ++ dwc_otg_urb->buf = buf; ++ dwc_otg_urb->dma = dma; ++ dwc_otg_urb->length = buflen; ++ dwc_otg_urb->setup_packet = setup_packet; ++ dwc_otg_urb->setup_dma = setup_dma; ++ dwc_otg_urb->flags = flags; ++ dwc_otg_urb->interval = interval; ++ dwc_otg_urb->status = -DWC_E_IN_PROGRESS; ++} ++ ++uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb) ++{ ++ return dwc_otg_urb->status; ++} ++ ++uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * dwc_otg_urb) ++{ ++ return dwc_otg_urb->actual_length; ++} ++ ++uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * dwc_otg_urb) ++{ ++ return dwc_otg_urb->error_count; ++} ++ ++void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb, ++ int desc_num, uint32_t offset, ++ uint32_t length) ++{ ++ dwc_otg_urb->iso_descs[desc_num].offset = offset; ++ dwc_otg_urb->iso_descs[desc_num].length = length; ++} ++ ++uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * dwc_otg_urb, ++ int desc_num) ++{ ++ return dwc_otg_urb->iso_descs[desc_num].status; ++} ++ ++uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t * ++ dwc_otg_urb, int desc_num) ++{ ++ return dwc_otg_urb->iso_descs[desc_num].actual_length; ++} ++ ++int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, void *ep_handle) ++{ ++ int allocated = 0; ++ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; ++ ++ if (qh) { ++ if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) { ++ allocated = 1; ++ } ++ } ++ return allocated; ++} ++ ++int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle) ++{ ++ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; ++ int freed = 0; ++ DWC_ASSERT(qh, "qh is not allocated\n"); ++ ++ if (DWC_LIST_EMPTY(&qh->qh_list_entry)) { ++ freed = 1; ++ } ++ ++ return freed; ++} ++ ++uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, void *ep_handle) ++{ ++ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; ++ DWC_ASSERT(qh, "qh is not allocated\n"); ++ return qh->usecs; ++} ++ ++void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd) ++{ ++#ifdef DEBUG ++ int num_channels; ++ int i; ++ gnptxsts_data_t np_tx_status; ++ hptxsts_data_t p_tx_status; ++ ++ num_channels = hcd->core_if->core_params->host_channels; ++ DWC_PRINTF("\n"); ++ DWC_PRINTF ++ ("************************************************************\n"); ++ DWC_PRINTF("HCD State:\n"); ++ DWC_PRINTF(" Num channels: %d\n", num_channels); ++ for (i = 0; i < num_channels; i++) { ++ dwc_hc_t *hc = hcd->hc_ptr_array[i]; ++ DWC_PRINTF(" Channel %d:\n", i); ++ DWC_PRINTF(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n", ++ hc->dev_addr, hc->ep_num, hc->ep_is_in); ++ DWC_PRINTF(" speed: %d\n", hc->speed); ++ DWC_PRINTF(" ep_type: %d\n", hc->ep_type); ++ DWC_PRINTF(" max_packet: %d\n", hc->max_packet); ++ DWC_PRINTF(" data_pid_start: %d\n", hc->data_pid_start); ++ DWC_PRINTF(" multi_count: %d\n", hc->multi_count); ++ DWC_PRINTF(" xfer_started: %d\n", hc->xfer_started); ++ DWC_PRINTF(" xfer_buff: %p\n", hc->xfer_buff); ++ DWC_PRINTF(" xfer_len: %d\n", hc->xfer_len); ++ DWC_PRINTF(" xfer_count: %d\n", hc->xfer_count); ++ DWC_PRINTF(" halt_on_queue: %d\n", hc->halt_on_queue); ++ DWC_PRINTF(" halt_pending: %d\n", hc->halt_pending); ++ DWC_PRINTF(" halt_status: %d\n", hc->halt_status); ++ DWC_PRINTF(" do_split: %d\n", hc->do_split); ++ DWC_PRINTF(" complete_split: %d\n", hc->complete_split); ++ DWC_PRINTF(" hub_addr: %d\n", hc->hub_addr); ++ DWC_PRINTF(" port_addr: %d\n", hc->port_addr); ++ DWC_PRINTF(" xact_pos: %d\n", hc->xact_pos); ++ DWC_PRINTF(" requests: %d\n", hc->requests); ++ DWC_PRINTF(" qh: %p\n", hc->qh); ++ if (hc->xfer_started) { ++ hfnum_data_t hfnum; ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; ++ hfnum.d32 = ++ DWC_READ_REG32(&hcd->core_if-> ++ host_if->host_global_regs->hfnum); ++ hcchar.d32 = ++ DWC_READ_REG32(&hcd->core_if->host_if-> ++ hc_regs[i]->hcchar); ++ hctsiz.d32 = ++ DWC_READ_REG32(&hcd->core_if->host_if-> ++ hc_regs[i]->hctsiz); ++ hcint.d32 = ++ DWC_READ_REG32(&hcd->core_if->host_if-> ++ hc_regs[i]->hcint); ++ hcintmsk.d32 = ++ DWC_READ_REG32(&hcd->core_if->host_if-> ++ hc_regs[i]->hcintmsk); ++ DWC_PRINTF(" hfnum: 0x%08x\n", hfnum.d32); ++ DWC_PRINTF(" hcchar: 0x%08x\n", hcchar.d32); ++ DWC_PRINTF(" hctsiz: 0x%08x\n", hctsiz.d32); ++ DWC_PRINTF(" hcint: 0x%08x\n", hcint.d32); ++ DWC_PRINTF(" hcintmsk: 0x%08x\n", hcintmsk.d32); ++ } ++ if (hc->xfer_started && hc->qh) { ++ dwc_otg_qtd_t *qtd; ++ dwc_otg_hcd_urb_t *urb; ++ ++ DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list, qtd_list_entry) { ++ if (!qtd->in_process) ++ break; ++ ++ urb = qtd->urb; ++ DWC_PRINTF(" URB Info:\n"); ++ DWC_PRINTF(" qtd: %p, urb: %p\n", qtd, urb); ++ if (urb) { ++ DWC_PRINTF(" Dev: %d, EP: %d %s\n", ++ dwc_otg_hcd_get_dev_addr(&urb-> ++ pipe_info), ++ dwc_otg_hcd_get_ep_num(&urb-> ++ pipe_info), ++ dwc_otg_hcd_is_pipe_in(&urb-> ++ pipe_info) ? ++ "IN" : "OUT"); ++ DWC_PRINTF(" Max packet size: %d\n", ++ dwc_otg_hcd_get_mps(&urb-> ++ pipe_info)); ++ DWC_PRINTF(" transfer_buffer: %p\n", ++ urb->buf); ++ DWC_PRINTF(" transfer_dma: %p\n", ++ (void *)urb->dma); ++ DWC_PRINTF(" transfer_buffer_length: %d\n", ++ urb->length); ++ DWC_PRINTF(" actual_length: %d\n", ++ urb->actual_length); ++ } ++ } ++ } ++ } ++ DWC_PRINTF(" non_periodic_channels: %d\n", hcd->non_periodic_channels); ++ DWC_PRINTF(" periodic_channels: %d\n", hcd->periodic_channels); ++ DWC_PRINTF(" periodic_usecs: %d\n", hcd->periodic_usecs); ++ np_tx_status.d32 = ++ DWC_READ_REG32(&hcd->core_if->core_global_regs->gnptxsts); ++ DWC_PRINTF(" NP Tx Req Queue Space Avail: %d\n", ++ np_tx_status.b.nptxqspcavail); ++ DWC_PRINTF(" NP Tx FIFO Space Avail: %d\n", ++ np_tx_status.b.nptxfspcavail); ++ p_tx_status.d32 = ++ DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hptxsts); ++ DWC_PRINTF(" P Tx Req Queue Space Avail: %d\n", ++ p_tx_status.b.ptxqspcavail); ++ DWC_PRINTF(" P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail); ++ dwc_otg_hcd_dump_frrem(hcd); ++ dwc_otg_dump_global_registers(hcd->core_if); ++ dwc_otg_dump_host_registers(hcd->core_if); ++ DWC_PRINTF ++ ("************************************************************\n"); ++ DWC_PRINTF("\n"); ++#endif ++} ++ ++#ifdef DEBUG ++void dwc_print_setup_data(uint8_t * setup) ++{ ++ int i; ++ if (CHK_DEBUG_LEVEL(DBG_HCD)) { ++ DWC_PRINTF("Setup Data = MSB "); ++ for (i = 7; i >= 0; i--) ++ DWC_PRINTF("%02x ", setup[i]); ++ DWC_PRINTF("\n"); ++ DWC_PRINTF(" bmRequestType Tranfer = %s\n", ++ (setup[0] & 0x80) ? "Device-to-Host" : ++ "Host-to-Device"); ++ DWC_PRINTF(" bmRequestType Type = "); ++ switch ((setup[0] & 0x60) >> 5) { ++ case 0: ++ DWC_PRINTF("Standard\n"); ++ break; ++ case 1: ++ DWC_PRINTF("Class\n"); ++ break; ++ case 2: ++ DWC_PRINTF("Vendor\n"); ++ break; ++ case 3: ++ DWC_PRINTF("Reserved\n"); ++ break; ++ } ++ DWC_PRINTF(" bmRequestType Recipient = "); ++ switch (setup[0] & 0x1f) { ++ case 0: ++ DWC_PRINTF("Device\n"); ++ break; ++ case 1: ++ DWC_PRINTF("Interface\n"); ++ break; ++ case 2: ++ DWC_PRINTF("Endpoint\n"); ++ break; ++ case 3: ++ DWC_PRINTF("Other\n"); ++ break; ++ default: ++ DWC_PRINTF("Reserved\n"); ++ break; ++ } ++ DWC_PRINTF(" bRequest = 0x%0x\n", setup[1]); ++ DWC_PRINTF(" wValue = 0x%0x\n", *((uint16_t *) & setup[2])); ++ DWC_PRINTF(" wIndex = 0x%0x\n", *((uint16_t *) & setup[4])); ++ DWC_PRINTF(" wLength = 0x%0x\n\n", *((uint16_t *) & setup[6])); ++ } ++} ++#endif ++ ++void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd) ++{ ++} ++ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd.h +new file mode 100644 +index 0000000..23eea36 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd.h +@@ -0,0 +1,803 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $ ++ * $Revision: #58 $ ++ * $Date: 2011/09/15 $ ++ * $Change: 1846647 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_DEVICE_ONLY ++#ifndef __DWC_HCD_H__ ++#define __DWC_HCD_H__ ++ ++#include "dwc_otg_os_dep.h" ++#include "usb.h" ++#include "dwc_otg_hcd_if.h" ++#include "dwc_otg_core_if.h" ++#include "dwc_list.h" ++#include "dwc_otg_cil.h" ++ ++/** ++ * @file ++ * ++ * This file contains the structures, constants, and interfaces for ++ * the Host Contoller Driver (HCD). ++ * ++ * The Host Controller Driver (HCD) is responsible for translating requests ++ * from the USB Driver into the appropriate actions on the DWC_otg controller. ++ * It isolates the USBD from the specifics of the controller by providing an ++ * API to the USBD. ++ */ ++ ++struct dwc_otg_hcd_pipe_info { ++ uint8_t dev_addr; ++ uint8_t ep_num; ++ uint8_t pipe_type; ++ uint8_t pipe_dir; ++ uint16_t mps; ++}; ++ ++struct dwc_otg_hcd_iso_packet_desc { ++ uint32_t offset; ++ uint32_t length; ++ uint32_t actual_length; ++ uint32_t status; ++}; ++ ++struct dwc_otg_qtd; ++ ++struct dwc_otg_hcd_urb { ++ void *priv; ++ struct dwc_otg_qtd *qtd; ++ void *buf; ++ dwc_dma_t dma; ++ void *setup_packet; ++ dwc_dma_t setup_dma; ++ uint32_t length; ++ uint32_t actual_length; ++ uint32_t status; ++ uint32_t error_count; ++ uint32_t packet_count; ++ uint32_t flags; ++ uint16_t interval; ++ struct dwc_otg_hcd_pipe_info pipe_info; ++ struct dwc_otg_hcd_iso_packet_desc iso_descs[0]; ++}; ++ ++static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe) ++{ ++ return pipe->ep_num; ++} ++ ++static inline uint8_t dwc_otg_hcd_get_pipe_type(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return pipe->pipe_type; ++} ++ ++static inline uint16_t dwc_otg_hcd_get_mps(struct dwc_otg_hcd_pipe_info *pipe) ++{ ++ return pipe->mps; ++} ++ ++static inline uint8_t dwc_otg_hcd_get_dev_addr(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return pipe->dev_addr; ++} ++ ++static inline uint8_t dwc_otg_hcd_is_pipe_isoc(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (pipe->pipe_type == UE_ISOCHRONOUS); ++} ++ ++static inline uint8_t dwc_otg_hcd_is_pipe_int(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (pipe->pipe_type == UE_INTERRUPT); ++} ++ ++static inline uint8_t dwc_otg_hcd_is_pipe_bulk(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (pipe->pipe_type == UE_BULK); ++} ++ ++static inline uint8_t dwc_otg_hcd_is_pipe_control(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (pipe->pipe_type == UE_CONTROL); ++} ++ ++static inline uint8_t dwc_otg_hcd_is_pipe_in(struct dwc_otg_hcd_pipe_info *pipe) ++{ ++ return (pipe->pipe_dir == UE_DIR_IN); ++} ++ ++static inline uint8_t dwc_otg_hcd_is_pipe_out(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (!dwc_otg_hcd_is_pipe_in(pipe)); ++} ++ ++static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe, ++ uint8_t devaddr, uint8_t ep_num, ++ uint8_t pipe_type, uint8_t pipe_dir, ++ uint16_t mps) ++{ ++ pipe->dev_addr = devaddr; ++ pipe->ep_num = ep_num; ++ pipe->pipe_type = pipe_type; ++ pipe->pipe_dir = pipe_dir; ++ pipe->mps = mps; ++} ++ ++/** ++ * Phases for control transfers. ++ */ ++typedef enum dwc_otg_control_phase { ++ DWC_OTG_CONTROL_SETUP, ++ DWC_OTG_CONTROL_DATA, ++ DWC_OTG_CONTROL_STATUS ++} dwc_otg_control_phase_e; ++ ++/** Transaction types. */ ++typedef enum dwc_otg_transaction_type { ++ DWC_OTG_TRANSACTION_NONE, ++ DWC_OTG_TRANSACTION_PERIODIC, ++ DWC_OTG_TRANSACTION_NON_PERIODIC, ++ DWC_OTG_TRANSACTION_ALL ++} dwc_otg_transaction_type_e; ++ ++struct dwc_otg_qh; ++ ++/** ++ * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control, ++ * interrupt, or isochronous transfer. A single QTD is created for each URB ++ * (of one of these types) submitted to the HCD. The transfer associated with ++ * a QTD may require one or multiple transactions. ++ * ++ * A QTD is linked to a Queue Head, which is entered in either the ++ * non-periodic or periodic schedule for execution. When a QTD is chosen for ++ * execution, some or all of its transactions may be executed. After ++ * execution, the state of the QTD is updated. The QTD may be retired if all ++ * its transactions are complete or if an error occurred. Otherwise, it ++ * remains in the schedule so more transactions can be executed later. ++ */ ++typedef struct dwc_otg_qtd { ++ /** ++ * Determines the PID of the next data packet for the data phase of ++ * control transfers. Ignored for other transfer types.
++ * One of the following values: ++ * - DWC_OTG_HC_PID_DATA0 ++ * - DWC_OTG_HC_PID_DATA1 ++ */ ++ uint8_t data_toggle; ++ ++ /** Current phase for control transfers (Setup, Data, or Status). */ ++ dwc_otg_control_phase_e control_phase; ++ ++ /** Keep track of the current split type ++ * for FS/LS endpoints on a HS Hub */ ++ uint8_t complete_split; ++ ++ /** How many bytes transferred during SSPLIT OUT */ ++ uint32_t ssplit_out_xfer_count; ++ ++ /** ++ * Holds the number of bus errors that have occurred for a transaction ++ * within this transfer. ++ */ ++ uint8_t error_count; ++ ++ /** ++ * Index of the next frame descriptor for an isochronous transfer. A ++ * frame descriptor describes the buffer position and length of the ++ * data to be transferred in the next scheduled (micro)frame of an ++ * isochronous transfer. It also holds status for that transaction. ++ * The frame index starts at 0. ++ */ ++ uint16_t isoc_frame_index; ++ ++ /** Position of the ISOC split on full/low speed */ ++ uint8_t isoc_split_pos; ++ ++ /** Position of the ISOC split in the buffer for the current frame */ ++ uint16_t isoc_split_offset; ++ ++ /** URB for this transfer */ ++ struct dwc_otg_hcd_urb *urb; ++ ++ struct dwc_otg_qh *qh; ++ ++ /** This list of QTDs */ ++ DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry; ++ ++ /** Indicates if this QTD is currently processed by HW. */ ++ uint8_t in_process; ++ ++ /** Number of DMA descriptors for this QTD */ ++ uint8_t n_desc; ++ ++ /** ++ * Last activated frame(packet) index. ++ * Used in Descriptor DMA mode only. ++ */ ++ uint16_t isoc_frame_index_last; ++ ++} dwc_otg_qtd_t; ++ ++DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd); ++ ++/** ++ * A Queue Head (QH) holds the static characteristics of an endpoint and ++ * maintains a list of transfers (QTDs) for that endpoint. A QH structure may ++ * be entered in either the non-periodic or periodic schedule. ++ */ ++typedef struct dwc_otg_qh { ++ /** ++ * Endpoint type. ++ * One of the following values: ++ * - UE_CONTROL ++ * - UE_BULK ++ * - UE_INTERRUPT ++ * - UE_ISOCHRONOUS ++ */ ++ uint8_t ep_type; ++ uint8_t ep_is_in; ++ ++ /** wMaxPacketSize Field of Endpoint Descriptor. */ ++ uint16_t maxp; ++ ++ /** ++ * Device speed. ++ * One of the following values: ++ * - DWC_OTG_EP_SPEED_LOW ++ * - DWC_OTG_EP_SPEED_FULL ++ * - DWC_OTG_EP_SPEED_HIGH ++ */ ++ uint8_t dev_speed; ++ ++ /** ++ * Determines the PID of the next data packet for non-control ++ * transfers. Ignored for control transfers.
++ * One of the following values: ++ * - DWC_OTG_HC_PID_DATA0 ++ * - DWC_OTG_HC_PID_DATA1 ++ */ ++ uint8_t data_toggle; ++ ++ /** Ping state if 1. */ ++ uint8_t ping_state; ++ ++ /** ++ * List of QTDs for this QH. ++ */ ++ struct dwc_otg_qtd_list qtd_list; ++ ++ /** Host channel currently processing transfers for this QH. */ ++ struct dwc_hc *channel; ++ ++ /** Full/low speed endpoint on high-speed hub requires split. */ ++ uint8_t do_split; ++ ++ /** @name Periodic schedule information */ ++ /** @{ */ ++ ++ /** Bandwidth in microseconds per (micro)frame. */ ++ uint16_t usecs; ++ ++ /** Interval between transfers in (micro)frames. */ ++ uint16_t interval; ++ ++ /** ++ * (micro)frame to initialize a periodic transfer. The transfer ++ * executes in the following (micro)frame. ++ */ ++ uint16_t sched_frame; ++ ++ /** (micro)frame at which last start split was initialized. */ ++ uint16_t start_split_frame; ++ ++ /** @} */ ++ ++ /** ++ * Used instead of original buffer if ++ * it(physical address) is not dword-aligned. ++ */ ++ uint8_t *dw_align_buf; ++ dwc_dma_t dw_align_buf_dma; ++ ++ /** Entry for QH in either the periodic or non-periodic schedule. */ ++ dwc_list_link_t qh_list_entry; ++ ++ /** @name Descriptor DMA support */ ++ /** @{ */ ++ ++ /** Descriptor List. */ ++ dwc_otg_host_dma_desc_t *desc_list; ++ ++ /** Descriptor List physical address. */ ++ dwc_dma_t desc_list_dma; ++ ++ /** ++ * Xfer Bytes array. ++ * Each element corresponds to a descriptor and indicates ++ * original XferSize size value for the descriptor. ++ */ ++ uint32_t *n_bytes; ++ ++ /** Actual number of transfer descriptors in a list. */ ++ uint16_t ntd; ++ ++ /** First activated isochronous transfer descriptor index. */ ++ uint8_t td_first; ++ /** Last activated isochronous transfer descriptor index. */ ++ uint8_t td_last; ++ ++ /** @} */ ++ ++} dwc_otg_qh_t; ++ ++DWC_CIRCLEQ_HEAD(hc_list, dwc_hc); ++ ++/** ++ * This structure holds the state of the HCD, including the non-periodic and ++ * periodic schedules. ++ */ ++struct dwc_otg_hcd { ++ /** The DWC otg device pointer */ ++ struct dwc_otg_device *otg_dev; ++ /** DWC OTG Core Interface Layer */ ++ dwc_otg_core_if_t *core_if; ++ ++ /** Function HCD driver callbacks */ ++ struct dwc_otg_hcd_function_ops *fops; ++ ++ /** Internal DWC HCD Flags */ ++ volatile union dwc_otg_hcd_internal_flags { ++ uint32_t d32; ++ struct { ++ unsigned port_connect_status_change:1; ++ unsigned port_connect_status:1; ++ unsigned port_reset_change:1; ++ unsigned port_enable_change:1; ++ unsigned port_suspend_change:1; ++ unsigned port_over_current_change:1; ++ unsigned port_l1_change:1; ++ unsigned reserved:26; ++ } b; ++ } flags; ++ ++ /** ++ * Inactive items in the non-periodic schedule. This is a list of ++ * Queue Heads. Transfers associated with these Queue Heads are not ++ * currently assigned to a host channel. ++ */ ++ dwc_list_link_t non_periodic_sched_inactive; ++ ++ /** ++ * Active items in the non-periodic schedule. This is a list of ++ * Queue Heads. Transfers associated with these Queue Heads are ++ * currently assigned to a host channel. ++ */ ++ dwc_list_link_t non_periodic_sched_active; ++ ++ /** ++ * Pointer to the next Queue Head to process in the active ++ * non-periodic schedule. ++ */ ++ dwc_list_link_t *non_periodic_qh_ptr; ++ ++ /** ++ * Inactive items in the periodic schedule. This is a list of QHs for ++ * periodic transfers that are _not_ scheduled for the next frame. ++ * Each QH in the list has an interval counter that determines when it ++ * needs to be scheduled for execution. This scheduling mechanism ++ * allows only a simple calculation for periodic bandwidth used (i.e. ++ * must assume that all periodic transfers may need to execute in the ++ * same frame). However, it greatly simplifies scheduling and should ++ * be sufficient for the vast majority of OTG hosts, which need to ++ * connect to a small number of peripherals at one time. ++ * ++ * Items move from this list to periodic_sched_ready when the QH ++ * interval counter is 0 at SOF. ++ */ ++ dwc_list_link_t periodic_sched_inactive; ++ ++ /** ++ * List of periodic QHs that are ready for execution in the next ++ * frame, but have not yet been assigned to host channels. ++ * ++ * Items move from this list to periodic_sched_assigned as host ++ * channels become available during the current frame. ++ */ ++ dwc_list_link_t periodic_sched_ready; ++ ++ /** ++ * List of periodic QHs to be executed in the next frame that are ++ * assigned to host channels. ++ * ++ * Items move from this list to periodic_sched_queued as the ++ * transactions for the QH are queued to the DWC_otg controller. ++ */ ++ dwc_list_link_t periodic_sched_assigned; ++ ++ /** ++ * List of periodic QHs that have been queued for execution. ++ * ++ * Items move from this list to either periodic_sched_inactive or ++ * periodic_sched_ready when the channel associated with the transfer ++ * is released. If the interval for the QH is 1, the item moves to ++ * periodic_sched_ready because it must be rescheduled for the next ++ * frame. Otherwise, the item moves to periodic_sched_inactive. ++ */ ++ dwc_list_link_t periodic_sched_queued; ++ ++ /** ++ * Total bandwidth claimed so far for periodic transfers. This value ++ * is in microseconds per (micro)frame. The assumption is that all ++ * periodic transfers may occur in the same (micro)frame. ++ */ ++ uint16_t periodic_usecs; ++ ++ /** ++ * Frame number read from the core at SOF. The value ranges from 0 to ++ * DWC_HFNUM_MAX_FRNUM. ++ */ ++ uint16_t frame_number; ++ ++ /** ++ * Count of periodic QHs, if using several eps. For SOF enable/disable. ++ */ ++ uint16_t periodic_qh_count; ++ ++ /** ++ * Free host channels in the controller. This is a list of ++ * dwc_hc_t items. ++ */ ++ struct hc_list free_hc_list; ++ /** ++ * Number of host channels assigned to periodic transfers. Currently ++ * assuming that there is a dedicated host channel for each periodic ++ * transaction and at least one host channel available for ++ * non-periodic transactions. ++ */ ++ int periodic_channels; ++ ++ /** ++ * Number of host channels assigned to non-periodic transfers. ++ */ ++ int non_periodic_channels; ++ ++ /** ++ * Array of pointers to the host channel descriptors. Allows accessing ++ * a host channel descriptor given the host channel number. This is ++ * useful in interrupt handlers. ++ */ ++ struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS]; ++ ++ /** ++ * Buffer to use for any data received during the status phase of a ++ * control transfer. Normally no data is transferred during the status ++ * phase. This buffer is used as a bit bucket. ++ */ ++ uint8_t *status_buf; ++ ++ /** ++ * DMA address for status_buf. ++ */ ++ dma_addr_t status_buf_dma; ++#define DWC_OTG_HCD_STATUS_BUF_SIZE 64 ++ ++ /** ++ * Connection timer. An OTG host must display a message if the device ++ * does not connect. Started when the VBus power is turned on via ++ * sysfs attribute "buspower". ++ */ ++ dwc_timer_t *conn_timer; ++ ++ /* Tasket to do a reset */ ++ dwc_tasklet_t *reset_tasklet; ++ ++ /* */ ++ dwc_spinlock_t *lock; ++ ++ /** ++ * Private data that could be used by OS wrapper. ++ */ ++ void *priv; ++ ++ uint8_t otg_port; ++ ++ /** Frame List */ ++ uint32_t *frame_list; ++ ++ /** Frame List DMA address */ ++ dma_addr_t frame_list_dma; ++ ++#ifdef DEBUG ++ uint32_t frrem_samples; ++ uint64_t frrem_accum; ++ ++ uint32_t hfnum_7_samples_a; ++ uint64_t hfnum_7_frrem_accum_a; ++ uint32_t hfnum_0_samples_a; ++ uint64_t hfnum_0_frrem_accum_a; ++ uint32_t hfnum_other_samples_a; ++ uint64_t hfnum_other_frrem_accum_a; ++ ++ uint32_t hfnum_7_samples_b; ++ uint64_t hfnum_7_frrem_accum_b; ++ uint32_t hfnum_0_samples_b; ++ uint64_t hfnum_0_frrem_accum_b; ++ uint32_t hfnum_other_samples_b; ++ uint64_t hfnum_other_frrem_accum_b; ++#endif ++}; ++ ++/** @name Transaction Execution Functions */ ++/** @{ */ ++extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t ++ * hcd); ++extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd, ++ dwc_otg_transaction_type_e tr_type); ++ ++/** @} */ ++ ++/** @name Interrupt Handler Functions */ ++/** @{ */ ++extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * ++ dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * ++ dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * ++ dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t * ++ dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t * ++ dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, ++ uint32_t num); ++extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t * ++ dwc_otg_hcd); ++/** @} */ ++ ++/** @name Schedule Queue Functions */ ++/** @{ */ ++ ++/* Implemented in dwc_otg_hcd_queue.c */ ++extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd, ++ dwc_otg_hcd_urb_t * urb, int atomic_alloc); ++extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); ++extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); ++extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); ++extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, ++ int sched_csplit); ++ ++/** Remove and free a QH */ ++static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd, ++ dwc_otg_qh_t * qh) ++{ ++ dwc_irqflags_t flags; ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ dwc_otg_hcd_qh_free(hcd, qh); ++} ++ ++/** Allocates memory for a QH structure. ++ * @return Returns the memory allocate or NULL on error. */ ++static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(int atomic_alloc) ++{ ++ if (atomic_alloc) ++ return (dwc_otg_qh_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qh_t)); ++ else ++ return (dwc_otg_qh_t *) DWC_ALLOC(sizeof(dwc_otg_qh_t)); ++} ++ ++extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, ++ int atomic_alloc); ++extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb); ++extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd, ++ dwc_otg_qh_t ** qh, int atomic_alloc); ++ ++/** Allocates memory for a QTD structure. ++ * @return Returns the memory allocate or NULL on error. */ ++static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(int atomic_alloc) ++{ ++ if (atomic_alloc) ++ return (dwc_otg_qtd_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qtd_t)); ++ else ++ return (dwc_otg_qtd_t *) DWC_ALLOC(sizeof(dwc_otg_qtd_t)); ++} ++ ++/** Frees the memory for a QTD structure. QTD should already be removed from ++ * list. ++ * @param qtd QTD to free.*/ ++static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd) ++{ ++ DWC_FREE(qtd); ++} ++ ++/** Removes a QTD from list. ++ * @param hcd HCD instance. ++ * @param qtd QTD to remove from list. ++ * @param qh QTD belongs to. ++ */ ++static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t * hcd, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_qh_t * qh) ++{ ++ DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry); ++} ++ ++/** Remove and free a QTD ++ * Need to disable IRQ and hold hcd lock while calling this function out of ++ * interrupt servicing chain */ ++static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_qh_t * qh) ++{ ++ dwc_otg_hcd_qtd_remove(hcd, qtd, qh); ++ dwc_otg_hcd_qtd_free(qtd); ++} ++ ++/** @} */ ++ ++/** @name Descriptor DMA Supporting Functions */ ++/** @{ */ ++ ++extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); ++extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_halt_status_e halt_status); ++ ++extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); ++extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); ++ ++/** @} */ ++ ++/** @name Internal Functions */ ++/** @{ */ ++dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb); ++/** @} */ ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++extern int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, ++ uint8_t devaddr); ++extern void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd); ++#endif ++ ++/** Gets the QH that contains the list_head */ ++#define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry) ++ ++/** Gets the QTD that contains the list_head */ ++#define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry) ++ ++/** Check if QH is non-periodic */ ++#define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \ ++ (_qh_ptr_->ep_type == UE_CONTROL)) ++ ++/** High bandwidth multiplier as encoded in highspeed endpoint descriptors */ ++#define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) ++ ++/** Packet size for any kind of endpoint descriptor */ ++#define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) ++ ++/** ++ * Returns true if _frame1 is less than or equal to _frame2. The comparison is ++ * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the ++ * frame number when the max frame number is reached. ++ */ ++static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2) ++{ ++ return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <= ++ (DWC_HFNUM_MAX_FRNUM >> 1); ++} ++ ++/** ++ * Returns true if _frame1 is greater than _frame2. The comparison is done ++ * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame ++ * number when the max frame number is reached. ++ */ ++static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2) ++{ ++ return (frame1 != frame2) && ++ (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) < ++ (DWC_HFNUM_MAX_FRNUM >> 1)); ++} ++ ++/** ++ * Increments _frame by the amount specified by _inc. The addition is done ++ * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value. ++ */ ++static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc) ++{ ++ return (frame + inc) & DWC_HFNUM_MAX_FRNUM; ++} ++ ++static inline uint16_t dwc_full_frame_num(uint16_t frame) ++{ ++ return (frame & DWC_HFNUM_MAX_FRNUM) >> 3; ++} ++ ++static inline uint16_t dwc_micro_frame_num(uint16_t frame) ++{ ++ return frame & 0x7; ++} ++ ++void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd); ++ ++#ifdef DEBUG ++/** ++ * Macro to sample the remaining PHY clocks left in the current frame. This ++ * may be used during debugging to determine the average time it takes to ++ * execute sections of code. There are two possible sample points, "a" and ++ * "b", so the _letter argument must be one of these values. ++ * ++ * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For ++ * example, "cat /sys/devices/lm0/hcd_frrem". ++ */ ++#define dwc_sample_frrem(_hcd, _qh, _letter) \ ++{ \ ++ hfnum_data_t hfnum; \ ++ dwc_otg_qtd_t *qtd; \ ++ qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \ ++ if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \ ++ hfnum.d32 = DWC_READ_REG32(&_hcd->core_if->host_if->host_global_regs->hfnum); \ ++ switch (hfnum.b.frnum & 0x7) { \ ++ case 7: \ ++ _hcd->hfnum_7_samples_##_letter++; \ ++ _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \ ++ break; \ ++ case 0: \ ++ _hcd->hfnum_0_samples_##_letter++; \ ++ _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \ ++ break; \ ++ default: \ ++ _hcd->hfnum_other_samples_##_letter++; \ ++ _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \ ++ break; \ ++ } \ ++ } \ ++} ++#else ++#define dwc_sample_frrem(_hcd, _qh, _letter) ++#endif ++#endif ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_ddma.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_ddma.c +new file mode 100644 +index 0000000..fd20354 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_ddma.c +@@ -0,0 +1,1122 @@ ++/*========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $ ++ * $Revision: #11 $ ++ * $Date: 2013/01/24 $ ++ * $Change: 2150761 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_DEVICE_ONLY ++ ++/** @file ++ * This file contains Descriptor DMA support implementation for host mode. ++ */ ++ ++#include "dwc_otg_hcd.h" ++#include "dwc_otg_regs.h" ++ ++static inline uint8_t frame_list_idx(uint16_t frame) ++{ ++ return (frame & (MAX_FRLIST_EN_NUM - 1)); ++} ++ ++static inline uint16_t desclist_idx_inc(uint16_t idx, uint16_t inc, uint8_t speed) ++{ ++ return (idx + inc) & ++ (((speed == ++ DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : ++ MAX_DMA_DESC_NUM_GENERIC) - 1); ++} ++ ++static inline uint16_t desclist_idx_dec(uint16_t idx, uint16_t inc, uint8_t speed) ++{ ++ return (idx - inc) & ++ (((speed == ++ DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : ++ MAX_DMA_DESC_NUM_GENERIC) - 1); ++} ++ ++static inline uint16_t max_desc_num(dwc_otg_qh_t * qh) ++{ ++ return (((qh->ep_type == UE_ISOCHRONOUS) ++ && (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH)) ++ ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC); ++} ++static inline uint16_t frame_incr_val(dwc_otg_qh_t * qh) ++{ ++ return ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) ++ ? ((qh->interval + 8 - 1) / 8) ++ : qh->interval); ++} ++ ++static int desc_list_alloc(dwc_otg_qh_t * qh) ++{ ++ int retval = 0; ++ ++ qh->desc_list = (dwc_otg_host_dma_desc_t *) ++ DWC_DMA_ALLOC(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh), ++ &qh->desc_list_dma); ++ ++ if (!qh->desc_list) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR("%s: DMA descriptor list allocation failed\n", __func__); ++ ++ } ++ ++ dwc_memset(qh->desc_list, 0x00, ++ sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh)); ++ ++ qh->n_bytes = ++ (uint32_t *) DWC_ALLOC(sizeof(uint32_t) * max_desc_num(qh)); ++ ++ if (!qh->n_bytes) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR ++ ("%s: Failed to allocate array for descriptors' size actual values\n", ++ __func__); ++ ++ } ++ return retval; ++ ++} ++ ++static void desc_list_free(dwc_otg_qh_t * qh) ++{ ++ if (qh->desc_list) { ++ DWC_DMA_FREE(max_desc_num(qh), qh->desc_list, ++ qh->desc_list_dma); ++ qh->desc_list = NULL; ++ } ++ ++ if (qh->n_bytes) { ++ DWC_FREE(qh->n_bytes); ++ qh->n_bytes = NULL; ++ } ++} ++ ++static int frame_list_alloc(dwc_otg_hcd_t * hcd) ++{ ++ int retval = 0; ++ if (hcd->frame_list) ++ return 0; ++ ++ hcd->frame_list = DWC_DMA_ALLOC(4 * MAX_FRLIST_EN_NUM, ++ &hcd->frame_list_dma); ++ if (!hcd->frame_list) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR("%s: Frame List allocation failed\n", __func__); ++ } ++ ++ dwc_memset(hcd->frame_list, 0x00, 4 * MAX_FRLIST_EN_NUM); ++ ++ return retval; ++} ++ ++static void frame_list_free(dwc_otg_hcd_t * hcd) ++{ ++ if (!hcd->frame_list) ++ return; ++ ++ DWC_DMA_FREE(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma); ++ hcd->frame_list = NULL; ++} ++ ++static void per_sched_enable(dwc_otg_hcd_t * hcd, uint16_t fr_list_en) ++{ ++ ++ hcfg_data_t hcfg; ++ ++ hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg); ++ ++ if (hcfg.b.perschedena) { ++ /* already enabled */ ++ return; ++ } ++ ++ DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hflbaddr, ++ hcd->frame_list_dma); ++ ++ switch (fr_list_en) { ++ case 64: ++ hcfg.b.frlisten = 3; ++ break; ++ case 32: ++ hcfg.b.frlisten = 2; ++ break; ++ case 16: ++ hcfg.b.frlisten = 1; ++ break; ++ case 8: ++ hcfg.b.frlisten = 0; ++ break; ++ default: ++ break; ++ } ++ ++ hcfg.b.perschedena = 1; ++ ++ DWC_DEBUGPL(DBG_HCD, "Enabling Periodic schedule\n"); ++ DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++ ++} ++ ++static void per_sched_disable(dwc_otg_hcd_t * hcd) ++{ ++ hcfg_data_t hcfg; ++ ++ hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg); ++ ++ if (!hcfg.b.perschedena) { ++ /* already disabled */ ++ return; ++ } ++ hcfg.b.perschedena = 0; ++ ++ DWC_DEBUGPL(DBG_HCD, "Disabling Periodic schedule\n"); ++ DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++} ++ ++/* ++ * Activates/Deactivates FrameList entries for the channel ++ * based on endpoint servicing period. ++ */ ++void update_frame_list(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t enable) ++{ ++ uint16_t i, j, inc; ++ dwc_hc_t *hc = NULL; ++ ++ if (!qh->channel) { ++ DWC_ERROR("qh->channel = %p", qh->channel); ++ return; ++ } ++ ++ if (!hcd) { ++ DWC_ERROR("------hcd = %p", hcd); ++ return; ++ } ++ ++ if (!hcd->frame_list) { ++ DWC_ERROR("-------hcd->frame_list = %p", hcd->frame_list); ++ return; ++ } ++ ++ hc = qh->channel; ++ inc = frame_incr_val(qh); ++ if (qh->ep_type == UE_ISOCHRONOUS) ++ i = frame_list_idx(qh->sched_frame); ++ else ++ i = 0; ++ ++ j = i; ++ do { ++ if (enable) ++ hcd->frame_list[j] |= (1 << hc->hc_num); ++ else ++ hcd->frame_list[j] &= ~(1 << hc->hc_num); ++ j = (j + inc) & (MAX_FRLIST_EN_NUM - 1); ++ } ++ while (j != i); ++ if (!enable) ++ return; ++ hc->schinfo = 0; ++ if (qh->channel->speed == DWC_OTG_EP_SPEED_HIGH) { ++ j = 1; ++ /* TODO - check this */ ++ inc = (8 + qh->interval - 1) / qh->interval; ++ for (i = 0; i < inc; i++) { ++ hc->schinfo |= j; ++ j = j << qh->interval; ++ } ++ } else { ++ hc->schinfo = 0xff; ++ } ++} ++ ++#if 1 ++void dump_frame_list(dwc_otg_hcd_t * hcd) ++{ ++ int i = 0; ++ DWC_PRINTF("--FRAME LIST (hex) --\n"); ++ for (i = 0; i < MAX_FRLIST_EN_NUM; i++) { ++ DWC_PRINTF("%x\t", hcd->frame_list[i]); ++ if (!(i % 8) && i) ++ DWC_PRINTF("\n"); ++ } ++ DWC_PRINTF("\n----\n"); ++ ++} ++#endif ++ ++static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ dwc_hc_t *hc = qh->channel; ++ if (dwc_qh_is_non_per(qh)) ++ hcd->non_periodic_channels--; ++ else ++ update_frame_list(hcd, qh, 0); ++ ++ /* ++ * The condition is added to prevent double cleanup try in case of device ++ * disconnect. See channel cleanup in dwc_otg_hcd_disconnect_cb(). ++ */ ++ if (hc->qh) { ++ dwc_otg_hc_cleanup(hcd->core_if, hc); ++ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); ++ hc->qh = NULL; ++ } ++ ++ qh->channel = NULL; ++ qh->ntd = 0; ++ ++ if (qh->desc_list) { ++ dwc_memset(qh->desc_list, 0x00, ++ sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh)); ++ } ++} ++ ++/** ++ * Initializes a QH structure's Descriptor DMA related members. ++ * Allocates memory for descriptor list. ++ * On first periodic QH, allocates memory for FrameList ++ * and enables periodic scheduling. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh The QH to init. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ int retval = 0; ++ ++ if (qh->do_split) { ++ DWC_ERROR("SPLIT Transfers are not supported in Descriptor DMA.\n"); ++ return -1; ++ } ++ ++ retval = desc_list_alloc(qh); ++ ++ if ((retval == 0) ++ && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) { ++ if (!hcd->frame_list) { ++ retval = frame_list_alloc(hcd); ++ /* Enable periodic schedule on first periodic QH */ ++ if (retval == 0) ++ per_sched_enable(hcd, MAX_FRLIST_EN_NUM); ++ } ++ } ++ ++ qh->ntd = 0; ++ ++ return retval; ++} ++ ++/** ++ * Frees descriptor list memory associated with the QH. ++ * If QH is periodic and the last, frees FrameList memory ++ * and disables periodic scheduling. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh The QH to init. ++ */ ++void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ desc_list_free(qh); ++ ++ /* ++ * Channel still assigned due to some reasons. ++ * Seen on Isoc URB dequeue. Channel halted but no subsequent ++ * ChHalted interrupt to release the channel. Afterwards ++ * when it comes here from endpoint disable routine ++ * channel remains assigned. ++ */ ++ if (qh->channel) ++ release_channel_ddma(hcd, qh); ++ ++ if ((qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT) ++ && !hcd->periodic_channels && hcd->frame_list) { ++ ++ per_sched_disable(hcd); ++ frame_list_free(hcd); ++ } ++} ++ ++static uint8_t frame_to_desc_idx(dwc_otg_qh_t * qh, uint16_t frame_idx) ++{ ++ if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) { ++ /* ++ * Descriptor set(8 descriptors) index ++ * which is 8-aligned. ++ */ ++ return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8; ++ } else { ++ return (frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1)); ++ } ++} ++ ++/* ++ * Determine starting frame for Isochronous transfer. ++ * Few frames skipped to prevent race condition with HC. ++ */ ++static uint8_t calc_starting_frame(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, ++ uint8_t * skip_frames) ++{ ++ uint16_t frame = 0; ++ hcd->frame_number = dwc_otg_hcd_get_frame_number(hcd); ++ ++ /* sched_frame is always frame number(not uFrame) both in FS and HS !! */ ++ ++ /* ++ * skip_frames is used to limit activated descriptors number ++ * to avoid the situation when HC services the last activated ++ * descriptor firstly. ++ * Example for FS: ++ * Current frame is 1, scheduled frame is 3. Since HC always fetches the descriptor ++ * corresponding to curr_frame+1, the descriptor corresponding to frame 2 ++ * will be fetched. If the number of descriptors is max=64 (or greather) the ++ * list will be fully programmed with Active descriptors and it is possible ++ * case(rare) that the latest descriptor(considering rollback) corresponding ++ * to frame 2 will be serviced first. HS case is more probable because, in fact, ++ * up to 11 uframes(16 in the code) may be skipped. ++ */ ++ if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) { ++ /* ++ * Consider uframe counter also, to start xfer asap. ++ * If half of the frame elapsed skip 2 frames otherwise ++ * just 1 frame. ++ * Starting descriptor index must be 8-aligned, so ++ * if the current frame is near to complete the next one ++ * is skipped as well. ++ */ ++ ++ if (dwc_micro_frame_num(hcd->frame_number) >= 5) { ++ *skip_frames = 2 * 8; ++ frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames); ++ } else { ++ *skip_frames = 1 * 8; ++ frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames); ++ } ++ ++ frame = dwc_full_frame_num(frame); ++ } else { ++ /* ++ * Two frames are skipped for FS - the current and the next. ++ * But for descriptor programming, 1 frame(descriptor) is enough, ++ * see example above. ++ */ ++ *skip_frames = 1; ++ frame = dwc_frame_num_inc(hcd->frame_number, 2); ++ } ++ ++ return frame; ++} ++ ++/* ++ * Calculate initial descriptor index for isochronous transfer ++ * based on scheduled frame. ++ */ ++static uint8_t recalc_initial_desc_idx(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ uint16_t frame = 0, fr_idx, fr_idx_tmp; ++ uint8_t skip_frames = 0; ++ /* ++ * With current ISOC processing algorithm the channel is being ++ * released when no more QTDs in the list(qh->ntd == 0). ++ * Thus this function is called only when qh->ntd == 0 and qh->channel == 0. ++ * ++ * So qh->channel != NULL branch is not used and just not removed from the ++ * source file. It is required for another possible approach which is, ++ * do not disable and release the channel when ISOC session completed, ++ * just move QH to inactive schedule until new QTD arrives. ++ * On new QTD, the QH moved back to 'ready' schedule, ++ * starting frame and therefore starting desc_index are recalculated. ++ * In this case channel is released only on ep_disable. ++ */ ++ ++ /* Calculate starting descriptor index. For INTERRUPT endpoint it is always 0. */ ++ if (qh->channel) { ++ frame = calc_starting_frame(hcd, qh, &skip_frames); ++ /* ++ * Calculate initial descriptor index based on FrameList current bitmap ++ * and servicing period. ++ */ ++ fr_idx_tmp = frame_list_idx(frame); ++ fr_idx = ++ (MAX_FRLIST_EN_NUM + frame_list_idx(qh->sched_frame) - ++ fr_idx_tmp) ++ % frame_incr_val(qh); ++ fr_idx = (fr_idx + fr_idx_tmp) % MAX_FRLIST_EN_NUM; ++ } else { ++ qh->sched_frame = calc_starting_frame(hcd, qh, &skip_frames); ++ fr_idx = frame_list_idx(qh->sched_frame); ++ } ++ ++ qh->td_first = qh->td_last = frame_to_desc_idx(qh, fr_idx); ++ ++ return skip_frames; ++} ++ ++#define ISOC_URB_GIVEBACK_ASAP ++ ++#define MAX_ISOC_XFER_SIZE_FS 1023 ++#define MAX_ISOC_XFER_SIZE_HS 3072 ++#define DESCNUM_THRESHOLD 4 ++ ++static void init_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, ++ uint8_t skip_frames) ++{ ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc; ++ dwc_otg_qtd_t *qtd; ++ dwc_otg_host_dma_desc_t *dma_desc; ++ uint16_t idx, inc, n_desc, ntd_max, max_xfer_size; ++ ++ idx = qh->td_last; ++ inc = qh->interval; ++ n_desc = 0; ++ ++ ntd_max = (max_desc_num(qh) + qh->interval - 1) / qh->interval; ++ if (skip_frames && !qh->channel) ++ ntd_max = ntd_max - skip_frames / qh->interval; ++ ++ max_xfer_size = ++ (qh->dev_speed == ++ DWC_OTG_EP_SPEED_HIGH) ? MAX_ISOC_XFER_SIZE_HS : ++ MAX_ISOC_XFER_SIZE_FS; ++ ++ DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) { ++ while ((qh->ntd < ntd_max) ++ && (qtd->isoc_frame_index_last < ++ qtd->urb->packet_count)) { ++ ++ dma_desc = &qh->desc_list[idx]; ++ dwc_memset(dma_desc, 0x00, sizeof(dwc_otg_host_dma_desc_t)); ++ ++ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last]; ++ ++ if (frame_desc->length > max_xfer_size) ++ qh->n_bytes[idx] = max_xfer_size; ++ else ++ qh->n_bytes[idx] = frame_desc->length; ++ dma_desc->status.b_isoc.n_bytes = qh->n_bytes[idx]; ++ dma_desc->status.b_isoc.a = 1; ++ dma_desc->status.b_isoc.sts = 0; ++ ++ dma_desc->buf = qtd->urb->dma + frame_desc->offset; ++ ++ qh->ntd++; ++ ++ qtd->isoc_frame_index_last++; ++ ++#ifdef ISOC_URB_GIVEBACK_ASAP ++ /* ++ * Set IOC for each descriptor corresponding to the ++ * last frame of the URB. ++ */ ++ if (qtd->isoc_frame_index_last == ++ qtd->urb->packet_count) ++ dma_desc->status.b_isoc.ioc = 1; ++ ++#endif ++ idx = desclist_idx_inc(idx, inc, qh->dev_speed); ++ n_desc++; ++ ++ } ++ qtd->in_process = 1; ++ } ++ ++ qh->td_last = idx; ++ ++#ifdef ISOC_URB_GIVEBACK_ASAP ++ /* Set IOC for the last descriptor if descriptor list is full */ ++ if (qh->ntd == ntd_max) { ++ idx = desclist_idx_dec(qh->td_last, inc, qh->dev_speed); ++ qh->desc_list[idx].status.b_isoc.ioc = 1; ++ } ++#else ++ /* ++ * Set IOC bit only for one descriptor. ++ * Always try to be ahead of HW processing, ++ * i.e. on IOC generation driver activates next descriptors but ++ * core continues to process descriptors followed the one with IOC set. ++ */ ++ ++ if (n_desc > DESCNUM_THRESHOLD) { ++ /* ++ * Move IOC "up". Required even if there is only one QTD ++ * in the list, cause QTDs migth continue to be queued, ++ * but during the activation it was only one queued. ++ * Actually more than one QTD might be in the list if this function called ++ * from XferCompletion - QTDs was queued during HW processing of the previous ++ * descriptor chunk. ++ */ ++ idx = dwc_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2), qh->dev_speed); ++ } else { ++ /* ++ * Set the IOC for the latest descriptor ++ * if either number of descriptor is not greather than threshold ++ * or no more new descriptors activated. ++ */ ++ idx = dwc_desclist_idx_dec(qh->td_last, inc, qh->dev_speed); ++ } ++ ++ qh->desc_list[idx].status.b_isoc.ioc = 1; ++#endif ++} ++ ++static void init_non_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ ++ dwc_hc_t *hc; ++ dwc_otg_host_dma_desc_t *dma_desc; ++ dwc_otg_qtd_t *qtd; ++ int num_packets, len, n_desc = 0; ++ ++ hc = qh->channel; ++ ++ /* ++ * Start with hc->xfer_buff initialized in ++ * assign_and_init_hc(), then if SG transfer consists of multiple URBs, ++ * this pointer re-assigned to the buffer of the currently processed QTD. ++ * For non-SG request there is always one QTD active. ++ */ ++ ++ DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) { ++ ++ if (n_desc) { ++ /* SG request - more than 1 QTDs */ ++ hc->xfer_buff = (uint8_t *)qtd->urb->dma + qtd->urb->actual_length; ++ hc->xfer_len = qtd->urb->length - qtd->urb->actual_length; ++ } ++ ++ qtd->n_desc = 0; ++ ++ do { ++ dma_desc = &qh->desc_list[n_desc]; ++ len = hc->xfer_len; ++ ++ if (len > MAX_DMA_DESC_SIZE) ++ len = MAX_DMA_DESC_SIZE - hc->max_packet + 1; ++ ++ if (hc->ep_is_in) { ++ if (len > 0) { ++ num_packets = (len + hc->max_packet - 1) / hc->max_packet; ++ } else { ++ /* Need 1 packet for transfer length of 0. */ ++ num_packets = 1; ++ } ++ /* Always program an integral # of max packets for IN transfers. */ ++ len = num_packets * hc->max_packet; ++ } ++ ++ dma_desc->status.b.n_bytes = len; ++ ++ qh->n_bytes[n_desc] = len; ++ ++ if ((qh->ep_type == UE_CONTROL) ++ && (qtd->control_phase == DWC_OTG_CONTROL_SETUP)) ++ dma_desc->status.b.sup = 1; /* Setup Packet */ ++ ++ dma_desc->status.b.a = 1; /* Active descriptor */ ++ dma_desc->status.b.sts = 0; ++ ++ dma_desc->buf = ++ ((unsigned long)hc->xfer_buff & 0xffffffff); ++ ++ /* ++ * Last descriptor(or single) of IN transfer ++ * with actual size less than MaxPacket. ++ */ ++ if (len > hc->xfer_len) { ++ hc->xfer_len = 0; ++ } else { ++ hc->xfer_buff += len; ++ hc->xfer_len -= len; ++ } ++ ++ qtd->n_desc++; ++ n_desc++; ++ } ++ while ((hc->xfer_len > 0) && (n_desc != MAX_DMA_DESC_NUM_GENERIC)); ++ ++ ++ qtd->in_process = 1; ++ ++ if (qh->ep_type == UE_CONTROL) ++ break; ++ ++ if (n_desc == MAX_DMA_DESC_NUM_GENERIC) ++ break; ++ } ++ ++ if (n_desc) { ++ /* Request Transfer Complete interrupt for the last descriptor */ ++ qh->desc_list[n_desc - 1].status.b.ioc = 1; ++ /* End of List indicator */ ++ qh->desc_list[n_desc - 1].status.b.eol = 1; ++ ++ hc->ntd = n_desc; ++ } ++} ++ ++/** ++ * For Control and Bulk endpoints initializes descriptor list ++ * and starts the transfer. ++ * ++ * For Interrupt and Isochronous endpoints initializes descriptor list ++ * then updates FrameList, marking appropriate entries as active. ++ * In case of Isochronous, the starting descriptor index is calculated based ++ * on the scheduled frame, but only on the first transfer descriptor within a session. ++ * Then starts the transfer via enabling the channel. ++ * For Isochronous endpoint the channel is not halted on XferComplete ++ * interrupt so remains assigned to the endpoint(QH) until session is done. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh The QH to init. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ /* Channel is already assigned */ ++ dwc_hc_t *hc = qh->channel; ++ uint8_t skip_frames = 0; ++ ++ switch (hc->ep_type) { ++ case DWC_OTG_EP_TYPE_CONTROL: ++ case DWC_OTG_EP_TYPE_BULK: ++ init_non_isoc_dma_desc(hcd, qh); ++ ++ dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); ++ break; ++ case DWC_OTG_EP_TYPE_INTR: ++ init_non_isoc_dma_desc(hcd, qh); ++ ++ update_frame_list(hcd, qh, 1); ++ ++ dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); ++ break; ++ case DWC_OTG_EP_TYPE_ISOC: ++ ++ if (!qh->ntd) ++ skip_frames = recalc_initial_desc_idx(hcd, qh); ++ ++ init_isoc_dma_desc(hcd, qh, skip_frames); ++ ++ if (!hc->xfer_started) { ++ ++ update_frame_list(hcd, qh, 1); ++ ++ /* ++ * Always set to max, instead of actual size. ++ * Otherwise ntd will be changed with ++ * channel being enabled. Not recommended. ++ * ++ */ ++ hc->ntd = max_desc_num(qh); ++ /* Enable channel only once for ISOC */ ++ dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); ++ } ++ ++ break; ++ default: ++ ++ break; ++ } ++} ++ ++static void complete_isoc_xfer_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_halt_status_e halt_status) ++{ ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc; ++ dwc_otg_qtd_t *qtd, *qtd_tmp; ++ dwc_otg_qh_t *qh; ++ dwc_otg_host_dma_desc_t *dma_desc; ++ uint16_t idx, remain; ++ uint8_t urb_compl; ++ ++ qh = hc->qh; ++ idx = qh->td_first; ++ ++ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) ++ qtd->in_process = 0; ++ return; ++ } else if ((halt_status == DWC_OTG_HC_XFER_AHB_ERR) || ++ (halt_status == DWC_OTG_HC_XFER_BABBLE_ERR)) { ++ /* ++ * Channel is halted in these error cases. ++ * Considered as serious issues. ++ * Complete all URBs marking all frames as failed, ++ * irrespective whether some of the descriptors(frames) succeeded or no. ++ * Pass error code to completion routine as well, to ++ * update urb->status, some of class drivers might use it to stop ++ * queing transfer requests. ++ */ ++ int err = (halt_status == DWC_OTG_HC_XFER_AHB_ERR) ++ ? (-DWC_E_IO) ++ : (-DWC_E_OVERFLOW); ++ ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { ++ for (idx = 0; idx < qtd->urb->packet_count; idx++) { ++ frame_desc = &qtd->urb->iso_descs[idx]; ++ frame_desc->status = err; ++ } ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, err); ++ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ } ++ return; ++ } ++ ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { ++ ++ if (!qtd->in_process) ++ break; ++ ++ urb_compl = 0; ++ ++ do { ++ ++ dma_desc = &qh->desc_list[idx]; ++ ++ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; ++ remain = hc->ep_is_in ? dma_desc->status.b_isoc.n_bytes : 0; ++ ++ if (dma_desc->status.b_isoc.sts == DMA_DESC_STS_PKTERR) { ++ /* ++ * XactError or, unable to complete all the transactions ++ * in the scheduled micro-frame/frame, ++ * both indicated by DMA_DESC_STS_PKTERR. ++ */ ++ qtd->urb->error_count++; ++ frame_desc->actual_length = qh->n_bytes[idx] - remain; ++ frame_desc->status = -DWC_E_PROTOCOL; ++ } else { ++ /* Success */ ++ ++ frame_desc->actual_length = qh->n_bytes[idx] - remain; ++ frame_desc->status = 0; ++ } ++ ++ if (++qtd->isoc_frame_index == qtd->urb->packet_count) { ++ /* ++ * urb->status is not used for isoc transfers here. ++ * The individual frame_desc status are used instead. ++ */ ++ ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); ++ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ ++ /* ++ * This check is necessary because urb_dequeue can be called ++ * from urb complete callback(sound driver example). ++ * All pending URBs are dequeued there, so no need for ++ * further processing. ++ */ ++ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { ++ return; ++ } ++ ++ urb_compl = 1; ++ ++ } ++ ++ qh->ntd--; ++ ++ /* Stop if IOC requested descriptor reached */ ++ if (dma_desc->status.b_isoc.ioc) { ++ idx = desclist_idx_inc(idx, qh->interval, hc->speed); ++ goto stop_scan; ++ } ++ ++ idx = desclist_idx_inc(idx, qh->interval, hc->speed); ++ ++ if (urb_compl) ++ break; ++ } ++ while (idx != qh->td_first); ++ } ++stop_scan: ++ qh->td_first = idx; ++} ++ ++uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_host_dma_desc_t * dma_desc, ++ dwc_otg_halt_status_e halt_status, ++ uint32_t n_bytes, uint8_t * xfer_done) ++{ ++ ++ uint16_t remain = hc->ep_is_in ? dma_desc->status.b.n_bytes : 0; ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ ++ if (halt_status == DWC_OTG_HC_XFER_AHB_ERR) { ++ urb->status = -DWC_E_IO; ++ return 1; ++ } ++ if (dma_desc->status.b.sts == DMA_DESC_STS_PKTERR) { ++ switch (halt_status) { ++ case DWC_OTG_HC_XFER_STALL: ++ urb->status = -DWC_E_PIPE; ++ break; ++ case DWC_OTG_HC_XFER_BABBLE_ERR: ++ urb->status = -DWC_E_OVERFLOW; ++ break; ++ case DWC_OTG_HC_XFER_XACT_ERR: ++ urb->status = -DWC_E_PROTOCOL; ++ break; ++ default: ++ DWC_ERROR("%s: Unhandled descriptor error status (%d)\n", __func__, ++ halt_status); ++ break; ++ } ++ return 1; ++ } ++ ++ if (dma_desc->status.b.a == 1) { ++ DWC_DEBUGPL(DBG_HCDV, ++ "Active descriptor encountered on channel %d\n", ++ hc->hc_num); ++ return 0; ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL) { ++ if (qtd->control_phase == DWC_OTG_CONTROL_DATA) { ++ urb->actual_length += n_bytes - remain; ++ if (remain || urb->actual_length == urb->length) { ++ /* ++ * For Control Data stage do not set urb->status=0 to prevent ++ * URB callback. Set it when Status phase done. See below. ++ */ ++ *xfer_done = 1; ++ } ++ ++ } else if (qtd->control_phase == DWC_OTG_CONTROL_STATUS) { ++ urb->status = 0; ++ *xfer_done = 1; ++ } ++ /* No handling for SETUP stage */ ++ } else { ++ /* BULK and INTR */ ++ urb->actual_length += n_bytes - remain; ++ if (remain || urb->actual_length == urb->length) { ++ urb->status = 0; ++ *xfer_done = 1; ++ } ++ } ++ ++ return 0; ++} ++ ++static void complete_non_isoc_xfer_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_halt_status_e halt_status) ++{ ++ dwc_otg_hcd_urb_t *urb = NULL; ++ dwc_otg_qtd_t *qtd, *qtd_tmp; ++ dwc_otg_qh_t *qh; ++ dwc_otg_host_dma_desc_t *dma_desc; ++ uint32_t n_bytes, n_desc, i; ++ uint8_t failed = 0, xfer_done; ++ ++ n_desc = 0; ++ ++ qh = hc->qh; ++ ++ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { ++ qtd->in_process = 0; ++ } ++ return; ++ } ++ ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { ++ ++ urb = qtd->urb; ++ ++ n_bytes = 0; ++ xfer_done = 0; ++ ++ for (i = 0; i < qtd->n_desc; i++) { ++ dma_desc = &qh->desc_list[n_desc]; ++ ++ n_bytes = qh->n_bytes[n_desc]; ++ ++ failed = ++ update_non_isoc_urb_state_ddma(hcd, hc, qtd, ++ dma_desc, ++ halt_status, n_bytes, ++ &xfer_done); ++ ++ if (failed ++ || (xfer_done ++ && (urb->status != -DWC_E_IN_PROGRESS))) { ++ ++ hcd->fops->complete(hcd, urb->priv, urb, ++ urb->status); ++ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ ++ if (failed) ++ goto stop_scan; ++ } else if (qh->ep_type == UE_CONTROL) { ++ if (qtd->control_phase == DWC_OTG_CONTROL_SETUP) { ++ if (urb->length > 0) { ++ qtd->control_phase = DWC_OTG_CONTROL_DATA; ++ } else { ++ qtd->control_phase = DWC_OTG_CONTROL_STATUS; ++ } ++ DWC_DEBUGPL(DBG_HCDV, " Control setup transaction done\n"); ++ } else if (qtd->control_phase == DWC_OTG_CONTROL_DATA) { ++ if (xfer_done) { ++ qtd->control_phase = DWC_OTG_CONTROL_STATUS; ++ DWC_DEBUGPL(DBG_HCDV, " Control data transfer done\n"); ++ } else if (i + 1 == qtd->n_desc) { ++ /* ++ * Last descriptor for Control data stage which is ++ * not completed yet. ++ */ ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ } ++ } ++ } ++ ++ n_desc++; ++ } ++ ++ } ++ ++stop_scan: ++ ++ if (qh->ep_type != UE_CONTROL) { ++ /* ++ * Resetting the data toggle for bulk ++ * and interrupt endpoints in case of stall. See handle_hc_stall_intr() ++ */ ++ if (halt_status == DWC_OTG_HC_XFER_STALL) ++ qh->data_toggle = DWC_OTG_HC_PID_DATA0; ++ else ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ } ++ ++ if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { ++ hcint_data_t hcint; ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ if (hcint.b.nyet) { ++ /* ++ * Got a NYET on the last transaction of the transfer. It ++ * means that the endpoint should be in the PING state at the ++ * beginning of the next transfer. ++ */ ++ qh->ping_state = 1; ++ clear_hc_int(hc_regs, nyet); ++ } ++ ++ } ++ ++} ++ ++/** ++ * This function is called from interrupt handlers. ++ * Scans the descriptor list, updates URB's status and ++ * calls completion routine for the URB if it's done. ++ * Releases the channel to be used by other transfers. ++ * In case of Isochronous endpoint the channel is not halted until ++ * the end of the session, i.e. QTD list is empty. ++ * If periodic channel released the FrameList is updated accordingly. ++ * ++ * Calls transaction selection routines to activate pending transfers. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param hc Host channel, the transfer is completed on. ++ * @param hc_regs Host channel registers. ++ * @param halt_status Reason the channel is being halted, ++ * or just XferComplete for isochronous transfer ++ */ ++void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_halt_status_e halt_status) ++{ ++ uint8_t continue_isoc_xfer = 0; ++ dwc_otg_transaction_type_e tr_type; ++ dwc_otg_qh_t *qh = hc->qh; ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ ++ complete_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status); ++ ++ /* Release the channel if halted or session completed */ ++ if (halt_status != DWC_OTG_HC_XFER_COMPLETE || ++ DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ ++ /* Halt the channel if session completed */ ++ if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { ++ dwc_otg_hc_halt(hcd->core_if, hc, halt_status); ++ } ++ ++ release_channel_ddma(hcd, qh); ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ } else { ++ /* Keep in assigned schedule to continue transfer */ ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, ++ &qh->qh_list_entry); ++ continue_isoc_xfer = 1; ++ ++ } ++ /** @todo Consider the case when period exceeds FrameList size. ++ * Frame Rollover interrupt should be used. ++ */ ++ } else { ++ /* Scan descriptor list to complete the URB(s), then release the channel */ ++ complete_non_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status); ++ ++ release_channel_ddma(hcd, qh); ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ ++ if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ /* Add back to inactive non-periodic schedule on normal completion */ ++ dwc_otg_hcd_qh_add(hcd, qh); ++ } ++ ++ } ++ tr_type = dwc_otg_hcd_select_transactions(hcd); ++ if (tr_type != DWC_OTG_TRANSACTION_NONE || continue_isoc_xfer) { ++ if (continue_isoc_xfer) { ++ if (tr_type == DWC_OTG_TRANSACTION_NONE) { ++ tr_type = DWC_OTG_TRANSACTION_PERIODIC; ++ } else if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC) { ++ tr_type = DWC_OTG_TRANSACTION_ALL; ++ } ++ } ++ dwc_otg_hcd_queue_transactions(hcd, tr_type); ++ } ++} ++ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_if.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_if.h +new file mode 100644 +index 0000000..4823167 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_if.h +@@ -0,0 +1,412 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_if.h $ ++ * $Revision: #12 $ ++ * $Date: 2011/10/26 $ ++ * $Change: 1873028 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_DEVICE_ONLY ++#ifndef __DWC_HCD_IF_H__ ++#define __DWC_HCD_IF_H__ ++ ++#include "dwc_otg_core_if.h" ++ ++/** @file ++ * This file defines DWC_OTG HCD Core API. ++ */ ++ ++struct dwc_otg_hcd; ++typedef struct dwc_otg_hcd dwc_otg_hcd_t; ++ ++struct dwc_otg_hcd_urb; ++typedef struct dwc_otg_hcd_urb dwc_otg_hcd_urb_t; ++ ++/** @name HCD Function Driver Callbacks */ ++/** @{ */ ++ ++/** This function is called whenever core switches to host mode. */ ++typedef int (*dwc_otg_hcd_start_cb_t) (dwc_otg_hcd_t * hcd); ++ ++/** This function is called when device has been disconnected */ ++typedef int (*dwc_otg_hcd_disconnect_cb_t) (dwc_otg_hcd_t * hcd); ++ ++/** Wrapper provides this function to HCD to core, so it can get hub information to which device is connected */ ++typedef int (*dwc_otg_hcd_hub_info_from_urb_cb_t) (dwc_otg_hcd_t * hcd, ++ void *urb_handle, ++ uint32_t * hub_addr, ++ uint32_t * port_addr); ++/** Via this function HCD core gets device speed */ ++typedef int (*dwc_otg_hcd_speed_from_urb_cb_t) (dwc_otg_hcd_t * hcd, ++ void *urb_handle); ++ ++/** This function is called when urb is completed */ ++typedef int (*dwc_otg_hcd_complete_urb_cb_t) (dwc_otg_hcd_t * hcd, ++ void *urb_handle, ++ dwc_otg_hcd_urb_t * dwc_otg_urb, ++ int32_t status); ++ ++/** Via this function HCD core gets b_hnp_enable parameter */ ++typedef int (*dwc_otg_hcd_get_b_hnp_enable) (dwc_otg_hcd_t * hcd); ++ ++struct dwc_otg_hcd_function_ops { ++ dwc_otg_hcd_start_cb_t start; ++ dwc_otg_hcd_disconnect_cb_t disconnect; ++ dwc_otg_hcd_hub_info_from_urb_cb_t hub_info; ++ dwc_otg_hcd_speed_from_urb_cb_t speed; ++ dwc_otg_hcd_complete_urb_cb_t complete; ++ dwc_otg_hcd_get_b_hnp_enable get_b_hnp_enable; ++}; ++/** @} */ ++ ++/** @name HCD Core API */ ++/** @{ */ ++/** This function allocates dwc_otg_hcd structure and returns pointer on it. */ ++extern dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void); ++ ++/** This function should be called to initiate HCD Core. ++ * ++ * @param hcd The HCD ++ * @param core_if The DWC_OTG Core ++ * ++ * Returns -DWC_E_NO_MEMORY if no enough memory. ++ * Returns 0 on success ++ */ ++extern int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if); ++ ++/** Frees HCD ++ * ++ * @param hcd The HCD ++ */ ++extern void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd); ++ ++/** This function should be called on every hardware interrupt. ++ * ++ * @param dwc_otg_hcd The HCD ++ * ++ * Returns non zero if interrupt is handled ++ * Return 0 if interrupt is not handled ++ */ ++extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++ ++/** ++ * Returns private data set by ++ * dwc_otg_hcd_set_priv_data function. ++ * ++ * @param hcd The HCD ++ */ ++extern void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Set private data. ++ * ++ * @param hcd The HCD ++ * @param priv_data pointer to be stored in private data ++ */ ++extern void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data); ++ ++/** ++ * This function initializes the HCD Core. ++ * ++ * @param hcd The HCD ++ * @param fops The Function Driver Operations data structure containing pointers to all callbacks. ++ * ++ * Returns -DWC_E_NO_DEVICE if Core is currently is in device mode. ++ * Returns 0 on success ++ */ ++extern int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd, ++ struct dwc_otg_hcd_function_ops *fops); ++ ++/** ++ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are ++ * stopped. ++ * ++ * @param hcd The HCD ++ */ ++extern void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Handles hub class-specific requests. ++ * ++ * @param dwc_otg_hcd The HCD ++ * @param typeReq Request Type ++ * @param wValue wValue from control request ++ * @param wIndex wIndex from control request ++ * @param buf data buffer ++ * @param wLength data buffer length ++ * ++ * Returns -DWC_E_INVALID if invalid argument is passed ++ * Returns 0 on success ++ */ ++extern int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, ++ uint16_t typeReq, uint16_t wValue, ++ uint16_t wIndex, uint8_t * buf, ++ uint16_t wLength); ++ ++/** ++ * Returns otg port number. ++ * ++ * @param hcd The HCD ++ */ ++extern uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Returns OTG version - either 1.3 or 2.0. ++ * ++ * @param core_if The core_if structure pointer ++ */ ++extern uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Returns 1 if currently core is acting as B host, and 0 otherwise. ++ * ++ * @param hcd The HCD ++ */ ++extern uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Returns current frame number. ++ * ++ * @param hcd The HCD ++ */ ++extern int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Dumps hcd state. ++ * ++ * @param hcd The HCD ++ */ ++extern void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Dump the average frame remaining at SOF. This can be used to ++ * determine average interrupt latency. Frame remaining is also shown for ++ * start transfer and two additional sample points. ++ * Currently this function is not implemented. ++ * ++ * @param hcd The HCD ++ */ ++extern void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Sends LPM transaction to the local device. ++ * ++ * @param hcd The HCD ++ * @param devaddr Device Address ++ * @param hird Host initiated resume duration ++ * @param bRemoteWake Value of bRemoteWake field in LPM transaction ++ * ++ * Returns negative value if sending LPM transaction was not succeeded. ++ * Returns 0 on success. ++ */ ++extern int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, ++ uint8_t hird, uint8_t bRemoteWake); ++ ++/* URB interface */ ++ ++/** ++ * Allocates memory for dwc_otg_hcd_urb structure. ++ * Allocated memory should be freed by call of DWC_FREE. ++ * ++ * @param hcd The HCD ++ * @param iso_desc_count Count of ISOC descriptors ++ * @param atomic_alloc Specefies whether to perform atomic allocation. ++ */ ++extern dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd, ++ int iso_desc_count, ++ int atomic_alloc); ++ ++/** ++ * Set pipe information in URB. ++ * ++ * @param hcd_urb DWC_OTG URB ++ * @param devaddr Device Address ++ * @param ep_num Endpoint Number ++ * @param ep_type Endpoint Type ++ * @param ep_dir Endpoint Direction ++ * @param mps Max Packet Size ++ */ ++extern void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * hcd_urb, ++ uint8_t devaddr, uint8_t ep_num, ++ uint8_t ep_type, uint8_t ep_dir, ++ uint16_t mps); ++ ++/* Transfer flags */ ++#define URB_GIVEBACK_ASAP 0x1 ++#define URB_SEND_ZERO_PACKET 0x2 ++ ++/** ++ * Sets dwc_otg_hcd_urb parameters. ++ * ++ * @param urb DWC_OTG URB allocated by dwc_otg_hcd_urb_alloc function. ++ * @param urb_handle Unique handle for request, this will be passed back ++ * to function driver in completion callback. ++ * @param buf The buffer for the data ++ * @param dma The DMA buffer for the data ++ * @param buflen Transfer length ++ * @param sp Buffer for setup data ++ * @param sp_dma DMA address of setup data buffer ++ * @param flags Transfer flags ++ * @param interval Polling interval for interrupt or isochronous transfers. ++ */ ++extern void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * urb, ++ void *urb_handle, void *buf, ++ dwc_dma_t dma, uint32_t buflen, void *sp, ++ dwc_dma_t sp_dma, uint32_t flags, ++ uint16_t interval); ++ ++/** Gets status from dwc_otg_hcd_urb ++ * ++ * @param dwc_otg_urb DWC_OTG URB ++ */ ++extern uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb); ++ ++/** Gets actual length from dwc_otg_hcd_urb ++ * ++ * @param dwc_otg_urb DWC_OTG URB ++ */ ++extern uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * ++ dwc_otg_urb); ++ ++/** Gets error count from dwc_otg_hcd_urb. Only for ISOC URBs ++ * ++ * @param dwc_otg_urb DWC_OTG URB ++ */ ++extern uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * ++ dwc_otg_urb); ++ ++/** Set ISOC descriptor offset and length ++ * ++ * @param dwc_otg_urb DWC_OTG URB ++ * @param desc_num ISOC descriptor number ++ * @param offset Offset from beginig of buffer. ++ * @param length Transaction length ++ */ ++extern void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb, ++ int desc_num, uint32_t offset, ++ uint32_t length); ++ ++/** Get status of ISOC descriptor, specified by desc_num ++ * ++ * @param dwc_otg_urb DWC_OTG URB ++ * @param desc_num ISOC descriptor number ++ */ ++extern uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * ++ dwc_otg_urb, int desc_num); ++ ++/** Get actual length of ISOC descriptor, specified by desc_num ++ * ++ * @param dwc_otg_urb DWC_OTG URB ++ * @param desc_num ISOC descriptor number ++ */ ++extern uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t * ++ dwc_otg_urb, ++ int desc_num); ++ ++/** Queue URB. After transfer is completes, the complete callback will be called with the URB status ++ * ++ * @param dwc_otg_hcd The HCD ++ * @param dwc_otg_urb DWC_OTG URB ++ * @param ep_handle Out parameter for returning endpoint handle ++ * @param atomic_alloc Flag to do atomic allocation if needed ++ * ++ * Returns -DWC_E_NO_DEVICE if no device is connected. ++ * Returns -DWC_E_NO_MEMORY if there is no enough memory. ++ * Returns 0 on success. ++ */ ++extern int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * dwc_otg_hcd, ++ dwc_otg_hcd_urb_t * dwc_otg_urb, ++ void **ep_handle, int atomic_alloc); ++ ++/** De-queue the specified URB ++ * ++ * @param dwc_otg_hcd The HCD ++ * @param dwc_otg_urb DWC_OTG URB ++ */ ++extern int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * dwc_otg_hcd, ++ dwc_otg_hcd_urb_t * dwc_otg_urb); ++ ++/** Frees resources in the DWC_otg controller related to a given endpoint. ++ * Any URBs for the endpoint must already be dequeued. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function ++ * @param retry Number of retries if there are queued transfers. ++ * ++ * Returns -DWC_E_INVALID if invalid arguments are passed. ++ * Returns 0 on success ++ */ ++extern int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle, ++ int retry); ++ ++/* Resets the data toggle in qh structure. This function can be called from ++ * usb_clear_halt routine. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function ++ * ++ * Returns -DWC_E_INVALID if invalid arguments are passed. ++ * Returns 0 on success ++ */ ++extern int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle); ++ ++/** Returns 1 if status of specified port is changed and 0 otherwise. ++ * ++ * @param hcd The HCD ++ * @param port Port number ++ */ ++extern int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port); ++ ++/** Call this function to check if bandwidth was allocated for specified endpoint. ++ * Only for ISOC and INTERRUPT endpoints. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle ++ */ ++extern int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, ++ void *ep_handle); ++ ++/** Call this function to check if bandwidth was freed for specified endpoint. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle ++ */ ++extern int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle); ++ ++/** Returns bandwidth allocated for specified endpoint in microseconds. ++ * Only for ISOC and INTERRUPT endpoints. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle ++ */ ++extern uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, ++ void *ep_handle); ++ ++/** @} */ ++ ++#endif /* __DWC_HCD_IF_H__ */ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_intr.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_intr.c +new file mode 100644 +index 0000000..f843e65 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_intr.c +@@ -0,0 +1,2096 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $ ++ * $Revision: #94 $ ++ * $Date: 2013/01/31 $ ++ * $Change: 2155605 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_DEVICE_ONLY ++ ++#include "dwc_otg_hcd.h" ++#include "dwc_otg_regs.h" ++ ++/** @file ++ * This file contains the implementation of the HCD Interrupt handlers. ++ */ ++ ++/** This function handles interrupts for the HCD. */ ++int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ int retval = 0; ++ ++ dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; ++ gintsts_data_t gintsts; ++#ifdef DEBUG ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++#endif ++ ++ if (dwc_otg_check_haps_status(core_if) == -1 ) { ++ DWC_WARN("HAPS is disconnected"); ++ return retval; ++ } ++ ++ /* Exit from ISR if core is hibernated */ ++ if (core_if->hibernation_suspend == 1) { ++ return retval; ++ } ++ DWC_SPINLOCK(dwc_otg_hcd->lock); ++ /* Check if HOST Mode */ ++ if (dwc_otg_is_host_mode(core_if)) { ++ gintsts.d32 = dwc_otg_read_core_intr(core_if); ++ if (!gintsts.d32) { ++ DWC_SPINUNLOCK(dwc_otg_hcd->lock); ++ return 0; ++ } ++#ifdef DEBUG ++ /* Don't print debug message in the interrupt handler on SOF */ ++#ifndef DEBUG_SOF ++ if (gintsts.d32 != DWC_SOF_INTR_MASK) ++#endif ++ DWC_DEBUGPL(DBG_HCD, "\n"); ++#endif ++ ++#ifdef DEBUG ++#ifndef DEBUG_SOF ++ if (gintsts.d32 != DWC_SOF_INTR_MASK) ++#endif ++ DWC_DEBUGPL(DBG_HCD, ++ "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x\n", ++ gintsts.d32); ++#endif ++ ++ if (gintsts.b.sofintr) { ++ retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd); ++ } ++ if (gintsts.b.rxstsqlvl) { ++ retval |= ++ dwc_otg_hcd_handle_rx_status_q_level_intr ++ (dwc_otg_hcd); ++ } ++ if (gintsts.b.nptxfempty) { ++ retval |= ++ dwc_otg_hcd_handle_np_tx_fifo_empty_intr ++ (dwc_otg_hcd); ++ } ++ if (gintsts.b.i2cintr) { ++ /** @todo Implement i2cintr handler. */ ++ } ++ if (gintsts.b.portintr) { ++ retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd); ++ } ++ if (gintsts.b.hcintr) { ++ retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd); ++ } ++ if (gintsts.b.ptxfempty) { ++ retval |= ++ dwc_otg_hcd_handle_perio_tx_fifo_empty_intr ++ (dwc_otg_hcd); ++ } ++#ifdef DEBUG ++#ifndef DEBUG_SOF ++ if (gintsts.d32 != DWC_SOF_INTR_MASK) ++#endif ++ { ++ DWC_DEBUGPL(DBG_HCD, ++ "DWC OTG HCD Finished Servicing Interrupts\n"); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintsts=0x%08x\n", ++ DWC_READ_REG32(&global_regs->gintsts)); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintmsk=0x%08x\n", ++ DWC_READ_REG32(&global_regs->gintmsk)); ++ } ++#endif ++ ++#ifdef DEBUG ++#ifndef DEBUG_SOF ++ if (gintsts.d32 != DWC_SOF_INTR_MASK) ++#endif ++ DWC_DEBUGPL(DBG_HCD, "\n"); ++#endif ++ ++ } ++ DWC_SPINUNLOCK(dwc_otg_hcd->lock); ++ return retval; ++} ++ ++#ifdef DWC_TRACK_MISSED_SOFS ++#warning Compiling code to track missed SOFs ++#define FRAME_NUM_ARRAY_SIZE 1000 ++/** ++ * This function is for debug only. ++ */ ++static inline void track_missed_sofs(uint16_t curr_frame_number) ++{ ++ static uint16_t frame_num_array[FRAME_NUM_ARRAY_SIZE]; ++ static uint16_t last_frame_num_array[FRAME_NUM_ARRAY_SIZE]; ++ static int frame_num_idx = 0; ++ static uint16_t last_frame_num = DWC_HFNUM_MAX_FRNUM; ++ static int dumped_frame_num_array = 0; ++ ++ if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) { ++ if (((last_frame_num + 1) & DWC_HFNUM_MAX_FRNUM) != ++ curr_frame_number) { ++ frame_num_array[frame_num_idx] = curr_frame_number; ++ last_frame_num_array[frame_num_idx++] = last_frame_num; ++ } ++ } else if (!dumped_frame_num_array) { ++ int i; ++ DWC_PRINTF("Frame Last Frame\n"); ++ DWC_PRINTF("----- ----------\n"); ++ for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) { ++ DWC_PRINTF("0x%04x 0x%04x\n", ++ frame_num_array[i], last_frame_num_array[i]); ++ } ++ dumped_frame_num_array = 1; ++ } ++ last_frame_num = curr_frame_number; ++} ++#endif ++ ++/** ++ * Handles the start-of-frame interrupt in host mode. Non-periodic ++ * transactions may be queued to the DWC_otg controller for the current ++ * (micro)frame. Periodic transactions may be queued to the controller for the ++ * next (micro)frame. ++ */ ++int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd) ++{ ++ hfnum_data_t hfnum; ++ dwc_list_link_t *qh_entry; ++ dwc_otg_qh_t *qh; ++ dwc_otg_transaction_type_e tr_type; ++ gintsts_data_t gintsts = {.d32 = 0 }; ++ ++ hfnum.d32 = ++ DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum); ++ ++#ifdef DEBUG_SOF ++ DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n"); ++#endif ++ hcd->frame_number = hfnum.b.frnum; ++ ++#ifdef DEBUG ++ hcd->frrem_accum += hfnum.b.frrem; ++ hcd->frrem_samples++; ++#endif ++ ++#ifdef DWC_TRACK_MISSED_SOFS ++ track_missed_sofs(hcd->frame_number); ++#endif ++ /* Determine whether any periodic QHs should be executed. */ ++ qh_entry = DWC_LIST_FIRST(&hcd->periodic_sched_inactive); ++ while (qh_entry != &hcd->periodic_sched_inactive) { ++ qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry); ++ qh_entry = qh_entry->next; ++ if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) { ++ /* ++ * Move QH to the ready list to be executed next ++ * (micro)frame. ++ */ ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready, ++ &qh->qh_list_entry); ++ } ++ } ++ tr_type = dwc_otg_hcd_select_transactions(hcd); ++ if (tr_type != DWC_OTG_TRANSACTION_NONE) { ++ dwc_otg_hcd_queue_transactions(hcd, tr_type); ++ } ++ ++ /* Clear interrupt */ ++ gintsts.b.sofintr = 1; ++ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** Handles the Rx Status Queue Level Interrupt, which indicates that there is at ++ * least one packet in the Rx FIFO. The packets are moved from the FIFO to ++ * memory if the DWC_otg controller is operating in Slave mode. */ ++int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ host_grxsts_data_t grxsts; ++ dwc_hc_t *hc = NULL; ++ ++ DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n"); ++ ++ grxsts.d32 = ++ DWC_READ_REG32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp); ++ ++ hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum]; ++ if (!hc) { ++ DWC_ERROR("Unable to get corresponding channel\n"); ++ return 0; ++ } ++ ++ /* Packet Status */ ++ DWC_DEBUGPL(DBG_HCDV, " Ch num = %d\n", grxsts.b.chnum); ++ DWC_DEBUGPL(DBG_HCDV, " Count = %d\n", grxsts.b.bcnt); ++ DWC_DEBUGPL(DBG_HCDV, " DPID = %d, hc.dpid = %d\n", grxsts.b.dpid, ++ hc->data_pid_start); ++ DWC_DEBUGPL(DBG_HCDV, " PStatus = %d\n", grxsts.b.pktsts); ++ ++ switch (grxsts.b.pktsts) { ++ case DWC_GRXSTS_PKTSTS_IN: ++ /* Read the data into the host buffer. */ ++ if (grxsts.b.bcnt > 0) { ++ dwc_otg_read_packet(dwc_otg_hcd->core_if, ++ hc->xfer_buff, grxsts.b.bcnt); ++ ++ /* Update the HC fields for the next packet received. */ ++ hc->xfer_count += grxsts.b.bcnt; ++ hc->xfer_buff += grxsts.b.bcnt; ++ } ++ ++ case DWC_GRXSTS_PKTSTS_IN_XFER_COMP: ++ case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR: ++ case DWC_GRXSTS_PKTSTS_CH_HALTED: ++ /* Handled in interrupt, just ignore data */ ++ break; ++ default: ++ DWC_ERROR("RX_STS_Q Interrupt: Unknown status %d\n", ++ grxsts.b.pktsts); ++ break; ++ } ++ ++ return 1; ++} ++ ++/** This interrupt occurs when the non-periodic Tx FIFO is half-empty. More ++ * data packets may be written to the FIFO for OUT transfers. More requests ++ * may be written to the non-periodic request queue for IN transfers. This ++ * interrupt is enabled only in Slave mode. */ ++int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Non-Periodic TxFIFO Empty Interrupt--\n"); ++ dwc_otg_hcd_queue_transactions(dwc_otg_hcd, ++ DWC_OTG_TRANSACTION_NON_PERIODIC); ++ return 1; ++} ++ ++/** This interrupt occurs when the periodic Tx FIFO is half-empty. More data ++ * packets may be written to the FIFO for OUT transfers. More requests may be ++ * written to the periodic request queue for IN transfers. This interrupt is ++ * enabled only in Slave mode. */ ++int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n"); ++ dwc_otg_hcd_queue_transactions(dwc_otg_hcd, ++ DWC_OTG_TRANSACTION_PERIODIC); ++ return 1; ++} ++ ++/** There are multiple conditions that can cause a port interrupt. This function ++ * determines which interrupt conditions have occurred and handles them ++ * appropriately. */ ++int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ int retval = 0; ++ hprt0_data_t hprt0; ++ hprt0_data_t hprt0_modify; ++ ++ hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0); ++ hprt0_modify.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0); ++ ++ /* Clear appropriate bits in HPRT0 to clear the interrupt bit in ++ * GINTSTS */ ++ ++ hprt0_modify.b.prtena = 0; ++ hprt0_modify.b.prtconndet = 0; ++ hprt0_modify.b.prtenchng = 0; ++ hprt0_modify.b.prtovrcurrchng = 0; ++ ++ /* Port Connect Detected ++ * Set flag and clear if detected */ ++ if (dwc_otg_hcd->core_if->hibernation_suspend == 1) { ++ // Dont modify port status if we are in hibernation state ++ hprt0_modify.b.prtconndet = 1; ++ hprt0_modify.b.prtenchng = 1; ++ DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32); ++ hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0); ++ return retval; ++ } ++ ++ if (hprt0.b.prtconndet) { ++ /** @todo - check if steps performed in 'else' block should be perfromed regardles adp */ ++ if (dwc_otg_hcd->core_if->adp_enable && ++ dwc_otg_hcd->core_if->adp.vbuson_timer_started == 1) { ++ DWC_PRINTF("PORT CONNECT DETECTED ----------------\n"); ++ DWC_TIMER_CANCEL(dwc_otg_hcd->core_if->adp.vbuson_timer); ++ dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0; ++ /* TODO - check if this is required, as ++ * host initialization was already performed ++ * after initial ADP probing ++ */ ++ /*dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0; ++ dwc_otg_core_init(dwc_otg_hcd->core_if); ++ dwc_otg_enable_global_interrupts(dwc_otg_hcd->core_if); ++ cil_hcd_start(dwc_otg_hcd->core_if);*/ ++ } else { ++ hprt0_data_t hprt0_local; ++ DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x " ++ "Port Connect Detected--\n", hprt0.d32); ++ dwc_otg_hcd->flags.b.port_connect_status_change = 1; ++ dwc_otg_hcd->flags.b.port_connect_status = 1; ++ hprt0_modify.b.prtconndet = 1; ++ /* PET testing */ ++ if (dwc_otg_hcd->core_if->otg_ver && (dwc_otg_hcd->core_if->test_mode == 7)) { ++ hprt0_local.d32 = dwc_otg_read_hprt0(dwc_otg_hcd->core_if); ++ hprt0_local.b.prtrst = 1; ++ DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_local.d32); ++ dwc_mdelay(60); ++ hprt0.d32 = dwc_otg_read_hprt0(dwc_otg_hcd->core_if); ++ hprt0.b.prtrst = 0; ++ DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0.d32); ++ } ++ ++ /* B-Device has connected, Delete the connection timer. */ ++ DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer); ++ } ++ /* The Hub driver asserts a reset when it sees port connect ++ * status change flag */ ++ retval |= 1; ++ } ++ ++ /* Port Enable Changed ++ * Clear if detected - Set internal flag if disabled */ ++ if (hprt0.b.prtenchng) { ++ DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x " ++ "Port Enable Changed--\n", hprt0.d32); ++ hprt0_modify.b.prtenchng = 1; ++ if (hprt0.b.prtena == 1) { ++ hfir_data_t hfir; ++ int do_reset = 0; ++ dwc_otg_core_params_t *params = ++ dwc_otg_hcd->core_if->core_params; ++ dwc_otg_core_global_regs_t *global_regs = ++ dwc_otg_hcd->core_if->core_global_regs; ++ dwc_otg_host_if_t *host_if = ++ dwc_otg_hcd->core_if->host_if; ++ ++ /* Every time when port enables calculate ++ * HFIR.FrInterval ++ */ ++ hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir); ++ hfir.b.frint = calc_frame_interval(dwc_otg_hcd->core_if); ++ DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32); ++ ++ /* Check if we need to adjust the PHY clock speed for ++ * low power and adjust it */ ++ if (params->host_support_fs_ls_low_power) { ++ gusbcfg_data_t usbcfg; ++ ++ usbcfg.d32 = ++ DWC_READ_REG32(&global_regs->gusbcfg); ++ ++ if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED ++ || hprt0.b.prtspd == ++ DWC_HPRT0_PRTSPD_FULL_SPEED) { ++ /* ++ * Low power ++ */ ++ hcfg_data_t hcfg; ++ if (usbcfg.b.phylpwrclksel == 0) { ++ /* Set PHY low power clock select for FS/LS devices */ ++ usbcfg.b.phylpwrclksel = 1; ++ DWC_WRITE_REG32 ++ (&global_regs->gusbcfg, ++ usbcfg.d32); ++ do_reset = 1; ++ } ++ ++ hcfg.d32 = ++ DWC_READ_REG32 ++ (&host_if->host_global_regs->hcfg); ++ ++ if (hprt0.b.prtspd == ++ DWC_HPRT0_PRTSPD_LOW_SPEED ++ && params->host_ls_low_power_phy_clk ++ == ++ DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ) ++ { ++ /* 6 MHZ */ ++ DWC_DEBUGPL(DBG_CIL, ++ "FS_PHY programming HCFG to 6 MHz (Low Power)\n"); ++ if (hcfg.b.fslspclksel != ++ DWC_HCFG_6_MHZ) { ++ hcfg.b.fslspclksel = ++ DWC_HCFG_6_MHZ; ++ DWC_WRITE_REG32 ++ (&host_if->host_global_regs->hcfg, ++ hcfg.d32); ++ do_reset = 1; ++ } ++ } else { ++ /* 48 MHZ */ ++ DWC_DEBUGPL(DBG_CIL, ++ "FS_PHY programming HCFG to 48 MHz ()\n"); ++ if (hcfg.b.fslspclksel != ++ DWC_HCFG_48_MHZ) { ++ hcfg.b.fslspclksel = ++ DWC_HCFG_48_MHZ; ++ DWC_WRITE_REG32 ++ (&host_if->host_global_regs->hcfg, ++ hcfg.d32); ++ do_reset = 1; ++ } ++ } ++ } else { ++ /* ++ * Not low power ++ */ ++ if (usbcfg.b.phylpwrclksel == 1) { ++ usbcfg.b.phylpwrclksel = 0; ++ DWC_WRITE_REG32 ++ (&global_regs->gusbcfg, ++ usbcfg.d32); ++ do_reset = 1; ++ } ++ } ++ ++ if (do_reset) { ++ DWC_TASK_SCHEDULE(dwc_otg_hcd->reset_tasklet); ++ } ++ } ++ ++ if (!do_reset) { ++ /* Port has been enabled set the reset change flag */ ++ dwc_otg_hcd->flags.b.port_reset_change = 1; ++ } ++ } else { ++ dwc_otg_hcd->flags.b.port_enable_change = 1; ++ } ++ retval |= 1; ++ } ++ ++ /** Overcurrent Change Interrupt */ ++ if (hprt0.b.prtovrcurrchng) { ++ DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x " ++ "Port Overcurrent Changed--\n", hprt0.d32); ++ dwc_otg_hcd->flags.b.port_over_current_change = 1; ++ hprt0_modify.b.prtovrcurrchng = 1; ++ retval |= 1; ++ } ++ ++ /* Clear Port Interrupts */ ++ DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32); ++ ++ return retval; ++} ++ ++/** This interrupt indicates that one or more host channels has a pending ++ * interrupt. There are multiple conditions that can cause each host channel ++ * interrupt. This function determines which conditions have occurred for each ++ * host channel interrupt and handles them appropriately. */ ++int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ int i; ++ int retval = 0; ++ haint_data_t haint; ++ ++ /* Clear appropriate bits in HCINTn to clear the interrupt bit in ++ * GINTSTS */ ++ ++ haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if); ++ ++ for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) { ++ if (haint.b2.chint & (1 << i)) { ++ retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i); ++ } ++ } ++ ++ return retval; ++} ++ ++/** ++ * Gets the actual length of a transfer after the transfer halts. _halt_status ++ * holds the reason for the halt. ++ * ++ * For IN transfers where halt_status is DWC_OTG_HC_XFER_COMPLETE, ++ * *short_read is set to 1 upon return if less than the requested ++ * number of bytes were transferred. Otherwise, *short_read is set to 0 upon ++ * return. short_read may also be NULL on entry, in which case it remains ++ * unchanged. ++ */ ++static uint32_t get_actual_xfer_length(dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_halt_status_e halt_status, ++ int *short_read) ++{ ++ hctsiz_data_t hctsiz; ++ uint32_t length; ++ ++ if (short_read != NULL) { ++ *short_read = 0; ++ } ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ ++ if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { ++ if (hc->ep_is_in) { ++ length = hc->xfer_len - hctsiz.b.xfersize; ++ if (short_read != NULL) { ++ *short_read = (hctsiz.b.xfersize != 0); ++ } ++ } else if (hc->qh->do_split) { ++ length = qtd->ssplit_out_xfer_count; ++ } else { ++ length = hc->xfer_len; ++ } ++ } else { ++ /* ++ * Must use the hctsiz.pktcnt field to determine how much data ++ * has been transferred. This field reflects the number of ++ * packets that have been transferred via the USB. This is ++ * always an integral number of packets if the transfer was ++ * halted before its normal completion. (Can't use the ++ * hctsiz.xfersize field because that reflects the number of ++ * bytes transferred via the AHB, not the USB). ++ */ ++ length = ++ (hc->start_pkt_count - hctsiz.b.pktcnt) * hc->max_packet; ++ } ++ ++ return length; ++} ++ ++/** ++ * Updates the state of the URB after a Transfer Complete interrupt on the ++ * host channel. Updates the actual_length field of the URB based on the ++ * number of bytes transferred via the host channel. Sets the URB status ++ * if the data transfer is finished. ++ * ++ * @return 1 if the data transfer specified by the URB is completely finished, ++ * 0 otherwise. ++ */ ++static int update_urb_state_xfer_comp(dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_hcd_urb_t * urb, ++ dwc_otg_qtd_t * qtd) ++{ ++ int xfer_done = 0; ++ int short_read = 0; ++ ++ int xfer_length; ++ ++ xfer_length = get_actual_xfer_length(hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_COMPLETE, ++ &short_read); ++ ++ ++ /* non DWORD-aligned buffer case handling. */ ++ if (hc->align_buff && xfer_length && hc->ep_is_in) { ++ dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, ++ xfer_length); ++ } ++ ++ urb->actual_length += xfer_length; ++ ++ if (xfer_length && (hc->ep_type == DWC_OTG_EP_TYPE_BULK) && ++ (urb->flags & URB_SEND_ZERO_PACKET) ++ && (urb->actual_length == urb->length) ++ && !(urb->length % hc->max_packet)) { ++ xfer_done = 0; ++ } else if (short_read || urb->actual_length == urb->length) { ++ xfer_done = 1; ++ urb->status = 0; ++ } ++ ++#ifdef DEBUG ++ { ++ hctsiz_data_t hctsiz; ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n", ++ __func__, (hc->ep_is_in ? "IN" : "OUT"), ++ hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " hc->xfer_len %d\n", hc->xfer_len); ++ DWC_DEBUGPL(DBG_HCDV, " hctsiz.xfersize %d\n", ++ hctsiz.b.xfersize); ++ DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n", ++ urb->length); ++ DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n", ++ urb->actual_length); ++ DWC_DEBUGPL(DBG_HCDV, " short_read %d, xfer_done %d\n", ++ short_read, xfer_done); ++ } ++#endif ++ ++ return xfer_done; ++} ++ ++/* ++ * Save the starting data toggle for the next transfer. The data toggle is ++ * saved in the QH for non-control transfers and it's saved in the QTD for ++ * control transfers. ++ */ ++void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, dwc_otg_qtd_t * qtd) ++{ ++ hctsiz_data_t hctsiz; ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ ++ if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) { ++ dwc_otg_qh_t *qh = hc->qh; ++ if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) { ++ qh->data_toggle = DWC_OTG_HC_PID_DATA0; ++ } else { ++ qh->data_toggle = DWC_OTG_HC_PID_DATA1; ++ } ++ } else { ++ if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) { ++ qtd->data_toggle = DWC_OTG_HC_PID_DATA0; ++ } else { ++ qtd->data_toggle = DWC_OTG_HC_PID_DATA1; ++ } ++ } ++} ++ ++/** ++ * Updates the state of an Isochronous URB when the transfer is stopped for ++ * any reason. The fields of the current entry in the frame descriptor array ++ * are set based on the transfer state and the input _halt_status. Completes ++ * the Isochronous URB if all the URB frames have been completed. ++ * ++ * @return DWC_OTG_HC_XFER_COMPLETE if there are more frames remaining to be ++ * transferred in the URB. Otherwise return DWC_OTG_HC_XFER_URB_COMPLETE. ++ */ ++static dwc_otg_halt_status_e ++update_isoc_urb_state(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status) ++{ ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ dwc_otg_halt_status_e ret_val = halt_status; ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc; ++ ++ frame_desc = &urb->iso_descs[qtd->isoc_frame_index]; ++ switch (halt_status) { ++ case DWC_OTG_HC_XFER_COMPLETE: ++ frame_desc->status = 0; ++ frame_desc->actual_length = ++ get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL); ++ ++ /* non DWORD-aligned buffer case handling. */ ++ if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) { ++ dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, ++ hc->qh->dw_align_buf, frame_desc->actual_length); ++ } ++ ++ break; ++ case DWC_OTG_HC_XFER_FRAME_OVERRUN: ++ urb->error_count++; ++ if (hc->ep_is_in) { ++ frame_desc->status = -DWC_E_NO_STREAM_RES; ++ } else { ++ frame_desc->status = -DWC_E_COMMUNICATION; ++ } ++ frame_desc->actual_length = 0; ++ break; ++ case DWC_OTG_HC_XFER_BABBLE_ERR: ++ urb->error_count++; ++ frame_desc->status = -DWC_E_OVERFLOW; ++ /* Don't need to update actual_length in this case. */ ++ break; ++ case DWC_OTG_HC_XFER_XACT_ERR: ++ urb->error_count++; ++ frame_desc->status = -DWC_E_PROTOCOL; ++ frame_desc->actual_length = ++ get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL); ++ ++ /* non DWORD-aligned buffer case handling. */ ++ if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) { ++ dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, ++ hc->qh->dw_align_buf, frame_desc->actual_length); ++ } ++ /* Skip whole frame */ ++ if (hc->qh->do_split && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && ++ hc->ep_is_in && hcd->core_if->dma_enable) { ++ qtd->complete_split = 0; ++ qtd->isoc_split_offset = 0; ++ } ++ ++ break; ++ default: ++ DWC_ASSERT(1, "Unhandled _halt_status (%d)\n", halt_status); ++ break; ++ } ++ if (++qtd->isoc_frame_index == urb->packet_count) { ++ /* ++ * urb->status is not used for isoc transfers. ++ * The individual frame_desc statuses are used instead. ++ */ ++ hcd->fops->complete(hcd, urb->priv, urb, 0); ++ ret_val = DWC_OTG_HC_XFER_URB_COMPLETE; ++ } else { ++ ret_val = DWC_OTG_HC_XFER_COMPLETE; ++ } ++ return ret_val; ++} ++ ++/** ++ * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic ++ * QHs, removes the QH from the active non-periodic schedule. If any QTDs are ++ * still linked to the QH, the QH is added to the end of the inactive ++ * non-periodic schedule. For periodic QHs, removes the QH from the periodic ++ * schedule if no more QTDs are linked to the QH. ++ */ ++static void deactivate_qh(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, int free_qtd) ++{ ++ int continue_split = 0; ++ dwc_otg_qtd_t *qtd; ++ ++ DWC_DEBUGPL(DBG_HCDV, " %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd); ++ ++ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); ++ ++ if (qtd->complete_split) { ++ continue_split = 1; ++ } else if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID || ++ qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END) { ++ continue_split = 1; ++ } ++ ++ if (free_qtd) { ++ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ continue_split = 0; ++ } ++ ++ qh->channel = NULL; ++ dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split); ++} ++ ++/** ++ * Releases a host channel for use by other transfers. Attempts to select and ++ * queue more transactions since at least one host channel is available. ++ * ++ * @param hcd The HCD state structure. ++ * @param hc The host channel to release. ++ * @param qtd The QTD associated with the host channel. This QTD may be freed ++ * if the transfer is complete or an error has occurred. ++ * @param halt_status Reason the channel is being released. This status ++ * determines the actions taken by this function. ++ */ ++static void release_channel(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_halt_status_e halt_status) ++{ ++ dwc_otg_transaction_type_e tr_type; ++ int free_qtd; ++ ++ DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d\n", ++ __func__, hc->hc_num, halt_status); ++ ++ switch (halt_status) { ++ case DWC_OTG_HC_XFER_URB_COMPLETE: ++ free_qtd = 1; ++ break; ++ case DWC_OTG_HC_XFER_AHB_ERR: ++ case DWC_OTG_HC_XFER_STALL: ++ case DWC_OTG_HC_XFER_BABBLE_ERR: ++ free_qtd = 1; ++ break; ++ case DWC_OTG_HC_XFER_XACT_ERR: ++ if (qtd->error_count >= 3) { ++ DWC_DEBUGPL(DBG_HCDV, ++ " Complete URB with transaction error\n"); ++ free_qtd = 1; ++ qtd->urb->status = -DWC_E_PROTOCOL; ++ hcd->fops->complete(hcd, qtd->urb->priv, ++ qtd->urb, -DWC_E_PROTOCOL); ++ } else { ++ free_qtd = 0; ++ } ++ break; ++ case DWC_OTG_HC_XFER_URB_DEQUEUE: ++ /* ++ * The QTD has already been removed and the QH has been ++ * deactivated. Don't want to do anything except release the ++ * host channel and try to queue more transfers. ++ */ ++ goto cleanup; ++ case DWC_OTG_HC_XFER_NO_HALT_STATUS: ++ free_qtd = 0; ++ break; ++ case DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE: ++ DWC_DEBUGPL(DBG_HCDV, ++ " Complete URB with I/O error\n"); ++ free_qtd = 1; ++ qtd->urb->status = -DWC_E_IO; ++ hcd->fops->complete(hcd, qtd->urb->priv, ++ qtd->urb, -DWC_E_IO); ++ break; ++ default: ++ free_qtd = 0; ++ break; ++ } ++ ++ deactivate_qh(hcd, hc->qh, free_qtd); ++ ++cleanup: ++ /* ++ * Release the host channel for use by other transfers. The cleanup ++ * function clears the channel interrupt enables and conditions, so ++ * there's no need to clear the Channel Halted interrupt separately. ++ */ ++ dwc_otg_hc_cleanup(hcd->core_if, hc); ++ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); ++ ++ switch (hc->ep_type) { ++ case DWC_OTG_EP_TYPE_CONTROL: ++ case DWC_OTG_EP_TYPE_BULK: ++ hcd->non_periodic_channels--; ++ break; ++ ++ default: ++ /* ++ * Don't release reservations for periodic channels here. ++ * That's done when a periodic transfer is descheduled (i.e. ++ * when the QH is removed from the periodic schedule). ++ */ ++ break; ++ } ++ ++ /* Try to queue more transfers now that there's a free channel. */ ++ tr_type = dwc_otg_hcd_select_transactions(hcd); ++ if (tr_type != DWC_OTG_TRANSACTION_NONE) { ++ dwc_otg_hcd_queue_transactions(hcd, tr_type); ++ } ++} ++ ++/** ++ * Halts a host channel. If the channel cannot be halted immediately because ++ * the request queue is full, this function ensures that the FIFO empty ++ * interrupt for the appropriate queue is enabled so that the halt request can ++ * be queued when there is space in the request queue. ++ * ++ * This function may also be called in DMA mode. In that case, the channel is ++ * simply released since the core always halts the channel automatically in ++ * DMA mode. ++ */ ++static void halt_channel(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status) ++{ ++ if (hcd->core_if->dma_enable) { ++ release_channel(hcd, hc, qtd, halt_status); ++ return; ++ } ++ ++ /* Slave mode processing... */ ++ dwc_otg_hc_halt(hcd->core_if, hc, halt_status); ++ ++ if (hc->halt_on_queue) { ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ dwc_otg_core_global_regs_t *global_regs; ++ global_regs = hcd->core_if->core_global_regs; ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || ++ hc->ep_type == DWC_OTG_EP_TYPE_BULK) { ++ /* ++ * Make sure the Non-periodic Tx FIFO empty interrupt ++ * is enabled so that the non-periodic schedule will ++ * be processed. ++ */ ++ gintmsk.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); ++ } else { ++ /* ++ * Move the QH from the periodic queued schedule to ++ * the periodic assigned schedule. This allows the ++ * halt to be queued when the periodic schedule is ++ * processed. ++ */ ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, ++ &hc->qh->qh_list_entry); ++ ++ /* ++ * Make sure the Periodic Tx FIFO Empty interrupt is ++ * enabled so that the periodic schedule will be ++ * processed. ++ */ ++ gintmsk.b.ptxfempty = 1; ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); ++ } ++ } ++} ++ ++/** ++ * Performs common cleanup for non-periodic transfers after a Transfer ++ * Complete interrupt. This function should be called after any endpoint type ++ * specific handling is finished to release the host channel. ++ */ ++static void complete_non_periodic_xfer(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_halt_status_e halt_status) ++{ ++ hcint_data_t hcint; ++ ++ qtd->error_count = 0; ++ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ if (hcint.b.nyet) { ++ /* ++ * Got a NYET on the last transaction of the transfer. This ++ * means that the endpoint should be in the PING state at the ++ * beginning of the next transfer. ++ */ ++ hc->qh->ping_state = 1; ++ clear_hc_int(hc_regs, nyet); ++ } ++ ++ /* ++ * Always halt and release the host channel to make it available for ++ * more transfers. There may still be more phases for a control ++ * transfer or more data packets for a bulk transfer at this point, ++ * but the host channel is still halted. A channel will be reassigned ++ * to the transfer when the non-periodic schedule is processed after ++ * the channel is released. This allows transactions to be queued ++ * properly via dwc_otg_hcd_queue_transactions, which also enables the ++ * Tx FIFO Empty interrupt if necessary. ++ */ ++ if (hc->ep_is_in) { ++ /* ++ * IN transfers in Slave mode require an explicit disable to ++ * halt the channel. (In DMA mode, this call simply releases ++ * the channel.) ++ */ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } else { ++ /* ++ * The channel is automatically disabled by the core for OUT ++ * transfers in Slave mode. ++ */ ++ release_channel(hcd, hc, qtd, halt_status); ++ } ++} ++ ++/** ++ * Performs common cleanup for periodic transfers after a Transfer Complete ++ * interrupt. This function should be called after any endpoint type specific ++ * handling is finished to release the host channel. ++ */ ++static void complete_periodic_xfer(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_halt_status_e halt_status) ++{ ++ hctsiz_data_t hctsiz; ++ qtd->error_count = 0; ++ ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) { ++ /* Core halts channel in these cases. */ ++ release_channel(hcd, hc, qtd, halt_status); ++ } else { ++ /* Flush any outstanding requests from the Tx queue. */ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++} ++ ++static int32_t handle_xfercomp_isoc_split_in(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ uint32_t len; ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc; ++ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; ++ ++ len = get_actual_xfer_length(hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_COMPLETE, NULL); ++ ++ if (!len) { ++ qtd->complete_split = 0; ++ qtd->isoc_split_offset = 0; ++ return 0; ++ } ++ frame_desc->actual_length += len; ++ ++ if (hc->align_buff && len) ++ dwc_memcpy(qtd->urb->buf + frame_desc->offset + ++ qtd->isoc_split_offset, hc->qh->dw_align_buf, len); ++ qtd->isoc_split_offset += len; ++ ++ if (frame_desc->length == frame_desc->actual_length) { ++ frame_desc->status = 0; ++ qtd->isoc_frame_index++; ++ qtd->complete_split = 0; ++ qtd->isoc_split_offset = 0; ++ } ++ ++ if (qtd->isoc_frame_index == qtd->urb->packet_count) { ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); ++ } else { ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS); ++ } ++ ++ return 1; /* Indicates that channel released */ ++} ++ ++/** ++ * Handles a host channel Transfer Complete interrupt. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ int urb_xfer_done; ++ dwc_otg_halt_status_e halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info); ++ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Transfer Complete--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_desc_enable) { ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, halt_status); ++ if (pipe_type == UE_ISOCHRONOUS) { ++ /* Do not disable the interrupt, just clear it */ ++ clear_hc_int(hc_regs, xfercomp); ++ return 1; ++ } ++ goto handle_xfercomp_done; ++ } ++ ++ /* ++ * Handle xfer complete on CSPLIT. ++ */ ++ ++ if (hc->qh->do_split) { ++ if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hc->ep_is_in ++ && hcd->core_if->dma_enable) { ++ if (qtd->complete_split ++ && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs, ++ qtd)) ++ goto handle_xfercomp_done; ++ } else { ++ qtd->complete_split = 0; ++ } ++ } ++ ++ /* Update the QTD and URB states. */ ++ switch (pipe_type) { ++ case UE_CONTROL: ++ switch (qtd->control_phase) { ++ case DWC_OTG_CONTROL_SETUP: ++ if (urb->length > 0) { ++ qtd->control_phase = DWC_OTG_CONTROL_DATA; ++ } else { ++ qtd->control_phase = DWC_OTG_CONTROL_STATUS; ++ } ++ DWC_DEBUGPL(DBG_HCDV, ++ " Control setup transaction done\n"); ++ halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ break; ++ case DWC_OTG_CONTROL_DATA:{ ++ urb_xfer_done = ++ update_urb_state_xfer_comp(hc, hc_regs, urb, ++ qtd); ++ if (urb_xfer_done) { ++ qtd->control_phase = ++ DWC_OTG_CONTROL_STATUS; ++ DWC_DEBUGPL(DBG_HCDV, ++ " Control data transfer done\n"); ++ } else { ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ } ++ halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ break; ++ } ++ case DWC_OTG_CONTROL_STATUS: ++ DWC_DEBUGPL(DBG_HCDV, " Control transfer complete\n"); ++ if (urb->status == -DWC_E_IN_PROGRESS) { ++ urb->status = 0; ++ } ++ hcd->fops->complete(hcd, urb->priv, urb, urb->status); ++ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; ++ if (!hcd->core_if->dma_enable && hcd->core_if->otg_ver == 1) ++ qtd->urb = NULL; ++ break; ++ } ++ ++ complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); ++ break; ++ case UE_BULK: ++ DWC_DEBUGPL(DBG_HCDV, " Bulk transfer complete\n"); ++ urb_xfer_done = ++ update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); ++ if (urb_xfer_done) { ++ hcd->fops->complete(hcd, urb->priv, urb, urb->status); ++ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; ++ } else { ++ halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ } ++ ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); ++ break; ++ case UE_INTERRUPT: ++ DWC_DEBUGPL(DBG_HCDV, " Interrupt transfer complete\n"); ++ urb_xfer_done = ++ update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); ++ ++ /* ++ * Interrupt URB is done on the first transfer complete ++ * interrupt. ++ */ ++ if (urb_xfer_done) { ++ hcd->fops->complete(hcd, urb->priv, urb, urb->status); ++ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; ++ } else { ++ halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ } ++ ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); ++ break; ++ case UE_ISOCHRONOUS: ++ DWC_DEBUGPL(DBG_HCDV, " Isochronous transfer complete\n"); ++ if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) { ++ halt_status = ++ update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_COMPLETE); ++ } ++ complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); ++ break; ++ } ++ ++handle_xfercomp_done: ++ disable_hc_int(hc_regs, xfercompl); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel STALL interrupt. This handler may be called in ++ * either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_stall_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info); ++ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "STALL Received--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_desc_enable) { ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_STALL); ++ goto handle_stall_done; ++ } ++ ++ if (pipe_type == UE_CONTROL) { ++ hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE); ++ } ++ ++ if (pipe_type == UE_BULK || pipe_type == UE_INTERRUPT) { ++ hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE); ++ /* ++ * USB protocol requires resetting the data toggle for bulk ++ * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT) ++ * setup command is issued to the endpoint. Anticipate the ++ * CLEAR_FEATURE command since a STALL has occurred and reset ++ * the data toggle now. ++ */ ++ hc->qh->data_toggle = 0; ++ } ++ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL); ++ ++handle_stall_done: ++ disable_hc_int(hc_regs, stall); ++ ++ return 1; ++} ++ ++/* ++ * Updates the state of the URB when a transfer has been stopped due to an ++ * abnormal condition before the transfer completes. Modifies the ++ * actual_length field of the URB to reflect the number of bytes that have ++ * actually been transferred via the host channel. ++ */ ++static void update_urb_state_xfer_intr(dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_hcd_urb_t * urb, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_halt_status_e halt_status) ++{ ++ uint32_t bytes_transferred = get_actual_xfer_length(hc, hc_regs, qtd, ++ halt_status, NULL); ++ /* non DWORD-aligned buffer case handling. */ ++ if (hc->align_buff && bytes_transferred && hc->ep_is_in) { ++ dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, ++ bytes_transferred); ++ } ++ ++ urb->actual_length += bytes_transferred; ++ ++#ifdef DEBUG ++ { ++ hctsiz_data_t hctsiz; ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n", ++ __func__, (hc->ep_is_in ? "IN" : "OUT"), ++ hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " hc->start_pkt_count %d\n", ++ hc->start_pkt_count); ++ DWC_DEBUGPL(DBG_HCDV, " hctsiz.pktcnt %d\n", hctsiz.b.pktcnt); ++ DWC_DEBUGPL(DBG_HCDV, " hc->max_packet %d\n", hc->max_packet); ++ DWC_DEBUGPL(DBG_HCDV, " bytes_transferred %d\n", ++ bytes_transferred); ++ DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n", ++ urb->actual_length); ++ DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n", ++ urb->length); ++ } ++#endif ++} ++ ++/** ++ * Handles a host channel NAK interrupt. This handler may be called in either ++ * DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "NAK Received--\n", hc->hc_num); ++ ++ /* ++ * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and ++ * interrupt. Re-start the SSPLIT transfer. ++ */ ++ if (hc->do_split) { ++ if (hc->complete_split) { ++ qtd->error_count = 0; ++ } ++ qtd->complete_split = 0; ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); ++ goto handle_nak_done; ++ } ++ ++ switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { ++ case UE_CONTROL: ++ case UE_BULK: ++ if (hcd->core_if->dma_enable && hc->ep_is_in) { ++ /* ++ * NAK interrupts are enabled on bulk/control IN ++ * transfers in DMA mode for the sole purpose of ++ * resetting the error count after a transaction error ++ * occurs. The core will continue transferring data. ++ */ ++ qtd->error_count = 0; ++ goto handle_nak_done; ++ } ++ ++ /* ++ * NAK interrupts normally occur during OUT transfers in DMA ++ * or Slave mode. For IN transfers, more requests will be ++ * queued as request queue space is available. ++ */ ++ qtd->error_count = 0; ++ ++ if (!hc->qh->ping_state) { ++ update_urb_state_xfer_intr(hc, hc_regs, ++ qtd->urb, qtd, ++ DWC_OTG_HC_XFER_NAK); ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ ++ if (hc->speed == DWC_OTG_EP_SPEED_HIGH) ++ hc->qh->ping_state = 1; ++ } ++ ++ /* ++ * Halt the channel so the transfer can be re-started from ++ * the appropriate point or the PING protocol will ++ * start/continue. ++ */ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); ++ break; ++ case UE_INTERRUPT: ++ qtd->error_count = 0; ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); ++ break; ++ case UE_ISOCHRONOUS: ++ /* Should never get called for isochronous transfers. */ ++ DWC_ASSERT(1, "NACK interrupt for ISOC transfer\n"); ++ break; ++ } ++ ++handle_nak_done: ++ disable_hc_int(hc_regs, nak); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel ACK interrupt. This interrupt is enabled when ++ * performing the PING protocol in Slave mode, when errors occur during ++ * either Slave mode or DMA mode, and during Start Split transactions. ++ */ ++static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "ACK Received--\n", hc->hc_num); ++ ++ if (hc->do_split) { ++ /* ++ * Handle ACK on SSPLIT. ++ * ACK should not occur in CSPLIT. ++ */ ++ if (!hc->ep_is_in && hc->data_pid_start != DWC_OTG_HC_PID_SETUP) { ++ qtd->ssplit_out_xfer_count = hc->xfer_len; ++ } ++ if (!(hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)) { ++ /* Don't need complete for isochronous out transfers. */ ++ qtd->complete_split = 1; ++ } ++ ++ /* ISOC OUT */ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) { ++ switch (hc->xact_pos) { ++ case DWC_HCSPLIT_XACTPOS_ALL: ++ break; ++ case DWC_HCSPLIT_XACTPOS_END: ++ qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL; ++ qtd->isoc_split_offset = 0; ++ break; ++ case DWC_HCSPLIT_XACTPOS_BEGIN: ++ case DWC_HCSPLIT_XACTPOS_MID: ++ /* ++ * For BEGIN or MID, calculate the length for ++ * the next microframe to determine the correct ++ * SSPLIT token, either MID or END. ++ */ ++ { ++ struct dwc_otg_hcd_iso_packet_desc ++ *frame_desc; ++ ++ frame_desc = ++ &qtd->urb-> ++ iso_descs[qtd->isoc_frame_index]; ++ qtd->isoc_split_offset += 188; ++ ++ if ((frame_desc->length - ++ qtd->isoc_split_offset) <= 188) { ++ qtd->isoc_split_pos = ++ DWC_HCSPLIT_XACTPOS_END; ++ } else { ++ qtd->isoc_split_pos = ++ DWC_HCSPLIT_XACTPOS_MID; ++ } ++ ++ } ++ break; ++ } ++ } else { ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK); ++ } ++ } else { ++ qtd->error_count = 0; ++ ++ if (hc->qh->ping_state) { ++ hc->qh->ping_state = 0; ++ /* ++ * Halt the channel so the transfer can be re-started ++ * from the appropriate point. This only happens in ++ * Slave mode. In DMA mode, the ping_state is cleared ++ * when the transfer is started because the core ++ * automatically executes the PING, then the transfer. ++ */ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK); ++ } ++ } ++ ++ /* ++ * If the ACK occurred when _not_ in the PING state, let the channel ++ * continue transferring data after clearing the error count. ++ */ ++ ++ disable_hc_int(hc_regs, ack); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel NYET interrupt. This interrupt should only occur on ++ * Bulk and Control OUT endpoints and for complete split transactions. If a ++ * NYET occurs at the same time as a Transfer Complete interrupt, it is ++ * handled in the xfercomp interrupt handler, not here. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "NYET Received--\n", hc->hc_num); ++ ++ /* ++ * NYET on CSPLIT ++ * re-do the CSPLIT immediately on non-periodic ++ */ ++ if (hc->do_split && hc->complete_split) { ++ if (hc->ep_is_in && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) ++ && hcd->core_if->dma_enable) { ++ qtd->complete_split = 0; ++ qtd->isoc_split_offset = 0; ++ if (++qtd->isoc_frame_index == qtd->urb->packet_count) { ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); ++ } ++ else ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS); ++ goto handle_nyet_done; ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ int frnum = dwc_otg_hcd_get_frame_number(hcd); ++ ++ if (dwc_full_frame_num(frnum) != ++ dwc_full_frame_num(hc->qh->sched_frame)) { ++ /* ++ * No longer in the same full speed frame. ++ * Treat this as a transaction error. ++ */ ++ qtd->complete_split = 0; ++ halt_channel(hcd, hc, qtd, ++ DWC_OTG_HC_XFER_XACT_ERR); ++ /** @todo add support for isoc release */ ++ goto handle_nyet_done; ++ } ++ } ++ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET); ++ goto handle_nyet_done; ++ } ++ ++ hc->qh->ping_state = 1; ++ qtd->error_count = 0; ++ ++ update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd, ++ DWC_OTG_HC_XFER_NYET); ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ ++ /* ++ * Halt the channel and re-start the transfer so the PING ++ * protocol will start. ++ */ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET); ++ ++handle_nyet_done: ++ disable_hc_int(hc_regs, nyet); ++ return 1; ++} ++ ++/** ++ * Handles a host channel babble interrupt. This handler may be called in ++ * either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_babble_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Babble Error--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_desc_enable) { ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ DWC_OTG_HC_XFER_BABBLE_ERR); ++ goto handle_babble_done; ++ } ++ ++ if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { ++ hcd->fops->complete(hcd, qtd->urb->priv, ++ qtd->urb, -DWC_E_OVERFLOW); ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_BABBLE_ERR); ++ } else { ++ dwc_otg_halt_status_e halt_status; ++ halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_BABBLE_ERR); ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++ ++handle_babble_done: ++ disable_hc_int(hc_regs, bblerr); ++ return 1; ++} ++ ++/** ++ * Handles a host channel AHB error interrupt. This handler is only called in ++ * DMA mode. ++ */ ++static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ hcchar_data_t hcchar; ++ hcsplt_data_t hcsplt; ++ hctsiz_data_t hctsiz; ++ uint32_t hcdma; ++ char *pipetype, *speed; ++ ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "AHB Error--\n", hc->hc_num); ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt); ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ hcdma = DWC_READ_REG32(&hc_regs->hcdma); ++ ++ DWC_ERROR("AHB ERROR, Channel %d\n", hc->hc_num); ++ DWC_ERROR(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32); ++ DWC_ERROR(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma); ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Enqueue\n"); ++ DWC_ERROR(" Device address: %d\n", ++ dwc_otg_hcd_get_dev_addr(&urb->pipe_info)); ++ DWC_ERROR(" Endpoint: %d, %s\n", ++ dwc_otg_hcd_get_ep_num(&urb->pipe_info), ++ (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT")); ++ ++ switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) { ++ case UE_CONTROL: ++ pipetype = "CONTROL"; ++ break; ++ case UE_BULK: ++ pipetype = "BULK"; ++ break; ++ case UE_INTERRUPT: ++ pipetype = "INTERRUPT"; ++ break; ++ case UE_ISOCHRONOUS: ++ pipetype = "ISOCHRONOUS"; ++ break; ++ default: ++ pipetype = "UNKNOWN"; ++ break; ++ } ++ ++ DWC_ERROR(" Endpoint type: %s\n", pipetype); ++ ++ switch (hc->speed) { ++ case DWC_OTG_EP_SPEED_HIGH: ++ speed = "HIGH"; ++ break; ++ case DWC_OTG_EP_SPEED_FULL: ++ speed = "FULL"; ++ break; ++ case DWC_OTG_EP_SPEED_LOW: ++ speed = "LOW"; ++ break; ++ default: ++ speed = "UNKNOWN"; ++ break; ++ }; ++ ++ DWC_ERROR(" Speed: %s\n", speed); ++ ++ DWC_ERROR(" Max packet size: %d\n", ++ dwc_otg_hcd_get_mps(&urb->pipe_info)); ++ DWC_ERROR(" Data buffer length: %d\n", urb->length); ++ DWC_ERROR(" Transfer buffer: %p, Transfer DMA: %p\n", ++ urb->buf, (void *)urb->dma); ++ DWC_ERROR(" Setup buffer: %p, Setup DMA: %p\n", ++ urb->setup_packet, (void *)urb->setup_dma); ++ DWC_ERROR(" Interval: %d\n", urb->interval); ++ ++ /* Core haltes the channel for Descriptor DMA mode */ ++ if (hcd->core_if->dma_desc_enable) { ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ DWC_OTG_HC_XFER_AHB_ERR); ++ goto handle_ahberr_done; ++ } ++ ++ hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_IO); ++ ++ /* ++ * Force a channel halt. Don't call halt_channel because that won't ++ * write to the HCCHARn register in DMA mode to force the halt. ++ */ ++ dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR); ++handle_ahberr_done: ++ disable_hc_int(hc_regs, ahberr); ++ return 1; ++} ++ ++/** ++ * Handles a host channel transaction error interrupt. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_xacterr_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Transaction Error--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_desc_enable) { ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ DWC_OTG_HC_XFER_XACT_ERR); ++ goto handle_xacterr_done; ++ } ++ ++ switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { ++ case UE_CONTROL: ++ case UE_BULK: ++ qtd->error_count++; ++ if (!hc->qh->ping_state) { ++ ++ update_urb_state_xfer_intr(hc, hc_regs, ++ qtd->urb, qtd, ++ DWC_OTG_HC_XFER_XACT_ERR); ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ if (!hc->ep_is_in && hc->speed == DWC_OTG_EP_SPEED_HIGH) { ++ hc->qh->ping_state = 1; ++ } ++ } ++ ++ /* ++ * Halt the channel so the transfer can be re-started from ++ * the appropriate point or the PING protocol will start. ++ */ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR); ++ break; ++ case UE_INTERRUPT: ++ qtd->error_count++; ++ if (hc->do_split && hc->complete_split) { ++ qtd->complete_split = 0; ++ } ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR); ++ break; ++ case UE_ISOCHRONOUS: ++ { ++ dwc_otg_halt_status_e halt_status; ++ halt_status = ++ update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_XACT_ERR); ++ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++ break; ++ } ++handle_xacterr_done: ++ disable_hc_int(hc_regs, xacterr); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel frame overrun interrupt. This handler may be called ++ * in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_frmovrun_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Frame Overrun--\n", hc->hc_num); ++ ++ switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { ++ case UE_CONTROL: ++ case UE_BULK: ++ break; ++ case UE_INTERRUPT: ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN); ++ break; ++ case UE_ISOCHRONOUS: ++ { ++ dwc_otg_halt_status_e halt_status; ++ halt_status = ++ update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_FRAME_OVERRUN); ++ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++ break; ++ } ++ ++ disable_hc_int(hc_regs, frmovrun); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel data toggle error interrupt. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Data Toggle Error--\n", hc->hc_num); ++ ++ if (hc->ep_is_in) { ++ qtd->error_count = 0; ++ } else { ++ DWC_ERROR("Data Toggle Error on OUT transfer," ++ "channel %d\n", hc->hc_num); ++ } ++ ++ disable_hc_int(hc_regs, datatglerr); ++ ++ return 1; ++} ++ ++#ifdef DEBUG ++/** ++ * This function is for debug only. It checks that a valid halt status is set ++ * and that HCCHARn.chdis is clear. If there's a problem, corrective action is ++ * taken and a warning is issued. ++ * @return 1 if halt status is ok, 0 otherwise. ++ */ ++static inline int halt_status_ok(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; ++ hcsplt_data_t hcsplt; ++ ++ if (hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS) { ++ /* ++ * This code is here only as a check. This condition should ++ * never happen. Ignore the halt if it does occur. ++ */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); ++ hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt); ++ DWC_WARN ++ ("%s: hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS, " ++ "channel %d, hcchar 0x%08x, hctsiz 0x%08x, " ++ "hcint 0x%08x, hcintmsk 0x%08x, " ++ "hcsplt 0x%08x, qtd->complete_split %d\n", __func__, ++ hc->hc_num, hcchar.d32, hctsiz.d32, hcint.d32, ++ hcintmsk.d32, hcsplt.d32, qtd->complete_split); ++ ++ DWC_WARN("%s: no halt status, channel %d, ignoring interrupt\n", ++ __func__, hc->hc_num); ++ DWC_WARN("\n"); ++ clear_hc_int(hc_regs, chhltd); ++ return 0; ++ } ++ ++ /* ++ * This code is here only as a check. hcchar.chdis should ++ * never be set when the halt interrupt occurs. Halt the ++ * channel again if it does occur. ++ */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chdis) { ++ DWC_WARN("%s: hcchar.chdis set unexpectedly, " ++ "hcchar 0x%08x, trying to halt again\n", ++ __func__, hcchar.d32); ++ clear_hc_int(hc_regs, chhltd); ++ hc->halt_pending = 0; ++ halt_channel(hcd, hc, qtd, hc->halt_status); ++ return 0; ++ } ++ ++ return 1; ++} ++#endif ++ ++/** ++ * Handles a host Channel Halted interrupt in DMA mode. This handler ++ * determines the reason the channel halted and proceeds accordingly. ++ */ ++static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; ++ int out_nak_enh = 0; ++ ++ /* For core with OUT NAK enhancement, the flow for high- ++ * speed CONTROL/BULK OUT is handled a little differently. ++ */ ++ if (hcd->core_if->snpsid >= OTG_CORE_REV_2_71a) { ++ if (hc->speed == DWC_OTG_EP_SPEED_HIGH && !hc->ep_is_in && ++ (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || ++ hc->ep_type == DWC_OTG_EP_TYPE_BULK)) { ++ out_nak_enh = 1; ++ } ++ } ++ ++ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE || ++ (hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR ++ && !hcd->core_if->dma_desc_enable)) { ++ /* ++ * Just release the channel. A dequeue can happen on a ++ * transfer timeout. In the case of an AHB Error, the channel ++ * was forced to halt because there's no way to gracefully ++ * recover. ++ */ ++ if (hcd->core_if->dma_desc_enable) ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ hc->halt_status); ++ else ++ release_channel(hcd, hc, qtd, hc->halt_status); ++ return; ++ } ++ ++ /* Read the HCINTn register to determine the cause for the halt. */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); ++ ++ if (hcint.b.xfercomp) { ++ /** @todo This is here because of a possible hardware bug. Spec ++ * says that on SPLIT-ISOC OUT transfers in DMA mode that a HALT ++ * interrupt w/ACK bit set should occur, but I only see the ++ * XFERCOMP bit, even with it masked out. This is a workaround ++ * for that behavior. Should fix this when hardware is fixed. ++ */ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) { ++ handle_hc_ack_intr(hcd, hc, hc_regs, qtd); ++ } ++ handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.stall) { ++ handle_hc_stall_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.xacterr && !hcd->core_if->dma_desc_enable) { ++ if (out_nak_enh) { ++ if (hcint.b.nyet || hcint.b.nak || hcint.b.ack) { ++ DWC_DEBUG("XactErr with NYET/NAK/ACK\n"); ++ qtd->error_count = 0; ++ } else { ++ DWC_DEBUG("XactErr without NYET/NAK/ACK\n"); ++ } ++ } ++ ++ /* ++ * Must handle xacterr before nak or ack. Could get a xacterr ++ * at the same time as either of these on a BULK/CONTROL OUT ++ * that started with a PING. The xacterr takes precedence. ++ */ ++ handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.xcs_xact && hcd->core_if->dma_desc_enable) { ++ handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) { ++ handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.bblerr) { ++ handle_hc_babble_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.frmovrun) { ++ handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd); ++ } else if (!out_nak_enh) { ++ if (hcint.b.nyet) { ++ /* ++ * Must handle nyet before nak or ack. Could get a nyet at the ++ * same time as either of those on a BULK/CONTROL OUT that ++ * started with a PING. The nyet takes precedence. ++ */ ++ handle_hc_nyet_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.nak && !hcintmsk.b.nak) { ++ /* ++ * If nak is not masked, it's because a non-split IN transfer ++ * is in an error state. In that case, the nak is handled by ++ * the nak interrupt handler, not here. Handle nak here for ++ * BULK/CONTROL OUT transfers, which halt on a NAK to allow ++ * rewinding the buffer pointer. ++ */ ++ handle_hc_nak_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.ack && !hcintmsk.b.ack) { ++ /* ++ * If ack is not masked, it's because a non-split IN transfer ++ * is in an error state. In that case, the ack is handled by ++ * the ack interrupt handler, not here. Handle ack here for ++ * split transfers. Start splits halt on ACK. ++ */ ++ handle_hc_ack_intr(hcd, hc, hc_regs, qtd); ++ } else { ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * A periodic transfer halted with no other channel ++ * interrupts set. Assume it was halted by the core ++ * because it could not be completed in its scheduled ++ * (micro)frame. ++ */ ++#ifdef DEBUG ++ DWC_PRINTF ++ ("%s: Halt channel %d (assume incomplete periodic transfer)\n", ++ __func__, hc->hc_num); ++#endif ++ halt_channel(hcd, hc, qtd, ++ DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE); ++ } else { ++ DWC_ERROR ++ ("%s: Channel %d, DMA Mode -- ChHltd set, but reason " ++ "for halting is unknown, hcint 0x%08x, intsts 0x%08x\n", ++ __func__, hc->hc_num, hcint.d32, ++ DWC_READ_REG32(&hcd-> ++ core_if->core_global_regs-> ++ gintsts)); ++ disable_hc_int(hc_regs, chhltd); ++ } ++ ++ } ++ } else { ++ DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n", ++ hcint.d32); ++ disable_hc_int(hc_regs, chhltd); ++ } ++} ++ ++/** ++ * Handles a host channel Channel Halted interrupt. ++ * ++ * In slave mode, this handler is called only when the driver specifically ++ * requests a halt. This occurs during handling other host channel interrupts ++ * (e.g. nak, xacterr, stall, nyet, etc.). ++ * ++ * In DMA mode, this is the interrupt that occurs when the core has finished ++ * processing a transfer on a channel. Other host channel interrupts (except ++ * ahberr) are disabled in DMA mode. ++ */ ++static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Channel Halted--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_enable) { ++ handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd); ++ } else { ++#ifdef DEBUG ++ if (!halt_status_ok(hcd, hc, hc_regs, qtd)) { ++ return 1; ++ } ++#endif ++ release_channel(hcd, hc, qtd, hc->halt_status); ++ } ++ ++ return 1; ++} ++ ++/** Handles interrupt for a specific Host Channel */ ++int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num) ++{ ++ int retval = 0; ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; ++ dwc_hc_t *hc; ++ dwc_otg_hc_regs_t *hc_regs; ++ dwc_otg_qtd_t *qtd; ++ ++ DWC_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", num); ++ ++ hc = dwc_otg_hcd->hc_ptr_array[num]; ++ hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num]; ++ qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list); ++ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); ++ DWC_DEBUGPL(DBG_HCDV, ++ " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n", ++ hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32)); ++ hcint.d32 = hcint.d32 & hcintmsk.d32; ++ ++ if (!dwc_otg_hcd->core_if->dma_enable) { ++ if (hcint.b.chhltd && hcint.d32 != 0x2) { ++ hcint.b.chhltd = 0; ++ } ++ } ++ ++ if (hcint.b.xfercomp) { ++ retval |= ++ handle_hc_xfercomp_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ /* ++ * If NYET occurred at same time as Xfer Complete, the NYET is ++ * handled by the Xfer Complete interrupt handler. Don't want ++ * to call the NYET interrupt handler in this case. ++ */ ++ hcint.b.nyet = 0; ++ } ++ if (hcint.b.chhltd) { ++ retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.ahberr) { ++ retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.stall) { ++ retval |= handle_hc_stall_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.nak) { ++ retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.ack) { ++ retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.nyet) { ++ retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.xacterr) { ++ retval |= handle_hc_xacterr_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.bblerr) { ++ retval |= handle_hc_babble_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.frmovrun) { ++ retval |= ++ handle_hc_frmovrun_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.datatglerr) { ++ retval |= ++ handle_hc_datatglerr_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ ++ return retval; ++} ++ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_linux.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_linux.c +new file mode 100644 +index 0000000..2e94f6e +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_linux.c +@@ -0,0 +1,840 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $ ++ * $Revision: #23 $ ++ * $Date: 2013/04/22 $ ++ * $Change: 2211149 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_DEVICE_ONLY ++ ++/** ++ * @file ++ * ++ * This file contains the implementation of the HCD. In Linux, the HCD ++ * implements the hc_driver API. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ++#include <../drivers/usb/core/hcd.h> ++#else ++#include ++#endif ++ ++#include "dwc_otg_hcd_if.h" ++#include "dwc_otg_dbg.h" ++#include "dwc_otg_driver.h" ++#include "dwc_otg_hcd.h" ++/** ++ * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is ++ * qualified with its direction (possible 32 endpoints per device). ++ */ ++#define dwc_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \ ++ ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4) ++ ++static const char dwc_otg_hcd_name[] = "dwc_otg_hcd"; ++ ++/** @name Linux HC Driver API Functions */ ++/** @{ */ ++static int urb_enqueue(struct usb_hcd *hcd, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ struct usb_host_endpoint *ep, ++#endif ++ struct urb *urb, gfp_t mem_flags); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb); ++#else ++static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status); ++#endif ++ ++static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep); ++#endif ++static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd); ++extern int hcd_start(struct usb_hcd *hcd); ++extern void hcd_stop(struct usb_hcd *hcd); ++static int get_frame_number(struct usb_hcd *hcd); ++extern int hub_status_data(struct usb_hcd *hcd, char *buf); ++extern int hub_control(struct usb_hcd *hcd, ++ u16 typeReq, ++ u16 wValue, u16 wIndex, char *buf, u16 wLength); ++ ++struct wrapper_priv_data { ++ dwc_otg_hcd_t *dwc_otg_hcd; ++}; ++ ++/** @} */ ++ ++static struct hc_driver dwc_otg_hc_driver = { ++ ++ .description = dwc_otg_hcd_name, ++ .product_desc = "DWC OTG Controller", ++ .hcd_priv_size = sizeof(struct wrapper_priv_data), ++ ++ .irq = dwc_otg_hcd_irq, ++ ++ .flags = HCD_MEMORY | HCD_USB2, ++ ++ //.reset = ++ .start = hcd_start, ++ //.suspend = ++ //.resume = ++ .stop = hcd_stop, ++ ++ .urb_enqueue = urb_enqueue, ++ .urb_dequeue = urb_dequeue, ++ .endpoint_disable = endpoint_disable, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++ .endpoint_reset = endpoint_reset, ++#endif ++ .get_frame_number = get_frame_number, ++ ++ .hub_status_data = hub_status_data, ++ .hub_control = hub_control, ++ //.bus_suspend = ++ //.bus_resume = ++}; ++ ++/** Gets the dwc_otg_hcd from a struct usb_hcd */ ++static inline dwc_otg_hcd_t *hcd_to_dwc_otg_hcd(struct usb_hcd *hcd) ++{ ++ struct wrapper_priv_data *p; ++ p = (struct wrapper_priv_data *)(hcd->hcd_priv); ++ return p->dwc_otg_hcd; ++} ++ ++/** Gets the struct usb_hcd that contains a dwc_otg_hcd_t. */ ++static inline struct usb_hcd *dwc_otg_hcd_to_hcd(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ return dwc_otg_hcd_get_priv_data(dwc_otg_hcd); ++} ++ ++/** Gets the usb_host_endpoint associated with an URB. */ ++inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb) ++{ ++ struct usb_device *dev = urb->dev; ++ int ep_num = usb_pipeendpoint(urb->pipe); ++ ++ if (usb_pipein(urb->pipe)) ++ return dev->ep_in[ep_num]; ++ else ++ return dev->ep_out[ep_num]; ++} ++ ++static int _disconnect(dwc_otg_hcd_t * hcd) ++{ ++ struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd); ++ ++ usb_hcd->self.is_b_host = 0; ++ return 0; ++} ++ ++static int _start(dwc_otg_hcd_t * hcd) ++{ ++ struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd); ++ ++ usb_hcd->self.is_b_host = dwc_otg_hcd_is_b_host(hcd); ++ hcd_start(usb_hcd); ++ ++ return 0; ++} ++ ++static int _hub_info(dwc_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr, ++ uint32_t * port_addr) ++{ ++ struct urb *urb = (struct urb *)urb_handle; ++ if (urb->dev->tt) { ++ *hub_addr = urb->dev->tt->hub->devnum; ++ } else { ++ *hub_addr = 0; ++ } ++ *port_addr = urb->dev->ttport; ++ return 0; ++} ++ ++static int _speed(dwc_otg_hcd_t * hcd, void *urb_handle) ++{ ++ struct urb *urb = (struct urb *)urb_handle; ++ return urb->dev->speed; ++} ++ ++static int _get_b_hnp_enable(dwc_otg_hcd_t * hcd) ++{ ++ struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd); ++ return usb_hcd->self.b_hnp_enable; ++} ++ ++static void allocate_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw, ++ struct urb *urb) ++{ ++ hcd_to_bus(hcd)->bandwidth_allocated += bw / urb->interval; ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ hcd_to_bus(hcd)->bandwidth_isoc_reqs++; ++ } else { ++ hcd_to_bus(hcd)->bandwidth_int_reqs++; ++ } ++} ++ ++static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw, ++ struct urb *urb) ++{ ++ hcd_to_bus(hcd)->bandwidth_allocated -= bw / urb->interval; ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ hcd_to_bus(hcd)->bandwidth_isoc_reqs--; ++ } else { ++ hcd_to_bus(hcd)->bandwidth_int_reqs--; ++ } ++} ++ ++/** ++ * Sets the final status of an URB and returns it to the device driver. Any ++ * required cleanup of the URB is performed. ++ */ ++static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle, ++ dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status) ++{ ++ struct urb *urb = (struct urb *)urb_handle; ++#ifdef DEBUG ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n", ++ __func__, urb, usb_pipedevice(urb->pipe), ++ usb_pipeendpoint(urb->pipe), ++ usb_pipein(urb->pipe) ? "IN" : "OUT", status); ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ int i; ++ for (i = 0; i < urb->number_of_packets; i++) { ++ DWC_PRINTF(" ISO Desc %d status: %d\n", ++ i, urb->iso_frame_desc[i].status); ++ } ++ } ++ } ++#endif ++ ++ urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb); ++ /* Convert status value. */ ++ switch (status) { ++ case -DWC_E_PROTOCOL: ++ status = -EPROTO; ++ break; ++ case -DWC_E_IN_PROGRESS: ++ status = -EINPROGRESS; ++ break; ++ case -DWC_E_PIPE: ++ status = -EPIPE; ++ break; ++ case -DWC_E_IO: ++ status = -EIO; ++ break; ++ case -DWC_E_TIMEOUT: ++ status = -ETIMEDOUT; ++ break; ++ case -DWC_E_OVERFLOW: ++ status = -EOVERFLOW; ++ break; ++ default: ++ if (status) { ++ DWC_PRINTF("Uknown urb status %d\n", status); ++ ++ } ++ } ++ ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ int i; ++ ++ urb->error_count = dwc_otg_hcd_urb_get_error_count(dwc_otg_urb); ++ for (i = 0; i < urb->number_of_packets; ++i) { ++ urb->iso_frame_desc[i].actual_length = ++ dwc_otg_hcd_urb_get_iso_desc_actual_length ++ (dwc_otg_urb, i); ++ urb->iso_frame_desc[i].status = ++ dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_urb, i); ++ } ++ } ++ ++ urb->status = status; ++ urb->hcpriv = NULL; ++ if (!status) { ++ if ((urb->transfer_flags & URB_SHORT_NOT_OK) && ++ (urb->actual_length < urb->transfer_buffer_length)) { ++ urb->status = -EREMOTEIO; ++ } ++ } ++ ++ if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) || ++ (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) { ++ struct usb_host_endpoint *ep = dwc_urb_to_endpoint(urb); ++ if (ep) { ++ free_bus_bandwidth(dwc_otg_hcd_to_hcd(hcd), ++ dwc_otg_hcd_get_ep_bandwidth(hcd, ++ ep->hcpriv), ++ urb); ++ } ++ } ++ ++ DWC_FREE(dwc_otg_urb); ++ ++ DWC_SPINUNLOCK(hcd->lock); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb); ++#else ++ usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status); ++#endif ++ DWC_SPINLOCK(hcd->lock); ++ ++ return 0; ++} ++ ++static struct dwc_otg_hcd_function_ops hcd_fops = { ++ .start = _start, ++ .disconnect = _disconnect, ++ .hub_info = _hub_info, ++ .speed = _speed, ++ .complete = _complete, ++ .get_b_hnp_enable = _get_b_hnp_enable, ++}; ++ ++/** ++ * Initializes the HCD. This function allocates memory for and initializes the ++ * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the ++ * USB bus with the core and calls the hc_driver->start() function. It returns ++ * a negative error on failure. ++ */ ++int hcd_init( ++#ifdef LM_INTERFACE ++ struct lm_device *_dev ++#elif defined(PCI_INTERFACE) ++ struct pci_dev *_dev ++#endif ++ ) ++{ ++ struct usb_hcd *hcd = NULL; ++ dwc_otg_hcd_t *dwc_otg_hcd = NULL; ++#ifdef LM_INTERFACE ++ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); ++#elif defined(PCI_INTERFACE) ++ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); ++#endif ++ ++ int retval = 0; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT\n"); ++ ++ /* Set device flags indicating whether the HCD supports DMA. */ ++ if (dwc_otg_is_dma_enable(otg_dev->core_if)) { ++#ifdef LM_INTERFACE ++ _dev->dev.dma_mask = (void *)~0; ++ _dev->dev.coherent_dma_mask = ~0; ++#elif defined(PCI_INTERFACE) ++ pci_set_dma_mask(_dev, DMA_BIT_MASK(32)); ++ pci_set_consistent_dma_mask(_dev, DMA_BIT_MASK(32)); ++#endif ++ ++ } else { ++#ifdef LM_INTERFACE ++ _dev->dev.dma_mask = (void *)0; ++ _dev->dev.coherent_dma_mask = 0; ++#elif defined(PCI_INTERFACE) ++ pci_set_dma_mask(_dev, 0); ++ pci_set_consistent_dma_mask(_dev, 0); ++#endif ++ } ++ ++ /* ++ * Allocate memory for the base HCD plus the DWC OTG HCD. ++ * Initialize the base HCD. ++ */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ++ hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, _dev->dev.bus_id); ++#else ++ hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, dev_name(&_dev->dev)); ++ hcd->has_tt = 1; ++// hcd->uses_new_polling = 1; ++// hcd->poll_rh = 0; ++#endif ++ if (!hcd) { ++ retval = -ENOMEM; ++ goto error1; ++ } ++ ++ hcd->regs = otg_dev->os_dep.base; ++ ++ /* Initialize the DWC OTG HCD. */ ++ dwc_otg_hcd = dwc_otg_hcd_alloc_hcd(); ++ if (!dwc_otg_hcd) { ++ goto error2; ++ } ++ ((struct wrapper_priv_data *)(hcd->hcd_priv))->dwc_otg_hcd = ++ dwc_otg_hcd; ++ otg_dev->hcd = dwc_otg_hcd; ++ ++ if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) { ++ goto error2; ++ } ++ ++ otg_dev->hcd->otg_dev = otg_dev; ++ hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel) ++ hcd->self.otg_version = dwc_otg_get_otg_version(otg_dev->core_if); ++ /* Don't support SG list at this point */ ++ hcd->self.sg_tablesize = 0; ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) ++ /* Do not to do HNP polling if not capable */ ++ if (otg_dev->core_if->otg_ver) ++ hcd->self.is_hnp_cap = dwc_otg_get_hnpcapable(otg_dev->core_if); ++#endif ++ /* ++ * Finish generic HCD initialization and start the HCD. This function ++ * allocates the DMA buffer pool, registers the USB bus, requests the ++ * IRQ line, and calls hcd_start method. ++ */ ++ retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED); ++ if (retval < 0) { ++ goto error2; ++ } ++ ++ dwc_otg_hcd_set_priv_data(dwc_otg_hcd, hcd); ++ return 0; ++ ++error2: ++ usb_put_hcd(hcd); ++error1: ++ return retval; ++} ++ ++/** ++ * Removes the HCD. ++ * Frees memory and resources associated with the HCD and deregisters the bus. ++ */ ++void hcd_remove( ++#ifdef LM_INTERFACE ++ struct lm_device *_dev ++#elif defined(PCI_INTERFACE) ++ struct pci_dev *_dev ++#endif ++ ) ++{ ++#ifdef LM_INTERFACE ++ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); ++#elif defined(PCI_INTERFACE) ++ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); ++#endif ++ ++ dwc_otg_hcd_t *dwc_otg_hcd; ++ struct usb_hcd *hcd; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD REMOVE\n"); ++ ++ if (!otg_dev) { ++ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__); ++ return; ++ } ++ ++ dwc_otg_hcd = otg_dev->hcd; ++ ++ if (!dwc_otg_hcd) { ++ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__); ++ return; ++ } ++ ++ hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd); ++ ++ if (!hcd) { ++ DWC_DEBUGPL(DBG_ANY, ++ "%s: dwc_otg_hcd_to_hcd(dwc_otg_hcd) NULL!\n", ++ __func__); ++ return; ++ } ++ usb_remove_hcd(hcd); ++ dwc_otg_hcd_set_priv_data(dwc_otg_hcd, NULL); ++ dwc_otg_hcd_remove(dwc_otg_hcd); ++ usb_put_hcd(hcd); ++} ++ ++/* ========================================================================= ++ * Linux HC Driver Functions ++ * ========================================================================= */ ++ ++/** Initializes the DWC_otg controller and its root hub and prepares it for host ++ * mode operation. Activates the root port. Returns 0 on success and a negative ++ * error code on failure. */ ++int hcd_start(struct usb_hcd *hcd) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ struct usb_bus *bus; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n"); ++ bus = hcd_to_bus(hcd); ++ ++ hcd->state = HC_STATE_RUNNING; ++ if (dwc_otg_hcd_start(dwc_otg_hcd, &hcd_fops)) { ++ if (dwc_otg_hcd->core_if->otg_ver && dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) ++ dwc_otg_hcd->core_if->op_state = B_PERIPHERAL; ++ return 0; ++ } ++ ++ /* Initialize and connect root hub if one is not already attached */ ++ if (bus->root_hub) { ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Has Root Hub\n"); ++ /* Inform the HUB driver to resume. */ ++ usb_hcd_resume_root_hub(hcd); ++ } ++ ++ return 0; ++} ++ ++/** ++ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are ++ * stopped. ++ */ ++void hcd_stop(struct usb_hcd *hcd) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++ dwc_otg_hcd_stop(dwc_otg_hcd); ++} ++ ++/** Returns the current frame number. */ ++static int get_frame_number(struct usb_hcd *hcd) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++ return dwc_otg_hcd_get_frame_number(dwc_otg_hcd); ++} ++ ++#ifdef DEBUG ++static void dump_urb_info(struct urb *urb, char *fn_name) ++{ ++ DWC_PRINTF("%s, urb %p\n", fn_name, urb); ++ DWC_PRINTF(" Device address: %d\n", usb_pipedevice(urb->pipe)); ++ DWC_PRINTF(" Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe), ++ (usb_pipein(urb->pipe) ? "IN" : "OUT")); ++ DWC_PRINTF(" Endpoint type: %s\n", ( { ++ char *pipetype; ++ switch (usb_pipetype(urb->pipe)) { ++case PIPE_CONTROL: ++pipetype = "CONTROL"; break; case PIPE_BULK: ++pipetype = "BULK"; break; case PIPE_INTERRUPT: ++pipetype = "INTERRUPT"; break; case PIPE_ISOCHRONOUS: ++pipetype = "ISOCHRONOUS"; break; default: ++ pipetype = "UNKNOWN"; break;}; ++ pipetype;} ++ )) ; ++ DWC_PRINTF(" Speed: %s\n", ( { ++ char *speed; switch (urb->dev->speed) { ++case USB_SPEED_HIGH: ++speed = "HIGH"; break; case USB_SPEED_FULL: ++speed = "FULL"; break; case USB_SPEED_LOW: ++speed = "LOW"; break; default: ++ speed = "UNKNOWN"; break;}; ++ speed;} ++ )) ; ++ DWC_PRINTF(" Max packet size: %d\n", ++ usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))); ++ DWC_PRINTF(" Data buffer length: %d\n", urb->transfer_buffer_length); ++ DWC_PRINTF(" Transfer buffer: %p, Transfer DMA: %p\n", ++ urb->transfer_buffer, (void *)urb->transfer_dma); ++ DWC_PRINTF(" Setup buffer: %p, Setup DMA: %p\n", ++ urb->setup_packet, (void *)urb->setup_dma); ++ DWC_PRINTF(" Interval: %d\n", urb->interval); ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ int i; ++ for (i = 0; i < urb->number_of_packets; i++) { ++ DWC_PRINTF(" ISO Desc %d:\n", i); ++ DWC_PRINTF(" offset: %d, length %d\n", ++ urb->iso_frame_desc[i].offset, ++ urb->iso_frame_desc[i].length); ++ } ++ } ++} ++ ++#endif ++ ++/** Starts processing a USB transfer request specified by a USB Request Block ++ * (URB). mem_flags indicates the type of memory allocation to use while ++ * processing this URB. */ ++static int urb_enqueue(struct usb_hcd *hcd, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ struct usb_host_endpoint *ep, ++#endif ++ struct urb *urb, gfp_t mem_flags) ++{ ++ int retval = 0; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) ++ struct usb_host_endpoint *ep = urb->ep; ++#endif ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ dwc_otg_hcd_urb_t *dwc_otg_urb; ++ int i; ++ int alloc_bandwidth = 0; ++ uint8_t ep_type = 0; ++ uint32_t flags = 0; ++ void *buf; ++ ++#ifdef DEBUG ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ dump_urb_info(urb, "urb_enqueue"); ++ } ++#endif ++ ++ if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) ++ || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) { ++ if (!dwc_otg_hcd_is_bandwidth_allocated ++ (dwc_otg_hcd, &ep->hcpriv)) { ++ alloc_bandwidth = 1; ++ } ++ } ++ ++ switch (usb_pipetype(urb->pipe)) { ++ case PIPE_CONTROL: ++ ep_type = USB_ENDPOINT_XFER_CONTROL; ++ break; ++ case PIPE_ISOCHRONOUS: ++ ep_type = USB_ENDPOINT_XFER_ISOC; ++ break; ++ case PIPE_BULK: ++ ep_type = USB_ENDPOINT_XFER_BULK; ++ break; ++ case PIPE_INTERRUPT: ++ ep_type = USB_ENDPOINT_XFER_INT; ++ break; ++ default: ++ DWC_WARN("Wrong ep type\n"); ++ } ++ ++ dwc_otg_urb = dwc_otg_hcd_urb_alloc(dwc_otg_hcd, ++ urb->number_of_packets, ++ mem_flags == GFP_ATOMIC ? 1 : 0); ++ ++ dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe), ++ usb_pipeendpoint(urb->pipe), ep_type, ++ usb_pipein(urb->pipe), ++ usb_maxpacket(urb->dev, urb->pipe, ++ !(usb_pipein(urb->pipe)))); ++ ++ buf = urb->transfer_buffer; ++ if (hcd->self.uses_dma) { ++ /* ++ * Calculate virtual address from physical address, ++ * because some class driver may not fill transfer_buffer. ++ * In Buffer DMA mode virual address is used, ++ * when handling non DWORD aligned buffers. ++ */ ++ buf = phys_to_virt(urb->transfer_dma); ++ } ++ ++ if (!(urb->transfer_flags & URB_NO_INTERRUPT)) ++ flags |= URB_GIVEBACK_ASAP; ++ if (urb->transfer_flags & URB_ZERO_PACKET) ++ flags |= URB_SEND_ZERO_PACKET; ++ ++ dwc_otg_hcd_urb_set_params(dwc_otg_urb, urb, buf, ++ urb->transfer_dma, ++ urb->transfer_buffer_length, ++ urb->setup_packet, ++ urb->setup_dma, flags, urb->interval); ++ ++ for (i = 0; i < urb->number_of_packets; ++i) { ++ dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_urb, i, ++ urb-> ++ iso_frame_desc[i].offset, ++ urb-> ++ iso_frame_desc[i].length); ++ } ++ ++ urb->hcpriv = dwc_otg_urb; ++ retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb, &ep->hcpriv, ++ mem_flags == GFP_ATOMIC ? 1 : 0); ++ if (!retval) { ++ if (alloc_bandwidth) { ++ allocate_bus_bandwidth(hcd, ++ dwc_otg_hcd_get_ep_bandwidth ++ (dwc_otg_hcd, ep->hcpriv), urb); ++ } ++ } else { ++ if (retval == -DWC_E_NO_DEVICE) { ++ retval = -ENODEV; ++ } ++ } ++ ++ return retval; ++} ++ ++/** Aborts/cancels a USB transfer request. Always returns 0 to indicate ++ * success. */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb) ++#else ++static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ++#endif ++{ ++ dwc_irqflags_t flags; ++ dwc_otg_hcd_t *dwc_otg_hcd; ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n"); ++ ++ dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++#ifdef DEBUG ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ dump_urb_info(urb, "urb_dequeue"); ++ } ++#endif ++ ++ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); ++ ++ dwc_otg_hcd_urb_dequeue(dwc_otg_hcd, urb->hcpriv); ++ ++ DWC_FREE(urb->hcpriv); ++ urb->hcpriv = NULL; ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); ++ ++ /* Higher layer software sets URB status. */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ usb_hcd_giveback_urb(hcd, urb); ++#else ++ usb_hcd_giveback_urb(hcd, urb, status); ++#endif ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ DWC_PRINTF("Called usb_hcd_giveback_urb()\n"); ++ DWC_PRINTF(" urb->status = %d\n", urb->status); ++ } ++ ++ return 0; ++} ++ ++/* Frees resources in the DWC_otg controller related to a given endpoint. Also ++ * clears state in the HCD related to the endpoint. Any URBs for the endpoint ++ * must already be dequeued. */ ++static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++ DWC_DEBUGPL(DBG_HCD, ++ "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, " ++ "endpoint=%d\n", ep->desc.bEndpointAddress, ++ dwc_ep_addr_to_endpoint(ep->desc.bEndpointAddress)); ++ dwc_otg_hcd_endpoint_disable(dwc_otg_hcd, ep->hcpriv, 250); ++ ep->hcpriv = NULL; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++/* Resets endpoint specific parameter values, in current version used to reset ++ * the data toggle(as a WA). This function can be called from usb_clear_halt routine */ ++static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) ++{ ++ dwc_irqflags_t flags; ++ struct usb_device *udev = NULL; ++ int epnum = usb_endpoint_num(&ep->desc); ++ int is_out = usb_endpoint_dir_out(&ep->desc); ++ int is_control = usb_endpoint_xfer_control(&ep->desc); ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++#ifdef LM_INTERFACE ++ struct lm_device *_dev = dwc_otg_hcd->otg_dev->os_dep.lmdev; ++#elif defined(PCI_INTERFACE) ++ struct pci_dev *_dev = dwc_otg_hcd->otg_dev->os_dep.pcidev; ++#endif ++ ++ if (_dev) ++ udev = to_usb_device(&_dev->dev); ++ else ++ return; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD EP RESET: Endpoint Num=0x%02d\n", epnum); ++ ++ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); ++ usb_settoggle(udev, epnum, is_out, 0); ++ if (is_control) ++ usb_settoggle(udev, epnum, !is_out, 0); ++ ++ if (ep->hcpriv) { ++ dwc_otg_hcd_endpoint_reset(dwc_otg_hcd, ep->hcpriv); ++ } ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); ++} ++#endif ++ ++/** Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if ++ * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid ++ * interrupt. ++ * ++ * This function is called by the USB core when an interrupt occurs */ ++static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ int32_t retval = dwc_otg_hcd_handle_intr(dwc_otg_hcd); ++ if (retval != 0) { ++ S3C2410X_CLEAR_EINTPEND(); ++ } ++ return IRQ_RETVAL(retval); ++} ++ ++/** Creates Status Change bitmap for the root hub and root port. The bitmap is ++ * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1 ++ * is the status change indicator for the single root port. Returns 1 if either ++ * change indicator is 1, otherwise returns 0. */ ++int hub_status_data(struct usb_hcd *hcd, char *buf) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++ buf[0] = 0; ++ buf[0] |= (dwc_otg_hcd_is_status_changed(dwc_otg_hcd, 1)) << 1; ++ ++ return (buf[0] != 0); ++} ++ ++/** Handles hub class-specific requests. */ ++int hub_control(struct usb_hcd *hcd, ++ u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) ++{ ++ int retval; ++ ++ retval = dwc_otg_hcd_hub_control(hcd_to_dwc_otg_hcd(hcd), ++ typeReq, wValue, wIndex, buf, wLength); ++ ++ switch (retval) { ++ case -DWC_E_INVALID: ++ retval = -EINVAL; ++ break; ++ } ++ ++ return retval; ++} ++ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_queue.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_queue.c +new file mode 100644 +index 0000000..be55ebb +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_queue.c +@@ -0,0 +1,721 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $ ++ * $Revision: #45 $ ++ * $Date: 2013/01/24 $ ++ * $Change: 2150293 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_DEVICE_ONLY ++ ++/** ++ * @file ++ * ++ * This file contains the functions to manage Queue Heads and Queue ++ * Transfer Descriptors. ++ */ ++ ++#include "dwc_otg_hcd.h" ++#include "dwc_otg_regs.h" ++ ++/** ++ * Free each QTD in the QH's QTD-list then free the QH. QH should already be ++ * removed from a list. QTD list should already be empty if called from URB ++ * Dequeue. ++ * ++ * @param hcd HCD instance. ++ * @param qh The QH to free. ++ */ ++void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ dwc_otg_qtd_t *qtd, *qtd_tmp; ++ dwc_irqflags_t flags; ++ ++ /* Free each QTD in the QTD list */ ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { ++ DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry); ++ dwc_otg_hcd_qtd_free(qtd); ++ } ++ ++ if (hcd->core_if->dma_desc_enable) { ++ dwc_otg_hcd_qh_free_ddma(hcd, qh); ++ } else if (qh->dw_align_buf) { ++ uint32_t buf_size; ++ if (qh->ep_type == UE_ISOCHRONOUS) { ++ buf_size = 4096; ++ } else { ++ buf_size = hcd->core_if->core_params->max_transfer_size; ++ } ++ DWC_DMA_FREE(buf_size, qh->dw_align_buf, qh->dw_align_buf_dma); ++ } ++ ++ DWC_FREE(qh); ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ return; ++} ++ ++#define BitStuffTime(bytecount) ((8 * 7* bytecount) / 6) ++#define HS_HOST_DELAY 5 /* nanoseconds */ ++#define FS_LS_HOST_DELAY 1000 /* nanoseconds */ ++#define HUB_LS_SETUP 333 /* nanoseconds */ ++#define NS_TO_US(ns) ((ns + 500) / 1000) ++ /* convert & round nanoseconds to microseconds */ ++ ++static uint32_t calc_bus_time(int speed, int is_in, int is_isoc, int bytecount) ++{ ++ unsigned long retval; ++ ++ switch (speed) { ++ case USB_SPEED_HIGH: ++ if (is_isoc) { ++ retval = ++ ((38 * 8 * 2083) + ++ (2083 * (3 + BitStuffTime(bytecount)))) / 1000 + ++ HS_HOST_DELAY; ++ } else { ++ retval = ++ ((55 * 8 * 2083) + ++ (2083 * (3 + BitStuffTime(bytecount)))) / 1000 + ++ HS_HOST_DELAY; ++ } ++ break; ++ case USB_SPEED_FULL: ++ if (is_isoc) { ++ retval = ++ (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000; ++ if (is_in) { ++ retval = 7268 + FS_LS_HOST_DELAY + retval; ++ } else { ++ retval = 6265 + FS_LS_HOST_DELAY + retval; ++ } ++ } else { ++ retval = ++ (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000; ++ retval = 9107 + FS_LS_HOST_DELAY + retval; ++ } ++ break; ++ case USB_SPEED_LOW: ++ if (is_in) { ++ retval = ++ (67667 * (31 + 10 * BitStuffTime(bytecount))) / ++ 1000; ++ retval = ++ 64060 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY + ++ retval; ++ } else { ++ retval = ++ (66700 * (31 + 10 * BitStuffTime(bytecount))) / ++ 1000; ++ retval = ++ 64107 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY + ++ retval; ++ } ++ break; ++ default: ++ DWC_WARN("Unknown device speed\n"); ++ retval = -1; ++ } ++ ++ return NS_TO_US(retval); ++} ++ ++/** ++ * Initializes a QH structure. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh The QH to init. ++ * @param urb Holds the information about the device/endpoint that we need ++ * to initialize the QH. ++ */ ++#define SCHEDULE_SLOP 10 ++void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb) ++{ ++ char *speed, *type; ++ int dev_speed; ++ uint32_t hub_addr, hub_port; ++ ++ dwc_memset(qh, 0, sizeof(dwc_otg_qh_t)); ++ ++ /* Initialize QH */ ++ qh->ep_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info); ++ qh->ep_is_in = dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0; ++ ++ qh->data_toggle = DWC_OTG_HC_PID_DATA0; ++ qh->maxp = dwc_otg_hcd_get_mps(&urb->pipe_info); ++ DWC_CIRCLEQ_INIT(&qh->qtd_list); ++ DWC_LIST_INIT(&qh->qh_list_entry); ++ qh->channel = NULL; ++ ++ /* FS/LS Enpoint on HS Hub ++ * NOT virtual root hub */ ++ dev_speed = hcd->fops->speed(hcd, urb->priv); ++ ++ hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &hub_port); ++ qh->do_split = 0; ++ ++ if (((dev_speed == USB_SPEED_LOW) || ++ (dev_speed == USB_SPEED_FULL)) && ++ (hub_addr != 0 && hub_addr != 1)) { ++ DWC_DEBUGPL(DBG_HCD, ++ "QH init: EP %d: TT found at hub addr %d, for port %d\n", ++ dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr, ++ hub_port); ++ qh->do_split = 1; ++ } ++ ++ if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) { ++ /* Compute scheduling parameters once and save them. */ ++ hprt0_data_t hprt; ++ ++ /** @todo Account for split transfers in the bus time. */ ++ int bytecount = ++ dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp); ++ ++ qh->usecs = ++ calc_bus_time((qh->do_split ? USB_SPEED_HIGH : dev_speed), ++ qh->ep_is_in, (qh->ep_type == UE_ISOCHRONOUS), ++ bytecount); ++ /* Start in a slightly future (micro)frame. */ ++ qh->sched_frame = dwc_frame_num_inc(hcd->frame_number, ++ SCHEDULE_SLOP); ++ qh->interval = urb->interval; ++ ++ hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0); ++ if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) && ++ ((dev_speed == USB_SPEED_LOW) || ++ (dev_speed == USB_SPEED_FULL))) { ++ qh->interval *= 8; ++ qh->sched_frame |= 0x7; ++ qh->start_split_frame = qh->sched_frame; ++ } ++ ++ } ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n"); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - qh = %p\n", qh); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Device Address = %d\n", ++ dwc_otg_hcd_get_dev_addr(&urb->pipe_info)); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Endpoint %d, %s\n", ++ dwc_otg_hcd_get_ep_num(&urb->pipe_info), ++ dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT"); ++ switch (dev_speed) { ++ case USB_SPEED_LOW: ++ qh->dev_speed = DWC_OTG_EP_SPEED_LOW; ++ speed = "low"; ++ break; ++ case USB_SPEED_FULL: ++ qh->dev_speed = DWC_OTG_EP_SPEED_FULL; ++ speed = "full"; ++ break; ++ case USB_SPEED_HIGH: ++ qh->dev_speed = DWC_OTG_EP_SPEED_HIGH; ++ speed = "high"; ++ break; ++ default: ++ speed = "?"; ++ break; ++ } ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Speed = %s\n", speed); ++ ++ switch (qh->ep_type) { ++ case UE_ISOCHRONOUS: ++ type = "isochronous"; ++ break; ++ case UE_INTERRUPT: ++ type = "interrupt"; ++ break; ++ case UE_CONTROL: ++ type = "control"; ++ break; ++ case UE_BULK: ++ type = "bulk"; ++ break; ++ default: ++ type = "?"; ++ break; ++ } ++ ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Type = %s\n", type); ++ ++#ifdef DEBUG ++ if (qh->ep_type == UE_INTERRUPT) { ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - usecs = %d\n", ++ qh->usecs); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - interval = %d\n", ++ qh->interval); ++ } ++#endif ++ ++} ++ ++/** ++ * This function allocates and initializes a QH. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param urb Holds the information about the device/endpoint that we need ++ * to initialize the QH. ++ * @param atomic_alloc Flag to do atomic allocation if needed ++ * ++ * @return Returns pointer to the newly allocated QH, or NULL on error. */ ++dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd, ++ dwc_otg_hcd_urb_t * urb, int atomic_alloc) ++{ ++ dwc_otg_qh_t *qh; ++ ++ /* Allocate memory */ ++ /** @todo add memflags argument */ ++ qh = dwc_otg_hcd_qh_alloc(atomic_alloc); ++ if (qh == NULL) { ++ DWC_ERROR("qh allocation failed"); ++ return NULL; ++ } ++ ++ qh_init(hcd, qh, urb); ++ ++ if (hcd->core_if->dma_desc_enable ++ && (dwc_otg_hcd_qh_init_ddma(hcd, qh) < 0)) { ++ dwc_otg_hcd_qh_free(hcd, qh); ++ return NULL; ++ } ++ ++ return qh; ++} ++ ++/** ++ * Checks that a channel is available for a periodic transfer. ++ * ++ * @return 0 if successful, negative error code otherise. ++ */ ++static int periodic_channel_available(dwc_otg_hcd_t * hcd) ++{ ++ /* ++ * Currently assuming that there is a dedicated host channnel for each ++ * periodic transaction plus at least one host channel for ++ * non-periodic transactions. ++ */ ++ int status; ++ int num_channels; ++ ++ num_channels = hcd->core_if->core_params->host_channels; ++ if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels) ++ && (hcd->periodic_channels < num_channels - 1)) { ++ status = 0; ++ } else { ++ DWC_INFO("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n", ++ __func__, num_channels, hcd->periodic_channels, hcd->non_periodic_channels); //NOTICE ++ status = -DWC_E_NO_SPACE; ++ } ++ ++ return status; ++} ++ ++/** ++ * Checks that there is sufficient bandwidth for the specified QH in the ++ * periodic schedule. For simplicity, this calculation assumes that all the ++ * transfers in the periodic schedule may occur in the same (micro)frame. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh QH containing periodic bandwidth required. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++static int check_periodic_bandwidth(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ int status; ++ int16_t max_claimed_usecs; ++ ++ status = 0; ++ ++ if ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) || qh->do_split) { ++ /* ++ * High speed mode. ++ * Max periodic usecs is 80% x 125 usec = 100 usec. ++ */ ++ ++ max_claimed_usecs = 100 - qh->usecs; ++ } else { ++ /* ++ * Full speed mode. ++ * Max periodic usecs is 90% x 1000 usec = 900 usec. ++ */ ++ max_claimed_usecs = 900 - qh->usecs; ++ } ++ ++ if (hcd->periodic_usecs > max_claimed_usecs) { ++ DWC_INFO("%s: already claimed usecs %d, required usecs %d\n", __func__, hcd->periodic_usecs, qh->usecs); //NOTICE ++ status = -DWC_E_NO_SPACE; ++ } ++ ++ return status; ++} ++ ++/** ++ * Checks that the max transfer size allowed in a host channel is large enough ++ * to handle the maximum data transfer in a single (micro)frame for a periodic ++ * transfer. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh QH for a periodic endpoint. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++static int check_max_xfer_size(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ int status; ++ uint32_t max_xfer_size; ++ uint32_t max_channel_xfer_size; ++ ++ status = 0; ++ ++ max_xfer_size = dwc_max_packet(qh->maxp) * dwc_hb_mult(qh->maxp); ++ max_channel_xfer_size = hcd->core_if->core_params->max_transfer_size; ++ ++ if (max_xfer_size > max_channel_xfer_size) { ++ DWC_INFO("%s: Periodic xfer length %d > " "max xfer length for channel %d\n", ++ __func__, max_xfer_size, max_channel_xfer_size); //NOTICE ++ status = -DWC_E_NO_SPACE; ++ } ++ ++ return status; ++} ++ ++/** ++ * Schedules an interrupt or isochronous transfer in the periodic schedule. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh QH for the periodic transfer. The QH should already contain the ++ * scheduling information. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ int status = 0; ++ ++ status = periodic_channel_available(hcd); ++ if (status) { ++ DWC_INFO("%s: No host channel available for periodic " "transfer.\n", __func__); //NOTICE ++ return status; ++ } ++ ++ status = check_periodic_bandwidth(hcd, qh); ++ if (status) { ++ DWC_INFO("%s: Insufficient periodic bandwidth for " "periodic transfer.\n", __func__); //NOTICE ++ return status; ++ } ++ ++ status = check_max_xfer_size(hcd, qh); ++ if (status) { ++ DWC_INFO("%s: Channel max transfer size too small " "for periodic transfer.\n", __func__); //NOTICE ++ return status; ++ } ++ ++ if (hcd->core_if->dma_desc_enable) { ++ /* Don't rely on SOF and start in ready schedule */ ++ DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry); ++ } ++ else { ++ /* Always start in the inactive schedule. */ ++ DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry); ++ } ++ ++ /* Reserve the periodic channel. */ ++ hcd->periodic_channels++; ++ ++ /* Update claimed usecs per (micro)frame. */ ++ hcd->periodic_usecs += qh->usecs; ++ ++ return status; ++} ++ ++/** ++ * This function adds a QH to either the non periodic or periodic schedule if ++ * it is not already in the schedule. If the QH is already in the schedule, no ++ * action is taken. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ int status = 0; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) { ++ /* QH already in a schedule. */ ++ return status; ++ } ++ ++ /* Add the new QH to the appropriate schedule */ ++ if (dwc_qh_is_non_per(qh)) { ++ /* Always start in the inactive schedule. */ ++ DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive, ++ &qh->qh_list_entry); ++ } else { ++ status = schedule_periodic(hcd, qh); ++ if ( !hcd->periodic_qh_count ) { ++ intr_mask.b.sofintr = 1; ++ DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } ++ hcd->periodic_qh_count++; ++ } ++ ++ return status; ++} ++ ++/** ++ * Removes an interrupt or isochronous transfer from the periodic schedule. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh QH for the periodic transfer. ++ */ ++static void deschedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ DWC_LIST_REMOVE_INIT(&qh->qh_list_entry); ++ ++ /* Release the periodic channel reservation. */ ++ hcd->periodic_channels--; ++ ++ /* Update claimed usecs per (micro)frame. */ ++ hcd->periodic_usecs -= qh->usecs; ++} ++ ++/** ++ * Removes a QH from either the non-periodic or periodic schedule. Memory is ++ * not freed. ++ * ++ * @param hcd The HCD state structure. ++ * @param qh QH to remove from schedule. */ ++void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ if (DWC_LIST_EMPTY(&qh->qh_list_entry)) { ++ /* QH is not in a schedule. */ ++ return; ++ } ++ ++ if (dwc_qh_is_non_per(qh)) { ++ if (hcd->non_periodic_qh_ptr == &qh->qh_list_entry) { ++ hcd->non_periodic_qh_ptr = ++ hcd->non_periodic_qh_ptr->next; ++ } ++ DWC_LIST_REMOVE_INIT(&qh->qh_list_entry); ++ } else { ++ deschedule_periodic(hcd, qh); ++ hcd->periodic_qh_count--; ++ if( !hcd->periodic_qh_count ) { ++ intr_mask.b.sofintr = 1; ++ DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ } ++ } ++} ++ ++/** ++ * Deactivates a QH. For non-periodic QHs, removes the QH from the active ++ * non-periodic schedule. The QH is added to the inactive non-periodic ++ * schedule if any QTDs are still attached to the QH. ++ * ++ * For periodic QHs, the QH is removed from the periodic queued schedule. If ++ * there are any QTDs still attached to the QH, the QH is added to either the ++ * periodic inactive schedule or the periodic ready schedule and its next ++ * scheduled frame is calculated. The QH is placed in the ready schedule if ++ * the scheduled frame has been reached already. Otherwise it's placed in the ++ * inactive schedule. If there are no QTDs attached to the QH, the QH is ++ * completely removed from the periodic schedule. ++ */ ++void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, ++ int sched_next_periodic_split) ++{ ++ if (dwc_qh_is_non_per(qh)) { ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ /* Add back to inactive non-periodic schedule. */ ++ dwc_otg_hcd_qh_add(hcd, qh); ++ } ++ } else { ++ uint16_t frame_number = dwc_otg_hcd_get_frame_number(hcd); ++ ++ if (qh->do_split) { ++ /* Schedule the next continuing periodic split transfer */ ++ if (sched_next_periodic_split) { ++ ++ qh->sched_frame = frame_number; ++ if (dwc_frame_num_le(frame_number, ++ dwc_frame_num_inc ++ (qh->start_split_frame, ++ 1))) { ++ /* ++ * Allow one frame to elapse after start ++ * split microframe before scheduling ++ * complete split, but DONT if we are ++ * doing the next start split in the ++ * same frame for an ISOC out. ++ */ ++ if ((qh->ep_type != UE_ISOCHRONOUS) || ++ (qh->ep_is_in != 0)) { ++ qh->sched_frame = ++ dwc_frame_num_inc(qh->sched_frame, 1); ++ } ++ } ++ } else { ++ qh->sched_frame = ++ dwc_frame_num_inc(qh->start_split_frame, ++ qh->interval); ++ if (dwc_frame_num_le ++ (qh->sched_frame, frame_number)) { ++ qh->sched_frame = frame_number; ++ } ++ qh->sched_frame |= 0x7; ++ qh->start_split_frame = qh->sched_frame; ++ } ++ } else { ++ qh->sched_frame = ++ dwc_frame_num_inc(qh->sched_frame, qh->interval); ++ if (dwc_frame_num_le(qh->sched_frame, frame_number)) { ++ qh->sched_frame = frame_number; ++ } ++ } ++ ++ if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ } else { ++ /* ++ * Remove from periodic_sched_queued and move to ++ * appropriate queue. ++ */ ++ if (qh->sched_frame == frame_number) { ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready, ++ &qh->qh_list_entry); ++ } else { ++ DWC_LIST_MOVE_HEAD ++ (&hcd->periodic_sched_inactive, ++ &qh->qh_list_entry); ++ } ++ } ++ } ++} ++ ++/** ++ * This function allocates and initializes a QTD. ++ * ++ * @param urb The URB to create a QTD from. Each URB-QTD pair will end up ++ * pointing to each other so each pair should have a unique correlation. ++ * @param atomic_alloc Flag to do atomic alloc if needed ++ * ++ * @return Returns pointer to the newly allocated QTD, or NULL on error. */ ++dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, int atomic_alloc) ++{ ++ dwc_otg_qtd_t *qtd; ++ ++ qtd = dwc_otg_hcd_qtd_alloc(atomic_alloc); ++ if (qtd == NULL) { ++ return NULL; ++ } ++ ++ dwc_otg_hcd_qtd_init(qtd, urb); ++ return qtd; ++} ++ ++/** ++ * Initializes a QTD structure. ++ * ++ * @param qtd The QTD to initialize. ++ * @param urb The URB to use for initialization. */ ++void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb) ++{ ++ dwc_memset(qtd, 0, sizeof(dwc_otg_qtd_t)); ++ qtd->urb = urb; ++ if (dwc_otg_hcd_get_pipe_type(&urb->pipe_info) == UE_CONTROL) { ++ /* ++ * The only time the QTD data toggle is used is on the data ++ * phase of control transfers. This phase always starts with ++ * DATA1. ++ */ ++ qtd->data_toggle = DWC_OTG_HC_PID_DATA1; ++ qtd->control_phase = DWC_OTG_CONTROL_SETUP; ++ } ++ ++ /* start split */ ++ qtd->complete_split = 0; ++ qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL; ++ qtd->isoc_split_offset = 0; ++ qtd->in_process = 0; ++ ++ /* Store the qtd ptr in the urb to reference what QTD. */ ++ urb->qtd = qtd; ++ return; ++} ++ ++/** ++ * This function adds a QTD to the QTD-list of a QH. It will find the correct ++ * QH to place the QTD into. If it does not find a QH, then it will create a ++ * new QH. If the QH to which the QTD is added is not currently scheduled, it ++ * is placed into the proper schedule based on its EP type. ++ * ++ * @param[in] qtd The QTD to add ++ * @param[in] hcd The DWC HCD structure ++ * @param[out] qh out parameter to return queue head ++ * @param atomic_alloc Flag to do atomic alloc if needed ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, ++ dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh, int atomic_alloc) ++{ ++ int retval = 0; ++ dwc_irqflags_t flags; ++ ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ ++ /* ++ * Get the QH which holds the QTD-list to insert to. Create QH if it ++ * doesn't exist. ++ */ ++ if (*qh == NULL) { ++ *qh = dwc_otg_hcd_qh_create(hcd, urb, atomic_alloc); ++ if (*qh == NULL) { ++ retval = -1; ++ goto done; ++ } ++ } ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ retval = dwc_otg_hcd_qh_add(hcd, *qh); ++ if (retval == 0) { ++ DWC_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd, ++ qtd_list_entry); ++ } ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ ++done: ++ ++ return retval; ++} ++ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_os_dep.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_os_dep.h +new file mode 100644 +index 0000000..7e491fe +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_os_dep.h +@@ -0,0 +1,88 @@ ++#ifndef _DWC_OS_DEP_H_ ++#define _DWC_OS_DEP_H_ ++ ++/** ++ * @file ++ * ++ * This file contains OS dependent structures. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++# include ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) ++# include ++#else ++# include ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) ++# include ++#else ++# include ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++# include ++#endif ++ ++ ++#include ++#include ++#include ++#include ++ ++ ++/** The OS page size */ ++#define DWC_OS_PAGE_SIZE PAGE_SIZE ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ++typedef int gfp_t; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ++# define IRQF_SHARED SA_SHIRQ ++#endif ++ ++typedef struct os_dependent { ++ /** Base address returned from ioremap() */ ++ void *base; ++ ++ /** Register offset for Diagnostic API */ ++ uint32_t reg_offset; ++ ++ uint32_t res_start; ++ ++ struct platform_device *lmdev; ++ ++} os_dependent_t; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_OS_DEP_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd.c +new file mode 100644 +index 0000000..36b52d5 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd.c +@@ -0,0 +1,2838 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $ ++ * $Revision: #105 $ ++ * $Date: 2013/05/16 $ ++ * $Change: 2231774 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_HOST_ONLY ++ ++/** @file ++ * This file implements PCD Core. All code in this file is portable and doesn't ++ * use any OS specific functions. ++ * PCD Core provides Interface, defined in ++ * header file, which can be used to implement OS specific PCD interface. ++ * ++ * An important function of the PCD is managing interrupts generated ++ * by the DWC_otg controller. The implementation of the DWC_otg device ++ * mode interrupt service routines is in dwc_otg_pcd_intr.c. ++ * ++ * @todo Add Device Mode test modes (Test J mode, Test K mode, etc). ++ * @todo Does it work when the request size is greater than DEPTSIZ ++ * transfer size ++ * ++ */ ++ ++#include "dwc_otg_pcd.h" ++ ++#ifdef DWC_UTE_CFI ++#include "dwc_otg_cfi.h" ++ ++extern int init_cfi(cfiobject_t * cfiobj); ++#endif ++static int bulk_num = 0; ++/** ++ * Choose endpoint from ep arrays using usb_ep structure. ++ */ ++static dwc_otg_pcd_ep_t *get_ep_from_handle(dwc_otg_pcd_t * pcd, void *handle) ++{ ++ int i; ++ if (pcd->ep0.priv == handle) { ++ return &pcd->ep0; ++ } ++ for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) { ++ if (pcd->in_ep[i].priv == handle) ++ return &pcd->in_ep[i]; ++ if (pcd->out_ep[i].priv == handle) ++ return &pcd->out_ep[i]; ++ } ++ ++ return NULL; ++} ++ ++/** ++ * This function completes a request. It call's the request call back. ++ */ ++void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req, ++ int32_t status) ++{ ++ unsigned stopped = ep->stopped; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(ep %p req %p)\n", __func__, ep, req); ++ DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry); ++ ++ /* don't modify queue heads during completion callback */ ++ ep->stopped = 1; ++ /* spin_unlock/spin_lock now done in fops->complete() */ ++ ep->pcd->fops->complete(ep->pcd, ep->priv, req->priv, status, ++ req->actual); ++ ++ if (ep->pcd->request_pending > 0) { ++ --ep->pcd->request_pending; ++ } ++ ++ ep->stopped = stopped; ++ DWC_FREE(req); ++} ++ ++/** ++ * This function terminates all the requsts in the EP request queue. ++ */ ++void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_pcd_request_t *req; ++ ++ ep->stopped = 1; ++ ++ /* called with irqs blocked?? */ ++ while (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ dwc_otg_request_done(ep, req, -DWC_E_SHUTDOWN); ++ } ++} ++ ++void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd, ++ const struct dwc_otg_pcd_function_ops *fops) ++{ ++ pcd->fops = fops; ++} ++ ++/** ++ * PCD Callback function for initializing the PCD when switching to ++ * device mode. ++ * ++ * @param p void pointer to the dwc_otg_pcd_t ++ */ ++static int32_t dwc_otg_pcd_start_cb(void *p) ++{ ++ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ /* ++ * Initialized the Core for Device mode. ++ */ ++ if (dwc_otg_is_device_mode(core_if)) { ++ dwc_otg_core_dev_init(core_if); ++ /* Set core_if's lock pointer to the pcd->lock */ ++ core_if->lock = pcd->lock; ++ } ++ return 1; ++} ++ ++/** CFI-specific buffer allocation function for EP */ ++#ifdef DWC_UTE_CFI ++uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr, ++ size_t buflen, int flags) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ ep = get_ep_from_handle(pcd, pep); ++ if (!ep) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ return pcd->cfi->ops.ep_alloc_buf(pcd->cfi, pcd, ep, addr, buflen, ++ flags); ++} ++#else ++uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr, ++ size_t buflen, int flags); ++#endif ++ ++/** ++ * PCD Callback function for notifying the PCD when resuming from ++ * suspend. ++ * ++ * @param p void pointer to the dwc_otg_pcd_t ++ */ ++static int32_t dwc_otg_pcd_resume_cb(void *p) ++{ ++ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; ++ ++ if (pcd->fops->resume) { ++ pcd->fops->resume(pcd); ++ } ++ ++ /* Stop the SRP timeout timer. */ ++ if ((GET_CORE_IF(pcd)->core_params->phy_type != DWC_PHY_TYPE_PARAM_FS) ++ || (!GET_CORE_IF(pcd)->core_params->i2c_enable)) { ++ if (GET_CORE_IF(pcd)->srp_timer_started) { ++ GET_CORE_IF(pcd)->srp_timer_started = 0; ++ DWC_TIMER_CANCEL(GET_CORE_IF(pcd)->srp_timer); ++ } ++ } ++ return 1; ++} ++ ++/** ++ * PCD Callback function for notifying the PCD device is suspended. ++ * ++ * @param p void pointer to the dwc_otg_pcd_t ++ */ ++static int32_t dwc_otg_pcd_suspend_cb(void *p) ++{ ++ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; ++ ++ if (pcd->fops->suspend) { ++ DWC_SPINUNLOCK(pcd->lock); ++ pcd->fops->suspend(pcd); ++ DWC_SPINLOCK(pcd->lock); ++ } ++ ++ return 1; ++} ++ ++/** ++ * PCD Callback function for stopping the PCD when switching to Host ++ * mode. ++ * ++ * @param p void pointer to the dwc_otg_pcd_t ++ */ ++static int32_t dwc_otg_pcd_stop_cb(void *p) ++{ ++ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; ++ extern void dwc_otg_pcd_stop(dwc_otg_pcd_t * _pcd); ++ ++ dwc_otg_pcd_stop(pcd); ++ return 1; ++} ++ ++/** ++ * PCD Callback structure for handling mode switching. ++ */ ++static dwc_otg_cil_callbacks_t pcd_callbacks = { ++ .start = dwc_otg_pcd_start_cb, ++ .stop = dwc_otg_pcd_stop_cb, ++ .suspend = dwc_otg_pcd_suspend_cb, ++ .resume_wakeup = dwc_otg_pcd_resume_cb, ++ .p = 0, /* Set at registration */ ++}; ++ ++/** ++ * This function allocates a DMA Descriptor chain for the Endpoint ++ * buffer to be used for a transfer to/from the specified endpoint. ++ */ ++dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(dwc_dma_t * dma_desc_addr, ++ uint32_t count) ++{ ++ return DWC_DMA_ALLOC_ATOMIC(count * sizeof(dwc_otg_dev_dma_desc_t), ++ dma_desc_addr); ++} ++ ++/** ++ * This function frees a DMA Descriptor chain that was allocated by ep_alloc_desc. ++ */ ++void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr, ++ uint32_t dma_desc_addr, uint32_t count) ++{ ++ DWC_DMA_FREE(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr, ++ dma_desc_addr); ++} ++ ++#ifdef DWC_EN_ISOC ++ ++/** ++ * This function initializes a descriptor chain for Isochronous transfer ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param dwc_ep The EP to start the transfer on. ++ * ++ */ ++void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * dwc_ep) ++{ ++ ++ dsts_data_t dsts = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ int i, j; ++ uint32_t len; ++ ++ if (dwc_ep->is_in) ++ dwc_ep->desc_cnt = dwc_ep->buf_proc_intrvl / dwc_ep->bInterval; ++ else ++ dwc_ep->desc_cnt = ++ dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm / ++ dwc_ep->bInterval; ++ ++ /** Allocate descriptors for double buffering */ ++ dwc_ep->iso_desc_addr = ++ dwc_otg_ep_alloc_desc_chain(&dwc_ep->iso_dma_desc_addr, ++ dwc_ep->desc_cnt * 2); ++ if (dwc_ep->desc_addr) { ++ DWC_WARN("%s, can't allocate DMA descriptor chain\n", __func__); ++ return; ++ } ++ ++ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ /** ISO OUT EP */ ++ if (dwc_ep->is_in == 0) { ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr; ++ dma_addr_t dma_ad; ++ uint32_t data_per_desc; ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[dwc_ep->num]; ++ int offset; ++ ++ addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl; ++ ++ /** Buffer 0 descriptors setup */ ++ dma_ad = dwc_ep->dma_addr0; ++ ++ sts.b_iso_out.bs = BS_HOST_READY; ++ sts.b_iso_out.rxsts = 0; ++ sts.b_iso_out.l = 0; ++ sts.b_iso_out.sp = 0; ++ sts.b_iso_out.ioc = 0; ++ sts.b_iso_out.pid = 0; ++ sts.b_iso_out.framenum = 0; ++ ++ offset = 0; ++ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; ++ i += dwc_ep->pkt_per_frm) { ++ ++ for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { ++ uint32_t len = (j + 1) * dwc_ep->maxpacket; ++ if (len > dwc_ep->data_per_frame) ++ data_per_desc = ++ dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket; ++ else ++ data_per_desc = dwc_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; ++ ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ } ++ ++ for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) { ++ uint32_t len = (j + 1) * dwc_ep->maxpacket; ++ if (len > dwc_ep->data_per_frame) ++ data_per_desc = ++ dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket; ++ else ++ data_per_desc = dwc_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ ++ sts.b_iso_out.ioc = 1; ++ len = (j + 1) * dwc_ep->maxpacket; ++ if (len > dwc_ep->data_per_frame) ++ data_per_desc = ++ dwc_ep->data_per_frame - j * dwc_ep->maxpacket; ++ else ++ data_per_desc = dwc_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ dma_desc++; ++ ++ /** Buffer 1 descriptors setup */ ++ sts.b_iso_out.ioc = 0; ++ dma_ad = dwc_ep->dma_addr1; ++ ++ offset = 0; ++ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; ++ i += dwc_ep->pkt_per_frm) { ++ for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { ++ uint32_t len = (j + 1) * dwc_ep->maxpacket; ++ if (len > dwc_ep->data_per_frame) ++ data_per_desc = ++ dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket; ++ else ++ data_per_desc = dwc_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; ++ ++ data_per_desc = ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ } ++ for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) { ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ ++ sts.b_iso_out.ioc = 1; ++ sts.b_iso_out.l = 1; ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ dwc_ep->next_frame = 0; ++ ++ /** Write dma_ad into DOEPDMA register */ ++ DWC_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) dwc_ep->iso_dma_desc_addr); ++ ++ } ++ /** ISO IN EP */ ++ else { ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr; ++ dma_addr_t dma_ad; ++ dwc_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[dwc_ep->num]; ++ unsigned int frmnumber; ++ fifosize_data_t txfifosize, rxfifosize; ++ ++ txfifosize.d32 = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[dwc_ep->num]-> ++ dtxfsts); ++ rxfifosize.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); ++ ++ addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl; ++ ++ dma_ad = dwc_ep->dma_addr0; ++ ++ dsts.d32 = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ sts.b_iso_in.bs = BS_HOST_READY; ++ sts.b_iso_in.txsts = 0; ++ sts.b_iso_in.sp = ++ (dwc_ep->data_per_frame % dwc_ep->maxpacket) ? 1 : 0; ++ sts.b_iso_in.ioc = 0; ++ sts.b_iso_in.pid = dwc_ep->pkt_per_frm; ++ ++ frmnumber = dwc_ep->next_frame; ++ ++ sts.b_iso_in.framenum = frmnumber; ++ sts.b_iso_in.txbytes = dwc_ep->data_per_frame; ++ sts.b_iso_in.l = 0; ++ ++ /** Buffer 0 descriptors setup */ ++ for (i = 0; i < dwc_ep->desc_cnt - 1; i++) { ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ dma_desc++; ++ ++ dma_ad += dwc_ep->data_per_frame; ++ sts.b_iso_in.framenum += dwc_ep->bInterval; ++ } ++ ++ sts.b_iso_in.ioc = 1; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++dma_desc; ++ ++ /** Buffer 1 descriptors setup */ ++ sts.b_iso_in.ioc = 0; ++ dma_ad = dwc_ep->dma_addr1; ++ ++ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; ++ i += dwc_ep->pkt_per_frm) { ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ dma_desc++; ++ ++ dma_ad += dwc_ep->data_per_frame; ++ sts.b_iso_in.framenum += dwc_ep->bInterval; ++ ++ sts.b_iso_in.ioc = 0; ++ } ++ sts.b_iso_in.ioc = 1; ++ sts.b_iso_in.l = 1; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ dwc_ep->next_frame = sts.b_iso_in.framenum + dwc_ep->bInterval; ++ ++ /** Write dma_ad into diepdma register */ ++ DWC_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) dwc_ep->iso_dma_desc_addr); ++ } ++ /** Enable endpoint, clear nak */ ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.usbactep = 1; ++ depctl.b.cnak = 1; ++ ++ DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32); ++ depctl.d32 = DWC_READ_REG32(addr); ++} ++ ++/** ++ * This function initializes a descriptor chain for Isochronous transfer ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * ep) ++{ ++ depctl_data_t depctl = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ ++ if (ep->is_in) { ++ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; ++ } else { ++ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; ++ } ++ ++ if (core_if->dma_enable == 0 || core_if->dma_desc_enable != 0) { ++ return; ++ } else { ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ ++ ep->xfer_len = ++ ep->data_per_frame * ep->buf_proc_intrvl / ep->bInterval; ++ ep->pkt_cnt = ++ (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; ++ ep->xfer_count = 0; ++ ep->xfer_buff = ++ (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0; ++ ep->dma_addr = ++ (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0; ++ ++ if (ep->is_in) { ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ deptsiz.b.mc = ep->pkt_per_frm; ++ deptsiz.b.xfersize = ep->xfer_len; ++ deptsiz.b.pktcnt = ++ (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ dieptsiz, deptsiz.d32); ++ ++ /* Write the DMA register */ ++ DWC_WRITE_REG32(& ++ (core_if->dev_if->in_ep_regs[ep->num]-> ++ diepdma), (uint32_t) ep->dma_addr); ++ ++ } else { ++ deptsiz.b.pktcnt = ++ (ep->xfer_len + (ep->maxpacket - 1)) / ++ ep->maxpacket; ++ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; ++ ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]-> ++ doeptsiz, deptsiz.d32); ++ ++ /* Write the DMA register */ ++ DWC_WRITE_REG32(& ++ (core_if->dev_if->out_ep_regs[ep->num]-> ++ doepdma), (uint32_t) ep->dma_addr); ++ ++ } ++ /** Enable endpoint, clear nak */ ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ ++ DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32); ++ } ++} ++ ++/** ++ * This function does the setup for a data transfer for an EP and ++ * starts the transfer. For an IN transfer, the packets will be ++ * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers, ++ * the packets are unloaded from the Rx FIFO in the ISR. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++ ++static void dwc_otg_iso_ep_start_transfer(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * ep) ++{ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ if (ep->is_in) { ++ ep->desc_cnt = ep->pkt_cnt / ep->pkt_per_frm; ++ } else { ++ ep->desc_cnt = ep->pkt_cnt; ++ } ++ dwc_otg_iso_ep_start_ddma_transfer(core_if, ep); ++ } else { ++ if (core_if->pti_enh_enable) { ++ dwc_otg_iso_ep_start_buf_transfer(core_if, ep); ++ } else { ++ ep->cur_pkt_addr = ++ (ep->proc_buf_num) ? ep->xfer_buff1 : ep-> ++ xfer_buff0; ++ ep->cur_pkt_dma_addr = ++ (ep->proc_buf_num) ? ep->dma_addr1 : ep-> ++ dma_addr0; ++ dwc_otg_iso_ep_start_frm_transfer(core_if, ep); ++ } ++ } ++ } else { ++ ep->cur_pkt_addr = ++ (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0; ++ ep->cur_pkt_dma_addr = ++ (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0; ++ dwc_otg_iso_ep_start_frm_transfer(core_if, ep); ++ } ++} ++ ++/** ++ * This function stops transfer for an EP and ++ * resets the ep's variables. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++ ++void dwc_otg_iso_ep_stop_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ ++ if (ep->is_in == 1) { ++ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; ++ } else { ++ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; ++ } ++ ++ /* disable the ep */ ++ depctl.d32 = DWC_READ_REG32(addr); ++ ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ ++ DWC_WRITE_REG32(addr, depctl.d32); ++ ++ if (core_if->dma_desc_enable && ++ ep->iso_desc_addr && ep->iso_dma_desc_addr) { ++ dwc_otg_ep_free_desc_chain(ep->iso_desc_addr, ++ ep->iso_dma_desc_addr, ++ ep->desc_cnt * 2); ++ } ++ ++ /* reset varibales */ ++ ep->dma_addr0 = 0; ++ ep->dma_addr1 = 0; ++ ep->xfer_buff0 = 0; ++ ep->xfer_buff1 = 0; ++ ep->data_per_frame = 0; ++ ep->data_pattern_frame = 0; ++ ep->sync_frame = 0; ++ ep->buf_proc_intrvl = 0; ++ ep->bInterval = 0; ++ ep->proc_buf_num = 0; ++ ep->pkt_per_frm = 0; ++ ep->desc_cnt = 0; ++ ep->iso_desc_addr = 0; ++ ep->iso_dma_desc_addr = 0; ++} ++ ++int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf0, uint8_t * buf1, dwc_dma_t dma0, ++ dwc_dma_t dma1, int sync_frame, int dp_frame, ++ int data_per_frame, int start_frame, ++ int buf_proc_intrvl, void *req_handle, ++ int atomic_alloc) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ dwc_irqflags_t flags = 0; ++ dwc_ep_t *dwc_ep; ++ int32_t frm_data; ++ dsts_data_t dsts; ++ dwc_otg_core_if_t *core_if; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ ++ if (!ep || !ep->desc || ep->dwc_ep.num == 0) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ core_if = GET_CORE_IF(pcd); ++ dwc_ep = &ep->dwc_ep; ++ ++ if (ep->iso_req_handle) { ++ DWC_WARN("ISO request in progress\n"); ++ } ++ ++ dwc_ep->dma_addr0 = dma0; ++ dwc_ep->dma_addr1 = dma1; ++ ++ dwc_ep->xfer_buff0 = buf0; ++ dwc_ep->xfer_buff1 = buf1; ++ ++ dwc_ep->data_per_frame = data_per_frame; ++ ++ /** @todo - pattern data support is to be implemented in the future */ ++ dwc_ep->data_pattern_frame = dp_frame; ++ dwc_ep->sync_frame = sync_frame; ++ ++ dwc_ep->buf_proc_intrvl = buf_proc_intrvl; ++ ++ dwc_ep->bInterval = 1 << (ep->desc->bInterval - 1); ++ ++ dwc_ep->proc_buf_num = 0; ++ ++ dwc_ep->pkt_per_frm = 0; ++ frm_data = ep->dwc_ep.data_per_frame; ++ while (frm_data > 0) { ++ dwc_ep->pkt_per_frm++; ++ frm_data -= ep->dwc_ep.maxpacket; ++ } ++ ++ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ if (start_frame == -1) { ++ dwc_ep->next_frame = dsts.b.soffn + 1; ++ if (dwc_ep->bInterval != 1) { ++ dwc_ep->next_frame = ++ dwc_ep->next_frame + (dwc_ep->bInterval - 1 - ++ dwc_ep->next_frame % ++ dwc_ep->bInterval); ++ } ++ } else { ++ dwc_ep->next_frame = start_frame; ++ } ++ ++ if (!core_if->pti_enh_enable) { ++ dwc_ep->pkt_cnt = ++ dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm / ++ dwc_ep->bInterval; ++ } else { ++ dwc_ep->pkt_cnt = ++ (dwc_ep->data_per_frame * ++ (dwc_ep->buf_proc_intrvl / dwc_ep->bInterval) ++ - 1 + dwc_ep->maxpacket) / dwc_ep->maxpacket; ++ } ++ ++ if (core_if->dma_desc_enable) { ++ dwc_ep->desc_cnt = ++ dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm / ++ dwc_ep->bInterval; ++ } ++ ++ if (atomic_alloc) { ++ dwc_ep->pkt_info = ++ DWC_ALLOC_ATOMIC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); ++ } else { ++ dwc_ep->pkt_info = ++ DWC_ALLOC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); ++ } ++ if (!dwc_ep->pkt_info) { ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return -DWC_E_NO_MEMORY; ++ } ++ if (core_if->pti_enh_enable) { ++ dwc_memset(dwc_ep->pkt_info, 0, ++ sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); ++ } ++ ++ dwc_ep->cur_pkt = 0; ++ ep->iso_req_handle = req_handle; ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ dwc_otg_iso_ep_start_transfer(core_if, dwc_ep); ++ return 0; ++} ++ ++int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle) ++{ ++ dwc_irqflags_t flags = 0; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep || !ep->desc || ep->dwc_ep.num == 0) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ dwc_ep = &ep->dwc_ep; ++ ++ dwc_otg_iso_ep_stop_transfer(GET_CORE_IF(pcd), dwc_ep); ++ ++ DWC_FREE(dwc_ep->pkt_info); ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ if (ep->iso_req_handle != req_handle) { ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ ep->iso_req_handle = 0; ++ return 0; ++} ++ ++/** ++ * This function is used for perodical data exchnage between PCD and gadget drivers. ++ * for Isochronous EPs ++ * ++ * - Every time a sync period completes this function is called to ++ * perform data exchange between PCD and gadget ++ */ ++void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep, ++ void *req_handle) ++{ ++ int i; ++ dwc_ep_t *dwc_ep; ++ ++ dwc_ep = &ep->dwc_ep; ++ ++ DWC_SPINUNLOCK(ep->pcd->lock); ++ pcd->fops->isoc_complete(pcd, ep->priv, ep->iso_req_handle, ++ dwc_ep->proc_buf_num ^ 0x1); ++ DWC_SPINLOCK(ep->pcd->lock); ++ ++ for (i = 0; i < dwc_ep->pkt_cnt; ++i) { ++ dwc_ep->pkt_info[i].status = 0; ++ dwc_ep->pkt_info[i].offset = 0; ++ dwc_ep->pkt_info[i].length = 0; ++ } ++} ++ ++int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *iso_req_handle) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep->desc || ep->dwc_ep.num == 0) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ dwc_ep = &ep->dwc_ep; ++ ++ return dwc_ep->pkt_cnt; ++} ++ ++void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *iso_req_handle, int packet, ++ int *status, int *actual, int *offset) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep) ++ DWC_WARN("bad ep\n"); ++ ++ dwc_ep = &ep->dwc_ep; ++ ++ *status = dwc_ep->pkt_info[packet].status; ++ *actual = dwc_ep->pkt_info[packet].length; ++ *offset = dwc_ep->pkt_info[packet].offset; ++} ++ ++#endif /* DWC_EN_ISOC */ ++ ++static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep, ++ uint32_t is_in, uint32_t ep_num) ++{ ++ /* Init EP structure */ ++ pcd_ep->desc = 0; ++ pcd_ep->pcd = pcd; ++ pcd_ep->stopped = 1; ++ pcd_ep->queue_sof = 0; ++ ++ /* Init DWC ep structure */ ++ pcd_ep->dwc_ep.is_in = is_in; ++ pcd_ep->dwc_ep.num = ep_num; ++ pcd_ep->dwc_ep.active = 0; ++ pcd_ep->dwc_ep.tx_fifo_num = 0; ++ /* Control until ep is actvated */ ++ pcd_ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL; ++ pcd_ep->dwc_ep.maxpacket = MAX_PACKET_SIZE; ++ pcd_ep->dwc_ep.dma_addr = 0; ++ pcd_ep->dwc_ep.start_xfer_buff = 0; ++ pcd_ep->dwc_ep.xfer_buff = 0; ++ pcd_ep->dwc_ep.xfer_len = 0; ++ pcd_ep->dwc_ep.xfer_count = 0; ++ pcd_ep->dwc_ep.sent_zlp = 0; ++ pcd_ep->dwc_ep.total_len = 0; ++ pcd_ep->dwc_ep.desc_addr = 0; ++ pcd_ep->dwc_ep.dma_desc_addr = 0; ++ DWC_CIRCLEQ_INIT(&pcd_ep->queue); ++} ++ ++/** ++ * Initialize ep's ++ */ ++static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd) ++{ ++ int i; ++ uint32_t hwcfg1; ++ dwc_otg_pcd_ep_t *ep; ++ int in_ep_cntr, out_ep_cntr; ++ uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps; ++ uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps; ++ ++ /** ++ * Initialize the EP0 structure. ++ */ ++ ep = &pcd->ep0; ++ dwc_otg_pcd_init_ep(pcd, ep, 0, 0); ++ ++ in_ep_cntr = 0; ++ hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3; ++ for (i = 1; in_ep_cntr < num_in_eps; i++) { ++ if ((hwcfg1 & 0x1) == 0) { ++ dwc_otg_pcd_ep_t *ep = &pcd->in_ep[in_ep_cntr]; ++ in_ep_cntr++; ++ /** ++ * @todo NGS: Add direction to EP, based on contents ++ * of HWCFG1. Need a copy of HWCFG1 in pcd structure? ++ * sprintf(";r ++ */ ++ dwc_otg_pcd_init_ep(pcd, ep, 1 /* IN */ , i); ++ ++ DWC_CIRCLEQ_INIT(&ep->queue); ++ } ++ hwcfg1 >>= 2; ++ } ++ ++ out_ep_cntr = 0; ++ hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2; ++ for (i = 1; out_ep_cntr < num_out_eps; i++) { ++ if ((hwcfg1 & 0x1) == 0) { ++ dwc_otg_pcd_ep_t *ep = &pcd->out_ep[out_ep_cntr]; ++ out_ep_cntr++; ++ /** ++ * @todo NGS: Add direction to EP, based on contents ++ * of HWCFG1. Need a copy of HWCFG1 in pcd structure? ++ * sprintf(";r ++ */ ++ dwc_otg_pcd_init_ep(pcd, ep, 0 /* OUT */ , i); ++ DWC_CIRCLEQ_INIT(&ep->queue); ++ } ++ hwcfg1 >>= 2; ++ } ++ ++ pcd->ep0state = EP0_DISCONNECT; ++ pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE; ++ pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL; ++} ++ ++/** ++ * Tasklet ++ * ++ */ ++extern void start_next_request(dwc_otg_pcd_ep_t * ep); ++ ++static void start_xfer_tasklet_func(void *data) ++{ ++ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ int i; ++ depctl_data_t diepctl; ++ ++ DWC_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n"); ++ ++ diepctl.d32 = DWC_READ_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl); ++ ++ if (pcd->ep0.queue_sof) { ++ pcd->ep0.queue_sof = 0; ++ start_next_request(&pcd->ep0); ++ // break; ++ } ++ ++ for (i = 0; i < core_if->dev_if->num_in_eps; i++) { ++ depctl_data_t diepctl; ++ diepctl.d32 = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl); ++ ++ if (pcd->in_ep[i].queue_sof) { ++ pcd->in_ep[i].queue_sof = 0; ++ start_next_request(&pcd->in_ep[i]); ++ // break; ++ } ++ } ++ ++ return; ++} ++ ++/** ++ * This function initialized the PCD portion of the driver. ++ * ++ */ ++dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_pcd_t *pcd = NULL; ++ dwc_otg_dev_if_t *dev_if; ++ ++ /* ++ * Allocate PCD structure ++ */ ++ pcd = DWC_ALLOC(sizeof(dwc_otg_pcd_t)); ++ ++ if (pcd == NULL) { ++ return NULL; ++ } ++ ++ pcd->lock = DWC_SPINLOCK_ALLOC(); ++ if (!pcd->lock) { ++ DWC_ERROR("Could not allocate lock for pcd"); ++ DWC_FREE(pcd); ++ return NULL; ++ } ++ /* Set core_if's lock pointer to hcd->lock */ ++ core_if->lock = pcd->lock; ++ pcd->core_if = core_if; ++ ++ dev_if = core_if->dev_if; ++ dev_if->isoc_ep = NULL; ++ ++ if (core_if->hwcfg4.b.ded_fifo_en) { ++ DWC_PRINTF("Dedicated Tx FIFOs mode\n"); ++ } else { ++ DWC_PRINTF("Shared Tx FIFO mode\n"); ++ } ++ ++ /* ++ * Initialized the Core for Device mode here if there is nod ADP support. ++ * Otherwise it will be done later in dwc_otg_adp_start routine. ++ */ ++ if (dwc_otg_is_device_mode(core_if) /*&& !core_if->adp_enable */ ) { ++ dwc_otg_core_dev_init(core_if); ++ } ++ ++ /* ++ * Register the PCD Callbacks. ++ */ ++ dwc_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd); ++ ++ /* ++ * Initialize the DMA buffer for SETUP packets ++ */ ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ pcd->setup_pkt = ++ DWC_DMA_ALLOC(sizeof(*pcd->setup_pkt) * 5, ++ &pcd->setup_pkt_dma_handle); ++ if (pcd->setup_pkt == NULL) { ++ DWC_FREE(pcd); ++ return NULL; ++ } ++ ++ pcd->status_buf = ++ DWC_DMA_ALLOC(sizeof(uint16_t), ++ &pcd->status_buf_dma_handle); ++ if (pcd->status_buf == NULL) { ++ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, ++ pcd->setup_pkt, pcd->setup_pkt_dma_handle); ++ DWC_FREE(pcd); ++ return NULL; ++ } ++ ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ dev_if->setup_desc_addr[0] = ++ dwc_otg_ep_alloc_desc_chain ++ (&dev_if->dma_setup_desc_addr[0], 1); ++ dev_if->setup_desc_addr[1] = ++ dwc_otg_ep_alloc_desc_chain ++ (&dev_if->dma_setup_desc_addr[1], 1); ++ dev_if->in_desc_addr = ++ dwc_otg_ep_alloc_desc_chain ++ (&dev_if->dma_in_desc_addr, 1); ++ dev_if->out_desc_addr = ++ dwc_otg_ep_alloc_desc_chain ++ (&dev_if->dma_out_desc_addr, 1); ++ pcd->data_terminated = 0; ++ ++ if (dev_if->setup_desc_addr[0] == 0 ++ || dev_if->setup_desc_addr[1] == 0 ++ || dev_if->in_desc_addr == 0 ++ || dev_if->out_desc_addr == 0) { ++ ++ if (dev_if->out_desc_addr) ++ dwc_otg_ep_free_desc_chain ++ (dev_if->out_desc_addr, ++ dev_if->dma_out_desc_addr, 1); ++ if (dev_if->in_desc_addr) ++ dwc_otg_ep_free_desc_chain ++ (dev_if->in_desc_addr, ++ dev_if->dma_in_desc_addr, 1); ++ if (dev_if->setup_desc_addr[1]) ++ dwc_otg_ep_free_desc_chain ++ (dev_if->setup_desc_addr[1], ++ dev_if->dma_setup_desc_addr[1], 1); ++ if (dev_if->setup_desc_addr[0]) ++ dwc_otg_ep_free_desc_chain ++ (dev_if->setup_desc_addr[0], ++ dev_if->dma_setup_desc_addr[0], 1); ++ ++ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, ++ pcd->setup_pkt, ++ pcd->setup_pkt_dma_handle); ++ DWC_DMA_FREE(sizeof(*pcd->status_buf), ++ pcd->status_buf, ++ pcd->status_buf_dma_handle); ++ ++ DWC_FREE(pcd); ++ ++ return NULL; ++ } ++ } ++ } else { ++ pcd->setup_pkt = DWC_ALLOC(sizeof(*pcd->setup_pkt) * 5); ++ if (pcd->setup_pkt == NULL) { ++ DWC_FREE(pcd); ++ return NULL; ++ } ++ ++ pcd->status_buf = DWC_ALLOC(sizeof(uint16_t)); ++ if (pcd->status_buf == NULL) { ++ DWC_FREE(pcd->setup_pkt); ++ DWC_FREE(pcd); ++ return NULL; ++ } ++ } ++ ++ dwc_otg_pcd_reinit(pcd); ++ ++ /* Allocate the cfi object for the PCD */ ++#ifdef DWC_UTE_CFI ++ pcd->cfi = DWC_ALLOC(sizeof(cfiobject_t)); ++ if (NULL == pcd->cfi) ++ goto fail; ++ if (init_cfi(pcd->cfi)) { ++ CFI_INFO("%s: Failed to init the CFI object\n", __func__); ++ goto fail; ++ } ++#endif ++ ++ /* Initialize tasklets */ ++ pcd->start_xfer_tasklet = DWC_TASK_ALLOC("xfer_tasklet", ++ start_xfer_tasklet_func, pcd); ++ pcd->test_mode_tasklet = DWC_TASK_ALLOC("test_mode_tasklet", ++ do_test_mode, pcd); ++ ++ return pcd; ++#ifdef DWC_UTE_CFI ++fail: ++#endif ++ if (pcd->setup_pkt) ++ DWC_FREE(pcd->setup_pkt); ++ if (pcd->status_buf) ++ DWC_FREE(pcd->status_buf); ++#ifdef DWC_UTE_CFI ++ if (pcd->cfi) ++ DWC_FREE(pcd->cfi); ++#endif ++ if (pcd) ++ DWC_FREE(pcd); ++ return NULL; ++ ++} ++ ++/** ++ * Remove PCD specific data ++ */ ++void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ int i; ++ if (pcd->core_if->core_params->dev_out_nak) { ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[i]); ++ pcd->core_if->ep_xfer_info[i].state = 0; ++ } ++ } ++ ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt, ++ pcd->setup_pkt_dma_handle); ++ DWC_DMA_FREE(sizeof(uint16_t), pcd->status_buf, ++ pcd->status_buf_dma_handle); ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0], ++ dev_if->dma_setup_desc_addr ++ [0], 1); ++ dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1], ++ dev_if->dma_setup_desc_addr ++ [1], 1); ++ dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr, ++ dev_if->dma_in_desc_addr, 1); ++ dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr, ++ dev_if->dma_out_desc_addr, ++ 1); ++ } ++ } else { ++ DWC_FREE(pcd->setup_pkt); ++ DWC_FREE(pcd->status_buf); ++ } ++ DWC_SPINLOCK_FREE(pcd->lock); ++ /* Set core_if's lock pointer to NULL */ ++ pcd->core_if->lock = NULL; ++ ++ DWC_TASK_FREE(pcd->start_xfer_tasklet); ++ DWC_TASK_FREE(pcd->test_mode_tasklet); ++ if (pcd->core_if->core_params->dev_out_nak) { ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ if (pcd->core_if->ep_xfer_timer[i]) { ++ DWC_TIMER_FREE(pcd->core_if->ep_xfer_timer[i]); ++ } ++ } ++ } ++ ++/* Release the CFI object's dynamic memory */ ++#ifdef DWC_UTE_CFI ++ if (pcd->cfi->ops.release) { ++ pcd->cfi->ops.release(pcd->cfi); ++ } ++#endif ++ ++ DWC_FREE(pcd); ++} ++ ++/** ++ * Returns whether registered pcd is dual speed or not ++ */ ++uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) || ++ ((core_if->hwcfg2.b.hs_phy_type == 2) && ++ (core_if->hwcfg2.b.fs_phy_type == 1) && ++ (core_if->core_params->ulpi_fs_ls))) { ++ return 0; ++ } ++ ++ return 1; ++} ++ ++/** ++ * Returns whether registered pcd is OTG capable or not ++ */ ++uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ gusbcfg_data_t usbcfg = {.d32 = 0 }; ++ uint32_t retval = 0; ++ ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) ++ if (!usbcfg.b.srpcap || !usbcfg.b.hnpcap) ++ return 0; ++ else ++ return 1; ++# else ++ if (!usbcfg.b.srpcap) ++ return 0; ++ else ++ retval |= 1; ++ ++ if (usbcfg.b.hnpcap) ++ retval |= 2; ++ ++ if (core_if->adp_enable) ++ retval |= 4; ++#endif ++ ++ return retval; ++} ++ ++/** ++ * This function assigns periodic Tx FIFO to an periodic EP ++ * in shared Tx FIFO mode ++ */ ++static uint32_t assign_tx_fifo(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t TxMsk = 1; ++ int i; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++i) { ++ if ((TxMsk & core_if->tx_msk) == 0) { ++ core_if->tx_msk |= TxMsk; ++ return i + 1; ++ } ++ TxMsk <<= 1; ++ } ++ return 0; ++} ++ ++/** ++ * This function assigns periodic Tx FIFO to an periodic EP ++ * in shared Tx FIFO mode ++ */ ++static uint32_t assign_perio_tx_fifo(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t PerTxMsk = 1; ++ int i; ++ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; ++i) { ++ if ((PerTxMsk & core_if->p_tx_msk) == 0) { ++ core_if->p_tx_msk |= PerTxMsk; ++ return i + 1; ++ } ++ PerTxMsk <<= 1; ++ } ++ return 0; ++} ++ ++/** ++ * This function releases periodic Tx FIFO ++ * in shared Tx FIFO mode ++ */ ++static void release_perio_tx_fifo(dwc_otg_core_if_t * core_if, ++ uint32_t fifo_num) ++{ ++ core_if->p_tx_msk = ++ (core_if->p_tx_msk & (1 << (fifo_num - 1))) ^ core_if->p_tx_msk; ++} ++ ++/** ++ * This function releases periodic Tx FIFO ++ * in shared Tx FIFO mode ++ */ ++static void release_tx_fifo(dwc_otg_core_if_t * core_if, uint32_t fifo_num) ++{ ++ core_if->tx_msk = ++ (core_if->tx_msk & (1 << (fifo_num - 1))) ^ core_if->tx_msk; ++} ++ ++/** ++ * This function is being called from gadget ++ * to enable PCD endpoint. ++ */ ++int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, ++ const uint8_t * ep_desc, void *usb_ep) ++{ ++ int num, dir; ++ dwc_otg_pcd_ep_t *ep = NULL; ++ const usb_endpoint_descriptor_t *desc; ++ dwc_irqflags_t flags; ++ fifosize_data_t dptxfsiz = {.d32 = 0 }; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; ++ int retval = 0; ++ int i, epcount; ++ ++ desc = (const usb_endpoint_descriptor_t *)ep_desc; ++ ++ if (!desc) { ++ pcd->ep0.priv = usb_ep; ++ ep = &pcd->ep0; ++ retval = -DWC_E_INVALID; ++ goto out; ++ } ++ ++ num = UE_GET_ADDR(desc->bEndpointAddress); ++ dir = UE_GET_DIR(desc->bEndpointAddress); ++ if (!desc->wMaxPacketSize) { ++ DWC_WARN("bad maxpacketsize\n"); ++ retval = -DWC_E_INVALID; ++ goto out; ++ } ++ ++ if (dir == UE_DIR_IN) { ++ epcount = pcd->core_if->dev_if->num_in_eps; ++ for (i = 0; i < epcount; i++) { ++ if (num == pcd->in_ep[i].dwc_ep.num) { ++ ep = &pcd->in_ep[i]; ++ break; ++ } ++ } ++ } else { ++ epcount = pcd->core_if->dev_if->num_out_eps; ++ for (i = 0; i < epcount; i++) { ++ if (num == pcd->out_ep[i].dwc_ep.num) { ++ ep = &pcd->out_ep[i]; ++ break; ++ } ++ } ++ } ++ ++ if (!ep) { ++ DWC_WARN("bad address\n"); ++ retval = -DWC_E_INVALID; ++ goto out; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ ep->desc = desc; ++ ep->priv = usb_ep; ++ ++ /* ++ * Activate the EP ++ */ ++ ep->stopped = 0; ++ ++ ep->dwc_ep.is_in = (dir == UE_DIR_IN); ++ ep->dwc_ep.maxpacket = UGETW(desc->wMaxPacketSize); ++ ++ ep->dwc_ep.type = desc->bmAttributes & UE_XFERTYPE; ++ ++ if (ep->dwc_ep.is_in) { ++ if (!GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ ep->dwc_ep.tx_fifo_num = 0; ++ ++ if (ep->dwc_ep.type == UE_ISOCHRONOUS) { ++ /* ++ * if ISOC EP then assign a Periodic Tx FIFO. ++ */ ++ ep->dwc_ep.tx_fifo_num = ++ assign_perio_tx_fifo(GET_CORE_IF(pcd)); ++ } ++ } else { ++ /* ++ * if Dedicated FIFOs mode is on then assign a Tx FIFO. ++ */ ++ ep->dwc_ep.tx_fifo_num = ++ assign_tx_fifo(GET_CORE_IF(pcd)); ++ } ++ ++ /* Calculating EP info controller base address */ ++ if (ep->dwc_ep.tx_fifo_num ++ && GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ gdfifocfg.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)-> ++ core_global_regs->gdfifocfg); ++ gdfifocfgbase.d32 = gdfifocfg.d32 >> 16; ++ dptxfsiz.d32 = ++ (DWC_READ_REG32 ++ (&GET_CORE_IF(pcd)->core_global_regs-> ++ dtxfsiz[ep->dwc_ep.tx_fifo_num - 1]) >> 16); ++ gdfifocfg.b.epinfobase = ++ gdfifocfgbase.d32 + dptxfsiz.d32; ++ if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) { ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)-> ++ core_global_regs->gdfifocfg, ++ gdfifocfg.d32); ++ } ++ } ++ } ++ /* Set initial data PID. */ ++ if (ep->dwc_ep.type == UE_BULK) { ++ ep->dwc_ep.data_pid_start = 0; ++ } ++ ++ /* Alloc DMA Descriptors */ ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++#ifndef DWC_UTE_PER_IO ++ if (ep->dwc_ep.type != UE_ISOCHRONOUS) { ++#endif ++ ep->dwc_ep.desc_addr = ++ dwc_otg_ep_alloc_desc_chain(&ep-> ++ dwc_ep.dma_desc_addr, ++ MAX_DMA_DESC_CNT); ++ if (!ep->dwc_ep.desc_addr) { ++ DWC_WARN("%s, can't allocate DMA descriptor\n", ++ __func__); ++ retval = -DWC_E_SHUTDOWN; ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ goto out; ++ } ++#ifndef DWC_UTE_PER_IO ++ } else { ++ ep->dwc_ep.desc_addr = ++ dwc_otg_ep_alloc_desc_chain(&ep-> ++ dwc_ep.dma_desc_addr, ++ MAX_DMA_DESC_CNT/2); ++ ep->dwc_ep.desc_addr1 = ++ dwc_otg_ep_alloc_desc_chain(&ep-> ++ dwc_ep.dma_desc_addr1, ++ MAX_DMA_DESC_CNT/2); ++ if (!ep->dwc_ep.desc_addr || !ep->dwc_ep.desc_addr1) { ++ DWC_WARN("%s, can't allocate DMA descriptor\n", ++ __func__); ++ retval = -DWC_E_SHUTDOWN; ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ goto out; ++ } ++ /* Set initial data PID. */ ++ if (ep->dwc_ep.type == UE_ISOCHRONOUS) { ++ ep->dwc_ep.iso_desc_first = 0; ++ ep->dwc_ep.iso_desc_second = 0; ++ ep->dwc_ep.iso_transfer_started = 0; ++ } ++ } ++#endif ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "Activate %s: type=%d, mps=%d desc=%p\n", ++ (ep->dwc_ep.is_in ? "IN" : "OUT"), ++ ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc); ++#ifdef DWC_UTE_PER_IO ++ ep->dwc_ep.xiso_bInterval = 1 << (ep->desc->bInterval - 1); ++#endif ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ ep->dwc_ep.bInterval = 1 << (ep->desc->bInterval - 1); ++ ep->dwc_ep.frame_num = 0xFFFFFFFF; ++ } ++ ++ dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep); ++ ++#ifdef DWC_UTE_CFI ++ if (pcd->cfi->ops.ep_enable) { ++ pcd->cfi->ops.ep_enable(pcd->cfi, pcd, ep); ++ } ++#endif ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++out: ++ return retval; ++} ++ ++/** ++ * This function is being called from gadget ++ * to disable PCD endpoint. ++ */ ++int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ dwc_irqflags_t flags; ++ dwc_otg_dev_dma_desc_t *desc_addr; ++ dwc_dma_t dma_desc_addr; ++ gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ fifosize_data_t dptxfsiz = {.d32 = 0 }; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ ++ if (!ep || !ep->desc) { ++ DWC_DEBUGPL(DBG_PCD, "bad ep address\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ dwc_otg_request_nuke(ep); ++ ++ dwc_otg_ep_deactivate(GET_CORE_IF(pcd), &ep->dwc_ep); ++ if (pcd->core_if->core_params->dev_out_nak) { ++ DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[ep->dwc_ep.num]); ++ pcd->core_if->ep_xfer_info[ep->dwc_ep.num].state = 0; ++ } ++ ep->desc = NULL; ++ ep->stopped = 1; ++ ++ gdfifocfg.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg); ++ gdfifocfgbase.d32 = gdfifocfg.d32 >> 16; ++ ++ if (ep->dwc_ep.is_in) { ++ if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ /* Flush the Tx FIFO */ ++ dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), ++ ep->dwc_ep.tx_fifo_num); ++ } ++ release_perio_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); ++ release_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); ++ if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ /* Decreasing EPinfo Base Addr */ ++ dptxfsiz.d32 = ++ (DWC_READ_REG32 ++ (&GET_CORE_IF(pcd)-> ++ core_global_regs->dtxfsiz[ep->dwc_ep.tx_fifo_num-1]) >> 16); ++ gdfifocfg.b.epinfobase = gdfifocfgbase.d32 - dptxfsiz.d32; ++ if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) { ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg, ++ gdfifocfg.d32); ++ } ++ } ++ } ++ ++ /* Free DMA Descriptors */ ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ if (ep->dwc_ep.type != UE_ISOCHRONOUS) { ++ desc_addr = ep->dwc_ep.desc_addr; ++ dma_desc_addr = ep->dwc_ep.dma_desc_addr; ++ ++ /* Cannot call dma_free_coherent() with IRQs disabled */ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr, ++ MAX_DMA_DESC_CNT); ++ ++ } else { ++ desc_addr = ep->dwc_ep.desc_addr; ++ dma_desc_addr = ep->dwc_ep.dma_desc_addr; ++ ++ /* Cannot call dma_free_coherent() with IRQs disabled */ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr, ++ MAX_DMA_DESC_CNT/2); ++ desc_addr = ep->dwc_ep.desc_addr1; ++ dma_desc_addr = ep->dwc_ep.dma_desc_addr1; ++ dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr, ++ MAX_DMA_DESC_CNT/2); ++ } ++ goto out_unlocked; ++ } ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++out_unlocked: ++ DWC_DEBUGPL(DBG_PCD, "%d %s disabled\n", ep->dwc_ep.num, ++ ep->dwc_ep.is_in ? "IN" : "OUT"); ++ return 0; ++ ++} ++ ++/** ++ * This function initializes dma descriptor chain for ISOC transfers. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++void dwc_otg_pcd_start_iso_ddma(dwc_otg_core_if_t * core_if, dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ dwc_otg_pcd_request_t *req = NULL; ++ dwc_ep_t *dwcep = NULL; ++ uint32_t frame_num = 0; ++ int i = 0; ++ int j; ++ int sync_request = 4; ++ uint16_t nat; ++ depctl_data_t depctl; ++ ++ dwcep = &ep->dwc_ep; ++ dma_desc = dwcep->desc_addr; ++ ++ nat = UGETW(ep->desc->wMaxPacketSize); ++ nat = (nat >> 11) & 0x03; ++ DWC_DEBUGPL(DBG_PCD, "nat=%u binterval =%02x\n",nat, dwcep->bInterval); ++ DWC_DEBUGPL(DBG_PCD, "frame_num = %d\n", dwcep->frame_num); ++ ++ /* Complete first three IN EP requests for the synchronization */ ++ if (dwcep->is_in) { ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ for (j = 0; j < sync_request; j++) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ DWC_PRINTF("ISOC 0x%p, req = NULL!\n", ep); ++ return; ++ } else { ++ /* Complete first request */ ++ req->actual = 0; ++ dwc_otg_request_done(ep, req, 0); ++ } ++ } ++ } else { ++ DWC_PRINTF("ISOC ep 0x%p, ep->queue empty!\n", ep); ++ return; ++ } ++ ++ frame_num = dwcep->frame_num + (sync_request -1)*dwcep->bInterval; ++ ++ DWC_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) { ++ i = i+1; ++ frame_num = (frame_num + dwcep->bInterval) & 0x3FFF; ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b_iso_in.bs = BS_HOST_BUSY; ++ dma_desc->buf = req->dma; ++ dma_desc->status.b_iso_in.txbytes = req->length; ++ dma_desc->status.b_iso_in.framenum = frame_num; ++ dma_desc->status.b_iso_in.txsts = 0; ++ dma_desc->status.b_iso_in.sp = (req->length % dwcep->maxpacket) ? 1 : 0; ++ dma_desc->status.b_iso_in.ioc = 1; ++ dma_desc->status.b_iso_in.pid = nat + 1; ++ dma_desc->status.b_iso_in.l = 0; ++ ++ if (req == DWC_CIRCLEQ_LAST(&ep->queue)) { ++ dma_desc->status.b_iso_in.l = 1; ++ } ++ dma_desc->status.b_iso_in.bs = BS_HOST_READY; ++ DWC_DEBUGPL(DBG_PCD, "ISO_DESC #%d %p status = %08x\n", i, dma_desc, dma_desc->status.d32); ++ if (i == MAX_DMA_DESC_CNT/2 - 1) { ++ dma_desc->status.b_iso_in.l = 1; ++ break; ++ } ++ dma_desc++; ++ } ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[dwcep->num]->diepdma, dwcep->dma_desc_addr); ++ DWC_DEBUGPL(DBG_PCD, "%d ISOC IN descs were programmed\n", i-1); ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->in_ep_regs[dwcep->num]->diepctl, 0, depctl.d32); ++ } else { ++ DWC_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) { ++ i = i+1; ++ frame_num = (frame_num + dwcep->bInterval) & 0x3FFF; ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b_iso_out.bs = BS_HOST_BUSY; ++ dma_desc->buf = req->dma; ++ dma_desc->status.b_iso_out.rxbytes = req->length; ++ dma_desc->status.b_iso_out.rxsts = 0; ++ dma_desc->status.b_iso_out.sp = (req->length % dwcep->maxpacket) ? 1 : 0; ++ dma_desc->status.b_iso_out.ioc = 1; ++ dma_desc->status.b_iso_out.pid = nat + 1; ++ dma_desc->status.b_iso_out.l = 0; ++ ++ if (req == DWC_CIRCLEQ_LAST(&ep->queue)) { ++ dma_desc->status.b_iso_out.l = 1; ++ } ++ dma_desc->status.b_iso_in.bs = BS_HOST_READY; ++ DWC_DEBUGPL(DBG_PCD, "ISO_DESC #%d %p status = %08x\n", i, dma_desc, dma_desc->status.d32); ++ if (i == MAX_DMA_DESC_CNT/2 - 1) { ++ dma_desc->status.b_iso_out.l = 1; ++ break; ++ } ++ dma_desc++; ++ } ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwcep->num]->doepdma, dwcep->dma_desc_addr); ++ DWC_DEBUGPL(DBG_PCD, "%d ISOC OUT descs were programmed\n", i-1); ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->out_ep_regs[dwcep->num]->doepctl, 0, depctl.d32); ++ } ++ dwcep->iso_desc_first = i; //vahrama - pay attention previous one was i-1 ++ dwcep->iso_transfer_started = 1; ++ dwcep->frame_num = frame_num; ++ dwcep->use_add_buf = 1; ++} ++/** ++ * Program next ISO request to the DMA chain ++ * ++ */ ++static void program_next_iso_request_ddma (dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req) ++{ ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ dwc_dma_t dma_desc_addr; ++ uint32_t frame_num = 0; ++ uint32_t nat; ++ uint32_t index; ++ ++ DWC_DEBUGPL(DBG_PCD, "%s", __FUNCTION__); ++ ++ if (ep->dwc_ep.use_add_buf) { ++ index = ep->dwc_ep.iso_desc_second + 1; ++ } else { ++ index = ep->dwc_ep.iso_desc_first + 1; ++ } ++ ++ if (index > MAX_DMA_DESC_CNT/2) { ++ DWC_PRINTF("There are no free descs in the chain!\n"); ++ return; ++ } ++ ++ if (ep->dwc_ep.use_add_buf) { ++ dma_desc = &ep->dwc_ep.desc_addr1[ep->dwc_ep.iso_desc_second]; ++ dma_desc_addr = ep->dwc_ep.dma_desc_addr1; ++ ep->dwc_ep.iso_desc_second += 1; ++ } else { ++ dma_desc = &ep->dwc_ep.desc_addr[ep->dwc_ep.iso_desc_first]; ++ dma_desc_addr = ep->dwc_ep.dma_desc_addr; ++ ep->dwc_ep.iso_desc_first += 1; ++ } ++ nat = UGETW(ep->desc->wMaxPacketSize); ++ nat = (nat >> 11) & 0x03; ++ ++ frame_num = (ep->dwc_ep.frame_num + ep->dwc_ep.bInterval) & 0x3FFF; ++ if (ep->dwc_ep.is_in) { ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b_iso_in.bs = BS_HOST_BUSY; ++ dma_desc->buf = req->dma; ++ dma_desc->status.b_iso_in.txbytes = req->length; ++ dma_desc->status.b_iso_in.framenum = frame_num; ++ dma_desc->status.b_iso_in.txsts = 0; ++ dma_desc->status.b_iso_in.sp = (req->length % ep->dwc_ep.maxpacket) ? 1 : 0; ++ dma_desc->status.b_iso_in.ioc = 1; ++ dma_desc->status.b_iso_in.pid = nat + 1; ++ dma_desc->status.b_iso_in.l = 1; ++ ++ dma_desc->status.b_iso_in.bs = BS_HOST_READY; ++ ++ /* Clear L bit on the previous desc of the chain */ ++ if (index > 1) { ++ dma_desc--; ++ dma_desc->status.b_iso_in.l = 0; ++ } ++ } else { ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b_iso_out.bs = BS_HOST_BUSY; ++ dma_desc->buf = req->dma; ++ dma_desc->status.b_iso_out.rxbytes = req->length; ++ dma_desc->status.b_iso_out.rxsts = 0; ++ dma_desc->status.b_iso_out.sp = (req->length % ep->dwc_ep.maxpacket) ? 1 : 0; ++ dma_desc->status.b_iso_out.ioc = 1; ++ dma_desc->status.b_iso_out.pid = nat + 1; ++ dma_desc->status.b_iso_out.l = 1; ++ ++ dma_desc->status.b_iso_out.bs = BS_HOST_READY; ++ ++ /* Clear L bit on the previous desc of the chain */ ++ if (index > 1) { ++ dma_desc--; ++ dma_desc->status.b_iso_out.l = 0; ++ } ++ } ++ ep->dwc_ep.frame_num = frame_num; ++ ++} ++ ++/******************************************************************************/ ++#ifdef DWC_UTE_PER_IO ++ ++/** ++ * Free the request and its extended parts ++ * ++ */ ++void dwc_pcd_xiso_ereq_free(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req) ++{ ++ DWC_FREE(req->ext_req.per_io_frame_descs); ++ DWC_FREE(req); ++} ++ ++/** ++ * Start the next request in the endpoint's queue. ++ * ++ */ ++int dwc_otg_pcd_xiso_start_next_request(dwc_otg_pcd_t * pcd, ++ dwc_otg_pcd_ep_t * ep) ++{ ++ int i; ++ dwc_otg_pcd_request_t *req = NULL; ++ dwc_ep_t *dwcep = NULL; ++ struct dwc_iso_xreq_port *ereq = NULL; ++ struct dwc_iso_pkt_desc_port *ddesc_iso; ++ uint16_t nat; ++ depctl_data_t diepctl; ++ ++ dwcep = &ep->dwc_ep; ++ ++ if (dwcep->xiso_active_xfers > 0) ++ return 0; ++ ++ nat = UGETW(ep->desc->wMaxPacketSize); ++ nat = (nat >> 11) & 0x03; ++ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ ereq = &req->ext_req; ++ ep->stopped = 0; ++ ++ /* Get the frame number */ ++ dwcep->xiso_frame_num = ++ dwc_otg_get_frame_number(GET_CORE_IF(pcd)); ++ DWC_DEBUG("FRM_NUM=%d", dwcep->xiso_frame_num); ++ ++ ddesc_iso = ereq->per_io_frame_descs; ++ ++ if (dwcep->is_in) { ++ /* Setup DMA Descriptor chain for IN Isoc request */ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ //if ((i % (nat + 1)) == 0) ++ if (i > 0) ++ dwcep->xiso_frame_num = ++ (dwcep->xiso_bInterval + ++ dwcep->xiso_frame_num) & 0x3FFF; ++ dwcep->desc_addr[i].buf = ++ req->dma + ddesc_iso[i].offset; ++ dwcep->desc_addr[i].status.b_iso_in.txbytes = ++ ddesc_iso[i].length; ++ dwcep->desc_addr[i].status.b_iso_in.framenum = ++ dwcep->xiso_frame_num; ++ dwcep->desc_addr[i].status.b_iso_in.bs = ++ BS_HOST_READY; ++ dwcep->desc_addr[i].status.b_iso_in.txsts = 0; ++ dwcep->desc_addr[i].status.b_iso_in.sp = ++ (ddesc_iso[i].length % ++ dwcep->maxpacket) ? 1 : 0; ++ dwcep->desc_addr[i].status.b_iso_in.ioc = 0; ++ dwcep->desc_addr[i].status.b_iso_in.pid = nat + 1; ++ dwcep->desc_addr[i].status.b_iso_in.l = 0; ++ ++ /* Process the last descriptor */ ++ if (i == ereq->pio_pkt_count - 1) { ++ dwcep->desc_addr[i].status.b_iso_in.ioc = 1; ++ dwcep->desc_addr[i].status.b_iso_in.l = 1; ++ } ++ } ++ ++ /* Setup and start the transfer for this endpoint */ ++ dwcep->xiso_active_xfers++; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ in_ep_regs[dwcep->num]->diepdma, ++ dwcep->dma_desc_addr); ++ diepctl.d32 = 0; ++ diepctl.b.epena = 1; ++ diepctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ in_ep_regs[dwcep->num]->diepctl, 0, ++ diepctl.d32); ++ } else { ++ /* Setup DMA Descriptor chain for OUT Isoc request */ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ //if ((i % (nat + 1)) == 0) ++ dwcep->xiso_frame_num = (dwcep->xiso_bInterval + ++ dwcep->xiso_frame_num) & 0x3FFF; ++ dwcep->desc_addr[i].buf = ++ req->dma + ddesc_iso[i].offset; ++ dwcep->desc_addr[i].status.b_iso_out.rxbytes = ++ ddesc_iso[i].length; ++ dwcep->desc_addr[i].status.b_iso_out.framenum = ++ dwcep->xiso_frame_num; ++ dwcep->desc_addr[i].status.b_iso_out.bs = ++ BS_HOST_READY; ++ dwcep->desc_addr[i].status.b_iso_out.rxsts = 0; ++ dwcep->desc_addr[i].status.b_iso_out.sp = ++ (ddesc_iso[i].length % ++ dwcep->maxpacket) ? 1 : 0; ++ dwcep->desc_addr[i].status.b_iso_out.ioc = 0; ++ dwcep->desc_addr[i].status.b_iso_out.pid = nat + 1; ++ dwcep->desc_addr[i].status.b_iso_out.l = 0; ++ ++ /* Process the last descriptor */ ++ if (i == ereq->pio_pkt_count - 1) { ++ dwcep->desc_addr[i].status.b_iso_out.ioc = 1; ++ dwcep->desc_addr[i].status.b_iso_out.l = 1; ++ } ++ } ++ ++ /* Setup and start the transfer for this endpoint */ ++ dwcep->xiso_active_xfers++; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->out_ep_regs[dwcep->num]-> ++ doepdma, dwcep->dma_desc_addr); ++ diepctl.d32 = 0; ++ diepctl.b.epena = 1; ++ diepctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->out_ep_regs[dwcep->num]-> ++ doepctl, 0, diepctl.d32); ++ } ++ ++ } else { ++ ep->stopped = 1; ++ } ++ ++ return 0; ++} ++ ++/** ++ * - Remove the request from the queue ++ */ ++void complete_xiso_ep(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_pcd_request_t *req = NULL; ++ struct dwc_iso_xreq_port *ereq = NULL; ++ struct dwc_iso_pkt_desc_port *ddesc_iso = NULL; ++ dwc_ep_t *dwcep = NULL; ++ int i; ++ ++ //DWC_DEBUG(); ++ dwcep = &ep->dwc_ep; ++ ++ /* Get the first pending request from the queue */ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); ++ return; ++ } ++ dwcep->xiso_active_xfers--; ++ dwcep->xiso_queued_xfers--; ++ /* Remove this request from the queue */ ++ DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry); ++ } else { ++ DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); ++ return; ++ } ++ ++ ep->stopped = 1; ++ ereq = &req->ext_req; ++ ddesc_iso = ereq->per_io_frame_descs; ++ ++ if (dwcep->xiso_active_xfers < 0) { ++ DWC_WARN("EP#%d (xiso_active_xfers=%d)", dwcep->num, ++ dwcep->xiso_active_xfers); ++ } ++ ++ /* Fill the Isoc descs of portable extended req from dma descriptors */ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ if (dwcep->is_in) { /* IN endpoints */ ++ ddesc_iso[i].actual_length = ddesc_iso[i].length - ++ dwcep->desc_addr[i].status.b_iso_in.txbytes; ++ ddesc_iso[i].status = ++ dwcep->desc_addr[i].status.b_iso_in.txsts; ++ } else { /* OUT endpoints */ ++ ddesc_iso[i].actual_length = ddesc_iso[i].length - ++ dwcep->desc_addr[i].status.b_iso_out.rxbytes; ++ ddesc_iso[i].status = ++ dwcep->desc_addr[i].status.b_iso_out.rxsts; ++ } ++ } ++ ++ DWC_SPINUNLOCK(ep->pcd->lock); ++ ++ /* Call the completion function in the non-portable logic */ ++ ep->pcd->fops->xisoc_complete(ep->pcd, ep->priv, req->priv, 0, ++ &req->ext_req); ++ ++ DWC_SPINLOCK(ep->pcd->lock); ++ ++ /* Free the request - specific freeing needed for extended request object */ ++ dwc_pcd_xiso_ereq_free(ep, req); ++ ++ /* Start the next request */ ++ dwc_otg_pcd_xiso_start_next_request(ep->pcd, ep); ++ ++ return; ++} ++ ++/** ++ * Create and initialize the Isoc pkt descriptors of the extended request. ++ * ++ */ ++static int dwc_otg_pcd_xiso_create_pkt_descs(dwc_otg_pcd_request_t * req, ++ void *ereq_nonport, ++ int atomic_alloc) ++{ ++ struct dwc_iso_xreq_port *ereq = NULL; ++ struct dwc_iso_xreq_port *req_mapped = NULL; ++ struct dwc_iso_pkt_desc_port *ipds = NULL; /* To be created in this function */ ++ uint32_t pkt_count; ++ int i; ++ ++ ereq = &req->ext_req; ++ req_mapped = (struct dwc_iso_xreq_port *)ereq_nonport; ++ pkt_count = req_mapped->pio_pkt_count; ++ ++ /* Create the isoc descs */ ++ if (atomic_alloc) { ++ ipds = DWC_ALLOC_ATOMIC(sizeof(*ipds) * pkt_count); ++ } else { ++ ipds = DWC_ALLOC(sizeof(*ipds) * pkt_count); ++ } ++ ++ if (!ipds) { ++ DWC_ERROR("Failed to allocate isoc descriptors"); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ /* Initialize the extended request fields */ ++ ereq->per_io_frame_descs = ipds; ++ ereq->error_count = 0; ++ ereq->pio_alloc_pkt_count = pkt_count; ++ ereq->pio_pkt_count = pkt_count; ++ ereq->tr_sub_flags = req_mapped->tr_sub_flags; ++ ++ /* Init the Isoc descriptors */ ++ for (i = 0; i < pkt_count; i++) { ++ ipds[i].length = req_mapped->per_io_frame_descs[i].length; ++ ipds[i].offset = req_mapped->per_io_frame_descs[i].offset; ++ ipds[i].status = req_mapped->per_io_frame_descs[i].status; /* 0 */ ++ ipds[i].actual_length = ++ req_mapped->per_io_frame_descs[i].actual_length; ++ } ++ ++ return 0; ++} ++ ++static void prn_ext_request(struct dwc_iso_xreq_port *ereq) ++{ ++ struct dwc_iso_pkt_desc_port *xfd = NULL; ++ int i; ++ ++ DWC_DEBUG("per_io_frame_descs=%p", ereq->per_io_frame_descs); ++ DWC_DEBUG("tr_sub_flags=%d", ereq->tr_sub_flags); ++ DWC_DEBUG("error_count=%d", ereq->error_count); ++ DWC_DEBUG("pio_alloc_pkt_count=%d", ereq->pio_alloc_pkt_count); ++ DWC_DEBUG("pio_pkt_count=%d", ereq->pio_pkt_count); ++ DWC_DEBUG("res=%d", ereq->res); ++ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ xfd = &ereq->per_io_frame_descs[0]; ++ DWC_DEBUG("FD #%d", i); ++ ++ DWC_DEBUG("xfd->actual_length=%d", xfd->actual_length); ++ DWC_DEBUG("xfd->length=%d", xfd->length); ++ DWC_DEBUG("xfd->offset=%d", xfd->offset); ++ DWC_DEBUG("xfd->status=%d", xfd->status); ++ } ++} ++ ++/** ++ * ++ */ ++int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen, ++ int zero, void *req_handle, int atomic_alloc, ++ void *ereq_nonport) ++{ ++ dwc_otg_pcd_request_t *req = NULL; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_irqflags_t flags; ++ int res; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ /* We support this extension only for DDMA mode */ ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ++ if (!GET_CORE_IF(pcd)->dma_desc_enable) ++ return -DWC_E_INVALID; ++ ++ /* Create a dwc_otg_pcd_request_t object */ ++ if (atomic_alloc) { ++ req = DWC_ALLOC_ATOMIC(sizeof(*req)); ++ } else { ++ req = DWC_ALLOC(sizeof(*req)); ++ } ++ ++ if (!req) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ /* Create the Isoc descs for this request which shall be the exact match ++ * of the structure sent to us from the non-portable logic */ ++ res = ++ dwc_otg_pcd_xiso_create_pkt_descs(req, ereq_nonport, atomic_alloc); ++ if (res) { ++ DWC_WARN("Failed to init the Isoc descriptors"); ++ DWC_FREE(req); ++ return res; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry); ++ req->buf = buf; ++ req->dma = dma_buf; ++ req->length = buflen; ++ req->sent_zlp = zero; ++ req->priv = req_handle; ++ ++ //DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ep->dwc_ep.dma_addr = dma_buf; ++ ep->dwc_ep.start_xfer_buff = buf; ++ ep->dwc_ep.xfer_buff = buf; ++ ep->dwc_ep.xfer_len = 0; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = buflen; ++ ++ /* Add this request to the tail */ ++ DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); ++ ep->dwc_ep.xiso_queued_xfers++; ++ ++//DWC_DEBUG("CP_0"); ++//DWC_DEBUG("req->ext_req.tr_sub_flags=%d", req->ext_req.tr_sub_flags); ++//prn_ext_request((struct dwc_iso_xreq_port *) ereq_nonport); ++//prn_ext_request(&req->ext_req); ++ ++ //DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ /* If the req->status == ASAP then check if there is any active transfer ++ * for this endpoint. If no active transfers, then get the first entry ++ * from the queue and start that transfer ++ */ ++ if (req->ext_req.tr_sub_flags == DWC_EREQ_TF_ASAP) { ++ res = dwc_otg_pcd_xiso_start_next_request(pcd, ep); ++ if (res) { ++ DWC_WARN("Failed to start the next Isoc transfer"); ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ DWC_FREE(req); ++ return res; ++ } ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return 0; ++} ++ ++#endif ++/* END ifdef DWC_UTE_PER_IO ***************************************************/ ++int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen, ++ int zero, void *req_handle, int atomic_alloc) ++{ ++ dwc_irqflags_t flags; ++ dwc_otg_pcd_request_t *req; ++ dwc_otg_pcd_ep_t *ep; ++ uint32_t max_transfer; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (atomic_alloc) { ++ req = DWC_ALLOC_ATOMIC(sizeof(*req)); ++ } else { ++ req = DWC_ALLOC(sizeof(*req)); ++ } ++ ++ if (!req) { ++ return -DWC_E_NO_MEMORY; ++ } ++ DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry); ++ if (!GET_CORE_IF(pcd)->core_params->opt) { ++ if (ep->dwc_ep.num != 0) { ++ DWC_ERROR("queue req %p, len %d buf %p\n", ++ req_handle, buflen, buf); ++ } ++ } ++ ++ req->buf = buf; ++ req->dma = dma_buf; ++ req->length = buflen; ++ req->sent_zlp = zero; ++ req->priv = req_handle; ++ req->dw_align_buf = NULL; ++ if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable ++ && !GET_CORE_IF(pcd)->dma_desc_enable) ++ req->dw_align_buf = DWC_DMA_ALLOC(buflen, ++ &req->dw_align_buf_dma); ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ /* ++ * After adding request to the queue for IN ISOC wait for In Token Received ++ * when TX FIFO is empty interrupt and for OUT ISOC wait for OUT Token ++ * Received when EP is disabled interrupt to obtain starting microframe ++ * (odd/even) start transfer ++ */ ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ if (req != 0) { ++ depctl_data_t depctl = {.d32 = ++ DWC_READ_REG32(&pcd->core_if->dev_if-> ++ in_ep_regs[ep->dwc_ep.num]-> ++ diepctl) }; ++ ++pcd->request_pending; ++ ++ DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); ++ if (ep->dwc_ep.is_in) { ++ depctl.b.cnak = 1; ++ DWC_WRITE_REG32(&pcd->core_if->dev_if-> ++ in_ep_regs[ep->dwc_ep.num]-> ++ diepctl, depctl.d32); ++ } ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ if (ep->dwc_ep.iso_transfer_started) { ++ /* ++ * Add next request to the descriptor chain ++ * currently not in use by HW ++ */ ++ program_next_iso_request_ddma(ep, req); ++ } else if (!ep->dwc_ep.is_in) ++ /* For OUT start first request immediately after queue */ ++ dwc_otg_pcd_start_iso_ddma(GET_CORE_IF(pcd), ep); ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ } ++ return 0; ++ } ++ ++ /* ++ * For EP0 IN without premature status, zlp is required? ++ */ ++ if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) { ++ DWC_DEBUGPL(DBG_PCDV, "%d-OUT ZLP\n", ep->dwc_ep.num); ++ //_req->zero = 1; ++ } ++ ++ /* Start the transfer */ ++ if (DWC_CIRCLEQ_EMPTY(&ep->queue) && !ep->stopped) { ++ /* EP0 Transfer? */ ++ if (ep->dwc_ep.num == 0) { ++ switch (pcd->ep0state) { ++ case EP0_IN_DATA_PHASE: ++ DWC_DEBUGPL(DBG_PCD, ++ "%s ep0: EP0_IN_DATA_PHASE\n", ++ __func__); ++ break; ++ ++ case EP0_OUT_DATA_PHASE: ++ DWC_DEBUGPL(DBG_PCD, ++ "%s ep0: EP0_OUT_DATA_PHASE\n", ++ __func__); ++ if (pcd->request_config) { ++ /* Complete STATUS PHASE */ ++ ep->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_STATUS_PHASE; ++ } ++ break; ++ ++ case EP0_IN_STATUS_PHASE: ++ DWC_DEBUGPL(DBG_PCD, ++ "%s ep0: EP0_IN_STATUS_PHASE\n", ++ __func__); ++ break; ++ ++ default: ++ DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n", ++ pcd->ep0state); ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return -DWC_E_SHUTDOWN; ++ } ++ ++ ep->dwc_ep.dma_addr = dma_buf; ++ ep->dwc_ep.start_xfer_buff = buf; ++ ep->dwc_ep.xfer_buff = buf; ++ ep->dwc_ep.xfer_len = buflen; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; ++ ++ if (zero) { ++ if ((ep->dwc_ep.xfer_len % ++ ep->dwc_ep.maxpacket == 0) ++ && (ep->dwc_ep.xfer_len != 0)) { ++ ep->dwc_ep.sent_zlp = 1; ++ } ++ ++ } ++ ++ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), ++ &ep->dwc_ep); ++ } // non-ep0 endpoints ++ else { ++#ifdef DWC_UTE_CFI ++ if (ep->dwc_ep.buff_mode != BM_STANDARD) { ++ /* store the request length */ ++ ep->dwc_ep.cfi_req_len = buflen; ++ pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ++ ep, req); ++ } else { ++#endif ++ max_transfer = ++ GET_CORE_IF(ep->pcd)->core_params-> ++ max_transfer_size; ++ ++ /* Setup and start the Transfer */ ++ if (req->dw_align_buf) { ++ if (ep->dwc_ep.is_in) ++ dwc_memcpy(req->dw_align_buf, ++ buf, buflen); ++ ep->dwc_ep.dma_addr = ++ req->dw_align_buf_dma; ++ ep->dwc_ep.start_xfer_buff = ++ req->dw_align_buf; ++ ep->dwc_ep.xfer_buff = ++ req->dw_align_buf; ++ } else { ++ ep->dwc_ep.dma_addr = dma_buf; ++ ep->dwc_ep.start_xfer_buff = buf; ++ ep->dwc_ep.xfer_buff = buf; ++ } ++ ep->dwc_ep.xfer_len = 0; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = buflen; ++ ++ ep->dwc_ep.maxxfer = max_transfer; ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ uint32_t out_max_xfer = ++ DDMA_MAX_TRANSFER_SIZE - ++ (DDMA_MAX_TRANSFER_SIZE % 4); ++ if (ep->dwc_ep.is_in) { ++ if (ep->dwc_ep.maxxfer > ++ DDMA_MAX_TRANSFER_SIZE) { ++ ep->dwc_ep.maxxfer = ++ DDMA_MAX_TRANSFER_SIZE; ++ } ++ } else { ++ if (ep->dwc_ep.maxxfer > ++ out_max_xfer) { ++ ep->dwc_ep.maxxfer = ++ out_max_xfer; ++ } ++ } ++ } ++ if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) { ++ ep->dwc_ep.maxxfer -= ++ (ep->dwc_ep.maxxfer % ++ ep->dwc_ep.maxpacket); ++ } ++ ++ if (zero) { ++ if ((ep->dwc_ep.total_len % ++ ep->dwc_ep.maxpacket == 0) ++ && (ep->dwc_ep.total_len != 0)) { ++ ep->dwc_ep.sent_zlp = 1; ++ } ++ } ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ dwc_otg_ep_start_transfer(GET_CORE_IF(pcd), ++ &ep->dwc_ep); ++ } ++ } ++ ++ if (req != 0) { ++ ++pcd->request_pending; ++ DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); ++ if (ep->dwc_ep.is_in && ep->stopped ++ && !(GET_CORE_IF(pcd)->dma_enable)) { ++ /** @todo NGS Create a function for this. */ ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ diepmsk.b.intktxfemp = 1; ++ if (GET_CORE_IF(pcd)->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->dev_global_regs->diepeachintmsk ++ [ep->dwc_ep.num], 0, ++ diepmsk.d32); ++ } else { ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->dev_global_regs-> ++ diepmsk, 0, diepmsk.d32); ++ } ++ ++ } ++ } ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ return 0; ++} ++ ++int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle) ++{ ++ dwc_irqflags_t flags; ++ dwc_otg_pcd_request_t *req; ++ dwc_otg_pcd_ep_t *ep; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) { ++ DWC_WARN("bad argument\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ /* make sure it's actually queued on this endpoint */ ++ DWC_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) { ++ if (req->priv == (void *)req_handle) { ++ break; ++ } ++ } ++ ++ if (req->priv != (void *)req_handle) { ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return -DWC_E_INVALID; ++ } ++ ++ if (!DWC_CIRCLEQ_EMPTY_ENTRY(req, queue_entry)) { ++ if(( ep != &pcd->ep0)&&(!ep->dwc_ep.is_in)) { ++ ep->dwc_ep.xfer_buff =NULL; ++ } ++ dwc_otg_request_done(ep, req, -DWC_E_RESTART); ++ } else { ++ req = NULL; ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ return req ? 0 : -DWC_E_SHUTDOWN; ++ ++} ++ ++int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ dwc_irqflags_t flags; ++ int retval = 0; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ ++ if (!ep || (!ep->desc && ep != &pcd->ep0) || ++ (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) { ++ DWC_WARN("%s, bad ep\n", __func__); ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num, ++ ep->dwc_ep.is_in ? "IN" : "OUT"); ++ retval = -DWC_E_AGAIN; ++ } else if (value == 0) { ++ ep->dwc_ep.stall_clear_flag = 0; ++ dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep); ++ } else if (value == 1) { ++ stall: ++ if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) { ++ dtxfsts_data_t txstatus; ++ fifosize_data_t txfifosize; ++ ++ txfifosize.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)-> ++ core_global_regs->dtxfsiz[ep->dwc_ep. ++ tx_fifo_num]); ++ txstatus.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->in_ep_regs[ep->dwc_ep.num]-> ++ dtxfsts); ++ ++ if (txstatus.b.txfspcavail < txfifosize.b.depth) { ++ DWC_WARN("%s() Data In Tx Fifo\n", __func__); ++ retval = -DWC_E_AGAIN; ++ } else { ++ if (ep->dwc_ep.num == 0) { ++ pcd->ep0state = EP0_STALL; ++ } ++ ++ ep->stopped = 1; ++ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), ++ &ep->dwc_ep); ++ } ++ } else { ++ if (ep->dwc_ep.num == 0) { ++ pcd->ep0state = EP0_STALL; ++ } ++ ++ ep->stopped = 1; ++ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep); ++ } ++ } else if (value == 2) { ++ ep->dwc_ep.stall_clear_flag = 0; ++ } else if (value == 3) { ++ ep->dwc_ep.stall_clear_flag = 1; ++ goto stall; ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ return retval; ++} ++ ++/** ++ * This function initiates remote wakeup of the host from suspend state. ++ */ ++void dwc_otg_pcd_rem_wkup_from_suspend(dwc_otg_pcd_t * pcd, int set) ++{ ++ dctl_data_t dctl = { 0 }; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dsts_data_t dsts; ++ ++ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ if (!dsts.b.suspsts) { ++ DWC_WARN("Remote wakeup while is not in suspend state\n"); ++ } ++ /* Check if DEVICE_REMOTE_WAKEUP feature enabled */ ++ if (pcd->remote_wakeup_enable) { ++ if (set) { ++ ++ if (core_if->adp_enable) { ++ gpwrdn_data_t gpwrdn; ++ ++ dwc_otg_adp_probe_stop(core_if); ++ ++ /* Mask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ ++ /* Disable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Device mode. ++ */ ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ ++ dwc_otg_initiate_srp(core_if); ++ } ++ ++ dctl.b.rmtwkupsig = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, 0, dctl.d32); ++ DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n"); ++ ++ dwc_mdelay(2); ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, dctl.d32, 0); ++ DWC_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n"); ++ } ++ } else { ++ DWC_DEBUGPL(DBG_PCD, "Remote Wakeup is disabled\n"); ++ } ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++/** ++ * This function initiates remote wakeup of the host from L1 sleep state. ++ */ ++void dwc_otg_pcd_rem_wkup_from_sleep(dwc_otg_pcd_t * pcd, int set) ++{ ++ glpmcfg_data_t lpmcfg; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ ++ /* Check if we are in L1 state */ ++ if (!lpmcfg.b.prt_sleep_sts) { ++ DWC_DEBUGPL(DBG_PCD, "Device is not in sleep state\n"); ++ return; ++ } ++ ++ /* Check if host allows remote wakeup */ ++ if (!lpmcfg.b.rem_wkup_en) { ++ DWC_DEBUGPL(DBG_PCD, "Host does not allow remote wakeup\n"); ++ return; ++ } ++ ++ /* Check if Resume OK */ ++ if (!lpmcfg.b.sleep_state_resumeok) { ++ DWC_DEBUGPL(DBG_PCD, "Sleep state resume is not OK\n"); ++ return; ++ } ++ ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.en_utmi_sleep = 0; ++ lpmcfg.b.hird_thres &= (~(1 << 4)); ++ ++ /* Clear Enbl_L1Gating bit. */ ++ pcgcctl.b.enbl_sleep_gating = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,0); ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++ ++ if (set) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.b.rmtwkupsig = 1; ++ /* Set RmtWkUpSig bit to start remote wakup signaling. ++ * Hardware will automatically clear this bit. ++ */ ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ 0, dctl.d32); ++ DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n"); ++ } ++ ++} ++#endif ++ ++/** ++ * Performs remote wakeup. ++ */ ++void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_irqflags_t flags; ++ if (dwc_otg_is_device_mode(core_if)) { ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ if (core_if->lx_state == DWC_OTG_L1) { ++ dwc_otg_pcd_rem_wkup_from_sleep(pcd, set); ++ } else { ++#endif ++ dwc_otg_pcd_rem_wkup_from_suspend(pcd, set); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ } ++#endif ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ } ++ return; ++} ++ ++void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dctl_data_t dctl = { 0 }; ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ dctl.b.sftdiscon = 1; ++ DWC_PRINTF("Soft disconnect for %d useconds\n",no_of_usecs); ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ dwc_udelay(no_of_usecs); ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32,0); ++ ++ } else{ ++ DWC_PRINTF("NOT SUPPORTED IN HOST MODE\n"); ++ } ++ return; ++ ++} ++ ++int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd) ++{ ++ dsts_data_t dsts; ++ gotgctl_data_t gotgctl; ++ ++ /* ++ * This function starts the Protocol if no session is in progress. If ++ * a session is already in progress, but the device is suspended, ++ * remote wakeup signaling is started. ++ */ ++ ++ /* Check if valid session */ ++ gotgctl.d32 = ++ DWC_READ_REG32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl)); ++ if (gotgctl.b.bsesvld) { ++ /* Check if suspend state */ ++ dsts.d32 = ++ DWC_READ_REG32(& ++ (GET_CORE_IF(pcd)->dev_if-> ++ dev_global_regs->dsts)); ++ if (dsts.b.suspsts) { ++ dwc_otg_pcd_remote_wakeup(pcd, 1); ++ } ++ } else { ++ dwc_otg_pcd_initiate_srp(pcd); ++ } ++ ++ return 0; ++ ++} ++ ++void dwc_otg_pcd_pullup(dwc_otg_pcd_t *pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ depctl_data_t depctl; ++ ++ depctl.d32 = 0; ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[bulk_num]->diepctl); ++ ++ depctl.b.setd1pid = 0; ++ depctl.b.setd0pid = 1; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[bulk_num]->diepctl, depctl.d32); ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[3]->diepctl); ++} ++ ++/** ++ * Start the SRP timer to detect when the SRP does not complete within ++ * 6 seconds. ++ * ++ * @param pcd the pcd structure. ++ */ ++void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd) ++{ ++ dwc_irqflags_t flags; ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ dwc_otg_initiate_srp(GET_CORE_IF(pcd)); ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++} ++ ++int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd) ++{ ++ return dwc_otg_get_frame_number(GET_CORE_IF(pcd)); ++} ++ ++int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd) ++{ ++ return GET_CORE_IF(pcd)->core_params->lpm_enable; ++} ++ ++int dwc_otg_pcd_is_besl_enabled(dwc_otg_pcd_t * pcd) ++{ ++ return GET_CORE_IF(pcd)->core_params->besl_enable; ++} ++ ++int dwc_otg_pcd_get_param_baseline_besl(dwc_otg_pcd_t * pcd) ++{ ++ return GET_CORE_IF(pcd)->core_params->baseline_besl; ++} ++ ++int dwc_otg_pcd_get_param_deep_besl(dwc_otg_pcd_t * pcd) ++{ ++ return GET_CORE_IF(pcd)->core_params->deep_besl; ++} ++ ++uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd) ++{ ++ return pcd->b_hnp_enable; ++} ++ ++uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd) ++{ ++ return pcd->a_hnp_support; ++} ++ ++uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd) ++{ ++ return pcd->a_alt_hnp_support; ++} ++ ++int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd) ++{ ++ return pcd->remote_wakeup_enable; ++} ++ ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd.h +new file mode 100644 +index 0000000..54ced23 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd.h +@@ -0,0 +1,268 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $ ++ * $Revision: #49 $ ++ * $Date: 2013/05/16 $ ++ * $Change: 2231774 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_HOST_ONLY ++#if !defined(__DWC_PCD_H__) ++#define __DWC_PCD_H__ ++ ++#include "dwc_otg_os_dep.h" ++#include "usb.h" ++#include "dwc_otg_cil.h" ++#include "dwc_otg_pcd_if.h" ++struct cfiobject; ++ ++/** ++ * @file ++ * ++ * This file contains the structures, constants, and interfaces for ++ * the Perpherial Contoller Driver (PCD). ++ * ++ * The Peripheral Controller Driver (PCD) for Linux will implement the ++ * Gadget API, so that the existing Gadget drivers can be used. For ++ * the Mass Storage Function driver the File-backed USB Storage Gadget ++ * (FBS) driver will be used. The FBS driver supports the ++ * Control-Bulk (CB), Control-Bulk-Interrupt (CBI), and Bulk-Only ++ * transports. ++ * ++ */ ++ ++/** Invalid DMA Address */ ++#define DWC_DMA_ADDR_INVALID (~(dwc_dma_t)0) ++ ++/** Max Transfer size for any EP */ ++#define DDMA_MAX_TRANSFER_SIZE 65535 ++ ++/** ++ * Get the pointer to the core_if from the pcd pointer. ++ */ ++#define GET_CORE_IF( _pcd ) (_pcd->core_if) ++ ++/** ++ * States of EP0. ++ */ ++typedef enum ep0_state { ++ EP0_DISCONNECT, /* no host */ ++ EP0_IDLE, ++ EP0_IN_DATA_PHASE, ++ EP0_OUT_DATA_PHASE, ++ EP0_IN_STATUS_PHASE, ++ EP0_OUT_STATUS_PHASE, ++ EP0_STALL, ++} ep0state_e; ++ ++/** Fordward declaration.*/ ++struct dwc_otg_pcd; ++ ++/** DWC_otg iso request structure. ++ * ++ */ ++typedef struct usb_iso_request dwc_otg_pcd_iso_request_t; ++ ++#ifdef DWC_UTE_PER_IO ++ ++/** ++ * This shall be the exact analogy of the same type structure defined in the ++ * usb_gadget.h. Each descriptor contains ++ */ ++struct dwc_iso_pkt_desc_port { ++ uint32_t offset; ++ uint32_t length; /* expected length */ ++ uint32_t actual_length; ++ uint32_t status; ++}; ++ ++struct dwc_iso_xreq_port { ++ /** transfer/submission flag */ ++ uint32_t tr_sub_flags; ++ /** Start the request ASAP */ ++#define DWC_EREQ_TF_ASAP 0x00000002 ++ /** Just enqueue the request w/o initiating a transfer */ ++#define DWC_EREQ_TF_ENQUEUE 0x00000004 ++ ++ /** ++ * count of ISO packets attached to this request - shall ++ * not exceed the pio_alloc_pkt_count ++ */ ++ uint32_t pio_pkt_count; ++ /** count of ISO packets allocated for this request */ ++ uint32_t pio_alloc_pkt_count; ++ /** number of ISO packet errors */ ++ uint32_t error_count; ++ /** reserved for future extension */ ++ uint32_t res; ++ /** Will be allocated and freed in the UTE gadget and based on the CFC value */ ++ struct dwc_iso_pkt_desc_port *per_io_frame_descs; ++}; ++#endif ++/** DWC_otg request structure. ++ * This structure is a list of requests. ++ */ ++typedef struct dwc_otg_pcd_request { ++ void *priv; ++ void *buf; ++ dwc_dma_t dma; ++ uint32_t length; ++ uint32_t actual; ++ unsigned sent_zlp:1; ++ /** ++ * Used instead of original buffer if ++ * it(physical address) is not dword-aligned. ++ **/ ++ uint8_t *dw_align_buf; ++ dwc_dma_t dw_align_buf_dma; ++ ++ DWC_CIRCLEQ_ENTRY(dwc_otg_pcd_request) queue_entry; ++#ifdef DWC_UTE_PER_IO ++ struct dwc_iso_xreq_port ext_req; ++ //void *priv_ereq_nport; /* */ ++#endif ++} dwc_otg_pcd_request_t; ++ ++DWC_CIRCLEQ_HEAD(req_list, dwc_otg_pcd_request); ++ ++/** PCD EP structure. ++ * This structure describes an EP, there is an array of EPs in the PCD ++ * structure. ++ */ ++typedef struct dwc_otg_pcd_ep { ++ /** USB EP Descriptor */ ++ const usb_endpoint_descriptor_t *desc; ++ ++ /** queue of dwc_otg_pcd_requests. */ ++ struct req_list queue; ++ unsigned stopped:1; ++ unsigned disabling:1; ++ unsigned dma:1; ++ unsigned queue_sof:1; ++ ++#ifdef DWC_EN_ISOC ++ /** ISOC req handle passed */ ++ void *iso_req_handle; ++#endif //_EN_ISOC_ ++ ++ /** DWC_otg ep data. */ ++ dwc_ep_t dwc_ep; ++ ++ /** Pointer to PCD */ ++ struct dwc_otg_pcd *pcd; ++ ++ void *priv; ++} dwc_otg_pcd_ep_t; ++ ++/** DWC_otg PCD Structure. ++ * This structure encapsulates the data for the dwc_otg PCD. ++ */ ++struct dwc_otg_pcd { ++ const struct dwc_otg_pcd_function_ops *fops; ++ /** The DWC otg device pointer */ ++ struct dwc_otg_device *otg_dev; ++ /** Core Interface */ ++ dwc_otg_core_if_t *core_if; ++ /** State of EP0 */ ++ ep0state_e ep0state; ++ /** EP0 Request is pending */ ++ unsigned ep0_pending:1; ++ /** Indicates when SET CONFIGURATION Request is in process */ ++ unsigned request_config:1; ++ /** The state of the Remote Wakeup Enable. */ ++ unsigned remote_wakeup_enable:1; ++ /** The state of the B-Device HNP Enable. */ ++ unsigned b_hnp_enable:1; ++ /** The state of A-Device HNP Support. */ ++ unsigned a_hnp_support:1; ++ /** The state of the A-Device Alt HNP support. */ ++ unsigned a_alt_hnp_support:1; ++ /** Count of pending Requests */ ++ unsigned request_pending; ++ ++ /** SETUP packet for EP0 ++ * This structure is allocated as a DMA buffer on PCD initialization ++ * with enough space for up to 3 setup packets. ++ */ ++ union { ++ usb_device_request_t req; ++ uint32_t d32[2]; ++ } *setup_pkt; ++ ++ dwc_dma_t setup_pkt_dma_handle; ++ ++ /* Additional buffer and flag for CTRL_WR premature case */ ++ uint8_t *backup_buf; ++ unsigned data_terminated; ++ ++ /** 2-byte dma buffer used to return status from GET_STATUS */ ++ uint16_t *status_buf; ++ dwc_dma_t status_buf_dma_handle; ++ ++ /** EP0 */ ++ dwc_otg_pcd_ep_t ep0; ++ ++ /** Array of IN EPs. */ ++ dwc_otg_pcd_ep_t in_ep[MAX_EPS_CHANNELS - 1]; ++ /** Array of OUT EPs. */ ++ dwc_otg_pcd_ep_t out_ep[MAX_EPS_CHANNELS - 1]; ++ /** number of valid EPs in the above array. */ ++// unsigned num_eps : 4; ++ dwc_spinlock_t *lock; ++ ++ /** Tasklet to defer starting of TEST mode transmissions until ++ * Status Phase has been completed. ++ */ ++ dwc_tasklet_t *test_mode_tasklet; ++ ++ /** Tasklet to delay starting of xfer in DMA mode */ ++ dwc_tasklet_t *start_xfer_tasklet; ++ ++ /** The test mode to enter when the tasklet is executed. */ ++ unsigned test_mode; ++ /** The cfi_api structure that implements most of the CFI API ++ * and OTG specific core configuration functionality ++ */ ++#ifdef DWC_UTE_CFI ++ struct cfiobject *cfi; ++#endif ++ ++}; ++ ++//FIXME this functions should be static, and this prototypes should be removed ++extern void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep); ++extern void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, ++ dwc_otg_pcd_request_t * req, int32_t status); ++ ++void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep, ++ void *req_handle); ++extern void dwc_otg_pcd_start_iso_ddma(dwc_otg_core_if_t * core_if, ++ dwc_otg_pcd_ep_t * ep); ++ ++extern void do_test_mode(void *data); ++#endif ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd_if.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd_if.h +new file mode 100644 +index 0000000..6cd75fa +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd_if.h +@@ -0,0 +1,368 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $ ++ * $Revision: #13 $ ++ * $Date: 2012/12/12 $ ++ * $Change: 2125019 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_HOST_ONLY ++ ++#if !defined(__DWC_PCD_IF_H__) ++#define __DWC_PCD_IF_H__ ++ ++//#include "dwc_os.h" ++#include "dwc_otg_core_if.h" ++ ++/** @file ++ * This file defines DWC_OTG PCD Core API. ++ */ ++ ++struct dwc_otg_pcd; ++typedef struct dwc_otg_pcd dwc_otg_pcd_t; ++ ++/** Maxpacket size for EP0 */ ++#define MAX_EP0_SIZE 64 ++/** Maxpacket size for any EP */ ++#define MAX_PACKET_SIZE 1024 ++ ++/** @name Function Driver Callbacks */ ++/** @{ */ ++ ++/** This function will be called whenever a previously queued request has ++ * completed. The status value will be set to -DWC_E_SHUTDOWN to indicated a ++ * failed or aborted transfer, or -DWC_E_RESTART to indicate the device was reset, ++ * or -DWC_E_TIMEOUT to indicate it timed out, or -DWC_E_INVALID to indicate invalid ++ * parameters. */ ++typedef int (*dwc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int32_t status, ++ uint32_t actual); ++/** ++ * This function will be called whenever a previousle queued ISOC request has ++ * completed. Count of ISOC packets could be read using dwc_otg_pcd_get_iso_packet_count ++ * function. ++ * The status of each ISOC packet could be read using dwc_otg_pcd_get_iso_packet_* ++ * functions. ++ */ ++typedef int (*dwc_isoc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int proc_buf_num); ++/** This function should handle any SETUP request that cannot be handled by the ++ * PCD Core. This includes most GET_DESCRIPTORs, SET_CONFIGS, Any ++ * class-specific requests, etc. The function must non-blocking. ++ * ++ * Returns 0 on success. ++ * Returns -DWC_E_NOT_SUPPORTED if the request is not supported. ++ * Returns -DWC_E_INVALID if the setup request had invalid parameters or bytes. ++ * Returns -DWC_E_SHUTDOWN on any other error. */ ++typedef int (*dwc_setup_cb_t) (dwc_otg_pcd_t * pcd, uint8_t * bytes); ++/** This is called whenever the device has been disconnected. The function ++ * driver should take appropriate action to clean up all pending requests in the ++ * PCD Core, remove all endpoints (except ep0), and initialize back to reset ++ * state. */ ++typedef int (*dwc_disconnect_cb_t) (dwc_otg_pcd_t * pcd); ++/** This function is called when device has been connected. */ ++typedef int (*dwc_connect_cb_t) (dwc_otg_pcd_t * pcd, int speed); ++/** This function is called when device has been suspended */ ++typedef int (*dwc_suspend_cb_t) (dwc_otg_pcd_t * pcd); ++/** This function is called when device has received LPM tokens, i.e. ++ * device has been sent to sleep state. */ ++typedef int (*dwc_sleep_cb_t) (dwc_otg_pcd_t * pcd); ++/** This function is called when device has been resumed ++ * from suspend(L2) or L1 sleep state. */ ++typedef int (*dwc_resume_cb_t) (dwc_otg_pcd_t * pcd); ++/** This function is called whenever hnp params has been changed. ++ * User can call get_b_hnp_enable, get_a_hnp_support, get_a_alt_hnp_support functions ++ * to get hnp parameters. */ ++typedef int (*dwc_hnp_params_changed_cb_t) (dwc_otg_pcd_t * pcd); ++/** This function is called whenever USB RESET is detected. */ ++typedef int (*dwc_reset_cb_t) (dwc_otg_pcd_t * pcd); ++ ++typedef int (*cfi_setup_cb_t) (dwc_otg_pcd_t * pcd, void *ctrl_req_bytes); ++ ++/** ++ * ++ * @param ep_handle Void pointer to the usb_ep structure ++ * @param ereq_port Pointer to the extended request structure created in the ++ * portable part. ++ */ ++typedef int (*xiso_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int32_t status, ++ void *ereq_port); ++/** Function Driver Ops Data Structure */ ++struct dwc_otg_pcd_function_ops { ++ dwc_connect_cb_t connect; ++ dwc_disconnect_cb_t disconnect; ++ dwc_setup_cb_t setup; ++ dwc_completion_cb_t complete; ++ dwc_isoc_completion_cb_t isoc_complete; ++ dwc_suspend_cb_t suspend; ++ dwc_sleep_cb_t sleep; ++ dwc_resume_cb_t resume; ++ dwc_reset_cb_t reset; ++ dwc_hnp_params_changed_cb_t hnp_changed; ++ cfi_setup_cb_t cfi_setup; ++#ifdef DWC_UTE_PER_IO ++ xiso_completion_cb_t xisoc_complete; ++#endif ++}; ++/** @} */ ++ ++/** @name Function Driver Functions */ ++/** @{ */ ++ ++/** Call this function to get pointer on dwc_otg_pcd_t, ++ * this pointer will be used for all PCD API functions. ++ * ++ * @param core_if The DWC_OTG Core ++ */ ++extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if); ++ ++/** Frees PCD allocated by dwc_otg_pcd_init ++ * ++ * @param pcd The PCD ++ */ ++extern void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd); ++ ++/** Call this to bind the function driver to the PCD Core. ++ * ++ * @param pcd Pointer on dwc_otg_pcd_t returned by dwc_otg_pcd_init function. ++ * @param fops The Function Driver Ops data structure containing pointers to all callbacks. ++ */ ++extern void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd, ++ const struct dwc_otg_pcd_function_ops *fops); ++ ++/** Enables an endpoint for use. This function enables an endpoint in ++ * the PCD. The endpoint is described by the ep_desc which has the ++ * same format as a USB ep descriptor. The ep_handle parameter is used to refer ++ * to the endpoint from other API functions and in callbacks. Normally this ++ * should be called after a SET_CONFIGURATION/SET_INTERFACE to configure the ++ * core for that interface. ++ * ++ * Returns -DWC_E_INVALID if invalid parameters were passed. ++ * Returns -DWC_E_SHUTDOWN if any other error ocurred. ++ * Returns 0 on success. ++ * ++ * @param pcd The PCD ++ * @param ep_desc Endpoint descriptor ++ * @param ep_handle Handle on endpoint, that will be used to identify endpoint. ++ */ ++extern int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, ++ const uint8_t * ep_desc, void *ep_handle); ++ ++/** Disable the endpoint referenced by ep_handle. ++ * ++ * Returns -DWC_E_INVALID if invalid parameters were passed. ++ * Returns -DWC_E_SHUTDOWN if any other error occurred. ++ * Returns 0 on success. */ ++extern int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle); ++ ++/** Queue a data transfer request on the endpoint referenced by ep_handle. ++ * After the transfer is completes, the complete callback will be called with ++ * the request status. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param buf The buffer for the data ++ * @param dma_buf The DMA buffer for the data ++ * @param buflen The length of the data transfer ++ * @param zero Specifies whether to send zero length last packet. ++ * @param req_handle Set this handle to any value to use to reference this ++ * request in the ep_dequeue function or from the complete callback ++ * @param atomic_alloc If driver need to perform atomic allocations ++ * for internal data structures. ++ * ++ * Returns -DWC_E_INVALID if invalid parameters were passed. ++ * Returns -DWC_E_SHUTDOWN if any other error ocurred. ++ * Returns 0 on success. */ ++extern int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf, dwc_dma_t dma_buf, ++ uint32_t buflen, int zero, void *req_handle, ++ int atomic_alloc); ++#ifdef DWC_UTE_PER_IO ++/** ++ * ++ * @param ereq_nonport Pointer to the extended request part of the ++ * usb_request structure defined in usb_gadget.h file. ++ */ ++extern int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf, dwc_dma_t dma_buf, ++ uint32_t buflen, int zero, ++ void *req_handle, int atomic_alloc, ++ void *ereq_nonport); ++ ++#endif ++ ++/** De-queue the specified data transfer that has not yet completed. ++ * ++ * Returns -DWC_E_INVALID if invalid parameters were passed. ++ * Returns -DWC_E_SHUTDOWN if any other error ocurred. ++ * Returns 0 on success. */ ++extern int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle); ++ ++/** Halt (STALL) an endpoint or clear it. ++ * ++ * Returns -DWC_E_INVALID if invalid parameters were passed. ++ * Returns -DWC_E_SHUTDOWN if any other error ocurred. ++ * Returns -DWC_E_AGAIN if the STALL cannot be sent and must be tried again later ++ * Returns 0 on success. */ ++extern int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value); ++ ++/** This function should be called on every hardware interrupt */ ++extern int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd); ++ ++/** This function returns current frame number */ ++extern int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd); ++ ++/** ++ * Start isochronous transfers on the endpoint referenced by ep_handle. ++ * For isochronous transfers duble buffering is used. ++ * After processing each of buffers comlete callback will be called with ++ * status for each transaction. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param buf0 The virtual address of first data buffer ++ * @param buf1 The virtual address of second data buffer ++ * @param dma0 The DMA address of first data buffer ++ * @param dma1 The DMA address of second data buffer ++ * @param sync_frame Data pattern frame number ++ * @param dp_frame Data size for pattern frame ++ * @param data_per_frame Data size for regular frame ++ * @param start_frame Frame number to start transfers, if -1 then start transfers ASAP. ++ * @param buf_proc_intrvl Interval of ISOC Buffer processing ++ * @param req_handle Handle of ISOC request ++ * @param atomic_alloc Specefies whether to perform atomic allocation for ++ * internal data structures. ++ * ++ * Returns -DWC_E_NO_MEMORY if there is no enough memory. ++ * Returns -DWC_E_INVALID if incorrect arguments are passed to the function. ++ * Returns -DW_E_SHUTDOWN for any other error. ++ * Returns 0 on success ++ */ ++extern int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf0, uint8_t * buf1, ++ dwc_dma_t dma0, dwc_dma_t dma1, ++ int sync_frame, int dp_frame, ++ int data_per_frame, int start_frame, ++ int buf_proc_intrvl, void *req_handle, ++ int atomic_alloc); ++ ++/** Stop ISOC transfers on endpoint referenced by ep_handle. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param req_handle Handle of ISOC request ++ * ++ * Returns -DWC_E_INVALID if incorrect arguments are passed to the function ++ * Returns 0 on success ++ */ ++int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle); ++ ++/** Get ISOC packet status. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param iso_req_handle Isochronoush request handle ++ * @param packet Number of packet ++ * @param status Out parameter for returning status ++ * @param actual Out parameter for returning actual length ++ * @param offset Out parameter for returning offset ++ * ++ */ ++extern void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, ++ void *ep_handle, ++ void *iso_req_handle, int packet, ++ int *status, int *actual, ++ int *offset); ++ ++/** Get ISOC packet count. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param iso_req_handle ++ */ ++extern int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, ++ void *ep_handle, ++ void *iso_req_handle); ++ ++/** This function starts the SRP Protocol if no session is in progress. If ++ * a session is already in progress, but the device is suspended, ++ * remote wakeup signaling is started. ++ */ ++extern int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd); ++ ++extern void dwc_otg_pcd_pullup(dwc_otg_pcd_t *pcd); ++ ++/** This function returns 1 if LPM support is enabled, and 0 otherwise. */ ++extern int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd); ++ ++/** This function returns 1 if LPM Errata support is enabled, and 0 otherwise. */ ++extern int dwc_otg_pcd_is_besl_enabled(dwc_otg_pcd_t * pcd); ++ ++/** This function returns baseline_besl module parametr. */ ++extern int dwc_otg_pcd_get_param_baseline_besl(dwc_otg_pcd_t * pcd); ++ ++/** This function returns deep_besl module parametr. */ ++extern int dwc_otg_pcd_get_param_deep_besl(dwc_otg_pcd_t * pcd); ++ ++/** This function returns 1 if remote wakeup is allowed and 0, otherwise. */ ++extern int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd); ++ ++/** Initiate SRP */ ++extern void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd); ++ ++/** Starts remote wakeup signaling. */ ++extern void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set); ++ ++/** Starts micorsecond soft disconnect. */ ++extern void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs); ++/** This function returns whether device is dualspeed.*/ ++extern uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd); ++ ++/** This function returns whether device is otg. */ ++extern uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd); ++ ++/** These functions allow to get hnp parameters */ ++extern uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd); ++extern uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd); ++extern uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd); ++ ++/** CFI specific Interface functions */ ++/** Allocate a cfi buffer */ ++extern uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, ++ dwc_dma_t * addr, size_t buflen, ++ int flags); ++ ++/******************************************************************************/ ++ ++/** @} */ ++ ++#endif /* __DWC_PCD_IF_H__ */ ++ ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd_intr.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd_intr.c +new file mode 100644 +index 0000000..b0f0ef1 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd_intr.c +@@ -0,0 +1,5427 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $ ++ * $Revision: #125 $ ++ * $Date: 2013/05/20 $ ++ * $Change: 2234037 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_HOST_ONLY ++ ++#include "dwc_otg_pcd.h" ++ ++#ifdef DWC_UTE_CFI ++#include "dwc_otg_cfi.h" ++#endif ++ ++//#include ++ ++#ifdef DWC_UTE_PER_IO ++extern void complete_xiso_ep(dwc_otg_pcd_ep_t * ep); ++#endif ++//#define PRINT_CFI_DMA_DESCS ++ ++#define DEBUG_EP0 ++ ++/* avoid null point */ ++uint8_t readpacket_buf[1024]; ++ ++/** ++ * This function updates OTG. ++ */ ++extern void hisi_switch_func(int otg); ++static void dwc_otg_pcd_update_otg(dwc_otg_pcd_t * pcd, const unsigned reset) ++{ ++ ++ if (reset) { ++ pcd->b_hnp_enable = 0; ++ pcd->a_hnp_support = 0; ++ pcd->a_alt_hnp_support = 0; ++ } ++ ++ if (pcd->fops->hnp_changed) { ++ pcd->fops->hnp_changed(pcd); ++ } ++} ++ ++/** @file ++ * This file contains the implementation of the PCD Interrupt handlers. ++ * ++ * The PCD handles the device interrupts. Many conditions can cause a ++ * device interrupt. When an interrupt occurs, the device interrupt ++ * service routine determines the cause of the interrupt and ++ * dispatches handling to the appropriate function. These interrupt ++ * handling functions are described below. ++ * All interrupt registers are processed from LSB to MSB. ++ */ ++ ++/** ++ * This function prints the ep0 state for debug purposes. ++ */ ++static inline void print_ep0_state(dwc_otg_pcd_t * pcd) ++{ ++#ifdef DEBUG ++ char str[40]; ++ ++ switch (pcd->ep0state) { ++ case EP0_DISCONNECT: ++ dwc_strcpy(str, "EP0_DISCONNECT"); ++ break; ++ case EP0_IDLE: ++ dwc_strcpy(str, "EP0_IDLE"); ++ break; ++ case EP0_IN_DATA_PHASE: ++ dwc_strcpy(str, "EP0_IN_DATA_PHASE"); ++ break; ++ case EP0_OUT_DATA_PHASE: ++ dwc_strcpy(str, "EP0_OUT_DATA_PHASE"); ++ break; ++ case EP0_IN_STATUS_PHASE: ++ dwc_strcpy(str, "EP0_IN_STATUS_PHASE"); ++ break; ++ case EP0_OUT_STATUS_PHASE: ++ dwc_strcpy(str, "EP0_OUT_STATUS_PHASE"); ++ break; ++ case EP0_STALL: ++ dwc_strcpy(str, "EP0_STALL"); ++ break; ++ default: ++ dwc_strcpy(str, "EP0_INVALID"); ++ } ++ ++ DWC_DEBUGPL(DBG_ANY, "%s(%d)\n", str, pcd->ep0state); ++#endif ++} ++ ++/** ++ * This function calculate the size of the payload in the memory ++ * for out endpoints and prints size for debug purposes(used in ++ * 2.93a DevOutNak feature). ++ */ ++static inline void print_memory_payload(dwc_otg_pcd_t * pcd, dwc_ep_t * ep) ++{ ++#ifdef DEBUG ++ deptsiz_data_t deptsiz_init = {.d32 = 0 }; ++ deptsiz_data_t deptsiz_updt = {.d32 = 0 }; ++ int pack_num; ++ unsigned payload; ++ ++ deptsiz_init.d32 = pcd->core_if->start_doeptsiz_val[ep->num]; ++ deptsiz_updt.d32 = ++ DWC_READ_REG32(&pcd->core_if->dev_if-> ++ out_ep_regs[ep->num]->doeptsiz); ++ /* Payload will be */ ++ payload = deptsiz_init.b.xfersize - deptsiz_updt.b.xfersize; ++ /* Packet count is decremented every time a packet ++ * is written to the RxFIFO not in to the external memory ++ * So, if payload == 0, then it means no packet was sent to ext memory*/ ++ pack_num = (!payload) ? 0 : (deptsiz_init.b.pktcnt - deptsiz_updt.b.pktcnt); ++ DWC_DEBUGPL(DBG_PCDV, ++ "Payload for EP%d-%s\n", ++ ep->num, (ep->is_in ? "IN" : "OUT")); ++ DWC_DEBUGPL(DBG_PCDV, ++ "Number of transfered bytes = 0x%08x\n", payload); ++ DWC_DEBUGPL(DBG_PCDV, ++ "Number of transfered packets = %d\n", pack_num); ++#endif ++} ++ ++ ++#ifdef DWC_UTE_CFI ++static inline void print_desc(struct dwc_otg_dma_desc *ddesc, ++ const uint8_t * epname, int descnum) ++{ ++ CFI_INFO ++ ("%s DMA_DESC(%d) buf=0x%08x bytes=0x%04x; sp=0x%x; l=0x%x; sts=0x%02x; bs=0x%02x\n", ++ epname, descnum, ddesc->buf, ddesc->status.b.bytes, ++ ddesc->status.b.sp, ddesc->status.b.l, ddesc->status.b.sts, ++ ddesc->status.b.bs); ++} ++#endif ++ ++/** ++ * This function returns pointer to in ep struct with number ep_num ++ */ ++static inline dwc_otg_pcd_ep_t *get_in_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num) ++{ ++ int i; ++ int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps; ++ if (ep_num == 0) { ++ return &pcd->ep0; ++ } else { ++ for (i = 0; i < num_in_eps; ++i) { ++ if (pcd->in_ep[i].dwc_ep.num == ep_num) ++ return &pcd->in_ep[i]; ++ } ++ return 0; ++ } ++} ++ ++/** ++ * This function returns pointer to out ep struct with number ep_num ++ */ ++static inline dwc_otg_pcd_ep_t *get_out_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num) ++{ ++ int i; ++ int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps; ++ if (ep_num == 0) { ++ return &pcd->ep0; ++ } else { ++ for (i = 0; i < num_out_eps; ++i) { ++ if (pcd->out_ep[i].dwc_ep.num == ep_num) ++ return &pcd->out_ep[i]; ++ } ++ return 0; ++ } ++} ++ ++/** ++ * This functions gets a pointer to an EP from the wIndex address ++ * value of the control request. ++ */ ++dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ uint32_t ep_num = UE_GET_ADDR(wIndex); ++ ++ if (ep_num == 0) { ++ ep = &pcd->ep0; ++ } else if (UE_GET_DIR(wIndex) == UE_DIR_IN) { /* in ep */ ++ ep = &pcd->in_ep[ep_num - 1]; ++ } else { ++ ep = &pcd->out_ep[ep_num - 1]; ++ } ++ ++ return ep; ++} ++ ++/** ++ * This function checks the EP request queue, if the queue is not ++ * empty the next request is started. ++ */ ++void start_next_request(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_pcd_request_t *req = 0; ++ uint32_t max_transfer = ++ GET_CORE_IF(ep->pcd)->core_params->max_transfer_size; ++ ++#ifdef DWC_UTE_CFI ++ struct dwc_otg_pcd *pcd; ++ pcd = ep->pcd; ++#endif ++ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ ++#ifdef DWC_UTE_CFI ++ if (ep->dwc_ep.buff_mode != BM_STANDARD) { ++ ep->dwc_ep.cfi_req_len = req->length; ++ pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ep, req); ++ } else { ++#endif ++ /* Setup and start the Transfer */ ++ if (req->dw_align_buf) { ++ ep->dwc_ep.dma_addr = req->dw_align_buf_dma; ++ ep->dwc_ep.start_xfer_buff = req->dw_align_buf; ++ ep->dwc_ep.xfer_buff = req->dw_align_buf; ++ } else { ++ ep->dwc_ep.dma_addr = req->dma; ++ ep->dwc_ep.start_xfer_buff = req->buf; ++ ep->dwc_ep.xfer_buff = req->buf; ++ } ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = req->length; ++ ep->dwc_ep.xfer_len = 0; ++ ep->dwc_ep.xfer_count = 0; ++ ++ ep->dwc_ep.maxxfer = max_transfer; ++ if (GET_CORE_IF(ep->pcd)->dma_desc_enable) { ++ uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE ++ - (DDMA_MAX_TRANSFER_SIZE % 4); ++ if (ep->dwc_ep.is_in) { ++ if (ep->dwc_ep.maxxfer > ++ DDMA_MAX_TRANSFER_SIZE) { ++ ep->dwc_ep.maxxfer = ++ DDMA_MAX_TRANSFER_SIZE; ++ } ++ } else { ++ if (ep->dwc_ep.maxxfer > out_max_xfer) { ++ ep->dwc_ep.maxxfer = ++ out_max_xfer; ++ } ++ } ++ } ++ if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) { ++ ep->dwc_ep.maxxfer -= ++ (ep->dwc_ep.maxxfer % ep->dwc_ep.maxpacket); ++ } ++ if (req->sent_zlp) { ++ if ((ep->dwc_ep.total_len % ++ ep->dwc_ep.maxpacket == 0) ++ && (ep->dwc_ep.total_len != 0)) { ++ ep->dwc_ep.sent_zlp = 1; ++ } ++ ++ } ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep); ++ } else if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ diepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ intr_mask.b.nak = 1; ++ ++ if (GET_CORE_IF(ep->pcd)->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&GET_CORE_IF(ep->pcd)->dev_if->dev_global_regs-> ++ diepeachintmsk[ep->dwc_ep.num], intr_mask.d32, 0); ++ } else { ++ DWC_MODIFY_REG32(&GET_CORE_IF(ep->pcd)->dev_if->dev_global_regs->diepmsk, ++ intr_mask.d32, 0); ++ } ++ DWC_PRINTF("There are no more ISOC requests \n"); ++ ep->dwc_ep.frame_num = 0xFFFFFFFF; ++ } ++} ++ ++/** ++ * This function handles the SOF Interrupts. At this time the SOF ++ * Interrupt is disabled. ++ */ ++int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ gintsts_data_t gintsts; ++ ++ DWC_DEBUGPL(DBG_PCD, "SOF\n"); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.sofintr = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This function handles the Rx Status Queue Level Interrupt, which ++ * indicates that there is a least one packet in the Rx FIFO. The ++ * packets are moved from the FIFO to memory, where they will be ++ * processed when the Endpoint Interrupt Register indicates Transfer ++ * Complete or SETUP Phase Done. ++ * ++ * Repeat the following until the Rx Status Queue is empty: ++ * -# Read the Receive Status Pop Register (GRXSTSP) to get Packet ++ * info ++ * -# If Receive FIFO is empty then skip to step Clear the interrupt ++ * and exit ++ * -# If SETUP Packet call dwc_otg_read_setup_packet to copy the ++ * SETUP data to the buffer ++ * -# If OUT Data Packet call dwc_otg_read_packet to copy the data ++ * to the destination buffer ++ */ ++int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gintmsk_data_t gintmask = {.d32 = 0 }; ++ device_grxsts_data_t status; ++ dwc_otg_pcd_ep_t *ep; ++ gintsts_data_t gintsts; ++#ifdef DEBUG ++ static char *dpid_str[] = { "D0", "D2", "D1", "MDATA" }; ++#endif ++ ++ //DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd); ++ /* Disable the Rx Status Queue Level interrupt */ ++ gintmask.b.rxstsqlvl = 1; ++ DWC_MODIFY_REG32(&global_regs->gintmsk, gintmask.d32, 0); ++ ++ /* Get the Status from the top of the FIFO */ ++ status.d32 = DWC_READ_REG32(&global_regs->grxstsp); ++ ++ DWC_DEBUGPL(DBG_PCD, "EP:%d BCnt:%d DPID:%s " ++ "pktsts:%x Frame:%d(0x%0x)\n", ++ status.b.epnum, status.b.bcnt, ++ dpid_str[status.b.dpid], ++ status.b.pktsts, status.b.fn, status.b.fn); ++ /* Get pointer to EP structure */ ++ ep = get_out_ep(pcd, status.b.epnum); ++ ++ switch (status.b.pktsts) { ++ case DWC_DSTS_GOUT_NAK: ++ DWC_DEBUGPL(DBG_PCDV, "Global OUT NAK\n"); ++ break; ++ case DWC_STS_DATA_UPDT: ++ DWC_DEBUGPL(DBG_PCDV, "OUT Data Packet\n"); ++ if (status.b.bcnt && ep->dwc_ep.xfer_buff) { ++ /** @todo NGS Check for buffer overflow? */ ++ dwc_otg_read_packet(core_if, ++ ep->dwc_ep.xfer_buff, ++ status.b.bcnt); ++ ep->dwc_ep.xfer_count += status.b.bcnt; ++ ep->dwc_ep.xfer_buff += status.b.bcnt; ++ } ++ if (status.b.bcnt &&(status.b.bcnt<1024) ++ && !ep->dwc_ep.xfer_buff) { ++ dwc_otg_read_packet(core_if, ++ readpacket_buf, ++ status.b.bcnt); ++ ep->dwc_ep.xfer_count += status.b.bcnt; ++ } ++ break; ++ case DWC_STS_XFER_COMP: ++ DWC_DEBUGPL(DBG_PCDV, "OUT Complete\n"); ++ break; ++ case DWC_DSTS_SETUP_COMP: ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCDV, "Setup Complete\n"); ++#endif ++ break; ++ case DWC_DSTS_SETUP_UPDT: ++ dwc_otg_read_setup_packet(core_if, pcd->setup_pkt->d32); ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, ++ "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n", ++ pcd->setup_pkt->req.bmRequestType, ++ pcd->setup_pkt->req.bRequest, ++ UGETW(pcd->setup_pkt->req.wValue), ++ UGETW(pcd->setup_pkt->req.wIndex), ++ UGETW(pcd->setup_pkt->req.wLength)); ++#endif ++ ep->dwc_ep.xfer_count += status.b.bcnt; ++ break; ++ default: ++ DWC_DEBUGPL(DBG_PCDV, "Invalid Packet Status (0x%0x)\n", ++ status.b.pktsts); ++ break; ++ } ++ ++ /* Enable the Rx Status Queue Level interrupt */ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmask.d32); ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.rxstsqlvl = 1; ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ //DWC_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__); ++ return 1; ++} ++ ++/** ++ * This function examines the Device IN Token Learning Queue to ++ * determine the EP number of the last IN token received. This ++ * implementation is for the Mass Storage device where there are only ++ * 2 IN EPs (Control-IN and BULK-IN). ++ * ++ * The EP numbers for the first six IN Tokens are in DTKNQR1 and there ++ * are 8 EP Numbers in each of the other possible DTKNQ Registers. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * ++ */ ++static inline int get_ep_of_last_in_token(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_device_global_regs_t *dev_global_regs = ++ core_if->dev_if->dev_global_regs; ++ const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth; ++ /* Number of Token Queue Registers */ ++ const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8; ++ dtknq1_data_t dtknqr1; ++ uint32_t in_tkn_epnums[4]; ++ int ndx = 0; ++ int i = 0; ++ volatile uint32_t *addr = &dev_global_regs->dtknqr1; ++ int epnum = 0; ++ ++ //DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH); ++ ++ /* Read the DTKNQ Registers */ ++ for (i = 0; i < DTKNQ_REG_CNT; i++) { ++ in_tkn_epnums[i] = DWC_READ_REG32(addr); ++ DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1, ++ in_tkn_epnums[i]); ++ if (addr == &dev_global_regs->dvbusdis) { ++ addr = &dev_global_regs->dtknqr3_dthrctl; ++ } else { ++ ++addr; ++ } ++ ++ } ++ ++ /* Copy the DTKNQR1 data to the bit field. */ ++ dtknqr1.d32 = in_tkn_epnums[0]; ++ /* Get the EP numbers */ ++ in_tkn_epnums[0] = dtknqr1.b.epnums0_5; ++ ndx = dtknqr1.b.intknwptr - 1; ++ ++ //DWC_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx); ++ if (ndx == -1) { ++ /** @todo Find a simpler way to calculate the max ++ * queue position.*/ ++ int cnt = TOKEN_Q_DEPTH; ++ if (TOKEN_Q_DEPTH <= 6) { ++ cnt = TOKEN_Q_DEPTH - 1; ++ } else if (TOKEN_Q_DEPTH <= 14) { ++ cnt = TOKEN_Q_DEPTH - 7; ++ } else if (TOKEN_Q_DEPTH <= 22) { ++ cnt = TOKEN_Q_DEPTH - 15; ++ } else { ++ cnt = TOKEN_Q_DEPTH - 23; ++ } ++ epnum = (in_tkn_epnums[DTKNQ_REG_CNT - 1] >> (cnt * 4)) & 0xF; ++ } else { ++ if (ndx <= 5) { ++ epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF; ++ } else if (ndx <= 13) { ++ ndx -= 6; ++ epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF; ++ } else if (ndx <= 21) { ++ ndx -= 14; ++ epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF; ++ } else if (ndx <= 29) { ++ ndx -= 22; ++ epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF; ++ } ++ } ++ //DWC_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum); ++ return epnum; ++} ++ ++/** ++ * This interrupt occurs when the non-periodic Tx FIFO is half-empty. ++ * The active request is checked for the next packet to be loaded into ++ * the non-periodic Tx FIFO. ++ */ ++int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ dwc_otg_dev_in_ep_regs_t *ep_regs; ++ gnptxsts_data_t txstatus = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ ++ int epnum = 0; ++ dwc_otg_pcd_ep_t *ep = 0; ++ uint32_t len = 0; ++ int dwords; ++ ++ /* Get the epnum from the IN Token Learning Queue. */ ++ epnum = get_ep_of_last_in_token(core_if); ++ ep = get_in_ep(pcd, epnum); ++ ++ DWC_DEBUGPL(DBG_PCD, "NP TxFifo Empty: %d \n", epnum); ++ ++ ep_regs = core_if->dev_if->in_ep_regs[epnum]; ++ ++ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; ++ if (len > ep->dwc_ep.maxpacket) { ++ len = ep->dwc_ep.maxpacket; ++ } ++ dwords = (len + 3) / 4; ++ ++ /* While there is space in the queue and space in the FIFO and ++ * More data to tranfer, Write packets to the Tx FIFO */ ++ txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts); ++ DWC_DEBUGPL(DBG_PCDV, "b4 GNPTXSTS=0x%08x\n", txstatus.d32); ++ ++ while (txstatus.b.nptxqspcavail > 0 && ++ txstatus.b.nptxfspcavail > dwords && ++ ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len) { ++ /* Write the FIFO */ ++ dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0); ++ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; ++ ++ if (len > ep->dwc_ep.maxpacket) { ++ len = ep->dwc_ep.maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts); ++ DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", txstatus.d32); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxsts)); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.nptxfempty = 1; ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This function is called when dedicated Tx FIFO Empty interrupt occurs. ++ * The active request is checked for the next packet to be loaded into ++ * apropriate Tx FIFO. ++ */ ++static int32_t write_empty_tx_fifo(dwc_otg_pcd_t * pcd, uint32_t epnum) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dwc_otg_dev_in_ep_regs_t *ep_regs; ++ dtxfsts_data_t txstatus = {.d32 = 0 }; ++ dwc_otg_pcd_ep_t *ep = 0; ++ uint32_t len = 0; ++ int dwords; ++ ++ ep = get_in_ep(pcd, epnum); ++ ++ DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum); ++ ++ ep_regs = core_if->dev_if->in_ep_regs[epnum]; ++ ++ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; ++ ++ if (len > ep->dwc_ep.maxpacket) { ++ len = ep->dwc_ep.maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ ++ /* While there is space in the queue and space in the FIFO and ++ * More data to tranfer, Write packets to the Tx FIFO */ ++ txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32); ++ ++ while (txstatus.b.txfspcavail >= dwords && ++ ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len && ++ ep->dwc_ep.xfer_len != 0) { ++ /* Write the FIFO */ ++ dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0); ++ ++ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; ++ if (len > ep->dwc_ep.maxpacket) { ++ len = ep->dwc_ep.maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ txstatus.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum, ++ txstatus.d32); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts)); ++ ++ return 1; ++} ++ ++/** ++ * This function is called when the Device is disconnected. It stops ++ * any active requests and informs the Gadget driver of the ++ * disconnect. ++ */ ++void dwc_otg_pcd_stop(dwc_otg_pcd_t * pcd) ++{ ++ int i, num_in_eps, num_out_eps; ++ dwc_otg_pcd_ep_t *ep; ++ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_SPINLOCK(pcd->lock); ++ ++ num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps; ++ num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s() \n", __func__); ++ /* don't disconnect drivers more than once */ ++ if (pcd->ep0state == EP0_DISCONNECT) { ++ DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__); ++ DWC_SPINUNLOCK(pcd->lock); ++ return; ++ } ++ pcd->ep0state = EP0_DISCONNECT; ++ ++ /* Reset the OTG state. */ ++ dwc_otg_pcd_update_otg(pcd, 1); ++ ++ /* Disable the NP Tx Fifo Empty Interrupt. */ ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Flush the FIFOs */ ++ /**@todo NGS Flush Periodic FIFOs */ ++ dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), 0x10); ++ dwc_otg_flush_rx_fifo(GET_CORE_IF(pcd)); ++ ++ /* prevent new request submissions, kill any outstanding requests */ ++ ep = &pcd->ep0; ++ dwc_otg_request_nuke(ep); ++ /* prevent new request submissions, kill any outstanding requests */ ++ for (i = 0; i < num_in_eps; i++) { ++ dwc_otg_pcd_ep_t *ep = &pcd->in_ep[i]; ++ dwc_otg_request_nuke(ep); ++ } ++ /* prevent new request submissions, kill any outstanding requests */ ++ for (i = 0; i < num_out_eps; i++) { ++ dwc_otg_pcd_ep_t *ep = &pcd->out_ep[i]; ++ dwc_otg_request_nuke(ep); ++ } ++ ++ /* report disconnect; the driver is already quiesced */ ++ if (pcd->fops->disconnect) { ++ DWC_SPINUNLOCK(pcd->lock); ++ pcd->fops->disconnect(pcd); ++ DWC_SPINLOCK(pcd->lock); ++ } ++ DWC_SPINUNLOCK(pcd->lock); ++} ++ ++/** ++ * This interrupt indicates that ... ++ */ ++int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "i2cintr"); ++ intr_mask.b.i2cintr = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.i2cintr = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that ... ++ */ ++int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintsts_data_t gintsts; ++ ++ DWC_DEBUGPL(DBG_PCDV,"Early Suspend Detected\n"); ++ ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.erlysuspend = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ DWC_SPINUNLOCK(GET_CORE_IF(pcd)->lock); ++ cil_pcd_stop(GET_CORE_IF(pcd)); ++ DWC_SPINLOCK(GET_CORE_IF(pcd)->lock); ++ ++ return 1; ++} ++ ++/** ++ * This function configures EPO to receive SETUP packets. ++ * ++ * @todo NGS: Update the comments from the HW FS. ++ * ++ * -# Program the following fields in the endpoint specific registers ++ * for Control OUT EP 0, in order to receive a setup packet ++ * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back ++ * setup packets) ++ * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back ++ * to back setup packets) ++ * - In DMA mode, DOEPDMA0 Register with a memory address to ++ * store any setup packets received ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param pcd Programming view of the PCD. ++ */ ++static inline void ep0_out_start(dwc_otg_core_if_t * core_if, ++ dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ deptsiz0_data_t doeptsize0 = {.d32 = 0 }; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ depctl_data_t doepctl = {.d32 = 0 }; ++ ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, "%s() doepctl0=%0x\n", __func__, ++ DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl)); ++#endif ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl); ++ if (doepctl.b.epena) { ++ return; ++ } ++ } ++ ++ doeptsize0.b.supcnt = 3; ++ doeptsize0.b.pktcnt = 1; ++ doeptsize0.b.xfersize = 8 * 3; ++ ++ if (core_if->dma_enable) { ++ if (!core_if->dma_desc_enable) { ++ /** put here as for Hermes mode deptisz register should not be written */ ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz, ++ doeptsize0.d32); ++ ++ /** @todo dma needs to handle multiple setup packets (up to 3) */ ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma, ++ pcd->setup_pkt_dma_handle); ++ } else { ++ dev_if->setup_desc_index = ++ (dev_if->setup_desc_index + 1) & 1; ++ dma_desc = ++ dev_if->setup_desc_addr[dev_if->setup_desc_index]; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ dma_desc->status.b.sr = 0; ++ dma_desc->status.b.mtrf = 0; ++ } ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.bytes = pcd->ep0.dwc_ep.maxpacket; ++ dma_desc->buf = pcd->setup_pkt_dma_handle; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DOEPDMA0 Register write */ ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma, ++ dev_if->dma_setup_desc_addr ++ [dev_if->setup_desc_index]); ++ } ++ ++ } else { ++ /** put here as for Hermes mode deptisz register should not be written */ ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz, ++ doeptsize0.d32); ++ } ++ ++ /** DOEPCTL0 Register write cnak will be set after setup interrupt */ ++ doepctl.d32 = 0; ++ doepctl.b.epena = 1; ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) { ++ doepctl.b.cnak = 1; ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); ++ } else { ++ DWC_MODIFY_REG32(&dev_if->out_ep_regs[0]->doepctl, 0, doepctl.d32); ++ } ++ ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n", ++ DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl)); ++ DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n", ++ DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl)); ++#endif ++} ++ ++/** ++ * This interrupt occurs when a USB Reset is detected. When the USB ++ * Reset Interrupt occurs the device state is set to DEFAULT and the ++ * EP0 state is set to IDLE. ++ * -# Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1) ++ * -# Unmask the following interrupt bits ++ * - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint) ++ * - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint) ++ * - DOEPMSK.SETUP = 1 ++ * - DOEPMSK.XferCompl = 1 ++ * - DIEPMSK.XferCompl = 1 ++ * - DIEPMSK.TimeOut = 1 ++ * -# Program the following fields in the endpoint specific registers ++ * for Control OUT EP 0, in order to receive a setup packet ++ * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back ++ * setup packets) ++ * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back ++ * to back setup packets) ++ * - In DMA mode, DOEPDMA0 Register with a memory address to ++ * store any setup packets received ++ * At this point, all the required initialization, except for enabling ++ * the control 0 OUT endpoint is done, for receiving SETUP packets. ++ */ ++int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ depctl_data_t doepctl = {.d32 = 0 }; ++ depctl_data_t diepctl = {.d32 = 0 }; ++ daint_data_t daintmsk = {.d32 = 0 }; ++ doepmsk_data_t doepmsk = {.d32 = 0 }; ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ dcfg_data_t dcfg = {.d32 = 0 }; ++ grstctl_t resetctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ int i = 0; ++ gintsts_data_t gintsts; ++ pcgcctl_data_t power = {.d32 = 0 }; ++ ++ power.d32 = DWC_READ_REG32(core_if->pcgcctl); ++ if (power.b.stoppclk) { ++ power.d32 = 0; ++ power.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0); ++ ++ power.b.pwrclmp = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0); ++ ++ power.b.rstpdwnmodule = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0); ++ } ++ ++ core_if->lx_state = DWC_OTG_L0; ++ core_if->otg_sts = 0; ++ ++ ++#ifdef DWC_EN_ISOC ++ for (i = 1; i < 16; ++i) { ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ ep = get_in_ep(pcd, i); ++ if (ep != 0) { ++ dwc_ep = &ep->dwc_ep; ++ dwc_ep->next_frame = 0xffffffff; ++ } ++ } ++#endif /* DWC_EN_ISOC */ ++ ++ /* reset the HNP settings */ ++ dwc_otg_pcd_update_otg(pcd, 1); ++ ++ /* Clear the Remote Wakeup Signalling */ ++ dctl.b.rmtwkupsig = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); ++ ++ /* Set NAK for all OUT EPs */ ++ doepctl.b.snak = 1; ++ for (i = 0; i <= dev_if->num_out_eps; i++) { ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32); ++ } ++ ++ /* Flush the NP Tx FIFO */ ++ dwc_otg_flush_tx_fifo(core_if, 0x10); ++ /* Flush the Learning Queue */ ++ resetctl.b.intknqflsh = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); ++ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) { ++ core_if->start_predict = 0; ++ for (i = 0; i <= core_if->dev_if->num_in_eps; ++i) { ++ core_if->nextep_seq[i] = 0xff; // 0xff - EP not active ++ } ++ core_if->nextep_seq[0] = 0; ++ core_if->first_in_nextep_seq = 0; ++ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); ++ diepctl.b.nextep = 0; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); ++ ++ /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */ ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt = 2; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); ++ } ++ } ++ ++ if (core_if->multiproc_int_enable) { ++ daintmsk.b.inep0 = 1; ++ daintmsk.b.outep0 = 1; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, ++ daintmsk.d32); ++ ++ doepmsk.b.setup = 1; ++ doepmsk.b.xfercompl = 1; ++ doepmsk.b.ahberr = 1; ++ doepmsk.b.epdisabled = 1; ++ ++ if ((core_if->dma_desc_enable) || ++ (core_if->dma_enable ++ && core_if->snpsid >= OTG_CORE_REV_3_00a)) { ++ doepmsk.b.stsphsercvd = 1; ++ } ++ if (core_if->dma_desc_enable) ++ doepmsk.b.bna = 1; ++/* ++ doepmsk.b.babble = 1; ++ doepmsk.b.nyet = 1; ++ ++ if (core_if->dma_enable) { ++ doepmsk.b.nak = 1; ++ } ++*/ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->doepeachintmsk[0], ++ doepmsk.d32); ++ ++ diepmsk.b.xfercompl = 1; ++ diepmsk.b.timeout = 1; ++ diepmsk.b.epdisabled = 1; ++ diepmsk.b.ahberr = 1; ++ diepmsk.b.intknepmis = 1; ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) ++ diepmsk.b.intknepmis = 0; ++ ++/* if (core_if->dma_desc_enable) { ++ diepmsk.b.bna = 1; ++ } ++*/ ++/* ++ if (core_if->dma_enable) { ++ diepmsk.b.nak = 1; ++ } ++*/ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->diepeachintmsk[0], ++ diepmsk.d32); ++ } else { ++ daintmsk.b.inep0 = 1; ++ daintmsk.b.outep0 = 1; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, ++ daintmsk.d32); ++ ++ doepmsk.b.setup = 1; ++ doepmsk.b.xfercompl = 1; ++ doepmsk.b.ahberr = 1; ++ doepmsk.b.epdisabled = 1; ++ ++ if ((core_if->dma_desc_enable) || ++ (core_if->dma_enable ++ && core_if->snpsid >= OTG_CORE_REV_3_00a)) { ++ doepmsk.b.stsphsercvd = 1; ++ } ++ if (core_if->dma_desc_enable) ++ doepmsk.b.bna = 1; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32); ++ ++ diepmsk.b.xfercompl = 1; ++ diepmsk.b.timeout = 1; ++ diepmsk.b.epdisabled = 1; ++ diepmsk.b.ahberr = 1; ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) ++ diepmsk.b.intknepmis = 0; ++/* ++ if (core_if->dma_desc_enable) { ++ diepmsk.b.bna = 1; ++ } ++*/ ++ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32); ++ } ++ ++ /* Reset Device Address */ ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.devaddr = 0; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ /* setup EP0 to receive SETUP packets */ ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) ++ ep0_out_start(core_if, pcd); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.usbreset = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * Get the device speed from the device status register and convert it ++ * to USB speed constant. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static int get_device_speed(dwc_otg_core_if_t * core_if) ++{ ++ dsts_data_t dsts; ++ int speed = 0; ++ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ switch (dsts.b.enumspd) { ++ case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: ++ speed = USB_SPEED_HIGH; ++ break; ++ case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: ++ case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ: ++ speed = USB_SPEED_FULL; ++ break; ++ ++ case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ: ++ speed = USB_SPEED_LOW; ++ break; ++ } ++ ++ return speed; ++} ++ ++/** ++ * Read the device status register and set the device speed in the ++ * data structure. ++ * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate. ++ */ ++int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ gintsts_data_t gintsts; ++ gusbcfg_data_t gusbcfg; ++ dwc_otg_core_global_regs_t *global_regs = ++ GET_CORE_IF(pcd)->core_global_regs; ++ uint8_t utmi16b, utmi8b; ++ int speed; ++ dcfg_data_t dcfg; ++ ++ DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n"); ++ ++ /* WA for the case when SW gets SPEED ENUM without first USB RESET case ++ * due to USB RESET issued by the host earlier. Anyways USB Reset routine ++ * needs to be called to at least program EP 0 OUT - vahrama ++ */ ++ dcfg.d32 = DWC_READ_REG32(&pcd->core_if->dev_if->dev_global_regs->dcfg); ++ if (pcd->core_if->otg_ver && dcfg.b.devaddr) ++ dwc_otg_pcd_handle_usb_reset_intr(pcd); ++ ++ ++ if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) { ++ utmi16b = 6; //vahrama old value was 6; ++ utmi8b = 9; ++ } else { ++ utmi16b = 4; ++ utmi8b = 8; ++ } ++ dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep); ++ if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) { ++ ep0_out_start(GET_CORE_IF(pcd), pcd); ++ } ++ ++#ifdef DEBUG_EP0 ++ print_ep0_state(pcd); ++#endif ++ ++ if (pcd->ep0state == EP0_DISCONNECT) { ++ pcd->ep0state = EP0_IDLE; ++ } else if (pcd->ep0state == EP0_STALL) { ++ pcd->ep0state = EP0_IDLE; ++ } ++ ++ pcd->ep0state = EP0_IDLE; ++ ++ ep0->stopped = 0; ++ ++ speed = get_device_speed(GET_CORE_IF(pcd)); ++ pcd->fops->connect(pcd, speed); ++ ++ /* Set USB turnaround time based on device speed and PHY interface. */ ++ gusbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); ++ if (speed == USB_SPEED_HIGH) { ++ if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == ++ DWC_HWCFG2_HS_PHY_TYPE_ULPI) { ++ /* ULPI interface */ ++ gusbcfg.b.usbtrdtim = 9; ++ } ++ if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == ++ DWC_HWCFG2_HS_PHY_TYPE_UTMI) { ++ /* UTMI+ interface */ ++ if (GET_CORE_IF(pcd)->hwcfg4.b.utmi_phy_data_width == 0) { ++ gusbcfg.b.usbtrdtim = utmi8b; ++ } else if (GET_CORE_IF(pcd)->hwcfg4. ++ b.utmi_phy_data_width == 1) { ++ gusbcfg.b.usbtrdtim = utmi16b; ++ } else if (GET_CORE_IF(pcd)-> ++ core_params->phy_utmi_width == 8) { ++ gusbcfg.b.usbtrdtim = utmi8b; ++ } else { ++ gusbcfg.b.usbtrdtim = utmi16b; ++ } ++ } ++ if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == ++ DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) { ++ /* UTMI+ OR ULPI interface */ ++ if (gusbcfg.b.ulpi_utmi_sel == 1) { ++ /* ULPI interface */ ++ gusbcfg.b.usbtrdtim = 9; ++ } else { ++ /* UTMI+ interface */ ++ if (GET_CORE_IF(pcd)-> ++ core_params->phy_utmi_width == 16) { ++ gusbcfg.b.usbtrdtim = utmi16b; ++ } else { ++ gusbcfg.b.usbtrdtim = utmi8b; ++ } ++ } ++ } ++ } else { ++ /* Full or low speed */ ++ gusbcfg.b.usbtrdtim = 9; ++ } ++ DWC_WRITE_REG32(&global_regs->gusbcfg, gusbcfg.d32); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.enumdone = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that the ISO OUT Packet was dropped due to ++ * Rx FIFO full or Rx Status Queue Full. If this interrupt occurs ++ * read all the data from the Rx FIFO. ++ */ ++int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ ++ DWC_WARN("INTERRUPT Handler not implemented for %s\n", ++ "ISOC Out Dropped"); ++ ++ intr_mask.b.isooutdrop = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.isooutdrop = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates the end of the portion of the micro-frame ++ * for periodic transactions. If there is a periodic transaction for ++ * the next frame, load the packets into the EP periodic Tx FIFO. ++ */ ++int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "EOP"); ++ ++ intr_mask.b.eopframe = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.eopframe = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that EP of the packet on the top of the ++ * non-periodic Tx FIFO does not match EP of the IN Token received. ++ * ++ * The "Device IN Token Queue" Registers are read to determine the ++ * order the IN Tokens have been received. The non-periodic Tx FIFO ++ * is flushed, so it can be reloaded in the order seen in the IN Token ++ * Queue. ++ */ ++int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintsts_data_t gintsts; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dctl_data_t dctl; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) { ++ core_if->start_predict = 1; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if); ++ ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (!gintsts.b.ginnakeff) { ++ /* Disable EP Mismatch interrupt */ ++ intr_mask.d32 = 0; ++ intr_mask.b.epmismatch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32, 0); ++ /* Enable the Global IN NAK Effective Interrupt */ ++ intr_mask.d32 = 0; ++ intr_mask.b.ginnakeff = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32); ++ /* Set the global non-periodic IN NAK handshake */ ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ dctl.b.sgnpinnak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++ } else { ++ DWC_PRINTF("gintsts.b.ginnakeff = 1! dctl.b.sgnpinnak not set\n"); ++ } ++ /* Disabling of all EP's will be done in dwc_otg_pcd_handle_in_nak_effective() ++ * handler after Global IN NAK Effective interrupt will be asserted */ ++ } ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.epmismatch = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt is valid only in DMA mode. This interrupt indicates that the ++ * core has stopped fetching data for IN endpoints due to the unavailability of ++ * TxFIFO space or Request Queue space. This interrupt is used by the ++ * application for an endpoint mismatch algorithm. ++ * ++ * @param pcd The PCD ++ */ ++int32_t dwc_otg_pcd_handle_ep_fetsusp_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintsts_data_t gintsts; ++ gintmsk_data_t gintmsk_data; ++ dctl_data_t dctl; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if); ++ ++ /* Clear the global non-periodic IN NAK handshake */ ++ dctl.d32 = 0; ++ dctl.b.cgnpinnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ ++ /* Mask GINTSTS.FETSUSP interrupt */ ++ gintmsk_data.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ gintmsk_data.b.fetsusp = 0; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk_data.d32); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.fetsusp = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This funcion stalls EP0. ++ */ ++static inline void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val) ++{ ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++// usb_device_request_t *ctrl = &pcd->setup_pkt->req; ++// DWC_WARN("req %02x.%02x protocol STALL; err %d\n", ++// ctrl->bmRequestType, ctrl->bRequest, err_val); ++ ++ ep0->dwc_ep.is_in = 1; ++ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->dwc_ep); ++ ep0->dwc_ep.is_in = 0; ++ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->dwc_ep); ++ pcd->ep0.stopped = 1; ++ pcd->ep0state = EP0_IDLE; ++ ep0_out_start(GET_CORE_IF(pcd), pcd); ++} ++ ++/** ++ * This functions delegates the setup command to the gadget driver. ++ */ ++static inline void do_gadget_setup(dwc_otg_pcd_t * pcd, ++ usb_device_request_t * ctrl) ++{ ++ int ret = 0; ++ DWC_SPINUNLOCK(pcd->lock); ++ ret = pcd->fops->setup(pcd, (uint8_t *) ctrl); ++ DWC_SPINLOCK(pcd->lock); ++ if (ret < 0) { ++ ep0_do_stall(pcd, ret); ++ } ++ ++ /** @todo This is a g_file_storage gadget driver specific ++ * workaround: a DELAYED_STATUS result from the fsg_setup ++ * routine will result in the gadget queueing a EP0 IN status ++ * phase for a two-stage control transfer. Exactly the same as ++ * a SET_CONFIGURATION/SET_INTERFACE except that this is a class ++ * specific request. Need a generic way to know when the gadget ++ * driver will queue the status phase. Can we assume when we ++ * call the gadget driver setup() function that it will always ++ * queue and require the following flag? Need to look into ++ * this. ++ */ ++ ++ if (ret == 256 + 999) { ++ pcd->request_config = 1; ++ } ++} ++ ++#ifdef DWC_UTE_CFI ++/** ++ * This functions delegates the CFI setup commands to the gadget driver. ++ * This function will return a negative value to indicate a failure. ++ */ ++static inline int cfi_gadget_setup(dwc_otg_pcd_t * pcd, ++ struct cfi_usb_ctrlrequest *ctrl_req) ++{ ++ int ret = 0; ++ ++ if (pcd->fops && pcd->fops->cfi_setup) { ++ DWC_SPINUNLOCK(pcd->lock); ++ ret = pcd->fops->cfi_setup(pcd, ctrl_req); ++ DWC_SPINLOCK(pcd->lock); ++ if (ret < 0) { ++ ep0_do_stall(pcd, ret); ++ return ret; ++ } ++ } ++ ++ return ret; ++} ++#endif ++ ++/** ++ * This function starts the Zero-Length Packet for the IN status phase ++ * of a 2 stage control transfer. ++ */ ++static inline void do_setup_in_status_phase(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ if (pcd->ep0state == EP0_STALL) { ++ return; ++ } ++ ++ pcd->ep0state = EP0_IN_STATUS_PHASE; ++ ++ /* Prepare for more SETUP Packets */ ++ DWC_DEBUGPL(DBG_PCD, "EP0 IN ZLP\n"); ++ if ((GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) ++ && (pcd->core_if->dma_desc_enable) ++ && (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len)) { ++ DWC_DEBUGPL(DBG_PCDV, ++ "Data terminated wait next packet in out_desc_addr\n"); ++ pcd->backup_buf = phys_to_virt(ep0->dwc_ep.dma_addr); ++ pcd->data_terminated = 1; ++ } ++ ep0->dwc_ep.xfer_len = 0; ++ ep0->dwc_ep.xfer_count = 0; ++ ep0->dwc_ep.is_in = 1; ++ ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle; ++ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep); ++ ++ /* Prepare for more SETUP Packets */ ++ //ep0_out_start(GET_CORE_IF(pcd), pcd); ++} ++ ++/** ++ * This function starts the Zero-Length Packet for the OUT status phase ++ * of a 2 stage control transfer. ++ */ ++static inline void do_setup_out_status_phase(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ doepint_data_t doepint; ++ doepint.d32 = DWC_READ_REG32(&pcd->core_if->dev_if->out_ep_regs[0]->doepint); ++ if (pcd->ep0state == EP0_STALL) { ++ DWC_DEBUGPL(DBG_PCD, "EP0 STALLED\n"); ++ return; ++ } ++ pcd->ep0state = EP0_OUT_STATUS_PHASE; ++ ++ DWC_DEBUGPL(DBG_PCD, "EP0 OUT ZLP\n"); ++ ep0->dwc_ep.xfer_len = 0; ++ ep0->dwc_ep.xfer_count = 0; ++ ep0->dwc_ep.is_in = 0; ++ ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle; ++ /* If there is xfercomplete on EP0 OUT do not start OUT Status stage. ++ * xfercomplete means that ZLP was already received as EP0 OUT is enabled ++ * during IN Data stage ++ */ ++ if ((doepint.b.xfercompl == 1) && (pcd->core_if->snpsid >= OTG_CORE_REV_3_00a) ++ && (pcd->core_if->dma_enable == 1) && (pcd->core_if->dma_desc_enable == 0)) { ++ DWC_DEBUGPL(DBG_PCD, "Status stage already completed\n"); ++ return; ++ } ++ ++ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep); ++ ++ /* Prepare for more SETUP Packets */ ++ if (GET_CORE_IF(pcd)->dma_enable == 0) { ++ ep0_out_start(GET_CORE_IF(pcd), pcd); ++ } ++} ++ ++/** ++ * Clear the EP halt (STALL) and if pending requests start the ++ * transfer. ++ */ ++static inline void pcd_clear_halt(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep) ++{ ++ if (ep->dwc_ep.stall_clear_flag) { ++ /* Start Control Status Phase */ ++ do_setup_in_status_phase(pcd); ++ return; ++ } ++ ++ dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep); ++ ++ /* Reactive the EP */ ++ dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep); ++ if (ep->stopped) { ++ ep->stopped = 0; ++ /* If there is a request in the EP queue start it */ ++ ++ /** @todo FIXME: this causes an EP mismatch in DMA mode. ++ * epmismatch not yet implemented. */ ++ ++ /* ++ * Above fixme is solved by implmenting a tasklet to call the ++ * start_next_request(), outside of interrupt context at some ++ * time after the current time, after a clear-halt setup packet. ++ * Still need to implement ep mismatch in the future if a gadget ++ * ever uses more than one endpoint at once ++ */ ++ ep->queue_sof = 1; ++ DWC_TASK_SCHEDULE(pcd->start_xfer_tasklet); ++ } ++ /* Start Control Status Phase */ ++ do_setup_in_status_phase(pcd); ++} ++ ++/** ++ * This function is called when the SET_FEATURE TEST_MODE Setup packet ++ * is sent from the host. The Device Control register is written with ++ * the Test Mode bits set to the specified Test Mode. This is done as ++ * a tasklet so that the "Status" phase of the control transfer ++ * completes before transmitting the TEST packets. ++ * ++ * @todo This has not been tested since the tasklet struct was put ++ * into the PCD struct! ++ * ++ */ ++void do_test_mode(void *data) ++{ ++ dctl_data_t dctl; ++ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ int test_mode = pcd->test_mode; ++ ++// DWC_WARN("%s() has not been tested since being rewritten!\n", __func__); ++ ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ switch (test_mode) { ++ case 1: // TEST_J ++ dctl.b.tstctl = 1; ++ break; ++ ++ case 2: // TEST_K ++ dctl.b.tstctl = 2; ++ break; ++ ++ case 3: // TEST_SE0_NAK ++ dctl.b.tstctl = 3; ++ break; ++ ++ case 4: // TEST_PACKET ++ dctl.b.tstctl = 4; ++ break; ++ ++ case 5: // TEST_FORCE_ENABLE ++ dctl.b.tstctl = 5; ++ break; ++ case 7: ++ dwc_otg_set_hnpreq(core_if, 1); ++ } ++ DWC_PRINTF("test mode = %d\n",test_mode); ++ core_if->test_mode = test_mode; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++} ++ ++/** ++ * This function process the GET_STATUS Setup Commands. ++ */ ++static inline void do_get_status(dwc_otg_pcd_t * pcd) ++{ ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ uint16_t *status = pcd->status_buf; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, ++ "GET_STATUS %02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, ++ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), ++ UGETW(ctrl.wLength)); ++#endif ++ ++ switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { ++ case UT_DEVICE: ++ if (UGETW(ctrl.wIndex) == 0xF000) { /* OTG Status selector */ ++ DWC_PRINTF("wIndex - %d\n", UGETW(ctrl.wIndex)); ++ DWC_PRINTF("OTG VERSION - %d\n", core_if->otg_ver); ++ DWC_PRINTF("OTG CAP - %d, %d\n", ++ core_if->core_params->otg_cap, ++ DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE); ++ if (core_if->otg_ver == 1 ++ && core_if->core_params->otg_cap == ++ DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { ++ uint8_t *otgsts = (uint8_t *) pcd->status_buf; ++ *otgsts = (core_if->otg_sts & 0x1); ++ pcd->ep0_pending = 1; ++ ep0->dwc_ep.start_xfer_buff = ++ (uint8_t *) otgsts; ++ ep0->dwc_ep.xfer_buff = (uint8_t *) otgsts; ++ ep0->dwc_ep.dma_addr = ++ pcd->status_buf_dma_handle; ++ ep0->dwc_ep.xfer_len = 1; ++ ep0->dwc_ep.xfer_count = 0; ++ ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len; ++ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), ++ &ep0->dwc_ep); ++ return; ++ } else { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ break; ++ } else { ++ *status = 0x1; /* Self powered */ ++ *status |= pcd->remote_wakeup_enable << 1; ++ break; ++ } ++ case UT_INTERFACE: ++ *status = 0; ++ break; ++ ++ case UT_ENDPOINT: ++ ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex)); ++ if (ep == 0 || UGETW(ctrl.wLength) > 2) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ /** @todo check for EP stall */ ++ *status = ep->stopped; ++ break; ++ } ++ pcd->ep0_pending = 1; ++ ep0->dwc_ep.start_xfer_buff = (uint8_t *) status; ++ ep0->dwc_ep.xfer_buff = (uint8_t *) status; ++ ep0->dwc_ep.dma_addr = pcd->status_buf_dma_handle; ++ ep0->dwc_ep.xfer_len = 2; ++ ep0->dwc_ep.xfer_count = 0; ++ ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len; ++ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep); ++} ++ ++/** ++ * This function process the SET_FEATURE Setup Commands. ++ */ ++static inline void do_set_feature(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ dwc_otg_pcd_ep_t *ep = 0; ++ int32_t otg_cap_param = core_if->core_params->otg_cap; ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_PCD, "SET_FEATURE:%02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, ++ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), ++ UGETW(ctrl.wLength)); ++ DWC_DEBUGPL(DBG_PCD, "otg_cap=%d\n", otg_cap_param); ++ ++ switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { ++ case UT_DEVICE: ++ switch (UGETW(ctrl.wValue)) { ++ case UF_DEVICE_REMOTE_WAKEUP: ++ pcd->remote_wakeup_enable = 1; ++ break; ++ ++ case UF_TEST_MODE: ++ /* Setup the Test Mode tasklet to do the Test ++ * Packet generation after the SETUP Status ++ * phase has completed. */ ++ ++ /** @todo This has not been tested since the ++ * tasklet struct was put into the PCD ++ * struct! */ ++ pcd->test_mode = UGETW(ctrl.wIndex) >> 8; ++ DWC_TASK_SCHEDULE(pcd->test_mode_tasklet); ++ break; ++ ++ case UF_DEVICE_B_HNP_ENABLE: ++ DWC_DEBUGPL(DBG_PCDV, ++ "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n"); ++ ++ /* dev may initiate HNP */ ++ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { ++ gotgctl.b.devhnpen = 1; ++ if (core_if->otg_ver) { ++ DWC_MODIFY_REG32(&global_regs->gotgctl, 0, gotgctl.d32); ++ /* Ensure that USB Suspend interrupt is unmasked */ ++ gintmsk.b.usbsuspend = 1; ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); ++ } ++ else { ++ pcd->b_hnp_enable = 1; ++ dwc_otg_pcd_update_otg(pcd, 0); ++ DWC_DEBUGPL(DBG_PCD, "Request B HNP\n"); ++ /**@todo Is the gotgctl.devhnpen cleared ++ * by a USB Reset? */ ++ gotgctl.b.hnpreq = 1; ++ DWC_WRITE_REG32(&global_regs->gotgctl, gotgctl.d32); ++ } ++ } else { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ break; ++ ++ case UF_DEVICE_A_HNP_SUPPORT: ++ /* RH port supports HNP */ ++ DWC_DEBUGPL(DBG_PCDV, ++ "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n"); ++ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { ++ pcd->a_hnp_support = 1; ++ dwc_otg_pcd_update_otg(pcd, 0); ++ } else { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ break; ++ ++ case UF_DEVICE_A_ALT_HNP_SUPPORT: ++ /* other RH port does */ ++ DWC_DEBUGPL(DBG_PCDV, ++ "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n"); ++ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { ++ pcd->a_alt_hnp_support = 1; ++ dwc_otg_pcd_update_otg(pcd, 0); ++ } else { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ break; ++ ++ default: ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ ++ } ++ do_setup_in_status_phase(pcd); ++ break; ++ ++ case UT_INTERFACE: ++ do_gadget_setup(pcd, &ctrl); ++ break; ++ ++ case UT_ENDPOINT: ++ if (UGETW(ctrl.wValue) == UF_ENDPOINT_HALT) { ++ ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex)); ++ if (ep == 0) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ep->stopped = 1; ++ dwc_otg_ep_set_stall(core_if, &ep->dwc_ep); ++ } ++ do_setup_in_status_phase(pcd); ++ break; ++ } ++} ++ ++/** ++ * This function process the CLEAR_FEATURE Setup Commands. ++ */ ++static inline void do_clear_feature(dwc_otg_pcd_t * pcd) ++{ ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ dwc_otg_pcd_ep_t *ep = 0; ++ ++ DWC_DEBUGPL(DBG_PCD, ++ "CLEAR_FEATURE:%02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, ++ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), ++ UGETW(ctrl.wLength)); ++ ++ switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { ++ case UT_DEVICE: ++ switch (UGETW(ctrl.wValue)) { ++ case UF_DEVICE_REMOTE_WAKEUP: ++ pcd->remote_wakeup_enable = 0; ++ break; ++ ++ case UF_TEST_MODE: ++ /** @todo Add CLEAR_FEATURE for TEST modes. */ ++ break; ++ ++ default: ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ do_setup_in_status_phase(pcd); ++ break; ++ ++ case UT_ENDPOINT: ++ ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex)); ++ if (ep == 0) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ++ pcd_clear_halt(pcd, ep); ++ ++ break; ++ } ++} ++ ++/** ++ * This function process the SET_ADDRESS Setup Commands. ++ */ ++static inline void do_set_address(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ ++ if (ctrl.bmRequestType == UT_DEVICE) { ++ dcfg_data_t dcfg = {.d32 = 0 }; ++ ++#ifdef DEBUG_EP0 ++// DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue); ++#endif ++ dcfg.b.devaddr = UGETW(ctrl.wValue); ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32); ++ do_setup_in_status_phase(pcd); ++ } ++} ++ ++/** ++ * This function processes SETUP commands. In Linux, the USB Command ++ * processing is done in two places - the first being the PCD and the ++ * second in the Gadget Driver (for example, the File-Backed Storage ++ * Gadget Driver). ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ *
Command Driver Description
GET_STATUS PCD Command is processed as ++ * defined in chapter 9 of the USB 2.0 Specification chapter 9 ++ *
CLEAR_FEATURE PCD The Device and Endpoint ++ * requests are the ENDPOINT_HALT feature is procesed, all others the ++ * interface requests are ignored.
SET_FEATURE PCD The Device and Endpoint ++ * requests are processed by the PCD. Interface requests are passed ++ * to the Gadget Driver.
SET_ADDRESS PCD Program the DCFG reg, ++ * with device address received
GET_DESCRIPTOR Gadget Driver Return the ++ * requested descriptor
SET_DESCRIPTOR Gadget Driver Optional - ++ * not implemented by any of the existing Gadget Drivers.
SET_CONFIGURATION Gadget Driver Disable ++ * all EPs and enable EPs for new configuration.
GET_CONFIGURATION Gadget Driver Return ++ * the current configuration
SET_INTERFACE Gadget Driver Disable all ++ * EPs and enable EPs for new configuration.
GET_INTERFACE Gadget Driver Return the ++ * current interface.
SYNC_FRAME PCD Display debug ++ * message.
++ * ++ * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are ++ * processed by pcd_setup. Calling the Function Driver's setup function from ++ * pcd_setup processes the gadget SETUP commands. ++ */ ++static inline void pcd_setup(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ ++ deptsiz0_data_t doeptsize0 = {.d32 = 0 }; ++ ++#ifdef DWC_UTE_CFI ++ int retval = 0; ++ struct cfi_usb_ctrlrequest cfi_req; ++#endif ++ ++ doeptsize0.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doeptsiz); ++ ++ /** In BDMA more then 1 setup packet is not supported till 3.00a */ ++ if (core_if->dma_enable && core_if->dma_desc_enable == 0 ++ && (doeptsize0.b.supcnt < 2) ++ && (core_if->snpsid < OTG_CORE_REV_2_94a)) { ++ DWC_ERROR ++ ("\n\n----------- CANNOT handle > 1 setup packet in DMA mode\n\n"); ++ } ++ if ((core_if->snpsid >= OTG_CORE_REV_3_00a) ++ && (core_if->dma_enable == 1) && (core_if->dma_desc_enable == 0)) { ++ if (doeptsize0.b.supcnt == 3 && ep0->dwc_ep.stp_rollover == 0) { ++ DWC_ERROR(" !!! Setup packet count was not updated by the core\n"); ++ return; ++ } ++ ctrl = ++ (pcd->setup_pkt + ++ (3 - doeptsize0.b.supcnt - 1 + ++ ep0->dwc_ep.stp_rollover))->req; ++ } ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, ++ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), ++ UGETW(ctrl.wLength)); ++#endif ++ ++ /* Clean up the request queue */ ++ dwc_otg_request_nuke(ep0); ++ ep0->stopped = 0; ++ ++ if (ctrl.bmRequestType & UE_DIR_IN) { ++ ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_DATA_PHASE; ++ } else { ++ ep0->dwc_ep.is_in = 0; ++ pcd->ep0state = EP0_OUT_DATA_PHASE; ++ } ++ ++ if (UGETW(ctrl.wLength) == 0) { ++ ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_STATUS_PHASE; ++ } ++ ++ if (UT_GET_TYPE(ctrl.bmRequestType) != UT_STANDARD) { ++ ++#ifdef DWC_UTE_CFI ++ DWC_MEMCPY(&cfi_req, &ctrl, sizeof(usb_device_request_t)); ++ ++ //printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n", ++ ctrl.bRequestType, ctrl.bRequest); ++ if (UT_GET_TYPE(cfi_req.bRequestType) == UT_VENDOR) { ++ if (cfi_req.bRequest > 0xB0 && cfi_req.bRequest < 0xBF) { ++ retval = cfi_setup(pcd, &cfi_req); ++ if (retval < 0) { ++ ep0_do_stall(pcd, retval); ++ pcd->ep0_pending = 0; ++ return; ++ } ++ ++ /* if need gadget setup then call it and check the retval */ ++ if (pcd->cfi->need_gadget_att) { ++ retval = ++ cfi_gadget_setup(pcd, ++ &pcd-> ++ cfi->ctrl_req); ++ if (retval < 0) { ++ pcd->ep0_pending = 0; ++ return; ++ } ++ } ++ ++ if (pcd->cfi->need_status_in_complete) { ++ do_setup_in_status_phase(pcd); ++ } ++ return; ++ } ++ } ++#endif ++ ++ /* handle non-standard (class/vendor) requests in the gadget driver */ ++ do_gadget_setup(pcd, &ctrl); ++ return; ++ } ++ ++ /** @todo NGS: Handle bad setup packet? */ ++ ++/////////////////////////////////////////// ++//// --- Standard Request handling --- //// ++ ++ switch (ctrl.bRequest) { ++ case UR_GET_STATUS: ++ do_get_status(pcd); ++ break; ++ ++ case UR_CLEAR_FEATURE: ++ do_clear_feature(pcd); ++ break; ++ ++ case UR_SET_FEATURE: ++ do_set_feature(pcd); ++ break; ++ ++ case UR_SET_ADDRESS: ++ do_set_address(pcd); ++ break; ++ ++ case UR_SET_INTERFACE: ++ case UR_SET_CONFIG: ++// _pcd->request_config = 1; /* Configuration changed */ ++ do_gadget_setup(pcd, &ctrl); ++ break; ++ ++ case UR_SYNCH_FRAME: ++ do_gadget_setup(pcd, &ctrl); ++ break; ++ ++ default: ++ /* Call the Gadget Driver's setup functions */ ++ do_gadget_setup(pcd, &ctrl); ++ break; ++ } ++} ++ ++/** ++ * This function completes the ep0 control transfer. ++ */ ++static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dwc_otg_dev_in_ep_regs_t *in_ep_regs = ++ dev_if->in_ep_regs[ep->dwc_ep.num]; ++#ifdef DEBUG_EP0 ++ dwc_otg_dev_out_ep_regs_t *out_ep_regs = ++ dev_if->out_ep_regs[ep->dwc_ep.num]; ++#endif ++ deptsiz0_data_t deptsiz; ++ dev_dma_desc_sts_t desc_sts = {.d32 = 0 }; ++ dwc_otg_pcd_request_t *req; ++ int is_last = 0; ++ dwc_otg_pcd_t *pcd = ep->pcd; ++ ++#ifdef DWC_UTE_CFI ++ struct cfi_usb_ctrlrequest *ctrlreq; ++ int retval = -DWC_E_NOT_SUPPORTED; ++#endif ++ ++ if (pcd->ep0_pending && DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ if (ep->dwc_ep.is_in) { ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCDV, "Do setup OUT status phase\n"); ++#endif ++ do_setup_out_status_phase(pcd); ++ } else { ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCDV, "Do setup IN status phase\n"); ++#endif ++ ++#ifdef DWC_UTE_CFI ++ ctrlreq = &pcd->cfi->ctrl_req; ++ ++ if (UT_GET_TYPE(ctrlreq->bRequestType) == UT_VENDOR) { ++ if (ctrlreq->bRequest > 0xB0 ++ && ctrlreq->bRequest < 0xBF) { ++ ++ /* Return if the PCD failed to handle the request */ ++ if ((retval = ++ pcd->cfi->ops. ++ ctrl_write_complete(pcd->cfi, ++ pcd)) < 0) { ++ CFI_INFO ++ ("ERROR setting a new value in the PCD(%d)\n", ++ retval); ++ ep0_do_stall(pcd, retval); ++ pcd->ep0_pending = 0; ++ return 0; ++ } ++ ++ /* If the gadget needs to be notified on the request */ ++ if (pcd->cfi->need_gadget_att == 1) { ++ //retval = do_gadget_setup(pcd, &pcd->cfi->ctrl_req); ++ retval = ++ cfi_gadget_setup(pcd, ++ &pcd->cfi-> ++ ctrl_req); ++ ++ /* Return from the function if the gadget failed to process ++ * the request properly - this should never happen !!! ++ */ ++ if (retval < 0) { ++ CFI_INFO ++ ("ERROR setting a new value in the gadget(%d)\n", ++ retval); ++ pcd->ep0_pending = 0; ++ return 0; ++ } ++ } ++ ++ CFI_INFO("%s: RETVAL=%d\n", __func__, ++ retval); ++ /* If we hit here then the PCD and the gadget has properly ++ * handled the request - so send the ZLP IN to the host. ++ */ ++ /* @todo: MAS - decide whether we need to start the setup ++ * stage based on the need_setup value of the cfi object ++ */ ++ do_setup_in_status_phase(pcd); ++ pcd->ep0_pending = 0; ++ return 1; ++ } ++ } ++#endif ++ ++ do_setup_in_status_phase(pcd); ++ } ++ pcd->ep0_pending = 0; ++ return 1; ++ } ++ ++ if (DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ return 0; ++ } ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ ++ if (pcd->ep0state == EP0_OUT_STATUS_PHASE ++ || pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ is_last = 1; ++ } else if (ep->dwc_ep.is_in) { ++ deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz); ++ if (core_if->dma_desc_enable != 0) ++ desc_sts = dev_if->in_desc_addr->status; ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCDV, "%d len=%d xfersize=%d pktcnt=%d\n", ++ ep->dwc_ep.num, ep->dwc_ep.xfer_len, ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++#endif ++ ++ if (((core_if->dma_desc_enable == 0) ++ && (deptsiz.b.xfersize == 0)) ++ || ((core_if->dma_desc_enable != 0) ++ && (desc_sts.b.bytes == 0))) { ++ req->actual = ep->dwc_ep.xfer_count; ++ /* Is a Zero Len Packet needed? */ ++ if (req->sent_zlp) { ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n"); ++#endif ++ req->sent_zlp = 0; ++ } ++ do_setup_out_status_phase(pcd); ++ } ++ } else { ++ /* ep0-OUT */ ++#ifdef DEBUG_EP0 ++ deptsiz.d32 = DWC_READ_REG32(&out_ep_regs->doeptsiz); ++ DWC_DEBUGPL(DBG_PCDV, "%d len=%d xsize=%d pktcnt=%d\n", ++ ep->dwc_ep.num, ep->dwc_ep.xfer_len, ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++#endif ++ req->actual = ep->dwc_ep.xfer_count; ++ ++ /* Is a Zero Len Packet needed? */ ++ if (req->sent_zlp) { ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n"); ++#endif ++ req->sent_zlp = 0; ++ } ++ /* For older cores do setup in status phase in Slave/BDMA modes, ++ * starting from 3.00 do that only in slave, and for DMA modes ++ * just re-enable ep 0 OUT here*/ ++ if (core_if->dma_enable == 0 ++ || (core_if->dma_desc_enable == 0 ++ && core_if->snpsid <= OTG_CORE_REV_2_94a)) { ++ do_setup_in_status_phase(pcd); ++ } else if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ DWC_DEBUGPL(DBG_PCDV, ++ "Enable out ep before in status phase\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ ++ /* Complete the request */ ++ if (is_last) { ++ dwc_otg_request_done(ep, req, 0); ++ ep->dwc_ep.start_xfer_buff = 0; ++ ep->dwc_ep.xfer_buff = 0; ++ ep->dwc_ep.xfer_len = 0; ++ return 1; ++ } ++ return 0; ++} ++ ++#ifdef DWC_UTE_CFI ++/** ++ * This function calculates traverses all the CFI DMA descriptors and ++ * and accumulates the bytes that are left to be transfered. ++ * ++ * @return The total bytes left to transfered, or a negative value as failure ++ */ ++static inline int cfi_calc_desc_residue(dwc_otg_pcd_ep_t * ep) ++{ ++ int32_t ret = 0; ++ int i; ++ struct dwc_otg_dma_desc *ddesc = NULL; ++ struct cfi_ep *cfiep; ++ ++ /* See if the pcd_ep has its respective cfi_ep mapped */ ++ cfiep = get_cfi_ep_by_pcd_ep(ep->pcd->cfi, ep); ++ if (!cfiep) { ++ CFI_INFO("%s: Failed to find ep\n", __func__); ++ return -1; ++ } ++ ++ ddesc = ep->dwc_ep.descs; ++ ++ for (i = 0; (i < cfiep->desc_count) && (i < MAX_DMA_DESCS_PER_EP); i++) { ++ ++#if defined(PRINT_CFI_DMA_DESCS) ++ print_desc(ddesc, ep->ep.name, i); ++#endif ++ ret += ddesc->status.b.bytes; ++ ddesc++; ++ } ++ ++ if (ret) ++ CFI_INFO("!!!!!!!!!! WARNING (%s) - residue=%d\n", __func__, ++ ret); ++ ++ return ret; ++} ++#endif ++ ++/** ++ * This function completes the request for the EP. If there are ++ * additional requests for the EP in the queue they will be started. ++ */ ++static void complete_ep(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dwc_otg_dev_in_ep_regs_t *in_ep_regs = ++ dev_if->in_ep_regs[ep->dwc_ep.num]; ++ deptsiz_data_t deptsiz; ++ dev_dma_desc_sts_t desc_sts; ++ dwc_otg_pcd_request_t *req = 0; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ uint32_t byte_count = 0; ++ int is_last = 0; ++ int i; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s() %d-%s\n", __func__, ep->dwc_ep.num, ++ (ep->dwc_ep.is_in ? "IN" : "OUT")); ++ ++ /* Get any pending requests */ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); ++ return; ++ } ++ } else { ++ DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); ++ return; ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "Requests %d\n", ep->pcd->request_pending); ++ ++ if (ep->dwc_ep.is_in) { ++ deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz); ++ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ if (deptsiz.b.xfersize == 0 ++ && deptsiz.b.pktcnt == 0) { ++ byte_count = ++ ep->dwc_ep.xfer_len - ++ ep->dwc_ep.xfer_count; ++ ++ ep->dwc_ep.xfer_buff += byte_count; ++ ep->dwc_ep.dma_addr += byte_count; ++ ep->dwc_ep.xfer_count += byte_count; ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "%d-%s len=%d xfersize=%d pktcnt=%d\n", ++ ep->dwc_ep.num, ++ (ep->dwc_ep. ++ is_in ? "IN" : "OUT"), ++ ep->dwc_ep.xfer_len, ++ deptsiz.b.xfersize, ++ deptsiz.b.pktcnt); ++ ++ if (ep->dwc_ep.xfer_len < ++ ep->dwc_ep.total_len) { ++ dwc_otg_ep_start_transfer ++ (core_if, &ep->dwc_ep); ++ } else if (ep->dwc_ep.sent_zlp) { ++ /* ++ * This fragment of code should initiate 0 ++ * length transfer in case if it is queued ++ * a transfer with size divisible to EPs max ++ * packet size and with usb_request zero field ++ * is set, which means that after data is transfered, ++ * it is also should be transfered ++ * a 0 length packet at the end. For Slave and ++ * Buffer DMA modes in this case SW has ++ * to initiate 2 transfers one with transfer size, ++ * and the second with 0 size. For Descriptor ++ * DMA mode SW is able to initiate a transfer, ++ * which will handle all the packets including ++ * the last 0 length. ++ */ ++ ep->dwc_ep.sent_zlp = 0; ++ dwc_otg_ep_start_zl_transfer ++ (core_if, &ep->dwc_ep); ++ } else { ++ is_last = 1; ++ } ++ } else { ++ if (ep->dwc_ep.type == ++ DWC_OTG_EP_TYPE_ISOC) { ++ req->actual = 0; ++ dwc_otg_request_done(ep, req, 0); ++ ++ ep->dwc_ep.start_xfer_buff = 0; ++ ep->dwc_ep.xfer_buff = 0; ++ ep->dwc_ep.xfer_len = 0; ++ ++ /* If there is a request in the queue start it. */ ++ start_next_request(ep); ++ } else ++ DWC_WARN ++ ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n", ++ ep->dwc_ep.num, ++ (ep->dwc_ep.is_in ? "IN" : "OUT"), ++ deptsiz.b.xfersize, ++ deptsiz.b.pktcnt); ++ } ++ } else { ++ dma_desc = ep->dwc_ep.desc_addr; ++ byte_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ++#ifdef DWC_UTE_CFI ++ CFI_INFO("%s: BUFFER_MODE=%d\n", __func__, ++ ep->dwc_ep.buff_mode); ++ if (ep->dwc_ep.buff_mode != BM_STANDARD) { ++ int residue; ++ ++ residue = cfi_calc_desc_residue(ep); ++ if (residue < 0) ++ return; ++ ++ byte_count = residue; ++ } else { ++#endif ++ for (i = 0; i < ep->dwc_ep.desc_cnt; ++ ++i) { ++ desc_sts = dma_desc->status; ++ byte_count += desc_sts.b.bytes; ++ dma_desc++; ++ } ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ if (byte_count == 0) { ++ ep->dwc_ep.xfer_count = ++ ep->dwc_ep.total_len; ++ is_last = 1; ++ } else { ++ DWC_WARN("Incomplete transfer\n"); ++ } ++ } ++ } else { ++ if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0) { ++ DWC_DEBUGPL(DBG_PCDV, ++ "%d-%s len=%d xfersize=%d pktcnt=%d\n", ++ ep->dwc_ep.num, ++ ep->dwc_ep.is_in ? "IN" : "OUT", ++ ep->dwc_ep.xfer_len, ++ deptsiz.b.xfersize, ++ deptsiz.b.pktcnt); ++ ++ /* Check if the whole transfer was completed, ++ * if no, setup transfer for next portion of data ++ */ ++ if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { ++ dwc_otg_ep_start_transfer(core_if, ++ &ep->dwc_ep); ++ } else if (ep->dwc_ep.sent_zlp) { ++ /* ++ * This fragment of code should initiate 0 ++ * length trasfer in case if it is queued ++ * a trasfer with size divisible to EPs max ++ * packet size and with usb_request zero field ++ * is set, which means that after data is transfered, ++ * it is also should be transfered ++ * a 0 length packet at the end. For Slave and ++ * Buffer DMA modes in this case SW has ++ * to initiate 2 transfers one with transfer size, ++ * and the second with 0 size. For Desriptor ++ * DMA mode SW is able to initiate a transfer, ++ * which will handle all the packets including ++ * the last 0 legth. ++ */ ++ ep->dwc_ep.sent_zlp = 0; ++ dwc_otg_ep_start_zl_transfer(core_if, ++ &ep->dwc_ep); ++ } else { ++ is_last = 1; ++ } ++ } else { ++ DWC_WARN ++ ("Incomplete transfer (%d-%s [siz=%d pkt=%d])\n", ++ ep->dwc_ep.num, ++ (ep->dwc_ep.is_in ? "IN" : "OUT"), ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ } ++ } ++ } else { ++ dwc_otg_dev_out_ep_regs_t *out_ep_regs = ++ dev_if->out_ep_regs[ep->dwc_ep.num]; ++ desc_sts.d32 = 0; ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ dma_desc = ep->dwc_ep.desc_addr; ++ byte_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ++#ifdef DWC_UTE_CFI ++ CFI_INFO("%s: BUFFER_MODE=%d\n", __func__, ++ ep->dwc_ep.buff_mode); ++ if (ep->dwc_ep.buff_mode != BM_STANDARD) { ++ int residue; ++ residue = cfi_calc_desc_residue(ep); ++ if (residue < 0) ++ return; ++ byte_count = residue; ++ } else { ++#endif ++ ++ for (i = 0; i < ep->dwc_ep.desc_cnt; ++ ++i) { ++ desc_sts = dma_desc->status; ++ byte_count += desc_sts.b.bytes; ++ dma_desc++; ++ } ++ ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ /* Checking for interrupt Out transfers with not ++ * dword aligned mps sizes ++ */ ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_INTR && ++ (ep->dwc_ep.maxpacket % 4)) { ++ ep->dwc_ep.xfer_count = ++ ep->dwc_ep.total_len - byte_count; ++ if ((ep->dwc_ep.xfer_len % ++ ep->dwc_ep.maxpacket) ++ && (ep->dwc_ep.xfer_len / ++ ep->dwc_ep.maxpacket < ++ MAX_DMA_DESC_CNT)) ++ ep->dwc_ep.xfer_len -= ++ (ep->dwc_ep.desc_cnt - ++ 1) * ep->dwc_ep.maxpacket + ++ ep->dwc_ep.xfer_len % ++ ep->dwc_ep.maxpacket; ++ else ++ ep->dwc_ep.xfer_len -= ++ ep->dwc_ep.desc_cnt * ++ ep->dwc_ep.maxpacket; ++ if (ep->dwc_ep.xfer_len > 0) { ++ dwc_otg_ep_start_transfer ++ (core_if, &ep->dwc_ep); ++ } else { ++ is_last = 1; ++ } ++ } else { ++ ep->dwc_ep.xfer_count = ++ ep->dwc_ep.total_len - byte_count + ++ ((4 - ++ (ep->dwc_ep. ++ total_len & 0x3)) & 0x3); ++ is_last = 1; ++ } ++ } else { ++ deptsiz.d32 = 0; ++ deptsiz.d32 = ++ DWC_READ_REG32(&out_ep_regs->doeptsiz); ++ ++ byte_count = (ep->dwc_ep.xfer_len - ++ ep->dwc_ep.xfer_count - ++ deptsiz.b.xfersize); ++ ep->dwc_ep.xfer_buff += byte_count; ++ ep->dwc_ep.dma_addr += byte_count; ++ ep->dwc_ep.xfer_count += byte_count; ++ ++ /* Check if the whole transfer was completed, ++ * if no, setup transfer for next portion of data ++ */ ++ if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { ++ dwc_otg_ep_start_transfer(core_if, ++ &ep->dwc_ep); ++ } else if (ep->dwc_ep.sent_zlp) { ++ /* ++ * This fragment of code should initiate 0 ++ * length trasfer in case if it is queued ++ * a trasfer with size divisible to EPs max ++ * packet size and with usb_request zero field ++ * is set, which means that after data is transfered, ++ * it is also should be transfered ++ * a 0 length packet at the end. For Slave and ++ * Buffer DMA modes in this case SW has ++ * to initiate 2 transfers one with transfer size, ++ * and the second with 0 size. For Desriptor ++ * DMA mode SW is able to initiate a transfer, ++ * which will handle all the packets including ++ * the last 0 legth. ++ */ ++ ep->dwc_ep.sent_zlp = 0; ++ dwc_otg_ep_start_zl_transfer(core_if, ++ &ep->dwc_ep); ++ } else { ++ is_last = 1; ++ } ++ } ++ } else { ++ /* Check if the whole transfer was completed, ++ * if no, setup transfer for next portion of data ++ */ ++ if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { ++ dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep); ++ } else if (ep->dwc_ep.sent_zlp) { ++ /* ++ * This fragment of code should initiate 0 ++ * length transfer in case if it is queued ++ * a transfer with size divisible to EPs max ++ * packet size and with usb_request zero field ++ * is set, which means that after data is transfered, ++ * it is also should be transfered ++ * a 0 length packet at the end. For Slave and ++ * Buffer DMA modes in this case SW has ++ * to initiate 2 transfers one with transfer size, ++ * and the second with 0 size. For Descriptor ++ * DMA mode SW is able to initiate a transfer, ++ * which will handle all the packets including ++ * the last 0 length. ++ */ ++ ep->dwc_ep.sent_zlp = 0; ++ dwc_otg_ep_start_zl_transfer(core_if, ++ &ep->dwc_ep); ++ } else { ++ is_last = 1; ++ } ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "addr %p, %d-%s len=%d cnt=%d xsize=%d pktcnt=%d\n", ++ &out_ep_regs->doeptsiz, ep->dwc_ep.num, ++ ep->dwc_ep.is_in ? "IN" : "OUT", ++ ep->dwc_ep.xfer_len, ep->dwc_ep.xfer_count, ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ } ++ ++ /* Complete the request */ ++ if (is_last) { ++#ifdef DWC_UTE_CFI ++ if (ep->dwc_ep.buff_mode != BM_STANDARD) { ++ req->actual = ep->dwc_ep.cfi_req_len - byte_count; ++ } else { ++#endif ++ req->actual = ep->dwc_ep.xfer_count; ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ if (req->dw_align_buf) { ++ if (!ep->dwc_ep.is_in) { ++ dwc_memcpy(req->buf, req->dw_align_buf, req->length); ++ } ++ DWC_DMA_FREE(req->length, req->dw_align_buf, ++ req->dw_align_buf_dma); ++ } ++ ++ dwc_otg_request_done(ep, req, 0); ++ ++ ep->dwc_ep.start_xfer_buff = 0; ++ ep->dwc_ep.xfer_buff = 0; ++ ep->dwc_ep.xfer_len = 0; ++ ++ /* If there is a request in the queue start it. */ ++ start_next_request(ep); ++ } ++} ++/** ++ * This function completes the request for the ISO EP in DDMA. If it is last ++ * descriptor and ep was disabled, then program already prepared(during ep_queue) ++ * descriptor chain if there are more requests to process ++ */ ++static void complete_ddma_iso_ep(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); ++ dev_dma_desc_sts_t desc_sts; ++ dwc_otg_pcd_request_t *req = 0; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ dwc_dma_t dma_desc_addr; ++ dwc_ep_t *dwc_ep; ++ uint32_t depdma; ++ uint32_t index; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s() %d-%s\n", __func__, ep->dwc_ep.num, ++ (ep->dwc_ep.is_in ? "IN" : "OUT")); ++ dwc_ep = &ep->dwc_ep; ++ if (dwc_ep->use_add_buf) { ++ dma_desc_addr = dwc_ep->dma_desc_addr; ++ dma_desc = dwc_ep->desc_addr; ++ } else { ++ dma_desc_addr = dwc_ep->dma_desc_addr1; ++ dma_desc = dwc_ep->desc_addr1; ++ } ++ /* Get any pending requests */ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); ++ return; ++ } ++ } else { ++ DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); ++ return; ++ } ++ ++ if (dwc_ep->is_in) { ++ depdma = DWC_READ_REG32(&core_if->dev_if->in_ep_regs[dwc_ep->num]->diepdma); ++ index = (depdma - dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t) - 1; ++ desc_sts = dma_desc[index].status; ++ req->actual = req->length - desc_sts.b_iso_in.txbytes; ++ } else { ++ depdma = DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepdma); ++ index = (depdma - dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t) - 1; ++ desc_sts = dma_desc[index].status; ++ if (req->length%4) ++ req->actual = req->length - desc_sts.b_iso_out.rxbytes + (4 - req->length%4); ++ else ++ req->actual = req->length - desc_sts.b_iso_out.rxbytes; ++ } ++ ++ /* Complete the request */ ++ dwc_otg_request_done(ep, req, 0); ++} ++ ++#ifdef DWC_EN_ISOC ++ ++/** ++ * This function BNA interrupt for Isochronous EPs ++ * ++ */ ++static void dwc_otg_pcd_handle_iso_bna(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_ep_t *dwc_ep = &ep->dwc_ep; ++ volatile uint32_t *addr; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dwc_otg_pcd_t *pcd = ep->pcd; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ int i; ++ ++ dma_desc = ++ dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * (dwc_ep->proc_buf_num); ++ ++ if (dwc_ep->is_in) { ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) { ++ sts.d32 = dma_desc->status.d32; ++ sts.b_iso_in.bs = BS_HOST_READY; ++ dma_desc->status.d32 = sts.d32; ++ } ++ } else { ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) { ++ sts.d32 = dma_desc->status.d32; ++ sts.b_iso_out.bs = BS_HOST_READY; ++ dma_desc->status.d32 = sts.d32; ++ } ++ } ++ ++ if (dwc_ep->is_in == 0) { ++ addr = ++ &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep-> ++ num]->doepctl; ++ } else { ++ addr = ++ &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl; ++ } ++ depctl.b.epena = 1; ++ DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32); ++} ++ ++/** ++ * This function sets latest iso packet information(non-PTI mode) ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void set_current_pkt_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ dma_addr_t dma_addr; ++ uint32_t offset; ++ ++ if (ep->proc_buf_num) ++ dma_addr = ep->dma_addr1; ++ else ++ dma_addr = ep->dma_addr0; ++ ++ if (ep->is_in) { ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[ep->num]->dieptsiz); ++ offset = ep->data_per_frame; ++ } else { ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->num]->doeptsiz); ++ offset = ++ ep->data_per_frame + ++ (0x4 & (0x4 - (ep->data_per_frame & 0x3))); ++ } ++ ++ if (!deptsiz.b.xfersize) { ++ ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame; ++ ep->pkt_info[ep->cur_pkt].offset = ++ ep->cur_pkt_dma_addr - dma_addr; ++ ep->pkt_info[ep->cur_pkt].status = 0; ++ } else { ++ ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame; ++ ep->pkt_info[ep->cur_pkt].offset = ++ ep->cur_pkt_dma_addr - dma_addr; ++ ep->pkt_info[ep->cur_pkt].status = -DWC_E_NO_DATA; ++ } ++ ep->cur_pkt_addr += offset; ++ ep->cur_pkt_dma_addr += offset; ++ ep->cur_pkt++; ++} ++ ++/** ++ * This function sets latest iso packet information(DDMA mode) ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param dwc_ep The EP to start the transfer on. ++ * ++ */ ++static void set_ddma_iso_pkts_info(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * dwc_ep) ++{ ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ iso_pkt_info_t *iso_packet; ++ uint32_t data_per_desc; ++ uint32_t offset; ++ int i, j; ++ ++ iso_packet = dwc_ep->pkt_info; ++ ++ /** Reinit closed DMA Descriptors*/ ++ /** ISO OUT EP */ ++ if (dwc_ep->is_in == 0) { ++ dma_desc = ++ dwc_ep->iso_desc_addr + ++ dwc_ep->desc_cnt * dwc_ep->proc_buf_num; ++ offset = 0; ++ ++ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; ++ i += dwc_ep->pkt_per_frm) { ++ for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep-> ++ data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - ++ data_per_desc % ++ 4) : 0; ++ ++ sts.d32 = dma_desc->status.d32; ++ ++ /* Write status in iso_packet_decsriptor */ ++ iso_packet->status = ++ sts.b_iso_out.rxsts + ++ (sts.b_iso_out.bs ^ BS_DMA_DONE); ++ if (iso_packet->status) { ++ iso_packet->status = -DWC_E_NO_DATA; ++ } ++ ++ /* Received data length */ ++ if (!sts.b_iso_out.rxbytes) { ++ iso_packet->length = ++ data_per_desc - ++ sts.b_iso_out.rxbytes; ++ } else { ++ iso_packet->length = ++ data_per_desc - ++ sts.b_iso_out.rxbytes + (4 - ++ dwc_ep->data_per_frame ++ % 4); ++ } ++ ++ iso_packet->offset = offset; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ iso_packet++; ++ } ++ } ++ ++ for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) { ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ ++ sts.d32 = dma_desc->status.d32; ++ ++ /* Write status in iso_packet_decsriptor */ ++ iso_packet->status = ++ sts.b_iso_out.rxsts + ++ (sts.b_iso_out.bs ^ BS_DMA_DONE); ++ if (iso_packet->status) { ++ iso_packet->status = -DWC_E_NO_DATA; ++ } ++ ++ /* Received data length */ ++ iso_packet->length = ++ dwc_ep->data_per_frame - sts.b_iso_out.rxbytes; ++ ++ iso_packet->offset = offset; ++ ++ offset += data_per_desc; ++ iso_packet++; ++ dma_desc++; ++ } ++ ++ sts.d32 = dma_desc->status.d32; ++ ++ /* Write status in iso_packet_decsriptor */ ++ iso_packet->status = ++ sts.b_iso_out.rxsts + (sts.b_iso_out.bs ^ BS_DMA_DONE); ++ if (iso_packet->status) { ++ iso_packet->status = -DWC_E_NO_DATA; ++ } ++ /* Received data length */ ++ if (!sts.b_iso_out.rxbytes) { ++ iso_packet->length = ++ dwc_ep->data_per_frame - sts.b_iso_out.rxbytes; ++ } else { ++ iso_packet->length = ++ dwc_ep->data_per_frame - sts.b_iso_out.rxbytes + ++ (4 - dwc_ep->data_per_frame % 4); ++ } ++ ++ iso_packet->offset = offset; ++ } else { ++/** ISO IN EP */ ++ ++ dma_desc = ++ dwc_ep->iso_desc_addr + ++ dwc_ep->desc_cnt * dwc_ep->proc_buf_num; ++ ++ for (i = 0; i < dwc_ep->desc_cnt - 1; i++) { ++ sts.d32 = dma_desc->status.d32; ++ ++ /* Write status in iso packet descriptor */ ++ iso_packet->status = ++ sts.b_iso_in.txsts + ++ (sts.b_iso_in.bs ^ BS_DMA_DONE); ++ if (iso_packet->status != 0) { ++ iso_packet->status = -DWC_E_NO_DATA; ++ ++ } ++ /* Bytes has been transfered */ ++ iso_packet->length = ++ dwc_ep->data_per_frame - sts.b_iso_in.txbytes; ++ ++ dma_desc++; ++ iso_packet++; ++ } ++ ++ sts.d32 = dma_desc->status.d32; ++ while (sts.b_iso_in.bs == BS_DMA_BUSY) { ++ sts.d32 = dma_desc->status.d32; ++ } ++ ++ /* Write status in iso packet descriptor ??? do be done with ERROR codes */ ++ iso_packet->status = ++ sts.b_iso_in.txsts + (sts.b_iso_in.bs ^ BS_DMA_DONE); ++ if (iso_packet->status != 0) { ++ iso_packet->status = -DWC_E_NO_DATA; ++ } ++ ++ /* Bytes has been transfered */ ++ iso_packet->length = ++ dwc_ep->data_per_frame - sts.b_iso_in.txbytes; ++ } ++} ++ ++/** ++ * This function reinitialize DMA Descriptors for Isochronous transfer ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param dwc_ep The EP to start the transfer on. ++ * ++ */ ++static void reinit_ddma_iso_xfer(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep) ++{ ++ int i, j; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ dma_addr_t dma_ad; ++ volatile uint32_t *addr; ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ uint32_t data_per_desc; ++ ++ if (dwc_ep->is_in == 0) { ++ addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl; ++ } else { ++ addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl; ++ } ++ ++ if (dwc_ep->proc_buf_num == 0) { ++ /** Buffer 0 descriptors setup */ ++ dma_ad = dwc_ep->dma_addr0; ++ } else { ++ /** Buffer 1 descriptors setup */ ++ dma_ad = dwc_ep->dma_addr1; ++ } ++ ++ /** Reinit closed DMA Descriptors*/ ++ /** ISO OUT EP */ ++ if (dwc_ep->is_in == 0) { ++ dma_desc = ++ dwc_ep->iso_desc_addr + ++ dwc_ep->desc_cnt * dwc_ep->proc_buf_num; ++ ++ sts.b_iso_out.bs = BS_HOST_READY; ++ sts.b_iso_out.rxsts = 0; ++ sts.b_iso_out.l = 0; ++ sts.b_iso_out.sp = 0; ++ sts.b_iso_out.ioc = 0; ++ sts.b_iso_out.pid = 0; ++ sts.b_iso_out.framenum = 0; ++ ++ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; ++ i += dwc_ep->pkt_per_frm) { ++ for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep-> ++ data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - ++ data_per_desc % ++ 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ dma_ad += data_per_desc; ++ dma_desc++; ++ } ++ } ++ ++ for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) { ++ ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ ++ sts.b_iso_out.ioc = 1; ++ sts.b_iso_out.l = dwc_ep->proc_buf_num; ++ ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ } else { ++/** ISO IN EP */ ++ ++ dma_desc = ++ dwc_ep->iso_desc_addr + ++ dwc_ep->desc_cnt * dwc_ep->proc_buf_num; ++ ++ sts.b_iso_in.bs = BS_HOST_READY; ++ sts.b_iso_in.txsts = 0; ++ sts.b_iso_in.sp = 0; ++ sts.b_iso_in.ioc = 0; ++ sts.b_iso_in.pid = dwc_ep->pkt_per_frm; ++ sts.b_iso_in.framenum = dwc_ep->next_frame; ++ sts.b_iso_in.txbytes = dwc_ep->data_per_frame; ++ sts.b_iso_in.l = 0; ++ ++ for (i = 0; i < dwc_ep->desc_cnt - 1; i++) { ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ sts.b_iso_in.framenum += dwc_ep->bInterval; ++ dma_ad += dwc_ep->data_per_frame; ++ dma_desc++; ++ } ++ ++ sts.b_iso_in.ioc = 1; ++ sts.b_iso_in.l = dwc_ep->proc_buf_num; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ dwc_ep->next_frame = ++ sts.b_iso_in.framenum + dwc_ep->bInterval * 1; ++ } ++ dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1; ++} ++ ++/** ++ * This function is to handle Iso EP transfer complete interrupt ++ * in case Iso out packet was dropped ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param dwc_ep The EP for wihich transfer complete was asserted ++ * ++ */ ++static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * dwc_ep) ++{ ++ uint32_t dma_addr; ++ uint32_t drp_pkt; ++ uint32_t drp_pkt_cnt; ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ int i; ++ ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[dwc_ep->num]->doeptsiz); ++ ++ drp_pkt = dwc_ep->pkt_cnt - deptsiz.b.pktcnt; ++ drp_pkt_cnt = dwc_ep->pkt_per_frm - (drp_pkt % dwc_ep->pkt_per_frm); ++ ++ /* Setting dropped packets status */ ++ for (i = 0; i < drp_pkt_cnt; ++i) { ++ dwc_ep->pkt_info[drp_pkt].status = -DWC_E_NO_DATA; ++ drp_pkt++; ++ deptsiz.b.pktcnt--; ++ } ++ ++ if (deptsiz.b.pktcnt > 0) { ++ deptsiz.b.xfersize = ++ dwc_ep->xfer_len - (dwc_ep->pkt_cnt - ++ deptsiz.b.pktcnt) * dwc_ep->maxpacket; ++ } else { ++ deptsiz.b.xfersize = 0; ++ deptsiz.b.pktcnt = 0; ++ } ++ ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz, ++ deptsiz.d32); ++ ++ if (deptsiz.b.pktcnt > 0) { ++ if (dwc_ep->proc_buf_num) { ++ dma_addr = ++ dwc_ep->dma_addr1 + dwc_ep->xfer_len - ++ deptsiz.b.xfersize; ++ } else { ++ dma_addr = ++ dwc_ep->dma_addr0 + dwc_ep->xfer_len - ++ deptsiz.b.xfersize;; ++ } ++ ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ out_ep_regs[dwc_ep->num]->doepdma, dma_addr); ++ ++ /** Re-enable endpoint, clear nak */ ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ ++ DWC_MODIFY_REG32(&core_if->dev_if-> ++ out_ep_regs[dwc_ep->num]->doepctl, depctl.d32, ++ depctl.d32); ++ return 0; ++ } else { ++ return 1; ++ } ++} ++ ++/** ++ * This function sets iso packets information(PTI mode) ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++static uint32_t set_iso_pkts_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ int i, j; ++ dma_addr_t dma_ad; ++ iso_pkt_info_t *packet_info = ep->pkt_info; ++ uint32_t offset; ++ uint32_t frame_data; ++ deptsiz_data_t deptsiz; ++ ++ if (ep->proc_buf_num == 0) { ++ /** Buffer 0 descriptors setup */ ++ dma_ad = ep->dma_addr0; ++ } else { ++ /** Buffer 1 descriptors setup */ ++ dma_ad = ep->dma_addr1; ++ } ++ ++ if (ep->is_in) { ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ dieptsiz); ++ } else { ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[ep->num]-> ++ doeptsiz); ++ } ++ ++ if (!deptsiz.b.xfersize) { ++ offset = 0; ++ for (i = 0; i < ep->pkt_cnt; i += ep->pkt_per_frm) { ++ frame_data = ep->data_per_frame; ++ for (j = 0; j < ep->pkt_per_frm; ++j) { ++ ++ /* Packet status - is not set as initially ++ * it is set to 0 and if packet was sent ++ successfully, status field will remain 0*/ ++ ++ /* Bytes has been transfered */ ++ packet_info->length = ++ (ep->maxpacket < ++ frame_data) ? ep->maxpacket : frame_data; ++ ++ /* Received packet offset */ ++ packet_info->offset = offset; ++ offset += packet_info->length; ++ frame_data -= packet_info->length; ++ ++ packet_info++; ++ } ++ } ++ return 1; ++ } else { ++ /* This is a workaround for in case of Transfer Complete with ++ * PktDrpSts interrupts merging - in this case Transfer complete ++ * interrupt for Isoc Out Endpoint is asserted without PktDrpSts ++ * set and with DOEPTSIZ register non zero. Investigations showed, ++ * that this happens when Out packet is dropped, but because of ++ * interrupts merging during first interrupt handling PktDrpSts ++ * bit is cleared and for next merged interrupts it is not reset. ++ * In this case SW hadles the interrupt as if PktDrpSts bit is set. ++ */ ++ if (ep->is_in) { ++ return 1; ++ } else { ++ return handle_iso_out_pkt_dropped(core_if, ep); ++ } ++ } ++} ++ ++/** ++ * This function is to handle Iso EP transfer complete interrupt ++ * ++ * @param pcd The PCD ++ * @param ep The EP for which transfer complete was asserted ++ * ++ */ ++static void complete_iso_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); ++ dwc_ep_t *dwc_ep = &ep->dwc_ep; ++ uint8_t is_last = 0; ++ ++ if (ep->dwc_ep.next_frame == 0xffffffff) { ++ DWC_WARN("Next frame is not set!\n"); ++ return; ++ } ++ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ set_ddma_iso_pkts_info(core_if, dwc_ep); ++ reinit_ddma_iso_xfer(core_if, dwc_ep); ++ is_last = 1; ++ } else { ++ if (core_if->pti_enh_enable) { ++ if (set_iso_pkts_info(core_if, dwc_ep)) { ++ dwc_ep->proc_buf_num = ++ (dwc_ep->proc_buf_num ^ 1) & 0x1; ++ dwc_otg_iso_ep_start_buf_transfer ++ (core_if, dwc_ep); ++ is_last = 1; ++ } ++ } else { ++ set_current_pkt_info(core_if, dwc_ep); ++ if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { ++ is_last = 1; ++ dwc_ep->cur_pkt = 0; ++ dwc_ep->proc_buf_num = ++ (dwc_ep->proc_buf_num ^ 1) & 0x1; ++ if (dwc_ep->proc_buf_num) { ++ dwc_ep->cur_pkt_addr = ++ dwc_ep->xfer_buff1; ++ dwc_ep->cur_pkt_dma_addr = ++ dwc_ep->dma_addr1; ++ } else { ++ dwc_ep->cur_pkt_addr = ++ dwc_ep->xfer_buff0; ++ dwc_ep->cur_pkt_dma_addr = ++ dwc_ep->dma_addr0; ++ } ++ ++ } ++ dwc_otg_iso_ep_start_frm_transfer(core_if, ++ dwc_ep); ++ } ++ } ++ } else { ++ set_current_pkt_info(core_if, dwc_ep); ++ if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { ++ is_last = 1; ++ dwc_ep->cur_pkt = 0; ++ dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1; ++ if (dwc_ep->proc_buf_num) { ++ dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff1; ++ dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr1; ++ } else { ++ dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff0; ++ dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr0; ++ } ++ ++ } ++ dwc_otg_iso_ep_start_frm_transfer(core_if, dwc_ep); ++ } ++ if (is_last) ++ dwc_otg_iso_buffer_done(pcd, ep, ep->iso_req_handle); ++} ++#endif /* DWC_EN_ISOC */ ++ ++/** ++ * This function handle BNA interrupt for Non Isochronous EPs ++ * ++ */ ++static void dwc_otg_pcd_handle_noniso_bna(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_ep_t *dwc_ep = &ep->dwc_ep; ++ volatile uint32_t *addr; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dwc_otg_pcd_t *pcd = ep->pcd; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if = ep->pcd->core_if; ++ int i, start; ++ ++ if (!dwc_ep->desc_cnt) ++ DWC_WARN("Ep%d %s Descriptor count = %d \n", dwc_ep->num, ++ (dwc_ep->is_in ? "IN" : "OUT"), dwc_ep->desc_cnt); ++ ++ if (core_if->core_params->cont_on_bna && !dwc_ep->is_in ++ && dwc_ep->type != DWC_OTG_EP_TYPE_CONTROL) { ++ uint32_t doepdma; ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[dwc_ep->num]; ++ doepdma = DWC_READ_REG32(&(out_regs->doepdma)); ++ start = (doepdma - dwc_ep->dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t); ++ dma_desc = &(dwc_ep->desc_addr[start]); ++ } else { ++ start = 0; ++ dma_desc = dwc_ep->desc_addr; ++ } ++ ++ ++ for (i = start; i < dwc_ep->desc_cnt; ++i, ++dma_desc) { ++ sts.d32 = dma_desc->status.d32; ++ sts.b.bs = BS_HOST_READY; ++ dma_desc->status.d32 = sts.d32; ++ } ++ ++ if (dwc_ep->is_in == 0) { ++ addr = ++ &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]-> ++ doepctl; ++ } else { ++ addr = ++ &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl; ++ } ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ DWC_MODIFY_REG32(addr, 0, depctl.d32); ++} ++ ++/** ++ * This function handles EP0 Control transfers. ++ * ++ * The state of the control transfers are tracked in ++ * ep0state. ++ */ ++static void handle_ep0(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ dev_dma_desc_sts_t desc_sts; ++ deptsiz0_data_t deptsiz; ++ uint32_t byte_count; ++ ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__); ++ print_ep0_state(pcd); ++#endif ++ ++ switch (pcd->ep0state) { ++ case EP0_DISCONNECT: ++ break; ++ ++ case EP0_IDLE: ++ pcd->request_config = 0; ++ ++ pcd_setup(pcd); ++ break; ++ ++ case EP0_IN_DATA_PHASE: ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, "DATA_IN EP%d-%s: type=%d, mps=%d\n", ++ ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"), ++ ep0->dwc_ep.type, ep0->dwc_ep.maxpacket); ++#endif ++ ++ if (core_if->dma_enable != 0) { ++ /* ++ * For EP0 we can only program 1 packet at a time so we ++ * need to do the make calculations after each complete. ++ * Call write_packet to make the calculations, as in ++ * slave mode, and use those values to determine if we ++ * can complete. ++ */ ++ if (core_if->dma_desc_enable == 0) { ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if-> ++ dev_if->in_ep_regs[0]-> ++ dieptsiz); ++ byte_count = ++ ep0->dwc_ep.xfer_len - deptsiz.b.xfersize; ++ } else { ++ desc_sts = ++ core_if->dev_if->in_desc_addr->status; ++ byte_count = ++ ep0->dwc_ep.xfer_len - desc_sts.b.bytes; ++ } ++ ep0->dwc_ep.xfer_count += byte_count; ++ ep0->dwc_ep.xfer_buff += byte_count; ++ ep0->dwc_ep.dma_addr += byte_count; ++ } ++ if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) { ++ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), ++ &ep0->dwc_ep); ++ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); ++ } else if (ep0->dwc_ep.sent_zlp) { ++ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), ++ &ep0->dwc_ep); ++ ep0->dwc_ep.sent_zlp = 0; ++ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n"); ++ } else { ++ ep0_complete_request(ep0); ++ DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); ++ } ++ break; ++ case EP0_OUT_DATA_PHASE: ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, "DATA_OUT EP%d-%s: type=%d, mps=%d\n", ++ ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"), ++ ep0->dwc_ep.type, ep0->dwc_ep.maxpacket); ++#endif ++ if (core_if->dma_enable != 0) { ++ if (core_if->dma_desc_enable == 0) { ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if-> ++ dev_if->out_ep_regs[0]-> ++ doeptsiz); ++ byte_count = ++ ep0->dwc_ep.maxpacket - deptsiz.b.xfersize; ++ } else { ++ desc_sts = ++ core_if->dev_if->out_desc_addr->status; ++ byte_count = ++ ep0->dwc_ep.maxpacket - desc_sts.b.bytes; ++ } ++ ep0->dwc_ep.xfer_count += byte_count; ++ ep0->dwc_ep.xfer_buff += byte_count; ++ ep0->dwc_ep.dma_addr += byte_count; ++ } ++ if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) { ++ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), ++ &ep0->dwc_ep); ++ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); ++ } else if (ep0->dwc_ep.sent_zlp) { ++ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), ++ &ep0->dwc_ep); ++ ep0->dwc_ep.sent_zlp = 0; ++ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n"); ++ } else { ++ ep0_complete_request(ep0); ++ DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); ++ } ++ break; ++ ++ case EP0_IN_STATUS_PHASE: ++ case EP0_OUT_STATUS_PHASE: ++ DWC_DEBUGPL(DBG_PCD, "CASE: EP0_STATUS\n"); ++ ep0_complete_request(ep0); ++ pcd->ep0state = EP0_IDLE; ++ ep0->stopped = 1; ++ ep0->dwc_ep.is_in = 0; /* OUT for next SETUP */ ++ ++ /* Prepare for more SETUP Packets */ ++ if (core_if->dma_enable) { ++ ep0_out_start(core_if, pcd); ++ } ++ break; ++ ++ case EP0_STALL: ++ DWC_ERROR("EP0 STALLed, should not get here pcd_setup()\n"); ++ break; ++ } ++#ifdef DEBUG_EP0 ++ print_ep0_state(pcd); ++#endif ++} ++ ++/** ++ * Restart transfer ++ */ ++static void restart_transfer(dwc_otg_pcd_t * pcd, const uint32_t epnum) ++{ ++ dwc_otg_core_if_t *core_if; ++ dwc_otg_dev_if_t *dev_if; ++ deptsiz_data_t dieptsiz = {.d32 = 0 }; ++ dwc_otg_pcd_ep_t *ep; ++ ++ ep = get_in_ep(pcd, epnum); ++ ++#ifdef DWC_EN_ISOC ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ return; ++ } ++#endif /* DWC_EN_ISOC */ ++ ++ core_if = GET_CORE_IF(pcd); ++ dev_if = core_if->dev_if; ++ ++ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz); ++ ++ DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x xfer_len=%0x" ++ " stopped=%d\n", ep->dwc_ep.xfer_buff, ++ ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len, ep->stopped); ++ /* ++ * If xfersize is 0 and pktcnt in not 0, resend the last packet. ++ */ ++ if (dieptsiz.b.pktcnt && dieptsiz.b.xfersize == 0 && ++ ep->dwc_ep.start_xfer_buff != 0) { ++ if (ep->dwc_ep.total_len <= ep->dwc_ep.maxpacket) { ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.xfer_buff = ep->dwc_ep.start_xfer_buff; ++ ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count; ++ } else { ++ ep->dwc_ep.xfer_count -= ep->dwc_ep.maxpacket; ++ /* convert packet size to dwords. */ ++ ep->dwc_ep.xfer_buff -= ep->dwc_ep.maxpacket; ++ ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count; ++ } ++ ep->stopped = 0; ++ DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x " ++ "xfer_len=%0x stopped=%d\n", ++ ep->dwc_ep.xfer_buff, ++ ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len, ++ ep->stopped); ++ if (epnum == 0) { ++ dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep); ++ } else { ++ dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep); ++ } ++ } ++} ++ ++/* ++ * This function create new nextep sequnce based on Learn Queue. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ */ ++void predict_nextep_seq( dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_device_global_regs_t *dev_global_regs = ++ core_if->dev_if->dev_global_regs; ++ const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth; ++ /* Number of Token Queue Registers */ ++ const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8; ++ dtknq1_data_t dtknqr1; ++ uint32_t in_tkn_epnums[4]; ++ uint8_t seqnum[MAX_EPS_CHANNELS]; ++ uint8_t intkn_seq[TOKEN_Q_DEPTH]; ++ grstctl_t resetctl = {.d32 = 0 }; ++ uint8_t temp; ++ int ndx = 0; ++ int start = 0; ++ int end = 0; ++ int sort_done = 0; ++ int i = 0; ++ volatile uint32_t *addr = &dev_global_regs->dtknqr1; ++ ++ DWC_DEBUGPL(DBG_PCD, "dev_token_q_depth=%d\n", TOKEN_Q_DEPTH); ++ ++ /* Read the DTKNQ Registers */ ++ for (i = 0; i < DTKNQ_REG_CNT; i++) { ++ in_tkn_epnums[i] = DWC_READ_REG32(addr); ++ DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1, ++ in_tkn_epnums[i]); ++ if (addr == &dev_global_regs->dvbusdis) { ++ addr = &dev_global_regs->dtknqr3_dthrctl; ++ } else { ++ ++addr; ++ } ++ ++ } ++ ++ /* Copy the DTKNQR1 data to the bit field. */ ++ dtknqr1.d32 = in_tkn_epnums[0]; ++ if (dtknqr1.b.wrap_bit) { ++ ndx = dtknqr1.b.intknwptr; ++ end = ndx - 1; ++ if (end < 0) ++ end = TOKEN_Q_DEPTH - 1; ++ } else { ++ ndx = 0; ++ end = dtknqr1.b.intknwptr - 1; ++ if (end < 0) ++ end = 0; ++ } ++ start = ndx; ++ ++ /* Fill seqnum[] by initial values: EP number + 31 */ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ seqnum[i] = i + 31; ++ } ++ ++ /* Fill intkn_seq[] from in_tkn_epnums[0] */ ++ for (i = 0; i < 6; i++) ++ intkn_seq[i] = (in_tkn_epnums[0] >> ((7 - i) * 4)) & 0xf; ++ ++ if (TOKEN_Q_DEPTH > 6) { ++ /* Fill intkn_seq[] from in_tkn_epnums[1] */ ++ for (i = 6; i < 14; i++) ++ intkn_seq[i] = ++ (in_tkn_epnums[1] >> ((7 - (i - 6)) * 4)) & 0xf; ++ } ++ ++ if (TOKEN_Q_DEPTH > 14) { ++ /* Fill intkn_seq[] from in_tkn_epnums[1] */ ++ for (i = 14; i < 22; i++) ++ intkn_seq[i] = ++ (in_tkn_epnums[2] >> ((7 - (i - 14)) * 4)) & 0xf; ++ } ++ ++ if (TOKEN_Q_DEPTH > 22) { ++ /* Fill intkn_seq[] from in_tkn_epnums[1] */ ++ for (i = 22; i < 30; i++) ++ intkn_seq[i] = ++ (in_tkn_epnums[3] >> ((7 - (i - 22)) * 4)) & 0xf; ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s start=%d end=%d intkn_seq[]:\n", __func__, ++ start, end); ++ for (i = 0; i < TOKEN_Q_DEPTH; i++) ++ DWC_DEBUGPL(DBG_PCDV, "%d\n", intkn_seq[i]); ++ ++ /* Update seqnum based on intkn_seq[] */ ++ i = 0; ++ do { ++ seqnum[intkn_seq[ndx]] = i; ++ ndx++; ++ i++; ++ if (ndx == TOKEN_Q_DEPTH) ++ ndx = 0; ++ } while (i < TOKEN_Q_DEPTH); ++ ++ /* Mark non active EP's in seqnum[] by 0xff */ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ if (core_if->nextep_seq[i] == 0xff) ++ seqnum[i] = 0xff; ++ } ++ ++ /* Sort seqnum[] */ ++ sort_done = 0; ++ while (!sort_done) { ++ sort_done = 1; ++ for (i = 0; i < core_if->dev_if->num_in_eps; i++) { ++ if (seqnum[i] > seqnum[i + 1]) { ++ temp = seqnum[i]; ++ seqnum[i] = seqnum[i + 1]; ++ seqnum[i + 1] = temp; ++ sort_done = 0; ++ } ++ } ++ } ++ ++ ndx = start + seqnum[0]; ++ if (ndx >= TOKEN_Q_DEPTH) ++ ndx = ndx % TOKEN_Q_DEPTH; ++ core_if->first_in_nextep_seq = intkn_seq[ndx]; ++ ++ /* Update seqnum[] by EP numbers */ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ ndx = start + i; ++ if (seqnum[i] < 31) { ++ ndx = start + seqnum[i]; ++ if (ndx >= TOKEN_Q_DEPTH) ++ ndx = ndx % TOKEN_Q_DEPTH; ++ seqnum[i] = intkn_seq[ndx]; ++ } else { ++ if (seqnum[i] < 0xff) { ++ seqnum[i] = seqnum[i] - 31; ++ } else { ++ break; ++ } ++ } ++ } ++ ++ /* Update nextep_seq[] based on seqnum[] */ ++ for (i = 0; i < core_if->dev_if->num_in_eps; i++) { ++ if (seqnum[i] != 0xff) { ++ if (seqnum[i + 1] != 0xff) { ++ core_if->nextep_seq[seqnum[i]] = seqnum[i + 1]; ++ } else { ++ core_if->nextep_seq[seqnum[i]] = core_if->first_in_nextep_seq; ++ break; ++ } ++ } else { ++ break; ++ } ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); ++ } ++ ++ /* Flush the Learning Queue */ ++ resetctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->grstctl); ++ resetctl.b.intknqflsh = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); ++ ++ ++} ++ ++/** ++ * handle the IN EP disable interrupt. ++ */ ++static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ deptsiz_data_t dieptsiz = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ gintmsk_data_t gintmsk_data; ++ depctl_data_t depctl; ++ uint32_t diepdma; ++ uint32_t remain_to_transfer = 0; ++ uint8_t i; ++ uint32_t xfer_size; ++ ++ ep = get_in_ep(pcd, epnum); ++ dwc_ep = &ep->dwc_ep; ++ ++ if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num); ++ complete_ep(ep); ++ return; ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "diepctl%d=%0x\n", epnum, ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl)); ++ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz); ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); ++ ++ DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n", ++ dieptsiz.b.pktcnt, dieptsiz.b.xfersize); ++ ++ if ((core_if->start_predict == 0) || (depctl.b.eptype & 1)) { ++ if (ep->stopped) { ++ if (core_if->en_multiple_tx_fifo) ++ /* Flush the Tx FIFO */ ++ dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num); ++ /* Clear the Global IN NP NAK */ ++ dctl.d32 = 0; ++ dctl.b.cgnpinnak = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ /* Restart the transaction */ ++ if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { ++ restart_transfer(pcd, epnum); ++ } ++ } else { ++ /* Restart the transaction */ ++ if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { ++ restart_transfer(pcd, epnum); ++ } ++ DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n"); ++ } ++ return; ++ } ++ ++ if (core_if->start_predict > 2) { // NP IN EP ++ core_if->start_predict--; ++ return; ++ } ++ ++ core_if->start_predict--; ++ ++ if (core_if->start_predict == 1) { // All NP IN Ep's disabled now ++ ++ predict_nextep_seq(core_if); ++ ++ /* Update all active IN EP's NextEP field based of nextep_seq[] */ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (core_if->nextep_seq[i] != 0xff) { // Active NP IN EP ++ depctl.b.nextep = core_if->nextep_seq[i]; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); ++ } ++ } ++ /* Flush Shared NP TxFIFO */ ++ dwc_otg_flush_tx_fifo(core_if, 0); ++ /* Rewind buffers */ ++ if (!core_if->dma_desc_enable) { ++ i = core_if->first_in_nextep_seq; ++ do { ++ ep = get_in_ep(pcd, i); ++ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz); ++ xfer_size = ep->dwc_ep.total_len - ep->dwc_ep.xfer_count; ++ if (xfer_size > ep->dwc_ep.maxxfer) ++ xfer_size = ep->dwc_ep.maxxfer; ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (dieptsiz.b.pktcnt != 0) { ++ if (xfer_size == 0) { ++ remain_to_transfer = 0; ++ } else { ++ if ((xfer_size % ep->dwc_ep.maxpacket) == 0) { ++ remain_to_transfer = ++ dieptsiz.b.pktcnt * ep->dwc_ep.maxpacket; ++ } else { ++ remain_to_transfer = ((dieptsiz.b.pktcnt -1) * ep->dwc_ep.maxpacket) ++ + (xfer_size % ep->dwc_ep.maxpacket); ++ } ++ } ++ diepdma = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepdma); ++ dieptsiz.b.xfersize = remain_to_transfer; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, dieptsiz.d32); ++ diepdma = ep->dwc_ep.dma_addr + (xfer_size - remain_to_transfer); ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, diepdma); ++ } ++ i = core_if->nextep_seq[i]; ++ } while (i != core_if->first_in_nextep_seq); ++ } else { // dma_desc_enable ++ DWC_PRINTF("%s Learning Queue not supported in DDMA\n", __func__); ++ } ++ ++ /* Restart transfers in predicted sequences */ ++ i = core_if->first_in_nextep_seq; ++ do { ++ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz); ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (dieptsiz.b.pktcnt != 0) { ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); ++ } ++ i = core_if->nextep_seq[i]; ++ } while (i != core_if->first_in_nextep_seq); ++ ++ /* Clear the global non-periodic IN NAK handshake */ ++ dctl.d32 = 0; ++ dctl.b.cgnpinnak = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ ++ /* Unmask EP Mismatch interrupt */ ++ gintmsk_data.d32 = 0; ++ gintmsk_data.b.epmismatch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk_data.d32); ++ ++ core_if->start_predict = 0; ++ ++ } ++} ++ ++/** ++ * Handler for the IN EP timeout handshake interrupt. ++ */ ++static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ ++#ifdef DEBUG ++ deptsiz_data_t dieptsiz = {.d32 = 0 }; ++ uint32_t num = 0; ++#endif ++ dctl_data_t dctl = {.d32 = 0 }; ++ dwc_otg_pcd_ep_t *ep; ++ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ ep = get_in_ep(pcd, epnum); ++ ++ /* Disable the NP Tx Fifo Empty Interrrupt */ ++ if (!core_if->dma_enable) { ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ } ++ /** @todo NGS Check EP type. ++ * Implement for Periodic EPs */ ++ /* ++ * Non-periodic EP ++ */ ++ /* Enable the Global IN NAK Effective Interrupt */ ++ intr_mask.b.ginnakeff = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32); ++ ++ /* Set Global IN NAK */ ++ dctl.b.sgnpinnak = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ ++ ep->stopped = 1; ++ ++#ifdef DEBUG ++ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[num]->dieptsiz); ++ DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n", ++ dieptsiz.b.pktcnt, dieptsiz.b.xfersize); ++#endif ++ ++#ifdef DISABLE_PERIODIC_EP ++ /* ++ * Set the NAK bit for this EP to ++ * start the disable process. ++ */ ++ diepctl.d32 = 0; ++ diepctl.b.snak = 1; ++ DWC_MODIFY_REG32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32, ++ diepctl.d32); ++ ep->disabling = 1; ++ ep->stopped = 1; ++#endif ++} ++ ++/** ++ * Handler for the IN EP NAK interrupt. ++ */ ++static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ /** @todo implement ISR */ ++ dwc_otg_core_if_t *core_if; ++ diepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "IN EP NAK"); ++ core_if = GET_CORE_IF(pcd); ++ intr_mask.b.nak = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ diepeachintmsk[epnum], intr_mask.d32, 0); ++ } else { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->diepmsk, ++ intr_mask.d32, 0); ++ } ++ ++ return 1; ++} ++ ++/** ++ * Handler for the OUT EP Babble interrupt. ++ */ ++static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ /** @todo implement ISR */ ++ dwc_otg_core_if_t *core_if; ++ doepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", ++ "OUT EP Babble"); ++ core_if = GET_CORE_IF(pcd); ++ intr_mask.b.babble = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[epnum], intr_mask.d32, 0); ++ } else { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, ++ intr_mask.d32, 0); ++ } ++ ++ return 1; ++} ++ ++/** ++ * Handler for the OUT EP NAK interrupt. ++ */ ++static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ /** @todo implement ISR */ ++ dwc_otg_core_if_t *core_if; ++ doepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_ANY, "INTERRUPT Handler not implemented for %s\n", "OUT EP NAK"); ++ core_if = GET_CORE_IF(pcd); ++ intr_mask.b.nak = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[epnum], intr_mask.d32, 0); ++ } else { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, ++ intr_mask.d32, 0); ++ } ++ ++ return 1; ++} ++ ++/** ++ * Handler for the OUT EP NYET interrupt. ++ */ ++static inline int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ /** @todo implement ISR */ ++ dwc_otg_core_if_t *core_if; ++ doepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NYET"); ++ core_if = GET_CORE_IF(pcd); ++ intr_mask.b.nyet = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[epnum], intr_mask.d32, 0); ++ } else { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, ++ intr_mask.d32, 0); ++ } ++ ++ return 1; ++} ++static void handle_xfercompl_iso_ddma (dwc_otg_dev_if_t *dev_if, dwc_otg_pcd_ep_t *ep) ++{ ++ depctl_data_t depctl; ++ dwc_ep_t *dwc_ep; ++ uint32_t doepdma; ++ dwc_dma_t dma_desc_addr; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ int index = 0; ++ uint8_t epnum; ++ ++ dwc_ep = &ep->dwc_ep; ++ epnum = dwc_ep->num; ++ ++ complete_ddma_iso_ep(ep); ++ ++ if (dwc_ep->is_in) { ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); ++ if (!depctl.b.epena) { ++ if (dwc_ep->use_add_buf) { ++ DWC_DEBUGPL(DBG_PCD, "go to second buffer \n"); ++ dwc_ep->use_add_buf = 0; ++ dwc_ep->iso_desc_first = 0; ++ if (dwc_ep->iso_desc_second) { ++ depctl_data_t diepctl; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepdma, ++ dwc_ep->dma_desc_addr1); ++ diepctl.d32 = 0; ++ diepctl.b.epena = 1; ++ diepctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&dev_if->in_ep_regs[epnum]->diepctl, ++ 0, diepctl.d32); ++ } else { ++ DWC_DEBUGPL(DBG_PCD, "DDMA: No more ISOC requests 1\n"); ++ } ++ } else { ++ DWC_DEBUGPL(DBG_PCD, "go to first buffer \n"); ++ dwc_ep->use_add_buf = 1; ++ dwc_ep->iso_desc_second = 0; ++ if (dwc_ep->iso_desc_first) { ++ depctl_data_t diepctl; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepdma, ++ dwc_ep->dma_desc_addr); ++ diepctl.d32 = 0; ++ diepctl.b.epena = 1; ++ diepctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&dev_if->in_ep_regs[epnum]->diepctl, ++ 0, diepctl.d32); ++ } else { ++ DWC_DEBUGPL(DBG_PCD, "DDMA: No more ISOC requests 2\n"); ++ } ++ } ++ } ++ } else { ++ depctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl); ++ doepdma = DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepdma); ++ ++ if (dwc_ep->use_add_buf) { ++ index = dwc_ep->iso_desc_first; ++ dma_desc_addr = dwc_ep->dma_desc_addr; ++ } else { ++ index = dwc_ep->iso_desc_second; ++ dma_desc_addr = dwc_ep->dma_desc_addr1; ++ } ++ ++ if (index == (doepdma - dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t)) { ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ DWC_MODIFY_REG32(&dev_if->out_ep_regs[epnum]->doepctl, 0, depctl.d32); ++ } ++ dma_desc = dwc_ep->desc_addr + dwc_ep->iso_desc_first; ++ if (!depctl.b.epena) { ++ if (dwc_ep->use_add_buf) { ++ DWC_DEBUGPL(DBG_PCD, "go to second buffer \n"); ++ dwc_ep->use_add_buf = 0; ++ dwc_ep->iso_desc_first = 0; ++ if (dwc_ep->iso_desc_second) { ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepdma, dwc_ep->dma_desc_addr1); ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&dev_if->out_ep_regs[epnum]->doepctl, 0, depctl.d32); ++ } else { ++ DWC_DEBUGPL(DBG_PCD, "DDMA: There are no more ISOC requests 1!!! \n"); ++ } ++ } else { ++ dwc_ep->use_add_buf = 1; ++ dwc_ep->iso_desc_second = 0; ++ if (dwc_ep->iso_desc_first) { ++ DWC_DEBUGPL(DBG_PCD, "go to first buffer"); ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepdma, dwc_ep->dma_desc_addr); ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&dev_if->out_ep_regs[epnum]->doepctl, 0, depctl.d32); ++ } else { ++ DWC_DEBUGPL(DBG_PCD, "DDMA: There are no more ISOC requests 2!!! \n"); ++ } ++ } ++ } ++ } ++} ++/** ++ * This interrupt indicates that an IN EP has a pending Interrupt. ++ * The sequence for handling the IN EP interrupt is shown below: ++ * -# Read the Device All Endpoint Interrupt register ++ * -# Repeat the following for each IN EP interrupt bit set (from ++ * LSB to MSB). ++ * -# Read the Device Endpoint Interrupt (DIEPINTn) register ++ * -# If "Transfer Complete" call the request complete function ++ * -# If "Endpoint Disabled" complete the EP disable procedure. ++ * -# If "AHB Error Interrupt" log error ++ * -# If "Time-out Handshake" log error ++ * -# If "IN Token Received when TxFIFO Empty" write packet to Tx ++ * FIFO. ++ * -# If "IN Token EP Mismatch" (disable, this is handled by EP ++ * Mismatch Interrupt) ++ */ ++static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd) ++{ ++#define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \ ++do { \ ++ diepint_data_t diepint = {.d32=0}; \ ++ diepint.b.__intr = 1; \ ++ DWC_WRITE_REG32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \ ++ diepint.d32); \ ++} while (0) ++ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ diepint_data_t diepint = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ uint32_t ep_intr; ++ uint32_t epnum = 0; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, pcd); ++ ++ /* Read in the device interrupt bits */ ++ ep_intr = dwc_otg_read_dev_all_in_ep_intr(core_if); ++ ++ /* Service the Device IN interrupts for each endpoint */ ++ while (ep_intr) { ++ if (ep_intr & 0x1) { ++ uint32_t empty_msk; ++ /* Get EP pointer */ ++ ep = get_in_ep(pcd, epnum); ++ dwc_ep = &ep->dwc_ep; ++ ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); ++ empty_msk = ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->dtknqr4_fifoemptymsk); ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "IN EP INTERRUPT - %d\nepmty_msk - %8x diepctl - %8x\n", ++ epnum, empty_msk, depctl.d32); ++ ++ DWC_DEBUGPL(DBG_PCD, ++ "EP%d-%s: type=%d, mps=%d\n", ++ dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"), ++ dwc_ep->type, dwc_ep->maxpacket); ++ ++ diepint.d32 = ++ dwc_otg_read_dev_in_ep_intr(core_if, dwc_ep); ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "EP %d Interrupt Register - 0x%x\n", epnum, ++ diepint.d32); ++ /* Transfer complete */ ++ if (diepint.b.xfercompl) { ++ /* Disable the NP Tx FIFO Empty ++ * Interrupt */ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32 ++ (&core_if->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ } else { ++ /* Disable the Tx FIFO Empty Interrupt for this EP */ ++ uint32_t fifoemptymsk = ++ 0x1 << dwc_ep->num; ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ fifoemptymsk, 0); ++ } ++ /* Clear the bit in DIEPINTn for this interrupt */ ++ CLEAR_IN_EP_INTR(core_if, epnum, xfercompl); ++ ++ /* Complete the transfer */ ++ if (epnum == 0) { ++ handle_ep0(pcd); ++ } ++#ifdef DWC_EN_ISOC ++ else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (!ep->stopped) ++ complete_iso_ep(pcd, ep); ++ } ++#endif /* DWC_EN_ISOC */ ++#ifdef DWC_UTE_PER_IO ++ else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (!ep->stopped) ++ complete_xiso_ep(ep); ++ } ++#endif /* DWC_UTE_PER_IO */ ++ else { ++ if (core_if->dma_desc_enable && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ handle_xfercompl_iso_ddma(dev_if, ep); ++ } else { ++ if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC && ++ dwc_ep->bInterval > 1) { ++ dwc_ep->frame_num += dwc_ep->bInterval; ++ if (dwc_ep->frame_num > 0x3FFF) ++ { ++ dwc_ep->frm_overrun = 1; ++ dwc_ep->frame_num &= 0x3FFF; ++ } else ++ dwc_ep->frm_overrun = 0; ++ } ++ complete_ep(ep); ++ if(diepint.b.nak) ++ CLEAR_IN_EP_INTR(core_if, epnum, nak); ++ } ++ } ++ } ++ /* Endpoint disable */ ++ if (diepint.b.epdisabled) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d IN disabled\n", ++ epnum); ++ handle_in_ep_disable_intr(pcd, epnum); ++ ++ /* Clear the bit in DIEPINTn for this interrupt */ ++ CLEAR_IN_EP_INTR(core_if, epnum, epdisabled); ++ } ++ /* AHB Error */ ++ if (diepint.b.ahberr) { ++ DWC_ERROR("EP%d IN AHB Error\n", epnum); ++ /* Clear the bit in DIEPINTn for this interrupt */ ++ CLEAR_IN_EP_INTR(core_if, epnum, ahberr); ++ } ++ /* TimeOUT Handshake (non-ISOC IN EPs) */ ++ if (diepint.b.timeout) { ++ DWC_ERROR("EP%d IN Time-out\n", epnum); ++ handle_in_ep_timeout_intr(pcd, epnum); ++ ++ CLEAR_IN_EP_INTR(core_if, epnum, timeout); ++ } ++ /** IN Token received with TxF Empty */ ++ if (diepint.b.intktxfemp) { ++ DWC_DEBUGPL(DBG_ANY, ++ "EP%d IN TKN TxFifo Empty\n", ++ epnum); ++ if (!ep->stopped && epnum != 0) { ++ ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ diepmsk.b.intktxfemp = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32 ++ (&dev_if->dev_global_regs->diepeachintmsk ++ [epnum], diepmsk.d32, 0); ++ } else { ++ DWC_MODIFY_REG32 ++ (&dev_if->dev_global_regs->diepmsk, ++ diepmsk.d32, 0); ++ } ++ } else if (core_if->dma_desc_enable ++ && epnum == 0 ++ && pcd->ep0state == ++ EP0_OUT_STATUS_PHASE) { ++ // EP0 IN set STALL ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs ++ [epnum]->diepctl); ++ ++ /* set the disable and stall bits */ ++ if (depctl.b.epena) { ++ depctl.b.epdis = 1; ++ } ++ depctl.b.stall = 1; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs ++ [epnum]->diepctl, ++ depctl.d32); ++ } ++ CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp); ++ } ++ /** IN Token Received with EP mismatch */ ++ if (diepint.b.intknepmis) { ++ DWC_DEBUGPL(DBG_ANY, ++ "EP%d IN TKN EP Mismatch\n", epnum); ++ CLEAR_IN_EP_INTR(core_if, epnum, intknepmis); ++ } ++ /** IN Endpoint NAK Effective */ ++ if (diepint.b.inepnakeff) { ++ DWC_DEBUGPL(DBG_ANY, ++ "EP%d IN EP NAK Effective\n", ++ epnum); ++ /* Periodic EP */ ++ if (ep->disabling) { ++ depctl.d32 = 0; ++ depctl.b.snak = 1; ++ depctl.b.epdis = 1; ++ DWC_MODIFY_REG32(&dev_if->in_ep_regs ++ [epnum]->diepctl, ++ depctl.d32, ++ depctl.d32); ++ } ++ CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff); ++ ++ } ++ ++ /** IN EP Tx FIFO Empty Intr */ ++ if (diepint.b.emptyintr) { ++ DWC_DEBUGPL(DBG_ANY, ++ "EP%d Tx FIFO Empty Intr \n", ++ epnum); ++ write_empty_tx_fifo(pcd, epnum); ++ ++ CLEAR_IN_EP_INTR(core_if, epnum, emptyintr); ++ ++ } ++ ++ /** IN EP BNA Intr */ ++ if (diepint.b.bna) { ++ CLEAR_IN_EP_INTR(core_if, epnum, bna); ++ if (core_if->dma_desc_enable) { ++#ifdef DWC_EN_ISOC ++ if (dwc_ep->type == ++ DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * This checking is performed to prevent first "false" BNA ++ * handling occuring right after reconnect ++ */ ++ if (dwc_ep->next_frame != ++ 0xffffffff) ++ dwc_otg_pcd_handle_iso_bna(ep); ++ } else ++#endif /* DWC_EN_ISOC */ ++ { ++ dwc_otg_pcd_handle_noniso_bna(ep); ++ } ++ } ++ } ++ /* NAK Interrupt */ ++ if (diepint.b.nak) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n", ++ epnum); ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ if (core_if->dma_desc_enable) { ++ if (ep->dwc_ep.frame_num == 0xFFFFFFFF) { ++ ep->dwc_ep.frame_num = core_if->frame_num; ++ dwc_otg_pcd_start_iso_ddma(core_if, ep); ++ } else { ++ CLEAR_IN_EP_INTR(core_if, epnum, nak); ++ } ++ } else { ++ depctl_data_t depctl; ++ if (ep->dwc_ep.frame_num == 0xFFFFFFFF) { ++ ep->dwc_ep.frame_num = core_if->frame_num; ++ if (ep->dwc_ep.bInterval > 1) { ++ depctl.d32 = 0; ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); ++ if (ep->dwc_ep.frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ depctl.b.setd0pid = 0; ++ } else { ++ depctl.b.setd0pid = 1; ++ depctl.b.setd1pid = 0; ++ } ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepctl, depctl.d32); ++ } ++ start_next_request(ep); ++ } ++ ep->dwc_ep.frame_num += ep->dwc_ep.bInterval; ++ if (dwc_ep->frame_num > 0x3FFF) { ++ dwc_ep->frm_overrun = 1; ++ dwc_ep->frame_num &= 0x3FFF; ++ } else { ++ dwc_ep->frm_overrun = 0; ++ } ++ } ++ } ++ ++ CLEAR_IN_EP_INTR(core_if, epnum, nak); ++ } ++ } ++ epnum++; ++ ep_intr >>= 1; ++ } ++ ++ return 1; ++#undef CLEAR_IN_EP_INTR ++} ++ ++/** ++ * This interrupt indicates that an OUT EP has a pending Interrupt. ++ * The sequence for handling the OUT EP interrupt is shown below: ++ * -# Read the Device All Endpoint Interrupt register ++ * -# Repeat the following for each OUT EP interrupt bit set (from ++ * LSB to MSB). ++ * -# Read the Device Endpoint Interrupt (DOEPINTn) register ++ * -# If "Transfer Complete" call the request complete function ++ * -# If "Endpoint Disabled" complete the EP disable procedure. ++ * -# If "AHB Error Interrupt" log error ++ * -# If "Setup Phase Done" process Setup Packet (See Standard USB ++ * Command Processing) ++ */ ++static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd) ++{ ++#define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \ ++do { \ ++ doepint_data_t doepint = {.d32=0}; \ ++ doepint.b.__intr = 1; \ ++ DWC_WRITE_REG32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \ ++ doepint.d32); \ ++} while (0) ++ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ uint32_t ep_intr; ++ doepint_data_t doepint = {.d32 = 0 }; ++ uint32_t epnum = 0; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ dctl_data_t dctl = {.d32 = 0 }; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__); ++ ++ /* Read in the device interrupt bits */ ++ ep_intr = dwc_otg_read_dev_all_out_ep_intr(core_if); ++ ++ while (ep_intr) { ++ if (ep_intr & 0x1) { ++ /* Get EP pointer */ ++ ep = get_out_ep(pcd, epnum); ++ dwc_ep = &ep->dwc_ep; ++ ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, ++ "EP%d-%s: type=%d, mps=%d\n", ++ dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"), ++ dwc_ep->type, dwc_ep->maxpacket); ++#endif ++ doepint.d32 = ++ dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep); ++ ++ /* Transfer complete */ ++ if (doepint.b.xfercompl) { ++ ++ if (epnum == 0) { ++ /* Clear the bit in DOEPINTn for this interrupt */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl); ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ DWC_DEBUGPL(DBG_PCDV, "in xfer xomplete DOEPINT=%x doepint=%x\n", ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepint), ++ doepint.d32); ++ DWC_DEBUGPL(DBG_PCDV, "DOEPCTL=%x \n", ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepctl)); ++ ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a ++ && core_if->dma_enable == 0) { ++ doepint_data_t doepint; ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepint); ++ if (pcd->ep0state == EP0_IDLE && doepint.b.sr) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, sr); ++ if (doepint.b.stsphsercvd) ++ CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd); ++ goto exit_xfercompl; ++ } ++ } ++ /* In case of DDMA look at SR bit to go to the Data Stage */ ++ if (core_if->dma_desc_enable) { ++ dev_dma_desc_sts_t status = {.d32 = 0}; ++ if (pcd->ep0state == EP0_IDLE) { ++ status.d32 = core_if->dev_if->setup_desc_addr[core_if-> ++ dev_if->setup_desc_index]->status.d32; ++ if(pcd->data_terminated) { ++ pcd->data_terminated = 0; ++ status.d32 = core_if->dev_if->out_desc_addr->status.d32; ++ dwc_memcpy(&pcd->setup_pkt->req, pcd->backup_buf, 8); ++ } ++ if (status.b.sr) { ++ if (doepint.b.setup) { ++ DWC_DEBUGPL(DBG_PCDV, "DMA DESC EP0_IDLE SR=1 setup=1\n"); ++ /* Already started data stage, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ /* Prepare for more setup packets */ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE || ++ pcd->ep0state == EP0_IN_DATA_PHASE) { ++ ep0_out_start(core_if, pcd); ++ } ++ ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ DWC_DEBUGPL(DBG_PCDV, ++ "EP0_IDLE SR=1 setup=0 new setup comes\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ } else { ++ dwc_otg_pcd_request_t *req; ++ dev_dma_desc_sts_t status = {.d32 = 0}; ++ diepint_data_t diepint0; ++ diepint0.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ ++ if (pcd->ep0state == EP0_STALL || pcd->ep0state == EP0_DISCONNECT) { ++ DWC_ERROR("EP0 is stalled/disconnected\n"); ++ } ++ ++ /* Clear IN xfercompl if set */ ++ if (diepint0.b.xfercompl && (pcd->ep0state == EP0_IN_STATUS_PHASE ++ || pcd->ep0state == EP0_IN_DATA_PHASE)) { ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint, diepint0.d32); ++ } ++ ++ status.d32 = core_if->dev_if->setup_desc_addr[core_if-> ++ dev_if->setup_desc_index]->status.d32; ++ ++ if ((pcd->ep0state == EP0_OUT_STATUS_PHASE) || ++ (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len ++ && pcd->ep0state == EP0_OUT_DATA_PHASE)) ++ status.d32 = core_if->dev_if->out_desc_addr->status.d32; ++ if (status.b.sr) { ++ if (DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n"); ++ } else { ++ DWC_DEBUGPL(DBG_PCDV, "complete req!!\n"); ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len && ++ pcd->ep0state == EP0_OUT_DATA_PHASE) { ++ /* Read arrived setup packet from req->buf */ ++ dwc_memcpy(&pcd->setup_pkt->req, ++ req->buf + ep->dwc_ep.xfer_count, 8); ++ } ++ req->actual = ep->dwc_ep.xfer_count; ++ dwc_otg_request_done(ep, req, -ECONNRESET); ++ ep->dwc_ep.start_xfer_buff = 0; ++ ep->dwc_ep.xfer_buff = 0; ++ ep->dwc_ep.xfer_len = 0; ++ } ++ pcd->ep0state = EP0_IDLE; ++ if (doepint.b.setup) { ++ DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n"); ++ /* Data stage started, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ /* Prepare for setup packets if ep0in was enabled*/ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ ep0_out_start(core_if, pcd); ++ } ++ ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ DWC_DEBUGPL(DBG_PCDV, ++ "EP0_IDLE SR=1 setup=0 new setup comes 2\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ } ++ } ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a && core_if->dma_enable ++ && core_if->dma_desc_enable == 0) { ++ doepint_data_t doepint_temp = {.d32 = 0}; ++ deptsiz0_data_t doeptsize0 = {.d32 = 0 }; ++ doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->dwc_ep.num]->doepint); ++ doeptsize0.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->dwc_ep.num]->doeptsiz); ++ if (((ep->dwc_ep.xfer_count == ep->dwc_ep.total_len || doeptsize0.b.xfersize == 64) && ++ pcd->ep0state == EP0_OUT_DATA_PHASE && doepint.b.stsphsercvd) || ++ (doeptsize0.b.xfersize == 24 && pcd->ep0state == EP0_IN_STATUS_PHASE)) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl); ++ DWC_DEBUGPL(DBG_PCDV, "WA for xfercompl along with stsphs \n"); ++ doepint.b.xfercompl = 0; ++ ep0_out_start(core_if, pcd); ++ goto exit_xfercompl; ++ } ++ ++ if (pcd->ep0state == EP0_IDLE) { ++ if (doepint_temp.b.sr) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, sr); ++ } ++ /* Delay is needed for core to update setup ++ * packet count from 3 to 2 after receiving ++ * setup packet*/ ++ dwc_udelay(100); ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepint); ++ if (doeptsize0.b.supcnt == 3) { ++ DWC_DEBUGPL(DBG_ANY, "Rolling over!!!!!!!\n"); ++ ep->dwc_ep.stp_rollover = 1; ++ } ++ if (doepint.b.setup) { ++retry: ++ /* Already started data stage, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ ep->dwc_ep.stp_rollover = 0; ++ /* Prepare for more setup packets */ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE || ++ pcd->ep0state == EP0_IN_DATA_PHASE) { ++ depctl_data_t depctl = {.d32 = 0}; ++ depctl.b.cnak = 1; ++ ep0_out_start(core_if, pcd); ++ /* Core not updating setup packet count ++ * in case of PET testing - @TODO vahrama ++ * to check with HW team further */ ++ if (!core_if->otg_ver) { ++ DWC_MODIFY_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepctl, 0, depctl.d32); ++ } ++ } ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ DWC_DEBUGPL(DBG_ANY, ++ "EP0_IDLE SR=1 setup=0 new setup comes\n"); ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepint); ++ if(doepint.b.setup) ++ goto retry; ++ ep0_out_start(core_if, pcd); ++ } ++ } else { ++ dwc_otg_pcd_request_t *req; ++ diepint_data_t diepint0 = {.d32 = 0}; ++ doepint_data_t doepint_temp = {.d32 = 0}; ++ depctl_data_t diepctl0; ++ diepint0.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ diepctl0.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepctl); ++ ++ if (pcd->ep0state == EP0_IN_DATA_PHASE ++ || pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ if (diepint0.b.xfercompl) { ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint, diepint0.d32); ++ } ++ if (diepctl0.b.epena) { ++ diepint_data_t diepint = {.d32 = 0}; ++ diepctl0.b.snak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepctl, diepctl0.d32); ++ do { ++ dwc_udelay(10); ++ diepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ } while (!diepint.b.inepnakeff); ++ diepint.b.inepnakeff = 1; ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint, diepint.d32); ++ diepctl0.d32 = 0; ++ diepctl0.b.epdis = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl, ++ diepctl0.d32); ++ do { ++ dwc_udelay(10); ++ diepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ } while (!diepint.b.epdisabled); ++ diepint.b.epdisabled = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepint, ++ diepint.d32); ++ } ++ } ++ doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->dwc_ep.num]->doepint); ++ if (doepint_temp.b.sr) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, sr); ++ if (DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n"); ++ } else { ++ DWC_DEBUGPL(DBG_PCDV, "complete req!!\n"); ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len && ++ pcd->ep0state == EP0_OUT_DATA_PHASE) { ++ /* Read arrived setup packet from req->buf */ ++ dwc_memcpy(&pcd->setup_pkt->req, ++ req->buf + ep->dwc_ep.xfer_count, 8); ++ } ++ req->actual = ep->dwc_ep.xfer_count; ++ dwc_otg_request_done(ep, req, -ECONNRESET); ++ ep->dwc_ep.start_xfer_buff = 0; ++ ep->dwc_ep.xfer_buff = 0; ++ ep->dwc_ep.xfer_len = 0; ++ } ++ pcd->ep0state = EP0_IDLE; ++ if (doepint.b.setup) { ++ DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n"); ++ /* Data stage started, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ /* Prepare for setup packets if ep0in was enabled*/ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ depctl_data_t depctl = {.d32 = 0}; ++ depctl.b.cnak = 1; ++ ep0_out_start(core_if, pcd); ++ /* Core not updating setup packet count ++ * in case of PET testing - @TODO vahrama ++ * to check with HW team further */ ++ if (!core_if->otg_ver) { ++ DWC_MODIFY_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepctl, 0, depctl.d32); ++ } ++ } ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ DWC_DEBUGPL(DBG_PCDV, ++ "EP0_IDLE SR=1 setup=0 new setup comes 2\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ } ++ } ++ if (core_if->dma_enable == 0 || pcd->ep0state != EP0_IDLE) ++ handle_ep0(pcd); ++exit_xfercompl: ++ DWC_DEBUGPL(DBG_PCDV, "after DOEPINT=%x doepint=%x\n", ++ dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep), doepint.d32); ++ } else { ++ if (core_if->dma_desc_enable == 0 ++ || pcd->ep0state != EP0_IDLE) ++ handle_ep0(pcd); ++ } ++#ifdef DWC_EN_ISOC ++ } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (doepint.b.pktdrpsts == 0) { ++ /* Clear the bit in DOEPINTn for this interrupt */ ++ CLEAR_OUT_EP_INTR(core_if, ++ epnum, ++ xfercompl); ++ complete_iso_ep(pcd, ep); ++ } else { ++ ++ doepint_data_t doepint = {.d32 = 0 }; ++ doepint.b.xfercompl = 1; ++ doepint.b.pktdrpsts = 1; ++ DWC_WRITE_REG32 ++ (&core_if->dev_if->out_ep_regs ++ [epnum]->doepint, ++ doepint.d32); ++ if (handle_iso_out_pkt_dropped ++ (core_if, dwc_ep)) { ++ complete_iso_ep(pcd, ++ ep); ++ } ++ } ++#endif /* DWC_EN_ISOC */ ++#ifdef DWC_UTE_PER_IO ++ } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl); ++ if (!ep->stopped) ++ complete_xiso_ep(ep); ++#endif /* DWC_UTE_PER_IO */ ++ } else { ++ /* Clear the bit in DOEPINTn for this interrupt */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, ++ xfercompl); ++ ++ if (core_if->core_params->dev_out_nak) { ++ DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[epnum]); ++ pcd->core_if->ep_xfer_info[epnum].state = 0; ++#ifdef DEBUG ++ print_memory_payload(pcd, dwc_ep); ++#endif ++ } ++ if (core_if->dma_desc_enable && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ handle_xfercompl_iso_ddma(core_if->dev_if, ep); ++ } else { ++ complete_ep(ep); ++ } ++ } ++ ++ } ++ if (doepint.b.stsphsercvd) { ++ deptsiz0_data_t deptsiz; ++ CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd); ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doeptsiz); ++ if ((core_if->dma_desc_enable) || (core_if->dma_enable && ++ core_if->snpsid >= OTG_CORE_REV_3_00a)) { ++ do_setup_in_status_phase(pcd); ++ } ++ } ++ ++ /* Endpoint disable */ ++ if (doepint.b.epdisabled) { ++ ++ /* Clear the bit in DOEPINTn for this interrupt */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled); ++ if (core_if->core_params->dev_out_nak) { ++#ifdef DEBUG ++ print_memory_payload(pcd, dwc_ep); ++#endif ++ /* In case of timeout condition */ ++ if (core_if->ep_xfer_info[epnum].state == 2) { ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dctl); ++ dctl.b.cgoutnak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ /* Unmask goutnakeff interrupt which was masked ++ * during handle nak out interrupt */ ++ gintmsk.b.goutnakeff = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, ++ 0, gintmsk.d32); ++ ++ complete_ep(ep); ++ } ++ } ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ++ { ++ dctl_data_t dctl; ++ gintmsk_data_t intr_mask = {.d32 = 0}; ++ dwc_otg_pcd_request_t *req = 0; ++ ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dctl); ++ dctl.b.cgoutnak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ ++ intr_mask.d32 = 0; ++ intr_mask.b.incomplisoout = 1; ++ ++ /* Get any pending requests */ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); ++ } else { ++ dwc_otg_request_done(ep, req, 0); ++ start_next_request(ep); ++ } ++ } else { ++ DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); ++ } ++ } ++ } ++ /* AHB Error */ ++ if (doepint.b.ahberr) { ++ DWC_ERROR("EP%d OUT AHB Error\n", epnum); ++ DWC_ERROR("EP%d DEPDMA=0x%08x \n", ++ epnum, core_if->dev_if->out_ep_regs[epnum]->doepdma); ++ CLEAR_OUT_EP_INTR(core_if, epnum, ahberr); ++ } ++ /* Setup Phase Done (contorl EPs) */ ++ if (doepint.b.setup) { ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n", epnum); ++#endif ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ ++ handle_ep0(pcd); ++ } ++ ++ /** OUT EP BNA Intr */ ++ if (doepint.b.bna) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, bna); ++ if (core_if->dma_desc_enable) { ++#ifdef DWC_EN_ISOC ++ if (dwc_ep->type == ++ DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * This checking is performed to prevent first "false" BNA ++ * handling occuring right after reconnect ++ */ ++ if (dwc_ep->next_frame != ++ 0xffffffff) ++ dwc_otg_pcd_handle_iso_bna(ep); ++ } else ++#endif /* DWC_EN_ISOC */ ++ if (ep->dwc_ep.type != DWC_OTG_EP_TYPE_ISOC) { ++ dwc_otg_pcd_handle_noniso_bna(ep); ++ } ++ } ++ } ++ /* Babble Interrupt */ ++ if (doepint.b.babble) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d OUT Babble\n", ++ epnum); ++ handle_out_ep_babble_intr(pcd, epnum); ++ ++ CLEAR_OUT_EP_INTR(core_if, epnum, babble); ++ } ++ if (doepint.b.outtknepdis) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d OUT Token received when EP is \ ++ disabled\n",epnum); ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ if (core_if->dma_desc_enable) { ++ if (!ep->dwc_ep.iso_transfer_started) { ++ ep->dwc_ep.frame_num = core_if->frame_num; ++ dwc_otg_pcd_start_iso_ddma(core_if, ep); ++ } ++ } else { ++ doepmsk_data_t doepmsk = {.d32 = 0}; ++ ep->dwc_ep.frame_num = core_if->frame_num; ++ if (ep->dwc_ep.bInterval > 1) { ++ depctl_data_t depctl; ++ depctl.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[epnum]->doepctl); ++ if (ep->dwc_ep.frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ depctl.b.setd0pid = 0; ++ } else { ++ depctl.b.setd0pid = 1; ++ depctl.b.setd1pid = 0; ++ } ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ out_ep_regs[epnum]->doepctl, depctl.d32); ++ } ++ ++ start_next_request(ep); ++ doepmsk.b.outtknepdis = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, ++ doepmsk.d32, 0); ++ } ++ } ++ CLEAR_OUT_EP_INTR(core_if, epnum, outtknepdis); ++ } ++ ++ /* NAK Interrutp */ ++ if (doepint.b.nak) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d OUT NAK\n", epnum); ++ handle_out_ep_nak_intr(pcd, epnum); ++ ++ CLEAR_OUT_EP_INTR(core_if, epnum, nak); ++ } ++ /* NYET Interrutp */ ++ if (doepint.b.nyet) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d OUT NYET\n", epnum); ++ handle_out_ep_nyet_intr(pcd, epnum); ++ ++ CLEAR_OUT_EP_INTR(core_if, epnum, nyet); ++ } ++ } ++ ++ epnum++; ++ ep_intr >>= 1; ++ } ++ ++ return 1; ++ ++#undef CLEAR_OUT_EP_INTR ++} ++static int drop_transfer(uint32_t trgt_fr, uint32_t curr_fr, uint8_t frm_overrun) ++{ ++ int retval = 0; ++ if(!frm_overrun && curr_fr >= trgt_fr) ++ retval = 1; ++ else if (frm_overrun ++ && (curr_fr >= trgt_fr && ((curr_fr - trgt_fr) < 0x3FFF / 2))) ++ retval = 1; ++ return retval; ++} ++ ++/** ++ * Incomplete ISO IN Transfer Interrupt. ++ * This interrupt indicates one of the following conditions occurred ++ * while transmitting an ISOC transaction. ++ * - Corrupted IN Token for ISOC EP. ++ * - Packet not complete in FIFO. ++ * The follow actions will be taken: ++ * -# Determine the EP ++ * -# Set incomplete flag in dwc_ep structure ++ * -# Disable EP; when "Endpoint Disabled" interrupt is received ++ * Flush FIFO ++ */ ++int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintsts_data_t gintsts; ++ ++#ifdef DWC_EN_ISOC ++ dwc_otg_dev_if_t *dev_if; ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dsts_data_t dsts = {.d32 = 0 }; ++ dwc_ep_t *dwc_ep; ++ int i; ++ ++ dev_if = GET_CORE_IF(pcd)->dev_if; ++ ++ for (i = 1; i <= dev_if->num_in_eps; ++i) { ++ dwc_ep = &pcd->in_ep[i].dwc_ep; ++ if (dwc_ep->active && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ deptsiz.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz); ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ ++ if (depctl.b.epdis && deptsiz.d32) { ++ set_current_pkt_info(GET_CORE_IF(pcd), dwc_ep); ++ if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { ++ dwc_ep->cur_pkt = 0; ++ dwc_ep->proc_buf_num = ++ (dwc_ep->proc_buf_num ^ 1) & 0x1; ++ ++ if (dwc_ep->proc_buf_num) { ++ dwc_ep->cur_pkt_addr = ++ dwc_ep->xfer_buff1; ++ dwc_ep->cur_pkt_dma_addr = ++ dwc_ep->dma_addr1; ++ } else { ++ dwc_ep->cur_pkt_addr = ++ dwc_ep->xfer_buff0; ++ dwc_ep->cur_pkt_dma_addr = ++ dwc_ep->dma_addr0; ++ } ++ ++ } ++ ++ dsts.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ dev_global_regs->dsts); ++ dwc_ep->next_frame = dsts.b.soffn; ++ ++ dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF ++ (pcd), ++ dwc_ep); ++ } ++ } ++ } ++ ++#else ++ depctl_data_t depctl = {.d32 = 0 }; ++ dwc_ep_t *dwc_ep; ++ dwc_otg_dev_if_t *dev_if; ++ int i; ++ dev_if = GET_CORE_IF(pcd)->dev_if; ++ ++ DWC_DEBUGPL(DBG_PCD,"Incomplete ISO IN \n"); ++ ++ for (i = 1; i <= dev_if->num_in_eps; ++i) { ++ dwc_ep = &pcd->in_ep[i-1].dwc_ep; ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (depctl.b.epena && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (drop_transfer(dwc_ep->frame_num, GET_CORE_IF(pcd)->frame_num, ++ dwc_ep->frm_overrun)) ++ { ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ depctl.b.snak = 1; ++ depctl.b.epdis = 1; ++ DWC_MODIFY_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32, depctl.d32); ++ } ++ } ++ } ++ ++ /*intr_mask.b.incomplisoin = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); */ ++#endif //DWC_EN_ISOC ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.incomplisoin = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * Incomplete ISO OUT Transfer Interrupt. ++ * ++ * This interrupt indicates that the core has dropped an ISO OUT ++ * packet. The following conditions can be the cause: ++ * - FIFO Full, the entire packet would not fit in the FIFO. ++ * - CRC Error ++ * - Corrupted Token ++ * The follow actions will be taken: ++ * -# Determine the EP ++ * -# Set incomplete flag in dwc_ep structure ++ * -# Read any data from the FIFO ++ * -# Disable EP. When "Endpoint Disabled" interrupt is received ++ * re-enable EP. ++ */ ++int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd) ++{ ++ ++ gintsts_data_t gintsts; ++ ++#ifdef DWC_EN_ISOC ++ dwc_otg_dev_if_t *dev_if; ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dsts_data_t dsts = {.d32 = 0 }; ++ dwc_ep_t *dwc_ep; ++ int i; ++ ++ dev_if = GET_CORE_IF(pcd)->dev_if; ++ ++ for (i = 1; i <= dev_if->num_out_eps; ++i) { ++ dwc_ep = &pcd->in_ep[i].dwc_ep; ++ if (pcd->out_ep[i].dwc_ep.active && ++ pcd->out_ep[i].dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ deptsiz.d32 = ++ DWC_READ_REG32(&dev_if->out_ep_regs[i]->doeptsiz); ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); ++ ++ if (depctl.b.epdis && deptsiz.d32) { ++ set_current_pkt_info(GET_CORE_IF(pcd), ++ &pcd->out_ep[i].dwc_ep); ++ if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { ++ dwc_ep->cur_pkt = 0; ++ dwc_ep->proc_buf_num = ++ (dwc_ep->proc_buf_num ^ 1) & 0x1; ++ ++ if (dwc_ep->proc_buf_num) { ++ dwc_ep->cur_pkt_addr = ++ dwc_ep->xfer_buff1; ++ dwc_ep->cur_pkt_dma_addr = ++ dwc_ep->dma_addr1; ++ } else { ++ dwc_ep->cur_pkt_addr = ++ dwc_ep->xfer_buff0; ++ dwc_ep->cur_pkt_dma_addr = ++ dwc_ep->dma_addr0; ++ } ++ ++ } ++ ++ dsts.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ dev_global_regs->dsts); ++ dwc_ep->next_frame = dsts.b.soffn; ++ ++ dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF ++ (pcd), ++ dwc_ep); ++ } ++ } ++ } ++#else ++ /** @todo implement ISR */ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if; ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ dwc_ep_t *dwc_ep = NULL; ++ int i; ++ core_if = GET_CORE_IF(pcd); ++ ++ for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { ++ dwc_ep = &pcd->out_ep[i].dwc_ep; ++ depctl.d32 = ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl); ++ if (depctl.b.epena && depctl.b.dpid == (core_if->frame_num & 0x1)) { ++ core_if->dev_if->isoc_ep = dwc_ep; ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz); ++ break; ++ } ++ } ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ intr_mask.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ ++ if (!intr_mask.b.goutnakeff) { ++ /* Unmask it */ ++ intr_mask.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32); ++ } ++ if (!gintsts.b.goutnakeff) { ++ dctl.b.sgoutnak = 1; ++ } ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++ ++ depctl.d32 = DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl); ++ if (depctl.b.epena) { ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ } ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl, depctl.d32); ++ ++ intr_mask.d32 = 0; ++ intr_mask.b.incomplisoout = 1; ++ ++#endif /* DWC_EN_ISOC */ ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.incomplisoout = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This function handles the Global IN NAK Effective interrupt. ++ * ++ */ ++int32_t dwc_otg_pcd_handle_in_nak_effective(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ depctl_data_t diepctl = {.d32 = 0 }; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ int i; ++ ++ DWC_DEBUGPL(DBG_PCD, "Global IN NAK Effective\n"); ++ ++ /* Disable all active IN EPs */ ++ for (i = 0; i <= dev_if->num_in_eps; i++) { ++ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (!(diepctl.b.eptype & 1) && diepctl.b.epena) { ++ if (core_if->start_predict > 0) ++ core_if->start_predict++; ++ diepctl.b.epdis = 1; ++ diepctl.b.snak = 1; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, diepctl.d32); ++ } ++ } ++ ++ ++ /* Disable the Global IN NAK Effective Interrupt */ ++ intr_mask.b.ginnakeff = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.ginnakeff = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * OUT NAK Effective. ++ * ++ */ ++int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ depctl_data_t doepctl; ++ int i; ++ ++ /* Disable the Global OUT NAK Effective Interrupt */ ++ intr_mask.b.goutnakeff = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* If DEV OUT NAK enabled */ ++ if (pcd->core_if->core_params->dev_out_nak) { ++ /* Run over all out endpoints to determine the ep number on ++ * which the timeout has happened ++ */ ++ for (i = 0; i <= dev_if->num_out_eps; i++) { ++ if (pcd->core_if->ep_xfer_info[i].state == 2) ++ break; ++ } ++ if (i > dev_if->num_out_eps) { ++ dctl_data_t dctl; ++ dctl.d32 = ++ DWC_READ_REG32(&dev_if->dev_global_regs->dctl); ++ dctl.b.cgoutnak = 1; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ goto out; ++ } ++ ++ /* Disable the endpoint */ ++ doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); ++ if (doepctl.b.epena) { ++ doepctl.b.epdis = 1; ++ doepctl.b.snak = 1; ++ } ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32); ++ return 1; ++ } ++ /* We come here from Incomplete ISO OUT handler */ ++ if (dev_if->isoc_ep) { ++ dwc_ep_t *dwc_ep = (dwc_ep_t *) dev_if->isoc_ep; ++ uint32_t epnum = dwc_ep->num; ++ doepint_data_t doepint; ++ doepint.d32 = ++ DWC_READ_REG32(&dev_if->out_ep_regs[dwc_ep->num]->doepint); ++ dev_if->isoc_ep = NULL; ++ doepctl.d32 = ++ DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl); ++ DWC_PRINTF("Before disable DOEPCTL = %08x\n", doepctl.d32); ++ if (doepctl.b.epena) { ++ doepctl.b.epdis = 1; ++ doepctl.b.snak = 1; ++ } ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepctl, ++ doepctl.d32); ++ return 1; ++ } else ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", ++ "Global OUT NAK Effective\n"); ++ ++out: ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * PCD interrupt handler. ++ * ++ * The PCD handles the device interrupts. Many conditions can cause a ++ * device interrupt. When an interrupt occurs, the device interrupt ++ * service routine determines the cause of the interrupt and ++ * dispatches handling to the appropriate function. These interrupt ++ * handling functions are described below. ++ * ++ * All interrupt registers are processed from LSB to MSB. ++ * ++ */ ++int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++#ifdef VERBOSE ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++#endif ++ gintsts_data_t gintr_status; ++ int32_t retval = 0; ++ ++ if (dwc_otg_check_haps_status(core_if) == -1 ) { ++ DWC_WARN("HAPS is disconnected"); ++ return retval; ++ } ++ ++ /* Exit from ISR if core is hibernated */ ++ if (core_if->hibernation_suspend == 1) { ++ return retval; ++ } ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_ANY, "%s() gintsts=%08x gintmsk=%08x\n", ++ __func__, ++ DWC_READ_REG32(&global_regs->gintsts), ++ DWC_READ_REG32(&global_regs->gintmsk)); ++#endif ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ DWC_SPINLOCK(pcd->lock); ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%08x gintmsk=%08x\n", ++ __func__, ++ DWC_READ_REG32(&global_regs->gintsts), ++ DWC_READ_REG32(&global_regs->gintmsk)); ++#endif ++ ++ gintr_status.d32 = dwc_otg_read_core_intr(core_if); ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s: gintsts&gintmsk=%08x\n", ++ __func__, gintr_status.d32); ++ ++ if (gintr_status.b.sofintr) { ++ retval |= dwc_otg_pcd_handle_sof_intr(pcd); ++ } ++ if (gintr_status.b.rxstsqlvl) { ++ retval |= ++ dwc_otg_pcd_handle_rx_status_q_level_intr(pcd); ++ } ++ if (gintr_status.b.nptxfempty) { ++ retval |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr(pcd); ++ } ++ if (gintr_status.b.goutnakeff) { ++ retval |= dwc_otg_pcd_handle_out_nak_effective(pcd); ++ } ++ if (gintr_status.b.i2cintr) { ++ retval |= dwc_otg_pcd_handle_i2c_intr(pcd); ++ } ++ if (gintr_status.b.erlysuspend) { ++ retval |= dwc_otg_pcd_handle_early_suspend_intr(pcd); ++ hisi_switch_func(0); ++ } ++ if (gintr_status.b.usbreset) { ++ retval |= dwc_otg_pcd_handle_usb_reset_intr(pcd); ++ hisi_switch_func(0); ++ } ++ if (gintr_status.b.enumdone) { ++ retval |= dwc_otg_pcd_handle_enum_done_intr(pcd); ++ } ++ if (gintr_status.b.isooutdrop) { ++ retval |= ++ dwc_otg_pcd_handle_isoc_out_packet_dropped_intr ++ (pcd); ++ } ++ if (gintr_status.b.eopframe) { ++ retval |= ++ dwc_otg_pcd_handle_end_periodic_frame_intr(pcd); ++ } ++ if (gintr_status.b.inepint) { ++ if (!core_if->multiproc_int_enable) { ++ retval |= dwc_otg_pcd_handle_in_ep_intr(pcd); ++ } ++ } ++ if (gintr_status.b.outepintr) { ++ if (!core_if->multiproc_int_enable) { ++ retval |= dwc_otg_pcd_handle_out_ep_intr(pcd); ++ } ++ } ++ if (gintr_status.b.epmismatch) { ++ retval |= dwc_otg_pcd_handle_ep_mismatch_intr(pcd); ++ } ++ if (gintr_status.b.fetsusp) { ++ retval |= dwc_otg_pcd_handle_ep_fetsusp_intr(pcd); ++ } ++ if (gintr_status.b.ginnakeff) { ++ retval |= dwc_otg_pcd_handle_in_nak_effective(pcd); ++ } ++ if (gintr_status.b.incomplisoin) { ++ retval |= ++ dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd); ++ } ++ if (gintr_status.b.incomplisoout) { ++ retval |= ++ dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd); ++ } ++ ++ /* In MPI mode Device Endpoints interrupts are asserted ++ * without setting outepintr and inepint bits set, so these ++ * Interrupt handlers are called without checking these bit-fields ++ */ ++ if (core_if->multiproc_int_enable) { ++ retval |= dwc_otg_pcd_handle_in_ep_intr(pcd); ++ retval |= dwc_otg_pcd_handle_out_ep_intr(pcd); ++ } ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__, ++ DWC_READ_REG32(&global_regs->gintsts)); ++#endif ++ DWC_SPINUNLOCK(pcd->lock); ++ } ++ return retval; ++} ++ ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd_linux.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd_linux.c +new file mode 100644 +index 0000000..5efda52 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd_linux.c +@@ -0,0 +1,1440 @@ ++ /* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $ ++ * $Revision: #28 $ ++ * $Date: 2013/05/07 $ ++ * $Change: 2224063 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_HOST_ONLY ++ ++/** @file ++ * This file implements the Peripheral Controller Driver. ++ * ++ * The Peripheral Controller Driver (PCD) is responsible for ++ * translating requests from the Function Driver into the appropriate ++ * actions on the DWC_otg controller. It isolates the Function Driver ++ * from the specifics of the controller by providing an API to the ++ * Function Driver. ++ * ++ * The Peripheral Controller Driver for Linux will implement the ++ * Gadget API, so that the existing Gadget drivers can be used. ++ * (Gadget Driver is the Linux terminology for a Function Driver.) ++ * ++ * The Linux Gadget API is defined in the header file ++ * . The USB EP operations API is ++ * defined in the structure usb_ep_ops and the USB ++ * Controller API is defined in the structure ++ * usb_gadget_ops. ++ * ++ */ ++ ++#include "dwc_otg_os_dep.h" ++#include "dwc_otg_pcd_if.h" ++#include "dwc_otg_pcd.h" ++#include "dwc_otg_driver.h" ++#include "dwc_otg_dbg.h" ++ ++static struct gadget_wrapper { ++ dwc_otg_pcd_t *pcd; ++ ++ struct usb_gadget gadget; ++ struct usb_gadget_driver *driver; ++ ++ struct usb_ep ep0; ++ struct usb_ep in_ep[16]; ++ struct usb_ep out_ep[16]; ++ ++} *gadget_wrapper; ++ ++/* Display the contents of the buffer */ ++extern void dump_msg(const u8 * buf, unsigned int length); ++ ++int udc_attach_driver(const char *name, struct usb_gadget_driver *driver) ++{ ++ //do nothing ,only make ++ return 0; ++} ++EXPORT_SYMBOL_GPL(udc_attach_driver); ++ ++static int usb_gadget_map_req(struct usb_gadget *gadget, ++ struct usb_request *req, struct dwc_otg_pcd_ep *ep) ++{ ++ if (req->length == 0) ++ return 0; ++ ++ if (req->num_sgs) { ++ dev_err(&gadget->dev, "controller not support scatter/gather dma\n"); ++ return -EFAULT; ++ ++ } else { ++ ++ if (ep == &gadget_wrapper->pcd->ep0) { ++ req->dma = dma_map_single(&gadget->dev, req->buf, req->length, ++ DMA_BIDIRECTIONAL); ++ } else { ++ req->dma = dma_map_single(&gadget->dev, req->buf, req->length, ++ ep->dwc_ep.is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); ++ } ++ ++ if (dma_mapping_error(&gadget->dev, req->dma)) { ++ dev_err(&gadget->dev, "failed to map buffer\n"); ++ return -EFAULT; ++ } ++ } ++ ++ return 0; ++} ++ ++static void usb_gadget_unmap_req(struct usb_gadget *gadget, ++ struct usb_request *req, struct dwc_otg_pcd_ep *ep) ++{ ++ if (req->length == 0) ++ return; ++ ++ if (req->num_mapped_sgs) { ++ dev_err(&gadget->dev, "controller not support scatter/gather dma\n"); ++ } else { ++ ++ if (ep == &gadget_wrapper->pcd->ep0) { ++ dma_unmap_single(&gadget->dev, req->dma, req->length, ++ DMA_BIDIRECTIONAL); ++ } else { ++ dma_unmap_single(&gadget->dev, req->dma, req->length, ++ ep->dwc_ep.is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); ++ } ++ } ++} ++ ++/** ++ * Get the dwc_otg_pcd_ep_t* from usb_ep* pointer - NULL in case ++ * if the endpoint is not found ++ */ ++static struct dwc_otg_pcd_ep *ep_from_handle(dwc_otg_pcd_t * pcd, void *handle) ++{ ++ int i; ++ if (pcd->ep0.priv == handle) { ++ return &pcd->ep0; ++ } ++ ++ for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) { ++ if (pcd->in_ep[i].priv == handle) ++ return &pcd->in_ep[i]; ++ if (pcd->out_ep[i].priv == handle) ++ return &pcd->out_ep[i]; ++ } ++ ++ return NULL; ++} ++ ++/* USB Endpoint Operations */ ++/* ++ * The following sections briefly describe the behavior of the Gadget ++ * API endpoint operations implemented in the DWC_otg driver ++ * software. Detailed descriptions of the generic behavior of each of ++ * these functions can be found in the Linux header file ++ * include/linux/usb_gadget.h. ++ * ++ * The Gadget API provides wrapper functions for each of the function ++ * pointers defined in usb_ep_ops. The Gadget Driver calls the wrapper ++ * function, which then calls the underlying PCD function. The ++ * following sections are named according to the wrapper ++ * functions. Within each section, the corresponding DWC_otg PCD ++ * function name is specified. ++ * ++ */ ++ ++/** ++ * This function is called by the Gadget Driver for each EP to be ++ * configured for the current configuration (SET_CONFIGURATION). ++ * ++ * This function initializes the dwc_otg_ep_t data structure, and then ++ * calls dwc_otg_ep_activate. ++ */ ++static int ep_enable(struct usb_ep *usb_ep, ++ const struct usb_endpoint_descriptor *ep_desc) ++{ ++ int retval; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, ep_desc); ++ ++ if (!usb_ep || !ep_desc || ep_desc->bDescriptorType != USB_DT_ENDPOINT) { ++ DWC_WARN("%s, bad ep or descriptor\n", __func__); ++ return -EINVAL; ++ } ++ if (usb_ep == &gadget_wrapper->ep0) { ++ DWC_WARN("%s, bad ep(0)\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* Check FIFO size? */ ++ if (!ep_desc->wMaxPacketSize) { ++ DWC_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name); ++ return -ERANGE; ++ } ++ ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ DWC_WARN("%s, bogus device state\n", __func__); ++ return -ESHUTDOWN; ++ } ++ ++ /* Delete after check - MAS */ ++ retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd, ++ (const uint8_t *)ep_desc, ++ (void *)usb_ep); ++ if (retval) { ++ DWC_WARN("dwc_otg_pcd_ep_enable failed\n"); ++ return -EINVAL; ++ } ++ ++ usb_ep->maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize); ++ ++ return 0; ++} ++ ++/** ++ * This function is called when an EP is disabled due to disconnect or ++ * change in configuration. Any pending requests will terminate with a ++ * status of -ESHUTDOWN. ++ * ++ * This function modifies the dwc_otg_ep_t data structure for this EP, ++ * and then calls dwc_otg_ep_deactivate. ++ */ ++static int ep_disable(struct usb_ep *usb_ep) ++{ ++ int retval; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, usb_ep); ++ if (!usb_ep) { ++ DWC_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__, ++ usb_ep ? usb_ep->name : NULL); ++ return -EINVAL; ++ } ++ ++ retval = dwc_otg_pcd_ep_disable(gadget_wrapper->pcd, usb_ep); ++ if (retval) { ++ retval = -EINVAL; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function allocates a request object to use with the specified ++ * endpoint. ++ * ++ * @param ep The endpoint to be used with with the request ++ * @param gfp_flags the GFP_* flags to use. ++ */ ++static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *ep, ++ gfp_t gfp_flags) ++{ ++ struct usb_request *usb_req; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d)\n", __func__, ep, gfp_flags); ++ if (0 == ep) { ++ DWC_WARN("%s() %s\n", __func__, "Invalid EP!\n"); ++ return 0; ++ } ++ usb_req = kmalloc(sizeof(*usb_req), gfp_flags); ++ if (0 == usb_req) { ++ DWC_WARN("%s() %s\n", __func__, "request allocation failed!\n"); ++ return 0; ++ } ++ memset(usb_req, 0, sizeof(*usb_req)); ++ usb_req->dma = DWC_DMA_ADDR_INVALID; ++ ++ return usb_req; ++} ++ ++/** ++ * This function frees a request object. ++ * ++ * @param ep The endpoint associated with the request ++ * @param req The request being freed ++ */ ++static void dwc_otg_pcd_free_request(struct usb_ep *ep, struct usb_request *req) ++{ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, ep, req); ++ ++ if (0 == ep || 0 == req) { ++ DWC_WARN("%s() %s\n", __func__, ++ "Invalid ep or req argument!\n"); ++ return; ++ } ++ ++ kfree(req); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++/** ++ * This function allocates an I/O buffer to be used for a transfer ++ * to/from the specified endpoint. ++ * ++ * @param usb_ep The endpoint to be used with with the request ++ * @param bytes The desired number of bytes for the buffer ++ * @param dma Pointer to the buffer's DMA address; must be valid ++ * @param gfp_flags the GFP_* flags to use. ++ * @return address of a new buffer or null is buffer could not be allocated. ++ */ ++static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes, ++ dma_addr_t * dma, gfp_t gfp_flags) ++{ ++ void *buf; ++ dwc_otg_pcd_t *pcd = 0; ++ ++ pcd = gadget_wrapper->pcd; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d,%p,%0x)\n", __func__, usb_ep, bytes, ++ dma, gfp_flags); ++ ++ /* Check dword alignment */ ++ if ((bytes & 0x3UL) != 0) { ++ DWC_WARN("%s() Buffer size is not a multiple of" ++ "DWORD size (%d)", __func__, bytes); ++ } ++ ++ buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags); ++ ++ /* Check dword alignment */ ++ if (((int)buf & 0x3UL) != 0) { ++ DWC_WARN("%s() Buffer is not DWORD aligned (%p)", ++ __func__, buf); ++ } ++ ++ return buf; ++} ++ ++/** ++ * This function frees an I/O buffer that was allocated by alloc_buffer. ++ * ++ * @param usb_ep the endpoint associated with the buffer ++ * @param buf address of the buffer ++ * @param dma The buffer's DMA address ++ * @param bytes The number of bytes of the buffer ++ */ ++static void dwc_otg_pcd_free_buffer(struct usb_ep *usb_ep, void *buf, ++ dma_addr_t dma, unsigned bytes) ++{ ++ dwc_otg_pcd_t *pcd = 0; ++ ++ pcd = gadget_wrapper->pcd; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%0x,%d)\n", __func__, buf, dma, bytes); ++ ++ dma_free_coherent(NULL, bytes, buf, dma); ++} ++#endif ++ ++/** ++ * This function is used to submit an I/O Request to an EP. ++ * ++ * - When the request completes the request's completion callback ++ * is called to return the request to the driver. ++ * - An EP, except control EPs, may have multiple requests ++ * pending. ++ * - Once submitted the request cannot be examined or modified. ++ * - Each request is turned into one or more packets. ++ * - A BULK EP can queue any amount of data; the transfer is ++ * packetized. ++ * - Zero length Packets are specified with the request 'zero' ++ * flag. ++ */ ++static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req, ++ gfp_t gfp_flags) ++{ ++ dwc_otg_pcd_t *pcd; ++ struct dwc_otg_pcd_ep *ep; ++ int retval, is_isoc_ep; ++ dma_addr_t dma_addr = 0; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p,%d)\n", ++ __func__, usb_ep, usb_req, gfp_flags); ++ ++ if (!usb_req || !usb_req->complete || !usb_req->buf) { ++ DWC_WARN("bad params\n"); ++ return -EINVAL; ++ } ++ ++ if (!usb_ep) { ++ DWC_WARN("bad ep\n"); ++ return -EINVAL; ++ } ++ ++ pcd = gadget_wrapper->pcd; ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n", ++ gadget_wrapper->gadget.speed); ++ DWC_WARN("bogus device state\n"); ++ return -ESHUTDOWN; ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "%s queue req %p, len %d buf %p\n", ++ usb_ep->name, usb_req, usb_req->length, usb_req->buf); ++ ++ usb_req->status = -EINPROGRESS; ++ usb_req->actual = 0; ++ ++ ep = ep_from_handle(pcd, usb_ep); ++ if (ep == NULL) ++ is_isoc_ep = 0; ++ else ++ is_isoc_ep = (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ? 1 : 0; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ dma_addr = usb_req->dma; ++#else ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ retval = usb_gadget_map_req(&gadget_wrapper->gadget, ++ usb_req, ep); ++ if (retval) { ++ return -EINVAL; ++ } ++ dma_addr =usb_req->dma; ++ } ++#endif ++ ++#ifdef DWC_UTE_PER_IO ++ if (is_isoc_ep == 1) { ++ retval = ++ dwc_otg_pcd_xiso_ep_queue(pcd, usb_ep, usb_req->buf, ++ dma_addr, usb_req->length, ++ usb_req->zero, usb_req, ++ gfp_flags == GFP_ATOMIC ? 1 : 0, ++ &usb_req->ext_req); ++ if (retval) ++ return -EINVAL; ++ ++ return 0; ++ } ++#endif ++ retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr, ++ usb_req->length, usb_req->zero, usb_req, ++ gfp_flags == GFP_ATOMIC ? 1 : 0); ++ if (retval) { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/** ++ * This function cancels an I/O request from an EP. ++ */ ++static int ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req) ++{ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, usb_req); ++ ++ if (!usb_ep || !usb_req) { ++ DWC_WARN("bad argument\n"); ++ return -EINVAL; ++ } ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ DWC_WARN("bogus device state\n"); ++ return -ESHUTDOWN; ++ } ++ if (dwc_otg_pcd_ep_dequeue(gadget_wrapper->pcd, usb_ep, usb_req)) { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/** ++ * usb_ep_set_halt stalls an endpoint. ++ * ++ * usb_ep_clear_halt clears an endpoint halt and resets its data ++ * toggle. ++ * ++ * Both of these functions are implemented with the same underlying ++ * function. The behavior depends on the value argument. ++ * ++ * @param[in] usb_ep the Endpoint to halt or clear halt. ++ * @param[in] value ++ * - 0 means clear_halt. ++ * - 1 means set_halt, ++ * - 2 means clear stall lock flag. ++ * - 3 means set stall lock flag. ++ */ ++static int ep_halt(struct usb_ep *usb_ep, int value) ++{ ++ int retval = 0; ++ ++ DWC_DEBUGPL(DBG_PCD, "HALT %s %d\n", usb_ep->name, value); ++ ++ if (!usb_ep) { ++ DWC_WARN("bad ep\n"); ++ return -EINVAL; ++ } ++ ++ retval = dwc_otg_pcd_ep_halt(gadget_wrapper->pcd, usb_ep, value); ++ if (retval == -DWC_E_AGAIN) { ++ return -EAGAIN; ++ } else if (retval) { ++ retval = -EINVAL; ++ } ++ ++ return retval; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) ++static int ep_wedge(struct usb_ep *usb_ep) ++{ ++ DWC_DEBUGPL(DBG_PCD, "WEDGE %s\n", usb_ep->name); ++ ++ return ep_halt(usb_ep, 3); ++} ++#endif ++ ++#ifdef DWC_EN_ISOC ++/** ++ * This function is used to submit an ISOC Transfer Request to an EP. ++ * ++ * - Every time a sync period completes the request's completion callback ++ * is called to provide data to the gadget driver. ++ * - Once submitted the request cannot be modified. ++ * - Each request is turned into periodic data packets untill ISO ++ * Transfer is stopped.. ++ */ ++static int iso_ep_start(struct usb_ep *usb_ep, struct usb_iso_request *req, ++ gfp_t gfp_flags) ++{ ++ int retval = 0; ++ ++ if (!req || !req->process_buffer || !req->buf0 || !req->buf1) { ++ DWC_WARN("bad params\n"); ++ return -EINVAL; ++ } ++ ++ if (!usb_ep) { ++ DWC_PRINTF("bad params\n"); ++ return -EINVAL; ++ } ++ ++ req->status = -EINPROGRESS; ++ ++ retval = ++ dwc_otg_pcd_iso_ep_start(gadget_wrapper->pcd, usb_ep, req->buf0, ++ req->buf1, req->dma0, req->dma1, ++ req->sync_frame, req->data_pattern_frame, ++ req->data_per_frame, ++ req-> ++ flags & USB_REQ_ISO_ASAP ? -1 : ++ req->start_frame, req->buf_proc_intrvl, ++ req, gfp_flags == GFP_ATOMIC ? 1 : 0); ++ ++ if (retval) { ++ return -EINVAL; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function stops ISO EP Periodic Data Transfer. ++ */ ++static int iso_ep_stop(struct usb_ep *usb_ep, struct usb_iso_request *req) ++{ ++ int retval = 0; ++ if (!usb_ep) { ++ DWC_WARN("bad ep\n"); ++ } ++ ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n", ++ gadget_wrapper->gadget.speed); ++ DWC_WARN("bogus device state\n"); ++ } ++ ++ dwc_otg_pcd_iso_ep_stop(gadget_wrapper->pcd, usb_ep, req); ++ if (retval) { ++ retval = -EINVAL; ++ } ++ ++ return retval; ++} ++ ++static struct usb_iso_request *alloc_iso_request(struct usb_ep *ep, ++ int packets, gfp_t gfp_flags) ++{ ++ struct usb_iso_request *pReq = NULL; ++ uint32_t req_size; ++ ++ req_size = sizeof(struct usb_iso_request); ++ req_size += ++ (2 * packets * (sizeof(struct usb_gadget_iso_packet_descriptor))); ++ ++ pReq = kmalloc(req_size, gfp_flags); ++ if (!pReq) { ++ DWC_WARN("Can't allocate Iso Request\n"); ++ return 0; ++ } ++ pReq->iso_packet_desc0 = (void *)(pReq + 1); ++ ++ pReq->iso_packet_desc1 = pReq->iso_packet_desc0 + packets; ++ ++ return pReq; ++} ++ ++static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req) ++{ ++ kfree(req); ++} ++ ++static struct usb_isoc_ep_ops dwc_otg_pcd_ep_ops = { ++ .ep_ops = { ++ .enable = ep_enable, ++ .disable = ep_disable, ++ ++ .alloc_request = dwc_otg_pcd_alloc_request, ++ .free_request = dwc_otg_pcd_free_request, ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ .alloc_buffer = dwc_otg_pcd_alloc_buffer, ++ .free_buffer = dwc_otg_pcd_free_buffer, ++#endif ++ ++ .queue = ep_queue, ++ .dequeue = ep_dequeue, ++ ++ .set_halt = ep_halt, ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) ++ .set_wedge = ep_wedge, ++ #endif ++ .fifo_status = 0, ++ .fifo_flush = 0, ++ }, ++ ++ .iso_ep_start = iso_ep_start, ++ .iso_ep_stop = iso_ep_stop, ++ .alloc_iso_request = alloc_iso_request, ++ .free_iso_request = free_iso_request, ++}; ++ ++#else ++ ++static struct usb_ep_ops dwc_otg_pcd_ep_ops = { ++ .enable = ep_enable, ++ .disable = ep_disable, ++ ++ .alloc_request = dwc_otg_pcd_alloc_request, ++ .free_request = dwc_otg_pcd_free_request, ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ .alloc_buffer = dwc_otg_pcd_alloc_buffer, ++ .free_buffer = dwc_otg_pcd_free_buffer, ++#endif ++ ++ .queue = ep_queue, ++ .dequeue = ep_dequeue, ++ ++ .set_halt = ep_halt, ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) ++ .set_wedge = ep_wedge, ++ #endif ++ ++ .fifo_status = 0, ++ .fifo_flush = 0, ++ ++}; ++ ++#endif /* _EN_ISOC_ */ ++/* Gadget Operations */ ++/** ++ * The following gadget operations will be implemented in the DWC_otg ++ * PCD. Functions in the API that are not described below are not ++ * implemented. ++ * ++ * The Gadget API provides wrapper functions for each of the function ++ * pointers defined in usb_gadget_ops. The Gadget Driver calls the ++ * wrapper function, which then calls the underlying PCD function. The ++ * following sections are named according to the wrapper functions ++ * (except for ioctl, which doesn't have a wrapper function). Within ++ * each section, the corresponding DWC_otg PCD function name is ++ * specified. ++ * ++ */ ++ ++/** ++ *Gets the USB Frame number of the last SOF. ++ */ ++static int get_frame_number(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget); ++ ++ if (gadget == 0) { ++ return -ENODEV; ++ } ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ return dwc_otg_pcd_get_frame_number(d->pcd); ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++static int test_lpm_enabled(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ ++ return dwc_otg_pcd_is_lpm_enabled(d->pcd); ++} ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) ++static int test_besl_enabled(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ ++ return dwc_otg_pcd_is_besl_enabled(d->pcd); ++} ++static int get_param_baseline_besl(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ ++ return dwc_otg_pcd_get_param_baseline_besl(d->pcd); ++} ++static int get_param_deep_besl(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ ++ return dwc_otg_pcd_get_param_deep_besl(d->pcd); ++} ++#endif ++#endif ++ ++/** ++ * Initiates Session Request Protocol (SRP) to wakeup the host if no ++ * session is in progress. If a session is already in progress, but ++ * the device is suspended, remote wakeup signaling is started. ++ * ++ */ ++static int wakeup(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget); ++ ++ if (gadget == 0) { ++ return -ENODEV; ++ } else { ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ } ++ dwc_otg_pcd_wakeup(d->pcd); ++ return 0; ++} ++ ++static int pullup(struct usb_gadget *gadget, int is_on) ++{ ++ struct gadget_wrapper *d; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget); ++ ++ if (gadget == 0) { ++ return -ENODEV; ++ } else { ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ } ++ ++ if (!is_on) ++ dwc_otg_pcd_pullup(d->pcd); ++ ++ return 0; ++} ++ ++static const struct usb_gadget_ops dwc_otg_pcd_ops = { ++ .get_frame = get_frame_number, ++ .wakeup = wakeup, ++ .pullup = pullup, ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ .lpm_support = test_lpm_enabled, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) ++ .besl_support = test_besl_enabled, ++ .get_baseline_besl = get_param_baseline_besl, ++ .get_deep_besl = get_param_deep_besl, ++#endif ++#endif ++ // current versions must always be self-powered ++}; ++ ++static int _setup(dwc_otg_pcd_t * pcd, uint8_t * bytes) ++{ ++ int retval = -DWC_E_NOT_SUPPORTED; ++ if (gadget_wrapper->driver && gadget_wrapper->driver->setup) { ++ retval = gadget_wrapper->driver->setup(&gadget_wrapper->gadget, ++ (struct usb_ctrlrequest ++ *)bytes); ++ } ++ ++ if (retval == -ENOTSUPP) { ++ retval = -DWC_E_NOT_SUPPORTED; ++ } else if (retval < 0) { ++ retval = -DWC_E_INVALID; ++ } ++ ++ return retval; ++} ++ ++#ifdef DWC_EN_ISOC ++static int _isoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int proc_buf_num) ++{ ++ int i, packet_count; ++ struct usb_gadget_iso_packet_descriptor *iso_packet = 0; ++ struct usb_iso_request *iso_req = req_handle; ++ ++ if (proc_buf_num) { ++ iso_packet = iso_req->iso_packet_desc1; ++ } else { ++ iso_packet = iso_req->iso_packet_desc0; ++ } ++ packet_count = ++ dwc_otg_pcd_get_iso_packet_count(pcd, ep_handle, req_handle); ++ for (i = 0; i < packet_count; ++i) { ++ int status; ++ int actual; ++ int offset; ++ dwc_otg_pcd_get_iso_packet_params(pcd, ep_handle, req_handle, ++ i, &status, &actual, &offset); ++ switch (status) { ++ case -DWC_E_NO_DATA: ++ status = -ENODATA; ++ break; ++ default: ++ if (status) { ++ DWC_PRINTF("unknown status in isoc packet\n"); ++ } ++ ++ } ++ iso_packet[i].status = status; ++ iso_packet[i].offset = offset; ++ iso_packet[i].actual_length = actual; ++ } ++ ++ iso_req->status = 0; ++ iso_req->process_buffer(ep_handle, iso_req); ++ ++ return 0; ++} ++#endif /* DWC_EN_ISOC */ ++ ++#ifdef DWC_UTE_PER_IO ++/** ++ * Copy the contents of the extended request to the Linux usb_request's ++ * extended part and call the gadget's completion. ++ * ++ * @param pcd Pointer to the pcd structure ++ * @param ep_handle Void pointer to the usb_ep structure ++ * @param req_handle Void pointer to the usb_request structure ++ * @param status Request status returned from the portable logic ++ * @param ereq_port Void pointer to the extended request structure ++ * created in the the portable part that contains the ++ * results of the processed iso packets. ++ */ ++static int _xisoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int32_t status, void *ereq_port) ++{ ++ struct dwc_ute_iso_req_ext *ereqorg = NULL; ++ struct dwc_iso_xreq_port *ereqport = NULL; ++ struct dwc_ute_iso_packet_descriptor *desc_org = NULL; ++ int i; ++ struct usb_request *req; ++ //struct dwc_ute_iso_packet_descriptor * ++ //int status = 0; ++ ++ req = (struct usb_request *)req_handle; ++ ereqorg = &req->ext_req; ++ ereqport = (struct dwc_iso_xreq_port *)ereq_port; ++ desc_org = ereqorg->per_io_frame_descs; ++ ++ if (req && req->complete) { ++ /* Copy the request data from the portable logic to our request */ ++ for (i = 0; i < ereqport->pio_pkt_count; i++) { ++ desc_org[i].actual_length = ++ ereqport->per_io_frame_descs[i].actual_length; ++ desc_org[i].status = ++ ereqport->per_io_frame_descs[i].status; ++ } ++ ++ switch (status) { ++ case -DWC_E_SHUTDOWN: ++ req->status = -ESHUTDOWN; ++ break; ++ case -DWC_E_RESTART: ++ req->status = -ECONNRESET; ++ break; ++ case -DWC_E_INVALID: ++ req->status = -EINVAL; ++ break; ++ case -DWC_E_TIMEOUT: ++ req->status = -ETIMEDOUT; ++ break; ++ default: ++ req->status = status; ++ } ++ ++ /* And call the gadget's completion */ ++ req->complete(ep_handle, req); ++ } ++ ++ return 0; ++} ++#endif /* DWC_UTE_PER_IO */ ++static int _complete(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int32_t status, uint32_t actual) ++{ ++ struct usb_request *req = (struct usb_request *)req_handle; ++ struct dwc_otg_pcd_ep *ep = NULL; ++ ++ ep = ep_from_handle(pcd, ep_handle); ++ ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ if (req->dma) ++ usb_gadget_unmap_req(&gadget_wrapper->gadget, ++ req, ep); ++ req->dma = (dma_addr_t)0; ++ } ++ ++ if (req && req->complete) { ++ switch (status) { ++ case -DWC_E_SHUTDOWN: ++ req->status = -ESHUTDOWN; ++ break; ++ case -DWC_E_RESTART: ++ req->status = -ECONNRESET; ++ break; ++ case -DWC_E_INVALID: ++ req->status = -EINVAL; ++ break; ++ case -DWC_E_TIMEOUT: ++ req->status = -ETIMEDOUT; ++ break; ++ default: ++ req->status = status; ++ ++ } ++ ++ req->actual = actual; ++ DWC_SPINUNLOCK(pcd->lock); ++ req->complete(ep_handle, req); ++ DWC_SPINLOCK(pcd->lock); ++ } ++#ifdef PCI_INTERFACE ++ dev = gadget_wrapper->pcd->otg_dev->os_dep.pcidev; ++ ep = ep_from_handle(pcd, ep_handle); ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ if (req->length != 0) ++ pci_unmap_single(dev, req->dma, req->length, ++ ep->dwc_ep.is_in ? PCI_DMA_TODEVICE : ++ PCI_DMA_FROMDEVICE); ++ } ++#endif ++ ++ return 0; ++} ++ ++static int _connect(dwc_otg_pcd_t * pcd, int speed) ++{ ++ gadget_wrapper->gadget.speed = speed; ++ return 0; ++} ++ ++static int _disconnect(dwc_otg_pcd_t * pcd) ++{ ++ if (gadget_wrapper->driver && gadget_wrapper->driver->disconnect) { ++ gadget_wrapper->driver->disconnect(&gadget_wrapper->gadget); ++ } ++ return 0; ++} ++ ++static int _resume(dwc_otg_pcd_t * pcd) ++{ ++ if (gadget_wrapper->driver && gadget_wrapper->driver->resume) { ++ gadget_wrapper->driver->resume(&gadget_wrapper->gadget); ++ } ++ ++ return 0; ++} ++ ++static int _suspend(dwc_otg_pcd_t * pcd) ++{ ++ if (gadget_wrapper->driver && gadget_wrapper->driver->suspend) { ++ gadget_wrapper->driver->suspend(&gadget_wrapper->gadget); ++ } ++ return 0; ++} ++ ++/** ++ * This function updates the otg values in the gadget structure. ++ */ ++static int _hnp_changed(dwc_otg_pcd_t * pcd) ++{ ++ ++ if (!gadget_wrapper->gadget.is_otg) ++ return 0; ++ ++ gadget_wrapper->gadget.b_hnp_enable = get_b_hnp_enable(pcd); ++ gadget_wrapper->gadget.a_hnp_support = get_a_hnp_support(pcd); ++ gadget_wrapper->gadget.a_alt_hnp_support = get_a_alt_hnp_support(pcd); ++ return 0; ++} ++ ++static int _reset(dwc_otg_pcd_t * pcd) ++{ ++ return 0; ++} ++ ++#ifdef DWC_UTE_CFI ++static int _cfi_setup(dwc_otg_pcd_t * pcd, void *cfi_req) ++{ ++ int retval = -DWC_E_INVALID; ++ if (gadget_wrapper->driver->cfi_feature_setup) { ++ retval = ++ gadget_wrapper->driver-> ++ cfi_feature_setup(&gadget_wrapper->gadget, ++ (struct cfi_usb_ctrlrequest *)cfi_req); ++ } ++ ++ return retval; ++} ++#endif ++ ++static const struct dwc_otg_pcd_function_ops fops = { ++ .complete = _complete, ++#ifdef DWC_EN_ISOC ++ .isoc_complete = _isoc_complete, ++#endif ++ .setup = _setup, ++ .disconnect = _disconnect, ++ .connect = _connect, ++ .resume = _resume, ++ .suspend = _suspend, ++ .hnp_changed = _hnp_changed, ++ .reset = _reset, ++#ifdef DWC_UTE_CFI ++ .cfi_setup = _cfi_setup, ++#endif ++#ifdef DWC_UTE_PER_IO ++ .xisoc_complete = _xisoc_complete, ++#endif ++}; ++ ++/** ++ * This function is the top level PCD interrupt handler. ++ */ ++static irqreturn_t dwc_otg_pcd_irq(int irq, void *dev) ++{ ++ dwc_otg_pcd_t *pcd = dev; ++ int32_t retval = IRQ_NONE; ++ ++ retval = dwc_otg_pcd_handle_intr(pcd); ++ if (retval != 0) { ++ S3C2410X_CLEAR_EINTPEND(); ++ } ++ return IRQ_RETVAL(retval); ++} ++ ++/** ++ * This function initialized the usb_ep structures to there default ++ * state. ++ * ++ * @param d Pointer on gadget_wrapper. ++ */ ++void gadget_add_eps(struct gadget_wrapper *d) ++{ ++ static const char *names[] = { ++ ++ "ep0", ++ "ep1in", ++ "ep2in", ++ "ep3in", ++ "ep4in", ++ "ep5in", ++ "ep6in", ++ "ep7in", ++ "ep8in", ++ "ep9in", ++ "ep10in", ++ "ep11in", ++ "ep12in", ++ "ep13in", ++ "ep14in", ++ "ep15in", ++ "ep1out", ++ "ep2out", ++ "ep3out", ++ "ep4out", ++ "ep5out", ++ "ep6out", ++ "ep7out", ++ "ep8out", ++ "ep9out", ++ "ep10out", ++ "ep11out", ++ "ep12out", ++ "ep13out", ++ "ep14out", ++ "ep15out" ++ }; ++ ++ int i; ++ struct usb_ep *ep; ++ int8_t dev_endpoints; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__); ++ ++ INIT_LIST_HEAD(&d->gadget.ep_list); ++ d->gadget.ep0 = &d->ep0; ++ d->gadget.speed = USB_SPEED_UNKNOWN; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) ++ d->gadget.max_speed = USB_SPEED_HIGH; ++#endif ++ ++ INIT_LIST_HEAD(&d->gadget.ep0->ep_list); ++ ++ /** ++ * Initialize the EP0 structure. ++ */ ++ ep = &d->ep0; ++ ++ /* Init the usb_ep structure. */ ++ ep->name = names[0]; ++ ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; ++ ++ /** ++ * @todo NGS: What should the max packet size be set to ++ * here? Before EP type is set? ++ */ ++ ep->maxpacket = MAX_PACKET_SIZE; ++ dwc_otg_pcd_ep_enable(d->pcd, NULL, ep); ++ ++ list_add_tail(&ep->ep_list, &d->gadget.ep_list); ++ ++ /** ++ * Initialize the EP structures. ++ */ ++ dev_endpoints = d->pcd->core_if->dev_if->num_in_eps; ++ ++ for (i = 0; i < dev_endpoints; i++) { ++ ep = &d->in_ep[i]; ++ ++ /* Init the usb_ep structure. */ ++ ep->name = names[d->pcd->in_ep[i].dwc_ep.num]; ++ ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; ++ ++ /** ++ * @todo NGS: What should the max packet size be set to ++ * here? Before EP type is set? ++ */ ++ ep->maxpacket = MAX_PACKET_SIZE; ++ ep->maxpacket_limit = MAX_PACKET_SIZE; ++ list_add_tail(&ep->ep_list, &d->gadget.ep_list); ++ } ++ ++ dev_endpoints = d->pcd->core_if->dev_if->num_out_eps; ++ ++ for (i = 0; i < dev_endpoints; i++) { ++ ep = &d->out_ep[i]; ++ ++ /* Init the usb_ep structure. */ ++ ep->name = names[15 + d->pcd->out_ep[i].dwc_ep.num]; ++ ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; ++ ++ /** ++ * @todo NGS: What should the max packet size be set to ++ * here? Before EP type is set? ++ */ ++ ep->maxpacket = MAX_PACKET_SIZE; ++ ep->maxpacket_limit = MAX_PACKET_SIZE; ++ ++ list_add_tail(&ep->ep_list, &d->gadget.ep_list); ++ } ++ ++ /* remove ep0 from the list. There is a ep0 pointer. */ ++ list_del_init(&d->ep0.ep_list); ++ ++ d->ep0.maxpacket = MAX_EP0_SIZE; ++} ++ ++/** ++ * This function releases the Gadget device. ++ * required by device_unregister(). ++ * ++ * @todo Should this do something? Should it free the PCD? ++ */ ++static void dwc_otg_pcd_gadget_release(struct device *dev) ++{ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev); ++} ++ ++static struct gadget_wrapper *alloc_wrapper( ++ struct platform_device *_dev ++ ) ++{ ++ static char pcd_name[] = "dwc_otg_pcd"; ++ ++ dwc_otg_device_t *otg_dev =platform_get_drvdata(_dev); ++ ++ ++ struct gadget_wrapper *d; ++ int retval; ++ ++ d = DWC_ALLOC(sizeof(*d)); ++ if (d == NULL) { ++ return NULL; ++ } ++ ++ memset(d, 0, sizeof(*d)); ++ ++ d->gadget.name = pcd_name; ++ d->pcd = otg_dev->pcd; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ++ strcpy(d->gadget.dev.bus_id, "gadget"); ++#else ++ dev_set_name(&d->gadget.dev, "%s", "gadget"); ++#endif ++ ++ d->gadget.dev.parent = &_dev->dev; ++ d->gadget.dev.release = dwc_otg_pcd_gadget_release; ++ d->gadget.ops = &dwc_otg_pcd_ops; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) ++ d->gadget.is_dualspeed = dwc_otg_pcd_is_dualspeed(otg_dev->pcd); ++#endif ++ d->gadget.is_otg = dwc_otg_pcd_is_otg(otg_dev->pcd); ++ ++ d->driver = 0; ++ /* Register the gadget device */ ++ retval = device_register(&d->gadget.dev); ++ if (retval != 0) { ++ DWC_ERROR("device_register failed\n"); ++ DWC_FREE(d); ++ return NULL; ++ } ++ ++ return d; ++} ++ ++static void free_wrapper(struct gadget_wrapper *d) ++{ ++ if (d->driver) { ++ /* should have been done already by driver model core */ ++ DWC_WARN("driver '%s' is still registered\n", ++ d->driver->driver.name); ++ usb_gadget_unregister_driver(d->driver); ++ } ++ ++ device_unregister(&d->gadget.dev); ++ DWC_FREE(d); ++} ++ ++/** ++ * This function initialized the PCD portion of the driver. ++ * ++ */ ++int pcd_init(struct platform_device *_dev, int irqnum ) ++{ ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); ++ ++ int retval = 0; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _dev); ++ ++ otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if); ++ ++ if (!otg_dev->pcd) { ++ DWC_ERROR("dwc_otg_pcd_init failed\n"); ++ return -ENOMEM; ++ } ++ ++ otg_dev->pcd->otg_dev = otg_dev; ++ gadget_wrapper = alloc_wrapper(_dev); ++ ++ /* ++ * Initialize EP structures ++ */ ++ gadget_add_eps(gadget_wrapper); ++ /* ++ * Setup interupt handler ++ */ ++ DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n", irqnum); ++ retval = request_irq(irqnum, dwc_otg_pcd_irq, ++ IRQF_SHARED, ++ gadget_wrapper->gadget.name, otg_dev->pcd); ++ if (retval != 0) { ++ DWC_ERROR("request of irq%d failed\n", irqnum); ++ free_wrapper(gadget_wrapper); ++ return -EBUSY; ++ } ++ ++ ++ dwc_otg_pcd_start(gadget_wrapper->pcd, &fops); ++ ++ return retval; ++} ++ ++/** ++ * Cleanup the PCD. ++ */ ++void pcd_remove( struct platform_device *_dev ) ++{ ++ ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); ++ ++ dwc_otg_pcd_t *pcd = otg_dev->pcd; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _dev); ++ ++ /* ++ * Free the IRQ ++ */ ++ free_irq(_dev->resource[1].start, pcd); ++ free_wrapper(gadget_wrapper); ++ dwc_otg_pcd_remove(otg_dev->pcd); ++ otg_dev->pcd = 0; ++} ++ ++/** ++ * This function registers a gadget driver with the PCD. ++ * ++ * When a driver is successfully registered, it will receive control ++ * requests including set_configuration(), which enables non-control ++ * requests. then usb traffic follows until a disconnect is reported. ++ * then a host may connect again, or the driver might get unbound. ++ * ++ * @param driver The driver being registered ++ * @param bind The bind function of gadget driver ++ */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) ++int usb_gadget_register_driver(struct usb_gadget_driver *driver) ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ int usb_gadget_probe_driver(struct usb_gadget_driver *driver) ++#else ++int usb_gadget_probe_driver(struct usb_gadget_driver *driver, ++ int (*bind)(struct usb_gadget *)) ++#endif ++{ ++ int retval; ++ ++ DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n", ++ driver->driver.name); ++ ++ if (!driver || ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) ++ driver->speed == USB_SPEED_UNKNOWN || ++#else ++ driver->max_speed == USB_SPEED_UNKNOWN || ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ !driver->bind || ++#else ++ !bind || ++#endif ++ !driver->unbind || !driver->disconnect || !driver->setup) { ++ DWC_DEBUGPL(DBG_PCDV, "EINVAL\n"); ++ return -EINVAL; ++ } ++ if (gadget_wrapper == 0) { ++ DWC_DEBUGPL(DBG_PCDV, "ENODEV\n"); ++ return -ENODEV; ++ } ++ if (gadget_wrapper->driver != 0) { ++ DWC_DEBUGPL(DBG_PCDV, "EBUSY (%p)\n", gadget_wrapper->driver); ++ return -EBUSY; ++ } ++ ++ /* hook up the driver */ ++ gadget_wrapper->driver = driver; ++ gadget_wrapper->gadget.dev.driver = &driver->driver; ++ ++ DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) ++ retval = driver->bind(&gadget_wrapper->gadget); ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ retval = driver->bind(&gadget_wrapper->gadget,gadget_wrapper->driver); ++#else ++ retval = bind(&gadget_wrapper->gadget); ++#endif ++ if (retval) { ++ DWC_ERROR("bind to driver %s --> error %d\n", ++ driver->driver.name, retval); ++ gadget_wrapper->driver = 0; ++ gadget_wrapper->gadget.dev.driver = 0; ++ return retval; ++ } ++ DWC_DEBUGPL(DBG_ANY, "registered gadget driver '%s'\n", ++ driver->driver.name); ++ return 0; ++} ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) ++EXPORT_SYMBOL(usb_gadget_register_driver); ++#else ++EXPORT_SYMBOL(usb_gadget_probe_driver); ++#endif ++ ++/** ++ * This function unregisters a gadget driver ++ * ++ * @param driver The driver being unregistered ++ */ ++int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) ++{ ++ //DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _driver); ++ ++ if (gadget_wrapper == 0) { ++ DWC_DEBUGPL(DBG_ANY, "%s Return(%d): s_pcd==0\n", __func__, ++ -ENODEV); ++ return -ENODEV; ++ } ++ if (driver == 0 || driver != gadget_wrapper->driver) { ++ DWC_DEBUGPL(DBG_ANY, "%s Return(%d): driver?\n", __func__, ++ -EINVAL); ++ return -EINVAL; ++ } ++ ++ driver->disconnect(&gadget_wrapper->gadget); ++ driver->unbind(&gadget_wrapper->gadget); ++ gadget_wrapper->driver = 0; ++ ++ DWC_DEBUGPL(DBG_ANY, "unregistered driver '%s'\n", driver->driver.name); ++ return 0; ++} ++ ++EXPORT_SYMBOL(usb_gadget_unregister_driver); ++ ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_regs.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_regs.h +new file mode 100644 +index 0000000..b148c3d +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_regs.h +@@ -0,0 +1,2557 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $ ++ * $Revision: #99 $ ++ * $Date: 2012/12/10 $ ++ * $Change: 2123206 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 __DWC_OTG_REGS_H__ ++#define __DWC_OTG_REGS_H__ ++ ++#include "dwc_otg_core_if.h" ++ ++/** ++ * @file ++ * ++ * This file contains the data structures for accessing the DWC_otg core registers. ++ * ++ * The application interfaces with the HS OTG core by reading from and ++ * writing to the Control and Status Register (CSR) space through the ++ * AHB Slave interface. These registers are 32 bits wide, and the ++ * addresses are 32-bit-block aligned. ++ * CSRs are classified as follows: ++ * - Core Global Registers ++ * - Device Mode Registers ++ * - Device Global Registers ++ * - Device Endpoint Specific Registers ++ * - Host Mode Registers ++ * - Host Global Registers ++ * - Host Port CSRs ++ * - Host Channel Specific Registers ++ * ++ * Only the Core Global registers can be accessed in both Device and ++ * Host modes. When the HS OTG core is operating in one mode, either ++ * Device or Host, the application must not access registers from the ++ * other mode. When the core switches from one mode to another, the ++ * registers in the new mode of operation must be reprogrammed as they ++ * would be after a power-on reset. ++ */ ++ ++/****************************************************************************/ ++/** DWC_otg Core registers . ++ * The dwc_otg_core_global_regs structure defines the size ++ * and relative field offsets for the Core Global registers. ++ */ ++typedef struct dwc_otg_core_global_regs { ++ /** OTG Control and Status Register. Offset: 000h */ ++ volatile uint32_t gotgctl; ++ /** OTG Interrupt Register. Offset: 004h */ ++ volatile uint32_t gotgint; ++ /**Core AHB Configuration Register. Offset: 008h */ ++ volatile uint32_t gahbcfg; ++ ++#define DWC_GLBINTRMASK 0x0001 ++#define DWC_DMAENABLE 0x0020 ++#define DWC_NPTXEMPTYLVL_EMPTY 0x0080 ++#define DWC_NPTXEMPTYLVL_HALFEMPTY 0x0000 ++#define DWC_PTXEMPTYLVL_EMPTY 0x0100 ++#define DWC_PTXEMPTYLVL_HALFEMPTY 0x0000 ++ ++ /**Core USB Configuration Register. Offset: 00Ch */ ++ volatile uint32_t gusbcfg; ++ /**Core Reset Register. Offset: 010h */ ++ volatile uint32_t grstctl; ++ /**Core Interrupt Register. Offset: 014h */ ++ volatile uint32_t gintsts; ++ /**Core Interrupt Mask Register. Offset: 018h */ ++ volatile uint32_t gintmsk; ++ /**Receive Status Queue Read Register (Read Only). Offset: 01Ch */ ++ volatile uint32_t grxstsr; ++ /**Receive Status Queue Read & POP Register (Read Only). Offset: 020h*/ ++ volatile uint32_t grxstsp; ++ /**Receive FIFO Size Register. Offset: 024h */ ++ volatile uint32_t grxfsiz; ++ /**Non Periodic Transmit FIFO Size Register. Offset: 028h */ ++ volatile uint32_t gnptxfsiz; ++ /**Non Periodic Transmit FIFO/Queue Status Register (Read ++ * Only). Offset: 02Ch */ ++ volatile uint32_t gnptxsts; ++ /**I2C Access Register. Offset: 030h */ ++ volatile uint32_t gi2cctl; ++ /**PHY Vendor Control Register. Offset: 034h */ ++ volatile uint32_t gpvndctl; ++ /**General Purpose Input/Output Register. Offset: 038h */ ++ volatile uint32_t ggpio; ++ /**User ID Register. Offset: 03Ch */ ++ volatile uint32_t guid; ++ /**Synopsys ID Register (Read Only). Offset: 040h */ ++ volatile uint32_t gsnpsid; ++ /**User HW Config1 Register (Read Only). Offset: 044h */ ++ volatile uint32_t ghwcfg1; ++ /**User HW Config2 Register (Read Only). Offset: 048h */ ++ volatile uint32_t ghwcfg2; ++#define DWC_SLAVE_ONLY_ARCH 0 ++#define DWC_EXT_DMA_ARCH 1 ++#define DWC_INT_DMA_ARCH 2 ++ ++#define DWC_MODE_HNP_SRP_CAPABLE 0 ++#define DWC_MODE_SRP_ONLY_CAPABLE 1 ++#define DWC_MODE_NO_HNP_SRP_CAPABLE 2 ++#define DWC_MODE_SRP_CAPABLE_DEVICE 3 ++#define DWC_MODE_NO_SRP_CAPABLE_DEVICE 4 ++#define DWC_MODE_SRP_CAPABLE_HOST 5 ++#define DWC_MODE_NO_SRP_CAPABLE_HOST 6 ++ ++ /**User HW Config3 Register (Read Only). Offset: 04Ch */ ++ volatile uint32_t ghwcfg3; ++ /**User HW Config4 Register (Read Only). Offset: 050h*/ ++ volatile uint32_t ghwcfg4; ++ /** Core LPM Configuration register Offset: 054h*/ ++ volatile uint32_t glpmcfg; ++ /** Global PowerDn Register Offset: 058h */ ++ volatile uint32_t gpwrdn; ++ /** Global DFIFO SW Config Register Offset: 05Ch */ ++ volatile uint32_t gdfifocfg; ++ /** ADP Control Register Offset: 060h */ ++ volatile uint32_t adpctl; ++ /** Reserved Offset: 064h-0FFh */ ++ volatile uint32_t reserved39[39]; ++ /** Host Periodic Transmit FIFO Size Register. Offset: 100h */ ++ volatile uint32_t hptxfsiz; ++ /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled, ++ otherwise Device Transmit FIFO#n Register. ++ * Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15). */ ++ volatile uint32_t dtxfsiz[15]; ++} dwc_otg_core_global_regs_t; ++ ++/** ++ * This union represents the bit fields of the Core OTG Control ++ * and Status Register (GOTGCTL). Set the bits using the bit ++ * fields then write the d32 value to the register. ++ */ ++typedef union gotgctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned sesreqscs:1; ++ unsigned sesreq:1; ++ unsigned vbvalidoven:1; ++ unsigned vbvalidovval:1; ++ unsigned avalidoven:1; ++ unsigned avalidovval:1; ++ unsigned bvalidoven:1; ++ unsigned bvalidovval:1; ++ unsigned hstnegscs:1; ++ unsigned hnpreq:1; ++ unsigned hstsethnpen:1; ++ unsigned devhnpen:1; ++ unsigned reserved12_15:4; ++ unsigned conidsts:1; ++ unsigned dbnctime:1; ++ unsigned asesvld:1; ++ unsigned bsesvld:1; ++ unsigned otgver:1; ++ unsigned reserved1:1; ++ unsigned multvalidbc:5; ++ unsigned chirpen:1; ++ unsigned reserved28_31:4; ++ } b; ++} gotgctl_data_t; ++ ++/** ++ * This union represents the bit fields of the Core OTG Interrupt Register ++ * (GOTGINT). Set/clear the bits using the bit fields then write the d32 ++ * value to the register. ++ */ ++typedef union gotgint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Current Mode */ ++ unsigned reserved0_1:2; ++ ++ /** Session End Detected */ ++ unsigned sesenddet:1; ++ ++ unsigned reserved3_7:5; ++ ++ /** Session Request Success Status Change */ ++ unsigned sesreqsucstschng:1; ++ /** Host Negotiation Success Status Change */ ++ unsigned hstnegsucstschng:1; ++ ++ unsigned reserved10_16:7; ++ ++ /** Host Negotiation Detected */ ++ unsigned hstnegdet:1; ++ /** A-Device Timeout Change */ ++ unsigned adevtoutchng:1; ++ /** Debounce Done */ ++ unsigned debdone:1; ++ /** Multi-Valued input changed */ ++ unsigned mvic:1; ++ ++ unsigned reserved31_21:11; ++ ++ } b; ++} gotgint_data_t; ++ ++/** ++ * This union represents the bit fields of the Core AHB Configuration ++ * Register (GAHBCFG). Set/clear the bits using the bit fields then ++ * write the d32 value to the register. ++ */ ++typedef union gahbcfg_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned glblintrmsk:1; ++#define DWC_GAHBCFG_GLBINT_ENABLE 1 ++ ++ unsigned hburstlen:4; ++#define DWC_GAHBCFG_INT_DMA_BURST_SINGLE 0 ++#define DWC_GAHBCFG_INT_DMA_BURST_INCR 1 ++#define DWC_GAHBCFG_INT_DMA_BURST_INCR4 3 ++#define DWC_GAHBCFG_INT_DMA_BURST_INCR8 5 ++#define DWC_GAHBCFG_INT_DMA_BURST_INCR16 7 ++ ++ unsigned dmaenable:1; ++#define DWC_GAHBCFG_DMAENABLE 1 ++ unsigned reserved:1; ++ unsigned nptxfemplvl_txfemplvl:1; ++ unsigned ptxfemplvl:1; ++#define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY 1 ++#define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0 ++ unsigned reserved9_20:12; ++ unsigned remmemsupp:1; ++ unsigned notialldmawrit:1; ++ unsigned ahbsingle:1; ++ unsigned reserved24_31:8; ++ } b; ++} gahbcfg_data_t; ++ ++/** ++ * This union represents the bit fields of the Core USB Configuration ++ * Register (GUSBCFG). Set the bits using the bit fields then write ++ * the d32 value to the register. ++ */ ++typedef union gusbcfg_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned toutcal:3; ++ unsigned phyif:1; ++ unsigned ulpi_utmi_sel:1; ++ unsigned fsintf:1; ++ unsigned physel:1; ++ unsigned ddrsel:1; ++ unsigned srpcap:1; ++ unsigned hnpcap:1; ++ unsigned usbtrdtim:4; ++ unsigned reserved1:1; ++ unsigned phylpwrclksel:1; ++ unsigned otgutmifssel:1; ++ unsigned ulpi_fsls:1; ++ unsigned ulpi_auto_res:1; ++ unsigned ulpi_clk_sus_m:1; ++ unsigned ulpi_ext_vbus_drv:1; ++ unsigned ulpi_int_vbus_indicator:1; ++ unsigned term_sel_dl_pulse:1; ++ unsigned indicator_complement:1; ++ unsigned indicator_pass_through:1; ++ unsigned ulpi_int_prot_dis:1; ++ unsigned ic_usb_cap:1; ++ unsigned ic_traffic_pull_remove:1; ++ unsigned tx_end_delay:1; ++ unsigned force_host_mode:1; ++ unsigned force_dev_mode:1; ++ unsigned reserved31:1; ++ } b; ++} gusbcfg_data_t; ++ ++/** ++ * This union represents the bit fields of the Core Reset Register ++ * (GRSTCTL). Set/clear the bits using the bit fields then write the ++ * d32 value to the register. ++ */ ++typedef union grstctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Core Soft Reset (CSftRst) (Device and Host) ++ * ++ * The application can flush the control logic in the ++ * entire core using this bit. This bit resets the ++ * pipelines in the AHB Clock domain as well as the ++ * PHY Clock domain. ++ * ++ * The state machines are reset to an IDLE state, the ++ * control bits in the CSRs are cleared, all the ++ * transmit FIFOs and the receive FIFO are flushed. ++ * ++ * The status mask bits that control the generation of ++ * the interrupt, are cleared, to clear the ++ * interrupt. The interrupt status bits are not ++ * cleared, so the application can get the status of ++ * any events that occurred in the core after it has ++ * set this bit. ++ * ++ * Any transactions on the AHB are terminated as soon ++ * as possible following the protocol. Any ++ * transactions on the USB are terminated immediately. ++ * ++ * The configuration settings in the CSRs are ++ * unchanged, so the software doesn't have to ++ * reprogram these registers (Device ++ * Configuration/Host Configuration/Core System ++ * Configuration/Core PHY Configuration). ++ * ++ * The application can write to this bit, any time it ++ * wants to reset the core. This is a self clearing ++ * bit and the core clears this bit after all the ++ * necessary logic is reset in the core, which may ++ * take several clocks, depending on the current state ++ * of the core. ++ */ ++ unsigned csftrst:1; ++ /** Hclk Soft Reset ++ * ++ * The application uses this bit to reset the control logic in ++ * the AHB clock domain. Only AHB clock domain pipelines are ++ * reset. ++ */ ++ unsigned hsftrst:1; ++ /** Host Frame Counter Reset (Host Only)
++ * ++ * The application can reset the (micro)frame number ++ * counter inside the core, using this bit. When the ++ * (micro)frame counter is reset, the subsequent SOF ++ * sent out by the core, will have a (micro)frame ++ * number of 0. ++ */ ++ unsigned hstfrm:1; ++ /** In Token Sequence Learning Queue Flush ++ * (INTknQFlsh) (Device Only) ++ */ ++ unsigned intknqflsh:1; ++ /** RxFIFO Flush (RxFFlsh) (Device and Host) ++ * ++ * The application can flush the entire Receive FIFO ++ * using this bit. The application must first ++ * ensure that the core is not in the middle of a ++ * transaction. The application should write into ++ * this bit, only after making sure that neither the ++ * DMA engine is reading from the RxFIFO nor the MAC ++ * is writing the data in to the FIFO. The ++ * application should wait until the bit is cleared ++ * before performing any other operations. This bit ++ * will takes 8 clocks (slowest of PHY or AHB clock) ++ * to clear. ++ */ ++ unsigned rxfflsh:1; ++ /** TxFIFO Flush (TxFFlsh) (Device and Host). ++ * ++ * This bit is used to selectively flush a single or ++ * all transmit FIFOs. The application must first ++ * ensure that the core is not in the middle of a ++ * transaction. The application should write into ++ * this bit, only after making sure that neither the ++ * DMA engine is writing into the TxFIFO nor the MAC ++ * is reading the data out of the FIFO. The ++ * application should wait until the core clears this ++ * bit, before performing any operations. This bit ++ * will takes 8 clocks (slowest of PHY or AHB clock) ++ * to clear. ++ */ ++ unsigned txfflsh:1; ++ ++ /** TxFIFO Number (TxFNum) (Device and Host). ++ * ++ * This is the FIFO number which needs to be flushed, ++ * using the TxFIFO Flush bit. This field should not ++ * be changed until the TxFIFO Flush bit is cleared by ++ * the core. ++ * - 0x0 : Non Periodic TxFIFO Flush ++ * - 0x1 : Periodic TxFIFO #1 Flush in device mode ++ * or Periodic TxFIFO in host mode ++ * - 0x2 : Periodic TxFIFO #2 Flush in device mode. ++ * - ... ++ * - 0xF : Periodic TxFIFO #15 Flush in device mode ++ * - 0x10: Flush all the Transmit NonPeriodic and ++ * Transmit Periodic FIFOs in the core ++ */ ++ unsigned txfnum:5; ++ /** Reserved */ ++ unsigned reserved11_29:19; ++ /** DMA Request Signal. Indicated DMA request is in ++ * probress. Used for debug purpose. */ ++ unsigned dmareq:1; ++ /** AHB Master Idle. Indicates the AHB Master State ++ * Machine is in IDLE condition. */ ++ unsigned ahbidle:1; ++ } b; ++} grstctl_t; ++ ++/** ++ * This union represents the bit fields of the Core Interrupt Mask ++ * Register (GINTMSK). Set/clear the bits using the bit fields then ++ * write the d32 value to the register. ++ */ ++typedef union gintmsk_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned reserved0:1; ++ unsigned modemismatch:1; ++ unsigned otgintr:1; ++ unsigned sofintr:1; ++ unsigned rxstsqlvl:1; ++ unsigned nptxfempty:1; ++ unsigned ginnakeff:1; ++ unsigned goutnakeff:1; ++ unsigned ulpickint:1; ++ unsigned i2cintr:1; ++ unsigned erlysuspend:1; ++ unsigned usbsuspend:1; ++ unsigned usbreset:1; ++ unsigned enumdone:1; ++ unsigned isooutdrop:1; ++ unsigned eopframe:1; ++ unsigned restoredone:1; ++ unsigned epmismatch:1; ++ unsigned inepintr:1; ++ unsigned outepintr:1; ++ unsigned incomplisoin:1; ++ unsigned incomplisoout:1; ++ unsigned fetsusp:1; ++ unsigned resetdet:1; ++ unsigned portintr:1; ++ unsigned hcintr:1; ++ unsigned ptxfempty:1; ++ unsigned lpmtranrcvd:1; ++ unsigned conidstschng:1; ++ unsigned disconnect:1; ++ unsigned sessreqintr:1; ++ unsigned wkupintr:1; ++ } b; ++} gintmsk_data_t; ++/** ++ * This union represents the bit fields of the Core Interrupt Register ++ * (GINTSTS). Set/clear the bits using the bit fields then write the ++ * d32 value to the register. ++ */ ++typedef union gintsts_data { ++ /** raw register data */ ++ uint32_t d32; ++#define DWC_SOF_INTR_MASK 0x0008 ++ /** register bits */ ++ struct { ++#define DWC_HOST_MODE 1 ++ unsigned curmode:1; ++ unsigned modemismatch:1; ++ unsigned otgintr:1; ++ unsigned sofintr:1; ++ unsigned rxstsqlvl:1; ++ unsigned nptxfempty:1; ++ unsigned ginnakeff:1; ++ unsigned goutnakeff:1; ++ unsigned ulpickint:1; ++ unsigned i2cintr:1; ++ unsigned erlysuspend:1; ++ unsigned usbsuspend:1; ++ unsigned usbreset:1; ++ unsigned enumdone:1; ++ unsigned isooutdrop:1; ++ unsigned eopframe:1; ++ unsigned restoredone:1; ++ unsigned epmismatch:1; ++ unsigned inepint:1; ++ unsigned outepintr:1; ++ unsigned incomplisoin:1; ++ unsigned incomplisoout:1; ++ unsigned fetsusp:1; ++ unsigned resetdet:1; ++ unsigned portintr:1; ++ unsigned hcintr:1; ++ unsigned ptxfempty:1; ++ unsigned lpmtranrcvd:1; ++ unsigned conidstschng:1; ++ unsigned disconnect:1; ++ unsigned sessreqintr:1; ++ unsigned wkupintr:1; ++ } b; ++} gintsts_data_t; ++ ++/** ++ * This union represents the bit fields in the Device Receive Status Read and ++ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the d32 ++ * element then read out the bits using the bit elements. ++ */ ++typedef union device_grxsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned epnum:4; ++ unsigned bcnt:11; ++ unsigned dpid:2; ++ ++#define DWC_STS_DATA_UPDT 0x2 // OUT Data Packet ++#define DWC_STS_XFER_COMP 0x3 // OUT Data Transfer Complete ++ ++#define DWC_DSTS_GOUT_NAK 0x1 // Global OUT NAK ++#define DWC_DSTS_SETUP_COMP 0x4 // Setup Phase Complete ++#define DWC_DSTS_SETUP_UPDT 0x6 // SETUP Packet ++ unsigned pktsts:4; ++ unsigned fn:4; ++ unsigned reserved25_31:7; ++ } b; ++} device_grxsts_data_t; ++ ++/** ++ * This union represents the bit fields in the Host Receive Status Read and ++ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the d32 ++ * element then read out the bits using the bit elements. ++ */ ++typedef union host_grxsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned chnum:4; ++ unsigned bcnt:11; ++ unsigned dpid:2; ++ ++ unsigned pktsts:4; ++#define DWC_GRXSTS_PKTSTS_IN 0x2 ++#define DWC_GRXSTS_PKTSTS_IN_XFER_COMP 0x3 ++#define DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5 ++#define DWC_GRXSTS_PKTSTS_CH_HALTED 0x7 ++ ++ unsigned reserved21_31:11; ++ } b; ++} host_grxsts_data_t; ++ ++/** ++ * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ, ++ * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the d32 element ++ * then read out the bits using the bit elements. ++ */ ++typedef union fifosize_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned startaddr:16; ++ unsigned depth:16; ++ } b; ++} fifosize_data_t; ++ ++/** ++ * This union represents the bit fields in the Non-Periodic Transmit ++ * FIFO/Queue Status Register (GNPTXSTS). Read the register into the ++ * d32 element then read out the bits using the bit ++ * elements. ++ */ ++typedef union gnptxsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned nptxfspcavail:16; ++ unsigned nptxqspcavail:8; ++ /** Top of the Non-Periodic Transmit Request Queue ++ * - bit 24 - Terminate (Last entry for the selected ++ * channel/EP) ++ * - bits 26:25 - Token Type ++ * - 2'b00 - IN/OUT ++ * - 2'b01 - Zero Length OUT ++ * - 2'b10 - PING/Complete Split ++ * - 2'b11 - Channel Halt ++ * - bits 30:27 - Channel/EP Number ++ */ ++ unsigned nptxqtop_terminate:1; ++ unsigned nptxqtop_token:2; ++ unsigned nptxqtop_chnep:4; ++ unsigned reserved:1; ++ } b; ++} gnptxsts_data_t; ++ ++/** ++ * This union represents the bit fields in the Transmit ++ * FIFO Status Register (DTXFSTS). Read the register into the ++ * d32 element then read out the bits using the bit ++ * elements. ++ */ ++typedef union dtxfsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned txfspcavail:16; ++ unsigned reserved:16; ++ } b; ++} dtxfsts_data_t; ++ ++/** ++ * This union represents the bit fields in the I2C Control Register ++ * (I2CCTL). Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++typedef union gi2cctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned rwdata:8; ++ unsigned regaddr:8; ++ unsigned addr:7; ++ unsigned i2cen:1; ++ unsigned ack:1; ++ unsigned i2csuspctl:1; ++ unsigned i2cdevaddr:2; ++ unsigned i2cdatse0:1; ++ unsigned reserved:1; ++ unsigned rw:1; ++ unsigned bsydne:1; ++ } b; ++} gi2cctl_data_t; ++ ++/** ++ * This union represents the bit fields in the PHY Vendor Control Register ++ * (GPVNDCTL). Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++typedef union gpvndctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned regdata:8; ++ unsigned vctrl:8; ++ unsigned regaddr16_21:6; ++ unsigned regwr:1; ++ unsigned reserved23_24:2; ++ unsigned newregreq:1; ++ unsigned vstsbsy:1; ++ unsigned vstsdone:1; ++ unsigned reserved28_30:3; ++ unsigned disulpidrvr:1; ++ } b; ++} gpvndctl_data_t; ++ ++/** ++ * This union represents the bit fields in the General Purpose ++ * Input/Output Register (GGPIO). ++ * Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++typedef union ggpio_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned gpi:16; ++ unsigned gpo:16; ++ } b; ++} ggpio_data_t; ++ ++/** ++ * This union represents the bit fields in the User ID Register ++ * (GUID). Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++typedef union guid_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned rwdata:32; ++ } b; ++} guid_data_t; ++ ++/** ++ * This union represents the bit fields in the Synopsys ID Register ++ * (GSNPSID). Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++typedef union gsnpsid_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned rwdata:32; ++ } b; ++} gsnpsid_data_t; ++ ++/** ++ * This union represents the bit fields in the User HW Config1 ++ * Register. Read the register into the d32 element then read ++ * out the bits using the bit elements. ++ */ ++typedef union hwcfg1_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned ep_dir0:2; ++ unsigned ep_dir1:2; ++ unsigned ep_dir2:2; ++ unsigned ep_dir3:2; ++ unsigned ep_dir4:2; ++ unsigned ep_dir5:2; ++ unsigned ep_dir6:2; ++ unsigned ep_dir7:2; ++ unsigned ep_dir8:2; ++ unsigned ep_dir9:2; ++ unsigned ep_dir10:2; ++ unsigned ep_dir11:2; ++ unsigned ep_dir12:2; ++ unsigned ep_dir13:2; ++ unsigned ep_dir14:2; ++ unsigned ep_dir15:2; ++ } b; ++} hwcfg1_data_t; ++ ++/** ++ * This union represents the bit fields in the User HW Config2 ++ * Register. Read the register into the d32 element then read ++ * out the bits using the bit elements. ++ */ ++typedef union hwcfg2_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /* GHWCFG2 */ ++ unsigned op_mode:3; ++#define DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG 0 ++#define DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1 ++#define DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2 ++#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3 ++#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4 ++#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5 ++#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6 ++ ++ unsigned architecture:2; ++ unsigned point2point:1; ++ unsigned hs_phy_type:2; ++#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0 ++#define DWC_HWCFG2_HS_PHY_TYPE_UTMI 1 ++#define DWC_HWCFG2_HS_PHY_TYPE_ULPI 2 ++#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3 ++ ++ unsigned fs_phy_type:2; ++ unsigned num_dev_ep:4; ++ unsigned num_host_chan:4; ++ unsigned perio_ep_supported:1; ++ unsigned dynamic_fifo:1; ++ unsigned multi_proc_int:1; ++ unsigned reserved21:1; ++ unsigned nonperio_tx_q_depth:2; ++ unsigned host_perio_tx_q_depth:2; ++ unsigned dev_token_q_depth:5; ++ unsigned otg_enable_ic_usb:1; ++ } b; ++} hwcfg2_data_t; ++ ++/** ++ * This union represents the bit fields in the User HW Config3 ++ * Register. Read the register into the d32 element then read ++ * out the bits using the bit elements. ++ */ ++typedef union hwcfg3_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /* GHWCFG3 */ ++ unsigned xfer_size_cntr_width:4; ++ unsigned packet_size_cntr_width:3; ++ unsigned otg_func:1; ++ unsigned i2c:1; ++ unsigned vendor_ctrl_if:1; ++ unsigned optional_features:1; ++ unsigned synch_reset_type:1; ++ unsigned adp_supp:1; ++ unsigned otg_enable_hsic:1; ++ unsigned bc_support:1; ++ unsigned otg_lpm_en:1; ++ unsigned dfifo_depth:16; ++ } b; ++} hwcfg3_data_t; ++ ++/** ++ * This union represents the bit fields in the User HW Config4 ++ * Register. Read the register into the d32 element then read ++ * out the bits using the bit elements. ++ */ ++typedef union hwcfg4_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned num_dev_perio_in_ep:4; ++ unsigned power_optimiz:1; ++ unsigned min_ahb_freq:1; ++ unsigned hiber:1; ++ unsigned xhiber:1; ++ unsigned reserved:6; ++ unsigned utmi_phy_data_width:2; ++ unsigned num_dev_mode_ctrl_ep:4; ++ unsigned iddig_filt_en:1; ++ unsigned vbus_valid_filt_en:1; ++ unsigned a_valid_filt_en:1; ++ unsigned b_valid_filt_en:1; ++ unsigned session_end_filt_en:1; ++ unsigned ded_fifo_en:1; ++ unsigned num_in_eps:4; ++ unsigned desc_dma:1; ++ unsigned desc_dma_dyn:1; ++ } b; ++} hwcfg4_data_t; ++ ++/** ++ * This union represents the bit fields of the Core LPM Configuration ++ * Register (GLPMCFG). Set the bits using bit fields then write ++ * the d32 value to the register. ++ */ ++typedef union glpmctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** LPM-Capable (LPMCap) (Device and Host) ++ * The application uses this bit to control ++ * the DWC_otg core LPM capabilities. ++ */ ++ unsigned lpm_cap_en:1; ++ /** LPM response programmed by application (AppL1Res) (Device) ++ * Handshake response to LPM token pre-programmed ++ * by device application software. ++ */ ++ unsigned appl_resp:1; ++ /** Host Initiated Resume Duration (HIRD) (Device and Host) ++ * In Host mode this field indicates the value of HIRD ++ * to be sent in an LPM transaction. ++ * In Device mode this field is updated with the ++ * Received LPM Token HIRD bmAttribute ++ * when an ACK/NYET/STALL response is sent ++ * to an LPM transaction. ++ */ ++ unsigned hird:4; ++ /** RemoteWakeEnable (bRemoteWake) (Device and Host) ++ * In Host mode this bit indicates the value of remote ++ * wake up to be sent in wIndex field of LPM transaction. ++ * In Device mode this field is updated with the ++ * Received LPM Token bRemoteWake bmAttribute ++ * when an ACK/NYET/STALL response is sent ++ * to an LPM transaction. ++ */ ++ unsigned rem_wkup_en:1; ++ /** Enable utmi_sleep_n (EnblSlpM) (Device and Host) ++ * The application uses this bit to control ++ * the utmi_sleep_n assertion to the PHY when in L1 state. ++ */ ++ unsigned en_utmi_sleep:1; ++ /** HIRD Threshold (HIRD_Thres) (Device and Host) ++ */ ++ unsigned hird_thres:5; ++ /** LPM Response (CoreL1Res) (Device and Host) ++ * In Host mode this bit contains handsake response to ++ * LPM transaction. ++ * In Device mode the response of the core to ++ * LPM transaction received is reflected in these two bits. ++ - 0x0 : ERROR (No handshake response) ++ - 0x1 : STALL ++ - 0x2 : NYET ++ - 0x3 : ACK ++ */ ++ unsigned lpm_resp:2; ++ /** Port Sleep Status (SlpSts) (Device and Host) ++ * This bit is set as long as a Sleep condition ++ * is present on the USB bus. ++ */ ++ unsigned prt_sleep_sts:1; ++ /** Sleep State Resume OK (L1ResumeOK) (Device and Host) ++ * Indicates that the application or host ++ * can start resume from Sleep state. ++ */ ++ unsigned sleep_state_resumeok:1; ++ /** LPM channel Index (LPM_Chnl_Indx) (Host) ++ * The channel number on which the LPM transaction ++ * has to be applied while sending ++ * an LPM transaction to the local device. ++ */ ++ unsigned lpm_chan_index:4; ++ /** LPM Retry Count (LPM_Retry_Cnt) (Host) ++ * Number host retries that would be performed ++ * if the device response was not valid response. ++ */ ++ unsigned retry_count:3; ++ /** Send LPM Transaction (SndLPM) (Host) ++ * When set by application software, ++ * an LPM transaction containing two tokens ++ * is sent. ++ */ ++ unsigned send_lpm:1; ++ /** LPM Retry status (LPM_RetryCnt_Sts) (Host) ++ * Number of LPM Host Retries still remaining ++ * to be transmitted for the current LPM sequence ++ */ ++ unsigned retry_count_sts:3; ++ /** Enable Best Effort Service Latency (BESL) (Device and Host) ++ * This bit enables the BESL features as defined in the LPM errata ++ */ ++ unsigned en_besl:1; ++ ++ unsigned reserved29:1; ++ /** In host mode once this bit is set, the host ++ * configures to drive the HSIC Idle state on the bus. ++ * It then waits for the device to initiate the Connect sequence. ++ * In device mode once this bit is set, the device waits for ++ * the HSIC Idle line state on the bus. Upon receving the Idle ++ * line state, it initiates the HSIC Connect sequence. ++ */ ++ unsigned hsic_connect:1; ++ /** This bit overrides and functionally inverts ++ * the if_select_hsic input port signal. ++ */ ++ unsigned inv_sel_hsic:1; ++ } b; ++} glpmcfg_data_t; ++ ++/** ++ * This union represents the bit fields of the Core ADP Timer, Control and ++ * Status Register (ADPTIMCTLSTS). Set the bits using bit fields then write ++ * the d32 value to the register. ++ */ ++typedef union adpctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Probe Discharge (PRB_DSCHG) ++ * These bits set the times for TADP_DSCHG. ++ * These bits are defined as follows: ++ * 2'b00 - 4 msec ++ * 2'b01 - 8 msec ++ * 2'b10 - 16 msec ++ * 2'b11 - 32 msec ++ */ ++ unsigned prb_dschg:2; ++ /** Probe Delta (PRB_DELTA) ++ * These bits set the resolution for RTIM value. ++ * The bits are defined in units of 32 kHz clock cycles as follows: ++ * 2'b00 - 1 cycles ++ * 2'b01 - 2 cycles ++ * 2'b10 - 3 cycles ++ * 2'b11 - 4 cycles ++ * For example if this value is chosen to 2'b01, it means that RTIM ++ * increments for every 3(three) 32Khz clock cycles. ++ */ ++ unsigned prb_delta:2; ++ /** Probe Period (PRB_PER) ++ * These bits sets the TADP_PRD as shown in Figure 4 as follows: ++ * 2'b00 - 0.625 to 0.925 sec (typical 0.775 sec) ++ * 2'b01 - 1.25 to 1.85 sec (typical 1.55 sec) ++ * 2'b10 - 1.9 to 2.6 sec (typical 2.275 sec) ++ * 2'b11 - Reserved ++ */ ++ unsigned prb_per:2; ++ /** These bits capture the latest time it took for VBUS to ramp from ++ * VADP_SINK to VADP_PRB. ++ * 0x000 - 1 cycles ++ * 0x001 - 2 cycles ++ * 0x002 - 3 cycles ++ * etc ++ * 0x7FF - 2048 cycles ++ * A time of 1024 cycles at 32 kHz corresponds to a time of 32 msec. ++ */ ++ unsigned rtim:11; ++ /** Enable Probe (EnaPrb) ++ * When programmed to 1'b1, the core performs a probe operation. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned enaprb:1; ++ /** Enable Sense (EnaSns) ++ * When programmed to 1'b1, the core performs a Sense operation. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned enasns:1; ++ /** ADP Reset (ADPRes) ++ * When set, ADP controller is reset. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adpres:1; ++ /** ADP Enable (ADPEn) ++ * When set, the core performs either ADP probing or sensing ++ * based on EnaPrb or EnaSns. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adpen:1; ++ /** ADP Probe Interrupt (ADP_PRB_INT) ++ * When this bit is set, it means that the VBUS ++ * voltage is greater than VADP_PRB or VADP_PRB is reached. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_prb_int:1; ++ /** ++ * ADP Sense Interrupt (ADP_SNS_INT) ++ * When this bit is set, it means that the VBUS voltage is greater than ++ * VADP_SNS value or VADP_SNS is reached. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_sns_int:1; ++ /** ADP Tomeout Interrupt (ADP_TMOUT_INT) ++ * This bit is relevant only for an ADP probe. ++ * When this bit is set, it means that the ramp time has ++ * completed ie ADPCTL.RTIM has reached its terminal value ++ * of 0x7FF. This is a debug feature that allows software ++ * to read the ramp time after each cycle. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_tmout_int:1; ++ /** ADP Probe Interrupt Mask (ADP_PRB_INT_MSK) ++ * When this bit is set, it unmasks the interrupt due to ADP_PRB_INT. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_prb_int_msk:1; ++ /** ADP Sense Interrupt Mask (ADP_SNS_INT_MSK) ++ * When this bit is set, it unmasks the interrupt due to ADP_SNS_INT. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_sns_int_msk:1; ++ /** ADP Timoeout Interrupt Mask (ADP_TMOUT_MSK) ++ * When this bit is set, it unmasks the interrupt due to ADP_TMOUT_INT. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_tmout_int_msk:1; ++ /** Access Request ++ * 2'b00 - Read/Write Valid (updated by the core) ++ * 2'b01 - Read ++ * 2'b00 - Write ++ * 2'b00 - Reserved ++ */ ++ unsigned ar:2; ++ /** Reserved */ ++ unsigned reserved29_31:3; ++ } b; ++} adpctl_data_t; ++ ++//////////////////////////////////////////// ++// Device Registers ++/** ++ * Device Global Registers. Offsets 800h-BFFh ++ * ++ * The following structures define the size and relative field offsets ++ * for the Device Mode Registers. ++ * ++ * These registers are visible only in Device mode and must not be ++ * accessed in Host mode, as the results are unknown. ++ */ ++typedef struct dwc_otg_dev_global_regs { ++ /** Device Configuration Register. Offset 800h */ ++ volatile uint32_t dcfg; ++ /** Device Control Register. Offset: 804h */ ++ volatile uint32_t dctl; ++ /** Device Status Register (Read Only). Offset: 808h */ ++ volatile uint32_t dsts; ++ /** Reserved. Offset: 80Ch */ ++ uint32_t unused; ++ /** Device IN Endpoint Common Interrupt Mask ++ * Register. Offset: 810h */ ++ volatile uint32_t diepmsk; ++ /** Device OUT Endpoint Common Interrupt Mask ++ * Register. Offset: 814h */ ++ volatile uint32_t doepmsk; ++ /** Device All Endpoints Interrupt Register. Offset: 818h */ ++ volatile uint32_t daint; ++ /** Device All Endpoints Interrupt Mask Register. Offset: ++ * 81Ch */ ++ volatile uint32_t daintmsk; ++ /** Device IN Token Queue Read Register-1 (Read Only). ++ * Offset: 820h */ ++ volatile uint32_t dtknqr1; ++ /** Device IN Token Queue Read Register-2 (Read Only). ++ * Offset: 824h */ ++ volatile uint32_t dtknqr2; ++ /** Device VBUS discharge Register. Offset: 828h */ ++ volatile uint32_t dvbusdis; ++ /** Device VBUS Pulse Register. Offset: 82Ch */ ++ volatile uint32_t dvbuspulse; ++ /** Device IN Token Queue Read Register-3 (Read Only). / ++ * Device Thresholding control register (Read/Write) ++ * Offset: 830h */ ++ volatile uint32_t dtknqr3_dthrctl; ++ /** Device IN Token Queue Read Register-4 (Read Only). / ++ * Device IN EPs empty Inr. Mask Register (Read/Write) ++ * Offset: 834h */ ++ volatile uint32_t dtknqr4_fifoemptymsk; ++ /** Device Each Endpoint Interrupt Register (Read Only). / ++ * Offset: 838h */ ++ volatile uint32_t deachint; ++ /** Device Each Endpoint Interrupt mask Register (Read/Write). / ++ * Offset: 83Ch */ ++ volatile uint32_t deachintmsk; ++ /** Device Each In Endpoint Interrupt mask Register (Read/Write). / ++ * Offset: 840h */ ++ volatile uint32_t diepeachintmsk[MAX_EPS_CHANNELS]; ++ /** Device Each Out Endpoint Interrupt mask Register (Read/Write). / ++ * Offset: 880h */ ++ volatile uint32_t doepeachintmsk[MAX_EPS_CHANNELS]; ++} dwc_otg_device_global_regs_t; ++ ++/** ++ * This union represents the bit fields in the Device Configuration ++ * Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. Write the ++ * d32 member to the dcfg register. ++ */ ++typedef union dcfg_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Device Speed */ ++ unsigned devspd:2; ++ /** Non Zero Length Status OUT Handshake */ ++ unsigned nzstsouthshk:1; ++#define DWC_DCFG_SEND_STALL 1 ++ ++ unsigned ena32khzs:1; ++ /** Device Addresses */ ++ unsigned devaddr:7; ++ /** Periodic Frame Interval */ ++ unsigned perfrint:2; ++#define DWC_DCFG_FRAME_INTERVAL_80 0 ++#define DWC_DCFG_FRAME_INTERVAL_85 1 ++#define DWC_DCFG_FRAME_INTERVAL_90 2 ++#define DWC_DCFG_FRAME_INTERVAL_95 3 ++ ++ /** Enable Device OUT NAK for bulk in DDMA mode */ ++ unsigned endevoutnak:1; ++ ++ unsigned reserved14_17:4; ++ /** In Endpoint Mis-match count */ ++ unsigned epmscnt:5; ++ /** Enable Descriptor DMA in Device mode */ ++ unsigned descdma:1; ++ unsigned perschintvl:2; ++ unsigned resvalid:6; ++ } b; ++} dcfg_data_t; ++ ++/** ++ * This union represents the bit fields in the Device Control ++ * Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union dctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Remote Wakeup */ ++ unsigned rmtwkupsig:1; ++ /** Soft Disconnect */ ++ unsigned sftdiscon:1; ++ /** Global Non-Periodic IN NAK Status */ ++ unsigned gnpinnaksts:1; ++ /** Global OUT NAK Status */ ++ unsigned goutnaksts:1; ++ /** Test Control */ ++ unsigned tstctl:3; ++ /** Set Global Non-Periodic IN NAK */ ++ unsigned sgnpinnak:1; ++ /** Clear Global Non-Periodic IN NAK */ ++ unsigned cgnpinnak:1; ++ /** Set Global OUT NAK */ ++ unsigned sgoutnak:1; ++ /** Clear Global OUT NAK */ ++ unsigned cgoutnak:1; ++ /** Power-On Programming Done */ ++ unsigned pwronprgdone:1; ++ /** Reserved */ ++ unsigned reserved:1; ++ /** Global Multi Count */ ++ unsigned gmc:2; ++ /** Ignore Frame Number for ISOC EPs */ ++ unsigned ifrmnum:1; ++ /** NAK on Babble */ ++ unsigned nakonbble:1; ++ /** Enable Continue on BNA */ ++ unsigned encontonbna:1; ++ /** Enable deep sleep besl reject feature*/ ++ unsigned besl_reject:1; ++ ++ unsigned reserved17_31:13; ++ } b; ++} dctl_data_t; ++ ++/** ++ * This union represents the bit fields in the Device Status ++ * Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union dsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Suspend Status */ ++ unsigned suspsts:1; ++ /** Enumerated Speed */ ++ unsigned enumspd:2; ++#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0 ++#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1 ++#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ 2 ++#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ 3 ++ /** Erratic Error */ ++ unsigned errticerr:1; ++ unsigned reserved4_7:4; ++ /** Frame or Microframe Number of the received SOF */ ++ unsigned soffn:14; ++ unsigned reserved22_31:10; ++ } b; ++} dsts_data_t; ++ ++/** ++ * This union represents the bit fields in the Device IN EP Interrupt ++ * Register and the Device IN EP Common Mask Register. ++ * ++ * - Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++typedef union diepint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer complete mask */ ++ unsigned xfercompl:1; ++ /** Endpoint disable mask */ ++ unsigned epdisabled:1; ++ /** AHB Error mask */ ++ unsigned ahberr:1; ++ /** TimeOUT Handshake mask (non-ISOC EPs) */ ++ unsigned timeout:1; ++ /** IN Token received with TxF Empty mask */ ++ unsigned intktxfemp:1; ++ /** IN Token Received with EP mismatch mask */ ++ unsigned intknepmis:1; ++ /** IN Endpoint NAK Effective mask */ ++ unsigned inepnakeff:1; ++ /** Reserved */ ++ unsigned emptyintr:1; ++ ++ unsigned txfifoundrn:1; ++ ++ /** BNA Interrupt mask */ ++ unsigned bna:1; ++ ++ unsigned reserved10_12:3; ++ /** BNA Interrupt mask */ ++ unsigned nak:1; ++ ++ unsigned reserved14_31:18; ++ } b; ++} diepint_data_t; ++ ++/** ++ * This union represents the bit fields in the Device IN EP ++ * Common/Dedicated Interrupt Mask Register. ++ */ ++typedef union diepint_data diepmsk_data_t; ++ ++/** ++ * This union represents the bit fields in the Device OUT EP Interrupt ++ * Registerand Device OUT EP Common Interrupt Mask Register. ++ * ++ * - Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++typedef union doepint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer complete */ ++ unsigned xfercompl:1; ++ /** Endpoint disable */ ++ unsigned epdisabled:1; ++ /** AHB Error */ ++ unsigned ahberr:1; ++ /** Setup Phase Done (contorl EPs) */ ++ unsigned setup:1; ++ /** OUT Token Received when Endpoint Disabled */ ++ unsigned outtknepdis:1; ++ ++ unsigned stsphsercvd:1; ++ /** Back-to-Back SETUP Packets Received */ ++ unsigned back2backsetup:1; ++ ++ unsigned reserved7:1; ++ /** OUT packet Error */ ++ unsigned outpkterr:1; ++ /** BNA Interrupt */ ++ unsigned bna:1; ++ ++ unsigned reserved10:1; ++ /** Packet Drop Status */ ++ unsigned pktdrpsts:1; ++ /** Babble Interrupt */ ++ unsigned babble:1; ++ /** NAK Interrupt */ ++ unsigned nak:1; ++ /** NYET Interrupt */ ++ unsigned nyet:1; ++ /** Bit indicating setup packet received */ ++ unsigned sr:1; ++ ++ unsigned reserved16_31:16; ++ } b; ++} doepint_data_t; ++ ++/** ++ * This union represents the bit fields in the Device OUT EP ++ * Common/Dedicated Interrupt Mask Register. ++ */ ++typedef union doepint_data doepmsk_data_t; ++ ++/** ++ * This union represents the bit fields in the Device All EP Interrupt ++ * and Mask Registers. ++ * - Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++typedef union daint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** IN Endpoint bits */ ++ unsigned in:16; ++ /** OUT Endpoint bits */ ++ unsigned out:16; ++ } ep; ++ struct { ++ /** IN Endpoint bits */ ++ unsigned inep0:1; ++ unsigned inep1:1; ++ unsigned inep2:1; ++ unsigned inep3:1; ++ unsigned inep4:1; ++ unsigned inep5:1; ++ unsigned inep6:1; ++ unsigned inep7:1; ++ unsigned inep8:1; ++ unsigned inep9:1; ++ unsigned inep10:1; ++ unsigned inep11:1; ++ unsigned inep12:1; ++ unsigned inep13:1; ++ unsigned inep14:1; ++ unsigned inep15:1; ++ /** OUT Endpoint bits */ ++ unsigned outep0:1; ++ unsigned outep1:1; ++ unsigned outep2:1; ++ unsigned outep3:1; ++ unsigned outep4:1; ++ unsigned outep5:1; ++ unsigned outep6:1; ++ unsigned outep7:1; ++ unsigned outep8:1; ++ unsigned outep9:1; ++ unsigned outep10:1; ++ unsigned outep11:1; ++ unsigned outep12:1; ++ unsigned outep13:1; ++ unsigned outep14:1; ++ unsigned outep15:1; ++ } b; ++} daint_data_t; ++ ++/** ++ * This union represents the bit fields in the Device IN Token Queue ++ * Read Registers. ++ * - Read the register into the d32 member. ++ * - READ-ONLY Register ++ */ ++typedef union dtknq1_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** In Token Queue Write Pointer */ ++ unsigned intknwptr:5; ++ /** Reserved */ ++ unsigned reserved05_06:2; ++ /** write pointer has wrapped. */ ++ unsigned wrap_bit:1; ++ /** EP Numbers of IN Tokens 0 ... 4 */ ++ unsigned epnums0_5:24; ++ } b; ++} dtknq1_data_t; ++ ++/** ++ * This union represents Threshold control Register ++ * - Read and write the register into the d32 member. ++ * - READ-WRITABLE Register ++ */ ++typedef union dthrctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** non ISO Tx Thr. Enable */ ++ unsigned non_iso_thr_en:1; ++ /** ISO Tx Thr. Enable */ ++ unsigned iso_thr_en:1; ++ /** Tx Thr. Length */ ++ unsigned tx_thr_len:9; ++ /** AHB Threshold ratio */ ++ unsigned ahb_thr_ratio:2; ++ /** Reserved */ ++ unsigned reserved13_15:3; ++ /** Rx Thr. Enable */ ++ unsigned rx_thr_en:1; ++ /** Rx Thr. Length */ ++ unsigned rx_thr_len:9; ++ unsigned reserved26:1; ++ /** Arbiter Parking Enable*/ ++ unsigned arbprken:1; ++ /** Reserved */ ++ unsigned reserved28_31:4; ++ } b; ++} dthrctl_data_t; ++ ++/** ++ * Device Logical IN Endpoint-Specific Registers. Offsets ++ * 900h-AFCh ++ * ++ * There will be one set of endpoint registers per logical endpoint ++ * implemented. ++ * ++ * These registers are visible only in Device mode and must not be ++ * accessed in Host mode, as the results are unknown. ++ */ ++typedef struct dwc_otg_dev_in_ep_regs { ++ /** Device IN Endpoint Control Register. Offset:900h + ++ * (ep_num * 20h) + 00h */ ++ volatile uint32_t diepctl; ++ /** Reserved. Offset:900h + (ep_num * 20h) + 04h */ ++ uint32_t reserved04; ++ /** Device IN Endpoint Interrupt Register. Offset:900h + ++ * (ep_num * 20h) + 08h */ ++ volatile uint32_t diepint; ++ /** Reserved. Offset:900h + (ep_num * 20h) + 0Ch */ ++ uint32_t reserved0C; ++ /** Device IN Endpoint Transfer Size ++ * Register. Offset:900h + (ep_num * 20h) + 10h */ ++ volatile uint32_t dieptsiz; ++ /** Device IN Endpoint DMA Address Register. Offset:900h + ++ * (ep_num * 20h) + 14h */ ++ volatile uint32_t diepdma; ++ /** Device IN Endpoint Transmit FIFO Status Register. Offset:900h + ++ * (ep_num * 20h) + 18h */ ++ volatile uint32_t dtxfsts; ++ /** Device IN Endpoint DMA Buffer Register. Offset:900h + ++ * (ep_num * 20h) + 1Ch */ ++ volatile uint32_t diepdmab; ++} dwc_otg_dev_in_ep_regs_t; ++ ++/** ++ * Device Logical OUT Endpoint-Specific Registers. Offsets: ++ * B00h-CFCh ++ * ++ * There will be one set of endpoint registers per logical endpoint ++ * implemented. ++ * ++ * These registers are visible only in Device mode and must not be ++ * accessed in Host mode, as the results are unknown. ++ */ ++typedef struct dwc_otg_dev_out_ep_regs { ++ /** Device OUT Endpoint Control Register. Offset:B00h + ++ * (ep_num * 20h) + 00h */ ++ volatile uint32_t doepctl; ++ /** Reserved. Offset:B00h + (ep_num * 20h) + 04h */ ++ uint32_t reserved04; ++ /** Device OUT Endpoint Interrupt Register. Offset:B00h + ++ * (ep_num * 20h) + 08h */ ++ volatile uint32_t doepint; ++ /** Reserved. Offset:B00h + (ep_num * 20h) + 0Ch */ ++ uint32_t reserved0C; ++ /** Device OUT Endpoint Transfer Size Register. Offset: ++ * B00h + (ep_num * 20h) + 10h */ ++ volatile uint32_t doeptsiz; ++ /** Device OUT Endpoint DMA Address Register. Offset:B00h ++ * + (ep_num * 20h) + 14h */ ++ volatile uint32_t doepdma; ++ /** Reserved. Offset:B00h + * (ep_num * 20h) + 18h */ ++ uint32_t unused; ++ /** Device OUT Endpoint DMA Buffer Register. Offset:B00h ++ * + (ep_num * 20h) + 1Ch */ ++ uint32_t doepdmab; ++} dwc_otg_dev_out_ep_regs_t; ++ ++/** ++ * This union represents the bit fields in the Device EP Control ++ * Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union depctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Maximum Packet Size ++ * IN/OUT EPn ++ * IN/OUT EP0 - 2 bits ++ * 2'b00: 64 Bytes ++ * 2'b01: 32 ++ * 2'b10: 16 ++ * 2'b11: 8 */ ++ unsigned mps:11; ++#define DWC_DEP0CTL_MPS_64 0 ++#define DWC_DEP0CTL_MPS_32 1 ++#define DWC_DEP0CTL_MPS_16 2 ++#define DWC_DEP0CTL_MPS_8 3 ++ ++ /** Next Endpoint ++ * IN EPn/IN EP0 ++ * OUT EPn/OUT EP0 - reserved */ ++ unsigned nextep:4; ++ ++ /** USB Active Endpoint */ ++ unsigned usbactep:1; ++ ++ /** Endpoint DPID (INTR/Bulk IN and OUT endpoints) ++ * This field contains the PID of the packet going to ++ * be received or transmitted on this endpoint. The ++ * application should program the PID of the first ++ * packet going to be received or transmitted on this ++ * endpoint , after the endpoint is ++ * activated. Application use the SetD1PID and ++ * SetD0PID fields of this register to program either ++ * D0 or D1 PID. ++ * ++ * The encoding for this field is ++ * - 0: D0 ++ * - 1: D1 ++ */ ++ unsigned dpid:1; ++ ++ /** NAK Status */ ++ unsigned naksts:1; ++ ++ /** Endpoint Type ++ * 2'b00: Control ++ * 2'b01: Isochronous ++ * 2'b10: Bulk ++ * 2'b11: Interrupt */ ++ unsigned eptype:2; ++ ++ /** Snoop Mode ++ * OUT EPn/OUT EP0 ++ * IN EPn/IN EP0 - reserved */ ++ unsigned snp:1; ++ ++ /** Stall Handshake */ ++ unsigned stall:1; ++ ++ /** Tx Fifo Number ++ * IN EPn/IN EP0 ++ * OUT EPn/OUT EP0 - reserved */ ++ unsigned txfnum:4; ++ ++ /** Clear NAK */ ++ unsigned cnak:1; ++ /** Set NAK */ ++ unsigned snak:1; ++ /** Set DATA0 PID (INTR/Bulk IN and OUT endpoints) ++ * Writing to this field sets the Endpoint DPID (DPID) ++ * field in this register to DATA0. Set Even ++ * (micro)frame (SetEvenFr) (ISO IN and OUT Endpoints) ++ * Writing to this field sets the Even/Odd ++ * (micro)frame (EO_FrNum) field to even (micro) ++ * frame. ++ */ ++ unsigned setd0pid:1; ++ /** Set DATA1 PID (INTR/Bulk IN and OUT endpoints) ++ * Writing to this field sets the Endpoint DPID (DPID) ++ * field in this register to DATA1 Set Odd ++ * (micro)frame (SetOddFr) (ISO IN and OUT Endpoints) ++ * Writing to this field sets the Even/Odd ++ * (micro)frame (EO_FrNum) field to odd (micro) frame. ++ */ ++ unsigned setd1pid:1; ++ ++ /** Endpoint Disable */ ++ unsigned epdis:1; ++ /** Endpoint Enable */ ++ unsigned epena:1; ++ } b; ++} depctl_data_t; ++ ++/** ++ * This union represents the bit fields in the Device EP Transfer ++ * Size Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union deptsiz_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer size */ ++ unsigned xfersize:19; ++/** Max packet count for EP (pow(2,10)-1) */ ++#define MAX_PKT_CNT 1023 ++ /** Packet Count */ ++ unsigned pktcnt:10; ++ /** Multi Count - Periodic IN endpoints */ ++ unsigned mc:2; ++ unsigned reserved:1; ++ } b; ++} deptsiz_data_t; ++ ++/** ++ * This union represents the bit fields in the Device EP 0 Transfer ++ * Size Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union deptsiz0_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer size */ ++ unsigned xfersize:7; ++ /** Reserved */ ++ unsigned reserved7_18:12; ++ /** Packet Count */ ++ unsigned pktcnt:2; ++ /** Reserved */ ++ unsigned reserved21_28:8; ++ /**Setup Packet Count (DOEPTSIZ0 Only) */ ++ unsigned supcnt:2; ++ unsigned reserved31; ++ } b; ++} deptsiz0_data_t; ++ ++///////////////////////////////////////////////// ++// DMA Descriptor Specific Structures ++// ++ ++/** Buffer status definitions */ ++ ++#define BS_HOST_READY 0x0 ++#define BS_DMA_BUSY 0x1 ++#define BS_DMA_DONE 0x2 ++#define BS_HOST_BUSY 0x3 ++ ++/** Receive/Transmit status definitions */ ++ ++#define RTS_SUCCESS 0x0 ++#define RTS_BUFFLUSH 0x1 ++#define RTS_RESERVED 0x2 ++#define RTS_BUFERR 0x3 ++ ++/** ++ * This union represents the bit fields in the DMA Descriptor ++ * status quadlet. Read the quadlet into the d32 member then ++ * set/clear the bits using the bit, b_iso_out and ++ * b_iso_in elements. ++ */ ++typedef union dev_dma_desc_sts { ++ /** raw register data */ ++ uint32_t d32; ++ /** quadlet bits */ ++ struct { ++ /** Received number of bytes */ ++ unsigned bytes:16; ++ /** NAK bit - only for OUT EPs */ ++ unsigned nak:1; ++ unsigned reserved17_22:6; ++ /** Multiple Transfer - only for OUT EPs */ ++ unsigned mtrf:1; ++ /** Setup Packet received - only for OUT EPs */ ++ unsigned sr:1; ++ /** Interrupt On Complete */ ++ unsigned ioc:1; ++ /** Short Packet */ ++ unsigned sp:1; ++ /** Last */ ++ unsigned l:1; ++ /** Receive Status */ ++ unsigned sts:2; ++ /** Buffer Status */ ++ unsigned bs:2; ++ } b; ++ ++//#ifdef DWC_EN_ISOC ++ /** iso out quadlet bits */ ++ struct { ++ /** Received number of bytes */ ++ unsigned rxbytes:11; ++ ++ unsigned reserved11:1; ++ /** Frame Number */ ++ unsigned framenum:11; ++ /** Received ISO Data PID */ ++ unsigned pid:2; ++ /** Interrupt On Complete */ ++ unsigned ioc:1; ++ /** Short Packet */ ++ unsigned sp:1; ++ /** Last */ ++ unsigned l:1; ++ /** Receive Status */ ++ unsigned rxsts:2; ++ /** Buffer Status */ ++ unsigned bs:2; ++ } b_iso_out; ++ ++ /** iso in quadlet bits */ ++ struct { ++ /** Transmited number of bytes */ ++ unsigned txbytes:12; ++ /** Frame Number */ ++ unsigned framenum:11; ++ /** Transmited ISO Data PID */ ++ unsigned pid:2; ++ /** Interrupt On Complete */ ++ unsigned ioc:1; ++ /** Short Packet */ ++ unsigned sp:1; ++ /** Last */ ++ unsigned l:1; ++ /** Transmit Status */ ++ unsigned txsts:2; ++ /** Buffer Status */ ++ unsigned bs:2; ++ } b_iso_in; ++//#endif /* DWC_EN_ISOC */ ++} dev_dma_desc_sts_t; ++ ++/** ++ * DMA Descriptor structure ++ * ++ * DMA Descriptor structure contains two quadlets: ++ * Status quadlet and Data buffer pointer. ++ */ ++typedef struct dwc_otg_dev_dma_desc { ++ /** DMA Descriptor status quadlet */ ++ dev_dma_desc_sts_t status; ++ /** DMA Descriptor data buffer pointer */ ++ uint32_t buf; ++} dwc_otg_dev_dma_desc_t; ++ ++/** ++ * The dwc_otg_dev_if structure contains information needed to manage ++ * the DWC_otg controller acting in device mode. It represents the ++ * programming view of the device-specific aspects of the controller. ++ */ ++typedef struct dwc_otg_dev_if { ++ /** Pointer to device Global registers. ++ * Device Global Registers starting at offset 800h ++ */ ++ dwc_otg_device_global_regs_t *dev_global_regs; ++#define DWC_DEV_GLOBAL_REG_OFFSET 0x800 ++ ++ /** ++ * Device Logical IN Endpoint-Specific Registers 900h-AFCh ++ */ ++ dwc_otg_dev_in_ep_regs_t *in_ep_regs[MAX_EPS_CHANNELS]; ++#define DWC_DEV_IN_EP_REG_OFFSET 0x900 ++#define DWC_EP_REG_OFFSET 0x20 ++ ++ /** Device Logical OUT Endpoint-Specific Registers B00h-CFCh */ ++ dwc_otg_dev_out_ep_regs_t *out_ep_regs[MAX_EPS_CHANNELS]; ++#define DWC_DEV_OUT_EP_REG_OFFSET 0xB00 ++ ++ /* Device configuration information */ ++ uint8_t speed; /**< Device Speed 0: Unknown, 1: LS, 2:FS, 3: HS */ ++ uint8_t num_in_eps; /**< Number # of Tx EP range: 0-15 exept ep0 */ ++ uint8_t num_out_eps; /**< Number # of Rx EP range: 0-15 exept ep 0*/ ++ ++ /** Size of periodic FIFOs (Bytes) */ ++ uint16_t perio_tx_fifo_size[MAX_PERIO_FIFOS]; ++ ++ /** Size of Tx FIFOs (Bytes) */ ++ uint16_t tx_fifo_size[MAX_TX_FIFOS]; ++ ++ /** Thresholding enable flags and length varaiables **/ ++ uint16_t rx_thr_en; ++ uint16_t iso_tx_thr_en; ++ uint16_t non_iso_tx_thr_en; ++ ++ uint16_t rx_thr_length; ++ uint16_t tx_thr_length; ++ ++ /** ++ * Pointers to the DMA Descriptors for EP0 Control ++ * transfers (virtual and physical) ++ */ ++ ++ /** 2 descriptors for SETUP packets */ ++ dwc_dma_t dma_setup_desc_addr[2]; ++ dwc_otg_dev_dma_desc_t *setup_desc_addr[2]; ++ ++ /** Pointer to Descriptor with latest SETUP packet */ ++ dwc_otg_dev_dma_desc_t *psetup; ++ ++ /** Index of current SETUP handler descriptor */ ++ uint32_t setup_desc_index; ++ ++ /** Descriptor for Data In or Status In phases */ ++ dwc_dma_t dma_in_desc_addr; ++ dwc_otg_dev_dma_desc_t *in_desc_addr; ++ ++ /** Descriptor for Data Out or Status Out phases */ ++ dwc_dma_t dma_out_desc_addr; ++ dwc_otg_dev_dma_desc_t *out_desc_addr; ++ ++ /** Setup Packet Detected - if set clear NAK when queueing */ ++ uint32_t spd; ++ /** Isoc ep pointer on which incomplete happens */ ++ void *isoc_ep; ++ ++} dwc_otg_dev_if_t; ++ ++///////////////////////////////////////////////// ++// Host Mode Register Structures ++// ++/** ++ * The Host Global Registers structure defines the size and relative ++ * field offsets for the Host Mode Global Registers. Host Global ++ * Registers offsets 400h-7FFh. ++*/ ++typedef struct dwc_otg_host_global_regs { ++ /** Host Configuration Register. Offset: 400h */ ++ volatile uint32_t hcfg; ++ /** Host Frame Interval Register. Offset: 404h */ ++ volatile uint32_t hfir; ++ /** Host Frame Number / Frame Remaining Register. Offset: 408h */ ++ volatile uint32_t hfnum; ++ /** Reserved. Offset: 40Ch */ ++ uint32_t reserved40C; ++ /** Host Periodic Transmit FIFO/ Queue Status Register. Offset: 410h */ ++ volatile uint32_t hptxsts; ++ /** Host All Channels Interrupt Register. Offset: 414h */ ++ volatile uint32_t haint; ++ /** Host All Channels Interrupt Mask Register. Offset: 418h */ ++ volatile uint32_t haintmsk; ++ /** Host Frame List Base Address Register . Offset: 41Ch */ ++ volatile uint32_t hflbaddr; ++} dwc_otg_host_global_regs_t; ++ ++/** ++ * This union represents the bit fields in the Host Configuration Register. ++ * Read the register into the d32 member then set/clear the bits using ++ * the bit elements. Write the d32 member to the hcfg register. ++ */ ++typedef union hcfg_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** FS/LS Phy Clock Select */ ++ unsigned fslspclksel:2; ++#define DWC_HCFG_30_60_MHZ 0 ++#define DWC_HCFG_48_MHZ 1 ++#define DWC_HCFG_6_MHZ 2 ++ ++ /** FS/LS Only Support */ ++ unsigned fslssupp:1; ++ unsigned reserved3_6:4; ++ /** Enable 32-KHz Suspend Mode */ ++ unsigned ena32khzs:1; ++ /** Resume Validation Periiod */ ++ unsigned resvalid:8; ++ unsigned reserved16_22:7; ++ /** Enable Scatter/gather DMA in Host mode */ ++ unsigned descdma:1; ++ /** Frame List Entries */ ++ unsigned frlisten:2; ++ /** Enable Periodic Scheduling */ ++ unsigned perschedena:1; ++ unsigned reserved27_30:4; ++ unsigned modechtimen:1; ++ } b; ++} hcfg_data_t; ++ ++/** ++ * This union represents the bit fields in the Host Frame Remaing/Number ++ * Register. ++ */ ++typedef union hfir_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ unsigned frint:16; ++ unsigned hfirrldctrl:1; ++ unsigned reserved:15; ++ } b; ++} hfir_data_t; ++ ++/** ++ * This union represents the bit fields in the Host Frame Remaing/Number ++ * Register. ++ */ ++typedef union hfnum_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ unsigned frnum:16; ++#define DWC_HFNUM_MAX_FRNUM 0x3FFF ++ unsigned frrem:16; ++ } b; ++} hfnum_data_t; ++ ++typedef union hptxsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ unsigned ptxfspcavail:16; ++ unsigned ptxqspcavail:8; ++ /** Top of the Periodic Transmit Request Queue ++ * - bit 24 - Terminate (last entry for the selected channel) ++ * - bits 26:25 - Token Type ++ * - 2'b00 - Zero length ++ * - 2'b01 - Ping ++ * - 2'b10 - Disable ++ * - bits 30:27 - Channel Number ++ * - bit 31 - Odd/even microframe ++ */ ++ unsigned ptxqtop_terminate:1; ++ unsigned ptxqtop_token:2; ++ unsigned ptxqtop_chnum:4; ++ unsigned ptxqtop_odd:1; ++ } b; ++} hptxsts_data_t; ++ ++/** ++ * This union represents the bit fields in the Host Port Control and Status ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. Write the d32 member to the ++ * hprt0 register. ++ */ ++typedef union hprt0_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned prtconnsts:1; ++ unsigned prtconndet:1; ++ unsigned prtena:1; ++ unsigned prtenchng:1; ++ unsigned prtovrcurract:1; ++ unsigned prtovrcurrchng:1; ++ unsigned prtres:1; ++ unsigned prtsusp:1; ++ unsigned prtrst:1; ++ unsigned reserved9:1; ++ unsigned prtlnsts:2; ++ unsigned prtpwr:1; ++ unsigned prttstctl:4; ++ unsigned prtspd:2; ++#define DWC_HPRT0_PRTSPD_HIGH_SPEED 0 ++#define DWC_HPRT0_PRTSPD_FULL_SPEED 1 ++#define DWC_HPRT0_PRTSPD_LOW_SPEED 2 ++ unsigned reserved19_31:13; ++ } b; ++} hprt0_data_t; ++ ++/** ++ * This union represents the bit fields in the Host All Interrupt ++ * Register. ++ */ ++typedef union haint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned ch0:1; ++ unsigned ch1:1; ++ unsigned ch2:1; ++ unsigned ch3:1; ++ unsigned ch4:1; ++ unsigned ch5:1; ++ unsigned ch6:1; ++ unsigned ch7:1; ++ unsigned ch8:1; ++ unsigned ch9:1; ++ unsigned ch10:1; ++ unsigned ch11:1; ++ unsigned ch12:1; ++ unsigned ch13:1; ++ unsigned ch14:1; ++ unsigned ch15:1; ++ unsigned reserved:16; ++ } b; ++ ++ struct { ++ unsigned chint:16; ++ unsigned reserved:16; ++ } b2; ++} haint_data_t; ++ ++/** ++ * This union represents the bit fields in the Host All Interrupt ++ * Register. ++ */ ++typedef union haintmsk_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned ch0:1; ++ unsigned ch1:1; ++ unsigned ch2:1; ++ unsigned ch3:1; ++ unsigned ch4:1; ++ unsigned ch5:1; ++ unsigned ch6:1; ++ unsigned ch7:1; ++ unsigned ch8:1; ++ unsigned ch9:1; ++ unsigned ch10:1; ++ unsigned ch11:1; ++ unsigned ch12:1; ++ unsigned ch13:1; ++ unsigned ch14:1; ++ unsigned ch15:1; ++ unsigned reserved:16; ++ } b; ++ ++ struct { ++ unsigned chint:16; ++ unsigned reserved:16; ++ } b2; ++} haintmsk_data_t; ++ ++/** ++ * Host Channel Specific Registers. 500h-5FCh ++ */ ++typedef struct dwc_otg_hc_regs { ++ /** Host Channel 0 Characteristic Register. Offset: 500h + (chan_num * 20h) + 00h */ ++ volatile uint32_t hcchar; ++ /** Host Channel 0 Split Control Register. Offset: 500h + (chan_num * 20h) + 04h */ ++ volatile uint32_t hcsplt; ++ /** Host Channel 0 Interrupt Register. Offset: 500h + (chan_num * 20h) + 08h */ ++ volatile uint32_t hcint; ++ /** Host Channel 0 Interrupt Mask Register. Offset: 500h + (chan_num * 20h) + 0Ch */ ++ volatile uint32_t hcintmsk; ++ /** Host Channel 0 Transfer Size Register. Offset: 500h + (chan_num * 20h) + 10h */ ++ volatile uint32_t hctsiz; ++ /** Host Channel 0 DMA Address Register. Offset: 500h + (chan_num * 20h) + 14h */ ++ volatile uint32_t hcdma; ++ volatile uint32_t reserved; ++ /** Host Channel 0 DMA Buffer Address Register. Offset: 500h + (chan_num * 20h) + 1Ch */ ++ volatile uint32_t hcdmab; ++} dwc_otg_hc_regs_t; ++ ++/** ++ * This union represents the bit fields in the Host Channel Characteristics ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. Write the d32 member to the ++ * hcchar register. ++ */ ++typedef union hcchar_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** Maximum packet size in bytes */ ++ unsigned mps:11; ++ ++ /** Endpoint number */ ++ unsigned epnum:4; ++ ++ /** 0: OUT, 1: IN */ ++ unsigned epdir:1; ++ ++ unsigned reserved:1; ++ ++ /** 0: Full/high speed device, 1: Low speed device */ ++ unsigned lspddev:1; ++ ++ /** 0: Control, 1: Isoc, 2: Bulk, 3: Intr */ ++ unsigned eptype:2; ++ ++ /** Packets per frame for periodic transfers. 0 is reserved. */ ++ unsigned multicnt:2; ++ ++ /** Device address */ ++ unsigned devaddr:7; ++ ++ /** ++ * Frame to transmit periodic transaction. ++ * 0: even, 1: odd ++ */ ++ unsigned oddfrm:1; ++ ++ /** Channel disable */ ++ unsigned chdis:1; ++ ++ /** Channel enable */ ++ unsigned chen:1; ++ } b; ++} hcchar_data_t; ++ ++typedef union hcsplt_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** Port Address */ ++ unsigned prtaddr:7; ++ ++ /** Hub Address */ ++ unsigned hubaddr:7; ++ ++ /** Transaction Position */ ++ unsigned xactpos:2; ++#define DWC_HCSPLIT_XACTPOS_MID 0 ++#define DWC_HCSPLIT_XACTPOS_END 1 ++#define DWC_HCSPLIT_XACTPOS_BEGIN 2 ++#define DWC_HCSPLIT_XACTPOS_ALL 3 ++ ++ /** Do Complete Split */ ++ unsigned compsplt:1; ++ ++ /** Reserved */ ++ unsigned reserved:14; ++ ++ /** Split Enble */ ++ unsigned spltena:1; ++ } b; ++} hcsplt_data_t; ++ ++/** ++ * This union represents the bit fields in the Host All Interrupt ++ * Register. ++ */ ++typedef union hcint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer Complete */ ++ unsigned xfercomp:1; ++ /** Channel Halted */ ++ unsigned chhltd:1; ++ /** AHB Error */ ++ unsigned ahberr:1; ++ /** STALL Response Received */ ++ unsigned stall:1; ++ /** NAK Response Received */ ++ unsigned nak:1; ++ /** ACK Response Received */ ++ unsigned ack:1; ++ /** NYET Response Received */ ++ unsigned nyet:1; ++ /** Transaction Err */ ++ unsigned xacterr:1; ++ /** Babble Error */ ++ unsigned bblerr:1; ++ /** Frame Overrun */ ++ unsigned frmovrun:1; ++ /** Data Toggle Error */ ++ unsigned datatglerr:1; ++ /** Buffer Not Available (only for DDMA mode) */ ++ unsigned bna:1; ++ /** Exessive transaction error (only for DDMA mode) */ ++ unsigned xcs_xact:1; ++ /** Frame List Rollover interrupt */ ++ unsigned frm_list_roll:1; ++ /** Reserved */ ++ unsigned reserved14_31:18; ++ } b; ++} hcint_data_t; ++ ++/** ++ * This union represents the bit fields in the Host Channel Interrupt Mask ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. Write the d32 member to the ++ * hcintmsk register. ++ */ ++typedef union hcintmsk_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ unsigned xfercompl:1; ++ unsigned chhltd:1; ++ unsigned ahberr:1; ++ unsigned stall:1; ++ unsigned nak:1; ++ unsigned ack:1; ++ unsigned nyet:1; ++ unsigned xacterr:1; ++ unsigned bblerr:1; ++ unsigned frmovrun:1; ++ unsigned datatglerr:1; ++ unsigned bna:1; ++ unsigned xcs_xact:1; ++ unsigned frm_list_roll:1; ++ unsigned reserved14_31:18; ++ } b; ++} hcintmsk_data_t; ++ ++/** ++ * This union represents the bit fields in the Host Channel Transfer Size ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. Write the d32 member to the ++ * hcchar register. ++ */ ++ ++typedef union hctsiz_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** Total transfer size in bytes */ ++ unsigned xfersize:19; ++ ++ /** Data packets to transfer */ ++ unsigned pktcnt:10; ++ ++ /** ++ * Packet ID for next data packet ++ * 0: DATA0 ++ * 1: DATA2 ++ * 2: DATA1 ++ * 3: MDATA (non-Control), SETUP (Control) ++ */ ++ unsigned pid:2; ++#define DWC_HCTSIZ_DATA0 0 ++#define DWC_HCTSIZ_DATA1 2 ++#define DWC_HCTSIZ_DATA2 1 ++#define DWC_HCTSIZ_MDATA 3 ++#define DWC_HCTSIZ_SETUP 3 ++ ++ /** Do PING protocol when 1 */ ++ unsigned dopng:1; ++ } b; ++ ++ /** register bits */ ++ struct { ++ /** Scheduling information */ ++ unsigned schinfo:8; ++ ++ /** Number of transfer descriptors. ++ * Max value: ++ * 64 in general, ++ * 256 only for HS isochronous endpoint. ++ */ ++ unsigned ntd:8; ++ ++ /** Data packets to transfer */ ++ unsigned reserved16_28:13; ++ ++ /** ++ * Packet ID for next data packet ++ * 0: DATA0 ++ * 1: DATA2 ++ * 2: DATA1 ++ * 3: MDATA (non-Control) ++ */ ++ unsigned pid:2; ++ ++ /** Do PING protocol when 1 */ ++ unsigned dopng:1; ++ } b_ddma; ++} hctsiz_data_t; ++ ++/** ++ * This union represents the bit fields in the Host DMA Address ++ * Register used in Descriptor DMA mode. ++ */ ++typedef union hcdma_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned reserved0_2:3; ++ /** Current Transfer Descriptor. Not used for ISOC */ ++ unsigned ctd:8; ++ /** Start Address of Descriptor List */ ++ unsigned dma_addr:21; ++ } b; ++} hcdma_data_t; ++ ++/** ++ * This union represents the bit fields in the DMA Descriptor ++ * status quadlet for host mode. Read the quadlet into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union host_dma_desc_sts { ++ /** raw register data */ ++ uint32_t d32; ++ /** quadlet bits */ ++ ++ /* for non-isochronous */ ++ struct { ++ /** Number of bytes */ ++ unsigned n_bytes:17; ++ /** QTD offset to jump when Short Packet received - only for IN EPs */ ++ unsigned qtd_offset:6; ++ /** ++ * Set to request the core to jump to alternate QTD if ++ * Short Packet received - only for IN EPs ++ */ ++ unsigned a_qtd:1; ++ /** ++ * Setup Packet bit. When set indicates that buffer contains ++ * setup packet. ++ */ ++ unsigned sup:1; ++ /** Interrupt On Complete */ ++ unsigned ioc:1; ++ /** End of List */ ++ unsigned eol:1; ++ unsigned reserved27:1; ++ /** Rx/Tx Status */ ++ unsigned sts:2; ++#define DMA_DESC_STS_PKTERR 1 ++ unsigned reserved30:1; ++ /** Active Bit */ ++ unsigned a:1; ++ } b; ++ /* for isochronous */ ++ struct { ++ /** Number of bytes */ ++ unsigned n_bytes:12; ++ unsigned reserved12_24:13; ++ /** Interrupt On Complete */ ++ unsigned ioc:1; ++ unsigned reserved26_27:2; ++ /** Rx/Tx Status */ ++ unsigned sts:2; ++ unsigned reserved30:1; ++ /** Active Bit */ ++ unsigned a:1; ++ } b_isoc; ++} host_dma_desc_sts_t; ++ ++#define MAX_DMA_DESC_SIZE 131071 ++#define MAX_DMA_DESC_NUM_GENERIC 64 ++#define MAX_DMA_DESC_NUM_HS_ISOC 256 ++#define MAX_FRLIST_EN_NUM 64 ++/** ++ * Host-mode DMA Descriptor structure ++ * ++ * DMA Descriptor structure contains two quadlets: ++ * Status quadlet and Data buffer pointer. ++ */ ++typedef struct dwc_otg_host_dma_desc { ++ /** DMA Descriptor status quadlet */ ++ host_dma_desc_sts_t status; ++ /** DMA Descriptor data buffer pointer */ ++ uint32_t buf; ++} dwc_otg_host_dma_desc_t; ++ ++/** OTG Host Interface Structure. ++ * ++ * The OTG Host Interface Structure structure contains information ++ * needed to manage the DWC_otg controller acting in host mode. It ++ * represents the programming view of the host-specific aspects of the ++ * controller. ++ */ ++typedef struct dwc_otg_host_if { ++ /** Host Global Registers starting at offset 400h.*/ ++ dwc_otg_host_global_regs_t *host_global_regs; ++#define DWC_OTG_HOST_GLOBAL_REG_OFFSET 0x400 ++ ++ /** Host Port 0 Control and Status Register */ ++ volatile uint32_t *hprt0; ++#define DWC_OTG_HOST_PORT_REGS_OFFSET 0x440 ++ ++ /** Host Channel Specific Registers at offsets 500h-5FCh. */ ++ dwc_otg_hc_regs_t *hc_regs[MAX_EPS_CHANNELS]; ++#define DWC_OTG_HOST_CHAN_REGS_OFFSET 0x500 ++#define DWC_OTG_CHAN_REGS_OFFSET 0x20 ++ ++ /* Host configuration information */ ++ /** Number of Host Channels (range: 1-16) */ ++ uint8_t num_host_channels; ++ /** Periodic EPs supported (0: no, 1: yes) */ ++ uint8_t perio_eps_supported; ++ /** Periodic Tx FIFO Size (Only 1 host periodic Tx FIFO) */ ++ uint16_t perio_tx_fifo_size; ++ ++} dwc_otg_host_if_t; ++ ++/** ++ * This union represents the bit fields in the Power and Clock Gating Control ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++typedef union pcgcctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** Stop Pclk */ ++ unsigned stoppclk:1; ++ /** Gate Hclk */ ++ unsigned gatehclk:1; ++ /** Power Clamp */ ++ unsigned pwrclmp:1; ++ /** Reset Power Down Modules */ ++ unsigned rstpdwnmodule:1; ++ /** Reserved */ ++ unsigned reserved:1; ++ /** Enable Sleep Clock Gating (Enbl_L1Gating) */ ++ unsigned enbl_sleep_gating:1; ++ /** PHY In Sleep (PhySleep) */ ++ unsigned phy_in_sleep:1; ++ /** Deep Sleep*/ ++ unsigned deep_sleep:1; ++ unsigned resetaftsusp:1; ++ unsigned restoremode:1; ++ unsigned enbl_extnd_hiber:1; ++ unsigned extnd_hiber_pwrclmp:1; ++ unsigned extnd_hiber_switch:1; ++ unsigned ess_reg_restored:1; ++ unsigned prt_clk_sel:2; ++ unsigned port_power:1; ++ unsigned max_xcvrselect:2; ++ unsigned max_termsel:1; ++ unsigned mac_dev_addr:7; ++ unsigned p2hd_dev_enum_spd:2; ++ unsigned p2hd_prt_spd:2; ++ unsigned if_dev_mode:1; ++ } b; ++} pcgcctl_data_t; ++ ++/** ++ * This union represents the bit fields in the Global Data FIFO Software ++ * Configuration Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union gdfifocfg_data { ++ /* raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** OTG Data FIFO depth */ ++ unsigned gdfifocfg:16; ++ /** Start address of EP info controller */ ++ unsigned epinfobase:16; ++ } b; ++} gdfifocfg_data_t; ++ ++/** ++ * This union represents the bit fields in the Global Power Down Register ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++typedef union gpwrdn_data { ++ /* raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** PMU Interrupt Select */ ++ unsigned pmuintsel:1; ++ /** PMU Active */ ++ unsigned pmuactv:1; ++ /** Restore */ ++ unsigned restore:1; ++ /** Power Down Clamp */ ++ unsigned pwrdnclmp:1; ++ /** Power Down Reset */ ++ unsigned pwrdnrstn:1; ++ /** Power Down Switch */ ++ unsigned pwrdnswtch:1; ++ /** Disable VBUS */ ++ unsigned dis_vbus:1; ++ /** Line State Change */ ++ unsigned lnstschng:1; ++ /** Line state change mask */ ++ unsigned lnstchng_msk:1; ++ /** Reset Detected */ ++ unsigned rst_det:1; ++ /** Reset Detect mask */ ++ unsigned rst_det_msk:1; ++ /** Disconnect Detected */ ++ unsigned disconn_det:1; ++ /** Disconnect Detect mask */ ++ unsigned disconn_det_msk:1; ++ /** Connect Detected*/ ++ unsigned connect_det:1; ++ /** Connect Detected Mask*/ ++ unsigned connect_det_msk:1; ++ /** SRP Detected */ ++ unsigned srp_det:1; ++ /** SRP Detect mask */ ++ unsigned srp_det_msk:1; ++ /** Status Change Interrupt */ ++ unsigned sts_chngint:1; ++ /** Status Change Interrupt Mask */ ++ unsigned sts_chngint_msk:1; ++ /** Line State */ ++ unsigned linestate:2; ++ /** Indicates current mode(status of IDDIG signal) */ ++ unsigned idsts:1; ++ /** B Session Valid signal status*/ ++ unsigned bsessvld:1; ++ /** ADP Event Detected */ ++ unsigned adp_int:1; ++ /** Multi Valued ID pin */ ++ unsigned mult_val_id_bc:5; ++ /** Reserved 24_31 */ ++ unsigned reserved29_31:3; ++ } b; ++} gpwrdn_data_t; ++ ++#endif +diff --git a/drivers/usb/gadget/udc/hiudc/usb.h b/drivers/usb/gadget/udc/hiudc/usb.h +new file mode 100644 +index 0000000..357d6c7 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/usb.h +@@ -0,0 +1,933 @@ ++/* ++ * Copyright (c) 1998 The NetBSD Foundation, Inc. ++ * All rights reserved. ++ * ++ * This code is derived from software contributed to The NetBSD Foundation ++ * by Lennart Augustsson (lennart@augustsson.net) at ++ * Carlstedt Research & Technology. ++ * ++ * 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. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by the NetBSD ++ * Foundation, Inc. and its contributors. ++ * 4. Neither the name of The NetBSD Foundation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. ++ */ ++ ++/* Modified by Synopsys, Inc, 12/12/2007 */ ++ ++ ++#ifndef _USB_H_ ++#define _USB_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* ++ * The USB records contain some unaligned little-endian word ++ * components. The U[SG]ETW macros take care of both the alignment ++ * and endian problem and should always be used to access non-byte ++ * values. ++ */ ++typedef u_int8_t uByte; ++typedef u_int8_t uWord[2]; ++typedef u_int8_t uDWord[4]; ++ ++#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h)) ++#define UCONSTW(x) { (x) & 0xff, ((x) >> 8) & 0xff } ++#define UCONSTDW(x) { (x) & 0xff, ((x) >> 8) & 0xff, \ ++ ((x) >> 16) & 0xff, ((x) >> 24) & 0xff } ++ ++#if 1 ++#define UGETW(w) ((w)[0] | ((w)[1] << 8)) ++#define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8)) ++#define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24)) ++#define USETDW(w,v) ((w)[0] = (u_int8_t)(v), \ ++ (w)[1] = (u_int8_t)((v) >> 8), \ ++ (w)[2] = (u_int8_t)((v) >> 16), \ ++ (w)[3] = (u_int8_t)((v) >> 24)) ++#else ++/* ++ * On little-endian machines that can handle unanliged accesses ++ * (e.g. i386) these macros can be replaced by the following. ++ */ ++#define UGETW(w) (*(u_int16_t *)(w)) ++#define USETW(w,v) (*(u_int16_t *)(w) = (v)) ++#define UGETDW(w) (*(u_int32_t *)(w)) ++#define USETDW(w,v) (*(u_int32_t *)(w) = (v)) ++#endif ++ ++/* ++ * Macros for accessing UAS IU fields, which are big-endian ++ */ ++#define IUSETW2(w,h,l) ((w)[0] = (u_int8_t)(h), (w)[1] = (u_int8_t)(l)) ++#define IUCONSTW(x) { ((x) >> 8) & 0xff, (x) & 0xff } ++#define IUCONSTDW(x) { ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \ ++ ((x) >> 8) & 0xff, (x) & 0xff } ++#define IUGETW(w) (((w)[0] << 8) | (w)[1]) ++#define IUSETW(w,v) ((w)[0] = (u_int8_t)((v) >> 8), (w)[1] = (u_int8_t)(v)) ++#define IUGETDW(w) (((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3]) ++#define IUSETDW(w,v) ((w)[0] = (u_int8_t)((v) >> 24), \ ++ (w)[1] = (u_int8_t)((v) >> 16), \ ++ (w)[2] = (u_int8_t)((v) >> 8), \ ++ (w)[3] = (u_int8_t)(v)) ++ ++#define UPACKED __attribute__((__packed__)) ++ ++typedef struct { ++ uByte bmRequestType; ++ uByte bRequest; ++ uWord wValue; ++ uWord wIndex; ++ uWord wLength; ++} UPACKED usb_device_request_t; ++ ++#define UT_GET_DIR(a) ((a) & 0x80) ++#define UT_WRITE 0x00 ++#define UT_READ 0x80 ++ ++#define UT_GET_TYPE(a) ((a) & 0x60) ++#define UT_STANDARD 0x00 ++#define UT_CLASS 0x20 ++#define UT_VENDOR 0x40 ++ ++#define UT_GET_RECIPIENT(a) ((a) & 0x1f) ++#define UT_DEVICE 0x00 ++#define UT_INTERFACE 0x01 ++#define UT_ENDPOINT 0x02 ++#define UT_OTHER 0x03 ++ ++#define UT_READ_DEVICE (UT_READ | UT_STANDARD | UT_DEVICE) ++#define UT_READ_INTERFACE (UT_READ | UT_STANDARD | UT_INTERFACE) ++#define UT_READ_ENDPOINT (UT_READ | UT_STANDARD | UT_ENDPOINT) ++#define UT_WRITE_DEVICE (UT_WRITE | UT_STANDARD | UT_DEVICE) ++#define UT_WRITE_INTERFACE (UT_WRITE | UT_STANDARD | UT_INTERFACE) ++#define UT_WRITE_ENDPOINT (UT_WRITE | UT_STANDARD | UT_ENDPOINT) ++#define UT_READ_CLASS_DEVICE (UT_READ | UT_CLASS | UT_DEVICE) ++#define UT_READ_CLASS_INTERFACE (UT_READ | UT_CLASS | UT_INTERFACE) ++#define UT_READ_CLASS_OTHER (UT_READ | UT_CLASS | UT_OTHER) ++#define UT_READ_CLASS_ENDPOINT (UT_READ | UT_CLASS | UT_ENDPOINT) ++#define UT_WRITE_CLASS_DEVICE (UT_WRITE | UT_CLASS | UT_DEVICE) ++#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE) ++#define UT_WRITE_CLASS_OTHER (UT_WRITE | UT_CLASS | UT_OTHER) ++#define UT_WRITE_CLASS_ENDPOINT (UT_WRITE | UT_CLASS | UT_ENDPOINT) ++#define UT_READ_VENDOR_DEVICE (UT_READ | UT_VENDOR | UT_DEVICE) ++#define UT_READ_VENDOR_INTERFACE (UT_READ | UT_VENDOR | UT_INTERFACE) ++#define UT_READ_VENDOR_OTHER (UT_READ | UT_VENDOR | UT_OTHER) ++#define UT_READ_VENDOR_ENDPOINT (UT_READ | UT_VENDOR | UT_ENDPOINT) ++#define UT_WRITE_VENDOR_DEVICE (UT_WRITE | UT_VENDOR | UT_DEVICE) ++#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE) ++#define UT_WRITE_VENDOR_OTHER (UT_WRITE | UT_VENDOR | UT_OTHER) ++#define UT_WRITE_VENDOR_ENDPOINT (UT_WRITE | UT_VENDOR | UT_ENDPOINT) ++ ++/* Requests */ ++#define UR_GET_STATUS 0x00 ++#define USTAT_STANDARD_STATUS 0x00 ++#define WUSTAT_WUSB_FEATURE 0x01 ++#define WUSTAT_CHANNEL_INFO 0x02 ++#define WUSTAT_RECEIVED_DATA 0x03 ++#define WUSTAT_MAS_AVAILABILITY 0x04 ++#define WUSTAT_CURRENT_TRANSMIT_POWER 0x05 ++#define UR_CLEAR_FEATURE 0x01 ++#define UR_SET_FEATURE 0x03 ++#define UR_SET_AND_TEST_FEATURE 0x0c ++#define UR_SET_ADDRESS 0x05 ++#define UR_GET_DESCRIPTOR 0x06 ++#define UDESC_DEVICE 0x01 ++#define UDESC_CONFIG 0x02 ++#define UDESC_STRING 0x03 ++#define UDESC_INTERFACE 0x04 ++#define UDESC_ENDPOINT 0x05 ++#define UDESC_SS_USB_COMPANION 0x30 ++#define UDESC_DEVICE_QUALIFIER 0x06 ++#define UDESC_OTHER_SPEED_CONFIGURATION 0x07 ++#define UDESC_INTERFACE_POWER 0x08 ++#define UDESC_OTG 0x09 ++#define WUDESC_SECURITY 0x0c ++#define WUDESC_KEY 0x0d ++#define WUD_GET_KEY_INDEX(_wValue_) ((_wValue_) & 0xf) ++#define WUD_GET_KEY_TYPE(_wValue_) (((_wValue_) & 0x30) >> 4) ++#define WUD_KEY_TYPE_ASSOC 0x01 ++#define WUD_KEY_TYPE_GTK 0x02 ++#define WUD_GET_KEY_ORIGIN(_wValue_) (((_wValue_) & 0x40) >> 6) ++#define WUD_KEY_ORIGIN_HOST 0x00 ++#define WUD_KEY_ORIGIN_DEVICE 0x01 ++#define WUDESC_ENCRYPTION_TYPE 0x0e ++#define WUDESC_BOS 0x0f ++#define WUDESC_DEVICE_CAPABILITY 0x10 ++#define WUDESC_WIRELESS_ENDPOINT_COMPANION 0x11 ++#define UDESC_BOS 0x0f ++#define UDESC_DEVICE_CAPABILITY 0x10 ++#define UDESC_CS_DEVICE 0x21 /* class specific */ ++#define UDESC_CS_CONFIG 0x22 ++#define UDESC_CS_STRING 0x23 ++#define UDESC_CS_INTERFACE 0x24 ++#define UDESC_CS_ENDPOINT 0x25 ++#define UDESC_HUB 0x29 ++#define UR_SET_DESCRIPTOR 0x07 ++#define UR_GET_CONFIG 0x08 ++#define UR_SET_CONFIG 0x09 ++#define UR_GET_INTERFACE 0x0a ++#define UR_SET_INTERFACE 0x0b ++#define UR_SYNCH_FRAME 0x0c ++#define WUR_SET_ENCRYPTION 0x0d ++#define WUR_GET_ENCRYPTION 0x0e ++#define WUR_SET_HANDSHAKE 0x0f ++#define WUR_GET_HANDSHAKE 0x10 ++#define WUR_SET_CONNECTION 0x11 ++#define WUR_SET_SECURITY_DATA 0x12 ++#define WUR_GET_SECURITY_DATA 0x13 ++#define WUR_SET_WUSB_DATA 0x14 ++#define WUDATA_DRPIE_INFO 0x01 ++#define WUDATA_TRANSMIT_DATA 0x02 ++#define WUDATA_TRANSMIT_PARAMS 0x03 ++#define WUDATA_RECEIVE_PARAMS 0x04 ++#define WUDATA_TRANSMIT_POWER 0x05 ++#define WUR_LOOPBACK_DATA_WRITE 0x15 ++#define WUR_LOOPBACK_DATA_READ 0x16 ++#define WUR_SET_INTERFACE_DS 0x17 ++ ++/* Feature numbers */ ++#define UF_ENDPOINT_HALT 0 ++#define UF_DEVICE_REMOTE_WAKEUP 1 ++#define UF_TEST_MODE 2 ++#define UF_DEVICE_B_HNP_ENABLE 3 ++#define UF_DEVICE_A_HNP_SUPPORT 4 ++#define UF_DEVICE_A_ALT_HNP_SUPPORT 5 ++#define WUF_WUSB 3 ++#define WUF_TX_DRPIE 0x0 ++#define WUF_DEV_XMIT_PACKET 0x1 ++#define WUF_COUNT_PACKETS 0x2 ++#define WUF_CAPTURE_PACKETS 0x3 ++#define UF_FUNCTION_SUSPEND 0 ++#define UF_U1_ENABLE 48 ++#define UF_U2_ENABLE 49 ++#define UF_LTM_ENABLE 50 ++ ++/* Class requests from the USB 2.0 hub spec, table 11-15 */ ++#define UCR_CLEAR_HUB_FEATURE (0x2000 | UR_CLEAR_FEATURE) ++#define UCR_CLEAR_PORT_FEATURE (0x2300 | UR_CLEAR_FEATURE) ++#define UCR_GET_HUB_DESCRIPTOR (0xa000 | UR_GET_DESCRIPTOR) ++#define UCR_GET_HUB_STATUS (0xa000 | UR_GET_STATUS) ++#define UCR_GET_PORT_STATUS (0xa300 | UR_GET_STATUS) ++#define UCR_SET_HUB_FEATURE (0x2000 | UR_SET_FEATURE) ++#define UCR_SET_PORT_FEATURE (0x2300 | UR_SET_FEATURE) ++#define UCR_SET_AND_TEST_PORT_FEATURE (0xa300 | UR_SET_AND_TEST_FEATURE) ++ ++#ifdef _MSC_VER ++#include ++#endif ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDescriptorSubtype; ++} UPACKED usb_descriptor_t; ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++} UPACKED usb_descriptor_header_t; ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord bcdUSB; ++#define UD_USB_2_0 0x0200 ++#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0) ++ uByte bDeviceClass; ++ uByte bDeviceSubClass; ++ uByte bDeviceProtocol; ++ uByte bMaxPacketSize; ++ /* The fields below are not part of the initial descriptor. */ ++ uWord idVendor; ++ uWord idProduct; ++ uWord bcdDevice; ++ uByte iManufacturer; ++ uByte iProduct; ++ uByte iSerialNumber; ++ uByte bNumConfigurations; ++} UPACKED usb_device_descriptor_t; ++#define USB_DEVICE_DESCRIPTOR_SIZE 18 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wTotalLength; ++ uByte bNumInterface; ++ uByte bConfigurationValue; ++ uByte iConfiguration; ++#define UC_ATT_ONE (1 << 7) /* must be set */ ++#define UC_ATT_SELFPOWER (1 << 6) /* self powered */ ++#define UC_ATT_WAKEUP (1 << 5) /* can wakeup */ ++#define UC_ATT_BATTERY (1 << 4) /* battery powered */ ++ uByte bmAttributes; ++#define UC_BUS_POWERED 0x80 ++#define UC_SELF_POWERED 0x40 ++#define UC_REMOTE_WAKEUP 0x20 ++ uByte bMaxPower; /* max current in 2 mA units */ ++#define UC_POWER_FACTOR 2 ++} UPACKED usb_config_descriptor_t; ++#define USB_CONFIG_DESCRIPTOR_SIZE 9 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bInterfaceNumber; ++ uByte bAlternateSetting; ++ uByte bNumEndpoints; ++ uByte bInterfaceClass; ++ uByte bInterfaceSubClass; ++ uByte bInterfaceProtocol; ++ uByte iInterface; ++} UPACKED usb_interface_descriptor_t; ++#define USB_INTERFACE_DESCRIPTOR_SIZE 9 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bEndpointAddress; ++#define UE_GET_DIR(a) ((a) & 0x80) ++#define UE_SET_DIR(a,d) ((a) | (((d)&1) << 7)) ++#define UE_DIR_IN 0x80 ++#define UE_DIR_OUT 0x00 ++#define UE_ADDR 0x0f ++#define UE_GET_ADDR(a) ((a) & UE_ADDR) ++ uByte bmAttributes; ++#define UE_XFERTYPE 0x03 ++#define UE_CONTROL 0x00 ++#define UE_ISOCHRONOUS 0x01 ++#define UE_BULK 0x02 ++#define UE_INTERRUPT 0x03 ++#define UE_GET_XFERTYPE(a) ((a) & UE_XFERTYPE) ++#define UE_ISO_TYPE 0x0c ++#define UE_ISO_ASYNC 0x04 ++#define UE_ISO_ADAPT 0x08 ++#define UE_ISO_SYNC 0x0c ++#define UE_GET_ISO_TYPE(a) ((a) & UE_ISO_TYPE) ++ uWord wMaxPacketSize; ++ uByte bInterval; ++} UPACKED usb_endpoint_descriptor_t; ++#define USB_ENDPOINT_DESCRIPTOR_SIZE 7 ++ ++typedef struct ss_endpoint_companion_descriptor { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bMaxBurst; ++#define USSE_GET_MAX_STREAMS(a) ((a) & 0x1f) ++#define USSE_SET_MAX_STREAMS(a, b) ((a) | ((b) & 0x1f)) ++#define USSE_GET_MAX_PACKET_NUM(a) ((a) & 0x03) ++#define USSE_SET_MAX_PACKET_NUM(a, b) ((a) | ((b) & 0x03)) ++ uByte bmAttributes; ++ uWord wBytesPerInterval; ++} UPACKED ss_endpoint_companion_descriptor_t; ++#define USB_SS_ENDPOINT_COMPANION_DESCRIPTOR_SIZE 6 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord bString[127]; ++} UPACKED usb_string_descriptor_t; ++#define USB_MAX_STRING_LEN 128 ++#define USB_LANGUAGE_TABLE 0 /* # of the string language id table */ ++ ++/* Hub specific request */ ++#define UR_GET_BUS_STATE 0x02 ++#define UR_CLEAR_TT_BUFFER 0x08 ++#define UR_RESET_TT 0x09 ++#define UR_GET_TT_STATE 0x0a ++#define UR_STOP_TT 0x0b ++ ++/* Hub features */ ++#define UHF_C_HUB_LOCAL_POWER 0 ++#define UHF_C_HUB_OVER_CURRENT 1 ++#define UHF_PORT_CONNECTION 0 ++#define UHF_PORT_ENABLE 1 ++#define UHF_PORT_SUSPEND 2 ++#define UHF_PORT_OVER_CURRENT 3 ++#define UHF_PORT_RESET 4 ++#define UHF_PORT_L1 5 ++#define UHF_PORT_POWER 8 ++#define UHF_PORT_LOW_SPEED 9 ++#define UHF_PORT_HIGH_SPEED 10 ++#define UHF_C_PORT_CONNECTION 16 ++#define UHF_C_PORT_ENABLE 17 ++#define UHF_C_PORT_SUSPEND 18 ++#define UHF_C_PORT_OVER_CURRENT 19 ++#define UHF_C_PORT_RESET 20 ++#define UHF_C_PORT_L1 23 ++#define UHF_PORT_TEST 21 ++#define UHF_PORT_INDICATOR 22 ++ ++typedef struct { ++ uByte bDescLength; ++ uByte bDescriptorType; ++ uByte bNbrPorts; ++ uWord wHubCharacteristics; ++#define UHD_PWR 0x0003 ++#define UHD_PWR_GANGED 0x0000 ++#define UHD_PWR_INDIVIDUAL 0x0001 ++#define UHD_PWR_NO_SWITCH 0x0002 ++#define UHD_COMPOUND 0x0004 ++#define UHD_OC 0x0018 ++#define UHD_OC_GLOBAL 0x0000 ++#define UHD_OC_INDIVIDUAL 0x0008 ++#define UHD_OC_NONE 0x0010 ++#define UHD_TT_THINK 0x0060 ++#define UHD_TT_THINK_8 0x0000 ++#define UHD_TT_THINK_16 0x0020 ++#define UHD_TT_THINK_24 0x0040 ++#define UHD_TT_THINK_32 0x0060 ++#define UHD_PORT_IND 0x0080 ++ uByte bPwrOn2PwrGood; /* delay in 2 ms units */ ++#define UHD_PWRON_FACTOR 2 ++ uByte bHubContrCurrent; ++ uByte DeviceRemovable[32]; /* max 255 ports */ ++#define UHD_NOT_REMOV(desc, i) \ ++ (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1) ++ /* deprecated */ uByte PortPowerCtrlMask[1]; ++} UPACKED usb_hub_descriptor_t; ++#define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */ ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord bcdUSB; ++ uByte bDeviceClass; ++ uByte bDeviceSubClass; ++ uByte bDeviceProtocol; ++ uByte bMaxPacketSize0; ++ uByte bNumConfigurations; ++ uByte bReserved; ++} UPACKED usb_device_qualifier_t; ++#define USB_DEVICE_QUALIFIER_SIZE 10 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bmAttributes; ++#define UOTG_SRP 0x01 ++#define UOTG_HNP 0x02 ++} UPACKED usb_otg_descriptor_t; ++ ++/* OTG feature selectors */ ++#define UOTG_B_HNP_ENABLE 3 ++#define UOTG_A_HNP_SUPPORT 4 ++#define UOTG_A_ALT_HNP_SUPPORT 5 ++ ++typedef struct { ++ uWord wStatus; ++/* Device status flags */ ++#define UDS_SELF_POWERED 0x0001 ++#define UDS_REMOTE_WAKEUP 0x0002 ++/* Endpoint status flags */ ++#define UES_HALT 0x0001 ++} UPACKED usb_status_t; ++ ++typedef struct { ++ uWord wHubStatus; ++#define UHS_LOCAL_POWER 0x0001 ++#define UHS_OVER_CURRENT 0x0002 ++ uWord wHubChange; ++} UPACKED usb_hub_status_t; ++ ++typedef struct { ++ uWord wPortStatus; ++#define UPS_CURRENT_CONNECT_STATUS 0x0001 ++#define UPS_PORT_ENABLED 0x0002 ++#define UPS_SUSPEND 0x0004 ++#define UPS_OVERCURRENT_INDICATOR 0x0008 ++#define UPS_RESET 0x0010 ++#define UPS_PORT_POWER 0x0100 ++#define UPS_LOW_SPEED 0x0200 ++#define UPS_HIGH_SPEED 0x0400 ++#define UPS_PORT_TEST 0x0800 ++#define UPS_PORT_INDICATOR 0x1000 ++ uWord wPortChange; ++#define UPS_C_CONNECT_STATUS 0x0001 ++#define UPS_C_PORT_ENABLED 0x0002 ++#define UPS_C_SUSPEND 0x0004 ++#define UPS_C_OVERCURRENT_INDICATOR 0x0008 ++#define UPS_C_PORT_RESET 0x0010 ++} UPACKED usb_port_status_t; ++ ++#ifdef _MSC_VER ++#include ++#endif ++ ++/* Device class codes */ ++#define UDCLASS_IN_INTERFACE 0x00 ++#define UDCLASS_COMM 0x02 ++#define UDCLASS_HUB 0x09 ++#define UDSUBCLASS_HUB 0x00 ++#define UDPROTO_FSHUB 0x00 ++#define UDPROTO_HSHUBSTT 0x01 ++#define UDPROTO_HSHUBMTT 0x02 ++#define UDCLASS_DIAGNOSTIC 0xdc ++#define UDCLASS_WIRELESS 0xe0 ++#define UDSUBCLASS_RF 0x01 ++#define UDPROTO_BLUETOOTH 0x01 ++#define UDCLASS_VENDOR 0xff ++ ++/* Interface class codes */ ++#define UICLASS_UNSPEC 0x00 ++ ++#define UICLASS_AUDIO 0x01 ++#define UISUBCLASS_AUDIOCONTROL 1 ++#define UISUBCLASS_AUDIOSTREAM 2 ++#define UISUBCLASS_MIDISTREAM 3 ++ ++#define UICLASS_CDC 0x02 /* communication */ ++#define UISUBCLASS_DIRECT_LINE_CONTROL_MODEL 1 ++#define UISUBCLASS_ABSTRACT_CONTROL_MODEL 2 ++#define UISUBCLASS_TELEPHONE_CONTROL_MODEL 3 ++#define UISUBCLASS_MULTICHANNEL_CONTROL_MODEL 4 ++#define UISUBCLASS_CAPI_CONTROLMODEL 5 ++#define UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6 ++#define UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7 ++#define UIPROTO_CDC_AT 1 ++ ++#define UICLASS_HID 0x03 ++#define UISUBCLASS_BOOT 1 ++#define UIPROTO_BOOT_KEYBOARD 1 ++ ++#define UICLASS_PHYSICAL 0x05 ++ ++#define UICLASS_IMAGE 0x06 ++ ++#define UICLASS_PRINTER 0x07 ++#define UISUBCLASS_PRINTER 1 ++#define UIPROTO_PRINTER_UNI 1 ++#define UIPROTO_PRINTER_BI 2 ++#define UIPROTO_PRINTER_1284 3 ++ ++#define UICLASS_MASS 0x08 ++#define UISUBCLASS_RBC 1 ++#define UISUBCLASS_SFF8020I 2 ++#define UISUBCLASS_QIC157 3 ++#define UISUBCLASS_UFI 4 ++#define UISUBCLASS_SFF8070I 5 ++#define UISUBCLASS_SCSI 6 ++#define UIPROTO_MASS_CBI_I 0 ++#define UIPROTO_MASS_CBI 1 ++#define UIPROTO_MASS_BBB_OLD 2 /* Not in the spec anymore */ ++#define UIPROTO_MASS_BBB 80 /* 'P' for the Iomega Zip drive */ ++ ++#define UICLASS_HUB 0x09 ++#define UISUBCLASS_HUB 0 ++#define UIPROTO_FSHUB 0 ++#define UIPROTO_HSHUBSTT 0 /* Yes, same as previous */ ++#define UIPROTO_HSHUBMTT 1 ++ ++#define UICLASS_CDC_DATA 0x0a ++#define UISUBCLASS_DATA 0 ++#define UIPROTO_DATA_ISDNBRI 0x30 /* Physical iface */ ++#define UIPROTO_DATA_HDLC 0x31 /* HDLC */ ++#define UIPROTO_DATA_TRANSPARENT 0x32 /* Transparent */ ++#define UIPROTO_DATA_Q921M 0x50 /* Management for Q921 */ ++#define UIPROTO_DATA_Q921 0x51 /* Data for Q921 */ ++#define UIPROTO_DATA_Q921TM 0x52 /* TEI multiplexer for Q921 */ ++#define UIPROTO_DATA_V42BIS 0x90 /* Data compression */ ++#define UIPROTO_DATA_Q931 0x91 /* Euro-ISDN */ ++#define UIPROTO_DATA_V120 0x92 /* V.24 rate adaption */ ++#define UIPROTO_DATA_CAPI 0x93 /* CAPI 2.0 commands */ ++#define UIPROTO_DATA_HOST_BASED 0xfd /* Host based driver */ ++#define UIPROTO_DATA_PUF 0xfe /* see Prot. Unit Func. Desc.*/ ++#define UIPROTO_DATA_VENDOR 0xff /* Vendor specific */ ++ ++#define UICLASS_SMARTCARD 0x0b ++ ++/*#define UICLASS_FIRM_UPD 0x0c*/ ++ ++#define UICLASS_SECURITY 0x0d ++ ++#define UICLASS_DIAGNOSTIC 0xdc ++ ++#define UICLASS_WIRELESS 0xe0 ++#define UISUBCLASS_RF 0x01 ++#define UIPROTO_BLUETOOTH 0x01 ++ ++#define UICLASS_APPL_SPEC 0xfe ++#define UISUBCLASS_FIRMWARE_DOWNLOAD 1 ++#define UISUBCLASS_IRDA 2 ++#define UIPROTO_IRDA 0 ++ ++#define UICLASS_VENDOR 0xff ++ ++#define USB_HUB_MAX_DEPTH 5 ++ ++/* ++ * Minimum time a device needs to be powered down to go through ++ * a power cycle. XXX Are these time in the spec? ++ */ ++#define USB_POWER_DOWN_TIME 200 /* ms */ ++#define USB_PORT_POWER_DOWN_TIME 100 /* ms */ ++ ++/* Allow for marginal (i.e. non-conforming) devices. */ ++#define USB_PORT_RESET_DELAY 50 /* ms */ ++#define USB_PORT_ROOT_RESET_DELAY 250 /* ms */ ++#define USB_PORT_RESET_RECOVERY 250 /* ms */ ++#define USB_PORT_POWERUP_DELAY 300 /* ms */ ++#define USB_SET_ADDRESS_SETTLE 10 /* ms */ ++#define USB_RESUME_DELAY (50*5) /* ms */ ++#define USB_RESUME_WAIT 50 /* ms */ ++#define USB_RESUME_RECOVERY 50 /* ms */ ++#define USB_EXTRA_POWER_UP_TIME 20 /* ms */ ++ ++#define USB_MIN_POWER 100 /* mA */ ++#define USB_MAX_POWER 500 /* mA */ ++ ++#define USB_BUS_RESET_DELAY 100 /* ms XXX?*/ ++ ++#define USB_UNCONFIG_NO 0 ++#define USB_UNCONFIG_INDEX (-1) ++ ++/*** ioctl() related stuff ***/ ++ ++struct usb_ctl_request { ++ int ucr_addr; ++ usb_device_request_t ucr_request; ++ void *ucr_data; ++ int ucr_flags; ++#define USBD_SHORT_XFER_OK 0x04 /* allow short reads */ ++ int ucr_actlen; /* actual length transferred */ ++}; ++ ++struct usb_alt_interface { ++ int uai_config_index; ++ int uai_interface_index; ++ int uai_alt_no; ++}; ++ ++#define USB_CURRENT_CONFIG_INDEX (-1) ++#define USB_CURRENT_ALT_INDEX (-1) ++ ++struct usb_config_desc { ++ int ucd_config_index; ++ usb_config_descriptor_t ucd_desc; ++}; ++ ++struct usb_interface_desc { ++ int uid_config_index; ++ int uid_interface_index; ++ int uid_alt_index; ++ usb_interface_descriptor_t uid_desc; ++}; ++ ++struct usb_endpoint_desc { ++ int ued_config_index; ++ int ued_interface_index; ++ int ued_alt_index; ++ int ued_endpoint_index; ++ usb_endpoint_descriptor_t ued_desc; ++}; ++ ++struct usb_full_desc { ++ int ufd_config_index; ++ u_int ufd_size; ++ u_char *ufd_data; ++}; ++ ++struct usb_string_desc { ++ int usd_string_index; ++ int usd_language_id; ++ usb_string_descriptor_t usd_desc; ++}; ++ ++struct usb_ctl_report_desc { ++ int ucrd_size; ++ u_char ucrd_data[1024]; /* filled data size will vary */ ++}; ++ ++typedef struct { u_int32_t cookie; } usb_event_cookie_t; ++ ++#define USB_MAX_DEVNAMES 4 ++#define USB_MAX_DEVNAMELEN 16 ++struct usb_device_info { ++ u_int8_t udi_bus; ++ u_int8_t udi_addr; /* device address */ ++ usb_event_cookie_t udi_cookie; ++ char udi_product[USB_MAX_STRING_LEN]; ++ char udi_vendor[USB_MAX_STRING_LEN]; ++ char udi_release[8]; ++ u_int16_t udi_productNo; ++ u_int16_t udi_vendorNo; ++ u_int16_t udi_releaseNo; ++ u_int8_t udi_class; ++ u_int8_t udi_subclass; ++ u_int8_t udi_protocol; ++ u_int8_t udi_config; ++ u_int8_t udi_speed; ++#define USB_SPEED_UNKNOWN 0 ++#define USB_SPEED_LOW 1 ++#define USB_SPEED_FULL 2 ++#define USB_SPEED_HIGH 3 ++#define USB_SPEED_VARIABLE 4 ++#define USB_SPEED_SUPER 5 ++ int udi_power; /* power consumption in mA, 0 if selfpowered */ ++ int udi_nports; ++ char udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN]; ++ u_int8_t udi_ports[16];/* hub only: addresses of devices on ports */ ++#define USB_PORT_ENABLED 0xff ++#define USB_PORT_SUSPENDED 0xfe ++#define USB_PORT_POWERED 0xfd ++#define USB_PORT_DISABLED 0xfc ++}; ++ ++struct usb_ctl_report { ++ int ucr_report; ++ u_char ucr_data[1024]; /* filled data size will vary */ ++}; ++ ++struct usb_device_stats { ++ u_long uds_requests[4]; /* indexed by transfer type UE_* */ ++}; ++ ++#define WUSB_MIN_IE 0x80 ++#define WUSB_WCTA_IE 0x80 ++#define WUSB_WCONNECTACK_IE 0x81 ++#define WUSB_WHOSTINFO_IE 0x82 ++#define WUHI_GET_CA(_bmAttributes_) ((_bmAttributes_) & 0x3) ++#define WUHI_CA_RECONN 0x00 ++#define WUHI_CA_LIMITED 0x01 ++#define WUHI_CA_ALL 0x03 ++#define WUHI_GET_MLSI(_bmAttributes_) (((_bmAttributes_) & 0x38) >> 3) ++#define WUSB_WCHCHANGEANNOUNCE_IE 0x83 ++#define WUSB_WDEV_DISCONNECT_IE 0x84 ++#define WUSB_WHOST_DISCONNECT_IE 0x85 ++#define WUSB_WRELEASE_CHANNEL_IE 0x86 ++#define WUSB_WWORK_IE 0x87 ++#define WUSB_WCHANNEL_STOP_IE 0x88 ++#define WUSB_WDEV_KEEPALIVE_IE 0x89 ++#define WUSB_WISOCH_DISCARD_IE 0x8A ++#define WUSB_WRESETDEVICE_IE 0x8B ++#define WUSB_WXMIT_PACKET_ADJUST_IE 0x8C ++#define WUSB_MAX_IE 0x8C ++ ++/* Device Notification Types */ ++ ++#define WUSB_DN_MIN 0x01 ++#define WUSB_DN_CONNECT 0x01 ++# define WUSB_DA_OLDCONN 0x00 ++# define WUSB_DA_NEWCONN 0x01 ++# define WUSB_DA_SELF_BEACON 0x02 ++# define WUSB_DA_DIR_BEACON 0x04 ++# define WUSB_DA_NO_BEACON 0x06 ++#define WUSB_DN_DISCONNECT 0x02 ++#define WUSB_DN_EPRDY 0x03 ++#define WUSB_DN_MASAVAILCHANGED 0x04 ++#define WUSB_DN_REMOTEWAKEUP 0x05 ++#define WUSB_DN_SLEEP 0x06 ++#define WUSB_DN_ALIVE 0x07 ++#define WUSB_DN_MAX 0x07 ++ ++#ifdef _MSC_VER ++#include ++#endif ++ ++/* WUSB Handshake Data. Used during the SET/GET HANDSHAKE requests */ ++typedef struct wusb_hndshk_data { ++ uByte bMessageNumber; ++ uByte bStatus; ++ uByte tTKID[3]; ++ uByte bReserved; ++ uByte CDID[16]; ++ uByte Nonce[16]; ++ uByte MIC[8]; ++} UPACKED wusb_hndshk_data_t; ++#define WUSB_HANDSHAKE_LEN_FOR_MIC 38 ++ ++/* WUSB Connection Context */ ++typedef struct wusb_conn_context { ++ uByte CHID [16]; ++ uByte CDID [16]; ++ uByte CK [16]; ++} UPACKED wusb_conn_context_t; ++ ++/* WUSB Security Descriptor */ ++typedef struct wusb_security_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wTotalLength; ++ uByte bNumEncryptionTypes; ++} UPACKED wusb_security_desc_t; ++ ++/* WUSB Encryption Type Descriptor */ ++typedef struct wusb_encrypt_type_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ ++ uByte bEncryptionType; ++#define WUETD_UNSECURE 0 ++#define WUETD_WIRED 1 ++#define WUETD_CCM_1 2 ++#define WUETD_RSA_1 3 ++ ++ uByte bEncryptionValue; ++ uByte bAuthKeyIndex; ++} UPACKED wusb_encrypt_type_desc_t; ++ ++/* WUSB Key Descriptor */ ++typedef struct wusb_key_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte tTKID[3]; ++ uByte bReserved; ++ uByte KeyData[1]; /* variable length */ ++} UPACKED wusb_key_desc_t; ++ ++/* WUSB BOS Descriptor (Binary device Object Store) */ ++typedef struct wusb_bos_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wTotalLength; ++ uByte bNumDeviceCaps; ++} UPACKED wusb_bos_desc_t; ++ ++#define USB_DEVICE_CAPABILITY_20_EXTENSION 0x02 ++typedef struct usb_dev_cap_20_ext_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++#define USB_20_EXT_LPM 0x02 ++ uDWord bmAttributes; ++} UPACKED usb_dev_cap_20_ext_desc_t; ++ ++#define USB_DEVICE_CAPABILITY_SS_USB 0x03 ++typedef struct usb_dev_cap_ss_usb { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++#define USB_DC_SS_USB_LTM_CAPABLE 0x02 ++ uByte bmAttributes; ++#define USB_DC_SS_USB_SPEED_SUPPORT_LOW 0x01 ++#define USB_DC_SS_USB_SPEED_SUPPORT_FULL 0x02 ++#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH 0x04 ++#define USB_DC_SS_USB_SPEED_SUPPORT_SS 0x08 ++ uWord wSpeedsSupported; ++ uByte bFunctionalitySupport; ++ uByte bU1DevExitLat; ++ uWord wU2DevExitLat; ++} UPACKED usb_dev_cap_ss_usb_t; ++ ++#define USB_DEVICE_CAPABILITY_CONTAINER_ID 0x04 ++typedef struct usb_dev_cap_container_id { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++ uByte bReserved; ++ uByte containerID[16]; ++} UPACKED usb_dev_cap_container_id_t; ++ ++/* Device Capability Type Codes */ ++#define WUSB_DEVICE_CAPABILITY_WIRELESS_USB 0x01 ++ ++/* Device Capability Descriptor */ ++typedef struct wusb_dev_cap_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++ uByte caps[1]; /* Variable length */ ++} UPACKED wusb_dev_cap_desc_t; ++ ++/* Device Capability Descriptor */ ++typedef struct wusb_dev_cap_uwb_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++ uByte bmAttributes; ++ uWord wPHYRates; /* Bitmap */ ++ uByte bmTFITXPowerInfo; ++ uByte bmFFITXPowerInfo; ++ uWord bmBandGroup; ++ uByte bReserved; ++} UPACKED wusb_dev_cap_uwb_desc_t; ++ ++/* Wireless USB Endpoint Companion Descriptor */ ++typedef struct wusb_endpoint_companion_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bMaxBurst; ++ uByte bMaxSequence; ++ uWord wMaxStreamDelay; ++ uWord wOverTheAirPacketSize; ++ uByte bOverTheAirInterval; ++ uByte bmCompAttributes; ++} UPACKED wusb_endpoint_companion_desc_t; ++ ++/* Wireless USB Numeric Association M1 Data Structure */ ++typedef struct wusb_m1_data { ++ uByte version; ++ uWord langId; ++ uByte deviceFriendlyNameLength; ++ uByte sha_256_m3[32]; ++ uByte deviceFriendlyName[256]; ++} UPACKED wusb_m1_data_t; ++ ++typedef struct wusb_m2_data { ++ uByte version; ++ uWord langId; ++ uByte hostFriendlyNameLength; ++ uByte pkh[384]; ++ uByte hostFriendlyName[256]; ++} UPACKED wusb_m2_data_t; ++ ++typedef struct wusb_m3_data { ++ uByte pkd[384]; ++ uByte nd; ++} UPACKED wusb_m3_data_t; ++ ++typedef struct wusb_m4_data { ++ uDWord _attributeTypeIdAndLength_1; ++ uWord associationTypeId; ++ ++ uDWord _attributeTypeIdAndLength_2; ++ uWord associationSubTypeId; ++ ++ uDWord _attributeTypeIdAndLength_3; ++ uDWord length; ++ ++ uDWord _attributeTypeIdAndLength_4; ++ uDWord associationStatus; ++ ++ uDWord _attributeTypeIdAndLength_5; ++ uByte chid[16]; ++ ++ uDWord _attributeTypeIdAndLength_6; ++ uByte cdid[16]; ++ ++ uDWord _attributeTypeIdAndLength_7; ++ uByte bandGroups[2]; ++} UPACKED wusb_m4_data_t; ++ ++#ifdef _MSC_VER ++#include ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _USB_H_ */ +diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c +index 76c1ad9..9bc0a73 100644 +--- a/drivers/video/fbdev/core/fbmem.c ++++ b/drivers/video/fbdev/core/fbmem.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + + #include + +@@ -1083,7 +1084,24 @@ fb_blank(struct fb_info *info, int blank) + return ret; + } + EXPORT_SYMBOL(fb_blank); ++#ifdef CONFIG_ARCH_HISI_BVT ++#ifdef CONFIG_DMA_SHARED_BUFFER ++int ++fb_get_dmabuf(struct fb_info *info, int flags) ++{ ++ struct dma_buf *dmabuf; ++ ++ if (info->fbops->fb_dmabuf_export == NULL) ++ return -ENOTTY; ++ ++ dmabuf = info->fbops->fb_dmabuf_export(info); ++ if (IS_ERR(dmabuf)) ++ return PTR_ERR(dmabuf); + ++ return dma_buf_fd(dmabuf, flags); ++} ++#endif ++#endif /* CONFIG_ARCH_HISI_BVT */ + static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) + { +@@ -1094,6 +1112,9 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, + struct fb_cmap cmap_from; + struct fb_cmap_user cmap; + struct fb_event event; ++#if defined(CONFIG_ARCH_HISI_BVT) && defined(CONFIG_DMA_SHARED_BUFFER) ++ struct fb_dmabuf_export dmaexp; ++#endif + void __user *argp = (void __user *)arg; + long ret = 0; + +@@ -1211,6 +1232,23 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, + unlock_fb_info(info); + console_unlock(); + break; ++#if defined(CONFIG_ARCH_HISI_BVT) && defined(CONFIG_DMA_SHARED_BUFFER) ++ case FBIOGET_DMABUF: ++ if (copy_from_user(&dmaexp, argp, sizeof(dmaexp))) ++ return -EFAULT; ++ ++ if (!lock_fb_info(info)) ++ return -ENODEV; ++ dmaexp.fd = fb_get_dmabuf(info, dmaexp.flags); ++ unlock_fb_info(info); ++ ++ if (dmaexp.fd < 0) ++ return dmaexp.fd; ++ ++ ret = copy_to_user(argp, &dmaexp, sizeof(dmaexp)) ++ ? -EFAULT : 0; ++ break; ++#endif /* CONFIG_ARCH_HISI_BVT */ + default: + if (!lock_fb_info(info)) + return -ENODEV; +diff --git a/fs/Kconfig b/fs/Kconfig +index 4bd03a2..9b0955c 100644 +--- a/fs/Kconfig ++++ b/fs/Kconfig +@@ -232,6 +232,7 @@ source "fs/hfsplus/Kconfig" + source "fs/befs/Kconfig" + source "fs/bfs/Kconfig" + source "fs/efs/Kconfig" ++source "fs/yaffs2/Kconfig" + source "fs/jffs2/Kconfig" + # UBIFS File system configuration + source "fs/ubifs/Kconfig" +diff --git a/fs/Makefile b/fs/Makefile +index ed2b632..c255772 100644 +--- a/fs/Makefile ++++ b/fs/Makefile +@@ -129,3 +129,4 @@ obj-y += exofs/ # Multiple modules + obj-$(CONFIG_CEPH_FS) += ceph/ + obj-$(CONFIG_PSTORE) += pstore/ + obj-$(CONFIG_EFIVAR_FS) += efivarfs/ ++obj-$(CONFIG_YAFFS_FS) += yaffs2/ +diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c +index 1626927..24940dd 100644 +--- a/fs/xfs/xfs_buf.c ++++ b/fs/xfs/xfs_buf.c +@@ -116,7 +116,7 @@ static inline void + __xfs_buf_ioacct_dec( + struct xfs_buf *bp) + { +- ASSERT(spin_is_locked(&bp->b_lock)); ++ lockdep_assert_held(&bp->b_lock); + + if (bp->b_state & XFS_BSTATE_IN_FLIGHT) { + bp->b_state &= ~XFS_BSTATE_IN_FLIGHT; +diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c +index 74304b6..e279882 100644 +--- a/fs/xfs/xfs_icache.c ++++ b/fs/xfs/xfs_icache.c +@@ -66,7 +66,6 @@ xfs_inode_alloc( + + XFS_STATS_INC(mp, vn_active); + ASSERT(atomic_read(&ip->i_pincount) == 0); +- ASSERT(!spin_is_locked(&ip->i_flags_lock)); + ASSERT(!xfs_isiflocked(ip)); + ASSERT(ip->i_ino == 0); + +@@ -192,7 +191,7 @@ xfs_perag_set_reclaim_tag( + { + struct xfs_mount *mp = pag->pag_mount; + +- ASSERT(spin_is_locked(&pag->pag_ici_lock)); ++ lockdep_assert_held(&pag->pag_ici_lock); + if (pag->pag_ici_reclaimable++) + return; + +@@ -214,7 +213,7 @@ xfs_perag_clear_reclaim_tag( + { + struct xfs_mount *mp = pag->pag_mount; + +- ASSERT(spin_is_locked(&pag->pag_ici_lock)); ++ lockdep_assert_held(&pag->pag_ici_lock); + if (--pag->pag_ici_reclaimable) + return; + +diff --git a/fs/yaffs2/Kconfig b/fs/yaffs2/Kconfig +new file mode 100644 +index 0000000..408570f +--- /dev/null ++++ b/fs/yaffs2/Kconfig +@@ -0,0 +1,171 @@ ++# ++# yaffs file system configurations ++# ++ ++config YAFFS_FS ++ tristate "yaffs2 file system support" ++ default n ++ depends on MTD_BLOCK ++ select YAFFS_YAFFS1 ++ select YAFFS_YAFFS2 ++ help ++ yaffs2, or Yet Another Flash File System, is a file system ++ optimised for NAND Flash chips. ++ ++ To compile the yaffs2 file system support as a module, choose M ++ here: the module will be called yaffs2. ++ ++ If unsure, say N. ++ ++ Further information on yaffs2 is available at ++ . ++ ++config YAFFS_YAFFS1 ++ bool "512 byte / page devices" ++ depends on YAFFS_FS ++ default y ++ help ++ Enable yaffs1 support -- yaffs for 512 byte / page devices ++ ++ Not needed for 2K-page devices. ++ ++ If unsure, say Y. ++ ++config YAFFS_9BYTE_TAGS ++ bool "Use older-style on-NAND data format with pageStatus byte" ++ depends on YAFFS_YAFFS1 ++ default n ++ help ++ ++ Older-style on-NAND data format has a "pageStatus" byte to record ++ chunk/page state. This byte is zero when the page is discarded. ++ Choose this option if you have existing on-NAND data using this ++ format that you need to continue to support. New data written ++ also uses the older-style format. Note: Use of this option ++ generally requires that MTD's oob layout be adjusted to use the ++ older-style format. See notes on tags formats and MTD versions ++ in yaffs_mtdif1.c. ++ ++ If unsure, say N. ++ ++config YAFFS_DOES_ECC ++ bool "Lets yaffs do its own ECC" ++ depends on YAFFS_FS && YAFFS_YAFFS1 && !YAFFS_9BYTE_TAGS ++ default n ++ help ++ This enables yaffs to use its own ECC functions instead of using ++ the ones from the generic MTD-NAND driver. ++ ++ If unsure, say N. ++ ++config YAFFS_ECC_WRONG_ORDER ++ bool "Use the same ecc byte order as Steven Hill's nand_ecc.c" ++ depends on YAFFS_FS && YAFFS_DOES_ECC && !YAFFS_9BYTE_TAGS ++ default n ++ help ++ This makes yaffs_ecc.c use the same ecc byte order as Steven ++ Hill's nand_ecc.c. If not set, then you get the same ecc byte ++ order as SmartMedia. ++ ++ If unsure, say N. ++ ++config YAFFS_YAFFS2 ++ bool "2048 byte (or larger) / page devices" ++ depends on YAFFS_FS ++ default y ++ help ++ Enable yaffs2 support -- yaffs for >= 2K bytes per page devices ++ ++ If unsure, say Y. ++ ++config YAFFS_AUTO_YAFFS2 ++ bool "Autoselect yaffs2 format" ++ depends on YAFFS_YAFFS2 ++ default y ++ help ++ Without this, you need to explicitely use yaffs2 as the file ++ system type. With this, you can say "yaffs" and yaffs or yaffs2 ++ will be used depending on the device page size (yaffs on ++ 512-byte page devices, yaffs2 on 2K page devices). ++ ++ If unsure, say Y. ++ ++config YAFFS_DISABLE_TAGS_ECC ++ bool "Disable yaffs from doing ECC on tags by default" ++ depends on YAFFS_FS && YAFFS_YAFFS2 ++ default n ++ help ++ This defaults yaffs to using its own ECC calculations on tags instead of ++ just relying on the MTD. ++ This behavior can also be overridden with tags_ecc_on and ++ tags_ecc_off mount options. ++ ++ If unsure, say N. ++ ++config YAFFS_ALWAYS_CHECK_CHUNK_ERASED ++ bool "Force chunk erase check" ++ depends on YAFFS_FS ++ default n ++ help ++ Normally yaffs only checks chunks before writing until an erased ++ chunk is found. This helps to detect any partially written ++ chunks that might have happened due to power loss. ++ ++ Enabling this forces on the test that chunks are erased in flash ++ before writing to them. This takes more time but is potentially ++ a bit more secure. ++ ++ Suggest setting Y during development and ironing out driver ++ issues etc. Suggest setting to N if you want faster writing. ++ ++ If unsure, say Y. ++ ++config YAFFS_EMPTY_LOST_AND_FOUND ++ bool "Empty lost and found on boot" ++ depends on YAFFS_FS ++ default n ++ help ++ If this is enabled then the contents of lost and found is ++ automatically dumped at mount. ++ ++ If unsure, say N. ++ ++config YAFFS_DISABLE_BLOCK_REFRESHING ++ bool "Disable yaffs2 block refreshing" ++ depends on YAFFS_FS ++ default n ++ help ++ If this is set, then block refreshing is disabled. ++ Block refreshing infrequently refreshes the oldest block in ++ a yaffs2 file system. This mechanism helps to refresh flash to ++ mitigate against data loss. This is particularly useful for MLC. ++ ++ If unsure, say N. ++ ++config YAFFS_DISABLE_BACKGROUND ++ bool "Disable yaffs2 background processing" ++ depends on YAFFS_FS ++ default n ++ help ++ If this is set, then background processing is disabled. ++ Background processing makes many foreground activities faster. ++ ++ If unsure, say N. ++ ++config YAFFS_DISABLE_BAD_BLOCK_MARKING ++ bool "Disable yaffs2 bad block marking" ++ depends on YAFFS_FS ++ default n ++ help ++ Useful during early flash bring up to prevent problems causing ++ lots of bad block marking. ++ ++ If unsure, say N. ++ ++config YAFFS_XATTR ++ bool "Enable yaffs2 xattr support" ++ depends on YAFFS_FS ++ default y ++ help ++ If this is set then yaffs2 will provide xattr support. ++ If unsure, say Y. +diff --git a/fs/yaffs2/Makefile b/fs/yaffs2/Makefile +new file mode 100644 +index 0000000..c052395 +--- /dev/null ++++ b/fs/yaffs2/Makefile +@@ -0,0 +1,19 @@ ++# ++# Makefile for the linux YAFFS filesystem routines. ++# ++ ++obj-$(CONFIG_YAFFS_FS) += yaffs.o ++ ++yaffs-y := yaffs_ecc.o yaffs_vfs.o yaffs_guts.o yaffs_checkptrw.o ++yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o ++yaffs-y += yaffs_tagscompat.o yaffs_tagsmarshall.o ++yaffs-y += yaffs_endian.o ++yaffs-y += yaffs_mtdif.o ++yaffs-y += yaffs_nameval.o yaffs_attribs.o ++yaffs-y += yaffs_allocator.o ++yaffs-y += yaffs_yaffs1.o ++yaffs-y += yaffs_yaffs2.o ++yaffs-y += yaffs_bitmap.o ++yaffs-y += yaffs_summary.o ++yaffs-y += yaffs_verify.o ++ +diff --git a/fs/yaffs2/yaffs_allocator.c b/fs/yaffs2/yaffs_allocator.c +new file mode 100644 +index 0000000..c8f2861 +--- /dev/null ++++ b/fs/yaffs2/yaffs_allocator.c +@@ -0,0 +1,357 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * 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 "yaffs_allocator.h" ++#include "yaffs_guts.h" ++#include "yaffs_trace.h" ++#include "yportenv.h" ++ ++/* ++ * Each entry in yaffs_tnode_list and yaffs_obj_list hold blocks ++ * of approx 100 objects that are themn allocated singly. ++ * This is basically a simplified slab allocator. ++ * ++ * We don't use the Linux slab allocator because slab does not allow ++ * us to dump all the objects in one hit when we do a umount and tear ++ * down all the tnodes and objects. slab requires that we first free ++ * the individual objects. ++ * ++ * Once yaffs has been mainlined I shall try to motivate for a change ++ * to slab to provide the extra features we need here. ++ */ ++ ++struct yaffs_tnode_list { ++ struct yaffs_tnode_list *next; ++ struct yaffs_tnode *tnodes; ++}; ++ ++struct yaffs_obj_list { ++ struct yaffs_obj_list *next; ++ struct yaffs_obj *objects; ++}; ++ ++struct yaffs_allocator { ++ int n_tnodes_created; ++ struct yaffs_tnode *free_tnodes; ++ int n_free_tnodes; ++ struct yaffs_tnode_list *alloc_tnode_list; ++ ++ int n_obj_created; ++ struct list_head free_objs; ++ int n_free_objects; ++ ++ struct yaffs_obj_list *allocated_obj_list; ++}; ++ ++static void yaffs_deinit_raw_tnodes(struct yaffs_dev *dev) ++{ ++ struct yaffs_allocator *allocator = ++ (struct yaffs_allocator *)dev->allocator; ++ struct yaffs_tnode_list *tmp; ++ ++ if (!allocator) { ++ BUG(); ++ return; ++ } ++ ++ while (allocator->alloc_tnode_list) { ++ tmp = allocator->alloc_tnode_list->next; ++ ++ kfree(allocator->alloc_tnode_list->tnodes); ++ kfree(allocator->alloc_tnode_list); ++ allocator->alloc_tnode_list = tmp; ++ } ++ ++ allocator->free_tnodes = NULL; ++ allocator->n_free_tnodes = 0; ++ allocator->n_tnodes_created = 0; ++} ++ ++static void yaffs_init_raw_tnodes(struct yaffs_dev *dev) ++{ ++ struct yaffs_allocator *allocator = dev->allocator; ++ ++ if (!allocator) { ++ BUG(); ++ return; ++ } ++ ++ allocator->alloc_tnode_list = NULL; ++ allocator->free_tnodes = NULL; ++ allocator->n_free_tnodes = 0; ++ allocator->n_tnodes_created = 0; ++} ++ ++static int yaffs_create_tnodes(struct yaffs_dev *dev, int n_tnodes) ++{ ++ struct yaffs_allocator *allocator = ++ (struct yaffs_allocator *)dev->allocator; ++ int i; ++ struct yaffs_tnode *new_tnodes; ++ u8 *mem; ++ struct yaffs_tnode *curr; ++ struct yaffs_tnode *next; ++ struct yaffs_tnode_list *tnl; ++ ++ if (!allocator) { ++ BUG(); ++ return YAFFS_FAIL; ++ } ++ ++ if (n_tnodes < 1) ++ return YAFFS_OK; ++ ++ /* make these things */ ++ new_tnodes = kmalloc(n_tnodes * dev->tnode_size, GFP_NOFS); ++ mem = (u8 *) new_tnodes; ++ ++ if (!new_tnodes) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs: Could not allocate Tnodes"); ++ return YAFFS_FAIL; ++ } ++ ++ /* New hookup for wide tnodes */ ++ for (i = 0; i < n_tnodes - 1; i++) { ++ curr = (struct yaffs_tnode *)&mem[i * dev->tnode_size]; ++ next = (struct yaffs_tnode *)&mem[(i + 1) * dev->tnode_size]; ++ curr->internal[0] = next; ++ } ++ ++ curr = (struct yaffs_tnode *)&mem[(n_tnodes - 1) * dev->tnode_size]; ++ curr->internal[0] = allocator->free_tnodes; ++ allocator->free_tnodes = (struct yaffs_tnode *)mem; ++ ++ allocator->n_free_tnodes += n_tnodes; ++ allocator->n_tnodes_created += n_tnodes; ++ ++ /* Now add this bunch of tnodes to a list for freeing up. ++ * NB If we can't add this to the management list it isn't fatal ++ * but it just means we can't free this bunch of tnodes later. ++ */ ++ tnl = kmalloc(sizeof(struct yaffs_tnode_list), GFP_NOFS); ++ if (!tnl) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "Could not add tnodes to management list"); ++ return YAFFS_FAIL; ++ } else { ++ tnl->tnodes = new_tnodes; ++ tnl->next = allocator->alloc_tnode_list; ++ allocator->alloc_tnode_list = tnl; ++ } ++ ++ yaffs_trace(YAFFS_TRACE_ALLOCATE, "Tnodes added"); ++ ++ return YAFFS_OK; ++} ++ ++struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev) ++{ ++ struct yaffs_allocator *allocator = ++ (struct yaffs_allocator *)dev->allocator; ++ struct yaffs_tnode *tn = NULL; ++ ++ if (!allocator) { ++ BUG(); ++ return NULL; ++ } ++ ++ /* If there are none left make more */ ++ if (!allocator->free_tnodes) ++ yaffs_create_tnodes(dev, YAFFS_ALLOCATION_NTNODES); ++ ++ if (allocator->free_tnodes) { ++ tn = allocator->free_tnodes; ++ allocator->free_tnodes = allocator->free_tnodes->internal[0]; ++ allocator->n_free_tnodes--; ++ } ++ ++ return tn; ++} ++ ++/* FreeTnode frees up a tnode and puts it back on the free list */ ++void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn) ++{ ++ struct yaffs_allocator *allocator = dev->allocator; ++ ++ if (!allocator) { ++ BUG(); ++ return; ++ } ++ ++ if (tn) { ++ tn->internal[0] = allocator->free_tnodes; ++ allocator->free_tnodes = tn; ++ allocator->n_free_tnodes++; ++ } ++ dev->checkpoint_blocks_required = 0; /* force recalculation */ ++} ++ ++/*--------------- yaffs_obj alloaction ------------------------ ++ * ++ * Free yaffs_objs are stored in a list using obj->siblings. ++ * The blocks of allocated objects are stored in a linked list. ++ */ ++ ++static void yaffs_init_raw_objs(struct yaffs_dev *dev) ++{ ++ struct yaffs_allocator *allocator = dev->allocator; ++ ++ if (!allocator) { ++ BUG(); ++ return; ++ } ++ ++ allocator->allocated_obj_list = NULL; ++ INIT_LIST_HEAD(&allocator->free_objs); ++ allocator->n_free_objects = 0; ++} ++ ++static void yaffs_deinit_raw_objs(struct yaffs_dev *dev) ++{ ++ struct yaffs_allocator *allocator = dev->allocator; ++ struct yaffs_obj_list *tmp; ++ ++ if (!allocator) { ++ BUG(); ++ return; ++ } ++ ++ while (allocator->allocated_obj_list) { ++ tmp = allocator->allocated_obj_list->next; ++ kfree(allocator->allocated_obj_list->objects); ++ kfree(allocator->allocated_obj_list); ++ allocator->allocated_obj_list = tmp; ++ } ++ ++ INIT_LIST_HEAD(&allocator->free_objs); ++ allocator->n_free_objects = 0; ++ allocator->n_obj_created = 0; ++} ++ ++static int yaffs_create_free_objs(struct yaffs_dev *dev, int n_obj) ++{ ++ struct yaffs_allocator *allocator = dev->allocator; ++ int i; ++ struct yaffs_obj *new_objs; ++ struct yaffs_obj_list *list; ++ ++ if (!allocator) { ++ BUG(); ++ return YAFFS_FAIL; ++ } ++ ++ if (n_obj < 1) ++ return YAFFS_OK; ++ ++ /* make these things */ ++ new_objs = kmalloc(n_obj * sizeof(struct yaffs_obj), GFP_NOFS); ++ list = kmalloc(sizeof(struct yaffs_obj_list), GFP_NOFS); ++ ++ if (!new_objs || !list) { ++ kfree(new_objs); ++ new_objs = NULL; ++ kfree(list); ++ list = NULL; ++ yaffs_trace(YAFFS_TRACE_ALLOCATE, ++ "Could not allocate more objects"); ++ return YAFFS_FAIL; ++ } ++ ++ /* Hook them into the free list */ ++ for (i = 0; i < n_obj; i++) ++ list_add(&new_objs[i].siblings, &allocator->free_objs); ++ ++ allocator->n_free_objects += n_obj; ++ allocator->n_obj_created += n_obj; ++ ++ /* Now add this bunch of Objects to a list for freeing up. */ ++ ++ list->objects = new_objs; ++ list->next = allocator->allocated_obj_list; ++ allocator->allocated_obj_list = list; ++ ++ return YAFFS_OK; ++} ++ ++struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev) ++{ ++ struct yaffs_obj *obj = NULL; ++ struct list_head *lh; ++ struct yaffs_allocator *allocator = dev->allocator; ++ ++ if (!allocator) { ++ BUG(); ++ return obj; ++ } ++ ++ /* If there are none left make more */ ++ if (list_empty(&allocator->free_objs)) ++ yaffs_create_free_objs(dev, YAFFS_ALLOCATION_NOBJECTS); ++ ++ if (!list_empty(&allocator->free_objs)) { ++ lh = allocator->free_objs.next; ++ obj = list_entry(lh, struct yaffs_obj, siblings); ++ list_del_init(lh); ++ allocator->n_free_objects--; ++ } ++ ++ return obj; ++} ++ ++void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj) ++{ ++ ++ struct yaffs_allocator *allocator = dev->allocator; ++ ++ if (!allocator) { ++ BUG(); ++ return; ++ } ++ ++ /* Link into the free list. */ ++ list_add(&obj->siblings, &allocator->free_objs); ++ allocator->n_free_objects++; ++} ++ ++void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev) ++{ ++ ++ if (!dev->allocator) { ++ BUG(); ++ return; ++ } ++ ++ yaffs_deinit_raw_tnodes(dev); ++ yaffs_deinit_raw_objs(dev); ++ kfree(dev->allocator); ++ dev->allocator = NULL; ++} ++ ++void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev) ++{ ++ struct yaffs_allocator *allocator; ++ ++ if (dev->allocator) { ++ BUG(); ++ return; ++ } ++ ++ allocator = kmalloc(sizeof(struct yaffs_allocator), GFP_NOFS); ++ if (allocator) { ++ dev->allocator = allocator; ++ yaffs_init_raw_tnodes(dev); ++ yaffs_init_raw_objs(dev); ++ } ++} ++ +diff --git a/fs/yaffs2/yaffs_allocator.h b/fs/yaffs2/yaffs_allocator.h +new file mode 100644 +index 0000000..a8cc322 +--- /dev/null ++++ b/fs/yaffs2/yaffs_allocator.h +@@ -0,0 +1,30 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_ALLOCATOR_H__ ++#define __YAFFS_ALLOCATOR_H__ ++ ++#include "yaffs_guts.h" ++ ++void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev); ++void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev); ++ ++struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev); ++void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn); ++ ++struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev); ++void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_attribs.c b/fs/yaffs2/yaffs_attribs.c +new file mode 100644 +index 0000000..5eb7c5a +--- /dev/null ++++ b/fs/yaffs2/yaffs_attribs.c +@@ -0,0 +1,136 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * 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 "yaffs_guts.h" ++#include "yaffs_attribs.h" ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) ++#define IATTR_UID ia_uid ++#define IATTR_GID ia_gid ++#else ++#define IATTR_UID ia_uid.val ++#define IATTR_GID ia_gid.val ++#endif ++ ++/* ++ * Loading attibs from/to object header assumes the object header ++ * is in cpu endian. ++ */ ++void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh) ++{ ++ obj->yst_uid = oh->yst_uid; ++ obj->yst_gid = oh->yst_gid; ++ obj->yst_atime = oh->yst_atime; ++ obj->yst_mtime = oh->yst_mtime; ++ obj->yst_ctime = oh->yst_ctime; ++ obj->yst_rdev = oh->yst_rdev; ++} ++ ++void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj) ++{ ++ oh->yst_uid = obj->yst_uid; ++ oh->yst_gid = obj->yst_gid; ++ oh->yst_atime = obj->yst_atime; ++ oh->yst_mtime = obj->yst_mtime; ++ oh->yst_ctime = obj->yst_ctime; ++ oh->yst_rdev = obj->yst_rdev; ++ ++} ++ ++void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c) ++{ ++ obj->yst_mtime = Y_CURRENT_TIME; ++ if (do_a) ++ obj->yst_atime = obj->yst_mtime; ++ if (do_c) ++ obj->yst_ctime = obj->yst_mtime; ++} ++ ++void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev) ++{ ++ yaffs_load_current_time(obj, 1, 1); ++ obj->yst_rdev = rdev; ++ obj->yst_uid = uid; ++ obj->yst_gid = gid; ++} ++ ++static loff_t yaffs_get_file_size(struct yaffs_obj *obj) ++{ ++ YCHAR *alias = NULL; ++ obj = yaffs_get_equivalent_obj(obj); ++ ++ switch (obj->variant_type) { ++ case YAFFS_OBJECT_TYPE_FILE: ++ return obj->variant.file_variant.file_size; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ alias = obj->variant.symlink_variant.alias; ++ if (!alias) ++ return 0; ++ return strnlen(alias, YAFFS_MAX_ALIAS_LENGTH); ++ default: ++ return 0; ++ } ++} ++ ++int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr) ++{ ++ unsigned int valid = attr->ia_valid; ++ ++ if (valid & ATTR_MODE) ++ obj->yst_mode = attr->ia_mode; ++ if (valid & ATTR_UID) ++ obj->yst_uid = attr->IATTR_UID; ++ if (valid & ATTR_GID) ++ obj->yst_gid = attr->IATTR_GID; ++ ++ if (valid & ATTR_ATIME) ++ obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime); ++ if (valid & ATTR_CTIME) ++ obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime); ++ if (valid & ATTR_MTIME) ++ obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime); ++ ++ if (valid & ATTR_SIZE) ++ yaffs_resize_file(obj, attr->ia_size); ++ ++ yaffs_update_oh(obj, NULL, 1, 0, 0, NULL); ++ ++ return YAFFS_OK; ++ ++} ++ ++int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr) ++{ ++ unsigned int valid = 0; ++ ++ attr->ia_mode = obj->yst_mode; ++ valid |= ATTR_MODE; ++ attr->IATTR_UID = obj->yst_uid; ++ valid |= ATTR_UID; ++ attr->IATTR_GID = obj->yst_gid; ++ valid |= ATTR_GID; ++ ++ Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime; ++ valid |= ATTR_ATIME; ++ Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime; ++ valid |= ATTR_CTIME; ++ Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime; ++ valid |= ATTR_MTIME; ++ ++ attr->ia_size = yaffs_get_file_size(obj); ++ valid |= ATTR_SIZE; ++ ++ attr->ia_valid = valid; ++ ++ return YAFFS_OK; ++} +diff --git a/fs/yaffs2/yaffs_attribs.h b/fs/yaffs2/yaffs_attribs.h +new file mode 100644 +index 0000000..5b21b08 +--- /dev/null ++++ b/fs/yaffs2/yaffs_attribs.h +@@ -0,0 +1,28 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_ATTRIBS_H__ ++#define __YAFFS_ATTRIBS_H__ ++ ++#include "yaffs_guts.h" ++ ++void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh); ++void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj); ++void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev); ++void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c); ++int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr); ++int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_bitmap.c b/fs/yaffs2/yaffs_bitmap.c +new file mode 100644 +index 0000000..bf8cbb3 +--- /dev/null ++++ b/fs/yaffs2/yaffs_bitmap.c +@@ -0,0 +1,99 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * 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 "yaffs_bitmap.h" ++#include "yaffs_trace.h" ++/* ++ * Chunk bitmap manipulations ++ */ ++ ++static inline u8 *yaffs_block_bits(struct yaffs_dev *dev, int blk) ++{ ++ if (blk < (int)dev->internal_start_block || ++ blk > (int)dev->internal_end_block) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "BlockBits block %d is not valid", ++ blk); ++ BUG(); ++ } ++ return dev->chunk_bits + ++ (dev->chunk_bit_stride * (blk - dev->internal_start_block)); ++} ++ ++void yaffs_verify_chunk_bit_id(struct yaffs_dev *dev, int blk, int chunk) ++{ ++ if (blk < (int)dev->internal_start_block || ++ blk > (int)dev->internal_end_block || ++ chunk < 0 || chunk >= (int)dev->param.chunks_per_block) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "Chunk Id (%d:%d) invalid", ++ blk, chunk); ++ BUG(); ++ } ++} ++ ++void yaffs_clear_chunk_bits(struct yaffs_dev *dev, int blk) ++{ ++ u8 *blk_bits = yaffs_block_bits(dev, blk); ++ ++ memset(blk_bits, 0, dev->chunk_bit_stride); ++} ++ ++void yaffs_clear_chunk_bit(struct yaffs_dev *dev, int blk, int chunk) ++{ ++ u8 *blk_bits = yaffs_block_bits(dev, blk); ++ ++ yaffs_verify_chunk_bit_id(dev, blk, chunk); ++ blk_bits[chunk / 8] &= ~(1 << (chunk & 7)); ++} ++ ++void yaffs_set_chunk_bit(struct yaffs_dev *dev, int blk, int chunk) ++{ ++ u8 *blk_bits = yaffs_block_bits(dev, blk); ++ ++ yaffs_verify_chunk_bit_id(dev, blk, chunk); ++ blk_bits[chunk / 8] |= (1 << (chunk & 7)); ++} ++ ++int yaffs_check_chunk_bit(struct yaffs_dev *dev, int blk, int chunk) ++{ ++ u8 *blk_bits = yaffs_block_bits(dev, blk); ++ ++ yaffs_verify_chunk_bit_id(dev, blk, chunk); ++ return (blk_bits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0; ++} ++ ++int yaffs_still_some_chunks(struct yaffs_dev *dev, int blk) ++{ ++ u8 *blk_bits = yaffs_block_bits(dev, blk); ++ int i; ++ ++ for (i = 0; i < dev->chunk_bit_stride; i++) { ++ if (*blk_bits) ++ return 1; ++ blk_bits++; ++ } ++ return 0; ++} ++ ++int yaffs_count_chunk_bits(struct yaffs_dev *dev, int blk) ++{ ++ u8 *blk_bits = yaffs_block_bits(dev, blk); ++ int i; ++ int n = 0; ++ ++ for (i = 0; i < dev->chunk_bit_stride; i++, blk_bits++) ++ n += hweight8(*blk_bits); ++ ++ return n; ++} +diff --git a/fs/yaffs2/yaffs_bitmap.h b/fs/yaffs2/yaffs_bitmap.h +new file mode 100644 +index 0000000..e26b37d +--- /dev/null ++++ b/fs/yaffs2/yaffs_bitmap.h +@@ -0,0 +1,33 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++/* ++ * Chunk bitmap manipulations ++ */ ++ ++#ifndef __YAFFS_BITMAP_H__ ++#define __YAFFS_BITMAP_H__ ++ ++#include "yaffs_guts.h" ++ ++void yaffs_verify_chunk_bit_id(struct yaffs_dev *dev, int blk, int chunk); ++void yaffs_clear_chunk_bits(struct yaffs_dev *dev, int blk); ++void yaffs_clear_chunk_bit(struct yaffs_dev *dev, int blk, int chunk); ++void yaffs_set_chunk_bit(struct yaffs_dev *dev, int blk, int chunk); ++int yaffs_check_chunk_bit(struct yaffs_dev *dev, int blk, int chunk); ++int yaffs_still_some_chunks(struct yaffs_dev *dev, int blk); ++int yaffs_count_chunk_bits(struct yaffs_dev *dev, int blk); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_checkptrw.c b/fs/yaffs2/yaffs_checkptrw.c +new file mode 100644 +index 0000000..c7cbda3 +--- /dev/null ++++ b/fs/yaffs2/yaffs_checkptrw.c +@@ -0,0 +1,481 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * 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 "yaffs_checkptrw.h" ++#include "yaffs_getblockinfo.h" ++#include "yaffs_endian.h" ++ ++struct yaffs_checkpt_chunk_hdr { ++ int version; ++ int seq; ++ u32 sum; ++ u32 xor; ++} ; ++ ++ ++static int apply_chunk_offset(struct yaffs_dev *dev, int chunk) ++{ ++ return chunk - dev->chunk_offset; ++} ++ ++static int apply_block_offset(struct yaffs_dev *dev, int block) ++{ ++ return block - dev->block_offset; ++} ++ ++ ++static void yaffs2_do_endian_hdr(struct yaffs_dev *dev, ++ struct yaffs_checkpt_chunk_hdr *hdr) ++{ ++ if (!dev->swap_endian) ++ return; ++ hdr->version = swap_s32(hdr->version); ++ hdr->seq = swap_s32(hdr->seq); ++ hdr->sum = swap_u32(hdr->sum); ++ hdr->xor = swap_u32(hdr->xor); ++} ++ ++static void yaffs2_checkpt_init_chunk_hdr(struct yaffs_dev *dev) ++{ ++ struct yaffs_checkpt_chunk_hdr hdr; ++ ++ hdr.version = YAFFS_CHECKPOINT_VERSION; ++ hdr.seq = dev->checkpt_page_seq; ++ hdr.sum = dev->checkpt_sum; ++ hdr.xor = dev->checkpt_xor; ++ ++ dev->checkpt_byte_offs = sizeof(hdr); ++ ++ yaffs2_do_endian_hdr(dev, &hdr); ++ memcpy(dev->checkpt_buffer, &hdr, sizeof(hdr)); ++} ++ ++static int yaffs2_checkpt_check_chunk_hdr(struct yaffs_dev *dev) ++{ ++ struct yaffs_checkpt_chunk_hdr hdr; ++ ++ memcpy(&hdr, dev->checkpt_buffer, sizeof(hdr)); ++ yaffs2_do_endian_hdr(dev, &hdr); ++ ++ dev->checkpt_byte_offs = sizeof(hdr); ++ ++ return hdr.version == YAFFS_CHECKPOINT_VERSION && ++ hdr.seq == dev->checkpt_page_seq && ++ hdr.sum == dev->checkpt_sum && ++ hdr.xor == dev->checkpt_xor; ++} ++ ++static int yaffs2_checkpt_space_ok(struct yaffs_dev *dev) ++{ ++ int blocks_avail = dev->n_erased_blocks - dev->param.n_reserved_blocks; ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "checkpt blocks_avail = %d", blocks_avail); ++ ++ return (blocks_avail <= 0) ? 0 : 1; ++} ++ ++static int yaffs_checkpt_erase(struct yaffs_dev *dev) ++{ ++ u32 i; ++ ++ if (!dev->drv.drv_erase_fn) ++ return 0; ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "checking blocks %d to %d", ++ dev->internal_start_block, dev->internal_end_block); ++ ++ for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) { ++ struct yaffs_block_info *bi = yaffs_get_block_info(dev, i); ++ int offset_i = apply_block_offset(dev, i); ++ int result; ++ ++ if (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "erasing checkpt block %d", i); ++ ++ dev->n_erasures++; ++ ++ result = dev->drv.drv_erase_fn(dev, offset_i); ++ if(result) { ++ bi->block_state = YAFFS_BLOCK_STATE_EMPTY; ++ dev->n_erased_blocks++; ++ dev->n_free_chunks += ++ dev->param.chunks_per_block; ++ } else { ++ dev->drv.drv_mark_bad_fn(dev, offset_i); ++ bi->block_state = YAFFS_BLOCK_STATE_DEAD; ++ } ++ } ++ } ++ ++ dev->blocks_in_checkpt = 0; ++ ++ return 1; ++} ++ ++static void yaffs2_checkpt_find_erased_block(struct yaffs_dev *dev) ++{ ++ u32 i; ++ int blocks_avail = dev->n_erased_blocks - dev->param.n_reserved_blocks; ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "allocating checkpt block: erased %d reserved %d avail %d next %d ", ++ dev->n_erased_blocks, dev->param.n_reserved_blocks, ++ blocks_avail, dev->checkpt_next_block); ++ ++ if (dev->checkpt_next_block >= 0 && ++ dev->checkpt_next_block <= (int)dev->internal_end_block && ++ blocks_avail > 0) { ++ ++ for (i = dev->checkpt_next_block; i <= dev->internal_end_block; ++ i++) { ++ struct yaffs_block_info *bi; ++ ++ bi = yaffs_get_block_info(dev, i); ++ if (bi->block_state == YAFFS_BLOCK_STATE_EMPTY) { ++ dev->checkpt_next_block = i + 1; ++ dev->checkpt_cur_block = i; ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "allocating checkpt block %d", i); ++ return; ++ } ++ } ++ } ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, "out of checkpt blocks"); ++ ++ dev->checkpt_next_block = -1; ++ dev->checkpt_cur_block = -1; ++} ++ ++static void yaffs2_checkpt_find_block(struct yaffs_dev *dev) ++{ ++ u32 i; ++ struct yaffs_ext_tags tags; ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "find next checkpt block: start: blocks %d next %d", ++ dev->blocks_in_checkpt, dev->checkpt_next_block); ++ ++ if (dev->blocks_in_checkpt < dev->checkpt_max_blocks) ++ for (i = dev->checkpt_next_block; i <= dev->internal_end_block; ++ i++) { ++ int chunk = i * dev->param.chunks_per_block; ++ enum yaffs_block_state state; ++ u32 seq; ++ ++ dev->tagger.read_chunk_tags_fn(dev, ++ apply_chunk_offset(dev, chunk), ++ NULL, &tags); ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "find next checkpt block: search: block %d state %d oid %d seq %d eccr %d", ++ i, (int) state, ++ tags.obj_id, tags.seq_number, ++ tags.ecc_result); ++ ++ if (tags.seq_number != YAFFS_SEQUENCE_CHECKPOINT_DATA) ++ continue; ++ ++ dev->tagger.query_block_fn(dev, ++ apply_block_offset(dev, i), ++ &state, &seq); ++ if (state == YAFFS_BLOCK_STATE_DEAD) ++ continue; ++ ++ /* Right kind of block */ ++ dev->checkpt_next_block = tags.obj_id; ++ dev->checkpt_cur_block = i; ++ dev->checkpt_block_list[dev->blocks_in_checkpt] = i; ++ dev->blocks_in_checkpt++; ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "found checkpt block %d", i); ++ return; ++ } ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, "found no more checkpt blocks"); ++ ++ dev->checkpt_next_block = -1; ++ dev->checkpt_cur_block = -1; ++} ++ ++int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing) ++{ ++ u32 i; ++ ++ dev->checkpt_open_write = writing; ++ ++ /* Got the functions we need? */ ++ if (!dev->tagger.write_chunk_tags_fn || ++ !dev->tagger.read_chunk_tags_fn || ++ !dev->drv.drv_erase_fn || ++ !dev->drv.drv_mark_bad_fn) ++ return 0; ++ ++ if (writing && !yaffs2_checkpt_space_ok(dev)) ++ return 0; ++ ++ if (!dev->checkpt_buffer) ++ dev->checkpt_buffer = ++ kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS); ++ if (!dev->checkpt_buffer) ++ return 0; ++ ++ dev->checkpt_page_seq = 0; ++ dev->checkpt_byte_count = 0; ++ dev->checkpt_sum = 0; ++ dev->checkpt_xor = 0; ++ dev->checkpt_cur_block = -1; ++ dev->checkpt_cur_chunk = -1; ++ dev->checkpt_next_block = dev->internal_start_block; ++ ++ if (writing) { ++ memset(dev->checkpt_buffer, 0, dev->data_bytes_per_chunk); ++ yaffs2_checkpt_init_chunk_hdr(dev); ++ return yaffs_checkpt_erase(dev); ++ } ++ ++ /* Opening for a read */ ++ /* Set to a value that will kick off a read */ ++ dev->checkpt_byte_offs = dev->data_bytes_per_chunk; ++ /* A checkpoint block list of 1 checkpoint block per 16 block is ++ * (hopefully) going to be way more than we need */ ++ dev->blocks_in_checkpt = 0; ++ dev->checkpt_max_blocks = ++ (dev->internal_end_block - dev->internal_start_block) / 16 + 2; ++ if (!dev->checkpt_block_list) ++ dev->checkpt_block_list = ++ kmalloc(sizeof(int) * dev->checkpt_max_blocks, GFP_NOFS); ++ ++ if (!dev->checkpt_block_list) ++ return 0; ++ ++ for (i = 0; i < dev->checkpt_max_blocks; i++) ++ dev->checkpt_block_list[i] = -1; ++ ++ return 1; ++} ++ ++int yaffs2_get_checkpt_sum(struct yaffs_dev *dev, u32 * sum) ++{ ++ u32 composite_sum; ++ ++ composite_sum = (dev->checkpt_sum << 8) | (dev->checkpt_xor & 0xff); ++ *sum = composite_sum; ++ return 1; ++} ++ ++static int yaffs2_checkpt_flush_buffer(struct yaffs_dev *dev) ++{ ++ int chunk; ++ int offset_chunk; ++ struct yaffs_ext_tags tags; ++ ++ if (dev->checkpt_cur_block < 0) { ++ yaffs2_checkpt_find_erased_block(dev); ++ dev->checkpt_cur_chunk = 0; ++ } ++ ++ if (dev->checkpt_cur_block < 0) ++ return 0; ++ ++ tags.is_deleted = 0; ++ tags.obj_id = dev->checkpt_next_block; /* Hint to next place to look */ ++ tags.chunk_id = dev->checkpt_page_seq + 1; ++ tags.seq_number = YAFFS_SEQUENCE_CHECKPOINT_DATA; ++ tags.n_bytes = dev->data_bytes_per_chunk; ++ if (dev->checkpt_cur_chunk == 0) { ++ /* First chunk we write for the block? Set block state to ++ checkpoint */ ++ struct yaffs_block_info *bi = ++ yaffs_get_block_info(dev, dev->checkpt_cur_block); ++ bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT; ++ dev->blocks_in_checkpt++; ++ } ++ ++ chunk = ++ dev->checkpt_cur_block * dev->param.chunks_per_block + ++ dev->checkpt_cur_chunk; ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "checkpoint wite buffer nand %d(%d:%d) objid %d chId %d", ++ chunk, dev->checkpt_cur_block, dev->checkpt_cur_chunk, ++ tags.obj_id, tags.chunk_id); ++ ++ offset_chunk = apply_chunk_offset(dev, chunk); ++ ++ dev->n_page_writes++; ++ ++ dev->tagger.write_chunk_tags_fn(dev, offset_chunk, ++ dev->checkpt_buffer, &tags); ++ dev->checkpt_page_seq++; ++ dev->checkpt_cur_chunk++; ++ if (dev->checkpt_cur_chunk >= (int)dev->param.chunks_per_block) { ++ dev->checkpt_cur_chunk = 0; ++ dev->checkpt_cur_block = -1; ++ } ++ memset(dev->checkpt_buffer, 0, dev->data_bytes_per_chunk); ++ ++ yaffs2_checkpt_init_chunk_hdr(dev); ++ ++ ++ return 1; ++} ++ ++int yaffs2_checkpt_wr(struct yaffs_dev *dev, const void *data, int n_bytes) ++{ ++ int i = 0; ++ int ok = 1; ++ u8 *data_bytes = (u8 *) data; ++ ++ if (!dev->checkpt_buffer) ++ return 0; ++ ++ if (!dev->checkpt_open_write) ++ return -1; ++ ++ while (i < n_bytes && ok) { ++ dev->checkpt_buffer[dev->checkpt_byte_offs] = *data_bytes; ++ dev->checkpt_sum += *data_bytes; ++ dev->checkpt_xor ^= *data_bytes; ++ ++ dev->checkpt_byte_offs++; ++ i++; ++ data_bytes++; ++ dev->checkpt_byte_count++; ++ ++ if (dev->checkpt_byte_offs < 0 || ++ dev->checkpt_byte_offs >= (int)dev->data_bytes_per_chunk) ++ ok = yaffs2_checkpt_flush_buffer(dev); ++ } ++ ++ return i; ++} ++ ++int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes) ++{ ++ int i = 0; ++ struct yaffs_ext_tags tags; ++ int chunk; ++ int offset_chunk; ++ u8 *data_bytes = (u8 *) data; ++ ++ if (!dev->checkpt_buffer) ++ return 0; ++ ++ if (dev->checkpt_open_write) ++ return -1; ++ ++ while (i < n_bytes) { ++ ++ if (dev->checkpt_byte_offs < 0 || ++ dev->checkpt_byte_offs >= (int)dev->data_bytes_per_chunk) { ++ ++ if (dev->checkpt_cur_block < 0) { ++ yaffs2_checkpt_find_block(dev); ++ dev->checkpt_cur_chunk = 0; ++ } ++ ++ /* Bail out if we can't find a checpoint block */ ++ if (dev->checkpt_cur_block < 0) ++ break; ++ ++ chunk = dev->checkpt_cur_block * ++ dev->param.chunks_per_block + ++ dev->checkpt_cur_chunk; ++ ++ offset_chunk = apply_chunk_offset(dev, chunk); ++ dev->n_page_reads++; ++ ++ /* Read in the next chunk */ ++ dev->tagger.read_chunk_tags_fn(dev, ++ offset_chunk, ++ dev->checkpt_buffer, ++ &tags); ++ ++ /* Bail out if the chunk is corrupted. */ ++ if (tags.chunk_id != (u32)(dev->checkpt_page_seq + 1) || ++ tags.ecc_result > YAFFS_ECC_RESULT_FIXED || ++ tags.seq_number != YAFFS_SEQUENCE_CHECKPOINT_DATA) ++ break; ++ ++ /* Bail out if it is not a checkpoint chunk. */ ++ if(!yaffs2_checkpt_check_chunk_hdr(dev)) ++ break; ++ ++ dev->checkpt_page_seq++; ++ dev->checkpt_cur_chunk++; ++ ++ if (dev->checkpt_cur_chunk >= ++ (int)dev->param.chunks_per_block) ++ dev->checkpt_cur_block = -1; ++ ++ } ++ ++ *data_bytes = dev->checkpt_buffer[dev->checkpt_byte_offs]; ++ dev->checkpt_sum += *data_bytes; ++ dev->checkpt_xor ^= *data_bytes; ++ dev->checkpt_byte_offs++; ++ i++; ++ data_bytes++; ++ dev->checkpt_byte_count++; ++ } ++ ++ return i; /* Number of bytes read */ ++} ++ ++int yaffs_checkpt_close(struct yaffs_dev *dev) ++{ ++ u32 i; ++ ++ if (dev->checkpt_open_write) { ++ if (dev->checkpt_byte_offs != ++ sizeof(sizeof(struct yaffs_checkpt_chunk_hdr))) ++ yaffs2_checkpt_flush_buffer(dev); ++ } else if (dev->checkpt_block_list) { ++ for (i = 0; ++ i < dev->blocks_in_checkpt && ++ dev->checkpt_block_list[i] >= 0; i++) { ++ int blk = dev->checkpt_block_list[i]; ++ struct yaffs_block_info *bi = NULL; ++ ++ if ((int)dev->internal_start_block <= blk && ++ blk <= (int)dev->internal_end_block) ++ bi = yaffs_get_block_info(dev, blk); ++ if (bi && bi->block_state == YAFFS_BLOCK_STATE_EMPTY) ++ bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT; ++ } ++ } ++ ++ dev->n_free_chunks -= ++ dev->blocks_in_checkpt * dev->param.chunks_per_block; ++ dev->n_erased_blocks -= dev->blocks_in_checkpt; ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, "checkpoint byte count %d", ++ dev->checkpt_byte_count); ++ ++ if (dev->checkpt_buffer) ++ return 1; ++ else ++ return 0; ++} ++ ++int yaffs2_checkpt_invalidate_stream(struct yaffs_dev *dev) ++{ ++ /* Erase the checkpoint data */ ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "checkpoint invalidate of %d blocks", ++ dev->blocks_in_checkpt); ++ ++ return yaffs_checkpt_erase(dev); ++} +diff --git a/fs/yaffs2/yaffs_checkptrw.h b/fs/yaffs2/yaffs_checkptrw.h +new file mode 100644 +index 0000000..cdbaba7 +--- /dev/null ++++ b/fs/yaffs2/yaffs_checkptrw.h +@@ -0,0 +1,33 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_CHECKPTRW_H__ ++#define __YAFFS_CHECKPTRW_H__ ++ ++#include "yaffs_guts.h" ++ ++int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing); ++ ++int yaffs2_checkpt_wr(struct yaffs_dev *dev, const void *data, int n_bytes); ++ ++int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes); ++ ++int yaffs2_get_checkpt_sum(struct yaffs_dev *dev, u32 * sum); ++ ++int yaffs_checkpt_close(struct yaffs_dev *dev); ++ ++int yaffs2_checkpt_invalidate_stream(struct yaffs_dev *dev); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_ecc.c b/fs/yaffs2/yaffs_ecc.c +new file mode 100644 +index 0000000..9294107 +--- /dev/null ++++ b/fs/yaffs2/yaffs_ecc.c +@@ -0,0 +1,281 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * 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 code implements the ECC algorithm used in SmartMedia. ++ * ++ * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes. ++ * The two unused bit are set to 1. ++ * The ECC can correct single bit errors in a 256-byte page of data. Thus, two ++ * such ECC blocks are used on a 512-byte NAND page. ++ * ++ */ ++ ++#include "yportenv.h" ++ ++#include "yaffs_ecc.h" ++ ++/* Table generated by gen-ecc.c ++ * Using a table means we do not have to calculate p1..p4 and p1'..p4' ++ * for each byte of data. These are instead provided in a table in bits7..2. ++ * Bit 0 of each entry indicates whether the entry has an odd or even parity, ++ * and therefore this bytes influence on the line parity. ++ */ ++ ++static const unsigned char column_parity_table[] = { ++ 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, ++ 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00, ++ 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, ++ 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95, ++ 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, ++ 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99, ++ 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, ++ 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c, ++ 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, ++ 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5, ++ 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, ++ 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30, ++ 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, ++ 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c, ++ 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, ++ 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9, ++ 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, ++ 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9, ++ 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, ++ 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c, ++ 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, ++ 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30, ++ 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, ++ 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5, ++ 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, ++ 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c, ++ 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, ++ 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99, ++ 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, ++ 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95, ++ 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, ++ 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00, ++}; ++ ++ ++/* Calculate the ECC for a 256-byte block of data */ ++void yaffs_ecc_calc(const unsigned char *data, unsigned char *ecc) ++{ ++ unsigned int i; ++ unsigned char col_parity = 0; ++ unsigned char line_parity = 0; ++ unsigned char line_parity_prime = 0; ++ unsigned char t; ++ unsigned char b; ++ ++ for (i = 0; i < 256; i++) { ++ b = column_parity_table[*data++]; ++ col_parity ^= b; ++ ++ if (b & 0x01) { /* odd number of bits in the byte */ ++ line_parity ^= i; ++ line_parity_prime ^= ~i; ++ } ++ } ++ ++ ecc[2] = (~col_parity) | 0x03; ++ ++ t = 0; ++ if (line_parity & 0x80) ++ t |= 0x80; ++ if (line_parity_prime & 0x80) ++ t |= 0x40; ++ if (line_parity & 0x40) ++ t |= 0x20; ++ if (line_parity_prime & 0x40) ++ t |= 0x10; ++ if (line_parity & 0x20) ++ t |= 0x08; ++ if (line_parity_prime & 0x20) ++ t |= 0x04; ++ if (line_parity & 0x10) ++ t |= 0x02; ++ if (line_parity_prime & 0x10) ++ t |= 0x01; ++ ecc[1] = ~t; ++ ++ t = 0; ++ if (line_parity & 0x08) ++ t |= 0x80; ++ if (line_parity_prime & 0x08) ++ t |= 0x40; ++ if (line_parity & 0x04) ++ t |= 0x20; ++ if (line_parity_prime & 0x04) ++ t |= 0x10; ++ if (line_parity & 0x02) ++ t |= 0x08; ++ if (line_parity_prime & 0x02) ++ t |= 0x04; ++ if (line_parity & 0x01) ++ t |= 0x02; ++ if (line_parity_prime & 0x01) ++ t |= 0x01; ++ ecc[0] = ~t; ++ ++} ++ ++/* Correct the ECC on a 256 byte block of data */ ++ ++int yaffs_ecc_correct(unsigned char *data, unsigned char *read_ecc, ++ const unsigned char *test_ecc) ++{ ++ unsigned char d0, d1, d2; /* deltas */ ++ ++ d0 = read_ecc[0] ^ test_ecc[0]; ++ d1 = read_ecc[1] ^ test_ecc[1]; ++ d2 = read_ecc[2] ^ test_ecc[2]; ++ ++ if ((d0 | d1 | d2) == 0) ++ return 0; /* no error */ ++ ++ if (((d0 ^ (d0 >> 1)) & 0x55) == 0x55 && ++ ((d1 ^ (d1 >> 1)) & 0x55) == 0x55 && ++ ((d2 ^ (d2 >> 1)) & 0x54) == 0x54) { ++ /* Single bit (recoverable) error in data */ ++ ++ unsigned byte; ++ unsigned bit; ++ ++ bit = byte = 0; ++ ++ if (d1 & 0x80) ++ byte |= 0x80; ++ if (d1 & 0x20) ++ byte |= 0x40; ++ if (d1 & 0x08) ++ byte |= 0x20; ++ if (d1 & 0x02) ++ byte |= 0x10; ++ if (d0 & 0x80) ++ byte |= 0x08; ++ if (d0 & 0x20) ++ byte |= 0x04; ++ if (d0 & 0x08) ++ byte |= 0x02; ++ if (d0 & 0x02) ++ byte |= 0x01; ++ ++ if (d2 & 0x80) ++ bit |= 0x04; ++ if (d2 & 0x20) ++ bit |= 0x02; ++ if (d2 & 0x08) ++ bit |= 0x01; ++ ++ data[byte] ^= (1 << bit); ++ ++ return 1; /* Corrected the error */ ++ } ++ ++ if ((hweight8(d0) + hweight8(d1) + hweight8(d2)) == 1) { ++ /* Reccoverable error in ecc */ ++ ++ read_ecc[0] = test_ecc[0]; ++ read_ecc[1] = test_ecc[1]; ++ read_ecc[2] = test_ecc[2]; ++ ++ return 1; /* Corrected the error */ ++ } ++ ++ /* Unrecoverable error */ ++ ++ return -1; ++ ++} ++ ++/* ++ * ECCxxxOther does ECC calcs on arbitrary n bytes of data ++ */ ++void yaffs_ecc_calc_other(const unsigned char *data, unsigned n_bytes, ++ struct yaffs_ecc_other *ecc_other) ++{ ++ unsigned int i; ++ unsigned char col_parity = 0; ++ unsigned line_parity = 0; ++ unsigned line_parity_prime = 0; ++ unsigned char b; ++ ++ for (i = 0; i < n_bytes; i++) { ++ b = column_parity_table[*data++]; ++ col_parity ^= b; ++ ++ if (b & 0x01) { ++ /* odd number of bits in the byte */ ++ line_parity ^= i; ++ line_parity_prime ^= ~i; ++ } ++ ++ } ++ ++ ecc_other->col_parity = (col_parity >> 2) & 0x3f; ++ ecc_other->line_parity = line_parity; ++ ecc_other->line_parity_prime = line_parity_prime; ++} ++ ++int yaffs_ecc_correct_other(unsigned char *data, unsigned n_bytes, ++ struct yaffs_ecc_other *read_ecc, ++ const struct yaffs_ecc_other *test_ecc) ++{ ++ unsigned char delta_col; /* column parity delta */ ++ unsigned delta_line; /* line parity delta */ ++ unsigned delta_line_prime; /* line parity delta */ ++ unsigned bit; ++ ++ delta_col = read_ecc->col_parity ^ test_ecc->col_parity; ++ delta_line = read_ecc->line_parity ^ test_ecc->line_parity; ++ delta_line_prime = ++ read_ecc->line_parity_prime ^ test_ecc->line_parity_prime; ++ ++ if ((delta_col | delta_line | delta_line_prime) == 0) ++ return 0; /* no error */ ++ ++ if (delta_line == ~delta_line_prime && ++ (((delta_col ^ (delta_col >> 1)) & 0x15) == 0x15)) { ++ /* Single bit (recoverable) error in data */ ++ ++ bit = 0; ++ ++ if (delta_col & 0x20) ++ bit |= 0x04; ++ if (delta_col & 0x08) ++ bit |= 0x02; ++ if (delta_col & 0x02) ++ bit |= 0x01; ++ ++ if (delta_line >= n_bytes) ++ return -1; ++ ++ data[delta_line] ^= (1 << bit); ++ ++ return 1; /* corrected */ ++ } ++ ++ if ((hweight32(delta_line) + ++ hweight32(delta_line_prime) + ++ hweight8(delta_col)) == 1) { ++ /* Reccoverable error in ecc */ ++ ++ *read_ecc = *test_ecc; ++ return 1; /* corrected */ ++ } ++ ++ /* Unrecoverable error */ ++ ++ return -1; ++} +diff --git a/fs/yaffs2/yaffs_ecc.h b/fs/yaffs2/yaffs_ecc.h +new file mode 100644 +index 0000000..17d47bd +--- /dev/null ++++ b/fs/yaffs2/yaffs_ecc.h +@@ -0,0 +1,44 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++/* ++ * This code implements the ECC algorithm used in SmartMedia. ++ * ++ * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes. ++ * The two unused bit are set to 1. ++ * The ECC can correct single bit errors in a 256-byte page of data. ++ * Thus, two such ECC blocks are used on a 512-byte NAND page. ++ * ++ */ ++ ++#ifndef __YAFFS_ECC_H__ ++#define __YAFFS_ECC_H__ ++ ++struct yaffs_ecc_other { ++ unsigned char col_parity; ++ unsigned line_parity; ++ unsigned line_parity_prime; ++}; ++ ++void yaffs_ecc_calc(const unsigned char *data, unsigned char *ecc); ++int yaffs_ecc_correct(unsigned char *data, unsigned char *read_ecc, ++ const unsigned char *test_ecc); ++ ++void yaffs_ecc_calc_other(const unsigned char *data, unsigned n_bytes, ++ struct yaffs_ecc_other *ecc); ++int yaffs_ecc_correct_other(unsigned char *data, unsigned n_bytes, ++ struct yaffs_ecc_other *read_ecc, ++ const struct yaffs_ecc_other *test_ecc); ++#endif +diff --git a/fs/yaffs2/yaffs_endian.c b/fs/yaffs2/yaffs_endian.c +new file mode 100644 +index 0000000..8c291ad +--- /dev/null ++++ b/fs/yaffs2/yaffs_endian.c +@@ -0,0 +1,106 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * 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. ++ * ++ * Endian processing functions. ++ */ ++ ++#include "yaffs_endian.h" ++#include "yaffs_guts.h" ++ ++ ++void yaffs_do_endian_u32(struct yaffs_dev *dev, u32 *val) ++{ ++ if (!dev->swap_endian) ++ return; ++ *val = swap_u32(*val); ++} ++ ++void yaffs_do_endian_s32(struct yaffs_dev *dev, s32 *val) ++{ ++ if (!dev->swap_endian) ++ return; ++ *val = swap_s32(*val); ++} ++ ++void yaffs_do_endian_oh(struct yaffs_dev *dev, struct yaffs_obj_hdr *oh) ++{ ++ if (!dev->swap_endian) ++ return; ++ /* Change every field */ ++ oh->type = swap_u32(oh->type); ++ oh->parent_obj_id = swap_u32(oh->parent_obj_id); ++ ++ oh->yst_mode = swap_u32(oh->yst_mode); ++ ++ oh->yst_uid = swap_u32(oh->yst_uid); ++ oh->yst_gid = swap_u32(oh->yst_gid); ++ oh->yst_atime = swap_u32(oh->yst_atime); ++ oh->yst_mtime = swap_u32(oh->yst_mtime); ++ oh->yst_ctime = swap_u32(oh->yst_ctime); ++ ++ oh->file_size_low = swap_u32(oh->file_size_low); ++ ++ oh->equiv_id = swap_u32(oh->equiv_id); ++ ++ oh->yst_rdev = swap_u32(oh->yst_rdev); ++ ++ oh->win_ctime[0] = swap_u32(oh->win_ctime[0]); ++ oh->win_ctime[1] = swap_u32(oh->win_ctime[1]); ++ oh->win_atime[0] = swap_u32(oh->win_atime[0]); ++ oh->win_atime[1] = swap_u32(oh->win_atime[1]); ++ oh->win_mtime[0] = swap_u32(oh->win_mtime[0]); ++ oh->win_mtime[1] = swap_u32(oh->win_mtime[1]); ++ ++ oh->inband_shadowed_obj_id = swap_u32(oh->inband_shadowed_obj_id); ++ oh->inband_is_shrink = swap_u32(oh->inband_is_shrink); ++ ++ oh->file_size_high = swap_u32(oh->file_size_high); ++ oh->reserved[0] = swap_u32(oh->reserved[0]); ++ oh->shadows_obj = swap_s32(oh->shadows_obj); ++ ++ oh->is_shrink = swap_u32(oh->is_shrink); ++} ++ ++ ++void yaffs_do_endian_packed_tags2(struct yaffs_dev *dev, ++ struct yaffs_packed_tags2_tags_only *ptt) ++{ ++ if (!dev->swap_endian) ++ return; ++ ptt->seq_number = swap_u32(ptt->seq_number); ++ ptt->obj_id = swap_u32(ptt->obj_id); ++ ptt->chunk_id = swap_u32(ptt->chunk_id); ++ ptt->n_bytes = swap_u32(ptt->n_bytes); ++} ++ ++void yaffs_endian_config(struct yaffs_dev *dev) ++{ ++ u32 x = 1; ++ ++ if (dev->tnode_size < 1) ++ BUG(); ++ ++ dev->swap_endian = 0; ++ ++ if (((char *)&x)[0] == 1) { ++ /* Little Endian. */ ++ if (dev->param.stored_endian == 2 /* big endian */) ++ dev->swap_endian = 1; ++ } else { ++ /* Big Endian. */ ++ if (dev->param.stored_endian == 1 /* little endian */) ++ dev->swap_endian = 1; ++ } ++ ++ if (dev->swap_endian) ++ dev->tn_swap_buffer = kmalloc(dev->tnode_size, GFP_NOFS); ++} +diff --git a/fs/yaffs2/yaffs_endian.h b/fs/yaffs2/yaffs_endian.h +new file mode 100644 +index 0000000..e2fc602 +--- /dev/null ++++ b/fs/yaffs2/yaffs_endian.h +@@ -0,0 +1,55 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_ENDIAN_H__ ++#define __YAFFS_ENDIAN_H__ ++#include "yaffs_guts.h" ++#include "yaffs_packedtags2.h" ++ ++static inline u32 swap_u32(u32 val) ++{ ++ return ((val >>24) & 0x000000ff) | ++ ((val >> 8) & 0x0000ff00) | ++ ((val << 8) & 0x00ff0000) | ++ ((val <<24) & 0xff000000); ++} ++ ++#define swap_s32(val) \ ++ (s32)(swap_u32((u32)(val))) ++ ++static inline loff_t swap_loff_t(loff_t lval) ++{ ++ u32 vall = swap_u32(FSIZE_LOW(lval)); ++ u32 valh; ++ ++ if (sizeof(loff_t) == sizeof(u32)) ++ return (loff_t) vall; ++ ++ valh = swap_u32(FSIZE_HIGH(lval)); ++ ++ return FSIZE_COMBINE(vall, valh); /*NB: h and l are swapped. */ ++} ++ ++ ++ ++struct yaffs_dev; ++void yaffs_do_endian_s32(struct yaffs_dev *dev, s32 *val); ++void yaffs_do_endian_u32(struct yaffs_dev *dev, u32 *val); ++void yaffs_do_endian_oh(struct yaffs_dev *dev, struct yaffs_obj_hdr *oh); ++void yaffs_do_endian_packed_tags2(struct yaffs_dev *dev, ++ struct yaffs_packed_tags2_tags_only *ptt); ++void yaffs_endian_config(struct yaffs_dev *dev); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_getblockinfo.h b/fs/yaffs2/yaffs_getblockinfo.h +new file mode 100644 +index 0000000..09b5a16 +--- /dev/null ++++ b/fs/yaffs2/yaffs_getblockinfo.h +@@ -0,0 +1,36 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_GETBLOCKINFO_H__ ++#define __YAFFS_GETBLOCKINFO_H__ ++ ++#include "yaffs_guts.h" ++#include "yaffs_trace.h" ++ ++/* Function to manipulate block info */ ++static inline struct yaffs_block_info *yaffs_get_block_info(struct yaffs_dev ++ *dev, int blk) ++{ ++ if (blk < (int)dev->internal_start_block || ++ blk > (int)dev->internal_end_block) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "**>> yaffs: get_block_info block %d is not valid", ++ blk); ++ BUG(); ++ } ++ return &dev->block_info[blk - dev->internal_start_block]; ++} ++ ++#endif +diff --git a/fs/yaffs2/yaffs_guts.c b/fs/yaffs2/yaffs_guts.c +new file mode 100644 +index 0000000..ef2deb6 +--- /dev/null ++++ b/fs/yaffs2/yaffs_guts.c +@@ -0,0 +1,5215 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * 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 "yportenv.h" ++#include "yaffs_trace.h" ++ ++#include "yaffs_guts.h" ++#include "yaffs_endian.h" ++#include "yaffs_getblockinfo.h" ++#include "yaffs_tagscompat.h" ++#include "yaffs_tagsmarshall.h" ++#include "yaffs_nand.h" ++#include "yaffs_yaffs1.h" ++#include "yaffs_yaffs2.h" ++#include "yaffs_bitmap.h" ++#include "yaffs_verify.h" ++#include "yaffs_nand.h" ++#include "yaffs_packedtags2.h" ++#include "yaffs_nameval.h" ++#include "yaffs_allocator.h" ++#include "yaffs_attribs.h" ++#include "yaffs_summary.h" ++ ++/* Note YAFFS_GC_GOOD_ENOUGH must be <= YAFFS_GC_PASSIVE_THRESHOLD */ ++#define YAFFS_GC_GOOD_ENOUGH 2 ++#define YAFFS_GC_PASSIVE_THRESHOLD 4 ++ ++#include "yaffs_ecc.h" ++ ++/* Forward declarations */ ++ ++static int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk, ++ const u8 *buffer, int n_bytes, int use_reserve); ++ ++static void yaffs_fix_null_name(struct yaffs_obj *obj, YCHAR *name, ++ int buffer_size); ++ ++/* Function to calculate chunk and offset */ ++ ++void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr, ++ int *chunk_out, u32 *offset_out) ++{ ++ int chunk; ++ u32 offset; ++ ++ chunk = (u32) (addr >> dev->chunk_shift); ++ ++ if (dev->chunk_div == 1) { ++ /* easy power of 2 case */ ++ offset = (u32) (addr & dev->chunk_mask); ++ } else { ++ /* Non power-of-2 case */ ++ ++ loff_t chunk_base; ++ ++ chunk /= dev->chunk_div; ++ ++ chunk_base = ((loff_t) chunk) * dev->data_bytes_per_chunk; ++ offset = (u32) (addr - chunk_base); ++ } ++ ++ *chunk_out = chunk; ++ *offset_out = offset; ++} ++ ++/* Function to return the number of shifts for a power of 2 greater than or ++ * equal to the given number ++ * Note we don't try to cater for all possible numbers and this does not have to ++ * be hellishly efficient. ++ */ ++ ++static inline u32 calc_shifts_ceiling(u32 x) ++{ ++ int extra_bits; ++ int shifts; ++ ++ shifts = extra_bits = 0; ++ ++ while (x > 1) { ++ if (x & 1) ++ extra_bits++; ++ x >>= 1; ++ shifts++; ++ } ++ ++ if (extra_bits) ++ shifts++; ++ ++ return shifts; ++} ++ ++/* Function to return the number of shifts to get a 1 in bit 0 ++ */ ++ ++static inline u32 calc_shifts(u32 x) ++{ ++ u32 shifts; ++ ++ shifts = 0; ++ ++ if (!x) ++ return 0; ++ ++ while (!(x & 1)) { ++ x >>= 1; ++ shifts++; ++ } ++ ++ return shifts; ++} ++ ++/* ++ * Temporary buffer manipulations. ++ */ ++ ++static int yaffs_init_tmp_buffers(struct yaffs_dev *dev) ++{ ++ int i; ++ u8 *buf = (u8 *) 1; ++ ++ memset(dev->temp_buffer, 0, sizeof(dev->temp_buffer)); ++ ++ for (i = 0; buf && i < YAFFS_N_TEMP_BUFFERS; i++) { ++ dev->temp_buffer[i].in_use = 0; ++ buf = kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS); ++ dev->temp_buffer[i].buffer = buf; ++ } ++ ++ return buf ? YAFFS_OK : YAFFS_FAIL; ++} ++ ++u8 *yaffs_get_temp_buffer(struct yaffs_dev * dev) ++{ ++ int i; ++ ++ dev->temp_in_use++; ++ if (dev->temp_in_use > dev->max_temp) ++ dev->max_temp = dev->temp_in_use; ++ ++ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { ++ if (dev->temp_buffer[i].in_use == 0) { ++ dev->temp_buffer[i].in_use = 1; ++ return dev->temp_buffer[i].buffer; ++ } ++ } ++ ++ yaffs_trace(YAFFS_TRACE_BUFFERS, "Out of temp buffers"); ++ /* ++ * If we got here then we have to allocate an unmanaged one ++ * This is not good. ++ */ ++ ++ dev->unmanaged_buffer_allocs++; ++ return kmalloc(dev->data_bytes_per_chunk, GFP_NOFS); ++ ++} ++ ++void yaffs_release_temp_buffer(struct yaffs_dev *dev, u8 *buffer) ++{ ++ int i; ++ ++ dev->temp_in_use--; ++ ++ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { ++ if (dev->temp_buffer[i].buffer == buffer) { ++ dev->temp_buffer[i].in_use = 0; ++ return; ++ } ++ } ++ ++ if (buffer) { ++ /* assume it is an unmanaged one. */ ++ yaffs_trace(YAFFS_TRACE_BUFFERS, ++ "Releasing unmanaged temp buffer"); ++ kfree(buffer); ++ dev->unmanaged_buffer_deallocs++; ++ } ++ ++} ++ ++/* ++ * Functions for robustisizing TODO ++ * ++ */ ++ ++static void yaffs_handle_chunk_wr_ok(struct yaffs_dev *dev, int nand_chunk, ++ const u8 *data, ++ const struct yaffs_ext_tags *tags) ++{ ++ (void) dev; ++ (void) nand_chunk; ++ (void) data; ++ (void) tags; ++} ++ ++static void yaffs_handle_chunk_update(struct yaffs_dev *dev, int nand_chunk, ++ const struct yaffs_ext_tags *tags) ++{ ++ (void) dev; ++ (void) nand_chunk; ++ (void) tags; ++} ++ ++void yaffs_handle_chunk_error(struct yaffs_dev *dev, ++ struct yaffs_block_info *bi) ++{ ++ if (!bi->gc_prioritise) { ++ bi->gc_prioritise = 1; ++ dev->has_pending_prioritised_gc = 1; ++ bi->chunk_error_strikes++; ++ ++ if (bi->chunk_error_strikes > 3) { ++ bi->needs_retiring = 1; /* Too many stikes, so retire */ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs: Block struck out"); ++ ++ } ++ } ++} ++ ++static void yaffs_handle_chunk_wr_error(struct yaffs_dev *dev, int nand_chunk, ++ int erased_ok) ++{ ++ int flash_block = nand_chunk / dev->param.chunks_per_block; ++ struct yaffs_block_info *bi = yaffs_get_block_info(dev, flash_block); ++ ++ yaffs_handle_chunk_error(dev, bi); ++ ++ if (erased_ok) { ++ /* Was an actual write failure, ++ * so mark the block for retirement.*/ ++ bi->needs_retiring = 1; ++ yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS, ++ "**>> Block %d needs retiring", flash_block); ++ } ++ ++ /* Delete the chunk */ ++ yaffs_chunk_del(dev, nand_chunk, 1, __LINE__); ++ yaffs_skip_rest_of_block(dev); ++} ++ ++/* ++ * Verification code ++ */ ++ ++/* ++ * Simple hash function. Needs to have a reasonable spread ++ */ ++ ++static inline int yaffs_hash_fn(int n) ++{ ++ if (n < 0) ++ n = -n; ++ return n % YAFFS_NOBJECT_BUCKETS; ++} ++ ++/* ++ * Access functions to useful fake objects. ++ * Note that root might have a presence in NAND if permissions are set. ++ */ ++ ++struct yaffs_obj *yaffs_root(struct yaffs_dev *dev) ++{ ++ return dev->root_dir; ++} ++ ++struct yaffs_obj *yaffs_lost_n_found(struct yaffs_dev *dev) ++{ ++ return dev->lost_n_found; ++} ++ ++/* ++ * Erased NAND checking functions ++ */ ++ ++int yaffs_check_ff(u8 *buffer, int n_bytes) ++{ ++ /* Horrible, slow implementation */ ++ while (n_bytes--) { ++ if (*buffer != 0xff) ++ return 0; ++ buffer++; ++ } ++ return 1; ++} ++ ++static int yaffs_check_chunk_erased(struct yaffs_dev *dev, int nand_chunk) ++{ ++ int retval = YAFFS_OK; ++ u8 *data = yaffs_get_temp_buffer(dev); ++ struct yaffs_ext_tags tags; ++ int result; ++ ++ result = yaffs_rd_chunk_tags_nand(dev, nand_chunk, data, &tags); ++ ++ if (result == YAFFS_FAIL || ++ tags.ecc_result > YAFFS_ECC_RESULT_NO_ERROR) ++ retval = YAFFS_FAIL; ++ ++ if (!yaffs_check_ff(data, dev->data_bytes_per_chunk) || ++ tags.chunk_used) { ++ yaffs_trace(YAFFS_TRACE_NANDACCESS, ++ "Chunk %d not erased", nand_chunk); ++ retval = YAFFS_FAIL; ++ } ++ ++ yaffs_release_temp_buffer(dev, data); ++ ++ return retval; ++ ++} ++ ++static int yaffs_verify_chunk_written(struct yaffs_dev *dev, ++ int nand_chunk, ++ const u8 *data, ++ struct yaffs_ext_tags *tags) ++{ ++ int retval = YAFFS_OK; ++ struct yaffs_ext_tags temp_tags; ++ u8 *buffer = yaffs_get_temp_buffer(dev); ++ int result; ++ ++ result = yaffs_rd_chunk_tags_nand(dev, nand_chunk, buffer, &temp_tags); ++ if (result == YAFFS_FAIL || ++ memcmp(buffer, data, dev->data_bytes_per_chunk) || ++ temp_tags.obj_id != tags->obj_id || ++ temp_tags.chunk_id != tags->chunk_id || ++ temp_tags.n_bytes != tags->n_bytes) ++ retval = YAFFS_FAIL; ++ ++ yaffs_release_temp_buffer(dev, buffer); ++ ++ return retval; ++} ++ ++ ++int yaffs_check_alloc_available(struct yaffs_dev *dev, int n_chunks) ++{ ++ int reserved_chunks; ++ int reserved_blocks = dev->param.n_reserved_blocks; ++ int checkpt_blocks; ++ ++ checkpt_blocks = yaffs_calc_checkpt_blocks_required(dev); ++ ++ reserved_chunks = ++ (reserved_blocks + checkpt_blocks) * dev->param.chunks_per_block; ++ ++ return (dev->n_free_chunks > (reserved_chunks + n_chunks)); ++} ++ ++static int yaffs_find_alloc_block(struct yaffs_dev *dev) ++{ ++ u32 i; ++ struct yaffs_block_info *bi; ++ ++ if (dev->n_erased_blocks < 1) { ++ /* Hoosterman we've got a problem. ++ * Can't get space to gc ++ */ ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs tragedy: no more erased blocks"); ++ ++ return -1; ++ } ++ ++ /* Find an empty block. */ ++ ++ for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) { ++ dev->alloc_block_finder++; ++ if (dev->alloc_block_finder < (int)dev->internal_start_block ++ || dev->alloc_block_finder > (int)dev->internal_end_block) { ++ dev->alloc_block_finder = dev->internal_start_block; ++ } ++ ++ bi = yaffs_get_block_info(dev, dev->alloc_block_finder); ++ ++ if (bi->block_state == YAFFS_BLOCK_STATE_EMPTY) { ++ bi->block_state = YAFFS_BLOCK_STATE_ALLOCATING; ++ dev->seq_number++; ++ bi->seq_number = dev->seq_number; ++ dev->n_erased_blocks--; ++ yaffs_trace(YAFFS_TRACE_ALLOCATE, ++ "Allocated block %d, seq %d, %d left" , ++ dev->alloc_block_finder, dev->seq_number, ++ dev->n_erased_blocks); ++ return dev->alloc_block_finder; ++ } ++ } ++ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs tragedy: no more erased blocks, but there should have been %d", ++ dev->n_erased_blocks); ++ ++ return -1; ++} ++ ++static int yaffs_alloc_chunk(struct yaffs_dev *dev, int use_reserver, ++ struct yaffs_block_info **block_ptr) ++{ ++ int ret_val; ++ struct yaffs_block_info *bi; ++ ++ if (dev->alloc_block < 0) { ++ /* Get next block to allocate off */ ++ dev->alloc_block = yaffs_find_alloc_block(dev); ++ dev->alloc_page = 0; ++ } ++ ++ if (!use_reserver && !yaffs_check_alloc_available(dev, 1)) { ++ /* No space unless we're allowed to use the reserve. */ ++ return -1; ++ } ++ ++ if (dev->n_erased_blocks < (int)dev->param.n_reserved_blocks ++ && dev->alloc_page == 0) ++ yaffs_trace(YAFFS_TRACE_ALLOCATE, "Allocating reserve"); ++ ++ /* Next page please.... */ ++ if (dev->alloc_block >= 0) { ++ bi = yaffs_get_block_info(dev, dev->alloc_block); ++ ++ ret_val = (dev->alloc_block * dev->param.chunks_per_block) + ++ dev->alloc_page; ++ bi->pages_in_use++; ++ yaffs_set_chunk_bit(dev, dev->alloc_block, dev->alloc_page); ++ ++ dev->alloc_page++; ++ ++ dev->n_free_chunks--; ++ ++ /* If the block is full set the state to full */ ++ if (dev->alloc_page >= dev->param.chunks_per_block) { ++ bi->block_state = YAFFS_BLOCK_STATE_FULL; ++ dev->alloc_block = -1; ++ } ++ ++ if (block_ptr) ++ *block_ptr = bi; ++ ++ return ret_val; ++ } ++ ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!"); ++ ++ return -1; ++} ++ ++static int yaffs_get_erased_chunks(struct yaffs_dev *dev) ++{ ++ int n; ++ ++ n = dev->n_erased_blocks * dev->param.chunks_per_block; ++ ++ if (dev->alloc_block > 0) ++ n += (dev->param.chunks_per_block - dev->alloc_page); ++ ++ return n; ++ ++} ++ ++/* ++ * yaffs_skip_rest_of_block() skips over the rest of the allocation block ++ * if we don't want to write to it. ++ */ ++void yaffs_skip_rest_of_block(struct yaffs_dev *dev) ++{ ++ struct yaffs_block_info *bi; ++ ++ if (dev->alloc_block > 0) { ++ bi = yaffs_get_block_info(dev, dev->alloc_block); ++ if (bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING) { ++ bi->block_state = YAFFS_BLOCK_STATE_FULL; ++ dev->alloc_block = -1; ++ } ++ } ++} ++ ++static int yaffs_write_new_chunk(struct yaffs_dev *dev, ++ const u8 *data, ++ struct yaffs_ext_tags *tags, int use_reserver) ++{ ++ u32 attempts = 0; ++ int write_ok = 0; ++ int chunk; ++ ++ yaffs2_checkpt_invalidate(dev); ++ ++ do { ++ struct yaffs_block_info *bi = 0; ++ int erased_ok = 0; ++ ++ chunk = yaffs_alloc_chunk(dev, use_reserver, &bi); ++ if (chunk < 0) { ++ /* no space */ ++ break; ++ } ++ ++ /* First check this chunk is erased, if it needs ++ * checking. The checking policy (unless forced ++ * always on) is as follows: ++ * ++ * Check the first page we try to write in a block. ++ * If the check passes then we don't need to check any ++ * more. If the check fails, we check again... ++ * If the block has been erased, we don't need to check. ++ * ++ * However, if the block has been prioritised for gc, ++ * then we think there might be something odd about ++ * this block and stop using it. ++ * ++ * Rationale: We should only ever see chunks that have ++ * not been erased if there was a partially written ++ * chunk due to power loss. This checking policy should ++ * catch that case with very few checks and thus save a ++ * lot of checks that are most likely not needed. ++ * ++ * Mods to the above ++ * If an erase check fails or the write fails we skip the ++ * rest of the block. ++ */ ++ ++ /* let's give it a try */ ++ attempts++; ++ ++ if (dev->param.always_check_erased) ++ bi->skip_erased_check = 0; ++ ++ if (!bi->skip_erased_check) { ++ erased_ok = yaffs_check_chunk_erased(dev, chunk); ++ if (erased_ok != YAFFS_OK) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "**>> yaffs chunk %d was not erased", ++ chunk); ++ ++ /* If not erased, delete this one, ++ * skip rest of block and ++ * try another chunk */ ++ yaffs_chunk_del(dev, chunk, 1, __LINE__); ++ yaffs_skip_rest_of_block(dev); ++ continue; ++ } ++ } ++ ++ write_ok = yaffs_wr_chunk_tags_nand(dev, chunk, data, tags); ++ ++ if (!bi->skip_erased_check) ++ write_ok = ++ yaffs_verify_chunk_written(dev, chunk, data, tags); ++ ++ if (write_ok != YAFFS_OK) { ++ /* Clean up aborted write, skip to next block and ++ * try another chunk */ ++ yaffs_handle_chunk_wr_error(dev, chunk, erased_ok); ++ continue; ++ } ++ ++ bi->skip_erased_check = 1; ++ ++ /* Copy the data into the robustification buffer */ ++ yaffs_handle_chunk_wr_ok(dev, chunk, data, tags); ++ ++ } while (write_ok != YAFFS_OK && ++ (yaffs_wr_attempts == 0 || attempts <= yaffs_wr_attempts)); ++ ++ if (!write_ok) ++ chunk = -1; ++ ++ if (attempts > 1) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "**>> yaffs write required %d attempts", ++ attempts); ++ dev->n_retried_writes += (attempts - 1); ++ } ++ ++ return chunk; ++} ++ ++/* ++ * Block retiring for handling a broken block. ++ */ ++ ++static void yaffs_retire_block(struct yaffs_dev *dev, int flash_block) ++{ ++ struct yaffs_block_info *bi = yaffs_get_block_info(dev, flash_block); ++ ++ yaffs2_checkpt_invalidate(dev); ++ ++ yaffs2_clear_oldest_dirty_seq(dev, bi); ++ ++ if (yaffs_mark_bad(dev, flash_block) != YAFFS_OK) { ++ if (yaffs_erase_block(dev, flash_block) != YAFFS_OK) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs: Failed to mark bad and erase block %d", ++ flash_block); ++ } else { ++ struct yaffs_ext_tags tags; ++ int chunk_id = ++ flash_block * dev->param.chunks_per_block; ++ ++ u8 *buffer = yaffs_get_temp_buffer(dev); ++ ++ memset(buffer, 0xff, dev->data_bytes_per_chunk); ++ memset(&tags, 0, sizeof(tags)); ++ tags.seq_number = YAFFS_SEQUENCE_BAD_BLOCK; ++ if (dev->tagger.write_chunk_tags_fn(dev, chunk_id - ++ dev->chunk_offset, ++ buffer, ++ &tags) != YAFFS_OK) ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs: Failed to write bad block marker to block %d", ++ flash_block); ++ ++ yaffs_release_temp_buffer(dev, buffer); ++ } ++ } ++ ++ bi->block_state = YAFFS_BLOCK_STATE_DEAD; ++ bi->gc_prioritise = 0; ++ bi->needs_retiring = 0; ++ ++ dev->n_retired_blocks++; ++} ++ ++/*---------------- Name handling functions ------------*/ ++ ++static void yaffs_load_name_from_oh(struct yaffs_dev *dev, YCHAR *name, ++ const YCHAR *oh_name, int buff_size) ++{ ++#ifdef CONFIG_YAFFS_AUTO_UNICODE ++ if (dev->param.auto_unicode) { ++ if (*oh_name) { ++ /* It is an ASCII name, do an ASCII to ++ * unicode conversion */ ++ const char *ascii_oh_name = (const char *)oh_name; ++ int n = buff_size - 1; ++ while (n > 0 && *ascii_oh_name) { ++ *name = *ascii_oh_name; ++ name++; ++ ascii_oh_name++; ++ n--; ++ } ++ } else { ++ strncpy(name, oh_name + 1, buff_size - 1); ++ } ++ } else { ++#else ++ (void) dev; ++ { ++#endif ++ strncpy(name, oh_name, buff_size - 1); ++ } ++} ++ ++static void yaffs_load_oh_from_name(struct yaffs_dev *dev, YCHAR *oh_name, ++ const YCHAR *name) ++{ ++#ifdef CONFIG_YAFFS_AUTO_UNICODE ++ ++ int is_ascii; ++ const YCHAR *w; ++ ++ if (dev->param.auto_unicode) { ++ ++ is_ascii = 1; ++ w = name; ++ ++ /* Figure out if the name will fit in ascii character set */ ++ while (is_ascii && *w) { ++ if ((*w) & 0xff00) ++ is_ascii = 0; ++ w++; ++ } ++ ++ if (is_ascii) { ++ /* It is an ASCII name, so convert unicode to ascii */ ++ char *ascii_oh_name = (char *)oh_name; ++ int n = YAFFS_MAX_NAME_LENGTH - 1; ++ while (n > 0 && *name) { ++ *ascii_oh_name = *name; ++ name++; ++ ascii_oh_name++; ++ n--; ++ } ++ } else { ++ /* Unicode name, so save starting at the second YCHAR */ ++ *oh_name = 0; ++ strncpy(oh_name + 1, name, YAFFS_MAX_NAME_LENGTH - 2); ++ } ++ } else { ++#else ++ dev = dev; ++ { ++#endif ++ strncpy(oh_name, name, YAFFS_MAX_NAME_LENGTH - 1); ++ } ++} ++ ++static u16 yaffs_calc_name_sum(const YCHAR *name) ++{ ++ u16 sum = 0; ++ u16 i = 1; ++ ++ if (!name) ++ return 0; ++ ++ while ((*name) && i < (YAFFS_MAX_NAME_LENGTH / 2)) { ++ ++ /* 0x1f mask is case insensitive */ ++ sum += ((*name) & 0x1f) * i; ++ i++; ++ name++; ++ } ++ return sum; ++} ++ ++ ++void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR * name) ++{ ++ memset(obj->short_name, 0, sizeof(obj->short_name)); ++ ++ if (name && !name[0]) { ++ yaffs_fix_null_name(obj, obj->short_name, ++ YAFFS_SHORT_NAME_LENGTH); ++ name = obj->short_name; ++ } else if (name && ++ strnlen(name, YAFFS_SHORT_NAME_LENGTH + 1) <= ++ YAFFS_SHORT_NAME_LENGTH) { ++ strcpy(obj->short_name, name); ++ } ++ ++ obj->sum = yaffs_calc_name_sum(name); ++} ++ ++void yaffs_set_obj_name_from_oh(struct yaffs_obj *obj, ++ const struct yaffs_obj_hdr *oh) ++{ ++#ifdef CONFIG_YAFFS_AUTO_UNICODE ++ YCHAR tmp_name[YAFFS_MAX_NAME_LENGTH + 1]; ++ memset(tmp_name, 0, sizeof(tmp_name)); ++ yaffs_load_name_from_oh(obj->my_dev, tmp_name, oh->name, ++ YAFFS_MAX_NAME_LENGTH + 1); ++ yaffs_set_obj_name(obj, tmp_name); ++#else ++ yaffs_set_obj_name(obj, oh->name); ++#endif ++} ++ ++loff_t yaffs_max_file_size(struct yaffs_dev *dev) ++{ ++ if (sizeof(loff_t) < 8) ++ return YAFFS_MAX_FILE_SIZE_32; ++ else ++ return ((loff_t) YAFFS_MAX_CHUNK_ID) * dev->data_bytes_per_chunk; ++} ++ ++/*-------------------- TNODES ------------------- ++ ++ * List of spare tnodes ++ * The list is hooked together using the first pointer ++ * in the tnode. ++ */ ++ ++struct yaffs_tnode *yaffs_get_tnode(struct yaffs_dev *dev) ++{ ++ struct yaffs_tnode *tn = yaffs_alloc_raw_tnode(dev); ++ ++ if (tn) { ++ memset(tn, 0, dev->tnode_size); ++ dev->n_tnodes++; ++ } ++ ++ dev->checkpoint_blocks_required = 0; /* force recalculation */ ++ ++ return tn; ++} ++ ++/* FreeTnode frees up a tnode and puts it back on the free list */ ++static void yaffs_free_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn) ++{ ++ yaffs_free_raw_tnode(dev, tn); ++ dev->n_tnodes--; ++ dev->checkpoint_blocks_required = 0; /* force recalculation */ ++} ++ ++static void yaffs_deinit_tnodes_and_objs(struct yaffs_dev *dev) ++{ ++ yaffs_deinit_raw_tnodes_and_objs(dev); ++ dev->n_obj = 0; ++ dev->n_tnodes = 0; ++} ++ ++static void yaffs_load_tnode_0(struct yaffs_dev *dev, struct yaffs_tnode *tn, ++ unsigned pos, unsigned val) ++{ ++ u32 *map = (u32 *) tn; ++ u32 bit_in_map; ++ u32 bit_in_word; ++ u32 word_in_map; ++ u32 mask; ++ ++ pos &= YAFFS_TNODES_LEVEL0_MASK; ++ val >>= dev->chunk_grp_bits; ++ ++ bit_in_map = pos * dev->tnode_width; ++ word_in_map = bit_in_map / 32; ++ bit_in_word = bit_in_map & (32 - 1); ++ ++ mask = dev->tnode_mask << bit_in_word; ++ ++ map[word_in_map] &= ~mask; ++ map[word_in_map] |= (mask & (val << bit_in_word)); ++ ++ if (dev->tnode_width > (32 - bit_in_word)) { ++ bit_in_word = (32 - bit_in_word); ++ word_in_map++; ++ mask = ++ dev->tnode_mask >> bit_in_word; ++ map[word_in_map] &= ~mask; ++ map[word_in_map] |= (mask & (val >> bit_in_word)); ++ } ++} ++ ++u32 yaffs_get_group_base(struct yaffs_dev *dev, struct yaffs_tnode *tn, ++ unsigned pos) ++{ ++ u32 *map = (u32 *) tn; ++ u32 bit_in_map; ++ u32 bit_in_word; ++ u32 word_in_map; ++ u32 val; ++ ++ pos &= YAFFS_TNODES_LEVEL0_MASK; ++ ++ bit_in_map = pos * dev->tnode_width; ++ word_in_map = bit_in_map / 32; ++ bit_in_word = bit_in_map & (32 - 1); ++ ++ val = map[word_in_map] >> bit_in_word; ++ ++ if (dev->tnode_width > (32 - bit_in_word)) { ++ bit_in_word = (32 - bit_in_word); ++ word_in_map++; ++ val |= (map[word_in_map] << bit_in_word); ++ } ++ ++ val &= dev->tnode_mask; ++ val <<= dev->chunk_grp_bits; ++ ++ return val; ++} ++ ++/* ------------------- End of individual tnode manipulation -----------------*/ ++ ++/* ---------Functions to manipulate the look-up tree (made up of tnodes) ------ ++ * The look up tree is represented by the top tnode and the number of top_level ++ * in the tree. 0 means only the level 0 tnode is in the tree. ++ */ ++ ++/* FindLevel0Tnode finds the level 0 tnode, if one exists. */ ++struct yaffs_tnode *yaffs_find_tnode_0(struct yaffs_dev *dev, ++ struct yaffs_file_var *file_struct, ++ u32 chunk_id) ++{ ++ struct yaffs_tnode *tn = file_struct->top; ++ u32 i; ++ int required_depth; ++ int level = file_struct->top_level; ++ ++ (void) dev; ++ ++ /* Check sane level and chunk Id */ ++ if (level < 0 || level > YAFFS_TNODES_MAX_LEVEL) ++ return NULL; ++ ++ if (chunk_id > YAFFS_MAX_CHUNK_ID) ++ return NULL; ++ ++ /* First check we're tall enough (ie enough top_level) */ ++ ++ i = chunk_id >> YAFFS_TNODES_LEVEL0_BITS; ++ required_depth = 0; ++ while (i) { ++ i >>= YAFFS_TNODES_INTERNAL_BITS; ++ required_depth++; ++ } ++ ++ if (required_depth > file_struct->top_level) ++ return NULL; /* Not tall enough, so we can't find it */ ++ ++ /* Traverse down to level 0 */ ++ while (level > 0 && tn) { ++ tn = tn->internal[(chunk_id >> ++ (YAFFS_TNODES_LEVEL0_BITS + ++ (level - 1) * ++ YAFFS_TNODES_INTERNAL_BITS)) & ++ YAFFS_TNODES_INTERNAL_MASK]; ++ level--; ++ } ++ ++ return tn; ++} ++ ++/* add_find_tnode_0 finds the level 0 tnode if it exists, ++ * otherwise first expands the tree. ++ * This happens in two steps: ++ * 1. If the tree isn't tall enough, then make it taller. ++ * 2. Scan down the tree towards the level 0 tnode adding tnodes if required. ++ * ++ * Used when modifying the tree. ++ * ++ * If the tn argument is NULL, then a fresh tnode will be added otherwise the ++ * specified tn will be plugged into the ttree. ++ */ ++ ++struct yaffs_tnode *yaffs_add_find_tnode_0(struct yaffs_dev *dev, ++ struct yaffs_file_var *file_struct, ++ u32 chunk_id, ++ struct yaffs_tnode *passed_tn) ++{ ++ int required_depth; ++ int i; ++ int l; ++ struct yaffs_tnode *tn; ++ u32 x; ++ ++ /* Check sane level and page Id */ ++ if (file_struct->top_level < 0 || ++ file_struct->top_level > YAFFS_TNODES_MAX_LEVEL) ++ return NULL; ++ ++ if (chunk_id > YAFFS_MAX_CHUNK_ID) ++ return NULL; ++ ++ /* First check we're tall enough (ie enough top_level) */ ++ ++ x = chunk_id >> YAFFS_TNODES_LEVEL0_BITS; ++ required_depth = 0; ++ while (x) { ++ x >>= YAFFS_TNODES_INTERNAL_BITS; ++ required_depth++; ++ } ++ ++ if (required_depth > file_struct->top_level) { ++ /* Not tall enough, gotta make the tree taller */ ++ for (i = file_struct->top_level; i < required_depth; i++) { ++ ++ tn = yaffs_get_tnode(dev); ++ ++ if (tn) { ++ tn->internal[0] = file_struct->top; ++ file_struct->top = tn; ++ file_struct->top_level++; ++ } else { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs: no more tnodes"); ++ return NULL; ++ } ++ } ++ } ++ ++ /* Traverse down to level 0, adding anything we need */ ++ ++ l = file_struct->top_level; ++ tn = file_struct->top; ++ ++ if (l > 0) { ++ while (l > 0 && tn) { ++ x = (chunk_id >> ++ (YAFFS_TNODES_LEVEL0_BITS + ++ (l - 1) * YAFFS_TNODES_INTERNAL_BITS)) & ++ YAFFS_TNODES_INTERNAL_MASK; ++ ++ if ((l > 1) && !tn->internal[x]) { ++ /* Add missing non-level-zero tnode */ ++ tn->internal[x] = yaffs_get_tnode(dev); ++ if (!tn->internal[x]) ++ return NULL; ++ } else if (l == 1) { ++ /* Looking from level 1 at level 0 */ ++ if (passed_tn) { ++ /* If we already have one, release it */ ++ if (tn->internal[x]) ++ yaffs_free_tnode(dev, ++ tn->internal[x]); ++ tn->internal[x] = passed_tn; ++ ++ } else if (!tn->internal[x]) { ++ /* Don't have one, none passed in */ ++ tn->internal[x] = yaffs_get_tnode(dev); ++ if (!tn->internal[x]) ++ return NULL; ++ } ++ } ++ ++ tn = tn->internal[x]; ++ l--; ++ } ++ } else { ++ /* top is level 0 */ ++ if (passed_tn) { ++ memcpy(tn, passed_tn, ++ (dev->tnode_width * YAFFS_NTNODES_LEVEL0) / 8); ++ yaffs_free_tnode(dev, passed_tn); ++ } ++ } ++ ++ return tn; ++} ++ ++static int yaffs_tags_match(const struct yaffs_ext_tags *tags, int obj_id, ++ int chunk_obj) ++{ ++ return (tags->chunk_id == (u32)chunk_obj && ++ tags->obj_id == (u32)obj_id && ++ !tags->is_deleted) ? 1 : 0; ++ ++} ++ ++static int yaffs_find_chunk_in_group(struct yaffs_dev *dev, int the_chunk, ++ struct yaffs_ext_tags *tags, int obj_id, ++ int inode_chunk) ++{ ++ int j; ++ ++ for (j = 0; the_chunk && j < dev->chunk_grp_size; j++) { ++ if (yaffs_check_chunk_bit ++ (dev, the_chunk / dev->param.chunks_per_block, ++ the_chunk % dev->param.chunks_per_block)) { ++ ++ if (dev->chunk_grp_size == 1) ++ return the_chunk; ++ else { ++ yaffs_rd_chunk_tags_nand(dev, the_chunk, NULL, ++ tags); ++ if (yaffs_tags_match(tags, ++ obj_id, inode_chunk)) { ++ /* found it; */ ++ return the_chunk; ++ } ++ } ++ } ++ the_chunk++; ++ } ++ return -1; ++} ++ ++int yaffs_find_chunk_in_file(struct yaffs_obj *in, int inode_chunk, ++ struct yaffs_ext_tags *tags) ++{ ++ /*Get the Tnode, then get the level 0 offset chunk offset */ ++ struct yaffs_tnode *tn; ++ int the_chunk = -1; ++ struct yaffs_ext_tags local_tags; ++ int ret_val = -1; ++ struct yaffs_dev *dev = in->my_dev; ++ ++ if (!tags) { ++ /* Passed a NULL, so use our own tags space */ ++ tags = &local_tags; ++ } ++ ++ tn = yaffs_find_tnode_0(dev, &in->variant.file_variant, inode_chunk); ++ ++ if (!tn) ++ return ret_val; ++ ++ the_chunk = yaffs_get_group_base(dev, tn, inode_chunk); ++ ++ ret_val = yaffs_find_chunk_in_group(dev, the_chunk, tags, in->obj_id, ++ inode_chunk); ++ return ret_val; ++} ++ ++static int yaffs_find_del_file_chunk(struct yaffs_obj *in, int inode_chunk, ++ struct yaffs_ext_tags *tags) ++{ ++ /* Get the Tnode, then get the level 0 offset chunk offset */ ++ struct yaffs_tnode *tn; ++ int the_chunk = -1; ++ struct yaffs_ext_tags local_tags; ++ struct yaffs_dev *dev = in->my_dev; ++ int ret_val = -1; ++ ++ if (!tags) { ++ /* Passed a NULL, so use our own tags space */ ++ tags = &local_tags; ++ } ++ ++ tn = yaffs_find_tnode_0(dev, &in->variant.file_variant, inode_chunk); ++ ++ if (!tn) ++ return ret_val; ++ ++ the_chunk = yaffs_get_group_base(dev, tn, inode_chunk); ++ ++ ret_val = yaffs_find_chunk_in_group(dev, the_chunk, tags, in->obj_id, ++ inode_chunk); ++ ++ /* Delete the entry in the filestructure (if found) */ ++ if (ret_val != -1) ++ yaffs_load_tnode_0(dev, tn, inode_chunk, 0); ++ ++ return ret_val; ++} ++ ++int yaffs_put_chunk_in_file(struct yaffs_obj *in, int inode_chunk, ++ int nand_chunk, int in_scan) ++{ ++ /* NB in_scan is zero unless scanning. ++ * For forward scanning, in_scan is > 0; ++ * for backward scanning in_scan is < 0 ++ * ++ * nand_chunk = 0 is a dummy insert to make sure the tnodes are there. ++ */ ++ ++ struct yaffs_tnode *tn; ++ struct yaffs_dev *dev = in->my_dev; ++ int existing_cunk; ++ struct yaffs_ext_tags existing_tags; ++ struct yaffs_ext_tags new_tags; ++ unsigned existing_serial, new_serial; ++ ++ if (in->variant_type != YAFFS_OBJECT_TYPE_FILE) { ++ /* Just ignore an attempt at putting a chunk into a non-file ++ * during scanning. ++ * If it is not during Scanning then something went wrong! ++ */ ++ if (!in_scan) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs tragedy:attempt to put data chunk into a non-file" ++ ); ++ BUG(); ++ } ++ ++ yaffs_chunk_del(dev, nand_chunk, 1, __LINE__); ++ return YAFFS_OK; ++ } ++ ++ tn = yaffs_add_find_tnode_0(dev, ++ &in->variant.file_variant, ++ inode_chunk, NULL); ++ if (!tn) ++ return YAFFS_FAIL; ++ ++ if (!nand_chunk) ++ /* Dummy insert, bail now */ ++ return YAFFS_OK; ++ ++ existing_cunk = yaffs_get_group_base(dev, tn, inode_chunk); ++ ++ if (in_scan != 0) { ++ /* If we're scanning then we need to test for duplicates ++ * NB This does not need to be efficient since it should only ++ * happen when the power fails during a write, then only one ++ * chunk should ever be affected. ++ * ++ * Correction for YAFFS2: This could happen quite a lot and we ++ * need to think about efficiency! TODO ++ * Update: For backward scanning we don't need to re-read tags ++ * so this is quite cheap. ++ */ ++ ++ if (existing_cunk > 0) { ++ /* NB Right now existing chunk will not be real ++ * chunk_id if the chunk group size > 1 ++ * thus we have to do a FindChunkInFile to get the ++ * real chunk id. ++ * ++ * We have a duplicate now we need to decide which ++ * one to use: ++ * ++ * Backwards scanning YAFFS2: The old one is what ++ * we use, dump the new one. ++ * YAFFS1: Get both sets of tags and compare serial ++ * numbers. ++ */ ++ ++ if (in_scan > 0) { ++ /* Only do this for forward scanning */ ++ yaffs_rd_chunk_tags_nand(dev, ++ nand_chunk, ++ NULL, &new_tags); ++ ++ /* Do a proper find */ ++ existing_cunk = ++ yaffs_find_chunk_in_file(in, inode_chunk, ++ &existing_tags); ++ } ++ ++ if (existing_cunk <= 0) { ++ /*Hoosterman - how did this happen? */ ++ ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs tragedy: existing chunk < 0 in scan" ++ ); ++ ++ } ++ ++ /* NB The deleted flags should be false, otherwise ++ * the chunks will not be loaded during a scan ++ */ ++ ++ if (in_scan > 0) { ++ new_serial = new_tags.serial_number; ++ existing_serial = existing_tags.serial_number; ++ } ++ ++ if ((in_scan > 0) && ++ (existing_cunk <= 0 || ++ ((existing_serial + 1) & 3) == new_serial)) { ++ /* Forward scanning. ++ * Use new ++ * Delete the old one and drop through to ++ * update the tnode ++ */ ++ yaffs_chunk_del(dev, existing_cunk, 1, ++ __LINE__); ++ } else { ++ /* Backward scanning or we want to use the ++ * existing one ++ * Delete the new one and return early so that ++ * the tnode isn't changed ++ */ ++ yaffs_chunk_del(dev, nand_chunk, 1, __LINE__); ++ return YAFFS_OK; ++ } ++ } ++ ++ } ++ ++ if (existing_cunk == 0) ++ in->n_data_chunks++; ++ ++ yaffs_load_tnode_0(dev, tn, inode_chunk, nand_chunk); ++ ++ return YAFFS_OK; ++} ++ ++static void yaffs_soft_del_chunk(struct yaffs_dev *dev, int chunk) ++{ ++ struct yaffs_block_info *the_block; ++ unsigned block_no; ++ ++ yaffs_trace(YAFFS_TRACE_DELETION, "soft delete chunk %d", chunk); ++ ++ block_no = chunk / dev->param.chunks_per_block; ++ the_block = yaffs_get_block_info(dev, block_no); ++ if (the_block) { ++ the_block->soft_del_pages++; ++ dev->n_free_chunks++; ++ yaffs2_update_oldest_dirty_seq(dev, block_no, the_block); ++ } ++} ++ ++/* SoftDeleteWorker scans backwards through the tnode tree and soft deletes all ++ * the chunks in the file. ++ * All soft deleting does is increment the block's softdelete count and pulls ++ * the chunk out of the tnode. ++ * Thus, essentially this is the same as DeleteWorker except that the chunks ++ * are soft deleted. ++ */ ++ ++static int yaffs_soft_del_worker(struct yaffs_obj *in, struct yaffs_tnode *tn, ++ u32 level, int chunk_offset) ++{ ++ int i; ++ int the_chunk; ++ int all_done = 1; ++ struct yaffs_dev *dev = in->my_dev; ++ ++ if (!tn) ++ return 1; ++ ++ if (level > 0) { ++ for (i = YAFFS_NTNODES_INTERNAL - 1; ++ all_done && i >= 0; ++ i--) { ++ if (tn->internal[i]) { ++ all_done = ++ yaffs_soft_del_worker(in, ++ tn->internal[i], ++ level - 1, ++ (chunk_offset << ++ YAFFS_TNODES_INTERNAL_BITS) ++ + i); ++ if (all_done) { ++ yaffs_free_tnode(dev, ++ tn->internal[i]); ++ tn->internal[i] = NULL; ++ } else { ++ /* Can this happen? */ ++ } ++ } ++ } ++ return (all_done) ? 1 : 0; ++ } ++ ++ /* level 0 */ ++ for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0; i--) { ++ the_chunk = yaffs_get_group_base(dev, tn, i); ++ if (the_chunk) { ++ yaffs_soft_del_chunk(dev, the_chunk); ++ yaffs_load_tnode_0(dev, tn, i, 0); ++ } ++ } ++ return 1; ++} ++ ++static void yaffs_remove_obj_from_dir(struct yaffs_obj *obj) ++{ ++ struct yaffs_dev *dev = obj->my_dev; ++ struct yaffs_obj *parent; ++ ++ yaffs_verify_obj_in_dir(obj); ++ parent = obj->parent; ++ ++ yaffs_verify_dir(parent); ++ ++ if (dev && dev->param.remove_obj_fn) ++ dev->param.remove_obj_fn(obj); ++ ++ list_del_init(&obj->siblings); ++ obj->parent = NULL; ++ ++ yaffs_verify_dir(parent); ++} ++ ++void yaffs_add_obj_to_dir(struct yaffs_obj *directory, struct yaffs_obj *obj) ++{ ++ if (!directory) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "tragedy: Trying to add an object to a null pointer directory" ++ ); ++ BUG(); ++ return; ++ } ++ if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "tragedy: Trying to add an object to a non-directory" ++ ); ++ BUG(); ++ } ++ ++ if (obj->siblings.prev == NULL) { ++ /* Not initialised */ ++ BUG(); ++ } ++ ++ yaffs_verify_dir(directory); ++ ++ yaffs_remove_obj_from_dir(obj); ++ ++ /* Now add it */ ++ list_add(&obj->siblings, &directory->variant.dir_variant.children); ++ obj->parent = directory; ++ ++ if (directory == obj->my_dev->unlinked_dir ++ || directory == obj->my_dev->del_dir) { ++ obj->unlinked = 1; ++ obj->my_dev->n_unlinked_files++; ++ obj->rename_allowed = 0; ++ } ++ ++ yaffs_verify_dir(directory); ++ yaffs_verify_obj_in_dir(obj); ++} ++ ++static int yaffs_change_obj_name(struct yaffs_obj *obj, ++ struct yaffs_obj *new_dir, ++ const YCHAR *new_name, int force, int shadows) ++{ ++ int unlink_op; ++ int del_op; ++ struct yaffs_obj *existing_target; ++ ++ if (new_dir == NULL) ++ new_dir = obj->parent; /* use the old directory */ ++ ++ if (new_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "tragedy: yaffs_change_obj_name: new_dir is not a directory" ++ ); ++ BUG(); ++ } ++ ++ unlink_op = (new_dir == obj->my_dev->unlinked_dir); ++ del_op = (new_dir == obj->my_dev->del_dir); ++ ++ existing_target = yaffs_find_by_name(new_dir, new_name); ++ ++ /* If the object is a file going into the unlinked directory, ++ * then it is OK to just stuff it in since duplicate names are OK. ++ * else only proceed if the new name does not exist and we're putting ++ * it into a directory. ++ */ ++ if (!(unlink_op || del_op || force || ++ shadows > 0 || !existing_target) || ++ new_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) ++ return YAFFS_FAIL; ++ ++ yaffs_set_obj_name(obj, new_name); ++ obj->dirty = 1; ++ yaffs_add_obj_to_dir(new_dir, obj); ++ ++ if (unlink_op) ++ obj->unlinked = 1; ++ ++ /* If it is a deletion then we mark it as a shrink for gc */ ++ if (yaffs_update_oh(obj, new_name, 0, del_op, shadows, NULL) >= 0) ++ return YAFFS_OK; ++ ++ return YAFFS_FAIL; ++} ++ ++/*------------------------ Short Operations Cache ------------------------------ ++ * In many situations where there is no high level buffering a lot of ++ * reads might be short sequential reads, and a lot of writes may be short ++ * sequential writes. eg. scanning/writing a jpeg file. ++ * In these cases, a short read/write cache can provide a huge perfomance ++ * benefit with dumb-as-a-rock code. ++ * In Linux, the page cache provides read buffering and the short op cache ++ * provides write buffering. ++ * ++ * There are a small number (~10) of cache chunks per device so that we don't ++ * need a very intelligent search. ++ */ ++ ++static int yaffs_obj_cache_dirty(struct yaffs_obj *obj) ++{ ++ struct yaffs_dev *dev = obj->my_dev; ++ int i; ++ struct yaffs_cache *cache; ++ int n_caches = obj->my_dev->param.n_caches; ++ ++ for (i = 0; i < n_caches; i++) { ++ cache = &dev->cache[i]; ++ if (cache->object == obj && cache->dirty) ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static void yaffs_flush_single_cache(struct yaffs_cache *cache, int discard) ++{ ++ ++ if (!cache || cache->locked) ++ return; ++ ++ /* Write it out and free it up if need be.*/ ++ if (cache->dirty) { ++ yaffs_wr_data_obj(cache->object, ++ cache->chunk_id, ++ cache->data, ++ cache->n_bytes, ++ 1); ++ ++ cache->dirty = 0; ++ } ++ ++ if (discard) ++ cache->object = NULL; ++} ++ ++static void yaffs_flush_file_cache(struct yaffs_obj *obj, int discard) ++{ ++ struct yaffs_dev *dev = obj->my_dev; ++ int i; ++ struct yaffs_cache *cache; ++ int n_caches = obj->my_dev->param.n_caches; ++ ++ if (n_caches < 1) ++ return; ++ ++ ++ /* Find the chunks for this object and flush them. */ ++ for (i = 0; i < n_caches; i++) { ++ cache = &dev->cache[i]; ++ if (cache->object == obj) ++ yaffs_flush_single_cache(cache, discard); ++ } ++ ++} ++ ++ ++void yaffs_flush_whole_cache(struct yaffs_dev *dev, int discard) ++{ ++ struct yaffs_obj *obj; ++ int n_caches = dev->param.n_caches; ++ int i; ++ ++ /* Find a dirty object in the cache and flush it... ++ * until there are no further dirty objects. ++ */ ++ do { ++ obj = NULL; ++ for (i = 0; i < n_caches && !obj; i++) { ++ if (dev->cache[i].object && dev->cache[i].dirty) ++ obj = dev->cache[i].object; ++ } ++ if (obj) ++ yaffs_flush_file_cache(obj, discard); ++ } while (obj); ++ ++} ++ ++/* Grab us an unused cache chunk for use. ++ * First look for an empty one. ++ * Then look for the least recently used non-dirty one. ++ * Then look for the least recently used dirty one...., flush and look again. ++ */ ++static struct yaffs_cache *yaffs_grab_chunk_worker(struct yaffs_dev *dev) ++{ ++ u32 i; ++ ++ if (dev->param.n_caches > 0) { ++ for (i = 0; i < dev->param.n_caches; i++) { ++ if (!dev->cache[i].object) ++ return &dev->cache[i]; ++ } ++ } ++ ++ return NULL; ++} ++ ++static struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev) ++{ ++ struct yaffs_cache *cache; ++ int usage; ++ u32 i; ++ ++ if (dev->param.n_caches < 1) ++ return NULL; ++ ++ /* First look for an unused cache */ ++ ++ cache = yaffs_grab_chunk_worker(dev); ++ ++ if (cache) ++ return cache; ++ ++ /* ++ * Thery were all in use. ++ * Find the LRU cache and flush it if it is dirty. ++ */ ++ ++ usage = -1; ++ cache = NULL; ++ ++ for (i = 0; i < dev->param.n_caches; i++) { ++ if (dev->cache[i].object && ++ !dev->cache[i].locked && ++ (dev->cache[i].last_use < usage || !cache)) { ++ usage = dev->cache[i].last_use; ++ cache = &dev->cache[i]; ++ } ++ } ++ ++#if 1 ++ yaffs_flush_single_cache(cache, 1); ++#else ++ yaffs_flush_file_cache(cache->object, 1); ++ cache = yaffs_grab_chunk_worker(dev); ++#endif ++ ++ return cache; ++} ++ ++/* Find a cached chunk */ ++static struct yaffs_cache *yaffs_find_chunk_cache(const struct yaffs_obj *obj, ++ int chunk_id) ++{ ++ struct yaffs_dev *dev = obj->my_dev; ++ u32 i; ++ ++ if (dev->param.n_caches < 1) ++ return NULL; ++ ++ for (i = 0; i < dev->param.n_caches; i++) { ++ if (dev->cache[i].object == obj && ++ dev->cache[i].chunk_id == chunk_id) { ++ dev->cache_hits++; ++ ++ return &dev->cache[i]; ++ } ++ } ++ return NULL; ++} ++ ++/* Mark the chunk for the least recently used algorithym */ ++static void yaffs_use_cache(struct yaffs_dev *dev, struct yaffs_cache *cache, ++ int is_write) ++{ ++ u32 i; ++ ++ if (dev->param.n_caches < 1) ++ return; ++ ++ if (dev->cache_last_use < 0 || ++ dev->cache_last_use > 100000000) { ++ /* Reset the cache usages */ ++ for (i = 1; i < dev->param.n_caches; i++) ++ dev->cache[i].last_use = 0; ++ ++ dev->cache_last_use = 0; ++ } ++ dev->cache_last_use++; ++ cache->last_use = dev->cache_last_use; ++ ++ if (is_write) ++ cache->dirty = 1; ++} ++ ++/* Invalidate a single cache page. ++ * Do this when a whole page gets written, ++ * ie the short cache for this page is no longer valid. ++ */ ++static void yaffs_invalidate_chunk_cache(struct yaffs_obj *object, int chunk_id) ++{ ++ struct yaffs_cache *cache; ++ ++ if (object->my_dev->param.n_caches > 0) { ++ cache = yaffs_find_chunk_cache(object, chunk_id); ++ ++ if (cache) ++ cache->object = NULL; ++ } ++} ++ ++/* Invalidate all the cache pages associated with this object ++ * Do this whenever ther file is deleted or resized. ++ */ ++static void yaffs_invalidate_whole_cache(struct yaffs_obj *in) ++{ ++ u32 i; ++ struct yaffs_dev *dev = in->my_dev; ++ ++ if (dev->param.n_caches > 0) { ++ /* Invalidate it. */ ++ for (i = 0; i < dev->param.n_caches; i++) { ++ if (dev->cache[i].object == in) ++ dev->cache[i].object = NULL; ++ } ++ } ++} ++ ++static void yaffs_unhash_obj(struct yaffs_obj *obj) ++{ ++ int bucket; ++ struct yaffs_dev *dev = obj->my_dev; ++ ++ /* If it is still linked into the bucket list, free from the list */ ++ if (!list_empty(&obj->hash_link)) { ++ list_del_init(&obj->hash_link); ++ bucket = yaffs_hash_fn(obj->obj_id); ++ dev->obj_bucket[bucket].count--; ++ } ++} ++ ++/* FreeObject frees up a Object and puts it back on the free list */ ++static void yaffs_free_obj(struct yaffs_obj *obj) ++{ ++ struct yaffs_dev *dev; ++ ++ if (!obj) { ++ BUG(); ++ return; ++ } ++ dev = obj->my_dev; ++ yaffs_trace(YAFFS_TRACE_OS, "FreeObject %p inode %p", ++ obj, obj->my_inode); ++ if (obj->parent) ++ BUG(); ++ if (!list_empty(&obj->siblings)) ++ BUG(); ++ ++ if (obj->my_inode) { ++ /* We're still hooked up to a cached inode. ++ * Don't delete now, but mark for later deletion ++ */ ++ obj->defered_free = 1; ++ return; ++ } ++ ++ yaffs_unhash_obj(obj); ++ ++ yaffs_free_raw_obj(dev, obj); ++ dev->n_obj--; ++ dev->checkpoint_blocks_required = 0; /* force recalculation */ ++} ++ ++void yaffs_handle_defered_free(struct yaffs_obj *obj) ++{ ++ if (obj->defered_free) ++ yaffs_free_obj(obj); ++} ++ ++static int yaffs_generic_obj_del(struct yaffs_obj *in) ++{ ++ /* Iinvalidate the file's data in the cache, without flushing. */ ++ yaffs_invalidate_whole_cache(in); ++ ++ if (in->my_dev->param.is_yaffs2 && in->parent != in->my_dev->del_dir) { ++ /* Move to unlinked directory so we have a deletion record */ ++ yaffs_change_obj_name(in, in->my_dev->del_dir, _Y("deleted"), 0, ++ 0); ++ } ++ ++ yaffs_remove_obj_from_dir(in); ++ yaffs_chunk_del(in->my_dev, in->hdr_chunk, 1, __LINE__); ++ in->hdr_chunk = 0; ++ ++ yaffs_free_obj(in); ++ return YAFFS_OK; ++ ++} ++ ++static void yaffs_soft_del_file(struct yaffs_obj *obj) ++{ ++ if (!obj->deleted || ++ obj->variant_type != YAFFS_OBJECT_TYPE_FILE || ++ obj->soft_del) ++ return; ++ ++ if (obj->n_data_chunks <= 0) { ++ /* Empty file with no duplicate object headers, ++ * just delete it immediately */ ++ yaffs_free_tnode(obj->my_dev, obj->variant.file_variant.top); ++ obj->variant.file_variant.top = NULL; ++ yaffs_trace(YAFFS_TRACE_TRACING, ++ "yaffs: Deleting empty file %d", ++ obj->obj_id); ++ yaffs_generic_obj_del(obj); ++ } else { ++ yaffs_soft_del_worker(obj, ++ obj->variant.file_variant.top, ++ obj->variant. ++ file_variant.top_level, 0); ++ obj->soft_del = 1; ++ } ++} ++ ++/* Pruning removes any part of the file structure tree that is beyond the ++ * bounds of the file (ie that does not point to chunks). ++ * ++ * A file should only get pruned when its size is reduced. ++ * ++ * Before pruning, the chunks must be pulled from the tree and the ++ * level 0 tnode entries must be zeroed out. ++ * Could also use this for file deletion, but that's probably better handled ++ * by a special case. ++ * ++ * This function is recursive. For levels > 0 the function is called again on ++ * any sub-tree. For level == 0 we just check if the sub-tree has data. ++ * If there is no data in a subtree then it is pruned. ++ */ ++ ++static struct yaffs_tnode *yaffs_prune_worker(struct yaffs_dev *dev, ++ struct yaffs_tnode *tn, u32 level, ++ int del0) ++{ ++ int i; ++ int has_data; ++ ++ if (!tn) ++ return tn; ++ ++ has_data = 0; ++ ++ if (level > 0) { ++ for (i = 0; i < YAFFS_NTNODES_INTERNAL; i++) { ++ if (tn->internal[i]) { ++ tn->internal[i] = ++ yaffs_prune_worker(dev, ++ tn->internal[i], ++ level - 1, ++ (i == 0) ? del0 : 1); ++ } ++ ++ if (tn->internal[i]) ++ has_data++; ++ } ++ } else { ++ int tnode_size_u32 = dev->tnode_size / sizeof(u32); ++ u32 *map = (u32 *) tn; ++ ++ for (i = 0; !has_data && i < tnode_size_u32; i++) { ++ if (map[i]) ++ has_data++; ++ } ++ } ++ ++ if (has_data == 0 && del0) { ++ /* Free and return NULL */ ++ yaffs_free_tnode(dev, tn); ++ tn = NULL; ++ } ++ return tn; ++} ++ ++static int yaffs_prune_tree(struct yaffs_dev *dev, ++ struct yaffs_file_var *file_struct) ++{ ++ int i; ++ int has_data; ++ int done = 0; ++ struct yaffs_tnode *tn; ++ ++ if (file_struct->top_level < 1) ++ return YAFFS_OK; ++ ++ file_struct->top = ++ yaffs_prune_worker(dev, file_struct->top, file_struct->top_level, 0); ++ ++ /* Now we have a tree with all the non-zero branches NULL but ++ * the height is the same as it was. ++ * Let's see if we can trim internal tnodes to shorten the tree. ++ * We can do this if only the 0th element in the tnode is in use ++ * (ie all the non-zero are NULL) ++ */ ++ ++ while (file_struct->top_level && !done) { ++ tn = file_struct->top; ++ ++ has_data = 0; ++ for (i = 1; i < YAFFS_NTNODES_INTERNAL; i++) { ++ if (tn->internal[i]) ++ has_data++; ++ } ++ ++ if (!has_data) { ++ file_struct->top = tn->internal[0]; ++ file_struct->top_level--; ++ yaffs_free_tnode(dev, tn); ++ } else { ++ done = 1; ++ } ++ } ++ ++ return YAFFS_OK; ++} ++ ++/*-------------------- End of File Structure functions.-------------------*/ ++ ++/* alloc_empty_obj gets us a clean Object.*/ ++static struct yaffs_obj *yaffs_alloc_empty_obj(struct yaffs_dev *dev) ++{ ++ struct yaffs_obj *obj = yaffs_alloc_raw_obj(dev); ++ ++ if (!obj) ++ return obj; ++ ++ dev->n_obj++; ++ ++ /* Now sweeten it up... */ ++ ++ memset(obj, 0, sizeof(struct yaffs_obj)); ++ obj->being_created = 1; ++ ++ obj->my_dev = dev; ++ obj->hdr_chunk = 0; ++ obj->variant_type = YAFFS_OBJECT_TYPE_UNKNOWN; ++ INIT_LIST_HEAD(&(obj->hard_links)); ++ INIT_LIST_HEAD(&(obj->hash_link)); ++ INIT_LIST_HEAD(&obj->siblings); ++ ++ /* Now make the directory sane */ ++ if (dev->root_dir) { ++ obj->parent = dev->root_dir; ++ list_add(&(obj->siblings), ++ &dev->root_dir->variant.dir_variant.children); ++ } ++ ++ /* Add it to the lost and found directory. ++ * NB Can't put root or lost-n-found in lost-n-found so ++ * check if lost-n-found exists first ++ */ ++ if (dev->lost_n_found) ++ yaffs_add_obj_to_dir(dev->lost_n_found, obj); ++ ++ obj->being_created = 0; ++ ++ dev->checkpoint_blocks_required = 0; /* force recalculation */ ++ ++ return obj; ++} ++ ++static int yaffs_find_nice_bucket(struct yaffs_dev *dev) ++{ ++ int i; ++ int l = 999; ++ int lowest = 999999; ++ ++ /* Search for the shortest list or one that ++ * isn't too long. ++ */ ++ ++ for (i = 0; i < 10 && lowest > 4; i++) { ++ dev->bucket_finder++; ++ dev->bucket_finder %= YAFFS_NOBJECT_BUCKETS; ++ if (dev->obj_bucket[dev->bucket_finder].count < lowest) { ++ lowest = dev->obj_bucket[dev->bucket_finder].count; ++ l = dev->bucket_finder; ++ } ++ } ++ ++ return l; ++} ++ ++static int yaffs_new_obj_id(struct yaffs_dev *dev) ++{ ++ int bucket = yaffs_find_nice_bucket(dev); ++ int found = 0; ++ struct list_head *i; ++ u32 n = (u32) bucket; ++ ++ /* ++ * Now find an object value that has not already been taken ++ * by scanning the list, incrementing each time by number of buckets. ++ */ ++ while (!found) { ++ found = 1; ++ n += YAFFS_NOBJECT_BUCKETS; ++ list_for_each(i, &dev->obj_bucket[bucket].list) { ++ /* Check if this value is already taken. */ ++ if (i && list_entry(i, struct yaffs_obj, ++ hash_link)->obj_id == n) ++ found = 0; ++ } ++ } ++ return n; ++} ++ ++static void yaffs_hash_obj(struct yaffs_obj *in) ++{ ++ int bucket = yaffs_hash_fn(in->obj_id); ++ struct yaffs_dev *dev = in->my_dev; ++ ++ list_add(&in->hash_link, &dev->obj_bucket[bucket].list); ++ dev->obj_bucket[bucket].count++; ++} ++ ++struct yaffs_obj *yaffs_find_by_number(struct yaffs_dev *dev, u32 number) ++{ ++ int bucket = yaffs_hash_fn(number); ++ struct list_head *i; ++ struct yaffs_obj *in; ++ ++ list_for_each(i, &dev->obj_bucket[bucket].list) { ++ /* Look if it is in the list */ ++ in = list_entry(i, struct yaffs_obj, hash_link); ++ if (in->obj_id == number) { ++ /* Don't show if it is defered free */ ++ if (in->defered_free) ++ return NULL; ++ return in; ++ } ++ } ++ ++ return NULL; ++} ++ ++static struct yaffs_obj *yaffs_new_obj(struct yaffs_dev *dev, int number, ++ enum yaffs_obj_type type) ++{ ++ struct yaffs_obj *the_obj = NULL; ++ struct yaffs_tnode *tn = NULL; ++ ++ if (number < 0) ++ number = yaffs_new_obj_id(dev); ++ ++ if (type == YAFFS_OBJECT_TYPE_FILE) { ++ tn = yaffs_get_tnode(dev); ++ if (!tn) ++ return NULL; ++ } ++ ++ the_obj = yaffs_alloc_empty_obj(dev); ++ if (!the_obj) { ++ if (tn) ++ yaffs_free_tnode(dev, tn); ++ return NULL; ++ } ++ ++ the_obj->fake = 0; ++ the_obj->rename_allowed = 1; ++ the_obj->unlink_allowed = 1; ++ the_obj->obj_id = number; ++ yaffs_hash_obj(the_obj); ++ the_obj->variant_type = type; ++ yaffs_load_current_time(the_obj, 1, 1); ++ ++ switch (type) { ++ case YAFFS_OBJECT_TYPE_FILE: ++ the_obj->variant.file_variant.file_size = 0; ++ the_obj->variant.file_variant.stored_size = 0; ++ the_obj->variant.file_variant.shrink_size = ++ yaffs_max_file_size(dev); ++ the_obj->variant.file_variant.top_level = 0; ++ the_obj->variant.file_variant.top = tn; ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ INIT_LIST_HEAD(&the_obj->variant.dir_variant.children); ++ INIT_LIST_HEAD(&the_obj->variant.dir_variant.dirty); ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ /* No action required */ ++ break; ++ case YAFFS_OBJECT_TYPE_UNKNOWN: ++ /* todo this should not happen */ ++ break; ++ } ++ return the_obj; ++} ++ ++static struct yaffs_obj *yaffs_create_fake_dir(struct yaffs_dev *dev, ++ int number, u32 mode) ++{ ++ ++ struct yaffs_obj *obj = ++ yaffs_new_obj(dev, number, YAFFS_OBJECT_TYPE_DIRECTORY); ++ ++ if (!obj) ++ return NULL; ++ ++ obj->fake = 1; /* it is fake so it might not use NAND */ ++ obj->rename_allowed = 0; ++ obj->unlink_allowed = 0; ++ obj->deleted = 0; ++ obj->unlinked = 0; ++ obj->yst_mode = mode; ++ obj->my_dev = dev; ++ obj->hdr_chunk = 0; /* Not a valid chunk. */ ++ return obj; ++ ++} ++ ++ ++static void yaffs_init_tnodes_and_objs(struct yaffs_dev *dev) ++{ ++ int i; ++ ++ dev->n_obj = 0; ++ dev->n_tnodes = 0; ++ yaffs_init_raw_tnodes_and_objs(dev); ++ ++ for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) { ++ INIT_LIST_HEAD(&dev->obj_bucket[i].list); ++ dev->obj_bucket[i].count = 0; ++ } ++} ++ ++struct yaffs_obj *yaffs_find_or_create_by_number(struct yaffs_dev *dev, ++ int number, ++ enum yaffs_obj_type type) ++{ ++ struct yaffs_obj *the_obj = NULL; ++ ++ if (number > 0) ++ the_obj = yaffs_find_by_number(dev, number); ++ ++ if (!the_obj) ++ the_obj = yaffs_new_obj(dev, number, type); ++ ++ return the_obj; ++ ++} ++ ++YCHAR *yaffs_clone_str(const YCHAR *str) ++{ ++ YCHAR *new_str = NULL; ++ int len; ++ ++ if (!str) ++ str = _Y(""); ++ ++ len = strnlen(str, YAFFS_MAX_ALIAS_LENGTH); ++ new_str = kmalloc((len + 1) * sizeof(YCHAR), GFP_NOFS); ++ if (new_str) { ++ strncpy(new_str, str, len); ++ new_str[len] = 0; ++ } ++ return new_str; ++ ++} ++/* ++ *yaffs_update_parent() handles fixing a directories mtime and ctime when a new ++ * link (ie. name) is created or deleted in the directory. ++ * ++ * ie. ++ * create dir/a : update dir's mtime/ctime ++ * rm dir/a: update dir's mtime/ctime ++ * modify dir/a: don't update dir's mtimme/ctime ++ * ++ * This can be handled immediately or defered. Defering helps reduce the number ++ * of updates when many files in a directory are changed within a brief period. ++ * ++ * If the directory updating is defered then yaffs_update_dirty_dirs must be ++ * called periodically. ++ */ ++ ++static void yaffs_update_parent(struct yaffs_obj *obj) ++{ ++ struct yaffs_dev *dev; ++ ++ if (!obj) ++ return; ++ dev = obj->my_dev; ++ obj->dirty = 1; ++ yaffs_load_current_time(obj, 0, 1); ++ if (dev->param.defered_dir_update) { ++ struct list_head *link = &obj->variant.dir_variant.dirty; ++ ++ if (list_empty(link)) { ++ list_add(link, &dev->dirty_dirs); ++ yaffs_trace(YAFFS_TRACE_BACKGROUND, ++ "Added object %d to dirty directories", ++ obj->obj_id); ++ } ++ ++ } else { ++ yaffs_update_oh(obj, NULL, 0, 0, 0, NULL); ++ } ++} ++ ++void yaffs_update_dirty_dirs(struct yaffs_dev *dev) ++{ ++ struct list_head *link; ++ struct yaffs_obj *obj; ++ struct yaffs_dir_var *d_s; ++ union yaffs_obj_var *o_v; ++ ++ yaffs_trace(YAFFS_TRACE_BACKGROUND, "Update dirty directories"); ++ ++ while (!list_empty(&dev->dirty_dirs)) { ++ link = dev->dirty_dirs.next; ++ list_del_init(link); ++ ++ d_s = list_entry(link, struct yaffs_dir_var, dirty); ++ o_v = list_entry(d_s, union yaffs_obj_var, dir_variant); ++ obj = list_entry(o_v, struct yaffs_obj, variant); ++ ++ yaffs_trace(YAFFS_TRACE_BACKGROUND, "Update directory %d", ++ obj->obj_id); ++ ++ if (obj->dirty) ++ yaffs_update_oh(obj, NULL, 0, 0, 0, NULL); ++ } ++} ++ ++/* ++ * Mknod (create) a new object. ++ * equiv_obj only has meaning for a hard link; ++ * alias_str only has meaning for a symlink. ++ * rdev only has meaning for devices (a subset of special objects) ++ */ ++ ++static struct yaffs_obj *yaffs_create_obj(enum yaffs_obj_type type, ++ struct yaffs_obj *parent, ++ const YCHAR *name, ++ u32 mode, ++ u32 uid, ++ u32 gid, ++ struct yaffs_obj *equiv_obj, ++ const YCHAR *alias_str, u32 rdev) ++{ ++ struct yaffs_obj *in; ++ YCHAR *str = NULL; ++ struct yaffs_dev *dev = parent->my_dev; ++ ++ /* Check if the entry exists. ++ * If it does then fail the call since we don't want a dup. */ ++ if (yaffs_find_by_name(parent, name)) ++ return NULL; ++ ++ if (type == YAFFS_OBJECT_TYPE_SYMLINK) { ++ str = yaffs_clone_str(alias_str); ++ if (!str) ++ return NULL; ++ } ++ ++ in = yaffs_new_obj(dev, -1, type); ++ ++ if (!in) { ++ kfree(str); ++ return NULL; ++ } ++ ++ in->hdr_chunk = 0; ++ in->valid = 1; ++ in->variant_type = type; ++ ++ in->yst_mode = mode; ++ ++ yaffs_attribs_init(in, gid, uid, rdev); ++ ++ in->n_data_chunks = 0; ++ ++ yaffs_set_obj_name(in, name); ++ in->dirty = 1; ++ ++ yaffs_add_obj_to_dir(parent, in); ++ ++ in->my_dev = parent->my_dev; ++ ++ switch (type) { ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ in->variant.symlink_variant.alias = str; ++ break; ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ in->variant.hardlink_variant.equiv_obj = equiv_obj; ++ in->variant.hardlink_variant.equiv_id = equiv_obj->obj_id; ++ list_add(&in->hard_links, &equiv_obj->hard_links); ++ break; ++ case YAFFS_OBJECT_TYPE_FILE: ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ case YAFFS_OBJECT_TYPE_UNKNOWN: ++ /* do nothing */ ++ break; ++ } ++ ++ if (yaffs_update_oh(in, name, 0, 0, 0, NULL) < 0) { ++ /* Could not create the object header, fail */ ++ yaffs_del_obj(in); ++ in = NULL; ++ } ++ ++ if (in) ++ yaffs_update_parent(parent); ++ ++ return in; ++} ++ ++struct yaffs_obj *yaffs_create_file(struct yaffs_obj *parent, ++ const YCHAR *name, u32 mode, u32 uid, ++ u32 gid) ++{ ++ return yaffs_create_obj(YAFFS_OBJECT_TYPE_FILE, parent, name, mode, ++ uid, gid, NULL, NULL, 0); ++} ++ ++struct yaffs_obj *yaffs_create_dir(struct yaffs_obj *parent, const YCHAR *name, ++ u32 mode, u32 uid, u32 gid) ++{ ++ return yaffs_create_obj(YAFFS_OBJECT_TYPE_DIRECTORY, parent, name, ++ mode, uid, gid, NULL, NULL, 0); ++} ++ ++struct yaffs_obj *yaffs_create_special(struct yaffs_obj *parent, ++ const YCHAR *name, u32 mode, u32 uid, ++ u32 gid, u32 rdev) ++{ ++ return yaffs_create_obj(YAFFS_OBJECT_TYPE_SPECIAL, parent, name, mode, ++ uid, gid, NULL, NULL, rdev); ++} ++ ++struct yaffs_obj *yaffs_create_symlink(struct yaffs_obj *parent, ++ const YCHAR *name, u32 mode, u32 uid, ++ u32 gid, const YCHAR *alias) ++{ ++ return yaffs_create_obj(YAFFS_OBJECT_TYPE_SYMLINK, parent, name, mode, ++ uid, gid, NULL, alias, 0); ++} ++ ++/* yaffs_link_obj returns the object id of the equivalent object.*/ ++struct yaffs_obj *yaffs_link_obj(struct yaffs_obj *parent, const YCHAR * name, ++ struct yaffs_obj *equiv_obj) ++{ ++ /* Get the real object in case we were fed a hard link obj */ ++ equiv_obj = yaffs_get_equivalent_obj(equiv_obj); ++ ++ if (yaffs_create_obj(YAFFS_OBJECT_TYPE_HARDLINK, ++ parent, name, 0, 0, 0, ++ equiv_obj, NULL, 0)) ++ return equiv_obj; ++ ++ return NULL; ++ ++} ++ ++ ++ ++/*---------------------- Block Management and Page Allocation -------------*/ ++ ++static void yaffs_deinit_blocks(struct yaffs_dev *dev) ++{ ++ if (dev->block_info_alt && dev->block_info) ++ vfree(dev->block_info); ++ else ++ kfree(dev->block_info); ++ ++ dev->block_info_alt = 0; ++ ++ dev->block_info = NULL; ++ ++ if (dev->chunk_bits_alt && dev->chunk_bits) ++ vfree(dev->chunk_bits); ++ else ++ kfree(dev->chunk_bits); ++ dev->chunk_bits_alt = 0; ++ dev->chunk_bits = NULL; ++} ++ ++static int yaffs_init_blocks(struct yaffs_dev *dev) ++{ ++ int n_blocks = dev->internal_end_block - dev->internal_start_block + 1; ++ ++ dev->block_info = NULL; ++ dev->chunk_bits = NULL; ++ dev->alloc_block = -1; /* force it to get a new one */ ++ ++ /* If the first allocation strategy fails, thry the alternate one */ ++ dev->block_info = ++ kmalloc(n_blocks * sizeof(struct yaffs_block_info), GFP_NOFS); ++ if (!dev->block_info) { ++ dev->block_info = ++ vmalloc(n_blocks * sizeof(struct yaffs_block_info)); ++ dev->block_info_alt = 1; ++ } else { ++ dev->block_info_alt = 0; ++ } ++ ++ if (!dev->block_info) ++ goto alloc_error; ++ ++ /* Set up dynamic blockinfo stuff. Round up bytes. */ ++ dev->chunk_bit_stride = (dev->param.chunks_per_block + 7) / 8; ++ dev->chunk_bits = ++ kmalloc(dev->chunk_bit_stride * n_blocks, GFP_NOFS); ++ if (!dev->chunk_bits) { ++ dev->chunk_bits = ++ vmalloc(dev->chunk_bit_stride * n_blocks); ++ dev->chunk_bits_alt = 1; ++ } else { ++ dev->chunk_bits_alt = 0; ++ } ++ if (!dev->chunk_bits) ++ goto alloc_error; ++ ++ ++ memset(dev->block_info, 0, n_blocks * sizeof(struct yaffs_block_info)); ++ memset(dev->chunk_bits, 0, dev->chunk_bit_stride * n_blocks); ++ return YAFFS_OK; ++ ++alloc_error: ++ yaffs_deinit_blocks(dev); ++ return YAFFS_FAIL; ++} ++ ++ ++void yaffs_block_became_dirty(struct yaffs_dev *dev, int block_no) ++{ ++ struct yaffs_block_info *bi = yaffs_get_block_info(dev, block_no); ++ int erased_ok = 0; ++ u32 i; ++ ++ /* If the block is still healthy erase it and mark as clean. ++ * If the block has had a data failure, then retire it. ++ */ ++ ++ yaffs_trace(YAFFS_TRACE_GC | YAFFS_TRACE_ERASE, ++ "yaffs_block_became_dirty block %d state %d %s", ++ block_no, bi->block_state, ++ (bi->needs_retiring) ? "needs retiring" : ""); ++ ++ yaffs2_clear_oldest_dirty_seq(dev, bi); ++ ++ bi->block_state = YAFFS_BLOCK_STATE_DIRTY; ++ ++ /* If this is the block being garbage collected then stop gc'ing */ ++ if (block_no == (int)dev->gc_block) ++ dev->gc_block = 0; ++ ++ /* If this block is currently the best candidate for gc ++ * then drop as a candidate */ ++ if (block_no == (int)dev->gc_dirtiest) { ++ dev->gc_dirtiest = 0; ++ dev->gc_pages_in_use = 0; ++ } ++ ++ if (!bi->needs_retiring) { ++ yaffs2_checkpt_invalidate(dev); ++ erased_ok = yaffs_erase_block(dev, block_no); ++ if (!erased_ok) { ++ dev->n_erase_failures++; ++ yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS, ++ "**>> Erasure failed %d", block_no); ++ } ++ } ++ ++ /* Verify erasure if needed */ ++ if (erased_ok && ++ ((yaffs_trace_mask & YAFFS_TRACE_ERASE) || ++ !yaffs_skip_verification(dev))) { ++ for (i = 0; i < dev->param.chunks_per_block; i++) { ++ if (!yaffs_check_chunk_erased(dev, ++ block_no * dev->param.chunks_per_block + i)) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ ">>Block %d erasure supposedly OK, but chunk %d not erased", ++ block_no, i); ++ } ++ } ++ } ++ ++ if (!erased_ok) { ++ /* We lost a block of free space */ ++ dev->n_free_chunks -= dev->param.chunks_per_block; ++ yaffs_retire_block(dev, block_no); ++ yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS, ++ "**>> Block %d retired", block_no); ++ return; ++ } ++ ++ /* Clean it up... */ ++ bi->block_state = YAFFS_BLOCK_STATE_EMPTY; ++ bi->seq_number = 0; ++ dev->n_erased_blocks++; ++ bi->pages_in_use = 0; ++ bi->soft_del_pages = 0; ++ bi->has_shrink_hdr = 0; ++ bi->skip_erased_check = 1; /* Clean, so no need to check */ ++ bi->gc_prioritise = 0; ++ bi->has_summary = 0; ++ ++ yaffs_clear_chunk_bits(dev, block_no); ++ ++ yaffs_trace(YAFFS_TRACE_ERASE, "Erased block %d", block_no); ++} ++ ++static inline int yaffs_gc_process_chunk(struct yaffs_dev *dev, ++ struct yaffs_block_info *bi, ++ int old_chunk, u8 *buffer) ++{ ++ int new_chunk; ++ int mark_flash = 1; ++ struct yaffs_ext_tags tags; ++ struct yaffs_obj *object; ++ int matching_chunk; ++ int ret_val = YAFFS_OK; ++ ++ memset(&tags, 0, sizeof(tags)); ++ yaffs_rd_chunk_tags_nand(dev, old_chunk, ++ buffer, &tags); ++ object = yaffs_find_by_number(dev, tags.obj_id); ++ ++ yaffs_trace(YAFFS_TRACE_GC_DETAIL, ++ "Collecting chunk in block %d, %d %d %d ", ++ dev->gc_chunk, tags.obj_id, ++ tags.chunk_id, tags.n_bytes); ++ ++ if (object && !yaffs_skip_verification(dev)) { ++ if (tags.chunk_id == 0) ++ matching_chunk = ++ object->hdr_chunk; ++ else if (object->soft_del) ++ /* Defeat the test */ ++ matching_chunk = old_chunk; ++ else ++ matching_chunk = ++ yaffs_find_chunk_in_file ++ (object, tags.chunk_id, ++ NULL); ++ ++ if (old_chunk != matching_chunk) ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "gc: page in gc mismatch: %d %d %d %d", ++ old_chunk, ++ matching_chunk, ++ tags.obj_id, ++ tags.chunk_id); ++ } ++ ++ if (!object) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "page %d in gc has no object: %d %d %d ", ++ old_chunk, ++ tags.obj_id, tags.chunk_id, ++ tags.n_bytes); ++ } ++ ++ if (object && ++ object->deleted && ++ object->soft_del && tags.chunk_id != 0) { ++ /* Data chunk in a soft deleted file, ++ * throw it away. ++ * It's a soft deleted data chunk, ++ * No need to copy this, just forget ++ * about it and fix up the object. ++ */ ++ ++ /* Free chunks already includes ++ * softdeleted chunks, how ever this ++ * chunk is going to soon be really ++ * deleted which will increment free ++ * chunks. We have to decrement free ++ * chunks so this works out properly. ++ */ ++ dev->n_free_chunks--; ++ bi->soft_del_pages--; ++ ++ object->n_data_chunks--; ++ if (object->n_data_chunks <= 0) { ++ /* remeber to clean up obj */ ++ dev->gc_cleanup_list[dev->n_clean_ups] = tags.obj_id; ++ dev->n_clean_ups++; ++ } ++ mark_flash = 0; ++ } else if (object) { ++ /* It's either a data chunk in a live ++ * file or an ObjectHeader, so we're ++ * interested in it. ++ * NB Need to keep the ObjectHeaders of ++ * deleted files until the whole file ++ * has been deleted off ++ */ ++ tags.serial_number++; ++ dev->n_gc_copies++; ++ ++ if (tags.chunk_id == 0) { ++ /* It is an object Id, ++ * We need to nuke the shrinkheader flags since its ++ * work is done. ++ * Also need to clean up shadowing. ++ * NB We don't want to do all the work of translating ++ * object header endianism back and forth so we leave ++ * the oh endian in its stored order. ++ */ ++ ++ struct yaffs_obj_hdr *oh; ++ oh = (struct yaffs_obj_hdr *) buffer; ++ ++ oh->is_shrink = 0; ++ tags.extra_is_shrink = 0; ++ oh->shadows_obj = 0; ++ oh->inband_shadowed_obj_id = 0; ++ tags.extra_shadows = 0; ++ ++ /* Update file size */ ++ if (object->variant_type == YAFFS_OBJECT_TYPE_FILE) { ++ yaffs_oh_size_load(dev, oh, ++ object->variant.file_variant.stored_size, 1); ++ tags.extra_file_size = ++ object->variant.file_variant.stored_size; ++ } ++ ++ yaffs_verify_oh(object, oh, &tags, 1); ++ new_chunk = ++ yaffs_write_new_chunk(dev, (u8 *) oh, &tags, 1); ++ } else { ++ new_chunk = ++ yaffs_write_new_chunk(dev, buffer, &tags, 1); ++ } ++ ++ if (new_chunk < 0) { ++ ret_val = YAFFS_FAIL; ++ } else { ++ ++ /* Now fix up the Tnodes etc. */ ++ ++ if (tags.chunk_id == 0) { ++ /* It's a header */ ++ object->hdr_chunk = new_chunk; ++ object->serial = tags.serial_number; ++ } else { ++ /* It's a data chunk */ ++ yaffs_put_chunk_in_file(object, tags.chunk_id, ++ new_chunk, 0); ++ } ++ } ++ } ++ if (ret_val == YAFFS_OK) ++ yaffs_chunk_del(dev, old_chunk, mark_flash, __LINE__); ++ return ret_val; ++} ++ ++static int yaffs_gc_block(struct yaffs_dev *dev, int block, int whole_block) ++{ ++ int old_chunk; ++ int ret_val = YAFFS_OK; ++ u32 i; ++ int is_checkpt_block; ++ int max_copies; ++ int chunks_before = yaffs_get_erased_chunks(dev); ++ int chunks_after; ++ struct yaffs_block_info *bi = yaffs_get_block_info(dev, block); ++ ++ is_checkpt_block = (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT); ++ ++ yaffs_trace(YAFFS_TRACE_TRACING, ++ "Collecting block %d, in use %d, shrink %d, whole_block %d", ++ block, bi->pages_in_use, bi->has_shrink_hdr, ++ whole_block); ++ ++ /*yaffs_verify_free_chunks(dev); */ ++ ++ if (bi->block_state == YAFFS_BLOCK_STATE_FULL) ++ bi->block_state = YAFFS_BLOCK_STATE_COLLECTING; ++ ++ bi->has_shrink_hdr = 0; /* clear the flag so that the block can erase */ ++ ++ dev->gc_disable = 1; ++ ++ yaffs_summary_gc(dev, block); ++ ++ if (is_checkpt_block || !yaffs_still_some_chunks(dev, block)) { ++ yaffs_trace(YAFFS_TRACE_TRACING, ++ "Collecting block %d that has no chunks in use", ++ block); ++ yaffs_block_became_dirty(dev, block); ++ } else { ++ ++ u8 *buffer = yaffs_get_temp_buffer(dev); ++ ++ yaffs_verify_blk(dev, bi, block); ++ ++ max_copies = (whole_block) ? dev->param.chunks_per_block : 5; ++ old_chunk = block * dev->param.chunks_per_block + dev->gc_chunk; ++ ++ for (/* init already done */ ; ++ ret_val == YAFFS_OK && ++ dev->gc_chunk < dev->param.chunks_per_block && ++ (bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) && ++ max_copies > 0; ++ dev->gc_chunk++, old_chunk++) { ++ if (yaffs_check_chunk_bit(dev, block, dev->gc_chunk)) { ++ /* Page is in use and might need to be copied */ ++ max_copies--; ++ ret_val = yaffs_gc_process_chunk(dev, bi, ++ old_chunk, buffer); ++ } ++ } ++ yaffs_release_temp_buffer(dev, buffer); ++ } ++ ++ yaffs_verify_collected_blk(dev, bi, block); ++ ++ if (bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) { ++ /* ++ * The gc did not complete. Set block state back to FULL ++ * because checkpointing does not restore gc. ++ */ ++ bi->block_state = YAFFS_BLOCK_STATE_FULL; ++ } else { ++ /* The gc completed. */ ++ /* Do any required cleanups */ ++ for (i = 0; i < dev->n_clean_ups; i++) { ++ /* Time to delete the file too */ ++ struct yaffs_obj *object = ++ yaffs_find_by_number(dev, dev->gc_cleanup_list[i]); ++ if (object) { ++ yaffs_free_tnode(dev, ++ object->variant.file_variant.top); ++ object->variant.file_variant.top = NULL; ++ yaffs_trace(YAFFS_TRACE_GC, ++ "yaffs: About to finally delete object %d", ++ object->obj_id); ++ yaffs_generic_obj_del(object); ++ object->my_dev->n_deleted_files--; ++ } ++ ++ } ++ chunks_after = yaffs_get_erased_chunks(dev); ++ if (chunks_before >= chunks_after) ++ yaffs_trace(YAFFS_TRACE_GC, ++ "gc did not increase free chunks before %d after %d", ++ chunks_before, chunks_after); ++ dev->gc_block = 0; ++ dev->gc_chunk = 0; ++ dev->n_clean_ups = 0; ++ } ++ ++ dev->gc_disable = 0; ++ ++ return ret_val; ++} ++ ++/* ++ * find_gc_block() selects the dirtiest block (or close enough) ++ * for garbage collection. ++ */ ++ ++static unsigned yaffs_find_gc_block(struct yaffs_dev *dev, ++ int aggressive, int background) ++{ ++ u32 i; ++ u32 iterations; ++ u32 selected = 0; ++ int prioritised = 0; ++ int prioritised_exist = 0; ++ struct yaffs_block_info *bi; ++ u32 threshold; ++ ++ /* First let's see if we need to grab a prioritised block */ ++ if (dev->has_pending_prioritised_gc && !aggressive) { ++ dev->gc_dirtiest = 0; ++ bi = dev->block_info; ++ for (i = dev->internal_start_block; ++ i <= dev->internal_end_block && !selected; i++) { ++ ++ if (bi->gc_prioritise) { ++ prioritised_exist = 1; ++ if (bi->block_state == YAFFS_BLOCK_STATE_FULL && ++ yaffs_block_ok_for_gc(dev, bi)) { ++ selected = i; ++ prioritised = 1; ++ } ++ } ++ bi++; ++ } ++ ++ /* ++ * If there is a prioritised block and none was selected then ++ * this happened because there is at least one old dirty block ++ * gumming up the works. Let's gc the oldest dirty block. ++ */ ++ ++ if (prioritised_exist && ++ !selected && dev->oldest_dirty_block > 0) ++ selected = dev->oldest_dirty_block; ++ ++ if (!prioritised_exist) /* None found, so we can clear this */ ++ dev->has_pending_prioritised_gc = 0; ++ } ++ ++ /* If we're doing aggressive GC then we are happy to take a less-dirty ++ * block, and search harder. ++ * else (leasurely gc), then we only bother to do this if the ++ * block has only a few pages in use. ++ */ ++ ++ if (!selected) { ++ u32 pages_used; ++ int n_blocks = ++ dev->internal_end_block - dev->internal_start_block + 1; ++ if (aggressive) { ++ threshold = dev->param.chunks_per_block; ++ iterations = n_blocks; ++ } else { ++ u32 max_threshold; ++ ++ if (background) ++ max_threshold = dev->param.chunks_per_block / 2; ++ else ++ max_threshold = dev->param.chunks_per_block / 8; ++ ++ if (max_threshold < YAFFS_GC_PASSIVE_THRESHOLD) ++ max_threshold = YAFFS_GC_PASSIVE_THRESHOLD; ++ ++ threshold = background ? (dev->gc_not_done + 2) * 2 : 0; ++ if (threshold < YAFFS_GC_PASSIVE_THRESHOLD) ++ threshold = YAFFS_GC_PASSIVE_THRESHOLD; ++ if (threshold > max_threshold) ++ threshold = max_threshold; ++ ++ iterations = n_blocks / 16 + 1; ++ if (iterations > 100) ++ iterations = 100; ++ } ++ ++ for (i = 0; ++ i < iterations && ++ (dev->gc_dirtiest < 1 || ++ dev->gc_pages_in_use > YAFFS_GC_GOOD_ENOUGH); ++ i++) { ++ dev->gc_block_finder++; ++ if (dev->gc_block_finder < dev->internal_start_block || ++ dev->gc_block_finder > dev->internal_end_block) ++ dev->gc_block_finder = ++ dev->internal_start_block; ++ ++ bi = yaffs_get_block_info(dev, dev->gc_block_finder); ++ ++ pages_used = bi->pages_in_use - bi->soft_del_pages; ++ ++ if (bi->block_state == YAFFS_BLOCK_STATE_FULL && ++ pages_used < dev->param.chunks_per_block && ++ (dev->gc_dirtiest < 1 || ++ pages_used < dev->gc_pages_in_use) && ++ yaffs_block_ok_for_gc(dev, bi)) { ++ dev->gc_dirtiest = dev->gc_block_finder; ++ dev->gc_pages_in_use = pages_used; ++ } ++ } ++ ++ if (dev->gc_dirtiest > 0 && dev->gc_pages_in_use <= threshold) ++ selected = dev->gc_dirtiest; ++ } ++ ++ /* ++ * If nothing has been selected for a while, try the oldest dirty ++ * because that's gumming up the works. ++ */ ++ ++ if (!selected && dev->param.is_yaffs2 && ++ dev->gc_not_done >= (background ? 10 : 20)) { ++ yaffs2_find_oldest_dirty_seq(dev); ++ if (dev->oldest_dirty_block > 0) { ++ selected = dev->oldest_dirty_block; ++ dev->gc_dirtiest = selected; ++ dev->oldest_dirty_gc_count++; ++ bi = yaffs_get_block_info(dev, selected); ++ dev->gc_pages_in_use = ++ bi->pages_in_use - bi->soft_del_pages; ++ } else { ++ dev->gc_not_done = 0; ++ } ++ } ++ ++ if (selected) { ++ yaffs_trace(YAFFS_TRACE_GC, ++ "GC Selected block %d with %d free, prioritised:%d", ++ selected, ++ dev->param.chunks_per_block - dev->gc_pages_in_use, ++ prioritised); ++ ++ dev->n_gc_blocks++; ++ if (background) ++ dev->bg_gcs++; ++ ++ dev->gc_dirtiest = 0; ++ dev->gc_pages_in_use = 0; ++ dev->gc_not_done = 0; ++ if (dev->refresh_skip > 0) ++ dev->refresh_skip--; ++ } else { ++ dev->gc_not_done++; ++ yaffs_trace(YAFFS_TRACE_GC, ++ "GC none: finder %d skip %d threshold %d dirtiest %d using %d oldest %d%s", ++ dev->gc_block_finder, dev->gc_not_done, threshold, ++ dev->gc_dirtiest, dev->gc_pages_in_use, ++ dev->oldest_dirty_block, background ? " bg" : ""); ++ } ++ ++ return selected; ++} ++ ++/* New garbage collector ++ * If we're very low on erased blocks then we do aggressive garbage collection ++ * otherwise we do "leasurely" garbage collection. ++ * Aggressive gc looks further (whole array) and will accept less dirty blocks. ++ * Passive gc only inspects smaller areas and only accepts more dirty blocks. ++ * ++ * The idea is to help clear out space in a more spread-out manner. ++ * Dunno if it really does anything useful. ++ */ ++static int yaffs_check_gc(struct yaffs_dev *dev, int background) ++{ ++ int aggressive = 0; ++ int gc_ok = YAFFS_OK; ++ int max_tries = 0; ++ int min_erased; ++ int erased_chunks; ++ int checkpt_block_adjust; ++ ++ if (dev->param.gc_control_fn && ++ (dev->param.gc_control_fn(dev) & 1) == 0) ++ return YAFFS_OK; ++ ++ if (dev->gc_disable) ++ /* Bail out so we don't get recursive gc */ ++ return YAFFS_OK; ++ ++ /* This loop should pass the first time. ++ * Only loops here if the collection does not increase space. ++ */ ++ ++ do { ++ max_tries++; ++ ++ checkpt_block_adjust = yaffs_calc_checkpt_blocks_required(dev); ++ ++ min_erased = ++ dev->param.n_reserved_blocks + checkpt_block_adjust + 1; ++ erased_chunks = ++ dev->n_erased_blocks * dev->param.chunks_per_block; ++ ++ /* If we need a block soon then do aggressive gc. */ ++ if (dev->n_erased_blocks < min_erased) ++ aggressive = 1; ++ else { ++ if (!background ++ && erased_chunks > (dev->n_free_chunks / 4)) ++ break; ++ ++ if (dev->gc_skip > 20) ++ dev->gc_skip = 20; ++ if (erased_chunks < dev->n_free_chunks / 2 || ++ dev->gc_skip < 1 || background) ++ aggressive = 0; ++ else { ++ dev->gc_skip--; ++ break; ++ } ++ } ++ ++ dev->gc_skip = 5; ++ ++ /* If we don't already have a block being gc'd then see if we ++ * should start another */ ++ ++ if (dev->gc_block < 1 && !aggressive) { ++ dev->gc_block = yaffs2_find_refresh_block(dev); ++ dev->gc_chunk = 0; ++ dev->n_clean_ups = 0; ++ } ++ if (dev->gc_block < 1) { ++ dev->gc_block = ++ yaffs_find_gc_block(dev, aggressive, background); ++ dev->gc_chunk = 0; ++ dev->n_clean_ups = 0; ++ } ++ ++ if (dev->gc_block > 0) { ++ dev->all_gcs++; ++ if (!aggressive) ++ dev->passive_gc_count++; ++ ++ yaffs_trace(YAFFS_TRACE_GC, ++ "yaffs: GC n_erased_blocks %d aggressive %d", ++ dev->n_erased_blocks, aggressive); ++ ++ gc_ok = yaffs_gc_block(dev, dev->gc_block, aggressive); ++ } ++ ++ if (dev->n_erased_blocks < (int)dev->param.n_reserved_blocks && ++ dev->gc_block > 0) { ++ yaffs_trace(YAFFS_TRACE_GC, ++ "yaffs: GC !!!no reclaim!!! n_erased_blocks %d after try %d block %d", ++ dev->n_erased_blocks, max_tries, ++ dev->gc_block); ++ } ++ } while ((dev->n_erased_blocks < (int)dev->param.n_reserved_blocks) && ++ (dev->gc_block > 0) && (max_tries < 2)); ++ ++ return aggressive ? gc_ok : YAFFS_OK; ++} ++ ++/* ++ * yaffs_bg_gc() ++ * Garbage collects. Intended to be called from a background thread. ++ * Returns non-zero if at least half the free chunks are erased. ++ */ ++int yaffs_bg_gc(struct yaffs_dev *dev, unsigned urgency) ++{ ++ int erased_chunks = dev->n_erased_blocks * dev->param.chunks_per_block; ++ ++ yaffs_trace(YAFFS_TRACE_BACKGROUND, "Background gc %u", urgency); ++ ++ yaffs_check_gc(dev, 1); ++ return erased_chunks > dev->n_free_chunks / 2; ++} ++ ++/*-------------------- Data file manipulation -----------------*/ ++ ++static int yaffs_rd_data_obj(struct yaffs_obj *in, int inode_chunk, u8 * buffer) ++{ ++ int nand_chunk = yaffs_find_chunk_in_file(in, inode_chunk, NULL); ++ ++ if (nand_chunk >= 0) ++ return yaffs_rd_chunk_tags_nand(in->my_dev, nand_chunk, ++ buffer, NULL); ++ else { ++ yaffs_trace(YAFFS_TRACE_NANDACCESS, ++ "Chunk %d not found zero instead", ++ nand_chunk); ++ /* get sane (zero) data if you read a hole */ ++ memset(buffer, 0, in->my_dev->data_bytes_per_chunk); ++ return 0; ++ } ++ ++} ++ ++void yaffs_chunk_del(struct yaffs_dev *dev, int chunk_id, int mark_flash, ++ int lyn) ++{ ++ int block; ++ int page; ++ struct yaffs_ext_tags tags; ++ struct yaffs_block_info *bi; ++ ++ if (chunk_id <= 0) ++ return; ++ ++ dev->n_deletions++; ++ block = chunk_id / dev->param.chunks_per_block; ++ page = chunk_id % dev->param.chunks_per_block; ++ ++ if (!yaffs_check_chunk_bit(dev, block, page)) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Deleting invalid chunk %d", chunk_id); ++ ++ bi = yaffs_get_block_info(dev, block); ++ ++ yaffs2_update_oldest_dirty_seq(dev, block, bi); ++ ++ yaffs_trace(YAFFS_TRACE_DELETION, ++ "line %d delete of chunk %d", ++ lyn, chunk_id); ++ ++ if (!dev->param.is_yaffs2 && mark_flash && ++ bi->block_state != YAFFS_BLOCK_STATE_COLLECTING) { ++ ++ memset(&tags, 0, sizeof(tags)); ++ tags.is_deleted = 1; ++ yaffs_wr_chunk_tags_nand(dev, chunk_id, NULL, &tags); ++ yaffs_handle_chunk_update(dev, chunk_id, &tags); ++ } else { ++ dev->n_unmarked_deletions++; ++ } ++ ++ /* Pull out of the management area. ++ * If the whole block became dirty, this will kick off an erasure. ++ */ ++ if (bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING || ++ bi->block_state == YAFFS_BLOCK_STATE_FULL || ++ bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN || ++ bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) { ++ dev->n_free_chunks++; ++ yaffs_clear_chunk_bit(dev, block, page); ++ bi->pages_in_use--; ++ ++ if (bi->pages_in_use == 0 && ++ !bi->has_shrink_hdr && ++ bi->block_state != YAFFS_BLOCK_STATE_ALLOCATING && ++ bi->block_state != YAFFS_BLOCK_STATE_NEEDS_SCAN) { ++ yaffs_block_became_dirty(dev, block); ++ } ++ } ++} ++ ++static int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk, ++ const u8 *buffer, int n_bytes, int use_reserve) ++{ ++ /* Find old chunk Need to do this to get serial number ++ * Write new one and patch into tree. ++ * Invalidate old tags. ++ */ ++ ++ int prev_chunk_id; ++ struct yaffs_ext_tags prev_tags; ++ int new_chunk_id; ++ struct yaffs_ext_tags new_tags; ++ struct yaffs_dev *dev = in->my_dev; ++ loff_t endpos; ++ ++ yaffs_check_gc(dev, 0); ++ ++ /* Get the previous chunk at this location in the file if it exists. ++ * If it does not exist then put a zero into the tree. This creates ++ * the tnode now, rather than later when it is harder to clean up. ++ */ ++ prev_chunk_id = yaffs_find_chunk_in_file(in, inode_chunk, &prev_tags); ++ if (prev_chunk_id < 1 && ++ !yaffs_put_chunk_in_file(in, inode_chunk, 0, 0)) ++ return 0; ++ ++ /* Set up new tags */ ++ memset(&new_tags, 0, sizeof(new_tags)); ++ ++ new_tags.chunk_id = inode_chunk; ++ new_tags.obj_id = in->obj_id; ++ new_tags.serial_number = ++ (prev_chunk_id > 0) ? prev_tags.serial_number + 1 : 1; ++ new_tags.n_bytes = n_bytes; ++ ++ if (n_bytes < 1 || n_bytes > (int)dev->data_bytes_per_chunk) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "Writing %d bytes to chunk!!!!!!!!!", ++ n_bytes); ++ BUG(); ++ } ++ ++ /* ++ * If this is a data chunk and the write goes past the end of the stored ++ * size then update the stored_size. ++ */ ++ if (inode_chunk > 0) { ++ endpos = (inode_chunk - 1) * dev->data_bytes_per_chunk + ++ n_bytes; ++ if (in->variant.file_variant.stored_size < endpos) ++ in->variant.file_variant.stored_size = endpos; ++ } ++ ++ new_chunk_id = ++ yaffs_write_new_chunk(dev, buffer, &new_tags, use_reserve); ++ ++ if (new_chunk_id > 0) { ++ yaffs_put_chunk_in_file(in, inode_chunk, new_chunk_id, 0); ++ ++ if (prev_chunk_id > 0) ++ yaffs_chunk_del(dev, prev_chunk_id, 1, __LINE__); ++ ++ yaffs_verify_file_sane(in); ++ } ++ return new_chunk_id; ++} ++ ++ ++ ++static int yaffs_do_xattrib_mod(struct yaffs_obj *obj, int set, ++ const YCHAR *name, const void *value, int size, ++ int flags) ++{ ++ struct yaffs_xattr_mod xmod; ++ int result; ++ ++ xmod.set = set; ++ xmod.name = name; ++ xmod.data = value; ++ xmod.size = size; ++ xmod.flags = flags; ++ xmod.result = -ENOSPC; ++ ++ result = yaffs_update_oh(obj, NULL, 0, 0, 0, &xmod); ++ ++ if (result > 0) ++ return xmod.result; ++ else ++ return -ENOSPC; ++} ++ ++static int yaffs_apply_xattrib_mod(struct yaffs_obj *obj, char *buffer, ++ struct yaffs_xattr_mod *xmod) ++{ ++ int retval = 0; ++ int x_offs = sizeof(struct yaffs_obj_hdr); ++ struct yaffs_dev *dev = obj->my_dev; ++ int x_size = dev->data_bytes_per_chunk - sizeof(struct yaffs_obj_hdr); ++ char *x_buffer = buffer + x_offs; ++ ++ if (xmod->set) ++ retval = ++ nval_set(dev, x_buffer, x_size, xmod->name, xmod->data, ++ xmod->size, xmod->flags); ++ else ++ retval = nval_del(dev, x_buffer, x_size, xmod->name); ++ ++ obj->has_xattr = nval_hasvalues(dev, x_buffer, x_size); ++ obj->xattr_known = 1; ++ xmod->result = retval; ++ ++ return retval; ++} ++ ++static int yaffs_do_xattrib_fetch(struct yaffs_obj *obj, const YCHAR *name, ++ void *value, int size) ++{ ++ char *buffer = NULL; ++ int result; ++ struct yaffs_ext_tags tags; ++ struct yaffs_dev *dev = obj->my_dev; ++ int x_offs = sizeof(struct yaffs_obj_hdr); ++ int x_size = dev->data_bytes_per_chunk - sizeof(struct yaffs_obj_hdr); ++ char *x_buffer; ++ int retval = 0; ++ ++ if (obj->hdr_chunk < 1) ++ return -ENODATA; ++ ++ /* If we know that the object has no xattribs then don't do all the ++ * reading and parsing. ++ */ ++ if (obj->xattr_known && !obj->has_xattr) { ++ if (name) ++ return -ENODATA; ++ else ++ return 0; ++ } ++ ++ buffer = (char *)yaffs_get_temp_buffer(dev); ++ if (!buffer) ++ return -ENOMEM; ++ ++ result = ++ yaffs_rd_chunk_tags_nand(dev, obj->hdr_chunk, (u8 *) buffer, &tags); ++ ++ if (result != YAFFS_OK) ++ retval = -ENOENT; ++ else { ++ x_buffer = buffer + x_offs; ++ ++ if (!obj->xattr_known) { ++ obj->has_xattr = nval_hasvalues(dev, x_buffer, x_size); ++ obj->xattr_known = 1; ++ } ++ ++ if (name) ++ retval = nval_get(dev, x_buffer, x_size, ++ name, value, size); ++ else ++ retval = nval_list(dev, x_buffer, x_size, value, size); ++ } ++ yaffs_release_temp_buffer(dev, (u8 *) buffer); ++ return retval; ++} ++ ++int yaffs_set_xattrib(struct yaffs_obj *obj, const YCHAR * name, ++ const void *value, int size, int flags) ++{ ++ return yaffs_do_xattrib_mod(obj, 1, name, value, size, flags); ++} ++ ++int yaffs_remove_xattrib(struct yaffs_obj *obj, const YCHAR * name) ++{ ++ return yaffs_do_xattrib_mod(obj, 0, name, NULL, 0, 0); ++} ++ ++int yaffs_get_xattrib(struct yaffs_obj *obj, const YCHAR * name, void *value, ++ int size) ++{ ++ return yaffs_do_xattrib_fetch(obj, name, value, size); ++} ++ ++int yaffs_list_xattrib(struct yaffs_obj *obj, char *buffer, int size) ++{ ++ return yaffs_do_xattrib_fetch(obj, NULL, buffer, size); ++} ++ ++static void yaffs_check_obj_details_loaded(struct yaffs_obj *in) ++{ ++ u8 *buf; ++ struct yaffs_obj_hdr *oh; ++ struct yaffs_dev *dev; ++ struct yaffs_ext_tags tags; ++ int result; ++ ++ if (!in || !in->lazy_loaded || in->hdr_chunk < 1) ++ return; ++ ++ dev = in->my_dev; ++ buf = yaffs_get_temp_buffer(dev); ++ ++ result = yaffs_rd_chunk_tags_nand(dev, in->hdr_chunk, buf, &tags); ++ ++ if (result == YAFFS_FAIL) ++ return; ++ ++ oh = (struct yaffs_obj_hdr *)buf; ++ ++ yaffs_do_endian_oh(dev, oh); ++ ++ in->lazy_loaded = 0; ++ in->yst_mode = oh->yst_mode; ++ yaffs_load_attribs(in, oh); ++ yaffs_set_obj_name_from_oh(in, oh); ++ ++ if (in->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) ++ in->variant.symlink_variant.alias = ++ yaffs_clone_str(oh->alias); ++ yaffs_release_temp_buffer(dev, buf); ++} ++ ++/* UpdateObjectHeader updates the header on NAND for an object. ++ * If name is not NULL, then that new name is used. ++ * ++ * We're always creating the obj header from scratch (except reading ++ * the old name) so first set up in cpu endianness then run it through ++ * endian fixing at the end. ++ * ++ * However, a twist: If there are xattribs we leave them as they were. ++ * ++ * Careful! The buffer holds the whole chunk. Part of the chunk holds the ++ * object header and the rest holds the xattribs, therefore we use a buffer ++ * pointer and an oh pointer to point to the same memory. ++ */ ++ ++int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, int force, ++ int is_shrink, int shadows, struct yaffs_xattr_mod *xmod) ++{ ++ ++ struct yaffs_block_info *bi; ++ struct yaffs_dev *dev = in->my_dev; ++ int prev_chunk_id; ++ int ret_val = 0; ++ int result = 0; ++ int new_chunk_id; ++ struct yaffs_ext_tags new_tags; ++ struct yaffs_ext_tags old_tags; ++ const YCHAR *alias = NULL; ++ u8 *buffer = NULL; ++ YCHAR old_name[YAFFS_MAX_NAME_LENGTH + 1]; ++ struct yaffs_obj_hdr *oh = NULL; ++ loff_t file_size = 0; ++ ++ strcpy(old_name, _Y("silly old name")); ++ ++ if (in->fake && in != dev->root_dir && !force && !xmod) ++ return ret_val; ++ ++ yaffs_check_gc(dev, 0); ++ yaffs_check_obj_details_loaded(in); ++ ++ buffer = yaffs_get_temp_buffer(in->my_dev); ++ oh = (struct yaffs_obj_hdr *)buffer; ++ ++ prev_chunk_id = in->hdr_chunk; ++ ++ if (prev_chunk_id > 0) { ++ /* Access the old obj header just to read the name. */ ++ result = yaffs_rd_chunk_tags_nand(dev, prev_chunk_id, ++ buffer, &old_tags); ++ if (result == YAFFS_OK) { ++ yaffs_verify_oh(in, oh, &old_tags, 0); ++ memcpy(old_name, oh->name, sizeof(oh->name)); ++ ++ /* ++ * NB We only wipe the object header area because the rest of ++ * the buffer might contain xattribs. ++ */ ++ memset(oh, 0xff, sizeof(*oh)); ++ } ++ } else { ++ memset(buffer, 0xff, dev->data_bytes_per_chunk); ++ } ++ ++ oh->type = in->variant_type; ++ oh->yst_mode = in->yst_mode; ++ oh->shadows_obj = oh->inband_shadowed_obj_id = shadows; ++ ++ yaffs_load_attribs_oh(oh, in); ++ ++ if (in->parent) ++ oh->parent_obj_id = in->parent->obj_id; ++ else ++ oh->parent_obj_id = 0; ++ ++ if (name && *name) { ++ memset(oh->name, 0, sizeof(oh->name)); ++ yaffs_load_oh_from_name(dev, oh->name, name); ++ } else if (prev_chunk_id > 0) { ++ memcpy(oh->name, old_name, sizeof(oh->name)); ++ } else { ++ memset(oh->name, 0, sizeof(oh->name)); ++ } ++ ++ oh->is_shrink = is_shrink; ++ ++ switch (in->variant_type) { ++ case YAFFS_OBJECT_TYPE_UNKNOWN: ++ /* Should not happen */ ++ break; ++ case YAFFS_OBJECT_TYPE_FILE: ++ if (oh->parent_obj_id != YAFFS_OBJECTID_DELETED && ++ oh->parent_obj_id != YAFFS_OBJECTID_UNLINKED) ++ file_size = in->variant.file_variant.stored_size; ++ yaffs_oh_size_load(dev, oh, file_size, 0); ++ break; ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ oh->equiv_id = in->variant.hardlink_variant.equiv_id; ++ break; ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ /* Do nothing */ ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ /* Do nothing */ ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ alias = in->variant.symlink_variant.alias; ++ if (!alias) ++ alias = _Y("no alias"); ++ strncpy(oh->alias, alias, YAFFS_MAX_ALIAS_LENGTH); ++ oh->alias[YAFFS_MAX_ALIAS_LENGTH] = 0; ++ break; ++ } ++ ++ /* process any xattrib modifications */ ++ if (xmod) ++ yaffs_apply_xattrib_mod(in, (char *)buffer, xmod); ++ ++ /* Tags */ ++ memset(&new_tags, 0, sizeof(new_tags)); ++ in->serial++; ++ new_tags.chunk_id = 0; ++ new_tags.obj_id = in->obj_id; ++ new_tags.serial_number = in->serial; ++ ++ /* Add extra info for file header */ ++ new_tags.extra_available = 1; ++ new_tags.extra_parent_id = oh->parent_obj_id; ++ new_tags.extra_file_size = file_size; ++ new_tags.extra_is_shrink = oh->is_shrink; ++ new_tags.extra_equiv_id = oh->equiv_id; ++ new_tags.extra_shadows = (oh->shadows_obj > 0) ? 1 : 0; ++ new_tags.extra_obj_type = in->variant_type; ++ ++ /* Now endian swizzle the oh if needed. */ ++ yaffs_do_endian_oh(dev, oh); ++ ++ yaffs_verify_oh(in, oh, &new_tags, 1); ++ ++ /* Create new chunk in NAND */ ++ new_chunk_id = ++ yaffs_write_new_chunk(dev, buffer, &new_tags, ++ (prev_chunk_id > 0) ? 1 : 0); ++ ++ if (buffer) ++ yaffs_release_temp_buffer(dev, buffer); ++ ++ if (new_chunk_id < 0) ++ return new_chunk_id; ++ ++ in->hdr_chunk = new_chunk_id; ++ ++ if (prev_chunk_id > 0) ++ yaffs_chunk_del(dev, prev_chunk_id, 1, __LINE__); ++ ++ if (!yaffs_obj_cache_dirty(in)) ++ in->dirty = 0; ++ ++ /* If this was a shrink, then mark the block ++ * that the chunk lives on */ ++ if (is_shrink) { ++ bi = yaffs_get_block_info(in->my_dev, ++ new_chunk_id / ++ in->my_dev->param.chunks_per_block); ++ bi->has_shrink_hdr = 1; ++ } ++ ++ ++ return new_chunk_id; ++} ++ ++/*--------------------- File read/write ------------------------ ++ * Read and write have very similar structures. ++ * In general the read/write has three parts to it ++ * An incomplete chunk to start with (if the read/write is not chunk-aligned) ++ * Some complete chunks ++ * An incomplete chunk to end off with ++ * ++ * Curve-balls: the first chunk might also be the last chunk. ++ */ ++ ++int yaffs_file_rd(struct yaffs_obj *in, u8 * buffer, loff_t offset, int n_bytes) ++{ ++ int chunk; ++ u32 start; ++ int n_copy; ++ int n = n_bytes; ++ int n_done = 0; ++ struct yaffs_cache *cache; ++ struct yaffs_dev *dev; ++ ++ dev = in->my_dev; ++ ++ while (n > 0) { ++ yaffs_addr_to_chunk(dev, offset, &chunk, &start); ++ chunk++; ++ ++ /* OK now check for the curveball where the start and end are in ++ * the same chunk. ++ */ ++ if ((start + n) < dev->data_bytes_per_chunk) ++ n_copy = n; ++ else ++ n_copy = dev->data_bytes_per_chunk - start; ++ ++ cache = yaffs_find_chunk_cache(in, chunk); ++ ++ /* If the chunk is already in the cache or it is less than ++ * a whole chunk or we're using inband tags then use the cache ++ * (if there is caching) else bypass the cache. ++ */ ++ if (cache || n_copy != (int)dev->data_bytes_per_chunk || ++ dev->param.inband_tags) { ++ if (dev->param.n_caches > 0) { ++ ++ /* If we can't find the data in the cache, ++ * then load it up. */ ++ ++ if (!cache) { ++ cache = ++ yaffs_grab_chunk_cache(in->my_dev); ++ cache->object = in; ++ cache->chunk_id = chunk; ++ cache->dirty = 0; ++ cache->locked = 0; ++ yaffs_rd_data_obj(in, chunk, ++ cache->data); ++ cache->n_bytes = 0; ++ } ++ ++ yaffs_use_cache(dev, cache, 0); ++ ++ cache->locked = 1; ++ ++ memcpy(buffer, &cache->data[start], n_copy); ++ ++ cache->locked = 0; ++ } else { ++ /* Read into the local buffer then copy.. */ ++ ++ u8 *local_buffer = ++ yaffs_get_temp_buffer(dev); ++ yaffs_rd_data_obj(in, chunk, local_buffer); ++ ++ memcpy(buffer, &local_buffer[start], n_copy); ++ ++ yaffs_release_temp_buffer(dev, local_buffer); ++ } ++ } else { ++ /* A full chunk. Read directly into the buffer. */ ++ yaffs_rd_data_obj(in, chunk, buffer); ++ } ++ n -= n_copy; ++ offset += n_copy; ++ buffer += n_copy; ++ n_done += n_copy; ++ } ++ return n_done; ++} ++ ++int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset, ++ int n_bytes, int write_through) ++{ ++ ++ int chunk; ++ u32 start; ++ int n_copy; ++ int n = n_bytes; ++ int n_done = 0; ++ int n_writeback; ++ loff_t start_write = offset; ++ int chunk_written = 0; ++ u32 n_bytes_read; ++ loff_t chunk_start; ++ struct yaffs_dev *dev; ++ ++ dev = in->my_dev; ++ ++ while (n > 0 && chunk_written >= 0) { ++ yaffs_addr_to_chunk(dev, offset, &chunk, &start); ++ ++ if (((loff_t)chunk) * ++ dev->data_bytes_per_chunk + start != offset || ++ start >= dev->data_bytes_per_chunk) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "AddrToChunk of offset %lld gives chunk %d start %d", ++ (long long)offset, chunk, start); ++ } ++ chunk++; /* File pos to chunk in file offset */ ++ ++ /* OK now check for the curveball where the start and end are in ++ * the same chunk. ++ */ ++ ++ if ((start + n) < dev->data_bytes_per_chunk) { ++ n_copy = n; ++ ++ /* Now calculate how many bytes to write back.... ++ * If we're overwriting and not writing to then end of ++ * file then we need to write back as much as was there ++ * before. ++ */ ++ ++ chunk_start = (((loff_t)(chunk - 1)) * ++ dev->data_bytes_per_chunk); ++ ++ if (chunk_start > in->variant.file_variant.file_size) ++ n_bytes_read = 0; /* Past end of file */ ++ else ++ n_bytes_read = ++ in->variant.file_variant.file_size - ++ chunk_start; ++ ++ if (n_bytes_read > dev->data_bytes_per_chunk) ++ n_bytes_read = dev->data_bytes_per_chunk; ++ ++ n_writeback = ++ (n_bytes_read > ++ (start + n)) ? n_bytes_read : (start + n); ++ ++ if (n_writeback < 0 || ++ n_writeback > (int)dev->data_bytes_per_chunk) ++ BUG(); ++ ++ } else { ++ n_copy = dev->data_bytes_per_chunk - start; ++ n_writeback = dev->data_bytes_per_chunk; ++ } ++ ++ if (n_copy != (int)dev->data_bytes_per_chunk || ++ !dev->param.cache_bypass_aligned || ++ dev->param.inband_tags) { ++ /* An incomplete start or end chunk (or maybe both ++ * start and end chunk), or we're using inband tags, ++ * or we're forcing writes through the cache, ++ * so we want to use the cache buffers. ++ */ ++ if (dev->param.n_caches > 0) { ++ struct yaffs_cache *cache; ++ ++ /* If we can't find the data in the cache, then ++ * load the cache */ ++ cache = yaffs_find_chunk_cache(in, chunk); ++ ++ if (!cache && ++ yaffs_check_alloc_available(dev, 1)) { ++ cache = yaffs_grab_chunk_cache(dev); ++ cache->object = in; ++ cache->chunk_id = chunk; ++ cache->dirty = 0; ++ cache->locked = 0; ++ yaffs_rd_data_obj(in, chunk, ++ cache->data); ++ } else if (cache && ++ !cache->dirty && ++ !yaffs_check_alloc_available(dev, ++ 1)) { ++ /* Drop the cache if it was a read cache ++ * item and no space check has been made ++ * for it. ++ */ ++ cache = NULL; ++ } ++ ++ if (cache) { ++ yaffs_use_cache(dev, cache, 1); ++ cache->locked = 1; ++ ++ memcpy(&cache->data[start], buffer, ++ n_copy); ++ ++ cache->locked = 0; ++ cache->n_bytes = n_writeback; ++ ++ if (write_through) { ++ chunk_written = ++ yaffs_wr_data_obj ++ (cache->object, ++ cache->chunk_id, ++ cache->data, ++ cache->n_bytes, 1); ++ cache->dirty = 0; ++ } ++ } else { ++ chunk_written = -1; /* fail write */ ++ } ++ } else { ++ /* An incomplete start or end chunk (or maybe ++ * both start and end chunk). Read into the ++ * local buffer then copy over and write back. ++ */ ++ ++ u8 *local_buffer = yaffs_get_temp_buffer(dev); ++ ++ yaffs_rd_data_obj(in, chunk, local_buffer); ++ memcpy(&local_buffer[start], buffer, n_copy); ++ ++ chunk_written = ++ yaffs_wr_data_obj(in, chunk, ++ local_buffer, ++ n_writeback, 0); ++ ++ yaffs_release_temp_buffer(dev, local_buffer); ++ } ++ } else { ++ /* A full chunk. Write directly from the buffer. */ ++ ++ chunk_written = ++ yaffs_wr_data_obj(in, chunk, buffer, ++ dev->data_bytes_per_chunk, 0); ++ ++ /* Since we've overwritten the cached data, ++ * we better invalidate it. */ ++ yaffs_invalidate_chunk_cache(in, chunk); ++ } ++ ++ if (chunk_written >= 0) { ++ n -= n_copy; ++ offset += n_copy; ++ buffer += n_copy; ++ n_done += n_copy; ++ } ++ } ++ ++ /* Update file object */ ++ ++ if ((start_write + n_done) > in->variant.file_variant.file_size) ++ in->variant.file_variant.file_size = (start_write + n_done); ++ ++ in->dirty = 1; ++ return n_done; ++} ++ ++int yaffs_wr_file(struct yaffs_obj *in, const u8 *buffer, loff_t offset, ++ int n_bytes, int write_through) ++{ ++ yaffs2_handle_hole(in, offset); ++ return yaffs_do_file_wr(in, buffer, offset, n_bytes, write_through); ++} ++ ++/* ---------------------- File resizing stuff ------------------ */ ++ ++static void yaffs_prune_chunks(struct yaffs_obj *in, loff_t new_size) ++{ ++ ++ struct yaffs_dev *dev = in->my_dev; ++ loff_t old_size = in->variant.file_variant.file_size; ++ int i; ++ int chunk_id; ++ u32 dummy; ++ int last_del; ++ int start_del; ++ ++ if (old_size > 0) ++ yaffs_addr_to_chunk(dev, old_size - 1, &last_del, &dummy); ++ else ++ last_del = 0; ++ ++ yaffs_addr_to_chunk(dev, new_size + dev->data_bytes_per_chunk - 1, ++ &start_del, &dummy); ++ last_del++; ++ start_del++; ++ ++ /* Delete backwards so that we don't end up with holes if ++ * power is lost part-way through the operation. ++ */ ++ for (i = last_del; i >= start_del; i--) { ++ /* NB this could be optimised somewhat, ++ * eg. could retrieve the tags and write them without ++ * using yaffs_chunk_del ++ */ ++ ++ chunk_id = yaffs_find_del_file_chunk(in, i, NULL); ++ ++ if (chunk_id < 1) ++ continue; ++ ++ if ((u32)chunk_id < ++ (dev->internal_start_block * dev->param.chunks_per_block) || ++ (u32)chunk_id >= ++ ((dev->internal_end_block + 1) * ++ dev->param.chunks_per_block)) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "Found daft chunk_id %d for %d", ++ chunk_id, i); ++ } else { ++ in->n_data_chunks--; ++ yaffs_chunk_del(dev, chunk_id, 1, __LINE__); ++ } ++ } ++} ++ ++void yaffs_resize_file_down(struct yaffs_obj *obj, loff_t new_size) ++{ ++ int new_full; ++ u32 new_partial; ++ struct yaffs_dev *dev = obj->my_dev; ++ ++ yaffs_addr_to_chunk(dev, new_size, &new_full, &new_partial); ++ ++ yaffs_prune_chunks(obj, new_size); ++ ++ if (new_partial != 0) { ++ int last_chunk = 1 + new_full; ++ u8 *local_buffer = yaffs_get_temp_buffer(dev); ++ ++ /* Rewrite the last chunk with its new size and zero pad */ ++ yaffs_rd_data_obj(obj, last_chunk, local_buffer); ++ memset(local_buffer + new_partial, 0, ++ dev->data_bytes_per_chunk - new_partial); ++ ++ yaffs_wr_data_obj(obj, last_chunk, local_buffer, ++ new_partial, 1); ++ ++ yaffs_release_temp_buffer(dev, local_buffer); ++ } ++ ++ obj->variant.file_variant.file_size = new_size; ++ obj->variant.file_variant.stored_size = new_size; ++ ++ yaffs_prune_tree(dev, &obj->variant.file_variant); ++} ++ ++int yaffs_resize_file(struct yaffs_obj *in, loff_t new_size) ++{ ++ struct yaffs_dev *dev = in->my_dev; ++ loff_t old_size = in->variant.file_variant.file_size; ++ ++ yaffs_flush_file_cache(in, 1); ++ yaffs_invalidate_whole_cache(in); ++ ++ yaffs_check_gc(dev, 0); ++ ++ if (in->variant_type != YAFFS_OBJECT_TYPE_FILE) ++ return YAFFS_FAIL; ++ ++ if (new_size == old_size) ++ return YAFFS_OK; ++ ++ if (new_size > old_size) { ++ yaffs2_handle_hole(in, new_size); ++ in->variant.file_variant.file_size = new_size; ++ } else { ++ /* new_size < old_size */ ++ yaffs_resize_file_down(in, new_size); ++ } ++ ++ /* Write a new object header to reflect the resize. ++ * show we've shrunk the file, if need be ++ * Do this only if the file is not in the deleted directories ++ * and is not shadowed. ++ */ ++ if (in->parent && ++ !in->is_shadowed && ++ in->parent->obj_id != YAFFS_OBJECTID_UNLINKED && ++ in->parent->obj_id != YAFFS_OBJECTID_DELETED) ++ yaffs_update_oh(in, NULL, 0, 0, 0, NULL); ++ ++ return YAFFS_OK; ++} ++ ++int yaffs_flush_file(struct yaffs_obj *in, ++ int update_time, ++ int data_sync, ++ int discard_cache) ++{ ++ if (!in->dirty) ++ return YAFFS_OK; ++ ++ yaffs_flush_file_cache(in, discard_cache); ++ ++ if (data_sync) ++ return YAFFS_OK; ++ ++ if (update_time) ++ yaffs_load_current_time(in, 0, 0); ++ ++ return (yaffs_update_oh(in, NULL, 0, 0, 0, NULL) >= 0) ? ++ YAFFS_OK : YAFFS_FAIL; ++} ++ ++ ++/* yaffs_del_file deletes the whole file data ++ * and the inode associated with the file. ++ * It does not delete the links associated with the file. ++ */ ++static int yaffs_unlink_file_if_needed(struct yaffs_obj *in) ++{ ++ int ret_val; ++ int del_now = 0; ++ struct yaffs_dev *dev = in->my_dev; ++ ++ if (!in->my_inode) ++ del_now = 1; ++ ++ if (del_now) { ++ ret_val = ++ yaffs_change_obj_name(in, in->my_dev->del_dir, ++ _Y("deleted"), 0, 0); ++ yaffs_trace(YAFFS_TRACE_TRACING, ++ "yaffs: immediate deletion of file %d", ++ in->obj_id); ++ in->deleted = 1; ++ in->my_dev->n_deleted_files++; ++ if (dev->param.disable_soft_del || dev->param.is_yaffs2) ++ yaffs_resize_file(in, 0); ++ yaffs_soft_del_file(in); ++ } else { ++ ret_val = ++ yaffs_change_obj_name(in, in->my_dev->unlinked_dir, ++ _Y("unlinked"), 0, 0); ++ } ++ return ret_val; ++} ++ ++static int yaffs_del_file(struct yaffs_obj *in) ++{ ++ int ret_val = YAFFS_OK; ++ int deleted; /* Need to cache value on stack if in is freed */ ++ struct yaffs_dev *dev = in->my_dev; ++ ++ if (dev->param.disable_soft_del || dev->param.is_yaffs2) ++ yaffs_resize_file(in, 0); ++ ++ if (in->n_data_chunks > 0) { ++ /* Use soft deletion if there is data in the file. ++ * That won't be the case if it has been resized to zero. ++ */ ++ if (!in->unlinked) ++ ret_val = yaffs_unlink_file_if_needed(in); ++ ++ deleted = in->deleted; ++ ++ if (ret_val == YAFFS_OK && in->unlinked && !in->deleted) { ++ in->deleted = 1; ++ deleted = 1; ++ in->my_dev->n_deleted_files++; ++ yaffs_soft_del_file(in); ++ } ++ return deleted ? YAFFS_OK : YAFFS_FAIL; ++ } else { ++ /* The file has no data chunks so we toss it immediately */ ++ yaffs_free_tnode(in->my_dev, in->variant.file_variant.top); ++ in->variant.file_variant.top = NULL; ++ yaffs_generic_obj_del(in); ++ ++ return YAFFS_OK; ++ } ++} ++ ++int yaffs_is_non_empty_dir(struct yaffs_obj *obj) ++{ ++ return (obj && ++ obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) && ++ !(list_empty(&obj->variant.dir_variant.children)); ++} ++ ++static int yaffs_del_dir(struct yaffs_obj *obj) ++{ ++ /* First check that the directory is empty. */ ++ if (yaffs_is_non_empty_dir(obj)) ++ return YAFFS_FAIL; ++ ++ return yaffs_generic_obj_del(obj); ++} ++ ++static int yaffs_del_symlink(struct yaffs_obj *in) ++{ ++ kfree(in->variant.symlink_variant.alias); ++ in->variant.symlink_variant.alias = NULL; ++ ++ return yaffs_generic_obj_del(in); ++} ++ ++static int yaffs_del_link(struct yaffs_obj *in) ++{ ++ /* remove this hardlink from the list associated with the equivalent ++ * object ++ */ ++ list_del_init(&in->hard_links); ++ return yaffs_generic_obj_del(in); ++} ++ ++int yaffs_del_obj(struct yaffs_obj *obj) ++{ ++ int ret_val = -1; ++ ++ switch (obj->variant_type) { ++ case YAFFS_OBJECT_TYPE_FILE: ++ ret_val = yaffs_del_file(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ if (!list_empty(&obj->variant.dir_variant.dirty)) { ++ yaffs_trace(YAFFS_TRACE_BACKGROUND, ++ "Remove object %d from dirty directories", ++ obj->obj_id); ++ list_del_init(&obj->variant.dir_variant.dirty); ++ } ++ return yaffs_del_dir(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ ret_val = yaffs_del_symlink(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ ret_val = yaffs_del_link(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ ret_val = yaffs_generic_obj_del(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_UNKNOWN: ++ ret_val = 0; ++ break; /* should not happen. */ ++ } ++ return ret_val; ++} ++ ++ ++static void yaffs_empty_dir_to_dir(struct yaffs_obj *from_dir, ++ struct yaffs_obj *to_dir) ++{ ++ struct yaffs_obj *obj; ++ struct list_head *lh; ++ struct list_head *n; ++ ++ list_for_each_safe(lh, n, &from_dir->variant.dir_variant.children) { ++ obj = list_entry(lh, struct yaffs_obj, siblings); ++ yaffs_add_obj_to_dir(to_dir, obj); ++ } ++} ++ ++struct yaffs_obj *yaffs_retype_obj(struct yaffs_obj *obj, ++ enum yaffs_obj_type type) ++{ ++ /* Tear down the old variant */ ++ switch (obj->variant_type) { ++ case YAFFS_OBJECT_TYPE_FILE: ++ /* Nuke file data */ ++ yaffs_resize_file(obj, 0); ++ yaffs_free_tnode(obj->my_dev, obj->variant.file_variant.top); ++ obj->variant.file_variant.top = NULL; ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ /* Put the children in lost and found. */ ++ yaffs_empty_dir_to_dir(obj, obj->my_dev->lost_n_found); ++ if (!list_empty(&obj->variant.dir_variant.dirty)) ++ list_del_init(&obj->variant.dir_variant.dirty); ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ /* Nuke symplink data */ ++ kfree(obj->variant.symlink_variant.alias); ++ obj->variant.symlink_variant.alias = NULL; ++ break; ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ list_del_init(&obj->hard_links); ++ break; ++ default: ++ break; ++ } ++ ++ memset(&obj->variant, 0, sizeof(obj->variant)); ++ ++ /*Set up new variant if the memset is not enough. */ ++ switch (type) { ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ INIT_LIST_HEAD(&obj->variant.dir_variant.children); ++ INIT_LIST_HEAD(&obj->variant.dir_variant.dirty); ++ break; ++ case YAFFS_OBJECT_TYPE_FILE: ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ default: ++ break; ++ } ++ ++ obj->variant_type = type; ++ ++ return obj; ++ ++} ++ ++static int yaffs_unlink_worker(struct yaffs_obj *obj) ++{ ++ int del_now = 0; ++ ++ if (!obj) ++ return YAFFS_FAIL; ++ ++ if (!obj->my_inode) ++ del_now = 1; ++ ++ yaffs_update_parent(obj->parent); ++ ++ if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK) { ++ return yaffs_del_link(obj); ++ } else if (!list_empty(&obj->hard_links)) { ++ /* Curve ball: We're unlinking an object that has a hardlink. ++ * ++ * This problem arises because we are not strictly following ++ * The Linux link/inode model. ++ * ++ * We can't really delete the object. ++ * Instead, we do the following: ++ * - Select a hardlink. ++ * - Unhook it from the hard links ++ * - Move it from its parent directory so that the rename works. ++ * - Rename the object to the hardlink's name. ++ * - Delete the hardlink ++ */ ++ ++ struct yaffs_obj *hl; ++ struct yaffs_obj *parent; ++ int ret_val; ++ YCHAR name[YAFFS_MAX_NAME_LENGTH + 1]; ++ ++ hl = list_entry(obj->hard_links.next, struct yaffs_obj, ++ hard_links); ++ ++ yaffs_get_obj_name(hl, name, YAFFS_MAX_NAME_LENGTH + 1); ++ parent = hl->parent; ++ ++ list_del_init(&hl->hard_links); ++ ++ yaffs_add_obj_to_dir(obj->my_dev->unlinked_dir, hl); ++ ++ ret_val = yaffs_change_obj_name(obj, parent, name, 0, 0); ++ ++ if (ret_val == YAFFS_OK) ++ ret_val = yaffs_generic_obj_del(hl); ++ ++ return ret_val; ++ ++ } else if (del_now) { ++ switch (obj->variant_type) { ++ case YAFFS_OBJECT_TYPE_FILE: ++ return yaffs_del_file(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ list_del_init(&obj->variant.dir_variant.dirty); ++ return yaffs_del_dir(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ return yaffs_del_symlink(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ return yaffs_generic_obj_del(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ case YAFFS_OBJECT_TYPE_UNKNOWN: ++ default: ++ return YAFFS_FAIL; ++ } ++ } else if (yaffs_is_non_empty_dir(obj)) { ++ return YAFFS_FAIL; ++ } else { ++ return yaffs_change_obj_name(obj, obj->my_dev->unlinked_dir, ++ _Y("unlinked"), 0, 0); ++ } ++} ++ ++int yaffs_unlink_obj(struct yaffs_obj *obj) ++{ ++ if (obj && obj->unlink_allowed) ++ return yaffs_unlink_worker(obj); ++ ++ return YAFFS_FAIL; ++} ++ ++int yaffs_unlinker(struct yaffs_obj *dir, const YCHAR *name) ++{ ++ struct yaffs_obj *obj; ++ ++ obj = yaffs_find_by_name(dir, name); ++ return yaffs_unlink_obj(obj); ++} ++ ++/* Note: ++ * If old_name is NULL then we take old_dir as the object to be renamed. ++ */ ++int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR *old_name, ++ struct yaffs_obj *new_dir, const YCHAR *new_name) ++{ ++ struct yaffs_obj *obj = NULL; ++ struct yaffs_obj *existing_target = NULL; ++ int force = 0; ++ int result; ++ struct yaffs_dev *dev; ++ ++ if (!old_dir || old_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { ++ BUG(); ++ return YAFFS_FAIL; ++ } ++ if (!new_dir || new_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { ++ BUG(); ++ return YAFFS_FAIL; ++ } ++ ++ dev = old_dir->my_dev; ++ ++#ifdef CONFIG_YAFFS_CASE_INSENSITIVE ++ /* Special case for case insemsitive systems. ++ * While look-up is case insensitive, the name isn't. ++ * Therefore we might want to change x.txt to X.txt ++ */ ++ if (old_dir == new_dir && ++ old_name && new_name && ++ strcmp(old_name, new_name) == 0) ++ force = 1; ++#endif ++ ++ if (strnlen(new_name, YAFFS_MAX_NAME_LENGTH + 1) > ++ YAFFS_MAX_NAME_LENGTH) ++ /* ENAMETOOLONG */ ++ return YAFFS_FAIL; ++ ++ if (old_name) ++ obj = yaffs_find_by_name(old_dir, old_name); ++ else{ ++ obj = old_dir; ++ old_dir = obj->parent; ++ } ++ ++ if (obj && obj->rename_allowed) { ++ /* Now handle an existing target, if there is one */ ++ existing_target = yaffs_find_by_name(new_dir, new_name); ++ if (yaffs_is_non_empty_dir(existing_target)) { ++ return YAFFS_FAIL; /* ENOTEMPTY */ ++ } else if (existing_target && existing_target != obj) { ++ /* Nuke the target first, using shadowing, ++ * but only if it isn't the same object. ++ * ++ * Note we must disable gc here otherwise it can mess ++ * up the shadowing. ++ * ++ */ ++ dev->gc_disable = 1; ++ yaffs_change_obj_name(obj, new_dir, new_name, force, ++ existing_target->obj_id); ++ existing_target->is_shadowed = 1; ++ yaffs_unlink_obj(existing_target); ++ dev->gc_disable = 0; ++ } ++ ++ result = yaffs_change_obj_name(obj, new_dir, new_name, 1, 0); ++ ++ yaffs_update_parent(old_dir); ++ if (new_dir != old_dir) ++ yaffs_update_parent(new_dir); ++ ++ return result; ++ } ++ return YAFFS_FAIL; ++} ++ ++/*----------------------- Initialisation Scanning ---------------------- */ ++ ++void yaffs_handle_shadowed_obj(struct yaffs_dev *dev, int obj_id, ++ int backward_scanning) ++{ ++ struct yaffs_obj *obj; ++ ++ if (backward_scanning) { ++ /* Handle YAFFS2 case (backward scanning) ++ * If the shadowed object exists then ignore. ++ */ ++ obj = yaffs_find_by_number(dev, obj_id); ++ if (obj) ++ return; ++ } ++ ++ /* Let's create it (if it does not exist) assuming it is a file so that ++ * it can do shrinking etc. ++ * We put it in unlinked dir to be cleaned up after the scanning ++ */ ++ obj = ++ yaffs_find_or_create_by_number(dev, obj_id, YAFFS_OBJECT_TYPE_FILE); ++ if (!obj) ++ return; ++ obj->is_shadowed = 1; ++ yaffs_add_obj_to_dir(dev->unlinked_dir, obj); ++ obj->variant.file_variant.shrink_size = 0; ++ obj->valid = 1; /* So that we don't read any other info. */ ++} ++ ++void yaffs_link_fixup(struct yaffs_dev *dev, struct list_head *hard_list) ++{ ++ struct list_head *lh; ++ struct list_head *save; ++ struct yaffs_obj *hl; ++ struct yaffs_obj *in; ++ ++ list_for_each_safe(lh, save, hard_list) { ++ hl = list_entry(lh, struct yaffs_obj, hard_links); ++ in = yaffs_find_by_number(dev, ++ hl->variant.hardlink_variant.equiv_id); ++ ++ if (in) { ++ /* Add the hardlink pointers */ ++ hl->variant.hardlink_variant.equiv_obj = in; ++ list_add(&hl->hard_links, &in->hard_links); ++ } else { ++ /* Todo Need to report/handle this better. ++ * Got a problem... hardlink to a non-existant object ++ */ ++ hl->variant.hardlink_variant.equiv_obj = NULL; ++ INIT_LIST_HEAD(&hl->hard_links); ++ } ++ } ++} ++ ++static void yaffs_strip_deleted_objs(struct yaffs_dev *dev) ++{ ++ /* ++ * Sort out state of unlinked and deleted objects after scanning. ++ */ ++ struct list_head *i; ++ struct list_head *n; ++ struct yaffs_obj *l; ++ ++ if (dev->read_only) ++ return; ++ ++ /* Soft delete all the unlinked files */ ++ list_for_each_safe(i, n, ++ &dev->unlinked_dir->variant.dir_variant.children) { ++ l = list_entry(i, struct yaffs_obj, siblings); ++ yaffs_del_obj(l); ++ } ++ ++ list_for_each_safe(i, n, &dev->del_dir->variant.dir_variant.children) { ++ l = list_entry(i, struct yaffs_obj, siblings); ++ yaffs_del_obj(l); ++ } ++} ++ ++/* ++ * This code iterates through all the objects making sure that they are rooted. ++ * Any unrooted objects are re-rooted in lost+found. ++ * An object needs to be in one of: ++ * - Directly under deleted, unlinked ++ * - Directly or indirectly under root. ++ * ++ * Note: ++ * This code assumes that we don't ever change the current relationships ++ * between directories: ++ * root_dir->parent == unlinked_dir->parent == del_dir->parent == NULL ++ * lost-n-found->parent == root_dir ++ * ++ * This fixes the problem where directories might have inadvertently been ++ * deleted leaving the object "hanging" without being rooted in the ++ * directory tree. ++ */ ++ ++static int yaffs_has_null_parent(struct yaffs_dev *dev, struct yaffs_obj *obj) ++{ ++ return (obj == dev->del_dir || ++ obj == dev->unlinked_dir || obj == dev->root_dir); ++} ++ ++static void yaffs_fix_hanging_objs(struct yaffs_dev *dev) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_obj *parent; ++ int i; ++ struct list_head *lh; ++ struct list_head *n; ++ int depth_limit; ++ int hanging; ++ ++ if (dev->read_only) ++ return; ++ ++ /* Iterate through the objects in each hash entry, ++ * looking at each object. ++ * Make sure it is rooted. ++ */ ++ ++ for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) { ++ list_for_each_safe(lh, n, &dev->obj_bucket[i].list) { ++ obj = list_entry(lh, struct yaffs_obj, hash_link); ++ parent = obj->parent; ++ ++ if (yaffs_has_null_parent(dev, obj)) { ++ /* These directories are not hanging */ ++ hanging = 0; ++ } else if (!parent || ++ parent->variant_type != ++ YAFFS_OBJECT_TYPE_DIRECTORY) { ++ hanging = 1; ++ } else if (yaffs_has_null_parent(dev, parent)) { ++ hanging = 0; ++ } else { ++ /* ++ * Need to follow the parent chain to ++ * see if it is hanging. ++ */ ++ hanging = 0; ++ depth_limit = 100; ++ ++ while (parent != dev->root_dir && ++ parent->parent && ++ parent->parent->variant_type == ++ YAFFS_OBJECT_TYPE_DIRECTORY && ++ depth_limit > 0) { ++ parent = parent->parent; ++ depth_limit--; ++ } ++ if (parent != dev->root_dir) ++ hanging = 1; ++ } ++ if (hanging) { ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ "Hanging object %d moved to lost and found", ++ obj->obj_id); ++ yaffs_add_obj_to_dir(dev->lost_n_found, obj); ++ } ++ } ++ } ++} ++ ++/* ++ * Delete directory contents for cleaning up lost and found. ++ */ ++static void yaffs_del_dir_contents(struct yaffs_obj *dir) ++{ ++ struct yaffs_obj *obj; ++ struct list_head *lh; ++ struct list_head *n; ++ ++ if (dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) ++ BUG(); ++ ++ list_for_each_safe(lh, n, &dir->variant.dir_variant.children) { ++ obj = list_entry(lh, struct yaffs_obj, siblings); ++ if (obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) ++ yaffs_del_dir_contents(obj); ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ "Deleting lost_found object %d", ++ obj->obj_id); ++ yaffs_unlink_obj(obj); ++ } ++} ++ ++static void yaffs_empty_l_n_f(struct yaffs_dev *dev) ++{ ++ yaffs_del_dir_contents(dev->lost_n_found); ++} ++ ++ ++struct yaffs_obj *yaffs_find_by_name(struct yaffs_obj *directory, ++ const YCHAR *name) ++{ ++ int sum; ++ struct list_head *i; ++ YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1]; ++ struct yaffs_obj *l; ++ ++ if (!name) ++ return NULL; ++ ++ if (!directory) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "tragedy: yaffs_find_by_name: null pointer directory" ++ ); ++ BUG(); ++ return NULL; ++ } ++ if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "tragedy: yaffs_find_by_name: non-directory" ++ ); ++ BUG(); ++ } ++ ++ sum = yaffs_calc_name_sum(name); ++ ++ list_for_each(i, &directory->variant.dir_variant.children) { ++ l = list_entry(i, struct yaffs_obj, siblings); ++ ++ if (l->parent != directory) ++ BUG(); ++ ++ yaffs_check_obj_details_loaded(l); ++ ++ /* Special case for lost-n-found */ ++ if (l->obj_id == YAFFS_OBJECTID_LOSTNFOUND) { ++ if (!strcmp(name, YAFFS_LOSTNFOUND_NAME)) ++ return l; ++ } else if (l->sum == sum || l->hdr_chunk <= 0) { ++ /* LostnFound chunk called Objxxx ++ * Do a real check ++ */ ++ yaffs_get_obj_name(l, buffer, ++ YAFFS_MAX_NAME_LENGTH + 1); ++ if (!strncmp(name, buffer, YAFFS_MAX_NAME_LENGTH)) ++ return l; ++ } ++ } ++ return NULL; ++} ++ ++/* GetEquivalentObject dereferences any hard links to get to the ++ * actual object. ++ */ ++ ++struct yaffs_obj *yaffs_get_equivalent_obj(struct yaffs_obj *obj) ++{ ++ if (obj && obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK) { ++ obj = obj->variant.hardlink_variant.equiv_obj; ++ yaffs_check_obj_details_loaded(obj); ++ } ++ return obj; ++} ++ ++/* ++ * A note or two on object names. ++ * * If the object name is missing, we then make one up in the form objnnn ++ * ++ * * ASCII names are stored in the object header's name field from byte zero ++ * * Unicode names are historically stored starting from byte zero. ++ * ++ * Then there are automatic Unicode names... ++ * The purpose of these is to save names in a way that can be read as ++ * ASCII or Unicode names as appropriate, thus allowing a Unicode and ASCII ++ * system to share files. ++ * ++ * These automatic unicode are stored slightly differently... ++ * - If the name can fit in the ASCII character space then they are saved as ++ * ascii names as per above. ++ * - If the name needs Unicode then the name is saved in Unicode ++ * starting at oh->name[1]. ++ ++ */ ++static void yaffs_fix_null_name(struct yaffs_obj *obj, YCHAR *name, ++ int buffer_size) ++{ ++ /* Create an object name if we could not find one. */ ++ if (strnlen(name, YAFFS_MAX_NAME_LENGTH) == 0) { ++ YCHAR local_name[20]; ++ YCHAR num_string[20]; ++ YCHAR *x = &num_string[19]; ++ unsigned v = obj->obj_id; ++ num_string[19] = 0; ++ while (v > 0) { ++ x--; ++ *x = '0' + (v % 10); ++ v /= 10; ++ } ++ /* make up a name */ ++ strcpy(local_name, YAFFS_LOSTNFOUND_PREFIX); ++ strcat(local_name, x); ++ strncpy(name, local_name, buffer_size - 1); ++ } ++} ++ ++int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR *name, int buffer_size) ++{ ++ memset(name, 0, buffer_size * sizeof(YCHAR)); ++ yaffs_check_obj_details_loaded(obj); ++ if (obj->obj_id == YAFFS_OBJECTID_LOSTNFOUND) { ++ strncpy(name, YAFFS_LOSTNFOUND_NAME, buffer_size - 1); ++ } else if (obj->short_name[0]) { ++ strcpy(name, obj->short_name); ++ } else if (obj->hdr_chunk > 0) { ++ int result = 0; ++ u8 *buffer = yaffs_get_temp_buffer(obj->my_dev); ++ ++ struct yaffs_obj_hdr *oh = (struct yaffs_obj_hdr *)buffer; ++ ++ memset(buffer, 0, obj->my_dev->data_bytes_per_chunk); ++ ++ if (obj->hdr_chunk > 0) { ++ result = yaffs_rd_chunk_tags_nand(obj->my_dev, ++ obj->hdr_chunk, ++ buffer, NULL); ++ } ++ if (result == YAFFS_OK) ++ yaffs_load_name_from_oh(obj->my_dev, name, oh->name, ++ buffer_size); ++ ++ yaffs_release_temp_buffer(obj->my_dev, buffer); ++ } ++ ++ yaffs_fix_null_name(obj, name, buffer_size); ++ ++ return strnlen(name, YAFFS_MAX_NAME_LENGTH); ++} ++ ++loff_t yaffs_get_obj_length(struct yaffs_obj *obj) ++{ ++ /* Dereference any hard linking */ ++ obj = yaffs_get_equivalent_obj(obj); ++ ++ if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE) ++ return obj->variant.file_variant.file_size; ++ if (obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) { ++ if (!obj->variant.symlink_variant.alias) ++ return 0; ++ return strnlen(obj->variant.symlink_variant.alias, ++ YAFFS_MAX_ALIAS_LENGTH); ++ } else { ++ /* Only a directory should drop through to here */ ++ return obj->my_dev->data_bytes_per_chunk; ++ } ++} ++ ++int yaffs_get_obj_link_count(struct yaffs_obj *obj) ++{ ++ int count = 0; ++ struct list_head *i; ++ ++ if (!obj->unlinked) ++ count++; /* the object itself */ ++ ++ list_for_each(i, &obj->hard_links) ++ count++; /* add the hard links; */ ++ ++ return count; ++} ++ ++int yaffs_get_obj_inode(struct yaffs_obj *obj) ++{ ++ obj = yaffs_get_equivalent_obj(obj); ++ ++ return obj->obj_id; ++} ++ ++unsigned yaffs_get_obj_type(struct yaffs_obj *obj) ++{ ++ obj = yaffs_get_equivalent_obj(obj); ++ ++ switch (obj->variant_type) { ++ case YAFFS_OBJECT_TYPE_FILE: ++ return DT_REG; ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ return DT_DIR; ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ return DT_LNK; ++ break; ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ return DT_REG; ++ break; ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ if (S_ISFIFO(obj->yst_mode)) ++ return DT_FIFO; ++ if (S_ISCHR(obj->yst_mode)) ++ return DT_CHR; ++ if (S_ISBLK(obj->yst_mode)) ++ return DT_BLK; ++ if (S_ISSOCK(obj->yst_mode)) ++ return DT_SOCK; ++ return DT_REG; ++ break; ++ default: ++ return DT_REG; ++ break; ++ } ++} ++ ++YCHAR *yaffs_get_symlink_alias(struct yaffs_obj *obj) ++{ ++ obj = yaffs_get_equivalent_obj(obj); ++ if (obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) ++ return yaffs_clone_str(obj->variant.symlink_variant.alias); ++ else ++ return yaffs_clone_str(_Y("")); ++} ++ ++/*--------------------------- Initialisation code -------------------------- */ ++ ++static int yaffs_check_dev_fns(struct yaffs_dev *dev) ++{ ++ struct yaffs_driver *drv = &dev->drv; ++ struct yaffs_tags_handler *tagger = &dev->tagger; ++ ++ /* Common functions, gotta have */ ++ if (!drv->drv_read_chunk_fn || ++ !drv->drv_write_chunk_fn || ++ !drv->drv_erase_fn) ++ return 0; ++ ++ if (dev->param.is_yaffs2 && ++ (!drv->drv_mark_bad_fn || !drv->drv_check_bad_fn)) ++ return 0; ++ ++ /* Install the default tags marshalling functions if needed. */ ++ yaffs_tags_compat_install(dev); ++ yaffs_tags_marshall_install(dev); ++ ++ /* Check we now have the marshalling functions required. */ ++ if (!tagger->write_chunk_tags_fn || ++ !tagger->read_chunk_tags_fn || ++ !tagger->query_block_fn || ++ !tagger->mark_bad_fn) ++ return 0; ++ ++ return 1; ++} ++ ++static int yaffs_create_initial_dir(struct yaffs_dev *dev) ++{ ++ /* Initialise the unlinked, deleted, root and lost+found directories */ ++ dev->lost_n_found = NULL; ++ dev->root_dir = NULL; ++ dev->unlinked_dir = NULL; ++ dev->del_dir = NULL; ++ ++ dev->unlinked_dir = ++ yaffs_create_fake_dir(dev, YAFFS_OBJECTID_UNLINKED, S_IFDIR); ++ dev->del_dir = ++ yaffs_create_fake_dir(dev, YAFFS_OBJECTID_DELETED, S_IFDIR); ++ dev->root_dir = ++ yaffs_create_fake_dir(dev, YAFFS_OBJECTID_ROOT, ++ YAFFS_ROOT_MODE | S_IFDIR); ++ dev->lost_n_found = ++ yaffs_create_fake_dir(dev, YAFFS_OBJECTID_LOSTNFOUND, ++ YAFFS_LOSTNFOUND_MODE | S_IFDIR); ++ ++ if (dev->lost_n_found && ++ dev->root_dir && ++ dev->unlinked_dir && ++ dev->del_dir) { ++ /* If lost-n-found is hidden then yank it out of the directory tree. */ ++ if (dev->param.hide_lost_n_found) ++ list_del_init(&dev->lost_n_found->siblings); ++ else ++ yaffs_add_obj_to_dir(dev->root_dir, dev->lost_n_found); ++ return YAFFS_OK; ++ } ++ return YAFFS_FAIL; ++} ++ ++/* Low level init. ++ * Typically only used by yaffs_guts_initialise, but also used by the ++ * Low level yaffs driver tests. ++ */ ++ ++int yaffs_guts_ll_init(struct yaffs_dev *dev) ++{ ++ ++ ++ yaffs_trace(YAFFS_TRACE_TRACING, "yaffs: yaffs_ll_init()"); ++ ++ if (!dev) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs: Need a device" ++ ); ++ return YAFFS_FAIL; ++ } ++ ++ if (dev->ll_init) ++ return YAFFS_OK; ++ ++ dev->internal_start_block = dev->param.start_block; ++ dev->internal_end_block = dev->param.end_block; ++ dev->block_offset = 0; ++ dev->chunk_offset = 0; ++ dev->n_free_chunks = 0; ++ ++ dev->gc_block = 0; ++ ++ if (dev->param.start_block == 0) { ++ dev->internal_start_block = dev->param.start_block + 1; ++ dev->internal_end_block = dev->param.end_block + 1; ++ dev->block_offset = 1; ++ dev->chunk_offset = dev->param.chunks_per_block; ++ } ++ ++ /* Check geometry parameters. */ ++ ++ if ((!dev->param.inband_tags && dev->param.is_yaffs2 && ++ dev->param.total_bytes_per_chunk < 1024) || ++ (!dev->param.is_yaffs2 && ++ dev->param.total_bytes_per_chunk < 512) || ++ (dev->param.inband_tags && !dev->param.is_yaffs2) || ++ dev->param.chunks_per_block < 2 || ++ dev->param.n_reserved_blocks < 2 || ++ dev->internal_start_block <= 0 || ++ dev->internal_end_block <= 0 || ++ dev->internal_end_block <= ++ (dev->internal_start_block + dev->param.n_reserved_blocks + 2) ++ ) { ++ /* otherwise it is too small */ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "NAND geometry problems: chunk size %d, type is yaffs%s, inband_tags %d ", ++ dev->param.total_bytes_per_chunk, ++ dev->param.is_yaffs2 ? "2" : "", ++ dev->param.inband_tags); ++ return YAFFS_FAIL; ++ } ++ ++ /* Sort out space for inband tags, if required */ ++ if (dev->param.inband_tags) ++ dev->data_bytes_per_chunk = ++ dev->param.total_bytes_per_chunk - ++ sizeof(struct yaffs_packed_tags2_tags_only); ++ else ++ dev->data_bytes_per_chunk = dev->param.total_bytes_per_chunk; ++ ++ /* Got the right mix of functions? */ ++ if (!yaffs_check_dev_fns(dev)) { ++ /* Function missing */ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "device function(s) missing or wrong"); ++ ++ return YAFFS_FAIL; ++ } ++ ++ if (yaffs_init_nand(dev) != YAFFS_OK) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "InitialiseNAND failed"); ++ return YAFFS_FAIL; ++ } ++ ++ return YAFFS_OK; ++} ++ ++ ++int yaffs_guts_format_dev(struct yaffs_dev *dev) ++{ ++ u32 i; ++ enum yaffs_block_state state; ++ u32 dummy; ++ ++ if(yaffs_guts_ll_init(dev) != YAFFS_OK) ++ return YAFFS_FAIL; ++ ++ if(dev->is_mounted) ++ return YAFFS_FAIL; ++ ++ for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) { ++ yaffs_query_init_block_state(dev, i, &state, &dummy); ++ if (state != YAFFS_BLOCK_STATE_DEAD) ++ yaffs_erase_block(dev, i); ++ } ++ ++ return YAFFS_OK; ++} ++ ++ ++int yaffs_guts_initialise(struct yaffs_dev *dev) ++{ ++ int init_failed = 0; ++ u32 x; ++ u32 bits; ++ ++ if(yaffs_guts_ll_init(dev) != YAFFS_OK) ++ return YAFFS_FAIL; ++ ++ if (dev->is_mounted) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "device already mounted"); ++ return YAFFS_FAIL; ++ } ++ ++ dev->is_mounted = 1; ++ ++ /* OK now calculate a few things for the device */ ++ ++ /* ++ * Calculate all the chunk size manipulation numbers: ++ */ ++ x = dev->data_bytes_per_chunk; ++ /* We always use dev->chunk_shift and dev->chunk_div */ ++ dev->chunk_shift = calc_shifts(x); ++ x >>= dev->chunk_shift; ++ dev->chunk_div = x; ++ /* We only use chunk mask if chunk_div is 1 */ ++ dev->chunk_mask = (1 << dev->chunk_shift) - 1; ++ ++ /* ++ * Calculate chunk_grp_bits. ++ * We need to find the next power of 2 > than internal_end_block ++ */ ++ ++ x = dev->param.chunks_per_block * (dev->internal_end_block + 1); ++ ++ bits = calc_shifts_ceiling(x); ++ ++ /* Set up tnode width if wide tnodes are enabled. */ ++ if (!dev->param.wide_tnodes_disabled) { ++ /* bits must be even so that we end up with 32-bit words */ ++ if (bits & 1) ++ bits++; ++ if (bits < 16) ++ dev->tnode_width = 16; ++ else ++ dev->tnode_width = bits; ++ } else { ++ dev->tnode_width = 16; ++ } ++ ++ dev->tnode_mask = (1 << dev->tnode_width) - 1; ++ ++ /* Level0 Tnodes are 16 bits or wider (if wide tnodes are enabled), ++ * so if the bitwidth of the ++ * chunk range we're using is greater than 16 we need ++ * to figure out chunk shift and chunk_grp_size ++ */ ++ ++ if (bits <= dev->tnode_width) ++ dev->chunk_grp_bits = 0; ++ else ++ dev->chunk_grp_bits = bits - dev->tnode_width; ++ ++ dev->tnode_size = (dev->tnode_width * YAFFS_NTNODES_LEVEL0) / 8; ++ if (dev->tnode_size < sizeof(struct yaffs_tnode)) ++ dev->tnode_size = sizeof(struct yaffs_tnode); ++ ++ dev->chunk_grp_size = 1 << dev->chunk_grp_bits; ++ ++ if (dev->param.chunks_per_block < dev->chunk_grp_size) { ++ /* We have a problem because the soft delete won't work if ++ * the chunk group size > chunks per block. ++ * This can be remedied by using larger "virtual blocks". ++ */ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "chunk group too large"); ++ ++ return YAFFS_FAIL; ++ } ++ ++ /* Finished verifying the device, continue with initialisation */ ++ ++ /* More device initialisation */ ++ dev->all_gcs = 0; ++ dev->passive_gc_count = 0; ++ dev->oldest_dirty_gc_count = 0; ++ dev->bg_gcs = 0; ++ dev->gc_block_finder = 0; ++ dev->buffered_block = -1; ++ dev->doing_buffered_block_rewrite = 0; ++ dev->n_deleted_files = 0; ++ dev->n_bg_deletions = 0; ++ dev->n_unlinked_files = 0; ++ dev->n_ecc_fixed = 0; ++ dev->n_ecc_unfixed = 0; ++ dev->n_tags_ecc_fixed = 0; ++ dev->n_tags_ecc_unfixed = 0; ++ dev->n_erase_failures = 0; ++ dev->n_erased_blocks = 0; ++ dev->gc_disable = 0; ++ dev->has_pending_prioritised_gc = 1; /* Assume the worst for now, ++ * will get fixed on first GC */ ++ INIT_LIST_HEAD(&dev->dirty_dirs); ++ dev->oldest_dirty_seq = 0; ++ dev->oldest_dirty_block = 0; ++ ++ yaffs_endian_config(dev); ++ ++ /* Initialise temporary buffers and caches. */ ++ if (!yaffs_init_tmp_buffers(dev)) ++ init_failed = 1; ++ ++ dev->cache = NULL; ++ dev->gc_cleanup_list = NULL; ++ ++ if (!init_failed && dev->param.n_caches > 0) { ++ u32 i; ++ void *buf; ++ u32 cache_bytes = ++ dev->param.n_caches * sizeof(struct yaffs_cache); ++ ++ if (dev->param.n_caches > YAFFS_MAX_SHORT_OP_CACHES) ++ dev->param.n_caches = YAFFS_MAX_SHORT_OP_CACHES; ++ ++ dev->cache = kmalloc(cache_bytes, GFP_NOFS); ++ ++ buf = (u8 *) dev->cache; ++ ++ if (dev->cache) ++ memset(dev->cache, 0, cache_bytes); ++ ++ for (i = 0; i < dev->param.n_caches && buf; i++) { ++ dev->cache[i].object = NULL; ++ dev->cache[i].last_use = 0; ++ dev->cache[i].dirty = 0; ++ dev->cache[i].data = buf = ++ kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS); ++ } ++ if (!buf) ++ init_failed = 1; ++ ++ dev->cache_last_use = 0; ++ } ++ ++ dev->cache_hits = 0; ++ ++ if (!init_failed) { ++ dev->gc_cleanup_list = ++ kmalloc(dev->param.chunks_per_block * sizeof(u32), ++ GFP_NOFS); ++ if (!dev->gc_cleanup_list) ++ init_failed = 1; ++ } ++ ++ if (dev->param.is_yaffs2) ++ dev->param.use_header_file_size = 1; ++ ++ if (!init_failed && !yaffs_init_blocks(dev)) ++ init_failed = 1; ++ ++ yaffs_init_tnodes_and_objs(dev); ++ ++ if (!init_failed && !yaffs_create_initial_dir(dev)) ++ init_failed = 1; ++ ++ if (!init_failed && dev->param.is_yaffs2 && ++ !dev->param.disable_summary && ++ !yaffs_summary_init(dev)) ++ init_failed = 1; ++ ++ if (!init_failed) { ++ /* Now scan the flash. */ ++ if (dev->param.is_yaffs2) { ++ if (yaffs2_checkpt_restore(dev)) { ++ yaffs_check_obj_details_loaded(dev->root_dir); ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT | ++ YAFFS_TRACE_MOUNT, ++ "yaffs: restored from checkpoint" ++ ); ++ } else { ++ ++ /* Clean up the mess caused by an aborted ++ * checkpoint load then scan backwards. ++ */ ++ yaffs_deinit_blocks(dev); ++ ++ yaffs_deinit_tnodes_and_objs(dev); ++ ++ dev->n_erased_blocks = 0; ++ dev->n_free_chunks = 0; ++ dev->alloc_block = -1; ++ dev->alloc_page = -1; ++ dev->n_deleted_files = 0; ++ dev->n_unlinked_files = 0; ++ dev->n_bg_deletions = 0; ++ ++ if (!init_failed && !yaffs_init_blocks(dev)) ++ init_failed = 1; ++ ++ yaffs_init_tnodes_and_objs(dev); ++ ++ if (!init_failed ++ && !yaffs_create_initial_dir(dev)) ++ init_failed = 1; ++ ++ if (!init_failed && !yaffs2_scan_backwards(dev)) ++ init_failed = 1; ++ } ++ } else if (!yaffs1_scan(dev)) { ++ init_failed = 1; ++ } ++ ++ yaffs_strip_deleted_objs(dev); ++ yaffs_fix_hanging_objs(dev); ++ if (dev->param.empty_lost_n_found) ++ yaffs_empty_l_n_f(dev); ++ } ++ ++ if (init_failed) { ++ /* Clean up the mess */ ++ yaffs_trace(YAFFS_TRACE_TRACING, ++ "yaffs: yaffs_guts_initialise() aborted."); ++ ++ yaffs_deinitialise(dev); ++ return YAFFS_FAIL; ++ } ++ ++ /* Zero out stats */ ++ dev->n_page_reads = 0; ++ dev->n_page_writes = 0; ++ dev->n_erasures = 0; ++ dev->n_gc_copies = 0; ++ dev->n_retried_writes = 0; ++ ++ dev->n_retired_blocks = 0; ++ ++ yaffs_verify_free_chunks(dev); ++ yaffs_verify_blocks(dev); ++ ++ /* Clean up any aborted checkpoint data */ ++ if (!dev->is_checkpointed && dev->blocks_in_checkpt > 0) ++ yaffs2_checkpt_invalidate(dev); ++ ++ yaffs_trace(YAFFS_TRACE_TRACING, ++ "yaffs: yaffs_guts_initialise() done."); ++ return YAFFS_OK; ++} ++ ++void yaffs_deinitialise(struct yaffs_dev *dev) ++{ ++ if (dev->is_mounted) { ++ u32 i; ++ ++ yaffs_deinit_blocks(dev); ++ yaffs_deinit_tnodes_and_objs(dev); ++ yaffs_summary_deinit(dev); ++ ++ if (dev->param.n_caches > 0 && dev->cache) { ++ ++ for (i = 0; i < dev->param.n_caches; i++) { ++ kfree(dev->cache[i].data); ++ dev->cache[i].data = NULL; ++ } ++ ++ kfree(dev->cache); ++ dev->cache = NULL; ++ } ++ ++ kfree(dev->gc_cleanup_list); ++ ++ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { ++ kfree(dev->temp_buffer[i].buffer); ++ dev->temp_buffer[i].buffer = NULL; ++ } ++ ++ kfree(dev->checkpt_buffer); ++ dev->checkpt_buffer = NULL; ++ kfree(dev->checkpt_block_list); ++ dev->checkpt_block_list = NULL; ++ ++ dev->is_mounted = 0; ++ ++ yaffs_deinit_nand(dev); ++ } ++} ++ ++int yaffs_count_free_chunks(struct yaffs_dev *dev) ++{ ++ int n_free = 0; ++ u32 b; ++ struct yaffs_block_info *blk; ++ ++ blk = dev->block_info; ++ for (b = dev->internal_start_block; b <= dev->internal_end_block; b++) { ++ switch (blk->block_state) { ++ case YAFFS_BLOCK_STATE_EMPTY: ++ case YAFFS_BLOCK_STATE_ALLOCATING: ++ case YAFFS_BLOCK_STATE_COLLECTING: ++ case YAFFS_BLOCK_STATE_FULL: ++ n_free += ++ (dev->param.chunks_per_block - blk->pages_in_use + ++ blk->soft_del_pages); ++ break; ++ default: ++ break; ++ } ++ blk++; ++ } ++ return n_free; ++} ++ ++int yaffs_get_n_free_chunks(struct yaffs_dev *dev) ++{ ++ /* This is what we report to the outside world */ ++ int n_free; ++ int n_dirty_caches; ++ int blocks_for_checkpt; ++ u32 i; ++ ++ n_free = dev->n_free_chunks; ++ n_free += dev->n_deleted_files; ++ ++ /* Now count and subtract the number of dirty chunks in the cache. */ ++ ++ for (n_dirty_caches = 0, i = 0; i < dev->param.n_caches; i++) { ++ if (dev->cache[i].dirty) ++ n_dirty_caches++; ++ } ++ ++ n_free -= n_dirty_caches; ++ ++ n_free -= ++ ((dev->param.n_reserved_blocks + 1) * dev->param.chunks_per_block); ++ ++ /* Now figure checkpoint space and report that... */ ++ blocks_for_checkpt = yaffs_calc_checkpt_blocks_required(dev); ++ ++ n_free -= (blocks_for_checkpt * dev->param.chunks_per_block); ++ ++ if (n_free < 0) ++ n_free = 0; ++ ++ return n_free; ++} ++ ++ ++/* ++ * Marshalling functions to get loff_t file sizes into and out of ++ * object headers. ++ */ ++void yaffs_oh_size_load(struct yaffs_dev *dev, ++ struct yaffs_obj_hdr *oh, ++ loff_t fsize, ++ int do_endian) ++{ ++ oh->file_size_low = FSIZE_LOW(fsize); ++ ++ oh->file_size_high = FSIZE_HIGH(fsize); ++ ++ if (do_endian) { ++ yaffs_do_endian_u32(dev, &oh->file_size_low); ++ yaffs_do_endian_u32(dev, &oh->file_size_high); ++ } ++} ++ ++loff_t yaffs_oh_to_size(struct yaffs_dev *dev, struct yaffs_obj_hdr *oh, ++ int do_endian) ++{ ++ loff_t retval; ++ ++ ++ if (sizeof(loff_t) >= 8 && ~(oh->file_size_high)) { ++ u32 low = oh->file_size_low; ++ u32 high = oh->file_size_high; ++ ++ if (do_endian) { ++ yaffs_do_endian_u32 (dev, &low); ++ yaffs_do_endian_u32 (dev, &high); ++ } ++ retval = FSIZE_COMBINE(high, low); ++ } else { ++ u32 low = oh->file_size_low; ++ ++ if (do_endian) ++ yaffs_do_endian_u32(dev, &low); ++ retval = (loff_t)low; ++ } ++ ++ return retval; ++} ++ ++ ++void yaffs_count_blocks_by_state(struct yaffs_dev *dev, int bs[10]) ++{ ++ u32 i; ++ struct yaffs_block_info *bi; ++ int s; ++ ++ for(i = 0; i < 10; i++) ++ bs[i] = 0; ++ ++ for(i = dev->internal_start_block; i <= dev->internal_end_block; i++) { ++ bi = yaffs_get_block_info(dev, i); ++ s = bi->block_state; ++ if(s > YAFFS_BLOCK_STATE_DEAD || s < YAFFS_BLOCK_STATE_UNKNOWN) ++ bs[0]++; ++ else ++ bs[s]++; ++ } ++} +diff --git a/fs/yaffs2/yaffs_guts.h b/fs/yaffs2/yaffs_guts.h +new file mode 100644 +index 0000000..974396f +--- /dev/null ++++ b/fs/yaffs2/yaffs_guts.h +@@ -0,0 +1,1070 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_GUTS_H__ ++#define __YAFFS_GUTS_H__ ++ ++#include "yportenv.h" ++ ++#define YAFFS_OK 1 ++#define YAFFS_FAIL 0 ++ ++/* Give us a Y=0x59, ++ * Give us an A=0x41, ++ * Give us an FF=0xff ++ * Give us an S=0x53 ++ * And what have we got... ++ */ ++#define YAFFS_MAGIC 0x5941ff53 ++ ++/* ++ * Tnodes form a tree with the tnodes in "levels" ++ * Levels greater than 0 hold 8 slots which point to other tnodes. ++ * Those at level 0 hold 16 slots which point to chunks in NAND. ++ * ++ * A maximum level of 8 thust supports files of size up to: ++ * ++ * 2^(3*MAX_LEVEL+4) ++ * ++ * Thus a max level of 8 supports files with up to 2^^28 chunks which gives ++ * a maximum file size of around 512Gbytees with 2k chunks. ++ */ ++#define YAFFS_NTNODES_LEVEL0 16 ++#define YAFFS_TNODES_LEVEL0_BITS 4 ++#define YAFFS_TNODES_LEVEL0_MASK 0xf ++ ++#define YAFFS_NTNODES_INTERNAL (YAFFS_NTNODES_LEVEL0 / 2) ++#define YAFFS_TNODES_INTERNAL_BITS (YAFFS_TNODES_LEVEL0_BITS - 1) ++#define YAFFS_TNODES_INTERNAL_MASK 0x7 ++#define YAFFS_TNODES_MAX_LEVEL 8 ++#define YAFFS_TNODES_MAX_BITS (YAFFS_TNODES_LEVEL0_BITS + \ ++ YAFFS_TNODES_INTERNAL_BITS * \ ++ YAFFS_TNODES_MAX_LEVEL) ++#define YAFFS_MAX_CHUNK_ID ((1 << YAFFS_TNODES_MAX_BITS) - 1) ++ ++#define YAFFS_MAX_FILE_SIZE_32 0x7fffffff ++ ++/* Constants for YAFFS1 mode */ ++#define YAFFS_BYTES_PER_SPARE 16 ++#define YAFFS_BYTES_PER_CHUNK 512 ++#define YAFFS_CHUNK_SIZE_SHIFT 9 ++#define YAFFS_CHUNKS_PER_BLOCK 32 ++#define YAFFS_BYTES_PER_BLOCK (YAFFS_CHUNKS_PER_BLOCK*YAFFS_BYTES_PER_CHUNK) ++ ++#define YAFFS_MIN_YAFFS2_CHUNK_SIZE 1024 ++#define YAFFS_MIN_YAFFS2_SPARE_SIZE 32 ++ ++ ++ ++#define YAFFS_ALLOCATION_NOBJECTS 100 ++#define YAFFS_ALLOCATION_NTNODES 100 ++#define YAFFS_ALLOCATION_NLINKS 100 ++ ++#define YAFFS_NOBJECT_BUCKETS 256 ++ ++#define YAFFS_OBJECT_SPACE 0x40000 ++#define YAFFS_MAX_OBJECT_ID (YAFFS_OBJECT_SPACE - 1) ++ ++/* Binary data version stamps */ ++#define YAFFS_SUMMARY_VERSION 1 ++ ++#ifdef CONFIG_YAFFS_UNICODE ++#define YAFFS_MAX_NAME_LENGTH 127 ++#define YAFFS_MAX_ALIAS_LENGTH 79 ++#else ++#define YAFFS_MAX_NAME_LENGTH 255 ++#define YAFFS_MAX_ALIAS_LENGTH 159 ++#endif ++ ++#define YAFFS_SHORT_NAME_LENGTH 15 ++ ++/* Some special object ids for pseudo objects */ ++#define YAFFS_OBJECTID_ROOT 1 ++#define YAFFS_OBJECTID_LOSTNFOUND 2 ++#define YAFFS_OBJECTID_UNLINKED 3 ++#define YAFFS_OBJECTID_DELETED 4 ++ ++/* Fake object Id for summary data */ ++#define YAFFS_OBJECTID_SUMMARY 0x10 ++ ++/* Pseudo object ids for checkpointing */ ++#define YAFFS_OBJECTID_CHECKPOINT_DATA 0x20 ++#define YAFFS_SEQUENCE_CHECKPOINT_DATA 0x21 ++ ++#define YAFFS_MAX_SHORT_OP_CACHES 20 ++ ++#define YAFFS_N_TEMP_BUFFERS 6 ++ ++/* We limit the number attempts at sucessfully saving a chunk of data. ++ * Small-page devices have 32 pages per block; large-page devices have 64. ++ * Default to something in the order of 5 to 10 blocks worth of chunks. ++ */ ++#define YAFFS_WR_ATTEMPTS (5*64) ++ ++/* Sequence numbers are used in YAFFS2 to determine block allocation order. ++ * The range is limited slightly to help distinguish bad numbers from good. ++ * This also allows us to perhaps in the future use special numbers for ++ * special purposes. ++ * EFFFFF00 allows the allocation of 8 blocks/second (~1Mbytes) for 15 years, ++ * and is a larger number than the lifetime of a 2GB device. ++ */ ++#define YAFFS_LOWEST_SEQUENCE_NUMBER 0x00001000 ++#define YAFFS_HIGHEST_SEQUENCE_NUMBER 0xefffff00 ++ ++/* Special sequence number for bad block that failed to be marked bad */ ++#define YAFFS_SEQUENCE_BAD_BLOCK 0xffff0000 ++ ++/* ChunkCache is used for short read/write operations.*/ ++struct yaffs_cache { ++ struct yaffs_obj *object; ++ int chunk_id; ++ int last_use; ++ int dirty; ++ int n_bytes; /* Only valid if the cache is dirty */ ++ int locked; /* Can't push out or flush while locked. */ ++ u8 *data; ++}; ++ ++/* yaffs1 tags structures in RAM ++ * NB This uses bitfield. Bitfields should not straddle a u32 boundary ++ * otherwise the structure size will get blown out. ++ */ ++ ++struct yaffs_tags { ++ u32 chunk_id:20; ++ u32 serial_number:2; ++ u32 n_bytes_lsb:10; ++ u32 obj_id:18; ++ u32 ecc:12; ++ u32 n_bytes_msb:2; ++}; ++ ++union yaffs_tags_union { ++ struct yaffs_tags as_tags; ++ u8 as_bytes[8]; ++ u32 as_u32[2]; ++}; ++ ++ ++/* Stuff used for extended tags in YAFFS2 */ ++ ++enum yaffs_ecc_result { ++ YAFFS_ECC_RESULT_UNKNOWN, ++ YAFFS_ECC_RESULT_NO_ERROR, ++ YAFFS_ECC_RESULT_FIXED, ++ YAFFS_ECC_RESULT_UNFIXED ++}; ++ ++/* ++ * Object type enum: ++ * When this is stored in flash we store it as a u32 instead ++ * to prevent any alignment change issues as compiler variants change. ++ */ ++ ++enum yaffs_obj_type { ++ YAFFS_OBJECT_TYPE_UNKNOWN, ++ YAFFS_OBJECT_TYPE_FILE, ++ YAFFS_OBJECT_TYPE_SYMLINK, ++ YAFFS_OBJECT_TYPE_DIRECTORY, ++ YAFFS_OBJECT_TYPE_HARDLINK, ++ YAFFS_OBJECT_TYPE_SPECIAL ++}; ++ ++#define YAFFS_OBJECT_TYPE_MAX YAFFS_OBJECT_TYPE_SPECIAL ++ ++struct yaffs_ext_tags { ++ unsigned chunk_used; /* Status of the chunk: used or unused */ ++ unsigned obj_id; /* If 0 this is not used */ ++ unsigned chunk_id; /* If 0 this is a header, else a data chunk */ ++ unsigned n_bytes; /* Only valid for data chunks */ ++ ++ /* The following stuff only has meaning when we read */ ++ enum yaffs_ecc_result ecc_result; ++ unsigned block_bad; ++ ++ /* YAFFS 1 stuff */ ++ unsigned is_deleted; /* The chunk is marked deleted */ ++ unsigned serial_number; /* Yaffs1 2-bit serial number */ ++ ++ /* YAFFS2 stuff */ ++ unsigned seq_number; /* The sequence number of this block */ ++ ++ /* Extra info if this is an object header (YAFFS2 only) */ ++ ++ unsigned extra_available; /* Extra info available if not zero */ ++ unsigned extra_parent_id; /* The parent object */ ++ unsigned extra_is_shrink; /* Is it a shrink header? */ ++ unsigned extra_shadows; /* Does this shadow another object? */ ++ ++ enum yaffs_obj_type extra_obj_type; /* What object type? */ ++ ++ loff_t extra_file_size; /* Length if it is a file */ ++ unsigned extra_equiv_id; /* Equivalent object for a hard link */ ++}; ++ ++/* Spare structure for YAFFS1 */ ++struct yaffs_spare { ++ u8 tb0; ++ u8 tb1; ++ u8 tb2; ++ u8 tb3; ++ u8 page_status; /* set to 0 to delete the chunk */ ++ u8 block_status; ++ u8 tb4; ++ u8 tb5; ++ u8 ecc1[3]; ++ u8 tb6; ++ u8 tb7; ++ u8 ecc2[3]; ++}; ++ ++/*Special structure for passing through to mtd */ ++struct yaffs_nand_spare { ++ struct yaffs_spare spare; ++ int eccres1; ++ int eccres2; ++}; ++ ++/* Block data in RAM */ ++ ++enum yaffs_block_state { ++ YAFFS_BLOCK_STATE_UNKNOWN = 0, ++ ++ YAFFS_BLOCK_STATE_SCANNING, ++ /* Being scanned */ ++ ++ YAFFS_BLOCK_STATE_NEEDS_SCAN, ++ /* The block might have something on it (ie it is allocating or full, ++ * perhaps empty) but it needs to be scanned to determine its true ++ * state. ++ * This state is only valid during scanning. ++ * NB We tolerate empty because the pre-scanner might be incapable of ++ * deciding ++ * However, if this state is returned on a YAFFS2 device, ++ * then we expect a sequence number ++ */ ++ ++ YAFFS_BLOCK_STATE_EMPTY, ++ /* This block is empty */ ++ ++ YAFFS_BLOCK_STATE_ALLOCATING, ++ /* This block is partially allocated. ++ * At least one page holds valid data. ++ * This is the one currently being used for page ++ * allocation. Should never be more than one of these. ++ * If a block is only partially allocated at mount it is treated as ++ * full. ++ */ ++ ++ YAFFS_BLOCK_STATE_FULL, ++ /* All the pages in this block have been allocated. ++ * If a block was only partially allocated when mounted we treat ++ * it as fully allocated. ++ */ ++ ++ YAFFS_BLOCK_STATE_DIRTY, ++ /* The block was full and now all chunks have been deleted. ++ * Erase me, reuse me. ++ */ ++ ++ YAFFS_BLOCK_STATE_CHECKPOINT, ++ /* This block is assigned to holding checkpoint data. */ ++ ++ YAFFS_BLOCK_STATE_COLLECTING, ++ /* This block is being garbage collected */ ++ ++ YAFFS_BLOCK_STATE_DEAD ++ /* This block has failed and is not in use */ ++}; ++ ++#define YAFFS_NUMBER_OF_BLOCK_STATES (YAFFS_BLOCK_STATE_DEAD + 1) ++ ++struct yaffs_block_info { ++ ++ s32 soft_del_pages:10; /* number of soft deleted pages */ ++ s32 pages_in_use:10; /* number of pages in use */ ++ u32 block_state:4; /* One of the above block states. */ ++ /* NB use unsigned because enum is sometimes ++ * an int */ ++ u32 needs_retiring:1; /* Data has failed on this block, */ ++ /*need to get valid data off and retire*/ ++ u32 skip_erased_check:1;/* Skip the erased check on this block */ ++ u32 gc_prioritise:1; /* An ECC check or blank check has failed. ++ Block should be prioritised for GC */ ++ u32 chunk_error_strikes:3; /* How many times we've had ecc etc ++ failures on this block and tried to reuse it */ ++ u32 has_summary:1; /* The block has a summary */ ++ ++ u32 has_shrink_hdr:1; /* This block has at least one shrink header */ ++ u32 seq_number; /* block sequence number for yaffs2 */ ++ ++}; ++ ++union yaffs_block_info_union { ++ struct yaffs_block_info bi; ++ u32 as_u32[2]; ++}; ++ ++/* -------------------------- Object structure -------------------------------*/ ++/* This is the object structure as stored on NAND */ ++ ++struct yaffs_obj_hdr { ++ u32 type; /* enum yaffs_obj_type */ ++ ++ /* Apply to everything */ ++ u32 parent_obj_id; ++ u16 sum_no_longer_used; /* checksum of name. No longer used */ ++ YCHAR name[YAFFS_MAX_NAME_LENGTH + 1]; ++ ++ /* The following apply to all object types except for hard links */ ++ u32 yst_mode; /* protection */ ++ ++ u32 yst_uid; ++ u32 yst_gid; ++ u32 yst_atime; ++ u32 yst_mtime; ++ u32 yst_ctime; ++ ++ /* File size applies to files only */ ++ u32 file_size_low; ++ ++ /* Equivalent object id applies to hard links only. */ ++ int equiv_id; ++ ++ /* Alias is for symlinks only. */ ++ YCHAR alias[YAFFS_MAX_ALIAS_LENGTH + 1]; ++ ++ u32 yst_rdev; /* stuff for block and char devices (major/min) */ ++ ++ u32 win_ctime[2]; ++ u32 win_atime[2]; ++ u32 win_mtime[2]; ++ ++ u32 inband_shadowed_obj_id; ++ u32 inband_is_shrink; ++ ++ u32 file_size_high; ++ u32 reserved[1]; ++ int shadows_obj; /* This object header shadows the ++ specified object if > 0 */ ++ ++ /* is_shrink applies to object headers written when wemake a hole. */ ++ u32 is_shrink; ++ ++}; ++ ++/*--------------------------- Tnode -------------------------- */ ++ ++struct yaffs_tnode { ++ struct yaffs_tnode *internal[YAFFS_NTNODES_INTERNAL]; ++}; ++ ++/*------------------------ Object -----------------------------*/ ++/* An object can be one of: ++ * - a directory (no data, has children links ++ * - a regular file (data.... not prunes :->). ++ * - a symlink [symbolic link] (the alias). ++ * - a hard link ++ */ ++ ++/* The file variant has three file sizes: ++ * - file_size : size of file as written into Yaffs - including data in cache. ++ * - stored_size - size of file as stored on media. ++ * - shrink_size - size of file that has been shrunk back to. ++ * ++ * The stored_size and file_size might be different because the data written ++ * into the cache will increase the file_size but the stored_size will only ++ * change when the data is actually stored. ++ * ++ */ ++struct yaffs_file_var { ++ loff_t file_size; ++ loff_t stored_size; ++ loff_t shrink_size; ++ int top_level; ++ struct yaffs_tnode *top; ++}; ++ ++struct yaffs_dir_var { ++ struct list_head children; /* list of child links */ ++ struct list_head dirty; /* Entry for list of dirty directories */ ++}; ++ ++struct yaffs_symlink_var { ++ YCHAR *alias; ++}; ++ ++struct yaffs_hardlink_var { ++ struct yaffs_obj *equiv_obj; ++ u32 equiv_id; ++}; ++ ++union yaffs_obj_var { ++ struct yaffs_file_var file_variant; ++ struct yaffs_dir_var dir_variant; ++ struct yaffs_symlink_var symlink_variant; ++ struct yaffs_hardlink_var hardlink_variant; ++}; ++ ++struct yaffs_obj { ++ u8 deleted:1; /* This should only apply to unlinked files. */ ++ u8 soft_del:1; /* it has also been soft deleted */ ++ u8 unlinked:1; /* An unlinked file.*/ ++ u8 fake:1; /* A fake object has no presence on NAND. */ ++ u8 rename_allowed:1; /* Some objects cannot be renamed. */ ++ u8 unlink_allowed:1; ++ u8 dirty:1; /* the object needs to be written to flash */ ++ u8 valid:1; /* When the file system is being loaded up, this ++ * object might be created before the data ++ * is available ++ * ie. file data chunks encountered before ++ * the header. ++ */ ++ u8 lazy_loaded:1; /* This object has been lazy loaded and ++ * is missing some detail */ ++ ++ u8 defered_free:1; /* Object is removed from NAND, but is ++ * still in the inode cache. ++ * Free of object is defered. ++ * until the inode is released. ++ */ ++ u8 being_created:1; /* This object is still being created ++ * so skip some verification checks. */ ++ u8 is_shadowed:1; /* This object is shadowed on the way ++ * to being renamed. */ ++ ++ u8 xattr_known:1; /* We know if this has object has xattribs ++ * or not. */ ++ u8 has_xattr:1; /* This object has xattribs. ++ * Only valid if xattr_known. */ ++ ++ u8 serial; /* serial number of chunk in NAND.*/ ++ u16 sum; /* sum of the name to speed searching */ ++ ++ struct yaffs_dev *my_dev; /* The device I'm on */ ++ ++ struct list_head hash_link; /* list of objects in hash bucket */ ++ ++ struct list_head hard_links; /* hard linked object chain*/ ++ ++ /* directory structure stuff */ ++ /* also used for linking up the free list */ ++ struct yaffs_obj *parent; ++ struct list_head siblings; ++ ++ /* Where's my object header in NAND? */ ++ int hdr_chunk; ++ ++ int n_data_chunks; /* Number of data chunks for this file. */ ++ ++ u32 obj_id; /* the object id value */ ++ ++ u32 yst_mode; ++ ++ YCHAR short_name[YAFFS_SHORT_NAME_LENGTH + 1]; ++ ++#ifdef CONFIG_YAFFS_WINCE ++ u32 win_ctime[2]; ++ u32 win_mtime[2]; ++ u32 win_atime[2]; ++#else ++ u32 yst_uid; ++ u32 yst_gid; ++ u32 yst_atime; ++ u32 yst_mtime; ++ u32 yst_ctime; ++#endif ++ ++ u32 yst_rdev; ++ ++ void *my_inode; ++ ++ u32 variant_type; /* enum yaffs_object_type */ ++ ++ union yaffs_obj_var variant; ++ ++}; ++ ++struct yaffs_obj_bucket { ++ struct list_head list; ++ int count; ++}; ++ ++ ++/*--------------------- Temporary buffers ---------------- ++ * ++ * These are chunk-sized working buffers. Each device has a few. ++ */ ++ ++struct yaffs_buffer { ++ u8 *buffer; ++ int in_use; ++}; ++ ++/*----------------- Device ---------------------------------*/ ++ ++struct yaffs_param { ++ const YCHAR *name; ++ ++ /* ++ * Entry parameters set up way early. Yaffs sets up the rest. ++ * The structure should be zeroed out before use so that unused ++ * and default values are zero. ++ */ ++ ++ int inband_tags; /* Use unband tags */ ++ u32 total_bytes_per_chunk; /* Should be >= 512, does not need to ++ be a power of 2 */ ++ u32 chunks_per_block; /* does not need to be a power of 2 */ ++ u32 spare_bytes_per_chunk; /* spare area size */ ++ u32 start_block; /* Start block we're allowed to use */ ++ u32 end_block; /* End block we're allowed to use */ ++ u32 n_reserved_blocks; /* Tuneable so that we can reduce ++ * reserved blocks on NOR and RAM. */ ++ ++ u32 n_caches; /* If == 0, then short op caching is disabled, ++ * else the number of short op caches. ++ */ ++ int cache_bypass_aligned; /* If non-zero then bypass the cache for ++ * aligned writes. ++ */ ++ ++ int use_nand_ecc; /* Flag to decide whether or not to use ++ * NAND driver ECC on data (yaffs1) */ ++ int tags_9bytes; /* Use 9 byte tags */ ++ int no_tags_ecc; /* Flag to decide whether or not to do ECC ++ * on packed tags (yaffs2) */ ++ ++ int is_yaffs2; /* Use yaffs2 mode on this device */ ++ ++ int empty_lost_n_found; /* Auto-empty lost+found directory on mount */ ++ ++ int refresh_period; /* How often to check for a block refresh */ ++ ++ /* Checkpoint control. Can be set before or after initialisation */ ++ u8 skip_checkpt_rd; ++ u8 skip_checkpt_wr; ++ ++ int enable_xattr; /* Enable xattribs */ ++ ++ int max_objects; /* ++ * Set to limit the number of objects created. ++ * 0 = no limit. ++ */ ++ ++ int hide_lost_n_found; /* Set non-zero to hide the lost-n-found dir. */ ++ ++ int stored_endian; /* 0=cpu endian, 1=little endian, 2=big endian */ ++ ++ /* The remove_obj_fn function must be supplied by OS flavours that ++ * need it. ++ * yaffs direct uses it to implement the faster readdir. ++ * Linux uses it to protect the directory during unlocking. ++ */ ++ void (*remove_obj_fn) (struct yaffs_obj *obj); ++ ++ /* Callback to mark the superblock dirty */ ++ void (*sb_dirty_fn) (struct yaffs_dev *dev); ++ ++ /* Callback to control garbage collection. */ ++ unsigned (*gc_control_fn) (struct yaffs_dev *dev); ++ ++ /* Debug control flags. Don't use unless you know what you're doing */ ++ int use_header_file_size; /* Flag to determine if we should use ++ * file sizes from the header */ ++ int disable_lazy_load; /* Disable lazy loading on this device */ ++ int wide_tnodes_disabled; /* Set to disable wide tnodes */ ++ int disable_soft_del; /* yaffs 1 only: Set to disable the use of ++ * softdeletion. */ ++ ++ int defered_dir_update; /* Set to defer directory updates */ ++ ++#ifdef CONFIG_YAFFS_AUTO_UNICODE ++ int auto_unicode; ++#endif ++ int always_check_erased; /* Force chunk erased check always on */ ++ ++ int disable_summary; ++ int disable_bad_block_marking; ++ ++}; ++ ++struct yaffs_driver { ++ int (*drv_write_chunk_fn) (struct yaffs_dev *dev, int nand_chunk, ++ const u8 *data, int data_len, ++ const u8 *oob, int oob_len); ++ int (*drv_read_chunk_fn) (struct yaffs_dev *dev, int nand_chunk, ++ u8 *data, int data_len, ++ u8 *oob, int oob_len, ++ enum yaffs_ecc_result *ecc_result); ++ int (*drv_erase_fn) (struct yaffs_dev *dev, int block_no); ++ int (*drv_mark_bad_fn) (struct yaffs_dev *dev, int block_no); ++ int (*drv_check_bad_fn) (struct yaffs_dev *dev, int block_no); ++ int (*drv_initialise_fn) (struct yaffs_dev *dev); ++ int (*drv_deinitialise_fn) (struct yaffs_dev *dev); ++}; ++ ++struct yaffs_tags_handler { ++ int (*write_chunk_tags_fn) (struct yaffs_dev *dev, ++ int nand_chunk, const u8 *data, ++ const struct yaffs_ext_tags *tags); ++ int (*read_chunk_tags_fn) (struct yaffs_dev *dev, ++ int nand_chunk, u8 *data, ++ struct yaffs_ext_tags *tags); ++ ++ int (*query_block_fn) (struct yaffs_dev *dev, int block_no, ++ enum yaffs_block_state *state, ++ u32 *seq_number); ++ int (*mark_bad_fn) (struct yaffs_dev *dev, int block_no); ++}; ++ ++struct yaffs_dev { ++ struct yaffs_param param; ++ struct yaffs_driver drv; ++ struct yaffs_tags_handler tagger; ++ ++ /* Context storage. Holds extra OS specific data for this device */ ++ ++ void *os_context; ++ void *driver_context; ++ ++ struct list_head dev_list; ++ ++ int ll_init; ++ /* Runtime parameters. Set up by YAFFS. */ ++ u32 data_bytes_per_chunk; ++ ++ /* Non-wide tnode stuff */ ++ u16 chunk_grp_bits; /* Number of bits that need to be resolved if ++ * the tnodes are not wide enough. ++ */ ++ u16 chunk_grp_size; /* == 2^^chunk_grp_bits */ ++ ++ struct yaffs_tnode *tn_swap_buffer; ++ ++ /* Stuff to support wide tnodes */ ++ u32 tnode_width; ++ u32 tnode_mask; ++ u32 tnode_size; ++ ++ /* Stuff for figuring out file offset to chunk conversions */ ++ u32 chunk_shift; /* Shift value */ ++ u32 chunk_div; /* Divisor after shifting: 1 for 2^n sizes */ ++ u32 chunk_mask; /* Mask to use for power-of-2 case */ ++ ++ int is_mounted; ++ int read_only; ++ int is_checkpointed; ++ int swap_endian; /* Stored endian needs endian swap. */ ++ ++ /* Stuff to support block offsetting to support start block zero */ ++ u32 internal_start_block; ++ u32 internal_end_block; ++ int block_offset; ++ int chunk_offset; ++ ++ /* Runtime checkpointing stuff */ ++ int checkpt_page_seq; /* running sequence number of checkpt pages */ ++ int checkpt_byte_count; ++ int checkpt_byte_offs; ++ u8 *checkpt_buffer; ++ int checkpt_open_write; ++ u32 blocks_in_checkpt; ++ int checkpt_cur_chunk; ++ int checkpt_cur_block; ++ int checkpt_next_block; ++ int *checkpt_block_list; ++ u32 checkpt_max_blocks; ++ u32 checkpt_sum; ++ u32 checkpt_xor; ++ ++ int checkpoint_blocks_required; /* Number of blocks needed to store ++ * current checkpoint set */ ++ ++ /* Block Info */ ++ struct yaffs_block_info *block_info; ++ u8 *chunk_bits; /* bitmap of chunks in use */ ++ u8 block_info_alt:1; /* allocated using alternative alloc */ ++ u8 chunk_bits_alt:1; /* allocated using alternative alloc */ ++ int chunk_bit_stride; /* Number of bytes of chunk_bits per block. ++ * Must be consistent with chunks_per_block. ++ */ ++ ++ int n_erased_blocks; ++ int alloc_block; /* Current block being allocated off */ ++ u32 alloc_page; ++ int alloc_block_finder; /* Used to search for next allocation block */ ++ ++ /* Object and Tnode memory management */ ++ void *allocator; ++ int n_obj; ++ int n_tnodes; ++ ++ int n_hardlinks; ++ ++ struct yaffs_obj_bucket obj_bucket[YAFFS_NOBJECT_BUCKETS]; ++ u32 bucket_finder; ++ ++ int n_free_chunks; ++ ++ /* Garbage collection control */ ++ u32 *gc_cleanup_list; /* objects to delete at the end of a GC. */ ++ u32 n_clean_ups; ++ ++ unsigned has_pending_prioritised_gc; /* We think this device might ++ have pending prioritised gcs */ ++ unsigned gc_disable; ++ unsigned gc_block_finder; ++ unsigned gc_dirtiest; ++ unsigned gc_pages_in_use; ++ unsigned gc_not_done; ++ unsigned gc_block; ++ unsigned gc_chunk; ++ unsigned gc_skip; ++ struct yaffs_summary_tags *gc_sum_tags; ++ ++ /* Special directories */ ++ struct yaffs_obj *root_dir; ++ struct yaffs_obj *lost_n_found; ++ ++ int buffered_block; /* Which block is buffered here? */ ++ int doing_buffered_block_rewrite; ++ ++ struct yaffs_cache *cache; ++ int cache_last_use; ++ ++ /* Stuff for background deletion and unlinked files. */ ++ struct yaffs_obj *unlinked_dir; /* Directory where unlinked and deleted ++ files live. */ ++ struct yaffs_obj *del_dir; /* Directory where deleted objects are ++ sent to disappear. */ ++ struct yaffs_obj *unlinked_deletion; /* Current file being ++ background deleted. */ ++ int n_deleted_files; /* Count of files awaiting deletion; */ ++ int n_unlinked_files; /* Count of unlinked files. */ ++ int n_bg_deletions; /* Count of background deletions. */ ++ ++ /* Temporary buffer management */ ++ struct yaffs_buffer temp_buffer[YAFFS_N_TEMP_BUFFERS]; ++ int max_temp; ++ int temp_in_use; ++ int unmanaged_buffer_allocs; ++ int unmanaged_buffer_deallocs; ++ ++ /* yaffs2 runtime stuff */ ++ unsigned seq_number; /* Sequence number of currently ++ allocating block */ ++ unsigned oldest_dirty_seq; ++ unsigned oldest_dirty_block; ++ ++ /* Block refreshing */ ++ int refresh_skip; /* A skip down counter. ++ * Refresh happens when this gets to zero. */ ++ ++ /* Dirty directory handling */ ++ struct list_head dirty_dirs; /* List of dirty directories */ ++ ++ /* Summary */ ++ int chunks_per_summary; ++ struct yaffs_summary_tags *sum_tags; ++ ++ /* Statistics */ ++ u32 n_page_writes; ++ u32 n_page_reads; ++ u32 n_erasures; ++ u32 n_bad_queries; ++ u32 n_bad_markings; ++ u32 n_erase_failures; ++ u32 n_gc_copies; ++ u32 all_gcs; ++ u32 passive_gc_count; ++ u32 oldest_dirty_gc_count; ++ u32 n_gc_blocks; ++ u32 bg_gcs; ++ u32 n_retried_writes; ++ u32 n_retired_blocks; ++ u32 n_ecc_fixed; ++ u32 n_ecc_unfixed; ++ u32 n_tags_ecc_fixed; ++ u32 n_tags_ecc_unfixed; ++ u32 n_deletions; ++ u32 n_unmarked_deletions; ++ u32 refresh_count; ++ u32 cache_hits; ++ u32 tags_used; ++ u32 summary_used; ++ ++}; ++ ++/* ++ * Checkpointing definitions. ++ */ ++ ++#define YAFFS_CHECKPOINT_VERSION 8 ++ ++/* yaffs_checkpt_obj holds the definition of an object as dumped ++ * by checkpointing. ++ */ ++ ++ ++/* Checkpint object bits in bitfield: offset, length */ ++#define CHECKPOINT_VARIANT_BITS 0, 3 ++#define CHECKPOINT_DELETED_BITS 3, 1 ++#define CHECKPOINT_SOFT_DEL_BITS 4, 1 ++#define CHECKPOINT_UNLINKED_BITS 5, 1 ++#define CHECKPOINT_FAKE_BITS 6, 1 ++#define CHECKPOINT_RENAME_ALLOWED_BITS 7, 1 ++#define CHECKPOINT_UNLINK_ALLOWED_BITS 8, 1 ++#define CHECKPOINT_SERIAL_BITS 9, 8 ++ ++struct yaffs_checkpt_obj { ++ int struct_type; ++ u32 obj_id; ++ u32 parent_id; ++ int hdr_chunk; ++ u32 bit_field; ++ int n_data_chunks; ++ loff_t size_or_equiv_obj; ++}; ++ ++/* The CheckpointDevice structure holds the device information that changes ++ *at runtime and must be preserved over unmount/mount cycles. ++ */ ++struct yaffs_checkpt_dev { ++ int struct_type; ++ int n_erased_blocks; ++ int alloc_block; /* Current block being allocated off */ ++ u32 alloc_page; ++ int n_free_chunks; ++ ++ int n_deleted_files; /* Count of files awaiting deletion; */ ++ int n_unlinked_files; /* Count of unlinked files. */ ++ int n_bg_deletions; /* Count of background deletions. */ ++ ++ /* yaffs2 runtime stuff */ ++ unsigned seq_number; /* Sequence number of currently ++ * allocating block */ ++ ++}; ++ ++struct yaffs_checkpt_validity { ++ int struct_type; ++ u32 magic; ++ u32 version; ++ u32 head; ++}; ++ ++struct yaffs_shadow_fixer { ++ int obj_id; ++ int shadowed_id; ++ struct yaffs_shadow_fixer *next; ++}; ++ ++/* Structure for doing xattr modifications */ ++struct yaffs_xattr_mod { ++ int set; /* If 0 then this is a deletion */ ++ const YCHAR *name; ++ const void *data; ++ int size; ++ int flags; ++ int result; ++}; ++ ++/*----------------------- YAFFS Functions -----------------------*/ ++ ++int yaffs_guts_initialise(struct yaffs_dev *dev); ++void yaffs_deinitialise(struct yaffs_dev *dev); ++ ++int yaffs_get_n_free_chunks(struct yaffs_dev *dev); ++ ++int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR * old_name, ++ struct yaffs_obj *new_dir, const YCHAR * new_name); ++ ++int yaffs_unlink_obj(struct yaffs_obj *obj); ++ ++int yaffs_unlinker(struct yaffs_obj *dir, const YCHAR * name); ++int yaffs_del_obj(struct yaffs_obj *obj); ++struct yaffs_obj *yaffs_retype_obj(struct yaffs_obj *obj, ++ enum yaffs_obj_type type); ++ ++ ++int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR * name, int buffer_size); ++loff_t yaffs_get_obj_length(struct yaffs_obj *obj); ++int yaffs_get_obj_inode(struct yaffs_obj *obj); ++unsigned yaffs_get_obj_type(struct yaffs_obj *obj); ++int yaffs_get_obj_link_count(struct yaffs_obj *obj); ++ ++/* File operations */ ++int yaffs_file_rd(struct yaffs_obj *obj, u8 * buffer, loff_t offset, ++ int n_bytes); ++int yaffs_wr_file(struct yaffs_obj *obj, const u8 * buffer, loff_t offset, ++ int n_bytes, int write_trhrough); ++int yaffs_resize_file(struct yaffs_obj *obj, loff_t new_size); ++ ++struct yaffs_obj *yaffs_create_file(struct yaffs_obj *parent, ++ const YCHAR *name, u32 mode, u32 uid, ++ u32 gid); ++ ++int yaffs_flush_file(struct yaffs_obj *in, ++ int update_time, ++ int data_sync, ++ int discard_cache); ++ ++/* Flushing and checkpointing */ ++void yaffs_flush_whole_cache(struct yaffs_dev *dev, int discard); ++ ++int yaffs_checkpoint_save(struct yaffs_dev *dev); ++int yaffs_checkpoint_restore(struct yaffs_dev *dev); ++ ++/* Directory operations */ ++struct yaffs_obj *yaffs_create_dir(struct yaffs_obj *parent, const YCHAR *name, ++ u32 mode, u32 uid, u32 gid); ++struct yaffs_obj *yaffs_find_by_name(struct yaffs_obj *the_dir, ++ const YCHAR *name); ++struct yaffs_obj *yaffs_find_by_number(struct yaffs_dev *dev, u32 number); ++ ++/* Link operations */ ++struct yaffs_obj *yaffs_link_obj(struct yaffs_obj *parent, const YCHAR *name, ++ struct yaffs_obj *equiv_obj); ++ ++struct yaffs_obj *yaffs_get_equivalent_obj(struct yaffs_obj *obj); ++ ++/* Symlink operations */ ++struct yaffs_obj *yaffs_create_symlink(struct yaffs_obj *parent, ++ const YCHAR *name, u32 mode, u32 uid, ++ u32 gid, const YCHAR *alias); ++YCHAR *yaffs_get_symlink_alias(struct yaffs_obj *obj); ++ ++/* Special inodes (fifos, sockets and devices) */ ++struct yaffs_obj *yaffs_create_special(struct yaffs_obj *parent, ++ const YCHAR *name, u32 mode, u32 uid, ++ u32 gid, u32 rdev); ++ ++int yaffs_set_xattrib(struct yaffs_obj *obj, const YCHAR *name, ++ const void *value, int size, int flags); ++int yaffs_get_xattrib(struct yaffs_obj *obj, const YCHAR *name, void *value, ++ int size); ++int yaffs_list_xattrib(struct yaffs_obj *obj, char *buffer, int size); ++int yaffs_remove_xattrib(struct yaffs_obj *obj, const YCHAR *name); ++ ++/* Special directories */ ++struct yaffs_obj *yaffs_root(struct yaffs_dev *dev); ++struct yaffs_obj *yaffs_lost_n_found(struct yaffs_dev *dev); ++ ++void yaffs_handle_defered_free(struct yaffs_obj *obj); ++ ++void yaffs_update_dirty_dirs(struct yaffs_dev *dev); ++ ++int yaffs_bg_gc(struct yaffs_dev *dev, unsigned urgency); ++ ++/* Debug dump */ ++int yaffs_dump_obj(struct yaffs_obj *obj); ++ ++void yaffs_guts_test(struct yaffs_dev *dev); ++int yaffs_guts_ll_init(struct yaffs_dev *dev); ++ ++ ++/* A few useful functions to be used within the core files*/ ++void yaffs_chunk_del(struct yaffs_dev *dev, int chunk_id, int mark_flash, ++ int lyn); ++int yaffs_check_ff(u8 *buffer, int n_bytes); ++void yaffs_handle_chunk_error(struct yaffs_dev *dev, ++ struct yaffs_block_info *bi); ++ ++u8 *yaffs_get_temp_buffer(struct yaffs_dev *dev); ++void yaffs_release_temp_buffer(struct yaffs_dev *dev, u8 *buffer); ++ ++struct yaffs_obj *yaffs_find_or_create_by_number(struct yaffs_dev *dev, ++ int number, ++ enum yaffs_obj_type type); ++int yaffs_put_chunk_in_file(struct yaffs_obj *in, int inode_chunk, ++ int nand_chunk, int in_scan); ++void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR *name); ++void yaffs_set_obj_name_from_oh(struct yaffs_obj *obj, ++ const struct yaffs_obj_hdr *oh); ++void yaffs_add_obj_to_dir(struct yaffs_obj *directory, struct yaffs_obj *obj); ++YCHAR *yaffs_clone_str(const YCHAR *str); ++void yaffs_link_fixup(struct yaffs_dev *dev, struct list_head *hard_list); ++void yaffs_block_became_dirty(struct yaffs_dev *dev, int block_no); ++int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, ++ int force, int is_shrink, int shadows, ++ struct yaffs_xattr_mod *xop); ++void yaffs_handle_shadowed_obj(struct yaffs_dev *dev, int obj_id, ++ int backward_scanning); ++int yaffs_check_alloc_available(struct yaffs_dev *dev, int n_chunks); ++struct yaffs_tnode *yaffs_get_tnode(struct yaffs_dev *dev); ++struct yaffs_tnode *yaffs_add_find_tnode_0(struct yaffs_dev *dev, ++ struct yaffs_file_var *file_struct, ++ u32 chunk_id, ++ struct yaffs_tnode *passed_tn); ++ ++int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset, ++ int n_bytes, int write_trhrough); ++void yaffs_resize_file_down(struct yaffs_obj *obj, loff_t new_size); ++void yaffs_skip_rest_of_block(struct yaffs_dev *dev); ++ ++int yaffs_count_free_chunks(struct yaffs_dev *dev); ++ ++struct yaffs_tnode *yaffs_find_tnode_0(struct yaffs_dev *dev, ++ struct yaffs_file_var *file_struct, ++ u32 chunk_id); ++ ++u32 yaffs_get_group_base(struct yaffs_dev *dev, struct yaffs_tnode *tn, ++ unsigned pos); ++ ++int yaffs_is_non_empty_dir(struct yaffs_obj *obj); ++ ++int yaffs_guts_format_dev(struct yaffs_dev *dev); ++ ++void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr, ++ int *chunk_out, u32 *offset_out); ++/* ++ * Marshalling functions to get loff_t file sizes into and out of ++ * object headers. ++ */ ++void yaffs_oh_size_load(struct yaffs_dev *dev, struct yaffs_obj_hdr *oh, ++ loff_t fsize, int do_endian); ++loff_t yaffs_oh_to_size(struct yaffs_dev *dev, struct yaffs_obj_hdr *oh, ++ int do_endian); ++loff_t yaffs_max_file_size(struct yaffs_dev *dev); ++ ++/* ++ * Debug function to count number of blocks in each state ++ * NB Needs to be called with correct number of integers ++ */ ++ ++void yaffs_count_blocks_by_state(struct yaffs_dev *dev, int bs[10]); ++ ++int yaffs_find_chunk_in_file(struct yaffs_obj *in, int inode_chunk, ++ struct yaffs_ext_tags *tags); ++ ++/* ++ * Define LOFF_T_32_BIT if a 32-bit LOFF_T is being used. ++ * Not serious if you get this wrong - you might just get some warnings. ++*/ ++ ++#ifdef LOFF_T_32_BIT ++#define FSIZE_LOW(fsize) (fsize) ++#define FSIZE_HIGH(fsize) 0 ++#define FSIZE_COMBINE(high, low) (low) ++#else ++#define FSIZE_LOW(fsize) ((fsize) & 0xffffffff) ++#define FSIZE_HIGH(fsize)(((fsize) >> 32) & 0xffffffff) ++#define FSIZE_COMBINE(high, low) ((((loff_t) (high)) << 32) | \ ++ (((loff_t) (low)) & 0xFFFFFFFF)) ++#endif ++ ++ ++#endif +diff --git a/fs/yaffs2/yaffs_linux.h b/fs/yaffs2/yaffs_linux.h +new file mode 100644 +index 0000000..c20ab14 +--- /dev/null ++++ b/fs/yaffs2/yaffs_linux.h +@@ -0,0 +1,48 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_LINUX_H__ ++#define __YAFFS_LINUX_H__ ++ ++#include "yportenv.h" ++ ++struct yaffs_linux_context { ++ struct list_head context_list; /* List of these we have mounted */ ++ struct yaffs_dev *dev; ++ struct super_block *super; ++ struct task_struct *bg_thread; /* Background thread for this device */ ++ int bg_running; ++ struct mutex gross_lock; /* Gross locking mutex*/ ++ u8 *spare_buffer; /* For mtdif2 use. Don't know the buffer size ++ * at compile time so we have to allocate it. ++ */ ++ struct list_head search_contexts; ++ struct task_struct *readdir_process; ++ unsigned mount_id; ++ int dirty; ++}; ++ ++#define yaffs_dev_to_lc(dev) ((struct yaffs_linux_context *)((dev)->os_context)) ++#define yaffs_dev_to_mtd(dev) ((struct mtd_info *)((dev)->driver_context)) ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) ++#define WRITE_SIZE_STR "writesize" ++#define WRITE_SIZE(mtd) ((mtd)->writesize) ++#else ++#define WRITE_SIZE_STR "oobblock" ++#define WRITE_SIZE(mtd) ((mtd)->oobblock) ++#endif ++ ++#endif +diff --git a/fs/yaffs2/yaffs_mtdif.c b/fs/yaffs2/yaffs_mtdif.c +new file mode 100644 +index 0000000..7c01461 +--- /dev/null ++++ b/fs/yaffs2/yaffs_mtdif.c +@@ -0,0 +1,310 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * 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 "yportenv.h" ++ ++#include "yaffs_mtdif.h" ++ ++#include "linux/mtd/mtd.h" ++#include "linux/types.h" ++#include "linux/time.h" ++#include "linux/mtd/nand.h" ++#include "linux/kernel.h" ++#include "linux/version.h" ++#include "linux/types.h" ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) ++#include "uapi/linux/major.h" ++#endif ++ ++#include "yaffs_trace.h" ++#include "yaffs_guts.h" ++#include "yaffs_linux.h" ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) ++#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO ++#endif ++ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) ++#define mtd_erase(m, ei) (m)->erase(m, ei) ++#define mtd_write_oob(m, addr, pops) (m)->write_oob(m, addr, pops) ++#define mtd_read_oob(m, addr, pops) (m)->read_oob(m, addr, pops) ++#define mtd_block_isbad(m, offs) (m)->block_isbad(m, offs) ++#define mtd_block_markbad(m, offs) (m)->block_markbad(m, offs) ++#endif ++ ++ ++ ++int nandmtd_erase_block(struct yaffs_dev *dev, int block_no) ++{ ++ struct mtd_info *mtd = yaffs_dev_to_mtd(dev); ++ u32 addr = ++ ((loff_t) block_no) * dev->param.total_bytes_per_chunk * ++ dev->param.chunks_per_block; ++ struct erase_info ei; ++ int retval = 0; ++ ++ ei.mtd = mtd; ++ ei.addr = addr; ++ ei.len = dev->param.total_bytes_per_chunk * dev->param.chunks_per_block; ++ ei.time = 1000; ++ ei.retries = 2; ++ ei.callback = NULL; ++ ei.priv = (u_long) dev; ++ ++ retval = mtd_erase(mtd, &ei); ++ ++ if (retval == 0) ++ return YAFFS_OK; ++ ++ return YAFFS_FAIL; ++} ++ ++ ++static int yaffs_mtd_write(struct yaffs_dev *dev, int nand_chunk, ++ const u8 *data, int data_len, ++ const u8 *oob, int oob_len) ++{ ++ struct mtd_info *mtd = yaffs_dev_to_mtd(dev); ++ loff_t addr; ++ struct mtd_oob_ops ops; ++ int retval; ++ ++ yaffs_trace(YAFFS_TRACE_MTD, ++ "yaffs_mtd_write(%p, %d, %p, %d, %p, %d)\n", ++ dev, nand_chunk, data, data_len, oob, oob_len); ++ ++ if (!data || !data_len) { ++ data = NULL; ++ data_len = 0; ++ } ++ ++ if (!oob || !oob_len) { ++ oob = NULL; ++ oob_len = 0; ++ } ++ ++ addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk; ++ memset(&ops, 0, sizeof(ops)); ++ ops.mode = MTD_OPS_AUTO_OOB; ++ ops.len = (data) ? data_len : 0; ++ ops.ooblen = oob_len; ++ ops.datbuf = (u8 *)data; ++ ops.oobbuf = (u8 *)oob; ++ ++ retval = mtd_write_oob(mtd, addr, &ops); ++ if (retval) { ++ yaffs_trace(YAFFS_TRACE_MTD, ++ "write_oob failed, chunk %d, mtd error %d", ++ nand_chunk, retval); ++ } ++ return retval ? YAFFS_FAIL : YAFFS_OK; ++} ++ ++static int yaffs_mtd_read(struct yaffs_dev *dev, int nand_chunk, ++ u8 *data, int data_len, ++ u8 *oob, int oob_len, ++ enum yaffs_ecc_result *ecc_result) ++{ ++ struct mtd_info *mtd = yaffs_dev_to_mtd(dev); ++ loff_t addr; ++ struct mtd_oob_ops ops; ++ int retval; ++ ++ addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk; ++ memset(&ops, 0, sizeof(ops)); ++ ops.mode = MTD_OPS_AUTO_OOB; ++ ops.len = (data) ? data_len : 0; ++ ops.ooblen = oob_len; ++ ops.datbuf = data; ++ ops.oobbuf = oob; ++ ++#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 20)) ++ /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug; ++ * help it out with ops.len = ops.ooblen when ops.datbuf == NULL. ++ */ ++ ops.len = (ops.datbuf) ? ops.len : ops.ooblen; ++#endif ++ /* Read page and oob using MTD. ++ * Check status and determine ECC result. ++ */ ++ retval = mtd_read_oob(mtd, addr, &ops); ++ if (retval) ++ yaffs_trace(YAFFS_TRACE_MTD, ++ "read_oob failed, chunk %d, mtd error %d", ++ nand_chunk, retval); ++ ++ switch (retval) { ++ case 0: ++ /* no error */ ++ if(ecc_result) ++ *ecc_result = YAFFS_ECC_RESULT_NO_ERROR; ++ break; ++ ++ case -EUCLEAN: ++ /* MTD's ECC fixed the data */ ++ if(ecc_result) ++ *ecc_result = YAFFS_ECC_RESULT_FIXED; ++ dev->n_ecc_fixed++; ++ break; ++ ++ case -EBADMSG: ++ default: ++ /* MTD's ECC could not fix the data */ ++ dev->n_ecc_unfixed++; ++ if(ecc_result) ++ *ecc_result = YAFFS_ECC_RESULT_UNFIXED; ++ return YAFFS_FAIL; ++ } ++ ++ return YAFFS_OK; ++} ++ ++static int yaffs_mtd_erase(struct yaffs_dev *dev, int block_no) ++{ ++ struct mtd_info *mtd = yaffs_dev_to_mtd(dev); ++ ++ loff_t addr; ++ struct erase_info ei; ++ int retval = 0; ++ u32 block_size; ++ ++ block_size = dev->param.total_bytes_per_chunk * ++ dev->param.chunks_per_block; ++ addr = ((loff_t) block_no) * block_size; ++ ++ ei.mtd = mtd; ++ ei.addr = addr; ++ ei.len = block_size; ++ ei.time = 1000; ++ ei.retries = 2; ++ ei.callback = NULL; ++ ei.priv = (u_long) dev; ++ ++ retval = mtd_erase(mtd, &ei); ++ ++ if (retval == 0) ++ return YAFFS_OK; ++ ++ return YAFFS_FAIL; ++} ++ ++static int yaffs_mtd_mark_bad(struct yaffs_dev *dev, int block_no) ++{ ++ struct mtd_info *mtd = yaffs_dev_to_mtd(dev); ++ int blocksize = dev->param.chunks_per_block * dev->param.total_bytes_per_chunk; ++ int retval; ++ ++ yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", block_no); ++ ++ retval = mtd_block_markbad(mtd, (loff_t) blocksize * block_no); ++ return (retval) ? YAFFS_FAIL : YAFFS_OK; ++} ++ ++static int yaffs_mtd_check_bad(struct yaffs_dev *dev, int block_no) ++{ ++ struct mtd_info *mtd = yaffs_dev_to_mtd(dev); ++ int blocksize = dev->param.chunks_per_block * dev->param.total_bytes_per_chunk; ++ int retval; ++ ++ yaffs_trace(YAFFS_TRACE_MTD, "checking block %d bad", block_no); ++ ++ retval = mtd_block_isbad(mtd, (loff_t) blocksize * block_no); ++ return (retval) ? YAFFS_FAIL : YAFFS_OK; ++} ++ ++static int yaffs_mtd_initialise(struct yaffs_dev *dev) ++{ ++ return YAFFS_OK; ++} ++ ++static int yaffs_mtd_deinitialise(struct yaffs_dev *dev) ++{ ++ return YAFFS_OK; ++} ++ ++ ++void yaffs_mtd_drv_install(struct yaffs_dev *dev) ++{ ++ struct yaffs_driver *drv = &dev->drv; ++ ++ drv->drv_write_chunk_fn = yaffs_mtd_write; ++ drv->drv_read_chunk_fn = yaffs_mtd_read; ++ drv->drv_erase_fn = yaffs_mtd_erase; ++ drv->drv_mark_bad_fn = yaffs_mtd_mark_bad; ++ drv->drv_check_bad_fn = yaffs_mtd_check_bad; ++ drv->drv_initialise_fn = yaffs_mtd_initialise; ++ drv->drv_deinitialise_fn = yaffs_mtd_deinitialise; ++} ++ ++ ++struct mtd_info * yaffs_get_mtd_device(dev_t sdev) ++{ ++ struct mtd_info *mtd; ++ ++ mtd = yaffs_get_mtd_device(sdev); ++ ++ /* Check it's an mtd device..... */ ++ if (MAJOR(sdev) != MTD_BLOCK_MAJOR) ++ return NULL; /* This isn't an mtd device */ ++ ++ /* Check it's NAND */ ++ if (mtd->type != MTD_NANDFLASH) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs: MTD device is not NAND it's type %d", ++ mtd->type); ++ return NULL; ++ } ++ ++ yaffs_trace(YAFFS_TRACE_OS, " %s %d", WRITE_SIZE_STR, WRITE_SIZE(mtd)); ++ yaffs_trace(YAFFS_TRACE_OS, " oobsize %d", mtd->oobsize); ++ yaffs_trace(YAFFS_TRACE_OS, " erasesize %d", mtd->erasesize); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) ++ yaffs_trace(YAFFS_TRACE_OS, " size %u", mtd->size); ++#else ++ yaffs_trace(YAFFS_TRACE_OS, " size %lld", mtd->size); ++#endif ++ ++ return mtd; ++} ++ ++int yaffs_verify_mtd(struct mtd_info *mtd, int yaffs_version, int inband_tags) ++{ ++ if (yaffs_version == 2) { ++ if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE || ++ mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) && ++ !inband_tags) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "MTD device does not have the right page sizes" ++ ); ++ return -1; ++ } ++ } else { ++ if (WRITE_SIZE(mtd) < YAFFS_BYTES_PER_CHUNK || ++ mtd->oobsize != YAFFS_BYTES_PER_SPARE) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "MTD device does not support have the right page sizes" ++ ); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++ ++void yaffs_put_mtd_device(struct mtd_info *mtd) ++{ ++ if(mtd) ++ put_mtd_device(mtd); ++} +diff --git a/fs/yaffs2/yaffs_mtdif.h b/fs/yaffs2/yaffs_mtdif.h +new file mode 100644 +index 0000000..9cff224 +--- /dev/null ++++ b/fs/yaffs2/yaffs_mtdif.h +@@ -0,0 +1,25 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_MTDIF_H__ ++#define __YAFFS_MTDIF_H__ ++ ++#include "yaffs_guts.h" ++ ++void yaffs_mtd_drv_install(struct yaffs_dev *dev); ++struct mtd_info * yaffs_get_mtd_device(dev_t sdev); ++void yaffs_put_mtd_device(struct mtd_info *mtd); ++int yaffs_verify_mtd(struct mtd_info *mtd, int yaffs_version, int inband_tags); ++#endif +diff --git a/fs/yaffs2/yaffs_nameval.c b/fs/yaffs2/yaffs_nameval.c +new file mode 100644 +index 0000000..eeb75be +--- /dev/null ++++ b/fs/yaffs2/yaffs_nameval.c +@@ -0,0 +1,230 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * 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 simple implementation of a name-value store assumes a small number of ++* values and fits into a small finite buffer. ++ * ++ * Each attribute is stored as a record: ++ * sizeof(size) bytes record size. ++ * strnlen+1 bytes name null terminated. ++ * nbytes value. ++ * ---------- ++ * total size stored in record size ++ * ++ * This code has not been tested with unicode yet. ++ */ ++ ++#include "yaffs_nameval.h" ++#include "yaffs_guts.h" ++#include "yportenv.h" ++#include "yaffs_endian.h" ++ ++static int nval_find(struct yaffs_dev *dev, ++ const char *xb, int xb_size, const YCHAR *name, ++ int *exist_size) ++{ ++ int pos = 0; ++ s32 size; ++ ++ memcpy(&size, xb, sizeof(size)); ++ yaffs_do_endian_s32(dev, &size); ++ ++ while (size > 0 && (size < xb_size) && (pos + size < xb_size)) { ++ if (!strncmp((YCHAR *) (xb + pos + sizeof(size)), ++ name, size)) { ++ if (exist_size) ++ *exist_size = size; ++ return pos; ++ } ++ pos += size; ++ if (pos < (int)(xb_size - sizeof(size))) { ++ memcpy(&size, xb + pos, sizeof(size)); ++ yaffs_do_endian_s32(dev, &size); ++ ++ } else ++ size = 0; ++ } ++ if (exist_size) ++ *exist_size = 0; ++ return -ENODATA; ++} ++ ++static int nval_used(struct yaffs_dev *dev, const char *xb, int xb_size) ++{ ++ int pos = 0; ++ s32 size; ++ ++ memcpy(&size, xb + pos, sizeof(size)); ++ yaffs_do_endian_s32(dev, &size); ++ ++ while (size > 0 && (size < xb_size) && (pos + size < xb_size)) { ++ pos += size; ++ if (pos < (int)(xb_size - sizeof(size))) { ++ memcpy(&size, xb + pos, sizeof(size)); ++ yaffs_do_endian_s32(dev, &size); ++ } else ++ size = 0; ++ } ++ return pos; ++} ++ ++int nval_del(struct yaffs_dev *dev, char *xb, int xb_size, const YCHAR *name) ++{ ++ int pos = nval_find(dev, xb, xb_size, name, NULL); ++ s32 size; ++ ++ if (pos < 0 || pos >= xb_size) ++ return -ENODATA; ++ ++ /* Find size, shift rest over this record, ++ * then zero out the rest of buffer */ ++ memcpy(&size, xb + pos, sizeof(size)); ++ yaffs_do_endian_s32(dev, &size); ++ ++ memcpy(xb + pos, xb + pos + size, xb_size - (pos + size)); ++ memset(xb + (xb_size - size), 0, size); ++ return 0; ++} ++ ++int nval_set(struct yaffs_dev *dev, ++ char *xb, int xb_size, const YCHAR *name, const char *buf, ++ int bsize, int flags) ++{ ++ int pos; ++ int namelen = strnlen(name, xb_size); ++ int size_exist = 0; ++ int space; ++ int start; ++ s32 reclen; ++ s32 reclen_endianised; ++ ++ pos = nval_find(dev, xb, xb_size, name, &size_exist); ++ ++ if (flags & XATTR_CREATE && pos >= 0) ++ return -EEXIST; ++ if (flags & XATTR_REPLACE && pos < 0) ++ return -ENODATA; ++ ++ start = nval_used(dev, xb, xb_size); ++ space = xb_size - start + size_exist; ++ ++ reclen = (sizeof(reclen) + namelen + 1 + bsize); ++ ++ if (reclen > space) ++ return -ENOSPC; ++ ++ if (pos >= 0) { ++ /* Exists, so delete it. */ ++ nval_del(dev, xb, xb_size, name); ++ start = nval_used(dev, xb, xb_size); ++ } ++ ++ pos = start; ++ ++ reclen_endianised = reclen; ++ yaffs_do_endian_s32(dev, &reclen_endianised); ++ memcpy(xb + pos, &reclen_endianised, sizeof(reclen_endianised)); ++ pos += sizeof(reclen_endianised); ++ strncpy((YCHAR *) (xb + pos), name, reclen); ++ pos += (namelen + 1); ++ memcpy(xb + pos, buf, bsize); ++ return 0; ++} ++ ++int nval_get(struct yaffs_dev *dev, ++ const char *xb, int xb_size, const YCHAR * name, char *buf, ++ int bsize) ++{ ++ int pos = nval_find(dev, xb, xb_size, name, NULL); ++ s32 size; ++ ++ if (pos >= 0 && pos < xb_size) { ++ ++ memcpy(&size, xb + pos, sizeof(size)); ++ yaffs_do_endian_s32(dev, &size); ++ pos += sizeof(size); /* advance past record length */ ++ size -= sizeof(size); ++ ++ /* Advance over name string */ ++ while (xb[pos] && size > 0 && pos < xb_size) { ++ pos++; ++ size--; ++ } ++ /*Advance over NUL */ ++ pos++; ++ size--; ++ ++ /* If bsize is zero then this is a size query. ++ * Return the size, but don't copy. ++ */ ++ if (!bsize) ++ return size; ++ ++ if (size <= bsize) { ++ memcpy(buf, xb + pos, size); ++ return size; ++ } ++ } ++ if (pos >= 0) ++ return -ERANGE; ++ ++ return -ENODATA; ++} ++ ++int nval_list(struct yaffs_dev *dev, const char *xb, int xb_size, char *buf, int bsize) ++{ ++ int pos = 0; ++ s32 size; ++ int name_len; ++ int ncopied = 0; ++ int filled = 0; ++ ++ memcpy(&size, xb + pos, sizeof(size)); ++ yaffs_do_endian_s32(dev, &size); ++ ++ while (size > (int)(sizeof(size)) && ++ size <= xb_size && ++ (pos + size) < xb_size && ++ !filled) { ++ pos += sizeof(size); ++ size -= sizeof(size); ++ name_len = strnlen((YCHAR *) (xb + pos), size); ++ if (ncopied + name_len + 1 < bsize) { ++ memcpy(buf, xb + pos, name_len * sizeof(YCHAR)); ++ buf += name_len; ++ *buf = '\0'; ++ buf++; ++ if (sizeof(YCHAR) > 1) { ++ *buf = '\0'; ++ buf++; ++ } ++ ncopied += (name_len + 1); ++ } else { ++ filled = 1; ++ } ++ pos += size; ++ if (pos < (int)(xb_size - sizeof(size))) { ++ memcpy(&size, xb + pos, sizeof(size)); ++ yaffs_do_endian_s32(dev, &size); ++ } ++ else ++ size = 0; ++ } ++ return ncopied; ++} ++ ++int nval_hasvalues(struct yaffs_dev *dev, const char *xb, int xb_size) ++{ ++ return nval_used(dev, xb, xb_size) > 0; ++} +diff --git a/fs/yaffs2/yaffs_nameval.h b/fs/yaffs2/yaffs_nameval.h +new file mode 100644 +index 0000000..aa05ada +--- /dev/null ++++ b/fs/yaffs2/yaffs_nameval.h +@@ -0,0 +1,33 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __NAMEVAL_H__ ++#define __NAMEVAL_H__ ++ ++#include "yportenv.h" ++ ++struct yaffs_dev; ++ ++int nval_del(struct yaffs_dev *dev, char *xb, int xb_size, const YCHAR * name); ++int nval_set(struct yaffs_dev *dev, ++ char *xb, int xb_size, const YCHAR * name, const char *buf, ++ int bsize, int flags); ++int nval_get(struct yaffs_dev *dev, ++ const char *xb, int xb_size, const YCHAR * name, char *buf, ++ int bsize); ++int nval_list(struct yaffs_dev *dev, ++ const char *xb, int xb_size, char *buf, int bsize); ++int nval_hasvalues(struct yaffs_dev *dev, const char *xb, int xb_size); ++#endif +diff --git a/fs/yaffs2/yaffs_nand.c b/fs/yaffs2/yaffs_nand.c +new file mode 100644 +index 0000000..0d8499b +--- /dev/null ++++ b/fs/yaffs2/yaffs_nand.c +@@ -0,0 +1,122 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * 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 "yaffs_nand.h" ++#include "yaffs_tagscompat.h" ++ ++#include "yaffs_getblockinfo.h" ++#include "yaffs_summary.h" ++ ++static int apply_chunk_offset(struct yaffs_dev *dev, int chunk) ++{ ++ return chunk - dev->chunk_offset; ++} ++ ++int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk, ++ u8 *buffer, struct yaffs_ext_tags *tags) ++{ ++ int result; ++ struct yaffs_ext_tags local_tags; ++ int flash_chunk = apply_chunk_offset(dev, nand_chunk); ++ ++ dev->n_page_reads++; ++ ++ /* If there are no tags provided use local tags. */ ++ if (!tags) ++ tags = &local_tags; ++ ++ result = dev->tagger.read_chunk_tags_fn(dev, flash_chunk, buffer, tags); ++ if (tags && tags->ecc_result > YAFFS_ECC_RESULT_NO_ERROR) { ++ ++ struct yaffs_block_info *bi; ++ bi = yaffs_get_block_info(dev, ++ nand_chunk / ++ dev->param.chunks_per_block); ++ yaffs_handle_chunk_error(dev, bi); ++ } ++ return result; ++} ++ ++int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev, ++ int nand_chunk, ++ const u8 *buffer, struct yaffs_ext_tags *tags) ++{ ++ int result; ++ int flash_chunk = apply_chunk_offset(dev, nand_chunk); ++ ++ dev->n_page_writes++; ++ ++ if (!tags) { ++ yaffs_trace(YAFFS_TRACE_ERROR, "Writing with no tags"); ++ BUG(); ++ return YAFFS_FAIL; ++ } ++ ++ tags->seq_number = dev->seq_number; ++ tags->chunk_used = 1; ++ yaffs_trace(YAFFS_TRACE_WRITE, ++ "Writing chunk %d tags %d %d", ++ nand_chunk, tags->obj_id, tags->chunk_id); ++ ++ result = dev->tagger.write_chunk_tags_fn(dev, flash_chunk, ++ buffer, tags); ++ ++ yaffs_summary_add(dev, tags, nand_chunk); ++ ++ return result; ++} ++ ++int yaffs_mark_bad(struct yaffs_dev *dev, int block_no) ++{ ++ block_no -= dev->block_offset; ++ dev->n_bad_markings++; ++ ++ if (dev->param.disable_bad_block_marking) ++ return YAFFS_OK; ++ ++ return dev->tagger.mark_bad_fn(dev, block_no); ++} ++ ++ ++int yaffs_query_init_block_state(struct yaffs_dev *dev, ++ int block_no, ++ enum yaffs_block_state *state, ++ u32 *seq_number) ++{ ++ block_no -= dev->block_offset; ++ return dev->tagger.query_block_fn(dev, block_no, state, seq_number); ++} ++ ++int yaffs_erase_block(struct yaffs_dev *dev, int block_no) ++{ ++ int result; ++ ++ block_no -= dev->block_offset; ++ dev->n_erasures++; ++ result = dev->drv.drv_erase_fn(dev, block_no); ++ return result; ++} ++ ++int yaffs_init_nand(struct yaffs_dev *dev) ++{ ++ if (dev->drv.drv_initialise_fn) ++ return dev->drv.drv_initialise_fn(dev); ++ return YAFFS_OK; ++} ++ ++int yaffs_deinit_nand(struct yaffs_dev *dev) ++{ ++ if (dev->drv.drv_deinitialise_fn) ++ return dev->drv.drv_deinitialise_fn(dev); ++ return YAFFS_OK; ++} +diff --git a/fs/yaffs2/yaffs_nand.h b/fs/yaffs2/yaffs_nand.h +new file mode 100644 +index 0000000..804e97a +--- /dev/null ++++ b/fs/yaffs2/yaffs_nand.h +@@ -0,0 +1,39 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_NAND_H__ ++#define __YAFFS_NAND_H__ ++#include "yaffs_guts.h" ++ ++int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk, ++ u8 *buffer, struct yaffs_ext_tags *tags); ++ ++int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev, ++ int nand_chunk, ++ const u8 *buffer, struct yaffs_ext_tags *tags); ++ ++int yaffs_mark_bad(struct yaffs_dev *dev, int block_no); ++ ++int yaffs_query_init_block_state(struct yaffs_dev *dev, ++ int block_no, ++ enum yaffs_block_state *state, ++ unsigned *seq_number); ++ ++int yaffs_erase_block(struct yaffs_dev *dev, int flash_block); ++ ++int yaffs_init_nand(struct yaffs_dev *dev); ++int yaffs_deinit_nand(struct yaffs_dev *dev); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_packedtags1.c b/fs/yaffs2/yaffs_packedtags1.c +new file mode 100644 +index 0000000..0928b8e +--- /dev/null ++++ b/fs/yaffs2/yaffs_packedtags1.c +@@ -0,0 +1,55 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * 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 "yaffs_packedtags1.h" ++#include "yportenv.h" ++ ++static const u8 all_ff[20] = { ++ 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff ++}; ++ ++void yaffs_pack_tags1(struct yaffs_packed_tags1 *pt, ++ const struct yaffs_ext_tags *t) ++{ ++ pt->chunk_id = t->chunk_id; ++ pt->serial_number = t->serial_number; ++ pt->n_bytes = t->n_bytes; ++ pt->obj_id = t->obj_id; ++ pt->ecc = 0; ++ pt->deleted = (t->is_deleted) ? 0 : 1; ++ pt->unused_stuff = 0; ++ pt->should_be_ff = 0xffffffff; ++} ++ ++void yaffs_unpack_tags1(struct yaffs_ext_tags *t, ++ const struct yaffs_packed_tags1 *pt) ++{ ++ if (memcmp(all_ff, pt, sizeof(struct yaffs_packed_tags1))) { ++ t->block_bad = 0; ++ if (pt->should_be_ff != 0xffffffff) ++ t->block_bad = 1; ++ t->chunk_used = 1; ++ t->obj_id = pt->obj_id; ++ t->chunk_id = pt->chunk_id; ++ t->n_bytes = pt->n_bytes; ++ t->ecc_result = YAFFS_ECC_RESULT_NO_ERROR; ++ t->is_deleted = (pt->deleted) ? 0 : 1; ++ t->serial_number = pt->serial_number; ++ } else { ++ memset(t, 0, sizeof(struct yaffs_ext_tags)); ++ } ++} +diff --git a/fs/yaffs2/yaffs_packedtags1.h b/fs/yaffs2/yaffs_packedtags1.h +new file mode 100644 +index 0000000..3015d58 +--- /dev/null ++++ b/fs/yaffs2/yaffs_packedtags1.h +@@ -0,0 +1,39 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++/* This is used to pack YAFFS1 tags, not YAFFS2 tags. */ ++ ++#ifndef __YAFFS_PACKEDTAGS1_H__ ++#define __YAFFS_PACKEDTAGS1_H__ ++ ++#include "yaffs_guts.h" ++ ++struct yaffs_packed_tags1 { ++ u32 chunk_id:20; ++ u32 serial_number:2; ++ u32 n_bytes:10; ++ u32 obj_id:18; ++ u32 ecc:12; ++ u32 deleted:1; ++ u32 unused_stuff:1; ++ unsigned should_be_ff; ++ ++}; ++ ++void yaffs_pack_tags1(struct yaffs_packed_tags1 *pt, ++ const struct yaffs_ext_tags *t); ++void yaffs_unpack_tags1(struct yaffs_ext_tags *t, ++ const struct yaffs_packed_tags1 *pt); ++#endif +diff --git a/fs/yaffs2/yaffs_packedtags2.c b/fs/yaffs2/yaffs_packedtags2.c +new file mode 100644 +index 0000000..d5291fc +--- /dev/null ++++ b/fs/yaffs2/yaffs_packedtags2.c +@@ -0,0 +1,208 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * 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 "yaffs_packedtags2.h" ++#include "yportenv.h" ++#include "yaffs_trace.h" ++#include "yaffs_endian.h" ++ ++/* This code packs a set of extended tags into a binary structure for ++ * NAND storage ++ */ ++ ++/* Some of the information is "extra" struff which can be packed in to ++ * speed scanning ++ * This is defined by having the EXTRA_HEADER_INFO_FLAG set. ++ */ ++ ++/* Extra flags applied to chunk_id */ ++ ++#define EXTRA_HEADER_INFO_FLAG 0x80000000 ++#define EXTRA_SHRINK_FLAG 0x40000000 ++#define EXTRA_SHADOWS_FLAG 0x20000000 ++#define EXTRA_SPARE_FLAGS 0x10000000 ++ ++#define ALL_EXTRA_FLAGS 0xf0000000 ++ ++/* Also, the top 4 bits of the object Id are set to the object type. */ ++#define EXTRA_OBJECT_TYPE_SHIFT (28) ++#define EXTRA_OBJECT_TYPE_MASK ((0x0f) << EXTRA_OBJECT_TYPE_SHIFT) ++ ++static void yaffs_dump_packed_tags2_tags_only( ++ const struct yaffs_packed_tags2_tags_only *ptt) ++{ ++ yaffs_trace(YAFFS_TRACE_MTD, ++ "packed tags obj %d chunk %d byte %d seq %d", ++ ptt->obj_id, ptt->chunk_id, ptt->n_bytes, ptt->seq_number); ++} ++ ++static void yaffs_dump_packed_tags2(const struct yaffs_packed_tags2 *pt) ++{ ++ yaffs_dump_packed_tags2_tags_only(&pt->t); ++} ++ ++static void yaffs_dump_tags2(const struct yaffs_ext_tags *t) ++{ ++ yaffs_trace(YAFFS_TRACE_MTD, ++ "ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d", ++ t->ecc_result, t->block_bad, t->chunk_used, t->obj_id, ++ t->chunk_id, t->n_bytes, t->is_deleted, t->serial_number, ++ t->seq_number); ++ ++} ++ ++static int yaffs_check_tags_extra_packable(const struct yaffs_ext_tags *t) ++{ ++ if (t->chunk_id != 0 || !t->extra_available) ++ return 0; ++ ++ /* Check if the file size is too long to store */ ++ if (t->extra_obj_type == YAFFS_OBJECT_TYPE_FILE && ++ (t->extra_file_size >> 31) != 0) ++ return 0; ++ return 1; ++} ++ ++void yaffs_pack_tags2_tags_only(struct yaffs_dev *dev, ++ struct yaffs_packed_tags2_tags_only *ptt, ++ const struct yaffs_ext_tags *t) ++{ ++ ptt->chunk_id = t->chunk_id; ++ ptt->seq_number = t->seq_number; ++ ptt->n_bytes = t->n_bytes; ++ ptt->obj_id = t->obj_id; ++ ++ /* Only store extra tags for object headers. ++ * If it is a file then only store if the file size is short\ ++ * enough to fit. ++ */ ++ if (yaffs_check_tags_extra_packable(t)) { ++ /* Store the extra header info instead */ ++ /* We save the parent object in the chunk_id */ ++ ptt->chunk_id = EXTRA_HEADER_INFO_FLAG | t->extra_parent_id; ++ if (t->extra_is_shrink) ++ ptt->chunk_id |= EXTRA_SHRINK_FLAG; ++ if (t->extra_shadows) ++ ptt->chunk_id |= EXTRA_SHADOWS_FLAG; ++ ++ ptt->obj_id &= ~EXTRA_OBJECT_TYPE_MASK; ++ ptt->obj_id |= (t->extra_obj_type << EXTRA_OBJECT_TYPE_SHIFT); ++ ++ if (t->extra_obj_type == YAFFS_OBJECT_TYPE_HARDLINK) ++ ptt->n_bytes = t->extra_equiv_id; ++ else if (t->extra_obj_type == YAFFS_OBJECT_TYPE_FILE) ++ ptt->n_bytes = (unsigned) t->extra_file_size; ++ else ++ ptt->n_bytes = 0; ++ } ++ ++ yaffs_dump_packed_tags2_tags_only(ptt); ++ yaffs_dump_tags2(t); ++ yaffs_do_endian_packed_tags2(dev, ptt); ++} ++ ++void yaffs_pack_tags2(struct yaffs_dev *dev, ++ struct yaffs_packed_tags2 *pt, ++ const struct yaffs_ext_tags *t, int tags_ecc) ++{ ++ yaffs_pack_tags2_tags_only(dev, &pt->t, t); ++ ++ if (tags_ecc) ++ yaffs_ecc_calc_other((unsigned char *)&pt->t, ++ sizeof(struct yaffs_packed_tags2_tags_only), ++ &pt->ecc); ++} ++ ++void yaffs_unpack_tags2_tags_only(struct yaffs_dev *dev, ++ struct yaffs_ext_tags *t, ++ struct yaffs_packed_tags2_tags_only *ptt_ptr) ++{ ++ struct yaffs_packed_tags2_tags_only ptt_copy = *ptt_ptr; ++ ++ memset(t, 0, sizeof(struct yaffs_ext_tags)); ++ ++ if (ptt_copy.seq_number == 0xffffffff) ++ return; ++ ++ yaffs_do_endian_packed_tags2(dev, &ptt_copy); ++ ++ t->block_bad = 0; ++ t->chunk_used = 1; ++ t->obj_id = ptt_copy.obj_id; ++ t->chunk_id = ptt_copy.chunk_id; ++ t->n_bytes = ptt_copy.n_bytes; ++ t->is_deleted = 0; ++ t->serial_number = 0; ++ t->seq_number = ptt_copy.seq_number; ++ ++ /* Do extra header info stuff */ ++ if (ptt_copy.chunk_id & EXTRA_HEADER_INFO_FLAG) { ++ t->chunk_id = 0; ++ t->n_bytes = 0; ++ ++ t->extra_available = 1; ++ t->extra_parent_id = ptt_copy.chunk_id & (~(ALL_EXTRA_FLAGS)); ++ t->extra_is_shrink = ptt_copy.chunk_id & EXTRA_SHRINK_FLAG ? 1 : 0; ++ t->extra_shadows = ptt_copy.chunk_id & EXTRA_SHADOWS_FLAG ? 1 : 0; ++ t->extra_obj_type = ptt_copy.obj_id >> EXTRA_OBJECT_TYPE_SHIFT; ++ t->obj_id &= ~EXTRA_OBJECT_TYPE_MASK; ++ ++ if (t->extra_obj_type == YAFFS_OBJECT_TYPE_HARDLINK) ++ t->extra_equiv_id = ptt_copy.n_bytes; ++ else ++ t->extra_file_size = ptt_copy.n_bytes; ++ } ++ yaffs_dump_packed_tags2_tags_only(ptt_ptr); ++ yaffs_dump_tags2(t); ++} ++ ++void yaffs_unpack_tags2(struct yaffs_dev *dev, ++ struct yaffs_ext_tags *t, ++ struct yaffs_packed_tags2 *pt, ++ int tags_ecc) ++{ ++ enum yaffs_ecc_result ecc_result = YAFFS_ECC_RESULT_NO_ERROR; ++ ++ if (pt->t.seq_number != 0xffffffff && tags_ecc) { ++ /* Chunk is in use and we need to do ECC */ ++ ++ struct yaffs_ecc_other ecc; ++ int result; ++ yaffs_ecc_calc_other((unsigned char *)&pt->t, ++ sizeof(struct yaffs_packed_tags2_tags_only), ++ &ecc); ++ result = ++ yaffs_ecc_correct_other((unsigned char *)&pt->t, ++ sizeof(struct yaffs_packed_tags2_tags_only), ++ &pt->ecc, &ecc); ++ switch (result) { ++ case 0: ++ ecc_result = YAFFS_ECC_RESULT_NO_ERROR; ++ break; ++ case 1: ++ ecc_result = YAFFS_ECC_RESULT_FIXED; ++ break; ++ case -1: ++ ecc_result = YAFFS_ECC_RESULT_UNFIXED; ++ break; ++ default: ++ ecc_result = YAFFS_ECC_RESULT_UNKNOWN; ++ } ++ } ++ yaffs_unpack_tags2_tags_only(dev, t, &pt->t); ++ ++ t->ecc_result = ecc_result; ++ ++ yaffs_dump_packed_tags2(pt); ++ yaffs_dump_tags2(t); ++} +diff --git a/fs/yaffs2/yaffs_packedtags2.h b/fs/yaffs2/yaffs_packedtags2.h +new file mode 100644 +index 0000000..9cafe0e +--- /dev/null ++++ b/fs/yaffs2/yaffs_packedtags2.h +@@ -0,0 +1,51 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++/* This is used to pack YAFFS2 tags, not YAFFS1tags. */ ++ ++#ifndef __YAFFS_PACKEDTAGS2_H__ ++#define __YAFFS_PACKEDTAGS2_H__ ++ ++#include "yaffs_guts.h" ++#include "yaffs_ecc.h" ++ ++struct yaffs_packed_tags2_tags_only { ++ unsigned seq_number; ++ unsigned obj_id; ++ unsigned chunk_id; ++ unsigned n_bytes; ++}; ++ ++struct yaffs_packed_tags2 { ++ struct yaffs_packed_tags2_tags_only t; ++ struct yaffs_ecc_other ecc; ++}; ++ ++/* Full packed tags with ECC, used for oob tags */ ++void yaffs_pack_tags2(struct yaffs_dev *dev, ++ struct yaffs_packed_tags2 *pt, ++ const struct yaffs_ext_tags *t, int tags_ecc); ++void yaffs_unpack_tags2(struct yaffs_dev *dev, ++ struct yaffs_ext_tags *t, struct yaffs_packed_tags2 *pt, ++ int tags_ecc); ++ ++/* Only the tags part (no ECC for use with inband tags */ ++void yaffs_pack_tags2_tags_only(struct yaffs_dev *dev, ++ struct yaffs_packed_tags2_tags_only *pt, ++ const struct yaffs_ext_tags *t); ++void yaffs_unpack_tags2_tags_only(struct yaffs_dev *dev, ++ struct yaffs_ext_tags *t, ++ struct yaffs_packed_tags2_tags_only *pt); ++#endif +diff --git a/fs/yaffs2/yaffs_summary.c b/fs/yaffs2/yaffs_summary.c +new file mode 100644 +index 0000000..1e7776b +--- /dev/null ++++ b/fs/yaffs2/yaffs_summary.c +@@ -0,0 +1,310 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * 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. ++ */ ++ ++/* Summaries write the useful part of the tags for the chunks in a block into an ++ * an array which is written to the last n chunks of the block. ++ * Reading the summaries gives all the tags for the block in one read. Much ++ * faster. ++ * ++ * Chunks holding summaries are marked with tags making it look like ++ * they are part of a fake file. ++ * ++ * The summary could also be used during gc. ++ * ++ */ ++ ++#include "yaffs_summary.h" ++#include "yaffs_packedtags2.h" ++#include "yaffs_nand.h" ++#include "yaffs_getblockinfo.h" ++#include "yaffs_bitmap.h" ++ ++/* ++ * The summary is built up in an array of summary tags. ++ * This gets written to the last one or two (maybe more) chunks in a block. ++ * A summary header is written as the first part of each chunk of summary data. ++ * The summary header must match or the summary is rejected. ++ */ ++ ++/* Summary tags don't need the sequence number because that is redundant. */ ++struct yaffs_summary_tags { ++ unsigned obj_id; ++ unsigned chunk_id; ++ unsigned n_bytes; ++}; ++ ++/* Summary header */ ++struct yaffs_summary_header { ++ unsigned version; /* Must match current version */ ++ unsigned block; /* Must be this block */ ++ unsigned seq; /* Must be this sequence number */ ++ unsigned sum; /* Just add up all the bytes in the tags */ ++}; ++ ++ ++static void yaffs_summary_clear(struct yaffs_dev *dev) ++{ ++ if (!dev->sum_tags) ++ return; ++ memset(dev->sum_tags, 0, dev->chunks_per_summary * ++ sizeof(struct yaffs_summary_tags)); ++} ++ ++ ++void yaffs_summary_deinit(struct yaffs_dev *dev) ++{ ++ kfree(dev->sum_tags); ++ dev->sum_tags = NULL; ++ kfree(dev->gc_sum_tags); ++ dev->gc_sum_tags = NULL; ++ dev->chunks_per_summary = 0; ++} ++ ++int yaffs_summary_init(struct yaffs_dev *dev) ++{ ++ int sum_bytes; ++ int chunks_used; /* Number of chunks used by summary */ ++ int sum_tags_bytes; ++ ++ sum_bytes = dev->param.chunks_per_block * ++ sizeof(struct yaffs_summary_tags); ++ ++ chunks_used = (sum_bytes + dev->data_bytes_per_chunk - 1)/ ++ (dev->data_bytes_per_chunk - ++ sizeof(struct yaffs_summary_header)); ++ ++ dev->chunks_per_summary = dev->param.chunks_per_block - chunks_used; ++ sum_tags_bytes = sizeof(struct yaffs_summary_tags) * ++ dev->chunks_per_summary; ++ dev->sum_tags = kmalloc(sum_tags_bytes, GFP_NOFS); ++ dev->gc_sum_tags = kmalloc(sum_tags_bytes, GFP_NOFS); ++ if (!dev->sum_tags || !dev->gc_sum_tags) { ++ yaffs_summary_deinit(dev); ++ return YAFFS_FAIL; ++ } ++ ++ yaffs_summary_clear(dev); ++ ++ return YAFFS_OK; ++} ++ ++static unsigned yaffs_summary_sum(struct yaffs_dev *dev) ++{ ++ u8 *sum_buffer = (u8 *)dev->sum_tags; ++ int i; ++ unsigned sum = 0; ++ ++ i = sizeof(struct yaffs_summary_tags) * ++ dev->chunks_per_summary; ++ while (i > 0) { ++ sum += *sum_buffer; ++ sum_buffer++; ++ i--; ++ } ++ ++ return sum; ++} ++ ++static int yaffs_summary_write(struct yaffs_dev *dev, int blk) ++{ ++ struct yaffs_ext_tags tags; ++ u8 *buffer; ++ u8 *sum_buffer = (u8 *)dev->sum_tags; ++ int n_bytes; ++ int chunk_in_nand; ++ int chunk_in_block; ++ int result; ++ int this_tx; ++ struct yaffs_summary_header hdr; ++ int sum_bytes_per_chunk = dev->data_bytes_per_chunk - sizeof(hdr); ++ struct yaffs_block_info *bi = yaffs_get_block_info(dev, blk); ++ ++ buffer = yaffs_get_temp_buffer(dev); ++ n_bytes = sizeof(struct yaffs_summary_tags) * ++ dev->chunks_per_summary; ++ memset(&tags, 0, sizeof(struct yaffs_ext_tags)); ++ tags.obj_id = YAFFS_OBJECTID_SUMMARY; ++ tags.chunk_id = 1; ++ chunk_in_block = dev->chunks_per_summary; ++ chunk_in_nand = dev->alloc_block * dev->param.chunks_per_block + ++ dev->chunks_per_summary; ++ hdr.version = YAFFS_SUMMARY_VERSION; ++ hdr.block = blk; ++ hdr.seq = bi->seq_number; ++ hdr.sum = yaffs_summary_sum(dev); ++ ++ do { ++ this_tx = n_bytes; ++ if (this_tx > sum_bytes_per_chunk) ++ this_tx = sum_bytes_per_chunk; ++ memcpy(buffer, &hdr, sizeof(hdr)); ++ memcpy(buffer + sizeof(hdr), sum_buffer, this_tx); ++ tags.n_bytes = this_tx + sizeof(hdr); ++ result = yaffs_wr_chunk_tags_nand(dev, chunk_in_nand, ++ buffer, &tags); ++ ++ if (result != YAFFS_OK) ++ break; ++ yaffs_set_chunk_bit(dev, blk, chunk_in_block); ++ bi->pages_in_use++; ++ dev->n_free_chunks--; ++ ++ n_bytes -= this_tx; ++ sum_buffer += this_tx; ++ chunk_in_nand++; ++ chunk_in_block++; ++ tags.chunk_id++; ++ } while (result == YAFFS_OK && n_bytes > 0); ++ yaffs_release_temp_buffer(dev, buffer); ++ ++ ++ if (result == YAFFS_OK) ++ bi->has_summary = 1; ++ ++ ++ return result; ++} ++ ++int yaffs_summary_read(struct yaffs_dev *dev, ++ struct yaffs_summary_tags *st, ++ int blk) ++{ ++ struct yaffs_ext_tags tags; ++ u8 *buffer; ++ u8 *sum_buffer = (u8 *)st; ++ int n_bytes; ++ u32 chunk_id; ++ int chunk_in_nand; ++ int chunk_in_block; ++ int result; ++ int this_tx; ++ struct yaffs_summary_header hdr; ++ struct yaffs_block_info *bi = yaffs_get_block_info(dev, blk); ++ int sum_bytes_per_chunk = dev->data_bytes_per_chunk - sizeof(hdr); ++ ++ buffer = yaffs_get_temp_buffer(dev); ++ n_bytes = sizeof(struct yaffs_summary_tags) * dev->chunks_per_summary; ++ chunk_in_block = dev->chunks_per_summary; ++ chunk_in_nand = blk * dev->param.chunks_per_block + ++ dev->chunks_per_summary; ++ chunk_id = 1; ++ do { ++ this_tx = n_bytes; ++ if (this_tx > sum_bytes_per_chunk) ++ this_tx = sum_bytes_per_chunk; ++ result = yaffs_rd_chunk_tags_nand(dev, chunk_in_nand, ++ buffer, &tags); ++ ++ if (tags.chunk_id != chunk_id || ++ tags.obj_id != YAFFS_OBJECTID_SUMMARY || ++ tags.chunk_used == 0 || ++ tags.ecc_result > YAFFS_ECC_RESULT_FIXED || ++ tags.n_bytes != (this_tx + sizeof(hdr))) ++ result = YAFFS_FAIL; ++ if (result != YAFFS_OK) ++ break; ++ ++ if (st == dev->sum_tags) { ++ /* If we're scanning then update the block info */ ++ yaffs_set_chunk_bit(dev, blk, chunk_in_block); ++ bi->pages_in_use++; ++ } ++ memcpy(&hdr, buffer, sizeof(hdr)); ++ memcpy(sum_buffer, buffer + sizeof(hdr), this_tx); ++ n_bytes -= this_tx; ++ sum_buffer += this_tx; ++ chunk_in_nand++; ++ chunk_in_block++; ++ chunk_id++; ++ } while (result == YAFFS_OK && n_bytes > 0); ++ yaffs_release_temp_buffer(dev, buffer); ++ ++ if (result == YAFFS_OK) { ++ /* Verify header */ ++ if (hdr.version != YAFFS_SUMMARY_VERSION || ++ hdr.seq != bi->seq_number || ++ hdr.sum != yaffs_summary_sum(dev)) ++ result = YAFFS_FAIL; ++ } ++ ++ if (st == dev->sum_tags && result == YAFFS_OK) ++ bi->has_summary = 1; ++ ++ return result; ++} ++ ++int yaffs_summary_add(struct yaffs_dev *dev, ++ struct yaffs_ext_tags *tags, ++ int chunk_in_nand) ++{ ++ struct yaffs_packed_tags2_tags_only tags_only; ++ struct yaffs_summary_tags *sum_tags; ++ int block_in_nand = chunk_in_nand / dev->param.chunks_per_block; ++ int chunk_in_block = chunk_in_nand % dev->param.chunks_per_block; ++ ++ if (!dev->sum_tags) ++ return YAFFS_OK; ++ ++ if (chunk_in_block >= 0 && chunk_in_block < dev->chunks_per_summary) { ++ yaffs_pack_tags2_tags_only(dev, &tags_only, tags); ++ sum_tags = &dev->sum_tags[chunk_in_block]; ++ ++ sum_tags->chunk_id = tags_only.chunk_id; ++ sum_tags->n_bytes = tags_only.n_bytes; ++ sum_tags->obj_id = tags_only.obj_id; ++ ++ if (chunk_in_block == dev->chunks_per_summary - 1) { ++ /* Time to write out the summary */ ++ yaffs_summary_write(dev, block_in_nand); ++ yaffs_summary_clear(dev); ++ yaffs_skip_rest_of_block(dev); ++ } ++ } ++ return YAFFS_OK; ++} ++ ++int yaffs_summary_fetch(struct yaffs_dev *dev, ++ struct yaffs_ext_tags *tags, ++ int chunk_in_block) ++{ ++ struct yaffs_packed_tags2_tags_only tags_only; ++ struct yaffs_summary_tags *sum_tags; ++ if (chunk_in_block >= 0 && chunk_in_block < dev->chunks_per_summary) { ++ sum_tags = &dev->sum_tags[chunk_in_block]; ++ tags_only.chunk_id = sum_tags->chunk_id; ++ tags_only.n_bytes = sum_tags->n_bytes; ++ tags_only.obj_id = sum_tags->obj_id; ++ yaffs_unpack_tags2_tags_only(dev, tags, &tags_only); ++ return YAFFS_OK; ++ } ++ return YAFFS_FAIL; ++} ++ ++void yaffs_summary_gc(struct yaffs_dev *dev, int blk) ++{ ++ struct yaffs_block_info *bi = yaffs_get_block_info(dev, blk); ++ u32 i; ++ ++ if (!bi->has_summary) ++ return; ++ ++ for (i = dev->chunks_per_summary; ++ i < dev->param.chunks_per_block; ++ i++) { ++ if (yaffs_check_chunk_bit(dev, blk, i)) { ++ yaffs_clear_chunk_bit(dev, blk, i); ++ bi->pages_in_use--; ++ dev->n_free_chunks++; ++ } ++ } ++} +diff --git a/fs/yaffs2/yaffs_summary.h b/fs/yaffs2/yaffs_summary.h +new file mode 100644 +index 0000000..be141d0 +--- /dev/null ++++ b/fs/yaffs2/yaffs_summary.h +@@ -0,0 +1,37 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_SUMMARY_H__ ++#define __YAFFS_SUMMARY_H__ ++ ++#include "yaffs_packedtags2.h" ++ ++ ++int yaffs_summary_init(struct yaffs_dev *dev); ++void yaffs_summary_deinit(struct yaffs_dev *dev); ++ ++int yaffs_summary_add(struct yaffs_dev *dev, ++ struct yaffs_ext_tags *tags, ++ int chunk_in_block); ++int yaffs_summary_fetch(struct yaffs_dev *dev, ++ struct yaffs_ext_tags *tags, ++ int chunk_in_block); ++int yaffs_summary_read(struct yaffs_dev *dev, ++ struct yaffs_summary_tags *st, ++ int blk); ++void yaffs_summary_gc(struct yaffs_dev *dev, int blk); ++ ++ ++#endif +diff --git a/fs/yaffs2/yaffs_tagscompat.c b/fs/yaffs2/yaffs_tagscompat.c +new file mode 100644 +index 0000000..e57c2d3 +--- /dev/null ++++ b/fs/yaffs2/yaffs_tagscompat.c +@@ -0,0 +1,400 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * 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 handles yaffs1-style tags to allow compatibility with Yaffs1 style ++ * flash layouts. ++ */ ++ ++#include "yaffs_guts.h" ++#include "yaffs_tagscompat.h" ++#include "yaffs_ecc.h" ++#include "yaffs_getblockinfo.h" ++#include "yaffs_trace.h" ++#include "yaffs_endian.h" ++ ++static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk); ++ ++ ++/********** Tags ECC calculations *********/ ++ ++void yaffs_calc_tags_ecc(struct yaffs_tags *tags) ++{ ++ /* Calculate an ecc */ ++ unsigned char *b = ((union yaffs_tags_union *)tags)->as_bytes; ++ unsigned i, j; ++ unsigned ecc = 0; ++ unsigned bit = 0; ++ ++ tags->ecc = 0; ++ ++ for (i = 0; i < 8; i++) { ++ for (j = 1; j & 0xff; j <<= 1) { ++ bit++; ++ if (b[i] & j) ++ ecc ^= bit; ++ } ++ } ++ tags->ecc = ecc; ++} ++ ++int yaffs_check_tags_ecc(struct yaffs_tags *tags) ++{ ++ unsigned ecc = tags->ecc; ++ ++ yaffs_calc_tags_ecc(tags); ++ ++ ecc ^= tags->ecc; ++ ++ if (ecc && ecc <= 64) { ++ /* TODO: Handle the failure better. Retire? */ ++ unsigned char *b = ((union yaffs_tags_union *)tags)->as_bytes; ++ ++ ecc--; ++ ++ b[ecc / 8] ^= (1 << (ecc & 7)); ++ ++ /* Now recvalc the ecc */ ++ yaffs_calc_tags_ecc(tags); ++ ++ return 1; /* recovered error */ ++ } else if (ecc) { ++ /* Wierd ecc failure value */ ++ /* TODO Need to do somethiong here */ ++ return -1; /* unrecovered error */ ++ } ++ return 0; ++} ++ ++/********** Tags **********/ ++ ++/* ++ * During tags storing/retireval we use a copy of the tags so that ++ * we can modify the endian etc without damaging the previous structure. ++ */ ++static void yaffs_load_tags_to_spare(struct yaffs_dev *dev, ++ struct yaffs_spare *spare_ptr, ++ struct yaffs_tags *tags_ptr) ++{ ++ union yaffs_tags_union *tu_ptr = (union yaffs_tags_union *)tags_ptr; ++ union yaffs_tags_union tags_stored = *tu_ptr; ++ ++ yaffs_calc_tags_ecc(&tags_stored.as_tags); ++ ++ yaffs_do_endian_u32(dev, &tags_stored.as_u32[0]); ++ yaffs_do_endian_u32(dev, &tags_stored.as_u32[1]); ++ ++ spare_ptr->tb0 = tags_stored.as_bytes[0]; ++ spare_ptr->tb1 = tags_stored.as_bytes[1]; ++ spare_ptr->tb2 = tags_stored.as_bytes[2]; ++ spare_ptr->tb3 = tags_stored.as_bytes[3]; ++ spare_ptr->tb4 = tags_stored.as_bytes[4]; ++ spare_ptr->tb5 = tags_stored.as_bytes[5]; ++ spare_ptr->tb6 = tags_stored.as_bytes[6]; ++ spare_ptr->tb7 = tags_stored.as_bytes[7]; ++} ++ ++static void yaffs_get_tags_from_spare(struct yaffs_dev *dev, ++ struct yaffs_spare *spare_ptr, ++ struct yaffs_tags *tags_ptr) ++{ ++ union yaffs_tags_union *tu = (union yaffs_tags_union *)tags_ptr; ++ union yaffs_tags_union tags_stored; ++ int result; ++ ++ tags_stored.as_bytes[0] = spare_ptr->tb0; ++ tags_stored.as_bytes[1] = spare_ptr->tb1; ++ tags_stored.as_bytes[2] = spare_ptr->tb2; ++ tags_stored.as_bytes[3] = spare_ptr->tb3; ++ tags_stored.as_bytes[4] = spare_ptr->tb4; ++ tags_stored.as_bytes[5] = spare_ptr->tb5; ++ tags_stored.as_bytes[6] = spare_ptr->tb6; ++ tags_stored.as_bytes[7] = spare_ptr->tb7; ++ ++ yaffs_do_endian_u32(dev, &tags_stored.as_u32[0]); ++ yaffs_do_endian_u32(dev, &tags_stored.as_u32[1]); ++ ++ *tu = tags_stored; ++ ++ result = yaffs_check_tags_ecc(tags_ptr); ++ if (result > 0) ++ dev->n_tags_ecc_fixed++; ++ else if (result < 0) ++ dev->n_tags_ecc_unfixed++; ++} ++ ++static void yaffs_spare_init(struct yaffs_spare *spare) ++{ ++ memset(spare, 0xff, sizeof(struct yaffs_spare)); ++} ++ ++static int yaffs_wr_nand(struct yaffs_dev *dev, ++ int nand_chunk, const u8 *data, ++ struct yaffs_spare *spare) ++{ ++ int data_size = dev->data_bytes_per_chunk; ++ ++ return dev->drv.drv_write_chunk_fn(dev, nand_chunk, ++ data, data_size, ++ (u8 *) spare, sizeof(*spare)); ++} ++ ++static int yaffs_rd_chunk_nand(struct yaffs_dev *dev, ++ int nand_chunk, ++ u8 *data, ++ struct yaffs_spare *spare, ++ enum yaffs_ecc_result *ecc_result, ++ int correct_errors) ++{ ++ int ret_val; ++ struct yaffs_spare local_spare; ++ int data_size; ++ int spare_size; ++ int ecc_result1, ecc_result2; ++ u8 calc_ecc[3]; ++ ++ if (!spare) { ++ /* If we don't have a real spare, then we use a local one. */ ++ /* Need this for the calculation of the ecc */ ++ spare = &local_spare; ++ } ++ data_size = dev->data_bytes_per_chunk; ++ spare_size = sizeof(struct yaffs_spare); ++ ++ if (dev->param.use_nand_ecc) ++ return dev->drv.drv_read_chunk_fn(dev, nand_chunk, ++ data, data_size, ++ (u8 *) spare, spare_size, ++ ecc_result); ++ ++ ++ /* Handle the ECC at this level. */ ++ ++ ret_val = dev->drv.drv_read_chunk_fn(dev, nand_chunk, ++ data, data_size, ++ (u8 *)spare, spare_size, ++ NULL); ++ if (!data || !correct_errors) ++ return ret_val; ++ ++ /* Do ECC correction if needed. */ ++ yaffs_ecc_calc(data, calc_ecc); ++ ecc_result1 = yaffs_ecc_correct(data, spare->ecc1, calc_ecc); ++ yaffs_ecc_calc(&data[256], calc_ecc); ++ ecc_result2 = yaffs_ecc_correct(&data[256], spare->ecc2, calc_ecc); ++ ++ if (ecc_result1 > 0) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "**>>yaffs ecc error fix performed on chunk %d:0", ++ nand_chunk); ++ dev->n_ecc_fixed++; ++ } else if (ecc_result1 < 0) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "**>>yaffs ecc error unfixed on chunk %d:0", ++ nand_chunk); ++ dev->n_ecc_unfixed++; ++ } ++ ++ if (ecc_result2 > 0) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "**>>yaffs ecc error fix performed on chunk %d:1", ++ nand_chunk); ++ dev->n_ecc_fixed++; ++ } else if (ecc_result2 < 0) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "**>>yaffs ecc error unfixed on chunk %d:1", ++ nand_chunk); ++ dev->n_ecc_unfixed++; ++ } ++ ++ if (ecc_result1 || ecc_result2) { ++ /* We had a data problem on this page */ ++ yaffs_handle_rd_data_error(dev, nand_chunk); ++ } ++ ++ if (ecc_result1 < 0 || ecc_result2 < 0) ++ *ecc_result = YAFFS_ECC_RESULT_UNFIXED; ++ else if (ecc_result1 > 0 || ecc_result2 > 0) ++ *ecc_result = YAFFS_ECC_RESULT_FIXED; ++ else ++ *ecc_result = YAFFS_ECC_RESULT_NO_ERROR; ++ ++ return ret_val; ++} ++ ++/* ++ * Functions for robustisizing ++ */ ++ ++static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk) ++{ ++ int flash_block = nand_chunk / dev->param.chunks_per_block; ++ ++ /* Mark the block for retirement */ ++ yaffs_get_block_info(dev, flash_block + dev->block_offset)-> ++ needs_retiring = 1; ++ yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS, ++ "**>>Block %d marked for retirement", ++ flash_block); ++ ++ /* TODO: ++ * Just do a garbage collection on the affected block ++ * then retire the block ++ * NB recursion ++ */ ++} ++ ++static int yaffs_tags_compat_wr(struct yaffs_dev *dev, ++ int nand_chunk, ++ const u8 *data, const struct yaffs_ext_tags *ext_tags) ++{ ++ struct yaffs_spare spare; ++ struct yaffs_tags tags; ++ ++ yaffs_spare_init(&spare); ++ ++ if (ext_tags->is_deleted) ++ spare.page_status = 0; ++ else { ++ tags.obj_id = ext_tags->obj_id; ++ tags.chunk_id = ext_tags->chunk_id; ++ ++ tags.n_bytes_lsb = ext_tags->n_bytes & (1024 - 1); ++ ++ if (dev->data_bytes_per_chunk >= 1024) ++ tags.n_bytes_msb = (ext_tags->n_bytes >> 10) & 3; ++ else ++ tags.n_bytes_msb = 3; ++ ++ tags.serial_number = ext_tags->serial_number; ++ ++ if (!dev->param.use_nand_ecc && data) { ++ yaffs_ecc_calc(data, spare.ecc1); ++ yaffs_ecc_calc(&data[256], spare.ecc2); ++ } ++ ++ yaffs_load_tags_to_spare(dev, &spare, &tags); ++ } ++ return yaffs_wr_nand(dev, nand_chunk, data, &spare); ++} ++ ++static int yaffs_tags_compat_rd(struct yaffs_dev *dev, ++ int nand_chunk, ++ u8 *data, struct yaffs_ext_tags *ext_tags) ++{ ++ struct yaffs_spare spare; ++ struct yaffs_tags tags; ++ enum yaffs_ecc_result ecc_result = YAFFS_ECC_RESULT_UNKNOWN; ++ static struct yaffs_spare spare_ff; ++ static int init; ++ int deleted; ++ ++ if (!init) { ++ memset(&spare_ff, 0xff, sizeof(spare_ff)); ++ init = 1; ++ } ++ ++ if (!yaffs_rd_chunk_nand(dev, nand_chunk, ++ data, &spare, &ecc_result, 1)) ++ return YAFFS_FAIL; ++ ++ /* ext_tags may be NULL */ ++ if (!ext_tags) ++ return YAFFS_OK; ++ ++ deleted = (hweight8(spare.page_status) < 7) ? 1 : 0; ++ ++ ext_tags->is_deleted = deleted; ++ ext_tags->ecc_result = ecc_result; ++ ext_tags->block_bad = 0; /* We're reading it */ ++ /* therefore it is not a bad block */ ++ ext_tags->chunk_used = ++ memcmp(&spare_ff, &spare, sizeof(spare_ff)) ? 1 : 0; ++ ++ if (ext_tags->chunk_used) { ++ yaffs_get_tags_from_spare(dev, &spare, &tags); ++ ++ ext_tags->obj_id = tags.obj_id; ++ ext_tags->chunk_id = tags.chunk_id; ++ ext_tags->n_bytes = tags.n_bytes_lsb; ++ ++ if (dev->data_bytes_per_chunk >= 1024) ++ ext_tags->n_bytes |= ++ (((unsigned)tags.n_bytes_msb) << 10); ++ ++ ext_tags->serial_number = tags.serial_number; ++ } ++ ++ return YAFFS_OK; ++} ++ ++static int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int flash_block) ++{ ++ struct yaffs_spare spare; ++ ++ memset(&spare, 0xff, sizeof(struct yaffs_spare)); ++ ++ spare.block_status = 'Y'; ++ ++ yaffs_wr_nand(dev, flash_block * dev->param.chunks_per_block, NULL, ++ &spare); ++ yaffs_wr_nand(dev, flash_block * dev->param.chunks_per_block + 1, ++ NULL, &spare); ++ ++ return YAFFS_OK; ++} ++ ++static int yaffs_tags_compat_query_block(struct yaffs_dev *dev, ++ int block_no, ++ enum yaffs_block_state *state, ++ u32 *seq_number) ++{ ++ struct yaffs_spare spare0, spare1; ++ static struct yaffs_spare spare_ff; ++ static int init; ++ enum yaffs_ecc_result dummy; ++ ++ if (!init) { ++ memset(&spare_ff, 0xff, sizeof(spare_ff)); ++ init = 1; ++ } ++ ++ *seq_number = 0; ++ ++ /* Look for bad block markers in the first two chunks */ ++ yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block, ++ NULL, &spare0, &dummy, 0); ++ yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block + 1, ++ NULL, &spare1, &dummy, 0); ++ ++ if (hweight8(spare0.block_status & spare1.block_status) < 7) ++ *state = YAFFS_BLOCK_STATE_DEAD; ++ else if (memcmp(&spare_ff, &spare0, sizeof(spare_ff)) == 0) ++ *state = YAFFS_BLOCK_STATE_EMPTY; ++ else ++ *state = YAFFS_BLOCK_STATE_NEEDS_SCAN; ++ ++ return YAFFS_OK; ++} ++ ++void yaffs_tags_compat_install(struct yaffs_dev *dev) ++{ ++ if(dev->param.is_yaffs2) ++ return; ++ if(!dev->tagger.write_chunk_tags_fn) ++ dev->tagger.write_chunk_tags_fn = yaffs_tags_compat_wr; ++ if(!dev->tagger.read_chunk_tags_fn) ++ dev->tagger.read_chunk_tags_fn = yaffs_tags_compat_rd; ++ if(!dev->tagger.query_block_fn) ++ dev->tagger.query_block_fn = yaffs_tags_compat_query_block; ++ if(!dev->tagger.mark_bad_fn) ++ dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad; ++} +diff --git a/fs/yaffs2/yaffs_tagscompat.h b/fs/yaffs2/yaffs_tagscompat.h +new file mode 100644 +index 0000000..92d298a +--- /dev/null ++++ b/fs/yaffs2/yaffs_tagscompat.h +@@ -0,0 +1,44 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_TAGSCOMPAT_H__ ++#define __YAFFS_TAGSCOMPAT_H__ ++ ++ ++#include "yaffs_guts.h" ++ ++#if 0 ++ ++ ++int yaffs_tags_compat_wr(struct yaffs_dev *dev, ++ int nand_chunk, ++ const u8 *data, const struct yaffs_ext_tags *tags); ++int yaffs_tags_compat_rd(struct yaffs_dev *dev, ++ int nand_chunk, ++ u8 *data, struct yaffs_ext_tags *tags); ++int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int block_no); ++int yaffs_tags_compat_query_block(struct yaffs_dev *dev, ++ int block_no, ++ enum yaffs_block_state *state, ++ u32 *seq_number); ++ ++#endif ++ ++ ++void yaffs_tags_compat_install(struct yaffs_dev *dev); ++void yaffs_calc_tags_ecc(struct yaffs_tags *tags); ++int yaffs_check_tags_ecc(struct yaffs_tags *tags); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_tagsmarshall.c b/fs/yaffs2/yaffs_tagsmarshall.c +new file mode 100644 +index 0000000..4a120d8 +--- /dev/null ++++ b/fs/yaffs2/yaffs_tagsmarshall.c +@@ -0,0 +1,206 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * 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 handles the marshalling (ie internal<-->external structure ++ * translation between the internal tags and the stored tags in Yaffs2-style ++ * tags storage. ++ */ ++ ++#include "yaffs_guts.h" ++#include "yaffs_trace.h" ++#include "yaffs_packedtags2.h" ++ ++static int yaffs_tags_marshall_write(struct yaffs_dev *dev, ++ int nand_chunk, const u8 *data, ++ const struct yaffs_ext_tags *tags) ++{ ++ struct yaffs_packed_tags2 pt; ++ int retval; ++ ++ int packed_tags_size = ++ dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt); ++ void *packed_tags_ptr = ++ dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt; ++ ++ yaffs_trace(YAFFS_TRACE_MTD, ++ "yaffs_tags_marshall_write chunk %d data %p tags %p", ++ nand_chunk, data, tags); ++ ++ /* For yaffs2 writing there must be both data and tags. ++ * If we're using inband tags, then the tags are stuffed into ++ * the end of the data buffer. ++ */ ++ if (!data || !tags) ++ BUG(); ++ else if (dev->param.inband_tags) { ++ struct yaffs_packed_tags2_tags_only *pt2tp; ++ pt2tp = ++ (struct yaffs_packed_tags2_tags_only *)(data + ++ dev-> ++ data_bytes_per_chunk); ++ yaffs_pack_tags2_tags_only(dev, pt2tp, tags); ++ } else { ++ yaffs_pack_tags2(dev, &pt, tags, !dev->param.no_tags_ecc); ++ } ++ ++ retval = dev->drv.drv_write_chunk_fn(dev, nand_chunk, ++ data, dev->param.total_bytes_per_chunk, ++ (dev->param.inband_tags) ? NULL : packed_tags_ptr, ++ (dev->param.inband_tags) ? 0 : packed_tags_size); ++ ++ return retval; ++} ++ ++static int yaffs_tags_marshall_read(struct yaffs_dev *dev, ++ int nand_chunk, u8 *data, ++ struct yaffs_ext_tags *tags) ++{ ++ int retval = 0; ++ int local_data = 0; ++ u8 spare_buffer[100]; ++ enum yaffs_ecc_result ecc_result; ++ ++ struct yaffs_packed_tags2 pt; ++ ++ int packed_tags_size = ++ dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt); ++ void *packed_tags_ptr = ++ dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt; ++ ++ yaffs_trace(YAFFS_TRACE_MTD, ++ "yaffs_tags_marshall_read chunk %d data %p tags %p", ++ nand_chunk, data, tags); ++ ++ if (dev->param.inband_tags) { ++ if (!data) { ++ local_data = 1; ++ data = yaffs_get_temp_buffer(dev); ++ } ++ } ++ ++ if (dev->param.inband_tags || (data && !tags)) ++ retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk, ++ data, dev->param.total_bytes_per_chunk, ++ NULL, 0, ++ &ecc_result); ++ else if (tags) ++ retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk, ++ data, dev->param.total_bytes_per_chunk, ++ spare_buffer, packed_tags_size, ++ &ecc_result); ++ else ++ BUG(); ++ ++ ++ if (retval == YAFFS_FAIL) ++ return YAFFS_FAIL; ++ ++ if (dev->param.inband_tags) { ++ if (tags) { ++ struct yaffs_packed_tags2_tags_only *pt2tp; ++ pt2tp = ++ (struct yaffs_packed_tags2_tags_only *) ++ &data[dev->data_bytes_per_chunk]; ++ yaffs_unpack_tags2_tags_only(dev, tags, pt2tp); ++ } ++ } else if (tags) { ++ memcpy(packed_tags_ptr, spare_buffer, packed_tags_size); ++ yaffs_unpack_tags2(dev, tags, &pt, !dev->param.no_tags_ecc); ++ } ++ ++ if (local_data) ++ yaffs_release_temp_buffer(dev, data); ++ ++ if (tags && ecc_result == YAFFS_ECC_RESULT_UNFIXED) { ++ tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED; ++ dev->n_ecc_unfixed++; ++ } ++ ++ if (tags && ecc_result == YAFFS_ECC_RESULT_FIXED) { ++ if (tags->ecc_result <= YAFFS_ECC_RESULT_NO_ERROR) ++ tags->ecc_result = YAFFS_ECC_RESULT_FIXED; ++ dev->n_ecc_fixed++; ++ } ++ ++ if (ecc_result < YAFFS_ECC_RESULT_UNFIXED) ++ return YAFFS_OK; ++ else ++ return YAFFS_FAIL; ++} ++ ++static int yaffs_tags_marshall_query_block(struct yaffs_dev *dev, int block_no, ++ enum yaffs_block_state *state, ++ u32 *seq_number) ++{ ++ int retval; ++ ++ yaffs_trace(YAFFS_TRACE_MTD, "yaffs_tags_marshall_query_block %d", ++ block_no); ++ ++ retval = dev->drv.drv_check_bad_fn(dev, block_no); ++ ++ if (retval== YAFFS_FAIL) { ++ yaffs_trace(YAFFS_TRACE_MTD, "block is bad"); ++ ++ *state = YAFFS_BLOCK_STATE_DEAD; ++ *seq_number = 0; ++ } else { ++ struct yaffs_ext_tags t; ++ ++ yaffs_tags_marshall_read(dev, ++ block_no * dev->param.chunks_per_block, ++ NULL, &t); ++ ++ if (t.chunk_used) { ++ *seq_number = t.seq_number; ++ *state = YAFFS_BLOCK_STATE_NEEDS_SCAN; ++ } else { ++ *seq_number = 0; ++ *state = YAFFS_BLOCK_STATE_EMPTY; ++ } ++ } ++ ++ yaffs_trace(YAFFS_TRACE_MTD, ++ "block query returns seq %d state %d", ++ *seq_number, *state); ++ ++ if (retval == 0) ++ return YAFFS_OK; ++ else ++ return YAFFS_FAIL; ++} ++ ++static int yaffs_tags_marshall_mark_bad(struct yaffs_dev *dev, int block_no) ++{ ++ return dev->drv.drv_mark_bad_fn(dev, block_no); ++ ++} ++ ++ ++void yaffs_tags_marshall_install(struct yaffs_dev *dev) ++{ ++ if (!dev->param.is_yaffs2) ++ return; ++ ++ if (!dev->tagger.write_chunk_tags_fn) ++ dev->tagger.write_chunk_tags_fn = yaffs_tags_marshall_write; ++ ++ if (!dev->tagger.read_chunk_tags_fn) ++ dev->tagger.read_chunk_tags_fn = yaffs_tags_marshall_read; ++ ++ if (!dev->tagger.query_block_fn) ++ dev->tagger.query_block_fn = yaffs_tags_marshall_query_block; ++ ++ if (!dev->tagger.mark_bad_fn) ++ dev->tagger.mark_bad_fn = yaffs_tags_marshall_mark_bad; ++ ++} +diff --git a/fs/yaffs2/yaffs_tagsmarshall.h b/fs/yaffs2/yaffs_tagsmarshall.h +new file mode 100644 +index 0000000..bf3e68a +--- /dev/null ++++ b/fs/yaffs2/yaffs_tagsmarshall.h +@@ -0,0 +1,22 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_TAGSMARSHALL_H__ ++#define __YAFFS_TAGSMARSHALL_H__ ++ ++#include "yaffs_guts.h" ++void yaffs_tags_marshall_install(struct yaffs_dev *dev); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_trace.h b/fs/yaffs2/yaffs_trace.h +new file mode 100644 +index 0000000..fd26054 +--- /dev/null ++++ b/fs/yaffs2/yaffs_trace.h +@@ -0,0 +1,57 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YTRACE_H__ ++#define __YTRACE_H__ ++ ++extern unsigned int yaffs_trace_mask; ++extern unsigned int yaffs_wr_attempts; ++ ++/* ++ * Tracing flags. ++ * The flags masked in YAFFS_TRACE_ALWAYS are always traced. ++ */ ++ ++#define YAFFS_TRACE_OS 0x00000002 ++#define YAFFS_TRACE_ALLOCATE 0x00000004 ++#define YAFFS_TRACE_SCAN 0x00000008 ++#define YAFFS_TRACE_BAD_BLOCKS 0x00000010 ++#define YAFFS_TRACE_ERASE 0x00000020 ++#define YAFFS_TRACE_GC 0x00000040 ++#define YAFFS_TRACE_WRITE 0x00000080 ++#define YAFFS_TRACE_TRACING 0x00000100 ++#define YAFFS_TRACE_DELETION 0x00000200 ++#define YAFFS_TRACE_BUFFERS 0x00000400 ++#define YAFFS_TRACE_NANDACCESS 0x00000800 ++#define YAFFS_TRACE_GC_DETAIL 0x00001000 ++#define YAFFS_TRACE_SCAN_DEBUG 0x00002000 ++#define YAFFS_TRACE_MTD 0x00004000 ++#define YAFFS_TRACE_CHECKPOINT 0x00008000 ++ ++#define YAFFS_TRACE_VERIFY 0x00010000 ++#define YAFFS_TRACE_VERIFY_NAND 0x00020000 ++#define YAFFS_TRACE_VERIFY_FULL 0x00040000 ++#define YAFFS_TRACE_VERIFY_ALL 0x000f0000 ++ ++#define YAFFS_TRACE_SYNC 0x00100000 ++#define YAFFS_TRACE_BACKGROUND 0x00200000 ++#define YAFFS_TRACE_LOCK 0x00400000 ++#define YAFFS_TRACE_MOUNT 0x00800000 ++ ++#define YAFFS_TRACE_ERROR 0x40000000 ++#define YAFFS_TRACE_BUG 0x80000000 ++#define YAFFS_TRACE_ALWAYS 0xf0000000 ++ ++#endif +diff --git a/fs/yaffs2/yaffs_verify.c b/fs/yaffs2/yaffs_verify.c +new file mode 100644 +index 0000000..7a341a2 +--- /dev/null ++++ b/fs/yaffs2/yaffs_verify.c +@@ -0,0 +1,540 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * 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 "yaffs_verify.h" ++#include "yaffs_trace.h" ++#include "yaffs_bitmap.h" ++#include "yaffs_getblockinfo.h" ++#include "yaffs_nand.h" ++ ++int yaffs_skip_verification(struct yaffs_dev *dev) ++{ ++ (void) dev; ++ return !(yaffs_trace_mask & ++ (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL)); ++} ++ ++static int yaffs_skip_full_verification(struct yaffs_dev *dev) ++{ ++ (void) dev; ++ return !(yaffs_trace_mask & (YAFFS_TRACE_VERIFY_FULL)); ++} ++ ++static int yaffs_skip_nand_verification(struct yaffs_dev *dev) ++{ ++ (void) dev; ++ return !(yaffs_trace_mask & (YAFFS_TRACE_VERIFY_NAND)); ++} ++ ++static const char * const block_state_name[] = { ++ "Unknown", ++ "Needs scan", ++ "Scanning", ++ "Empty", ++ "Allocating", ++ "Full", ++ "Dirty", ++ "Checkpoint", ++ "Collecting", ++ "Dead" ++}; ++ ++void yaffs_verify_blk(struct yaffs_dev *dev, struct yaffs_block_info *bi, int n) ++{ ++ int actually_used; ++ int in_use; ++ ++ if (yaffs_skip_verification(dev)) ++ return; ++ ++ /* Report illegal runtime states */ ++ if (bi->block_state >= YAFFS_NUMBER_OF_BLOCK_STATES) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Block %d has undefined state %d", ++ n, bi->block_state); ++ ++ switch (bi->block_state) { ++ case YAFFS_BLOCK_STATE_UNKNOWN: ++ case YAFFS_BLOCK_STATE_SCANNING: ++ case YAFFS_BLOCK_STATE_NEEDS_SCAN: ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Block %d has bad run-state %s", ++ n, block_state_name[bi->block_state]); ++ } ++ ++ /* Check pages in use and soft deletions are legal */ ++ ++ actually_used = bi->pages_in_use - bi->soft_del_pages; ++ ++ if (bi->pages_in_use < 0 || ++ bi->pages_in_use > (int)dev->param.chunks_per_block || ++ bi->soft_del_pages < 0 || ++ bi->soft_del_pages > (int)dev->param.chunks_per_block || ++ actually_used < 0 || actually_used > (int)dev->param.chunks_per_block) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Block %d has illegal values pages_in_used %d soft_del_pages %d", ++ n, bi->pages_in_use, bi->soft_del_pages); ++ ++ /* Check chunk bitmap legal */ ++ in_use = yaffs_count_chunk_bits(dev, n); ++ if (in_use != bi->pages_in_use) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Block %d has inconsistent values pages_in_use %d counted chunk bits %d", ++ n, bi->pages_in_use, in_use); ++} ++ ++void yaffs_verify_collected_blk(struct yaffs_dev *dev, ++ struct yaffs_block_info *bi, int n) ++{ ++ yaffs_verify_blk(dev, bi, n); ++ ++ /* After collection the block should be in the erased state */ ++ ++ if (bi->block_state != YAFFS_BLOCK_STATE_COLLECTING && ++ bi->block_state != YAFFS_BLOCK_STATE_EMPTY) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "Block %d is in state %d after gc, should be erased", ++ n, bi->block_state); ++ } ++} ++ ++void yaffs_verify_blocks(struct yaffs_dev *dev) ++{ ++ u32 i; ++ u32 state_count[YAFFS_NUMBER_OF_BLOCK_STATES]; ++ int illegal_states = 0; ++ ++ if (yaffs_skip_verification(dev)) ++ return; ++ ++ memset(state_count, 0, sizeof(state_count)); ++ ++ for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) { ++ struct yaffs_block_info *bi = yaffs_get_block_info(dev, i); ++ yaffs_verify_blk(dev, bi, i); ++ ++ if (bi->block_state < YAFFS_NUMBER_OF_BLOCK_STATES) ++ state_count[bi->block_state]++; ++ else ++ illegal_states++; ++ } ++ ++ yaffs_trace(YAFFS_TRACE_VERIFY, "Block summary"); ++ ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "%d blocks have illegal states", ++ illegal_states); ++ if (state_count[YAFFS_BLOCK_STATE_ALLOCATING] > 1) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Too many allocating blocks"); ++ ++ for (i = 0; i < YAFFS_NUMBER_OF_BLOCK_STATES; i++) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "%s %d blocks", ++ block_state_name[i], state_count[i]); ++ ++ if (dev->blocks_in_checkpt != state_count[YAFFS_BLOCK_STATE_CHECKPOINT]) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Checkpoint block count wrong dev %d count %d", ++ dev->blocks_in_checkpt, ++ state_count[YAFFS_BLOCK_STATE_CHECKPOINT]); ++ ++ if (dev->n_erased_blocks != (int)state_count[YAFFS_BLOCK_STATE_EMPTY]) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Erased block count wrong dev %d count %d", ++ dev->n_erased_blocks, ++ state_count[YAFFS_BLOCK_STATE_EMPTY]); ++ ++ if (state_count[YAFFS_BLOCK_STATE_COLLECTING] > 1) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Too many collecting blocks %d (max is 1)", ++ state_count[YAFFS_BLOCK_STATE_COLLECTING]); ++} ++ ++/* ++ * Verify the object header. oh must be valid, but obj and tags may be NULL in ++ * which case those tests will not be performed. ++ */ ++void yaffs_verify_oh(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh, ++ struct yaffs_ext_tags *tags, int parent_check) ++{ ++ if (obj && yaffs_skip_verification(obj->my_dev)) ++ return; ++ ++ if (!(tags && obj && oh)) { ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Verifying object header tags %p obj %p oh %p", ++ tags, obj, oh); ++ return; ++ } ++ ++ if (oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN || ++ oh->type > YAFFS_OBJECT_TYPE_MAX) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d header type is illegal value 0x%x", ++ tags->obj_id, oh->type); ++ ++ if (tags->obj_id != obj->obj_id) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d header mismatch obj_id %d", ++ tags->obj_id, obj->obj_id); ++ ++ /* ++ * Check that the object's parent ids match if parent_check requested. ++ * ++ * Tests do not apply to the root object. ++ */ ++ ++ if (parent_check && tags->obj_id > 1 && !obj->parent) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d header mismatch parent_id %d obj->parent is NULL", ++ tags->obj_id, oh->parent_obj_id); ++ ++ if (parent_check && obj->parent && ++ oh->parent_obj_id != obj->parent->obj_id && ++ (oh->parent_obj_id != YAFFS_OBJECTID_UNLINKED || ++ obj->parent->obj_id != YAFFS_OBJECTID_DELETED)) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d header mismatch parent_id %d parent_obj_id %d", ++ tags->obj_id, oh->parent_obj_id, ++ obj->parent->obj_id); ++ ++ if (tags->obj_id > 1 && oh->name[0] == 0) /* Null name */ ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d header name is NULL", ++ obj->obj_id); ++ ++ if (tags->obj_id > 1 && ((u8) (oh->name[0])) == 0xff) /* Junk name */ ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d header name is 0xff", ++ obj->obj_id); ++} ++ ++void yaffs_verify_file(struct yaffs_obj *obj) ++{ ++ u32 x; ++ int required_depth; ++ int last_chunk; ++ u32 offset_in_chunk; ++ u32 the_chunk; ++ ++ int i; ++ struct yaffs_dev *dev; ++ struct yaffs_ext_tags tags; ++ struct yaffs_tnode *tn; ++ u32 obj_id; ++ ++ if (!obj) ++ return; ++ ++ if (yaffs_skip_verification(obj->my_dev)) ++ return; ++ ++ dev = obj->my_dev; ++ obj_id = obj->obj_id; ++ ++ ++ /* Check file size is consistent with tnode depth */ ++ yaffs_addr_to_chunk(dev, obj->variant.file_variant.file_size, ++ &last_chunk, &offset_in_chunk); ++ last_chunk++; ++ x = last_chunk >> YAFFS_TNODES_LEVEL0_BITS; ++ required_depth = 0; ++ while (x > 0) { ++ x >>= YAFFS_TNODES_INTERNAL_BITS; ++ required_depth++; ++ } ++ ++ /* Check that the chunks in the tnode tree are all correct. ++ * We do this by scanning through the tnode tree and ++ * checking the tags for every chunk match. ++ */ ++ ++ if (yaffs_skip_nand_verification(dev)) ++ return; ++ ++ for (i = 1; i <= last_chunk; i++) { ++ tn = yaffs_find_tnode_0(dev, &obj->variant.file_variant, i); ++ ++ if (!tn) ++ continue; ++ ++ the_chunk = yaffs_get_group_base(dev, tn, i); ++ if (the_chunk > 0) { ++ yaffs_rd_chunk_tags_nand(dev, the_chunk, NULL, ++ &tags); ++ if (tags.obj_id != obj_id || tags.chunk_id != (u32)i) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Object %d chunk_id %d NAND mismatch chunk %d tags (%d:%d)", ++ obj_id, i, the_chunk, ++ tags.obj_id, tags.chunk_id); ++ } ++ } ++} ++ ++void yaffs_verify_link(struct yaffs_obj *obj) ++{ ++ if (obj && yaffs_skip_verification(obj->my_dev)) ++ return; ++ ++ /* Verify sane equivalent object */ ++} ++ ++void yaffs_verify_symlink(struct yaffs_obj *obj) ++{ ++ if (obj && yaffs_skip_verification(obj->my_dev)) ++ return; ++ ++ /* Verify symlink string */ ++} ++ ++void yaffs_verify_special(struct yaffs_obj *obj) ++{ ++ if (obj && yaffs_skip_verification(obj->my_dev)) ++ return; ++} ++ ++void yaffs_verify_obj(struct yaffs_obj *obj) ++{ ++ struct yaffs_dev *dev; ++ u32 chunk_min; ++ u32 chunk_max; ++ u32 chunk_id_ok; ++ u32 chunk_in_range; ++ u32 chunk_wrongly_deleted; ++ u32 chunk_valid; ++ ++ if (!obj) ++ return; ++ ++ if (obj->being_created) ++ return; ++ ++ dev = obj->my_dev; ++ ++ if (yaffs_skip_verification(dev)) ++ return; ++ ++ /* Check sane object header chunk */ ++ ++ chunk_min = dev->internal_start_block * dev->param.chunks_per_block; ++ chunk_max = ++ (dev->internal_end_block + 1) * dev->param.chunks_per_block - 1; ++ ++ chunk_in_range = (((unsigned)(obj->hdr_chunk)) >= chunk_min && ++ ((unsigned)(obj->hdr_chunk)) <= chunk_max); ++ chunk_id_ok = chunk_in_range || (obj->hdr_chunk == 0); ++ chunk_valid = chunk_in_range && ++ yaffs_check_chunk_bit(dev, ++ obj->hdr_chunk / dev->param.chunks_per_block, ++ obj->hdr_chunk % dev->param.chunks_per_block); ++ chunk_wrongly_deleted = chunk_in_range && !chunk_valid; ++ ++ if (!obj->fake && (!chunk_id_ok || chunk_wrongly_deleted)) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d has chunk_id %d %s %s", ++ obj->obj_id, obj->hdr_chunk, ++ chunk_id_ok ? "" : ",out of range", ++ chunk_wrongly_deleted ? ",marked as deleted" : ""); ++ ++ if (chunk_valid && !yaffs_skip_nand_verification(dev)) { ++ struct yaffs_ext_tags tags; ++ struct yaffs_obj_hdr *oh; ++ u8 *buffer = yaffs_get_temp_buffer(dev); ++ ++ oh = (struct yaffs_obj_hdr *)buffer; ++ ++ yaffs_rd_chunk_tags_nand(dev, obj->hdr_chunk, buffer, &tags); ++ ++ yaffs_verify_oh(obj, oh, &tags, 1); ++ ++ yaffs_release_temp_buffer(dev, buffer); ++ } ++ ++ /* Verify it has a parent */ ++ if (obj && !obj->fake && (!obj->parent || obj->parent->my_dev != dev)) { ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d has parent pointer %p which does not look like an object", ++ obj->obj_id, obj->parent); ++ } ++ ++ /* Verify parent is a directory */ ++ if (obj->parent && ++ obj->parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d's parent is not a directory (type %d)", ++ obj->obj_id, obj->parent->variant_type); ++ } ++ ++ switch (obj->variant_type) { ++ case YAFFS_OBJECT_TYPE_FILE: ++ yaffs_verify_file(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ yaffs_verify_symlink(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ yaffs_verify_dir(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ yaffs_verify_link(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ yaffs_verify_special(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_UNKNOWN: ++ default: ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d has illegaltype %d", ++ obj->obj_id, obj->variant_type); ++ break; ++ } ++} ++ ++void yaffs_verify_objects(struct yaffs_dev *dev) ++{ ++ struct yaffs_obj *obj; ++ int i; ++ struct list_head *lh; ++ ++ if (yaffs_skip_verification(dev)) ++ return; ++ ++ /* Iterate through the objects in each hash entry */ ++ ++ for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) { ++ list_for_each(lh, &dev->obj_bucket[i].list) { ++ obj = list_entry(lh, struct yaffs_obj, hash_link); ++ yaffs_verify_obj(obj); ++ } ++ } ++} ++ ++void yaffs_verify_obj_in_dir(struct yaffs_obj *obj) ++{ ++ struct list_head *lh; ++ struct yaffs_obj *list_obj; ++ int count = 0; ++ ++ if (!obj) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "No object to verify"); ++ BUG(); ++ return; ++ } ++ ++ if (yaffs_skip_verification(obj->my_dev)) ++ return; ++ ++ if (!obj->parent) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "Object does not have parent"); ++ BUG(); ++ return; ++ } ++ ++ if (obj->parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "Parent is not directory"); ++ BUG(); ++ } ++ ++ /* Iterate through the objects in each hash entry */ ++ ++ list_for_each(lh, &obj->parent->variant.dir_variant.children) { ++ list_obj = list_entry(lh, struct yaffs_obj, siblings); ++ yaffs_verify_obj(list_obj); ++ if (obj == list_obj) ++ count++; ++ } ++ ++ if (count != 1) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "Object in directory %d times", ++ count); ++ BUG(); ++ } ++} ++ ++void yaffs_verify_dir(struct yaffs_obj *directory) ++{ ++ struct list_head *lh; ++ struct yaffs_obj *list_obj; ++ struct yaffs_dev *dev; ++ ++ if (!directory) { ++ BUG(); ++ return; ++ } ++ ++ dev = directory->my_dev; ++ ++ if (!dev) { ++ BUG(); ++ return; ++ } ++ ++ if (directory == dev->root_dir || ++ directory == dev->lost_n_found || ++ directory == dev->unlinked_dir || ++ directory == dev->del_dir) ++ return; ++ ++ if (yaffs_skip_full_verification(directory->my_dev)) ++ return; ++ ++ if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "Directory has wrong type: %d", ++ directory->variant_type); ++ BUG(); ++ } ++ ++ /* Iterate through the objects in each hash entry */ ++ ++ list_for_each(lh, &directory->variant.dir_variant.children) { ++ list_obj = list_entry(lh, struct yaffs_obj, siblings); ++ if (list_obj->parent != directory) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "Object in directory list has wrong parent %p", ++ list_obj->parent); ++ BUG(); ++ } ++ yaffs_verify_obj_in_dir(list_obj); ++ } ++} ++ ++static int yaffs_free_verification_failures; ++ ++void yaffs_verify_free_chunks(struct yaffs_dev *dev) ++{ ++ int counted; ++ int difference; ++ ++ if (yaffs_skip_verification(dev)) ++ return; ++ ++ counted = yaffs_count_free_chunks(dev); ++ ++ difference = dev->n_free_chunks - counted; ++ ++ if (difference) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "Freechunks verification failure %d %d %d", ++ dev->n_free_chunks, counted, difference); ++ yaffs_free_verification_failures++; ++ } ++} ++ ++int yaffs_verify_file_sane(struct yaffs_obj *in) ++{ ++ (void) in; ++ return YAFFS_OK; ++} +diff --git a/fs/yaffs2/yaffs_verify.h b/fs/yaffs2/yaffs_verify.h +new file mode 100644 +index 0000000..4f4af8d +--- /dev/null ++++ b/fs/yaffs2/yaffs_verify.h +@@ -0,0 +1,43 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_VERIFY_H__ ++#define __YAFFS_VERIFY_H__ ++ ++#include "yaffs_guts.h" ++ ++void yaffs_verify_blk(struct yaffs_dev *dev, struct yaffs_block_info *bi, ++ int n); ++void yaffs_verify_collected_blk(struct yaffs_dev *dev, ++ struct yaffs_block_info *bi, int n); ++void yaffs_verify_blocks(struct yaffs_dev *dev); ++ ++void yaffs_verify_oh(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh, ++ struct yaffs_ext_tags *tags, int parent_check); ++void yaffs_verify_file(struct yaffs_obj *obj); ++void yaffs_verify_link(struct yaffs_obj *obj); ++void yaffs_verify_symlink(struct yaffs_obj *obj); ++void yaffs_verify_special(struct yaffs_obj *obj); ++void yaffs_verify_obj(struct yaffs_obj *obj); ++void yaffs_verify_objects(struct yaffs_dev *dev); ++void yaffs_verify_obj_in_dir(struct yaffs_obj *obj); ++void yaffs_verify_dir(struct yaffs_obj *directory); ++void yaffs_verify_free_chunks(struct yaffs_dev *dev); ++ ++int yaffs_verify_file_sane(struct yaffs_obj *obj); ++ ++int yaffs_skip_verification(struct yaffs_dev *dev); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c +new file mode 100644 +index 0000000..acb0c4a +--- /dev/null ++++ b/fs/yaffs2/yaffs_vfs.c +@@ -0,0 +1,3751 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * Acknowledgements: ++ * Luc van OostenRyck for numerous patches. ++ * Nick Bane for numerous patches. ++ * Nick Bane for 2.5/2.6 integration. ++ * Andras Toth for mknod rdev issue. ++ * Michael Fischer for finding the problem with inode inconsistency. ++ * Some code bodily lifted from JFFS ++ * ++ * 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 is the file system front-end to YAFFS that hooks it up to ++ * the VFS. ++ * ++ * Special notes: ++ * >> 2.4: sb->u.generic_sbp points to the struct yaffs_dev associated with ++ * this superblock ++ * >> 2.6: sb->s_fs_info points to the struct yaffs_dev associated with this ++ * superblock ++ * >> inode->u.generic_ip points to the associated struct yaffs_obj. ++ */ ++ ++/* ++ * There are two variants of the VFS glue code. This variant should compile ++ * for any version of Linux. ++ */ ++#include ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)) ++#define YAFFS_COMPILE_BACKGROUND ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)) ++#define YAFFS_COMPILE_FREEZER ++#endif ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) ++#define YAFFS_COMPILE_EXPORTFS ++#endif ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)) ++#define YAFFS_USE_SETATTR_COPY ++#define YAFFS_USE_TRUNCATE_SETSIZE ++#endif ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)) ++#define YAFFS_HAS_EVICT_INODE ++#endif ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)) && \ ++ (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)) ++#define YAFFS_NEW_FOLLOW_LINK 1 ++#else ++#define YAFFS_NEW_FOLLOW_LINK 0 ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) ++#define YAFFS_HAS_WRITE_SUPER ++#endif ++ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)) ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)) ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++ ++#if (YAFFS_NEW_FOLLOW_LINK == 1) ++#include ++#endif ++ ++#ifdef YAFFS_COMPILE_EXPORTFS ++#include ++#endif ++ ++#ifdef YAFFS_COMPILE_BACKGROUND ++#include ++#include ++#endif ++#ifdef YAFFS_COMPILE_FREEZER ++#include ++#endif ++ ++#include ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++ ++#include ++ ++#define UnlockPage(p) unlock_page(p) ++#define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags) ++ ++/* FIXME: use sb->s_id instead ? */ ++#define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf) ++ ++#else ++ ++#include ++#define BDEVNAME_SIZE 0 ++#define yaffs_devname(sb, buf) kdevname(sb->s_dev) ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)) ++/* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */ ++#define __user ++#endif ++ ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)) ++#define YPROC_ROOT (&proc_root) ++#else ++#define YPROC_ROOT NULL ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)) ++#define Y_INIT_TIMER(a) init_timer(a) ++#else ++#define Y_INIT_TIMER(a) init_timer_on_stack(a) ++#endif ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27)) ++#define YAFFS_USE_WRITE_BEGIN_END 1 ++#else ++#define YAFFS_USE_WRITE_BEGIN_END 0 ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) ++#define YAFFS_SUPER_HAS_DIRTY ++#endif ++ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) ++#define set_nlink(inode, count) do { (inode)->i_nlink = (count); } while(0) ++#endif ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28)) ++static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size) ++{ ++ uint64_t result = partition_size; ++ do_div(result, block_size); ++ return (uint32_t) result; ++} ++#else ++#define YCALCBLOCKS(s, b) ((s)/(b)) ++#endif ++ ++#include ++#include ++ ++#include "yportenv.h" ++#include "yaffs_trace.h" ++#include "yaffs_guts.h" ++#include "yaffs_attribs.h" ++ ++#include "yaffs_linux.h" ++ ++#include "yaffs_mtdif.h" ++#include "yaffs_packedtags2.h" ++#include "yaffs_getblockinfo.h" ++ ++unsigned int yaffs_trace_mask = ++ YAFFS_TRACE_BAD_BLOCKS | ++ YAFFS_TRACE_ALWAYS | ++ 0; ++ ++unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS; ++unsigned int yaffs_auto_checkpoint = 1; ++unsigned int yaffs_gc_control = 1; ++unsigned int yaffs_bg_enable = 1; ++unsigned int yaffs_auto_select = 1; ++/* Module Parameters */ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++module_param(yaffs_trace_mask, uint, 0644); ++module_param(yaffs_wr_attempts, uint, 0644); ++module_param(yaffs_auto_checkpoint, uint, 0644); ++module_param(yaffs_gc_control, uint, 0644); ++module_param(yaffs_bg_enable, uint, 0644); ++#else ++MODULE_PARM(yaffs_trace_mask, "i"); ++MODULE_PARM(yaffs_wr_attempts, "i"); ++MODULE_PARM(yaffs_auto_checkpoint, "i"); ++MODULE_PARM(yaffs_gc_control, "i"); ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)) ++/* use iget and read_inode */ ++#define Y_IGET(sb, inum) iget((sb), (inum)) ++ ++#else ++/* Call local equivalent */ ++#define YAFFS_USE_OWN_IGET ++#define Y_IGET(sb, inum) yaffs_iget((sb), (inum)) ++ ++#endif ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18)) ++#define yaffs_inode_to_obj_lv(iptr) ((iptr)->i_private) ++#else ++#define yaffs_inode_to_obj_lv(iptr) ((iptr)->u.generic_ip) ++#endif ++ ++#define yaffs_inode_to_obj(iptr) \ ++ ((struct yaffs_obj *)(yaffs_inode_to_obj_lv(iptr))) ++#define yaffs_dentry_to_obj(dptr) yaffs_inode_to_obj((dptr)->d_inode) ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++#define yaffs_super_to_dev(sb) ((struct yaffs_dev *)sb->s_fs_info) ++#else ++#define yaffs_super_to_dev(sb) ((struct yaffs_dev *)sb->u.generic_sbp) ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) ++#define Y_CLEAR_INODE(i) clear_inode(i) ++#else ++#define Y_CLEAR_INODE(i) end_writeback(i) ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) ++#define YAFFS_USE_DIR_ITERATE ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) ++#define YAFFS_USE_XATTR ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0)) ++#define YAFFS_NEW_PROCFS ++#include ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) ++#define PAGE_CACHE_SIZE PAGE_SIZE ++#define PAGE_CACHE_SHIFT PAGE_SHIFT ++#define Y_GET_DENTRY(f) ((f)->f_path.dentry) ++#define page_cache_release put_page ++#define YAFFS_NEW_XATTR 1 ++#define YAFFS_NEW_GET_LINK 1 ++#else ++#define Y_GET_DENTRY(f) ((f)->f_dentry) ++#define YAFFS_NEW_XATTR 0 ++#define YAFFS_NEW_GET_LINK 0 ++#endif ++ ++#define update_dir_time(dir) do {\ ++ (dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \ ++ } while (0) ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) ++static inline int setattr_prepare(struct dentry *dentry, struct iattr *attr) ++{ ++ return inode_change_ok(dentry->d_inode, attr); ++} ++#endif ++ ++static void yaffs_fill_inode_from_obj(struct inode *inode, ++ struct yaffs_obj *obj); ++ ++ ++static void yaffs_gross_lock(struct yaffs_dev *dev) ++{ ++ yaffs_trace(YAFFS_TRACE_LOCK, "yaffs locking %p", current); ++ mutex_lock(&(yaffs_dev_to_lc(dev)->gross_lock)); ++ yaffs_trace(YAFFS_TRACE_LOCK, "yaffs locked %p", current); ++} ++ ++static void yaffs_gross_unlock(struct yaffs_dev *dev) ++{ ++ yaffs_trace(YAFFS_TRACE_LOCK, "yaffs unlocking %p", current); ++ mutex_unlock(&(yaffs_dev_to_lc(dev)->gross_lock)); ++} ++ ++ ++static int yaffs_readpage_nolock(struct file *f, struct page *pg) ++{ ++ /* Lifted from jffs2 */ ++ ++ struct yaffs_obj *obj; ++ unsigned char *pg_buf; ++ int ret; ++ loff_t pos = ((loff_t) pg->index) << PAGE_SHIFT; ++ struct yaffs_dev *dev; ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_readpage_nolock at %lld, size %08x", ++ (long long)pos, ++ (unsigned)PAGE_SIZE); ++ ++ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f)); ++ ++ dev = obj->my_dev; ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++ BUG_ON(!PageLocked(pg)); ++#else ++ if (!PageLocked(pg)) ++ PAGE_BUG(pg); ++#endif ++ ++ pg_buf = kmap(pg); ++ /* FIXME: Can kmap fail? */ ++ ++ yaffs_gross_lock(dev); ++ ++ ret = yaffs_file_rd(obj, pg_buf, pos, PAGE_CACHE_SIZE); ++ ++ yaffs_gross_unlock(dev); ++ ++ if (ret >= 0) ++ ret = 0; ++ ++ if (ret) { ++ ClearPageUptodate(pg); ++ SetPageError(pg); ++ } else { ++ SetPageUptodate(pg); ++ ClearPageError(pg); ++ } ++ ++ flush_dcache_page(pg); ++ kunmap(pg); ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage_nolock done"); ++ return ret; ++} ++ ++static int yaffs_readpage_unlock(struct file *f, struct page *pg) ++{ ++ int ret = yaffs_readpage_nolock(f, pg); ++ UnlockPage(pg); ++ return ret; ++} ++ ++static int yaffs_readpage(struct file *f, struct page *pg) ++{ ++ int ret; ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage"); ++ ret = yaffs_readpage_unlock(f, pg); ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage done"); ++ return ret; ++} ++ ++ ++static void yaffs_set_super_dirty_val(struct yaffs_dev *dev, int val) ++{ ++ struct yaffs_linux_context *lc = yaffs_dev_to_lc(dev); ++ ++ if (lc) ++ lc->dirty = val; ++ ++# ifdef YAFFS_SUPER_HAS_DIRTY ++ { ++ struct super_block *sb = lc->super; ++ ++ if (sb) ++ sb->s_dirt = val; ++ } ++#endif ++ ++} ++ ++static void yaffs_set_super_dirty(struct yaffs_dev *dev) ++{ ++ yaffs_set_super_dirty_val(dev, 1); ++} ++ ++static void yaffs_clear_super_dirty(struct yaffs_dev *dev) ++{ ++ yaffs_set_super_dirty_val(dev, 0); ++} ++ ++static int yaffs_check_super_dirty(struct yaffs_dev *dev) ++{ ++ struct yaffs_linux_context *lc = yaffs_dev_to_lc(dev); ++ ++ if (lc && lc->dirty) ++ return 1; ++ ++# ifdef YAFFS_SUPER_HAS_DIRTY ++ { ++ struct super_block *sb = lc->super; ++ ++ if (sb && sb->s_dirt) ++ return 1; ++ } ++#endif ++ return 0; ++ ++} ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++static int yaffs_writepage(struct page *page, struct writeback_control *wbc) ++#else ++static int yaffs_writepage(struct page *page) ++#endif ++{ ++ struct yaffs_dev *dev; ++ struct address_space *mapping = page->mapping; ++ struct inode *inode; ++ unsigned long end_index; ++ char *buffer; ++ struct yaffs_obj *obj; ++ int n_written = 0; ++ unsigned n_bytes; ++ loff_t i_size; ++ ++ if (!mapping) ++ BUG(); ++ inode = mapping->host; ++ if (!inode) ++ BUG(); ++ i_size = i_size_read(inode); ++ ++ end_index = i_size >> PAGE_CACHE_SHIFT; ++ ++ if (page->index < end_index) ++ n_bytes = PAGE_CACHE_SIZE; ++ else { ++ n_bytes = i_size & (PAGE_CACHE_SIZE - 1); ++ ++ if (page->index > end_index || !n_bytes) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_writepage at %lld, inode size = %lld!!", ++ ((loff_t)page->index) << PAGE_CACHE_SHIFT, ++ inode->i_size); ++ yaffs_trace(YAFFS_TRACE_OS, ++ " -> don't care!!"); ++ ++ zero_user_segment(page, 0, PAGE_CACHE_SIZE); ++ set_page_writeback(page); ++ unlock_page(page); ++ end_page_writeback(page); ++ return 0; ++ } ++ } ++ ++ if (n_bytes != PAGE_CACHE_SIZE) ++ zero_user_segment(page, n_bytes, PAGE_CACHE_SIZE); ++ ++ get_page(page); ++ ++ buffer = kmap(page); ++ ++ obj = yaffs_inode_to_obj(inode); ++ dev = obj->my_dev; ++ yaffs_gross_lock(dev); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_writepage at %lld, size %08x", ++ ((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes); ++ yaffs_trace(YAFFS_TRACE_OS, ++ "writepag0: obj = %lld, ino = %lld", ++ obj->variant.file_variant.file_size, inode->i_size); ++ ++ n_written = yaffs_wr_file(obj, buffer, ++ ((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes, 0); ++ ++ yaffs_set_super_dirty(dev); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "writepag1: obj = %lld, ino = %lld", ++ obj->variant.file_variant.file_size, inode->i_size); ++ ++ yaffs_gross_unlock(dev); ++ ++ kunmap(page); ++ set_page_writeback(page); ++ unlock_page(page); ++ end_page_writeback(page); ++ put_page(page); ++ ++ return (n_written == n_bytes) ? 0 : -ENOSPC; ++} ++ ++/* Space holding and freeing is done to ensure we have space available for write_begin/end */ ++/* For now we just assume few parallel writes and check against a small number. */ ++/* Todo: need to do this with a counter to handle parallel reads better */ ++ ++static ssize_t yaffs_hold_space(struct file *f) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev; ++ ++ int n_free_chunks; ++ ++ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f)); ++ ++ dev = obj->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ n_free_chunks = yaffs_get_n_free_chunks(dev); ++ ++ yaffs_gross_unlock(dev); ++ ++ return (n_free_chunks > 20) ? 1 : 0; ++} ++ ++static void yaffs_release_space(struct file *f) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev; ++ ++ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f)); ++ ++ dev = obj->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ yaffs_gross_unlock(dev); ++} ++ ++#if (YAFFS_USE_WRITE_BEGIN_END > 0) ++static int yaffs_write_begin(struct file *filp, struct address_space *mapping, ++ loff_t pos, unsigned len, unsigned flags, ++ struct page **pagep, void **fsdata) ++{ ++ struct page *pg = NULL; ++ pgoff_t index = pos >> PAGE_CACHE_SHIFT; ++ ++ int ret = 0; ++ int space_held = 0; ++ ++ /* Get a page */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) ++ pg = grab_cache_page_write_begin(mapping, index, flags); ++#else ++ pg = __grab_cache_page(mapping, index); ++#endif ++ ++ *pagep = pg; ++ if (!pg) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ yaffs_trace(YAFFS_TRACE_OS, ++ "start yaffs_write_begin index %d(%x) uptodate %d", ++ (int)index, (int)index, Page_Uptodate(pg) ? 1 : 0); ++ ++ /* Get fs space */ ++ space_held = yaffs_hold_space(filp); ++ ++ if (!space_held) { ++ ret = -ENOSPC; ++ goto out; ++ } ++ ++ /* Update page if required */ ++ ++ if (!Page_Uptodate(pg)) ++ ret = yaffs_readpage_nolock(filp, pg); ++ ++ if (ret) ++ goto out; ++ ++ /* Happy path return */ ++ yaffs_trace(YAFFS_TRACE_OS, "end yaffs_write_begin - ok"); ++ ++ return 0; ++ ++out: ++ yaffs_trace(YAFFS_TRACE_OS, ++ "end yaffs_write_begin fail returning %d", ret); ++ if (space_held) ++ yaffs_release_space(filp); ++ if (pg) { ++ unlock_page(pg); ++ page_cache_release(pg); ++ } ++ return ret; ++} ++ ++#else ++ ++static int yaffs_prepare_write(struct file *f, struct page *pg, ++ unsigned offset, unsigned to) ++{ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_prepair_write"); ++ ++ if (!Page_Uptodate(pg)) ++ return yaffs_readpage_nolock(f, pg); ++ return 0; ++} ++#endif ++ ++ ++static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, ++ loff_t * pos) ++{ ++ struct yaffs_obj *obj; ++ int n_written; ++ loff_t ipos; ++ struct inode *inode; ++ struct yaffs_dev *dev; ++ ++ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f)); ++ ++ if (!obj) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_file_write: hey obj is null!"); ++ return -EINVAL; ++ } ++ ++ dev = obj->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ inode = Y_GET_DENTRY(f)->d_inode; ++ ++ if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND) ++ ipos = inode->i_size; ++ else ++ ipos = *pos; ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_file_write about to write writing %u(%x) bytes to object %d at %lld", ++ (unsigned)n, (unsigned)n, obj->obj_id, ipos); ++ ++ n_written = yaffs_wr_file(obj, buf, ipos, n, 0); ++ ++ yaffs_set_super_dirty(dev); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_file_write: %d(%x) bytes written", ++ (unsigned)n, (unsigned)n); ++ ++ if (n_written > 0) { ++ ipos += n_written; ++ *pos = ipos; ++ if (ipos > inode->i_size) { ++ inode->i_size = ipos; ++ inode->i_blocks = (ipos + 511) >> 9; ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_file_write size updated to %lld bytes, %d blocks", ++ ipos, (int)(inode->i_blocks)); ++ } ++ ++ } ++ yaffs_gross_unlock(dev); ++ return (n_written == 0) && (n > 0) ? -ENOSPC : n_written; ++} ++ ++ ++#if (YAFFS_USE_WRITE_BEGIN_END > 0) ++static int yaffs_write_end(struct file *filp, struct address_space *mapping, ++ loff_t pos, unsigned len, unsigned copied, ++ struct page *pg, void *fsdadata) ++{ ++ int ret = 0; ++ void *addr, *kva; ++ uint32_t offset_into_page = pos & (PAGE_CACHE_SIZE - 1); ++ ++ kva = kmap(pg); ++ addr = kva + offset_into_page; ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_write_end addr %p pos %lld n_bytes %d", ++ addr, pos, copied); ++ ++ ret = yaffs_file_write(filp, addr, copied, &pos); ++ ++ if (ret != copied) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_write_end not same size ret %d copied %d", ++ ret, copied); ++ SetPageError(pg); ++ } ++ ++ kunmap(pg); ++ ++ yaffs_release_space(filp); ++ unlock_page(pg); ++ page_cache_release(pg); ++ return ret; ++} ++#else ++ ++static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, ++ unsigned to) ++{ ++ void *addr, *kva; ++ ++ loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset; ++ int n_bytes = to - offset; ++ int n_written; ++ ++ kva = kmap(pg); ++ addr = kva + offset; ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_commit_write addr %p pos %lld n_bytes %d", ++ addr, pos, n_bytes); ++ ++ n_written = yaffs_file_write(f, addr, n_bytes, &pos); ++ ++ if (n_written != n_bytes) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_commit_write not same size n_written %d n_bytes %d", ++ n_written, n_bytes); ++ SetPageError(pg); ++ } ++ kunmap(pg); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_commit_write returning %d", ++ n_written == n_bytes ? 0 : n_written); ++ ++ return n_written == n_bytes ? 0 : n_written; ++} ++#endif ++ ++static struct address_space_operations yaffs_file_address_operations = { ++ .readpage = yaffs_readpage, ++ .writepage = yaffs_writepage, ++#if (YAFFS_USE_WRITE_BEGIN_END > 0) ++ .write_begin = yaffs_write_begin, ++ .write_end = yaffs_write_end, ++#else ++ .prepare_write = yaffs_prepare_write, ++ .commit_write = yaffs_commit_write, ++#endif ++}; ++ ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) ++static int yaffs_file_flush(struct file *file, fl_owner_t id) ++#else ++static int yaffs_file_flush(struct file *file) ++#endif ++{ ++ struct yaffs_obj *obj = yaffs_dentry_to_obj(Y_GET_DENTRY(file)); ++ ++ struct yaffs_dev *dev = obj->my_dev; ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_file_flush object %d (%s)", ++ obj->obj_id, ++ obj->dirty ? "dirty" : "clean"); ++ ++ yaffs_gross_lock(dev); ++ ++ yaffs_flush_file(obj, 1, 0, 0); ++ ++ yaffs_gross_unlock(dev); ++ ++ return 0; ++} ++ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) ++static int yaffs_sync_object(struct file *file, loff_t start, loff_t end, int datasync) ++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34)) ++static int yaffs_sync_object(struct file *file, int datasync) ++#else ++static int yaffs_sync_object(struct file *file, struct dentry *dentry, ++ int datasync) ++#endif ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev; ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34)) ++ struct dentry *dentry = file->f_path.dentry; ++#endif ++ ++ obj = yaffs_dentry_to_obj(dentry); ++ ++ dev = obj->my_dev; ++ ++ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC, ++ "yaffs_sync_object"); ++ yaffs_gross_lock(dev); ++ yaffs_flush_file(obj, 1, datasync, 0); ++ yaffs_gross_unlock(dev); ++ return 0; ++} ++ ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)) ++static const struct file_operations yaffs_file_operations = { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) ++ .read = new_sync_read, ++ .write = new_sync_write, ++#endif ++ .read_iter = generic_file_read_iter, ++ .write_iter = generic_file_write_iter, ++#else ++ .read = do_sync_read, ++ .write = do_sync_write, ++ .aio_read = generic_file_aio_read, ++ .aio_write = generic_file_aio_write, ++#endif ++ .mmap = generic_file_mmap, ++ .flush = yaffs_file_flush, ++ .fsync = yaffs_sync_object, ++ .splice_read = generic_file_splice_read, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++ .splice_write = iter_file_splice_write, ++#else ++ .splice_write = generic_file_splice_write, ++#endif ++ .llseek = generic_file_llseek, ++}; ++ ++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18)) ++ ++static const struct file_operations yaffs_file_operations = { ++ .read = do_sync_read, ++ .write = do_sync_write, ++ .aio_read = generic_file_aio_read, ++ .aio_write = generic_file_aio_write, ++ .mmap = generic_file_mmap, ++ .flush = yaffs_file_flush, ++ .fsync = yaffs_sync_object, ++ .sendfile = generic_file_sendfile, ++}; ++ ++#else ++ ++static const struct file_operations yaffs_file_operations = { ++ .read = generic_file_read, ++ .write = generic_file_write, ++ .mmap = generic_file_mmap, ++ .flush = yaffs_file_flush, ++ .fsync = yaffs_sync_object, ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++ .sendfile = generic_file_sendfile, ++#endif ++}; ++#endif ++ ++ ++ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)) ++static void zero_user_segment(struct page *page, unsigned start, unsigned end) ++{ ++ void *kaddr = kmap_atomic(page, KM_USER0); ++ memset(kaddr + start, 0, end - start); ++ kunmap_atomic(kaddr, KM_USER0); ++ flush_dcache_page(page); ++} ++#endif ++ ++ ++static int yaffs_vfs_setsize(struct inode *inode, loff_t newsize) ++{ ++#ifdef YAFFS_USE_TRUNCATE_SETSIZE ++ truncate_setsize(inode, newsize); ++ return 0; ++#else ++ truncate_inode_pages(&inode->i_data, newsize); ++ return 0; ++#endif ++ ++} ++ ++ ++static int yaffs_vfs_setattr(struct inode *inode, struct iattr *attr) ++{ ++#ifdef YAFFS_USE_SETATTR_COPY ++ setattr_copy(inode, attr); ++ return 0; ++#else ++ return inode_setattr(inode, attr); ++#endif ++ ++} ++ ++static int yaffs_setattr(struct dentry *dentry, struct iattr *attr) ++{ ++ struct inode *inode = dentry->d_inode; ++ int error = 0; ++ struct yaffs_dev *dev; ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_setattr of object %d", ++ yaffs_inode_to_obj(inode)->obj_id); ++#if 0 ++ /* Fail if a requested resize >= 2GB */ ++ if (attr->ia_valid & ATTR_SIZE && (attr->ia_size >> 31)) ++ error = -EINVAL; ++#endif ++ ++ if (error == 0) ++ error = setattr_prepare(dentry, attr); ++ if (error == 0) { ++ int result; ++ if (!error) { ++ error = yaffs_vfs_setattr(inode, attr); ++ yaffs_trace(YAFFS_TRACE_OS, "inode_setattr called"); ++ if (attr->ia_valid & ATTR_SIZE) { ++ yaffs_vfs_setsize(inode, attr->ia_size); ++ inode->i_blocks = (inode->i_size + 511) >> 9; ++ } ++ } ++ dev = yaffs_inode_to_obj(inode)->my_dev; ++ if (attr->ia_valid & ATTR_SIZE) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "resize to %d(%x)", ++ (int)(attr->ia_size), ++ (int)(attr->ia_size)); ++ } ++ yaffs_gross_lock(dev); ++ result = yaffs_set_attribs(yaffs_inode_to_obj(inode), attr); ++ if (result == YAFFS_OK) { ++ error = 0; ++ } else { ++ error = -EPERM; ++ } ++ yaffs_gross_unlock(dev); ++ ++ } ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_setattr done returning %d", error); ++ ++ return error; ++} ++ ++#ifdef YAFFS_USE_XATTR ++#if (YAFFS_NEW_XATTR > 0) ++static int yaffs_setxattr(struct dentry *dentry, struct inode *inode, ++ const char *name, const void *value, size_t size, int flags) ++{ ++#else ++static int yaffs_setxattr(struct dentry *dentry, const char *name, ++ const void *value, size_t size, int flags) ++{ ++ struct inode *inode = dentry->d_inode; ++#endif ++ int error = 0; ++ struct yaffs_dev *dev; ++ struct yaffs_obj *obj = yaffs_inode_to_obj(inode); ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_setxattr of object %d", obj->obj_id); ++ ++ if (error == 0) { ++ int result; ++ dev = obj->my_dev; ++ yaffs_gross_lock(dev); ++ result = yaffs_set_xattrib(obj, name, value, size, flags); ++ if (result == YAFFS_OK) ++ error = 0; ++ else if (result < 0) ++ error = result; ++ yaffs_gross_unlock(dev); ++ ++ } ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_setxattr done returning %d", error); ++ ++ return error; ++} ++ ++#ifdef YAFFS_NEW_XATTR ++static ssize_t yaffs_getxattr(struct dentry * dentry, struct inode *inode, ++ const char *name, void *buff, size_t size) ++{ ++#else ++static ssize_t yaffs_getxattr(struct dentry * dentry, const char *name, ++ void *buff, size_t size) ++{ ++ struct inode *inode = dentry->d_inode; ++#endif ++ int error = 0; ++ struct yaffs_dev *dev; ++ struct yaffs_obj *obj = yaffs_inode_to_obj(inode); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_getxattr \"%s\" from object %d", ++ name, obj->obj_id); ++ ++ if (error == 0) { ++ dev = obj->my_dev; ++ yaffs_gross_lock(dev); ++ error = yaffs_get_xattrib(obj, name, buff, size); ++ yaffs_gross_unlock(dev); ++ ++ } ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_getxattr done returning %d", error); ++ ++ return error; ++} ++ ++static int yaffs_removexattr(struct dentry *dentry, const char *name) ++{ ++ struct inode *inode = dentry->d_inode; ++ int error = 0; ++ struct yaffs_dev *dev; ++ struct yaffs_obj *obj = yaffs_inode_to_obj(inode); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_removexattr of object %d", obj->obj_id); ++ ++ if (error == 0) { ++ int result; ++ dev = obj->my_dev; ++ yaffs_gross_lock(dev); ++ result = yaffs_remove_xattrib(obj, name); ++ if (result == YAFFS_OK) ++ error = 0; ++ else if (result < 0) ++ error = result; ++ yaffs_gross_unlock(dev); ++ ++ } ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_removexattr done returning %d", error); ++ ++ return error; ++} ++#endif ++ ++static ssize_t yaffs_listxattr(struct dentry * dentry, char *buff, size_t size) ++{ ++ struct inode *inode = dentry->d_inode; ++ int error = 0; ++ struct yaffs_dev *dev; ++ struct yaffs_obj *obj = yaffs_inode_to_obj(inode); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_listxattr of object %d", obj->obj_id); ++ ++ if (error == 0) { ++ dev = obj->my_dev; ++ yaffs_gross_lock(dev); ++ error = yaffs_list_xattrib(obj, buff, size); ++ yaffs_gross_unlock(dev); ++ ++ } ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_listxattr done returning %d", error); ++ ++ return error; ++} ++ ++ ++static const struct inode_operations yaffs_file_inode_operations = { ++ .setattr = yaffs_setattr, ++#ifdef YAFFS_USE_XATTR ++ .setxattr = yaffs_setxattr, ++ .getxattr = yaffs_getxattr, ++ .removexattr = yaffs_removexattr, ++#endif ++ .listxattr = yaffs_listxattr, ++}; ++ ++ ++static int yaffs_readlink(struct dentry *dentry, char __user * buffer, ++ int buflen) ++{ ++ unsigned char *alias; ++ int ret; ++ ++ struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry)); ++ ++ yaffs_gross_unlock(dev); ++ ++ if (!alias) ++ return -ENOMEM; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0) ++ ret = vfs_readlink(dentry, buffer, buflen, alias); ++#else ++ ret = readlink_copy(buffer, buflen, alias); ++#endif ++ kfree(alias); ++ return ret; ++} ++ ++#if (YAFFS_NEW_GET_LINK == 0) ++#if (YAFFS_NEW_FOLLOW_LINK == 1) ++static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd) ++{ ++ void *ret; ++#else ++static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd) ++{ ++ int ret ++#endif ++ unsigned char *alias; ++ int ret_int = 0; ++ struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry)); ++ yaffs_gross_unlock(dev); ++ ++ if (!alias) { ++ ret_int = -ENOMEM; ++ goto out; ++ } ++#if (YAFFS_NEW_FOLLOW_LINK == 1) ++ nd_set_link(nd, alias); ++ ret = alias; ++out: ++ if (ret_int) ++ ret = ERR_PTR(ret_int); ++ return ret; ++#else ++ ret = vfs_follow_link(nd, alias); ++ kfree(alias); ++out: ++ if (ret_int) ++ ret = ret_int; ++ return ret; ++#endif ++} ++#else ++static const char *yaffs_get_link(struct dentry *dentry, struct inode *inode, struct delayed_call *done) ++{ ++ unsigned char *alias; ++ struct yaffs_dev *dev; ++ ++ if (!dentry) ++ return ERR_PTR(-ECHILD); ++ ++ dev = yaffs_dentry_to_obj(dentry)->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry)); ++ yaffs_gross_unlock(dev); ++ ++ if (!alias) ++ return ERR_PTR(-ENOMEM); ++ set_delayed_call(done, kfree_link, alias); ++ return alias; ++} ++#endif ++ ++#ifdef YAFFS_HAS_PUT_INODE ++ ++/* For now put inode is just for debugging ++ * Put inode is called when the inode **structure** is put. ++ */ ++static void yaffs_put_inode(struct inode *inode) ++{ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_put_inode: ino %d, count %d"), ++ (int)inode->i_ino, atomic_read(&inode->i_count); ++ ++} ++#endif ++ ++#if (YAFFS_NEW_FOLLOW_LINK == 1) ++void yaffs_put_link(struct dentry *dentry, struct nameidata *nd, void *alias) ++{ ++ kfree(alias); ++} ++#endif ++ ++static const struct inode_operations yaffs_symlink_inode_operations = { ++ .readlink = yaffs_readlink, ++#if (YAFFS_NEW_GET_LINK == 1) ++ .get_link = yaffs_get_link, ++#else ++ .follow_link = yaffs_follow_link, ++#endif ++#if (YAFFS_NEW_FOLLOW_LINK == 1) ++ .put_link = yaffs_put_link, ++#endif ++ .setattr = yaffs_setattr, ++#ifdef YAFFS_USE_XATTR ++ .setxattr = yaffs_setxattr, ++ .getxattr = yaffs_getxattr, ++ .removexattr = yaffs_removexattr, ++#endif ++ .listxattr = yaffs_listxattr, ++}; ++ ++#ifdef YAFFS_USE_OWN_IGET ++ ++static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino) ++{ ++ struct inode *inode; ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev = yaffs_super_to_dev(sb); ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_iget for %lu", ino); ++ ++ inode = iget_locked(sb, ino); ++ if (!inode) ++ return ERR_PTR(-ENOMEM); ++ if (!(inode->i_state & I_NEW)) ++ return inode; ++ ++ /* NB This is called as a side effect of other functions, but ++ * we had to release the lock to prevent deadlocks, so ++ * need to lock again. ++ */ ++ ++ yaffs_gross_lock(dev); ++ ++ obj = yaffs_find_by_number(dev, inode->i_ino); ++ ++ yaffs_fill_inode_from_obj(inode, obj); ++ ++ yaffs_gross_unlock(dev); ++ ++ unlock_new_inode(inode); ++ return inode; ++} ++ ++#else ++ ++static void yaffs_read_inode(struct inode *inode) ++{ ++ /* NB This is called as a side effect of other functions, but ++ * we had to release the lock to prevent deadlocks, so ++ * need to lock again. ++ */ ++ ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev = yaffs_super_to_dev(inode->i_sb); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_read_inode for %d", (int)inode->i_ino); ++ ++ if (current != yaffs_dev_to_lc(dev)->readdir_process) ++ yaffs_gross_lock(dev); ++ ++ obj = yaffs_find_by_number(dev, inode->i_ino); ++ ++ yaffs_fill_inode_from_obj(inode, obj); ++ ++ if (current != yaffs_dev_to_lc(dev)->readdir_process) ++ yaffs_gross_unlock(dev); ++} ++ ++#endif ++ ++ ++ ++struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev, ++ struct yaffs_obj *obj) ++{ ++ struct inode *inode; ++ ++ if (!sb) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_get_inode for NULL super_block!!"); ++ return NULL; ++ ++ } ++ ++ if (!obj) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_get_inode for NULL object!!"); ++ return NULL; ++ ++ } ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_get_inode for object %d", obj->obj_id); ++ ++ inode = Y_IGET(sb, obj->obj_id); ++ if (IS_ERR(inode)) ++ return NULL; ++ ++ /* NB Side effect: iget calls back to yaffs_read_inode(). */ ++ /* iget also increments the inode's i_count */ ++ /* NB You can't be holding gross_lock or deadlock will happen! */ ++ ++ return inode; ++} ++ ++ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) ++#define YCRED(x) x ++#else ++#define YCRED(x) (x->cred) ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) ++#define YPROC_uid(p) (YCRED(p)->fsuid) ++#define YPROC_gid(p) (YCRED(p)->fsgid) ++#define EXTRACT_gid(x) x ++#define EXTRACT_uid(x) x ++#define MAKE_gid(x) x ++#define MAKE_uid(x) x ++#else ++#define YPROC_uid(p) from_kuid(&init_user_ns, YCRED(p)->fsuid) ++#define YPROC_gid(p) from_kgid(&init_user_ns, YCRED(p)->fsgid) ++#define EXTRACT_gid(x) from_kgid(&init_user_ns, x) ++#define EXTRACT_uid(x) from_kuid(&init_user_ns, x) ++#define MAKE_gid(x) make_kgid(&init_user_ns, x) ++#define MAKE_uid(x) make_kuid(&init_user_ns, x) ++#endif ++ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) ++static int yaffs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, ++ dev_t rdev) ++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, ++ dev_t rdev) ++#else ++static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, ++ int rdev) ++#endif ++{ ++ struct inode *inode; ++ ++ struct yaffs_obj *obj = NULL; ++ struct yaffs_dev *dev; ++ ++ struct yaffs_obj *parent = yaffs_inode_to_obj(dir); ++ ++ int error = -ENOSPC; ++ uid_t uid = YPROC_uid(current); ++ gid_t gid = ++ (dir->i_mode & S_ISGID) ? EXTRACT_gid(dir->i_gid) : YPROC_gid(current); ++ ++ if ((dir->i_mode & S_ISGID) && S_ISDIR(mode)) ++ mode |= S_ISGID; ++ ++ if (parent) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_mknod: parent object %d type %d", ++ parent->obj_id, parent->variant_type); ++ } else { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_mknod: could not get parent object"); ++ return -EPERM; ++ } ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_mknod: making oject for %s, mode %x dev %x", ++ dentry->d_name.name, mode, rdev); ++ ++ dev = parent->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ switch (mode & S_IFMT) { ++ default: ++ /* Special (socket, fifo, device...) */ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making special"); ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++ obj = ++ yaffs_create_special(parent, dentry->d_name.name, mode, uid, ++ gid, old_encode_dev(rdev)); ++#else ++ obj = ++ yaffs_create_special(parent, dentry->d_name.name, mode, uid, ++ gid, rdev); ++#endif ++ break; ++ case S_IFREG: /* file */ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making file"); ++ obj = yaffs_create_file(parent, dentry->d_name.name, mode, uid, ++ gid); ++ break; ++ case S_IFDIR: /* directory */ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making directory"); ++ obj = yaffs_create_dir(parent, dentry->d_name.name, mode, ++ uid, gid); ++ break; ++ case S_IFLNK: /* symlink */ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making symlink"); ++ obj = NULL; /* Do we ever get here? */ ++ break; ++ } ++ ++ /* Can not call yaffs_get_inode() with gross lock held */ ++ yaffs_gross_unlock(dev); ++ ++ if (obj) { ++ inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj); ++ d_instantiate(dentry, inode); ++ update_dir_time(dir); ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_mknod created object %d count = %d", ++ obj->obj_id, atomic_read(&inode->i_count)); ++ error = 0; ++ yaffs_fill_inode_from_obj(dir, parent); ++ } else { ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod failed making object"); ++ error = -ENOMEM; ++ } ++ ++ return error; ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) ++static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ++#else ++static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode) ++#endif ++{ ++ int ret_val; ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mkdir"); ++ ret_val = yaffs_mknod(dir, dentry, mode | S_IFDIR, 0); ++ return ret_val; ++} ++ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) ++static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode, ++ bool dummy) ++#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) ++static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode, ++ struct nameidata *n) ++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode, ++ struct nameidata *n) ++#else ++static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode) ++#endif ++{ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_create"); ++ return yaffs_mknod(dir, dentry, mode | S_IFREG, 0); ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) ++static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry, ++ unsigned int dummy) ++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry, ++ struct nameidata *n) ++#else ++static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry) ++#endif ++{ ++ struct yaffs_obj *obj; ++ struct inode *inode = NULL; /* NCB 2.5/2.6 needs NULL here */ ++ ++ struct yaffs_dev *dev = yaffs_inode_to_obj(dir)->my_dev; ++ ++ if (current != yaffs_dev_to_lc(dev)->readdir_process) ++ yaffs_gross_lock(dev); ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_lookup for %d:%s", ++ yaffs_inode_to_obj(dir)->obj_id, dentry->d_name.name); ++ ++ obj = yaffs_find_by_name(yaffs_inode_to_obj(dir), dentry->d_name.name); ++ ++ obj = yaffs_get_equivalent_obj(obj); /* in case it was a hardlink */ ++ ++ /* Can't hold gross lock when calling yaffs_get_inode() */ ++ if (current != yaffs_dev_to_lc(dev)->readdir_process) ++ yaffs_gross_unlock(dev); ++ ++ if (obj) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_lookup found %d", obj->obj_id); ++ ++ inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj); ++ } else { ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_lookup not found"); ++ ++ } ++ ++/* added NCB for 2.5/6 compatability - forces add even if inode is ++ * NULL which creates dentry hash */ ++ d_add(dentry, inode); ++ ++ return NULL; ++} ++ ++/* ++ * Create a link... ++ */ ++static int yaffs_link(struct dentry *old_dentry, struct inode *dir, ++ struct dentry *dentry) ++{ ++ struct inode *inode = old_dentry->d_inode; ++ struct yaffs_obj *obj = NULL; ++ struct yaffs_obj *link = NULL; ++ struct yaffs_dev *dev; ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_link"); ++ ++ obj = yaffs_inode_to_obj(inode); ++ dev = obj->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ if (!S_ISDIR(inode->i_mode)) /* Don't link directories */ ++ link = ++ yaffs_link_obj(yaffs_inode_to_obj(dir), dentry->d_name.name, ++ obj); ++ ++ if (link) { ++ set_nlink(old_dentry->d_inode, yaffs_get_obj_link_count(obj)); ++ d_instantiate(dentry, old_dentry->d_inode); ++ atomic_inc(&old_dentry->d_inode->i_count); ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_link link count %d i_count %d", ++ old_dentry->d_inode->i_nlink, ++ atomic_read(&old_dentry->d_inode->i_count)); ++ } ++ ++ yaffs_gross_unlock(dev); ++ ++ if (link) { ++ update_dir_time(dir); ++ return 0; ++ } ++ ++ return -EPERM; ++} ++ ++static int yaffs_symlink(struct inode *dir, struct dentry *dentry, ++ const char *symname) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev; ++ uid_t uid = YPROC_uid(current); ++ gid_t gid = ++ (dir->i_mode & S_ISGID) ? EXTRACT_gid(dir->i_gid) : YPROC_gid(current); ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink"); ++ ++ if (strnlen(dentry->d_name.name, YAFFS_MAX_NAME_LENGTH + 1) > ++ YAFFS_MAX_NAME_LENGTH) ++ return -ENAMETOOLONG; ++ ++ if (strnlen(symname, YAFFS_MAX_ALIAS_LENGTH + 1) > ++ YAFFS_MAX_ALIAS_LENGTH) ++ return -ENAMETOOLONG; ++ ++ dev = yaffs_inode_to_obj(dir)->my_dev; ++ yaffs_gross_lock(dev); ++ obj = yaffs_create_symlink(yaffs_inode_to_obj(dir), dentry->d_name.name, ++ S_IFLNK | S_IRWXUGO, uid, gid, symname); ++ yaffs_gross_unlock(dev); ++ ++ if (obj) { ++ struct inode *inode; ++ ++ inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj); ++ d_instantiate(dentry, inode); ++ update_dir_time(dir); ++ yaffs_trace(YAFFS_TRACE_OS, "symlink created OK"); ++ return 0; ++ } else { ++ yaffs_trace(YAFFS_TRACE_OS, "symlink not created"); ++ } ++ ++ return -ENOMEM; ++} ++ ++/* ++ * The VFS layer already does all the dentry stuff for rename. ++ * ++ * NB: POSIX says you can rename an object over an old object of the same name ++ */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) ++static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry, ++ struct inode *new_dir, struct dentry *new_dentry, unsigned int unused) ++#else ++static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry, ++ struct inode *new_dir, struct dentry *new_dentry) ++#endif ++{ ++ struct yaffs_dev *dev; ++ int ret_val = YAFFS_FAIL; ++ struct yaffs_obj *target; ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_rename"); ++ dev = yaffs_inode_to_obj(old_dir)->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ /* Check if the target is an existing directory that is not empty. */ ++ target = yaffs_find_by_name(yaffs_inode_to_obj(new_dir), ++ new_dentry->d_name.name); ++ ++ if (target && target->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY && ++ !list_empty(&target->variant.dir_variant.children)) { ++ ++ yaffs_trace(YAFFS_TRACE_OS, "target is non-empty dir"); ++ ++ ret_val = YAFFS_FAIL; ++ } else { ++ /* Now does unlinking internally using shadowing mechanism */ ++ yaffs_trace(YAFFS_TRACE_OS, "calling yaffs_rename_obj"); ++ ++ ret_val = yaffs_rename_obj(yaffs_inode_to_obj(old_dir), ++ old_dentry->d_name.name, ++ yaffs_inode_to_obj(new_dir), ++ new_dentry->d_name.name); ++ } ++ yaffs_gross_unlock(dev); ++ ++ if (ret_val == YAFFS_OK) { ++ if (target) ++ inode_dec_link_count(new_dentry->d_inode); ++ ++ update_dir_time(old_dir); ++ if (old_dir != new_dir) ++ update_dir_time(new_dir); ++ return 0; ++ } else { ++ return -ENOTEMPTY; ++ } ++} ++ ++ ++ ++ ++static int yaffs_unlink(struct inode *dir, struct dentry *dentry) ++{ ++ int ret_val; ++ ++ struct yaffs_dev *dev; ++ struct yaffs_obj *obj; ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_unlink %d:%s", ++ (int)(dir->i_ino), dentry->d_name.name); ++ obj = yaffs_inode_to_obj(dir); ++ dev = obj->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ ret_val = yaffs_unlinker(obj, dentry->d_name.name); ++ ++ if (ret_val == YAFFS_OK) { ++ inode_dec_link_count(dentry->d_inode); ++ dir->i_version++; ++ yaffs_gross_unlock(dev); ++ update_dir_time(dir); ++ return 0; ++ } ++ yaffs_gross_unlock(dev); ++ return -ENOTEMPTY; ++} ++ ++ ++ ++static const struct inode_operations yaffs_dir_inode_operations = { ++ .create = yaffs_create, ++ .lookup = yaffs_lookup, ++ .link = yaffs_link, ++ .unlink = yaffs_unlink, ++ .symlink = yaffs_symlink, ++ .mkdir = yaffs_mkdir, ++ .rmdir = yaffs_unlink, ++ .mknod = yaffs_mknod, ++ .rename = yaffs_rename, ++ .setattr = yaffs_setattr, ++ .listxattr = yaffs_listxattr, ++#ifdef YAFFS_USE_XATTR ++ .setxattr = yaffs_setxattr, ++ .getxattr = yaffs_getxattr, ++ .removexattr = yaffs_removexattr, ++#endif ++}; ++ ++/*-----------------------------------------------------------------*/ ++/* Directory search context allows us to unlock access to yaffs during ++ * filldir without causing problems with the directory being modified. ++ * This is similar to the tried and tested mechanism used in yaffs direct. ++ * ++ * A search context iterates along a doubly linked list of siblings in the ++ * directory. If the iterating object is deleted then this would corrupt ++ * the list iteration, likely causing a crash. The search context avoids ++ * this by using the remove_obj_fn to move the search context to the ++ * next object before the object is deleted. ++ * ++ * Many readdirs (and thus seach conexts) may be alive simulateously so ++ * each struct yaffs_dev has a list of these. ++ * ++ * A seach context lives for the duration of a readdir. ++ * ++ * All these functions must be called while yaffs is locked. ++ */ ++ ++struct yaffs_search_context { ++ struct yaffs_dev *dev; ++ struct yaffs_obj *dir_obj; ++ struct yaffs_obj *next_return; ++ struct list_head others; ++}; ++ ++/* ++ * yaffs_new_search() creates a new search context, initialises it and ++ * adds it to the device's search context list. ++ * ++ * Called at start of readdir. ++ */ ++static struct yaffs_search_context *yaffs_new_search(struct yaffs_obj *dir) ++{ ++ struct yaffs_dev *dev = dir->my_dev; ++ struct yaffs_search_context *sc = ++ kmalloc(sizeof(struct yaffs_search_context), GFP_NOFS); ++ if (sc) { ++ sc->dir_obj = dir; ++ sc->dev = dev; ++ if (list_empty(&sc->dir_obj->variant.dir_variant.children)) ++ sc->next_return = NULL; ++ else ++ sc->next_return = ++ list_entry(dir->variant.dir_variant.children.next, ++ struct yaffs_obj, siblings); ++ INIT_LIST_HEAD(&sc->others); ++ list_add(&sc->others, &(yaffs_dev_to_lc(dev)->search_contexts)); ++ } ++ return sc; ++} ++ ++/* ++ * yaffs_search_end() disposes of a search context and cleans up. ++ */ ++static void yaffs_search_end(struct yaffs_search_context *sc) ++{ ++ if (sc) { ++ list_del(&sc->others); ++ kfree(sc); ++ } ++} ++ ++/* ++ * yaffs_search_advance() moves a search context to the next object. ++ * Called when the search iterates or when an object removal causes ++ * the search context to be moved to the next object. ++ */ ++static void yaffs_search_advance(struct yaffs_search_context *sc) ++{ ++ if (!sc) ++ return; ++ ++ if (sc->next_return == NULL || ++ list_empty(&sc->dir_obj->variant.dir_variant.children)) ++ sc->next_return = NULL; ++ else { ++ struct list_head *next = sc->next_return->siblings.next; ++ ++ if (next == &sc->dir_obj->variant.dir_variant.children) ++ sc->next_return = NULL; /* end of list */ ++ else ++ sc->next_return = ++ list_entry(next, struct yaffs_obj, siblings); ++ } ++} ++ ++/* ++ * yaffs_remove_obj_callback() is called when an object is unlinked. ++ * We check open search contexts and advance any which are currently ++ * on the object being iterated. ++ */ ++static void yaffs_remove_obj_callback(struct yaffs_obj *obj) ++{ ++ ++ struct list_head *i; ++ struct yaffs_search_context *sc; ++ struct list_head *search_contexts = ++ &(yaffs_dev_to_lc(obj->my_dev)->search_contexts); ++ ++ /* Iterate through the directory search contexts. ++ * If any are currently on the object being removed, then advance ++ * the search context to the next object to prevent a hanging pointer. ++ */ ++ list_for_each(i, search_contexts) { ++ sc = list_entry(i, struct yaffs_search_context, others); ++ if (sc->next_return == obj) ++ yaffs_search_advance(sc); ++ } ++ ++} ++ ++ ++/*-----------------------------------------------------------------*/ ++ ++#ifdef YAFFS_USE_DIR_ITERATE ++static int yaffs_iterate(struct file *f, struct dir_context *dc) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev; ++ struct yaffs_search_context *sc; ++ unsigned long curoffs; ++ struct yaffs_obj *l; ++ int ret_val = 0; ++ ++ char name[YAFFS_MAX_NAME_LENGTH + 1]; ++ ++ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f)); ++ dev = obj->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ yaffs_dev_to_lc(dev)->readdir_process = current; ++ ++ sc = yaffs_new_search(obj); ++ if (!sc) { ++ ret_val = -ENOMEM; ++ goto out; ++ } ++ ++ if (!dir_emit_dots(f, dc)) ++ return 0; ++ ++ curoffs = 1; ++ ++ while (sc->next_return) { ++ curoffs++; ++ l = sc->next_return; ++ if (curoffs >= dc->pos) { ++ int this_inode = yaffs_get_obj_inode(l); ++ int this_type = yaffs_get_obj_type(l); ++ ++ yaffs_get_obj_name(l, name, YAFFS_MAX_NAME_LENGTH + 1); ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_readdir: %s inode %d", ++ name, yaffs_get_obj_inode(l)); ++ ++ yaffs_gross_unlock(dev); ++ ++ if (!dir_emit(dc, ++ name, ++ strlen(name), ++ this_inode, ++ this_type)) { ++ yaffs_gross_lock(dev); ++ goto out; ++ } ++ ++ yaffs_gross_lock(dev); ++ ++ dc->pos++; ++ f->f_pos++; ++ } ++ yaffs_search_advance(sc); ++ } ++ ++out: ++ yaffs_search_end(sc); ++ yaffs_dev_to_lc(dev)->readdir_process = NULL; ++ yaffs_gross_unlock(dev); ++ ++ return ret_val; ++} ++ ++#else ++ ++static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev; ++ struct yaffs_search_context *sc; ++ struct inode *inode = Y_GET_DENTRY(f)->d_inode; ++ unsigned long offset, curoffs; ++ struct yaffs_obj *l; ++ int ret_val = 0; ++ ++ char name[YAFFS_MAX_NAME_LENGTH + 1]; ++ ++ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f)); ++ dev = obj->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ yaffs_dev_to_lc(dev)->readdir_process = current; ++ ++ offset = f->f_pos; ++ ++ sc = yaffs_new_search(obj); ++ if (!sc) { ++ ret_val = -ENOMEM; ++ goto out; ++ } ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_readdir: starting at %d", (int)offset); ++ ++ if (offset == 0) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_readdir: entry . ino %d", ++ (int)inode->i_ino); ++ yaffs_gross_unlock(dev); ++ if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) < 0) { ++ yaffs_gross_lock(dev); ++ goto out; ++ } ++ yaffs_gross_lock(dev); ++ offset++; ++ f->f_pos++; ++ } ++ if (offset == 1) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_readdir: entry .. ino %d", ++ (int)f->f_dentry->d_parent->d_inode->i_ino); ++ yaffs_gross_unlock(dev); ++ if (filldir(dirent, "..", 2, offset, ++ f->f_dentry->d_parent->d_inode->i_ino, ++ DT_DIR) < 0) { ++ yaffs_gross_lock(dev); ++ goto out; ++ } ++ yaffs_gross_lock(dev); ++ offset++; ++ f->f_pos++; ++ } ++ ++ curoffs = 1; ++ ++ /* If the directory has changed since the open or last call to ++ readdir, rewind to after the 2 canned entries. */ ++ if (f->f_version != inode->i_version) { ++ offset = 2; ++ f->f_pos = offset; ++ f->f_version = inode->i_version; ++ } ++ ++ while (sc->next_return) { ++ curoffs++; ++ l = sc->next_return; ++ if (curoffs >= offset) { ++ int this_inode = yaffs_get_obj_inode(l); ++ int this_type = yaffs_get_obj_type(l); ++ ++ yaffs_get_obj_name(l, name, YAFFS_MAX_NAME_LENGTH + 1); ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_readdir: %s inode %d", ++ name, yaffs_get_obj_inode(l)); ++ ++ yaffs_gross_unlock(dev); ++ ++ if (filldir(dirent, ++ name, ++ strlen(name), ++ offset, this_inode, this_type) < 0) { ++ yaffs_gross_lock(dev); ++ goto out; ++ } ++ ++ yaffs_gross_lock(dev); ++ ++ offset++; ++ f->f_pos++; ++ } ++ yaffs_search_advance(sc); ++ } ++ ++out: ++ yaffs_search_end(sc); ++ yaffs_dev_to_lc(dev)->readdir_process = NULL; ++ yaffs_gross_unlock(dev); ++ ++ return ret_val; ++} ++ ++#endif ++ ++static const struct file_operations yaffs_dir_operations = { ++ .read = generic_read_dir, ++#ifdef YAFFS_USE_DIR_ITERATE ++ .iterate = yaffs_iterate, ++#else ++ .readdir = yaffs_readdir, ++#endif ++ .fsync = yaffs_sync_object, ++ .llseek = generic_file_llseek, ++}; ++ ++static void yaffs_fill_inode_from_obj(struct inode *inode, ++ struct yaffs_obj *obj) ++{ ++ if (inode && obj) { ++ ++ /* Check mode against the variant type and attempt to repair if broken. */ ++ u32 mode = obj->yst_mode; ++ switch (obj->variant_type) { ++ case YAFFS_OBJECT_TYPE_FILE: ++ if (!S_ISREG(mode)) { ++ obj->yst_mode &= ~S_IFMT; ++ obj->yst_mode |= S_IFREG; ++ } ++ ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ if (!S_ISLNK(mode)) { ++ obj->yst_mode &= ~S_IFMT; ++ obj->yst_mode |= S_IFLNK; ++ } ++ ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ if (!S_ISDIR(mode)) { ++ obj->yst_mode &= ~S_IFMT; ++ obj->yst_mode |= S_IFDIR; ++ } ++ ++ break; ++ case YAFFS_OBJECT_TYPE_UNKNOWN: ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ default: ++ /* TODO? */ ++ break; ++ } ++ ++ inode->i_flags |= S_NOATIME; ++ ++ inode->i_ino = obj->obj_id; ++ inode->i_mode = obj->yst_mode; ++ inode->i_uid = MAKE_uid(obj->yst_uid); ++ inode->i_gid = MAKE_gid(obj->yst_gid); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)) ++ inode->i_blksize = inode->i_sb->s_blocksize; ++#endif ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++ ++ inode->i_rdev = old_decode_dev(obj->yst_rdev); ++ inode->i_atime.tv_sec = (time_t) (obj->yst_atime); ++ inode->i_atime.tv_nsec = 0; ++ inode->i_mtime.tv_sec = (time_t) obj->yst_mtime; ++ inode->i_mtime.tv_nsec = 0; ++ inode->i_ctime.tv_sec = (time_t) obj->yst_ctime; ++ inode->i_ctime.tv_nsec = 0; ++#else ++ inode->i_rdev = obj->yst_rdev; ++ inode->i_atime = obj->yst_atime; ++ inode->i_mtime = obj->yst_mtime; ++ inode->i_ctime = obj->yst_ctime; ++#endif ++ inode->i_size = yaffs_get_obj_length(obj); ++ inode->i_blocks = (inode->i_size + 511) >> 9; ++ ++ set_nlink(inode, yaffs_get_obj_link_count(obj)); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_fill_inode mode %x uid %d gid %d size %lld count %d", ++ inode->i_mode, obj->yst_uid, obj->yst_gid, ++ inode->i_size, atomic_read(&inode->i_count)); ++ ++ switch (obj->yst_mode & S_IFMT) { ++ default: /* fifo, device or socket */ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++ init_special_inode(inode, obj->yst_mode, ++ old_decode_dev(obj->yst_rdev)); ++#else ++ init_special_inode(inode, obj->yst_mode, ++ (dev_t) (obj->yst_rdev)); ++#endif ++ break; ++ case S_IFREG: /* file */ ++ inode->i_op = &yaffs_file_inode_operations; ++ inode->i_fop = &yaffs_file_operations; ++ inode->i_mapping->a_ops = ++ &yaffs_file_address_operations; ++ break; ++ case S_IFDIR: /* directory */ ++ inode->i_op = &yaffs_dir_inode_operations; ++ inode->i_fop = &yaffs_dir_operations; ++ break; ++ case S_IFLNK: /* symlink */ ++ inode->i_op = &yaffs_symlink_inode_operations; ++ break; ++ } ++ ++ yaffs_inode_to_obj_lv(inode) = obj; ++ ++ obj->my_inode = inode; ++ ++ } else { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_fill_inode invalid parameters"); ++ } ++ ++} ++ ++ ++ ++/* ++ * yaffs background thread functions . ++ * yaffs_bg_thread_fn() the thread function ++ * yaffs_bg_start() launches the background thread. ++ * yaffs_bg_stop() cleans up the background thread. ++ * ++ * NB: ++ * The thread should only run after the yaffs is initialised ++ * The thread should be stopped before yaffs is unmounted. ++ * The thread should not do any writing while the fs is in read only. ++ */ ++ ++static unsigned yaffs_bg_gc_urgency(struct yaffs_dev *dev) ++{ ++ unsigned erased_chunks = ++ dev->n_erased_blocks * dev->param.chunks_per_block; ++ struct yaffs_linux_context *context = yaffs_dev_to_lc(dev); ++ unsigned scattered = 0; /* Free chunks not in an erased block */ ++ ++ if (erased_chunks < dev->n_free_chunks) ++ scattered = (dev->n_free_chunks - erased_chunks); ++ ++ if (!context->bg_running) ++ return 0; ++ else if (scattered < (dev->param.chunks_per_block * 2)) ++ return 0; ++ else if (erased_chunks > dev->n_free_chunks / 2) ++ return 0; ++ else if (erased_chunks > dev->n_free_chunks / 4) ++ return 1; ++ else ++ return 2; ++} ++ ++#ifdef YAFFS_COMPILE_BACKGROUND ++ ++void yaffs_background_waker(unsigned long data) ++{ ++ wake_up_process((struct task_struct *)data); ++} ++ ++static int yaffs_bg_thread_fn(void *data) ++{ ++ struct yaffs_dev *dev = (struct yaffs_dev *)data; ++ struct yaffs_linux_context *context = yaffs_dev_to_lc(dev); ++ unsigned long now = jiffies; ++ unsigned long next_dir_update = now; ++ unsigned long next_gc = now; ++ unsigned long expires; ++ unsigned int urgency; ++ ++ int gc_result; ++ struct timer_list timer; ++ ++ yaffs_trace(YAFFS_TRACE_BACKGROUND, ++ "yaffs_background starting for dev %p", (void *)dev); ++ ++#ifdef YAFFS_COMPILE_FREEZER ++ set_freezable(); ++#endif ++ while (context->bg_running) { ++ yaffs_trace(YAFFS_TRACE_BACKGROUND, "yaffs_background"); ++ ++ if (kthread_should_stop()) ++ break; ++ ++#ifdef YAFFS_COMPILE_FREEZER ++ if (try_to_freeze()) ++ continue; ++#endif ++ yaffs_gross_lock(dev); ++ ++ now = jiffies; ++ ++ if (time_after(now, next_dir_update) && yaffs_bg_enable) { ++ yaffs_update_dirty_dirs(dev); ++ next_dir_update = now + HZ; ++ } ++ ++ if (time_after(now, next_gc) && yaffs_bg_enable) { ++ if (!dev->is_checkpointed) { ++ urgency = yaffs_bg_gc_urgency(dev); ++ gc_result = yaffs_bg_gc(dev, urgency); ++ if (urgency > 1) ++ next_gc = now + HZ / 20 + 1; ++ else if (urgency > 0) ++ next_gc = now + HZ / 10 + 1; ++ else ++ next_gc = now + HZ * 2; ++ } else { ++ /* ++ * gc not running so set to next_dir_update ++ * to cut down on wake ups ++ */ ++ next_gc = next_dir_update; ++ } ++ } ++ yaffs_gross_unlock(dev); ++#if 1 ++ expires = next_dir_update; ++ if (time_before(next_gc, expires)) ++ expires = next_gc; ++ if (time_before(expires, now)) ++ expires = now + HZ; ++ ++ Y_INIT_TIMER(&timer); ++ timer.expires = expires + 1; ++ timer.data = (unsigned long)current; ++ timer.function = yaffs_background_waker; ++ ++ set_current_state(TASK_INTERRUPTIBLE); ++ add_timer(&timer); ++ schedule(); ++ del_timer_sync(&timer); ++#else ++ msleep(10); ++#endif ++ } ++ ++ return 0; ++} ++ ++static int yaffs_bg_start(struct yaffs_dev *dev) ++{ ++ int retval = 0; ++ struct yaffs_linux_context *context = yaffs_dev_to_lc(dev); ++ ++ if (dev->read_only) ++ return -1; ++ ++ context->bg_running = 1; ++ ++ context->bg_thread = kthread_run(yaffs_bg_thread_fn, ++ (void *)dev, "yaffs-bg-%d", ++ context->mount_id); ++ ++ if (IS_ERR(context->bg_thread)) { ++ retval = PTR_ERR(context->bg_thread); ++ context->bg_thread = NULL; ++ context->bg_running = 0; ++ } ++ return retval; ++} ++ ++static void yaffs_bg_stop(struct yaffs_dev *dev) ++{ ++ struct yaffs_linux_context *ctxt = yaffs_dev_to_lc(dev); ++ ++ ctxt->bg_running = 0; ++ ++ if (ctxt->bg_thread) { ++ kthread_stop(ctxt->bg_thread); ++ ctxt->bg_thread = NULL; ++ } ++} ++#else ++static int yaffs_bg_thread_fn(void *data) ++{ ++ return 0; ++} ++ ++static int yaffs_bg_start(struct yaffs_dev *dev) ++{ ++ return 0; ++} ++ ++static void yaffs_bg_stop(struct yaffs_dev *dev) ++{ ++} ++#endif ++ ++ ++static void yaffs_flush_inodes(struct super_block *sb) ++{ ++ struct inode *iptr; ++ struct yaffs_obj *obj; ++ ++ list_for_each_entry(iptr, &sb->s_inodes, i_sb_list) { ++ obj = yaffs_inode_to_obj(iptr); ++ if (obj) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "flushing obj %d", ++ obj->obj_id); ++ yaffs_flush_file(obj, 1, 0, 0); ++ } ++ } ++} ++ ++static void yaffs_flush_super(struct super_block *sb, int do_checkpoint) ++{ ++ struct yaffs_dev *dev = yaffs_super_to_dev(sb); ++ if (!dev) ++ return; ++ ++ yaffs_flush_inodes(sb); ++ yaffs_update_dirty_dirs(dev); ++ yaffs_flush_whole_cache(dev, 1); ++ if (do_checkpoint) ++ yaffs_checkpoint_save(dev); ++} ++ ++static LIST_HEAD(yaffs_context_list); ++struct mutex yaffs_context_lock; ++ ++static void yaffs_put_super(struct super_block *sb) ++{ ++ struct yaffs_dev *dev = yaffs_super_to_dev(sb); ++ struct mtd_info *mtd = yaffs_dev_to_mtd(dev); ++ ++ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS, ++ "yaffs_put_super"); ++ ++ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND, ++ "Shutting down yaffs background thread"); ++ yaffs_bg_stop(dev); ++ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND, ++ "yaffs background thread shut down"); ++ ++ yaffs_gross_lock(dev); ++ ++ yaffs_flush_super(sb, 1); ++ ++ yaffs_deinitialise(dev); ++ ++ yaffs_gross_unlock(dev); ++ ++ mutex_lock(&yaffs_context_lock); ++ list_del_init(&(yaffs_dev_to_lc(dev)->context_list)); ++ mutex_unlock(&yaffs_context_lock); ++ ++ if (yaffs_dev_to_lc(dev)->spare_buffer) { ++ kfree(yaffs_dev_to_lc(dev)->spare_buffer); ++ yaffs_dev_to_lc(dev)->spare_buffer = NULL; ++ } ++ ++ kfree(dev); ++ ++ yaffs_put_mtd_device(mtd); ++ ++ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS, ++ "yaffs_put_super done"); ++} ++ ++ ++static unsigned yaffs_gc_control_callback(struct yaffs_dev *dev) ++{ ++ return yaffs_gc_control; ++} ++ ++ ++#ifdef YAFFS_COMPILE_EXPORTFS ++ ++static struct inode *yaffs2_nfs_get_inode(struct super_block *sb, uint64_t ino, ++ uint32_t generation) ++{ ++ return Y_IGET(sb, ino); ++} ++ ++static struct dentry *yaffs2_fh_to_dentry(struct super_block *sb, ++ struct fid *fid, int fh_len, ++ int fh_type) ++{ ++ return generic_fh_to_dentry(sb, fid, fh_len, fh_type, ++ yaffs2_nfs_get_inode); ++} ++ ++static struct dentry *yaffs2_fh_to_parent(struct super_block *sb, ++ struct fid *fid, int fh_len, ++ int fh_type) ++{ ++ return generic_fh_to_parent(sb, fid, fh_len, fh_type, ++ yaffs2_nfs_get_inode); ++} ++ ++struct dentry *yaffs2_get_parent(struct dentry *dentry) ++{ ++ ++ struct super_block *sb = dentry->d_inode->i_sb; ++ struct dentry *parent = ERR_PTR(-ENOENT); ++ struct inode *inode; ++ unsigned long parent_ino; ++ struct yaffs_obj *d_obj; ++ struct yaffs_obj *parent_obj; ++ ++ d_obj = yaffs_inode_to_obj(dentry->d_inode); ++ ++ if (d_obj) { ++ parent_obj = d_obj->parent; ++ if (parent_obj) { ++ parent_ino = yaffs_get_obj_inode(parent_obj); ++ inode = Y_IGET(sb, parent_ino); ++ ++ if (IS_ERR(inode)) { ++ parent = ERR_CAST(inode); ++ } else { ++ parent = d_obtain_alias(inode); ++ if (!IS_ERR(parent)) { ++ parent = ERR_PTR(-ENOMEM); ++ iput(inode); ++ } ++ } ++ } ++ } ++ ++ return parent; ++} ++ ++/* Just declare a zero structure as a NULL value implies ++ * using the default functions of exportfs. ++ */ ++ ++static struct export_operations yaffs_export_ops = { ++ .fh_to_dentry = yaffs2_fh_to_dentry, ++ .fh_to_parent = yaffs2_fh_to_parent, ++ .get_parent = yaffs2_get_parent, ++}; ++ ++#endif ++ ++static void yaffs_unstitch_obj(struct inode *inode, struct yaffs_obj *obj) ++{ ++ /* Clear the association between the inode and ++ * the struct yaffs_obj. ++ */ ++ obj->my_inode = NULL; ++ yaffs_inode_to_obj_lv(inode) = NULL; ++ ++ /* If the object freeing was deferred, then the real ++ * free happens now. ++ * This should fix the inode inconsistency problem. ++ */ ++ yaffs_handle_defered_free(obj); ++} ++ ++#ifdef YAFFS_HAS_EVICT_INODE ++/* yaffs_evict_inode combines into one operation what was previously done in ++ * yaffs_clear_inode() and yaffs_delete_inode() ++ * ++ */ ++static void yaffs_evict_inode(struct inode *inode) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev; ++ int deleteme = 0; ++ ++ obj = yaffs_inode_to_obj(inode); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_evict_inode: ino %d, count %d %s", ++ (int)inode->i_ino, atomic_read(&inode->i_count), ++ obj ? "object exists" : "null object"); ++ ++ if (!inode->i_nlink && !is_bad_inode(inode)) ++ deleteme = 1; ++ truncate_inode_pages(&inode->i_data, 0); ++ Y_CLEAR_INODE(inode); ++ ++ if (deleteme && obj) { ++ dev = obj->my_dev; ++ yaffs_gross_lock(dev); ++ yaffs_del_obj(obj); ++ yaffs_gross_unlock(dev); ++ } ++ if (obj) { ++ dev = obj->my_dev; ++ yaffs_gross_lock(dev); ++ yaffs_unstitch_obj(inode, obj); ++ yaffs_gross_unlock(dev); ++ } ++} ++#else ++ ++/* clear is called to tell the fs to release any per-inode data it holds. ++ * The object might still exist on disk and is just being thrown out of the cache ++ * or else the object has actually been deleted and we're being called via ++ * the chain ++ * yaffs_delete_inode() -> clear_inode()->yaffs_clear_inode() ++ */ ++ ++static void yaffs_clear_inode(struct inode *inode) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev; ++ ++ obj = yaffs_inode_to_obj(inode); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_clear_inode: ino %d, count %d %s", ++ (int)inode->i_ino, atomic_read(&inode->i_count), ++ obj ? "object exists" : "null object"); ++ ++ if (obj) { ++ dev = obj->my_dev; ++ yaffs_gross_lock(dev); ++ yaffs_unstitch_obj(inode, obj); ++ yaffs_gross_unlock(dev); ++ } ++ ++} ++ ++/* delete is called when the link count is zero and the inode ++ * is put (ie. nobody wants to know about it anymore, time to ++ * delete the file). ++ * NB Must call clear_inode() ++ */ ++static void yaffs_delete_inode(struct inode *inode) ++{ ++ struct yaffs_obj *obj = yaffs_inode_to_obj(inode); ++ struct yaffs_dev *dev; ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_delete_inode: ino %d, count %d %s", ++ (int)inode->i_ino, atomic_read(&inode->i_count), ++ obj ? "object exists" : "null object"); ++ ++ if (obj) { ++ dev = obj->my_dev; ++ yaffs_gross_lock(dev); ++ yaffs_del_obj(obj); ++ yaffs_gross_unlock(dev); ++ } ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)) ++ truncate_inode_pages(&inode->i_data, 0); ++#endif ++ clear_inode(inode); ++} ++#endif ++ ++ ++ ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) ++static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf) ++{ ++ struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev; ++ struct super_block *sb = dentry->d_sb; ++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf) ++{ ++ struct yaffs_dev *dev = yaffs_super_to_dev(sb); ++#else ++static int yaffs_statfs(struct super_block *sb, struct statfs *buf) ++{ ++ struct yaffs_dev *dev = yaffs_super_to_dev(sb); ++#endif ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_statfs"); ++ ++ yaffs_gross_lock(dev); ++ ++ buf->f_type = YAFFS_MAGIC; ++ buf->f_bsize = sb->s_blocksize; ++ buf->f_namelen = 255; ++ ++ if (dev->data_bytes_per_chunk & (dev->data_bytes_per_chunk - 1)) { ++ /* Do this if chunk size is not a power of 2 */ ++ ++ uint64_t bytes_in_dev; ++ uint64_t bytes_free; ++ ++ bytes_in_dev = ++ ((uint64_t) ++ ((dev->param.end_block - dev->param.start_block + ++ 1))) * ((uint64_t) (dev->param.chunks_per_block * ++ dev->data_bytes_per_chunk)); ++ ++ do_div(bytes_in_dev, sb->s_blocksize); /* bytes_in_dev becomes the number of blocks */ ++ buf->f_blocks = bytes_in_dev; ++ ++ bytes_free = ((uint64_t) (yaffs_get_n_free_chunks(dev))) * ++ ((uint64_t) (dev->data_bytes_per_chunk)); ++ ++ do_div(bytes_free, sb->s_blocksize); ++ ++ buf->f_bfree = bytes_free; ++ ++ } else if (sb->s_blocksize > dev->data_bytes_per_chunk) { ++ ++ buf->f_blocks = ++ (dev->param.end_block - dev->param.start_block + 1) * ++ dev->param.chunks_per_block / ++ (sb->s_blocksize / dev->data_bytes_per_chunk); ++ buf->f_bfree = ++ yaffs_get_n_free_chunks(dev) / ++ (sb->s_blocksize / dev->data_bytes_per_chunk); ++ } else { ++ buf->f_blocks = ++ (dev->param.end_block - dev->param.start_block + 1) * ++ dev->param.chunks_per_block * ++ (dev->data_bytes_per_chunk / sb->s_blocksize); ++ ++ buf->f_bfree = ++ yaffs_get_n_free_chunks(dev) * ++ (dev->data_bytes_per_chunk / sb->s_blocksize); ++ } ++ ++ buf->f_files = 0; ++ buf->f_ffree = 0; ++ buf->f_bavail = buf->f_bfree; ++ ++ yaffs_gross_unlock(dev); ++ return 0; ++} ++ ++ ++ ++static int yaffs_do_sync_fs(struct super_block *sb, int request_checkpoint) ++{ ++ ++ struct yaffs_dev *dev = yaffs_super_to_dev(sb); ++ unsigned int oneshot_checkpoint = (yaffs_auto_checkpoint & 4); ++ unsigned gc_urgent = yaffs_bg_gc_urgency(dev); ++ int do_checkpoint; ++ int dirty = yaffs_check_super_dirty(dev); ++ ++ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND, ++ "yaffs_do_sync_fs: gc-urgency %d %s %s%s", ++ gc_urgent, ++ dirty ? "dirty" : "clean", ++ request_checkpoint ? "checkpoint requested" : "no checkpoint", ++ oneshot_checkpoint ? " one-shot" : ""); ++ ++ yaffs_gross_lock(dev); ++ do_checkpoint = ((request_checkpoint && !gc_urgent) || ++ oneshot_checkpoint) && !dev->is_checkpointed; ++ ++ if (dirty || do_checkpoint) { ++ yaffs_flush_super(sb, !dev->is_checkpointed && do_checkpoint); ++ yaffs_clear_super_dirty(dev); ++ if (oneshot_checkpoint) ++ yaffs_auto_checkpoint &= ~4; ++ } ++ yaffs_gross_unlock(dev); ++ ++ return 0; ++} ++ ++ ++#ifdef YAFFS_HAS_WRITE_SUPER ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) ++static void yaffs_write_super(struct super_block *sb) ++#else ++static int yaffs_write_super(struct super_block *sb) ++#endif ++{ ++ unsigned request_checkpoint = (yaffs_auto_checkpoint >= 2); ++ ++ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND, ++ "yaffs_write_super %s", ++ request_checkpoint ? " checkpt" : ""); ++ ++ yaffs_do_sync_fs(sb, request_checkpoint); ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)) ++ return 0; ++#endif ++} ++#endif ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) ++static int yaffs_sync_fs(struct super_block *sb, int wait) ++#else ++static int yaffs_sync_fs(struct super_block *sb) ++#endif ++{ ++ unsigned request_checkpoint = (yaffs_auto_checkpoint >= 1); ++ ++ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC, ++ "yaffs_sync_fs%s", request_checkpoint ? " checkpt" : ""); ++ ++ yaffs_do_sync_fs(sb, request_checkpoint); ++ ++ return 0; ++} ++ ++/* the function only is used to change dev->read_only when this file system ++ * is remounted. ++ */ ++static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data) ++{ ++ int read_only = 0; ++ struct mtd_info *mtd; ++ struct yaffs_dev *dev = 0; ++ ++ /* Get the device */ ++ mtd = get_mtd_device(NULL, MINOR(sb->s_dev)); ++ if (!mtd) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "MTD device #%u doesn't appear to exist", ++ MINOR(sb->s_dev)); ++ return 1; ++ } ++ ++ /* Check it's NAND */ ++ if (mtd->type != MTD_NANDFLASH) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "MTD device is not NAND it's type %d", ++ mtd->type); ++ return 1; ++ } ++ ++ read_only = ((*flags & MS_RDONLY) != 0); ++ if (!read_only && !(mtd->flags & MTD_WRITEABLE)) { ++ read_only = 1; ++ printk(KERN_INFO ++ "yaffs: mtd is read only, setting superblock read only"); ++ *flags |= MS_RDONLY; ++ } ++ ++ dev = sb->s_fs_info; ++ dev->read_only = read_only; ++ ++ return 0; ++} ++ ++static const struct super_operations yaffs_super_ops = { ++ .statfs = yaffs_statfs, ++ ++#ifndef YAFFS_USE_OWN_IGET ++ .read_inode = yaffs_read_inode, ++#endif ++#ifdef YAFFS_HAS_PUT_INODE ++ .put_inode = yaffs_put_inode, ++#endif ++ .put_super = yaffs_put_super, ++#ifdef YAFFS_HAS_EVICT_INODE ++ .evict_inode = yaffs_evict_inode, ++#else ++ .delete_inode = yaffs_delete_inode, ++ .clear_inode = yaffs_clear_inode, ++#endif ++ .sync_fs = yaffs_sync_fs, ++#ifdef YAFFS_HAS_WRITE_SUPER ++ .write_super = yaffs_write_super, ++#endif ++ .remount_fs = yaffs_remount_fs, ++}; ++ ++struct yaffs_options { ++ int inband_tags; ++ int skip_checkpoint_read; ++ int skip_checkpoint_write; ++ int no_cache; ++ int tags_ecc_on; ++ int tags_ecc_overridden; ++ int lazy_loading_enabled; ++ int lazy_loading_overridden; ++ int empty_lost_and_found; ++ int empty_lost_and_found_overridden; ++ int disable_summary; ++}; ++ ++#define MAX_OPT_LEN 30 ++static int yaffs_parse_options(struct yaffs_options *options, ++ const char *options_str) ++{ ++ char cur_opt[MAX_OPT_LEN + 1]; ++ int p; ++ int error = 0; ++ ++ /* Parse through the options which is a comma seperated list */ ++ ++ while (options_str && *options_str && !error) { ++ memset(cur_opt, 0, MAX_OPT_LEN + 1); ++ p = 0; ++ ++ while (*options_str == ',') ++ options_str++; ++ ++ while (*options_str && *options_str != ',') { ++ if (p < MAX_OPT_LEN) { ++ cur_opt[p] = *options_str; ++ p++; ++ } ++ options_str++; ++ } ++ ++ if (!strcmp(cur_opt, "inband-tags")) { ++ options->inband_tags = 1; ++ } else if (!strcmp(cur_opt, "tags-ecc-off")) { ++ options->tags_ecc_on = 0; ++ options->tags_ecc_overridden = 1; ++ } else if (!strcmp(cur_opt, "tags-ecc-on")) { ++ options->tags_ecc_on = 1; ++ options->tags_ecc_overridden = 1; ++ } else if (!strcmp(cur_opt, "lazy-loading-off")) { ++ options->lazy_loading_enabled = 0; ++ options->lazy_loading_overridden = 1; ++ } else if (!strcmp(cur_opt, "lazy-loading-on")) { ++ options->lazy_loading_enabled = 1; ++ options->lazy_loading_overridden = 1; ++ } else if (!strcmp(cur_opt, "disable-summary")) { ++ options->disable_summary = 1; ++ } else if (!strcmp(cur_opt, "empty-lost-and-found-off")) { ++ options->empty_lost_and_found = 0; ++ options->empty_lost_and_found_overridden = 1; ++ } else if (!strcmp(cur_opt, "empty-lost-and-found-on")) { ++ options->empty_lost_and_found = 1; ++ options->empty_lost_and_found_overridden = 1; ++ } else if (!strcmp(cur_opt, "no-cache")) { ++ options->no_cache = 1; ++ } else if (!strcmp(cur_opt, "no-checkpoint-read")) { ++ options->skip_checkpoint_read = 1; ++ } else if (!strcmp(cur_opt, "no-checkpoint-write")) { ++ options->skip_checkpoint_write = 1; ++ } else if (!strcmp(cur_opt, "no-checkpoint")) { ++ options->skip_checkpoint_read = 1; ++ options->skip_checkpoint_write = 1; ++ } else { ++ printk(KERN_INFO "yaffs: Bad mount option \"%s\"\n", ++ cur_opt); ++ error = 1; ++ } ++ } ++ ++ return error; ++} ++ ++ ++static struct dentry *yaffs_make_root(struct inode *inode) ++{ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) ++ struct dentry *root = d_alloc_root(inode); ++ ++ if (!root) ++ iput(inode); ++ ++ return root; ++#else ++ return d_make_root(inode); ++#endif ++} ++ ++ ++ ++ ++static struct super_block *yaffs_internal_read_super(int yaffs_version, ++ struct super_block *sb, ++ void *data, int silent) ++{ ++ int n_blocks; ++ struct inode *inode = NULL; ++ struct dentry *root; ++ struct yaffs_dev *dev = 0; ++ char devname_buf[BDEVNAME_SIZE + 1]; ++ struct mtd_info *mtd; ++ int err; ++ char *data_str = (char *)data; ++ struct yaffs_linux_context *context = NULL; ++ struct yaffs_param *param; ++ ++ int read_only = 0; ++ int inband_tags = 0; ++ ++ struct yaffs_options options; ++ ++ unsigned mount_id; ++ int found; ++ struct yaffs_linux_context *context_iterator; ++ struct list_head *l; ++ ++ if (!sb) { ++ printk(KERN_INFO "yaffs: sb is NULL\n"); ++ return NULL; ++ } ++ ++ sb->s_magic = YAFFS_MAGIC; ++ sb->s_op = &yaffs_super_ops; ++ sb->s_flags |= MS_NOATIME; ++ ++ read_only = ((sb->s_flags & MS_RDONLY) != 0); ++ ++#ifdef YAFFS_COMPILE_EXPORTFS ++ sb->s_export_op = &yaffs_export_ops; ++#endif ++ ++ if (!sb->s_dev) ++ printk(KERN_INFO "yaffs: sb->s_dev is NULL\n"); ++ else if (!yaffs_devname(sb, devname_buf)) ++ printk(KERN_INFO "yaffs: devname is NULL\n"); ++ else ++ printk(KERN_INFO "yaffs: dev is %d name is \"%s\" %s\n", ++ sb->s_dev, ++ yaffs_devname(sb, devname_buf), read_only ? "ro" : "rw"); ++ ++ if (!data_str) ++ data_str = ""; ++ ++ printk(KERN_INFO "yaffs: passed flags \"%s\"\n", data_str); ++ ++ memset(&options, 0, sizeof(options)); ++ ++ if (yaffs_parse_options(&options, data_str)) { ++ /* Option parsing failed */ ++ return NULL; ++ } ++ ++ sb->s_blocksize = PAGE_CACHE_SIZE; ++ sb->s_blocksize_bits = PAGE_CACHE_SHIFT; ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_read_super: Using yaffs%d", yaffs_version); ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_read_super: block size %d", (int)(sb->s_blocksize)); ++ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs: Attempting MTD mount of %u.%u,\"%s\"", ++ MAJOR(sb->s_dev), MINOR(sb->s_dev), ++ yaffs_devname(sb, devname_buf)); ++ ++ /* Get the device */ ++ mtd = get_mtd_device(NULL, MINOR(sb->s_dev)); ++ if (IS_ERR(mtd)) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs: MTD device %u either not valid or unavailable", ++ MINOR(sb->s_dev)); ++ return NULL; ++ } ++ ++ if (yaffs_auto_select && yaffs_version == 1 && WRITE_SIZE(mtd) >= 2048) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs2"); ++ yaffs_version = 2; ++ } ++ ++ /* Added NCB 26/5/2006 for completeness */ ++ if (yaffs_version == 2 && !options.inband_tags ++ && WRITE_SIZE(mtd) == 512) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs1"); ++ yaffs_version = 1; ++ } ++ ++ if (mtd->oobavail < sizeof(struct yaffs_packed_tags2) || ++ options.inband_tags) ++ inband_tags = 1; ++ ++ if(yaffs_verify_mtd(mtd, yaffs_version, inband_tags) < 0) ++ return NULL; ++ ++ /* OK, so if we got here, we have an MTD that's NAND and looks ++ * like it has the right capabilities ++ * Set the struct yaffs_dev up for mtd ++ */ ++ ++ if (!read_only && !(mtd->flags & MTD_WRITEABLE)) { ++ read_only = 1; ++ printk(KERN_INFO ++ "yaffs: mtd is read only, setting superblock read only\n" ++ ); ++ sb->s_flags |= MS_RDONLY; ++ } ++ ++ dev = kmalloc(sizeof(struct yaffs_dev), GFP_KERNEL); ++ context = kmalloc(sizeof(struct yaffs_linux_context), GFP_KERNEL); ++ ++ if (!dev || !context) { ++ kfree(dev); ++ kfree(context); ++ dev = NULL; ++ context = NULL; ++ ++ /* Deep shit could not allocate device structure */ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs_read_super: Failed trying to allocate struct yaffs_dev." ++ ); ++ return NULL; ++ } ++ memset(dev, 0, sizeof(struct yaffs_dev)); ++ param = &(dev->param); ++ ++ memset(context, 0, sizeof(struct yaffs_linux_context)); ++ dev->os_context = context; ++ INIT_LIST_HEAD(&(context->context_list)); ++ context->dev = dev; ++ context->super = sb; ++ ++ dev->read_only = read_only; ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++ sb->s_fs_info = dev; ++#else ++ sb->u.generic_sbp = dev; ++#endif ++ ++ ++ dev->driver_context = mtd; ++ param->name = mtd->name; ++ ++ /* Set up the memory size parameters.... */ ++ ++ ++ param->n_reserved_blocks = 5; ++ param->n_caches = (options.no_cache) ? 0 : 10; ++ param->inband_tags = inband_tags; ++ ++ param->enable_xattr = 1; ++ if (options.lazy_loading_overridden) ++ param->disable_lazy_load = !options.lazy_loading_enabled; ++ ++ param->defered_dir_update = 1; ++ ++ if (options.tags_ecc_overridden) ++ param->no_tags_ecc = !options.tags_ecc_on; ++ ++ param->empty_lost_n_found = 1; ++ param->refresh_period = 500; ++ param->disable_summary = options.disable_summary; ++ ++ ++#ifdef CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING ++ param->disable_bad_block_marking = 1; ++#endif ++ if (options.empty_lost_and_found_overridden) ++ param->empty_lost_n_found = options.empty_lost_and_found; ++ ++ /* ... and the functions. */ ++ if (yaffs_version == 2) { ++ param->is_yaffs2 = 1; ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) ++ param->total_bytes_per_chunk = mtd->writesize; ++ param->chunks_per_block = mtd->erasesize / mtd->writesize; ++#else ++ param->total_bytes_per_chunk = mtd->oobblock; ++ param->chunks_per_block = mtd->erasesize / mtd->oobblock; ++#endif ++ n_blocks = YCALCBLOCKS(mtd->size, mtd->erasesize); ++ ++ param->start_block = 0; ++ param->end_block = n_blocks - 1; ++ } else { ++ param->is_yaffs2 = 0; ++ n_blocks = YCALCBLOCKS(mtd->size, ++ YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK); ++ ++ param->chunks_per_block = YAFFS_CHUNKS_PER_BLOCK; ++ param->total_bytes_per_chunk = YAFFS_BYTES_PER_CHUNK; ++ } ++ ++ param->start_block = 0; ++ param->end_block = n_blocks - 1; ++ ++ yaffs_mtd_drv_install(dev); ++ ++ param->sb_dirty_fn = yaffs_set_super_dirty; ++ param->gc_control_fn = yaffs_gc_control_callback; ++ ++ yaffs_dev_to_lc(dev)->super = sb; ++ ++ param->use_nand_ecc = 1; ++ ++ param->skip_checkpt_rd = options.skip_checkpoint_read; ++ param->skip_checkpt_wr = options.skip_checkpoint_write; ++ ++ mutex_lock(&yaffs_context_lock); ++ /* Get a mount id */ ++ found = 0; ++ for (mount_id = 0; !found; mount_id++) { ++ found = 1; ++ list_for_each(l, &yaffs_context_list) { ++ context_iterator = ++ list_entry(l, struct yaffs_linux_context, ++ context_list); ++ if (context_iterator->mount_id == mount_id) ++ found = 0; ++ } ++ } ++ context->mount_id = mount_id; ++ ++ list_add_tail(&(yaffs_dev_to_lc(dev)->context_list), ++ &yaffs_context_list); ++ mutex_unlock(&yaffs_context_lock); ++ ++ /* Directory search handling... */ ++ INIT_LIST_HEAD(&(yaffs_dev_to_lc(dev)->search_contexts)); ++ param->remove_obj_fn = yaffs_remove_obj_callback; ++ ++ mutex_init(&(yaffs_dev_to_lc(dev)->gross_lock)); ++ ++ yaffs_gross_lock(dev); ++ ++ err = yaffs_guts_initialise(dev); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_read_super: guts initialised %s", ++ (err == YAFFS_OK) ? "OK" : "FAILED"); ++ ++ if (err == YAFFS_OK) ++ yaffs_bg_start(dev); ++ ++ if (!context->bg_thread) ++ param->defered_dir_update = 0; ++ ++ sb->s_maxbytes = yaffs_max_file_size(dev); ++ ++ /* Release lock before yaffs_get_inode() */ ++ yaffs_gross_unlock(dev); ++ ++ /* Create root inode */ ++ if (err == YAFFS_OK) ++ inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0, yaffs_root(dev)); ++ ++ if (!inode) ++ return NULL; ++ ++ inode->i_op = &yaffs_dir_inode_operations; ++ inode->i_fop = &yaffs_dir_operations; ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_read_super: got root inode"); ++ ++ root = yaffs_make_root(inode); ++ ++ if (!root) ++ return NULL; ++ ++ sb->s_root = root; ++ if(!dev->is_checkpointed) ++ yaffs_set_super_dirty(dev); ++ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs_read_super: is_checkpointed %d", ++ dev->is_checkpointed); ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_read_super: done"); ++ return sb; ++} ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data, ++ int silent) ++{ ++ return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL; ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) ++static struct dentry *yaffs_mount(struct file_system_type *fs_type, int flags, ++ const char *dev_name, void *data) ++{ ++ return mount_bdev(fs_type, flags, dev_name, data, yaffs_internal_read_super_mtd); ++} ++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) ++static int yaffs_read_super(struct file_system_type *fs, ++ int flags, const char *dev_name, ++ void *data, struct vfsmount *mnt) ++{ ++ ++ return get_sb_bdev(fs, flags, dev_name, data, ++ yaffs_internal_read_super_mtd, mnt); ++} ++#else ++static struct super_block *yaffs_read_super(struct file_system_type *fs, ++ int flags, const char *dev_name, ++ void *data) ++{ ++ ++ return get_sb_bdev(fs, flags, dev_name, data, ++ yaffs_internal_read_super_mtd); ++} ++#endif ++ ++static struct file_system_type yaffs_fs_type = { ++ .owner = THIS_MODULE, ++ .name = "yaffs", ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) ++ .mount = yaffs_mount, ++#else ++ .get_sb = yaffs_read_super, ++#endif ++ .kill_sb = kill_block_super, ++ .fs_flags = FS_REQUIRES_DEV, ++}; ++#else ++static struct super_block *yaffs_read_super(struct super_block *sb, void *data, ++ int silent) ++{ ++ return yaffs_internal_read_super(1, sb, data, silent); ++} ++ ++static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super, ++ FS_REQUIRES_DEV); ++#endif ++ ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data, ++ int silent) ++{ ++ return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL; ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) ++static struct dentry *yaffs2_mount(struct file_system_type *fs_type, int flags, ++ const char *dev_name, void *data) ++{ ++ return mount_bdev(fs_type, flags, dev_name, data, yaffs2_internal_read_super_mtd); ++} ++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) ++static int yaffs2_read_super(struct file_system_type *fs, ++ int flags, const char *dev_name, void *data, ++ struct vfsmount *mnt) ++{ ++ return get_sb_bdev(fs, flags, dev_name, data, ++ yaffs2_internal_read_super_mtd, mnt); ++} ++#else ++static struct super_block *yaffs2_read_super(struct file_system_type *fs, ++ int flags, const char *dev_name, ++ void *data) ++{ ++ ++ return get_sb_bdev(fs, flags, dev_name, data, ++ yaffs2_internal_read_super_mtd); ++} ++#endif ++ ++static struct file_system_type yaffs2_fs_type = { ++ .owner = THIS_MODULE, ++ .name = "yaffs2", ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) ++ .mount = yaffs2_mount, ++#else ++ .get_sb = yaffs2_read_super, ++#endif ++ .kill_sb = kill_block_super, ++ .fs_flags = FS_REQUIRES_DEV, ++}; ++#else ++static struct super_block *yaffs2_read_super(struct super_block *sb, ++ void *data, int silent) ++{ ++ return yaffs_internal_read_super(2, sb, data, silent); ++} ++ ++static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super, ++ FS_REQUIRES_DEV); ++#endif ++ ++ ++static struct proc_dir_entry *my_proc_entry; ++ ++static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev) ++{ ++ struct yaffs_param *param = &dev->param; ++ int bs[10]; ++ ++ yaffs_count_blocks_by_state(dev,bs); ++ ++ buf += sprintf(buf, "start_block.......... %d\n", param->start_block); ++ buf += sprintf(buf, "end_block............ %d\n", param->end_block); ++ buf += sprintf(buf, "total_bytes_per_chunk %d\n", ++ param->total_bytes_per_chunk); ++ buf += sprintf(buf, "use_nand_ecc......... %d\n", param->use_nand_ecc); ++ buf += sprintf(buf, "no_tags_ecc.......... %d\n", param->no_tags_ecc); ++ buf += sprintf(buf, "is_yaffs2............ %d\n", param->is_yaffs2); ++ buf += sprintf(buf, "inband_tags.......... %d\n", param->inband_tags); ++ buf += sprintf(buf, "empty_lost_n_found... %d\n", ++ param->empty_lost_n_found); ++ buf += sprintf(buf, "disable_lazy_load.... %d\n", ++ param->disable_lazy_load); ++ buf += sprintf(buf, "disable_bad_block_mrk %d\n", ++ param->disable_bad_block_marking); ++ buf += sprintf(buf, "refresh_period....... %d\n", ++ param->refresh_period); ++ buf += sprintf(buf, "n_caches............. %d\n", param->n_caches); ++ buf += sprintf(buf, "n_reserved_blocks.... %d\n", ++ param->n_reserved_blocks); ++ buf += sprintf(buf, "always_check_erased.. %d\n", ++ param->always_check_erased); ++ buf += sprintf(buf, "\n"); ++ buf += sprintf(buf, "block count by state\n"); ++ buf += sprintf(buf, "0:%d 1:%d 2:%d 3:%d 4:%d\n", ++ bs[0], bs[1], bs[2], bs[3], bs[4]); ++ buf += sprintf(buf, "5:%d 6:%d 7:%d 8:%d 9:%d\n", ++ bs[5], bs[6], bs[7], bs[8], bs[9]); ++ ++ return buf; ++} ++ ++static char *yaffs_dump_dev_part1(char *buf, struct yaffs_dev *dev) ++{ ++ buf += sprintf(buf, "max file size....... %lld\n", ++ (long long) yaffs_max_file_size(dev)); ++ buf += sprintf(buf, "data_bytes_per_chunk. %d\n", ++ dev->data_bytes_per_chunk); ++ buf += sprintf(buf, "chunk_grp_bits....... %d\n", dev->chunk_grp_bits); ++ buf += sprintf(buf, "chunk_grp_size....... %d\n", dev->chunk_grp_size); ++ buf += sprintf(buf, "n_erased_blocks...... %d\n", dev->n_erased_blocks); ++ buf += sprintf(buf, "blocks_in_checkpt.... %d\n", ++ dev->blocks_in_checkpt); ++ buf += sprintf(buf, "\n"); ++ buf += sprintf(buf, "n_tnodes............. %d\n", dev->n_tnodes); ++ buf += sprintf(buf, "n_obj................ %d\n", dev->n_obj); ++ buf += sprintf(buf, "n_free_chunks........ %d\n", dev->n_free_chunks); ++ buf += sprintf(buf, "\n"); ++ buf += sprintf(buf, "n_page_writes........ %u\n", dev->n_page_writes); ++ buf += sprintf(buf, "n_page_reads......... %u\n", dev->n_page_reads); ++ buf += sprintf(buf, "n_erasures........... %u\n", dev->n_erasures); ++ buf += sprintf(buf, "n_gc_copies.......... %u\n", dev->n_gc_copies); ++ buf += sprintf(buf, "all_gcs.............. %u\n", dev->all_gcs); ++ buf += sprintf(buf, "passive_gc_count..... %u\n", ++ dev->passive_gc_count); ++ buf += sprintf(buf, "oldest_dirty_gc_count %u\n", ++ dev->oldest_dirty_gc_count); ++ buf += sprintf(buf, "n_gc_blocks.......... %u\n", dev->n_gc_blocks); ++ buf += sprintf(buf, "bg_gcs............... %u\n", dev->bg_gcs); ++ buf += sprintf(buf, "n_retried_writes..... %u\n", ++ dev->n_retried_writes); ++ buf += sprintf(buf, "n_retired_blocks..... %u\n", ++ dev->n_retired_blocks); ++ buf += sprintf(buf, "n_ecc_fixed.......... %u\n", dev->n_ecc_fixed); ++ buf += sprintf(buf, "n_ecc_unfixed........ %u\n", dev->n_ecc_unfixed); ++ buf += sprintf(buf, "n_tags_ecc_fixed..... %u\n", ++ dev->n_tags_ecc_fixed); ++ buf += sprintf(buf, "n_tags_ecc_unfixed... %u\n", ++ dev->n_tags_ecc_unfixed); ++ buf += sprintf(buf, "cache_hits........... %u\n", dev->cache_hits); ++ buf += sprintf(buf, "n_deleted_files...... %u\n", dev->n_deleted_files); ++ buf += sprintf(buf, "n_unlinked_files..... %u\n", ++ dev->n_unlinked_files); ++ buf += sprintf(buf, "refresh_count........ %u\n", dev->refresh_count); ++ buf += sprintf(buf, "n_bg_deletions....... %u\n", dev->n_bg_deletions); ++ buf += sprintf(buf, "tags_used............ %u\n", dev->tags_used); ++ buf += sprintf(buf, "summary_used......... %u\n", dev->summary_used); ++ ++ return buf; ++} ++ ++static int yaffs_proc_read(char *page, ++ char **start, ++ off_t offset, int count, int *eof, void *data) ++{ ++ struct list_head *item; ++ char *buf = page; ++ int step = offset; ++ int n = 0; ++ ++ /* Get proc_file_read() to step 'offset' by one on each sucessive call. ++ * We use 'offset' (*ppos) to indicate where we are in dev_list. ++ * This also assumes the user has posted a read buffer large ++ * enough to hold the complete output; but that's life in /proc. ++ */ ++ ++ *(int *)start = 1; ++ ++ /* Print header first */ ++ if (step == 0) ++ buf += ++ sprintf(buf, "Multi-version YAFFS\n"); ++ else if (step == 1) ++ buf += sprintf(buf, "\n"); ++ else { ++ step -= 2; ++ ++ mutex_lock(&yaffs_context_lock); ++ ++ /* Locate and print the Nth entry. Order N-squared but N is small. */ ++ list_for_each(item, &yaffs_context_list) { ++ struct yaffs_linux_context *dc = ++ list_entry(item, struct yaffs_linux_context, ++ context_list); ++ struct yaffs_dev *dev = dc->dev; ++ ++ if (n < (step & ~1)) { ++ n += 2; ++ continue; ++ } ++ if ((step & 1) == 0) { ++ buf += ++ sprintf(buf, "\nDevice %d \"%s\"\n", n, ++ dev->param.name); ++ buf = yaffs_dump_dev_part0(buf, dev); ++ } else { ++ buf = yaffs_dump_dev_part1(buf, dev); ++ } ++ ++ break; ++ } ++ mutex_unlock(&yaffs_context_lock); ++ } ++ ++ return buf - page < count ? buf - page : count; ++} ++ ++/** ++ * Set the verbosity of the warnings and error messages. ++ * ++ * Note that the names can only be a..z or _ with the current code. ++ */ ++ ++static struct { ++ char *mask_name; ++ unsigned mask_bitfield; ++} mask_flags[] = { ++ {"allocate", YAFFS_TRACE_ALLOCATE}, ++ {"always", YAFFS_TRACE_ALWAYS}, ++ {"background", YAFFS_TRACE_BACKGROUND}, ++ {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS}, ++ {"buffers", YAFFS_TRACE_BUFFERS}, ++ {"bug", YAFFS_TRACE_BUG}, ++ {"checkpt", YAFFS_TRACE_CHECKPOINT}, ++ {"deletion", YAFFS_TRACE_DELETION}, ++ {"erase", YAFFS_TRACE_ERASE}, ++ {"error", YAFFS_TRACE_ERROR}, ++ {"gc_detail", YAFFS_TRACE_GC_DETAIL}, ++ {"gc", YAFFS_TRACE_GC}, ++ {"lock", YAFFS_TRACE_LOCK}, ++ {"mtd", YAFFS_TRACE_MTD}, ++ {"nandaccess", YAFFS_TRACE_NANDACCESS}, ++ {"os", YAFFS_TRACE_OS}, ++ {"scan_debug", YAFFS_TRACE_SCAN_DEBUG}, ++ {"scan", YAFFS_TRACE_SCAN}, ++ {"mount", YAFFS_TRACE_MOUNT}, ++ {"tracing", YAFFS_TRACE_TRACING}, ++ {"sync", YAFFS_TRACE_SYNC}, ++ {"write", YAFFS_TRACE_WRITE}, ++ {"verify", YAFFS_TRACE_VERIFY}, ++ {"verify_nand", YAFFS_TRACE_VERIFY_NAND}, ++ {"verify_full", YAFFS_TRACE_VERIFY_FULL}, ++ {"verify_all", YAFFS_TRACE_VERIFY_ALL}, ++ {"all", 0xffffffff}, ++ {"none", 0}, ++ {NULL, 0}, ++}; ++ ++#define MAX_MASK_NAME_LENGTH 40 ++static int yaffs_proc_write_trace_options(struct file *file, const char *buf, ++ unsigned long count) ++{ ++ unsigned rg = 0, mask_bitfield; ++ char *end; ++ char *mask_name; ++ const char *x; ++ char substring[MAX_MASK_NAME_LENGTH + 1]; ++ int i; ++ int done = 0; ++ int add, len = 0; ++ int pos = 0; ++ ++ rg = yaffs_trace_mask; ++ ++ while (!done && (pos < count)) { ++ done = 1; ++ while ((pos < count) && isspace(buf[pos])) ++ pos++; ++ ++ switch (buf[pos]) { ++ case '+': ++ case '-': ++ case '=': ++ add = buf[pos]; ++ pos++; ++ break; ++ ++ default: ++ add = ' '; ++ break; ++ } ++ mask_name = NULL; ++ ++ mask_bitfield = simple_strtoul(buf + pos, &end, 0); ++ ++ if (end > buf + pos) { ++ mask_name = "numeral"; ++ len = end - (buf + pos); ++ pos += len; ++ done = 0; ++ } else { ++ for (x = buf + pos, i = 0; ++ (*x == '_' || (*x >= 'a' && *x <= 'z')) && ++ i < MAX_MASK_NAME_LENGTH; x++, i++, pos++) ++ substring[i] = *x; ++ substring[i] = '\0'; ++ ++ for (i = 0; mask_flags[i].mask_name != NULL; i++) { ++ if (strcmp(substring, mask_flags[i].mask_name) ++ == 0) { ++ mask_name = mask_flags[i].mask_name; ++ mask_bitfield = ++ mask_flags[i].mask_bitfield; ++ done = 0; ++ break; ++ } ++ } ++ } ++ ++ if (mask_name != NULL) { ++ done = 0; ++ switch (add) { ++ case '-': ++ rg &= ~mask_bitfield; ++ break; ++ case '+': ++ rg |= mask_bitfield; ++ break; ++ case '=': ++ rg = mask_bitfield; ++ break; ++ default: ++ rg |= mask_bitfield; ++ break; ++ } ++ } ++ } ++ ++ yaffs_trace_mask = rg | YAFFS_TRACE_ALWAYS; ++ ++ printk(KERN_DEBUG "new trace = 0x%08X\n", yaffs_trace_mask); ++ ++ if (rg & YAFFS_TRACE_ALWAYS) { ++ for (i = 0; mask_flags[i].mask_name != NULL; i++) { ++ char flag; ++ flag = ((rg & mask_flags[i].mask_bitfield) == ++ mask_flags[i].mask_bitfield) ? '+' : '-'; ++ printk(KERN_DEBUG "%c%s\n", flag, ++ mask_flags[i].mask_name); ++ } ++ } ++ ++ return count; ++} ++ ++/* Debug strings are of the form: ++ * .bnnn print info on block n ++ * .cobjn,chunkn print nand chunk id for objn:chunkn ++ */ ++ ++static int yaffs_proc_debug_write(struct file *file, const char *buf, ++ unsigned long count) ++{ ++ ++ char str[100]; ++ char *p0; ++ char *p1; ++ long p1_val; ++ long p0_val; ++ char cmd; ++ struct list_head *item; ++ ++ memset(str, 0, sizeof(str)); ++ memcpy(str, buf, min((size_t)count, sizeof(str) -1)); ++ ++ cmd = str[1]; ++ ++ p0 = str + 2; ++ ++ p1 = p0; ++ ++ while (*p1 && *p1 != ',') { ++ p1++; ++ } ++ *p1 = '\0'; ++ p1++; ++ ++ p0_val = simple_strtol(p0, NULL, 0); ++ p1_val = simple_strtol(p1, NULL, 0); ++ ++ ++ mutex_lock(&yaffs_context_lock); ++ ++ /* Locate and print the Nth entry. Order N-squared but N is small. */ ++ list_for_each(item, &yaffs_context_list) { ++ struct yaffs_linux_context *dc = ++ list_entry(item, struct yaffs_linux_context, ++ context_list); ++ struct yaffs_dev *dev = dc->dev; ++ ++ if (cmd == 'b') { ++ struct yaffs_block_info *bi; ++ ++ bi = yaffs_get_block_info(dev,p0_val); ++ ++ if(bi) { ++ printk("Block %d: state %d, retire %d, use %d, seq %d\n", ++ (int)p0_val, bi->block_state, ++ bi->needs_retiring, bi->pages_in_use, ++ bi->seq_number); ++ } ++ } else if (cmd == 'c') { ++ struct yaffs_obj *obj; ++ int nand_chunk; ++ ++ obj = yaffs_find_by_number(dev, p0_val); ++ if (!obj) ++ printk("No obj %d\n", (int)p0_val); ++ else { ++ if(p1_val == 0) ++ nand_chunk = obj->hdr_chunk; ++ else ++ nand_chunk = ++ yaffs_find_chunk_in_file(obj, ++ p1_val, NULL); ++ printk("Nand chunk for %d:%d is %d\n", ++ (int)p0_val, (int)p1_val, nand_chunk); ++ } ++ } ++ } ++ ++ mutex_unlock(&yaffs_context_lock); ++ ++ return count; ++} ++ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) ++static int yaffs_proc_write(struct file *file, const char *buf, ++ unsigned long count, void *ppos) ++#else ++static ssize_t yaffs_proc_write(struct file *file, const char __user *buf, ++ size_t count, loff_t *ppos) ++#endif ++{ ++ if (buf[0] == '.') ++ return yaffs_proc_debug_write(file, buf, count); ++ return yaffs_proc_write_trace_options(file, buf, count); ++} ++ ++/* Stuff to handle installation of file systems */ ++struct file_system_to_install { ++ struct file_system_type *fst; ++ int installed; ++}; ++ ++static struct file_system_to_install fs_to_install[] = { ++ {&yaffs_fs_type, 0}, ++ {&yaffs2_fs_type, 0}, ++ {NULL, 0} ++}; ++ ++ ++#ifdef YAFFS_NEW_PROCFS ++static int yaffs_proc_show(struct seq_file *m, void *v) ++{ ++ /* FIXME: Unify in a better way? */ ++ char buffer[512]; ++ char *start; ++ int len; ++ ++ len = yaffs_proc_read(buffer, &start, 0, sizeof(buffer), NULL, NULL); ++ seq_puts(m, buffer); ++ return 0; ++} ++ ++static int yaffs_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, yaffs_proc_show, NULL); ++} ++ ++static struct file_operations procfs_ops = { ++ .owner = THIS_MODULE, ++ .open = yaffs_proc_open, ++ .read = seq_read, ++ .write = yaffs_proc_write, ++}; ++ ++static int yaffs_procfs_init(void) ++{ ++ /* Install the proc_fs entries */ ++ my_proc_entry = proc_create("yaffs", ++ S_IRUGO | S_IFREG, ++ YPROC_ROOT, ++ &procfs_ops); ++ ++ if (my_proc_entry) { ++ return 0; ++ } else { ++ return -ENOMEM; ++ } ++} ++ ++#else ++ ++ ++static int yaffs_procfs_init(void) ++{ ++ /* Install the proc_fs entries */ ++ my_proc_entry = create_proc_entry("yaffs", ++ S_IRUGO | S_IFREG, YPROC_ROOT); ++ ++ if (my_proc_entry) { ++ my_proc_entry->write_proc = yaffs_proc_write; ++ my_proc_entry->read_proc = yaffs_proc_read; ++ my_proc_entry->data = NULL; ++ return 0; ++ } else { ++ return -ENOMEM; ++ } ++} ++ ++#endif ++ ++ ++static int __init init_yaffs_fs(void) ++{ ++ int error = 0; ++ struct file_system_to_install *fsinst; ++ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs Installing."); ++ ++ mutex_init(&yaffs_context_lock); ++ ++ error = yaffs_procfs_init(); ++ if (error) ++ return error; ++ ++ /* Now add the file system entries */ ++ ++ fsinst = fs_to_install; ++ ++ while (fsinst->fst && !error) { ++ error = register_filesystem(fsinst->fst); ++ if (!error) ++ fsinst->installed = 1; ++ fsinst++; ++ } ++ ++ /* Any errors? uninstall */ ++ if (error) { ++ fsinst = fs_to_install; ++ ++ while (fsinst->fst) { ++ if (fsinst->installed) { ++ unregister_filesystem(fsinst->fst); ++ fsinst->installed = 0; ++ } ++ fsinst++; ++ } ++ } ++ ++ return error; ++} ++ ++static void __exit exit_yaffs_fs(void) ++{ ++ ++ struct file_system_to_install *fsinst; ++ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs removing."); ++ ++ remove_proc_entry("yaffs", YPROC_ROOT); ++ ++ fsinst = fs_to_install; ++ ++ while (fsinst->fst) { ++ if (fsinst->installed) { ++ unregister_filesystem(fsinst->fst); ++ fsinst->installed = 0; ++ } ++ fsinst++; ++ } ++} ++ ++module_init(init_yaffs_fs) ++ module_exit(exit_yaffs_fs) ++ ++ MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system"); ++MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2011"); ++MODULE_LICENSE("GPL"); +diff --git a/fs/yaffs2/yaffs_yaffs1.c b/fs/yaffs2/yaffs_yaffs1.c +new file mode 100644 +index 0000000..0cdc8c8 +--- /dev/null ++++ b/fs/yaffs2/yaffs_yaffs1.c +@@ -0,0 +1,424 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * 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 "yaffs_yaffs1.h" ++#include "yportenv.h" ++#include "yaffs_trace.h" ++#include "yaffs_bitmap.h" ++#include "yaffs_getblockinfo.h" ++#include "yaffs_nand.h" ++#include "yaffs_attribs.h" ++ ++int yaffs1_scan(struct yaffs_dev *dev) ++{ ++ struct yaffs_ext_tags tags; ++ u32 blk; ++ int result; ++ int chunk; ++ u32 c; ++ int deleted; ++ enum yaffs_block_state state; ++ LIST_HEAD(hard_list); ++ struct yaffs_block_info *bi; ++ u32 seq_number; ++ struct yaffs_obj_hdr *oh; ++ struct yaffs_obj *in; ++ struct yaffs_obj *parent; ++ int alloc_failed = 0; ++ struct yaffs_shadow_fixer *shadow_fixers = NULL; ++ u8 *chunk_data; ++ ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ "yaffs1_scan starts intstartblk %d intendblk %d...", ++ dev->internal_start_block, dev->internal_end_block); ++ ++ chunk_data = yaffs_get_temp_buffer(dev); ++ ++ dev->seq_number = YAFFS_LOWEST_SEQUENCE_NUMBER; ++ ++ /* Scan all the blocks to determine their state */ ++ bi = dev->block_info; ++ for (blk = dev->internal_start_block; blk <= dev->internal_end_block; ++ blk++) { ++ yaffs_clear_chunk_bits(dev, blk); ++ bi->pages_in_use = 0; ++ bi->soft_del_pages = 0; ++ ++ yaffs_query_init_block_state(dev, blk, &state, &seq_number); ++ ++ bi->block_state = state; ++ bi->seq_number = seq_number; ++ ++ if (bi->seq_number == YAFFS_SEQUENCE_BAD_BLOCK) ++ bi->block_state = state = YAFFS_BLOCK_STATE_DEAD; ++ ++ yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, ++ "Block scanning block %d state %d seq %d", ++ blk, state, seq_number); ++ ++ if (state == YAFFS_BLOCK_STATE_DEAD) { ++ yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, ++ "block %d is bad", blk); ++ } else if (state == YAFFS_BLOCK_STATE_EMPTY) { ++ yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, "Block empty "); ++ dev->n_erased_blocks++; ++ dev->n_free_chunks += dev->param.chunks_per_block; ++ } ++ bi++; ++ } ++ ++ /* For each block.... */ ++ for (blk = dev->internal_start_block; ++ !alloc_failed && blk <= dev->internal_end_block; blk++) { ++ ++ cond_resched(); ++ ++ bi = yaffs_get_block_info(dev, blk); ++ state = bi->block_state; ++ ++ deleted = 0; ++ ++ /* For each chunk in each block that needs scanning.... */ ++ for (c = 0; ++ !alloc_failed && c < dev->param.chunks_per_block && ++ state == YAFFS_BLOCK_STATE_NEEDS_SCAN; c++) { ++ /* Read the tags and decide what to do */ ++ chunk = blk * dev->param.chunks_per_block + c; ++ ++ result = yaffs_rd_chunk_tags_nand(dev, chunk, NULL, ++ &tags); ++ ++ if (result != YAFFS_OK) ++ continue; ++ /* Let's have a good look at this chunk... */ ++ ++ if (tags.ecc_result == YAFFS_ECC_RESULT_UNFIXED || ++ tags.is_deleted) { ++ /* YAFFS1 only... ++ * A deleted chunk ++ */ ++ deleted++; ++ dev->n_free_chunks++; ++ } else if (!tags.chunk_used) { ++ /* An unassigned chunk in the block ++ * This means that either the block is empty or ++ * this is the one being allocated from ++ */ ++ ++ if (c == 0) { ++ /* We're looking at the first chunk in ++ *the block so the block is unused */ ++ state = YAFFS_BLOCK_STATE_EMPTY; ++ dev->n_erased_blocks++; ++ } else { ++ /* this is the block being allocated */ ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ " Allocating from %d %d", ++ blk, c); ++ state = YAFFS_BLOCK_STATE_ALLOCATING; ++ dev->alloc_block = blk; ++ dev->alloc_page = c; ++ dev->alloc_block_finder = blk; ++ ++ } ++ ++ dev->n_free_chunks += ++ (dev->param.chunks_per_block - c); ++ } else if (tags.chunk_id > 0) { ++ /* chunk_id > 0 so it is a data chunk... */ ++ unsigned int endpos; ++ ++ yaffs_set_chunk_bit(dev, blk, c); ++ bi->pages_in_use++; ++ ++ in = yaffs_find_or_create_by_number(dev, ++ tags.obj_id, ++ YAFFS_OBJECT_TYPE_FILE); ++ /* PutChunkIntoFile checks for a clash ++ * (two data chunks with the same chunk_id). ++ */ ++ ++ if (!in) ++ alloc_failed = 1; ++ ++ if (in) { ++ if (!yaffs_put_chunk_in_file ++ (in, tags.chunk_id, chunk, 1)) ++ alloc_failed = 1; ++ } ++ ++ endpos = ++ (tags.chunk_id - 1) * ++ dev->data_bytes_per_chunk + ++ tags.n_bytes; ++ if (in && ++ in->variant_type == ++ YAFFS_OBJECT_TYPE_FILE && ++ in->variant.file_variant.stored_size < ++ endpos) { ++ in->variant.file_variant.stored_size = ++ endpos; ++ if (!dev->param.use_header_file_size) { ++ in->variant. ++ file_variant.file_size = ++ in->variant. ++ file_variant.stored_size; ++ } ++ ++ } ++ } else { ++ /* chunk_id == 0, so it is an ObjectHeader. ++ * Make the object ++ */ ++ yaffs_set_chunk_bit(dev, blk, c); ++ bi->pages_in_use++; ++ ++ result = yaffs_rd_chunk_tags_nand(dev, chunk, ++ chunk_data, ++ NULL); ++ ++ oh = (struct yaffs_obj_hdr *)chunk_data; ++ ++ in = yaffs_find_by_number(dev, tags.obj_id); ++ if (in && in->variant_type != oh->type) { ++ /* This should not happen, but somehow ++ * Wev'e ended up with an obj_id that ++ * has been reused but not yet deleted, ++ * and worse still it has changed type. ++ * Delete the old object. ++ */ ++ ++ yaffs_del_obj(in); ++ in = NULL; ++ } ++ ++ in = yaffs_find_or_create_by_number(dev, ++ tags.obj_id, ++ oh->type); ++ ++ if (!in) ++ alloc_failed = 1; ++ ++ if (in && oh->shadows_obj > 0) { ++ ++ struct yaffs_shadow_fixer *fixer; ++ fixer = ++ kmalloc(sizeof ++ (struct yaffs_shadow_fixer), ++ GFP_NOFS); ++ if (fixer) { ++ fixer->next = shadow_fixers; ++ shadow_fixers = fixer; ++ fixer->obj_id = tags.obj_id; ++ fixer->shadowed_id = ++ oh->shadows_obj; ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ " Shadow fixer: %d shadows %d", ++ fixer->obj_id, ++ fixer->shadowed_id); ++ ++ } ++ ++ } ++ ++ if (in && in->valid) { ++ /* We have already filled this one. ++ * We have a duplicate and need to ++ * resolve it. */ ++ ++ unsigned existing_serial = in->serial; ++ unsigned new_serial = ++ tags.serial_number; ++ ++ if (((existing_serial + 1) & 3) == ++ new_serial) { ++ /* Use new one - destroy the ++ * exisiting one */ ++ yaffs_chunk_del(dev, ++ in->hdr_chunk, ++ 1, __LINE__); ++ in->valid = 0; ++ } else { ++ /* Use existing - destroy ++ * this one. */ ++ yaffs_chunk_del(dev, chunk, 1, ++ __LINE__); ++ } ++ } ++ ++ if (in && !in->valid && ++ (tags.obj_id == YAFFS_OBJECTID_ROOT || ++ tags.obj_id == ++ YAFFS_OBJECTID_LOSTNFOUND)) { ++ /* We only load some info, don't fiddle ++ * with directory structure */ ++ in->valid = 1; ++ in->variant_type = oh->type; ++ ++ in->yst_mode = oh->yst_mode; ++ yaffs_load_attribs(in, oh); ++ in->hdr_chunk = chunk; ++ in->serial = tags.serial_number; ++ ++ } else if (in && !in->valid) { ++ /* we need to load this info */ ++ ++ in->valid = 1; ++ in->variant_type = oh->type; ++ ++ in->yst_mode = oh->yst_mode; ++ yaffs_load_attribs(in, oh); ++ in->hdr_chunk = chunk; ++ in->serial = tags.serial_number; ++ ++ yaffs_set_obj_name_from_oh(in, oh); ++ in->dirty = 0; ++ ++ /* directory stuff... ++ * hook up to parent ++ */ ++ ++ parent = ++ yaffs_find_or_create_by_number ++ (dev, oh->parent_obj_id, ++ YAFFS_OBJECT_TYPE_DIRECTORY); ++ if (!parent) ++ alloc_failed = 1; ++ if (parent && parent->variant_type == ++ YAFFS_OBJECT_TYPE_UNKNOWN) { ++ /* Set up as a directory */ ++ parent->variant_type = ++ YAFFS_OBJECT_TYPE_DIRECTORY; ++ INIT_LIST_HEAD(&parent-> ++ variant.dir_variant. ++ children); ++ } else if (!parent || ++ parent->variant_type != ++ YAFFS_OBJECT_TYPE_DIRECTORY) { ++ /* Hoosterman, a problem.... ++ * We're trying to use a ++ * non-directory as a directory ++ */ ++ ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found." ++ ); ++ parent = dev->lost_n_found; ++ } ++ ++ yaffs_add_obj_to_dir(parent, in); ++ ++ switch (in->variant_type) { ++ case YAFFS_OBJECT_TYPE_UNKNOWN: ++ /* Todo got a problem */ ++ break; ++ case YAFFS_OBJECT_TYPE_FILE: ++ if (dev->param. ++ use_header_file_size) ++ in->variant. ++ file_variant.file_size ++ = yaffs_oh_to_size(dev, oh, 0); ++ break; ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ in->variant. ++ hardlink_variant.equiv_id = ++ oh->equiv_id; ++ list_add(&in->hard_links, ++ &hard_list); ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ /* Do nothing */ ++ break; ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ /* Do nothing */ ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ in->variant.symlink_variant. ++ alias = ++ yaffs_clone_str(oh->alias); ++ if (!in->variant. ++ symlink_variant.alias) ++ alloc_failed = 1; ++ break; ++ } ++ } ++ } ++ } ++ ++ if (state == YAFFS_BLOCK_STATE_NEEDS_SCAN) { ++ /* If we got this far while scanning, ++ * then the block is fully allocated. */ ++ state = YAFFS_BLOCK_STATE_FULL; ++ } ++ ++ if (state == YAFFS_BLOCK_STATE_ALLOCATING) { ++ /* If the block was partially allocated then ++ * treat it as fully allocated. */ ++ state = YAFFS_BLOCK_STATE_FULL; ++ dev->alloc_block = -1; ++ } ++ ++ bi->block_state = state; ++ ++ /* Now let's see if it was dirty */ ++ if (bi->pages_in_use == 0 && ++ !bi->has_shrink_hdr && ++ bi->block_state == YAFFS_BLOCK_STATE_FULL) ++ yaffs_block_became_dirty(dev, blk); ++ } ++ ++ /* Ok, we've done all the scanning. ++ * Fix up the hard link chains. ++ * We should now have scanned all the objects, now it's time to add ++ * these hardlinks. ++ */ ++ ++ yaffs_link_fixup(dev, &hard_list); ++ ++ /* ++ * Fix up any shadowed objects. ++ * There should not be more than one of these. ++ */ ++ { ++ struct yaffs_shadow_fixer *fixer; ++ struct yaffs_obj *obj; ++ ++ while (shadow_fixers) { ++ fixer = shadow_fixers; ++ shadow_fixers = fixer->next; ++ /* Complete the rename transaction by deleting the ++ * shadowed object then setting the object header ++ to unshadowed. ++ */ ++ obj = yaffs_find_by_number(dev, fixer->shadowed_id); ++ if (obj) ++ yaffs_del_obj(obj); ++ ++ obj = yaffs_find_by_number(dev, fixer->obj_id); ++ ++ if (obj) ++ yaffs_update_oh(obj, NULL, 1, 0, 0, NULL); ++ ++ kfree(fixer); ++ } ++ } ++ ++ yaffs_release_temp_buffer(dev, chunk_data); ++ ++ if (alloc_failed) ++ return YAFFS_FAIL; ++ ++ yaffs_trace(YAFFS_TRACE_SCAN, "yaffs1_scan ends"); ++ ++ return YAFFS_OK; ++} +diff --git a/fs/yaffs2/yaffs_yaffs1.h b/fs/yaffs2/yaffs_yaffs1.h +new file mode 100644 +index 0000000..97e2fdd +--- /dev/null ++++ b/fs/yaffs2/yaffs_yaffs1.h +@@ -0,0 +1,22 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_YAFFS1_H__ ++#define __YAFFS_YAFFS1_H__ ++ ++#include "yaffs_guts.h" ++int yaffs1_scan(struct yaffs_dev *dev); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_yaffs2.c b/fs/yaffs2/yaffs_yaffs2.c +new file mode 100644 +index 0000000..47fa8eb +--- /dev/null ++++ b/fs/yaffs2/yaffs_yaffs2.c +@@ -0,0 +1,1712 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * 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 "yaffs_guts.h" ++#include "yaffs_trace.h" ++#include "yaffs_yaffs2.h" ++#include "yaffs_checkptrw.h" ++#include "yaffs_bitmap.h" ++#include "yaffs_nand.h" ++#include "yaffs_getblockinfo.h" ++#include "yaffs_verify.h" ++#include "yaffs_attribs.h" ++#include "yaffs_summary.h" ++#include "yaffs_endian.h" ++ ++/* ++ * Checkpoints are really no benefit on very small partitions. ++ * ++ * To save space on small partitions don't bother with checkpoints unless ++ * the partition is at least this big. ++ */ ++#define YAFFS_CHECKPOINT_MIN_BLOCKS 60 ++#define YAFFS_SMALL_HOLE_THRESHOLD 4 ++ ++/* ++ * Oldest Dirty Sequence Number handling. ++ */ ++ ++/* yaffs_calc_oldest_dirty_seq() ++ * yaffs2_find_oldest_dirty_seq() ++ * Calculate the oldest dirty sequence number if we don't know it. ++ */ ++void yaffs_calc_oldest_dirty_seq(struct yaffs_dev *dev) ++{ ++ u32 i; ++ unsigned seq; ++ unsigned block_no = 0; ++ struct yaffs_block_info *b; ++ ++ if (!dev->param.is_yaffs2) ++ return; ++ ++ /* Find the oldest dirty sequence number. */ ++ seq = dev->seq_number + 1; ++ b = dev->block_info; ++ for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) { ++ if (b->block_state == YAFFS_BLOCK_STATE_FULL && ++ (u32)(b->pages_in_use - b->soft_del_pages) < ++ dev->param.chunks_per_block && ++ b->seq_number < seq) { ++ seq = b->seq_number; ++ block_no = i; ++ } ++ b++; ++ } ++ ++ if (block_no) { ++ dev->oldest_dirty_seq = seq; ++ dev->oldest_dirty_block = block_no; ++ } ++} ++ ++void yaffs2_find_oldest_dirty_seq(struct yaffs_dev *dev) ++{ ++ if (!dev->param.is_yaffs2) ++ return; ++ ++ if (!dev->oldest_dirty_seq) ++ yaffs_calc_oldest_dirty_seq(dev); ++} ++ ++/* ++ * yaffs_clear_oldest_dirty_seq() ++ * Called when a block is erased or marked bad. (ie. when its seq_number ++ * becomes invalid). If the value matches the oldest then we clear ++ * dev->oldest_dirty_seq to force its recomputation. ++ */ ++void yaffs2_clear_oldest_dirty_seq(struct yaffs_dev *dev, ++ struct yaffs_block_info *bi) ++{ ++ ++ if (!dev->param.is_yaffs2) ++ return; ++ ++ if (!bi || bi->seq_number == dev->oldest_dirty_seq) { ++ dev->oldest_dirty_seq = 0; ++ dev->oldest_dirty_block = 0; ++ } ++} ++ ++/* ++ * yaffs2_update_oldest_dirty_seq() ++ * Update the oldest dirty sequence number whenever we dirty a block. ++ * Only do this if the oldest_dirty_seq is actually being tracked. ++ */ ++void yaffs2_update_oldest_dirty_seq(struct yaffs_dev *dev, unsigned block_no, ++ struct yaffs_block_info *bi) ++{ ++ if (!dev->param.is_yaffs2) ++ return; ++ ++ if (dev->oldest_dirty_seq) { ++ if (dev->oldest_dirty_seq > bi->seq_number) { ++ dev->oldest_dirty_seq = bi->seq_number; ++ dev->oldest_dirty_block = block_no; ++ } ++ } ++} ++ ++int yaffs_block_ok_for_gc(struct yaffs_dev *dev, struct yaffs_block_info *bi) ++{ ++ ++ if (!dev->param.is_yaffs2) ++ return 1; /* disqualification only applies to yaffs2. */ ++ ++ if (!bi->has_shrink_hdr) ++ return 1; /* can gc */ ++ ++ yaffs2_find_oldest_dirty_seq(dev); ++ ++ /* Can't do gc of this block if there are any blocks older than this ++ * one that have discarded pages. ++ */ ++ return (bi->seq_number <= dev->oldest_dirty_seq); ++} ++ ++/* ++ * yaffs2_find_refresh_block() ++ * periodically finds the oldest full block by sequence number for refreshing. ++ * Only for yaffs2. ++ */ ++u32 yaffs2_find_refresh_block(struct yaffs_dev *dev) ++{ ++ u32 b; ++ u32 oldest = 0; ++ u32 oldest_seq = 0; ++ struct yaffs_block_info *bi; ++ ++ if (!dev->param.is_yaffs2) ++ return oldest; ++ ++ /* ++ * If refresh period < 10 then refreshing is disabled. ++ */ ++ if (dev->param.refresh_period < 10) ++ return oldest; ++ ++ /* ++ * Fix broken values. ++ */ ++ if (dev->refresh_skip > dev->param.refresh_period) ++ dev->refresh_skip = dev->param.refresh_period; ++ ++ if (dev->refresh_skip > 0) ++ return oldest; ++ ++ /* ++ * Refresh skip is now zero. ++ * We'll do a refresh this time around.... ++ * Update the refresh skip and find the oldest block. ++ */ ++ dev->refresh_skip = dev->param.refresh_period; ++ dev->refresh_count++; ++ bi = dev->block_info; ++ for (b = dev->internal_start_block; b <= dev->internal_end_block; b++) { ++ ++ if (bi->block_state == YAFFS_BLOCK_STATE_FULL) { ++ ++ if (oldest < 1 || bi->seq_number < oldest_seq) { ++ oldest = b; ++ oldest_seq = bi->seq_number; ++ } ++ } ++ bi++; ++ } ++ ++ if (oldest > 0) { ++ yaffs_trace(YAFFS_TRACE_GC, ++ "GC refresh count %d selected block %d with seq_number %d", ++ dev->refresh_count, oldest, oldest_seq); ++ } ++ ++ return oldest; ++} ++ ++int yaffs2_checkpt_required(struct yaffs_dev *dev) ++{ ++ int nblocks; ++ ++ if (!dev->param.is_yaffs2) ++ return 0; ++ ++ nblocks = dev->internal_end_block - dev->internal_start_block + 1; ++ ++ return !dev->param.skip_checkpt_wr && ++ !dev->read_only && (nblocks >= YAFFS_CHECKPOINT_MIN_BLOCKS); ++} ++ ++int yaffs_calc_checkpt_blocks_required(struct yaffs_dev *dev) ++{ ++ int retval; ++ int n_bytes = 0; ++ int n_blocks; ++ int dev_blocks; ++ ++ if (!dev->param.is_yaffs2) ++ return 0; ++ ++ if (!dev->checkpoint_blocks_required && yaffs2_checkpt_required(dev)) { ++ /* Not a valid value so recalculate */ ++ dev_blocks = dev->param.end_block - dev->param.start_block + 1; ++ n_bytes += sizeof(struct yaffs_checkpt_validity); ++ n_bytes += sizeof(struct yaffs_checkpt_dev); ++ n_bytes += dev_blocks * sizeof(struct yaffs_block_info); ++ n_bytes += dev_blocks * dev->chunk_bit_stride; ++ n_bytes += ++ (sizeof(struct yaffs_checkpt_obj) + sizeof(u32)) * ++ dev->n_obj; ++ n_bytes += (dev->tnode_size + sizeof(u32)) * dev->n_tnodes; ++ n_bytes += sizeof(struct yaffs_checkpt_validity); ++ n_bytes += sizeof(u32); /* checksum */ ++ ++ /* Round up and add 2 blocks to allow for some bad blocks, ++ * so add 3 */ ++ ++ n_blocks = ++ (n_bytes / ++ (dev->data_bytes_per_chunk * ++ dev->param.chunks_per_block)) + 3; ++ ++ dev->checkpoint_blocks_required = n_blocks; ++ } ++ ++ retval = dev->checkpoint_blocks_required - dev->blocks_in_checkpt; ++ if (retval < 0) ++ retval = 0; ++ return retval; ++} ++ ++/*--------------------- Checkpointing --------------------*/ ++ ++static void yaffs2_do_endian_validity_marker(struct yaffs_dev *dev, ++ struct yaffs_checkpt_validity *v) ++{ ++ ++ if (!dev->swap_endian) ++ return; ++ v->struct_type = swap_s32(v->struct_type); ++ v->magic = swap_u32(v->magic); ++ v->version = swap_u32(v->version); ++ v->head = swap_u32(v->head); ++} ++ ++static int yaffs2_wr_checkpt_validity_marker(struct yaffs_dev *dev, int head) ++{ ++ struct yaffs_checkpt_validity cp; ++ ++ memset(&cp, 0, sizeof(cp)); ++ ++ cp.struct_type = sizeof(cp); ++ cp.magic = YAFFS_MAGIC; ++ cp.version = YAFFS_CHECKPOINT_VERSION; ++ cp.head = (head) ? 1 : 0; ++ ++ yaffs2_do_endian_validity_marker(dev, &cp); ++ ++ return (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp)) ? 1 : 0; ++} ++ ++static int yaffs2_rd_checkpt_validity_marker(struct yaffs_dev *dev, int head) ++{ ++ struct yaffs_checkpt_validity cp; ++ int ok; ++ ++ ok = (yaffs2_checkpt_rd(dev, &cp, sizeof(cp)) == sizeof(cp)); ++ yaffs2_do_endian_validity_marker(dev, &cp); ++ ++ if (ok) ++ ok = (cp.struct_type == sizeof(cp)) && ++ (cp.magic == YAFFS_MAGIC) && ++ (cp.version == YAFFS_CHECKPOINT_VERSION) && ++ (cp.head == ((head) ? 1 : 0)); ++ return ok ? 1 : 0; ++} ++ ++static void yaffs2_dev_to_checkpt_dev(struct yaffs_checkpt_dev *cp, ++ struct yaffs_dev *dev) ++{ ++ cp->struct_type = sizeof(*cp); ++ ++ cp->n_erased_blocks = dev->n_erased_blocks; ++ cp->alloc_block = dev->alloc_block; ++ cp->alloc_page = dev->alloc_page; ++ cp->n_free_chunks = dev->n_free_chunks; ++ ++ cp->n_deleted_files = dev->n_deleted_files; ++ cp->n_unlinked_files = dev->n_unlinked_files; ++ cp->n_bg_deletions = dev->n_bg_deletions; ++ cp->seq_number = dev->seq_number; ++ ++} ++ ++static void yaffs_checkpt_dev_to_dev(struct yaffs_dev *dev, ++ struct yaffs_checkpt_dev *cp) ++{ ++ dev->n_erased_blocks = cp->n_erased_blocks; ++ dev->alloc_block = cp->alloc_block; ++ dev->alloc_page = cp->alloc_page; ++ dev->n_free_chunks = cp->n_free_chunks; ++ ++ dev->n_deleted_files = cp->n_deleted_files; ++ dev->n_unlinked_files = cp->n_unlinked_files; ++ dev->n_bg_deletions = cp->n_bg_deletions; ++ dev->seq_number = cp->seq_number; ++} ++ ++static void yaffs2_do_endian_checkpt_dev(struct yaffs_dev *dev, ++ struct yaffs_checkpt_dev *cp) ++{ ++ if (!dev->swap_endian) ++ return; ++ cp->struct_type = swap_s32(cp->struct_type); ++ cp->n_erased_blocks = swap_s32(cp->n_erased_blocks); ++ cp->alloc_block = swap_s32(cp->alloc_block); ++ cp->alloc_page = swap_u32(cp->alloc_page); ++ cp->n_free_chunks = swap_s32(cp->n_free_chunks); ++ cp->n_deleted_files = swap_s32(cp->n_deleted_files); ++ cp->n_unlinked_files = swap_s32(cp->n_unlinked_files); ++ cp->n_bg_deletions = swap_s32(cp->n_bg_deletions); ++} ++ ++static int yaffs2_wr_checkpt_dev(struct yaffs_dev *dev) ++{ ++ struct yaffs_checkpt_dev cp; ++ u32 n_bytes; ++ u32 n_blocks = dev->internal_end_block - dev->internal_start_block + 1; ++ int ok; ++ u32 i; ++ union yaffs_block_info_union bu; ++ ++ /* Write device runtime values */ ++ yaffs2_dev_to_checkpt_dev(&cp, dev); ++ yaffs2_do_endian_checkpt_dev(dev, &cp); ++ ++ ok = (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp)); ++ if (!ok) ++ return 0; ++ ++ /* Write block info. */ ++ if (!dev->swap_endian) { ++ n_bytes = n_blocks * sizeof(struct yaffs_block_info); ++ ok = (yaffs2_checkpt_wr(dev, dev->block_info, n_bytes) == ++ (int)n_bytes); ++ } else { ++ /* ++ * Need to swap the endianisms. We can't do this in place ++ * since that would damage live data, ++ * so write one block info at a time using a copy. ++ */ ++ for (i = 0; i < n_blocks && ok; i++) { ++ bu.bi = dev->block_info[i]; ++ bu.as_u32[0] = swap_u32(bu.as_u32[0]); ++ bu.as_u32[1] = swap_u32(bu.as_u32[1]); ++ ok = (yaffs2_checkpt_wr(dev, &bu, sizeof(bu)) == sizeof(bu)); ++ } ++ } ++ ++ if (!ok) ++ return 0; ++ ++ /* ++ * Write chunk bits. Chunk bits are in bytes so ++ * no endian conversion is needed. ++ */ ++ n_bytes = n_blocks * dev->chunk_bit_stride; ++ ok = (yaffs2_checkpt_wr(dev, dev->chunk_bits, n_bytes) == ++ (int)n_bytes); ++ ++ return ok ? 1 : 0; ++} ++ ++static int yaffs2_rd_checkpt_dev(struct yaffs_dev *dev) ++{ ++ struct yaffs_checkpt_dev cp; ++ u32 n_bytes; ++ u32 n_blocks = ++ (dev->internal_end_block - dev->internal_start_block + 1); ++ int ok; ++ ++ ok = (yaffs2_checkpt_rd(dev, &cp, sizeof(cp)) == sizeof(cp)); ++ if (!ok) ++ return 0; ++ yaffs2_do_endian_checkpt_dev(dev, &cp); ++ ++ if (cp.struct_type != sizeof(cp)) ++ return 0; ++ ++ yaffs_checkpt_dev_to_dev(dev, &cp); ++ ++ n_bytes = n_blocks * sizeof(struct yaffs_block_info); ++ ++ ok = (yaffs2_checkpt_rd(dev, dev->block_info, n_bytes) == ++ (int)n_bytes); ++ ++ if (!ok) ++ return 0; ++ ++ if (dev->swap_endian) { ++ /* The block info can just be handled as a list of u32s. */ ++ u32 *as_u32 = (u32 *) dev->block_info; ++ u32 n_u32s = n_bytes/sizeof(u32); ++ u32 i; ++ ++ for (i=0; i < n_u32s; i++) ++ as_u32[i] = swap_u32(as_u32[i]); ++ } ++ ++ n_bytes = n_blocks * dev->chunk_bit_stride; ++ ++ ok = (yaffs2_checkpt_rd(dev, dev->chunk_bits, n_bytes) == ++ (int)n_bytes); ++ ++ ++ return ok ? 1 : 0; ++} ++ ++ ++static void yaffs2_checkpt_obj_bit_assign(struct yaffs_checkpt_obj *cp, ++ int bit_offset, ++ int bit_width, ++ u32 value) ++{ ++ u32 and_mask; ++ ++ and_mask = ((1<bit_field &= ~and_mask; ++ cp->bit_field |= ((value << bit_offset) & and_mask); ++} ++ ++static u32 yaffs2_checkpt_obj_bit_get(struct yaffs_checkpt_obj *cp, ++ int bit_offset, ++ int bit_width) ++{ ++ u32 and_mask; ++ ++ and_mask = ((1<bit_field >> bit_offset) & and_mask; ++} ++ ++static void yaffs2_obj_checkpt_obj(struct yaffs_checkpt_obj *cp, ++ struct yaffs_obj *obj) ++{ ++ cp->obj_id = obj->obj_id; ++ cp->parent_id = (obj->parent) ? obj->parent->obj_id : 0; ++ cp->hdr_chunk = obj->hdr_chunk; ++ ++ yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_VARIANT_BITS, obj->variant_type); ++ yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_DELETED_BITS, obj->deleted); ++ yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_SOFT_DEL_BITS, obj->soft_del); ++ yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_UNLINKED_BITS, obj->unlinked); ++ yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_FAKE_BITS, obj->fake); ++ yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_RENAME_ALLOWED_BITS, obj->rename_allowed); ++ yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_UNLINK_ALLOWED_BITS, obj->unlink_allowed); ++ yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_SERIAL_BITS, obj->serial); ++ ++ cp->n_data_chunks = obj->n_data_chunks; ++ ++ if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE) ++ cp->size_or_equiv_obj = obj->variant.file_variant.file_size; ++ else if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK) ++ cp->size_or_equiv_obj = obj->variant.hardlink_variant.equiv_id; ++} ++ ++static int yaffs2_checkpt_obj_to_obj(struct yaffs_obj *obj, ++ struct yaffs_checkpt_obj *cp) ++{ ++ struct yaffs_obj *parent; ++ u32 cp_variant_type = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_VARIANT_BITS); ++ ++ if (obj->variant_type != cp_variant_type) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "Checkpoint read object %d type %d chunk %d does not match existing object type %d", ++ cp->obj_id, cp_variant_type, cp->hdr_chunk, ++ obj->variant_type); ++ return 0; ++ } ++ ++ obj->obj_id = cp->obj_id; ++ ++ if (cp->parent_id) ++ parent = yaffs_find_or_create_by_number(obj->my_dev, ++ cp->parent_id, ++ YAFFS_OBJECT_TYPE_DIRECTORY); ++ else ++ parent = NULL; ++ ++ if (parent) { ++ if (parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "Checkpoint read object %d parent %d type %d chunk %d Parent type, %d, not directory", ++ cp->obj_id, cp->parent_id, ++ cp_variant_type, cp->hdr_chunk, ++ parent->variant_type); ++ return 0; ++ } ++ yaffs_add_obj_to_dir(parent, obj); ++ } ++ ++ obj->hdr_chunk = cp->hdr_chunk; ++ ++ obj->variant_type = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_VARIANT_BITS); ++ obj->deleted = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_DELETED_BITS); ++ obj->soft_del = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_SOFT_DEL_BITS); ++ obj->unlinked = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_UNLINKED_BITS); ++ obj->fake = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_FAKE_BITS); ++ obj->rename_allowed = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_RENAME_ALLOWED_BITS); ++ obj->unlink_allowed = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_UNLINK_ALLOWED_BITS); ++ obj->serial = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_SERIAL_BITS); ++ ++ obj->n_data_chunks = cp->n_data_chunks; ++ ++ if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE) { ++ obj->variant.file_variant.file_size = cp->size_or_equiv_obj; ++ obj->variant.file_variant.stored_size = cp->size_or_equiv_obj; ++ } else if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK) { ++ obj->variant.hardlink_variant.equiv_id = cp->size_or_equiv_obj; ++ } ++ if (obj->hdr_chunk > 0) ++ obj->lazy_loaded = 1; ++ return 1; ++} ++ ++static void yaffs2_do_endian_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn) ++{ ++ int i; ++ u32 *as_u32 = (u32 *)tn; ++ int tnode_size_u32 = dev->tnode_size / sizeof(u32); ++ ++ if (!dev->swap_endian) ++ return; ++ /* Swap all the tnode data as u32s to fix endianisms. */ ++ for (i = 0; iswap_endian) ++ return tn; ++ ++ memcpy(dev->tn_swap_buffer, tn, dev->tnode_size); ++ tn = dev->tn_swap_buffer; ++ ++ yaffs2_do_endian_tnode(dev, tn); ++ ++ return tn; ++} ++ ++static int yaffs2_checkpt_tnode_worker(struct yaffs_obj *in, ++ struct yaffs_tnode *tn, u32 level, ++ int chunk_offset) ++{ ++ int i; ++ struct yaffs_dev *dev = in->my_dev; ++ int ok = 1; ++ u32 base_offset; ++ ++ if (!tn) ++ return 1; ++ ++ if (level > 0) { ++ for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++) { ++ if (!tn->internal[i]) ++ continue; ++ ok = yaffs2_checkpt_tnode_worker(in, ++ tn->internal[i], ++ level - 1, ++ (chunk_offset << ++ YAFFS_TNODES_INTERNAL_BITS) + i); ++ } ++ return ok; ++ } ++ ++ /* Level 0 tnode */ ++ base_offset = chunk_offset << YAFFS_TNODES_LEVEL0_BITS; ++ yaffs_do_endian_u32(dev, &base_offset); ++ ++ ok = (yaffs2_checkpt_wr(dev, &base_offset, sizeof(base_offset)) == ++ sizeof(base_offset)); ++ if (ok) { ++ /* ++ * NB Can't do an in-place endian swizzle since that would ++ * damage current tnode data. ++ * If a tnode endian conversion is required we do a copy. ++ */ ++ tn = yaffs2_do_endian_tnode_copy(dev, tn); ++ ok = (yaffs2_checkpt_wr(dev, tn, dev->tnode_size) == ++ (int)dev->tnode_size); ++ } ++ return ok; ++} ++ ++static int yaffs2_wr_checkpt_tnodes(struct yaffs_obj *obj) ++{ ++ u32 end_marker = ~0; ++ int ok = 1; ++ ++ if (obj->variant_type != YAFFS_OBJECT_TYPE_FILE) ++ return ok; ++ ++ ok = yaffs2_checkpt_tnode_worker(obj, ++ obj->variant.file_variant.top, ++ obj->variant.file_variant. ++ top_level, 0); ++ if (ok) ++ ok = (yaffs2_checkpt_wr(obj->my_dev, &end_marker, ++ sizeof(end_marker)) == sizeof(end_marker)); ++ ++ return ok ? 1 : 0; ++} ++ ++static int yaffs2_rd_checkpt_tnodes(struct yaffs_obj *obj) ++{ ++ u32 base_chunk; ++ int ok = 1; ++ struct yaffs_dev *dev = obj->my_dev; ++ struct yaffs_file_var *file_stuct_ptr = &obj->variant.file_variant; ++ struct yaffs_tnode *tn; ++ int nread = 0; ++ ++ ok = (yaffs2_checkpt_rd(dev, &base_chunk, sizeof(base_chunk)) == ++ sizeof(base_chunk)); ++ ++ yaffs_do_endian_u32(dev, &base_chunk); ++ ++ while (ok && (~base_chunk)) { ++ nread++; ++ /* Read level 0 tnode */ ++ ++ tn = yaffs_get_tnode(dev); ++ if (tn) { ++ ok = (yaffs2_checkpt_rd(dev, tn, dev->tnode_size) == ++ (int)dev->tnode_size); ++ yaffs2_do_endian_tnode(dev, tn); ++ } ++ else ++ ok = 0; ++ ++ if (tn && ok) ++ ok = yaffs_add_find_tnode_0(dev, ++ file_stuct_ptr, ++ base_chunk, tn) ? 1 : 0; ++ ++ if (ok) { ++ ok = (yaffs2_checkpt_rd ++ (dev, &base_chunk, ++ sizeof(base_chunk)) == sizeof(base_chunk)); ++ yaffs_do_endian_u32(dev, &base_chunk); ++ } ++ ++ } ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "Checkpoint read tnodes %d records, last %d. ok %d", ++ nread, base_chunk, ok); ++ ++ return ok ? 1 : 0; ++} ++ ++ ++static void yaffs2_do_endian_checkpt_obj(struct yaffs_dev *dev, ++ struct yaffs_checkpt_obj *cp) ++{ ++ if (!dev->swap_endian) ++ return; ++ cp->struct_type = swap_s32(cp->struct_type); ++ cp->obj_id = swap_u32(cp->obj_id); ++ cp->parent_id = swap_u32(cp->parent_id); ++ cp->hdr_chunk = swap_s32(cp->hdr_chunk); ++ cp->bit_field = swap_u32(cp->bit_field); ++ cp->n_data_chunks = swap_s32(cp->n_data_chunks); ++ cp->size_or_equiv_obj = swap_loff_t(cp->size_or_equiv_obj); ++} ++ ++static int yaffs2_wr_checkpt_objs(struct yaffs_dev *dev) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_checkpt_obj cp; ++ int i; ++ int ok = 1; ++ struct list_head *lh; ++ u32 cp_variant_type; ++ ++ /* Iterate through the objects in each hash entry, ++ * dumping them to the checkpointing stream. ++ */ ++ ++ for (i = 0; ok && i < YAFFS_NOBJECT_BUCKETS; i++) { ++ list_for_each(lh, &dev->obj_bucket[i].list) { ++ obj = list_entry(lh, struct yaffs_obj, hash_link); ++ if (!obj->defered_free) { ++ yaffs2_obj_checkpt_obj(&cp, obj); ++ cp.struct_type = sizeof(cp); ++ cp_variant_type = yaffs2_checkpt_obj_bit_get( ++ &cp, CHECKPOINT_VARIANT_BITS); ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "Checkpoint write object %d parent %d type %d chunk %d obj addr %p", ++ cp.obj_id, cp.parent_id, ++ cp_variant_type, cp.hdr_chunk, obj); ++ ++ yaffs2_do_endian_checkpt_obj (dev, &cp); ++ ok = (yaffs2_checkpt_wr(dev, &cp, ++ sizeof(cp)) == sizeof(cp)); ++ ++ if (ok && ++ obj->variant_type == ++ YAFFS_OBJECT_TYPE_FILE) ++ ok = yaffs2_wr_checkpt_tnodes(obj); ++ } ++ } ++ } ++ ++ /* Dump end of list */ ++ memset(&cp, 0xff, sizeof(struct yaffs_checkpt_obj)); ++ cp.struct_type = sizeof(cp); ++ yaffs2_do_endian_checkpt_obj (dev, &cp); ++ ++ if (ok) ++ ok = (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp)); ++ ++ return ok ? 1 : 0; ++} ++ ++static int yaffs2_rd_checkpt_objs(struct yaffs_dev *dev) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_checkpt_obj cp; ++ int ok = 1; ++ int done = 0; ++ u32 cp_variant_type; ++ LIST_HEAD(hard_list); ++ ++ ++ while (ok && !done) { ++ ok = (yaffs2_checkpt_rd(dev, &cp, sizeof(cp)) == sizeof(cp)); ++ yaffs2_do_endian_checkpt_obj (dev, &cp); ++ ++ if (cp.struct_type != sizeof(cp)) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "struct size %d instead of %d ok %d", ++ cp.struct_type, (int)sizeof(cp), ok); ++ ok = 0; ++ } ++ ++ cp_variant_type = yaffs2_checkpt_obj_bit_get( ++ &cp, CHECKPOINT_VARIANT_BITS); ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "Checkpoint read object %d parent %d type %d chunk %d ", ++ cp.obj_id, cp.parent_id, cp_variant_type, ++ cp.hdr_chunk); ++ ++ if (ok && cp.obj_id == (u32)(~0)) { ++ done = 1; ++ } else if (ok) { ++ obj = ++ yaffs_find_or_create_by_number(dev, cp.obj_id, ++ cp_variant_type); ++ if (obj) { ++ ok = yaffs2_checkpt_obj_to_obj(obj, &cp); ++ if (!ok) ++ break; ++ if (obj->variant_type == ++ YAFFS_OBJECT_TYPE_FILE) { ++ ok = yaffs2_rd_checkpt_tnodes(obj); ++ } else if (obj->variant_type == ++ YAFFS_OBJECT_TYPE_HARDLINK) { ++ list_add(&obj->hard_links, &hard_list); ++ } ++ } else { ++ ok = 0; ++ } ++ } ++ } ++ ++ if (ok) ++ yaffs_link_fixup(dev, &hard_list); ++ ++ return ok ? 1 : 0; ++} ++ ++static int yaffs2_wr_checkpt_sum(struct yaffs_dev *dev) ++{ ++ u32 checkpt_sum; ++ int ok; ++ ++ yaffs2_get_checkpt_sum(dev, &checkpt_sum); ++ ++ yaffs_do_endian_u32(dev, &checkpt_sum); ++ ++ ok = (yaffs2_checkpt_wr(dev, &checkpt_sum, sizeof(checkpt_sum)) == ++ sizeof(checkpt_sum)); ++ ++ if (!ok) ++ return 0; ++ ++ return 1; ++} ++ ++static int yaffs2_rd_checkpt_sum(struct yaffs_dev *dev) ++{ ++ u32 checkpt_sum0; ++ u32 checkpt_sum1; ++ int ok; ++ ++ yaffs2_get_checkpt_sum(dev, &checkpt_sum0); ++ ++ ok = (yaffs2_checkpt_rd(dev, &checkpt_sum1, sizeof(checkpt_sum1)) == ++ sizeof(checkpt_sum1)); ++ ++ if (!ok) ++ return 0; ++ yaffs_do_endian_u32(dev, &checkpt_sum1); ++ ++ if (checkpt_sum0 != checkpt_sum1) ++ return 0; ++ ++ return 1; ++} ++ ++static int yaffs2_wr_checkpt_data(struct yaffs_dev *dev) ++{ ++ int ok = 1; ++ ++ if (!yaffs2_checkpt_required(dev)) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "skipping checkpoint write"); ++ ok = 0; ++ } ++ ++ if (ok) ++ ok = yaffs2_checkpt_open(dev, 1); ++ ++ if (ok) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "write checkpoint validity"); ++ ok = yaffs2_wr_checkpt_validity_marker(dev, 1); ++ } ++ if (ok) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "write checkpoint device"); ++ ok = yaffs2_wr_checkpt_dev(dev); ++ } ++ if (ok) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "write checkpoint objects"); ++ ok = yaffs2_wr_checkpt_objs(dev); ++ } ++ if (ok) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "write checkpoint validity"); ++ ok = yaffs2_wr_checkpt_validity_marker(dev, 0); ++ } ++ ++ if (ok) ++ ok = yaffs2_wr_checkpt_sum(dev); ++ ++ if (!yaffs_checkpt_close(dev)) ++ ok = 0; ++ ++ if (ok) ++ dev->is_checkpointed = 1; ++ else ++ dev->is_checkpointed = 0; ++ ++ return dev->is_checkpointed; ++} ++ ++static int yaffs2_rd_checkpt_data(struct yaffs_dev *dev) ++{ ++ int ok = 1; ++ ++ if (!dev->param.is_yaffs2) ++ ok = 0; ++ ++ if (ok && dev->param.skip_checkpt_rd) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "skipping checkpoint read"); ++ ok = 0; ++ } ++ ++ if (ok) ++ ok = yaffs2_checkpt_open(dev, 0); /* open for read */ ++ ++ if (ok) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "read checkpoint validity"); ++ ok = yaffs2_rd_checkpt_validity_marker(dev, 1); ++ } ++ if (ok) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "read checkpoint device"); ++ ok = yaffs2_rd_checkpt_dev(dev); ++ } ++ if (ok) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "read checkpoint objects"); ++ ok = yaffs2_rd_checkpt_objs(dev); ++ } ++ if (ok) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "read checkpoint validity"); ++ ok = yaffs2_rd_checkpt_validity_marker(dev, 0); ++ } ++ ++ if (ok) { ++ ok = yaffs2_rd_checkpt_sum(dev); ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "read checkpoint checksum %d", ok); ++ } ++ ++ if (!yaffs_checkpt_close(dev)) ++ ok = 0; ++ ++ if (ok) ++ dev->is_checkpointed = 1; ++ else ++ dev->is_checkpointed = 0; ++ ++ return ok ? 1 : 0; ++} ++ ++void yaffs2_checkpt_invalidate(struct yaffs_dev *dev) ++{ ++ if (dev->is_checkpointed || dev->blocks_in_checkpt > 0) { ++ dev->is_checkpointed = 0; ++ yaffs2_checkpt_invalidate_stream(dev); ++ } ++ if (dev->param.sb_dirty_fn) ++ dev->param.sb_dirty_fn(dev); ++} ++ ++int yaffs_checkpoint_save(struct yaffs_dev *dev) ++{ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "save entry: is_checkpointed %d", ++ dev->is_checkpointed); ++ ++ yaffs_verify_objects(dev); ++ yaffs_verify_blocks(dev); ++ yaffs_verify_free_chunks(dev); ++ ++ if (!dev->is_checkpointed) { ++ yaffs2_checkpt_invalidate(dev); ++ yaffs2_wr_checkpt_data(dev); ++ } ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT | YAFFS_TRACE_MOUNT, ++ "save exit: is_checkpointed %d", ++ dev->is_checkpointed); ++ ++ return dev->is_checkpointed; ++} ++ ++int yaffs2_checkpt_restore(struct yaffs_dev *dev) ++{ ++ int retval; ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "restore entry: is_checkpointed %d", ++ dev->is_checkpointed); ++ ++ retval = yaffs2_rd_checkpt_data(dev); ++ ++ if (dev->is_checkpointed) { ++ yaffs_verify_objects(dev); ++ yaffs_verify_blocks(dev); ++ yaffs_verify_free_chunks(dev); ++ } ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "restore exit: is_checkpointed %d", ++ dev->is_checkpointed); ++ ++ return retval; ++} ++ ++/* End of checkpointing */ ++ ++/* Hole handling logic for truncate past end of file */ ++ ++int yaffs2_handle_hole(struct yaffs_obj *obj, loff_t new_size) ++{ ++ /* if new_size > old_file_size. ++ * We're going to be writing a hole. ++ * If the hole is small then write zeros otherwise write a start ++ * of hole marker. ++ */ ++ loff_t old_file_size; ++ loff_t increase; ++ int small_hole; ++ int result = YAFFS_OK; ++ struct yaffs_dev *dev = NULL; ++ u8 *local_buffer = NULL; ++ int small_increase_ok = 0; ++ ++ if (!obj) ++ return YAFFS_FAIL; ++ ++ if (obj->variant_type != YAFFS_OBJECT_TYPE_FILE) ++ return YAFFS_FAIL; ++ ++ dev = obj->my_dev; ++ ++ /* Bail out if not yaffs2 mode */ ++ if (!dev->param.is_yaffs2) ++ return YAFFS_OK; ++ ++ old_file_size = obj->variant.file_variant.file_size; ++ ++ if (new_size <= old_file_size) ++ return YAFFS_OK; ++ ++ increase = new_size - old_file_size; ++ ++ if (increase < YAFFS_SMALL_HOLE_THRESHOLD * dev->data_bytes_per_chunk && ++ yaffs_check_alloc_available(dev, YAFFS_SMALL_HOLE_THRESHOLD + 1)) ++ small_hole = 1; ++ else ++ small_hole = 0; ++ ++ if (small_hole) ++ local_buffer = yaffs_get_temp_buffer(dev); ++ ++ if (local_buffer) { ++ /* fill hole with zero bytes */ ++ loff_t pos = old_file_size; ++ int this_write; ++ int written; ++ memset(local_buffer, 0, dev->data_bytes_per_chunk); ++ small_increase_ok = 1; ++ ++ while (increase > 0 && small_increase_ok) { ++ this_write = increase; ++ if (this_write > (int)dev->data_bytes_per_chunk) ++ this_write = dev->data_bytes_per_chunk; ++ written = ++ yaffs_do_file_wr(obj, local_buffer, pos, this_write, ++ 0); ++ if (written == this_write) { ++ pos += this_write; ++ increase -= this_write; ++ } else { ++ small_increase_ok = 0; ++ } ++ } ++ ++ yaffs_release_temp_buffer(dev, local_buffer); ++ ++ /* If out of space then reverse any chunks we've added */ ++ if (!small_increase_ok) ++ yaffs_resize_file_down(obj, old_file_size); ++ } ++ ++ if (!small_increase_ok && ++ obj->parent && ++ obj->parent->obj_id != YAFFS_OBJECTID_UNLINKED && ++ obj->parent->obj_id != YAFFS_OBJECTID_DELETED) { ++ /* Write a hole start header with the old file size */ ++ yaffs_update_oh(obj, NULL, 0, 1, 0, NULL); ++ } ++ ++ return result; ++} ++ ++/* Yaffs2 scanning */ ++ ++struct yaffs_block_index { ++ int seq; ++ int block; ++}; ++ ++static int yaffs2_ybicmp(const void *a, const void *b) ++{ ++ int aseq = ((struct yaffs_block_index *)a)->seq; ++ int bseq = ((struct yaffs_block_index *)b)->seq; ++ int ablock = ((struct yaffs_block_index *)a)->block; ++ int bblock = ((struct yaffs_block_index *)b)->block; ++ ++ if (aseq == bseq) ++ return ablock - bblock; ++ ++ return aseq - bseq; ++} ++ ++static inline int yaffs2_scan_chunk(struct yaffs_dev *dev, ++ struct yaffs_block_info *bi, ++ int blk, int chunk_in_block, ++ int *found_chunks, ++ u8 *chunk_data, ++ struct list_head *hard_list, ++ int summary_available) ++{ ++ struct yaffs_obj_hdr *oh; ++ struct yaffs_obj *in; ++ struct yaffs_obj *parent; ++ int equiv_id; ++ loff_t file_size; ++ int is_shrink; ++ int is_unlinked; ++ struct yaffs_ext_tags tags; ++ int result; ++ int alloc_failed = 0; ++ int chunk = blk * dev->param.chunks_per_block + chunk_in_block; ++ struct yaffs_file_var *file_var; ++ struct yaffs_hardlink_var *hl_var; ++ struct yaffs_symlink_var *sl_var; ++ ++ if (summary_available) { ++ result = yaffs_summary_fetch(dev, &tags, chunk_in_block); ++ tags.seq_number = bi->seq_number; ++ } ++ ++ if (!summary_available || tags.obj_id == 0) { ++ result = yaffs_rd_chunk_tags_nand(dev, chunk, NULL, &tags); ++ dev->tags_used++; ++ } else { ++ dev->summary_used++; ++ } ++ ++ if (result == YAFFS_FAIL) ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ "Could not get tags for chunk %d\n", chunk); ++ /* Let's have a good look at this chunk... */ ++ ++ if (!tags.chunk_used) { ++ /* An unassigned chunk in the block. ++ * If there are used chunks after this one, then ++ * it is a chunk that was skipped due to failing ++ * the erased check. Just skip it so that it can ++ * be deleted. ++ * But, more typically, We get here when this is ++ * an unallocated chunk and his means that ++ * either the block is empty or this is the one ++ * being allocated from ++ */ ++ ++ if (*found_chunks) { ++ /* This is a chunk that was skipped due ++ * to failing the erased check */ ++ } else if (chunk_in_block == 0) { ++ /* We're looking at the first chunk in ++ * the block so the block is unused */ ++ bi->block_state = YAFFS_BLOCK_STATE_EMPTY; ++ dev->n_erased_blocks++; ++ } else { ++ if (bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN || ++ bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING) { ++ if (dev->seq_number == bi->seq_number) { ++ /* Allocating from this block*/ ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ " Allocating from %d %d", ++ blk, chunk_in_block); ++ ++ bi->block_state = ++ YAFFS_BLOCK_STATE_ALLOCATING; ++ dev->alloc_block = blk; ++ dev->alloc_page = chunk_in_block; ++ dev->alloc_block_finder = blk; ++ } else { ++ /* This is a partially written block ++ * that is not the current ++ * allocation block. ++ */ ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ "Partially written block %d detected. gc will fix this.", ++ blk); ++ } ++ } ++ } ++ ++ dev->n_free_chunks++; ++ ++ } else if (tags.ecc_result == ++ YAFFS_ECC_RESULT_UNFIXED) { ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ " Unfixed ECC in chunk(%d:%d), chunk ignored", ++ blk, chunk_in_block); ++ dev->n_free_chunks++; ++ } else if (tags.obj_id > YAFFS_MAX_OBJECT_ID || ++ tags.chunk_id > YAFFS_MAX_CHUNK_ID || ++ tags.obj_id == YAFFS_OBJECTID_SUMMARY || ++ (tags.chunk_id > 0 && ++ tags.n_bytes > dev->data_bytes_per_chunk) || ++ tags.seq_number != bi->seq_number) { ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ "Chunk (%d:%d) with bad tags:obj = %d, chunk_id = %d, n_bytes = %d, ignored", ++ blk, chunk_in_block, tags.obj_id, ++ tags.chunk_id, tags.n_bytes); ++ dev->n_free_chunks++; ++ } else if (tags.chunk_id > 0) { ++ /* chunk_id > 0 so it is a data chunk... */ ++ loff_t endpos; ++ loff_t chunk_base = (tags.chunk_id - 1) * ++ dev->data_bytes_per_chunk; ++ ++ *found_chunks = 1; ++ ++ yaffs_set_chunk_bit(dev, blk, chunk_in_block); ++ bi->pages_in_use++; ++ ++ in = yaffs_find_or_create_by_number(dev, ++ tags.obj_id, ++ YAFFS_OBJECT_TYPE_FILE); ++ if (!in) ++ /* Out of memory */ ++ alloc_failed = 1; ++ ++ if (in && ++ in->variant_type == YAFFS_OBJECT_TYPE_FILE && ++ chunk_base < in->variant.file_variant.shrink_size) { ++ /* This has not been invalidated by ++ * a resize */ ++ if (!yaffs_put_chunk_in_file(in, tags.chunk_id, ++ chunk, -1)) ++ alloc_failed = 1; ++ ++ /* File size is calculated by looking at ++ * the data chunks if we have not ++ * seen an object header yet. ++ * Stop this practice once we find an ++ * object header. ++ */ ++ endpos = chunk_base + tags.n_bytes; ++ ++ if (!in->valid && ++ in->variant.file_variant.stored_size < endpos) { ++ in->variant.file_variant. ++ stored_size = endpos; ++ in->variant.file_variant. ++ file_size = endpos; ++ } ++ } else if (in) { ++ /* This chunk has been invalidated by a ++ * resize, or a past file deletion ++ * so delete the chunk*/ ++ yaffs_chunk_del(dev, chunk, 1, __LINE__); ++ } ++ } else { ++ /* chunk_id == 0, so it is an ObjectHeader. ++ * Thus, we read in the object header and make ++ * the object ++ */ ++ *found_chunks = 1; ++ ++ yaffs_set_chunk_bit(dev, blk, chunk_in_block); ++ bi->pages_in_use++; ++ ++ oh = NULL; ++ in = NULL; ++ ++ if (tags.extra_available) { ++ in = yaffs_find_or_create_by_number(dev, ++ tags.obj_id, ++ tags.extra_obj_type); ++ if (!in) ++ alloc_failed = 1; ++ } ++ ++ if (!in || ++ (!in->valid && dev->param.disable_lazy_load) || ++ tags.extra_shadows || ++ (!in->valid && (tags.obj_id == YAFFS_OBJECTID_ROOT || ++ tags.obj_id == YAFFS_OBJECTID_LOSTNFOUND))) { ++ ++ /* If we don't have valid info then we ++ * need to read the chunk ++ * TODO In future we can probably defer ++ * reading the chunk and living with ++ * invalid data until needed. ++ */ ++ ++ result = yaffs_rd_chunk_tags_nand(dev, ++ chunk, ++ chunk_data, ++ NULL); ++ ++ oh = (struct yaffs_obj_hdr *)chunk_data; ++ ++ yaffs_do_endian_oh(dev, oh); ++ ++ if (dev->param.inband_tags) { ++ /* Fix up the header if they got ++ * corrupted by inband tags */ ++ oh->shadows_obj = ++ oh->inband_shadowed_obj_id; ++ oh->is_shrink = ++ oh->inband_is_shrink; ++ } ++ ++ if (!in) { ++ in = yaffs_find_or_create_by_number(dev, ++ tags.obj_id, oh->type); ++ if (!in) ++ alloc_failed = 1; ++ } ++ } ++ ++ if (!in) { ++ /* TODO Hoosterman we have a problem! */ ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs tragedy: Could not make object for object %d at chunk %d during scan", ++ tags.obj_id, chunk); ++ return YAFFS_FAIL; ++ } ++ ++ if (in->valid) { ++ /* We have already filled this one. ++ * We have a duplicate that will be ++ * discarded, but we first have to suck ++ * out resize info if it is a file. ++ */ ++ if ((in->variant_type == YAFFS_OBJECT_TYPE_FILE) && ++ ((oh && oh->type == YAFFS_OBJECT_TYPE_FILE) || ++ (tags.extra_available && ++ tags.extra_obj_type == YAFFS_OBJECT_TYPE_FILE) ++ )) { ++ loff_t this_size = (oh) ? ++ yaffs_oh_to_size(dev, oh, 0) : ++ tags.extra_file_size; ++ u32 parent_obj_id = (oh) ? ++ (u32)oh->parent_obj_id : ++ tags.extra_parent_id; ++ ++ is_shrink = (oh) ? ++ oh->is_shrink : ++ tags.extra_is_shrink; ++ ++ /* If it is deleted (unlinked ++ * at start also means deleted) ++ * we treat the file size as ++ * being zeroed at this point. ++ */ ++ if (parent_obj_id == YAFFS_OBJECTID_DELETED || ++ parent_obj_id == YAFFS_OBJECTID_UNLINKED) { ++ this_size = 0; ++ is_shrink = 1; ++ } ++ ++ if (is_shrink && ++ in->variant.file_variant.shrink_size > ++ this_size) ++ in->variant.file_variant.shrink_size = ++ this_size; ++ ++ if (is_shrink) ++ bi->has_shrink_hdr = 1; ++ } ++ /* Use existing - destroy this one. */ ++ yaffs_chunk_del(dev, chunk, 1, __LINE__); ++ } ++ ++ if (!in->valid && in->variant_type != ++ (oh ? oh->type : tags.extra_obj_type)) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs tragedy: Bad type, %d != %d, for object %d at chunk %d during scan", ++ oh ? oh->type : tags.extra_obj_type, ++ in->variant_type, tags.obj_id, ++ chunk); ++ in = yaffs_retype_obj(in, oh ? oh->type : tags.extra_obj_type); ++ } ++ ++ if (!in->valid && ++ (tags.obj_id == YAFFS_OBJECTID_ROOT || ++ tags.obj_id == YAFFS_OBJECTID_LOSTNFOUND)) { ++ /* We only load some info, don't fiddle ++ * with directory structure */ ++ in->valid = 1; ++ ++ if (oh) { ++ in->yst_mode = oh->yst_mode; ++ yaffs_load_attribs(in, oh); ++ in->lazy_loaded = 0; ++ } else { ++ in->lazy_loaded = 1; ++ } ++ in->hdr_chunk = chunk; ++ ++ } else if (!in->valid) { ++ /* we need to load this info */ ++ in->valid = 1; ++ in->hdr_chunk = chunk; ++ if (oh) { ++ in->variant_type = oh->type; ++ in->yst_mode = oh->yst_mode; ++ yaffs_load_attribs(in, oh); ++ ++ if (oh->shadows_obj > 0) ++ yaffs_handle_shadowed_obj(dev, ++ oh->shadows_obj, 1); ++ ++ yaffs_set_obj_name_from_oh(in, oh); ++ parent = yaffs_find_or_create_by_number(dev, ++ oh->parent_obj_id, ++ YAFFS_OBJECT_TYPE_DIRECTORY); ++ file_size = yaffs_oh_to_size(dev, oh, 0); ++ is_shrink = oh->is_shrink; ++ equiv_id = oh->equiv_id; ++ } else { ++ in->variant_type = tags.extra_obj_type; ++ parent = yaffs_find_or_create_by_number(dev, ++ tags.extra_parent_id, ++ YAFFS_OBJECT_TYPE_DIRECTORY); ++ file_size = tags.extra_file_size; ++ is_shrink = tags.extra_is_shrink; ++ equiv_id = tags.extra_equiv_id; ++ in->lazy_loaded = 1; ++ } ++ in->dirty = 0; ++ ++ if (!parent) ++ alloc_failed = 1; ++ ++ /* directory stuff... ++ * hook up to parent ++ */ ++ ++ if (parent && ++ parent->variant_type == YAFFS_OBJECT_TYPE_UNKNOWN) { ++ /* Set up as a directory */ ++ parent->variant_type = ++ YAFFS_OBJECT_TYPE_DIRECTORY; ++ INIT_LIST_HEAD(&parent-> ++ variant.dir_variant.children); ++ } else if (!parent || ++ parent->variant_type != ++ YAFFS_OBJECT_TYPE_DIRECTORY) { ++ /* Hoosterman, another problem.... ++ * Trying to use a non-directory as a directory ++ */ ++ ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found." ++ ); ++ parent = dev->lost_n_found; ++ } ++ yaffs_add_obj_to_dir(parent, in); ++ ++ is_unlinked = (parent == dev->del_dir) || ++ (parent == dev->unlinked_dir); ++ ++ if (is_shrink) ++ /* Mark the block */ ++ bi->has_shrink_hdr = 1; ++ ++ /* Note re hardlinks. ++ * Since we might scan a hardlink before its equivalent ++ * object is scanned we put them all in a list. ++ * After scanning is complete, we should have all the ++ * objects, so we run through this list and fix up all ++ * the chains. ++ */ ++ ++ switch (in->variant_type) { ++ case YAFFS_OBJECT_TYPE_UNKNOWN: ++ /* Todo got a problem */ ++ break; ++ case YAFFS_OBJECT_TYPE_FILE: ++ file_var = &in->variant.file_variant; ++ if (file_var->stored_size < file_size) { ++ /* This covers the case where the file ++ * size is greater than the data held. ++ * This will happen if the file is ++ * resized to be larger than its ++ * current data extents. ++ */ ++ file_var->file_size = file_size; ++ file_var->stored_size = file_size; ++ } ++ ++ if (file_var->shrink_size > file_size) ++ file_var->shrink_size = file_size; ++ ++ break; ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ hl_var = &in->variant.hardlink_variant; ++ if (!is_unlinked) { ++ hl_var->equiv_id = equiv_id; ++ list_add(&in->hard_links, hard_list); ++ } ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ /* Do nothing */ ++ break; ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ /* Do nothing */ ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ sl_var = &in->variant.symlink_variant; ++ if (oh) { ++ sl_var->alias = ++ yaffs_clone_str(oh->alias); ++ if (!sl_var->alias) ++ alloc_failed = 1; ++ } ++ break; ++ } ++ } ++ } ++ return alloc_failed ? YAFFS_FAIL : YAFFS_OK; ++} ++ ++int yaffs2_scan_backwards(struct yaffs_dev *dev) ++{ ++ u32 blk; ++ int block_iter; ++ int start_iter; ++ int end_iter; ++ int n_to_scan = 0; ++ enum yaffs_block_state state; ++ int c; ++ LIST_HEAD(hard_list); ++ struct yaffs_block_info *bi; ++ u32 seq_number; ++ int n_blocks = dev->internal_end_block - dev->internal_start_block + 1; ++ u8 *chunk_data; ++ int found_chunks; ++ int alloc_failed = 0; ++ struct yaffs_block_index *block_index = NULL; ++ int alt_block_index = 0; ++ int summary_available; ++ ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ "yaffs2_scan_backwards starts intstartblk %d intendblk %d...", ++ dev->internal_start_block, dev->internal_end_block); ++ ++ dev->seq_number = YAFFS_LOWEST_SEQUENCE_NUMBER; ++ ++ block_index = ++ kmalloc(n_blocks * sizeof(struct yaffs_block_index), GFP_NOFS); ++ ++ if (!block_index) { ++ block_index = ++ vmalloc(n_blocks * sizeof(struct yaffs_block_index)); ++ alt_block_index = 1; ++ } ++ ++ if (!block_index) { ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ "yaffs2_scan_backwards() could not allocate block index!" ++ ); ++ return YAFFS_FAIL; ++ } ++ ++ dev->blocks_in_checkpt = 0; ++ ++ chunk_data = yaffs_get_temp_buffer(dev); ++ ++ /* Scan all the blocks to determine their state */ ++ bi = dev->block_info; ++ for (blk = dev->internal_start_block; blk <= dev->internal_end_block; ++ blk++) { ++ yaffs_clear_chunk_bits(dev, blk); ++ bi->pages_in_use = 0; ++ bi->soft_del_pages = 0; ++ ++ yaffs_query_init_block_state(dev, blk, &state, &seq_number); ++ ++ bi->block_state = state; ++ bi->seq_number = seq_number; ++ ++ if (bi->seq_number == YAFFS_SEQUENCE_CHECKPOINT_DATA) ++ bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT; ++ if (bi->seq_number == YAFFS_SEQUENCE_BAD_BLOCK) ++ bi->block_state = YAFFS_BLOCK_STATE_DEAD; ++ ++ yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, ++ "Block scanning block %d state %d seq %d", ++ blk, bi->block_state, seq_number); ++ ++ if (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT) { ++ dev->blocks_in_checkpt++; ++ ++ } else if (bi->block_state == YAFFS_BLOCK_STATE_DEAD) { ++ yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, ++ "block %d is bad", blk); ++ } else if (bi->block_state == YAFFS_BLOCK_STATE_EMPTY) { ++ yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, "Block empty "); ++ dev->n_erased_blocks++; ++ dev->n_free_chunks += dev->param.chunks_per_block; ++ } else if (bi->block_state == ++ YAFFS_BLOCK_STATE_NEEDS_SCAN) { ++ /* Determine the highest sequence number */ ++ if (seq_number >= YAFFS_LOWEST_SEQUENCE_NUMBER && ++ seq_number < YAFFS_HIGHEST_SEQUENCE_NUMBER) { ++ block_index[n_to_scan].seq = seq_number; ++ block_index[n_to_scan].block = blk; ++ n_to_scan++; ++ if (seq_number >= dev->seq_number) ++ dev->seq_number = seq_number; ++ } else { ++ /* TODO: Nasty sequence number! */ ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ "Block scanning block %d has bad sequence number %d", ++ blk, seq_number); ++ } ++ } ++ bi++; ++ } ++ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "%d blocks to be sorted...", n_to_scan); ++ ++ cond_resched(); ++ ++ /* Sort the blocks by sequence number */ ++ sort(block_index, n_to_scan, sizeof(struct yaffs_block_index), ++ yaffs2_ybicmp, NULL); ++ ++ cond_resched(); ++ ++ yaffs_trace(YAFFS_TRACE_SCAN, "...done"); ++ ++ /* Now scan the blocks looking at the data. */ ++ start_iter = 0; ++ end_iter = n_to_scan - 1; ++ yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, "%d blocks to scan", n_to_scan); ++ ++ /* For each block.... backwards */ ++ for (block_iter = end_iter; ++ !alloc_failed && block_iter >= start_iter; ++ block_iter--) { ++ /* Cooperative multitasking! This loop can run for so ++ long that watchdog timers expire. */ ++ cond_resched(); ++ ++ /* get the block to scan in the correct order */ ++ blk = block_index[block_iter].block; ++ bi = yaffs_get_block_info(dev, blk); ++ ++ summary_available = yaffs_summary_read(dev, dev->sum_tags, blk); ++ ++ /* For each chunk in each block that needs scanning.... */ ++ found_chunks = 0; ++ if (summary_available) ++ c = dev->chunks_per_summary - 1; ++ else ++ c = dev->param.chunks_per_block - 1; ++ ++ for (/* c is already initialised */; ++ !alloc_failed && c >= 0 && ++ (bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN || ++ bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING); ++ c--) { ++ /* Scan backwards... ++ * Read the tags and decide what to do ++ */ ++ if (yaffs2_scan_chunk(dev, bi, blk, c, ++ &found_chunks, chunk_data, ++ &hard_list, summary_available) == ++ YAFFS_FAIL) ++ alloc_failed = 1; ++ } ++ ++ if (bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN) { ++ /* If we got this far while scanning, then the block ++ * is fully allocated. */ ++ bi->block_state = YAFFS_BLOCK_STATE_FULL; ++ } ++ ++ /* Now let's see if it was dirty */ ++ if (bi->pages_in_use == 0 && ++ !bi->has_shrink_hdr && ++ bi->block_state == YAFFS_BLOCK_STATE_FULL) { ++ yaffs_block_became_dirty(dev, blk); ++ } ++ } ++ ++ yaffs_skip_rest_of_block(dev); ++ ++ if (alt_block_index) ++ vfree(block_index); ++ else ++ kfree(block_index); ++ ++ /* Ok, we've done all the scanning. ++ * Fix up the hard link chains. ++ * We have scanned all the objects, now it's time to add these ++ * hardlinks. ++ */ ++ yaffs_link_fixup(dev, &hard_list); ++ ++ yaffs_release_temp_buffer(dev, chunk_data); ++ ++ if (alloc_failed) ++ return YAFFS_FAIL; ++ ++ yaffs_trace(YAFFS_TRACE_SCAN, "yaffs2_scan_backwards ends"); ++ ++ return YAFFS_OK; ++} +diff --git a/fs/yaffs2/yaffs_yaffs2.h b/fs/yaffs2/yaffs_yaffs2.h +new file mode 100644 +index 0000000..2363bfd +--- /dev/null ++++ b/fs/yaffs2/yaffs_yaffs2.h +@@ -0,0 +1,39 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_YAFFS2_H__ ++#define __YAFFS_YAFFS2_H__ ++ ++#include "yaffs_guts.h" ++ ++void yaffs_calc_oldest_dirty_seq(struct yaffs_dev *dev); ++void yaffs2_find_oldest_dirty_seq(struct yaffs_dev *dev); ++void yaffs2_clear_oldest_dirty_seq(struct yaffs_dev *dev, ++ struct yaffs_block_info *bi); ++void yaffs2_update_oldest_dirty_seq(struct yaffs_dev *dev, unsigned block_no, ++ struct yaffs_block_info *bi); ++int yaffs_block_ok_for_gc(struct yaffs_dev *dev, struct yaffs_block_info *bi); ++u32 yaffs2_find_refresh_block(struct yaffs_dev *dev); ++int yaffs2_checkpt_required(struct yaffs_dev *dev); ++int yaffs_calc_checkpt_blocks_required(struct yaffs_dev *dev); ++ ++void yaffs2_checkpt_invalidate(struct yaffs_dev *dev); ++int yaffs2_checkpt_save(struct yaffs_dev *dev); ++int yaffs2_checkpt_restore(struct yaffs_dev *dev); ++ ++int yaffs2_handle_hole(struct yaffs_obj *obj, loff_t new_size); ++int yaffs2_scan_backwards(struct yaffs_dev *dev); ++ ++#endif +diff --git a/fs/yaffs2/yportenv.h b/fs/yaffs2/yportenv.h +new file mode 100644 +index 0000000..8975af3 +--- /dev/null ++++ b/fs/yaffs2/yportenv.h +@@ -0,0 +1,85 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YPORTENV_H__ ++#define __YPORTENV_H__ ++ ++/* ++ * Define the MTD version in terms of Linux Kernel versions ++ * This allows yaffs to be used independantly of the kernel ++ * as well as with it. ++ */ ++ ++#define MTD_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c)) ++ ++#ifdef YAFFS_OUT_OF_TREE ++#include "moduleconfig.h" ++#endif ++ ++#include ++#define MTD_VERSION_CODE LINUX_VERSION_CODE ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)) ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* These type wrappings are used to support Unicode names in WinCE. */ ++#define YCHAR char ++#define YUCHAR unsigned char ++#define _Y(x) x ++ ++#define YAFFS_LOSTNFOUND_NAME "lost+found" ++#define YAFFS_LOSTNFOUND_PREFIX "obj" ++ ++ ++#define YAFFS_ROOT_MODE 0755 ++#define YAFFS_LOSTNFOUND_MODE 0700 ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++#define Y_CURRENT_TIME CURRENT_TIME.tv_sec ++#define Y_TIME_CONVERT(x) (x).tv_sec ++#else ++#define Y_CURRENT_TIME CURRENT_TIME ++#define Y_TIME_CONVERT(x) (x) ++#endif ++ ++#define compile_time_assertion(assertion) \ ++ ({ int x = __builtin_choose_expr(assertion, 0, (void)0); (void) x; }) ++ ++ ++#define yaffs_printf(msk, fmt, ...) \ ++ printk(KERN_DEBUG "yaffs: " fmt "\n", ##__VA_ARGS__) ++ ++#define yaffs_trace(msk, fmt, ...) do { \ ++ if (yaffs_trace_mask & (msk)) \ ++ printk(KERN_DEBUG "yaffs: " fmt "\n", ##__VA_ARGS__); \ ++} while (0) ++ ++ ++#endif +diff --git a/include/dt-bindings/clock/hi3516a-clock.h b/include/dt-bindings/clock/hi3516a-clock.h +new file mode 100644 +index 0000000..aa9bcd0 +--- /dev/null ++++ b/include/dt-bindings/clock/hi3516a-clock.h +@@ -0,0 +1,105 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef __DTS_HI3516A_CLOCK_H ++#define __DTS_HI3516A_CLOCK_H ++ ++/* clk in CRG */ ++/* fixed rate clocks */ ++#define HI3516A_INNER_CLK_OFFSET 64 ++#define HI3516A_FIXED_3M 65 ++#define HI3516A_FIXED_6M 66 ++#define HI3516A_FIXED_13P5M 67 ++#define HI3516A_FIXED_24M 68 ++#define HI3516A_FIXED_25M 69 ++#define HI3516A_FIXED_27M 70 ++#define HI3516A_FIXED_37P125M 71 ++#define HI3516A_FIXED_50M 72 ++#define HI3516A_FIXED_74P25M 73 ++#define HI3516A_FIXED_75M 74 ++#define HI3516A_FIXED_99M 75 ++#define HI3516A_FIXED_100M 76 ++#define HI3516A_FIXED_125M 77 ++#define HI3516A_FIXED_145M 78 ++#define HI3516A_FIXED_148P5M 79 ++#define HI3516A_FIXED_150M 80 ++#define HI3516A_FIXED_194M 81 ++#define HI3516A_FIXED_198M 82 ++#define HI3516A_FIXED_200M 83 ++#define HI3516A_FIXED_229M 84 ++#define HI3516A_FIXED_237M 85 ++#define HI3516A_FIXED_242M 86 ++#define HI3516A_FIXED_250M 87 ++#define HI3516A_FIXED_297M 88 ++#define HI3516A_FIXED_300M 89 ++#define HI3516A_FIXED_333M 90 ++#define HI3516A_FIXED_400M 91 ++#define HI3516A_FIXED_500M 92 ++#define HI3516A_FIXED_594M 93 ++#define HI3516A_FIXED_600M 94 ++#define HI3516A_FIXED_726P25M 95 ++#define HI3516A_FIXED_750M 96 ++#define HI3516A_FIXED_900M 97 ++#define HI3516A_FIXED_1000M 98 ++#define HI3516A_FIXED_1188M 99 ++ ++/* mux clocks */ ++#define HI3516A_SYSAXI_CLK 0 ++#define HI3516A_SNOR_MUX 1 ++#define HI3516A_SNAND_MUX 2 ++#define HI3516A_NAND_MUX 3 ++#define HI3516A_UART_MUX 4 ++#define HI3516A_ETH_PHY_MUX 5 ++#define HI3516A_A7_MUX 6 ++#define HI3516A_MMC0_MUX 7 ++#define HI3516A_MMC1_MUX 8 ++#define HI3516A_USB2_CTRL_UTMI0_REQ 9 ++#define HI3516A_USB2_HRST_REQ 10 ++ ++/* gate clocks */ ++#define HI3516A_SNOR_CLK 15 ++#define HI3516A_SNAND_CLK 16 ++#define HI3516A_NAND_CLK 17 ++#define HI3516A_UART0_CLK 18 ++#define HI3516A_UART1_CLK 19 ++#define HI3516A_UART2_CLK 20 ++#define HI3516A_UART3_CLK 21 ++#define HI3516A_ETH_CLK 22 ++#define HI3516A_ETH_MACIF_CLK 23 ++#define HI3516A_MMC0_CLK 24 ++#define HI3516A_MMC1_CLK 25 ++#define HI3516A_SPI0_CLK 26 ++#define HI3516A_SPI1_CLK 27 ++#define HI3516A_DMAC_CLK 28 ++ ++/* pll clock */ ++#define HI3516A_APLL_CLK 30 ++ ++#define HI3516A_CRG_NR_CLKS 128 ++#define HI3516A_CRG_NR_RSTS 0x12c ++ ++/* clock in system control */ ++/* mux clocks */ ++#define HI3516A_TIME0_0_CLK 1 ++#define HI3516A_TIME0_1_CLK 2 ++#define HI3516A_TIME1_2_CLK 3 ++#define HI3516A_TIME1_3_CLK 4 ++ ++#define HI3516A_SYS_NR_CLKS 10 ++ ++#endif /* __DTS_HI3516A_CLOCK_H */ +diff --git a/include/dt-bindings/clock/hi3518ev20x-clock.h b/include/dt-bindings/clock/hi3518ev20x-clock.h +new file mode 100644 +index 0000000..41d87c2 +--- /dev/null ++++ b/include/dt-bindings/clock/hi3518ev20x-clock.h +@@ -0,0 +1,86 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef __DTS_HI3518EV20X_CLOCK_H ++#define __DTS_HI3518EV20X_CLOCK_H ++ ++/* clk in CRG */ ++/* fixed rate clocks */ ++#define HI3518EV20X_INNER_CLK_OFFSET 64 ++#define HI3518EV20X_FIXED_3M 65 ++#define HI3518EV20X_FIXED_6M 66 ++#define HI3518EV20X_FIXED_24M 67 ++#define HI3518EV20X_FIXED_25M 68 ++#define HI3518EV20X_FIXED_27M 69 ++#define HI3518EV20X_FIXED_37P125M 70 ++#define HI3518EV20X_FIXED_49P5M 71 ++#define HI3518EV20X_FIXED_50M 72 ++#define HI3518EV20X_FIXED_54M 73 ++#define HI3518EV20X_FIXED_74P25M 74 ++#define HI3518EV20X_FIXED_99M 75 ++#define HI3518EV20X_FIXED_125M 76 ++#define HI3518EV20X_FIXED_148P5M 77 ++#define HI3518EV20X_FIXED_198M 78 ++#define HI3518EV20X_FIXED_200M 79 ++#define HI3518EV20X_FIXED_250M 80 ++#define HI3518EV20X_FIXED_297M 81 ++#define HI3518EV20X_FIXED_300M 82 ++#define HI3518EV20X_FIXED_396M 83 ++#define HI3518EV20X_FIXED_540M 84 ++#define HI3518EV20X_FIXED_594M 85 ++#define HI3518EV20X_FIXED_600M 86 ++#define HI3518EV20X_FIXED_650M 87 ++#define HI3518EV20X_FIXED_750M 88 ++#define HI3518EV20X_FIXED_1188M 89 ++ ++/* mux clocks */ ++#define HI3518EV20X_SYSAPB_CLK 0 ++#define HI3518EV20X_FMC_MUX 1 ++#define HI3518EV20X_UART_MUX 2 ++#define HI3518EV20X_ETH_MUX 3 ++#define HI3518EV20X_USB2_CTRL_UTMI0_REQ 4 ++#define HI3518EV20X_USB2_HRST_REQ 5 ++#define HI3518EV20X_MMC0_MUX 6 ++#define HI3518EV20X_MMC1_MUX 7 ++ ++/* gate clocks */ ++#define HI3518EV20X_FMC_CLK 20 ++#define HI3518EV20X_UART0_CLK 21 ++#define HI3518EV20X_UART1_CLK 22 ++#define HI3518EV20X_UART2_CLK 23 ++#define HI3518EV20X_UART3_CLK 24 ++#define HI3518EV20X_ETH_CLK 25 ++#define HI3518EV20X_MMC0_CLK 26 ++#define HI3518EV20X_MMC1_CLK 27 ++#define HI3518EV20X_SPI0_CLK 28 ++#define HI3518EV20X_SPI1_CLK 29 ++#define HI3518EV20X_DMAC_CLK 30 ++ ++#define HI3518EV20X_CRG_NR_CLKS 128 ++#define HI3518EV20X_CRG_NR_RSTS 128 ++ ++/* clock in system control */ ++/* mux clocks */ ++#define HI3518EV20X_TIME0_0_CLK 1 ++#define HI3518EV20X_TIME0_1_CLK 2 ++#define HI3518EV20X_TIME1_2_CLK 3 ++#define HI3518EV20X_TIME1_3_CLK 4 ++ ++#define HI3518EV20X_SC_NR_CLKS 4 ++ ++#endif /* __DTS_HI3518EV20X_CLOCK_H */ +diff --git a/include/dt-bindings/clock/hi3521a-clock.h b/include/dt-bindings/clock/hi3521a-clock.h +new file mode 100644 +index 0000000..9e40c29 +--- /dev/null ++++ b/include/dt-bindings/clock/hi3521a-clock.h +@@ -0,0 +1,97 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef __DTS_HI3521A_CLOCK_H ++#define __DTS_HI3521A_CLOCK_H ++ ++#include ++ ++/* interrupt specifier cell 0 */ ++#define GIC_SPI 0 ++#define GIC_PPI 1 ++ ++/* clk in CRG */ ++/* fixed rate clocks */ ++#define HI3521A_INNER_CLK_OFFSET 64 ++#define HI3521A_FIXED_2M 65 ++#define HI3521A_FIXED_2P2M 66 ++#define HI3521A_FIXED_2P5M 67 ++#define HI3521A_FIXED_3M 68 ++#define HI3521A_FIXED_24M 69 ++#define HI3521A_FIXED_25M 70 ++#define HI3521A_FIXED_27M 71 ++#define HI3521A_FIXED_50M 72 ++#define HI3521A_FIXED_54M 73 ++#define HI3521A_FIXED_60M 74 ++#define HI3521A_FIXED_62P5M 75 ++#define HI3521A_FIXED_75M 76 ++#define HI3521A_FIXED_83M 77 ++#define HI3521A_FIXED_100M 78 ++#define HI3521A_FIXED_125M 79 ++#define HI3521A_FIXED_150M 80 ++#define HI3521A_FIXED_162M 81 ++#define HI3521A_FIXED_187M 82 ++#define HI3521A_FIXED_187P5M 83 ++#define HI3521A_FIXED_202P5M 84 ++#define HI3521A_FIXED_250M 85 ++#define HI3521A_FIXED_270M 86 ++#define HI3521A_FIXED_300M 87 ++#define HI3521A_FIXED_324M 88 ++#define HI3521A_FIXED_375M 89 ++#define HI3521A_FIXED_400M 90 ++#define HI3521A_FIXED_405M 91 ++#define HI3521A_FIXED_500M 92 ++#define HI3521A_FIXED_750M 93 ++#define HI3521A_FIXED_800M 94 ++#define HI3521A_FIXED_810M 95 ++#define HI3521A_FIXED_1500M 96 ++#define HI3521A_FIXED_1620M 97 ++ ++/* mux clocks */ ++#define HI3521A_SYSAPB_CLK 0 ++#define HI3521A_FMC_MUX 1 ++#define HI3521A_UART_MUX 2 ++#define HI3521A_ETH_PHY_MUX 3 ++ ++/* gate clocks */ ++#define HI3521A_FMC_CLK 20 ++#define HI3521A_UART0_CLK 21 ++#define HI3521A_UART1_CLK 22 ++#define HI3521A_UART2_CLK 23 ++#define HI3521A_ETH_CLK 24 ++#define HI3521A_ETH_MACIF_CLK 25 ++#define HI3521A_SPI0_CLK 26 ++#define HI3521A_DMAC_CLK 27 ++ ++#define HI3521A_CRG_NR_CLKS 128 ++#define HI3521A_CRG_NR_RSTS 0xB8 ++ ++/* clock in system control */ ++/* mux clocks */ ++#define HI3521A_TIME0_0_CLK 1 ++#define HI3521A_TIME0_1_CLK 2 ++#define HI3521A_TIME1_2_CLK 3 ++#define HI3521A_TIME1_3_CLK 4 ++#define HI3521A_TIME2_4_CLK 5 ++#define HI3521A_TIME2_5_CLK 6 ++#define HI3521A_TIME3_6_CLK 7 ++#define HI3521A_TIME3_7_CLK 8 ++ ++#define HI3521A_SC_NR_CLKS 10 ++ ++#endif /* __DTS_HI3521A_CLOCK_H */ +diff --git a/include/dt-bindings/clock/hi3531a-clock.h b/include/dt-bindings/clock/hi3531a-clock.h +new file mode 100644 +index 0000000..961a41c +--- /dev/null ++++ b/include/dt-bindings/clock/hi3531a-clock.h +@@ -0,0 +1,105 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef __DTS_HI3531A_CLOCK_H ++#define __DTS_HI3531A_CLOCK_H ++ ++#include ++ ++/* interrupt specifier cell 0 */ ++#define GIC_SPI 0 ++#define GIC_PPI 1 ++ ++/* clk in hi3531A CRG */ ++/* fixed rate clocks */ ++#define HI3531A_INNER_CLK_OFFSET 64 ++#define HI3531A_FIXED_2M 65 ++#define HI3531A_FIXED_2P02M 66 ++#define HI3531A_FIXED_2P5M 67 ++#define HI3531A_FIXED_3M 68 ++#define HI3531A_FIXED_24M 69 ++#define HI3531A_FIXED_25M 70 ++#define HI3531A_FIXED_27M 71 ++#define HI3531A_FIXED_37P125M 72 ++#define HI3531A_FIXED_37P5M 73 ++#define HI3531A_FIXED_40P5M 74 ++#define HI3531A_FIXED_48M 75 ++#define HI3531A_FIXED_50M 76 ++#define HI3531A_FIXED_54M 77 ++#define HI3531A_FIXED_59P2M 78 ++#define HI3531A_FIXED_60M 79 ++#define HI3531A_FIXED_62P5M 80 ++#define HI3531A_FIXED_74P25M 81 ++#define HI3531A_FIXED_75M 82 ++#define HI3531A_FIXED_83P3M 83 ++#define HI3531A_FIXED_100M 84 ++#define HI3531A_FIXED_125M 85 ++#define HI3531A_FIXED_150M 86 ++#define HI3531A_FIXED_187P5M 87 ++#define HI3531A_FIXED_200M 88 ++#define HI3531A_FIXED_250M 89 ++#define HI3531A_FIXED_300M 90 ++#define HI3531A_FIXED_324M 91 ++#define HI3531A_FIXED_355M 92 ++#define HI3531A_FIXED_400M 93 ++#define HI3531A_FIXED_433M 94 ++#define HI3531A_FIXED_500M 95 ++#define HI3531A_FIXED_750M 96 ++#define HI3531A_FIXED_800M 97 ++#define HI3531A_FIXED_1000M 98 ++#define HI3531A_FIXED_1420M 99 ++#define HI3531A_FIXED_1500M 100 ++ ++/* mux clocks */ ++#define HI3531A_PERIAXI_CLK 0 ++#define HI3531A_SYSAXI_CLK 1 ++#define HI3531A_NFC_MUX 2 ++#define HI3531A_FMC_MUX 3 ++#define HI3531A_UART_MUX 4 ++#define HI3531A_ETH_PHY_MUX 5 ++ ++/* gate clocks */ ++#define HI3531A_UART0_CLK 20 ++#define HI3531A_UART1_CLK 21 ++#define HI3531A_UART2_CLK 22 ++#define HI3531A_UART3_CLK 23 ++#define HI3531A_UART4_CLK 24 ++#define HI3531A_NFC_CLK 25 ++#define HI3531A_FMC_CLK 26 ++#define HI3531A_ETH_CLK 27 ++#define HI3531A_ETH_MACIF_CLK 28 ++#define HI3531A_SPI0_CLK 29 ++#define HI3531A_DMAC_CLK 30 ++ ++#define HI3531A_CRG_NR_CLKS 60 ++#define HI3531A_CRG_NR_RSTS 0x250 ++ ++/* clock in system control */ ++/* mux clocks */ ++#define HI3531A_TIME0_0_CLK 1 ++#define HI3531A_TIME0_1_CLK 2 ++#define HI3531A_TIME1_2_CLK 3 ++#define HI3531A_TIME1_3_CLK 4 ++#define HI3531A_TIME2_4_CLK 5 ++#define HI3531A_TIME2_5_CLK 6 ++#define HI3531A_TIME3_6_CLK 7 ++#define HI3531A_TIME3_7_CLK 8 ++ ++#define HI3531A_SYS_NR_CLKS 10 ++ ++#endif /* __DTS_HI3531A_CLOCK_H */ +diff --git a/include/dt-bindings/clock/hi3536dv100-clock.h b/include/dt-bindings/clock/hi3536dv100-clock.h +new file mode 100644 +index 0000000..f6b36e1 +--- /dev/null ++++ b/include/dt-bindings/clock/hi3536dv100-clock.h +@@ -0,0 +1,82 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef __DTS_HI3536DV100_CLOCK_H ++#define __DTS_HI3536DV100_CLOCK_H ++ ++/* clk in Hi3536D CRG */ ++/* fixed rate clocks */ ++#define HI3536DV100_FIXED_3M 1 ++#define HI3536DV100_FIXED_6M 2 ++#define HI3536DV100_FIXED_12M 3 ++#define HI3536DV100_FIXED_24M 4 ++#define HI3536DV100_FIXED_50M 5 ++#define HI3536DV100_FIXED_83P3M 6 ++#define HI3536DV100_FIXED_100M 7 ++#define HI3536DV100_FIXED_125M 8 ++#define HI3536DV100_FIXED_148P5M 9 ++#define HI3536DV100_FIXED_150M 10 ++#define HI3536DV100_FIXED_200M 11 ++#define HI3536DV100_FIXED_250M 12 ++#define HI3536DV100_FIXED_300M 13 ++#define HI3536DV100_FIXED_324M 14 ++#define HI3536DV100_FIXED_342M 15 ++#define HI3536DV100_FIXED_375M 16 ++#define HI3536DV100_FIXED_400M 17 ++#define HI3536DV100_FIXED_448M 18 ++#define HI3536DV100_FIXED_500M 19 ++#define HI3536DV100_FIXED_540M 20 ++#define HI3536DV100_FIXED_600M 21 ++#define HI3536DV100_FIXED_750M 22 ++#define HI3536DV100_FIXED_1500M 23 ++ ++/* mux clocks */ ++#define HI3536DV100_SYSAXI_CLK 24 ++#define HI3536DV100_SYSAPB_CLK 25 ++#define HI3536DV100_FMC_MUX 26 ++#define HI3536DV100_UART_MUX 27 ++ ++/* gate clocks */ ++#define HI3536DV100_UART0_CLK 28 ++#define HI3536DV100_UART1_CLK 29 ++#define HI3536DV100_UART2_CLK 30 ++#define HI3536DV100_FMC_CLK 31 ++#define HI3536DV100_ETH0_CLK 32 ++#define HI3536DV100_ETH0_PHY_CLK 33 ++#define HI3536DV100_USB2_BUS_CLK 34 ++#define HI3536DV100_USB2_CLK 35 ++#define HI3536DV100_SATA_CLK 36 ++#define HI3536DV100_DMAC_CLK 37 ++ ++#define HI3536DV100_CRG_NR_CLKS 40 ++#define HI3536DV100_CRG_NR_RSTS 0x200 ++ ++/* clock in system control */ ++/* mux clocks */ ++#define HI3536DV100_TIME0_0_CLK 1 ++#define HI3536DV100_TIME0_1_CLK 2 ++#define HI3536DV100_TIME1_2_CLK 3 ++#define HI3536DV100_TIME1_3_CLK 4 ++#define HI3536DV100_TIME2_4_CLK 5 ++#define HI3536DV100_TIME2_5_CLK 6 ++#define HI3536DV100_TIME3_6_CLK 7 ++#define HI3536DV100_TIME3_7_CLK 8 ++ ++#define HI3536DV100_SC_NR_CLKS 10 ++ ++#endif /* __DTS_HI3536DV100_CLOCK_H */ +diff --git a/include/dt-bindings/clock/hi3559av100-clock.h b/include/dt-bindings/clock/hi3559av100-clock.h +new file mode 100644 +index 0000000..122c092 +--- /dev/null ++++ b/include/dt-bindings/clock/hi3559av100-clock.h +@@ -0,0 +1,174 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef __DTS_HI3559AV100_CLOCK_H ++#define __DTS_HI3559AV100_CLOCK_H ++ ++/* fixed rate */ ++#define HI3559AV100_FIXED_1188M 1 ++#define HI3559AV100_FIXED_1000M 2 ++#define HI3559AV100_FIXED_842M 3 ++#define HI3559AV100_FIXED_792M 4 ++#define HI3559AV100_FIXED_750M 5 ++#define HI3559AV100_FIXED_710M 6 ++#define HI3559AV100_FIXED_680M 7 ++#define HI3559AV100_FIXED_667M 8 ++#define HI3559AV100_FIXED_631M 9 ++#define HI3559AV100_FIXED_600M 10 ++#define HI3559AV100_FIXED_568M 11 ++#define HI3559AV100_FIXED_500M 12 ++#define HI3559AV100_FIXED_475M 13 ++#define HI3559AV100_FIXED_428M 14 ++#define HI3559AV100_FIXED_400M 15 ++#define HI3559AV100_FIXED_396M 16 ++#define HI3559AV100_FIXED_300M 17 ++#define HI3559AV100_FIXED_250M 18 ++#define HI3559AV100_FIXED_198M 19 ++#define HI3559AV100_FIXED_187p5M 20 ++#define HI3559AV100_FIXED_150M 21 ++#define HI3559AV100_FIXED_148p5M 22 ++#define HI3559AV100_FIXED_125M 23 ++#define HI3559AV100_FIXED_107M 24 ++#define HI3559AV100_FIXED_100M 25 ++#define HI3559AV100_FIXED_99M 26 ++#define HI3559AV100_FIXED_74p25M 27 ++#define HI3559AV100_FIXED_72M 28 ++#define HI3559AV100_FIXED_60M 29 ++#define HI3559AV100_FIXED_54M 30 ++#define HI3559AV100_FIXED_50M 31 ++#define HI3559AV100_FIXED_49p5M 32 ++#define HI3559AV100_FIXED_37p125M 33 ++#define HI3559AV100_FIXED_36M 34 ++#define HI3559AV100_FIXED_32p4M 35 ++#define HI3559AV100_FIXED_27M 36 ++#define HI3559AV100_FIXED_25M 37 ++#define HI3559AV100_FIXED_24M 38 ++#define HI3559AV100_FIXED_12M 39 ++#define HI3559AV100_FIXED_3M 40 ++#define HI3559AV100_FIXED_1p6M 41 ++#define HI3559AV100_FIXED_400K 42 ++#define HI3559AV100_FIXED_100K 43 ++#define HI3559AV100_FIXED_200M 44 ++#define HI3559AV100_FIXED_75M 75 ++ ++#define HI3559AV100_I2C0_CLK 50 ++#define HI3559AV100_I2C1_CLK 51 ++#define HI3559AV100_I2C2_CLK 52 ++#define HI3559AV100_I2C3_CLK 53 ++#define HI3559AV100_I2C4_CLK 54 ++#define HI3559AV100_I2C5_CLK 55 ++#define HI3559AV100_I2C6_CLK 56 ++#define HI3559AV100_I2C7_CLK 57 ++#define HI3559AV100_I2C8_CLK 58 ++#define HI3559AV100_I2C9_CLK 59 ++#define HI3559AV100_I2C10_CLK 60 ++#define HI3559AV100_I2C11_CLK 61 ++ ++#define HI3559AV100_SPI0_CLK 62 ++#define HI3559AV100_SPI1_CLK 63 ++#define HI3559AV100_SPI2_CLK 64 ++#define HI3559AV100_SPI3_CLK 65 ++#define HI3559AV100_SPI4_CLK 66 ++#define HI3559AV100_SPI5_CLK 67 ++#define HI3559AV100_SPI6_CLK 68 ++ ++#define HI3559AV100_EDMAC_CLK 69 ++#define HI3559AV100_EDMAC_AXICLK 70 ++#define HI3559AV100_EDMAC1_CLK 71 ++#define HI3559AV100_EDMAC1_AXICLK 72 ++#define HI3559AV100_VDMAC_CLK 73 ++ ++/* mux clocks */ ++#define HI3559AV100_FMC_MUX 80 ++#define HI3559AV100_SYSAPB_MUX 81 ++#define HI3559AV100_UART_MUX 82 ++#define HI3559AV100_SYSBUS_MUX 83 ++#define HI3559AV100_A73_MUX 84 ++#define HI3559AV100_MMC0_MUX 85 ++#define HI3559AV100_MMC1_MUX 86 ++#define HI3559AV100_MMC2_MUX 87 ++#define HI3559AV100_MMC3_MUX 88 ++ ++/* gate clocks */ ++#define HI3559AV100_FMC_CLK 90 ++#define HI3559AV100_UART0_CLK 91 ++#define HI3559AV100_UART1_CLK 92 ++#define HI3559AV100_UART2_CLK 93 ++#define HI3559AV100_UART3_CLK 94 ++#define HI3559AV100_UART4_CLK 95 ++#define HI3559AV100_MMC0_CLK 96 ++#define HI3559AV100_MMC1_CLK 97 ++#define HI3559AV100_MMC2_CLK 98 ++#define HI3559AV100_MMC3_CLK 99 ++ ++#define HI3559AV100_ETH_CLK 100 ++#define HI3559AV100_ETH_MACIF_CLK 101 ++#define HI3559AV100_ETH1_CLK 102 ++#define HI3559AV100_ETH1_MACIF_CLK 103 ++ ++/* complex */ ++#define HI3559AV100_MAC0_CLK 110 ++#define HI3559AV100_MAC1_CLK 111 ++#define HI3559AV100_SATA_CLK 112 ++#define HI3559AV100_USB_CLK 113 ++#define HI3559AV100_USB1_CLK 114 ++ ++/* pll clocks */ ++#define HI3559AV100_APLL_CLK 250 ++#define HI3559AV100_GPLL_CLK 251 ++ ++#define HI3559AV100_CRG_NR_CLKS 256 ++ ++#define HI3559AV100_SHUB_SOURCE_SOC_24M 0 ++#define HI3559AV100_SHUB_SOURCE_SOC_200M 1 ++#define HI3559AV100_SHUB_SOURCE_SOC_300M 2 ++#define HI3559AV100_SHUB_SOURCE_PLL 3 ++#define HI3559AV100_SHUB_SOURCE_CLK 4 ++ ++#define HI3559AV100_SHUB_I2C0_CLK 10 ++#define HI3559AV100_SHUB_I2C1_CLK 11 ++#define HI3559AV100_SHUB_I2C2_CLK 12 ++#define HI3559AV100_SHUB_I2C3_CLK 13 ++#define HI3559AV100_SHUB_I2C4_CLK 14 ++#define HI3559AV100_SHUB_I2C5_CLK 15 ++#define HI3559AV100_SHUB_I2C6_CLK 16 ++#define HI3559AV100_SHUB_I2C7_CLK 17 ++ ++#define HI3559AV100_SHUB_SPI_SOURCE_CLK 20 ++#define HI3559AV100_SHUB_SPI4_SOURCE_CLK 21 ++#define HI3559AV100_SHUB_SPI0_CLK 22 ++#define HI3559AV100_SHUB_SPI1_CLK 23 ++#define HI3559AV100_SHUB_SPI2_CLK 24 ++#define HI3559AV100_SHUB_SPI3_CLK 25 ++#define HI3559AV100_SHUB_SPI4_CLK 26 ++ ++#define HI3559AV100_SHUB_UART_CLK_32K 30 ++#define HI3559AV100_SHUB_UART_SOURCE_CLK 31 ++#define HI3559AV100_SHUB_UART_DIV_CLK 32 ++#define HI3559AV100_SHUB_UART0_CLK 33 ++#define HI3559AV100_SHUB_UART1_CLK 34 ++#define HI3559AV100_SHUB_UART2_CLK 35 ++#define HI3559AV100_SHUB_UART3_CLK 36 ++#define HI3559AV100_SHUB_UART4_CLK 37 ++#define HI3559AV100_SHUB_UART5_CLK 38 ++#define HI3559AV100_SHUB_UART6_CLK 39 ++ ++#define HI3559AV100_SHUB_NR_CLKS 40 ++ ++#endif /* __DTS_HI3559AV100_CLOCK_H */ ++ +diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h +index bb31373..234529b 100644 +--- a/include/linux/cpuidle.h ++++ b/include/linux/cpuidle.h +@@ -62,6 +62,7 @@ struct cpuidle_state { + }; + + /* Idle State Flags */ ++#define CPUIDLE_FLAG_TIME_VALID (0x01) /* is residency time measurable? */ + #define CPUIDLE_FLAG_COUPLED (0x02) /* state applies to multiple cpus */ + #define CPUIDLE_FLAG_TIMER_STOP (0x04) /* timer is stopped on this state */ + +diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h +index 08528af..7fb344f 100644 +--- a/include/linux/dma-mapping.h ++++ b/include/linux/dma-mapping.h +@@ -705,6 +705,8 @@ dma_mark_declared_memory_occupied(struct device *dev, + /* + * Managed DMA API + */ ++void hi_dmac_map_area(const void *kaddr, size_t size, ++ enum dma_data_direction dir); + extern void *dmam_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t gfp); + extern void dmam_free_coherent(struct device *dev, size_t size, void *vaddr, +diff --git a/include/linux/fb.h b/include/linux/fb.h +index a964d07..ce0d385 100644 +--- a/include/linux/fb.h ++++ b/include/linux/fb.h +@@ -237,7 +237,14 @@ struct fb_deferred_io { + void (*deferred_io)(struct fb_info *info, struct list_head *pagelist); + }; + #endif ++#ifdef CONFIG_ARCH_HISI_BVT ++#define FBIOGET_DMABUF _IOR('F', 0x21, struct fb_dmabuf_export) + ++struct fb_dmabuf_export { ++ __u32 fd; ++ __u32 flags; ++}; ++#endif + /* + * Frame buffer operations + * +@@ -320,6 +327,12 @@ struct fb_ops { + /* called at KDB enter and leave time to prepare the console */ + int (*fb_debug_enter)(struct fb_info *info); + int (*fb_debug_leave)(struct fb_info *info); ++#ifdef CONFIG_ARCH_HISI_BVT ++#ifdef CONFIG_DMA_SHARED_BUFFER ++ /* Export the frame buffer as a dmabuf object */ ++ struct dma_buf *(*fb_dmabuf_export)(struct fb_info *info); ++#endif ++#endif + }; + + #ifdef CONFIG_FB_TILEBLITTING +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 2f63d44..dd88ded 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -941,9 +941,9 @@ static inline struct file *get_file(struct file *f) + /* Page cache limit. The filesystems should put that into their s_maxbytes + limits, otherwise bad things can happen in VM. */ + #if BITS_PER_LONG==32 +-#define MAX_LFS_FILESIZE (((loff_t)PAGE_SIZE << (BITS_PER_LONG-1))-1) ++#define MAX_LFS_FILESIZE ((loff_t)ULONG_MAX << PAGE_SHIFT) + #elif BITS_PER_LONG==64 +-#define MAX_LFS_FILESIZE ((loff_t)0x7fffffffffffffffLL) ++#define MAX_LFS_FILESIZE ((loff_t)LLONG_MAX) + #endif + + #define FL_POSIX 1 +diff --git a/include/linux/hidmac.h b/include/linux/hidmac.h +new file mode 100644 +index 0000000..bf291be +--- /dev/null ++++ b/include/linux/hidmac.h +@@ -0,0 +1,135 @@ ++/****************************************************************************** ++ * COPYRIGHT (C) 2013 Hisilicon ++ * All rights reserved. ++ * *** ++ * Create 2013-08-23 ++ * ++ ******************************************************************************/ ++#ifndef __DMAC_H__ ++#define __DMAC_H__ ++ ++#define DMAC_ERROR_BASE 100 ++#define DMAC_CHN_SUCCESS (DMAC_ERROR_BASE+0x10) ++ ++#ifdef CONFIG_HI_DMAC ++extern int dma_driver_init(void); ++extern int dmac_channelclose(unsigned int channel); ++extern int dmac_channelstart(unsigned int u32channel); ++extern int dmac_channel_allocate(void *pisr); ++ ++extern int dmac_start_m2p(unsigned int channel, unsigned int pmemaddr, ++ unsigned int uwperipheralid, ++ unsigned int uwnumtransfers, ++ unsigned int next_lli_addr); ++extern int dmac_m2p_transfer(unsigned int memaddr, ++ unsigned int uwperipheralid, unsigned int length); ++extern int dmac_channel_free(unsigned int channel); ++extern int do_dma_m2p(unsigned int mem_addr, unsigned int peripheral_addr, ++ unsigned int length); ++extern int do_dma_p2m(unsigned int mem_addr, unsigned int peripheral_addr, ++ unsigned int length); ++extern int dmac_wait(int channel); ++extern int dmac_start_m2m(unsigned int channel, unsigned int psource, ++ unsigned int pdest, unsigned int uwnumtransfers); ++extern int dmac_m2m_transfer(unsigned int source, ++ unsigned int dest, unsigned int length); ++extern int dmac_register_isr(unsigned int channel, void *pisr); ++extern int free_dmalli_space(unsigned int *ppheadlli, unsigned int page_num); ++extern int dmac_start_llim2p(unsigned int channel, unsigned int *pfirst_lli, ++ unsigned int uwperipheralid); ++extern int dmac_buildllim2m(unsigned int *ppheadlli, unsigned int pdest, ++ unsigned int psource, ++ unsigned int totaltransfersize, ++ unsigned int uwnumtransfers); ++extern int dmac_start_llim2m(unsigned int channel, unsigned int *pfirst_lli); ++extern int allocate_dmalli_space(unsigned int *ppheadlli, ++ unsigned int page_num); ++ ++extern int do_dma_llim2m_isp(unsigned int *source, ++ unsigned int *dest, ++ unsigned int *length, ++ unsigned int num); ++ ++#else /* !CONFIG_HI_DMAC */ ++static inline int dma_driver_init(void) { return 0; } ++static inline int dmac_channelclose(unsigned int channel) { return 0; } ++static inline int dmac_channelstart(unsigned int u32channel) { return 0; } ++static inline int dmac_channel_allocate(void *pisr) { return 0; } ++ ++static inline int dmac_start_m2p(unsigned int channel, unsigned int pmemaddr, ++ unsigned int uwperipheralid, ++ unsigned int uwnumtransfers, ++ unsigned int next_lli_addr) ++{ return 0; } ++ ++static inline int dmac_m2p_transfer(unsigned int memaddr, ++ unsigned int uwperipheralid, unsigned int length) ++{ return 0; } ++ ++static inline int dmac_channel_free(unsigned int channel) { return 0; } ++ ++int do_dma_m2p(unsigned int mem_addr, unsigned int peripheral_addr, ++ unsigned int length) ++{ return 0; } ++ ++static inline int do_dma_p2m(unsigned int mem_addr, ++ unsigned int peripheral_addr, ++ unsigned int length) ++{ return 0; } ++ ++static inline int dmac_wait(int channel) { return 0; } ++ ++static inline int dmac_start_m2m(unsigned int channel, unsigned int psource, ++ unsigned int pdest, unsigned int uwnumtransfers) ++{ return 0; } ++ ++static inline int dmac_m2m_transfer(unsigned int source, ++ unsigned int dest, unsigned int length) ++{ return 0; } ++ ++static inline int dmac_register_isr(unsigned int channel, void *pisr) ++{ return 0; } ++ ++static inline int free_dmalli_space(unsigned int *ppheadlli, ++ unsigned int page_num) ++{ return 0; } ++ ++static inline int dmac_start_llim2p(unsigned int channel, ++ unsigned int *pfirst_lli, ++ unsigned int uwperipheralid) ++{ return 0; } ++ ++static inline int dmac_buildllim2m(unsigned int *ppheadlli, unsigned int pdest, ++ unsigned int psource, ++ unsigned int totaltransfersize, ++ unsigned int uwnumtransfers) ++{ return 0; } ++ ++static inline int dmac_start_llim2m(unsigned int channel, ++ unsigned int *pfirst_lli) ++{ return 0; } ++ ++static inline int allocate_dmalli_space(unsigned int *ppheadlli, ++ unsigned int page_num) ++{ return 0; } ++ ++static inline int do_dma_llim2m_isp(unsigned int *source, ++ unsigned int *dest, ++ unsigned int *length, ++ unsigned int num) ++{ return 0; } ++#endif /* CONFIG_HI_DMAC */ ++ ++/*structure for LLI*/ ++typedef struct dmac_lli { ++ /*source address*/ ++ unsigned int src_addr; ++ /*destination address*/ ++ unsigned int dst_addr; ++ /*pointer to next LLI*/ ++ unsigned int next_lli; ++ /*control word*/ ++ unsigned int lli_transfer_ctrl; ++} dmac_lli; ++ ++#endif +diff --git a/include/linux/hiedmac.h b/include/linux/hiedmac.h +new file mode 100644 +index 0000000..a561ca3 +--- /dev/null ++++ b/include/linux/hiedmac.h +@@ -0,0 +1,32 @@ ++#ifndef __DMAC_H__ ++#define __DMAC_H__ ++ ++#define DMAC_ERROR_BASE 0x64 ++ ++#define DMAC_CHN_SUCCESS (DMAC_ERROR_BASE+0x10) ++#define DMAC_CHN_ERROR (DMAC_ERROR_BASE+0x11) ++#define DMAC_CHN_TIMEOUT (DMAC_ERROR_BASE+0x12) ++#define DMAC_CHN_ALLOCAT (DMAC_ERROR_BASE+0x13) ++#define DMAC_CHN_VACANCY (DMAC_ERROR_BASE+0x14) ++ ++/*structure for LLI*/ ++typedef struct dmac_lli { ++ //must be 64Byte aligned ++ unsigned long next_lli; ++ unsigned int reserved[5]; ++ unsigned int count; ++ unsigned long src_addr; ++ unsigned long dest_addr; ++ unsigned int config; ++ unsigned int pad[51]; ++} dmac_lli; ++ ++typedef void DMAC_ISR(unsigned int channel, int status); ++ ++int do_dma_llim2m(unsigned long source, ++ unsigned long dest, ++ unsigned long length); ++int dmac_m2m_transfer(unsigned long source, unsigned long dest, ++ unsigned int length); ++ ++#endif +diff --git a/include/linux/i2c.h b/include/linux/i2c.h +index 6422eef..253ff53 100644 +--- a/include/linux/i2c.h ++++ b/include/linux/i2c.h +@@ -68,6 +68,29 @@ extern int i2c_master_recv(const struct i2c_client *client, char *buf, + */ + extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num); ++ ++#ifdef CONFIG_ARCH_HISI_BVT ++#ifdef CONFIG_I2C_HISI ++extern int hi_i2c_dma_read(const struct i2c_client *client, ++ unsigned int dma_buf, unsigned int reg_addr, ++ unsigned int reg_addr_num, unsigned int length); ++ ++extern int hi_i2c_dma_write(const struct i2c_client *client, ++ unsigned int dma_buf, unsigned int reg_addr, ++ unsigned int reg_addr_num, unsigned int length); ++#endif ++ ++extern int hi_i2c_master_send(const struct i2c_client *client, const char *buf, ++ int count); ++ ++extern int hi_i2c_master_recv(const struct i2c_client *client, char *buf, ++ int count); ++ ++extern int hi_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ++ int num); ++ ++#endif ++ + /* Unlocked flavor */ + extern int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num); +@@ -553,6 +576,9 @@ struct i2c_adapter { + const struct i2c_lock_operations *lock_ops; + struct rt_mutex bus_lock; + struct rt_mutex mux_lock; ++#ifdef CONFIG_ARCH_HISI_BVT ++ spinlock_t spinlock; ++#endif + + int timeout; /* in jiffies */ + int retries; +diff --git a/include/linux/mfd/hisi_fmc.h b/include/linux/mfd/hisi_fmc.h +new file mode 100644 +index 0000000..ecf30c5 +--- /dev/null ++++ b/include/linux/mfd/hisi_fmc.h +@@ -0,0 +1,527 @@ ++/* ++ * Header file for HiSilicon Flash Memory Controller Driver ++ * ++ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd. ++ * ++ * 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 __HISI_FMC_H ++#define __HISI_FMC_H ++ ++#include ++#include ++#include ++#include ++ ++/*****************************************************************************/ ++#define _512B (512) ++#define _1K (1024) ++#define _2K (2048) ++#define _4K (4096) ++#define _8K (8192) ++#define _16K (16384) ++#define _32K (32768) ++#define _64K (0x10000UL) ++#define _128K (0x20000UL) ++#define _256K (0x40000UL) ++#define _512K (0x80000UL) ++#define _1M (0x100000UL) ++#define _2M (0x200000UL) ++#define _4M (0x400000UL) ++#define _8M (0x800000UL) ++#define _16M (0x1000000UL) ++#define _32M (0x2000000UL) ++#define _64M (0x4000000UL) ++#define _128M (0x8000000UL) ++#define _256M (0x10000000UL) ++#define _512M (0x20000000UL) ++#define _1G (0x40000000ULL) ++#define _2G (0x80000000ULL) ++#define _4G (0x100000000ULL) ++#define _8G (0x200000000ULL) ++#define _16G (0x400000000ULL) ++#define _64G (0x1000000000ULL) ++ ++/*****************************************************************************/ ++/* HIFMC REG MAP */ ++/*****************************************************************************/ ++#define FMC_CFG 0x00 ++#define FMC_CFG_SPI_NAND_SEL(_type) (((_size) & 0x3) << 11) ++#define SPI_NOR_ADDR_MODE BIT(10) ++#define FMC_CFG_OP_MODE_MASK BIT_MASK(0) ++#define FMC_CFG_OP_MODE_BOOT 0 ++#define FMC_CFG_OP_MODE_NORMAL 1 ++#define SPI_NOR_ADDR_MODE_3BYTES (0x0 << 10) ++#define SPI_NOR_ADDR_MODE_4BYTES (0x1 << 10) ++ ++#define FMC_CFG_BLOCK_SIZE(_size) (((_size) & 0x3) << 8) ++#define FMC_CFG_ECC_TYPE(_type) (((_type) & 0x7) << 5) ++#define FMC_CFG_PAGE_SIZE(_size) (((_size) & 0x3) << 3) ++#define FMC_CFG_FLASH_SEL(_type) (((_type) & 0x3) << 1) ++#define FMC_CFG_OP_MODE(_mode) ((_mode) & 0x1) ++ ++#define SPI_NAND_MFR_OTHER 0x0 ++#define SPI_NAND_MFR_WINBOND 0x1 ++#define SPI_NAND_MFR_ESMT 0x2 ++#define SPI_NAND_MFR_MICRON 0x3 ++ ++#define SPI_NAND_SEL_SHIFT 11 ++#define SPI_NAND_SEL_MASK (0x3 << SPI_NAND_SEL_SHIFT) ++ ++#define SPI_NOR_ADDR_MODE_3_BYTES 0x0 ++#define SPI_NOR_ADDR_MODE_4_BYTES 0x1 ++ ++#define SPI_NOR_ADDR_MODE_SHIFT 10 ++#define SPI_NOR_ADDR_MODE_MASK (0x1 << SPI_NOR_ADDR_MODE_SHIFT) ++ ++#define BLOCK_SIZE_64_PAGE 0x0 ++#define BLOCK_SIZE_128_PAGE 0x1 ++#define BLOCK_SIZE_256_PAGE 0x2 ++#define BLOCK_SIZE_512_PAGE 0x3 ++ ++#define BLOCK_SIZE_MASK (0x3 << 8) ++ ++#define ECC_TYPE_0BIT 0x0 ++#define ECC_TYPE_8BIT 0x1 ++#define ECC_TYPE_16BIT 0x2 ++#define ECC_TYPE_24BIT 0x3 ++#define ECC_TYPE_28BIT 0x4 ++#define ECC_TYPE_40BIT 0x5 ++#define ECC_TYPE_64BIT 0x6 ++ ++#define ECC_TYPE_SHIFT 5 ++#define ECC_TYPE_MASK (0x7 << ECC_TYPE_SHIFT) ++ ++#define PAGE_SIZE_2KB 0x0 ++#define PAGE_SIZE_4KB 0x1 ++#define PAGE_SIZE_8KB 0x2 ++#define PAGE_SIZE_16KB 0x3 ++ ++#define PAGE_SIZE_SHIFT 3 ++#define PAGE_SIZE_MASK (0x3 << PAGE_SIZE_SHIFT) ++ ++#define FLASH_TYPE_SPI_NOR 0x0 ++#define FLASH_TYPE_SPI_NAND 0x1 ++#define FLASH_TYPE_NAND 0x2 ++#define FLASH_TYPE_UNKNOWN 0x3 ++ ++#define FLASH_TYPE_SEL_MASK (0x3 << 1) ++#define GET_SPI_FLASH_TYPE(_reg) (((_reg) >> 1) & 0x3) ++ ++/*****************************************************************************/ ++#define FMC_GLOBAL_CFG 0x04 ++#define FMC_GLOBAL_CFG_WP_ENABLE BIT(6) ++#define FMC_GLOBAL_CFG_RANDOMIZER_EN (1 << 2) ++#define FLASH_TYPE_SEL_MASK (0x3 << 1) ++#define FMC_CFG_FLASH_SEL(_type) (((_type) & 0x3) << 1) ++ ++#define FMC_GLOBAL_CFG_DTR_MODE BIT(11) ++/*****************************************************************************/ ++#define FMC_SPI_TIMING_CFG 0x08 ++#define TIMING_CFG_TCSH(nr) (((nr) & 0xf) << 8) ++#define TIMING_CFG_TCSS(nr) (((nr) & 0xf) << 4) ++#define TIMING_CFG_TSHSL(nr) ((nr) & 0xf) ++ ++#define CS_HOLD_TIME 0x6 ++#define CS_SETUP_TIME 0x6 ++#define CS_DESELECT_TIME 0xf ++ ++/*****************************************************************************/ ++#define FMC_PND_PWIDTH_CFG 0x0c ++#define PWIDTH_CFG_RW_HCNT(_n) (((_n) & 0xf) << 8) ++#define PWIDTH_CFG_R_LCNT(_n) (((_n) & 0xf) << 4) ++#define PWIDTH_CFG_W_LCNT(_n) ((_n) & 0xf) ++ ++#define RW_H_WIDTH (0xa) ++#define R_L_WIDTH (0xa) ++#define W_L_WIDTH (0xa) ++ ++/*****************************************************************************/ ++#define FMC_INT 0x18 ++#define FMC_INT_AHB_OP BIT(7) ++#define FMC_INT_WR_LOCK BIT(6) ++#define FMC_INT_DMA_ERR BIT(5) ++#define FMC_INT_ERR_ALARM BIT(4) ++#define FMC_INT_ERR_INVALID BIT(3) ++#define FMC_INT_ERR_INVALID_MASK (0x8) ++#define FMC_INT_ERR_VALID BIT(2) ++#define FMC_INT_ERR_VALID_MASK (0x4) ++#define FMC_INT_OP_FAIL BIT(1) ++#define FMC_INT_OP_DONE BIT(0) ++ ++/*****************************************************************************/ ++#define FMC_INT_EN 0x1c ++#define FMC_INT_EN_AHB_OP BIT(7) ++#define FMC_INT_EN_WR_LOCK BIT(6) ++#define FMC_INT_EN_DMA_ERR BIT(5) ++#define FMC_INT_EN_ERR_ALARM BIT(4) ++#define FMC_INT_EN_ERR_INVALID BIT(3) ++#define FMC_INT_EN_ERR_VALID BIT(2) ++#define FMC_INT_EN_OP_FAIL BIT(1) ++#define FMC_INT_EN_OP_DONE BIT(0) ++ ++/*****************************************************************************/ ++#define FMC_INT_CLR 0x20 ++#define FMC_INT_CLR_AHB_OP BIT(7) ++#define FMC_INT_CLR_WR_LOCK BIT(6) ++#define FMC_INT_CLR_DMA_ERR BIT(5) ++#define FMC_INT_CLR_ERR_ALARM BIT(4) ++#define FMC_INT_CLR_ERR_INVALID BIT(3) ++#define FMC_INT_CLR_ERR_VALID BIT(2) ++#define FMC_INT_CLR_OP_FAIL BIT(1) ++#define FMC_INT_CLR_OP_DONE BIT(0) ++ ++#define FMC_INT_CLR_ALL 0xff ++ ++/*****************************************************************************/ ++#define FMC_CMD 0x24 ++#define FMC_CMD_CMD2(_cmd) (((_cmd) & 0xff) << 8) ++#define FMC_CMD_CMD1(_cmd) ((_cmd) & 0xff) ++ ++/*****************************************************************************/ ++#define FMC_ADDRH 0x28 ++#define FMC_ADDRH_SET(_addr) ((_addr) & 0xff) ++ ++/*****************************************************************************/ ++#define FMC_ADDRL 0x2c ++#define FMC_ADDRL_BLOCK_MASK(_page) ((_page) & 0xffffffc0) ++#define FMC_ADDRL_BLOCK_H_MASK(_page) (((_page) & 0xffff) << 16) ++#define FMC_ADDRL_BLOCK_L_MASK(_page) ((_page) & 0xffc0) ++ ++#define READ_ID_ADDR 0x00 ++#define PROTECT_ADDR 0xa0 ++#define FEATURE_ADDR 0xb0 ++#define STATUS_ADDR 0xc0 ++/*****************************************************************************/ ++#define FMC_OP_CFG 0x30 ++#define OP_CFG_FM_CS(_cs) ((_cs) << 11) ++#define OP_CFG_FORCE_CS_EN(_en) ((_en) << 10) ++#define OP_CFG_MEM_IF_TYPE(_type) (((_type) & 0x7) << 7) ++#define OP_CFG_ADDR_NUM(_addr) (((_addr) & 0x7) << 4) ++#define OP_CFG_DUMMY_NUM(_dummy) ((_dummy) & 0xf) ++#define OP_CFG_OEN_EN (0x1 << 13) ++ ++#define IF_TYPE_SHIFT 7 ++#define IF_TYPE_MASK (0x7 << IF_TYPE_SHIFT) ++ ++#define READ_ID_ADDR_NUM 1 ++#define FEATURES_OP_ADDR_NUM 1 ++#define STD_OP_ADDR_NUM 3 ++ ++/*****************************************************************************/ ++#define FMC_SPI_OP_ADDR 0x34 ++ ++/*****************************************************************************/ ++#define FMC_DATA_NUM 0x38 ++#define FMC_DATA_NUM_CNT(_n) ((_n) & 0x3fff) ++ ++#define SPI_NOR_SR_LEN 1 /* Status Register length */ ++#define SPI_NOR_CR_LEN 1 /* Config Register length */ ++#define FEATURES_DATA_LEN 1 ++#define READ_OOB_BB_LEN 1 ++ ++#define PROTECT_BRWD_MASK BIT(7) ++#define PROTECT_BP3_MASK BIT(6) ++#define PROTECT_BP2_MASK BIT(5) ++#define PROTECT_BP1_MASK BIT(4) ++#define PROTECT_BP0_MASK BIT(3) ++ ++#define ANY_BP_ENABLE(_val) ((PROTECT_BP3_MASK & _val) \ ++ || (PROTECT_BP2_MASK & _val) \ ++ || (PROTECT_BP1_MASK & _val) \ ++ || (PROTECT_BP0_MASK & _val)) ++ ++#define ALL_BP_MASK (PROTECT_BP3_MASK \ ++ | PROTECT_BP2_MASK \ ++ | PROTECT_BP1_MASK \ ++ | PROTECT_BP0_MASK) ++ ++#define FEATURE_ECC_ENABLE (1 << 4) ++#define FEATURE_QE_ENABLE (1 << 0) ++ ++/*****************************************************************************/ ++#define FMC_OP 0x3c ++#define FMC_OP_DUMMY_EN BIT(8) ++#define FMC_OP_CMD1_EN BIT(7) ++#define FMC_OP_ADDR_EN BIT(6) ++#define FMC_OP_WRITE_DATA_EN BIT(5) ++#define FMC_OP_CMD2_EN BIT(4) ++#define FMC_OP_WAIT_READY_EN BIT(3) ++#define FMC_OP_READ_DATA_EN BIT(2) ++#define FMC_OP_READ_STATUS_EN BIT(1) ++#define FMC_OP_REG_OP_START BIT(0) ++ ++/*****************************************************************************/ ++#define FMC_DMA_LEN 0x40 ++#define FMC_DMA_LEN_SET(_len) ((_len) & 0x0fffffff) ++ ++/*****************************************************************************/ ++#define FMC_DMA_AHB_CTRL 0x48 ++#define FMC_DMA_AHB_CTRL_DMA_PP_EN BIT(3) ++#define FMC_DMA_AHB_CTRL_BURST16_EN BIT(2) ++#define FMC_DMA_AHB_CTRL_BURST8_EN BIT(1) ++#define FMC_DMA_AHB_CTRL_BURST4_EN BIT(0) ++ ++#define ALL_BURST_ENABLE (FMC_DMA_AHB_CTRL_BURST16_EN \ ++ | FMC_DMA_AHB_CTRL_BURST8_EN \ ++ | FMC_DMA_AHB_CTRL_BURST4_EN) ++ ++#define FMC_DMA_ADDR_OFFSET 4096 ++ ++/*****************************************************************************/ ++#define FMC_DMA_SADDR_D0 0x4c ++ ++/* Nand Flash pagesize is impossible over 32K; oobsize should less than 8K*/ ++#define HIFMC_DMA_MAX_PAGESIZE (0x8000) ++#define HIFMC_DMA_MAX_OOBSIZE (0x2000) ++/* HIFMC_DMA_MAX_LEN also suit for SPI Nor Flash DMA LEN */ ++#define HIFMC_DMA_MAX_LEN (HIFMC_DMA_MAX_PAGESIZE + HIFMC_DMA_MAX_OOBSIZE) ++#define HIFMC_DMA_MASK (HIFMC_DMA_MAX_LEN - 1) ++ ++/*****************************************************************************/ ++#define FMC_DMA_SADDR_D1 0x50 ++ ++/*****************************************************************************/ ++#define FMC_DMA_SADDR_D2 0x54 ++ ++/*****************************************************************************/ ++#define FMC_DMA_SADDR_D3 0x58 ++ ++/*****************************************************************************/ ++#define FMC_DMA_SADDR_OOB 0x5c ++ ++#ifdef CONFIG_64BIT ++/*****************************************************************************/ ++#define FMC_DMA_SADDRH_D0 0x200 ++#define FMC_DMA_SADDRH_SHIFT 0x3LL ++#define FMC_DMA_SADDRH_MASK (FMC_DMA_SADDRH_SHIFT << 32) ++ ++/*****************************************************************************/ ++#define FMC_DMA_SADDRH_OOB 0x210 ++#endif ++ ++/*****************************************************************************/ ++#define FMC_DMA_BLK_SADDR 0x60 ++#define FMC_DMA_BLK_SADDR_SET(_addr) ((_addr) & 0xffffff) ++ ++/*****************************************************************************/ ++#define FMC_DMA_BLK_LEN 0x64 ++#define FMC_DMA_BLK_LEN_SET(_len) ((_len) & 0xffff) ++ ++/*****************************************************************************/ ++#define FMC_OP_CTRL 0x68 ++#define OP_CTRL_RD_OPCODE(code) (((code) & 0xff) << 16) ++#define OP_CTRL_WR_OPCODE(code) (((code) & 0xff) << 8) ++#define OP_CTRL_RD_OP_SEL(_op) (((_op) & 0x3) << 4) ++#define OP_CTRL_DMA_OP(_type) ((_type) << 2) ++#define OP_CTRL_RW_OP(op) ((op) << 1) ++#define OP_CTRL_DMA_OP_READY BIT(0) ++ ++#define RD_OP_READ_ALL_PAGE 0x0 ++#define RD_OP_READ_OOB 0x1 ++#define RD_OP_BLOCK_READ 0x2 ++ ++#define RD_OP_SHIFT 4 ++#define RD_OP_MASK (0x3 << RD_OP_SHIFT) ++ ++#define OP_TYPE_DMA 0x0 ++#define OP_TYPE_REG 0x1 ++ ++#define FMC_OP_READ 0x0 ++#define FMC_OP_WRITE 0x1 ++#define RW_OP_READ 0x0 ++#define RW_OP_WRITE 0x1 ++ ++/*****************************************************************************/ ++#define FMC_OP_PARA 0x70 ++#define FMC_OP_PARA_RD_OOB_ONLY BIT(1) ++ ++/*****************************************************************************/ ++#define FMC_BOOT_SET 0x74 ++#define FMC_BOOT_SET_DEVICE_ECC_EN BIT(3) ++#define FMC_BOOT_SET_BOOT_QUAD_EN BIT(1) ++ ++/*****************************************************************************/ ++#define FMC_STATUS 0xac ++ ++/*****************************************************************************/ ++#ifndef FMC_VERSION ++#define FMC_VERSION 0xbc ++#endif ++ ++/* Hifmc IP version */ ++#ifndef HIFMC_VER_100 ++#define HIFMC_VER_100 (0x100) ++#endif ++ ++/*****************************************************************************/ ++/* DMA address align with 32 bytes. */ ++#define FMC_DMA_ALIGN 32 ++ ++#define FMC_CHIP_DELAY 25 ++/*****************************************************************************/ ++#define HIFMC_ECC_ERR_NUM0_BUF0 0xc0 ++#define GET_ECC_ERR_NUM(_i, _reg) (((_reg) >> ((_i) * 8)) & 0xff) ++ ++#define DISABLE 0 ++#define ENABLE 1 ++ ++/*****************************************************************************/ ++#define HIFMC_REG_ADDRESS_LEN 0x200 ++ ++/*****************************************************************************/ ++#define FMC_MAX_READY_WAIT_JIFFIES (HZ) ++ ++#define MAX_SPI_NOR_ID_LEN 8 ++#define MAX_NAND_ID_LEN 8 ++#define MAX_SPI_NAND_ID_LEN 3 ++ ++#define GET_OP 0 ++#define SET_OP 1 ++ ++#define STATUS_ECC_MASK (0x3 << 4) ++#define STATUS_P_FAIL_MASK (1 << 3) ++#define STATUS_E_FAIL_MASK (1 << 2) ++#define STATUS_WEL_MASK (1 << 1) ++#define STATUS_OIP_MASK (1 << 0) ++ ++/*****************************************************************************/ ++#define FMC_VERSION 0xbc ++ ++/* Hifmc IP version */ ++#define HIFMC_VER_100 (0x100) ++ ++#define CONFIG_SPI_NAND_MAX_CHIP_NUM (1) ++ ++#define CONFIG_HIFMC100_MAX_NAND_CHIP (1) ++ ++/*****************************************************************************/ ++#define GET_PAGE_INDEX(host) \ ++ ((host->addr_value[0] >> 16) | (host->addr_value[1] << 16)) ++/*****************************************************************************/ ++#define HIFMC_MAX_CHIP_NUM 2 ++ ++extern unsigned char hifmc_cs_user[]; ++ ++/*****************************************************************************/ ++#define hifmc_readl(_host, _reg) \ ++ (readl((char *)_host->regbase + (_reg))) ++ ++#define hifmc_readb( _addr) \ ++ (readb((void __iomem *)(_addr))) ++ ++#define hifmc_readw( _addr) \ ++ (readw((void __iomem *)(_addr))) ++ ++#define hifmc_writel(_host, _reg, _value) \ ++ (writel((u_int)(_value), ((char *)_host->regbase + (_reg)))) ++ ++#define hifmc_writeb(_val, _addr) \ ++ (writeb((u_int)(_val), ((char *)_addr))) ++ ++/*****************************************************************************/ ++#define FMC_WAIT_TIMEOUT 0x2000000 ++ ++#define FMC_CMD_WAIT_CPU_FINISH(_host) \ ++ do { \ ++ unsigned regval, timeout = FMC_WAIT_TIMEOUT * 2; \ ++ do { \ ++ regval = hifmc_readl((_host), FMC_OP); \ ++ --timeout; \ ++ } while ((regval & FMC_OP_REG_OP_START) && timeout); \ ++ if (!timeout) \ ++ pr_info("Error: Wait cmd cpu finish timeout!\n"); \ ++ } while (0) ++ ++/*****************************************************************************/ ++#define FMC_DMA_WAIT_INT_FINISH(_host) \ ++ do { \ ++ unsigned regval, timeout = FMC_WAIT_TIMEOUT; \ ++ do { \ ++ regval = hifmc_readl((_host), FMC_INT); \ ++ --timeout; \ ++ } while ((!(regval & FMC_INT_OP_DONE) && timeout)); \ ++ if (!timeout) \ ++ pr_info("Error: Wait dma int finish timeout!\n"); \ ++ } while (0) ++ ++/*****************************************************************************/ ++#define FMC_DMA_WAIT_CPU_FINISH(_host) \ ++ do { \ ++ unsigned regval, timeout = FMC_WAIT_TIMEOUT; \ ++ do { \ ++ regval = hifmc_readl((_host), FMC_OP_CTRL); \ ++ --timeout; \ ++ } while ((regval & OP_CTRL_DMA_OP_READY) && timeout); \ ++ if (!timeout) \ ++ pr_info("Error: Wait dma cpu finish timeout!\n"); \ ++ } while (0) ++ ++/*****************************************************************************/ ++#define BT_DBG 0 /* Boot init debug print */ ++#define ER_DBG 0 /* Erase debug print */ ++#define WR_DBG 0 /* Write debug print */ ++#define RD_DBG 0 /* Read debug print */ ++#define QE_DBG 0 /* Quad Enable debug print */ ++#define OP_DBG 0 /* OP command debug print */ ++#define DMA_DB 0 /* DMA read or write debug print */ ++#define AC_DBG 0 /* 3-4byte Address Cycle */ ++#define SR_DBG 0 /* Status Register debug print */ ++#define CR_DBG 0 /* Config Register debug print */ ++#define FT_DBG 0 /* Features debug print */ ++#define WE_DBG 0 /* Write Enable debug print */ ++#define BP_DBG 0 /* Block Protection debug print */ ++#define EC_DBG 0 /* enable/disable ecc0 and randomizer */ ++#define PM_DBG 0 /* power management debug */ ++ ++#define FMC_PR(_type, _fmt, arg...) \ ++ do { \ ++ if (_type) \ ++ DB_MSG(_fmt, ##arg) \ ++ } while (0) ++ ++#define DB_MSG(_fmt, arg...) \ ++ pr_info("%s(%d): " _fmt, __func__, __LINE__, ##arg); ++ ++#define DB_BUG(fmt, args...) \ ++ do { \ ++ pr_info("%s(%d): BUG: " fmt, __FILE__, __LINE__, ##args); \ ++ while (1) \ ++ ; \ ++ } while (0) ++ ++/*****************************************************************************/ ++enum hifmc_iftype { ++ IF_TYPE_STD, ++ IF_TYPE_DUAL, ++ IF_TYPE_DIO, ++ IF_TYPE_QUAD, ++ IF_TYPE_QIO, ++}; ++ ++struct hisi_fmc { ++ void __iomem *regbase; ++ void __iomem *iobase; ++ struct clk *clk; ++ struct mutex lock; ++ void *buffer; ++ dma_addr_t dma_buffer; ++}; ++ ++struct hifmc_cmd_op { ++ unsigned char cs; ++ unsigned char cmd; ++ unsigned char l_cmd; ++ unsigned char addr_h; ++ unsigned int addr_l; ++ unsigned int data_no; ++ unsigned short option; ++ unsigned short op_cfg; ++}; ++ ++extern struct mutex fmc_switch_mutex; ++ ++#endif /*__HISI_FMC_H*/ +diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h +index d8905a2..27f5c74 100644 +--- a/include/linux/mtd/nand.h ++++ b/include/linux/mtd/nand.h +@@ -80,6 +80,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); + #define NAND_CMD_READOOB 0x50 + #define NAND_CMD_ERASE1 0x60 + #define NAND_CMD_STATUS 0x70 ++#define NAND_CMD_STATUS_MULTI 0x71 + #define NAND_CMD_SEQIN 0x80 + #define NAND_CMD_RNDIN 0x85 + #define NAND_CMD_READID 0x90 +@@ -87,6 +88,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); + #define NAND_CMD_PARAM 0xec + #define NAND_CMD_GET_FEATURES 0xee + #define NAND_CMD_SET_FEATURES 0xef ++#define NAND_CMD_SYNC_RESET 0xfc + #define NAND_CMD_RESET 0xff + + #define NAND_CMD_LOCK 0x2a +@@ -925,9 +927,16 @@ static inline void nand_set_controller_data(struct nand_chip *chip, void *priv) + #define NAND_MFR_AMD 0x01 + #define NAND_MFR_MACRONIX 0xc2 + #define NAND_MFR_EON 0x92 ++#define NAND_MFR_WINBOND 0xef ++#define NAND_MFR_ATO 0x9b ++#define NAND_MFR_MXIC 0xc2 ++#define NAND_MFR_ALL_FLASH 0xc1 ++#define NAND_MFR_PARAGON 0xa1 + #define NAND_MFR_SANDISK 0x45 + #define NAND_MFR_INTEL 0x89 + #define NAND_MFR_ATO 0x9b ++#define NAND_MFR_GD_ESMT 0xc8 ++#define NAND_MFR_HEYANGTEK 0xc9 + + /* The maximum expected count of bytes in the NAND ID sequence */ + #define NAND_MAX_ID_LEN 8 +diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h +index c425c7b..f66420c 100644 +--- a/include/linux/mtd/spi-nor.h ++++ b/include/linux/mtd/spi-nor.h +@@ -12,7 +12,6 @@ + + #include + #include +-#include + + /* + * Manufacturer IDs +@@ -21,13 +20,50 @@ + * Sometimes these are the same as CFI IDs, but sometimes they aren't. + */ + #define SNOR_MFR_ATMEL CFI_MFR_ATMEL +-#define SNOR_MFR_GIGADEVICE 0xc8 + #define SNOR_MFR_INTEL CFI_MFR_INTEL + #define SNOR_MFR_MICRON CFI_MFR_ST /* ST Micro <--> Micron */ + #define SNOR_MFR_MACRONIX CFI_MFR_MACRONIX + #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_EON CFI_MFR_EON ++#define SNOR_MFR_WINBOND 0xef ++#define SNOR_MFR_ESMT 0x8c ++#define SNOR_MFR_GD 0xc8 ++ ++/* Flash set the RESET# from */ ++#define SPI_NOR_SR_RST_MASK BIT(7) ++#define SPI_NOR_GET_RST(val) (((val) & SPI_NOR_SR_RST_MASK) >> 7) ++#define SPI_NOR_SET_RST(val) ((val) | SPI_NOR_SR_RST_MASK) ++ ++/* Flash block protect */ ++#ifdef CONFIG_HISI_SPI_BLOCK_PROTECT ++#define _2M (0x200000UL) ++#define _4M (0x400000UL) ++#define _8M (0x800000UL) ++#define _16M (0x1000000UL) ++#define _32M (0x2000000UL) ++ ++#define BP_NUM_3 3 ++#define BP_NUM_4 4 ++ ++#define DEBUG_SPI_NOR_BP 0 ++ ++#define SPI_NOR_SR_SRWD_SHIFT 7 ++#define SPI_NOR_SR_SRWD_MASK (1 << SPI_NOR_SR_SRWD_SHIFT) ++ ++#define SPI_NOR_SR_BP0_SHIFT 2 ++#define SPI_NOR_SR_BP_WIDTH_4 0xf ++#define SPI_NOR_SR_BP_MASK_4 (SPI_NOR_SR_BP_WIDTH_4 << SPI_NOR_SR_BP0_SHIFT) ++ ++#define SPI_NOR_SR_BP_WIDTH_3 0x7 ++#define SPI_NOR_SR_BP_MASK_3 (SPI_NOR_SR_BP_WIDTH_3 << SPI_NOR_SR_BP0_SHIFT) ++ ++#define SPI_NOR_SR_TB_SHIFT 3 ++#define SPI_NOR_SR_TB_MASK (1 << SPI_NOR_SR_TB_SHIFT) ++ ++#define LOCK_LEVEL_MAX(bp_num) (((0x01) << bp_num) - 1) ++ ++#endif /* CONFIG_SPI_BLOCK_PROTECT */ + + /* + * Note on opcode nomenclature: some opcodes have a format like +@@ -40,27 +76,42 @@ + /* Flash opcodes. */ + #define SPINOR_OP_WREN 0x06 /* Write enable */ + #define SPINOR_OP_RDSR 0x05 /* Read status register */ ++#define SPINOR_OP_RDSR2 0x35 /* Read Status Register-2 */ ++#define SPINOR_OP_RDSR3 0x15 /* Read Status Register-3 */ + #define SPINOR_OP_WRSR 0x01 /* Write status register 1 byte */ ++#define SPINOR_OP_WRSR2 0x31 /* Write Status Register-2 1 byte*/ ++#define SPINOR_OP_WRSR3 0x11 /* Write Status Register-3 1 byte*/ + #define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */ + #define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */ +-#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual SPI) */ +-#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad SPI) */ ++#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual Output SPI) */ ++#define SPINOR_OP_READ_1_2_2 0xbb /* Read data bytes (Dual I/O SPI) */ ++#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad Output SPI) */ ++#define SPINOR_OP_READ_1_4_4 0xeb /* Read data bytes (Quad I/O SPI) */ + #define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */ ++#define SPINOR_OP_PP_1_1_4 0x32 /* Quad page program */ ++#define SPINOR_OP_PP_1_4_4 0x38 /* Quad page program */ + #define SPINOR_OP_BE_4K 0x20 /* Erase 4KiB block */ + #define SPINOR_OP_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ + #define SPINOR_OP_BE_32K 0x52 /* Erase 32KiB block */ + #define SPINOR_OP_CHIP_ERASE 0xc7 /* Erase whole flash chip */ + #define SPINOR_OP_SE 0xd8 /* Sector erase (usually 64KiB) */ + #define SPINOR_OP_RDID 0x9f /* Read JEDEC ID */ ++#define SPINOR_OP_RDSFDP 0x5a /* Read SFDP */ + #define SPINOR_OP_RDCR 0x35 /* Read configuration register */ + #define SPINOR_OP_RDFSR 0x70 /* Read flag status register */ + + /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ +-#define SPINOR_OP_READ4 0x13 /* Read data bytes (low frequency) */ +-#define SPINOR_OP_READ4_FAST 0x0c /* Read data bytes (high frequency) */ +-#define SPINOR_OP_READ4_1_1_2 0x3c /* Read data bytes (Dual SPI) */ +-#define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad SPI) */ ++#define SPINOR_OP_READ_4B 0x13 /* Read data bytes (low frequency) */ ++#define SPINOR_OP_READ_FAST_4B 0x0c /* Read data bytes (high frequency) */ ++#define SPINOR_OP_READ_1_1_2_4B 0x3c /* Read data bytes (Dual Output SPI) */ ++#define SPINOR_OP_READ_1_2_2_4B 0xbc /* Read data bytes (Dual I/O SPI) */ ++#define SPINOR_OP_READ_1_1_4_4B 0x6c /* Read data bytes (Quad Output SPI) */ ++#define SPINOR_OP_READ_1_4_4_4B 0xec /* Read data bytes (Quad I/O SPI) */ + #define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */ ++#define SPINOR_OP_PP_1_1_4_4B 0x34 /* Quad page program */ ++#define SPINOR_OP_PP_1_4_4_4B 0x3e /* Quad page program */ ++#define SPINOR_OP_BE_4K_4B 0x21 /* Erase 4KiB block */ ++#define SPINOR_OP_BE_32K_4B 0x5c /* Erase 32KiB block */ + #define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */ + + /* Used for SST flashes only. */ +@@ -73,12 +124,20 @@ + #define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */ + + /* Used for Spansion flashes only. */ ++#define SPINOR_OP_BRRD 0x16 /* Bank register write */ + #define SPINOR_OP_BRWR 0x17 /* Bank register write */ + ++/* Used for GigaDevice flashes only. */ ++#define SPINOR_OP_WRCR 0x31 /* Config register write */ ++ + /* Used for Micron flashes only. */ + #define SPINOR_OP_RD_EVCR 0x65 /* Read EVCR register */ + #define SPINOR_OP_WD_EVCR 0x61 /* Write EVCR register */ + ++/* Software reset code */ ++#define SPINOR_ENABLE_RESET 0x66 /* Enable reset */ ++#define SPINOR_OP_RESET 0x99 /* Reset */ ++ + /* Status Register bits. */ + #define SR_WIP BIT(0) /* Write in progress */ + #define SR_WEL BIT(1) /* Write enable latch */ +@@ -92,6 +151,7 @@ + #define SR_QUAD_EN_MX BIT(6) /* Macronix Quad I/O */ + + /* Enhanced Volatile Configuration Register bits */ ++#define EVCR_DUAL_EN_MICRON BIT(6) /* Micron Dual I/O */ + #define EVCR_QUAD_EN_MICRON BIT(7) /* Micron Quad I/O */ + + /* Flag Status Register bits */ +@@ -100,11 +160,105 @@ + /* Configuration Register bits. */ + #define CR_QUAD_EN_SPAN BIT(1) /* Spansion Quad I/O */ + +-enum read_mode { +- SPI_NOR_NORMAL = 0, +- SPI_NOR_FAST, +- SPI_NOR_DUAL, +- SPI_NOR_QUAD, ++/* Supported modes */ ++enum spi_nor_mode_index { ++ /* Sorted by ascending priority order */ ++ SNOR_MIDX_SLOW = 0, ++ SNOR_MIDX_1_1_1, ++ SNOR_MIDX_1_1_2, ++ SNOR_MIDX_1_2_2, ++ SNOR_MIDX_1_1_4, ++ SNOR_MIDX_1_4_4, ++ ++ SNOR_MIDX_MAX ++}; ++ ++#define SNOR_MODE_SLOW BIT(SNOR_MIDX_SLOW) ++#define SNOR_MODE_1_1_1 BIT(SNOR_MIDX_1_1_1) ++#define SNOR_MODE_1_1_2 BIT(SNOR_MIDX_1_1_2) ++#define SNOR_MODE_1_2_2 BIT(SNOR_MIDX_1_2_2) ++#define SNOR_MODE_1_1_4 BIT(SNOR_MIDX_1_1_4) ++#define SNOR_MODE_1_4_4 BIT(SNOR_MIDX_1_4_4) ++ ++struct spi_nor_modes { ++ u32 rd_modes; /* supported SPI modes for (Fast) Read */ ++ u32 wr_modes; /* supported SPI modes for Page Program */ ++}; ++ ++struct spi_nor_read_op { ++ u8 num_mode_clocks; ++ u8 num_wait_states; ++ u8 opcode; ++}; ++ ++#define SNOR_OP_READ(_num_mode_clocks, _num_wait_states, _opcode) \ ++ { \ ++ .num_mode_clocks = _num_mode_clocks, \ ++ .num_wait_states = _num_wait_states, \ ++ .opcode = _opcode, \ ++ } ++ ++struct spi_nor_erase_type { ++ u8 size; /* specifies 'N' so erase size = 2^N */ ++ u8 opcode; ++}; ++ ++#define SNOR_OP_ERASE(_size, _opcode) { .size = _size, .opcode = _opcode } ++#define SNOR_OP_ERASE_64K(_opcode) SNOR_OP_ERASE(0x10, _opcode) ++#define SNOR_OP_ERASE_32K(_opcode) SNOR_OP_ERASE(0x0f, _opcode) ++#define SNOR_OP_ERASE_4K(_opcode) SNOR_OP_ERASE(0x0c, _opcode) ++ ++struct spi_nor; ++ ++#define SNOR_MAX_ERASE_TYPES 4 ++ ++struct spi_nor_basic_flash_parameter { ++ /* Fast Read settings */ ++ u32 rd_modes; ++ struct spi_nor_read_op reads[SNOR_MIDX_MAX]; ++ ++ /* Page Program settings */ ++ u32 wr_modes; ++ u8 page_programs[SNOR_MIDX_MAX]; ++ ++ /* Sector Erase settings */ ++ struct spi_nor_erase_type erase_types[SNOR_MAX_ERASE_TYPES]; ++ ++ int (*enable_quad_io)(struct spi_nor *nor); ++}; ++ ++#define SNOR_PROTO_CODE_OFF 8 ++#define SNOR_PROTO_CODE_MASK GENMASK(11, 8) ++#define SNOR_PROTO_CODE_TO_PROTO(code) \ ++ (((code) << SNOR_PROTO_CODE_OFF) & SNOR_PROTO_CODE_MASK) ++#define SNOR_PROTO_CODE_FROM_PROTO(proto) \ ++ ((((u32)(proto)) & SNOR_PROTO_CODE_MASK) >> SNOR_PROTO_CODE_OFF) ++ ++#define SNOR_PROTO_ADDR_OFF 4 ++#define SNOR_PROTO_ADDR_MASK GENMASK(7, 4) ++#define SNOR_PROTO_ADDR_TO_PROTO(addr) \ ++ (((addr) << SNOR_PROTO_ADDR_OFF) & SNOR_PROTO_ADDR_MASK) ++#define SNOR_PROTO_ADDR_FROM_PROTO(proto) \ ++ ((((u32)(proto)) & SNOR_PROTO_ADDR_MASK) >> SNOR_PROTO_ADDR_OFF) ++ ++#define SNOR_PROTO_DATA_OFF 0 ++#define SNOR_PROTO_DATA_MASK GENMASK(3, 0) ++#define SNOR_PROTO_DATA_TO_PROTO(data) \ ++ (((data) << SNOR_PROTO_DATA_OFF) & SNOR_PROTO_DATA_MASK) ++#define SNOR_PROTO_DATA_FROM_PROTO(proto) \ ++ ((((u32)(proto)) & SNOR_PROTO_DATA_MASK) >> SNOR_PROTO_DATA_OFF) ++ ++#define SNOR_PROTO(code, addr, data) \ ++ (SNOR_PROTO_CODE_TO_PROTO(code) | \ ++ SNOR_PROTO_ADDR_TO_PROTO(addr) | \ ++ SNOR_PROTO_DATA_TO_PROTO(data)) ++ ++enum spi_nor_protocol { ++ SNOR_PROTO_1_1_1 = SNOR_PROTO(1, 1, 1), /* SPI */ ++ SNOR_PROTO_1_1_2 = SNOR_PROTO(1, 1, 2), /* Dual Output */ ++ SNOR_PROTO_1_2_2 = SNOR_PROTO(1, 2, 2), /* Dual IO */ ++ SNOR_PROTO_1_1_4 = SNOR_PROTO(1, 1, 4), /* Quad Output */ ++ SNOR_PROTO_1_4_4 = SNOR_PROTO(1, 4, 4), /* Quad IO */ + }; + + #define SPI_NOR_MAX_CMD_SIZE 8 +@@ -121,20 +275,26 @@ enum spi_nor_option_flags { + SNOR_F_HAS_SR_TB = BIT(1), + }; + ++struct mtd_info; ++ + /** + * struct spi_nor - Structure for defining a the SPI NOR layer + * @mtd: point to a mtd_info structure + * @lock: the lock for the read/write/erase/lock/unlock operations + * @dev: point to a spi device, or a spi nor controller device. ++ * @flash_node: point to a device node describing this flash instance. + * @page_size: the page size of the SPI NOR + * @addr_width: number of address bytes + * @erase_opcode: the opcode for erasing a sector + * @read_opcode: the read opcode + * @read_dummy: the dummy needed by the read operation + * @program_opcode: the program opcode +- * @flash_read: the mode of the read + * @sst_write_second: used by the SST write operation + * @flags: flag options for the current SPI-NOR (SNOR_F_*) ++ * @erase_proto: the SPI protocol used by erase operations ++ * @read_proto: the SPI protocol used by read operations ++ * @write_proto: the SPI protocol used by write operations ++ * @reg_proto the SPI protocol used by read_reg/write_reg operations + * @cmd_buf: used by the write_reg + * @prepare: [OPTIONAL] do some preparations for the + * read/write/erase/lock/unlock operations +@@ -157,13 +317,16 @@ struct spi_nor { + struct mtd_info mtd; + struct mutex lock; + struct device *dev; ++ struct device_node *flash_node; + u32 page_size; + u8 addr_width; + u8 erase_opcode; + u8 read_opcode; + u8 read_dummy; + u8 program_opcode; +- enum read_mode flash_read; ++ enum spi_nor_protocol erase_proto; ++ enum spi_nor_protocol read_proto; ++ enum spi_nor_protocol write_proto; + bool sst_write_second; + u32 flags; + u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE]; +@@ -183,6 +346,11 @@ struct spi_nor { + int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len); + int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len); + ++#ifdef CONFIG_HISI_SPI_BLOCK_PROTECT ++ unsigned int end_addr; ++ unsigned int lock_level_max; ++ unsigned char level; ++#endif + void *priv; + }; + +@@ -201,7 +369,7 @@ static inline struct device_node *spi_nor_get_flash_node(struct spi_nor *nor) + * spi_nor_scan() - scan the SPI NOR + * @nor: the spi_nor structure + * @name: the chip type name +- * @mode: the read mode supported by the driver ++ * @modes: the SPI modes supported by the controller driver + * + * The drivers can use this fuction to scan the SPI NOR. + * In the scanning, it will try to get all the necessary information to +@@ -211,6 +379,12 @@ 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); ++int spi_nor_scan(struct spi_nor *nor, const char *name, ++ struct spi_nor_modes *modes); ++void spi_nor_driver_shutdown(struct spi_nor *nor); ++#ifdef CONFIG_PM ++int spi_nor_suspend(struct spi_nor *nor, pm_message_t state); ++int spi_nor_resume(struct spi_nor *nor); ++#endif + + #endif +diff --git a/include/linux/phy.h b/include/linux/phy.h +index 6c9b1e0..b08bcf7 100644 +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -829,6 +829,10 @@ int phy_register_fixup_for_id(const char *bus_id, + int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask, + int (*run)(struct phy_device *)); + ++int phy_unregister_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask); ++int phy_unregister_fixup_for_id(const char *bus_id); ++int phy_unregister_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask); ++ + int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable); + int phy_get_eee_err(struct phy_device *phydev); + int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data); +diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h +index 4b743ac..54eeb07 100644 +--- a/include/linux/spi/spi.h ++++ b/include/linux/spi/spi.h +@@ -233,6 +233,8 @@ struct spi_transfer; + * @remove: Unbinds this driver from the spi device + * @shutdown: Standard shutdown callback used during system state + * transitions such as powerdown/halt and kexec ++ * @suspend: Standard suspend callback used during system state transitions ++ * @resume: Standard resume callback used during system state transitions + * @driver: SPI device drivers should initialize the name and owner + * field of this structure. + * +@@ -253,6 +255,8 @@ struct spi_driver { + int (*probe)(struct spi_device *spi); + int (*remove)(struct spi_device *spi); + void (*shutdown)(struct spi_device *spi); ++ int (*suspend)(struct spi_device *spi, pm_message_t mesg); ++ int (*resume)(struct spi_device *spi); + struct device_driver driver; + }; + +diff --git a/include/uapi/linux/i2c-dev.h b/include/uapi/linux/i2c-dev.h +index 2f05e66..e68dbb9 100644 +--- a/include/uapi/linux/i2c-dev.h ++++ b/include/uapi/linux/i2c-dev.h +@@ -50,6 +50,9 @@ + + #define I2C_PEC 0x0708 /* != 0 to use PEC with SMBus */ + #define I2C_SMBUS 0x0720 /* SMBus transfer */ ++#define I2C_16BIT_REG 0x0709 /* 16BIT REG WIDTH */ ++#define I2C_16BIT_DATA 0x070a /* 16BIT DATA WIDTH */ ++#define I2C_DMA 0x070b /* DMA mode */ + + + /* This is the structure as used in the I2C_SMBUS ioctl call */ +diff --git a/include/uapi/linux/i2c.h b/include/uapi/linux/i2c.h +index 009e27b..4195a49 100644 +--- a/include/uapi/linux/i2c.h ++++ b/include/uapi/linux/i2c.h +@@ -71,12 +71,19 @@ struct i2c_msg { + #define I2C_M_RD 0x0001 /* read data, from slave to master */ + /* I2C_M_RD is guaranteed to be 0x0001! */ + #define I2C_M_TEN 0x0010 /* this is a ten bit chip address */ ++#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */ ++#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ ++#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ + #define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */ + #define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */ + #define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ + #define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ + #define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_NOSTART */ + #define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */ ++#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */ ++#define I2C_M_16BIT_REG 0x0002 /* indicate reg bit-width is 16bit */ ++#define I2C_M_16BIT_DATA 0x0008 /* indicate data bit-width is 16bit */ ++#define I2C_M_DMA 0x0004 /* indicate use dma mode */ + __u16 len; /* msg length */ + __u8 *buf; /* pointer to msg data */ + }; +diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c +index 5ebee31..c0942b7 100644 +--- a/kernel/sched/cputime.c ++++ b/kernel/sched/cputime.c +@@ -75,6 +75,9 @@ static cputime_t irqtime_account_update(u64 irqtime, int idx, cputime_t maxtime) + u64 *cpustat = kcpustat_this_cpu->cpustat; + cputime_t irq_cputime; + ++ if (nsecs_to_cputime64(irqtime) <= cpustat[idx]) ++ return 0; ++ + irq_cputime = nsecs_to_cputime64(irqtime) - cpustat[idx]; + irq_cputime = min(irq_cputime, maxtime); + cpustat[idx] += irq_cputime; +diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c +index 7001da9..b7efe2f 100644 +--- a/net/core/net_namespace.c ++++ b/net/core/net_namespace.c +@@ -263,7 +263,7 @@ struct net *get_net_ns_by_id(struct net *net, int id) + spin_lock_irqsave(&net->nsid_lock, flags); + peer = idr_find(&net->netns_ids, id); + if (peer) +- get_net(peer); ++ peer = maybe_get_net(peer); + spin_unlock_irqrestore(&net->nsid_lock, flags); + rcu_read_unlock(); + +diff --git a/net/core/sock.c b/net/core/sock.c +index 1989b3d..221edb6 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -1957,7 +1957,11 @@ int sock_cmsg_send(struct sock *sk, struct msghdr *msg, + EXPORT_SYMBOL(sock_cmsg_send); + + /* On 32bit arches, an skb frag is limited to 2^15 */ ++#if defined(CONFIG_ARCH_HI3516A) ++#define SKB_FRAG_PAGE_ORDER 0 ++#else + #define SKB_FRAG_PAGE_ORDER get_order(32768) ++#endif + + /** + * skb_page_frag_refill - check that a page_frag contains enough room +diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c +index e9065b8..abb2c30 100644 +--- a/net/ipv6/output_core.c ++++ b/net/ipv6/output_core.c +@@ -78,7 +78,7 @@ EXPORT_SYMBOL(ipv6_select_ident); + + int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) + { +- u16 offset = sizeof(struct ipv6hdr); ++ unsigned int offset = sizeof(struct ipv6hdr); + unsigned int packet_len = skb_tail_pointer(skb) - + skb_network_header(skb); + int found_rhdr = 0; +@@ -86,6 +86,7 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) + + while (offset <= packet_len) { + struct ipv6_opt_hdr *exthdr; ++ unsigned int len; + + switch (**nexthdr) { + +@@ -111,7 +112,10 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) + + exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) + + offset); +- offset += ipv6_optlen(exthdr); ++ len = ipv6_optlen(exthdr); ++ if (len + offset >= IPV6_MAXPLEN) ++ return -EINVAL; ++ offset += len; + *nexthdr = &exthdr->nexthdr; + } + +diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean +index 50616ea..2e70c6f 100644 +--- a/scripts/Makefile.clean ++++ b/scripts/Makefile.clean +@@ -11,7 +11,7 @@ include scripts/Kbuild.include + + # The filename Kbuild has precedence over Makefile + kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) +-include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile) ++-include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile) + + # Figure out what we need to build from the various variables + # ========================================================================== +diff --git a/scripts/setlocalversion b/scripts/setlocalversion +old mode 100755 +new mode 100644 +index 966dd39..5a4833a +--- a/scripts/setlocalversion ++++ b/scripts/setlocalversion +@@ -153,6 +153,7 @@ if test ! "$srctree" -ef .; then + res="$res$(collect_files "$srctree"/localversion*)" + fi + ++LOCALVERSION= + # CONFIG_LOCALVERSION and LOCALVERSION (if set) + res="${res}${CONFIG_LOCALVERSION}${LOCALVERSION}" + diff --git a/br-ext-chip-hisilicon/board/hi3516cv300/hi3516cv300.config b/br-ext-chip-hisilicon/board/hi3516cv300/hi3516cv300.config new file mode 100644 index 000000000..72e91bbfb --- /dev/null +++ b/br-ext-chip-hisilicon/board/hi3516cv300/hi3516cv300.config @@ -0,0 +1,2 @@ +MEM_START_ADDR=0x80000000 +KERNEL_UPLOAD_ADDR=0x81000000 diff --git a/br-ext-chip-hisilicon/board/hi3516cv300/hi3516ev100.config b/br-ext-chip-hisilicon/board/hi3516cv300/hi3516ev100.config new file mode 100644 index 000000000..72e91bbfb --- /dev/null +++ b/br-ext-chip-hisilicon/board/hi3516cv300/hi3516ev100.config @@ -0,0 +1,2 @@ +MEM_START_ADDR=0x80000000 +KERNEL_UPLOAD_ADDR=0x81000000 diff --git a/br-ext-chip-hisilicon/board/hi3516cv300/kernel/hi3516cv300.generic.config b/br-ext-chip-hisilicon/board/hi3516cv300/kernel/hi3516cv300.generic.config new file mode 100644 index 000000000..daa956ec9 --- /dev/null +++ b/br-ext-chip-hisilicon/board/hi3516cv300/kernel/hi3516cv300.generic.config @@ -0,0 +1,2543 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 3.18.20 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_ARM_HAS_SG_CHAIN=y +CONFIG_MIGHT_HAVE_PCI=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=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_GENERIC_BUG=y +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_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +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_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +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_HARDIRQS_SW_RESEND=y +CONFIG_IRQ_DOMAIN=y +CONFIG_HANDLE_DOMAIN_IRQ=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +CONFIG_NO_HZ=y +# CONFIG_HIGH_RES_TIMERS is not set + +# +# CPU/Task time and stats accounting +# +CONFIG_VIRT_CPU_ACCOUNTING=y +# CONFIG_TICK_CPU_ACCOUNTING is not set +CONFIG_VIRT_CPU_ACCOUNTING_GEN=y +# 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_PREEMPT_RCU is not set +# CONFIG_TASKS_RCU is not set +# CONFIG_RCU_STALL_COMMON is not set +CONFIG_CONTEXT_TRACKING=y +# CONFIG_CONTEXT_TRACKING_FORCE is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_BUILD_BIN2C is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CGROUP_FREEZER is not set +# CONFIG_CGROUP_DEVICE is not set +# CONFIG_CPUSETS is not set +# CONFIG_CGROUP_CPUACCT is not set +# CONFIG_RESOURCE_COUNTERS is not set +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_CFS_BANDWIDTH is not set +# CONFIG_RT_GROUP_SCHED is not set +# CONFIG_BLK_CGROUP is not set +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_IPC_NS=y +# CONFIG_USER_NS is not set +CONFIG_PID_NS=y +CONFIG_NET_NS=y +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_RD_LZ4=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_BPF=y +# CONFIG_EXPERT is not set +CONFIG_UID16=y +# CONFIG_SGETMASK_SYSCALL is not set +CONFIG_SYSFS_SYSCALL=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +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_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=y +CONFIG_SLUB_DEBUG=y +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_JUMP_LABEL is not set +# CONFIG_UPROBES is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OLD_SIGACTION=y + +# +# GCOV-based kernel profiling +# +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=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_BLOCK=y +CONFIG_LBDAF=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +CONFIG_BLK_CMDLINE_PARSER=y + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_CMDLINE_PARTITION=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" +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=y + +# +# System Type +# +CONFIG_MMU=y +CONFIG_ARCH_MULTIPLATFORM=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP 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_MSM is not set +# CONFIG_ARCH_SHMOBILE_LEGACY is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C24XX is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP1 is not set + +# +# Multiple platform selection +# + +# +# CPU Core family selection +# +# CONFIG_ARCH_MULTI_V4 is not set +# CONFIG_ARCH_MULTI_V4T is not set +CONFIG_ARCH_MULTI_V5=y +CONFIG_ARCH_MULTI_V4_V5=y +# CONFIG_ARCH_MULTI_V6 is not set +# CONFIG_ARCH_MULTI_V7 is not set +CONFIG_ARCH_MULTI_CPU_AUTO=y +# CONFIG_ARCH_MVEBU is not set +CONFIG_ARCH_HISI=y + +# +# Hisilicon platform type +# +CONFIG_ARCH_HI3516CV300=y +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_NSPIRE is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_WM8505 is not set +CONFIG_ARM_TIMER_SP804=y + +# +# Processor Type +# +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_PABRT_LEGACY=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_USE_DOMAINS=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_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +CONFIG_NEED_KUSER_HELPERS=y +CONFIG_KUSER_HELPERS=y +# CONFIG_CACHE_L2X0 is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 +CONFIG_MULTI_IRQ_HANDLER=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y +# CONFIG_PCI is not set +# CONFIG_PCI_SYSCALL is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y +CONFIG_VMSPLIT_3G=y +# 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=y +# CONFIG_HIGHPTE is not set +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +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_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=999999 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_BOUNCE=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_NEED_PER_CPU_KM=y +# CONFIG_CLEANCACHE is not set +# CONFIG_FRONTSWAP is not set +# CONFIG_CMA is not set +# CONFIG_ZPOOL is not set +# CONFIG_ZBUD is not set +# CONFIG_ZSMALLOC 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_ARM_FLUSH_CONSOLE_ON_RESTART is not set + +# +# Boot options +# +CONFIG_USE_OF=y +CONFIG_ATAGS=y +# CONFIG_DEPRECATED_PARAM_STRUCT is not set +# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y +# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set +CONFIG_CMDLINE="" +# 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_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_BINFMT_SCRIPT=y +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_COREDUMP=y + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_WAKELOCK=y +CONFIG_HIBERNATE_CALLBACKS=y +CONFIG_HISI_SNAPSHOT_BOOT=y +# CONFIG_DEFAULT_MTD is not set +CONFIG_DEFAULT_DDR=y +CONFIG_SNAPSHOT_BUF_START=0x8a000000 +CONFIG_SNAPSHOT_BUF_SIZE=0x4000000 +CONFIG_HIBERNATION=y +CONFIG_GZIP_COMPRESS=y +CONFIG_PM_STD_PARTITION="" +CONFIG_PM_SLEEP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +# CONFIG_PM_RUNTIME is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM_EMULATION is not set +CONFIG_PM_CLK=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_CPU_PM=y +# CONFIG_SUSPEND_TIME is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM_CPU_SUSPEND=y +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 is not set +# 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=m +# 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_GENEVE 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=m +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG 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=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_VTI is not set +CONFIG_IPV6_SIT=m +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_GRE is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_ANDROID_PARANOID_NETWORK is not set +CONFIG_NET_ACTIVITY_STATS=y +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NET_PTP_CLASSIFY is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK_ACCT is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NF_TABLES is not set +# CONFIG_NETFILTER_XTABLES is not set +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV4 is not set +# CONFIG_NF_LOG_ARP is not set +# CONFIG_NF_LOG_IPV4 is not set +# CONFIG_NF_REJECT_IPV4 is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set + +# +# IPv6: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV6 is not set +# CONFIG_NF_REJECT_IPV6 is not set +# CONFIG_NF_LOG_IPV6 is not set +# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_NET_MPLS_GSO is not set +# CONFIG_HSR is not set +# CONFIG_CGROUP_NET_PRIO is not set +# CONFIG_CGROUP_NET_CLASSID 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_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +# CONFIG_WIMAX is not set +# CONFIG_RFKILL 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_HAVE_BPF_JIT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_UEVENT_HELPER is not set +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set +CONFIG_ALLOW_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +# CONFIG_HAVE_CPU_AUTOPROBE is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_FENCE_TRACE 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_SWAP is not set +CONFIG_HIFMC=y +CONFIG_HIFMC_SPI_NAND=y +# CONFIG_HIFMC_NAND 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 is not set +# 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_IDS=y +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_DENALI is not set +# CONFIG_MTD_NAND_GPIO is not set +# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_DOCG4 is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set +# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set +# CONFIG_MTD_NAND_HINFC610 is not set +# CONFIG_HIFMC100_NAND is not set +CONFIG_HIFMC100_SPI_NAND=y +CONFIG_SPI_NAND_MAX_CHIP_NUM=1 +# CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC is not set +CONFIG_HIFMC100_AUTO_PAGESIZE_ECC=y +# CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE 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_SPI_NOR_USE_4K_SECTORS is not set +CONFIG_SPI_HISI_SFC=y +CONFIG_CLOSE_SPI_8PIN_4IO=y +CONFIG_HISI_SPI_BLOCK_PROTECT=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_LIMIT=20 +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +# CONFIG_MTD_UBI_BLOCK is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +# CONFIG_OF_SELFTEST 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_MTD=y +CONFIG_OF_RESERVED_MEM=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=65536 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set + +# +# Misc devices +# +# 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_BH1780 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_UID_STAT is not set +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI 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 +# + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# +# CONFIG_ECHO is not set +# CONFIG_CXL_BASE is not set + +# +# hisi 'himm/himd.l/himc'support +# +# CONFIG_HISI_REG is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=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_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_NLMON is not set + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6060 is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +# CONFIG_NET_DSA_MV88E6131 is not set +# CONFIG_NET_DSA_MV88E6123_61_65 is not set +# CONFIG_NET_DSA_MV88E6171 is not set +# CONFIG_NET_DSA_BCM_SF2 is not set +CONFIG_ETHERNET=y +# CONFIG_ALTERA_TSE is not set +# CONFIG_NET_XGENE is not set +# CONFIG_NET_VENDOR_ARC 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_FARADAY is not set +CONFIG_NET_VENDOR_HISILICON=y +# CONFIG_HIX5HD2_GMAC is not set +CONFIG_HISI_FEMAC=y +# CONFIG_HIETH_GMAC is not set +# CONFIG_HIETH_SWITCH_FABRIC 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=y +# CONFIG_ENC28J60 is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_ETHOC is not set +# CONFIG_NET_VENDOR_QUALCOMM 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_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_AT803X_PHY is not set +# CONFIG_AMD_PHY is not set +# CONFIG_AMD_XGBE_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY 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_BCM_UNIMAC is not set +CONFIG_MDIO_HISI_FEMAC=y +# CONFIG_MDIO_HISI_GEMAC 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_USBNET is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_WLAN is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_ISDN 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=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set +# CONFIG_INPUT_KEYRESET is not set +# CONFIG_INPUT_KEYCOMBO is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_CAP1106 is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_CYPRESS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB 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 + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# 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=y + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X 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_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_ST_ASC is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_DCC_TTY 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=m + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL 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_CBUS_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_GPIO is not set +CONFIG_I2C_HIBVT=y +# CONFIG_I2C_HISI_V110 is not set +# CONFIG_I2C_NOMADIK 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_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +CONFIG_SPI_PL022=y +# 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_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=y +# 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_PINCONF=y +CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +CONFIG_PINCTRL_SINGLE=y +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_OF_GPIO=y +CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_DWAPB is not set +# CONFIG_GPIO_EM is not set +# CONFIG_GPIO_ZEVIO is not set +CONFIG_GPIO_PL061=y +# CONFIG_GPIO_SCH311X is not set +# CONFIG_GPIO_SYSCON is not set +# CONFIG_GPIO_GRGPIO is not set + +# +# I2C GPIO expanders: +# +# 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_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# LPC GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# + +# +# USB GPIO expanders: +# +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_SMB347 is not set +CONFIG_POWER_RESET=y +# CONFIG_POWER_RESET_BRCMSTB is not set +# CONFIG_POWER_RESET_GPIO is not set +# CONFIG_POWER_RESET_GPIO_RESTART is not set +CONFIG_POWER_RESET_HISI=y +# CONFIG_POWER_RESET_LTC2952 is not set +# CONFIG_POWER_RESET_RESTART is not set +# CONFIG_POWER_RESET_VERSATILE is not set +CONFIG_POWER_RESET_SYSCON=y +# CONFIG_POWER_AVS is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG 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=y +# 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_BCM590XX is not set +# CONFIG_MFD_AXP20X 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_DA9063 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_MFD_HISI_FMC=y +# CONFIG_HTC_EGPIO 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_MAX77686 is not set +# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +CONFIG_MFD_SYSCON=y +# 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_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 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=m + +# +# Multimedia core support +# +CONFIG_MEDIA_CAMERA_SUPPORT=y +# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set +# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set +# CONFIG_MEDIA_RADIO_SUPPORT is not set +# CONFIG_MEDIA_SDR_SUPPORT is not set +# CONFIG_MEDIA_RC_SUPPORT is not set +# CONFIG_MEDIA_CONTROLLER is not set +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L2=m +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_VIDEOBUF2_CORE=m +CONFIG_VIDEOBUF2_MEMOPS=m +CONFIG_VIDEOBUF2_VMALLOC=m +# CONFIG_TTPCI_EEPROM is not set + +# +# Media drivers +# +# CONFIG_MEDIA_USB_SUPPORT is not set +# CONFIG_V4L_PLATFORM_DRIVERS is not set +# CONFIG_V4L_MEM2MEM_DRIVERS is not set +# CONFIG_V4L_TEST_DRIVERS is not set + +# +# Supported MMC/SDIO adapters +# +# CONFIG_CYPRESS_FIRMWARE is not set + +# +# Media ancillary drivers (tuners, sensors, i2c, frontends) +# +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y + +# +# Audio decoders, processors and mixers +# + +# +# RDS decoders +# + +# +# Video decoders +# + +# +# Video and audio decoders +# + +# +# Video encoders +# + +# +# Camera sensor devices +# + +# +# Flash devices +# + +# +# Video improvement chips +# + +# +# Audio/Video compression chips +# + +# +# Miscellaneous helper chips +# + +# +# Sensors used on soc_camera driver +# + +# +# Tools to develop new frontends +# +# CONFIG_DVB_DUMMY_FE is not set + +# +# Graphics support +# +# CONFIG_IMX_IPUV3_CORE is not set + +# +# Direct Rendering Manager +# +# CONFIG_DRM is not set + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_CMDLINE=y +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_FB_SSD1307 is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_VGASTATE is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set +# CONFIG_LOGO is not set +# CONFIG_SOUND is not set + +# +# HID support +# +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set +# CONFIG_HIDRAW is not set +# CONFIG_UHID is not set +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +CONFIG_HID_A4TECH=y +# CONFIG_HID_ACRUX is not set +CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_AUREAL is not set +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +# CONFIG_HID_CP2112 is not set +CONFIG_HID_CYPRESS=y +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_ELECOM is not set +# CONFIG_HID_ELO is not set +CONFIG_HID_EZKEY=y +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_HUION is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_TWINHAN is not set +CONFIG_HID_KENSINGTON=y +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LENOVO is not set +CONFIG_HID_LOGITECH=y +# CONFIG_HID_LOGITECH_HIDPP is not set +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGIG940_FF is not set +# CONFIG_LOGIWHEELS_FF is not set +# CONFIG_HID_MAGICMOUSE is not set +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PENMOUNT is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_RMI is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HID_SENSOR_HUB is not set + +# +# USB HID support +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV 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 is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_FSM is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB_CBAF 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=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_FUSBH200_HCD is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_MAX3421_HCD is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +# 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 is not set +# 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 +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK 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 is not set +# CONFIG_USB_CHIPIDEA 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_LED 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_SISUSBVGA 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_LINK_LAYER_TEST is not set + +# +# USB Physical Layer drivers +# +# CONFIG_USB_PHY is not set +# CONFIG_USB_OTG_WAKELOCK is not set +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_AM335X_PHY_USB 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=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_MV_UDC is not set +CONFIG_HIUSB_DEVICE2_0=y +CONFIG_USB_HISI_UDC=m +# CONFIG_USB_AUTO_SWITCH is not set +# CONFIG_HIUSB_DEVICE3_0 is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_LIBCOMPOSITE=m +CONFIG_USB_F_MASS_STORAGE=m +CONFIG_USB_F_UAC1=m +CONFIG_USB_F_UVC=m +# CONFIG_USB_CONFIGFS is not set +# CONFIG_USB_ZERO is not set +CONFIG_USB_AUDIO=m +CONFIG_GADGET_UAC1=y +# CONFIG_USB_ETH is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +CONFIG_USB_MASS_STORAGE=m +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set +CONFIG_USB_G_WEBCAM_AUDIO=m +# CONFIG_UWB is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_CLKGATE is not set +CONFIG_MMC_EMBEDDED_SDIO=y +# CONFIG_MMC_PARANOID_SD_INIT is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_ARMMMCI is not set +# CONFIG_MMC_SDHCI is not set +# 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_HIMCIV200=y +CONFIG_SEND_AUTO_STOP=y +CONFIG_DETECT_CARD_TIME=200 +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_SWITCH is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_EDAC is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES 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 + +# +# SOC (System On Chip) specific Drivers +# +# CONFIG_SOC_TI 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_SI570 is not set +# CONFIG_COMMON_CLK_PXA is not set +# CONFIG_COMMON_CLK_QCOM is not set + +# +# Hardware Spinlock drivers +# + +# +# Clock Source drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_MMIO=y +# 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_CLKSRC_VERSATILE 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 +# +# CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +# CONFIG_IIO is not set +# CONFIG_PWM is not set +CONFIG_IRQCHIP=y +CONFIG_ARM_VIC=y +CONFIG_ARM_VIC_NR=2 +# CONFIG_IPACK_BUS is not set +CONFIG_RESET_CONTROLLER=y +# CONFIG_FMC is not set + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +# CONFIG_BCM_KONA_USB2_PHY is not set +CONFIG_PHY_HISI_INNO_USB2=y +# CONFIG_POWERCAP is not set +# CONFIG_MCB is not set +CONFIG_HI_DMAC=y +CONFIG_HI_DMAC_CHANNEL_NUM=4 + +# +# Hisilicon driver support +# + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT23=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +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=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +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=m +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_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_YAFFS_FS=y +CONFIG_YAFFS_YAFFS1=y +# CONFIG_YAFFS_9BYTE_TAGS is not set +# CONFIG_YAFFS_DOES_ECC is not set +CONFIG_YAFFS_YAFFS2=y +CONFIG_YAFFS_AUTO_YAFFS2=y +# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set +# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set +# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set +# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set +# CONFIG_YAFFS_DISABLE_BACKGROUND is not set +# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set +CONFIG_YAFFS_XATTR=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_LOGFS is not set +CONFIG_CRAMFS=y +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_FILE_CACHE=y +# CONFIG_SQUASHFS_FILE_DIRECT is not set +CONFIG_SQUASHFS_DECOMP_SINGLE=y +# CONFIG_SQUASHFS_DECOMP_MULTI is not set +# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set +# CONFIG_SQUASHFS_XATTR is not set +CONFIG_SQUASHFS_ZLIB=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# 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_F2FS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V2=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +# 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_ACL_SUPPORT=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 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set + +# +# Compile-time checks and compiler options +# +# CONFIG_DEBUG_INFO is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_ON_OOPS_VALUE=1 +CONFIG_PANIC_TIMEOUT=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_TIMER_STATS is not set + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set + +# +# RCU Debugging +# +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_TORTURE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP 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 is not set + +# +# Runtime Testing +# +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_ARM_PTDUMP is not set +CONFIG_STRICT_DEVMEM=y +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_LL is not set +CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +# CONFIG_DEBUG_UART_PL01X is not set +# CONFIG_DEBUG_UART_8250 is not set +# CONFIG_DEBUG_UART_BCM63XX is not set +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +# CONFIG_OC_ETM is not set +# CONFIG_DEBUG_SET_MODULE_RONX is not set +# CONFIG_CORESIGHT is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS 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_HASH=y +CONFIG_CRYPTO_HASH2=y +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# 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_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_CMAC is not set +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32 is not set +# CONFIG_CRYPTO_CRCT10DIF is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# 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_SHA1_ARM is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_AES_ARM is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# 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 is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 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=y +# CONFIG_CRYPTO_ZLIB is not set +CONFIG_CRYPTO_LZO=y +# 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 is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_HISILICON is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=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_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_DECOMPRESS=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_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_LZ4=y +CONFIG_GENERIC_ALLOCATOR=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_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set +CONFIG_LIBFDT=y +CONFIG_ARCH_HAS_SG_CHAIN=y +# CONFIG_VIRTUALIZATION is not set diff --git a/br-ext-chip-hisilicon/board/hi3516cv300/kernel/hi3516ev100.generic.config b/br-ext-chip-hisilicon/board/hi3516cv300/kernel/hi3516ev100.generic.config new file mode 100644 index 000000000..daa956ec9 --- /dev/null +++ b/br-ext-chip-hisilicon/board/hi3516cv300/kernel/hi3516ev100.generic.config @@ -0,0 +1,2543 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 3.18.20 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_ARM_HAS_SG_CHAIN=y +CONFIG_MIGHT_HAVE_PCI=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=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_GENERIC_BUG=y +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_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +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_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +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_HARDIRQS_SW_RESEND=y +CONFIG_IRQ_DOMAIN=y +CONFIG_HANDLE_DOMAIN_IRQ=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +CONFIG_NO_HZ=y +# CONFIG_HIGH_RES_TIMERS is not set + +# +# CPU/Task time and stats accounting +# +CONFIG_VIRT_CPU_ACCOUNTING=y +# CONFIG_TICK_CPU_ACCOUNTING is not set +CONFIG_VIRT_CPU_ACCOUNTING_GEN=y +# 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_PREEMPT_RCU is not set +# CONFIG_TASKS_RCU is not set +# CONFIG_RCU_STALL_COMMON is not set +CONFIG_CONTEXT_TRACKING=y +# CONFIG_CONTEXT_TRACKING_FORCE is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_BUILD_BIN2C is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CGROUP_FREEZER is not set +# CONFIG_CGROUP_DEVICE is not set +# CONFIG_CPUSETS is not set +# CONFIG_CGROUP_CPUACCT is not set +# CONFIG_RESOURCE_COUNTERS is not set +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_CFS_BANDWIDTH is not set +# CONFIG_RT_GROUP_SCHED is not set +# CONFIG_BLK_CGROUP is not set +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_IPC_NS=y +# CONFIG_USER_NS is not set +CONFIG_PID_NS=y +CONFIG_NET_NS=y +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_RD_LZ4=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_BPF=y +# CONFIG_EXPERT is not set +CONFIG_UID16=y +# CONFIG_SGETMASK_SYSCALL is not set +CONFIG_SYSFS_SYSCALL=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +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_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=y +CONFIG_SLUB_DEBUG=y +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_JUMP_LABEL is not set +# CONFIG_UPROBES is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OLD_SIGACTION=y + +# +# GCOV-based kernel profiling +# +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=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_BLOCK=y +CONFIG_LBDAF=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +CONFIG_BLK_CMDLINE_PARSER=y + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_CMDLINE_PARTITION=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" +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=y + +# +# System Type +# +CONFIG_MMU=y +CONFIG_ARCH_MULTIPLATFORM=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP 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_MSM is not set +# CONFIG_ARCH_SHMOBILE_LEGACY is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C24XX is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP1 is not set + +# +# Multiple platform selection +# + +# +# CPU Core family selection +# +# CONFIG_ARCH_MULTI_V4 is not set +# CONFIG_ARCH_MULTI_V4T is not set +CONFIG_ARCH_MULTI_V5=y +CONFIG_ARCH_MULTI_V4_V5=y +# CONFIG_ARCH_MULTI_V6 is not set +# CONFIG_ARCH_MULTI_V7 is not set +CONFIG_ARCH_MULTI_CPU_AUTO=y +# CONFIG_ARCH_MVEBU is not set +CONFIG_ARCH_HISI=y + +# +# Hisilicon platform type +# +CONFIG_ARCH_HI3516CV300=y +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_NSPIRE is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_WM8505 is not set +CONFIG_ARM_TIMER_SP804=y + +# +# Processor Type +# +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_PABRT_LEGACY=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_USE_DOMAINS=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_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +CONFIG_NEED_KUSER_HELPERS=y +CONFIG_KUSER_HELPERS=y +# CONFIG_CACHE_L2X0 is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 +CONFIG_MULTI_IRQ_HANDLER=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y +# CONFIG_PCI is not set +# CONFIG_PCI_SYSCALL is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y +CONFIG_VMSPLIT_3G=y +# 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=y +# CONFIG_HIGHPTE is not set +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +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_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=999999 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_BOUNCE=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_NEED_PER_CPU_KM=y +# CONFIG_CLEANCACHE is not set +# CONFIG_FRONTSWAP is not set +# CONFIG_CMA is not set +# CONFIG_ZPOOL is not set +# CONFIG_ZBUD is not set +# CONFIG_ZSMALLOC 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_ARM_FLUSH_CONSOLE_ON_RESTART is not set + +# +# Boot options +# +CONFIG_USE_OF=y +CONFIG_ATAGS=y +# CONFIG_DEPRECATED_PARAM_STRUCT is not set +# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y +# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set +CONFIG_CMDLINE="" +# 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_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_BINFMT_SCRIPT=y +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_COREDUMP=y + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_WAKELOCK=y +CONFIG_HIBERNATE_CALLBACKS=y +CONFIG_HISI_SNAPSHOT_BOOT=y +# CONFIG_DEFAULT_MTD is not set +CONFIG_DEFAULT_DDR=y +CONFIG_SNAPSHOT_BUF_START=0x8a000000 +CONFIG_SNAPSHOT_BUF_SIZE=0x4000000 +CONFIG_HIBERNATION=y +CONFIG_GZIP_COMPRESS=y +CONFIG_PM_STD_PARTITION="" +CONFIG_PM_SLEEP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +# CONFIG_PM_RUNTIME is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM_EMULATION is not set +CONFIG_PM_CLK=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_CPU_PM=y +# CONFIG_SUSPEND_TIME is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM_CPU_SUSPEND=y +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 is not set +# 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=m +# 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_GENEVE 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=m +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG 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=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_VTI is not set +CONFIG_IPV6_SIT=m +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_GRE is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_ANDROID_PARANOID_NETWORK is not set +CONFIG_NET_ACTIVITY_STATS=y +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NET_PTP_CLASSIFY is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK_ACCT is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NF_TABLES is not set +# CONFIG_NETFILTER_XTABLES is not set +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV4 is not set +# CONFIG_NF_LOG_ARP is not set +# CONFIG_NF_LOG_IPV4 is not set +# CONFIG_NF_REJECT_IPV4 is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set + +# +# IPv6: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV6 is not set +# CONFIG_NF_REJECT_IPV6 is not set +# CONFIG_NF_LOG_IPV6 is not set +# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_NET_MPLS_GSO is not set +# CONFIG_HSR is not set +# CONFIG_CGROUP_NET_PRIO is not set +# CONFIG_CGROUP_NET_CLASSID 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_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +# CONFIG_WIMAX is not set +# CONFIG_RFKILL 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_HAVE_BPF_JIT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_UEVENT_HELPER is not set +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set +CONFIG_ALLOW_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +# CONFIG_HAVE_CPU_AUTOPROBE is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_FENCE_TRACE 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_SWAP is not set +CONFIG_HIFMC=y +CONFIG_HIFMC_SPI_NAND=y +# CONFIG_HIFMC_NAND 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 is not set +# 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_IDS=y +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_DENALI is not set +# CONFIG_MTD_NAND_GPIO is not set +# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_DOCG4 is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set +# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set +# CONFIG_MTD_NAND_HINFC610 is not set +# CONFIG_HIFMC100_NAND is not set +CONFIG_HIFMC100_SPI_NAND=y +CONFIG_SPI_NAND_MAX_CHIP_NUM=1 +# CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC is not set +CONFIG_HIFMC100_AUTO_PAGESIZE_ECC=y +# CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE 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_SPI_NOR_USE_4K_SECTORS is not set +CONFIG_SPI_HISI_SFC=y +CONFIG_CLOSE_SPI_8PIN_4IO=y +CONFIG_HISI_SPI_BLOCK_PROTECT=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_LIMIT=20 +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +# CONFIG_MTD_UBI_BLOCK is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +# CONFIG_OF_SELFTEST 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_MTD=y +CONFIG_OF_RESERVED_MEM=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=65536 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set + +# +# Misc devices +# +# 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_BH1780 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_UID_STAT is not set +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI 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 +# + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# +# CONFIG_ECHO is not set +# CONFIG_CXL_BASE is not set + +# +# hisi 'himm/himd.l/himc'support +# +# CONFIG_HISI_REG is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=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_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_NLMON is not set + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6060 is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +# CONFIG_NET_DSA_MV88E6131 is not set +# CONFIG_NET_DSA_MV88E6123_61_65 is not set +# CONFIG_NET_DSA_MV88E6171 is not set +# CONFIG_NET_DSA_BCM_SF2 is not set +CONFIG_ETHERNET=y +# CONFIG_ALTERA_TSE is not set +# CONFIG_NET_XGENE is not set +# CONFIG_NET_VENDOR_ARC 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_FARADAY is not set +CONFIG_NET_VENDOR_HISILICON=y +# CONFIG_HIX5HD2_GMAC is not set +CONFIG_HISI_FEMAC=y +# CONFIG_HIETH_GMAC is not set +# CONFIG_HIETH_SWITCH_FABRIC 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=y +# CONFIG_ENC28J60 is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_ETHOC is not set +# CONFIG_NET_VENDOR_QUALCOMM 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_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_AT803X_PHY is not set +# CONFIG_AMD_PHY is not set +# CONFIG_AMD_XGBE_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY 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_BCM_UNIMAC is not set +CONFIG_MDIO_HISI_FEMAC=y +# CONFIG_MDIO_HISI_GEMAC 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_USBNET is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_WLAN is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_ISDN 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=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set +# CONFIG_INPUT_KEYRESET is not set +# CONFIG_INPUT_KEYCOMBO is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_CAP1106 is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_CYPRESS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB 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 + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# 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=y + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X 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_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_ST_ASC is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_DCC_TTY 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=m + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL 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_CBUS_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_GPIO is not set +CONFIG_I2C_HIBVT=y +# CONFIG_I2C_HISI_V110 is not set +# CONFIG_I2C_NOMADIK 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_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +CONFIG_SPI_PL022=y +# 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_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=y +# 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_PINCONF=y +CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +CONFIG_PINCTRL_SINGLE=y +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_OF_GPIO=y +CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_DWAPB is not set +# CONFIG_GPIO_EM is not set +# CONFIG_GPIO_ZEVIO is not set +CONFIG_GPIO_PL061=y +# CONFIG_GPIO_SCH311X is not set +# CONFIG_GPIO_SYSCON is not set +# CONFIG_GPIO_GRGPIO is not set + +# +# I2C GPIO expanders: +# +# 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_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# LPC GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# + +# +# USB GPIO expanders: +# +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_SMB347 is not set +CONFIG_POWER_RESET=y +# CONFIG_POWER_RESET_BRCMSTB is not set +# CONFIG_POWER_RESET_GPIO is not set +# CONFIG_POWER_RESET_GPIO_RESTART is not set +CONFIG_POWER_RESET_HISI=y +# CONFIG_POWER_RESET_LTC2952 is not set +# CONFIG_POWER_RESET_RESTART is not set +# CONFIG_POWER_RESET_VERSATILE is not set +CONFIG_POWER_RESET_SYSCON=y +# CONFIG_POWER_AVS is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG 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=y +# 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_BCM590XX is not set +# CONFIG_MFD_AXP20X 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_DA9063 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_MFD_HISI_FMC=y +# CONFIG_HTC_EGPIO 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_MAX77686 is not set +# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +CONFIG_MFD_SYSCON=y +# 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_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 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=m + +# +# Multimedia core support +# +CONFIG_MEDIA_CAMERA_SUPPORT=y +# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set +# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set +# CONFIG_MEDIA_RADIO_SUPPORT is not set +# CONFIG_MEDIA_SDR_SUPPORT is not set +# CONFIG_MEDIA_RC_SUPPORT is not set +# CONFIG_MEDIA_CONTROLLER is not set +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L2=m +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_VIDEOBUF2_CORE=m +CONFIG_VIDEOBUF2_MEMOPS=m +CONFIG_VIDEOBUF2_VMALLOC=m +# CONFIG_TTPCI_EEPROM is not set + +# +# Media drivers +# +# CONFIG_MEDIA_USB_SUPPORT is not set +# CONFIG_V4L_PLATFORM_DRIVERS is not set +# CONFIG_V4L_MEM2MEM_DRIVERS is not set +# CONFIG_V4L_TEST_DRIVERS is not set + +# +# Supported MMC/SDIO adapters +# +# CONFIG_CYPRESS_FIRMWARE is not set + +# +# Media ancillary drivers (tuners, sensors, i2c, frontends) +# +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y + +# +# Audio decoders, processors and mixers +# + +# +# RDS decoders +# + +# +# Video decoders +# + +# +# Video and audio decoders +# + +# +# Video encoders +# + +# +# Camera sensor devices +# + +# +# Flash devices +# + +# +# Video improvement chips +# + +# +# Audio/Video compression chips +# + +# +# Miscellaneous helper chips +# + +# +# Sensors used on soc_camera driver +# + +# +# Tools to develop new frontends +# +# CONFIG_DVB_DUMMY_FE is not set + +# +# Graphics support +# +# CONFIG_IMX_IPUV3_CORE is not set + +# +# Direct Rendering Manager +# +# CONFIG_DRM is not set + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_CMDLINE=y +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_FB_SSD1307 is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_VGASTATE is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set +# CONFIG_LOGO is not set +# CONFIG_SOUND is not set + +# +# HID support +# +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set +# CONFIG_HIDRAW is not set +# CONFIG_UHID is not set +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +CONFIG_HID_A4TECH=y +# CONFIG_HID_ACRUX is not set +CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_AUREAL is not set +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +# CONFIG_HID_CP2112 is not set +CONFIG_HID_CYPRESS=y +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_ELECOM is not set +# CONFIG_HID_ELO is not set +CONFIG_HID_EZKEY=y +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_HUION is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_TWINHAN is not set +CONFIG_HID_KENSINGTON=y +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LENOVO is not set +CONFIG_HID_LOGITECH=y +# CONFIG_HID_LOGITECH_HIDPP is not set +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGIG940_FF is not set +# CONFIG_LOGIWHEELS_FF is not set +# CONFIG_HID_MAGICMOUSE is not set +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PENMOUNT is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_RMI is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HID_SENSOR_HUB is not set + +# +# USB HID support +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV 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 is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_FSM is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB_CBAF 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=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_FUSBH200_HCD is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_MAX3421_HCD is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +# 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 is not set +# 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 +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK 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 is not set +# CONFIG_USB_CHIPIDEA 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_LED 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_SISUSBVGA 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_LINK_LAYER_TEST is not set + +# +# USB Physical Layer drivers +# +# CONFIG_USB_PHY is not set +# CONFIG_USB_OTG_WAKELOCK is not set +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_AM335X_PHY_USB 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=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_MV_UDC is not set +CONFIG_HIUSB_DEVICE2_0=y +CONFIG_USB_HISI_UDC=m +# CONFIG_USB_AUTO_SWITCH is not set +# CONFIG_HIUSB_DEVICE3_0 is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_LIBCOMPOSITE=m +CONFIG_USB_F_MASS_STORAGE=m +CONFIG_USB_F_UAC1=m +CONFIG_USB_F_UVC=m +# CONFIG_USB_CONFIGFS is not set +# CONFIG_USB_ZERO is not set +CONFIG_USB_AUDIO=m +CONFIG_GADGET_UAC1=y +# CONFIG_USB_ETH is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +CONFIG_USB_MASS_STORAGE=m +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set +CONFIG_USB_G_WEBCAM_AUDIO=m +# CONFIG_UWB is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_CLKGATE is not set +CONFIG_MMC_EMBEDDED_SDIO=y +# CONFIG_MMC_PARANOID_SD_INIT is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_ARMMMCI is not set +# CONFIG_MMC_SDHCI is not set +# 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_HIMCIV200=y +CONFIG_SEND_AUTO_STOP=y +CONFIG_DETECT_CARD_TIME=200 +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_SWITCH is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_EDAC is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES 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 + +# +# SOC (System On Chip) specific Drivers +# +# CONFIG_SOC_TI 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_SI570 is not set +# CONFIG_COMMON_CLK_PXA is not set +# CONFIG_COMMON_CLK_QCOM is not set + +# +# Hardware Spinlock drivers +# + +# +# Clock Source drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_MMIO=y +# 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_CLKSRC_VERSATILE 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 +# +# CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +# CONFIG_IIO is not set +# CONFIG_PWM is not set +CONFIG_IRQCHIP=y +CONFIG_ARM_VIC=y +CONFIG_ARM_VIC_NR=2 +# CONFIG_IPACK_BUS is not set +CONFIG_RESET_CONTROLLER=y +# CONFIG_FMC is not set + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +# CONFIG_BCM_KONA_USB2_PHY is not set +CONFIG_PHY_HISI_INNO_USB2=y +# CONFIG_POWERCAP is not set +# CONFIG_MCB is not set +CONFIG_HI_DMAC=y +CONFIG_HI_DMAC_CHANNEL_NUM=4 + +# +# Hisilicon driver support +# + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT23=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +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=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +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=m +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_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_YAFFS_FS=y +CONFIG_YAFFS_YAFFS1=y +# CONFIG_YAFFS_9BYTE_TAGS is not set +# CONFIG_YAFFS_DOES_ECC is not set +CONFIG_YAFFS_YAFFS2=y +CONFIG_YAFFS_AUTO_YAFFS2=y +# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set +# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set +# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set +# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set +# CONFIG_YAFFS_DISABLE_BACKGROUND is not set +# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set +CONFIG_YAFFS_XATTR=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_LOGFS is not set +CONFIG_CRAMFS=y +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_FILE_CACHE=y +# CONFIG_SQUASHFS_FILE_DIRECT is not set +CONFIG_SQUASHFS_DECOMP_SINGLE=y +# CONFIG_SQUASHFS_DECOMP_MULTI is not set +# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set +# CONFIG_SQUASHFS_XATTR is not set +CONFIG_SQUASHFS_ZLIB=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# 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_F2FS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V2=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +# 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_ACL_SUPPORT=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 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set + +# +# Compile-time checks and compiler options +# +# CONFIG_DEBUG_INFO is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_ON_OOPS_VALUE=1 +CONFIG_PANIC_TIMEOUT=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_TIMER_STATS is not set + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set + +# +# RCU Debugging +# +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_TORTURE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP 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 is not set + +# +# Runtime Testing +# +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_ARM_PTDUMP is not set +CONFIG_STRICT_DEVMEM=y +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_LL is not set +CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +# CONFIG_DEBUG_UART_PL01X is not set +# CONFIG_DEBUG_UART_8250 is not set +# CONFIG_DEBUG_UART_BCM63XX is not set +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +# CONFIG_OC_ETM is not set +# CONFIG_DEBUG_SET_MODULE_RONX is not set +# CONFIG_CORESIGHT is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS 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_HASH=y +CONFIG_CRYPTO_HASH2=y +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# 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_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_CMAC is not set +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32 is not set +# CONFIG_CRYPTO_CRCT10DIF is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# 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_SHA1_ARM is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_AES_ARM is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# 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 is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 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=y +# CONFIG_CRYPTO_ZLIB is not set +CONFIG_CRYPTO_LZO=y +# 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 is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_HISILICON is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=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_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_DECOMPRESS=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_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_LZ4=y +CONFIG_GENERIC_ALLOCATOR=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_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set +CONFIG_LIBFDT=y +CONFIG_ARCH_HAS_SG_CHAIN=y +# CONFIG_VIRTUALIZATION is not set diff --git a/br-ext-chip-hisilicon/board/hi3516cv300/kernel/overlay/include/linux/compiler-gcc6.h b/br-ext-chip-hisilicon/board/hi3516cv300/kernel/overlay/include/linux/compiler-gcc6.h new file mode 100644 index 000000000..c8c565952 --- /dev/null +++ b/br-ext-chip-hisilicon/board/hi3516cv300/kernel/overlay/include/linux/compiler-gcc6.h @@ -0,0 +1,65 @@ +#ifndef __LINUX_COMPILER_H +#error "Please don't include directly, include instead." +#endif + +#define __used __attribute__((__used__)) +#define __must_check __attribute__((warn_unused_result)) +#define __compiler_offsetof(a, b) __builtin_offsetof(a, b) + +/* Mark functions as cold. gcc will assume any path leading to a call + to them will be unlikely. This means a lot of manual unlikely()s + are unnecessary now for any paths leading to the usual suspects + like BUG(), printk(), panic() etc. [but let's keep them for now for + older compilers] + + Early snapshots of gcc 4.3 don't support this and we can't detect this + in the preprocessor, but we can live with this because they're unreleased. + Maketime probing would be overkill here. + + gcc also has a __attribute__((__hot__)) to move hot functions into + a special section, but I don't see any sense in this right now in + the kernel context */ +#define __cold __attribute__((__cold__)) + +#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) + +#ifndef __CHECKER__ +# define __compiletime_warning(message) __attribute__((warning(message))) +# define __compiletime_error(message) __attribute__((error(message))) +#endif /* __CHECKER__ */ + +/* + * Mark a position in code as unreachable. This can be used to + * suppress control flow warnings after asm blocks that transfer + * control elsewhere. + * + * Early snapshots of gcc 4.5 don't support this and we can't detect + * this in the preprocessor, but we can live with this because they're + * unreleased. Really, we need to have autoconf for the kernel. + */ +#define unreachable() __builtin_unreachable() + +/* Mark a function definition as prohibited from being cloned. */ +#define __noclone __attribute__((__noclone__)) + +/* + * Tell the optimizer that something else uses this function or variable. + */ +#define __visible __attribute__((externally_visible)) + +/* + * GCC 'asm goto' miscompiles certain code sequences: + * + * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670 + * + * Work it around via a compiler barrier quirk suggested by Jakub Jelinek. + * + * (asm goto is automatically volatile - the naming reflects this.) + */ +#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) + +#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP +#define __HAVE_BUILTIN_BSWAP32__ +#define __HAVE_BUILTIN_BSWAP64__ +#define __HAVE_BUILTIN_BSWAP16__ +#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */ diff --git a/br-ext-chip-hisilicon/board/hi3516cv300/kernel/overlay/include/linux/compiler-gcc7.h b/br-ext-chip-hisilicon/board/hi3516cv300/kernel/overlay/include/linux/compiler-gcc7.h new file mode 100644 index 000000000..c8c565952 --- /dev/null +++ b/br-ext-chip-hisilicon/board/hi3516cv300/kernel/overlay/include/linux/compiler-gcc7.h @@ -0,0 +1,65 @@ +#ifndef __LINUX_COMPILER_H +#error "Please don't include directly, include instead." +#endif + +#define __used __attribute__((__used__)) +#define __must_check __attribute__((warn_unused_result)) +#define __compiler_offsetof(a, b) __builtin_offsetof(a, b) + +/* Mark functions as cold. gcc will assume any path leading to a call + to them will be unlikely. This means a lot of manual unlikely()s + are unnecessary now for any paths leading to the usual suspects + like BUG(), printk(), panic() etc. [but let's keep them for now for + older compilers] + + Early snapshots of gcc 4.3 don't support this and we can't detect this + in the preprocessor, but we can live with this because they're unreleased. + Maketime probing would be overkill here. + + gcc also has a __attribute__((__hot__)) to move hot functions into + a special section, but I don't see any sense in this right now in + the kernel context */ +#define __cold __attribute__((__cold__)) + +#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) + +#ifndef __CHECKER__ +# define __compiletime_warning(message) __attribute__((warning(message))) +# define __compiletime_error(message) __attribute__((error(message))) +#endif /* __CHECKER__ */ + +/* + * Mark a position in code as unreachable. This can be used to + * suppress control flow warnings after asm blocks that transfer + * control elsewhere. + * + * Early snapshots of gcc 4.5 don't support this and we can't detect + * this in the preprocessor, but we can live with this because they're + * unreleased. Really, we need to have autoconf for the kernel. + */ +#define unreachable() __builtin_unreachable() + +/* Mark a function definition as prohibited from being cloned. */ +#define __noclone __attribute__((__noclone__)) + +/* + * Tell the optimizer that something else uses this function or variable. + */ +#define __visible __attribute__((externally_visible)) + +/* + * GCC 'asm goto' miscompiles certain code sequences: + * + * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670 + * + * Work it around via a compiler barrier quirk suggested by Jakub Jelinek. + * + * (asm goto is automatically volatile - the naming reflects this.) + */ +#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) + +#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP +#define __HAVE_BUILTIN_BSWAP32__ +#define __HAVE_BUILTIN_BSWAP64__ +#define __HAVE_BUILTIN_BSWAP16__ +#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */ diff --git a/br-ext-chip-hisilicon/board/hi3516cv300/kernel/patches/hi3516cv300_kernel-3.18.20_sdk-2.0.4.0.patch b/br-ext-chip-hisilicon/board/hi3516cv300/kernel/patches/hi3516cv300_kernel-3.18.20_sdk-2.0.4.0.patch new file mode 100644 index 000000000..f0756f497 --- /dev/null +++ b/br-ext-chip-hisilicon/board/hi3516cv300/kernel/patches/hi3516cv300_kernel-3.18.20_sdk-2.0.4.0.patch @@ -0,0 +1,338806 @@ +diff --git a/Documentation/ABI/testing/configfs-usb-gadget-midi b/Documentation/ABI/testing/configfs-usb-gadget-midi +new file mode 100644 +index 0000000..6b341df +--- /dev/null ++++ b/Documentation/ABI/testing/configfs-usb-gadget-midi +@@ -0,0 +1,12 @@ ++What: /config/usb-gadget/gadget/functions/midi.name ++Date: Nov 2014 ++KernelVersion: 3.19 ++Description: ++ The attributes: ++ ++ index - index value for the USB MIDI adapter ++ id - ID string for the USB MIDI adapter ++ buflen - MIDI buffer length ++ qlen - USB read request queue length ++ in_ports - number of MIDI input ports ++ out_ports - number of MIDI output ports +diff --git a/Documentation/ABI/testing/sysfs-class-dual-role-usb b/Documentation/ABI/testing/sysfs-class-dual-role-usb +new file mode 100644 +index 0000000..a900fd7 +--- /dev/null ++++ b/Documentation/ABI/testing/sysfs-class-dual-role-usb +@@ -0,0 +1,71 @@ ++What: /sys/class/dual_role_usb/.../ ++Date: June 2015 ++Contact: Badhri Jagan Sridharan ++Description: ++ Provide a generic interface to monitor and change ++ the state of dual role usb ports. The name here ++ refers to the name mentioned in the ++ dual_role_phy_desc that is passed while registering ++ the dual_role_phy_intstance through ++ devm_dual_role_instance_register. ++ ++What: /sys/class/dual_role_usb/.../supported_modes ++Date: June 2015 ++Contact: Badhri Jagan Sridharan ++Description: ++ This is a static node, once initialized this ++ is not expected to change during runtime. "dfp" ++ refers to "downstream facing port" i.e. port can ++ only act as host. "ufp" refers to "upstream ++ facing port" i.e. port can only act as device. ++ "dfp ufp" refers to "dual role port" i.e. the port ++ can either be a host port or a device port. ++ ++What: /sys/class/dual_role_usb/.../mode ++Date: June 2015 ++Contact: Badhri Jagan Sridharan ++Description: ++ The mode node refers to the current mode in which the ++ port is operating. "dfp" for host ports. "ufp" for device ++ ports and "none" when cable is not connected. ++ ++ On devices where the USB mode is software-controllable, ++ userspace can change the mode by writing "dfp" or "ufp". ++ On devices where the USB mode is fixed in hardware, ++ this attribute is read-only. ++ ++What: /sys/class/dual_role_usb/.../power_role ++Date: June 2015 ++Contact: Badhri Jagan Sridharan ++Description: ++ The power_role node mentions whether the port ++ is "sink"ing or "source"ing power. "none" if ++ they are not connected. ++ ++ On devices implementing USB Power Delivery, ++ userspace can control the power role by writing "sink" or ++ "source". On devices without USB-PD, this attribute is ++ read-only. ++ ++What: /sys/class/dual_role_usb/.../data_role ++Date: June 2015 ++Contact: Badhri Jagan Sridharan ++Description: ++ The data_role node mentions whether the port ++ is acting as "host" or "device" for USB data connection. ++ "none" if there is no active data link. ++ ++ On devices implementing USB Power Delivery, userspace ++ can control the data role by writing "host" or "device". ++ On devices without USB-PD, this attribute is read-only ++ ++What: /sys/class/dual_role_usb/.../powers_vconn ++Date: June 2015 ++Contact: Badhri Jagan Sridharan ++Description: ++ The powers_vconn node mentions whether the port ++ is supplying power for VCONN pin. ++ ++ On devices with software control of VCONN, ++ userspace can disable the power supply to VCONN by writing "n", ++ or enable the power supply by writing "y". +diff --git a/Documentation/ABI/testing/sysfs-kernel-wakeup_reasons b/Documentation/ABI/testing/sysfs-kernel-wakeup_reasons +new file mode 100644 +index 0000000..acb19b9 +--- /dev/null ++++ b/Documentation/ABI/testing/sysfs-kernel-wakeup_reasons +@@ -0,0 +1,16 @@ ++What: /sys/kernel/wakeup_reasons/last_resume_reason ++Date: February 2014 ++Contact: Ruchi Kandoi ++Description: ++ The /sys/kernel/wakeup_reasons/last_resume_reason is ++ used to report wakeup reasons after system exited suspend. ++ ++What: /sys/kernel/wakeup_reasons/last_suspend_time ++Date: March 2015 ++Contact: jinqian ++Description: ++ The /sys/kernel/wakeup_reasons/last_suspend_time is ++ used to report time spent in last suspend cycle. It contains ++ two numbers (in seconds) separated by space. First number is ++ the time spent in suspend and resume processes. Second number ++ is the time spent in sleep state. +\ No newline at end of file +diff --git a/Documentation/android.txt b/Documentation/android.txt +new file mode 100644 +index 0000000..0f40a78 +--- /dev/null ++++ b/Documentation/android.txt +@@ -0,0 +1,121 @@ ++ ============= ++ A N D R O I D ++ ============= ++ ++Copyright (C) 2009 Google, Inc. ++Written by Mike Chan ++ ++CONTENTS: ++--------- ++ ++1. Android ++ 1.1 Required enabled config options ++ 1.2 Required disabled config options ++ 1.3 Recommended enabled config options ++2. Contact ++ ++ ++1. Android ++========== ++ ++Android (www.android.com) is an open source operating system for mobile devices. ++This document describes configurations needed to run the Android framework on ++top of the Linux kernel. ++ ++To see a working defconfig look at msm_defconfig or goldfish_defconfig ++which can be found at http://android.git.kernel.org in kernel/common.git ++and kernel/msm.git ++ ++ ++1.1 Required enabled config options ++----------------------------------- ++After building a standard defconfig, ensure that these options are enabled in ++your .config or defconfig if they are not already. Based off the msm_defconfig. ++You should keep the rest of the default options enabled in the defconfig ++unless you know what you are doing. ++ ++ANDROID_PARANOID_NETWORK ++ASHMEM ++CONFIG_FB_MODE_HELPERS ++CONFIG_FONT_8x16 ++CONFIG_FONT_8x8 ++CONFIG_YAFFS_SHORT_NAMES_IN_RAM ++DAB ++EARLYSUSPEND ++FB ++FB_CFB_COPYAREA ++FB_CFB_FILLRECT ++FB_CFB_IMAGEBLIT ++FB_DEFERRED_IO ++FB_TILEBLITTING ++HIGH_RES_TIMERS ++INOTIFY ++INOTIFY_USER ++INPUT_EVDEV ++INPUT_GPIO ++INPUT_MISC ++LEDS_CLASS ++LEDS_GPIO ++LOCK_KERNEL ++LkOGGER ++LOW_MEMORY_KILLER ++MISC_DEVICES ++NEW_LEDS ++NO_HZ ++POWER_SUPPLY ++PREEMPT ++RAMFS ++RTC_CLASS ++RTC_LIB ++SWITCH ++SWITCH_GPIO ++TMPFS ++UID_STAT ++UID16 ++USB_FUNCTION ++USB_FUNCTION_ADB ++USER_WAKELOCK ++VIDEO_OUTPUT_CONTROL ++WAKELOCK ++YAFFS_AUTO_YAFFS2 ++YAFFS_FS ++YAFFS_YAFFS1 ++YAFFS_YAFFS2 ++ ++ ++1.2 Required disabled config options ++------------------------------------ ++CONFIG_YAFFS_DISABLE_LAZY_LOAD ++DNOTIFY ++ ++ ++1.3 Recommended enabled config options ++------------------------------ ++ANDROID_PMEM ++PSTORE_CONSOLE ++PSTORE_RAM ++SCHEDSTATS ++DEBUG_PREEMPT ++DEBUG_MUTEXES ++DEBUG_SPINLOCK_SLEEP ++DEBUG_INFO ++FRAME_POINTER ++CPU_FREQ ++CPU_FREQ_TABLE ++CPU_FREQ_DEFAULT_GOV_ONDEMAND ++CPU_FREQ_GOV_ONDEMAND ++CRC_CCITT ++EMBEDDED ++INPUT_TOUCHSCREEN ++I2C ++I2C_BOARDINFO ++LOG_BUF_SHIFT=17 ++SERIAL_CORE ++SERIAL_CORE_CONSOLE ++ ++ ++2. Contact ++========== ++website: http://android.git.kernel.org ++ ++mailing-lists: android-kernel@googlegroups.com +diff --git a/Documentation/arm/small_task_packing.txt b/Documentation/arm/small_task_packing.txt +new file mode 100644 +index 0000000..613f2aa +--- /dev/null ++++ b/Documentation/arm/small_task_packing.txt +@@ -0,0 +1,135 @@ ++Small Task Packing in the big.LITTLE MP Reference Patch Set ++ ++What is small task packing? ++---- ++Simply that the scheduler will fit as many small tasks on a single CPU ++as possible before using other CPUs. A small task is defined as one ++whose tracked load is less than 90% of a NICE_0 task. This is a change ++from the usual behavior since the scheduler will normally use an idle ++CPU for a waking task unless that task is considered cache hot. ++ ++ ++How is it implemented? ++---- ++Since all small tasks must wake up relatively frequently, the main ++requirement for packing small tasks is to select a partly-busy CPU when ++waking rather than looking for an idle CPU. We use the tracked load of ++the CPU runqueue to determine how heavily loaded each CPU is and the ++tracked load of the task to determine if it will fit on the CPU. We ++always start with the lowest-numbered CPU in a sched domain and stop ++looking when we find a CPU with enough space for the task. ++ ++Some further tweaks are necessary to suppress load balancing when the ++CPU is not fully loaded, otherwise the scheduler attempts to spread ++tasks evenly across the domain. ++ ++ ++How does it interact with the HMP patches? ++---- ++Firstly, we only enable packing on the little domain. The intent is that ++the big domain is intended to spread tasks amongst the available CPUs ++one-task-per-CPU. The little domain however is attempting to use as ++little power as possible while servicing its tasks. ++ ++Secondly, since we offload big tasks onto little CPUs in order to try ++to devote one CPU to each task, we have a threshold above which we do ++not try to pack a task and instead will select an idle CPU if possible. ++This maintains maximum forward progress for busy tasks temporarily ++demoted from big CPUs. ++ ++ ++Can the behaviour be tuned? ++---- ++Yes, the load level of a 'full' CPU can be easily modified in the source ++and is exposed through sysfs as /sys/kernel/hmp/packing_limit to be ++changed at runtime. The presence of the packing behaviour is controlled ++by CONFIG_SCHED_HMP_LITTLE_PACKING and can be disabled at run-time ++using /sys/kernel/hmp/packing_enable. ++The definition of a small task is hard coded as 90% of NICE_0_LOAD ++and cannot be modified at run time. ++ ++ ++Why do I need to tune it? ++---- ++The optimal configuration is likely to be different depending upon the ++design and manufacturing of your SoC. ++ ++In the main, there are two system effects from enabling small task ++packing. ++ ++1. CPU operating point may increase ++2. wakeup latency of tasks may be increased ++ ++There are also likely to be secondary effects from loading one CPU ++rather than spreading tasks. ++ ++Note that all of these system effects are dependent upon the workload ++under consideration. ++ ++ ++CPU Operating Point ++---- ++The primary impact of loading one CPU with a number of light tasks is to ++increase the compute requirement of that CPU since it is no longer idle ++as often. Increased compute requirement causes an increase in the ++frequency of the CPU through CPUfreq. ++ ++Consider this example: ++We have a system with 3 CPUs which can operate at any frequency between ++350MHz and 1GHz. The system has 6 tasks which would each produce 10% ++load at 1GHz. The scheduler has frequency-invariant load scaling ++enabled. Our DVFS governor aims for 80% utilization at the chosen ++frequency. ++ ++Without task packing, these tasks will be spread out amongst all CPUs ++such that each has 2. This will produce roughly 20% system load, and ++the frequency of the package will remain at 350MHz. ++ ++With task packing set to the default packing_limit, all of these tasks ++will sit on one CPU and require a package frequency of ~750MHz to reach ++80% utilization. (0.75 = 0.6 * 0.8). ++ ++When a package operates on a single frequency domain, all CPUs in that ++package share frequency and voltage. ++ ++Depending upon the SoC implementation there can be a significant amount ++of energy lost to leakage from idle CPUs. The decision about how ++loaded a CPU must be to be considered 'full' is therefore controllable ++through sysfs (sys/kernel/hmp/packing_limit) and directly in the code. ++ ++Continuing the example, lets set packing_limit to 450 which means we ++will pack tasks until the total load of all running tasks >= 450. In ++practise, this is very similar to a 55% idle 1Ghz CPU. ++ ++Now we are only able to place 4 tasks on CPU0, and two will overflow ++onto CPU1. CPU0 will have a load of 40% and CPU1 will have a load of ++20%. In order to still hit 80% utilization, CPU0 now only needs to ++operate at (0.4*0.8=0.32) 320MHz, which means that the lowest operating ++point will be selected, the same as in the non-packing case, except that ++now CPU2 is no longer needed and can be power-gated. ++ ++In order to use less energy, the saving from power-gating CPU2 must be ++more than the energy spent running CPU0 for the extra cycles. This ++depends upon the SoC implementation. ++ ++This is obviously a contrived example requiring all the tasks to ++be runnable at the same time, but it illustrates the point. ++ ++ ++Wakeup Latency ++---- ++This is an unavoidable consequence of trying to pack tasks together ++rather than giving them a CPU each. If you cannot find an acceptable ++level of wakeup latency, you should turn packing off. ++ ++Cyclictest is a good test application for determining the added latency ++when configuring packing. ++ ++ ++Why is it turned off for the VersatileExpress V2P_CA15A7 CoreTile? ++---- ++Simply, this core tile only has power gating for the whole A7 package. ++When small task packing is enabled, all our low-energy use cases ++normally fit onto one A7 CPU. We therefore end up with 2 mostly-idle ++CPUs and one mostly-busy CPU. This decreases the amount of time ++available where the whole package is idle and can be turned off. +diff --git a/Documentation/arm64/legacy_instructions.txt b/Documentation/arm64/legacy_instructions.txt +new file mode 100644 +index 0000000..01bf3d9 +--- /dev/null ++++ b/Documentation/arm64/legacy_instructions.txt +@@ -0,0 +1,57 @@ ++The arm64 port of the Linux kernel provides infrastructure to support ++emulation of instructions which have been deprecated, or obsoleted in ++the architecture. The infrastructure code uses undefined instruction ++hooks to support emulation. Where available it also allows turning on ++the instruction execution in hardware. ++ ++The emulation mode can be controlled by writing to sysctl nodes ++(/proc/sys/abi). The following explains the different execution ++behaviours and the corresponding values of the sysctl nodes - ++ ++* Undef ++ Value: 0 ++ Generates undefined instruction abort. Default for instructions that ++ have been obsoleted in the architecture, e.g., SWP ++ ++* Emulate ++ Value: 1 ++ Uses software emulation. To aid migration of software, in this mode ++ usage of emulated instruction is traced as well as rate limited ++ warnings are issued. This is the default for deprecated ++ instructions, .e.g., CP15 barriers ++ ++* Hardware Execution ++ Value: 2 ++ Although marked as deprecated, some implementations may support the ++ enabling/disabling of hardware support for the execution of these ++ instructions. Using hardware execution generally provides better ++ performance, but at the loss of ability to gather runtime statistics ++ about the use of the deprecated instructions. ++ ++The default mode depends on the status of the instruction in the ++architecture. Deprecated instructions should default to emulation ++while obsolete instructions must be undefined by default. ++ ++Note: Instruction emulation may not be possible in all cases. See ++individual instruction notes for further information. ++ ++Supported legacy instructions ++----------------------------- ++* SWP{B} ++Node: /proc/sys/abi/swp ++Status: Obsolete ++Default: Undef (0) ++ ++* CP15 Barriers ++Node: /proc/sys/abi/cp15_barrier ++Status: Deprecated ++Default: Emulate (1) ++ ++* SETEND ++Node: /proc/sys/abi/setend ++Status: Deprecated ++Default: Emulate (1)* ++Note: All the cpus on the system must have mixed endian support at EL0 ++for this feature to be enabled. If a new CPU - which doesn't support mixed ++endian - is hotplugged in after this feature has been enabled, there could ++be unexpected results in the application. +diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt +index 10c949b..925b820 100644 +--- a/Documentation/cgroups/cgroups.txt ++++ b/Documentation/cgroups/cgroups.txt +@@ -578,6 +578,15 @@ is completely unused; @cgrp->parent is still valid. (Note - can also + be called for a newly-created cgroup if an error occurs after this + subsystem's create() method has been called for the new cgroup). + ++int allow_attach(struct cgroup *cgrp, struct cgroup_taskset *tset) ++(cgroup_mutex held by caller) ++ ++Called prior to moving a task into a cgroup; if the subsystem ++returns an error, this will abort the attach operation. Used ++to extend the permission checks - if all subsystems in a cgroup ++return 0, the attach will be allowed to proceed, even if the ++default permission check (root or same user) fails. ++ + int can_attach(struct cgroup *cgrp, struct cgroup_taskset *tset) + (cgroup_mutex held by caller) + +diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt +index 77ec215..2ed766e 100644 +--- a/Documentation/cpu-freq/governors.txt ++++ b/Documentation/cpu-freq/governors.txt +@@ -28,6 +28,7 @@ Contents: + 2.3 Userspace + 2.4 Ondemand + 2.5 Conservative ++2.6 Interactive + + 3. The Governor Interface in the CPUfreq Core + +@@ -218,6 +219,90 @@ a decision on when to decrease the frequency while running in any + speed. Load for frequency increase is still evaluated every + sampling rate. + ++2.6 Interactive ++--------------- ++ ++The CPUfreq governor "interactive" is designed for latency-sensitive, ++interactive workloads. This governor sets the CPU speed depending on ++usage, similar to "ondemand" and "conservative" governors, but with a ++different set of configurable behaviors. ++ ++The tuneable values for this governor are: ++ ++target_loads: CPU load values used to adjust speed to influence the ++current CPU load toward that value. In general, the lower the target ++load, the more often the governor will raise CPU speeds to bring load ++below the target. The format is a single target load, optionally ++followed by pairs of CPU speeds and CPU loads to target at or above ++those speeds. Colons can be used between the speeds and associated ++target loads for readability. For example: ++ ++ 85 1000000:90 1700000:99 ++ ++targets CPU load 85% below speed 1GHz, 90% at or above 1GHz, until ++1.7GHz and above, at which load 99% is targeted. If speeds are ++specified these must appear in ascending order. Higher target load ++values are typically specified for higher speeds, that is, target load ++values also usually appear in an ascending order. The default is ++target load 90% for all speeds. ++ ++min_sample_time: The minimum amount of time to spend at the current ++frequency before ramping down. Default is 80000 uS. ++ ++hispeed_freq: An intermediate "hi speed" at which to initially ramp ++when CPU load hits the value specified in go_hispeed_load. If load ++stays high for the amount of time specified in above_hispeed_delay, ++then speed may be bumped higher. Default is the maximum speed ++allowed by the policy at governor initialization time. ++ ++go_hispeed_load: The CPU load at which to ramp to hispeed_freq. ++Default is 99%. ++ ++above_hispeed_delay: When speed is at or above hispeed_freq, wait for ++this long before raising speed in response to continued high load. ++The format is a single delay value, optionally followed by pairs of ++CPU speeds and the delay to use at or above those speeds. Colons can ++be used between the speeds and associated delays for readability. For ++example: ++ ++ 80000 1300000:200000 1500000:40000 ++ ++uses delay 80000 uS until CPU speed 1.3 GHz, at which speed delay ++200000 uS is used until speed 1.5 GHz, at which speed (and above) ++delay 40000 uS is used. If speeds are specified these must appear in ++ascending order. Default is 20000 uS. ++ ++timer_rate: Sample rate for reevaluating CPU load when the CPU is not ++idle. A deferrable timer is used, such that the CPU will not be woken ++from idle to service this timer until something else needs to run. ++(The maximum time to allow deferring this timer when not running at ++minimum speed is configurable via timer_slack.) Default is 20000 uS. ++ ++timer_slack: Maximum additional time to defer handling the governor ++sampling timer beyond timer_rate when running at speeds above the ++minimum. For platforms that consume additional power at idle when ++CPUs are running at speeds greater than minimum, this places an upper ++bound on how long the timer will be deferred prior to re-evaluating ++load and dropping speed. For example, if timer_rate is 20000uS and ++timer_slack is 10000uS then timers will be deferred for up to 30msec ++when not at lowest speed. A value of -1 means defer timers ++indefinitely at all speeds. Default is 80000 uS. ++ ++boost: If non-zero, immediately boost speed of all CPUs to at least ++hispeed_freq until zero is written to this attribute. If zero, allow ++CPU speeds to drop below hispeed_freq according to load as usual. ++Default is zero. ++ ++boostpulse: On each write, immediately boost speed of all CPUs to ++hispeed_freq for at least the period of time specified by ++boostpulse_duration, after which speeds are allowed to drop below ++hispeed_freq according to load as usual. ++ ++boostpulse_duration: Length of time to hold CPU speed at hispeed_freq ++on a write to boostpulse, before allowing speed to drop according to ++load as usual. Default is 80000 uS. ++ ++ + 3. The Governor Interface in the CPUfreq Core + ============================================= + +diff --git a/Documentation/device-mapper/dm-crypt.txt b/Documentation/device-mapper/dm-crypt.txt +index c81839b..692171f 100644 +--- a/Documentation/device-mapper/dm-crypt.txt ++++ b/Documentation/device-mapper/dm-crypt.txt +@@ -5,7 +5,7 @@ Device-Mapper's "crypt" target provides transparent encryption of block devices + using the kernel crypto API. + + For a more detailed description of supported parameters see: +-http://code.google.com/p/cryptsetup/wiki/DMCrypt ++https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt + + Parameters: \ + [<#opt_params> ] +@@ -51,7 +51,7 @@ Parameters: \ + Otherwise #opt_params is the number of following arguments. + + Example of optional parameters section: +- 1 allow_discards ++ 3 allow_discards same_cpu_crypt submit_from_crypt_cpus + + allow_discards + Block discard requests (a.k.a. TRIM) are passed through the crypt device. +@@ -63,11 +63,24 @@ allow_discards + used space etc.) if the discarded blocks can be located easily on the + device later. + ++same_cpu_crypt ++ Perform encryption using the same cpu that IO was submitted on. ++ The default is to use an unbound workqueue so that encryption work ++ is automatically balanced between available CPUs. ++ ++submit_from_crypt_cpus ++ Disable offloading writes to a separate thread after encryption. ++ There are some situations where offloading write bios from the ++ encryption threads to a single thread degrades performance ++ significantly. The default is to offload write bios to the same ++ thread because it benefits CFQ to have writes submitted using the ++ same context. ++ + Example scripts + =============== + LUKS (Linux Unified Key Setup) is now the preferred way to set up disk + encryption with dm-crypt using the 'cryptsetup' utility, see +-http://code.google.com/p/cryptsetup/ ++https://gitlab.com/cryptsetup/cryptsetup + + [[ + #!/bin/sh +diff --git a/Documentation/device-mapper/verity.txt b/Documentation/device-mapper/verity.txt +index 9884681..0075f70 100644 +--- a/Documentation/device-mapper/verity.txt ++++ b/Documentation/device-mapper/verity.txt +@@ -125,7 +125,7 @@ block boundary) are the hash blocks which are stored a depth at a time + + The full specification of kernel parameters and on-disk metadata format + is available at the cryptsetup project's wiki page +- http://code.google.com/p/cryptsetup/wiki/DMVerity ++ https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity + + Status + ====== +@@ -142,7 +142,7 @@ Set up a device: + + A command line tool veritysetup is available to compute or verify + the hash tree or activate the kernel device. This is available from +-the cryptsetup upstream repository http://code.google.com/p/cryptsetup/ ++the cryptsetup upstream repository https://gitlab.com/cryptsetup/cryptsetup/ + (as a libcryptsetup extension). + + Create hash on the device: +diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt +new file mode 100644 +index 0000000..88602b7 +--- /dev/null ++++ b/Documentation/devicetree/bindings/arm/coresight.txt +@@ -0,0 +1,199 @@ ++* CoreSight Components: ++ ++CoreSight components are compliant with the ARM CoreSight architecture ++specification and can be connected in various topologies to suit a particular ++SoCs tracing needs. These trace components can generally be classified as ++sinks, links and sources. Trace data produced by one or more sources flows ++through the intermediate links connecting the source to the currently selected ++sink. Each CoreSight component device should use these properties to describe ++its hardware characteristcs. ++ ++* Required properties for all components *except* non-configurable replicators: ++ ++ * compatible: These have to be supplemented with "arm,primecell" as ++ drivers are using the AMBA bus interface. Possible values include: ++ - "arm,coresight-etb10", "arm,primecell"; ++ - "arm,coresight-tpiu", "arm,primecell"; ++ - "arm,coresight-tmc", "arm,primecell"; ++ - "arm,coresight-funnel", "arm,primecell"; ++ - "arm,coresight-etm3x", "arm,primecell"; ++ ++ * reg: physical base address and length of the register ++ set(s) of the component. ++ ++ * clocks: the clock associated to this component. ++ ++ * clock-names: the name of the clock as referenced by the code. ++ Since we are using the AMBA framework, the name should be ++ "apb_pclk". ++ ++ * port or ports: The representation of the component's port ++ layout using the generic DT graph presentation found in ++ "bindings/graph.txt". ++ ++* Required properties for devices that don't show up on the AMBA bus, such as ++ non-configurable replicators: ++ ++ * compatible: Currently supported value is (note the absence of the ++ AMBA markee): ++ - "arm,coresight-replicator" ++ ++ * port or ports: same as above. ++ ++* Optional properties for ETM/PTMs: ++ ++ * arm,cp14: must be present if the system accesses ETM/PTM management ++ registers via co-processor 14. ++ ++ * cpu: the cpu phandle this ETM/PTM is affined to. When omitted the ++ source is considered to belong to CPU0. ++ ++* Optional property for TMC: ++ ++ * arm,buffer-size: size of contiguous buffer space for TMC ETR ++ (embedded trace router) ++ ++ ++Example: ++ ++1. Sinks ++ etb@20010000 { ++ compatible = "arm,coresight-etb10", "arm,primecell"; ++ reg = <0 0x20010000 0 0x1000>; ++ ++ clocks = <&oscclk6a>; ++ clock-names = "apb_pclk"; ++ port { ++ etb_in_port: endpoint@0 { ++ slave-mode; ++ remote-endpoint = <&replicator_out_port0>; ++ }; ++ }; ++ }; ++ ++ tpiu@20030000 { ++ compatible = "arm,coresight-tpiu", "arm,primecell"; ++ reg = <0 0x20030000 0 0x1000>; ++ ++ clocks = <&oscclk6a>; ++ clock-names = "apb_pclk"; ++ port { ++ tpiu_in_port: endpoint@0 { ++ slave-mode; ++ remote-endpoint = <&replicator_out_port1>; ++ }; ++ }; ++ }; ++ ++2. Links ++ replicator { ++ /* non-configurable replicators don't show up on the ++ * AMBA bus. As such no need to add "arm,primecell". ++ */ ++ compatible = "arm,coresight-replicator"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* replicator output ports */ ++ port@0 { ++ reg = <0>; ++ replicator_out_port0: endpoint { ++ remote-endpoint = <&etb_in_port>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ replicator_out_port1: endpoint { ++ remote-endpoint = <&tpiu_in_port>; ++ }; ++ }; ++ ++ /* replicator input port */ ++ port@2 { ++ reg = <0>; ++ replicator_in_port0: endpoint { ++ slave-mode; ++ remote-endpoint = <&funnel_out_port0>; ++ }; ++ }; ++ }; ++ }; ++ ++ funnel@20040000 { ++ compatible = "arm,coresight-funnel", "arm,primecell"; ++ reg = <0 0x20040000 0 0x1000>; ++ ++ clocks = <&oscclk6a>; ++ clock-names = "apb_pclk"; ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* funnel output port */ ++ port@0 { ++ reg = <0>; ++ funnel_out_port0: endpoint { ++ remote-endpoint = ++ <&replicator_in_port0>; ++ }; ++ }; ++ ++ /* funnel input ports */ ++ port@1 { ++ reg = <0>; ++ funnel_in_port0: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm0_out_port>; ++ }; ++ }; ++ ++ port@2 { ++ reg = <1>; ++ funnel_in_port1: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm1_out_port>; ++ }; ++ }; ++ ++ port@3 { ++ reg = <2>; ++ funnel_in_port2: endpoint { ++ slave-mode; ++ remote-endpoint = <&etm0_out_port>; ++ }; ++ }; ++ ++ }; ++ }; ++ ++3. Sources ++ ptm@2201c000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0x2201c000 0 0x1000>; ++ ++ cpu = <&cpu0>; ++ clocks = <&oscclk6a>; ++ clock-names = "apb_pclk"; ++ port { ++ ptm0_out_port: endpoint { ++ remote-endpoint = <&funnel_in_port0>; ++ }; ++ }; ++ }; ++ ++ ptm@2201d000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0x2201d000 0 0x1000>; ++ ++ cpu = <&cpu1>; ++ clocks = <&oscclk6a>; ++ clock-names = "apb_pclk"; ++ port { ++ ptm1_out_port: endpoint { ++ remote-endpoint = <&funnel_in_port1>; ++ }; ++ }; ++ }; +diff --git a/Documentation/devicetree/bindings/clock/hi3519-clock.txt b/Documentation/devicetree/bindings/clock/hi3519-clock.txt +new file mode 100644 +index 0000000..9fea878 +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/hi3519-clock.txt +@@ -0,0 +1,46 @@ ++* Hisilicon Hi3519 Clock and Reset Generator(CRG) ++ ++The Hi3519 CRG module provides clock and reset signals to various ++controllers within the SoC. ++ ++This binding uses the following bindings: ++ Documentation/devicetree/bindings/clock/clock-bindings.txt ++ Documentation/devicetree/bindings/reset/reset.txt ++ ++Required Properties: ++ ++- compatible: should be one of the following. ++ - "hisilicon,hi3519-clock" - controller compatible with Hi3519 SoC. ++ ++- reg: physical base address of the controller and length of memory mapped ++ region. ++ ++- #clock-cells: should be 1. ++ ++Each clock is assigned an identifier and client nodes use this identifier ++to specify the clock which they consume. ++ ++All these identifier could be found in . ++ ++- #reset-cells: should be 2. ++ ++A reset signal can be controlled by writing a bit register in the CRG module. ++The reset specifier consists of two cells. The first cell represents the ++register offset relative to the base address. The second cell represents the ++bit index in the register. ++ ++Example: CRG nodes ++CRG: clock-reset-controller { ++ compatible = "hisilicon,hi3519-clock"; ++ reg = <0x12010000 0x10000>; ++ #clock-cells = <1>; ++ #reset-cells = <2>; ++}; ++ ++Example: consumer nodes ++i2c0: i2c@0x12110000 { ++ compatible = "hisilicon,hi3519-i2c"; ++ reg = <0x12110000 0x1000>; ++ clocks = <&CRG HI3519_I2C0_RST>;*/ ++ resets = <&CRG 0xE4 0>; ++}; +diff --git a/Documentation/devicetree/bindings/i2c/i2c-hibvt.txt b/Documentation/devicetree/bindings/i2c/i2c-hibvt.txt +new file mode 100644 +index 0000000..db3d2e2 +--- /dev/null ++++ b/Documentation/devicetree/bindings/i2c/i2c-hibvt.txt +@@ -0,0 +1,24 @@ ++Hisilicon BVT I2C master controller ++ ++Required properties: ++- compatible: should be "hisilicon,hibvt-i2c" and one of the following: ++ "hisilicon,hi3516cv300-i2c" ++- reg: physical base address of the controller and length of memory mapped. ++ region. ++- interrupts: interrupt number to the cpu. ++- clocks: phandles to input clocks. ++ ++Optional properties: ++- clock-frequency: Desired I2C bus frequency in Hz, otherwise defaults to 100000. ++ ++Other properties: ++see Documentation/devicetree/bindings/i2c/i2c.txt. ++ ++Examples: ++i2c_bus0: i2c@12110000 { ++ compatible = "hisilicon,hi3516cv300-i2c", "hisilicon,hibvt-i2c"; ++ reg = <0x12110000 0x100>; ++ interrupts = <20>; ++ clocks = <&crg_ctrl HI3516CV300_APB_CLK>; ++ clock-frequency = <100000>; ++}; +diff --git a/Documentation/devicetree/bindings/net/hisilicon-femac-mdio.txt b/Documentation/devicetree/bindings/net/hisilicon-femac-mdio.txt +new file mode 100644 +index 0000000..23a39a3 +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/hisilicon-femac-mdio.txt +@@ -0,0 +1,22 @@ ++Hisilicon Fast Ethernet MDIO Controller interface ++ ++Required properties: ++- compatible: should be "hisilicon,hisi-femac-mdio". ++- reg: address and length of the register set for the device. ++- clocks: A phandle to the reference clock for this device. ++ ++- PHY subnode: inherits from phy binding [1] ++[1] Documentation/devicetree/bindings/net/phy.txt ++ ++Example: ++mdio: mdio@10091100 { ++ compatible = "hisilicon,hisi-femac-mdio"; ++ reg = <0x10091100 0x10>; ++ clocks = <&crg HI3516CV300_MDIO_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ phy0: phy@1 { ++ reg = <1>; ++ }; ++}; +diff --git a/Documentation/devicetree/bindings/net/hisilicon-femac.txt b/Documentation/devicetree/bindings/net/hisilicon-femac.txt +new file mode 100644 +index 0000000..d11af5e +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/hisilicon-femac.txt +@@ -0,0 +1,39 @@ ++Hisilicon Fast Ethernet MAC controller ++ ++Required properties: ++- compatible: should contain one of the following version strings: ++ * "hisilicon,hisi-femac-v1" ++ * "hisilicon,hisi-femac-v2" ++ and the soc string "hisilicon,hi3516cv300-femac". ++- reg: specifies base physical address(s) and size of the device registers. ++ The first region is the MAC core register base and size. ++ The second region is the global MAC control register. ++- interrupts: should contain the MAC interrupt. ++- clocks: A phandle to the MAC main clock. ++- resets: should contain the phandle to the MAC reset signal(required) and ++ the PHY reset signal(optional). ++- reset-names: should contain the reset signal name "mac"(required) ++ and "phy"(optional). ++- mac-address: see ethernet.txt [1]. ++- phy-mode: see ethernet.txt [1]. ++- phy-handle: see ethernet.txt [1]. ++- hisilicon,phy-reset-delays-us: triplet of delays if PHY reset signal given. ++ The 1st cell is reset pre-delay in micro seconds. ++ The 2nd cell is reset pulse in micro seconds. ++ The 3rd cell is reset post-delay in micro seconds. ++ ++[1] Documentation/devicetree/bindings/net/ethernet.txt ++ ++Example: ++ hisi_femac: ethernet@10090000 { ++ compatible = "hisilicon,hi3516cv300-femac","hisilicon,hisi-femac-v2"; ++ reg = <0x10090000 0x1000>,<0x10091300 0x200>; ++ interrupts = <12>; ++ clocks = <&crg HI3518EV200_ETH_CLK>; ++ resets = <&crg 0xec 0>,<&crg 0xec 3>; ++ reset-names = "mac","phy"; ++ mac-address = [00 00 00 00 00 00]; ++ phy-mode = "mii"; ++ phy-handle = <&phy0>; ++ hisilicon,phy-reset-delays-us = <10000 20000 20000>; ++ }; +diff --git a/Documentation/devicetree/bindings/net/hisilicon-gemac-mdio.txt b/Documentation/devicetree/bindings/net/hisilicon-gemac-mdio.txt +new file mode 100644 +index 0000000..c6f8202 +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/hisilicon-gemac-mdio.txt +@@ -0,0 +1,22 @@ ++Hisilicon Gigabit Ethernet MDIO Controller interface ++ ++Required properties: ++- compatible: should be "hisilicon,hisi-gemac-mdio". ++- reg: address and length of the register set for the device. ++- clocks: A phandle to the reference clock for this device. ++ ++- PHY subnode: inherits from phy binding [1] ++[1] Documentation/devicetree/bindings/net/phy.txt ++ ++Example: ++mdio: mdio@100503c0 { ++ compatible = "hisilicon,hisi-gemac-mdio"; ++ reg = <0x100503c0 0x20>; ++ clocks = <&crg HI3519V100_MDIO_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ phy0: phy@1 { ++ reg = <1>; ++ }; ++}; +diff --git a/Documentation/devicetree/bindings/net/hisilicon-hieth.txt b/Documentation/devicetree/bindings/net/hisilicon-hieth.txt +new file mode 100644 +index 0000000..21f8744 +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/hisilicon-hieth.txt +@@ -0,0 +1,45 @@ ++Hisilicon hieth controller ++ ++Required properties: ++- compatible: should be "hisilicon,hieth". ++- reg: specifies base physical address(s) and size of the device registers. ++ The region is the MAC register base and size. ++- interrupts: should contain the MAC interrupt. ++- #address-cells: must be <1>. ++- #size-cells: must be <0>. ++- phy-mode: see ethernet.txt [1]. ++- phy-handle: see ethernet.txt [1]. ++- mac-address: see ethernet.txt [1]. ++- clocks: clock phandle and specifier pair. ++- resets: reset controller phandle and specifier pair. ++ ++- PHY subnode: inherits from phy binding [2] ++ ++[1] Documentation/devicetree/bindings/net/ethernet.txt ++[2] Documentation/devicetree/bindings/net/phy.txt ++ ++Example: ++ hieth: ethernet@10050000 { ++ compatible = "hisilicon,hieth"; ++ reg = <0x10050000 0x4000>; ++ interrupts = <12>; ++ ++ clocks = <&clock HI3516CV300_ETH_CLK>; ++ clock-names = "clk"; ++ ++ resets = <&clock 0xcc 0>, ++ <&clock 0xcc 3>; ++ reset-names = "mac_reset", ++ "phy0_reset"; ++ ++ phy-handle = <&hieth_phy0>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hieth_phy0: hieth_phy@1 { ++ reg = <1>; ++ mac-address = [00 00 00 00 00 00]; ++ phy-mode = "mii"; ++ }; ++ }; +diff --git a/Documentation/devicetree/bindings/net/hisilicon-higmac.txt b/Documentation/devicetree/bindings/net/hisilicon-higmac.txt +new file mode 100644 +index 0000000..ea096d2 +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/hisilicon-higmac.txt +@@ -0,0 +1,52 @@ ++Hisilicon higmac controller ++ ++Required properties: ++- compatible: should be "hisilicon,higmac" and one of the following: ++ - "hisilicon,higmac-v1" ++ - "hisilicon,higmac-v2" ++ - "hisilicon,higmac-v3" ++ - "hisilicon,higmac-v4" ++ - "hisilicon,higmac-v5" ++- reg: specifies base physical address(s) and size of the device registers. ++ The first region is the MAC register base and size. ++ The second region is external interface control register. ++- interrupts: should contain the MAC interrupt. ++- #address-cells: must be <1>. ++- #size-cells: must be <0>. ++- phy-mode: see ethernet.txt [1]. ++- phy-handle: see ethernet.txt [1]. ++- mac-address: see ethernet.txt [1]. ++- clocks: clock phandle and specifier pair. ++- resets: reset controller phandle and specifier pair. ++ ++- PHY subnode: inherits from phy binding [2] ++ ++[1] Documentation/devicetree/bindings/net/ethernet.txt ++[2] Documentation/devicetree/bindings/net/phy.txt ++ ++Example: ++ higmac: ethernet@10050000 { ++ compatible = "hisilicon,higmac"; ++ reg = <0x10050000 0x1000>,<0x120100ec 0x4>; ++ interrupts = <0 25 4>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ phy-mode = "rgmii"; ++ phy-handle = <ð_phy>; ++ mac-address = [00 00 00 00 00 00]; ++ clocks = <&clock HI3519_ETH_CLK>, ++ <&clock HI3519_ETH_MACIF_CLK>; ++ clock-names = "higmac_clk", ++ "macif_clk"; ++ ++ resets = <&clock 0xcc 0>, ++ <&clock 0xcc 2>, ++ <&clock 0xcc 7>; ++ reset-names = "port_reset", ++ "macif_reset", ++ "phy_reset"; ++ ++ eth_phy: ethernet-phy@1 { ++ reg = <1>; ++ }; ++ }; +diff --git a/Documentation/devicetree/bindings/phy/hisi-sata-nano-phy.txt b/Documentation/devicetree/bindings/phy/hisi-sata-nano-phy.txt +new file mode 100644 +index 0000000..f06efeb +--- /dev/null ++++ b/Documentation/devicetree/bindings/phy/hisi-sata-nano-phy.txt +@@ -0,0 +1,22 @@ ++Hisilicon SATA NANO PHY ++----------------------- ++ ++Required properties: ++- compatible: should be "hisilicon,hisi-sata-nano-phy" ++- reg: offset and length of the PHY registers ++- #phy-cells: must be 0 ++Refer to phy/phy-bindings.txt for the generic PHY binding properties ++ ++Optional Properties: ++- hisilicon,peripheral-syscon: phandle of syscon used to control peripheral. ++- hisilicon,power-reg: offset and bit number within peripheral-syscon, ++ register of controlling sata power supply. ++ ++Example: ++ sata_phy: phy@f9900000 { ++ compatible = "hisilicon,hisi-sata-nano-phy"; ++ reg = <0xf9900000 0x10000>; ++ #phy-cells = <0>; ++ hisilicon,peripheral-syscon = <&peripheral_ctrl>; ++ hisilicon,power-reg = <0x8 10>; ++ }; +diff --git a/Documentation/devicetree/bindings/phy/hisi-usb-phy.txt b/Documentation/devicetree/bindings/phy/hisi-usb-phy.txt +new file mode 100644 +index 0000000..5d53065 +--- /dev/null ++++ b/Documentation/devicetree/bindings/phy/hisi-usb-phy.txt +@@ -0,0 +1,15 @@ ++Hisilicon hi3519 USB2 PHY ++----------------------- ++ ++Required properties: ++- compatible: should be "hisilicon,hisi-usb-phy" ++- reg: offset and length of the PHY registers ++- #phy-cells: must be 0 ++Refer to phy/phy-bindings.txt for the generic PHY binding properties ++ ++Example: ++ usb_phy: phy { ++ compatible = "hisilicon,hisi-usb-phy"; ++ reg = <0x12030000 0x10000>, <0x12010000 0x10000>; ++ #phy-cells = <0>; ++ }; +diff --git a/Documentation/devicetree/bindings/phy/hisi-usb3-phy.txt b/Documentation/devicetree/bindings/phy/hisi-usb3-phy.txt +new file mode 100644 +index 0000000..9781fc1 +--- /dev/null ++++ b/Documentation/devicetree/bindings/phy/hisi-usb3-phy.txt +@@ -0,0 +1,15 @@ ++Hisilicon hi3519 USB3 PHY ++----------------------- ++ ++Required properties: ++- compatible: should be "hisilicon,hisi-usb3-phy" ++- reg: offset and length of the PHY registers ++- #phy-cells: must be 0 ++Refer to phy/phy-bindings.txt for the generic PHY binding properties ++ ++Example: ++ usb3_phy: phy { ++ compatible = "hisilicon,hisi-usb3-phy"; ++ reg = <0x10180000 0x10000>, <0x12010000 0x10000>; ++ #phy-cells = <0>; ++ }; +diff --git a/Documentation/devicetree/bindings/phy/phy-hisi-inno-usb2.txt b/Documentation/devicetree/bindings/phy/phy-hisi-inno-usb2.txt +new file mode 100644 +index 0000000..59eaf73 +--- /dev/null ++++ b/Documentation/devicetree/bindings/phy/phy-hisi-inno-usb2.txt +@@ -0,0 +1,48 @@ ++HiSilicon INNO USB2 PHY ++----------------------- ++Required properties: ++- compatible: Should be "hisilicon,inno_usb2_phy" ++- #phy-cells: Must be 0 ++- hisilicon,peripheral-syscon: Phandle of syscon used to control phy. ++- hisilicon,reg-num: Number of phy registers which should be configured ++at phy intialization stage ++- hisilicon,reg-seq: Sequence of triplets of (address, value, delay-us). ++The number of triplets is equal to "hisilicon,reg-num". Each triplet is ++used to write one phy register. The delay-us cell represents the delay ++time in microseconds to be applied after each write. ++- clocks: Phandle and clock specifier pair for reference clock utmi_refclk. ++- resets: List of phandle and reset specifier pairs for each reset signal in ++reset-names. ++- reset-names: Should be "por_rst" and "test_rst". The test_rst only ++exists in some of SOCs, so it is optional. ++ ++Phy node can includes up to four subnodes. Each subnode represents one port. ++The required properties of port node are as follows: ++- clocks: Phandle and clock specifier pair for utmi_clock. ++- resets: List of phandle and reset specifier pairs for port reset and utmi reset. ++- reset-names: List of reset signal names. Should be "port_rst" and "utmi_rst" ++ ++Refer to phy/phy-bindings.txt for the generic PHY binding properties ++ ++Example: ++usb_phy: phy { ++ compatible = "hisilicon,inno_usb2_phy"; ++ #phy-cells = <0>; ++ hisilicon,peripheral-syscon = <&peri_ctrl>; ++ hisilicon,reg-num = <7>; ++ hisilicon,reg-seq = <0x80 0x800000 20>, ++ <0x80 0xa0060c 200>, ++ <0x80 0x80001c 20>, ++ <0x80 0xa0001c 20>, ++ <0x80 0x80060f 20>, ++ <0x80 0xa0060f 20>, ++ <0x80 0x800a4b 20>; ++ clocks = <&crg USB2_REF_CLK>; ++ resets = <&crg 0xb4 2>; ++ reset-names = "por_rst"; ++ port0 { ++ clocks = <&crg USB2_UTMI0_CLK>; ++ resets = <&crg 0xb4 5>, <&crg 0xb4 1>; ++ reset-names = "port_rst", "utmi_rst"; ++ }; ++ }; +diff --git a/Documentation/devicetree/bindings/pwm/pwm-hibvt.txt b/Documentation/devicetree/bindings/pwm/pwm-hibvt.txt +new file mode 100644 +index 0000000..2ecf4e4 +--- /dev/null ++++ b/Documentation/devicetree/bindings/pwm/pwm-hibvt.txt +@@ -0,0 +1,20 @@ ++Hisilicon PWM controller ++ ++Required properties: ++-compatible: should contain one SoC specific compatible string and one generic compatible ++string "hisilicon, hibvt-pwm". The SoC specific strings supported including: ++ "hisilicon,hi3516cv300-pwm" ++ "hisilicon,hi3519v100-pwm" ++- reg: physical base address and length of the controller's registers. ++- clocks: phandle and clock specifier of the PWM reference clock. ++- resets: phandle and reset specifier for the PWM controller reset. ++ ++Example: ++ pwm: pwm@12130000 { ++ ++ compatible = "hisilicon,hi3516cv300-pwm", "hisilicon,hibvt-pwm"; ++ compatible = "hisilicon,hi3519v100-pwm", "hisilicon,hibvt-pwm"; ++ reg = <0x12130000 0x10000>; ++ clocks = <&crg_ctrl HI3516CV300_PWM_CLK>; ++ resets = <&crg_ctrl 0x38 0>; ++ }; +diff --git a/Documentation/devicetree/bindings/rtc/rtc-hibvt.txt b/Documentation/devicetree/bindings/rtc/rtc-hibvt.txt +new file mode 100644 +index 0000000..1543ee1 +--- /dev/null ++++ b/Documentation/devicetree/bindings/rtc/rtc-hibvt.txt +@@ -0,0 +1,16 @@ ++Hisilicon RTC controller ++ ++Required properties: ++-compatible: should contain one SoC specific compatible string ++The SoC specific strings supported including: ++- compatible: "hisilicon,hi35xvr-rtc" ++- reg: physical base address and length of the controller's registers. ++- interrupts: IRQ line for the RTC. ++ ++Example: ++rtc: rtc@120b0000 { ++ compatible = "hisilicon,hi35xvr-rtc"; ++ reg = <0x120b0000 0x10000>; ++ interrupts = <0 5 4>; ++ }; ++ +diff --git a/Documentation/devicetree/bindings/thermal/thermal.txt b/Documentation/devicetree/bindings/thermal/thermal.txt +index f5db6b7..99d6608 100644 +--- a/Documentation/devicetree/bindings/thermal/thermal.txt ++++ b/Documentation/devicetree/bindings/thermal/thermal.txt +@@ -167,6 +167,13 @@ Optional property: + by means of sensor ID. Additional coefficients are + interpreted as constant offset. + ++- sustainable-power: An estimate of the sustainable power (in mW) that the ++ Type: unsigned thermal zone can dissipate at the desired ++ Size: one cell control temperature. For reference, the ++ sustainable power of a 4'' phone is typically ++ 2000mW, while on a 10'' tablet is around ++ 4500mW. ++ + Note: The delay properties are bound to the maximum dT/dt (temperature + derivative over time) in two situations for a thermal zone: + (i) - when passive cooling is activated (polling-delay-passive); and +@@ -546,6 +553,8 @@ thermal-zones { + */ + coefficients = <1200 -345 890>; + ++ sustainable-power = <2500>; ++ + trips { + /* Trips are based on resulting linear equation */ + cpu-trip: cpu-trip { +diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt +index eb8a10e..e2def60 100644 +--- a/Documentation/filesystems/proc.txt ++++ b/Documentation/filesystems/proc.txt +@@ -369,6 +369,8 @@ is not associated with a file: + [stack:1001] = the stack of the thread with tid 1001 + [vdso] = the "virtual dynamic shared object", + the kernel system call handler ++ [anon:] = an anonymous mapping that has been ++ named by userspace + + or if empty, the mapping is anonymous. + +@@ -419,6 +421,7 @@ KernelPageSize: 4 kB + MMUPageSize: 4 kB + Locked: 374 kB + VmFlags: rd ex mr mw me de ++Name: name from userspace + + the first of these lines shows the same information as is displayed for the + mapping in /proc/PID/maps. The remaining lines show the size of the mapping +@@ -470,6 +473,9 @@ Note that there is no guarantee that every flag and associated mnemonic will + be present in all further kernel releases. Things get changed, the flags may + be vanished or the reverse -- new added. + ++The "Name" field will only be present on a mapping that has been named by ++userspace, and will show the name passed in by userspace. ++ + This file is only present if the CONFIG_MMU kernel configuration option is + enabled. + +@@ -488,6 +494,10 @@ To clear the bits for the file mapped pages associated with the process + To clear the soft-dirty bit + > echo 4 > /proc/PID/clear_refs + ++To reset the peak resident set size ("high water mark") to the process's ++current value: ++ > echo 5 > /proc/PID/clear_refs ++ + Any other value written to /proc/PID/clear_refs will have no effect. + + The /proc/pid/pagemap gives the PFN, which can be used to find the pageflags +diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt +index a476b08..64a0fc5 100644 +--- a/Documentation/networking/ip-sysctl.txt ++++ b/Documentation/networking/ip-sysctl.txt +@@ -60,7 +60,9 @@ fwmark_reflect - BOOLEAN + Controls the fwmark of kernel-generated IPv4 reply packets that are not + associated with a socket for example, TCP RSTs or ICMP echo replies). + If unset, these packets have a fwmark of zero. If set, they have the +- fwmark of the packet they are replying to. ++ fwmark of the packet they are replying to. Similarly affects the fwmark ++ used by internal routing lookups triggered by incoming packets, such as ++ the ones used for Path MTU Discovery. + Default: 0 + + route/max_size - INTEGER +@@ -516,6 +518,16 @@ tcp_fastopen - INTEGER + + See include/net/tcp.h and the code for more details. + ++tcp_fwmark_accept - BOOLEAN ++ If set, incoming connections to listening sockets that do not have a ++ socket mark will set the mark of the accepting socket to the fwmark of ++ the incoming SYN packet. This will cause all packets on that connection ++ (starting from the first SYNACK) to be sent with that fwmark. The ++ listening socket's mark is unchanged. Listening sockets that already ++ have a fwmark set via setsockopt(SOL_SOCKET, SO_MARK, ...) are ++ unaffected. ++ Default: 0 ++ + tcp_syn_retries - INTEGER + Number of times initial SYNs for an active TCP connection attempt + will be retransmitted. Should not be higher than 255. Default value +@@ -1212,7 +1224,9 @@ fwmark_reflect - BOOLEAN + Controls the fwmark of kernel-generated IPv6 reply packets that are not + associated with a socket for example, TCP RSTs or ICMPv6 echo replies). + If unset, these packets have a fwmark of zero. If set, they have the +- fwmark of the packet they are replying to. ++ fwmark of the packet they are replying to. Similarly affects the fwmark ++ used by internal routing lookups triggered by incoming packets, such as ++ the ones used for Path MTU Discovery. + Default: 0 + + conf/interface/*: +@@ -1466,6 +1480,19 @@ suppress_frag_ndisc - INTEGER + 1 - (default) discard fragmented neighbor discovery packets + 0 - allow fragmented neighbor discovery packets + ++optimistic_dad - BOOLEAN ++ Whether to perform Optimistic Duplicate Address Detection (RFC 4429). ++ 0: disabled (default) ++ 1: enabled ++ ++use_optimistic - BOOLEAN ++ If enabled, do not classify optimistic addresses as deprecated during ++ source address selection. Preferred addresses will still be chosen ++ before optimistic addresses, subject to other ranking in the source ++ address selection algorithm. ++ 0: disabled (default) ++ 1: enabled ++ + icmp/*: + ratelimit - INTEGER + Limit the maximal rates for sending ICMPv6 packets. +diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt +index e839e7e..e9cb02a 100644 +--- a/Documentation/networking/phy.txt ++++ b/Documentation/networking/phy.txt +@@ -337,3 +337,12 @@ Board Fixups + The stubs set one of the two matching criteria, and set the other one to + match anything. + ++ When phy_register_fixup() or *_for_uid()/*_for_id() is called at module, ++ unregister fixup and free allocate memory are required. ++ ++ Call one of following function before unloading module. ++ ++ int phy_unregister_fixup(const char *phy_id, u32 phy_uid, u32 phy_uid_mask); ++ int phy_unregister_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask); ++ int phy_register_fixup_for_id(const char *phy_id); ++ +diff --git a/Documentation/sync.txt b/Documentation/sync.txt +new file mode 100644 +index 0000000..a2d05e7 +--- /dev/null ++++ b/Documentation/sync.txt +@@ -0,0 +1,75 @@ ++Motivation: ++ ++In complicated DMA pipelines such as graphics (multimedia, camera, gpu, display) ++a consumer of a buffer needs to know when the producer has finished producing ++it. Likewise the producer needs to know when the consumer is finished with the ++buffer so it can reuse it. A particular buffer may be consumed by multiple ++consumers which will retain the buffer for different amounts of time. In ++addition, a consumer may consume multiple buffers atomically. ++The sync framework adds an API which allows synchronization between the ++producers and consumers in a generic way while also allowing platforms which ++have shared hardware synchronization primitives to exploit them. ++ ++Goals: ++ * provide a generic API for expressing synchronization dependencies ++ * allow drivers to exploit hardware synchronization between hardware ++ blocks ++ * provide a userspace API that allows a compositor to manage ++ dependencies. ++ * provide rich telemetry data to allow debugging slowdowns and stalls of ++ the graphics pipeline. ++ ++Objects: ++ * sync_timeline ++ * sync_pt ++ * sync_fence ++ ++sync_timeline: ++ ++A sync_timeline is an abstract monotonically increasing counter. In general, ++each driver/hardware block context will have one of these. They can be backed ++by the appropriate hardware or rely on the generic sw_sync implementation. ++Timelines are only ever created through their specific implementations ++(i.e. sw_sync.) ++ ++sync_pt: ++ ++A sync_pt is an abstract value which marks a point on a sync_timeline. Sync_pts ++have a single timeline parent. They have 3 states: active, signaled, and error. ++They start in active state and transition, once, to either signaled (when the ++timeline counter advances beyond the sync_pt鈥檚 value) or error state. ++ ++sync_fence: ++ ++Sync_fences are the primary primitives used by drivers to coordinate ++synchronization of their buffers. They are a collection of sync_pts which may ++or may not have the same timeline parent. A sync_pt can only exist in one fence ++and the fence's list of sync_pts is immutable once created. Fences can be ++waited on synchronously or asynchronously. Two fences can also be merged to ++create a third fence containing a copy of the two fences鈥 sync_pts. Fences are ++backed by file descriptors to allow userspace to coordinate the display pipeline ++dependencies. ++ ++Use: ++ ++A driver implementing sync support should have a work submission function which: ++ * takes a fence argument specifying when to begin work ++ * asynchronously queues that work to kick off when the fence is signaled ++ * returns a fence to indicate when its work will be done. ++ * signals the returned fence once the work is completed. ++ ++Consider an imaginary display driver that has the following API: ++/* ++ * assumes buf is ready to be displayed. ++ * blocks until the buffer is on screen. ++ */ ++ void display_buffer(struct dma_buf *buf); ++ ++The new API will become: ++/* ++ * will display buf when fence is signaled. ++ * returns immediately with a fence that will signal when buf ++ * is no longer displayed. ++ */ ++struct sync_fence* display_buffer(struct dma_buf *buf, ++ struct sync_fence *fence); +diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt +index 88152f2..302b5ed 100644 +--- a/Documentation/sysctl/fs.txt ++++ b/Documentation/sysctl/fs.txt +@@ -32,6 +32,8 @@ Currently, these files are in /proc/sys/fs: + - nr_open + - overflowuid + - overflowgid ++- pipe-user-pages-hard ++- pipe-user-pages-soft + - protected_hardlinks + - protected_symlinks + - suid_dumpable +@@ -159,6 +161,27 @@ The default is 65534. + + ============================================================== + ++pipe-user-pages-hard: ++ ++Maximum total number of pages a non-privileged user may allocate for pipes. ++Once this limit is reached, no new pipes may be allocated until usage goes ++below the limit again. When set to 0, no limit is applied, which is the default ++setting. ++ ++============================================================== ++ ++pipe-user-pages-soft: ++ ++Maximum total number of pages a non-privileged user may allocate for pipes ++before the pipe size gets limited to a single page. Once this limit is reached, ++new pipes will be limited to a single page in size for this user in order to ++limit total memory usage, and trying to increase them using fcntl() will be ++denied until usage goes below the limit again. The default value allows to ++allocate up to 1024 pipes at their default size. When set to 0, no limit is ++applied. ++ ++============================================================== ++ + protected_hardlinks: + + A long-standing class of security issues is the hardlink-based +diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt +index 4415aa9..9aecaa5 100644 +--- a/Documentation/sysctl/vm.txt ++++ b/Documentation/sysctl/vm.txt +@@ -29,6 +29,7 @@ Currently, these files are in /proc/sys/vm: + - dirty_writeback_centisecs + - drop_caches + - extfrag_threshold ++- extra_free_kbytes + - hugepages_treat_as_movable + - hugetlb_shm_group + - laptop_mode +@@ -225,6 +226,21 @@ fragmentation index is <= extfrag_threshold. The default value is 500. + + ============================================================== + ++extra_free_kbytes ++ ++This parameter tells the VM to keep extra free memory between the threshold ++where background reclaim (kswapd) kicks in, and the threshold where direct ++reclaim (by allocating processes) kicks in. ++ ++This is useful for workloads that require low latency memory allocations ++and have a bounded burstiness in memory allocations, for example a ++realtime application that receives and transmits network traffic ++(causing in-kernel memory allocations) with a maximum total message burst ++size of 200MB may need 200MB of extra free memory to avoid direct reclaim ++related latencies. ++ ++============================================================== ++ + hugepages_treat_as_movable + + This parameter controls whether we can allocate hugepages from ZONE_MOVABLE +diff --git a/Documentation/thermal/cpu-cooling-api.txt b/Documentation/thermal/cpu-cooling-api.txt +index fca24c9..7165358 100644 +--- a/Documentation/thermal/cpu-cooling-api.txt ++++ b/Documentation/thermal/cpu-cooling-api.txt +@@ -3,7 +3,7 @@ CPU cooling APIs How To + + Written by Amit Daniel Kachhap + +-Updated: 12 May 2012 ++Updated: 6 Jan 2015 + + Copyright (c) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com) + +@@ -25,8 +25,173 @@ the user. The registration APIs returns the cooling device pointer. + + clip_cpus: cpumask of cpus where the frequency constraints will happen. + +-1.1.2 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) ++1.1.2 struct thermal_cooling_device *of_cpufreq_cooling_register( ++ struct device_node *np, const struct cpumask *clip_cpus) ++ ++ This interface function registers the cpufreq cooling device with ++ the name "thermal-cpufreq-%x" linking it with a device tree node, in ++ order to bind it via the thermal DT code. This api can support multiple ++ instances of cpufreq cooling devices. ++ ++ np: pointer to the cooling device device tree node ++ clip_cpus: cpumask of cpus where the frequency constraints will happen. ++ ++1.1.3 struct thermal_cooling_device *cpufreq_power_cooling_register( ++ const struct cpumask *clip_cpus, u32 capacitance, ++ get_static_t plat_static_func) ++ ++Similar to cpufreq_cooling_register, this function registers a cpufreq ++cooling device. Using this function, the cooling device will ++implement the power extensions by using a simple cpu power model. The ++cpus must have registered their OPPs using the OPP library. ++ ++The additional parameters are needed for the power model (See 2. Power ++models). "capacitance" is the dynamic power coefficient (See 2.1 ++Dynamic power). "plat_static_func" is a function to calculate the ++static power consumed by these cpus (See 2.2 Static power). ++ ++1.1.4 struct thermal_cooling_device *of_cpufreq_power_cooling_register( ++ struct device_node *np, const struct cpumask *clip_cpus, u32 capacitance, ++ get_static_t plat_static_func) ++ ++Similar to cpufreq_power_cooling_register, this function register a ++cpufreq cooling device with power extensions using the device tree ++information supplied by the np parameter. ++ ++1.1.5 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) + + This interface function unregisters the "thermal-cpufreq-%x" cooling device. + + cdev: Cooling device pointer which has to be unregistered. ++ ++2. Power models ++ ++The power API registration functions provide a simple power model for ++CPUs. The current power is calculated as dynamic + (optionally) ++static power. This power model requires that the operating-points of ++the CPUs are registered using the kernel's opp library and the ++`cpufreq_frequency_table` is assigned to the `struct device` of the ++cpu. If you are using CONFIG_CPUFREQ_DT then the ++`cpufreq_frequency_table` should already be assigned to the cpu ++device. ++ ++The `plat_static_func` parameter of `cpufreq_power_cooling_register()` ++and `of_cpufreq_power_cooling_register()` is optional. If you don't ++provide it, only dynamic power will be considered. ++ ++2.1 Dynamic power ++ ++The dynamic power consumption of a processor depends on many factors. ++For a given processor implementation the primary factors are: ++ ++- The time the processor spends running, consuming dynamic power, as ++ compared to the time in idle states where dynamic consumption is ++ negligible. Herein we refer to this as 'utilisation'. ++- The voltage and frequency levels as a result of DVFS. The DVFS ++ level is a dominant factor governing power consumption. ++- In running time the 'execution' behaviour (instruction types, memory ++ access patterns and so forth) causes, in most cases, a second order ++ variation. In pathological cases this variation can be significant, ++ but typically it is of a much lesser impact than the factors above. ++ ++A high level dynamic power consumption model may then be represented as: ++ ++Pdyn = f(run) * Voltage^2 * Frequency * Utilisation ++ ++f(run) here represents the described execution behaviour and its ++result has a units of Watts/Hz/Volt^2 (this often expressed in ++mW/MHz/uVolt^2) ++ ++The detailed behaviour for f(run) could be modelled on-line. However, ++in practice, such an on-line model has dependencies on a number of ++implementation specific processor support and characterisation ++factors. Therefore, in initial implementation that contribution is ++represented as a constant coefficient. This is a simplification ++consistent with the relative contribution to overall power variation. ++ ++In this simplified representation our model becomes: ++ ++Pdyn = Capacitance * Voltage^2 * Frequency * Utilisation ++ ++Where `capacitance` is a constant that represents an indicative ++running time dynamic power coefficient in fundamental units of ++mW/MHz/uVolt^2. Typical values for mobile CPUs might lie in range ++from 100 to 500. For reference, the approximate values for the SoC in ++ARM's Juno Development Platform are 530 for the Cortex-A57 cluster and ++140 for the Cortex-A53 cluster. ++ ++ ++2.2 Static power ++ ++Static leakage power consumption depends on a number of factors. For a ++given circuit implementation the primary factors are: ++ ++- Time the circuit spends in each 'power state' ++- Temperature ++- Operating voltage ++- Process grade ++ ++The time the circuit spends in each 'power state' for a given ++evaluation period at first order means OFF or ON. However, ++'retention' states can also be supported that reduce power during ++inactive periods without loss of context. ++ ++Note: The visibility of state entries to the OS can vary, according to ++platform specifics, and this can then impact the accuracy of a model ++based on OS state information alone. It might be possible in some ++cases to extract more accurate information from system resources. ++ ++The temperature, operating voltage and process 'grade' (slow to fast) ++of the circuit are all significant factors in static leakage power ++consumption. All of these have complex relationships to static power. ++ ++Circuit implementation specific factors include the chosen silicon ++process as well as the type, number and size of transistors in both ++the logic gates and any RAM elements included. ++ ++The static power consumption modelling must take into account the ++power managed regions that are implemented. Taking the example of an ++ARM processor cluster, the modelling would take into account whether ++each CPU can be powered OFF separately or if only a single power ++region is implemented for the complete cluster. ++ ++In one view, there are others, a static power consumption model can ++then start from a set of reference values for each power managed ++region (e.g. CPU, Cluster/L2) in each state (e.g. ON, OFF) at an ++arbitrary process grade, voltage and temperature point. These values ++are then scaled for all of the following: the time in each state, the ++process grade, the current temperature and the operating voltage. ++However, since both implementation specific and complex relationships ++dominate the estimate, the appropriate interface to the model from the ++cpu cooling device is to provide a function callback that calculates ++the static power in this platform. When registering the cpu cooling ++device pass a function pointer that follows the `get_static_t` ++prototype: ++ ++ int plat_get_static(cpumask_t *cpumask, int interval, ++ unsigned long voltage, u32 &power); ++ ++`cpumask` is the cpumask of the cpus involved in the calculation. ++`voltage` is the voltage at which they are operating. The function ++should calculate the average static power for the last `interval` ++milliseconds. It returns 0 on success, -E* on error. If it ++succeeds, it should store the static power in `power`. Reading the ++temperature of the cpus described by `cpumask` is left for ++plat_get_static() to do as the platform knows best which thermal ++sensor is closest to the cpu. ++ ++If `plat_static_func` is NULL, static power is considered to be ++negligible for this platform and only dynamic power is considered. ++ ++The platform specific callback can then use any combination of tables ++and/or equations to permute the estimated value. Process grade ++information is not passed to the model since access to such data, from ++on-chip measurement capability or manufacture time data, is platform ++specific. ++ ++Note: the significance of static power for CPUs in comparison to ++dynamic power is highly dependent on implementation. Given the ++potential complexity in implementation, the importance and accuracy of ++its inclusion when using cpu cooling devices should be assessed on a ++case by case basis. ++ +diff --git a/Documentation/thermal/power_allocator.txt b/Documentation/thermal/power_allocator.txt +new file mode 100644 +index 0000000..c3797b5 +--- /dev/null ++++ b/Documentation/thermal/power_allocator.txt +@@ -0,0 +1,247 @@ ++Power allocator governor tunables ++================================= ++ ++Trip points ++----------- ++ ++The governor requires the following two passive trip points: ++ ++1. "switch on" trip point: temperature above which the governor ++ control loop starts operating. This is the first passive trip ++ point of the thermal zone. ++ ++2. "desired temperature" trip point: it should be higher than the ++ "switch on" trip point. This the target temperature the governor ++ is controlling for. This is the last passive trip point of the ++ thermal zone. ++ ++PID Controller ++-------------- ++ ++The power allocator governor implements a ++Proportional-Integral-Derivative controller (PID controller) with ++temperature as the control input and power as the controlled output: ++ ++ P_max = k_p * e + k_i * err_integral + k_d * diff_err + sustainable_power ++ ++where ++ e = desired_temperature - current_temperature ++ err_integral is the sum of previous errors ++ diff_err = e - previous_error ++ ++It is similar to the one depicted below: ++ ++ k_d ++ | ++current_temp | ++ | v ++ | +----------+ +---+ ++ | +----->| diff_err |-->| X |------+ ++ | | +----------+ +---+ | ++ | | | tdp actor ++ | | k_i | | get_requested_power() ++ | | | | | | | ++ | | | | | | | ... ++ v | v v v v v ++ +---+ | +-------+ +---+ +---+ +---+ +----------+ ++ | S |-------+----->| sum e |----->| X |--->| S |-->| S |-->|power | ++ +---+ | +-------+ +---+ +---+ +---+ |allocation| ++ ^ | ^ +----------+ ++ | | | | | ++ | | +---+ | | | ++ | +------->| X |-------------------+ v v ++ | +---+ granted performance ++desired_temperature ^ ++ | ++ | ++ k_po/k_pu ++ ++Sustainable power ++----------------- ++ ++An estimate of the sustainable dissipatable power (in mW) should be ++provided while registering the thermal zone. This estimates the ++sustained power that can be dissipated at the desired control ++temperature. This is the maximum sustained power for allocation at ++the desired maximum temperature. The actual sustained power can vary ++for a number of reasons. The closed loop controller will take care of ++variations such as environmental conditions, and some factors related ++to the speed-grade of the silicon. `sustainable_power` is therefore ++simply an estimate, and may be tuned to affect the aggressiveness of ++the thermal ramp. For reference, the sustainable power of a 4" phone ++is typically 2000mW, while on a 10" tablet is around 4500mW (may vary ++depending on screen size). ++ ++If you are using device tree, do add it as a property of the ++thermal-zone. For example: ++ ++ thermal-zones { ++ soc_thermal { ++ polling-delay = <1000>; ++ polling-delay-passive = <100>; ++ sustainable-power = <2500>; ++ ... ++ ++Instead, if the thermal zone is registered from the platform code, pass a ++`thermal_zone_params` that has a `sustainable_power`. If no ++`thermal_zone_params` were being passed, then something like below ++will suffice: ++ ++ static const struct thermal_zone_params tz_params = { ++ .sustainable_power = 3500, ++ }; ++ ++and then pass `tz_params` as the 5th parameter to ++`thermal_zone_device_register()` ++ ++k_po and k_pu ++------------- ++ ++The implementation of the PID controller in the power allocator ++thermal governor allows the configuration of two proportional term ++constants: `k_po` and `k_pu`. `k_po` is the proportional term ++constant during temperature overshoot periods (current temperature is ++above "desired temperature" trip point). Conversely, `k_pu` is the ++proportional term constant during temperature undershoot periods ++(current temperature below "desired temperature" trip point). ++ ++These controls are intended as the primary mechanism for configuring ++the permitted thermal "ramp" of the system. For instance, a lower ++`k_pu` value will provide a slower ramp, at the cost of capping ++available capacity at a low temperature. On the other hand, a high ++value of `k_pu` will result in the governor granting very high power ++whilst temperature is low, and may lead to temperature overshooting. ++ ++The default value for `k_pu` is: ++ ++ 2 * sustainable_power / (desired_temperature - switch_on_temp) ++ ++This means that at `switch_on_temp` the output of the controller's ++proportional term will be 2 * `sustainable_power`. The default value ++for `k_po` is: ++ ++ sustainable_power / (desired_temperature - switch_on_temp) ++ ++Focusing on the proportional and feed forward values of the PID ++controller equation we have: ++ ++ P_max = k_p * e + sustainable_power ++ ++The proportional term is proportional to the difference between the ++desired temperature and the current one. When the current temperature ++is the desired one, then the proportional component is zero and ++`P_max` = `sustainable_power`. That is, the system should operate in ++thermal equilibrium under constant load. `sustainable_power` is only ++an estimate, which is the reason for closed-loop control such as this. ++ ++Expanding `k_pu` we get: ++ P_max = 2 * sustainable_power * (T_set - T) / (T_set - T_on) + ++ sustainable_power ++ ++where ++ T_set is the desired temperature ++ T is the current temperature ++ T_on is the switch on temperature ++ ++When the current temperature is the switch_on temperature, the above ++formula becomes: ++ ++ P_max = 2 * sustainable_power * (T_set - T_on) / (T_set - T_on) + ++ sustainable_power = 2 * sustainable_power + sustainable_power = ++ 3 * sustainable_power ++ ++Therefore, the proportional term alone linearly decreases power from ++3 * `sustainable_power` to `sustainable_power` as the temperature ++rises from the switch on temperature to the desired temperature. ++ ++k_i and integral_cutoff ++----------------------- ++ ++`k_i` configures the PID loop's integral term constant. This term ++allows the PID controller to compensate for long term drift and for ++the quantized nature of the output control: cooling devices can't set ++the exact power that the governor requests. When the temperature ++error is below `integral_cutoff`, errors are accumulated in the ++integral term. This term is then multiplied by `k_i` and the result ++added to the output of the controller. Typically `k_i` is set low (1 ++or 2) and `integral_cutoff` is 0. ++ ++k_d ++--- ++ ++`k_d` configures the PID loop's derivative term constant. It's ++recommended to leave it as the default: 0. ++ ++Cooling device power API ++======================== ++ ++Cooling devices controlled by this governor must supply the additional ++"power" API in their `cooling_device_ops`. It consists on three ops: ++ ++1. int get_requested_power(struct thermal_cooling_device *cdev, ++ struct thermal_zone_device *tz, u32 *power); ++@cdev: The `struct thermal_cooling_device` pointer ++@tz: thermal zone in which we are currently operating ++@power: pointer in which to store the calculated power ++ ++`get_requested_power()` calculates the power requested by the device ++in milliwatts and stores it in @power . It should return 0 on ++success, -E* on failure. This is currently used by the power ++allocator governor to calculate how much power to give to each cooling ++device. ++ ++2. int state2power(struct thermal_cooling_device *cdev, struct ++ thermal_zone_device *tz, unsigned long state, u32 *power); ++@cdev: The `struct thermal_cooling_device` pointer ++@tz: thermal zone in which we are currently operating ++@state: A cooling device state ++@power: pointer in which to store the equivalent power ++ ++Convert cooling device state @state into power consumption in ++milliwatts and store it in @power. It should return 0 on success, -E* ++on failure. This is currently used by thermal core to calculate the ++maximum power that an actor can consume. ++ ++3. int power2state(struct thermal_cooling_device *cdev, u32 power, ++ unsigned long *state); ++@cdev: The `struct thermal_cooling_device` pointer ++@power: power in milliwatts ++@state: pointer in which to store the resulting state ++ ++Calculate a cooling device state that would make the device consume at ++most @power mW and store it in @state. It should return 0 on success, ++-E* on failure. This is currently used by the thermal core to convert ++a given power set by the power allocator governor to a state that the ++cooling device can set. It is a function because this conversion may ++depend on external factors that may change so this function should the ++best conversion given "current circumstances". ++ ++Cooling device weights ++---------------------- ++ ++Weights are a mechanism to bias the allocation among cooling ++devices. They express the relative power efficiency of different ++cooling devices. Higher weight can be used to express higher power ++efficiency. Weighting is relative such that if each cooling device ++has a weight of one they are considered equal. This is particularly ++useful in heterogeneous systems where two cooling devices may perform ++the same kind of compute, but with different efficiency. For example, ++a system with two different types of processors. ++ ++If the thermal zone is registered using ++`thermal_zone_device_register()` (i.e., platform code), then weights ++are passed as part of the thermal zone's `thermal_bind_parameters`. ++If the platform is registered using device tree, then they are passed ++as the `contribution` property of each map in the `cooling-maps` node. ++ ++Limitations of the power allocator governor ++=========================================== ++ ++The power allocator governor's PID controller works best if there is a ++periodic tick. If you have a driver that calls ++`thermal_zone_device_update()` (or anything that ends up calling the ++governor's `throttle()` function) repetitively, the governor response ++won't be very good. Note that this is not particular to this ++governor, step-wise will also misbehave if you call its throttle() ++faster than the normal thermal framework tick (due to interrupts for ++example) as it will overreact. +diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt +index 87519cb..c1f6864 100644 +--- a/Documentation/thermal/sysfs-api.txt ++++ b/Documentation/thermal/sysfs-api.txt +@@ -95,7 +95,7 @@ temperature) and throttle appropriate devices. + 1.3 interface for binding a thermal zone device with a thermal cooling device + 1.3.1 int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, + int trip, struct thermal_cooling_device *cdev, +- unsigned long upper, unsigned long lower); ++ unsigned long upper, unsigned long lower, unsigned int weight); + + This interface function bind a thermal cooling device to the certain trip + point of a thermal zone device. +@@ -110,6 +110,8 @@ temperature) and throttle appropriate devices. + lower:the Minimum cooling state can be used for this trip point. + THERMAL_NO_LIMIT means no lower limit, + and the cooling device can be in cooling state 0. ++ weight: the influence of this cooling device in this thermal ++ zone. See 1.4.1 below for more information. + + 1.3.2 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, + int trip, struct thermal_cooling_device *cdev); +@@ -127,9 +129,15 @@ temperature) and throttle appropriate devices. + This structure defines the following parameters that are used to bind + a zone with a cooling device for a particular trip point. + .cdev: The cooling device pointer +- .weight: The 'influence' of a particular cooling device on this zone. +- This is on a percentage scale. The sum of all these weights +- (for a particular zone) cannot exceed 100. ++ .weight: The 'influence' of a particular cooling device on this ++ zone. This is relative to the rest of the cooling ++ devices. For example, if all cooling devices have a ++ weight of 1, then they all contribute the same. You can ++ use percentages if you want, but it's not mandatory. A ++ weight of 0 means that this cooling device doesn't ++ contribute to the cooling of this zone unless all cooling ++ devices have a weight of 0. If all weights are 0, then ++ they all contribute the same. + .trip_mask:This is a bit mask that gives the binding relation between + this thermal zone and cdev, for a particular trip point. + If nth bit is set, then the cdev and thermal zone are bound +@@ -176,6 +184,14 @@ Thermal zone device sys I/F, created once it's registered: + |---trip_point_[0-*]_type: Trip point type + |---trip_point_[0-*]_hyst: Hysteresis value for this trip point + |---emul_temp: Emulated temperature set node ++ |---sustainable_power: Sustainable dissipatable power ++ |---k_po: Proportional term during temperature overshoot ++ |---k_pu: Proportional term during temperature undershoot ++ |---k_i: PID's integral term in the power allocator gov ++ |---k_d: PID's derivative term in the power allocator ++ |---integral_cutoff: Offset above which errors are accumulated ++ |---slope: Slope constant applied as linear extrapolation ++ |---offset: Offset constant applied as linear extrapolation + + Thermal cooling device sys I/F, created once it's registered: + /sys/class/thermal/cooling_device[0-*]: +@@ -192,6 +208,8 @@ thermal_zone_bind_cooling_device/thermal_zone_unbind_cooling_device. + /sys/class/thermal/thermal_zone[0-*]: + |---cdev[0-*]: [0-*]th cooling device in current thermal zone + |---cdev[0-*]_trip_point: Trip point that cdev[0-*] is associated with ++ |---cdev[0-*]_weight: Influence of the cooling device in ++ this thermal zone + + Besides the thermal zone device sysfs I/F and cooling device sysfs I/F, + the generic thermal driver also creates a hwmon sysfs I/F for each _type_ +@@ -265,6 +283,14 @@ cdev[0-*]_trip_point + point. + RO, Optional + ++cdev[0-*]_weight ++ The influence of cdev[0-*] in this thermal zone. This value ++ is relative to the rest of cooling devices in the thermal ++ zone. For example, if a cooling device has a weight double ++ than that of other, it's twice as effective in cooling the ++ thermal zone. ++ RW, Optional ++ + passive + Attribute is only present for zones in which the passive cooling + policy is not supported by native thermal driver. Default is zero +@@ -289,6 +315,66 @@ emul_temp + because userland can easily disable the thermal policy by simply + flooding this sysfs node with low temperature values. + ++sustainable_power ++ An estimate of the sustained power that can be dissipated by ++ the thermal zone. Used by the power allocator governor. For ++ more information see Documentation/thermal/power_allocator.txt ++ Unit: milliwatts ++ RW, Optional ++ ++k_po ++ The proportional term of the power allocator governor's PID ++ controller during temperature overshoot. Temperature overshoot ++ is when the current temperature is above the "desired ++ temperature" trip point. For more information see ++ Documentation/thermal/power_allocator.txt ++ RW, Optional ++ ++k_pu ++ The proportional term of the power allocator governor's PID ++ controller during temperature undershoot. Temperature undershoot ++ is when the current temperature is below the "desired ++ temperature" trip point. For more information see ++ Documentation/thermal/power_allocator.txt ++ RW, Optional ++ ++k_i ++ The integral term of the power allocator governor's PID ++ controller. This term allows the PID controller to compensate ++ for long term drift. For more information see ++ Documentation/thermal/power_allocator.txt ++ RW, Optional ++ ++k_d ++ The derivative term of the power allocator governor's PID ++ controller. For more information see ++ Documentation/thermal/power_allocator.txt ++ RW, Optional ++ ++integral_cutoff ++ Temperature offset from the desired temperature trip point ++ above which the integral term of the power allocator ++ governor's PID controller starts accumulating errors. For ++ example, if integral_cutoff is 0, then the integral term only ++ accumulates error when temperature is above the desired ++ temperature trip point. For more information see ++ Documentation/thermal/power_allocator.txt ++ RW, Optional ++ ++slope ++ The slope constant used in a linear extrapolation model ++ to determine a hotspot temperature based off the sensor's ++ raw readings. It is up to the device driver to determine ++ the usage of these values. ++ RW, Optional ++ ++offset ++ The offset constant used in a linear extrapolation model ++ to determine a hotspot temperature based off the sensor's ++ raw readings. It is up to the device driver to determine ++ the usage of these values. ++ RW, Optional ++ + ***************************** + * Cooling device attributes * + ***************************** +@@ -318,7 +404,8 @@ passive, active. If an ACPI thermal zone supports critical, passive, + active[0] and active[1] at the same time, it may register itself as a + thermal_zone_device (thermal_zone1) with 4 trip points in all. + It has one processor and one fan, which are both registered as +-thermal_cooling_device. ++thermal_cooling_device. Both are considered to have the same ++effectiveness in cooling the thermal zone. + + If the processor is listed in _PSL method, and the fan is listed in _AL0 + method, the sys I/F structure will be built like this: +@@ -340,8 +427,10 @@ method, the sys I/F structure will be built like this: + |---trip_point_3_type: active1 + |---cdev0: --->/sys/class/thermal/cooling_device0 + |---cdev0_trip_point: 1 /* cdev0 can be used for passive */ ++ |---cdev0_weight: 1024 + |---cdev1: --->/sys/class/thermal/cooling_device3 + |---cdev1_trip_point: 2 /* cdev1 can be used for active[0]*/ ++ |---cdev1_weight: 1024 + + |cooling_device0: + |---type: Processor +diff --git a/Documentation/trace/coresight.txt b/Documentation/trace/coresight.txt +new file mode 100644 +index 0000000..77d14d5 +--- /dev/null ++++ b/Documentation/trace/coresight.txt +@@ -0,0 +1,299 @@ ++ Coresight - HW Assisted Tracing on ARM ++ ====================================== ++ ++ Author: Mathieu Poirier ++ Date: September 11th, 2014 ++ ++Introduction ++------------ ++ ++Coresight is an umbrella of technologies allowing for the debugging of ARM ++based SoC. It includes solutions for JTAG and HW assisted tracing. This ++document is concerned with the latter. ++ ++HW assisted tracing is becoming increasingly useful when dealing with systems ++that have many SoCs and other components like GPU and DMA engines. ARM has ++developed a HW assisted tracing solution by means of different components, each ++being added to a design at synthesis time to cater to specific tracing needs. ++Compoments are generally categorised as source, link and sinks and are ++(usually) discovered using the AMBA bus. ++ ++"Sources" generate a compressed stream representing the processor instruction ++path based on tracing scenarios as configured by users. From there the stream ++flows through the coresight system (via ATB bus) using links that are connecting ++the emanating source to a sink(s). Sinks serve as endpoints to the coresight ++implementation, either storing the compressed stream in a memory buffer or ++creating an interface to the outside world where data can be transferred to a ++host without fear of filling up the onboard coresight memory buffer. ++ ++At typical coresight system would look like this: ++ ++ ***************************************************************** ++ **************************** AMBA AXI ****************************===|| ++ ***************************************************************** || ++ ^ ^ | || ++ | | * ** ++ 0000000 ::::: 0000000 ::::: ::::: @@@@@@@ |||||||||||| ++ 0 CPU 0<-->: C : 0 CPU 0<-->: C : : C : @ STM @ || System || ++ |->0000000 : T : |->0000000 : T : : T :<--->@@@@@ || Memory || ++ | #######<-->: I : | #######<-->: I : : I : @@@<-| |||||||||||| ++ | # ETM # ::::: | # PTM # ::::: ::::: @ | ++ | ##### ^ ^ | ##### ^ ! ^ ! . | ||||||||| ++ | |->### | ! | |->### | ! | ! . | || DAP || ++ | | # | ! | | # | ! | ! . | ||||||||| ++ | | . | ! | | . | ! | ! . | | | ++ | | . | ! | | . | ! | ! . | | * ++ | | . | ! | | . | ! | ! . | | SWD/ ++ | | . | ! | | . | ! | ! . | | JTAG ++ *****************************************************************<-| ++ *************************** AMBA Debug APB ************************ ++ ***************************************************************** ++ | . ! . ! ! . | ++ | . * . * * . | ++ ***************************************************************** ++ ******************** Cross Trigger Matrix (CTM) ******************* ++ ***************************************************************** ++ | . ^ . . | ++ | * ! * * | ++ ***************************************************************** ++ ****************** AMBA Advanced Trace Bus (ATB) ****************** ++ ***************************************************************** ++ | ! =============== | ++ | * ===== F =====<---------| ++ | ::::::::: ==== U ==== ++ |-->:: CTI ::&& ETB &&<......II I ======= ++ | ! &&&&&&&&& II I . ++ | ! I I . ++ | ! I REP I<.......... ++ | ! I I ++ | !!>&&&&&&&&& II I *Source: ARM ltd. ++ |------>& TPIU &<......II I DAP = Debug Access Port ++ &&&&&&&&& IIIIIII ETM = Embedded Trace Macrocell ++ ; PTM = Program Trace Macrocell ++ ; CTI = Cross Trigger Interface ++ * ETB = Embedded Trace Buffer ++ To trace port TPIU= Trace Port Interface Unit ++ SWD = Serial Wire Debug ++ ++While on target configuration of the components is done via the APB bus, ++all trace data are carried out-of-band on the ATB bus. The CTM provides ++a way to aggregate and distribute signals between CoreSight components. ++ ++The coresight framework provides a central point to represent, configure and ++manage coresight devices on a platform. This first implementation centers on ++the basic tracing functionality, enabling components such ETM/PTM, funnel, ++replicator, TMC, TPIU and ETB. Future work will enable more ++intricate IP blocks such as STM and CTI. ++ ++ ++Acronyms and Classification ++--------------------------- ++ ++Acronyms: ++ ++PTM: Program Trace Macrocell ++ETM: Embedded Trace Macrocell ++STM: System trace Macrocell ++ETB: Embedded Trace Buffer ++ITM: Instrumentation Trace Macrocell ++TPIU: Trace Port Interface Unit ++TMC-ETR: Trace Memory Controller, configured as Embedded Trace Router ++TMC-ETF: Trace Memory Controller, configured as Embedded Trace FIFO ++CTI: Cross Trigger Interface ++ ++Classification: ++ ++Source: ++ ETMv3.x ETMv4, PTMv1.0, PTMv1.1, STM, STM500, ITM ++Link: ++ Funnel, replicator (intelligent or not), TMC-ETR ++Sinks: ++ ETBv1.0, ETB1.1, TPIU, TMC-ETF ++Misc: ++ CTI ++ ++ ++Device Tree Bindings ++---------------------- ++ ++See Documentation/devicetree/bindings/arm/coresight.txt for details. ++ ++As of this writing drivers for ITM, STMs and CTIs are not provided but are ++expected to be added as the solution matures. ++ ++ ++Framework and implementation ++---------------------------- ++ ++The coresight framework provides a central point to represent, configure and ++manage coresight devices on a platform. Any coresight compliant device can ++register with the framework for as long as they use the right APIs: ++ ++struct coresight_device *coresight_register(struct coresight_desc *desc); ++void coresight_unregister(struct coresight_device *csdev); ++ ++The registering function is taking a "struct coresight_device *csdev" and ++register the device with the core framework. The unregister function takes ++a reference to a "strut coresight_device", obtained at registration time. ++ ++If everything goes well during the registration process the new devices will ++show up under /sys/bus/coresight/devices, as showns here for a TC2 platform: ++ ++root:~# ls /sys/bus/coresight/devices/ ++replicator 20030000.tpiu 2201c000.ptm 2203c000.etm 2203e000.etm ++20010000.etb 20040000.funnel 2201d000.ptm 2203d000.etm ++root:~# ++ ++The functions take a "struct coresight_device", which looks like this: ++ ++struct coresight_desc { ++ enum coresight_dev_type type; ++ struct coresight_dev_subtype subtype; ++ const struct coresight_ops *ops; ++ struct coresight_platform_data *pdata; ++ struct device *dev; ++ const struct attribute_group **groups; ++}; ++ ++ ++The "coresight_dev_type" identifies what the device is, i.e, source link or ++sink while the "coresight_dev_subtype" will characterise that type further. ++ ++The "struct coresight_ops" is mandatory and will tell the framework how to ++perform base operations related to the components, each component having ++a different set of requirement. For that "struct coresight_ops_sink", ++"struct coresight_ops_link" and "struct coresight_ops_source" have been ++provided. ++ ++The next field, "struct coresight_platform_data *pdata" is acquired by calling ++"of_get_coresight_platform_data()", as part of the driver's _probe routine and ++"struct device *dev" gets the device reference embedded in the "amba_device": ++ ++static int etm_probe(struct amba_device *adev, const struct amba_id *id) ++{ ++ ... ++ ... ++ drvdata->dev = &adev->dev; ++ ... ++} ++ ++Specific class of device (source, link, or sink) have generic operations ++that can be performed on them (see "struct coresight_ops"). The ++"**groups" is a list of sysfs entries pertaining to operations ++specific to that component only. "Implementation defined" customisations are ++expected to be accessed and controlled using those entries. ++ ++Last but not least, "struct module *owner" is expected to be set to reflect ++the information carried in "THIS_MODULE". ++ ++How to use ++---------- ++ ++Before trace collection can start, a coresight sink needs to be identify. ++There is no limit on the amount of sinks (nor sources) that can be enabled at ++any given moment. As a generic operation, all device pertaining to the sink ++class will have an "active" entry in sysfs: ++ ++root:/sys/bus/coresight/devices# ls ++replicator 20030000.tpiu 2201c000.ptm 2203c000.etm 2203e000.etm ++20010000.etb 20040000.funnel 2201d000.ptm 2203d000.etm ++root:/sys/bus/coresight/devices# ls 20010000.etb ++enable_sink status trigger_cntr ++root:/sys/bus/coresight/devices# echo 1 > 20010000.etb/enable_sink ++root:/sys/bus/coresight/devices# cat 20010000.etb/enable_sink ++1 ++root:/sys/bus/coresight/devices# ++ ++At boot time the current etm3x driver will configure the first address ++comparator with "_stext" and "_etext", essentially tracing any instruction ++that falls within that range. As such "enabling" a source will immediately ++trigger a trace capture: ++ ++root:/sys/bus/coresight/devices# echo 1 > 2201c000.ptm/enable_source ++root:/sys/bus/coresight/devices# cat 2201c000.ptm/enable_source ++1 ++root:/sys/bus/coresight/devices# cat 20010000.etb/status ++Depth: 0x2000 ++Status: 0x1 ++RAM read ptr: 0x0 ++RAM wrt ptr: 0x19d3 <----- The write pointer is moving ++Trigger cnt: 0x0 ++Control: 0x1 ++Flush status: 0x0 ++Flush ctrl: 0x2001 ++root:/sys/bus/coresight/devices# ++ ++Trace collection is stopped the same way: ++ ++root:/sys/bus/coresight/devices# echo 0 > 2201c000.ptm/enable_source ++root:/sys/bus/coresight/devices# ++ ++The content of the ETB buffer can be harvested directly from /dev: ++ ++root:/sys/bus/coresight/devices# dd if=/dev/20010000.etb \ ++of=~/cstrace.bin ++ ++64+0 records in ++64+0 records out ++32768 bytes (33 kB) copied, 0.00125258 s, 26.2 MB/s ++root:/sys/bus/coresight/devices# ++ ++The file cstrace.bin can be decompressed using "ptm2human", DS-5 or Trace32. ++ ++Following is a DS-5 output of an experimental loop that increments a variable up ++to a certain value. The example is simple and yet provides a glimpse of the ++wealth of possibilities that coresight provides. ++ ++Info Tracing enabled ++Instruction 106378866 0x8026B53C E52DE004 false PUSH {lr} ++Instruction 0 0x8026B540 E24DD00C false SUB sp,sp,#0xc ++Instruction 0 0x8026B544 E3A03000 false MOV r3,#0 ++Instruction 0 0x8026B548 E58D3004 false STR r3,[sp,#4] ++Instruction 0 0x8026B54C E59D3004 false LDR r3,[sp,#4] ++Instruction 0 0x8026B550 E3530004 false CMP r3,#4 ++Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1 ++Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4] ++Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c ++Timestamp Timestamp: 17106715833 ++Instruction 319 0x8026B54C E59D3004 false LDR r3,[sp,#4] ++Instruction 0 0x8026B550 E3530004 false CMP r3,#4 ++Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1 ++Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4] ++Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c ++Instruction 9 0x8026B54C E59D3004 false LDR r3,[sp,#4] ++Instruction 0 0x8026B550 E3530004 false CMP r3,#4 ++Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1 ++Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4] ++Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c ++Instruction 7 0x8026B54C E59D3004 false LDR r3,[sp,#4] ++Instruction 0 0x8026B550 E3530004 false CMP r3,#4 ++Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1 ++Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4] ++Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c ++Instruction 7 0x8026B54C E59D3004 false LDR r3,[sp,#4] ++Instruction 0 0x8026B550 E3530004 false CMP r3,#4 ++Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1 ++Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4] ++Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c ++Instruction 10 0x8026B54C E59D3004 false LDR r3,[sp,#4] ++Instruction 0 0x8026B550 E3530004 false CMP r3,#4 ++Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1 ++Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4] ++Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c ++Instruction 6 0x8026B560 EE1D3F30 false MRC p15,#0x0,r3,c13,c0,#1 ++Instruction 0 0x8026B564 E1A0100D false MOV r1,sp ++Instruction 0 0x8026B568 E3C12D7F false BIC r2,r1,#0x1fc0 ++Instruction 0 0x8026B56C E3C2203F false BIC r2,r2,#0x3f ++Instruction 0 0x8026B570 E59D1004 false LDR r1,[sp,#4] ++Instruction 0 0x8026B574 E59F0010 false LDR r0,[pc,#16] ; [0x8026B58C] = 0x80550368 ++Instruction 0 0x8026B578 E592200C false LDR r2,[r2,#0xc] ++Instruction 0 0x8026B57C E59221D0 false LDR r2,[r2,#0x1d0] ++Instruction 0 0x8026B580 EB07A4CF true BL {pc}+0x1e9344 ; 0x804548c4 ++Info Tracing enabled ++Instruction 13570831 0x8026B584 E28DD00C false ADD sp,sp,#0xc ++Instruction 0 0x8026B588 E8BD8000 true LDM sp!,{pc} ++Timestamp Timestamp: 17107041535 +diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt +index 4da4261..0344f76 100644 +--- a/Documentation/trace/ftrace.txt ++++ b/Documentation/trace/ftrace.txt +@@ -2043,6 +2043,35 @@ will produce: + 1) 1.449 us | } + + ++You can disable the hierarchical function call formatting and instead print a ++flat list of function entry and return events. This uses the format described ++in the Output Formatting section and respects all the trace options that ++control that formatting. Hierarchical formatting is the default. ++ ++ hierachical: echo nofuncgraph-flat > trace_options ++ flat: echo funcgraph-flat > trace_options ++ ++ ie: ++ ++ # tracer: function_graph ++ # ++ # entries-in-buffer/entries-written: 68355/68355 #P:2 ++ # ++ # _-----=> irqs-off ++ # / _----=> need-resched ++ # | / _---=> hardirq/softirq ++ # || / _--=> preempt-depth ++ # ||| / delay ++ # TASK-PID CPU# |||| TIMESTAMP FUNCTION ++ # | | | |||| | | ++ sh-1806 [001] d... 198.843443: graph_ent: func=_raw_spin_lock ++ sh-1806 [001] d... 198.843445: graph_ent: func=__raw_spin_lock ++ sh-1806 [001] d..1 198.843447: graph_ret: func=__raw_spin_lock ++ sh-1806 [001] d..1 198.843449: graph_ret: func=_raw_spin_lock ++ sh-1806 [001] d..1 198.843451: graph_ent: func=_raw_spin_unlock_irqrestore ++ sh-1806 [001] d... 198.843453: graph_ret: func=_raw_spin_unlock_irqrestore ++ ++ + You might find other useful features for this tracer in the + following "dynamic ftrace" section such as tracing only specific + functions or tasks. +diff --git a/MAINTAINERS b/MAINTAINERS +index c721042..0c921c8 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -918,6 +918,14 @@ M: Hubert Feurstein + S: Maintained + F: arch/arm/mach-ep93xx/micro9.c + ++ARM/CORESIGHT FRAMEWORK AND DRIVERS ++M: Mathieu Poirier ++L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) ++S: Maintained ++F: drivers/hwtracing/coresight/* ++F: Documentation/trace/coresight.txt ++F: Documentation/devicetree/bindings/arm/coresight.txt ++ + ARM/CORGI MACHINE SUPPORT + M: Richard Purdie + S: Maintained +@@ -9297,6 +9305,7 @@ Q: https://patchwork.kernel.org/project/linux-pm/list/ + S: Supported + F: drivers/thermal/ + F: include/linux/thermal.h ++F: include/uapi/linux/thermal.h + F: include/linux/cpu_cooling.h + F: Documentation/devicetree/bindings/thermal/ + +diff --git a/Makefile b/Makefile +index 3ef5895..56992aa 100644 +--- a/Makefile ++++ b/Makefile +@@ -2,7 +2,7 @@ VERSION = 3 + PATCHLEVEL = 18 + SUBLEVEL = 20 + EXTRAVERSION = +-NAME = Diseased Newt ++NAME = Shuffling Zombie Juror + + # *DOCUMENTATION* + # To see a list of typical targets execute "make help" +diff --git a/android/configs/README b/android/configs/README +new file mode 100644 +index 0000000..8798731 +--- /dev/null ++++ b/android/configs/README +@@ -0,0 +1,15 @@ ++The files in this directory are meant to be used as a base for an Android ++kernel config. All devices should have the options in android-base.cfg enabled. ++While not mandatory, the options in android-recommended.cfg enable advanced ++Android features. ++ ++Assuming you already have a minimalist defconfig for your device, a possible ++way to enable these options would be: ++ ++ ARCH= scripts/kconfig/merge_config.sh /_defconfig android/configs/android-base.cfg android/configs/android-recommended.cfg ++ ++This will generate a .config that can then be used to save a new defconfig or ++compile a new kernel with Android features enabled. ++ ++Because there is no tool to consistently generate these config fragments, ++lets keep them alphabetically sorted instead of random. +diff --git a/android/configs/android-base.cfg b/android/configs/android-base.cfg +new file mode 100644 +index 0000000..154bf16 +--- /dev/null ++++ b/android/configs/android-base.cfg +@@ -0,0 +1,160 @@ ++# KEEP ALPHABETICALLY SORTED ++# CONFIG_DEVKMEM is not set ++# CONFIG_DEVMEM is not set ++# CONFIG_INET_LRO is not set ++# CONFIG_MODULES is not set ++# CONFIG_OABI_COMPAT is not set ++CONFIG_ANDROID=y ++CONFIG_ANDROID_BINDER_IPC=y ++CONFIG_ANDROID_LOW_MEMORY_KILLER=y ++CONFIG_ARMV8_DEPRECATED=y ++CONFIG_ASHMEM=y ++CONFIG_AUDIT=y ++CONFIG_BLK_DEV_DM=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_CGROUPS=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_CGROUP_DEBUG=y ++CONFIG_CGROUP_FREEZER=y ++CONFIG_CGROUP_SCHED=y ++CONFIG_CP15_BARRIER_EMULATION=y ++CONFIG_DM_CRYPT=y ++CONFIG_DM_VERITY=y ++CONFIG_EMBEDDED=y ++CONFIG_FB=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_INET6_AH=y ++CONFIG_INET6_ESP=y ++CONFIG_INET6_IPCOMP=y ++CONFIG_INET=y ++CONFIG_INET_ESP=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_IP6_NF_FILTER=y ++CONFIG_IP6_NF_IPTABLES=y ++CONFIG_IP6_NF_MANGLE=y ++CONFIG_IP6_NF_RAW=y ++CONFIG_IP6_NF_TARGET_REJECT=y ++CONFIG_IP6_NF_TARGET_REJECT_SKERR=y ++CONFIG_IPV6=y ++CONFIG_IPV6_MIP6=y ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_IPV6_OPTIMISTIC_DAD=y ++CONFIG_IPV6_PRIVACY=y ++CONFIG_IPV6_ROUTER_PREF=y ++CONFIG_IPV6_ROUTE_INFO=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_NF_ARPFILTER=y ++CONFIG_IP_NF_ARPTABLES=y ++CONFIG_IP_NF_ARP_MANGLE=y ++CONFIG_IP_NF_FILTER=y ++CONFIG_IP_NF_IPTABLES=y ++CONFIG_IP_NF_MANGLE=y ++CONFIG_IP_NF_MATCH_AH=y ++CONFIG_IP_NF_MATCH_ECN=y ++CONFIG_IP_NF_MATCH_TTL=y ++CONFIG_IP_NF_RAW=y ++CONFIG_IP_NF_SECURITY=y ++CONFIG_IP_NF_TARGET_MASQUERADE=y ++CONFIG_IP_NF_TARGET_NETMAP=y ++CONFIG_IP_NF_TARGET_REDIRECT=y ++CONFIG_IP_NF_TARGET_REJECT=y ++CONFIG_IP_NF_TARGET_REJECT_SKERR=y ++CONFIG_NET=y ++CONFIG_NETDEVICES=y ++CONFIG_NETFILTER=y ++CONFIG_NETFILTER_TPROXY=y ++CONFIG_NETFILTER_XT_MATCH_COMMENT=y ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=y ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y ++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y ++CONFIG_NETFILTER_XT_MATCH_HELPER=y ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=y ++CONFIG_NETFILTER_XT_MATCH_LENGTH=y ++CONFIG_NETFILTER_XT_MATCH_LIMIT=y ++CONFIG_NETFILTER_XT_MATCH_MAC=y ++CONFIG_NETFILTER_XT_MATCH_MARK=y ++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y ++CONFIG_NETFILTER_XT_MATCH_POLICY=y ++CONFIG_NETFILTER_XT_MATCH_QTAGUID=y ++CONFIG_NETFILTER_XT_MATCH_QUOTA2=y ++CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y ++CONFIG_NETFILTER_XT_MATCH_QUOTA=y ++CONFIG_NETFILTER_XT_MATCH_SOCKET=y ++CONFIG_NETFILTER_XT_MATCH_STATE=y ++CONFIG_NETFILTER_XT_MATCH_STATISTIC=y ++CONFIG_NETFILTER_XT_MATCH_STRING=y ++CONFIG_NETFILTER_XT_MATCH_TIME=y ++CONFIG_NETFILTER_XT_MATCH_U32=y ++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y ++CONFIG_NETFILTER_XT_TARGET_CONNMARK=y ++CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y ++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y ++CONFIG_NETFILTER_XT_TARGET_MARK=y ++CONFIG_NETFILTER_XT_TARGET_NFLOG=y ++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y ++CONFIG_NETFILTER_XT_TARGET_SECMARK=y ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=y ++CONFIG_NETFILTER_XT_TARGET_TPROXY=y ++CONFIG_NETFILTER_XT_TARGET_TRACE=y ++CONFIG_NET_CLS_ACT=y ++CONFIG_NET_CLS_U32=y ++CONFIG_NET_EMATCH=y ++CONFIG_NET_EMATCH_U32=y ++CONFIG_NET_KEY=y ++CONFIG_NET_SCHED=y ++CONFIG_NET_SCH_HTB=y ++CONFIG_NF_CONNTRACK=y ++CONFIG_NF_CONNTRACK_AMANDA=y ++CONFIG_NF_CONNTRACK_EVENTS=y ++CONFIG_NF_CONNTRACK_FTP=y ++CONFIG_NF_CONNTRACK_H323=y ++CONFIG_NF_CONNTRACK_IPV4=y ++CONFIG_NF_CONNTRACK_IPV6=y ++CONFIG_NF_CONNTRACK_IRC=y ++CONFIG_NF_CONNTRACK_NETBIOS_NS=y ++CONFIG_NF_CONNTRACK_PPTP=y ++CONFIG_NF_CONNTRACK_SANE=y ++CONFIG_NF_CONNTRACK_SECMARK=y ++CONFIG_NF_CONNTRACK_TFTP=y ++CONFIG_NF_CT_NETLINK=y ++CONFIG_NF_CT_PROTO_DCCP=y ++CONFIG_NF_CT_PROTO_SCTP=y ++CONFIG_NF_CT_PROTO_UDPLITE=y ++CONFIG_NF_NAT=y ++CONFIG_NO_HZ=y ++CONFIG_PACKET=y ++CONFIG_PM_AUTOSLEEP=y ++CONFIG_PM_WAKELOCKS=y ++CONFIG_PPP=y ++CONFIG_PPPOLAC=y ++CONFIG_PPPOPNS=y ++CONFIG_PPP_BSDCOMP=y ++CONFIG_PPP_DEFLATE=y ++CONFIG_PPP_MPPE=y ++CONFIG_PREEMPT=y ++CONFIG_RESOURCE_COUNTERS=y ++CONFIG_RTC_CLASS=y ++CONFIG_RT_GROUP_SCHED=y ++CONFIG_SECURITY=y ++CONFIG_SECURITY_NETWORK=y ++CONFIG_SECURITY_SELINUX=y ++CONFIG_SETEND_EMULATION=y ++CONFIG_STAGING=y ++CONFIG_SWITCH=y ++CONFIG_SWP_EMULATION=y ++CONFIG_SYNC=y ++CONFIG_SYSVIPC=y ++CONFIG_TUN=y ++CONFIG_UNIX=y ++CONFIG_USB_GADGET=y ++CONFIG_USB_CONFIGFS=y ++CONFIG_USB_CONFIGFS_F_FS=y ++CONFIG_USB_CONFIGFS_F_MTP=y ++CONFIG_USB_CONFIGFS_F_PTP=y ++CONFIG_USB_CONFIGFS_F_ACC=y ++CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y ++CONFIG_USB_CONFIGFS_UEVENT=y ++CONFIG_USB_OTG_WAKELOCK=y ++CONFIG_XFRM_USER=y +diff --git a/android/configs/android-recommended.cfg b/android/configs/android-recommended.cfg +new file mode 100644 +index 0000000..960b9de +--- /dev/null ++++ b/android/configs/android-recommended.cfg +@@ -0,0 +1,121 @@ ++# KEEP ALPHABETICALLY SORTED ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++# CONFIG_INPUT_MOUSE is not set ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_NF_CONNTRACK_SIP is not set ++# CONFIG_PM_WAKELOCKS_GC is not set ++# CONFIG_VT is not set ++CONFIG_ANDROID_TIMED_GPIO=y ++CONFIG_BACKLIGHT_LCD_SUPPORT=y ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_SIZE=8192 ++CONFIG_COMPACTION=y ++CONFIG_DM_UEVENT=y ++CONFIG_DRAGONRISE_FF=y ++CONFIG_ENABLE_DEFAULT_TRACERS=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_SECURITY=y ++CONFIG_FUSE_FS=y ++CONFIG_GREENASIA_FF=y ++CONFIG_HIDRAW=y ++CONFIG_HID_A4TECH=y ++CONFIG_HID_ACRUX=y ++CONFIG_HID_ACRUX_FF=y ++CONFIG_HID_APPLE=y ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++CONFIG_HID_CYPRESS=y ++CONFIG_HID_DRAGONRISE=y ++CONFIG_HID_ELECOM=y ++CONFIG_HID_EMS_FF=y ++CONFIG_HID_EZKEY=y ++CONFIG_HID_GREENASIA=y ++CONFIG_HID_GYRATION=y ++CONFIG_HID_HOLTEK=y ++CONFIG_HID_KENSINGTON=y ++CONFIG_HID_KEYTOUCH=y ++CONFIG_HID_KYE=y ++CONFIG_HID_LCPOWER=y ++CONFIG_HID_LOGITECH=y ++CONFIG_HID_LOGITECH_DJ=y ++CONFIG_HID_MAGICMOUSE=y ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++CONFIG_HID_MULTITOUCH=y ++CONFIG_HID_NTRIG=y ++CONFIG_HID_ORTEK=y ++CONFIG_HID_PANTHERLORD=y ++CONFIG_HID_PETALYNX=y ++CONFIG_HID_PICOLCD=y ++CONFIG_HID_PRIMAX=y ++CONFIG_HID_PRODIKEYS=y ++CONFIG_HID_ROCCAT=y ++CONFIG_HID_SAITEK=y ++CONFIG_HID_SAMSUNG=y ++CONFIG_HID_SMARTJOYPLUS=y ++CONFIG_HID_SONY=y ++CONFIG_HID_SPEEDLINK=y ++CONFIG_HID_SUNPLUS=y ++CONFIG_HID_THRUSTMASTER=y ++CONFIG_HID_TIVO=y ++CONFIG_HID_TOPSEED=y ++CONFIG_HID_TWINHAN=y ++CONFIG_HID_UCLOGIC=y ++CONFIG_HID_WACOM=y ++CONFIG_HID_WALTOP=y ++CONFIG_HID_WIIMOTE=y ++CONFIG_HID_ZEROPLUS=y ++CONFIG_HID_ZYDACRON=y ++CONFIG_INPUT_EVDEV=y ++CONFIG_INPUT_GPIO=y ++CONFIG_INPUT_JOYSTICK=y ++CONFIG_INPUT_KEYCHORD=y ++CONFIG_INPUT_KEYRESET=y ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_TABLET=y ++CONFIG_INPUT_UINPUT=y ++CONFIG_ION=y ++CONFIG_JOYSTICK_XPAD=y ++CONFIG_JOYSTICK_XPAD_FF=y ++CONFIG_JOYSTICK_XPAD_LEDS=y ++CONFIG_KALLSYMS_ALL=y ++CONFIG_KSM=y ++CONFIG_LOGIG940_FF=y ++CONFIG_LOGIRUMBLEPAD2_FF=y ++CONFIG_LOGITECH_FF=y ++CONFIG_MD=y ++CONFIG_MEDIA_SUPPORT=y ++CONFIG_MSDOS_FS=y ++CONFIG_PANIC_TIMEOUT=5 ++CONFIG_PANTHERLORD_FF=y ++CONFIG_PERF_EVENTS=y ++CONFIG_PM_DEBUG=y ++CONFIG_PM_RUNTIME=y ++CONFIG_PM_WAKELOCKS_LIMIT=0 ++CONFIG_POWER_SUPPLY=y ++CONFIG_PSTORE=y ++CONFIG_PSTORE_CONSOLE=y ++CONFIG_PSTORE_RAM=y ++CONFIG_SCHEDSTATS=y ++CONFIG_SMARTJOYPLUS_FF=y ++CONFIG_SND=y ++CONFIG_SOUND=y ++CONFIG_SUSPEND_TIME=y ++CONFIG_TABLET_USB_ACECAD=y ++CONFIG_TABLET_USB_AIPTEK=y ++CONFIG_TABLET_USB_GTCO=y ++CONFIG_TABLET_USB_HANWANG=y ++CONFIG_TABLET_USB_KBTAB=y ++CONFIG_TABLET_USB_WACOM=y ++CONFIG_TIMER_STATS=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++CONFIG_UHID=y ++CONFIG_UID_STAT=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_HIDDEV=y ++CONFIG_USB_USBNET=y ++CONFIG_VFAT_FS=y +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 89c4b5c..20c9e39 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -311,7 +311,7 @@ config ARCH_MULTIPLATFORM + select ARCH_WANT_OPTIONAL_GPIOLIB + select ARM_HAS_SG_CHAIN + select ARM_PATCH_PHYS_VIRT +- select AUTO_ZRELADDR ++ #select AUTO_ZRELADDR + select CLKSRC_OF + select COMMON_CLK + select GENERIC_CLOCKEVENTS +@@ -1311,6 +1311,7 @@ source "drivers/pci/Kconfig" + source "drivers/pci/pcie/Kconfig" + + source "drivers/pcmcia/Kconfig" ++source "drivers/pci/hipcie/Kconfig" + + endmenu + +@@ -1385,6 +1386,107 @@ config SCHED_SMT + MultiThreading at a cost of slightly increased overhead in some + places. If unsure say N here. + ++config DISABLE_CPU_SCHED_DOMAIN_BALANCE ++ bool "(EXPERIMENTAL) Disable CPU level scheduler load-balancing" ++ help ++ Disables scheduler load-balancing at CPU sched domain level. ++ ++config SCHED_HMP ++ bool "(EXPERIMENTAL) Heterogenous multiprocessor scheduling" ++ depends on DISABLE_CPU_SCHED_DOMAIN_BALANCE && SCHED_MC && FAIR_GROUP_SCHED && !SCHED_AUTOGROUP ++ help ++ Experimental scheduler optimizations for heterogeneous platforms. ++ Attempts to introspectively select task affinity to optimize power ++ and performance. Basic support for multiple (>2) cpu types is in place, ++ but it has only been tested with two types of cpus. ++ There is currently no support for migration of task groups, hence ++ !SCHED_AUTOGROUP. Furthermore, normal load-balancing must be disabled ++ between cpus of different type (DISABLE_CPU_SCHED_DOMAIN_BALANCE). ++ When turned on, this option adds sys/kernel/hmp directory which ++ contains the following files: ++ up_threshold - the load average threshold used for up migration ++ (0 - 1023) ++ down_threshold - the load average threshold used for down migration ++ (0 - 1023) ++ hmp_domains - a list of cpumasks for the present HMP domains, ++ starting with the 'biggest' and ending with the ++ 'smallest'. ++ Note that both the threshold files can be written at runtime to ++ control scheduler behaviour. ++ ++config SCHED_HMP_PRIO_FILTER ++ bool "(EXPERIMENTAL) Filter HMP migrations by task priority" ++ depends on SCHED_HMP ++ help ++ Enables task priority based HMP migration filter. Any task with ++ a NICE value above the threshold will always be on low-power cpus ++ with less compute capacity. ++ ++config SCHED_HMP_PRIO_FILTER_VAL ++ int "NICE priority threshold" ++ default 5 ++ depends on SCHED_HMP_PRIO_FILTER ++ ++config HMP_FAST_CPU_MASK ++ string "HMP scheduler fast CPU mask" ++ depends on SCHED_HMP ++ help ++ Specify the cpuids of the fast CPUs in the system as a list string, ++ e.g. cpuid 0+1 should be specified as 0-1. ++ ++config HMP_SLOW_CPU_MASK ++ string "HMP scheduler slow CPU mask" ++ depends on SCHED_HMP ++ help ++ Specify the cpuids of the slow CPUs in the system as a list string, ++ e.g. cpuid 0+1 should be specified as 0-1. ++ ++config HMP_VARIABLE_SCALE ++ bool "Allows changing the load tracking scale through sysfs" ++ depends on SCHED_HMP ++ help ++ When turned on, this option exports the load average period value ++ for the load tracking patches through sysfs. ++ The values can be modified to change the rate of load accumulation ++ used for HMP migration. 'load_avg_period_ms' is the time in ms to ++ reach a load average of 0.5 for an idle task of 0 load average ++ ratio which becomes 100% busy. ++ For example, with load_avg_period_ms = 128 and up_threshold = 512, ++ a running task with a load of 0 will be migrated to a bigger CPU after ++ 128ms, because after 128ms its load_avg_ratio is 0.5 and the real ++ up_threshold is 0.5. ++ This patch has the same behavior as changing the Y of the load ++ average computation to ++ (1002/1024)^(LOAD_AVG_PERIOD/load_avg_period_ms) ++ but removes intermediate overflows in computation. ++ ++config HMP_FREQUENCY_INVARIANT_SCALE ++ bool "(EXPERIMENTAL) Frequency-Invariant Tracked Load for HMP" ++ depends on SCHED_HMP && CPU_FREQ ++ help ++ Scales the current load contribution in line with the frequency ++ of the CPU that the task was executed on. ++ In this version, we use a simple linear scale derived from the ++ maximum frequency reported by CPUFreq. ++ Restricting tracked load to be scaled by the CPU's frequency ++ represents the consumption of possible compute capacity ++ (rather than consumption of actual instantaneous capacity as ++ normal) and allows the HMP migration's simple threshold ++ migration strategy to interact more predictably with CPUFreq's ++ asynchronous compute capacity changes. ++ ++config SCHED_HMP_LITTLE_PACKING ++ bool "Small task packing for HMP" ++ depends on SCHED_HMP ++ default n ++ help ++ Allows the HMP Scheduler to pack small tasks into CPUs in the ++ smallest HMP domain. ++ Controlled by two sysfs files in sys/kernel/hmp. ++ packing_enable: 1 to enable, 0 to disable packing. Default 1. ++ packing_limit: runqueue load ratio where a RQ is considered ++ to be full. Default is NICE_0_LOAD * 9/8. ++ + config HAVE_ARM_SCU + bool + help +@@ -1790,6 +1892,15 @@ config XEN + help + Say Y if you want to run Linux in a Virtual Machine on Xen on ARM. + ++config ARM_FLUSH_CONSOLE_ON_RESTART ++ bool "Force flush the console on restart" ++ help ++ If the console is locked while the system is rebooted, the messages ++ in the temporary logbuffer would not have propogated to all the ++ console drivers. This option forces the console lock to be ++ released if it failed to be acquired, which will cause all the ++ pending messages to be flushed. ++ + endmenu + + menu "Boot options" +@@ -1820,6 +1931,21 @@ config DEPRECATED_PARAM_STRUCT + This was deprecated in 2001 and announced to live on for 5 years. + Some old boot loaders still use this way. + ++config BUILD_ARM_APPENDED_DTB_IMAGE ++ bool "Build a concatenated zImage/dtb by default" ++ depends on OF ++ help ++ Enabling this option will cause a concatenated zImage and list of ++ DTBs to be built by default (instead of a standalone zImage.) ++ The image will built in arch/arm/boot/zImage-dtb ++ ++config BUILD_ARM_APPENDED_DTB_IMAGE_NAMES ++ string "Default dtb names" ++ depends on BUILD_ARM_APPENDED_DTB_IMAGE ++ help ++ Space separated list of names of dtbs to append when ++ building a concatenated zImage-dtb. ++ + # Compressed boot loader in ROM. Yes, we really want to ask about + # TEXT and BSS so we preserve their values in the config files. + config ZBOOT_ROM_TEXT +diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug +index d8f6a2e..74debb3 100644 +--- a/arch/arm/Kconfig.debug ++++ b/arch/arm/Kconfig.debug +@@ -232,6 +232,77 @@ choice + Say Y here if you want kernel low-level debugging support + on HI3716 UART. + ++ config DEBUG_HI3516CV300_UART ++ bool "Hisilicon Hi3516cv300 Debug UART" ++ depends on ARCH_HI3516CV300 ++ select DEBUG_UART_PL01X ++ help ++ Say Y here if you want kernel low-level debugging support ++ on HI3516CV300 UART. ++ ++ config DEBUG_HI3519_UART ++ bool "Hisilicon Hi3519 Debug UART" ++ depends on ARCH_HI3519 ++ select DEBUG_UART_PL01X ++ help ++ Say Y here if you want kernel low-level debugging support ++ on HI3519 UART. ++ ++ config DEBUG_HI3519V101_UART ++ bool "Hisilicon Hi3519V101 Debug UART" ++ depends on ARCH_HI3519V101 ++ select DEBUG_UART_PL01X ++ help ++ Say Y here if you want kernel low-level debugging support ++ on HI3519V101 UART. ++ ++ config DEBUG_HI3559_UART ++ bool "Hisilicon Hi3559 Debug UART" ++ depends on ARCH_HI3559 ++ select DEBUG_UART_PL01X ++ help ++ Say Y here if you want kernel low-level debugging support ++ on HI3559 UART. ++ ++ config DEBUG_HI3516AV200_UART ++ bool "Hisilicon Hi3516AV200 Debug UART" ++ depends on ARCH_HI3516AV200 ++ select DEBUG_UART_PL01X ++ help ++ Say Y here if you want kernel low-level debugging support ++ on HI3516AV200 UART. ++ ++ config DEBUG_HI3556_UART ++ bool "Hisilicon Hi3556 Debug UART" ++ depends on ARCH_HI3556 ++ select DEBUG_UART_PL01X ++ help ++ Say Y here if you want kernel low-level debugging support ++ on HI3556 UART. ++ config DEBUG_HI3536C_UART ++ bool "Hisilicon Hi3536C Debug UART" ++ depends on ARCH_HI3536C ++ select DEBUG_UART_PL01X ++ help ++ Say Y here if you want kernel low-level debugging support ++ on HI3536C UART. ++ ++ config DEBUG_HI3531D_UART ++ bool "Hisilicon Hi3531D Debug UART" ++ depends on ARCH_HI3531D ++ select DEBUG_UART_PL01X ++ help ++ Say Y here if you want kernel low-level debugging support ++ on HI3531D UART. ++ ++ config DEBUG_HI3521D_UART ++ bool "Hisilicon Hi3521D Debug UART" ++ depends on ARCH_HI3521D ++ select DEBUG_UART_PL01X ++ help ++ Say Y here if you want kernel low-level debugging support ++ on HI3521D UART. ++ + config DEBUG_HIGHBANK_UART + bool "Kernel low-level debugging messages via Highbank UART" + depends on ARCH_HIGHBANK +@@ -1160,6 +1231,15 @@ config DEBUG_UART_PHYS + default 0xf8b00000 if DEBUG_HIX5HD2_UART + default 0xf991e000 if DEBUG_QCOM_UARTDM + default 0xfcb00000 if DEBUG_HI3620_UART ++ default 0x12100000 if DEBUG_HI3516CV300_UART ++ default 0x12100000 if DEBUG_HI3519_UART ++ default 0x12100000 if DEBUG_HI3519V101_UART ++ default 0x12100000 if DEBUG_HI3516AV200_UART ++ default 0x12100000 if DEBUG_HI3559_UART ++ default 0x12100000 if DEBUG_HI3556_UART ++ default 0x12080000 if DEBUG_HI3536C_UART ++ default 0x12080000 if DEBUG_HI3531D_UART ++ default 0x12080000 if DEBUG_HI3521D_UART + default 0xfe800000 if ARCH_IOP32X + default 0xff690000 if DEBUG_RK32_UART2 + default 0xffc02000 if DEBUG_SOCFPGA_UART +@@ -1218,6 +1298,15 @@ config DEBUG_UART_VIRT + default 0xfe300000 if DEBUG_BCM_KONA_UART + default 0xfe800000 if ARCH_IOP32X + default 0xfeb00000 if DEBUG_HI3620_UART || DEBUG_HIX5HD2_UART ++ default 0xfef00000 if DEBUG_HI3516CV300_UART ++ default 0xfef00000 if DEBUG_HI3519_UART ++ default 0xfef00000 if DEBUG_HI3519V101_UART ++ default 0xfef00000 if DEBUG_HI3516AV200_UART ++ default 0xfef00000 if DEBUG_HI3559_UART ++ default 0xfef00000 if DEBUG_HI3556_UART ++ default 0xfe480000 if DEBUG_HI3536C_UART ++ default 0xfe880000 if DEBUG_HI3531D_UART ++ default 0xfe480000 if DEBUG_HI3521D_UART + default 0xfeb24000 if DEBUG_RK3X_UART0 + default 0xfeb26000 if DEBUG_RK3X_UART1 + default 0xfeb30c00 if DEBUG_KEYSTONE_UART0 +@@ -1299,7 +1388,7 @@ config EARLY_PRINTK + + config OC_ETM + bool "On-chip ETM and ETB" +- depends on ARM_AMBA ++ depends on ARM_AMBA && !CORESIGHT + help + Enables the on-chip embedded trace macrocell and embedded trace + buffer driver that will allow you to collect traces of the +@@ -1331,4 +1420,6 @@ config DEBUG_SET_MODULE_RONX + against certain classes of kernel exploits. + If in doubt, say "N". + ++source "drivers/hwtracing/coresight/Kconfig" ++ + endmenu +diff --git a/arch/arm/Makefile b/arch/arm/Makefile +index 034a949..d2b2bfb 100644 +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -50,6 +50,14 @@ AS += -EL + LD += -EL + endif + ++# ++# The Scalar Replacement of Aggregates (SRA) optimization pass in GCC 4.9 and ++# later may result in code being generated that handles signed short and signed ++# char struct members incorrectly. So disable it. ++# (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65932) ++# ++KBUILD_CFLAGS += $(call cc-option,-fno-ipa-sra) ++ + # This selects which instruction set is used. + # Note that GCC does not numerically define an architecture version + # macro, but instead defines a whole series of macros which makes +@@ -278,6 +286,8 @@ libs-y := arch/arm/lib/ $(libs-y) + # Default target when executing plain make + ifeq ($(CONFIG_XIP_KERNEL),y) + KBUILD_IMAGE := xipImage ++else ifeq ($(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE),y) ++KBUILD_IMAGE := zImage-dtb + else + KBUILD_IMAGE := zImage + endif +@@ -312,8 +322,15 @@ $(INSTALL_TARGETS): + $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@ + + PHONY += dtbs dtbs_install +-dtbs dtbs_install: prepare scripts +- $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $@ ++ ++dtbs: prepare scripts ++ $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) ++ ++dtbs_install: ++ $(Q)$(MAKE) $(dtbinst)=$(boot)/dts MACHINE=$(MACHINE) ++ ++zImage-dtb: vmlinux scripts dtbs ++ $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ + + # We use MRPROPER_FILES and CLEAN_FILES now + archclean: +diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore +index 3c79f85..ad7a025 100644 +--- a/arch/arm/boot/.gitignore ++++ b/arch/arm/boot/.gitignore +@@ -4,3 +4,4 @@ xipImage + bootpImage + uImage + *.dtb ++zImage-dtb +\ No newline at end of file +diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile +index ec2f806..afe52d3 100644 +--- a/arch/arm/boot/Makefile ++++ b/arch/arm/boot/Makefile +@@ -14,6 +14,8 @@ + ifneq ($(MACHINE),) + include $(srctree)/$(MACHINE)/Makefile.boot + endif ++include $(srctree)/arch/arm/mach-hisi/Makefile.boot ++include $(srctree)/arch/arm/boot/dts/Makefile + + # Note: the following conditions must always be true: + # ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET) +@@ -25,7 +27,15 @@ INITRD_PHYS := $(initrd_phys-y) + + export ZRELADDR INITRD_PHYS PARAMS_PHYS + +-targets := Image zImage xipImage bootpImage uImage ++targets := Image zImage xipImage bootpImage uImage zImage-dtb ++ ++DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES)) ++ifneq ($(DTB_NAMES),) ++DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES)) ++else ++DTB_LIST := $(dtb-y) ++endif ++DTB_OBJS := $(addprefix $(obj)/dts/,$(DTB_LIST)) + + ifeq ($(CONFIG_XIP_KERNEL),y) + +@@ -55,6 +65,10 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE + $(call if_changed,objcopy) + @$(kecho) ' Kernel: $@ is ready' + ++$(obj)/zImage-dtb: $(obj)/zImage $(DTB_OBJS) FORCE ++ $(call if_changed,cat) ++ @echo ' Kernel: $@ is ready' ++ + endif + + ifneq ($(LOADADDR),) +@@ -75,7 +89,7 @@ if [ $(words $(UIMAGE_LOADADDR)) -ne 1 ]; then \ + false; \ + fi + +-$(obj)/uImage: $(obj)/zImage FORCE ++$(obj)/uImage: $(obj)/zImage-dtb FORCE + @$(check_for_multiple_loadaddr) + $(call if_changed,uimage) + @$(kecho) ' Image $@ is ready' +diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile +index 3ea230a..57bae7b 100644 +--- a/arch/arm/boot/compressed/Makefile ++++ b/arch/arm/boot/compressed/Makefile +@@ -23,7 +23,11 @@ endif + + AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET) + HEAD = head.o ++ifeq ($(CONFIG_HW_DECOMPRESS),y) ++OBJS += misc.o hw_decompress.o ++else + OBJS += misc.o decompress.o ++endif + ifeq ($(CONFIG_DEBUG_UNCOMPRESS),y) + OBJS += debug.o + endif +diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S +index 68be901..aaf54a8 100644 +--- a/arch/arm/boot/compressed/head.S ++++ b/arch/arm/boot/compressed/head.S +@@ -176,6 +176,16 @@ not_angel: + ldr r4, =zreladdr + #endif + ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101\ ++ || defined CONFIG_ARCH_HI3559 || defined CONFIG_ARCH_HI3556 || defined CONFIG_ARCH_HI3516AV200) ++ /* ++ * set SMP bit ACTLR register to enable I cache and D cache ++ */ ++ mrc p15, 0, r0, c1, c0, 1 ++ orr r0, #(1 << 6) ++ mcr p15, 0, r0, c1, c0, 1 ++#endif ++ + /* + * Set up a page table only if it won't overwrite ourself. + * That means r4 < pc && r4 - 16k page directory > &_end. +@@ -730,6 +740,8 @@ __armv7_mmu_cache_on: + bic r6, r6, #1 << 31 @ 32-bit translation system + bic r6, r6, #3 << 0 @ use only ttbr0 + mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer ++ mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs ++ mcr p15, 0, r0, c7, c5, 4 @ ISB + mcrne p15, 0, r1, c3, c0, 0 @ load domain access control + mcrne p15, 0, r6, c2, c0, 2 @ load ttb control + #endif +diff --git a/arch/arm/boot/compressed/hw_decompress.c b/arch/arm/boot/compressed/hw_decompress.c +new file mode 100644 +index 0000000..20cd896 +--- /dev/null ++++ b/arch/arm/boot/compressed/hw_decompress.c +@@ -0,0 +1,266 @@ ++#include"hw_decompress.h" ++#if defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) ++#include"hw_decompress_hi3559.h" ++#endif ++ ++static inline void udelay(unsigned long loops) ++{ ++ __asm__ volatile ("1:\n" ++ "subs %0, %1, #1\n" ++ "bne 1b" : "=r" (loops) : "0" (loops)); ++} ++ ++unsigned int hw_dec_type = 0; ++unsigned int hw_dec_sop = 0; ++unsigned int hw_dec_eop = 0; ++unsigned int hw_dec_cur_blk = 0; ++unsigned int hw_blk_total_num = 0; ++ ++void hw_dec_sop_eop_first_set(int block_num) ++{ ++ if (block_num == 1) { ++ hw_dec_sop = 1; ++ hw_dec_eop = 1; ++ } else { ++ hw_dec_sop = 1; ++ hw_dec_eop = 0; ++ } ++ ++ hw_dec_type = 0; ++ hw_dec_cur_blk = 0; ++ hw_blk_total_num = block_num; ++} ++ ++static inline void hw_dec_work_en_set(unsigned int work_en_flg) ++{ ++ /* Enable the emar*/ ++ writel(work_en_flg, (void *)(HW_DEC_REG_BASE_ADDR + EAMR_WORK_EN_REG_OFST)); ++} ++ ++static inline void hw_dec_rtn_baddr_set(unsigned int addr) ++{ ++ writel(addr, (void *)(HW_DEC_REG_BASE_ADDR + DPRS_DATA_RTN_BADDR)); ++} ++ ++static inline void hw_dec_dprs_data_baddr_set(unsigned int addr) ++{ ++ writel(addr, (void *)(HW_DEC_REG_BASE_ADDR + DPRS_DATA_INFO_BADDR)); ++} ++ ++static inline void hw_dec_data_rtn_len_set(unsigned int len) ++{ ++ writel(len, (void *)(HW_DEC_REG_BASE_ADDR + DPRS_DATA_RTN_LEN)); ++} ++ ++static inline void hw_dec_dprs_data_len_set(unsigned int len) ++{ ++ writel(len, (void *)(HW_DEC_REG_BASE_ADDR + DPRS_DATA_INFO_LEN)); ++} ++ ++static inline void hw_dec_crc_check_en(unsigned int crc_en) ++{ ++ writel(crc_en, (void *)(HW_DEC_REG_BASE_ADDR + CRC_CHECK_EN)); ++} ++ ++static inline void hw_dec_data_crc32_set(unsigned int crc32) ++{ ++ writel(crc32, (void *)(HW_DEC_REG_BASE_ADDR + DPRS_DATA_CRC32)); ++} ++ ++static inline unsigned int hw_dec_buf_status_get(void) ++{ ++ return readl((void *)(HW_DEC_REG_BASE_ADDR + BUF_INFO)); ++} ++ ++static inline unsigned int hw_dec_dprs_rtn_status_get(void) ++{ ++ return readl((void *)(HW_DEC_REG_BASE_ADDR + DPRS_RTN_INFO)); ++} ++ ++static inline void hw_dec_buf_status_clr(void) ++{ ++ writel(0x1, (void *)(HW_DEC_REG_BASE_ADDR + BUF_INFO_CLR)); ++} ++ ++static inline void hw_dec_dprs_rtn_status_clr(void) ++{ ++ writel(0x1, (void *)(HW_DEC_REG_BASE_ADDR + RLT_INFO_CLR)); ++} ++ ++static inline void hw_dec_intr_en_set(int blk_intr_en, int task_intr_en) ++{ ++ U_INTR_EN intr_en; ++ intr_en.bits.task_intrpt_en = task_intr_en; ++ intr_en.bits.block_intrpt_en = blk_intr_en; ++ writel(intr_en.u32, (void *)(HW_DEC_REG_BASE_ADDR + INT_EN_REG_ADDR)); ++} ++ ++static inline unsigned int hw_dec_intr_status_get(void) ++{ ++ return readl((void *)(HW_DEC_REG_BASE_ADDR + INT_STATUS_REG_ADDR)); ++} ++ ++static inline void hw_dec_block_intr_status_clr(void) ++{ ++ U_INTR_CLR intr_clr; ++ ++ intr_clr.u32 = readl((void *)(HW_DEC_REG_BASE_ADDR + INT_CLEAR_REG_ADDR)); ++ intr_clr.bits.block_intrpt_clr = 0x1; ++ writel(intr_clr.u32, (void *)(HW_DEC_REG_BASE_ADDR + INT_CLEAR_REG_ADDR)); ++} ++ ++static inline void hw_dec_task_intr_status_clr(void) ++{ ++ U_INTR_CLR intr_clr; ++ ++ intr_clr.u32 = readl((void *)(HW_DEC_REG_BASE_ADDR + INT_CLEAR_REG_ADDR)); ++ intr_clr.bits.task_intrpt_clr = 0x1; ++ writel(intr_clr.u32, (void *)(HW_DEC_REG_BASE_ADDR + INT_CLEAR_REG_ADDR)); ++} ++ ++int hw_dec_intr_proc(int irq, void *para) ++{ ++ U_BUF_STATUS buf_status; ++ U_INTR_STATUS intr_status; ++ U_DPRS_RTN_STATUS dprs_status; ++ ++ intr_status.u32 = hw_dec_intr_status_get(); ++ if (intr_status.bits.block_intrpt) { ++ buf_status.u32 = hw_dec_buf_status_get(); ++ if (buf_status.bits.aval_flg) ++ hw_dec_buf_status_clr(); ++ ++ hw_dec_block_intr_status_clr(); ++ } ++ ++ if (intr_status.bits.task_intrpt) { ++ dprs_status.u32 = hw_dec_dprs_rtn_status_get(); ++ if (dprs_status.bits.aval_flg) { ++ if (dprs_status.bits.err_info) { ++ // printk("err = 0x%x, dec_data_len = 0x%x\n", ++ // dprs_status.bits.err_info, ++ // readl(HW_DEC_REG_BASE_ADDR ++ // + DPRS_RTN_LEN)); ++ } ++ hw_dec_dprs_rtn_status_clr(); ++ } ++ ++ hw_dec_task_intr_status_clr(); ++ return 0; ++ } ++ ++ return -1; ++} ++ ++void hw_dec_start(unsigned int src_baddr, ++ unsigned int dst_baddr, ++ unsigned int src_len, ++ unsigned int dst_len, ++ unsigned int crc_en, ++ unsigned int crc32, ++ unsigned int dec_type) ++{ ++ unsigned int val; ++ ++ if (hw_dec_sop) { ++ if (!dec_type) { ++ /* set the parameters of output buffer */ ++ hw_dec_rtn_baddr_set(dst_baddr); ++ hw_dec_data_rtn_len_set(dst_len); ++ } else { ++ /* set the parameter of output buffer */ ++ hw_dec_dprs_data_baddr_set(dst_baddr); ++ hw_dec_dprs_data_len_set(PAGE_NR(dst_len) * 4); ++ } ++ } ++ ++ /* set the parameter of input buffer */ ++ writel(src_baddr, (void *)(HW_DEC_REG_BASE_ADDR + DPRS_DATA_SRC_BADDR)); ++ ++ val = src_len | (hw_dec_sop << 28) ++ | (hw_dec_eop << 29) | (!dec_type << 31); ++ writel(val, (void *)(HW_DEC_REG_BASE_ADDR + DPRS_DATA_SRC_LEN)); ++ ++ hw_dec_crc_check_en(crc_en); ++} ++ ++int hw_dec_wait_finish(void) ++{ ++ int ret; ++ int times = 0; ++ ++ do { ++ ret = hw_dec_intr_proc(HW_DEC_INTR, NULL); ++ times++; ++ if (times > 100000) { ++ // printk("hardware decompress overtime!" ++ // " func:%s, line:%d\n", ++ // __func__, __LINE__); ++ times = 0; ++ break; ++ } ++ ++ udelay(1000); ++ } while (-1 == ret); ++ ++ return ret; ++} ++ ++void hw_gzip_init(void) ++{ ++ enable_decompress_clock(); ++ /* Init the emar interface */ ++ writel(0, (void *)(HW_DEC_REG_BASE_ADDR + EAMR_RID_REG_OFST)); ++ writel(0x3, (void *)(HW_DEC_REG_BASE_ADDR + EAMR_ROSD_REG_OFST)); ++ writel(0, (void *)(HW_DEC_REG_BASE_ADDR + EAMR_WID_REG_OFST)); ++ writel(0x3, (void *)(HW_DEC_REG_BASE_ADDR + EAMR_WOSD_REG_OFST)); ++ ++ /*Enable interrupt*/ ++ hw_dec_intr_en_set(0x1, 0x1); ++ ++ /* Enable emar*/ ++ hw_dec_work_en_set(0x1); ++} ++ ++int hw_gzip_dec(unsigned int dst, int *dstlen, unsigned int src, int srclen) ++{ ++ int ret; ++ ++ hw_dec_sop_eop_first_set(1); ++ ++ hw_dec_start(src, dst, srclen, *dstlen, 0, 0, hw_dec_type); ++ ++ ret = hw_dec_wait_finish(); ++ if (ret) ++ return -1; ++ ++ //*dstlen = readl(HW_DEC_REG_BASE_ADDR + DPRS_RTN_LEN); ++ ++ return 0; ++} ++ ++void hw_gzip_exit(void) ++{ ++ /*Disable emar*/ ++ hw_dec_work_en_set(0x0); ++ ++ /*Disable interrupt*/ ++ hw_dec_intr_en_set(0x0, 0x0); ++ disable_decompress_clock(); ++} ++ ++ ++int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)) ++{ ++ unsigned int src_pa = (unsigned long)input; ++ unsigned int dst_pa = (unsigned long)output; ++ int dstlen = 0x800000; ++ ++ hw_gzip_init(); ++ ++ hw_gzip_dec(dst_pa, &dstlen, src_pa, len); ++ ++ hw_gzip_exit(); ++ ++ return 0; ++} +diff --git a/arch/arm/boot/compressed/hw_decompress.h b/arch/arm/boot/compressed/hw_decompress.h +new file mode 100644 +index 0000000..053c419 +--- /dev/null ++++ b/arch/arm/boot/compressed/hw_decompress.h +@@ -0,0 +1,130 @@ ++#include ++ ++/* for fast boot */ ++#define HW_DEC_INTR (73) ++ ++/* These are same definition as in linux 2.6.11 kernel. */ ++//#define PAGE_SIZE 4096 ++#define PAGE_NR(x) (((x)+PAGE_SIZE-1)/PAGE_SIZE) ++#define __ALIGN_UP(x,y) (((x)+(y)-1) & (~((y)-1))) ++ ++/* The base address for emar*/ ++#define HW_DEC_REG_BASE_ADDR (0x110c0000) ++ ++/* The global init registers for emar interface */ ++#define EAMR_RID_REG_OFST (0x0108) ++#define EAMR_ROSD_REG_OFST (0x010C) ++#define EAMR_WID_REG_OFST (0x0110) ++#define EAMR_WOSD_REG_OFST (0x0114) ++ ++/* The enable register */ ++#define EAMR_WORK_EN_REG_OFST (0x0100) ++ ++#define DPRS_DATA_SRC_BADDR (0x2040) ++#define DPRS_DATA_SRC_LEN (0x2044) ++ ++/* Decompress parameter reigsters for page address */ ++#define DPRS_DATA_RTN_BADDR (0x2020) ++#define DPRS_DATA_RTN_LEN (0x2024) ++ ++/* Decompress parameter registers for page data */ ++#define DPRS_DATA_INFO_BADDR (0x2028) ++#define DPRS_DATA_INFO_LEN (0x202C) ++ ++#define DPRS_DATA_CRC32 (0x2030) ++ ++#define CRC_CHECK_EN (0x4000) ++ ++/* The status registers*/ ++#define BUF_INFO (0x2080) ++#define DPRS_RTN_INFO (0x2084) ++#define DPRS_RTN_LEN (0x2088) ++#define BUF_INFO_CLR (0x2090) ++#define RLT_INFO_CLR (0x2094) ++ ++/* The intr registers*/ ++#define INT_EN_REG_ADDR (0x0128) ++#define INT_STATUS_REG_ADDR (0x0124) ++#define INT_CLEAR_REG_ADDR (0x0130) ++ ++/* Define the union U_DPRS_DATA_BUF_INFO */ ++typedef union { ++ /* Define the struct bits */ ++ struct { ++ unsigned int buf_len:24; /* [23..0] */ ++ unsigned int buf_id:2; /* [25..24] */ ++ unsigned int reserved_1:2; /* [27..26] */ ++ unsigned int eop:1; /* [28] */ ++ unsigned int sop:1; /* [29] */ ++ unsigned int reserved_0:1; /* [30] */ ++ unsigned int mode:1; /* [31] */ ++ } bits; ++ ++ /* Define an unsigned member */ ++ unsigned int u32; ++ ++} U_DPRS_DATA_BUF_INFO; ++ ++typedef union { ++ struct { ++ unsigned int buf_id:2; /* [1:0] */ ++ unsigned int rsv:29; /* [30:2] */ ++ unsigned int aval_flg:1; /* [31] */ ++ } bits; ++ unsigned int u32; ++} U_BUF_STATUS; ++ ++typedef union { ++ struct { ++ unsigned int err_info:8; /* [7:0] */ ++ unsigned int rsv:23; /* [30:8] */ ++ unsigned int aval_flg:1; /* [31] */ ++ } bits; ++ ++ unsigned int u32; ++ ++} U_DPRS_RTN_STATUS; ++ ++/* Define the union U_INT_EN */ ++typedef union { ++ /* Define the struct bits */ ++ struct { ++ unsigned int task_intrpt_en:1; /* [0] */ ++ unsigned int block_intrpt_en:1; /* [1] */ ++ unsigned int reserved_0:30; /* [31..2] */ ++ } bits; ++ ++ /* Define an unsigned member */ ++ unsigned int u32; ++ ++} U_INTR_EN; ++ ++typedef union { ++ /* Define the struct bits */ ++ struct { ++ unsigned int task_intrpt:1; /* [0] */ ++ unsigned int block_intrpt:1; /* [1] */ ++ unsigned int reserved_0:30; /* [31..2] */ ++ } bits; ++ ++ /* Define an unsigned member */ ++ unsigned int u32; ++ ++} U_INTR_STATUS; ++ ++typedef union { ++ /* Define the struct bits */ ++ struct { ++ unsigned int task_intrpt_clr:1; /* [0] */ ++ unsigned int block_intrpt_clr:1; /* [1] */ ++ unsigned int reserved_0:30; /* [31..2] */ ++ } bits; ++ ++ /* Define an unsigned member */ ++ unsigned int u32; ++} U_INTR_CLR; ++ ++ ++void hw_gzip_exit(void); ++int hw_gzip_dec(unsigned int dst, int *dstlen, unsigned int src, int srclen); ++void hw_gzip_init(void); +diff --git a/arch/arm/boot/compressed/hw_decompress_hi3559.h b/arch/arm/boot/compressed/hw_decompress_hi3559.h +new file mode 100644 +index 0000000..32f4dde +--- /dev/null ++++ b/arch/arm/boot/compressed/hw_decompress_hi3559.h +@@ -0,0 +1,21 @@ ++#define CRG_REG_BASE 0x12010000 ++#define PERI_CRG33 0x84 ++#define GZIP_CLKEN (1<<1) ++ ++static void disable_decompress_clock(void) ++{ ++ unsigned int regval; ++ ++ regval = readl((void *)(CRG_REG_BASE + PERI_CRG33)); ++ regval &= ~GZIP_CLKEN; ++ writel(regval, (void *)(CRG_REG_BASE + PERI_CRG33)); ++} ++ ++static void enable_decompress_clock(void) ++{ ++ unsigned int regval; ++ ++ regval = readl((void *)(CRG_REG_BASE + PERI_CRG33)); ++ regval |= GZIP_CLKEN; ++ writel(regval, (void *)(CRG_REG_BASE + PERI_CRG33)); ++} +diff --git a/arch/arm/boot/compressed/vmlinux.lds.S b/arch/arm/boot/compressed/vmlinux.lds.S +index 2b60b84..48ab3fb 100644 +--- a/arch/arm/boot/compressed/vmlinux.lds.S ++++ b/arch/arm/boot/compressed/vmlinux.lds.S +@@ -48,6 +48,7 @@ SECTIONS + *(.rodata) + *(.rodata.*) + } ++ . = ALIGN(16); + .piggydata : { + *(.piggydata) + } +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index 38c89ca..3f541e2 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -91,6 +91,22 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \ + exynos5800-peach-pi.dtb + dtb-$(CONFIG_ARCH_HI3xxx) += hi3620-hi4511.dtb + dtb-$(CONFIG_ARCH_HIX5HD2) += hisi-x5hd2-dkb.dtb ++dtb-$(CONFIG_ARCH_HI3516CV300) += hi3516cv300-demb.dtb ++dtb-$(CONFIG_ARCH_HI3536C) += hi3536c-demb.dtb ++dtb-$(CONFIG_ARCH_HI3521D) += hi3521d-demb.dtb ++dtb-$(CONFIG_ARCH_HI3531D) += hi3531d-demb.dtb ++ifeq ($(CONFIG_SMP),y) ++dtb-$(CONFIG_ARCH_HI3519) += hisi-hi3519-hmp-demb.dtb ++dtb-$(CONFIG_ARCH_HI3519V101) += hisi-hi3519v101-hmp-demb.dtb ++dtb-$(CONFIG_ARCH_HI3516AV200) += hisi-hi3516av200-hmp-demb.dtb ++dtb-$(CONFIG_ARCH_HI3559) += hisi-hi3559-hmp-demb.dtb ++else ++dtb-$(CONFIG_ARCH_HI3519) += hisi-hi3519-demb.dtb ++dtb-$(CONFIG_ARCH_HI3519V101) += hisi-hi3519v101-demb.dtb ++dtb-$(CONFIG_ARCH_HI3516AV200) += hisi-hi3516av200-demb.dtb ++dtb-$(CONFIG_ARCH_HI3559) += hisi-hi3559-demb.dtb ++dtb-$(CONFIG_ARCH_HI3556) += hisi-hi3556-demb.dtb ++endif + dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb \ + ecx-2000.dtb + dtb-$(CONFIG_ARCH_HIP04) += hip04-d01.dtb +@@ -517,15 +533,14 @@ dtb-$(CONFIG_MACH_DOVE) += dove-cm-a510.dtb \ + dove-dove-db.dtb + dtb-$(CONFIG_ARCH_MEDIATEK) += mt6589-aquaris5.dtb + +-targets += dtbs dtbs_install +-targets += $(dtb-y) ++DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES)) ++ifneq ($(DTB_NAMES),) ++DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES)) ++else ++DTB_LIST := $(dtb-y) + endif + +-# *.dtb used to be generated in the directory above. Clean out the +-# old build results so people don't accidentally use them. +-dtbs: $(addprefix $(obj)/, $(dtb-y)) +- $(Q)rm -f $(obj)/../*.dtb +- +-clean-files := *.dtb ++endif + +-dtbs_install: $(addsuffix _dtbinst_, $(dtb-y)) ++always := $(DTB_LIST) ++clean-files := *.dtb +diff --git a/arch/arm/boot/dts/hi3516cv300-demb.dts b/arch/arm/boot/dts/hi3516cv300-demb.dts +new file mode 100644 +index 0000000..1584a45 +--- /dev/null ++++ b/arch/arm/boot/dts/hi3516cv300-demb.dts +@@ -0,0 +1,636 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++ ++/dts-v1/; ++#include "hi3516cv300.dtsi" ++ ++/ { ++ model = "Hisilicon Hi3516CV300 DEMO Board"; ++ compatible = "hisilicon,hi3516cv300"; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x10000000>; ++ }; ++}; ++ ++&dual_timer0 { ++ status = "okay"; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&i2c_bus1 { ++ status = "okay"; ++ clock-frequency = <100000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pmux &i2c1_pconf>; ++}; ++ ++&spi_bus1{ ++ status = "disabled"; ++ num-cs = <2>; ++ cs-gpios = <&gpio_chip5 3 0>, <&gpio_chip5 4 0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi1_pmux &spi1_pconf1 &spi1_pconf2 &spi1_pconf3>; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <50000000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <50000000>; ++ }; ++}; ++ ++&pwm { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_pmux>; ++}; ++ ++&hisfc { ++ assigned-clocks = <&crg_ctrl HI3516CV300_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++}; ++ ++&hisnfc { ++ assigned-clocks = <&crg_ctrl HI3516CV300_FMC_CLK>; ++ assigned-clock-rates = <83300000>; ++ ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ }; ++}; ++ ++&mmc0 { ++ status = "okay"; ++}; ++ ++&mmc1 { ++ status = "okay"; ++}; ++ ++&mmc2 { ++ status = "okay"; ++}; ++ ++&mdio { ++ phy0: phy@1 { ++ reg = <1>; ++ }; ++}; ++ ++&hisi_femac { ++ mac-address = [00 00 00 00 00 00]; ++ phy-mode = "rmii"; ++ phy-handle = <&phy0>; ++ hisilicon,phy-reset-delays-us = <10000 10000 150000>; ++}; ++ ++&usb_phy { ++ status = "okay"; ++}; ++ ++&ehci { ++ status = "okay"; ++}; ++ ++&ohci { ++ status = "okay"; ++}; ++ ++&hiudc { ++ status = "okay"; ++}; ++ ++&hidmac { ++ status = "okay"; ++}; ++ ++&dmac { ++ status = "disabled"; ++}; ++ ++&gpio_chip0 { ++ status = "okay"; ++}; ++ ++&gpio_chip1 { ++ status = "okay"; ++}; ++ ++&gpio_chip2 { ++ status = "okay"; ++}; ++ ++&gpio_chip3 { ++ status = "okay"; ++}; ++ ++&gpio_chip4 { ++ status = "okay"; ++}; ++ ++&gpio_chip5 { ++ status = "okay"; ++}; ++ ++&gpio_chip6 { ++ status = "okay"; ++}; ++ ++&gpio_chip7 { ++ status = "okay"; ++}; ++ ++&gpio_chip8 { ++ status = "okay"; ++}; ++ ++&pmux { ++ i2c0_pmux: i2c0_pmux { ++ pinctrl-single,pins = < ++ 0x2c 0x3 /*I2C0_SDA*/ ++ 0x30 0x3 /*I2C0_SCL*/ ++ >; ++ }; ++ ++ i2c1_pmux: i2c1_pmux { ++ pinctrl-single,pins = < ++ 0x20 0x1 /*I2C1_SDA*/ ++ 0x24 0x1 /*I2C1_SCL*/ ++ >; ++ }; ++ ++ spi0_pmux: spi0_pmux { ++ pinctrl-single,pins = < ++ 0x28 0x1 /*SPI0_SDI*/ ++ 0x2c 0x1 /*SPI0_SDO*/ ++ 0x30 0x1 /*SPI0_SCLK*/ ++ 0x34 0x1 /*SPI0_CSN*/ ++ >; ++ }; ++ ++ spi1_pmux: spi1_pmux { ++ pinctrl-single,pins = < ++ 0xc4 0x1 /*SPI1_CSN1*/ ++ 0xc8 0x1 /*SPI1_CSN0*/ ++ 0xcc 0x1 /*SPI1_SDO*/ ++ 0xd0 0x1 /*SPI1_SDI*/ ++ 0xd4 0x1 /*SPI1_SCLK*/ ++ >; ++ }; ++ ++ sensor_pmux: sensor_pmux { ++ pinctrl-single,pins = < ++ 0x38 0x1 /*SENSOR_RSTN*/ ++ 0x3c 0x1 /*SENSOR_CLK*/ ++ >; ++ }; ++ ++ spi_3wire_pmux: spi_3wire_pmux{ ++ pinctrl-single,pins = < ++ 0x2c 0x2 /*SPI_3LINE_SDATA*/ ++ 0x30 0x2 /*SPI_3LINE_SCLK*/ ++ 0x34 0x2 /*SPI_3LINE_CSN*/ ++ >; ++ }; ++ ++ vi_flash_trig_pmux: vi_flash_trig_pmux { ++ pinctrl-single,pins = < ++ 0x1c 0x1 /*FLASH_TRIG*/ ++ >; ++ }; ++ ++ vi_shutter_trig_pmux: vi_shutter_trig_pmux { ++ pinctrl-single,pins = < ++ 0x18 0x1 /*SHUTTER_TRIG*/ ++ >; ++ }; ++ ++ vi_bt1120_pmux: vi_bt1120_pmux{ ++ pinctrl-single,pins = < ++ 0x40 0x1 /*VI_DATA13*/ ++ 0x44 0x1 /*VI_DATA10*/ ++ 0x48 0x1 /*VI_DATA12*/ ++ 0x4c 0x1 /*VI_DATA11*/ ++ 0x50 0x1 /*VI_DATA9*/ ++ 0x54 0x1 /*VI_DATA14*/ ++ 0x58 0x1 /*VI_DATA15*/ ++ 0x5c 0x1 /*VI_VS*/ ++ 0x60 0x1 /*VI_HS*/ ++ >; ++ }; ++ ++ sensor_dc_pmux: sensor_dc_pmux{ ++ pinctrl-single,pins = < ++ 0x40 0x1 /*VI_DATA13*/ ++ 0x44 0x1 /*VI_DATA10*/ ++ 0x48 0x1 /*VI_DATA12*/ ++ 0x4c 0x1 /*VI_DATA11*/ ++ 0x50 0x1 /*VI_DATA9*/ ++ 0x54 0x1 /*VI_DATA14*/ ++ 0x58 0x1 /*VI_DATA15*/ ++ 0x5c 0x1 /*VI_VS*/ ++ 0x60 0x1 /*VI_HS*/ ++ >; ++ }; ++ ++ vo_bt656_pmux: vo_bt656_pmux{ ++ pinctrl-single,pins = < ++ 0x40 0x2 /*VOU656_CLK*/ ++ 0x44 0x2 /*VOU656_DATA3*/ ++ 0x48 0x2 /*VOU656_DATA7*/ ++ 0x4c 0x2 /*VOU656_DATA2*/ ++ 0x50 0x2 /*VOU656_DATA6*/ ++ 0x54 0x2 /*VOU656_DATA5*/ ++ 0x58 0x2 /*VOU656_DATA4*/ ++ 0x5c 0x2 /*VOU656_DATA1*/ ++ 0x60 0x2 /*VOU656_DATA0*/ ++ >; ++ }; ++ ++ vo_lcd_pmux: vo_lcd_pmux{ ++ pinctrl-single,pins = < ++ 0x40 0x3 /*LCD_CLK*/ ++ 0x44 0x3 /*LCD_DATA1*/ ++ 0x48 0x3 /*LCD_DATA3*/ ++ 0x4c 0x3 /*LCD_DATA2*/ ++ 0x50 0x3 /*LCD_DATA4*/ ++ 0x54 0x3 /*LCD_DATA5*/ ++ 0x58 0x3 /*LCD_DATA0*/ ++ 0x5c 0x3 /*LCD_HSYNC*/ ++ 0x60 0x3 /*LCD_VSYNC*/ ++ 0x64 0x3 /*LCD_DE*/ ++ >; ++ }; ++ ++ i2s_with_jtag_pmux: i2s_with_jtag_pmux{ ++ pinctrl-single,pins = < ++ 0xc4 0x4 /*I2S_SD_TX*/ ++ 0xc8 0x4 /*I2S_WS_TX*/ ++ 0xcc 0x4 /*I2S_BCLK_TX*/ ++ 0xd0 0x4 /*I2S_MCLK*/ ++ 0xd4 0x4 /*I2S_SD_RX*/ ++ >; ++ }; ++ ++ i2s_with_vi_pmux: i2s_with_vi_pmux{ ++ pinctrl-single,pins = < ++ 0x40 0x4 /*I2S_MCLK*/ ++ 0x44 0x4 /*I2S_SD_TX*/ ++ 0x48 0x4 /*I2S_BCLK_TX*/ ++ 0x4c 0x4 /*I2S_WS_TX*/ ++ 0x58 0x4 /*I2S_SD_RX*/ ++ >; ++ }; ++ ++ pwm_pmux: pwm_pmux{ ++ pinctrl-single,pins = < ++ 0x04 0x1 ++ 0x08 0x1 ++ 0x0c 0x1 ++ >; ++ }; ++}; ++ ++&pconf { ++ i2c0_pconf: i2c0_pconf { ++ pinctrl-single,pins = < ++ 0x2c 0 ++ 0x30 0 ++ >; ++ pinctrl-single,drive-strength = <0x70 0xff>; ++ }; ++ ++ i2c1_pconf: i2c1_pconf { ++ pinctrl-single,pins = < ++ 0x20 0 ++ 0x24 0 ++ >; ++ pinctrl-single,drive-strength = <0x30 0xff>; ++ }; ++ ++ /*spi0 drive strength conf 1~3*/ ++ spi0_pconf1: spi0_pconf1 { ++ pinctrl-single,pins = < ++ 0x28 0 ++ 0x2c 0 ++ >; ++ pinctrl-single,drive-strength = <0x20 0xff>; ++ }; ++ ++ spi0_pconf2: spi0_pconf2 { ++ pinctrl-single,pins = < ++ 0x30 0 ++ >; ++ pinctrl-single,drive-strength = <0x50 0xff>; ++ }; ++ ++ spi0_pconf3: spi0_pconf3 { ++ pinctrl-single,pins = < ++ 0x34 0 ++ >; ++ pinctrl-single,drive-strength = <0x30 0xff>; ++ }; ++ ++ /*spi1 drive strength conf 1~3*/ ++ spi1_pconf1: spi1_pconf1 { ++ pinctrl-single,pins = < ++ 0xe4 0 ++ 0xe8 0 ++ >; ++ pinctrl-single,drive-strength = <0x30 0xff>; ++ }; ++ ++ spi1_pconf2: spi1_pconf2 { ++ pinctrl-single,pins = < ++ 0xec 0 ++ 0xf0 0 ++ >; ++ pinctrl-single,drive-strength = <0x20 0xff>; ++ }; ++ ++ spi1_pconf3: spi1_pconf3 { ++ pinctrl-single,pins = < ++ 0xf4 0 ++ >; ++ pinctrl-single,drive-strength = <0x0 0xff>; ++ }; ++ ++ spi_3wire_pconf: spi_3wire_pconf{ ++ pinctrl-single,pins = < ++ 0x2c 0 ++ 0x30 0 ++ 0x34 0 ++ >; ++ pinctrl-single,drive-strength = <0x70 0xff>; ++ }; ++ ++ sensor_pconf1: sensor_pconf1 { ++ pinctrl-single,pins = < ++ 0x38 0 ++ >; ++ pinctrl-single,drive-strength = <0x31 0xff>; ++ }; ++ ++ sensor_pconf2: sensor_pconf2 { ++ pinctrl-single,pins = < ++ 0x3c 0 ++ >; ++ pinctrl-single,drive-strength = <0x20 0xff>; ++ }; ++ ++ vi_bt1120_pconf: vi_bt1120_pconf { ++ pinctrl-single,pins = < ++ 0x40 0 ++ 0x44 0 ++ 0x48 0 ++ 0x4c 0 ++ 0x50 0 ++ 0x54 0 ++ 0x58 0 ++ 0x5c 0 ++ 0x60 0 ++ >; ++ pinctrl-single,drive-strength = <0x70 0xff>; ++ }; ++ ++ sensor_dc_pconf: sensor_dc_pconf { ++ pinctrl-single,pins = < ++ 0x40 0 ++ 0x44 0 ++ 0x48 0 ++ 0x4c 0 ++ 0x50 0 ++ 0x54 0 ++ 0x58 0 ++ 0x5c 0 ++ 0x60 0 ++ >; ++ pinctrl-single,drive-strength = <0x70 0xff>; ++ }; ++ ++ vo_bt656_pconf1: vo_bt656_pconf1 { ++ pinctrl-single,pins = < ++ 0x40 0 ++ >; ++ pinctrl-single,drive-strength = <0x40 0xff>; ++ }; ++ ++ vo_bt656_pconf2: vo_bt656_pconf2 { ++ pinctrl-single,pins = < ++ 0x44 0 ++ 0x48 0 ++ 0x4c 0 ++ 0x50 0 ++ 0x54 0 ++ 0x58 0 ++ 0x5c 0 ++ 0x60 0 ++ >; ++ pinctrl-single,drive-strength = <0x20 0xff>; ++ }; ++ ++ vo_lcd_pconf1: vo_lcd_pconf1 { ++ pinctrl-single,pins = < ++ 0x40 0 ++ >; ++ pinctrl-single,drive-strength = <0x40 0xff>; ++ }; ++ ++ vo_lcd_pconf2: vo_lcd_pconf2 { ++ pinctrl-single,pins = < ++ 0x44 0 ++ 0x48 0 ++ 0x4c 0 ++ 0x50 0 ++ 0x54 0 ++ 0x58 0 ++ 0x5c 0 ++ 0x60 0 ++ 0x64 0 ++ >; ++ pinctrl-single,drive-strength = <0x10 0xff>; ++ }; ++ ++ i2s_with_jtag_pconf: i2s_with_jtag_pconf{ ++ pinctrl-single,pins = < ++ 0xe4 0 ++ 0xe8 0 ++ 0xec 0 ++ 0xf0 0 ++ 0xf4 0 ++ >; ++ pinctrl-single,drive-strength = <0x30 0xff>; ++ }; ++ ++ i2s_with_vi_pconf: i2s_with_vi_pconf{ ++ pinctrl-single,pins = < ++ 0x40 0 ++ 0x44 0 ++ 0x48 0 ++ 0x4c 0 ++ 0x58 0 ++ >; ++ pinctrl-single,drive-strength = <0x70 0xff>; ++ }; ++}; ++ ++&i2c_bus0 { ++ status = "okay"; ++ clock-frequency = <100000>; ++}; ++ ++&spi_bus0{ ++ status = "okay"; ++ num-cs = <1>; ++ cs-gpios = <&gpio_chip0 6 0>; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <50000000>; ++ }; ++}; ++ ++&sensor_device0 { ++ pinctrl-names = "i2c_mipi", "ssp_mipi", "i2c_dc", "ssp_dc", "sleep"; ++ pinctrl-0 = <&sensor_pmux &sensor_pconf1 &sensor_pconf2 &i2c0_pmux &i2c0_pconf>; ++ pinctrl-1 = <&sensor_pmux &sensor_pconf1 &sensor_pconf2 &spi0_pmux &spi0_pconf1 &spi0_pconf2 &spi0_pconf3>; ++ pinctrl-2 = <&sensor_pmux &sensor_pconf1 &sensor_pconf2 &i2c0_pmux &i2c0_pconf &sensor_dc_pmux &sensor_dc_pconf>; ++ pinctrl-3 = <&sensor_pmux &sensor_pconf1 &sensor_pconf2 &spi0_pmux &spi0_pconf1 &spi0_pconf2 &spi0_pconf3 &sensor_dc_pmux &sensor_dc_pconf>; ++ pinctrl-4 = <&sensor_pmux &sensor_pconf1 &sensor_pconf2>; ++}; ++ ++&viu { ++ pinctrl-names = "default", "bt1120", "sleep"; ++ pinctrl-0 = <&vi_flash_trig_pmux &vi_shutter_trig_pmux>; ++ pinctrl-1 = <&vi_flash_trig_pmux &vi_shutter_trig_pmux &vi_bt1120_pmux &vi_bt1120_pconf>; ++ pinctrl-2 = <&vi_flash_trig_pmux &vi_shutter_trig_pmux>; ++}; ++ ++&vou { ++ pinctrl-names = "bt656", "lcd", "sleep", "default"; ++ pinctrl-0 = <&vo_bt656_pmux &vo_bt656_pconf1 &vo_bt656_pconf2>; ++ pinctrl-1 = <&vo_lcd_pmux &vo_lcd_pconf1 &vo_lcd_pconf2>; ++ pinctrl-2 = <>; ++ pinctrl-3 = <>; ++}; ++ ++/* ++&audio { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s_with_jtag_pmux &i2s_with_jtag_pconf>; ++}; ++*/ ++ ++&pin_ctrl_online { ++ pinctrl-single,pins = < ++ 0x12030000 0x00000080 ++ 0x12030044 0x66664111 ++ 0x12030048 0x66666013 ++ 0x1203004c 0x65266666 ++ 0x12030050 0x00000011 ++ 0x12030054 0x00000110 ++ 0x12030058 0x00000000 ++ 0x12060204 0x1f>; ++}; ++ ++&pin_ctrl_offline { ++ pinctrl-single,pins = < ++ 0x12030000 0x00000000 ++ 0x12030044 0x66666111 ++ 0x12030048 0x66666023 ++ 0x1203004c 0x65266666 ++ 0x12030050 0x00000011 ++ 0x12030054 0x00000100 ++ 0x12030058 0x00000000 ++ 0x12060204 0x2>; ++}; ++ ++&pin_ctrl_ddr { ++ pinctrl-single,pins = < ++ 0x120600c0 0x76543210 ++ 0x120600c4 0x76543210 ++ 0x120600c8 0x76543210 ++ 0x120600cc 0x76543210 ++ 0x120600d0 0x76543210 ++ 0x120600d4 0x76543210 ++ 0x12060100 0x76543210 ++ 0x12060104 0x76543210 ++ 0x12060108 0x76543210 ++ 0x1206010c 0x76543210 ++ 0x12060110 0x76543210 ++ 0x12060114 0x76543210 ++ 0x12060140 0x00000000 ++ 0x12060144 0x00000000 ++ 0x12060148 0x00000000 ++ 0x1206014c 0x00000000 ++ 0x12060150 0x00000000 ++ 0x12060154 0x00000000 ++ 0x12060180 0x00004000 ++ 0x12060184 0x00004000 ++ 0x12060188 0x00000000 ++ 0x1206018c 0x00000000 ++ 0x12060190 0x00000100 ++ 0x12060194 0x00000000 ++ 0x12060200 0x1f ++ 0x12060208 0x2 ++ 0x1206020c 0x2 ++ 0x12060214 0x3 ++ 0x12060240 0xb ++ 0x12060244 0x0 ++ 0x12060040 0x81001000 ++ 0x12060044 0x81001000 ++ 0x12060048 0x81001000 ++ 0x1206004c 0x81001000 ++ 0x12060050 0x81001000 ++ 0x12060054 0x81001000 ++ 0x120614bc 0x101 ++ 0x113200E0 0xd ++ >; ++}; ++ ++&user_pinmux { ++ pinctrl-single,pins = < ++ >; ++}; +diff --git a/arch/arm/boot/dts/hi3516cv300.dtsi b/arch/arm/boot/dts/hi3516cv300.dtsi +new file mode 100644 +index 0000000..2832476 +--- /dev/null ++++ b/arch/arm/boot/dts/hi3516cv300.dtsi +@@ -0,0 +1,675 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "skeleton.dtsi" ++#include ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ aliases { ++ serial0 = &uart0; ++ serial1 = &uart1; ++ serial2 = &uart2; ++ i2c0 = &i2c_bus0; ++ i2c1 = &i2c_bus1; ++ spi0 = &spi_bus0; ++ spi1 = &spi_bus1; ++ gpio0 = &gpio_chip0; ++ gpio1 = &gpio_chip1; ++ gpio2 = &gpio_chip2; ++ gpio3 = &gpio_chip3; ++ gpio4 = &gpio_chip4; ++ gpio5 = &gpio_chip5; ++ gpio6 = &gpio_chip6; ++ gpio7 = &gpio_chip7; ++ gpio8 = &gpio_chip8; ++ sensor0 = &sensor_device0; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,arm926ej-s"; ++ reg = <0>; ++ }; ++ }; ++ ++ vic: interrupt-controller@10040000 { ++ compatible = "arm,pl190-vic"; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ reg = <0x10040000 0x1000>; ++ }; ++ ++ soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&vic>; ++ ranges; ++ ++ crg_ctrl: crg_ctrl@12010000 { ++ compatible = "hisilicon,hi3516cv300-crg"; ++ reg = <0x12010000 0x1000>; ++ #clock-cells = <1>; ++ #reset-cells = <2>; ++ }; ++ ++ sys_ctrl: system-controller@12020000 { ++ compatible = "hisilicon,hi3516cv300-sys", "syscon"; ++ reg = <0x12020000 0x1000>; ++ #clock-cells = <1>; ++ }; ++ ++ reboot { ++ compatible = "syscon-reboot"; ++ regmap = <&sys_ctrl>; ++ offset = <0x4>; ++ mask = <0xdeadbeef>; ++ }; ++ ++ pm { ++ compatible = "hisilicon,hibvt-pm"; ++ reg = <0x12020000 0x1000>, <0x12000000 0x1000>; ++ }; ++ ++ pm_hibernate { ++ compatible = "hisilicon,hibvt-pm-hibernate"; ++ reg = <0x12020000 0x1000>; ++ }; ++ ++ dual_timer0: dual_timer@12000000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ reg = <0x12000000 0x1000>; ++ interrupts = <3>; ++ clocks = <&sys_ctrl HI3516CV300_TIME00_CLK>, ++ <&sys_ctrl HI3516CV300_TIME01_CLK>, ++ <&crg_ctrl HI3516CV300_APB_CLK>; ++ clock-names = "timer0", "timer1", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer1: dual_timer@12001000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ reg = <0x12001000 0x1000>; ++ interrupts = <4>; ++ clocks = <&sys_ctrl HI3516CV300_TIME10_CLK>, ++ <&sys_ctrl HI3516CV300_TIME11_CLK>, ++ <&crg_ctrl HI3516CV300_APB_CLK>; ++ clock-names = "timer0", "timer1", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart0: uart@12100000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12100000 0x1000>; ++ interrupts = <5>; ++ clocks = <&crg_ctrl HI3516CV300_UART0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart1: uart@12101000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12101000 0x1000>; ++ interrupts = <30>; ++ clocks = <&crg_ctrl HI3516CV300_UART1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart2: uart@12102000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12102000 0x1000>; ++ interrupts = <25>; ++ clocks = <&crg_ctrl HI3516CV300_UART2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ i2c_bus0: i2c@12110000 { ++ compatible = "hisilicon,hi3516cv300-i2c", ++ "hisilicon,hibvt-i2c"; ++ reg = <0x12110000 0x1000>; ++ clocks = <&crg_ctrl HI3516CV300_APB_CLK>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus1: i2c@12112000 { ++ compatible = "hisilicon,hi3516cv300-i2c", ++ "hisilicon,hibvt-i2c"; ++ reg = <0x12112000 0x1000>; ++ clocks = <&crg_ctrl HI3516CV300_APB_CLK>; ++ status = "disabled"; ++ }; ++ ++ spi_bus0: spi@12120000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12120000 0x1000>; ++ interrupts = <6>; ++ clocks = <&crg_ctrl HI3516CV300_SPI0_CLK>; ++ clock-names = "apb_pclk"; ++ /* dmas = <&dmac 12 1>, <&dmac 13 2>; */ ++ /* dma-names = "rx", "tx"; */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ spi_bus1: spi@12121000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12121000 0x1000>, <0x12030000 0x4>; ++ interrupts = <7>; ++ clocks = <&crg_ctrl HI3516CV300_SPI1_CLK>; ++ clock-names = "apb_pclk"; ++ /* dmas = <&dmac 14 1>, <&dmac 15 2>; */ ++ /* dma-names = "rx", "tx"; */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ hisi,spi_cs_sb = <4>; ++ hisi,spi_cs_mask_bit = <0x10>; ++ status = "disabled"; ++ }; ++ ++ fmc: spi-nor-controller@10000000 { ++ compatible = "hisilicon,hisi-fmc"; ++ reg = <0x10000000 0x1000>, <0x14000000 0x1000000>; ++ reg-names = "control", "memory"; ++ clocks = <&crg_ctrl HI3516CV300_FMC_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hisfc:spi-nor@0 { ++ compatible = "hisilicon,hisi-sfc"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hisnfc:spi-nand@0 { ++ compatible = "hisilicon,hisi-spi-nand"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ ++ mmc2: himciv200.MMC@0x100e0000 { ++ compatible = "hisilicon,hi3516cv300-himciv200"; ++ reg = <0x100e0000 0x1000>; ++ interrupts = <11>; ++ clocks = <&crg_ctrl HI3516CV300_MMC2_CLK>; ++ clock-names = "mmc_clk"; ++ max-frequency = <99000000>; ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-mmc-hw-reset; ++ mmc-hs200-1_8v; ++ full-pwr-cycle; ++ devid = <2>; ++ regmap = <&sys_ctrl>; ++ status = "disabled"; ++ }; ++ ++ mmc0: himciv200.SD@0x100c0000 { ++ compatible = "hisilicon,hi3516cv300-himciv200"; ++ reg = <0x100c0000 0x1000>; ++ interrupts = <18>; ++ clocks = <&crg_ctrl HI3516CV300_MMC0_CLK>; ++ clock-names = "mmc_clk"; ++ max-frequency = <49500000>; ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ devid = <0>; ++ status = "disabled"; ++ }; ++ ++ mmc1: himciv200.SD@0x100d0000 { ++ compatible = "hisilicon,hi3516cv300-himciv200"; ++ reg = <0x100d0000 0x1000>; ++ interrupts = <27>; ++ clocks = <&crg_ctrl HI3516CV300_MMC1_CLK>; ++ clock-names = "mmc_clk"; ++ max-frequency = <49500000>; ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ devid = <1>; ++ status = "disabled"; ++ }; ++ ++ mmc3: himciv200.SD@0x100f0000 { ++ compatible = "hisilicon,hi3516cv300-himciv200"; ++ reg = <0x100f0000 0x1000>; ++ interrupts = <27>; ++ clocks = <&crg_ctrl HI3516CV300_MMC3_CLK>; ++ clock-names = "mmc_clk"; ++ max-frequency = <49500000>; ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ devid = <3>; ++ status = "disabled"; ++ }; ++ ++ mdio: mdio@10051100 { ++ compatible = "hisilicon,hisi-femac-mdio"; ++ reg = <0x10051100 0x10>; ++ clocks = <&crg_ctrl HI3516CV300_ETH_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hisi_femac: ethernet@10090000 { ++ compatible = "hisilicon,hi3516cv300-femac", ++ "hisilicon,hisi-femac-v2"; ++ reg = <0x10050000 0x1000>,<0x10051300 0x200>; ++ interrupts = <12>; ++ clocks = <&crg_ctrl HI3516CV300_ETH_CLK>; ++ resets = <&crg_ctrl 0xec 0>, <&crg_ctrl 0xec 3>; ++ reset-names = "mac","phy"; ++ }; ++ ++ usb_phy: usbphy { ++ compatible = "hisilicon,inno_usb2_phy"; ++ reg = <0x12030000 0x1000>, <0x120d0000 0x1000>, ++ <0x12010000 0x1000>, <0x12020000 0x1000>; ++ clocks = <&crg_ctrl HI3516CV300_USB2_BUS_CLK>; ++ clock-names = "ref_clk"; ++ #phy-cells = <0>; ++ resets = <&crg_ctrl 0xb8 13>, <&crg_ctrl 0xb8 17>; ++ reset-names = "por_rst", "test_rst"; ++ status = "disabled"; ++ port0: port0 { ++ clocks = <&crg_ctrl HI3516CV300_UTMI0_CLK>; ++ resets = <&crg_ctrl 0xb8 14>, ++ <&crg_ctrl 0xb8 9>; ++ reset-names = "port_rst", "utmi_rst"; ++ }; ++ }; ++ ++ ehci: ehci@0x10120000 { ++ compatible = "generic-ehci"; ++ reg = <0x10120000 0x10000>; ++ interrupts = <15>; ++ clocks = <&crg_ctrl HI3516CV300_USB2_CLK>; ++ clock-names = "clk"; ++ status = "disabled"; ++ }; ++ ++ ohci: ohci@0x10110000 { ++ compatible = "generic-ohci"; ++ reg = <0x10110000 0x10000>; ++ interrupts = <16>; ++ clocks = <&crg_ctrl HI3516CV300_USB2_CLK>; ++ clock-names = "clk"; ++ status = "disabled"; ++ }; ++ ++ hiudc: hiudc@0x10130000 { ++ compatible = "hiudc"; ++ reg = <0x10130000 0x40000>; ++ interrupts = <10>; ++ clocks = <&crg_ctrl HI3516CV300_USB2_CLK>; ++ clock-names = "clk"; ++ status = "disabled"; ++ }; ++ ++ hidmac: hidma-controller@10030000 { ++ compatible = "hisilicon,hisi-dmac"; ++ reg = <0x10030000 0x1000>; ++ interrupts = <14>; ++ clocks = <&crg_ctrl HI3516CV300_DMAC_CLK>; ++ clock-names = "apb_pclk"; ++ resets = <&crg_ctrl 0xd8 4>; ++ reset-names = "dma-reset"; ++ #dma-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ dmac: dma-controller@10030000 { ++ compatible = "arm,pl080", "arm,primecell"; ++ reg = <0x10030000 0x1000>; ++ interrupts = <14>; ++ clocks = <&crg_ctrl HI3516CV300_DMAC_CLK>; ++ clock-names = "apb_pclk"; ++ lli-bus-interface-ahb1; ++ lli-bus-interface-ahb2; ++ mem-bus-interface-ahb1; ++ mem-bus-interface-ahb2; ++ memcpy-burst-size = <256>; ++ memcpy-bus-width = <32>; ++ #dma-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip0: gpio@12140000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12140000 0x1000>; ++ interrupts = <31>; ++ clocks = <&crg_ctrl HI3516CV300_APB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ gpio-ranges = <&pmux 0 61 2>, ++ <&pmux 4 11 1>, ++ <&pmux 5 10 1>, ++ <&pmux 6 13 2>; ++ ++ status = "disabled"; ++ }; ++ ++ gpio_chip1: gpio@12141000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12141000 0x1000>; ++ interrupts = <31>; ++ clocks = <&crg_ctrl HI3516CV300_APB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ gpio-ranges = <&pmux 0 16 7>, ++ <&pmux 7 0 1>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip2: gpio@12142000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12142000 0x1000>; ++ interrupts = <31>; ++ clocks = <&crg_ctrl HI3516CV300_APB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ gpio-ranges = <&pmux 0 46 1>, ++ <&pmux 1 45 1>, ++ <&pmux 2 44 1>, ++ <&pmux 3 43 1>, ++ <&pmux 4 39 1>, ++ <&pmux 5 38 1>, ++ <&pmux 6 40 1>, ++ <&pmux 7 48 1>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip3: gpio@12143000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12143000 0x1000>; ++ interrupts = <31>; ++ clocks = <&crg_ctrl HI3516CV300_APB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ gpio-ranges = <&pmux 0 37 1>, ++ <&pmux 1 36 1>, ++ <&pmux 2 35 1>, ++ <&pmux 3 34 1>, ++ <&pmux 4 23 2>, ++ <&pmux 6 8 2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip4: gpio@12144000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12144000 0x1000>; ++ interrupts = <31>; ++ clocks = <&crg_ctrl HI3516CV300_APB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ gpio-ranges = <&pmux 0 27 1>, ++ <&pmux 1 26 1>, ++ <&pmux 2 31 1>, ++ <&pmux 3 30 1>, ++ <&pmux 4 28 2>, ++ <&pmux 6 33 1>, ++ <&pmux 7 32 1>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip5: gpio@12145000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12145000 0x1000>; ++ interrupts = <31>; ++ clocks = <&crg_ctrl HI3516CV300_APB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ gpio-ranges = <&pmux 0 53 1>, ++ <&pmux 1 51 2>, ++ <&pmux 3 50 1>, ++ <&pmux 4 49 1>, ++ <&pmux 5 47 1>, ++ <&pmux 6 40 2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip6: gpio@12146000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12146000 0x1000>; ++ interrupts = <31>; ++ clocks = <&crg_ctrl HI3516CV300_APB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ gpio-ranges = <&pmux 0 7 1>, ++ <&pmux 1 6 1>, ++ <&pmux 2 4 1>, ++ <&pmux 3 5 1>, ++ <&pmux 4 15 1>, ++ <&pmux 5 1 3>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip7: gpio@12147000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12147000 0x1000>; ++ interrupts = <31>; ++ clocks = <&crg_ctrl HI3516CV300_APB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ gpio-ranges = <&pmux 1 55 6>, ++ <&pmux 7 25 1>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip8: gpio@12148000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12148000 0x1000>; ++ interrupts = <31>; ++ clocks = <&crg_ctrl HI3516CV300_APB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ gpio-ranges = <&pmux 0 63 3>, ++ <&pmux 3 12 1>; ++ status = "disabled"; ++ }; ++ ++ pmux: pinmux@12040000 { ++ compatible = "pinctrl-single"; ++ reg = <0x12040000 0x108>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ #gpio-range-cells = <3>; ++ ranges; ++ ++ pinctrl-single,register-width = <32>; ++ pinctrl-single,function-mask = <7>; ++ /* pin base, nr pins & gpio function */ ++ pinctrl-single,gpio-range = <&range 0 54 0 ++ &range 55 6 1 &range 61 5 0>; ++ ++ range: gpio-range { ++ #pinctrl-single,gpio-range-cells = <3>; ++ }; ++ }; ++ ++ pconf: pinconf@12040800 { ++ compatible = "pinconf-single"; ++ reg = <0x12040800 0x130>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ pinctrl-single,register-width = <32>; ++ }; ++ }; ++ ++ media { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&vic>; ++ ranges; ++ ++ sys: sys@12010000 { ++ compatible = "hisilicon,hi35xx_sys"; ++ reg = <0x12010000 0x10000>, <0x12020000 0x10000>, ++ <0x12060000 0x10000>, <0X12030000 0x10000>; ++ reg-names = "crg", "sys", "ddr", "misc"; ++ }; ++ ++ audio: audio@11310000 { ++ compatible = "hisilicon,hi35xx_aiao"; ++ interrupts = <9>; ++ reg = <0x11310000 0x10000>, <0x11320000 0x2000>; ++ reg-names = "aiao", "acodec"; ++ clocks = <&crg_ctrl HI3516CV300_AIAO_CLK>; ++ }; ++ ++ ive: ive@11230000 { ++ compatible = "hisilicon,hi35xx_ive"; ++ interrupts = <21>; ++ reg = <0x11230000 0x10000>; ++ clocks = <&crg_ctrl HI3516CV300_IVE_CLK>; ++ }; ++ ++ sensor_device0: sensor_device0 { ++ compatible = "hisilicon,hi35xx_sensor"; ++ clocks = <&crg_ctrl HI3516CV300_SENSOR_CLK>; ++ }; ++ ++ mipi: mipi@11300000 { ++ compatible = "hisilicon,hi35xx_mipi"; ++ interrupts = <28>; ++ reg = <0x11300000 0x10000>; ++ clocks = <&crg_ctrl HI3516CV300_MIPI_CLK>; ++ }; ++ ++ isp: isp@11380000 { ++ compatible = "hisilicon,hi35xx_isp"; ++ interrupts = <22>; ++ reg = <0x11380000 0x10000>, <0x11392200 0x40000>; ++ reg-names = "reg_vicap_base_va", "reg_isp_base_va"; ++ }; ++ ++ viu: viu@11380000 { ++ compatible = "hisilicon,hi35xx_viu"; ++ interrupts = <22>; ++ interrupt-names = "viu0"; ++ reg = <0x11380000 0x70000>; ++ reg-names = "viu0"; ++ clocks = <&crg_ctrl HI3516CV300_VIU_CLK>, <&crg_ctrl HI3516CV300_ISP_CLK>; ++ clock-names = "viu0", "isp0"; ++ }; ++ ++ vou: vou@11400000 { ++ compatible = "hisilicon,hi35xx_vou"; ++ interrupts = <23>; ++ reg = <0x11400000 0x10000>; ++ }; ++ ++ vgs: vgs@11240000 { ++ compatible = "hisilicon,hi35xx_vgs"; ++ interrupts = <29>; ++ reg = <0x11240000 0x10000>; ++ clocks = <&crg_ctrl HI3516CV300_VGS_CLK>; ++ }; ++ ++ vpss: vpss@11250000 { ++ compatible = "hisilicon,hi35xx_vpss"; ++ interrupts = <17>, <22>; ++ interrupt-names = "vpss", "vi"; ++ reg = <0x11250000 0x10000>; ++ clocks = <&crg_ctrl HI3516CV300_VPSS_CLK>; ++ }; ++ ++ vedu: vedu@11260000 { ++ compatible = "hisilicon,hi35xx_vedu"; ++ interrupts = <24>; ++ reg = <0x11260000 0x10000>; ++ clocks = <&crg_ctrl HI3516CV300_VEDU_CLK>; ++ }; ++ ++ jpege: jpege@11220000 { ++ compatible = "hisilicon,hi35xx_jpege"; ++ interrupts = <26>; ++ reg = <0x11220000 0x10000>; ++ clocks = <&crg_ctrl HI3516CV300_JPGE_CLK>; ++ }; ++ ++ pwm: pwm@12130000 { ++ compatible = "hisilicon,hi3516cv300-pwm"; ++ reg = <0x12130000 0x10000>; ++ clocks = <&crg_ctrl HI3516CV300_PWM_CLK>; ++ resets = <&crg_ctrl 0x38 0>; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ piris: piris@12140000 { ++ compatible = "hisilicon,piris"; ++ reg = <0x12140000 0x10000>; ++ }; ++ ++ wtdg: wtdg@12080000 { ++ compatible = "hisilicon,hi_wdg"; ++ reg = <0x12080000 0x10000>; ++ reg-names = "wtdg"; ++ }; ++ ++ rtc: rtc@12090000 { ++ compatible = "hisilicon,hi_rtc"; ++ interrupts = <2>; ++ reg = <0x12090000 0x10000>; ++ }; ++ ++ ir: ir@120f0000{ ++ compatible = "hisilicon,hi_ir"; ++ interrupts = <19>; ++ reg = <0x120f0000 0x10000>; ++ }; ++ ++ online_flag: online_flag { ++ compatible = "hisilicon,vi-vpss-online"; ++ }; ++ ++ pin_ctrl_ddr: pin_ctrl_ddr { ++ compatible = "hisilicon,pinctrl-ddr"; ++ }; ++ ++ pin_ctrl_online: pin_ctrl_online { ++ compatible = "hisilicon,pinctrl-online"; ++ }; ++ ++ pin_ctrl_offline: pin_ctrl_offline { ++ compatible = "hisilicon,pinctrl-offline"; ++ }; ++ ++ user_pinmux: user_pinmux { ++ compatible = "hisilicon,user_define_pinmux"; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/hi3521d-demb.dts b/arch/arm/boot/dts/hi3521d-demb.dts +new file mode 100644 +index 0000000..548ed81 +--- /dev/null ++++ b/arch/arm/boot/dts/hi3521d-demb.dts +@@ -0,0 +1,275 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/dts-v1/; ++#include "hi3521d.dtsi" ++ ++/ { ++ model = "Hisilicon HI3521D DEMO Board"; ++ compatible = "hisilicon,hi3521d"; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ enable-method = "hisilicon,hi3521d-smp"; ++ ++ cpu@0 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ clock-frequency = ; ++ reg = <0>; ++ }; ++ ++ cpu@1 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ clock-frequency = ; ++ reg = <1>; ++ }; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x40000000>; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&spi_bus0{ ++ status = "okay"; ++ num-cs = <2>; ++ ++ spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <31250000>; ++ }; ++ ++ spidev@1 { ++ compatible = "spidev"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <31250000>; ++ }; ++}; ++ ++&hisfc { ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++}; ++ ++&hisnfc { ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ }; ++}; ++ ++&hidmac { ++ status = "okay"; ++}; ++ ++&mdio { ++ ethphy: ethernet-phy@1 { ++ reg = <1>; ++ }; ++}; ++ ++&higmac { ++ phy-handle = <ðphy>; ++ phy-mode = "rgmii"; ++}; ++ ++&pmux { ++ ++ viadclk_demob_pmux: viadclk_demob_pmux{ ++ pinctrl-single,pins = < ++ 0x0000 0x2 ++ 0x0024 0x2 ++ 0x0048 0x2 ++ 0x0070 0x2 ++ 0x0094 0x2 ++ >; ++ }; ++ ++ viadclk_sck_pmux: viadclk_sck_pmux{ ++ pinctrl-single,pins = < ++ 0x0000 0x2 ++ 0x004c 0x2 ++ 0x0024 0x2 ++ 0x0048 0x2 ++ 0x0070 0x2 ++ 0x0094 0x2 ++ >; ++ }; ++ ++ vicap_demob_pmux: vicap_demob_pmux{ ++ pinctrl-single,pins = < ++ 0x0004 0x1 ++ 0x0008 0x1 ++ 0x000c 0x1 ++ 0x0010 0x1 ++ 0x0014 0x1 ++ 0x0018 0x1 ++ 0x001c 0x1 ++ 0x0020 0x1 ++ 0x0028 0x1 ++ 0x002c 0x1 ++ 0x0030 0x1 ++ 0x0034 0x1 ++ 0x0038 0x1 ++ 0x003c 0x1 ++ 0x0040 0x1 ++ 0x0044 0x1 ++ 0x0050 0x1 ++ 0x0054 0x1 ++ 0x0058 0x1 ++ 0x005c 0x1 ++ 0x0060 0x1 ++ 0x0064 0x1 ++ 0x0068 0x1 ++ 0x006c 0x1 ++ 0x0074 0x1 ++ 0x0078 0x1 ++ 0x007c 0x1 ++ 0x0080 0x1 ++ 0x0084 0x1 ++ 0x0088 0x1 ++ 0x008c 0x1 ++ 0x0090 0x1 ++ >; ++ }; ++ ++ vo_vga_pmux: vo_vga_pmux{ ++ pinctrl-single,pins = < ++ 0x0174 0x1 ++ 0x017c 0x1 ++ 0x0180 0x1 ++ >; ++ }; ++ ++ vo_hdmi_pmux: vo_hdmi_pmux{ ++ pinctrl-single,pins = < ++ 0x0098 0x1 ++ 0x009c 0X1 ++ >; ++ }; ++ ++ i2s0_pmux: i2s0_pmux { ++ pinctrl-single,pins = < ++ 0x00a0 0x1 ++ 0x00a4 0x1 ++ 0x00a8 0x1 ++ >; ++ }; ++ ++ i2s1_pmux: i2s1_pmux { ++ pinctrl-single,pins = < ++ 0x00b0 0x1 ++ 0x00b4 0x1 ++ >; ++ }; ++ ++ i2s2_demob_pmux: i2s2_demob_pmux { ++ pinctrl-single,pins = < ++ 0x00b8 0x1 ++ 0x00bc 0x1 ++ 0x00c0 0x1 ++ >; ++ }; ++ ++ i2s2_sck_pmux: i2s2_sck_pmux { ++ pinctrl-single,pins = < ++ 0x00b8 0x1 ++ 0x00bc 0x1 ++ 0x00c0 0x1 ++ 0x00ac 0x2 ++ >; ++ }; ++}; ++ ++&sys_config_ctrl { ++ padctrl-ability,demo = < ++ 0x120f08a0 0x120 ++ 0x120f08a4 0x130 ++ 0x120f08a8 0x130 ++ 0x120f08ac 0x120 ++ 0x120f08b0 0x130 ++ 0x120f08b4 0x130 ++ 0x120f08b8 0x120 ++ 0x120f08bc 0x130 ++ 0x120f08c0 0x130 ++ 0x120f0800 0x140 ++ 0x120f084c 0x140 ++ 0x120f0898 0x40 ++ 0x120f089c 0x40 ++ >; ++ ++ sysctrl-ddr,pins = < ++ 0x12040098 0x00ffff1f ++ 0x1204009c 0x8888 ++ 0x12040168 0x00000f55 ++ 0x1212007c 0x35533201 ++ 0x12120080 0x65335526 ++ 0x12120084 0x66666666 ++ 0x12120094 0x65 /*VIVO axi max: 7*/ ++ >; ++ dllctrl-ddr,pins = < ++ 0x120401e0 0x0 /*DLL rst, disable*/ ++ 0x120401ec 0x0 ++ 0x120401f8 0x0 ++ 0x12040204 0x0 ++ 0x120401e0 0x4 /*DLL rst, disable*/ ++ 0x120401ec 0x4 ++ 0x120401f8 0x4 ++ 0x12040204 0x4 ++ 0x120401e0 0x6 /*DLL 150M and DLL rst, disable*/ ++ 0x120401ec 0x6 ++ 0x120401f8 0x6 ++ 0x12040204 0x6 ++ 0x120401e0 0x7 /*DLL 150M and DLL rst, enable*/ ++ 0x120401ec 0x7 ++ 0x120401f8 0x7 ++ 0x12040204 0x7 ++ 0x120401e0 0x3 /*DLL 150M and DLL unrst, enable*/ ++ 0x120401ec 0x3 ++ 0x120401f8 0x3 ++ 0x12040204 0x3 ++ 0x120401e4 0x10 /*dll_slave_en:1,dll_stop:0*/ ++ 0x120401F0 0x10 ++ 0x120401fC 0x10 ++ 0x12040208 0x10 ++ >; ++ ++ pinctrl-names = "demo", "sck", "default"; ++ pinctrl-0 = <&viadclk_demob_pmux &vicap_demob_pmux &i2s0_pmux &i2s2_demob_pmux &vo_hdmi_pmux &vo_vga_pmux>; ++ pinctrl-1 = <&viadclk_sck_pmux &vicap_demob_pmux &i2s0_pmux &i2s1_pmux &i2s2_sck_pmux &vo_hdmi_pmux &vo_vga_pmux >; ++ pinctrl-2 = <>; ++}; +diff --git a/arch/arm/boot/dts/hi3521d.dtsi b/arch/arm/boot/dts/hi3521d.dtsi +new file mode 100644 +index 0000000..5a2a2da +--- /dev/null ++++ b/arch/arm/boot/dts/hi3521d.dtsi +@@ -0,0 +1,392 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "skeleton.dtsi" ++#include ++/ { ++ aliases { ++ fmc = &fmc; ++ serial0 = &uart0; ++ spi0 = &spi_bus0; ++ }; ++ ++ clock: clock@12040000 { ++ compatible = "hisilicon,hi3521d-clock"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ #clock-cells = <1>; ++ #reset-cells = <2>; ++ reg = <0x12040000 0x1000>; ++ }; ++ ++ gic: interrupt-controller@10300000 { ++ compatible = "arm,cortex-a7-gic"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ /* gic dist base, gic cpu base , no virtual support */ ++ reg = <0x10301000 0x1000>, <0x10302000 0x100>; ++ }; ++ ++ soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ sysctrl: system-controller@12050000 { ++ compatible = "hisilicon,sysctrl"; ++ reg = <0x12050000 0x1000>; ++ reboot-offset = <0x4>; ++ #clock-cells = <1>; ++ }; ++ ++ pmu { ++ compatible = "arm,cortex-a7-pmu"; ++ interrupts = <0 54 4>, ++ <0 48 4>; ++ }; ++ ++ amba { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "arm,amba-bus"; ++ ranges; ++ ++ uart0: uart@12080000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12080000 0x1000>; ++ interrupts = <0 6 4>; ++ clocks = <&clock HI3521D_UART0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart1: uart@121090000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12090000 0x1000>; ++ interrupts = <0 7 4>; ++ clocks = <&clock HI3521D_UART1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart2: uart@120a0000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x120a0000 0x1000>; ++ interrupts = <0 8 4>; ++ clocks = <&clock HI3521D_UART2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ timer@0x12000000 { ++ compatible = "hisilicon,timer"; ++ /* timer0 & timer1 & timer2*/ ++ reg = <0x12000000 0x20>, /* clocksource */ ++ <0x12000020 0x20>, /* local timer for each cpu */ ++ <0x12010000 0x20>; ++ interrupts = <0 1 4>, <0 2 4>; /* irq of local timer */ ++ clocks = <&sysctrl HI3521D_TIME0_0_CLK>; ++ clock-names = "timer00"; ++ }; ++ }; ++ ++ /* dual timer 0 and 1 have used for clocksource and local timer */ ++ dual_timer2: dual_timer@12020000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer4 & timer5 */ ++ interrupts = <0 3 4>; ++ reg = <0x12020000 0x1000>; ++ clocks = <&sysctrl HI3521D_TIME2_4_CLK>, ++ <&sysctrl HI3521D_TIME2_5_CLK>, ++ <&clock HI3521D_SYSAXI_CLK>; ++ clock-names = "timer4", "timer5", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer3: dual_timer@12030000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer6 & timer7 */ ++ interrupts = <0 4 4>; ++ reg = <0x12030000 0x1000>; ++ clocks = <&sysctrl HI3521D_TIME3_6_CLK>, ++ <&sysctrl HI3521D_TIME3_7_CLK>, ++ <&clock HI3521D_SYSAXI_CLK>; ++ clock-names = "timer6", "timer7", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ spi_bus0: spi@120d0000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x120d0000 0x1000>, <0x12120014 0x4>; ++ interrupts = <0 14 4>; ++ clocks = <&clock HI3521D_SPI0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ hisi,spi_cs_sb = <0>; ++ hisi,spi_cs_mask_bit = <0x00000003>; ++ }; ++ ++ sata_phy: phy@11010000 { ++ compatible = "hisilicon,hisi-sata-nano-phy"; ++ reg = <0x11010000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ++ ahci: sata@11010000 { ++ compatible = "hisilicon,hisi-ahci"; ++ reg = <0x11010000 0x1000>; ++ interrupts = <0 17 4>; ++ phys = <&sata_phy>; ++ phy-names = "sata-phy"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ usb_phy: usbphy { ++ compatible = "hisilicon,hi3521d-usb2-phy"; ++ reg = <0x12040000 0x1000>, <0x12120000 0x1000>; ++ }; ++ ++ ehci@0x10120000 { ++ compatible = "generic-ehci"; ++ reg = <0x10040000 0x10000>; ++ interrupts = <0 19 4>; ++ }; ++ ++ ohci@0x10110000 { ++ compatible = "generic-ohci"; ++ reg = <0x10030000 0x10000>; ++ interrupts = <0 18 4>; ++ }; ++ ++ mdio: mdio@100a03c0 { ++ compatible = "hisilicon,hisi-gemac-mdio"; ++ reg = <0x100a03c0 0x20>; ++ clocks = <&clock HI3521D_ETH_CLK>; ++ resets = <&clock 0x14c 5>; ++ reset-names = "phy_reset"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ higmac: ethernet@100a0000 { ++ compatible = "hisilicon,higmac-v5"; ++ reg = <0x100a0000 0x1000>,<0x100a300c 0x4>; ++ interrupts = <0 16 4>, <0 61 4>, <0 62 4>, <0 63 4>; ++ ++ clocks = <&clock HI3521D_ETH_CLK>, ++ <&clock HI3521D_ETH_MACIF_CLK>; ++ clock-names = "higmac_clk", ++ "macif_clk"; ++ ++ resets = <&clock 0x14c 0>, ++ <&clock 0x14c 2>, ++ <&clock 0x14c 5>; ++ reset-names = "port_reset", ++ "macif_reset", ++ "phy_reset"; ++ ++ mac-address = [00 00 00 00 00 00]; ++ }; ++ ++ fmc: flash-memory-controller@10000000 { ++ compatible = "hisilicon,hisi-fmc"; ++ reg = <0x10000000 0x1000>, <0x14000000 0x10000>; ++ reg-names = "control", "memory"; ++ clocks = <&clock HI3521D_FMC_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hisfc:spi_nor_controller { ++ compatible = "hisilicon,hisi-sfc"; ++ assigned-clocks = <&clock HI3521D_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hisnfc:spi_nand_controller { ++ compatible = "hisilicon,hisi-spi-nand"; ++ assigned-clocks = <&clock HI3521D_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ ++ hidmac: hidma-controller@10060000 { ++ compatible = "hisilicon,hisi-dmac"; ++ reg = <0x10060000 0x1000>; ++ interrupts = <0 10 4>; ++ clocks = <&clock HI3521D_DMAC_CLK>; ++ clock-names = "dmac_clk"; ++ resets = <&clock 0x144 0>; ++ reset-names = "dma-reset"; ++ #dma-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ pmux: pinmux@120F0000 { ++ compatible = "pinctrl-single"; ++ reg = <0x120F0000 0x3A8>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ #gpio-range-cells = <3>; ++ ranges; ++ ++ pinctrl-single,register-width = <32>; ++ pinctrl-single,function-mask = <7>; ++ /* pin base, nr pins & gpio function */ ++ pinctrl-single,gpio-range = <&range 0 54 0 ++ &range 55 6 1 &range 61 5 0>; ++ ++ range: gpio-range { ++ #pinctrl-single,gpio-range-cells = <3>; ++ }; ++ }; ++ }; ++ ++ media { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ osal: osal { ++ compatible = "hisilicon,osal"; ++ }; ++ ++ sys: sys@12040000 { ++ compatible = "hisilicon,hi35xx_sys"; ++ reg = <0x12040000 0x10000>, <0x12050000 0x10000>, ++ <0x12110000 0x10000>, <0x12120000 0x10000>; ++ reg-names = "crg", "sys", "ddr", "misc"; ++ }; ++ ++ viu: viu@130C0000 { ++ compatible = "hisilicon,hi35xx_viu"; ++ interrupts = <0 28 4>; ++ reg = <0x130C0000 0x40000>; ++ clocks = <&clock HI3521D_VIU_CLK>; ++ clock-names = "viu"; ++ }; ++ ++ vou: vou@13020000 { ++ compatible = "hisilicon,hi35xx_vou"; ++ interrupts = <0 30 4>; ++ reg = <0x13020000 0x10000>; ++ }; ++ ++ vda: vda@13150000 { ++ compatible = "hisilicon,hi35xx_vda"; ++ interrupts = <0 43 4>; ++ reg = <0x13150000 0x10000>; ++ }; ++ ++ ive: ive@13060000 { ++ compatible = "hisilicon,hi35xx_ive"; ++ interrupts = <0 33 4>; ++ reg = <0x13060000 0x10000>; ++ }; ++ ++ vgs: vgs@13080000 { ++ compatible = "hisilicon,hi35xx_vgs"; ++ interrupts = <0 35 4>; ++ reg = <0x13080000 0x10000>; ++ }; ++ ++ vpss: vpss@13110000 { ++ compatible = "hisilicon,hi35xx_vpss"; ++ interrupts = <0 37 4>; ++ interrupt-names = "vpss0"; ++ reg = <0x13110000 0x10000>; ++ reg-names = "vpss0"; ++ }; ++ ++ audio: audio@13140000 { ++ compatible = "hisilicon,hi35xx_aiao"; ++ interrupts = <0 40 4>; ++ reg = <0x13140000 0x10000>, <0x13120000 0x10000>; ++ reg-names = "aiao", "voie"; ++ }; ++ ++ vdec: vdec@13100000 { ++ compatible = "hisilicon,hi35xx_vdec"; ++ interrupts =<0 21 4> , <0 23 4>; ++ interrupt-names ="vdm", "scd"; ++ reg = <0x13100000 0xc000>, <0x1310c000 0x4000>; ++ reg-names = "vdm", "scd"; ++ }; ++ ++ tde: tde@13050000 { ++ compatible = "hisilicon,hi35xx_tde"; ++ interrupts = <0 32 4>; ++ reg = <0x13050000 0x1000>; ++ }; ++ ++ jpgd: jpgd@13070000 { ++ compatible = "hisilicon,hi35xx_jpgd"; ++ interrupts = <0 34 4>; ++ interrupt-names = "jpgd"; ++ reg = <0x13070000 0x10000>; ++ reg-names = "jpgd"; ++ }; ++ ++ vedu: vedu@13040000 { ++ compatible = "hisilicon,hi35xx_vedu"; ++ interrupts = <0 31 4>; ++ interrupt-names = "vedu0"; ++ reg = <0x13040000 0x10000>; ++ reg-names = "vedu0"; ++ }; ++ ++ jpege: jpege@13130000 { ++ compatible = "hisilicon,hi35xx_jpege"; ++ interrupts = <0 39 4>; ++ reg = <0x13130000 0x10000>; ++ }; ++ ++ online_flag: online_flag { ++ compatible = "hisilicon,vi-vpss-online"; ++ }; ++ ++ sys_config_ctrl: sys_config_ctrl { ++ compatible = "hisilicon,sys_config_ctrl"; ++ }; ++ ++ pin_ctrl_ddr: pin_ctrl_ddr { ++ compatible = "hisilicon,pinctrl-ddrpinctrl-ddr"; ++ }; ++ ++ pin_ctrl_online: pin_ctrl_online { ++ compatible = "hisilicon,pinctrl-online"; ++ }; ++ ++ pin_ctrl_offline: pin_ctrl_offline { ++ compatible = "hisilicon,pinctrl-offline"; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/hi3531d-demb.dts b/arch/arm/boot/dts/hi3531d-demb.dts +new file mode 100644 +index 0000000..901076a +--- /dev/null ++++ b/arch/arm/boot/dts/hi3531d-demb.dts +@@ -0,0 +1,558 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/dts-v1/; ++#include "hi3531d.dtsi" ++ ++/ { ++ model = "Hisilicon HI3531D DEMO Board"; ++ compatible = "hisilicon,hi3531d"; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ enable-method = "hisilicon,hi3531d-smp"; ++ ++ cpu@0 { ++ compatible = "arm,cortex-a9"; ++ device_type = "cpu"; ++ reg = <0>; ++ next-level-cache = <&L2>; ++ }; ++ ++ cpu@1 { ++ compatible = "arm,cortex-a9"; ++ device_type = "cpu"; ++ reg = <1>; ++ next-level-cache = <&L2>; ++ }; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x40000000 0xc0000000>; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&spi_bus0{ ++ status = "okay"; ++ num-cs = <4>; ++ ++ spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <40500000>; ++ }; ++ ++ spidev@1 { ++ compatible = "spidev"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <40500000>; ++ }; ++ ++ spidev@2 { ++ compatible = "spidev"; ++ reg = <2>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <40500000>; ++ }; ++ ++ spidev@3 { ++ compatible = "spidev"; ++ reg = <3>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <40500000>; ++ }; ++}; ++ ++&hisfc { ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++}; ++ ++&hisnfc { ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ }; ++}; ++ ++&hinfc610 { ++ assigned-clocks = <&clock HI3531D_NFC_CLK>; ++ assigned-clock-rates = <200000000>; ++ ++ hinand { ++ compatible = "jedec,nand"; ++ reg = <0>; ++ nand-max-frequency = <200000000>; ++ }; ++}; ++ ++&hidmac { ++ status = "okay"; ++}; ++ ++&mdio { ++ ethphy: ethernet-phy@1 { ++ reg = <1>; ++ }; ++}; ++ ++&higmac { ++ phy-handle = <ðphy>; ++ phy-mode = "rgmii"; ++}; ++ ++&pmux { ++ i2c0_pmux: i2c0_pmux { ++ pinctrl-single,pins = < ++ 0x01CC 0x1 /*I2C0_SDA*/ ++ 0x01D0 0x1 /*I2C0_SCL*/ ++ >; ++ }; ++ ++ i2c1_pmux: i2c1_pmux { ++ pinctrl-single,pins = < ++ 0x0148 0x2 /*I2C1_SDA*/ ++ 0x014C 0x2 /*I2C1_SCL*/ ++ >; ++ }; ++ ++ vicap_demob_pmux: vicap_demob_pmux{ ++ pinctrl-single,pins = < ++ 0x0000 0x0 /*VI0_CLK*/ ++ 0x0024 0x0 /*VI1_CLK*/ ++ 0x0048 0x1 /*VI_ADC_REFCLK0*/ ++ 0x004c 0x0 /*VI2_CLK*/ ++ 0x0070 0x0 /*VI3_CLK*/ ++ 0x0094 0x1 /*VI_ADC_REFCLK1*/ ++ 0x0098 0x0 /*VI4_CLK*/ ++ 0x00bc 0x0 /*VI5_CLK*/ ++ 0x00e4 0x0 /*VI6_CLK*/ ++ 0x0108 0x0 /*VI7_CLK*/ ++ >; ++ }; ++ vicap_demopro_pmux: vicap_demopro_pmux{ ++ pinctrl-single,pins = < ++ 0x0000 0x2 /*VI_ADC_REFCLK0*/ ++ 0x0024 0x2 /*VI0_CLK*/ ++ 0x0048 0x2 /*VI1_CLK*/ ++ 0x004c 0x2 /*VI_ADC_REFCLK1*/ ++ 0x0070 0x2 /*VI2_CLK*/ ++ 0x0094 0x2 /*VI3_CLK*/ ++ 0x00bc 0x2 /*VI_ADC_REFCLK2*/ ++ 0x00E0 0x2 /*VI4_CLK */ ++ 0x0108 0x2 /*VI_ADC_REFCLK3*/ ++ 0x012C 0x2 /*VI6_CLK */ ++ >; ++ }; ++ vicap_cascade_pmux: vicap_cascade_pmux{ ++ pinctrl-single,pins = < ++ 0x0290 0x1 /*VI8_DAT14*/ ++ 0x0294 0x1 /*VI8_DAT13*/ ++ 0x0298 0x1 /*VI8_DAT12*/ ++ 0x029C 0x1 /*VI8_DAT11*/ ++ 0x02A0 0x1 /*VI8_DAT10*/ ++ 0x02A4 0x1 /*VI8_DAT9 */ ++ 0x02A8 0x1 /*VI8_DAT8 */ ++ 0x02AC 0x1 /*VI8_DAT7 */ ++ 0x02B0 0x1 /*VI8_DAT1 */ ++ 0x02B4 0x1 /*VI8_CLK */ ++ 0x02B8 0x1 /*VI8_DAT3 */ ++ 0x02BC 0x1 /*VI8_DAT4 */ ++ 0x02C0 0x1 /*VI8_DAT5 */ ++ 0x02C4 0x1 /*VI8_DAT6 */ ++ 0x02C8 0x1 /*VI8_DAT2 */ ++ 0x02CC 0x1 /*VI8_DAT0 */ ++ 0x02D0 0x1 /*VI8_DAT15*/ ++ >; ++ }; ++ ++ vicap_sck_pmux: vicap_sck_pmux{ ++ pinctrl-single,pins = < ++ 0x0000 0x2 /* 0: VI0_CLK 1: GPIO21_0 2: VI_ADC_REFCLK0 */ ++ 0x0024 0x2 /* 0: VI1_CLK 1: GPIO21_1 2: VI0_CLK */ ++ 0x0048 0x2 /* 0: GPIO21_2 1: VI_ADC_REFCLK0 2: VI1_CLK */ ++ 0x004c 0x2 /* 0: VI2_CLK 1: GPIO21_3 2: VI_ADC_REFCLK1 */ ++ 0x0070 0x2 /* 0: VI3_CLK 1: GPIO21_4 2: VI2_CLK */ ++ 0x0094 0x2 /* 0: GPIO21_5 1: VI_ADC_REFCLK1 2: VI3_CLK */ ++ 0x0098 0x2 /* 0: VI4_CLK 1: GPIO21_6 2: VI_ADC_REFCLK2 */ ++ 0x00bc 0x2 /* 0: VI5_CLK 1: GPIO21_7 2: VI4_CLK */ ++ 0x00E0 0x2 /* 0: GPIO12_1 1: VI_ADC_REFCLK2 2: VI5_CLK */ ++ 0x00e4 0x2 /* 0: VI6_CLK 1: GPIO12_2 2: VI_ADC_REFCLK3 */ ++ 0x0108 0x2 /* 0: VI7_CLK 1: GPIO15_7 2: VI6_CLK */ ++ 0x012C 0x2 /* 0: GPIO20_6 1: VI_ADC_REFCLK3 2: VI7_CLK */ ++ >; ++ }; ++ ++ vo_bt1120_pmux_demo: vo_bt1120_pmux_demo{ ++ pinctrl-single,pins = < ++ 0x0154 0x1 /*VOU_SLV_DAT15*/ ++ 0x0158 0x1 /*VOU_SLV_DAT1*/ ++ 0x015C 0x1 /*VOU1120_DAT1*/ ++ 0x0160 0x1 /*VOU1120_DAT2*/ ++ 0x0164 0x1 /*VOU1120_DAT3*/ ++ 0x0168 0x1 /*VOU1120_DAT4*/ ++ 0x016C 0x1 /*VOU1120_DAT5*/ ++ 0x0170 0x1 /*VOU1120_DAT6*/ ++ 0x0174 0x1 /*VOU1120_DAT7*/ ++ 0x0178 0x1 /*VOU1120_DAT8*/ ++ 0x017C 0x1 /*VOU1120_DAT9*/ ++ 0x0180 0x1 /*VOU1120_DAT10*/ ++ 0x0184 0x1 /*VOU1120_DAT11*/ ++ 0x0188 0x1 /*VOU1120_DAT12*/ ++ 0x018C 0x1 /*VOU1120_DAT13*/ ++ 0x0190 0x1 /*VOU1120_DAT14*/ ++ 0x0194 0x1 /*VOU1120_DAT15*/ ++ >; ++ }; ++ ++ vo_bt1120_pmux_slave1: vo_bt1120_pmux_slave1{ ++ pinctrl-single,pins = < ++ 0x01D4 0x1 /*VOU_SLV_DAT15*/ ++ 0x01D8 0x1 /*VOU_SLV_DAT1*/ ++ 0x01DC 0x1 /*VOU_SLV_DAT0*/ ++ 0x01E0 0x1 /*VOU_SLV_DAT9*/ ++ 0x01E4 0x1 /*VOU_SLV_DAT14*/ ++ 0x01E8 0x1 /*VOU_SLV_DAT8*/ ++ 0x01EC 0x1 /*VOU_SLV_CLK*/ ++ 0x01F0 0x1 /*VOU_SLV_DAT2*/ ++ 0x01F4 0x1 /*VOU_SLV_DAT3*/ ++ 0x01F8 0x1 /*VOU_SLV_DAT5 */ ++ 0x01FC 0x1 /*VOU_SLV_DAT4 */ ++ 0x0200 0x1 /*VOU_SLV_DAT11*/ ++ 0x0204 0x1 /*VOU_SLV_DAT10*/ ++ 0x0208 0x1 /*VOU_SLV_DAT7 */ ++ 0x020C 0x1 /*VOU_SLV_DAT6 */ ++ 0x0210 0x1 /*VOU_SLV_DAT12*/ ++ 0x0214 0x1 /*VOU_SLV_DAT13*/ ++ >; ++ }; ++ ++ vo_bt1120_pmux_slave2: vo_bt1120_pmux_slave2{ ++ pinctrl-single,pins = < ++ 0x01D4 0x1 /*VOU_SLV_DAT15*/ ++ 0x01D8 0x1 /*VOU_SLV_DAT1*/ ++ 0x01DC 0x1 /*VOU_SLV_DAT0*/ ++ 0x01E0 0x1 /*VOU_SLV_DAT9*/ ++ 0x01E4 0x1 /*VOU_SLV_DAT14*/ ++ 0x01E8 0x1 /*VOU_SLV_DAT8*/ ++ 0x01EC 0x1 /*VOU_SLV_CLK*/ ++ 0x01F0 0x1 /*VOU_SLV_DAT2*/ ++ 0x01F4 0x1 /*VOU_SLV_DAT3*/ ++ 0x01F8 0x1 /*VOU_SLV_DAT5 */ ++ 0x01FC 0x1 /*VOU_SLV_DAT4 */ ++ 0x0200 0x1 /*VOU_SLV_DAT11*/ ++ 0x0204 0x1 /*VOU_SLV_DAT10*/ ++ 0x0208 0x1 /*VOU_SLV_DAT7 */ ++ 0x020C 0x1 /*VOU_SLV_DAT6 */ ++ 0x0210 0x1 /*VOU_SLV_DAT12*/ ++ 0x0214 0x1 /*VOU_SLV_DAT13*/ ++ >; ++ }; ++ ++ ++ vo_vga_pmux: vo_vga_pmux{ ++ pinctrl-single,pins = < ++ 0x01A4 0x1 /*VGA_HS*/ ++ 0x01A8 0X1 /*VGA_VS*/ ++ >; ++ }; ++ ++ i2s0_pmux: i2s0_pmux { ++ pinctrl-single,pins = < ++ 0x0130 0x1 /* 0: GPIO11_0 1: I2S0_BCLK_RX */ ++ 0x0134 0x1 /* 0: GPIO11_1 1: I2S0_WS_RX */ ++ 0x0138 0x1 /* 0: GPIO11_2 1: I2S0_SD_RX */ ++ 0x01B4 0x1 /* 0: GPIO12_0 1: I2S2_SD_RX */ ++ 0x01BC 0x1 /* 0: GPIO12_4 1: I2S2_MCLK */ ++ >; ++ }; ++ ++ i2s1_pmux: i2s1_pmux { ++ pinctrl-single,pins = < ++ 0x013c 0x1 /*I2S1_BCLK_RX*/ ++ 0x0140 0x1 /*I2S1_WS_RX*/ ++ 0x0144 0x1 /*I2S1_SD_RX*/ ++ >; ++ }; ++ ++ i2s2_pmux: i2s2_pmux { ++ pinctrl-single,pins = < ++ 0x01AC 0x1 /*I2S2_BCLK_RX*/ ++ 0x01B0 0x1 /*I2S2_WS_RX*/ ++ 0x01B8 0x1 /*I2S2_SD_RX*/ ++ >; ++ }; ++ ++ i2s3_pmux: i2s3_pmux { ++ pinctrl-single,pins = < ++ 0x0198 0x1 /*I2S3_BCLK_RX*/ ++ 0x019C 0x1 /*I2S3_WS_RX*/ ++ 0x01A0 0x1 /*I2S3_SD_RX*/ ++ >; ++ }; ++ ++ uart0_pmux: uart0_pmux { ++ pinctrl-single,pins = < ++ 0x0158 0x2 /*0: GPIO9_0 1: VOU1120_DAT0 2: UART0_RXD*/ ++ 0x015c 0x2 /*0: GPIO9_1 1: VOU1120_DAT1 2: UART0_TXD*/ ++ >; ++ }; ++}; ++ ++&sys_config_ctrl { ++ ++ padctrl-ability,demo = < ++ 0x120f093c 0x130 ++ 0x120f0940 0x130 ++ 0x120f0944 0x130 ++ 0x120f09bc 0x130 ++ 0x120f09c0 0x130 ++ 0x120f09c8 0x530 ++ 0x120f09a8 0x130 ++ 0x120f09ac 0x130 ++ 0x120f09b0 0x530 ++ 0x120f0b1c 0x130 ++ 0x120f0b24 0x130 ++ 0x120f0b28 0x130 ++ 0x120f0964 0x40 ++ 0x120f0968 0x210 ++ 0x120f096c 0x10 ++ 0x120f0970 0x210 ++ 0x120f0974 0x10 ++ 0x120f0978 0x10 ++ 0x120f097c 0x10 ++ 0x120f0980 0x210 ++ 0x120f0984 0x10 ++ 0x120f0988 0x410 ++ 0x120f098c 0x410 ++ 0x120f0990 0x410 ++ 0x120f0994 0x10 ++ 0x120f0998 0x10 ++ 0x120f099c 0x10 ++ 0x120f09a0 0x10 ++ 0x120f09a4 0x10 ++ 0x120f09b4 0x40 ++ 0x120f09b8 0x40 ++ >; ++ ++ padctrl-ability,sck = < ++ 0x120f093c 0x130 ++ 0x120f0940 0x130 ++ 0x120f0944 0x130 ++ 0x120f09bc 0x130 ++ 0x120f09c0 0x130 ++ 0x120f09c8 0x530 ++ 0x120f09a8 0x130 ++ 0x120f09ac 0x130 ++ 0x120f09b0 0x530 ++ 0x120f0b1c 0x130 ++ 0x120f0b24 0x130 ++ 0x120f0b28 0x130 ++ 0x120f0964 0x40 ++ 0x120f0968 0x210 ++ 0x120f096c 0x10 ++ 0x120f0970 0x210 ++ 0x120f0974 0x10 ++ 0x120f0978 0x10 ++ 0x120f097c 0x10 ++ 0x120f0980 0x210 ++ 0x120f0984 0x10 ++ 0x120f0988 0x410 ++ 0x120f098c 0x410 ++ 0x120f0990 0x410 ++ 0x120f0994 0x10 ++ 0x120f0998 0x10 ++ 0x120f099c 0x10 ++ 0x120f09a0 0x10 ++ 0x120f09a4 0x10 ++ 0x120f09b4 0x40 ++ 0x120f09b8 0x40 ++ 0x120f0930 0x130/* I2S0_BCLK_RX------I2S0_BCLK_RX */ ++ 0x120f0934 0x130/* I2S0_WS_RX------I2S0_WS_RX */ ++ 0x120f0938 0x130/* I2S0_SD_RX------I2S0_SD_RX */ ++ 0x120f09c4 0x130/* I2S2_SD_RX------I2S2_SD_RX */ ++ 0x120f09cc 0x530/* I2S2_MCLK------I2S2_MCLK */ ++ >; ++ ++ padctrl-ability,slave1 = < ++ 0x120f093c 0x130 ++ 0x120f0940 0x130 ++ 0x120f0944 0x130 ++ 0x120f09bc 0x130 ++ 0x120f09c0 0x130 ++ 0x120f09c8 0x530 ++ 0x120f0b1c 0x130 ++ 0x120f0b24 0x130 ++ 0x120f0b28 0x130 ++ 0x120f0ac4 0x330 ++ 0x120f0adc 0x130 ++ 0x120f0ac0 0x330 ++ 0x120f0ad8 0x130 ++ 0x120f0ac8 0x130 ++ 0x120f0acc 0x130 ++ 0x120f0ad0 0x130 ++ 0x120f0ad4 0x130 ++ 0x120f0abc 0x130 ++ 0x120f0ab8 0x130 ++ 0x120f0ab4 0x130 ++ 0x120f0ab0 0x130 ++ 0x120f0aac 0x130 ++ 0x120f0aa8 0x130 ++ 0x120f0aa4 0x130 ++ 0x120f0aa0 0x130 ++ 0x120f0ae0 0x130 ++ 0x120f09b4 0x40 ++ 0x120f09b8 0x40 ++ 0x120f09fc 0xD0 ++ 0x120f09ec 0x20 ++ 0x120f09e8 0x20 ++ 0x120f0a00 0x20 ++ 0x120f0a04 0x20 ++ 0x120f0a0c 0x20 ++ 0x120f0a08 0x220 ++ 0x120f0a1c 0x20 ++ 0x120f0a18 0x220 ++ 0x120f09f8 0x20 ++ 0x120f09f0 0x20 ++ 0x120f0a14 0x20 ++ 0x120f0a10 0x20 ++ 0x120f0a20 0x220 ++ 0x120f0a24 0x20 ++ 0x120f09f4 0x20 ++ 0x120f09e4 0x20 ++ 0x120f09fc 0xD0 ++ 0x12040178 0x40 ++ >; ++ ++padctrl-ability,slave2 = < ++ 0x120f093c 0x130 ++ 0x120f0940 0x130 ++ 0x120f0944 0x130 ++ 0x120f09bc 0x130 ++ 0x120f09c0 0x130 ++ 0x120f09c8 0x530 ++ 0x120f09fc 0xD0 ++ 0x120f09ec 0x20 ++ 0x120f09e8 0x20 ++ 0x120f0a00 0x20 ++ 0x120f0a04 0x20 ++ 0x120f0a0c 0x20 ++ 0x120f0a08 0x220 ++ 0x120f0a1c 0x20 ++ 0x120f0a18 0x220 ++ 0x120f09f8 0x20 ++ 0x120f09f0 0x20 ++ 0x120f0a14 0x20 ++ 0x120f0a10 0x20 ++ 0x120f0a20 0x220 ++ 0x120f0a24 0x20 ++ 0x120f09f4 0x20 ++ 0x120f09e4 0x20 ++ 0x12040178 0x40 ++ >; ++ ++ sysctrl-ddr,pins = < ++ 0x1212007c 0x35553301 ++ 0x12120080 0x33355633 ++ 0x12120084 0x66266623 ++ 0x12120088 0x66666666 ++ 0x12120054 0x80018001 ++ 0x12040094 0x0000FFFF /*PPC*/ ++ 0x12040098 0x01ffff1f ++ 0x1204009c 0x8888 /*PT clk default 9999*/ ++ 0x120400a0 0x88888 ++ 0x12040168 0x00000f55 /*ADC*/ ++ >; ++ ++ dllctrl-ddr,pins = < ++ 0x120401e0 0x0 /*DLL rst, disable*/ ++ 0x120401ec 0x0 ++ 0x120401f8 0x0 ++ 0x12040204 0x0 ++ 0x12040210 0x0 ++ 0x1204021c 0x0 ++ 0x12040228 0x0 ++ 0x12040234 0x0 ++ 0x120401e0 0x4 /*DLL rst, disable*/ ++ 0x120401ec 0x4 ++ 0x120401f8 0x4 ++ 0x12040204 0x4 ++ 0x12040210 0x4 ++ 0x1204021c 0x4 ++ 0x12040228 0x4 ++ 0x12040234 0x4 ++ 0x120401e0 0x6 /*DLL 150M and DLL rst, disable*/ ++ 0x120401ec 0x6 ++ 0x120401f8 0x6 ++ 0x12040204 0x6 ++ 0x12040210 0x6 ++ 0x1204021c 0x6 ++ 0x12040228 0x6 ++ 0x12040234 0x6 ++ 0x120401e0 0x7 /*DLL 150M and DLL rst, enable*/ ++ 0x120401ec 0x7 ++ 0x120401f8 0x7 ++ 0x12040204 0x7 ++ 0x12040210 0x7 ++ 0x1204021c 0x7 ++ 0x12040228 0x7 ++ 0x12040234 0x7 ++ 0x120401e0 0x3 /*DLL 150M and DLL unrst, enable*/ ++ 0x120401ec 0x3 ++ 0x120401f8 0x3 ++ 0x12040204 0x3 ++ 0x12040210 0x3 ++ 0x1204021c 0x3 ++ 0x12040228 0x3 ++ 0x12040234 0x3 ++ 0x120401e4 0x10 /*dll_slave_en:1,dll_stop:0*/ ++ 0x120401F0 0x10 ++ 0x120401fC 0x10 ++ 0x12040208 0x10 ++ 0x12040214 0x10 ++ 0x12040220 0x10 ++ 0x1204022c 0x10 ++ 0x12040238 0x10 ++ >; ++ ++ pinctrl-names = "demo", "demopro", "slave1", "slave2", "sck", "default"; ++ pinctrl-0 = <&vo_bt1120_pmux_demo &vo_vga_pmux &vicap_demob_pmux &i2c0_pmux &i2c1_pmux &i2s1_pmux &i2s2_pmux &i2s3_pmux>; ++ pinctrl-1 = <&vo_bt1120_pmux_demo &vo_vga_pmux &vicap_demopro_pmux &i2c0_pmux &i2c1_pmux &i2s1_pmux &i2s2_pmux &i2s3_pmux>; ++ pinctrl-2 = <&vo_bt1120_pmux_slave1 &vo_vga_pmux &vicap_demob_pmux &i2c0_pmux &i2c1_pmux &i2s1_pmux &i2s2_pmux &i2s3_pmux &vicap_cascade_pmux>; ++ pinctrl-3 = <&vo_bt1120_pmux_slave2 &vo_vga_pmux &vicap_demob_pmux &i2c0_pmux &i2c1_pmux &i2s1_pmux &i2s2_pmux &i2s3_pmux &uart0_pmux>; ++ pinctrl-4 = <&vo_bt1120_pmux_demo &vo_vga_pmux &vicap_sck_pmux &i2c0_pmux &i2c1_pmux &i2s1_pmux &i2s2_pmux &i2s3_pmux &i2s0_pmux>; ++ pinctrl-5 = <>; ++}; +diff --git a/arch/arm/boot/dts/hi3531d.dtsi b/arch/arm/boot/dts/hi3531d.dtsi +new file mode 100644 +index 0000000..aac76f7 +--- /dev/null ++++ b/arch/arm/boot/dts/hi3531d.dtsi +@@ -0,0 +1,417 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "skeleton.dtsi" ++#include ++/ { ++ aliases { ++ fmc = &fmc; ++ serial0 = &uart0; ++ spi0 = &spi_bus0; ++ }; ++ ++ clock: clock@12040000 { ++ compatible = "hisilicon,hi3531d-clock"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ #clock-cells = <1>; ++ #reset-cells = <2>; ++ reg = <0x12040000 0x1000>; ++ }; ++ ++ gic: interrupt-controller@10300000 { ++ compatible = "arm,cortex-a9-gic"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ /* gic dist base, gic cpu base , no virtual support */ ++ reg = <0x10301000 0x1000>, <0x10300100 0x100>; ++ }; ++ ++ soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ sysctrl: system-controller@12050000 { ++ compatible = "hisilicon,sysctrl"; ++ reg = <0x12050000 0x1000>; ++ reboot-offset = <0x4>; ++ #clock-cells = <1>; ++ }; ++ ++ pmu { ++ compatible = "arm,cortex-a9-pmu"; ++ interrupts = <0 25 4>, ++ <0 54 4>; ++ }; ++ ++ amba { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "arm,amba-bus"; ++ ranges; ++ ++ L2: l2-cache@10700000 { ++ compatible = "arm,pl310-cache"; ++ reg = <0x10700000 0x10000>; ++ interrupts = <0 55 4>; ++ cache-unified; ++ cache-level = <2>; ++ }; ++ ++ uart0: uart@12080000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12080000 0x1000>; ++ interrupts = <0 6 4>; ++ clocks = <&clock HI3531D_UART0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart1: uart@121090000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12090000 0x1000>; ++ interrupts = <0 7 4>; ++ clocks = <&clock HI3531D_UART1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart2: uart@120a0000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x120a0000 0x1000>; ++ interrupts = <0 8 4>; ++ clocks = <&clock HI3531D_UART2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart3: uart@12130000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12130000 0x1000>; ++ interrupts = <0 20 4>; ++ clocks = <&clock HI3531D_UART3_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ timer@0x12000000 { ++ compatible = "hisilicon,timer"; ++ /* timer0 & timer1 & timer2*/ ++ reg = <0x12000000 0x20>, /* clocksource */ ++ <0x12000020 0x20>, /* local timer for each cpu */ ++ <0x12010000 0x20>; ++ interrupts = <0 1 4>, <0 2 4>; /* irq of local timer */ ++ clocks = <&sysctrl HI3531D_TIME0_0_CLK>; ++ clock-names = "timer00"; ++ }; ++ }; ++ ++ /* dual timer 0 and 1 have used for clocksource and local timer */ ++ dual_timer2: dual_timer@12020000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer4 & timer5 */ ++ interrupts = <0 3 4>; ++ reg = <0x12020000 0x1000>; ++ clocks = <&sysctrl HI3531D_TIME2_4_CLK>, ++ <&sysctrl HI3531D_TIME2_5_CLK>, ++ <&clock HI3531D_PERIAXI_CLK>; ++ clock-names = "timer4", "timer5", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer3: dual_timer@12030000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer4 & timer5 */ ++ interrupts = <0 4 4>; ++ reg = <0x12030000 0x1000>; ++ clocks = <&sysctrl HI3531D_TIME3_6_CLK>, ++ <&sysctrl HI3531D_TIME3_7_CLK>, ++ <&clock HI3531D_PERIAXI_CLK>; ++ clock-names = "timer6", "timer7", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ spi_bus0: spi@120d0000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x120d0000 0x1000>, <0x12120014 0x4>; ++ interrupts = <0 14 4>; ++ clocks = <&clock HI3531D_SPI0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ hisi,spi_cs_sb = <0>; ++ hisi,spi_cs_mask_bit = <0x00000007>; ++ }; ++ ++ sata_phy: phy@11010000 { ++ compatible = "hisilicon,hisi-sata-nano-phy"; ++ reg = <0x11010000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ++ ahci: sata@11010000 { ++ compatible = "hisilicon,hisi-ahci"; ++ reg = <0x11010000 0x1000>; ++ interrupts = <0 17 4>; ++ phys = <&sata_phy>; ++ phy-names = "sata-phy"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ usb_phy: usbphy { ++ compatible = "hisilicon,hi3531d-usb2-phy"; ++ reg = <0x12040000 0x1000>, <0x12120000 0x1000>, ++ <0x12010000 0x1000>; ++ }; ++ ++ usb3_phy: phy3 { ++ compatible = "hisilicon,hi3531d-usb3-phy"; ++ reg = <0x11000000 0x10000>, <0x12040000 0x10000>, ++ <0x12120000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ++ ehci@0x10120000 { ++ compatible = "generic-ehci"; ++ reg = <0x100c0000 0x10000>; ++ interrupts = <0 19 4>; ++ }; ++ ++ ohci@0x10110000 { ++ compatible = "generic-ohci"; ++ reg = <0x100b0000 0x10000>; ++ interrupts = <0 18 4>; ++ }; ++ ++ xhci@0x10180000 { ++ compatible = "hisilicon,hi3519-xhci", "generic-xhci"; ++ reg = <0x11000000 0x10000>; ++ interrupts = <0 22 4>; ++ }; ++ ++ mdio: mdio@100a03c0 { ++ compatible = "hisilicon,hisi-gemac-mdio"; ++ reg = <0x100a03c0 0x20>; ++ clocks = <&clock HI3531D_ETH_CLK>; ++ resets = <&clock 0x14c 5>; ++ reset-names = "phy_reset"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ higmac: ethernet@100a0000 { ++ compatible = "hisilicon,higmac"; ++ reg = <0x100a0000 0x1000>,<0x1204015c 0x4>; ++ interrupts = <0 16 4>; ++ ++ clocks = <&clock HI3531D_ETH_CLK>, ++ <&clock HI3531D_ETH_MACIF_CLK>; ++ clock-names = "higmac_clk", ++ "macif_clk"; ++ ++ resets = <&clock 0x14c 0>, ++ <&clock 0x14c 2>, ++ <&clock 0x14c 5>; ++ reset-names = "port_reset", ++ "macif_reset", ++ "phy_reset"; ++ ++ mac-address = [00 00 00 00 00 00]; ++ }; ++ ++ fmc: flash-memory-controller@10000000 { ++ compatible = "hisilicon,hisi-fmc"; ++ reg = <0x10000000 0x1000>, <0x14000000 0x10000>; ++ reg-names = "control", "memory"; ++ clocks = <&clock HI3531D_FMC_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hisfc:spi_nor_controller { ++ compatible = "hisilicon,hisi-sfc"; ++ assigned-clocks = <&clock HI3531D_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hisnfc:spi_nand_controller { ++ compatible = "hisilicon,hisi-spi-nand"; ++ assigned-clocks = <&clock HI3531D_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ ++ hidmac: hidma-controller@10060000 { ++ compatible = "hisilicon,hisi-dmac"; ++ reg = <0x10060000 0x1000>; ++ interrupts = <0 10 4>; ++ clocks = <&clock HI3531D_DMAC_CLK>; ++ clock-names = "dmac_clk"; ++ resets = <&clock 0x144 0>; ++ reset-names = "dma-reset"; ++ #dma-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ pmux: pinmux@120F0000 { ++ compatible = "pinctrl-single"; ++ reg = <0x120F0000 0x3A8>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ #gpio-range-cells = <3>; ++ ranges; ++ ++ pinctrl-single,register-width = <32>; ++ pinctrl-single,function-mask = <7>; ++ /* pin base, nr pins & gpio function */ ++ pinctrl-single,gpio-range = <&range 0 54 0 ++ &range 55 6 1 &range 61 5 0>; ++ ++ range: gpio-range { ++ #pinctrl-single,gpio-range-cells = <3>; ++ }; ++ }; ++ ++ hinfc610: parallel-nand-controller@10010000 { ++ compatible = "hisilicon,hinfc610-nand"; ++ reg = <0x10010000 0x1000>, <0x15000000 0x10000>; ++ reg-names = "control", "memory"; ++ clocks = <&clock HI3531D_NFC_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ ++ media { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ osal: osal { ++ compatible = "hisilicon,osal"; ++ }; ++ ++ sys: sys@12040000 { ++ compatible = "hisilicon,hi35xx_sys"; ++ reg = <0x12040000 0x10000>, <0x12050000 0x10000>, ++ <0x12110000 0x10000>, <0x12120000 0x10000>; ++ reg-names = "crg", "sys", "ddr", "misc"; ++ }; ++ ++ viu: viu@130C0000 { ++ compatible = "hisilicon,hi35xx_viu"; ++ interrupts = <0 28 4>; ++ reg = <0x130C0000 0x40000>; ++ reg-names = "viu"; ++ clocks = <&clock HI3531D_VIU_CLK>; ++ clock-names = "viu"; ++ }; ++ ++ vou: vou@13020000 { ++ compatible = "hisilicon,hi35xx_vou"; ++ interrupts = <0 30 4>; ++ reg = <0x13020000 0x10000>; ++ }; ++ ++ vda: vda@13090000 { ++ compatible = "hisilicon,hi35xx_vda"; ++ interrupts = <0 43 4>; ++ reg = <0x13090000 0x10000>; ++ }; ++ ++ ive: ive@13060000 { ++ compatible = "hisilicon,hi35xx_ive"; ++ interrupts = <0 33 4>; ++ reg = <0x13060000 0x10000>; ++ }; ++ ++ vgs: vgs@13150000 { ++ compatible = "hisilicon,hi35xx_vgs"; ++ interrupts = <0 35 4>; ++ reg = <0x13150000 0x10000>; ++ }; ++ ++ vpss: vpss@13080000 { ++ compatible = "hisilicon,hi35xx_vpss"; ++ interrupts = <0 37 4>, <0 46 4>, <0 47 4>; ++ interrupt-names = "vpss0", "vpss1", "vpss2"; ++ reg = <0x13080000 0x10000>, <0x13110000 0x10000>, <0x13180000 0x10000>; ++ reg-names = "vpss0", "vpss1", "vpss2"; ++ }; ++ ++ audio: audio@13140000 { ++ compatible = "hisilicon,hi35xx_aiao"; ++ interrupts = <0 40 4>; ++ reg = <0x13140000 0x10000>, <0x13120000 0x10000>; ++ reg-names = "aiao", "voie"; ++ }; ++ ++ vdec: vdec@13170000 { ++ compatible = "hisilicon,hi35xx_vdec"; ++ interrupts = <0 81 4>, <0 83 4>; ++ interrupt-names = "vdm", "scd"; ++ reg = <0x13170000 0xc000>, <0x1317c000 0x4000>; ++ reg-names = "vdm", "scd"; ++ }; ++ ++ tde: tde@13050000 { ++ compatible = "hisilicon,hi35xx_tde"; ++ interrupts = <0 32 4>; ++ reg = <0x13050000 0x1000>; ++ }; ++ ++ jpgd: jpgd@13070000 { ++ compatible = "hisilicon,hi35xx_jpgd"; ++ interrupts = <0 34 4>; ++ interrupt-names = "jpgd"; ++ reg = <0x13070000 0x10000>; ++ reg-names = "jpgd"; ++ }; ++ ++ vedu: vedu@13040000 { ++ compatible = "hisilicon,hi35xx_vedu"; ++ interrupts = <0 31 4>, <0 36 4>; ++ interrupt-names = "vedu0", "vedu1"; ++ reg = <0x13040000 0x10000>, <0x13100000 0x10000>; ++ reg-names = "vedu0", "vedu1"; ++ }; ++ ++ jpege: jpege@13130000 { ++ compatible = "hisilicon,hi35xx_jpege"; ++ interrupts = <0 39 4>; ++ reg = <0x13130000 0x10000>; ++ }; ++ ++ sys_config_ctrl: sys_config_ctrl { ++ compatible = "hisilicon,sys_config_ctrl"; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/hi3536c-demb.dts b/arch/arm/boot/dts/hi3536c-demb.dts +new file mode 100644 +index 0000000..afdbced +--- /dev/null ++++ b/arch/arm/boot/dts/hi3536c-demb.dts +@@ -0,0 +1,199 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/dts-v1/; ++#include "hi3536c.dtsi" ++ ++/ { ++ model = "Hisilicon HI3536C DEMO Board"; ++ compatible = "hisilicon,hi3536c"; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ enable-method = "hisilicon,hi3536c-smp"; ++ ++ cpu@0 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ clock-frequency = ; ++ reg = <0>; ++ }; ++ ++ cpu@1 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ clock-frequency = ; ++ reg = <1>; ++ }; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x20000000>; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&rtc { ++ status = "okay"; ++}; ++ ++&spi_bus0{ ++ status = "okay"; ++ num-cs = <2>; ++ ++ spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <37500000>; ++ }; ++ ++ spidev@1 { ++ compatible = "spidev"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <37500000>; ++ }; ++}; ++ ++&hisfc { ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++}; ++ ++&hisnfc { ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ }; ++}; ++ ++&hidmac { ++ status = "okay"; ++}; ++ ++&mdio { ++ ethphy: ethernet-phy@1 { ++ reg = <1>; ++ }; ++}; ++&mdio1 { ++ ethphy1: ethernet-phy@2 { ++ reg = <2>; ++ }; ++}; ++ ++&higmac { ++ phy-handle = <ðphy>; ++ phy-mode = "rgmii"; ++}; ++&higmac1 { ++ phy-handle = <ðphy1>; ++ phy-mode = "rgmii"; ++}; ++ ++ ++&pmux { ++ ++ vo_vga_pmux: vo_vga_pmux{ ++ pinctrl-single,pins = < ++ 0x0174 0x1 ++ 0x017c 0x1 ++ 0x0180 0x1 ++ >; ++ }; ++ ++ vo_hdmi_pmux: vo_hdmi_pmux{ ++ pinctrl-single,pins = < ++ 0x0098 0x1 ++ 0x009c 0X1 ++ >; ++ }; ++ ++ i2c0_pmux: i2c0_pmux { ++ pinctrl-single,pins = < ++ 0x00e0 0x1 ++ 0x00e4 0x1 ++ >; ++ }; ++ ++ i2s0_pmux: i2s0_pmux { ++ pinctrl-single,pins = < ++ 0x00a0 0x1 ++ 0x00a4 0x1 ++ 0x00a8 0x1 ++ >; ++ }; ++ ++ i2s1_pmux: i2s1_pmux { ++ pinctrl-single,pins = < ++ 0x00b0 0x1 ++ 0x00b4 0x1 ++ >; ++ }; ++ ++ i2s2_sck_pmux: i2s2_sck_pmux { ++ pinctrl-single,pins = < ++ 0x00b8 0x1 ++ 0x00bc 0x1 ++ 0x00c0 0x1 ++ 0x00ac 0x2 ++ >; ++ }; ++}; ++ ++&sys_config_ctrl { ++ padctrl-ability,demo = < ++ 0x120f08a0 0x120 ++ 0x120f08a4 0x130 ++ 0x120f08a8 0x130 ++ 0x120f08ac 0x120 ++ 0x120f08b0 0x130 ++ 0x120f08b4 0x130 ++ 0x120f08b8 0x120 ++ 0x120f08bc 0x130 ++ 0x120f08c0 0x130 ++ 0x120f0898 0x40 ++ 0x120f089c 0x40 ++ >; ++ ++ sysctrl-ddr,pins = < ++ 0x1212007c 0x35533201 ++ 0x12120080 0x25335526 ++ 0x12120084 0x66666666 ++ 0x12120094 0x65 ++ >; ++ ++ pinctrl-names = "demo", "sck", "default"; ++ pinctrl-0 = <&i2c0_pmux &i2s1_pmux &i2s2_sck_pmux &vo_hdmi_pmux &vo_vga_pmux>; ++ pinctrl-1 = <&i2s0_pmux &i2s1_pmux &i2s2_sck_pmux &vo_hdmi_pmux &vo_vga_pmux>; ++ pinctrl-2 = <>; ++}; +diff --git a/arch/arm/boot/dts/hi3536c.dtsi b/arch/arm/boot/dts/hi3536c.dtsi +new file mode 100644 +index 0000000..8605c9d +--- /dev/null ++++ b/arch/arm/boot/dts/hi3536c.dtsi +@@ -0,0 +1,408 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "skeleton.dtsi" ++#include ++/ { ++ aliases { ++ fmc = &fmc; ++ serial0 = &uart0; ++ spi0 = &spi_bus0; ++ }; ++ ++ clock: clock@12040000 { ++ compatible = "hisilicon,hi3536c-clock"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ #clock-cells = <1>; ++ #reset-cells = <2>; ++ reg = <0x12040000 0x1000>; ++ }; ++ ++ gic: interrupt-controller@10300000 { ++ compatible = "arm,cortex-a7-gic"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ /* gic dist base, gic cpu base , no virtual support */ ++ reg = <0x10301000 0x1000>, <0x10302000 0x100>; ++ }; ++ ++ soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ rtc: rtc@120b0000 { ++ compatible = "hisilicon,hi35xx-rtc"; ++ interrupts = <0 5 4>; ++ reg = <0x120b0000 0x10000>; ++ status = "disabled"; ++ }; ++ sysctrl: system-controller@12050000 { ++ compatible = "hisilicon,sysctrl"; ++ reg = <0x12050000 0x1000>; ++ reboot-offset = <0x4>; ++ #clock-cells = <1>; ++ }; ++ ++ pmu { ++ compatible = "arm,cortex-a7-pmu"; ++ interrupts = <0 54 4>, ++ <0 48 4>; ++ }; ++ ++ amba { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "arm,amba-bus"; ++ ranges; ++ ++ uart0: uart@12080000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12080000 0x1000>; ++ interrupts = <0 6 4>; ++ clocks = <&clock HI3536C_UART0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart1: uart@121090000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12090000 0x1000>; ++ interrupts = <0 7 4>; ++ clocks = <&clock HI3536C_UART1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart2: uart@120a0000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x120a0000 0x1000>; ++ interrupts = <0 8 4>; ++ clocks = <&clock HI3536C_UART2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ timer@0x12000000 { ++ compatible = "hisilicon,timer"; ++ /* timer0 & timer1 & timer2*/ ++ reg = <0x12000000 0x20>, /* clocksource */ ++ <0x12000020 0x20>, /* local timer for each cpu */ ++ <0x12010000 0x20>; ++ interrupts = <0 1 4>, <0 2 4>; /* irq of local timer */ ++ clocks = <&sysctrl HI3536C_TIME0_0_CLK>; ++ clock-names = "timer00"; ++ }; ++ }; ++ ++ /* dual timer 0 and 1 have used for clocksource and local timer */ ++ dual_timer2: dual_timer@12020000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer4 & timer5 */ ++ interrupts = <0 3 4>; ++ reg = <0x12020000 0x1000>; ++ clocks = <&sysctrl HI3536C_TIME2_4_CLK>, ++ <&sysctrl HI3536C_TIME2_5_CLK>, ++ <&clock HI3536C_SYSAXI_CLK>; ++ clock-names = "timer4", "timer5", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer3: dual_timer@12030000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ /* timer6 & timer7 */ ++ interrupts = <0 4 4>; ++ reg = <0x12030000 0x1000>; ++ clocks = <&sysctrl HI3536C_TIME3_6_CLK>, ++ <&sysctrl HI3536C_TIME3_7_CLK>, ++ <&clock HI3536C_SYSAXI_CLK>; ++ clock-names = "timer6", "timer7", "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ spi_bus0: spi@120d0000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x120d0000 0x1000>, <0x12120014 0x4>; ++ interrupts = <0 14 4>; ++ clocks = <&clock HI3536C_SPI0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ hisi,spi_cs_sb = <0>; ++ hisi,spi_cs_mask_bit = <0x00000003>; ++ }; ++ ++ sata_phy: phy@11010000 { ++ compatible = "hisilicon,hisi-sata-nano-phy"; ++ reg = <0x11010000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ++ ahci: sata@11010000 { ++ compatible = "hisilicon,hisi-ahci"; ++ reg = <0x11010000 0x1000>; ++ interrupts = <0 17 4>; ++ phys = <&sata_phy>; ++ phy-names = "sata-phy"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ usb_phy: usbphy { ++ compatible = "hisilicon,hisi-usb-phy"; ++ reg = <0x12120000 0x1000>, <0x12040000 0x1000>; ++ }; ++ ++ ehci@0x10120000 { ++ compatible = "generic-ehci"; ++ reg = <0x10040000 0x10000>; ++ interrupts = <0 19 4>; ++ }; ++ ++ ohci@0x10110000 { ++ compatible = "generic-ohci"; ++ reg = <0x10030000 0x10000>; ++ interrupts = <0 18 4>; ++ }; ++ ++ mdio: mdio@100a03c0 { ++ compatible = "hisilicon,hisi-gemac-mdio"; ++ reg = <0x100a03c0 0x20>; ++ clocks = <&clock HI3536C_ETH_CLK>; ++ resets = <&clock 0x14c 5>; ++ reset-names = "phy_reset"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ mdio1: mdio@100a13c0 { ++ compatible = "hisilicon,hisi-gemac-mdio"; ++ reg = <0x100a13c0 0x20>; ++ clocks = <&clock HI3536C_ETH1_CLK>; ++ resets = <&clock 0x14c 13>; ++ reset-names = "phy_reset"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ higmac: ethernet@100a0000 { ++ compatible = "hisilicon,higmac-v5"; ++ reg = <0x100a0000 0x1000>,<0x100a300c 0x4>; ++ interrupts = <0 16 4>, <0 61 4>, <0 62 4>, <0 63 4>; ++ ++ clocks = <&clock HI3536C_ETH_CLK>, ++ <&clock HI3536C_ETH_MACIF_CLK>; ++ clock-names = "higmac_clk", ++ "macif_clk"; ++ ++ resets = <&clock 0x14c 0>, ++ <&clock 0x14c 2>, ++ <&clock 0x14c 5>; ++ reset-names = "port_reset", ++ "macif_reset", ++ "phy_reset"; ++ ++ mac-address = [00 00 00 00 00 00]; ++ }; ++ higmac1: ethernet@100a1000 { ++ compatible = "hisilicon,higmac-v5"; ++ reg = <0x100a1000 0x1000>,<0x100a3010 0x4>; ++ interrupts = <0 16 4>, <0 61 4>, <0 62 4>, <0 63 4>; ++ ++ clocks = <&clock HI3536C_ETH1_CLK>, ++ <&clock HI3536C_ETH_MACIF1_CLK>; ++ clock-names = "higmac_clk", ++ "macif_clk"; ++ ++ resets = <&clock 0x14c 8>, ++ <&clock 0x14c 10>, ++ <&clock 0x14c 13>; ++ reset-names = "port_reset", ++ "macif_reset", ++ "phy_reset"; ++ ++ mac-address = [00 00 00 00 00 00]; ++ }; ++ ++ ++ fmc: flash-memory-controller@10000000 { ++ compatible = "hisilicon,hisi-fmc"; ++ reg = <0x10000000 0x1000>, <0x14000000 0x10000>; ++ reg-names = "control", "memory"; ++ clocks = <&clock HI3536C_FMC_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hisfc:spi_nor_controller { ++ compatible = "hisilicon,hisi-sfc"; ++ assigned-clocks = <&clock HI3536C_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hisnfc:spi_nand_controller { ++ compatible = "hisilicon,hisi-spi-nand"; ++ assigned-clocks = <&clock HI3536C_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ ++ hidmac: hidma-controller@10060000 { ++ compatible = "hisilicon,hisi-dmac"; ++ reg = <0x10060000 0x1000>; ++ interrupts = <0 10 4>; ++ clocks = <&clock HI3536C_DMAC_CLK>; ++ clock-names = "dmac_clk"; ++ resets = <&clock 0x144 0>; ++ reset-names = "dma-reset"; ++ #dma-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ pmux: pinmux@120F0000 { ++ compatible = "pinctrl-single"; ++ reg = <0x120F0000 0x3A8>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ #gpio-range-cells = <3>; ++ ranges; ++ ++ pinctrl-single,register-width = <32>; ++ pinctrl-single,function-mask = <7>; ++ /* pin base, nr pins & gpio function */ ++ pinctrl-single,gpio-range = <&range 0 54 0 ++ &range 55 6 1 &range 61 5 0>; ++ ++ range: gpio-range { ++ #pinctrl-single,gpio-range-cells = <3>; ++ }; ++ }; ++ }; ++ ++ ++ media { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ osal: osal { ++ compatible = "hisilicon,osal"; ++ }; ++ ++ sys: sys@12040000 { ++ compatible = "hisilicon,hi35xx_sys"; ++ reg = <0x12040000 0x10000>, <0x12050000 0x10000>, ++ <0x12110000 0x10000>, <0x12120000 0x10000>; ++ reg-names = "crg", "sys", "ddr", "misc"; ++ }; ++ ++ vou: vou@13020000 { ++ compatible = "hisilicon,hi35xx_vou"; ++ interrupts = <0 30 4>; ++ reg = <0x13020000 0x10000>; ++ }; ++ ++ vda: vda@13150000 { ++ compatible = "hisilicon,hi35xx_vda"; ++ interrupts = <0 43 4>; ++ reg = <0x13150000 0x10000>; ++ }; ++ ++ ive: ive@13060000 { ++ compatible = "hisilicon,hi35xx_ive"; ++ interrupts = <0 33 4>; ++ reg = <0x13060000 0x10000>; ++ }; ++ ++ vgs: vgs@13080000 { ++ compatible = "hisilicon,hi35xx_vgs"; ++ interrupts = <0 35 4>; ++ reg = <0x13080000 0x10000>; ++ }; ++ ++ vpss: vpss@13110000 { ++ compatible = "hisilicon,hi35xx_vpss"; ++ interrupts = <0 37 4>; ++ interrupt-names = "vpss0"; ++ reg = <0x13110000 0x10000>; ++ reg-names = "vpss0"; ++ }; ++ ++ audio: audio@13140000 { ++ compatible = "hisilicon,hi35xx_aiao"; ++ interrupts = <0 40 4>; ++ reg = <0x13140000 0x10000>, <0x13120000 0x10000>; ++ reg-names = "aiao", "voie"; ++ }; ++ ++ vdec: vdec@13100000 { ++ compatible = "hisilicon,hi35xx_vdec"; ++ interrupts =<0 21 4> , <0 23 4>; ++ interrupt-names ="vdm", "scd"; ++ reg = <0x13100000 0xc000>, <0x1310c000 0x4000>; ++ reg-names = "vdm", "scd"; ++ }; ++ ++ tde: tde@13050000 { ++ compatible = "hisilicon,hi35xx_tde"; ++ interrupts = <0 32 4>; ++ reg = <0x13050000 0x1000>; ++ }; ++ ++ jpgd: jpgd@13070000 { ++ compatible = "hisilicon,hi35xx_jpgd"; ++ interrupts = <0 34 4>; ++ interrupt-names = "jpgd"; ++ reg = <0x13070000 0x10000>; ++ reg-names = "jpgd"; ++ }; ++ ++ vedu: vedu@13040000 { ++ compatible = "hisilicon,hi35xx_vedu"; ++ interrupts = <0 31 4>; ++ interrupt-names = "vedu0"; ++ reg = <0x13040000 0x10000>; ++ reg-names = "vedu0"; ++ }; ++ ++ jpege: jpege@13130000 { ++ compatible = "hisilicon,hi35xx_jpege"; ++ interrupts = <0 39 4>; ++ reg = <0x13130000 0x10000>; ++ }; ++ ++ sys_config_ctrl: sys_config_ctrl { ++ compatible = "hisilicon,sys_config_ctrl"; ++ }; ++ ++ pin_ctrl_ddr: pin_ctrl_ddr { ++ compatible = "hisilicon,pinctrl-ddrpinctrl-ddr"; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/hip04.dtsi b/arch/arm/boot/dts/hip04.dtsi +index 93b6c90..44044f2 100644 +--- a/arch/arm/boot/dts/hip04.dtsi ++++ b/arch/arm/boot/dts/hip04.dtsi +@@ -190,6 +190,12 @@ + clock-frequency = <168000000>; + }; + ++ clk_375m: clk_375m { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <375000000>; ++ }; ++ + soc { + /* It's a 32-bit SoC. */ + #address-cells = <1>; +@@ -264,4 +270,714 @@ + }; + + }; ++ ++ etb@0,e3c42000 { ++ compatible = "arm,coresight-etb10", "arm,primecell"; ++ reg = <0 0xe3c42000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ port { ++ etb0_in_port: endpoint@0 { ++ slave-mode; ++ remote-endpoint = <&replicator0_out_port0>; ++ }; ++ }; ++ }; ++ ++ etb@0,e3c82000 { ++ compatible = "arm,coresight-etb10", "arm,primecell"; ++ reg = <0 0xe3c82000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ port { ++ etb1_in_port: endpoint@0 { ++ slave-mode; ++ remote-endpoint = <&replicator1_out_port0>; ++ }; ++ }; ++ }; ++ ++ etb@0,e3cc2000 { ++ compatible = "arm,coresight-etb10", "arm,primecell"; ++ reg = <0 0xe3cc2000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ port { ++ etb2_in_port: endpoint@0 { ++ slave-mode; ++ remote-endpoint = <&replicator2_out_port0>; ++ }; ++ }; ++ }; ++ ++ etb@0,e3d02000 { ++ compatible = "arm,coresight-etb10", "arm,primecell"; ++ reg = <0 0xe3d02000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ port { ++ etb3_in_port: endpoint@0 { ++ slave-mode; ++ remote-endpoint = <&replicator3_out_port0>; ++ }; ++ }; ++ }; ++ ++ tpiu@0,e3c05000 { ++ compatible = "arm,coresight-tpiu", "arm,primecell"; ++ reg = <0 0xe3c05000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ port { ++ tpiu_in_port: endpoint@0 { ++ slave-mode; ++ remote-endpoint = <&funnel4_out_port0>; ++ }; ++ }; ++ }; ++ ++ replicator0 { ++ /* non-configurable replicators don't show up on the ++ * AMBA bus. As such no need to add "arm,primecell". ++ */ ++ compatible = "arm,coresight-replicator"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* replicator output ports */ ++ port@0 { ++ reg = <0>; ++ replicator0_out_port0: endpoint { ++ remote-endpoint = <&etb0_in_port>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ replicator0_out_port1: endpoint { ++ remote-endpoint = <&funnel4_in_port0>; ++ }; ++ }; ++ ++ /* replicator input port */ ++ port@2 { ++ reg = <0>; ++ replicator0_in_port0: endpoint { ++ slave-mode; ++ remote-endpoint = <&funnel0_out_port0>; ++ }; ++ }; ++ }; ++ }; ++ ++ replicator1 { ++ /* non-configurable replicators don't show up on the ++ * AMBA bus. As such no need to add "arm,primecell". ++ */ ++ compatible = "arm,coresight-replicator"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* replicator output ports */ ++ port@0 { ++ reg = <0>; ++ replicator1_out_port0: endpoint { ++ remote-endpoint = <&etb1_in_port>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ replicator1_out_port1: endpoint { ++ remote-endpoint = <&funnel4_in_port1>; ++ }; ++ }; ++ ++ /* replicator input port */ ++ port@2 { ++ reg = <0>; ++ replicator1_in_port0: endpoint { ++ slave-mode; ++ remote-endpoint = <&funnel1_out_port0>; ++ }; ++ }; ++ }; ++ }; ++ ++ replicator2 { ++ /* non-configurable replicators don't show up on the ++ * AMBA bus. As such no need to add "arm,primecell". ++ */ ++ compatible = "arm,coresight-replicator"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* replicator output ports */ ++ port@0 { ++ reg = <0>; ++ replicator2_out_port0: endpoint { ++ remote-endpoint = <&etb2_in_port>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ replicator2_out_port1: endpoint { ++ remote-endpoint = <&funnel4_in_port2>; ++ }; ++ }; ++ ++ /* replicator input port */ ++ port@2 { ++ reg = <0>; ++ replicator2_in_port0: endpoint { ++ slave-mode; ++ remote-endpoint = <&funnel2_out_port0>; ++ }; ++ }; ++ }; ++ }; ++ ++ replicator3 { ++ /* non-configurable replicators don't show up on the ++ * AMBA bus. As such no need to add "arm,primecell". ++ */ ++ compatible = "arm,coresight-replicator"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* replicator output ports */ ++ port@0 { ++ reg = <0>; ++ replicator3_out_port0: endpoint { ++ remote-endpoint = <&etb3_in_port>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ replicator3_out_port1: endpoint { ++ remote-endpoint = <&funnel4_in_port3>; ++ }; ++ }; ++ ++ /* replicator input port */ ++ port@2 { ++ reg = <0>; ++ replicator3_in_port0: endpoint { ++ slave-mode; ++ remote-endpoint = <&funnel3_out_port0>; ++ }; ++ }; ++ }; ++ }; ++ ++ funnel@0,e3c41000 { ++ compatible = "arm,coresight-funnel", "arm,primecell"; ++ reg = <0 0xe3c41000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* funnel output port */ ++ port@0 { ++ reg = <0>; ++ funnel0_out_port0: endpoint { ++ remote-endpoint = ++ <&replicator0_in_port0>; ++ }; ++ }; ++ ++ /* funnel input ports */ ++ port@1 { ++ reg = <0>; ++ funnel0_in_port0: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm0_out_port>; ++ }; ++ }; ++ ++ port@2 { ++ reg = <1>; ++ funnel0_in_port1: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm1_out_port>; ++ }; ++ }; ++ ++ port@3 { ++ reg = <2>; ++ funnel0_in_port2: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm2_out_port>; ++ }; ++ }; ++ ++ port@4 { ++ reg = <3>; ++ funnel0_in_port3: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm3_out_port>; ++ }; ++ }; ++ }; ++ }; ++ ++ funnel@0,e3c81000 { ++ compatible = "arm,coresight-funnel", "arm,primecell"; ++ reg = <0 0xe3c81000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* funnel output port */ ++ port@0 { ++ reg = <0>; ++ funnel1_out_port0: endpoint { ++ remote-endpoint = ++ <&replicator1_in_port0>; ++ }; ++ }; ++ ++ /* funnel input ports */ ++ port@1 { ++ reg = <0>; ++ funnel1_in_port0: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm4_out_port>; ++ }; ++ }; ++ ++ port@2 { ++ reg = <1>; ++ funnel1_in_port1: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm5_out_port>; ++ }; ++ }; ++ ++ port@3 { ++ reg = <2>; ++ funnel1_in_port2: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm6_out_port>; ++ }; ++ }; ++ ++ port@4 { ++ reg = <3>; ++ funnel1_in_port3: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm7_out_port>; ++ }; ++ }; ++ }; ++ }; ++ ++ funnel@0,e3cc1000 { ++ compatible = "arm,coresight-funnel", "arm,primecell"; ++ reg = <0 0xe3cc1000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* funnel output port */ ++ port@0 { ++ reg = <0>; ++ funnel2_out_port0: endpoint { ++ remote-endpoint = ++ <&replicator2_in_port0>; ++ }; ++ }; ++ ++ /* funnel input ports */ ++ port@1 { ++ reg = <0>; ++ funnel2_in_port0: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm8_out_port>; ++ }; ++ }; ++ ++ port@2 { ++ reg = <1>; ++ funnel2_in_port1: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm9_out_port>; ++ }; ++ }; ++ ++ port@3 { ++ reg = <2>; ++ funnel2_in_port2: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm10_out_port>; ++ }; ++ }; ++ ++ port@4 { ++ reg = <3>; ++ funnel2_in_port3: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm11_out_port>; ++ }; ++ }; ++ }; ++ }; ++ ++ funnel@0,e3d01000 { ++ compatible = "arm,coresight-funnel", "arm,primecell"; ++ reg = <0 0xe3d01000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* funnel output port */ ++ port@0 { ++ reg = <0>; ++ funnel3_out_port0: endpoint { ++ remote-endpoint = ++ <&replicator3_in_port0>; ++ }; ++ }; ++ ++ /* funnel input ports */ ++ port@1 { ++ reg = <0>; ++ funnel3_in_port0: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm12_out_port>; ++ }; ++ }; ++ ++ port@2 { ++ reg = <1>; ++ funnel3_in_port1: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm13_out_port>; ++ }; ++ }; ++ ++ port@3 { ++ reg = <2>; ++ funnel3_in_port2: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm14_out_port>; ++ }; ++ }; ++ ++ port@4 { ++ reg = <3>; ++ funnel3_in_port3: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm15_out_port>; ++ }; ++ }; ++ }; ++ }; ++ ++ funnel@0,e3c04000 { ++ compatible = "arm,coresight-funnel", "arm,primecell"; ++ reg = <0 0xe3c04000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* funnel output port */ ++ port@0 { ++ reg = <0>; ++ funnel4_out_port0: endpoint { ++ remote-endpoint = <&tpiu_in_port>; ++ }; ++ }; ++ ++ /* funnel input ports */ ++ port@1 { ++ reg = <0>; ++ funnel4_in_port0: endpoint { ++ slave-mode; ++ remote-endpoint = ++ <&replicator0_out_port1>; ++ }; ++ }; ++ ++ port@2 { ++ reg = <1>; ++ funnel4_in_port1: endpoint { ++ slave-mode; ++ remote-endpoint = ++ <&replicator1_out_port1>; ++ }; ++ }; ++ ++ port@3 { ++ reg = <2>; ++ funnel4_in_port2: endpoint { ++ slave-mode; ++ remote-endpoint = ++ <&replicator2_out_port1>; ++ }; ++ }; ++ ++ port@4 { ++ reg = <3>; ++ funnel4_in_port3: endpoint { ++ slave-mode; ++ remote-endpoint = ++ <&replicator3_out_port1>; ++ }; ++ }; ++ }; ++ }; ++ ++ ptm@0,e3c7c000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0xe3c7c000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ cpu = <&CPU0>; ++ port { ++ ptm0_out_port: endpoint { ++ remote-endpoint = <&funnel0_in_port0>; ++ }; ++ }; ++ }; ++ ++ ptm@0,e3c7d000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0xe3c7d000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ cpu = <&CPU1>; ++ port { ++ ptm1_out_port: endpoint { ++ remote-endpoint = <&funnel0_in_port1>; ++ }; ++ }; ++ }; ++ ++ ptm@0,e3c7e000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0xe3c7e000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ cpu = <&CPU2>; ++ port { ++ ptm2_out_port: endpoint { ++ remote-endpoint = <&funnel0_in_port2>; ++ }; ++ }; ++ }; ++ ++ ptm@0,e3c7f000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0xe3c7f000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ cpu = <&CPU3>; ++ port { ++ ptm3_out_port: endpoint { ++ remote-endpoint = <&funnel0_in_port3>; ++ }; ++ }; ++ }; ++ ++ ptm@0,e3cbc000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0xe3cbc000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ cpu = <&CPU4>; ++ port { ++ ptm4_out_port: endpoint { ++ remote-endpoint = <&funnel1_in_port0>; ++ }; ++ }; ++ }; ++ ++ ptm@0,e3cbd000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0xe3cbd000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ cpu = <&CPU5>; ++ port { ++ ptm5_out_port: endpoint { ++ remote-endpoint = <&funnel1_in_port1>; ++ }; ++ }; ++ }; ++ ++ ptm@0,e3cbe000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0xe3cbe000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ cpu = <&CPU6>; ++ port { ++ ptm6_out_port: endpoint { ++ remote-endpoint = <&funnel1_in_port2>; ++ }; ++ }; ++ }; ++ ++ ptm@0,e3cbf000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0xe3cbf000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ cpu = <&CPU7>; ++ port { ++ ptm7_out_port: endpoint { ++ remote-endpoint = <&funnel1_in_port3>; ++ }; ++ }; ++ }; ++ ++ ptm@0,e3cfc000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0xe3cfc000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ cpu = <&CPU8>; ++ port { ++ ptm8_out_port: endpoint { ++ remote-endpoint = <&funnel2_in_port0>; ++ }; ++ }; ++ }; ++ ++ ptm@0,e3cfd000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0xe3cfd000 0 0x1000>; ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ cpu = <&CPU9>; ++ port { ++ ptm9_out_port: endpoint { ++ remote-endpoint = <&funnel2_in_port1>; ++ }; ++ }; ++ }; ++ ++ ptm@0,e3cfe000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0xe3cfe000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ cpu = <&CPU10>; ++ port { ++ ptm10_out_port: endpoint { ++ remote-endpoint = <&funnel2_in_port2>; ++ }; ++ }; ++ }; ++ ++ ptm@0,e3cff000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0xe3cff000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ cpu = <&CPU11>; ++ port { ++ ptm11_out_port: endpoint { ++ remote-endpoint = <&funnel2_in_port3>; ++ }; ++ }; ++ }; ++ ++ ptm@0,e3d3c000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0xe3d3c000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ cpu = <&CPU12>; ++ port { ++ ptm12_out_port: endpoint { ++ remote-endpoint = <&funnel3_in_port0>; ++ }; ++ }; ++ }; ++ ++ ptm@0,e3d3d000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0xe3d3d000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ cpu = <&CPU13>; ++ port { ++ ptm13_out_port: endpoint { ++ remote-endpoint = <&funnel3_in_port1>; ++ }; ++ }; ++ }; ++ ++ ptm@0,e3d3e000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0xe3d3e000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ cpu = <&CPU14>; ++ port { ++ ptm14_out_port: endpoint { ++ remote-endpoint = <&funnel3_in_port2>; ++ }; ++ }; ++ }; ++ ++ ptm@0,e3d3f000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0xe3d3f000 0 0x1000>; ++ ++ clocks = <&clk_375m>; ++ clock-names = "apb_pclk"; ++ cpu = <&CPU15>; ++ port { ++ ptm15_out_port: endpoint { ++ remote-endpoint = <&funnel3_in_port3>; ++ }; ++ }; ++ }; + }; +diff --git a/arch/arm/boot/dts/hisi-hi3516av200-demb.dts b/arch/arm/boot/dts/hisi-hi3516av200-demb.dts +new file mode 100644 +index 0000000..6cf8ba4 +--- /dev/null ++++ b/arch/arm/boot/dts/hisi-hi3516av200-demb.dts +@@ -0,0 +1,247 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/dts-v1/; ++#include "hisi-hi3516av200.dtsi" ++ ++/ { ++ model = "Hisilicon HI3516AV200 DEMO Board"; ++ compatible = "hisilicon,hi3516av200"; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ enable-method = "hisilicon,hi3516av200-smp"; ++ ++ cpu@0 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ clock-frequency = ; ++ reg = <0>; ++ cci-control-port = <&cci_control0>; ++ }; ++ ++ /*cpu@100 { ++ compatible = "arm,cortex-a17"; ++ device_type = "cpu"; ++ clock-frequency = ; ++ reg = <0x100>; ++ cci-control-port = <&cci_control1>; ++ };*/ ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x40000000>; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&dual_timer0 { ++ status = "okay"; ++}; ++ ++&i2c_bus0 { ++ status = "okay"; ++}; ++ ++&i2c_bus1 { ++ status = "okay"; ++}; ++ ++&i2c_bus2 { ++ status = "okay"; ++}; ++ ++&i2c_bus3 { ++ status = "okay"; ++}; ++ ++&spi_bus0 { ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++ ++}; ++ ++&spi_bus1 { ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++}; ++ ++&spi_bus2 { ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++}; ++ ++&spi_bus3 { ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++}; ++ ++&hisfc { ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++ ++}; ++ ++&hisnfc { ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ }; ++}; ++ ++&hinfc { ++ hinand { ++ compatible = "jedec,nand"; ++ reg = <0>; ++ nand-max-frequency = <200000000>; ++ }; ++}; ++ ++&mmc0 { ++ status = "okay"; ++}; ++ ++&mmc1 { ++ status = "okay"; ++}; ++ ++&mmc2 { ++ status = "okay"; ++}; ++ ++&mdio { ++ ethphy: ethernet-phy@1 { ++ reg = <1>; ++ }; ++}; ++ ++&higmac { ++ phy-handle = <ðphy>; ++ phy-mode = "rgmii"; ++}; ++ ++&gpio_chip0 { ++ status = "okay"; ++}; ++ ++&gpio_chip1 { ++ status = "okay"; ++}; ++ ++&gpio_chip2 { ++ status = "okay"; ++}; ++ ++&gpio_chip3 { ++ status = "okay"; ++}; ++ ++&gpio_chip4 { ++ status = "okay"; ++}; ++ ++&gpio_chip5 { ++ status = "okay"; ++}; ++ ++&gpio_chip6 { ++ status = "okay"; ++}; ++ ++&gpio_chip7 { ++ status = "okay"; ++}; ++ ++&gpio_chip8 { ++ status = "okay"; ++}; ++ ++&gpio_chip9 { ++ status = "okay"; ++}; ++ ++&gpio_chip10 { ++ status = "okay"; ++}; ++ ++&gpio_chip11 { ++ status = "okay"; ++}; ++ ++&gpio_chip12 { ++ status = "okay"; ++}; ++ ++&gpio_chip13 { ++ status = "okay"; ++}; ++ ++&gpio_chip14 { ++ status = "okay"; ++}; ++ ++&gpio_chip16 { ++ status = "okay"; ++}; +diff --git a/arch/arm/boot/dts/hisi-hi3516av200-hmp-demb.dts b/arch/arm/boot/dts/hisi-hi3516av200-hmp-demb.dts +new file mode 100644 +index 0000000..3c6f10c +--- /dev/null ++++ b/arch/arm/boot/dts/hisi-hi3516av200-hmp-demb.dts +@@ -0,0 +1,310 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/dts-v1/; ++#include "hisi-hi3516av200.dtsi" ++ ++/ { ++ model = "Hisilicon HI3516AV200 DEMO Board"; ++ compatible = "hisilicon,hi3516av200"; ++ ++ chosen { ++ bootargs = "console=ttyAMA0,115200 early_printk ++root=/dev/mtdblock2 rootfstype=jffs2 mtdparts=hi_sfc:1M(boot), ++4M(kernel),11M(rootfs)"; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ enable-method = "hisilicon,hi3516av200-smp"; ++ ++ cpu@0 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ clock-frequency = ; ++ reg = <0>; ++ cci-control-port = <&cci_control0>; ++ }; ++ ++ cpu@100 { ++ compatible = "arm,cortex-a17"; ++ device_type = "cpu"; ++ reg = <0x100>; ++ cci-control-port = <&cci_control1>; ++ operating-points = < ++ /* KHz uV */ ++ 1250000 1060000 ++ 1150000 1060000 ++ 1000000 1000000 ++ 930000 1000000 ++ 792000 940000 ++ 594000 940000 ++ >; ++ clocks = <&clock HI3516AV200_A17_MUX>, ++ <&clock HI3516AV200_FIXED_400M>, ++ <&clock HI3516AV200_FIXED_500M>, ++ <&clock HI3516AV200_FIXED_594M>, ++ <&clock HI3516AV200_FIXED_792M>, ++ <&clock HI3516AV200_APLL_CLK>; ++ clock-names = "a17_mux","400m", "500m", ++ "594m", "792m", "apll"; ++ vcc-supply = <&a17_regulator>; ++ }; ++ }; ++ ++ avs { ++ compatible = "hi3516av200,avs"; ++ avs-num = <2>; ++ avs-name-array = "cpu-avs","media-avs"; ++ cpu_avs: cpu_avs{ ++ avs-name = "cpu-avs"; ++ opp-num = <6>; ++ opp-freq = <1250000 1150000 1000000 930000 792000 594000 >; ++ opp-volt-min = <870000 870000 800000 800000 740000 740000>; ++ opp-hpm = <310 310 280 280 250 250>; ++ opp-div = <24 22 19 18 15 11>; ++ opp-volt-max = <1060000>; ++ }; ++ ++ media_avs: media_avs{ ++ avs-name = "media-avs"; ++ opp-num = <4>; ++ opp-prof-num = <2>; ++ opp-temp-num = <2>; ++ opp-temp = <50 200>; ++ opp-freq = <1 2 3 4>; ++ opp-volt-min = < ++ /* profile2 profile3*/ ++ 770000 770000 ++ 770000 770000 ++ >; ++ opp-hpm = < ++ /* profile2 profile3*/ ++ 210 215 ++ 190 215 ++ >; ++ opp-div = <3 3 3 3>; ++ opp-volt-max = < ++ /* profile2 profile3*/ ++ 977000 977000 ++ 977000 977000 ++ >; ++ }; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x40000000>; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&dual_timer0 { ++ status = "okay"; ++}; ++ ++&i2c_bus0 { ++ status = "okay"; ++}; ++ ++&i2c_bus1 { ++ status = "okay"; ++}; ++ ++&i2c_bus2 { ++ status = "okay"; ++}; ++ ++&i2c_bus3 { ++ status = "okay"; ++}; ++ ++&spi_bus0 { ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24000000>; ++ }; ++ ++}; ++ ++&spi_bus1 { ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24000000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24000000>; ++ }; ++}; ++ ++&spi_bus2 { ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24000000>; ++ }; ++}; ++ ++&spi_bus3 { ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24000000>; ++ }; ++}; ++ ++&hisfc { ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++}; ++ ++&hisnfc { ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ }; ++}; ++ ++&hinfc { ++ hinand { ++ compatible = "jedec,nand"; ++ reg = <0>; ++ nand-max-frequency = <200000000>; ++ }; ++}; ++ ++&mmc0 { ++ status = "okay"; ++}; ++ ++&mmc1 { ++ status = "okay"; ++}; ++ ++&mmc2 { ++ status = "okay"; ++}; ++ ++&mdio { ++ ethphy: ethernet-phy@1 { ++ reg = <1>; ++ }; ++}; ++ ++&higmac { ++ compatible = "hisilicon,higmac-v3", "hisilicon,higmac"; ++ phy-handle = <ðphy>; ++ phy-mode = "rgmii"; ++}; ++ ++&gpio_chip0 { ++ status = "okay"; ++}; ++ ++&gpio_chip1 { ++ status = "okay"; ++}; ++ ++&gpio_chip2 { ++ status = "okay"; ++}; ++ ++&gpio_chip3 { ++ status = "okay"; ++}; ++ ++&gpio_chip4 { ++ status = "okay"; ++}; ++ ++&gpio_chip5 { ++ status = "okay"; ++}; ++ ++&gpio_chip6 { ++ status = "okay"; ++}; ++ ++&gpio_chip7 { ++ status = "okay"; ++}; ++ ++&gpio_chip8 { ++ status = "okay"; ++}; ++ ++&gpio_chip9 { ++ status = "okay"; ++}; ++ ++&gpio_chip10 { ++ status = "okay"; ++}; ++ ++&gpio_chip11 { ++ status = "okay"; ++}; ++ ++&gpio_chip12 { ++ status = "okay"; ++}; ++ ++&gpio_chip13 { ++ status = "okay"; ++}; ++ ++&gpio_chip14 { ++ status = "okay"; ++}; ++ ++&gpio_chip16 { ++ status = "okay"; ++}; +diff --git a/arch/arm/boot/dts/hisi-hi3516av200.dtsi b/arch/arm/boot/dts/hisi-hi3516av200.dtsi +new file mode 100644 +index 0000000..203d20a +--- /dev/null ++++ b/arch/arm/boot/dts/hisi-hi3516av200.dtsi +@@ -0,0 +1,778 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "skeleton.dtsi" ++#include ++/ { ++ aliases { ++ serial0 = &uart0; ++ i2c0 = &i2c_bus0; ++ i2c1 = &i2c_bus1; ++ i2c2 = &i2c_bus2; ++ i2c3 = &i2c_bus3; ++ spi0 = &spi_bus0; ++ spi1 = &spi_bus1; ++ spi2 = &spi_bus2; ++ spi3 = &spi_bus3; ++ gpio0 = &gpio_chip0; ++ gpio1 = &gpio_chip1; ++ gpio2 = &gpio_chip2; ++ gpio3 = &gpio_chip3; ++ gpio4 = &gpio_chip4; ++ gpio5 = &gpio_chip5; ++ gpio6 = &gpio_chip6; ++ gpio7 = &gpio_chip7; ++ gpio8 = &gpio_chip8; ++ gpio9 = &gpio_chip9; ++ gpio10 = &gpio_chip10; ++ gpio11 = &gpio_chip11; ++ gpio12 = &gpio_chip12; ++ gpio13 = &gpio_chip13; ++ gpio14 = &gpio_chip14; ++ gpio16 = &gpio_chip16; ++ }; ++ ++ gic: interrupt-controller@10300000 { ++ compatible = "arm,cortex-a7-gic"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ /* gic dist base, gic cpu base , no virtual support */ ++ reg = <0x10301000 0x1000>, <0x10302000 0x1000>; ++ }; ++ ++ clock: clock0 { ++ compatible = "hisilicon,hi3516av200-clock"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ #clock-cells = <1>; ++ #reset-cells = <2>; ++ reg = <0x12010000 0x10000>; ++ }; ++ ++ syscounter { ++ compatible = "arm,armv7-timer"; ++ interrupt-parent = <&gic>; ++ interrupts = <1 13 0xf08>, ++ <1 14 0xf08>; ++ clock-frequency = <24000000>; ++ }; ++ ++ soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ amba { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "arm,amba-bus"; ++ ranges; ++ ++ uart0: uart@12100000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12100000 0x1000>; ++ interrupts = <0 4 4>; ++ clocks = <&clock HI3516AV200_UART0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart1: uart@12101000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12101000 0x1000>; ++ interrupts = <0 5 4>; ++ clocks = <&clock HI3516AV200_UART1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart2: uart@12102000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12102000 0x1000>; ++ interrupts = <0 6 4>; ++ clocks = <&clock HI3516AV200_UART2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart3: uart@12103000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12103000 0x1000>; ++ interrupts = <0 7 4>; ++ clocks = <&clock HI3516AV200_UART3_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart4: uart@12104000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12104000 0x1000>; ++ interrupts = <0 8 4>; ++ clocks = <&clock HI3516AV200_UART4_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ sys: sys@12010000 { ++ compatible = "hisilicon,hi35xx_sys"; ++ reg = <0x12020000 0x10000>, <0x12060000 0x10000>, <0X12030000 0x10000>; ++ reg-names = "sys", "ddr", "misc"; ++ }; ++ ++ mipi: mipi@11300000 { ++ compatible = "hisilicon,hi35xx_mipi"; ++ interrupts = <0 28 4>, <0 29 4>; ++ interrupt-names = "mipi0", "mipi1"; ++ reg = <0x11300000 0x10000>; ++ }; ++ ++ isp: isp@11380000 { ++ compatible = "hisilicon,hi35xx_isp"; ++ interrupts = <0 30 4>, <0 31 4>; ++ interrupt-names = "isp0", "isp1"; ++ }; ++ ++ viu: viu@11380000 { ++ compatible = "hisilicon,hi35xx_viu"; ++ interrupts = <0 30 4>, <0 31 4>; ++ interrupt-names = "viu0", "viu1"; ++ reg = <0x11380000 0x70000>, <0x11480000 0x70000>; ++ reg-names = "viu0", "viu1"; ++ }; ++ ++ vou: vou@11000000 { ++ compatible = "hisilicon,hi35xx_vou"; ++ interrupts = <0 27 4>; ++ reg = <0x11000000 0x20000>; ++ }; ++ ++ tde: tde@11100000 { ++ compatible = "hisilicon,hi35xx_tde"; ++ interrupts = <0 34 4>; ++ reg = <0x11100000 0x10000>; ++ }; ++ ++ fisheye: fisheye@11110000 { ++ compatible = "hisilicon,hi35xx_fisheye"; ++ interrupts = <0 48 4>; ++ reg = <0x11110000 0x10000>; ++ }; ++ ++ vgs: vgs@11120000 { ++ compatible = "hisilicon,hi35xx_vgs"; ++ interrupts = <0 35 4>; ++ reg = <0x11120000 0x10000>; ++ }; ++ ++ vpss: vpss@11180000 { ++ compatible = "hisilicon,hi35xx_vpss"; ++ interrupts = <0 30 4>, <0 32 4>; ++ interrupt-names = "viu0", "vpss"; ++ reg = <0x11180000 0x10000>; ++ }; ++ ++ vedu: vedu@11280000 { ++ compatible = "hisilicon,hi35xx_vedu"; ++ interrupts = <0 37 4>; ++ reg = <0x11280000 0x10000>; ++ }; ++ ++ jpege: jpege@11200000 { ++ compatible = "hisilicon,hi35xx_jpege"; ++ interrupts = <0 38 4>; ++ reg = <0x11200000 0x10000>; ++ }; ++ ++ aiao: aiao@11080000 { ++ compatible = "hisilicon,hi35xx_aiao"; ++ interrupts = <0 36 4>; ++ reg = <0x11080000 0x3000>; ++ }; ++ ++ ive: ive@11040000 { ++ compatible = "hisilicon,hi35xx_ive"; ++ interrupts = <0 39 4>; ++ reg = <0x11040000 0x10000>; ++ }; ++ ++ fd: fd@11060000 { ++ compatible = "hisilicon,hi35xx_fd"; ++ interrupts = <0 40 4>; ++ reg = <0x11060000 0x10000>; ++ }; ++ ++ pwm: pwm@12130000 { ++ compatible = "hisilicon,pwm"; ++ reg = <0x12130000 0x10000>; ++ }; ++ ++ piris: piris@12145000 { ++ compatible = "hisilicon,piris"; ++ reg = <0x12145000 0x1000>; ++ }; ++ ++ wtdg: wtdg@12080000 { ++ compatible = "hisilicon,hi_wdg"; ++ reg = <0x12080000 0x10000>; ++ reg-names = "wtdg"; ++ }; ++ ++ rtc: rtc@12090000 { ++ compatible = "hisilicon,hi_rtc"; ++ interrupts = <0 1 4>; ++ reg = <0x12090000 0x10000>; ++ }; ++ ++ ir: ir@120f0000{ ++ compatible = "hisilicon,hi_ir"; ++ interrupts = <0 15 4>; ++ reg = <0x120f0000 0x10000>; ++ }; ++ ++ pm { ++ compatible = "hisilicon,hibvt-pm"; ++ reg = <0x12020000 0x1000>, <0x12000000 0x1000>; ++ }; ++ ++ pm_hibernate { ++ compatible = "hisilicon,hibvt-pm-hibernate"; ++ reg = <0x12020000 0x1000>; ++ }; ++ ++ dual_timer0: dual_timer@12000000 { ++ compatible = "arm,sp804"; ++ /* timer0 & timer1 */ ++ interrupts = <0 64 4>, <0 65 4>; ++ reg = <0x12000000 0x1000>; ++ clocks = <&clock HI3516AV200_FIXED_3M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer1: dual_timer@12001000 { ++ compatible = "arm,sp804"; ++ /* timer2 & timer3 */ ++ interrupts = <0 66 4>, <0 67 4>; ++ reg = <0x12001000 0x1000>; ++ clocks = <&clock HI3516AV200_FIXED_3M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer2: dual_timer@12002000 { ++ compatible = "arm,sp804"; ++ /* timer4 & timer5 */ ++ interrupts = <0 68 4>, <0 69 4>; ++ reg = <0x12002000 0x1000>; ++ clocks = <&clock HI3516AV200_FIXED_3M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ i2c_bus0: i2c@12110000 { ++ compatible = "hisilicon,hisi-i2c-v110"; ++ reg = <0x12110000 0x100>; ++ clocks = <&clock HI3516AV200_I2C_MUX>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus1: i2c@12111000 { ++ compatible = "hisilicon,hisi-i2c-v110"; ++ reg = <0x12111000 0x100>; ++ clocks = <&clock HI3516AV200_I2C_MUX>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus2: i2c@12112000 { ++ compatible = "hisilicon,hisi-i2c-v110"; ++ reg = <0x12112000 0x100>; ++ clocks = <&clock HI3516AV200_I2C_MUX>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus3: i2c@12113000 { ++ compatible = "hisilicon,hisi-i2c-v110"; ++ reg = <0x12113000 0x100>; ++ clocks = <&clock HI3516AV200_I2C_MUX>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ spi_bus0: spi@12120000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12120000 0x1000>; ++ interrupts = <0 9 4>; ++ clocks = <&clock HI3516AV200_SPI0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ num-cs = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ spi_bus1: spi@12121000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12121000 0x1000>; ++ interrupts = <0 10 4>; ++ clocks = <&clock HI3516AV200_SPI1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ num-cs = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ spi_bus2: spi@12122000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12122000 0x1000>, <0x12030004 0x4>; ++ interrupts = <0 11 4>; ++ clocks = <&clock HI3516AV200_SPI2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ num-cs = <2>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ hisi,spi_cs_sb = <26>; ++ hisi,spi_cs_mask_bit = <0x0c000000>; ++ }; ++ ++ spi_bus3: spi@12123000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12123000 0x1000>; ++ interrupts = <0 12 4>; ++ clocks = <&clock HI3516AV200_SPI3_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ num-cs = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ gpio_chip0: gpio_chip@12140000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12140000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3516AV200_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip1: gpio_chip@12141000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12141000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3516AV200_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip2: gpio_chip@12142000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12142000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3516AV200_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip3: gpio_chip@12143000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12143000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3516AV200_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip4: gpio_chip@12144000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12144000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3516AV200_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip5: gpio_chip@12145000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12145000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3516AV200_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip6: gpio_chip@12146000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12146000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3516AV200_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip7: gpio_chip@12147000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12147000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3516AV200_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip8: gpio_chip@12148000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12148000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3516AV200_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip9: gpio_chip@12149000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12149000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3516AV200_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip10: gpio_chip@1214a000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214a000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3516AV200_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip11: gpio_chip@1214b000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214b000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3516AV200_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip12: gpio_chip@1214c000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214c000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3516AV200_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip13: gpio_chip@1214d000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214d000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3516AV200_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip14: gpio_chip@1214e000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214e000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3516AV200_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip16: gpio_chip@12150000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12150000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3516AV200_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ }; ++ ++ pmc@0x120a0000 { ++ compatible = "hisilicon,pmc"; ++ reg = <0x120a0000 0x1000>; ++ }; ++ ++ sysctrl: system-controller@00000000 { ++ compatible = "hisilicon,sysctrl"; ++ reg = <0x12020000 0x1000>; ++ reboot-offset = <0x4>; ++ }; ++ ++ usb_phy: phy { ++ compatible = "hisilicon,hisi-usb-phy"; ++ reg = <0x12030000 0x10000>, <0x12010000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ++ usb3_phy: phy3 { ++ compatible = "hisilicon,hisi-usb3-phy"; ++ reg = <0x10180000 0x10000>, <0x12010000 0x10000>, ++ <0x12030000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ehci@0x10120000 { ++ compatible = "generic-ehci"; ++ reg = <0x10120000 0x10000>; ++ interrupts = <0 19 4>; ++ ++ clocks = <&clock HI3516AV200_USB2_CTRL_UTMI0_REQ>, ++ <&clock HI3516AV200_USB2_HRST_REQ>; ++ clock-names = "usb2_cttl_utmi0_req", "usb2_hrst_req"; ++ }; ++ ++ ohci@0x10110000 { ++ compatible = "generic-ohci"; ++ reg = <0x10110000 0x10000>; ++ interrupts = <0 20 4>; ++ ++ clocks = <&clock HI3516AV200_USB2_CTRL_UTMI0_REQ>, ++ <&clock HI3516AV200_USB2_HRST_REQ>; ++ clock-names = "usb2_cttl_utmi0_req", "usb2_hrst_req"; ++ }; ++ ++ xhci@0x10180000 { ++ compatible = "hisilicon,hi3516av200-xhci", "generic-xhci"; ++ reg = <0x10180000 0x10000>; ++ interrupts = <0 22 4>; ++ ++ clocks = <&clock HI3516AV200_USB3_CLK>; ++ clock-names = "clk"; ++ }; ++ ++ hiudc@0x10130000 { ++ compatible = "hiudc"; ++ reg = <0x10130000 0x40000>; ++ interrupts = <0 21 4>; ++ ++ clocks = <&clock HI3516AV200_USB2_HRST_REQ>; ++ clock-names = "clk"; ++ }; ++ ++ hiudc3@0x10180000 { ++ compatible = "dwc_usb3"; ++ reg = <0x10180000 0x40000>; ++ interrupts = <0 22 4>; ++ ++ clocks = <&clock HI3516AV200_USB3_CLK>; ++ clock-names = "clk"; ++ }; ++ ++ cci: cci@1ff00000 { ++ compatible = "arm,cci-400"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x1ff00000 0x1000>; ++ ranges = <0x0 0x1ff00000 0x6000>; ++ ++ cci_control0: slave-if@4000 { ++ compatible = "arm,cci-400-ctrl-if"; ++ interface-type = "ace"; ++ reg = <0x2000 0x1000>; ++ }; ++ ++ cci_control1: slave-if@5000 { ++ compatible = "arm,cci-400-ctrl-if"; ++ interface-type = "ace"; ++ reg = <0x3000 0x1000>; ++ }; ++ ++ }; ++ ++ regulators@120a0000 { ++ compatible = "hi35xx,regulators"; ++ reg = <0x120a0000 0x1000>; ++ regulator-num = <2>; ++ regulator-name-array = "regulator-a17","regulator-media"; ++ ++ a17_regulator: a17_regulator{ ++ regulator-name = "regulator-a17"; ++ regulator-min-microvolt = <651216>; ++ regulator-max-microvolt = <1083359>; ++ regulator-always-on; ++ reg_offset = <0x4>; ++ }; ++ ++ media_regulator: media_regulator{ ++ regulator-name = "regulator-media"; ++ regulator-min-microvolt = <649609>; ++ regulator-max-microvolt = <977031>; ++ regulator-always-on; ++ reg_offset = <0xC>; ++ }; ++ }; ++ ++ pmu { ++ compatible = "arm,cortex-a7-pmu", "arm,cortex-a17-pmu"; ++ interrupts = <0 45 4>, ++ <0 46 4>; ++ }; ++ ++ mdio: mdio@100503c0 { ++ compatible = "hisilicon,hisi-gemac-mdio"; ++ reg = <0x100503c0 0x20>; ++ clocks = <&clock HI3516AV200_ETH_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ higmac: ethernet@10050000 { ++ compatible = "hisilicon,higmac"; ++ reg = <0x10050000 0x1000>,<0x120100ec 0x4>; ++ interrupts = <0 25 4>; ++ ++ clocks = <&clock HI3516AV200_ETH_CLK>, ++ <&clock HI3516AV200_ETH_MACIF_CLK>; ++ clock-names = "higmac_clk", ++ "macif_clk"; ++ ++ resets = <&clock 0xcc 0>, ++ <&clock 0xcc 2>, ++ <&clock 0xcc 7>; ++ reset-names = "port_reset", ++ "macif_reset", ++ "phy_reset"; ++ ++ mac-address = [00 00 00 00 00 00]; ++ }; ++ ++ mmc2: himciv200.MMC@0x100e0000 { ++ compatible = "hisilicon,hi3516av200-himciv200"; ++ reg = <0x100e0000 0x10000>; ++ interrupts = <0 13 4>; ++ ++ clocks = <&clock HI3516AV200_MMC2_CLK>; ++ clock-names = "mmc_clk"; ++ ++ bus-width = <8>; ++ max-frequency = <148500000>; ++ cap-mmc-highspeed; ++ cap-mmc-hw-reset; ++ full-pwr-cycle; ++ mmc-hs400-1_8v; ++ devid = <2>; ++ status = "disabled"; ++ }; ++ ++ mmc0: himciv200.SD@0x100c0000 { ++ compatible = "hisilicon,hi3516av200-himciv200"; ++ reg = <0x100c0000 0x10000>; ++ interrupts = <0 23 4>; ++ ++ clocks = <&clock HI3516AV200_MMC0_CLK>; ++ clock-names = "mmc_clk"; ++ ++ bus-width = <4>; ++ max-frequency = <148500000>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ devid = <0>; ++ status = "disabled"; ++ }; ++ ++ mmc1: himciv200.SD@0x100d0000 { ++ compatible = "hisilicon,hi3516av200-himciv200"; ++ reg = <0x100d0000 0x10000>; ++ interrupts = <0 24 4>; ++ ++ clocks = <&clock HI3516AV200_MMC1_CLK>; ++ clock-names = "mmc_clk"; ++ ++ bus-width = <4>; ++ max-frequency = <148500000>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ devid = <1>; ++ status = "disabled"; ++ }; ++ ++ fmc: spi-nor-controller@10000000 { ++ compatible = "hisilicon,hisi-fmc"; ++ reg = <0x10000000 0x1000>, <0x14000000 0x1000000>; ++ reg-names = "control", "memory"; ++ clocks = <&clock HI3516AV200_FMC_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hisfc:spi-nor@0 { ++ compatible = "hisilicon,hisi-sfc"; ++ assigned-clocks = <&clock HI3516AV200_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hisnfc:spi-nand@0 { ++ compatible = "hisilicon,hisi-spi-nand"; ++ assigned-clocks = <&clock HI3516AV200_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hinfc:nand@0 { ++ compatible = "hisilicon,hisi-nand"; ++ assigned-clocks = <&clock HI3516AV200_FMC_CLK>; ++ assigned-clock-rates = <200000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ }; ++ ++}; +diff --git a/arch/arm/boot/dts/hisi-hi3519-demb.dts b/arch/arm/boot/dts/hisi-hi3519-demb.dts +new file mode 100644 +index 0000000..9b56684 +--- /dev/null ++++ b/arch/arm/boot/dts/hisi-hi3519-demb.dts +@@ -0,0 +1,109 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/dts-v1/; ++#include "hisi-hi3519.dtsi" ++ ++/ { ++ model = "Hisilicon HI3519 DEMO Board"; ++ compatible = "hisilicon,hi3519"; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ enable-method = "hisilicon,hi3519-smp"; ++ ++ cpu@0 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ clock-frequency = ; ++ reg = <0>; ++ cci-control-port = <&cci_control0>; ++ }; ++ ++ /*cpu@100 { ++ compatible = "arm,cortex-a17"; ++ device_type = "cpu"; ++ clock-frequency = ; ++ reg = <0x100>; ++ cci-control-port = <&cci_control1>; ++ };*/ ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x40000000>; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&dual_timer0 { ++ status = "okay"; ++}; ++ ++&hisfc { ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++}; ++ ++&hisnfc { ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ }; ++}; ++ ++&hinfc { ++ hinand { ++ compatible = "jedec,nand"; ++ reg = <0>; ++ nand-max-frequency = <200000000>; ++ }; ++}; ++ ++&mmc0 { ++ status = "okay"; ++}; ++ ++&mmc1 { ++ status = "okay"; ++}; ++ ++&mmc2 { ++ status = "okay"; ++}; ++ ++&mdio { ++ ethphy: ethernet-phy@1 { ++ reg = <1>; ++ }; ++}; ++ ++&higmac { ++ phy-handle = <ðphy>; ++ phy-mode = "rgmii"; ++}; +diff --git a/arch/arm/boot/dts/hisi-hi3519-hmp-demb.dts b/arch/arm/boot/dts/hisi-hi3519-hmp-demb.dts +new file mode 100644 +index 0000000..c43b941 +--- /dev/null ++++ b/arch/arm/boot/dts/hisi-hi3519-hmp-demb.dts +@@ -0,0 +1,159 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/dts-v1/; ++#include "hisi-hi3519.dtsi" ++ ++/ { ++ model = "Hisilicon HI3519 DEMO Board"; ++ compatible = "hisilicon,hi3519"; ++ ++ chosen { ++ bootargs = "console=ttyAMA0,115200 early_printk ++root=/dev/mtdblock2 rootfstype=jffs2 mtdparts=hi_sfc:1M(boot), ++4M(kernel),11M(rootfs)"; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ enable-method = "hisilicon,hi3519-smp"; ++ ++ cpu@0 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ clock-frequency = ; ++ reg = <0>; ++ cci-control-port = <&cci_control0>; ++ }; ++ ++ cpu@100 { ++ compatible = "arm,cortex-a17"; ++ device_type = "cpu"; ++ reg = <0x100>; ++ cci-control-port = <&cci_control1>; ++#if 1 ++ operating-points = < ++ /* KHz uV */ ++ 1150000 1000000 ++ 1000000 960000 ++ 880000 920000 ++ 792000 890000 ++ 594000 830000 ++ >; ++ clocks = <&clock HI3519_A17_MUX>, ++ <&clock HI3519_FIXED_400M>, ++ <&clock HI3519_FIXED_500M>, ++ <&clock HI3519_FIXED_594M>, ++ <&clock HI3519_FIXED_792M>, ++ <&clock HI3519_FIXED_1000M>, ++ <&clock HI3519_APLL_CLK>; ++ clock-names = "a17_mux","400m", "500m", ++ "594m", "792m","1000m", "apll"; ++ vcc-supply = <&a17_regulator>; ++#endif ++ }; ++ }; ++ ++ avs { ++ compatible = "hi3519,avs"; ++ avs-num = <2>; ++ avs-name-array = "cpu-avs","media-avs"; ++ cpu_avs: cpu_avs{ ++ avs-name = "cpu-avs"; ++ opp-num = <5>; ++ opp-freq = <1150000 1000000 880000 792000 594000 >; ++ opp-volt-min = <800000 750000 720000 700000 670000 >; ++ opp-hpm = <305 290 270 240 220 >; ++ opp-div = <22 19 17 15 11 >; ++ opp-volt-max = <1000000>; ++ }; ++ ++ media_avs: media_avs{ ++ avs-name = "media-avs"; ++ opp-num = <1>; ++ opp-freq = <1>; ++ opp-volt-min = <750000>; ++ opp-hpm = <260>; ++ opp-div = <3>; ++ opp-volt-max = <950000>; ++ }; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x40000000>; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&dual_timer0 { ++ status = "okay"; ++}; ++ ++&hisfc { ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++}; ++ ++&hisnfc { ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ }; ++}; ++ ++&hinfc { ++ hinand { ++ compatible = "jedec,nand"; ++ reg = <0>; ++ nand-max-frequency = <200000000>; ++ }; ++}; ++ ++&mmc0 { ++ status = "okay"; ++}; ++ ++&mmc1 { ++ status = "okay"; ++}; ++ ++&mmc2 { ++ status = "okay"; ++}; ++ ++&mdio { ++ ethphy: ethernet-phy@1 { ++ reg = <1>; ++ }; ++}; ++ ++&higmac { ++ phy-handle = <ðphy>; ++ phy-mode = "rgmii"; ++}; +diff --git a/arch/arm/boot/dts/hisi-hi3519.dtsi b/arch/arm/boot/dts/hisi-hi3519.dtsi +new file mode 100644 +index 0000000..8fb6d56 +--- /dev/null ++++ b/arch/arm/boot/dts/hisi-hi3519.dtsi +@@ -0,0 +1,470 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "skeleton.dtsi" ++#include ++/ { ++ aliases { ++ serial0 = &uart0; ++ spi0 = &spi_bus0; ++ spi1 = &spi_bus1; ++ spi2 = &spi_bus2; ++ }; ++ ++ gic: interrupt-controller@10300000 { ++ compatible = "arm,cortex-a7-gic"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ /* gic dist base, gic cpu base , no virtual support */ ++ reg = <0x10301000 0x1000>, <0x10302000 0x1000>; ++ }; ++ ++ clock: clock0 { ++ compatible = "hisilicon,hi3519-clock"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ #clock-cells = <1>; ++ #reset-cells = <2>; ++ reg = <0x12010000 0x10000>; ++ }; ++ ++ syscounter { ++ compatible = "arm,armv7-timer"; ++ interrupt-parent = <&gic>; ++ interrupts = <1 13 0xf08>, ++ <1 14 0xf08>; ++ clock-frequency = <24000000>; ++ }; ++ ++ soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ amba { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "arm,amba-bus"; ++ ranges; ++ ++ uart0: uart@12100000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12100000 0x1000>; ++ interrupts = <0 4 4>; ++ clocks = <&clock HI3519_UART0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart1: uart@12101000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12101000 0x1000>; ++ interrupts = <0 5 4>; ++ clocks = <&clock HI3519_UART1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart2: uart@12102000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12102000 0x1000>; ++ interrupts = <0 6 4>; ++ clocks = <&clock HI3519_UART2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart3: uart@12103000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12103000 0x1000>; ++ interrupts = <0 7 4>; ++ clocks = <&clock HI3519_UART3_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart4: uart@12104000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12104000 0x1000>; ++ interrupts = <0 8 4>; ++ clocks = <&clock HI3519_UART4_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ ++ pm { ++ compatible = "hisilicon,hibvt-pm"; ++ reg = <0x12020000 0x1000>, <0x12000000 0x1000>; ++ }; ++ ++ pm_hibernate { ++ compatible = "hisilicon,hibvt-pm-hibernate"; ++ reg = <0x12020000 0x1000>; ++ }; ++ ++ dual_timer0: dual_timer@12000000 { ++ compatible = "arm,sp804"; ++ /* timer0 & timer1 */ ++ interrupts = <0 64 4>, <0 65 4>; ++ reg = <0x12000000 0x1000>; ++ clocks = <&clock HI3519_FIXED_3M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer1: dual_timer@12001000 { ++ compatible = "arm,sp804"; ++ /* timer2 & timer3 */ ++ interrupts = <0 66 4>, <0 67 4>; ++ reg = <0x12001000 0x1000>; ++ clocks = <&clock HI3519_FIXED_3M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer2: dual_timer@12002000 { ++ compatible = "arm,sp804"; ++ /* timer4 & timer5 */ ++ interrupts = <0 68 4>, <0 69 4>; ++ reg = <0x12002000 0x1000>; ++ clocks = <&clock HI3519_FIXED_3M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ spi_bus0: spi@12120000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12120000 0x1000>; ++ interrupts = <0 9 4>; ++ clocks = <&clock HI3519_SPI0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "okay"; ++ num-cs = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++ ++ }; ++ ++ spi_bus1: spi@12121000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12121000 0x1000>, <0x12030004 0x4>; ++ interrupts = <0 10 4>; ++ clocks = <&clock HI3519_SPI1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "okay"; ++ num-cs = <2>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ hisi,spi_cs_sb = <26>; ++ hisi,spi_cs_mask_bit = <0x0c000000>; ++ ++ spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++ ++ spidev@1 { ++ compatible = "spidev"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++ }; ++ ++ spi_bus2: spi@12122000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12122000 0x1000>; ++ interrupts = <0 11 4>; ++ clocks = <&clock HI3519_SPI2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "okay"; ++ num-cs = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++ }; ++ ++ }; ++ ++ pmc@0x120a0000 { ++ compatible = "hisilicon,pmc"; ++ reg = <0x120a0000 0x1000>; ++ }; ++ ++ sysctrl: system-controller@00000000 { ++ compatible = "hisilicon,sysctrl"; ++ reg = <0x12020000 0x1000>; ++ reboot-offset = <0x4>; ++ }; ++ ++ usb_phy: phy { ++ compatible = "hisilicon,hisi-usb-phy"; ++ reg = <0x12030000 0x10000>, <0x12010000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ++ usb3_phy: phy3 { ++ compatible = "hisilicon,hisi-usb3-phy"; ++ reg = <0x10180000 0x10000>, <0x12010000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ehci@0x10120000 { ++ compatible = "generic-ehci"; ++ reg = <0x10120000 0x10000>; ++ interrupts = <0 19 4>; ++ ++ clocks = <&clock HI3519_USB2_CTRL_UTMI0_REQ>, ++ <&clock HI3519_USB2_HRST_REQ>; ++ clock-names = "usb2_cttl_utmi0_req", "usb2_hrst_req"; ++ }; ++ ++ ohci@0x10110000 { ++ compatible = "generic-ohci"; ++ reg = <0x10110000 0x10000>; ++ interrupts = <0 20 4>; ++ ++ clocks = <&clock HI3519_USB2_CTRL_UTMI0_REQ>, ++ <&clock HI3519_USB2_HRST_REQ>; ++ clock-names = "usb2_cttl_utmi0_req", "usb2_hrst_req"; ++ }; ++ ++ xhci@0x10180000 { ++ compatible = "hisilicon,hi3519-xhci", "generic-xhci"; ++ reg = <0x10180000 0x10000>; ++ interrupts = <0 22 4>; ++ ++ clocks = <&clock HI3519_USB3_CLK>; ++ clock-names = "clk"; ++ }; ++ ++ hiudc@0x10130000 { ++ compatible = "hiudc"; ++ reg = <0x10130000 0x40000>; ++ interrupts = <0 21 4>; ++ ++ clocks = <&clock HI3519_USB2_HRST_REQ>; ++ clock-names = "clk"; ++ }; ++ ++ hiudc3@0x10180000 { ++ compatible = "dwc_usb3"; ++ reg = <0x10180000 0x40000>; ++ interrupts = <0 22 4>; ++ ++ clocks = <&clock HI3519_USB3_CLK>; ++ clock-names = "clk"; ++ }; ++ ++ cci: cci@1ff00000 { ++ compatible = "arm,cci-400"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x1ff00000 0x1000>; ++ ranges = <0x0 0x1ff00000 0x6000>; ++ ++ cci_control0: slave-if@4000 { ++ compatible = "arm,cci-400-ctrl-if"; ++ interface-type = "ace"; ++ reg = <0x1000 0x1000>; ++ }; ++ ++ cci_control1: slave-if@5000 { ++ compatible = "arm,cci-400-ctrl-if"; ++ interface-type = "ace"; ++ reg = <0x2000 0x1000>; ++ }; ++ ++ }; ++ ++ regulators@120a0000 { ++ compatible = "hi3519,regulators"; ++ reg = <0x120a0000 0x1000>; ++ regulator-num = <2>; ++ regulator-name-array = "regulator-a17","regulator-media"; ++ ++ a17_regulator: a17_regulator{ ++ regulator-name = "regulator-a17"; ++ regulator-min-microvolt = <648633>; ++ regulator-max-microvolt = <1200525>; ++ regulator-always-on; ++ reg_offset = <0x4>; ++ }; ++ ++ media_regulator: media_regulator{ ++ regulator-name = "regulator-media"; ++ regulator-min-microvolt = <649740>; ++ regulator-max-microvolt = <1204331>; ++ regulator-always-on; ++ reg_offset = <0xC>; ++ }; ++ }; ++ ++ pmu { ++ compatible = "arm,cortex-a7-pmu", "arm,cortex-a17-pmu"; ++ interrupts = <0 45 4>, ++ <0 46 4>; ++ }; ++ ++ mdio: mdio@100503c0 { ++ compatible = "hisilicon,hisi-gemac-mdio"; ++ reg = <0x100503c0 0x20>; ++ clocks = <&clock HI3519_ETH_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ higmac: ethernet@10050000 { ++ compatible = "hisilicon,higmac"; ++ reg = <0x10050000 0x1000>,<0x120100ec 0x4>; ++ interrupts = <0 25 4>; ++ ++ clocks = <&clock HI3519_ETH_CLK>, ++ <&clock HI3519_ETH_MACIF_CLK>; ++ clock-names = "higmac_clk", ++ "macif_clk"; ++ ++ resets = <&clock 0xcc 0>, ++ <&clock 0xcc 2>, ++ <&clock 0xcc 7>; ++ reset-names = "port_reset", ++ "macif_reset", ++ "phy_reset"; ++ ++ mac-address = [00 00 00 00 00 00]; ++ }; ++ ++ mmc2: himciv200.MMC@0x100e0000 { ++ compatible = "hisilicon,hi3519-himciv200"; ++ reg = <0x100e0000 0x10000>; ++ interrupts = <0 13 4>; ++ ++ clocks = <&clock HI3519_MMC2_CLK>; ++ clock-names = "mmc_clk"; ++ ++ bus-width = <8>; ++ max-frequency = <99000000>; ++ cap-mmc-highspeed; ++ cap-mmc-hw-reset; ++ full-pwr-cycle; ++ mmc-hs400-1_8v; ++ devid = <2>; ++ status = "disabled"; ++ }; ++ ++ mmc0: himciv200.SD@0x100c0000 { ++ compatible = "hisilicon,hi3519-himciv200"; ++ reg = <0x100c0000 0x10000>; ++ interrupts = <0 23 4>; ++ ++ clocks = <&clock HI3519_MMC0_CLK>; ++ clock-names = "mmc_clk"; ++ ++ bus-width = <4>; ++ max-frequency = <99000000>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ devid = <0>; ++ status = "disabled"; ++ }; ++ ++ mmc1: himciv200.SD@0x100d0000 { ++ compatible = "hisilicon,hi3519-himciv200"; ++ reg = <0x100d0000 0x10000>; ++ interrupts = <0 24 4>; ++ ++ clocks = <&clock HI3519_MMC1_CLK>; ++ clock-names = "mmc_clk"; ++ ++ bus-width = <4>; ++ max-frequency = <99000000>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ devid = <1>; ++ status = "disabled"; ++ }; ++ ++ fmc: spi-nor-controller@10000000 { ++ compatible = "hisilicon,hisi-fmc"; ++ reg = <0x10000000 0x1000>, <0x14000000 0x1000000>; ++ reg-names = "control", "memory"; ++ clocks = <&clock HI3519_FMC_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hisfc:spi-nor@0 { ++ compatible = "hisilicon,hisi-sfc"; ++ assigned-clocks = <&clock HI3519_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hisnfc:spi-nand@0 { ++ compatible = "hisilicon,hisi-spi-nand"; ++ assigned-clocks = <&clock HI3519_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hinfc:nand@0 { ++ compatible = "hisilicon,hisi-nand"; ++ assigned-clocks = <&clock HI3519_FMC_CLK>; ++ assigned-clock-rates = <200000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ }; ++ ++}; +diff --git a/arch/arm/boot/dts/hisi-hi3519v101-demb.dts b/arch/arm/boot/dts/hisi-hi3519v101-demb.dts +new file mode 100644 +index 0000000..7478525 +--- /dev/null ++++ b/arch/arm/boot/dts/hisi-hi3519v101-demb.dts +@@ -0,0 +1,247 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/dts-v1/; ++#include "hisi-hi3519v101.dtsi" ++ ++/ { ++ model = "Hisilicon HI3519V101 DEMO Board"; ++ compatible = "hisilicon,hi3519v101"; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ enable-method = "hisilicon,hi3519-smp"; ++ ++ cpu@0 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ clock-frequency = ; ++ reg = <0>; ++ cci-control-port = <&cci_control0>; ++ }; ++ ++ /*cpu@100 { ++ compatible = "arm,cortex-a17"; ++ device_type = "cpu"; ++ clock-frequency = ; ++ reg = <0x100>; ++ cci-control-port = <&cci_control1>; ++ };*/ ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x40000000>; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&dual_timer0 { ++ status = "okay"; ++}; ++ ++&i2c_bus0 { ++ status = "okay"; ++}; ++ ++&i2c_bus1 { ++ status = "okay"; ++}; ++ ++&i2c_bus2 { ++ status = "okay"; ++}; ++ ++&i2c_bus3 { ++ status = "okay"; ++}; ++ ++&spi_bus0 { ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++ ++}; ++ ++&spi_bus1 { ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++}; ++ ++&spi_bus2 { ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++}; ++ ++&spi_bus3 { ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++}; ++ ++&hisfc { ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++ ++}; ++ ++&hisnfc { ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ }; ++}; ++ ++&hinfc { ++ hinand { ++ compatible = "jedec,nand"; ++ reg = <0>; ++ nand-max-frequency = <200000000>; ++ }; ++}; ++ ++&mmc0 { ++ status = "okay"; ++}; ++ ++&mmc1 { ++ status = "okay"; ++}; ++ ++&mmc2 { ++ status = "okay"; ++}; ++ ++&mdio { ++ ethphy: ethernet-phy@1 { ++ reg = <1>; ++ }; ++}; ++ ++&higmac { ++ phy-handle = <ðphy>; ++ phy-mode = "rgmii"; ++}; ++ ++&gpio_chip0 { ++ status = "okay"; ++}; ++ ++&gpio_chip1 { ++ status = "okay"; ++}; ++ ++&gpio_chip2 { ++ status = "okay"; ++}; ++ ++&gpio_chip3 { ++ status = "okay"; ++}; ++ ++&gpio_chip4 { ++ status = "okay"; ++}; ++ ++&gpio_chip5 { ++ status = "okay"; ++}; ++ ++&gpio_chip6 { ++ status = "okay"; ++}; ++ ++&gpio_chip7 { ++ status = "okay"; ++}; ++ ++&gpio_chip8 { ++ status = "okay"; ++}; ++ ++&gpio_chip9 { ++ status = "okay"; ++}; ++ ++&gpio_chip10 { ++ status = "okay"; ++}; ++ ++&gpio_chip11 { ++ status = "okay"; ++}; ++ ++&gpio_chip12 { ++ status = "okay"; ++}; ++ ++&gpio_chip13 { ++ status = "okay"; ++}; ++ ++&gpio_chip14 { ++ status = "okay"; ++}; ++ ++&gpio_chip16 { ++ status = "okay"; ++}; +diff --git a/arch/arm/boot/dts/hisi-hi3519v101-hmp-demb.dts b/arch/arm/boot/dts/hisi-hi3519v101-hmp-demb.dts +new file mode 100644 +index 0000000..dd2412f +--- /dev/null ++++ b/arch/arm/boot/dts/hisi-hi3519v101-hmp-demb.dts +@@ -0,0 +1,310 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/dts-v1/; ++#include "hisi-hi3519v101.dtsi" ++ ++/ { ++ model = "Hisilicon HI3519V101 DEMO Board"; ++ compatible = "hisilicon,hi3519v101"; ++ ++ chosen { ++ bootargs = "console=ttyAMA0,115200 early_printk ++root=/dev/mtdblock2 rootfstype=jffs2 mtdparts=hi_sfc:1M(boot), ++4M(kernel),11M(rootfs)"; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ enable-method = "hisilicon,hi3519-smp"; ++ ++ cpu@0 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ clock-frequency = ; ++ reg = <0>; ++ cci-control-port = <&cci_control0>; ++ }; ++ ++ cpu@100 { ++ compatible = "arm,cortex-a17"; ++ device_type = "cpu"; ++ reg = <0x100>; ++ cci-control-port = <&cci_control1>; ++ operating-points = < ++ /* KHz uV */ ++ 1250000 1060000 ++ 1150000 1060000 ++ 1000000 1000000 ++ 930000 1000000 ++ 792000 940000 ++ 594000 940000 ++ >; ++ clocks = <&clock HI3519_A17_MUX>, ++ <&clock HI3519_FIXED_400M>, ++ <&clock HI3519_FIXED_500M>, ++ <&clock HI3519_FIXED_594M>, ++ <&clock HI3519_FIXED_792M>, ++ <&clock HI3519_APLL_CLK>; ++ clock-names = "a17_mux","400m", "500m", ++ "594m", "792m", "apll"; ++ vcc-supply = <&a17_regulator>; ++ }; ++ }; ++ ++ avs { ++ compatible = "hi3519,avs"; ++ avs-num = <2>; ++ avs-name-array = "cpu-avs","media-avs"; ++ cpu_avs: cpu_avs{ ++ avs-name = "cpu-avs"; ++ opp-num = <6>; ++ opp-freq = <1250000 1150000 1000000 930000 792000 594000 >; ++ opp-volt-min = <870000 870000 800000 800000 740000 740000>; ++ opp-hpm = <310 310 280 280 250 250>; ++ opp-div = <24 22 19 18 15 11>; ++ opp-volt-max = <1060000>; ++ }; ++ ++ media_avs: media_avs{ ++ avs-name = "media-avs"; ++ opp-num = <4>; ++ opp-prof-num = <2>; ++ opp-temp-num = <2>; ++ opp-temp = <50 200>; ++ opp-freq = <1 2 3 4>; ++ opp-volt-min = < ++ /* profile2 profile3*/ ++ 770000 770000 ++ 770000 770000 ++ >; ++ opp-hpm = < ++ /* profile2 profile3*/ ++ 210 215 ++ 190 215 ++ >; ++ opp-div = <3 3 3 3>; ++ opp-volt-max = < ++ /* profile2 profile3*/ ++ 977000 977000 ++ 977000 977000 ++ >; ++ }; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x40000000>; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&dual_timer0 { ++ status = "okay"; ++}; ++ ++&i2c_bus0 { ++ status = "okay"; ++}; ++ ++&i2c_bus1 { ++ status = "okay"; ++}; ++ ++&i2c_bus2 { ++ status = "okay"; ++}; ++ ++&i2c_bus3 { ++ status = "okay"; ++}; ++ ++&spi_bus0 { ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24000000>; ++ }; ++ ++}; ++ ++&spi_bus1 { ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24000000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24000000>; ++ }; ++}; ++ ++&spi_bus2 { ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24000000>; ++ }; ++}; ++ ++&spi_bus3 { ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24000000>; ++ }; ++}; ++ ++&hisfc { ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++}; ++ ++&hisnfc { ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ }; ++}; ++ ++&hinfc { ++ hinand { ++ compatible = "jedec,nand"; ++ reg = <0>; ++ nand-max-frequency = <200000000>; ++ }; ++}; ++ ++&mmc0 { ++ status = "okay"; ++}; ++ ++&mmc1 { ++ status = "okay"; ++}; ++ ++&mmc2 { ++ status = "okay"; ++}; ++ ++&mdio { ++ ethphy: ethernet-phy@1 { ++ reg = <1>; ++ }; ++}; ++ ++&higmac { ++ compatible = "hisilicon,higmac-v3", "hisilicon,higmac"; ++ phy-handle = <ðphy>; ++ phy-mode = "rgmii"; ++}; ++ ++&gpio_chip0 { ++ status = "okay"; ++}; ++ ++&gpio_chip1 { ++ status = "okay"; ++}; ++ ++&gpio_chip2 { ++ status = "okay"; ++}; ++ ++&gpio_chip3 { ++ status = "okay"; ++}; ++ ++&gpio_chip4 { ++ status = "okay"; ++}; ++ ++&gpio_chip5 { ++ status = "okay"; ++}; ++ ++&gpio_chip6 { ++ status = "okay"; ++}; ++ ++&gpio_chip7 { ++ status = "okay"; ++}; ++ ++&gpio_chip8 { ++ status = "okay"; ++}; ++ ++&gpio_chip9 { ++ status = "okay"; ++}; ++ ++&gpio_chip10 { ++ status = "okay"; ++}; ++ ++&gpio_chip11 { ++ status = "okay"; ++}; ++ ++&gpio_chip12 { ++ status = "okay"; ++}; ++ ++&gpio_chip13 { ++ status = "okay"; ++}; ++ ++&gpio_chip14 { ++ status = "okay"; ++}; ++ ++&gpio_chip16 { ++ status = "okay"; ++}; +diff --git a/arch/arm/boot/dts/hisi-hi3519v101.dtsi b/arch/arm/boot/dts/hisi-hi3519v101.dtsi +new file mode 100644 +index 0000000..df48673 +--- /dev/null ++++ b/arch/arm/boot/dts/hisi-hi3519v101.dtsi +@@ -0,0 +1,777 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "skeleton.dtsi" ++#include ++/ { ++ aliases { ++ serial0 = &uart0; ++ i2c0 = &i2c_bus0; ++ i2c1 = &i2c_bus1; ++ i2c2 = &i2c_bus2; ++ i2c3 = &i2c_bus3; ++ spi0 = &spi_bus0; ++ spi1 = &spi_bus1; ++ spi2 = &spi_bus2; ++ spi3 = &spi_bus3; ++ gpio0 = &gpio_chip0; ++ gpio1 = &gpio_chip1; ++ gpio2 = &gpio_chip2; ++ gpio3 = &gpio_chip3; ++ gpio4 = &gpio_chip4; ++ gpio5 = &gpio_chip5; ++ gpio6 = &gpio_chip6; ++ gpio7 = &gpio_chip7; ++ gpio8 = &gpio_chip8; ++ gpio9 = &gpio_chip9; ++ gpio10 = &gpio_chip10; ++ gpio11 = &gpio_chip11; ++ gpio12 = &gpio_chip12; ++ gpio13 = &gpio_chip13; ++ gpio14 = &gpio_chip14; ++ gpio16 = &gpio_chip16; ++ }; ++ ++ gic: interrupt-controller@10300000 { ++ compatible = "arm,cortex-a7-gic"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ /* gic dist base, gic cpu base , no virtual support */ ++ reg = <0x10301000 0x1000>, <0x10302000 0x1000>; ++ }; ++ ++ clock: clock0 { ++ compatible = "hisilicon,hi3519v101-clock"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ #clock-cells = <1>; ++ #reset-cells = <2>; ++ reg = <0x12010000 0x10000>; ++ }; ++ ++ syscounter { ++ compatible = "arm,armv7-timer"; ++ interrupt-parent = <&gic>; ++ interrupts = <1 13 0xf08>, ++ <1 14 0xf08>; ++ clock-frequency = <24000000>; ++ }; ++ ++ soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ amba { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "arm,amba-bus"; ++ ranges; ++ ++ uart0: uart@12100000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12100000 0x1000>; ++ interrupts = <0 4 4>; ++ clocks = <&clock HI3519_UART0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart1: uart@12101000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12101000 0x1000>; ++ interrupts = <0 5 4>; ++ clocks = <&clock HI3519_UART1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart2: uart@12102000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12102000 0x1000>; ++ interrupts = <0 6 4>; ++ clocks = <&clock HI3519_UART2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart3: uart@12103000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12103000 0x1000>; ++ interrupts = <0 7 4>; ++ clocks = <&clock HI3519_UART3_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart4: uart@12104000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12104000 0x1000>; ++ interrupts = <0 8 4>; ++ clocks = <&clock HI3519_UART4_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ sys: sys@12010000 { ++ compatible = "hisilicon,hi35xx_sys"; ++ reg = <0x12020000 0x10000>, <0x12060000 0x10000>, <0X12030000 0x10000>; ++ reg-names = "sys", "ddr", "misc"; ++ }; ++ ++ mipi: mipi@11300000 { ++ compatible = "hisilicon,hi35xx_mipi"; ++ interrupts = <0 28 4>, <0 29 4>; ++ interrupt-names = "mipi0", "mipi1"; ++ reg = <0x11300000 0x10000>; ++ }; ++ ++ isp: isp@11380000 { ++ compatible = "hisilicon,hi35xx_isp"; ++ interrupts = <0 30 4>, <0 31 4>; ++ interrupt-names = "isp0", "isp1"; ++ }; ++ ++ viu: viu@11380000 { ++ compatible = "hisilicon,hi35xx_viu"; ++ interrupts = <0 30 4>, <0 31 4>; ++ interrupt-names = "viu0", "viu1"; ++ reg = <0x11380000 0x70000>, <0x11480000 0x70000>; ++ reg-names = "viu0", "viu1"; ++ }; ++ ++ vou: vou@11000000 { ++ compatible = "hisilicon,hi35xx_vou"; ++ interrupts = <0 27 4>; ++ reg = <0x11000000 0x20000>; ++ }; ++ ++ tde: tde@11100000 { ++ compatible = "hisilicon,hi35xx_tde"; ++ interrupts = <0 34 4>; ++ reg = <0x11100000 0x10000>; ++ }; ++ ++ fisheye: fisheye@11110000 { ++ compatible = "hisilicon,hi35xx_fisheye"; ++ interrupts = <0 48 4>; ++ reg = <0x11110000 0x10000>; ++ }; ++ ++ vgs: vgs@11120000 { ++ compatible = "hisilicon,hi35xx_vgs"; ++ interrupts = <0 35 4>; ++ reg = <0x11120000 0x10000>; ++ }; ++ ++ vpss: vpss@11180000 { ++ compatible = "hisilicon,hi35xx_vpss"; ++ interrupts = <0 30 4>, <0 32 4>; ++ interrupt-names = "viu0", "vpss"; ++ reg = <0x11180000 0x10000>; ++ }; ++ ++ vedu: vedu@11280000 { ++ compatible = "hisilicon,hi35xx_vedu"; ++ interrupts = <0 37 4>; ++ reg = <0x11280000 0x10000>; ++ }; ++ ++ jpege: jpege@11200000 { ++ compatible = "hisilicon,hi35xx_jpege"; ++ interrupts = <0 38 4>; ++ reg = <0x11200000 0x10000>; ++ }; ++ ++ aiao: aiao@11080000 { ++ compatible = "hisilicon,hi35xx_aiao"; ++ interrupts = <0 36 4>; ++ reg = <0x11080000 0x3000>; ++ }; ++ ++ ive: ive@11040000 { ++ compatible = "hisilicon,hi35xx_ive"; ++ interrupts = <0 39 4>; ++ reg = <0x11040000 0x10000>; ++ }; ++ ++ fd: fd@11060000 { ++ compatible = "hisilicon,hi35xx_fd"; ++ interrupts = <0 40 4>; ++ reg = <0x11060000 0x10000>; ++ }; ++ ++ pwm: pwm@12130000 { ++ compatible = "hisilicon,pwm"; ++ reg = <0x12130000 0x10000>; ++ }; ++ ++ piris: piris@12145000 { ++ compatible = "hisilicon,piris"; ++ reg = <0x12145000 0x1000>; ++ }; ++ ++ wtdg: wtdg@12080000 { ++ compatible = "hisilicon,hi_wdg"; ++ reg = <0x12080000 0x10000>; ++ reg-names = "wtdg"; ++ }; ++ ++ rtc: rtc@12090000 { ++ compatible = "hisilicon,hi_rtc"; ++ interrupts = <0 1 4>; ++ reg = <0x12090000 0x10000>; ++ }; ++ ++ ir: ir@120f0000{ ++ compatible = "hisilicon,hi_ir"; ++ interrupts = <0 15 4>; ++ reg = <0x120f0000 0x10000>; ++ }; ++ ++ pm { ++ compatible = "hisilicon,hibvt-pm"; ++ reg = <0x12020000 0x1000>, <0x12000000 0x1000>; ++ }; ++ ++ pm_hibernate { ++ compatible = "hisilicon,hibvt-pm-hibernate"; ++ reg = <0x12020000 0x1000>; ++ }; ++ ++ dual_timer0: dual_timer@12000000 { ++ compatible = "arm,sp804"; ++ /* timer0 & timer1 */ ++ interrupts = <0 64 4>, <0 65 4>; ++ reg = <0x12000000 0x1000>; ++ clocks = <&clock HI3519_FIXED_3M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer1: dual_timer@12001000 { ++ compatible = "arm,sp804"; ++ /* timer2 & timer3 */ ++ interrupts = <0 66 4>, <0 67 4>; ++ reg = <0x12001000 0x1000>; ++ clocks = <&clock HI3519_FIXED_3M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer2: dual_timer@12002000 { ++ compatible = "arm,sp804"; ++ /* timer4 & timer5 */ ++ interrupts = <0 68 4>, <0 69 4>; ++ reg = <0x12002000 0x1000>; ++ clocks = <&clock HI3519_FIXED_3M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ i2c_bus0: i2c@12110000 { ++ compatible = "hisilicon,hisi-i2c-v110"; ++ reg = <0x12110000 0x100>; ++ clocks = <&clock HI3519_I2C_MUX>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus1: i2c@12111000 { ++ compatible = "hisilicon,hisi-i2c-v110"; ++ reg = <0x12111000 0x100>; ++ clocks = <&clock HI3519_I2C_MUX>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus2: i2c@12112000 { ++ compatible = "hisilicon,hisi-i2c-v110"; ++ reg = <0x12112000 0x100>; ++ clocks = <&clock HI3519_I2C_MUX>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus3: i2c@12113000 { ++ compatible = "hisilicon,hisi-i2c-v110"; ++ reg = <0x12113000 0x100>; ++ clocks = <&clock HI3519_I2C_MUX>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ spi_bus0: spi@12120000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12120000 0x1000>; ++ interrupts = <0 9 4>; ++ clocks = <&clock HI3519_SPI0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ num-cs = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ spi_bus1: spi@12121000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12121000 0x1000>; ++ interrupts = <0 10 4>; ++ clocks = <&clock HI3519_SPI1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ num-cs = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ spi_bus2: spi@12122000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12122000 0x1000>, <0x12030004 0x4>; ++ interrupts = <0 11 4>; ++ clocks = <&clock HI3519_SPI2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ num-cs = <2>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ hisi,spi_cs_sb = <26>; ++ hisi,spi_cs_mask_bit = <0x0c000000>; ++ }; ++ ++ spi_bus3: spi@12123000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12123000 0x1000>; ++ interrupts = <0 12 4>; ++ clocks = <&clock HI3519_SPI3_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ num-cs = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ gpio_chip0: gpio_chip@12140000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12140000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3519_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip1: gpio_chip@12141000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12141000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3519_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip2: gpio_chip@12142000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12142000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3519_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip3: gpio_chip@12143000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12143000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3519_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip4: gpio_chip@12144000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12144000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3519_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip5: gpio_chip@12145000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12145000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3519_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip6: gpio_chip@12146000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12146000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3519_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip7: gpio_chip@12147000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12147000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3519_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip8: gpio_chip@12148000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12148000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3519_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip9: gpio_chip@12149000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12149000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3519_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip10: gpio_chip@1214a000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214a000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3519_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip11: gpio_chip@1214b000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214b000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3519_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip12: gpio_chip@1214c000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214c000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3519_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip13: gpio_chip@1214d000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214d000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3519_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip14: gpio_chip@1214e000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214e000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3519_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip16: gpio_chip@12150000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12150000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3519_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ }; ++ ++ pmc@0x120a0000 { ++ compatible = "hisilicon,pmc"; ++ reg = <0x120a0000 0x1000>; ++ }; ++ ++ sysctrl: system-controller@00000000 { ++ compatible = "hisilicon,sysctrl"; ++ reg = <0x12020000 0x1000>; ++ reboot-offset = <0x4>; ++ }; ++ ++ usb_phy: phy { ++ compatible = "hisilicon,hisi-usb-phy"; ++ reg = <0x12030000 0x10000>, <0x12010000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ++ usb3_phy: phy3 { ++ compatible = "hisilicon,hisi-usb3-phy"; ++ reg = <0x10180000 0x10000>, <0x12010000 0x10000>, ++ <0x12030000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ehci@0x10120000 { ++ compatible = "generic-ehci"; ++ reg = <0x10120000 0x10000>; ++ interrupts = <0 19 4>; ++ ++ clocks = <&clock HI3519_USB2_CTRL_UTMI0_REQ>, ++ <&clock HI3519_USB2_HRST_REQ>; ++ clock-names = "usb2_cttl_utmi0_req", "usb2_hrst_req"; ++ }; ++ ++ ohci@0x10110000 { ++ compatible = "generic-ohci"; ++ reg = <0x10110000 0x10000>; ++ interrupts = <0 20 4>; ++ clocks = <&clock HI3519_USB2_CTRL_UTMI0_REQ>, ++ <&clock HI3519_USB2_HRST_REQ>; ++ clock-names = "usb2_cttl_utmi0_req", "usb2_hrst_req"; ++ }; ++ ++ xhci@0x10180000 { ++ compatible = "hisilicon,hi3519-xhci", "generic-xhci"; ++ reg = <0x10180000 0x10000>; ++ interrupts = <0 22 4>; ++ ++ clocks = <&clock HI3519_USB3_CLK>; ++ clock-names = "clk"; ++ }; ++ ++ hiudc@0x10130000 { ++ compatible = "hiudc"; ++ reg = <0x10130000 0x40000>; ++ interrupts = <0 21 4>; ++ ++ clocks = <&clock HI3519_USB2_HRST_REQ>; ++ clock-names = "clk"; ++ }; ++ ++ hiudc3@0x10180000 { ++ compatible = "dwc_usb3"; ++ reg = <0x10180000 0x40000>; ++ interrupts = <0 22 4>; ++ ++ clocks = <&clock HI3519_USB3_CLK>; ++ clock-names = "clk"; ++ }; ++ ++ cci: cci@1ff00000 { ++ compatible = "arm,cci-400"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x1ff00000 0x1000>; ++ ranges = <0x0 0x1ff00000 0x6000>; ++ ++ cci_control0: slave-if@4000 { ++ compatible = "arm,cci-400-ctrl-if"; ++ interface-type = "ace"; ++ reg = <0x2000 0x1000>; ++ }; ++ ++ cci_control1: slave-if@5000 { ++ compatible = "arm,cci-400-ctrl-if"; ++ interface-type = "ace"; ++ reg = <0x3000 0x1000>; ++ }; ++ ++ }; ++ ++ regulators@120a0000 { ++ compatible = "hi35xx,regulators"; ++ reg = <0x120a0000 0x1000>; ++ regulator-num = <2>; ++ regulator-name-array = "regulator-a17","regulator-media"; ++ ++ a17_regulator: a17_regulator{ ++ regulator-name = "regulator-a17"; ++ regulator-min-microvolt = <651216>; ++ regulator-max-microvolt = <1083359>; ++ regulator-always-on; ++ reg_offset = <0x4>; ++ }; ++ ++ media_regulator: media_regulator{ ++ regulator-name = "regulator-media"; ++ regulator-min-microvolt = <649609>; ++ regulator-max-microvolt = <977031>; ++ regulator-always-on; ++ reg_offset = <0xC>; ++ }; ++ }; ++ ++ pmu { ++ compatible = "arm,cortex-a7-pmu", "arm,cortex-a17-pmu"; ++ interrupts = <0 45 4>, ++ <0 46 4>; ++ }; ++ ++ mdio: mdio@100503c0 { ++ compatible = "hisilicon,hisi-gemac-mdio"; ++ reg = <0x100503c0 0x20>; ++ clocks = <&clock HI3519_ETH_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ higmac: ethernet@10050000 { ++ compatible = "hisilicon,higmac"; ++ reg = <0x10050000 0x1000>,<0x120100ec 0x4>; ++ interrupts = <0 25 4>; ++ ++ clocks = <&clock HI3519_ETH_CLK>, ++ <&clock HI3519_ETH_MACIF_CLK>; ++ clock-names = "higmac_clk", ++ "macif_clk"; ++ ++ resets = <&clock 0xcc 0>, ++ <&clock 0xcc 2>, ++ <&clock 0xcc 7>; ++ reset-names = "port_reset", ++ "macif_reset", ++ "phy_reset"; ++ ++ mac-address = [00 00 00 00 00 00]; ++ }; ++ ++ mmc2: himciv200.MMC@0x100e0000 { ++ compatible = "hisilicon,hi3519-himciv200"; ++ reg = <0x100e0000 0x10000>; ++ interrupts = <0 13 4>; ++ ++ clocks = <&clock HI3519_MMC2_CLK>; ++ clock-names = "mmc_clk"; ++ ++ bus-width = <8>; ++ max-frequency = <148500000>; ++ cap-mmc-highspeed; ++ cap-mmc-hw-reset; ++ full-pwr-cycle; ++ mmc-hs400-1_8v; ++ devid = <2>; ++ status = "disabled"; ++ }; ++ ++ mmc0: himciv200.SD@0x100c0000 { ++ compatible = "hisilicon,hi3519-himciv200"; ++ reg = <0x100c0000 0x10000>; ++ interrupts = <0 23 4>; ++ ++ clocks = <&clock HI3519_MMC0_CLK>; ++ clock-names = "mmc_clk"; ++ ++ bus-width = <4>; ++ max-frequency = <148500000>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ devid = <0>; ++ status = "disabled"; ++ }; ++ ++ mmc1: himciv200.SD@0x100d0000 { ++ compatible = "hisilicon,hi3519-himciv200"; ++ reg = <0x100d0000 0x10000>; ++ interrupts = <0 24 4>; ++ ++ clocks = <&clock HI3519_MMC1_CLK>; ++ clock-names = "mmc_clk"; ++ ++ bus-width = <4>; ++ max-frequency = <148500000>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ devid = <1>; ++ status = "disabled"; ++ }; ++ ++ fmc: spi-nor-controller@10000000 { ++ compatible = "hisilicon,hisi-fmc"; ++ reg = <0x10000000 0x1000>, <0x14000000 0x1000000>; ++ reg-names = "control", "memory"; ++ clocks = <&clock HI3519_FMC_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hisfc:spi-nor@0 { ++ compatible = "hisilicon,hisi-sfc"; ++ assigned-clocks = <&clock HI3519_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hisnfc:spi-nand@0 { ++ compatible = "hisilicon,hisi-spi-nand"; ++ assigned-clocks = <&clock HI3519_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hinfc:nand@0 { ++ compatible = "hisilicon,hisi-nand"; ++ assigned-clocks = <&clock HI3519_FMC_CLK>; ++ assigned-clock-rates = <200000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ }; ++ ++}; +diff --git a/arch/arm/boot/dts/hisi-hi3556-demb.dts b/arch/arm/boot/dts/hisi-hi3556-demb.dts +new file mode 100644 +index 0000000..1e99e3e +--- /dev/null ++++ b/arch/arm/boot/dts/hisi-hi3556-demb.dts +@@ -0,0 +1,236 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/dts-v1/; ++#include "hisi-hi3556.dtsi" ++ ++/ { ++ model = "Hisilicon HI3556 DEMO Board"; ++ compatible = "hisilicon,hi3556"; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ enable-method = "hisilicon,hi3556-smp"; ++ ++ cpu@0 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ clock-frequency = ; ++ reg = <0>; ++ cci-control-port = <&cci_control0>; ++ }; ++ ++ /*cpu@100 { ++ compatible = "arm,cortex-a17"; ++ device_type = "cpu"; ++ clock-frequency = ; ++ reg = <0x100>; ++ cci-control-port = <&cci_control1>; ++ };*/ ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x40000000>; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&dual_timer0 { ++ status = "okay"; ++}; ++ ++&i2c_bus0 { ++ status = "disabled"; ++}; ++ ++&i2c_bus1 { ++ status = "disabled"; ++}; ++ ++&i2c_bus2 { ++ status = "disabled"; ++}; ++ ++&i2c_bus3 { ++ status = "okay"; ++}; ++ ++&spi_bus0 { ++ status = "disabled"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++ ++}; ++ ++&spi_bus1 { ++ status = "disabled"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++}; ++ ++&spi_bus2 { ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++}; ++ ++&spi_bus3 { ++ status = "disabled"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++}; ++ ++&hisfc { ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++ ++}; ++ ++&hisnfc { ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ }; ++}; ++ ++&hinfc { ++ hinand { ++ compatible = "jedec,nand"; ++ reg = <0>; ++ nand-max-frequency = <200000000>; ++ }; ++}; ++ ++&mmc0 { ++ status = "okay"; ++}; ++ ++&mmc1 { ++ status = "okay"; ++}; ++ ++&mmc2 { ++ status = "disabled"; ++}; ++ ++&gpio_chip0 { ++ status = "disabled"; ++}; ++ ++&gpio_chip1 { ++ status = "disabled"; ++}; ++ ++&gpio_chip2 { ++ status = "disabled"; ++}; ++ ++&gpio_chip3 { ++ status = "disabled"; ++}; ++ ++&gpio_chip4 { ++ status = "disabled"; ++}; ++ ++&gpio_chip5 { ++ status = "disabled"; ++}; ++ ++&gpio_chip6 { ++ status = "disabled"; ++}; ++ ++&gpio_chip7 { ++ status = "disabled"; ++}; ++ ++&gpio_chip8 { ++ status = "disabled"; ++}; ++ ++&gpio_chip9 { ++ status = "disabled"; ++}; ++ ++&gpio_chip10 { ++ status = "disabled"; ++}; ++ ++&gpio_chip11 { ++ status = "disabled"; ++}; ++ ++&gpio_chip12 { ++ status = "disabled"; ++}; ++ ++&gpio_chip13 { ++ status = "disabled"; ++}; ++ ++&gpio_chip14 { ++ status = "disabled"; ++}; ++ ++&gpio_chip16 { ++ status = "disabled"; ++}; +diff --git a/arch/arm/boot/dts/hisi-hi3556.dtsi b/arch/arm/boot/dts/hisi-hi3556.dtsi +new file mode 100644 +index 0000000..4a92aa6 +--- /dev/null ++++ b/arch/arm/boot/dts/hisi-hi3556.dtsi +@@ -0,0 +1,755 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "skeleton.dtsi" ++#include ++/ { ++ aliases { ++ serial0 = &uart0; ++ i2c0 = &i2c_bus0; ++ i2c1 = &i2c_bus1; ++ i2c2 = &i2c_bus2; ++ i2c3 = &i2c_bus3; ++ spi0 = &spi_bus0; ++ spi1 = &spi_bus1; ++ spi2 = &spi_bus2; ++ spi3 = &spi_bus3; ++ gpio0 = &gpio_chip0; ++ gpio1 = &gpio_chip1; ++ gpio2 = &gpio_chip2; ++ gpio3 = &gpio_chip3; ++ gpio4 = &gpio_chip4; ++ gpio5 = &gpio_chip5; ++ gpio6 = &gpio_chip6; ++ gpio7 = &gpio_chip7; ++ gpio8 = &gpio_chip8; ++ gpio9 = &gpio_chip9; ++ gpio10 = &gpio_chip10; ++ gpio11 = &gpio_chip11; ++ gpio12 = &gpio_chip12; ++ gpio13 = &gpio_chip13; ++ gpio14 = &gpio_chip14; ++ gpio16 = &gpio_chip16; ++ }; ++ ++ gic: interrupt-controller@10300000 { ++ compatible = "arm,cortex-a7-gic"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ /* gic dist base, gic cpu base , no virtual support */ ++ reg = <0x10301000 0x1000>, <0x10302000 0x1000>; ++ }; ++ ++ clock: clock0 { ++ compatible = "hisilicon,hi3556-clock"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ #clock-cells = <1>; ++ #reset-cells = <2>; ++ reg = <0x12010000 0x10000>; ++ }; ++ ++ syscounter { ++ compatible = "arm,armv7-timer"; ++ interrupt-parent = <&gic>; ++ interrupts = <1 13 0xf08>, ++ <1 14 0xf08>; ++ clock-frequency = <24000000>; ++ }; ++ ++ soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ amba { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "arm,amba-bus"; ++ ranges; ++ ++ uart0: uart@12100000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12100000 0x1000>; ++ interrupts = <0 4 4>; ++ clocks = <&clock HI3556_UART0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart1: uart@12101000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12101000 0x1000>; ++ interrupts = <0 5 4>; ++ clocks = <&clock HI3556_UART1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart2: uart@12102000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12102000 0x1000>; ++ interrupts = <0 6 4>; ++ clocks = <&clock HI3556_UART2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart3: uart@12103000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12103000 0x1000>; ++ interrupts = <0 7 4>; ++ clocks = <&clock HI3556_UART3_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart4: uart@12104000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12104000 0x1000>; ++ interrupts = <0 8 4>; ++ clocks = <&clock HI3556_UART4_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ sys: sys@12010000 { ++ compatible = "hisilicon,hi35xx_sys"; ++ reg = <0x12020000 0x10000>, <0x12060000 0x10000>, <0X12030000 0x10000>; ++ reg-names = "sys", "ddr", "misc"; ++ }; ++ ++ mipi: mipi@11300000 { ++ compatible = "hisilicon,hi35xx_mipi"; ++ interrupts = <0 28 4>, <0 29 4>; ++ interrupt-names = "mipi0", "mipi1"; ++ reg = <0x11300000 0x10000>; ++ }; ++ ++ isp: isp@11380000 { ++ compatible = "hisilicon,hi35xx_isp"; ++ interrupts = <0 30 4>, <0 31 4>; ++ interrupt-names = "isp0", "isp1"; ++ }; ++ ++ viu: viu@11380000 { ++ compatible = "hisilicon,hi35xx_viu"; ++ interrupts = <0 30 4>, <0 31 4>; ++ interrupt-names = "viu0", "viu1"; ++ reg = <0x11380000 0x70000>, <0x11480000 0x70000>; ++ reg-names = "viu0", "viu1"; ++ }; ++ ++ vou: vou@11000000 { ++ compatible = "hisilicon,hi35xx_vou"; ++ interrupts = <0 27 4>; ++ reg = <0x11000000 0x20000>; ++ }; ++ ++ tde: tde@11100000 { ++ compatible = "hisilicon,hi35xx_tde"; ++ interrupts = <0 34 4>; ++ reg = <0x11100000 0x10000>; ++ }; ++ ++ fisheye: fisheye@11110000 { ++ compatible = "hisilicon,hi35xx_fisheye"; ++ interrupts = <0 48 4>; ++ reg = <0x11110000 0x10000>; ++ }; ++ ++ vgs: vgs@11120000 { ++ compatible = "hisilicon,hi35xx_vgs"; ++ interrupts = <0 35 4>; ++ reg = <0x11120000 0x10000>; ++ }; ++ ++ vpss: vpss@11180000 { ++ compatible = "hisilicon,hi35xx_vpss"; ++ interrupts = <0 32 4>; ++ reg = <0x11180000 0x10000>; ++ }; ++ ++ vedu: vedu@11280000 { ++ compatible = "hisilicon,hi35xx_vedu"; ++ interrupts = <0 37 4>; ++ reg = <0x11280000 0x10000>; ++ }; ++ ++ jpege: jpege@11200000 { ++ compatible = "hisilicon,hi35xx_jpege"; ++ interrupts = <0 38 4>; ++ reg = <0x11200000 0x10000>; ++ }; ++ ++ aiao: aiao@11080000 { ++ compatible = "hisilicon,hi35xx_aiao"; ++ interrupts = <0 36 4>; ++ reg = <0x11080000 0x3000>; ++ }; ++ ++ ive: ive@11040000 { ++ compatible = "hisilicon,hi35xx_ive"; ++ interrupts = <0 39 4>; ++ reg = <0x11040000 0x10000>; ++ }; ++ ++ fd: fd@11060000 { ++ compatible = "hisilicon,hi35xx_fd"; ++ interrupts = <0 40 4>; ++ reg = <0x11060000 0x10000>; ++ }; ++ ++ pwm: pwm@12130000 { ++ compatible = "hisilicon,pwm"; ++ reg = <0x12130000 0x10000>; ++ }; ++ ++ piris: piris@12145000 { ++ compatible = "hisilicon,piris"; ++ reg = <0x12145000 0x1000>; ++ }; ++ ++ wtdg: wtdg@12080000 { ++ compatible = "hisilicon,hi_wdg"; ++ reg = <0x12080000 0x10000>; ++ reg-names = "wtdg"; ++ }; ++ ++ rtc: rtc@12090000 { ++ compatible = "hisilicon,hi_rtc"; ++ interrupts = <0 1 4>; ++ reg = <0x12090000 0x8000>; ++ }; ++ ++ pwr: wtdg@12098000 { ++ compatible = "hisilicon,hi_pwr"; ++ reg = <0x12098000 0x8000>; ++ reg-names = "pwr"; ++ }; ++ ++ ir: ir@120f0000{ ++ compatible = "hisilicon,hi_ir"; ++ interrupts = <0 15 4>; ++ reg = <0x120f0000 0x10000>; ++ }; ++ ++ pm { ++ compatible = "hisilicon,hibvt-pm"; ++ reg = <0x12020000 0x1000>, <0x12000000 0x1000>; ++ }; ++ ++ pm_hibernate { ++ compatible = "hisilicon,hibvt-pm-hibernate"; ++ reg = <0x12020000 0x1000>; ++ }; ++ ++ dual_timer0: dual_timer@12000000 { ++ compatible = "arm,sp804"; ++ /* timer0 & timer1 */ ++ interrupts = <0 64 4>, <0 65 4>; ++ reg = <0x12000000 0x1000>; ++ clocks = <&clock HI3556_FIXED_3M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer1: dual_timer@12001000 { ++ compatible = "arm,sp804"; ++ /* timer2 & timer3 */ ++ interrupts = <0 66 4>, <0 67 4>; ++ reg = <0x12001000 0x1000>; ++ clocks = <&clock HI3556_FIXED_3M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer2: dual_timer@12002000 { ++ compatible = "arm,sp804"; ++ /* timer4 & timer5 */ ++ interrupts = <0 68 4>, <0 69 4>; ++ reg = <0x12002000 0x1000>; ++ clocks = <&clock HI3556_FIXED_3M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ i2c_bus0: i2c@12110000 { ++ compatible = "hisilicon,hisi-i2c-v110"; ++ reg = <0x12110000 0x100>; ++ clocks = <&clock HI3556_I2C_MUX>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus1: i2c@12111000 { ++ compatible = "hisilicon,hisi-i2c-v110"; ++ reg = <0x12111000 0x100>; ++ clocks = <&clock HI3556_I2C_MUX>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus2: i2c@12112000 { ++ compatible = "hisilicon,hisi-i2c-v110"; ++ reg = <0x12112000 0x100>; ++ clocks = <&clock HI3556_I2C_MUX>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus3: i2c@12113000 { ++ compatible = "hisilicon,hisi-i2c-v110"; ++ reg = <0x12113000 0x100>; ++ clocks = <&clock HI3556_I2C_MUX>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ spi_bus0: spi@12120000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12120000 0x1000>; ++ interrupts = <0 9 4>; ++ clocks = <&clock HI3556_SPI0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ num-cs = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ spi_bus1: spi@12121000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12121000 0x1000>; ++ interrupts = <0 10 4>; ++ clocks = <&clock HI3556_SPI1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ num-cs = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ spi_bus2: spi@12122000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12122000 0x1000>, <0x12030004 0x4>; ++ interrupts = <0 11 4>; ++ clocks = <&clock HI3556_SPI2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ num-cs = <2>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ hisi,spi_cs_sb = <26>; ++ hisi,spi_cs_mask_bit = <0x0c000000>; ++ }; ++ ++ spi_bus3: spi@12123000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12123000 0x1000>; ++ interrupts = <0 12 4>; ++ clocks = <&clock HI3556_SPI3_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ num-cs = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ gpio_chip0: gpio_chip@12140000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12140000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3556_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip1: gpio_chip@12141000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12141000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3556_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip2: gpio_chip@12142000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12142000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3556_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip3: gpio_chip@12143000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12143000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3556_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip4: gpio_chip@12144000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12144000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3556_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip5: gpio_chip@12145000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12145000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3556_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip6: gpio_chip@12146000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12146000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3556_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip7: gpio_chip@12147000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12147000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3556_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip8: gpio_chip@12148000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12148000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3556_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip9: gpio_chip@12149000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12149000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3556_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip10: gpio_chip@1214a000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214a000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3556_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip11: gpio_chip@1214b000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214b000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3556_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip12: gpio_chip@1214c000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214c000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3556_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip13: gpio_chip@1214d000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214d000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3556_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip14: gpio_chip@1214e000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214e000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3556_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip16: gpio_chip@12150000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12150000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3556_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ }; ++ ++ pmc@0x120a0000 { ++ compatible = "hisilicon,pmc"; ++ reg = <0x120a0000 0x1000>; ++ }; ++ ++ sysctrl: system-controller@00000000 { ++ compatible = "hisilicon,sysctrl"; ++ reg = <0x12020000 0x1000>; ++ reboot-offset = <0x4>; ++ }; ++ ++ usb_phy: phy { ++ compatible = "hisilicon,hisi-usb-phy"; ++ reg = <0x12030000 0x10000>, <0x12010000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ++ usb3_phy: phy3 { ++ compatible = "hisilicon,hisi-usb3-phy"; ++ reg = <0x10180000 0x10000>, <0x12010000 0x10000>, ++ <0x12030000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ehci@0x10120000 { ++ compatible = "generic-ehci"; ++ reg = <0x10120000 0x10000>; ++ interrupts = <0 19 4>; ++ ++ clocks = <&clock HI3556_USB2_CTRL_UTMI0_REQ>, ++ <&clock HI3556_USB2_HRST_REQ>; ++ clock-names = "usb2_cttl_utmi0_req", "usb2_hrst_req"; ++ }; ++ ++ ohci@0x10110000 { ++ compatible = "generic-ohci"; ++ reg = <0x10110000 0x10000>; ++ interrupts = <0 20 4>; ++ ++ clocks = <&clock HI3556_USB2_CTRL_UTMI0_REQ>, ++ <&clock HI3556_USB2_HRST_REQ>; ++ clock-names = "usb2_cttl_utmi0_req", "usb2_hrst_req"; ++ }; ++ ++ xhci@0x10180000 { ++ compatible = "hisilicon,hi3556-xhci", "generic-xhci"; ++ reg = <0x10180000 0x10000>; ++ interrupts = <0 22 4>; ++ ++ clocks = <&clock HI3556_USB3_CLK>; ++ clock-names = "clk"; ++ }; ++ ++ hiudc@0x10130000 { ++ compatible = "hiudc"; ++ reg = <0x10130000 0x40000>; ++ interrupts = <0 21 4>; ++ ++ clocks = <&clock HI3556_USB2_HRST_REQ>; ++ clock-names = "clk"; ++ }; ++ ++ hiudc3@0x10180000 { ++ compatible = "dwc_usb3"; ++ reg = <0x10180000 0x40000>; ++ interrupts = <0 22 4>; ++ ++ clocks = <&clock HI3556_USB3_CLK>; ++ clock-names = "clk"; ++ }; ++ ++ cci: cci@1ff00000 { ++ compatible = "arm,cci-400"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x1ff00000 0x1000>; ++ ranges = <0x0 0x1ff00000 0x6000>; ++ ++ cci_control0: slave-if@4000 { ++ compatible = "arm,cci-400-ctrl-if"; ++ interface-type = "ace"; ++ reg = <0x2000 0x1000>; ++ }; ++ ++ cci_control1: slave-if@5000 { ++ compatible = "arm,cci-400-ctrl-if"; ++ interface-type = "ace"; ++ reg = <0x3000 0x1000>; ++ }; ++ ++ }; ++ ++ regulators@120a0000 { ++ compatible = "hi3556,regulators"; ++ reg = <0x120a0000 0x1000>; ++ regulator-num = <2>; ++ regulator-name-array = "regulator-a17","regulator-media"; ++ ++ a17_regulator: a17_regulator{ ++ regulator-name = "regulator-a17"; ++ regulator-min-microvolt = <648633>; ++ regulator-max-microvolt = <1200525>; ++ regulator-always-on; ++ reg_offset = <0x4>; ++ }; ++ ++ media_regulator: media_regulator{ ++ regulator-name = "regulator-media"; ++ regulator-min-microvolt = <649740>; ++ regulator-max-microvolt = <1204331>; ++ regulator-always-on; ++ reg_offset = <0xC>; ++ }; ++ }; ++ ++ pmu { ++ compatible = "arm,cortex-a7-pmu", "arm,cortex-a17-pmu"; ++ interrupts = <0 45 4>, ++ <0 46 4>; ++ }; ++ ++ mmc2: himciv200.MMC@0x100e0000 { ++ compatible = "hisilicon,hi3556-himciv200"; ++ reg = <0x100e0000 0x10000>; ++ interrupts = <0 13 4>; ++ ++ clocks = <&clock HI3556_MMC2_CLK>; ++ clock-names = "mmc_clk"; ++ ++ bus-width = <8>; ++ max-frequency = <148500000>; ++ cap-mmc-highspeed; ++ cap-mmc-hw-reset; ++ full-pwr-cycle; ++ mmc-hs400-1_8v; ++ devid = <2>; ++ status = "disabled"; ++ }; ++ ++ mmc0: himciv200.SD@0x100c0000 { ++ compatible = "hisilicon,hi3556-himciv200"; ++ reg = <0x100c0000 0x10000>; ++ interrupts = <0 23 4>; ++ ++ clocks = <&clock HI3556_MMC0_CLK>; ++ clock-names = "mmc_clk"; ++ ++ bus-width = <4>; ++ max-frequency = <148500000>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ devid = <0>; ++ status = "disabled"; ++ }; ++ ++ mmc1: himciv200.SD@0x100d0000 { ++ compatible = "hisilicon,hi3556-himciv200"; ++ reg = <0x100d0000 0x10000>; ++ interrupts = <0 24 4>; ++ ++ clocks = <&clock HI3556_MMC1_CLK>; ++ clock-names = "mmc_clk"; ++ ++ bus-width = <4>; ++ max-frequency = <148500000>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ devid = <1>; ++ status = "disabled"; ++ }; ++ ++ fmc: spi-nor-controller@10000000 { ++ compatible = "hisilicon,hisi-fmc"; ++ reg = <0x10000000 0x1000>, <0x14000000 0x1000000>; ++ reg-names = "control", "memory"; ++ clocks = <&clock HI3556_FMC_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hisfc:spi-nor@0 { ++ compatible = "hisilicon,hisi-sfc"; ++ assigned-clocks = <&clock HI3556_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hisnfc:spi-nand@0 { ++ compatible = "hisilicon,hisi-spi-nand"; ++ assigned-clocks = <&clock HI3556_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hinfc:nand@0 { ++ compatible = "hisilicon,hisi-nand"; ++ assigned-clocks = <&clock HI3556_FMC_CLK>; ++ assigned-clock-rates = <200000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ }; ++ ++}; +diff --git a/arch/arm/boot/dts/hisi-hi3559-demb.dts b/arch/arm/boot/dts/hisi-hi3559-demb.dts +new file mode 100644 +index 0000000..0fa7209 +--- /dev/null ++++ b/arch/arm/boot/dts/hisi-hi3559-demb.dts +@@ -0,0 +1,236 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/dts-v1/; ++#include "hisi-hi3559.dtsi" ++ ++/ { ++ model = "Hisilicon HI3559 DEMO Board"; ++ compatible = "hisilicon,hi3559"; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ enable-method = "hisilicon,hi3559-smp"; ++ ++ cpu@0 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ clock-frequency = ; ++ reg = <0>; ++ cci-control-port = <&cci_control0>; ++ }; ++ ++ /*cpu@100 { ++ compatible = "arm,cortex-a17"; ++ device_type = "cpu"; ++ clock-frequency = ; ++ reg = <0x100>; ++ cci-control-port = <&cci_control1>; ++ };*/ ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x40000000>; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&dual_timer0 { ++ status = "okay"; ++}; ++ ++&i2c_bus0 { ++ status = "disabled"; ++}; ++ ++&i2c_bus1 { ++ status = "disabled"; ++}; ++ ++&i2c_bus2 { ++ status = "disabled"; ++}; ++ ++&i2c_bus3 { ++ status = "okay"; ++}; ++ ++&spi_bus0 { ++ status = "disabled"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++ ++}; ++ ++&spi_bus1 { ++ status = "disabled"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++}; ++ ++&spi_bus2 { ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ reg = <1>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++}; ++ ++&spi_bus3 { ++ status = "disabled"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ reg = <0>; ++ pl022,interface = <0>; ++ pl022,com-mode = <0>; ++ spi-max-frequency = <24750000>; ++ }; ++}; ++ ++&hisfc { ++ hi_sfc { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ m25p,fast-read; ++ }; ++ ++}; ++ ++&hisnfc { ++ hinand { ++ compatible = "jedec,spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <160000000>; ++ }; ++}; ++ ++&hinfc { ++ hinand { ++ compatible = "jedec,nand"; ++ reg = <0>; ++ nand-max-frequency = <200000000>; ++ }; ++}; ++ ++&mmc0 { ++ status = "okay"; ++}; ++ ++&mmc1 { ++ status = "okay"; ++}; ++ ++&mmc2 { ++ status = "disabled"; ++}; ++ ++&gpio_chip0 { ++ status = "disabled"; ++}; ++ ++&gpio_chip1 { ++ status = "disabled"; ++}; ++ ++&gpio_chip2 { ++ status = "disabled"; ++}; ++ ++&gpio_chip3 { ++ status = "disabled"; ++}; ++ ++&gpio_chip4 { ++ status = "disabled"; ++}; ++ ++&gpio_chip5 { ++ status = "disabled"; ++}; ++ ++&gpio_chip6 { ++ status = "disabled"; ++}; ++ ++&gpio_chip7 { ++ status = "disabled"; ++}; ++ ++&gpio_chip8 { ++ status = "disabled"; ++}; ++ ++&gpio_chip9 { ++ status = "disabled"; ++}; ++ ++&gpio_chip10 { ++ status = "disabled"; ++}; ++ ++&gpio_chip11 { ++ status = "disabled"; ++}; ++ ++&gpio_chip12 { ++ status = "disabled"; ++}; ++ ++&gpio_chip13 { ++ status = "disabled"; ++}; ++ ++&gpio_chip14 { ++ status = "disabled"; ++}; ++ ++&gpio_chip16 { ++ status = "disabled"; ++}; +diff --git a/arch/arm/boot/dts/hisi-hi3559.dtsi b/arch/arm/boot/dts/hisi-hi3559.dtsi +new file mode 100644 +index 0000000..58b6d8c +--- /dev/null ++++ b/arch/arm/boot/dts/hisi-hi3559.dtsi +@@ -0,0 +1,755 @@ ++/* ++ * Copyright (c) 2013-2014 Linaro Ltd. ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "skeleton.dtsi" ++#include ++/ { ++ aliases { ++ serial0 = &uart0; ++ i2c0 = &i2c_bus0; ++ i2c1 = &i2c_bus1; ++ i2c2 = &i2c_bus2; ++ i2c3 = &i2c_bus3; ++ spi0 = &spi_bus0; ++ spi1 = &spi_bus1; ++ spi2 = &spi_bus2; ++ spi3 = &spi_bus3; ++ gpio0 = &gpio_chip0; ++ gpio1 = &gpio_chip1; ++ gpio2 = &gpio_chip2; ++ gpio3 = &gpio_chip3; ++ gpio4 = &gpio_chip4; ++ gpio5 = &gpio_chip5; ++ gpio6 = &gpio_chip6; ++ gpio7 = &gpio_chip7; ++ gpio8 = &gpio_chip8; ++ gpio9 = &gpio_chip9; ++ gpio10 = &gpio_chip10; ++ gpio11 = &gpio_chip11; ++ gpio12 = &gpio_chip12; ++ gpio13 = &gpio_chip13; ++ gpio14 = &gpio_chip14; ++ gpio16 = &gpio_chip16; ++ }; ++ ++ gic: interrupt-controller@10300000 { ++ compatible = "arm,cortex-a7-gic"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ /* gic dist base, gic cpu base , no virtual support */ ++ reg = <0x10301000 0x1000>, <0x10302000 0x1000>; ++ }; ++ ++ clock: clock0 { ++ compatible = "hisilicon,hi3559-clock"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ #clock-cells = <1>; ++ #reset-cells = <2>; ++ reg = <0x12010000 0x10000>; ++ }; ++ ++ syscounter { ++ compatible = "arm,armv7-timer"; ++ interrupt-parent = <&gic>; ++ interrupts = <1 13 0xf08>, ++ <1 14 0xf08>; ++ clock-frequency = <24000000>; ++ }; ++ ++ soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ amba { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "arm,amba-bus"; ++ ranges; ++ ++ uart0: uart@12100000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12100000 0x1000>; ++ interrupts = <0 4 4>; ++ clocks = <&clock HI3559_UART0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart1: uart@12101000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12101000 0x1000>; ++ interrupts = <0 5 4>; ++ clocks = <&clock HI3559_UART1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart2: uart@12102000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12102000 0x1000>; ++ interrupts = <0 6 4>; ++ clocks = <&clock HI3559_UART2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart3: uart@12103000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12103000 0x1000>; ++ interrupts = <0 7 4>; ++ clocks = <&clock HI3559_UART3_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ uart4: uart@12104000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x12104000 0x1000>; ++ interrupts = <0 8 4>; ++ clocks = <&clock HI3559_UART4_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ sys: sys@12010000 { ++ compatible = "hisilicon,hi35xx_sys"; ++ reg = <0x12020000 0x10000>, <0x12060000 0x10000>, <0X12030000 0x10000>; ++ reg-names = "sys", "ddr", "misc"; ++ }; ++ ++ mipi: mipi@11300000 { ++ compatible = "hisilicon,hi35xx_mipi"; ++ interrupts = <0 28 4>, <0 29 4>; ++ interrupt-names = "mipi0", "mipi1"; ++ reg = <0x11300000 0x10000>; ++ }; ++ ++ isp: isp@11380000 { ++ compatible = "hisilicon,hi35xx_isp"; ++ interrupts = <0 30 4>, <0 31 4>; ++ interrupt-names = "isp0", "isp1"; ++ }; ++ ++ viu: viu@11380000 { ++ compatible = "hisilicon,hi35xx_viu"; ++ interrupts = <0 30 4>, <0 31 4>; ++ interrupt-names = "viu0", "viu1"; ++ reg = <0x11380000 0x70000>, <0x11480000 0x70000>; ++ reg-names = "viu0", "viu1"; ++ }; ++ ++ vou: vou@11000000 { ++ compatible = "hisilicon,hi35xx_vou"; ++ interrupts = <0 27 4>; ++ reg = <0x11000000 0x20000>; ++ }; ++ ++ tde: tde@11100000 { ++ compatible = "hisilicon,hi35xx_tde"; ++ interrupts = <0 34 4>; ++ reg = <0x11100000 0x10000>; ++ }; ++ ++ fisheye: fisheye@11110000 { ++ compatible = "hisilicon,hi35xx_fisheye"; ++ interrupts = <0 48 4>; ++ reg = <0x11110000 0x10000>; ++ }; ++ ++ vgs: vgs@11120000 { ++ compatible = "hisilicon,hi35xx_vgs"; ++ interrupts = <0 35 4>; ++ reg = <0x11120000 0x10000>; ++ }; ++ ++ vpss: vpss@11180000 { ++ compatible = "hisilicon,hi35xx_vpss"; ++ interrupts = <0 32 4>; ++ reg = <0x11180000 0x10000>; ++ }; ++ ++ vedu: vedu@11280000 { ++ compatible = "hisilicon,hi35xx_vedu"; ++ interrupts = <0 37 4>; ++ reg = <0x11280000 0x10000>; ++ }; ++ ++ jpege: jpege@11200000 { ++ compatible = "hisilicon,hi35xx_jpege"; ++ interrupts = <0 38 4>; ++ reg = <0x11200000 0x10000>; ++ }; ++ ++ aiao: aiao@11080000 { ++ compatible = "hisilicon,hi35xx_aiao"; ++ interrupts = <0 36 4>; ++ reg = <0x11080000 0x3000>; ++ }; ++ ++ ive: ive@11040000 { ++ compatible = "hisilicon,hi35xx_ive"; ++ interrupts = <0 39 4>; ++ reg = <0x11040000 0x10000>; ++ }; ++ ++ fd: fd@11060000 { ++ compatible = "hisilicon,hi35xx_fd"; ++ interrupts = <0 40 4>; ++ reg = <0x11060000 0x10000>; ++ }; ++ ++ pwm: pwm@12130000 { ++ compatible = "hisilicon,pwm"; ++ reg = <0x12130000 0x10000>; ++ }; ++ ++ piris: piris@12145000 { ++ compatible = "hisilicon,piris"; ++ reg = <0x12145000 0x1000>; ++ }; ++ ++ wtdg: wtdg@12080000 { ++ compatible = "hisilicon,hi_wdg"; ++ reg = <0x12080000 0x10000>; ++ reg-names = "wtdg"; ++ }; ++ ++ rtc: rtc@12090000 { ++ compatible = "hisilicon,hi_rtc"; ++ interrupts = <0 1 4>; ++ reg = <0x12090000 0x8000>; ++ }; ++ ++ pwr: wtdg@12098000 { ++ compatible = "hisilicon,hi_pwr"; ++ reg = <0x12098000 0x8000>; ++ reg-names = "pwr"; ++ }; ++ ++ ir: ir@120f0000{ ++ compatible = "hisilicon,hi_ir"; ++ interrupts = <0 15 4>; ++ reg = <0x120f0000 0x10000>; ++ }; ++ ++ pm { ++ compatible = "hisilicon,hibvt-pm"; ++ reg = <0x12020000 0x1000>, <0x12000000 0x1000>; ++ }; ++ ++ pm_hibernate { ++ compatible = "hisilicon,hibvt-pm-hibernate"; ++ reg = <0x12020000 0x1000>; ++ }; ++ ++ dual_timer0: dual_timer@12000000 { ++ compatible = "arm,sp804"; ++ /* timer0 & timer1 */ ++ interrupts = <0 64 4>, <0 65 4>; ++ reg = <0x12000000 0x1000>; ++ clocks = <&clock HI3559_FIXED_3M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer1: dual_timer@12001000 { ++ compatible = "arm,sp804"; ++ /* timer2 & timer3 */ ++ interrupts = <0 66 4>, <0 67 4>; ++ reg = <0x12001000 0x1000>; ++ clocks = <&clock HI3559_FIXED_3M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ dual_timer2: dual_timer@12002000 { ++ compatible = "arm,sp804"; ++ /* timer4 & timer5 */ ++ interrupts = <0 68 4>, <0 69 4>; ++ reg = <0x12002000 0x1000>; ++ clocks = <&clock HI3559_FIXED_3M>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ }; ++ ++ i2c_bus0: i2c@12110000 { ++ compatible = "hisilicon,hisi-i2c-v110"; ++ reg = <0x12110000 0x100>; ++ clocks = <&clock HI3559_I2C_MUX>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus1: i2c@12111000 { ++ compatible = "hisilicon,hisi-i2c-v110"; ++ reg = <0x12111000 0x100>; ++ clocks = <&clock HI3559_I2C_MUX>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus2: i2c@12112000 { ++ compatible = "hisilicon,hisi-i2c-v110"; ++ reg = <0x12112000 0x100>; ++ clocks = <&clock HI3559_I2C_MUX>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ i2c_bus3: i2c@12113000 { ++ compatible = "hisilicon,hisi-i2c-v110"; ++ reg = <0x12113000 0x100>; ++ clocks = <&clock HI3559_I2C_MUX>; ++ clock-frequency = <100000>; ++ status = "disabled"; ++ }; ++ ++ spi_bus0: spi@12120000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12120000 0x1000>; ++ interrupts = <0 9 4>; ++ clocks = <&clock HI3559_SPI0_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ num-cs = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ spi_bus1: spi@12121000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12121000 0x1000>; ++ interrupts = <0 10 4>; ++ clocks = <&clock HI3559_SPI1_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ num-cs = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ spi_bus2: spi@12122000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12122000 0x1000>, <0x12030004 0x4>; ++ interrupts = <0 11 4>; ++ clocks = <&clock HI3559_SPI2_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ num-cs = <2>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ hisi,spi_cs_sb = <26>; ++ hisi,spi_cs_mask_bit = <0x0c000000>; ++ }; ++ ++ spi_bus3: spi@12123000 { ++ compatible = "arm,pl022", "arm,primecell"; ++ arm,primecell-periphid = <0x00800022>; ++ reg = <0x12123000 0x1000>; ++ interrupts = <0 12 4>; ++ clocks = <&clock HI3559_SPI3_CLK>; ++ clock-names = "apb_pclk"; ++ status = "disabled"; ++ num-cs = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ gpio_chip0: gpio_chip@12140000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12140000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3559_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip1: gpio_chip@12141000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12141000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3559_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip2: gpio_chip@12142000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12142000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3559_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip3: gpio_chip@12143000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12143000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3559_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip4: gpio_chip@12144000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12144000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3559_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip5: gpio_chip@12145000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12145000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3559_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip6: gpio_chip@12146000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12146000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3559_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip7: gpio_chip@12147000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12147000 0x1000>; ++ interrupts = <0 43 4>; ++ clocks = <&clock HI3559_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip8: gpio_chip@12148000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12148000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3559_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip9: gpio_chip@12149000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12149000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3559_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip10: gpio_chip@1214a000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214a000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3559_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip11: gpio_chip@1214b000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214b000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3559_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip12: gpio_chip@1214c000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214c000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3559_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip13: gpio_chip@1214d000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214d000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3559_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip14: gpio_chip@1214e000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x1214e000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3559_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ gpio_chip16: gpio_chip@12150000 { ++ compatible = "arm,pl061", "arm,primecell"; ++ reg = <0x12150000 0x1000>; ++ interrupts = <0 44 4>; ++ clocks = <&clock HI3559_SYSAPB_CLK>; ++ clock-names = "apb_pclk"; ++ #gpio-cells = <2>; ++ status = "disabled"; ++ }; ++ }; ++ ++ pmc@0x120a0000 { ++ compatible = "hisilicon,pmc"; ++ reg = <0x120a0000 0x1000>; ++ }; ++ ++ sysctrl: system-controller@00000000 { ++ compatible = "hisilicon,sysctrl"; ++ reg = <0x12020000 0x1000>; ++ reboot-offset = <0x4>; ++ }; ++ ++ usb_phy: phy { ++ compatible = "hisilicon,hisi-usb-phy"; ++ reg = <0x12030000 0x10000>, <0x12010000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ++ usb3_phy: phy3 { ++ compatible = "hisilicon,hisi-usb3-phy"; ++ reg = <0x10180000 0x10000>, <0x12010000 0x10000>, ++ <0x12030000 0x10000>; ++ #phy-cells = <0>; ++ }; ++ ehci@0x10120000 { ++ compatible = "generic-ehci"; ++ reg = <0x10120000 0x10000>; ++ interrupts = <0 19 4>; ++ ++ clocks = <&clock HI3559_USB2_CTRL_UTMI0_REQ>, ++ <&clock HI3559_USB2_HRST_REQ>; ++ clock-names = "usb2_cttl_utmi0_req", "usb2_hrst_req"; ++ }; ++ ++ ohci@0x10110000 { ++ compatible = "generic-ohci"; ++ reg = <0x10110000 0x10000>; ++ interrupts = <0 20 4>; ++ ++ clocks = <&clock HI3559_USB2_CTRL_UTMI0_REQ>, ++ <&clock HI3559_USB2_HRST_REQ>; ++ clock-names = "usb2_cttl_utmi0_req", "usb2_hrst_req"; ++ }; ++ ++ xhci@0x10180000 { ++ compatible = "hisilicon,hi3559-xhci", "generic-xhci"; ++ reg = <0x10180000 0x10000>; ++ interrupts = <0 22 4>; ++ ++ clocks = <&clock HI3559_USB3_CLK>; ++ clock-names = "clk"; ++ }; ++ ++ hiudc@0x10130000 { ++ compatible = "hiudc"; ++ reg = <0x10130000 0x40000>; ++ interrupts = <0 21 4>; ++ ++ clocks = <&clock HI3559_USB2_HRST_REQ>; ++ clock-names = "clk"; ++ }; ++ ++ hiudc3@0x10180000 { ++ compatible = "dwc_usb3"; ++ reg = <0x10180000 0x40000>; ++ interrupts = <0 22 4>; ++ ++ clocks = <&clock HI3559_USB3_CLK>; ++ clock-names = "clk"; ++ }; ++ ++ cci: cci@1ff00000 { ++ compatible = "arm,cci-400"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x1ff00000 0x1000>; ++ ranges = <0x0 0x1ff00000 0x6000>; ++ ++ cci_control0: slave-if@4000 { ++ compatible = "arm,cci-400-ctrl-if"; ++ interface-type = "ace"; ++ reg = <0x2000 0x1000>; ++ }; ++ ++ cci_control1: slave-if@5000 { ++ compatible = "arm,cci-400-ctrl-if"; ++ interface-type = "ace"; ++ reg = <0x3000 0x1000>; ++ }; ++ ++ }; ++ ++ regulators@120a0000 { ++ compatible = "hi3559,regulators"; ++ reg = <0x120a0000 0x1000>; ++ regulator-num = <2>; ++ regulator-name-array = "regulator-a17","regulator-media"; ++ ++ a17_regulator: a17_regulator{ ++ regulator-name = "regulator-a17"; ++ regulator-min-microvolt = <648633>; ++ regulator-max-microvolt = <1200525>; ++ regulator-always-on; ++ reg_offset = <0x4>; ++ }; ++ ++ media_regulator: media_regulator{ ++ regulator-name = "regulator-media"; ++ regulator-min-microvolt = <649740>; ++ regulator-max-microvolt = <1204331>; ++ regulator-always-on; ++ reg_offset = <0xC>; ++ }; ++ }; ++ ++ pmu { ++ compatible = "arm,cortex-a7-pmu", "arm,cortex-a17-pmu"; ++ interrupts = <0 45 4>, ++ <0 46 4>; ++ }; ++ ++ mmc2: himciv200.MMC@0x100e0000 { ++ compatible = "hisilicon,hi3559-himciv200"; ++ reg = <0x100e0000 0x10000>; ++ interrupts = <0 13 4>; ++ ++ clocks = <&clock HI3559_MMC2_CLK>; ++ clock-names = "mmc_clk"; ++ ++ bus-width = <8>; ++ max-frequency = <148500000>; ++ cap-mmc-highspeed; ++ cap-mmc-hw-reset; ++ full-pwr-cycle; ++ mmc-hs400-1_8v; ++ devid = <2>; ++ status = "disabled"; ++ }; ++ ++ mmc0: himciv200.SD@0x100c0000 { ++ compatible = "hisilicon,hi3559-himciv200"; ++ reg = <0x100c0000 0x10000>; ++ interrupts = <0 23 4>; ++ ++ clocks = <&clock HI3559_MMC0_CLK>; ++ clock-names = "mmc_clk"; ++ ++ bus-width = <4>; ++ max-frequency = <148500000>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ devid = <0>; ++ status = "disabled"; ++ }; ++ ++ mmc1: himciv200.SD@0x100d0000 { ++ compatible = "hisilicon,hi3559-himciv200"; ++ reg = <0x100d0000 0x10000>; ++ interrupts = <0 24 4>; ++ ++ clocks = <&clock HI3559_MMC1_CLK>; ++ clock-names = "mmc_clk"; ++ ++ bus-width = <4>; ++ max-frequency = <148500000>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ devid = <1>; ++ status = "disabled"; ++ }; ++ ++ fmc: spi-nor-controller@10000000 { ++ compatible = "hisilicon,hisi-fmc"; ++ reg = <0x10000000 0x1000>, <0x14000000 0x1000000>; ++ reg-names = "control", "memory"; ++ clocks = <&clock HI3559_FMC_CLK>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hisfc:spi-nor@0 { ++ compatible = "hisilicon,hisi-sfc"; ++ assigned-clocks = <&clock HI3559_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hisnfc:spi-nand@0 { ++ compatible = "hisilicon,hisi-spi-nand"; ++ assigned-clocks = <&clock HI3559_FMC_CLK>; ++ assigned-clock-rates = <24000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ hinfc:nand@0 { ++ compatible = "hisilicon,hisi-nand"; ++ assigned-clocks = <&clock HI3559_FMC_CLK>; ++ assigned-clock-rates = <200000000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; ++ }; ++ ++}; +diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts +index 322fd15..7a2aeac 100644 +--- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts ++++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts +@@ -358,6 +358,204 @@ + }; + }; + ++ etb@0,20010000 { ++ compatible = "arm,coresight-etb10", "arm,primecell"; ++ reg = <0 0x20010000 0 0x1000>; ++ ++ clocks = <&oscclk6a>; ++ clock-names = "apb_pclk"; ++ port { ++ etb_in_port: endpoint@0 { ++ slave-mode; ++ remote-endpoint = <&replicator_out_port0>; ++ }; ++ }; ++ }; ++ ++ tpiu@0,20030000 { ++ compatible = "arm,coresight-tpiu", "arm,primecell"; ++ reg = <0 0x20030000 0 0x1000>; ++ ++ clocks = <&oscclk6a>; ++ clock-names = "apb_pclk"; ++ port { ++ tpiu_in_port: endpoint@0 { ++ slave-mode; ++ remote-endpoint = <&replicator_out_port1>; ++ }; ++ }; ++ }; ++ ++ replicator { ++ /* non-configurable replicators don't show up on the ++ * AMBA bus. As such no need to add "arm,primecell". ++ */ ++ compatible = "arm,coresight-replicator"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* replicator output ports */ ++ port@0 { ++ reg = <0>; ++ replicator_out_port0: endpoint { ++ remote-endpoint = <&etb_in_port>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ replicator_out_port1: endpoint { ++ remote-endpoint = <&tpiu_in_port>; ++ }; ++ }; ++ ++ /* replicator input port */ ++ port@2 { ++ reg = <0>; ++ replicator_in_port0: endpoint { ++ slave-mode; ++ remote-endpoint = <&funnel_out_port0>; ++ }; ++ }; ++ }; ++ }; ++ ++ funnel@0,20040000 { ++ compatible = "arm,coresight-funnel", "arm,primecell"; ++ reg = <0 0x20040000 0 0x1000>; ++ ++ clocks = <&oscclk6a>; ++ clock-names = "apb_pclk"; ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* funnel output port */ ++ port@0 { ++ reg = <0>; ++ funnel_out_port0: endpoint { ++ remote-endpoint = ++ <&replicator_in_port0>; ++ }; ++ }; ++ ++ /* funnel input ports */ ++ port@1 { ++ reg = <0>; ++ funnel_in_port0: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm0_out_port>; ++ }; ++ }; ++ ++ port@2 { ++ reg = <1>; ++ funnel_in_port1: endpoint { ++ slave-mode; ++ remote-endpoint = <&ptm1_out_port>; ++ }; ++ }; ++ ++ port@3 { ++ reg = <2>; ++ funnel_in_port2: endpoint { ++ slave-mode; ++ remote-endpoint = <&etm0_out_port>; ++ }; ++ }; ++ ++ /* Input port #3 is for ITM, not supported here */ ++ ++ port@4 { ++ reg = <4>; ++ funnel_in_port4: endpoint { ++ slave-mode; ++ remote-endpoint = <&etm1_out_port>; ++ }; ++ }; ++ ++ port@5 { ++ reg = <5>; ++ funnel_in_port5: endpoint { ++ slave-mode; ++ remote-endpoint = <&etm2_out_port>; ++ }; ++ }; ++ }; ++ }; ++ ++ ptm@0,2201c000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0x2201c000 0 0x1000>; ++ ++ cpu = <&cpu0>; ++ clocks = <&oscclk6a>; ++ clock-names = "apb_pclk"; ++ port { ++ ptm0_out_port: endpoint { ++ remote-endpoint = <&funnel_in_port0>; ++ }; ++ }; ++ }; ++ ++ ptm@0,2201d000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0x2201d000 0 0x1000>; ++ ++ cpu = <&cpu1>; ++ clocks = <&oscclk6a>; ++ clock-names = "apb_pclk"; ++ port { ++ ptm1_out_port: endpoint { ++ remote-endpoint = <&funnel_in_port1>; ++ }; ++ }; ++ }; ++ ++ etm@0,2203c000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0x2203c000 0 0x1000>; ++ ++ cpu = <&cpu2>; ++ clocks = <&oscclk6a>; ++ clock-names = "apb_pclk"; ++ port { ++ etm0_out_port: endpoint { ++ remote-endpoint = <&funnel_in_port2>; ++ }; ++ }; ++ }; ++ ++ etm@0,2203d000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0x2203d000 0 0x1000>; ++ ++ cpu = <&cpu3>; ++ clocks = <&oscclk6a>; ++ clock-names = "apb_pclk"; ++ port { ++ etm1_out_port: endpoint { ++ remote-endpoint = <&funnel_in_port4>; ++ }; ++ }; ++ }; ++ ++ etm@0,2203e000 { ++ compatible = "arm,coresight-etm3x", "arm,primecell"; ++ reg = <0 0x2203e000 0 0x1000>; ++ ++ cpu = <&cpu4>; ++ clocks = <&oscclk6a>; ++ clock-names = "apb_pclk"; ++ port { ++ etm2_out_port: endpoint { ++ remote-endpoint = <&funnel_in_port5>; ++ }; ++ }; ++ }; ++ + smb { + compatible = "simple-bus"; + +diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig +index c3a4e9c..f4a38a7 100644 +--- a/arch/arm/common/Kconfig ++++ b/arch/arm/common/Kconfig +@@ -20,3 +20,7 @@ config SHARP_SCOOP + + config TI_PRIV_EDMA + bool ++ ++config FIQ_GLUE ++ bool ++ select FIQ +diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile +index 70b1eff..5748afd 100644 +--- a/arch/arm/common/Makefile ++++ b/arch/arm/common/Makefile +@@ -4,6 +4,7 @@ + + obj-y += firmware.o + ++obj-$(CONFIG_FIQ_GLUE) += fiq_glue.o fiq_glue_setup.o + obj-$(CONFIG_ICST) += icst.o + obj-$(CONFIG_SA1111) += sa1111.o + obj-$(CONFIG_DMABOUNCE) += dmabounce.o +diff --git a/arch/arm/common/fiq_glue.S b/arch/arm/common/fiq_glue.S +new file mode 100644 +index 0000000..24b42ce +--- /dev/null ++++ b/arch/arm/common/fiq_glue.S +@@ -0,0 +1,118 @@ ++/* ++ * Copyright (C) 2008 Google, 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. ++ * ++ */ ++ ++#include ++#include ++ ++ .text ++ ++ .global fiq_glue_end ++ ++ /* fiq stack: r0-r15,cpsr,spsr of interrupted mode */ ++ ++ENTRY(fiq_glue) ++ /* store pc, cpsr from previous mode, reserve space for spsr */ ++ mrs r12, spsr ++ sub lr, lr, #4 ++ subs r10, #1 ++ bne nested_fiq ++ ++ str r12, [sp, #-8]! ++ str lr, [sp, #-4]! ++ ++ /* store r8-r14 from previous mode */ ++ sub sp, sp, #(7 * 4) ++ stmia sp, {r8-r14}^ ++ nop ++ ++ /* store r0-r7 from previous mode */ ++ stmfd sp!, {r0-r7} ++ ++ /* setup func(data,regs) arguments */ ++ mov r0, r9 ++ mov r1, sp ++ mov r3, r8 ++ ++ mov r7, sp ++ ++ /* Get sp and lr from non-user modes */ ++ and r4, r12, #MODE_MASK ++ cmp r4, #USR_MODE ++ beq fiq_from_usr_mode ++ ++ mov r7, sp ++ orr r4, r4, #(PSR_I_BIT | PSR_F_BIT) ++ msr cpsr_c, r4 ++ str sp, [r7, #(4 * 13)] ++ str lr, [r7, #(4 * 14)] ++ mrs r5, spsr ++ str r5, [r7, #(4 * 17)] ++ ++ cmp r4, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT) ++ /* use fiq stack if we reenter this mode */ ++ subne sp, r7, #(4 * 3) ++ ++fiq_from_usr_mode: ++ msr cpsr_c, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT) ++ mov r2, sp ++ sub sp, r7, #12 ++ stmfd sp!, {r2, ip, lr} ++ /* call func(data,regs) */ ++ blx r3 ++ ldmfd sp, {r2, ip, lr} ++ mov sp, r2 ++ ++ /* restore/discard saved state */ ++ cmp r4, #USR_MODE ++ beq fiq_from_usr_mode_exit ++ ++ msr cpsr_c, r4 ++ ldr sp, [r7, #(4 * 13)] ++ ldr lr, [r7, #(4 * 14)] ++ msr spsr_cxsf, r5 ++ ++fiq_from_usr_mode_exit: ++ msr cpsr_c, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT) ++ ++ ldmfd sp!, {r0-r7} ++ ldr lr, [sp, #(4 * 7)] ++ ldr r12, [sp, #(4 * 8)] ++ add sp, sp, #(10 * 4) ++exit_fiq: ++ msr spsr_cxsf, r12 ++ add r10, #1 ++ cmp r11, #0 ++ moveqs pc, lr ++ bx r11 /* jump to custom fiq return function */ ++ ++nested_fiq: ++ orr r12, r12, #(PSR_F_BIT) ++ b exit_fiq ++ ++fiq_glue_end: ++ ++ENTRY(fiq_glue_setup) /* func, data, sp, smc call number */ ++ stmfd sp!, {r4} ++ mrs r4, cpsr ++ msr cpsr_c, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT) ++ movs r8, r0 ++ mov r9, r1 ++ mov sp, r2 ++ mov r11, r3 ++ moveq r10, #0 ++ movne r10, #1 ++ msr cpsr_c, r4 ++ ldmfd sp!, {r4} ++ bx lr ++ +diff --git a/arch/arm/common/fiq_glue_setup.c b/arch/arm/common/fiq_glue_setup.c +new file mode 100644 +index 0000000..8cb1b61 +--- /dev/null ++++ b/arch/arm/common/fiq_glue_setup.c +@@ -0,0 +1,147 @@ ++/* ++ * Copyright (C) 2010 Google, 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++extern unsigned char fiq_glue, fiq_glue_end; ++extern void fiq_glue_setup(void *func, void *data, void *sp, ++ fiq_return_handler_t fiq_return_handler); ++ ++static struct fiq_handler fiq_debbuger_fiq_handler = { ++ .name = "fiq_glue", ++}; ++DEFINE_PER_CPU(void *, fiq_stack); ++static struct fiq_glue_handler *current_handler; ++static fiq_return_handler_t fiq_return_handler; ++static DEFINE_MUTEX(fiq_glue_lock); ++ ++static void fiq_glue_setup_helper(void *info) ++{ ++ struct fiq_glue_handler *handler = info; ++ fiq_glue_setup(handler->fiq, handler, ++ __get_cpu_var(fiq_stack) + THREAD_START_SP, ++ fiq_return_handler); ++} ++ ++int fiq_glue_register_handler(struct fiq_glue_handler *handler) ++{ ++ int ret; ++ int cpu; ++ ++ if (!handler || !handler->fiq) ++ return -EINVAL; ++ ++ mutex_lock(&fiq_glue_lock); ++ if (fiq_stack) { ++ ret = -EBUSY; ++ goto err_busy; ++ } ++ ++ for_each_possible_cpu(cpu) { ++ void *stack; ++ stack = (void *)__get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER); ++ if (WARN_ON(!stack)) { ++ ret = -ENOMEM; ++ goto err_alloc_fiq_stack; ++ } ++ per_cpu(fiq_stack, cpu) = stack; ++ } ++ ++ ret = claim_fiq(&fiq_debbuger_fiq_handler); ++ if (WARN_ON(ret)) ++ goto err_claim_fiq; ++ ++ current_handler = handler; ++ on_each_cpu(fiq_glue_setup_helper, handler, true); ++ set_fiq_handler(&fiq_glue, &fiq_glue_end - &fiq_glue); ++ ++ mutex_unlock(&fiq_glue_lock); ++ return 0; ++ ++err_claim_fiq: ++err_alloc_fiq_stack: ++ for_each_possible_cpu(cpu) { ++ __free_pages(per_cpu(fiq_stack, cpu), THREAD_SIZE_ORDER); ++ per_cpu(fiq_stack, cpu) = NULL; ++ } ++err_busy: ++ mutex_unlock(&fiq_glue_lock); ++ return ret; ++} ++ ++static void fiq_glue_update_return_handler(void (*fiq_return)(void)) ++{ ++ fiq_return_handler = fiq_return; ++ if (current_handler) ++ on_each_cpu(fiq_glue_setup_helper, current_handler, true); ++} ++ ++int fiq_glue_set_return_handler(void (*fiq_return)(void)) ++{ ++ int ret; ++ ++ mutex_lock(&fiq_glue_lock); ++ if (fiq_return_handler) { ++ ret = -EBUSY; ++ goto err_busy; ++ } ++ fiq_glue_update_return_handler(fiq_return); ++ ret = 0; ++err_busy: ++ mutex_unlock(&fiq_glue_lock); ++ ++ return ret; ++} ++EXPORT_SYMBOL(fiq_glue_set_return_handler); ++ ++int fiq_glue_clear_return_handler(void (*fiq_return)(void)) ++{ ++ int ret; ++ ++ mutex_lock(&fiq_glue_lock); ++ if (WARN_ON(fiq_return_handler != fiq_return)) { ++ ret = -EINVAL; ++ goto err_inval; ++ } ++ fiq_glue_update_return_handler(NULL); ++ ret = 0; ++err_inval: ++ mutex_unlock(&fiq_glue_lock); ++ ++ return ret; ++} ++EXPORT_SYMBOL(fiq_glue_clear_return_handler); ++ ++/** ++ * fiq_glue_resume - Restore fiqs after suspend or low power idle states ++ * ++ * This must be called before calling local_fiq_enable after returning from a ++ * power state where the fiq mode registers were lost. If a driver provided ++ * a resume hook when it registered the handler it will be called. ++ */ ++ ++void fiq_glue_resume(void) ++{ ++ if (!current_handler) ++ return; ++ fiq_glue_setup(current_handler->fiq, current_handler, ++ __get_cpu_var(fiq_stack) + THREAD_START_SP, ++ fiq_return_handler); ++ if (current_handler->resume) ++ current_handler->resume(current_handler); ++} ++ +diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c +index 1921132..687bafe 100644 +--- a/arch/arm/common/timer-sp.c ++++ b/arch/arm/common/timer-sp.c +@@ -226,6 +226,10 @@ static void __init sp804_of_init(struct device_node *np) + writel(0, base + TIMER_CTRL); + writel(0, base + TIMER_2_BASE + TIMER_CTRL); + ++ /* Ensure timer interrupts are clear */ ++ writel(1, base + TIMER_INTCLR); ++ writel(1, base + TIMER_2_BASE + TIMER_INTCLR); ++ + if (initialized || !of_device_is_available(np)) + goto err; + +diff --git a/arch/arm/configs/hi3516av200_big_little_defconfig b/arch/arm/configs/hi3516av200_big_little_defconfig +new file mode 100644 +index 0000000..afed80c +--- /dev/null ++++ b/arch/arm/configs/hi3516av200_big_little_defconfig +@@ -0,0 +1,2599 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_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_GENERIC_BUG=y ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++# CONFIG_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++# CONFIG_NO_HZ_FULL is not set ++CONFIG_NO_HZ=y ++# 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_TREE_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++# CONFIG_RCU_USER_QS is not set ++CONFIG_RCU_FANOUT=32 ++CONFIG_RCU_FANOUT_LEAF=16 ++# CONFIG_RCU_FANOUT_EXACT is not set ++# CONFIG_RCU_FAST_NO_HZ is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_RCU_NOCB_CPU is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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=y ++CONFIG_SLUB_DEBUG=y ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_STOP_MACHINE=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++# CONFIG_ARCH_HI3519V101 is not set ++CONFIG_ARCH_HI3516AV200=y ++# CONFIG_ARCH_HI3559 is not set ++# CONFIG_ARCH_HI3556 is not set ++CONFIG_PMC=y ++# CONFIG_ARCH_HI3536C is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_643719 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_754327 is not set ++# CONFIG_ARM_ERRATA_764369 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_798181 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++CONFIG_SMP=y ++CONFIG_SMP_ON_UP=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++CONFIG_SCHED_MC=y ++# CONFIG_SCHED_SMT is not set ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_SCHED_HMP=y ++# CONFIG_SCHED_HMP_PRIO_FILTER is not set ++CONFIG_HMP_FAST_CPU_MASK="" ++CONFIG_HMP_SLOW_CPU_MASK="" ++CONFIG_HMP_VARIABLE_SCALE=y ++# CONFIG_HMP_FREQUENCY_INVARIANT_SCALE is not set ++# CONFIG_SCHED_HMP_LITTLE_PACKING is not set ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++# CONFIG_MCPM is not set ++# CONFIG_BIG_LITTLE is not set ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++CONFIG_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_ARM_PSCI is not set ++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_THUMB2_KERNEL 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=y ++# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# CONFIG_CLEANCACHE is not set ++# CONFIG_FRONTSWAP is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++CONFIG_CMA_AREAS=7 ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++CONFIG_AUTO_ZRELADDR=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_INTERACTIVE=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPUFREQ_DT=y ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++ ++# ++# CPU Idle ++# ++CONFIG_CPU_IDLE=y ++CONFIG_CPU_IDLE_GOV_LADDER=y ++CONFIG_CPU_IDLE_GOV_MENU=y ++ ++# ++# ARM CPU Idle Drivers ++# ++CONFIG_ARM_HI3516AV200_CPUIDLE=y ++# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++CONFIG_VFP=y ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HISI_SNAPSHOT_BOOT=y ++# CONFIG_DEFAULT_MTD is not set ++CONFIG_DEFAULT_DDR=y ++CONFIG_SNAPSHOT_BUF_START=0x8a000000 ++CONFIG_SNAPSHOT_BUF_SIZE=0x4000000 ++CONFIG_HIBERNATION=y ++CONFIG_GZIP_COMPRESS=y ++CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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=m ++# 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_GENEVE 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=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# CONFIG_DMA_SHARED_BUFFER is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=16 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++CONFIG_ARM_CCI=y ++# 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_SWAP is not set ++CONFIG_HIFMC=y ++CONFIG_HIFMC_SPI_NAND=y ++# CONFIG_HIFMC_NAND 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 is not set ++# 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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HIFMC100_NAND is not set ++CONFIG_HIFMC100_SPI_NAND=y ++CONFIG_SPI_NAND_MAX_CHIP_NUM=1 ++# CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE 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_SPI_NOR_USE_4K_SECTORS is not set ++CONFIG_SPI_HISI_SFC=y ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++# CONFIG_MTD_UBI is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++CONFIG_HISI_REG=y ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++CONFIG_ETHERNET=y ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC 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_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# CONFIG_HIETH_SWITCH_FABRIC 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_ETHOC is not set ++# CONFIG_NET_VENDOR_QUALCOMM 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_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY 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_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_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_ST_ASC 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_DCC_TTY 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_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_HIBVT is not set ++CONFIG_I2C_HISI_V110=y ++# CONFIG_I2C_NOMADIK 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_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_OC_TINY is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_ARCH_WANT_OPTIONAL_GPIOLIB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_DEVRES=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_GENERIC_PLATFORM is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_EM is not set ++# CONFIG_GPIO_ZEVIO is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_SCH311X is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_GRGPIO is not set ++ ++# ++# I2C GPIO expanders: ++# ++# 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_ADP5588 is not set ++# CONFIG_GPIO_ADNP is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_GPIO_MC33880 is not set ++# CONFIG_GPIO_74X164 is not set ++ ++# ++# AC97 GPIO expanders: ++# ++ ++# ++# LPC GPIO expanders: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++ ++# ++# USB GPIO expanders: ++# ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_BCM590XX is not set ++# CONFIG_MFD_AXP20X 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_EGPIO 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X is not set ++# CONFIG_MFD_TPS65910 is not set ++# CONFIG_MFD_TPS65912 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_XHCI_HISILICON=y ++CONFIG_USB_EHCI_HCD=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_HCD is not set ++# CONFIG_USB_FOTG210_HCD is not set ++# CONFIG_USB_MAX3421_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_SISUSBVGA 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_OTG_WAKELOCK is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_AUTO_SWITCH is not set ++# CONFIG_HIUSB_DEVICE3_0 is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_ACM=m ++CONFIG_USB_U_SERIAL=m ++CONFIG_USB_U_ETHER=m ++CONFIG_USB_F_SERIAL=m ++CONFIG_USB_F_OBEX=m ++CONFIG_USB_F_ECM=m ++CONFIG_USB_F_SUBSET=m ++CONFIG_USB_F_RNDIS=m ++CONFIG_USB_F_MASS_STORAGE=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++CONFIG_USB_ETH=m ++CONFIG_USB_ETH_RNDIS=y ++# CONFIG_USB_ETH_EEM is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++CONFIG_USB_G_SERIAL=m ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_UWB is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# 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_HIMCIV200=y ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=y ++CONFIG_PHY_HISI_USB3=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_IO_BASE=0x10030000 ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE 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=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_RCU_CPU_STALL_INFO is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_HASH=y ++CONFIG_CRYPTO_HASH2=y ++# CONFIG_CRYPTO_MANAGER is not set ++# CONFIG_CRYPTO_MANAGER2 is not set ++# CONFIG_CRYPTO_USER is not set ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_PCRYPT is not set ++# 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_SEQIV is not set ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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_ZLIB is not set ++# CONFIG_CRYPTO_LZO 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3516av200_big_little_nand_defconfig b/arch/arm/configs/hi3516av200_big_little_nand_defconfig +new file mode 100644 +index 0000000..3990e3f +--- /dev/null ++++ b/arch/arm/configs/hi3516av200_big_little_nand_defconfig +@@ -0,0 +1,2597 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_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_GENERIC_BUG=y ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++# CONFIG_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++# CONFIG_NO_HZ_FULL is not set ++CONFIG_NO_HZ=y ++# 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_TREE_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++# CONFIG_RCU_USER_QS is not set ++CONFIG_RCU_FANOUT=32 ++CONFIG_RCU_FANOUT_LEAF=16 ++# CONFIG_RCU_FANOUT_EXACT is not set ++# CONFIG_RCU_FAST_NO_HZ is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_RCU_NOCB_CPU is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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=y ++CONFIG_SLUB_DEBUG=y ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_STOP_MACHINE=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++# CONFIG_ARCH_HI3519V101 is not set ++CONFIG_ARCH_HI3516AV200=y ++# CONFIG_ARCH_HI3559 is not set ++# CONFIG_ARCH_HI3556 is not set ++CONFIG_PMC=y ++# CONFIG_ARCH_HI3536C is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_643719 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_754327 is not set ++# CONFIG_ARM_ERRATA_764369 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_798181 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++CONFIG_SMP=y ++CONFIG_SMP_ON_UP=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++CONFIG_SCHED_MC=y ++# CONFIG_SCHED_SMT is not set ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_SCHED_HMP=y ++# CONFIG_SCHED_HMP_PRIO_FILTER is not set ++CONFIG_HMP_FAST_CPU_MASK="" ++CONFIG_HMP_SLOW_CPU_MASK="" ++CONFIG_HMP_VARIABLE_SCALE=y ++# CONFIG_HMP_FREQUENCY_INVARIANT_SCALE is not set ++# CONFIG_SCHED_HMP_LITTLE_PACKING is not set ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++# CONFIG_MCPM is not set ++# CONFIG_BIG_LITTLE is not set ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++CONFIG_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_ARM_PSCI is not set ++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_THUMB2_KERNEL 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=y ++# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# CONFIG_CLEANCACHE is not set ++# CONFIG_FRONTSWAP is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++CONFIG_CMA_AREAS=7 ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++CONFIG_AUTO_ZRELADDR=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_INTERACTIVE=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPUFREQ_DT=y ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++ ++# ++# CPU Idle ++# ++CONFIG_CPU_IDLE=y ++CONFIG_CPU_IDLE_GOV_LADDER=y ++CONFIG_CPU_IDLE_GOV_MENU=y ++ ++# ++# ARM CPU Idle Drivers ++# ++CONFIG_ARM_HI3516AV200_CPUIDLE=y ++# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++CONFIG_VFP=y ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HISI_SNAPSHOT_BOOT=y ++# CONFIG_DEFAULT_MTD is not set ++CONFIG_DEFAULT_DDR=y ++CONFIG_SNAPSHOT_BUF_START=0x8a000000 ++CONFIG_SNAPSHOT_BUF_SIZE=0x4000000 ++CONFIG_HIBERNATION=y ++CONFIG_GZIP_COMPRESS=y ++CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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=m ++# 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_GENEVE 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=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# CONFIG_DMA_SHARED_BUFFER is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=16 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++CONFIG_ARM_CCI=y ++# 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_SWAP is not set ++CONFIG_HIFMC=y ++# CONFIG_HIFMC_SPI_NAND is not set ++CONFIG_HIFMC_NAND=y ++ ++# ++# 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_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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++CONFIG_HIFMC100_NAND=y ++CONFIG_HIFMC100_MAX_NAND_CHIP=1 ++# CONFIG_HIFMC100_NAND_EDO_MODE is not set ++CONFIG_RW_H_WIDTH=10 ++CONFIG_R_L_WIDTH=10 ++CONFIG_W_L_WIDTH=10 ++# CONFIG_HIFMC100_NAND_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_NAND_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_NAND_PAGESIZE_AUTO_ECC_NONE 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 is not set ++# CONFIG_MTD_UBI is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++CONFIG_HISI_REG=y ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++CONFIG_ETHERNET=y ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC 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_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# CONFIG_HIETH_SWITCH_FABRIC 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_ETHOC is not set ++# CONFIG_NET_VENDOR_QUALCOMM 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_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY 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_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_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_ST_ASC 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_DCC_TTY 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_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_HIBVT is not set ++CONFIG_I2C_HISI_V110=y ++# CONFIG_I2C_NOMADIK 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_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_OC_TINY is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_ARCH_WANT_OPTIONAL_GPIOLIB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_DEVRES=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_GENERIC_PLATFORM is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_EM is not set ++# CONFIG_GPIO_ZEVIO is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_SCH311X is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_GRGPIO is not set ++ ++# ++# I2C GPIO expanders: ++# ++# 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_ADP5588 is not set ++# CONFIG_GPIO_ADNP is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_GPIO_MC33880 is not set ++# CONFIG_GPIO_74X164 is not set ++ ++# ++# AC97 GPIO expanders: ++# ++ ++# ++# LPC GPIO expanders: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++ ++# ++# USB GPIO expanders: ++# ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_BCM590XX is not set ++# CONFIG_MFD_AXP20X 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_EGPIO 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X is not set ++# CONFIG_MFD_TPS65910 is not set ++# CONFIG_MFD_TPS65912 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_XHCI_HISILICON=y ++CONFIG_USB_EHCI_HCD=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_HCD is not set ++# CONFIG_USB_FOTG210_HCD is not set ++# CONFIG_USB_MAX3421_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_SISUSBVGA 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_OTG_WAKELOCK is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_AUTO_SWITCH is not set ++# CONFIG_HIUSB_DEVICE3_0 is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_ACM=m ++CONFIG_USB_U_SERIAL=m ++CONFIG_USB_U_ETHER=m ++CONFIG_USB_F_SERIAL=m ++CONFIG_USB_F_OBEX=m ++CONFIG_USB_F_ECM=m ++CONFIG_USB_F_SUBSET=m ++CONFIG_USB_F_RNDIS=m ++CONFIG_USB_F_MASS_STORAGE=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++CONFIG_USB_ETH=m ++CONFIG_USB_ETH_RNDIS=y ++# CONFIG_USB_ETH_EEM is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++CONFIG_USB_G_SERIAL=m ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_UWB is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# 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_HIMCIV200=y ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=y ++CONFIG_PHY_HISI_USB3=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_IO_BASE=0x10030000 ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE 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=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_RCU_CPU_STALL_INFO is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_HASH=y ++CONFIG_CRYPTO_HASH2=y ++# CONFIG_CRYPTO_MANAGER is not set ++# CONFIG_CRYPTO_MANAGER2 is not set ++# CONFIG_CRYPTO_USER is not set ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_PCRYPT is not set ++# 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_SEQIV is not set ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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_ZLIB is not set ++# CONFIG_CRYPTO_LZO 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3516cv300_full_defconfig b/arch/arm/configs/hi3516cv300_full_defconfig +new file mode 100644 +index 0000000..91018d9d +--- /dev/null ++++ b/arch/arm/configs/hi3516cv300_full_defconfig +@@ -0,0 +1,2531 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=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_GENERIC_BUG=y ++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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++CONFIG_NO_HZ=y ++# CONFIG_HIGH_RES_TIMERS is not set ++ ++# ++# CPU/Task time and stats accounting ++# ++CONFIG_VIRT_CPU_ACCOUNTING=y ++# CONFIG_TICK_CPU_ACCOUNTING is not set ++CONFIG_VIRT_CPU_ACCOUNTING_GEN=y ++# 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_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++# CONFIG_RCU_STALL_COMMON is not set ++CONFIG_CONTEXT_TRACKING=y ++# CONFIG_CONTEXT_TRACKING_FORCE is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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=y ++CONFIG_SLUB_DEBUG=y ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL is not set ++# CONFIG_UPROBES is not set ++# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set ++CONFIG_ARCH_USE_BUILTIN_BSWAP=y ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=y ++CONFIG_HAVE_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V4 is not set ++# CONFIG_ARCH_MULTI_V4T is not set ++CONFIG_ARCH_MULTI_V5=y ++CONFIG_ARCH_MULTI_V4_V5=y ++# CONFIG_ARCH_MULTI_V6 is not set ++# CONFIG_ARCH_MULTI_V7 is not set ++CONFIG_ARCH_MULTI_CPU_AUTO=y ++# CONFIG_ARCH_MVEBU is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++CONFIG_ARCH_HI3516CV300=y ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MXS is not set ++# CONFIG_ARCH_NOMADIK is not set ++# CONFIG_ARCH_NSPIRE is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_U300 is not set ++# CONFIG_ARCH_WM8505 is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_ARM926T=y ++CONFIG_CPU_32v5=y ++CONFIG_CPU_ABRT_EV5TJ=y ++CONFIG_CPU_PABRT_LEGACY=y ++CONFIG_CPU_CACHE_VIVT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++CONFIG_CPU_USE_DOMAINS=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_DCACHE_WRITETHROUGH is not set ++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set ++CONFIG_NEED_KUSER_HELPERS=y ++CONFIG_KUSER_HELPERS=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT=5 ++CONFIG_MULTI_IRQ_HANDLER=y ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_VMSPLIT_3G=y ++# 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++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_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=999999 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_NEED_PER_CPU_KM=y ++# CONFIG_CLEANCACHE is not set ++# CONFIG_FRONTSWAP is not set ++# CONFIG_CMA is not set ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# 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_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HISI_SNAPSHOT_BOOT=y ++# CONFIG_DEFAULT_MTD is not set ++CONFIG_DEFAULT_DDR=y ++CONFIG_SNAPSHOT_BUF_START=0x8a000000 ++CONFIG_SNAPSHOT_BUF_SIZE=0x4000000 ++CONFIG_HIBERNATION=y ++CONFIG_GZIP_COMPRESS=y ++CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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=m ++# 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_GENEVE 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=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE 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_SWAP is not set ++CONFIG_HIFMC=y ++CONFIG_HIFMC_SPI_NAND=y ++# CONFIG_HIFMC_NAND 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 is not set ++# 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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_MTD_NAND_HINFC610 is not set ++# CONFIG_HIFMC100_NAND is not set ++CONFIG_HIFMC100_SPI_NAND=y ++CONFIG_SPI_NAND_MAX_CHIP_NUM=1 ++# CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE 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_SPI_NOR_USE_4K_SECTORS is not set ++CONFIG_SPI_HISI_SFC=y ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++CONFIG_ETHERNET=y ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC 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_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++CONFIG_HISI_FEMAC=y ++# CONFIG_HIETH_GMAC is not set ++# CONFIG_HIETH_SWITCH_FABRIC 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=y ++# CONFIG_ENC28J60 is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_ETHOC is not set ++# CONFIG_NET_VENDOR_QUALCOMM 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_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY 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_BCM_UNIMAC is not set ++CONFIG_MDIO_HISI_FEMAC=y ++# CONFIG_MDIO_HISI_GEMAC 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_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_ST_ASC is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_HW_RANDOM=y ++# CONFIG_HW_RANDOM_TIMERIOMEM is not set ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++# CONFIG_DCC_TTY 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=m ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set ++# CONFIG_I2C_MUX_GPIO is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PCA954x is not set ++# CONFIG_I2C_MUX_PINCTRL 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_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_GPIO is not set ++CONFIG_I2C_HIBVT=y ++# CONFIG_I2C_HISI_V110 is not set ++# CONFIG_I2C_NOMADIK 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_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_OC_TINY is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_DEVRES=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_GENERIC_PLATFORM is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_EM is not set ++# CONFIG_GPIO_ZEVIO is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_SCH311X is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_GRGPIO is not set ++ ++# ++# I2C GPIO expanders: ++# ++# 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_ADP5588 is not set ++# CONFIG_GPIO_ADNP is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_GPIO_MC33880 is not set ++# CONFIG_GPIO_74X164 is not set ++ ++# ++# AC97 GPIO expanders: ++# ++ ++# ++# LPC GPIO expanders: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++ ++# ++# USB GPIO expanders: ++# ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++CONFIG_POWER_RESET_SYSCON=y ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_BCM590XX is not set ++# CONFIG_MFD_AXP20X 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_EGPIO 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X is not set ++# CONFIG_MFD_TPS65910 is not set ++# CONFIG_MFD_TPS65912 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=m ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=m ++CONFIG_VIDEO_V4L2=m ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=m ++CONFIG_VIDEOBUF2_MEMOPS=m ++CONFIG_VIDEOBUF2_VMALLOC=m ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++# CONFIG_MEDIA_USB_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# Audio decoders, processors and mixers ++# ++ ++# ++# RDS decoders ++# ++ ++# ++# Video decoders ++# ++ ++# ++# Video and audio decoders ++# ++ ++# ++# Video encoders ++# ++ ++# ++# Camera sensor devices ++# ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++ ++# ++# Audio/Video compression chips ++# ++ ++# ++# Miscellaneous helper chips ++# ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_HCD is not set ++# CONFIG_USB_FOTG210_HCD is not set ++# CONFIG_USB_MAX3421_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_SISUSBVGA 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_OTG_WAKELOCK is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_AUTO_SWITCH is not set ++# CONFIG_HIUSB_DEVICE3_0 is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_MASS_STORAGE=m ++CONFIG_USB_F_UAC1=m ++CONFIG_USB_F_UVC=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++CONFIG_USB_AUDIO=m ++CONFIG_GADGET_UAC1=y ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM is not set ++CONFIG_USB_G_WEBCAM_AUDIO=m ++# CONFIG_UWB is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# 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_HIMCIV200=y ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++# 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_VIC=y ++CONFIG_ARM_VIC_NR=2 ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# File systems ++# ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_LOGFS is not set ++CONFIG_CRAMFS=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++# CONFIG_DLM is not set ++ ++# ++# Kernel hacking ++# ++ ++# ++# printk and dmesg options ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_HASH=y ++CONFIG_CRYPTO_HASH2=y ++# CONFIG_CRYPTO_MANAGER is not set ++# CONFIG_CRYPTO_MANAGER2 is not set ++# CONFIG_CRYPTO_USER is not set ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# 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_SEQIV is not set ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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=y ++# CONFIG_CRYPTO_ZLIB is not set ++CONFIG_CRYPTO_LZO=y ++# 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_CRYPTO_DEV_HISILICON is not set ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=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_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3516ev100_full_defconfig b/arch/arm/configs/hi3516ev100_full_defconfig +new file mode 100644 +index 0000000..70f4635 +--- /dev/null ++++ b/arch/arm/configs/hi3516ev100_full_defconfig +@@ -0,0 +1,2529 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=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_GENERIC_BUG=y ++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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++CONFIG_NO_HZ=y ++# CONFIG_HIGH_RES_TIMERS is not set ++ ++# ++# CPU/Task time and stats accounting ++# ++CONFIG_VIRT_CPU_ACCOUNTING=y ++# CONFIG_TICK_CPU_ACCOUNTING is not set ++CONFIG_VIRT_CPU_ACCOUNTING_GEN=y ++# 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_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++# CONFIG_RCU_STALL_COMMON is not set ++CONFIG_CONTEXT_TRACKING=y ++# CONFIG_CONTEXT_TRACKING_FORCE is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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=y ++CONFIG_SLUB_DEBUG=y ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL is not set ++# CONFIG_UPROBES is not set ++# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set ++CONFIG_ARCH_USE_BUILTIN_BSWAP=y ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=y ++CONFIG_HAVE_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V4 is not set ++# CONFIG_ARCH_MULTI_V4T is not set ++CONFIG_ARCH_MULTI_V5=y ++CONFIG_ARCH_MULTI_V4_V5=y ++# CONFIG_ARCH_MULTI_V6 is not set ++# CONFIG_ARCH_MULTI_V7 is not set ++CONFIG_ARCH_MULTI_CPU_AUTO=y ++# CONFIG_ARCH_MVEBU is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++CONFIG_ARCH_HI3516CV300=y ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MXS is not set ++# CONFIG_ARCH_NOMADIK is not set ++# CONFIG_ARCH_NSPIRE is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_U300 is not set ++# CONFIG_ARCH_WM8505 is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_ARM926T=y ++CONFIG_CPU_32v5=y ++CONFIG_CPU_ABRT_EV5TJ=y ++CONFIG_CPU_PABRT_LEGACY=y ++CONFIG_CPU_CACHE_VIVT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++CONFIG_CPU_USE_DOMAINS=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_DCACHE_WRITETHROUGH is not set ++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set ++CONFIG_NEED_KUSER_HELPERS=y ++CONFIG_KUSER_HELPERS=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT=5 ++CONFIG_MULTI_IRQ_HANDLER=y ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_VMSPLIT_3G=y ++# 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++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_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=999999 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_NEED_PER_CPU_KM=y ++# CONFIG_CLEANCACHE is not set ++# CONFIG_FRONTSWAP is not set ++# CONFIG_CMA is not set ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# 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_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HISI_SNAPSHOT_BOOT=y ++# CONFIG_DEFAULT_MTD is not set ++CONFIG_DEFAULT_DDR=y ++CONFIG_SNAPSHOT_BUF_START=0x8a000000 ++CONFIG_SNAPSHOT_BUF_SIZE=0x4000000 ++CONFIG_HIBERNATION=y ++CONFIG_GZIP_COMPRESS=y ++CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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=m ++# 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_GENEVE 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=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE 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_SWAP is not set ++CONFIG_HIFMC=y ++CONFIG_HIFMC_SPI_NAND=y ++# CONFIG_HIFMC_NAND 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 is not set ++# 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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HIFMC100_NAND is not set ++CONFIG_HIFMC100_SPI_NAND=y ++CONFIG_SPI_NAND_MAX_CHIP_NUM=1 ++# CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE 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_SPI_NOR_USE_4K_SECTORS is not set ++CONFIG_SPI_HISI_SFC=y ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++CONFIG_ETHERNET=y ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC 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_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++CONFIG_HISI_FEMAC=y ++# CONFIG_HIETH_GMAC is not set ++# CONFIG_HIETH_SWITCH_FABRIC 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=y ++# CONFIG_ENC28J60 is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_ETHOC is not set ++# CONFIG_NET_VENDOR_QUALCOMM 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_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY 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_BCM_UNIMAC is not set ++CONFIG_MDIO_HISI_FEMAC=y ++# CONFIG_MDIO_HISI_GEMAC 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_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_ST_ASC is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_HW_RANDOM=y ++# CONFIG_HW_RANDOM_TIMERIOMEM is not set ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++# CONFIG_DCC_TTY 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=m ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set ++# CONFIG_I2C_MUX_GPIO is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PCA954x is not set ++# CONFIG_I2C_MUX_PINCTRL 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_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_GPIO is not set ++CONFIG_I2C_HIBVT=y ++# CONFIG_I2C_HISI_V110 is not set ++# CONFIG_I2C_NOMADIK 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_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_OC_TINY is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_DEVRES=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_GENERIC_PLATFORM is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_EM is not set ++# CONFIG_GPIO_ZEVIO is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_SCH311X is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_GRGPIO is not set ++ ++# ++# I2C GPIO expanders: ++# ++# 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_ADP5588 is not set ++# CONFIG_GPIO_ADNP is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_GPIO_MC33880 is not set ++# CONFIG_GPIO_74X164 is not set ++ ++# ++# AC97 GPIO expanders: ++# ++ ++# ++# LPC GPIO expanders: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++ ++# ++# USB GPIO expanders: ++# ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++CONFIG_POWER_RESET_SYSCON=y ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_BCM590XX is not set ++# CONFIG_MFD_AXP20X 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_EGPIO 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X is not set ++# CONFIG_MFD_TPS65910 is not set ++# CONFIG_MFD_TPS65912 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=m ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=m ++CONFIG_VIDEO_V4L2=m ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=m ++CONFIG_VIDEOBUF2_MEMOPS=m ++CONFIG_VIDEOBUF2_VMALLOC=m ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++# CONFIG_MEDIA_USB_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# Audio decoders, processors and mixers ++# ++ ++# ++# RDS decoders ++# ++ ++# ++# Video decoders ++# ++ ++# ++# Video and audio decoders ++# ++ ++# ++# Video encoders ++# ++ ++# ++# Camera sensor devices ++# ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++ ++# ++# Audio/Video compression chips ++# ++ ++# ++# Miscellaneous helper chips ++# ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_HCD is not set ++# CONFIG_USB_FOTG210_HCD is not set ++# CONFIG_USB_MAX3421_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_SISUSBVGA 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_OTG_WAKELOCK is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_AUTO_SWITCH is not set ++# CONFIG_HIUSB_DEVICE3_0 is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_MASS_STORAGE=m ++CONFIG_USB_F_UAC1=m ++CONFIG_USB_F_UVC=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++CONFIG_USB_AUDIO=m ++CONFIG_GADGET_UAC1=y ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM is not set ++CONFIG_USB_G_WEBCAM_AUDIO=m ++# CONFIG_UWB is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# 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_HIMCIV200=y ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++# 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_VIC=y ++CONFIG_ARM_VIC_NR=2 ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# File systems ++# ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_LOGFS is not set ++CONFIG_CRAMFS=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++# CONFIG_DLM is not set ++ ++# ++# Kernel hacking ++# ++ ++# ++# printk and dmesg options ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_HASH=y ++CONFIG_CRYPTO_HASH2=y ++# CONFIG_CRYPTO_MANAGER is not set ++# CONFIG_CRYPTO_MANAGER2 is not set ++# CONFIG_CRYPTO_USER is not set ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# 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_SEQIV is not set ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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=y ++# CONFIG_CRYPTO_ZLIB is not set ++CONFIG_CRYPTO_LZO=y ++# 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=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_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3516ev100_mini_defconfig b/arch/arm/configs/hi3516ev100_mini_defconfig +new file mode 100644 +index 0000000..116773a +--- /dev/null ++++ b/arch/arm/configs/hi3516ev100_mini_defconfig +@@ -0,0 +1,2188 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=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_GENERIC_BUG=y ++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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++CONFIG_NO_HZ=y ++# CONFIG_HIGH_RES_TIMERS is not set ++ ++# ++# CPU/Task time and stats accounting ++# ++CONFIG_VIRT_CPU_ACCOUNTING=y ++# CONFIG_TICK_CPU_ACCOUNTING is not set ++CONFIG_VIRT_CPU_ACCOUNTING_GEN=y ++# 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_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++# CONFIG_RCU_STALL_COMMON is not set ++CONFIG_CONTEXT_TRACKING=y ++# CONFIG_CONTEXT_TRACKING_FORCE is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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=y ++CONFIG_SLUB_DEBUG=y ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL is not set ++# CONFIG_UPROBES is not set ++# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set ++CONFIG_ARCH_USE_BUILTIN_BSWAP=y ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=y ++CONFIG_HAVE_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V4 is not set ++# CONFIG_ARCH_MULTI_V4T is not set ++CONFIG_ARCH_MULTI_V5=y ++CONFIG_ARCH_MULTI_V4_V5=y ++# CONFIG_ARCH_MULTI_V6 is not set ++# CONFIG_ARCH_MULTI_V7 is not set ++CONFIG_ARCH_MULTI_CPU_AUTO=y ++# CONFIG_ARCH_MVEBU is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++CONFIG_ARCH_HI3516CV300=y ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MXS is not set ++# CONFIG_ARCH_NOMADIK is not set ++# CONFIG_ARCH_NSPIRE is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_U300 is not set ++# CONFIG_ARCH_WM8505 is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_ARM926T=y ++CONFIG_CPU_32v5=y ++CONFIG_CPU_ABRT_EV5TJ=y ++CONFIG_CPU_PABRT_LEGACY=y ++CONFIG_CPU_CACHE_VIVT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++CONFIG_CPU_USE_DOMAINS=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++# CONFIG_ARM_THUMB is not set ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set ++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set ++CONFIG_NEED_KUSER_HELPERS=y ++CONFIG_KUSER_HELPERS=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT=5 ++CONFIG_MULTI_IRQ_HANDLER=y ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_VMSPLIT_3G=y ++# 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++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_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=999999 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_NEED_PER_CPU_KM=y ++# CONFIG_CLEANCACHE is not set ++# CONFIG_FRONTSWAP is not set ++# CONFIG_CMA is not set ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# 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_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HISI_SNAPSHOT_BOOT=y ++# CONFIG_DEFAULT_MTD is not set ++CONFIG_DEFAULT_DDR=y ++CONFIG_SNAPSHOT_BUF_START=0x8a000000 ++CONFIG_SNAPSHOT_BUF_SIZE=0x4000000 ++CONFIG_HIBERNATION=y ++CONFIG_GZIP_COMPRESS=y ++CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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=m ++# 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_GENEVE 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=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_WIRELESS is not set ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# 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_SWAP is not set ++CONFIG_HIFMC=y ++# CONFIG_HIFMC_SPI_NAND is not set ++# CONFIG_HIFMC_NAND 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 is not set ++# 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_IDS=y ++# 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_SPI_NOR_USE_4K_SECTORS is not set ++CONFIG_SPI_HISI_SFC=y ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++CONFIG_ETHERNET=y ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC 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_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++CONFIG_HISI_FEMAC=y ++# CONFIG_HIETH_GMAC is not set ++# CONFIG_HIETH_SWITCH_FABRIC 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=y ++# CONFIG_ENC28J60 is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_ETHOC is not set ++# CONFIG_NET_VENDOR_QUALCOMM 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_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY 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_BCM_UNIMAC is not set ++CONFIG_MDIO_HISI_FEMAC=y ++# CONFIG_MDIO_HISI_GEMAC is not set ++# CONFIG_MICREL_KS8995MA is not set ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++ ++# ++# Host-side USB support is needed for USB Network Adapter support ++# ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_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_ST_ASC is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_HW_RANDOM=y ++# CONFIG_HW_RANDOM_TIMERIOMEM is not set ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++# CONFIG_DCC_TTY 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_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_GPIO is not set ++CONFIG_I2C_HIBVT=y ++# CONFIG_I2C_HISI_V110 is not set ++# CONFIG_I2C_NOMADIK 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_PARPORT_LIGHT is not set ++# CONFIG_I2C_TAOS_EVM is not set ++ ++# ++# Other I2C/SMBus bus drivers ++# ++# CONFIG_I2C_STUB 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_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_OC_TINY is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_DEVRES=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_GENERIC_PLATFORM is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_EM is not set ++# CONFIG_GPIO_ZEVIO is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_SCH311X is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_GRGPIO is not set ++ ++# ++# I2C GPIO expanders: ++# ++# 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_ADP5588 is not set ++# CONFIG_GPIO_ADNP is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_GPIO_MC33880 is not set ++# CONFIG_GPIO_74X164 is not set ++ ++# ++# AC97 GPIO expanders: ++# ++ ++# ++# LPC GPIO expanders: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++ ++# ++# USB GPIO expanders: ++# ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++CONFIG_POWER_RESET_SYSCON=y ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_BCM590XX is not set ++# CONFIG_MFD_AXP20X 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_EGPIO 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_MENF21BMC is not set ++# CONFIG_EZX_PCAP is not set ++# CONFIG_MFD_RETU is not set ++# CONFIG_MFD_PCF50633 is not set ++# CONFIG_MFD_PM8921_CORE 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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X is not set ++# CONFIG_MFD_TPS65910 is not set ++# CONFIG_MFD_TPS65912 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 ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# I2C HID support ++# ++# CONFIG_I2C_HID is not set ++CONFIG_USB_OHCI_LITTLE_ENDIAN=y ++# CONFIG_USB_SUPPORT is not set ++# CONFIG_UWB is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# CONFIG_MMC_DW is not set ++# CONFIG_MMC_USDHI6ROL0 is not set ++CONFIG_HIMCIV200=y ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++# 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_VIC=y ++CONFIG_ARM_VIC_NR=2 ++# CONFIG_IPACK_BUS is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# File systems ++# ++# 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_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++# CONFIG_DLM is not set ++ ++# ++# Kernel hacking ++# ++ ++# ++# printk and dmesg options ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_HASH=y ++CONFIG_CRYPTO_HASH2=y ++# CONFIG_CRYPTO_MANAGER is not set ++# CONFIG_CRYPTO_MANAGER2 is not set ++# CONFIG_CRYPTO_USER is not set ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# 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_SEQIV is not set ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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=y ++# CONFIG_CRYPTO_ZLIB is not set ++CONFIG_CRYPTO_LZO=y ++# 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=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_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3519_big_little_defconfig b/arch/arm/configs/hi3519_big_little_defconfig +new file mode 100644 +index 0000000..f09a9bf +--- /dev/null ++++ b/arch/arm/configs/hi3519_big_little_defconfig +@@ -0,0 +1,2515 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_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_GENERIC_BUG=y ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++# CONFIG_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++# CONFIG_NO_HZ_FULL is not set ++CONFIG_NO_HZ=y ++# 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_TREE_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++# CONFIG_RCU_USER_QS is not set ++CONFIG_RCU_FANOUT=32 ++CONFIG_RCU_FANOUT_LEAF=16 ++# CONFIG_RCU_FANOUT_EXACT is not set ++# CONFIG_RCU_FAST_NO_HZ is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_RCU_NOCB_CPU is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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=y ++CONFIG_SLUB_DEBUG=y ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_STOP_MACHINE=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++CONFIG_ARCH_HI3519=y ++# CONFIG_ARCH_HI3519V101 is not set ++# CONFIG_ARCH_HI3516AV200 is not set ++# CONFIG_ARCH_HI3559 is not set ++# CONFIG_ARCH_HI3556 is not set ++CONFIG_PMC=y ++# CONFIG_ARCH_HI3536C is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_643719 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_754327 is not set ++# CONFIG_ARM_ERRATA_764369 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_798181 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++CONFIG_SMP=y ++CONFIG_SMP_ON_UP=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++CONFIG_SCHED_MC=y ++# CONFIG_SCHED_SMT is not set ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_SCHED_HMP=y ++# CONFIG_SCHED_HMP_PRIO_FILTER is not set ++CONFIG_HMP_FAST_CPU_MASK="" ++CONFIG_HMP_SLOW_CPU_MASK="" ++CONFIG_HMP_VARIABLE_SCALE=y ++# CONFIG_HMP_FREQUENCY_INVARIANT_SCALE is not set ++# CONFIG_SCHED_HMP_LITTLE_PACKING is not set ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++# CONFIG_MCPM is not set ++# CONFIG_BIG_LITTLE is not set ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++CONFIG_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_ARM_PSCI is not set ++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_THUMB2_KERNEL 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=y ++# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# CONFIG_CLEANCACHE is not set ++# CONFIG_FRONTSWAP is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++CONFIG_CMA_AREAS=7 ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++CONFIG_AUTO_ZRELADDR=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_INTERACTIVE=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPUFREQ_DT=y ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HISI_SNAPSHOT_BOOT=y ++# CONFIG_DEFAULT_MTD is not set ++CONFIG_DEFAULT_DDR=y ++CONFIG_SNAPSHOT_BUF_START=0x8a000000 ++CONFIG_SNAPSHOT_BUF_SIZE=0x4000000 ++CONFIG_HIBERNATION=y ++CONFIG_GZIP_COMPRESS=y ++CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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=m ++# 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_GENEVE 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=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# CONFIG_DMA_SHARED_BUFFER is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=16 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++CONFIG_ARM_CCI=y ++# 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_SWAP is not set ++CONFIG_HIFMC=y ++CONFIG_HIFMC_SPI_NAND=y ++# CONFIG_HIFMC_NAND 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 is not set ++# 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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_HIFMC100_NAND is not set ++CONFIG_HIFMC100_SPI_NAND=y ++CONFIG_SPI_NAND_MAX_CHIP_NUM=1 ++# CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE 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_SPI_NOR_USE_4K_SECTORS is not set ++CONFIG_SPI_HISI_SFC=y ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++# CONFIG_MTD_UBI is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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_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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++CONFIG_HISI_REG=y ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++CONFIG_ETHERNET=y ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC 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_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# CONFIG_HIETH_SWITCH_FABRIC 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_ETHOC is not set ++# CONFIG_NET_VENDOR_QUALCOMM 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_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_MMIOREG is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART 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_ST_ASC 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_DCC_TTY is not set ++# CONFIG_XILLYBUS is not set ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_COMPAT=y ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_MUX=y ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_MUX_PCA9541 is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_HIBVT is not set ++# CONFIG_I2C_HISI_V110 is not set ++# CONFIG_I2C_NOMADIK 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_HI_I2C=y ++CONFIG_HI_I2C0_IO_BASE=0x12110000 ++CONFIG_HI_I2C0_IO_SIZE=0x1000 ++CONFIG_HI_I2C1_IO_BASE=0x12111000 ++CONFIG_HI_I2C1_IO_SIZE=0x1000 ++CONFIG_HI_I2C2_IO_BASE=0x12112000 ++CONFIG_HI_I2C2_IO_SIZE=0x1000 ++CONFIG_HI_I2C3_IO_BASE=0x12113000 ++CONFIG_HI_I2C3_IO_SIZE=0x1000 ++CONFIG_HI_I2C_RETRIES=0x1 ++CONFIG_HI_I2C_TX_FIFO=0x8 ++CONFIG_HI_I2C_RX_FIFO=0x8 ++CONFIG_HI_I2C0_CLK_LIMIT=100000 ++CONFIG_HI_I2C1_CLK_LIMIT=100000 ++CONFIG_HI_I2C2_CLK_LIMIT=100000 ++CONFIG_HI_I2C3_CLK_LIMIT=100000 ++# CONFIG_I2C_STUB 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_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_ARCH_WANT_OPTIONAL_GPIOLIB=y ++# CONFIG_GPIOLIB is not set ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# CONFIG_MFD_AS3711 is not set ++# CONFIG_MFD_AS3722 is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_BCM590XX is not set ++# CONFIG_MFD_AXP20X is not set ++# CONFIG_MFD_CROS_EC 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS6507X is not set ++# CONFIG_MFD_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_XHCI_HISILICON=y ++CONFIG_USB_EHCI_HCD=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_HCD is not set ++# CONFIG_USB_FOTG210_HCD is not set ++# CONFIG_USB_MAX3421_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_SISUSBVGA 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_OTG_WAKELOCK is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB is not set ++# CONFIG_USB_ISP1301 is not set ++# CONFIG_USB_ULPI is not set ++CONFIG_USB_GADGET=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_AUTO_SWITCH is not set ++# CONFIG_HIUSB_DEVICE3_0 is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_ACM=m ++CONFIG_USB_U_SERIAL=m ++CONFIG_USB_U_ETHER=m ++CONFIG_USB_F_SERIAL=m ++CONFIG_USB_F_OBEX=m ++CONFIG_USB_F_ECM=m ++CONFIG_USB_F_SUBSET=m ++CONFIG_USB_F_RNDIS=m ++CONFIG_USB_F_MASS_STORAGE=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++CONFIG_USB_ETH=m ++CONFIG_USB_ETH_RNDIS=y ++# CONFIG_USB_ETH_EEM is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++CONFIG_USB_G_SERIAL=m ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_UWB is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# 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_HIMCIV200=y ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=y ++CONFIG_PHY_HISI_USB3=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++# CONFIG_HI_DMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE 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=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=21 ++# CONFIG_RCU_CPU_STALL_INFO is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++# CONFIG_STRICT_DEVMEM is not set ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_HASH=y ++CONFIG_CRYPTO_HASH2=y ++# CONFIG_CRYPTO_MANAGER is not set ++# CONFIG_CRYPTO_MANAGER2 is not set ++# CONFIG_CRYPTO_USER is not set ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_PCRYPT is not set ++# 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_SEQIV is not set ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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_ZLIB is not set ++# CONFIG_CRYPTO_LZO 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3519_big_little_nand_defconfig b/arch/arm/configs/hi3519_big_little_nand_defconfig +new file mode 100644 +index 0000000..9eed93e +--- /dev/null ++++ b/arch/arm/configs/hi3519_big_little_nand_defconfig +@@ -0,0 +1,2513 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_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_GENERIC_BUG=y ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++# CONFIG_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++# CONFIG_NO_HZ_FULL is not set ++CONFIG_NO_HZ=y ++# 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_TREE_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++# CONFIG_RCU_USER_QS is not set ++CONFIG_RCU_FANOUT=32 ++CONFIG_RCU_FANOUT_LEAF=16 ++# CONFIG_RCU_FANOUT_EXACT is not set ++# CONFIG_RCU_FAST_NO_HZ is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_RCU_NOCB_CPU is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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=y ++CONFIG_SLUB_DEBUG=y ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_STOP_MACHINE=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++CONFIG_ARCH_HI3519=y ++# CONFIG_ARCH_HI3519V101 is not set ++# CONFIG_ARCH_HI3516AV200 is not set ++# CONFIG_ARCH_HI3559 is not set ++# CONFIG_ARCH_HI3556 is not set ++CONFIG_PMC=y ++# CONFIG_ARCH_HI3536C is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_643719 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_754327 is not set ++# CONFIG_ARM_ERRATA_764369 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_798181 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++CONFIG_SMP=y ++CONFIG_SMP_ON_UP=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++CONFIG_SCHED_MC=y ++# CONFIG_SCHED_SMT is not set ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_SCHED_HMP=y ++# CONFIG_SCHED_HMP_PRIO_FILTER is not set ++CONFIG_HMP_FAST_CPU_MASK="" ++CONFIG_HMP_SLOW_CPU_MASK="" ++CONFIG_HMP_VARIABLE_SCALE=y ++# CONFIG_HMP_FREQUENCY_INVARIANT_SCALE is not set ++# CONFIG_SCHED_HMP_LITTLE_PACKING is not set ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++# CONFIG_MCPM is not set ++# CONFIG_BIG_LITTLE is not set ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++CONFIG_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_ARM_PSCI is not set ++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_THUMB2_KERNEL 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=y ++# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# CONFIG_CLEANCACHE is not set ++# CONFIG_FRONTSWAP is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++CONFIG_CMA_AREAS=7 ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++CONFIG_AUTO_ZRELADDR=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_INTERACTIVE=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPUFREQ_DT=y ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HISI_SNAPSHOT_BOOT=y ++# CONFIG_DEFAULT_MTD is not set ++CONFIG_DEFAULT_DDR=y ++CONFIG_SNAPSHOT_BUF_START=0x8a000000 ++CONFIG_SNAPSHOT_BUF_SIZE=0x4000000 ++CONFIG_HIBERNATION=y ++CONFIG_GZIP_COMPRESS=y ++CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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=m ++# 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_GENEVE 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=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# CONFIG_DMA_SHARED_BUFFER is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=16 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++CONFIG_ARM_CCI=y ++# 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_SWAP is not set ++CONFIG_HIFMC=y ++# CONFIG_HIFMC_SPI_NAND is not set ++CONFIG_HIFMC_NAND=y ++ ++# ++# 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_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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++CONFIG_HIFMC100_NAND=y ++CONFIG_HIFMC100_MAX_NAND_CHIP=1 ++# CONFIG_HIFMC100_NAND_EDO_MODE is not set ++CONFIG_RW_H_WIDTH=10 ++CONFIG_R_L_WIDTH=10 ++CONFIG_W_L_WIDTH=10 ++# CONFIG_HIFMC100_NAND_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_NAND_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_NAND_PAGESIZE_AUTO_ECC_NONE 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 is not set ++# CONFIG_MTD_UBI is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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_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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++CONFIG_HISI_REG=y ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++CONFIG_ETHERNET=y ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC 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_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# CONFIG_HIETH_SWITCH_FABRIC 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_ETHOC is not set ++# CONFIG_NET_VENDOR_QUALCOMM 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_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_MMIOREG is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART 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_ST_ASC 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_DCC_TTY is not set ++# CONFIG_XILLYBUS is not set ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_COMPAT=y ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_MUX=y ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_MUX_PCA9541 is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_HIBVT is not set ++# CONFIG_I2C_HISI_V110 is not set ++# CONFIG_I2C_NOMADIK 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_HI_I2C=y ++CONFIG_HI_I2C0_IO_BASE=0x12110000 ++CONFIG_HI_I2C0_IO_SIZE=0x1000 ++CONFIG_HI_I2C1_IO_BASE=0x12111000 ++CONFIG_HI_I2C1_IO_SIZE=0x1000 ++CONFIG_HI_I2C2_IO_BASE=0x12112000 ++CONFIG_HI_I2C2_IO_SIZE=0x1000 ++CONFIG_HI_I2C3_IO_BASE=0x12113000 ++CONFIG_HI_I2C3_IO_SIZE=0x1000 ++CONFIG_HI_I2C_RETRIES=0x1 ++CONFIG_HI_I2C_TX_FIFO=0x8 ++CONFIG_HI_I2C_RX_FIFO=0x8 ++CONFIG_HI_I2C0_CLK_LIMIT=100000 ++CONFIG_HI_I2C1_CLK_LIMIT=100000 ++CONFIG_HI_I2C2_CLK_LIMIT=100000 ++CONFIG_HI_I2C3_CLK_LIMIT=100000 ++# CONFIG_I2C_STUB 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_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_ARCH_WANT_OPTIONAL_GPIOLIB=y ++# CONFIG_GPIOLIB is not set ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# CONFIG_MFD_AS3711 is not set ++# CONFIG_MFD_AS3722 is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_BCM590XX is not set ++# CONFIG_MFD_AXP20X is not set ++# CONFIG_MFD_CROS_EC 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS6507X is not set ++# CONFIG_MFD_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_XHCI_HISILICON=y ++CONFIG_USB_EHCI_HCD=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_HCD is not set ++# CONFIG_USB_FOTG210_HCD is not set ++# CONFIG_USB_MAX3421_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_SISUSBVGA 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_OTG_WAKELOCK is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB is not set ++# CONFIG_USB_ISP1301 is not set ++# CONFIG_USB_ULPI is not set ++CONFIG_USB_GADGET=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_AUTO_SWITCH is not set ++# CONFIG_HIUSB_DEVICE3_0 is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_ACM=m ++CONFIG_USB_U_SERIAL=m ++CONFIG_USB_U_ETHER=m ++CONFIG_USB_F_SERIAL=m ++CONFIG_USB_F_OBEX=m ++CONFIG_USB_F_ECM=m ++CONFIG_USB_F_SUBSET=m ++CONFIG_USB_F_RNDIS=m ++CONFIG_USB_F_MASS_STORAGE=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++CONFIG_USB_ETH=m ++CONFIG_USB_ETH_RNDIS=y ++# CONFIG_USB_ETH_EEM is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++CONFIG_USB_G_SERIAL=m ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_UWB is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# 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_HIMCIV200=y ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=y ++CONFIG_PHY_HISI_USB3=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++# CONFIG_HI_DMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE 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=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=21 ++# CONFIG_RCU_CPU_STALL_INFO is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++# CONFIG_STRICT_DEVMEM is not set ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_HASH=y ++CONFIG_CRYPTO_HASH2=y ++# CONFIG_CRYPTO_MANAGER is not set ++# CONFIG_CRYPTO_MANAGER2 is not set ++# CONFIG_CRYPTO_USER is not set ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_PCRYPT is not set ++# 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_SEQIV is not set ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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_ZLIB is not set ++# CONFIG_CRYPTO_LZO 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3519v101_big_little_defconfig b/arch/arm/configs/hi3519v101_big_little_defconfig +new file mode 100644 +index 0000000..59fc573 +--- /dev/null ++++ b/arch/arm/configs/hi3519v101_big_little_defconfig +@@ -0,0 +1,2705 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_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_GENERIC_BUG=y ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++# CONFIG_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++# CONFIG_NO_HZ_FULL is not set ++CONFIG_NO_HZ=y ++# 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_TREE_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++# CONFIG_RCU_USER_QS is not set ++CONFIG_RCU_FANOUT=32 ++CONFIG_RCU_FANOUT_LEAF=16 ++# CONFIG_RCU_FANOUT_EXACT is not set ++# CONFIG_RCU_FAST_NO_HZ is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_RCU_NOCB_CPU is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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=y ++CONFIG_SLUB_DEBUG=y ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_STOP_MACHINE=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++CONFIG_ARCH_HI3519V101=y ++# CONFIG_ARCH_HI3516AV200 is not set ++# CONFIG_ARCH_HI3559 is not set ++# CONFIG_ARCH_HI3556 is not set ++CONFIG_PMC=y ++# CONFIG_ARCH_HI3536C is not set ++# CONFIG_ARCH_HI3531D is not set ++# CONFIG_ARCH_HI3521D is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_643719 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_754327 is not set ++# CONFIG_ARM_ERRATA_764369 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_798181 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++CONFIG_SMP=y ++CONFIG_SMP_ON_UP=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++CONFIG_SCHED_MC=y ++# CONFIG_SCHED_SMT is not set ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_SCHED_HMP=y ++# CONFIG_SCHED_HMP_PRIO_FILTER is not set ++CONFIG_HMP_FAST_CPU_MASK="" ++CONFIG_HMP_SLOW_CPU_MASK="" ++CONFIG_HMP_VARIABLE_SCALE=y ++# CONFIG_HMP_FREQUENCY_INVARIANT_SCALE is not set ++# CONFIG_SCHED_HMP_LITTLE_PACKING is not set ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++# CONFIG_MCPM is not set ++# CONFIG_BIG_LITTLE is not set ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++CONFIG_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_ARM_PSCI is not set ++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_THUMB2_KERNEL 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=y ++# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# CONFIG_CLEANCACHE is not set ++# CONFIG_FRONTSWAP is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++CONFIG_CMA_AREAS=7 ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++CONFIG_AUTO_ZRELADDR=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_INTERACTIVE=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPUFREQ_DT=y ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++ ++# ++# CPU Idle ++# ++CONFIG_CPU_IDLE=y ++CONFIG_CPU_IDLE_GOV_LADDER=y ++CONFIG_CPU_IDLE_GOV_MENU=y ++ ++# ++# ARM CPU Idle Drivers ++# ++CONFIG_ARM_HI3519V101_CPUIDLE=y ++# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++CONFIG_VFP=y ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HISI_SNAPSHOT_BOOT=y ++# CONFIG_DEFAULT_MTD is not set ++CONFIG_DEFAULT_DDR=y ++CONFIG_SNAPSHOT_BUF_START=0x8a000000 ++CONFIG_SNAPSHOT_BUF_SIZE=0x4000000 ++CONFIG_HIBERNATION=y ++CONFIG_GZIP_COMPRESS=y ++CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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=m ++# 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_GENEVE 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=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=16 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++CONFIG_ARM_CCI=y ++# 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_SWAP is not set ++CONFIG_HIFMC=y ++CONFIG_HIFMC_SPI_NAND=y ++# CONFIG_HIFMC_NAND 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 is not set ++# 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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_MTD_NAND_HINFC610 is not set ++# CONFIG_HIFMC100_NAND is not set ++CONFIG_HIFMC100_SPI_NAND=y ++CONFIG_SPI_NAND_MAX_CHIP_NUM=1 ++# CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE 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_SPI_NOR_USE_4K_SECTORS is not set ++CONFIG_SPI_HISI_SFC=y ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++# CONFIG_MTD_UBI is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++CONFIG_HISI_REG=y ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++CONFIG_ETHERNET=y ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC 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_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# CONFIG_HIETH_SWITCH_FABRIC 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_ETHOC is not set ++# CONFIG_NET_VENDOR_QUALCOMM 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_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY 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_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_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_ST_ASC 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_DCC_TTY 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=y ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set ++# CONFIG_I2C_MUX_GPIO is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PCA954x 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_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_HIBVT is not set ++CONFIG_I2C_HISI_V110=y ++# CONFIG_I2C_NOMADIK 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_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_OC_TINY is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_ARCH_WANT_OPTIONAL_GPIOLIB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_DEVRES=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_GENERIC_PLATFORM is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_EM is not set ++# CONFIG_GPIO_ZEVIO is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_SCH311X is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_GRGPIO is not set ++ ++# ++# I2C GPIO expanders: ++# ++# 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_ADP5588 is not set ++# CONFIG_GPIO_ADNP is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_GPIO_MC33880 is not set ++# CONFIG_GPIO_74X164 is not set ++ ++# ++# AC97 GPIO expanders: ++# ++ ++# ++# LPC GPIO expanders: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++ ++# ++# USB GPIO expanders: ++# ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_BCM590XX is not set ++# CONFIG_MFD_AXP20X 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_EGPIO 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X is not set ++# CONFIG_MFD_TPS65910 is not set ++# CONFIG_MFD_TPS65912 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=m ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=m ++CONFIG_VIDEO_V4L2=m ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=m ++CONFIG_VIDEOBUF2_MEMOPS=m ++CONFIG_VIDEOBUF2_VMALLOC=m ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++# CONFIG_MEDIA_USB_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# Audio decoders, processors and mixers ++# ++ ++# ++# RDS decoders ++# ++ ++# ++# Video decoders ++# ++ ++# ++# Video and audio decoders ++# ++ ++# ++# Video encoders ++# ++ ++# ++# Camera sensor devices ++# ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++ ++# ++# Audio/Video compression chips ++# ++ ++# ++# Miscellaneous helper chips ++# ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_XHCI_HISILICON=y ++CONFIG_USB_EHCI_HCD=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_HCD is not set ++# CONFIG_USB_FOTG210_HCD is not set ++# CONFIG_USB_MAX3421_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_SISUSBVGA 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_OTG_WAKELOCK is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_AUTO_SWITCH is not set ++# CONFIG_HIUSB_DEVICE3_0 is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_ACM=m ++CONFIG_USB_U_SERIAL=m ++CONFIG_USB_U_ETHER=m ++CONFIG_USB_F_SERIAL=m ++CONFIG_USB_F_OBEX=m ++CONFIG_USB_F_ECM=m ++CONFIG_USB_F_SUBSET=m ++CONFIG_USB_F_RNDIS=m ++CONFIG_USB_F_MASS_STORAGE=m ++CONFIG_USB_F_UAC1=m ++CONFIG_USB_F_UVC=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++CONFIG_USB_AUDIO=m ++CONFIG_GADGET_UAC1=y ++CONFIG_USB_ETH=m ++CONFIG_USB_ETH_RNDIS=y ++# CONFIG_USB_ETH_EEM is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++CONFIG_USB_G_SERIAL=m ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM is not set ++CONFIG_USB_G_WEBCAM_AUDIO=m ++# CONFIG_UWB is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# 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_HIMCIV200=y ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=y ++CONFIG_PHY_HISI_USB3=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_IO_BASE=0x10030000 ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE 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=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_RCU_CPU_STALL_INFO is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_HASH=y ++CONFIG_CRYPTO_HASH2=y ++# CONFIG_CRYPTO_MANAGER is not set ++# CONFIG_CRYPTO_MANAGER2 is not set ++# CONFIG_CRYPTO_USER is not set ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_PCRYPT is not set ++# 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_SEQIV is not set ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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_ZLIB is not set ++# CONFIG_CRYPTO_LZO 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_CRYPTO_DEV_HISILICON is not set ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3519v101_big_little_nand_defconfig b/arch/arm/configs/hi3519v101_big_little_nand_defconfig +new file mode 100644 +index 0000000..19a0e82 +--- /dev/null ++++ b/arch/arm/configs/hi3519v101_big_little_nand_defconfig +@@ -0,0 +1,2703 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_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_GENERIC_BUG=y ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++# CONFIG_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++# CONFIG_NO_HZ_FULL is not set ++CONFIG_NO_HZ=y ++# 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_TREE_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++# CONFIG_RCU_USER_QS is not set ++CONFIG_RCU_FANOUT=32 ++CONFIG_RCU_FANOUT_LEAF=16 ++# CONFIG_RCU_FANOUT_EXACT is not set ++# CONFIG_RCU_FAST_NO_HZ is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_RCU_NOCB_CPU is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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=y ++CONFIG_SLUB_DEBUG=y ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_STOP_MACHINE=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++CONFIG_ARCH_HI3519V101=y ++# CONFIG_ARCH_HI3516AV200 is not set ++# CONFIG_ARCH_HI3559 is not set ++# CONFIG_ARCH_HI3556 is not set ++CONFIG_PMC=y ++# CONFIG_ARCH_HI3536C is not set ++# CONFIG_ARCH_HI3531D is not set ++# CONFIG_ARCH_HI3521D is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_643719 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_754327 is not set ++# CONFIG_ARM_ERRATA_764369 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_798181 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++CONFIG_SMP=y ++CONFIG_SMP_ON_UP=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++CONFIG_SCHED_MC=y ++# CONFIG_SCHED_SMT is not set ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_SCHED_HMP=y ++# CONFIG_SCHED_HMP_PRIO_FILTER is not set ++CONFIG_HMP_FAST_CPU_MASK="" ++CONFIG_HMP_SLOW_CPU_MASK="" ++CONFIG_HMP_VARIABLE_SCALE=y ++# CONFIG_HMP_FREQUENCY_INVARIANT_SCALE is not set ++# CONFIG_SCHED_HMP_LITTLE_PACKING is not set ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++# CONFIG_MCPM is not set ++# CONFIG_BIG_LITTLE is not set ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++CONFIG_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_ARM_PSCI is not set ++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_THUMB2_KERNEL 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=y ++# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# CONFIG_CLEANCACHE is not set ++# CONFIG_FRONTSWAP is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++CONFIG_CMA_AREAS=7 ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++CONFIG_AUTO_ZRELADDR=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_INTERACTIVE=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPUFREQ_DT=y ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set ++ ++# ++# CPU Idle ++# ++CONFIG_CPU_IDLE=y ++CONFIG_CPU_IDLE_GOV_LADDER=y ++CONFIG_CPU_IDLE_GOV_MENU=y ++ ++# ++# ARM CPU Idle Drivers ++# ++CONFIG_ARM_HI3519V101_CPUIDLE=y ++# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++CONFIG_VFP=y ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HISI_SNAPSHOT_BOOT=y ++# CONFIG_DEFAULT_MTD is not set ++CONFIG_DEFAULT_DDR=y ++CONFIG_SNAPSHOT_BUF_START=0x8a000000 ++CONFIG_SNAPSHOT_BUF_SIZE=0x4000000 ++CONFIG_HIBERNATION=y ++CONFIG_GZIP_COMPRESS=y ++CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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=m ++# 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_GENEVE 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=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=16 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++CONFIG_ARM_CCI=y ++# 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_SWAP is not set ++CONFIG_HIFMC=y ++# CONFIG_HIFMC_SPI_NAND is not set ++CONFIG_HIFMC_NAND=y ++ ++# ++# 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_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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_MTD_NAND_HINFC610 is not set ++CONFIG_HIFMC100_NAND=y ++CONFIG_HIFMC100_MAX_NAND_CHIP=1 ++# CONFIG_HIFMC100_NAND_EDO_MODE is not set ++CONFIG_RW_H_WIDTH=10 ++CONFIG_R_L_WIDTH=10 ++CONFIG_W_L_WIDTH=10 ++# CONFIG_HIFMC100_NAND_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_NAND_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_NAND_PAGESIZE_AUTO_ECC_NONE 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 is not set ++# CONFIG_MTD_UBI is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++CONFIG_HISI_REG=y ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++CONFIG_ETHERNET=y ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC 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_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# CONFIG_HIETH_SWITCH_FABRIC 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_ETHOC is not set ++# CONFIG_NET_VENDOR_QUALCOMM 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_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY 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_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_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_ST_ASC 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_DCC_TTY 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=y ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set ++# CONFIG_I2C_MUX_GPIO is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PCA954x 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_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_HIBVT is not set ++CONFIG_I2C_HISI_V110=y ++# CONFIG_I2C_NOMADIK 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_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_OC_TINY is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_ARCH_WANT_OPTIONAL_GPIOLIB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_DEVRES=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_GENERIC_PLATFORM is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_EM is not set ++# CONFIG_GPIO_ZEVIO is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_SCH311X is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_GRGPIO is not set ++ ++# ++# I2C GPIO expanders: ++# ++# 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_ADP5588 is not set ++# CONFIG_GPIO_ADNP is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_GPIO_MC33880 is not set ++# CONFIG_GPIO_74X164 is not set ++ ++# ++# AC97 GPIO expanders: ++# ++ ++# ++# LPC GPIO expanders: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++ ++# ++# USB GPIO expanders: ++# ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_BCM590XX is not set ++# CONFIG_MFD_AXP20X 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_EGPIO 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X is not set ++# CONFIG_MFD_TPS65910 is not set ++# CONFIG_MFD_TPS65912 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=m ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=m ++CONFIG_VIDEO_V4L2=m ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=m ++CONFIG_VIDEOBUF2_MEMOPS=m ++CONFIG_VIDEOBUF2_VMALLOC=m ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++# CONFIG_MEDIA_USB_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# Audio decoders, processors and mixers ++# ++ ++# ++# RDS decoders ++# ++ ++# ++# Video decoders ++# ++ ++# ++# Video and audio decoders ++# ++ ++# ++# Video encoders ++# ++ ++# ++# Camera sensor devices ++# ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++ ++# ++# Audio/Video compression chips ++# ++ ++# ++# Miscellaneous helper chips ++# ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_XHCI_HISILICON=y ++CONFIG_USB_EHCI_HCD=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_HCD is not set ++# CONFIG_USB_FOTG210_HCD is not set ++# CONFIG_USB_MAX3421_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_SISUSBVGA 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_OTG_WAKELOCK is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_AUTO_SWITCH is not set ++# CONFIG_HIUSB_DEVICE3_0 is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_ACM=m ++CONFIG_USB_U_SERIAL=m ++CONFIG_USB_U_ETHER=m ++CONFIG_USB_F_SERIAL=m ++CONFIG_USB_F_OBEX=m ++CONFIG_USB_F_ECM=m ++CONFIG_USB_F_SUBSET=m ++CONFIG_USB_F_RNDIS=m ++CONFIG_USB_F_MASS_STORAGE=m ++CONFIG_USB_F_UAC1=m ++CONFIG_USB_F_UVC=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++CONFIG_USB_AUDIO=m ++CONFIG_GADGET_UAC1=y ++CONFIG_USB_ETH=m ++CONFIG_USB_ETH_RNDIS=y ++# CONFIG_USB_ETH_EEM is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++CONFIG_USB_G_SERIAL=m ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++# CONFIG_USB_G_MULTI is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM is not set ++CONFIG_USB_G_WEBCAM_AUDIO=m ++# CONFIG_UWB is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# 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_HIMCIV200=y ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=y ++CONFIG_PHY_HISI_USB3=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_IO_BASE=0x10030000 ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE 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=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_RCU_CPU_STALL_INFO is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_HASH=y ++CONFIG_CRYPTO_HASH2=y ++# CONFIG_CRYPTO_MANAGER is not set ++# CONFIG_CRYPTO_MANAGER2 is not set ++# CONFIG_CRYPTO_USER is not set ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_PCRYPT is not set ++# 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_SEQIV is not set ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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_ZLIB is not set ++# CONFIG_CRYPTO_LZO 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_CRYPTO_DEV_HISILICON is not set ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3521d_full_defconfig b/arch/arm/configs/hi3521d_full_defconfig +new file mode 100644 +index 0000000..0798397 +--- /dev/null ++++ b/arch/arm/configs/hi3521d_full_defconfig +@@ -0,0 +1,2433 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_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_GENERIC_BUG=y ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++# CONFIG_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++# CONFIG_FHANDLE is not set ++CONFIG_USELIB=y ++# CONFIG_AUDIT is not set ++ ++# ++# IRQ subsystem ++# ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_GENERIC_IRQ_SHOW=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_HZ_PERIODIC=y ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NO_HZ_FULL 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_TREE_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++# CONFIG_RCU_USER_QS is not set ++CONFIG_RCU_FANOUT=32 ++CONFIG_RCU_FANOUT_LEAF=16 ++# CONFIG_RCU_FANOUT_EXACT is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_RCU_NOCB_CPU is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_STOP_MACHINE=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++# CONFIG_ARCH_HI3519V101 is not set ++# CONFIG_ARCH_HI3516AV200 is not set ++# CONFIG_ARCH_HI3559 is not set ++# CONFIG_ARCH_HI3556 is not set ++# CONFIG_ARCH_HI3536C is not set ++# CONFIG_ARCH_HI3531D is not set ++CONFIG_ARCH_HI3521D=y ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_643719 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_754327 is not set ++# CONFIG_ARM_ERRATA_764369 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_798181 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++CONFIG_SMP=y ++CONFIG_SMP_ON_UP=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++# CONFIG_SCHED_MC is not set ++# CONFIG_SCHED_SMT is not set ++# CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE is not set ++CONFIG_HAVE_ARM_SCU=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++# CONFIG_MCPM is not set ++# CONFIG_BIG_LITTLE is not set ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++CONFIG_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_ARM_PSCI is not set ++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_THUMB2_KERNEL is not set ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_HAVE_ARCH_PFN_VALID=y ++CONFIG_HIGHMEM=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++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_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# 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_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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++CONFIG_AUTO_ZRELADDR=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_GOV_INTERACTIVE is not set ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++CONFIG_CPUFREQ_DT=y ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ 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_FPE_NWFPE is not set ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_VFP=y ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++# CONFIG_HISI_SNAPSHOT_BOOT is not set ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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=m ++# CONFIG_IP_MROUTE is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_NET_UDP_TUNNEL is not set ++# CONFIG_NET_FOU is not set ++# CONFIG_GENEVE 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=m ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_WIRELESS is not set ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# CONFIG_DMA_SHARED_BUFFER is not set ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++# CONFIG_ARM_CCI 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_HIFMC=y ++CONFIG_HIFMC_SPI_NAND=y ++# CONFIG_HIFMC_NAND 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 is not set ++# 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=y ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOCG3 is not set ++CONFIG_MTD_NAND_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_MTD_NAND_HINFC610 is not set ++# CONFIG_HIFMC100_NAND is not set ++CONFIG_HIFMC100_SPI_NAND=y ++CONFIG_SPI_NAND_MAX_CHIP_NUM=1 ++# CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE 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_SPI_NOR_USE_4K_SECTORS is not set ++CONFIG_SPI_HISI_SFC=y ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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_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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++CONFIG_BLK_DEV_SR=y ++# CONFIG_BLK_DEV_SR_VENDOR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HI_SATA=y ++CONFIG_HI_SATA_IOBASE=0x11010000 ++CONFIG_HI_SATA_FBS=1 ++CONFIG_HI_SATA_NCQ=1 ++CONFIG_ATA=y ++# CONFIG_ATA_NONSTANDARD is not set ++CONFIG_ATA_VERBOSE_ERROR=y ++CONFIG_SATA_PMP=y ++ ++# ++# Controllers with non-SFF native interface ++# ++CONFIG_SATA_AHCI_PLATFORM=y ++# CONFIG_ATA_SFF is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++CONFIG_ETHERNET=y ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC 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_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# CONFIG_HIETH_SWITCH_FABRIC 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_ETHOC is not set ++# CONFIG_NET_VENDOR_QUALCOMM 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_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_MMIOREG is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART 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_ST_ASC 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_DCC_TTY is not set ++# CONFIG_XILLYBUS is not set ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_COMPAT=y ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_MUX=y ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PINCTRL is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_HIBVT is not set ++# CONFIG_I2C_HISI_V110 is not set ++# CONFIG_I2C_NOMADIK 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_HI_I2C=y ++CONFIG_HI_I2C0_IO_BASE=0x120c0000 ++CONFIG_HI_I2C0_IO_SIZE=0x1000 ++CONFIG_HI_I2C_RETRIES=0x1 ++CONFIG_HI_I2C_TX_FIFO=0x8 ++CONFIG_HI_I2C_RX_FIFO=0x8 ++CONFIG_HI_I2C0_CLK_LIMIT=100000 ++# CONFIG_I2C_STUB 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_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y ++# CONFIG_GPIOLIB is not set ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# CONFIG_MFD_AS3711 is not set ++# CONFIG_MFD_AS3722 is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_BCM590XX is not set ++# CONFIG_MFD_AXP20X is not set ++# CONFIG_MFD_CROS_EC 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS6507X is not set ++# CONFIG_MFD_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_HCD is not set ++# CONFIG_USB_FOTG210_HCD is not set ++# CONFIG_USB_MAX3421_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_SISUSBVGA 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_OTG_WAKELOCK is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB is not set ++# CONFIG_USB_ISP1301 is not set ++# CONFIG_USB_ULPI is not set ++# CONFIG_USB_GADGET is not set ++# CONFIG_UWB is not set ++# CONFIG_MMC is not set ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++# CONFIG_PHY_HISI_INNO_USB2 is not set ++CONFIG_PHY_HI35x1D_INNO_USB2=y ++CONFIG_HI_NANO_PHY_SATA=y ++CONFIG_HI_SATA_PORTS=2 ++CONFIG_HI_SATA_MODE=1 ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++# CONFIG_JOLIET is not set ++# CONFIG_ZISOFS is not set ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_LOGFS is not set ++CONFIG_CRAMFS=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_RCU_CPU_STALL_INFO is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_HASH=y ++CONFIG_CRYPTO_HASH2=y ++# CONFIG_CRYPTO_MANAGER is not set ++# CONFIG_CRYPTO_MANAGER2 is not set ++# CONFIG_CRYPTO_USER is not set ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_PCRYPT is not set ++# 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_SEQIV is not set ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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=y ++# CONFIG_CRYPTO_ZLIB is not set ++CONFIG_CRYPTO_LZO=y ++# 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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=y ++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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_GLOB=y ++# CONFIG_GLOB_SELFTEST is not set ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3531d_full_defconfig b/arch/arm/configs/hi3531d_full_defconfig +new file mode 100644 +index 0000000..309c44f +--- /dev/null ++++ b/arch/arm/configs/hi3531d_full_defconfig +@@ -0,0 +1,2611 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_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_NEED_MACH_IO_H=y ++CONFIG_GENERIC_BUG=y ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++# CONFIG_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++# CONFIG_FHANDLE is not set ++CONFIG_USELIB=y ++# CONFIG_AUDIT is not set ++ ++# ++# IRQ subsystem ++# ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_GENERIC_IRQ_SHOW=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_HZ_PERIODIC=y ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NO_HZ_FULL 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_TREE_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++# CONFIG_RCU_USER_QS is not set ++CONFIG_RCU_FANOUT=32 ++CONFIG_RCU_FANOUT_LEAF=16 ++# CONFIG_RCU_FANOUT_EXACT is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_RCU_NOCB_CPU is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_PCI_QUIRKS=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=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_STOP_MACHINE=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++# CONFIG_ARCH_HI3519V101 is not set ++# CONFIG_ARCH_HI3516AV200 is not set ++# CONFIG_ARCH_HI3559 is not set ++# CONFIG_ARCH_HI3556 is not set ++# CONFIG_ARCH_HI3536C is not set ++CONFIG_ARCH_HI3531D=y ++# CONFIG_ARCH_HI3521D is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_OUTER_CACHE=y ++CONFIG_OUTER_CACHE_SYNC=y ++CONFIG_MIGHT_HAVE_CACHE_L2X0=y ++CONFIG_CACHE_L2X0=y ++CONFIG_CACHE_PL310=y ++# CONFIG_PL310_ERRATA_588369 is not set ++# CONFIG_PL310_ERRATA_727915 is not set ++# CONFIG_PL310_ERRATA_753970 is not set ++# CONFIG_PL310_ERRATA_769419 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_643719 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_754327 is not set ++# CONFIG_ARM_ERRATA_764369 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_798181 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++CONFIG_PCI=y ++CONFIG_PCI_SYSCALL=y ++# CONFIG_PCI_MSI is not set ++# CONFIG_PCI_DEBUG is not set ++# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set ++# CONFIG_PCI_STUB is not set ++# CONFIG_PCI_IOV is not set ++# CONFIG_PCI_PRI is not set ++# CONFIG_PCI_PASID is not set ++ ++# ++# PCI host controller drivers ++# ++# CONFIG_PCI_HOST_GENERIC is not set ++CONFIG_PCIEPORTBUS=y ++CONFIG_PCIEAER=y ++# CONFIG_PCIE_ECRC is not set ++# CONFIG_PCIEAER_INJECT is not set ++CONFIG_PCIEASPM=y ++# CONFIG_PCIEASPM_DEBUG is not set ++CONFIG_PCIEASPM_DEFAULT=y ++# CONFIG_PCIEASPM_POWERSAVE is not set ++# CONFIG_PCIEASPM_PERFORMANCE is not set ++# CONFIG_PCCARD is not set ++CONFIG_HIPCIE=y ++ ++# ++# PCI Express configs ++# ++CONFIG_PCIE0_SEL=1 ++CONFIG_PCIE0_DEVICES_MEM_SIZE=0x8000000 ++CONFIG_PCIE0_DEVICES_CONFIG_SIZE=0x8000000 ++CONFIG_LIMIT_MAX_RD_REQ_SIZE=y ++CONFIG_PCIE1_SEL=1 ++CONFIG_PCIE1_DEVICES_MEM_SIZE=0x7800000 ++CONFIG_PCIE1_DEVICES_CONFIG_SIZE=0x800000 ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++CONFIG_SMP=y ++CONFIG_SMP_ON_UP=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++# CONFIG_SCHED_MC is not set ++# CONFIG_SCHED_SMT is not set ++# CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE is not set ++CONFIG_HAVE_ARM_SCU=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++# CONFIG_MCPM is not set ++# CONFIG_BIG_LITTLE is not set ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++CONFIG_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_ARM_PSCI is not set ++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_THUMB2_KERNEL is not set ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_HAVE_ARCH_PFN_VALID=y ++CONFIG_HIGHMEM=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++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_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# 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_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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++CONFIG_AUTO_ZRELADDR=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_GOV_INTERACTIVE is not set ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++CONFIG_CPUFREQ_DT=y ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ 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_FPE_NWFPE is not set ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_VFP=y ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++# CONFIG_HISI_SNAPSHOT_BOOT is not set ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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=m ++# CONFIG_IP_MROUTE is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_NET_UDP_TUNNEL is not set ++# CONFIG_NET_FOU is not set ++# CONFIG_GENEVE 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=m ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_WIRELESS is not set ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# CONFIG_DMA_SHARED_BUFFER is not set ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++# CONFIG_ARM_CCI 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_HIFMC=y ++CONFIG_HIFMC_SPI_NAND=y ++# CONFIG_HIFMC_NAND 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_INTEL_VR_NOR is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_DATAFLASH is not set ++# CONFIG_MTD_M25P80 is not set ++# 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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_RICOH is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_MTD_NAND_HINFC610 is not set ++# CONFIG_HIFMC100_NAND is not set ++CONFIG_HIFMC100_SPI_NAND=y ++CONFIG_SPI_NAND_MAX_CHIP_NUM=1 ++# CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE 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_SPI_NOR_USE_4K_SECTORS is not set ++CONFIG_SPI_HISI_SFC=y ++# CONFIG_CLOSE_SPI_8PIN_4IO is not set ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++# CONFIG_MTD_UBI is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST is not set ++CONFIG_OF_FLATTREE=y ++CONFIG_OF_EARLY_FLATTREE=y ++CONFIG_OF_ADDRESS=y ++CONFIG_OF_ADDRESS_PCI=y ++CONFIG_OF_IRQ=y ++CONFIG_OF_NET=y ++CONFIG_OF_MDIO=y ++CONFIG_OF_PCI=y ++CONFIG_OF_PCI_IRQ=y ++CONFIG_OF_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set ++# CONFIG_BLK_CPQ_CISS_DA is not set ++# CONFIG_BLK_DEV_DAC960 is not set ++# CONFIG_BLK_DEV_UMEM is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_NVME is not set ++# CONFIG_BLK_DEV_SX8 is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_BLK_DEV_RSXX is not set ++ ++# ++# Misc devices ++# ++# CONFIG_SENSORS_LIS3LV02D is not set ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_DUMMY_IRQ is not set ++# CONFIG_PHANTOM is not set ++# CONFIG_SGI_IOC4 is not set ++# CONFIG_TIFM_CORE is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_HP_ILO 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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 ++# CONFIG_CB710_CORE is not set ++ ++# ++# Texas Instruments shared transport line discipline ++# ++# 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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++CONFIG_HAVE_IDE=y ++# CONFIG_IDE is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++CONFIG_BLK_DEV_SR=y ++# CONFIG_BLK_DEV_SR_VENDOR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HI_SATA=y ++CONFIG_HI_SATA_IOBASE=0x11010000 ++CONFIG_HI_SATA_FBS=1 ++CONFIG_HI_SATA_NCQ=1 ++CONFIG_ATA=y ++# CONFIG_ATA_NONSTANDARD is not set ++CONFIG_ATA_VERBOSE_ERROR=y ++CONFIG_SATA_PMP=y ++ ++# ++# Controllers with non-SFF native interface ++# ++# CONFIG_SATA_AHCI is not set ++CONFIG_SATA_AHCI_PLATFORM=y ++# CONFIG_SATA_INIC162X is not set ++# CONFIG_SATA_ACARD_AHCI is not set ++# CONFIG_SATA_SIL24 is not set ++# CONFIG_ATA_SFF is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++# CONFIG_FUSION is not set ++ ++# ++# IEEE 1394 (FireWire) support ++# ++# CONFIG_FIREWIRE is not set ++# CONFIG_FIREWIRE_NOSY is not set ++# CONFIG_I2O is not set ++CONFIG_NETDEVICES=y ++CONFIG_NET_CORE=y ++# CONFIG_BONDING is not set ++# CONFIG_DUMMY is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC is not set ++# CONFIG_NET_TEAM is not set ++# CONFIG_MACVLAN is not set ++# CONFIG_VXLAN 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_VETH is not set ++# CONFIG_NLMON is not set ++# CONFIG_ARCNET is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++CONFIG_ETHERNET=y ++# CONFIG_NET_VENDOR_3COM is not set ++# CONFIG_NET_VENDOR_ADAPTEC is not set ++# CONFIG_NET_VENDOR_AGERE is not set ++# CONFIG_NET_VENDOR_ALTEON is not set ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC is not set ++# CONFIG_NET_VENDOR_ATHEROS is not set ++# CONFIG_NET_CADENCE is not set ++# CONFIG_NET_VENDOR_BROADCOM is not set ++# CONFIG_NET_VENDOR_BROCADE is not set ++# CONFIG_NET_VENDOR_CHELSIO is not set ++# CONFIG_NET_VENDOR_CIRRUS is not set ++# CONFIG_NET_VENDOR_CISCO is not set ++# CONFIG_DM9000 is not set ++# CONFIG_DNET is not set ++# CONFIG_NET_VENDOR_DEC is not set ++# CONFIG_NET_VENDOR_DLINK is not set ++# CONFIG_NET_VENDOR_EMULEX is not set ++# CONFIG_NET_VENDOR_EXAR is not set ++# CONFIG_NET_VENDOR_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# CONFIG_HIETH_SWITCH_FABRIC is not set ++# CONFIG_NET_VENDOR_HP is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_IP1000 is not set ++# CONFIG_JME is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++# CONFIG_NET_VENDOR_MELLANOX is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_MICROCHIP is not set ++# CONFIG_NET_VENDOR_MYRI is not set ++# CONFIG_FEALNX is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NVIDIA is not set ++# CONFIG_NET_VENDOR_OKI is not set ++# CONFIG_ETHOC is not set ++# CONFIG_NET_PACKET_ENGINE is not set ++# CONFIG_NET_VENDOR_QLOGIC is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++# CONFIG_NET_VENDOR_REALTEK is not set ++# CONFIG_NET_VENDOR_RDC is not set ++# CONFIG_NET_VENDOR_SAMSUNG is not set ++# CONFIG_NET_VENDOR_SEEQ is not set ++# CONFIG_NET_VENDOR_SILAN is not set ++# CONFIG_NET_VENDOR_SIS is not set ++# CONFIG_SFC is not set ++# CONFIG_NET_VENDOR_SMSC is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++# CONFIG_NET_VENDOR_SUN is not set ++# CONFIG_NET_VENDOR_TEHUTI is not set ++# CONFIG_NET_VENDOR_TI is not set ++# CONFIG_NET_VENDOR_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_FDDI is not set ++# CONFIG_HIPPI is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_MMIOREG is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_VMXNET3 is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_SERIAL_NONSTANDARD is not set ++# CONFIG_NOZOMI is not set ++# CONFIG_N_GSM is not set ++# CONFIG_TRACE_SINK is not set ++CONFIG_DEVMEM=y ++CONFIG_DEVKMEM=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X is not set ++# CONFIG_SERIAL_MFD_HSU is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_JSM is not set ++# CONFIG_SERIAL_SCCNXP is not set ++# CONFIG_SERIAL_SC16IS7XX is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++# CONFIG_SERIAL_ARC is not set ++# CONFIG_SERIAL_RP2 is not set ++# CONFIG_SERIAL_FSL_LPUART is not set ++# CONFIG_SERIAL_ST_ASC 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_APPLICOM is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_DEVPORT=y ++# CONFIG_DCC_TTY is not set ++# CONFIG_XILLYBUS is not set ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_COMPAT=y ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_MUX=y ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PINCTRL is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# PC SMBus host controller drivers ++# ++# CONFIG_I2C_ALI1535 is not set ++# CONFIG_I2C_ALI1563 is not set ++# CONFIG_I2C_ALI15X3 is not set ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++# CONFIG_I2C_I801 is not set ++# CONFIG_I2C_ISCH is not set ++# CONFIG_I2C_PIIX4 is not set ++# CONFIG_I2C_NFORCE2 is not set ++# CONFIG_I2C_SIS5595 is not set ++# CONFIG_I2C_SIS630 is not set ++# CONFIG_I2C_SIS96X is not set ++# CONFIG_I2C_VIA is not set ++# CONFIG_I2C_VIAPRO is not set ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_DESIGNWARE_PCI is not set ++# CONFIG_I2C_HIBVT is not set ++# CONFIG_I2C_HISI_V110 is not set ++# CONFIG_I2C_NOMADIK 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_HI_I2C=y ++CONFIG_HI_I2C0_IO_BASE=0x120c0000 ++CONFIG_HI_I2C0_IO_SIZE=0x1000 ++CONFIG_HI_I2C1_IO_BASE=0x122e0000 ++CONFIG_HI_I2C1_IO_SIZE=0x1000 ++CONFIG_HI_I2C_RETRIES=0x1 ++CONFIG_HI_I2C_TX_FIFO=0x8 ++CONFIG_HI_I2C_RX_FIFO=0x8 ++CONFIG_HI_I2C0_CLK_LIMIT=100000 ++CONFIG_HI_I2C1_CLK_LIMIT=100000 ++# CONFIG_I2C_STUB 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_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# CONFIG_SPI_PXA2XX 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y ++# CONFIG_GPIOLIB is not set ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# CONFIG_MFD_AS3711 is not set ++# CONFIG_MFD_AS3722 is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_BCM590XX is not set ++# CONFIG_MFD_AXP20X is not set ++# CONFIG_MFD_CROS_EC 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_LPC_ICH is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_INTEL_SOC_PMIC is not set ++# CONFIG_MFD_JANZ_CMODIO 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_RDC321X is not set ++# CONFIG_MFD_RTSX_PCI 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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS6507X is not set ++# CONFIG_MFD_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X 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_VX855 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++CONFIG_VGA_ARB=y ++CONFIG_VGA_ARB_MAX_GPUS=16 ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_CIRRUS is not set ++# CONFIG_FB_PM2 is not set ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_NVIDIA is not set ++# CONFIG_FB_RIVA is not set ++# CONFIG_FB_I740 is not set ++# CONFIG_FB_MATROX is not set ++# CONFIG_FB_RADEON is not set ++# CONFIG_FB_ATY128 is not set ++# CONFIG_FB_ATY is not set ++# CONFIG_FB_S3 is not set ++# CONFIG_FB_SAVAGE is not set ++# CONFIG_FB_SIS is not set ++# CONFIG_FB_NEOMAGIC is not set ++# CONFIG_FB_KYRO is not set ++# CONFIG_FB_3DFX is not set ++# CONFIG_FB_VOODOO1 is not set ++# CONFIG_FB_VT8623 is not set ++# CONFIG_FB_TRIDENT is not set ++# CONFIG_FB_ARK is not set ++# CONFIG_FB_PM3 is not set ++# CONFIG_FB_CARMINE is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_MB862XX is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PCI=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_XHCI_HISILICON=y ++CONFIG_USB_EHCI_HCD=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_PCI=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_HCD is not set ++# CONFIG_USB_FOTG210_HCD is not set ++# CONFIG_USB_MAX3421_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PCI=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# CONFIG_USB_UHCI_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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_SISUSBVGA 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_OTG_WAKELOCK is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB is not set ++# CONFIG_USB_ISP1301 is not set ++# CONFIG_USB_ULPI is not set ++# CONFIG_USB_GADGET is not set ++# CONFIG_UWB is not set ++# CONFIG_MMC is not set ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_INFINIBAND is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES is not set ++# CONFIG_AUXDISPLAY is not set ++# CONFIG_UIO is not set ++# CONFIG_VIRT_DRIVERS is not set ++ ++# ++# Virtio drivers ++# ++# CONFIG_VIRTIO_PCI is not set ++# CONFIG_VIRTIO_MMIO is not set ++ ++# ++# Microsoft Hyper-V guest support ++# ++# CONFIG_STAGING is not set ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_VME_BUS is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++# CONFIG_PHY_HISI_INNO_USB2 is not set ++CONFIG_PHY_HI35x1D_INNO_USB2=y ++CONFIG_PHY_HI3531D_USB3=y ++CONFIG_HI_NANO_PHY_SATA=y ++CONFIG_HI_SATA_PORTS=4 ++CONFIG_HI_SATA_MODE=1 ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++CONFIG_RAS=y ++# CONFIG_THUNDERBOLT is not set ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++# CONFIG_JOLIET is not set ++# CONFIG_ZISOFS is not set ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_RCU_CPU_STALL_INFO is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_HASH=y ++CONFIG_CRYPTO_HASH2=y ++# CONFIG_CRYPTO_MANAGER is not set ++# CONFIG_CRYPTO_MANAGER2 is not set ++# CONFIG_CRYPTO_USER is not set ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_PCRYPT is not set ++# 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_SEQIV is not set ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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_ZLIB is not set ++# CONFIG_CRYPTO_LZO 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_CRYPTO_DEV_HIFN_795X is not set ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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=y ++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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_GLOB=y ++# CONFIG_GLOB_SELFTEST is not set ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3531d_full_slave_defconfig b/arch/arm/configs/hi3531d_full_slave_defconfig +new file mode 100644 +index 0000000..30e6c6f +--- /dev/null ++++ b/arch/arm/configs/hi3531d_full_slave_defconfig +@@ -0,0 +1,2437 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_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_GENERIC_BUG=y ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++# CONFIG_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++# CONFIG_FHANDLE is not set ++CONFIG_USELIB=y ++# CONFIG_AUDIT is not set ++ ++# ++# IRQ subsystem ++# ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_GENERIC_IRQ_SHOW=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_HZ_PERIODIC=y ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NO_HZ_FULL 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_TREE_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++# CONFIG_RCU_USER_QS is not set ++CONFIG_RCU_FANOUT=32 ++CONFIG_RCU_FANOUT_LEAF=16 ++# CONFIG_RCU_FANOUT_EXACT is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_RCU_NOCB_CPU is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_STOP_MACHINE=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++# CONFIG_ARCH_HI3519V101 is not set ++# CONFIG_ARCH_HI3516AV200 is not set ++# CONFIG_ARCH_HI3559 is not set ++# CONFIG_ARCH_HI3556 is not set ++# CONFIG_ARCH_HI3536C is not set ++CONFIG_ARCH_HI3531D=y ++# CONFIG_ARCH_HI3521D is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_OUTER_CACHE=y ++CONFIG_OUTER_CACHE_SYNC=y ++CONFIG_MIGHT_HAVE_CACHE_L2X0=y ++CONFIG_CACHE_L2X0=y ++CONFIG_CACHE_PL310=y ++# CONFIG_PL310_ERRATA_588369 is not set ++# CONFIG_PL310_ERRATA_727915 is not set ++# CONFIG_PL310_ERRATA_753970 is not set ++# CONFIG_PL310_ERRATA_769419 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_643719 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_754327 is not set ++# CONFIG_ARM_ERRATA_764369 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_798181 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++CONFIG_SMP=y ++CONFIG_SMP_ON_UP=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++# CONFIG_SCHED_MC is not set ++# CONFIG_SCHED_SMT is not set ++# CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE is not set ++CONFIG_HAVE_ARM_SCU=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++# CONFIG_MCPM is not set ++# CONFIG_BIG_LITTLE is not set ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++CONFIG_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_ARM_PSCI is not set ++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_THUMB2_KERNEL is not set ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_HAVE_ARCH_PFN_VALID=y ++CONFIG_HIGHMEM=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++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_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# 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_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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++CONFIG_AUTO_ZRELADDR=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_GOV_INTERACTIVE is not set ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++CONFIG_CPUFREQ_DT=y ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ 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_FPE_NWFPE is not set ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_VFP=y ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++# CONFIG_HISI_SNAPSHOT_BOOT is not set ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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=m ++# CONFIG_IP_MROUTE is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_NET_UDP_TUNNEL is not set ++# CONFIG_NET_FOU is not set ++# CONFIG_GENEVE 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=m ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_WIRELESS is not set ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# CONFIG_DMA_SHARED_BUFFER is not set ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++# CONFIG_ARM_CCI 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_HIFMC=y ++CONFIG_HIFMC_SPI_NAND=y ++# CONFIG_HIFMC_NAND 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 is not set ++# 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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_MTD_NAND_HINFC610 is not set ++# CONFIG_HIFMC100_NAND is not set ++CONFIG_HIFMC100_SPI_NAND=y ++CONFIG_SPI_NAND_MAX_CHIP_NUM=1 ++# CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE 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_SPI_NOR_USE_4K_SECTORS is not set ++CONFIG_SPI_HISI_SFC=y ++# CONFIG_CLOSE_SPI_8PIN_4IO is not set ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++# CONFIG_MTD_UBI is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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_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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++CONFIG_BLK_DEV_SR=y ++# CONFIG_BLK_DEV_SR_VENDOR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HI_SATA=y ++CONFIG_HI_SATA_IOBASE=0x11010000 ++CONFIG_HI_SATA_FBS=1 ++CONFIG_HI_SATA_NCQ=1 ++CONFIG_ATA=y ++# CONFIG_ATA_NONSTANDARD is not set ++CONFIG_ATA_VERBOSE_ERROR=y ++CONFIG_SATA_PMP=y ++ ++# ++# Controllers with non-SFF native interface ++# ++CONFIG_SATA_AHCI_PLATFORM=y ++# CONFIG_ATA_SFF is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++CONFIG_ETHERNET=y ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC 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_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# CONFIG_HIETH_SWITCH_FABRIC 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_ETHOC is not set ++# CONFIG_NET_VENDOR_QUALCOMM 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_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_MMIOREG is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART 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_ST_ASC 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_DCC_TTY is not set ++# CONFIG_XILLYBUS is not set ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_COMPAT=y ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_MUX=y ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PINCTRL is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_HIBVT is not set ++# CONFIG_I2C_HISI_V110 is not set ++# CONFIG_I2C_NOMADIK 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_HI_I2C=y ++CONFIG_HI_I2C0_IO_BASE=0x120c0000 ++CONFIG_HI_I2C0_IO_SIZE=0x1000 ++CONFIG_HI_I2C1_IO_BASE=0x122e0000 ++CONFIG_HI_I2C1_IO_SIZE=0x1000 ++CONFIG_HI_I2C_RETRIES=0x1 ++CONFIG_HI_I2C_TX_FIFO=0x8 ++CONFIG_HI_I2C_RX_FIFO=0x8 ++CONFIG_HI_I2C0_CLK_LIMIT=100000 ++CONFIG_HI_I2C1_CLK_LIMIT=100000 ++# CONFIG_I2C_STUB 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_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y ++# CONFIG_GPIOLIB is not set ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# CONFIG_MFD_AS3711 is not set ++# CONFIG_MFD_AS3722 is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_BCM590XX is not set ++# CONFIG_MFD_AXP20X is not set ++# CONFIG_MFD_CROS_EC 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS6507X is not set ++# CONFIG_MFD_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_XHCI_HISILICON=y ++CONFIG_USB_EHCI_HCD=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_HCD is not set ++# CONFIG_USB_FOTG210_HCD is not set ++# CONFIG_USB_MAX3421_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_SISUSBVGA 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_OTG_WAKELOCK is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB is not set ++# CONFIG_USB_ISP1301 is not set ++# CONFIG_USB_ULPI is not set ++# CONFIG_USB_GADGET is not set ++# CONFIG_UWB is not set ++# CONFIG_MMC is not set ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++# CONFIG_PHY_HISI_INNO_USB2 is not set ++CONFIG_PHY_HI35x1D_INNO_USB2=y ++CONFIG_PHY_HI3531D_USB3=y ++CONFIG_HI_NANO_PHY_SATA=y ++CONFIG_HI_SATA_PORTS=4 ++CONFIG_HI_SATA_MODE=1 ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++# CONFIG_JOLIET is not set ++# CONFIG_ZISOFS is not set ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_RCU_CPU_STALL_INFO is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_HASH=y ++CONFIG_CRYPTO_HASH2=y ++# CONFIG_CRYPTO_MANAGER is not set ++# CONFIG_CRYPTO_MANAGER2 is not set ++# CONFIG_CRYPTO_USER is not set ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_PCRYPT is not set ++# 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_SEQIV is not set ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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_ZLIB is not set ++# CONFIG_CRYPTO_LZO 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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=y ++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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_GLOB=y ++# CONFIG_GLOB_SELFTEST is not set ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3531d_nand_defconfig b/arch/arm/configs/hi3531d_nand_defconfig +new file mode 100644 +index 0000000..a88a13d +--- /dev/null ++++ b/arch/arm/configs/hi3531d_nand_defconfig +@@ -0,0 +1,2603 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_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_NEED_MACH_IO_H=y ++CONFIG_GENERIC_BUG=y ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++# CONFIG_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++# CONFIG_FHANDLE is not set ++CONFIG_USELIB=y ++# CONFIG_AUDIT is not set ++ ++# ++# IRQ subsystem ++# ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_GENERIC_IRQ_SHOW=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_HZ_PERIODIC=y ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NO_HZ_FULL 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_TREE_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++# CONFIG_RCU_USER_QS is not set ++CONFIG_RCU_FANOUT=32 ++CONFIG_RCU_FANOUT_LEAF=16 ++# CONFIG_RCU_FANOUT_EXACT is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_RCU_NOCB_CPU is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_PCI_QUIRKS=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=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_STOP_MACHINE=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++# CONFIG_ARCH_HI3519V101 is not set ++# CONFIG_ARCH_HI3516AV200 is not set ++# CONFIG_ARCH_HI3559 is not set ++# CONFIG_ARCH_HI3556 is not set ++# CONFIG_ARCH_HI3536C is not set ++CONFIG_ARCH_HI3531D=y ++# CONFIG_ARCH_HI3521D is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_OUTER_CACHE=y ++CONFIG_OUTER_CACHE_SYNC=y ++CONFIG_MIGHT_HAVE_CACHE_L2X0=y ++CONFIG_CACHE_L2X0=y ++CONFIG_CACHE_PL310=y ++# CONFIG_PL310_ERRATA_588369 is not set ++# CONFIG_PL310_ERRATA_727915 is not set ++# CONFIG_PL310_ERRATA_753970 is not set ++# CONFIG_PL310_ERRATA_769419 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_643719 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_754327 is not set ++# CONFIG_ARM_ERRATA_764369 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_798181 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++CONFIG_PCI=y ++CONFIG_PCI_SYSCALL=y ++# CONFIG_PCI_MSI is not set ++# CONFIG_PCI_DEBUG is not set ++# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set ++# CONFIG_PCI_STUB is not set ++# CONFIG_PCI_IOV is not set ++# CONFIG_PCI_PRI is not set ++# CONFIG_PCI_PASID is not set ++ ++# ++# PCI host controller drivers ++# ++# CONFIG_PCI_HOST_GENERIC is not set ++CONFIG_PCIEPORTBUS=y ++CONFIG_PCIEAER=y ++# CONFIG_PCIE_ECRC is not set ++# CONFIG_PCIEAER_INJECT is not set ++CONFIG_PCIEASPM=y ++# CONFIG_PCIEASPM_DEBUG is not set ++CONFIG_PCIEASPM_DEFAULT=y ++# CONFIG_PCIEASPM_POWERSAVE is not set ++# CONFIG_PCIEASPM_PERFORMANCE is not set ++# CONFIG_PCCARD is not set ++CONFIG_HIPCIE=y ++ ++# ++# PCI Express configs ++# ++CONFIG_PCIE0_SEL=1 ++CONFIG_PCIE0_DEVICES_MEM_SIZE=0x8000000 ++CONFIG_PCIE0_DEVICES_CONFIG_SIZE=0x8000000 ++CONFIG_LIMIT_MAX_RD_REQ_SIZE=y ++CONFIG_PCIE1_SEL=1 ++CONFIG_PCIE1_DEVICES_MEM_SIZE=0x8000000 ++CONFIG_PCIE1_DEVICES_CONFIG_SIZE=0x8000000 ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++CONFIG_SMP=y ++CONFIG_SMP_ON_UP=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++# CONFIG_SCHED_MC is not set ++# CONFIG_SCHED_SMT is not set ++# CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE is not set ++CONFIG_HAVE_ARM_SCU=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++# CONFIG_MCPM is not set ++# CONFIG_BIG_LITTLE is not set ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++CONFIG_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_ARM_PSCI is not set ++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_THUMB2_KERNEL is not set ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_HAVE_ARCH_PFN_VALID=y ++CONFIG_HIGHMEM=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++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_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# 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_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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++CONFIG_AUTO_ZRELADDR=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_GOV_INTERACTIVE is not set ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++CONFIG_CPUFREQ_DT=y ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ 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_FPE_NWFPE is not set ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_VFP=y ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++# CONFIG_HISI_SNAPSHOT_BOOT is not set ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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=m ++# CONFIG_IP_MROUTE is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_NET_UDP_TUNNEL is not set ++# CONFIG_NET_FOU is not set ++# CONFIG_GENEVE 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=m ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_WIRELESS is not set ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# CONFIG_DMA_SHARED_BUFFER is not set ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++# CONFIG_ARM_CCI 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_HIFMC 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_INTEL_VR_NOR is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_PMC551 is not set ++# CONFIG_MTD_DATAFLASH is not set ++# 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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_RICOH is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_CAFE is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++CONFIG_MTD_NAND_HINFC610=y ++# CONFIG_MTD_PARTITION_FROM_DTS is not set ++CONFIG_HINFC610_MAX_CHIP=1 ++# CONFIG_HINFC610_DBG_NAND_DEBUG is not set ++CONFIG_HINFC610_AUTO_PAGESIZE_ECC=y ++# CONFIG_HINFC610_PAGESIZE_AUTO_ECC_NONE 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 is not set ++# CONFIG_MTD_UBI is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST is not set ++CONFIG_OF_FLATTREE=y ++CONFIG_OF_EARLY_FLATTREE=y ++CONFIG_OF_ADDRESS=y ++CONFIG_OF_ADDRESS_PCI=y ++CONFIG_OF_IRQ=y ++CONFIG_OF_NET=y ++CONFIG_OF_MDIO=y ++CONFIG_OF_PCI=y ++CONFIG_OF_PCI_IRQ=y ++CONFIG_OF_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set ++# CONFIG_BLK_CPQ_CISS_DA is not set ++# CONFIG_BLK_DEV_DAC960 is not set ++# CONFIG_BLK_DEV_UMEM is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_NVME is not set ++# CONFIG_BLK_DEV_SX8 is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_BLK_DEV_RSXX is not set ++ ++# ++# Misc devices ++# ++# CONFIG_SENSORS_LIS3LV02D is not set ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_DUMMY_IRQ is not set ++# CONFIG_PHANTOM is not set ++# CONFIG_SGI_IOC4 is not set ++# CONFIG_TIFM_CORE is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_HP_ILO 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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 ++# CONFIG_CB710_CORE is not set ++ ++# ++# Texas Instruments shared transport line discipline ++# ++# 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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++CONFIG_HAVE_IDE=y ++# CONFIG_IDE is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++CONFIG_BLK_DEV_SR=y ++# CONFIG_BLK_DEV_SR_VENDOR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HI_SATA=y ++CONFIG_HI_SATA_IOBASE=0x11010000 ++CONFIG_HI_SATA_FBS=1 ++CONFIG_HI_SATA_NCQ=1 ++CONFIG_ATA=y ++# CONFIG_ATA_NONSTANDARD is not set ++CONFIG_ATA_VERBOSE_ERROR=y ++CONFIG_SATA_PMP=y ++ ++# ++# Controllers with non-SFF native interface ++# ++# CONFIG_SATA_AHCI is not set ++CONFIG_SATA_AHCI_PLATFORM=y ++# CONFIG_SATA_INIC162X is not set ++# CONFIG_SATA_ACARD_AHCI is not set ++# CONFIG_SATA_SIL24 is not set ++# CONFIG_ATA_SFF is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++# CONFIG_FUSION is not set ++ ++# ++# IEEE 1394 (FireWire) support ++# ++# CONFIG_FIREWIRE is not set ++# CONFIG_FIREWIRE_NOSY is not set ++# CONFIG_I2O is not set ++CONFIG_NETDEVICES=y ++CONFIG_NET_CORE=y ++# CONFIG_BONDING is not set ++# CONFIG_DUMMY is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_NET_FC is not set ++# CONFIG_NET_TEAM is not set ++# CONFIG_MACVLAN is not set ++# CONFIG_VXLAN 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_VETH is not set ++# CONFIG_NLMON is not set ++# CONFIG_ARCNET is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++CONFIG_ETHERNET=y ++# CONFIG_NET_VENDOR_3COM is not set ++# CONFIG_NET_VENDOR_ADAPTEC is not set ++# CONFIG_NET_VENDOR_AGERE is not set ++# CONFIG_NET_VENDOR_ALTEON is not set ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC is not set ++# CONFIG_NET_VENDOR_ATHEROS is not set ++# CONFIG_NET_CADENCE is not set ++# CONFIG_NET_VENDOR_BROADCOM is not set ++# CONFIG_NET_VENDOR_BROCADE is not set ++# CONFIG_NET_VENDOR_CHELSIO is not set ++# CONFIG_NET_VENDOR_CIRRUS is not set ++# CONFIG_NET_VENDOR_CISCO is not set ++# CONFIG_DM9000 is not set ++# CONFIG_DNET is not set ++# CONFIG_NET_VENDOR_DEC is not set ++# CONFIG_NET_VENDOR_DLINK is not set ++# CONFIG_NET_VENDOR_EMULEX is not set ++# CONFIG_NET_VENDOR_EXAR is not set ++# CONFIG_NET_VENDOR_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# CONFIG_HIETH_SWITCH_FABRIC is not set ++# CONFIG_NET_VENDOR_HP is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_IP1000 is not set ++# CONFIG_JME is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++# CONFIG_NET_VENDOR_MELLANOX is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_MICROCHIP is not set ++# CONFIG_NET_VENDOR_MYRI is not set ++# CONFIG_FEALNX is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NVIDIA is not set ++# CONFIG_NET_VENDOR_OKI is not set ++# CONFIG_ETHOC is not set ++# CONFIG_NET_PACKET_ENGINE is not set ++# CONFIG_NET_VENDOR_QLOGIC is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++# CONFIG_NET_VENDOR_REALTEK is not set ++# CONFIG_NET_VENDOR_RDC is not set ++# CONFIG_NET_VENDOR_SAMSUNG is not set ++# CONFIG_NET_VENDOR_SEEQ is not set ++# CONFIG_NET_VENDOR_SILAN is not set ++# CONFIG_NET_VENDOR_SIS is not set ++# CONFIG_SFC is not set ++# CONFIG_NET_VENDOR_SMSC is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++# CONFIG_NET_VENDOR_SUN is not set ++# CONFIG_NET_VENDOR_TEHUTI is not set ++# CONFIG_NET_VENDOR_TI is not set ++# CONFIG_NET_VENDOR_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_FDDI is not set ++# CONFIG_HIPPI is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_MMIOREG is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_VMXNET3 is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_PCIPS2 is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_SERIAL_NONSTANDARD is not set ++# CONFIG_NOZOMI is not set ++# CONFIG_N_GSM is not set ++# CONFIG_TRACE_SINK is not set ++CONFIG_DEVMEM=y ++CONFIG_DEVKMEM=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X is not set ++# CONFIG_SERIAL_MFD_HSU is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_JSM is not set ++# CONFIG_SERIAL_SCCNXP is not set ++# CONFIG_SERIAL_SC16IS7XX is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++# CONFIG_SERIAL_ARC is not set ++# CONFIG_SERIAL_RP2 is not set ++# CONFIG_SERIAL_FSL_LPUART is not set ++# CONFIG_SERIAL_ST_ASC 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_APPLICOM is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_DEVPORT=y ++# CONFIG_DCC_TTY is not set ++# CONFIG_XILLYBUS is not set ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_COMPAT=y ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_MUX=y ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PINCTRL is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# PC SMBus host controller drivers ++# ++# CONFIG_I2C_ALI1535 is not set ++# CONFIG_I2C_ALI1563 is not set ++# CONFIG_I2C_ALI15X3 is not set ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++# CONFIG_I2C_I801 is not set ++# CONFIG_I2C_ISCH is not set ++# CONFIG_I2C_PIIX4 is not set ++# CONFIG_I2C_NFORCE2 is not set ++# CONFIG_I2C_SIS5595 is not set ++# CONFIG_I2C_SIS630 is not set ++# CONFIG_I2C_SIS96X is not set ++# CONFIG_I2C_VIA is not set ++# CONFIG_I2C_VIAPRO is not set ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_DESIGNWARE_PCI is not set ++# CONFIG_I2C_HIBVT is not set ++# CONFIG_I2C_HISI_V110 is not set ++# CONFIG_I2C_NOMADIK 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_HI_I2C=y ++CONFIG_HI_I2C0_IO_BASE=0x120c0000 ++CONFIG_HI_I2C0_IO_SIZE=0x1000 ++CONFIG_HI_I2C1_IO_BASE=0x122e0000 ++CONFIG_HI_I2C1_IO_SIZE=0x1000 ++CONFIG_HI_I2C_RETRIES=0x1 ++CONFIG_HI_I2C_TX_FIFO=0x8 ++CONFIG_HI_I2C_RX_FIFO=0x8 ++CONFIG_HI_I2C0_CLK_LIMIT=100000 ++CONFIG_HI_I2C1_CLK_LIMIT=100000 ++# CONFIG_I2C_STUB 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_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# CONFIG_SPI_PXA2XX 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y ++# CONFIG_GPIOLIB is not set ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# CONFIG_MFD_AS3711 is not set ++# CONFIG_MFD_AS3722 is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_BCM590XX is not set ++# CONFIG_MFD_AXP20X is not set ++# CONFIG_MFD_CROS_EC 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_LPC_ICH is not set ++# CONFIG_LPC_SCH is not set ++# CONFIG_INTEL_SOC_PMIC is not set ++# CONFIG_MFD_JANZ_CMODIO 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_RDC321X is not set ++# CONFIG_MFD_RTSX_PCI 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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS6507X is not set ++# CONFIG_MFD_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X 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_VX855 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++CONFIG_VGA_ARB=y ++CONFIG_VGA_ARB_MAX_GPUS=16 ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_CIRRUS is not set ++# CONFIG_FB_PM2 is not set ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CYBER2000 is not set ++# CONFIG_FB_ASILIANT is not set ++# CONFIG_FB_IMSTT is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_NVIDIA is not set ++# CONFIG_FB_RIVA is not set ++# CONFIG_FB_I740 is not set ++# CONFIG_FB_MATROX is not set ++# CONFIG_FB_RADEON is not set ++# CONFIG_FB_ATY128 is not set ++# CONFIG_FB_ATY is not set ++# CONFIG_FB_S3 is not set ++# CONFIG_FB_SAVAGE is not set ++# CONFIG_FB_SIS is not set ++# CONFIG_FB_NEOMAGIC is not set ++# CONFIG_FB_KYRO is not set ++# CONFIG_FB_3DFX is not set ++# CONFIG_FB_VOODOO1 is not set ++# CONFIG_FB_VT8623 is not set ++# CONFIG_FB_TRIDENT is not set ++# CONFIG_FB_ARK is not set ++# CONFIG_FB_PM3 is not set ++# CONFIG_FB_CARMINE is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_MB862XX is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PCI=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_XHCI_HISILICON=y ++CONFIG_USB_EHCI_HCD=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_PCI=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_HCD is not set ++# CONFIG_USB_FOTG210_HCD is not set ++# CONFIG_USB_MAX3421_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PCI=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# CONFIG_USB_UHCI_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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_SISUSBVGA 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_OTG_WAKELOCK is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB is not set ++# CONFIG_USB_ISP1301 is not set ++# CONFIG_USB_ULPI is not set ++# CONFIG_USB_GADGET is not set ++# CONFIG_UWB is not set ++# CONFIG_MMC is not set ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_INFINIBAND is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES is not set ++# CONFIG_AUXDISPLAY is not set ++# CONFIG_UIO is not set ++# CONFIG_VIRT_DRIVERS is not set ++ ++# ++# Virtio drivers ++# ++# CONFIG_VIRTIO_PCI is not set ++# CONFIG_VIRTIO_MMIO is not set ++ ++# ++# Microsoft Hyper-V guest support ++# ++# CONFIG_STAGING is not set ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_VME_BUS is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++# CONFIG_PHY_HISI_INNO_USB2 is not set ++CONFIG_PHY_HI35x1D_INNO_USB2=y ++CONFIG_PHY_HI3531D_USB3=y ++CONFIG_HI_NANO_PHY_SATA=y ++CONFIG_HI_SATA_PORTS=4 ++CONFIG_HI_SATA_MODE=1 ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++CONFIG_RAS=y ++# CONFIG_THUNDERBOLT is not set ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++# CONFIG_JOLIET is not set ++# CONFIG_ZISOFS is not set ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_RCU_CPU_STALL_INFO is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_HASH=y ++CONFIG_CRYPTO_HASH2=y ++# CONFIG_CRYPTO_MANAGER is not set ++# CONFIG_CRYPTO_MANAGER2 is not set ++# CONFIG_CRYPTO_USER is not set ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_PCRYPT is not set ++# 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_SEQIV is not set ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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_ZLIB is not set ++# CONFIG_CRYPTO_LZO 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_CRYPTO_DEV_HIFN_795X is not set ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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=y ++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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_GLOB=y ++# CONFIG_GLOB_SELFTEST is not set ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3531d_nand_slave_defconfig b/arch/arm/configs/hi3531d_nand_slave_defconfig +new file mode 100644 +index 0000000..aa7138a +--- /dev/null ++++ b/arch/arm/configs/hi3531d_nand_slave_defconfig +@@ -0,0 +1,2429 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_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_GENERIC_BUG=y ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++# CONFIG_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++# CONFIG_FHANDLE is not set ++CONFIG_USELIB=y ++# CONFIG_AUDIT is not set ++ ++# ++# IRQ subsystem ++# ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_GENERIC_IRQ_SHOW=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_HZ_PERIODIC=y ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NO_HZ_FULL 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_TREE_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++# CONFIG_RCU_USER_QS is not set ++CONFIG_RCU_FANOUT=32 ++CONFIG_RCU_FANOUT_LEAF=16 ++# CONFIG_RCU_FANOUT_EXACT is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_RCU_NOCB_CPU is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_STOP_MACHINE=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++# CONFIG_ARCH_HI3519V101 is not set ++# CONFIG_ARCH_HI3516AV200 is not set ++# CONFIG_ARCH_HI3559 is not set ++# CONFIG_ARCH_HI3556 is not set ++# CONFIG_ARCH_HI3536C is not set ++CONFIG_ARCH_HI3531D=y ++# CONFIG_ARCH_HI3521D is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_OUTER_CACHE=y ++CONFIG_OUTER_CACHE_SYNC=y ++CONFIG_MIGHT_HAVE_CACHE_L2X0=y ++CONFIG_CACHE_L2X0=y ++CONFIG_CACHE_PL310=y ++# CONFIG_PL310_ERRATA_588369 is not set ++# CONFIG_PL310_ERRATA_727915 is not set ++# CONFIG_PL310_ERRATA_753970 is not set ++# CONFIG_PL310_ERRATA_769419 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_643719 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_754327 is not set ++# CONFIG_ARM_ERRATA_764369 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_798181 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++CONFIG_SMP=y ++CONFIG_SMP_ON_UP=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++# CONFIG_SCHED_MC is not set ++# CONFIG_SCHED_SMT is not set ++# CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE is not set ++CONFIG_HAVE_ARM_SCU=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++# CONFIG_MCPM is not set ++# CONFIG_BIG_LITTLE is not set ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++CONFIG_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_ARM_PSCI is not set ++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_THUMB2_KERNEL is not set ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_HAVE_ARCH_PFN_VALID=y ++CONFIG_HIGHMEM=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++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_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# 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_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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++CONFIG_AUTO_ZRELADDR=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_GOV_INTERACTIVE is not set ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++CONFIG_CPUFREQ_DT=y ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ 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_FPE_NWFPE is not set ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_VFP=y ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++# CONFIG_HISI_SNAPSHOT_BOOT is not set ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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=m ++# CONFIG_IP_MROUTE is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_NET_UDP_TUNNEL is not set ++# CONFIG_NET_FOU is not set ++# CONFIG_GENEVE 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=m ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_WIRELESS is not set ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# CONFIG_DMA_SHARED_BUFFER is not set ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++# CONFIG_ARM_CCI 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_HIFMC 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_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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++CONFIG_MTD_NAND_HINFC610=y ++# CONFIG_MTD_PARTITION_FROM_DTS is not set ++CONFIG_HINFC610_MAX_CHIP=1 ++# CONFIG_HINFC610_DBG_NAND_DEBUG is not set ++CONFIG_HINFC610_AUTO_PAGESIZE_ECC=y ++# CONFIG_HINFC610_PAGESIZE_AUTO_ECC_NONE 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 is not set ++# CONFIG_MTD_UBI is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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_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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++CONFIG_BLK_DEV_SR=y ++# CONFIG_BLK_DEV_SR_VENDOR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HI_SATA=y ++CONFIG_HI_SATA_IOBASE=0x11010000 ++CONFIG_HI_SATA_FBS=1 ++CONFIG_HI_SATA_NCQ=1 ++CONFIG_ATA=y ++# CONFIG_ATA_NONSTANDARD is not set ++CONFIG_ATA_VERBOSE_ERROR=y ++CONFIG_SATA_PMP=y ++ ++# ++# Controllers with non-SFF native interface ++# ++CONFIG_SATA_AHCI_PLATFORM=y ++# CONFIG_ATA_SFF is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++CONFIG_ETHERNET=y ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC 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_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# CONFIG_HIETH_SWITCH_FABRIC 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_ETHOC is not set ++# CONFIG_NET_VENDOR_QUALCOMM 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_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_MMIOREG is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART 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_ST_ASC 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_DCC_TTY is not set ++# CONFIG_XILLYBUS is not set ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_COMPAT=y ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_MUX=y ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PINCTRL is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_HIBVT is not set ++# CONFIG_I2C_HISI_V110 is not set ++# CONFIG_I2C_NOMADIK 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_HI_I2C=y ++CONFIG_HI_I2C0_IO_BASE=0x120c0000 ++CONFIG_HI_I2C0_IO_SIZE=0x1000 ++CONFIG_HI_I2C1_IO_BASE=0x122e0000 ++CONFIG_HI_I2C1_IO_SIZE=0x1000 ++CONFIG_HI_I2C_RETRIES=0x1 ++CONFIG_HI_I2C_TX_FIFO=0x8 ++CONFIG_HI_I2C_RX_FIFO=0x8 ++CONFIG_HI_I2C0_CLK_LIMIT=100000 ++CONFIG_HI_I2C1_CLK_LIMIT=100000 ++# CONFIG_I2C_STUB 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_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y ++# CONFIG_GPIOLIB is not set ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# CONFIG_MFD_AS3711 is not set ++# CONFIG_MFD_AS3722 is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_BCM590XX is not set ++# CONFIG_MFD_AXP20X is not set ++# CONFIG_MFD_CROS_EC 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS6507X is not set ++# CONFIG_MFD_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_XHCI_HISILICON=y ++CONFIG_USB_EHCI_HCD=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_HCD is not set ++# CONFIG_USB_FOTG210_HCD is not set ++# CONFIG_USB_MAX3421_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_SISUSBVGA 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_OTG_WAKELOCK is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB is not set ++# CONFIG_USB_ISP1301 is not set ++# CONFIG_USB_ULPI is not set ++# CONFIG_USB_GADGET is not set ++# CONFIG_UWB is not set ++# CONFIG_MMC is not set ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++# CONFIG_PHY_HISI_INNO_USB2 is not set ++CONFIG_PHY_HI35x1D_INNO_USB2=y ++CONFIG_PHY_HI3531D_USB3=y ++CONFIG_HI_NANO_PHY_SATA=y ++CONFIG_HI_SATA_PORTS=4 ++CONFIG_HI_SATA_MODE=1 ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++# CONFIG_JOLIET is not set ++# CONFIG_ZISOFS is not set ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_RCU_CPU_STALL_INFO is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_HASH=y ++CONFIG_CRYPTO_HASH2=y ++# CONFIG_CRYPTO_MANAGER is not set ++# CONFIG_CRYPTO_MANAGER2 is not set ++# CONFIG_CRYPTO_USER is not set ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_PCRYPT is not set ++# 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_SEQIV is not set ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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_ZLIB is not set ++# CONFIG_CRYPTO_LZO 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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=y ++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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_GLOB=y ++# CONFIG_GLOB_SELFTEST is not set ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3536c_full_defconfig b/arch/arm/configs/hi3536c_full_defconfig +new file mode 100644 +index 0000000..59f1a87 +--- /dev/null ++++ b/arch/arm/configs/hi3536c_full_defconfig +@@ -0,0 +1,2521 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=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_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_GENERIC_BUG=y ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++# CONFIG_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++CONFIG_CROSS_MEMORY_ATTACH=y ++# CONFIG_FHANDLE is not set ++CONFIG_USELIB=y ++# CONFIG_AUDIT is not set ++ ++# ++# IRQ subsystem ++# ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_GENERIC_IRQ_SHOW=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_HZ_PERIODIC=y ++# CONFIG_NO_HZ_IDLE is not set ++# CONFIG_NO_HZ_FULL 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_TREE_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++CONFIG_RCU_STALL_COMMON=y ++# CONFIG_RCU_USER_QS is not set ++CONFIG_RCU_FANOUT=32 ++CONFIG_RCU_FANOUT_LEAF=16 ++# CONFIG_RCU_FANOUT_EXACT is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_RCU_NOCB_CPU is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++CONFIG_SLUB_CPU_PARTIAL=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_STOP_MACHINE=y ++CONFIG_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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_MUTEX_SPIN_ON_OWNER=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++# CONFIG_ARCH_HI3519V101 is not set ++# CONFIG_ARCH_HI3516AV200 is not set ++# CONFIG_ARCH_HI3559 is not set ++# CONFIG_ARCH_HI3556 is not set ++CONFIG_ARCH_HI3536C=y ++# CONFIG_ARCH_HI3531D is not set ++# CONFIG_ARCH_HI3521D is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_643719 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_754327 is not set ++# CONFIG_ARM_ERRATA_764369 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_798181 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++CONFIG_SMP=y ++CONFIG_SMP_ON_UP=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++# CONFIG_SCHED_MC is not set ++# CONFIG_SCHED_SMT is not set ++# CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE is not set ++CONFIG_HAVE_ARM_SCU=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++# CONFIG_MCPM is not set ++# CONFIG_BIG_LITTLE is not set ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++CONFIG_NR_CPUS=4 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_ARM_PSCI is not set ++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_THUMB2_KERNEL is not set ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_HAVE_ARCH_PFN_VALID=y ++CONFIG_HIGHMEM=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++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_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++# 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_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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++CONFIG_AUTO_ZRELADDR=y ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_GOV_USERSPACE is not set ++# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set ++# CONFIG_CPU_FREQ_GOV_INTERACTIVE is not set ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++CONFIG_CPUFREQ_DT=y ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ 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_FPE_NWFPE is not set ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_VFP=y ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++# CONFIG_HISI_SNAPSHOT_BOOT is not set ++CONFIG_PM_SLEEP=y ++CONFIG_PM_SLEEP_SMP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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=m ++# CONFIG_IP_MROUTE is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_NET_UDP_TUNNEL is not set ++# CONFIG_NET_FOU is not set ++# CONFIG_GENEVE 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=m ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++CONFIG_RPS=y ++CONFIG_RFS_ACCEL=y ++CONFIG_XPS=y ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID is not set ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_BQL=y ++# CONFIG_BPF_JIT is not set ++CONFIG_NET_FLOW_LIMIT=y ++ ++# ++# 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_WIRELESS is not set ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++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_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++# CONFIG_DMA_SHARED_BUFFER is not set ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++# CONFIG_ARM_CCI 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_HIFMC=y ++CONFIG_HIFMC_SPI_NAND=y ++# CONFIG_HIFMC_NAND 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 is not set ++# 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=y ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOCG3 is not set ++CONFIG_MTD_NAND_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_MTD_NAND_HINFC610 is not set ++# CONFIG_HIFMC100_NAND is not set ++CONFIG_HIFMC100_SPI_NAND=y ++CONFIG_SPI_NAND_MAX_CHIP_NUM=1 ++# CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE 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_SPI_NOR_USE_4K_SECTORS is not set ++CONFIG_SPI_HISI_SFC=y ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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_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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++CONFIG_BLK_DEV_SR=y ++# CONFIG_BLK_DEV_SR_VENDOR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++CONFIG_HI_SATA=y ++CONFIG_HI_SATA_IOBASE=0x11010000 ++CONFIG_HI_SATA_FBS=1 ++CONFIG_HI_SATA_NCQ=1 ++CONFIG_ATA=y ++# CONFIG_ATA_NONSTANDARD is not set ++CONFIG_ATA_VERBOSE_ERROR=y ++CONFIG_SATA_PMP=y ++ ++# ++# Controllers with non-SFF native interface ++# ++CONFIG_SATA_AHCI_PLATFORM=y ++# CONFIG_ATA_SFF is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++CONFIG_ETHERNET=y ++# CONFIG_ALTERA_TSE is not set ++# CONFIG_NET_XGENE is not set ++# CONFIG_NET_VENDOR_ARC 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_FARADAY is not set ++CONFIG_NET_VENDOR_HISILICON=y ++# CONFIG_HIX5HD2_GMAC is not set ++# CONFIG_HISI_FEMAC is not set ++CONFIG_HIETH_GMAC=y ++CONFIG_HIGMAC_DESC_4WORD=y ++CONFIG_HIGMAC_RXCSUM=y ++CONFIG_RX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_SUPPORT=y ++CONFIG_TX_FLOW_CTRL_PAUSE_TIME=0xFFFF ++CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL=0xFFFF ++CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD=16 ++CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD=32 ++# CONFIG_HIETH_SWITCH_FABRIC 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_ETHOC is not set ++# CONFIG_NET_VENDOR_QUALCOMM 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_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_MMIOREG is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++CONFIG_MDIO_HISI_GEMAC=y ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_WLAN is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_JOYDEV=y ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART 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_ST_ASC 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_DCC_TTY is not set ++# CONFIG_XILLYBUS is not set ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_COMPAT=y ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_MUX=y ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PINCTRL is not set ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_HIBVT is not set ++# CONFIG_I2C_HISI_V110 is not set ++# CONFIG_I2C_NOMADIK 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_HI_I2C=y ++CONFIG_HI_I2C0_IO_BASE=0x120c0000 ++CONFIG_HI_I2C0_IO_SIZE=0x1000 ++CONFIG_HI_I2C_RETRIES=0x1 ++CONFIG_HI_I2C_TX_FIFO=0x8 ++CONFIG_HI_I2C_RX_FIFO=0x8 ++CONFIG_HI_I2C0_CLK_LIMIT=100000 ++# CONFIG_I2C_STUB 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_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_PINCONF=y ++CONFIG_GENERIC_PINCONF=y ++# CONFIG_DEBUG_PINCTRL is not set ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y ++CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y ++# CONFIG_GPIOLIB is not set ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_MANAGER is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# CONFIG_MFD_AS3711 is not set ++# CONFIG_MFD_AS3722 is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_BCM590XX is not set ++# CONFIG_MFD_AXP20X is not set ++# CONFIG_MFD_CROS_EC 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS6507X is not set ++# CONFIG_MFD_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEFAULT_PERSIST=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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=y ++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_HCD is not set ++# CONFIG_USB_FOTG210_HCD is not set ++# CONFIG_USB_MAX3421_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++# 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 is not set ++# 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 ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_SISUSBVGA 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_OTG_WAKELOCK is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB is not set ++# CONFIG_USB_ISP1301 is not set ++# CONFIG_USB_ULPI is not set ++# CONFIG_USB_GADGET is not set ++# CONFIG_UWB is not set ++# CONFIG_MMC is not set ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++CONFIG_RTC_CLASS=y ++CONFIG_RTC_HCTOSYS=y ++CONFIG_RTC_SYSTOHC=y ++CONFIG_RTC_HCTOSYS_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_DS1307 is not set ++# CONFIG_RTC_DRV_DS1374 is not set ++# CONFIG_RTC_DRV_DS1672 is not set ++# CONFIG_RTC_DRV_DS3232 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_ISL12057 is not set ++# CONFIG_RTC_DRV_X1205 is not set ++# CONFIG_RTC_DRV_PCF2127 is not set ++# CONFIG_RTC_DRV_PCF8523 is not set ++# CONFIG_RTC_DRV_PCF8563 is not set ++# CONFIG_RTC_DRV_PCF85063 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_RX8581 is not set ++# CONFIG_RTC_DRV_RX8025 is not set ++# CONFIG_RTC_DRV_EM3027 is not set ++# CONFIG_RTC_DRV_RV3029C2 is not set ++ ++# ++# SPI RTC drivers ++# ++# CONFIG_RTC_DRV_M41T93 is not set ++# CONFIG_RTC_DRV_M41T94 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_MAX6902 is not set ++# CONFIG_RTC_DRV_R9701 is not set ++# CONFIG_RTC_DRV_RS5C348 is not set ++# CONFIG_RTC_DRV_DS3234 is not set ++# CONFIG_RTC_DRV_PCF2123 is not set ++# CONFIG_RTC_DRV_RX4581 is not set ++# CONFIG_RTC_DRV_MCP795 is not set ++ ++# ++# Platform RTC drivers ++# ++CONFIG_RTC_DRV_HIBVT=y ++# 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_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_PL030 is not set ++# CONFIG_RTC_DRV_PL031 is not set ++# CONFIG_RTC_DRV_SNVS is not set ++# CONFIG_RTC_DRV_XGENE is not set ++ ++# ++# HID Sensor RTC drivers ++# ++# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=y ++CONFIG_HI_NANO_PHY_SATA=y ++CONFIG_HI_SATA_PORTS=2 ++CONFIG_HI_SATA_MODE=1 ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++CONFIG_HI_DMAC=y ++CONFIG_HI_DMAC_CHANNEL_NUM=4 ++ ++# ++# Hisilicon driver support ++# ++ ++# ++# File systems ++# ++CONFIG_DCACHE_WORD_ACCESS=y ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++# CONFIG_JOLIET is not set ++# CONFIG_ZISOFS is not set ++# CONFIG_UDF_FS is not set ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_LOGFS is not set ++CONFIG_CRAMFS=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_PER_CPU_MAPS is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++# CONFIG_PANIC_ON_OOPS is not set ++CONFIG_PANIC_ON_OOPS_VALUE=0 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_RCU_CPU_STALL_INFO is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_HASH=y ++CONFIG_CRYPTO_HASH2=y ++# CONFIG_CRYPTO_MANAGER is not set ++# CONFIG_CRYPTO_MANAGER2 is not set ++# CONFIG_CRYPTO_USER is not set ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_PCRYPT is not set ++# 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_SEQIV is not set ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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=y ++# CONFIG_CRYPTO_ZLIB is not set ++CONFIG_CRYPTO_LZO=y ++# 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_CPU_RMAP=y ++CONFIG_DQL=y ++CONFIG_GLOB=y ++# CONFIG_GLOB_SELFTEST is not set ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++# CONFIG_AVERAGE is not set ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3556_single_defconfig b/arch/arm/configs/hi3556_single_defconfig +new file mode 100644 +index 0000000..1260690 +--- /dev/null ++++ b/arch/arm/configs/hi3556_single_defconfig +@@ -0,0 +1,2617 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=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_GENERIC_BUG=y ++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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++# CONFIG_HW_DECOMPRESS is not set ++CONFIG_SOFT_DECOMPRESS=y ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++CONFIG_NO_HZ=y ++# 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_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++# CONFIG_RCU_STALL_COMMON is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++# CONFIG_ARCH_HI3519V101 is not set ++# CONFIG_ARCH_HI3516AV200 is not set ++# CONFIG_ARCH_HI3559 is not set ++CONFIG_ARCH_HI3556=y ++# CONFIG_ARCH_HI3536C is not set ++# CONFIG_ARCH_HI3531D is not set ++# CONFIG_ARCH_HI3521D is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++# CONFIG_SMP is not set ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++# CONFIG_ARM_PSCI is not set ++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 is not set ++# 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=y ++CONFIG_HZ=1000 ++# CONFIG_SCHED_HRTICK is not set ++# CONFIG_THUMB2_KERNEL 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=y ++# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_NEED_PER_CPU_KM=y ++# CONFIG_CLEANCACHE is not set ++# CONFIG_FRONTSWAP is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++CONFIG_CMA_AREAS=7 ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_AUTO_ZRELADDR is not set ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_INTERACTIVE=y ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++# CONFIG_CPUFREQ_DT is not set ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HISI_SNAPSHOT_BOOT=y ++# CONFIG_DEFAULT_MTD is not set ++CONFIG_DEFAULT_DDR=y ++CONFIG_SNAPSHOT_BUF_START=0x8a000000 ++CONFIG_SNAPSHOT_BUF_SIZE=0x4000000 ++CONFIG_HIBERNATION=y ++CONFIG_GZIP_COMPRESS=y ++CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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=m ++# 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_GENEVE 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=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=16 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++CONFIG_ARM_CCI=y ++# 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_SWAP is not set ++CONFIG_HIFMC=y ++CONFIG_HIFMC_SPI_NAND=y ++# CONFIG_HIFMC_NAND 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 is not set ++# 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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_MTD_NAND_HINFC610 is not set ++# CONFIG_HIFMC100_NAND is not set ++CONFIG_HIFMC100_SPI_NAND=y ++CONFIG_SPI_NAND_MAX_CHIP_NUM=1 ++# CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE 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_SPI_NOR_USE_4K_SECTORS is not set ++CONFIG_SPI_HISI_SFC=y ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++# CONFIG_ETHERNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY 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_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++# CONFIG_MDIO_HISI_GEMAC 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++CONFIG_WLAN=y ++# CONFIG_WIFI_CONTROL_FUNC is not set ++# CONFIG_HOSTAP is not set ++# CONFIG_WL_TI is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_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_ST_ASC is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_HW_RANDOM=y ++# CONFIG_HW_RANDOM_TIMERIOMEM is not set ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++# CONFIG_DCC_TTY 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=m ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set ++# CONFIG_I2C_MUX_GPIO is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PCA954x 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_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_HIBVT is not set ++CONFIG_I2C_HISI_V110=y ++# CONFIG_I2C_NOMADIK 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_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_OC_TINY is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_ARCH_WANT_OPTIONAL_GPIOLIB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_DEVRES=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_GENERIC_PLATFORM is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_EM is not set ++# CONFIG_GPIO_ZEVIO is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_SCH311X is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_GRGPIO is not set ++ ++# ++# I2C GPIO expanders: ++# ++# 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_ADP5588 is not set ++# CONFIG_GPIO_ADNP is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_GPIO_MC33880 is not set ++# CONFIG_GPIO_74X164 is not set ++ ++# ++# AC97 GPIO expanders: ++# ++ ++# ++# LPC GPIO expanders: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++ ++# ++# USB GPIO expanders: ++# ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_BCM590XX is not set ++# CONFIG_MFD_AXP20X 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_EGPIO 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X is not set ++# CONFIG_MFD_TPS65910 is not set ++# CONFIG_MFD_TPS65912 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=m ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=m ++CONFIG_VIDEO_V4L2=m ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=m ++CONFIG_VIDEOBUF2_MEMOPS=m ++CONFIG_VIDEOBUF2_VMALLOC=m ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++# CONFIG_MEDIA_USB_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# Audio decoders, processors and mixers ++# ++ ++# ++# RDS decoders ++# ++ ++# ++# Video decoders ++# ++ ++# ++# Video and audio decoders ++# ++ ++# ++# Video encoders ++# ++ ++# ++# Camera sensor devices ++# ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++ ++# ++# Audio/Video compression chips ++# ++ ++# ++# Miscellaneous helper chips ++# ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++# CONFIG_USB_DEFAULT_PERSIST is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_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 is not set ++# 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 ++# ++# CONFIG_USB_STORAGE is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_OTG_WAKELOCK is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_AUTO_SWITCH is not set ++# CONFIG_HIUSB_DEVICE3_0 is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_ACM=m ++CONFIG_USB_U_SERIAL=m ++CONFIG_USB_U_ETHER=m ++CONFIG_USB_F_RNDIS=m ++CONFIG_USB_F_MASS_STORAGE=m ++CONFIG_USB_F_UAC1=m ++CONFIG_USB_F_UVC=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++CONFIG_USB_AUDIO=m ++CONFIG_GADGET_UAC1=y ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++CONFIG_USB_G_MULTI=m ++CONFIG_USB_G_MULTI_RNDIS=y ++# CONFIG_USB_G_MULTI_CDC is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM is not set ++CONFIG_USB_G_WEBCAM_AUDIO=m ++# CONFIG_UWB is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# 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_HIMCIV200=y ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++# CONFIG_HI_DMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE 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=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_LOGFS is not set ++CONFIG_CRAMFS=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_RNG=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_PCOMP2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++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=y ++# CONFIG_CRYPTO_GCM is not set ++CONFIG_CRYPTO_SEQIV=y ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=y ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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=y ++# CONFIG_CRYPTO_ZLIB is not set ++CONFIG_CRYPTO_LZO=y ++# 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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=y ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++CONFIG_AVERAGE=y ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3556_single_nand_defconfig b/arch/arm/configs/hi3556_single_nand_defconfig +new file mode 100644 +index 0000000..64824dd +--- /dev/null ++++ b/arch/arm/configs/hi3556_single_nand_defconfig +@@ -0,0 +1,2615 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=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_GENERIC_BUG=y ++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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++# CONFIG_HW_DECOMPRESS is not set ++CONFIG_SOFT_DECOMPRESS=y ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++CONFIG_NO_HZ=y ++# 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_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++# CONFIG_RCU_STALL_COMMON is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++# CONFIG_ARCH_HI3519V101 is not set ++# CONFIG_ARCH_HI3516AV200 is not set ++# CONFIG_ARCH_HI3559 is not set ++CONFIG_ARCH_HI3556=y ++# CONFIG_ARCH_HI3536C is not set ++# CONFIG_ARCH_HI3531D is not set ++# CONFIG_ARCH_HI3521D is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++# CONFIG_SMP is not set ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++# CONFIG_ARM_PSCI is not set ++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 is not set ++# 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=y ++CONFIG_HZ=1000 ++# CONFIG_SCHED_HRTICK is not set ++# CONFIG_THUMB2_KERNEL 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=y ++# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_NEED_PER_CPU_KM=y ++# CONFIG_CLEANCACHE is not set ++# CONFIG_FRONTSWAP is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++CONFIG_CMA_AREAS=7 ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_AUTO_ZRELADDR is not set ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_INTERACTIVE=y ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++# CONFIG_CPUFREQ_DT is not set ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HISI_SNAPSHOT_BOOT=y ++# CONFIG_DEFAULT_MTD is not set ++CONFIG_DEFAULT_DDR=y ++CONFIG_SNAPSHOT_BUF_START=0x8a000000 ++CONFIG_SNAPSHOT_BUF_SIZE=0x4000000 ++CONFIG_HIBERNATION=y ++CONFIG_GZIP_COMPRESS=y ++CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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=m ++# 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_GENEVE 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=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=16 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++CONFIG_ARM_CCI=y ++# 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_SWAP is not set ++CONFIG_HIFMC=y ++# CONFIG_HIFMC_SPI_NAND is not set ++CONFIG_HIFMC_NAND=y ++ ++# ++# 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_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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_MTD_NAND_HINFC610 is not set ++CONFIG_HIFMC100_NAND=y ++CONFIG_HIFMC100_MAX_NAND_CHIP=1 ++# CONFIG_HIFMC100_NAND_EDO_MODE is not set ++CONFIG_RW_H_WIDTH=10 ++CONFIG_R_L_WIDTH=10 ++CONFIG_W_L_WIDTH=10 ++# CONFIG_HIFMC100_NAND_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_NAND_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_NAND_PAGESIZE_AUTO_ECC_NONE 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 is not set ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++# CONFIG_ETHERNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY 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_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++# CONFIG_MDIO_HISI_GEMAC 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++CONFIG_WLAN=y ++# CONFIG_WIFI_CONTROL_FUNC is not set ++# CONFIG_HOSTAP is not set ++# CONFIG_WL_TI is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_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_ST_ASC is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_HW_RANDOM=y ++# CONFIG_HW_RANDOM_TIMERIOMEM is not set ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++# CONFIG_DCC_TTY 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=m ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set ++# CONFIG_I2C_MUX_GPIO is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PCA954x 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_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_HIBVT is not set ++CONFIG_I2C_HISI_V110=y ++# CONFIG_I2C_NOMADIK 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_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_OC_TINY is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_ARCH_WANT_OPTIONAL_GPIOLIB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_DEVRES=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_GENERIC_PLATFORM is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_EM is not set ++# CONFIG_GPIO_ZEVIO is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_SCH311X is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_GRGPIO is not set ++ ++# ++# I2C GPIO expanders: ++# ++# 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_ADP5588 is not set ++# CONFIG_GPIO_ADNP is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_GPIO_MC33880 is not set ++# CONFIG_GPIO_74X164 is not set ++ ++# ++# AC97 GPIO expanders: ++# ++ ++# ++# LPC GPIO expanders: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++ ++# ++# USB GPIO expanders: ++# ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_BCM590XX is not set ++# CONFIG_MFD_AXP20X 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_EGPIO 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X is not set ++# CONFIG_MFD_TPS65910 is not set ++# CONFIG_MFD_TPS65912 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=m ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=m ++CONFIG_VIDEO_V4L2=m ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=m ++CONFIG_VIDEOBUF2_MEMOPS=m ++CONFIG_VIDEOBUF2_VMALLOC=m ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++# CONFIG_MEDIA_USB_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# Audio decoders, processors and mixers ++# ++ ++# ++# RDS decoders ++# ++ ++# ++# Video decoders ++# ++ ++# ++# Video and audio decoders ++# ++ ++# ++# Video encoders ++# ++ ++# ++# Camera sensor devices ++# ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++ ++# ++# Audio/Video compression chips ++# ++ ++# ++# Miscellaneous helper chips ++# ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++# CONFIG_USB_DEFAULT_PERSIST is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_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 is not set ++# 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 ++# ++# CONFIG_USB_STORAGE is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_OTG_WAKELOCK is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_AUTO_SWITCH is not set ++# CONFIG_HIUSB_DEVICE3_0 is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_ACM=m ++CONFIG_USB_U_SERIAL=m ++CONFIG_USB_U_ETHER=m ++CONFIG_USB_F_RNDIS=m ++CONFIG_USB_F_MASS_STORAGE=m ++CONFIG_USB_F_UAC1=m ++CONFIG_USB_F_UVC=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++CONFIG_USB_AUDIO=m ++CONFIG_GADGET_UAC1=y ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++CONFIG_USB_G_MULTI=m ++CONFIG_USB_G_MULTI_RNDIS=y ++# CONFIG_USB_G_MULTI_CDC is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM is not set ++CONFIG_USB_G_WEBCAM_AUDIO=m ++# CONFIG_UWB is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# 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_HIMCIV200=y ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++# CONFIG_HI_DMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE 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=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_LOGFS is not set ++CONFIG_CRAMFS=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_RNG=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_PCOMP2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++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=y ++# CONFIG_CRYPTO_GCM is not set ++CONFIG_CRYPTO_SEQIV=y ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=y ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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=y ++# CONFIG_CRYPTO_ZLIB is not set ++CONFIG_CRYPTO_LZO=y ++# 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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=y ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++CONFIG_AVERAGE=y ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3556_single_nand_mini_defconfig b/arch/arm/configs/hi3556_single_nand_mini_defconfig +new file mode 100644 +index 0000000..b56c7ef +--- /dev/null ++++ b/arch/arm/configs/hi3556_single_nand_mini_defconfig +@@ -0,0 +1,2396 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=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_GENERIC_BUG=y ++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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_HW_DECOMPRESS=y ++# CONFIG_SOFT_DECOMPRESS is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++CONFIG_NO_HZ=y ++# 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_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++# CONFIG_RCU_STALL_COMMON is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++# CONFIG_NAMESPACES is not set ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++# CONFIG_BLK_DEV_INITRD is not set ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++CONFIG_EXPERT=y ++# CONFIG_UID16 is not set ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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 is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++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_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++# CONFIG_ARCH_HI3519V101 is not set ++# CONFIG_ARCH_HI3516AV200 is not set ++# CONFIG_ARCH_HI3559 is not set ++CONFIG_ARCH_HI3556=y ++# CONFIG_ARCH_HI3536C is not set ++# CONFIG_ARCH_HI3531D is not set ++# CONFIG_ARCH_HI3521D is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++# CONFIG_SMP is not set ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++# CONFIG_ARM_PSCI is not set ++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 is not set ++# 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=y ++CONFIG_HZ=1000 ++# CONFIG_SCHED_HRTICK is not set ++# CONFIG_THUMB2_KERNEL 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=y ++# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_NEED_PER_CPU_KM=y ++# CONFIG_CLEANCACHE is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++CONFIG_CMA_AREAS=7 ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_AUTO_ZRELADDR is not set ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_INTERACTIVE=y ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++# CONFIG_CPUFREQ_DT is not set ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_WAKELOCK is not set ++# CONFIG_HISI_SNAPSHOT_BOOT is not set ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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 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_GENEVE 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 is not set ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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 is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES 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_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_IEEE802154 is not set ++# CONFIG_NET_SCHED is not set ++# CONFIG_DCB is not set ++# CONFIG_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=16 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++CONFIG_ARM_CCI=y ++# 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_HIFMC=y ++# CONFIG_HIFMC_SPI_NAND is not set ++CONFIG_HIFMC_NAND=y ++ ++# ++# 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_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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_MTD_NAND_HINFC610 is not set ++CONFIG_HIFMC100_NAND=y ++CONFIG_HIFMC100_MAX_NAND_CHIP=1 ++CONFIG_HIFMC100_NAND_EDO_MODE=y ++CONFIG_RW_H_WIDTH=3 ++CONFIG_R_L_WIDTH=2 ++CONFIG_W_L_WIDTH=2 ++# CONFIG_HIFMC100_NAND_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_NAND_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_NAND_PAGESIZE_AUTO_ECC_NONE 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 is not set ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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_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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++# CONFIG_ETHERNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_MMIOREG is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++# CONFIG_MDIO_HISI_GEMAC is not set ++# CONFIG_MICREL_KS8995MA is not set ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++ ++# ++# Host-side USB support is needed for USB Network Adapter support ++# ++CONFIG_USB_NET_DRIVERS=m ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++CONFIG_WLAN=y ++# CONFIG_WIFI_CONTROL_FUNC is not set ++# CONFIG_HOSTAP is not set ++# CONFIG_WL_TI is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO 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 ++ ++# ++# 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_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART 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_ST_ASC is not set ++# CONFIG_TTY_PRINTK is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_HW_RANDOM=y ++# CONFIG_HW_RANDOM_TIMERIOMEM is not set ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++# CONFIG_DCC_TTY 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=m ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_MUX_PCA9541 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_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_HIBVT is not set ++CONFIG_I2C_HISI_V110=y ++# CONFIG_I2C_NOMADIK 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_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_ARCH_WANT_OPTIONAL_GPIOLIB=y ++# CONFIG_GPIOLIB is not set ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# CONFIG_MFD_AS3711 is not set ++# CONFIG_MFD_AS3722 is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_BCM590XX is not set ++# CONFIG_MFD_AXP20X is not set ++# CONFIG_MFD_CROS_EC 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS6507X is not set ++# CONFIG_MFD_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=m ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=m ++CONFIG_VIDEO_V4L2=m ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=m ++CONFIG_VIDEOBUF2_MEMOPS=m ++CONFIG_VIDEOBUF2_VMALLOC=m ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++# CONFIG_MEDIA_USB_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# Audio decoders, processors and mixers ++# ++ ++# ++# RDS decoders ++# ++ ++# ++# Video decoders ++# ++ ++# ++# Video and audio decoders ++# ++ ++# ++# Video encoders ++# ++ ++# ++# Camera sensor devices ++# ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++ ++# ++# Audio/Video compression chips ++# ++ ++# ++# Miscellaneous helper chips ++# ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++# CONFIG_HID_A4TECH is not set ++# CONFIG_HID_ACRUX is not set ++# CONFIG_HID_APPLE is not set ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++# CONFIG_HID_BELKIN is not set ++# CONFIG_HID_CHERRY is not set ++# CONFIG_HID_CHICONY is not set ++# CONFIG_HID_CYPRESS is not set ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++# CONFIG_HID_EZKEY is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++# CONFIG_HID_KENSINGTON is not set ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++# CONFIG_HID_LOGITECH is not set ++# CONFIG_HID_MAGICMOUSE is not set ++# CONFIG_HID_MICROSOFT is not set ++# CONFIG_HID_MONTEREY is not set ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=m ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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=m ++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set ++ ++# ++# Miscellaneous USB options ++# ++# CONFIG_USB_DEFAULT_PERSIST is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_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 is not set ++# 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 ++# ++# CONFIG_USB_STORAGE is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB is not set ++# CONFIG_USB_ISP1301 is not set ++# CONFIG_USB_ULPI is not set ++CONFIG_USB_GADGET=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_AUTO_SWITCH is not set ++# CONFIG_HIUSB_DEVICE3_0 is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_ACM=m ++CONFIG_USB_U_SERIAL=m ++CONFIG_USB_U_ETHER=m ++CONFIG_USB_F_RNDIS=m ++CONFIG_USB_F_MASS_STORAGE=m ++CONFIG_USB_F_UAC1=m ++CONFIG_USB_F_UVC=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++CONFIG_USB_AUDIO=m ++CONFIG_GADGET_UAC1=y ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++CONFIG_USB_G_MULTI=m ++CONFIG_USB_G_MULTI_RNDIS=y ++# CONFIG_USB_G_MULTI_CDC is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM is not set ++CONFIG_USB_G_WEBCAM_AUDIO=m ++# CONFIG_UWB is not set ++CONFIG_MMC=m ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=m ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# 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_HIMCIV200=m ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=m ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++# CONFIG_HI_DMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE 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_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS is not set ++# CONFIG_JFFS2_FS is not set ++CONFIG_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_RNG=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_PCOMP2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++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=y ++# CONFIG_CRYPTO_GCM is not set ++CONFIG_CRYPTO_SEQIV=y ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=y ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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=y ++# CONFIG_CRYPTO_ZLIB is not set ++CONFIG_CRYPTO_LZO=y ++# 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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=y ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=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_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++CONFIG_AVERAGE=y ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3556_single_spinand_mini_defconfig b/arch/arm/configs/hi3556_single_spinand_mini_defconfig +new file mode 100644 +index 0000000..6cf319c +--- /dev/null ++++ b/arch/arm/configs/hi3556_single_spinand_mini_defconfig +@@ -0,0 +1,2398 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=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_GENERIC_BUG=y ++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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_HW_DECOMPRESS=y ++# CONFIG_SOFT_DECOMPRESS is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++CONFIG_NO_HZ=y ++# 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_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++# CONFIG_RCU_STALL_COMMON is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++# CONFIG_NAMESPACES is not set ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++# CONFIG_BLK_DEV_INITRD is not set ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++CONFIG_EXPERT=y ++# CONFIG_UID16 is not set ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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 is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++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_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++# CONFIG_ARCH_HI3519V101 is not set ++# CONFIG_ARCH_HI3516AV200 is not set ++# CONFIG_ARCH_HI3559 is not set ++CONFIG_ARCH_HI3556=y ++# CONFIG_ARCH_HI3536C is not set ++# CONFIG_ARCH_HI3531D is not set ++# CONFIG_ARCH_HI3521D is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++# CONFIG_SMP is not set ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++# CONFIG_ARM_PSCI is not set ++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 is not set ++# 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=y ++CONFIG_HZ=1000 ++# CONFIG_SCHED_HRTICK is not set ++# CONFIG_THUMB2_KERNEL 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=y ++# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_NEED_PER_CPU_KM=y ++# CONFIG_CLEANCACHE is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++CONFIG_CMA_AREAS=7 ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_AUTO_ZRELADDR is not set ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_INTERACTIVE=y ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++# CONFIG_CPUFREQ_DT is not set ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_WAKELOCK is not set ++# CONFIG_HISI_SNAPSHOT_BOOT is not set ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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 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_GENEVE 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 is not set ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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 is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES 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_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_IEEE802154 is not set ++# CONFIG_NET_SCHED is not set ++# CONFIG_DCB is not set ++# CONFIG_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=16 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++CONFIG_ARM_CCI=y ++# 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_HIFMC=y ++CONFIG_HIFMC_SPI_NAND=y ++# CONFIG_HIFMC_NAND 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_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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_MTD_NAND_HINFC610 is not set ++# CONFIG_HIFMC100_NAND is not set ++CONFIG_HIFMC100_SPI_NAND=y ++CONFIG_SPI_NAND_MAX_CHIP_NUM=1 ++# CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE 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 is not set ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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_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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++# CONFIG_ETHERNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_MMIOREG is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++# CONFIG_MDIO_HISI_GEMAC is not set ++# CONFIG_MICREL_KS8995MA is not set ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++ ++# ++# Host-side USB support is needed for USB Network Adapter support ++# ++CONFIG_USB_NET_DRIVERS=m ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++CONFIG_WLAN=y ++# CONFIG_WIFI_CONTROL_FUNC is not set ++# CONFIG_HOSTAP is not set ++# CONFIG_WL_TI is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO 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 ++ ++# ++# 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_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART 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_ST_ASC is not set ++# CONFIG_TTY_PRINTK is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_HW_RANDOM=y ++# CONFIG_HW_RANDOM_TIMERIOMEM is not set ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++# CONFIG_DCC_TTY 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=m ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_MUX_PCA9541 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_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_HIBVT is not set ++CONFIG_I2C_HISI_V110=y ++# CONFIG_I2C_NOMADIK 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_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_ARCH_WANT_OPTIONAL_GPIOLIB=y ++# CONFIG_GPIOLIB is not set ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# CONFIG_MFD_AS3711 is not set ++# CONFIG_MFD_AS3722 is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_BCM590XX is not set ++# CONFIG_MFD_AXP20X is not set ++# CONFIG_MFD_CROS_EC 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS6507X is not set ++# CONFIG_MFD_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=m ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=m ++CONFIG_VIDEO_V4L2=m ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=m ++CONFIG_VIDEOBUF2_MEMOPS=m ++CONFIG_VIDEOBUF2_VMALLOC=m ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++# CONFIG_MEDIA_USB_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# Audio decoders, processors and mixers ++# ++ ++# ++# RDS decoders ++# ++ ++# ++# Video decoders ++# ++ ++# ++# Video and audio decoders ++# ++ ++# ++# Video encoders ++# ++ ++# ++# Camera sensor devices ++# ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++ ++# ++# Audio/Video compression chips ++# ++ ++# ++# Miscellaneous helper chips ++# ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=m ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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=m ++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set ++ ++# ++# Miscellaneous USB options ++# ++# CONFIG_USB_DEFAULT_PERSIST is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_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 is not set ++# 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 ++# ++# CONFIG_USB_STORAGE is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB is not set ++# CONFIG_USB_ISP1301 is not set ++# CONFIG_USB_ULPI is not set ++CONFIG_USB_GADGET=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_AUTO_SWITCH is not set ++# CONFIG_HIUSB_DEVICE3_0 is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_ACM=m ++CONFIG_USB_U_SERIAL=m ++CONFIG_USB_U_ETHER=m ++CONFIG_USB_F_RNDIS=m ++CONFIG_USB_F_MASS_STORAGE=m ++CONFIG_USB_F_UAC1=m ++CONFIG_USB_F_UVC=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++CONFIG_USB_AUDIO=m ++CONFIG_GADGET_UAC1=y ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++CONFIG_USB_G_MULTI=m ++CONFIG_USB_G_MULTI_RNDIS=y ++# CONFIG_USB_G_MULTI_CDC is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM is not set ++CONFIG_USB_G_WEBCAM_AUDIO=m ++# CONFIG_UWB is not set ++CONFIG_MMC=m ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=m ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# 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_HIMCIV200=m ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=m ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++# CONFIG_HI_DMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE 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_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS is not set ++# CONFIG_JFFS2_FS is not set ++CONFIG_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_RNG=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_PCOMP2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++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=y ++# CONFIG_CRYPTO_GCM is not set ++CONFIG_CRYPTO_SEQIV=y ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=y ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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=y ++# CONFIG_CRYPTO_ZLIB is not set ++CONFIG_CRYPTO_LZO=y ++# 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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=y ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=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_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++CONFIG_AVERAGE=y ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3556_single_spinor_mini_defconfig b/arch/arm/configs/hi3556_single_spinor_mini_defconfig +new file mode 100644 +index 0000000..31cd1bb +--- /dev/null ++++ b/arch/arm/configs/hi3556_single_spinor_mini_defconfig +@@ -0,0 +1,2399 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=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_GENERIC_BUG=y ++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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_HW_DECOMPRESS=y ++# CONFIG_SOFT_DECOMPRESS is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++CONFIG_NO_HZ=y ++# 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_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++# CONFIG_RCU_STALL_COMMON is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++# CONFIG_NAMESPACES is not set ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++# CONFIG_BLK_DEV_INITRD is not set ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++CONFIG_EXPERT=y ++# CONFIG_UID16 is not set ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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 is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++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_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++# CONFIG_ARCH_HI3519V101 is not set ++# CONFIG_ARCH_HI3516AV200 is not set ++# CONFIG_ARCH_HI3559 is not set ++CONFIG_ARCH_HI3556=y ++# CONFIG_ARCH_HI3536C is not set ++# CONFIG_ARCH_HI3531D is not set ++# CONFIG_ARCH_HI3521D is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++# CONFIG_SMP is not set ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++# CONFIG_ARM_PSCI is not set ++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 is not set ++# 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=y ++CONFIG_HZ=1000 ++# CONFIG_SCHED_HRTICK is not set ++# CONFIG_THUMB2_KERNEL 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=y ++# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_NEED_PER_CPU_KM=y ++# CONFIG_CLEANCACHE is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++CONFIG_CMA_AREAS=7 ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_AUTO_ZRELADDR is not set ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_INTERACTIVE=y ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++# CONFIG_CPUFREQ_DT is not set ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_WAKELOCK is not set ++# CONFIG_HISI_SNAPSHOT_BOOT is not set ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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 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_GENEVE 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 is not set ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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 is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES 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_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_IEEE802154 is not set ++# CONFIG_NET_SCHED is not set ++# CONFIG_DCB is not set ++# CONFIG_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=16 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++CONFIG_ARM_CCI=y ++# 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_HIFMC 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 is not set ++# 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_IDS 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_SPI_NOR_USE_4K_SECTORS is not set ++CONFIG_SPI_HISI_SFC=y ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++CONFIG_MTD_UBI_FASTMAP=y ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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_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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++# CONFIG_ETHERNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_MMIOREG is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++# CONFIG_MDIO_HISI_GEMAC is not set ++# CONFIG_MICREL_KS8995MA is not set ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++ ++# ++# Host-side USB support is needed for USB Network Adapter support ++# ++CONFIG_USB_NET_DRIVERS=m ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++CONFIG_WLAN=y ++# CONFIG_WIFI_CONTROL_FUNC is not set ++# CONFIG_HOSTAP is not set ++# CONFIG_WL_TI is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO 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 ++ ++# ++# 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_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART 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_ST_ASC is not set ++# CONFIG_TTY_PRINTK is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_HW_RANDOM=y ++# CONFIG_HW_RANDOM_TIMERIOMEM is not set ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++# CONFIG_DCC_TTY 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=m ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_MUX_PCA9541 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_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_HIBVT is not set ++CONFIG_I2C_HISI_V110=y ++# CONFIG_I2C_NOMADIK 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_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_ARCH_WANT_OPTIONAL_GPIOLIB=y ++# CONFIG_GPIOLIB is not set ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# CONFIG_MFD_AS3711 is not set ++# CONFIG_MFD_AS3722 is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_BCM590XX is not set ++# CONFIG_MFD_AXP20X is not set ++# CONFIG_MFD_CROS_EC 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS6507X is not set ++# CONFIG_MFD_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=m ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=m ++CONFIG_VIDEO_V4L2=m ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=m ++CONFIG_VIDEOBUF2_MEMOPS=m ++CONFIG_VIDEOBUF2_VMALLOC=m ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++# CONFIG_MEDIA_USB_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# Audio decoders, processors and mixers ++# ++ ++# ++# RDS decoders ++# ++ ++# ++# Video decoders ++# ++ ++# ++# Video and audio decoders ++# ++ ++# ++# Video encoders ++# ++ ++# ++# Camera sensor devices ++# ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++ ++# ++# Audio/Video compression chips ++# ++ ++# ++# Miscellaneous helper chips ++# ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++# CONFIG_HID_A4TECH is not set ++# CONFIG_HID_ACRUX is not set ++# CONFIG_HID_APPLE is not set ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++# CONFIG_HID_BELKIN is not set ++# CONFIG_HID_CHERRY is not set ++# CONFIG_HID_CHICONY is not set ++# CONFIG_HID_CYPRESS is not set ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++# CONFIG_HID_EZKEY is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++# CONFIG_HID_KENSINGTON is not set ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++# CONFIG_HID_LOGITECH is not set ++# CONFIG_HID_MAGICMOUSE is not set ++# CONFIG_HID_MICROSOFT is not set ++# CONFIG_HID_MONTEREY is not set ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=m ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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=m ++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set ++ ++# ++# Miscellaneous USB options ++# ++# CONFIG_USB_DEFAULT_PERSIST is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_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 is not set ++# 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 ++# ++# CONFIG_USB_STORAGE is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB is not set ++# CONFIG_USB_ISP1301 is not set ++# CONFIG_USB_ULPI is not set ++CONFIG_USB_GADGET=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_AUTO_SWITCH is not set ++# CONFIG_HIUSB_DEVICE3_0 is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_ACM=m ++CONFIG_USB_U_SERIAL=m ++CONFIG_USB_U_ETHER=m ++CONFIG_USB_F_RNDIS=m ++CONFIG_USB_F_MASS_STORAGE=m ++CONFIG_USB_F_UAC1=m ++CONFIG_USB_F_UVC=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++CONFIG_USB_AUDIO=m ++CONFIG_GADGET_UAC1=y ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++CONFIG_USB_G_MULTI=m ++CONFIG_USB_G_MULTI_RNDIS=y ++# CONFIG_USB_G_MULTI_CDC is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM is not set ++CONFIG_USB_G_WEBCAM_AUDIO=m ++# CONFIG_UWB is not set ++CONFIG_MMC=m ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=m ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# 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_HIMCIV200=m ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=m ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++# CONFIG_HI_DMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE 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_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_LOGFS is not set ++# CONFIG_CRAMFS is not set ++CONFIG_SQUASHFS=y ++CONFIG_SQUASHFS_FILE_CACHE=y ++# CONFIG_SQUASHFS_FILE_DIRECT is not set ++CONFIG_SQUASHFS_DECOMP_SINGLE=y ++# CONFIG_SQUASHFS_DECOMP_MULTI is not set ++# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set ++# CONFIG_SQUASHFS_XATTR is not set ++CONFIG_SQUASHFS_ZLIB=y ++CONFIG_SQUASHFS_LZO=y ++# CONFIG_SQUASHFS_XZ is not set ++# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set ++# CONFIG_SQUASHFS_EMBEDDED is not set ++CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_RNG=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_PCOMP2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++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=y ++# CONFIG_CRYPTO_GCM is not set ++CONFIG_CRYPTO_SEQIV=y ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=y ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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=y ++# CONFIG_CRYPTO_ZLIB is not set ++CONFIG_CRYPTO_LZO=y ++# 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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=y ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=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_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++CONFIG_AVERAGE=y ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3559_single_defconfig b/arch/arm/configs/hi3559_single_defconfig +new file mode 100644 +index 0000000..0b5f028 +--- /dev/null ++++ b/arch/arm/configs/hi3559_single_defconfig +@@ -0,0 +1,2617 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=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_GENERIC_BUG=y ++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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++# CONFIG_HW_DECOMPRESS is not set ++CONFIG_SOFT_DECOMPRESS=y ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++CONFIG_NO_HZ=y ++# 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_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++# CONFIG_RCU_STALL_COMMON is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++# CONFIG_ARCH_HI3519V101 is not set ++# CONFIG_ARCH_HI3516AV200 is not set ++CONFIG_ARCH_HI3559=y ++# CONFIG_ARCH_HI3556 is not set ++# CONFIG_ARCH_HI3536C is not set ++# CONFIG_ARCH_HI3531D is not set ++# CONFIG_ARCH_HI3521D is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++# CONFIG_SMP is not set ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++# CONFIG_ARM_PSCI is not set ++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 is not set ++# 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=y ++CONFIG_HZ=1000 ++# CONFIG_SCHED_HRTICK is not set ++# CONFIG_THUMB2_KERNEL 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=y ++# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_NEED_PER_CPU_KM=y ++# CONFIG_CLEANCACHE is not set ++# CONFIG_FRONTSWAP is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++CONFIG_CMA_AREAS=7 ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_AUTO_ZRELADDR is not set ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_INTERACTIVE=y ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++# CONFIG_CPUFREQ_DT is not set ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HISI_SNAPSHOT_BOOT=y ++# CONFIG_DEFAULT_MTD is not set ++CONFIG_DEFAULT_DDR=y ++CONFIG_SNAPSHOT_BUF_START=0x8a000000 ++CONFIG_SNAPSHOT_BUF_SIZE=0x4000000 ++CONFIG_HIBERNATION=y ++CONFIG_GZIP_COMPRESS=y ++CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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=m ++# 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_GENEVE 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=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=16 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++CONFIG_ARM_CCI=y ++# 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_SWAP is not set ++CONFIG_HIFMC=y ++CONFIG_HIFMC_SPI_NAND=y ++# CONFIG_HIFMC_NAND 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 is not set ++# 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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_MTD_NAND_HINFC610 is not set ++# CONFIG_HIFMC100_NAND is not set ++CONFIG_HIFMC100_SPI_NAND=y ++CONFIG_SPI_NAND_MAX_CHIP_NUM=1 ++# CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE 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_SPI_NOR_USE_4K_SECTORS is not set ++CONFIG_SPI_HISI_SFC=y ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++# CONFIG_ETHERNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY 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_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++# CONFIG_MDIO_HISI_GEMAC 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++CONFIG_WLAN=y ++# CONFIG_WIFI_CONTROL_FUNC is not set ++# CONFIG_HOSTAP is not set ++# CONFIG_WL_TI is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_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_ST_ASC is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_HW_RANDOM=y ++# CONFIG_HW_RANDOM_TIMERIOMEM is not set ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++# CONFIG_DCC_TTY 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=m ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set ++# CONFIG_I2C_MUX_GPIO is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PCA954x 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_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_HIBVT is not set ++CONFIG_I2C_HISI_V110=y ++# CONFIG_I2C_NOMADIK 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_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_OC_TINY is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_ARCH_WANT_OPTIONAL_GPIOLIB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_DEVRES=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_GENERIC_PLATFORM is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_EM is not set ++# CONFIG_GPIO_ZEVIO is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_SCH311X is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_GRGPIO is not set ++ ++# ++# I2C GPIO expanders: ++# ++# 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_ADP5588 is not set ++# CONFIG_GPIO_ADNP is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_GPIO_MC33880 is not set ++# CONFIG_GPIO_74X164 is not set ++ ++# ++# AC97 GPIO expanders: ++# ++ ++# ++# LPC GPIO expanders: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++ ++# ++# USB GPIO expanders: ++# ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_BCM590XX is not set ++# CONFIG_MFD_AXP20X 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_EGPIO 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X is not set ++# CONFIG_MFD_TPS65910 is not set ++# CONFIG_MFD_TPS65912 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=m ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=m ++CONFIG_VIDEO_V4L2=m ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=m ++CONFIG_VIDEOBUF2_MEMOPS=m ++CONFIG_VIDEOBUF2_VMALLOC=m ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++# CONFIG_MEDIA_USB_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# Audio decoders, processors and mixers ++# ++ ++# ++# RDS decoders ++# ++ ++# ++# Video decoders ++# ++ ++# ++# Video and audio decoders ++# ++ ++# ++# Video encoders ++# ++ ++# ++# Camera sensor devices ++# ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++ ++# ++# Audio/Video compression chips ++# ++ ++# ++# Miscellaneous helper chips ++# ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++# CONFIG_USB_DEFAULT_PERSIST is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_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 is not set ++# 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 ++# ++# CONFIG_USB_STORAGE is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_OTG_WAKELOCK is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_AUTO_SWITCH is not set ++# CONFIG_HIUSB_DEVICE3_0 is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_ACM=m ++CONFIG_USB_U_SERIAL=m ++CONFIG_USB_U_ETHER=m ++CONFIG_USB_F_RNDIS=m ++CONFIG_USB_F_MASS_STORAGE=m ++CONFIG_USB_F_UAC1=m ++CONFIG_USB_F_UVC=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++CONFIG_USB_AUDIO=m ++CONFIG_GADGET_UAC1=y ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++CONFIG_USB_G_MULTI=m ++CONFIG_USB_G_MULTI_RNDIS=y ++# CONFIG_USB_G_MULTI_CDC is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM is not set ++CONFIG_USB_G_WEBCAM_AUDIO=m ++# CONFIG_UWB is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# 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_HIMCIV200=y ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++# CONFIG_HI_DMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE 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=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_LOGFS is not set ++CONFIG_CRAMFS=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_RNG=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_PCOMP2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++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=y ++# CONFIG_CRYPTO_GCM is not set ++CONFIG_CRYPTO_SEQIV=y ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=y ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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=y ++# CONFIG_CRYPTO_ZLIB is not set ++CONFIG_CRYPTO_LZO=y ++# 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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=y ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++CONFIG_AVERAGE=y ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3559_single_nand_defconfig b/arch/arm/configs/hi3559_single_nand_defconfig +new file mode 100644 +index 0000000..02fae8f +--- /dev/null ++++ b/arch/arm/configs/hi3559_single_nand_defconfig +@@ -0,0 +1,2615 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=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_GENERIC_BUG=y ++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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++# CONFIG_HW_DECOMPRESS is not set ++CONFIG_SOFT_DECOMPRESS=y ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++CONFIG_NO_HZ=y ++# 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_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++# CONFIG_RCU_STALL_COMMON is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++CONFIG_RD_BZIP2=y ++CONFIG_RD_LZMA=y ++CONFIG_RD_XZ=y ++CONFIG_RD_LZO=y ++CONFIG_RD_LZ4=y ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++# CONFIG_EXPERT is not set ++CONFIG_UID16=y ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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=y ++CONFIG_SLUB_DEBUG=y ++# CONFIG_COMPAT_BRK is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=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_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++# CONFIG_ARCH_HI3519V101 is not set ++# CONFIG_ARCH_HI3516AV200 is not set ++CONFIG_ARCH_HI3559=y ++# CONFIG_ARCH_HI3556 is not set ++# CONFIG_ARCH_HI3536C is not set ++# CONFIG_ARCH_HI3531D is not set ++# CONFIG_ARCH_HI3521D is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++# CONFIG_SMP is not set ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++# CONFIG_ARM_PSCI is not set ++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 is not set ++# 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=y ++CONFIG_HZ=1000 ++# CONFIG_SCHED_HRTICK is not set ++# CONFIG_THUMB2_KERNEL 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=y ++# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_NEED_PER_CPU_KM=y ++# CONFIG_CLEANCACHE is not set ++# CONFIG_FRONTSWAP is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++CONFIG_CMA_AREAS=7 ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_AUTO_ZRELADDR is not set ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_INTERACTIVE=y ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++# CONFIG_CPUFREQ_DT is not set ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_WAKELOCK=y ++CONFIG_HIBERNATE_CALLBACKS=y ++CONFIG_HISI_SNAPSHOT_BOOT=y ++# CONFIG_DEFAULT_MTD is not set ++CONFIG_DEFAULT_DDR=y ++CONFIG_SNAPSHOT_BUF_START=0x8a000000 ++CONFIG_SNAPSHOT_BUF_SIZE=0x4000000 ++CONFIG_HIBERNATION=y ++CONFIG_GZIP_COMPRESS=y ++CONFIG_PM_STD_PARTITION="" ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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=m ++# 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_GENEVE 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=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++# CONFIG_IPV6_VTI is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_GRE is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_NF_REJECT_IPV6 is not set ++# CONFIG_NF_LOG_IPV6 is not set ++# CONFIG_IP6_NF_IPTABLES 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_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_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=16 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++CONFIG_ARM_CCI=y ++# 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_SWAP is not set ++CONFIG_HIFMC=y ++# CONFIG_HIFMC_SPI_NAND is not set ++CONFIG_HIFMC_NAND=y ++ ++# ++# 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_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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_GPIO is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_MTD_NAND_HINFC610 is not set ++CONFIG_HIFMC100_NAND=y ++CONFIG_HIFMC100_MAX_NAND_CHIP=1 ++# CONFIG_HIFMC100_NAND_EDO_MODE is not set ++CONFIG_RW_H_WIDTH=10 ++CONFIG_R_L_WIDTH=10 ++CONFIG_W_L_WIDTH=10 ++# CONFIG_HIFMC100_NAND_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_NAND_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_NAND_PAGESIZE_AUTO_ECC_NONE 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 is not set ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++# CONFIG_ETHERNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY 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_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++# CONFIG_MDIO_HISI_GEMAC 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++CONFIG_WLAN=y ++# CONFIG_WIFI_CONTROL_FUNC is not set ++# CONFIG_HOSTAP is not set ++# CONFIG_WL_TI is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_TCA8418 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_LM8333 is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_SAMSUNG is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_OMAP4 is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_CAP1106 is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_CYPRESS=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_SENTELIC is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_CYAPA is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_MOUSE_SYNAPTICS_I2C is not set ++# CONFIG_MOUSE_SYNAPTICS_USB 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 ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_SERIO_ARC_PS2 is not set ++# CONFIG_SERIO_APBPS2 is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTY=y ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_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_ST_ASC is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_HW_RANDOM=y ++# CONFIG_HW_RANDOM_TIMERIOMEM is not set ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++# CONFIG_DCC_TTY 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=m ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set ++# CONFIG_I2C_MUX_GPIO is not set ++# CONFIG_I2C_MUX_PCA9541 is not set ++# CONFIG_I2C_MUX_PCA954x 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_CBUS_GPIO is not set ++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_HIBVT is not set ++CONFIG_I2C_HISI_V110=y ++# CONFIG_I2C_NOMADIK 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_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_FSL_SPI is not set ++# CONFIG_SPI_OC_TINY is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_ARCH_WANT_OPTIONAL_GPIOLIB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_DEVRES=y ++CONFIG_OF_GPIO=y ++CONFIG_GPIOLIB_IRQCHIP=y ++# CONFIG_DEBUG_GPIO is not set ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_GENERIC_PLATFORM is not set ++# CONFIG_GPIO_DWAPB is not set ++# CONFIG_GPIO_EM is not set ++# CONFIG_GPIO_ZEVIO is not set ++CONFIG_GPIO_PL061=y ++# CONFIG_GPIO_SCH311X is not set ++# CONFIG_GPIO_SYSCON is not set ++# CONFIG_GPIO_GRGPIO is not set ++ ++# ++# I2C GPIO expanders: ++# ++# 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_ADP5588 is not set ++# CONFIG_GPIO_ADNP is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_GPIO_MC33880 is not set ++# CONFIG_GPIO_74X164 is not set ++ ++# ++# AC97 GPIO expanders: ++# ++ ++# ++# LPC GPIO expanders: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++ ++# ++# USB GPIO expanders: ++# ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_GPIO is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_BQ24190 is not set ++# CONFIG_CHARGER_BQ24735 is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++# CONFIG_POWER_RESET_GPIO is not set ++# CONFIG_POWER_RESET_GPIO_RESTART is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_LTC2952 is not set ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# 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_BCM590XX is not set ++# CONFIG_MFD_AXP20X 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_EGPIO 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X is not set ++# CONFIG_MFD_TPS65910 is not set ++# CONFIG_MFD_TPS65912 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_GPIO is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=m ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=m ++CONFIG_VIDEO_V4L2=m ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=m ++CONFIG_VIDEOBUF2_MEMOPS=m ++CONFIG_VIDEOBUF2_VMALLOC=m ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++# CONFIG_MEDIA_USB_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# Audio decoders, processors and mixers ++# ++ ++# ++# RDS decoders ++# ++ ++# ++# Video decoders ++# ++ ++# ++# Video and audio decoders ++# ++ ++# ++# Video encoders ++# ++ ++# ++# Camera sensor devices ++# ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++ ++# ++# Audio/Video compression chips ++# ++ ++# ++# Miscellaneous helper chips ++# ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_FB_SSD1307 is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++# CONFIG_HID_CP2112 is not set ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=y ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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 is not set ++ ++# ++# Miscellaneous USB options ++# ++# CONFIG_USB_DEFAULT_PERSIST is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_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 is not set ++# 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 ++# ++# CONFIG_USB_STORAGE is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_USB_OTG_WAKELOCK is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB 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=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_AUTO_SWITCH is not set ++# CONFIG_HIUSB_DEVICE3_0 is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++# CONFIG_USB_DUMMY_HCD is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_ACM=m ++CONFIG_USB_U_SERIAL=m ++CONFIG_USB_U_ETHER=m ++CONFIG_USB_F_RNDIS=m ++CONFIG_USB_F_MASS_STORAGE=m ++CONFIG_USB_F_UAC1=m ++CONFIG_USB_F_UVC=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++CONFIG_USB_AUDIO=m ++CONFIG_GADGET_UAC1=y ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++CONFIG_USB_G_MULTI=m ++CONFIG_USB_G_MULTI_RNDIS=y ++# CONFIG_USB_G_MULTI_CDC is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM is not set ++CONFIG_USB_G_WEBCAM_AUDIO=m ++# CONFIG_UWB is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# 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_HIMCIV200=y ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=y ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++# CONFIG_HI_DMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE 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=y ++CONFIG_EXT4_USE_FOR_EXT23=y ++# CONFIG_EXT4_FS_POSIX_ACL is not set ++# CONFIG_EXT4_FS_SECURITY is not set ++# CONFIG_EXT4_DEBUG is not set ++CONFIG_JBD2=y ++# CONFIG_JBD2_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set ++# CONFIG_YAFFS_DISABLE_BACKGROUND is not set ++# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set ++CONFIG_YAFFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_LOGFS is not set ++CONFIG_CRAMFS=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_RNG=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_PCOMP2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++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=y ++# CONFIG_CRYPTO_GCM is not set ++CONFIG_CRYPTO_SEQIV=y ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=y ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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=y ++# CONFIG_CRYPTO_ZLIB is not set ++CONFIG_CRYPTO_LZO=y ++# 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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=y ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_LZ4_DECOMPRESS=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_GZIP=y ++CONFIG_DECOMPRESS_BZIP2=y ++CONFIG_DECOMPRESS_LZMA=y ++CONFIG_DECOMPRESS_XZ=y ++CONFIG_DECOMPRESS_LZO=y ++CONFIG_DECOMPRESS_LZ4=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++CONFIG_AVERAGE=y ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3559_single_nand_mini_defconfig b/arch/arm/configs/hi3559_single_nand_mini_defconfig +new file mode 100644 +index 0000000..d1101a1 +--- /dev/null ++++ b/arch/arm/configs/hi3559_single_nand_mini_defconfig +@@ -0,0 +1,2396 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=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_GENERIC_BUG=y ++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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_HW_DECOMPRESS=y ++# CONFIG_SOFT_DECOMPRESS is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++CONFIG_NO_HZ=y ++# 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_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++# CONFIG_RCU_STALL_COMMON is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++# CONFIG_NAMESPACES is not set ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++# CONFIG_BLK_DEV_INITRD is not set ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++CONFIG_EXPERT=y ++# CONFIG_UID16 is not set ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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 is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++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_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++# CONFIG_ARCH_HI3519V101 is not set ++# CONFIG_ARCH_HI3516AV200 is not set ++CONFIG_ARCH_HI3559=y ++# CONFIG_ARCH_HI3556 is not set ++# CONFIG_ARCH_HI3536C is not set ++# CONFIG_ARCH_HI3531D is not set ++# CONFIG_ARCH_HI3521D is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++# CONFIG_SMP is not set ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++# CONFIG_ARM_PSCI is not set ++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 is not set ++# 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=y ++CONFIG_HZ=1000 ++# CONFIG_SCHED_HRTICK is not set ++# CONFIG_THUMB2_KERNEL 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=y ++# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_NEED_PER_CPU_KM=y ++# CONFIG_CLEANCACHE is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++CONFIG_CMA_AREAS=7 ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_AUTO_ZRELADDR is not set ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_INTERACTIVE=y ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++# CONFIG_CPUFREQ_DT is not set ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_WAKELOCK is not set ++# CONFIG_HISI_SNAPSHOT_BOOT is not set ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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 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_GENEVE 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 is not set ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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 is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES 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_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_IEEE802154 is not set ++# CONFIG_NET_SCHED is not set ++# CONFIG_DCB is not set ++# CONFIG_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=16 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++CONFIG_ARM_CCI=y ++# 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_HIFMC=y ++# CONFIG_HIFMC_SPI_NAND is not set ++CONFIG_HIFMC_NAND=y ++ ++# ++# 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_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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_MTD_NAND_HINFC610 is not set ++CONFIG_HIFMC100_NAND=y ++CONFIG_HIFMC100_MAX_NAND_CHIP=1 ++CONFIG_HIFMC100_NAND_EDO_MODE=y ++CONFIG_RW_H_WIDTH=3 ++CONFIG_R_L_WIDTH=2 ++CONFIG_W_L_WIDTH=2 ++# CONFIG_HIFMC100_NAND_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_NAND_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_NAND_PAGESIZE_AUTO_ECC_NONE 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 is not set ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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_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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++# CONFIG_ETHERNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_MMIOREG is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++# CONFIG_MDIO_HISI_GEMAC is not set ++# CONFIG_MICREL_KS8995MA is not set ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++ ++# ++# Host-side USB support is needed for USB Network Adapter support ++# ++CONFIG_USB_NET_DRIVERS=m ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++CONFIG_WLAN=y ++# CONFIG_WIFI_CONTROL_FUNC is not set ++# CONFIG_HOSTAP is not set ++# CONFIG_WL_TI is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO 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 ++ ++# ++# 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_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART 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_ST_ASC is not set ++# CONFIG_TTY_PRINTK is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_HW_RANDOM=y ++# CONFIG_HW_RANDOM_TIMERIOMEM is not set ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++# CONFIG_DCC_TTY 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=m ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_MUX_PCA9541 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_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_HIBVT is not set ++CONFIG_I2C_HISI_V110=y ++# CONFIG_I2C_NOMADIK 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_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_ARCH_WANT_OPTIONAL_GPIOLIB=y ++# CONFIG_GPIOLIB is not set ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# CONFIG_MFD_AS3711 is not set ++# CONFIG_MFD_AS3722 is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_BCM590XX is not set ++# CONFIG_MFD_AXP20X is not set ++# CONFIG_MFD_CROS_EC 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS6507X is not set ++# CONFIG_MFD_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=m ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=m ++CONFIG_VIDEO_V4L2=m ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=m ++CONFIG_VIDEOBUF2_MEMOPS=m ++CONFIG_VIDEOBUF2_VMALLOC=m ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++# CONFIG_MEDIA_USB_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# Audio decoders, processors and mixers ++# ++ ++# ++# RDS decoders ++# ++ ++# ++# Video decoders ++# ++ ++# ++# Video and audio decoders ++# ++ ++# ++# Video encoders ++# ++ ++# ++# Camera sensor devices ++# ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++ ++# ++# Audio/Video compression chips ++# ++ ++# ++# Miscellaneous helper chips ++# ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++# CONFIG_HID_A4TECH is not set ++# CONFIG_HID_ACRUX is not set ++# CONFIG_HID_APPLE is not set ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++# CONFIG_HID_BELKIN is not set ++# CONFIG_HID_CHERRY is not set ++# CONFIG_HID_CHICONY is not set ++# CONFIG_HID_CYPRESS is not set ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++# CONFIG_HID_EZKEY is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++# CONFIG_HID_KENSINGTON is not set ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++# CONFIG_HID_LOGITECH is not set ++# CONFIG_HID_MAGICMOUSE is not set ++# CONFIG_HID_MICROSOFT is not set ++# CONFIG_HID_MONTEREY is not set ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=m ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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=m ++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set ++ ++# ++# Miscellaneous USB options ++# ++# CONFIG_USB_DEFAULT_PERSIST is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_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 is not set ++# 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 ++# ++# CONFIG_USB_STORAGE is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB is not set ++# CONFIG_USB_ISP1301 is not set ++# CONFIG_USB_ULPI is not set ++CONFIG_USB_GADGET=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_AUTO_SWITCH is not set ++# CONFIG_HIUSB_DEVICE3_0 is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_ACM=m ++CONFIG_USB_U_SERIAL=m ++CONFIG_USB_U_ETHER=m ++CONFIG_USB_F_RNDIS=m ++CONFIG_USB_F_MASS_STORAGE=m ++CONFIG_USB_F_UAC1=m ++CONFIG_USB_F_UVC=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++CONFIG_USB_AUDIO=m ++CONFIG_GADGET_UAC1=y ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++CONFIG_USB_G_MULTI=m ++CONFIG_USB_G_MULTI_RNDIS=y ++# CONFIG_USB_G_MULTI_CDC is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM is not set ++CONFIG_USB_G_WEBCAM_AUDIO=m ++# CONFIG_UWB is not set ++CONFIG_MMC=m ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=m ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# 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_HIMCIV200=m ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=m ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++# CONFIG_HI_DMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE 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_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS is not set ++# CONFIG_JFFS2_FS is not set ++CONFIG_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++# CONFIG_DEBUG_MEMORY_INIT is not set ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_RNG=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_PCOMP2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++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=y ++# CONFIG_CRYPTO_GCM is not set ++CONFIG_CRYPTO_SEQIV=y ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=y ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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=y ++# CONFIG_CRYPTO_ZLIB is not set ++CONFIG_CRYPTO_LZO=y ++# 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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=y ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=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_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++CONFIG_AVERAGE=y ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3559_single_spinand_mini_defconfig b/arch/arm/configs/hi3559_single_spinand_mini_defconfig +new file mode 100644 +index 0000000..36d3e93 +--- /dev/null ++++ b/arch/arm/configs/hi3559_single_spinand_mini_defconfig +@@ -0,0 +1,2398 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=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_GENERIC_BUG=y ++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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_HW_DECOMPRESS=y ++# CONFIG_SOFT_DECOMPRESS is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++CONFIG_NO_HZ=y ++# 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_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++# CONFIG_RCU_STALL_COMMON is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++# CONFIG_NAMESPACES is not set ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++# CONFIG_BLK_DEV_INITRD is not set ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++CONFIG_EXPERT=y ++# CONFIG_UID16 is not set ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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 is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++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_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++# CONFIG_ARCH_HI3519V101 is not set ++# CONFIG_ARCH_HI3516AV200 is not set ++CONFIG_ARCH_HI3559=y ++# CONFIG_ARCH_HI3556 is not set ++# CONFIG_ARCH_HI3536C is not set ++# CONFIG_ARCH_HI3531D is not set ++# CONFIG_ARCH_HI3521D is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++# CONFIG_SMP is not set ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++# CONFIG_ARM_PSCI is not set ++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 is not set ++# 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=y ++CONFIG_HZ=1000 ++# CONFIG_SCHED_HRTICK is not set ++# CONFIG_THUMB2_KERNEL 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=y ++# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_NEED_PER_CPU_KM=y ++# CONFIG_CLEANCACHE is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++CONFIG_CMA_AREAS=7 ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_AUTO_ZRELADDR is not set ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_INTERACTIVE=y ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++# CONFIG_CPUFREQ_DT is not set ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_WAKELOCK is not set ++# CONFIG_HISI_SNAPSHOT_BOOT is not set ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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 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_GENEVE 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 is not set ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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 is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES 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_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_IEEE802154 is not set ++# CONFIG_NET_SCHED is not set ++# CONFIG_DCB is not set ++# CONFIG_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=16 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++CONFIG_ARM_CCI=y ++# 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_HIFMC=y ++CONFIG_HIFMC_SPI_NAND=y ++# CONFIG_HIFMC_NAND 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_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_IDS=y ++CONFIG_MTD_NAND_ECC=y ++# CONFIG_MTD_NAND_ECC_SMC is not set ++CONFIG_MTD_NAND=y ++# CONFIG_MTD_NAND_ECC_BCH is not set ++# CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_NAND_DENALI is not set ++# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_DOCG4 is not set ++# CONFIG_MTD_NAND_NANDSIM is not set ++# CONFIG_MTD_NAND_PLATFORM is not set ++# CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 is not set ++# CONFIG_HISI_NAND_ECC_STATUS_REPORT is not set ++# CONFIG_MTD_NAND_HINFC610 is not set ++# CONFIG_HIFMC100_NAND is not set ++CONFIG_HIFMC100_SPI_NAND=y ++CONFIG_SPI_NAND_MAX_CHIP_NUM=1 ++# CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC is not set ++CONFIG_HIFMC100_AUTO_PAGESIZE_ECC=y ++# CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE 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 is not set ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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_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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++# CONFIG_ETHERNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_MMIOREG is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++# CONFIG_MDIO_HISI_GEMAC is not set ++# CONFIG_MICREL_KS8995MA is not set ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++ ++# ++# Host-side USB support is needed for USB Network Adapter support ++# ++CONFIG_USB_NET_DRIVERS=m ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++CONFIG_WLAN=y ++# CONFIG_WIFI_CONTROL_FUNC is not set ++# CONFIG_HOSTAP is not set ++# CONFIG_WL_TI is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO 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 ++ ++# ++# 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_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART 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_ST_ASC is not set ++# CONFIG_TTY_PRINTK is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_HW_RANDOM=y ++# CONFIG_HW_RANDOM_TIMERIOMEM is not set ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++# CONFIG_DCC_TTY 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=m ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_MUX_PCA9541 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_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_HIBVT is not set ++CONFIG_I2C_HISI_V110=y ++# CONFIG_I2C_NOMADIK 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_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_ARCH_WANT_OPTIONAL_GPIOLIB=y ++# CONFIG_GPIOLIB is not set ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# CONFIG_MFD_AS3711 is not set ++# CONFIG_MFD_AS3722 is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_BCM590XX is not set ++# CONFIG_MFD_AXP20X is not set ++# CONFIG_MFD_CROS_EC 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS6507X is not set ++# CONFIG_MFD_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=m ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=m ++CONFIG_VIDEO_V4L2=m ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=m ++CONFIG_VIDEOBUF2_MEMOPS=m ++CONFIG_VIDEOBUF2_VMALLOC=m ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++# CONFIG_MEDIA_USB_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# Audio decoders, processors and mixers ++# ++ ++# ++# RDS decoders ++# ++ ++# ++# Video decoders ++# ++ ++# ++# Video and audio decoders ++# ++ ++# ++# Video encoders ++# ++ ++# ++# Camera sensor devices ++# ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++ ++# ++# Audio/Video compression chips ++# ++ ++# ++# Miscellaneous helper chips ++# ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++CONFIG_HID_A4TECH=y ++# CONFIG_HID_ACRUX is not set ++CONFIG_HID_APPLE=y ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++CONFIG_HID_BELKIN=y ++CONFIG_HID_CHERRY=y ++CONFIG_HID_CHICONY=y ++CONFIG_HID_CYPRESS=y ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++CONFIG_HID_EZKEY=y ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++CONFIG_HID_KENSINGTON=y ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++CONFIG_HID_LOGITECH=y ++# CONFIG_HID_LOGITECH_HIDPP is not set ++# CONFIG_LOGITECH_FF is not set ++# CONFIG_LOGIRUMBLEPAD2_FF is not set ++# CONFIG_LOGIG940_FF is not set ++# CONFIG_LOGIWHEELS_FF is not set ++# CONFIG_HID_MAGICMOUSE is not set ++CONFIG_HID_MICROSOFT=y ++CONFIG_HID_MONTEREY=y ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=m ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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=m ++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set ++ ++# ++# Miscellaneous USB options ++# ++# CONFIG_USB_DEFAULT_PERSIST is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_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 is not set ++# 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 ++# ++# CONFIG_USB_STORAGE is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB is not set ++# CONFIG_USB_ISP1301 is not set ++# CONFIG_USB_ULPI is not set ++CONFIG_USB_GADGET=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_AUTO_SWITCH is not set ++# CONFIG_HIUSB_DEVICE3_0 is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_ACM=m ++CONFIG_USB_U_SERIAL=m ++CONFIG_USB_U_ETHER=m ++CONFIG_USB_F_RNDIS=m ++CONFIG_USB_F_MASS_STORAGE=m ++CONFIG_USB_F_UAC1=m ++CONFIG_USB_F_UVC=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++CONFIG_USB_AUDIO=m ++CONFIG_GADGET_UAC1=y ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++CONFIG_USB_G_MULTI=m ++CONFIG_USB_G_MULTI_RNDIS=y ++# CONFIG_USB_G_MULTI_CDC is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM is not set ++CONFIG_USB_G_WEBCAM_AUDIO=m ++# CONFIG_UWB is not set ++CONFIG_MMC=m ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=m ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# 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_HIMCIV200=m ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=m ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++# CONFIG_HI_DMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE 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_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS is not set ++# CONFIG_JFFS2_FS is not set ++CONFIG_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_RNG=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_PCOMP2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++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=y ++# CONFIG_CRYPTO_GCM is not set ++CONFIG_CRYPTO_SEQIV=y ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=y ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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=y ++# CONFIG_CRYPTO_ZLIB is not set ++CONFIG_CRYPTO_LZO=y ++# 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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=y ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=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_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++CONFIG_AVERAGE=y ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hi3559_single_spinor_mini_defconfig b/arch/arm/configs/hi3559_single_spinor_mini_defconfig +new file mode 100644 +index 0000000..5d582aeb7 +--- /dev/null ++++ b/arch/arm/configs/hi3559_single_spinor_mini_defconfig +@@ -0,0 +1,2399 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm 3.18.20 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_ARM_HAS_SG_CHAIN=y ++CONFIG_MIGHT_HAVE_PCI=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=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_GENERIC_BUG=y ++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_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++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=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_XZ is not set ++# CONFIG_KERNEL_LZO is not set ++# CONFIG_KERNEL_LZ4 is not set ++CONFIG_HW_DECOMPRESS=y ++# CONFIG_SOFT_DECOMPRESS is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++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_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++CONFIG_NO_HZ=y ++# 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_PREEMPT_RCU is not set ++# CONFIG_TASKS_RCU is not set ++# CONFIG_RCU_STALL_COMMON is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_BUILD_BIN2C is not set ++# CONFIG_IKCONFIG is not set ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_RESOURCE_COUNTERS is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++# CONFIG_RT_GROUP_SCHED is not set ++# CONFIG_BLK_CGROUP is not set ++# CONFIG_CHECKPOINT_RESTORE is not set ++# CONFIG_NAMESPACES is not set ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++# CONFIG_BLK_DEV_INITRD is not set ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_BPF=y ++CONFIG_EXPERT=y ++# CONFIG_UID16 is not set ++# CONFIG_SGETMASK_SYSCALL is not set ++CONFIG_SYSFS_SYSCALL=y ++# CONFIG_SYSCTL_SYSCALL is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++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_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 is not set ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++# CONFIG_JUMP_LABEL 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_ARCH_TRACEHOOK=y ++CONFIG_HAVE_DMA_ATTRS=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_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_CLONE_BACKWARDS=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_OLD_SIGACTION=y ++ ++# ++# GCOV-based kernel profiling ++# ++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_BLOCK=y ++CONFIG_LBDAF=y ++CONFIG_BLK_DEV_BSG=y ++# CONFIG_BLK_DEV_BSGLIB is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++CONFIG_BLK_CMDLINE_PARSER=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_AIX_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_CMDLINE_PARTITION=y ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_DEFAULT_DEADLINE=y ++# CONFIG_DEFAULT_CFQ is not set ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="deadline" ++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=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++CONFIG_ARCH_MULTIPLATFORM=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS711X 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_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_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP 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_MSM is not set ++# CONFIG_ARCH_SHMOBILE_LEGACY is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C24XX is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP1 is not set ++ ++# ++# Multiple platform selection ++# ++ ++# ++# CPU Core family selection ++# ++# CONFIG_ARCH_MULTI_V6 is not set ++CONFIG_ARCH_MULTI_V7=y ++CONFIG_ARCH_MULTI_V6_V7=y ++# CONFIG_ARCH_MULTI_CPU_AUTO is not set ++# CONFIG_ARCH_VIRT is not set ++# CONFIG_ARCH_MVEBU is not set ++# CONFIG_ARCH_BCM is not set ++# CONFIG_ARCH_BERLIN is not set ++# CONFIG_ARCH_HIGHBANK is not set ++CONFIG_ARCH_HISI=y ++ ++# ++# Hisilicon platform type ++# ++# CONFIG_ARCH_HI3xxx is not set ++# CONFIG_ARCH_HIP04 is not set ++# CONFIG_ARCH_HIX5HD2 is not set ++# CONFIG_ARCH_HI3519 is not set ++# CONFIG_ARCH_HI3519V101 is not set ++# CONFIG_ARCH_HI3516AV200 is not set ++CONFIG_ARCH_HI3559=y ++# CONFIG_ARCH_HI3556 is not set ++# CONFIG_ARCH_HI3536C is not set ++# CONFIG_ARCH_HI3531D is not set ++# CONFIG_ARCH_HI3521D is not set ++# CONFIG_ARCH_KEYSTONE is not set ++# CONFIG_ARCH_MESON is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MEDIATEK is not set ++ ++# ++# TI OMAP/AM/DM/DRA Family ++# ++# CONFIG_ARCH_OMAP3 is not set ++# CONFIG_ARCH_OMAP4 is not set ++# CONFIG_SOC_OMAP5 is not set ++# CONFIG_SOC_AM33XX is not set ++# CONFIG_SOC_AM43XX is not set ++# CONFIG_SOC_DRA7XX is not set ++# CONFIG_ARCH_QCOM is not set ++# CONFIG_ARCH_ROCKCHIP is not set ++# CONFIG_ARCH_SOCFPGA is not set ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_STI is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS is not set ++# CONFIG_ARCH_SHMOBILE_MULTI is not set ++# CONFIG_ARCH_SUNXI is not set ++# CONFIG_ARCH_SIRF is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_WM8850 is not set ++# CONFIG_ARCH_ZYNQ is not set ++CONFIG_ARM_TIMER_SP804=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V7=y ++CONFIG_CPU_32v6K=y ++CONFIG_CPU_32v7=y ++CONFIG_CPU_ABRT_EV7=y ++CONFIG_CPU_PABRT_V7=y ++CONFIG_CPU_CACHE_V7=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V7=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_LPAE is not set ++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set ++CONFIG_ARM_THUMB=y ++# CONFIG_ARM_THUMBEE is not set ++CONFIG_ARM_VIRT_EXT=y ++CONFIG_SWP_EMULATE=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_MIGHT_HAVE_CACHE_L2X0=y ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_ARM_L1_CACHE_SHIFT_6=y ++CONFIG_ARM_L1_CACHE_SHIFT=6 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_MULTI_IRQ_HANDLER=y ++# CONFIG_ARM_ERRATA_430973 is not set ++# CONFIG_ARM_ERRATA_720789 is not set ++# CONFIG_ARM_ERRATA_754322 is not set ++# CONFIG_ARM_ERRATA_775420 is not set ++# CONFIG_ARM_ERRATA_773022 is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI is not set ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_HAVE_SMP=y ++# CONFIG_SMP is not set ++CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++# CONFIG_ARM_PSCI is not set ++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 is not set ++# 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=y ++CONFIG_HZ=1000 ++# CONFIG_SCHED_HRTICK is not set ++# CONFIG_THUMB2_KERNEL 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=y ++# CONFIG_HIGHPTE is not set ++CONFIG_ARCH_WANT_GENERAL_HUGETLB=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_NO_BOOTMEM=y ++CONFIG_MEMORY_ISOLATION=y ++# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_COMPACTION=y ++CONFIG_MIGRATION=y ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_BOUNCE=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_NEED_PER_CPU_KM=y ++# CONFIG_CLEANCACHE is not set ++CONFIG_CMA=y ++# CONFIG_CMA_DEBUG is not set ++CONFIG_CMA_AREAS=7 ++# CONFIG_ZPOOL is not set ++# CONFIG_ZBUD is not set ++# CONFIG_ZSMALLOC 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_XEN is not set ++# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set ++ ++# ++# Boot options ++# ++CONFIG_USE_OF=y ++CONFIG_ATAGS=y ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE 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=y ++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set ++CONFIG_CMDLINE="" ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_AUTO_ZRELADDR is not set ++ ++# ++# CPU Power Management ++# ++ ++# ++# CPU Frequency scaling ++# ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_STAT=y ++# CONFIG_CPU_FREQ_STAT_DETAILS is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set ++# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_INTERACTIVE=y ++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set ++# CONFIG_CPUFREQ_DT is not set ++ ++# ++# ARM CPU frequency scaling drivers ++# ++# CONFIG_ARM_KIRKWOOD_CPUFREQ 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 ++CONFIG_VFPv3=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_BINFMT_SCRIPT=y ++# CONFIG_HAVE_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++CONFIG_COREDUMP=y ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_WAKELOCK is not set ++# CONFIG_HISI_SNAPSHOT_BOOT is not set ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_AUTOSLEEP is not set ++# CONFIG_PM_WAKELOCKS is not set ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_PM_OPP=y ++CONFIG_PM_CLK=y ++# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set ++CONFIG_CPU_PM=y ++# CONFIG_SUSPEND_TIME is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARM_CPU_SUSPEND=y ++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 is not set ++# 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 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_GENEVE 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 is not set ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++CONFIG_INET_LRO=y ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_INET_UDP_DIAG 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 is not set ++# CONFIG_ANDROID_PARANOID_NETWORK is not set ++CONFIG_NET_ACTIVITY_STATS=y ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NET_PTP_CLASSIFY is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_ACCT is not set ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NF_TABLES is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_SET is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_NF_LOG_ARP is not set ++# CONFIG_NF_LOG_IPV4 is not set ++# CONFIG_NF_REJECT_IPV4 is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES 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_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_IEEE802154 is not set ++# CONFIG_NET_SCHED is not set ++# CONFIG_DCB is not set ++# CONFIG_BATMAN_ADV is not set ++# CONFIG_OPENVSWITCH is not set ++# CONFIG_VSOCKETS is not set ++# CONFIG_NETLINK_MMAP is not set ++# CONFIG_NETLINK_DIAG is not set ++# CONFIG_NET_MPLS_GSO is not set ++# CONFIG_HSR is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID 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_WIRELESS=y ++# CONFIG_CFG80211 is not set ++# CONFIG_LIB80211 is not set ++ ++# ++# CFG80211 needs to be enabled for MAC80211 ++# ++# CONFIG_WIMAX is not set ++# CONFIG_RFKILL is not set ++# CONFIG_RFKILL_REGULATOR 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_HAVE_BPF_JIT=y ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_UEVENT_HELPER is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_STANDALONE=y ++# CONFIG_PREVENT_FIRMWARE_BUILD is not set ++CONFIG_FW_LOADER=y ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set ++CONFIG_ALLOW_DEV_COREDUMP=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_DEBUG_DEVRES is not set ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_GENERIC_CPU_DEVICES is not set ++# CONFIG_HAVE_CPU_AUTOPROBE is not set ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_DMA_SHARED_BUFFER=y ++# CONFIG_FENCE_TRACE is not set ++CONFIG_DMA_CMA=y ++ ++# ++# Default contiguous memory area size: ++# ++CONFIG_CMA_SIZE_MBYTES=16 ++CONFIG_CMA_SIZE_SEL_MBYTES=y ++# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set ++# CONFIG_CMA_SIZE_SEL_MIN is not set ++# CONFIG_CMA_SIZE_SEL_MAX is not set ++CONFIG_CMA_ALIGNMENT=8 ++ ++# ++# Bus devices ++# ++# CONFIG_BRCMSTB_GISB_ARB is not set ++CONFIG_ARM_CCI=y ++# 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_HIFMC 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 is not set ++# 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_IDS 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_SPI_NOR_USE_4K_SECTORS is not set ++CONFIG_SPI_HISI_SFC=y ++CONFIG_CLOSE_SPI_8PIN_4IO=y ++CONFIG_HISI_SPI_BLOCK_PROTECT=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++CONFIG_MTD_UBI_FASTMAP=y ++# CONFIG_MTD_UBI_GLUEBI is not set ++# CONFIG_MTD_UBI_BLOCK is not set ++CONFIG_DTC=y ++CONFIG_OF=y ++ ++# ++# Device Tree and Open Firmware support ++# ++# CONFIG_OF_SELFTEST 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_MTD=y ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_NULL_BLK is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_DRBD is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=65536 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_BLK_DEV_RBD is not set ++ ++# ++# Misc devices ++# ++# 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_BH1780 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_UID_STAT is not set ++# CONFIG_BMP085_I2C is not set ++# CONFIG_BMP085_SPI 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_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 ++# ++ ++# ++# Intel MIC Host Driver ++# ++ ++# ++# Intel MIC Card Driver ++# ++# CONFIG_ECHO is not set ++# CONFIG_CXL_BASE is not set ++ ++# ++# hisi 'himm/himd.l/himc'support ++# ++# CONFIG_HISI_REG is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_SCSI_MQ_DEFAULT is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=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_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_TUN is not set ++# CONFIG_VETH is not set ++# CONFIG_NLMON is not set ++ ++# ++# CAIF transport drivers ++# ++ ++# ++# Distributed Switch Architecture drivers ++# ++# CONFIG_NET_DSA_MV88E6XXX is not set ++# CONFIG_NET_DSA_MV88E6060 is not set ++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set ++# CONFIG_NET_DSA_MV88E6131 is not set ++# CONFIG_NET_DSA_MV88E6123_61_65 is not set ++# CONFIG_NET_DSA_MV88E6171 is not set ++# CONFIG_NET_DSA_BCM_SF2 is not set ++# CONFIG_ETHERNET is not set ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_AT803X_PHY is not set ++# CONFIG_AMD_PHY is not set ++# CONFIG_AMD_XGBE_PHY is not set ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_BCM7XXX_PHY is not set ++# CONFIG_BCM87XX_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++# CONFIG_MDIO_BUS_MUX_MMIOREG is not set ++# CONFIG_MDIO_BCM_UNIMAC is not set ++# CONFIG_MDIO_HISI_FEMAC is not set ++# CONFIG_MDIO_HISI_GEMAC is not set ++# CONFIG_MICREL_KS8995MA is not set ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++ ++# ++# Host-side USB support is needed for USB Network Adapter support ++# ++CONFIG_USB_NET_DRIVERS=m ++# 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_USBNET is not set ++# CONFIG_USB_IPHETH is not set ++CONFIG_WLAN=y ++# CONFIG_WIFI_CONTROL_FUNC is not set ++# CONFIG_HOSTAP is not set ++# CONFIG_WL_TI is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++# CONFIG_WAN is not set ++# CONFIG_ISDN 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=y ++# CONFIG_INPUT_EVBUG is not set ++# CONFIG_INPUT_KEYRESET is not set ++# CONFIG_INPUT_KEYCOMBO 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 ++ ++# ++# 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_VT_CONSOLE=y ++CONFIG_VT_CONSOLE_SLEEP=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# 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=y ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_EARLYCON=y ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX310X 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_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART 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_ST_ASC is not set ++# CONFIG_TTY_PRINTK is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_HW_RANDOM=y ++# CONFIG_HW_RANDOM_TIMERIOMEM is not set ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++# CONFIG_DCC_TTY 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=m ++ ++# ++# Multiplexer I2C Chip support ++# ++# CONFIG_I2C_MUX_PCA9541 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_DESIGNWARE_PLATFORM is not set ++# CONFIG_I2C_HIBVT is not set ++CONFIG_I2C_HISI_V110=y ++# CONFIG_I2C_NOMADIK 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_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++# CONFIG_SPI_DEBUG is not set ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_CADENCE is not set ++# CONFIG_SPI_FSL_SPI is not set ++CONFIG_SPI_PL022=y ++# 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_DESIGNWARE is not set ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# 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_ARCH_WANT_OPTIONAL_GPIOLIB=y ++# CONFIG_GPIOLIB is not set ++# CONFIG_W1 is not set ++CONFIG_POWER_SUPPLY=y ++# CONFIG_POWER_SUPPLY_DEBUG is not set ++# CONFIG_PDA_POWER is not set ++# CONFIG_TEST_POWER is not set ++# CONFIG_BATTERY_DS2780 is not set ++# CONFIG_BATTERY_DS2781 is not set ++# CONFIG_BATTERY_DS2782 is not set ++# CONFIG_BATTERY_SBS is not set ++# CONFIG_BATTERY_BQ27x00 is not set ++# CONFIG_BATTERY_MAX17040 is not set ++# CONFIG_BATTERY_MAX17042 is not set ++# CONFIG_CHARGER_MAX8903 is not set ++# CONFIG_CHARGER_LP8727 is not set ++# CONFIG_CHARGER_BQ2415X is not set ++# CONFIG_CHARGER_SMB347 is not set ++CONFIG_POWER_RESET=y ++# CONFIG_POWER_RESET_BRCMSTB is not set ++CONFIG_POWER_RESET_HISI=y ++# CONFIG_POWER_RESET_RESTART is not set ++# CONFIG_POWER_RESET_VERSATILE is not set ++# CONFIG_POWER_RESET_SYSCON is not set ++# CONFIG_POWER_AVS is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++# CONFIG_WATCHDOG 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=y ++# CONFIG_MFD_AS3711 is not set ++# CONFIG_MFD_AS3722 is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_BCM590XX is not set ++# CONFIG_MFD_AXP20X is not set ++# CONFIG_MFD_CROS_EC 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_DA9063 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_MFD_HISI_FMC=y ++# CONFIG_HTC_PASIC3 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_MAX77686 is not set ++# CONFIG_MFD_MAX77693 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_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_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_SMSC is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_MFD_STMPE is not set ++CONFIG_MFD_SYSCON=y ++# 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_TPS6507X is not set ++# CONFIG_MFD_TPS65090 is not set ++# CONFIG_MFD_TPS65217 is not set ++# CONFIG_MFD_TPS65218 is not set ++# CONFIG_MFD_TPS6586X 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=y ++# CONFIG_REGULATOR_DEBUG is not set ++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set ++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set ++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set ++# CONFIG_REGULATOR_ACT8865 is not set ++# CONFIG_REGULATOR_AD5398 is not set ++# CONFIG_REGULATOR_ANATOP is not set ++# CONFIG_REGULATOR_DA9210 is not set ++# CONFIG_REGULATOR_DA9211 is not set ++# CONFIG_REGULATOR_FAN53555 is not set ++# CONFIG_REGULATOR_ISL9305 is not set ++# CONFIG_REGULATOR_ISL6271A is not set ++# CONFIG_REGULATOR_LP3971 is not set ++# CONFIG_REGULATOR_LP3972 is not set ++# CONFIG_REGULATOR_LP872X is not set ++# CONFIG_REGULATOR_LP8755 is not set ++# CONFIG_REGULATOR_LTC3589 is not set ++# CONFIG_REGULATOR_MAX1586 is not set ++# CONFIG_REGULATOR_MAX8649 is not set ++# CONFIG_REGULATOR_MAX8660 is not set ++# CONFIG_REGULATOR_MAX8952 is not set ++# CONFIG_REGULATOR_MAX8973 is not set ++# CONFIG_REGULATOR_PFUZE100 is not set ++# CONFIG_REGULATOR_TPS51632 is not set ++# CONFIG_REGULATOR_TPS62360 is not set ++# CONFIG_REGULATOR_TPS65023 is not set ++# CONFIG_REGULATOR_TPS6507X is not set ++# CONFIG_REGULATOR_TPS6524X is not set ++CONFIG_MEDIA_SUPPORT=m ++ ++# ++# Multimedia core support ++# ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set ++# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set ++# CONFIG_MEDIA_RADIO_SUPPORT is not set ++# CONFIG_MEDIA_SDR_SUPPORT is not set ++# CONFIG_MEDIA_RC_SUPPORT is not set ++# CONFIG_MEDIA_CONTROLLER is not set ++CONFIG_VIDEO_DEV=m ++CONFIG_VIDEO_V4L2=m ++# CONFIG_VIDEO_ADV_DEBUG is not set ++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set ++CONFIG_VIDEOBUF2_CORE=m ++CONFIG_VIDEOBUF2_MEMOPS=m ++CONFIG_VIDEOBUF2_VMALLOC=m ++# CONFIG_TTPCI_EEPROM is not set ++ ++# ++# Media drivers ++# ++# CONFIG_MEDIA_USB_SUPPORT is not set ++# CONFIG_V4L_PLATFORM_DRIVERS is not set ++# CONFIG_V4L_MEM2MEM_DRIVERS is not set ++# CONFIG_V4L_TEST_DRIVERS is not set ++ ++# ++# Supported MMC/SDIO adapters ++# ++# CONFIG_CYPRESS_FIRMWARE is not set ++ ++# ++# Media ancillary drivers (tuners, sensors, i2c, frontends) ++# ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++ ++# ++# Audio decoders, processors and mixers ++# ++ ++# ++# RDS decoders ++# ++ ++# ++# Video decoders ++# ++ ++# ++# Video and audio decoders ++# ++ ++# ++# Video encoders ++# ++ ++# ++# Camera sensor devices ++# ++ ++# ++# Flash devices ++# ++ ++# ++# Video improvement chips ++# ++ ++# ++# Audio/Video compression chips ++# ++ ++# ++# Miscellaneous helper chips ++# ++ ++# ++# Sensors used on soc_camera driver ++# ++ ++# ++# Tools to develop new frontends ++# ++# CONFIG_DVB_DUMMY_FE is not set ++ ++# ++# Graphics support ++# ++# CONFIG_IMX_IPUV3_CORE is not set ++ ++# ++# Direct Rendering Manager ++# ++# CONFIG_DRM is not set ++ ++# ++# Frame buffer Devices ++# ++CONFIG_FB=y ++# CONFIG_FIRMWARE_EDID is not set ++CONFIG_FB_CMDLINE=y ++# CONFIG_FB_DDC is not set ++# CONFIG_FB_BOOT_VESA_SUPPORT is not set ++# CONFIG_FB_CFB_FILLRECT is not set ++# CONFIG_FB_CFB_COPYAREA is not set ++# CONFIG_FB_CFB_IMAGEBLIT is not set ++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set ++# CONFIG_FB_SYS_FILLRECT is not set ++# CONFIG_FB_SYS_COPYAREA is not set ++# CONFIG_FB_SYS_IMAGEBLIT is not set ++# CONFIG_FB_FOREIGN_ENDIAN is not set ++# CONFIG_FB_SYS_FOPS is not set ++# CONFIG_FB_SVGALIB is not set ++# CONFIG_FB_MACMODES is not set ++# CONFIG_FB_BACKLIGHT is not set ++# CONFIG_FB_MODE_HELPERS is not set ++# CONFIG_FB_TILEBLITTING is not set ++ ++# ++# Frame buffer hardware drivers ++# ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_OPENCORES is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_SMSCUFX is not set ++# CONFIG_FB_UDL is not set ++# CONFIG_FB_VIRTUAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_AUO_K190X is not set ++# CONFIG_FB_SIMPLE is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++# CONFIG_VGASTATE is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE is not set ++# CONFIG_LOGO is not set ++# CONFIG_SOUND is not set ++ ++# ++# HID support ++# ++CONFIG_HID=y ++# CONFIG_HID_BATTERY_STRENGTH is not set ++# CONFIG_HIDRAW is not set ++# CONFIG_UHID is not set ++CONFIG_HID_GENERIC=y ++ ++# ++# Special HID drivers ++# ++# CONFIG_HID_A4TECH is not set ++# CONFIG_HID_ACRUX is not set ++# CONFIG_HID_APPLE is not set ++# CONFIG_HID_APPLEIR is not set ++# CONFIG_HID_AUREAL is not set ++# CONFIG_HID_BELKIN is not set ++# CONFIG_HID_CHERRY is not set ++# CONFIG_HID_CHICONY is not set ++# CONFIG_HID_CYPRESS is not set ++# CONFIG_HID_DRAGONRISE is not set ++# CONFIG_HID_EMS_FF is not set ++# CONFIG_HID_ELECOM is not set ++# CONFIG_HID_ELO is not set ++# CONFIG_HID_EZKEY is not set ++# CONFIG_HID_HOLTEK is not set ++# CONFIG_HID_HUION is not set ++# CONFIG_HID_KEYTOUCH is not set ++# CONFIG_HID_KYE is not set ++# CONFIG_HID_UCLOGIC is not set ++# CONFIG_HID_WALTOP is not set ++# CONFIG_HID_GYRATION is not set ++# CONFIG_HID_ICADE is not set ++# CONFIG_HID_TWINHAN is not set ++# CONFIG_HID_KENSINGTON is not set ++# CONFIG_HID_LCPOWER is not set ++# CONFIG_HID_LENOVO is not set ++# CONFIG_HID_LOGITECH is not set ++# CONFIG_HID_MAGICMOUSE is not set ++# CONFIG_HID_MICROSOFT is not set ++# CONFIG_HID_MONTEREY is not set ++# CONFIG_HID_MULTITOUCH is not set ++# CONFIG_HID_NTRIG is not set ++# CONFIG_HID_ORTEK is not set ++# CONFIG_HID_PANTHERLORD is not set ++# CONFIG_HID_PENMOUNT is not set ++# CONFIG_HID_PETALYNX is not set ++# CONFIG_HID_PICOLCD is not set ++# CONFIG_HID_PRIMAX is not set ++# CONFIG_HID_ROCCAT is not set ++# CONFIG_HID_SAITEK is not set ++# CONFIG_HID_SAMSUNG is not set ++# CONFIG_HID_SPEEDLINK is not set ++# CONFIG_HID_STEELSERIES is not set ++# CONFIG_HID_SUNPLUS is not set ++# CONFIG_HID_RMI is not set ++# CONFIG_HID_GREENASIA is not set ++# CONFIG_HID_SMARTJOYPLUS is not set ++# CONFIG_HID_TIVO is not set ++# CONFIG_HID_TOPSEED is not set ++# CONFIG_HID_THRUSTMASTER is not set ++# CONFIG_HID_WACOM is not set ++# CONFIG_HID_XINMO is not set ++# CONFIG_HID_ZEROPLUS is not set ++# CONFIG_HID_ZYDACRON is not set ++# CONFIG_HID_SENSOR_HUB is not set ++ ++# ++# USB HID support ++# ++CONFIG_USB_HID=m ++# CONFIG_HID_PID is not set ++# CONFIG_USB_HIDDEV 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=m ++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set ++ ++# ++# Miscellaneous USB options ++# ++# CONFIG_USB_DEFAULT_PERSIST is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_OTG_FSM is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB_CBAF 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_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_FUSBH200_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 is not set ++# 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 ++# ++# CONFIG_USB_STORAGE is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK 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 is not set ++# CONFIG_USB_CHIPIDEA 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_LED 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_LINK_LAYER_TEST is not set ++ ++# ++# USB Physical Layer drivers ++# ++# CONFIG_USB_PHY is not set ++# CONFIG_NOP_USB_XCEIV is not set ++# CONFIG_AM335X_PHY_USB is not set ++# CONFIG_USB_ISP1301 is not set ++# CONFIG_USB_ULPI is not set ++CONFIG_USB_GADGET=y ++# CONFIG_USB_GADGET_DEBUG is not set ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++ ++# ++# USB Peripheral Controller ++# ++# CONFIG_USB_FUSB300 is not set ++# CONFIG_USB_FOTG210_UDC is not set ++# CONFIG_USB_GR_UDC is not set ++# CONFIG_USB_R8A66597 is not set ++# CONFIG_USB_PXA27X is not set ++# CONFIG_USB_MV_UDC is not set ++CONFIG_HIUSB_DEVICE2_0=y ++CONFIG_USB_HISI_UDC=m ++# CONFIG_USB_AUTO_SWITCH is not set ++# CONFIG_HIUSB_DEVICE3_0 is not set ++# CONFIG_USB_MV_U3D is not set ++# CONFIG_USB_M66592 is not set ++# CONFIG_USB_NET2272 is not set ++# CONFIG_USB_GADGET_XILINX is not set ++CONFIG_USB_LIBCOMPOSITE=m ++CONFIG_USB_F_ACM=m ++CONFIG_USB_U_SERIAL=m ++CONFIG_USB_U_ETHER=m ++CONFIG_USB_F_RNDIS=m ++CONFIG_USB_F_MASS_STORAGE=m ++CONFIG_USB_F_UAC1=m ++CONFIG_USB_F_UVC=m ++# CONFIG_USB_CONFIGFS is not set ++# CONFIG_USB_ZERO is not set ++CONFIG_USB_AUDIO=m ++CONFIG_GADGET_UAC1=y ++# CONFIG_USB_ETH is not set ++# CONFIG_USB_G_NCM is not set ++# CONFIG_USB_GADGETFS is not set ++# CONFIG_USB_FUNCTIONFS is not set ++CONFIG_USB_MASS_STORAGE=m ++# CONFIG_USB_G_SERIAL is not set ++# CONFIG_USB_G_PRINTER is not set ++# CONFIG_USB_CDC_COMPOSITE is not set ++# CONFIG_USB_G_ACM_MS is not set ++CONFIG_USB_G_MULTI=m ++CONFIG_USB_G_MULTI_RNDIS=y ++# CONFIG_USB_G_MULTI_CDC is not set ++# CONFIG_USB_G_HID is not set ++# CONFIG_USB_G_DBGP is not set ++# CONFIG_USB_G_WEBCAM is not set ++CONFIG_USB_G_WEBCAM_AUDIO=m ++# CONFIG_UWB is not set ++CONFIG_MMC=m ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_CLKGATE is not set ++CONFIG_MMC_EMBEDDED_SDIO=y ++# CONFIG_MMC_PARANOID_SD_INIT is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=m ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_ARMMMCI is not set ++# CONFIG_MMC_SDHCI is not set ++# 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_HIMCIV200=m ++CONFIG_SEND_AUTO_STOP=y ++CONFIG_DETECT_CARD_TIME=200 ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_SWITCH is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_EDAC is not set ++CONFIG_RTC_LIB=y ++# CONFIG_RTC_CLASS is not set ++# CONFIG_DMADEVICES 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 ++ ++# ++# SOC (System On Chip) specific Drivers ++# ++# CONFIG_SOC_TI 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_SI570 is not set ++# CONFIG_COMMON_CLK_PXA is not set ++# CONFIG_COMMON_CLK_QCOM is not set ++ ++# ++# Hardware Spinlock drivers ++# ++ ++# ++# Clock Source drivers ++# ++CONFIG_CLKSRC_OF=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS 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_CLKSRC_VERSATILE 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 ++# ++# CONFIG_PM_DEVFREQ is not set ++# CONFIG_EXTCON is not set ++# CONFIG_MEMORY is not set ++# CONFIG_IIO is not set ++# CONFIG_PWM is not set ++CONFIG_IRQCHIP=y ++CONFIG_ARM_GIC=y ++# CONFIG_IPACK_BUS is not set ++CONFIG_ARCH_HAS_RESET_CONTROLLER=y ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FMC is not set ++ ++# ++# PHY Subsystem ++# ++CONFIG_GENERIC_PHY=y ++# CONFIG_BCM_KONA_USB2_PHY is not set ++CONFIG_PHY_HISI_INNO_USB2=m ++# CONFIG_POWERCAP is not set ++# CONFIG_MCB is not set ++# CONFIG_HI_DMAC is not set ++ ++# ++# Hisilicon driver support ++# ++# CONFIG_CMA_MEM_SHARED is not set ++# CONFIG_CMA_ADVANCE_SHARE 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_XFS_FS is not set ++# CONFIG_GFS2_FS is not set ++# CONFIG_OCFS2_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++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=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++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=m ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_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_YAFFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY 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_UBIFS_FS=y ++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_ZLIB=y ++# CONFIG_LOGFS is not set ++# CONFIG_CRAMFS is not set ++CONFIG_SQUASHFS=y ++CONFIG_SQUASHFS_FILE_CACHE=y ++# CONFIG_SQUASHFS_FILE_DIRECT is not set ++CONFIG_SQUASHFS_DECOMP_SINGLE=y ++# CONFIG_SQUASHFS_DECOMP_MULTI is not set ++# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set ++# CONFIG_SQUASHFS_XATTR is not set ++CONFIG_SQUASHFS_ZLIB=y ++CONFIG_SQUASHFS_LZO=y ++# CONFIG_SQUASHFS_XZ is not set ++# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set ++# CONFIG_SQUASHFS_EMBEDDED is not set ++CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 ++# 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_F2FS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++# 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_ACL_SUPPORT=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 is not set ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++# CONFIG_BOOT_PRINTK_DELAY is not set ++ ++# ++# Compile-time checks and compiler options ++# ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_READABLE_ASM is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_DEBUG_KERNEL=y ++ ++# ++# Memory Debugging ++# ++# CONFIG_DEBUG_PAGEALLOC is not set ++# CONFIG_DEBUG_OBJECTS is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_HAVE_DEBUG_KMEMLEAK=y ++# CONFIG_DEBUG_KMEMLEAK is not set ++# CONFIG_DEBUG_STACK_USAGE is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_DEBUG_MEMORY_INIT=y ++# CONFIG_DEBUG_HIGHMEM is not set ++# CONFIG_DEBUG_SHIRQ is not set ++ ++# ++# Debug Lockups and Hangs ++# ++# CONFIG_LOCKUP_DETECTOR is not set ++# CONFIG_DETECT_HUNG_TASK is not set ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=0 ++CONFIG_SCHED_DEBUG=y ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_SCHED_STACK_END_CHECK is not set ++# CONFIG_TIMER_STATS is not set ++ ++# ++# Lock Debugging (spinlocks, mutexes, etc...) ++# ++# CONFIG_DEBUG_RT_MUTEXES is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_MUTEXES is not set ++# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set ++# CONFIG_DEBUG_LOCK_ALLOC is not set ++# CONFIG_PROVE_LOCKING is not set ++# CONFIG_LOCK_STAT is not set ++# CONFIG_DEBUG_ATOMIC_SLEEP is not set ++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set ++# CONFIG_LOCK_TORTURE_TEST is not set ++CONFIG_STACKTRACE=y ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_LIST is not set ++# CONFIG_DEBUG_PI_LIST is not set ++# CONFIG_DEBUG_SG is not set ++# CONFIG_DEBUG_NOTIFIERS is not set ++# CONFIG_DEBUG_CREDENTIALS is not set ++ ++# ++# RCU Debugging ++# ++# CONFIG_SPARSE_RCU_POINTER is not set ++# CONFIG_TORTURE_TEST is not set ++# CONFIG_RCU_TORTURE_TEST is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set ++# CONFIG_NOTIFIER_ERROR_INJECTION is not set ++# CONFIG_FAULT_INJECTION is not set ++# CONFIG_LATENCYTOP 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 is not set ++ ++# ++# Runtime Testing ++# ++# CONFIG_TEST_LIST_SORT is not set ++# CONFIG_BACKTRACE_SELF_TEST is not set ++# CONFIG_RBTREE_TEST is not set ++# CONFIG_INTERVAL_TREE_TEST is not set ++# CONFIG_PERCPU_TEST is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_TEST_STRING_HELPERS is not set ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_TEST_RHASHTABLE 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_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_KGDB is not set ++# CONFIG_ARM_PTDUMP is not set ++CONFIG_STRICT_DEVMEM=y ++CONFIG_ARM_UNWIND=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_LL is not set ++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" ++# CONFIG_DEBUG_UART_PL01X is not set ++# CONFIG_DEBUG_UART_8250 is not set ++# CONFIG_DEBUG_UART_BCM63XX is not set ++CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" ++# CONFIG_OC_ETM is not set ++# CONFIG_PID_IN_CONTEXTIDR is not set ++# CONFIG_DEBUG_SET_MODULE_RONX is not set ++# CONFIG_CORESIGHT is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS 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_RNG=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_PCOMP2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_USER is not set ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++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=y ++# CONFIG_CRYPTO_GCM is not set ++CONFIG_CRYPTO_SEQIV=y ++ ++# ++# Block modes ++# ++# CONFIG_CRYPTO_CBC is not set ++CONFIG_CRYPTO_CTR=y ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_CMAC is not set ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_CRC32 is not set ++# CONFIG_CRYPTO_CRCT10DIF is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# 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_SHA1_ARM is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_SHA512_ARM_NEON is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_AES_ARM is not set ++# CONFIG_CRYPTO_AES_ARM_BS is not set ++# 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 is not set ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 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=y ++# CONFIG_CRYPTO_ZLIB is not set ++CONFIG_CRYPTO_LZO=y ++# 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 is not set ++# CONFIG_CRYPTO_USER_API_HASH is not set ++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set ++CONFIG_CRYPTO_HW=y ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=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=y ++# 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_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=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_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HAS_DMA=y ++CONFIG_DQL=y ++CONFIG_NLATTR=y ++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y ++CONFIG_AVERAGE=y ++# CONFIG_CORDIC is not set ++# CONFIG_DDR is not set ++CONFIG_LIBFDT=y ++CONFIG_ARCH_HAS_SG_CHAIN=y ++# CONFIG_VIRTUALIZATION is not set +diff --git a/arch/arm/configs/hisi_defconfig b/arch/arm/configs/hisi_defconfig +index 1772505..9e35ff8 100644 +--- a/arch/arm/configs/hisi_defconfig ++++ b/arch/arm/configs/hisi_defconfig +@@ -7,6 +7,7 @@ CONFIG_ARCH_HISI=y + CONFIG_ARCH_HI3xxx=y + CONFIG_ARCH_HIX5HD2=y + CONFIG_ARCH_HIP04=y ++CONFIG_ARCH_HI3519=y + CONFIG_SMP=y + CONFIG_NR_CPUS=16 + CONFIG_PREEMPT=y +diff --git a/arch/arm/include/asm/fiq_glue.h b/arch/arm/include/asm/fiq_glue.h +new file mode 100644 +index 0000000..a9e244f9 +--- /dev/null ++++ b/arch/arm/include/asm/fiq_glue.h +@@ -0,0 +1,33 @@ ++/* ++ * Copyright (C) 2010 Google, 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. ++ */ ++ ++#ifndef __ASM_FIQ_GLUE_H ++#define __ASM_FIQ_GLUE_H ++ ++struct fiq_glue_handler { ++ void (*fiq)(struct fiq_glue_handler *h, void *regs, void *svc_sp); ++ void (*resume)(struct fiq_glue_handler *h); ++}; ++typedef void (*fiq_return_handler_t)(void); ++ ++int fiq_glue_register_handler(struct fiq_glue_handler *handler); ++int fiq_glue_set_return_handler(fiq_return_handler_t fiq_return); ++int fiq_glue_clear_return_handler(fiq_return_handler_t fiq_return); ++ ++#ifdef CONFIG_FIQ_GLUE ++void fiq_glue_resume(void); ++#else ++static inline void fiq_glue_resume(void) {} ++#endif ++ ++#endif +diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h +index fe3ea77..5df33e3 100644 +--- a/arch/arm/include/asm/hardirq.h ++++ b/arch/arm/include/asm/hardirq.h +@@ -5,7 +5,7 @@ + #include + #include + +-#define NR_IPI 8 ++#define NR_IPI 9 + + typedef struct { + unsigned int __softirq_pending; +diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h +index ad774f3..b350765 100644 +--- a/arch/arm/include/asm/hardware/coresight.h ++++ b/arch/arm/include/asm/hardware/coresight.h +@@ -17,15 +17,23 @@ + #define TRACER_ACCESSED_BIT 0 + #define TRACER_RUNNING_BIT 1 + #define TRACER_CYCLE_ACC_BIT 2 ++#define TRACER_TRACE_DATA_BIT 3 ++#define TRACER_TIMESTAMP_BIT 4 ++#define TRACER_BRANCHOUTPUT_BIT 5 ++#define TRACER_RETURN_STACK_BIT 6 + #define TRACER_ACCESSED BIT(TRACER_ACCESSED_BIT) + #define TRACER_RUNNING BIT(TRACER_RUNNING_BIT) + #define TRACER_CYCLE_ACC BIT(TRACER_CYCLE_ACC_BIT) ++#define TRACER_TRACE_DATA BIT(TRACER_TRACE_DATA_BIT) ++#define TRACER_TIMESTAMP BIT(TRACER_TIMESTAMP_BIT) ++#define TRACER_BRANCHOUTPUT BIT(TRACER_BRANCHOUTPUT_BIT) ++#define TRACER_RETURN_STACK BIT(TRACER_RETURN_STACK_BIT) + + #define TRACER_TIMEOUT 10000 + +-#define etm_writel(t, v, x) \ +- (writel_relaxed((v), (t)->etm_regs + (x))) +-#define etm_readl(t, x) (readl_relaxed((t)->etm_regs + (x))) ++#define etm_writel(t, id, v, x) \ ++ (writel_relaxed((v), (t)->etm_regs[(id)] + (x))) ++#define etm_readl(t, id, x) (readl_relaxed((t)->etm_regs[(id)] + (x))) + + /* CoreSight Management Registers */ + #define CSMR_LOCKACCESS 0xfb0 +@@ -43,7 +51,7 @@ + #define ETMCTRL_POWERDOWN 1 + #define ETMCTRL_PROGRAM (1 << 10) + #define ETMCTRL_PORTSEL (1 << 11) +-#define ETMCTRL_DO_CONTEXTID (3 << 14) ++#define ETMCTRL_CONTEXTIDSIZE(x) (((x) & 3) << 14) + #define ETMCTRL_PORTMASK1 (7 << 4) + #define ETMCTRL_PORTMASK2 (1 << 21) + #define ETMCTRL_PORTMASK (ETMCTRL_PORTMASK1 | ETMCTRL_PORTMASK2) +@@ -55,9 +63,12 @@ + #define ETMCTRL_DATA_DO_BOTH (ETMCTRL_DATA_DO_DATA | ETMCTRL_DATA_DO_ADDR) + #define ETMCTRL_BRANCH_OUTPUT (1 << 8) + #define ETMCTRL_CYCLEACCURATE (1 << 12) ++#define ETMCTRL_TIMESTAMP_EN (1 << 28) ++#define ETMCTRL_RETURN_STACK_EN (1 << 29) + + /* ETM configuration code register */ + #define ETMR_CONFCODE (0x04) ++#define ETMCCR_ETMIDR_PRESENT BIT(31) + + /* ETM trace start/stop resource control register */ + #define ETMR_TRACESSCTRL (0x18) +@@ -113,10 +124,25 @@ + #define ETMR_TRACEENCTRL 0x24 + #define ETMTE_INCLEXCL BIT(24) + #define ETMR_TRACEENEVT 0x20 +-#define ETMCTRL_OPTS (ETMCTRL_DO_CPRT | \ +- ETMCTRL_DATA_DO_ADDR | \ +- ETMCTRL_BRANCH_OUTPUT | \ +- ETMCTRL_DO_CONTEXTID) ++ ++#define ETMR_VIEWDATAEVT 0x30 ++#define ETMR_VIEWDATACTRL1 0x34 ++#define ETMR_VIEWDATACTRL2 0x38 ++#define ETMR_VIEWDATACTRL3 0x3c ++#define ETMVDC3_EXCLONLY BIT(16) ++ ++#define ETMCTRL_OPTS (ETMCTRL_DO_CPRT) ++ ++#define ETMR_ID 0x1e4 ++#define ETMIDR_VERSION(x) (((x) >> 4) & 0xff) ++#define ETMIDR_VERSION_3_1 0x21 ++#define ETMIDR_VERSION_PFT_1_0 0x30 ++ ++#define ETMR_CCE 0x1e8 ++#define ETMCCER_RETURN_STACK_IMPLEMENTED BIT(23) ++#define ETMCCER_TIMESTAMPING_IMPLEMENTED BIT(22) ++ ++#define ETMR_TRACEIDR 0x200 + + /* ETM management registers, "ETM Architecture", 3.5.24 */ + #define ETMMR_OSLAR 0x300 +@@ -140,14 +166,16 @@ + #define ETBFF_TRIGIN BIT(8) + #define ETBFF_TRIGEVT BIT(9) + #define ETBFF_TRIGFL BIT(10) ++#define ETBFF_STOPFL BIT(12) + + #define etb_writel(t, v, x) \ + (writel_relaxed((v), (t)->etb_regs + (x))) + #define etb_readl(t, x) (readl_relaxed((t)->etb_regs + (x))) + +-#define etm_lock(t) do { etm_writel((t), 0, CSMR_LOCKACCESS); } while (0) +-#define etm_unlock(t) \ +- do { etm_writel((t), CS_LAR_KEY, CSMR_LOCKACCESS); } while (0) ++#define etm_lock(t, id) \ ++ do { etm_writel((t), (id), 0, CSMR_LOCKACCESS); } while (0) ++#define etm_unlock(t, id) \ ++ do { etm_writel((t), (id), CS_LAR_KEY, CSMR_LOCKACCESS); } while (0) + + #define etb_lock(t) do { etb_writel((t), 0, CSMR_LOCKACCESS); } while (0) + #define etb_unlock(t) \ +diff --git a/arch/arm/include/asm/hardware/cp14.h b/arch/arm/include/asm/hardware/cp14.h +new file mode 100644 +index 0000000..61576dc +--- /dev/null ++++ b/arch/arm/include/asm/hardware/cp14.h +@@ -0,0 +1,542 @@ ++/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * 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 __ASM_HARDWARE_CP14_H ++#define __ASM_HARDWARE_CP14_H ++ ++#include ++ ++/* Accessors for CP14 registers */ ++#define dbg_read(reg) RCP14_##reg() ++#define dbg_write(val, reg) WCP14_##reg(val) ++#define etm_read(reg) RCP14_##reg() ++#define etm_write(val, reg) WCP14_##reg(val) ++ ++/* MRC14 and MCR14 */ ++#define MRC14(op1, crn, crm, op2) \ ++({ \ ++u32 val; \ ++asm volatile("mrc p14, "#op1", %0, "#crn", "#crm", "#op2 : "=r" (val)); \ ++val; \ ++}) ++ ++#define MCR14(val, op1, crn, crm, op2) \ ++({ \ ++asm volatile("mcr p14, "#op1", %0, "#crn", "#crm", "#op2 : : "r" (val));\ ++}) ++ ++/* ++ * Debug Registers ++ * ++ * Available only in DBGv7 ++ * DBGECR, DBGDSCCR, DBGDSMCR, DBGDRCR ++ * ++ * Available only in DBGv7.1 ++ * DBGBXVRm, DBGOSDLR, DBGDEVID2, DBGDEVID1 ++ * ++ * Read only ++ * DBGDIDR, DBGDSCRint, DBGDTRRXint, DBGDRAR, DBGOSLSR, DBGOSSRR, DBGPRSR, ++ * DBGPRSR, DBGDSAR, DBGAUTHSTATUS, DBGDEVID2, DBGDEVID1, DBGDEVID ++ * ++ * Write only ++ * DBGDTRTXint, DBGOSLAR ++ */ ++#define RCP14_DBGDIDR() MRC14(0, c0, c0, 0) ++#define RCP14_DBGDSCRint() MRC14(0, c0, c1, 0) ++#define RCP14_DBGDTRRXint() MRC14(0, c0, c5, 0) ++#define RCP14_DBGWFAR() MRC14(0, c0, c6, 0) ++#define RCP14_DBGVCR() MRC14(0, c0, c7, 0) ++#define RCP14_DBGECR() MRC14(0, c0, c9, 0) ++#define RCP14_DBGDSCCR() MRC14(0, c0, c10, 0) ++#define RCP14_DBGDSMCR() MRC14(0, c0, c11, 0) ++#define RCP14_DBGDTRRXext() MRC14(0, c0, c0, 2) ++#define RCP14_DBGDSCRext() MRC14(0, c0, c2, 2) ++#define RCP14_DBGDTRTXext() MRC14(0, c0, c3, 2) ++#define RCP14_DBGDRCR() MRC14(0, c0, c4, 2) ++#define RCP14_DBGBVR0() MRC14(0, c0, c0, 4) ++#define RCP14_DBGBVR1() MRC14(0, c0, c1, 4) ++#define RCP14_DBGBVR2() MRC14(0, c0, c2, 4) ++#define RCP14_DBGBVR3() MRC14(0, c0, c3, 4) ++#define RCP14_DBGBVR4() MRC14(0, c0, c4, 4) ++#define RCP14_DBGBVR5() MRC14(0, c0, c5, 4) ++#define RCP14_DBGBVR6() MRC14(0, c0, c6, 4) ++#define RCP14_DBGBVR7() MRC14(0, c0, c7, 4) ++#define RCP14_DBGBVR8() MRC14(0, c0, c8, 4) ++#define RCP14_DBGBVR9() MRC14(0, c0, c9, 4) ++#define RCP14_DBGBVR10() MRC14(0, c0, c10, 4) ++#define RCP14_DBGBVR11() MRC14(0, c0, c11, 4) ++#define RCP14_DBGBVR12() MRC14(0, c0, c12, 4) ++#define RCP14_DBGBVR13() MRC14(0, c0, c13, 4) ++#define RCP14_DBGBVR14() MRC14(0, c0, c14, 4) ++#define RCP14_DBGBVR15() MRC14(0, c0, c15, 4) ++#define RCP14_DBGBCR0() MRC14(0, c0, c0, 5) ++#define RCP14_DBGBCR1() MRC14(0, c0, c1, 5) ++#define RCP14_DBGBCR2() MRC14(0, c0, c2, 5) ++#define RCP14_DBGBCR3() MRC14(0, c0, c3, 5) ++#define RCP14_DBGBCR4() MRC14(0, c0, c4, 5) ++#define RCP14_DBGBCR5() MRC14(0, c0, c5, 5) ++#define RCP14_DBGBCR6() MRC14(0, c0, c6, 5) ++#define RCP14_DBGBCR7() MRC14(0, c0, c7, 5) ++#define RCP14_DBGBCR8() MRC14(0, c0, c8, 5) ++#define RCP14_DBGBCR9() MRC14(0, c0, c9, 5) ++#define RCP14_DBGBCR10() MRC14(0, c0, c10, 5) ++#define RCP14_DBGBCR11() MRC14(0, c0, c11, 5) ++#define RCP14_DBGBCR12() MRC14(0, c0, c12, 5) ++#define RCP14_DBGBCR13() MRC14(0, c0, c13, 5) ++#define RCP14_DBGBCR14() MRC14(0, c0, c14, 5) ++#define RCP14_DBGBCR15() MRC14(0, c0, c15, 5) ++#define RCP14_DBGWVR0() MRC14(0, c0, c0, 6) ++#define RCP14_DBGWVR1() MRC14(0, c0, c1, 6) ++#define RCP14_DBGWVR2() MRC14(0, c0, c2, 6) ++#define RCP14_DBGWVR3() MRC14(0, c0, c3, 6) ++#define RCP14_DBGWVR4() MRC14(0, c0, c4, 6) ++#define RCP14_DBGWVR5() MRC14(0, c0, c5, 6) ++#define RCP14_DBGWVR6() MRC14(0, c0, c6, 6) ++#define RCP14_DBGWVR7() MRC14(0, c0, c7, 6) ++#define RCP14_DBGWVR8() MRC14(0, c0, c8, 6) ++#define RCP14_DBGWVR9() MRC14(0, c0, c9, 6) ++#define RCP14_DBGWVR10() MRC14(0, c0, c10, 6) ++#define RCP14_DBGWVR11() MRC14(0, c0, c11, 6) ++#define RCP14_DBGWVR12() MRC14(0, c0, c12, 6) ++#define RCP14_DBGWVR13() MRC14(0, c0, c13, 6) ++#define RCP14_DBGWVR14() MRC14(0, c0, c14, 6) ++#define RCP14_DBGWVR15() MRC14(0, c0, c15, 6) ++#define RCP14_DBGWCR0() MRC14(0, c0, c0, 7) ++#define RCP14_DBGWCR1() MRC14(0, c0, c1, 7) ++#define RCP14_DBGWCR2() MRC14(0, c0, c2, 7) ++#define RCP14_DBGWCR3() MRC14(0, c0, c3, 7) ++#define RCP14_DBGWCR4() MRC14(0, c0, c4, 7) ++#define RCP14_DBGWCR5() MRC14(0, c0, c5, 7) ++#define RCP14_DBGWCR6() MRC14(0, c0, c6, 7) ++#define RCP14_DBGWCR7() MRC14(0, c0, c7, 7) ++#define RCP14_DBGWCR8() MRC14(0, c0, c8, 7) ++#define RCP14_DBGWCR9() MRC14(0, c0, c9, 7) ++#define RCP14_DBGWCR10() MRC14(0, c0, c10, 7) ++#define RCP14_DBGWCR11() MRC14(0, c0, c11, 7) ++#define RCP14_DBGWCR12() MRC14(0, c0, c12, 7) ++#define RCP14_DBGWCR13() MRC14(0, c0, c13, 7) ++#define RCP14_DBGWCR14() MRC14(0, c0, c14, 7) ++#define RCP14_DBGWCR15() MRC14(0, c0, c15, 7) ++#define RCP14_DBGDRAR() MRC14(0, c1, c0, 0) ++#define RCP14_DBGBXVR0() MRC14(0, c1, c0, 1) ++#define RCP14_DBGBXVR1() MRC14(0, c1, c1, 1) ++#define RCP14_DBGBXVR2() MRC14(0, c1, c2, 1) ++#define RCP14_DBGBXVR3() MRC14(0, c1, c3, 1) ++#define RCP14_DBGBXVR4() MRC14(0, c1, c4, 1) ++#define RCP14_DBGBXVR5() MRC14(0, c1, c5, 1) ++#define RCP14_DBGBXVR6() MRC14(0, c1, c6, 1) ++#define RCP14_DBGBXVR7() MRC14(0, c1, c7, 1) ++#define RCP14_DBGBXVR8() MRC14(0, c1, c8, 1) ++#define RCP14_DBGBXVR9() MRC14(0, c1, c9, 1) ++#define RCP14_DBGBXVR10() MRC14(0, c1, c10, 1) ++#define RCP14_DBGBXVR11() MRC14(0, c1, c11, 1) ++#define RCP14_DBGBXVR12() MRC14(0, c1, c12, 1) ++#define RCP14_DBGBXVR13() MRC14(0, c1, c13, 1) ++#define RCP14_DBGBXVR14() MRC14(0, c1, c14, 1) ++#define RCP14_DBGBXVR15() MRC14(0, c1, c15, 1) ++#define RCP14_DBGOSLSR() MRC14(0, c1, c1, 4) ++#define RCP14_DBGOSSRR() MRC14(0, c1, c2, 4) ++#define RCP14_DBGOSDLR() MRC14(0, c1, c3, 4) ++#define RCP14_DBGPRCR() MRC14(0, c1, c4, 4) ++#define RCP14_DBGPRSR() MRC14(0, c1, c5, 4) ++#define RCP14_DBGDSAR() MRC14(0, c2, c0, 0) ++#define RCP14_DBGITCTRL() MRC14(0, c7, c0, 4) ++#define RCP14_DBGCLAIMSET() MRC14(0, c7, c8, 6) ++#define RCP14_DBGCLAIMCLR() MRC14(0, c7, c9, 6) ++#define RCP14_DBGAUTHSTATUS() MRC14(0, c7, c14, 6) ++#define RCP14_DBGDEVID2() MRC14(0, c7, c0, 7) ++#define RCP14_DBGDEVID1() MRC14(0, c7, c1, 7) ++#define RCP14_DBGDEVID() MRC14(0, c7, c2, 7) ++ ++#define WCP14_DBGDTRTXint(val) MCR14(val, 0, c0, c5, 0) ++#define WCP14_DBGWFAR(val) MCR14(val, 0, c0, c6, 0) ++#define WCP14_DBGVCR(val) MCR14(val, 0, c0, c7, 0) ++#define WCP14_DBGECR(val) MCR14(val, 0, c0, c9, 0) ++#define WCP14_DBGDSCCR(val) MCR14(val, 0, c0, c10, 0) ++#define WCP14_DBGDSMCR(val) MCR14(val, 0, c0, c11, 0) ++#define WCP14_DBGDTRRXext(val) MCR14(val, 0, c0, c0, 2) ++#define WCP14_DBGDSCRext(val) MCR14(val, 0, c0, c2, 2) ++#define WCP14_DBGDTRTXext(val) MCR14(val, 0, c0, c3, 2) ++#define WCP14_DBGDRCR(val) MCR14(val, 0, c0, c4, 2) ++#define WCP14_DBGBVR0(val) MCR14(val, 0, c0, c0, 4) ++#define WCP14_DBGBVR1(val) MCR14(val, 0, c0, c1, 4) ++#define WCP14_DBGBVR2(val) MCR14(val, 0, c0, c2, 4) ++#define WCP14_DBGBVR3(val) MCR14(val, 0, c0, c3, 4) ++#define WCP14_DBGBVR4(val) MCR14(val, 0, c0, c4, 4) ++#define WCP14_DBGBVR5(val) MCR14(val, 0, c0, c5, 4) ++#define WCP14_DBGBVR6(val) MCR14(val, 0, c0, c6, 4) ++#define WCP14_DBGBVR7(val) MCR14(val, 0, c0, c7, 4) ++#define WCP14_DBGBVR8(val) MCR14(val, 0, c0, c8, 4) ++#define WCP14_DBGBVR9(val) MCR14(val, 0, c0, c9, 4) ++#define WCP14_DBGBVR10(val) MCR14(val, 0, c0, c10, 4) ++#define WCP14_DBGBVR11(val) MCR14(val, 0, c0, c11, 4) ++#define WCP14_DBGBVR12(val) MCR14(val, 0, c0, c12, 4) ++#define WCP14_DBGBVR13(val) MCR14(val, 0, c0, c13, 4) ++#define WCP14_DBGBVR14(val) MCR14(val, 0, c0, c14, 4) ++#define WCP14_DBGBVR15(val) MCR14(val, 0, c0, c15, 4) ++#define WCP14_DBGBCR0(val) MCR14(val, 0, c0, c0, 5) ++#define WCP14_DBGBCR1(val) MCR14(val, 0, c0, c1, 5) ++#define WCP14_DBGBCR2(val) MCR14(val, 0, c0, c2, 5) ++#define WCP14_DBGBCR3(val) MCR14(val, 0, c0, c3, 5) ++#define WCP14_DBGBCR4(val) MCR14(val, 0, c0, c4, 5) ++#define WCP14_DBGBCR5(val) MCR14(val, 0, c0, c5, 5) ++#define WCP14_DBGBCR6(val) MCR14(val, 0, c0, c6, 5) ++#define WCP14_DBGBCR7(val) MCR14(val, 0, c0, c7, 5) ++#define WCP14_DBGBCR8(val) MCR14(val, 0, c0, c8, 5) ++#define WCP14_DBGBCR9(val) MCR14(val, 0, c0, c9, 5) ++#define WCP14_DBGBCR10(val) MCR14(val, 0, c0, c10, 5) ++#define WCP14_DBGBCR11(val) MCR14(val, 0, c0, c11, 5) ++#define WCP14_DBGBCR12(val) MCR14(val, 0, c0, c12, 5) ++#define WCP14_DBGBCR13(val) MCR14(val, 0, c0, c13, 5) ++#define WCP14_DBGBCR14(val) MCR14(val, 0, c0, c14, 5) ++#define WCP14_DBGBCR15(val) MCR14(val, 0, c0, c15, 5) ++#define WCP14_DBGWVR0(val) MCR14(val, 0, c0, c0, 6) ++#define WCP14_DBGWVR1(val) MCR14(val, 0, c0, c1, 6) ++#define WCP14_DBGWVR2(val) MCR14(val, 0, c0, c2, 6) ++#define WCP14_DBGWVR3(val) MCR14(val, 0, c0, c3, 6) ++#define WCP14_DBGWVR4(val) MCR14(val, 0, c0, c4, 6) ++#define WCP14_DBGWVR5(val) MCR14(val, 0, c0, c5, 6) ++#define WCP14_DBGWVR6(val) MCR14(val, 0, c0, c6, 6) ++#define WCP14_DBGWVR7(val) MCR14(val, 0, c0, c7, 6) ++#define WCP14_DBGWVR8(val) MCR14(val, 0, c0, c8, 6) ++#define WCP14_DBGWVR9(val) MCR14(val, 0, c0, c9, 6) ++#define WCP14_DBGWVR10(val) MCR14(val, 0, c0, c10, 6) ++#define WCP14_DBGWVR11(val) MCR14(val, 0, c0, c11, 6) ++#define WCP14_DBGWVR12(val) MCR14(val, 0, c0, c12, 6) ++#define WCP14_DBGWVR13(val) MCR14(val, 0, c0, c13, 6) ++#define WCP14_DBGWVR14(val) MCR14(val, 0, c0, c14, 6) ++#define WCP14_DBGWVR15(val) MCR14(val, 0, c0, c15, 6) ++#define WCP14_DBGWCR0(val) MCR14(val, 0, c0, c0, 7) ++#define WCP14_DBGWCR1(val) MCR14(val, 0, c0, c1, 7) ++#define WCP14_DBGWCR2(val) MCR14(val, 0, c0, c2, 7) ++#define WCP14_DBGWCR3(val) MCR14(val, 0, c0, c3, 7) ++#define WCP14_DBGWCR4(val) MCR14(val, 0, c0, c4, 7) ++#define WCP14_DBGWCR5(val) MCR14(val, 0, c0, c5, 7) ++#define WCP14_DBGWCR6(val) MCR14(val, 0, c0, c6, 7) ++#define WCP14_DBGWCR7(val) MCR14(val, 0, c0, c7, 7) ++#define WCP14_DBGWCR8(val) MCR14(val, 0, c0, c8, 7) ++#define WCP14_DBGWCR9(val) MCR14(val, 0, c0, c9, 7) ++#define WCP14_DBGWCR10(val) MCR14(val, 0, c0, c10, 7) ++#define WCP14_DBGWCR11(val) MCR14(val, 0, c0, c11, 7) ++#define WCP14_DBGWCR12(val) MCR14(val, 0, c0, c12, 7) ++#define WCP14_DBGWCR13(val) MCR14(val, 0, c0, c13, 7) ++#define WCP14_DBGWCR14(val) MCR14(val, 0, c0, c14, 7) ++#define WCP14_DBGWCR15(val) MCR14(val, 0, c0, c15, 7) ++#define WCP14_DBGBXVR0(val) MCR14(val, 0, c1, c0, 1) ++#define WCP14_DBGBXVR1(val) MCR14(val, 0, c1, c1, 1) ++#define WCP14_DBGBXVR2(val) MCR14(val, 0, c1, c2, 1) ++#define WCP14_DBGBXVR3(val) MCR14(val, 0, c1, c3, 1) ++#define WCP14_DBGBXVR4(val) MCR14(val, 0, c1, c4, 1) ++#define WCP14_DBGBXVR5(val) MCR14(val, 0, c1, c5, 1) ++#define WCP14_DBGBXVR6(val) MCR14(val, 0, c1, c6, 1) ++#define WCP14_DBGBXVR7(val) MCR14(val, 0, c1, c7, 1) ++#define WCP14_DBGBXVR8(val) MCR14(val, 0, c1, c8, 1) ++#define WCP14_DBGBXVR9(val) MCR14(val, 0, c1, c9, 1) ++#define WCP14_DBGBXVR10(val) MCR14(val, 0, c1, c10, 1) ++#define WCP14_DBGBXVR11(val) MCR14(val, 0, c1, c11, 1) ++#define WCP14_DBGBXVR12(val) MCR14(val, 0, c1, c12, 1) ++#define WCP14_DBGBXVR13(val) MCR14(val, 0, c1, c13, 1) ++#define WCP14_DBGBXVR14(val) MCR14(val, 0, c1, c14, 1) ++#define WCP14_DBGBXVR15(val) MCR14(val, 0, c1, c15, 1) ++#define WCP14_DBGOSLAR(val) MCR14(val, 0, c1, c0, 4) ++#define WCP14_DBGOSSRR(val) MCR14(val, 0, c1, c2, 4) ++#define WCP14_DBGOSDLR(val) MCR14(val, 0, c1, c3, 4) ++#define WCP14_DBGPRCR(val) MCR14(val, 0, c1, c4, 4) ++#define WCP14_DBGITCTRL(val) MCR14(val, 0, c7, c0, 4) ++#define WCP14_DBGCLAIMSET(val) MCR14(val, 0, c7, c8, 6) ++#define WCP14_DBGCLAIMCLR(val) MCR14(val, 0, c7, c9, 6) ++ ++/* ++ * ETM Registers ++ * ++ * Available only in ETMv3.3, 3.4, 3.5 ++ * ETMASICCR, ETMTECR2, ETMFFRR, ETMVDEVR, ETMVDCR1, ETMVDCR2, ETMVDCR3, ++ * ETMDCVRn, ETMDCMRn ++ * ++ * Available only in ETMv3.5 as read only ++ * ETMIDR2 ++ * ++ * Available only in ETMv3.5, PFTv1.0, 1.1 ++ * ETMTSEVR, ETMVMIDCVR, ETMPDCR ++ * ++ * Read only ++ * ETMCCR, ETMSCR, ETMIDR, ETMCCER, ETMOSLSR ++ * ETMLSR, ETMAUTHSTATUS, ETMDEVID, ETMDEVTYPE, ETMPIDR4, ETMPIDR5, ETMPIDR6, ++ * ETMPIDR7, ETMPIDR0, ETMPIDR1, ETMPIDR2, ETMPIDR2, ETMPIDR3, ETMCIDR0, ++ * ETMCIDR1, ETMCIDR2, ETMCIDR3 ++ * ++ * Write only ++ * ETMOSLAR, ETMLAR ++ * Note: ETMCCER[11] controls WO nature of certain regs. Refer ETM arch spec. ++ */ ++#define RCP14_ETMCR() MRC14(1, c0, c0, 0) ++#define RCP14_ETMCCR() MRC14(1, c0, c1, 0) ++#define RCP14_ETMTRIGGER() MRC14(1, c0, c2, 0) ++#define RCP14_ETMASICCR() MRC14(1, c0, c3, 0) ++#define RCP14_ETMSR() MRC14(1, c0, c4, 0) ++#define RCP14_ETMSCR() MRC14(1, c0, c5, 0) ++#define RCP14_ETMTSSCR() MRC14(1, c0, c6, 0) ++#define RCP14_ETMTECR2() MRC14(1, c0, c7, 0) ++#define RCP14_ETMTEEVR() MRC14(1, c0, c8, 0) ++#define RCP14_ETMTECR1() MRC14(1, c0, c9, 0) ++#define RCP14_ETMFFRR() MRC14(1, c0, c10, 0) ++#define RCP14_ETMFFLR() MRC14(1, c0, c11, 0) ++#define RCP14_ETMVDEVR() MRC14(1, c0, c12, 0) ++#define RCP14_ETMVDCR1() MRC14(1, c0, c13, 0) ++#define RCP14_ETMVDCR2() MRC14(1, c0, c14, 0) ++#define RCP14_ETMVDCR3() MRC14(1, c0, c15, 0) ++#define RCP14_ETMACVR0() MRC14(1, c0, c0, 1) ++#define RCP14_ETMACVR1() MRC14(1, c0, c1, 1) ++#define RCP14_ETMACVR2() MRC14(1, c0, c2, 1) ++#define RCP14_ETMACVR3() MRC14(1, c0, c3, 1) ++#define RCP14_ETMACVR4() MRC14(1, c0, c4, 1) ++#define RCP14_ETMACVR5() MRC14(1, c0, c5, 1) ++#define RCP14_ETMACVR6() MRC14(1, c0, c6, 1) ++#define RCP14_ETMACVR7() MRC14(1, c0, c7, 1) ++#define RCP14_ETMACVR8() MRC14(1, c0, c8, 1) ++#define RCP14_ETMACVR9() MRC14(1, c0, c9, 1) ++#define RCP14_ETMACVR10() MRC14(1, c0, c10, 1) ++#define RCP14_ETMACVR11() MRC14(1, c0, c11, 1) ++#define RCP14_ETMACVR12() MRC14(1, c0, c12, 1) ++#define RCP14_ETMACVR13() MRC14(1, c0, c13, 1) ++#define RCP14_ETMACVR14() MRC14(1, c0, c14, 1) ++#define RCP14_ETMACVR15() MRC14(1, c0, c15, 1) ++#define RCP14_ETMACTR0() MRC14(1, c0, c0, 2) ++#define RCP14_ETMACTR1() MRC14(1, c0, c1, 2) ++#define RCP14_ETMACTR2() MRC14(1, c0, c2, 2) ++#define RCP14_ETMACTR3() MRC14(1, c0, c3, 2) ++#define RCP14_ETMACTR4() MRC14(1, c0, c4, 2) ++#define RCP14_ETMACTR5() MRC14(1, c0, c5, 2) ++#define RCP14_ETMACTR6() MRC14(1, c0, c6, 2) ++#define RCP14_ETMACTR7() MRC14(1, c0, c7, 2) ++#define RCP14_ETMACTR8() MRC14(1, c0, c8, 2) ++#define RCP14_ETMACTR9() MRC14(1, c0, c9, 2) ++#define RCP14_ETMACTR10() MRC14(1, c0, c10, 2) ++#define RCP14_ETMACTR11() MRC14(1, c0, c11, 2) ++#define RCP14_ETMACTR12() MRC14(1, c0, c12, 2) ++#define RCP14_ETMACTR13() MRC14(1, c0, c13, 2) ++#define RCP14_ETMACTR14() MRC14(1, c0, c14, 2) ++#define RCP14_ETMACTR15() MRC14(1, c0, c15, 2) ++#define RCP14_ETMDCVR0() MRC14(1, c0, c0, 3) ++#define RCP14_ETMDCVR2() MRC14(1, c0, c2, 3) ++#define RCP14_ETMDCVR4() MRC14(1, c0, c4, 3) ++#define RCP14_ETMDCVR6() MRC14(1, c0, c6, 3) ++#define RCP14_ETMDCVR8() MRC14(1, c0, c8, 3) ++#define RCP14_ETMDCVR10() MRC14(1, c0, c10, 3) ++#define RCP14_ETMDCVR12() MRC14(1, c0, c12, 3) ++#define RCP14_ETMDCVR14() MRC14(1, c0, c14, 3) ++#define RCP14_ETMDCMR0() MRC14(1, c0, c0, 4) ++#define RCP14_ETMDCMR2() MRC14(1, c0, c2, 4) ++#define RCP14_ETMDCMR4() MRC14(1, c0, c4, 4) ++#define RCP14_ETMDCMR6() MRC14(1, c0, c6, 4) ++#define RCP14_ETMDCMR8() MRC14(1, c0, c8, 4) ++#define RCP14_ETMDCMR10() MRC14(1, c0, c10, 4) ++#define RCP14_ETMDCMR12() MRC14(1, c0, c12, 4) ++#define RCP14_ETMDCMR14() MRC14(1, c0, c14, 4) ++#define RCP14_ETMCNTRLDVR0() MRC14(1, c0, c0, 5) ++#define RCP14_ETMCNTRLDVR1() MRC14(1, c0, c1, 5) ++#define RCP14_ETMCNTRLDVR2() MRC14(1, c0, c2, 5) ++#define RCP14_ETMCNTRLDVR3() MRC14(1, c0, c3, 5) ++#define RCP14_ETMCNTENR0() MRC14(1, c0, c4, 5) ++#define RCP14_ETMCNTENR1() MRC14(1, c0, c5, 5) ++#define RCP14_ETMCNTENR2() MRC14(1, c0, c6, 5) ++#define RCP14_ETMCNTENR3() MRC14(1, c0, c7, 5) ++#define RCP14_ETMCNTRLDEVR0() MRC14(1, c0, c8, 5) ++#define RCP14_ETMCNTRLDEVR1() MRC14(1, c0, c9, 5) ++#define RCP14_ETMCNTRLDEVR2() MRC14(1, c0, c10, 5) ++#define RCP14_ETMCNTRLDEVR3() MRC14(1, c0, c11, 5) ++#define RCP14_ETMCNTVR0() MRC14(1, c0, c12, 5) ++#define RCP14_ETMCNTVR1() MRC14(1, c0, c13, 5) ++#define RCP14_ETMCNTVR2() MRC14(1, c0, c14, 5) ++#define RCP14_ETMCNTVR3() MRC14(1, c0, c15, 5) ++#define RCP14_ETMSQ12EVR() MRC14(1, c0, c0, 6) ++#define RCP14_ETMSQ21EVR() MRC14(1, c0, c1, 6) ++#define RCP14_ETMSQ23EVR() MRC14(1, c0, c2, 6) ++#define RCP14_ETMSQ31EVR() MRC14(1, c0, c3, 6) ++#define RCP14_ETMSQ32EVR() MRC14(1, c0, c4, 6) ++#define RCP14_ETMSQ13EVR() MRC14(1, c0, c5, 6) ++#define RCP14_ETMSQR() MRC14(1, c0, c7, 6) ++#define RCP14_ETMEXTOUTEVR0() MRC14(1, c0, c8, 6) ++#define RCP14_ETMEXTOUTEVR1() MRC14(1, c0, c9, 6) ++#define RCP14_ETMEXTOUTEVR2() MRC14(1, c0, c10, 6) ++#define RCP14_ETMEXTOUTEVR3() MRC14(1, c0, c11, 6) ++#define RCP14_ETMCIDCVR0() MRC14(1, c0, c12, 6) ++#define RCP14_ETMCIDCVR1() MRC14(1, c0, c13, 6) ++#define RCP14_ETMCIDCVR2() MRC14(1, c0, c14, 6) ++#define RCP14_ETMCIDCMR() MRC14(1, c0, c15, 6) ++#define RCP14_ETMIMPSPEC0() MRC14(1, c0, c0, 7) ++#define RCP14_ETMIMPSPEC1() MRC14(1, c0, c1, 7) ++#define RCP14_ETMIMPSPEC2() MRC14(1, c0, c2, 7) ++#define RCP14_ETMIMPSPEC3() MRC14(1, c0, c3, 7) ++#define RCP14_ETMIMPSPEC4() MRC14(1, c0, c4, 7) ++#define RCP14_ETMIMPSPEC5() MRC14(1, c0, c5, 7) ++#define RCP14_ETMIMPSPEC6() MRC14(1, c0, c6, 7) ++#define RCP14_ETMIMPSPEC7() MRC14(1, c0, c7, 7) ++#define RCP14_ETMSYNCFR() MRC14(1, c0, c8, 7) ++#define RCP14_ETMIDR() MRC14(1, c0, c9, 7) ++#define RCP14_ETMCCER() MRC14(1, c0, c10, 7) ++#define RCP14_ETMEXTINSELR() MRC14(1, c0, c11, 7) ++#define RCP14_ETMTESSEICR() MRC14(1, c0, c12, 7) ++#define RCP14_ETMEIBCR() MRC14(1, c0, c13, 7) ++#define RCP14_ETMTSEVR() MRC14(1, c0, c14, 7) ++#define RCP14_ETMAUXCR() MRC14(1, c0, c15, 7) ++#define RCP14_ETMTRACEIDR() MRC14(1, c1, c0, 0) ++#define RCP14_ETMIDR2() MRC14(1, c1, c2, 0) ++#define RCP14_ETMVMIDCVR() MRC14(1, c1, c0, 1) ++#define RCP14_ETMOSLSR() MRC14(1, c1, c1, 4) ++/* Not available in PFTv1.1 */ ++#define RCP14_ETMOSSRR() MRC14(1, c1, c2, 4) ++#define RCP14_ETMPDCR() MRC14(1, c1, c4, 4) ++#define RCP14_ETMPDSR() MRC14(1, c1, c5, 4) ++#define RCP14_ETMITCTRL() MRC14(1, c7, c0, 4) ++#define RCP14_ETMCLAIMSET() MRC14(1, c7, c8, 6) ++#define RCP14_ETMCLAIMCLR() MRC14(1, c7, c9, 6) ++#define RCP14_ETMLSR() MRC14(1, c7, c13, 6) ++#define RCP14_ETMAUTHSTATUS() MRC14(1, c7, c14, 6) ++#define RCP14_ETMDEVID() MRC14(1, c7, c2, 7) ++#define RCP14_ETMDEVTYPE() MRC14(1, c7, c3, 7) ++#define RCP14_ETMPIDR4() MRC14(1, c7, c4, 7) ++#define RCP14_ETMPIDR5() MRC14(1, c7, c5, 7) ++#define RCP14_ETMPIDR6() MRC14(1, c7, c6, 7) ++#define RCP14_ETMPIDR7() MRC14(1, c7, c7, 7) ++#define RCP14_ETMPIDR0() MRC14(1, c7, c8, 7) ++#define RCP14_ETMPIDR1() MRC14(1, c7, c9, 7) ++#define RCP14_ETMPIDR2() MRC14(1, c7, c10, 7) ++#define RCP14_ETMPIDR3() MRC14(1, c7, c11, 7) ++#define RCP14_ETMCIDR0() MRC14(1, c7, c12, 7) ++#define RCP14_ETMCIDR1() MRC14(1, c7, c13, 7) ++#define RCP14_ETMCIDR2() MRC14(1, c7, c14, 7) ++#define RCP14_ETMCIDR3() MRC14(1, c7, c15, 7) ++ ++#define WCP14_ETMCR(val) MCR14(val, 1, c0, c0, 0) ++#define WCP14_ETMTRIGGER(val) MCR14(val, 1, c0, c2, 0) ++#define WCP14_ETMASICCR(val) MCR14(val, 1, c0, c3, 0) ++#define WCP14_ETMSR(val) MCR14(val, 1, c0, c4, 0) ++#define WCP14_ETMTSSCR(val) MCR14(val, 1, c0, c6, 0) ++#define WCP14_ETMTECR2(val) MCR14(val, 1, c0, c7, 0) ++#define WCP14_ETMTEEVR(val) MCR14(val, 1, c0, c8, 0) ++#define WCP14_ETMTECR1(val) MCR14(val, 1, c0, c9, 0) ++#define WCP14_ETMFFRR(val) MCR14(val, 1, c0, c10, 0) ++#define WCP14_ETMFFLR(val) MCR14(val, 1, c0, c11, 0) ++#define WCP14_ETMVDEVR(val) MCR14(val, 1, c0, c12, 0) ++#define WCP14_ETMVDCR1(val) MCR14(val, 1, c0, c13, 0) ++#define WCP14_ETMVDCR2(val) MCR14(val, 1, c0, c14, 0) ++#define WCP14_ETMVDCR3(val) MCR14(val, 1, c0, c15, 0) ++#define WCP14_ETMACVR0(val) MCR14(val, 1, c0, c0, 1) ++#define WCP14_ETMACVR1(val) MCR14(val, 1, c0, c1, 1) ++#define WCP14_ETMACVR2(val) MCR14(val, 1, c0, c2, 1) ++#define WCP14_ETMACVR3(val) MCR14(val, 1, c0, c3, 1) ++#define WCP14_ETMACVR4(val) MCR14(val, 1, c0, c4, 1) ++#define WCP14_ETMACVR5(val) MCR14(val, 1, c0, c5, 1) ++#define WCP14_ETMACVR6(val) MCR14(val, 1, c0, c6, 1) ++#define WCP14_ETMACVR7(val) MCR14(val, 1, c0, c7, 1) ++#define WCP14_ETMACVR8(val) MCR14(val, 1, c0, c8, 1) ++#define WCP14_ETMACVR9(val) MCR14(val, 1, c0, c9, 1) ++#define WCP14_ETMACVR10(val) MCR14(val, 1, c0, c10, 1) ++#define WCP14_ETMACVR11(val) MCR14(val, 1, c0, c11, 1) ++#define WCP14_ETMACVR12(val) MCR14(val, 1, c0, c12, 1) ++#define WCP14_ETMACVR13(val) MCR14(val, 1, c0, c13, 1) ++#define WCP14_ETMACVR14(val) MCR14(val, 1, c0, c14, 1) ++#define WCP14_ETMACVR15(val) MCR14(val, 1, c0, c15, 1) ++#define WCP14_ETMACTR0(val) MCR14(val, 1, c0, c0, 2) ++#define WCP14_ETMACTR1(val) MCR14(val, 1, c0, c1, 2) ++#define WCP14_ETMACTR2(val) MCR14(val, 1, c0, c2, 2) ++#define WCP14_ETMACTR3(val) MCR14(val, 1, c0, c3, 2) ++#define WCP14_ETMACTR4(val) MCR14(val, 1, c0, c4, 2) ++#define WCP14_ETMACTR5(val) MCR14(val, 1, c0, c5, 2) ++#define WCP14_ETMACTR6(val) MCR14(val, 1, c0, c6, 2) ++#define WCP14_ETMACTR7(val) MCR14(val, 1, c0, c7, 2) ++#define WCP14_ETMACTR8(val) MCR14(val, 1, c0, c8, 2) ++#define WCP14_ETMACTR9(val) MCR14(val, 1, c0, c9, 2) ++#define WCP14_ETMACTR10(val) MCR14(val, 1, c0, c10, 2) ++#define WCP14_ETMACTR11(val) MCR14(val, 1, c0, c11, 2) ++#define WCP14_ETMACTR12(val) MCR14(val, 1, c0, c12, 2) ++#define WCP14_ETMACTR13(val) MCR14(val, 1, c0, c13, 2) ++#define WCP14_ETMACTR14(val) MCR14(val, 1, c0, c14, 2) ++#define WCP14_ETMACTR15(val) MCR14(val, 1, c0, c15, 2) ++#define WCP14_ETMDCVR0(val) MCR14(val, 1, c0, c0, 3) ++#define WCP14_ETMDCVR2(val) MCR14(val, 1, c0, c2, 3) ++#define WCP14_ETMDCVR4(val) MCR14(val, 1, c0, c4, 3) ++#define WCP14_ETMDCVR6(val) MCR14(val, 1, c0, c6, 3) ++#define WCP14_ETMDCVR8(val) MCR14(val, 1, c0, c8, 3) ++#define WCP14_ETMDCVR10(val) MCR14(val, 1, c0, c10, 3) ++#define WCP14_ETMDCVR12(val) MCR14(val, 1, c0, c12, 3) ++#define WCP14_ETMDCVR14(val) MCR14(val, 1, c0, c14, 3) ++#define WCP14_ETMDCMR0(val) MCR14(val, 1, c0, c0, 4) ++#define WCP14_ETMDCMR2(val) MCR14(val, 1, c0, c2, 4) ++#define WCP14_ETMDCMR4(val) MCR14(val, 1, c0, c4, 4) ++#define WCP14_ETMDCMR6(val) MCR14(val, 1, c0, c6, 4) ++#define WCP14_ETMDCMR8(val) MCR14(val, 1, c0, c8, 4) ++#define WCP14_ETMDCMR10(val) MCR14(val, 1, c0, c10, 4) ++#define WCP14_ETMDCMR12(val) MCR14(val, 1, c0, c12, 4) ++#define WCP14_ETMDCMR14(val) MCR14(val, 1, c0, c14, 4) ++#define WCP14_ETMCNTRLDVR0(val) MCR14(val, 1, c0, c0, 5) ++#define WCP14_ETMCNTRLDVR1(val) MCR14(val, 1, c0, c1, 5) ++#define WCP14_ETMCNTRLDVR2(val) MCR14(val, 1, c0, c2, 5) ++#define WCP14_ETMCNTRLDVR3(val) MCR14(val, 1, c0, c3, 5) ++#define WCP14_ETMCNTENR0(val) MCR14(val, 1, c0, c4, 5) ++#define WCP14_ETMCNTENR1(val) MCR14(val, 1, c0, c5, 5) ++#define WCP14_ETMCNTENR2(val) MCR14(val, 1, c0, c6, 5) ++#define WCP14_ETMCNTENR3(val) MCR14(val, 1, c0, c7, 5) ++#define WCP14_ETMCNTRLDEVR0(val) MCR14(val, 1, c0, c8, 5) ++#define WCP14_ETMCNTRLDEVR1(val) MCR14(val, 1, c0, c9, 5) ++#define WCP14_ETMCNTRLDEVR2(val) MCR14(val, 1, c0, c10, 5) ++#define WCP14_ETMCNTRLDEVR3(val) MCR14(val, 1, c0, c11, 5) ++#define WCP14_ETMCNTVR0(val) MCR14(val, 1, c0, c12, 5) ++#define WCP14_ETMCNTVR1(val) MCR14(val, 1, c0, c13, 5) ++#define WCP14_ETMCNTVR2(val) MCR14(val, 1, c0, c14, 5) ++#define WCP14_ETMCNTVR3(val) MCR14(val, 1, c0, c15, 5) ++#define WCP14_ETMSQ12EVR(val) MCR14(val, 1, c0, c0, 6) ++#define WCP14_ETMSQ21EVR(val) MCR14(val, 1, c0, c1, 6) ++#define WCP14_ETMSQ23EVR(val) MCR14(val, 1, c0, c2, 6) ++#define WCP14_ETMSQ31EVR(val) MCR14(val, 1, c0, c3, 6) ++#define WCP14_ETMSQ32EVR(val) MCR14(val, 1, c0, c4, 6) ++#define WCP14_ETMSQ13EVR(val) MCR14(val, 1, c0, c5, 6) ++#define WCP14_ETMSQR(val) MCR14(val, 1, c0, c7, 6) ++#define WCP14_ETMEXTOUTEVR0(val) MCR14(val, 1, c0, c8, 6) ++#define WCP14_ETMEXTOUTEVR1(val) MCR14(val, 1, c0, c9, 6) ++#define WCP14_ETMEXTOUTEVR2(val) MCR14(val, 1, c0, c10, 6) ++#define WCP14_ETMEXTOUTEVR3(val) MCR14(val, 1, c0, c11, 6) ++#define WCP14_ETMCIDCVR0(val) MCR14(val, 1, c0, c12, 6) ++#define WCP14_ETMCIDCVR1(val) MCR14(val, 1, c0, c13, 6) ++#define WCP14_ETMCIDCVR2(val) MCR14(val, 1, c0, c14, 6) ++#define WCP14_ETMCIDCMR(val) MCR14(val, 1, c0, c15, 6) ++#define WCP14_ETMIMPSPEC0(val) MCR14(val, 1, c0, c0, 7) ++#define WCP14_ETMIMPSPEC1(val) MCR14(val, 1, c0, c1, 7) ++#define WCP14_ETMIMPSPEC2(val) MCR14(val, 1, c0, c2, 7) ++#define WCP14_ETMIMPSPEC3(val) MCR14(val, 1, c0, c3, 7) ++#define WCP14_ETMIMPSPEC4(val) MCR14(val, 1, c0, c4, 7) ++#define WCP14_ETMIMPSPEC5(val) MCR14(val, 1, c0, c5, 7) ++#define WCP14_ETMIMPSPEC6(val) MCR14(val, 1, c0, c6, 7) ++#define WCP14_ETMIMPSPEC7(val) MCR14(val, 1, c0, c7, 7) ++/* Can be read only in ETMv3.4, ETMv3.5 */ ++#define WCP14_ETMSYNCFR(val) MCR14(val, 1, c0, c8, 7) ++#define WCP14_ETMEXTINSELR(val) MCR14(val, 1, c0, c11, 7) ++#define WCP14_ETMTESSEICR(val) MCR14(val, 1, c0, c12, 7) ++#define WCP14_ETMEIBCR(val) MCR14(val, 1, c0, c13, 7) ++#define WCP14_ETMTSEVR(val) MCR14(val, 1, c0, c14, 7) ++#define WCP14_ETMAUXCR(val) MCR14(val, 1, c0, c15, 7) ++#define WCP14_ETMTRACEIDR(val) MCR14(val, 1, c1, c0, 0) ++#define WCP14_ETMIDR2(val) MCR14(val, 1, c1, c2, 0) ++#define WCP14_ETMVMIDCVR(val) MCR14(val, 1, c1, c0, 1) ++#define WCP14_ETMOSLAR(val) MCR14(val, 1, c1, c0, 4) ++/* Not available in PFTv1.1 */ ++#define WCP14_ETMOSSRR(val) MCR14(val, 1, c1, c2, 4) ++#define WCP14_ETMPDCR(val) MCR14(val, 1, c1, c4, 4) ++#define WCP14_ETMPDSR(val) MCR14(val, 1, c1, c5, 4) ++#define WCP14_ETMITCTRL(val) MCR14(val, 1, c7, c0, 4) ++#define WCP14_ETMCLAIMSET(val) MCR14(val, 1, c7, c8, 6) ++#define WCP14_ETMCLAIMCLR(val) MCR14(val, 1, c7, c9, 6) ++/* Writes to this from CP14 interface are ignored */ ++#define WCP14_ETMLAR(val) MCR14(val, 1, c7, c12, 6) ++ ++#endif +diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h +index 1805674..630a208 100644 +--- a/arch/arm/include/asm/io.h ++++ b/arch/arm/include/asm/io.h +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + /* + * ISA I/O bus memory addresses are 1:1 with the physical address. +@@ -37,6 +38,10 @@ + #define isa_page_to_bus page_to_phys + #define isa_bus_to_virt phys_to_virt + ++#include ++#include ++extern raw_spinlock_t hisilcon_lock; ++ + /* + * Atomic MMIO-wide IO modify + */ +@@ -63,6 +68,10 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); + */ + #define __raw_readw(a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a)) + #define __raw_writew(v,a) ((void)(__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v))) ++ ++#define __hi_raw_readw(a) __raw_readw(a) ++#define __hi_raw_writew(v,a) __raw_writew(v,a) ++ + #else + /* + * When running under a hypervisor, we want to avoid I/O accesses with +@@ -76,6 +85,23 @@ static inline void __raw_writew(u16 val, volatile void __iomem *addr) + : "r" (val)); + } + ++static inline void __hi_raw_writew(u16 val, volatile void __iomem *addr) ++{ ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++ unsigned long flags; ++ raw_spin_lock_irqsave(&hisilcon_lock, flags); ++ dsb(); ++ isb(); ++#endif ++ asm volatile("strh %1, %0" ++ : "+Q" (*(volatile u16 __force *)addr) ++ : "r" (val)); ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++ dsb(); ++ isb(); ++ raw_spin_unlock_irqrestore(&hisilcon_lock, flags); ++#endif ++} + static inline u16 __raw_readw(const volatile void __iomem *addr) + { + u16 val; +@@ -84,6 +110,27 @@ static inline u16 __raw_readw(const volatile void __iomem *addr) + "=r" (val)); + return val; + } ++ ++static inline u16 __hi_raw_readw(const volatile void __iomem *addr) ++{ ++ u16 val; ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++ unsigned long flags; ++ raw_spin_lock_irqsave(&hisilcon_lock, flags); ++ dsb(); ++ isb(); ++#endif ++ asm volatile("ldrh %1, %0" ++ : "+Q" (*(volatile u16 __force *)addr), ++ "=r" (val)); ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++ dsb(); ++ isb(); ++ raw_spin_unlock_irqrestore(&hisilcon_lock, flags); ++#endif ++ return val; ++} ++ + #endif + + static inline void __raw_writeb(u8 val, volatile void __iomem *addr) +@@ -93,6 +140,24 @@ static inline void __raw_writeb(u8 val, volatile void __iomem *addr) + : "r" (val)); + } + ++static inline void __hi_raw_writeb(u8 val, volatile void __iomem *addr) ++{ ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++ unsigned long flags; ++ raw_spin_lock_irqsave(&hisilcon_lock, flags); ++ dsb(); ++ isb(); ++#endif ++ asm volatile("strb %1, %0" ++ : "+Qo" (*(volatile u8 __force *)addr) ++ : "r" (val)); ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++ dsb(); ++ isb(); ++ raw_spin_unlock_irqrestore(&hisilcon_lock, flags); ++#endif ++} ++ + static inline void __raw_writel(u32 val, volatile void __iomem *addr) + { + asm volatile("str %1, %0" +@@ -100,6 +165,24 @@ static inline void __raw_writel(u32 val, volatile void __iomem *addr) + : "r" (val)); + } + ++static inline void __hi_raw_writel(u32 val, volatile void __iomem *addr) ++{ ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++ unsigned long flags; ++ raw_spin_lock_irqsave(&hisilcon_lock, flags); ++ dsb(); ++ isb(); ++#endif ++ asm volatile("str %1, %0" ++ : "+Qo" (*(volatile u32 __force *)addr) ++ : "r" (val)); ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++ dsb(); ++ isb(); ++ raw_spin_unlock_irqrestore(&hisilcon_lock, flags); ++#endif ++} ++ + static inline u8 __raw_readb(const volatile void __iomem *addr) + { + u8 val; +@@ -109,6 +192,26 @@ static inline u8 __raw_readb(const volatile void __iomem *addr) + return val; + } + ++static inline u8 __hi_raw_readb(const volatile void __iomem *addr) ++{ ++ u8 val; ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++ unsigned long flags; ++ raw_spin_lock_irqsave(&hisilcon_lock, flags); ++ dsb(); ++ isb(); ++#endif ++ asm volatile("ldrb %1, %0" ++ : "+Qo" (*(volatile u8 __force *)addr), ++ "=r" (val)); ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++ dsb(); ++ isb(); ++ raw_spin_unlock_irqrestore(&hisilcon_lock, flags); ++#endif ++ return val; ++} ++ + static inline u32 __raw_readl(const volatile void __iomem *addr) + { + u32 val; +@@ -118,6 +221,26 @@ static inline u32 __raw_readl(const volatile void __iomem *addr) + return val; + } + ++static inline u32 __hi_raw_readl(const volatile void __iomem *addr) ++{ ++ u32 val; ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++ unsigned long flags; ++ raw_spin_lock_irqsave(&hisilcon_lock, flags); ++ dsb(); ++ isb(); ++#endif ++ asm volatile("ldr %1, %0" ++ : "+Qo" (*(volatile u32 __force *)addr), ++ "=r" (val)); ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++ dsb(); ++ isb(); ++ raw_spin_unlock_irqrestore(&hisilcon_lock, flags); ++#endif ++ return val; ++} ++ + /* + * Architecture ioremap implementation. + */ +@@ -307,18 +430,36 @@ extern void _memset_io(volatile void __iomem *, int, size_t); + #define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \ + __raw_readl(c)); __r; }) + ++#define hi_readb_relaxed(c) ({ u8 __r = __hi_raw_readb(c); __r; }) ++#define hi_readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \ ++ __hi_raw_readw(c)); __r; }) ++#define hi_readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \ ++ __hi_raw_readl(c)); __r; }) ++ + #define writeb_relaxed(v,c) __raw_writeb(v,c) + #define writew_relaxed(v,c) __raw_writew((__force u16) cpu_to_le16(v),c) + #define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c) + ++#define hi_writeb_relaxed(v,c) __hi_raw_writeb(v,c) ++#define hi_writew_relaxed(v,c) __hi_raw_writew((__force u16) cpu_to_le16(v),c) ++#define hi_writel_relaxed(v,c) __hi_raw_writel((__force u32) cpu_to_le32(v),c) ++ + #define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; }) + #define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; }) + #define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; }) + ++#define hi_readb(c) ({ u8 __v = hi_readb_relaxed(c); __iormb(); __v; }) ++#define hi_readw(c) ({ u16 __v = hi_readw_relaxed(c); __iormb(); __v; }) ++#define hi_readl(c) ({ u32 __v = hi_readl_relaxed(c); __iormb(); __v; }) ++ + #define writeb(v,c) ({ __iowmb(); writeb_relaxed(v,c); }) + #define writew(v,c) ({ __iowmb(); writew_relaxed(v,c); }) + #define writel(v,c) ({ __iowmb(); writel_relaxed(v,c); }) + ++#define hi_writeb(v,c) ({ __iowmb(); hi_writeb_relaxed(v,c); }) ++#define hi_writew(v,c) ({ __iowmb(); hi_writew_relaxed(v,c); }) ++#define hi_writel(v,c) ({ __iowmb(); hi_writel_relaxed(v,c); }) ++ + #define readsb(p,d,l) __raw_readsb(p,d,l) + #define readsw(p,d,l) __raw_readsw(p,d,l) + #define readsl(p,d,l) __raw_readsl(p,d,l) +diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h +index 53c15de..809203a 100644 +--- a/arch/arm/include/asm/irq.h ++++ b/arch/arm/include/asm/irq.h +@@ -35,6 +35,9 @@ extern void (*handle_arch_irq)(struct pt_regs *); + extern void set_handle_irq(void (*handle_irq)(struct pt_regs *)); + #endif + ++void arch_trigger_all_cpu_backtrace(void); ++#define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace ++ + #endif + + #endif +diff --git a/arch/arm/include/asm/mach/mmc.h b/arch/arm/include/asm/mach/mmc.h +new file mode 100644 +index 0000000..bca864a +--- /dev/null ++++ b/arch/arm/include/asm/mach/mmc.h +@@ -0,0 +1,28 @@ ++/* ++ * arch/arm/include/asm/mach/mmc.h ++ */ ++#ifndef ASMARM_MACH_MMC_H ++#define ASMARM_MACH_MMC_H ++ ++#include ++#include ++#include ++ ++struct embedded_sdio_data { ++ struct sdio_cis cis; ++ struct sdio_cccr cccr; ++ struct sdio_embedded_func *funcs; ++ int num_funcs; ++}; ++ ++struct mmc_platform_data { ++ unsigned int ocr_mask; /* available voltages */ ++ int built_in; /* built-in device flag */ ++ int card_present; /* card detect state */ ++ u32 (*translate_vdd)(struct device *, unsigned int); ++ unsigned int (*status)(struct device *); ++ struct embedded_sdio_data *embedded_sdio; ++ int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id); ++}; ++ ++#endif +diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h +index e731018..c1668d1 100644 +--- a/arch/arm/include/asm/memory.h ++++ b/arch/arm/include/asm/memory.h +@@ -289,6 +289,9 @@ static inline void *phys_to_virt(phys_addr_t x) + */ + #define __pa(x) __virt_to_phys((unsigned long)(x)) + #define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x))) ++#ifdef CONFIG_HISI_SNAPSHOT_BOOT ++#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x), 0)) ++#endif + #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) + + extern phys_addr_t (*arch_virt_to_idmap)(unsigned long x); +diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h +index 18f5a55..7f31b4f 100644 +--- a/arch/arm/include/asm/smp.h ++++ b/arch/arm/include/asm/smp.h +@@ -81,6 +81,8 @@ extern void arch_send_wakeup_ipi_mask(const struct cpumask *mask); + + extern int register_ipi_completion(struct completion *completion, int cpu); + ++extern void smp_send_all_cpu_backtrace(void); ++ + struct smp_operations { + #ifdef CONFIG_SMP + /* +diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h +index 2fe85ff..d71d002 100644 +--- a/arch/arm/include/asm/topology.h ++++ b/arch/arm/include/asm/topology.h +@@ -23,11 +23,45 @@ extern struct cputopo_arm cpu_topology[NR_CPUS]; + void init_cpu_topology(void); + void store_cpu_topology(unsigned int cpuid); + const struct cpumask *cpu_coregroup_mask(int cpu); ++int cluster_to_logical_mask(unsigned int socket_id, cpumask_t *cluster_mask); ++ ++#ifdef CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE ++/* Common values for CPUs */ ++#ifndef SD_CPU_INIT ++#define SD_CPU_INIT (struct sched_domain) { \ ++ .min_interval = 1, \ ++ .max_interval = 4, \ ++ .busy_factor = 64, \ ++ .imbalance_pct = 125, \ ++ .cache_nice_tries = 1, \ ++ .busy_idx = 2, \ ++ .idle_idx = 1, \ ++ .newidle_idx = 0, \ ++ .wake_idx = 0, \ ++ .forkexec_idx = 0, \ ++ \ ++ .flags = 0*SD_LOAD_BALANCE \ ++ | 1*SD_BALANCE_NEWIDLE \ ++ | 1*SD_BALANCE_EXEC \ ++ | 1*SD_BALANCE_FORK \ ++ | 0*SD_BALANCE_WAKE \ ++ | 1*SD_WAKE_AFFINE \ ++ | 0*SD_SHARE_CPUPOWER \ ++ | 0*SD_SHARE_PKG_RESOURCES \ ++ | 0*SD_SERIALIZE \ ++ , \ ++ .last_balance = jiffies, \ ++ .balance_interval = 1, \ ++} ++#endif ++#endif /* CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE */ + + #else + + static inline void init_cpu_topology(void) { } + static inline void store_cpu_topology(unsigned int cpuid) { } ++static inline int cluster_to_logical_mask(unsigned int socket_id, ++ cpumask_t *cluster_mask) { return -EINVAL; } + + #endif + +diff --git a/arch/arm/include/mach/hi3516av200_io.h b/arch/arm/include/mach/hi3516av200_io.h +new file mode 100644 +index 0000000..eb992fe +--- /dev/null ++++ b/arch/arm/include/mach/hi3516av200_io.h +@@ -0,0 +1,46 @@ ++#ifndef __HI3516AV200_IO_H ++#define __HI3516AV200_IO_H ++ ++#ifdef CONFIG_PCI ++#define IO_SPACE_LIMIT 0xffffffff ++#define __io(a) __typesafe_io(PCI_IO_VIRT_BASE + ((a) & IO_SPACE_LIMIT)) ++#endif ++ ++/* phys_addr virt_addr ++ * 0x1000_0000 <-----> 0xFE00_0000 ++ */ ++#define HI3516AV200_IOCH1_VIRT (0xFE000000) ++#define HI3516AV200_IOCH1_PHYS (0x10000000) ++#define HI3516AV200_IOCH1_SIZE (0x00310000) ++ ++/* phys_addr virt_addr ++ * 0x11000000 <-----> 0xFE400000 ++ */ ++#define HI3516AV200_IOCH2_VIRT (0xFE400000) ++#define HI3516AV200_IOCH2_PHYS (0x11000000) ++#define HI3516AV200_IOCH2_SIZE (0x004F0000) ++ ++/* phys_addr virt_addr ++ * 0x12000000 <-----> 0xFE900000 ++ */ ++#define HI3516AV200_IOCH3_VIRT (0xFE900000) ++#define HI3516AV200_IOCH3_PHYS (0x12000000) ++#define HI3516AV200_IOCH3_SIZE (0x00170000) ++ ++ ++#define IO_OFFSET_LOW (0xEC900000) ++#define IO_OFFSET_MID (0xED400000) ++#define IO_OFFSET_HIGH (0xEE000000) ++ ++#define IO_ADDRESS_LOW(x) ((x) + IO_OFFSET_LOW) ++#define IO_ADDRESS_MID(x) ((x) + IO_OFFSET_MID) ++#define IO_ADDRESS_HIGH(x) ((x) + IO_OFFSET_HIGH) ++ ++#define __IO_ADDRESS(x) ((x >= HI3516AV200_IOCH2_PHYS) ? IO_ADDRESS_MID(x)\ ++ : IO_ADDRESS_HIGH(x)) ++#define IO_ADDRESS(x) ((x) >= HI3516AV200_IOCH3_PHYS ? IO_ADDRESS_LOW(x)\ ++ : __IO_ADDRESS(x)) ++ ++#define __io_address(n) (IOMEM(IO_ADDRESS(n))) ++ ++#endif +diff --git a/arch/arm/include/mach/hi3516av200_platform.h b/arch/arm/include/mach/hi3516av200_platform.h +new file mode 100644 +index 0000000..a7aaa25 +--- /dev/null ++++ b/arch/arm/include/mach/hi3516av200_platform.h +@@ -0,0 +1,164 @@ ++#ifndef __HI3516AV200_CHIP_REGS_H__ ++#define __HI3516AV200_CHIP_REGS_H__ ++ ++/* SRAM Base Address Register */ ++#define SRAM_BASE_ADDRESS 0x4010000 ++ ++#define REG_BASE_TIMER01 0x12000000 ++#define REG_BASE_TIMER23 0x12001000 ++ ++/* -------------------------------------------------------------------- */ ++/* Clock and Reset Generator REG */ ++/* -------------------------------------------------------------------- */ ++#define CRG_REG_BASE 0x12010000 ++#define REG_BASE_CRG CRG_REG_BASE ++ ++#define REG_CRG48 0x00c0 ++ ++/* FMC CRG register offset */ ++#define REG_FMC_CRG REG_CRG48 ++#define FMC_CLK_SEL(_clk) (((_clk) & 0x7) << 2) ++#define FMC_CLK_SEL_MASK (0x7 << 2) ++#define GET_FMC_CLK_TYPE(_reg) (((_reg) >> 2) & 0x7) ++/* SDR/DDR clock */ ++#define FMC_CLK_24M 0 ++#define FMC_CLK_75M 1 ++#define FMC_CLK_125M 2 ++#define FMC_CLK_150M 3 ++#define FMC_CLK_200M 4 ++#define FMC_CLK_250M 5 ++/* Only DDR clock */ ++#define FMC_CLK_300M 6 ++#define FMC_CLK_400M 7 ++#define FMC_CLK_ENABLE (0x1 << 1) ++#define FMC_SOFT_RST_REQ (0x1 << 0) ++ ++#define REG_BASE_UART0 0x12100000 ++#define REG_BASE_UART1 0x12101000 ++#define REG_BASE_UART2 0x12102000 ++#define REG_BASE_UART3 0x12103000 ++#define REG_BASE_UART4 0x12104000 ++#define REG_BASE_CUR_UART REG_BASE_UART0 ++ ++#define PMC_BASE 0x120a0000 ++ ++#define CCI_BASE 0x1ff00000 ++#define CCI_PORT0_BASE 0x1ff01000 ++#define CCI_PORT1_BASE 0x1ff02000 ++ ++ ++#define REG_BASE_A7_PERI 0x10300000 ++ ++/*CORTTX-A7 MPCORE MEMORY REGION*/ ++#define REG_A7_PERI_SCU 0x0000 ++#define REG_A7_PERI_GIC_CPU 0x2000 ++#define REG_A7_PERI_GLOBAL_TIMER 0x0200 ++#define REG_A7_PERI_PRI_TIMER_WDT 0x0600 ++#define REG_A7_PERI_GIC_DIST 0x1000 ++/* -------------------------------------------------------------------- */ ++/* System Control REG */ ++/* -------------------------------------------------------------------- */ ++#define SYS_CTRL_BASE 0x12020000 ++ ++/* System Control register offset */ ++#define REG_SC_CTRL 0x0000 ++ ++/* System soft reset register offset */ ++#define REG_SC_SYSRES 0x0004 ++ ++/* System Status register offset */ ++#define REG_SC_STAT 0x008c ++ ++/* if bit[5:4]=00b: boot form SPI && bit[3]=0: SPI nor flash ++ * bit[7]=0: 3-Byte address mode; bit[7]=1: 4-Byte address mode */ ++#define GET_SPI_NOR_ADDR_MODE(_reg) (((_reg) >> 7) & 0x1) ++#define GET_SYS_BOOT_MODE(_reg) (((_reg) >> 4) & 0x3) ++#define BOOT_MODE_MASK ((0x3) << 4) ++#define BOOT_FROM_SPI 0 ++#define BOOT_FROM_NAND 1 ++#define BOOT_FROM_EMMC 2 ++#define BOOT_FROM_DDR 3 ++/* bit[3]=0; SPI nor flash; bit[3]=1: SPI nand flash */ ++#define GET_SPI_DEVICE_TYPE(_reg) (((_reg) >> 3) & 0x1) ++ ++#define REG_SC_XTALCTRL 0x0010 ++#define REG_SC_APLLCTRL 0x0014 ++#define REG_SC_APLLFREQCTRL0 0x0018 ++#define REG_SC_APLLFREQCTRL1 0x001C ++#define REG_SC_VPLL0FREQCTRL0 0x0020 ++#define REG_SC_VPLL0FREQCTRL1 0x0024 ++#define REG_SC_VPLL1FREQCTRL0 0x0028 ++#define REG_SC_VPLL1FREQCTRL1 0x002C ++#define REG_SC_EPLLFREQCTRL0 0x0030 ++#define REG_SC_EPLLFREQCTRL1 0x0034 ++#define REG_SC_QPLLFREQCTRL0 0x0038 ++#define REG_SC_QPLLFREQCTRL1 0x003C ++#define REG_SC_LOW_POWER_CTRL 0x0040 ++#define REG_SC_IO_REUSE_SEL 0x0044 ++#define REG_SC_SRST_REQ_CTRL 0x0048 ++#define REG_SC_CA_RST_CTRL 0x004C ++#define REG_SC_WDG_RST_CTRL 0x0050 ++#define REG_SC_DDRC_DFI_RST_CTRL 0x0054 ++#define REG_SC_PLLLOCK_STAT 0x0070 ++#define REG_SC_GEN0 0x0080 ++#define REG_SC_GEN1 0x0084 ++#define REG_SC_GEN2 0x0088 ++#define REG_SC_GEN3 0x008C ++#define REG_SC_GEN4 0x0090 ++#define REG_SC_GEN5 0x0094 ++#define REG_SC_GEN6 0x0098 ++#define REG_SC_GEN7 0x009C ++#define REG_SC_GEN8 0x00A0 ++#define REG_SC_GEN9 0x00A4 ++#define REG_SC_GEN10 0x00A8 ++#define REG_SC_GEN11 0x00AC ++#define REG_SC_GEN12 0x00B0 ++#define REG_SC_GEN13 0x00B4 ++#define REG_SC_GEN14 0x00B8 ++#define REG_SC_GEN15 0x00BC ++#define REG_SC_GEN16 0x00C0 ++#define REG_SC_GEN17 0x00C4 ++#define REG_SC_GEN18 0x00C8 ++#define REG_SC_GEN19 0x00CC ++#define REG_SC_GEN20 0x00D0 ++#define REG_SC_GEN21 0x00D4 ++#define REG_SC_GEN22 0x00D8 ++#define REG_SC_GEN23 0x00DC ++#define REG_SC_GEN24 0x00E0 ++#define REG_SC_GEN25 0x00E4 ++#define REG_SC_GEN26 0x00E8 ++#define REG_SC_GEN27 0x00EC ++#define REG_SC_GEN28 0x00F0 ++#define REG_SC_GEN29 0x00F4 ++#define REG_SC_GEN30 0x00F8 ++#define REG_SC_GEN31 0x00FC ++#define REG_SC_LOCKEN 0x020C ++#define REG_SC_SYSID0 0x0EE0 ++#define REG_SC_SYSID1 0x0EE4 ++#define REG_SC_SYSID2 0x0EE8 ++#define REG_SC_SYSID3 0x0EEC ++ ++/*#define REG_BASE_WDG0 0xF8A2C000 */ ++ ++#define REG_PERI_CRG94 0x178 ++#define REG_PERI_CRG10 0x0028 ++#define REG_PERI_CRG98 0x0188 ++ ++#define CFG_GIC_CPU_BASE (IO_ADDRESS(REG_BASE_A7_PERI)\ ++ + REG_A7_PERI_GIC_CPU) ++#define CFG_GIC_DIST_BASE (IO_ADDRESS(REG_BASE_A7_PERI)\ ++ + REG_A7_PERI_GIC_DIST) ++ ++ ++/*********************************************************************/ ++/* ++ * 0x1-> init item1 ++ * 0x2-> init item2 ++ * 0x3->init item1 & item2 ++ */ ++#define INIT_REG_ITEM1 1 ++#define INIT_REG_ITEM2 2 ++#define INIT_REG_ITEM1_ITEM2 (INIT_REG_ITEM1 | INIT_REG_ITEM2) ++ ++ ++#endif /* End of __HI_CHIP_REGS_H__ */ +diff --git a/arch/arm/include/mach/hi3519_io.h b/arch/arm/include/mach/hi3519_io.h +new file mode 100644 +index 0000000..108d401 +--- /dev/null ++++ b/arch/arm/include/mach/hi3519_io.h +@@ -0,0 +1,46 @@ ++#ifndef __HI3519_IO_H ++#define __HI3519_IO_H ++ ++#ifdef CONFIG_PCI ++#define IO_SPACE_LIMIT 0xffffffff ++#define __io(a) __typesafe_io(PCI_IO_VIRT_BASE + ((a) & IO_SPACE_LIMIT)) ++#endif ++ ++/* phys_addr virt_addr ++ * 0x1000_0000 <-----> 0xFE00_0000 ++ */ ++#define HI3519_IOCH1_VIRT (0xFE000000) ++#define HI3519_IOCH1_PHYS (0x10000000) ++#define HI3519_IOCH1_SIZE (0x00310000) ++ ++/* phys_addr virt_addr ++ * 0x11000000 <-----> 0xFE400000 ++ */ ++#define HI3519_IOCH2_VIRT (0xFE400000) ++#define HI3519_IOCH2_PHYS (0x11000000) ++#define HI3519_IOCH2_SIZE (0x003F0000) ++ ++/* phys_addr virt_addr ++ * 0x12000000 <-----> 0xFE800000 ++ */ ++#define HI3519_IOCH3_VIRT (0xFE800000) ++#define HI3519_IOCH3_PHYS (0x12000000) ++#define HI3519_IOCH3_SIZE (0x00170000) ++ ++ ++#define IO_OFFSET_LOW (0xEC800000) ++#define IO_OFFSET_MID (0xED400000) ++#define IO_OFFSET_HIGH (0xEE000000) ++ ++#define IO_ADDRESS_LOW(x) ((x) + IO_OFFSET_LOW) ++#define IO_ADDRESS_MID(x) ((x) + IO_OFFSET_MID) ++#define IO_ADDRESS_HIGH(x) ((x) + IO_OFFSET_HIGH) ++ ++#define __IO_ADDRESS(x) ((x >= HI3519_IOCH2_PHYS) ? IO_ADDRESS_MID(x)\ ++ : IO_ADDRESS_HIGH(x)) ++#define IO_ADDRESS(x) ((x) >= HI3519_IOCH3_PHYS ? IO_ADDRESS_LOW(x)\ ++ : __IO_ADDRESS(x)) ++ ++#define __io_address(n) (IOMEM(IO_ADDRESS(n))) ++ ++#endif +diff --git a/arch/arm/include/mach/hi3519_platform.h b/arch/arm/include/mach/hi3519_platform.h +new file mode 100644 +index 0000000..b845f33 +--- /dev/null ++++ b/arch/arm/include/mach/hi3519_platform.h +@@ -0,0 +1,164 @@ ++#ifndef __HI3519_CHIP_REGS_H__ ++#define __HI3519_CHIP_REGS_H__ ++ ++/* SRAM Base Address Register */ ++#define SRAM_BASE_ADDRESS 0x4010000 ++ ++#define REG_BASE_TIMER01 0x12000000 ++#define REG_BASE_TIMER23 0x12001000 ++ ++/* -------------------------------------------------------------------- */ ++/* Clock and Reset Generator REG */ ++/* -------------------------------------------------------------------- */ ++#define CRG_REG_BASE 0x12010000 ++#define REG_BASE_CRG CRG_REG_BASE ++ ++#define REG_CRG48 0x00c0 ++ ++/* FMC CRG register offset */ ++#define REG_FMC_CRG REG_CRG48 ++#define FMC_CLK_SEL(_clk) (((_clk) & 0x7) << 2) ++#define FMC_CLK_SEL_MASK (0x7 << 2) ++#define GET_FMC_CLK_TYPE(_reg) (((_reg) >> 2) & 0x7) ++/* SDR/DDR clock */ ++#define FMC_CLK_24M 0 ++#define FMC_CLK_75M 1 ++#define FMC_CLK_125M 2 ++#define FMC_CLK_150M 3 ++#define FMC_CLK_200M 4 ++#define FMC_CLK_250M 5 ++/* Only DDR clock */ ++#define FMC_CLK_300M 6 ++#define FMC_CLK_400M 7 ++#define FMC_CLK_ENABLE (0x1 << 1) ++#define FMC_SOFT_RST_REQ (0x1 << 0) ++ ++#define REG_BASE_UART0 0x12100000 ++#define REG_BASE_UART1 0x12101000 ++#define REG_BASE_UART2 0x12102000 ++#define REG_BASE_UART3 0x12103000 ++#define REG_BASE_UART4 0x12104000 ++#define REG_BASE_CUR_UART REG_BASE_UART0 ++ ++#define PMC_BASE 0x120a0000 ++ ++#define CCI_BASE 0x1ff00000 ++#define CCI_PORT0_BASE 0x1ff01000 ++#define CCI_PORT1_BASE 0x1ff02000 ++ ++ ++#define REG_BASE_A7_PERI 0x10300000 ++ ++/*CORTTX-A7 MPCORE MEMORY REGION*/ ++#define REG_A7_PERI_SCU 0x0000 ++#define REG_A7_PERI_GIC_CPU 0x2000 ++#define REG_A7_PERI_GLOBAL_TIMER 0x0200 ++#define REG_A7_PERI_PRI_TIMER_WDT 0x0600 ++#define REG_A7_PERI_GIC_DIST 0x1000 ++/* -------------------------------------------------------------------- */ ++/* System Control REG */ ++/* -------------------------------------------------------------------- */ ++#define SYS_CTRL_BASE 0x12020000 ++ ++/* System Control register offset */ ++#define REG_SC_CTRL 0x0000 ++ ++/* System soft reset register offset */ ++#define REG_SC_SYSRES 0x0004 ++ ++/* System Status register offset */ ++#define REG_SC_STAT 0x008c ++ ++/* if bit[5:4]=00b: boot form SPI && bit[3]=0: SPI nor flash ++ * bit[7]=0: 3-Byte address mode; bit[7]=1: 4-Byte address mode */ ++#define GET_SPI_NOR_ADDR_MODE(_reg) (((_reg) >> 7) & 0x1) ++#define GET_SYS_BOOT_MODE(_reg) (((_reg) >> 4) & 0x3) ++#define BOOT_MODE_MASK ((0x3) << 4) ++#define BOOT_FROM_SPI 0 ++#define BOOT_FROM_NAND 1 ++#define BOOT_FROM_EMMC 2 ++#define BOOT_FROM_DDR 3 ++/* bit[3]=0; SPI nor flash; bit[3]=1: SPI nand flash */ ++#define GET_SPI_DEVICE_TYPE(_reg) (((_reg) >> 3) & 0x1) ++ ++#define REG_SC_XTALCTRL 0x0010 ++#define REG_SC_APLLCTRL 0x0014 ++#define REG_SC_APLLFREQCTRL0 0x0018 ++#define REG_SC_APLLFREQCTRL1 0x001C ++#define REG_SC_VPLL0FREQCTRL0 0x0020 ++#define REG_SC_VPLL0FREQCTRL1 0x0024 ++#define REG_SC_VPLL1FREQCTRL0 0x0028 ++#define REG_SC_VPLL1FREQCTRL1 0x002C ++#define REG_SC_EPLLFREQCTRL0 0x0030 ++#define REG_SC_EPLLFREQCTRL1 0x0034 ++#define REG_SC_QPLLFREQCTRL0 0x0038 ++#define REG_SC_QPLLFREQCTRL1 0x003C ++#define REG_SC_LOW_POWER_CTRL 0x0040 ++#define REG_SC_IO_REUSE_SEL 0x0044 ++#define REG_SC_SRST_REQ_CTRL 0x0048 ++#define REG_SC_CA_RST_CTRL 0x004C ++#define REG_SC_WDG_RST_CTRL 0x0050 ++#define REG_SC_DDRC_DFI_RST_CTRL 0x0054 ++#define REG_SC_PLLLOCK_STAT 0x0070 ++#define REG_SC_GEN0 0x0080 ++#define REG_SC_GEN1 0x0084 ++#define REG_SC_GEN2 0x0088 ++#define REG_SC_GEN3 0x008C ++#define REG_SC_GEN4 0x0090 ++#define REG_SC_GEN5 0x0094 ++#define REG_SC_GEN6 0x0098 ++#define REG_SC_GEN7 0x009C ++#define REG_SC_GEN8 0x00A0 ++#define REG_SC_GEN9 0x00A4 ++#define REG_SC_GEN10 0x00A8 ++#define REG_SC_GEN11 0x00AC ++#define REG_SC_GEN12 0x00B0 ++#define REG_SC_GEN13 0x00B4 ++#define REG_SC_GEN14 0x00B8 ++#define REG_SC_GEN15 0x00BC ++#define REG_SC_GEN16 0x00C0 ++#define REG_SC_GEN17 0x00C4 ++#define REG_SC_GEN18 0x00C8 ++#define REG_SC_GEN19 0x00CC ++#define REG_SC_GEN20 0x00D0 ++#define REG_SC_GEN21 0x00D4 ++#define REG_SC_GEN22 0x00D8 ++#define REG_SC_GEN23 0x00DC ++#define REG_SC_GEN24 0x00E0 ++#define REG_SC_GEN25 0x00E4 ++#define REG_SC_GEN26 0x00E8 ++#define REG_SC_GEN27 0x00EC ++#define REG_SC_GEN28 0x00F0 ++#define REG_SC_GEN29 0x00F4 ++#define REG_SC_GEN30 0x00F8 ++#define REG_SC_GEN31 0x00FC ++#define REG_SC_LOCKEN 0x020C ++#define REG_SC_SYSID0 0x0EE0 ++#define REG_SC_SYSID1 0x0EE4 ++#define REG_SC_SYSID2 0x0EE8 ++#define REG_SC_SYSID3 0x0EEC ++ ++/*#define REG_BASE_WDG0 0xF8A2C000 */ ++ ++#define REG_PERI_CRG94 0x178 ++#define REG_PERI_CRG10 0x0028 ++#define REG_PERI_CRG98 0x0188 ++ ++#define CFG_GIC_CPU_BASE (IO_ADDRESS(REG_BASE_A7_PERI)\ ++ + REG_A7_PERI_GIC_CPU) ++#define CFG_GIC_DIST_BASE (IO_ADDRESS(REG_BASE_A7_PERI)\ ++ + REG_A7_PERI_GIC_DIST) ++ ++ ++/*********************************************************************/ ++/* ++ * 0x1-> init item1 ++ * 0x2-> init item2 ++ * 0x3->init item1 & item2 ++ */ ++#define INIT_REG_ITEM1 1 ++#define INIT_REG_ITEM2 2 ++#define INIT_REG_ITEM1_ITEM2 (INIT_REG_ITEM1 | INIT_REG_ITEM2) ++ ++ ++#endif /* End of __HI_CHIP_REGS_H__ */ +diff --git a/arch/arm/include/mach/hi3519v101_io.h b/arch/arm/include/mach/hi3519v101_io.h +new file mode 100644 +index 0000000..7083af5 +--- /dev/null ++++ b/arch/arm/include/mach/hi3519v101_io.h +@@ -0,0 +1,46 @@ ++#ifndef __HI3519_IO_H ++#define __HI3519_IO_H ++ ++#ifdef CONFIG_PCI ++#define IO_SPACE_LIMIT 0xffffffff ++#define __io(a) __typesafe_io(PCI_IO_VIRT_BASE + ((a) & IO_SPACE_LIMIT)) ++#endif ++ ++/* phys_addr virt_addr ++ * 0x1000_0000 <-----> 0xFE00_0000 ++ */ ++#define HI3519_IOCH1_VIRT (0xFE000000) ++#define HI3519_IOCH1_PHYS (0x10000000) ++#define HI3519_IOCH1_SIZE (0x00310000) ++ ++/* phys_addr virt_addr ++ * 0x11000000 <-----> 0xFE400000 ++ */ ++#define HI3519_IOCH2_VIRT (0xFE400000) ++#define HI3519_IOCH2_PHYS (0x11000000) ++#define HI3519_IOCH2_SIZE (0x004F0000) ++ ++/* phys_addr virt_addr ++ * 0x12000000 <-----> 0xFE900000 ++ */ ++#define HI3519_IOCH3_VIRT (0xFE900000) ++#define HI3519_IOCH3_PHYS (0x12000000) ++#define HI3519_IOCH3_SIZE (0x00170000) ++ ++ ++#define IO_OFFSET_LOW (0xEC900000) ++#define IO_OFFSET_MID (0xED400000) ++#define IO_OFFSET_HIGH (0xEE000000) ++ ++#define IO_ADDRESS_LOW(x) ((x) + IO_OFFSET_LOW) ++#define IO_ADDRESS_MID(x) ((x) + IO_OFFSET_MID) ++#define IO_ADDRESS_HIGH(x) ((x) + IO_OFFSET_HIGH) ++ ++#define __IO_ADDRESS(x) ((x >= HI3519_IOCH2_PHYS) ? IO_ADDRESS_MID(x)\ ++ : IO_ADDRESS_HIGH(x)) ++#define IO_ADDRESS(x) ((x) >= HI3519_IOCH3_PHYS ? IO_ADDRESS_LOW(x)\ ++ : __IO_ADDRESS(x)) ++ ++#define __io_address(n) (IOMEM(IO_ADDRESS(n))) ++ ++#endif +diff --git a/arch/arm/include/mach/hi3521d_io.h b/arch/arm/include/mach/hi3521d_io.h +new file mode 100644 +index 0000000..ed686f8 +--- /dev/null ++++ b/arch/arm/include/mach/hi3521d_io.h +@@ -0,0 +1,43 @@ ++#ifndef __HI3521D_IO_H ++#define __HI3521D_IO_H ++ ++/* phys_addr virt_addr ++ * 0x1000_0000 <-----> 0xFE00_0000 ++ * 0x1004_0000 <-----> 0xFE04_0000 ++ */ ++#define HI3521D_IOCH1_VIRT (0xFE000000) ++#define HI3521D_IOCH1_PHYS (0x10000000) ++#define HI3521D_IOCH1_SIZE (0x00400000) ++ ++/* phys_addr virt_addr ++ * 0x1200_0000 <-----> 0xFE4_00000 ++ * 0x1223_0000 <-----> 0xFE63_0000 ++ */ ++#define HI3521D_IOCH2_VIRT (0xFE400000) ++#define HI3521D_IOCH2_PHYS (0x12000000) ++#define HI3521D_IOCH2_SIZE (0x00230000) ++ ++/* phys_addr virt_addr ++ * 0x1300_0000 <-----> 0xFE70_0000 ++ * 0x1316_0000 <-----> 0xFE86_0000 ++ */ ++#define HI3521D_IOCH3_VIRT (0xFE700000) ++#define HI3521D_IOCH3_PHYS (0x13000000) ++#define HI3521D_IOCH3_SIZE (0x00160000) ++ ++#define IO_OFFSET_LOW (0xEB700000) ++#define IO_OFFSET_MID (0xEC400000) ++#define IO_OFFSET_HIGH (0xEE000000) ++ ++#define IO_ADDRESS_LOW(x) ((x) + IO_OFFSET_LOW) ++#define IO_ADDRESS_MID(x) ((x) + IO_OFFSET_MID) ++#define IO_ADDRESS_HIGH(x) ((x) + IO_OFFSET_HIGH) ++ ++#define __IO_ADDRESS_HIGH(x) ((x >= HI3521D_IOCH2_PHYS) ? IO_ADDRESS_MID(x) \ ++ : IO_ADDRESS_HIGH(x)) ++#define IO_ADDRESS(x) ((x) >= HI3521D_IOCH3_PHYS ? IO_ADDRESS_LOW(x) \ ++ : __IO_ADDRESS_HIGH(x)) ++ ++#define __io_address(x) (IOMEM(IO_ADDRESS(x))) ++ ++#endif +diff --git a/arch/arm/include/mach/hi3521d_platform.h b/arch/arm/include/mach/hi3521d_platform.h +new file mode 100644 +index 0000000..ac2d8b6 +--- /dev/null ++++ b/arch/arm/include/mach/hi3521d_platform.h +@@ -0,0 +1,88 @@ ++#ifndef __HI3521D_CHIP_REGS_H__ ++#define __HI3521D_CHIP_REGS_H__ ++ ++/* -------------------------------------------------------------------- */ ++/* SRAM Base Address Register */ ++#define SRAM_BASE_ADDRESS 0x04010000 ++ ++/* -------------------------------------------------------------------- */ ++/*CORTTX-A7 MPCORE MEMORY REGION*/ ++/* -------------------------------------------------------------------- */ ++#define REG_BASE_A7_PERI 0x10300000 ++#define A7_PERI_BASE REG_BASE_A7_PERI ++ ++#define REG_A7_PERI_SCU 0x0000 ++ ++/* -------------------------------------------------------------------- */ ++/* Clock and Reset Generator REG */ ++/* -------------------------------------------------------------------- */ ++#define REG_BASE_CRG 0x12040000 ++#define CRG_REG_BASE REG_BASE_CRG ++ ++#define REG_CRG32 0x0080 ++ ++/* A7 soft reset request register offset */ ++#define REG_A7_SRST_CRG REG_CRG32 ++#define DBG1_SRST_REQ BIT(4) ++#define CORE1_SRST_REQ BIT(2) ++ ++/* Ethernet CRG register offset */ ++#define REG_ETH_CRG 0x014C ++#define REG_ETH_MAC_IF 0x008C ++ ++#define UART_CKSEL_MASK (0x3 << 18) ++#define UART_CKSEL_24M (0x2 << 18) ++ ++#define REG_BASE_CUR_UART REG_BASE_UART0 ++ ++/*********************************************************************/ ++#define A7_AXI_SCALE_REG IO_ADDRESS(REG_BASE_CRG + 0x50) ++ ++/* -------------------------------------------------------------------- */ ++#define DDR_MEM_BASE 0x80000000 ++#define CFG_TIMER_PER (4) /* AXI:APB is 4:1 */ ++/* -------------------------------------------------------------------- */ ++#define get_bus_clk() ({ \ ++ unsigned long tmp_reg, busclk = 0;\ ++ tmp_reg = readl((void *)A7_AXI_SCALE_REG);\ ++ tmp_reg = (tmp_reg >> 2) & 0x3;\ ++ if (0x3 == tmp_reg) {\ ++ busclk = 300000000;\ ++ } else if (0x1 == tmp_reg) {\ ++ busclk = 200000000;\ ++ } \ ++ busclk;\ ++}) ++ ++/* hisilicon satav200 register */ ++#define HI_SATA_PORT_FIFOTH 0x44 ++#define HI_SATA_PORT_PHYCTL1 0x48 ++#define HI_SATA_PORT_PHYCTL 0x74 ++ ++#define HI_SATA_PHY_CTL0 0xA0 ++#define HI_SATA_PHY_CTL1 0xA4 ++#define HI_SATA_PHY_CTL2 0xB0 ++#define HI_SATA_PHY_RST_BACK_MASK 0xAC ++ ++#define HI_SATA_FIFOTH_VALUE 0xFEED9F24 ++ ++#define HI_SATA_BIGENDINE (1 << 3) ++ ++#define HI_SATA_PHY_MODE_1_5G 0 ++#define HI_SATA_PHY_MODE_3G 1 ++#define HI_SATA_PHY_MODE_6G 2 ++ ++#define HI_SATA_PHY_1_5G 0x0e180000 ++#define HI_SATA_PHY_3G 0x0e390000 ++#define HI_SATA_PHY_6G 0x0e5a0000 ++ ++#define HI_SATA_PHY_SG_1_5G 0x50438 ++#define HI_SATA_PHY_SG_3G 0x50438 ++#define HI_SATA_PHY_SG_6G 0x50438 ++ ++#define HI_SATA_MISC_CTRL IO_ADDRESS(0x12120000) ++#define HI_SATA_MISC_SATA_PHY0 (HI_SATA_MISC_CTRL + 0x58) ++#define HI_SATA_MISC_SATA_PHY1 (HI_SATA_MISC_CTRL + 0x64) ++ ++#endif /* End of __HI_CHIP_REGS_H__ */ ++ +diff --git a/arch/arm/include/mach/hi3531d_io.h b/arch/arm/include/mach/hi3531d_io.h +new file mode 100644 +index 0000000..6d2640e +--- /dev/null ++++ b/arch/arm/include/mach/hi3531d_io.h +@@ -0,0 +1,61 @@ ++#ifndef __HI3531D_IO_H ++#define __HI3531D_IO_H ++ ++#ifdef CONFIG_PCI ++#define IO_SPACE_LIMIT 0xffffffff ++#define __io(a) __typesafe_io(PCI_IO_VIRT_BASE + ((a) & IO_SPACE_LIMIT)) ++#endif ++ ++/* phys_addr virt_addr ++ * 0x1000_0000 <-----> 0xFE00_0000 ++ * 0x1071_0000 <-----> 0xFE71_0000 ++ */ ++#define HI3531D_IOCH1_VIRT (0xFE000000) ++#define HI3531D_IOCH1_PHYS (0x10000000) ++#define HI3531D_IOCH1_SIZE (0x00710000) ++#define IO_OFFSET_IOCH1 (0xEE000000) ++ ++/* phys_addr virt_addr ++ * 0x1100_0000 <-----> 0xFE78_0000 ++ * 0x1104_0000 <-----> 0xFE7C_0000 ++ */ ++#define HI3531D_IOCH2_VIRT (0xFE780000) ++#define HI3531D_IOCH2_PHYS (0x11000000) ++#define HI3531D_IOCH2_SIZE (0x00040000) ++#define IO_OFFSET_IOCH2 (0xED780000) ++ ++/* phys_addr virt_addr ++ * 0x1200_0000 <-----> 0xFE80_0000 ++ * 0x1230_0000 <-----> 0xFEB0_0000 ++ */ ++#define HI3531D_IOCH3_VIRT (0xFE800000) ++#define HI3531D_IOCH3_PHYS (0x12000000) ++#define HI3531D_IOCH3_SIZE (0x00300000) ++#define IO_OFFSET_IOCH3 (0xEC800000) ++ ++/* phys_addr virt_addr ++ * 0x1300_0000 <-----> 0xFEB0_0000 ++ * 0x131A_0000 <-----> 0xFECA_0000 ++ */ ++#define HI3531D_IOCH4_VIRT (0xFEB00000) ++#define HI3531D_IOCH4_PHYS (0x13000000) ++#define HI3531D_IOCH4_SIZE (0x001A0000) ++#define IO_OFFSET_IOCH4 (0xEBB00000) ++ ++#define IO_ADDR_HIGH_H(n) ((n) + IO_OFFSET_IOCH4) ++#define IO_ADDR_HIGH_L(n) ((n) + IO_OFFSET_IOCH3) ++#define IO_ADDR_LOW_H(n) ((n) + IO_OFFSET_IOCH2) ++#define IO_ADDR_LOW_L(n) ((n) + IO_OFFSET_IOCH1) ++ ++#define __IO_ADDR_HIGH(n) ((n >= HI3531D_IOCH4_PHYS) ? IO_ADDR_HIGH_H(n) \ ++ : IO_ADDR_HIGH_L(n)) ++ ++#define __IO_ADDR_LOW(n) ((n >= HI3531D_IOCH2_PHYS) ? IO_ADDR_LOW_H(n) \ ++ : IO_ADDR_LOW_L(n)) ++ ++#define IO_ADDRESS(n) ((n) >= HI3531D_IOCH3_PHYS ? __IO_ADDR_HIGH(n) \ ++ : __IO_ADDR_LOW(n)) ++ ++#define __io_address(n) (IOMEM(IO_ADDRESS(n))) ++ ++#endif +diff --git a/arch/arm/include/mach/hi3531d_platform.h b/arch/arm/include/mach/hi3531d_platform.h +new file mode 100644 +index 0000000..c2ff7c0 +--- /dev/null ++++ b/arch/arm/include/mach/hi3531d_platform.h +@@ -0,0 +1,279 @@ ++#ifndef __HI3531D_CHIP_REGS_H__ ++#define __HI3531D_CHIP_REGS_H__ ++ ++/* -------------------------------------------------------------------- */ ++/* SRAM Base Address Register */ ++#define SRAM_BASE_ADDRESS 0x04010000 ++ ++/* -------------------------------------------------------------------- */ ++#define FMC_REG_BASE 0x10000000 ++#define NFC_REG_BASE 0x10010000 ++ ++/* -------------------------------------------------------------------- */ ++/* CORTTX-A9 internal Register */ ++/* -------------------------------------------------------------------- */ ++#define A9_PERI_BASE 0x10300000 ++ ++#define REG_A9_PERI_SCU 0x0000 ++#define REG_A9_PERI_GIC_CPU 0x0100 ++#define REG_A9_PERI_GLOBAL_TIMER 0x0200 ++#define REG_A9_PERI_PRI_TIMER_WDT 0x0600 ++#define REG_A9_PERI_GIC_DIST 0x1000 ++ ++#define CFG_GIC_CPU_BASE (IO_ADDRESS(A9_PERI_BASE) \ ++ + REG_A9_PERI_GIC_CPU) ++#define CFG_GIC_DIST_BASE (IO_ADDRESS(A9_PERI_BASE) \ ++ + REG_A9_PERI_GIC_DIST) ++ ++ /* -------------------------------------------------------------------- */ ++#define GSF_REG_BASE 0x100a0000 ++ ++/* -------------------------------------------------------------------- */ ++#define REG_BASE_L2CACHE 0x10700000 ++ ++/* -------------------------------------------------------------------- */ ++#define TIMER0_REG_BASE 0x12000000 ++#define TIMER1_REG_BASE 0x12000020 ++#define TIMER2_REG_BASE 0x12010000 ++#define TIMER3_REG_BASE 0x12010020 ++#define TIMER4_REG_BASE 0x12020000 ++#define TIMER5_REG_BASE 0x12020020 ++#define TIMER6_REG_BASE 0x12030000 ++#define TIMER7_REG_BASE 0x12030020 ++ ++/* -------------------------------------------------------------------- */ ++/* Clock and Reset Generator REG */ ++/* -------------------------------------------------------------------- */ ++#define CRG_REG_BASE 0x12040000 ++#define REG_BASE_CRG CRG_REG_BASE ++ ++#define REG_CRG20 0x0050 ++#define REG_CRG32 0x0080 ++#define REG_CRG72 0x0120 ++#define REG_CRG75 0x012c ++#define REG_CRG76 0x0130 ++#define REG_CRG77 0x0134 ++#define REG_CRG79 0x013c ++#define REG_CRG81 0x0144 ++#define REG_CRG82 0x0148 ++#define REG_CRG83 0x014c ++#define REG_CRG85 0x0154 ++#define REG_CRG87 0x015c ++#define REG_CRG91 0x016c ++ ++/* SOC CRG register offset */ ++#define REG_SOC_CRG REG_CRG20 ++#define GET_SYS_BUS_CLK(_reg) (((_reg) >> 2) & 0x3) ++#define SYS_CLK_XTAL 0 ++#define SYS_CLK_324M 1 ++#define SYS_CLK_375M 2 ++#define GET_PERI_AXI_CLK(_reg) ((_reg) & 0x3) ++#define PERI_CLK_XTAL 0 ++#define PERI_CLK_200M 1 ++#define PERI_CLK_300M 2 ++ ++/* A9 soft reset request register offset */ ++#define REG_A9_SRST_CRG REG_CRG32 ++#define WDG1_SRST_REQ (0x1 << 6) ++#define DBG1_SRST_REQ (0x1 << 5) ++#define CPU1_SRST_REQ (0x1 << 4) ++ ++/* USB 3.0 CRG PHY register offset */ ++#define REG_USB3_PHY0 REG_CRG72 ++ ++/* USB 3.0 CRG Control register offset */ ++#define REG_USB3_CTRL REG_CRG75 ++ ++/* USB 2.0 CRG Control register offset */ ++#define REG_USB2_CTRL REG_CRG76 ++ ++/* USB 2.0 CRG PHY register offset */ ++#define REG_USB2_PHY0 REG_CRG77 ++#define REG_USB2_PHY1 REG_CRG91 ++ ++/* NFC CRG register offset */ ++#define REG_NFC_CRG REG_CRG79 ++#define NFC_CLK_SEL(_clk) (((_clk) & 0x3) << 2) ++#define NFC_CLK_24M 0 ++#define NFC_CLK_200M 1 ++#define NFC_CLK_ENABLE (1 << 1) ++ ++/* DMAC CRG register offset */ ++#define REG_DMAC_CRG REG_CRG81 ++#define DMAC_CLK_EN (0x1 << 1) ++#define DMAC_SRST_REQ (0x1 << 0) ++ ++/* FMC CRG register offset */ ++#define REG_FMC_CRG REG_CRG82 ++#define FMC_CLK_SEL(_clk) (((_clk) & 0x3) << 2) ++#define FMC_CLK_SEL_MASK (0x3 << 2) ++#define FMC_CLK_24M 0 ++#define FMC_CLK_83M 1 ++#define FMC_CLK_125M 2 ++#define FMC_CLK_150M 3 ++#define FMC_CLK_ENABLE (0x1 << 1) ++ ++/* Ethernet CRG register offset */ ++#define REG_ETH_CRG REG_CRG83 ++#define REG_ETH_MAC_IF REG_CRG87 ++ ++/* Uart CRG register offset */ ++#define REG_UART_CRG REG_CRG85 ++#define UART_CLK_SEL(_clk) (((_clk) & 0x3) << 19) ++#define UART_CLK_SEL_MASK (0x3 << 19) ++#define UART_CLK_APB 0 ++#define UART_CLK_24M 1 ++#define UART_CLK_2M 2 ++ ++/* SSP CRG register offset */ ++#define REG_SSP_CRG REG_CRG85 ++#define SSP_CLK_ENABLE (0x1 << 13) ++#define SSP_SOFT_RESET_REQ (0x1 << 5) ++ ++/* -------------------------------------------------------------------- */ ++/* System Control REG */ ++/* -------------------------------------------------------------------- */ ++#define SYS_CTRL_BASE 0x12050000 ++ ++/* System Control register offset */ ++#define REG_SC_CTRL 0x0000 ++#define SC_CTRL_TIMER7_CLK_SEL(_clk) (((_clk) & 0x1) << 31) ++#define SC_CTRL_TIMER6_CLK_SEL(_clk) (((_clk) & 0x1) << 29) ++#define SC_CTRL_TIMER5_CLK_SEL(_clk) (((_clk) & 0x1) << 27) ++#define SC_CTRL_TIMER4_CLK_SEL(_clk) (((_clk) & 0x1) << 25) ++#define SC_CTRL_TIMER3_CLK_SEL(_clk) (((_clk) & 0x1) << 22) ++#define SC_CTRL_TIMER2_CLK_SEL(_clk) (((_clk) & 0x1) << 20) ++#define SC_CTRL_TIMER1_CLK_SEL(_clk) (((_clk) & 0x1) << 18) ++#define SC_CTRL_TIMER0_CLK_SEL(_clk) (((_clk) & 0x1) << 16) ++#define TIMER_CLK_3M 0 ++#define TIMER_CLK_BUS 1 ++ ++/* System soft reset register offset */ ++#define REG_SC_SYSRES 0x0004 ++ ++#define REG_SC_SOFT_INT 0x001c ++#define REG_SC_SOFT_TYPE 0x0020 ++#define REG_SC_LOCK_EN 0x0044 ++ ++/* System Status register offset */ ++#define REG_SC_STAT 0x008c ++#define SYS_CTRL_SYSSTAT REG_SC_STAT ++ ++/* bit[8]=0; SPI nor flash; bit[8]=1: SPI nand flash */ ++#define GET_SPI_DEVICE_TYPE(_reg) (((_reg) >> 8) & 0x1) ++/* if bit[8]=0 SPI nor flash ++ * * bit[7]=0: 3-Byte address mode; bit[7]=1: 4-Byte address mode */ ++#define GET_SPI_NOR_ADDR_MODE(_reg) (((_reg) >> 7) & 0x1) ++ ++#define REG_SC_SYSID0 0x0EE0 ++#define REG_SC_SYSID1 0x0EE4 ++#define REG_SC_SYSID2 0x0EE8 ++#define REG_SC_SYSID3 0x0EEC ++ ++/* -------------------------------------------------------------------- */ ++/* UART Control REG */ ++/* -------------------------------------------------------------------- */ ++#define UART0_REG_BASE 0x12080000 ++#define UART1_REG_BASE 0x12090000 ++#define UART2_REG_BASE 0x120A0000 ++#define UART3_REG_BASE 0x12130000 ++ ++#define REG_UART_DATA 0x0000 ++#define REG_UART_FLAG 0x0018 ++#define REG_UART_CTRL 0x0030 ++#define REG_UART_DMA_CR 0x0048 ++ ++/* -------------------------------------------------------------------- */ ++/* I2C Control REG */ ++/* -------------------------------------------------------------------- */ ++#define I2C0_REG_BASE 0x120c0000 ++#define I2C1_REG_BASE 0x122e0000 ++ ++#define REG_I2C_DATA 0x0010 ++ ++/* -------------------------------------------------------------------- */ ++/* SSP Control REG */ ++/* -------------------------------------------------------------------- */ ++#define SSP_REG_BASE 0x120d0000 ++ ++#define REG_SSP_DATA 0x0008 ++ ++/* -------------------------------------------------------------------- */ ++/* Peripheral Control REG */ ++/* -------------------------------------------------------------------- */ ++#define MISC_REG_BASE 0x12120000 ++ ++#define MISC_CTRL5 0x0014 ++#define MISC_CTRL36 0x0090 ++#define MISC_CTRL37 0x0094 ++#define MISC_CTRL74 0x0128 ++#define MISC_CTRL75 0x012c ++#define MISC_CTRL78 0x0138 ++ ++/* SPI Chip Select register offset */ ++#define REG_SSP_CS MISC_CTRL5 ++#define SSP_CS_SEL(_cs) (((_cs) & 0x3) << 0) ++#define SSP_CS_SEL_MASK (0x3 << 0) ++ ++/* USB 2.0 MISC Control register offset */ ++#define REG_USB2_CTRL0 MISC_CTRL36 ++#define REG_USB2_CTRL1 MISC_CTRL37 ++ ++/* USB 3.0 MISC Control register offset */ ++#define REG_USB3_CTRL0 MISC_CTRL74 ++#define REG_USB3_CTRL1 MISC_CTRL75 ++ ++#define REG_COMB_PHY1 MISC_CTRL78 ++ ++/* hisilicon satav200 register */ ++#define HI_SATA_PORT_FIFOTH 0x44 ++#define HI_SATA_PORT_PHYCTL1 0x48 ++#define HI_SATA_PORT_PHYCTL 0x74 ++ ++#define HI_SATA_PHY_CTL0 0xA0 ++#define HI_SATA_PHY_CTL1 0xA4 ++#define HI_SATA_PHY_CTL2 0xB0 ++#define HI_SATA_PHY_RST_BACK_MASK 0xAC ++ ++#define HI_SATA_FIFOTH_VALUE 0xFEED9F24 ++ ++#define HI_SATA_BIGENDINE (1 << 3) ++ ++#define HI_SATA_PHY_MODE_1_5G 0 ++#define HI_SATA_PHY_MODE_3G 1 ++#define HI_SATA_PHY_MODE_6G 2 ++ ++#define HI_SATA_PHY_1_5G 0x0e180000 ++#define HI_SATA_PHY_3G 0x0e390000 ++#define HI_SATA_PHY_6G 0x0e5a0000 ++ ++#define HI_SATA_PHY_SG_1_5G 0x50438 ++#define HI_SATA_PHY_SG_3G 0x50438 ++#define HI_SATA_PHY_SG_6G 0x50438 ++ ++#define HI_SATA_MISC_CTRL IO_ADDRESS(0x12120000) ++#define HI_SATA_MISC_COMB_PHY0 (HI_SATA_MISC_CTRL + 0x134) ++#define HI_SATA_MISC_COMB_PHY1 (HI_SATA_MISC_CTRL + 0x138) ++#define HI_SATA_MISC_COMB_PHY2 (HI_SATA_MISC_CTRL + 0x140) ++#define HI_SATA_MISC_COMB_PHY3 (HI_SATA_MISC_CTRL + 0x144) ++ ++/* -------------------------------------------------------------------- */ ++#define FMC_MEM_BASE 0x14000000 ++#define NFC_MEM_BASE 0x15000000 ++#define DDR_MEM_BASE 0x40000000 ++ ++#define CFG_TIMER_PER (4) /* AXI:APB is 4:1 */ ++/* -------------------------------------------------------------------- */ ++#define get_bus_clk() ({ \ ++ unsigned int base, regval, busclk = 0; \ ++ base = IO_ADDRESS(CRG_REG_BASE + REG_SOC_CRG); \ ++ regval = readl((void *)base); \ ++ regval = GET_PERI_AXI_CLK(regval); \ ++ if (PERI_CLK_200M == regval) \ ++ busclk = 200000000; \ ++ else if (PERI_CLK_300M == regval) \ ++ busclk = 300000000; \ ++ busclk; \ ++ }) ++ ++#endif /* End of __HI3531D_CHIP_REGS_H__ */ +diff --git a/arch/arm/include/mach/hi3536c_io.h b/arch/arm/include/mach/hi3536c_io.h +new file mode 100644 +index 0000000..5e0f34d +--- /dev/null ++++ b/arch/arm/include/mach/hi3536c_io.h +@@ -0,0 +1,43 @@ ++#ifndef __HI3536C_IO_H ++#define __HI3536C_IO_H ++ ++/* phys_addr virt_addr ++ * 0x1000_0000 <-----> 0xFE00_0000 ++ * 0x1004_0000 <-----> 0xFE04_0000 ++ */ ++#define HI3536C_IOCH1_VIRT (0xFE000000) ++#define HI3536C_IOCH1_PHYS (0x10000000) ++#define HI3536C_IOCH1_SIZE (0x00400000) ++ ++/* phys_addr virt_addr ++ * 0x1200_0000 <-----> 0xFE4_00000 ++ * 0x1223_0000 <-----> 0xFE63_0000 ++ */ ++#define HI3536C_IOCH2_VIRT (0xFE400000) ++#define HI3536C_IOCH2_PHYS (0x12000000) ++#define HI3536C_IOCH2_SIZE (0x00230000) ++ ++/* phys_addr virt_addr ++ * 0x1300_0000 <-----> 0xFE70_0000 ++ * 0x1316_0000 <-----> 0xFE86_0000 ++ */ ++#define HI3536C_IOCH3_VIRT (0xFE700000) ++#define HI3536C_IOCH3_PHYS (0x13000000) ++#define HI3536C_IOCH3_SIZE (0x00160000) ++ ++#define IO_OFFSET_LOW (0xEB700000) ++#define IO_OFFSET_MID (0xEC400000) ++#define IO_OFFSET_HIGH (0xEE000000) ++ ++#define IO_ADDRESS_LOW(x) ((x) + IO_OFFSET_LOW) ++#define IO_ADDRESS_MID(x) ((x) + IO_OFFSET_MID) ++#define IO_ADDRESS_HIGH(x) ((x) + IO_OFFSET_HIGH) ++ ++#define __IO_ADDRESS_HIGH(x) ((x >= HI3536C_IOCH2_PHYS) ? IO_ADDRESS_MID(x) \ ++ : IO_ADDRESS_HIGH(x)) ++#define IO_ADDRESS(x) ((x) >= HI3536C_IOCH3_PHYS ? IO_ADDRESS_LOW(x) \ ++ : __IO_ADDRESS_HIGH(x)) ++ ++#define __io_address(x) (IOMEM(IO_ADDRESS(x))) ++ ++#endif +diff --git a/arch/arm/include/mach/hi3536c_platform.h b/arch/arm/include/mach/hi3536c_platform.h +new file mode 100644 +index 0000000..5191057 +--- /dev/null ++++ b/arch/arm/include/mach/hi3536c_platform.h +@@ -0,0 +1,88 @@ ++#ifndef __HI3536C_CHIP_REGS_H__ ++#define __HI3536C_CHIP_REGS_H__ ++ ++/* -------------------------------------------------------------------- */ ++/* SRAM Base Address Register */ ++#define SRAM_BASE_ADDRESS 0x04010000 ++ ++/* -------------------------------------------------------------------- */ ++/*CORTTX-A7 MPCORE MEMORY REGION*/ ++/* -------------------------------------------------------------------- */ ++#define REG_BASE_A7_PERI 0x10300000 ++#define A7_PERI_BASE REG_BASE_A7_PERI ++ ++#define REG_A7_PERI_SCU 0x0000 ++ ++/* -------------------------------------------------------------------- */ ++/* Clock and Reset Generator REG */ ++/* -------------------------------------------------------------------- */ ++#define REG_BASE_CRG 0x12040000 ++#define CRG_REG_BASE REG_BASE_CRG ++ ++#define REG_CRG32 0x0080 ++ ++/* A7 soft reset request register offset */ ++#define REG_A7_SRST_CRG REG_CRG32 ++#define DBG1_SRST_REQ BIT(4) ++#define CORE1_SRST_REQ BIT(2) ++ ++/* Ethernet CRG register offset */ ++#define REG_ETH_CRG 0x014C ++#define REG_ETH_MAC_IF 0x008C ++ ++#define UART_CKSEL_MASK (0x3 << 18) ++#define UART_CKSEL_24M (0x2 << 18) ++ ++#define REG_BASE_CUR_UART REG_BASE_UART0 ++ ++/*********************************************************************/ ++#define A7_AXI_SCALE_REG IO_ADDRESS(REG_BASE_CRG + 0x50) ++ ++/* -------------------------------------------------------------------- */ ++#define DDR_MEM_BASE 0x80000000 ++#define CFG_TIMER_PER (4) /* AXI:APB is 4:1 */ ++/* -------------------------------------------------------------------- */ ++#define get_bus_clk() ({ \ ++ unsigned long tmp_reg, busclk = 0;\ ++ tmp_reg = readl((void *)A7_AXI_SCALE_REG);\ ++ tmp_reg = (tmp_reg >> 2) & 0x3;\ ++ if (0x3 == tmp_reg) {\ ++ busclk = 300000000;\ ++ } else if (0x1 == tmp_reg) {\ ++ busclk = 200000000;\ ++ } \ ++ busclk;\ ++}) ++ ++/* hisilicon satav200 register */ ++#define HI_SATA_PORT_FIFOTH 0x44 ++#define HI_SATA_PORT_PHYCTL1 0x48 ++#define HI_SATA_PORT_PHYCTL 0x74 ++ ++#define HI_SATA_PHY_CTL0 0xA0 ++#define HI_SATA_PHY_CTL1 0xA4 ++#define HI_SATA_PHY_CTL2 0xB0 ++#define HI_SATA_PHY_RST_BACK_MASK 0xAC ++ ++#define HI_SATA_FIFOTH_VALUE 0xFEED9F24 ++ ++#define HI_SATA_BIGENDINE (1 << 3) ++ ++#define HI_SATA_PHY_MODE_1_5G 0 ++#define HI_SATA_PHY_MODE_3G 1 ++#define HI_SATA_PHY_MODE_6G 2 ++ ++#define HI_SATA_PHY_1_5G 0x0e180000 ++#define HI_SATA_PHY_3G 0x0e390000 ++#define HI_SATA_PHY_6G 0x0e5a0000 ++ ++#define HI_SATA_PHY_SG_1_5G 0x50438 ++#define HI_SATA_PHY_SG_3G 0x50438 ++#define HI_SATA_PHY_SG_6G 0x50438 ++ ++#define HI_SATA_MISC_CTRL IO_ADDRESS(0x12120000) ++#define HI_SATA_MISC_SATA_PHY0 (HI_SATA_MISC_CTRL + 0x58) ++#define HI_SATA_MISC_SATA_PHY1 (HI_SATA_MISC_CTRL + 0x64) ++ ++#endif /* End of __HI_CHIP_REGS_H__ */ ++ +diff --git a/arch/arm/include/mach/hi3559_io.h b/arch/arm/include/mach/hi3559_io.h +new file mode 100644 +index 0000000..0238699 +--- /dev/null ++++ b/arch/arm/include/mach/hi3559_io.h +@@ -0,0 +1,46 @@ ++#ifndef __HI3559_IO_H ++#define __HI3559_IO_H ++ ++#ifdef CONFIG_PCI ++#define IO_SPACE_LIMIT 0xffffffff ++#define __io(a) __typesafe_io(PCI_IO_VIRT_BASE + ((a) & IO_SPACE_LIMIT)) ++#endif ++ ++/* phys_addr virt_addr ++ * 0x1000_0000 <-----> 0xFE00_0000 ++ */ ++#define HI3559_IOCH1_VIRT (0xFE000000) ++#define HI3559_IOCH1_PHYS (0x10000000) ++#define HI3559_IOCH1_SIZE (0x00310000) ++ ++/* phys_addr virt_addr ++ * 0x11000000 <-----> 0xFE400000 ++ */ ++#define HI3559_IOCH2_VIRT (0xFE400000) ++#define HI3559_IOCH2_PHYS (0x11000000) ++#define HI3559_IOCH2_SIZE (0x004F0000) ++ ++/* phys_addr virt_addr ++ * 0x12000000 <-----> 0xFE900000 ++ */ ++#define HI3559_IOCH3_VIRT (0xFE900000) ++#define HI3559_IOCH3_PHYS (0x12000000) ++#define HI3559_IOCH3_SIZE (0x00170000) ++ ++ ++#define IO_OFFSET_LOW (0xEC900000) ++#define IO_OFFSET_MID (0xED400000) ++#define IO_OFFSET_HIGH (0xEE000000) ++ ++#define IO_ADDRESS_LOW(x) ((x) + IO_OFFSET_LOW) ++#define IO_ADDRESS_MID(x) ((x) + IO_OFFSET_MID) ++#define IO_ADDRESS_HIGH(x) ((x) + IO_OFFSET_HIGH) ++ ++#define __IO_ADDRESS(x) ((x >= HI3559_IOCH2_PHYS) ? IO_ADDRESS_MID(x)\ ++ : IO_ADDRESS_HIGH(x)) ++#define IO_ADDRESS(x) ((x) >= HI3559_IOCH3_PHYS ? IO_ADDRESS_LOW(x)\ ++ : __IO_ADDRESS(x)) ++ ++#define __io_address(n) (IOMEM(IO_ADDRESS(n))) ++ ++#endif +diff --git a/arch/arm/include/mach/hi3559_platform.h b/arch/arm/include/mach/hi3559_platform.h +new file mode 100644 +index 0000000..0e2f4d4 +--- /dev/null ++++ b/arch/arm/include/mach/hi3559_platform.h +@@ -0,0 +1,164 @@ ++#ifndef __HI3559_CHIP_REGS_H__ ++#define __HI3559_CHIP_REGS_H__ ++ ++/* SRAM Base Address Register */ ++#define SRAM_BASE_ADDRESS 0x4010000 ++ ++#define REG_BASE_TIMER01 0x12000000 ++#define REG_BASE_TIMER23 0x12001000 ++ ++/* -------------------------------------------------------------------- */ ++/* Clock and Reset Generator REG */ ++/* -------------------------------------------------------------------- */ ++#define CRG_REG_BASE 0x12010000 ++#define REG_BASE_CRG CRG_REG_BASE ++ ++#define REG_CRG48 0x00c0 ++ ++/* FMC CRG register offset */ ++#define REG_FMC_CRG REG_CRG48 ++#define FMC_CLK_SEL(_clk) (((_clk) & 0x7) << 2) ++#define FMC_CLK_SEL_MASK (0x7 << 2) ++#define GET_FMC_CLK_TYPE(_reg) (((_reg) >> 2) & 0x7) ++/* SDR/DDR clock */ ++#define FMC_CLK_24M 0 ++#define FMC_CLK_75M 1 ++#define FMC_CLK_125M 2 ++#define FMC_CLK_150M 3 ++#define FMC_CLK_200M 4 ++#define FMC_CLK_250M 5 ++/* Only DDR clock */ ++#define FMC_CLK_300M 6 ++#define FMC_CLK_400M 7 ++#define FMC_CLK_ENABLE (0x1 << 1) ++#define FMC_SOFT_RST_REQ (0x1 << 0) ++ ++#define REG_BASE_UART0 0x12100000 ++#define REG_BASE_UART1 0x12101000 ++#define REG_BASE_UART2 0x12102000 ++#define REG_BASE_UART3 0x12103000 ++#define REG_BASE_UART4 0x12104000 ++#define REG_BASE_CUR_UART REG_BASE_UART0 ++ ++#define PMC_BASE 0x120a0000 ++ ++#define CCI_BASE 0x1ff00000 ++#define CCI_PORT0_BASE 0x1ff01000 ++#define CCI_PORT1_BASE 0x1ff02000 ++ ++ ++#define REG_BASE_A7_PERI 0x10300000 ++ ++/*CORTTX-A7 MPCORE MEMORY REGION*/ ++#define REG_A7_PERI_SCU 0x0000 ++#define REG_A7_PERI_GIC_CPU 0x2000 ++#define REG_A7_PERI_GLOBAL_TIMER 0x0200 ++#define REG_A7_PERI_PRI_TIMER_WDT 0x0600 ++#define REG_A7_PERI_GIC_DIST 0x1000 ++/* -------------------------------------------------------------------- */ ++/* System Control REG */ ++/* -------------------------------------------------------------------- */ ++#define SYS_CTRL_BASE 0x12020000 ++ ++/* System Control register offset */ ++#define REG_SC_CTRL 0x0000 ++ ++/* System soft reset register offset */ ++#define REG_SC_SYSRES 0x0004 ++ ++/* System Status register offset */ ++#define REG_SC_STAT 0x008c ++ ++/* if bit[5:4]=00b: boot form SPI && bit[3]=0: SPI nor flash ++ * bit[7]=0: 3-Byte address mode; bit[7]=1: 4-Byte address mode */ ++#define GET_SPI_NOR_ADDR_MODE(_reg) (((_reg) >> 7) & 0x1) ++#define GET_SYS_BOOT_MODE(_reg) (((_reg) >> 4) & 0x3) ++#define BOOT_MODE_MASK ((0x3) << 4) ++#define BOOT_FROM_SPI 0 ++#define BOOT_FROM_NAND 1 ++#define BOOT_FROM_EMMC 2 ++#define BOOT_FROM_DDR 3 ++/* bit[3]=0; SPI nor flash; bit[3]=1: SPI nand flash */ ++#define GET_SPI_DEVICE_TYPE(_reg) (((_reg) >> 3) & 0x1) ++ ++#define REG_SC_XTALCTRL 0x0010 ++#define REG_SC_APLLCTRL 0x0014 ++#define REG_SC_APLLFREQCTRL0 0x0018 ++#define REG_SC_APLLFREQCTRL1 0x001C ++#define REG_SC_VPLL0FREQCTRL0 0x0020 ++#define REG_SC_VPLL0FREQCTRL1 0x0024 ++#define REG_SC_VPLL1FREQCTRL0 0x0028 ++#define REG_SC_VPLL1FREQCTRL1 0x002C ++#define REG_SC_EPLLFREQCTRL0 0x0030 ++#define REG_SC_EPLLFREQCTRL1 0x0034 ++#define REG_SC_QPLLFREQCTRL0 0x0038 ++#define REG_SC_QPLLFREQCTRL1 0x003C ++#define REG_SC_LOW_POWER_CTRL 0x0040 ++#define REG_SC_IO_REUSE_SEL 0x0044 ++#define REG_SC_SRST_REQ_CTRL 0x0048 ++#define REG_SC_CA_RST_CTRL 0x004C ++#define REG_SC_WDG_RST_CTRL 0x0050 ++#define REG_SC_DDRC_DFI_RST_CTRL 0x0054 ++#define REG_SC_PLLLOCK_STAT 0x0070 ++#define REG_SC_GEN0 0x0080 ++#define REG_SC_GEN1 0x0084 ++#define REG_SC_GEN2 0x0088 ++#define REG_SC_GEN3 0x008C ++#define REG_SC_GEN4 0x0090 ++#define REG_SC_GEN5 0x0094 ++#define REG_SC_GEN6 0x0098 ++#define REG_SC_GEN7 0x009C ++#define REG_SC_GEN8 0x00A0 ++#define REG_SC_GEN9 0x00A4 ++#define REG_SC_GEN10 0x00A8 ++#define REG_SC_GEN11 0x00AC ++#define REG_SC_GEN12 0x00B0 ++#define REG_SC_GEN13 0x00B4 ++#define REG_SC_GEN14 0x00B8 ++#define REG_SC_GEN15 0x00BC ++#define REG_SC_GEN16 0x00C0 ++#define REG_SC_GEN17 0x00C4 ++#define REG_SC_GEN18 0x00C8 ++#define REG_SC_GEN19 0x00CC ++#define REG_SC_GEN20 0x00D0 ++#define REG_SC_GEN21 0x00D4 ++#define REG_SC_GEN22 0x00D8 ++#define REG_SC_GEN23 0x00DC ++#define REG_SC_GEN24 0x00E0 ++#define REG_SC_GEN25 0x00E4 ++#define REG_SC_GEN26 0x00E8 ++#define REG_SC_GEN27 0x00EC ++#define REG_SC_GEN28 0x00F0 ++#define REG_SC_GEN29 0x00F4 ++#define REG_SC_GEN30 0x00F8 ++#define REG_SC_GEN31 0x00FC ++#define REG_SC_LOCKEN 0x020C ++#define REG_SC_SYSID0 0x0EE0 ++#define REG_SC_SYSID1 0x0EE4 ++#define REG_SC_SYSID2 0x0EE8 ++#define REG_SC_SYSID3 0x0EEC ++ ++/*#define REG_BASE_WDG0 0xF8A2C000 */ ++ ++#define REG_PERI_CRG94 0x178 ++#define REG_PERI_CRG10 0x0028 ++#define REG_PERI_CRG98 0x0188 ++ ++#define CFG_GIC_CPU_BASE (IO_ADDRESS(REG_BASE_A7_PERI)\ ++ + REG_A7_PERI_GIC_CPU) ++#define CFG_GIC_DIST_BASE (IO_ADDRESS(REG_BASE_A7_PERI)\ ++ + REG_A7_PERI_GIC_DIST) ++ ++ ++/*********************************************************************/ ++/* ++ * 0x1-> init item1 ++ * 0x2-> init item2 ++ * 0x3->init item1 & item2 ++ */ ++#define INIT_REG_ITEM1 1 ++#define INIT_REG_ITEM2 2 ++#define INIT_REG_ITEM1_ITEM2 (INIT_REG_ITEM1 | INIT_REG_ITEM2) ++ ++ ++#endif /* End of __HI_CHIP_REGS_H__ */ +diff --git a/arch/arm/include/mach/io.h b/arch/arm/include/mach/io.h +new file mode 100644 +index 0000000..ae92d98 +--- /dev/null ++++ b/arch/arm/include/mach/io.h +@@ -0,0 +1,32 @@ ++#ifndef __ASM_ARM_ARCH_IO_H ++#define __ASM_ARM_ARCH_IO_H ++ ++#ifdef CONFIG_ARCH_HI3519 ++#include ++#endif ++ ++#ifdef CONFIG_ARCH_HI3519V101 ++#include ++#endif ++ ++#if defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) ++#include ++#endif ++ ++#ifdef CONFIG_ARCH_HI3516AV200 ++#include ++#endif ++ ++#ifdef CONFIG_ARCH_HI3536C ++#include ++#endif ++ ++#ifdef CONFIG_ARCH_HI3531D ++#include ++#endif ++ ++#ifdef CONFIG_ARCH_HI3521D ++#include ++#endif ++ ++#endif +diff --git a/arch/arm/include/mach/platform.h b/arch/arm/include/mach/platform.h +new file mode 100644 +index 0000000..ef78a22 +--- /dev/null ++++ b/arch/arm/include/mach/platform.h +@@ -0,0 +1,28 @@ ++#ifndef __HI_CHIP_REGS_H__ ++#define __HI_CHIP_REGS_H__ ++ ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++#include ++#endif ++ ++#if defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) ++#include ++#endif ++ ++#ifdef CONFIG_ARCH_HI3516AV200 ++#include ++#endif ++ ++#ifdef CONFIG_ARCH_HI3536C ++#include ++#endif ++ ++#ifdef CONFIG_ARCH_HI3531D ++#include ++#endif ++ ++#ifdef CONFIG_ARCH_HI3521D ++#include ++#endif ++ ++#endif /* End of __HI_CHIP_REGS_H__ */ +diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c +index a88671c..152a95a 100644 +--- a/arch/arm/kernel/armksyms.c ++++ b/arch/arm/kernel/armksyms.c +@@ -83,6 +83,7 @@ EXPORT_SYMBOL(__raw_writesl); + EXPORT_SYMBOL(strchr); + EXPORT_SYMBOL(strrchr); + EXPORT_SYMBOL(memset); ++ + EXPORT_SYMBOL(memcpy); + EXPORT_SYMBOL(memmove); + EXPORT_SYMBOL(memchr); +diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c +index 2d2d608..e4d88fa 100644 +--- a/arch/arm/kernel/asm-offsets.c ++++ b/arch/arm/kernel/asm-offsets.c +@@ -10,9 +10,11 @@ + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +-#include + #include + #include ++#ifdef CONFIG_HISI_SNAPSHOT_BOOT ++#include ++#endif + #include + #ifdef CONFIG_KVM_ARM_HOST + #include +@@ -40,19 +42,10 @@ + * GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c + * (http://gcc.gnu.org/PR8896) and incorrect structure + * initialisation in fs/jffs2/erase.c +- * GCC 4.8.0-4.8.2: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58854 +- * miscompiles find_get_entry(), and can result in EXT3 and EXT4 +- * filesystem corruption (possibly other FS too). + */ +-#ifdef __GNUC__ + #if (__GNUC__ == 3 && __GNUC_MINOR__ < 3) + #error Your compiler is too buggy; it is known to miscompile kernels. +-#error Known good compilers: 3.3, 4.x +-#endif +-#if GCC_VERSION >= 40800 && GCC_VERSION < 40803 +-#error Your compiler is too buggy; it is known to miscompile kernels +-#error and result in filesystem corruption and oopses. +-#endif ++#error Known good compilers: 3.3 + #endif + + int main(void) +@@ -165,6 +158,11 @@ int main(void) + DEFINE(DMA_BIDIRECTIONAL, DMA_BIDIRECTIONAL); + DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE); + DEFINE(DMA_FROM_DEVICE, DMA_FROM_DEVICE); ++#ifdef CONFIG_HISI_SNAPSHOT_BOOT ++ DEFINE(PBE_ADDRESS, offsetof(struct pbe, address)); ++ DEFINE(PBE_ORIG_ADDRESS, offsetof(struct pbe, orig_address)); ++ DEFINE(PBE_NEXT, offsetof(struct pbe, next)); ++#endif + BLANK(); + DEFINE(CACHE_WRITEBACK_ORDER, __CACHE_WRITEBACK_ORDER); + DEFINE(CACHE_WRITEBACK_GRANULE, __CACHE_WRITEBACK_GRANULE); +diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c +index 131a6ab..a634e0e 100644 +--- a/arch/arm/kernel/etm.c ++++ b/arch/arm/kernel/etm.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -37,26 +38,37 @@ MODULE_AUTHOR("Alexander Shishkin"); + struct tracectx { + unsigned int etb_bufsz; + void __iomem *etb_regs; +- void __iomem *etm_regs; ++ void __iomem **etm_regs; ++ int etm_regs_count; + unsigned long flags; + int ncmppairs; + int etm_portsz; ++ int etm_contextid_size; ++ u32 etb_fc; ++ unsigned long range_start; ++ unsigned long range_end; ++ unsigned long data_range_start; ++ unsigned long data_range_end; ++ bool dump_initial_etb; + struct device *dev; + struct clk *emu_clk; + struct mutex mutex; + }; + +-static struct tracectx tracer; ++static struct tracectx tracer = { ++ .range_start = (unsigned long)_stext, ++ .range_end = (unsigned long)_etext, ++}; + + static inline bool trace_isrunning(struct tracectx *t) + { + return !!(t->flags & TRACER_RUNNING); + } + +-static int etm_setup_address_range(struct tracectx *t, int n, ++static int etm_setup_address_range(struct tracectx *t, int id, int n, + unsigned long start, unsigned long end, int exclude, int data) + { +- u32 flags = ETMAAT_ARM | ETMAAT_IGNCONTEXTID | ETMAAT_NSONLY | \ ++ u32 flags = ETMAAT_ARM | ETMAAT_IGNCONTEXTID | ETMAAT_IGNSECURITY | + ETMAAT_NOVALCMP; + + if (n < 1 || n > t->ncmppairs) +@@ -72,95 +84,185 @@ static int etm_setup_address_range(struct tracectx *t, int n, + flags |= ETMAAT_IEXEC; + + /* first comparator for the range */ +- etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2)); +- etm_writel(t, start, ETMR_COMP_VAL(n * 2)); ++ etm_writel(t, id, flags, ETMR_COMP_ACC_TYPE(n * 2)); ++ etm_writel(t, id, start, ETMR_COMP_VAL(n * 2)); + + /* second comparator is right next to it */ +- etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2 + 1)); +- etm_writel(t, end, ETMR_COMP_VAL(n * 2 + 1)); +- +- flags = exclude ? ETMTE_INCLEXCL : 0; +- etm_writel(t, flags | (1 << n), ETMR_TRACEENCTRL); ++ etm_writel(t, id, flags, ETMR_COMP_ACC_TYPE(n * 2 + 1)); ++ etm_writel(t, id, end, ETMR_COMP_VAL(n * 2 + 1)); ++ ++ if (data) { ++ flags = exclude ? ETMVDC3_EXCLONLY : 0; ++ if (exclude) ++ n += 8; ++ etm_writel(t, id, flags | BIT(n), ETMR_VIEWDATACTRL3); ++ } else { ++ flags = exclude ? ETMTE_INCLEXCL : 0; ++ etm_writel(t, id, flags | (1 << n), ETMR_TRACEENCTRL); ++ } + + return 0; + } + +-static int trace_start(struct tracectx *t) ++static int trace_start_etm(struct tracectx *t, int id) + { + u32 v; + unsigned long timeout = TRACER_TIMEOUT; + +- etb_unlock(t); +- +- etb_writel(t, 0, ETBR_FORMATTERCTRL); +- etb_writel(t, 1, ETBR_CTRL); +- +- etb_lock(t); +- +- /* configure etm */ + v = ETMCTRL_OPTS | ETMCTRL_PROGRAM | ETMCTRL_PORTSIZE(t->etm_portsz); ++ v |= ETMCTRL_CONTEXTIDSIZE(t->etm_contextid_size); + + if (t->flags & TRACER_CYCLE_ACC) + v |= ETMCTRL_CYCLEACCURATE; + +- etm_unlock(t); ++ if (t->flags & TRACER_BRANCHOUTPUT) ++ v |= ETMCTRL_BRANCH_OUTPUT; ++ ++ if (t->flags & TRACER_TRACE_DATA) ++ v |= ETMCTRL_DATA_DO_ADDR; ++ ++ if (t->flags & TRACER_TIMESTAMP) ++ v |= ETMCTRL_TIMESTAMP_EN; ++ ++ if (t->flags & TRACER_RETURN_STACK) ++ v |= ETMCTRL_RETURN_STACK_EN; + +- etm_writel(t, v, ETMR_CTRL); ++ etm_unlock(t, id); + +- while (!(etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout) ++ etm_writel(t, id, v, ETMR_CTRL); ++ ++ while (!(etm_readl(t, id, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout) + ; + if (!timeout) { + dev_dbg(t->dev, "Waiting for progbit to assert timed out\n"); +- etm_lock(t); ++ etm_lock(t, id); + return -EFAULT; + } + +- etm_setup_address_range(t, 1, (unsigned long)_stext, +- (unsigned long)_etext, 0, 0); +- etm_writel(t, 0, ETMR_TRACEENCTRL2); +- etm_writel(t, 0, ETMR_TRACESSCTRL); +- etm_writel(t, 0x6f, ETMR_TRACEENEVT); ++ if (t->range_start || t->range_end) ++ etm_setup_address_range(t, id, 1, ++ t->range_start, t->range_end, 0, 0); ++ else ++ etm_writel(t, id, ETMTE_INCLEXCL, ETMR_TRACEENCTRL); ++ ++ etm_writel(t, id, 0, ETMR_TRACEENCTRL2); ++ etm_writel(t, id, 0, ETMR_TRACESSCTRL); ++ etm_writel(t, id, 0x6f, ETMR_TRACEENEVT); ++ ++ etm_writel(t, id, 0, ETMR_VIEWDATACTRL1); ++ etm_writel(t, id, 0, ETMR_VIEWDATACTRL2); ++ ++ if (t->data_range_start || t->data_range_end) ++ etm_setup_address_range(t, id, 2, t->data_range_start, ++ t->data_range_end, 0, 1); ++ else ++ etm_writel(t, id, ETMVDC3_EXCLONLY, ETMR_VIEWDATACTRL3); ++ ++ etm_writel(t, id, 0x6f, ETMR_VIEWDATAEVT); + + v &= ~ETMCTRL_PROGRAM; + v |= ETMCTRL_PORTSEL; + +- etm_writel(t, v, ETMR_CTRL); ++ etm_writel(t, id, v, ETMR_CTRL); + + timeout = TRACER_TIMEOUT; +- while (etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM && --timeout) ++ while (etm_readl(t, id, ETMR_CTRL) & ETMCTRL_PROGRAM && --timeout) + ; + if (!timeout) { + dev_dbg(t->dev, "Waiting for progbit to deassert timed out\n"); +- etm_lock(t); ++ etm_lock(t, id); + return -EFAULT; + } + +- etm_lock(t); ++ etm_lock(t, id); ++ return 0; ++} ++ ++static int trace_start(struct tracectx *t) ++{ ++ int ret; ++ int id; ++ u32 etb_fc = t->etb_fc; ++ ++ etb_unlock(t); ++ ++ t->dump_initial_etb = false; ++ etb_writel(t, 0, ETBR_WRITEADDR); ++ etb_writel(t, etb_fc, ETBR_FORMATTERCTRL); ++ etb_writel(t, 1, ETBR_CTRL); ++ ++ etb_lock(t); ++ ++ /* configure etm(s) */ ++ for (id = 0; id < t->etm_regs_count; id++) { ++ ret = trace_start_etm(t, id); ++ if (ret) ++ return ret; ++ } + + t->flags |= TRACER_RUNNING; + + return 0; + } + +-static int trace_stop(struct tracectx *t) ++static int trace_stop_etm(struct tracectx *t, int id) + { + unsigned long timeout = TRACER_TIMEOUT; + +- etm_unlock(t); ++ etm_unlock(t, id); + +- etm_writel(t, 0x440, ETMR_CTRL); +- while (!(etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout) ++ etm_writel(t, id, 0x440, ETMR_CTRL); ++ while (!(etm_readl(t, id, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout) + ; + if (!timeout) { +- dev_dbg(t->dev, "Waiting for progbit to assert timed out\n"); +- etm_lock(t); ++ dev_err(t->dev, ++ "etm%d: Waiting for progbit to assert timed out\n", ++ id); ++ etm_lock(t, id); + return -EFAULT; + } + +- etm_lock(t); ++ etm_lock(t, id); ++ return 0; ++} ++ ++static int trace_power_down_etm(struct tracectx *t, int id) ++{ ++ unsigned long timeout = TRACER_TIMEOUT; ++ etm_unlock(t, id); ++ while (!(etm_readl(t, id, ETMR_STATUS) & ETMST_PROGBIT) && --timeout) ++ ; ++ if (!timeout) { ++ dev_err(t->dev, "etm%d: Waiting for status progbit to assert timed out\n", ++ id); ++ etm_lock(t, id); ++ return -EFAULT; ++ } ++ ++ etm_writel(t, id, 0x441, ETMR_CTRL); ++ ++ etm_lock(t, id); ++ return 0; ++} ++ ++static int trace_stop(struct tracectx *t) ++{ ++ int id; ++ unsigned long timeout = TRACER_TIMEOUT; ++ u32 etb_fc = t->etb_fc; ++ ++ for (id = 0; id < t->etm_regs_count; id++) ++ trace_stop_etm(t, id); ++ ++ for (id = 0; id < t->etm_regs_count; id++) ++ trace_power_down_etm(t, id); + + etb_unlock(t); +- etb_writel(t, ETBFF_MANUAL_FLUSH, ETBR_FORMATTERCTRL); ++ if (etb_fc) { ++ etb_fc |= ETBFF_STOPFL; ++ etb_writel(t, t->etb_fc, ETBR_FORMATTERCTRL); ++ } ++ etb_writel(t, etb_fc | ETBFF_MANUAL_FLUSH, ETBR_FORMATTERCTRL); + + timeout = TRACER_TIMEOUT; + while (etb_readl(t, ETBR_FORMATTERCTRL) & +@@ -185,24 +287,15 @@ static int trace_stop(struct tracectx *t) + static int etb_getdatalen(struct tracectx *t) + { + u32 v; +- int rp, wp; ++ int wp; + + v = etb_readl(t, ETBR_STATUS); + + if (v & 1) + return t->etb_bufsz; + +- rp = etb_readl(t, ETBR_READADDR); + wp = etb_readl(t, ETBR_WRITEADDR); +- +- if (rp > wp) { +- etb_writel(t, 0, ETBR_READADDR); +- etb_writel(t, 0, ETBR_WRITEADDR); +- +- return 0; +- } +- +- return wp - rp; ++ return wp; + } + + /* sysrq+v will always stop the running trace and leave it at that */ +@@ -235,21 +328,18 @@ static void etm_dump(void) + printk("%08x", cpu_to_be32(etb_readl(t, ETBR_READMEM))); + printk(KERN_INFO "\n--- ETB buffer end ---\n"); + +- /* deassert the overflow bit */ +- etb_writel(t, 1, ETBR_CTRL); +- etb_writel(t, 0, ETBR_CTRL); +- +- etb_writel(t, 0, ETBR_TRIGGERCOUNT); +- etb_writel(t, 0, ETBR_READADDR); +- etb_writel(t, 0, ETBR_WRITEADDR); +- + etb_lock(t); + } + + static void sysrq_etm_dump(int key) + { ++ if (!mutex_trylock(&tracer.mutex)) { ++ printk(KERN_INFO "Tracing hardware busy\n"); ++ return; ++ } + dev_dbg(tracer.dev, "Dumping ETB buffer\n"); + etm_dump(); ++ mutex_unlock(&tracer.mutex); + } + + static struct sysrq_key_op sysrq_etm_op = { +@@ -276,6 +366,10 @@ static ssize_t etb_read(struct file *file, char __user *data, + struct tracectx *t = file->private_data; + u32 first = 0; + u32 *buf; ++ int wpos; ++ int skip; ++ long wlength; ++ loff_t pos = *ppos; + + mutex_lock(&t->mutex); + +@@ -287,31 +381,39 @@ static ssize_t etb_read(struct file *file, char __user *data, + etb_unlock(t); + + total = etb_getdatalen(t); ++ if (total == 0 && t->dump_initial_etb) ++ total = t->etb_bufsz; + if (total == t->etb_bufsz) + first = etb_readl(t, ETBR_WRITEADDR); + ++ if (pos > total * 4) { ++ skip = 0; ++ wpos = total; ++ } else { ++ skip = (int)pos % 4; ++ wpos = (int)pos / 4; ++ } ++ total -= wpos; ++ first = (first + wpos) % t->etb_bufsz; ++ + etb_writel(t, first, ETBR_READADDR); + +- length = min(total * 4, (int)len); +- buf = vmalloc(length); ++ wlength = min(total, DIV_ROUND_UP(skip + (int)len, 4)); ++ length = min(total * 4 - skip, (int)len); ++ buf = vmalloc(wlength * 4); + +- dev_dbg(t->dev, "ETB buffer length: %d\n", total); ++ dev_dbg(t->dev, "ETB read %ld bytes to %lld from %ld words at %d\n", ++ length, pos, wlength, first); ++ dev_dbg(t->dev, "ETB buffer length: %d\n", total + wpos); + dev_dbg(t->dev, "ETB status reg: %x\n", etb_readl(t, ETBR_STATUS)); +- for (i = 0; i < length / 4; i++) ++ for (i = 0; i < wlength; i++) + buf[i] = etb_readl(t, ETBR_READMEM); + +- /* the only way to deassert overflow bit in ETB status is this */ +- etb_writel(t, 1, ETBR_CTRL); +- etb_writel(t, 0, ETBR_CTRL); +- +- etb_writel(t, 0, ETBR_WRITEADDR); +- etb_writel(t, 0, ETBR_READADDR); +- etb_writel(t, 0, ETBR_TRIGGERCOUNT); +- + etb_lock(t); + +- length -= copy_to_user(data, buf, length); ++ length -= copy_to_user(data, (u8 *)buf + skip, length); + vfree(buf); ++ *ppos = pos + length; + + out: + mutex_unlock(&t->mutex); +@@ -348,28 +450,17 @@ static int etb_probe(struct amba_device *dev, const struct amba_id *id) + if (ret) + goto out; + ++ mutex_lock(&t->mutex); + t->etb_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res)); + if (!t->etb_regs) { + ret = -ENOMEM; + goto out_release; + } + ++ t->dev = &dev->dev; ++ t->dump_initial_etb = true; + amba_set_drvdata(dev, t); + +- etb_miscdev.parent = &dev->dev; +- +- ret = misc_register(&etb_miscdev); +- if (ret) +- goto out_unmap; +- +- t->emu_clk = clk_get(&dev->dev, "emu_src_ck"); +- if (IS_ERR(t->emu_clk)) { +- dev_dbg(&dev->dev, "Failed to obtain emu_src_ck.\n"); +- return -EFAULT; +- } +- +- clk_enable(t->emu_clk); +- + etb_unlock(t); + t->etb_bufsz = etb_readl(t, ETBR_DEPTH); + dev_dbg(&dev->dev, "Size: %x\n", t->etb_bufsz); +@@ -378,6 +469,20 @@ static int etb_probe(struct amba_device *dev, const struct amba_id *id) + etb_writel(t, 0, ETBR_CTRL); + etb_writel(t, 0x1000, ETBR_FORMATTERCTRL); + etb_lock(t); ++ mutex_unlock(&t->mutex); ++ ++ etb_miscdev.parent = &dev->dev; ++ ++ ret = misc_register(&etb_miscdev); ++ if (ret) ++ goto out_unmap; ++ ++ /* Get optional clock. Currently used to select clock source on omap3 */ ++ t->emu_clk = clk_get(&dev->dev, "emu_src_ck"); ++ if (IS_ERR(t->emu_clk)) ++ dev_dbg(&dev->dev, "Failed to obtain emu_src_ck.\n"); ++ else ++ clk_enable(t->emu_clk); + + dev_dbg(&dev->dev, "ETB AMBA driver initialized.\n"); + +@@ -385,9 +490,12 @@ out: + return ret; + + out_unmap: ++ mutex_lock(&t->mutex); + iounmap(t->etb_regs); ++ t->etb_regs = NULL; + + out_release: ++ mutex_unlock(&t->mutex); + amba_release_regions(dev); + + return ret; +@@ -400,8 +508,10 @@ static int etb_remove(struct amba_device *dev) + iounmap(t->etb_regs); + t->etb_regs = NULL; + +- clk_disable(t->emu_clk); +- clk_put(t->emu_clk); ++ if (!IS_ERR(t->emu_clk)) { ++ clk_disable(t->emu_clk); ++ clk_put(t->emu_clk); ++ } + + amba_release_regions(dev); + +@@ -445,7 +555,10 @@ static ssize_t trace_running_store(struct kobject *kobj, + return -EINVAL; + + mutex_lock(&tracer.mutex); +- ret = value ? trace_start(&tracer) : trace_stop(&tracer); ++ if (!tracer.etb_regs) ++ ret = -ENODEV; ++ else ++ ret = value ? trace_start(&tracer) : trace_stop(&tracer); + mutex_unlock(&tracer.mutex); + + return ret ? : n; +@@ -460,36 +573,50 @@ static ssize_t trace_info_show(struct kobject *kobj, + { + u32 etb_wa, etb_ra, etb_st, etb_fc, etm_ctrl, etm_st; + int datalen; ++ int id; ++ int ret; + +- etb_unlock(&tracer); +- datalen = etb_getdatalen(&tracer); +- etb_wa = etb_readl(&tracer, ETBR_WRITEADDR); +- etb_ra = etb_readl(&tracer, ETBR_READADDR); +- etb_st = etb_readl(&tracer, ETBR_STATUS); +- etb_fc = etb_readl(&tracer, ETBR_FORMATTERCTRL); +- etb_lock(&tracer); +- +- etm_unlock(&tracer); +- etm_ctrl = etm_readl(&tracer, ETMR_CTRL); +- etm_st = etm_readl(&tracer, ETMR_STATUS); +- etm_lock(&tracer); ++ mutex_lock(&tracer.mutex); ++ if (tracer.etb_regs) { ++ etb_unlock(&tracer); ++ datalen = etb_getdatalen(&tracer); ++ etb_wa = etb_readl(&tracer, ETBR_WRITEADDR); ++ etb_ra = etb_readl(&tracer, ETBR_READADDR); ++ etb_st = etb_readl(&tracer, ETBR_STATUS); ++ etb_fc = etb_readl(&tracer, ETBR_FORMATTERCTRL); ++ etb_lock(&tracer); ++ } else { ++ etb_wa = etb_ra = etb_st = etb_fc = ~0; ++ datalen = -1; ++ } + +- return sprintf(buf, "Trace buffer len: %d\nComparator pairs: %d\n" ++ ret = sprintf(buf, "Trace buffer len: %d\nComparator pairs: %d\n" + "ETBR_WRITEADDR:\t%08x\n" + "ETBR_READADDR:\t%08x\n" + "ETBR_STATUS:\t%08x\n" +- "ETBR_FORMATTERCTRL:\t%08x\n" +- "ETMR_CTRL:\t%08x\n" +- "ETMR_STATUS:\t%08x\n", ++ "ETBR_FORMATTERCTRL:\t%08x\n", + datalen, + tracer.ncmppairs, + etb_wa, + etb_ra, + etb_st, +- etb_fc, ++ etb_fc ++ ); ++ ++ for (id = 0; id < tracer.etm_regs_count; id++) { ++ etm_unlock(&tracer, id); ++ etm_ctrl = etm_readl(&tracer, id, ETMR_CTRL); ++ etm_st = etm_readl(&tracer, id, ETMR_STATUS); ++ etm_lock(&tracer, id); ++ ret += sprintf(buf + ret, "ETMR_CTRL:\t%08x\n" ++ "ETMR_STATUS:\t%08x\n", + etm_ctrl, + etm_st + ); ++ } ++ mutex_unlock(&tracer.mutex); ++ ++ return ret; + } + + static struct kobj_attribute trace_info_attr = +@@ -528,42 +655,260 @@ static ssize_t trace_mode_store(struct kobject *kobj, + static struct kobj_attribute trace_mode_attr = + __ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store); + ++static ssize_t trace_contextid_size_show(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ char *buf) ++{ ++ /* 0: No context id tracing, 1: One byte, 2: Two bytes, 3: Four bytes */ ++ return sprintf(buf, "%d\n", (1 << tracer.etm_contextid_size) >> 1); ++} ++ ++static ssize_t trace_contextid_size_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t n) ++{ ++ unsigned int contextid_size; ++ ++ if (sscanf(buf, "%u", &contextid_size) != 1) ++ return -EINVAL; ++ ++ if (contextid_size == 3 || contextid_size > 4) ++ return -EINVAL; ++ ++ mutex_lock(&tracer.mutex); ++ tracer.etm_contextid_size = fls(contextid_size); ++ mutex_unlock(&tracer.mutex); ++ ++ return n; ++} ++ ++static struct kobj_attribute trace_contextid_size_attr = ++ __ATTR(trace_contextid_size, 0644, ++ trace_contextid_size_show, trace_contextid_size_store); ++ ++static ssize_t trace_branch_output_show(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ char *buf) ++{ ++ return sprintf(buf, "%d\n", !!(tracer.flags & TRACER_BRANCHOUTPUT)); ++} ++ ++static ssize_t trace_branch_output_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t n) ++{ ++ unsigned int branch_output; ++ ++ if (sscanf(buf, "%u", &branch_output) != 1) ++ return -EINVAL; ++ ++ mutex_lock(&tracer.mutex); ++ if (branch_output) { ++ tracer.flags |= TRACER_BRANCHOUTPUT; ++ /* Branch broadcasting is incompatible with the return stack */ ++ tracer.flags &= ~TRACER_RETURN_STACK; ++ } else { ++ tracer.flags &= ~TRACER_BRANCHOUTPUT; ++ } ++ mutex_unlock(&tracer.mutex); ++ ++ return n; ++} ++ ++static struct kobj_attribute trace_branch_output_attr = ++ __ATTR(trace_branch_output, 0644, ++ trace_branch_output_show, trace_branch_output_store); ++ ++static ssize_t trace_return_stack_show(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ char *buf) ++{ ++ return sprintf(buf, "%d\n", !!(tracer.flags & TRACER_RETURN_STACK)); ++} ++ ++static ssize_t trace_return_stack_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t n) ++{ ++ unsigned int return_stack; ++ ++ if (sscanf(buf, "%u", &return_stack) != 1) ++ return -EINVAL; ++ ++ mutex_lock(&tracer.mutex); ++ if (return_stack) { ++ tracer.flags |= TRACER_RETURN_STACK; ++ /* Return stack is incompatible with branch broadcasting */ ++ tracer.flags &= ~TRACER_BRANCHOUTPUT; ++ } else { ++ tracer.flags &= ~TRACER_RETURN_STACK; ++ } ++ mutex_unlock(&tracer.mutex); ++ ++ return n; ++} ++ ++static struct kobj_attribute trace_return_stack_attr = ++ __ATTR(trace_return_stack, 0644, ++ trace_return_stack_show, trace_return_stack_store); ++ ++static ssize_t trace_timestamp_show(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ char *buf) ++{ ++ return sprintf(buf, "%d\n", !!(tracer.flags & TRACER_TIMESTAMP)); ++} ++ ++static ssize_t trace_timestamp_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t n) ++{ ++ unsigned int timestamp; ++ ++ if (sscanf(buf, "%u", ×tamp) != 1) ++ return -EINVAL; ++ ++ mutex_lock(&tracer.mutex); ++ if (timestamp) ++ tracer.flags |= TRACER_TIMESTAMP; ++ else ++ tracer.flags &= ~TRACER_TIMESTAMP; ++ mutex_unlock(&tracer.mutex); ++ ++ return n; ++} ++ ++static struct kobj_attribute trace_timestamp_attr = ++ __ATTR(trace_timestamp, 0644, ++ trace_timestamp_show, trace_timestamp_store); ++ ++static ssize_t trace_range_show(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ char *buf) ++{ ++ return sprintf(buf, "%08lx %08lx\n", ++ tracer.range_start, tracer.range_end); ++} ++ ++static ssize_t trace_range_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t n) ++{ ++ unsigned long range_start, range_end; ++ ++ if (sscanf(buf, "%lx %lx", &range_start, &range_end) != 2) ++ return -EINVAL; ++ ++ mutex_lock(&tracer.mutex); ++ tracer.range_start = range_start; ++ tracer.range_end = range_end; ++ mutex_unlock(&tracer.mutex); ++ ++ return n; ++} ++ ++ ++static struct kobj_attribute trace_range_attr = ++ __ATTR(trace_range, 0644, trace_range_show, trace_range_store); ++ ++static ssize_t trace_data_range_show(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ char *buf) ++{ ++ unsigned long range_start; ++ u64 range_end; ++ mutex_lock(&tracer.mutex); ++ range_start = tracer.data_range_start; ++ range_end = tracer.data_range_end; ++ if (!range_end && (tracer.flags & TRACER_TRACE_DATA)) ++ range_end = 0x100000000ULL; ++ mutex_unlock(&tracer.mutex); ++ return sprintf(buf, "%08lx %08llx\n", range_start, range_end); ++} ++ ++static ssize_t trace_data_range_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t n) ++{ ++ unsigned long range_start; ++ u64 range_end; ++ ++ if (sscanf(buf, "%lx %llx", &range_start, &range_end) != 2) ++ return -EINVAL; ++ ++ mutex_lock(&tracer.mutex); ++ tracer.data_range_start = range_start; ++ tracer.data_range_end = (unsigned long)range_end; ++ if (range_end) ++ tracer.flags |= TRACER_TRACE_DATA; ++ else ++ tracer.flags &= ~TRACER_TRACE_DATA; ++ mutex_unlock(&tracer.mutex); ++ ++ return n; ++} ++ ++ ++static struct kobj_attribute trace_data_range_attr = ++ __ATTR(trace_data_range, 0644, ++ trace_data_range_show, trace_data_range_store); ++ + static int etm_probe(struct amba_device *dev, const struct amba_id *id) + { + struct tracectx *t = &tracer; + int ret = 0; ++ void __iomem **new_regs; ++ int new_count; ++ u32 etmccr; ++ u32 etmidr; ++ u32 etmccer = 0; ++ u8 etm_version = 0; ++ ++ mutex_lock(&t->mutex); ++ new_count = t->etm_regs_count + 1; ++ new_regs = krealloc(t->etm_regs, ++ sizeof(t->etm_regs[0]) * new_count, GFP_KERNEL); + +- if (t->etm_regs) { +- dev_dbg(&dev->dev, "ETM already initialized\n"); +- ret = -EBUSY; ++ if (!new_regs) { ++ dev_dbg(&dev->dev, "Failed to allocate ETM register array\n"); ++ ret = -ENOMEM; + goto out; + } ++ t->etm_regs = new_regs; + + ret = amba_request_regions(dev, NULL); + if (ret) + goto out; + +- t->etm_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res)); +- if (!t->etm_regs) { ++ t->etm_regs[t->etm_regs_count] = ++ ioremap_nocache(dev->res.start, resource_size(&dev->res)); ++ if (!t->etm_regs[t->etm_regs_count]) { + ret = -ENOMEM; + goto out_release; + } + +- amba_set_drvdata(dev, t); ++ amba_set_drvdata(dev, t->etm_regs[t->etm_regs_count]); + +- mutex_init(&t->mutex); +- t->dev = &dev->dev; +- t->flags = TRACER_CYCLE_ACC; ++ t->flags = TRACER_CYCLE_ACC | TRACER_TRACE_DATA | TRACER_BRANCHOUTPUT; + t->etm_portsz = 1; ++ t->etm_contextid_size = 3; + +- etm_unlock(t); +- (void)etm_readl(t, ETMMR_PDSR); ++ etm_unlock(t, t->etm_regs_count); ++ (void)etm_readl(t, t->etm_regs_count, ETMMR_PDSR); + /* dummy first read */ +- (void)etm_readl(&tracer, ETMMR_OSSRR); +- +- t->ncmppairs = etm_readl(t, ETMR_CONFCODE) & 0xf; +- etm_writel(t, 0x440, ETMR_CTRL); +- etm_lock(t); ++ (void)etm_readl(&tracer, t->etm_regs_count, ETMMR_OSSRR); ++ ++ etmccr = etm_readl(t, t->etm_regs_count, ETMR_CONFCODE); ++ t->ncmppairs = etmccr & 0xf; ++ if (etmccr & ETMCCR_ETMIDR_PRESENT) { ++ etmidr = etm_readl(t, t->etm_regs_count, ETMR_ID); ++ etm_version = ETMIDR_VERSION(etmidr); ++ if (etm_version >= ETMIDR_VERSION_3_1) ++ etmccer = etm_readl(t, t->etm_regs_count, ETMR_CCE); ++ } ++ etm_writel(t, t->etm_regs_count, 0x441, ETMR_CTRL); ++ etm_writel(t, t->etm_regs_count, new_count, ETMR_TRACEIDR); ++ etm_lock(t, t->etm_regs_count); + + ret = sysfs_create_file(&dev->dev.kobj, + &trace_running_attr.attr); +@@ -579,32 +924,97 @@ static int etm_probe(struct amba_device *dev, const struct amba_id *id) + if (ret) + dev_dbg(&dev->dev, "Failed to create trace_mode in sysfs\n"); + +- dev_dbg(t->dev, "ETM AMBA driver initialized.\n"); ++ ret = sysfs_create_file(&dev->dev.kobj, ++ &trace_contextid_size_attr.attr); ++ if (ret) ++ dev_dbg(&dev->dev, ++ "Failed to create trace_contextid_size in sysfs\n"); ++ ++ ret = sysfs_create_file(&dev->dev.kobj, ++ &trace_branch_output_attr.attr); ++ if (ret) ++ dev_dbg(&dev->dev, ++ "Failed to create trace_branch_output in sysfs\n"); ++ ++ if (etmccer & ETMCCER_RETURN_STACK_IMPLEMENTED) { ++ ret = sysfs_create_file(&dev->dev.kobj, ++ &trace_return_stack_attr.attr); ++ if (ret) ++ dev_dbg(&dev->dev, ++ "Failed to create trace_return_stack in sysfs\n"); ++ } ++ ++ if (etmccer & ETMCCER_TIMESTAMPING_IMPLEMENTED) { ++ ret = sysfs_create_file(&dev->dev.kobj, ++ &trace_timestamp_attr.attr); ++ if (ret) ++ dev_dbg(&dev->dev, ++ "Failed to create trace_timestamp in sysfs\n"); ++ } ++ ++ ret = sysfs_create_file(&dev->dev.kobj, &trace_range_attr.attr); ++ if (ret) ++ dev_dbg(&dev->dev, "Failed to create trace_range in sysfs\n"); ++ ++ if (etm_version < ETMIDR_VERSION_PFT_1_0) { ++ ret = sysfs_create_file(&dev->dev.kobj, ++ &trace_data_range_attr.attr); ++ if (ret) ++ dev_dbg(&dev->dev, ++ "Failed to create trace_data_range in sysfs\n"); ++ } else { ++ tracer.flags &= ~TRACER_TRACE_DATA; ++ } ++ ++ dev_dbg(&dev->dev, "ETM AMBA driver initialized.\n"); ++ ++ /* Enable formatter if there are multiple trace sources */ ++ if (new_count > 1) ++ t->etb_fc = ETBFF_ENFCONT | ETBFF_ENFTC; ++ ++ t->etm_regs_count = new_count; + + out: ++ mutex_unlock(&t->mutex); + return ret; + + out_unmap: +- iounmap(t->etm_regs); ++ iounmap(t->etm_regs[t->etm_regs_count]); + + out_release: + amba_release_regions(dev); + ++ mutex_unlock(&t->mutex); + return ret; + } + + static int etm_remove(struct amba_device *dev) + { +- struct tracectx *t = amba_get_drvdata(dev); +- +- iounmap(t->etm_regs); +- t->etm_regs = NULL; +- +- amba_release_regions(dev); ++ int i; ++ struct tracectx *t = &tracer; ++ void __iomem *etm_regs = amba_get_drvdata(dev); + + sysfs_remove_file(&dev->dev.kobj, &trace_running_attr.attr); + sysfs_remove_file(&dev->dev.kobj, &trace_info_attr.attr); + sysfs_remove_file(&dev->dev.kobj, &trace_mode_attr.attr); ++ sysfs_remove_file(&dev->dev.kobj, &trace_range_attr.attr); ++ sysfs_remove_file(&dev->dev.kobj, &trace_data_range_attr.attr); ++ ++ mutex_lock(&t->mutex); ++ for (i = 0; i < t->etm_regs_count; i++) ++ if (t->etm_regs[i] == etm_regs) ++ break; ++ for (; i < t->etm_regs_count - 1; i++) ++ t->etm_regs[i] = t->etm_regs[i + 1]; ++ t->etm_regs_count--; ++ if (!t->etm_regs_count) { ++ kfree(t->etm_regs); ++ t->etm_regs = NULL; ++ } ++ mutex_unlock(&t->mutex); ++ ++ iounmap(etm_regs); ++ amba_release_regions(dev); + + return 0; + } +@@ -614,6 +1024,10 @@ static struct amba_id etm_ids[] = { + .id = 0x0003b921, + .mask = 0x0007ffff, + }, ++ { ++ .id = 0x0003b950, ++ .mask = 0x0007ffff, ++ }, + { 0, 0 }, + }; + +@@ -631,6 +1045,8 @@ static int __init etm_init(void) + { + int retval; + ++ mutex_init(&tracer.mutex); ++ + retval = amba_driver_register(&etb_driver); + if (retval) { + printk(KERN_ERR "Failed to register etb\n"); +diff --git a/arch/arm/kernel/hibernate.c b/arch/arm/kernel/hibernate.c +index cfb354f..785c461 100644 +--- a/arch/arm/kernel/hibernate.c ++++ b/arch/arm/kernel/hibernate.c +@@ -24,6 +24,7 @@ + #include + #include "reboot.h" + ++#ifndef CONFIG_HISI_SNAPSHOT_BOOT + int pfn_is_nosave(unsigned long pfn) + { + unsigned long nosave_begin_pfn = virt_to_pfn(&__nosave_begin); +@@ -42,7 +43,9 @@ void notrace restore_processor_state(void) + { + local_fiq_enable(); + } ++#endif + ++#ifndef CONFIG_HISI_SNAPSHOT_BOOT + /* + * Snapshot kernel memory and reset the system. + * +@@ -105,3 +108,4 @@ int swsusp_arch_resume(void) + resume_stack + ARRAY_SIZE(resume_stack)); + return 0; + } ++#endif +diff --git a/arch/arm/kernel/io.c b/arch/arm/kernel/io.c +index 9203cf8..9d5a96f 100644 +--- a/arch/arm/kernel/io.c ++++ b/arch/arm/kernel/io.c +@@ -79,6 +79,8 @@ void _memset_io(volatile void __iomem *dst, int c, size_t count) + dst++; + } + } ++DEFINE_RAW_SPINLOCK(hisilcon_lock); ++EXPORT_SYMBOL(hisilcon_lock); + + EXPORT_SYMBOL(_memcpy_fromio); + EXPORT_SYMBOL(_memcpy_toio); +diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c +index a74b53c..2412558 100644 +--- a/arch/arm/kernel/kgdb.c ++++ b/arch/arm/kernel/kgdb.c +@@ -144,6 +144,8 @@ int kgdb_arch_handle_exception(int exception_vector, int signo, + + static int kgdb_brk_fn(struct pt_regs *regs, unsigned int instr) + { ++ if (user_mode(regs)) ++ return -1; + kgdb_handle_exception(1, SIGTRAP, 0, regs); + + return 0; +@@ -151,6 +153,8 @@ static int kgdb_brk_fn(struct pt_regs *regs, unsigned int instr) + + static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int instr) + { ++ if (user_mode(regs)) ++ return -1; + compiled_break = 1; + kgdb_handle_exception(1, SIGTRAP, 0, regs); + +diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c +index ecefea4..617ec4a 100644 +--- a/arch/arm/kernel/process.c ++++ b/arch/arm/kernel/process.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -60,9 +61,46 @@ static const char *isa_modes[] __maybe_unused = { + "ARM" , "Thumb" , "Jazelle", "ThumbEE" + }; + ++#ifdef CONFIG_SMP ++void arch_trigger_all_cpu_backtrace(void) ++{ ++ smp_send_all_cpu_backtrace(); ++} ++#else ++void arch_trigger_all_cpu_backtrace(void) ++{ ++ dump_stack(); ++} ++#endif ++ + extern void call_with_stack(void (*fn)(void *), void *arg, void *sp); + typedef void (*phys_reset_t)(unsigned long); + ++#ifdef CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART ++void arm_machine_flush_console(void) ++{ ++ printk("\n"); ++ pr_emerg("Restarting %s\n", linux_banner); ++ if (console_trylock()) { ++ console_unlock(); ++ return; ++ } ++ ++ mdelay(50); ++ ++ local_irq_disable(); ++ if (!console_trylock()) ++ pr_emerg("arm_restart: Console was locked! Busting\n"); ++ else ++ pr_emerg("arm_restart: Console was locked!\n"); ++ console_unlock(); ++} ++#else ++void arm_machine_flush_console(void) ++{ ++} ++#endif ++ + /* + * A temporary stack to use for CPU reset. This is static so that we + * don't clobber it with the identity mapping. When running with this +@@ -154,6 +192,7 @@ void arch_cpu_idle_prepare(void) + + void arch_cpu_idle_enter(void) + { ++ idle_notifier_call_chain(IDLE_START); + ledtrig_cpu(CPU_LED_IDLE_START); + #ifdef CONFIG_PL310_ERRATA_769419 + wmb(); +@@ -163,6 +202,7 @@ void arch_cpu_idle_enter(void) + void arch_cpu_idle_exit(void) + { + ledtrig_cpu(CPU_LED_IDLE_END); ++ idle_notifier_call_chain(IDLE_END); + } + + #ifdef CONFIG_HOTPLUG_CPU +@@ -183,6 +223,16 @@ void arch_cpu_idle_dead(void) + */ + void machine_shutdown(void) + { ++#ifdef CONFIG_SMP ++ /* ++ * Disable preemption so we're guaranteed to ++ * run to power off or reboot and prevent ++ * the possibility of switching to another ++ * thread that might wind up blocking on ++ * one of the stopped CPUs. ++ */ ++ preempt_disable(); ++#endif + disable_nonboot_cpus(); + } + +@@ -231,6 +281,11 @@ void machine_restart(char *cmd) + local_irq_disable(); + smp_send_stop(); + ++ ++ /* Flush the console to make sure all the relevant messages make it ++ * out to the console drivers */ ++ arm_machine_flush_console(); ++ + if (arm_pm_restart) + arm_pm_restart(reboot_mode, cmd); + else +@@ -245,6 +300,77 @@ void machine_restart(char *cmd) + while (1); + } + ++/* ++ * dump a block of kernel memory from around the given address ++ */ ++static void show_data(unsigned long addr, int nbytes, const char *name) ++{ ++ int i, j; ++ int nlines; ++ u32 *p; ++ ++ /* ++ * don't attempt to dump non-kernel addresses or ++ * values that are probably just small negative numbers ++ */ ++ if (addr < PAGE_OFFSET || addr > -256UL) ++ return; ++ ++ printk("\n%s: %#lx:\n", name, addr); ++ ++ /* ++ * round address down to a 32 bit boundary ++ * and always dump a multiple of 32 bytes ++ */ ++ p = (u32 *)(addr & ~(sizeof(u32) - 1)); ++ nbytes += (addr & (sizeof(u32) - 1)); ++ nlines = (nbytes + 31) / 32; ++ ++ ++ for (i = 0; i < nlines; i++) { ++ /* ++ * just display low 16 bits of address to keep ++ * each line of the dump < 80 characters ++ */ ++ printk("%04lx ", (unsigned long)p & 0xffff); ++ for (j = 0; j < 8; j++) { ++ u32 data; ++ if (probe_kernel_address(p, data)) { ++ printk(" ********"); ++ } else { ++ printk(" %08x", data); ++ } ++ ++p; ++ } ++ printk("\n"); ++ } ++} ++ ++static void show_extra_register_data(struct pt_regs *regs, int nbytes) ++{ ++ mm_segment_t fs; ++ ++ fs = get_fs(); ++ set_fs(KERNEL_DS); ++ show_data(regs->ARM_pc - nbytes, nbytes * 2, "PC"); ++ show_data(regs->ARM_lr - nbytes, nbytes * 2, "LR"); ++ show_data(regs->ARM_sp - nbytes, nbytes * 2, "SP"); ++ show_data(regs->ARM_ip - nbytes, nbytes * 2, "IP"); ++ show_data(regs->ARM_fp - nbytes, nbytes * 2, "FP"); ++ show_data(regs->ARM_r0 - nbytes, nbytes * 2, "R0"); ++ show_data(regs->ARM_r1 - nbytes, nbytes * 2, "R1"); ++ show_data(regs->ARM_r2 - nbytes, nbytes * 2, "R2"); ++ show_data(regs->ARM_r3 - nbytes, nbytes * 2, "R3"); ++ show_data(regs->ARM_r4 - nbytes, nbytes * 2, "R4"); ++ show_data(regs->ARM_r5 - nbytes, nbytes * 2, "R5"); ++ show_data(regs->ARM_r6 - nbytes, nbytes * 2, "R6"); ++ show_data(regs->ARM_r7 - nbytes, nbytes * 2, "R7"); ++ show_data(regs->ARM_r8 - nbytes, nbytes * 2, "R8"); ++ show_data(regs->ARM_r9 - nbytes, nbytes * 2, "R9"); ++ show_data(regs->ARM_r10 - nbytes, nbytes * 2, "R10"); ++ set_fs(fs); ++} ++ + void __show_regs(struct pt_regs *regs) + { + unsigned long flags; +@@ -306,6 +432,8 @@ void __show_regs(struct pt_regs *regs) + printk("Control: %08x%s\n", ctrl, buf); + } + #endif ++ ++ show_extra_register_data(regs, 128); + } + + void show_regs(struct pt_regs * regs) +diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c +index a8e32aa..9ce02e6 100644 +--- a/arch/arm/kernel/smp.c ++++ b/arch/arm/kernel/smp.c +@@ -72,6 +72,7 @@ enum ipi_msg_type { + IPI_CPU_STOP, + IPI_IRQ_WORK, + IPI_COMPLETION, ++ IPI_CPU_BACKTRACE, + }; + + static DECLARE_COMPLETION(cpu_running); +@@ -456,6 +457,7 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = { + S(IPI_CPU_STOP, "CPU stop interrupts"), + S(IPI_IRQ_WORK, "IRQ work interrupts"), + S(IPI_COMPLETION, "completion interrupts"), ++ S(IPI_CPU_BACKTRACE, "CPU backtrace"), + }; + + static void smp_cross_call(const struct cpumask *target, unsigned int ipinr) +@@ -557,6 +559,58 @@ static void ipi_complete(unsigned int cpu) + complete(per_cpu(cpu_completion, cpu)); + } + ++static cpumask_t backtrace_mask; ++static DEFINE_RAW_SPINLOCK(backtrace_lock); ++ ++/* "in progress" flag of arch_trigger_all_cpu_backtrace */ ++static unsigned long backtrace_flag; ++ ++void smp_send_all_cpu_backtrace(void) ++{ ++ unsigned int this_cpu = smp_processor_id(); ++ int i; ++ ++ if (test_and_set_bit(0, &backtrace_flag)) ++ /* ++ * If there is already a trigger_all_cpu_backtrace() in progress ++ * (backtrace_flag == 1), don't output double cpu dump infos. ++ */ ++ return; ++ ++ cpumask_copy(&backtrace_mask, cpu_online_mask); ++ cpu_clear(this_cpu, backtrace_mask); ++ ++ pr_info("Backtrace for cpu %d (current):\n", this_cpu); ++ dump_stack(); ++ ++ pr_info("\nsending IPI to all other CPUs:\n"); ++ smp_cross_call(&backtrace_mask, IPI_CPU_BACKTRACE); ++ ++ /* Wait for up to 10 seconds for all other CPUs to do the backtrace */ ++ for (i = 0; i < 10 * 1000; i++) { ++ if (cpumask_empty(&backtrace_mask)) ++ break; ++ mdelay(1); ++ } ++ ++ clear_bit(0, &backtrace_flag); ++ smp_mb__after_atomic(); ++} ++ ++/* ++ * ipi_cpu_backtrace - handle IPI from smp_send_all_cpu_backtrace() ++ */ ++static void ipi_cpu_backtrace(unsigned int cpu, struct pt_regs *regs) ++{ ++ if (cpu_isset(cpu, backtrace_mask)) { ++ raw_spin_lock(&backtrace_lock); ++ pr_warning("IPI backtrace for cpu %d\n", cpu); ++ show_regs(regs); ++ raw_spin_unlock(&backtrace_lock); ++ cpu_clear(cpu, backtrace_mask); ++ } ++} ++ + /* + * Main handler for inter-processor interrupts + */ +@@ -623,6 +677,10 @@ void handle_IPI(int ipinr, struct pt_regs *regs) + irq_exit(); + break; + ++ case IPI_CPU_BACKTRACE: ++ ipi_cpu_backtrace(cpu, regs); ++ break; ++ + default: + printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n", + cpu, ipinr); +diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c +index 89cfdd6..32782d2 100644 +--- a/arch/arm/kernel/topology.c ++++ b/arch/arm/kernel/topology.c +@@ -23,6 +23,7 @@ + #include + + #include ++#include + #include + + /* +@@ -290,6 +291,142 @@ static struct sched_domain_topology_level arm_topology[] = { + }; + + /* ++ * cluster_to_logical_mask - return cpu logical mask of CPUs in a cluster ++ * @socket_id: cluster HW identifier ++ * @cluster_mask: the cpumask location to be initialized, modified by the ++ * function only if return value == 0 ++ * ++ * Return: ++ * ++ * 0 on success ++ * -EINVAL if cluster_mask is NULL or there is no record matching socket_id ++ */ ++int cluster_to_logical_mask(unsigned int socket_id, cpumask_t *cluster_mask) ++{ ++ int cpu; ++ ++ if (!cluster_mask) ++ return -EINVAL; ++ ++ for_each_online_cpu(cpu) ++ if (socket_id == topology_physical_package_id(cpu)) { ++ cpumask_copy(cluster_mask, topology_core_cpumask(cpu)); ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++ ++#ifdef CONFIG_SCHED_HMP ++ ++static const char * const little_cores[] = { ++ "arm,cortex-a7", ++ NULL, ++}; ++ ++static bool is_little_cpu(struct device_node *cn) ++{ ++ const char * const *lc; ++ ++ for (lc = little_cores; *lc; lc++) ++ if (of_device_is_compatible(cn, *lc)) ++ return true; ++ return false; ++} ++ ++void __init arch_get_fast_and_slow_cpus(struct cpumask *fast, ++ struct cpumask *slow) ++{ ++ struct device_node *cn = NULL; ++ int cpu; ++ ++ cpumask_clear(fast); ++ cpumask_clear(slow); ++ ++ /* ++ * Use the config options if they are given. This helps testing ++ * HMP scheduling on systems without a big.LITTLE architecture. ++ */ ++ if (strlen(CONFIG_HMP_FAST_CPU_MASK) ++ && strlen(CONFIG_HMP_SLOW_CPU_MASK)) { ++ if (cpulist_parse(CONFIG_HMP_FAST_CPU_MASK, fast)) ++ WARN(1, "Failed to parse HMP fast cpu mask!\n"); ++ if (cpulist_parse(CONFIG_HMP_SLOW_CPU_MASK, slow)) ++ WARN(1, "Failed to parse HMP slow cpu mask!\n"); ++ return; ++ } ++ ++ /* ++ * Else, parse device tree for little cores. ++ */ ++ while ((cn = of_find_node_by_type(cn, "cpu"))) { ++ ++ const u32 *mpidr; ++ int len; ++ ++ mpidr = of_get_property(cn, "reg", &len); ++ if (!mpidr || len != 4) { ++ pr_err("* %s missing reg property\n", cn->full_name); ++ continue; ++ } ++ ++ cpu = get_logical_index(be32_to_cpup(mpidr)); ++ if (cpu == -EINVAL) { ++ pr_err("couldn't get logical index for mpidr %x\n", ++ be32_to_cpup(mpidr)); ++ break; ++ } ++ ++ if (is_little_cpu(cn)) ++ cpumask_set_cpu(cpu, slow); ++ else ++ cpumask_set_cpu(cpu, fast); ++ } ++ ++ if (!cpumask_empty(fast) && !cpumask_empty(slow)) ++ return; ++ ++ /* ++ * We didn't find both big and little cores so let's call all cores ++ * fast as this will keep the system running, with all cores being ++ * treated equal. ++ */ ++ cpumask_setall(fast); ++ cpumask_clear(slow); ++} ++ ++void __init arch_get_hmp_domains(struct list_head *hmp_domains_list) ++{ ++ struct cpumask hmp_fast_cpu_mask; ++ struct cpumask hmp_slow_cpu_mask; ++ struct hmp_domain *domain; ++ ++ arch_get_fast_and_slow_cpus(&hmp_fast_cpu_mask, &hmp_slow_cpu_mask); ++ ++ /* ++ * Initialize hmp_domains ++ * Must be ordered with respect to compute capacity. ++ * Fastest domain at head of list. ++ */ ++ if (!cpumask_empty(&hmp_slow_cpu_mask)) { ++ domain = (struct hmp_domain *) ++ kmalloc(sizeof(struct hmp_domain), GFP_KERNEL); ++ cpumask_copy(&domain->possible_cpus, &hmp_slow_cpu_mask); ++ cpumask_and(&domain->cpus, cpu_online_mask, ++ &domain->possible_cpus); ++ list_add(&domain->hmp_domains, hmp_domains_list); ++ } ++ domain = (struct hmp_domain *) ++ kmalloc(sizeof(struct hmp_domain), GFP_KERNEL); ++ cpumask_copy(&domain->possible_cpus, &hmp_fast_cpu_mask); ++ cpumask_and(&domain->cpus, cpu_online_mask, &domain->possible_cpus); ++ list_add(&domain->hmp_domains, hmp_domains_list); ++} ++#endif /* CONFIG_SCHED_HMP */ ++ ++ ++/* + * init_cpu_topology is called at boot when only one cpu is running + * which prevent simultaneous write access to cpu_topology array + */ +diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S +index a9b9e22..3d71892 100644 +--- a/arch/arm/lib/memcpy.S ++++ b/arch/arm/lib/memcpy.S +@@ -55,7 +55,6 @@ + .text + + /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */ +- + ENTRY(memcpy) + + #include "copy_template.S" +diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig +index cd19433..cd5b7dc 100644 +--- a/arch/arm/mach-hisi/Kconfig ++++ b/arch/arm/mach-hisi/Kconfig +@@ -1,8 +1,7 @@ + config ARCH_HISI + bool "Hisilicon SoC Support" +- depends on ARCH_MULTI_V7 + select ARM_AMBA +- select ARM_GIC ++ select ARM_GIC if ARCH_MULTI_V7 + select ARM_TIMER_SP804 + select POWER_RESET + select POWER_RESET_HISI +@@ -40,6 +39,124 @@ config ARCH_HIX5HD2 + select PINCTRL_SINGLE + help + Support for Hisilicon HIX5HD2 SoC family ++ ++config ARCH_HI3519 ++ bool "Hisilicon Hi3519 Cortex-a7.Cortex-a17 family" if ARCH_MULTI_V7 ++ select HAVE_ARM_ARCH_TIMER ++ select ARM_CCI ++ select ARCH_HAS_RESET_CONTROLLER ++ select RESET_CONTROLLER ++ select PM_OPP ++ select PMC if SMP ++ select NEED_MACH_IO_H if PCI ++ help ++ Support for Hisilicon Hi3519 Soc family ++ ++config ARCH_HI3519V101 ++ bool "Hisilicon Hi3519V101 Cortex-a7.Cortex-a17 family" if ARCH_MULTI_V7 ++ select HAVE_ARM_ARCH_TIMER ++ select ARM_CCI ++ select ARCH_HAS_RESET_CONTROLLER ++ select RESET_CONTROLLER ++ select PM_OPP ++ select PMC if SMP ++ select NEED_MACH_IO_H if PCI ++ help ++ Support for Hisilicon Hi3519V101 Soc family ++ ++config ARCH_HI3516AV200 ++ bool "Hisilicon Hi3516AV200 Cortex-a7.Cortex-a17 family" if ARCH_MULTI_V7 ++ select HAVE_ARM_ARCH_TIMER ++ select ARM_CCI ++ select ARCH_HAS_RESET_CONTROLLER ++ select RESET_CONTROLLER ++ select PM_OPP ++ select PMC if SMP ++ select NEED_MACH_IO_H if PCI ++ help ++ Support for Hisilicon Hi3516AV200 Soc family ++ ++config ARCH_HI3559 ++ bool "Hisilicon Hi3559 Cortex-a7.Cortex-a17 family" if ARCH_MULTI_V7 ++ select HAVE_ARM_ARCH_TIMER ++ select ARM_CCI ++ select ARCH_HAS_RESET_CONTROLLER ++ select RESET_CONTROLLER ++ select PM_OPP ++ select PMC if SMP ++ select NEED_MACH_IO_H if PCI ++ help ++ Support for Hisilicon Hi3559 Soc family ++ ++config ARCH_HI3556 ++ bool "Hisilicon Hi3556 Cortex-a7.Cortex-a17 family" if ARCH_MULTI_V7 ++ select HAVE_ARM_ARCH_TIMER ++ select ARM_CCI ++ select ARCH_HAS_RESET_CONTROLLER ++ select RESET_CONTROLLER ++ select PM_OPP ++ select PMC if SMP ++ select NEED_MACH_IO_H if PCI ++ help ++ Support for Hisilicon Hi3556 Soc family ++ ++ ++if ARCH_HI3519 || ARCH_HI3519V101 || ARCH_HI3559 || ARCH_HI3556 || ARCH_HI3516AV200 ++ ++config PMC ++ bool ++ help ++ support power control for Hi3519 or Hi3519V101 or Hi3516AV200 or HI3559 Cortex-a17 or HI3556 Cortex-a17 ++ ++endif ++ ++config ARCH_HI3516CV300 ++ bool "Hisilicon Hi3516cv300 arm926ej-s family" if ARCH_MULTI_V5 ++ depends on ARCH_MULTI_V5 ++ select ARM_VIC ++ select PINCTRL ++ select PINCTRL_SINGLE ++ help ++ Support for Hisilicon Hi3516cv300 Soc family ++ ++config ARCH_HI3536C ++ bool "Hisilicon Hi3536C Cortex-a7 family" if ARCH_MULTI_V7 ++ select HAVE_ARM_ARCH_TIMER ++ select ARM_GIC ++ select ARCH_HAS_RESET_CONTROLLER ++ select RESET_CONTROLLER ++ select PINCTRL ++ select PINCTRL_SINGLE ++ select HAVE_ARM_SCU if SMP ++ help ++ Support for Hisilicon Hi3536C Soc family ++ ++config ARCH_HI3531D ++ bool "Hisilicon Hi3531D Cortex-a9 family" if ARCH_MULTI_V7 ++ select HAVE_ARM_ARCH_TIMER ++ select ARM_GIC ++ select ARCH_HAS_RESET_CONTROLLER ++ select RESET_CONTROLLER ++ select PINCTRL ++ select PINCTRL_SINGLE ++ select CACHE_L2X0 ++ select HAVE_ARM_SCU if SMP ++ select NEED_MACH_IO_H if PCI ++ help ++ Support for Hisilicon Hi3531D Soc family ++ ++config ARCH_HI3521D ++ bool "Hisilicon Hi3521D Cortex-a7 family" if ARCH_MULTI_V7 ++ select HAVE_ARM_ARCH_TIMER ++ select ARM_GIC ++ select ARCH_HAS_RESET_CONTROLLER ++ select RESET_CONTROLLER ++ select PINCTRL ++ select PINCTRL_SINGLE ++ select HAVE_ARM_SCU if SMP ++ help ++ Support for Hisilicon Hi3521D Soc family ++ + endmenu + + endif +diff --git a/arch/arm/mach-hisi/Makefile b/arch/arm/mach-hisi/Makefile +index 6b7b303..167c7b9 100644 +--- a/arch/arm/mach-hisi/Makefile ++++ b/arch/arm/mach-hisi/Makefile +@@ -6,4 +6,33 @@ CFLAGS_platmcpm.o := -march=armv7-a + + obj-y += hisilicon.o + obj-$(CONFIG_MCPM) += platmcpm.o ++ifdef CONFIG_ARCH_HI3519 ++obj-$(CONFIG_PMC) += pmc_hi3519.o ++endif ++ifdef CONFIG_ARCH_HI3519V101 ++obj-$(CONFIG_PMC) += pmc_hi3519v101.o ++endif ++ifdef CONFIG_ARCH_HI3516AV200 ++obj-$(CONFIG_PMC) += pmc_hi3516av200.o ++endif ++ifdef CONFIG_ARCH_HI3559 ++obj-$(CONFIG_PMC) += pmc_hi3559.o ++obj-$(CONFIG_PM) += pwr_hi3559.o ++endif ++ifdef CONFIG_ARCH_HI3556 ++obj-$(CONFIG_PMC) += pmc_hi3559.o ++obj-$(CONFIG_PM) += pwr_hi3559.o ++endif ++obj-$(CONFIG_ARCH_HI3536C) += pmc_hi3536c.o ++obj-$(CONFIG_ARCH_HI3531D) += pmc_hi3531d.o ++obj-$(CONFIG_ARCH_HI3521D) += pmc_hi3521d.o ++ + obj-$(CONFIG_SMP) += platsmp.o hotplug.o headsmp.o ++obj-$(CONFIG_PM) += pm.o ++obj-$(CONFIG_CACHE_L2X0) += l2cache.o ++obj-$(CONFIG_HISI_SNAPSHOT_BOOT) += fastboot/ ++ifdef CONFIG_ARCH_MULTI_V5 ++obj-$(CONFIG_HISI_SNAPSHOT_BOOT) += hibernate.o swsusp.o ++else ++obj-$(CONFIG_HISI_SNAPSHOT_BOOT) += hibernate.o swsusp.o cpu_helper_a7.o ++endif +diff --git a/arch/arm/mach-hisi/Makefile.boot b/arch/arm/mach-hisi/Makefile.boot +new file mode 100644 +index 0000000..a652afa +--- /dev/null ++++ b/arch/arm/mach-hisi/Makefile.boot +@@ -0,0 +1,18 @@ ++ifdef CONFIG_ARCH_HI3559 ++zreladdr-y := 0x88008000 ++else ++ifdef CONFIG_ARCH_HI3556 ++zreladdr-y := 0x83008000 ++else ++zreladdr-y := 0x80008000 ++endif ++ ++ifdef CONFIG_ARCH_HI3531D ++zreladdr-y := 0x40008000 ++endif ++ ++endif ++ ++params_phys-y := 0x00000100 ++initrd_phys-y := 0x00800000 ++#LOADADDR := 0x88000000 +diff --git a/arch/arm/mach-hisi/core.h b/arch/arm/mach-hisi/core.h +index 88b1f48..3ad3bec 100644 +--- a/arch/arm/mach-hisi/core.h ++++ b/arch/arm/mach-hisi/core.h +@@ -17,4 +17,38 @@ extern struct smp_operations hix5hd2_smp_ops; + extern void hix5hd2_set_cpu(int cpu, bool enable); + extern void hix5hd2_cpu_die(unsigned int cpu); + ++extern void hi3519_secondary_startup(void); ++extern void hi3519_cpu_die(unsigned int cpu); ++extern int hi3519_cpu_kill(unsigned int cpu); ++ ++extern void hi3516av200_secondary_startup(void); ++extern void hi3516av200_cpu_die(unsigned int cpu); ++extern int hi3516av200_cpu_kill(unsigned int cpu); ++ ++extern void hi3559_secondary_startup(void); ++extern void hi3559_cpu_die(unsigned int cpu); ++extern int hi3559_cpu_kill(unsigned int cpu); ++ ++extern void hi3536c_secondary_startup(void); ++extern void hi3536c_cpu_die(unsigned int cpu); ++extern int hi3536c_cpu_kill(unsigned int cpu); ++void hi3536c_scu_power_up(int cpu); ++ ++extern void hi3531d_secondary_startup(void); ++extern void hi3531d_cpu_die(unsigned int cpu); ++extern int hi3531d_cpu_kill(unsigned int cpu); ++void hi3531d_scu_power_up(int cpu); ++ ++extern void hi3521d_secondary_startup(void); ++extern void hi3521d_cpu_die(unsigned int cpu); ++extern int hi3521d_cpu_kill(unsigned int cpu); ++void hi3521d_scu_power_up(int cpu); ++ ++extern void hi_pmc_power_up(void); ++extern void hi_pmc_power_up_done(void); ++extern void hi_pmc_set_ac_inactive(void); ++extern void hi_pmc_power_down(void); ++#ifdef CONFIG_ARCH_HI3519 ++extern void hi_pmc_kill_cpu(unsigned int cpu); ++#endif + #endif +diff --git a/arch/arm/mach-hisi/cpu_helper_a7.S b/arch/arm/mach-hisi/cpu_helper_a7.S +new file mode 100644 +index 0000000..5783ef5 +--- /dev/null ++++ b/arch/arm/mach-hisi/cpu_helper_a7.S +@@ -0,0 +1,835 @@ ++#include ++ ++ @ Aliases for mode encodings - do not change ++ .equ MODE_USR, 0x10 ++ .equ MODE_FIQ, 0x11 ++ .equ MODE_IRQ, 0x12 ++ .equ MODE_SVC, 0x13 ++ .equ MODE_MON, 0x16 @ A-profile (Security Extensions) only ++ .equ MODE_ABT, 0x17 ++ .equ MODE_UND, 0x1B ++ .equ MODE_SYS, 0x1F ++ .equ MODE_HYP, 0x1A ++ ++ .equ TTBCR_EAE, (1<<31) @ Are we using LPAE? ++ ++ .equ PFR0_THUMB_EE_SUPPORT, (1<<12) ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ ++ @ This function takes three arguments ++ @ r0: Destination start address (must be word aligned) ++ @ r1: Source start address (must be word aligned) ++ @ r2: Number of words to copy ++ @ Return value is updated destination pointer (first unwritten word) ++ ++ .global copy_words ++copy_words: ++ .func ++ push {r3} ++ cmp r2, #0 ++ beq 1f ++2: ++ ldr r3, [r1], #4 ++ str r3, [r0], #4 ++ subs r2, r2, #1 ++ bne 2b ++1: ++ pop {r3} ++ bx lr ++ ++ .endfunc ++ ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ .global save_performance_monitors ++ ++save_performance_monitors: ++ .func ++ push {r4, r8, r9, r10} ++ ++ mrc p15,0,r8,c9,c12,0 @ PMon: Control Register ++ bic r1,r8,#1 ++ mcr p15,0,r1,c9,c12,0 @ disable counter updates from here ++ isb @ 0b0 => PMCR<0> ++ mrc p15,0,r9,c9,c12,5 @ PMon: Event Counter Selection Register ++ mrc p15,0,r10,c9,c12,1 @ PMon: Count Enable Set Reg ++ stm r0!, {r8-r10} ++ mrc p15,0,r8,c9,c12,2 @ PMon: Count Enable Clear Register ++ mrc p15,0,r9,c9,c13,0 @ PMon: Cycle Counter Register ++ mrc p15,0,r10,c9,c12,3 @ PMon: Overflow flag Status Register ++ stm r0!, {r8-r10} ++ mrc p15,0,r8,c9,c14,1 @ PMon: Interrupt Enable Set Registern ++ mrc p15,0,r9,c9,c14,2 @ PMon: Interrupt Enable Clear Register ++ stm r0!, {r8-r9} ++ mrc p15,0,r8,c9,c12,0 @ Read PMon Control Register ++ ubfx r9,r8,#11,#5 @ extract # of event counters, N ++ tst r9, r9 ++ beq 1f ++ ++ mov r8,#0 ++0: ++ mcr p15,0,r8,c9,c12,5 @ PMon: select CounterN ++ isb ++ mrc p15,0,r3,c9,c13,1 @ PMon: save Event Type Register ++ mrc p15,0,r4,c9,c13,2 @ PMon: save Event Counter Register ++ stm r0!, {r3,r4} ++ add r8,r8,#1 @ increment index ++ @ cmps r8,r9 ++ cmp r8,r9 ++ bne 0b ++ ++1: ++ pop {r4, r8, r9, r10} ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global restore_performance_monitors ++restore_performance_monitors: ++ .func ++ push {r4-r6, r8-r10, lr} ++ @ NOTE: all counters disabled by PMCR ++ @<0> == 0 on reset ++ ldr r8,[r0] @ r8 = PMCR ++ add r1,r0,#20 @ r1 now points to saved PMOVSR ++ ldr r9,[r1] @ r9 = PMOVSR ++ ++ mvn r2,#0 @ generate Register of all 1's ++ mcr p15,0,r2,c9,c14,2 @ disable all counter related interrupts ++ mcr p15,0,r2,c9,c12,3 @ clear all overflow flags ++ isb ++ ++ ubfx r12,r8,#11,#5 @ extract # of event counters, N (0-31) ++ tst r12, r12 ++ beq 20f ++ ++ add r1,r0,#32 @ r1 now points to the 1st saved event ++ @counter ++ @@ Restore counters ++ mov r6,#0 ++10: ++ mcr p15,0,r6,c9,c12,5 @ PMon: select CounterN ++ isb ++ ldm r1!, {r3,r4} @ Read saved data ++ mcr p15,0,r3,c9,c13,1 @ PMon: restore Event Type Register ++ mcr p15,0,r4,c9,c13,2 @ PMon: restore Event Counter Register ++ add r6,r6,#1 @ increment index ++ @ cmps r6,r12 ++ cmp r6,r12 ++ bne 10b ++ ++20: ++ tst r9, #0x80000000 @ check for cycle count overflow flag ++ beq 40f ++ mcr p15,0,r2,c9,c13,0 @ set Cycle Counter to all 1's ++ isb ++ mov r3, #1 ++ mcr p15,0,r3,c9,c12,0 @ set the PMCR global enable bit ++ mov r3, #0x80000000 ++ mcr p15,0,r3,c9,c12,1 @ enable the Cycle Counter ++ isb ++ ++30: ++ mrc p15,0,r4,c9,c12,3 @ check cycle count overflow now set ++ movs r4,r4 @ test bit<31> ++ bpl 30b ++ mcr p15,0,r3,c9,c12,2 @ disable the Cycle Counter ++ ++40: ++ mov r1, #0 ++ mcr p15,0,r1,c9,c12,0 @ clear the PMCR global enable bit ++ isb ++ ++ @@ Restore left regs but PMCR ++ add r1,r0,#4 @ r1 now points to the PMSELR ++ ldm r1!,{r3,r4} ++ mcr p15,0,r3,c9,c12,5 @ PMon: Event Counter Selection Reg ++ mcr p15,0,r4,c9,c12,1 @ PMon: Count Enable Set Reg ++ ldm r1!, {r3,r4} ++ mcr p15,0,r4,c9,c13,0 @ PMon: Cycle Counter Register ++ ldm r1!,{r3,r4} ++ mcr p15,0,r3,c9,c14,2 @ PMon: Interrupt Enable Clear Reg ++ mcr p15,0,r4,c9,c14,1 @ PMon: Interrupt Enable Set Reg ++ ldr r3,[r1] ++ isb ++ ldr r0,[r0] ++ mcr p15,0,r0,c9,c12,0 @ restore the PM Control Register ++ isb ++ ++ pop {r4-r6, r8-r10, pc} ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global save_banked_registers ++save_banked_registers: ++ .func ++ ++ PUSH {r3, lr} ++ ++ mrs r2, CPSR @ save current mode ++ and r3, r2, #0x1f @ If we are in HYP mode then use the virt. ++ cmp r3, #MODE_HYP @ instructions to save the banked registers ++ beq save_in_hyp @ without changing the mode ++ ++ cps #MODE_SYS @ switch to System mode ++ str sp,[r0], #4 @ save the User SP ++ str lr,[r0], #4 @ save the User LR ++ cps #MODE_ABT @ switch to Abort mode ++ str sp,[r0], #4 @ save the current SP ++ mrs r3,SPSR ++ stm r0!,{r3,lr} @ save the current SPSR, LR ++ cps #MODE_UND @ switch to Undefined mode ++ str sp,[r0], #4 @ save the current SP ++ mrs r3,SPSR ++ stm r0!,{r3,lr} @ save the current SPSR, LR ++ cps #MODE_IRQ @ switch to IRQ mode ++ str sp,[r0], #4 @ save the current SP ++ mrs r3,SPSR ++ stm r0!,{r3,lr} @ save the current SPSR, LR ++ cps #MODE_FIQ @ switch to FIQ mode ++ str SP,[r0], #4 @ save the current SP ++ mrs r3,SPSR ++ stm r0!,{r8-r12,lr} @ save the current SPSR,r8-r12,LR ++ msr CPSR_cxsf, r2 @ switch back to original mode ++ ++ POP {r3, lr} ++ STR SP, [r0], #4 @ save the current SP ++ MRS r3, SPSR ++ STM r0!, {r3, r4-r12, LR} @ save the current SPSR, ++ @ r4-r12,LR ++ dsb ++ ++ bx lr ++ ++save_in_hyp : ++ @ mrs r1, SP_usr @ rewrite ++ cps #MODE_SYS @ switch to System mode ++ str sp,[r1], #4 @ save the User SP ++ stm r0!, {r1} ++ ++ @ mrs r1, SP_und @ rewrite ++ cps #MODE_UND @ switch to Undefined mode ++ str sp,[r1], #4 @ save the current SP ++ @ mrs r2, SPSR_und @ rewrite ++ cps #MODE_UND @ switch to Undefined mode ++ mrs r2,SPSR @ save the current SPSR ++ @ mrs r3, LR_und @ rewrite ++ cps #MODE_UND @ switch to Undefined mode ++ str lr,[r3], #4 @ save the current LR ++ stm r0!, {r1-r3} ++ ++ @ mrs r1, SP_abt @ rewrite ++ cps #MODE_ABT @ switch to Abort mode ++ str sp,[r1], #4 @ save the current SP ++ @ mrs r2, SPSR_abt @ rewrite ++ cps #MODE_ABT @ switch to Abort mode ++ mrs r2,SPSR @ save the current SPSR ++ @ mrs r3, LR_abt @ rewrite ++ str lr,[r3], #4 @ save the current LR ++ stm r0!, {r1-r3} ++ ++ @ mrs r1, SP_svc @ rewrite ++ cps #MODE_SVC @ switch to SVC mode ++ str sp,[r1], #4 @ save the current SP ++ @ mrs r2, SPSR_svc @ rewrite ++ cps #MODE_SVC @ switch to SVC mode ++ mrs r2,SPSR @ save the current SPSR ++ @ mrs r3, LR_svc @ rewrite ++ cps #MODE_SVC @ switch to SVC mode ++ str lr,[r3], #4 @ save the current LR ++ stm r0!, {r1-r3} ++ ++ @ mrs r1, SP_irq @ rewrite ++ cps #MODE_IRQ @ switch to IRQ mode ++ str sp,[r1], #4 @ save the current SP ++ @ mrs r2, SPSR_irq @ rewrite ++ cps #MODE_IRQ @ switch to IRQ mode ++ mrs r2,SPSR @ save the current SPSR ++ @ mrs r3, LR_irq @ rewrite ++ cps #MODE_IRQ @ switch to IRQ mode ++ str lr,[r3], #4 @ save the current LR ++ stm r0!, {r1-r3} ++ ++ @ mrs r1, SP_fiq @ rewrite ++ cps #MODE_FIQ @ switch to FIQ mode ++ str sp,[r1], #4 @ save the current SP ++ @ mrs r2, SPSR_fiq @ rewrite ++ cps #MODE_FIQ @ switch to FIQ mode ++ mrs r2,SPSR @ save the current SPSR ++ @ mrs r3, LR_fiq @ rewrite ++ cps #MODE_FIQ @ switch to FIQ mode ++ str lr,[r3], #4 @ save the current LR ++ stm r0!, {r1-r3} ++ ++ @ mrs r1, r8_fiq @ rewrite ++ @ mrs r2, r9_fiq @ rewrite ++ @ mrs r3, r10_fiq @ rewrite ++ @ stm r0!, {r1-r3} @ rewrite ++ @ mrs r1, r11_fiq @ rewrite ++ @ mrs r2, r12_fiq @ rewrite ++ @ stm r0!, {r1-r2} @ rewrite ++ cps #MODE_FIQ @ switch to FIQ mode ++ stm r0!,{r8-r12} @ save the current r8-r12 ++ ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global restore_banked_registers ++restore_banked_registers: ++ .func ++ mrs r2, CPSR @ save current mode ++ and r3, r2, #0x1f @ If we are in HYP mode then use the virt. ++ cmp r3, #MODE_HYP @ instructions to restore the banked registers ++ beq rest_in_hyp @ without changing the mode ++ ++ cps #MODE_SYS @ switch to System mode ++ ldr sp,[r0],#4 @ restore the User SP ++ ldr lr,[r0],#4 @ restore the User LR ++ cps #MODE_ABT @ switch to Abort mode ++ ldr sp,[r0],#4 @ restore the current SP ++ ldm r0!,{r3,lr} @ restore the current LR ++ msr SPSR_fsxc,r3 @ restore the current SPSR ++ cps #MODE_UND @ switch to Undefined mode ++ ldr sp,[r0],#4 @ restore the current SP ++ ldm r0!,{r3,lr} @ restore the current LR ++ msr SPSR_fsxc,r3 @ restore the current SPSR ++ cps #MODE_IRQ @ switch to IRQ mode ++ ldr sp,[r0],#4 @ restore the current SP ++ ldm r0!,{r3,lr} @ restore the current LR ++ msr SPSR_fsxc,r3 @ restore the current SPSR ++ cps #MODE_FIQ @ switch to FIQ mode ++ ldr sp,[r0],#4 @ restore the current SP ++ ldm r0!,{r8-r12,lr} @ restore the current r8-r12,LR ++ msr SPSR_fsxc,r4 @ restore the current SPSR ++ msr CPSR_cxsf, r2 @ switch back to original mode ++ ++ LDR SP, [r0], #4 @ restore the current SP ++ LDM r0!, {r3, r4-r12, LR} @ restore the current r4-r12,LR ++ MSR SPSR_fsxc, r3 @ restore the current SPSR ++ dsb ++0: ++ bx lr ++ ++rest_in_hyp: ++ ldm r0!, {r1} ++ @ msr SP_usr, r1 @ rewrite ++ cps #MODE_SYS @ switch to System mode ++ ldr sp,[r1],#4 @ restore the User SP ++ ++ ldm r0!, {r1-r3} ++ @ msr SP_und, r1 @ rewrite ++ cps #MODE_UND @ switch to Undefined mode ++ ldr sp,[r1],#4 @ restore the User SP ++ @ msr SPSR_und, r2 @ rewrite ++ cps #MODE_UND @ switch to Undefined mode ++ msr SPSR_fsxc,r2 @ restore the current SPSR ++ @ msr LR_und, r3 @ rewrite ++ cps #MODE_UND @ switch to Undefined mode ++ ldr lr,[r3],#4 @ restore the User LR ++ ++ ldm r0!, {r1-r3} ++ @ msr SP_abt, r1 @ rewrite ++ cps #MODE_ABT @ switch to Abort mode ++ ldr sp,[r1],#4 @ restore the User SP ++ @ msr SPSR_abt, r2 @ rewrite ++ cps #MODE_ABT @ switch to Abort mode ++ msr SPSR_fsxc,r2 @ restore the current SPSR ++ @ msr LR_abt, r3 @ rewrite ++ cps #MODE_ABT @ switch to Abort mode ++ ldr lr,[r3],#4 @ restore the User LR ++ ++ ldm r0!, {r1-r3} ++ @ msr SP_svc, r1 @ rewrite ++ cps #MODE_SVC @ switch to SVC mode ++ ldr sp,[r1],#4 @ restore the User SP ++ @ msr SPSR_svc, r2 @ rewrite ++ cps #MODE_SVC @ switch to SVC mode ++ msr SPSR_fsxc,r2 @ restore the current SPSR ++ @ msr LR_svc, r3 @ rewrite ++ cps #MODE_SVC @ switch to SVC mode ++ ldr lr,[r3],#4 @ restore the User LR ++ ++ ldm r0!, {r1-r3} ++ @ msr SP_irq, r1 @ rewrite ++ cps #MODE_IRQ @ switch to IRQ mode ++ ldr sp,[r1],#4 @ restore the User SP ++ @ msr SPSR_irq, r2 @ rewrite ++ cps #MODE_IRQ @ switch to IRQ mode ++ msr SPSR_fsxc,r2 @ restore the current SPSR ++ @ msr LR_irq, r3 @ rewrite ++ cps #MODE_IRQ @ switch to IRQ mode ++ ldr lr,[r3],#4 @ restore the User LR ++ ++ ldm r0!, {r1-r3} ++ @ msr SP_fiq, r1 @ rewrite ++ cps #MODE_FIQ @ switch to FIQ mode ++ ldr sp,[r1],#4 @ restore the User SP ++ @ msr SPSR_fiq, r2 @ rewrite ++ cps #MODE_FIQ @ switch to FIQ mode ++ msr SPSR_fsxc,r2 @ restore the current SPSR ++ @ msr LR_fiq, r3 @ rewrite ++ cps #MODE_FIQ @ switch to FIQ mode ++ ldr lr,[r3],#4 @ restore the User LR ++ ++ @ ldm r0!, {r1-r3} ++ @ msr r8_fiq, r1 @ rewrite ++ @ msr r9_fiq, r2 @ rewrite ++ @ msr r10_fiq, r3 @ rewrite ++ @ ldm r0!, {r1-r2} ++ @ msr r11_fiq, r1 @ rewrite ++ @ msr r12_fiq, r2 @ rewrite ++ cps #MODE_FIQ @ switch to FIQ mode ++ ldm r0!,{r8-r12} @ restore the current r8-r12 ++ ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global save_cp15 ++save_cp15: ++ .func ++ @ CSSELR Cache Size Selection Register ++ mrc p15,2,r3,c0,c0,0 ++ str r3,[r0], #4 ++ ++ @ IMPLEMENTATION DEFINED - proprietary features: ++ @ (CP15 register 15, TCM support, lockdown support, etc.) ++ ++ @ NOTE: IMP DEF registers might have save and restore order that relate ++ @ to other CP15 registers or logical grouping requirements and can ++ @ therefore occur at any point in this sequence. ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global restore_cp15 ++restore_cp15: ++ .func ++ @ CSSELR Cache Size Selection Register ++ ldr r3,[r0], #4 ++ mcr p15,2,r3,c0,c0,0 ++ ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global save_vfp ++save_vfp: ++ .func ++ @ FPU state save/restore. ++ @ FPSID,MVFR0 and MVFR1 don't get ++ @serialized/saved (Read Only). ++ mrc p15,0,r3,c1,c0,2 @ CPACR allows CP10 and CP11 access ++ ORR r2,r3,#0xF00000 ++ mcr p15,0,r2,c1,c0,2 ++ isb ++ mrc p15,0,r2,c1,c0,2 ++ and r2,r2,#0xF00000 ++ cmp r2,#0xF00000 ++ beq 0f ++ movs r2, #0 ++ b 2f ++ ++ @ Save configuration registers and enable. ++0: ++ FMRX r12,FPEXC @ vmrs r12,FPEXC ++ str r12,[r0],#4 @ Save the FPEXC ++ @ Enable FPU access to ++ @ save/restore the other registers. ++ ldr r2,=0x40000000 ++ FMXR FPEXC,r2 @ vmsr FPEXC,r2 ++ FMRX r2,FPSCR @ vmrs r2,FPSCR ++ str r2,[r0],#4 @ Save the FPSCR ++ @ Store the VFP-D16 registers. ++ vstm r0!, {D0-D15} ++ @ Check for Advanced SIMD/VFP-D32 support ++ FMRX r2,MVFR0 @ vmrs r2,MVFR0 ++ and r2,r2,#0xF @ extract the A_SIMD bitfield ++ cmp r2, #0x2 ++ blt 1f ++ @ Store the Advanced SIMD/VFP-D32 ++ @ additional registers. ++ @vstm r0!, {D16-D31} ++ ++ @ IMPLEMENTATION DEFINED: save any subarchitecture defined state ++ @ NOTE: Don't change the order of the FPEXC and CPACR restores ++ @ Restore the original En bit of FPU. ++1: ++ FMXR FPEXC,r12 @ vmsr FPEXC,r12 ++ ++ @ Restore the original CPACR value. ++2: ++ mcr p15,0,r3,c1,c0,2 ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global restore_vfp ++restore_vfp: ++ .func ++ @ FPU state save/restore. Obviously FPSID,MVFR0 and MVFR1 don't get ++ @ serialized (RO). ++ @ Modify CPACR to allow CP10 and CP11 access ++ mrc p15,0,r1,c1,c0,2 ++ ORR r2,r1,#0x00F00000 ++ mcr p15,0,r2,c1,c0,2 ++ @ Enable FPU access to save/restore ++ @ the rest of registers. ++ ldr r2,=0x40000000 ++ FMXR FPEXC, r2 @ vmsr FPEXC, r2 ++ @ Recover FPEXC and FPSCR. These will ++ @ be restored later. ++ ldm r0!,{r3,r12} ++ @ Restore the VFP-D16 registers. ++ vldm r0!, {D0-D15} ++ @ Check for Advanced SIMD/VFP-D32 support ++ FMRX r2, MVFR0 @ vmrs r2, MVFR0 ++ and r2,r2,#0xF @ extract the A_SIMD bitfield ++ cmp r2, #0x2 ++ blt 0f ++ ++ @ Store the Advanced SIMD/VFP-D32 additional registers. ++ @vldm r0!, {D16-D31} ++ ++ @ IMPLEMENTATION DEFINED: restore any subarchitecture defined state ++0: ++ @ Restore configuration registers and enable. ++ @ Restore FPSCR _before_ FPEXC since FPEXC could disable FPU ++ @ and make setting FPSCR unpredictable. ++ FMXR FPSCR,r12 @ vmsr FPSCR,r12 ++ @ Restore FPEXC after FPSCR ++ FMXR FPEXC,r3 @ vmsr FPEXC,r3 ++ @ Restore CPACR ++ @ will restore in mt_restore_control_registers ++ @ mcr p15,0,r1,c1,c0,2 ++ ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++@ Function called with two arguments: ++@ r0 contains address to store control registers ++@ r1 is non-zero if we are Secure ++ ++ .global save_control_registers ++save_control_registers: ++ .func ++ cmp r1, #0 @ Are we Secure? ++ mrc p15,0,r2,c1,c0,1 @ ACTLR - Auxiliary Control Register ++ mrc p15,0,r3,c1,c0,0 @ SCTLR - System Control Register ++ mrc p15,0,r12,c1,c0,2 @ CPACR - Coprocessor Access Control ++ @ Register ++ stm r0!, {r2-r3, r12} ++ ++ mrcne p15,0,r1,c12,c0,1 @ MVBAR - Monitor Vector Base Address ++ @ Register ++ mrcne p15,0,r2,c1,c1,0 @ Secure Configuration Register ++ mrcne p15,0,r3,c1,c1,1 @ Secure Debug Enable Register ++ mrcne p15,0,r12,c1,c1,2 @ Non-Secure Access Control Register ++ stmne r0!, {r1-r3,r12} ++ ++ mrc p15,0,r1,c13,c0,1 @ CONTEXTIDR ++ mrc p15,0,r2,c13,c0,2 @ TPIDRURW ++ mrc p15,0,r3,c13,c0,3 @ TPIDRURO ++ mrc p15,0,r12,c13,c0,4 @ TPIDRPRW ++ stm r0!, {r1-r3,r12} ++ ++ @ The next two registers are only present if ThumbEE is implemented ++ mrc p15, 0, r1, c0, c1, 0 @ Read ID_PFR0 ++ tst r1, #PFR0_THUMB_EE_SUPPORT ++ mrcne p14,6,r1,c0,c0,0 @ TEECR ++ mrcne p14,6,r2,c1,c0,0 @ TEEHBR ++ stmne r0!, {r1, r2} ++ ++ mrc p14,7,r1,c1,c0,0 @ JOSCR ++ mrc p14,7,r2,c2,c0,0 @ JMCR ++ stm r0!, {r1, r2} ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++@ Function called with two arguments: ++@ r0 contains address to read control registers ++@ r1 is non-zero if we are Secure ++ ++ .global restore_control_registers ++restore_control_registers: ++ .func ++ cmp r1, #0 @ Are we Secure? ++ ldm r0!, {r2-r3, r12} ++ mcr p15,0,r2,c1,c0,1 @ ACTLR - Auxiliary Control Register ++ mcr p15,0,r3,c1,c0,0 @ SCTLR - System Control Register ++ mcr p15,0,r12,c1,c0,2 @ CPACR - Coprocessor Access Control ++ @ Register ++ ++ ldmne r0!, {r1-r3,r12} ++ mcrne p15,0,r1,c12,c0,1 @ MVBAR - Monitor Vector Base Address ++ @ Register ++ mcrne p15,0,r2,c1,c1,0 @ Secure Configuration Register ++ mcrne p15,0,r3,c1,c1,1 @ Secure Debug Enable Register ++ mcrne p15,0,r12,c1,c1,2 @ Non-Secure Access Control Register ++ ++ ldm r0!, {r1-r3,r12} ++ mcr p15,0,r1,c13,c0,1 @ CONTEXTIDR ++ mcr p15,0,r2,c13,c0,2 @ TPIDRURW ++ mcr p15,0,r3,c13,c0,3 @ TPIDRURO ++ mcr p15,0,r12,c13,c0,4 @ TPIDRPRW ++ ++ @ The next two registers are only present if ThumbEE is implemented ++ mrc p15, 0, r1, c0, c1, 0 @ Read ID_PFR0 ++ tst r1, #PFR0_THUMB_EE_SUPPORT ++ ldmne r0!, {r1,r2} ++ mcrne p14,6,r1,c0,c0,0 @ TEECR ++ mcrne p14,6,r2,c1,c0,0 @ TEEHBR ++ ++ ldm r0!, {r1, r2} ++ mcr p14,7,r1,c1,c0,0 @ JOSCR ++ mcr p14,7,r2,c2,c0,0 @ JMCR ++ isb ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global save_mmu ++save_mmu: ++ .func ++ push {r4, r5, r6, r7} ++ @ ASSUMPTION: no useful fault address / fault status information ++ ++ mrc p15,0,r4,c12,c0,0 @ VBAR ++ mrc p15,0,r5,c2,c0,2 @ TTBCR ++ tst r5, #TTBCR_EAE @ Are we using LPAE? ++ ++ @ save 32 or 64 bit TTBRs ++ mrceq p15,0,r6,c2,c0,0 @ 32 bit TTBR0 ++ mrceq p15,0,r7,c2,c0,1 @ 32 bit TTBR1 ++ mrrcne p15,0,r6,r7,c2 @ 64 bit TTBR0 ++ stm r0!, {r4-r7} ++ mrrcne p15,1,r6,r7,c2 @ 64 bit TTBR1 ++ stmne r0!, {r6-r7} ++ ++ mrc p15,0,r4,c3,c0,0 @ DACR ++ mrc p15,0,r5,c7,c4,0 @ PAR ++ mrc p15,0,r6,c10,c2,0 @ PRRR ++ mrc p15,0,r7,c10,c2,1 @ NMRR ++ stm r0!, {r4-r7} ++ ++ pop {r4, r5, r6, r7} ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global restore_mmu ++restore_mmu: ++ .func ++ push {r4, r5, r6, r7} ++ ldm r0!, {r4-r7} ++ mcr p15,0,r4,c12,c0,0 @ VBAR ++ mcr p15,0,r5,c2,c0,2 @ TTBCR ++ ++ tst r5, #TTBCR_EAE @ Are we using LPAE? ++ ++ @ restore 32 or 64 bit TTBRs ++ mcreq p15,0,r6,c2,c0,0 @ 32 bit TTBR0 ++ mcreq p15,0,r7,c2,c0,1 @ 32 bit TTBR1 ++ mcrrne p15,0,r6,r7,c2 @ 64-bit TTBR0 ++ ldmne r0!, {r6-r7} ++ mcrrne p15,1,r6,r7,c2 @ 64-bit TTBR1 ++ ++ ldm r0!, {r4-r7} ++ mcr p15,0,r4,c3,c0,0 @ DACR ++ mcr p15,0,r5,c7,c4,0 @ PAR ++ mcr p15,0,r6,c10,c2,0 @ PRRR ++ mcr p15,0,r7,c10,c2,1 @ NMRR ++ ++ pop {r4, r5, r6, r7} ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global save_mpu ++save_mpu: ++ .func ++ mrc p15, 0, r1, c0, c0, 4 @ Read MPUIR ++ and r1, r1, #0xff00 ++ lsr r1, r1, #8 @ Extract number of MPU regions ++ ++ @ Loop over the number of regions ++10: ++ cmp r1, #0 ++ beq 20f ++ sub r1, r1, #1 ++ mcr p15, 0, r1, c6, c2, 0 @ Write RGNR ++ mrc p15, 0, r2, c6, c1, 0 @ Read MPU Region Base Address Register ++ mrc p15, 0, r3, c6, c1, 2 @ Read Data MPU Region Size and Enable ++ @ Register ++ mrc p15, 0, r12, c6, c1, 4 @ Read Region access control Register ++ stm r0!, {r2, r3, r12} ++ b 10b ++ ++20: ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global restore_mpu ++restore_mpu: ++ .func ++ mrc p15, 0, r1, c0, c0, 4 @ Read MPUIR ++ and r1, r1, #0xff00 ++ lsr r1, r1, #8 @ Extract number of MPU regions ++ ++ @ Loop over the number of regions ++10: ++ cmp r1, #0 ++ beq 20f ++ ldm r0!, {r2, r3, r12} ++ sub r1, r1, #1 ++ mcr p15, 0, r1, c6, c2, 0 @ Write RGNR ++ mcr p15, 0, r2, c6, c1, 0 @ Write MPU Region Base Address ++ @ Register ++ mcr p15, 0, r3, c6, c1, 2 @ Write Data MPU Region Size and Enable ++ @ Register ++ mcr p15, 0, r12, c6, c1, 4 @ Write Region access control Register ++ b 10b ++ ++20: ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++@ If r1 is 0, we assume that the OS is not using the Virtualization extensions, ++@ and that the warm boot code will set up CNTHCTL correctly. If r1 is non-zero ++@ then CNTHCTL is saved and restored ++@ CNTP_CVAL will be preserved as it is in the always-on domain. ++ ++ .global save_generic_timer ++save_generic_timer: ++ .func ++ mrc p15,0,r2,c14,c2,1 @ read CNTP_CTL ++ mrc p15,0,r3,c14,c2,0 @ read CNTP_TVAL ++ mrc p15,0,r12,c14,c1,0 @ read CNTKCTL ++ stm r0!, {r2, r3, r12} ++ cmp r1, #0 ++ mrcne p15,4,r1,c14,c1,0 @ read CNTHCTL ++ strne r1, [r0], #4 ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global restore_generic_timer ++restore_generic_timer: ++ .func ++ ldm r0!, {r2, r3, r12} ++ mcr p15,0,r3,c14,c2,0 @ write CNTP_TVAL ++ mcr p15,0,r12,c14,c1,0 @ write CNTKCTL ++ mcr p15,0,r2,c14,c2,1 @ write CNTP_CTL ++ cmp r1, #0 ++ ldrne r1, [r0], #4 ++ mcrne p15,4,r1,c14,c1,0 @ write CNTHCTL ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global save_fault_status ++save_fault_status: ++ .func ++ mrc p15,0,r1,c6,c0,0 @ read DFAR ++ mrc p15,0,r2,c6,c0,2 @ read IFAR ++ mrc p15,0,r3,c5,c0,0 @ read DFSR ++ mrc p15,0,r12,c5,c0,1 @ read IFSR ++ stm r0!, {r1,r2,r3,r12} ++ mrc p15,0,r1,c5,c1,0 @ read ADFSR ++ mrc p15,0,r2,c5,c1,1 @ read AIFSR ++ stm r0!, {r1,r2} ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global restore_fault_status ++restore_fault_status: ++ .func ++ ldm r0!, {r1,r2,r3,r12} ++ mcr p15,0,r1,c6,c0,0 @ write DFAR ++ mcr p15,0,r2,c6,c0,2 @ write IFAR ++ mcr p15,0,r3,c5,c0,0 @ write DFSR ++ mcr p15,0,r12,c5,c0,1 @ write IFSR ++ ldm r0!, {r1,r2} ++ mcr p15,0,r1,c5,c1,0 @ write ADFSR ++ mcr p15,0,r2,c5,c1,1 @ write AIFSR ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global write_cntp_ctl ++write_cntp_ctl: ++ .func ++ mcr p15, 0, r0, c14, c2, 1 ++ dsb ++ isb ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global read_cpuid ++read_cpuid: ++ .func ++ mrc p15, 0, r0, c0, c0, 5 ++ ands r0, r0, #0xf ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global read_clusterid ++read_clusterid: ++ .func ++ mrc p15, 0, r0, c0, c0, 5 ++ lsr r0, r0, #0x8 ++ ands r0, r0, #0xf ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global read_nsacr ++read_nsacr: ++ .func ++ mrc p15, 0, r0, c1, c1, 2 ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++ ++ .global invalidate_unified_TLB_inner_shareable ++invalidate_unified_TLB_inner_shareable: ++ .func ++ mov r0, #0 ++ mcr p15, 0, r0, c8, c3, 0 ++ bx lr ++ .endfunc ++ ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +diff --git a/arch/arm/mach-hisi/fastboot/Makefile b/arch/arm/mach-hisi/fastboot/Makefile +new file mode 100644 +index 0000000..99e1a02 +--- /dev/null ++++ b/arch/arm/mach-hisi/fastboot/Makefile +@@ -0,0 +1,4 @@ ++obj-y += hibernate_umh.o ++obj-y += hibernate_misc.o ++obj-y += hibernate_pmmon.o ++#obj-y += hibernate_fs.o +diff --git a/arch/arm/mach-hisi/fastboot/fastboot_bootldr_info.c b/arch/arm/mach-hisi/fastboot/fastboot_bootldr_info.c +new file mode 100644 +index 0000000..1d62568 +--- /dev/null ++++ b/arch/arm/mach-hisi/fastboot/fastboot_bootldr_info.c +@@ -0,0 +1,258 @@ ++#include ++#include ++#include ++#include ++ ++/* error message prefix */ ++#define ERRP "bootinfo: " ++ ++/* debug macro */ ++#if 0 ++#define dbg(x) do { printk("BOOTINFO-CMDLINE-PART: "); printk x; } while(0) ++#else ++#define dbg(x) ++#endif ++ ++struct boot_partition { ++ char *name; ++ uint64_t size; ++ uint64_t offset; ++}; ++ ++struct cmdline_boot_partition { ++ int num_parts; ++ struct boot_partition *parts; ++}; ++ ++static char *bootpart_cmdline; ++ ++static struct cmdline_boot_partition *boot_partitions; ++ ++int __init fastboot_find_bootpartition(const char *name, ++ unsigned long long *offset, unsigned long long *size) ++{ ++ struct boot_partition *part; ++ int i; ++ ++ if (!boot_partitions) { ++ pr_err("%s: could not found partinfo\n", __func__); ++ return -EFAULT; ++ } ++ ++ for (i = 0; i < boot_partitions->num_parts; i++) { ++ part = boot_partitions->parts + i; ++ if (strcmp(name, part->name) == 0) { ++ *offset = part->offset; ++ *size = part->size; ++ return 0; ++ } ++ } ++ ++ pr_err("%s: could not found %s\n", __func__, name); ++ return -ENOENT; ++} ++ ++/* strongly based on drivers/mtd/cmdlinepart.c */ ++static struct boot_partition __init *newbootpart(char *s, ++ char **retptr, ++ int *num_parts, ++ int this_part, ++ unsigned char **extra_mem_ptr, ++ int extra_mem_size) ++{ ++ struct boot_partition *parts; ++ unsigned long long size; ++ unsigned long long offset = 0; ++ char *name; ++ int name_len; ++ unsigned char *extra_mem; ++ char delim; ++ ++ size = memparse(s, &s); ++ ++ /* check for offset */ ++ if (*s == '@') { ++ s++; ++ offset = memparse(s, &s); ++ } ++ /* now look for name */ ++ delim = 0; ++ if (*s == '(') ++ delim = ')'; ++ ++ if (delim) { ++ char *p; ++ name = ++s; ++ p = strchr(name, delim); ++ if (!p) { ++ pr_err(ERRP "no closing %c found\n", delim); ++ return NULL; ++ } ++ name_len = p - name; ++ s = p + 1; ++ } else { ++ name = NULL; ++ name_len = 13; /* Partition_000 */ ++ } ++ ++ /* record name length for memory allocation later */ ++ extra_mem_size += name_len + 1; ++ ++ /* test if more partitions are following */ ++ if (*s == ',') { ++ /* more partitions follow, parse them */ ++ parts = newbootpart(s + 1, &s, num_parts, this_part + 1, ++ &extra_mem, extra_mem_size); ++ if (!parts) ++ return NULL; ++ } else { ++ /* this is the last partition: allocate space for all */ ++ int alloc_size; ++ ++ *num_parts = this_part + 1; ++ alloc_size = *num_parts * sizeof(struct boot_partition) ++ + extra_mem_size; ++ parts = kzalloc(alloc_size, GFP_KERNEL); ++ if (!parts) { ++ pr_err(ERRP "out of memory\n"); ++ return NULL; ++ } ++ extra_mem = (unsigned char *)(parts + *num_parts); ++ } ++ ++ /* enter this partition (offset will be calculated later if it is zero at this point) */ ++ parts[this_part].size = size; ++ parts[this_part].offset = offset; ++ if (name) ++ strlcpy(extra_mem, name, name_len + 1); ++ else ++ sprintf(extra_mem, "Partition_%03d", this_part); ++ parts[this_part].name = extra_mem; ++ extra_mem += name_len + 1; ++ ++ dbg(("partition %d: name <%s>, offset %llx, size %llx\n", ++ this_part, ++ parts[this_part].name, ++ parts[this_part].offset, ++ parts[this_part].size)); ++ ++ /* return (updated) pointer to extra_mem memory */ ++ if (extra_mem_ptr) ++ *extra_mem_ptr = extra_mem; ++ ++ /* return (updated) pointer command line string */ ++ *retptr = s; ++ ++ /* return partition table */ ++ return parts; ++} ++ ++/* strongly based on drivers/mtd/cmdlinepart.c */ ++static int __init bootpart_cmdline_parse(char *s) ++{ ++ struct cmdline_boot_partition *this_bootpart = NULL; ++ struct boot_partition *parts = NULL; ++ int num_parts; ++ ++ if (!s) ++ return 0; ++ ++ parts = newbootpart(s, /* cmdline */ ++ &s, /* out: updated cmdline ptr */ ++ &num_parts, /* out: number of parts */ ++ 0, /* first partition */ ++ (unsigned char**)&this_bootpart, /* out: extra mem */ ++ sizeof(*this_bootpart) + sizeof(void*)-1 /*alignment*/); ++ if(!parts) { ++ /* ++ * An error occurred. We're either: ++ * a) out of memory, or ++ * b) in the middle of the partition spec ++ * Either way, this part is hosed and we're ++ * unlikely to succeed in parsing any more ++ */ ++ return 0; ++ } ++ ++ /* align this_bootpart */ ++ this_bootpart = (struct cmdline_boot_partition *) ++ ALIGN((unsigned long)this_bootpart, sizeof(void*)); ++ /* enter results */ ++ this_bootpart->parts = parts; ++ this_bootpart->num_parts = num_parts; ++ ++ /* does another spec follow? */ ++ if (*s != '\0') ++ pr_err(ERRP "bad character after partition (%c)\n", *s); ++ ++ boot_partitions = this_bootpart; ++ ++ return 0; ++} ++ ++static void *bootpartinfo_seq_start(struct seq_file *file, loff_t *index) ++{ ++ if (!boot_partitions) ++ return NULL; ++ if (*index >= boot_partitions->num_parts) ++ return NULL; ++ return boot_partitions->parts + *index; ++} ++ ++static void *bootpartinfo_seq_next(struct seq_file *file, void *data, ++ loff_t *index) ++{ ++ if (data == NULL) ++ return NULL; ++ if (!boot_partitions) ++ return NULL; ++ (*index)++; ++ if (*index >= boot_partitions->num_parts) ++ return NULL; ++ return boot_partitions->parts + *index; ++} ++ ++static void bootpartinfo_seq_stop(struct seq_file *file, void *data) ++{ ++} ++ ++static int bootpartinfo_seq_show(struct seq_file *file, void *data) ++{ ++ struct boot_partition *bpart = data; ++ return seq_printf(file, "0x%016llx@0x%016llx: %s\n", ++ bpart->size, bpart->offset, bpart->name); ++} ++ ++static const struct seq_operations bootpartinfo_seq_ops = { ++ .start = bootpartinfo_seq_start, ++ .next = bootpartinfo_seq_next, ++ .stop = bootpartinfo_seq_stop, ++ .show = bootpartinfo_seq_show, ++}; ++ ++static int bootpartinfo_proc_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &bootpartinfo_seq_ops); ++} ++ ++static const struct file_operations bootpartinfo_proc_fops = { ++ .open = bootpartinfo_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = seq_release, ++}; ++ ++static int __init fastboot_bootloader_info_init(void) ++{ ++ bootpart_cmdline_parse(bootpart_cmdline); ++ proc_create("bootpartinfo", 0444, NULL, &bootpartinfo_proc_fops); ++ return 0; ++} ++module_init(fastboot_bootloader_info_init); ++ ++static int __init bootpart_setup(char *s) ++{ ++ bootpart_cmdline = s; ++ return 1; ++} ++__setup("bootparts=", bootpart_setup); +diff --git a/arch/arm/mach-hisi/fastboot/fastboot_pm.h b/arch/arm/mach-hisi/fastboot/fastboot_pm.h +new file mode 100644 +index 0000000..277781c +--- /dev/null ++++ b/arch/arm/mach-hisi/fastboot/fastboot_pm.h +@@ -0,0 +1,8 @@ ++ ++extern int fastboot_pm_call_umh(char *event_str, unsigned long event); ++ ++extern void __exit fastboot_hibernation_misc_exit(void); ++extern int __init fastboot_hibernation_misc_init(void); ++ ++extern int fastboot_hibernate_fs_suspend(void); ++extern int fastboot_hibernate_fs_resume(void); +diff --git a/arch/arm/mach-hisi/fastboot/hibernate_bdev.c b/arch/arm/mach-hisi/fastboot/hibernate_bdev.c +new file mode 100644 +index 0000000..4eee2e6 +--- /dev/null ++++ b/arch/arm/mach-hisi/fastboot/hibernate_bdev.c +@@ -0,0 +1,261 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct hibernate_bdev { ++ const char *path; ++ struct mutex lock; ++ int devidx; ++ struct gendisk *disk; ++ struct request_queue *rq; ++ spinlock_t queue_lock; ++ struct task_struct *thread; ++ struct file *filp; ++ atomic_t opened; ++ void *priv; ++}; ++ ++static int HB_BDEV_MAJOR = 0; ++static const char *HB_BDEV_NAME = "hb_bdev"; ++ ++static sector_t HB_OFFSET; ++static sector_t HB_SIZE; ++ ++extern int __init fastboot_find_bootpartition(const char *name, ++ unsigned long long *offset, unsigned long long *size); ++ ++static int hb_bdev_thread(void *arg); ++ ++static inline int __hb_init_env(void) ++{ ++ unsigned long long ofs, sz; ++ int n = fastboot_find_bootpartition("hibernate", &ofs, &sz); ++ if (n < 0) ++ return n; ++ HB_OFFSET = ofs >> 9; ++ HB_SIZE = sz >> 9; ++ ++ if (!HB_BDEV_MAJOR) ++ HB_BDEV_MAJOR = register_blkdev(HB_BDEV_MAJOR, HB_BDEV_NAME); ++ ++ return 0; ++} ++ ++static int hb_bdev_open(struct block_device *bdev, fmode_t mode) ++{ ++ struct hibernate_bdev *hb = bdev->bd_disk->private_data; ++ ++ int devidx = MINOR(bdev->bd_dev); ++ if (!hb) ++ return -ERESTARTSYS; ++ ++ if (IS_ERR_OR_NULL(hb->filp)) { ++ hb->filp = filp_open(hb->path, O_RDWR|O_SYNC | O_LARGEFILE, 0); ++ if (!hb->filp) ++ hb->filp = ERR_PTR(-ERESTARTSYS); ++ if (!IS_ERR(hb->filp)) { ++ hb->thread = kthread_run(hb_bdev_thread, hb, ++ "%s%d", HB_BDEV_NAME, devidx); ++ if (IS_ERR(hb->thread)) { ++ int ret = PTR_ERR(hb->thread); ++ filp_close(hb->filp, current->files); ++ hb->filp = ERR_PTR(-ERESTARTSYS); ++ return ret; ++ } ++ } ++ } ++ ++ if (IS_ERR_OR_NULL(hb->filp)) ++ return PTR_ERR(hb->filp); ++ ++ atomic_inc(&hb->opened); ++ return 0; ++} ++ ++static int hb_bdev_release(struct gendisk *disk, fmode_t mode) ++{ ++ struct hibernate_bdev *hb = disk->private_data; ++ if (!hb) ++ return -ENXIO; ++ if (atomic_dec_and_test(&hb->opened)) { ++ kthread_stop(hb->thread); ++ if (!IS_ERR_OR_NULL(hb->filp)) ++ filp_close(hb->filp, current->files); ++ hb->filp = ERR_PTR(-ENODEV); ++ } ++ return 0; ++} ++ ++static const struct block_device_operations hb_bdev_ops = { ++ .owner = THIS_MODULE, ++ .open = hb_bdev_open, ++ .release = hb_bdev_release, ++}; ++ ++static int hb_bdev_do_request(struct hibernate_bdev *hb, ++ struct request *req) ++{ ++ unsigned long long offset_tmp; ++ unsigned long long offset, len; ++ char *buf; ++ int ret; ++ ++ if (!hb->filp) ++ return -ENODEV; ++ /*modify because linux3.x change, --liucan*/ ++#if 0 ++ if (!blk_fs_request(req)) ++ return -EIO; ++#else ++ if (req->cmd_type != REQ_TYPE_FS) ++ return 0; ++#endif ++ ++ if (blk_rq_pos(req) + blk_rq_cur_sectors(req) > ++ get_capacity(req->rq_disk)) ++ return -ENOSPC; ++ ++ offset = (blk_rq_pos(req) + HB_OFFSET) << 9; ++ len = blk_rq_cur_bytes(req); ++ buf = req->buffer; ++ ++ offset_tmp = offset; ++ ++ switch(rq_data_dir(req)) { ++ case READ: ++ ret = vfs_read(hb->filp, (char __user*)buf, len, &offset_tmp); ++ rq_flush_dcache_pages(req); ++ break; ++ case WRITE: ++ rq_flush_dcache_pages(req); ++ ret = vfs_write(hb->filp, (char __user*)buf, len, &offset_tmp); ++ break; ++ default: ++ pr_err("%s: Unknown request %u\n", __func__, rq_data_dir(req)); ++ return -EIO; ++ } ++ ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int hb_bdev_thread(void *arg) ++{ ++ struct hibernate_bdev *hb = arg; ++ struct request_queue *rq = hb->rq; ++ struct request *req = NULL; ++ ++ set_fs(get_ds()); ++ ++ spin_lock_irq(rq->queue_lock); ++ ++ while (!kthread_should_stop()) { ++ int res; ++ ++ if (!req && !(req = blk_fetch_request(rq))) { ++ set_current_state(TASK_INTERRUPTIBLE); ++ spin_unlock_irq(rq->queue_lock); ++ schedule(); ++ spin_lock_irq(rq->queue_lock); ++ continue; ++ } ++ ++ spin_unlock_irq(rq->queue_lock); ++ ++ mutex_lock(&hb->lock); ++ res = hb_bdev_do_request(hb, req); ++ mutex_unlock(&hb->lock); ++ ++ spin_lock_irq(rq->queue_lock); ++ ++ if (!__blk_end_request_cur(req, res)) ++ req = NULL; ++ } ++ ++ if (req) ++ __blk_end_request_all(req, -EIO); ++ ++ spin_unlock_irq(rq->queue_lock); ++ ++ return 0; ++} ++ ++static void hb_bdev_request(struct request_queue *rq) ++{ ++ struct hibernate_bdev *hb; ++ struct request *req = NULL; ++ ++ hb = rq->queuedata; ++ ++ if (!hb) ++ while ((req = blk_fetch_request(rq)) != NULL) ++ __blk_end_request_all(req, -ENODEV); ++ else ++ wake_up_process(hb->thread); ++} ++ ++static int hibernate_add_blkdev(int devidx, const char *path) ++{ ++ struct hibernate_bdev *hb; ++ struct gendisk *gd; ++ ++ hb = kzalloc(sizeof(*hb), GFP_KERNEL); ++ if (!hb) ++ return -ENOMEM; ++ hb->path = path; ++ mutex_init(&hb->lock); ++ atomic_set(&hb->opened, 0); ++ hb->filp = ERR_PTR(-ENODEV); ++ ++ gd = alloc_disk(1); ++ if (!gd) { ++ kfree(hb); ++ return -ENOMEM; ++ } ++ ++ hb->disk = gd; ++ gd->private_data = hb; ++ gd->major = HB_BDEV_MAJOR; ++ gd->first_minor = devidx; ++ gd->fops = &hb_bdev_ops; ++ snprintf(gd->disk_name, sizeof(gd->disk_name), "%s%d", ++ HB_BDEV_NAME, devidx); ++ ++ set_capacity(gd, HB_SIZE); ++ ++ spin_lock_init(&hb->queue_lock); ++ hb->rq = blk_init_queue(hb_bdev_request, &hb->queue_lock); ++ if (!hb->rq) { ++ kfree(gd); ++ kfree(hb); ++ return -ENOMEM; ++ } ++ hb->rq->queuedata = hb; ++ blk_queue_logical_block_size(hb->rq, 4096); ++ gd->queue = hb->rq; ++ ++ add_disk(gd); ++ ++ return 0; ++} ++ ++static int __init hibernate_bdev_init(void) ++{ ++ if (__hb_init_env() < 0) ++ return 0; ++ hibernate_add_blkdev(0, "/dev/block/mmcblk0"); ++ return 0; ++} ++late_initcall(hibernate_bdev_init); +diff --git a/arch/arm/mach-hisi/fastboot/hibernate_fs.c b/arch/arm/mach-hisi/fastboot/hibernate_fs.c +new file mode 100644 +index 0000000..6e179fe +--- /dev/null ++++ b/arch/arm/mach-hisi/fastboot/hibernate_fs.c +@@ -0,0 +1,1910 @@ ++/* ++ * Todo ++ * - save & restore inotify kernel space watches ++ * - save & restore eventpolls ++ * - save & restore file locks ++ * - save & restore file mapping ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define pr_err_bug_if(condition, fmt, ...) \ ++ do { \ ++ if (unlikely(condition)) { \ ++ printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__); \ ++ BUG(); \ ++ } \ ++ } while (0) ++ ++#define pr_err_if(condition, fmt, ...) \ ++ do { \ ++ if (unlikely(condition)) \ ++ printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__); \ ++ } while (0) ++ ++ ++struct saved_mountpoint { ++ struct list_head node; ++ char *dev_name; ++ char *dir_name; ++ char *type; ++ char *data; ++#define MNT_MOVED (MNT_INTERNAL << 1) ++ unsigned long flags; ++}; ++ ++static LIST_HEAD(saved_mountpoints); ++ ++static char path_buf_a[PATH_MAX]; ++static char path_buf_b[PATH_MAX]; ++ ++static inline char *__d_path_wrapper(struct path *path, bool b) ++{ ++ if (!b) ++ return d_path(path, &path_buf_a[0], sizeof(path_buf_a)); ++ else ++ return d_path(path, &path_buf_b[0], sizeof(path_buf_b)); ++} ++ ++static inline char *d_path_wrapper(struct path *path) ++{ ++ return __d_path_wrapper(path, 0); ++} ++ ++static inline char *d_path_of_file(struct file *file) ++{ ++ return d_path_wrapper(&file->f_path); ++} ++ ++static inline char *d_path_of_mnt(struct vfsmount *mnt) ++{ ++ struct path mntpath = { .dentry = mnt->mnt_root, .mnt = mnt }; ++ return d_path_wrapper(&mntpath); ++} ++ ++static bool is_rw_bdev(struct vfsmount *mnt) ++{ ++ struct super_block *sb; ++ bool rw_bdev = false; ++ ++ if (!mnt || !mnt->mnt_sb) ++ goto out; ++ ++ spin_lock(&sb_lock); ++ sb = mnt->mnt_sb; ++ ++ if (!hlist_unhashed(&sb->s_instances) && ++ MAJOR(sb->s_dev) != 0 && ++ sb->s_bdi != &noop_backing_dev_info && ++ !__mnt_is_readonly(mnt)) { ++ rw_bdev = true; ++ } ++ spin_unlock(&sb_lock); ++ ++out: ++ return rw_bdev; ++} ++ ++extern spinlock_t vfsmount_lock; ++ ++/* self included */ ++static bool have_rw_bdev_parent(struct vfsmount *self) ++{ ++ struct vfsmount *parent = self; ++ bool have_rw_bdev = true; ++ ++ spin_lock(&vfsmount_lock); ++repeat: ++ have_rw_bdev = is_rw_bdev(parent); ++ if (have_rw_bdev) ++ goto out; ++ ++ if (!IS_ROOT(parent->mnt_mountpoint)) { ++ parent = parent->mnt_parent; ++ goto repeat; ++ } ++out: ++ spin_unlock(&vfsmount_lock); ++ return have_rw_bdev; ++} ++ ++static inline struct mnt_namespace *get_init_mnt_ns(void) ++{ ++ struct nsproxy *nsp; ++ ++ rcu_read_lock(); ++ nsp = task_nsproxy(&init_task); ++ BUG_ON(!(nsp && nsp->mnt_ns)); ++ get_mnt_ns(nsp->mnt_ns); ++ rcu_read_unlock(); ++ ++ return nsp->mnt_ns; ++} ++ ++static bool null_check(struct vfsmount *mnt) ++{ ++ return true; ++} ++ ++static int ++iterate_mounts_safe_reverse(int (*f)(struct vfsmount *, void *), ++ bool (*check)(struct vfsmount *), void *arg) ++{ ++ struct mnt_namespace *mnt_ns; ++ struct vfsmount *mnt, *tmp; ++ int error = 0; ++ ++ if (!check) ++ check = null_check; ++ ++ mnt_ns = get_init_mnt_ns(); ++ list_for_each_entry_safe_reverse(mnt, tmp, &mnt_ns->list, mnt_list) { ++ if (!check(mnt)) ++ continue; ++ ++ mntget(mnt); ++ error = f(mnt, arg); ++ mntput_no_expire(mnt); ++ if (error) ++ goto out; ++ } ++ ++out: ++ put_mnt_ns(mnt_ns); ++ return error; ++} ++ ++extern struct dentry *lookup_hash(struct nameidata *nd); ++ ++/* copied from do_rmdir */ ++static long do_kern_rmdir(const char *pathname) ++{ ++ int error = 0; ++ struct dentry *dentry; ++ struct nameidata nd; ++ ++ error = path_lookup(pathname, LOOKUP_PARENT, &nd); ++ if (error) ++ return error; ++ ++ switch(nd.last_type) { ++ case LAST_DOTDOT: ++ error = -ENOTEMPTY; ++ goto exit1; ++ case LAST_DOT: ++ error = -EINVAL; ++ goto exit1; ++ case LAST_ROOT: ++ error = -EBUSY; ++ goto exit1; ++ } ++ ++ nd.flags &= ~LOOKUP_PARENT; ++ ++ mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); ++ dentry = lookup_hash(&nd); ++ error = PTR_ERR(dentry); ++ if (IS_ERR(dentry)) ++ goto exit2; ++ error = mnt_want_write(nd.path.mnt); ++ if (error) ++ goto exit3; ++ error = security_path_rmdir(&nd.path, dentry); ++ if (error) ++ goto exit4; ++ error = vfs_rmdir(nd.path.dentry->d_inode, dentry); ++exit4: ++ mnt_drop_write(nd.path.mnt); ++exit3: ++ dput(dentry); ++exit2: ++ mutex_unlock(&nd.path.dentry->d_inode->i_mutex); ++exit1: ++ path_put(&nd.path); ++ return error; ++} ++ ++/* move to /dev/, mostly writable and living on ram */ ++#define SAFE_ROOT "/dev/hib_safe/" ++ ++static void mount_saved_mountpoints(void) ++{ ++ struct saved_mountpoint *saved, *tmp; ++ bool move = false; ++ ++ list_for_each_entry_safe(saved, tmp, &saved_mountpoints, node) { ++ int error; ++ char *dir; ++ char *dev; ++ ++ pr_info("PM:FS: restore mount [%s:%s]\n", ++ saved->dir_name, saved->dev_name); ++ pr_debug("PM:FS: type : %s\n", saved->type); ++ pr_debug("PM:FS: flags : 0x%08lx\n", saved->flags); ++ pr_debug("PM:FS: data : %s\n", ++ saved->data ? saved->data : "null"); ++ ++ error = do_mount(saved->dev_name, saved->dir_name, ++ saved->type, saved->flags, saved->data); ++ move = saved->flags & MS_MOVE; ++ ++ dir = move ? saved->dev_name : saved->dir_name; ++ dev = move ? saved->dir_name : saved->dev_name; ++ ++ if (error) { ++ pr_err("PM:FS: %s failed [%s:%s] (%d)\n", ++ move ? "move mount" : "mount", ++ dir, dev, error); ++ } else { ++ pr_debug("PM:FS: %s partition [%s:%s]\n", ++ move ? "moved" : "mounted", dir, dev); ++ } ++ ++ if (move) { ++ struct path moved; ++ int error = kern_path(dev, 0, &moved); ++ if (!error) { ++ struct mnt_namespace *ns = ++ get_init_mnt_ns(); ++ list_move_tail(&moved.mnt->mnt_list, ++ &ns->list); ++ put_mnt_ns(ns); ++ path_put(&moved); ++ } ++ do_kern_rmdir(saved->dev_name); ++ } ++ ++ list_del(&saved->node); ++ kfree(saved->dir_name); ++ kfree(saved->dev_name); ++ kfree(saved->type); ++ if (saved->data) ++ free_page((unsigned long)saved->data); ++ kfree(saved); ++ } ++} ++ ++static inline int get_s_flags_from_mnt(struct vfsmount *mnt) ++{ ++ int mnt_flags = mnt->mnt_flags; ++ int s_flags = mnt->mnt_sb->s_flags; ++ ++ if (mnt_flags & MNT_RELATIME) ++ s_flags &= ~MS_NOATIME; ++ if (mnt_flags & MNT_NOSUID) ++ s_flags |= MS_NOSUID; ++ if (mnt_flags & MNT_NODEV) ++ s_flags |= MS_NODEV; ++ if (mnt_flags & MNT_NOEXEC) ++ s_flags |= MS_NOEXEC; ++ if (mnt_flags & MNT_NOATIME) ++ s_flags |= MS_NOATIME; ++ if (mnt_flags & MNT_NODIRATIME) ++ s_flags |= MS_NODIRATIME; ++ if (mnt_flags & MNT_READONLY) ++ s_flags |= MS_RDONLY; ++ if (!(mnt_flags & (MNT_RELATIME | MNT_NOATIME))) ++ s_flags |= MS_STRICTATIME; ++ if (mnt_flags & MNT_MOVED) ++ s_flags |= MS_MOVE; ++ ++ return s_flags; ++} ++ ++static int save_mountpoint(struct vfsmount *mnt, const char *dir_name) ++{ ++ struct saved_mountpoint *save; ++ const char *options; ++ const char *dev_name; ++ int error = -ENOMEM; ++ ++ /* when moved, need to get old path */ ++ if (mnt->mnt_flags & MNT_MOVED) { ++ dev_name = d_path_of_mnt(mnt); ++ mnt->mnt_flags &= ~MNT_MOVED; ++ } else { ++ dev_name = mnt->mnt_devname; ++ } ++ ++ save = kzalloc(sizeof(*save), GFP_ATOMIC); ++ if (!save) ++ return -ENOMEM; ++ ++ pr_info("PM:FS: save partition [%s:%s]\n", dir_name, mnt->mnt_devname); ++ pr_debug("PM:FS: type : %s\n", mnt->mnt_sb->s_type->name); ++ pr_debug("PM:FS: flags : 0x%08lx\n", mnt->mnt_sb->s_flags); ++ pr_debug("PM:FS: data : %s\n", mnt->mnt_sb->s_options); ++ ++ INIT_LIST_HEAD(&save->node); ++ ++ save->flags = get_s_flags_from_mnt(mnt); ++ save->dir_name = kstrdup(dir_name, GFP_ATOMIC); ++ if (!save->dir_name) ++ goto free_save; ++ save->dev_name = kstrdup(dev_name, GFP_ATOMIC); ++ if (!save->dev_name) ++ goto free_dirname; ++ save->type = kstrdup(mnt->mnt_sb->s_type->name, GFP_ATOMIC); ++ if (!save->type) ++ goto free_devname; ++ rcu_read_lock(); ++ options = rcu_dereference(mnt->mnt_sb->s_options); ++ if (options && options[0]) { ++ save->data = (char *)__get_free_page(GFP_ATOMIC); ++ if (!save->data) { ++ rcu_read_unlock(); ++ goto free_type; ++ } ++ memset(save->data, 0, PAGE_SIZE); ++ strncpy(save->data, options, PAGE_SIZE); ++ } ++ rcu_read_unlock(); ++ ++ list_add(&save->node, &saved_mountpoints); ++ ++ return 0; ++ ++free_type: ++ kfree(save->type); ++free_devname: ++ kfree(save->dev_name); ++free_dirname: ++ kfree(save->dir_name); ++free_save: ++ kfree(save); ++ return error; ++} ++ ++static bool check_if_task_running(struct super_block *sb) ++{ ++ struct task_struct *task; ++ bool running = false; ++ ++ /* check if running process */ ++ read_lock(&tasklist_lock); ++ for_each_process(task) { ++ struct fs_struct *fs; ++ task_lock(task); ++ fs = task->fs; ++ if (!fs) { ++ goto next; ++ } ++ read_lock(&fs->lock); ++ if (sb == fs->root.mnt->mnt_sb) { ++ pr_debug("PM:FS: task [%s] is running on [%s] (root)\n", ++ &task->comm[0], d_path_wrapper(&fs->root)); ++ running = true; ++ } ++ if (sb == fs->pwd.mnt->mnt_sb) { ++ pr_debug("PM:FS: task [%s] is running on [%s] (pwd)\n", ++ &task->comm[0], d_path_wrapper(&fs->pwd)); ++ running = true; ++ } ++ read_unlock(&fs->lock); ++ next: ++ task_unlock(task); ++ } ++ read_unlock(&tasklist_lock); ++ ++ return running; ++} ++ ++static bool check_if_file_opening(struct super_block *sb) ++{ ++ bool opening = false; ++ ++ file_list_lock(); ++ if (!list_empty(&sb->s_files)) { ++#if defined(DEBUG) ++ struct file *file; ++ list_for_each_entry(file, &sb->s_files, f_u.fu_list) { ++ pr_debug("PM:FS: file [%s] is still open\n", ++ d_path_of_file(file)); ++ } ++#endif ++ opening = true; ++ } ++ file_list_unlock(); ++ ++ return opening; ++} ++ ++#ifdef CONFIG_INOTIFY_USER ++ ++extern struct srcu_struct fsnotify_grp_srcu; ++extern struct list_head fsnotify_groups; ++extern const struct fsnotify_ops inotify_fsnotify_ops; ++ ++static bool check_if_inotify_user_watching(struct super_block *sb) ++{ ++ struct fsnotify_group *group; ++ bool watching = false; ++ int idx; ++ ++ /* check if inotify_user */ ++ idx = srcu_read_lock(&fsnotify_grp_srcu); ++ list_for_each_entry_rcu(group, &fsnotify_groups, group_list) { ++ spin_lock(&group->mark_lock); ++ if (group->ops == &inotify_fsnotify_ops) { ++ struct fsnotify_mark_entry *entry; ++ list_for_each_entry(entry, ++ &group->mark_entries, g_list) { ++ struct inode *inode = entry->inode; ++#if defined(DEBUG) ++ struct dentry *dentry; ++#endif ++ if (sb != inode->i_sb) ++ continue; ++#if defined(DEBUG) ++ dentry = d_find_alias(inode); ++ pr_debug("PM:FS: inotify [%s] still watching\n", ++ dentry->d_name.name); ++ dput(dentry); ++#endif ++ watching = true; ++ } ++ } ++ spin_unlock(&group->mark_lock); ++ } ++ srcu_read_unlock(&fsnotify_grp_srcu, idx); ++ ++ return watching; ++} ++#else ++static inline bool check_if_inotify_user_watching(struct super_block *sb) ++{ ++ return false; ++} ++#endif ++ ++extern struct vfsmount *next_mnt(struct vfsmount *p, struct vfsmount *root); ++ ++/* copied from may_umount_tree */ ++static bool check_if_mnt_holding(struct vfsmount *mnt) ++{ ++ bool holding = false; ++ int actual_refs = 0; ++ int minimum_refs = 0; ++ struct vfsmount *p; ++ ++ spin_lock(&vfsmount_lock); ++ for (p = mnt; p; p = next_mnt(p, mnt)) { ++ actual_refs += atomic_read(&p->mnt_count); ++ minimum_refs += 2; ++ } ++ spin_unlock(&vfsmount_lock); ++ ++ if (actual_refs > minimum_refs) { ++ pr_debug("PM:FS: [%s] actual_refs:%d,minimum_refs:%d\n", ++ d_path_of_mnt(mnt), actual_refs, minimum_refs); ++ holding = true; ++ } ++ ++ return holding; ++} ++ ++static bool check_if_unmountable(struct vfsmount *mnt) ++{ ++ struct super_block *sb = mnt->mnt_sb; ++ bool opening, running, watching, holding; ++ char *p = d_path_of_mnt(mnt); ++ ++ if (!sb) { ++ return false; ++ } ++ ++ holding = check_if_mnt_holding(mnt); ++ watching = check_if_inotify_user_watching(sb); ++ opening = check_if_file_opening(sb); ++ running = check_if_task_running(sb); ++ ++ pr_err_if(holding, "PM:FS: Still Holding [%s:%s]\n", ++ p, mnt->mnt_devname); ++ pr_err_if(watching, "PM:FS: Still Watching [%s:%s]\n", ++ p, mnt->mnt_devname); ++ pr_err_if(opening, "PM:FS: Still Opening [%s:%s]\n", ++ p, mnt->mnt_devname); ++ pr_err_if(running, "PM:FS: Still Running [%s:%s]\n", ++ p, mnt->mnt_devname); ++ ++ return !holding && !opening && !running && !watching; ++} ++ ++static inline void thaw_flusher(void) ++{ ++ struct task_struct *task, *g; ++ read_lock(&tasklist_lock); ++ do_each_thread(g, task) { ++ if (task->flags & PF_FLUSHER) ++ thaw_process(task); ++ } while_each_thread(g, task); ++ read_unlock(&tasklist_lock); ++} ++ ++static inline void freeze_flusher(void) ++{ ++ struct task_struct *task, *g; ++ read_lock(&tasklist_lock); ++ do_each_thread(g, task) { ++ if (task->flags & PF_FLUSHER) ++ freeze_task(task, false); ++ } while_each_thread(g, task); ++ read_unlock(&tasklist_lock); ++} ++ ++/* copied from sys_mkdirat */ ++static int kern_mkdirat(const char *name, int mode) ++{ ++ struct dentry *dentry; ++ struct nameidata nd; ++ int error; ++ ++ error = path_lookup(name, LOOKUP_PARENT, &nd); ++ if (error) ++ goto out_err; ++ ++ dentry = lookup_create(&nd, 1); ++ error = PTR_ERR(dentry); ++ if (IS_ERR(dentry)) ++ goto out_unlock; ++ ++ error = mnt_want_write(nd.path.mnt); ++ if (error) ++ goto out_dput; ++ error = security_path_mkdir(&nd.path, dentry, mode); ++ if (error) ++ goto out_drop_write; ++ error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); ++out_drop_write: ++ mnt_drop_write(nd.path.mnt); ++out_dput: ++ dput(dentry); ++out_unlock: ++ mutex_unlock(&nd.path.dentry->d_inode->i_mutex); ++ path_put(&nd.path); ++out_err: ++ return error; ++} ++ ++static inline int mkdir_safe(void) ++{ ++ int error = kern_mkdirat(SAFE_ROOT, 755); ++ if (error != -EEXIST) ++ return error; ++ ++ return 0; ++} ++ ++static int mkdir_on_safe(const char *name, int mode, char **safe_dir) ++{ ++ static char safe_path[PATH_MAX]; ++ int error; ++ ++ error = mkdir_safe(); ++ if (error) ++ return error; ++ ++ snprintf(&safe_path[0], sizeof(safe_path), "%s/%s", SAFE_ROOT, name); ++ ++ error = kern_mkdirat(&safe_path[0], 755); ++ if (error) ++ return error; ++ ++ if (safe_dir) ++ *safe_dir = &safe_path[0]; ++ ++ return error; ++} ++ ++static int do_move_mount_to_safe(struct vfsmount *mnt, char *from) ++{ ++ char *to; ++ char temp[9]; ++ int error; ++ ++ /* FIXME - means nothing */ ++ sprintf(&temp[0], "%p", mnt); ++ error = mkdir_on_safe(temp, 755, &to); ++ if (error) ++ return error; ++ ++ error = do_mount(from, to, NULL, MS_MOVE, NULL); ++ if (error) ++ return error; ++ ++ /* MNT_MOVED set here to pick it up during resumption and cleared. */ ++ mnt->mnt_flags |= MNT_MOVED; ++ return error; ++} ++ ++/* FIXME - Is it enough ? */ ++static inline bool is_on_ram(struct vfsmount *mnt) ++{ ++ return MAJOR(mnt->mnt_sb->s_dev) == 0 ? true : false; ++} ++ ++struct umount_mnt { ++ struct list_head node; ++ struct vfsmount *mnt; ++}; ++ ++extern int do_umount(struct vfsmount *mnt, int flags); ++ ++static int unmount_rw_backing_dev(struct vfsmount *mnt, void *unused, ++ int is_on_ram) ++{ ++ struct path path = { .dentry = mnt->mnt_root, .mnt = mnt }; ++ char *orig = __d_path_wrapper(&path, true /* b */); ++ bool move = false; ++ int error; ++ ++ /* ++ * need to move a mount, it is not neccessary to check_if_unmountable() ++ */ ++ if (is_on_ram) { ++ move = true; ++ error = do_move_mount_to_safe(mnt, orig); ++ /* d_path_mnt() gives different path after here */ ++ } else { ++ if (check_if_unmountable(mnt)) ++ error = do_umount(mnt, 0); ++ else { ++ pr_err("PM:FS: [%s:%s] is unmountable\n", ++ d_path_of_mnt(mnt), mnt->mnt_devname); ++ error = -EBUSY; ++ } ++ } ++ ++ if (error) { ++ pr_err("PM:FS: %s failed [%s:%s] (%d)\n", ++ move ? "move mount" : "unmount", ++ orig, ++ move ? d_path_of_mnt(mnt) : mnt->mnt_devname, ++ error); ++ } else { ++#if defined(DEBUG) ++ pr_debug("PM:FS: %s partition [%s:%s]\n", ++ move ? "moved" : "unmounted", ++ orig, ++ move ? d_path_of_mnt(mnt) : mnt->mnt_devname); ++#endif ++ error = save_mountpoint(mnt, orig); ++ } ++ ++ return error; ++} ++ ++static int collect_mnt_on_rw_backing_devs(struct vfsmount *mnt, void *list) ++{ ++ struct list_head *umount_list = list; ++ struct umount_mnt *umount; ++ ++ umount = kmalloc(sizeof(*umount), GFP_KERNEL); ++ if (unlikely(!umount)) ++ return -ENOMEM; ++ ++ INIT_LIST_HEAD(&umount->node); ++ umount->mnt = mntget(mnt); ++ ++ list_add_tail(&umount->node, umount_list); ++ return 0; ++} ++ ++static int unmount_rw_backing_devs(void) ++{ ++ LIST_HEAD(umount_list); ++ struct umount_mnt *umount, *tmp; ++ int error; ++ ++ error = iterate_mounts_safe_reverse(collect_mnt_on_rw_backing_devs, ++ have_rw_bdev_parent, &umount_list); ++ ++ thaw_flusher(); ++ ++ list_for_each_entry_safe(umount, tmp, &umount_list, node) { ++ struct vfsmount *mnt = umount->mnt; ++ int is_ram = 0; ++ ++ list_del(&umount->node); ++ kfree(umount); ++ ++ if (is_on_ram(mnt)) is_ram = 1; ++ error = unmount_rw_backing_dev(mnt, NULL, is_ram); ++ if (!error && !is_ram /* !-EBUSY */) { ++ pr_err_bug_if(atomic_read(&mnt->mnt_count) != 1, ++ "PM:FS: " ++ "mount count should be 1 but %d\n", ++ atomic_read(&mnt->mnt_count)); ++ } ++ /* mnt will be destroyed if no error */ ++ mntput_no_expire(mnt); ++ } ++ ++ freeze_flusher(); ++ return error; ++} ++ ++static LIST_HEAD(saved_task_fs_list); ++ ++struct saved_task_fs { ++ struct list_head list; ++ ++ struct task_struct *task; ++ char *root; ++ char *pwd; ++}; ++ ++static struct saved_task_fs *alloc_saved_task_fs(struct task_struct *task, ++ bool move_root, bool move_pwd) ++{ ++ struct fs_struct *fs = task->fs; ++ int root_len = 0; ++ int pwd_len = 0; ++ int null_len = 0; ++ struct saved_task_fs *saved; ++ ++ read_lock(&fs->lock); ++ ++ if (move_root) { ++ root_len = strlen(d_path_wrapper(&fs->root)); ++ null_len++; ++ } ++ if (move_pwd) { ++ pwd_len = strlen(d_path_wrapper(&fs->pwd)); ++ null_len++; ++ } ++ ++ saved = kzalloc(sizeof(*saved) + root_len + pwd_len + null_len, ++ GFP_ATOMIC); ++ if (!saved) ++ goto unlock; ++ ++ INIT_LIST_HEAD(&saved->list); ++ saved->task = task; ++ ++ if (move_root) { ++ saved->root = (char *)saved + sizeof(*saved); ++ strcpy(saved->root, d_path_wrapper(&fs->root)); ++ } ++ if (move_pwd) { ++ if (saved->root) ++ saved->pwd = saved->root + root_len + 1; ++ else ++ saved->pwd = (char *)saved + sizeof(*saved); ++ strcpy(saved->pwd, d_path_wrapper(&fs->pwd)); ++ } ++ ++unlock: ++ read_unlock(&fs->lock); ++ return saved; ++} ++ ++static int move_task_fs_to(struct task_struct *task, ++ const char *root, const char *pwd) ++{ ++ struct path root_path, *old_root = NULL; ++ struct path pwd_path; ++ int error; ++ ++ if (root) { ++ error = kern_path(root, LOOKUP_FOLLOW, &root_path); ++ if (error) { ++ pr_err("PM:FS: failed to get root path [%s]\n", root); ++ return error; ++ } ++ ++ /* to rollback root when moving pwd fails */ ++ old_root = &task->fs->root; ++ path_get(old_root); ++ ++ set_fs_root(task->fs, &root_path); ++ path_put(&root_path); ++ } ++ if (pwd) { ++ error = kern_path(pwd, LOOKUP_FOLLOW, &pwd_path); ++ if (error) { ++ pr_err("PM:FS: failed to get pwd path [%s]\n", pwd); ++ goto out; ++ } ++ ++ set_fs_pwd(task->fs, &pwd_path); ++ path_put(&pwd_path); ++ } ++ ++out: ++ if (old_root) { ++ if (error) ++ set_fs_root(task->fs, old_root); ++ path_put(old_root); ++ } ++ ++ return error; ++} ++ ++static int move_task_fs_to_safe(struct task_struct *task, ++ bool move_root, bool move_pwd) ++{ ++ struct saved_task_fs *saved; ++ char *root = NULL; ++ char *pwd = NULL; ++ int error; ++ ++ if (!move_root && !move_pwd) ++ return 0; ++ ++ /* sleeping function called from invalid context */ ++ error = mkdir_safe(); ++ if (error) ++ return error; ++ ++ error = -ENOMEM; ++ saved = alloc_saved_task_fs(task, move_root, move_pwd); ++ if (!saved) ++ goto rm_safe; ++ ++ if (move_root) { ++ root = SAFE_ROOT; ++ pr_info("PM:FS: move task [%s] on root:%s to %s\n", ++ &task->comm[0], ++ d_path_wrapper(&task->fs->root), root); ++ ++ } ++ if (move_pwd) { ++ pwd = SAFE_ROOT; ++ pr_info("PM:FS: move task [%s] on pwd:%s to %s\n", ++ &task->comm[0], ++ d_path_wrapper(&task->fs->pwd), pwd); ++ } ++ ++ error = move_task_fs_to(task, root, pwd); ++ if (error) ++ goto free_saved; ++ ++ list_add(&saved->list, &saved_task_fs_list); ++ return 0; ++ ++free_saved: ++ kfree(saved); ++rm_safe: ++ do_kern_rmdir(SAFE_ROOT); ++ return error; ++} ++ ++static int save_task_fs_on_rw_backing_devs(void) ++{ ++ struct task_struct *task; ++ int error = 0; ++ ++ for_each_process(task) { ++ struct fs_struct *fs; ++ bool move_root = false; ++ bool move_pwd = false; ++ ++ fs = task->fs; ++ if (!fs) ++ goto next; ++ ++ if (have_rw_bdev_parent(fs->root.mnt)) ++ move_root = true; ++ if (have_rw_bdev_parent(fs->pwd.mnt)) ++ move_pwd = true; ++ ++ if (move_root || move_pwd) ++ error = move_task_fs_to_safe(task, move_root, move_pwd); ++ ++ next: ++ if (error) ++ break; ++ } ++ ++ return error; ++} ++ ++static void restore_saved_task_fs(void) ++{ ++ struct saved_task_fs *saved, *n; ++ ++ list_for_each_entry_safe(saved, n, &saved_task_fs_list, list) { ++ int error; ++ ++ if (saved->root) ++ pr_debug("PM:FS: restore task [%s] on root:%s\n", ++ &saved->task->comm[0], saved->root); ++ if (saved->pwd) ++ pr_debug("PM:FS: restore task [%s] on pwd:%s\n", ++ &saved->task->comm[0], saved->pwd); ++ ++ error = move_task_fs_to(saved->task, saved->root, saved->pwd); ++ if (unlikely(error)) { ++ pr_err("PM:FS: failed to restore fs for task [%s] " ++ "root:%s pwd:%s (%d)\n", ++ &saved->task->comm[0], ++ saved->root ? saved->root : "null", ++ saved->pwd ? saved->pwd : "null", ++ error); ++ } ++ list_del(&saved->list); ++ kfree(saved); ++ } ++ ++ do_kern_rmdir(SAFE_ROOT); ++} ++ ++/* ++ * FIXME ++ * How can inode-like one be used instead of file_path ? ++ * in other words, use alternative inode structure and file_path as a dentry ++ */ ++static LIST_HEAD(file_path_list); ++ ++struct file_path { ++ struct list_head node; /* file_path_list */ ++ struct list_head fobj_list; ++ ++ char *path; ++ ++ //counter ++}; ++ ++/* one per struct file instance */ ++struct file_object { ++ struct list_head same_fpath; /* fobj_list */ ++ struct list_head fdesc_list; ++ ++ struct file *file; /* make it null when f_count is zero */ ++ ++ atomic_long_t count; ++ unsigned int flags; ++ fmode_t mode; ++ loff_t pos; ++ loff_t size; ++}; ++ ++struct file_descriptor { ++ struct list_head same_fobj; /* fdesc_list */ ++ ++ int fd; ++ struct task_struct *task; ++}; ++ ++static loff_t noentry_lseek(struct file *file, loff_t offset, int orig) ++{ ++ pr_err("PM:FS: [%s] lseek(%lld, %d) on [%s]", ++ ¤t->comm[0], offset, orig, d_path_of_file(file)); ++ return -EBADF; ++} ++ ++static ssize_t noentry_read(struct file *file, ++ char __user *buf, size_t count, loff_t *ppos) ++{ ++ pr_err("PM:FS: [%s] read(%p, %d, %lld) on [%s]\n", ++ ¤t->comm[0], buf, count, *ppos, d_path_of_file(file)); ++ return -EBADF; ++} ++ ++static ssize_t noentry_write(struct file *file, ++ const char __user *buf, size_t count, ++ loff_t *ppos) ++{ ++ pr_err("PM:FS: [%s] write(%p, %d, %lld) on [%s]\n", ++ ¤t->comm[0], buf, count, *ppos, d_path_of_file(file)); ++ return -EBADF; ++} ++ ++static int noentry_release(struct inode *inode, struct file *file) ++{ ++ pr_err("PM:FS: [%s] close() on [%s]\n", ++ ¤t->group_leader->comm[0], d_path_of_file(file)); ++ return 0; ++} ++ ++/* ++ * FIXME ++ * - check whether more callbacks are necessary. ++ */ ++static const struct file_operations noentry_fops = { ++ .llseek = noentry_lseek, ++ .read = noentry_read, ++ .write = noentry_write, ++ .release = noentry_release, ++}; ++ ++static inline bool is_noentry_file(const struct file *file) ++{ ++ return file->f_op == &noentry_fops; ++} ++ ++/* ++ * NOTE ++ * It's not sufficient to get file path from anon_inodefs for debugging. ++ * It just gives us short "anon_inode:[kind]". We override anon_inodefs's ++ * d_dname() so we can get full file path pointed by noentry file. ++ * This means all d_op is overriden and could be a problem if anon_inodefs ++ * implements other dentry operations. But it does not at this time. ++ */ ++/* copied from dynamic_dname but it uses bigger static buffer */ ++static char *__dynamic_dname(struct dentry *dentry, ++ char *buffer, int buflen, const char *fmt, ...) ++{ ++ va_list args; ++ int sz; ++ ++ va_start(args, fmt); ++ sz = vsnprintf(path_buf_b, sizeof(path_buf_b), fmt, args) + 1; ++ va_end(args); ++ ++ if (sz > sizeof(path_buf_b) || sz > buflen) ++ return ERR_PTR(-ENAMETOOLONG); ++ ++ buffer += buflen - sz; ++ return memcpy(buffer, path_buf_b, sz); ++} ++ ++static char *noentry_dentry_dname(struct dentry *dentry, ++ char *buffer, int buflen) ++{ ++ char *p = __dynamic_dname(dentry, buffer, buflen, "noentry:%s", ++ dentry->d_name.name); ++ if (IS_ERR(p)) ++ return "noentry:nofilenameavailble"; ++ else ++ return p; ++} ++ ++static const struct dentry_operations noentry_dentry_operations = { ++ .d_dname = noentry_dentry_dname, ++}; ++ ++static struct file *get_noentry_file(const char *name) ++{ ++ struct file *file; ++ ++ file = anon_inode_getfile(name, &noentry_fops, NULL, 0); ++ if (IS_ERR(file)) ++ goto out; ++ ++ /* override d_op to get full filename */ ++ file->f_dentry->d_op = &noentry_dentry_operations; ++ ++out: ++ return file; ++} ++ ++static inline bool is_task_fd_slot_empty(struct task_struct *task, unsigned fd) ++{ ++ struct files_struct *files = task->files; ++ struct fdtable *fdt = files_fdtable(files); ++ bool is_empty = true; ++ ++ if (fd >= fdt->max_fds) { ++ is_empty = false; ++ goto out; ++ } ++ if (rcu_dereference_raw(fdt->fd[fd]) != NULL) { ++ is_empty = false; ++ goto out; ++ } ++ if (fd <= files->next_fd) ++ files->next_fd = fd + 1; ++out: ++ return is_empty; ++} ++ ++static void task_fd_install(struct task_struct *task, ++ unsigned int fd, int flags, struct file *file) ++{ ++ struct files_struct *files = task->files; ++ struct fdtable *fdt; ++ ++ spin_lock(&files->file_lock); ++ ++ fdt = files_fdtable(files); ++ BUG_ON(!is_task_fd_slot_empty(task, fd)); ++ ++ FD_SET(fd, fdt->open_fds); ++ if (flags & O_CLOEXEC) ++ FD_SET(fd, fdt->close_on_exec); ++ else ++ FD_CLR(fd, fdt->close_on_exec); ++ rcu_assign_pointer(fdt->fd[fd], file); ++ ++ spin_unlock(&files->file_lock); ++} ++ ++static off_t filp_lseek(struct file *file, off_t offset, unsigned int origin) ++{ ++ off_t retval; ++ ++ if (!file) ++ return -EBADF; ++ ++ retval = -EINVAL; ++ if (origin <= SEEK_MAX) { ++ loff_t res = vfs_llseek(file, offset, origin); ++ retval = res; ++ if (res != (loff_t)retval) ++ retval = -EOVERFLOW; ++ } ++ ++ return retval; ++} ++ ++static inline char *get_file_flags_readable(unsigned int flags, fmode_t mode) ++{ ++ static char open_flags[64]; ++ snprintf(&open_flags[0], sizeof(open_flags), ++ "%s%s%s", ++ (flags & O_ACCMODE) == O_RDWR ? "RDWR ": ++ ((flags & O_ACCMODE) == O_RDONLY ? "RD ": ++ ((flags & O_ACCMODE) == O_WRONLY ? "WR ":" ")), ++ (mode | flags) & FMODE_EXEC ? "EXEC ":" ", ++ flags & O_DIRECTORY ? "DIR ":""); ++ return &open_flags[0]; ++} ++ ++static void restore_file_descriptors(struct file_object *fobj) ++{ ++ struct file_descriptor *fdesc, *tmp; ++ ++ list_for_each_entry_safe(fdesc, tmp, &fobj->fdesc_list, same_fobj) { ++ /* ++ * Failed to open both of the original file and noentry file. ++ * leave the fd and fdslot empty so that the process's syscalls ++ * can fail with -EBADF. ++ */ ++ if (unlikely(!fobj->file)) { ++ pr_err("PM:FS: " ++ "have no file to restore [%s(%d)][fd:%d]\n", ++ &fdesc->task->comm[0], fdesc->task->pid, ++ fdesc->fd); ++ goto free; ++ } ++ /* install fd and get file instance */ ++ task_fd_install(fdesc->task, ++ fdesc->fd, fobj->flags, fobj->file); ++ get_file(fobj->file); ++ ++ pr_info("PM:FS: restore fd [%s(%d)][fd:%d]\n", ++ &fdesc->task->comm[0], fdesc->task->pid, fdesc->fd); ++ ++free: ++ list_del(&fdesc->same_fobj); ++ kfree(fdesc); ++ } ++} ++ ++static void restore_file_objects(struct file_path *fpath) ++{ ++ const char *filename = fpath->path; ++ struct file_object *fobj, *tmp; ++ ++ list_for_each_entry_safe(fobj, tmp, &fpath->fobj_list, same_fpath) { ++ struct file *file; ++ ++ /* in case of error on suspension, file object is alive */ ++ if (unlikely(fobj->file)) ++ goto restore_fdesc; ++ ++ /* we must put the file after all fds are restored */ ++ file = filp_open(filename, fobj->flags, fobj->mode); ++ if (unlikely(IS_ERR(file))) { ++ pr_err("PM:FS: opening [%s] failed (%d)\n", ++ filename, (int)PTR_ERR(file)); ++ ++ file = get_noentry_file(filename); ++ if (IS_ERR(file)) { ++ pr_err("PM:FS: getting noentry file failed " ++ "(%ld) not recoverable\n", ++ PTR_ERR(file)); ++ /* ++ * make it null so we can recognize it during ++ * fd restoration. ++ */ ++ file = NULL; ++ } else { ++ pr_err("PM:FS: " ++ "got noentry file instead of [%s]\n", ++ filename); ++ } ++ } else { ++ /* ++ * sanity check - if oops, something's wroing, fix ! ++ */ ++ pr_err_bug_if(fobj->flags != file->f_flags, ++ "PM:FS: mismatch file flags, should be " ++ "%x (but %x)\n", ++ fobj->flags, file->f_flags); ++ pr_err_bug_if(fobj->mode != file->f_mode, ++ "PM:FS: mismatch file mode, should be " ++ "%x (but %x)\n", ++ fobj->mode, file->f_mode); ++ ++ /* size truncated ? */ ++ if (unlikely(fobj->pos > ++ i_size_read(file->f_dentry->d_inode))) { ++ pr_err("PM:FS: file size (%lld) smaller than " ++ "offset (%lld)\n", ++ i_size_read(file->f_dentry->d_inode), ++ fobj->pos); ++ /* set pos with inode's size */ ++ fobj->pos = ++ i_size_read(file->f_dentry->d_inode); ++ } ++ ++ /* seek offset */ ++ BUG_ON(filp_lseek(file, fobj->pos, 0) < 0); ++ ++ pr_debug("PM:FS: restore file object [%p:%s]\n", ++ file, filename); ++ pr_debug("PM:FS: open flags : %s\n", ++ get_file_flags_readable(fobj->flags, ++ fobj->mode)); ++ pr_debug("PM:FS: open mode : 0x%08x\n", fobj->mode); ++ pr_debug("PM:FS: offset : %lld\n", fobj->pos); ++ pr_debug("PM:FS: size : %lld\n", ++ i_size_read(file->f_dentry->d_inode)); ++ } ++ fobj->file = file; ++ ++ restore_fdesc: ++ /* task's file descriptors */ ++ restore_file_descriptors(fobj); ++ ++ /* original file or noentry file */ ++ if (likely(fobj->file)) { ++ /* ++ * sanity check - if oops, something's wroing, fix ! ++ * file_count can be 1 (in case someting's wrong), so ++ * check it before dropping reference. ++ */ ++ pr_err_bug_if(file_count(fobj->file) < 2, ++ "PM:FS: file count is %ld\n", ++ file_count(fobj->file)); ++ pr_err_bug_if((file_count(fobj->file) - 1) != ++ atomic_long_read(&fobj->count), ++ "PM:FS: mismatch file count, it should " ++ "be %ld (but %ld)\n", ++ atomic_long_read(&fobj->count), ++ file_count(fobj->file) - 1); ++ } ++ ++ /* ++ * we should put the file because additional count is held in ++ * filp_open(). ++ */ ++ if (likely(fobj->file)) ++ fput(fobj->file); ++ ++ list_del(&fobj->same_fpath); ++ kfree(fobj); ++ } ++} ++ ++static void open_saved_files(void) ++{ ++ struct file_path *fpath, *tmp; ++ ++ list_for_each_entry_safe(fpath, tmp, &file_path_list, node) { ++ pr_info("PM:FS: restore file [%s]", fpath->path); ++ restore_file_objects(fpath); ++ list_del(&fpath->node); ++ kfree(fpath); ++ } ++} ++ ++static struct file_path *get_file_path(struct file *file) ++{ ++ const char *filename = d_path_of_file(file); ++ struct file_path *fpath; ++ ++ /* search first */ ++ list_for_each_entry(fpath, &file_path_list, node) { ++ if (!strcmp(fpath->path, filename)) ++ return fpath; ++ } ++ ++ /* new a file_path */ ++ fpath = kmalloc(sizeof(*fpath) + strlen(filename) + 1, GFP_ATOMIC); ++ if (!fpath) ++ return ERR_PTR(-ENOMEM); ++ ++ INIT_LIST_HEAD(&fpath->node); ++ INIT_LIST_HEAD(&fpath->fobj_list); ++ fpath->path = (char *)fpath + sizeof(*fpath); ++ strcpy(fpath->path, filename); ++ ++ list_add_tail(&fpath->node, &file_path_list); ++ ++ pr_info("PM:FS: save file [%s]\n", filename); ++ return fpath; ++} ++ ++static struct file_object *get_file_object(struct file *file) ++{ ++ struct file_path *fpath; ++ struct file_object *fobj; ++ ++ fpath = get_file_path(file); ++ if (IS_ERR(fpath)) ++ return ERR_PTR(-ENOMEM); ++ ++ /* search first */ ++ list_for_each_entry(fobj, &fpath->fobj_list, same_fpath) { ++ if (fobj->file && (fobj->file == file)) ++ return fobj; ++ } ++ ++ /* new a file_object */ ++ fobj = kzalloc(sizeof(*fobj), GFP_ATOMIC); ++ if (!fobj) ++ return ERR_PTR(-ENOMEM); ++ ++ INIT_LIST_HEAD(&fobj->same_fpath); ++ INIT_LIST_HEAD(&fobj->fdesc_list); ++ fobj->file = file; ++ atomic_long_set(&fobj->count, file_count(file)); ++ fobj->flags = file->f_flags & ~(O_CREAT | O_TRUNC | O_EXCL); ++ fobj->mode = file->f_mode; ++ fobj->pos = file->f_pos; ++ fobj->size = i_size_read(file->f_dentry->d_inode); ++ ++ list_add_tail(&fobj->same_fpath, &fpath->fobj_list); ++ ++ pr_debug("PM:FS: save file object [%p:%s]\n", file, fpath->path); ++ pr_debug("PM:FS: open count: %ld\n", file_count(file)); ++ pr_debug("PM:FS: open flags: %s\n", ++ get_file_flags_readable(file->f_flags, file->f_mode)); ++ pr_debug("PM:FS: open mode : 0x%08x\n", file->f_mode); ++ pr_debug("PM:FS: offset : %lld\n", file->f_pos); ++ pr_debug("PM:FS: size : %lld\n", ++ i_size_read(file->f_dentry->d_inode)); ++ ++ /* ++ * grab additional 1 ref to prevent it from being destroyed in filp_cl- ++ * ose() which may sleep. ++ * file object will be destoryed at the end of close_files_on_rw_backi- ++ * ng_devs(). ++ */ ++ get_file(fobj->file); ++ ++ return fobj; ++} ++ ++static void __put_unused_fd(struct files_struct *files, unsigned int fd) ++{ ++ struct fdtable *fdt = files_fdtable(files); ++ __FD_CLR(fd, fdt->open_fds); ++ if (fd < files->next_fd) ++ files->next_fd = fd; ++} ++ ++static int check_file_busy(struct task_struct *task, struct file *file) ++{ ++ struct list_head *l; ++ int nr_epolls = 0; ++ struct inode *inode = file->f_path.dentry->d_inode; ++ struct file_lock *flock; ++ int nr_flocks = 0; ++ struct vm_area_struct *vma; ++ struct address_space *mapping; ++ struct prio_tree_iter iter; ++ int nr_mappings = 0; ++ int busy = 0; ++ ++ /* FIXME - remove this and save & restore eventpolls */ ++ spin_lock(&file->f_lock); ++ list_for_each(l, &file->f_ep_links) ++ nr_epolls++; ++ spin_unlock(&file->f_lock); ++ ++ /* lock_kernel(); */ ++ for (flock = inode->i_flock; flock != NULL; flock = flock->fl_next) ++ nr_flocks++; ++ /* unlock_kernel(); */ ++ ++ mapping = file->f_mapping; ++ spin_lock(&mapping->i_mmap_lock); ++ vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, 0, ULONG_MAX) { ++ nr_mappings++; ++ } ++ spin_unlock(&mapping->i_mmap_lock); ++ ++ if (unlikely(nr_epolls)) { ++ busy = 1; ++ pr_err("PM:FS: file [%s] (opened by [%s:%d]) has eventpolls " ++ "(%d)\n", d_path_of_file(file), ++ &task->comm[0], task->pid, nr_epolls); ++ } ++ if (unlikely(nr_flocks)) { ++ busy = 1; ++ pr_err("PM:FS: file [%s] (opened by [%s:%d]) has locks (%d)\n", ++ d_path_of_file(file), ++ &task->comm[0], task->pid, nr_flocks); ++ } ++ if (unlikely(nr_mappings)) { ++ busy = 1; ++ pr_err("PM:FS: " ++ "file [%s] (opened by [%s:%d]) has been mmapped (%d)\n", ++ d_path_of_file(file), ++ &task->comm[0], task->pid, nr_mappings); ++ } ++ ++ return busy; ++} ++ ++static int task_save_close_file(struct task_struct *task, int fd) ++{ ++ struct files_struct *files = task->files; ++ struct fdtable *fdt = files_fdtable(files); ++ struct file *file = fcheck_files(files, fd); ++ struct file_object *fobj; ++ struct file_descriptor *fdesc; ++ ++ if (check_file_busy(task, file)) ++ return -EBUSY; ++ ++ fobj = get_file_object(file); ++ if (IS_ERR(fobj)) ++ return PTR_ERR(fobj); ++ ++ fdesc = kmalloc(sizeof(*fdesc), GFP_ATOMIC); ++ if (!fdesc) ++ return -ENOMEM; ++ ++ pr_info("PM:FS: save fd [%s(%d)][fd:%d]\n", ++ &task->comm[0], task->pid, fd); ++ ++ /* backup fd */ ++ INIT_LIST_HEAD(&fdesc->same_fobj); ++ fdesc->fd = fd; ++ fdesc->task = task; ++ ++ /* ++ * decrease count (close), ++ * it should be 2 at least, 1 held in get_file_object(). ++ */ ++ BUG_ON(file_count(file) == 1); ++ fput(file); ++ ++ /* free fd slot */ ++ rcu_assign_pointer(fdt->fd[fd], NULL); ++ FD_CLR(fd, fdt->close_on_exec); ++ __put_unused_fd(files, fd); ++ ++ /* link to fobj */ ++ list_add_tail(&fdesc->same_fobj, &fobj->fdesc_list); ++ ++ return 0; ++} ++ ++static bool is_on_rw_backing_dev(struct file *file) ++{ ++ struct vfsmount *mnt = file->f_vfsmnt; ++ return is_rw_bdev(mnt); ++} ++ ++static int task_close_file_on_rw_backing_dev(struct task_struct *task, int fd) ++{ ++ struct files_struct *files = task->files; ++ struct file *file = fcheck_files(files, fd); ++ int error = 0; ++ ++ if (!file) { ++ pr_err("PM:FS: no file structure\n"); ++ error = -EBADF; ++ goto out; ++ } ++ ++ if (!is_on_rw_backing_dev(file)) ++ goto out; ++ ++ if (!frozen(task)) { ++ pr_err("PM:FS: task [%s] that opened file [%s] not frozen\n", ++ &task->comm[0], d_path_of_file(file)); ++ error = -EBUSY; ++ goto out; ++ } ++ ++ error = task_save_close_file(task, fd); ++ if (error) { ++ pr_err("PM:FS: failed to close file %s on process %s\n", ++ &task->comm[0], d_path_of_file(file)); ++ goto out; ++ } ++ ++out: ++ return error; ++} ++ ++static int task_close_files_on_rw_backing_devs(struct task_struct *task) ++{ ++ struct files_struct *files = task->files; ++ struct fdtable *fdt; ++ int i = 0; ++ int error = 0; ++ ++ if (!frozen(task) || !files) ++ return 0; ++ ++ spin_lock(&files->file_lock); ++ fdt = files_fdtable(files); ++ for (i = 0; i < fdt->max_fds; i++) { ++ struct file *file = fcheck_files(files, i); ++ if (!file) ++ continue; ++ error = task_close_file_on_rw_backing_dev(task, i); ++ if (error) ++ goto out; ++ } ++out: ++ spin_unlock(&files->file_lock); ++ return error; ++} ++ ++static int close_files_on_rw_backing_devs(void) ++{ ++ struct task_struct *task; ++ struct file_path *fpath; ++ int error = 0; ++ ++ read_lock(&tasklist_lock); ++ for_each_process(task) { ++ task_lock(task); ++ error = task_close_files_on_rw_backing_devs(task); ++ task_unlock(task); ++ if (error) { ++ goto unlock; ++ } ++ } ++unlock: ++ read_unlock(&tasklist_lock); ++ ++ /* ++ * On error, do not free files on file_path_list here. ++ * They will be restored by simply increasing files' counts not to ++ * bother closing and reopening files. ++ */ ++ if (unlikely(error)) ++ goto out; ++ ++ /* free files */ ++ list_for_each_entry(fpath, &file_path_list, node) { ++ struct file_object *fobj; ++ list_for_each_entry(fobj, &fpath->fobj_list, same_fpath) { ++ /* sanity check - if oops, something's wroing, fix ! */ ++ pr_err_bug_if(file_count(fobj->file) != 1, ++ "PM:FS: " ++ "file count is %ld, should be 1\n", ++ file_count(fobj->file)); ++ /* free and nullify, reinstantiated on resumption. */ ++ BUG_ON(filp_close(fobj->file, task->files) < 0); ++ fobj->file = NULL; ++ } ++ } ++ ++out: ++ return error; ++} ++ ++#ifdef CONFIG_INOTIFY_USER ++ ++struct saved_inotify_user { ++ struct list_head node; ++ struct fsnotify_group *group; ++ int wd; ++ u32 mask; ++ char *path; ++}; ++ ++static LIST_HEAD(saved_inotify_users); ++ ++extern void inotify_free_mark(struct fsnotify_mark_entry *entry); ++extern struct kmem_cache *inotify_inode_mark_cachep __read_mostly; ++extern int inotify_max_user_watches __read_mostly; ++extern void inotify_remove_from_idr(struct fsnotify_group *group, ++ struct inotify_inode_mark_entry *ientry); ++ ++/* copied from inotify_new_watch() */ ++static int restore_saved_inotify_user(struct saved_inotify_user *saved, ++ struct path *path) ++{ ++ struct fsnotify_group *group = saved->group; ++ const char *filepath = saved->path; ++ int wd = saved->wd; ++ u32 mask = saved->mask; ++ struct inotify_inode_mark_entry *tmp_ientry; ++ struct inode *inode; ++ int ret; ++ ++ /* don't allow invalid bits: we don't want flags set */ ++ if (unlikely(!mask)) ++ return -EINVAL; ++ ++ inode = path->dentry->d_inode; ++ ++ tmp_ientry = kmem_cache_alloc(inotify_inode_mark_cachep, GFP_KERNEL); ++ if (unlikely(!tmp_ientry)) ++ return -ENOMEM; ++ ++ tmp_ientry->path = kstrdup(filepath, GFP_KERNEL); ++ if (unlikely(!tmp_ientry->path)) { ++ kmem_cache_free(inotify_inode_mark_cachep, tmp_ientry); ++ return -ENOMEM; ++ } ++ ++ fsnotify_init_mark(&tmp_ientry->fsn_entry, inotify_free_mark); ++ tmp_ientry->fsn_entry.mask = mask; ++ tmp_ientry->wd = -1; ++ ++ ret = -ENOSPC; ++ if (atomic_read(&group->inotify_data.user->inotify_watches) >= ++ inotify_max_user_watches) ++ goto out_err; ++retry: ++ ret = -ENOMEM; ++ if (unlikely(!idr_pre_get(&group->inotify_data.idr, GFP_KERNEL))) ++ goto out_err; ++ ++ /* we are putting the mark on the idr, take a reference */ ++ fsnotify_get_mark(&tmp_ientry->fsn_entry); ++ ++ spin_lock(&group->inotify_data.idr_lock); ++ ret = idr_get_new_above(&group->inotify_data.idr, &tmp_ientry->fsn_entry, ++ wd, &tmp_ientry->wd); ++ spin_unlock(&group->inotify_data.idr_lock); ++ if (ret) { ++ /* we didn't get on the idr, drop the idr reference */ ++ fsnotify_put_mark(&tmp_ientry->fsn_entry); ++ ++ /* idr was out of memory allocate and try again */ ++ if (ret == -EAGAIN) ++ goto retry; ++ goto out_err; ++ } ++ ++ BUG_ON(wd != tmp_ientry->wd); ++ ++ /* we are on the idr, now get on the inode */ ++ ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode); ++ if (ret) { ++ /* we failed to get on the inode, get off the idr */ ++ inotify_remove_from_idr(group, tmp_ientry); ++ goto out_err; ++ } ++ ++ /* update the idr hint, who cares about races, it's just a hint */ ++ group->inotify_data.last_wd = tmp_ientry->wd; ++ ++ /* increment the number of watches the user has */ ++ atomic_inc(&group->inotify_data.user->inotify_watches); ++ ++ /* return the watch descriptor for this tmp_ientry entry */ ++ ret = tmp_ientry->wd; ++ ++ /* if this mark added a new event update the group mask */ ++ if (mask & ~group->mask) ++ fsnotify_recalc_group_mask(group); ++ ++ pr_info("PM:FS: restore inotify user [%s]\n", filepath); ++ pr_debug("PM:FS: user : %p\n", group->inotify_data.user); ++ pr_debug("PM:FS: watches: %d\n", ++ atomic_read(&group->inotify_data.user->inotify_watches)); ++ pr_debug("PM:FS: group : %p\n", group); ++ pr_debug("PM:FS: mask : 0x%08x\n", mask); ++ pr_debug("PM:FS: wd : %d\n", wd); ++ ++out_err: ++ /* match the ref from fsnotify_init_markentry() */ ++ fsnotify_put_mark(&tmp_ientry->fsn_entry); ++ ++ return ret; ++} ++ ++static void restore_saved_inotify_users(void) ++{ ++ struct saved_inotify_user *saved, *tmp; ++ struct path path; ++ ++ list_for_each_entry_safe(saved, tmp, &saved_inotify_users, node) { ++ int error; ++ ++ error = kern_path(saved->path, 0, &path); ++ if (error /* -ENOENT */) { ++ struct file *file; ++ ++ pr_err("PM:FS: not found path [%s] (%d)\n", ++ saved->path, error); ++ ++ file = get_noentry_file(saved->path); ++ if (IS_ERR(file)) { ++ error = PTR_ERR(file); ++ pr_err("PM:FS: failed to get noentry file, " ++ "not recoverable (%d)\n", error); ++ goto next; ++ } ++ pr_err("PM:FS: got noentry file and put inotify user " ++ "on it\n"); ++ path = file->f_path; ++ path_get(&path); ++ /* ++ * inotify registeration needs only f_path, not file ++ * itself. ++ */ ++ filp_close(file, NULL); ++ } ++ ++ error = restore_saved_inotify_user(saved, &path); ++#if 0 ++ if (!error) { ++ /* ++ * In real world, it's right to regard restored files ++ * as modified in most cases ? ++ */ ++ fsnotify_enable(); ++ fsnotify_modify(path.dentry); ++ fsnotify_disable(); ++ } ++#endif ++ path_put(&path); ++ next: ++ list_del(&saved->node); ++ kfree(saved); ++ } ++} ++ ++static int save_inotify_user_group_on_mnt(struct fsnotify_group *group, ++ struct vfsmount *mnt) ++{ ++ struct fsnotify_mark_entry *entry, *tmp; ++ int error = 0; ++ ++ spin_lock(&group->mark_lock); ++ list_for_each_entry_safe(entry, tmp, &group->mark_entries, g_list) { ++ struct inode *inode = entry->inode; ++ struct inotify_inode_mark_entry *ientry = ++ container_of(entry, struct inotify_inode_mark_entry, ++ fsn_entry); ++ struct user_struct *user = group->inotify_data.user; ++ struct saved_inotify_user *save; ++ char *path_str = ientry->path; ++ ++ if (inode->i_sb != mnt->mnt_sb) ++ continue; ++ ++ save = kzalloc(sizeof(*save) + strlen(path_str) + 1, ++ GFP_ATOMIC); ++ if (!save) { ++ error = -ENOMEM; ++ goto unlock; ++ } ++ INIT_LIST_HEAD(&save->node); ++ save->path = (char *)save + sizeof(*save); ++ ++ strcpy(save->path, path_str); ++ save->group = group; ++ save->wd = ientry->wd; ++ save->mask = entry->mask; ++ list_add(&save->node, &saved_inotify_users); ++ pr_info("PM:FS: save inotify user [%s]\n", save->path); ++ pr_debug("PM:FS: user : %p\n", user); ++ pr_debug("PM:FS: watches: %d\n", ++ atomic_read(&user->inotify_watches)); ++ pr_debug("PM:FS: group : %p\n", group); ++ pr_debug("PM:FS: mask : 0x%08x\n", entry->mask); ++ pr_debug("PM:FS: wd : %d\n", ientry->wd); ++ ++ fsnotify_get_mark(entry); ++ spin_unlock(&group->mark_lock); ++ ++ fsnotify_destroy_mark_by_entry(entry); ++ fsnotify_put_mark(entry); ++ ++ spin_lock(&group->mark_lock); ++ } ++ ++unlock: ++ spin_unlock(&group->mark_lock); ++ return error; ++} ++ ++static int save_inotify_users_on_mnt(struct vfsmount *mnt, void *unused) ++{ ++ struct fsnotify_group *group; ++ int idx; ++ int ret = 0; ++ ++ idx = srcu_read_lock(&fsnotify_grp_srcu); ++ list_for_each_entry_rcu(group, &fsnotify_groups, group_list) { ++ if (group->ops == &inotify_fsnotify_ops) { ++ ret = save_inotify_user_group_on_mnt(group, mnt); ++ if (ret) ++ goto unlock; ++ } ++ } ++unlock: ++ srcu_read_unlock(&fsnotify_grp_srcu, idx); ++ return ret; ++} ++ ++static int save_inotify_users_on_rw_backing_devs(void) ++{ ++ return iterate_mounts_safe_reverse(save_inotify_users_on_mnt, ++ is_rw_bdev, NULL); ++} ++ ++#else ++inline static int save_inotify_users_on_rw_partitions(void) { return 0; } ++inline static int restore_saved_inotify_users(void) { return 0; } ++ ++#endif /* CONFIG_INOTIFY_USER */ ++ ++int fastboot_hibernate_fs_suspend(void) ++{ ++ int error; ++ ++ pr_debug("PM:FS: Got PM_POST_FREEZE_PROCESS event\n"); ++ ++ error = save_inotify_users_on_rw_backing_devs(); ++ if (error) ++ goto restore_inotify_users; ++ error = close_files_on_rw_backing_devs(); ++ if (error) ++ goto open; ++ error = save_task_fs_on_rw_backing_devs(); ++ if (error) ++ goto restore_task_fs; ++ error = unmount_rw_backing_devs(); ++ if (error) ++ goto mount; ++ ++ pr_debug("PM:FS: Done with PM_POST_FREEZE_PROCESS event\n"); ++ return 0; ++ ++mount: ++ mount_saved_mountpoints(); ++restore_task_fs: ++ restore_saved_task_fs(); ++open: ++ open_saved_files(); ++restore_inotify_users: ++ restore_saved_inotify_users(); ++ ++ pr_err("PM:FS: failure in suspending filesystem (%d)\n", error); ++ return error; ++} ++ ++int fastboot_hibernate_fs_resume(void) ++{ ++ pr_debug("PM:FS: Got PM_THAW_PROCESS_PREPARE event\n"); ++ ++ /* no error check for task'fs */ ++ mount_saved_mountpoints(); ++ restore_saved_task_fs(); ++ open_saved_files(); ++ restore_saved_inotify_users(); ++ ++ pr_debug("PM:FS: Done with PM_THAW_PROCESS_PREPARE event\n"); ++ return 0; ++} +diff --git a/arch/arm/mach-hisi/fastboot/hibernate_misc.c b/arch/arm/mach-hisi/fastboot/hibernate_misc.c +new file mode 100644 +index 0000000..bd8529a +--- /dev/null ++++ b/arch/arm/mach-hisi/fastboot/hibernate_misc.c +@@ -0,0 +1,188 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static DEFINE_MUTEX(file_mutex); ++ ++struct sb_files_mount ++{ ++ struct seq_file m; ++ struct path path; ++ struct vfsmount *mnt; ++}; ++ ++extern int kern_path(const char *, unsigned int, struct path *); ++extern char *get_task_comm(char *, struct task_struct *); ++ ++static char mnt_path[64] = {0,}; ++ ++static inline char *__dpath_of_filp(struct file *filp, char *buf, int len) ++{ ++ struct path mnt_path; ++ mnt_path.dentry = filp->f_dentry; ++ mnt_path.mnt = filp->f_vfsmnt; ++ return d_path(&mnt_path, buf, len); ++} ++ ++static void *sb_files_seq_start(struct seq_file *m, loff_t *pos) ++{ ++ struct sb_files_mount *priv = m->private; ++ mutex_lock(&file_mutex); ++ ++ /* fix me */ ++/*#ifdef CONFIG_SMP ++ return seq_list_start(priv->mnt->mnt_sb->s_files, *pos); ++#else*/ ++ return seq_list_start(&priv->mnt->mnt_sb->s_files, *pos); ++/*#endif*/ ++} ++ ++static void *m_next(struct seq_file *m, void *v, loff_t *pos) ++{ ++ struct sb_files_mount *priv = m->private; ++ ++ /* fix me */ ++/*#ifdef CONFIG_SMP ++ return seq_list_next(v, priv->mnt->mnt_sb->s_files, pos); ++#else*/ ++ return seq_list_next(v, &priv->mnt->mnt_sb->s_files, pos); ++/*#endif*/ ++} ++ ++static void m_stop(struct seq_file *m, void *v) ++{ ++ mutex_unlock(&file_mutex); ++} ++ ++static int sb_files_seq_show(struct seq_file *m, void *v) ++{ ++ struct file *filp = list_entry(v, struct file, f_u.fu_llist); ++ char buf[128], *path; ++ unsigned int acc; ++ struct vm_area_struct *vma; ++ struct address_space *mapping; ++ int mmap_count = 0; ++ ++ path = __dpath_of_filp(filp, buf, sizeof(buf)); ++ acc = filp->f_flags & O_ACCMODE; ++ mapping = filp->f_mapping; ++ ++ vma_interval_tree_foreach(vma, &mapping->i_mmap, 0, ULONG_MAX) { ++ mmap_count++; ++ } ++ ++ seq_printf(m, "[%s]\n", path); ++ seq_printf(m, "\topen count: %ld\n", file_count(filp)); ++ seq_printf(m, "\topen flags: %s%s%s%s\n", ++ (filp->f_mode | filp->f_flags) & FMODE_EXEC ? "EXEC ":" ", ++ filp->f_flags & O_DIRECTORY ? "DIR ":" ", ++ acc == O_RDWR ? "RDWR ": ++ (acc == O_RDONLY ? "RD ": ++ (acc == O_WRONLY ? " WR ":" ")), ++ mmap_count ? "MMAP":""); ++ ++ return 0; ++} ++ ++static const struct seq_operations sb_files_seq_ops = { ++ .start = sb_files_seq_start, ++ .next = m_next, ++ .stop = m_stop, ++ .show = sb_files_seq_show, ++}; ++ ++static int sb_files_open(struct inode *inode, struct file *file) ++{ ++ struct sb_files_mount *priv; ++ int ret = -1; ++ ++ priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ if (mnt_path[0] != 0) ++ ret = kern_path(mnt_path, 0, &priv->path); ++ ++ if (ret) ++ ret = kern_path("/", 0, &priv->path); ++ ++ priv->mnt = collect_mounts(&priv->path); ++ ++ file->private_data = &priv->m; ++ ret = seq_open(file, &sb_files_seq_ops); ++ if (ret) { ++ path_put(&priv->path); ++ drop_collected_mounts(priv->mnt); ++ kfree(priv); ++ return ret; ++ } ++ ++ priv->m.private = priv; ++ return 0; ++} ++ ++static int sb_files_release(struct inode *inode, struct file *file) ++{ ++ struct sb_files_mount *priv = file->private_data; ++ if (priv) { ++ path_put(&priv->path); ++ drop_collected_mounts(priv->mnt); ++ kfree(priv); ++ } ++ return 0; ++} ++ ++static ssize_t sb_files_write(struct file *file, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ size_t c = sizeof(mnt_path)-1 < count ? sizeof(mnt_path)-1 : count; ++ int ret; ++ if (unlikely((ret = copy_from_user(mnt_path, buf, c)) < 0)) ++ return -EFAULT; ++ mnt_path[c] = 0; ++ if (c > 1) { ++ if (mnt_path[c-1] == '\n') ++ mnt_path[c-1] = '\0'; ++ } ++ *ppos += c; ++ return c; ++} ++ ++static const struct file_operations sb_files_proc_fops = { ++ .open = sb_files_open, ++ .release = sb_files_release, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ ++ /* FIXME */ ++ .write = sb_files_write, ++}; ++ ++int __init fastboot_hibernation_misc_init(void) ++{ ++ proc_create("dump_sb_files", 0444, NULL, &sb_files_proc_fops); ++ return 0; ++} ++ ++#ifdef MODULE ++void __exit fastboot_hibernation_misc_exit(void) ++{ ++ remove_proc_entry("dump_sb_files", NULL); ++} ++#endif +diff --git a/arch/arm/mach-hisi/fastboot/hibernate_pmmon.c b/arch/arm/mach-hisi/fastboot/hibernate_pmmon.c +new file mode 100644 +index 0000000..5add8d7 +--- /dev/null ++++ b/arch/arm/mach-hisi/fastboot/hibernate_pmmon.c +@@ -0,0 +1,107 @@ ++#include ++#include ++#include ++ ++#include "fastboot_pm.h" ++ ++#if defined(CONFIG_PM) && defined(CONFIG_SUSPEND) ++ ++static char *pm_umh_str; ++static int fastboot_pm_monitor(struct notifier_block *this, ++ unsigned long event, void *ptr) ++{ ++ switch (event) { ++ case PM_HIBERNATION_PREPARE: /* starting pm_suspend_to_hibernation */ ++ pm_umh_str = "PM_HIBERNATION_PREPARE"; ++ break; ++ case PM_POST_HIBERNATION: /* end of pm_resume_from_hibernation */ ++ pm_umh_str = "PM_POST_HIBERNATION"; ++ break; ++ case PM_SUSPEND_PREPARE: /* starting pm_suspend */ ++ pm_umh_str = "PM_SUSPEND_PREPARE"; ++ break; ++ case PM_POST_SUSPEND: /* end of pm_resume */ ++ pm_umh_str = "PM_POST_SUSPEND"; ++ break; ++ case PM_RESTORE_PREPARE: /* pm_suspend failure ? */ ++ pm_umh_str = "PM_RESTORE_PREPARE"; ++ break; ++ case PM_POST_RESTORE: /* pm_suspend failure ? */ ++ pm_umh_str = "PM_POST_RESTORE"; ++ break; ++ case PM_POST_FREEZE_PROCESS: ++ pm_umh_str = "PM_POST_FREEZE_PROCESS"; ++ break; ++ case PM_THAW_PROCESS_PREPARE: ++ pm_umh_str = "PM_THAW_PROCESS_PREPARE"; ++ /*mark by liucan*/ ++ //fastboot_hibernate_fs_resume(); ++ break; ++ case PM_POST_DEVICE_SUSPEND: ++ pm_umh_str = "PM_POST_DEVICE_SUSPEND"; ++ break; ++ case PM_RESUME_DEVICE_PREPARE: ++ pm_umh_str = "PM_RESUME_DEVICE_PREPARE"; ++ break; ++ default: ++ printk("%s: unknown event, ignoring...\n", __func__); ++ return 0; ++ } ++ ++ /* FIXME: ++ * The callee must be on a initrd in order to handle DEVICE events. ++ * Or it will be blocked forever because a storage was suspended. ++ */ ++ if (event != PM_POST_DEVICE_SUSPEND ++ && event != PM_RESUME_DEVICE_PREPARE) { ++ fastboot_pm_call_umh(pm_umh_str, event); ++ } ++ ++ switch (event) { ++ case PM_POST_FREEZE_PROCESS: ++ // mark by liucan. ++ //fastboot_hibernate_fs_suspend(); ++ //break; ++ case PM_HIBERNATION_PREPARE: ++ case PM_POST_HIBERNATION: ++ case PM_SUSPEND_PREPARE: ++ case PM_POST_SUSPEND: ++ case PM_RESTORE_PREPARE: ++ case PM_POST_RESTORE: ++ case PM_THAW_PROCESS_PREPARE: ++ case PM_POST_DEVICE_SUSPEND: ++ case PM_RESUME_DEVICE_PREPARE: ++ default: ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static struct notifier_block fastboot_pm_notifier = { ++ .notifier_call = fastboot_pm_monitor, ++}; ++ ++static int __init fastboot_pm_monitor_init(void) ++{ ++ register_pm_notifier(&fastboot_pm_notifier); ++ return 0; ++} ++#if 0 ++#ifdef MODULE ++static void __exit fastboot_pm_monitor_exit(void) ++{ ++ printk("hahaha\n"); ++ unregister_pm_notifier(&fastboot_pm_notifier); ++} ++ ++module_init(fastboot_pm_monitor_init); ++module_exit(fastboot_pm_monitor_exit); ++#else ++late_initcall(fastboot_pm_monitor_init); ++#endif ++#endif ++late_initcall(fastboot_pm_monitor_init); ++#endif /* CONFIG_PM && CONFIG_SUSPEND */ ++ ++MODULE_LICENSE("GPL"); +diff --git a/arch/arm/mach-hisi/fastboot/hibernate_umh.c b/arch/arm/mach-hisi/fastboot/hibernate_umh.c +new file mode 100644 +index 0000000..9f56da4 +--- /dev/null ++++ b/arch/arm/mach-hisi/fastboot/hibernate_umh.c +@@ -0,0 +1,79 @@ ++#include ++#include ++#include ++ ++#include "fastboot_pm.h" ++ ++/* ++ * ToDo ++ * add uevent ++ */ ++ ++#if defined(CONFIG_PM) && defined(CONFIG_SUSPEND) ++ ++#define PM_EVENT_HELPER_LEN (32) ++ ++static char pm_umh_helper[PM_EVENT_HELPER_LEN] = { 0, }; ++static struct ctl_table_header *ctl; ++ ++static struct ctl_table pm_umh_ctl[] = { ++ { ++ .procname = "pm_notifier", ++ .data = &pm_umh_helper, ++ .maxlen = PM_EVENT_HELPER_LEN, ++ .mode = 0644, ++ .proc_handler = proc_dostring, ++ }, ++ {} ++}; ++ ++static struct ctl_path pm_umh_root[] = { ++ { ++ .procname = "kernel", ++ }, ++ {} ++}; ++ ++int fastboot_pm_call_umh(char *event_str, unsigned long event) ++{ ++ char *argv[3] = {pm_umh_helper, event_str, NULL}; ++ char *envp[3] = {"HOME=/", NULL, NULL }; ++ int ret; ++ ++ if (!pm_umh_helper[0]) ++ return 0; ++ ++ /* NOTE: may cannot access to Android's property services. */ ++ envp[1] = "PATH=/usr/bin:/usr/sbin:/bin:/sbin"; ++ ret = call_usermodehelper_fns_force(argv[0], argv, envp, ++ UMH_WAIT_PROC, NULL, NULL, NULL); ++ if (ret < 0) ++ pr_err("%s: helper failed(%d)\n", __func__, ret); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(fastboot_pm_call_umh); ++ ++static int __init fastboot_pm_umh_init(void) ++{ ++ ctl = register_sysctl_paths(pm_umh_root, pm_umh_ctl); ++ fastboot_hibernation_misc_init(); ++ return 0; ++} ++ ++#if 0 ++#ifdef MODULE ++static void __exit fastboot_pm_umh_exit(void) ++{ ++ fastboot_hibernation_misc_exit(); ++ unregister_sysctl_table(ctl); ++} ++ ++module_init(fastboot_pm_umh_init); ++module_exit(fastboot_pm_umh_exit); ++#else ++late_initcall(fastboot_pm_umh_init); ++#endif ++#endif ++late_initcall(fastboot_pm_umh_init); ++#endif /* CONFIG_PM && CONFIG_SUSPEND */ +diff --git a/arch/arm/mach-hisi/headsmp.S b/arch/arm/mach-hisi/headsmp.S +index 278889c..0d0abd4 100644 +--- a/arch/arm/mach-hisi/headsmp.S ++++ b/arch/arm/mach-hisi/headsmp.S +@@ -8,9 +8,292 @@ + */ + #include + #include ++#include + + __CPUINIT + + ENTRY(hix5hd2_secondary_startup) + bl v7_invalidate_l1 + b secondary_startup ++ENDPROC(hix5hd2_secondary_startup) ++ ++ ++ENTRY(hi3519_secondary_startup) ++ /* Set A17 acinactive to 1, bit 8 is acinactive */ ++ bl hi_pmc_clear_a17_ac ++ ++ bl cci_enable_port_for_self ++ ++ /* config l2ctl */ ++ mrc p15, 1, r0, c9, c0, 2 ++ mov r2, #0x100000 ++ orr r1, r1, r2 ++ mcr p15, 1, r0, c9, c0, 2 ++ ++ /* ++ * set SMP bit ACTLR register for A17 slave core ++ */ ++ mrc p15, 0, r0, c1, c0, 1 ++ orr r0, #(1 << 6) ++ mcr p15, 0, r0, c1, c0, 1 ++ ++ bl v7_invalidate_l1 ++ ++ b secondary_startup ++ENDPROC(hi3519_secondary_startup) ++ ++ENTRY(hi3519_cpu_resume) ++ safe_svcmode_maskall r1 ++ ++ /* Set A17 acinactive to 0, bit 8 is acinactive */ ++ bl hi_pmc_clear_a17_ac ++ ++ bl cci_enable_port_for_self ++ ++ /* config l2ctl, just follow the datasheet why?*/ ++ mrc p15, 1, r0, c9, c0, 2 ++ mov r2, #0x100000 ++ orr r1, r1, r2 ++ mcr p15, 1, r0, c9, c0, 2 ++ ++ /* ++ * set SMP bit ACTLR register for A17 slave core ++ */ ++ mrc p15, 0, r0, c1, c0, 1 ++ orr r0, #(1 << 6) ++ mcr p15, 0, r0, c1, c0, 1 ++ ++ b cpu_resume ++ ++ENDPROC(hi3519_cpu_resume) ++ ++ENTRY(hi3516av200_secondary_startup) ++ /* Set A17 acinactive to 1, bit 8 is acinactive */ ++ bl hi_pmc_clear_a17_ac ++ ++ bl cci_enable_port_for_self ++ ++ /* config l2ctl */ ++ mrc p15, 1, r0, c9, c0, 2 ++ mov r2, #0x100000 ++ orr r1, r1, r2 ++ mcr p15, 1, r0, c9, c0, 2 ++ ++ /* ++ * set SMP bit ACTLR register for A17 slave core ++ */ ++ mrc p15, 0, r0, c1, c0, 1 ++ orr r0, #(1 << 6) ++ mcr p15, 0, r0, c1, c0, 1 ++ ++ bl v7_invalidate_l1 ++ ++ b secondary_startup ++ENDPROC(hi3516av200_secondary_startup) ++ ++ENTRY(hi3516av200_cpu_resume) ++ safe_svcmode_maskall r1 ++ ++ /* Set A17 acinactive to 0, bit 8 is acinactive */ ++ bl hi_pmc_clear_a17_ac ++ ++ bl cci_enable_port_for_self ++ ++ /* config l2ctl, just follow the datasheet why?*/ ++ mrc p15, 1, r0, c9, c0, 2 ++ mov r2, #0x100000 ++ orr r1, r1, r2 ++ mcr p15, 1, r0, c9, c0, 2 ++ ++ /* ++ * set SMP bit ACTLR register for A17 slave core ++ */ ++ mrc p15, 0, r0, c1, c0, 1 ++ orr r0, #(1 << 6) ++ mcr p15, 0, r0, c1, c0, 1 ++ ++ b cpu_resume ++ ++ENDPROC(hi3516av200_cpu_resume) ++ ++ENTRY(hi3559_secondary_startup) ++ /* Set A17 acinactive to 1, bit 8 is acinactive */ ++ bl hi_pmc_clear_a17_ac ++ ++ bl cci_enable_port_for_self ++ ++ /* config l2ctl */ ++ mrc p15, 1, r0, c9, c0, 2 ++ mov r2, #0x100000 ++ orr r1, r1, r2 ++ mcr p15, 1, r0, c9, c0, 2 ++ ++ /* ++ * set SMP bit ACTLR register for A17 slave core ++ */ ++ mrc p15, 0, r0, c1, c0, 1 ++ orr r0, #(1 << 6) ++ mcr p15, 0, r0, c1, c0, 1 ++ ++ bl v7_invalidate_l1 ++ ++ b secondary_startup ++ENDPROC(hi3559_secondary_startup) ++ ++ENTRY(hi3559_cpu_resume) ++ safe_svcmode_maskall r1 ++ ++ /* Set A17 acinactive to 0, bit 8 is acinactive */ ++ bl hi_pmc_clear_a17_ac ++ ++ bl cci_enable_port_for_self ++ ++ /* config l2ctl, just follow the datasheet why?*/ ++ mrc p15, 1, r0, c9, c0, 2 ++ mov r2, #0x100000 ++ orr r1, r1, r2 ++ mcr p15, 1, r0, c9, c0, 2 ++ ++ /* ++ * set SMP bit ACTLR register for A17 slave core ++ */ ++ mrc p15, 0, r0, c1, c0, 1 ++ orr r0, #(1 << 6) ++ mcr p15, 0, r0, c1, c0, 1 ++ ++ b cpu_resume ++ ++ENDPROC(hi3559_cpu_resume) ++ ++#ifdef CONFIG_ARCH_HI3531D ++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ++@ ++@ corrupt: r0, r1, r2, r3 ++@ ++.align 2 ++ ++flash_cache_all: ++ ++ /* disable MMU stuff and caches */ ++ mrc p15, 0, r0, c1, c0, 0 ++ orr r0, r0, #0x00002000 /* clear bits 13 (--V-) */ ++ bic r0, r0, #0x00000007 /* clear bits 2:0 (-CAM) */ ++ orr r0, r0, #0x00000002 /* set bit 1 (--A-) Align */ ++ orr r0, r0, #0x00000800 /* set bit 12 (Z---) BTB */ ++ mcr p15, 0, r0, c1, c0, 0 ++ ++ /* ++ * Invalidate L1 I/D ++ */ ++ mov r0, #0 /* set up for MCR */ ++ mcr p15, 0, r0, c8, c7, 0 /* invalidate TLBs */ ++ mcr p15, 0, r0, c7, c5, 0 /* invalidate icache */ ++ ++ /* Invalidate L1 D-cache */ ++ mcr p15, 2, r0, c0, c0, 0 /* select L1 data cache */ ++ /* Read Current Cache Size Identification Register */ ++ mrc p15, 1, r3, c0, c0, 0 ++ ldr r1, =0x1ff ++ and r3, r1, r3, LSR #13 /* r3 = (number of sets -1) */ ++ mov r0, #0 ++way_loop: ++ mov r1, #0 /* r1->set counter */ ++line_loop: ++ mov r2, r0, LSL #30 ++ orr r2, r1, LSL #5 /* r2->set/way cache-op format */ ++ mcr p15, 0, r2, c7, c6, 2 /* Invalidate line described by r2 */ ++ add r1, r1, #1 /* Increment set counter */ ++ cmp r1, r3 /* Check if the last set is reached */ ++ ble line_loop /* if not, continue the set_loop */ ++ add r0, r0, #1 /* else, Increment way counter */ ++ cmp r0, #4 /* Check if the last way is reached */ ++ blt way_loop /* if not, continue the way_loop */ ++ ++ mov pc, lr ++#endif ++ ++ENTRY(hi3536c_secondary_startup) ++ /* set the cpu to SVC32 mode */ ++ mrs r0, cpsr ++ bic r0, r0, #0x1f /* r0 = ((~0x1F) & r0) */ ++ orr r0, r0, #0xd3 /* r0 = (0xd3 | r0) */ ++ msr cpsr, r0 ++ ++ mrc p15, 0, r0, c0, c0, 5 ++ and r0, r0, #15 ++ adr r4, 1f ++ ldmia r4, {r5, r6} ++ sub r4, r4, r5 ++ add r6, r6, r4 ++pen_36c: ldr r7, [r6] ++ cmp r7, r0 ++ bne pen_36c ++ ++ /* ++ * we've been released from the holding pen: secondary_stack ++ * should now contain the SVC stack for this core ++ */ ++ b secondary_startup ++ ++1: .long . ++ .long pen_release ++ENDPROC(hi3536c_secondary_startup) ++ ++ENTRY(hi3531d_secondary_startup) ++ /* set the cpu to SVC32 mode */ ++ mrs r0, cpsr ++ bic r0, r0, #0x1f /* r0 = ((~0x1F) & r0) */ ++ orr r0, r0, #0xd3 /* r0 = (0xd3 | r0) */ ++ msr cpsr, r0 ++ ++#ifdef CONFIG_ARCH_HI3531D ++ bl flash_cache_all ++#endif ++ ++ mrc p15, 0, r0, c0, c0, 5 ++ and r0, r0, #15 ++ adr r4, 1f ++ ldmia r4, {r5, r6} ++ sub r4, r4, r5 ++ add r6, r6, r4 ++pen: ldr r7, [r6] ++ cmp r7, r0 ++ bne pen ++ ++ /* ++ * we've been released from the holding pen: secondary_stack ++ * should now contain the SVC stack for this core ++ */ ++ b secondary_startup ++ ++ 1: .long . ++ .long pen_release ++ENDPROC(hi3531d_secondary_startup) ++ ++ENTRY(hi3521d_secondary_startup) ++ /* set the cpu to SVC32 mode */ ++ mrs r0, cpsr ++ bic r0, r0, #0x1f /* r0 = ((~0x1F) & r0) */ ++ orr r0, r0, #0xd3 /* r0 = (0xd3 | r0) */ ++ msr cpsr, r0 ++ ++ mrc p15, 0, r0, c0, c0, 5 ++ and r0, r0, #15 ++ adr r4, 1f ++ ldmia r4, {r5, r6} ++ sub r4, r4, r5 ++ add r6, r6, r4 ++pen_21d: ldr r7, [r6] ++ cmp r7, r0 ++ bne pen_21d ++ ++ /* ++ * we've been released from the holding pen: secondary_stack ++ * should now contain the SVC stack for this core ++ */ ++ b secondary_startup ++ ++1: .long . ++ .long pen_release ++ENDPROC(hi3521d_secondary_startup) ++ +diff --git a/arch/arm/mach-hisi/hibernate.c b/arch/arm/mach-hisi/hibernate.c +new file mode 100644 +index 0000000..bd90b23 +--- /dev/null ++++ b/arch/arm/mach-hisi/hibernate.c +@@ -0,0 +1,220 @@ ++/* ++ * ARM Cortex-A7 save/restore for suspend to disk (Hibernation) ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++typedef struct fault_regs { ++ unsigned long dfar; ++ unsigned long ifar; ++ unsigned long ifsr; ++ unsigned long dfsr; ++ unsigned long adfsr; ++ unsigned long aifsr; ++} cp15_fault_regs; ++ ++typedef struct vfp_context { ++ unsigned long fpexc; ++ unsigned long fpscr; ++ /*we just used low 32bit of d0-d15*/ ++ unsigned long d0_15[16]; ++} vfp_context; ++ ++typedef struct generic_timer_context { ++ unsigned long cntfrq; ++ unsigned long long cntvoff; ++ unsigned long cnthctl; ++ unsigned long cntkctl; ++ unsigned long long cntp_cval; ++ unsigned long cntp_tval; ++ unsigned long cntp_ctl; ++ unsigned long long cntv_cval; ++ unsigned long cntv_tval; ++ unsigned long cntv_ctl; ++ unsigned long long cnthp_cval; ++ unsigned long cnthp_tval; ++ unsigned long cnthp_ctl; ++} gen_timer_context; ++#if __LINUX_ARM_ARCH__ > 5 ++typedef struct ns_saved_context { ++ unsigned long cp15_misc_regs[2]; /* cp15 miscellaneous registers */ ++ unsigned long cp15_ctrl_regs[20]; /* cp15 control registers */ ++ unsigned long cp15_mmu_regs[16]; /* cp15 mmu registers */ ++ cp15_fault_regs cp15_fault_regs; /* cp15 fault status registers */ ++ gen_timer_context gen_timer_regs; ++ vfp_context vfp_regs; ++} saved_context; ++#else /* for ARM9 */ ++/* image of the saved processor state */ ++typedef struct ns_saved_context { ++ /* ++ * Structure saved_context would be used to hold processor state ++ * except caller and callee registers, just before suspending. ++ */ ++ ++ /* coprocessor 15 registers */ ++ // __u32 ID_code; /* read only reg */ ++ // __u32 cache_type; /* read only reg */ ++ // __u32 TCM_stat; /* read only reg */ ++ __u32 CR; ++ __u32 TTBR; ++ __u32 DACR; ++ __u32 D_FSR; ++ __u32 I_FSR; ++ __u32 FAR; ++ // __u32 COR; /*write only reg */ ++ // __u32 TLBOR; /*write only reg */ ++ __u32 D_CLR; ++ __u32 I_CLR; ++ __u32 D_TCMRR; ++ __u32 I_TCMRR; ++ __u32 TLBLR; ++ __u32 FCSE; ++ __u32 CID; ++} saved_context; ++#endif ++#ifdef CONFIG_DEBUG_LL ++extern void printascii(const char *); ++#endif ++ ++extern const void __nosave_begin, __nosave_end; ++ ++/*save&restore helper functions*/ ++extern asmlinkage void save_cp15(void *pointer); ++extern asmlinkage void save_control_registers(void *pointer, int is_secure); ++extern asmlinkage void save_mmu(void *pointer); ++extern asmlinkage void save_fault_status(void *pointer); ++extern asmlinkage void save_vfp(void *pointer); ++extern asmlinkage void save_generic_timer(void *pointer, int is_hyp); ++extern asmlinkage void restore_control_registers(void *pointer, int is_secure); ++ ++extern asmlinkage void restore_vfp(void *pointer); ++extern asmlinkage void restore_cp15(void *pointer); ++extern asmlinkage void restore_mmu(void *pointer); ++extern asmlinkage void restore_fault_status(void *pointer); ++extern asmlinkage void restore_generic_timer(void *pointer, int is_hyp); ++extern asmlinkage void invalidate_unified_TLB_inner_shareable(void); ++ ++/*variable define here*/ ++saved_context saved_ctx __attribute__((aligned(PAGE_SIZE))); ++ ++const void *saved_processor_context = &saved_ctx; ++ ++int pfn_is_nosave(unsigned long pfn) ++{ ++ unsigned long nosave_begin_pfn = __pa_symbol(&__nosave_begin) ++ >> PAGE_SHIFT; ++ unsigned long nosave_end_pfn = PAGE_ALIGN(__pa_symbol(&__nosave_end)) ++ >> PAGE_SHIFT; ++ ++ return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn); ++} ++ ++ ++void __save_processor_state(saved_context *ctxt) ++{ ++#ifdef CONFIG_DEBUG_LL ++ printascii("__save_processor_state(): enter\n"); ++#endif ++#if __LINUX_ARM_ARCH__ > 5 ++ save_cp15(ctxt->cp15_misc_regs); ++ ++ save_control_registers(ctxt->cp15_ctrl_regs, 0x0); ++ ++ save_mmu(ctxt->cp15_mmu_regs); ++ ++ save_fault_status(&ctxt->cp15_fault_regs); ++ ++ save_vfp(&ctxt->vfp_regs); ++#else /* for ARM9 */ ++ /* save coprocessor 15 registers */ ++ asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r" (ctxt->CR)); ++ asm volatile ("mrc p15, 0, %0, c3, c0, 0" : "=r" (ctxt->DACR)); ++ asm volatile ("mrc p15, 0, %0, c5, c0, 0" : "=r" (ctxt->D_FSR)); ++ asm volatile ("mrc p15, 0, %0, c5, c0, 1" : "=r" (ctxt->I_FSR)); ++ asm volatile ("mrc p15, 0, %0, c6, c0, 0" : "=r" (ctxt->FAR)); ++ asm volatile ("mrc p15, 0, %0, c9, c0, 0" : "=r" (ctxt->D_CLR)); ++ asm volatile ("mrc p15, 0, %0, c9, c0, 1" : "=r" (ctxt->I_CLR)); ++ asm volatile ("mrc p15, 0, %0, c9, c1, 0" : "=r" (ctxt->D_TCMRR)); ++ asm volatile ("mrc p15, 0, %0, c9, c1, 1" : "=r" (ctxt->I_TCMRR)); ++ asm volatile ("mrc p15, 0, %0, c10, c0, 0" : "=r" (ctxt->TLBLR)); ++ asm volatile ("mrc p15, 0, %0, c13, c0, 0" : "=r" (ctxt->FCSE)); ++ asm volatile ("mrc p15, 0, %0, c13, c0, 1" : "=r" (ctxt->CID)); ++ asm volatile ("mrc p15, 0, %0, c2, c0, 0" : "=r" (ctxt->TTBR)); ++#endif ++ ++#ifdef CONFIG_DEBUG_LL ++ printascii("__save_processor_state(): exit\n"); ++#endif ++} ++ ++ ++void __restore_processor_state(saved_context *ctxt) ++{ ++#ifdef CONFIG_DEBUG_LL ++ printascii("__restore_processor_state(): enter\n"); ++#endif ++#if __LINUX_ARM_ARCH__ > 5 ++ restore_vfp(&ctxt->vfp_regs); ++ ++ restore_fault_status(&ctxt->cp15_fault_regs); ++ ++ restore_mmu(ctxt->cp15_mmu_regs); ++ ++ invalidate_unified_TLB_inner_shareable(); ++ ++ restore_control_registers(ctxt->cp15_ctrl_regs, 0x0); ++ isb(); ++ dsb(); ++ ++ restore_cp15(ctxt->cp15_misc_regs); ++#else /*for arm9 */ ++ /* restore coprocessor 15 registers */ ++ asm volatile ("mcr p15, 0, %0, c2, c0, 0" : : "r" (ctxt->TTBR)); ++ asm volatile ("mcr p15, 0, %0, c13, c0, 1" : : "r" (ctxt->CID)); ++ asm volatile ("mcr p15, 0, %0, c13, c0, 0" : : "r" (ctxt->FCSE)); ++ asm volatile ("mcr p15, 0, %0, c10, c0, 0" : : "r" (ctxt->TLBLR)); ++ asm volatile ("mcr p15, 0, %0, c9, c1, 1" : : "r" (ctxt->I_TCMRR)); ++ asm volatile ("mcr p15, 0, %0, c9, c1, 0" : : "r" (ctxt->D_TCMRR)); ++ asm volatile ("mcr p15, 0, %0, c9, c0, 1" : : "r" (ctxt->I_CLR)); ++ asm volatile ("mcr p15, 0, %0, c9, c0, 0" : : "r" (ctxt->D_CLR)); ++ asm volatile ("mcr p15, 0, %0, c6, c0, 0" : : "r" (ctxt->FAR)); ++ asm volatile ("mcr p15, 0, %0, c5, c0, 1" : : "r" (ctxt->I_FSR)); ++ asm volatile ("mcr p15, 0, %0, c5, c0, 0" : : "r" (ctxt->D_FSR)); ++ asm volatile ("mcr p15, 0, %0, c3, c0, 0" : : "r" (ctxt->DACR)); ++ asm volatile ("mcr p15, 0, %0, c1, c0, 0" : : "r" (ctxt->CR)); ++#endif ++ ++#ifdef CONFIG_DEBUG_LL ++ printascii("__restore_processor_state(): done\n"); ++#endif ++} ++ ++void save_processor_state(void) ++{ ++ preempt_disable(); ++ __save_processor_state(&saved_ctx); ++} ++EXPORT_SYMBOL(save_processor_state); ++ ++void restore_processor_state(void) ++{ ++ __restore_processor_state(&saved_ctx); ++ preempt_enable(); ++} ++EXPORT_SYMBOL(restore_processor_state); +diff --git a/arch/arm/mach-hisi/hisilicon.c b/arch/arm/mach-hisi/hisilicon.c +index 7744c35..43d9d78 100644 +--- a/arch/arm/mach-hisi/hisilicon.c ++++ b/arch/arm/mach-hisi/hisilicon.c +@@ -17,6 +17,7 @@ + + #include + #include ++#include + + #define HI3620_SYSCTRL_PHYS_BASE 0xfc802000 + #define HI3620_SYSCTRL_VIRT_BASE 0xfe802000 +@@ -45,6 +46,268 @@ static void __init hi3620_map_io(void) + iotable_init(hi3620_io_desc, ARRAY_SIZE(hi3620_io_desc)); + } + ++extern unsigned long long notrace sched_clock(void); ++unsigned long long hi_sched_clock(void) ++{ ++ return sched_clock(); ++} ++EXPORT_SYMBOL(hi_sched_clock); ++ ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++static struct map_desc hi3519_io_desc[] __initdata = { ++ /* hi3519_IOCH1 */ ++ { ++ .virtual = HI3519_IOCH1_VIRT, ++ .pfn = __phys_to_pfn(HI3519_IOCH1_PHYS), ++ .length = HI3519_IOCH1_SIZE, ++ .type = MT_DEVICE ++ }, ++ /* hi3519_IOCH2 */ ++ { ++ .virtual = HI3519_IOCH2_VIRT, ++ .pfn = __phys_to_pfn(HI3519_IOCH2_PHYS), ++ .length = HI3519_IOCH2_SIZE, ++ .type = MT_DEVICE ++ }, ++ /* hi3519_IOCH2 */ ++ { ++ .virtual = HI3519_IOCH3_VIRT, ++ .pfn = __phys_to_pfn(HI3519_IOCH3_PHYS), ++ .length = HI3519_IOCH3_SIZE, ++ .type = MT_DEVICE ++ }, ++ ++}; ++ ++static void __init hi3519_reserve(void) ++{ ++#ifdef CONFIG_DMA_CMA ++ extern int hisi_declare_heap_memory(void); ++ hisi_declare_heap_memory(); ++#endif ++} ++#endif ++ ++#ifdef CONFIG_ARCH_HI3516AV200 ++static struct map_desc hi3516av200_io_desc[] __initdata = { ++ /* hi3516av200_IOCH1 */ ++ { ++ .virtual = HI3516AV200_IOCH1_VIRT, ++ .pfn = __phys_to_pfn(HI3516AV200_IOCH1_PHYS), ++ .length = HI3516AV200_IOCH1_SIZE, ++ .type = MT_DEVICE ++ }, ++ /* hi3516av200_IOCH2 */ ++ { ++ .virtual = HI3516AV200_IOCH2_VIRT, ++ .pfn = __phys_to_pfn(HI3516AV200_IOCH2_PHYS), ++ .length = HI3516AV200_IOCH2_SIZE, ++ .type = MT_DEVICE ++ }, ++ /* hi3516av200_IOCH2 */ ++ { ++ .virtual = HI3516AV200_IOCH3_VIRT, ++ .pfn = __phys_to_pfn(HI3516AV200_IOCH3_PHYS), ++ .length = HI3516AV200_IOCH3_SIZE, ++ .type = MT_DEVICE ++ }, ++ ++}; ++ ++static void __init hi3516av200_reserve(void) ++{ ++#ifdef CONFIG_DMA_CMA ++ extern int hisi_declare_heap_memory(void); ++ hisi_declare_heap_memory(); ++#endif ++} ++#endif ++#if defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) ++static struct map_desc hi3559_io_desc[] __initdata = { ++ /* hi3559_IOCH1 */ ++ { ++ .virtual = HI3559_IOCH1_VIRT, ++ .pfn = __phys_to_pfn(HI3559_IOCH1_PHYS), ++ .length = HI3559_IOCH1_SIZE, ++ .type = MT_DEVICE ++ }, ++ /* hi3559_IOCH2 */ ++ { ++ .virtual = HI3559_IOCH2_VIRT, ++ .pfn = __phys_to_pfn(HI3559_IOCH2_PHYS), ++ .length = HI3559_IOCH2_SIZE, ++ .type = MT_DEVICE ++ }, ++ /* hi3559_IOCH2 */ ++ { ++ .virtual = HI3559_IOCH3_VIRT, ++ .pfn = __phys_to_pfn(HI3559_IOCH3_PHYS), ++ .length = HI3559_IOCH3_SIZE, ++ .type = MT_DEVICE ++ }, ++ ++}; ++#endif ++ ++#ifdef CONFIG_ARCH_HI3536C ++static struct map_desc hi3536c_io_desc[] __initdata = { ++ /* hi3536c_IOCH1 */ ++ { ++ .virtual = HI3536C_IOCH1_VIRT, ++ .pfn = __phys_to_pfn(HI3536C_IOCH1_PHYS), ++ .length = HI3536C_IOCH1_SIZE, ++ .type = MT_DEVICE ++ }, ++ /* hi3536c_IOCH2 */ ++ { ++ .virtual = HI3536C_IOCH2_VIRT, ++ .pfn = __phys_to_pfn(HI3536C_IOCH2_PHYS), ++ .length = HI3536C_IOCH2_SIZE, ++ .type = MT_DEVICE ++ }, ++ /* hi3536c_IOCH3 */ ++ { ++ .virtual = HI3536C_IOCH3_VIRT, ++ .pfn = __phys_to_pfn(HI3536C_IOCH3_PHYS), ++ .length = HI3536C_IOCH3_SIZE, ++ .type = MT_DEVICE ++ }, ++}; ++ ++static void __init hi3536c_map_io(void) ++{ ++ iotable_init(hi3536c_io_desc, ARRAY_SIZE(hi3536c_io_desc)); ++} ++ ++static void __init hi3536c_init_early(void) ++{ ++ ++} ++#endif /* CONFIG_ARCH_HI3536C */ ++ ++#ifdef CONFIG_ARCH_HI3531D ++static struct map_desc hi3531d_io_desc[] __initdata = { ++ /* hi3531d_IOCH1 */ ++ { ++ .virtual = HI3531D_IOCH1_VIRT, ++ .pfn = __phys_to_pfn(HI3531D_IOCH1_PHYS), ++ .length = HI3531D_IOCH1_SIZE, ++ .type = MT_DEVICE ++ }, ++ /* hi3531d_IOCH2 */ ++ { ++ .virtual = HI3531D_IOCH2_VIRT, ++ .pfn = __phys_to_pfn(HI3531D_IOCH2_PHYS), ++ .length = HI3531D_IOCH2_SIZE, ++ .type = MT_DEVICE ++ }, ++ /* hi3531d_IOCH3 */ ++ { ++ .virtual = HI3531D_IOCH3_VIRT, ++ .pfn = __phys_to_pfn(HI3531D_IOCH3_PHYS), ++ .length = HI3531D_IOCH3_SIZE, ++ .type = MT_DEVICE ++ }, ++ /* hi3531d_IOCH4 */ ++ { ++ .virtual = HI3531D_IOCH4_VIRT, ++ .pfn = __phys_to_pfn(HI3531D_IOCH4_PHYS), ++ .length = HI3531D_IOCH4_SIZE, ++ .type = MT_DEVICE ++ }, ++ ++}; ++ ++void __init hi3531d_map_io(void) ++{ ++ iotable_init(hi3531d_io_desc, ARRAY_SIZE(hi3531d_io_desc)); ++} ++ ++static void __init hi3531d_init_early(void) ++{ ++ /* ++ * 1. enable L1 prefetch [2] ++ * 4. enable allocation in one cache way only. [8] ++ */ ++ asm volatile ( ++ " mrc p15, 0, r0, c1, c0, 1\n" ++ " orr r0, r0, #0x104\n" ++ " mcr p15, 0, r0, c1, c0, 1\n" ++ : ++ : ++ : "r0", "cc"); ++ ++} ++#endif ++ ++#ifdef CONFIG_ARCH_HI3521D ++static struct map_desc hi3521d_io_desc[] __initdata = { ++ /* hi3521d_IOCH1 */ ++ { ++ .virtual = HI3521D_IOCH1_VIRT, ++ .pfn = __phys_to_pfn(HI3521D_IOCH1_PHYS), ++ .length = HI3521D_IOCH1_SIZE, ++ .type = MT_DEVICE ++ }, ++ /* hi3521d_IOCH2 */ ++ { ++ .virtual = HI3521D_IOCH2_VIRT, ++ .pfn = __phys_to_pfn(HI3521D_IOCH2_PHYS), ++ .length = HI3521D_IOCH2_SIZE, ++ .type = MT_DEVICE ++ }, ++ /* hi3521d_IOCH3 */ ++ { ++ .virtual = HI3521D_IOCH3_VIRT, ++ .pfn = __phys_to_pfn(HI3521D_IOCH3_PHYS), ++ .length = HI3521D_IOCH3_SIZE, ++ .type = MT_DEVICE ++ }, ++}; ++ ++static void __init hi3521d_map_io(void) ++{ ++ iotable_init(hi3521d_io_desc, ARRAY_SIZE(hi3521d_io_desc)); ++} ++ ++static void __init hi3521d_init_early(void) ++{ ++ ++} ++#endif /* CONFIG_ARCH_HI3521D */ ++ ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++static void __init hi3519_map_io(void) ++{ ++ /* debug_ll_io_init(); */ ++ iotable_init(hi3519_io_desc, ARRAY_SIZE(hi3519_io_desc)); ++} ++#endif ++ ++#ifdef CONFIG_ARCH_HI3516AV200 ++static void __init hi3516av200_map_io(void) ++{ ++ /* debug_ll_io_init(); */ ++ iotable_init(hi3516av200_io_desc, ARRAY_SIZE(hi3516av200_io_desc)); ++} ++#endif ++ ++#if defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) ++static void __init hi3559_map_io(void) ++{ ++ /* debug_ll_io_init(); */ ++ iotable_init(hi3559_io_desc, ARRAY_SIZE(hi3559_io_desc)); ++} ++ ++static void __init hi3559_reserve(void) ++{ ++#ifdef CONFIG_DMA_CMA ++ extern int hisi_declare_heap_memory(void); ++ hisi_declare_heap_memory(); ++#endif ++} ++#endif ++ + static const char *hi3xxx_compat[] __initconst = { + "hisilicon,hi3620-hi4511", + NULL, +@@ -72,3 +335,100 @@ static const char *hip04_compat[] __initconst = { + DT_MACHINE_START(HIP04, "Hisilicon HiP04 (Flattened Device Tree)") + .dt_compat = hip04_compat, + MACHINE_END ++ ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++static const char *hi3519_compat[] __initconst = { ++ "hisilicon,hi3519", ++ "hisilicon,hi3519v101", ++ NULL, ++}; ++#endif ++ ++#ifdef CONFIG_ARCH_HI3516AV200 ++static const char *hi3516av200_compat[] __initconst = { ++ "hisilicon,hi3516av200", ++ NULL, ++}; ++#endif ++#if defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) ++static const char *hi3559_compat[] __initconst = { ++ "hisilicon,hi3559", ++ "hisilicon,hi3556", ++ NULL, ++}; ++#endif ++ ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++DT_MACHINE_START(HI3519_DT, "Hisilicon Hi3519 (Flattened Device Tree)") ++ .map_io = hi3519_map_io, ++ .dt_compat = hi3519_compat, ++ .reserve = hi3519_reserve, ++MACHINE_END ++#endif ++ ++#ifdef CONFIG_ARCH_HI3516AV200 ++DT_MACHINE_START(HI3516AV200_DT, "Hisilicon Hi3516av200 (Flattened Device Tree)") ++ .map_io = hi3516av200_map_io, ++ .dt_compat = hi3516av200_compat, ++ .reserve = hi3516av200_reserve, ++MACHINE_END ++#endif ++#if defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) ++DT_MACHINE_START(HI3559_DT, "Hisilicon Hi3559/Hi3556 (Flattened Device Tree)") ++ .map_io = hi3559_map_io, ++ .dt_compat = hi3559_compat, ++ .reserve = hi3559_reserve, ++MACHINE_END ++#endif ++ ++#ifdef CONFIG_ARCH_HI3516CV300 ++static const char *hi3516cv300_compat[] __initconst = { ++ "hisilicon,hi3516cv300", ++ NULL, ++}; ++ ++DT_MACHINE_START(HI3516CV300_DT, ++ "Hisilicon Hi3516cv300 (Flattened Device Tree)") ++ .dt_compat = hi3516cv300_compat, ++MACHINE_END ++#endif ++ ++#ifdef CONFIG_ARCH_HI3536C ++static const char *hi3536c_compat[] __initconst = { ++ "hisilicon,hi3536c", ++ NULL, ++}; ++ ++DT_MACHINE_START(HI3536C_DT, "Hisilicon Hi3536C (Flattened Device Tree)") ++ .map_io = hi3536c_map_io, ++ .dt_compat = hi3536c_compat, ++ .init_early = hi3536c_init_early, ++MACHINE_END ++#endif ++ ++#ifdef CONFIG_ARCH_HI3531D ++static const char *hi3531d_compat[] __initconst = { ++ "hisilicon,hi3531d", ++ NULL, ++}; ++ ++DT_MACHINE_START(HI3531D_DT, "Hisilicon Hi3531D (Flattened Device Tree)") ++ .map_io = hi3531d_map_io, ++ .dt_compat = hi3531d_compat, ++ .init_early = hi3531d_init_early, ++MACHINE_END ++#endif ++ ++#ifdef CONFIG_ARCH_HI3521D ++static const char *hi3521d_compat[] __initconst = { ++ "hisilicon,hi3521d", ++ NULL, ++}; ++ ++DT_MACHINE_START(HI3521D_DT, "Hisilicon Hi3521D (Flattened Device Tree)") ++ .map_io = hi3521d_map_io, ++ .dt_compat = hi3521d_compat, ++ .init_early = hi3521d_init_early, ++MACHINE_END ++#endif ++ +diff --git a/arch/arm/mach-hisi/hotplug.c b/arch/arm/mach-hisi/hotplug.c +index 84e6919..5f3ebf6 100644 +--- a/arch/arm/mach-hisi/hotplug.c ++++ b/arch/arm/mach-hisi/hotplug.c +@@ -11,11 +11,22 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include ++#include ++ + #include "core.h" + ++#if (defined(CONFIG_ARCH_HI3531D) \ ++ || defined(CONFIG_ARCH_HI3536C) \ ++ || defined(CONFIG_ARCH_HI3521D)) ++#include ++#include ++#endif ++ + /* Sysctrl registers in Hi3620 SoC */ + #define SCISOEN 0xc0 + #define SCISODIS 0xc4 +@@ -257,4 +268,289 @@ void hix5hd2_cpu_die(unsigned int cpu) + flush_cache_all(); + hix5hd2_set_cpu(cpu, false); + } ++ ++int hi3519_cpu_kill(unsigned int cpu) ++{ ++#ifdef CONFIG_ARCH_HI3519 ++ hi_pmc_kill_cpu(cpu); ++#endif ++ return 1; ++} ++ ++int hi3559_cpu_kill(unsigned int cpu) ++{ ++ return 1; ++} ++ ++int hi3516av200_cpu_kill(unsigned int cpu) ++{ ++ return 1; ++} ++ ++void hi3519_cpu_die(unsigned int cpu) ++{ ++ /*avoid interrupt to disturb wfi&&pmc sequence */ ++ gic_cpu_if_down(); ++ /* disable Dcache */ ++ set_cr(get_cr() & ~CR_C); ++ /* CLREX */ ++ asm volatile ("clrex"); ++ ++ /* Clean & Invalidata L1 Data Cache, L2 Cache */ ++ /* flush_cache_all(); */ ++ ++ /* clean&invalidate l1 cache */ ++ asm volatile("mov r0, #0\n"); ++ asm volatile("mcr p15, 1, r0, c15, c14, 0\n"); ++ asm volatile("dsb\n"); ++ ++ /* clean&invalidate l2 cache */ ++ asm volatile("mov r0, #2\n"); ++ asm volatile("mcr p15, 1, r0, c15, c14, 0\n"); ++ asm volatile("dsb\n"); ++ ++ /* Set ACTLR.SMP to 0, AMP -> SMP */ ++ asm volatile ( ++ " mrc p15, 0, r0, c1, c0, 1\n" ++ " bic r0, #0x40\n" ++ " mcr p15, 0, r0, c1, c0, 1\n" ++ : ++ : ++ : "r0", "cc"); ++ ++ /* disable cci snoop */ ++ cci_disable_port_by_cpu(cpu_logical_map(cpu)); ++ ++ /* avoid debug event wake up cpu */ ++ /* asm volatile("mcr p14, 0, %0, c1, c3, 0" : : "r" (1)); */ ++ ++ /* ISB & DSB */ ++ isb(); ++ dsb(); ++ ++ /* clear core ac inactive */ ++ hi_pmc_set_ac_inactive(); ++ ++ /* power down */ ++ hi_pmc_power_down(); ++ ++ dsb(); ++ /* wfi */ ++ while (1) ++ wfi(); ++ ++} ++ ++void hi3516av200_cpu_die(unsigned int cpu) ++{ ++ /*avoid interrupt to disturb wfi&&pmc sequence */ ++ gic_cpu_if_down(); ++ /* disable Dcache */ ++ set_cr(get_cr() & ~CR_C); ++ /* CLREX */ ++ asm volatile ("clrex"); ++ ++ /* Clean & Invalidata L1 Data Cache, L2 Cache */ ++ /* flush_cache_all(); */ ++ ++ /* clean&invalidate l1 cache */ ++ asm volatile("mov r0, #0\n"); ++ asm volatile("mcr p15, 1, r0, c15, c14, 0\n"); ++ asm volatile("dsb\n"); ++ ++ /* clean&invalidate l2 cache */ ++ asm volatile("mov r0, #2\n"); ++ asm volatile("mcr p15, 1, r0, c15, c14, 0\n"); ++ asm volatile("dsb\n"); ++ ++ /* Set ACTLR.SMP to 0, AMP -> SMP */ ++ asm volatile ( ++ " mrc p15, 0, r0, c1, c0, 1\n" ++ " bic r0, #0x40\n" ++ " mcr p15, 0, r0, c1, c0, 1\n" ++ : ++ : ++ : "r0", "cc"); ++ ++ /* disable cci snoop */ ++ cci_disable_port_by_cpu(cpu_logical_map(cpu)); ++ ++ /* avoid debug event wake up cpu */ ++ /* asm volatile("mcr p14, 0, %0, c1, c3, 0" : : "r" (1)); */ ++ ++ /* ISB & DSB */ ++ isb(); ++ dsb(); ++ ++ /* clear core ac inactive */ ++ hi_pmc_set_ac_inactive(); ++ ++ /* power down */ ++ hi_pmc_power_down(); ++ ++ dsb(); ++ /* wfi */ ++ while (1) ++ wfi(); ++ ++} ++ ++void hi3559_cpu_die(unsigned int cpu) ++{ ++ /*avoid interrupt to disturb wfi&&pmc sequence */ ++ gic_cpu_if_down(); ++ /* disable Dcache */ ++ set_cr(get_cr() & ~CR_C); ++ /* CLREX */ ++ asm volatile ("clrex"); ++ ++ /* Clean & Invalidata L1 Data Cache, L2 Cache */ ++ /* flush_cache_all(); */ ++ ++ /* clean&invalidate l1 cache */ ++ asm volatile("mov r0, #0\n"); ++ asm volatile("mcr p15, 1, r0, c15, c14, 0\n"); ++ asm volatile("dsb\n"); ++ ++ /* clean&invalidate l2 cache */ ++ asm volatile("mov r0, #2\n"); ++ asm volatile("mcr p15, 1, r0, c15, c14, 0\n"); ++ asm volatile("dsb\n"); ++ ++ /* Set ACTLR.SMP to 0, AMP -> SMP */ ++ asm volatile ( ++ " mrc p15, 0, r0, c1, c0, 1\n" ++ " bic r0, #0x40\n" ++ " mcr p15, 0, r0, c1, c0, 1\n" ++ : ++ : ++ : "r0", "cc"); ++ ++ /* disable cci snoop */ ++ cci_disable_port_by_cpu(cpu_logical_map(cpu)); ++ ++ /* avoid debug event wake up cpu */ ++ /* asm volatile("mcr p14, 0, %0, c1, c3, 0" : : "r" (1)); */ ++ ++ /* ISB & DSB */ ++ isb(); ++ dsb(); ++ ++ /* clear core ac inactive */ ++ hi_pmc_set_ac_inactive(); ++ ++ /* power down */ ++ hi_pmc_power_down(); ++ ++ dsb(); ++ /* wfi */ ++ while (1) ++ wfi(); ++ ++} ++ ++int hi3536c_cpu_kill(unsigned int cpu) ++{ ++ return 1; ++} ++ ++void hi3536c_scu_power_up(int cpu) ++{ ++#ifdef CONFIG_ARCH_HI3536C ++ unsigned int regval; ++ ++ /* clear the slave cpu reset */ ++ regval = readl(__io_address(CRG_REG_BASE + REG_A7_SRST_CRG)); ++ regval &= ~CORE1_SRST_REQ; ++ writel(regval, __io_address(CRG_REG_BASE + REG_A7_SRST_CRG)); ++#endif ++} ++ ++static inline void hi3536c_scu_power_off(int cpu) ++{ ++#ifdef CONFIG_ARCH_HI3536C ++ unsigned long regval; ++ ++ regval = readl(__io_address(CRG_REG_BASE + REG_A7_SRST_CRG)); ++ regval |= (DBG1_SRST_REQ | CORE1_SRST_REQ); ++ writel(regval, __io_address(CRG_REG_BASE + REG_A7_SRST_CRG)); ++#endif ++} ++ ++void hi3536c_cpu_die(unsigned int cpu) ++{ ++ flush_cache_all(); ++ hi3536c_scu_power_off(cpu); ++ BUG(); ++} ++ ++int hi3531d_cpu_kill(unsigned int cpu) ++{ ++ return 1; ++} ++ ++void hi3531d_scu_power_up(int cpu) ++{ ++#ifdef CONFIG_ARCH_HI3531D ++ unsigned int regval; ++ ++ /* clear the slave cpu reset */ ++ regval = readl(__io_address(CRG_REG_BASE + REG_A9_SRST_CRG)); ++ regval &= ~CPU1_SRST_REQ; ++ writel(regval, __io_address(CRG_REG_BASE + REG_A9_SRST_CRG)); ++#endif ++} ++ ++static inline void hi3531d_scu_power_off(int cpu) ++{ ++#ifdef CONFIG_ARCH_HI3531D ++ unsigned long regval; ++ ++ regval = readl(__io_address(CRG_REG_BASE + REG_A9_SRST_CRG)); ++ regval |= (WDG1_SRST_REQ | DBG1_SRST_REQ | CPU1_SRST_REQ); ++ writel(regval, __io_address(CRG_REG_BASE + REG_A9_SRST_CRG)); ++#endif ++} ++ ++void hi3531d_cpu_die(unsigned int cpu) ++{ ++ flush_cache_all(); ++ hi3531d_scu_power_off(cpu); ++ BUG(); ++} ++ ++int hi3521d_cpu_kill(unsigned int cpu) ++{ ++ return 1; ++} ++ ++void hi3521d_scu_power_up(int cpu) ++{ ++#ifdef CONFIG_ARCH_HI3521D ++ unsigned int regval; ++ ++ /* clear the slave cpu reset */ ++ regval = readl(__io_address(CRG_REG_BASE + REG_A7_SRST_CRG)); ++ regval &= ~CORE1_SRST_REQ; ++ writel(regval, __io_address(CRG_REG_BASE + REG_A7_SRST_CRG)); ++#endif ++} ++ ++static inline void hi3521d_scu_power_off(int cpu) ++{ ++#ifdef CONFIG_ARCH_HI3521D ++ unsigned long regval; ++ ++ regval = readl(__io_address(CRG_REG_BASE + REG_A7_SRST_CRG)); ++ regval |= (DBG1_SRST_REQ | CORE1_SRST_REQ); ++ writel(regval, __io_address(CRG_REG_BASE + REG_A7_SRST_CRG)); ++#endif ++} ++ ++void hi3521d_cpu_die(unsigned int cpu) ++{ ++ flush_cache_all(); ++ hi3521d_scu_power_off(cpu); ++ BUG(); ++} + #endif +diff --git a/arch/arm/mach-hisi/l2cache.c b/arch/arm/mach-hisi/l2cache.c +new file mode 100644 +index 0000000..52aa2ec +--- /dev/null ++++ b/arch/arm/mach-hisi/l2cache.c +@@ -0,0 +1,71 @@ ++/* ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#define pr_fmt(fmt) "l2cache: " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static void __iomem *l2x0_virt_base = __io_address(REG_BASE_L2CACHE); ++ ++static int __init l2_cache_init(void) ++{ ++ u32 val; ++ /* ++ * Bits Value Description ++ * [31] 0 : SBZ ++ * [30] 1 : Double linefill enable (L3) ++ * [29] 1 : Instruction prefetching enable ++ * [28] 1 : Data prefetching enabled ++ * [27] 0 : Double linefill on WRAP read enabled (L3) ++ * [26:25] 0 : SBZ ++ * [24] 1 : Prefetch drop enable (L3) ++ * [23] 0 : Incr double Linefill enable (L3) ++ * [22] 0 : SBZ ++ * [21] 0 : Not same ID on exclusive sequence enable (L3) ++ * [20:5] 0 : SBZ ++ * [4:0] 0 : use the Prefetch offset values 0. ++ */ ++ /* writel_relaxed(0x71000000, l2x0_virt_base + L2X0_PREFETCH_CTRL); */ ++ writel_relaxed(0x71000000, l2x0_virt_base + L310_PREFETCH_CTRL); ++ ++ val = __raw_readl(l2x0_virt_base + L2X0_AUX_CTRL); ++ val |= (1 << 30); /* Early BRESP enabled */ ++ val |= (1 << 0); /* Full Line of Zero Enable */ ++ writel_relaxed(val, l2x0_virt_base + L2X0_AUX_CTRL); ++ l2x0_init(l2x0_virt_base, 0x00430000, 0xFFB0FFFF); ++ /* ++ * 2. enable L2 prefetch hint [1]a ++ * 3. enable write full line of zeros mode. [3]a ++ * a: This feature must be enabled only when the slaves ++ * connected on the Cortex-A9 AXI master port support it. ++ */ ++ asm volatile ( ++ " mrc p15, 0, r0, c1, c0, 1\n" ++ " orr r0, r0, #0x02\n" ++ " mcr p15, 0, r0, c1, c0, 1\n" ++ : ++ : ++ : "r0", "cc"); ++ ++ return 0; ++} ++early_initcall(l2_cache_init); +diff --git a/arch/arm/mach-hisi/platsmp.c b/arch/arm/mach-hisi/platsmp.c +index 575dd82..fdc3984 100644 +--- a/arch/arm/mach-hisi/platsmp.c ++++ b/arch/arm/mach-hisi/platsmp.c +@@ -7,19 +7,48 @@ + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ ++ ++#include + #include + #include + #include +- + #include + #include + #include + ++#if (defined(CONFIG_ARCH_HI3531D) \ ++ || defined(CONFIG_ARCH_HI3536C) \ ++ || defined(CONFIG_ARCH_HI3521D)) ++#include ++#include ++#endif ++ + #include "core.h" + + #define HIX5HD2_BOOT_ADDRESS 0xffff0000 ++#define HI3519_BOOT_ADDRESS 0x00000000 ++#define HI3559_BOOT_ADDRESS 0x00000000 ++#define HI3516AV200_BOOT_ADDRESS 0x00000000 ++#define HI3536C_BOOT_ADDRESS 0x00000000 ++#define HI3531D_BOOT_ADDRESS 0x00000000 ++#define HI3521D_BOOT_ADDRESS 0x00000000 + ++static void __iomem *hi3519_bootaddr; ++static void __iomem *hi3559_bootaddr; ++static void __iomem *hi3516av200_bootaddr; ++static void __iomem *hi3536c_bootaddr; ++static void __iomem *hi3531d_bootaddr; ++static void __iomem *hi3521d_bootaddr; + static void __iomem *ctrl_base; ++static DEFINE_SPINLOCK(boot_lock); ++ ++static void __cpuinit hi_write_pen_release(int val) ++{ ++ pen_release = val; ++ smp_wmb(); ++ __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); ++ outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); ++} + + void hi3xxx_set_cpu_jump(int cpu, void *jump_addr) + { +@@ -132,5 +161,622 @@ struct smp_operations hix5hd2_smp_ops __initdata = { + #endif + }; + ++void hi3519_set_cpu_jump(unsigned int cpu, phys_addr_t jumpaddr) ++{ ++ /* only cortex-a17 boot from phys 0 address */ ++ if (cpu != 1) ++ return; ++ /* ldr pc, [rc, #-4] */ ++ writel_relaxed(0xe51ff004, hi3519_bootaddr); ++ /* pc jump phy address */ ++ writel_relaxed(jumpaddr, hi3519_bootaddr + 4); ++ ++ dsb(); ++} ++ ++void hi3516av200_set_cpu_jump(unsigned int cpu, phys_addr_t jumpaddr) ++{ ++ /* only cortex-a17 boot from phys 0 address */ ++ if (cpu != 1) ++ return; ++ /* ldr pc, [rc, #-4] */ ++ writel_relaxed(0xe51ff004, hi3516av200_bootaddr); ++ /* pc jump phy address */ ++ writel_relaxed(jumpaddr, hi3516av200_bootaddr + 4); ++ ++ dsb(); ++} ++ ++void hi3559_set_cpu_jump(unsigned int cpu, phys_addr_t jumpaddr) ++{ ++ /* only cortex-a17 boot from phys 0 address */ ++ if (cpu != 1) ++ return; ++ /* ldr pc, [rc, #-4] */ ++ writel_relaxed(0xe51ff004, hi3559_bootaddr); ++ /* pc jump phy address */ ++ writel_relaxed(jumpaddr, hi3559_bootaddr + 4); ++ ++ dsb(); ++} ++ ++static void __init hi3519_smp_prepare_cpus(unsigned int max_cpus) ++{ ++ if (!hi3519_bootaddr) ++ hi3519_bootaddr = ioremap(HI3519_BOOT_ADDRESS, PAGE_SIZE); ++ ++ sync_cache_w(&hi3519_bootaddr); ++} ++ ++static void __init hi3516av200_smp_prepare_cpus(unsigned int max_cpus) ++{ ++ if (!hi3516av200_bootaddr) ++ hi3516av200_bootaddr = ioremap(HI3516AV200_BOOT_ADDRESS, PAGE_SIZE); ++ ++ sync_cache_w(&hi3516av200_bootaddr); ++} ++ ++static void __init hi3559_smp_prepare_cpus(unsigned int max_cpus) ++{ ++ if (!hi3559_bootaddr) ++ hi3559_bootaddr = ioremap(HI3559_BOOT_ADDRESS, PAGE_SIZE); ++ ++ sync_cache_w(&hi3559_bootaddr); ++} ++ ++static int hi3519_boot_secondary(unsigned int cpu, struct task_struct *idle) ++{ ++ flush_cache_all(); ++ ++ hi3519_set_cpu_jump(cpu, virt_to_phys(hi3519_secondary_startup)); ++ ++ hi_pmc_power_up(); ++ ++ return 0; ++} ++ ++static int hi3516av200_boot_secondary(unsigned int cpu, struct task_struct *idle) ++{ ++ flush_cache_all(); ++ ++ hi3516av200_set_cpu_jump(cpu, virt_to_phys(hi3516av200_secondary_startup)); ++ ++ hi_pmc_power_up(); ++ ++ return 0; ++} ++ ++static int hi3559_boot_secondary(unsigned int cpu, struct task_struct *idle) ++{ ++ flush_cache_all(); ++ ++ hi3559_set_cpu_jump(cpu, virt_to_phys(hi3559_secondary_startup)); ++ ++ hi_pmc_power_up(); ++ ++ return 0; ++} ++ ++static void HI3519_secondary_init(unsigned int cpu) ++{ ++/* ++ hi_pmc_power_up_done(); ++*/ ++} ++ ++static void HI3516av200_secondary_init(unsigned int cpu) ++{ ++/* ++ hi_pmc_power_up_done(); ++*/ ++} ++ ++static void HI3559_secondary_init(unsigned int cpu) ++{ ++/* ++ hi_pmc_power_up_done(); ++*/ ++} ++ ++void hi3536c_set_cpu_jump(unsigned int cpu, phys_addr_t jumpaddr) ++{ ++ /* only cortex-a17 boot from phys 0 address */ ++ if (cpu != 1) ++ return; ++ /* ldr pc, [rc, #-4] */ ++ writel_relaxed(0xe51ff004, hi3536c_bootaddr); ++ /* pc jump phy address */ ++ writel_relaxed(jumpaddr, hi3536c_bootaddr + 4); ++ ++ dsb(); ++} ++ ++void hi3531d_set_cpu_jump(unsigned int cpu, phys_addr_t jumpaddr) ++{ ++ /* only cortex-a17 boot from phys 0 address */ ++ if (cpu != 1) ++ return; ++ /* ldr pc, [rc, #-4] */ ++ writel_relaxed(0xe51ff004, hi3531d_bootaddr); ++ /* pc jump phy address */ ++ writel_relaxed(jumpaddr, hi3531d_bootaddr + 4); ++ ++ dsb(); ++} ++ ++void hi3521d_set_cpu_jump(unsigned int cpu, phys_addr_t jumpaddr) ++{ ++ /* only cortex-a17 boot from phys 0 address */ ++ if (cpu != 1) ++ return; ++ /* ldr pc, [rc, #-4] */ ++ writel_relaxed(0xe51ff004, hi3521d_bootaddr); ++ /* pc jump phy address */ ++ writel_relaxed(jumpaddr, hi3521d_bootaddr + 4); ++ ++ dsb(); ++} ++ ++static void __iomem *scu_base_addr(void) ++{ ++#ifdef CONFIG_ARCH_HI3531D ++ return __io_address(A9_PERI_BASE + REG_A9_PERI_SCU); ++#elif (defined(CONFIG_ARCH_HI3536C) \ ++ || defined(CONFIG_ARCH_HI3521D)) ++ return __io_address(A7_PERI_BASE + REG_A7_PERI_SCU); ++#endif ++ return NULL; ++} ++ ++static void __init hi3536c_smp_prepare_cpus(unsigned int max_cpus) ++{ ++ void __iomem *base = NULL; ++ ++ base = scu_base_addr(); ++ if (!base) ++ return; ++ ++ scu_enable(base); ++} ++ ++static void __init hi3531d_smp_prepare_cpus(unsigned int max_cpus) ++{ ++ scu_enable(scu_base_addr()); ++} ++ ++static void __init hi3521d_smp_prepare_cpus(unsigned int max_cpus) ++{ ++ scu_enable(scu_base_addr()); ++} ++ ++/*****************************************************************************/ ++/* ++ * copy startup code to sram, and flash cache. ++ * @start_addr: slave start phy address ++ * @jump_addr: slave jump phy address ++ */ ++static void hi3536c_set_scu_boot_addr(unsigned int start_addr, ++ unsigned int jump_addr) ++{ ++ unsigned int *virtaddr; ++ unsigned int *p_virtaddr; ++ ++ p_virtaddr = virtaddr = ioremap(start_addr, PAGE_SIZE); ++ ++ *p_virtaddr++ = 0xe51ff004; /* ldr pc, [pc, #-4] */ ++ *p_virtaddr++ = jump_addr; /* pc jump phy address */ ++ ++ smp_wmb(); ++ ++ __cpuc_flush_dcache_area((void *)virtaddr, ++ (size_t)((char *)p_virtaddr - (char *)virtaddr)); ++ outer_clean_range(__pa(virtaddr), __pa(p_virtaddr)); ++ ++ iounmap(virtaddr); ++} ++ ++/*****************************************************************************/ ++/* ++ * copy startup code to sram, and flash cache. ++ * @start_addr: slave start phy address ++ * @jump_addr: slave jump phy address ++ */ ++static void hi3531d_set_scu_boot_addr(unsigned int start_addr, ++ unsigned int jump_addr) ++{ ++ unsigned int *virtaddr; ++ unsigned int *p_virtaddr; ++ ++ p_virtaddr = virtaddr = ioremap(start_addr, PAGE_SIZE); ++ ++ *p_virtaddr++ = 0xe51ff004; /* ldr pc, [pc, #-4] */ ++ *p_virtaddr++ = jump_addr; /* pc jump phy address */ ++ ++ smp_wmb(); ++ ++ __cpuc_flush_dcache_area((void *)virtaddr, ++ (size_t)((char *)p_virtaddr - (char *)virtaddr)); ++ outer_clean_range(__pa(virtaddr), __pa(p_virtaddr)); ++ ++ iounmap(virtaddr); ++} ++ ++static void hi3521d_set_scu_boot_addr(unsigned int start_addr, ++ unsigned int jump_addr) ++{ ++ unsigned int *virtaddr; ++ unsigned int *p_virtaddr; ++ ++ p_virtaddr = virtaddr = ioremap(start_addr, PAGE_SIZE); ++ ++ *p_virtaddr++ = 0xe51ff004; /* ldr pc, [pc, #-4] */ ++ *p_virtaddr++ = jump_addr; /* pc jump phy address */ ++ ++ smp_wmb(); ++ ++ __cpuc_flush_dcache_area((void *)virtaddr, ++ (size_t)((char *)p_virtaddr - (char *)virtaddr)); ++ outer_clean_range(__pa(virtaddr), __pa(p_virtaddr)); ++ ++ iounmap(virtaddr); ++} ++ ++static int __cpuinit hi3536c_boot_secondary(unsigned int cpu, ++ struct task_struct *idle) ++{ ++ unsigned long timeout; ++ ++ hi3536c_set_scu_boot_addr(0x00000000, ++ (unsigned int)virt_to_phys(hi3536c_secondary_startup)); ++ ++ /* ++ * set synchronisation state between this boot processor ++ * and the secondary one ++ */ ++ spin_lock(&boot_lock); ++ ++ hi3536c_scu_power_up(cpu); ++ /* ++ * The secondary processor is waiting to be released from ++ * the holding pen - release it, then wait for it to flag ++ * that it has been released by resetting pen_release. ++ * ++ * Note that "pen_release" is the hardware CPU ID, whereas ++ * "cpu" is Linux's internal ID. ++ */ ++ hi_write_pen_release(cpu); ++ ++ /* ++ * Send the secondary CPU a soft interrupt, thereby causing ++ * the boot monitor to read the system wide flags register, ++ * and branch to the address found there. ++ */ ++ arch_send_wakeup_ipi_mask(cpumask_of(cpu)); ++ ++ /* ++ * Send the secondary CPU a soft interrupt, thereby causing ++ * the boot monitor to read the system wide flags register, ++ * and branch to the address found there. ++ */ ++ timeout = jiffies + (5 * HZ); ++ while (time_before(jiffies, timeout)) { ++ smp_rmb(); ++ if (pen_release == -1) ++ break; ++ ++ udelay(10); ++ } ++ ++ /* ++ * now the secondary core is starting up let it run its ++ * calibrations, then wait for it to finish ++ */ ++ spin_unlock(&boot_lock); ++ ++ return pen_release != -1 ? -ENOSYS : 0; ++} ++ ++static int hi3531d_boot_secondary(unsigned int cpu, struct task_struct *idle) ++{ ++ unsigned long timeout; ++ ++ hi3531d_set_scu_boot_addr(0x00000000, ++ (unsigned int)virt_to_phys(hi3531d_secondary_startup)); ++ ++ /* ++ * * set synchronisation state between this boot processor ++ * * and the secondary one ++ * */ ++ spin_lock(&boot_lock); ++ ++ hi3531d_scu_power_up(cpu); ++ ++ /* ++ * The secondary processor is waiting to be released from ++ * the holding pen - release it, then wait for it to flag ++ * that it has been released by resetting pen_release. ++ * ++ * Note that "pen_release" is the hardware CPU ID, whereas ++ * "cpu" is Linux's internal ID. ++ */ ++ hi_write_pen_release(cpu); ++ ++ /* ++ * Send the secondary CPU a soft interrupt, thereby causing ++ * the boot monitor to read the system wide flags register, ++ * and branch to the address found there. ++ */ ++ arch_send_wakeup_ipi_mask(cpumask_of(cpu)); ++ ++ /* ++ * Send the secondary CPU a soft interrupt, thereby causing ++ * the boot monitor to read the system wide flags register, ++ * and branch to the address found there. ++ */ ++ timeout = jiffies + (5 * HZ); ++ while (time_before(jiffies, timeout)) { ++ smp_rmb(); ++ if (pen_release == -1) ++ break; ++ udelay(10); ++ } ++ ++ /* ++ * now the secondary core is starting up let it run its ++ * calibrations, then wait for it to finish ++ */ ++ spin_unlock(&boot_lock); ++ return pen_release != -1 ? -ENOSYS : 0; ++} ++ ++static int __cpuinit hi3521d_boot_secondary(unsigned int cpu, ++ struct task_struct *idle) ++{ ++ unsigned long timeout; ++ ++ hi3521d_set_scu_boot_addr(0x00000000, ++ (unsigned int)virt_to_phys(hi3521d_secondary_startup)); ++ ++ /* ++ * set synchronisation state between this boot processor ++ * and the secondary one ++ */ ++ spin_lock(&boot_lock); ++ ++ hi3521d_scu_power_up(cpu); ++ /* ++ * The secondary processor is waiting to be released from ++ * the holding pen - release it, then wait for it to flag ++ * that it has been released by resetting pen_release. ++ * ++ * Note that "pen_release" is the hardware CPU ID, whereas ++ * "cpu" is Linux's internal ID. ++ */ ++ hi_write_pen_release(cpu); ++ ++ /* ++ * Send the secondary CPU a soft interrupt, thereby causing ++ * the boot monitor to read the system wide flags register, ++ * and branch to the address found there. ++ */ ++ arch_send_wakeup_ipi_mask(cpumask_of(cpu)); ++ ++ /* ++ * Send the secondary CPU a soft interrupt, thereby causing ++ * the boot monitor to read the system wide flags register, ++ * and branch to the address found there. ++ */ ++ timeout = jiffies + (5 * HZ); ++ while (time_before(jiffies, timeout)) { ++ smp_rmb(); ++ if (pen_release == -1) ++ break; ++ ++ udelay(10); ++ } ++ ++ /* ++ * now the secondary core is starting up let it run its ++ * calibrations, then wait for it to finish ++ */ ++ spin_unlock(&boot_lock); ++ ++ return pen_release != -1 ? -ENOSYS : 0; ++} ++ ++static void __cpuinit hi3536c_secondary_init(unsigned int cpu) ++{ ++ /* ++ * let the primary processor know we're out of the ++ * pen, then head off into the C entry point ++ */ ++ hi_write_pen_release(-1); ++ ++ /* ++ * Synchronise with the boot thread. ++ */ ++ spin_lock(&boot_lock); ++ spin_unlock(&boot_lock); ++} ++ ++static void hi3531d_secondary_init(unsigned int cpu) ++{ ++ /* ++ * 1. enable L1 prefetch [2] ++ * 2. enable L2 prefetch hint [1]a ++ * 3. enable write full line of zeros mode. [3]a ++ * 4. enable allocation in one cache way only. [8] ++ * a: This feature must be enabled only when the slaves ++ * connected on the Cortex-A17 AXI master port support it. ++ */ ++ asm volatile ( ++ " mrc p15, 0, r0, c1, c0, 1\n" ++ " orr r0, r0, #0x0104\n" ++ " orr r0, r0, #0x02\n" ++ " mcr p15, 0, r0, c1, c0, 1\n" ++ : ++ : ++ : "r0", "cc"); ++ ++ /* ++ * * let the primary processor know we're out of the ++ * * pen, then head off into the C entry point ++ * */ ++ hi_write_pen_release(-1); ++ ++ /* ++ * Synchronise with the boot thread. ++ */ ++ spin_lock(&boot_lock); ++ spin_unlock(&boot_lock); ++} ++ ++static void __cpuinit hi3521d_secondary_init(unsigned int cpu) ++{ ++ /* ++ * let the primary processor know we're out of the ++ * pen, then head off into the C entry point ++ */ ++ hi_write_pen_release(-1); ++ ++ /* ++ * Synchronise with the boot thread. ++ */ ++ spin_lock(&boot_lock); ++ spin_unlock(&boot_lock); ++} ++ ++static void __init hi3536c_smp_init_cpus(void) ++{ ++ unsigned int i, ncores, l2ctlr; ++ ++ asm volatile("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr)); ++ ncores = ((l2ctlr >> 24) & 0x3) + 1; ++ ++ /* sanity check */ ++ if (ncores > NR_CPUS) { ++ printk(KERN_WARNING ++ "Realview: no. of cores (%d) greater than configured " ++ "maximum of %d - clipping\n", ++ ncores, NR_CPUS); ++ ncores = NR_CPUS; ++ } ++ ++ for (i = 0; i < ncores; i++) ++ set_cpu_possible(i, true); ++} ++ ++static void __init hi3531d_smp_init_cpus(void) ++{ ++ void __iomem *scu_base = scu_base_addr(); ++ unsigned int i, ncores; ++ ++ ncores = scu_base ? scu_get_core_count(scu_base) : 1; ++ ++ /* sanity check */ ++ if (ncores > NR_CPUS) { ++ printk(KERN_WARNING ++ "Realview: no. of cores (%d) greater than configured " ++ "maximum of %d - clipping\n", ++ ncores, NR_CPUS); ++ ncores = NR_CPUS; ++ } ++ ++ for (i = 0; i < ncores; i++) ++ set_cpu_possible(i, true); ++} ++ ++ ++ ++static void __init hi3521d_smp_init_cpus(void) ++{ ++ unsigned int i, ncores, l2ctlr; ++ ++ asm volatile("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr)); ++ ncores = ((l2ctlr >> 24) & 0x3) + 1; ++ ++ /* sanity check */ ++ if (ncores > NR_CPUS) { ++ printk(KERN_WARNING ++ "Realview: no. of cores (%d) greater than configured " ++ "maximum of %d - clipping\n", ++ ncores, NR_CPUS); ++ ncores = NR_CPUS; ++ } ++ ++ for (i = 0; i < ncores; i++) ++ set_cpu_possible(i, true); ++} ++ ++struct smp_operations hi3536c_smp_ops __initdata = { ++ .smp_init_cpus = hi3536c_smp_init_cpus, ++ .smp_prepare_cpus = hi3536c_smp_prepare_cpus, ++ .smp_secondary_init = hi3536c_secondary_init, ++ .smp_boot_secondary = hi3536c_boot_secondary, ++#ifdef CONFIG_HOTPLUG_CPU ++ .cpu_die = hi3536c_cpu_die, ++ .cpu_kill = hi3536c_cpu_kill, ++#endif ++}; ++ ++struct smp_operations hi3531d_smp_ops __initdata = { ++ .smp_init_cpus = hi3531d_smp_init_cpus, ++ .smp_prepare_cpus = hi3531d_smp_prepare_cpus, ++ .smp_secondary_init = hi3531d_secondary_init, ++ .smp_boot_secondary = hi3531d_boot_secondary, ++#ifdef CONFIG_HOTPLUG_CPU ++ .cpu_die = hi3531d_cpu_die, ++ .cpu_kill = hi3531d_cpu_kill, ++#endif ++}; ++ ++struct smp_operations hi3521d_smp_ops __initdata = { ++ .smp_init_cpus = hi3521d_smp_init_cpus, ++ .smp_prepare_cpus = hi3521d_smp_prepare_cpus, ++ .smp_secondary_init = hi3521d_secondary_init, ++ .smp_boot_secondary = hi3521d_boot_secondary, ++#ifdef CONFIG_HOTPLUG_CPU ++ .cpu_die = hi3521d_cpu_die, ++ .cpu_kill = hi3521d_cpu_kill, ++#endif ++}; ++ ++struct smp_operations hi3519_smp_ops __initdata = { ++ .smp_prepare_cpus = hi3519_smp_prepare_cpus, ++ .smp_boot_secondary = hi3519_boot_secondary, ++ .smp_secondary_init = HI3519_secondary_init, ++#ifdef CONFIG_HOTPLUG_CPU ++ .cpu_die = hi3519_cpu_die, ++ .cpu_kill = hi3519_cpu_kill, ++#endif ++}; ++ ++struct smp_operations hi3516av200_smp_ops __initdata = { ++ .smp_prepare_cpus = hi3516av200_smp_prepare_cpus, ++ .smp_boot_secondary = hi3516av200_boot_secondary, ++ .smp_secondary_init = HI3516av200_secondary_init, ++#ifdef CONFIG_HOTPLUG_CPU ++ .cpu_die = hi3516av200_cpu_die, ++ .cpu_kill = hi3516av200_cpu_kill, ++#endif ++}; ++ ++struct smp_operations hi3559_smp_ops __initdata = { ++ .smp_prepare_cpus = hi3559_smp_prepare_cpus, ++ .smp_boot_secondary = hi3559_boot_secondary, ++ .smp_secondary_init = HI3559_secondary_init, ++#ifdef CONFIG_HOTPLUG_CPU ++ .cpu_die = hi3559_cpu_die, ++ .cpu_kill = hi3559_cpu_kill, ++#endif ++}; ++ ++ + CPU_METHOD_OF_DECLARE(hi3xxx_smp, "hisilicon,hi3620-smp", &hi3xxx_smp_ops); + CPU_METHOD_OF_DECLARE(hix5hd2_smp, "hisilicon,hix5hd2-smp", &hix5hd2_smp_ops); ++CPU_METHOD_OF_DECLARE(hi3519_smp, "hisilicon,hi3519-smp", &hi3519_smp_ops); ++CPU_METHOD_OF_DECLARE(hi3559_smp, "hisilicon,hi3559-smp", &hi3559_smp_ops); ++CPU_METHOD_OF_DECLARE(hi3516av200_smp, "hisilicon,hi3516av200-smp", &hi3516av200_smp_ops); ++CPU_METHOD_OF_DECLARE(hi3536c_smp, "hisilicon,hi3536c-smp", &hi3536c_smp_ops); ++CPU_METHOD_OF_DECLARE(hi3531d_smp, "hisilicon,hi3531d-smp", &hi3531d_smp_ops); ++CPU_METHOD_OF_DECLARE(hi3521d_smp, "hisilicon,hi3521d-smp", &hi3521d_smp_ops); +diff --git a/arch/arm/mach-hisi/pm.c b/arch/arm/mach-hisi/pm.c +new file mode 100644 +index 0000000..c4b8870 +--- /dev/null ++++ b/arch/arm/mach-hisi/pm.c +@@ -0,0 +1,288 @@ ++/* ++ * power mangager control for hisilicon soc ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++struct hibvt_pm_dev { ++ void __iomem *sys_ctrl_base; ++ void __iomem *time0_base; ++}; ++ ++static struct hibvt_pm_dev g_hibvt_pm; ++ ++void (*hi_power_off)(void) = NULL; ++EXPORT_SYMBOL(hi_power_off); ++ ++void hi_pm_power_off(void) ++{ ++ /* Disable interrupts first */ ++ local_irq_disable(); ++ local_fiq_disable(); ++ ++ /* Clean and invalidate caches */ ++ flush_cache_all(); ++ ++ /* Turn off caching */ ++ cpu_proc_fin(); ++ ++ /* Push out any further dirty data, and ensure cache is empty */ ++ flush_cache_all(); ++ ++ /* ++ * Now call the architecture specific reboot code. ++ */ ++ if(hi_power_off) ++ hi_power_off(); ++ /* ++ * Whoops - the architecture was unable to reboot. ++ * Tell the user! ++ */ ++ mdelay(1000); ++ ++ printk(KERN_EMERG "Poweroff failed -- System halted\n"); ++ ++ while (1) ++ ; ++} ++ ++/*hibernate methods*/ ++#ifdef CONFIG_HIBERNATION ++unsigned long saved_interrupt_mask[128]; ++unsigned long saved_cpu_target_mask[128]; ++ ++typedef struct __timer_register { ++ unsigned long timer_load; ++ unsigned long timer_value; ++ unsigned long timer_ctrl; ++ unsigned long timer_bgload; ++} timer_register; ++ ++static timer_register timer0[2]; ++static int timer_init_value; ++static int save_timer0(void) ++{ ++ void __iomem *timer0_base_addr = g_hibvt_pm.time0_base; ++ ++ timer_init_value = readl(g_hibvt_pm.sys_ctrl_base); ++ /*protect timer0_0*/ ++ timer0[0].timer_load = readl(timer0_base_addr + TIMER_LOAD); ++ timer0[0].timer_value = readl(timer0_base_addr + TIMER_VALUE); ++ timer0[0].timer_ctrl = readl(timer0_base_addr + TIMER_CTRL); ++ timer0[0].timer_bgload = readl(timer0_base_addr + TIMER_BGLOAD); ++ /*disable timer0_0 */ ++ writel(0, timer0_base_addr + TIMER_CTRL); ++ ++ /*protect timer0_1*/ ++ timer0[1].timer_load = readl(timer0_base_addr + 0x20 + TIMER_LOAD); ++ timer0[1].timer_value = readl(timer0_base_addr + 0x20 + TIMER_VALUE); ++ timer0[1].timer_ctrl = readl(timer0_base_addr + 0x20 + TIMER_CTRL); ++ timer0[1].timer_bgload = readl(timer0_base_addr + 0x20 + TIMER_BGLOAD); ++ /*disable timer0_1 */ ++ writel(0, timer0_base_addr + 0x20 + TIMER_CTRL); ++ ++ return 0; ++} ++ ++ ++static int restore_timer0(void) ++{ ++ void __iomem *timer0_base_addr = g_hibvt_pm.time0_base; ++ ++ writel(timer_init_value, g_hibvt_pm.sys_ctrl_base); ++ /* restore timer0_0 */ ++ writel(0, timer0_base_addr + TIMER_CTRL); ++ writel(1, timer0_base_addr + TIMER_INTCLR); ++ ++ writel(timer0[0].timer_value, timer0_base_addr + TIMER_LOAD); ++ writel(timer0[0].timer_ctrl, timer0_base_addr + TIMER_CTRL); ++ writel(timer0[0].timer_bgload, timer0_base_addr + TIMER_BGLOAD); ++ ++ /* restore timer0_1 */ ++ writel(0, timer0_base_addr + 0x20 + TIMER_CTRL); ++ writel(1, timer0_base_addr + 0x20 + TIMER_INTCLR); ++ ++ writel(timer0[1].timer_value, timer0_base_addr + 0x20 + TIMER_LOAD); ++ writel(timer0[1].timer_ctrl, timer0_base_addr + 0x20 + TIMER_CTRL); ++ writel(timer0[1].timer_bgload, timer0_base_addr + 0x20 + TIMER_BGLOAD); ++ ++ return 0; ++} ++static int hi_hiber_begin(void) ++{ ++ return 0; ++} ++ ++static void hi_hiber_end(void) ++{ ++} ++ ++static int hi_hiber_pre_snapshot(void) ++{ ++ save_timer0(); ++ return 0; ++} ++ ++static void hi_hiber_finish(void) ++{ ++ restore_timer0(); ++} ++ ++static int hi_hiber_prepare(void) ++{ ++ return 0; ++} ++ ++static void hi_hiber_leave(void) ++{ ++} ++ ++static int hi_hiber_enter(void) ++{ ++#ifdef CONFIG_DEFAULT_MTD ++ hi_pm_power_off(); ++#else ++ kernel_restart(NULL); ++#endif ++ return 0; ++} ++ ++static int hi_hiber_restore(void) ++{ ++ return 0; ++} ++ ++static void hi_hiber_restore_cleanup(void) ++{ ++} ++ ++static void hi_hiber_recover(void) ++{ ++} ++ ++struct platform_hibernation_ops hi_hibernation_ops = { ++ .begin = hi_hiber_begin, ++ .end = hi_hiber_end, ++ .pre_snapshot = hi_hiber_pre_snapshot, ++ .finish = hi_hiber_finish, ++ .prepare = hi_hiber_prepare, ++ .enter = hi_hiber_enter, ++ .leave = hi_hiber_leave, ++ .pre_restore = hi_hiber_restore, ++ .restore_cleanup = hi_hiber_restore_cleanup, ++ .recover = hi_hiber_recover, ++}; ++#endif /* CONFIG_HIBERNATION */ ++ ++ ++/*pm methods*/ ++static int hi_pm_enter(suspend_state_t state) ++{ ++ return 0; ++} ++ ++int hi_pm_valid(suspend_state_t state) ++{ ++ return 1; ++} ++ ++static const struct platform_suspend_ops hi_pm_ops = { ++ .enter = hi_pm_enter, ++ .valid = hi_pm_valid, ++}; ++ ++static int hi_pm_probe(struct platform_device *pdev) ++{ ++ g_hibvt_pm.sys_ctrl_base = of_iomap(pdev->dev.of_node, 0); ++ if (!g_hibvt_pm.sys_ctrl_base) { ++ pr_err("%s: failed to map system controller registers\n", ++ __func__); ++ return -ENOMEM; ++ } ++ ++ g_hibvt_pm.time0_base = of_iomap(pdev->dev.of_node, 1); ++ if (!g_hibvt_pm.time0_base) { ++ pr_err("%s: failed to map timer registers\n", __func__); ++ iounmap(g_hibvt_pm.sys_ctrl_base); ++ return -ENOMEM; ++ } ++ ++ pm_power_off = hi_pm_power_off; ++ ++ suspend_set_ops(&hi_pm_ops); ++ ++#ifdef CONFIG_HIBERNATION ++ /* registering hibernation call backs */ ++ hibernation_set_ops(&hi_hibernation_ops); ++#endif ++ return 0; ++} ++ ++static const struct of_device_id hi_pm_match_table[] = { ++ { .compatible = "hisilicon,hibvt-pm" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, hi_pm_match_table); ++ ++static struct platform_driver hi_pm_driver = { ++ .probe = hi_pm_probe, ++ .driver = { ++ .name = "hibvt-pm", ++ .of_match_table = hi_pm_match_table, ++ }, ++}; ++ ++static int __init hi_pm_init(void) ++{ ++ return platform_driver_register(&hi_pm_driver); ++} ++module_init(hi_pm_init); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("HiSilicon BVT PM Driver"); +diff --git a/arch/arm/mach-hisi/pmc_hi3516av200.c b/arch/arm/mach-hisi/pmc_hi3516av200.c +new file mode 100644 +index 0000000..df36e44 +--- /dev/null ++++ b/arch/arm/mach-hisi/pmc_hi3516av200.c +@@ -0,0 +1,207 @@ ++/* ++ * power mangager control for hisilicon hi3516av200 soc ++ * ++ * Copyright (c) 2015 HiSilicon Technologies Co., Ltd. ++ * Authors: zengtao@hisilicon.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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define PERI_PMC77 (0x134) ++#define PERI_PMC79 (0x13c) ++#define PERI_PMC85 (0x154) ++ ++static void __iomem *pmc_base; ++static u32 pmc_phys_addr; ++ ++#define PMC_ADDRESS(reg) (pmc_base + reg) ++/* set bitfield of reg from start bit to end - 1 bit */ ++static void reg_bit_set(u32 reg, u32 start, u32 end, u32 val) ++{ ++ u32 regval, mask; ++ ++ regval = readl((void __iomem *)PMC_ADDRESS(reg)); ++ mask = ((0xffffffff << (32 - start)) >> (32 - start)) ++ | ((0xffffffff >> end) << end); ++ ++ regval &= mask; ++ regval |= (val << start); ++ ++ writel(regval, (void __iomem *)PMC_ADDRESS(reg)); ++} ++ ++/* get bitfield of reg from start bit to end - 1 bit */ ++static u32 reg_bit_get(u32 reg, u32 start, u32 end) ++{ ++ u32 regval; ++ ++ ++ regval = readl((void __iomem *)PMC_ADDRESS(reg)); ++ regval = (regval << (32 - end)) >> (32 - end); ++ regval = regval >> start; ++ ++ ++ return regval; ++} ++ ++void hi_pmc_power_up_done(void) ++{ ++ writel(0, (void __iomem *)PMC_ADDRESS(PERI_PMC85)); ++ writel(1, (void __iomem *)PMC_ADDRESS(PERI_PMC85)); ++ ++} ++ ++/* before power down set ac inactive */ ++void hi_pmc_set_ac_inactive(void) ++{ ++ reg_bit_set(PERI_PMC79, 8, 9, 1); ++} ++ ++/* after powerup clear ac inactive */ ++void hi_pmc_clear_ac_inactive(void) ++{ ++ reg_bit_set(PERI_PMC79, 8, 9, 0); ++} ++EXPORT_SYMBOL(hi_pmc_clear_ac_inactive); ++ ++/* call from assable context */ ++asmlinkage void __naked hi_pmc_clear_a17_ac(void) ++{ ++ asm volatile("\n" ++ "adr r2, 1f\n" ++ "ldmia r2, {r1, r3}\n" ++ "sub r0, r2, r1\n" ++ "ldr r2, [r0, r3]\n" ++ "ldr r0, ="__stringify(PERI_PMC79)"\n" ++ "add r0, r0, r2\n" ++ "ldr r1, [r0]\n" ++ "bic r1, #0x100\n" ++ "str r1, [r0]\n" ++ "mov r0, #0\n" ++ "bx lr\n" ++ ++ ".align 2\n" ++ "1: .word .\n" ++ " .word pmc_phys_addr\n" ++ ); ++ ++ unreachable(); ++} ++ ++static void hi_pmc_config(void) ++{ ++ /* enable pmc timeout */ ++ reg_bit_set(PERI_PMC77, 12, 13, 1); ++ /* enable pmc auto mode */ ++ reg_bit_set(PERI_PMC79, 0, 2, 0); ++ /* enable irq triger source power on */ ++ reg_bit_set(PERI_PMC79, 7, 8, 1); ++} ++ ++/* cpu hotplug powerup */ ++void hi_pmc_power_up(void) ++{ ++ u32 power_state; ++ ++ hi_pmc_config(); ++ ++ /* make sure it powerup state when power up */ ++ power_state = reg_bit_get(PERI_PMC79, 12, 16); ++ BUG_ON(power_state != 0); ++ ++ /* disable interrupt wakeup */ ++ reg_bit_set(PERI_PMC79, 5, 6, 0); ++ ++ /* power on */ ++ reg_bit_set(PERI_PMC79, 3, 4, 0); ++ reg_bit_set(PERI_PMC79, 3, 4, 1); ++} ++ ++/* cpu hotplug powerdown */ ++void hi_pmc_power_down(void) ++{ ++ u32 power_state; ++ ++ power_state = reg_bit_get(PERI_PMC79, 12, 16); ++ BUG_ON(power_state != 6); ++ ++ /* disable interrupt wakeup */ ++ reg_bit_set(PERI_PMC79, 5, 6, 0); ++ ++ /* power off */ ++ reg_bit_set(PERI_PMC79, 4, 5, 0); ++ reg_bit_set(PERI_PMC79, 4, 5, 1); ++} ++ ++/* cpuidle powerdown */ ++void hi_pmc_automode_power_down(void) ++{ ++ u32 power_state; ++ ++ power_state = reg_bit_get(PERI_PMC79, 12, 16); ++ BUG_ON(power_state != 6); ++ ++ /* enable interrupt wakeup */ ++ reg_bit_set(PERI_PMC79, 5, 6, 1); ++ ++ /* power off */ ++ reg_bit_set(PERI_PMC79, 4, 5, 0); ++ reg_bit_set(PERI_PMC79, 4, 5, 1); ++ ++} ++EXPORT_SYMBOL(hi_pmc_automode_power_down); ++ ++ ++/* enable timeout */ ++static int hi_pmc_init(void) ++{ ++ struct device_node *np; ++ struct resource res; ++ int ret = -ENODEV; ++ ++ np = of_find_compatible_node(NULL, NULL, "hisilicon,pmc"); ++ if (!np) ++ goto err; ++ ++ pmc_base = of_iomap(np, 0); ++ if (!pmc_base) { ++ pr_err("failed to map pmc base\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ ret = of_address_to_resource(np, 0, &res); ++ if (ret) { ++ pr_err("failed to get pmc base phys\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ pmc_phys_addr = res.start; ++ ++err: ++ return ret; ++} ++ ++early_initcall(hi_pmc_init); +diff --git a/arch/arm/mach-hisi/pmc_hi3519.c b/arch/arm/mach-hisi/pmc_hi3519.c +new file mode 100644 +index 0000000..17689f3 +--- /dev/null ++++ b/arch/arm/mach-hisi/pmc_hi3519.c +@@ -0,0 +1,281 @@ ++/* ++ * power mangager control for hisilicon hi3519 soc ++ * ++ * Copyright (c) 2015 HiSilicon Technologies Co., Ltd. ++ * Authors: zengtao@hisilicon.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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define PERI_PMC77 (0x134) ++#define PERI_PMC79 (0x13c) ++#define PERI_PMC85 (0x154) ++ ++static void __iomem *pmc_base; ++static u32 pmc_phys_addr; ++ ++#define PMC_ADDRESS(reg) (pmc_base + reg) ++/* set bitfield of reg from start bit to end - 1 bit */ ++static void reg_bit_set(u32 reg, u32 start, u32 end, u32 val) ++{ ++ u32 regval, mask; ++ ++ regval = readl((void __iomem *)PMC_ADDRESS(reg)); ++ mask = ((0xffffffff << (32 - start)) >> (32 - start)) ++ | ((0xffffffff >> end) << end); ++ ++ regval &= mask; ++ regval |= (val << start); ++ ++ writel(regval, (void __iomem *)PMC_ADDRESS(reg)); ++} ++ ++/* get bitfield of reg from start bit to end - 1 bit */ ++static u32 reg_bit_get(u32 reg, u32 start, u32 end) ++{ ++ u32 regval; ++ ++ regval = readl((void __iomem *)PMC_ADDRESS(reg)); ++ regval = (regval << (32 - end)) >> (32 - end); ++ regval = regval >> start; ++ ++ return regval; ++} ++ ++void hi_pmc_power_up_done(void) ++{ ++ writel(0, (void __iomem *)PMC_ADDRESS(PERI_PMC85)); ++ writel(1, (void __iomem *)PMC_ADDRESS(PERI_PMC85)); ++ ++} ++ ++/* before power down set ac inactive */ ++void hi_pmc_set_ac_inactive(void) ++{ ++ reg_bit_set(PERI_PMC79, 8, 9, 1); ++} ++ ++/* after powerup clear ac inactive */ ++void hi_pmc_clear_ac_inactive(void) ++{ ++ reg_bit_set(PERI_PMC79, 8, 9, 0); ++} ++EXPORT_SYMBOL(hi_pmc_clear_ac_inactive); ++ ++/* ++ * call from assable context, same as the ++ * hi_pmc_clear_ac_inactive ++ */ ++asmlinkage void __naked hi_pmc_clear_a17_ac(void) ++{ ++ asm volatile("\n" ++ "adr r2, 1f\n" ++ "ldmia r2, {r1, r3}\n" ++ "sub r0, r2, r1\n" ++ "ldr r2, [r0, r3]\n" ++ "ldr r0, ="__stringify(PERI_PMC79)"\n" ++ "add r0, r0, r2\n" ++ "ldr r1, [r0]\n" ++ "bic r1, #0x100\n" ++ "str r1, [r0]\n" ++ "mov r0, #0\n" ++ "bx lr\n" ++ ++ ".align 2\n" ++ "1: .word .\n" ++ " .word pmc_phys_addr\n" ++ ); ++ ++ unreachable(); ++} ++ ++/* cpu hotplug powerup */ ++void hi_pmc_power_up(void) ++{ ++ u32 power_state; ++ ++ writel(readl((void *)IO_ADDRESS(0x12030004)) | 0x40000000, ++ (void *)IO_ADDRESS(0x12030004)); ++ ++ reg_bit_set(PERI_PMC79, 0, 2, 0x2); ++ ++ writel(readl((void *)IO_ADDRESS(CRG_REG_BASE + REG_PERI_CRG10)) ++ | (1<<21), ++ (void *)IO_ADDRESS(CRG_REG_BASE + REG_PERI_CRG10)); ++ ++ reg_bit_set(PERI_PMC77, 1, 2, 0x0); ++ ++ mdelay(1); ++ power_state = reg_bit_get(PERI_PMC77, 2, 3); ++ while (power_state) ++ power_state = reg_bit_get(PERI_PMC77, 2, 3); ++ ++ reg_bit_set(PERI_PMC77, 0, 1, 0x0); ++ writel(readl((void *)IO_ADDRESS(CRG_REG_BASE + REG_PERI_CRG10)) ++ & 0xfff7ffff, ++ (void *)IO_ADDRESS(CRG_REG_BASE + REG_PERI_CRG10)); ++ ++ reg_bit_set(PERI_PMC77, 5, 6, 0x1); ++ mdelay(1); ++ power_state = reg_bit_get(PERI_PMC77, 6, 7); ++ while (power_state != 1) ++ power_state = reg_bit_get(PERI_PMC77, 6, 7); ++ ++ writel(readl((void *)IO_ADDRESS(CRG_REG_BASE + REG_PERI_CRG10)) ++ & 0xfffffffd, ++ (void *)IO_ADDRESS(CRG_REG_BASE + REG_PERI_CRG10)); ++} ++ ++void hi_pmc_kill_cpu(unsigned int cpu) ++{ ++ unsigned int state; ++ ++ while (1) { ++ state = readl((void *)IO_ADDRESS(0x12030004)) & 0x40000000; ++ if (!state) ++ break; ++ } ++ ++ while (1) { ++ state = reg_bit_get(PERI_PMC77, 7, 9); ++ if (state == 3) ++ break; ++ } ++ ++ while (1) { ++ state = reg_bit_get(PERI_PMC77, 3, 5); ++ if (state == 0) ++ break; ++ } ++ ++ reg_bit_set(PERI_PMC77, 5, 6, 0x0); ++ ++ while (1) { ++ state = reg_bit_get(PERI_PMC77, 6, 7); ++ if (state == 0) ++ break; ++ } ++ ++ reg_bit_set(PERI_PMC77, 0, 1, 0x1); ++ ++ writel(readl((void *)IO_ADDRESS(CRG_REG_BASE + REG_PERI_CRG10)) ++ | (1<<19), ++ (void *)IO_ADDRESS(CRG_REG_BASE + REG_PERI_CRG10)); ++ writel(readl((void *)IO_ADDRESS(CRG_REG_BASE + REG_PERI_CRG10)) ++ & 0xffdfffff, ++ (void *)IO_ADDRESS(CRG_REG_BASE + REG_PERI_CRG10)); ++ ++ reg_bit_set(PERI_PMC77, 1, 2, 0x1); ++ ++ while (1) { ++ state = reg_bit_get(PERI_PMC77, 2, 3); ++ if (state == 1) ++ break; ++ } ++} ++ ++/* cpu hotplug powerdown */ ++void hi_pmc_power_down(void) ++{ ++#if 0 ++ u32 power_state; ++ ++ power_state = reg_bit_get(PERI_PMC79, 12, 16); ++ BUG_ON(power_state != 6); ++ ++ /* disable interrupt wakeup */ ++ reg_bit_set(PERI_PMC79, 5, 6, 0); ++ ++ /* power off */ ++ reg_bit_set(PERI_PMC79, 4, 5, 0); ++ reg_bit_set(PERI_PMC79, 4, 5, 1); ++#endif ++ reg_bit_set(PERI_PMC79, 0, 2, 2); ++ writel(readl((void *)IO_ADDRESS(0x12030004)) & 0xbfffffff, ++ (void *)IO_ADDRESS(0x12030004)); ++ ++} ++ ++/* cpuidle powerdown */ ++void hi_pmc_automode_power_down(void) ++{ ++ u32 power_state; ++ ++ power_state = reg_bit_get(PERI_PMC79, 12, 16); ++ BUG_ON(power_state != 6); ++ ++ /* enable interrupt wakeup */ ++ reg_bit_set(PERI_PMC79, 5, 6, 1); ++ ++ /* power off */ ++ reg_bit_set(PERI_PMC79, 4, 5, 0); ++ reg_bit_set(PERI_PMC79, 4, 5, 1); ++ ++} ++EXPORT_SYMBOL(hi_pmc_automode_power_down); ++ ++static void hi_pmc_config(void) ++{ ++ /* enable pmc timeout */ ++ reg_bit_set(PERI_PMC77, 12, 13, 1); ++ /* enable pmc auto mode */ ++ reg_bit_set(PERI_PMC79, 0, 2, 0); ++ /* enable irq triger source power on */ ++ reg_bit_set(PERI_PMC79, 7, 8, 1); ++} ++ ++/* enable timeout */ ++static int hi_pmc_init(void) ++{ ++ struct device_node *np; ++ struct resource res; ++ int ret = -ENODEV; ++ ++ np = of_find_compatible_node(NULL, NULL, "hisilicon,pmc"); ++ if (!np) ++ goto err; ++ ++ pmc_base = of_iomap(np, 0); ++ if (!pmc_base) { ++ pr_err("failed to map pmc base\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ ret = of_address_to_resource(np, 0, &res); ++ if (ret) { ++ pr_err("failed to get pmc base phys\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ pmc_phys_addr = res.start; ++ ++ hi_pmc_config(); ++err: ++ return ret; ++} ++ ++early_initcall(hi_pmc_init); +diff --git a/arch/arm/mach-hisi/pmc_hi3519v101.c b/arch/arm/mach-hisi/pmc_hi3519v101.c +new file mode 100644 +index 0000000..e652fb9 +--- /dev/null ++++ b/arch/arm/mach-hisi/pmc_hi3519v101.c +@@ -0,0 +1,207 @@ ++/* ++ * power mangager control for hisilicon hi3519 soc ++ * ++ * Copyright (c) 2015 HiSilicon Technologies Co., Ltd. ++ * Authors: zengtao@hisilicon.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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define PERI_PMC77 (0x134) ++#define PERI_PMC79 (0x13c) ++#define PERI_PMC85 (0x154) ++ ++static void __iomem *pmc_base; ++static u32 pmc_phys_addr; ++ ++#define PMC_ADDRESS(reg) (pmc_base + reg) ++/* set bitfield of reg from start bit to end - 1 bit */ ++static void reg_bit_set(u32 reg, u32 start, u32 end, u32 val) ++{ ++ u32 regval, mask; ++ ++ regval = readl((void __iomem *)PMC_ADDRESS(reg)); ++ mask = ((0xffffffff << (32 - start)) >> (32 - start)) ++ | ((0xffffffff >> end) << end); ++ ++ regval &= mask; ++ regval |= (val << start); ++ ++ writel(regval, (void __iomem *)PMC_ADDRESS(reg)); ++} ++ ++/* get bitfield of reg from start bit to end - 1 bit */ ++static u32 reg_bit_get(u32 reg, u32 start, u32 end) ++{ ++ u32 regval; ++ ++ ++ regval = readl((void __iomem *)PMC_ADDRESS(reg)); ++ regval = (regval << (32 - end)) >> (32 - end); ++ regval = regval >> start; ++ ++ ++ return regval; ++} ++ ++void hi_pmc_power_up_done(void) ++{ ++ writel(0, (void __iomem *)PMC_ADDRESS(PERI_PMC85)); ++ writel(1, (void __iomem *)PMC_ADDRESS(PERI_PMC85)); ++ ++} ++ ++/* before power down set ac inactive */ ++void hi_pmc_set_ac_inactive(void) ++{ ++ reg_bit_set(PERI_PMC79, 8, 9, 1); ++} ++ ++/* after powerup clear ac inactive */ ++void hi_pmc_clear_ac_inactive(void) ++{ ++ reg_bit_set(PERI_PMC79, 8, 9, 0); ++} ++EXPORT_SYMBOL(hi_pmc_clear_ac_inactive); ++ ++/* call from assable context */ ++asmlinkage void __naked hi_pmc_clear_a17_ac(void) ++{ ++ asm volatile("\n" ++ "adr r2, 1f\n" ++ "ldmia r2, {r1, r3}\n" ++ "sub r0, r2, r1\n" ++ "ldr r2, [r0, r3]\n" ++ "ldr r0, ="__stringify(PERI_PMC79)"\n" ++ "add r0, r0, r2\n" ++ "ldr r1, [r0]\n" ++ "bic r1, #0x100\n" ++ "str r1, [r0]\n" ++ "mov r0, #0\n" ++ "bx lr\n" ++ ++ ".align 2\n" ++ "1: .word .\n" ++ " .word pmc_phys_addr\n" ++ ); ++ ++ unreachable(); ++} ++ ++static void hi_pmc_config(void) ++{ ++ /* enable pmc timeout */ ++ reg_bit_set(PERI_PMC77, 12, 13, 1); ++ /* enable pmc auto mode */ ++ reg_bit_set(PERI_PMC79, 0, 2, 0); ++ /* enable irq triger source power on */ ++ reg_bit_set(PERI_PMC79, 7, 8, 1); ++} ++ ++/* cpu hotplug powerup */ ++void hi_pmc_power_up(void) ++{ ++ u32 power_state; ++ ++ hi_pmc_config(); ++ ++ /* make sure it powerup state when power up */ ++ power_state = reg_bit_get(PERI_PMC79, 12, 16); ++ BUG_ON(power_state != 0); ++ ++ /* disable interrupt wakeup */ ++ reg_bit_set(PERI_PMC79, 5, 6, 0); ++ ++ /* power on */ ++ reg_bit_set(PERI_PMC79, 3, 4, 0); ++ reg_bit_set(PERI_PMC79, 3, 4, 1); ++} ++ ++/* cpu hotplug powerdown */ ++void hi_pmc_power_down(void) ++{ ++ u32 power_state; ++ ++ power_state = reg_bit_get(PERI_PMC79, 12, 16); ++ BUG_ON(power_state != 6); ++ ++ /* disable interrupt wakeup */ ++ reg_bit_set(PERI_PMC79, 5, 6, 0); ++ ++ /* power off */ ++ reg_bit_set(PERI_PMC79, 4, 5, 0); ++ reg_bit_set(PERI_PMC79, 4, 5, 1); ++} ++ ++/* cpuidle powerdown */ ++void hi_pmc_automode_power_down(void) ++{ ++ u32 power_state; ++ ++ power_state = reg_bit_get(PERI_PMC79, 12, 16); ++ BUG_ON(power_state != 6); ++ ++ /* enable interrupt wakeup */ ++ reg_bit_set(PERI_PMC79, 5, 6, 1); ++ ++ /* power off */ ++ reg_bit_set(PERI_PMC79, 4, 5, 0); ++ reg_bit_set(PERI_PMC79, 4, 5, 1); ++ ++} ++EXPORT_SYMBOL(hi_pmc_automode_power_down); ++ ++ ++/* enable timeout */ ++static int hi_pmc_init(void) ++{ ++ struct device_node *np; ++ struct resource res; ++ int ret = -ENODEV; ++ ++ np = of_find_compatible_node(NULL, NULL, "hisilicon,pmc"); ++ if (!np) ++ goto err; ++ ++ pmc_base = of_iomap(np, 0); ++ if (!pmc_base) { ++ pr_err("failed to map pmc base\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ ret = of_address_to_resource(np, 0, &res); ++ if (ret) { ++ pr_err("failed to get pmc base phys\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ pmc_phys_addr = res.start; ++ ++err: ++ return ret; ++} ++ ++early_initcall(hi_pmc_init); +diff --git a/arch/arm/mach-hisi/pmc_hi3521d.c b/arch/arm/mach-hisi/pmc_hi3521d.c +new file mode 100644 +index 0000000..54b9294 +--- /dev/null ++++ b/arch/arm/mach-hisi/pmc_hi3521d.c +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++ ++asmlinkage void __naked cci_enable_port_for_self(void) ++{ ++} ++ ++asmlinkage void __naked hi_pmc_clear_a17_ac(void) ++{ ++} ++ ++void hi_pmc_power_up(void) ++{ ++} ++ ++void hi_pmc_set_ac_inactive(void) ++{ ++} ++ ++void hi_pmc_power_down(void) ++{ ++} ++ +diff --git a/arch/arm/mach-hisi/pmc_hi3531d.c b/arch/arm/mach-hisi/pmc_hi3531d.c +new file mode 100644 +index 0000000..54b9294 +--- /dev/null ++++ b/arch/arm/mach-hisi/pmc_hi3531d.c +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++ ++asmlinkage void __naked cci_enable_port_for_self(void) ++{ ++} ++ ++asmlinkage void __naked hi_pmc_clear_a17_ac(void) ++{ ++} ++ ++void hi_pmc_power_up(void) ++{ ++} ++ ++void hi_pmc_set_ac_inactive(void) ++{ ++} ++ ++void hi_pmc_power_down(void) ++{ ++} ++ +diff --git a/arch/arm/mach-hisi/pmc_hi3536c.c b/arch/arm/mach-hisi/pmc_hi3536c.c +new file mode 100644 +index 0000000..54b9294 +--- /dev/null ++++ b/arch/arm/mach-hisi/pmc_hi3536c.c +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (c) 2015-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++ ++asmlinkage void __naked cci_enable_port_for_self(void) ++{ ++} ++ ++asmlinkage void __naked hi_pmc_clear_a17_ac(void) ++{ ++} ++ ++void hi_pmc_power_up(void) ++{ ++} ++ ++void hi_pmc_set_ac_inactive(void) ++{ ++} ++ ++void hi_pmc_power_down(void) ++{ ++} ++ +diff --git a/arch/arm/mach-hisi/pmc_hi3559.c b/arch/arm/mach-hisi/pmc_hi3559.c +new file mode 100644 +index 0000000..7767ef2 +--- /dev/null ++++ b/arch/arm/mach-hisi/pmc_hi3559.c +@@ -0,0 +1,207 @@ ++/* ++ * power mangager control for hisilicon hi3559 soc ++ * ++ * Copyright (c) 2015 HiSilicon Technologies Co., Ltd. ++ * Authors: zengtao@hisilicon.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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define PERI_PMC77 (0x134) ++#define PERI_PMC79 (0x13c) ++#define PERI_PMC85 (0x154) ++ ++static void __iomem *pmc_base; ++static u32 pmc_phys_addr; ++ ++#define PMC_ADDRESS(reg) (pmc_base + reg) ++/* set bitfield of reg from start bit to end - 1 bit */ ++static void reg_bit_set(u32 reg, u32 start, u32 end, u32 val) ++{ ++ u32 regval, mask; ++ ++ regval = readl((void __iomem *)PMC_ADDRESS(reg)); ++ mask = ((0xffffffff << (32 - start)) >> (32 - start)) ++ | ((0xffffffff >> end) << end); ++ ++ regval &= mask; ++ regval |= (val << start); ++ ++ writel(regval, (void __iomem *)PMC_ADDRESS(reg)); ++} ++ ++/* get bitfield of reg from start bit to end - 1 bit */ ++static u32 reg_bit_get(u32 reg, u32 start, u32 end) ++{ ++ u32 regval; ++ ++ ++ regval = readl((void __iomem *)PMC_ADDRESS(reg)); ++ regval = (regval << (32 - end)) >> (32 - end); ++ regval = regval >> start; ++ ++ ++ return regval; ++} ++ ++void hi_pmc_power_up_done(void) ++{ ++ writel(0, (void __iomem *)PMC_ADDRESS(PERI_PMC85)); ++ writel(1, (void __iomem *)PMC_ADDRESS(PERI_PMC85)); ++ ++} ++ ++/* before power down set ac inactive */ ++void hi_pmc_set_ac_inactive(void) ++{ ++ reg_bit_set(PERI_PMC79, 8, 9, 1); ++} ++ ++/* after powerup clear ac inactive */ ++void hi_pmc_clear_ac_inactive(void) ++{ ++ reg_bit_set(PERI_PMC79, 8, 9, 0); ++} ++EXPORT_SYMBOL(hi_pmc_clear_ac_inactive); ++ ++/* call from assable context */ ++asmlinkage void __naked hi_pmc_clear_a17_ac(void) ++{ ++ asm volatile("\n" ++ "adr r2, 1f\n" ++ "ldmia r2, {r1, r3}\n" ++ "sub r0, r2, r1\n" ++ "ldr r2, [r0, r3]\n" ++ "ldr r0, ="__stringify(PERI_PMC79)"\n" ++ "add r0, r0, r2\n" ++ "ldr r1, [r0]\n" ++ "bic r1, #0x100\n" ++ "str r1, [r0]\n" ++ "mov r0, #0\n" ++ "bx lr\n" ++ ++ ".align 2\n" ++ "1: .word .\n" ++ " .word pmc_phys_addr\n" ++ ); ++ ++ unreachable(); ++} ++ ++static void hi_pmc_config(void) ++{ ++ /* enable pmc timeout */ ++ reg_bit_set(PERI_PMC77, 12, 13, 1); ++ /* enable pmc auto mode */ ++ reg_bit_set(PERI_PMC79, 0, 2, 0); ++ /* enable irq triger source power on */ ++ reg_bit_set(PERI_PMC79, 7, 8, 1); ++} ++ ++/* cpu hotplug powerup */ ++void hi_pmc_power_up(void) ++{ ++ u32 power_state; ++ ++ hi_pmc_config(); ++ ++ /* make sure it powerup state when power up */ ++ power_state = reg_bit_get(PERI_PMC79, 12, 16); ++ BUG_ON(power_state != 0); ++ ++ /* disable interrupt wakeup */ ++ reg_bit_set(PERI_PMC79, 5, 6, 0); ++ ++ /* power on */ ++ reg_bit_set(PERI_PMC79, 3, 4, 0); ++ reg_bit_set(PERI_PMC79, 3, 4, 1); ++} ++ ++/* cpu hotplug powerdown */ ++void hi_pmc_power_down(void) ++{ ++ u32 power_state; ++ ++ power_state = reg_bit_get(PERI_PMC79, 12, 16); ++ BUG_ON(power_state != 6); ++ ++ /* disable interrupt wakeup */ ++ reg_bit_set(PERI_PMC79, 5, 6, 0); ++ ++ /* power off */ ++ reg_bit_set(PERI_PMC79, 4, 5, 0); ++ reg_bit_set(PERI_PMC79, 4, 5, 1); ++} ++ ++/* cpuidle powerdown */ ++void hi_pmc_automode_power_down(void) ++{ ++ u32 power_state; ++ ++ power_state = reg_bit_get(PERI_PMC79, 12, 16); ++ BUG_ON(power_state != 6); ++ ++ /* enable interrupt wakeup */ ++ reg_bit_set(PERI_PMC79, 5, 6, 1); ++ ++ /* power off */ ++ reg_bit_set(PERI_PMC79, 4, 5, 0); ++ reg_bit_set(PERI_PMC79, 4, 5, 1); ++ ++} ++EXPORT_SYMBOL(hi_pmc_automode_power_down); ++ ++ ++/* enable timeout */ ++static int hi_pmc_init(void) ++{ ++ struct device_node *np; ++ struct resource res; ++ int ret = -ENODEV; ++ ++ np = of_find_compatible_node(NULL, NULL, "hisilicon,pmc"); ++ if (!np) ++ goto err; ++ ++ pmc_base = of_iomap(np, 0); ++ if (!pmc_base) { ++ pr_err("failed to map pmc base\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ ret = of_address_to_resource(np, 0, &res); ++ if (ret) { ++ pr_err("failed to get pmc base phys\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ pmc_phys_addr = res.start; ++ ++err: ++ return ret; ++} ++ ++early_initcall(hi_pmc_init); +diff --git a/arch/arm/mach-hisi/pwr_hi3559.c b/arch/arm/mach-hisi/pwr_hi3559.c +new file mode 100644 +index 0000000..38a07fb +--- /dev/null ++++ b/arch/arm/mach-hisi/pwr_hi3559.c +@@ -0,0 +1,81 @@ ++/* ++ * The power mangager control for hisilicon soc ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define PWR_CTRL0 (0x34) ++ ++static void __iomem *pwr_base; ++ ++#define PWR_ADDRESS(reg) (pwr_base + reg) ++/* set bitfield of reg from start bit to end - 1 bit */ ++static void reg_bit_set(u32 reg, u32 start, u32 end, u32 val) ++{ ++ u32 regval, mask; ++ ++ regval = readl((void __iomem *)PWR_ADDRESS(reg)); ++ mask = ((0xffffffff << (32 - start)) >> (32 - start)) ++ | ((0xffffffff >> end) << end); ++ ++ regval &= mask; ++ regval |= (val << start); ++ ++ writel(regval, (void __iomem *)PWR_ADDRESS(reg)); ++} ++ ++/* power off interface */ ++void hi_pwr_off(void) ++{ ++ /* set pwr_off_ctrl to 0x1 not 0x2 */ ++ /* if set to 0x2, must wait about 2 seconds when power on */ ++ reg_bit_set(PWR_CTRL0, 0, 1, 0x1); ++} ++ ++extern void (*hi_power_off)(void); ++static int hi_pwr_init(void) ++{ ++ struct device_node *np; ++ int ret = 0; ++ ++ np = of_find_compatible_node(NULL, NULL, "hisilicon,hi_pwr"); ++ if (!np) { ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ pwr_base = of_iomap(np, 0); ++ if (!pwr_base) { ++ pr_err("failed to map pwr base\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ hi_power_off = hi_pwr_off; ++err: ++ return ret; ++} ++early_initcall(hi_pwr_init); ++ +diff --git a/arch/arm/mach-hisi/swsusp.S b/arch/arm/mach-hisi/swsusp.S +new file mode 100644 +index 0000000..03983bc +--- /dev/null ++++ b/arch/arm/mach-hisi/swsusp.S +@@ -0,0 +1,306 @@ ++/* ++ * Hibernation support specific for ARM ++ * ++ * Copyright (C) 2010 Nokia Corporation ++ * Copyright (C) 2010 Texas Instruments, Inc. ++ * Copyright (C) 2006 Rafael J. Wysocki ++ * ++ * Contact: Hiroshi DOYU ++ * ++ * License terms: GNU General Public License (GPL) version 2 ++ */ ++ ++ ++#include ++.text ++ ++#define LOCAL_WORD(x) \ ++ .data ; \ ++ .p2align 2 ; \ ++ .type x, #object ; \ ++ .size x, 4 ; \ ++x: ; \ ++ .long 1 ++ ++#define WORD_ADDR(x) \ ++ .align 2 ; \ ++.L##x: ; \ ++ .word x ++ ++/*user*/ ++LOCAL_WORD(saved_context_r0) ++LOCAL_WORD(saved_context_r1) ++LOCAL_WORD(saved_context_r2) ++LOCAL_WORD(saved_context_r3) ++LOCAL_WORD(saved_context_r4) ++LOCAL_WORD(saved_context_r5) ++LOCAL_WORD(saved_context_r6) ++LOCAL_WORD(saved_context_r7) ++LOCAL_WORD(saved_context_r8) ++LOCAL_WORD(saved_context_r9) ++LOCAL_WORD(saved_context_r10) ++LOCAL_WORD(saved_context_r11) ++LOCAL_WORD(saved_context_r12) ++LOCAL_WORD(saved_context_r13) ++LOCAL_WORD(saved_context_r14) ++LOCAL_WORD(saved_cpsr) ++ ++LOCAL_WORD(saved_context_r8_fiq) ++LOCAL_WORD(saved_context_r9_fiq) ++LOCAL_WORD(saved_context_r10_fiq) ++LOCAL_WORD(saved_context_r11_fiq) ++LOCAL_WORD(saved_context_r12_fiq) ++LOCAL_WORD(saved_context_r13_fiq) ++LOCAL_WORD(saved_context_r14_fiq) ++LOCAL_WORD(saved_spsr_fiq) ++ ++LOCAL_WORD(saved_context_r13_irq) ++LOCAL_WORD(saved_context_r14_irq) ++LOCAL_WORD(saved_spsr_irq) ++ ++LOCAL_WORD(saved_context_r13_svc) ++LOCAL_WORD(saved_context_r14_svc) ++LOCAL_WORD(saved_spsr_svc) ++ ++LOCAL_WORD(saved_context_r13_abt) ++LOCAL_WORD(saved_context_r14_abt) ++LOCAL_WORD(saved_spsr_abt) ++ ++LOCAL_WORD(saved_context_r13_und) ++LOCAL_WORD(saved_context_r14_und) ++LOCAL_WORD(saved_spsr_und) ++ ++#define CHANGE_MODE(x) \ ++ mov r1, r0 ; \ ++ bic r1, r1, #0x1f ; \ ++ orr r1, r1, #0x##x ; \ ++ msr cpsr_c, r1 ++ ++ENTRY(swsusp_arch_suspend) ++ /* ++ * Save current program status register ++ */ ++ ldr r3, .Lsaved_cpsr ++ mrs r0, cpsr ++ str r0, [r3] ++ ++ CHANGE_MODE(1f) /* Change to system(user) mode*/ ++ ldr r3, .Lsaved_context_r0 ++ stmia r3, {r0-r14} ++ ++ CHANGE_MODE(11) /* change to fiq mode */ ++ /* save nonvolatile int register */ ++ ldr r3, .Lsaved_context_r8_fiq ++ stmia r3, {r8-r14} ++ /* save spsr_fiq register */ ++ ldr r3, .Lsaved_spsr_fiq ++ mrs r1, spsr ++ str r1, [r3] ++ ++ CHANGE_MODE(12) /* change to irq mode */ ++ /* save nonvolatile int register */ ++ ldr r3, .Lsaved_context_r13_irq ++ stmia r3, {r13-r14} ++ /* save spsr_irq register */ ++ ldr r3, .Lsaved_spsr_irq ++ mrs r1, spsr ++ str r1, [r3] ++ ++ CHANGE_MODE(13) /* change to svc mode */ ++ /* save nonvolatile int register */ ++ ldr r3, .Lsaved_context_r13_svc ++ stmia r3, {r13-r14} ++ /* save spsr_svc register */ ++ ldr r3, .Lsaved_spsr_svc ++ mrs r1, spsr ++ str r1, [r3] ++ ++ CHANGE_MODE(17) /* change to abt mode */ ++ /* save nonvolatile int register */ ++ ldr r3, .Lsaved_context_r13_abt ++ stmia r3, {r13-r14} ++ /* save spsr_abt register */ ++ ldr r3, .Lsaved_spsr_abt ++ mrs r1, spsr ++ str r1, [r3] ++ ++ CHANGE_MODE(1b) /* change to und mode */ ++ /* save nonvolatile int register */ ++ ldr r3, .Lsaved_context_r13_und ++ stmia r3, {r13-r14} ++ /* save spsr_und register */ ++ ldr r3, .Lsaved_spsr_und ++ mrs r1, spsr ++ str r1, [r3] ++ ++ /* ++ * Go back to original SVC mode ++ */ ++ msr cpsr_c, r0 ++ ++ bl swsusp_save ++ ++#ifdef CONFIG_DEBUG_LL ++ adr r0, str_marker_1 ++ bl printascii ++ mov r0, #0 ++#endif ++ ++ /* ++ * Restore return address ++ */ ++ ldr r3, .Lsaved_context_r14_svc ++ ldr lr, [r3] ++ mov pc, lr ++ ++ WORD_ADDR(saved_context_r0) ++ WORD_ADDR(saved_cpsr) ++ ++ WORD_ADDR(saved_context_r8_fiq) ++ WORD_ADDR(saved_spsr_fiq) ++ ++ WORD_ADDR(saved_context_r13_irq) ++ WORD_ADDR(saved_spsr_irq) ++ ++ WORD_ADDR(saved_context_r13_svc) ++ WORD_ADDR(saved_context_r14_svc) ++ WORD_ADDR(saved_spsr_svc) ++ ++ WORD_ADDR(saved_context_r13_abt) ++ WORD_ADDR(saved_spsr_abt) ++ ++ WORD_ADDR(saved_context_r13_und) ++ WORD_ADDR(saved_spsr_und) ++ ++ENDPROC(swsusp_arch_suspend) ++ ++ENTRY(swsusp_arch_resume) ++ ++#ifdef CONFIG_DEBUG_LL ++ adr r0, str_marker_1 ++ bl printascii ++ mov r0, #0 ++#endif ++ ++#ifdef CONFIG_HISI_SNAPSHOT_BOOT ++ /* FIXME: need to check the cp15, c0 #4, ++ * "Instruction Set Attributes Register 4" ++ */ ++ #dsb ++ #isb ++ ++#else /* CONFIG_HISI_SNAPSHOT_BOOT */ ++ ++ /* ++ * Restore_pblist is the starting point for loaded pages ++ */ ++ ldr r0, .Lrestore_pblist ++ ldr r6, [r0] ++ ++ .Lcopy_loop: ++ ldr r4, [r6] /* src IOW present address */ ++ ldr r5, [r6, #4] /* dst IOW original address*/ ++ mov r9, #1024 /* No. of entries in one page(4 bytes each entry)*/ ++ ++ .Lcopy_one_page: ++ /* ++ * This loop could be optimized by using stm and ldm. ++ */ ++ ldr r8, [r4], #4 ++ str r8, [r5], #4 ++ subs r9, r9, #1 ++ bne .Lcopy_one_page ++ ++ /* The last field of struct pbe is a pointer to the next pbe struct */ ++ ldr r6, [r6, #8] ++ cmp r6, #0 ++ bne .Lcopy_loop ++#endif /* CONFIG_HISI_SNAPSHOT_BOOT */ ++ /* ++ * Restore SVC context ++ */ ++ ldr r3, .Lsaved_context_r13_svc ++ ldmia r3, {r13-r14} ++ ldr r3, .Lsaved_spsr_svc ++ ldr r1, [r3] ++ msr spsr_cxsf, r1 ++ ++ mrs r0, cpsr /* Save current mode into r0 */ ++ ++ CHANGE_MODE(11) /* change to fiq mode */ ++ /* restore nonvolatile int register */ ++ ldr r3, .Lsaved_context_r8_fiq ++ ldmia r3, {r8-r14} ++ /* restore spsr_fiq register */ ++ ldr r3, .Lsaved_spsr_fiq ++ ldr r1, [r3] ++ msr spsr_cxsf, r1 ++ ++ CHANGE_MODE(12) /* change to irq mode */ ++ /* restore nonvolatile int register */ ++ ldr r3, .Lsaved_context_r13_irq ++ ldmia r3, {r13-r14} ++ /* restore spsr_irq register */ ++ ldr r3, .Lsaved_spsr_irq ++ ldr r1, [r3] ++ msr spsr_cxsf, r1 ++ ++ CHANGE_MODE(17) /* change to abt mode */ ++ /* restore nonvolatile int register */ ++ ldr r3, .Lsaved_context_r13_abt ++ ldmia r3, {r13-r14} ++ /* restore spsr_abt register */ ++ ldr r3, .Lsaved_spsr_abt ++ ldr r1, [r3] ++ msr spsr_cxsf, r1 ++ ++ CHANGE_MODE(1b) /* change to und mode */ ++ /* restore nonvolatile int register */ ++ ldr r3, .Lsaved_context_r13_und ++ ldmia r3, {r13-r14} ++ /* restore spsr_und register */ ++ ldr r3, .Lsaved_spsr_und ++ ldr r1, [r3] ++ msr spsr_cxsf, r1 ++ ++ CHANGE_MODE(1f) /* Change to system(user) mode */ ++ ++ /* in_suspend = 0 */ ++ ldr r3,.Lsaved_in_suspend ++ mov r1,#0 ++ str r1,[r3] ++ ++ /* ++ * Restore User context ++ */ ++ ldr r3, .Lsaved_context_r0 ++ ldmia r3, {r0-r14} ++ ldr r3, .Lsaved_cpsr ++ ldr r1, [r3] ++ msr cpsr_cxsf, r1 ++ ++ /* ++ * Flush TLB (Invalidate unified TLB unlocked entries) ++ */ ++ mov r1, #0 ++ mcr p15, 0, r1, c8, c7, 0 ++ ++#ifdef CONFIG_DEBUG_LL ++ adr r0, str_marker_1 ++ bl printascii ++ mov r0, #0 ++#endif ++ ++ /* Set the return value */ ++ mov r0, #0 ++ ++ /* Restore return address */ ++ ldr r3, .Lsaved_context_r14_svc ++ ldr lr, [r3] ++ mov pc, lr ++ENDPROC(swsusp_arch_resume) ++ ++str_marker_1: .asciz "swsusp_arch_mark!!!\n\0" ++ ++ .align 4 ++.Lsaved_in_suspend: .long in_suspend +diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S +index 2465995..11da0f5 100644 +--- a/arch/arm/mm/cache-v6.S ++++ b/arch/arm/mm/cache-v6.S +@@ -270,6 +270,11 @@ v6_dma_clean_range: + * - end - virtual end address of region + */ + ENTRY(v6_dma_flush_range) ++#ifdef CONFIG_CACHE_FLUSH_RANGE_LIMIT ++ sub r2, r1, r0 ++ cmp r2, #CONFIG_CACHE_FLUSH_RANGE_LIMIT ++ bhi v6_dma_flush_dcache_all ++#endif + #ifdef CONFIG_DMA_CACHE_RWFO + ldrb r2, [r0] @ read for ownership + strb r2, [r0] @ write for ownership +@@ -292,6 +297,18 @@ ENTRY(v6_dma_flush_range) + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + ret lr + ++#ifdef CONFIG_CACHE_FLUSH_RANGE_LIMIT ++v6_dma_flush_dcache_all: ++ mov r0, #0 ++#ifdef HARVARD_CACHE ++ mcr p15, 0, r0, c7, c14, 0 @ D cache clean+invalidate ++#else ++ mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate ++#endif ++ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer ++ mov pc, lr ++#endif ++ + /* + * dma_map_area(start, size, dir) + * - start - kernel virtual start address +diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c +index e890711..369dc9b 100644 +--- a/arch/arm/mm/dma-mapping.c ++++ b/arch/arm/mm/dma-mapping.c +@@ -221,7 +221,7 @@ static u64 get_coherent_dma_mask(struct device *dev) + return mask; + } + +-static void __dma_clear_buffer(struct page *page, size_t size) ++void __dma_clear_buffer(struct page *page, size_t size) + { + /* + * Ensure that the allocated pages are zeroed, and that any data +@@ -246,6 +246,7 @@ static void __dma_clear_buffer(struct page *page, size_t size) + outer_flush_range(__pa(ptr), __pa(ptr) + size); + } + } ++EXPORT_SYMBOL(__dma_clear_buffer); + + /* + * Allocate a DMA buffer for 'dev' of size 'size' using the +@@ -465,6 +466,12 @@ static void __dma_remap(struct page *page, size_t size, pgprot_t prot) + flush_tlb_kernel_range(start, end); + } + ++void hisi_flush_tlb_kernel_range(unsigned long start, unsigned long end) ++{ ++ flush_tlb_kernel_range(start, end); ++} ++EXPORT_SYMBOL(hisi_flush_tlb_kernel_range); ++ + static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp, + pgprot_t prot, struct page **ret_page, + const void *caller) +diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c +index eb8830a..b784579 100644 +--- a/arch/arm/mm/fault.c ++++ b/arch/arm/mm/fault.c +@@ -274,10 +274,10 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) + local_irq_enable(); + + /* +- * If we're in an interrupt or have no user ++ * If we're in an interrupt, or have no irqs, or have no user + * context, we must not take the fault.. + */ +- if (in_atomic() || !mm) ++ if (in_atomic() || irqs_disabled() || !mm) + goto no_context; + + if (user_mode(regs)) +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index dc2d66c..43fe143 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -37,6 +37,7 @@ config ARM64 + select HAVE_ARCH_AUDITSYSCALL + select HAVE_ARCH_JUMP_LABEL + select HAVE_ARCH_KGDB ++ select HAVE_ARCH_SECCOMP_FILTER + select HAVE_ARCH_TRACEHOOK + select HAVE_BPF_JIT + select HAVE_C_RECORDMCOUNT +@@ -88,6 +89,10 @@ config MMU + config NO_IOPORT_MAP + def_bool y if !PCI + ++config ILLEGAL_POINTER_VALUE ++ hex ++ default 0xdead000000000000 ++ + config STACKTRACE_SUPPORT + def_bool y + +@@ -474,6 +479,19 @@ config ARCH_HAS_CACHE_LINE_SIZE + + source "mm/Kconfig" + ++config SECCOMP ++ bool "Enable seccomp to safely compute untrusted bytecode" ++ ---help--- ++ This kernel feature is useful for number crunching applications ++ that may need to compute untrusted bytecode during their ++ execution. By using pipes or other transports made available to ++ the process as file descriptors supporting the read/write ++ syscalls, it's possible to isolate those applications in ++ their own address space using seccomp. Once seccomp is ++ enabled via prctl(PR_SET_SECCOMP), it cannot be disabled ++ and the task is only allowed to execute a few safe syscalls ++ defined by each seccomp mode. ++ + config XEN_DOM0 + def_bool y + depends on XEN +@@ -490,6 +508,74 @@ config FORCE_MAX_ZONEORDER + default "14" if (ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE) + default "11" + ++menuconfig ARMV8_DEPRECATED ++ bool "Emulate deprecated/obsolete ARMv8 instructions" ++ depends on COMPAT ++ help ++ Legacy software support may require certain instructions ++ that have been deprecated or obsoleted in the architecture. ++ ++ Enable this config to enable selective emulation of these ++ features. ++ ++ If unsure, say Y ++ ++if ARMV8_DEPRECATED ++ ++config SWP_EMULATION ++ bool "Emulate SWP/SWPB instructions" ++ help ++ ARMv8 obsoletes the use of A32 SWP/SWPB instructions such that ++ they are always undefined. Say Y here to enable software ++ emulation of these instructions for userspace using LDXR/STXR. ++ ++ In some older versions of glibc [<=2.8] SWP is used during futex ++ trylock() operations with the assumption that the code will not ++ be preempted. This invalid assumption may be more likely to fail ++ with SWP emulation enabled, leading to deadlock of the user ++ application. ++ ++ NOTE: when accessing uncached shared regions, LDXR/STXR rely ++ on an external transaction monitoring block called a global ++ monitor to maintain update atomicity. If your system does not ++ implement a global monitor, this option can cause programs that ++ perform SWP operations to uncached memory to deadlock. ++ ++ If unsure, say Y ++ ++config CP15_BARRIER_EMULATION ++ bool "Emulate CP15 Barrier instructions" ++ help ++ The CP15 barrier instructions - CP15ISB, CP15DSB, and ++ CP15DMB - are deprecated in ARMv8 (and ARMv7). It is ++ strongly recommended to use the ISB, DSB, and DMB ++ instructions instead. ++ ++ Say Y here to enable software emulation of these ++ instructions for AArch32 userspace code. When this option is ++ enabled, CP15 barrier usage is traced which can help ++ identify software that needs updating. ++ ++ If unsure, say Y ++ ++config SETEND_EMULATION ++ bool "Emulate SETEND instruction" ++ help ++ The SETEND instruction alters the data-endianness of the ++ AArch32 EL0, and is deprecated in ARMv8. ++ ++ Say Y here to enable software emulation of the instruction ++ for AArch32 userspace code. ++ ++ Note: All the cpus on the system must have mixed endian support at EL0 ++ for this feature to be enabled. If a new CPU - which doesn't support mixed ++ endian - is hotplugged in after this feature has been enabled, there could ++ be unexpected results in the applications. ++ ++ If unsure, say Y ++ ++endif ++ + endmenu + + menu "Boot options" +@@ -502,6 +588,23 @@ config CMDLINE + entering them here. As a minimum, you should specify the the + root device (e.g. root=/dev/nfs). + ++choice ++ prompt "Kernel command line type" if CMDLINE != "" ++ default CMDLINE_FROM_BOOTLOADER ++ ++config CMDLINE_FROM_BOOTLOADER ++ bool "Use bootloader kernel arguments if available" ++ help ++ Uses the command-line options passed by the boot loader. If ++ the boot loader doesn't provide any, the default kernel command ++ string provided in CMDLINE will be used. ++ ++config CMDLINE_EXTEND ++ bool "Extend bootloader kernel arguments" ++ help ++ The command-line arguments provided by the boot loader will be ++ appended to the default kernel command string. ++ + config CMDLINE_FORCE + bool "Always use the default kernel command string" + help +@@ -509,6 +612,7 @@ config CMDLINE_FORCE + loader passes other arguments to the kernel. + This is useful if you cannot or don't want to change the + command-line options your boot loader passes to the kernel. ++endchoice + + config EFI_STUB + bool +@@ -530,6 +634,21 @@ config EFI + allow the kernel to be booted as an EFI application. This + is only useful on systems that have UEFI firmware. + ++config BUILD_ARM64_APPENDED_DTB_IMAGE ++ bool "Build a concatenated Image.gz/dtb by default" ++ depends on OF ++ help ++ Enabling this option will cause a concatenated Image.gz and list of ++ DTBs to be built by default (instead of a standalone Image.gz.) ++ The image will built in arch/arm64/boot/Image.gz-dtb ++ ++config BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES ++ string "Default dtb names" ++ depends on BUILD_ARM64_APPENDED_DTB_IMAGE ++ help ++ Space separated list of names of dtbs to append when ++ building a concatenated Image.gz-dtb. ++ + endmenu + + menu "Userspace binary formats" +diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug +index 0a12933..8dd3a55 100644 +--- a/arch/arm64/Kconfig.debug ++++ b/arch/arm64/Kconfig.debug +@@ -54,4 +54,6 @@ config DEBUG_SET_MODULE_RONX + against certain classes of kernel exploits. + If in doubt, say "N". + ++source "drivers/hwtracing/coresight/Kconfig" ++ + endmenu +diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile +index 20901ff..18daa9f 100644 +--- a/arch/arm64/Makefile ++++ b/arch/arm64/Makefile +@@ -20,6 +20,7 @@ LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) + KBUILD_DEFCONFIG := defconfig + + KBUILD_CFLAGS += -mgeneral-regs-only ++KBUILD_CFLAGS += -fno-pic + ifeq ($(CONFIG_CPU_BIG_ENDIAN), y) + KBUILD_CPPFLAGS += -mbig-endian + AS += -EB +@@ -54,7 +55,12 @@ libs-y += $(LIBGCC) + libs-$(CONFIG_EFI_STUB) += drivers/firmware/efi/libstub/ + + # Default target when executing plain make ++ifeq ($(CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE),y) ++KBUILD_IMAGE := Image.gz-dtb ++else + KBUILD_IMAGE := Image.gz ++endif ++ + KBUILD_DTBS := dtbs + + all: $(KBUILD_IMAGE) $(KBUILD_DTBS) +@@ -70,8 +76,16 @@ zinstall install: vmlinux + %.dtb: scripts + $(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@ + +-dtbs: scripts +- $(Q)$(MAKE) $(build)=$(boot)/dts dtbs ++PHONY += dtbs dtbs_install ++ ++dtbs: prepare scripts ++ $(Q)$(MAKE) $(build)=$(boot)/dts ++ ++dtbs_install: ++ $(Q)$(MAKE) $(dtbinst)=$(boot)/dts ++ ++Image.gz-dtb: vmlinux scripts dtbs ++ $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ + + PHONY += vdso_install + vdso_install: +@@ -85,6 +99,7 @@ define archhelp + echo '* Image.gz - Compressed kernel image (arch/$(ARCH)/boot/Image.gz)' + echo ' Image - Uncompressed kernel image (arch/$(ARCH)/boot/Image)' + echo '* dtbs - Build device tree blobs for enabled boards' ++ echo ' dtbs_install - Install dtbs to $(INSTALL_DTBS_PATH)' + echo ' install - Install uncompressed kernel' + echo ' zinstall - Install compressed kernel' + echo ' Install using (your) ~/bin/installkernel or' +diff --git a/arch/arm64/boot/.gitignore b/arch/arm64/boot/.gitignore +index 8dab0bb..eb35511 100644 +--- a/arch/arm64/boot/.gitignore ++++ b/arch/arm64/boot/.gitignore +@@ -1,2 +1,3 @@ + Image + Image.gz ++Image.gz-dtb +diff --git a/arch/arm64/boot/Makefile b/arch/arm64/boot/Makefile +index 5a0e3ab..71f513f 100644 +--- a/arch/arm64/boot/Makefile ++++ b/arch/arm64/boot/Makefile +@@ -14,14 +14,27 @@ + # Based on the ia64 boot/Makefile. + # + ++include $(srctree)/arch/arm64/boot/dts/Makefile ++ + targets := Image Image.gz + ++DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES)) ++ifneq ($(DTB_NAMES),) ++DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES)) ++DTB_OBJS := $(addprefix $(obj)/dts/,$(DTB_LIST)) ++else ++DTB_OBJS := $(shell find $(obj)/dts/ -name \*.dtb) ++endif ++ + $(obj)/Image: vmlinux FORCE + $(call if_changed,objcopy) + + $(obj)/Image.gz: $(obj)/Image FORCE + $(call if_changed,gzip) + ++$(obj)/Image.gz-dtb: $(obj)/Image.gz $(DTB_OBJS) FORCE ++ $(call if_changed,cat) ++ + install: $(obj)/Image + $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \ + $(obj)/Image System.map "$(INSTALL_PATH)" +diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile +index f8001a6..68d2567 100644 +--- a/arch/arm64/boot/dts/Makefile ++++ b/arch/arm64/boot/dts/Makefile +@@ -1,10 +1,6 @@ +-dtb-$(CONFIG_ARCH_THUNDER) += thunder-88xx.dtb +-dtb-$(CONFIG_ARCH_VEXPRESS) += rtsm_ve-aemv8a.dtb foundation-v8.dtb +-dtb-$(CONFIG_ARCH_XGENE) += apm-mustang.dtb ++dts-dirs += apm ++dts-dirs += arm ++dts-dirs += cavium + +-targets += dtbs +-targets += $(dtb-y) +- +-dtbs: $(addprefix $(obj)/, $(dtb-y)) +- +-clean-files := *.dtb ++always := $(dtb-y) ++subdir-y := $(dts-dirs) +diff --git a/arch/arm64/boot/dts/apm-mustang.dts b/arch/arm64/boot/dts/apm-mustang.dts +deleted file mode 100644 +index 2e25de08..0000000 +--- a/arch/arm64/boot/dts/apm-mustang.dts ++++ /dev/null +@@ -1,50 +0,0 @@ +-/* +- * dts file for AppliedMicro (APM) Mustang Board +- * +- * Copyright (C) 2013, Applied Micro Circuits Corporation +- * +- * 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. +- */ +- +-/dts-v1/; +- +-/include/ "apm-storm.dtsi" +- +-/ { +- model = "APM X-Gene Mustang board"; +- compatible = "apm,mustang", "apm,xgene-storm"; +- +- chosen { }; +- +- memory { +- device_type = "memory"; +- reg = < 0x1 0x00000000 0x0 0x80000000 >; /* Updated by bootloader */ +- }; +-}; +- +-&pcie0clk { +- status = "ok"; +-}; +- +-&pcie0 { +- status = "ok"; +-}; +- +-&serial0 { +- status = "ok"; +-}; +- +-&menet { +- status = "ok"; +-}; +- +-&sgenet0 { +- status = "ok"; +-}; +- +-&xgenet { +- status = "ok"; +-}; +diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi +deleted file mode 100644 +index f1ad9c2..0000000 +--- a/arch/arm64/boot/dts/apm-storm.dtsi ++++ /dev/null +@@ -1,660 +0,0 @@ +-/* +- * dts file for AppliedMicro (APM) X-Gene Storm SOC +- * +- * Copyright (C) 2013, Applied Micro Circuits Corporation +- * +- * 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. +- */ +- +-/ { +- compatible = "apm,xgene-storm"; +- interrupt-parent = <&gic>; +- #address-cells = <2>; +- #size-cells = <2>; +- +- cpus { +- #address-cells = <2>; +- #size-cells = <0>; +- +- cpu@000 { +- device_type = "cpu"; +- compatible = "apm,potenza", "arm,armv8"; +- reg = <0x0 0x000>; +- enable-method = "spin-table"; +- cpu-release-addr = <0x1 0x0000fff8>; +- }; +- cpu@001 { +- device_type = "cpu"; +- compatible = "apm,potenza", "arm,armv8"; +- reg = <0x0 0x001>; +- enable-method = "spin-table"; +- cpu-release-addr = <0x1 0x0000fff8>; +- }; +- cpu@100 { +- device_type = "cpu"; +- compatible = "apm,potenza", "arm,armv8"; +- reg = <0x0 0x100>; +- enable-method = "spin-table"; +- cpu-release-addr = <0x1 0x0000fff8>; +- }; +- cpu@101 { +- device_type = "cpu"; +- compatible = "apm,potenza", "arm,armv8"; +- reg = <0x0 0x101>; +- enable-method = "spin-table"; +- cpu-release-addr = <0x1 0x0000fff8>; +- }; +- cpu@200 { +- device_type = "cpu"; +- compatible = "apm,potenza", "arm,armv8"; +- reg = <0x0 0x200>; +- enable-method = "spin-table"; +- cpu-release-addr = <0x1 0x0000fff8>; +- }; +- cpu@201 { +- device_type = "cpu"; +- compatible = "apm,potenza", "arm,armv8"; +- reg = <0x0 0x201>; +- enable-method = "spin-table"; +- cpu-release-addr = <0x1 0x0000fff8>; +- }; +- cpu@300 { +- device_type = "cpu"; +- compatible = "apm,potenza", "arm,armv8"; +- reg = <0x0 0x300>; +- enable-method = "spin-table"; +- cpu-release-addr = <0x1 0x0000fff8>; +- }; +- cpu@301 { +- device_type = "cpu"; +- compatible = "apm,potenza", "arm,armv8"; +- reg = <0x0 0x301>; +- enable-method = "spin-table"; +- cpu-release-addr = <0x1 0x0000fff8>; +- }; +- }; +- +- gic: interrupt-controller@78010000 { +- compatible = "arm,cortex-a15-gic"; +- #interrupt-cells = <3>; +- interrupt-controller; +- reg = <0x0 0x78010000 0x0 0x1000>, /* GIC Dist */ +- <0x0 0x78020000 0x0 0x1000>, /* GIC CPU */ +- <0x0 0x78040000 0x0 0x2000>, /* GIC VCPU Control */ +- <0x0 0x78060000 0x0 0x2000>; /* GIC VCPU */ +- interrupts = <1 9 0xf04>; /* GIC Maintenence IRQ */ +- }; +- +- timer { +- compatible = "arm,armv8-timer"; +- interrupts = <1 0 0xff01>, /* Secure Phys IRQ */ +- <1 13 0xff01>, /* Non-secure Phys IRQ */ +- <1 14 0xff01>, /* Virt IRQ */ +- <1 15 0xff01>; /* Hyp IRQ */ +- clock-frequency = <50000000>; +- }; +- +- soc { +- compatible = "simple-bus"; +- #address-cells = <2>; +- #size-cells = <2>; +- ranges; +- +- clocks { +- #address-cells = <2>; +- #size-cells = <2>; +- ranges; +- refclk: refclk { +- compatible = "fixed-clock"; +- #clock-cells = <1>; +- clock-frequency = <100000000>; +- clock-output-names = "refclk"; +- }; +- +- pcppll: pcppll@17000100 { +- compatible = "apm,xgene-pcppll-clock"; +- #clock-cells = <1>; +- clocks = <&refclk 0>; +- clock-names = "pcppll"; +- reg = <0x0 0x17000100 0x0 0x1000>; +- clock-output-names = "pcppll"; +- type = <0>; +- }; +- +- socpll: socpll@17000120 { +- compatible = "apm,xgene-socpll-clock"; +- #clock-cells = <1>; +- clocks = <&refclk 0>; +- clock-names = "socpll"; +- reg = <0x0 0x17000120 0x0 0x1000>; +- clock-output-names = "socpll"; +- type = <1>; +- }; +- +- socplldiv2: socplldiv2 { +- compatible = "fixed-factor-clock"; +- #clock-cells = <1>; +- clocks = <&socpll 0>; +- clock-names = "socplldiv2"; +- clock-mult = <1>; +- clock-div = <2>; +- clock-output-names = "socplldiv2"; +- }; +- +- qmlclk: qmlclk { +- compatible = "apm,xgene-device-clock"; +- #clock-cells = <1>; +- clocks = <&socplldiv2 0>; +- clock-names = "qmlclk"; +- reg = <0x0 0x1703C000 0x0 0x1000>; +- reg-names = "csr-reg"; +- clock-output-names = "qmlclk"; +- }; +- +- ethclk: ethclk { +- compatible = "apm,xgene-device-clock"; +- #clock-cells = <1>; +- clocks = <&socplldiv2 0>; +- clock-names = "ethclk"; +- reg = <0x0 0x17000000 0x0 0x1000>; +- reg-names = "div-reg"; +- divider-offset = <0x238>; +- divider-width = <0x9>; +- divider-shift = <0x0>; +- clock-output-names = "ethclk"; +- }; +- +- menetclk: menetclk { +- compatible = "apm,xgene-device-clock"; +- #clock-cells = <1>; +- clocks = <ðclk 0>; +- reg = <0x0 0x1702C000 0x0 0x1000>; +- reg-names = "csr-reg"; +- clock-output-names = "menetclk"; +- }; +- +- sge0clk: sge0clk@1f21c000 { +- compatible = "apm,xgene-device-clock"; +- #clock-cells = <1>; +- clocks = <&socplldiv2 0>; +- reg = <0x0 0x1f21c000 0x0 0x1000>; +- reg-names = "csr-reg"; +- csr-mask = <0x3>; +- clock-output-names = "sge0clk"; +- }; +- +- xge0clk: xge0clk@1f61c000 { +- compatible = "apm,xgene-device-clock"; +- #clock-cells = <1>; +- clocks = <&socplldiv2 0>; +- reg = <0x0 0x1f61c000 0x0 0x1000>; +- reg-names = "csr-reg"; +- csr-mask = <0x3>; +- clock-output-names = "xge0clk"; +- }; +- +- sataphy1clk: sataphy1clk@1f21c000 { +- compatible = "apm,xgene-device-clock"; +- #clock-cells = <1>; +- clocks = <&socplldiv2 0>; +- reg = <0x0 0x1f21c000 0x0 0x1000>; +- reg-names = "csr-reg"; +- clock-output-names = "sataphy1clk"; +- status = "disabled"; +- csr-offset = <0x4>; +- csr-mask = <0x00>; +- enable-offset = <0x0>; +- enable-mask = <0x06>; +- }; +- +- sataphy2clk: sataphy1clk@1f22c000 { +- compatible = "apm,xgene-device-clock"; +- #clock-cells = <1>; +- clocks = <&socplldiv2 0>; +- reg = <0x0 0x1f22c000 0x0 0x1000>; +- reg-names = "csr-reg"; +- clock-output-names = "sataphy2clk"; +- status = "ok"; +- csr-offset = <0x4>; +- csr-mask = <0x3a>; +- enable-offset = <0x0>; +- enable-mask = <0x06>; +- }; +- +- sataphy3clk: sataphy1clk@1f23c000 { +- compatible = "apm,xgene-device-clock"; +- #clock-cells = <1>; +- clocks = <&socplldiv2 0>; +- reg = <0x0 0x1f23c000 0x0 0x1000>; +- reg-names = "csr-reg"; +- clock-output-names = "sataphy3clk"; +- status = "ok"; +- csr-offset = <0x4>; +- csr-mask = <0x3a>; +- enable-offset = <0x0>; +- enable-mask = <0x06>; +- }; +- +- sata01clk: sata01clk@1f21c000 { +- compatible = "apm,xgene-device-clock"; +- #clock-cells = <1>; +- clocks = <&socplldiv2 0>; +- reg = <0x0 0x1f21c000 0x0 0x1000>; +- reg-names = "csr-reg"; +- clock-output-names = "sata01clk"; +- csr-offset = <0x4>; +- csr-mask = <0x05>; +- enable-offset = <0x0>; +- enable-mask = <0x39>; +- }; +- +- sata23clk: sata23clk@1f22c000 { +- compatible = "apm,xgene-device-clock"; +- #clock-cells = <1>; +- clocks = <&socplldiv2 0>; +- reg = <0x0 0x1f22c000 0x0 0x1000>; +- reg-names = "csr-reg"; +- clock-output-names = "sata23clk"; +- csr-offset = <0x4>; +- csr-mask = <0x05>; +- enable-offset = <0x0>; +- enable-mask = <0x39>; +- }; +- +- sata45clk: sata45clk@1f23c000 { +- compatible = "apm,xgene-device-clock"; +- #clock-cells = <1>; +- clocks = <&socplldiv2 0>; +- reg = <0x0 0x1f23c000 0x0 0x1000>; +- reg-names = "csr-reg"; +- clock-output-names = "sata45clk"; +- csr-offset = <0x4>; +- csr-mask = <0x05>; +- enable-offset = <0x0>; +- enable-mask = <0x39>; +- }; +- +- rtcclk: rtcclk@17000000 { +- compatible = "apm,xgene-device-clock"; +- #clock-cells = <1>; +- clocks = <&socplldiv2 0>; +- reg = <0x0 0x17000000 0x0 0x2000>; +- reg-names = "csr-reg"; +- csr-offset = <0xc>; +- csr-mask = <0x2>; +- enable-offset = <0x10>; +- enable-mask = <0x2>; +- clock-output-names = "rtcclk"; +- }; +- +- rngpkaclk: rngpkaclk@17000000 { +- compatible = "apm,xgene-device-clock"; +- #clock-cells = <1>; +- clocks = <&socplldiv2 0>; +- reg = <0x0 0x17000000 0x0 0x2000>; +- reg-names = "csr-reg"; +- csr-offset = <0xc>; +- csr-mask = <0x10>; +- enable-offset = <0x10>; +- enable-mask = <0x10>; +- clock-output-names = "rngpkaclk"; +- }; +- +- pcie0clk: pcie0clk@1f2bc000 { +- status = "disabled"; +- compatible = "apm,xgene-device-clock"; +- #clock-cells = <1>; +- clocks = <&socplldiv2 0>; +- reg = <0x0 0x1f2bc000 0x0 0x1000>; +- reg-names = "csr-reg"; +- clock-output-names = "pcie0clk"; +- }; +- +- pcie1clk: pcie1clk@1f2cc000 { +- status = "disabled"; +- compatible = "apm,xgene-device-clock"; +- #clock-cells = <1>; +- clocks = <&socplldiv2 0>; +- reg = <0x0 0x1f2cc000 0x0 0x1000>; +- reg-names = "csr-reg"; +- clock-output-names = "pcie1clk"; +- }; +- +- pcie2clk: pcie2clk@1f2dc000 { +- status = "disabled"; +- compatible = "apm,xgene-device-clock"; +- #clock-cells = <1>; +- clocks = <&socplldiv2 0>; +- reg = <0x0 0x1f2dc000 0x0 0x1000>; +- reg-names = "csr-reg"; +- clock-output-names = "pcie2clk"; +- }; +- +- pcie3clk: pcie3clk@1f50c000 { +- status = "disabled"; +- compatible = "apm,xgene-device-clock"; +- #clock-cells = <1>; +- clocks = <&socplldiv2 0>; +- reg = <0x0 0x1f50c000 0x0 0x1000>; +- reg-names = "csr-reg"; +- clock-output-names = "pcie3clk"; +- }; +- +- pcie4clk: pcie4clk@1f51c000 { +- status = "disabled"; +- compatible = "apm,xgene-device-clock"; +- #clock-cells = <1>; +- clocks = <&socplldiv2 0>; +- reg = <0x0 0x1f51c000 0x0 0x1000>; +- reg-names = "csr-reg"; +- clock-output-names = "pcie4clk"; +- }; +- }; +- +- pcie0: pcie@1f2b0000 { +- status = "disabled"; +- device_type = "pci"; +- compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie"; +- #interrupt-cells = <1>; +- #size-cells = <2>; +- #address-cells = <3>; +- reg = < 0x00 0x1f2b0000 0x0 0x00010000 /* Controller registers */ +- 0xe0 0xd0000000 0x0 0x00040000>; /* PCI config space */ +- reg-names = "csr", "cfg"; +- ranges = <0x01000000 0x00 0x00000000 0xe0 0x10000000 0x00 0x00010000 /* io */ +- 0x02000000 0x00 0x80000000 0xe1 0x80000000 0x00 0x80000000>; /* mem */ +- dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 +- 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; +- interrupt-map-mask = <0x0 0x0 0x0 0x7>; +- interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc2 0x1 +- 0x0 0x0 0x0 0x2 &gic 0x0 0xc3 0x1 +- 0x0 0x0 0x0 0x3 &gic 0x0 0xc4 0x1 +- 0x0 0x0 0x0 0x4 &gic 0x0 0xc5 0x1>; +- dma-coherent; +- clocks = <&pcie0clk 0>; +- }; +- +- pcie1: pcie@1f2c0000 { +- status = "disabled"; +- device_type = "pci"; +- compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie"; +- #interrupt-cells = <1>; +- #size-cells = <2>; +- #address-cells = <3>; +- reg = < 0x00 0x1f2c0000 0x0 0x00010000 /* Controller registers */ +- 0xd0 0xd0000000 0x0 0x00040000>; /* PCI config space */ +- reg-names = "csr", "cfg"; +- ranges = <0x01000000 0x0 0x00000000 0xd0 0x10000000 0x00 0x00010000 /* io */ +- 0x02000000 0x0 0x80000000 0xd1 0x80000000 0x00 0x80000000>; /* mem */ +- dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 +- 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; +- interrupt-map-mask = <0x0 0x0 0x0 0x7>; +- interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc8 0x1 +- 0x0 0x0 0x0 0x2 &gic 0x0 0xc9 0x1 +- 0x0 0x0 0x0 0x3 &gic 0x0 0xca 0x1 +- 0x0 0x0 0x0 0x4 &gic 0x0 0xcb 0x1>; +- dma-coherent; +- clocks = <&pcie1clk 0>; +- }; +- +- pcie2: pcie@1f2d0000 { +- status = "disabled"; +- device_type = "pci"; +- compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie"; +- #interrupt-cells = <1>; +- #size-cells = <2>; +- #address-cells = <3>; +- reg = < 0x00 0x1f2d0000 0x0 0x00010000 /* Controller registers */ +- 0x90 0xd0000000 0x0 0x00040000>; /* PCI config space */ +- reg-names = "csr", "cfg"; +- ranges = <0x01000000 0x0 0x00000000 0x90 0x10000000 0x0 0x00010000 /* io */ +- 0x02000000 0x0 0x80000000 0x91 0x80000000 0x0 0x80000000>; /* mem */ +- dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 +- 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; +- interrupt-map-mask = <0x0 0x0 0x0 0x7>; +- interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xce 0x1 +- 0x0 0x0 0x0 0x2 &gic 0x0 0xcf 0x1 +- 0x0 0x0 0x0 0x3 &gic 0x0 0xd0 0x1 +- 0x0 0x0 0x0 0x4 &gic 0x0 0xd1 0x1>; +- dma-coherent; +- clocks = <&pcie2clk 0>; +- }; +- +- pcie3: pcie@1f500000 { +- status = "disabled"; +- device_type = "pci"; +- compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie"; +- #interrupt-cells = <1>; +- #size-cells = <2>; +- #address-cells = <3>; +- reg = < 0x00 0x1f500000 0x0 0x00010000 /* Controller registers */ +- 0xa0 0xd0000000 0x0 0x00040000>; /* PCI config space */ +- reg-names = "csr", "cfg"; +- ranges = <0x01000000 0x0 0x00000000 0xa0 0x10000000 0x0 0x00010000 /* io */ +- 0x02000000 0x0 0x80000000 0xa1 0x80000000 0x0 0x80000000>; /* mem */ +- dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 +- 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; +- interrupt-map-mask = <0x0 0x0 0x0 0x7>; +- interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xd4 0x1 +- 0x0 0x0 0x0 0x2 &gic 0x0 0xd5 0x1 +- 0x0 0x0 0x0 0x3 &gic 0x0 0xd6 0x1 +- 0x0 0x0 0x0 0x4 &gic 0x0 0xd7 0x1>; +- dma-coherent; +- clocks = <&pcie3clk 0>; +- }; +- +- pcie4: pcie@1f510000 { +- status = "disabled"; +- device_type = "pci"; +- compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie"; +- #interrupt-cells = <1>; +- #size-cells = <2>; +- #address-cells = <3>; +- reg = < 0x00 0x1f510000 0x0 0x00010000 /* Controller registers */ +- 0xc0 0xd0000000 0x0 0x00200000>; /* PCI config space */ +- reg-names = "csr", "cfg"; +- ranges = <0x01000000 0x0 0x00000000 0xc0 0x10000000 0x0 0x00010000 /* io */ +- 0x02000000 0x0 0x80000000 0xc1 0x80000000 0x0 0x80000000>; /* mem */ +- dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 +- 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; +- interrupt-map-mask = <0x0 0x0 0x0 0x7>; +- interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xda 0x1 +- 0x0 0x0 0x0 0x2 &gic 0x0 0xdb 0x1 +- 0x0 0x0 0x0 0x3 &gic 0x0 0xdc 0x1 +- 0x0 0x0 0x0 0x4 &gic 0x0 0xdd 0x1>; +- dma-coherent; +- clocks = <&pcie4clk 0>; +- }; +- +- serial0: serial@1c020000 { +- status = "disabled"; +- device_type = "serial"; +- compatible = "ns16550a"; +- reg = <0 0x1c020000 0x0 0x1000>; +- reg-shift = <2>; +- clock-frequency = <10000000>; /* Updated by bootloader */ +- interrupt-parent = <&gic>; +- interrupts = <0x0 0x4c 0x4>; +- }; +- +- serial1: serial@1c021000 { +- status = "disabled"; +- device_type = "serial"; +- compatible = "ns16550a"; +- reg = <0 0x1c021000 0x0 0x1000>; +- reg-shift = <2>; +- clock-frequency = <10000000>; /* Updated by bootloader */ +- interrupt-parent = <&gic>; +- interrupts = <0x0 0x4d 0x4>; +- }; +- +- serial2: serial@1c022000 { +- status = "disabled"; +- device_type = "serial"; +- compatible = "ns16550a"; +- reg = <0 0x1c022000 0x0 0x1000>; +- reg-shift = <2>; +- clock-frequency = <10000000>; /* Updated by bootloader */ +- interrupt-parent = <&gic>; +- interrupts = <0x0 0x4e 0x4>; +- }; +- +- serial3: serial@1c023000 { +- status = "disabled"; +- device_type = "serial"; +- compatible = "ns16550a"; +- reg = <0 0x1c023000 0x0 0x1000>; +- reg-shift = <2>; +- clock-frequency = <10000000>; /* Updated by bootloader */ +- interrupt-parent = <&gic>; +- interrupts = <0x0 0x4f 0x4>; +- }; +- +- phy1: phy@1f21a000 { +- compatible = "apm,xgene-phy"; +- reg = <0x0 0x1f21a000 0x0 0x100>; +- #phy-cells = <1>; +- clocks = <&sataphy1clk 0>; +- status = "disabled"; +- apm,tx-boost-gain = <30 30 30 30 30 30>; +- apm,tx-eye-tuning = <2 10 10 2 10 10>; +- }; +- +- phy2: phy@1f22a000 { +- compatible = "apm,xgene-phy"; +- reg = <0x0 0x1f22a000 0x0 0x100>; +- #phy-cells = <1>; +- clocks = <&sataphy2clk 0>; +- status = "ok"; +- apm,tx-boost-gain = <30 30 30 30 30 30>; +- apm,tx-eye-tuning = <1 10 10 2 10 10>; +- }; +- +- phy3: phy@1f23a000 { +- compatible = "apm,xgene-phy"; +- reg = <0x0 0x1f23a000 0x0 0x100>; +- #phy-cells = <1>; +- clocks = <&sataphy3clk 0>; +- status = "ok"; +- apm,tx-boost-gain = <31 31 31 31 31 31>; +- apm,tx-eye-tuning = <2 10 10 2 10 10>; +- }; +- +- sata1: sata@1a000000 { +- compatible = "apm,xgene-ahci"; +- reg = <0x0 0x1a000000 0x0 0x1000>, +- <0x0 0x1f210000 0x0 0x1000>, +- <0x0 0x1f21d000 0x0 0x1000>, +- <0x0 0x1f21e000 0x0 0x1000>, +- <0x0 0x1f217000 0x0 0x1000>; +- interrupts = <0x0 0x86 0x4>; +- dma-coherent; +- status = "disabled"; +- clocks = <&sata01clk 0>; +- phys = <&phy1 0>; +- phy-names = "sata-phy"; +- }; +- +- sata2: sata@1a400000 { +- compatible = "apm,xgene-ahci"; +- reg = <0x0 0x1a400000 0x0 0x1000>, +- <0x0 0x1f220000 0x0 0x1000>, +- <0x0 0x1f22d000 0x0 0x1000>, +- <0x0 0x1f22e000 0x0 0x1000>, +- <0x0 0x1f227000 0x0 0x1000>; +- interrupts = <0x0 0x87 0x4>; +- dma-coherent; +- status = "ok"; +- clocks = <&sata23clk 0>; +- phys = <&phy2 0>; +- phy-names = "sata-phy"; +- }; +- +- sata3: sata@1a800000 { +- compatible = "apm,xgene-ahci"; +- reg = <0x0 0x1a800000 0x0 0x1000>, +- <0x0 0x1f230000 0x0 0x1000>, +- <0x0 0x1f23d000 0x0 0x1000>, +- <0x0 0x1f23e000 0x0 0x1000>; +- interrupts = <0x0 0x88 0x4>; +- dma-coherent; +- status = "ok"; +- clocks = <&sata45clk 0>; +- phys = <&phy3 0>; +- phy-names = "sata-phy"; +- }; +- +- rtc: rtc@10510000 { +- compatible = "apm,xgene-rtc"; +- reg = <0x0 0x10510000 0x0 0x400>; +- interrupts = <0x0 0x46 0x4>; +- #clock-cells = <1>; +- clocks = <&rtcclk 0>; +- }; +- +- menet: ethernet@17020000 { +- compatible = "apm,xgene-enet"; +- status = "disabled"; +- reg = <0x0 0x17020000 0x0 0xd100>, +- <0x0 0X17030000 0x0 0Xc300>, +- <0x0 0X10000000 0x0 0X200>; +- reg-names = "enet_csr", "ring_csr", "ring_cmd"; +- interrupts = <0x0 0x3c 0x4>; +- dma-coherent; +- clocks = <&menetclk 0>; +- /* mac address will be overwritten by the bootloader */ +- local-mac-address = [00 00 00 00 00 00]; +- phy-connection-type = "rgmii"; +- phy-handle = <&menetphy>; +- mdio { +- compatible = "apm,xgene-mdio"; +- #address-cells = <1>; +- #size-cells = <0>; +- menetphy: menetphy@3 { +- compatible = "ethernet-phy-id001c.c915"; +- reg = <0x3>; +- }; +- +- }; +- }; +- +- sgenet0: ethernet@1f210000 { +- compatible = "apm,xgene-enet"; +- status = "disabled"; +- reg = <0x0 0x1f210000 0x0 0xd100>, +- <0x0 0x1f200000 0x0 0Xc300>, +- <0x0 0x1B000000 0x0 0X200>; +- reg-names = "enet_csr", "ring_csr", "ring_cmd"; +- interrupts = <0x0 0xA0 0x4>; +- dma-coherent; +- clocks = <&sge0clk 0>; +- local-mac-address = [00 00 00 00 00 00]; +- phy-connection-type = "sgmii"; +- }; +- +- xgenet: ethernet@1f610000 { +- compatible = "apm,xgene-enet"; +- status = "disabled"; +- reg = <0x0 0x1f610000 0x0 0xd100>, +- <0x0 0x1f600000 0x0 0Xc300>, +- <0x0 0x18000000 0x0 0X200>; +- reg-names = "enet_csr", "ring_csr", "ring_cmd"; +- interrupts = <0x0 0x60 0x4>; +- dma-coherent; +- clocks = <&xge0clk 0>; +- /* mac address will be overwritten by the bootloader */ +- local-mac-address = [00 00 00 00 00 00]; +- phy-connection-type = "xgmii"; +- }; +- +- rng: rng@10520000 { +- compatible = "apm,xgene-rng"; +- reg = <0x0 0x10520000 0x0 0x100>; +- interrupts = <0x0 0x41 0x4>; +- clocks = <&rngpkaclk 0>; +- }; +- }; +-}; +diff --git a/arch/arm64/boot/dts/apm/Makefile b/arch/arm64/boot/dts/apm/Makefile +new file mode 100644 +index 0000000..a2afabb +--- /dev/null ++++ b/arch/arm64/boot/dts/apm/Makefile +@@ -0,0 +1,5 @@ ++dtb-$(CONFIG_ARCH_XGENE) += apm-mustang.dtb ++ ++always := $(dtb-y) ++subdir-y := $(dts-dirs) ++clean-files := *.dtb +diff --git a/arch/arm64/boot/dts/apm/apm-mustang.dts b/arch/arm64/boot/dts/apm/apm-mustang.dts +new file mode 100644 +index 0000000..2e25de08 +--- /dev/null ++++ b/arch/arm64/boot/dts/apm/apm-mustang.dts +@@ -0,0 +1,50 @@ ++/* ++ * dts file for AppliedMicro (APM) Mustang Board ++ * ++ * Copyright (C) 2013, Applied Micro Circuits Corporation ++ * ++ * 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. ++ */ ++ ++/dts-v1/; ++ ++/include/ "apm-storm.dtsi" ++ ++/ { ++ model = "APM X-Gene Mustang board"; ++ compatible = "apm,mustang", "apm,xgene-storm"; ++ ++ chosen { }; ++ ++ memory { ++ device_type = "memory"; ++ reg = < 0x1 0x00000000 0x0 0x80000000 >; /* Updated by bootloader */ ++ }; ++}; ++ ++&pcie0clk { ++ status = "ok"; ++}; ++ ++&pcie0 { ++ status = "ok"; ++}; ++ ++&serial0 { ++ status = "ok"; ++}; ++ ++&menet { ++ status = "ok"; ++}; ++ ++&sgenet0 { ++ status = "ok"; ++}; ++ ++&xgenet { ++ status = "ok"; ++}; +diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi +new file mode 100644 +index 0000000..f1ad9c2 +--- /dev/null ++++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi +@@ -0,0 +1,660 @@ ++/* ++ * dts file for AppliedMicro (APM) X-Gene Storm SOC ++ * ++ * Copyright (C) 2013, Applied Micro Circuits Corporation ++ * ++ * 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. ++ */ ++ ++/ { ++ compatible = "apm,xgene-storm"; ++ interrupt-parent = <&gic>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ cpus { ++ #address-cells = <2>; ++ #size-cells = <0>; ++ ++ cpu@000 { ++ device_type = "cpu"; ++ compatible = "apm,potenza", "arm,armv8"; ++ reg = <0x0 0x000>; ++ enable-method = "spin-table"; ++ cpu-release-addr = <0x1 0x0000fff8>; ++ }; ++ cpu@001 { ++ device_type = "cpu"; ++ compatible = "apm,potenza", "arm,armv8"; ++ reg = <0x0 0x001>; ++ enable-method = "spin-table"; ++ cpu-release-addr = <0x1 0x0000fff8>; ++ }; ++ cpu@100 { ++ device_type = "cpu"; ++ compatible = "apm,potenza", "arm,armv8"; ++ reg = <0x0 0x100>; ++ enable-method = "spin-table"; ++ cpu-release-addr = <0x1 0x0000fff8>; ++ }; ++ cpu@101 { ++ device_type = "cpu"; ++ compatible = "apm,potenza", "arm,armv8"; ++ reg = <0x0 0x101>; ++ enable-method = "spin-table"; ++ cpu-release-addr = <0x1 0x0000fff8>; ++ }; ++ cpu@200 { ++ device_type = "cpu"; ++ compatible = "apm,potenza", "arm,armv8"; ++ reg = <0x0 0x200>; ++ enable-method = "spin-table"; ++ cpu-release-addr = <0x1 0x0000fff8>; ++ }; ++ cpu@201 { ++ device_type = "cpu"; ++ compatible = "apm,potenza", "arm,armv8"; ++ reg = <0x0 0x201>; ++ enable-method = "spin-table"; ++ cpu-release-addr = <0x1 0x0000fff8>; ++ }; ++ cpu@300 { ++ device_type = "cpu"; ++ compatible = "apm,potenza", "arm,armv8"; ++ reg = <0x0 0x300>; ++ enable-method = "spin-table"; ++ cpu-release-addr = <0x1 0x0000fff8>; ++ }; ++ cpu@301 { ++ device_type = "cpu"; ++ compatible = "apm,potenza", "arm,armv8"; ++ reg = <0x0 0x301>; ++ enable-method = "spin-table"; ++ cpu-release-addr = <0x1 0x0000fff8>; ++ }; ++ }; ++ ++ gic: interrupt-controller@78010000 { ++ compatible = "arm,cortex-a15-gic"; ++ #interrupt-cells = <3>; ++ interrupt-controller; ++ reg = <0x0 0x78010000 0x0 0x1000>, /* GIC Dist */ ++ <0x0 0x78020000 0x0 0x1000>, /* GIC CPU */ ++ <0x0 0x78040000 0x0 0x2000>, /* GIC VCPU Control */ ++ <0x0 0x78060000 0x0 0x2000>; /* GIC VCPU */ ++ interrupts = <1 9 0xf04>; /* GIC Maintenence IRQ */ ++ }; ++ ++ timer { ++ compatible = "arm,armv8-timer"; ++ interrupts = <1 0 0xff01>, /* Secure Phys IRQ */ ++ <1 13 0xff01>, /* Non-secure Phys IRQ */ ++ <1 14 0xff01>, /* Virt IRQ */ ++ <1 15 0xff01>; /* Hyp IRQ */ ++ clock-frequency = <50000000>; ++ }; ++ ++ soc { ++ compatible = "simple-bus"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ clocks { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ refclk: refclk { ++ compatible = "fixed-clock"; ++ #clock-cells = <1>; ++ clock-frequency = <100000000>; ++ clock-output-names = "refclk"; ++ }; ++ ++ pcppll: pcppll@17000100 { ++ compatible = "apm,xgene-pcppll-clock"; ++ #clock-cells = <1>; ++ clocks = <&refclk 0>; ++ clock-names = "pcppll"; ++ reg = <0x0 0x17000100 0x0 0x1000>; ++ clock-output-names = "pcppll"; ++ type = <0>; ++ }; ++ ++ socpll: socpll@17000120 { ++ compatible = "apm,xgene-socpll-clock"; ++ #clock-cells = <1>; ++ clocks = <&refclk 0>; ++ clock-names = "socpll"; ++ reg = <0x0 0x17000120 0x0 0x1000>; ++ clock-output-names = "socpll"; ++ type = <1>; ++ }; ++ ++ socplldiv2: socplldiv2 { ++ compatible = "fixed-factor-clock"; ++ #clock-cells = <1>; ++ clocks = <&socpll 0>; ++ clock-names = "socplldiv2"; ++ clock-mult = <1>; ++ clock-div = <2>; ++ clock-output-names = "socplldiv2"; ++ }; ++ ++ qmlclk: qmlclk { ++ compatible = "apm,xgene-device-clock"; ++ #clock-cells = <1>; ++ clocks = <&socplldiv2 0>; ++ clock-names = "qmlclk"; ++ reg = <0x0 0x1703C000 0x0 0x1000>; ++ reg-names = "csr-reg"; ++ clock-output-names = "qmlclk"; ++ }; ++ ++ ethclk: ethclk { ++ compatible = "apm,xgene-device-clock"; ++ #clock-cells = <1>; ++ clocks = <&socplldiv2 0>; ++ clock-names = "ethclk"; ++ reg = <0x0 0x17000000 0x0 0x1000>; ++ reg-names = "div-reg"; ++ divider-offset = <0x238>; ++ divider-width = <0x9>; ++ divider-shift = <0x0>; ++ clock-output-names = "ethclk"; ++ }; ++ ++ menetclk: menetclk { ++ compatible = "apm,xgene-device-clock"; ++ #clock-cells = <1>; ++ clocks = <ðclk 0>; ++ reg = <0x0 0x1702C000 0x0 0x1000>; ++ reg-names = "csr-reg"; ++ clock-output-names = "menetclk"; ++ }; ++ ++ sge0clk: sge0clk@1f21c000 { ++ compatible = "apm,xgene-device-clock"; ++ #clock-cells = <1>; ++ clocks = <&socplldiv2 0>; ++ reg = <0x0 0x1f21c000 0x0 0x1000>; ++ reg-names = "csr-reg"; ++ csr-mask = <0x3>; ++ clock-output-names = "sge0clk"; ++ }; ++ ++ xge0clk: xge0clk@1f61c000 { ++ compatible = "apm,xgene-device-clock"; ++ #clock-cells = <1>; ++ clocks = <&socplldiv2 0>; ++ reg = <0x0 0x1f61c000 0x0 0x1000>; ++ reg-names = "csr-reg"; ++ csr-mask = <0x3>; ++ clock-output-names = "xge0clk"; ++ }; ++ ++ sataphy1clk: sataphy1clk@1f21c000 { ++ compatible = "apm,xgene-device-clock"; ++ #clock-cells = <1>; ++ clocks = <&socplldiv2 0>; ++ reg = <0x0 0x1f21c000 0x0 0x1000>; ++ reg-names = "csr-reg"; ++ clock-output-names = "sataphy1clk"; ++ status = "disabled"; ++ csr-offset = <0x4>; ++ csr-mask = <0x00>; ++ enable-offset = <0x0>; ++ enable-mask = <0x06>; ++ }; ++ ++ sataphy2clk: sataphy1clk@1f22c000 { ++ compatible = "apm,xgene-device-clock"; ++ #clock-cells = <1>; ++ clocks = <&socplldiv2 0>; ++ reg = <0x0 0x1f22c000 0x0 0x1000>; ++ reg-names = "csr-reg"; ++ clock-output-names = "sataphy2clk"; ++ status = "ok"; ++ csr-offset = <0x4>; ++ csr-mask = <0x3a>; ++ enable-offset = <0x0>; ++ enable-mask = <0x06>; ++ }; ++ ++ sataphy3clk: sataphy1clk@1f23c000 { ++ compatible = "apm,xgene-device-clock"; ++ #clock-cells = <1>; ++ clocks = <&socplldiv2 0>; ++ reg = <0x0 0x1f23c000 0x0 0x1000>; ++ reg-names = "csr-reg"; ++ clock-output-names = "sataphy3clk"; ++ status = "ok"; ++ csr-offset = <0x4>; ++ csr-mask = <0x3a>; ++ enable-offset = <0x0>; ++ enable-mask = <0x06>; ++ }; ++ ++ sata01clk: sata01clk@1f21c000 { ++ compatible = "apm,xgene-device-clock"; ++ #clock-cells = <1>; ++ clocks = <&socplldiv2 0>; ++ reg = <0x0 0x1f21c000 0x0 0x1000>; ++ reg-names = "csr-reg"; ++ clock-output-names = "sata01clk"; ++ csr-offset = <0x4>; ++ csr-mask = <0x05>; ++ enable-offset = <0x0>; ++ enable-mask = <0x39>; ++ }; ++ ++ sata23clk: sata23clk@1f22c000 { ++ compatible = "apm,xgene-device-clock"; ++ #clock-cells = <1>; ++ clocks = <&socplldiv2 0>; ++ reg = <0x0 0x1f22c000 0x0 0x1000>; ++ reg-names = "csr-reg"; ++ clock-output-names = "sata23clk"; ++ csr-offset = <0x4>; ++ csr-mask = <0x05>; ++ enable-offset = <0x0>; ++ enable-mask = <0x39>; ++ }; ++ ++ sata45clk: sata45clk@1f23c000 { ++ compatible = "apm,xgene-device-clock"; ++ #clock-cells = <1>; ++ clocks = <&socplldiv2 0>; ++ reg = <0x0 0x1f23c000 0x0 0x1000>; ++ reg-names = "csr-reg"; ++ clock-output-names = "sata45clk"; ++ csr-offset = <0x4>; ++ csr-mask = <0x05>; ++ enable-offset = <0x0>; ++ enable-mask = <0x39>; ++ }; ++ ++ rtcclk: rtcclk@17000000 { ++ compatible = "apm,xgene-device-clock"; ++ #clock-cells = <1>; ++ clocks = <&socplldiv2 0>; ++ reg = <0x0 0x17000000 0x0 0x2000>; ++ reg-names = "csr-reg"; ++ csr-offset = <0xc>; ++ csr-mask = <0x2>; ++ enable-offset = <0x10>; ++ enable-mask = <0x2>; ++ clock-output-names = "rtcclk"; ++ }; ++ ++ rngpkaclk: rngpkaclk@17000000 { ++ compatible = "apm,xgene-device-clock"; ++ #clock-cells = <1>; ++ clocks = <&socplldiv2 0>; ++ reg = <0x0 0x17000000 0x0 0x2000>; ++ reg-names = "csr-reg"; ++ csr-offset = <0xc>; ++ csr-mask = <0x10>; ++ enable-offset = <0x10>; ++ enable-mask = <0x10>; ++ clock-output-names = "rngpkaclk"; ++ }; ++ ++ pcie0clk: pcie0clk@1f2bc000 { ++ status = "disabled"; ++ compatible = "apm,xgene-device-clock"; ++ #clock-cells = <1>; ++ clocks = <&socplldiv2 0>; ++ reg = <0x0 0x1f2bc000 0x0 0x1000>; ++ reg-names = "csr-reg"; ++ clock-output-names = "pcie0clk"; ++ }; ++ ++ pcie1clk: pcie1clk@1f2cc000 { ++ status = "disabled"; ++ compatible = "apm,xgene-device-clock"; ++ #clock-cells = <1>; ++ clocks = <&socplldiv2 0>; ++ reg = <0x0 0x1f2cc000 0x0 0x1000>; ++ reg-names = "csr-reg"; ++ clock-output-names = "pcie1clk"; ++ }; ++ ++ pcie2clk: pcie2clk@1f2dc000 { ++ status = "disabled"; ++ compatible = "apm,xgene-device-clock"; ++ #clock-cells = <1>; ++ clocks = <&socplldiv2 0>; ++ reg = <0x0 0x1f2dc000 0x0 0x1000>; ++ reg-names = "csr-reg"; ++ clock-output-names = "pcie2clk"; ++ }; ++ ++ pcie3clk: pcie3clk@1f50c000 { ++ status = "disabled"; ++ compatible = "apm,xgene-device-clock"; ++ #clock-cells = <1>; ++ clocks = <&socplldiv2 0>; ++ reg = <0x0 0x1f50c000 0x0 0x1000>; ++ reg-names = "csr-reg"; ++ clock-output-names = "pcie3clk"; ++ }; ++ ++ pcie4clk: pcie4clk@1f51c000 { ++ status = "disabled"; ++ compatible = "apm,xgene-device-clock"; ++ #clock-cells = <1>; ++ clocks = <&socplldiv2 0>; ++ reg = <0x0 0x1f51c000 0x0 0x1000>; ++ reg-names = "csr-reg"; ++ clock-output-names = "pcie4clk"; ++ }; ++ }; ++ ++ pcie0: pcie@1f2b0000 { ++ status = "disabled"; ++ device_type = "pci"; ++ compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie"; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ reg = < 0x00 0x1f2b0000 0x0 0x00010000 /* Controller registers */ ++ 0xe0 0xd0000000 0x0 0x00040000>; /* PCI config space */ ++ reg-names = "csr", "cfg"; ++ ranges = <0x01000000 0x00 0x00000000 0xe0 0x10000000 0x00 0x00010000 /* io */ ++ 0x02000000 0x00 0x80000000 0xe1 0x80000000 0x00 0x80000000>; /* mem */ ++ dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 ++ 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; ++ interrupt-map-mask = <0x0 0x0 0x0 0x7>; ++ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc2 0x1 ++ 0x0 0x0 0x0 0x2 &gic 0x0 0xc3 0x1 ++ 0x0 0x0 0x0 0x3 &gic 0x0 0xc4 0x1 ++ 0x0 0x0 0x0 0x4 &gic 0x0 0xc5 0x1>; ++ dma-coherent; ++ clocks = <&pcie0clk 0>; ++ }; ++ ++ pcie1: pcie@1f2c0000 { ++ status = "disabled"; ++ device_type = "pci"; ++ compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie"; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ reg = < 0x00 0x1f2c0000 0x0 0x00010000 /* Controller registers */ ++ 0xd0 0xd0000000 0x0 0x00040000>; /* PCI config space */ ++ reg-names = "csr", "cfg"; ++ ranges = <0x01000000 0x0 0x00000000 0xd0 0x10000000 0x00 0x00010000 /* io */ ++ 0x02000000 0x0 0x80000000 0xd1 0x80000000 0x00 0x80000000>; /* mem */ ++ dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 ++ 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; ++ interrupt-map-mask = <0x0 0x0 0x0 0x7>; ++ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc8 0x1 ++ 0x0 0x0 0x0 0x2 &gic 0x0 0xc9 0x1 ++ 0x0 0x0 0x0 0x3 &gic 0x0 0xca 0x1 ++ 0x0 0x0 0x0 0x4 &gic 0x0 0xcb 0x1>; ++ dma-coherent; ++ clocks = <&pcie1clk 0>; ++ }; ++ ++ pcie2: pcie@1f2d0000 { ++ status = "disabled"; ++ device_type = "pci"; ++ compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie"; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ reg = < 0x00 0x1f2d0000 0x0 0x00010000 /* Controller registers */ ++ 0x90 0xd0000000 0x0 0x00040000>; /* PCI config space */ ++ reg-names = "csr", "cfg"; ++ ranges = <0x01000000 0x0 0x00000000 0x90 0x10000000 0x0 0x00010000 /* io */ ++ 0x02000000 0x0 0x80000000 0x91 0x80000000 0x0 0x80000000>; /* mem */ ++ dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 ++ 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; ++ interrupt-map-mask = <0x0 0x0 0x0 0x7>; ++ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xce 0x1 ++ 0x0 0x0 0x0 0x2 &gic 0x0 0xcf 0x1 ++ 0x0 0x0 0x0 0x3 &gic 0x0 0xd0 0x1 ++ 0x0 0x0 0x0 0x4 &gic 0x0 0xd1 0x1>; ++ dma-coherent; ++ clocks = <&pcie2clk 0>; ++ }; ++ ++ pcie3: pcie@1f500000 { ++ status = "disabled"; ++ device_type = "pci"; ++ compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie"; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ reg = < 0x00 0x1f500000 0x0 0x00010000 /* Controller registers */ ++ 0xa0 0xd0000000 0x0 0x00040000>; /* PCI config space */ ++ reg-names = "csr", "cfg"; ++ ranges = <0x01000000 0x0 0x00000000 0xa0 0x10000000 0x0 0x00010000 /* io */ ++ 0x02000000 0x0 0x80000000 0xa1 0x80000000 0x0 0x80000000>; /* mem */ ++ dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 ++ 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; ++ interrupt-map-mask = <0x0 0x0 0x0 0x7>; ++ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xd4 0x1 ++ 0x0 0x0 0x0 0x2 &gic 0x0 0xd5 0x1 ++ 0x0 0x0 0x0 0x3 &gic 0x0 0xd6 0x1 ++ 0x0 0x0 0x0 0x4 &gic 0x0 0xd7 0x1>; ++ dma-coherent; ++ clocks = <&pcie3clk 0>; ++ }; ++ ++ pcie4: pcie@1f510000 { ++ status = "disabled"; ++ device_type = "pci"; ++ compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie"; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ reg = < 0x00 0x1f510000 0x0 0x00010000 /* Controller registers */ ++ 0xc0 0xd0000000 0x0 0x00200000>; /* PCI config space */ ++ reg-names = "csr", "cfg"; ++ ranges = <0x01000000 0x0 0x00000000 0xc0 0x10000000 0x0 0x00010000 /* io */ ++ 0x02000000 0x0 0x80000000 0xc1 0x80000000 0x0 0x80000000>; /* mem */ ++ dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000 ++ 0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>; ++ interrupt-map-mask = <0x0 0x0 0x0 0x7>; ++ interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xda 0x1 ++ 0x0 0x0 0x0 0x2 &gic 0x0 0xdb 0x1 ++ 0x0 0x0 0x0 0x3 &gic 0x0 0xdc 0x1 ++ 0x0 0x0 0x0 0x4 &gic 0x0 0xdd 0x1>; ++ dma-coherent; ++ clocks = <&pcie4clk 0>; ++ }; ++ ++ serial0: serial@1c020000 { ++ status = "disabled"; ++ device_type = "serial"; ++ compatible = "ns16550a"; ++ reg = <0 0x1c020000 0x0 0x1000>; ++ reg-shift = <2>; ++ clock-frequency = <10000000>; /* Updated by bootloader */ ++ interrupt-parent = <&gic>; ++ interrupts = <0x0 0x4c 0x4>; ++ }; ++ ++ serial1: serial@1c021000 { ++ status = "disabled"; ++ device_type = "serial"; ++ compatible = "ns16550a"; ++ reg = <0 0x1c021000 0x0 0x1000>; ++ reg-shift = <2>; ++ clock-frequency = <10000000>; /* Updated by bootloader */ ++ interrupt-parent = <&gic>; ++ interrupts = <0x0 0x4d 0x4>; ++ }; ++ ++ serial2: serial@1c022000 { ++ status = "disabled"; ++ device_type = "serial"; ++ compatible = "ns16550a"; ++ reg = <0 0x1c022000 0x0 0x1000>; ++ reg-shift = <2>; ++ clock-frequency = <10000000>; /* Updated by bootloader */ ++ interrupt-parent = <&gic>; ++ interrupts = <0x0 0x4e 0x4>; ++ }; ++ ++ serial3: serial@1c023000 { ++ status = "disabled"; ++ device_type = "serial"; ++ compatible = "ns16550a"; ++ reg = <0 0x1c023000 0x0 0x1000>; ++ reg-shift = <2>; ++ clock-frequency = <10000000>; /* Updated by bootloader */ ++ interrupt-parent = <&gic>; ++ interrupts = <0x0 0x4f 0x4>; ++ }; ++ ++ phy1: phy@1f21a000 { ++ compatible = "apm,xgene-phy"; ++ reg = <0x0 0x1f21a000 0x0 0x100>; ++ #phy-cells = <1>; ++ clocks = <&sataphy1clk 0>; ++ status = "disabled"; ++ apm,tx-boost-gain = <30 30 30 30 30 30>; ++ apm,tx-eye-tuning = <2 10 10 2 10 10>; ++ }; ++ ++ phy2: phy@1f22a000 { ++ compatible = "apm,xgene-phy"; ++ reg = <0x0 0x1f22a000 0x0 0x100>; ++ #phy-cells = <1>; ++ clocks = <&sataphy2clk 0>; ++ status = "ok"; ++ apm,tx-boost-gain = <30 30 30 30 30 30>; ++ apm,tx-eye-tuning = <1 10 10 2 10 10>; ++ }; ++ ++ phy3: phy@1f23a000 { ++ compatible = "apm,xgene-phy"; ++ reg = <0x0 0x1f23a000 0x0 0x100>; ++ #phy-cells = <1>; ++ clocks = <&sataphy3clk 0>; ++ status = "ok"; ++ apm,tx-boost-gain = <31 31 31 31 31 31>; ++ apm,tx-eye-tuning = <2 10 10 2 10 10>; ++ }; ++ ++ sata1: sata@1a000000 { ++ compatible = "apm,xgene-ahci"; ++ reg = <0x0 0x1a000000 0x0 0x1000>, ++ <0x0 0x1f210000 0x0 0x1000>, ++ <0x0 0x1f21d000 0x0 0x1000>, ++ <0x0 0x1f21e000 0x0 0x1000>, ++ <0x0 0x1f217000 0x0 0x1000>; ++ interrupts = <0x0 0x86 0x4>; ++ dma-coherent; ++ status = "disabled"; ++ clocks = <&sata01clk 0>; ++ phys = <&phy1 0>; ++ phy-names = "sata-phy"; ++ }; ++ ++ sata2: sata@1a400000 { ++ compatible = "apm,xgene-ahci"; ++ reg = <0x0 0x1a400000 0x0 0x1000>, ++ <0x0 0x1f220000 0x0 0x1000>, ++ <0x0 0x1f22d000 0x0 0x1000>, ++ <0x0 0x1f22e000 0x0 0x1000>, ++ <0x0 0x1f227000 0x0 0x1000>; ++ interrupts = <0x0 0x87 0x4>; ++ dma-coherent; ++ status = "ok"; ++ clocks = <&sata23clk 0>; ++ phys = <&phy2 0>; ++ phy-names = "sata-phy"; ++ }; ++ ++ sata3: sata@1a800000 { ++ compatible = "apm,xgene-ahci"; ++ reg = <0x0 0x1a800000 0x0 0x1000>, ++ <0x0 0x1f230000 0x0 0x1000>, ++ <0x0 0x1f23d000 0x0 0x1000>, ++ <0x0 0x1f23e000 0x0 0x1000>; ++ interrupts = <0x0 0x88 0x4>; ++ dma-coherent; ++ status = "ok"; ++ clocks = <&sata45clk 0>; ++ phys = <&phy3 0>; ++ phy-names = "sata-phy"; ++ }; ++ ++ rtc: rtc@10510000 { ++ compatible = "apm,xgene-rtc"; ++ reg = <0x0 0x10510000 0x0 0x400>; ++ interrupts = <0x0 0x46 0x4>; ++ #clock-cells = <1>; ++ clocks = <&rtcclk 0>; ++ }; ++ ++ menet: ethernet@17020000 { ++ compatible = "apm,xgene-enet"; ++ status = "disabled"; ++ reg = <0x0 0x17020000 0x0 0xd100>, ++ <0x0 0X17030000 0x0 0Xc300>, ++ <0x0 0X10000000 0x0 0X200>; ++ reg-names = "enet_csr", "ring_csr", "ring_cmd"; ++ interrupts = <0x0 0x3c 0x4>; ++ dma-coherent; ++ clocks = <&menetclk 0>; ++ /* mac address will be overwritten by the bootloader */ ++ local-mac-address = [00 00 00 00 00 00]; ++ phy-connection-type = "rgmii"; ++ phy-handle = <&menetphy>; ++ mdio { ++ compatible = "apm,xgene-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ menetphy: menetphy@3 { ++ compatible = "ethernet-phy-id001c.c915"; ++ reg = <0x3>; ++ }; ++ ++ }; ++ }; ++ ++ sgenet0: ethernet@1f210000 { ++ compatible = "apm,xgene-enet"; ++ status = "disabled"; ++ reg = <0x0 0x1f210000 0x0 0xd100>, ++ <0x0 0x1f200000 0x0 0Xc300>, ++ <0x0 0x1B000000 0x0 0X200>; ++ reg-names = "enet_csr", "ring_csr", "ring_cmd"; ++ interrupts = <0x0 0xA0 0x4>; ++ dma-coherent; ++ clocks = <&sge0clk 0>; ++ local-mac-address = [00 00 00 00 00 00]; ++ phy-connection-type = "sgmii"; ++ }; ++ ++ xgenet: ethernet@1f610000 { ++ compatible = "apm,xgene-enet"; ++ status = "disabled"; ++ reg = <0x0 0x1f610000 0x0 0xd100>, ++ <0x0 0x1f600000 0x0 0Xc300>, ++ <0x0 0x18000000 0x0 0X200>; ++ reg-names = "enet_csr", "ring_csr", "ring_cmd"; ++ interrupts = <0x0 0x60 0x4>; ++ dma-coherent; ++ clocks = <&xge0clk 0>; ++ /* mac address will be overwritten by the bootloader */ ++ local-mac-address = [00 00 00 00 00 00]; ++ phy-connection-type = "xgmii"; ++ }; ++ ++ rng: rng@10520000 { ++ compatible = "apm,xgene-rng"; ++ reg = <0x0 0x10520000 0x0 0x100>; ++ interrupts = <0x0 0x41 0x4>; ++ clocks = <&rngpkaclk 0>; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/arm/Makefile b/arch/arm64/boot/dts/arm/Makefile +new file mode 100644 +index 0000000..301a0da +--- /dev/null ++++ b/arch/arm64/boot/dts/arm/Makefile +@@ -0,0 +1,7 @@ ++dtb-$(CONFIG_ARCH_VEXPRESS) += foundation-v8.dtb ++dtb-$(CONFIG_ARCH_VEXPRESS) += juno.dtb ++dtb-$(CONFIG_ARCH_VEXPRESS) += rtsm_ve-aemv8a.dtb ++ ++always := $(dtb-y) ++subdir-y := $(dts-dirs) ++clean-files := *.dtb +diff --git a/arch/arm64/boot/dts/arm/foundation-v8.dts b/arch/arm64/boot/dts/arm/foundation-v8.dts +new file mode 100644 +index 0000000..4eac8dc +--- /dev/null ++++ b/arch/arm64/boot/dts/arm/foundation-v8.dts +@@ -0,0 +1,240 @@ ++/* ++ * ARM Ltd. ++ * ++ * ARMv8 Foundation model DTS ++ */ ++ ++/dts-v1/; ++ ++/memreserve/ 0x80000000 0x00010000; ++ ++/ { ++ model = "Foundation-v8A"; ++ compatible = "arm,foundation-aarch64", "arm,vexpress"; ++ interrupt-parent = <&gic>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ chosen { }; ++ ++ aliases { ++ serial0 = &v2m_serial0; ++ serial1 = &v2m_serial1; ++ serial2 = &v2m_serial2; ++ serial3 = &v2m_serial3; ++ }; ++ ++ cpus { ++ #address-cells = <2>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,armv8"; ++ reg = <0x0 0x0>; ++ enable-method = "spin-table"; ++ cpu-release-addr = <0x0 0x8000fff8>; ++ next-level-cache = <&L2_0>; ++ }; ++ cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,armv8"; ++ reg = <0x0 0x1>; ++ enable-method = "spin-table"; ++ cpu-release-addr = <0x0 0x8000fff8>; ++ next-level-cache = <&L2_0>; ++ }; ++ cpu@2 { ++ device_type = "cpu"; ++ compatible = "arm,armv8"; ++ reg = <0x0 0x2>; ++ enable-method = "spin-table"; ++ cpu-release-addr = <0x0 0x8000fff8>; ++ next-level-cache = <&L2_0>; ++ }; ++ cpu@3 { ++ device_type = "cpu"; ++ compatible = "arm,armv8"; ++ reg = <0x0 0x3>; ++ enable-method = "spin-table"; ++ cpu-release-addr = <0x0 0x8000fff8>; ++ next-level-cache = <&L2_0>; ++ }; ++ ++ L2_0: l2-cache0 { ++ compatible = "cache"; ++ }; ++ }; ++ ++ memory@80000000 { ++ device_type = "memory"; ++ reg = <0x00000000 0x80000000 0 0x80000000>, ++ <0x00000008 0x80000000 0 0x80000000>; ++ }; ++ ++ gic: interrupt-controller@2c001000 { ++ compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ reg = <0x0 0x2c001000 0 0x1000>, ++ <0x0 0x2c002000 0 0x1000>, ++ <0x0 0x2c004000 0 0x2000>, ++ <0x0 0x2c006000 0 0x2000>; ++ interrupts = <1 9 0xf04>; ++ }; ++ ++ timer { ++ compatible = "arm,armv8-timer"; ++ interrupts = <1 13 0xf08>, ++ <1 14 0xf08>, ++ <1 11 0xf08>, ++ <1 10 0xf08>; ++ clock-frequency = <100000000>; ++ }; ++ ++ pmu { ++ compatible = "arm,armv8-pmuv3"; ++ interrupts = <0 60 4>, ++ <0 61 4>, ++ <0 62 4>, ++ <0 63 4>; ++ }; ++ ++ smb { ++ compatible = "arm,vexpress,v2m-p1", "simple-bus"; ++ arm,v2m-memory-map = "rs1"; ++ #address-cells = <2>; /* SMB chipselect number and offset */ ++ #size-cells = <1>; ++ ++ ranges = <0 0 0 0x08000000 0x04000000>, ++ <1 0 0 0x14000000 0x04000000>, ++ <2 0 0 0x18000000 0x04000000>, ++ <3 0 0 0x1c000000 0x04000000>, ++ <4 0 0 0x0c000000 0x04000000>, ++ <5 0 0 0x10000000 0x04000000>; ++ ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 63>; ++ interrupt-map = <0 0 0 &gic 0 0 4>, ++ <0 0 1 &gic 0 1 4>, ++ <0 0 2 &gic 0 2 4>, ++ <0 0 3 &gic 0 3 4>, ++ <0 0 4 &gic 0 4 4>, ++ <0 0 5 &gic 0 5 4>, ++ <0 0 6 &gic 0 6 4>, ++ <0 0 7 &gic 0 7 4>, ++ <0 0 8 &gic 0 8 4>, ++ <0 0 9 &gic 0 9 4>, ++ <0 0 10 &gic 0 10 4>, ++ <0 0 11 &gic 0 11 4>, ++ <0 0 12 &gic 0 12 4>, ++ <0 0 13 &gic 0 13 4>, ++ <0 0 14 &gic 0 14 4>, ++ <0 0 15 &gic 0 15 4>, ++ <0 0 16 &gic 0 16 4>, ++ <0 0 17 &gic 0 17 4>, ++ <0 0 18 &gic 0 18 4>, ++ <0 0 19 &gic 0 19 4>, ++ <0 0 20 &gic 0 20 4>, ++ <0 0 21 &gic 0 21 4>, ++ <0 0 22 &gic 0 22 4>, ++ <0 0 23 &gic 0 23 4>, ++ <0 0 24 &gic 0 24 4>, ++ <0 0 25 &gic 0 25 4>, ++ <0 0 26 &gic 0 26 4>, ++ <0 0 27 &gic 0 27 4>, ++ <0 0 28 &gic 0 28 4>, ++ <0 0 29 &gic 0 29 4>, ++ <0 0 30 &gic 0 30 4>, ++ <0 0 31 &gic 0 31 4>, ++ <0 0 32 &gic 0 32 4>, ++ <0 0 33 &gic 0 33 4>, ++ <0 0 34 &gic 0 34 4>, ++ <0 0 35 &gic 0 35 4>, ++ <0 0 36 &gic 0 36 4>, ++ <0 0 37 &gic 0 37 4>, ++ <0 0 38 &gic 0 38 4>, ++ <0 0 39 &gic 0 39 4>, ++ <0 0 40 &gic 0 40 4>, ++ <0 0 41 &gic 0 41 4>, ++ <0 0 42 &gic 0 42 4>; ++ ++ ethernet@2,02000000 { ++ compatible = "smsc,lan91c111"; ++ reg = <2 0x02000000 0x10000>; ++ interrupts = <15>; ++ }; ++ ++ v2m_clk24mhz: clk24mhz { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24000000>; ++ clock-output-names = "v2m:clk24mhz"; ++ }; ++ ++ v2m_refclk1mhz: refclk1mhz { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <1000000>; ++ clock-output-names = "v2m:refclk1mhz"; ++ }; ++ ++ v2m_refclk32khz: refclk32khz { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <32768>; ++ clock-output-names = "v2m:refclk32khz"; ++ }; ++ ++ iofpga@3,00000000 { ++ compatible = "arm,amba-bus", "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0 3 0 0x200000>; ++ ++ v2m_sysreg: sysreg@010000 { ++ compatible = "arm,vexpress-sysreg"; ++ reg = <0x010000 0x1000>; ++ }; ++ ++ v2m_serial0: uart@090000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x090000 0x1000>; ++ interrupts = <5>; ++ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; ++ clock-names = "uartclk", "apb_pclk"; ++ }; ++ ++ v2m_serial1: uart@0a0000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x0a0000 0x1000>; ++ interrupts = <6>; ++ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; ++ clock-names = "uartclk", "apb_pclk"; ++ }; ++ ++ v2m_serial2: uart@0b0000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x0b0000 0x1000>; ++ interrupts = <7>; ++ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; ++ clock-names = "uartclk", "apb_pclk"; ++ }; ++ ++ v2m_serial3: uart@0c0000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x0c0000 0x1000>; ++ interrupts = <8>; ++ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; ++ clock-names = "uartclk", "apb_pclk"; ++ }; ++ ++ virtio_block@0130000 { ++ compatible = "virtio,mmio"; ++ reg = <0x130000 0x200>; ++ interrupts = <42>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/arm/juno-clocks.dtsi b/arch/arm64/boot/dts/arm/juno-clocks.dtsi +new file mode 100644 +index 0000000..c9b89ef +--- /dev/null ++++ b/arch/arm64/boot/dts/arm/juno-clocks.dtsi +@@ -0,0 +1,44 @@ ++/* ++ * ARM Juno Platform clocks ++ * ++ * Copyright (c) 2013-2014 ARM Ltd ++ * ++ * This file is licensed under a dual GPLv2 or BSD license. ++ * ++ */ ++ ++ /* SoC fixed clocks */ ++ soc_uartclk: refclk7273800hz { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <7273800>; ++ clock-output-names = "juno:uartclk"; ++ }; ++ ++ soc_usb48mhz: clk48mhz { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <48000000>; ++ clock-output-names = "clk48mhz"; ++ }; ++ ++ soc_smc50mhz: clk50mhz { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <50000000>; ++ clock-output-names = "smc_clk"; ++ }; ++ ++ soc_refclk100mhz: refclk100mhz { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <100000000>; ++ clock-output-names = "apb_pclk"; ++ }; ++ ++ soc_faxiclk: refclk533mhz { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <533000000>; ++ clock-output-names = "faxi_clk"; ++ }; +diff --git a/arch/arm64/boot/dts/arm/juno-motherboard.dtsi b/arch/arm64/boot/dts/arm/juno-motherboard.dtsi +new file mode 100644 +index 0000000..c138b95 +--- /dev/null ++++ b/arch/arm64/boot/dts/arm/juno-motherboard.dtsi +@@ -0,0 +1,129 @@ ++/* ++ * ARM Juno Platform motherboard peripherals ++ * ++ * Copyright (c) 2013-2014 ARM Ltd ++ * ++ * This file is licensed under a dual GPLv2 or BSD license. ++ * ++ */ ++ ++ mb_clk24mhz: clk24mhz { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24000000>; ++ clock-output-names = "juno_mb:clk24mhz"; ++ }; ++ ++ mb_clk25mhz: clk25mhz { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <25000000>; ++ clock-output-names = "juno_mb:clk25mhz"; ++ }; ++ ++ motherboard { ++ compatible = "arm,vexpress,v2p-p1", "simple-bus"; ++ #address-cells = <2>; /* SMB chipselect number and offset */ ++ #size-cells = <1>; ++ #interrupt-cells = <1>; ++ ranges; ++ model = "V2M-Juno"; ++ arm,hbi = <0x252>; ++ arm,vexpress,site = <0>; ++ arm,v2m-memory-map = "rs1"; ++ ++ mb_fixed_3v3: fixedregulator@0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "MCC_SB_3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ }; ++ ++ ethernet@2,00000000 { ++ compatible = "smsc,lan9118", "smsc,lan9115"; ++ reg = <2 0x00000000 0x10000>; ++ interrupts = <3>; ++ phy-mode = "mii"; ++ reg-io-width = <4>; ++ smsc,irq-active-high; ++ smsc,irq-push-pull; ++ clocks = <&mb_clk25mhz>; ++ vdd33a-supply = <&mb_fixed_3v3>; ++ vddvario-supply = <&mb_fixed_3v3>; ++ }; ++ ++ usb@5,00000000 { ++ compatible = "nxp,usb-isp1763"; ++ reg = <5 0x00000000 0x20000>; ++ bus-width = <16>; ++ interrupts = <4>; ++ }; ++ ++ iofpga@3,00000000 { ++ compatible = "arm,amba-bus", "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0 3 0 0x200000>; ++ ++ mmci@050000 { ++ compatible = "arm,pl180", "arm,primecell"; ++ reg = <0x050000 0x1000>; ++ interrupts = <5>; ++ /* cd-gpios = <&v2m_mmc_gpios 0 0>; ++ wp-gpios = <&v2m_mmc_gpios 1 0>; */ ++ max-frequency = <12000000>; ++ vmmc-supply = <&mb_fixed_3v3>; ++ clocks = <&mb_clk24mhz>, <&soc_smc50mhz>; ++ clock-names = "mclk", "apb_pclk"; ++ }; ++ ++ kmi@060000 { ++ compatible = "arm,pl050", "arm,primecell"; ++ reg = <0x060000 0x1000>; ++ interrupts = <8>; ++ clocks = <&mb_clk24mhz>, <&soc_smc50mhz>; ++ clock-names = "KMIREFCLK", "apb_pclk"; ++ }; ++ ++ kmi@070000 { ++ compatible = "arm,pl050", "arm,primecell"; ++ reg = <0x070000 0x1000>; ++ interrupts = <8>; ++ clocks = <&mb_clk24mhz>, <&soc_smc50mhz>; ++ clock-names = "KMIREFCLK", "apb_pclk"; ++ }; ++ ++ wdt@0f0000 { ++ compatible = "arm,sp805", "arm,primecell"; ++ reg = <0x0f0000 0x10000>; ++ interrupts = <7>; ++ clocks = <&mb_clk24mhz>, <&soc_smc50mhz>; ++ clock-names = "wdogclk", "apb_pclk"; ++ }; ++ ++ v2m_timer01: timer@110000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ reg = <0x110000 0x10000>; ++ interrupts = <9>; ++ clocks = <&mb_clk24mhz>, <&soc_smc50mhz>; ++ clock-names = "timclken1", "apb_pclk"; ++ }; ++ ++ v2m_timer23: timer@120000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ reg = <0x120000 0x10000>; ++ interrupts = <9>; ++ clocks = <&mb_clk24mhz>, <&soc_smc50mhz>; ++ clock-names = "timclken1", "apb_pclk"; ++ }; ++ ++ rtc@170000 { ++ compatible = "arm,pl031", "arm,primecell"; ++ reg = <0x170000 0x10000>; ++ interrupts = <0>; ++ clocks = <&soc_smc50mhz>; ++ clock-names = "apb_pclk"; ++ }; ++ }; ++ }; +diff --git a/arch/arm64/boot/dts/arm/juno.dts b/arch/arm64/boot/dts/arm/juno.dts +new file mode 100644 +index 0000000..5e9110a +--- /dev/null ++++ b/arch/arm64/boot/dts/arm/juno.dts +@@ -0,0 +1,238 @@ ++/* ++ * ARM Ltd. Juno Platform ++ * ++ * Copyright (c) 2013-2014 ARM Ltd. ++ * ++ * This file is licensed under a dual GPLv2 or BSD license. ++ */ ++ ++/dts-v1/; ++ ++#include ++ ++/ { ++ model = "ARM Juno development board (r0)"; ++ compatible = "arm,juno", "arm,vexpress"; ++ interrupt-parent = <&gic>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ aliases { ++ serial0 = &soc_uart0; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ psci { ++ compatible = "arm,psci-0.2"; ++ method = "smc"; ++ }; ++ ++ cpus { ++ #address-cells = <2>; ++ #size-cells = <0>; ++ ++ A57_0: cpu@0 { ++ compatible = "arm,cortex-a57","arm,armv8"; ++ reg = <0x0 0x0>; ++ device_type = "cpu"; ++ enable-method = "psci"; ++ next-level-cache = <&A57_L2>; ++ }; ++ ++ A57_1: cpu@1 { ++ compatible = "arm,cortex-a57","arm,armv8"; ++ reg = <0x0 0x1>; ++ device_type = "cpu"; ++ enable-method = "psci"; ++ next-level-cache = <&A57_L2>; ++ }; ++ ++ A53_0: cpu@100 { ++ compatible = "arm,cortex-a53","arm,armv8"; ++ reg = <0x0 0x100>; ++ device_type = "cpu"; ++ enable-method = "psci"; ++ next-level-cache = <&A53_L2>; ++ }; ++ ++ A53_1: cpu@101 { ++ compatible = "arm,cortex-a53","arm,armv8"; ++ reg = <0x0 0x101>; ++ device_type = "cpu"; ++ enable-method = "psci"; ++ next-level-cache = <&A53_L2>; ++ }; ++ ++ A53_2: cpu@102 { ++ compatible = "arm,cortex-a53","arm,armv8"; ++ reg = <0x0 0x102>; ++ device_type = "cpu"; ++ enable-method = "psci"; ++ next-level-cache = <&A53_L2>; ++ }; ++ ++ A53_3: cpu@103 { ++ compatible = "arm,cortex-a53","arm,armv8"; ++ reg = <0x0 0x103>; ++ device_type = "cpu"; ++ enable-method = "psci"; ++ next-level-cache = <&A53_L2>; ++ }; ++ ++ A57_L2: l2-cache0 { ++ compatible = "cache"; ++ }; ++ ++ A53_L2: l2-cache1 { ++ compatible = "cache"; ++ }; ++ }; ++ ++ memory@80000000 { ++ device_type = "memory"; ++ /* last 16MB of the first memory area is reserved for secure world use by firmware */ ++ reg = <0x00000000 0x80000000 0x0 0x7f000000>, ++ <0x00000008 0x80000000 0x1 0x80000000>; ++ }; ++ ++ gic: interrupt-controller@2c001000 { ++ compatible = "arm,gic-400", "arm,cortex-a15-gic"; ++ reg = <0x0 0x2c010000 0 0x1000>, ++ <0x0 0x2c02f000 0 0x2000>, ++ <0x0 0x2c04f000 0 0x2000>, ++ <0x0 0x2c06f000 0 0x2000>; ++ #address-cells = <0>; ++ #interrupt-cells = <3>; ++ interrupt-controller; ++ interrupts = ; ++ }; ++ ++ timer { ++ compatible = "arm,armv8-timer"; ++ interrupts = , ++ , ++ , ++ ; ++ }; ++ ++ pmu { ++ compatible = "arm,armv8-pmuv3"; ++ interrupts = , ++ , ++ , ++ , ++ , ++ ; ++ interrupt-affinity = <&A57_0>, ++ <&A57_1>, ++ <&A53_0>, ++ <&A53_1>, ++ <&A53_2>, ++ <&A53_3>; ++ }; ++ ++ /include/ "juno-clocks.dtsi" ++ ++ dma@7ff00000 { ++ compatible = "arm,pl330", "arm,primecell"; ++ reg = <0x0 0x7ff00000 0 0x1000>; ++ #dma-cells = <1>; ++ #dma-channels = <8>; ++ #dma-requests = <32>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&soc_faxiclk>; ++ clock-names = "apb_pclk"; ++ }; ++ ++ soc_uart0: uart@7ff80000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x0 0x7ff80000 0x0 0x1000>; ++ interrupts = ; ++ clocks = <&soc_uartclk>, <&soc_refclk100mhz>; ++ clock-names = "uartclk", "apb_pclk"; ++ }; ++ ++ i2c@7ffa0000 { ++ compatible = "snps,designware-i2c"; ++ reg = <0x0 0x7ffa0000 0x0 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = ; ++ clock-frequency = <400000>; ++ i2c-sda-hold-time-ns = <500>; ++ clocks = <&soc_smc50mhz>; ++ ++ dvi0: dvi-transmitter@70 { ++ compatible = "nxp,tda998x"; ++ reg = <0x70>; ++ }; ++ ++ dvi1: dvi-transmitter@71 { ++ compatible = "nxp,tda998x"; ++ reg = <0x71>; ++ }; ++ }; ++ ++ ohci@7ffb0000 { ++ compatible = "generic-ohci"; ++ reg = <0x0 0x7ffb0000 0x0 0x10000>; ++ interrupts = ; ++ clocks = <&soc_usb48mhz>; ++ }; ++ ++ ehci@7ffc0000 { ++ compatible = "generic-ehci"; ++ reg = <0x0 0x7ffc0000 0x0 0x10000>; ++ interrupts = ; ++ clocks = <&soc_usb48mhz>; ++ }; ++ ++ memory-controller@7ffd0000 { ++ compatible = "arm,pl354", "arm,primecell"; ++ reg = <0 0x7ffd0000 0 0x1000>; ++ interrupts = , ++ ; ++ clocks = <&soc_smc50mhz>; ++ clock-names = "apb_pclk"; ++ }; ++ ++ smb { ++ compatible = "simple-bus"; ++ #address-cells = <2>; ++ #size-cells = <1>; ++ ranges = <0 0 0 0x08000000 0x04000000>, ++ <1 0 0 0x14000000 0x04000000>, ++ <2 0 0 0x18000000 0x04000000>, ++ <3 0 0 0x1c000000 0x04000000>, ++ <4 0 0 0x0c000000 0x04000000>, ++ <5 0 0 0x10000000 0x04000000>; ++ ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 15>; ++ interrupt-map = <0 0 0 &gic 0 68 IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 1 &gic 0 69 IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 2 &gic 0 70 IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 3 &gic 0 160 IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 4 &gic 0 161 IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 5 &gic 0 162 IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 6 &gic 0 163 IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 7 &gic 0 164 IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 8 &gic 0 165 IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 9 &gic 0 166 IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 10 &gic 0 167 IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 11 &gic 0 168 IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 12 &gic 0 169 IRQ_TYPE_LEVEL_HIGH>; ++ ++ /include/ "juno-motherboard.dtsi" ++ }; ++}; +diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts +new file mode 100644 +index 0000000..20addab +--- /dev/null ++++ b/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts +@@ -0,0 +1,167 @@ ++/* ++ * ARM Ltd. Fast Models ++ * ++ * Architecture Envelope Model (AEM) ARMv8-A ++ * ARMAEMv8AMPCT ++ * ++ * RTSM_VE_AEMv8A.lisa ++ */ ++ ++/dts-v1/; ++ ++/memreserve/ 0x80000000 0x00010000; ++ ++/ { ++ model = "RTSM_VE_AEMv8A"; ++ compatible = "arm,rtsm_ve,aemv8a", "arm,vexpress"; ++ interrupt-parent = <&gic>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ chosen { }; ++ ++ aliases { ++ serial0 = &v2m_serial0; ++ serial1 = &v2m_serial1; ++ serial2 = &v2m_serial2; ++ serial3 = &v2m_serial3; ++ }; ++ ++ cpus { ++ #address-cells = <2>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,armv8"; ++ reg = <0x0 0x0>; ++ enable-method = "spin-table"; ++ cpu-release-addr = <0x0 0x8000fff8>; ++ next-level-cache = <&L2_0>; ++ }; ++ cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,armv8"; ++ reg = <0x0 0x1>; ++ enable-method = "spin-table"; ++ cpu-release-addr = <0x0 0x8000fff8>; ++ next-level-cache = <&L2_0>; ++ }; ++ cpu@2 { ++ device_type = "cpu"; ++ compatible = "arm,armv8"; ++ reg = <0x0 0x2>; ++ enable-method = "spin-table"; ++ cpu-release-addr = <0x0 0x8000fff8>; ++ next-level-cache = <&L2_0>; ++ }; ++ cpu@3 { ++ device_type = "cpu"; ++ compatible = "arm,armv8"; ++ reg = <0x0 0x3>; ++ enable-method = "spin-table"; ++ cpu-release-addr = <0x0 0x8000fff8>; ++ next-level-cache = <&L2_0>; ++ }; ++ ++ L2_0: l2-cache0 { ++ compatible = "cache"; ++ }; ++ }; ++ ++ memory@80000000 { ++ device_type = "memory"; ++ reg = <0x00000000 0x80000000 0 0x80000000>, ++ <0x00000008 0x80000000 0 0x80000000>; ++ }; ++ ++ gic: interrupt-controller@2c001000 { ++ compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ reg = <0x0 0x2c001000 0 0x1000>, ++ <0x0 0x2c002000 0 0x1000>, ++ <0x0 0x2c004000 0 0x2000>, ++ <0x0 0x2c006000 0 0x2000>; ++ interrupts = <1 9 0xf04>; ++ }; ++ ++ timer { ++ compatible = "arm,armv8-timer"; ++ interrupts = <1 13 0xf08>, ++ <1 14 0xf08>, ++ <1 11 0xf08>, ++ <1 10 0xf08>; ++ clock-frequency = <100000000>; ++ }; ++ ++ pmu { ++ compatible = "arm,armv8-pmuv3"; ++ interrupts = <0 60 4>, ++ <0 61 4>, ++ <0 62 4>, ++ <0 63 4>; ++ }; ++ ++ smb { ++ compatible = "simple-bus"; ++ ++ #address-cells = <2>; ++ #size-cells = <1>; ++ ranges = <0 0 0 0x08000000 0x04000000>, ++ <1 0 0 0x14000000 0x04000000>, ++ <2 0 0 0x18000000 0x04000000>, ++ <3 0 0 0x1c000000 0x04000000>, ++ <4 0 0 0x0c000000 0x04000000>, ++ <5 0 0 0x10000000 0x04000000>; ++ ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 63>; ++ interrupt-map = <0 0 0 &gic 0 0 4>, ++ <0 0 1 &gic 0 1 4>, ++ <0 0 2 &gic 0 2 4>, ++ <0 0 3 &gic 0 3 4>, ++ <0 0 4 &gic 0 4 4>, ++ <0 0 5 &gic 0 5 4>, ++ <0 0 6 &gic 0 6 4>, ++ <0 0 7 &gic 0 7 4>, ++ <0 0 8 &gic 0 8 4>, ++ <0 0 9 &gic 0 9 4>, ++ <0 0 10 &gic 0 10 4>, ++ <0 0 11 &gic 0 11 4>, ++ <0 0 12 &gic 0 12 4>, ++ <0 0 13 &gic 0 13 4>, ++ <0 0 14 &gic 0 14 4>, ++ <0 0 15 &gic 0 15 4>, ++ <0 0 16 &gic 0 16 4>, ++ <0 0 17 &gic 0 17 4>, ++ <0 0 18 &gic 0 18 4>, ++ <0 0 19 &gic 0 19 4>, ++ <0 0 20 &gic 0 20 4>, ++ <0 0 21 &gic 0 21 4>, ++ <0 0 22 &gic 0 22 4>, ++ <0 0 23 &gic 0 23 4>, ++ <0 0 24 &gic 0 24 4>, ++ <0 0 25 &gic 0 25 4>, ++ <0 0 26 &gic 0 26 4>, ++ <0 0 27 &gic 0 27 4>, ++ <0 0 28 &gic 0 28 4>, ++ <0 0 29 &gic 0 29 4>, ++ <0 0 30 &gic 0 30 4>, ++ <0 0 31 &gic 0 31 4>, ++ <0 0 32 &gic 0 32 4>, ++ <0 0 33 &gic 0 33 4>, ++ <0 0 34 &gic 0 34 4>, ++ <0 0 35 &gic 0 35 4>, ++ <0 0 36 &gic 0 36 4>, ++ <0 0 37 &gic 0 37 4>, ++ <0 0 38 &gic 0 38 4>, ++ <0 0 39 &gic 0 39 4>, ++ <0 0 40 &gic 0 40 4>, ++ <0 0 41 &gic 0 41 4>, ++ <0 0 42 &gic 0 42 4>; ++ ++ /include/ "rtsm_ve-motherboard.dtsi" ++ }; ++}; +diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi +new file mode 100644 +index 0000000..c46cbb2 +--- /dev/null ++++ b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi +@@ -0,0 +1,273 @@ ++/* ++ * ARM Ltd. Fast Models ++ * ++ * Versatile Express (VE) system model ++ * Motherboard component ++ * ++ * VEMotherBoard.lisa ++ */ ++ ++ motherboard { ++ arm,v2m-memory-map = "rs1"; ++ compatible = "arm,vexpress,v2m-p1", "simple-bus"; ++ #address-cells = <2>; /* SMB chipselect number and offset */ ++ #size-cells = <1>; ++ #interrupt-cells = <1>; ++ ranges; ++ ++ flash@0,00000000 { ++ compatible = "arm,vexpress-flash", "cfi-flash"; ++ reg = <0 0x00000000 0x04000000>, ++ <4 0x00000000 0x04000000>; ++ bank-width = <4>; ++ }; ++ ++ v2m_video_ram: vram@2,00000000 { ++ compatible = "arm,vexpress-vram"; ++ reg = <2 0x00000000 0x00800000>; ++ }; ++ ++ ethernet@2,02000000 { ++ compatible = "smsc,lan91c111"; ++ reg = <2 0x02000000 0x10000>; ++ interrupts = <15>; ++ }; ++ ++ v2m_clk24mhz: clk24mhz { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24000000>; ++ clock-output-names = "v2m:clk24mhz"; ++ }; ++ ++ v2m_refclk1mhz: refclk1mhz { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <1000000>; ++ clock-output-names = "v2m:refclk1mhz"; ++ }; ++ ++ v2m_refclk32khz: refclk32khz { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <32768>; ++ clock-output-names = "v2m:refclk32khz"; ++ }; ++ ++ iofpga@3,00000000 { ++ compatible = "arm,amba-bus", "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0 3 0 0x200000>; ++ ++ v2m_sysreg: sysreg@010000 { ++ compatible = "arm,vexpress-sysreg"; ++ reg = <0x010000 0x1000>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++ ++ v2m_sysctl: sysctl@020000 { ++ compatible = "arm,sp810", "arm,primecell"; ++ reg = <0x020000 0x1000>; ++ clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>; ++ clock-names = "refclk", "timclk", "apb_pclk"; ++ #clock-cells = <1>; ++ clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3"; ++ }; ++ ++ aaci@040000 { ++ compatible = "arm,pl041", "arm,primecell"; ++ reg = <0x040000 0x1000>; ++ interrupts = <11>; ++ clocks = <&v2m_clk24mhz>; ++ clock-names = "apb_pclk"; ++ }; ++ ++ mmci@050000 { ++ compatible = "arm,pl180", "arm,primecell"; ++ reg = <0x050000 0x1000>; ++ interrupts = <9 10>; ++ cd-gpios = <&v2m_sysreg 0 0>; ++ wp-gpios = <&v2m_sysreg 1 0>; ++ max-frequency = <12000000>; ++ vmmc-supply = <&v2m_fixed_3v3>; ++ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; ++ clock-names = "mclk", "apb_pclk"; ++ }; ++ ++ kmi@060000 { ++ compatible = "arm,pl050", "arm,primecell"; ++ reg = <0x060000 0x1000>; ++ interrupts = <12>; ++ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; ++ clock-names = "KMIREFCLK", "apb_pclk"; ++ }; ++ ++ kmi@070000 { ++ compatible = "arm,pl050", "arm,primecell"; ++ reg = <0x070000 0x1000>; ++ interrupts = <13>; ++ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; ++ clock-names = "KMIREFCLK", "apb_pclk"; ++ }; ++ ++ v2m_serial0: uart@090000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x090000 0x1000>; ++ interrupts = <5>; ++ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; ++ clock-names = "uartclk", "apb_pclk"; ++ }; ++ ++ v2m_serial1: uart@0a0000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x0a0000 0x1000>; ++ interrupts = <6>; ++ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; ++ clock-names = "uartclk", "apb_pclk"; ++ }; ++ ++ v2m_serial2: uart@0b0000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x0b0000 0x1000>; ++ interrupts = <7>; ++ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; ++ clock-names = "uartclk", "apb_pclk"; ++ }; ++ ++ v2m_serial3: uart@0c0000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x0c0000 0x1000>; ++ interrupts = <8>; ++ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; ++ clock-names = "uartclk", "apb_pclk"; ++ }; ++ ++ wdt@0f0000 { ++ compatible = "arm,sp805", "arm,primecell"; ++ reg = <0x0f0000 0x1000>; ++ interrupts = <0>; ++ clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>; ++ clock-names = "wdogclk", "apb_pclk"; ++ }; ++ ++ v2m_timer01: timer@110000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ reg = <0x110000 0x1000>; ++ interrupts = <2>; ++ clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>; ++ clock-names = "timclken1", "timclken2", "apb_pclk"; ++ }; ++ ++ v2m_timer23: timer@120000 { ++ compatible = "arm,sp804", "arm,primecell"; ++ reg = <0x120000 0x1000>; ++ interrupts = <3>; ++ clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>; ++ clock-names = "timclken1", "timclken2", "apb_pclk"; ++ }; ++ ++ rtc@170000 { ++ compatible = "arm,pl031", "arm,primecell"; ++ reg = <0x170000 0x1000>; ++ interrupts = <4>; ++ clocks = <&v2m_clk24mhz>; ++ clock-names = "apb_pclk"; ++ }; ++ ++ clcd@1f0000 { ++ compatible = "arm,pl111", "arm,primecell"; ++ reg = <0x1f0000 0x1000>; ++ interrupt-names = "combined"; ++ interrupts = <14>; ++ clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>; ++ clock-names = "clcdclk", "apb_pclk"; ++ arm,pl11x,framebuffer = <0x18000000 0x00180000>; ++ memory-region = <&v2m_video_ram>; ++ max-memory-bandwidth = <130000000>; /* 16bpp @ 63.5MHz */ ++ ++ port { ++ v2m_clcd_pads: endpoint { ++ remote-endpoint = <&v2m_clcd_panel>; ++ arm,pl11x,tft-r0g0b0-pads = <0 8 16>; ++ }; ++ }; ++ ++ panel { ++ compatible = "panel-dpi"; ++ ++ port { ++ v2m_clcd_panel: endpoint { ++ remote-endpoint = <&v2m_clcd_pads>; ++ }; ++ }; ++ ++ panel-timing { ++ clock-frequency = <63500127>; ++ hactive = <1024>; ++ hback-porch = <152>; ++ hfront-porch = <48>; ++ hsync-len = <104>; ++ vactive = <768>; ++ vback-porch = <23>; ++ vfront-porch = <3>; ++ vsync-len = <4>; ++ }; ++ }; ++ }; ++ ++ virtio_block@0130000 { ++ compatible = "virtio,mmio"; ++ reg = <0x130000 0x200>; ++ interrupts = <42>; ++ }; ++ }; ++ ++ v2m_fixed_3v3: fixedregulator@0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ }; ++ ++ mcc { ++ compatible = "arm,vexpress,config-bus"; ++ arm,vexpress,config-bridge = <&v2m_sysreg>; ++ ++ v2m_oscclk1: osc@1 { ++ /* CLCD clock */ ++ compatible = "arm,vexpress-osc"; ++ arm,vexpress-sysreg,func = <1 1>; ++ freq-range = <23750000 63500000>; ++ #clock-cells = <0>; ++ clock-output-names = "v2m:oscclk1"; ++ }; ++ ++ reset@0 { ++ compatible = "arm,vexpress-reset"; ++ arm,vexpress-sysreg,func = <5 0>; ++ }; ++ ++ muxfpga@0 { ++ compatible = "arm,vexpress-muxfpga"; ++ arm,vexpress-sysreg,func = <7 0>; ++ }; ++ ++ shutdown@0 { ++ compatible = "arm,vexpress-shutdown"; ++ arm,vexpress-sysreg,func = <8 0>; ++ }; ++ ++ reboot@0 { ++ compatible = "arm,vexpress-reboot"; ++ arm,vexpress-sysreg,func = <9 0>; ++ }; ++ ++ dvimode@0 { ++ compatible = "arm,vexpress-dvimode"; ++ arm,vexpress-sysreg,func = <11 0>; ++ }; ++ }; ++ }; +diff --git a/arch/arm64/boot/dts/cavium/Makefile b/arch/arm64/boot/dts/cavium/Makefile +new file mode 100644 +index 0000000..e34f89d +--- /dev/null ++++ b/arch/arm64/boot/dts/cavium/Makefile +@@ -0,0 +1,5 @@ ++dtb-$(CONFIG_ARCH_THUNDER) += thunder-88xx.dtb ++ ++always := $(dtb-y) ++subdir-y := $(dts-dirs) ++clean-files := *.dtb +diff --git a/arch/arm64/boot/dts/cavium/thunder-88xx.dts b/arch/arm64/boot/dts/cavium/thunder-88xx.dts +new file mode 100644 +index 0000000..800ba65 +--- /dev/null ++++ b/arch/arm64/boot/dts/cavium/thunder-88xx.dts +@@ -0,0 +1,67 @@ ++/* ++ * Cavium Thunder DTS file - Thunder board description ++ * ++ * Copyright (C) 2014, Cavium Inc. ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This library 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 library 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 library; if not, write to the Free ++ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, ++ * MA 02110-1301 USA ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++ ++/include/ "thunder-88xx.dtsi" ++ ++/ { ++ model = "Cavium ThunderX CN88XX board"; ++ compatible = "cavium,thunder-88xx"; ++ ++ aliases { ++ serial0 = &uaa0; ++ serial1 = &uaa1; ++ }; ++ ++ memory@00000000 { ++ device_type = "memory"; ++ reg = <0x0 0x00000000 0x0 0x80000000>; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi b/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi +new file mode 100644 +index 0000000..d8c0bdc +--- /dev/null ++++ b/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi +@@ -0,0 +1,401 @@ ++/* ++ * Cavium Thunder DTS file - Thunder SoC description ++ * ++ * Copyright (C) 2014, Cavium Inc. ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This library 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 library 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 library; if not, write to the Free ++ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, ++ * MA 02110-1301 USA ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/ { ++ compatible = "cavium,thunder-88xx"; ++ interrupt-parent = <&gic0>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ psci { ++ compatible = "arm,psci-0.2"; ++ method = "smc"; ++ }; ++ ++ cpus { ++ #address-cells = <2>; ++ #size-cells = <0>; ++ ++ cpu@000 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x000>; ++ enable-method = "psci"; ++ }; ++ cpu@001 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x001>; ++ enable-method = "psci"; ++ }; ++ cpu@002 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x002>; ++ enable-method = "psci"; ++ }; ++ cpu@003 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x003>; ++ enable-method = "psci"; ++ }; ++ cpu@004 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x004>; ++ enable-method = "psci"; ++ }; ++ cpu@005 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x005>; ++ enable-method = "psci"; ++ }; ++ cpu@006 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x006>; ++ enable-method = "psci"; ++ }; ++ cpu@007 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x007>; ++ enable-method = "psci"; ++ }; ++ cpu@008 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x008>; ++ enable-method = "psci"; ++ }; ++ cpu@009 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x009>; ++ enable-method = "psci"; ++ }; ++ cpu@00a { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x00a>; ++ enable-method = "psci"; ++ }; ++ cpu@00b { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x00b>; ++ enable-method = "psci"; ++ }; ++ cpu@00c { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x00c>; ++ enable-method = "psci"; ++ }; ++ cpu@00d { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x00d>; ++ enable-method = "psci"; ++ }; ++ cpu@00e { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x00e>; ++ enable-method = "psci"; ++ }; ++ cpu@00f { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x00f>; ++ enable-method = "psci"; ++ }; ++ cpu@100 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x100>; ++ enable-method = "psci"; ++ }; ++ cpu@101 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x101>; ++ enable-method = "psci"; ++ }; ++ cpu@102 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x102>; ++ enable-method = "psci"; ++ }; ++ cpu@103 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x103>; ++ enable-method = "psci"; ++ }; ++ cpu@104 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x104>; ++ enable-method = "psci"; ++ }; ++ cpu@105 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x105>; ++ enable-method = "psci"; ++ }; ++ cpu@106 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x106>; ++ enable-method = "psci"; ++ }; ++ cpu@107 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x107>; ++ enable-method = "psci"; ++ }; ++ cpu@108 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x108>; ++ enable-method = "psci"; ++ }; ++ cpu@109 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x109>; ++ enable-method = "psci"; ++ }; ++ cpu@10a { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x10a>; ++ enable-method = "psci"; ++ }; ++ cpu@10b { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x10b>; ++ enable-method = "psci"; ++ }; ++ cpu@10c { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x10c>; ++ enable-method = "psci"; ++ }; ++ cpu@10d { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x10d>; ++ enable-method = "psci"; ++ }; ++ cpu@10e { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x10e>; ++ enable-method = "psci"; ++ }; ++ cpu@10f { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x10f>; ++ enable-method = "psci"; ++ }; ++ cpu@200 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x200>; ++ enable-method = "psci"; ++ }; ++ cpu@201 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x201>; ++ enable-method = "psci"; ++ }; ++ cpu@202 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x202>; ++ enable-method = "psci"; ++ }; ++ cpu@203 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x203>; ++ enable-method = "psci"; ++ }; ++ cpu@204 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x204>; ++ enable-method = "psci"; ++ }; ++ cpu@205 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x205>; ++ enable-method = "psci"; ++ }; ++ cpu@206 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x206>; ++ enable-method = "psci"; ++ }; ++ cpu@207 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x207>; ++ enable-method = "psci"; ++ }; ++ cpu@208 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x208>; ++ enable-method = "psci"; ++ }; ++ cpu@209 { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x209>; ++ enable-method = "psci"; ++ }; ++ cpu@20a { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x20a>; ++ enable-method = "psci"; ++ }; ++ cpu@20b { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x20b>; ++ enable-method = "psci"; ++ }; ++ cpu@20c { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x20c>; ++ enable-method = "psci"; ++ }; ++ cpu@20d { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x20d>; ++ enable-method = "psci"; ++ }; ++ cpu@20e { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x20e>; ++ enable-method = "psci"; ++ }; ++ cpu@20f { ++ device_type = "cpu"; ++ compatible = "cavium,thunder", "arm,armv8"; ++ reg = <0x0 0x20f>; ++ enable-method = "psci"; ++ }; ++ }; ++ ++ timer { ++ compatible = "arm,armv8-timer"; ++ interrupts = <1 13 0xff01>, ++ <1 14 0xff01>, ++ <1 11 0xff01>, ++ <1 10 0xff01>; ++ }; ++ ++ soc { ++ compatible = "simple-bus"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ refclk50mhz: refclk50mhz { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <50000000>; ++ clock-output-names = "refclk50mhz"; ++ }; ++ ++ gic0: interrupt-controller@8010,00000000 { ++ compatible = "arm,gic-v3"; ++ #interrupt-cells = <3>; ++ interrupt-controller; ++ reg = <0x8010 0x00000000 0x0 0x010000>, /* GICD */ ++ <0x8010 0x80000000 0x0 0x600000>; /* GICR */ ++ interrupts = <1 9 0xf04>; ++ }; ++ ++ uaa0: serial@87e0,24000000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x87e0 0x24000000 0x0 0x1000>; ++ interrupts = <1 21 4>; ++ clocks = <&refclk50mhz>; ++ clock-names = "apb_pclk"; ++ }; ++ ++ uaa1: serial@87e0,25000000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x87e0 0x25000000 0x0 0x1000>; ++ interrupts = <1 22 4>; ++ clocks = <&refclk50mhz>; ++ clock-names = "apb_pclk"; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/foundation-v8.dts b/arch/arm64/boot/dts/foundation-v8.dts +deleted file mode 100644 +index 4a06090..0000000 +--- a/arch/arm64/boot/dts/foundation-v8.dts ++++ /dev/null +@@ -1,232 +0,0 @@ +-/* +- * ARM Ltd. +- * +- * ARMv8 Foundation model DTS +- */ +- +-/dts-v1/; +- +-/memreserve/ 0x80000000 0x00010000; +- +-/ { +- model = "Foundation-v8A"; +- compatible = "arm,foundation-aarch64", "arm,vexpress"; +- interrupt-parent = <&gic>; +- #address-cells = <2>; +- #size-cells = <2>; +- +- chosen { }; +- +- aliases { +- serial0 = &v2m_serial0; +- serial1 = &v2m_serial1; +- serial2 = &v2m_serial2; +- serial3 = &v2m_serial3; +- }; +- +- cpus { +- #address-cells = <2>; +- #size-cells = <0>; +- +- cpu@0 { +- device_type = "cpu"; +- compatible = "arm,armv8"; +- reg = <0x0 0x0>; +- enable-method = "spin-table"; +- cpu-release-addr = <0x0 0x8000fff8>; +- }; +- cpu@1 { +- device_type = "cpu"; +- compatible = "arm,armv8"; +- reg = <0x0 0x1>; +- enable-method = "spin-table"; +- cpu-release-addr = <0x0 0x8000fff8>; +- }; +- cpu@2 { +- device_type = "cpu"; +- compatible = "arm,armv8"; +- reg = <0x0 0x2>; +- enable-method = "spin-table"; +- cpu-release-addr = <0x0 0x8000fff8>; +- }; +- cpu@3 { +- device_type = "cpu"; +- compatible = "arm,armv8"; +- reg = <0x0 0x3>; +- enable-method = "spin-table"; +- cpu-release-addr = <0x0 0x8000fff8>; +- }; +- }; +- +- memory@80000000 { +- device_type = "memory"; +- reg = <0x00000000 0x80000000 0 0x80000000>, +- <0x00000008 0x80000000 0 0x80000000>; +- }; +- +- gic: interrupt-controller@2c001000 { +- compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; +- #interrupt-cells = <3>; +- #address-cells = <0>; +- interrupt-controller; +- reg = <0x0 0x2c001000 0 0x1000>, +- <0x0 0x2c002000 0 0x1000>, +- <0x0 0x2c004000 0 0x2000>, +- <0x0 0x2c006000 0 0x2000>; +- interrupts = <1 9 0xf04>; +- }; +- +- timer { +- compatible = "arm,armv8-timer"; +- interrupts = <1 13 0xff01>, +- <1 14 0xff01>, +- <1 11 0xff01>, +- <1 10 0xff01>; +- clock-frequency = <100000000>; +- }; +- +- pmu { +- compatible = "arm,armv8-pmuv3"; +- interrupts = <0 60 4>, +- <0 61 4>, +- <0 62 4>, +- <0 63 4>; +- }; +- +- smb { +- compatible = "arm,vexpress,v2m-p1", "simple-bus"; +- arm,v2m-memory-map = "rs1"; +- #address-cells = <2>; /* SMB chipselect number and offset */ +- #size-cells = <1>; +- +- ranges = <0 0 0 0x08000000 0x04000000>, +- <1 0 0 0x14000000 0x04000000>, +- <2 0 0 0x18000000 0x04000000>, +- <3 0 0 0x1c000000 0x04000000>, +- <4 0 0 0x0c000000 0x04000000>, +- <5 0 0 0x10000000 0x04000000>; +- +- #interrupt-cells = <1>; +- interrupt-map-mask = <0 0 63>; +- interrupt-map = <0 0 0 &gic 0 0 4>, +- <0 0 1 &gic 0 1 4>, +- <0 0 2 &gic 0 2 4>, +- <0 0 3 &gic 0 3 4>, +- <0 0 4 &gic 0 4 4>, +- <0 0 5 &gic 0 5 4>, +- <0 0 6 &gic 0 6 4>, +- <0 0 7 &gic 0 7 4>, +- <0 0 8 &gic 0 8 4>, +- <0 0 9 &gic 0 9 4>, +- <0 0 10 &gic 0 10 4>, +- <0 0 11 &gic 0 11 4>, +- <0 0 12 &gic 0 12 4>, +- <0 0 13 &gic 0 13 4>, +- <0 0 14 &gic 0 14 4>, +- <0 0 15 &gic 0 15 4>, +- <0 0 16 &gic 0 16 4>, +- <0 0 17 &gic 0 17 4>, +- <0 0 18 &gic 0 18 4>, +- <0 0 19 &gic 0 19 4>, +- <0 0 20 &gic 0 20 4>, +- <0 0 21 &gic 0 21 4>, +- <0 0 22 &gic 0 22 4>, +- <0 0 23 &gic 0 23 4>, +- <0 0 24 &gic 0 24 4>, +- <0 0 25 &gic 0 25 4>, +- <0 0 26 &gic 0 26 4>, +- <0 0 27 &gic 0 27 4>, +- <0 0 28 &gic 0 28 4>, +- <0 0 29 &gic 0 29 4>, +- <0 0 30 &gic 0 30 4>, +- <0 0 31 &gic 0 31 4>, +- <0 0 32 &gic 0 32 4>, +- <0 0 33 &gic 0 33 4>, +- <0 0 34 &gic 0 34 4>, +- <0 0 35 &gic 0 35 4>, +- <0 0 36 &gic 0 36 4>, +- <0 0 37 &gic 0 37 4>, +- <0 0 38 &gic 0 38 4>, +- <0 0 39 &gic 0 39 4>, +- <0 0 40 &gic 0 40 4>, +- <0 0 41 &gic 0 41 4>, +- <0 0 42 &gic 0 42 4>; +- +- ethernet@2,02000000 { +- compatible = "smsc,lan91c111"; +- reg = <2 0x02000000 0x10000>; +- interrupts = <15>; +- }; +- +- v2m_clk24mhz: clk24mhz { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-frequency = <24000000>; +- clock-output-names = "v2m:clk24mhz"; +- }; +- +- v2m_refclk1mhz: refclk1mhz { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-frequency = <1000000>; +- clock-output-names = "v2m:refclk1mhz"; +- }; +- +- v2m_refclk32khz: refclk32khz { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-frequency = <32768>; +- clock-output-names = "v2m:refclk32khz"; +- }; +- +- iofpga@3,00000000 { +- compatible = "arm,amba-bus", "simple-bus"; +- #address-cells = <1>; +- #size-cells = <1>; +- ranges = <0 3 0 0x200000>; +- +- v2m_sysreg: sysreg@010000 { +- compatible = "arm,vexpress-sysreg"; +- reg = <0x010000 0x1000>; +- }; +- +- v2m_serial0: uart@090000 { +- compatible = "arm,pl011", "arm,primecell"; +- reg = <0x090000 0x1000>; +- interrupts = <5>; +- clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; +- clock-names = "uartclk", "apb_pclk"; +- }; +- +- v2m_serial1: uart@0a0000 { +- compatible = "arm,pl011", "arm,primecell"; +- reg = <0x0a0000 0x1000>; +- interrupts = <6>; +- clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; +- clock-names = "uartclk", "apb_pclk"; +- }; +- +- v2m_serial2: uart@0b0000 { +- compatible = "arm,pl011", "arm,primecell"; +- reg = <0x0b0000 0x1000>; +- interrupts = <7>; +- clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; +- clock-names = "uartclk", "apb_pclk"; +- }; +- +- v2m_serial3: uart@0c0000 { +- compatible = "arm,pl011", "arm,primecell"; +- reg = <0x0c0000 0x1000>; +- interrupts = <8>; +- clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; +- clock-names = "uartclk", "apb_pclk"; +- }; +- +- virtio_block@0130000 { +- compatible = "virtio,mmio"; +- reg = <0x130000 0x200>; +- interrupts = <42>; +- }; +- }; +- }; +-}; +diff --git a/arch/arm64/boot/dts/include/dt-bindings b/arch/arm64/boot/dts/include/dt-bindings +new file mode 120000 +index 0000000..08c00e4 +--- /dev/null ++++ b/arch/arm64/boot/dts/include/dt-bindings +@@ -0,0 +1 @@ ++../../../../../include/dt-bindings +\ No newline at end of file +diff --git a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts +deleted file mode 100644 +index 572005e..0000000 +--- a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts ++++ /dev/null +@@ -1,159 +0,0 @@ +-/* +- * ARM Ltd. Fast Models +- * +- * Architecture Envelope Model (AEM) ARMv8-A +- * ARMAEMv8AMPCT +- * +- * RTSM_VE_AEMv8A.lisa +- */ +- +-/dts-v1/; +- +-/memreserve/ 0x80000000 0x00010000; +- +-/ { +- model = "RTSM_VE_AEMv8A"; +- compatible = "arm,rtsm_ve,aemv8a", "arm,vexpress"; +- interrupt-parent = <&gic>; +- #address-cells = <2>; +- #size-cells = <2>; +- +- chosen { }; +- +- aliases { +- serial0 = &v2m_serial0; +- serial1 = &v2m_serial1; +- serial2 = &v2m_serial2; +- serial3 = &v2m_serial3; +- }; +- +- cpus { +- #address-cells = <2>; +- #size-cells = <0>; +- +- cpu@0 { +- device_type = "cpu"; +- compatible = "arm,armv8"; +- reg = <0x0 0x0>; +- enable-method = "spin-table"; +- cpu-release-addr = <0x0 0x8000fff8>; +- }; +- cpu@1 { +- device_type = "cpu"; +- compatible = "arm,armv8"; +- reg = <0x0 0x1>; +- enable-method = "spin-table"; +- cpu-release-addr = <0x0 0x8000fff8>; +- }; +- cpu@2 { +- device_type = "cpu"; +- compatible = "arm,armv8"; +- reg = <0x0 0x2>; +- enable-method = "spin-table"; +- cpu-release-addr = <0x0 0x8000fff8>; +- }; +- cpu@3 { +- device_type = "cpu"; +- compatible = "arm,armv8"; +- reg = <0x0 0x3>; +- enable-method = "spin-table"; +- cpu-release-addr = <0x0 0x8000fff8>; +- }; +- }; +- +- memory@80000000 { +- device_type = "memory"; +- reg = <0x00000000 0x80000000 0 0x80000000>, +- <0x00000008 0x80000000 0 0x80000000>; +- }; +- +- gic: interrupt-controller@2c001000 { +- compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; +- #interrupt-cells = <3>; +- #address-cells = <0>; +- interrupt-controller; +- reg = <0x0 0x2c001000 0 0x1000>, +- <0x0 0x2c002000 0 0x1000>, +- <0x0 0x2c004000 0 0x2000>, +- <0x0 0x2c006000 0 0x2000>; +- interrupts = <1 9 0xf04>; +- }; +- +- timer { +- compatible = "arm,armv8-timer"; +- interrupts = <1 13 0xff01>, +- <1 14 0xff01>, +- <1 11 0xff01>, +- <1 10 0xff01>; +- clock-frequency = <100000000>; +- }; +- +- pmu { +- compatible = "arm,armv8-pmuv3"; +- interrupts = <0 60 4>, +- <0 61 4>, +- <0 62 4>, +- <0 63 4>; +- }; +- +- smb { +- compatible = "simple-bus"; +- +- #address-cells = <2>; +- #size-cells = <1>; +- ranges = <0 0 0 0x08000000 0x04000000>, +- <1 0 0 0x14000000 0x04000000>, +- <2 0 0 0x18000000 0x04000000>, +- <3 0 0 0x1c000000 0x04000000>, +- <4 0 0 0x0c000000 0x04000000>, +- <5 0 0 0x10000000 0x04000000>; +- +- #interrupt-cells = <1>; +- interrupt-map-mask = <0 0 63>; +- interrupt-map = <0 0 0 &gic 0 0 4>, +- <0 0 1 &gic 0 1 4>, +- <0 0 2 &gic 0 2 4>, +- <0 0 3 &gic 0 3 4>, +- <0 0 4 &gic 0 4 4>, +- <0 0 5 &gic 0 5 4>, +- <0 0 6 &gic 0 6 4>, +- <0 0 7 &gic 0 7 4>, +- <0 0 8 &gic 0 8 4>, +- <0 0 9 &gic 0 9 4>, +- <0 0 10 &gic 0 10 4>, +- <0 0 11 &gic 0 11 4>, +- <0 0 12 &gic 0 12 4>, +- <0 0 13 &gic 0 13 4>, +- <0 0 14 &gic 0 14 4>, +- <0 0 15 &gic 0 15 4>, +- <0 0 16 &gic 0 16 4>, +- <0 0 17 &gic 0 17 4>, +- <0 0 18 &gic 0 18 4>, +- <0 0 19 &gic 0 19 4>, +- <0 0 20 &gic 0 20 4>, +- <0 0 21 &gic 0 21 4>, +- <0 0 22 &gic 0 22 4>, +- <0 0 23 &gic 0 23 4>, +- <0 0 24 &gic 0 24 4>, +- <0 0 25 &gic 0 25 4>, +- <0 0 26 &gic 0 26 4>, +- <0 0 27 &gic 0 27 4>, +- <0 0 28 &gic 0 28 4>, +- <0 0 29 &gic 0 29 4>, +- <0 0 30 &gic 0 30 4>, +- <0 0 31 &gic 0 31 4>, +- <0 0 32 &gic 0 32 4>, +- <0 0 33 &gic 0 33 4>, +- <0 0 34 &gic 0 34 4>, +- <0 0 35 &gic 0 35 4>, +- <0 0 36 &gic 0 36 4>, +- <0 0 37 &gic 0 37 4>, +- <0 0 38 &gic 0 38 4>, +- <0 0 39 &gic 0 39 4>, +- <0 0 40 &gic 0 40 4>, +- <0 0 41 &gic 0 41 4>, +- <0 0 42 &gic 0 42 4>; +- +- /include/ "rtsm_ve-motherboard.dtsi" +- }; +-}; +diff --git a/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi b/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi +deleted file mode 100644 +index c46cbb2..0000000 +--- a/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi ++++ /dev/null +@@ -1,273 +0,0 @@ +-/* +- * ARM Ltd. Fast Models +- * +- * Versatile Express (VE) system model +- * Motherboard component +- * +- * VEMotherBoard.lisa +- */ +- +- motherboard { +- arm,v2m-memory-map = "rs1"; +- compatible = "arm,vexpress,v2m-p1", "simple-bus"; +- #address-cells = <2>; /* SMB chipselect number and offset */ +- #size-cells = <1>; +- #interrupt-cells = <1>; +- ranges; +- +- flash@0,00000000 { +- compatible = "arm,vexpress-flash", "cfi-flash"; +- reg = <0 0x00000000 0x04000000>, +- <4 0x00000000 0x04000000>; +- bank-width = <4>; +- }; +- +- v2m_video_ram: vram@2,00000000 { +- compatible = "arm,vexpress-vram"; +- reg = <2 0x00000000 0x00800000>; +- }; +- +- ethernet@2,02000000 { +- compatible = "smsc,lan91c111"; +- reg = <2 0x02000000 0x10000>; +- interrupts = <15>; +- }; +- +- v2m_clk24mhz: clk24mhz { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-frequency = <24000000>; +- clock-output-names = "v2m:clk24mhz"; +- }; +- +- v2m_refclk1mhz: refclk1mhz { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-frequency = <1000000>; +- clock-output-names = "v2m:refclk1mhz"; +- }; +- +- v2m_refclk32khz: refclk32khz { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-frequency = <32768>; +- clock-output-names = "v2m:refclk32khz"; +- }; +- +- iofpga@3,00000000 { +- compatible = "arm,amba-bus", "simple-bus"; +- #address-cells = <1>; +- #size-cells = <1>; +- ranges = <0 3 0 0x200000>; +- +- v2m_sysreg: sysreg@010000 { +- compatible = "arm,vexpress-sysreg"; +- reg = <0x010000 0x1000>; +- gpio-controller; +- #gpio-cells = <2>; +- }; +- +- v2m_sysctl: sysctl@020000 { +- compatible = "arm,sp810", "arm,primecell"; +- reg = <0x020000 0x1000>; +- clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>; +- clock-names = "refclk", "timclk", "apb_pclk"; +- #clock-cells = <1>; +- clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3"; +- }; +- +- aaci@040000 { +- compatible = "arm,pl041", "arm,primecell"; +- reg = <0x040000 0x1000>; +- interrupts = <11>; +- clocks = <&v2m_clk24mhz>; +- clock-names = "apb_pclk"; +- }; +- +- mmci@050000 { +- compatible = "arm,pl180", "arm,primecell"; +- reg = <0x050000 0x1000>; +- interrupts = <9 10>; +- cd-gpios = <&v2m_sysreg 0 0>; +- wp-gpios = <&v2m_sysreg 1 0>; +- max-frequency = <12000000>; +- vmmc-supply = <&v2m_fixed_3v3>; +- clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; +- clock-names = "mclk", "apb_pclk"; +- }; +- +- kmi@060000 { +- compatible = "arm,pl050", "arm,primecell"; +- reg = <0x060000 0x1000>; +- interrupts = <12>; +- clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; +- clock-names = "KMIREFCLK", "apb_pclk"; +- }; +- +- kmi@070000 { +- compatible = "arm,pl050", "arm,primecell"; +- reg = <0x070000 0x1000>; +- interrupts = <13>; +- clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; +- clock-names = "KMIREFCLK", "apb_pclk"; +- }; +- +- v2m_serial0: uart@090000 { +- compatible = "arm,pl011", "arm,primecell"; +- reg = <0x090000 0x1000>; +- interrupts = <5>; +- clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; +- clock-names = "uartclk", "apb_pclk"; +- }; +- +- v2m_serial1: uart@0a0000 { +- compatible = "arm,pl011", "arm,primecell"; +- reg = <0x0a0000 0x1000>; +- interrupts = <6>; +- clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; +- clock-names = "uartclk", "apb_pclk"; +- }; +- +- v2m_serial2: uart@0b0000 { +- compatible = "arm,pl011", "arm,primecell"; +- reg = <0x0b0000 0x1000>; +- interrupts = <7>; +- clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; +- clock-names = "uartclk", "apb_pclk"; +- }; +- +- v2m_serial3: uart@0c0000 { +- compatible = "arm,pl011", "arm,primecell"; +- reg = <0x0c0000 0x1000>; +- interrupts = <8>; +- clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; +- clock-names = "uartclk", "apb_pclk"; +- }; +- +- wdt@0f0000 { +- compatible = "arm,sp805", "arm,primecell"; +- reg = <0x0f0000 0x1000>; +- interrupts = <0>; +- clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>; +- clock-names = "wdogclk", "apb_pclk"; +- }; +- +- v2m_timer01: timer@110000 { +- compatible = "arm,sp804", "arm,primecell"; +- reg = <0x110000 0x1000>; +- interrupts = <2>; +- clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>; +- clock-names = "timclken1", "timclken2", "apb_pclk"; +- }; +- +- v2m_timer23: timer@120000 { +- compatible = "arm,sp804", "arm,primecell"; +- reg = <0x120000 0x1000>; +- interrupts = <3>; +- clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>; +- clock-names = "timclken1", "timclken2", "apb_pclk"; +- }; +- +- rtc@170000 { +- compatible = "arm,pl031", "arm,primecell"; +- reg = <0x170000 0x1000>; +- interrupts = <4>; +- clocks = <&v2m_clk24mhz>; +- clock-names = "apb_pclk"; +- }; +- +- clcd@1f0000 { +- compatible = "arm,pl111", "arm,primecell"; +- reg = <0x1f0000 0x1000>; +- interrupt-names = "combined"; +- interrupts = <14>; +- clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>; +- clock-names = "clcdclk", "apb_pclk"; +- arm,pl11x,framebuffer = <0x18000000 0x00180000>; +- memory-region = <&v2m_video_ram>; +- max-memory-bandwidth = <130000000>; /* 16bpp @ 63.5MHz */ +- +- port { +- v2m_clcd_pads: endpoint { +- remote-endpoint = <&v2m_clcd_panel>; +- arm,pl11x,tft-r0g0b0-pads = <0 8 16>; +- }; +- }; +- +- panel { +- compatible = "panel-dpi"; +- +- port { +- v2m_clcd_panel: endpoint { +- remote-endpoint = <&v2m_clcd_pads>; +- }; +- }; +- +- panel-timing { +- clock-frequency = <63500127>; +- hactive = <1024>; +- hback-porch = <152>; +- hfront-porch = <48>; +- hsync-len = <104>; +- vactive = <768>; +- vback-porch = <23>; +- vfront-porch = <3>; +- vsync-len = <4>; +- }; +- }; +- }; +- +- virtio_block@0130000 { +- compatible = "virtio,mmio"; +- reg = <0x130000 0x200>; +- interrupts = <42>; +- }; +- }; +- +- v2m_fixed_3v3: fixedregulator@0 { +- compatible = "regulator-fixed"; +- regulator-name = "3V3"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- regulator-always-on; +- }; +- +- mcc { +- compatible = "arm,vexpress,config-bus"; +- arm,vexpress,config-bridge = <&v2m_sysreg>; +- +- v2m_oscclk1: osc@1 { +- /* CLCD clock */ +- compatible = "arm,vexpress-osc"; +- arm,vexpress-sysreg,func = <1 1>; +- freq-range = <23750000 63500000>; +- #clock-cells = <0>; +- clock-output-names = "v2m:oscclk1"; +- }; +- +- reset@0 { +- compatible = "arm,vexpress-reset"; +- arm,vexpress-sysreg,func = <5 0>; +- }; +- +- muxfpga@0 { +- compatible = "arm,vexpress-muxfpga"; +- arm,vexpress-sysreg,func = <7 0>; +- }; +- +- shutdown@0 { +- compatible = "arm,vexpress-shutdown"; +- arm,vexpress-sysreg,func = <8 0>; +- }; +- +- reboot@0 { +- compatible = "arm,vexpress-reboot"; +- arm,vexpress-sysreg,func = <9 0>; +- }; +- +- dvimode@0 { +- compatible = "arm,vexpress-dvimode"; +- arm,vexpress-sysreg,func = <11 0>; +- }; +- }; +- }; +diff --git a/arch/arm64/boot/dts/thunder-88xx.dts b/arch/arm64/boot/dts/thunder-88xx.dts +deleted file mode 100644 +index 800ba65..0000000 +--- a/arch/arm64/boot/dts/thunder-88xx.dts ++++ /dev/null +@@ -1,67 +0,0 @@ +-/* +- * Cavium Thunder DTS file - Thunder board description +- * +- * Copyright (C) 2014, Cavium Inc. +- * +- * This file is dual-licensed: you can use it either under the terms +- * of the GPL or the X11 license, at your option. Note that this dual +- * licensing only applies to this file, and not this project as a +- * whole. +- * +- * a) This library 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 library 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 library; if not, write to the Free +- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +- * MA 02110-1301 USA +- * +- * Or, alternatively, +- * +- * b) Permission is hereby granted, free of charge, to any person +- * obtaining a copy of this software and associated documentation +- * files (the "Software"), to deal in the Software without +- * restriction, including without limitation the rights to use, +- * copy, modify, merge, publish, distribute, sublicense, and/or +- * sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following +- * conditions: +- * +- * The above copyright notice and this permission notice shall be +- * included in all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. +- */ +- +-/dts-v1/; +- +-/include/ "thunder-88xx.dtsi" +- +-/ { +- model = "Cavium ThunderX CN88XX board"; +- compatible = "cavium,thunder-88xx"; +- +- aliases { +- serial0 = &uaa0; +- serial1 = &uaa1; +- }; +- +- memory@00000000 { +- device_type = "memory"; +- reg = <0x0 0x00000000 0x0 0x80000000>; +- }; +-}; +diff --git a/arch/arm64/boot/dts/thunder-88xx.dtsi b/arch/arm64/boot/dts/thunder-88xx.dtsi +deleted file mode 100644 +index d8c0bdc..0000000 +--- a/arch/arm64/boot/dts/thunder-88xx.dtsi ++++ /dev/null +@@ -1,401 +0,0 @@ +-/* +- * Cavium Thunder DTS file - Thunder SoC description +- * +- * Copyright (C) 2014, Cavium Inc. +- * +- * This file is dual-licensed: you can use it either under the terms +- * of the GPL or the X11 license, at your option. Note that this dual +- * licensing only applies to this file, and not this project as a +- * whole. +- * +- * a) This library 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 library 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 library; if not, write to the Free +- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +- * MA 02110-1301 USA +- * +- * Or, alternatively, +- * +- * b) Permission is hereby granted, free of charge, to any person +- * obtaining a copy of this software and associated documentation +- * files (the "Software"), to deal in the Software without +- * restriction, including without limitation the rights to use, +- * copy, modify, merge, publish, distribute, sublicense, and/or +- * sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following +- * conditions: +- * +- * The above copyright notice and this permission notice shall be +- * included in all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. +- */ +- +-/ { +- compatible = "cavium,thunder-88xx"; +- interrupt-parent = <&gic0>; +- #address-cells = <2>; +- #size-cells = <2>; +- +- psci { +- compatible = "arm,psci-0.2"; +- method = "smc"; +- }; +- +- cpus { +- #address-cells = <2>; +- #size-cells = <0>; +- +- cpu@000 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x000>; +- enable-method = "psci"; +- }; +- cpu@001 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x001>; +- enable-method = "psci"; +- }; +- cpu@002 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x002>; +- enable-method = "psci"; +- }; +- cpu@003 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x003>; +- enable-method = "psci"; +- }; +- cpu@004 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x004>; +- enable-method = "psci"; +- }; +- cpu@005 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x005>; +- enable-method = "psci"; +- }; +- cpu@006 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x006>; +- enable-method = "psci"; +- }; +- cpu@007 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x007>; +- enable-method = "psci"; +- }; +- cpu@008 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x008>; +- enable-method = "psci"; +- }; +- cpu@009 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x009>; +- enable-method = "psci"; +- }; +- cpu@00a { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x00a>; +- enable-method = "psci"; +- }; +- cpu@00b { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x00b>; +- enable-method = "psci"; +- }; +- cpu@00c { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x00c>; +- enable-method = "psci"; +- }; +- cpu@00d { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x00d>; +- enable-method = "psci"; +- }; +- cpu@00e { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x00e>; +- enable-method = "psci"; +- }; +- cpu@00f { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x00f>; +- enable-method = "psci"; +- }; +- cpu@100 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x100>; +- enable-method = "psci"; +- }; +- cpu@101 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x101>; +- enable-method = "psci"; +- }; +- cpu@102 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x102>; +- enable-method = "psci"; +- }; +- cpu@103 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x103>; +- enable-method = "psci"; +- }; +- cpu@104 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x104>; +- enable-method = "psci"; +- }; +- cpu@105 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x105>; +- enable-method = "psci"; +- }; +- cpu@106 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x106>; +- enable-method = "psci"; +- }; +- cpu@107 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x107>; +- enable-method = "psci"; +- }; +- cpu@108 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x108>; +- enable-method = "psci"; +- }; +- cpu@109 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x109>; +- enable-method = "psci"; +- }; +- cpu@10a { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x10a>; +- enable-method = "psci"; +- }; +- cpu@10b { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x10b>; +- enable-method = "psci"; +- }; +- cpu@10c { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x10c>; +- enable-method = "psci"; +- }; +- cpu@10d { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x10d>; +- enable-method = "psci"; +- }; +- cpu@10e { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x10e>; +- enable-method = "psci"; +- }; +- cpu@10f { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x10f>; +- enable-method = "psci"; +- }; +- cpu@200 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x200>; +- enable-method = "psci"; +- }; +- cpu@201 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x201>; +- enable-method = "psci"; +- }; +- cpu@202 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x202>; +- enable-method = "psci"; +- }; +- cpu@203 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x203>; +- enable-method = "psci"; +- }; +- cpu@204 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x204>; +- enable-method = "psci"; +- }; +- cpu@205 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x205>; +- enable-method = "psci"; +- }; +- cpu@206 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x206>; +- enable-method = "psci"; +- }; +- cpu@207 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x207>; +- enable-method = "psci"; +- }; +- cpu@208 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x208>; +- enable-method = "psci"; +- }; +- cpu@209 { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x209>; +- enable-method = "psci"; +- }; +- cpu@20a { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x20a>; +- enable-method = "psci"; +- }; +- cpu@20b { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x20b>; +- enable-method = "psci"; +- }; +- cpu@20c { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x20c>; +- enable-method = "psci"; +- }; +- cpu@20d { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x20d>; +- enable-method = "psci"; +- }; +- cpu@20e { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x20e>; +- enable-method = "psci"; +- }; +- cpu@20f { +- device_type = "cpu"; +- compatible = "cavium,thunder", "arm,armv8"; +- reg = <0x0 0x20f>; +- enable-method = "psci"; +- }; +- }; +- +- timer { +- compatible = "arm,armv8-timer"; +- interrupts = <1 13 0xff01>, +- <1 14 0xff01>, +- <1 11 0xff01>, +- <1 10 0xff01>; +- }; +- +- soc { +- compatible = "simple-bus"; +- #address-cells = <2>; +- #size-cells = <2>; +- ranges; +- +- refclk50mhz: refclk50mhz { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-frequency = <50000000>; +- clock-output-names = "refclk50mhz"; +- }; +- +- gic0: interrupt-controller@8010,00000000 { +- compatible = "arm,gic-v3"; +- #interrupt-cells = <3>; +- interrupt-controller; +- reg = <0x8010 0x00000000 0x0 0x010000>, /* GICD */ +- <0x8010 0x80000000 0x0 0x600000>; /* GICR */ +- interrupts = <1 9 0xf04>; +- }; +- +- uaa0: serial@87e0,24000000 { +- compatible = "arm,pl011", "arm,primecell"; +- reg = <0x87e0 0x24000000 0x0 0x1000>; +- interrupts = <1 21 4>; +- clocks = <&refclk50mhz>; +- clock-names = "apb_pclk"; +- }; +- +- uaa1: serial@87e0,25000000 { +- compatible = "arm,pl011", "arm,primecell"; +- reg = <0x87e0 0x25000000 0x0 0x1000>; +- interrupts = <1 22 4>; +- clocks = <&refclk50mhz>; +- clock-names = "apb_pclk"; +- }; +- }; +-}; +diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h +index 56de5aa..3fb053f 100644 +--- a/arch/arm64/include/asm/compat.h ++++ b/arch/arm64/include/asm/compat.h +@@ -205,6 +205,13 @@ typedef struct compat_siginfo { + compat_long_t _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + int _fd; + } _sigpoll; ++ ++ /* SIGSYS */ ++ struct { ++ compat_uptr_t _call_addr; /* calling user insn */ ++ int _syscall; /* triggering system call number */ ++ compat_uint_t _arch; /* AUDIT_ARCH_* of syscall */ ++ } _sigsys; + } _sifields; + } compat_siginfo_t; + +diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h +index c008bae..3ae74b5 100644 +--- a/arch/arm64/include/asm/cpufeature.h ++++ b/arch/arm64/include/asm/cpufeature.h +@@ -54,6 +54,9 @@ static inline void cpus_set_cap(unsigned int num) + + void check_local_cpu_errata(void); + ++bool cpu_supports_mixed_endian_el0(void); ++bool system_supports_mixed_endian_el0(void); ++ + #endif /* __ASSEMBLY__ */ + + #endif +diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h +index 8adb986..a84ec60 100644 +--- a/arch/arm64/include/asm/cputype.h ++++ b/arch/arm64/include/asm/cputype.h +@@ -72,6 +72,18 @@ + + #define APM_CPU_PART_POTENZA 0x000 + ++#define ID_AA64MMFR0_BIGENDEL0_SHIFT 16 ++#define ID_AA64MMFR0_BIGENDEL0_MASK (0xf << ID_AA64MMFR0_BIGENDEL0_SHIFT) ++#define ID_AA64MMFR0_BIGENDEL0(mmfr0) \ ++ (((mmfr0) & ID_AA64MMFR0_BIGENDEL0_MASK) >> ID_AA64MMFR0_BIGENDEL0_SHIFT) ++#define ID_AA64MMFR0_BIGEND_SHIFT 8 ++#define ID_AA64MMFR0_BIGEND_MASK (0xf << ID_AA64MMFR0_BIGEND_SHIFT) ++#define ID_AA64MMFR0_BIGEND(mmfr0) \ ++ (((mmfr0) & ID_AA64MMFR0_BIGEND_MASK) >> ID_AA64MMFR0_BIGEND_SHIFT) ++ ++#define SCTLR_EL1_CP15BEN (0x1 << 5) ++#define SCTLR_EL1_SED (0x1 << 8) ++ + #ifndef __ASSEMBLY__ + + /* +@@ -104,6 +116,11 @@ static inline u32 __attribute_const__ read_cpuid_cachetype(void) + return read_cpuid(CTR_EL0); + } + ++static inline bool id_aa64mmfr0_mixed_endian_el0(u64 mmfr0) ++{ ++ return (ID_AA64MMFR0_BIGEND(mmfr0) == 0x1) || ++ (ID_AA64MMFR0_BIGENDEL0(mmfr0) == 0x1); ++} + #endif /* __ASSEMBLY__ */ + + #endif +diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h +index 56a9e63..e2ff32a 100644 +--- a/arch/arm64/include/asm/insn.h ++++ b/arch/arm64/include/asm/insn.h +@@ -354,6 +354,16 @@ bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn); + int aarch64_insn_patch_text_nosync(void *addr, u32 insn); + int aarch64_insn_patch_text_sync(void *addrs[], u32 insns[], int cnt); + int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt); ++ ++bool aarch32_insn_is_wide(u32 insn); ++ ++#define A32_RN_OFFSET 16 ++#define A32_RT_OFFSET 12 ++#define A32_RT2_OFFSET 0 ++ ++u32 aarch32_insn_extract_reg_num(u32 insn, int offset); ++u32 aarch32_insn_mcr_extract_opc2(u32 insn); ++u32 aarch32_insn_mcr_extract_crm(u32 insn); + #endif /* __ASSEMBLY__ */ + + #endif /* __ASM_INSN_H */ +diff --git a/arch/arm64/include/asm/opcodes.h b/arch/arm64/include/asm/opcodes.h +new file mode 100644 +index 0000000..4e603ea +--- /dev/null ++++ b/arch/arm64/include/asm/opcodes.h +@@ -0,0 +1 @@ ++#include <../../arm/include/asm/opcodes.h> +diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h +index 41ed9e1..d6dd9fd 100644 +--- a/arch/arm64/include/asm/ptrace.h ++++ b/arch/arm64/include/asm/ptrace.h +@@ -58,6 +58,13 @@ + #define COMPAT_PSR_Z_BIT 0x40000000 + #define COMPAT_PSR_N_BIT 0x80000000 + #define COMPAT_PSR_IT_MASK 0x0600fc00 /* If-Then execution state mask */ ++ ++#ifdef CONFIG_CPU_BIG_ENDIAN ++#define COMPAT_PSR_ENDSTATE COMPAT_PSR_E_BIT ++#else ++#define COMPAT_PSR_ENDSTATE 0 ++#endif ++ + /* + * These are 'magic' values for PTRACE_PEEKUSR that return info about where a + * process is located in memory. +diff --git a/arch/arm64/include/asm/seccomp.h b/arch/arm64/include/asm/seccomp.h +new file mode 100644 +index 0000000..c76fac9 +--- /dev/null ++++ b/arch/arm64/include/asm/seccomp.h +@@ -0,0 +1,25 @@ ++/* ++ * arch/arm64/include/asm/seccomp.h ++ * ++ * Copyright (C) 2014 Linaro Limited ++ * Author: AKASHI Takahiro ++ * ++ * 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 _ASM_SECCOMP_H ++#define _ASM_SECCOMP_H ++ ++#include ++ ++#ifdef CONFIG_COMPAT ++#define __NR_seccomp_read_32 __NR_compat_read ++#define __NR_seccomp_write_32 __NR_compat_write ++#define __NR_seccomp_exit_32 __NR_compat_exit ++#define __NR_seccomp_sigreturn_32 __NR_compat_rt_sigreturn ++#endif /* CONFIG_COMPAT */ ++ ++#include ++ ++#endif /* _ASM_SECCOMP_H */ +diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h +index 10ca8ff..232e4ba 100644 +--- a/arch/arm64/include/asm/traps.h ++++ b/arch/arm64/include/asm/traps.h +@@ -18,6 +18,22 @@ + #ifndef __ASM_TRAP_H + #define __ASM_TRAP_H + ++#include ++ ++struct pt_regs; ++ ++struct undef_hook { ++ struct list_head node; ++ u32 instr_mask; ++ u32 instr_val; ++ u64 pstate_mask; ++ u64 pstate_val; ++ int (*fn)(struct pt_regs *regs, u32 instr); ++}; ++ ++void register_undef_hook(struct undef_hook *hook); ++void unregister_undef_hook(struct undef_hook *hook); ++ + static inline int in_exception_text(unsigned long ptr) + { + extern char __exception_text_start[]; +diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h +index 6d2bf41..49c9aef 100644 +--- a/arch/arm64/include/asm/unistd.h ++++ b/arch/arm64/include/asm/unistd.h +@@ -31,6 +31,9 @@ + * Compat syscall numbers used by the AArch64 kernel. + */ + #define __NR_compat_restart_syscall 0 ++#define __NR_compat_exit 1 ++#define __NR_compat_read 3 ++#define __NR_compat_write 4 + #define __NR_compat_sigreturn 119 + #define __NR_compat_rt_sigreturn 173 + +diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h +index 9dfdac4..8893ceb 100644 +--- a/arch/arm64/include/asm/unistd32.h ++++ b/arch/arm64/include/asm/unistd32.h +@@ -787,7 +787,8 @@ __SYSCALL(__NR_sched_setattr, sys_sched_setattr) + __SYSCALL(__NR_sched_getattr, sys_sched_getattr) + #define __NR_renameat2 382 + __SYSCALL(__NR_renameat2, sys_renameat2) +- /* 383 for seccomp */ ++#define __NR_seccomp 383 ++__SYSCALL(__NR_seccomp, sys_seccomp) + #define __NR_getrandom 384 + __SYSCALL(__NR_getrandom, sys_getrandom) + #define __NR_memfd_create 385 +diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile +index da22728..0a44aa5 100644 +--- a/arch/arm64/kernel/Makefile ++++ b/arch/arm64/kernel/Makefile +@@ -5,6 +5,7 @@ + CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET) + AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET) + CFLAGS_efi-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) ++CFLAGS_armv8_deprecated.o := -I$(src) + + CFLAGS_REMOVE_ftrace.o = -pg + CFLAGS_REMOVE_insn.o = -pg +@@ -14,11 +15,12 @@ CFLAGS_REMOVE_return_address.o = -pg + arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \ + entry-fpsimd.o process.o ptrace.o setup.o signal.o \ + sys.o stacktrace.o time.o traps.o io.o vdso.o \ +- hyp-stub.o psci.o cpu_ops.o insn.o return_address.o \ +- cpuinfo.o cpu_errata.o alternative.o ++ hyp-stub.o psci.o psci-call.o cpu_ops.o insn.o \ ++ return_address.o cpuinfo.o cpu_errata.o alternative.o + + arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \ +- sys_compat.o ++ sys_compat.o \ ++ ../../arm/kernel/opcodes.o + arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o + arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o + arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o topology.o +@@ -31,6 +33,7 @@ arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o + arm64-obj-$(CONFIG_KGDB) += kgdb.o + arm64-obj-$(CONFIG_EFI) += efi.o efi-stub.o efi-entry.o + arm64-obj-$(CONFIG_PCI) += pci.o ++arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o + + obj-y += $(arm64-obj-y) vdso/ + obj-m += $(arm64-obj-m) +diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c +new file mode 100644 +index 0000000..7922c2e +--- /dev/null ++++ b/arch/arm64/kernel/armv8_deprecated.c +@@ -0,0 +1,662 @@ ++/* ++ * Copyright (C) 2014 ARM 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define CREATE_TRACE_POINTS ++#include "trace-events-emulation.h" ++ ++/* ++ * The runtime support for deprecated instruction support can be in one of ++ * following three states - ++ * ++ * 0 = undef ++ * 1 = emulate (software emulation) ++ * 2 = hw (supported in hardware) ++ */ ++enum insn_emulation_mode { ++ INSN_UNDEF, ++ INSN_EMULATE, ++ INSN_HW, ++}; ++ ++enum legacy_insn_status { ++ INSN_DEPRECATED, ++ INSN_OBSOLETE, ++}; ++ ++struct insn_emulation_ops { ++ const char *name; ++ enum legacy_insn_status status; ++ struct undef_hook *hooks; ++ int (*set_hw_mode)(bool enable); ++}; ++ ++struct insn_emulation { ++ struct list_head node; ++ struct insn_emulation_ops *ops; ++ int current_mode; ++ int min; ++ int max; ++}; ++ ++static LIST_HEAD(insn_emulation); ++static int nr_insn_emulated; ++static DEFINE_RAW_SPINLOCK(insn_emulation_lock); ++ ++static void register_emulation_hooks(struct insn_emulation_ops *ops) ++{ ++ struct undef_hook *hook; ++ ++ BUG_ON(!ops->hooks); ++ ++ for (hook = ops->hooks; hook->instr_mask; hook++) ++ register_undef_hook(hook); ++ ++ pr_notice("Registered %s emulation handler\n", ops->name); ++} ++ ++static void remove_emulation_hooks(struct insn_emulation_ops *ops) ++{ ++ struct undef_hook *hook; ++ ++ BUG_ON(!ops->hooks); ++ ++ for (hook = ops->hooks; hook->instr_mask; hook++) ++ unregister_undef_hook(hook); ++ ++ pr_notice("Removed %s emulation handler\n", ops->name); ++} ++ ++static void enable_insn_hw_mode(void *data) ++{ ++ struct insn_emulation *insn = (struct insn_emulation *)data; ++ if (insn->ops->set_hw_mode) ++ insn->ops->set_hw_mode(true); ++} ++ ++static void disable_insn_hw_mode(void *data) ++{ ++ struct insn_emulation *insn = (struct insn_emulation *)data; ++ if (insn->ops->set_hw_mode) ++ insn->ops->set_hw_mode(false); ++} ++ ++/* Run set_hw_mode(mode) on all active CPUs */ ++static int run_all_cpu_set_hw_mode(struct insn_emulation *insn, bool enable) ++{ ++ if (!insn->ops->set_hw_mode) ++ return -EINVAL; ++ if (enable) ++ on_each_cpu(enable_insn_hw_mode, (void *)insn, true); ++ else ++ on_each_cpu(disable_insn_hw_mode, (void *)insn, true); ++ return 0; ++} ++ ++/* ++ * Run set_hw_mode for all insns on a starting CPU. ++ * Returns: ++ * 0 - If all the hooks ran successfully. ++ * -EINVAL - At least one hook is not supported by the CPU. ++ */ ++static int run_all_insn_set_hw_mode(unsigned long cpu) ++{ ++ int rc = 0; ++ unsigned long flags; ++ struct insn_emulation *insn; ++ ++ raw_spin_lock_irqsave(&insn_emulation_lock, flags); ++ list_for_each_entry(insn, &insn_emulation, node) { ++ bool enable = (insn->current_mode == INSN_HW); ++ if (insn->ops->set_hw_mode && insn->ops->set_hw_mode(enable)) { ++ pr_warn("CPU[%ld] cannot support the emulation of %s", ++ cpu, insn->ops->name); ++ rc = -EINVAL; ++ } ++ } ++ raw_spin_unlock_irqrestore(&insn_emulation_lock, flags); ++ return rc; ++} ++ ++static int update_insn_emulation_mode(struct insn_emulation *insn, ++ enum insn_emulation_mode prev) ++{ ++ int ret = 0; ++ ++ switch (prev) { ++ case INSN_UNDEF: /* Nothing to be done */ ++ break; ++ case INSN_EMULATE: ++ remove_emulation_hooks(insn->ops); ++ break; ++ case INSN_HW: ++ if (!run_all_cpu_set_hw_mode(insn, false)) ++ pr_notice("Disabled %s support\n", insn->ops->name); ++ break; ++ } ++ ++ switch (insn->current_mode) { ++ case INSN_UNDEF: ++ break; ++ case INSN_EMULATE: ++ register_emulation_hooks(insn->ops); ++ break; ++ case INSN_HW: ++ ret = run_all_cpu_set_hw_mode(insn, true); ++ if (!ret) ++ pr_notice("Enabled %s support\n", insn->ops->name); ++ break; ++ } ++ ++ return ret; ++} ++ ++static void register_insn_emulation(struct insn_emulation_ops *ops) ++{ ++ unsigned long flags; ++ struct insn_emulation *insn; ++ ++ insn = kzalloc(sizeof(*insn), GFP_KERNEL); ++ insn->ops = ops; ++ insn->min = INSN_UNDEF; ++ ++ switch (ops->status) { ++ case INSN_DEPRECATED: ++ insn->current_mode = INSN_EMULATE; ++ /* Disable the HW mode if it was turned on at early boot time */ ++ run_all_cpu_set_hw_mode(insn, false); ++ insn->max = INSN_HW; ++ break; ++ case INSN_OBSOLETE: ++ insn->current_mode = INSN_UNDEF; ++ insn->max = INSN_EMULATE; ++ break; ++ } ++ ++ raw_spin_lock_irqsave(&insn_emulation_lock, flags); ++ list_add(&insn->node, &insn_emulation); ++ nr_insn_emulated++; ++ raw_spin_unlock_irqrestore(&insn_emulation_lock, flags); ++ ++ /* Register any handlers if required */ ++ update_insn_emulation_mode(insn, INSN_UNDEF); ++} ++ ++static int emulation_proc_handler(struct ctl_table *table, int write, ++ void __user *buffer, size_t *lenp, ++ loff_t *ppos) ++{ ++ int ret = 0; ++ struct insn_emulation *insn = (struct insn_emulation *) table->data; ++ enum insn_emulation_mode prev_mode = insn->current_mode; ++ ++ table->data = &insn->current_mode; ++ ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); ++ ++ if (ret || !write || prev_mode == insn->current_mode) ++ goto ret; ++ ++ ret = update_insn_emulation_mode(insn, prev_mode); ++ if (ret) { ++ /* Mode change failed, revert to previous mode. */ ++ insn->current_mode = prev_mode; ++ update_insn_emulation_mode(insn, INSN_UNDEF); ++ } ++ret: ++ table->data = insn; ++ return ret; ++} ++ ++static struct ctl_table ctl_abi[] = { ++ { ++ .procname = "abi", ++ .mode = 0555, ++ }, ++ { } ++}; ++ ++static void register_insn_emulation_sysctl(struct ctl_table *table) ++{ ++ unsigned long flags; ++ int i = 0; ++ struct insn_emulation *insn; ++ struct ctl_table *insns_sysctl, *sysctl; ++ ++ insns_sysctl = kzalloc(sizeof(*sysctl) * (nr_insn_emulated + 1), ++ GFP_KERNEL); ++ ++ raw_spin_lock_irqsave(&insn_emulation_lock, flags); ++ list_for_each_entry(insn, &insn_emulation, node) { ++ sysctl = &insns_sysctl[i]; ++ ++ sysctl->mode = 0644; ++ sysctl->maxlen = sizeof(int); ++ ++ sysctl->procname = insn->ops->name; ++ sysctl->data = insn; ++ sysctl->extra1 = &insn->min; ++ sysctl->extra2 = &insn->max; ++ sysctl->proc_handler = emulation_proc_handler; ++ i++; ++ } ++ raw_spin_unlock_irqrestore(&insn_emulation_lock, flags); ++ ++ table->child = insns_sysctl; ++ register_sysctl_table(table); ++} ++ ++/* ++ * Implement emulation of the SWP/SWPB instructions using load-exclusive and ++ * store-exclusive. ++ * ++ * Syntax of SWP{B} instruction: SWP{B} , , [] ++ * Where: Rt = destination ++ * Rt2 = source ++ * Rn = address ++ */ ++ ++/* ++ * Error-checking SWP macros implemented using ldxr{b}/stxr{b} ++ */ ++#define __user_swpX_asm(data, addr, res, temp, B) \ ++ __asm__ __volatile__( \ ++ " mov %w2, %w1\n" \ ++ "0: ldxr"B" %w1, [%3]\n" \ ++ "1: stxr"B" %w0, %w2, [%3]\n" \ ++ " cbz %w0, 2f\n" \ ++ " mov %w0, %w4\n" \ ++ "2:\n" \ ++ " .pushsection .fixup,\"ax\"\n" \ ++ " .align 2\n" \ ++ "3: mov %w0, %w5\n" \ ++ " b 2b\n" \ ++ " .popsection" \ ++ " .pushsection __ex_table,\"a\"\n" \ ++ " .align 3\n" \ ++ " .quad 0b, 3b\n" \ ++ " .quad 1b, 3b\n" \ ++ " .popsection" \ ++ : "=&r" (res), "+r" (data), "=&r" (temp) \ ++ : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT) \ ++ : "memory") ++ ++#define __user_swp_asm(data, addr, res, temp) \ ++ __user_swpX_asm(data, addr, res, temp, "") ++#define __user_swpb_asm(data, addr, res, temp) \ ++ __user_swpX_asm(data, addr, res, temp, "b") ++ ++/* ++ * Bit 22 of the instruction encoding distinguishes between ++ * the SWP and SWPB variants (bit set means SWPB). ++ */ ++#define TYPE_SWPB (1 << 22) ++ ++/* ++ * Set up process info to signal segmentation fault - called on access error. ++ */ ++static void set_segfault(struct pt_regs *regs, unsigned long addr) ++{ ++ siginfo_t info; ++ ++ down_read(¤t->mm->mmap_sem); ++ if (find_vma(current->mm, addr) == NULL) ++ info.si_code = SEGV_MAPERR; ++ else ++ info.si_code = SEGV_ACCERR; ++ up_read(¤t->mm->mmap_sem); ++ ++ info.si_signo = SIGSEGV; ++ info.si_errno = 0; ++ info.si_addr = (void *) instruction_pointer(regs); ++ ++ pr_debug("SWP{B} emulation: access caused memory abort!\n"); ++ arm64_notify_die("Illegal memory access", regs, &info, 0); ++} ++ ++static int emulate_swpX(unsigned int address, unsigned int *data, ++ unsigned int type) ++{ ++ unsigned int res = 0; ++ ++ if ((type != TYPE_SWPB) && (address & 0x3)) { ++ /* SWP to unaligned address not permitted */ ++ pr_debug("SWP instruction on unaligned pointer!\n"); ++ return -EFAULT; ++ } ++ ++ while (1) { ++ unsigned long temp; ++ ++ if (type == TYPE_SWPB) ++ __user_swpb_asm(*data, address, res, temp); ++ else ++ __user_swp_asm(*data, address, res, temp); ++ ++ if (likely(res != -EAGAIN) || signal_pending(current)) ++ break; ++ ++ cond_resched(); ++ } ++ ++ return res; ++} ++ ++/* ++ * swp_handler logs the id of calling process, dissects the instruction, sanity ++ * checks the memory location, calls emulate_swpX for the actual operation and ++ * deals with fixup/error handling before returning ++ */ ++static int swp_handler(struct pt_regs *regs, u32 instr) ++{ ++ u32 destreg, data, type, address = 0; ++ int rn, rt2, res = 0; ++ ++ perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->pc); ++ ++ type = instr & TYPE_SWPB; ++ ++ switch (arm_check_condition(instr, regs->pstate)) { ++ case ARM_OPCODE_CONDTEST_PASS: ++ break; ++ case ARM_OPCODE_CONDTEST_FAIL: ++ /* Condition failed - return to next instruction */ ++ goto ret; ++ case ARM_OPCODE_CONDTEST_UNCOND: ++ /* If unconditional encoding - not a SWP, undef */ ++ return -EFAULT; ++ default: ++ return -EINVAL; ++ } ++ ++ rn = aarch32_insn_extract_reg_num(instr, A32_RN_OFFSET); ++ rt2 = aarch32_insn_extract_reg_num(instr, A32_RT2_OFFSET); ++ ++ address = (u32)regs->user_regs.regs[rn]; ++ data = (u32)regs->user_regs.regs[rt2]; ++ destreg = aarch32_insn_extract_reg_num(instr, A32_RT_OFFSET); ++ ++ pr_debug("addr in r%d->0x%08x, dest is r%d, source in r%d->0x%08x)\n", ++ rn, address, destreg, ++ aarch32_insn_extract_reg_num(instr, A32_RT2_OFFSET), data); ++ ++ /* Check access in reasonable access range for both SWP and SWPB */ ++ if (!access_ok(VERIFY_WRITE, (address & ~3), 4)) { ++ pr_debug("SWP{B} emulation: access to 0x%08x not allowed!\n", ++ address); ++ goto fault; ++ } ++ ++ res = emulate_swpX(address, &data, type); ++ if (res == -EFAULT) ++ goto fault; ++ else if (res == 0) ++ regs->user_regs.regs[destreg] = data; ++ ++ret: ++ if (type == TYPE_SWPB) ++ trace_instruction_emulation("swpb", regs->pc); ++ else ++ trace_instruction_emulation("swp", regs->pc); ++ ++ pr_warn_ratelimited("\"%s\" (%ld) uses obsolete SWP{B} instruction at 0x%llx\n", ++ current->comm, (unsigned long)current->pid, regs->pc); ++ ++ regs->pc += 4; ++ return 0; ++ ++fault: ++ set_segfault(regs, address); ++ ++ return 0; ++} ++ ++/* ++ * Only emulate SWP/SWPB executed in ARM state/User mode. ++ * The kernel must be SWP free and SWP{B} does not exist in Thumb. ++ */ ++static struct undef_hook swp_hooks[] = { ++ { ++ .instr_mask = 0x0fb00ff0, ++ .instr_val = 0x01000090, ++ .pstate_mask = COMPAT_PSR_MODE_MASK, ++ .pstate_val = COMPAT_PSR_MODE_USR, ++ .fn = swp_handler ++ }, ++ { } ++}; ++ ++static struct insn_emulation_ops swp_ops = { ++ .name = "swp", ++ .status = INSN_OBSOLETE, ++ .hooks = swp_hooks, ++ .set_hw_mode = NULL, ++}; ++ ++static int cp15barrier_handler(struct pt_regs *regs, u32 instr) ++{ ++ perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->pc); ++ ++ switch (arm_check_condition(instr, regs->pstate)) { ++ case ARM_OPCODE_CONDTEST_PASS: ++ break; ++ case ARM_OPCODE_CONDTEST_FAIL: ++ /* Condition failed - return to next instruction */ ++ goto ret; ++ case ARM_OPCODE_CONDTEST_UNCOND: ++ /* If unconditional encoding - not a barrier instruction */ ++ return -EFAULT; ++ default: ++ return -EINVAL; ++ } ++ ++ switch (aarch32_insn_mcr_extract_crm(instr)) { ++ case 10: ++ /* ++ * dmb - mcr p15, 0, Rt, c7, c10, 5 ++ * dsb - mcr p15, 0, Rt, c7, c10, 4 ++ */ ++ if (aarch32_insn_mcr_extract_opc2(instr) == 5) { ++ dmb(sy); ++ trace_instruction_emulation( ++ "mcr p15, 0, Rt, c7, c10, 5 ; dmb", regs->pc); ++ } else { ++ dsb(sy); ++ trace_instruction_emulation( ++ "mcr p15, 0, Rt, c7, c10, 4 ; dsb", regs->pc); ++ } ++ break; ++ case 5: ++ /* ++ * isb - mcr p15, 0, Rt, c7, c5, 4 ++ * ++ * Taking an exception or returning from one acts as an ++ * instruction barrier. So no explicit barrier needed here. ++ */ ++ trace_instruction_emulation( ++ "mcr p15, 0, Rt, c7, c5, 4 ; isb", regs->pc); ++ break; ++ } ++ ++ret: ++ pr_warn_ratelimited("\"%s\" (%ld) uses deprecated CP15 Barrier instruction at 0x%llx\n", ++ current->comm, (unsigned long)current->pid, regs->pc); ++ ++ regs->pc += 4; ++ return 0; ++} ++ ++static inline void config_sctlr_el1(u32 clear, u32 set) ++{ ++ u32 val; ++ ++ asm volatile("mrs %0, sctlr_el1" : "=r" (val)); ++ val &= ~clear; ++ val |= set; ++ asm volatile("msr sctlr_el1, %0" : : "r" (val)); ++} ++ ++static int cp15_barrier_set_hw_mode(bool enable) ++{ ++ if (enable) ++ config_sctlr_el1(0, SCTLR_EL1_CP15BEN); ++ else ++ config_sctlr_el1(SCTLR_EL1_CP15BEN, 0); ++ return 0; ++} ++ ++static struct undef_hook cp15_barrier_hooks[] = { ++ { ++ .instr_mask = 0x0fff0fdf, ++ .instr_val = 0x0e070f9a, ++ .pstate_mask = COMPAT_PSR_MODE_MASK, ++ .pstate_val = COMPAT_PSR_MODE_USR, ++ .fn = cp15barrier_handler, ++ }, ++ { ++ .instr_mask = 0x0fff0fff, ++ .instr_val = 0x0e070f95, ++ .pstate_mask = COMPAT_PSR_MODE_MASK, ++ .pstate_val = COMPAT_PSR_MODE_USR, ++ .fn = cp15barrier_handler, ++ }, ++ { } ++}; ++ ++static struct insn_emulation_ops cp15_barrier_ops = { ++ .name = "cp15_barrier", ++ .status = INSN_DEPRECATED, ++ .hooks = cp15_barrier_hooks, ++ .set_hw_mode = cp15_barrier_set_hw_mode, ++}; ++ ++static int setend_set_hw_mode(bool enable) ++{ ++ if (!cpu_supports_mixed_endian_el0()) ++ return -EINVAL; ++ ++ if (enable) ++ config_sctlr_el1(SCTLR_EL1_SED, 0); ++ else ++ config_sctlr_el1(0, SCTLR_EL1_SED); ++ return 0; ++} ++ ++static int compat_setend_handler(struct pt_regs *regs, u32 big_endian) ++{ ++ char *insn; ++ ++ perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->pc); ++ ++ if (big_endian) { ++ insn = "setend be"; ++ regs->pstate |= COMPAT_PSR_E_BIT; ++ } else { ++ insn = "setend le"; ++ regs->pstate &= ~COMPAT_PSR_E_BIT; ++ } ++ ++ trace_instruction_emulation(insn, regs->pc); ++ pr_warn_ratelimited("\"%s\" (%ld) uses deprecated setend instruction at 0x%llx\n", ++ current->comm, (unsigned long)current->pid, regs->pc); ++ ++ return 0; ++} ++ ++static int a32_setend_handler(struct pt_regs *regs, u32 instr) ++{ ++ int rc = compat_setend_handler(regs, (instr >> 9) & 1); ++ regs->pc += 4; ++ return rc; ++} ++ ++static int t16_setend_handler(struct pt_regs *regs, u32 instr) ++{ ++ int rc = compat_setend_handler(regs, (instr >> 3) & 1); ++ regs->pc += 2; ++ return rc; ++} ++ ++static struct undef_hook setend_hooks[] = { ++ { ++ .instr_mask = 0xfffffdff, ++ .instr_val = 0xf1010000, ++ .pstate_mask = COMPAT_PSR_MODE_MASK, ++ .pstate_val = COMPAT_PSR_MODE_USR, ++ .fn = a32_setend_handler, ++ }, ++ { ++ /* Thumb mode */ ++ .instr_mask = 0x0000fff7, ++ .instr_val = 0x0000b650, ++ .pstate_mask = (COMPAT_PSR_T_BIT | COMPAT_PSR_MODE_MASK), ++ .pstate_val = (COMPAT_PSR_T_BIT | COMPAT_PSR_MODE_USR), ++ .fn = t16_setend_handler, ++ }, ++ {} ++}; ++ ++static struct insn_emulation_ops setend_ops = { ++ .name = "setend", ++ .status = INSN_DEPRECATED, ++ .hooks = setend_hooks, ++ .set_hw_mode = setend_set_hw_mode, ++}; ++ ++static int insn_cpu_hotplug_notify(struct notifier_block *b, ++ unsigned long action, void *hcpu) ++{ ++ int rc = 0; ++ if ((action & ~CPU_TASKS_FROZEN) == CPU_STARTING) ++ rc = run_all_insn_set_hw_mode((unsigned long)hcpu); ++ ++ return notifier_from_errno(rc); ++} ++ ++static struct notifier_block insn_cpu_hotplug_notifier = { ++ .notifier_call = insn_cpu_hotplug_notify, ++}; ++ ++/* ++ * Invoked as late_initcall, since not needed before init spawned. ++ */ ++static int __init armv8_deprecated_init(void) ++{ ++ if (IS_ENABLED(CONFIG_SWP_EMULATION)) ++ register_insn_emulation(&swp_ops); ++ ++ if (IS_ENABLED(CONFIG_CP15_BARRIER_EMULATION)) ++ register_insn_emulation(&cp15_barrier_ops); ++ ++ if (IS_ENABLED(CONFIG_SETEND_EMULATION)) { ++ if(system_supports_mixed_endian_el0()) ++ register_insn_emulation(&setend_ops); ++ else ++ pr_info("setend instruction emulation is not supported on the system"); ++ } ++ ++ register_cpu_notifier(&insn_cpu_hotplug_notifier); ++ register_insn_emulation_sysctl(ctl_abi); ++ ++ return 0; ++} ++ ++late_initcall(armv8_deprecated_init); +diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c +index 16d6d03..e86b9b4 100644 +--- a/arch/arm64/kernel/cpuinfo.c ++++ b/arch/arm64/kernel/cpuinfo.c +@@ -35,6 +35,27 @@ + */ + DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data); + static struct cpuinfo_arm64 boot_cpu_data; ++static bool mixed_endian_el0 = true; ++ ++bool cpu_supports_mixed_endian_el0(void) ++{ ++ return id_aa64mmfr0_mixed_endian_el0(read_cpuid(ID_AA64MMFR0_EL1)); ++} ++ ++bool system_supports_mixed_endian_el0(void) ++{ ++ return mixed_endian_el0; ++} ++ ++static void update_mixed_endian_el0_support(struct cpuinfo_arm64 *info) ++{ ++ mixed_endian_el0 &= id_aa64mmfr0_mixed_endian_el0(info->reg_id_aa64mmfr0); ++} ++ ++static void update_cpu_features(struct cpuinfo_arm64 *info) ++{ ++ update_mixed_endian_el0_support(info); ++} + + static char *icache_policy_str[] = { + [ICACHE_POLICY_RESERVED] = "RESERVED/UNKNOWN", +@@ -189,6 +210,7 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info) + cpuinfo_detect_icache_policy(info); + + check_local_cpu_errata(); ++ update_cpu_features(info); + } + + void cpuinfo_store_cpu(void) +diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S +index 6c99b46..c19999c 100644 +--- a/arch/arm64/kernel/entry.S ++++ b/arch/arm64/kernel/entry.S +@@ -475,8 +475,8 @@ el0_da: + bic x0, x26, #(0xff << 56) + mov x1, x25 + mov x2, sp +- adr lr, ret_to_user +- b do_mem_abort ++ bl do_mem_abort ++ b ret_to_user + el0_ia: + /* + * Instruction abort handling +@@ -488,8 +488,8 @@ el0_ia: + mov x0, x26 + orr x1, x25, #1 << 24 // use reserved ISS bit for instruction aborts + mov x2, sp +- adr lr, ret_to_user +- b do_mem_abort ++ bl do_mem_abort ++ b ret_to_user + el0_fpsimd_acc: + /* + * Floating Point or Advanced SIMD access +@@ -498,8 +498,8 @@ el0_fpsimd_acc: + ct_user_exit + mov x0, x25 + mov x1, sp +- adr lr, ret_to_user +- b do_fpsimd_acc ++ bl do_fpsimd_acc ++ b ret_to_user + el0_fpsimd_exc: + /* + * Floating Point or Advanced SIMD exception +@@ -508,8 +508,8 @@ el0_fpsimd_exc: + ct_user_exit + mov x0, x25 + mov x1, sp +- adr lr, ret_to_user +- b do_fpsimd_exc ++ bl do_fpsimd_exc ++ b ret_to_user + el0_sp_pc: + /* + * Stack or PC alignment exception handling +@@ -521,8 +521,8 @@ el0_sp_pc: + mov x0, x26 + mov x1, x25 + mov x2, sp +- adr lr, ret_to_user +- b do_sp_pc_abort ++ bl do_sp_pc_abort ++ b ret_to_user + el0_undef: + /* + * Undefined instruction +@@ -531,8 +531,8 @@ el0_undef: + enable_dbg_and_irq + ct_user_exit + mov x0, sp +- adr lr, ret_to_user +- b do_undefinstr ++ bl do_undefinstr ++ b ret_to_user + el0_dbg: + /* + * Debug exception handling +@@ -551,8 +551,8 @@ el0_inv: + mov x0, sp + mov x1, #BAD_SYNC + mrs x2, esr_el1 +- adr lr, ret_to_user +- b bad_mode ++ bl bad_mode ++ b ret_to_user + ENDPROC(el0_sync) + + .align 6 +@@ -674,14 +674,15 @@ el0_svc_naked: // compat entry point + ldr x16, [tsk, #TI_FLAGS] // check for syscall hooks + tst x16, #_TIF_SYSCALL_WORK + b.ne __sys_trace +- adr lr, ret_fast_syscall // return address + cmp scno, sc_nr // check upper syscall limit + b.hs ni_sys + ldr x16, [stbl, scno, lsl #3] // address in the syscall table +- br x16 // call sys_* routine ++ blr x16 // call sys_* routine ++ b ret_fast_syscall + ni_sys: + mov x0, sp +- b do_ni_syscall ++ bl do_ni_syscall ++ b ret_fast_syscall + ENDPROC(el0_svc) + + /* +@@ -689,26 +690,38 @@ ENDPROC(el0_svc) + * switches, and waiting for our parent to respond. + */ + __sys_trace: +- mov x0, sp ++ mov w0, #-1 // set default errno for ++ cmp scno, x0 // user-issued syscall(-1) ++ b.ne 1f ++ mov x0, #-ENOSYS ++ str x0, [sp, #S_X0] ++1: mov x0, sp + bl syscall_trace_enter +- adr lr, __sys_trace_return // return address ++ cmp w0, #-1 // skip the syscall? ++ b.eq __sys_trace_return_skipped + uxtw scno, w0 // syscall number (possibly new) + mov x1, sp // pointer to regs + cmp scno, sc_nr // check upper syscall limit +- b.hs ni_sys ++ b.hs __ni_sys_trace + ldp x0, x1, [sp] // restore the syscall args + ldp x2, x3, [sp, #S_X2] + ldp x4, x5, [sp, #S_X4] + ldp x6, x7, [sp, #S_X6] + ldr x16, [stbl, scno, lsl #3] // address in the syscall table +- br x16 // call sys_* routine ++ blr x16 // call sys_* routine + + __sys_trace_return: +- str x0, [sp] // save returned x0 ++ str x0, [sp, #S_X0] // save returned x0 ++__sys_trace_return_skipped: + mov x0, sp + bl syscall_trace_exit + b ret_to_user + ++__ni_sys_trace: ++ mov x0, sp ++ bl do_ni_syscall ++ b __sys_trace_return ++ + /* + * Special system call wrappers. + */ +diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c +index 8cd27fe..7e9327a 100644 +--- a/arch/arm64/kernel/insn.c ++++ b/arch/arm64/kernel/insn.c +@@ -960,3 +960,29 @@ u32 aarch64_insn_gen_logical_shifted_reg(enum aarch64_insn_register dst, + + return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_6, insn, shift); + } ++ ++bool aarch32_insn_is_wide(u32 insn) ++{ ++ return insn >= 0xe800; ++} ++ ++/* ++ * Macros/defines for extracting register numbers from instruction. ++ */ ++u32 aarch32_insn_extract_reg_num(u32 insn, int offset) ++{ ++ return (insn & (0xf << offset)) >> offset; ++} ++ ++#define OPC2_MASK 0x7 ++#define OPC2_OFFSET 5 ++u32 aarch32_insn_mcr_extract_opc2(u32 insn) ++{ ++ return (insn & (OPC2_MASK << OPC2_OFFSET)) >> OPC2_OFFSET; ++} ++ ++#define CRM_MASK 0xf ++u32 aarch32_insn_mcr_extract_crm(u32 insn) ++{ ++ return insn & CRM_MASK; ++} +diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c +index fde9923..07c4c53 100644 +--- a/arch/arm64/kernel/process.c ++++ b/arch/arm64/kernel/process.c +@@ -163,6 +163,70 @@ void machine_restart(char *cmd) + while (1); + } + ++/* ++ * dump a block of kernel memory from around the given address ++ */ ++static void show_data(unsigned long addr, int nbytes, const char *name) ++{ ++ int i, j; ++ int nlines; ++ u32 *p; ++ ++ /* ++ * don't attempt to dump non-kernel addresses or ++ * values that are probably just small negative numbers ++ */ ++ if (addr < PAGE_OFFSET || addr > -256UL) ++ return; ++ ++ printk("\n%s: %#lx:\n", name, addr); ++ ++ /* ++ * round address down to a 32 bit boundary ++ * and always dump a multiple of 32 bytes ++ */ ++ p = (u32 *)(addr & ~(sizeof(u32) - 1)); ++ nbytes += (addr & (sizeof(u32) - 1)); ++ nlines = (nbytes + 31) / 32; ++ ++ ++ for (i = 0; i < nlines; i++) { ++ /* ++ * just display low 16 bits of address to keep ++ * each line of the dump < 80 characters ++ */ ++ printk("%04lx ", (unsigned long)p & 0xffff); ++ for (j = 0; j < 8; j++) { ++ u32 data; ++ if (probe_kernel_address(p, data)) { ++ printk(" ********"); ++ } else { ++ printk(" %08x", data); ++ } ++ ++p; ++ } ++ printk("\n"); ++ } ++} ++ ++static void show_extra_register_data(struct pt_regs *regs, int nbytes) ++{ ++ mm_segment_t fs; ++ unsigned int i; ++ ++ fs = get_fs(); ++ set_fs(KERNEL_DS); ++ show_data(regs->pc - nbytes, nbytes * 2, "PC"); ++ show_data(regs->regs[30] - nbytes, nbytes * 2, "LR"); ++ show_data(regs->sp - nbytes, nbytes * 2, "SP"); ++ for (i = 0; i < 30; i++) { ++ char name[4]; ++ snprintf(name, sizeof(name), "X%u", i); ++ show_data(regs->regs[i] - nbytes, nbytes * 2, name); ++ } ++ set_fs(fs); ++} ++ + void __show_regs(struct pt_regs *regs) + { + int i, top_reg; +@@ -189,6 +253,8 @@ void __show_regs(struct pt_regs *regs) + if (i % 2 == 0) + printk("\n"); + } ++ if (!user_mode(regs)) ++ show_extra_register_data(regs, 128); + printk("\n"); + } + +diff --git a/arch/arm64/kernel/psci-call.S b/arch/arm64/kernel/psci-call.S +new file mode 100644 +index 0000000..cf83e61 +--- /dev/null ++++ b/arch/arm64/kernel/psci-call.S +@@ -0,0 +1,28 @@ ++/* ++ * 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 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. ++ * ++ * Copyright (C) 2015 ARM Limited ++ * ++ * Author: Will Deacon ++ */ ++ ++#include ++ ++/* int __invoke_psci_fn_hvc(u64 function_id, u64 arg0, u64 arg1, u64 arg2) */ ++ENTRY(__invoke_psci_fn_hvc) ++ hvc #0 ++ ret ++ENDPROC(__invoke_psci_fn_hvc) ++ ++/* int __invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1, u64 arg2) */ ++ENTRY(__invoke_psci_fn_smc) ++ smc #0 ++ ret ++ENDPROC(__invoke_psci_fn_smc) +diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c +index 663da77..81c081e 100644 +--- a/arch/arm64/kernel/psci.c ++++ b/arch/arm64/kernel/psci.c +@@ -57,6 +57,9 @@ static struct psci_operations psci_ops; + static int (*invoke_psci_fn)(u64, u64, u64, u64); + typedef int (*psci_initcall_t)(const struct device_node *); + ++asmlinkage int __invoke_psci_fn_hvc(u64, u64, u64, u64); ++asmlinkage int __invoke_psci_fn_smc(u64, u64, u64, u64); ++ + enum psci_function { + PSCI_FN_CPU_SUSPEND, + PSCI_FN_CPU_ON, +@@ -109,40 +112,6 @@ static void psci_power_state_unpack(u32 power_state, + PSCI_0_2_POWER_STATE_AFFL_SHIFT; + } + +-/* +- * The following two functions are invoked via the invoke_psci_fn pointer +- * and will not be inlined, allowing us to piggyback on the AAPCS. +- */ +-static noinline int __invoke_psci_fn_hvc(u64 function_id, u64 arg0, u64 arg1, +- u64 arg2) +-{ +- asm volatile( +- __asmeq("%0", "x0") +- __asmeq("%1", "x1") +- __asmeq("%2", "x2") +- __asmeq("%3", "x3") +- "hvc #0\n" +- : "+r" (function_id) +- : "r" (arg0), "r" (arg1), "r" (arg2)); +- +- return function_id; +-} +- +-static noinline int __invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1, +- u64 arg2) +-{ +- asm volatile( +- __asmeq("%0", "x0") +- __asmeq("%1", "x1") +- __asmeq("%2", "x2") +- __asmeq("%3", "x3") +- "smc #0\n" +- : "+r" (function_id) +- : "r" (arg0), "r" (arg1), "r" (arg2)); +- +- return function_id; +-} +- + static int psci_get_version(void) + { + int err; +diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c +index 8a4ae8e..d882b83 100644 +--- a/arch/arm64/kernel/ptrace.c ++++ b/arch/arm64/kernel/ptrace.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -551,6 +552,32 @@ static int tls_set(struct task_struct *target, const struct user_regset *regset, + return ret; + } + ++static int system_call_get(struct task_struct *target, ++ const struct user_regset *regset, ++ unsigned int pos, unsigned int count, ++ void *kbuf, void __user *ubuf) ++{ ++ int syscallno = task_pt_regs(target)->syscallno; ++ ++ return user_regset_copyout(&pos, &count, &kbuf, &ubuf, ++ &syscallno, 0, -1); ++} ++ ++static int system_call_set(struct task_struct *target, ++ const struct user_regset *regset, ++ unsigned int pos, unsigned int count, ++ const void *kbuf, const void __user *ubuf) ++{ ++ int syscallno, ret; ++ ++ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &syscallno, 0, -1); ++ if (ret) ++ return ret; ++ ++ task_pt_regs(target)->syscallno = syscallno; ++ return ret; ++} ++ + enum aarch64_regset { + REGSET_GPR, + REGSET_FPR, +@@ -559,6 +586,7 @@ enum aarch64_regset { + REGSET_HW_BREAK, + REGSET_HW_WATCH, + #endif ++ REGSET_SYSTEM_CALL, + }; + + static const struct user_regset aarch64_regsets[] = { +@@ -608,6 +636,14 @@ static const struct user_regset aarch64_regsets[] = { + .set = hw_break_set, + }, + #endif ++ [REGSET_SYSTEM_CALL] = { ++ .core_note_type = NT_ARM_SYSTEM_CALL, ++ .n = 1, ++ .size = sizeof(int), ++ .align = sizeof(int), ++ .get = system_call_get, ++ .set = system_call_set, ++ }, + }; + + static const struct user_regset_view user_aarch64_view = { +@@ -1114,6 +1150,10 @@ static void tracehook_report_syscall(struct pt_regs *regs, + + asmlinkage int syscall_trace_enter(struct pt_regs *regs) + { ++ /* Do the secure computing check first; failures should be fast. */ ++ if (secure_computing() == -1) ++ return -1; ++ + if (test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER); + +diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c +index d502a86..ae8be92 100644 +--- a/arch/arm64/kernel/setup.c ++++ b/arch/arm64/kernel/setup.c +@@ -314,6 +314,8 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys) + while (true) + cpu_relax(); + } ++ ++ dump_stack_set_arch_desc("%s (DT)", of_flat_dt_get_machine_name()); + } + + /* +diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c +index 76920d4..6acffec 100644 +--- a/arch/arm64/kernel/signal32.c ++++ b/arch/arm64/kernel/signal32.c +@@ -185,6 +185,12 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) + err |= __put_user(from->si_uid, &to->si_uid); + err |= __put_user(from->si_int, &to->si_int); + break; ++ case __SI_SYS: ++ err |= __put_user((compat_uptr_t)(unsigned long) ++ from->si_call_addr, &to->si_call_addr); ++ err |= __put_user(from->si_syscall, &to->si_syscall); ++ err |= __put_user(from->si_arch, &to->si_arch); ++ break; + default: /* this is just in case for now ... */ + err |= __put_user(from->si_pid, &to->si_pid); + err |= __put_user(from->si_uid, &to->si_uid); +@@ -433,7 +439,7 @@ static void compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka, + { + compat_ulong_t handler = ptr_to_compat(ka->sa.sa_handler); + compat_ulong_t retcode; +- compat_ulong_t spsr = regs->pstate & ~PSR_f; ++ compat_ulong_t spsr = regs->pstate & ~(PSR_f | COMPAT_PSR_E_BIT); + int thumb; + + /* Check if the handler is written for ARM or Thumb */ +@@ -447,6 +453,9 @@ static void compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka, + /* The IT state must be cleared for both ARM and Thumb-2 */ + spsr &= ~COMPAT_PSR_IT_MASK; + ++ /* Restore the original endianness */ ++ spsr |= COMPAT_PSR_ENDSTATE; ++ + if (ka->sa.sa_flags & SA_RESTORER) { + retcode = ptr_to_compat(ka->sa.sa_restorer); + } else { +diff --git a/arch/arm64/kernel/trace-events-emulation.h b/arch/arm64/kernel/trace-events-emulation.h +new file mode 100644 +index 0000000..ae1dd59 +--- /dev/null ++++ b/arch/arm64/kernel/trace-events-emulation.h +@@ -0,0 +1,35 @@ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM emulation ++ ++#if !defined(_TRACE_EMULATION_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_EMULATION_H ++ ++#include ++ ++TRACE_EVENT(instruction_emulation, ++ ++ TP_PROTO(const char *instr, u64 addr), ++ TP_ARGS(instr, addr), ++ ++ TP_STRUCT__entry( ++ __string(instr, instr) ++ __field(u64, addr) ++ ), ++ ++ TP_fast_assign( ++ __assign_str(instr, instr); ++ __entry->addr = addr; ++ ), ++ ++ TP_printk("instr=\"%s\" addr=0x%llx", __get_str(instr), __entry->addr) ++); ++ ++#endif /* _TRACE_EMULATION_H */ ++ ++/* This part must be outside protection */ ++#undef TRACE_INCLUDE_PATH ++#undef TRACE_INCLUDE_FILE ++#define TRACE_INCLUDE_PATH . ++ ++#define TRACE_INCLUDE_FILE trace-events-emulation ++#include +diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c +index de1b085..0a801e3 100644 +--- a/arch/arm64/kernel/traps.c ++++ b/arch/arm64/kernel/traps.c +@@ -259,6 +259,69 @@ void arm64_notify_die(const char *str, struct pt_regs *regs, + } + } + ++static LIST_HEAD(undef_hook); ++static DEFINE_RAW_SPINLOCK(undef_lock); ++ ++void register_undef_hook(struct undef_hook *hook) ++{ ++ unsigned long flags; ++ ++ raw_spin_lock_irqsave(&undef_lock, flags); ++ list_add(&hook->node, &undef_hook); ++ raw_spin_unlock_irqrestore(&undef_lock, flags); ++} ++ ++void unregister_undef_hook(struct undef_hook *hook) ++{ ++ unsigned long flags; ++ ++ raw_spin_lock_irqsave(&undef_lock, flags); ++ list_del(&hook->node); ++ raw_spin_unlock_irqrestore(&undef_lock, flags); ++} ++ ++static int call_undef_hook(struct pt_regs *regs) ++{ ++ struct undef_hook *hook; ++ unsigned long flags; ++ u32 instr; ++ int (*fn)(struct pt_regs *regs, u32 instr) = NULL; ++ void __user *pc = (void __user *)instruction_pointer(regs); ++ ++ if (!user_mode(regs)) ++ return 1; ++ ++ if (compat_thumb_mode(regs)) { ++ /* 16-bit Thumb instruction */ ++ if (get_user(instr, (u16 __user *)pc)) ++ goto exit; ++ instr = le16_to_cpu(instr); ++ if (aarch32_insn_is_wide(instr)) { ++ u32 instr2; ++ ++ if (get_user(instr2, (u16 __user *)(pc + 2))) ++ goto exit; ++ instr2 = le16_to_cpu(instr2); ++ instr = (instr << 16) | instr2; ++ } ++ } else { ++ /* 32-bit ARM instruction */ ++ if (get_user(instr, (u32 __user *)pc)) ++ goto exit; ++ instr = le32_to_cpu(instr); ++ } ++ ++ raw_spin_lock_irqsave(&undef_lock, flags); ++ list_for_each_entry(hook, &undef_hook, node) ++ if ((instr & hook->instr_mask) == hook->instr_val && ++ (regs->pstate & hook->pstate_mask) == hook->pstate_val) ++ fn = hook->fn; ++ ++ raw_spin_unlock_irqrestore(&undef_lock, flags); ++exit: ++ return fn ? fn(regs, instr) : 1; ++} ++ + asmlinkage void __exception do_undefinstr(struct pt_regs *regs) + { + siginfo_t info; +@@ -268,6 +331,9 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) + if (!aarch32_break_handler(regs)) + return; + ++ if (call_undef_hook(regs) == 0) ++ return; ++ + if (show_unhandled_signals && unhandled_signal(current, SIGILL) && + printk_ratelimit()) { + pr_info("%s[%d]: undefined instruction: pc=%p\n", +diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c +index f752943..b45b313 100644 +--- a/arch/arm64/mm/init.c ++++ b/arch/arm64/mm/init.c +@@ -114,9 +114,11 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max) + } + + #ifdef CONFIG_HAVE_ARCH_PFN_VALID ++#define PFN_MASK ((1UL << (64 - PAGE_SHIFT)) - 1) ++ + int pfn_valid(unsigned long pfn) + { +- return memblock_is_memory(pfn << PAGE_SHIFT); ++ return (pfn & PFN_MASK) == pfn && memblock_is_memory(pfn << PAGE_SHIFT); + } + EXPORT_SYMBOL(pfn_valid); + #endif +diff --git a/arch/x86/include/asm/idle.h b/arch/x86/include/asm/idle.h +index c5d1785..02bab09 100644 +--- a/arch/x86/include/asm/idle.h ++++ b/arch/x86/include/asm/idle.h +@@ -1,13 +1,6 @@ + #ifndef _ASM_X86_IDLE_H + #define _ASM_X86_IDLE_H + +-#define IDLE_START 1 +-#define IDLE_END 2 +- +-struct notifier_block; +-void idle_notifier_register(struct notifier_block *n); +-void idle_notifier_unregister(struct notifier_block *n); +- + #ifdef CONFIG_X86_64 + void enter_idle(void); + void exit_idle(void); +diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c +index a388bb8..0885df5 100644 +--- a/arch/x86/kernel/process.c ++++ b/arch/x86/kernel/process.c +@@ -42,19 +42,6 @@ __visible DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss) = INIT_TSS; + + #ifdef CONFIG_X86_64 + static DEFINE_PER_CPU(unsigned char, is_idle); +-static ATOMIC_NOTIFIER_HEAD(idle_notifier); +- +-void idle_notifier_register(struct notifier_block *n) +-{ +- atomic_notifier_chain_register(&idle_notifier, n); +-} +-EXPORT_SYMBOL_GPL(idle_notifier_register); +- +-void idle_notifier_unregister(struct notifier_block *n) +-{ +- atomic_notifier_chain_unregister(&idle_notifier, n); +-} +-EXPORT_SYMBOL_GPL(idle_notifier_unregister); + #endif + + struct kmem_cache *task_xstate_cachep; +@@ -262,14 +249,14 @@ static inline void play_dead(void) + void enter_idle(void) + { + this_cpu_write(is_idle, 1); +- atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL); ++ idle_notifier_call_chain(IDLE_START); + } + + static void __exit_idle(void) + { + if (x86_test_and_clear_bit_percpu(0, is_idle) == 0) + return; +- atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL); ++ idle_notifier_call_chain(IDLE_END); + } + + /* Called from interrupts to signify idle end */ +diff --git a/block/bsg.c b/block/bsg.c +index 276e869..fc60769 100644 +--- a/block/bsg.c ++++ b/block/bsg.c +@@ -677,6 +677,9 @@ bsg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) + + dprintk("%s: write %Zd bytes\n", bd->name, count); + ++ if (unlikely(segment_eq(get_fs(), KERNEL_DS))) ++ return -EINVAL; ++ + bsg_set_block(bd, file); + + bytes_written = 0; +diff --git a/block/genhd.c b/block/genhd.c +index c2fb3f7..b529e50 100644 +--- a/block/genhd.c ++++ b/block/genhd.c +@@ -829,6 +829,7 @@ static void disk_seqf_stop(struct seq_file *seqf, void *v) + if (iter) { + class_dev_iter_exit(iter); + kfree(iter); ++ seqf->private = NULL; + } + } + +@@ -1116,6 +1117,22 @@ static void disk_release(struct device *dev) + blk_put_queue(disk->queue); + kfree(disk); + } ++ ++static int disk_uevent(struct device *dev, struct kobj_uevent_env *env) ++{ ++ struct gendisk *disk = dev_to_disk(dev); ++ struct disk_part_iter piter; ++ struct hd_struct *part; ++ int cnt = 0; ++ ++ disk_part_iter_init(&piter, disk, 0); ++ while((part = disk_part_iter_next(&piter))) ++ cnt++; ++ disk_part_iter_exit(&piter); ++ add_uevent_var(env, "NPARTS=%u", cnt); ++ return 0; ++} ++ + struct class block_class = { + .name = "block", + }; +@@ -1135,6 +1152,7 @@ static struct device_type disk_type = { + .groups = disk_attr_groups, + .release = disk_release, + .devnode = block_devnode, ++ .uevent = disk_uevent, + }; + + #ifdef CONFIG_PROC_FS +diff --git a/block/ioprio.c b/block/ioprio.c +index 31666c9..3cf3ede 100644 +--- a/block/ioprio.c ++++ b/block/ioprio.c +@@ -148,9 +148,11 @@ static int get_task_ioprio(struct task_struct *p) + ret = security_task_getioprio(p); + if (ret) + goto out; ++ task_lock(p); + ret = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, IOPRIO_NORM); + if (p->io_context) + ret = p->io_context->ioprio; ++ task_unlock(p); + out: + return ret; + } +diff --git a/block/partition-generic.c b/block/partition-generic.c +index 0d9e5f9..47284e7 100644 +--- a/block/partition-generic.c ++++ b/block/partition-generic.c +@@ -217,10 +217,21 @@ static void part_release(struct device *dev) + kfree(p); + } + ++static int part_uevent(struct device *dev, struct kobj_uevent_env *env) ++{ ++ struct hd_struct *part = dev_to_part(dev); ++ ++ add_uevent_var(env, "PARTN=%u", part->partno); ++ if (part->info && part->info->volname[0]) ++ add_uevent_var(env, "PARTNAME=%s", part->info->volname); ++ return 0; ++} ++ + struct device_type part_type = { + .name = "partition", + .groups = part_attr_groups, + .release = part_release, ++ .uevent = part_uevent, + }; + + static void delete_partition_rcu_cb(struct rcu_head *head) +diff --git a/drivers/Kconfig b/drivers/Kconfig +index 1a693d3..845873a 100644 +--- a/drivers/Kconfig ++++ b/drivers/Kconfig +@@ -100,6 +100,8 @@ source "drivers/memstick/Kconfig" + + source "drivers/leds/Kconfig" + ++source "drivers/switch/Kconfig" ++ + source "drivers/accessibility/Kconfig" + + source "drivers/infiniband/Kconfig" +@@ -182,4 +184,8 @@ source "drivers/ras/Kconfig" + + source "drivers/thunderbolt/Kconfig" + ++source "drivers/hidmac/Kconfig" ++ ++source "drivers/hisilicon/Kconfig" ++ + endmenu +diff --git a/drivers/Makefile b/drivers/Makefile +index ebee555..744a120 100644 +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -117,6 +117,7 @@ obj-$(CONFIG_CPU_IDLE) += cpuidle/ + obj-y += mmc/ + obj-$(CONFIG_MEMSTICK) += memstick/ + obj-y += leds/ ++obj-$(CONFIG_SWITCH) += switch/ + obj-$(CONFIG_INFINIBAND) += infiniband/ + obj-$(CONFIG_SGI_SN) += sn/ + obj-y += firmware/ +@@ -161,3 +162,6 @@ obj-$(CONFIG_POWERCAP) += powercap/ + obj-$(CONFIG_MCB) += mcb/ + obj-$(CONFIG_RAS) += ras/ + obj-$(CONFIG_THUNDERBOLT) += thunderbolt/ ++obj-$(CONFIG_CORESIGHT) += hwtracing/coresight/ ++obj-$(CONFIG_HI_DMAC) += hidmac/ ++obj-y += hisilicon/ +diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c +index d24fa19..6d4e44e 100644 +--- a/drivers/acpi/thermal.c ++++ b/drivers/acpi/thermal.c +@@ -800,7 +800,8 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, + result = + thermal_zone_bind_cooling_device + (thermal, trip, cdev, +- THERMAL_NO_LIMIT, THERMAL_NO_LIMIT); ++ THERMAL_NO_LIMIT, THERMAL_NO_LIMIT, ++ THERMAL_WEIGHT_DEFAULT); + else + result = + thermal_zone_unbind_cooling_device +@@ -824,7 +825,8 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, + if (bind) + result = thermal_zone_bind_cooling_device + (thermal, trip, cdev, +- THERMAL_NO_LIMIT, THERMAL_NO_LIMIT); ++ THERMAL_NO_LIMIT, THERMAL_NO_LIMIT, ++ THERMAL_WEIGHT_DEFAULT); + else + result = thermal_zone_unbind_cooling_device + (thermal, trip, cdev); +@@ -841,7 +843,8 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, + result = thermal_zone_bind_cooling_device + (thermal, THERMAL_TRIPS_NONE, + cdev, THERMAL_NO_LIMIT, +- THERMAL_NO_LIMIT); ++ THERMAL_NO_LIMIT, ++ THERMAL_WEIGHT_DEFAULT); + else + result = thermal_zone_unbind_cooling_device + (thermal, THERMAL_TRIPS_NONE, +diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c +index 47bbdc1..a4ac490 100644 +--- a/drivers/amba/bus.c ++++ b/drivers/amba/bus.c +@@ -336,7 +336,7 @@ int amba_device_add(struct amba_device *dev, struct resource *parent) + + amba_put_disable_pclk(dev); + +- if (cid == AMBA_CID) ++ if (cid == AMBA_CID || cid == CORESIGHT_CID) + dev->periphid = pid; + + if (!dev->periphid) +diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig +index cd4cccb..c4d06e0 100644 +--- a/drivers/ata/Kconfig ++++ b/drivers/ata/Kconfig +@@ -2,6 +2,8 @@ + # SATA/PATA driver configuration + # + ++source "drivers/ata/Kconfig.hiahci" ++ + config HAVE_PATA_PLATFORM + bool + help +diff --git a/drivers/ata/Kconfig.hiahci b/drivers/ata/Kconfig.hiahci +new file mode 100644 +index 0000000..ddee693 +--- /dev/null ++++ b/drivers/ata/Kconfig.hiahci +@@ -0,0 +1,36 @@ ++menuconfig HI_SATA ++ bool "hisilicon sata device support" ++ depends on (ARCH_HI3531D || ARCH_HI3521D || ARCH_HI3536C) ++ default y if (ARCH_HI3531D || ARCH_HI3521D || ARCH_HI3536C) ++ select ATA ++ select ATA_VERBOSE_ERROR ++ select SATA_PMP ++ select SATA_AHCI_PLATFORM ++ ++if HI_SATA ++config HI_SATA_IOBASE ++ hex "hi sata IO address" ++ default "0x11010000" if (ARCH_HI3531D || ARCH_HI3521D || ARCH_HI3536C) ++ help ++ hisilicon sata io base address. ++ ++config HI_SATA_FBS ++ int "hi sata FIS-Based switching" ++ default 1 ++ range 0 1 ++ help ++ Hisatav200 supports FBS. ++ FBS is FIS-Based switching. ++ Choose y if you want to use it. ++ ++config HI_SATA_NCQ ++ int "hi sata Native Command Queuing" ++ default 1 ++ range 0 1 ++ help ++ Hisatav200 supports NCQ. ++ NCQ is Native Command Queuing. ++ Choose y if you want to use it. ++ ++endif ++ +diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile +index ae41107..d674ff1 100644 +--- a/drivers/ata/Makefile ++++ b/drivers/ata/Makefile +@@ -1,5 +1,6 @@ + + obj-$(CONFIG_ATA) += libata.o ++obj-$(CONFIG_HI_SATA) += hi_sata_dbg.o + + # non-SFF interface + obj-$(CONFIG_SATA_AHCI) += ahci.o libahci.o +diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h +index 40f0e34..a773f34 100644 +--- a/drivers/ata/ahci.h ++++ b/drivers/ata/ahci.h +@@ -334,6 +334,9 @@ struct ahci_host_priv { + bool got_runtime_pm; /* Did we do pm_runtime_get? */ + struct clk *clks[AHCI_MAX_CLKS]; /* Optional */ + struct regulator *target_pwr; /* Optional */ ++#define PCI_AHCI 0 ++#define ORI_AHCI 1 ++ u32 type; + /* + * If platform uses PHYs. There is a 1:1 relation between the port number and + * the PHY position in this array. +diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c +index 06f1d59..590f823 100644 +--- a/drivers/ata/ahci_platform.c ++++ b/drivers/ata/ahci_platform.c +@@ -22,6 +22,11 @@ + #include + #include "ahci.h" + ++static unsigned int ncq_en = CONFIG_HI_SATA_NCQ; ++module_param(ncq_en, uint, 0600); ++MODULE_PARM_DESC(ncq_en, "ahci ncq flag (default:1)"); ++extern unsigned int sata_port_map; ++ + static const struct ata_port_info ahci_port_info = { + .flags = AHCI_FLAG_COMMON, + .pio_mask = ATA_PIO4, +@@ -31,7 +36,11 @@ static const struct ata_port_info ahci_port_info = { + + static int ahci_probe(struct platform_device *pdev) + { ++#if (!defined(CONFIG_ARCH_HI3531D) \ ++ && !defined(CONFIG_ARCH_HI3521D) \ ++ && !defined(CONFIG_ARCH_HI3536C)) + struct device *dev = &pdev->dev; ++#endif + struct ahci_host_priv *hpriv; + int rc; + +@@ -43,8 +52,17 @@ static int ahci_probe(struct platform_device *pdev) + if (rc) + return rc; + ++#if (defined(CONFIG_ARCH_HI3531D) \ ++ || defined(CONFIG_ARCH_HI3521D) \ ++ || defined(CONFIG_ARCH_HI3536C)) ++ hpriv->type = ORI_AHCI; ++ hpriv->force_port_map = sata_port_map; ++ if (!ncq_en) ++ hpriv->flags |= AHCI_HFLAG_NO_NCQ; ++#else + if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci")) + hpriv->flags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ; ++#endif + + rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info); + if (rc) +diff --git a/drivers/ata/hi_sata_dbg.c b/drivers/ata/hi_sata_dbg.c +new file mode 100644 +index 0000000..8442fbc +--- /dev/null ++++ b/drivers/ata/hi_sata_dbg.c +@@ -0,0 +1,158 @@ ++#include ++#include ++#include ++#include ++#include ++#include "ahci.h" ++#include "hi_sata_dbg.h" ++ ++void hi_sata_mem_dump(unsigned int *addr, unsigned int size) ++{ ++ int ix; ++ ++ for (ix = 0; ix < size; ix += 0x04, addr++) { ++ if (!(ix & 0x0F)) ++ pr_debug("\n0x%08X: ", ++ (unsigned int)virt_to_phys(addr)); ++ pr_debug("%08X ", *addr); ++ } ++} ++EXPORT_SYMBOL(hi_sata_mem_dump); ++ ++void hi_sata_phys_mem_dump(unsigned int addr, unsigned int size) ++{ ++ hi_sata_mem_dump(phys_to_virt(addr), size); ++} ++EXPORT_SYMBOL(hi_sata_phys_mem_dump); ++ ++void hi_ahci_reg_dump(void) ++{ ++ int ix; ++ unsigned int regbase; ++ ++ regbase = CONFIG_HI_SATA_IOBASE; ++ pr_debug("AHCI GHC Register dump:"); ++ for (ix = 0; ix <= 0x28; ix += 0x04) { ++ if (!(ix & 0x0F)) ++ pr_debug("\n0x%08X: ", (regbase + ix)); ++ pr_debug("%08X ", readl(__io_address(regbase + ix))); ++ } ++ pr_debug("\n"); ++ ++ regbase = CONFIG_HI_SATA_IOBASE + 0x0100; ++ pr_debug("AHCI PORT 0 Register dump:"); ++ for (ix = 0; ix <= 0x7F; ix += 0x04) { ++ if (!(ix & 0x0F)) ++ pr_debug("\n0x%08X: ", (regbase + ix)); ++ pr_debug("%08X ", readl(__io_address(regbase + ix))); ++ } ++ pr_debug("\n"); ++} ++EXPORT_SYMBOL(hi_ahci_reg_dump); ++ ++void hi_ahci_rx_fis_dump(struct ata_link *link, int pmp_port_num) ++{ ++ struct ahci_port_priv *pp = NULL; ++ ++ pp = link->ap->private_data; ++ if (NULL == pp) { ++ pr_debug("Error: pp=NULL\n"); ++ return; ++ } ++ pr_debug("ACHI Received FIS:"); ++ hi_sata_phys_mem_dump((unsigned int)(pp->rx_fis_dma), ++ AHCI_RX_FIS_SZ * pmp_port_num); ++ pr_debug("\n"); ++} ++EXPORT_SYMBOL_GPL(hi_ahci_rx_fis_dump); ++ ++void hi_ata_taskfile_dump(struct ata_taskfile *tf) ++{ ++ if (NULL == tf) { ++ pr_debug("Error: tf=NULL\n"); ++ return; ++ } ++ ++ pr_debug("Taskfile dump:\n"); ++ pr_debug("flags:0x%08lX, protocol:0x%02X, command:0x%02X, device:0x%02X, ctl:0x%02X\n", ++ tf->flags, tf->protocol, tf->command, tf->device, tf->ctl); ++ pr_debug("feature:0x%08X, nsect:0x%02X, lbal:0x%02X, lbam:0x%02X, lbah:0x%02X\n", ++ tf->feature, tf->nsect, tf->lbal, tf->lbam, tf->lbah); ++ pr_debug("hob_feature:0x%08X, hob_nsect:0x%02X, hob_lbal:0x%02X, hob_lbam:0x%02X, hob_lbah:0x%02X\n", ++ tf->hob_feature, tf->hob_nsect, tf->hob_lbal, ++ tf->hob_lbam, tf->hob_lbah); ++} ++EXPORT_SYMBOL_GPL(hi_ata_taskfile_dump); ++ ++static void __hi_ahci_st_md(void __iomem *addr) ++{ ++ unsigned int *addr_v; ++ unsigned int *tmp; ++ unsigned int i; ++ ++ addr_v = (unsigned int *)addr; ++ ++ pr_debug("\n\n"); ++ for (i = 0; i < 16; i++) { ++ tmp = addr_v + i * 4; ++ pr_debug("%8x: %8x %8x %8x %8x\n", ++ (unsigned int)(addr + i * 16), ++ *tmp, *(tmp + 1), *(tmp + 2), *(tmp + 3)); ++ } ++ ++ pr_debug("\n"); ++} ++ ++void hi_ahci_st_dump(void __iomem *port_base) ++{ ++ unsigned int tmp; ++ ++ pr_debug("\n**********Dmac status**********\n"); ++ tmp = readl(port_base + 0x58); ++ pr_debug("txdmac_curr_st:0x%2x\n", (tmp>>24) & 0xf); ++ tmp = readl(port_base + 0x64); ++ pr_debug("rxdmac_curr_st:0x%2x\n", (tmp>>24) & 0xf); ++ tmp = readl(port_base + 0x70); ++ pr_debug("dmac tx fifo:count-0x%x-empty-%x-ful-%x\n", ++ (tmp>>0) & 0xff, ++ (tmp>>16) & 0x1, (tmp>>17) & 0x1); ++ pr_debug("dmac rx fifo:count-0x%x-empty-%x-ful-%x\n", ++ (tmp>>8) & 0xff, ++ (tmp>>18) & 0x1, (tmp>>19) & 0x1); ++ ++ pr_debug("\n"); ++ pr_debug("**********HBA status**********\n"); ++ tmp = readl(port_base + 0x50); ++ pr_debug("pxxx_curr_st:0x%2x ndrx_curr_st:0x%2x\n", ++ (tmp>>24) & 0xf, ++ (tmp>>16) & 0xff); ++ pr_debug("cfis_curr_st:0x%2x piox_curr_st:0x%2x\n", ++ (tmp>>12) & 0xf, ++ (tmp>>8) & 0xf); ++ pr_debug("pmxx_curr_st:0x%2x errx_curr_st:0x%2x\n", ++ (tmp>>4) & 0xf, ++ (tmp>>0) & 0xf); ++ ++ pr_debug("\n"); ++ pr_debug("**********Link status**********\n"); ++ tmp = readl(port_base + 0x54); ++ pr_debug("link_curr_st:0x%2x\n", (tmp>>24) & 0x1f); ++ pr_debug("link tx fifo:count-0x%x-empty-%x-ful-%x\n", ++ (tmp>>0) & 0x1f, ++ (tmp>>5) & 0x1, (tmp>>6) & 0x1); ++ pr_debug("link rx fifo:count-0x%x-empty-%x-ful-%x\n", ++ (tmp>>8) & 0x1f, ++ (tmp>>13) & 0x1, (tmp>>14) & 0x1); ++ pr_debug("link df fifo:count-0x%x-empty-%x-ful-%x\n\n", ++ (tmp>>16) & 0x1f, ++ (tmp>>21) & 0x1, (tmp>>22) & 0x1); ++ ++ pr_debug("**********CMD header**********\n"); ++ tmp = readl(port_base + 0x0); ++ __hi_ahci_st_md(phys_to_virt(tmp)); ++ __hi_ahci_st_md(phys_to_virt(tmp+0x100)); ++ __hi_ahci_st_md(phys_to_virt(tmp+0x200)); ++ __hi_ahci_st_md(phys_to_virt(tmp+0x300)); ++} ++EXPORT_SYMBOL_GPL(hi_ahci_st_dump); ++ +diff --git a/drivers/ata/hi_sata_dbg.h b/drivers/ata/hi_sata_dbg.h +new file mode 100644 +index 0000000..f8398db +--- /dev/null ++++ b/drivers/ata/hi_sata_dbg.h +@@ -0,0 +1,47 @@ ++ ++#ifndef _HI_SATA_DBG_H ++#define _HI_SATA_DBG_H ++#include ++#include ++#include ++#include "ahci.h" ++ ++ ++void hi_sata_mem_dump(unsigned int *addr, unsigned int size); ++void hi_sata_phys_mem_dump(unsigned int addr, unsigned int size); ++void hi_ahci_rx_fis_dump(struct ata_link *link, int pmp_port_num); ++void hi_ata_taskfile_dump(struct ata_taskfile *tf); ++void hi_ahci_st_dump(void __iomem *port_base); ++void hi_ahci_reg_dump(void); ++ ++#define HI_AHCI_REG_DUMP(X) \ ++do {\ ++ pr_debug("------------------[ Start ]--------------------\n"); \ ++ pr_debug("Dump AHCI registers at %s %d\n", __func__, __LINE__); \ ++ hi_ahci_reg_dump(); \ ++ pr_debug("------------------[ End ]--------------------\n");\ ++} while (0) ++ ++#define hi_sata_readl(addr) do {\ ++ unsigned int reg = readl((unsigned int)addr); \ ++ pr_debug("HI_AHCI(REG) %s:%d: readl(0x%08X) = 0x%08X\n",\ ++ __func__, __LINE__, (unsigned int)addr, reg); \ ++ reg;\ ++ } while (0) ++ ++#define hi_sata_writel(v, addr) do { writel(v, (unsigned int)addr); \ ++ pr_debug("HI_AHCI(REG) %s:%d: writel(0x%08X) = 0x%08X\n",\ ++ __func__, __LINE__, (unsigned int)addr, \ ++ (unsigned int)(v)); \ ++ } while (0) ++ ++#undef HI_DUMP_AHCI_REG_OPS ++#ifdef HI_DUMP_AHCI_REG_OPS ++#define readl(addr) hi_sata_readl(addr) ++#define write(v, addr) hi_sata_writel(v, addr) ++#endif ++ ++#endif /* _HI_SATA_DBG_H */ ++ ++ ++ +diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c +index de88999..181f249 100644 +--- a/drivers/ata/libahci.c ++++ b/drivers/ata/libahci.c +@@ -46,6 +46,9 @@ + #include "ahci.h" + #include "libata.h" + ++#include ++#include ++ + static int ahci_skip_host_reset; + int ahci_ignore_sss; + EXPORT_SYMBOL_GPL(ahci_ignore_sss); +@@ -56,6 +59,33 @@ MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip) + module_param_named(ignore_sss, ahci_ignore_sss, int, 0444); + MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)"); + ++#ifdef CONFIG_HI_NANO_PHY_SATA ++extern void hisi_sata_reset_rxtx_assert(unsigned int port_no); ++extern void hisi_sata_reset_rxtx_deassert(unsigned int port_no); ++extern void hi_sata_set_eq(unsigned int port_no); ++extern void hi_sata_eq_recovery(unsigned int port_no); ++#endif ++ ++#if (defined(CONFIG_ARCH_HI3531D) \ ++ || defined(CONFIG_ARCH_HI3521D) \ ++ || defined(CONFIG_ARCH_HI3536C)) ++#define AHCI_TIMEOUT_COUNT 10 ++#define AHCI_POLL_TIMER (20 * HZ) ++ ++static int fbs_en = CONFIG_HI_SATA_FBS; ++module_param(fbs_en, uint, 0600); ++MODULE_PARM_DESC(fbs_en, "ahci fbs flags (default:1)"); ++ ++struct ata_fbs_ctrl { ++ unsigned int fbs_enable_ctrl; /* fbs enable or disable control switch */ ++ unsigned int fbs_mode_ctrl; /* 1.5G: fbs disable, 3G/6G: fbs enable */ ++ unsigned int fbs_enable_flag; ++ unsigned int fbs_disable_flag; ++ unsigned int fbs_cmd_issue_flag; ++ struct timer_list poll_timer; ++}; ++static struct ata_fbs_ctrl fbs_ctrl[4]; ++#endif + static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, + unsigned hints); + static ssize_t ahci_led_show(struct ata_port *ap, char *buf); +@@ -1295,8 +1325,32 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, + bool fbs_disabled = false; + int rc; + ++#if (defined(CONFIG_ARCH_HI3531D) \ ++ || defined(CONFIG_ARCH_HI3521D) \ ++ || defined(CONFIG_ARCH_HI3536C)) ++ unsigned int port_num = ap->port_no; ++#endif ++ + DPRINTK("ENTER\n"); + ++#if (defined(CONFIG_ARCH_HI3531D) \ ++ || defined(CONFIG_ARCH_HI3521D) \ ++ || defined(CONFIG_ARCH_HI3536C)) ++ if (fbs_ctrl[port_num].fbs_enable_ctrl && ++ (link->pmp == SATA_PMP_CTRL_PORT) && ++ (hpriv->type == ORI_AHCI)) { ++ struct ahci_port_priv *pp = ap->private_data; ++ ++ if (pp->fbs_enabled == false) ++ ahci_enable_fbs(ap); ++ ++ fbs_ctrl[port_num].fbs_enable_flag = 0; ++ fbs_ctrl[port_num].fbs_disable_flag = 0; ++ fbs_ctrl[port_num].fbs_cmd_issue_flag = 0; ++ ++ } ++#endif ++ + /* prepare for SRST (AHCI-1.1 10.4.1) */ + rc = ahci_kick_engine(ap); + if (rc && rc != -EOPNOTSUPP) +@@ -1325,6 +1379,10 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, + AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY, msecs)) { + rc = -EIO; + reason = "1st FIS failed"; ++#ifdef CONFIG_HI_NANO_PHY_SATA ++ hisi_sata_reset_rxtx_assert(ap->port_no); ++ hisi_sata_reset_rxtx_deassert(ap->port_no); ++#endif + goto fail; + } + +@@ -1471,9 +1529,23 @@ static void ahci_postreset(struct ata_link *link, unsigned int *class) + struct ata_port *ap = link->ap; + void __iomem *port_mmio = ahci_port_base(ap); + u32 new_tmp, tmp; ++#ifdef CONFIG_HI_NANO_PHY_SATA ++ u32 sstatus; ++#endif + + ata_std_postreset(link, class); + ++#ifdef CONFIG_HI_NANO_PHY_SATA ++ /* recovery EQ, when SATA link up 6Gbps for Nano PHY */ ++ if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 && ++ ((sstatus & 0xf) == 0x3)) { /* link online */ ++ if (((sstatus >> 4) & 0xf) == 3) /* 3: 6Gbps, 2: 3Gbps, 1: 1.5Gbps */ ++ hi_sata_eq_recovery(ap->port_no); ++ } else ++ hi_sata_set_eq(ap->port_no); ++ ++#endif ++ + /* Make sure port's ATAPI bit is set appropriately */ + new_tmp = tmp = readl(port_mmio + PORT_CMD); + if (*class == ATA_DEV_ATAPI) +@@ -1514,6 +1586,70 @@ static int ahci_pmp_qc_defer(struct ata_queued_cmd *qc) + struct ata_port *ap = qc->ap; + struct ahci_port_priv *pp = ap->private_data; + ++#if (defined(CONFIG_ARCH_HI3531D) \ ++ || defined(CONFIG_ARCH_HI3521D) \ ++ || defined(CONFIG_ARCH_HI3536C)) ++ struct ahci_host_priv *hpriv = ap->host->private_data; ++ int is_atapi = ata_is_atapi(qc->tf.protocol); ++ void __iomem *port_mmio = ahci_port_base(ap); ++ unsigned int port_num = ap->port_no; ++ unsigned int cmd_timeout_count; ++ ++ if (fbs_ctrl[port_num].fbs_enable_ctrl && ++ (ap->link.pmp == SATA_PMP_CTRL_PORT) && ++ (hpriv->type == ORI_AHCI)) { ++ if (is_atapi || fbs_ctrl[ap->port_no].fbs_cmd_issue_flag) { ++ mod_timer(&fbs_ctrl[port_num].poll_timer, ++ jiffies + AHCI_POLL_TIMER); ++ ++ if (!fbs_ctrl[port_num].fbs_disable_flag) { ++ cmd_timeout_count = 0; ++ while (readl(port_mmio + PORT_SCR_ACT) ++ || readl(port_mmio ++ + PORT_CMD_ISSUE) ++ || readl(port_mmio ++ + PORT_IRQ_STAT)) { ++ cmd_timeout_count++; ++ if (cmd_timeout_count >= ++ AHCI_TIMEOUT_COUNT) { ++ fbs_ctrl[ap->port_no]. ++ fbs_cmd_issue_flag = 1; ++ return ATA_DEFER_LINK; ++ } ++ } ++ ++ if (pp->fbs_enabled == true) ++ ahci_disable_fbs(ap); ++ ++ ap->excl_link = NULL; ++ ap->nr_active_links = 0; ++ fbs_ctrl[port_num].fbs_disable_flag = 1; ++ fbs_ctrl[port_num].fbs_enable_flag = 0; ++ fbs_ctrl[ap->port_no].fbs_cmd_issue_flag = 0; ++ } ++ } else { ++ if (fbs_ctrl[port_num].fbs_enable_flag) { ++ cmd_timeout_count = 0; ++ while (readl(port_mmio + PORT_SCR_ACT) ++ || readl(port_mmio ++ + PORT_CMD_ISSUE) ++ || readl(port_mmio ++ + PORT_IRQ_STAT)) { ++ cmd_timeout_count++; ++ if (cmd_timeout_count >= ++ AHCI_TIMEOUT_COUNT) { ++ return ATA_DEFER_LINK; ++ } ++ } ++ ++ if (pp->fbs_enabled == false) ++ ahci_enable_fbs(ap); ++ fbs_ctrl[port_num].fbs_enable_flag = 0; ++ fbs_ctrl[port_num].fbs_disable_flag = 0; ++ } ++ } ++ } ++#endif + if (!sata_pmp_attached(ap) || pp->fbs_enabled) + return ata_std_qc_defer(qc); + else +@@ -1558,6 +1694,9 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) + ahci_fill_cmd_slot(pp, qc->tag, opts); + } + ++#if (!defined(CONFIG_ARCH_HI3531D) \ ++ && !defined(CONFIG_ARCH_HI3536C) \ ++ && !defined(CONFIG_ARCH_HI3521D)) + static void ahci_fbs_dec_intr(struct ata_port *ap) + { + struct ahci_port_priv *pp = ap->private_data; +@@ -1581,6 +1720,7 @@ static void ahci_fbs_dec_intr(struct ata_port *ap) + if (fbs & PORT_FBS_DEC) + dev_err(ap->host->dev, "failed to clear device error\n"); + } ++#endif + + static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) + { +@@ -1684,11 +1824,24 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) + + /* okay, let's hand over to EH */ + +- if (irq_stat & PORT_IRQ_FREEZE) +- ata_port_freeze(ap); +- else if (fbs_need_dec) { ++ if (irq_stat & PORT_IRQ_FREEZE) { ++ if ((irq_stat & PORT_IRQ_IF_ERR) && fbs_need_dec) { ++ ata_link_abort(link); ++#if (!defined(CONFIG_ARCH_HI3531D) \ ++ && !defined(CONFIG_ARCH_HI3536C) \ ++ && !defined(CONFIG_ARCH_HI3521D)) ++ ++ ahci_fbs_dec_intr(ap); ++#endif ++ } else ++ ata_port_freeze(ap); ++ } else if (fbs_need_dec) { + ata_link_abort(link); ++#if (!defined(CONFIG_ARCH_HI3531D) \ ++ && !defined(CONFIG_ARCH_HI3536C) \ ++ && !defined(CONFIG_ARCH_HI3521D)) + ahci_fbs_dec_intr(ap); ++#endif + } else + ata_port_abort(ap); + } +@@ -2092,7 +2245,11 @@ static void ahci_enable_fbs(struct ata_port *ap) + writel(fbs | PORT_FBS_EN, port_mmio + PORT_FBS); + fbs = readl(port_mmio + PORT_FBS); + if (fbs & PORT_FBS_EN) { ++#if (!defined(CONFIG_ARCH_HI3531D) \ ++ && !defined(CONFIG_ARCH_HI3536C) \ ++ && !defined(CONFIG_ARCH_HI3521D)) + dev_info(ap->host->dev, "FBS is enabled\n"); ++#endif + pp->fbs_enabled = true; + pp->fbs_last_dev = -1; /* initialization */ + } else +@@ -2127,11 +2284,20 @@ static void ahci_disable_fbs(struct ata_port *ap) + if (fbs & PORT_FBS_EN) + dev_err(ap->host->dev, "Failed to disable FBS\n"); + else { ++#if (defined(CONFIG_ARCH_HI3531D) \ ++ || defined(CONFIG_ARCH_HI3521D) \ ++ || defined(CONFIG_ARCH_HI3536C)) + dev_info(ap->host->dev, "FBS is disabled\n"); ++#endif + pp->fbs_enabled = false; + } + + hpriv->start_engine(ap); ++#if (defined(CONFIG_ARCH_HI3531D) \ ++ || defined(CONFIG_ARCH_HI3521D) \ ++ || defined(CONFIG_ARCH_HI3536C)) ++ writel(HI_SATA_FIFOTH_VALUE, (port_mmio + HI_SATA_PORT_FIFOTH)); ++#endif + } + + static void ahci_pmp_attach(struct ata_port *ap) +@@ -2140,11 +2306,26 @@ static void ahci_pmp_attach(struct ata_port *ap) + struct ahci_port_priv *pp = ap->private_data; + u32 cmd; + ++#if (defined(CONFIG_ARCH_HI3531D) \ ++ || defined(CONFIG_ARCH_HI3521D) \ ++ || defined(CONFIG_ARCH_HI3536C)) ++ struct ahci_host_priv *hpriv = ap->host->private_data; ++ unsigned int port_num = ap->port_no; ++#endif ++ + cmd = readl(port_mmio + PORT_CMD); + cmd |= PORT_CMD_PMP; + writel(cmd, port_mmio + PORT_CMD); + + ahci_enable_fbs(ap); ++#if (defined(CONFIG_ARCH_HI3531D) \ ++ || defined(CONFIG_ARCH_HI3521D) \ ++ || defined(CONFIG_ARCH_HI3536C)) ++ if (hpriv->type == ORI_AHCI) { ++ if (!fbs_ctrl[port_num].fbs_enable_ctrl) ++ ahci_disable_fbs(ap); ++ } ++#endif + + pp->intr_mask |= PORT_IRQ_BAD_PMP; + +@@ -2211,6 +2392,21 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg) + } + #endif + ++#if (defined(CONFIG_ARCH_HI3531D) \ ++ || defined(CONFIG_ARCH_HI3521D) \ ++ || defined(CONFIG_ARCH_HI3536C)) ++static void ahci_poll_func(unsigned long arg) ++{ ++ struct ata_port *ap = (struct ata_port *)arg; ++ unsigned int port_num = ap->port_no; ++ ++ if (ap->link.pmp == SATA_PMP_CTRL_PORT) { ++ fbs_ctrl[port_num].fbs_enable_flag = 1; ++ fbs_ctrl[port_num].fbs_disable_flag = 0; ++ } ++} ++#endif ++ + static int ahci_port_start(struct ata_port *ap) + { + struct ahci_host_priv *hpriv = ap->host->private_data; +@@ -2304,6 +2500,22 @@ static int ahci_port_start(struct ata_port *ap) + + ap->private_data = pp; + ++#if (defined(CONFIG_ARCH_HI3531D) \ ++ || defined(CONFIG_ARCH_HI3521D) \ ++ || defined(CONFIG_ARCH_HI3536C)) ++ if (hpriv->type == ORI_AHCI) { ++ fbs_ctrl[ap->port_no].fbs_enable_ctrl = fbs_en; ++ fbs_ctrl[ap->port_no].fbs_enable_flag = 0; ++ fbs_ctrl[ap->port_no].fbs_disable_flag = 0; ++ fbs_ctrl[ap->port_no].fbs_cmd_issue_flag = 0; ++ ++ init_timer(&fbs_ctrl[ap->port_no].poll_timer); ++ fbs_ctrl[ap->port_no].poll_timer.function = ahci_poll_func; ++ fbs_ctrl[ap->port_no].poll_timer.data = (unsigned long)ap; ++ fbs_ctrl[ap->port_no].poll_timer.expires = jiffies + AHCI_POLL_TIMER; ++ } ++#endif ++ + /* engage engines, captain */ + return ahci_port_resume(ap); + } +diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c +index 0b03f90..4ca5f2d 100644 +--- a/drivers/ata/libahci_platform.c ++++ b/drivers/ata/libahci_platform.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include "ahci.h" + + static void ahci_host_stop(struct ata_host *host); +diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig +index df04227..c7d273b 100644 +--- a/drivers/base/Kconfig ++++ b/drivers/base/Kconfig +@@ -220,8 +220,13 @@ config GENERIC_CPU_DEVICES + bool + default n + ++config HAVE_CPU_AUTOPROBE ++ def_bool ARCH_HAS_CPU_AUTOPROBE ++ + config GENERIC_CPU_AUTOPROBE + bool ++ depends on !ARCH_HAS_CPU_AUTOPROBE ++ select HAVE_CPU_AUTOPROBE + + config SOC_BUS + bool +diff --git a/drivers/base/core.c b/drivers/base/core.c +index 842d047..93ad1c7 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -531,6 +531,7 @@ static DEVICE_ATTR_RO(dev); + + /* /sys/devices/ */ + struct kset *devices_kset; ++EXPORT_SYMBOL(devices_kset); + + /** + * device_create_file - create sysfs attribute file for device. +diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c +index 006b1bc..8a38bf8 100644 +--- a/drivers/base/cpu.c ++++ b/drivers/base/cpu.c +@@ -287,6 +287,7 @@ static void cpu_device_release(struct device *dev) + */ + } + ++#ifdef CONFIG_HAVE_CPU_AUTOPROBE + #ifdef CONFIG_GENERIC_CPU_AUTOPROBE + static ssize_t print_cpu_modalias(struct device *dev, + struct device_attribute *attr, +@@ -309,6 +310,9 @@ static ssize_t print_cpu_modalias(struct device *dev, + buf[n++] = '\n'; + return n; + } ++#else ++#define print_cpu_modalias arch_print_cpu_modalias ++#endif + + static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env) + { +@@ -342,7 +346,7 @@ int register_cpu(struct cpu *cpu, int num) + cpu->dev.offline_disabled = !cpu->hotpluggable; + cpu->dev.offline = !cpu_online(num); + cpu->dev.of_node = of_get_cpu_node(num, NULL); +-#ifdef CONFIG_GENERIC_CPU_AUTOPROBE ++#ifdef CONFIG_HAVE_CPU_AUTOPROBE + cpu->dev.bus->uevent = cpu_uevent; + #endif + cpu->dev.groups = common_cpu_attr_groups; +@@ -366,7 +370,7 @@ struct device *get_cpu_device(unsigned cpu) + } + EXPORT_SYMBOL_GPL(get_cpu_device); + +-#ifdef CONFIG_GENERIC_CPU_AUTOPROBE ++#ifdef CONFIG_HAVE_CPU_AUTOPROBE + static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL); + #endif + +@@ -380,7 +384,7 @@ static struct attribute *cpu_root_attrs[] = { + &cpu_attrs[2].attr.attr, + &dev_attr_kernel_max.attr, + &dev_attr_offline.attr, +-#ifdef CONFIG_GENERIC_CPU_AUTOPROBE ++#ifdef CONFIG_HAVE_CPU_AUTOPROBE + &dev_attr_modalias.attr, + #endif + NULL +diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c +index 950fff9..6e57cc1 100644 +--- a/drivers/base/dma-contiguous.c ++++ b/drivers/base/dma-contiguous.c +@@ -195,6 +195,7 @@ struct page *dma_alloc_from_contiguous(struct device *dev, int count, + + return cma_alloc(dev_get_cma_area(dev), count, align); + } ++EXPORT_SYMBOL(dma_alloc_from_contiguous); + + /** + * dma_release_from_contiguous() - release allocated pages +@@ -211,6 +212,7 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages, + { + return cma_release(dev_get_cma_area(dev), pages, count); + } ++EXPORT_SYMBOL(dma_release_from_contiguous); + + /* + * Support for reserved memory regions defined in device tree +diff --git a/drivers/base/platform.c b/drivers/base/platform.c +index 360272c..43d6530 100644 +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -731,7 +731,7 @@ static ssize_t driver_override_store(struct device *dev, + const char *buf, size_t count) + { + struct platform_device *pdev = to_platform_device(dev); +- char *driver_override, *old = pdev->driver_override, *cp; ++ char *driver_override, *old, *cp; + + if (count > PATH_MAX) + return -EINVAL; +@@ -744,6 +744,9 @@ static ssize_t driver_override_store(struct device *dev, + if (cp) + *cp = '\0'; + ++ device_lock(dev); ++ old = pdev->driver_override; ++ + if (strlen(driver_override)) { + pdev->driver_override = driver_override; + } else { +@@ -751,6 +754,8 @@ static ssize_t driver_override_store(struct device *dev, + pdev->driver_override = NULL; + } + ++ device_unlock(dev); ++ + kfree(old); + + return count; +@@ -760,8 +765,12 @@ static ssize_t driver_override_show(struct device *dev, + struct device_attribute *attr, char *buf) + { + struct platform_device *pdev = to_platform_device(dev); ++ ssize_t len; + +- return sprintf(buf, "%s\n", pdev->driver_override); ++ device_lock(dev); ++ len = sprintf(buf, "%s\n", pdev->driver_override); ++ device_unlock(dev); ++ return len; + } + static DEVICE_ATTR_RW(driver_override); + +diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c +index 9717d5f..bf957ca 100644 +--- a/drivers/base/power/main.c ++++ b/drivers/base/power/main.c +@@ -32,10 +32,13 @@ + #include + #include + #include ++#include + + #include "../base.h" + #include "power.h" +- ++#ifdef CONFIG_HISI_SNAPSHOT_BOOT ++extern int pm_notifier_call_chain(unsigned long val); ++#endif + typedef int (*pm_callback_t)(struct device *); + + /* +@@ -58,6 +61,12 @@ struct suspend_stats suspend_stats; + static DEFINE_MUTEX(dpm_list_mtx); + static pm_message_t pm_transition; + ++static void dpm_drv_timeout(unsigned long data); ++struct dpm_drv_wd_data { ++ struct device *dev; ++ struct task_struct *tsk; ++}; ++ + static int async_error; + + static char *pm_verb(int event) +@@ -828,6 +837,30 @@ static void async_resume(void *data, async_cookie_t cookie) + } + + /** ++ * dpm_drv_timeout - Driver suspend / resume watchdog handler ++ * @data: struct device which timed out ++ * ++ * Called when a driver has timed out suspending or resuming. ++ * There's not much we can do here to recover so ++ * BUG() out for a crash-dump ++ * ++ */ ++static void dpm_drv_timeout(unsigned long data) ++{ ++ struct dpm_drv_wd_data *wd_data = (void *)data; ++ struct device *dev = wd_data->dev; ++ struct task_struct *tsk = wd_data->tsk; ++ ++ printk(KERN_EMERG "**** DPM device timeout: %s (%s)\n", dev_name(dev), ++ (dev->driver ? dev->driver->name : "no driver")); ++ ++ printk(KERN_EMERG "dpm suspend stack:\n"); ++ show_stack(tsk, NULL); ++ ++ BUG(); ++} ++ ++/** + * dpm_resume - Execute "resume" callbacks for non-sysdev devices. + * @state: PM transition of the system being carried out. + * +@@ -973,6 +1006,9 @@ void dpm_complete(pm_message_t state) + */ + void dpm_resume_end(pm_message_t state) + { ++#ifdef CONFIG_HISI_SNAPSHOT_BOOT ++ pm_notifier_call_chain(PM_RESUME_DEVICE_PREPARE); ++#endif + dpm_resume(state); + dpm_complete(state); + } +@@ -1336,6 +1372,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) + pm_callback_t callback = NULL; + char *info = NULL; + int error = 0; ++ struct timer_list timer; ++ struct dpm_drv_wd_data data; ++ char suspend_abort[MAX_SUSPEND_ABORT_LEN]; + DECLARE_DPM_WATCHDOG_ON_STACK(wd); + + dpm_wait_for_children(dev, async); +@@ -1353,12 +1392,23 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) + pm_wakeup_event(dev, 0); + + if (pm_wakeup_pending()) { ++ pm_get_active_wakeup_sources(suspend_abort, ++ MAX_SUSPEND_ABORT_LEN); ++ log_suspend_abort_reason(suspend_abort); + async_error = -EBUSY; + goto Complete; + } + + if (dev->power.syscore) + goto Complete; ++ ++ data.dev = dev; ++ data.tsk = get_current(); ++ init_timer_on_stack(&timer); ++ timer.expires = jiffies + HZ * 12; ++ timer.function = dpm_drv_timeout; ++ timer.data = (unsigned long)&data; ++ add_timer(&timer); + + if (dev->power.direct_complete) { + if (pm_runtime_status_suspended(dev)) { +@@ -1439,6 +1489,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) + device_unlock(dev); + dpm_watchdog_clear(&wd); + ++ del_timer_sync(&timer); ++ destroy_timer_on_stack(&timer); ++ + Complete: + complete_all(&dev->power.completion); + if (error) +@@ -1661,6 +1714,10 @@ int dpm_suspend_start(pm_message_t state) + dpm_save_failed_step(SUSPEND_PREPARE); + } else + error = dpm_suspend(state); ++#ifdef CONFIG_HISI_SNAPSHOT_BOOT ++ if (!error) ++ pm_notifier_call_chain(PM_POST_DEVICE_SUSPEND); ++#endif + return error; + } + EXPORT_SYMBOL_GPL(dpm_suspend_start); +diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c +index c2744b3..f1cf53a 100644 +--- a/drivers/base/power/wakeup.c ++++ b/drivers/base/power/wakeup.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + + #include "power.h" +@@ -668,6 +669,37 @@ void pm_wakeup_event(struct device *dev, unsigned int msec) + } + EXPORT_SYMBOL_GPL(pm_wakeup_event); + ++void pm_get_active_wakeup_sources(char *pending_wakeup_source, size_t max) ++{ ++ struct wakeup_source *ws, *last_active_ws = NULL; ++ int len = 0; ++ bool active = false; ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(ws, &wakeup_sources, entry) { ++ if (ws->active) { ++ if (!active) ++ len += scnprintf(pending_wakeup_source, max, ++ "Pending Wakeup Sources: "); ++ len += scnprintf(pending_wakeup_source + len, max - len, ++ "%s ", ws->name); ++ active = true; ++ } else if (!active && ++ (!last_active_ws || ++ ktime_to_ns(ws->last_time) > ++ ktime_to_ns(last_active_ws->last_time))) { ++ last_active_ws = ws; ++ } ++ } ++ if (!active && last_active_ws) { ++ scnprintf(pending_wakeup_source, max, ++ "Last active Wakeup Source: %s", ++ last_active_ws->name); ++ } ++ rcu_read_unlock(); ++} ++EXPORT_SYMBOL_GPL(pm_get_active_wakeup_sources); ++ + void pm_print_active_wakeup_sources(void) + { + struct wakeup_source *ws; +diff --git a/drivers/base/syscore.c b/drivers/base/syscore.c +index 8d98a32..96c34a9 100644 +--- a/drivers/base/syscore.c ++++ b/drivers/base/syscore.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + static LIST_HEAD(syscore_ops_list); + static DEFINE_MUTEX(syscore_ops_lock); +@@ -75,6 +76,8 @@ int syscore_suspend(void) + return 0; + + err_out: ++ log_suspend_abort_reason("System core suspend callback %pF failed", ++ ops->suspend); + pr_err("PM: System core suspend callback %pF failed.\n", ops->suspend); + + list_for_each_entry_continue(ops, &syscore_ops_list, node) +diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig +index efefd12..b96a3a5 100644 +--- a/drivers/char/Kconfig ++++ b/drivers/char/Kconfig +@@ -6,6 +6,19 @@ menu "Character devices" + + source "drivers/tty/Kconfig" + ++config DEVMEM ++ bool "Memory device driver" ++ default y ++ help ++ The memory driver provides two character devices, mem and kmem, which ++ provide access to the system's memory. The mem device is a view of ++ physical memory, and each byte in the device corresponds to the ++ matching physical address. The kmem device is the same as mem, but ++ the addresses correspond to the kernel's virtual address space rather ++ than physical memory. These devices are standard parts of a Linux ++ system and most users should say Y here. You might say N if very ++ security conscience or memory is tight. ++ + config DEVKMEM + bool "/dev/kmem virtual device support" + default y +@@ -579,6 +592,10 @@ config DEVPORT + depends on ISA || PCI + default y + ++config DCC_TTY ++ tristate "DCC tty driver" ++ depends on ARM ++ + source "drivers/s390/char/Kconfig" + + config MSM_SMD_PKT +diff --git a/drivers/char/Makefile b/drivers/char/Makefile +index d06cde26..e38fb5b 100644 +--- a/drivers/char/Makefile ++++ b/drivers/char/Makefile +@@ -55,6 +55,7 @@ obj-$(CONFIG_PCMCIA) += pcmcia/ + obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o + obj-$(CONFIG_TCG_TPM) += tpm/ + ++obj-$(CONFIG_DCC_TTY) += dcc_tty.o + obj-$(CONFIG_PS3_FLASH) += ps3flash.o + + obj-$(CONFIG_JS_RTC) += js-rtc.o +diff --git a/drivers/char/dcc_tty.c b/drivers/char/dcc_tty.c +new file mode 100644 +index 0000000..0a62d41 +--- /dev/null ++++ b/drivers/char/dcc_tty.c +@@ -0,0 +1,326 @@ ++/* drivers/char/dcc_tty.c ++ * ++ * Copyright (C) 2007 Google, 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. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++MODULE_DESCRIPTION("DCC TTY Driver"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION("1.0"); ++ ++DEFINE_SPINLOCK(g_dcc_tty_lock); ++static struct hrtimer g_dcc_timer; ++static char g_dcc_buffer[16]; ++static int g_dcc_buffer_head; ++static int g_dcc_buffer_count; ++static unsigned g_dcc_write_delay_usecs = 1; ++static struct tty_driver *g_dcc_tty_driver; ++static struct tty_struct *g_dcc_tty; ++static int g_dcc_tty_open_count; ++ ++static void dcc_poll_locked(void) ++{ ++ char ch; ++ int rch; ++ int written; ++ ++ while (g_dcc_buffer_count) { ++ ch = g_dcc_buffer[g_dcc_buffer_head]; ++ asm( ++ "mrc 14, 0, r15, c0, c1, 0\n" ++ "mcrcc 14, 0, %1, c0, c5, 0\n" ++ "movcc %0, #1\n" ++ "movcs %0, #0\n" ++ : "=r" (written) ++ : "r" (ch) ++ ); ++ if (written) { ++ if (ch == '\n') ++ g_dcc_buffer[g_dcc_buffer_head] = '\r'; ++ else { ++ g_dcc_buffer_head = (g_dcc_buffer_head + 1) % ARRAY_SIZE(g_dcc_buffer); ++ g_dcc_buffer_count--; ++ if (g_dcc_tty) ++ tty_wakeup(g_dcc_tty); ++ } ++ g_dcc_write_delay_usecs = 1; ++ } else { ++ if (g_dcc_write_delay_usecs > 0x100) ++ break; ++ g_dcc_write_delay_usecs <<= 1; ++ udelay(g_dcc_write_delay_usecs); ++ } ++ } ++ ++ if (g_dcc_tty && !test_bit(TTY_THROTTLED, &g_dcc_tty->flags)) { ++ asm( ++ "mrc 14, 0, %0, c0, c1, 0\n" ++ "tst %0, #(1 << 30)\n" ++ "moveq %0, #-1\n" ++ "mrcne 14, 0, %0, c0, c5, 0\n" ++ : "=r" (rch) ++ ); ++ if (rch >= 0) { ++ ch = rch; ++ tty_insert_flip_string(g_dcc_tty->port, &ch, 1); ++ tty_flip_buffer_push(g_dcc_tty->port); ++ } ++ } ++ ++ ++ if (g_dcc_buffer_count) ++ hrtimer_start(&g_dcc_timer, ktime_set(0, g_dcc_write_delay_usecs * NSEC_PER_USEC), HRTIMER_MODE_REL); ++ else ++ hrtimer_start(&g_dcc_timer, ktime_set(0, 20 * NSEC_PER_MSEC), HRTIMER_MODE_REL); ++} ++ ++static int dcc_tty_open(struct tty_struct * tty, struct file * filp) ++{ ++ int ret; ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&g_dcc_tty_lock, irq_flags); ++ if (g_dcc_tty == NULL || g_dcc_tty == tty) { ++ g_dcc_tty = tty; ++ g_dcc_tty_open_count++; ++ ret = 0; ++ } else ++ ret = -EBUSY; ++ spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags); ++ ++ printk("dcc_tty_open, tty %p, f_flags %x, returned %d\n", tty, filp->f_flags, ret); ++ ++ return ret; ++} ++ ++static void dcc_tty_close(struct tty_struct * tty, struct file * filp) ++{ ++ printk("dcc_tty_close, tty %p, f_flags %x\n", tty, filp->f_flags); ++ if (g_dcc_tty == tty) { ++ if (--g_dcc_tty_open_count == 0) ++ g_dcc_tty = NULL; ++ } ++} ++ ++static int dcc_write(const unsigned char *buf_start, int count) ++{ ++ const unsigned char *buf = buf_start; ++ unsigned long irq_flags; ++ int copy_len; ++ int space_left; ++ int tail; ++ ++ if (count < 1) ++ return 0; ++ ++ spin_lock_irqsave(&g_dcc_tty_lock, irq_flags); ++ do { ++ tail = (g_dcc_buffer_head + g_dcc_buffer_count) % ARRAY_SIZE(g_dcc_buffer); ++ copy_len = ARRAY_SIZE(g_dcc_buffer) - tail; ++ space_left = ARRAY_SIZE(g_dcc_buffer) - g_dcc_buffer_count; ++ if (copy_len > space_left) ++ copy_len = space_left; ++ if (copy_len > count) ++ copy_len = count; ++ memcpy(&g_dcc_buffer[tail], buf, copy_len); ++ g_dcc_buffer_count += copy_len; ++ buf += copy_len; ++ count -= copy_len; ++ if (copy_len < count && copy_len < space_left) { ++ space_left -= copy_len; ++ copy_len = count; ++ if (copy_len > space_left) { ++ copy_len = space_left; ++ } ++ memcpy(g_dcc_buffer, buf, copy_len); ++ buf += copy_len; ++ count -= copy_len; ++ g_dcc_buffer_count += copy_len; ++ } ++ dcc_poll_locked(); ++ space_left = ARRAY_SIZE(g_dcc_buffer) - g_dcc_buffer_count; ++ } while(count && space_left); ++ spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags); ++ return buf - buf_start; ++} ++ ++static int dcc_tty_write(struct tty_struct * tty, const unsigned char *buf, int count) ++{ ++ int ret; ++ /* printk("dcc_tty_write %p, %d\n", buf, count); */ ++ ret = dcc_write(buf, count); ++ if (ret != count) ++ printk("dcc_tty_write %p, %d, returned %d\n", buf, count, ret); ++ return ret; ++} ++ ++static int dcc_tty_write_room(struct tty_struct *tty) ++{ ++ int space_left; ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&g_dcc_tty_lock, irq_flags); ++ space_left = ARRAY_SIZE(g_dcc_buffer) - g_dcc_buffer_count; ++ spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags); ++ return space_left; ++} ++ ++static int dcc_tty_chars_in_buffer(struct tty_struct *tty) ++{ ++ int ret; ++ asm( ++ "mrc 14, 0, %0, c0, c1, 0\n" ++ "mov %0, %0, LSR #30\n" ++ "and %0, %0, #1\n" ++ : "=r" (ret) ++ ); ++ return ret; ++} ++ ++static void dcc_tty_unthrottle(struct tty_struct * tty) ++{ ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&g_dcc_tty_lock, irq_flags); ++ dcc_poll_locked(); ++ spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags); ++} ++ ++static enum hrtimer_restart dcc_tty_timer_func(struct hrtimer *timer) ++{ ++ unsigned long irq_flags; ++ ++ spin_lock_irqsave(&g_dcc_tty_lock, irq_flags); ++ dcc_poll_locked(); ++ spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags); ++ return HRTIMER_NORESTART; ++} ++ ++void dcc_console_write(struct console *co, const char *b, unsigned count) ++{ ++#if 1 ++ dcc_write(b, count); ++#else ++ /* blocking printk */ ++ while (count > 0) { ++ int written; ++ written = dcc_write(b, count); ++ if (written) { ++ b += written; ++ count -= written; ++ } ++ } ++#endif ++} ++ ++static struct tty_driver *dcc_console_device(struct console *c, int *index) ++{ ++ *index = 0; ++ return g_dcc_tty_driver; ++} ++ ++static int __init dcc_console_setup(struct console *co, char *options) ++{ ++ if (co->index != 0) ++ return -ENODEV; ++ return 0; ++} ++ ++ ++static struct console dcc_console = ++{ ++ .name = "ttyDCC", ++ .write = dcc_console_write, ++ .device = dcc_console_device, ++ .setup = dcc_console_setup, ++ .flags = CON_PRINTBUFFER, ++ .index = -1, ++}; ++ ++static struct tty_operations dcc_tty_ops = { ++ .open = dcc_tty_open, ++ .close = dcc_tty_close, ++ .write = dcc_tty_write, ++ .write_room = dcc_tty_write_room, ++ .chars_in_buffer = dcc_tty_chars_in_buffer, ++ .unthrottle = dcc_tty_unthrottle, ++}; ++ ++static int __init dcc_tty_init(void) ++{ ++ int ret; ++ ++ hrtimer_init(&g_dcc_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ g_dcc_timer.function = dcc_tty_timer_func; ++ ++ g_dcc_tty_driver = alloc_tty_driver(1); ++ if (!g_dcc_tty_driver) { ++ printk(KERN_ERR "dcc_tty_probe: alloc_tty_driver failed\n"); ++ ret = -ENOMEM; ++ goto err_alloc_tty_driver_failed; ++ } ++ g_dcc_tty_driver->owner = THIS_MODULE; ++ g_dcc_tty_driver->driver_name = "dcc"; ++ g_dcc_tty_driver->name = "ttyDCC"; ++ g_dcc_tty_driver->major = 0; // auto assign ++ g_dcc_tty_driver->minor_start = 0; ++ g_dcc_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; ++ g_dcc_tty_driver->subtype = SERIAL_TYPE_NORMAL; ++ g_dcc_tty_driver->init_termios = tty_std_termios; ++ g_dcc_tty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; ++ tty_set_operations(g_dcc_tty_driver, &dcc_tty_ops); ++ ret = tty_register_driver(g_dcc_tty_driver); ++ if (ret) { ++ printk(KERN_ERR "dcc_tty_probe: tty_register_driver failed, %d\n", ret); ++ goto err_tty_register_driver_failed; ++ } ++ tty_register_device(g_dcc_tty_driver, 0, NULL); ++ ++ register_console(&dcc_console); ++ hrtimer_start(&g_dcc_timer, ktime_set(0, 0), HRTIMER_MODE_REL); ++ ++ return 0; ++ ++err_tty_register_driver_failed: ++ put_tty_driver(g_dcc_tty_driver); ++ g_dcc_tty_driver = NULL; ++err_alloc_tty_driver_failed: ++ return ret; ++} ++ ++static void __exit dcc_tty_exit(void) ++{ ++ int ret; ++ ++ tty_unregister_device(g_dcc_tty_driver, 0); ++ ret = tty_unregister_driver(g_dcc_tty_driver); ++ if (ret < 0) { ++ printk(KERN_ERR "dcc_tty_remove: tty_unregister_driver failed, %d\n", ret); ++ } else { ++ put_tty_driver(g_dcc_tty_driver); ++ } ++ g_dcc_tty_driver = NULL; ++} ++ ++module_init(dcc_tty_init); ++module_exit(dcc_tty_exit); ++ ++ +diff --git a/drivers/char/mem.c b/drivers/char/mem.c +index 524b707..f6ea960 100644 +--- a/drivers/char/mem.c ++++ b/drivers/char/mem.c +@@ -58,6 +58,7 @@ static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size) + } + #endif + ++#if defined(CONFIG_DEVMEM) || defined(CONFIG_DEVKMEM) + #ifdef CONFIG_STRICT_DEVMEM + static inline int range_is_allowed(unsigned long pfn, unsigned long size) + { +@@ -83,7 +84,9 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size) + return 1; + } + #endif ++#endif + ++#ifdef CONFIG_DEVMEM + void __weak unxlate_dev_mem_ptr(unsigned long phys, void *addr) + { + } +@@ -216,6 +219,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf, + *ppos += written; + return written; + } ++#endif /* CONFIG_DEVMEM */ ++ ++#if defined(CONFIG_DEVMEM) || defined(CONFIG_DEVKMEM) + + int __weak phys_mem_access_prot_allowed(struct file *file, + unsigned long pfn, unsigned long size, pgprot_t *vma_prot) +@@ -338,6 +344,49 @@ static int mmap_mem(struct file *file, struct vm_area_struct *vma) + return 0; + } + ++static int mmap_venc(struct file *file, struct vm_area_struct *vma) ++{ ++ size_t size = (vma->vm_end - vma->vm_start)>>1; ++ ++ if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size)) ++ return -EINVAL; ++ ++ if (!private_mapping_ok(vma)) ++ return -ENOSYS; ++ ++ if (!range_is_allowed(vma->vm_pgoff, size)) ++ return -EPERM; ++ ++ if (!phys_mem_access_prot_allowed(file, vma->vm_pgoff, size, ++ &vma->vm_page_prot)) ++ return -EINVAL; ++ ++ vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, ++ size, ++ vma->vm_page_prot); ++ ++ vma->vm_ops = &mmap_mem_ops; ++ ++ /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */ ++ if (remap_pfn_range(vma, ++ vma->vm_start, ++ vma->vm_pgoff, ++ size, ++ vma->vm_page_prot)) ++ return -EAGAIN; ++ ++ if (remap_pfn_range(vma, ++ vma->vm_start + size, ++ vma->vm_pgoff, ++ size, ++ vma->vm_page_prot)) ++ return -EAGAIN; ++ ++ return 0; ++} ++ ++#endif /* CONFIG_DEVMEM */ ++ + #ifdef CONFIG_DEVKMEM + static int mmap_kmem(struct file *file, struct vm_area_struct *vma) + { +@@ -667,6 +716,8 @@ static loff_t null_lseek(struct file *file, loff_t offset, int orig) + return file->f_pos = 0; + } + ++#if defined(CONFIG_DEVMEM) || defined(CONFIG_DEVKMEM) || defined(CONFIG_DEVPORT) ++ + /* + * The memory devices use the full 32/64 bits of the offset, and so we cannot + * check against negative addresses: they are ok. The return value is weird, +@@ -700,10 +751,14 @@ static loff_t memory_lseek(struct file *file, loff_t offset, int orig) + return ret; + } + ++#endif ++ ++#if defined(CONFIG_DEVMEM) || defined(CONFIG_DEVKMEM) || defined(CONFIG_DEVPORT) + static int open_port(struct inode *inode, struct file *filp) + { + return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; + } ++#endif + + #define zero_lseek null_lseek + #define full_lseek null_lseek +@@ -712,6 +767,7 @@ static int open_port(struct inode *inode, struct file *filp) + #define open_mem open_port + #define open_kmem open_mem + ++#ifdef CONFIG_DEVMEM + static const struct file_operations mem_fops = { + .llseek = memory_lseek, + .read = read_mem, +@@ -721,6 +777,17 @@ static const struct file_operations mem_fops = { + .get_unmapped_area = get_unmapped_area_mem, + }; + ++ ++static const struct file_operations venc_fops = { ++ .llseek = memory_lseek, ++ .read = read_mem, ++ .write = write_mem, ++ .mmap = mmap_venc, ++ .open = open_mem, ++ .get_unmapped_area = get_unmapped_area_mem, ++}; ++#endif ++ + #ifdef CONFIG_DEVKMEM + static const struct file_operations kmem_fops = { + .llseek = memory_lseek, +@@ -782,7 +849,9 @@ static const struct memdev { + const struct file_operations *fops; + struct backing_dev_info *dev_info; + } devlist[] = { ++#ifdef CONFIG_DEVMEM + [1] = { "mem", 0, &mem_fops, &directly_mappable_cdev_bdi }, ++#endif + #ifdef CONFIG_DEVKMEM + [2] = { "kmem", 0, &kmem_fops, &directly_mappable_cdev_bdi }, + #endif +@@ -797,6 +866,9 @@ static const struct memdev { + #ifdef CONFIG_PRINTK + [11] = { "kmsg", 0644, &kmsg_fops, NULL }, + #endif ++#ifdef CONFIG_DEVMEM ++ [13] = { "vencmem", 0, &venc_fops, &directly_mappable_cdev_bdi }, ++#endif + }; + + static int memory_open(struct inode *inode, struct file *filp) +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 9cd6968..f41b114 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -661,7 +661,8 @@ retry: + if (r == &nonblocking_pool) { + prandom_reseed_late(); + wake_up_interruptible(&urandom_init_wait); +- pr_notice("random: %s pool is initialized\n", r->name); ++ /* Don't want to print this sentence and annotate it! 2015-12-23 */ ++ /*pr_notice("random: %s pool is initialized\n", r->name);*/ + } + } + +diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig +index 455fd17..dd112f0 100644 +--- a/drivers/clk/Kconfig ++++ b/drivers/clk/Kconfig +@@ -134,6 +134,24 @@ config COMMON_CLK_PXA + ---help--- + Sypport for the Marvell PXA SoC. + ++config COMMON_CLK_FREQ_STATS_ACCOUNTING ++ bool "Enable clock frequency stats accounting" ++ depends on COMMON_CLK ++ depends on DEBUG_FS ++ ---help--- ++ Allows accounting of the time spent by various clocks in each ++ of its operating frequency. The stats get reported as a part ++ of clk_summary. Would be be useful in finding out which ++ components are running at what power states to debug ++ battery consumption issues. ++ ++config COMMON_CLK_BEGIN_ACCOUNTING_FROM_BOOT ++ bool "Start clock frequency stats accounting from boot" ++ depends on COMMON_CLK_FREQ_STATS_ACCOUNTING ++ ---help--- ++ Enabling this option starts the frequency accounting right from ++ the boot. ++ + source "drivers/clk/qcom/Kconfig" + + endmenu +diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile +index d5fba5b..62d74f2 100644 +--- a/drivers/clk/Makefile ++++ b/drivers/clk/Makefile +@@ -46,6 +46,10 @@ obj-$(CONFIG_ARCH_BERLIN) += berlin/ + obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/ + obj-$(CONFIG_ARCH_HIP04) += hisilicon/ + obj-$(CONFIG_ARCH_HIX5HD2) += hisilicon/ ++obj-$(CONFIG_ARCH_HISI) += hisilicon/ ++obj-$(CONFIG_ARCH_HI3536C) += hisilicon/ ++obj-$(CONFIG_ARCH_HI3531D) += hisilicon/ ++obj-$(CONFIG_ARCH_HI3521D) += hisilicon/ + obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ + ifeq ($(CONFIG_COMMON_CLK), y) + obj-$(CONFIG_ARCH_MMP) += mmp/ +diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c +index 7d74830..d2f0a56 100644 +--- a/drivers/clk/clk.c ++++ b/drivers/clk/clk.c +@@ -114,6 +114,134 @@ static struct hlist_head *orphan_list[] = { + NULL, + }; + ++#ifdef CONFIG_COMMON_CLK_FREQ_STATS_ACCOUNTING ++ ++#ifdef CONFIG_COMMON_CLK_BEGIN_ACCOUNTING_FROM_BOOT ++static bool freq_stats_on = true; ++#else ++static bool freq_stats_on; ++#endif /*CONFIG_COMMON_CLK_BEGIN_ACCOUNTING_FROM_BOOT*/ ++ ++static void free_tree(struct rb_node *node) ++{ ++ struct freq_stats *this; ++ ++ if (!node) ++ return; ++ ++ free_tree(node->rb_left); ++ free_tree(node->rb_right); ++ ++ this = rb_entry(node, struct freq_stats, node); ++ kfree(this); ++} ++ ++static struct freq_stats *freq_stats_insert(struct rb_root *freq_stats_table, ++ unsigned long rate) ++{ ++ struct rb_node **new = &(freq_stats_table->rb_node), *parent = NULL; ++ struct freq_stats *this; ++ ++ /* Figure out where to put new node */ ++ while (*new) { ++ this = rb_entry(*new, struct freq_stats, node); ++ parent = *new; ++ ++ if (rate < this->rate) ++ new = &((*new)->rb_left); ++ else if (rate > this->rate) ++ new = &((*new)->rb_right); ++ else ++ return this; ++ } ++ ++ this = kzalloc(sizeof(*this), GFP_ATOMIC); ++ this->rate = rate; ++ ++ /* Add new node and rebalance tree. */ ++ rb_link_node(&this->node, parent, new); ++ rb_insert_color(&this->node, freq_stats_table); ++ ++ return this; ++} ++ ++static void generic_print_freq_stats_table(struct seq_file *m, ++ struct clk *clk, ++ bool indent, int level) ++{ ++ struct rb_node *pos; ++ struct freq_stats *cur; ++ ++ if (indent) ++ seq_printf(m, "%*s*%s%20s", level * 3 + 1, "", ++ !clk->current_freq_stats ? "[" : "", ++ "default_freq"); ++ else ++ seq_printf(m, "%2s%20s", !clk->current_freq_stats ? "[" : "", ++ "default_freq"); ++ ++ if (!clk->current_freq_stats && !ktime_equal(clk->start_time, ++ ktime_set(0, 0))) ++ seq_printf(m, "%40llu", ++ ktime_to_ms(ktime_add(clk->default_freq_time, ++ ktime_sub(ktime_get(), clk->start_time)))); ++ else ++ seq_printf(m, "%40llu", ktime_to_ms(clk->default_freq_time)); ++ ++ if (!clk->current_freq_stats) ++ seq_puts(m, "]"); ++ ++ seq_puts(m, "\n"); ++ ++ for (pos = rb_first(&clk->freq_stats_table); pos; pos = rb_next(pos)) { ++ cur = rb_entry(pos, typeof(*cur), node); ++ ++ if (indent) ++ seq_printf(m, "%*s*%s%20lu", level * 3 + 1, "", ++ cur->rate == clk->rate ? "[" : "", cur->rate); ++ else ++ seq_printf(m, "%2s%20lu", cur->rate == clk->rate ? ++ "[" : "", cur->rate); ++ ++ if (cur->rate == clk->rate && !ktime_equal(clk->start_time, ++ ktime_set(0, 0))) ++ seq_printf(m, "%40llu", ++ ktime_to_ms(ktime_add(cur->time_spent, ++ ktime_sub(ktime_get(), clk->start_time)))); ++ else ++ seq_printf(m, "%40llu", ktime_to_ms(cur->time_spent)); ++ ++ if (cur->rate == clk->rate) ++ seq_puts(m, "]"); ++ seq_puts(m, "\n"); ++ } ++} ++ ++static int clock_print_freq_stats_table(struct seq_file *m, void *unused) ++{ ++ struct clk *clk = m->private; ++ ++ if (!(clk->flags & CLK_GET_RATE_NOCACHE)) ++ generic_print_freq_stats_table(m, clk, false, 0); ++ ++ return 0; ++} ++ ++static int freq_stats_table_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, clock_print_freq_stats_table, ++ inode->i_private); ++} ++ ++static const struct file_operations freq_stats_table_fops = { ++ .open = freq_stats_table_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = seq_release, ++}; ++#endif /*CONFIG_COMMON_CLK_FREQ_STATS_ACCOUNTING*/ ++ ++ + static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level) + { + if (!c) +@@ -124,6 +252,12 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level) + 30 - level * 3, c->name, + c->enable_count, c->prepare_count, clk_get_rate(c), + clk_get_accuracy(c), clk_get_phase(c)); ++ ++#ifdef CONFIG_COMMON_CLK_FREQ_STATS_ACCOUNTING ++ if (!(c->flags & CLK_GET_RATE_NOCACHE)) ++ generic_print_freq_stats_table(s, c, true, level); ++#endif /*CONFIG_COMMON_CLK_FREQ_STATS_ACCOUNTING*/ ++ + } + + static void clk_summary_show_subtree(struct seq_file *s, struct clk *c, +@@ -240,6 +374,78 @@ static const struct file_operations clk_dump_fops = { + .release = single_release, + }; + ++#ifdef CONFIG_COMMON_CLK_FREQ_STATS_ACCOUNTING ++static int freq_stats_get(void *unused, u64 *val) ++{ ++ *val = freq_stats_on; ++ return 0; ++} ++ ++static void clk_traverse_subtree(struct clk *clk, int freq_stats_on) ++{ ++ struct clk *child; ++ struct rb_node *node; ++ ++ if (!clk) ++ return; ++ ++ if (freq_stats_on) { ++ for (node = rb_first(&clk->freq_stats_table); ++ node; node = rb_next(node)) ++ rb_entry(node, struct freq_stats, node)->time_spent = ++ ktime_set(0, 0); ++ ++ clk->current_freq_stats = freq_stats_insert( ++ &clk->freq_stats_table, ++ clk_get_rate(clk)); ++ ++ if (clk->enable_count > 0) ++ clk->start_time = ktime_get(); ++ } else { ++ if (clk->enable_count > 0) { ++ if (!clk->current_freq_stats) ++ clk->default_freq_time = ++ ktime_add(clk->default_freq_time, ++ ktime_sub(ktime_get(), clk->start_time)); ++ else ++ clk->current_freq_stats->time_spent = ++ ktime_add(clk->current_freq_stats->time_spent, ++ ktime_sub(ktime_get(), clk->start_time)); ++ ++ clk->start_time = ktime_set(0, 0); ++ } ++ } ++ hlist_for_each_entry(child, &clk->children, child_node) ++ clk_traverse_subtree(child, freq_stats_on); ++} ++ ++static int freq_stats_set(void *data, u64 val) ++{ ++ struct clk *c; ++ unsigned long flags; ++ struct hlist_head **lists = (struct hlist_head **)data; ++ ++ clk_prepare_lock(); ++ flags = clk_enable_lock(); ++ ++ if (val == 0) ++ freq_stats_on = 0; ++ else ++ freq_stats_on = 1; ++ ++ for (; *lists; lists++) ++ hlist_for_each_entry(c, *lists, child_node) ++ clk_traverse_subtree(c, freq_stats_on); ++ ++ clk_enable_unlock(flags); ++ clk_prepare_unlock(); ++ ++ return 0; ++} ++DEFINE_SIMPLE_ATTRIBUTE(freq_stats_fops, freq_stats_get, ++ freq_stats_set, "%llu\n"); ++#endif /*CONFIG_COMMON_CLK_FREQ_STATS_ACCOUNTING*/ ++ + static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) + { + struct dentry *d; +@@ -291,6 +497,14 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) + if (!d) + goto err_out; + ++#ifdef CONFIG_COMMON_CLK_FREQ_STATS_ACCOUNTING ++ d = debugfs_create_file("frequency_stats_table", S_IRUGO, clk->dentry, ++ clk, &freq_stats_table_fops); ++ ++ if (!d) ++ goto err_out; ++#endif /*CONFIG_COMMON_CLK_FREQ_STATS_ACCOUNTING*/ ++ + if (clk->ops->debug_init) { + ret = clk->ops->debug_init(clk->hw, clk->dentry); + if (ret) +@@ -403,6 +617,13 @@ static int __init clk_debug_init(void) + if (!d) + return -ENOMEM; + ++#ifdef CONFIG_COMMON_CLK_FREQ_STATS_ACCOUNTING ++ d = debugfs_create_file("freq_stats_on", S_IRUGO|S_IWUSR, ++ rootdir, &all_lists, &freq_stats_fops); ++ if (!d) ++ return -ENOMEM; ++#endif /*CONFIG_COMMON_CLK_FREQ_STATS_ACCOUNTING*/ ++ + mutex_lock(&clk_debug_lock); + hlist_for_each_entry(clk, &clk_debug_list, debug_node) + clk_debug_create_one(clk, rootdir); +@@ -852,6 +1073,22 @@ static void __clk_disable(struct clk *clk) + if (clk->ops->disable) + clk->ops->disable(clk->hw); + ++#ifdef CONFIG_COMMON_CLK_FREQ_STATS_ACCOUNTING ++ ++ if (freq_stats_on) { ++ if (!clk->current_freq_stats) ++ clk->default_freq_time = ++ ktime_add(clk->default_freq_time, ++ ktime_sub(ktime_get(), clk->start_time)); ++ else ++ clk->current_freq_stats->time_spent = ++ ktime_add(clk->current_freq_stats->time_spent, ++ ktime_sub(ktime_get(), clk->start_time)); ++ ++ clk->start_time = ktime_set(0, 0); ++ } ++#endif /*CONFIG_COMMON_CLK_FREQ_STATS_ACCOUNTING*/ ++ + __clk_disable(clk->parent); + } + +@@ -903,6 +1140,11 @@ static int __clk_enable(struct clk *clk) + return ret; + } + } ++ ++#ifdef CONFIG_COMMON_CLK_FREQ_STATS_ACCOUNTING ++ if (freq_stats_on) ++ clk->start_time = ktime_get(); ++#endif /*CONFIG_COMMON_CLK_FREQ_STATS_ACCOUNTING*/ + } + + clk->enable_count++; +@@ -1483,6 +1725,32 @@ static void clk_change_rate(struct clk *clk) + + clk->rate = clk_recalc(clk, best_parent_rate); + ++#ifdef CONFIG_COMMON_CLK_FREQ_STATS_ACCOUNTING ++ if (freq_stats_on) { ++ if (!ktime_equal(clk->start_time, ktime_set(0, 0))) { ++ if (!clk->current_freq_stats) ++ clk->default_freq_time = ++ ktime_add(clk->default_freq_time, ++ ktime_sub(ktime_get(), ++ clk->start_time)); ++ else ++ clk->current_freq_stats->time_spent = ++ ktime_add( ++ clk->current_freq_stats->time_spent, ++ ktime_sub(ktime_get(), ++ clk->start_time)); ++ } ++ ++ clk->current_freq_stats = freq_stats_insert( ++ &clk->freq_stats_table, ++ clk->rate); ++ ++ if (clk->enable_count > 0) ++ clk->start_time = ktime_get(); ++ } ++#endif /*CONFIG_COMMON_CLK_FREQ_STATS_ACCOUNTING*/ ++ ++ + if (clk->notifier_count && old_rate != clk->rate) + __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate); + +@@ -2112,6 +2380,11 @@ static void __clk_release(struct kref *ref) + + kfree(clk->parent_names); + kfree(clk->name); ++ ++#ifdef CONFIG_COMMON_CLK_FREQ_STATS_ACCOUNTING ++ free_tree(clk->freq_stats_table.rb_node); ++#endif/*CONFIG_COMMON_CLK_FREQ_STATS_ACCOUNTING*/ ++ + kfree(clk); + } + +diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile +index 038c02f..cf455ca 100644 +--- a/drivers/clk/hisilicon/Makefile ++++ b/drivers/clk/hisilicon/Makefile +@@ -2,8 +2,17 @@ + # Hisilicon Clock specific Makefile + # + +-obj-y += clk.o clkgate-separated.o ++obj-y += clk.o clkgate-separated.o clk_ops.o + + obj-$(CONFIG_ARCH_HI3xxx) += clk-hi3620.o + obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o + obj-$(CONFIG_ARCH_HIX5HD2) += clk-hix5hd2.o ++obj-$(CONFIG_ARCH_HI3516CV300) += clk-hi3516cv300.o reset.o ++obj-$(CONFIG_ARCH_HI3519) += clk-hi3519.o reset.o ++obj-$(CONFIG_ARCH_HI3519V101) += clk-hi3519v101.o reset.o ++obj-$(CONFIG_ARCH_HI3516AV200) += clk-hi3516av200.o reset.o ++obj-$(CONFIG_ARCH_HI3559) += clk-hi3559.o reset.o ++obj-$(CONFIG_ARCH_HI3556) += clk-hi3556.o reset.o ++obj-$(CONFIG_ARCH_HI3536C) += clk-hi3536c.o reset.o ++obj-$(CONFIG_ARCH_HI3531D) += clk-hi3531d.o reset.o ++obj-$(CONFIG_ARCH_HI3521D) += clk-hi3521d.o reset.o +diff --git a/drivers/clk/hisilicon/clk-hi3516av200.c b/drivers/clk/hisilicon/clk-hi3516av200.c +new file mode 100644 +index 0000000..ca4c165 +--- /dev/null ++++ b/drivers/clk/hisilicon/clk-hi3516av200.c +@@ -0,0 +1,385 @@ ++/* ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "clk.h" ++#include "reset.h" ++ ++/******************************************************************************/ ++struct hi3516av200_pll_clock { ++ u32 id; ++ const char *name; ++ const char *parent_name; ++ u32 ctrl_reg1; ++ u8 frac_shift; ++ u8 frac_width; ++ u8 postdiv1_shift; ++ u8 postdiv1_width; ++ u8 postdiv2_shift; ++ u8 postdiv2_width; ++ u32 ctrl_reg2; ++ u8 fbdiv_shift; ++ u8 fbdiv_width; ++ u8 refdiv_shift; ++ u8 refdiv_width; ++}; ++ ++struct hi3516av200_clk_pll { ++ struct clk_hw hw; ++ u32 id; ++ void __iomem *ctrl_reg1; ++ u8 frac_shift; ++ u8 frac_width; ++ u8 postdiv1_shift; ++ u8 postdiv1_width; ++ u8 postdiv2_shift; ++ u8 postdiv2_width; ++ void __iomem *ctrl_reg2; ++ u8 fbdiv_shift; ++ u8 fbdiv_width; ++ u8 refdiv_shift; ++ u8 refdiv_width; ++}; ++ ++static struct hisi_fixed_rate_clock hi3516av200_fixed_rate_clks[] __initdata = { ++ { HI3516AV200_FIXED_2376M, "2376m", NULL, CLK_IS_ROOT, 2376000000UL, }, ++ { HI3516AV200_FIXED_1188M, "1188m", NULL, CLK_IS_ROOT, 1188000000, }, ++ { HI3516AV200_FIXED_594M, "594m", NULL, CLK_IS_ROOT, 594000000, }, ++ { HI3516AV200_FIXED_297M, "297m", NULL, CLK_IS_ROOT, 297000000, }, ++ { HI3516AV200_FIXED_148P5M, "148p5m", NULL, CLK_IS_ROOT, 148500000, }, ++ { HI3516AV200_FIXED_74P25M, "74p25m", NULL, CLK_IS_ROOT, 74250000, }, ++ { HI3516AV200_FIXED_792M, "792m", NULL, CLK_IS_ROOT, 792000000, }, ++ { HI3516AV200_FIXED_475M, "475m", NULL, CLK_IS_ROOT, 475000000, }, ++ { HI3516AV200_FIXED_340M, "340m", NULL, CLK_IS_ROOT, 340000000, }, ++ { HI3516AV200_FIXED_72M, "72m", NULL, CLK_IS_ROOT, 72000000, }, ++ { HI3516AV200_FIXED_400M, "400m", NULL, CLK_IS_ROOT, 400000000, }, ++ { HI3516AV200_FIXED_200M, "200m", NULL, CLK_IS_ROOT, 200000000, }, ++ { HI3516AV200_FIXED_54M, "54m", NULL, CLK_IS_ROOT, 54000000, }, ++ { HI3516AV200_FIXED_27M, "27m", NULL, CLK_IS_ROOT, 1188000000, }, ++ { HI3516AV200_FIXED_37P125M, "37p125m", NULL, CLK_IS_ROOT, 37125000, }, ++ { HI3516AV200_FIXED_3000M, "3000m", NULL, CLK_IS_ROOT, 3000000000UL, }, ++ { HI3516AV200_FIXED_1500M, "1500m", NULL, CLK_IS_ROOT, 1500000000, }, ++ { HI3516AV200_FIXED_500M, "500m", NULL, CLK_IS_ROOT, 500000000, }, ++ { HI3516AV200_FIXED_250M, "250m", NULL, CLK_IS_ROOT, 250000000, }, ++ { HI3516AV200_FIXED_125M, "125m", NULL, CLK_IS_ROOT, 125000000, }, ++ { HI3516AV200_FIXED_1000M, "1000m", NULL, CLK_IS_ROOT, 1000000000, }, ++ { HI3516AV200_FIXED_600M, "600m", NULL, CLK_IS_ROOT, 600000000, }, ++ { HI3516AV200_FIXED_750M, "750m", NULL, CLK_IS_ROOT, 750000000, }, ++ { HI3516AV200_FIXED_150M, "150m", NULL, CLK_IS_ROOT, 150000000, }, ++ { HI3516AV200_FIXED_75M, "75m", NULL, CLK_IS_ROOT, 75000000, }, ++ { HI3516AV200_FIXED_300M, "300m", NULL, CLK_IS_ROOT, 300000000, }, ++ { HI3516AV200_FIXED_60M, "60m", NULL, CLK_IS_ROOT, 60000000, }, ++ { HI3516AV200_FIXED_214M, "214m", NULL, CLK_IS_ROOT, 214000000, }, ++ { HI3516AV200_FIXED_107M, "107m", NULL, CLK_IS_ROOT, 107000000, }, ++ { HI3516AV200_FIXED_100M, "100m", NULL, CLK_IS_ROOT, 100000000, }, ++ { HI3516AV200_FIXED_50M, "50m", NULL, CLK_IS_ROOT, 50000000, }, ++ { HI3516AV200_FIXED_25M, "25m", NULL, CLK_IS_ROOT, 25000000, }, ++ { HI3516AV200_FIXED_24M, "24m", NULL, CLK_IS_ROOT, 24000000, }, ++ { HI3516AV200_FIXED_3M, "3m", NULL, CLK_IS_ROOT, 3000000, }, ++ { HI3516AV200_FIXED_198M, "198m", NULL, CLK_IS_ROOT, 198000000, }, ++ { HI3516AV200_FIXED_396M, "396m", NULL, CLK_IS_ROOT, 396000000, }, ++}; ++ ++static const char *sysaxi_mux_p[] __initconst = {"24m", "198m", }; ++static u32 sysaxi_mux_table[] = {0, 1}; ++ ++static const char *fmc_mux_p[] __initconst = { ++ "24m", "75m", "125m", "150m", "198m", "250m", "300m", "396m", }; ++static u32 fmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6, 7}; ++ ++static const char *mmc_mux_p[] __initconst = { ++ "100m", "198m", "396m", "594m", "792m", "1188m", }; ++static u32 mmc_mux_table[] = {0, 1, 3, 4, 5, 7}; ++ ++static const char *a17_mux_p[] __initconst = { ++ "24m", "apll", "594m", "792m", }; ++static u32 a17_mux_table[] = {0, 1, 3, 4}; ++ ++static const char *i2c_mux_p[] __initconst = {"clk_sysapb", "50m"}; ++static u32 i2c_mux_table[] = {0, 1}; ++ ++static struct hisi_mux_clock hi3516av200_mux_clks[] __initdata = { ++ { HI3516AV200_SYSAXI_MUX, "sysaxi_mux", sysaxi_mux_p, ++ ARRAY_SIZE(sysaxi_mux_p), ++ CLK_SET_RATE_PARENT, 0x34, 12, 2, 0, sysaxi_mux_table, }, ++ { HI3516AV200_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc0, 2, 3, 0, fmc_mux_table, }, ++ { HI3516AV200_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 10, 3, 0, mmc_mux_table, }, ++ { HI3516AV200_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 2, 3, 0, mmc_mux_table, }, ++ { HI3516AV200_MMC2_MUX, "mmc2_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 18, 3, 0, mmc_mux_table, }, ++ { HI3516AV200_A17_MUX, "a17_mux", a17_mux_p, ARRAY_SIZE(a17_mux_p), ++ CLK_SET_RATE_PARENT, 0x34, 4, 3, 0, a17_mux_table, }, ++ { HI3516AV200_I2C_MUX, "i2c_mux", i2c_mux_p, ARRAY_SIZE(i2c_mux_p), ++ CLK_SET_RATE_PARENT, 0xe4, 26, 1, 0, i2c_mux_table, }, ++ ++}; ++ ++static struct hisi_fixed_factor_clock ++ hi3516av200_fixed_factor_clks[] __initdata = { ++ { HI3516AV200_SYSAPB_CLK, "clk_sysapb", "sysaxi_mux", 1, 4, ++ CLK_SET_RATE_PARENT}, ++ { HI3516AV200_MMC0_FAC_CLK, "mmc0_fac", "mmc0_mux", 1, 8, ++ CLK_SET_RATE_PARENT}, ++ { HI3516AV200_MMC1_FAC_CLK, "mmc1_fac", "mmc1_mux", 1, 8, ++ CLK_SET_RATE_PARENT}, ++ { HI3516AV200_MMC2_FAC_CLK, "mmc2_fac", "mmc2_mux", 1, 8, ++ CLK_SET_RATE_PARENT}, ++}; ++ ++static struct hisi_gate_clock hi3516av200_gate_clks[] __initdata = { ++#ifdef CONFIG_HIFMC ++ /* fmc */ ++ { HI3516AV200_FMC_CLK, "clk_fmc", "fmc_mux", ++ CLK_SET_RATE_PARENT, 0xc0, 1, 0, }, ++#endif ++ /* mmc */ ++ { HI3516AV200_MMC0_CLK, "clk_mmc0", "mmc0_fac", ++ CLK_SET_RATE_PARENT, 0xc4, 9, 0, }, ++ { HI3516AV200_MMC1_CLK, "clk_mmc1", "mmc1_fac", ++ CLK_SET_RATE_PARENT, 0xc4, 1, 0, }, ++ { HI3516AV200_MMC2_CLK, "clk_mmc2", "mmc2_fac", ++ CLK_SET_RATE_PARENT, 0xc4, 17, 0, }, ++ ++ /* usb ctrl */ ++ { HI3516AV200_USB2_CTRL_UTMI0_REQ, "usb2_cttl_utmi0_req", NULL, ++ CLK_SET_RATE_PARENT, 0xb4, 5, 1, }, ++ { HI3516AV200_USB2_HRST_REQ, "usb2_hrst_req", NULL, ++ CLK_SET_RATE_PARENT, 0xb4, 0, 1, }, ++ { HI3516AV200_USB3_CLK, "usb3_vcc_srst_req2", NULL, ++ CLK_SET_RATE_PARENT, 0xb8, 0, 1, }, ++ ++ /* uart */ ++ { HI3516AV200_UART0_CLK, "clk_uart0", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 20, 0, }, ++ { HI3516AV200_UART1_CLK, "clk_uart1", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 21, 0, }, ++ { HI3516AV200_UART2_CLK, "clk_uart2", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 22, 0, }, ++ { HI3516AV200_UART3_CLK, "clk_uart3", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 23, 0, }, ++ { HI3516AV200_UART4_CLK, "clk_uart4", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 24, 0, }, ++ ++ /* ethernet mac */ ++ { HI3516AV200_ETH_CLK, "clk_eth", NULL, ++ CLK_IS_ROOT, 0xcc, 1, 0, }, ++ { HI3516AV200_ETH_MACIF_CLK, "clk_eth_macif", NULL, ++ CLK_IS_ROOT, 0xcc, 3, 0, }, ++ ++ /* spi */ ++ { HI3516AV200_SPI0_CLK, "clk_spi0", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 16, 0, }, ++ { HI3516AV200_SPI1_CLK, "clk_spi1", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 17, 0, }, ++ { HI3516AV200_SPI2_CLK, "clk_spi2", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 18, 0, }, ++ { HI3516AV200_SPI3_CLK, "clk_spi3", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 28, 0, }, ++}; ++ ++static struct hi3516av200_pll_clock hi3516av200_pll_clks[] __initdata = { ++ { HI3516AV200_APLL_CLK, "apll", NULL, 0x0, 0, 24, 24, 3, 28, 3, ++ 0x4, 0, 12, 12, 6}, ++}; ++ ++ ++#define to_pll_clk(_hw) container_of(_hw, struct hi3516av200_clk_pll, hw) ++ ++static void hi3516av200_calc_pll(u32 *frac_val, ++ u32 *postdiv1_val, ++ u32 *postdiv2_val, ++ u32 *fbdiv_val, ++ u32 *refdiv_val, ++ unsigned long rate) ++{ ++ u64 rem; ++ *frac_val = 0; ++ rem = do_div(rate, 1000000); ++ *fbdiv_val = rate; ++ *refdiv_val = 24; ++ rem = rem * (1 << 24); ++ do_div(rem, 1000000); ++ *frac_val = rem; ++} ++ ++static int clk_pll_set_rate(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct hi3516av200_clk_pll *clk = to_pll_clk(hw); ++ u32 frac_val, postdiv1_val, postdiv2_val, fbdiv_val, refdiv_val; ++ u32 val; ++ ++ /*Fixme ignore postdives now because apll don't use them*/ ++ postdiv1_val = postdiv2_val = 0; ++ ++ hi3516av200_calc_pll(&frac_val, &postdiv1_val, &postdiv2_val, ++ &fbdiv_val, &refdiv_val, rate); ++ ++ val = readl_relaxed(clk->ctrl_reg1); ++ val &= ~(((1 << clk->frac_width) - 1) << clk->frac_shift); ++ val &= ~(((1 << clk->postdiv1_width) - 1) << clk->postdiv1_shift); ++ val &= ~(((1 << clk->postdiv2_width) - 1) << clk->postdiv2_shift); ++ ++ val |= frac_val << clk->frac_shift; ++ val |= postdiv1_val << clk->postdiv1_shift; ++ val |= postdiv2_val << clk->postdiv2_shift; ++ writel_relaxed(val, clk->ctrl_reg1); ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val &= ~(((1 << clk->fbdiv_width) - 1) << clk->fbdiv_shift); ++ val &= ~(((1 << clk->refdiv_width) - 1) << clk->refdiv_shift); ++ ++ val |= fbdiv_val << clk->fbdiv_shift; ++ val |= refdiv_val << clk->refdiv_shift; ++ writel_relaxed(val, clk->ctrl_reg2); ++ ++ return 0; ++} ++ ++static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct hi3516av200_clk_pll *clk = to_pll_clk(hw); ++ u64 frac_val, fbdiv_val, refdiv_val; ++ u32 val; ++ u64 tmp, rate; ++ ++ val = readl_relaxed(clk->ctrl_reg1); ++ val = val >> clk->frac_shift; ++ val &= ((1 << clk->frac_width) - 1); ++ frac_val = val; ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val = val >> clk->fbdiv_shift; ++ val &= ((1 << clk->fbdiv_width) - 1); ++ fbdiv_val = val; ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val = val >> clk->refdiv_shift; ++ val &= ((1 << clk->refdiv_width) - 1); ++ refdiv_val = val; ++ ++ /* rate = 24000000 * (fbdiv + frac / (1<<24) ) / refdiv */ ++ rate = 0; ++ tmp = 24000000 * fbdiv_val; ++ rate += tmp; ++ do_div(rate, refdiv_val); ++ ++ return rate; ++} ++ ++ ++static long clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *best_parent_rate, ++ struct clk **best_parent_p) ++{ ++ return rate; ++} ++ ++static struct clk_ops clk_pll_ops = { ++ .set_rate = clk_pll_set_rate, ++ .determine_rate = clk_pll_determine_rate, ++ .recalc_rate = clk_pll_recalc_rate, ++}; ++ ++void __init hi3516av200_clk_register_pll(struct hi3516av200_pll_clock *clks, ++ int nums, struct hisi_clock_data *data) ++{ ++ void __iomem *base = data->base; ++ int i; ++ ++ for (i = 0; i < nums; i++) { ++ struct hi3516av200_clk_pll *p_clk; ++ struct clk *clk; ++ struct clk_init_data init; ++ ++ p_clk = kzalloc(sizeof(*p_clk), GFP_KERNEL); ++ if (!p_clk) ++ return; ++ ++ init.name = clks[i].name; ++ init.flags = CLK_IS_BASIC; ++ init.parent_names = ++ (clks[i].parent_name ? &clks[i].parent_name : NULL); ++ init.num_parents = (clks[i].parent_name ? 1 : 0); ++ init.ops = &clk_pll_ops; ++ ++ p_clk->ctrl_reg1 = base + clks[i].ctrl_reg1; ++ p_clk->frac_shift = clks[i].frac_shift; ++ p_clk->frac_width = clks[i].frac_width; ++ p_clk->postdiv1_shift = clks[i].postdiv1_shift; ++ p_clk->postdiv1_width = clks[i].postdiv1_width; ++ p_clk->postdiv2_shift = clks[i].postdiv2_shift; ++ p_clk->postdiv2_width = clks[i].postdiv2_width; ++ ++ p_clk->ctrl_reg2 = base + clks[i].ctrl_reg2; ++ p_clk->fbdiv_shift = clks[i].fbdiv_shift; ++ p_clk->fbdiv_width = clks[i].fbdiv_width; ++ p_clk->refdiv_shift = clks[i].refdiv_shift; ++ p_clk->refdiv_width = clks[i].refdiv_width; ++ p_clk->hw.init = &init; ++ ++ clk = clk_register(NULL, &p_clk->hw); ++ if (IS_ERR(clk)) { ++ kfree(p_clk); ++ pr_err("%s: failed to register clock %s\n", ++ __func__, clks[i].name); ++ continue; ++ } ++ ++ data->clk_data.clks[clks[i].id] = clk; ++ } ++ ++ ++} ++ ++static void __init hi3516av200_clk_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ ++ clk_data = hisi_clk_init(np, HI3516AV200_NR_CLKS); ++ if (!clk_data) ++ return; ++ if (IS_ENABLED(CONFIG_RESET_CONTROLLER)) ++ hisi_reset_init(np, HI3516AV200_NR_RSTS); ++ ++ hisi_clk_register_fixed_rate(hi3516av200_fixed_rate_clks, ++ ARRAY_SIZE(hi3516av200_fixed_rate_clks), ++ clk_data); ++ hi3516av200_clk_register_pll(hi3516av200_pll_clks, ++ ARRAY_SIZE(hi3516av200_pll_clks), clk_data); ++ ++ hisi_clk_register_mux(hi3516av200_mux_clks, ++ ARRAY_SIZE(hi3516av200_mux_clks), ++ clk_data); ++ hisi_clk_register_fixed_factor(hi3516av200_fixed_factor_clks, ++ ARRAY_SIZE(hi3516av200_fixed_factor_clks), clk_data); ++ hisi_clk_register_gate(hi3516av200_gate_clks, ++ ARRAY_SIZE(hi3516av200_gate_clks), clk_data); ++} ++ ++CLK_OF_DECLARE(hi3516av200_clk, "hisilicon,hi3516av200-clock", ++ hi3516av200_clk_init); +diff --git a/drivers/clk/hisilicon/clk-hi3516cv300.c b/drivers/clk/hisilicon/clk-hi3516cv300.c +new file mode 100644 +index 0000000..4d41475 +--- /dev/null ++++ b/drivers/clk/hisilicon/clk-hi3516cv300.c +@@ -0,0 +1,244 @@ ++/* ++ * Hi3516cv300 Clock Driver ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include "clk.h" ++#include "reset.h" ++ ++static struct ++hisi_fixed_rate_clock hi3516cv300_fixed_rate_clks_crg[] __initdata = { ++ { HI3516CV300_FIXED_3M, "3m", NULL, CLK_IS_ROOT, 3000000, }, ++ { HI3516CV300_FIXED_6M, "6m", NULL, CLK_IS_ROOT, 6000000, }, ++ { HI3516CV300_FIXED_12M, "12m", NULL, CLK_IS_ROOT, 12000000, }, ++ { HI3516CV300_FIXED_15M, "15m", NULL, CLK_IS_ROOT, 15000000, }, ++ { HI3516CV300_FIXED_24M, "24m", NULL, CLK_IS_ROOT, 24000000, }, ++ { HI3516CV300_FIXED_25M, "25m", NULL, CLK_IS_ROOT, 25000000, }, ++ { HI3516CV300_FIXED_27M, "27m", NULL, CLK_IS_ROOT, 27000000, }, ++ { HI3516CV300_FIXED_37P125M, "37.125m", NULL, CLK_IS_ROOT, 37125000, }, ++ { HI3516CV300_FIXED_44M, "44m", NULL, CLK_IS_ROOT, 44000000, }, ++ { HI3516CV300_FIXED_49P5M, "49.5m", NULL, CLK_IS_ROOT, 49500000, }, ++ { HI3516CV300_FIXED_50M, "50m", NULL, CLK_IS_ROOT, 50000000, }, ++ { HI3516CV300_FIXED_54M, "54m", NULL, CLK_IS_ROOT, 54000000, }, ++ { HI3516CV300_FIXED_74P25M, "74.25m", NULL, CLK_IS_ROOT, 74250000, }, ++ { HI3516CV300_FIXED_75M, "75m", NULL, CLK_IS_ROOT, 75000000, }, ++ { HI3516CV300_FIXED_83P3M, "83.3m", NULL, CLK_IS_ROOT, 83300000, }, ++ { HI3516CV300_FIXED_99M, "99m", NULL, CLK_IS_ROOT, 99000000, }, ++ { HI3516CV300_FIXED_100M, "100m", NULL, CLK_IS_ROOT, 100000000, }, ++ { HI3516CV300_FIXED_125M, "125m", NULL, CLK_IS_ROOT, 125000000, }, ++ { HI3516CV300_FIXED_148P5M, "148.5m", NULL, CLK_IS_ROOT, 148500000, }, ++ { HI3516CV300_FIXED_150M, "150m", NULL, CLK_IS_ROOT, 150000000, }, ++ { HI3516CV300_FIXED_166P6M, "166.6m", NULL, CLK_IS_ROOT, 166600000, }, ++ { HI3516CV300_FIXED_198M, "198m", NULL, CLK_IS_ROOT, 198000000, }, ++ { HI3516CV300_FIXED_200M, "200m", NULL, CLK_IS_ROOT, 200000000, }, ++ { HI3516CV300_FIXED_250M, "250m", NULL, CLK_IS_ROOT, 250000000, }, ++ { HI3516CV300_FIXED_297M, "297m", NULL, CLK_IS_ROOT, 297000000, }, ++ { HI3516CV300_FIXED_300M, "300m", NULL, CLK_IS_ROOT, 300000000, }, ++ { HI3516CV300_FIXED_396M, "396m", NULL, CLK_IS_ROOT, 396000000, }, ++ { HI3516CV300_FIXED_400M, "400m", NULL, CLK_IS_ROOT, 400000000, }, ++}; ++ ++static const char *apb_mux_p[] __initconst = {"24m", "50m"}; ++static const char *uart_mux_p[] __initconst = {"24m", "6m"}; ++static const char *fmc_mux_p[] __initconst = { ++ "24m", "83.3m", "148.5m", "198m", "297m" ++}; ++static const char *mmc_mux_p[] __initconst = {"49.5m"}; ++static const char *mmc2_mux_p[] __initconst = {"99m", "49.5m"}; ++static const char *sensor_mux_p[] = {"74.25m", "37.125m", "54m", "27m", "24m", "25m", "24m", "25m"}; ++static const char *viu_mux_p[] = {"83.3m", "125m", "148.5m", "198m", "250m"}; ++static const char *vedu_mux_p[] = {"166.6m", "198m"}; ++static const char *vpss_mux_p[] = {"148.5m", "198m", "250m"}; ++static const char *vgs_mux_p[] = {"198m", "250m", "297m"}; ++static const char *ive_mux_p[] = {"198m", "250m", "297m"}; ++static const char *pwm_mux_p[] = {"3m", "50m", "24m", "24m"}; ++ ++static u32 apb_mux_table[] = {0, 1}; ++static u32 uart_mux_table[] = {0, 1}; ++static u32 fmc_mux_table[] = {0, 1, 2, 3, 4}; ++static u32 mmc_mux_table[] = {0}; ++static u32 mmc2_mux_table[] = {0, 2}; ++static u32 pwm_mux_table[] = {0, 1, 2, 3}; ++ ++static u32 sensor_mux_p_table[] = {0, 1, 2, 3, 4, 5, 6, 7}; ++static u32 viu_mux_p_table[] = {0, 1, 2, 3, 4}; ++static u32 vedu_mux_p_table[] = {0, 1}; ++static u32 vpss_mux_p_table[] = {0, 1, 2}; ++static u32 vgs_mux_p_table[] = {0, 1, 2}; ++static u32 ive_mux_p_table[] = {0, 1, 2}; ++static struct hisi_mux_clock hi3516cv300_mux_clks_crg[] __initdata = { ++ { HI3516CV300_APB_CLK, "apb", apb_mux_p, ARRAY_SIZE(apb_mux_p), ++ CLK_SET_RATE_PARENT, 0x30, 0, 1, 0, apb_mux_table, }, ++ { HI3516CV300_UART_MUX, "uart_mux", uart_mux_p, ARRAY_SIZE(uart_mux_p), ++ CLK_SET_RATE_PARENT, 0xe4, 19, 1, 0, uart_mux_table, }, ++ { HI3516CV300_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc0, 2, 3, 0, fmc_mux_table, }, ++ { HI3516CV300_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 4, 2, 0, mmc_mux_table, }, ++ { HI3516CV300_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 12, 2, 0, mmc_mux_table, }, ++ { HI3516CV300_MMC2_MUX, "mmc2_mux", mmc2_mux_p, ARRAY_SIZE(mmc2_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 20, 2, 0, mmc2_mux_table, }, ++ { HI3516CV300_MMC3_MUX, "mmc3_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc8, 4, 2, 0, mmc_mux_table, }, ++ { HI3516CV300_PWM_MUX, "pwm_mux", pwm_mux_p, ARRAY_SIZE(pwm_mux_p), ++ CLK_SET_RATE_PARENT, 0x38, 2, 2, 0, pwm_mux_table, }, ++ ++ /* media mux clock*/ ++ { HI3516CV300_SENSOR_MUX, "sensor_mux", sensor_mux_p, ARRAY_SIZE(sensor_mux_p), ++ CLK_SET_RATE_PARENT, 0x2c, 23, 3, 0, sensor_mux_p_table, }, ++ { HI3516CV300_VIU_MUX, "viu_mux", viu_mux_p, ARRAY_SIZE(viu_mux_p), ++ CLK_SET_RATE_PARENT, 0x2c, 2, 3, 0, viu_mux_p_table, }, ++ { HI3516CV300_VEDU_MUX, "vedu_mux", vedu_mux_p, ARRAY_SIZE(vedu_mux_p), ++ CLK_SET_RATE_PARENT, 0x40, 10, 2, 0, vedu_mux_p_table, }, ++ { HI3516CV300_VPSS_MUX, "vpss_mux", vpss_mux_p, ARRAY_SIZE(vpss_mux_p), ++ CLK_SET_RATE_PARENT, 0x48, 10, 2, 0, vpss_mux_p_table, }, ++ { HI3516CV300_VGS_MUX, "vgs_mux", vgs_mux_p, ARRAY_SIZE(vgs_mux_p), ++ CLK_SET_RATE_PARENT, 0x5c, 10, 2, 0, vgs_mux_p_table, }, ++ { HI3516CV300_IVE_MUX, "ive_mux", ive_mux_p, ARRAY_SIZE(ive_mux_p), ++ CLK_SET_RATE_PARENT, 0x6c, 2, 2, 0, ive_mux_p_table, }, ++}; ++ ++static struct hisi_divider_clock hi3516cv300_div_clks[] = { ++ { HI3516CV300_ISP_DIV, "isp_div", "viu_mux", 0, 0x2c, 17, 1, 0, NULL, }, ++}; ++ ++static struct hisi_gate_clock hi3516cv300_gate_clks_crg[] __initdata = { ++ /* uart */ ++ { HI3516CV300_UART0_CLK, "clk_uart0", "uart_mux", ++ CLK_SET_RATE_PARENT, 0xe4, 15, 0, }, ++ { HI3516CV300_UART1_CLK, "clk_uart1", "uart_mux", ++ CLK_SET_RATE_PARENT, 0xe4, 16, 0, }, ++ { HI3516CV300_UART2_CLK, "clk_uart2", "uart_mux", ++ CLK_SET_RATE_PARENT, 0xe4, 17, 0, }, ++ /* spi */ ++ { HI3516CV300_SPI0_CLK, "clk_spi0", "100m", ++ CLK_SET_RATE_PARENT, 0xe4, 13, 0, }, ++ { HI3516CV300_SPI1_CLK, "clk_spi1", "100m", ++ CLK_SET_RATE_PARENT, 0xe4, 14, 0, }, ++ /* fmc */ ++ { HI3516CV300_FMC_CLK, "clk_fmc", "fmc_mux", ++ CLK_SET_RATE_PARENT, 0xc0, 1, 0, }, ++ { HI3516CV300_MMC0_CLK, "clk_mmc0", "mmc0_mux", ++ CLK_SET_RATE_PARENT, 0xc4, 1, 0, }, ++ { HI3516CV300_MMC1_CLK, "clk_mmc1", "mmc1_mux", ++ CLK_SET_RATE_PARENT, 0xc4, 9, 0, }, ++ { HI3516CV300_MMC2_CLK, "clk_mmc2", "mmc2_mux", ++ CLK_SET_RATE_PARENT, 0xc4, 17, 0, }, ++ { HI3516CV300_MMC3_CLK, "clk_mmc3", "mmc3_mux", ++ CLK_SET_RATE_PARENT, 0xc8, 1, 0, }, ++ /* ethernet mac */ ++ { HI3516CV300_ETH_CLK, "clk_eth", NULL, CLK_IS_ROOT, 0xec, 1, 0, }, ++ { HI3516CV300_USB2_BUS_CLK, "clk_usb2_bus", NULL, ++ CLK_SET_RATE_PARENT, 0xb8, 8, 1, }, ++ { HI3516CV300_UTMI0_CLK, "clk_utmi0", NULL, ++ CLK_SET_RATE_PARENT, 0xb8, 11, 1, }, ++ { HI3516CV300_USB2_CLK, "clk_usb2", NULL, ++ CLK_SET_RATE_PARENT, 0xb8, 12, 1, }, ++ { HI3516CV300_DMAC_CLK, "clk_dmac", NULL, CLK_IS_ROOT, 0xd8, 5, 0, }, ++ ++ { HI3516CV300_PWM_CLK, "clk_pwm", "pwm_mux", CLK_SET_RATE_PARENT, ++ 0x38, 1, 0, }, ++ ++ /* media gate clock*/ ++ { HI3516CV300_SENSOR_CLK, "clk_sensor", "sensor_mux", CLK_SET_RATE_PARENT, ++ 0x2c, 26, 0, }, ++ { HI3516CV300_MIPI_CLK, "clk_mipi", NULL, CLK_SET_RATE_PARENT, ++ 0x2c, 15, 0, }, ++ { HI3516CV300_ISP_CLK, "clk_isp", "isp_div", CLK_SET_RATE_PARENT, 0x2c, 18, 0, }, ++ { HI3516CV300_VIU_CLK, "clk_viu", "viu_mux", CLK_SET_RATE_PARENT, ++ 0x2c, 0, 0, }, ++ { HI3516CV300_VEDU_CLK, "clk_vedu", "vedu_mux", CLK_SET_RATE_PARENT, ++ 0x40, 1, 0, }, ++ { HI3516CV300_VPSS_CLK, "clk_vpss", "vpss_mux", CLK_SET_RATE_PARENT, ++ 0x48, 1, 0, }, ++ { HI3516CV300_VGS_CLK, "clk_vgs", "vgs_mux", CLK_SET_RATE_PARENT, ++ 0x5c, 1, 0, }, ++ { HI3516CV300_JPGE_CLK, "clk_jpge", NULL, CLK_SET_RATE_PARENT, ++ 0x60, 1, 0, }, ++ { HI3516CV300_IVE_CLK, "clk_ive", "ive_mux", CLK_SET_RATE_PARENT, ++ 0x6c, 1, 0, }, ++ { HI3516CV300_AIAO_CLK, "clk_aiao", NULL, CLK_SET_RATE_PARENT, ++ 0x8c, 1, 0, }, ++}; ++ ++static void __init hi3516cv300_clk_crg_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ unsigned int count = 0; ++ ++ clk_data = hisi_clk_init(np, HI3516CV300_CRG_NR_CLKS); ++ if (!clk_data) ++ return; ++ ++ hisi_clk_register_fixed_rate(hi3516cv300_fixed_rate_clks_crg, ++ ARRAY_SIZE(hi3516cv300_fixed_rate_clks_crg), ++ clk_data); ++ hisi_clk_register_mux(hi3516cv300_mux_clks_crg, ++ ARRAY_SIZE(hi3516cv300_mux_clks_crg), clk_data); ++ hisi_clk_register_divider(hi3516cv300_div_clks, ++ ARRAY_SIZE(hi3516cv300_div_clks), clk_data); ++ hisi_clk_register_gate(hi3516cv300_gate_clks_crg, ++ ARRAY_SIZE(hi3516cv300_gate_clks_crg), clk_data); ++ ++ if (!of_property_read_u32(np, "#reset-cells", &count) && (count == 2)) ++ hisi_reset_init(np, HI3516CV300_CRG_NR_RSTS); ++} ++ ++static const char *timer_mux_p[] __initconst = { "3m", "apb" }; ++static u32 timer_mux_table[] = {0, 1}; ++ ++static struct hisi_mux_clock hi3516cv300_mux_clks_sys[] __initdata = { ++ { HI3516CV300_TIME00_CLK, "timer00", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 16, 1, 0, timer_mux_table, }, ++ ++ { HI3516CV300_TIME01_CLK, "timer01", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 18, 1, 0, timer_mux_table, }, ++ ++ { HI3516CV300_TIME10_CLK, "timer10", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 20, 1, 0, timer_mux_table, }, ++ ++ { HI3516CV300_TIME11_CLK, "timer11", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 22, 1, 0, timer_mux_table, }, ++}; ++ ++static void __init hi3516cv300_clk_sys_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ unsigned int count = 0; ++ ++ clk_data = hisi_clk_init(np, HI3516CV300_SYS_NR_CLKS); ++ if (!clk_data) ++ return; ++ ++ hisi_clk_register_mux(hi3516cv300_mux_clks_sys, ++ ARRAY_SIZE(hi3516cv300_mux_clks_sys), clk_data); ++ ++ if (!of_property_read_u32(np, "#reset-cells", &count) && (count == 2)) ++ hisi_reset_init(np, HI3516CV300_SYS_NR_RSTS); ++} ++ ++CLK_OF_DECLARE(hi3516cv300_clk, "hisilicon,hi3516cv300-crg", ++ hi3516cv300_clk_crg_init); ++CLK_OF_DECLARE(hi3516cv300_clk_sys, "hisilicon,hi3516cv300-sys", ++ hi3516cv300_clk_sys_init); +diff --git a/drivers/clk/hisilicon/clk-hi3519.c b/drivers/clk/hisilicon/clk-hi3519.c +new file mode 100644 +index 0000000..1cd0676 +--- /dev/null ++++ b/drivers/clk/hisilicon/clk-hi3519.c +@@ -0,0 +1,375 @@ ++/* ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "clk.h" ++#include "reset.h" ++ ++/******************************************************************************/ ++struct hi3519_pll_clock { ++ u32 id; ++ const char *name; ++ const char *parent_name; ++ u32 ctrl_reg1; ++ u8 frac_shift; ++ u8 frac_width; ++ u8 postdiv1_shift; ++ u8 postdiv1_width; ++ u8 postdiv2_shift; ++ u8 postdiv2_width; ++ u32 ctrl_reg2; ++ u8 fbdiv_shift; ++ u8 fbdiv_width; ++ u8 refdiv_shift; ++ u8 refdiv_width; ++}; ++ ++struct hi3519_clk_pll { ++ struct clk_hw hw; ++ u32 id; ++ void __iomem *ctrl_reg1; ++ u8 frac_shift; ++ u8 frac_width; ++ u8 postdiv1_shift; ++ u8 postdiv1_width; ++ u8 postdiv2_shift; ++ u8 postdiv2_width; ++ void __iomem *ctrl_reg2; ++ u8 fbdiv_shift; ++ u8 fbdiv_width; ++ u8 refdiv_shift; ++ u8 refdiv_width; ++}; ++ ++static struct hisi_fixed_rate_clock hi3519_fixed_rate_clks[] __initdata = { ++ { HI3519_FIXED_2376M, "2376m", NULL, CLK_IS_ROOT, 2376000000UL, }, ++ { HI3519_FIXED_1188M, "1188m", NULL, CLK_IS_ROOT, 1188000000, }, ++ { HI3519_FIXED_594M, "594m", NULL, CLK_IS_ROOT, 594000000, }, ++ { HI3519_FIXED_297M, "297m", NULL, CLK_IS_ROOT, 297000000, }, ++ { HI3519_FIXED_148P5M, "148p5m", NULL, CLK_IS_ROOT, 148500000, }, ++ { HI3519_FIXED_74P25M, "74p25m", NULL, CLK_IS_ROOT, 74250000, }, ++ { HI3519_FIXED_792M, "792m", NULL, CLK_IS_ROOT, 792000000, }, ++ { HI3519_FIXED_475M, "475m", NULL, CLK_IS_ROOT, 475000000, }, ++ { HI3519_FIXED_340M, "340m", NULL, CLK_IS_ROOT, 340000000, }, ++ { HI3519_FIXED_72M, "72m", NULL, CLK_IS_ROOT, 72000000, }, ++ { HI3519_FIXED_400M, "400m", NULL, CLK_IS_ROOT, 400000000, }, ++ { HI3519_FIXED_200M, "200m", NULL, CLK_IS_ROOT, 200000000, }, ++ { HI3519_FIXED_54M, "54m", NULL, CLK_IS_ROOT, 54000000, }, ++ { HI3519_FIXED_27M, "27m", NULL, CLK_IS_ROOT, 1188000000, }, ++ { HI3519_FIXED_37P125M, "37p125m", NULL, CLK_IS_ROOT, 37125000, }, ++ { HI3519_FIXED_3000M, "3000m", NULL, CLK_IS_ROOT, 3000000000UL, }, ++ { HI3519_FIXED_1500M, "1500m", NULL, CLK_IS_ROOT, 1500000000, }, ++ { HI3519_FIXED_500M, "500m", NULL, CLK_IS_ROOT, 500000000, }, ++ { HI3519_FIXED_250M, "250m", NULL, CLK_IS_ROOT, 250000000, }, ++ { HI3519_FIXED_125M, "125m", NULL, CLK_IS_ROOT, 125000000, }, ++ { HI3519_FIXED_1000M, "1000m", NULL, CLK_IS_ROOT, 1000000000, }, ++ { HI3519_FIXED_600M, "600m", NULL, CLK_IS_ROOT, 600000000, }, ++ { HI3519_FIXED_750M, "750m", NULL, CLK_IS_ROOT, 750000000, }, ++ { HI3519_FIXED_150M, "150m", NULL, CLK_IS_ROOT, 150000000, }, ++ { HI3519_FIXED_75M, "75m", NULL, CLK_IS_ROOT, 75000000, }, ++ { HI3519_FIXED_300M, "300m", NULL, CLK_IS_ROOT, 300000000, }, ++ { HI3519_FIXED_60M, "60m", NULL, CLK_IS_ROOT, 60000000, }, ++ { HI3519_FIXED_214M, "214m", NULL, CLK_IS_ROOT, 214000000, }, ++ { HI3519_FIXED_107M, "107m", NULL, CLK_IS_ROOT, 107000000, }, ++ { HI3519_FIXED_100M, "100m", NULL, CLK_IS_ROOT, 100000000, }, ++ { HI3519_FIXED_50M, "50m", NULL, CLK_IS_ROOT, 50000000, }, ++ { HI3519_FIXED_25M, "25m", NULL, CLK_IS_ROOT, 25000000, }, ++ { HI3519_FIXED_24M, "24m", NULL, CLK_IS_ROOT, 24000000, }, ++ { HI3519_FIXED_3M, "3m", NULL, CLK_IS_ROOT, 3000000, }, ++}; ++ ++static const char *sysaxi_mux_p[] __initconst = {"24m", "200m", }; ++static u32 sysaxi_mux_table[] = {0, 1}; ++ ++static const char *fmc_mux_p[] __initconst = { ++ "24m", "75m", "125m", "150m", "200m", "250m", "300m", "400m", }; ++static u32 fmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6, 7}; ++ ++static const char *mmc_mux_p[] __initconst = { ++ "100m", "200m", "300m", "400m", "594m", "792m", }; ++static u32 mmc_mux_table[] = {0, 1, 2, 3, 4, 5}; ++ ++static const char *a17_mux_p[] __initconst = { ++ "400m", "500m", "594m", "792m", "1000m", "apll"}; ++static u32 a17_mux_table[] = {7, 6, 5, 4, 3, 1}; ++ ++static const char *i2c_mux_p[] __initconst = {"clk_sysapb", "50m"}; ++static u32 i2c_mux_table[] = {0, 1}; ++ ++static struct hisi_mux_clock hi3519_mux_clks[] __initdata = { ++ { HI3519_SYSAXI_MUX, "sysaxi_mux", sysaxi_mux_p, ++ ARRAY_SIZE(sysaxi_mux_p), ++ CLK_SET_RATE_PARENT, 0x34, 12, 2, 0, sysaxi_mux_table, }, ++ { HI3519_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc0, 2, 3, 0, fmc_mux_table, }, ++ { HI3519_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 10, 3, 0, mmc_mux_table, }, ++ { HI3519_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 2, 3, 0, mmc_mux_table, }, ++ { HI3519_MMC2_MUX, "mmc2_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 18, 3, 0, mmc_mux_table, }, ++ { HI3519_A17_MUX, "a17_mux", a17_mux_p, ARRAY_SIZE(a17_mux_p), ++ CLK_SET_RATE_PARENT, 0x34, 4, 3, 0, a17_mux_table, }, ++ { HI3519_I2C_MUX, "i2c_mux", i2c_mux_p, ARRAY_SIZE(i2c_mux_p), ++ CLK_SET_RATE_PARENT, 0xe4, 26, 1, 0, i2c_mux_table, }, ++}; ++ ++static struct hisi_fixed_factor_clock hi3519_fixed_factor_clks[] __initdata = { ++ { HI3519_SYSAPB_CLK, "clk_sysapb", "sysaxi_mux", 1, 4, ++ CLK_SET_RATE_PARENT}, ++ { HI3519_MMC0_FAC_CLK, "mmc0_fac", "mmc0_mux", 1, 8, ++ CLK_SET_RATE_PARENT}, ++ { HI3519_MMC1_FAC_CLK, "mmc1_fac", "mmc1_mux", 1, 8, ++ CLK_SET_RATE_PARENT}, ++ { HI3519_MMC2_FAC_CLK, "mmc2_fac", "mmc2_mux", 1, 8, ++ CLK_SET_RATE_PARENT}, ++}; ++ ++static struct hisi_gate_clock hi3519_gate_clks[] __initdata = { ++#ifdef CONFIG_HIFMC ++ /* fmc */ ++ { HI3519_FMC_CLK, "clk_fmc", "fmc_mux", ++ CLK_SET_RATE_PARENT, 0xc0, 1, 0, }, ++#endif ++ /* mmc */ ++ { HI3519_MMC0_CLK, "clk_mmc0", "mmc0_fac", ++ CLK_SET_RATE_PARENT, 0xc4, 9, 0, }, ++ { HI3519_MMC1_CLK, "clk_mmc1", "mmc1_fac", ++ CLK_SET_RATE_PARENT, 0xc4, 1, 0, }, ++ { HI3519_MMC2_CLK, "clk_mmc2", "mmc2_fac", ++ CLK_SET_RATE_PARENT, 0xc4, 17, 0, }, ++ ++ /* usb ctrl */ ++ { HI3519_USB2_CTRL_UTMI0_REQ, "usb2_cttl_utmi0_req", NULL, ++ CLK_SET_RATE_PARENT, 0xb4, 5, 1, }, ++ { HI3519_USB2_HRST_REQ, "usb2_hrst_req", NULL, ++ CLK_SET_RATE_PARENT, 0xb4, 0, 1, }, ++ { HI3519_USB3_CLK, "usb3_vcc_srst_req2", NULL, ++ CLK_SET_RATE_PARENT, 0xb8, 0, 1, }, ++ /* uart */ ++ { HI3519_UART0_CLK, "clk_uart0", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 20, 0, }, ++ { HI3519_UART1_CLK, "clk_uart1", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 21, 0, }, ++ { HI3519_UART2_CLK, "clk_uart2", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 22, 0, }, ++ { HI3519_UART3_CLK, "clk_uart3", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 23, 0, }, ++ { HI3519_UART4_CLK, "clk_uart4", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 24, 0, }, ++ /* ethernet mac */ ++ { HI3519_ETH_CLK, "clk_eth", NULL, ++ CLK_IS_ROOT, 0xcc, 1, 0, }, ++ { HI3519_ETH_MACIF_CLK, "clk_eth_macif", NULL, ++ CLK_IS_ROOT, 0xcc, 3, 0, }, ++ /* spi */ ++ { HI3519_SPI0_CLK, "clk_spi0", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 16, 0, }, ++ { HI3519_SPI1_CLK, "clk_spi1", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 17, 0, }, ++ { HI3519_SPI2_CLK, "clk_spi2", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 18, 0, }, ++}; ++ ++static struct hi3519_pll_clock hi3519_pll_clks[] __initdata = { ++ { HI3519_APLL_CLK, "apll", NULL, 0x0, 0, 24, 24, 3, 28, 3, ++ 0x4, 0, 12, 12, 6}, ++}; ++ ++ ++#define to_pll_clk(_hw) container_of(_hw, struct hi3519_clk_pll, hw) ++ ++static void hi3519_calc_pll(u32 *frac_val, u32 *postdiv1_val, u32 *postdiv2_val, ++ u32 *fbdiv_val, u32 *refdiv_val, unsigned long rate) ++{ ++ u64 rem; ++ *frac_val = 0; ++ rem = do_div(rate, 1000000); ++ *fbdiv_val = rate; ++ *refdiv_val = 24; ++ rem = rem * (1 << 24); ++ do_div(rem, 1000000); ++ *frac_val = rem; ++} ++ ++static int clk_pll_set_rate(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct hi3519_clk_pll *clk = to_pll_clk(hw); ++ u32 frac_val, postdiv1_val, postdiv2_val, fbdiv_val, refdiv_val; ++ u32 val; ++ ++ /*Fixme ignore postdives now because apll don't use them*/ ++ postdiv1_val = postdiv2_val = 0; ++ ++ hi3519_calc_pll(&frac_val, &postdiv1_val, &postdiv2_val, ++ &fbdiv_val, &refdiv_val, rate); ++ ++ val = readl_relaxed(clk->ctrl_reg1); ++ val &= ~(((1 << clk->frac_width) - 1) << clk->frac_shift); ++ val &= ~(((1 << clk->postdiv1_width) - 1) << clk->postdiv1_shift); ++ val &= ~(((1 << clk->postdiv2_width) - 1) << clk->postdiv2_shift); ++ ++ val |= frac_val << clk->frac_shift; ++ val |= postdiv1_val << clk->postdiv1_shift; ++ val |= postdiv2_val << clk->postdiv2_shift; ++ writel_relaxed(val, clk->ctrl_reg1); ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val &= ~(((1 << clk->fbdiv_width) - 1) << clk->fbdiv_shift); ++ val &= ~(((1 << clk->refdiv_width) - 1) << clk->refdiv_shift); ++ ++ val |= fbdiv_val << clk->fbdiv_shift; ++ val |= refdiv_val << clk->refdiv_shift; ++ writel_relaxed(val, clk->ctrl_reg2); ++ ++ return 0; ++} ++ ++static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct hi3519_clk_pll *clk = to_pll_clk(hw); ++ u64 frac_val, fbdiv_val, refdiv_val; ++ u32 val; ++ u64 tmp, rate; ++ ++ val = readl_relaxed(clk->ctrl_reg1); ++ val = val >> clk->frac_shift; ++ val &= ((1 << clk->frac_width) - 1); ++ frac_val = val; ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val = val >> clk->fbdiv_shift; ++ val &= ((1 << clk->fbdiv_width) - 1); ++ fbdiv_val = val; ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val = val >> clk->refdiv_shift; ++ val &= ((1 << clk->refdiv_width) - 1) ; ++ refdiv_val = val; ++ ++ /* rate = 24000000 * (fbdiv + frac / (1<<24) ) / refdiv */ ++ rate = 0; ++ tmp = 24000000 * fbdiv_val; ++ rate += tmp; ++#if 0 ++ tmp = 24000000 * frac_val; ++ do_div(tmp, (1<<24)); ++ rate += tmp; ++#endif ++ do_div(rate, refdiv_val); ++ ++ return rate; ++} ++ ++ ++static long clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *best_parent_rate, ++ struct clk **best_parent_p) ++{ ++ return rate; ++} ++ ++static struct clk_ops clk_pll_ops = { ++ .set_rate = clk_pll_set_rate, ++ .determine_rate = clk_pll_determine_rate, ++ .recalc_rate = clk_pll_recalc_rate, ++}; ++ ++void __init hi3519_clk_register_pll(struct hi3519_pll_clock *clks, ++ int nums, struct hisi_clock_data *data) ++{ ++ void __iomem *base = data->base; ++ int i; ++ ++ for (i = 0; i < nums; i++) { ++ struct hi3519_clk_pll *p_clk; ++ struct clk *clk; ++ struct clk_init_data init; ++ ++ p_clk = kzalloc(sizeof(*p_clk), GFP_KERNEL); ++ if (!p_clk) ++ return; ++ ++ init.name = clks[i].name; ++ init.flags = CLK_IS_BASIC; ++ init.parent_names = ++ (clks[i].parent_name ? &clks[i].parent_name : NULL); ++ init.num_parents = (clks[i].parent_name ? 1 : 0); ++ init.ops = &clk_pll_ops; ++ ++ p_clk->ctrl_reg1 = base + clks[i].ctrl_reg1; ++ p_clk->frac_shift = clks[i].frac_shift; ++ p_clk->frac_width = clks[i].frac_width; ++ p_clk->postdiv1_shift = clks[i].postdiv1_shift; ++ p_clk->postdiv1_width = clks[i].postdiv1_width; ++ p_clk->postdiv2_shift = clks[i].postdiv2_shift; ++ p_clk->postdiv2_width = clks[i].postdiv2_width; ++ ++ p_clk->ctrl_reg2 = base + clks[i].ctrl_reg2; ++ p_clk->fbdiv_shift = clks[i].fbdiv_shift; ++ p_clk->fbdiv_width = clks[i].fbdiv_width; ++ p_clk->refdiv_shift = clks[i].refdiv_shift; ++ p_clk->refdiv_width = clks[i].refdiv_width; ++ p_clk->hw.init = &init; ++ ++ clk = clk_register(NULL, &p_clk->hw); ++ if (IS_ERR(clk)) { ++ kfree(p_clk); ++ pr_err("%s: failed to register clock %s\n", ++ __func__, clks[i].name); ++ continue; ++ } ++ ++ data->clk_data.clks[clks[i].id] = clk; ++ } ++ ++ ++} ++ ++static void __init hi3519_clk_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ ++ clk_data = hisi_clk_init(np, HI3519_NR_CLKS); ++ if (!clk_data) ++ return; ++ if (IS_ENABLED(CONFIG_RESET_CONTROLLER)) ++ hisi_reset_init(np, HI3519_NR_RSTS); ++ ++ hisi_clk_register_fixed_rate(hi3519_fixed_rate_clks, ++ ARRAY_SIZE(hi3519_fixed_rate_clks), ++ clk_data); ++ hi3519_clk_register_pll(hi3519_pll_clks, ++ ARRAY_SIZE(hi3519_pll_clks), clk_data); ++ ++ hisi_clk_register_mux(hi3519_mux_clks, ARRAY_SIZE(hi3519_mux_clks), ++ clk_data); ++ hisi_clk_register_fixed_factor(hi3519_fixed_factor_clks, ++ ARRAY_SIZE(hi3519_fixed_factor_clks), clk_data); ++ hisi_clk_register_gate(hi3519_gate_clks, ++ ARRAY_SIZE(hi3519_gate_clks), clk_data); ++} ++ ++CLK_OF_DECLARE(hi3519_clk, "hisilicon,hi3519-clock", hi3519_clk_init); +diff --git a/drivers/clk/hisilicon/clk-hi3519v101.c b/drivers/clk/hisilicon/clk-hi3519v101.c +new file mode 100644 +index 0000000..1f30e6c +--- /dev/null ++++ b/drivers/clk/hisilicon/clk-hi3519v101.c +@@ -0,0 +1,385 @@ ++/* ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "clk.h" ++#include "reset.h" ++ ++/******************************************************************************/ ++struct hi3519v101_pll_clock { ++ u32 id; ++ const char *name; ++ const char *parent_name; ++ u32 ctrl_reg1; ++ u8 frac_shift; ++ u8 frac_width; ++ u8 postdiv1_shift; ++ u8 postdiv1_width; ++ u8 postdiv2_shift; ++ u8 postdiv2_width; ++ u32 ctrl_reg2; ++ u8 fbdiv_shift; ++ u8 fbdiv_width; ++ u8 refdiv_shift; ++ u8 refdiv_width; ++}; ++ ++struct hi3519v101_clk_pll { ++ struct clk_hw hw; ++ u32 id; ++ void __iomem *ctrl_reg1; ++ u8 frac_shift; ++ u8 frac_width; ++ u8 postdiv1_shift; ++ u8 postdiv1_width; ++ u8 postdiv2_shift; ++ u8 postdiv2_width; ++ void __iomem *ctrl_reg2; ++ u8 fbdiv_shift; ++ u8 fbdiv_width; ++ u8 refdiv_shift; ++ u8 refdiv_width; ++}; ++ ++static struct hisi_fixed_rate_clock hi3519v101_fixed_rate_clks[] __initdata = { ++ { HI3519_FIXED_2376M, "2376m", NULL, CLK_IS_ROOT, 2376000000UL, }, ++ { HI3519_FIXED_1188M, "1188m", NULL, CLK_IS_ROOT, 1188000000, }, ++ { HI3519_FIXED_594M, "594m", NULL, CLK_IS_ROOT, 594000000, }, ++ { HI3519_FIXED_297M, "297m", NULL, CLK_IS_ROOT, 297000000, }, ++ { HI3519_FIXED_148P5M, "148p5m", NULL, CLK_IS_ROOT, 148500000, }, ++ { HI3519_FIXED_74P25M, "74p25m", NULL, CLK_IS_ROOT, 74250000, }, ++ { HI3519_FIXED_792M, "792m", NULL, CLK_IS_ROOT, 792000000, }, ++ { HI3519_FIXED_475M, "475m", NULL, CLK_IS_ROOT, 475000000, }, ++ { HI3519_FIXED_340M, "340m", NULL, CLK_IS_ROOT, 340000000, }, ++ { HI3519_FIXED_72M, "72m", NULL, CLK_IS_ROOT, 72000000, }, ++ { HI3519_FIXED_400M, "400m", NULL, CLK_IS_ROOT, 400000000, }, ++ { HI3519_FIXED_200M, "200m", NULL, CLK_IS_ROOT, 200000000, }, ++ { HI3519_FIXED_54M, "54m", NULL, CLK_IS_ROOT, 54000000, }, ++ { HI3519_FIXED_27M, "27m", NULL, CLK_IS_ROOT, 1188000000, }, ++ { HI3519_FIXED_37P125M, "37p125m", NULL, CLK_IS_ROOT, 37125000, }, ++ { HI3519_FIXED_3000M, "3000m", NULL, CLK_IS_ROOT, 3000000000UL, }, ++ { HI3519_FIXED_1500M, "1500m", NULL, CLK_IS_ROOT, 1500000000, }, ++ { HI3519_FIXED_500M, "500m", NULL, CLK_IS_ROOT, 500000000, }, ++ { HI3519_FIXED_250M, "250m", NULL, CLK_IS_ROOT, 250000000, }, ++ { HI3519_FIXED_125M, "125m", NULL, CLK_IS_ROOT, 125000000, }, ++ { HI3519_FIXED_1000M, "1000m", NULL, CLK_IS_ROOT, 1000000000, }, ++ { HI3519_FIXED_600M, "600m", NULL, CLK_IS_ROOT, 600000000, }, ++ { HI3519_FIXED_750M, "750m", NULL, CLK_IS_ROOT, 750000000, }, ++ { HI3519_FIXED_150M, "150m", NULL, CLK_IS_ROOT, 150000000, }, ++ { HI3519_FIXED_75M, "75m", NULL, CLK_IS_ROOT, 75000000, }, ++ { HI3519_FIXED_300M, "300m", NULL, CLK_IS_ROOT, 300000000, }, ++ { HI3519_FIXED_60M, "60m", NULL, CLK_IS_ROOT, 60000000, }, ++ { HI3519_FIXED_214M, "214m", NULL, CLK_IS_ROOT, 214000000, }, ++ { HI3519_FIXED_107M, "107m", NULL, CLK_IS_ROOT, 107000000, }, ++ { HI3519_FIXED_100M, "100m", NULL, CLK_IS_ROOT, 100000000, }, ++ { HI3519_FIXED_50M, "50m", NULL, CLK_IS_ROOT, 50000000, }, ++ { HI3519_FIXED_25M, "25m", NULL, CLK_IS_ROOT, 25000000, }, ++ { HI3519_FIXED_24M, "24m", NULL, CLK_IS_ROOT, 24000000, }, ++ { HI3519_FIXED_3M, "3m", NULL, CLK_IS_ROOT, 3000000, }, ++ { HI3519_FIXED_198M, "198m", NULL, CLK_IS_ROOT, 198000000, }, ++ { HI3519_FIXED_396M, "396m", NULL, CLK_IS_ROOT, 396000000, }, ++}; ++ ++static const char *sysaxi_mux_p[] __initconst = {"24m", "198m", }; ++static u32 sysaxi_mux_table[] = {0, 1}; ++ ++static const char *fmc_mux_p[] __initconst = { ++ "24m", "75m", "125m", "150m", "198m", "250m", "300m", "396m", }; ++static u32 fmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6, 7}; ++ ++static const char *mmc_mux_p[] __initconst = { ++ "100m", "198m", "396m", "594m", "792m", "1188m", }; ++static u32 mmc_mux_table[] = {0, 1, 3, 4, 5, 7}; ++ ++static const char *a17_mux_p[] __initconst = { ++ "24m", "apll", "594m", "792m", }; ++static u32 a17_mux_table[] = {0, 1, 3, 4}; ++ ++static const char *i2c_mux_p[] __initconst = {"clk_sysapb", "50m"}; ++static u32 i2c_mux_table[] = {0, 1}; ++ ++static struct hisi_mux_clock hi3519v101_mux_clks[] __initdata = { ++ { HI3519_SYSAXI_MUX, "sysaxi_mux", sysaxi_mux_p, ++ ARRAY_SIZE(sysaxi_mux_p), ++ CLK_SET_RATE_PARENT, 0x34, 12, 2, 0, sysaxi_mux_table, }, ++ { HI3519_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc0, 2, 3, 0, fmc_mux_table, }, ++ { HI3519_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 10, 3, 0, mmc_mux_table, }, ++ { HI3519_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 2, 3, 0, mmc_mux_table, }, ++ { HI3519_MMC2_MUX, "mmc2_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 18, 3, 0, mmc_mux_table, }, ++ { HI3519_A17_MUX, "a17_mux", a17_mux_p, ARRAY_SIZE(a17_mux_p), ++ CLK_SET_RATE_PARENT, 0x34, 4, 3, 0, a17_mux_table, }, ++ { HI3519_I2C_MUX, "i2c_mux", i2c_mux_p, ARRAY_SIZE(i2c_mux_p), ++ CLK_SET_RATE_PARENT, 0xe4, 26, 1, 0, i2c_mux_table, }, ++ ++}; ++ ++static struct hisi_fixed_factor_clock ++ hi3519v101_fixed_factor_clks[] __initdata = { ++ { HI3519_SYSAPB_CLK, "clk_sysapb", "sysaxi_mux", 1, 4, ++ CLK_SET_RATE_PARENT}, ++ { HI3519_MMC0_FAC_CLK, "mmc0_fac", "mmc0_mux", 1, 8, ++ CLK_SET_RATE_PARENT}, ++ { HI3519_MMC1_FAC_CLK, "mmc1_fac", "mmc1_mux", 1, 8, ++ CLK_SET_RATE_PARENT}, ++ { HI3519_MMC2_FAC_CLK, "mmc2_fac", "mmc2_mux", 1, 8, ++ CLK_SET_RATE_PARENT}, ++}; ++ ++static struct hisi_gate_clock hi3519v101_gate_clks[] __initdata = { ++#ifdef CONFIG_HIFMC ++ /* fmc */ ++ { HI3519_FMC_CLK, "clk_fmc", "fmc_mux", ++ CLK_SET_RATE_PARENT, 0xc0, 1, 0, }, ++#endif ++ /* mmc */ ++ { HI3519_MMC0_CLK, "clk_mmc0", "mmc0_fac", ++ CLK_SET_RATE_PARENT, 0xc4, 9, 0, }, ++ { HI3519_MMC1_CLK, "clk_mmc1", "mmc1_fac", ++ CLK_SET_RATE_PARENT, 0xc4, 1, 0, }, ++ { HI3519_MMC2_CLK, "clk_mmc2", "mmc2_fac", ++ CLK_SET_RATE_PARENT, 0xc4, 17, 0, }, ++ ++ /* usb ctrl */ ++ { HI3519_USB2_CTRL_UTMI0_REQ, "usb2_cttl_utmi0_req", NULL, ++ CLK_SET_RATE_PARENT, 0xb4, 5, 1, }, ++ { HI3519_USB2_HRST_REQ, "usb2_hrst_req", NULL, ++ CLK_SET_RATE_PARENT, 0xb4, 0, 1, }, ++ { HI3519_USB3_CLK, "usb3_vcc_srst_req2", NULL, ++ CLK_SET_RATE_PARENT, 0xb8, 0, 1, }, ++ ++ /* uart */ ++ { HI3519_UART0_CLK, "clk_uart0", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 20, 0, }, ++ { HI3519_UART1_CLK, "clk_uart1", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 21, 0, }, ++ { HI3519_UART2_CLK, "clk_uart2", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 22, 0, }, ++ { HI3519_UART3_CLK, "clk_uart3", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 23, 0, }, ++ { HI3519_UART4_CLK, "clk_uart4", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 24, 0, }, ++ ++ /* ethernet mac */ ++ { HI3519_ETH_CLK, "clk_eth", NULL, ++ CLK_IS_ROOT, 0xcc, 1, 0, }, ++ { HI3519_ETH_MACIF_CLK, "clk_eth_macif", NULL, ++ CLK_IS_ROOT, 0xcc, 3, 0, }, ++ ++ /* spi */ ++ { HI3519_SPI0_CLK, "clk_spi0", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 16, 0, }, ++ { HI3519_SPI1_CLK, "clk_spi1", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 17, 0, }, ++ { HI3519_SPI2_CLK, "clk_spi2", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 18, 0, }, ++ { HI3519_SPI3_CLK, "clk_spi3", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 28, 0, }, ++}; ++ ++static struct hi3519v101_pll_clock hi3519v101_pll_clks[] __initdata = { ++ { HI3519_APLL_CLK, "apll", NULL, 0x0, 0, 24, 24, 3, 28, 3, ++ 0x4, 0, 12, 12, 6}, ++}; ++ ++ ++#define to_pll_clk(_hw) container_of(_hw, struct hi3519v101_clk_pll, hw) ++ ++static void hi3519v101_calc_pll(u32 *frac_val, ++ u32 *postdiv1_val, ++ u32 *postdiv2_val, ++ u32 *fbdiv_val, ++ u32 *refdiv_val, ++ unsigned long rate) ++{ ++ u64 rem; ++ *frac_val = 0; ++ rem = do_div(rate, 1000000); ++ *fbdiv_val = rate; ++ *refdiv_val = 24; ++ rem = rem * (1 << 24); ++ do_div(rem, 1000000); ++ *frac_val = rem; ++} ++ ++static int clk_pll_set_rate(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct hi3519v101_clk_pll *clk = to_pll_clk(hw); ++ u32 frac_val, postdiv1_val, postdiv2_val, fbdiv_val, refdiv_val; ++ u32 val; ++ ++ /*Fixme ignore postdives now because apll don't use them*/ ++ postdiv1_val = postdiv2_val = 0; ++ ++ hi3519v101_calc_pll(&frac_val, &postdiv1_val, &postdiv2_val, ++ &fbdiv_val, &refdiv_val, rate); ++ ++ val = readl_relaxed(clk->ctrl_reg1); ++ val &= ~(((1 << clk->frac_width) - 1) << clk->frac_shift); ++ val &= ~(((1 << clk->postdiv1_width) - 1) << clk->postdiv1_shift); ++ val &= ~(((1 << clk->postdiv2_width) - 1) << clk->postdiv2_shift); ++ ++ val |= frac_val << clk->frac_shift; ++ val |= postdiv1_val << clk->postdiv1_shift; ++ val |= postdiv2_val << clk->postdiv2_shift; ++ writel_relaxed(val, clk->ctrl_reg1); ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val &= ~(((1 << clk->fbdiv_width) - 1) << clk->fbdiv_shift); ++ val &= ~(((1 << clk->refdiv_width) - 1) << clk->refdiv_shift); ++ ++ val |= fbdiv_val << clk->fbdiv_shift; ++ val |= refdiv_val << clk->refdiv_shift; ++ writel_relaxed(val, clk->ctrl_reg2); ++ ++ return 0; ++} ++ ++static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct hi3519v101_clk_pll *clk = to_pll_clk(hw); ++ u64 frac_val, fbdiv_val, refdiv_val; ++ u32 val; ++ u64 tmp, rate; ++ ++ val = readl_relaxed(clk->ctrl_reg1); ++ val = val >> clk->frac_shift; ++ val &= ((1 << clk->frac_width) - 1); ++ frac_val = val; ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val = val >> clk->fbdiv_shift; ++ val &= ((1 << clk->fbdiv_width) - 1); ++ fbdiv_val = val; ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val = val >> clk->refdiv_shift; ++ val &= ((1 << clk->refdiv_width) - 1); ++ refdiv_val = val; ++ ++ /* rate = 24000000 * (fbdiv + frac / (1<<24) ) / refdiv */ ++ rate = 0; ++ tmp = 24000000 * fbdiv_val; ++ rate += tmp; ++ do_div(rate, refdiv_val); ++ ++ return rate; ++} ++ ++ ++static long clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *best_parent_rate, ++ struct clk **best_parent_p) ++{ ++ return rate; ++} ++ ++static struct clk_ops clk_pll_ops = { ++ .set_rate = clk_pll_set_rate, ++ .determine_rate = clk_pll_determine_rate, ++ .recalc_rate = clk_pll_recalc_rate, ++}; ++ ++void __init hi3519v101_clk_register_pll(struct hi3519v101_pll_clock *clks, ++ int nums, struct hisi_clock_data *data) ++{ ++ void __iomem *base = data->base; ++ int i; ++ ++ for (i = 0; i < nums; i++) { ++ struct hi3519v101_clk_pll *p_clk; ++ struct clk *clk; ++ struct clk_init_data init; ++ ++ p_clk = kzalloc(sizeof(*p_clk), GFP_KERNEL); ++ if (!p_clk) ++ return; ++ ++ init.name = clks[i].name; ++ init.flags = CLK_IS_BASIC; ++ init.parent_names = ++ (clks[i].parent_name ? &clks[i].parent_name : NULL); ++ init.num_parents = (clks[i].parent_name ? 1 : 0); ++ init.ops = &clk_pll_ops; ++ ++ p_clk->ctrl_reg1 = base + clks[i].ctrl_reg1; ++ p_clk->frac_shift = clks[i].frac_shift; ++ p_clk->frac_width = clks[i].frac_width; ++ p_clk->postdiv1_shift = clks[i].postdiv1_shift; ++ p_clk->postdiv1_width = clks[i].postdiv1_width; ++ p_clk->postdiv2_shift = clks[i].postdiv2_shift; ++ p_clk->postdiv2_width = clks[i].postdiv2_width; ++ ++ p_clk->ctrl_reg2 = base + clks[i].ctrl_reg2; ++ p_clk->fbdiv_shift = clks[i].fbdiv_shift; ++ p_clk->fbdiv_width = clks[i].fbdiv_width; ++ p_clk->refdiv_shift = clks[i].refdiv_shift; ++ p_clk->refdiv_width = clks[i].refdiv_width; ++ p_clk->hw.init = &init; ++ ++ clk = clk_register(NULL, &p_clk->hw); ++ if (IS_ERR(clk)) { ++ kfree(p_clk); ++ pr_err("%s: failed to register clock %s\n", ++ __func__, clks[i].name); ++ continue; ++ } ++ ++ data->clk_data.clks[clks[i].id] = clk; ++ } ++ ++ ++} ++ ++static void __init hi3519v101_clk_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ ++ clk_data = hisi_clk_init(np, HI3519_NR_CLKS); ++ if (!clk_data) ++ return; ++ if (IS_ENABLED(CONFIG_RESET_CONTROLLER)) ++ hisi_reset_init(np, HI3519_NR_RSTS); ++ ++ hisi_clk_register_fixed_rate(hi3519v101_fixed_rate_clks, ++ ARRAY_SIZE(hi3519v101_fixed_rate_clks), ++ clk_data); ++ hi3519v101_clk_register_pll(hi3519v101_pll_clks, ++ ARRAY_SIZE(hi3519v101_pll_clks), clk_data); ++ ++ hisi_clk_register_mux(hi3519v101_mux_clks, ++ ARRAY_SIZE(hi3519v101_mux_clks), ++ clk_data); ++ hisi_clk_register_fixed_factor(hi3519v101_fixed_factor_clks, ++ ARRAY_SIZE(hi3519v101_fixed_factor_clks), clk_data); ++ hisi_clk_register_gate(hi3519v101_gate_clks, ++ ARRAY_SIZE(hi3519v101_gate_clks), clk_data); ++} ++ ++CLK_OF_DECLARE(hi3519v101_clk, "hisilicon,hi3519v101-clock", ++ hi3519v101_clk_init); +diff --git a/drivers/clk/hisilicon/clk-hi3521d.c b/drivers/clk/hisilicon/clk-hi3521d.c +new file mode 100644 +index 0000000..a74cc92 +--- /dev/null ++++ b/drivers/clk/hisilicon/clk-hi3521d.c +@@ -0,0 +1,179 @@ ++/* ++ * Hi3521D Clock Driver ++ * ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include "clk.h" ++#include "reset.h" ++ ++static struct ++hisi_fixed_rate_clock hi3521d_fixed_rate_clks_crg[] __initdata = { ++ { HI3521D_FIXED_3M, "3m", NULL, CLK_IS_ROOT, 3000000, }, ++ { HI3521D_FIXED_6M, "6m", NULL, CLK_IS_ROOT, 6000000, }, ++ { HI3521D_FIXED_12M, "12m", NULL, CLK_IS_ROOT, 12000000, }, ++ { HI3521D_FIXED_24M, "24m", NULL, CLK_IS_ROOT, 24000000, }, ++ { HI3521D_FIXED_83P3M, "83.3m", NULL, CLK_IS_ROOT, 83300000, }, ++ { HI3521D_FIXED_100M, "100m", NULL, CLK_IS_ROOT, 100000000, }, ++ { HI3521D_FIXED_125M, "125m", NULL, CLK_IS_ROOT, 125000000, }, ++ { HI3521D_FIXED_150M, "150m", NULL, CLK_IS_ROOT, 150000000, }, ++ { HI3521D_FIXED_200M, "200m", NULL, CLK_IS_ROOT, 200000000, }, ++ { HI3521D_FIXED_250M, "250m", NULL, CLK_IS_ROOT, 250000000, }, ++ { HI3521D_FIXED_300M, "300m", NULL, CLK_IS_ROOT, 300000000, }, ++ { HI3521D_FIXED_324M, "324m", NULL, CLK_IS_ROOT, 324000000, }, ++ { HI3521D_FIXED_342M, "342m", NULL, CLK_IS_ROOT, 342000000, }, ++ { HI3521D_FIXED_342M, "375m", NULL, CLK_IS_ROOT, 375000000, }, ++ { HI3521D_FIXED_400M, "400m", NULL, CLK_IS_ROOT, 400000000, }, ++ { HI3521D_FIXED_448M, "448m", NULL, CLK_IS_ROOT, 448000000, }, ++ { HI3521D_FIXED_500M, "500m", NULL, CLK_IS_ROOT, 500000000, }, ++ { HI3521D_FIXED_540M, "540m", NULL, CLK_IS_ROOT, 540000000, }, ++ { HI3521D_FIXED_600M, "600m", NULL, CLK_IS_ROOT, 600000000, }, ++ { HI3521D_FIXED_750M, "750m", NULL, CLK_IS_ROOT, 750000000, }, ++ { HI3521D_FIXED_1500M, "1500m", NULL, CLK_IS_ROOT, 1500000000UL, }, ++}; ++ ++static const char *sysaxi_mux_p[] __initconst = { ++ "24m", "200m", "250m", "300m"}; ++/* If syaaxi bus clock is 200MHz, so the APB clock is 50MHz, factor is 4 */ ++static const char *uart_mux_p[] __initconst = {"sysaxi_mux", "24m", "2m"}; ++static const char *fmc_mux_p[] __initconst = { ++ "24m", "83.3m", "150m"}; ++ ++static const char *viu_mux_p[] = {"300m", "200m", "150m"}; ++static u32 sysaxi_mux_table[] = {0, 1, 2, 3}; ++static u32 uart_mux_table[] = {0, 1, 2}; ++static u32 fmc_mux_table[] = {0, 1, 2}; ++static u32 viu_mux_p_table[] = {0, 1, 2}; ++ ++static struct hisi_mux_clock hi3521d_mux_clks_crg[] __initdata = { ++ { HI3521D_SYSAXI_CLK, "sysaxi_mux", sysaxi_mux_p, ++ ARRAY_SIZE(sysaxi_mux_p), ++ CLK_SET_RATE_PARENT, 0x50, 2, 2, 0, sysaxi_mux_table, }, ++ { HI3521D_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), ++ CLK_SET_RATE_PARENT, 0x148, 2, 2, 0, fmc_mux_table, }, ++ { HI3521D_UART_MUX, "uart_mux", uart_mux_p, ++ ARRAY_SIZE(uart_mux_p), ++ CLK_SET_RATE_PARENT, 0x154, 19, 2, 0, uart_mux_table, }, ++ { HI3521D_VIU_MUX, "viu_mux", viu_mux_p, ARRAY_SIZE(viu_mux_p), ++ CLK_SET_RATE_PARENT, 0x98, 5, 2, 0, viu_mux_p_table, }, ++}; ++ ++static struct hisi_fixed_factor_clock ++ hi3521d_fixed_factor_clks[] __initdata = { ++ { HI3521D_SYSAXI_CLK, "clk_sysaxi", "sysaxi_mux", 1, 4, ++ CLK_SET_RATE_PARENT}, ++}; ++ ++static struct hisi_gate_clock hi3521d_gate_clks[] __initdata = { ++#ifdef CONFIG_HIFMC ++ /* fmc */ ++ { HI3521D_FMC_CLK, "clk_fmc", "fmc_mux", ++ CLK_SET_RATE_PARENT, 0x148, 1, 0, }, ++#endif ++ /* uart */ ++ { HI3521D_UART0_CLK, "clk_uart0", "24m", ++ CLK_SET_RATE_PARENT, 0x154, 15, 0, }, ++ { HI3521D_UART1_CLK, "clk_uart1", "24m", ++ CLK_SET_RATE_PARENT, 0x154, 16, 0, }, ++ { HI3521D_UART2_CLK, "clk_uart2", "24m", ++ CLK_SET_RATE_PARENT, 0x154, 17, 0, }, ++ { HI3521D_UART3_CLK, "clk_uart3", "24m", ++ CLK_SET_RATE_PARENT, 0x154, 18, 0, }, ++ /* ethernet mac */ ++ { HI3521D_ETH_PHY_CLK, "clk_eth_phy", NULL, ++ CLK_SET_RATE_PARENT, 0x14c, 6, 0, }, ++ { HI3521D_ETH_PUB_CLK, "clk_eth_pub", "clk_eth_phy", ++ CLK_SET_RATE_PARENT, 0x14c, 7, 0, }, ++ { HI3521D_ETH_CLK, "clk_eth", "clk_eth_pub", ++ CLK_SET_RATE_PARENT, 0x14c, 1, 0, }, ++ { HI3521D_ETH_MACIF_CLK, "clk_eth_macif", "clk_eth_pub", ++ CLK_SET_RATE_PARENT, 0x14c, 3, 0, }, ++ /* spi */ ++ { HI3521D_SPI0_CLK, "clk_spi0", "clk_sysaxi", ++ CLK_SET_RATE_PARENT, 0x154, 13, 0, }, ++ { HI3521D_VIU_CLK, "clk_viu", "viu_mux", CLK_SET_RATE_PARENT, ++ 0x98, 2, 0, }, ++ /* dma */ ++ { HI3521D_DMAC_CLK, "clk_dmac", "50m", CLK_SET_RATE_PARENT, ++ 0x144, 1, 0, }, ++}; ++ ++static void __init hi3521d_clk_crg_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ unsigned int count = 0; ++ ++ clk_data = hisi_clk_init(np, HI3521D_CRG_NR_CLKS); ++ if (!clk_data) ++ return; ++ ++ hisi_clk_register_fixed_rate(hi3521d_fixed_rate_clks_crg, ++ ARRAY_SIZE(hi3521d_fixed_rate_clks_crg), ++ clk_data); ++ hisi_clk_register_mux(hi3521d_mux_clks_crg, ++ ARRAY_SIZE(hi3521d_mux_clks_crg), clk_data); ++ hisi_clk_register_fixed_factor(hi3521d_fixed_factor_clks, ++ ARRAY_SIZE(hi3521d_fixed_factor_clks), clk_data); ++ hisi_clk_register_gate(hi3521d_gate_clks, ++ ARRAY_SIZE(hi3521d_gate_clks), clk_data); ++ ++ if (!of_property_read_u32(np, "#reset-cells", &count) && (count == 2)) ++ hisi_reset_init(np, HI3521D_CRG_NR_RSTS); ++} ++ ++static const char *timer_mux_p[] __initconst = { "3m", "clk_sysapb" }; ++static u32 timer_mux_table[] = {0, 1}; ++ ++static struct hisi_mux_clock hi3521d_mux_clks_sys[] __initdata = { ++ { HI3521D_TIME0_0_CLK, "timer00", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 16, 1, 0, timer_mux_table, }, ++ ++ { HI3521D_TIME0_1_CLK, "timer01", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 18, 1, 0, timer_mux_table, }, ++ ++ { HI3521D_TIME1_2_CLK, "timer12", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 20, 1, 0, timer_mux_table, }, ++ ++ { HI3521D_TIME1_3_CLK, "timer13", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 22, 1, 0, timer_mux_table, }, ++}; ++ ++static void __init hi3521d_clk_sys_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ unsigned int count = 0; ++ ++ clk_data = hisi_clk_init(np, HI3521D_SYS_NR_CLKS); ++ if (!clk_data) ++ return; ++ ++ hisi_clk_register_mux(hi3521d_mux_clks_sys, ++ ARRAY_SIZE(hi3521d_mux_clks_sys), clk_data); ++ ++ if (!of_property_read_u32(np, "#reset-cells", &count) && (count == 2)) ++ hisi_reset_init(np, HI3521D_SYS_NR_RSTS); ++} ++ ++CLK_OF_DECLARE(hi3521d_clk_crg, "hisilicon,hi3521d-clock", ++ hi3521d_clk_crg_init); ++CLK_OF_DECLARE(hi3521d_clk_sys, "hisilicon,sysctrl", hi3521d_clk_sys_init); ++ +diff --git a/drivers/clk/hisilicon/clk-hi3531d.c b/drivers/clk/hisilicon/clk-hi3531d.c +new file mode 100644 +index 0000000..5dc519e +--- /dev/null ++++ b/drivers/clk/hisilicon/clk-hi3531d.c +@@ -0,0 +1,205 @@ ++/* ++ * Hi3531D Clock Driver ++ * ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include "clk.h" ++#include "reset.h" ++ ++static struct ++hisi_fixed_rate_clock hi3531d_fixed_rate_clks_crg[] __initdata = { ++ { HI3531D_FIXED_3M, "3m", NULL, CLK_IS_ROOT, 3000000, }, ++ { HI3531D_FIXED_6M, "6m", NULL, CLK_IS_ROOT, 6000000, }, ++ { HI3531D_FIXED_12M, "12m", NULL, CLK_IS_ROOT, 12000000, }, ++ { HI3531D_FIXED_15M, "15m", NULL, CLK_IS_ROOT, 15000000, }, ++ { HI3531D_FIXED_24M, "24m", NULL, CLK_IS_ROOT, 24000000, }, ++ { HI3531D_FIXED_44M, "44m", NULL, CLK_IS_ROOT, 44000000, }, ++ { HI3531D_FIXED_49P5, "49.5m", NULL, CLK_IS_ROOT, 49500000, }, ++ { HI3531D_FIXED_50M, "50m", NULL, CLK_IS_ROOT, 50000000, }, ++ { HI3531D_FIXED_54M, "54m", NULL, CLK_IS_ROOT, 54000000, }, ++ { HI3531D_FIXED_75M, "75m", NULL, CLK_IS_ROOT, 75000000, }, ++ { HI3531D_FIXED_83P3M, "83.3m", NULL, CLK_IS_ROOT, 83300000, }, ++ { HI3531D_FIXED_99M, "99m", NULL, CLK_IS_ROOT, 99000000, }, ++ { HI3531D_FIXED_100M, "100m", NULL, CLK_IS_ROOT, 100000000, }, ++ { HI3531D_FIXED_125M, "125m", NULL, CLK_IS_ROOT, 125000000, }, ++ { HI3531D_FIXED_150M, "150m", NULL, CLK_IS_ROOT, 150000000, }, ++ { HI3531D_FIXED_200M, "200m", NULL, CLK_IS_ROOT, 200000000, }, ++ { HI3531D_FIXED_250M, "250m", NULL, CLK_IS_ROOT, 250000000, }, ++ { HI3531D_FIXED_300M, "300m", NULL, CLK_IS_ROOT, 300000000, }, ++ { HI3531D_FIXED_324M, "324m", NULL, CLK_IS_ROOT, 324000000, }, ++ { HI3531D_FIXED_342M, "342m", NULL, CLK_IS_ROOT, 342000000, }, ++ { HI3531D_FIXED_342M, "375m", NULL, CLK_IS_ROOT, 375000000, }, ++ { HI3531D_FIXED_400M, "400m", NULL, CLK_IS_ROOT, 400000000, }, ++ { HI3531D_FIXED_448M, "448m", NULL, CLK_IS_ROOT, 448000000, }, ++ { HI3531D_FIXED_500M, "500m", NULL, CLK_IS_ROOT, 500000000, }, ++ { HI3531D_FIXED_540M, "540m", NULL, CLK_IS_ROOT, 540000000, }, ++ { HI3531D_FIXED_600M, "600m", NULL, CLK_IS_ROOT, 600000000, }, ++ { HI3531D_FIXED_750M, "750m", NULL, CLK_IS_ROOT, 750000000, }, ++ { HI3531D_FIXED_1500M, "1500m", NULL, CLK_IS_ROOT, 1500000000UL, }, ++}; ++ ++static const char *periaxi_mux_p[] __initconst = { ++ "24m", "200m", "300m"}; ++static const char *sysaxi_mux_p[] __initconst = { ++ "24m", "324m", "375m"}; ++/* PERIAXI clock is 200MHz, so the APB clock is 50MHz, factor is 4 */ ++static const char *uart_mux_p[] __initconst = {"clk_sysapb", "24m", "2m"}; ++static const char *fmc_mux_p[] __initconst = { ++ "24m", "83.3m", "125m", "150m"}; ++static const char *nfc_mux_p[] __initconst = { ++ "24m", "200m"}; ++ ++static const char *viu_mux_p[] = {"300m", "200m", "150m"}; ++ ++static u32 periaxi_mux_table[] = {0, 1, 2}; ++static u32 sysaxi_mux_table[] = {0, 1, 2}; ++static u32 uart_mux_table[] = {0, 1, 2}; ++static u32 fmc_mux_table[] = {0, 1, 2, 3}; ++static u32 nfc_mux_table[] = {0, 1}; ++static u32 viu_mux_p_table[] = {0, 1, 2}; ++ ++static struct hisi_mux_clock hi3531d_mux_clks_crg[] __initdata = { ++ { HI3531D_PERIAXI_CLK, "periaxi_mux", periaxi_mux_p, ++ ARRAY_SIZE(periaxi_mux_p), ++ CLK_SET_RATE_PARENT, 0x50, 0, 2, 0, periaxi_mux_table, }, ++ { HI3531D_SYSAXI_CLK, "sysaxi_mux", sysaxi_mux_p, ++ ARRAY_SIZE(sysaxi_mux_p), ++ CLK_SET_RATE_PARENT, 0x50, 2, 2, 0, sysaxi_mux_table, }, ++ { HI3531D_NFC_MUX, "nfc_mux", nfc_mux_p, ARRAY_SIZE(nfc_mux_p), ++ CLK_SET_RATE_PARENT, 0x13c, 2, 1, 0, nfc_mux_table, }, ++ { HI3531D_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), ++ CLK_SET_RATE_PARENT, 0x148, 2, 2, 0, fmc_mux_table, }, ++ { HI3531D_UART_MUX, "uart_mux", uart_mux_p, ++ ARRAY_SIZE(uart_mux_p), ++ CLK_SET_RATE_PARENT, 0x154, 19, 2, 0, uart_mux_table, }, ++ ++ /* media mux clock*/ ++ { HI3531D_VIU_MUX, "viu_mux", viu_mux_p, ARRAY_SIZE(viu_mux_p), ++ CLK_SET_RATE_PARENT, 0x98, 5, 2, 0, viu_mux_p_table, }, ++ ++}; ++ ++static struct hisi_fixed_factor_clock ++ hi3531d_fixed_factor_clks[] __initdata = { ++ { HI3531D_PERIAXI_CLK, "clk_sysapb", "periaxi_mux", 1, 4, ++ CLK_SET_RATE_PARENT}, ++ { HI3531D_SYSAXI_CLK, "clk_sysaxi", "sysaxi_mux", 1, 4, ++ CLK_SET_RATE_PARENT}, ++}; ++ ++static struct hisi_gate_clock hi3531d_gate_clks[] __initdata = { ++#ifdef CONFIG_HIFMC ++ /* fmc */ ++ { HI3531D_FMC_CLK, "clk_fmc", "fmc_mux", ++ CLK_SET_RATE_PARENT, 0x148, 1, 0, }, ++#endif ++#ifdef CONFIG_HINFC ++ /* hinfc610 */ ++ { HI3531D_NFC_CLK, "clk_nfc", "nfc_mux", ++ CLK_SET_RATE_PARENT, 0x13c, 1, 0, }, ++#endif ++ /* uart */ ++ { HI3531D_UART0_CLK, "clk_uart0", "24m", ++ CLK_SET_RATE_PARENT, 0x154, 15, 0, }, ++ { HI3531D_UART1_CLK, "clk_uart1", "24m", ++ CLK_SET_RATE_PARENT, 0x154, 16, 0, }, ++ { HI3531D_UART2_CLK, "clk_uart2", "24m", ++ CLK_SET_RATE_PARENT, 0x154, 17, 0, }, ++ { HI3531D_UART3_CLK, "clk_uart3", "24m", ++ CLK_SET_RATE_PARENT, 0x154, 18, 0, }, ++ /* ethernet mac */ ++ { HI3531D_ETH_CLK, "clk_eth", NULL, ++ CLK_IS_ROOT, 0x14c, 1, 0, }, ++ { HI3531D_ETH_MACIF_CLK, "clk_eth_macif", NULL, ++ CLK_IS_ROOT, 0x14c, 3, 0, }, ++ /* spi */ ++ { HI3531D_SPI0_CLK, "clk_spi0", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0x154, 13, 0, }, ++ /* media gate clock*/ ++ { HI3531D_VIU_CLK, "clk_viu", "viu_mux", CLK_SET_RATE_PARENT, ++ 0x98, 2, 0, }, ++ /* dma */ ++ { HI3531D_DMAC_CLK, "clk_dmac", "50m", CLK_SET_RATE_PARENT, ++ 0x144, 1, 0, }, ++}; ++ ++static void __init hi3531d_clk_crg_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ unsigned int count = 0; ++ ++ clk_data = hisi_clk_init(np, HI3531D_CRG_NR_CLKS); ++ if (!clk_data) ++ return; ++ ++ hisi_clk_register_fixed_rate(hi3531d_fixed_rate_clks_crg, ++ ARRAY_SIZE(hi3531d_fixed_rate_clks_crg), ++ clk_data); ++ hisi_clk_register_mux(hi3531d_mux_clks_crg, ++ ARRAY_SIZE(hi3531d_mux_clks_crg), clk_data); ++ hisi_clk_register_fixed_factor(hi3531d_fixed_factor_clks, ++ ARRAY_SIZE(hi3531d_fixed_factor_clks), clk_data); ++ hisi_clk_register_gate(hi3531d_gate_clks, ++ ARRAY_SIZE(hi3531d_gate_clks), clk_data); ++ ++ if (!of_property_read_u32(np, "#reset-cells", &count) && (count == 2)) ++ hisi_reset_init(np, HI3531D_CRG_NR_RSTS); ++} ++ ++static const char *timer_mux_p[] __initconst = { "3m", "clk_sysapb" }; ++static u32 timer_mux_table[] = {0, 1}; ++ ++static struct hisi_mux_clock hi3531d_mux_clks_sys[] __initdata = { ++ { HI3531D_TIME0_0_CLK, "timer00", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 16, 1, 0, timer_mux_table, }, ++ ++ { HI3531D_TIME0_1_CLK, "timer01", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 18, 1, 0, timer_mux_table, }, ++ ++ { HI3531D_TIME1_2_CLK, "timer12", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 20, 1, 0, timer_mux_table, }, ++ ++ { HI3531D_TIME1_3_CLK, "timer13", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 22, 1, 0, timer_mux_table, }, ++}; ++ ++static void __init hi3531d_clk_sys_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ unsigned int count = 0; ++ ++ clk_data = hisi_clk_init(np, HI3531D_SYS_NR_CLKS); ++ if (!clk_data) ++ return; ++ ++ hisi_clk_register_mux(hi3531d_mux_clks_sys, ++ ARRAY_SIZE(hi3531d_mux_clks_sys), clk_data); ++ ++ if (!of_property_read_u32(np, "#reset-cells", &count) && (count == 2)) ++ hisi_reset_init(np, HI3531D_SYS_NR_RSTS); ++} ++ ++CLK_OF_DECLARE(hi3531d_clk_crg, "hisilicon,hi3531d-clock", ++ hi3531d_clk_crg_init); ++CLK_OF_DECLARE(hi3531d_clk_sys, "hisilicon,sysctrl", hi3531d_clk_sys_init); ++ +diff --git a/drivers/clk/hisilicon/clk-hi3536c.c b/drivers/clk/hisilicon/clk-hi3536c.c +new file mode 100644 +index 0000000..e3ebd35 +--- /dev/null ++++ b/drivers/clk/hisilicon/clk-hi3536c.c +@@ -0,0 +1,178 @@ ++/* ++ * Hi3536C Clock Driver ++ * ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include "clk.h" ++#include "reset.h" ++ ++static struct ++hisi_fixed_rate_clock hi3536c_fixed_rate_clks_crg[] __initdata = { ++ { HI3536C_FIXED_3M, "3m", NULL, CLK_IS_ROOT, 3000000, }, ++ { HI3536C_FIXED_6M, "6m", NULL, CLK_IS_ROOT, 6000000, }, ++ { HI3536C_FIXED_12M, "12m", NULL, CLK_IS_ROOT, 12000000, }, ++ { HI3536C_FIXED_24M, "24m", NULL, CLK_IS_ROOT, 24000000, }, ++ { HI3536C_FIXED_83P3M, "83.3m", NULL, CLK_IS_ROOT, 83300000, }, ++ { HI3536C_FIXED_100M, "100m", NULL, CLK_IS_ROOT, 100000000, }, ++ { HI3536C_FIXED_125M, "125m", NULL, CLK_IS_ROOT, 125000000, }, ++ { HI3536C_FIXED_150M, "150m", NULL, CLK_IS_ROOT, 150000000, }, ++ { HI3536C_FIXED_200M, "200m", NULL, CLK_IS_ROOT, 200000000, }, ++ { HI3536C_FIXED_250M, "250m", NULL, CLK_IS_ROOT, 250000000, }, ++ { HI3536C_FIXED_300M, "300m", NULL, CLK_IS_ROOT, 300000000, }, ++ { HI3536C_FIXED_324M, "324m", NULL, CLK_IS_ROOT, 324000000, }, ++ { HI3536C_FIXED_342M, "342m", NULL, CLK_IS_ROOT, 342000000, }, ++ { HI3536C_FIXED_342M, "375m", NULL, CLK_IS_ROOT, 375000000, }, ++ { HI3536C_FIXED_400M, "400m", NULL, CLK_IS_ROOT, 400000000, }, ++ { HI3536C_FIXED_448M, "448m", NULL, CLK_IS_ROOT, 448000000, }, ++ { HI3536C_FIXED_500M, "500m", NULL, CLK_IS_ROOT, 500000000, }, ++ { HI3536C_FIXED_540M, "540m", NULL, CLK_IS_ROOT, 540000000, }, ++ { HI3536C_FIXED_600M, "600m", NULL, CLK_IS_ROOT, 600000000, }, ++ { HI3536C_FIXED_750M, "750m", NULL, CLK_IS_ROOT, 750000000, }, ++ { HI3536C_FIXED_1500M, "1500m", NULL, CLK_IS_ROOT, 1500000000UL, }, ++}; ++ ++static const char *sysaxi_mux_p[] __initconst = { ++ "24m", "200m", "250m", "300m"}; ++/* If syaaxi bus clock is 200MHz, so the APB clock is 50MHz, factor is 4 */ ++static const char *uart_mux_p[] __initconst = {"sysaxi_mux", "24m", "2m"}; ++static const char *fmc_mux_p[] __initconst = { ++ "24m", "83.3m", "150m"}; ++ ++static u32 sysaxi_mux_table[] = {0, 1, 2, 3}; ++static u32 uart_mux_table[] = {0, 1, 2}; ++static u32 fmc_mux_table[] = {0, 1, 2}; ++ ++static struct hisi_mux_clock hi3536c_mux_clks_crg[] __initdata = { ++ { HI3536C_SYSAXI_CLK, "sysaxi_mux", sysaxi_mux_p, ++ ARRAY_SIZE(sysaxi_mux_p), ++ CLK_SET_RATE_PARENT, 0x50, 2, 2, 0, sysaxi_mux_table, }, ++ { HI3536C_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), ++ CLK_SET_RATE_PARENT, 0x148, 2, 2, 0, fmc_mux_table, }, ++ { HI3536C_UART_MUX, "uart_mux", uart_mux_p, ++ ARRAY_SIZE(uart_mux_p), ++ CLK_SET_RATE_PARENT, 0x154, 19, 2, 0, uart_mux_table, }, ++}; ++ ++static struct hisi_fixed_factor_clock ++ hi3536c_fixed_factor_clks[] __initdata = { ++ { HI3536C_SYSAXI_CLK, "clk_sysaxi", "sysaxi_mux", 1, 4, ++ CLK_SET_RATE_PARENT}, ++}; ++ ++static struct hisi_gate_clock hi3536c_gate_clks[] __initdata = { ++#ifdef CONFIG_HIFMC ++ /* fmc */ ++ { HI3536C_FMC_CLK, "clk_fmc", "fmc_mux", ++ CLK_SET_RATE_PARENT, 0x148, 1, 0, }, ++#endif ++ /* uart */ ++ { HI3536C_UART0_CLK, "clk_uart0", "24m", ++ CLK_SET_RATE_PARENT, 0x154, 15, 0, }, ++ { HI3536C_UART1_CLK, "clk_uart1", "24m", ++ CLK_SET_RATE_PARENT, 0x154, 16, 0, }, ++ { HI3536C_UART2_CLK, "clk_uart2", "24m", ++ CLK_SET_RATE_PARENT, 0x154, 17, 0, }, ++ /* ethernet mac */ ++ { HI3536C_ETH_PHY_CLK, "clk_eth_phy", NULL, ++ CLK_SET_RATE_PARENT, 0x14c, 6, 0, }, ++ { HI3536C_ETH_PUB_CLK, "clk_eth_pub", "clk_eth_phy", ++ CLK_SET_RATE_PARENT, 0x14c, 7, 0, }, ++ { HI3536C_ETH_CLK, "clk_eth", "clk_eth_pub", ++ CLK_SET_RATE_PARENT, 0x14c, 1, 0, }, ++ { HI3536C_ETH_MACIF_CLK, "clk_eth_macif", "clk_eth_pub", ++ CLK_SET_RATE_PARENT, 0x14c, 3, 0, }, ++ /* ethernet mac1 */ ++ { HI3536C_ETH1_PHY_CLK, "clk_eth1_phy", NULL, ++ CLK_SET_RATE_PARENT, 0x14c, 14, 0, }, ++ { HI3536C_ETH1_CLK, "clk_eth1", "clk_eth1_phy", ++ CLK_SET_RATE_PARENT, 0x14c, 9, 0, }, ++ { HI3536C_ETH_MACIF1_CLK, "clk_eth_macif1", "clk_eth1_phy", ++ CLK_SET_RATE_PARENT, 0x14c, 11, 0, }, ++ /* spi */ ++ { HI3536C_SPI0_CLK, "clk_spi0", "clk_sysaxi", ++ CLK_SET_RATE_PARENT, 0x154, 13, 0, }, ++ /* dma */ ++ { HI3536C_DMAC_CLK, "clk_dmac", "50m", CLK_SET_RATE_PARENT, ++ 0x144, 1, 0, }, ++}; ++ ++static void __init hi3536c_clk_crg_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ unsigned int count = 0; ++ ++ clk_data = hisi_clk_init(np, HI3536C_CRG_NR_CLKS); ++ if (!clk_data) ++ return; ++ ++ hisi_clk_register_fixed_rate(hi3536c_fixed_rate_clks_crg, ++ ARRAY_SIZE(hi3536c_fixed_rate_clks_crg), ++ clk_data); ++ hisi_clk_register_mux(hi3536c_mux_clks_crg, ++ ARRAY_SIZE(hi3536c_mux_clks_crg), clk_data); ++ hisi_clk_register_fixed_factor(hi3536c_fixed_factor_clks, ++ ARRAY_SIZE(hi3536c_fixed_factor_clks), clk_data); ++ hisi_clk_register_gate(hi3536c_gate_clks, ++ ARRAY_SIZE(hi3536c_gate_clks), clk_data); ++ ++ if (!of_property_read_u32(np, "#reset-cells", &count) && (count == 2)) ++ hisi_reset_init(np, HI3536C_CRG_NR_RSTS); ++} ++ ++static const char *timer_mux_p[] __initconst = { "3m", "clk_sysapb" }; ++static u32 timer_mux_table[] = {0, 1}; ++ ++static struct hisi_mux_clock hi3536c_mux_clks_sys[] __initdata = { ++ { HI3536C_TIME0_0_CLK, "timer00", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 16, 1, 0, timer_mux_table, }, ++ ++ { HI3536C_TIME0_1_CLK, "timer01", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 18, 1, 0, timer_mux_table, }, ++ ++ { HI3536C_TIME1_2_CLK, "timer12", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 20, 1, 0, timer_mux_table, }, ++ ++ { HI3536C_TIME1_3_CLK, "timer13", timer_mux_p, ++ ARRAY_SIZE(timer_mux_p), CLK_SET_RATE_PARENT, ++ 0x0, 22, 1, 0, timer_mux_table, }, ++}; ++ ++static void __init hi3536c_clk_sys_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ unsigned int count = 0; ++ ++ clk_data = hisi_clk_init(np, HI3536C_SYS_NR_CLKS); ++ if (!clk_data) ++ return; ++ ++ hisi_clk_register_mux(hi3536c_mux_clks_sys, ++ ARRAY_SIZE(hi3536c_mux_clks_sys), clk_data); ++ ++ if (!of_property_read_u32(np, "#reset-cells", &count) && (count == 2)) ++ hisi_reset_init(np, HI3536C_SYS_NR_RSTS); ++} ++ ++CLK_OF_DECLARE(hi3536c_clk_crg, "hisilicon,hi3536c-clock", ++ hi3536c_clk_crg_init); ++CLK_OF_DECLARE(hi3536c_clk_sys, "hisilicon,sysctrl", hi3536c_clk_sys_init); ++ +diff --git a/drivers/clk/hisilicon/clk-hi3556.c b/drivers/clk/hisilicon/clk-hi3556.c +new file mode 100644 +index 0000000..56e160f +--- /dev/null ++++ b/drivers/clk/hisilicon/clk-hi3556.c +@@ -0,0 +1,384 @@ ++/* ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "clk.h" ++#include "reset.h" ++ ++/******************************************************************************/ ++struct hi3556_pll_clock { ++ u32 id; ++ const char *name; ++ const char *parent_name; ++ u32 ctrl_reg1; ++ u8 frac_shift; ++ u8 frac_width; ++ u8 postdiv1_shift; ++ u8 postdiv1_width; ++ u8 postdiv2_shift; ++ u8 postdiv2_width; ++ u32 ctrl_reg2; ++ u8 fbdiv_shift; ++ u8 fbdiv_width; ++ u8 refdiv_shift; ++ u8 refdiv_width; ++}; ++ ++struct hi3556_clk_pll { ++ struct clk_hw hw; ++ u32 id; ++ void __iomem *ctrl_reg1; ++ u8 frac_shift; ++ u8 frac_width; ++ u8 postdiv1_shift; ++ u8 postdiv1_width; ++ u8 postdiv2_shift; ++ u8 postdiv2_width; ++ void __iomem *ctrl_reg2; ++ u8 fbdiv_shift; ++ u8 fbdiv_width; ++ u8 refdiv_shift; ++ u8 refdiv_width; ++}; ++ ++static struct hisi_fixed_rate_clock hi3556_fixed_rate_clks[] __initdata = { ++ { HI3556_FIXED_2376M, "2376m", NULL, CLK_IS_ROOT, 2376000000UL, }, ++ { HI3556_FIXED_1188M, "1188m", NULL, CLK_IS_ROOT, 1188000000, }, ++ { HI3556_FIXED_594M, "594m", NULL, CLK_IS_ROOT, 594000000, }, ++ { HI3556_FIXED_297M, "297m", NULL, CLK_IS_ROOT, 297000000, }, ++ { HI3556_FIXED_148P5M, "148p5m", NULL, CLK_IS_ROOT, 148500000, }, ++ { HI3556_FIXED_74P25M, "74p25m", NULL, CLK_IS_ROOT, 74250000, }, ++ { HI3556_FIXED_792M, "792m", NULL, CLK_IS_ROOT, 792000000, }, ++ { HI3556_FIXED_475M, "475m", NULL, CLK_IS_ROOT, 475000000, }, ++ { HI3556_FIXED_340M, "340m", NULL, CLK_IS_ROOT, 340000000, }, ++ { HI3556_FIXED_72M, "72m", NULL, CLK_IS_ROOT, 72000000, }, ++ { HI3556_FIXED_400M, "400m", NULL, CLK_IS_ROOT, 400000000, }, ++ { HI3556_FIXED_200M, "200m", NULL, CLK_IS_ROOT, 200000000, }, ++ { HI3556_FIXED_54M, "54m", NULL, CLK_IS_ROOT, 54000000, }, ++ { HI3556_FIXED_27M, "27m", NULL, CLK_IS_ROOT, 1188000000, }, ++ { HI3556_FIXED_37P125M, "37p125m", NULL, CLK_IS_ROOT, 37125000, }, ++ { HI3556_FIXED_3000M, "3000m", NULL, CLK_IS_ROOT, 3000000000UL, }, ++ { HI3556_FIXED_1500M, "1500m", NULL, CLK_IS_ROOT, 1500000000, }, ++ { HI3556_FIXED_500M, "500m", NULL, CLK_IS_ROOT, 500000000, }, ++ { HI3556_FIXED_250M, "250m", NULL, CLK_IS_ROOT, 250000000, }, ++ { HI3556_FIXED_125M, "125m", NULL, CLK_IS_ROOT, 125000000, }, ++ { HI3556_FIXED_1000M, "1000m", NULL, CLK_IS_ROOT, 1000000000, }, ++ { HI3556_FIXED_600M, "600m", NULL, CLK_IS_ROOT, 600000000, }, ++ { HI3556_FIXED_750M, "750m", NULL, CLK_IS_ROOT, 750000000, }, ++ { HI3556_FIXED_150M, "150m", NULL, CLK_IS_ROOT, 150000000, }, ++ { HI3556_FIXED_75M, "75m", NULL, CLK_IS_ROOT, 75000000, }, ++ { HI3556_FIXED_300M, "300m", NULL, CLK_IS_ROOT, 300000000, }, ++ { HI3556_FIXED_60M, "60m", NULL, CLK_IS_ROOT, 60000000, }, ++ { HI3556_FIXED_214M, "214m", NULL, CLK_IS_ROOT, 214000000, }, ++ { HI3556_FIXED_107M, "107m", NULL, CLK_IS_ROOT, 107000000, }, ++ { HI3556_FIXED_100M, "100m", NULL, CLK_IS_ROOT, 100000000, }, ++ { HI3556_FIXED_50M, "50m", NULL, CLK_IS_ROOT, 50000000, }, ++ { HI3556_FIXED_25M, "25m", NULL, CLK_IS_ROOT, 25000000, }, ++ { HI3556_FIXED_24M, "24m", NULL, CLK_IS_ROOT, 24000000, }, ++ { HI3556_FIXED_3M, "3m", NULL, CLK_IS_ROOT, 3000000, }, ++ { HI3556_FIXED_198M, "198m", NULL, CLK_IS_ROOT, 198000000, }, ++ { HI3556_FIXED_396M, "396m", NULL, CLK_IS_ROOT, 396000000, }, ++}; ++ ++static const char *sysaxi_mux_p[] __initconst = {"24m", "198m", }; ++static u32 sysaxi_mux_table[] = {0, 1}; ++ ++static const char *fmc_mux_p[] __initconst = { ++ "24m", "75m", "125m", "150m", "198m", "250m", "300m", "396m", }; ++static u32 fmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6, 7}; ++ ++static const char *mmc_mux_p[] __initconst = { ++ "100m", "198m", "396m", "594m", "792m", "1188m", }; ++static u32 mmc_mux_table[] = {0, 1, 3, 4, 5, 7}; ++ ++static const char *a17_mux_p[] __initconst = { ++ "24m", "apll", "594m", "792m", }; ++static u32 a17_mux_table[] = {0, 1, 3, 4}; ++ ++static const char *i2c_mux_p[] __initconst = {"clk_sysapb", "50m"}; ++static u32 i2c_mux_table[] = {0, 1}; ++ ++static struct hisi_mux_clock hi3556_mux_clks[] __initdata = { ++ { HI3556_SYSAXI_MUX, "sysaxi_mux", sysaxi_mux_p, ++ ARRAY_SIZE(sysaxi_mux_p), ++ CLK_SET_RATE_PARENT, 0x34, 12, 2, 0, sysaxi_mux_table, }, ++ { HI3556_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc0, 2, 3, 0, fmc_mux_table, }, ++ { HI3556_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 10, 3, 0, mmc_mux_table, }, ++ { HI3556_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 2, 3, 0, mmc_mux_table, }, ++ { HI3556_MMC2_MUX, "mmc2_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 18, 3, 0, mmc_mux_table, }, ++ { HI3556_A17_MUX, "a17_mux", a17_mux_p, ARRAY_SIZE(a17_mux_p), ++ CLK_SET_RATE_PARENT, 0x34, 4, 3, 0, a17_mux_table, }, ++ { HI3556_I2C_MUX, "i2c_mux", i2c_mux_p, ARRAY_SIZE(i2c_mux_p), ++ CLK_SET_RATE_PARENT, 0xe4, 26, 1, 0, i2c_mux_table, }, ++ ++}; ++ ++static struct hisi_fixed_factor_clock ++ hi3556_fixed_factor_clks[] __initdata = { ++ { HI3556_SYSAPB_CLK, "clk_sysapb", "sysaxi_mux", 1, 4, ++ CLK_SET_RATE_PARENT}, ++ { HI3556_MMC0_FAC_CLK, "mmc0_fac", "mmc0_mux", 1, 8, ++ CLK_SET_RATE_PARENT}, ++ { HI3556_MMC1_FAC_CLK, "mmc1_fac", "mmc1_mux", 1, 8, ++ CLK_SET_RATE_PARENT}, ++ { HI3556_MMC2_FAC_CLK, "mmc2_fac", "mmc2_mux", 1, 8, ++ CLK_SET_RATE_PARENT}, ++}; ++ ++static struct hisi_gate_clock hi3556_gate_clks[] __initdata = { ++#ifdef CONFIG_HIFMC ++ /* fmc */ ++ { HI3556_FMC_CLK, "clk_fmc", "fmc_mux", ++ CLK_SET_RATE_PARENT, 0xc0, 1, 0, }, ++#endif ++ /* mmc */ ++ { HI3556_MMC0_CLK, "clk_mmc0", "mmc0_fac", ++ CLK_SET_RATE_PARENT, 0xc4, 9, 0, }, ++ { HI3556_MMC1_CLK, "clk_mmc1", "mmc1_fac", ++ CLK_SET_RATE_PARENT, 0xc4, 1, 0, }, ++ { HI3556_MMC2_CLK, "clk_mmc2", "mmc2_fac", ++ CLK_SET_RATE_PARENT, 0xc4, 17, 0, }, ++ ++ /* usb ctrl */ ++ { HI3556_USB2_CTRL_UTMI0_REQ, "usb2_cttl_utmi0_req", NULL, ++ CLK_SET_RATE_PARENT, 0xb4, 5, 1, }, ++ { HI3556_USB2_HRST_REQ, "usb2_hrst_req", NULL, ++ CLK_SET_RATE_PARENT, 0xb4, 0, 1, }, ++ { HI3556_USB3_CLK, "usb3_vcc_srst_req2", NULL, ++ CLK_SET_RATE_PARENT, 0xb8, 0, 1, }, ++ ++ /* uart */ ++ { HI3556_UART0_CLK, "clk_uart0", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 20, 0, }, ++ { HI3556_UART1_CLK, "clk_uart1", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 21, 0, }, ++ { HI3556_UART2_CLK, "clk_uart2", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 22, 0, }, ++ { HI3556_UART3_CLK, "clk_uart3", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 23, 0, }, ++ { HI3556_UART4_CLK, "clk_uart4", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 24, 0, }, ++ ++ /* ethernet mac */ ++ { HI3556_ETH_CLK, "clk_eth", NULL, ++ CLK_IS_ROOT, 0xcc, 1, 0, }, ++ { HI3556_ETH_MACIF_CLK, "clk_eth_macif", NULL, ++ CLK_IS_ROOT, 0xcc, 3, 0, }, ++ ++ /* spi */ ++ { HI3556_SPI0_CLK, "clk_spi0", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 16, 0, }, ++ { HI3556_SPI1_CLK, "clk_spi1", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 17, 0, }, ++ { HI3556_SPI2_CLK, "clk_spi2", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 18, 0, }, ++ { HI3556_SPI3_CLK, "clk_spi3", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 28, 0, }, ++}; ++ ++static struct hi3556_pll_clock hi3556_pll_clks[] __initdata = { ++ { HI3556_APLL_CLK, "apll", NULL, 0x0, 0, 24, 24, 3, 28, 3, ++ 0x4, 0, 12, 12, 6}, ++}; ++ ++ ++#define to_pll_clk(_hw) container_of(_hw, struct hi3556_clk_pll, hw) ++ ++static void hi3556_calc_pll(u32 *frac_val, ++ u32 *postdiv1_val, ++ u32 *postdiv2_val, ++ u32 *fbdiv_val, ++ u32 *refdiv_val, ++ unsigned long rate) ++{ ++ u64 rem; ++ *frac_val = 0; ++ rem = do_div(rate, 1000000); ++ *fbdiv_val = rate; ++ *refdiv_val = 24; ++ rem = rem * (1 << 24); ++ do_div(rem, 1000000); ++ *frac_val = rem; ++} ++ ++static int clk_pll_set_rate(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct hi3556_clk_pll *clk = to_pll_clk(hw); ++ u32 frac_val, postdiv1_val, postdiv2_val, fbdiv_val, refdiv_val; ++ u32 val; ++ ++ /*Fixme ignore postdives now because apll don't use them*/ ++ postdiv1_val = postdiv2_val = 0; ++ ++ hi3556_calc_pll(&frac_val, &postdiv1_val, &postdiv2_val, ++ &fbdiv_val, &refdiv_val, rate); ++ ++ val = readl_relaxed(clk->ctrl_reg1); ++ val &= ~(((1 << clk->frac_width) - 1) << clk->frac_shift); ++ val &= ~(((1 << clk->postdiv1_width) - 1) << clk->postdiv1_shift); ++ val &= ~(((1 << clk->postdiv2_width) - 1) << clk->postdiv2_shift); ++ ++ val |= frac_val << clk->frac_shift; ++ val |= postdiv1_val << clk->postdiv1_shift; ++ val |= postdiv2_val << clk->postdiv2_shift; ++ writel_relaxed(val, clk->ctrl_reg1); ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val &= ~(((1 << clk->fbdiv_width) - 1) << clk->fbdiv_shift); ++ val &= ~(((1 << clk->refdiv_width) - 1) << clk->refdiv_shift); ++ ++ val |= fbdiv_val << clk->fbdiv_shift; ++ val |= refdiv_val << clk->refdiv_shift; ++ writel_relaxed(val, clk->ctrl_reg2); ++ ++ return 0; ++} ++ ++static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct hi3556_clk_pll *clk = to_pll_clk(hw); ++ u64 frac_val, fbdiv_val, refdiv_val; ++ u32 val; ++ u64 tmp, rate; ++ ++ val = readl_relaxed(clk->ctrl_reg1); ++ val = val >> clk->frac_shift; ++ val &= ((1 << clk->frac_width) - 1); ++ frac_val = val; ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val = val >> clk->fbdiv_shift; ++ val &= ((1 << clk->fbdiv_width) - 1); ++ fbdiv_val = val; ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val = val >> clk->refdiv_shift; ++ val &= ((1 << clk->refdiv_width) - 1); ++ refdiv_val = val; ++ ++ /* rate = 24000000 * (fbdiv + frac / (1<<24) ) / refdiv */ ++ rate = 0; ++ tmp = 24000000 * fbdiv_val; ++ rate += tmp; ++ do_div(rate, refdiv_val); ++ ++ return rate; ++} ++ ++ ++static long clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *best_parent_rate, ++ struct clk **best_parent_p) ++{ ++ return rate; ++} ++ ++static struct clk_ops clk_pll_ops = { ++ .set_rate = clk_pll_set_rate, ++ .determine_rate = clk_pll_determine_rate, ++ .recalc_rate = clk_pll_recalc_rate, ++}; ++ ++void __init hi3556_clk_register_pll(struct hi3556_pll_clock *clks, ++ int nums, struct hisi_clock_data *data) ++{ ++ void __iomem *base = data->base; ++ int i; ++ ++ for (i = 0; i < nums; i++) { ++ struct hi3556_clk_pll *p_clk; ++ struct clk *clk; ++ struct clk_init_data init; ++ ++ p_clk = kzalloc(sizeof(*p_clk), GFP_KERNEL); ++ if (!p_clk) ++ return; ++ ++ init.name = clks[i].name; ++ init.flags = CLK_IS_BASIC; ++ init.parent_names = ++ (clks[i].parent_name ? &clks[i].parent_name : NULL); ++ init.num_parents = (clks[i].parent_name ? 1 : 0); ++ init.ops = &clk_pll_ops; ++ ++ p_clk->ctrl_reg1 = base + clks[i].ctrl_reg1; ++ p_clk->frac_shift = clks[i].frac_shift; ++ p_clk->frac_width = clks[i].frac_width; ++ p_clk->postdiv1_shift = clks[i].postdiv1_shift; ++ p_clk->postdiv1_width = clks[i].postdiv1_width; ++ p_clk->postdiv2_shift = clks[i].postdiv2_shift; ++ p_clk->postdiv2_width = clks[i].postdiv2_width; ++ ++ p_clk->ctrl_reg2 = base + clks[i].ctrl_reg2; ++ p_clk->fbdiv_shift = clks[i].fbdiv_shift; ++ p_clk->fbdiv_width = clks[i].fbdiv_width; ++ p_clk->refdiv_shift = clks[i].refdiv_shift; ++ p_clk->refdiv_width = clks[i].refdiv_width; ++ p_clk->hw.init = &init; ++ ++ clk = clk_register(NULL, &p_clk->hw); ++ if (IS_ERR(clk)) { ++ kfree(p_clk); ++ pr_err("%s: failed to register clock %s\n", ++ __func__, clks[i].name); ++ continue; ++ } ++ ++ data->clk_data.clks[clks[i].id] = clk; ++ } ++ ++ ++} ++ ++static void __init hi3556_clk_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ ++ clk_data = hisi_clk_init(np, HI3556_NR_CLKS); ++ if (!clk_data) ++ return; ++ if (IS_ENABLED(CONFIG_RESET_CONTROLLER)) ++ hisi_reset_init(np, HI3556_NR_RSTS); ++ ++ hisi_clk_register_fixed_rate(hi3556_fixed_rate_clks, ++ ARRAY_SIZE(hi3556_fixed_rate_clks), ++ clk_data); ++ hi3556_clk_register_pll(hi3556_pll_clks, ++ ARRAY_SIZE(hi3556_pll_clks), clk_data); ++ ++ hisi_clk_register_mux(hi3556_mux_clks, ++ ARRAY_SIZE(hi3556_mux_clks), ++ clk_data); ++ hisi_clk_register_fixed_factor(hi3556_fixed_factor_clks, ++ ARRAY_SIZE(hi3556_fixed_factor_clks), clk_data); ++ hisi_clk_register_gate(hi3556_gate_clks, ++ ARRAY_SIZE(hi3556_gate_clks), clk_data); ++} ++ ++CLK_OF_DECLARE(hi3556_clk, "hisilicon,hi3556-clock", hi3556_clk_init); +diff --git a/drivers/clk/hisilicon/clk-hi3559.c b/drivers/clk/hisilicon/clk-hi3559.c +new file mode 100644 +index 0000000..1ae6f6e +--- /dev/null ++++ b/drivers/clk/hisilicon/clk-hi3559.c +@@ -0,0 +1,384 @@ ++/* ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "clk.h" ++#include "reset.h" ++ ++/******************************************************************************/ ++struct hi3559_pll_clock { ++ u32 id; ++ const char *name; ++ const char *parent_name; ++ u32 ctrl_reg1; ++ u8 frac_shift; ++ u8 frac_width; ++ u8 postdiv1_shift; ++ u8 postdiv1_width; ++ u8 postdiv2_shift; ++ u8 postdiv2_width; ++ u32 ctrl_reg2; ++ u8 fbdiv_shift; ++ u8 fbdiv_width; ++ u8 refdiv_shift; ++ u8 refdiv_width; ++}; ++ ++struct hi3559_clk_pll { ++ struct clk_hw hw; ++ u32 id; ++ void __iomem *ctrl_reg1; ++ u8 frac_shift; ++ u8 frac_width; ++ u8 postdiv1_shift; ++ u8 postdiv1_width; ++ u8 postdiv2_shift; ++ u8 postdiv2_width; ++ void __iomem *ctrl_reg2; ++ u8 fbdiv_shift; ++ u8 fbdiv_width; ++ u8 refdiv_shift; ++ u8 refdiv_width; ++}; ++ ++static struct hisi_fixed_rate_clock hi3559_fixed_rate_clks[] __initdata = { ++ { HI3559_FIXED_2376M, "2376m", NULL, CLK_IS_ROOT, 2376000000UL, }, ++ { HI3559_FIXED_1188M, "1188m", NULL, CLK_IS_ROOT, 1188000000, }, ++ { HI3559_FIXED_594M, "594m", NULL, CLK_IS_ROOT, 594000000, }, ++ { HI3559_FIXED_297M, "297m", NULL, CLK_IS_ROOT, 297000000, }, ++ { HI3559_FIXED_148P5M, "148p5m", NULL, CLK_IS_ROOT, 148500000, }, ++ { HI3559_FIXED_74P25M, "74p25m", NULL, CLK_IS_ROOT, 74250000, }, ++ { HI3559_FIXED_792M, "792m", NULL, CLK_IS_ROOT, 792000000, }, ++ { HI3559_FIXED_475M, "475m", NULL, CLK_IS_ROOT, 475000000, }, ++ { HI3559_FIXED_340M, "340m", NULL, CLK_IS_ROOT, 340000000, }, ++ { HI3559_FIXED_72M, "72m", NULL, CLK_IS_ROOT, 72000000, }, ++ { HI3559_FIXED_400M, "400m", NULL, CLK_IS_ROOT, 400000000, }, ++ { HI3559_FIXED_200M, "200m", NULL, CLK_IS_ROOT, 200000000, }, ++ { HI3559_FIXED_54M, "54m", NULL, CLK_IS_ROOT, 54000000, }, ++ { HI3559_FIXED_27M, "27m", NULL, CLK_IS_ROOT, 1188000000, }, ++ { HI3559_FIXED_37P125M, "37p125m", NULL, CLK_IS_ROOT, 37125000, }, ++ { HI3559_FIXED_3000M, "3000m", NULL, CLK_IS_ROOT, 3000000000UL, }, ++ { HI3559_FIXED_1500M, "1500m", NULL, CLK_IS_ROOT, 1500000000, }, ++ { HI3559_FIXED_500M, "500m", NULL, CLK_IS_ROOT, 500000000, }, ++ { HI3559_FIXED_250M, "250m", NULL, CLK_IS_ROOT, 250000000, }, ++ { HI3559_FIXED_125M, "125m", NULL, CLK_IS_ROOT, 125000000, }, ++ { HI3559_FIXED_1000M, "1000m", NULL, CLK_IS_ROOT, 1000000000, }, ++ { HI3559_FIXED_600M, "600m", NULL, CLK_IS_ROOT, 600000000, }, ++ { HI3559_FIXED_750M, "750m", NULL, CLK_IS_ROOT, 750000000, }, ++ { HI3559_FIXED_150M, "150m", NULL, CLK_IS_ROOT, 150000000, }, ++ { HI3559_FIXED_75M, "75m", NULL, CLK_IS_ROOT, 75000000, }, ++ { HI3559_FIXED_300M, "300m", NULL, CLK_IS_ROOT, 300000000, }, ++ { HI3559_FIXED_60M, "60m", NULL, CLK_IS_ROOT, 60000000, }, ++ { HI3559_FIXED_214M, "214m", NULL, CLK_IS_ROOT, 214000000, }, ++ { HI3559_FIXED_107M, "107m", NULL, CLK_IS_ROOT, 107000000, }, ++ { HI3559_FIXED_100M, "100m", NULL, CLK_IS_ROOT, 100000000, }, ++ { HI3559_FIXED_50M, "50m", NULL, CLK_IS_ROOT, 50000000, }, ++ { HI3559_FIXED_25M, "25m", NULL, CLK_IS_ROOT, 25000000, }, ++ { HI3559_FIXED_24M, "24m", NULL, CLK_IS_ROOT, 24000000, }, ++ { HI3559_FIXED_3M, "3m", NULL, CLK_IS_ROOT, 3000000, }, ++ { HI3559_FIXED_198M, "198m", NULL, CLK_IS_ROOT, 198000000, }, ++ { HI3559_FIXED_396M, "396m", NULL, CLK_IS_ROOT, 396000000, }, ++}; ++ ++static const char *sysaxi_mux_p[] __initconst = {"24m", "198m", }; ++static u32 sysaxi_mux_table[] = {0, 1}; ++ ++static const char *fmc_mux_p[] __initconst = { ++ "24m", "75m", "125m", "150m", "198m", "250m", "300m", "396m", }; ++static u32 fmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6, 7}; ++ ++static const char *mmc_mux_p[] __initconst = { ++ "100m", "198m", "396m", "594m", "792m", "1188m", }; ++static u32 mmc_mux_table[] = {0, 1, 3, 4, 5, 7}; ++ ++static const char *a17_mux_p[] __initconst = { ++ "24m", "apll", "594m", "792m", }; ++static u32 a17_mux_table[] = {0, 1, 3, 4}; ++ ++static const char *i2c_mux_p[] __initconst = {"clk_sysapb", "50m"}; ++static u32 i2c_mux_table[] = {0, 1}; ++ ++static struct hisi_mux_clock hi3559_mux_clks[] __initdata = { ++ { HI3559_SYSAXI_MUX, "sysaxi_mux", sysaxi_mux_p, ++ ARRAY_SIZE(sysaxi_mux_p), ++ CLK_SET_RATE_PARENT, 0x34, 12, 2, 0, sysaxi_mux_table, }, ++ { HI3559_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc0, 2, 3, 0, fmc_mux_table, }, ++ { HI3559_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 10, 3, 0, mmc_mux_table, }, ++ { HI3559_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 2, 3, 0, mmc_mux_table, }, ++ { HI3559_MMC2_MUX, "mmc2_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), ++ CLK_SET_RATE_PARENT, 0xc4, 18, 3, 0, mmc_mux_table, }, ++ { HI3559_A17_MUX, "a17_mux", a17_mux_p, ARRAY_SIZE(a17_mux_p), ++ CLK_SET_RATE_PARENT, 0x34, 4, 3, 0, a17_mux_table, }, ++ { HI3559_I2C_MUX, "i2c_mux", i2c_mux_p, ARRAY_SIZE(i2c_mux_p), ++ CLK_SET_RATE_PARENT, 0xe4, 26, 1, 0, i2c_mux_table, }, ++ ++}; ++ ++static struct hisi_fixed_factor_clock ++ hi3559_fixed_factor_clks[] __initdata = { ++ { HI3559_SYSAPB_CLK, "clk_sysapb", "sysaxi_mux", 1, 4, ++ CLK_SET_RATE_PARENT}, ++ { HI3559_MMC0_FAC_CLK, "mmc0_fac", "mmc0_mux", 1, 8, ++ CLK_SET_RATE_PARENT}, ++ { HI3559_MMC1_FAC_CLK, "mmc1_fac", "mmc1_mux", 1, 8, ++ CLK_SET_RATE_PARENT}, ++ { HI3559_MMC2_FAC_CLK, "mmc2_fac", "mmc2_mux", 1, 8, ++ CLK_SET_RATE_PARENT}, ++}; ++ ++static struct hisi_gate_clock hi3559_gate_clks[] __initdata = { ++#ifdef CONFIG_HIFMC ++ /* fmc */ ++ { HI3559_FMC_CLK, "clk_fmc", "fmc_mux", ++ CLK_SET_RATE_PARENT, 0xc0, 1, 0, }, ++#endif ++ /* mmc */ ++ { HI3559_MMC0_CLK, "clk_mmc0", "mmc0_fac", ++ CLK_SET_RATE_PARENT, 0xc4, 9, 0, }, ++ { HI3559_MMC1_CLK, "clk_mmc1", "mmc1_fac", ++ CLK_SET_RATE_PARENT, 0xc4, 1, 0, }, ++ { HI3559_MMC2_CLK, "clk_mmc2", "mmc2_fac", ++ CLK_SET_RATE_PARENT, 0xc4, 17, 0, }, ++ ++ /* usb ctrl */ ++ { HI3559_USB2_CTRL_UTMI0_REQ, "usb2_cttl_utmi0_req", NULL, ++ CLK_SET_RATE_PARENT, 0xb4, 5, 1, }, ++ { HI3559_USB2_HRST_REQ, "usb2_hrst_req", NULL, ++ CLK_SET_RATE_PARENT, 0xb4, 0, 1, }, ++ { HI3559_USB3_CLK, "usb3_vcc_srst_req2", NULL, ++ CLK_SET_RATE_PARENT, 0xb8, 0, 1, }, ++ ++ /* uart */ ++ { HI3559_UART0_CLK, "clk_uart0", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 20, 0, }, ++ { HI3559_UART1_CLK, "clk_uart1", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 21, 0, }, ++ { HI3559_UART2_CLK, "clk_uart2", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 22, 0, }, ++ { HI3559_UART3_CLK, "clk_uart3", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 23, 0, }, ++ { HI3559_UART4_CLK, "clk_uart4", "24m", ++ CLK_SET_RATE_PARENT, 0xe4, 24, 0, }, ++ ++ /* ethernet mac */ ++ { HI3559_ETH_CLK, "clk_eth", NULL, ++ CLK_IS_ROOT, 0xcc, 1, 0, }, ++ { HI3559_ETH_MACIF_CLK, "clk_eth_macif", NULL, ++ CLK_IS_ROOT, 0xcc, 3, 0, }, ++ ++ /* spi */ ++ { HI3559_SPI0_CLK, "clk_spi0", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 16, 0, }, ++ { HI3559_SPI1_CLK, "clk_spi1", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 17, 0, }, ++ { HI3559_SPI2_CLK, "clk_spi2", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 18, 0, }, ++ { HI3559_SPI3_CLK, "clk_spi3", "clk_sysapb", ++ CLK_SET_RATE_PARENT, 0xe4, 28, 0, }, ++}; ++ ++static struct hi3559_pll_clock hi3559_pll_clks[] __initdata = { ++ { HI3559_APLL_CLK, "apll", NULL, 0x0, 0, 24, 24, 3, 28, 3, ++ 0x4, 0, 12, 12, 6}, ++}; ++ ++ ++#define to_pll_clk(_hw) container_of(_hw, struct hi3559_clk_pll, hw) ++ ++static void hi3559_calc_pll(u32 *frac_val, ++ u32 *postdiv1_val, ++ u32 *postdiv2_val, ++ u32 *fbdiv_val, ++ u32 *refdiv_val, ++ unsigned long rate) ++{ ++ u64 rem; ++ *frac_val = 0; ++ rem = do_div(rate, 1000000); ++ *fbdiv_val = rate; ++ *refdiv_val = 24; ++ rem = rem * (1 << 24); ++ do_div(rem, 1000000); ++ *frac_val = rem; ++} ++ ++static int clk_pll_set_rate(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct hi3559_clk_pll *clk = to_pll_clk(hw); ++ u32 frac_val, postdiv1_val, postdiv2_val, fbdiv_val, refdiv_val; ++ u32 val; ++ ++ /*Fixme ignore postdives now because apll don't use them*/ ++ postdiv1_val = postdiv2_val = 0; ++ ++ hi3559_calc_pll(&frac_val, &postdiv1_val, &postdiv2_val, ++ &fbdiv_val, &refdiv_val, rate); ++ ++ val = readl_relaxed(clk->ctrl_reg1); ++ val &= ~(((1 << clk->frac_width) - 1) << clk->frac_shift); ++ val &= ~(((1 << clk->postdiv1_width) - 1) << clk->postdiv1_shift); ++ val &= ~(((1 << clk->postdiv2_width) - 1) << clk->postdiv2_shift); ++ ++ val |= frac_val << clk->frac_shift; ++ val |= postdiv1_val << clk->postdiv1_shift; ++ val |= postdiv2_val << clk->postdiv2_shift; ++ writel_relaxed(val, clk->ctrl_reg1); ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val &= ~(((1 << clk->fbdiv_width) - 1) << clk->fbdiv_shift); ++ val &= ~(((1 << clk->refdiv_width) - 1) << clk->refdiv_shift); ++ ++ val |= fbdiv_val << clk->fbdiv_shift; ++ val |= refdiv_val << clk->refdiv_shift; ++ writel_relaxed(val, clk->ctrl_reg2); ++ ++ return 0; ++} ++ ++static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct hi3559_clk_pll *clk = to_pll_clk(hw); ++ u64 frac_val, fbdiv_val, refdiv_val; ++ u32 val; ++ u64 tmp, rate; ++ ++ val = readl_relaxed(clk->ctrl_reg1); ++ val = val >> clk->frac_shift; ++ val &= ((1 << clk->frac_width) - 1); ++ frac_val = val; ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val = val >> clk->fbdiv_shift; ++ val &= ((1 << clk->fbdiv_width) - 1); ++ fbdiv_val = val; ++ ++ val = readl_relaxed(clk->ctrl_reg2); ++ val = val >> clk->refdiv_shift; ++ val &= ((1 << clk->refdiv_width) - 1); ++ refdiv_val = val; ++ ++ /* rate = 24000000 * (fbdiv + frac / (1<<24) ) / refdiv */ ++ rate = 0; ++ tmp = 24000000 * fbdiv_val; ++ rate += tmp; ++ do_div(rate, refdiv_val); ++ ++ return rate; ++} ++ ++ ++static long clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *best_parent_rate, ++ struct clk **best_parent_p) ++{ ++ return rate; ++} ++ ++static struct clk_ops clk_pll_ops = { ++ .set_rate = clk_pll_set_rate, ++ .determine_rate = clk_pll_determine_rate, ++ .recalc_rate = clk_pll_recalc_rate, ++}; ++ ++void __init hi3559_clk_register_pll(struct hi3559_pll_clock *clks, ++ int nums, struct hisi_clock_data *data) ++{ ++ void __iomem *base = data->base; ++ int i; ++ ++ for (i = 0; i < nums; i++) { ++ struct hi3559_clk_pll *p_clk; ++ struct clk *clk; ++ struct clk_init_data init; ++ ++ p_clk = kzalloc(sizeof(*p_clk), GFP_KERNEL); ++ if (!p_clk) ++ return; ++ ++ init.name = clks[i].name; ++ init.flags = CLK_IS_BASIC; ++ init.parent_names = ++ (clks[i].parent_name ? &clks[i].parent_name : NULL); ++ init.num_parents = (clks[i].parent_name ? 1 : 0); ++ init.ops = &clk_pll_ops; ++ ++ p_clk->ctrl_reg1 = base + clks[i].ctrl_reg1; ++ p_clk->frac_shift = clks[i].frac_shift; ++ p_clk->frac_width = clks[i].frac_width; ++ p_clk->postdiv1_shift = clks[i].postdiv1_shift; ++ p_clk->postdiv1_width = clks[i].postdiv1_width; ++ p_clk->postdiv2_shift = clks[i].postdiv2_shift; ++ p_clk->postdiv2_width = clks[i].postdiv2_width; ++ ++ p_clk->ctrl_reg2 = base + clks[i].ctrl_reg2; ++ p_clk->fbdiv_shift = clks[i].fbdiv_shift; ++ p_clk->fbdiv_width = clks[i].fbdiv_width; ++ p_clk->refdiv_shift = clks[i].refdiv_shift; ++ p_clk->refdiv_width = clks[i].refdiv_width; ++ p_clk->hw.init = &init; ++ ++ clk = clk_register(NULL, &p_clk->hw); ++ if (IS_ERR(clk)) { ++ kfree(p_clk); ++ pr_err("%s: failed to register clock %s\n", ++ __func__, clks[i].name); ++ continue; ++ } ++ ++ data->clk_data.clks[clks[i].id] = clk; ++ } ++ ++ ++} ++ ++static void __init hi3559_clk_init(struct device_node *np) ++{ ++ struct hisi_clock_data *clk_data; ++ ++ clk_data = hisi_clk_init(np, HI3559_NR_CLKS); ++ if (!clk_data) ++ return; ++ if (IS_ENABLED(CONFIG_RESET_CONTROLLER)) ++ hisi_reset_init(np, HI3559_NR_RSTS); ++ ++ hisi_clk_register_fixed_rate(hi3559_fixed_rate_clks, ++ ARRAY_SIZE(hi3559_fixed_rate_clks), ++ clk_data); ++ hi3559_clk_register_pll(hi3559_pll_clks, ++ ARRAY_SIZE(hi3559_pll_clks), clk_data); ++ ++ hisi_clk_register_mux(hi3559_mux_clks, ++ ARRAY_SIZE(hi3559_mux_clks), ++ clk_data); ++ hisi_clk_register_fixed_factor(hi3559_fixed_factor_clks, ++ ARRAY_SIZE(hi3559_fixed_factor_clks), clk_data); ++ hisi_clk_register_gate(hi3559_gate_clks, ++ ARRAY_SIZE(hi3559_gate_clks), clk_data); ++} ++ ++CLK_OF_DECLARE(hi3559_clk, "hisilicon,hi3559-clock", hi3559_clk_init); +diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c +index a078e84..870a505 100644 +--- a/drivers/clk/hisilicon/clk.c ++++ b/drivers/clk/hisilicon/clk.c +@@ -232,3 +232,25 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks, + data->clk_data.clks[clks[i].id] = clk; + } + } ++ ++void __init hisi_clk_register_ops(struct hiclk_hw *clks, ++ int nums, struct hisi_clock_data *data) ++{ ++ struct clk *clk; ++ int i; ++ ++ for (i = 0; i < nums; i++) { ++ struct hiclk_hw *hihw = &clks[i]; ++ ++ clk = clk_register_ops_table(NULL, hihw, NULL); ++ if (IS_ERR(clk)) { ++ pr_err("%s: failed to register clock %s\n", ++ __func__, clks[i].name); ++ continue; ++ } ++ ++ clk_register_clkdev(clk, clks[i].name, NULL); ++ ++ data->clk_data.clks[clks[i].id] = clk; ++ } ++} +diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h +index 31083ff..46e7417 100644 +--- a/drivers/clk/hisilicon/clk.h ++++ b/drivers/clk/hisilicon/clk.h +@@ -30,6 +30,50 @@ + #include + #include + ++#define CLK(_id, _mask, _value, _rstbit, _rate, _ops) \ ++{.id = _id, \ ++ .name = #_id, \ ++ .offset = _id, \ ++ .mask = _mask, \ ++ .value = _value, \ ++ .rstbit = _rstbit, \ ++ .rate = _rate, \ ++ .ops = _ops,} ++ ++#define CLK_SHARED(_id, _off, _mask, _value, _rstbit, _rate, _ops) \ ++{.id = _id, \ ++ .name = #_id, \ ++ .offset = _off, \ ++ .mask = _mask, \ ++ .value = _value, \ ++ .rstbit = _rstbit, \ ++ .rate = _rate, \ ++ .ops = _ops,} ++ ++struct hiclk_hw { ++ int id; ++ const char *name; ++ u32 offset; ++ u32 mask; ++ u32 value; ++ u32 rstbit; ++ ++ unsigned long rate; ++ struct clk_ops *ops; ++ struct clk_hw hw; ++ ++#define CLKHW_RESET (0x01) ++#define CLKHW_ENABLE (0x02) ++ ++ u32 flags; ++}; ++ ++extern struct clk_ops clk_ops_hiusb2_host; ++extern struct clk_ops clk_ops_hiusb3; ++extern struct clk_ops clk_ops_himci; ++ ++#define to_hiclk_hw(_hw) container_of(_hw, struct hiclk_hw, hw) ++ + struct hisi_clock_data { + struct clk_onecell_data clk_data; + void __iomem *base; +@@ -96,6 +140,9 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *, + u8, spinlock_t *); + + struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int); ++struct clk *clk_register_ops_table(struct device *, ++ struct hiclk_hw *, ++ struct clk_ops *); + void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *, + int, struct hisi_clock_data *); + void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *, +@@ -108,4 +155,6 @@ void __init hisi_clk_register_gate(struct hisi_gate_clock *, + int, struct hisi_clock_data *); + void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *, + int, struct hisi_clock_data *); ++void __init hisi_clk_register_ops(struct hiclk_hw *, ++ int, struct hisi_clock_data *); + #endif /* __HISI_CLK_H */ +diff --git a/drivers/clk/hisilicon/clk_ops.c b/drivers/clk/hisilicon/clk_ops.c +new file mode 100644 +index 0000000..268c232 +--- /dev/null ++++ b/drivers/clk/hisilicon/clk_ops.c +@@ -0,0 +1,53 @@ ++/* ++ * Hisilicon clock separated gate driver ++ * ++ * Copyright (c) 2012-2013 Hisilicon Limited. ++ * Copyright (c) 2012-2013 Linaro Limited. ++ * ++ * Author: Haojian Zhuang ++ * Xin Li ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include "clk.h" ++ ++struct clk *clk_register_ops_table(struct device *dev, ++ struct hiclk_hw *hihw, ++ struct clk_ops *clkops) ++{ ++ struct clk *clk; ++ struct clk_init_data init; ++ ++ init.name = hihw->name; ++ init.flags = CLK_IS_ROOT | CLK_IS_BASIC; ++ init.parent_names = NULL; ++ init.num_parents = 0; ++ init.ops = hihw->ops; ++ ++ hihw->hw.init = &init; ++ ++ clk = clk_register(dev, &hihw->hw); ++ if (IS_ERR(clk)) { ++ pr_err("%s: register clock fail.\n", __func__); ++ return NULL; ++ } ++ ++ return clk; ++} +diff --git a/drivers/clk/hisilicon/reset.c b/drivers/clk/hisilicon/reset.c +new file mode 100644 +index 0000000..85b4ae7 +--- /dev/null ++++ b/drivers/clk/hisilicon/reset.c +@@ -0,0 +1,147 @@ ++/* ++ * Hisilicon Reset Controller driver ++ * ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define HISI_RESET_BIT_SHIFT 0 ++#define HISI_RESET_BIT_WIDTH 16 ++#define HISI_RESET_OFFSET_SHIFT 16 ++#define HISI_RESET_OFFSET_WIDTH 16 ++ ++struct hisi_reset_controller { ++ spinlock_t lock; ++ void __iomem *membase; ++ struct reset_controller_dev rcdev; ++}; ++ ++ ++#define to_hisi_reset_controller(rcdev) \ ++ container_of(rcdev, struct hisi_reset_controller, rcdev) ++ ++/*31 16 0 ++ |---reset_spec->args[0]---|---reset_spec->args[1]---| ++ |-------reg_offset--------|--------reg_bit----------|*/ ++static int hisi_reset_of_xlate(struct reset_controller_dev *rcdev, ++ const struct of_phandle_args *reset_spec) ++{ ++ unsigned int offset, bit, id; ++ __be32 *addr; ++ u64 size; ++ ++ if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells)) ++ return -EINVAL; ++ ++ addr = (__be32 *)of_get_address(rcdev->of_node, 0, &size, NULL); ++ if (!addr) ++ return -EINVAL; ++ ++ if (reset_spec->args[1] >= 32 ++ || reset_spec->args[0] + reset_spec->args[1] / 8 > size) ++ return -EINVAL; ++ ++ offset = reset_spec->args[0] & (BIT(HISI_RESET_OFFSET_WIDTH) - 1); ++ bit = (reset_spec->args[1] & (BIT(HISI_RESET_BIT_WIDTH) - 1)); ++ id = offset << HISI_RESET_OFFSET_SHIFT | bit; ++ ++ return id; ++} ++ ++static int hisi_reset_assert(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ struct hisi_reset_controller *rstc = to_hisi_reset_controller(rcdev); ++ unsigned int offset, bit; ++ unsigned long flags; ++ u32 reg; ++ ++ offset = id >> HISI_RESET_OFFSET_SHIFT; ++ offset &= (BIT(HISI_RESET_OFFSET_WIDTH) - 1); ++ bit = id & (BIT(HISI_RESET_BIT_WIDTH) - 1); ++ ++ spin_lock_irqsave(&rstc->lock, flags); ++ ++ reg = readl(rstc->membase + offset); ++ writel(reg | BIT(bit), rstc->membase + offset); ++ ++ spin_unlock_irqrestore(&rstc->lock, flags); ++ ++ return 0; ++} ++ ++static int hisi_reset_deassert(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ struct hisi_reset_controller *rstc = to_hisi_reset_controller(rcdev); ++ unsigned int offset, bit; ++ unsigned long flags; ++ u32 reg; ++ ++ offset = id >> HISI_RESET_OFFSET_SHIFT; ++ offset &= (BIT(HISI_RESET_OFFSET_WIDTH) - 1); ++ bit = id & (BIT(HISI_RESET_BIT_WIDTH) - 1); ++ ++ spin_lock_irqsave(&rstc->lock, flags); ++ ++ reg = readl(rstc->membase + offset); ++ writel(reg & ~BIT(bit), rstc->membase + offset); ++ ++ spin_unlock_irqrestore(&rstc->lock, flags); ++ ++ return 0; ++} ++ ++static struct reset_control_ops hisi_reset_ops = { ++ .assert = hisi_reset_assert, ++ .deassert = hisi_reset_deassert, ++}; ++ ++int __init hisi_reset_init(struct device_node *np, ++ int nr_rsts) ++{ ++ struct hisi_reset_controller *rstc; ++ ++ rstc = kzalloc(sizeof(*rstc), GFP_KERNEL); ++ if (!rstc) ++ return -ENOMEM; ++ ++ rstc->membase = of_iomap(np, 0); ++ if (!rstc->membase) ++ return -EINVAL; ++ ++ spin_lock_init(&rstc->lock); ++ ++ rstc->rcdev.owner = THIS_MODULE; ++ rstc->rcdev.nr_resets = nr_rsts; ++ rstc->rcdev.ops = &hisi_reset_ops; ++ rstc->rcdev.of_node = np; ++ rstc->rcdev.of_reset_n_cells = 2; ++ rstc->rcdev.of_xlate = hisi_reset_of_xlate; ++ ++ return reset_controller_register(&rstc->rcdev); ++} +diff --git a/drivers/clk/hisilicon/reset.h b/drivers/clk/hisilicon/reset.h +new file mode 100644 +index 0000000..74bea4e +--- /dev/null ++++ b/drivers/clk/hisilicon/reset.h +@@ -0,0 +1,25 @@ ++/* ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#ifndef __HISI_RESET_H ++#define __HISI_RESET_H ++ ++#include ++ ++int __init hisi_reset_init(struct device_node *np, int nr_rsts); ++ ++#endif /* __HISI_RESET_H */ +diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig +index 9042060..497b2f5 100644 +--- a/drivers/clocksource/Kconfig ++++ b/drivers/clocksource/Kconfig +@@ -110,6 +110,14 @@ config ARM_ARCH_TIMER_EVTSTREAM + This must be disabled for hardware validation purposes to detect any + hardware anomalies of missing events. + ++config ARM_ARCH_TIMER_VCT_ACCESS ++ bool "Support for ARM architected timer virtual counter access in userspace" ++ default n ++ depends on ARM_ARCH_TIMER ++ help ++ This option enables support for reading the ARM architected timer's ++ virtual counter in userspace. ++ + config ARM_GLOBAL_TIMER + bool + select CLKSRC_OF if OF +diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c +index 84b4c8b..fdf3959 100644 +--- a/drivers/clocksource/arm_arch_timer.c ++++ b/drivers/clocksource/arm_arch_timer.c +@@ -339,7 +339,10 @@ static void arch_counter_set_user_access(void) + | ARCH_TIMER_USR_PCT_ACCESS_EN); + + /* Enable user access to the virtual counter */ +- cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; ++ if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_VCT_ACCESS)) ++ cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; ++ else ++ cntkctl &= ~ARCH_TIMER_USR_VCT_ACCESS_EN; + + arch_timer_set_cntkctl(cntkctl); + } +diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig +index 3489f8f..548311f 100644 +--- a/drivers/cpufreq/Kconfig ++++ b/drivers/cpufreq/Kconfig +@@ -102,6 +102,16 @@ config CPU_FREQ_DEFAULT_GOV_CONSERVATIVE + Be aware that not all cpufreq drivers support the conservative + governor. If unsure have a look at the help section of the + driver. Fallback governor will be the performance governor. ++ ++config CPU_FREQ_DEFAULT_GOV_INTERACTIVE ++ bool "interactive" ++ select CPU_FREQ_GOV_INTERACTIVE ++ help ++ Use the CPUFreq governor 'interactive' as default. This allows ++ you to get a full dynamic cpu frequency capable system by simply ++ loading your cpufreq low-level hardware driver, using the ++ 'interactive' governor for latency-sensitive workloads. ++ + endchoice + + config CPU_FREQ_GOV_PERFORMANCE +@@ -159,6 +169,23 @@ config CPU_FREQ_GOV_ONDEMAND + + If in doubt, say N. + ++config CPU_FREQ_GOV_INTERACTIVE ++ tristate "'interactive' cpufreq policy governor" ++ help ++ 'interactive' - This driver adds a dynamic cpufreq policy governor ++ designed for latency-sensitive workloads. ++ ++ This governor attempts to reduce the latency of clock ++ increases so that the system is more responsive to ++ interactive workloads. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called cpufreq_interactive. ++ ++ For details, take a look at linux/Documentation/cpu-freq. ++ ++ If in doubt, say N. ++ + config CPU_FREQ_GOV_CONSERVATIVE + tristate "'conservative' cpufreq governor" + depends on CPU_FREQ +diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm +index 83a75dc..28c9b5f 100644 +--- a/drivers/cpufreq/Kconfig.arm ++++ b/drivers/cpufreq/Kconfig.arm +@@ -247,3 +247,4 @@ config ARM_TEGRA_CPUFREQ + default y + help + This adds the CPUFreq driver support for TEGRA SOCs. ++ +diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile +index 40c53dc..b89b1f7 100644 +--- a/drivers/cpufreq/Makefile ++++ b/drivers/cpufreq/Makefile +@@ -11,6 +11,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o + obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o + obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o + obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o ++obj-$(CONFIG_CPU_FREQ_GOV_INTERACTIVE) += cpufreq_interactive.o + obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o + + obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o +diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c +new file mode 100644 +index 0000000..e569e0b +--- /dev/null ++++ b/drivers/cpufreq/cpufreq_interactive.c +@@ -0,0 +1,1338 @@ ++/* ++ * drivers/cpufreq/cpufreq_interactive.c ++ * ++ * Copyright (C) 2010 Google, 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. ++ * ++ * Author: Mike Chan (mike@android.com) ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define CREATE_TRACE_POINTS ++#include ++ ++struct cpufreq_interactive_cpuinfo { ++ struct timer_list cpu_timer; ++ struct timer_list cpu_slack_timer; ++ spinlock_t load_lock; /* protects the next 4 fields */ ++ u64 time_in_idle; ++ u64 time_in_idle_timestamp; ++ u64 cputime_speedadj; ++ u64 cputime_speedadj_timestamp; ++ struct cpufreq_policy *policy; ++ struct cpufreq_frequency_table *freq_table; ++ spinlock_t target_freq_lock; /*protects target freq */ ++ unsigned int target_freq; ++ unsigned int floor_freq; ++ u64 pol_floor_val_time; /* policy floor_validate_time */ ++ u64 loc_floor_val_time; /* per-cpu floor_validate_time */ ++ u64 pol_hispeed_val_time; /* policy hispeed_validate_time */ ++ u64 loc_hispeed_val_time; /* per-cpu hispeed_validate_time */ ++ struct rw_semaphore enable_sem; ++ int governor_enabled; ++}; ++ ++static DEFINE_PER_CPU(struct cpufreq_interactive_cpuinfo, cpuinfo); ++ ++/* realtime thread handles frequency scaling */ ++static struct task_struct *speedchange_task; ++static cpumask_t speedchange_cpumask; ++static spinlock_t speedchange_cpumask_lock; ++static struct mutex gov_lock; ++ ++/* Target load. Lower values result in higher CPU speeds. */ ++#define DEFAULT_TARGET_LOAD 90 ++static unsigned int default_target_loads[] = {DEFAULT_TARGET_LOAD}; ++ ++#define DEFAULT_TIMER_RATE (20 * USEC_PER_MSEC) ++#define DEFAULT_ABOVE_HISPEED_DELAY DEFAULT_TIMER_RATE ++static unsigned int default_above_hispeed_delay[] = { ++ DEFAULT_ABOVE_HISPEED_DELAY }; ++ ++struct cpufreq_interactive_tunables { ++ int usage_count; ++ /* Hi speed to bump to from lo speed when load burst (default max) */ ++ unsigned int hispeed_freq; ++ /* Go to hi speed when CPU load at or above this value. */ ++#define DEFAULT_GO_HISPEED_LOAD 99 ++ unsigned long go_hispeed_load; ++ /* Target load. Lower values result in higher CPU speeds. */ ++ spinlock_t target_loads_lock; ++ unsigned int *target_loads; ++ int ntarget_loads; ++ /* ++ * The minimum amount of time to spend at a frequency before we can ramp ++ * down. ++ */ ++#define DEFAULT_MIN_SAMPLE_TIME (80 * USEC_PER_MSEC) ++ unsigned long min_sample_time; ++ /* ++ * The sample rate of the timer used to increase frequency ++ */ ++ unsigned long timer_rate; ++ /* ++ * Wait this long before raising speed above hispeed, by default a ++ * single timer interval. ++ */ ++ spinlock_t above_hispeed_delay_lock; ++ unsigned int *above_hispeed_delay; ++ int nabove_hispeed_delay; ++ /* Non-zero means indefinite speed boost active */ ++ int boost_val; ++ /* Duration of a boot pulse in usecs */ ++ int boostpulse_duration_val; ++ /* End time of boost pulse in ktime converted to usecs */ ++ u64 boostpulse_endtime; ++ bool boosted; ++ /* ++ * Max additional time to wait in idle, beyond timer_rate, at speeds ++ * above minimum before wakeup to reduce speed, or -1 if unnecessary. ++ */ ++#define DEFAULT_TIMER_SLACK (4 * DEFAULT_TIMER_RATE) ++ int timer_slack_val; ++ bool io_is_busy; ++}; ++ ++/* For cases where we have single governor instance for system */ ++static struct cpufreq_interactive_tunables *common_tunables; ++ ++static struct attribute_group *get_sysfs_attr(void); ++ ++static void cpufreq_interactive_timer_resched( ++ struct cpufreq_interactive_cpuinfo *pcpu) ++{ ++ struct cpufreq_interactive_tunables *tunables = ++ pcpu->policy->governor_data; ++ unsigned long expires; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&pcpu->load_lock, flags); ++ pcpu->time_in_idle = ++ get_cpu_idle_time(smp_processor_id(), ++ &pcpu->time_in_idle_timestamp, ++ tunables->io_is_busy); ++ pcpu->cputime_speedadj = 0; ++ pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp; ++ expires = jiffies + usecs_to_jiffies(tunables->timer_rate); ++ mod_timer_pinned(&pcpu->cpu_timer, expires); ++ ++ if (tunables->timer_slack_val >= 0 && ++ pcpu->target_freq > pcpu->policy->min) { ++ expires += usecs_to_jiffies(tunables->timer_slack_val); ++ mod_timer_pinned(&pcpu->cpu_slack_timer, expires); ++ } ++ ++ spin_unlock_irqrestore(&pcpu->load_lock, flags); ++} ++ ++/* The caller shall take enable_sem write semaphore to avoid any timer race. ++ * The cpu_timer and cpu_slack_timer must be deactivated when calling this ++ * function. ++ */ ++static void cpufreq_interactive_timer_start( ++ struct cpufreq_interactive_tunables *tunables, int cpu) ++{ ++ struct cpufreq_interactive_cpuinfo *pcpu = &per_cpu(cpuinfo, cpu); ++ unsigned long expires = jiffies + ++ usecs_to_jiffies(tunables->timer_rate); ++ unsigned long flags; ++ ++ pcpu->cpu_timer.expires = expires; ++ add_timer_on(&pcpu->cpu_timer, cpu); ++ if (tunables->timer_slack_val >= 0 && ++ pcpu->target_freq > pcpu->policy->min) { ++ expires += usecs_to_jiffies(tunables->timer_slack_val); ++ pcpu->cpu_slack_timer.expires = expires; ++ add_timer_on(&pcpu->cpu_slack_timer, cpu); ++ } ++ ++ spin_lock_irqsave(&pcpu->load_lock, flags); ++ pcpu->time_in_idle = ++ get_cpu_idle_time(cpu, &pcpu->time_in_idle_timestamp, ++ tunables->io_is_busy); ++ pcpu->cputime_speedadj = 0; ++ pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp; ++ spin_unlock_irqrestore(&pcpu->load_lock, flags); ++} ++ ++static unsigned int freq_to_above_hispeed_delay( ++ struct cpufreq_interactive_tunables *tunables, ++ unsigned int freq) ++{ ++ int i; ++ unsigned int ret; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tunables->above_hispeed_delay_lock, flags); ++ ++ for (i = 0; i < tunables->nabove_hispeed_delay - 1 && ++ freq >= tunables->above_hispeed_delay[i+1]; i += 2) ++ ; ++ ++ ret = tunables->above_hispeed_delay[i]; ++ spin_unlock_irqrestore(&tunables->above_hispeed_delay_lock, flags); ++ return ret; ++} ++ ++static unsigned int freq_to_targetload( ++ struct cpufreq_interactive_tunables *tunables, unsigned int freq) ++{ ++ int i; ++ unsigned int ret; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tunables->target_loads_lock, flags); ++ ++ for (i = 0; i < tunables->ntarget_loads - 1 && ++ freq >= tunables->target_loads[i+1]; i += 2) ++ ; ++ ++ ret = tunables->target_loads[i]; ++ spin_unlock_irqrestore(&tunables->target_loads_lock, flags); ++ return ret; ++} ++ ++/* ++ * If increasing frequencies never map to a lower target load then ++ * choose_freq() will find the minimum frequency that does not exceed its ++ * target load given the current load. ++ */ ++static unsigned int choose_freq(struct cpufreq_interactive_cpuinfo *pcpu, ++ unsigned int loadadjfreq) ++{ ++ unsigned int freq = pcpu->policy->cur; ++ unsigned int prevfreq, freqmin, freqmax; ++ unsigned int tl; ++ int index; ++ ++ freqmin = 0; ++ freqmax = UINT_MAX; ++ ++ do { ++ prevfreq = freq; ++ tl = freq_to_targetload(pcpu->policy->governor_data, freq); ++ ++ /* ++ * Find the lowest frequency where the computed load is less ++ * than or equal to the target load. ++ */ ++ ++ if (cpufreq_frequency_table_target( ++ pcpu->policy, pcpu->freq_table, loadadjfreq / tl, ++ CPUFREQ_RELATION_L, &index)) ++ break; ++ freq = pcpu->freq_table[index].frequency; ++ ++ if (freq > prevfreq) { ++ /* The previous frequency is too low. */ ++ freqmin = prevfreq; ++ ++ if (freq >= freqmax) { ++ /* ++ * Find the highest frequency that is less ++ * than freqmax. ++ */ ++ if (cpufreq_frequency_table_target( ++ pcpu->policy, pcpu->freq_table, ++ freqmax - 1, CPUFREQ_RELATION_H, ++ &index)) ++ break; ++ freq = pcpu->freq_table[index].frequency; ++ ++ if (freq == freqmin) { ++ /* ++ * The first frequency below freqmax ++ * has already been found to be too ++ * low. freqmax is the lowest speed ++ * we found that is fast enough. ++ */ ++ freq = freqmax; ++ break; ++ } ++ } ++ } else if (freq < prevfreq) { ++ /* The previous frequency is high enough. */ ++ freqmax = prevfreq; ++ ++ if (freq <= freqmin) { ++ /* ++ * Find the lowest frequency that is higher ++ * than freqmin. ++ */ ++ if (cpufreq_frequency_table_target( ++ pcpu->policy, pcpu->freq_table, ++ freqmin + 1, CPUFREQ_RELATION_L, ++ &index)) ++ break; ++ freq = pcpu->freq_table[index].frequency; ++ ++ /* ++ * If freqmax is the first frequency above ++ * freqmin then we have already found that ++ * this speed is fast enough. ++ */ ++ if (freq == freqmax) ++ break; ++ } ++ } ++ ++ /* If same frequency chosen as previous then done. */ ++ } while (freq != prevfreq); ++ ++ return freq; ++} ++ ++static u64 update_load(int cpu) ++{ ++ struct cpufreq_interactive_cpuinfo *pcpu = &per_cpu(cpuinfo, cpu); ++ struct cpufreq_interactive_tunables *tunables = ++ pcpu->policy->governor_data; ++ u64 now; ++ u64 now_idle; ++ unsigned int delta_idle; ++ unsigned int delta_time; ++ u64 active_time; ++ ++ now_idle = get_cpu_idle_time(cpu, &now, tunables->io_is_busy); ++ delta_idle = (unsigned int)(now_idle - pcpu->time_in_idle); ++ delta_time = (unsigned int)(now - pcpu->time_in_idle_timestamp); ++ ++ if (delta_time <= delta_idle) ++ active_time = 0; ++ else ++ active_time = delta_time - delta_idle; ++ ++ pcpu->cputime_speedadj += active_time * pcpu->policy->cur; ++ ++ pcpu->time_in_idle = now_idle; ++ pcpu->time_in_idle_timestamp = now; ++ return now; ++} ++ ++static void cpufreq_interactive_timer(unsigned long data) ++{ ++ u64 now; ++ unsigned int delta_time; ++ u64 cputime_speedadj; ++ int cpu_load; ++ struct cpufreq_interactive_cpuinfo *pcpu = ++ &per_cpu(cpuinfo, data); ++ struct cpufreq_interactive_tunables *tunables = ++ pcpu->policy->governor_data; ++ unsigned int new_freq; ++ unsigned int loadadjfreq; ++ unsigned int index; ++ unsigned long flags; ++ u64 max_fvtime; ++ ++ if (!down_read_trylock(&pcpu->enable_sem)) ++ return; ++ if (!pcpu->governor_enabled) ++ goto exit; ++ ++ spin_lock_irqsave(&pcpu->load_lock, flags); ++ now = update_load(data); ++ delta_time = (unsigned int)(now - pcpu->cputime_speedadj_timestamp); ++ cputime_speedadj = pcpu->cputime_speedadj; ++ spin_unlock_irqrestore(&pcpu->load_lock, flags); ++ ++ if (WARN_ON_ONCE(!delta_time)) ++ goto rearm; ++ ++ spin_lock_irqsave(&pcpu->target_freq_lock, flags); ++ do_div(cputime_speedadj, delta_time); ++ loadadjfreq = (unsigned int)cputime_speedadj * 100; ++ cpu_load = loadadjfreq / pcpu->policy->cur; ++ tunables->boosted = tunables->boost_val || now < tunables->boostpulse_endtime; ++ ++ if (cpu_load >= tunables->go_hispeed_load || tunables->boosted) { ++ if (pcpu->policy->cur < tunables->hispeed_freq) { ++ new_freq = tunables->hispeed_freq; ++ } else { ++ new_freq = choose_freq(pcpu, loadadjfreq); ++ ++ if (new_freq < tunables->hispeed_freq) ++ new_freq = tunables->hispeed_freq; ++ } ++ } else { ++ new_freq = choose_freq(pcpu, loadadjfreq); ++ if (new_freq > tunables->hispeed_freq && ++ pcpu->policy->cur < tunables->hispeed_freq) ++ new_freq = tunables->hispeed_freq; ++ } ++ ++ if (pcpu->policy->cur >= tunables->hispeed_freq && ++ new_freq > pcpu->policy->cur && ++ now - pcpu->pol_hispeed_val_time < ++ freq_to_above_hispeed_delay(tunables, pcpu->policy->cur)) { ++ trace_cpufreq_interactive_notyet( ++ data, cpu_load, pcpu->target_freq, ++ pcpu->policy->cur, new_freq); ++ spin_unlock_irqrestore(&pcpu->target_freq_lock, flags); ++ goto rearm; ++ } ++ ++ pcpu->loc_hispeed_val_time = now; ++ ++ if (cpufreq_frequency_table_target(pcpu->policy, pcpu->freq_table, ++ new_freq, CPUFREQ_RELATION_L, ++ &index)) { ++ spin_unlock_irqrestore(&pcpu->target_freq_lock, flags); ++ goto rearm; ++ } ++ ++ new_freq = pcpu->freq_table[index].frequency; ++ ++ /* ++ * Do not scale below floor_freq unless we have been at or above the ++ * floor frequency for the minimum sample time since last validated. ++ */ ++ max_fvtime = max(pcpu->pol_floor_val_time, pcpu->loc_floor_val_time); ++ if (new_freq < pcpu->floor_freq && ++ pcpu->target_freq >= pcpu->policy->cur) { ++ if (now - max_fvtime < tunables->min_sample_time) { ++ trace_cpufreq_interactive_notyet( ++ data, cpu_load, pcpu->target_freq, ++ pcpu->policy->cur, new_freq); ++ spin_unlock_irqrestore(&pcpu->target_freq_lock, flags); ++ goto rearm; ++ } ++ } ++ ++ /* ++ * Update the timestamp for checking whether speed has been held at ++ * or above the selected frequency for a minimum of min_sample_time, ++ * if not boosted to hispeed_freq. If boosted to hispeed_freq then we ++ * allow the speed to drop as soon as the boostpulse duration expires ++ * (or the indefinite boost is turned off). ++ */ ++ ++ if (!tunables->boosted || new_freq > tunables->hispeed_freq) { ++ pcpu->floor_freq = new_freq; ++ if (pcpu->target_freq >= pcpu->policy->cur || ++ new_freq >= pcpu->policy->cur) ++ pcpu->loc_floor_val_time = now; ++ } ++ ++ if (pcpu->target_freq == new_freq && ++ pcpu->target_freq <= pcpu->policy->cur) { ++ trace_cpufreq_interactive_already( ++ data, cpu_load, pcpu->target_freq, ++ pcpu->policy->cur, new_freq); ++ spin_unlock_irqrestore(&pcpu->target_freq_lock, flags); ++ goto rearm; ++ } ++ ++ trace_cpufreq_interactive_target(data, cpu_load, pcpu->target_freq, ++ pcpu->policy->cur, new_freq); ++ ++ pcpu->target_freq = new_freq; ++ spin_unlock_irqrestore(&pcpu->target_freq_lock, flags); ++ spin_lock_irqsave(&speedchange_cpumask_lock, flags); ++ cpumask_set_cpu(data, &speedchange_cpumask); ++ spin_unlock_irqrestore(&speedchange_cpumask_lock, flags); ++ wake_up_process(speedchange_task); ++ ++rearm: ++ if (!timer_pending(&pcpu->cpu_timer)) ++ cpufreq_interactive_timer_resched(pcpu); ++ ++exit: ++ up_read(&pcpu->enable_sem); ++ return; ++} ++ ++static void cpufreq_interactive_idle_end(void) ++{ ++ struct cpufreq_interactive_cpuinfo *pcpu = ++ &per_cpu(cpuinfo, smp_processor_id()); ++ ++ if (!down_read_trylock(&pcpu->enable_sem)) ++ return; ++ if (!pcpu->governor_enabled) { ++ up_read(&pcpu->enable_sem); ++ return; ++ } ++ ++ /* Arm the timer for 1-2 ticks later if not already. */ ++ if (!timer_pending(&pcpu->cpu_timer)) { ++ cpufreq_interactive_timer_resched(pcpu); ++ } else if (time_after_eq(jiffies, pcpu->cpu_timer.expires)) { ++ del_timer(&pcpu->cpu_timer); ++ del_timer(&pcpu->cpu_slack_timer); ++ cpufreq_interactive_timer(smp_processor_id()); ++ } ++ ++ up_read(&pcpu->enable_sem); ++} ++ ++static int cpufreq_interactive_speedchange_task(void *data) ++{ ++ unsigned int cpu; ++ cpumask_t tmp_mask; ++ unsigned long flags; ++ struct cpufreq_interactive_cpuinfo *pcpu; ++ ++ while (1) { ++ set_current_state(TASK_INTERRUPTIBLE); ++ spin_lock_irqsave(&speedchange_cpumask_lock, flags); ++ ++ if (cpumask_empty(&speedchange_cpumask)) { ++ spin_unlock_irqrestore(&speedchange_cpumask_lock, ++ flags); ++ schedule(); ++ ++ if (kthread_should_stop()) ++ break; ++ ++ spin_lock_irqsave(&speedchange_cpumask_lock, flags); ++ } ++ ++ set_current_state(TASK_RUNNING); ++ tmp_mask = speedchange_cpumask; ++ cpumask_clear(&speedchange_cpumask); ++ spin_unlock_irqrestore(&speedchange_cpumask_lock, flags); ++ ++ for_each_cpu(cpu, &tmp_mask) { ++ unsigned int j; ++ unsigned int max_freq = 0; ++ struct cpufreq_interactive_cpuinfo *pjcpu; ++ u64 hvt = ~0ULL, fvt = 0; ++ ++ pcpu = &per_cpu(cpuinfo, cpu); ++ if (!down_read_trylock(&pcpu->enable_sem)) ++ continue; ++ if (!pcpu->governor_enabled) { ++ up_read(&pcpu->enable_sem); ++ continue; ++ } ++ ++ for_each_cpu(j, pcpu->policy->cpus) { ++ pjcpu = &per_cpu(cpuinfo, j); ++ ++ fvt = max(fvt, pjcpu->loc_floor_val_time); ++ if (pjcpu->target_freq > max_freq) { ++ max_freq = pjcpu->target_freq; ++ hvt = pjcpu->loc_hispeed_val_time; ++ } else if (pjcpu->target_freq == max_freq) { ++ hvt = min(hvt, pjcpu->loc_hispeed_val_time); ++ } ++ } ++ for_each_cpu(j, pcpu->policy->cpus) { ++ pjcpu = &per_cpu(cpuinfo, j); ++ pjcpu->pol_floor_val_time = fvt; ++ } ++ ++ if (max_freq != pcpu->policy->cur) { ++ __cpufreq_driver_target(pcpu->policy, ++ max_freq, ++ CPUFREQ_RELATION_H); ++ for_each_cpu(j, pcpu->policy->cpus) { ++ pjcpu = &per_cpu(cpuinfo, j); ++ pjcpu->pol_hispeed_val_time = hvt; ++ } ++ } ++ trace_cpufreq_interactive_setspeed(cpu, ++ pcpu->target_freq, ++ pcpu->policy->cur); ++ ++ up_read(&pcpu->enable_sem); ++ } ++ } ++ ++ return 0; ++} ++ ++static void cpufreq_interactive_boost(struct cpufreq_interactive_tunables *tunables) ++{ ++ int i; ++ int anyboost = 0; ++ unsigned long flags[2]; ++ struct cpufreq_interactive_cpuinfo *pcpu; ++ ++ tunables->boosted = true; ++ ++ spin_lock_irqsave(&speedchange_cpumask_lock, flags[0]); ++ ++ for_each_online_cpu(i) { ++ pcpu = &per_cpu(cpuinfo, i); ++ if (tunables != pcpu->policy->governor_data) ++ continue; ++ ++ spin_lock_irqsave(&pcpu->target_freq_lock, flags[1]); ++ if (pcpu->target_freq < tunables->hispeed_freq) { ++ pcpu->target_freq = tunables->hispeed_freq; ++ cpumask_set_cpu(i, &speedchange_cpumask); ++ pcpu->pol_hispeed_val_time = ++ ktime_to_us(ktime_get()); ++ anyboost = 1; ++ } ++ spin_unlock_irqrestore(&pcpu->target_freq_lock, flags[1]); ++ } ++ ++ spin_unlock_irqrestore(&speedchange_cpumask_lock, flags[0]); ++ ++ if (anyboost) ++ wake_up_process(speedchange_task); ++} ++ ++static int cpufreq_interactive_notifier( ++ struct notifier_block *nb, unsigned long val, void *data) ++{ ++ struct cpufreq_freqs *freq = data; ++ struct cpufreq_interactive_cpuinfo *pcpu; ++ int cpu; ++ unsigned long flags; ++ ++ if (val == CPUFREQ_POSTCHANGE) { ++ pcpu = &per_cpu(cpuinfo, freq->cpu); ++ if (!down_read_trylock(&pcpu->enable_sem)) ++ return 0; ++ if (!pcpu->governor_enabled) { ++ up_read(&pcpu->enable_sem); ++ return 0; ++ } ++ ++ for_each_cpu(cpu, pcpu->policy->cpus) { ++ struct cpufreq_interactive_cpuinfo *pjcpu = ++ &per_cpu(cpuinfo, cpu); ++ if (cpu != freq->cpu) { ++ if (!down_read_trylock(&pjcpu->enable_sem)) ++ continue; ++ if (!pjcpu->governor_enabled) { ++ up_read(&pjcpu->enable_sem); ++ continue; ++ } ++ } ++ spin_lock_irqsave(&pjcpu->load_lock, flags); ++ update_load(cpu); ++ spin_unlock_irqrestore(&pjcpu->load_lock, flags); ++ if (cpu != freq->cpu) ++ up_read(&pjcpu->enable_sem); ++ } ++ ++ up_read(&pcpu->enable_sem); ++ } ++ return 0; ++} ++ ++static struct notifier_block cpufreq_notifier_block = { ++ .notifier_call = cpufreq_interactive_notifier, ++}; ++ ++static unsigned int *get_tokenized_data(const char *buf, int *num_tokens) ++{ ++ const char *cp; ++ int i; ++ int ntokens = 1; ++ unsigned int *tokenized_data; ++ int err = -EINVAL; ++ ++ cp = buf; ++ while ((cp = strpbrk(cp + 1, " :"))) ++ ntokens++; ++ ++ if (!(ntokens & 0x1)) ++ goto err; ++ ++ tokenized_data = kmalloc(ntokens * sizeof(unsigned int), GFP_KERNEL); ++ if (!tokenized_data) { ++ err = -ENOMEM; ++ goto err; ++ } ++ ++ cp = buf; ++ i = 0; ++ while (i < ntokens) { ++ if (sscanf(cp, "%u", &tokenized_data[i++]) != 1) ++ goto err_kfree; ++ ++ cp = strpbrk(cp, " :"); ++ if (!cp) ++ break; ++ cp++; ++ } ++ ++ if (i != ntokens) ++ goto err_kfree; ++ ++ *num_tokens = ntokens; ++ return tokenized_data; ++ ++err_kfree: ++ kfree(tokenized_data); ++err: ++ return ERR_PTR(err); ++} ++ ++static ssize_t show_target_loads( ++ struct cpufreq_interactive_tunables *tunables, ++ char *buf) ++{ ++ int i; ++ ssize_t ret = 0; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tunables->target_loads_lock, flags); ++ ++ for (i = 0; i < tunables->ntarget_loads; i++) ++ ret += sprintf(buf + ret, "%u%s", tunables->target_loads[i], ++ i & 0x1 ? ":" : " "); ++ ++ sprintf(buf + ret - 1, "\n"); ++ spin_unlock_irqrestore(&tunables->target_loads_lock, flags); ++ return ret; ++} ++ ++static ssize_t store_target_loads( ++ struct cpufreq_interactive_tunables *tunables, ++ const char *buf, size_t count) ++{ ++ int ntokens; ++ unsigned int *new_target_loads = NULL; ++ unsigned long flags; ++ ++ new_target_loads = get_tokenized_data(buf, &ntokens); ++ if (IS_ERR(new_target_loads)) ++ return PTR_RET(new_target_loads); ++ ++ spin_lock_irqsave(&tunables->target_loads_lock, flags); ++ if (tunables->target_loads != default_target_loads) ++ kfree(tunables->target_loads); ++ tunables->target_loads = new_target_loads; ++ tunables->ntarget_loads = ntokens; ++ spin_unlock_irqrestore(&tunables->target_loads_lock, flags); ++ return count; ++} ++ ++static ssize_t show_above_hispeed_delay( ++ struct cpufreq_interactive_tunables *tunables, char *buf) ++{ ++ int i; ++ ssize_t ret = 0; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tunables->above_hispeed_delay_lock, flags); ++ ++ for (i = 0; i < tunables->nabove_hispeed_delay; i++) ++ ret += sprintf(buf + ret, "%u%s", ++ tunables->above_hispeed_delay[i], ++ i & 0x1 ? ":" : " "); ++ ++ sprintf(buf + ret - 1, "\n"); ++ spin_unlock_irqrestore(&tunables->above_hispeed_delay_lock, flags); ++ return ret; ++} ++ ++static ssize_t store_above_hispeed_delay( ++ struct cpufreq_interactive_tunables *tunables, ++ const char *buf, size_t count) ++{ ++ int ntokens; ++ unsigned int *new_above_hispeed_delay = NULL; ++ unsigned long flags; ++ ++ new_above_hispeed_delay = get_tokenized_data(buf, &ntokens); ++ if (IS_ERR(new_above_hispeed_delay)) ++ return PTR_RET(new_above_hispeed_delay); ++ ++ spin_lock_irqsave(&tunables->above_hispeed_delay_lock, flags); ++ if (tunables->above_hispeed_delay != default_above_hispeed_delay) ++ kfree(tunables->above_hispeed_delay); ++ tunables->above_hispeed_delay = new_above_hispeed_delay; ++ tunables->nabove_hispeed_delay = ntokens; ++ spin_unlock_irqrestore(&tunables->above_hispeed_delay_lock, flags); ++ return count; ++ ++} ++ ++static ssize_t show_hispeed_freq(struct cpufreq_interactive_tunables *tunables, ++ char *buf) ++{ ++ return sprintf(buf, "%u\n", tunables->hispeed_freq); ++} ++ ++static ssize_t store_hispeed_freq(struct cpufreq_interactive_tunables *tunables, ++ const char *buf, size_t count) ++{ ++ int ret; ++ long unsigned int val; ++ ++ ret = kstrtoul(buf, 0, &val); ++ if (ret < 0) ++ return ret; ++ tunables->hispeed_freq = val; ++ return count; ++} ++ ++static ssize_t show_go_hispeed_load(struct cpufreq_interactive_tunables ++ *tunables, char *buf) ++{ ++ return sprintf(buf, "%lu\n", tunables->go_hispeed_load); ++} ++ ++static ssize_t store_go_hispeed_load(struct cpufreq_interactive_tunables ++ *tunables, const char *buf, size_t count) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = kstrtoul(buf, 0, &val); ++ if (ret < 0) ++ return ret; ++ tunables->go_hispeed_load = val; ++ return count; ++} ++ ++static ssize_t show_min_sample_time(struct cpufreq_interactive_tunables ++ *tunables, char *buf) ++{ ++ return sprintf(buf, "%lu\n", tunables->min_sample_time); ++} ++ ++static ssize_t store_min_sample_time(struct cpufreq_interactive_tunables ++ *tunables, const char *buf, size_t count) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = kstrtoul(buf, 0, &val); ++ if (ret < 0) ++ return ret; ++ tunables->min_sample_time = val; ++ return count; ++} ++ ++static ssize_t show_timer_rate(struct cpufreq_interactive_tunables *tunables, ++ char *buf) ++{ ++ return sprintf(buf, "%lu\n", tunables->timer_rate); ++} ++ ++static ssize_t store_timer_rate(struct cpufreq_interactive_tunables *tunables, ++ const char *buf, size_t count) ++{ ++ int ret; ++ unsigned long val, val_round; ++ ++ ret = kstrtoul(buf, 0, &val); ++ if (ret < 0) ++ return ret; ++ ++ val_round = jiffies_to_usecs(usecs_to_jiffies(val)); ++ if (val != val_round) ++ pr_warn("timer_rate not aligned to jiffy. Rounded up to %lu\n", ++ val_round); ++ ++ tunables->timer_rate = val_round; ++ return count; ++} ++ ++static ssize_t show_timer_slack(struct cpufreq_interactive_tunables *tunables, ++ char *buf) ++{ ++ return sprintf(buf, "%d\n", tunables->timer_slack_val); ++} ++ ++static ssize_t store_timer_slack(struct cpufreq_interactive_tunables *tunables, ++ const char *buf, size_t count) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = kstrtol(buf, 10, &val); ++ if (ret < 0) ++ return ret; ++ ++ tunables->timer_slack_val = val; ++ return count; ++} ++ ++static ssize_t show_boost(struct cpufreq_interactive_tunables *tunables, ++ char *buf) ++{ ++ return sprintf(buf, "%d\n", tunables->boost_val); ++} ++ ++static ssize_t store_boost(struct cpufreq_interactive_tunables *tunables, ++ const char *buf, size_t count) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = kstrtoul(buf, 0, &val); ++ if (ret < 0) ++ return ret; ++ ++ tunables->boost_val = val; ++ ++ if (tunables->boost_val) { ++ trace_cpufreq_interactive_boost("on"); ++ if (!tunables->boosted) ++ cpufreq_interactive_boost(tunables); ++ } else { ++ tunables->boostpulse_endtime = ktime_to_us(ktime_get()); ++ trace_cpufreq_interactive_unboost("off"); ++ } ++ ++ return count; ++} ++ ++static ssize_t store_boostpulse(struct cpufreq_interactive_tunables *tunables, ++ const char *buf, size_t count) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = kstrtoul(buf, 0, &val); ++ if (ret < 0) ++ return ret; ++ ++ tunables->boostpulse_endtime = ktime_to_us(ktime_get()) + ++ tunables->boostpulse_duration_val; ++ trace_cpufreq_interactive_boost("pulse"); ++ if (!tunables->boosted) ++ cpufreq_interactive_boost(tunables); ++ return count; ++} ++ ++static ssize_t show_boostpulse_duration(struct cpufreq_interactive_tunables ++ *tunables, char *buf) ++{ ++ return sprintf(buf, "%d\n", tunables->boostpulse_duration_val); ++} ++ ++static ssize_t store_boostpulse_duration(struct cpufreq_interactive_tunables ++ *tunables, const char *buf, size_t count) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = kstrtoul(buf, 0, &val); ++ if (ret < 0) ++ return ret; ++ ++ tunables->boostpulse_duration_val = val; ++ return count; ++} ++ ++static ssize_t show_io_is_busy(struct cpufreq_interactive_tunables *tunables, ++ char *buf) ++{ ++ return sprintf(buf, "%u\n", tunables->io_is_busy); ++} ++ ++static ssize_t store_io_is_busy(struct cpufreq_interactive_tunables *tunables, ++ const char *buf, size_t count) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = kstrtoul(buf, 0, &val); ++ if (ret < 0) ++ return ret; ++ tunables->io_is_busy = val; ++ return count; ++} ++ ++/* ++ * Create show/store routines ++ * - sys: One governor instance for complete SYSTEM ++ * - pol: One governor instance per struct cpufreq_policy ++ */ ++#define show_gov_pol_sys(file_name) \ ++static ssize_t show_##file_name##_gov_sys \ ++(struct kobject *kobj, struct attribute *attr, char *buf) \ ++{ \ ++ return show_##file_name(common_tunables, buf); \ ++} \ ++ \ ++static ssize_t show_##file_name##_gov_pol \ ++(struct cpufreq_policy *policy, char *buf) \ ++{ \ ++ return show_##file_name(policy->governor_data, buf); \ ++} ++ ++#define store_gov_pol_sys(file_name) \ ++static ssize_t store_##file_name##_gov_sys \ ++(struct kobject *kobj, struct attribute *attr, const char *buf, \ ++ size_t count) \ ++{ \ ++ return store_##file_name(common_tunables, buf, count); \ ++} \ ++ \ ++static ssize_t store_##file_name##_gov_pol \ ++(struct cpufreq_policy *policy, const char *buf, size_t count) \ ++{ \ ++ return store_##file_name(policy->governor_data, buf, count); \ ++} ++ ++#define show_store_gov_pol_sys(file_name) \ ++show_gov_pol_sys(file_name); \ ++store_gov_pol_sys(file_name) ++ ++show_store_gov_pol_sys(target_loads); ++show_store_gov_pol_sys(above_hispeed_delay); ++show_store_gov_pol_sys(hispeed_freq); ++show_store_gov_pol_sys(go_hispeed_load); ++show_store_gov_pol_sys(min_sample_time); ++show_store_gov_pol_sys(timer_rate); ++show_store_gov_pol_sys(timer_slack); ++show_store_gov_pol_sys(boost); ++store_gov_pol_sys(boostpulse); ++show_store_gov_pol_sys(boostpulse_duration); ++show_store_gov_pol_sys(io_is_busy); ++ ++#define gov_sys_attr_rw(_name) \ ++static struct global_attr _name##_gov_sys = \ ++__ATTR(_name, 0644, show_##_name##_gov_sys, store_##_name##_gov_sys) ++ ++#define gov_pol_attr_rw(_name) \ ++static struct freq_attr _name##_gov_pol = \ ++__ATTR(_name, 0644, show_##_name##_gov_pol, store_##_name##_gov_pol) ++ ++#define gov_sys_pol_attr_rw(_name) \ ++ gov_sys_attr_rw(_name); \ ++ gov_pol_attr_rw(_name) ++ ++gov_sys_pol_attr_rw(target_loads); ++gov_sys_pol_attr_rw(above_hispeed_delay); ++gov_sys_pol_attr_rw(hispeed_freq); ++gov_sys_pol_attr_rw(go_hispeed_load); ++gov_sys_pol_attr_rw(min_sample_time); ++gov_sys_pol_attr_rw(timer_rate); ++gov_sys_pol_attr_rw(timer_slack); ++gov_sys_pol_attr_rw(boost); ++gov_sys_pol_attr_rw(boostpulse_duration); ++gov_sys_pol_attr_rw(io_is_busy); ++ ++static struct global_attr boostpulse_gov_sys = ++ __ATTR(boostpulse, 0200, NULL, store_boostpulse_gov_sys); ++ ++static struct freq_attr boostpulse_gov_pol = ++ __ATTR(boostpulse, 0200, NULL, store_boostpulse_gov_pol); ++ ++/* One Governor instance for entire system */ ++static struct attribute *interactive_attributes_gov_sys[] = { ++ &target_loads_gov_sys.attr, ++ &above_hispeed_delay_gov_sys.attr, ++ &hispeed_freq_gov_sys.attr, ++ &go_hispeed_load_gov_sys.attr, ++ &min_sample_time_gov_sys.attr, ++ &timer_rate_gov_sys.attr, ++ &timer_slack_gov_sys.attr, ++ &boost_gov_sys.attr, ++ &boostpulse_gov_sys.attr, ++ &boostpulse_duration_gov_sys.attr, ++ &io_is_busy_gov_sys.attr, ++ NULL, ++}; ++ ++static struct attribute_group interactive_attr_group_gov_sys = { ++ .attrs = interactive_attributes_gov_sys, ++ .name = "interactive", ++}; ++ ++/* Per policy governor instance */ ++static struct attribute *interactive_attributes_gov_pol[] = { ++ &target_loads_gov_pol.attr, ++ &above_hispeed_delay_gov_pol.attr, ++ &hispeed_freq_gov_pol.attr, ++ &go_hispeed_load_gov_pol.attr, ++ &min_sample_time_gov_pol.attr, ++ &timer_rate_gov_pol.attr, ++ &timer_slack_gov_pol.attr, ++ &boost_gov_pol.attr, ++ &boostpulse_gov_pol.attr, ++ &boostpulse_duration_gov_pol.attr, ++ &io_is_busy_gov_pol.attr, ++ NULL, ++}; ++ ++static struct attribute_group interactive_attr_group_gov_pol = { ++ .attrs = interactive_attributes_gov_pol, ++ .name = "interactive", ++}; ++ ++static struct attribute_group *get_sysfs_attr(void) ++{ ++ if (have_governor_per_policy()) ++ return &interactive_attr_group_gov_pol; ++ else ++ return &interactive_attr_group_gov_sys; ++} ++ ++static int cpufreq_interactive_idle_notifier(struct notifier_block *nb, ++ unsigned long val, ++ void *data) ++{ ++ if (val == IDLE_END) ++ cpufreq_interactive_idle_end(); ++ ++ return 0; ++} ++ ++static struct notifier_block cpufreq_interactive_idle_nb = { ++ .notifier_call = cpufreq_interactive_idle_notifier, ++}; ++ ++static int cpufreq_governor_interactive(struct cpufreq_policy *policy, ++ unsigned int event) ++{ ++ int rc; ++ unsigned int j; ++ struct cpufreq_interactive_cpuinfo *pcpu; ++ struct cpufreq_frequency_table *freq_table; ++ struct cpufreq_interactive_tunables *tunables; ++ unsigned long flags; ++ ++ if (have_governor_per_policy()) ++ tunables = policy->governor_data; ++ else ++ tunables = common_tunables; ++ ++ WARN_ON(!tunables && (event != CPUFREQ_GOV_POLICY_INIT)); ++ ++ switch (event) { ++ case CPUFREQ_GOV_POLICY_INIT: ++ if (have_governor_per_policy()) { ++ WARN_ON(tunables); ++ } else if (tunables) { ++ tunables->usage_count++; ++ policy->governor_data = tunables; ++ return 0; ++ } ++ ++ tunables = kzalloc(sizeof(*tunables), GFP_KERNEL); ++ if (!tunables) { ++ pr_err("%s: POLICY_INIT: kzalloc failed\n", __func__); ++ return -ENOMEM; ++ } ++ ++ tunables->usage_count = 1; ++ tunables->above_hispeed_delay = default_above_hispeed_delay; ++ tunables->nabove_hispeed_delay = ++ ARRAY_SIZE(default_above_hispeed_delay); ++ tunables->go_hispeed_load = DEFAULT_GO_HISPEED_LOAD; ++ tunables->target_loads = default_target_loads; ++ tunables->ntarget_loads = ARRAY_SIZE(default_target_loads); ++ tunables->min_sample_time = DEFAULT_MIN_SAMPLE_TIME; ++ tunables->timer_rate = DEFAULT_TIMER_RATE; ++ tunables->boostpulse_duration_val = DEFAULT_MIN_SAMPLE_TIME; ++ tunables->timer_slack_val = DEFAULT_TIMER_SLACK; ++ ++ spin_lock_init(&tunables->target_loads_lock); ++ spin_lock_init(&tunables->above_hispeed_delay_lock); ++ ++ policy->governor_data = tunables; ++ if (!have_governor_per_policy()) { ++ common_tunables = tunables; ++ WARN_ON(cpufreq_get_global_kobject()); ++ } ++ ++ rc = sysfs_create_group(get_governor_parent_kobj(policy), ++ get_sysfs_attr()); ++ if (rc) { ++ kfree(tunables); ++ policy->governor_data = NULL; ++ if (!have_governor_per_policy()) { ++ common_tunables = NULL; ++ cpufreq_put_global_kobject(); ++ } ++ return rc; ++ } ++ ++ if (!policy->governor->initialized) { ++ idle_notifier_register(&cpufreq_interactive_idle_nb); ++ cpufreq_register_notifier(&cpufreq_notifier_block, ++ CPUFREQ_TRANSITION_NOTIFIER); ++ } ++ ++ break; ++ ++ case CPUFREQ_GOV_POLICY_EXIT: ++ if (!--tunables->usage_count) { ++ if (policy->governor->initialized == 1) { ++ cpufreq_unregister_notifier(&cpufreq_notifier_block, ++ CPUFREQ_TRANSITION_NOTIFIER); ++ idle_notifier_unregister(&cpufreq_interactive_idle_nb); ++ } ++ ++ sysfs_remove_group(get_governor_parent_kobj(policy), ++ get_sysfs_attr()); ++ ++ if (!have_governor_per_policy()) ++ cpufreq_put_global_kobject(); ++ ++ kfree(tunables); ++ common_tunables = NULL; ++ } ++ ++ policy->governor_data = NULL; ++ break; ++ ++ case CPUFREQ_GOV_START: ++ mutex_lock(&gov_lock); ++ ++ freq_table = cpufreq_frequency_get_table(policy->cpu); ++ if (!tunables->hispeed_freq) ++ tunables->hispeed_freq = policy->max; ++ ++ for_each_cpu(j, policy->cpus) { ++ pcpu = &per_cpu(cpuinfo, j); ++ pcpu->policy = policy; ++ pcpu->target_freq = policy->cur; ++ pcpu->freq_table = freq_table; ++ pcpu->floor_freq = pcpu->target_freq; ++ pcpu->pol_floor_val_time = ++ ktime_to_us(ktime_get()); ++ pcpu->loc_floor_val_time = pcpu->pol_floor_val_time; ++ pcpu->pol_hispeed_val_time = pcpu->pol_floor_val_time; ++ pcpu->loc_hispeed_val_time = pcpu->pol_floor_val_time; ++ down_write(&pcpu->enable_sem); ++ del_timer_sync(&pcpu->cpu_timer); ++ del_timer_sync(&pcpu->cpu_slack_timer); ++ cpufreq_interactive_timer_start(tunables, j); ++ pcpu->governor_enabled = 1; ++ up_write(&pcpu->enable_sem); ++ } ++ ++ mutex_unlock(&gov_lock); ++ break; ++ ++ case CPUFREQ_GOV_STOP: ++ mutex_lock(&gov_lock); ++ for_each_cpu(j, policy->cpus) { ++ pcpu = &per_cpu(cpuinfo, j); ++ down_write(&pcpu->enable_sem); ++ pcpu->governor_enabled = 0; ++ del_timer_sync(&pcpu->cpu_timer); ++ del_timer_sync(&pcpu->cpu_slack_timer); ++ up_write(&pcpu->enable_sem); ++ } ++ ++ mutex_unlock(&gov_lock); ++ break; ++ ++ case CPUFREQ_GOV_LIMITS: ++ if (policy->max < policy->cur) ++ __cpufreq_driver_target(policy, ++ policy->max, CPUFREQ_RELATION_H); ++ else if (policy->min > policy->cur) ++ __cpufreq_driver_target(policy, ++ policy->min, CPUFREQ_RELATION_L); ++ for_each_cpu(j, policy->cpus) { ++ pcpu = &per_cpu(cpuinfo, j); ++ ++ down_read(&pcpu->enable_sem); ++ if (pcpu->governor_enabled == 0) { ++ up_read(&pcpu->enable_sem); ++ continue; ++ } ++ ++ spin_lock_irqsave(&pcpu->target_freq_lock, flags); ++ if (policy->max < pcpu->target_freq) ++ pcpu->target_freq = policy->max; ++ else if (policy->min > pcpu->target_freq) ++ pcpu->target_freq = policy->min; ++ ++ spin_unlock_irqrestore(&pcpu->target_freq_lock, flags); ++ up_read(&pcpu->enable_sem); ++ } ++ break; ++ } ++ return 0; ++} ++ ++#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE ++static ++#endif ++struct cpufreq_governor cpufreq_gov_interactive = { ++ .name = "interactive", ++ .governor = cpufreq_governor_interactive, ++ .max_transition_latency = 10000000, ++ .owner = THIS_MODULE, ++}; ++ ++static void cpufreq_interactive_nop_timer(unsigned long data) ++{ ++} ++ ++static int __init cpufreq_interactive_init(void) ++{ ++ unsigned int i; ++ struct cpufreq_interactive_cpuinfo *pcpu; ++ struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; ++ ++ /* Initalize per-cpu timers */ ++ for_each_possible_cpu(i) { ++ pcpu = &per_cpu(cpuinfo, i); ++ init_timer_deferrable(&pcpu->cpu_timer); ++ pcpu->cpu_timer.function = cpufreq_interactive_timer; ++ pcpu->cpu_timer.data = i; ++ init_timer(&pcpu->cpu_slack_timer); ++ pcpu->cpu_slack_timer.function = cpufreq_interactive_nop_timer; ++ spin_lock_init(&pcpu->load_lock); ++ spin_lock_init(&pcpu->target_freq_lock); ++ init_rwsem(&pcpu->enable_sem); ++ } ++ ++ spin_lock_init(&speedchange_cpumask_lock); ++ mutex_init(&gov_lock); ++ speedchange_task = ++ kthread_create(cpufreq_interactive_speedchange_task, NULL, ++ "cfinteractive"); ++ if (IS_ERR(speedchange_task)) ++ return PTR_ERR(speedchange_task); ++ ++ sched_setscheduler_nocheck(speedchange_task, SCHED_FIFO, ¶m); ++ get_task_struct(speedchange_task); ++ ++ /* NB: wake up so the thread does not look hung to the freezer */ ++ wake_up_process(speedchange_task); ++ ++ return cpufreq_register_governor(&cpufreq_gov_interactive); ++} ++ ++#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE ++fs_initcall(cpufreq_interactive_init); ++#else ++module_init(cpufreq_interactive_init); ++#endif ++ ++static void __exit cpufreq_interactive_exit(void) ++{ ++ cpufreq_unregister_governor(&cpufreq_gov_interactive); ++ kthread_stop(speedchange_task); ++ put_task_struct(speedchange_task); ++} ++ ++module_exit(cpufreq_interactive_exit); ++ ++MODULE_AUTHOR("Mike Chan "); ++MODULE_DESCRIPTION("'cpufreq_interactive' - A cpufreq governor for " ++ "Latency sensitive workloads"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c +index 0cd9b4d..a2f1d41 100644 +--- a/drivers/cpufreq/cpufreq_stats.c ++++ b/drivers/cpufreq/cpufreq_stats.c +@@ -13,6 +13,9 @@ + #include + #include + #include ++#include ++#include ++#include + #include + + static spinlock_t cpufreq_stats_lock; +@@ -31,7 +34,28 @@ struct cpufreq_stats { + #endif + }; + ++struct all_cpufreq_stats { ++ unsigned int state_num; ++ cputime64_t *time_in_state; ++ unsigned int *freq_table; ++}; ++ ++struct cpufreq_power_stats { ++ unsigned int state_num; ++ unsigned int *curr; ++ unsigned int *freq_table; ++}; ++ ++struct all_freq_table { ++ unsigned int *freq_table; ++ unsigned int table_size; ++}; ++ ++static struct all_freq_table *all_freq_table; ++ ++static DEFINE_PER_CPU(struct all_cpufreq_stats *, all_cpufreq_stats); + static DEFINE_PER_CPU(struct cpufreq_stats *, cpufreq_stats_table); ++static DEFINE_PER_CPU(struct cpufreq_power_stats *, cpufreq_power_stats); + + struct cpufreq_stats_attribute { + struct attribute attr; +@@ -41,14 +65,24 @@ struct cpufreq_stats_attribute { + static int cpufreq_stats_update(unsigned int cpu) + { + struct cpufreq_stats *stat; ++ struct all_cpufreq_stats *all_stat; + unsigned long long cur_time; + + cur_time = get_jiffies_64(); + spin_lock(&cpufreq_stats_lock); + stat = per_cpu(cpufreq_stats_table, cpu); +- if (stat->time_in_state) ++ all_stat = per_cpu(all_cpufreq_stats, cpu); ++ if (!stat) { ++ spin_unlock(&cpufreq_stats_lock); ++ return 0; ++ } ++ if (stat->time_in_state) { + stat->time_in_state[stat->last_index] += + cur_time - stat->last_time; ++ if (all_stat) ++ all_stat->time_in_state[stat->last_index] += ++ cur_time - stat->last_time; ++ } + stat->last_time = cur_time; + spin_unlock(&cpufreq_stats_lock); + return 0; +@@ -79,6 +113,104 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf) + return len; + } + ++static int get_index_all_cpufreq_stat(struct all_cpufreq_stats *all_stat, ++ unsigned int freq) ++{ ++ int i; ++ if (!all_stat) ++ return -1; ++ for (i = 0; i < all_stat->state_num; i++) { ++ if (all_stat->freq_table[i] == freq) ++ return i; ++ } ++ return -1; ++} ++ ++void acct_update_power(struct task_struct *task, cputime_t cputime) { ++ struct cpufreq_power_stats *powerstats; ++ struct cpufreq_stats *stats; ++ unsigned int cpu_num, curr; ++ ++ if (!task) ++ return; ++ cpu_num = task_cpu(task); ++ powerstats = per_cpu(cpufreq_power_stats, cpu_num); ++ stats = per_cpu(cpufreq_stats_table, cpu_num); ++ if (!powerstats || !stats) ++ return; ++ ++ curr = powerstats->curr[stats->last_index]; ++ if (task->cpu_power != ULLONG_MAX) ++ task->cpu_power += curr * cputime_to_usecs(cputime); ++} ++EXPORT_SYMBOL_GPL(acct_update_power); ++ ++static ssize_t show_current_in_state(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ ssize_t len = 0; ++ unsigned int i, cpu; ++ struct cpufreq_power_stats *powerstats; ++ ++ spin_lock(&cpufreq_stats_lock); ++ for_each_possible_cpu(cpu) { ++ powerstats = per_cpu(cpufreq_power_stats, cpu); ++ if (!powerstats) ++ continue; ++ len += scnprintf(buf + len, PAGE_SIZE - len, "CPU%d:", cpu); ++ for (i = 0; i < powerstats->state_num; i++) ++ len += scnprintf(buf + len, PAGE_SIZE - len, ++ "%d=%d ", powerstats->freq_table[i], ++ powerstats->curr[i]); ++ len += scnprintf(buf + len, PAGE_SIZE - len, "\n"); ++ } ++ spin_unlock(&cpufreq_stats_lock); ++ return len; ++} ++ ++static ssize_t show_all_time_in_state(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ ssize_t len = 0; ++ unsigned int i, cpu, freq, index; ++ struct all_cpufreq_stats *all_stat; ++ struct cpufreq_policy *policy; ++ ++ len += scnprintf(buf + len, PAGE_SIZE - len, "freq\t\t"); ++ for_each_possible_cpu(cpu) { ++ len += scnprintf(buf + len, PAGE_SIZE - len, "cpu%d\t\t", cpu); ++ if (cpu_online(cpu)) ++ cpufreq_stats_update(cpu); ++ } ++ ++ if (!all_freq_table) ++ goto out; ++ for (i = 0; i < all_freq_table->table_size; i++) { ++ freq = all_freq_table->freq_table[i]; ++ len += scnprintf(buf + len, PAGE_SIZE - len, "\n%u\t\t", freq); ++ for_each_possible_cpu(cpu) { ++ policy = cpufreq_cpu_get(cpu); ++ if (policy == NULL) ++ continue; ++ all_stat = per_cpu(all_cpufreq_stats, policy->cpu); ++ index = get_index_all_cpufreq_stat(all_stat, freq); ++ if (index != -1) { ++ len += scnprintf(buf + len, PAGE_SIZE - len, ++ "%llu\t\t", (unsigned long long) ++ cputime64_to_clock_t(all_stat->time_in_state[index])); ++ } else { ++ len += scnprintf(buf + len, PAGE_SIZE - len, ++ "N/A\t\t"); ++ } ++ cpufreq_cpu_put(policy); ++ } ++ } ++ ++out: ++ len += scnprintf(buf + len, PAGE_SIZE - len, "\n"); ++ return len; ++} ++ + #ifdef CONFIG_CPU_FREQ_STAT_DETAILS + static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf) + { +@@ -142,6 +274,12 @@ static struct attribute_group stats_attr_group = { + .name = "stats" + }; + ++static struct kobj_attribute _attr_all_time_in_state = __ATTR(all_time_in_state, ++ 0444, show_all_time_in_state, NULL); ++ ++static struct kobj_attribute _attr_current_in_state = __ATTR(current_in_state, ++ 0444, show_current_in_state, NULL); ++ + static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq) + { + int index; +@@ -180,17 +318,54 @@ static void cpufreq_stats_free_table(unsigned int cpu) + cpufreq_cpu_put(policy); + } + +-static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) ++static void cpufreq_allstats_free(void) ++{ ++ int cpu; ++ struct all_cpufreq_stats *all_stat; ++ ++ sysfs_remove_file(cpufreq_global_kobject, ++ &_attr_all_time_in_state.attr); ++ ++ for_each_possible_cpu(cpu) { ++ all_stat = per_cpu(all_cpufreq_stats, cpu); ++ if (!all_stat) ++ continue; ++ kfree(all_stat->time_in_state); ++ kfree(all_stat); ++ per_cpu(all_cpufreq_stats, cpu) = NULL; ++ } ++ if (all_freq_table) { ++ kfree(all_freq_table->freq_table); ++ kfree(all_freq_table); ++ all_freq_table = NULL; ++ } ++} ++ ++static void cpufreq_powerstats_free(void) ++{ ++ int cpu; ++ struct cpufreq_power_stats *powerstats; ++ ++ sysfs_remove_file(cpufreq_global_kobject, &_attr_current_in_state.attr); ++ ++ for_each_possible_cpu(cpu) { ++ powerstats = per_cpu(cpufreq_power_stats, cpu); ++ if (!powerstats) ++ continue; ++ kfree(powerstats->curr); ++ kfree(powerstats); ++ per_cpu(cpufreq_power_stats, cpu) = NULL; ++ } ++} ++ ++static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, ++ struct cpufreq_frequency_table *table, int count) + { +- unsigned int i, count = 0, ret = 0; ++ unsigned int i, ret = 0; + struct cpufreq_stats *stat; + unsigned int alloc_size; + unsigned int cpu = policy->cpu; +- struct cpufreq_frequency_table *pos, *table; +- +- table = cpufreq_frequency_get_table(cpu); +- if (unlikely(!table)) +- return 0; ++ struct cpufreq_frequency_table *pos; + + if (per_cpu(cpufreq_stats_table, cpu)) + return -EBUSY; +@@ -205,9 +380,6 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) + stat->cpu = cpu; + per_cpu(cpufreq_stats_table, cpu) = stat; + +- cpufreq_for_each_valid_entry(pos, table) +- count++; +- + alloc_size = count * sizeof(int) + count * sizeof(u64); + + #ifdef CONFIG_CPU_FREQ_STAT_DETAILS +@@ -242,10 +414,159 @@ error_out: + return ret; + } + ++static void cpufreq_stats_update_policy_cpu(struct cpufreq_policy *policy) ++{ ++ struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, ++ policy->last_cpu); ++ ++ pr_debug("Updating stats_table for new_cpu %u from last_cpu %u\n", ++ policy->cpu, policy->last_cpu); ++ per_cpu(cpufreq_stats_table, policy->cpu) = per_cpu(cpufreq_stats_table, ++ policy->last_cpu); ++ per_cpu(cpufreq_stats_table, policy->last_cpu) = NULL; ++ stat->cpu = policy->cpu; ++} ++ ++static void cpufreq_powerstats_create(unsigned int cpu, ++ struct cpufreq_frequency_table *table, int count) { ++ unsigned int alloc_size, i = 0, ret = 0; ++ struct cpufreq_power_stats *powerstats; ++ struct cpufreq_frequency_table *pos; ++ struct device_node *cpu_node; ++ char device_path[16]; ++ ++ powerstats = kzalloc(sizeof(struct cpufreq_power_stats), ++ GFP_KERNEL); ++ if (!powerstats) ++ return; ++ ++ /* Allocate memory for freq table per cpu as well as clockticks per ++ * freq*/ ++ alloc_size = count * sizeof(unsigned int) + ++ count * sizeof(unsigned int); ++ powerstats->curr = kzalloc(alloc_size, GFP_KERNEL); ++ if (!powerstats->curr) { ++ kfree(powerstats); ++ return; ++ } ++ powerstats->freq_table = powerstats->curr + count; ++ ++ spin_lock(&cpufreq_stats_lock); ++ i = 0; ++ cpufreq_for_each_valid_entry(pos, table) ++ powerstats->freq_table[i++] = pos->frequency; ++ powerstats->state_num = i; ++ ++ snprintf(device_path, sizeof(device_path), "/cpus/cpu@%d", cpu); ++ cpu_node = of_find_node_by_path(device_path); ++ if (cpu_node) { ++ ret = of_property_read_u32_array(cpu_node, "current", ++ powerstats->curr, count); ++ if (ret) { ++ kfree(powerstats->curr); ++ kfree(powerstats); ++ powerstats = NULL; ++ } ++ } ++ per_cpu(cpufreq_power_stats, cpu) = powerstats; ++ spin_unlock(&cpufreq_stats_lock); ++} ++ ++static int compare_for_sort(const void *lhs_ptr, const void *rhs_ptr) ++{ ++ unsigned int lhs = *(const unsigned int *)(lhs_ptr); ++ unsigned int rhs = *(const unsigned int *)(rhs_ptr); ++ if (lhs < rhs) ++ return -1; ++ if (lhs > rhs) ++ return 1; ++ return 0; ++} ++ ++static bool check_all_freq_table(unsigned int freq) ++{ ++ int i; ++ for (i = 0; i < all_freq_table->table_size; i++) { ++ if (freq == all_freq_table->freq_table[i]) ++ return true; ++ } ++ return false; ++} ++ ++static void create_all_freq_table(void) ++{ ++ all_freq_table = kzalloc(sizeof(struct all_freq_table), ++ GFP_KERNEL); ++ if (!all_freq_table) ++ pr_warn("could not allocate memory for all_freq_table\n"); ++ return; ++} ++ ++static void add_all_freq_table(unsigned int freq) ++{ ++ unsigned int size; ++ size = sizeof(unsigned int) * (all_freq_table->table_size + 1); ++ all_freq_table->freq_table = krealloc(all_freq_table->freq_table, ++ size, GFP_ATOMIC); ++ if (IS_ERR(all_freq_table->freq_table)) { ++ pr_warn("Could not reallocate memory for freq_table\n"); ++ all_freq_table->freq_table = NULL; ++ return; ++ } ++ all_freq_table->freq_table[all_freq_table->table_size++] = freq; ++} ++ ++static void cpufreq_allstats_create(unsigned int cpu, ++ struct cpufreq_frequency_table *table, int count) ++{ ++ int i , j = 0; ++ unsigned int alloc_size; ++ struct all_cpufreq_stats *all_stat; ++ bool sort_needed = false; ++ ++ all_stat = kzalloc(sizeof(struct all_cpufreq_stats), ++ GFP_KERNEL); ++ if (!all_stat) { ++ pr_warn("Cannot allocate memory for cpufreq stats\n"); ++ return; ++ } ++ ++ /*Allocate memory for freq table per cpu as well as clockticks per freq*/ ++ alloc_size = count * sizeof(int) + count * sizeof(cputime64_t); ++ all_stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL); ++ if (!all_stat->time_in_state) { ++ pr_warn("Cannot allocate memory for cpufreq time_in_state\n"); ++ kfree(all_stat); ++ all_stat = NULL; ++ return; ++ } ++ all_stat->freq_table = (unsigned int *) ++ (all_stat->time_in_state + count); ++ ++ spin_lock(&cpufreq_stats_lock); ++ for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { ++ unsigned int freq = table[i].frequency; ++ if (freq == CPUFREQ_ENTRY_INVALID) ++ continue; ++ all_stat->freq_table[j++] = freq; ++ if (all_freq_table && !check_all_freq_table(freq)) { ++ add_all_freq_table(freq); ++ sort_needed = true; ++ } ++ } ++ if (sort_needed) ++ sort(all_freq_table->freq_table, all_freq_table->table_size, ++ sizeof(unsigned int), &compare_for_sort, NULL); ++ all_stat->state_num = j; ++ per_cpu(all_cpufreq_stats, cpu) = all_stat; ++ spin_unlock(&cpufreq_stats_lock); ++} ++ + static void cpufreq_stats_create_table(unsigned int cpu) + { + struct cpufreq_policy *policy; +- ++ struct cpufreq_frequency_table *table, *pos; ++ int count = 0; + /* + * "likely(!policy)" because normally cpufreq_stats will be registered + * before cpufreq driver +@@ -254,37 +575,52 @@ static void cpufreq_stats_create_table(unsigned int cpu) + if (likely(!policy)) + return; + +- __cpufreq_stats_create_table(policy); ++ table = cpufreq_frequency_get_table(policy->cpu); ++ if (likely(table)) { ++ cpufreq_for_each_valid_entry(pos, table) ++ count++; + +- cpufreq_cpu_put(policy); +-} ++ if (!per_cpu(all_cpufreq_stats, cpu)) ++ cpufreq_allstats_create(cpu, table, count); + +-static void cpufreq_stats_update_policy_cpu(struct cpufreq_policy *policy) +-{ +- struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, +- policy->last_cpu); ++ if (!per_cpu(cpufreq_power_stats, cpu)) ++ cpufreq_powerstats_create(cpu, table, count); + +- pr_debug("Updating stats_table for new_cpu %u from last_cpu %u\n", +- policy->cpu, policy->last_cpu); +- per_cpu(cpufreq_stats_table, policy->cpu) = per_cpu(cpufreq_stats_table, +- policy->last_cpu); +- per_cpu(cpufreq_stats_table, policy->last_cpu) = NULL; +- stat->cpu = policy->cpu; ++ __cpufreq_stats_create_table(policy, table, count); ++ } ++ cpufreq_cpu_put(policy); + } + + static int cpufreq_stat_notifier_policy(struct notifier_block *nb, + unsigned long val, void *data) + { +- int ret = 0; ++ int ret = 0, count = 0; + struct cpufreq_policy *policy = data; ++ struct cpufreq_frequency_table *table, *pos; ++ unsigned int cpu_num, cpu = policy->cpu; + + if (val == CPUFREQ_UPDATE_POLICY_CPU) { + cpufreq_stats_update_policy_cpu(policy); + return 0; + } + ++ table = cpufreq_frequency_get_table(cpu); ++ if (!table) ++ return 0; ++ ++ cpufreq_for_each_valid_entry(pos, table) ++ count++; ++ ++ if (!per_cpu(all_cpufreq_stats, cpu)) ++ cpufreq_allstats_create(cpu, table, count); ++ ++ for_each_possible_cpu(cpu_num) { ++ if (!per_cpu(cpufreq_power_stats, cpu_num)) ++ cpufreq_powerstats_create(cpu_num, table, count); ++ } ++ + if (val == CPUFREQ_CREATE_POLICY) +- ret = __cpufreq_stats_create_table(policy); ++ ret = __cpufreq_stats_create_table(policy, table, count); + else if (val == CPUFREQ_REMOVE_POLICY) + __cpufreq_stats_free_table(policy); + +@@ -359,6 +695,18 @@ static int __init cpufreq_stats_init(void) + return ret; + } + ++ create_all_freq_table(); ++ WARN_ON(cpufreq_get_global_kobject()); ++ ret = sysfs_create_file(cpufreq_global_kobject, ++ &_attr_all_time_in_state.attr); ++ if (ret) ++ pr_warn("Cannot create sysfs file for cpufreq stats\n"); ++ ++ ret = sysfs_create_file(cpufreq_global_kobject, ++ &_attr_current_in_state.attr); ++ if (ret) ++ pr_warn("Cannot create sysfs file for cpufreq current stats\n"); ++ + return 0; + } + static void __exit cpufreq_stats_exit(void) +@@ -371,6 +719,9 @@ static void __exit cpufreq_stats_exit(void) + CPUFREQ_TRANSITION_NOTIFIER); + for_each_online_cpu(cpu) + cpufreq_stats_free_table(cpu); ++ cpufreq_allstats_free(); ++ cpufreq_powerstats_free(); ++ cpufreq_put_global_kobject(); + } + + MODULE_AUTHOR("Zou Nan hai "); +diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm +index 8c16ab2..289bf08 100644 +--- a/drivers/cpuidle/Kconfig.arm ++++ b/drivers/cpuidle/Kconfig.arm +@@ -63,3 +63,33 @@ config ARM_MVEBU_V7_CPUIDLE + depends on ARCH_MVEBU + help + Select this to enable cpuidle on Armada 370, 38x and XP processors. ++ ++config ARM_HI3519_CPUIDLE ++ bool "CPU Idle Driver for Hi3519 processors" ++ depends on ARCH_HI3519 ++ help ++ Select this to enable cpuidle on Hi3519 processors. ++ ++config ARM_HI3519V101_CPUIDLE ++ bool "CPU Idle Driver for Hi3519v101 processors" ++ depends on ARCH_HI3519V101 ++ help ++ Select this to enable cpuidle on Hi3519v101 processors. ++ ++config ARM_HI3516AV200_CPUIDLE ++ bool "CPU Idle Driver for Hi3516av200 processors" ++ depends on ARCH_HI3516AV200 ++ help ++ Select this to enable cpuidle on Hi3516av200 processors. ++ ++config ARM_HI3559_CPUIDLE ++ bool "CPU Idle Driver for Hi3559 processors" ++ depends on ARCH_HI3559 ++ help ++ Select this to enable cpuidle on Hi3559 processors. ++ ++config ARM_HI3556_CPUIDLE ++ bool "CPU Idle Driver for Hi3556 processors" ++ depends on ARCH_HI3556 ++ help ++ Select this to enable cpuidle on Hi3556 processors. +diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile +index 4d177b9..00cda8b 100644 +--- a/drivers/cpuidle/Makefile ++++ b/drivers/cpuidle/Makefile +@@ -17,7 +17,10 @@ obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o + obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o + obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o + obj-$(CONFIG_ARM_EXYNOS_CPUIDLE) += cpuidle-exynos.o +- ++obj-$(CONFIG_ARM_HI3519_CPUIDLE) += cpuidle-hi3519.o ++obj-$(CONFIG_ARM_HI3519V101_CPUIDLE) += cpuidle-hi3519.o ++obj-$(CONFIG_ARM_HI3516AV200_CPUIDLE) += cpuidle-hi3516av200.o ++obj-$(CONFIG_ARM_HI3556_CPUIDLE) += cpuidle-hi3559.o + ############################################################################### + # MIPS drivers + obj-$(CONFIG_MIPS_CPS_CPUIDLE) += cpuidle-cps.o +diff --git a/drivers/cpuidle/cpuidle-hi3516av200.c b/drivers/cpuidle/cpuidle-hi3516av200.c +new file mode 100644 +index 0000000..5d318ad +--- /dev/null ++++ b/drivers/cpuidle/cpuidle-hi3516av200.c +@@ -0,0 +1,286 @@ ++/* ++ * ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++ ++/* extern functions */ ++extern void hi3516av200_set_cpu_jump(int cpu, phys_addr_t jumpaddr); ++extern void hi3516av200_cpu_resume(void); ++extern void hi_pmc_set_ac_inactive(void); ++extern void hi_pmc_automode_power_down(void); ++extern void hi_pmc_power_up_done(void); ++ ++static int bl_cpuidle_simple_enter(struct cpuidle_device *dev, ++ struct cpuidle_driver *drv, int index); ++ ++int bl_cpuidle_simple_enter(struct cpuidle_device *dev, ++ struct cpuidle_driver *drv, int index) ++{ ++#if defined(CPUIDLE_DEBUG) ++ int cpuid = smp_processor_id(); ++ ++ pr_debug("%s cpu:%d enter", __func__, cpuid); ++#endif ++ cpu_do_idle(); ++ return index; ++} ++ ++static int bl_enter_cpu_powerdown(struct cpuidle_device *dev, ++ struct cpuidle_driver *drv, int idx); ++ ++ ++static struct cpuidle_state bl_cpuidle_set[] __initdata = { ++ [0] = { ++ .enter = bl_cpuidle_simple_enter, ++ .exit_latency = 1, ++ .target_residency = 1, ++ .power_usage = UINT_MAX, ++ .flags = CPUIDLE_FLAG_TIME_VALID, ++ .name = "WFI", ++ .desc = "ARM WFI", ++ }, ++ [1] = { ++ .enter = bl_enter_cpu_powerdown, ++ .exit_latency = 500, ++ .target_residency = 1000, ++ .flags = CPUIDLE_FLAG_TIME_VALID | ++ CPUIDLE_FLAG_TIMER_STOP, ++ .name = "C1", ++ .desc = "ARM cpu A17 Cluster power down", ++ }, ++}; ++ ++static struct cpuidle_driver bl_idle_driver = { ++ .name = "bl_idle", ++ .owner = THIS_MODULE, ++ .safe_state_index = 0 ++}; ++ ++static DEFINE_PER_CPU(struct cpuidle_device, bl_idle_dev); ++ ++static void bl_cpu_smp_disable(void) ++{ ++ /* Set ACTLR.SMP to 0, AMP -> SMP */ ++ asm volatile ( ++ " mrc p15, 0, r0, c1, c0, 1\n" ++ " bic r0, #0x40\n" ++ " mcr p15, 0, r0, c1, c0, 1\n" ++ : ++ : ++ : "r0", "cc"); ++} ++ ++/* ++ * switch to init_mm, init_mm page table entries must in memory ++ * not in the cpu cache ++ */ ++static void setup_mm_for_idle(void) ++{ ++ struct mm_struct *mm = &init_mm; ++ ++ cpu_switch_mm(mm->pgd, mm); ++ local_flush_bp_all(); ++ local_flush_tlb_all(); ++} ++ ++static void bl_cpu_powerdown(u64 expected_residency) ++{ ++ int cpu = smp_processor_id(); ++ /* disable irq */ ++ if (WARN(!irqs_disabled(), "Interrupts should be disabled\n")) ++ local_irq_disable(); ++ ++ /* ++ * Once the Dcache is disabled and the tlb is empty, the ptw will ++ * fetch page table entries for the code after Dcache disable from ++ * memory, but the mm is active_mm from last user process's mm, and ++ * the mm->pgd may located in cpu cache(see dcache_clean_area), so ++ * switch to init_mm to avoid access fault. ++ */ ++ setup_mm_for_idle(); ++ /* move the power code here to measure the idle enter time */ ++ hi_pmc_automode_power_down(); ++ ++ gic_cpu_if_down(); ++ ++ /* close Dcache */ ++ set_cr(get_cr() & ~CR_C); ++ /* CLREX */ ++ asm volatile ("clrex"); ++ ++ /* Clean & Invalidata L1 Data Cache, L2 Cache */ ++/* for cortex a17 just one single instruction is enough ++ flush_cache_all(); ++*/ ++ /* clean&invalidate l1 cache */ ++ asm volatile("mov r0, #0"); ++ asm volatile("mcr p15, 1, r0, c15, c14, 0"); ++ asm volatile("dsb"); ++ ++ /* clean&invalidate l2 cache */ ++ asm volatile("mov r0, #2"); ++ asm volatile("mcr p15, 1, r0, c15, c14, 0"); ++ asm volatile("dsb"); ++ ++ /* switch SMP to AMP(ACTLR.SMP->1'b0) */ ++ bl_cpu_smp_disable(); ++ ++ /* disable cci snoop */ ++ cci_disable_port_by_cpu(cpu_logical_map(cpu)); ++ ++ /* asm volatile("mcr p14, 0, %0, c1, c3, 0" : : "r" (1)); */ ++ ++ /* ISB & DSB */ ++ isb(); ++ dsb(); ++ ++ hi_pmc_set_ac_inactive(); ++/* ++ hi_pmc_automode_power_down(); ++*/ ++ dsb(); ++ /* WFI */ ++ while (1) ++ wfi(); ++ ++ BUG(); ++} ++ ++static int bl_cpu_powered_up(void) ++{ ++ /*dcache enble*/ ++ set_cr(get_cr() | CR_C); ++ ++ hi_pmc_power_up_done(); ++ ++ return 0; ++} ++ ++ ++static int notrace bl_cpu_powerdown_finisher(unsigned long arg) ++{ ++ hi3516av200_set_cpu_jump(smp_processor_id(), ++ (phys_addr_t)virt_to_phys(hi3516av200_cpu_resume)); ++ ++ bl_cpu_powerdown(0); ++ ++ return 1; ++} ++ ++/* ++ * bl_enter_cpu_powerdown - Programs CPU to enter the specified state ++ * @dev: cpuidle device ++ * @drv: The target state to be programmed ++ * @idx: state index ++ * ++ * Called from the CPUidle framework to program the device to the ++ * specified target state selected by the governor. ++ */ ++int bl_enter_cpu_powerdown(struct cpuidle_device *dev, ++ struct cpuidle_driver *drv, int idx) ++{ ++ int cpuid = smp_processor_id(); ++ ++ /* A7 can not power down */ ++ if (cpuid == 0) { ++ cpu_do_idle(); ++ return idx; ++ } ++ ++ BUG_ON(!irqs_disabled()); ++ ++ cpu_pm_enter(); ++ ++ cpu_suspend((unsigned long) dev, bl_cpu_powerdown_finisher); ++ ++ bl_cpu_powered_up(); ++ ++ cpu_pm_exit(); ++ ++ return idx; ++} ++/* ++ * bl_idle_init ++ * ++ * Registers the bl specific cpuidle driver with the cpuidle ++ * framework with the valid set of states. ++ */ ++ ++static int __init bl_idle_init(void) ++{ ++ struct cpuidle_device *dev; ++ int i, cpu_id; ++ struct cpuidle_driver *drv = &bl_idle_driver; ++ ++ drv->state_count = (sizeof(bl_cpuidle_set) / ++ sizeof(struct cpuidle_state)); ++ ++ ++ for (i = 0; i < drv->state_count; i++) { ++ memcpy(&drv->states[i], &bl_cpuidle_set[i], ++ sizeof(struct cpuidle_state)); ++ } ++ cpuidle_register_driver(drv); ++ ++ for_each_cpu(cpu_id, cpu_online_mask) { ++ /* cpu 0 use default idle */ ++ if (cpu_id == 0) ++ continue; ++ pr_err("CPUidle for CPU%d registered\n", cpu_id); ++ dev = &per_cpu(bl_idle_dev, cpu_id); ++ dev->cpu = cpu_id; ++ ++ if (cpuidle_register_device(dev)) { ++ pr_err("%s: Cpuidle register device failed\n", ++ __func__); ++ return -EIO; ++ } ++ } ++ ++ ++ return 0; ++} ++ ++device_initcall(bl_idle_init); +diff --git a/drivers/cpuidle/cpuidle-hi3519.c b/drivers/cpuidle/cpuidle-hi3519.c +new file mode 100644 +index 0000000..f3d952c +--- /dev/null ++++ b/drivers/cpuidle/cpuidle-hi3519.c +@@ -0,0 +1,274 @@ ++/** ++ * cpuidle-hi3519.c ++ * ++ * Copyright (c) 2009-2014, HiSilicon Technologies Co., Ltd. ++ * All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++ ++/* extern functions */ ++extern void hi3519_set_cpu_jump(int cpu, phys_addr_t jumpaddr); ++extern void hi3519_cpu_resume(void); ++extern void hi_pmc_set_ac_inactive(void); ++extern void hi_pmc_automode_power_down(void); ++extern void hi_pmc_power_up_done(void); ++ ++static int bl_cpuidle_simple_enter(struct cpuidle_device *dev, ++ struct cpuidle_driver *drv, int index); ++ ++int bl_cpuidle_simple_enter(struct cpuidle_device *dev, ++ struct cpuidle_driver *drv, int index) ++{ ++#if defined(CPUIDLE_DEBUG) ++ int cpuid = smp_processor_id(); ++ ++ pr_debug("%s cpu:%d enter", __func__, cpuid); ++#endif ++ cpu_do_idle(); ++ return index; ++} ++ ++static int bl_enter_cpu_powerdown(struct cpuidle_device *dev, ++ struct cpuidle_driver *drv, int idx); ++ ++ ++static struct cpuidle_state bl_cpuidle_set[] __initdata = { ++ [0] = { ++ .enter = bl_cpuidle_simple_enter, ++ .exit_latency = 1, ++ .target_residency = 1, ++ .power_usage = UINT_MAX, ++ .flags = CPUIDLE_FLAG_TIME_VALID, ++ .name = "WFI", ++ .desc = "ARM WFI", ++ }, ++ [1] = { ++ .enter = bl_enter_cpu_powerdown, ++ .exit_latency = 500, ++ .target_residency = 1000, ++ .flags = CPUIDLE_FLAG_TIME_VALID | ++ CPUIDLE_FLAG_TIMER_STOP, ++ .name = "C1", ++ .desc = "ARM cpu A17 Cluster power down", ++ }, ++}; ++ ++static struct cpuidle_driver bl_idle_driver = { ++ .name = "bl_idle", ++ .owner = THIS_MODULE, ++ .safe_state_index = 0 ++}; ++ ++static DEFINE_PER_CPU(struct cpuidle_device, bl_idle_dev); ++ ++static void bl_cpu_smp_disable(void) ++{ ++ /* Set ACTLR.SMP to 0, AMP -> SMP */ ++ asm volatile ( ++ " mrc p15, 0, r0, c1, c0, 1\n" ++ " bic r0, #0x40\n" ++ " mcr p15, 0, r0, c1, c0, 1\n" ++ : ++ : ++ : "r0", "cc"); ++} ++ ++/* ++ * switch to init_mm, init_mm page table entries must in memory ++ * not in the cpu cache ++ */ ++static void setup_mm_for_idle(void) ++{ ++ struct mm_struct *mm = &init_mm; ++ ++ cpu_switch_mm(mm->pgd, mm); ++ local_flush_bp_all(); ++ local_flush_tlb_all(); ++} ++ ++static void bl_cpu_powerdown(u64 expected_residency) ++{ ++ int cpu = smp_processor_id(); ++ /* disable irq */ ++ if (WARN(!irqs_disabled(), "Interrupts should be disabled\n")) ++ local_irq_disable(); ++ ++ /* ++ * Once the Dcache is disabled and the tlb is empty, the ptw will ++ * fetch page table entries for the code after Dcache disable from ++ * memory, but the mm is active_mm from last user process's mm, and ++ * the mm->pgd may located in cpu cache(see dcache_clean_area), so ++ * switch to init_mm to avoid access fault. ++ */ ++ setup_mm_for_idle(); ++ /* move the power code here to measure the idle enter time */ ++ hi_pmc_automode_power_down(); ++ ++ gic_cpu_if_down(); ++ ++ /* close Dcache */ ++ set_cr(get_cr() & ~CR_C); ++ /* CLREX */ ++ asm volatile ("clrex"); ++ ++ /* Clean & Invalidata L1 Data Cache, L2 Cache */ ++/* for cortex a17 just one single instruction is enough ++ flush_cache_all(); ++*/ ++ /* clean&invalidate l1 cache */ ++ asm volatile("mov r0, #0"); ++ asm volatile("mcr p15, 1, r0, c15, c14, 0"); ++ asm volatile("dsb"); ++ ++ /* clean&invalidate l2 cache */ ++ asm volatile("mov r0, #2"); ++ asm volatile("mcr p15, 1, r0, c15, c14, 0"); ++ asm volatile("dsb"); ++ ++ /* switch SMP to AMP(ACTLR.SMP->1'b0) */ ++ bl_cpu_smp_disable(); ++ ++ /* disable cci snoop */ ++ cci_disable_port_by_cpu(cpu_logical_map(cpu)); ++ ++ /* asm volatile("mcr p14, 0, %0, c1, c3, 0" : : "r" (1)); */ ++ ++ /* ISB & DSB */ ++ isb(); ++ dsb(); ++ ++ hi_pmc_set_ac_inactive(); ++/* ++ hi_pmc_automode_power_down(); ++*/ ++ dsb(); ++ /* WFI */ ++ while (1) ++ wfi(); ++ ++ BUG(); ++} ++ ++static int bl_cpu_powered_up(void) ++{ ++ /*dcache enble*/ ++ set_cr(get_cr() | CR_C); ++ ++ hi_pmc_power_up_done(); ++ ++ return 0; ++} ++ ++ ++static int notrace bl_cpu_powerdown_finisher(unsigned long arg) ++{ ++ hi3519_set_cpu_jump(smp_processor_id(), ++ (phys_addr_t)virt_to_phys(hi3519_cpu_resume)); ++ ++ bl_cpu_powerdown(0); ++ ++ return 1; ++} ++ ++/* ++ * bl_enter_cpu_powerdown - Programs CPU to enter the specified state ++ * @dev: cpuidle device ++ * @drv: The target state to be programmed ++ * @idx: state index ++ * ++ * Called from the CPUidle framework to program the device to the ++ * specified target state selected by the governor. ++ */ ++int bl_enter_cpu_powerdown(struct cpuidle_device *dev, ++ struct cpuidle_driver *drv, int idx) ++{ ++ int cpuid = smp_processor_id(); ++ ++ /* A7 can not power down */ ++ if (cpuid == 0) { ++ cpu_do_idle(); ++ return idx; ++ } ++ ++ BUG_ON(!irqs_disabled()); ++ ++ cpu_pm_enter(); ++ ++ cpu_suspend((unsigned long) dev, bl_cpu_powerdown_finisher); ++ ++ bl_cpu_powered_up(); ++ ++ cpu_pm_exit(); ++ ++ return idx; ++} ++/* ++ * bl_idle_init ++ * ++ * Registers the bl specific cpuidle driver with the cpuidle ++ * framework with the valid set of states. ++ */ ++ ++static int __init bl_idle_init(void) ++{ ++ struct cpuidle_device *dev; ++ int i, cpu_id; ++ struct cpuidle_driver *drv = &bl_idle_driver; ++ ++ drv->state_count = (sizeof(bl_cpuidle_set) / ++ sizeof(struct cpuidle_state)); ++ ++ ++ for (i = 0; i < drv->state_count; i++) { ++ memcpy(&drv->states[i], &bl_cpuidle_set[i], ++ sizeof(struct cpuidle_state)); ++ } ++ cpuidle_register_driver(drv); ++ ++ for_each_cpu(cpu_id, cpu_online_mask) { ++ /* cpu 0 use default idle */ ++ if (cpu_id == 0) ++ continue; ++ pr_err("CPUidle for CPU%d registered\n", cpu_id); ++ dev = &per_cpu(bl_idle_dev, cpu_id); ++ dev->cpu = cpu_id; ++ ++ if (cpuidle_register_device(dev)) { ++ pr_err("%s: Cpuidle register device failed\n", ++ __func__); ++ return -EIO; ++ } ++ } ++ ++ ++ return 0; ++} ++ ++device_initcall(bl_idle_init); +diff --git a/drivers/cpuidle/cpuidle-hi3559.c b/drivers/cpuidle/cpuidle-hi3559.c +new file mode 100644 +index 0000000..1e18ae4 +--- /dev/null ++++ b/drivers/cpuidle/cpuidle-hi3559.c +@@ -0,0 +1,253 @@ ++/** ++ * cpuidle-hi3559.c ++ * ++ * Copyright (c) 2009-2014, HiSilicon Technologies Co., Ltd. ++ * All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++ ++/* extern functions */ ++extern void hi3559_set_cpu_jump(int cpu, phys_addr_t jumpaddr); ++extern void hi3559_cpu_resume(void); ++extern void hi_pmc_set_ac_inactive(void); ++extern void hi_pmc_automode_power_down(void); ++extern void hi_pmc_power_up_done(void); ++ ++static int bl_cpuidle_simple_enter(struct cpuidle_device *dev, ++ struct cpuidle_driver *drv, int index); ++ ++int bl_cpuidle_simple_enter(struct cpuidle_device *dev, ++ struct cpuidle_driver *drv, int index) ++{ ++#if defined(CPUIDLE_DEBUG) ++ int cpuid = smp_processor_id(); ++ ++ pr_debug("%s cpu:%d enter", __func__, cpuid); ++#endif ++ cpu_do_idle(); ++ return index; ++} ++ ++static int bl_enter_cpu_powerdown(struct cpuidle_device *dev, ++ struct cpuidle_driver *drv, int idx); ++ ++ ++static struct cpuidle_state bl_cpuidle_set[] __initdata = { ++ [0] = { ++ .enter = bl_cpuidle_simple_enter, ++ .exit_latency = 1, ++ .target_residency = 1, ++ .power_usage = UINT_MAX, ++ .flags = CPUIDLE_FLAG_TIME_VALID, ++ .name = "WFI", ++ .desc = "ARM WFI", ++ }, ++ [1] = { ++ .enter = bl_enter_cpu_powerdown, ++ .exit_latency = 500, ++ .target_residency = 1000, ++ .flags = CPUIDLE_FLAG_TIME_VALID | ++ CPUIDLE_FLAG_TIMER_STOP, ++ .name = "C1", ++ .desc = "ARM cpu A17 Cluster power down", ++ }, ++}; ++ ++static struct cpuidle_driver bl_idle_driver = { ++ .name = "bl_idle", ++ .owner = THIS_MODULE, ++ .safe_state_index = 0 ++}; ++ ++static DEFINE_PER_CPU(struct cpuidle_device, bl_idle_dev); ++ ++static void bl_cpu_smp_disable(void) ++{ ++ /* Set ACTLR.SMP to 0, AMP -> SMP */ ++ asm volatile ( ++ " mrc p15, 0, r0, c1, c0, 1\n" ++ " bic r0, #0x40\n" ++ " mcr p15, 0, r0, c1, c0, 1\n" ++ : ++ : ++ : "r0", "cc"); ++} ++ ++static void bl_cpu_powerdown(u64 expected_residency) ++{ ++ int cpu = smp_processor_id(); ++ /* disable irq */ ++ if (WARN(!irqs_disabled(), "Interrupts should be disabled\n")) ++ local_irq_disable(); ++ ++ /* move the power code here to measure the idle enter time */ ++ hi_pmc_automode_power_down(); ++ ++ gic_cpu_if_down(); ++ ++ /* close Dcache */ ++ set_cr(get_cr() & ~CR_C); ++ /* CLREX */ ++ asm volatile ("clrex"); ++ ++ /* Clean & Invalidata L1 Data Cache, L2 Cache */ ++/* for cortex a17 just one single instruction is enough ++ flush_cache_all(); ++*/ ++ /* clean&invalidate l1 cache */ ++ asm volatile("mov r0, #0"); ++ asm volatile("mcr p15, 1, r0, c15, c14, 0"); ++ asm volatile("dsb"); ++ ++ /* clean&invalidate l2 cache */ ++ asm volatile("mov r0, #2"); ++ asm volatile("mcr p15, 1, r0, c15, c14, 0"); ++ asm volatile("dsb"); ++ ++ /* switch SMP to AMP(ACTLR.SMP->1'b0) */ ++ bl_cpu_smp_disable(); ++ ++ /* disable cci snoop */ ++ cci_disable_port_by_cpu(cpu_logical_map(cpu)); ++ ++ /* asm volatile("mcr p14, 0, %0, c1, c3, 0" : : "r" (1)); */ ++ ++ /* ISB & DSB */ ++ isb(); ++ dsb(); ++ ++ hi_pmc_set_ac_inactive(); ++/* ++ hi_pmc_automode_power_down(); ++*/ ++ dsb(); ++ /* WFI */ ++ while (1) ++ wfi(); ++ ++ BUG(); ++} ++ ++static int bl_cpu_powered_up(void) ++{ ++ /*dcache enble*/ ++ set_cr(get_cr() | CR_C); ++ ++ hi_pmc_power_up_done(); ++ ++ return 0; ++} ++ ++ ++static int notrace bl_cpu_powerdown_finisher(unsigned long arg) ++{ ++ hi3559_set_cpu_jump(smp_processor_id(), ++ (phys_addr_t)virt_to_phys(hi3559_cpu_resume)); ++ ++ bl_cpu_powerdown(0); ++ ++ return 1; ++} ++ ++/* ++ * bl_enter_cpu_powerdown - Programs CPU to enter the specified state ++ * @dev: cpuidle device ++ * @drv: The target state to be programmed ++ * @idx: state index ++ * ++ * Called from the CPUidle framework to program the device to the ++ * specified target state selected by the governor. ++ */ ++int bl_enter_cpu_powerdown(struct cpuidle_device *dev, ++ struct cpuidle_driver *drv, int idx) ++{ ++ int cpuid = smp_processor_id(); ++ ++ /* A7 can not power down */ ++ if (cpuid == 0) { ++ cpu_do_idle(); ++ return idx; ++ } ++ ++ BUG_ON(!irqs_disabled()); ++ ++ cpu_pm_enter(); ++ ++ cpu_suspend((unsigned long) dev, bl_cpu_powerdown_finisher); ++ ++ bl_cpu_powered_up(); ++ ++ cpu_pm_exit(); ++ ++ return idx; ++} ++/* ++ * bl_idle_init ++ * ++ * Registers the bl specific cpuidle driver with the cpuidle ++ * framework with the valid set of states. ++ */ ++ ++static int __init bl_idle_init(void) ++{ ++ struct cpuidle_device *dev; ++ int i, cpu_id; ++ struct cpuidle_driver *drv = &bl_idle_driver; ++ ++ drv->state_count = (sizeof(bl_cpuidle_set) / ++ sizeof(struct cpuidle_state)); ++ ++ ++ for (i = 0; i < drv->state_count; i++) { ++ memcpy(&drv->states[i], &bl_cpuidle_set[i], ++ sizeof(struct cpuidle_state)); ++ } ++ cpuidle_register_driver(drv); ++ ++ for_each_cpu(cpu_id, cpu_online_mask) { ++ /* cpu 0 use default idle */ ++ if (cpu_id == 0) ++ continue; ++ pr_err("CPUidle for CPU%d registered\n", cpu_id); ++ dev = &per_cpu(bl_idle_dev, cpu_id); ++ dev->cpu = cpu_id; ++ ++ if (cpuidle_register_device(dev)) { ++ pr_err("%s: Cpuidle register device failed\n", ++ __func__); ++ return -EIO; ++ } ++ } ++ ++ ++ return 0; ++} ++ ++device_initcall(bl_idle_init); +diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c +index 710a233..386261a 100644 +--- a/drivers/cpuidle/governors/menu.c ++++ b/drivers/cpuidle/governors/menu.c +@@ -178,7 +178,12 @@ static inline int performance_multiplier(unsigned long nr_iowaiters, unsigned lo + + /* for higher loadavg, we are more reluctant */ + +- mult += 2 * get_loadavg(load); ++ /* ++ * this doesn't work as intended - it is almost always 0, but can ++ * sometimes, depending on workload, spike very high into the hundreds ++ * even when the average cpu load is under 10%. ++ */ ++ /* mult += 2 * get_loadavg(); */ + + /* for IO wait tasks (per cpu!) we add 5x each */ + mult += 10 * nr_iowaiters; +diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig +index 2fb0fdf..7aea536 100644 +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -436,4 +436,6 @@ config CRYPTO_DEV_QCE + hardware. To compile this driver as a module, choose M here. The + module will be called qcrypto. + ++source drivers/crypto/hisi-cipher/Kconfig ++ + endif # CRYPTO_HW +diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile +index 3924f93..96b3c42 100644 +--- a/drivers/crypto/Makefile ++++ b/drivers/crypto/Makefile +@@ -25,3 +25,4 @@ obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o + obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/ + obj-$(CONFIG_CRYPTO_DEV_QAT) += qat/ + obj-$(CONFIG_CRYPTO_DEV_QCE) += qce/ ++obj-$(CONFIG_CRYPTO_DEV_HISILICON) += hisi-cipher/ +diff --git a/drivers/crypto/hisi-cipher/Kconfig b/drivers/crypto/hisi-cipher/Kconfig +new file mode 100644 +index 0000000..7e520a9 +--- /dev/null ++++ b/drivers/crypto/hisi-cipher/Kconfig +@@ -0,0 +1,15 @@ ++# ++# Copyright (C) Hisilicon 2018 ++# License terms: GNU General Public License (GPL) version 2 ++# ++ ++menuconfig CRYPTO_DEV_HISILICON ++ bool "Hisi Cipher Support" ++ depends on CRYPTO_HW ++ default n ++ help ++ This driver interfaces with the hardware hisi cipher.Supporting ++ aes/des/des3 cipher algorithm(cbc/ecb/ofb/cfb/ctr/ccm/gcm mode avalible), ++ sah1/sha256/hmac1/hmac256, rng, rsa algorithm support. ++ To compile this driver as a module, ++ This select support:the module will be called hisi-cipher. +\ No newline at end of file +diff --git a/drivers/crypto/hisi-cipher/Makefile b/drivers/crypto/hisi-cipher/Makefile +new file mode 100644 +index 0000000..dffde46 +--- /dev/null ++++ b/drivers/crypto/hisi-cipher/Makefile +@@ -0,0 +1 @@ ++obj-y += src/ +diff --git a/drivers/crypto/hisi-cipher/arch/hi3516a/config.h b/drivers/crypto/hisi-cipher/arch/hi3516a/config.h +new file mode 100644 +index 0000000..bbf5408 +--- /dev/null ++++ b/drivers/crypto/hisi-cipher/arch/hi3516a/config.h +@@ -0,0 +1,30 @@ ++#ifndef __CONFIG_H__ ++#define __CONFIG_H__ ++ ++#ifdef CHIP_TYPE_hi3516a ++ ++/********* Here define the function supported by chip *****************/ ++#define CIPHER_IRQ_NUMBER 58 ++//#define CIPHER_HASH_SUPPORT ++//#define CIPHER_MHASH_SUPPORT ++//#define CIPHER_RSA_SUPPORT ++//#define CIPHER_RNG_SUPPORT ++//#define CIPHER_CCM_GCM_SUPPORT ++//#define CIPHER_EFUSE_SUPPORT ++#define CIPHER_MULTICIPHER_SUPPORT ++ ++/********* Here define the base address of chip ***********************/ ++#define REG_BASE_PHY_ADDR_CIPHER (0x100c0000) ++ ++/********* Here define the clcok and reset signal in CRG ***************/ ++#define REG_CRG_CLK_PHY_ADDR_CIPHER (0x2003007C) ++#define CRG_RST_BIT_CIPHER 0 ++#define CRG_CLK_BIT_CIPHER 1 ++#define CIPHER_READL readl ++#define CIPHER_WRITEL writel ++ ++#else ++ #error You need to define a correct chip type! ++#endif ++#endif ++ +diff --git a/drivers/crypto/hisi-cipher/arch/hi3516a/hi_unf_cipher.h b/drivers/crypto/hisi-cipher/arch/hi3516a/hi_unf_cipher.h +new file mode 100644 +index 0000000..3af6b3d +--- /dev/null ++++ b/drivers/crypto/hisi-cipher/arch/hi3516a/hi_unf_cipher.h +@@ -0,0 +1,314 @@ ++#ifndef __HI_UNF_CIPHER_H__ ++#define __HI_UNF_CIPHER_H__ ++ ++#include "hi_type.h" ++ ++#ifdef __cplusplus ++#if __cplusplus ++extern "C" { ++#endif ++#endif /* __cplusplus */ ++/*************************** Structure Definition ****************************/ ++/** \addtogroup CIPHER */ ++/** @{ */ /** |<--- 8bit --->|<--- 8bit --->| ++ |--------------------------------------------------------------| ++ | HI_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 HI_HANDLE_MAKEHANDLE(mod, privatedata, chnid) (HI_HANDLE)( (((mod)& 0xffff) << 16) | ((((privatedata)& 0xff) << 8) ) | (((chnid) & 0xff)) ) ++ ++#define HI_HANDLE_GET_MODID(handle) (((handle) >> 16) & 0xffff) ++#define HI_HANDLE_GET_PriDATA(handle) (((handle) >> 8) & 0xff) ++#define HI_HANDLE_GET_CHNID(handle) (((handle)) & 0xff) ++ ++#ifndef __HuaweiLite__ ++#define UNUSED(x) ((x)=(x)) ++#endif ++ ++ ++/** @} */ /** TX, odd number-->RX*/ ++ uwsrc_addr = memaddr; ++ uwdst_addr = (unsigned int)(g_peripheral[uwperipheralid].peri_addr); ++ ++ tmp = uwnumtransfers >> uwwidth; ++ if (tmp & (~0x0fff)) { ++ dma_err("Invalidate size%x\n", uwnumtransfers); ++ return -EINVAL; ++ } ++ ++ tmp = tmp & 0xfff; ++ uwtrans_control = tmp | ++ (g_peripheral[uwperipheralid].transfer_ctrl & (~0xfff)); ++ dmac_writew(DMAC_INTTCCLEAR, (0x1<<(unsigned int)uwchannel_num)); ++ dmac_writew(DMAC_INTERRCLR, (0x1<<(unsigned int)uwchannel_num)); ++ dmac_writew(DMAC_CxSRCADDR(uwchannel_num), (unsigned int)uwsrc_addr); ++ dmac_writew(DMAC_CxDESTADDR(uwchannel_num), (unsigned int)uwdst_addr); ++ dmac_writew(DMAC_CxCONTROL(uwchannel_num), ++ (unsigned int)uwtrans_control); ++ dmac_writew(DMAC_CxCONFIG(uwchannel_num), ++ (g_peripheral[uwperipheralid].transfer_cfg)); ++ ++ return 0; ++} ++ ++/* ++ * enable memory and peripheral dma transfer ++ * note: ++ * it is necessary to call dmac_channelstart to enable channel ++ */ ++int dmac_start_p2m(unsigned int channel, unsigned int memaddr, ++ unsigned int uwperipheralid, unsigned int uwnumtransfers, ++ unsigned int next_lli_addr) ++{ ++ unsigned int uwtrans_control = 0; ++ unsigned int addtmp, tmp; ++ unsigned int uwdst_addr = 0, uwsrc_addr = 0; ++ unsigned int uwwidth; ++ int uwchannel_num; ++ ++ addtmp = memaddr; ++ ++ if ((uwperipheralid > 15)) { ++ dma_err("Invalid peripheral id%x\n", uwperipheralid); ++ return -EINVAL; ++ } ++ ++ uwchannel_num = (int)channel; ++ if ((uwchannel_num == DMAC_CHANNEL_INVALID) ++ || (uwchannel_num > 3) || (uwchannel_num < 0)) { ++ dma_err("failure alloc\n"); ++ return -EFAULT; ++ } ++ ++ /* must modified with different peripheral */ ++ uwwidth = g_peripheral[uwperipheralid].transfer_width; ++ ++ /* check transfer direction * ++ * even number-->TX, odd number-->RX*/ ++ uwsrc_addr = (unsigned int)(g_peripheral[uwperipheralid].peri_addr); ++ uwdst_addr = memaddr; ++ ++ tmp = uwnumtransfers >> uwwidth; ++ if (tmp & (~0x0fff)) { ++ dma_err("Invalidate size%x\n", uwnumtransfers); ++ return -EINVAL; ++ } ++ ++ tmp = tmp & 0xfff; ++ uwtrans_control = tmp | ++ (g_peripheral[uwperipheralid].transfer_ctrl & (~0xfff)); ++ dmac_writew(DMAC_INTTCCLEAR, (0x1<<(unsigned int)uwchannel_num)); ++ dmac_writew(DMAC_INTERRCLR, (0x1<<(unsigned int)uwchannel_num)); ++ dmac_writew(DMAC_CxSRCADDR(uwchannel_num), (unsigned int)uwsrc_addr); ++ dmac_writew(DMAC_CxDESTADDR(uwchannel_num), (unsigned int)uwdst_addr); ++ dmac_writew(DMAC_CxCONTROL(uwchannel_num), ++ (unsigned int)uwtrans_control); ++ dmac_writew(DMAC_CxCONFIG(uwchannel_num), ++ (g_peripheral[uwperipheralid].transfer_cfg)); ++ ++ return 0; ++} ++ ++/* ++ * execute memory to memory dma transfer without LLI ++ */ ++int dmac_m2m_transfer(unsigned int source, unsigned int dest, ++ unsigned int length) ++{ ++ unsigned int ulchnn, dma_size = 0; ++ unsigned int dma_count, left_size; ++ ++ left_size = length; ++ dma_count = 0; ++ ulchnn = dmac_channel_allocate(NULL); ++ ++ ulchnn = 2; ++ ++ dma_err("use channel %d\n", ulchnn); ++ ++ while ((left_size >> 2) >= 0xffc) { ++ dma_size = 0xffc; ++ left_size -= (dma_size << 2); ++ dma_err("left_size is %x.", left_size); ++ dmac_start_m2m(ulchnn, (unsigned int)(source ++ + dma_count * (dma_size << 2)), ++ (unsigned int)(dest + dma_count * (dma_size << 2)), ++ (dma_size << 2)); ++ if (dmac_channelstart(ulchnn) != 0) { ++ dma_err("start channel error...\n"); ++ return -1; ++ } ++ ++ if (dmac_wait(ulchnn) != DMAC_CHN_SUCCESS) { ++ dma_err("dma transfer error...\n"); ++ return -1; ++ } ++ ++ dma_count++; ++ } ++ ++ dmac_start_m2m(ulchnn, (source + dma_count * (dma_size << 2)), ++ (dest + dma_count * (dma_size << 2)), (left_size << 2)); ++ ++ if (dmac_channelstart(ulchnn) != 0) ++ return -1; ++ ++ if (dmac_wait(ulchnn) != DMAC_CHN_SUCCESS) ++ return -1; ++ ++ return 0; ++} ++EXPORT_SYMBOL(dmac_m2m_transfer); ++ ++/* ++ * execute memory to peripheral dma transfer without LLI ++ */ ++int dmac_m2p_transfer(unsigned int memaddr, unsigned int uwperipheralid, ++ unsigned int length) ++{ ++ unsigned int ulchnn, dma_size = 0; ++ unsigned int dma_count, left_size; ++ unsigned int uwwidth; ++ ++ left_size = length; ++ dma_count = 0; ++ ++ ulchnn = dmac_channel_allocate(NULL); ++ if (DMAC_CHANNEL_INVALID == ulchnn) ++ return -1; ++ ++ uwwidth = g_peripheral[uwperipheralid].transfer_width; ++ ++ while ((left_size >> uwwidth) >= 0xffc) { ++ dma_size = 0xffc; ++ left_size -= (dma_size << uwwidth); ++ ++ if (dmac_start_m2p(ulchnn, ++ (unsigned int)(memaddr + dma_count * dma_size), ++ uwperipheralid, (dma_size << uwwidth), 0) < 0) ++ return -1; ++ ++ if (dmac_channelstart(ulchnn) != 0) ++ return -1; ++ ++ if (dmac_wait(ulchnn) != DMAC_CHN_SUCCESS) { ++ dmac_channel_free(ulchnn); ++ return -1; ++ } ++ ++ dma_count++; ++ } ++ ++ pr_debug("memaddr=0x%x\n", (unsigned int)(memaddr ++ + dma_count * dma_size)); ++ ++ if (dmac_start_m2p(ulchnn, ++ (unsigned int)(memaddr + dma_count * dma_size), ++ uwperipheralid, left_size, 0) < 0) ++ return -1; ++ ++ if (dmac_channelstart(ulchnn) != 0) ++ return -1; ++ ++ return ulchnn; ++} ++ ++/* ++ * execute memory to peripheral dma transfer without LLI ++ */ ++int dmac_p2m_transfer(unsigned int memaddr, unsigned int uwperipheralid, ++ unsigned int length) ++{ ++ unsigned int ulchnn, dma_size = 0; ++ unsigned int dma_count, left_size; ++ unsigned int uwwidth; ++ ++ left_size = length; ++ dma_count = 0; ++ ++ ulchnn = dmac_channel_allocate(NULL); ++ if (DMAC_CHANNEL_INVALID == ulchnn) ++ return -1; ++ ++ uwwidth = g_peripheral[uwperipheralid].transfer_width; ++ ++ while ((left_size >> uwwidth) >= 0xffc) { ++ dma_size = 0xffc; ++ left_size -= (dma_size << uwwidth); ++ ++ if (dmac_start_p2m(ulchnn, ++ (unsigned int)(memaddr + dma_count * dma_size), ++ uwperipheralid, (dma_size << uwwidth), 0) < 0) ++ return -1; ++ ++ if (dmac_channelstart(ulchnn) != 0) ++ return -1; ++ ++ if (dmac_wait(ulchnn) != DMAC_CHN_SUCCESS) { ++ dmac_channel_free(ulchnn); ++ return -1; ++ } ++ ++ dma_count++; ++ } ++ ++ pr_debug("memaddr=0x%x\n", (unsigned int)(memaddr ++ + dma_count * dma_size)); ++ ++ if (dmac_start_p2m(ulchnn, ++ (unsigned int)(memaddr + dma_count * dma_size), ++ uwperipheralid, left_size, 0) < 0) ++ return -1; ++ ++ if (dmac_channelstart(ulchnn) != 0) ++ return -1; ++ ++ return ulchnn; ++} ++ ++/* ++ * memory to memory dma transfer with LLI ++ * ++ * @source ++ * @dest ++ * @length ++ * @num ++ * */ ++int do_dma_llim2m_isp(unsigned int *source, ++ unsigned int *dest, ++ unsigned int *length, ++ unsigned int num) ++{ ++ unsigned int chnn; ++ int ret = 0; ++ ++ /* the dma channel is default using 2 */ ++ chnn = 2; ++ ++ ret = dmac_buildllim2m_isp(pllihead, source, dest, length, num); ++ ++ if (ret) { ++ dma_err("build lli error...\n"); ++ return -1; ++ } ++ ++ /* dmac_register_isr(chnn, dmac_channel_close); */ ++ ret = dmac_start_llim2m(chnn, pllihead); ++ if (ret) ++ return -1; ++ ++ if (dmac_channelstart(chnn) != 0) { ++ dma_err("start channel error...\n"); ++ return -1; ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL(do_dma_llim2m_isp); ++ ++int do_dma_m2p(unsigned int memaddr, unsigned int peripheral_addr, ++ unsigned int length) ++{ ++ int ret = 0; ++ int uwperipheralid; ++ ++ uwperipheralid = dmac_check_request(peripheral_addr, TX); ++ if (uwperipheralid < 0) { ++ dma_err("m2p:Invalid devaddr\n"); ++ return -1; ++ } ++ ++ ret = dmac_m2p_transfer(memaddr, uwperipheralid, length); ++ if (ret == -1) { ++ dma_err("m2p:trans err\n"); ++ return -1; ++ } ++ ++ return ret; ++} ++ ++int do_dma_p2m(unsigned int memaddr, unsigned int peripheral_addr, ++ unsigned int length) ++{ ++ int ret = -1; ++ int uwperipheralid; ++ ++ uwperipheralid = dmac_check_request(peripheral_addr, RX); ++ if (uwperipheralid < 0) { ++ dma_err("p2m:Invalid devaddr.\n"); ++ return -1; ++ } ++ ++ ret = dmac_p2m_transfer(memaddr, uwperipheralid, length); ++ if (ret == -1) { ++ dma_err("p2m:trans err\n"); ++ return -1; ++ } ++ ++ return ret; ++} ++ ++/* ++ * Apply DMA interrupt resource ++ * init channel state ++ */ ++static int hi_dmac_probe(struct platform_device *platdev) ++{ ++ unsigned int i; ++ ++ reg_dmac_base_va = (void *)IO_ADDRESS(DMAC_BASE_REG); ++ ++ dmac_init(); ++ ++ for (i = 0; i < DMAC_MAX_CHANNELS; i++) ++ g_channel_status[i] = DMAC_CHN_VACANCY; ++ ++ return 0; ++} ++ ++static int hi_dmac_remove(struct platform_device *platdev) ++{ ++ int i; ++ ++ for (i = 0; i < DMAC_MAX_CHANNELS; i++) ++ g_channel_status[i] = DMAC_CHN_VACANCY; ++ ++ return 0; ++} ++ ++static int hi_dmac_suspend(struct platform_device *dev, pm_message_t state) ++{ ++ int i; ++ ++ for (i = 0; i < DMAC_MAX_CHANNELS; i++) ++ g_channel_status[i] = DMAC_CHN_VACANCY; ++ ++ return 0; ++} ++ ++static int hi_dmac_resume(struct platform_device *dev) ++{ ++ int i; ++ ++ dmac_init(); ++ ++ for (i = 0; i < DMAC_MAX_CHANNELS; i++) ++ g_channel_status[i] = DMAC_CHN_VACANCY; ++ ++ return 0; ++} ++ ++struct platform_device hi_dmac_device = { ++ .name = "hisilicon-dmac", ++ .id = 0, ++}; ++ ++static struct platform_driver hi_dmac_driver = { ++ .probe = hi_dmac_probe, ++ .remove = hi_dmac_remove, ++ .suspend = hi_dmac_suspend, ++ .resume = hi_dmac_resume, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "hisilicon-dmac", ++ }, ++}; ++ ++int __init dma_driver_init(void) ++{ ++ int ret = 0; ++ ++ ret = platform_device_register(&hi_dmac_device); ++ if (ret) { ++ pr_err("register netdevice device failed!"); ++ goto _error_register_device; ++ } ++ ++ ret = platform_driver_register(&hi_dmac_driver); ++ if (ret) { ++ pr_err("register netdevice driver failed!"); ++ goto _error_register_driver; ++ } ++ ++ return ret; ++ ++_error_register_driver: ++ platform_device_unregister(&hi_dmac_device); ++_error_register_device: ++ return -1; ++} ++ ++static void __exit dma_driver_exit(void) ++{ ++ platform_driver_unregister(&hi_dmac_driver); ++ ++ platform_device_unregister(&hi_dmac_device); ++} ++ ++module_init(dma_driver_init); ++module_exit(dma_driver_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Hisilicon"); +diff --git a/drivers/hidmac/hi_dmac.h b/drivers/hidmac/hi_dmac.h +new file mode 100644 +index 0000000..11f2b23 +--- /dev/null ++++ b/drivers/hidmac/hi_dmac.h +@@ -0,0 +1,79 @@ ++/* ./drivers/hidmac/hi_dmac.h ++ * ++ * ++ * History: ++ * 17-August-2006 create this file ++ */ ++#ifndef __HI_DMAC_H__ ++#define __HI_DMAC_H__ ++ ++#define dmac_writew(addr, value)\ ++ hi_writel(value, (void *)(addr)) ++#define dmac_readw(addr, v)\ ++ v = hi_readl((void *)(addr)) ++ ++/*#define DMA_DEBUG*/ ++#ifdef DMA_DEBUG ++#define dma_debug printk ++#else ++#define dma_debug(fmt, ...) do {} while (0); ++#endif ++ ++#define DMAC_CONFIGURATIONx_HALT_DMA_ENABLE (0x01L<<18) ++#define DMAC_CONFIGURATIONx_ACTIVE (0x01L<<17) ++#define DMAC_CONFIGURATIONx_CHANNEL_ENABLE 1 ++#define DMAC_CONFIGURATIONx_CHANNEL_DISABLE 0 ++ ++/*definition for the return value*/ ++#define DMAC_ERROR_BASE 100 ++#define DMAC_CHANNEL_INVALID (DMAC_ERROR_BASE+1) ++ ++#define DMAC_TRXFERSIZE_INVALID (DMAC_ERROR_BASE+2) ++#define DMAC_SOURCE_ADDRESS_INVALID (DMAC_ERROR_BASE+3) ++#define DMAC_DESTINATION_ADDRESS_INVALID (DMAC_ERROR_BASE+4) ++#define DMAC_MEMORY_ADDRESS_INVALID (DMAC_ERROR_BASE+5) ++#define DMAC_PERIPHERAL_ID_INVALID (DMAC_ERROR_BASE+6) ++#define DMAC_DIRECTION_ERROR (DMAC_ERROR_BASE+7) ++#define DMAC_TRXFER_ERROR (DMAC_ERROR_BASE+8) ++#define DMAC_LLIHEAD_ERROR (DMAC_ERROR_BASE+9) ++#define DMAC_SWIDTH_ERROR (DMAC_ERROR_BASE+0xa) ++#define DMAC_LLI_ADDRESS_INVALID (DMAC_ERROR_BASE+0xb) ++#define DMAC_TRANS_CONTROL_INVALID (DMAC_ERROR_BASE+0xc) ++#define DMAC_MEMORY_ALLOCATE_ERROR (DMAC_ERROR_BASE+0xd) ++#define DMAC_NOT_FINISHED (DMAC_ERROR_BASE+0xe) ++ ++#define DMAC_TIMEOUT (DMAC_ERROR_BASE+0xf) ++#define DMAC_CHN_SUCCESS (DMAC_ERROR_BASE+0x10) ++#define DMAC_CHN_ERROR (DMAC_ERROR_BASE+0x11) ++#define DMAC_CHN_TIMEOUT (DMAC_ERROR_BASE+0x12) ++#define DMAC_CHN_ALLOCAT (DMAC_ERROR_BASE+0x13) ++#define DMAC_CHN_VACANCY (DMAC_ERROR_BASE+0x14) ++ ++#define DMAC_CONFIGURATIONx_ACTIVE_NOT 0 ++ ++/*the means the bit in the channel control register*/ ++#define DMAC_TRANS_SIZE 0xff0 ++ ++/*DMAC peripheral structure*/ ++typedef struct dmac_peripheral { ++ /* peripherial ID*/ ++ unsigned int peri_id; ++ /*peripheral data register address*/ ++ unsigned int peri_addr; ++ /*default channel control word*/ ++ unsigned int transfer_ctrl; ++ /*default channel configuration word*/ ++ unsigned int transfer_cfg; ++ /*default channel configuration word*/ ++ unsigned int transfer_width; ++} dmac_peripheral; ++ ++typedef struct mem_addr { ++ unsigned int addr_base; ++ unsigned int size; ++} mem_addr; ++ ++typedef unsigned int dma_addr_t; ++/* #define PAGE_SIZE 0x1000 */ ++ ++#endif /* End of #ifndef __HI_INC_ECSDMACC_H__ */ +diff --git a/drivers/hidmac/hi_pl08x.c b/drivers/hidmac/hi_pl08x.c +new file mode 100644 +index 0000000..7375ed9 +--- /dev/null ++++ b/drivers/hidmac/hi_pl08x.c +@@ -0,0 +1,1282 @@ ++/* ++ * ++ * Copyright (c) 2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hi_dmac.h" ++ ++#ifdef CONFIG_ARCH_HI3516CV300 ++#include "hidmac_hi3516cv300.h" ++#endif ++ ++#ifdef CONFIG_ARCH_HI3531D ++#include "hidmac_hi3531d.h" ++#endif ++ ++#ifdef CONFIG_ARCH_HI3521D ++#include "hidmac_hi3521d.h" ++#endif ++ ++#ifdef CONFIG_ARCH_HI3536C ++#include "hidmac_hi3536c.h" ++#endif ++ ++#define RX 0 ++#define TX 1 ++ ++static int dmac_channel[CHANNEL_NUM] = {0, 1, 2, 3}; ++ ++int g_channel_status[CHANNEL_NUM]; ++ ++/* #define DEBUG */ ++ ++#define DEBUG ++#ifdef DEBUG ++#define dma_err printk ++#else ++#define dma_err(fmt, ...) do {} while (0) ++#endif ++ ++/* ++ *Define Memory range ++ */ ++mem_addr mem_num[MEM_MAX_NUM] = { ++ {DDRAM_ADRS, DDRAM_SIZE}, ++ {FLASH_BASE, FLASH_SIZE} ++}; ++ ++typedef void REG_ISR(int *p_dma_chn, int *p_dma_status); ++REG_ISR *function[CHANNEL_NUM]; ++ ++struct hidmac_host { ++ struct clk *clk; ++ struct reset_control *rstc; ++ void __iomem *regbase; ++ ++ int irq; ++}; ++ ++void __iomem *dma_regbase; ++unsigned int pllihead[2]; ++ ++#define CLR_INT(i) ((*(unsigned int *)(dma_regbase+0x008)) = (1 << i)) ++ ++/* ++ * memory address validity check ++ * ++static int mem_check_valid(unsigned int addr) ++{ ++ unsigned int cnt; ++ ++ for (cnt = 0; cnt < MEM_MAX_NUM; cnt++) { ++ if ((addr >= mem_num[cnt].addr_base) && ++ (addr <= (mem_num[cnt].addr_base + mem_num[cnt].size))) ++ return 0; ++ } ++ ++ return -1; ++} */ ++ ++/* ++ * dmac interrupt handle function ++ */ ++irqreturn_t dmac_isr(int irq, void *dev_id) ++{ ++ struct hidmac_host *dma = dev_id; ++ unsigned int channel_status; ++ unsigned int channel_tc_status, channel_err_status; ++ unsigned int i; ++ ++ /*read the status of current interrupt */ ++ dmac_readw(dma->regbase + DMAC_INTSTATUS, channel_status); ++ ++ /*decide which channel has trigger the interrupt*/ ++ for (i = 0; i < DMAC_MAX_CHANNELS; i++) { ++ if ((((channel_status >> i) & 0x1) == 0x01)) { ++ /* [HSCP201306240006],l00181524,20130625 */ ++ /* The INT status should be read first then clear it */ ++ /* CLR_INT(i); */ ++ dmac_readw(dma->regbase + DMAC_INTTCSTATUS, channel_tc_status); ++ dmac_readw(dma->regbase + DMAC_INTERRORSTATUS, channel_err_status); ++ CLR_INT(i); ++ /*??HSCP201403110002?? l00183122 20140723*/ ++ if (g_channel_status[i] == DMAC_CHN_VACANCY ++ && (function[i]) == NULL) { ++ if ((0x01 == ((channel_tc_status >> i) & 0x01))) ++ dmac_writew(dma->regbase + DMAC_INTTCCLEAR, ++ (0x01 << i)); ++ else if ((0x01 == ((channel_err_status ++ >> i)&0x01))) ++ dmac_writew(dma->regbase + DMAC_INTERRCLR, ++ (0x01 << i)); ++ continue; ++ } ++ ++ /* save the current channel transfer */ ++ /* status to g_channel_status[i] */ ++ if ((0x01 == ((channel_tc_status >> i) & 0x01))) { ++ g_channel_status[i] = DMAC_CHN_SUCCESS; ++ dmac_writew(dma->regbase + DMAC_INTTCCLEAR, (0x01 << i)); ++ } else if ((0x01 == ((channel_err_status >> i)&0x01))) { ++ g_channel_status[i] = -DMAC_CHN_ERROR; ++ dmac_writew(dma->regbase + DMAC_INTERRCLR, (0x01 << i)); ++ } else { ++ pr_err("Isr Error in DMAC_IntHandeler"); ++ pr_err("%d! channel\n", i); ++ } ++ ++ if ((function[i]) != NULL) ++ function[i](&i, &g_channel_status[i]); ++ } ++ } ++ ++ return IRQ_RETVAL(1); ++} ++ ++/* ++ * update the state of channels ++ */ ++#define HI_DMA_UPDATE_TIMEOUT 5000000 ++static int dma_update_status(unsigned int channel) ++{ ++ ++ unsigned int channel_status; ++ unsigned int channel_tc_status[3]; ++ unsigned int channel_err_status[3]; ++ unsigned int i = channel, j, time = 0; ++ ++ ++ while (1) { ++ for (j = 0; j < 3; j++) { ++ dmac_readw(dma_regbase + DMAC_RAWINTTCSTATUS, ++ channel_status); ++ channel_tc_status[j] = (channel_status >> i) & 0x01; ++ dmac_readw(dma_regbase + DMAC_RAWINTERRORSTATUS, ++ channel_status); ++ channel_err_status[j] = (channel_status >> i) & 0x01; ++ } ++ ++ if ((channel_tc_status[0] == 0x1) && ++ (channel_tc_status[1] == 0x1) && ++ (channel_tc_status[2] == 0x1)) { ++ g_channel_status[i] = DMAC_CHN_SUCCESS; ++ dmac_writew(dma_regbase + DMAC_INTTCCLEAR, (0x01 << i)); ++ break; ++ } else if ((channel_err_status[0] == 0x1) && ++ (channel_err_status[1] == 0x1) && ++ (channel_err_status[2] == 0x1)) { ++ g_channel_status[i] = -DMAC_CHN_ERROR; ++ dma_err("Error in DMAC %d finish!\n", i); ++ dmac_writew(dma_regbase + DMAC_INTERRCLR, (0x01 << i)); ++ break; ++ } ++ ++ if (++time == HI_DMA_UPDATE_TIMEOUT) { ++ dma_err("Timeout in DMAC %d!\n", i); ++ g_channel_status[i] = -DMAC_CHN_TIMEOUT; ++ break; ++ } ++ } ++ ++ return g_channel_status[i]; ++} ++ ++ ++/* ++ * check the state of channels ++ */ ++static int dmac_check_over(unsigned int channel) ++{ ++ int status = 0; ++ ++ if (-DMAC_CHN_ERROR == g_channel_status[channel]) { ++ dma_err("Error transfer %d finished\n", channel); ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(channel), DMAC_CxDISABLE); ++ g_channel_status[channel] = DMAC_CHN_VACANCY; ++ status = -DMAC_CHN_ERROR; ++ } else if (DMAC_NOT_FINISHED == g_channel_status[channel]) ++ status = DMAC_NOT_FINISHED; ++ else if (DMAC_CHN_ALLOCAT == g_channel_status[channel]) ++ status = DMAC_CHN_ALLOCAT; ++ else if (DMAC_CHN_VACANCY == g_channel_status[channel]) ++ status = DMAC_CHN_VACANCY; ++ else if (-DMAC_CHN_TIMEOUT == g_channel_status[channel]) { ++ dma_err("transfer %d timeout!\n", channel); ++ status = -DMAC_CHN_TIMEOUT; ++ } else if (DMAC_CHN_SUCCESS == g_channel_status[channel]) ++ /*The transfer of Channel %d has finished successfully!*/ ++ status = DMAC_CHN_SUCCESS; ++ else { ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(channel), DMAC_CxDISABLE); ++ g_channel_status[channel] = DMAC_CHN_VACANCY; ++ status = -DMAC_CHN_ERROR; ++ } ++ return status; ++} ++ ++spinlock_t my_lcok = __SPIN_LOCK_UNLOCKED(old_style_spin_init); ++unsigned long flags; ++ ++/* ++ * allocate channel. ++ */ ++int dmac_channel_allocate(void *pisr) ++{ ++ unsigned int i, channelinfo, g_channelinfo; ++ ++ for (i = 0; i < CHANNEL_NUM; i++) ++ dmac_check_over(dmac_channel[i]); ++ ++ dmac_readw(dma_regbase + DMAC_ENBLDCHNS, g_channelinfo); ++ g_channelinfo = g_channelinfo & 0x00ff; ++ ++ for (i = 0; i < CHANNEL_NUM; i++) { ++ if (g_channel_status[dmac_channel[i]] == DMAC_CHN_VACANCY) { ++ channelinfo = g_channelinfo >> dmac_channel[i]; ++ if (0x00 == (channelinfo & 0x01)) { ++ /*clear the interrupt in this channel */ ++ dmac_writew(dma_regbase + DMAC_INTERRCLR, ++ (0x01 << dmac_channel[i])); ++ dmac_writew(dma_regbase + DMAC_INTTCCLEAR, ++ (0x01 << dmac_channel[i])); ++ ++ g_channel_status[dmac_channel[i]] ++ = DMAC_CHN_ALLOCAT; ++ return dmac_channel[i]; ++ } ++ } ++ } ++ ++ dma_err("no to alloc\n"); ++ return -EINVAL; ++} ++EXPORT_SYMBOL(dmac_channel_allocate); ++ ++int dmac_register_isr(unsigned int channel, void *pisr) ++{ ++ if (channel > CHANNEL_NUM - 1) { ++ dma_err("channel which choosed %d is error !\n", channel); ++ return -1; ++ } ++ ++ if (g_channel_status[channel] != DMAC_CHN_VACANCY) { ++ dma_err("dma chn %d is in used!\n", channel); ++ return -1; ++ } ++ ++ /*clear the interrupt in this channel */ ++ dmac_writew(dma_regbase + DMAC_INTERRCLR, (0x01 << channel)); ++ dmac_writew(dma_regbase + DMAC_INTTCCLEAR, (0x01 << channel)); ++ ++ function[channel] = (void *)pisr; ++ g_channel_status[channel] = DMAC_CHN_ALLOCAT; ++ ++ return 0; ++} ++EXPORT_SYMBOL(dmac_register_isr); ++ ++/* ++ * free channel ++ */ ++int dmac_channel_free(unsigned int channel) ++{ ++ if (channel >= DMAC_MAX_CHANNELS) { ++ dma_err("channel larger than total.\n"); ++ return -EINVAL; ++ } ++ ++ g_channel_status[channel] = DMAC_CHN_VACANCY; ++ return 0; ++} ++EXPORT_SYMBOL(dmac_channel_free); ++ ++static unsigned int dmac_check_request(unsigned int peripheral_addr, ++ int direction) ++{ ++ int i; ++ /* check request pipe with peripheral_addr */ ++ for (i = direction; i < DMAC_MAX_PERIPHERALS; i = i + 2) { ++ if (g_peripheral[i].peri_addr == peripheral_addr) ++ return i; ++ } ++ ++ dma_err("Invalid devaddr\n"); ++ ++ return -1; ++} ++ ++/* ++ * init dmac register ++ * clear interrupt flags ++ * called by dma_driver_init ++ */ ++int dmac_init(struct hidmac_host *dma) ++{ ++ unsigned int i, tempvalue; ++ int ret; ++ ++ clk_prepare_enable(dma->clk); ++ reset_control_deassert(dma->rstc); ++ ++ dmac_readw(dma->regbase + DMAC_CONFIG, tempvalue); ++ if (tempvalue == 0) { ++ dmac_writew(dma->regbase + DMAC_CONFIG, ++ DMAC_CONFIG_VAL); ++ dmac_writew(dma->regbase + DMAC_INTTCCLEAR, 0xFF); ++ dmac_writew(dma->regbase + DMAC_INTERRCLR, 0xFF); ++ for (i = 0; i < DMAC_MAX_CHANNELS; i++) { ++ dmac_writew(dma->regbase + DMAC_CxCONFIG(i), ++ DMAC_CxDISABLE); ++ function[i] = NULL; ++ } ++ } ++ ++ /* creat LLI */ ++ /* alloc space for dma lli, as the source is uncontinuous, so... */ ++ ret = allocate_dmalli_space(pllihead, 1); ++ if (ret < 0) ++ return -1; ++ ++ if (request_irq(dma->irq, dmac_isr, 0, "hi_dma", dma)) { ++ dma_err("DMA Irq %d request failed\n", dma->irq); ++ free_dmalli_space(pllihead, 1); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++ ++/* ++ * alloc_dma_lli_space ++ * output: ++ * ppheadlli[0]: memory physics address ++ * ppheadlli[1]: virtual address ++ * ++ */ ++int allocate_dmalli_space(unsigned int *ppheadlli, unsigned int page_num) ++{ ++ dma_addr_t dma_phys; ++ void *dma_virt; ++ ++ dma_virt = dma_alloc_coherent(NULL, page_num*PAGE_SIZE, ++ &dma_phys, GFP_DMA | __GFP_WAIT); ++ if (NULL == dma_virt) { ++ dma_err("can't get dma mem from system\n"); ++ return -1; ++ } ++ ++ ppheadlli[0] = (unsigned int)(dma_phys); ++ ppheadlli[1] = (unsigned int)(dma_virt); ++ ++ return 0; ++} ++EXPORT_SYMBOL(allocate_dmalli_space); ++ ++/* ++ * free_dma_lli_space ++ */ ++int free_dmalli_space(unsigned int *ppheadlli, unsigned int page_num) ++{ ++ dma_addr_t dma_phys; ++ unsigned int dma_virt; ++ ++ dma_phys = (dma_addr_t)(ppheadlli[0]); ++ dma_virt = ppheadlli[1]; ++ ++ dma_free_coherent(NULL, page_num*PAGE_SIZE, ++ (void *)dma_virt, dma_phys); ++ ++ ppheadlli[0] = 0; ++ ppheadlli[1] = 0; ++ return 0; ++} ++EXPORT_SYMBOL(free_dmalli_space); ++ ++/* ++ * config register for memory to memory DMA transfer without LLI ++ * note: ++ * it is necessary to call dmac_channelstart for channel enable ++ */ ++int dmac_start_m2m(unsigned int channel, unsigned int psource, ++ unsigned int pdest, unsigned int uwnumtransfers) ++{ ++ unsigned int uwchannel_num, tmp_trasnsfer; ++ ++ if (uwnumtransfers > (MAXTRANSFERSIZE << 2)) { ++ dma_err("Invalidate transfer size,size=%x\n", uwnumtransfers); ++ return -EINVAL; ++ } ++ ++ uwchannel_num = channel; ++ ++ if ((uwchannel_num == DMAC_CHANNEL_INVALID) ++ || (uwchannel_num > CHANNEL_NUM)) { ++ pr_err("failure of DMAC channel allocation in M2M function!\n"); ++ return -EFAULT; ++ } ++ ++ /* dmac_writew (DMAC_CxCONFIG(uwchannel_num), DMAC_CxDISABLE); */ ++ dmac_writew(dma_regbase + DMAC_CxSRCADDR(uwchannel_num), psource); ++ dmac_writew(dma_regbase + DMAC_CxDESTADDR(uwchannel_num), pdest); ++ dmac_writew(dma_regbase + DMAC_CxLLI(uwchannel_num), 0); ++ tmp_trasnsfer = (uwnumtransfers >> 2) & 0xfff; ++ tmp_trasnsfer = tmp_trasnsfer | (DMAC_CxCONTROL_M2M & (~0xfff)); ++ dmac_writew(dma_regbase + DMAC_CxCONTROL(uwchannel_num), tmp_trasnsfer); ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(uwchannel_num), DMAC_CxCONFIG_M2M); ++ ++ return 0; ++} ++EXPORT_SYMBOL(dmac_start_m2m); ++ ++/* ++ * channel enable ++ * start a dma transfer immediately ++ */ ++int dmac_channelstart(unsigned int u32channel) ++{ ++ ++ unsigned int reg_value; ++ ++ if (u32channel >= DMAC_MAX_CHANNELS) { ++ dma_err("channel larger %d\n", DMAC_MAX_CHANNELS); ++ return -EINVAL; ++ } ++ ++ g_channel_status[u32channel] = DMAC_NOT_FINISHED; ++ dmac_readw(dma_regbase + DMAC_CxCONFIG(u32channel), reg_value); ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(u32channel), ++ (reg_value | DMAC_CHANNEL_ENABLE)); ++ ++ return 0; ++} ++EXPORT_SYMBOL(dmac_channelstart); ++ ++/* ++ * wait for transfer end ++ */ ++int dmac_wait(int channel) ++{ ++ int ret_result, ret = 0; ++ ++ if (channel < 0) ++ return -1; ++ ++ while (1) { ++ ret_result = dma_update_status(channel); ++ if (ret_result == -DMAC_CHN_ERROR) { ++ dma_err("Transfer Error.\n"); ++ ret = -1; ++ goto end; ++ } else if (ret_result == DMAC_NOT_FINISHED) ++ udelay(10); ++ else if (ret_result == DMAC_CHN_SUCCESS) { ++ ret = DMAC_CHN_SUCCESS; ++ goto end; ++ } ++ else if (ret_result == DMAC_CHN_VACANCY) { ++ ret = DMAC_CHN_SUCCESS; ++ goto end; ++ } else if (ret_result == -DMAC_CHN_TIMEOUT) { ++ dma_err("Timeout.\n"); ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(channel), DMAC_CxDISABLE); ++ g_channel_status[channel] = DMAC_CHN_VACANCY; ++ ret = -1; ++ goto end; ++ } ++ } ++end: ++ dmac_channelclose(channel); ++ return ret; ++} ++EXPORT_SYMBOL(dmac_wait); ++ ++/* ++ * buile LLI for memory to memory DMA transfer ++ */ ++int dmac_buildllim2m_isp(unsigned int *ppheadlli, unsigned int *psource, ++ unsigned int *pdest, unsigned int *length, ++ unsigned int lli_num) ++{ ++ unsigned int address, phy_address; ++ unsigned int j; ++ ++ if (ppheadlli != NULL) { ++ phy_address = (unsigned int)(ppheadlli[0]); ++ dma_debug("phy_address: 0x%X\n",phy_address); ++ address = (unsigned int)(ppheadlli[1]); ++ dma_debug("address: 0x%X\n",address); ++ for (j = 0; j < lli_num; j++) { ++ dma_debug("psource[%d]: 0x%X\n", j, psource[j]); ++ dmac_writew(address, psource[j]); ++ address += 4; ++ phy_address += 4; ++ dma_debug("pdest[%d]: 0x%X\n", j, pdest[j]); ++ dmac_writew(address, pdest[j]); ++ address += 4; ++ phy_address += 4; ++ ++ /* if the last node, next_lli_addr = 0*/ ++ if (j == (lli_num - 1)) ++ dmac_writew(address, 0); ++ else ++ dmac_writew(address, ++ (((phy_address + 8) & (~0x03)) ++ | DMAC_CxLLI_LM)); ++ ++ address += 4; ++ phy_address += 4; ++ ++ if (j == (lli_num - 1)) { ++ dmac_writew(address, ((DMAC_CxCONTROL_LLIM2M_ISP ++ &(~0xfff)) | (length[j]) ++ | 0x80000000)); ++ } else { ++ dmac_writew(address, ++ (((DMAC_CxCONTROL_LLIM2M_ISP&(~0xfff)) | ++ (length[j])) & 0x7fffffff)); ++ } ++ ++ address += 4; ++ phy_address += 4; ++ } ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(dmac_buildllim2m_isp); ++ ++/* ++ * buile LLI for memory to memory DMA transfer ++ */ ++int dmac_buildllim2m(unsigned int *ppheadlli, unsigned int pdest, ++ unsigned int psource, unsigned int totaltransfersize, ++ unsigned int uwnumtransfers) ++{ ++ unsigned int lli_num = 0; ++ unsigned int last_lli = 0; ++ unsigned int address , phy_address, srcaddr, denstaddr; ++ unsigned int j; ++ ++ lli_num = (totaltransfersize / uwnumtransfers); ++ ++ if ((totaltransfersize % uwnumtransfers) != 0) ++ last_lli = 1, ++lli_num; ++ ++ if (ppheadlli != NULL) { ++ phy_address = (unsigned int)(ppheadlli[0]); ++ address = (unsigned int)(ppheadlli[1]); ++ for (j = 0; j < lli_num; j++) { ++ srcaddr = (psource + (j*uwnumtransfers)); ++ dmac_writew(address, srcaddr); ++ address += 4; ++ phy_address += 4; ++ denstaddr = (pdest + (j*uwnumtransfers)); ++ dmac_writew(address, denstaddr); ++ address += 4; ++ phy_address += 4; ++ if (j == (lli_num - 1)) ++ dmac_writew(address, 0); ++ else ++ dmac_writew(address, ++ (((phy_address + 8) & (~0x03)) ++ | DMAC_CxLLI_LM)); ++ ++ address += 4; ++ phy_address += 4; ++ ++ if ((j == (lli_num - 1)) && (last_lli == 0)) ++ dmac_writew(address, ((DMAC_CxCONTROL_LLIM2M ++ &(~0xfff)) | (uwnumtransfers >> 2) ++ | 0x80000000)); ++ else if ((j == (lli_num - 1)) && (last_lli == 1)) ++ dmac_writew(address, ((DMAC_CxCONTROL_LLIM2M ++ & (~0xfff)) | ((totaltransfersize ++ % uwnumtransfers) >> 2) | 0x80000000)); ++ else ++ dmac_writew(address, ++ (((DMAC_CxCONTROL_LLIM2M&(~0xfff)) | ++ (uwnumtransfers >> 2)) & 0x7fffffff)); ++ ++ address += 4; ++ phy_address += 4; ++ } ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(dmac_buildllim2m); ++ ++/* ++ * disable channel ++ * used before the operation of register configuration ++ */ ++int dmac_channelclose(unsigned int channel) ++{ ++ unsigned int reg_value, count; ++ ++ if (channel >= DMAC_MAX_CHANNELS) { ++ dma_err("channel larger than total.\n"); ++ return -EINVAL; ++ } ++ ++ dmac_readw(dma_regbase + DMAC_CxCONFIG(channel), reg_value); ++ ++#define CHANNEL_CLOSE_IMMEDIATE ++#ifdef CHANNEL_CLOSE_IMMEDIATE ++ reg_value &= 0xFFFFFFFE; ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(channel) , reg_value); ++#else ++ reg_value |= DMAC_CONFIGURATIONx_HALT_DMA_ENABLE; ++ /*ignore incoming dma request*/ ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(channel), reg_value); ++ dmac_readw(dma_regbase + DMAC_CxCONFIG(channel), reg_value); ++ /*if FIFO is empty*/ ++ while ((reg_value & DMAC_CONFIGURATIONx_ACTIVE) ++ == DMAC_CONFIGURATIONx_ACTIVE) ++ dmac_readw(dma_regbase + DMAC_CxCONFIG(channel), reg_value); ++ reg_value &= 0xFFFFFFFE; ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(channel), reg_value); ++#endif ++ ++ dmac_readw(dma_regbase + DMAC_ENBLDCHNS, reg_value); ++ reg_value = reg_value & 0x00ff; ++ count = 0; ++ while (((reg_value >> channel) & 0x1) == 1) { ++ dmac_readw(dma_regbase + DMAC_ENBLDCHNS, reg_value); ++ reg_value = reg_value & 0x00ff; ++ if (count++ > 10000) { ++ dma_err("close failure.\n"); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(dmac_channelclose); ++ ++/* ++ * load configuration from LLI for memory to memory ++ */ ++int dmac_start_llim2m(unsigned int channel, unsigned int *pfirst_lli) ++{ ++ unsigned int uwchannel_num; ++ dmac_lli plli; ++ unsigned int first_lli; ++ ++ if (NULL == pfirst_lli) { ++ dma_err("Invalidate LLI head!\n"); ++ return -EFAULT; ++ } ++ ++ uwchannel_num = channel; ++ if ((uwchannel_num == DMAC_CHANNEL_INVALID) || ++ (uwchannel_num > 7)) { ++ dma_err("failure of DMAC channel allocation in"); ++ dma_err("LLIM2M function,channel=%x!\n ", uwchannel_num); ++ return -EINVAL; ++ } ++ ++ memset(&plli, 0, sizeof(plli)); ++ first_lli = (unsigned int)pfirst_lli[1]; ++ dmac_readw(first_lli, plli.src_addr); ++ dmac_readw(first_lli+4, plli.dst_addr); ++ dmac_readw(first_lli+8, plli.next_lli); ++ dmac_readw(first_lli+12, plli.lli_transfer_ctrl); ++ ++ dmac_channelclose(uwchannel_num); ++ dmac_writew(dma_regbase + DMAC_INTTCCLEAR, (0x1 << uwchannel_num)); ++ dmac_writew(dma_regbase + DMAC_INTERRCLR, (0x1 << uwchannel_num)); ++ dmac_writew(dma_regbase + DMAC_SYNC, 0x0); ++ ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(uwchannel_num), ++ DMAC_CxDISABLE); ++ dmac_writew(dma_regbase + DMAC_CxSRCADDR(uwchannel_num), ++ (unsigned int)(plli.src_addr)); ++ dmac_writew(dma_regbase + DMAC_CxDESTADDR(uwchannel_num), ++ (unsigned int)(plli.dst_addr)); ++ dmac_writew(dma_regbase + DMAC_CxLLI(uwchannel_num), ++ (unsigned int)(plli.next_lli)); ++ dmac_writew(dma_regbase + DMAC_CxCONTROL(uwchannel_num), ++ (unsigned int)(plli.lli_transfer_ctrl)); ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(uwchannel_num), ++ DMAC_CxCONFIG_LLIM2M); ++ ++ return 0; ++} ++EXPORT_SYMBOL(dmac_start_llim2m); ++ ++/* ++ * load configuration from LLI for memory and peripheral ++ */ ++int dmac_start_llim2p(unsigned int channel, unsigned int *pfirst_lli, ++ unsigned int uwperipheralid) ++{ ++ unsigned int uwchannel_num; ++ dmac_lli plli; ++ unsigned int first_lli; ++ unsigned int temp = 0; ++ ++ if (NULL == pfirst_lli) { ++ dma_err("Invalidate LLI head!\n"); ++ return -EINVAL; ++ } ++ uwchannel_num = channel; ++ if ((uwchannel_num == DMAC_CHANNEL_INVALID) || ++ (uwchannel_num > CHANNEL_NUM)) { ++ dma_err("failure of DMAC channel allocation in"); ++ dma_err("LLIM2P function, channel=%x!\n ", uwchannel_num); ++ return -EINVAL; ++ } ++ ++ memset(&plli, 0, sizeof(plli)); ++ first_lli = (unsigned int)pfirst_lli[1]; ++ dmac_readw(first_lli, plli.src_addr); ++ dmac_readw(first_lli+4, plli.dst_addr); ++ dmac_readw(first_lli+8, plli.next_lli); ++ dmac_readw(first_lli+12, plli.lli_transfer_ctrl); ++ ++ dmac_channelclose(uwchannel_num); ++ dmac_writew(dma_regbase + DMAC_INTTCCLEAR, (0x1< 15)) { ++ dma_err("Invalid peripheral id%x\n", uwperipheralid); ++ return -EINVAL; ++ } ++ ++ uwchannel_num = (int)channel; ++ if ((uwchannel_num == DMAC_CHANNEL_INVALID) ++ || (uwchannel_num > CHANNEL_NUM) || (uwchannel_num < 0)) { ++ dma_err("failure alloc\n"); ++ return -EFAULT; ++ } ++ ++ /* must modified with different peripheral */ ++ uwwidth = g_peripheral[uwperipheralid].transfer_width; ++ ++ /* check transfer direction * ++ * even number-->TX, odd number-->RX*/ ++ uwsrc_addr = memaddr; ++ uwdst_addr = (unsigned int)(g_peripheral[uwperipheralid].peri_addr); ++ ++ tmp = uwnumtransfers >> uwwidth; ++ if (tmp & (~0x0fff)) { ++ dma_err("Invalidate size%x\n", uwnumtransfers); ++ return -EINVAL; ++ } ++ ++ tmp = tmp & 0xfff; ++ uwtrans_control = tmp | ++ (g_peripheral[uwperipheralid].transfer_ctrl & (~0xfff)); ++ dmac_writew(dma_regbase + DMAC_INTTCCLEAR, (0x1<<(unsigned int)uwchannel_num)); ++ dmac_writew(dma_regbase + DMAC_INTERRCLR, (0x1<<(unsigned int)uwchannel_num)); ++ dmac_writew(dma_regbase + DMAC_CxSRCADDR(uwchannel_num), (unsigned int)uwsrc_addr); ++ dmac_writew(dma_regbase + DMAC_CxDESTADDR(uwchannel_num), (unsigned int)uwdst_addr); ++ dmac_writew(dma_regbase + DMAC_CxCONTROL(uwchannel_num), ++ (unsigned int)uwtrans_control); ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(uwchannel_num), ++ (g_peripheral[uwperipheralid].transfer_cfg)); ++ ++ return 0; ++} ++ ++/* ++ * enable memory and peripheral dma transfer ++ * note: ++ * it is necessary to call dmac_channelstart to enable channel ++ */ ++int dmac_start_p2m(unsigned int channel, unsigned int memaddr, ++ unsigned int uwperipheralid, unsigned int uwnumtransfers, ++ unsigned int next_lli_addr) ++{ ++ unsigned int uwtrans_control = 0; ++ unsigned int addtmp, tmp; ++ unsigned int uwdst_addr = 0, uwsrc_addr = 0; ++ unsigned int uwwidth; ++ int uwchannel_num; ++ ++ addtmp = memaddr; ++ ++ if ((uwperipheralid > 15)) { ++ dma_err("Invalid peripheral id%x\n", uwperipheralid); ++ return -EINVAL; ++ } ++ ++ uwchannel_num = (int)channel; ++ if ((uwchannel_num == DMAC_CHANNEL_INVALID) ++ || (uwchannel_num > 3) || (uwchannel_num < 0)) { ++ dma_err("failure alloc\n"); ++ return -EFAULT; ++ } ++ ++ /* must modified with different peripheral */ ++ uwwidth = g_peripheral[uwperipheralid].transfer_width; ++ ++ /* check transfer direction * ++ * even number-->TX, odd number-->RX*/ ++ uwsrc_addr = (unsigned int)(g_peripheral[uwperipheralid].peri_addr); ++ uwdst_addr = memaddr; ++ ++ tmp = uwnumtransfers >> uwwidth; ++ if (tmp & (~0x0fff)) { ++ dma_err("Invalidate size%x\n", uwnumtransfers); ++ return -EINVAL; ++ } ++ ++ tmp = tmp & 0xfff; ++ uwtrans_control = tmp | ++ (g_peripheral[uwperipheralid].transfer_ctrl & (~0xfff)); ++ dmac_writew(dma_regbase + DMAC_INTTCCLEAR, (0x1<<(unsigned int)uwchannel_num)); ++ dmac_writew(dma_regbase + DMAC_INTERRCLR, (0x1<<(unsigned int)uwchannel_num)); ++ dmac_writew(dma_regbase + DMAC_CxSRCADDR(uwchannel_num), ++ (unsigned int)uwsrc_addr); ++ dmac_writew(dma_regbase + DMAC_CxDESTADDR(uwchannel_num), ++ (unsigned int)uwdst_addr); ++ dmac_writew(dma_regbase + DMAC_CxCONTROL(uwchannel_num), ++ (unsigned int)uwtrans_control); ++ dmac_writew(dma_regbase + DMAC_CxCONFIG(uwchannel_num), ++ (g_peripheral[uwperipheralid].transfer_cfg)); ++ ++ return 0; ++} ++ ++/* ++ * execute memory to memory dma transfer without LLI ++ */ ++int dmac_m2m_transfer(unsigned int source, unsigned int dest, ++ unsigned int length) ++{ ++ unsigned int ulchnn, dma_size = 0; ++ unsigned int dma_count, left_size; ++ ++ left_size = length; ++ dma_count = 0; ++ ulchnn = dmac_channel_allocate(NULL); ++ ++ ulchnn = 2; ++ ++ dma_err("use channel %d\n", ulchnn); ++ ++ while ((left_size >> 2) >= 0xffc) { ++ dma_size = 0xffc; ++ left_size -= (dma_size << 2); ++ dma_err("left_size is %x.", left_size); ++ dmac_start_m2m(ulchnn, (unsigned int)(source ++ + dma_count * (dma_size << 2)), ++ (unsigned int)(dest + dma_count * (dma_size << 2)), ++ (dma_size << 2)); ++ if (dmac_channelstart(ulchnn) != 0) { ++ dma_err("start channel error...\n"); ++ return -1; ++ } ++ ++ if (dmac_wait(ulchnn) != DMAC_CHN_SUCCESS) { ++ dma_err("dma transfer error...\n"); ++ return -1; ++ } ++ ++ dma_count++; ++ } ++ ++ dmac_start_m2m(ulchnn, (source + dma_count * (dma_size << 2)), ++ (dest + dma_count * (dma_size << 2)), (left_size << 2)); ++ ++ if (dmac_channelstart(ulchnn) != 0) ++ return -1; ++ ++ if (dmac_wait(ulchnn) != DMAC_CHN_SUCCESS) ++ return -1; ++ ++ return 0; ++} ++EXPORT_SYMBOL(dmac_m2m_transfer); ++ ++/* ++ * execute memory to peripheral dma transfer without LLI ++ */ ++int dmac_m2p_transfer(unsigned int memaddr, unsigned int uwperipheralid, ++ unsigned int length) ++{ ++ unsigned int ulchnn, dma_size = 0; ++ unsigned int dma_count, left_size; ++ unsigned int uwwidth; ++ ++ left_size = length; ++ dma_count = 0; ++ ++ ulchnn = dmac_channel_allocate(NULL); ++ if (DMAC_CHANNEL_INVALID == ulchnn) ++ return -1; ++ ++ uwwidth = g_peripheral[uwperipheralid].transfer_width; ++ ++ while ((left_size >> uwwidth) >= 0xffc) { ++ dma_size = 0xffc; ++ left_size -= (dma_size << uwwidth); ++ ++ if (dmac_start_m2p(ulchnn, ++ (unsigned int)(memaddr + dma_count * dma_size), ++ uwperipheralid, (dma_size << uwwidth), 0) < 0) ++ return -1; ++ ++ if (dmac_channelstart(ulchnn) != 0) ++ return -1; ++ ++ if (dmac_wait(ulchnn) != DMAC_CHN_SUCCESS) { ++ dmac_channel_free(ulchnn); ++ return -1; ++ } ++ ++ dma_count++; ++ } ++ ++ pr_debug("memaddr=0x%x\n", (unsigned int)(memaddr ++ + dma_count * dma_size)); ++ ++ if (dmac_start_m2p(ulchnn, ++ (unsigned int)(memaddr + dma_count * dma_size), ++ uwperipheralid, left_size, 0) < 0) ++ return -1; ++ ++ if (dmac_channelstart(ulchnn) != 0) ++ return -1; ++ ++ return ulchnn; ++} ++ ++/* ++ * execute memory to peripheral dma transfer without LLI ++ */ ++int dmac_p2m_transfer(unsigned int memaddr, unsigned int uwperipheralid, ++ unsigned int length) ++{ ++ unsigned int ulchnn, dma_size = 0; ++ unsigned int dma_count, left_size; ++ unsigned int uwwidth; ++ ++ left_size = length; ++ dma_count = 0; ++ ++ ulchnn = dmac_channel_allocate(NULL); ++ if (DMAC_CHANNEL_INVALID == ulchnn) ++ return -1; ++ ++ uwwidth = g_peripheral[uwperipheralid].transfer_width; ++ ++ while ((left_size >> uwwidth) >= 0xffc) { ++ dma_size = 0xffc; ++ left_size -= (dma_size << uwwidth); ++ ++ if (dmac_start_p2m(ulchnn, ++ (unsigned int)(memaddr + dma_count * dma_size), ++ uwperipheralid, (dma_size << uwwidth), 0) < 0) ++ return -1; ++ ++ if (dmac_channelstart(ulchnn) != 0) ++ return -1; ++ ++ if (dmac_wait(ulchnn) != DMAC_CHN_SUCCESS) { ++ dmac_channel_free(ulchnn); ++ return -1; ++ } ++ ++ dma_count++; ++ } ++ ++ pr_debug("memaddr=0x%x\n", (unsigned int)(memaddr ++ + dma_count * dma_size)); ++ ++ if (dmac_start_p2m(ulchnn, ++ (unsigned int)(memaddr + dma_count * dma_size), ++ uwperipheralid, left_size, 0) < 0) ++ return -1; ++ ++ if (dmac_channelstart(ulchnn) != 0) ++ return -1; ++ ++ return ulchnn; ++} ++ ++/* ++ * memory to memory dma transfer with LLI ++ * ++ * @source ++ * @dest ++ * @length ++ * @num ++ * */ ++int do_dma_llim2m_isp(unsigned int *source, ++ unsigned int *dest, ++ unsigned int *length, ++ unsigned int num) ++{ ++ unsigned int chnn; ++ int ret = 0; ++ ++ /* the dma channel is default using 2 */ ++ chnn = 2; ++ ++ ret = dmac_buildllim2m_isp(pllihead, source, dest, length, num); ++ ++ if (ret) { ++ dma_err("build lli error...\n"); ++ return -1; ++ } ++ ++ /* dmac_register_isr(chnn, dmac_channel_close); */ ++ ret = dmac_start_llim2m(chnn, pllihead); ++ if (ret) ++ return -1; ++ ++ if (dmac_channelstart(chnn) != 0) { ++ dma_err("start channel error...\n"); ++ return -1; ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL(do_dma_llim2m_isp); ++ ++int do_dma_m2p(unsigned int memaddr, unsigned int peripheral_addr, ++ unsigned int length) ++{ ++ int ret = 0; ++ int uwperipheralid; ++ ++ uwperipheralid = dmac_check_request(peripheral_addr, TX); ++ if (uwperipheralid < 0) { ++ dma_err("m2p:Invalid devaddr\n"); ++ return -1; ++ } ++ ++ ret = dmac_m2p_transfer(memaddr, uwperipheralid, length); ++ if (ret == -1) { ++ dma_err("m2p:trans err\n"); ++ return -1; ++ } ++ ++ return ret; ++} ++ ++int do_dma_p2m(unsigned int memaddr, unsigned int peripheral_addr, ++ unsigned int length) ++{ ++ int ret = -1; ++ int uwperipheralid; ++ ++ uwperipheralid = dmac_check_request(peripheral_addr, RX); ++ if (uwperipheralid < 0) { ++ dma_err("p2m:Invalid devaddr.\n"); ++ return -1; ++ } ++ ++ ret = dmac_p2m_transfer(memaddr, uwperipheralid, length); ++ if (ret == -1) { ++ dma_err("p2m:trans err\n"); ++ return -1; ++ } ++ ++ return ret; ++} ++ ++/* ++ * Apply DMA interrupt resource ++ * init channel state ++ */ ++static int hi_dmac_probe(struct platform_device *platdev) ++{ ++ unsigned int i; ++ struct hidmac_host *dma; ++ struct resource *res; ++ int ret; ++ ++ dma = devm_kzalloc(&platdev->dev, sizeof(*dma), GFP_KERNEL); ++ if (!dma) ++ return -ENOMEM; ++ ++ res = platform_get_resource(platdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&platdev->dev, "no mmio resource\n"); ++ return -ENODEV; ++ } ++ ++ dma->regbase = devm_ioremap_resource(&platdev->dev, res); ++ if (IS_ERR(dma->regbase)) ++ return PTR_ERR(dma->regbase); ++ ++ dma->clk = devm_clk_get(&platdev->dev, NULL); ++ if (IS_ERR(dma->clk)) ++ return PTR_ERR(dma->clk); ++ ++ dma->rstc = devm_reset_control_get(&platdev->dev, "dma-reset"); ++ if (IS_ERR(dma->rstc)) ++ return PTR_ERR(dma->rstc); ++ ++ dma->irq = platform_get_irq(platdev, 0); ++ if (unlikely(dma->irq < 0)) ++ return -ENODEV; ++ ++ dma_regbase = dma->regbase; ++ ++ ret = dmac_init(dma); ++ if (ret) ++ return -ENODEV; ++ ++ platform_set_drvdata(platdev, dma); ++ ++ for (i = 0; i < DMAC_MAX_CHANNELS; i++) ++ g_channel_status[i] = DMAC_CHN_VACANCY; ++ ++ return ret; ++} ++ ++static int hi_dmac_remove(struct platform_device *platdev) ++{ ++ int i; ++ struct hidmac_host *dma = platform_get_drvdata(platdev); ++ ++ clk_disable_unprepare(dma->clk); ++ ++ for (i = 0; i < DMAC_MAX_CHANNELS; i++) ++ g_channel_status[i] = DMAC_CHN_VACANCY; ++ ++ free_dmalli_space(pllihead, 1); ++ ++ return 0; ++} ++ ++static int hi_dmac_suspend(struct platform_device *platdev, ++ pm_message_t state) ++{ ++ int i; ++ struct hidmac_host *dma = platform_get_drvdata(platdev); ++ ++ clk_prepare_enable(dma->clk); ++ ++ for (i = 0; i < DMAC_MAX_CHANNELS; i++) ++ g_channel_status[i] = DMAC_CHN_VACANCY; ++ ++ clk_disable_unprepare(dma->clk); ++ ++ return 0; ++} ++ ++static int hi_dmac_resume(struct platform_device *platdev) ++{ ++ int i; ++ struct hidmac_host *dma = platform_get_drvdata(platdev); ++ unsigned int tempvalue; ++ ++ clk_prepare_enable(dma->clk); ++ reset_control_deassert(dma->rstc); ++ ++ dmac_readw(dma->regbase + DMAC_CONFIG, tempvalue); ++ if (tempvalue == 0) { ++ dmac_writew(dma->regbase + DMAC_CONFIG, ++ DMAC_CONFIG_VAL); ++ dmac_writew(dma->regbase + DMAC_INTTCCLEAR, 0xFF); ++ dmac_writew(dma->regbase + DMAC_INTERRCLR, 0xFF); ++ for (i = 0; i < DMAC_MAX_CHANNELS; i++) { ++ dmac_writew(dma->regbase + DMAC_CxCONFIG(i), ++ DMAC_CxDISABLE); ++ function[i] = NULL; ++ } ++ } ++ ++ for (i = 0; i < DMAC_MAX_CHANNELS; i++) ++ g_channel_status[i] = DMAC_CHN_VACANCY; ++ ++ return 0; ++} ++ ++static const struct of_device_id hisi_dmac_dt_ids[] = { ++ { .compatible = "hisilicon,hisi-dmac"}, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, hisi_dmac_dt_ids); ++ ++static struct platform_driver hisi_dmac_driver = { ++ .driver = { ++ .name = "hisi-dmac", ++ .of_match_table = hisi_dmac_dt_ids, ++ }, ++ .probe = hi_dmac_probe, ++ .remove = hi_dmac_remove, ++ .suspend = hi_dmac_suspend, ++ .resume = hi_dmac_resume, ++}; ++ ++module_platform_driver(hisi_dmac_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Hisilicon"); ++MODULE_DESCRIPTION("HiSilicon DMA Controller driver"); +diff --git a/drivers/hidmac/hidmac_hi3516av200.c b/drivers/hidmac/hidmac_hi3516av200.c +new file mode 100644 +index 0000000..cf9132a +--- /dev/null ++++ b/drivers/hidmac/hidmac_hi3516av200.c +@@ -0,0 +1,90 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define SYS_CRG_BASE IO_ADDRESS(0x12010000) ++#define REG_PERI_CRG56 0xe0 ++#define DMAC_CLK_EN (1 << 1) ++#define DMAC_SRST_REQ (1 << 0) ++ ++/* ++ * DMA config array! ++ * DREQ, FIFO, CONTROL, CONFIG, BITWIDTH ++ */ ++dmac_peripheral g_peripheral[DMAC_MAX_PERIPHERALS] = { ++ /* periphal 0: UART0 RX, 8bit width */ ++ {0, UART0_DATA_REG, 0x99000000, 0xd000, 0}, ++ ++ /* periphal 1: UART0 TX, 8bit width */ ++ {1, UART0_DATA_REG, 0x96000000, 0xc840, 0}, ++ ++ /*periphal 2: UART1 RX, 8bit width */ ++ {2, UART1_DATA_REG, 0x99000000, 0xd004, 0}, ++ ++ /*periphal 3: UART1 TX, 8bit width */ ++ {3, UART1_DATA_REG, 0x96000000, 0xc8c0, 0}, ++ ++ /*periphal 4: UART2 RX, 8bit width */ ++ {4, UART2_DATA_REG, 0x99000000, 0xd008, 0}, ++ ++ /*periphal 5: UART2 TX, 8bit width */ ++ {5, UART2_DATA_REG, 0x96000000, 0xc940, 0}, ++ ++ /*periphal 6: UART3 RX, 8bit width */ ++ {6, UART3_DATA_REG, 0x99000000, 0xd00c, 0}, ++ ++ /*periphal 7: UART3 TX, 8bit width */ ++ {7, UART3_DATA_REG, 0x96000000, 0xc9c0, 0}, ++ ++ /*periphal 8: I2C0 RX, 8bit width */ ++ {8, I2C0_DATA_REG, 0x99000000, 0xd010, 0}, ++ ++ /*periphal 9: I2C0 TX, 8bit width */ ++ {9, I2C0_DATA_REG, 0x96000000, 0xca40, 0}, ++ ++ /*periphal 10: I2C1 RX, 8bit width */ ++ {10, I2C1_DATA_REG, 0x99000000, 0xd014, 0}, ++ ++ /*periphal 11: I2C1 TX, 8bit width */ ++ {11, I2C1_DATA_REG, 0x96000000, 0xcac0, 0}, ++ ++ /*periphal 12: I2C2 RX, 8bit width */ ++ {12, SPI2_DATA_REG, 0x99000000, 0xd018, 0}, ++ ++ /*periphal 13: I2C2 TX, 8bit width */ ++ {13, SPI2_DATA_REG, 0x96000000, 0xcb40, 0}, ++ ++ /*periphal 14: I2C3 RX, 8bit width */ ++ {14, I2C2_DATA_REG, 0x99000000, 0xd01c, 0}, ++ ++ /*periphal 15: I2C3 TX, 8bit width */ ++ {15, I2C2_DATA_REG, 0x96000000, 0xcbc0, 0}, ++}; ++ ++void hidmac_clk_en(void) ++{ ++ unsigned int tmp; ++ ++ dmac_readw(SYS_CRG_BASE + REG_PERI_CRG56, tmp); ++ tmp |= DMAC_CLK_EN; ++ dmac_writew(SYS_CRG_BASE + REG_PERI_CRG56, tmp); ++} ++ ++void hidmac_unreset(void) ++{ ++ unsigned int tmp; ++ ++ dmac_readw(SYS_CRG_BASE + REG_PERI_CRG56, tmp); ++ tmp &= ~DMAC_SRST_REQ; ++ dmac_writew(SYS_CRG_BASE + REG_PERI_CRG56, tmp); ++} +diff --git a/drivers/hidmac/hidmac_hi3516av200.h b/drivers/hidmac/hidmac_hi3516av200.h +new file mode 100644 +index 0000000..a0e7beb +--- /dev/null ++++ b/drivers/hidmac/hidmac_hi3516av200.h +@@ -0,0 +1,99 @@ ++#ifndef __HI_DMAC_HI3516AV200_H__ ++#define __HI_DMAC_HI3516AV200_H__ ++ ++#define DDRAM_ADRS 0x80000000 /* fixed */ ++#define DDRAM_SIZE 0x3FFFFFFF /* 1GB DDR. */ ++ ++#define FLASH_BASE 0x10000000 ++#define FLASH_SIZE 0x04000000 /* (32MB) */ ++ ++#define DMAC_BASE_REG CONFIG_HI_DMAC_IO_BASE ++#define DMAC_INTTCCLEAR IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X08) ++ ++#define DMAC_INTSTATUS IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X00) ++#define DMAC_INTTCSTATUS IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X04) ++#define DMAC_INTERRORSTATUS IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X0C) ++ ++#define DMAC_INTERRCLR IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X10) ++#define DMAC_RAWINTTCSTATUS IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X14) ++#define DMAC_RAWINTERRORSTATUS IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X18) ++#define DMAC_ENBLDCHNS IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X1C) ++#define DMAC_CONFIG IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X30) ++#define DMAC_SYNC IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X34) ++ ++#define DMAC_MAXTRANSFERSIZE 0x0fff /*the max length is denoted by 0-11bit*/ ++#define MAXTRANSFERSIZE DMAC_MAXTRANSFERSIZE ++#define DMAC_CxDISABLE 0x00 ++#define DMAC_CxENABLE 0x01 ++ ++/*the definition for DMAC channel register*/ ++#define DMAC_CxBASE(i) IO_DMAC_ADDRESS(DMAC_BASE_REG + 0x100+i*0x20) ++#define DMAC_CxSRCADDR(i) DMAC_CxBASE(i) ++#define DMAC_CxDESTADDR(i) (DMAC_CxBASE(i)+0x04) ++#define DMAC_CxLLI(i) (DMAC_CxBASE(i)+0x08) ++#define DMAC_CxCONTROL(i) (DMAC_CxBASE(i)+0x0C) ++#define DMAC_CxCONFIG(i) (DMAC_CxBASE(i)+0x10) ++ ++/*the means the bit in the channel control register*/ ++#define DMAC_CxCONTROL_M2M 0x9d480000 /* Dwidth=32,burst size=4 */ ++#define DMAC_CxCONTROL_LLIM2M 0x0f480000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxLLI_LM 0x01 ++ ++#define DMAC_CxCONFIG_M2M 0xc000 ++#define DMAC_CxCONFIG_LLIM2M 0xc000 ++ ++/*#define DMAC_CxCONFIG_M2M 0x4001*/ ++#define DMAC_CHANNEL_ENABLE 1 ++#define DMAC_CHANNEL_DISABLE 0xfffffffe ++ ++#define DMAC_CxCONTROL_P2M 0x89409000 ++#define DMAC_CxCONFIG_P2M 0xd000 ++ ++#define DMAC_CxCONTROL_M2P 0x86089000 ++#define DMAC_CxCONFIG_M2P 0xc800 ++ ++#define DMAC_CxCONFIG_SIO_P2M 0x0000d000 ++#define DMAC_CxCONFIG_SIO_M2P 0x0000c800 ++ ++/*default the config and sync regsiter for DMAC controller*/ ++/*M1,M2 little endian, enable DMAC*/ ++#define DMAC_CONFIG_VAL 0x01 ++/*enable the sync logic for the 16 peripheral*/ ++#define DMAC_SYNC_VAL 0x0 ++ ++#define DMAC_MAX_PERIPHERALS 16 ++#define MEM_MAX_NUM 2 ++#define CHANNEL_NUM CONFIG_HI_DMAC_CHANNEL_NUM ++#define DMAC_MAX_CHANNELS CHANNEL_NUM ++ ++#define REG_BASE_UART0 0x12100000 ++#define UART0_DATA_REG (REG_BASE_UART0 + 0x0) ++ ++#define REG_BASE_UART1 0x12101000 ++#define UART1_DATA_REG (REG_BASE_UART1 + 0x0) ++ ++#define REG_BASE_UART2 0x12102000 ++#define UART2_DATA_REG (REG_BASE_UART2 + 0x0) ++ ++#define REG_BASE_UART3 0x12103000 ++#define UART3_DATA_REG (REG_BASE_UART3 + 0x0) ++ ++#define REG_BASE_I2C0 0x12110000 ++#define I2C0_DATA_REG (REG_BASE_I2C0 + 0x10) ++ ++#define REG_BASE_I2C1 0x12111000 ++#define I2C1_DATA_REG (REG_BASE_I2C1 + 0x10) ++ ++#define REG_BASE_I2C2 0x12112000 ++#define I2C2_DATA_REG (REG_BASE_I2C2 + 0x10) ++ ++#define REG_BASE_I2C3 0x12113000 ++#define I2C3_DATA_REG (REG_BASE_I2C3 + 0x10) ++ ++#define REG_BASE_SPI2 0x12122000 ++#define SPI2_DATA_REG (REG_BASE_SPI2 + 0x8) ++ ++/*the transfer control and configuration value for different peripheral*/ ++ ++extern int g_channel_status[CHANNEL_NUM]; ++#endif +diff --git a/drivers/hidmac/hidmac_hi3516cv300.h b/drivers/hidmac/hidmac_hi3516cv300.h +new file mode 100644 +index 0000000..61fbf09 +--- /dev/null ++++ b/drivers/hidmac/hidmac_hi3516cv300.h +@@ -0,0 +1,139 @@ ++#ifndef __HI_DMAC_HI3516CV300_H__ ++#define __HI_DMAC_HI3516CV300_H__ ++ ++#define DDRAM_ADRS 0x80000000 /* fixed */ ++#define DDRAM_SIZE 0x3FFFFFFF /* 1GB DDR. */ ++ ++#define FLASH_BASE 0x10000000 ++#define FLASH_SIZE 0x04000000 /* (32MB) */ ++ ++#define DMAC_INTSTATUS 0X00 ++#define DMAC_INTTCSTATUS 0X04 ++#define DMAC_INTTCCLEAR 0X08 ++#define DMAC_INTERRORSTATUS 0X0C ++ ++#define DMAC_INTERRCLR 0X10 ++#define DMAC_RAWINTTCSTATUS 0X14 ++#define DMAC_RAWINTERRORSTATUS 0X18 ++#define DMAC_ENBLDCHNS 0X1C ++#define DMAC_CONFIG 0X30 ++#define DMAC_SYNC 0X34 ++ ++#define DMAC_MAXTRANSFERSIZE 0x0fff /*the max length is denoted by 0-11bit*/ ++#define MAXTRANSFERSIZE DMAC_MAXTRANSFERSIZE ++#define DMAC_CxDISABLE 0x00 ++#define DMAC_CxENABLE 0x01 ++ ++/*the definition for DMAC channel register*/ ++#define DMAC_CxBASE(i) (0x100+i*0x20) ++#define DMAC_CxSRCADDR(i) DMAC_CxBASE(i) ++#define DMAC_CxDESTADDR(i) (DMAC_CxBASE(i)+0x04) ++#define DMAC_CxLLI(i) (DMAC_CxBASE(i)+0x08) ++#define DMAC_CxCONTROL(i) (DMAC_CxBASE(i)+0x0C) ++#define DMAC_CxCONFIG(i) (DMAC_CxBASE(i)+0x10) ++ ++/*the means the bit in the channel control register*/ ++#define DMAC_CxCONTROL_M2M 0x9d480000 /* Dwidth=32,burst size=4 */ ++#define DMAC_CxCONTROL_LLIM2M 0x0f480000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxCONTROL_LLIM2M_ISP 0x0b489000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxLLI_LM 0x01 ++ ++#define NUM_HAL_INTERRUPT_DMAC (14 + 16) ++ ++#define DMAC_CxCONFIG_M2M 0xc000 ++#define DMAC_CxCONFIG_LLIM2M 0xc000 ++ ++/*#define DMAC_CxCONFIG_M2M 0x4001*/ ++#define DMAC_CHANNEL_ENABLE 1 ++#define DMAC_CHANNEL_DISABLE 0xfffffffe ++ ++#define DMAC_CxCONTROL_P2M 0x89409000 ++#define DMAC_CxCONFIG_P2M 0xd000 ++ ++#define DMAC_CxCONTROL_M2P 0x86089000 ++#define DMAC_CxCONFIG_M2P 0xc800 ++ ++#define DMAC_CxCONFIG_SIO_P2M 0x0000d000 ++#define DMAC_CxCONFIG_SIO_M2P 0x0000c800 ++ ++/*default the config and sync regsiter for DMAC controller*/ ++/*M1,M2 little endian, enable DMAC*/ ++#define DMAC_CONFIG_VAL 0x01 ++/*enable the sync logic for the 16 peripheral*/ ++#define DMAC_SYNC_VAL 0x0 ++ ++#define DMAC_MAX_PERIPHERALS 16 ++#define MEM_MAX_NUM 2 ++#define CHANNEL_NUM CONFIG_HI_DMAC_CHANNEL_NUM ++#define DMAC_MAX_CHANNELS CHANNEL_NUM ++ ++#define REG_BASE_I2C0 0x12110000 ++#define I2C0_DATA_REG (REG_BASE_I2C0 + 0x14) ++ ++#define REG_BASE_I2C1 0x12112000 ++#define I2C1_DATA_REG (REG_BASE_I2C1 + 0x14) ++ ++#define REG_BASE_UART0 0x12100000 ++#define UART0_DATA_REG (REG_BASE_UART0 + 0x0) ++ ++#define REG_BASE_UART1 0x12101000 ++#define UART1_DATA_REG (REG_BASE_UART1 + 0x0) ++ ++#define REG_BASE_UART2 0x12102000 ++#define UART2_DATA_REG (REG_BASE_UART2 + 0x0) ++ ++#define REG_BASE_SPI0 0x12110000 ++#define SPI0_DATA_REG (REG_BASE_SPI0 + 0x8) ++ ++#define REG_BASE_SPI1 0x12121000 ++#define SPI1_DATA_REG (REG_BASE_SPI1 + 0x8) ++ ++/*the transfer control and configuration value for different peripheral*/ ++ ++extern int g_channel_status[CHANNEL_NUM]; ++ ++dmac_peripheral g_peripheral[DMAC_MAX_PERIPHERALS] = { ++ /*periphal 0: I2C0 RX, 8bit width */ ++ {0, I2C0_DATA_REG, 0x99000000, 0xd010, 0}, ++ ++ /*periphal 1: I2C0 TX, 8bit width */ ++ {1, I2C0_DATA_REG, 0x96000000, 0xca40, 0}, ++ ++ /*periphal 4: I2C1 RX, 8bit width */ ++ {4, I2C1_DATA_REG, 0x99000000, 0xd014, 0}, ++ ++ /*periphal 5: I2C1 TX, 8bit width */ ++ {5, I2C1_DATA_REG, 0x96000000, 0xcac0, 0}, ++ ++ /*periphal 6: UART0 RX, 8bit width */ ++ {6, UART0_DATA_REG, 0x99000000, 0xd000, 0}, ++ ++ /*periphal 7: UART0 TX, 8bit width */ ++ {7, UART0_DATA_REG, 0x96000000, 0xc840, 0}, ++ ++ /*periphal 8: UART1 RX, 8bit width */ ++ {8, UART1_DATA_REG, 0x99000000, 0xd004, 0}, ++ ++ /*periphal 9: UART1 TX, 8bit width */ ++ {9, UART1_DATA_REG, 0x96000000, 0xc8c0, 0}, ++ ++ /*periphal 10: UART2 RX, 8bit width */ ++ {10, UART2_DATA_REG, 0x99000000, 0xd008, 0}, ++ ++ /*periphal 11: UART2 TX, 8bit width */ ++ {11, UART2_DATA_REG, 0x96000000, 0xc940, 0}, ++ ++ /*periphal 12: I2C2 RX, 8bit width */ ++ {12, SPI0_DATA_REG, 0x99000000, 0xd018, 0}, ++ ++ /*periphal 13: I2C2 TX, 8bit width */ ++ {13, SPI0_DATA_REG, 0x96000000, 0xcb40, 0}, ++ ++ /*periphal 14: I2C3 RX, 8bit width */ ++ {14, SPI1_DATA_REG, 0x99000000, 0xd01c, 0}, ++ ++ /*periphal 15: I2C3 TX, 8bit width */ ++ {15, SPI1_DATA_REG, 0x96000000, 0xcbc0, 0}, ++}; ++ ++#endif +diff --git a/drivers/hidmac/hidmac_hi3519.c b/drivers/hidmac/hidmac_hi3519.c +new file mode 100644 +index 0000000..c1f0234 +--- /dev/null ++++ b/drivers/hidmac/hidmac_hi3519.c +@@ -0,0 +1,90 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define SYS_CRG_BASE IO_ADDRESS(0x12010000) ++#define REG_PERI_CRG56 0xe0 ++#define DMAC_CLK_EN (1 << 1) ++#define DMAC_SRST_REQ (1 << 0) ++ ++/* ++ * DMA config array! ++ * DREQ, FIFO, CONTROL, CONFIG, BITWIDTH ++ */ ++dmac_peripheral g_peripheral[DMAC_MAX_PERIPHERALS] = { ++ /* periphal 0: UART0 RX, 8bit width */ ++ {0, UART0_DATA_REG, 0x99000000, 0xd000, 0}, ++ ++ /* periphal 1: UART0 TX, 8bit width */ ++ {1, UART0_DATA_REG, 0x96000000, 0xc840, 0}, ++ ++ /*periphal 2: UART1 RX, 8bit width */ ++ {2, UART1_DATA_REG, 0x99000000, 0xd004, 0}, ++ ++ /*periphal 3: UART1 TX, 8bit width */ ++ {3, UART1_DATA_REG, 0x96000000, 0xc8c0, 0}, ++ ++ /*periphal 4: UART2 RX, 8bit width */ ++ {4, UART2_DATA_REG, 0x99000000, 0xd008, 0}, ++ ++ /*periphal 5: UART2 TX, 8bit width */ ++ {5, UART2_DATA_REG, 0x96000000, 0xc940, 0}, ++ ++ /*periphal 6: UART3 RX, 8bit width */ ++ {6, UART3_DATA_REG, 0x99000000, 0xd00c, 0}, ++ ++ /*periphal 7: UART3 TX, 8bit width */ ++ {7, UART3_DATA_REG, 0x96000000, 0xc9c0, 0}, ++ ++ /*periphal 8: I2C0 RX, 8bit width */ ++ {8, I2C0_DATA_REG, 0x99000000, 0xd010, 0}, ++ ++ /*periphal 9: I2C0 TX, 8bit width */ ++ {9, I2C0_DATA_REG, 0x96000000, 0xca40, 0}, ++ ++ /*periphal 10: I2C1 RX, 8bit width */ ++ {10, I2C1_DATA_REG, 0x99000000, 0xd014, 0}, ++ ++ /*periphal 11: I2C1 TX, 8bit width */ ++ {11, I2C1_DATA_REG, 0x96000000, 0xcac0, 0}, ++ ++ /*periphal 12: I2C2 RX, 8bit width */ ++ {12, I2C2_DATA_REG, 0x99000000, 0xd018, 0}, ++ ++ /*periphal 13: I2C2 TX, 8bit width */ ++ {13, I2C2_DATA_REG, 0x96000000, 0xcb40, 0}, ++ ++ /*periphal 14: I2C3 RX, 8bit width */ ++ {14, I2C3_DATA_REG, 0x99000000, 0xd01c, 0}, ++ ++ /*periphal 15: I2C3 TX, 8bit width */ ++ {15, I2C3_DATA_REG, 0x96000000, 0xcbc0, 0}, ++}; ++ ++void hidmac_clk_en(void) ++{ ++ unsigned int tmp; ++ ++ dmac_readw(SYS_CRG_BASE + REG_PERI_CRG56, tmp); ++ tmp |= DMAC_CLK_EN; ++ dmac_writew(SYS_CRG_BASE + REG_PERI_CRG56, tmp); ++} ++ ++void hidmac_unreset(void) ++{ ++ unsigned int tmp; ++ ++ dmac_readw(SYS_CRG_BASE + REG_PERI_CRG56, tmp); ++ tmp &= ~DMAC_SRST_REQ; ++ dmac_writew(SYS_CRG_BASE + REG_PERI_CRG56, tmp); ++} +diff --git a/drivers/hidmac/hidmac_hi3519.h b/drivers/hidmac/hidmac_hi3519.h +new file mode 100644 +index 0000000..edd7e0a +--- /dev/null ++++ b/drivers/hidmac/hidmac_hi3519.h +@@ -0,0 +1,99 @@ ++#ifndef __HI_DMAC_HI3519_H__ ++#define __HI_DMAC_HI3519_H__ ++ ++#define DDRAM_ADRS 0x80000000 /* fixed */ ++#define DDRAM_SIZE 0x3FFFFFFF /* 1GB DDR. */ ++ ++#define FLASH_BASE 0x10000000 ++#define FLASH_SIZE 0x04000000 /* (32MB) */ ++ ++#define DMAC_BASE_REG CONFIG_HI_DMAC_IO_BASE ++#define DMAC_INTTCCLEAR IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X08) ++ ++#define DMAC_INTSTATUS IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X00) ++#define DMAC_INTTCSTATUS IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X04) ++#define DMAC_INTERRORSTATUS IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X0C) ++ ++#define DMAC_INTERRCLR IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X10) ++#define DMAC_RAWINTTCSTATUS IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X14) ++#define DMAC_RAWINTERRORSTATUS IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X18) ++#define DMAC_ENBLDCHNS IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X1C) ++#define DMAC_CONFIG IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X30) ++#define DMAC_SYNC IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X34) ++ ++#define DMAC_MAXTRANSFERSIZE 0x0fff /*the max length is denoted by 0-11bit*/ ++#define MAXTRANSFERSIZE DMAC_MAXTRANSFERSIZE ++#define DMAC_CxDISABLE 0x00 ++#define DMAC_CxENABLE 0x01 ++ ++/*the definition for DMAC channel register*/ ++#define DMAC_CxBASE(i) IO_DMAC_ADDRESS(DMAC_BASE_REG + 0x100+i*0x20) ++#define DMAC_CxSRCADDR(i) DMAC_CxBASE(i) ++#define DMAC_CxDESTADDR(i) (DMAC_CxBASE(i)+0x04) ++#define DMAC_CxLLI(i) (DMAC_CxBASE(i)+0x08) ++#define DMAC_CxCONTROL(i) (DMAC_CxBASE(i)+0x0C) ++#define DMAC_CxCONFIG(i) (DMAC_CxBASE(i)+0x10) ++ ++/*the means the bit in the channel control register*/ ++#define DMAC_CxCONTROL_M2M 0x9d480000 /* Dwidth=32,burst size=4 */ ++#define DMAC_CxCONTROL_LLIM2M 0x0f480000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxLLI_LM 0x01 ++ ++#define DMAC_CxCONFIG_M2M 0xc000 ++#define DMAC_CxCONFIG_LLIM2M 0xc000 ++ ++/*#define DMAC_CxCONFIG_M2M 0x4001*/ ++#define DMAC_CHANNEL_ENABLE 1 ++#define DMAC_CHANNEL_DISABLE 0xfffffffe ++ ++#define DMAC_CxCONTROL_P2M 0x89409000 ++#define DMAC_CxCONFIG_P2M 0xd000 ++ ++#define DMAC_CxCONTROL_M2P 0x86089000 ++#define DMAC_CxCONFIG_M2P 0xc800 ++ ++#define DMAC_CxCONFIG_SIO_P2M 0x0000d000 ++#define DMAC_CxCONFIG_SIO_M2P 0x0000c800 ++ ++/*default the config and sync regsiter for DMAC controller*/ ++/*M1,M2 little endian, enable DMAC*/ ++#define DMAC_CONFIG_VAL 0x01 ++/*enable the sync logic for the 16 peripheral*/ ++#define DMAC_SYNC_VAL 0x0 ++ ++#define DMAC_MAX_PERIPHERALS 16 ++#define MEM_MAX_NUM 2 ++#define CHANNEL_NUM CONFIG_HI_DMAC_CHANNEL_NUM ++#define DMAC_MAX_CHANNELS CHANNEL_NUM ++ ++#define REG_BASE_UART0 0x12100000 ++#define UART0_DATA_REG (REG_BASE_UART0 + 0x0) ++ ++#define REG_BASE_UART1 0x12101000 ++#define UART1_DATA_REG (REG_BASE_UART1 + 0x0) ++ ++#define REG_BASE_UART2 0x12102000 ++#define UART2_DATA_REG (REG_BASE_UART2 + 0x0) ++ ++#define REG_BASE_UART3 0x12103000 ++#define UART3_DATA_REG (REG_BASE_UART3 + 0x0) ++ ++#define REG_BASE_I2C0 0x12110000 ++#define I2C0_DATA_REG (REG_BASE_I2C0 + 0x10) ++ ++#define REG_BASE_I2C1 0x12111000 ++#define I2C1_DATA_REG (REG_BASE_I2C1 + 0x10) ++ ++#define REG_BASE_I2C2 0x12112000 ++#define I2C2_DATA_REG (REG_BASE_I2C2 + 0x10) ++ ++#define REG_BASE_I2C3 0x12113000 ++#define I2C3_DATA_REG (REG_BASE_I2C3 + 0x10) ++ ++#define REG_BASE_SPI2 0x12122000 ++#define SPI2_DATA_REG (REG_BASE_SPI2 + 0x8) ++ ++/*the transfer control and configuration value for different peripheral*/ ++ ++extern int g_channel_status[CHANNEL_NUM]; ++#endif +diff --git a/drivers/hidmac/hidmac_hi3519v101.c b/drivers/hidmac/hidmac_hi3519v101.c +new file mode 100644 +index 0000000..cf9132a +--- /dev/null ++++ b/drivers/hidmac/hidmac_hi3519v101.c +@@ -0,0 +1,90 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define SYS_CRG_BASE IO_ADDRESS(0x12010000) ++#define REG_PERI_CRG56 0xe0 ++#define DMAC_CLK_EN (1 << 1) ++#define DMAC_SRST_REQ (1 << 0) ++ ++/* ++ * DMA config array! ++ * DREQ, FIFO, CONTROL, CONFIG, BITWIDTH ++ */ ++dmac_peripheral g_peripheral[DMAC_MAX_PERIPHERALS] = { ++ /* periphal 0: UART0 RX, 8bit width */ ++ {0, UART0_DATA_REG, 0x99000000, 0xd000, 0}, ++ ++ /* periphal 1: UART0 TX, 8bit width */ ++ {1, UART0_DATA_REG, 0x96000000, 0xc840, 0}, ++ ++ /*periphal 2: UART1 RX, 8bit width */ ++ {2, UART1_DATA_REG, 0x99000000, 0xd004, 0}, ++ ++ /*periphal 3: UART1 TX, 8bit width */ ++ {3, UART1_DATA_REG, 0x96000000, 0xc8c0, 0}, ++ ++ /*periphal 4: UART2 RX, 8bit width */ ++ {4, UART2_DATA_REG, 0x99000000, 0xd008, 0}, ++ ++ /*periphal 5: UART2 TX, 8bit width */ ++ {5, UART2_DATA_REG, 0x96000000, 0xc940, 0}, ++ ++ /*periphal 6: UART3 RX, 8bit width */ ++ {6, UART3_DATA_REG, 0x99000000, 0xd00c, 0}, ++ ++ /*periphal 7: UART3 TX, 8bit width */ ++ {7, UART3_DATA_REG, 0x96000000, 0xc9c0, 0}, ++ ++ /*periphal 8: I2C0 RX, 8bit width */ ++ {8, I2C0_DATA_REG, 0x99000000, 0xd010, 0}, ++ ++ /*periphal 9: I2C0 TX, 8bit width */ ++ {9, I2C0_DATA_REG, 0x96000000, 0xca40, 0}, ++ ++ /*periphal 10: I2C1 RX, 8bit width */ ++ {10, I2C1_DATA_REG, 0x99000000, 0xd014, 0}, ++ ++ /*periphal 11: I2C1 TX, 8bit width */ ++ {11, I2C1_DATA_REG, 0x96000000, 0xcac0, 0}, ++ ++ /*periphal 12: I2C2 RX, 8bit width */ ++ {12, SPI2_DATA_REG, 0x99000000, 0xd018, 0}, ++ ++ /*periphal 13: I2C2 TX, 8bit width */ ++ {13, SPI2_DATA_REG, 0x96000000, 0xcb40, 0}, ++ ++ /*periphal 14: I2C3 RX, 8bit width */ ++ {14, I2C2_DATA_REG, 0x99000000, 0xd01c, 0}, ++ ++ /*periphal 15: I2C3 TX, 8bit width */ ++ {15, I2C2_DATA_REG, 0x96000000, 0xcbc0, 0}, ++}; ++ ++void hidmac_clk_en(void) ++{ ++ unsigned int tmp; ++ ++ dmac_readw(SYS_CRG_BASE + REG_PERI_CRG56, tmp); ++ tmp |= DMAC_CLK_EN; ++ dmac_writew(SYS_CRG_BASE + REG_PERI_CRG56, tmp); ++} ++ ++void hidmac_unreset(void) ++{ ++ unsigned int tmp; ++ ++ dmac_readw(SYS_CRG_BASE + REG_PERI_CRG56, tmp); ++ tmp &= ~DMAC_SRST_REQ; ++ dmac_writew(SYS_CRG_BASE + REG_PERI_CRG56, tmp); ++} +diff --git a/drivers/hidmac/hidmac_hi3521d.h b/drivers/hidmac/hidmac_hi3521d.h +new file mode 100644 +index 0000000..67877ff +--- /dev/null ++++ b/drivers/hidmac/hidmac_hi3521d.h +@@ -0,0 +1,120 @@ ++#ifndef __HI_DMAC_HI3521D_H__ ++#define __HI_DMAC_HI3521D_H__ ++ ++#define DDRAM_ADRS 0x80000000 /* fixed */ ++#define DDRAM_SIZE 0x1FFFFFFF /* 512M DDR. */ ++ ++#define FLASH_BASE 0x10000000 ++#define FLASH_SIZE 0x04000000 /* (32MB) */ ++ ++#define DMAC_INTSTATUS 0X00 ++#define DMAC_INTTCSTATUS 0X04 ++#define DMAC_INTTCCLEAR 0X08 ++#define DMAC_INTERRORSTATUS 0X0C ++ ++#define DMAC_INTERRCLR 0X10 ++#define DMAC_RAWINTTCSTATUS 0X14 ++#define DMAC_RAWINTERRORSTATUS 0X18 ++#define DMAC_ENBLDCHNS 0X1C ++#define DMAC_CONFIG 0X30 ++#define DMAC_SYNC 0X34 ++ ++#define DMAC_MAXTRANSFERSIZE 0x0fff /*the max length is denoted by 0-11bit*/ ++#define MAXTRANSFERSIZE DMAC_MAXTRANSFERSIZE ++#define DMAC_CxDISABLE 0x00 ++#define DMAC_CxENABLE 0x01 ++ ++/*the definition for DMAC channel register*/ ++#define DMAC_CxBASE(i) (0x100+i*0x20) ++#define DMAC_CxSRCADDR(i) DMAC_CxBASE(i) ++#define DMAC_CxDESTADDR(i) (DMAC_CxBASE(i)+0x04) ++#define DMAC_CxLLI(i) (DMAC_CxBASE(i)+0x08) ++#define DMAC_CxCONTROL(i) (DMAC_CxBASE(i)+0x0C) ++#define DMAC_CxCONFIG(i) (DMAC_CxBASE(i)+0x10) ++ ++/*the means the bit in the channel control register*/ ++#define DMAC_CxCONTROL_M2M 0x9d480000 /* Dwidth=32,burst size=4 */ ++#define DMAC_CxCONTROL_LLIM2M 0x0f480000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxCONTROL_LLIM2M_ISP 0x0b489000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxLLI_LM 0x01 ++ ++#define NUM_HAL_INTERRUPT_DMAC (14 + 16) ++ ++#define DMAC_CxCONFIG_M2M 0xc000 ++#define DMAC_CxCONFIG_LLIM2M 0xc000 ++ ++/*#define DMAC_CxCONFIG_M2M 0x4001*/ ++#define DMAC_CHANNEL_ENABLE 1 ++#define DMAC_CHANNEL_DISABLE 0xfffffffe ++ ++#define DMAC_CxCONTROL_P2M 0x89409000 ++#define DMAC_CxCONFIG_P2M 0xd000 ++ ++#define DMAC_CxCONTROL_M2P 0x86089000 ++#define DMAC_CxCONFIG_M2P 0xc800 ++ ++#define DMAC_CxCONFIG_SIO_P2M 0x0000d000 ++#define DMAC_CxCONFIG_SIO_M2P 0x0000c800 ++ ++/*default the config and sync regsiter for DMAC controller*/ ++/*M1,M2 little endian, enable DMAC*/ ++#define DMAC_CONFIG_VAL 0x01 ++/*enable the sync logic for the 16 peripheral*/ ++#define DMAC_SYNC_VAL 0x0 ++ ++#define DMAC_MAX_PERIPHERALS 16 ++#define MEM_MAX_NUM 2 ++#define CHANNEL_NUM CONFIG_HI_DMAC_CHANNEL_NUM ++#define DMAC_MAX_CHANNELS CHANNEL_NUM ++ ++#define REG_BASE_I2C0 0x120c0000 ++#define I2C0_DATA_RXF (REG_BASE_I2C0 + 0x10) ++#define I2C0_DATA_TXF (REG_BASE_I2C0 + 0x10) ++ ++ ++#define REG_BASE_UART0 0x12080000 ++#define UART0_DATA_REG (REG_BASE_UART0 + 0x0) ++ ++#define REG_BASE_UART1 0x12090000 ++#define UART1_DATA_REG (REG_BASE_UART1 + 0x0) ++ ++#define REG_BASE_UART2 0x120a0000 ++#define UART2_DATA_REG (REG_BASE_UART2 + 0x0) ++ ++/*the transfer control and configuration value for different peripheral*/ ++ ++extern int g_channel_status[CHANNEL_NUM]; ++ ++dmac_peripheral g_peripheral[DMAC_MAX_PERIPHERALS] = { ++ /*periphal 0: UART0 RX, 8bit width */ ++ {0, UART0_DATA_REG, 0x99000000, 0xd000, 0}, ++ ++ /*periphal 1: UART0 TX, 8bit width */ ++ {1, UART0_DATA_REG, 0x96000000, 0xc840, 0}, ++ ++ /*periphal 2: UART1 RX, 8bit width */ ++ {2, UART1_DATA_REG, 0x99000000, 0xd004, 0}, ++ ++ /*periphal 3: UART1 TX, 8bit width */ ++ {3, UART1_DATA_REG, 0x96000000, 0xc8c0, 0}, ++ ++ /*periphal 4: UART2 RX, 8bit width */ ++ {4, UART2_DATA_REG, 0x99000000, 0xd008, 0}, ++ ++ /*periphal 5: UART2 TX, 8bit width */ ++ {5, UART2_DATA_REG, 0x96000000, 0xc940, 0}, ++ ++ /*periphal 6: ssp RX, 8bit width */ ++ {6, 0, 0x99000000, 0xd00c, 0}, ++ ++ /*periphal 7: ssp TX, 8bit width */ ++ {7, 0, 0x96000000, 0xc9c0, 0}, ++ ++ /*periphal 8: I2C0 RX, 8bit width */ ++ {8, I2C0_DATA_RXF, 0x99000000, 0x1010, 0}, ++ ++ /*periphal 9: I2C0 TX, 8bit width */ ++ {9, I2C0_DATA_TXF, 0x96000000, 0x0a40, 0}, ++}; ++ ++#endif +diff --git a/drivers/hidmac/hidmac_hi3531d.h b/drivers/hidmac/hidmac_hi3531d.h +new file mode 100644 +index 0000000..91d00b0 +--- /dev/null ++++ b/drivers/hidmac/hidmac_hi3531d.h +@@ -0,0 +1,135 @@ ++#ifndef __HI_DMAC_HI3531D_H__ ++#define __HI_DMAC_HI3531D_H__ ++ ++#define DDRAM_ADRS 0x80000000 /* fixed */ ++#define DDRAM_SIZE 0x1FFFFFFF /* 512M DDR. */ ++ ++#define FLASH_BASE 0x10000000 ++#define FLASH_SIZE 0x04000000 /* (32MB) */ ++ ++#define DMAC_INTSTATUS 0X00 ++#define DMAC_INTTCSTATUS 0X04 ++#define DMAC_INTTCCLEAR 0X08 ++#define DMAC_INTERRORSTATUS 0X0C ++ ++#define DMAC_INTERRCLR 0X10 ++#define DMAC_RAWINTTCSTATUS 0X14 ++#define DMAC_RAWINTERRORSTATUS 0X18 ++#define DMAC_ENBLDCHNS 0X1C ++#define DMAC_CONFIG 0X30 ++#define DMAC_SYNC 0X34 ++ ++#define DMAC_MAXTRANSFERSIZE 0x0fff /*the max length is denoted by 0-11bit*/ ++#define MAXTRANSFERSIZE DMAC_MAXTRANSFERSIZE ++#define DMAC_CxDISABLE 0x00 ++#define DMAC_CxENABLE 0x01 ++ ++/*the definition for DMAC channel register*/ ++#define DMAC_CxBASE(i) (0x100+i*0x20) ++#define DMAC_CxSRCADDR(i) DMAC_CxBASE(i) ++#define DMAC_CxDESTADDR(i) (DMAC_CxBASE(i)+0x04) ++#define DMAC_CxLLI(i) (DMAC_CxBASE(i)+0x08) ++#define DMAC_CxCONTROL(i) (DMAC_CxBASE(i)+0x0C) ++#define DMAC_CxCONFIG(i) (DMAC_CxBASE(i)+0x10) ++ ++/*the means the bit in the channel control register*/ ++#define DMAC_CxCONTROL_M2M 0x9d480000 /* Dwidth=32,burst size=4 */ ++#define DMAC_CxCONTROL_LLIM2M 0x0f480000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxCONTROL_LLIM2M_ISP 0x0b489000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxLLI_LM 0x01 ++ ++#define NUM_HAL_INTERRUPT_DMAC (14 + 16) ++ ++#define DMAC_CxCONFIG_M2M 0xc000 ++#define DMAC_CxCONFIG_LLIM2M 0xc000 ++ ++/*#define DMAC_CxCONFIG_M2M 0x4001*/ ++#define DMAC_CHANNEL_ENABLE 1 ++#define DMAC_CHANNEL_DISABLE 0xfffffffe ++ ++#define DMAC_CxCONTROL_P2M 0x89409000 ++#define DMAC_CxCONFIG_P2M 0xd000 ++ ++#define DMAC_CxCONTROL_M2P 0x86089000 ++#define DMAC_CxCONFIG_M2P 0xc800 ++ ++#define DMAC_CxCONFIG_SIO_P2M 0x0000d000 ++#define DMAC_CxCONFIG_SIO_M2P 0x0000c800 ++ ++/*default the config and sync regsiter for DMAC controller*/ ++/*M1,M2 little endian, enable DMAC*/ ++#define DMAC_CONFIG_VAL 0x01 ++/*enable the sync logic for the 16 peripheral*/ ++#define DMAC_SYNC_VAL 0x0 ++ ++#define DMAC_MAX_PERIPHERALS 16 ++#define MEM_MAX_NUM 2 ++#define CHANNEL_NUM CONFIG_HI_DMAC_CHANNEL_NUM ++#define DMAC_MAX_CHANNELS CHANNEL_NUM ++ ++#define REG_BASE_I2C0 0x120c0000 ++#define I2C0_DATA_RXF (REG_BASE_I2C0 + 0x10) ++#define I2C0_DATA_TXF (REG_BASE_I2C0 + 0x10) ++ ++#define REG_BASE_I2C1 0x120e0000 ++#define I2C1_DATA_RXF (REG_BASE_I2C1 + 0x10) ++#define I2C1_DATA_TXF (REG_BASE_I2C1 + 0x10) ++ ++#define REG_BASE_UART0 0x12080000 ++#define UART0_DATA_REG (REG_BASE_UART0 + 0x0) ++ ++#define REG_BASE_UART1 0x12090000 ++#define UART1_DATA_REG (REG_BASE_UART1 + 0x0) ++ ++#define REG_BASE_UART2 0x120a0000 ++#define UART2_DATA_REG (REG_BASE_UART2 + 0x0) ++ ++/*the transfer control and configuration value for different peripheral*/ ++ ++extern int g_channel_status[CHANNEL_NUM]; ++ ++dmac_peripheral g_peripheral[DMAC_MAX_PERIPHERALS] = { ++ /*periphal 0: UART0 RX, 8bit width */ ++ {0, UART0_DATA_REG, 0x99000000, 0xd000, 0}, ++ ++ /*periphal 1: UART0 TX, 8bit width */ ++ {1, UART0_DATA_REG, 0x96000000, 0xc840, 0}, ++ ++ /*periphal 2: UART1 RX, 8bit width */ ++ {2, UART1_DATA_REG, 0x99000000, 0xd004, 0}, ++ ++ /*periphal 3: UART1 TX, 8bit width */ ++ {3, UART1_DATA_REG, 0x96000000, 0xc8c0, 0}, ++ ++ /*periphal 4: UART2 RX, 8bit width */ ++ {4, UART2_DATA_REG, 0x99000000, 0xd008, 0}, ++ ++ /*periphal 5: UART2 TX, 8bit width */ ++ {5, UART2_DATA_REG, 0x96000000, 0xc940, 0}, ++ ++ /*periphal 6: SSP RX, 8bit width */ ++ {6, 0, 0x99000000, 0xd00c, 0}, ++ ++ /*periphal 7: SSP TX, 8bit width */ ++ {7, 0, 0x96000000, 0xc9c0, 0}, ++ ++ /*periphal 8: I2C0 RX, 8bit width */ ++ {8, I2C0_DATA_RXF, 0x99000000, 0x1010, 0}, ++ ++ /*periphal 9: I2C0 TX, 8bit width */ ++ {9, I2C0_DATA_TXF, 0x96000000, 0x0a40, 0}, ++ ++ /*periphal 10: UART3 RX, 8bit width */ ++ {10, 0, 0x99000000, 0xd014, 0}, ++ ++ /*periphal 11: UART3 TX, 8bit width */ ++ {11, 0, 0x96000000, 0xcb00, 0}, ++ ++ /*periphal 12: I2C1 RX, 8bit width */ ++ {12, I2C1_DATA_RXF, 0x99000000, 0x1018, 0}, ++ ++ /*periphal 13: I2C1 TX, 8bit width */ ++ {13, I2C1_DATA_TXF, 0x96000000, 0x0b40, 0}, ++}; ++ ++#endif +diff --git a/drivers/hidmac/hidmac_hi3536c.h b/drivers/hidmac/hidmac_hi3536c.h +new file mode 100644 +index 0000000..b34bdf2 +--- /dev/null ++++ b/drivers/hidmac/hidmac_hi3536c.h +@@ -0,0 +1,121 @@ ++#ifndef __HI_DMAC_HI3536C_H__ ++#define __HI_DMAC_HI3536C_H__ ++ ++#define DDRAM_ADRS 0x80000000 /* fixed */ ++#define DDRAM_SIZE 0x1FFFFFFF /* 512M DDR. */ ++ ++#define FLASH_BASE 0x10000000 ++#define FLASH_SIZE 0x04000000 /* (32MB) */ ++ ++#define DMAC_INTSTATUS 0X00 ++#define DMAC_INTTCSTATUS 0X04 ++#define DMAC_INTTCCLEAR 0X08 ++#define DMAC_INTERRORSTATUS 0X0C ++ ++#define DMAC_INTERRCLR 0X10 ++#define DMAC_RAWINTTCSTATUS 0X14 ++#define DMAC_RAWINTERRORSTATUS 0X18 ++#define DMAC_ENBLDCHNS 0X1C ++#define DMAC_CONFIG 0X30 ++#define DMAC_SYNC 0X34 ++ ++#define DMAC_MAXTRANSFERSIZE 0x0fff /*the max length is denoted by 0-11bit*/ ++#define MAXTRANSFERSIZE DMAC_MAXTRANSFERSIZE ++#define DMAC_CxDISABLE 0x00 ++#define DMAC_CxENABLE 0x01 ++ ++/*the definition for DMAC channel register*/ ++#define DMAC_CxBASE(i) (0x100+i*0x20) ++#define DMAC_CxSRCADDR(i) DMAC_CxBASE(i) ++#define DMAC_CxDESTADDR(i) (DMAC_CxBASE(i)+0x04) ++#define DMAC_CxLLI(i) (DMAC_CxBASE(i)+0x08) ++#define DMAC_CxCONTROL(i) (DMAC_CxBASE(i)+0x0C) ++#define DMAC_CxCONFIG(i) (DMAC_CxBASE(i)+0x10) ++ ++/*the means the bit in the channel control register*/ ++#define DMAC_CxCONTROL_M2M 0x9d480000 /* Dwidth=32,burst size=4 */ ++#define DMAC_CxCONTROL_LLIM2M 0x0f480000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxCONTROL_LLIM2M_ISP 0x0b489000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxLLI_LM 0x01 ++ ++#define NUM_HAL_INTERRUPT_DMAC (14 + 16) ++ ++#define DMAC_CxCONFIG_M2M 0xc000 ++#define DMAC_CxCONFIG_LLIM2M 0xc000 ++ ++/*#define DMAC_CxCONFIG_M2M 0x4001*/ ++#define DMAC_CHANNEL_ENABLE 1 ++#define DMAC_CHANNEL_DISABLE 0xfffffffe ++ ++#define DMAC_CxCONTROL_P2M 0x89409000 ++#define DMAC_CxCONFIG_P2M 0xd000 ++ ++#define DMAC_CxCONTROL_M2P 0x86089000 ++#define DMAC_CxCONFIG_M2P 0xc800 ++ ++#define DMAC_CxCONFIG_SIO_P2M 0x0000d000 ++#define DMAC_CxCONFIG_SIO_M2P 0x0000c800 ++ ++/*default the config and sync regsiter for DMAC controller*/ ++/*M1,M2 little endian, enable DMAC*/ ++#define DMAC_CONFIG_VAL 0x01 ++/*enable the sync logic for the 16 peripheral*/ ++#define DMAC_SYNC_VAL 0x0 ++ ++#define DMAC_MAX_PERIPHERALS 16 ++#define MEM_MAX_NUM 2 ++#define CHANNEL_NUM CONFIG_HI_DMAC_CHANNEL_NUM ++#define DMAC_MAX_CHANNELS CHANNEL_NUM ++ ++#define REG_BASE_I2C0 0x120c0000 ++#define I2C0_DATA_RXF (REG_BASE_I2C0 + 0x10) ++#define I2C0_DATA_TXF (REG_BASE_I2C0 + 0x10) ++ ++ ++#define REG_BASE_UART0 0x12080000 ++#define UART0_DATA_REG (REG_BASE_UART0 + 0x0) ++ ++#define REG_BASE_UART1 0x12090000 ++#define UART1_DATA_REG (REG_BASE_UART1 + 0x0) ++ ++#define REG_BASE_UART2 0x120a0000 ++#define UART2_DATA_REG (REG_BASE_UART2 + 0x0) ++ ++/*the transfer control and configuration value for different peripheral*/ ++ ++extern int g_channel_status[CHANNEL_NUM]; ++ ++dmac_peripheral g_peripheral[DMAC_MAX_PERIPHERALS] = { ++ /*periphal 0: UART0 RX, 8bit width */ ++ {0, UART0_DATA_REG, 0x99000000, 0xd000, 0}, ++ ++ /*periphal 1: UART0 TX, 8bit width */ ++ {1, UART0_DATA_REG, 0x96000000, 0xc840, 0}, ++ ++ /*periphal 2: UART1 RX, 8bit width */ ++ {2, UART1_DATA_REG, 0x99000000, 0xd004, 0}, ++ ++ /*periphal 3: UART1 TX, 8bit width */ ++ {3, UART1_DATA_REG, 0x96000000, 0xc8c0, 0}, ++ ++ /*periphal 4: UART2 RX, 8bit width */ ++ {4, UART2_DATA_REG, 0x99000000, 0xd008, 0}, ++ ++ /*periphal 5: UART2 TX, 8bit width */ ++ {5, UART2_DATA_REG, 0x96000000, 0xc940, 0}, ++ ++ /*periphal 6: SSP RX, 8bit width */ ++ {6, 0, 0x99000000, 0xd00c, 0}, ++ ++ /*periphal 7: SSP TX, 8bit width */ ++ {7, 0, 0x96000000, 0xc9c0, 0}, ++ ++ /*periphal 8: I2C0 RX, 8bit width */ ++ {8, I2C0_DATA_RXF, 0x99000000, 0x1010, 0}, ++ ++ /*periphal 9: I2C0 TX, 8bit width */ ++ {9, I2C0_DATA_TXF, 0x96000000, 0x0a40, 0}, ++ ++}; ++ ++#endif +diff --git a/drivers/hidmac/hidmac_hi3559.c b/drivers/hidmac/hidmac_hi3559.c +new file mode 100644 +index 0000000..3d8df63 +--- /dev/null ++++ b/drivers/hidmac/hidmac_hi3559.c +@@ -0,0 +1,90 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define SYS_CRG_BASE IO_ADDRESS(0x12010000) ++#define REG_PERI_CRG56 0xe0 ++#define DMAC_CLK_EN (1 << 1) ++#define DMAC_SRST_REQ (1 << 0) ++ ++/* ++ * DMA config array! ++ * DREQ, FIFO, CONTROL, CONFIG, BITWIDTH ++ */ ++dmac_peripheral g_peripheral[DMAC_MAX_PERIPHERALS] = { ++ /* periphal 0: UART0 RX, 8bit width */ ++ {0, UART0_DATA_REG, 0x99000000, 0xd000, 0}, ++ ++ /* periphal 1: UART0 TX, 8bit width */ ++ {1, UART0_DATA_REG, 0x96000000, 0xc840, 0}, ++ ++ /*periphal 2: UART1 RX, 8bit width */ ++ {2, UART1_DATA_REG, 0x99000000, 0xd004, 0}, ++ ++ /*periphal 3: UART1 TX, 8bit width */ ++ {3, UART1_DATA_REG, 0x96000000, 0xc8c0, 0}, ++ ++ /*periphal 4: UART2 RX, 8bit width */ ++ {4, UART2_DATA_REG, 0x99000000, 0xd008, 0}, ++ ++ /*periphal 5: UART2 TX, 8bit width */ ++ {5, UART2_DATA_REG, 0x96000000, 0xc940, 0}, ++ ++ /*periphal 6: I2C3 RX, 8bit width */ ++ {6, I2C3_DATA_REG, 0x99000000, 0xd00c, 0}, ++ ++ /*periphal 7: I2C3 TX, 8bit width */ ++ {7, I2C3_DATA_REG, 0x96000000, 0xc9c0, 0}, ++ ++ /*periphal 8: I2C0 RX, 8bit width */ ++ {8, I2C0_DATA_REG, 0x99000000, 0xd010, 0}, ++ ++ /*periphal 9: I2C0 TX, 8bit width */ ++ {9, I2C0_DATA_REG, 0x96000000, 0xca40, 0}, ++ ++ /*periphal 10: I2C1 RX, 8bit width */ ++ {10, I2C1_DATA_REG, 0x99000000, 0xd014, 0}, ++ ++ /*periphal 11: I2C1 TX, 8bit width */ ++ {11, I2C1_DATA_REG, 0x96000000, 0xcac0, 0}, ++ ++ /*periphal 12: SPI2 RX, 8bit width */ ++ {12, SPI2_DATA_REG, 0x99000000, 0xd018, 0}, ++ ++ /*periphal 13: SPI2 TX, 8bit width */ ++ {13, SPI2_DATA_REG, 0x96000000, 0xcb40, 0}, ++ ++ /*periphal 14: I2C2 RX, 8bit width */ ++ {14, I2C2_DATA_REG, 0x99000000, 0xd01c, 0}, ++ ++ /*periphal 15: I2C2 TX, 8bit width */ ++ {15, I2C2_DATA_REG, 0x96000000, 0xcbc0, 0}, ++}; ++ ++void hidmac_clk_en(void) ++{ ++ unsigned int tmp; ++ ++ dmac_readw(SYS_CRG_BASE + REG_PERI_CRG56, tmp); ++ tmp |= DMAC_CLK_EN; ++ dmac_writew(SYS_CRG_BASE + REG_PERI_CRG56, tmp); ++} ++ ++void hidmac_unreset(void) ++{ ++ unsigned int tmp; ++ ++ dmac_readw(SYS_CRG_BASE + REG_PERI_CRG56, tmp); ++ tmp &= ~DMAC_SRST_REQ; ++ dmac_writew(SYS_CRG_BASE + REG_PERI_CRG56, tmp); ++} +diff --git a/drivers/hidmac/hidmac_hi3559.h b/drivers/hidmac/hidmac_hi3559.h +new file mode 100644 +index 0000000..cbf943e +--- /dev/null ++++ b/drivers/hidmac/hidmac_hi3559.h +@@ -0,0 +1,99 @@ ++#ifndef __HI_DMAC_HI3559_H__ ++#define __HI_DMAC_HI3559_H__ ++ ++#define DDRAM_ADRS 0x80000000 /* fixed */ ++#define DDRAM_SIZE 0x3FFFFFFF /* 1GB DDR. */ ++ ++#define FLASH_BASE 0x10000000 ++#define FLASH_SIZE 0x04000000 /* (32MB) */ ++ ++#define DMAC_BASE_REG CONFIG_HI_DMAC_IO_BASE ++#define DMAC_INTTCCLEAR IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X08) ++ ++#define DMAC_INTSTATUS IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X00) ++#define DMAC_INTTCSTATUS IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X04) ++#define DMAC_INTERRORSTATUS IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X0C) ++ ++#define DMAC_INTERRCLR IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X10) ++#define DMAC_RAWINTTCSTATUS IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X14) ++#define DMAC_RAWINTERRORSTATUS IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X18) ++#define DMAC_ENBLDCHNS IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X1C) ++#define DMAC_CONFIG IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X30) ++#define DMAC_SYNC IO_DMAC_ADDRESS(DMAC_BASE_REG + 0X34) ++ ++#define DMAC_MAXTRANSFERSIZE 0x0fff /*the max length is denoted by 0-11bit*/ ++#define MAXTRANSFERSIZE DMAC_MAXTRANSFERSIZE ++#define DMAC_CxDISABLE 0x00 ++#define DMAC_CxENABLE 0x01 ++ ++/*the definition for DMAC channel register*/ ++#define DMAC_CxBASE(i) IO_DMAC_ADDRESS(DMAC_BASE_REG + 0x100+i*0x20) ++#define DMAC_CxSRCADDR(i) DMAC_CxBASE(i) ++#define DMAC_CxDESTADDR(i) (DMAC_CxBASE(i)+0x04) ++#define DMAC_CxLLI(i) (DMAC_CxBASE(i)+0x08) ++#define DMAC_CxCONTROL(i) (DMAC_CxBASE(i)+0x0C) ++#define DMAC_CxCONFIG(i) (DMAC_CxBASE(i)+0x10) ++ ++/*the means the bit in the channel control register*/ ++#define DMAC_CxCONTROL_M2M 0x9d480000 /* Dwidth=32,burst size=4 */ ++#define DMAC_CxCONTROL_LLIM2M 0x0f480000 /* Dwidth=32,burst size=1 */ ++#define DMAC_CxLLI_LM 0x01 ++ ++#define DMAC_CxCONFIG_M2M 0xc000 ++#define DMAC_CxCONFIG_LLIM2M 0xc000 ++ ++/*#define DMAC_CxCONFIG_M2M 0x4001*/ ++#define DMAC_CHANNEL_ENABLE 1 ++#define DMAC_CHANNEL_DISABLE 0xfffffffe ++ ++#define DMAC_CxCONTROL_P2M 0x89409000 ++#define DMAC_CxCONFIG_P2M 0xd000 ++ ++#define DMAC_CxCONTROL_M2P 0x86089000 ++#define DMAC_CxCONFIG_M2P 0xc800 ++ ++#define DMAC_CxCONFIG_SIO_P2M 0x0000d000 ++#define DMAC_CxCONFIG_SIO_M2P 0x0000c800 ++ ++/*default the config and sync regsiter for DMAC controller*/ ++/*M1,M2 little endian, enable DMAC*/ ++#define DMAC_CONFIG_VAL 0x01 ++/*enable the sync logic for the 16 peripheral*/ ++#define DMAC_SYNC_VAL 0x0 ++ ++#define DMAC_MAX_PERIPHERALS 16 ++#define MEM_MAX_NUM 2 ++#define CHANNEL_NUM CONFIG_HI_DMAC_CHANNEL_NUM ++#define DMAC_MAX_CHANNELS CHANNEL_NUM ++ ++#define REG_BASE_UART0 0x12100000 ++#define UART0_DATA_REG (REG_BASE_UART0 + 0x0) ++ ++#define REG_BASE_UART1 0x12101000 ++#define UART1_DATA_REG (REG_BASE_UART1 + 0x0) ++ ++#define REG_BASE_UART2 0x12102000 ++#define UART2_DATA_REG (REG_BASE_UART2 + 0x0) ++ ++#define REG_BASE_UART3 0x12103000 ++#define UART3_DATA_REG (REG_BASE_UART3 + 0x0) ++ ++#define REG_BASE_I2C0 0x12110000 ++#define I2C0_DATA_REG (REG_BASE_I2C0 + 0x10) ++ ++#define REG_BASE_I2C1 0x12111000 ++#define I2C1_DATA_REG (REG_BASE_I2C1 + 0x10) ++ ++#define REG_BASE_I2C2 0x12112000 ++#define I2C2_DATA_REG (REG_BASE_I2C2 + 0x10) ++ ++#define REG_BASE_I2C3 0x12113000 ++#define I2C3_DATA_REG (REG_BASE_I2C3 + 0x10) ++ ++#define REG_BASE_SPI2 0x12122000 ++#define SPI2_DATA_REG (REG_BASE_SPI2 + 0x8) ++ ++/*the transfer control and configuration value for different peripheral*/ ++ ++extern int g_channel_status[CHANNEL_NUM]; ++#endif +diff --git a/drivers/hisilicon/Kconfig b/drivers/hisilicon/Kconfig +new file mode 100644 +index 0000000..df2670b +--- /dev/null ++++ b/drivers/hisilicon/Kconfig +@@ -0,0 +1,5 @@ ++menu "Hisilicon driver support" ++ ++source "drivers/hisilicon/cma/Kconfig" ++ ++endmenu +diff --git a/drivers/hisilicon/Makefile b/drivers/hisilicon/Makefile +new file mode 100644 +index 0000000..12004b2 +--- /dev/null ++++ b/drivers/hisilicon/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-y += clocksource/ ++obj-$(CONFIG_CMA) += cma/ +diff --git a/drivers/hisilicon/clocksource/Makefile b/drivers/hisilicon/clocksource/Makefile +new file mode 100644 +index 0000000..2c6bfe5 +--- /dev/null ++++ b/drivers/hisilicon/clocksource/Makefile +@@ -0,0 +1,4 @@ ++#TODO: ARM64 Timer ++ccflags-y += -Iarch/arm/include ++ ++obj-y += timer.o hrtimer_test.o +diff --git a/drivers/hisilicon/clocksource/hrtimer_test.c b/drivers/hisilicon/clocksource/hrtimer_test.c +new file mode 100644 +index 0000000..645b0cf +--- /dev/null ++++ b/drivers/hisilicon/clocksource/hrtimer_test.c +@@ -0,0 +1,175 @@ ++/* ++ * hrtimer() test kernel module ++ * ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DEFAULT_ITERATIONS 100 ++ ++#define DEBUGFS_FILENAME "hrtimer_test" ++ ++ ++static DEFINE_MUTEX(hrtimer_test_lock); ++static struct dentry *hrtimer_test_debugfs_file; ++static int hrtimer_test_usecs; ++static int hrtimer_test_iterations = DEFAULT_ITERATIONS; ++ ++static int hrtimer_test_single(struct seq_file *s, int usecs, uint32_t iters) ++{ ++ int min = 0, max = 0, fail_count = 0; ++ uint64_t sum = 0; ++ uint64_t avg; ++ int i; ++ /* Allow hrtimer to be up to 0.5% fast */ ++ int allowed_error_ns = usecs * 5; ++ ktime_t waittime; ++ ++ for (i = 0; i < iters; ++i) { ++ struct timespec ts1, ts2; ++ int time_passed; ++ struct sched_param param = { .sched_priority = 99 }; ++ sched_setscheduler(current, SCHED_FIFO, ¶m); ++ waittime = ns_to_ktime(usecs * 1000); ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ ktime_get_ts(&ts1); ++ schedule_hrtimeout(&waittime, HRTIMER_MODE_REL); ++ ktime_get_ts(&ts2); ++ time_passed = timespec_to_ns(&ts2) - timespec_to_ns(&ts1); ++ ++ if (i == 0 || time_passed < min) ++ min = time_passed; ++ if (i == 0 || time_passed > max) ++ max = time_passed; ++ if ((time_passed + allowed_error_ns) / 1000 < usecs) ++ ++fail_count; ++ WARN_ON(time_passed < 0); ++ sum += time_passed; ++ } ++ ++ avg = sum; ++ do_div(avg, iters); ++ seq_printf(s, "%d usecs x %d: exp=%d allowed=%d min=%d avg=%lld max=%d", ++ usecs, iters, usecs * 1000, ++ (usecs * 1000) - allowed_error_ns, min, avg, max); ++ if (fail_count) ++ seq_printf(s, " FAIL=%d", fail_count); ++ seq_puts(s, "\n"); ++ ++ return 0; ++} ++ ++static int hrtimer_test_show(struct seq_file *s, void *v) ++{ ++ int usecs; ++ int iters; ++ int ret = 0; ++ ++ mutex_lock(&hrtimer_test_lock); ++ usecs = hrtimer_test_usecs; ++ iters = hrtimer_test_iterations; ++ mutex_unlock(&hrtimer_test_lock); ++ ++ if (usecs > 0 && iters > 0) { ++ return hrtimer_test_single(s, usecs, iters); ++ } else if (usecs == 0) { ++ struct timespec ts; ++ ++ ktime_get_ts(&ts); ++ seq_printf(s, "hrtimer() test (lpj=%ld kt=%ld.%09ld)\n", ++ loops_per_jiffy, ts.tv_sec, ts.tv_nsec); ++ seq_puts(s, "usage:\n"); ++ seq_puts(s, "echo usecs [ITERS] > " DEBUGFS_FILENAME "\n"); ++ seq_puts(s, "cat " DEBUGFS_FILENAME "\n"); ++ } ++ ++ return ret; ++} ++ ++static int hrtimer_test_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, hrtimer_test_show, inode->i_private); ++} ++ ++static ssize_t hrtimer_test_write(struct file *file, const char __user *buf, ++ size_t count, loff_t *pos) ++{ ++ char lbuf[32]; ++ int ret; ++ int usecs; ++ int iters; ++ ++ if (count >= sizeof(lbuf)) ++ return -EINVAL; ++ ++ if (copy_from_user(lbuf, buf, count)) ++ return -EFAULT; ++ lbuf[count] = '\0'; ++ ++ ret = sscanf(lbuf, "%d %d", &usecs, &iters); ++ if (ret < 1) ++ return -EINVAL; ++ else if (ret < 2) ++ iters = DEFAULT_ITERATIONS; ++ ++ mutex_lock(&hrtimer_test_lock); ++ hrtimer_test_usecs = usecs; ++ hrtimer_test_iterations = iters; ++ mutex_unlock(&hrtimer_test_lock); ++ ++ return count; ++} ++ ++static const struct file_operations hrtimer_test_debugfs_ops = { ++ .owner = THIS_MODULE, ++ .open = hrtimer_test_open, ++ .read = seq_read, ++ .write = hrtimer_test_write, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int __init hrtimer_test_init(void) ++{ ++ mutex_lock(&hrtimer_test_lock); ++ hrtimer_test_debugfs_file = debugfs_create_file(DEBUGFS_FILENAME, ++ S_IRUSR, NULL, NULL, &hrtimer_test_debugfs_ops); ++ mutex_unlock(&hrtimer_test_lock); ++ ++ return 0; ++} ++ ++module_init(hrtimer_test_init); ++ ++static void __exit hrtimer_test_exit(void) ++{ ++ mutex_lock(&hrtimer_test_lock); ++ debugfs_remove(hrtimer_test_debugfs_file); ++ mutex_unlock(&hrtimer_test_lock); ++} ++ ++module_exit(hrtimer_test_exit); ++ ++MODULE_AUTHOR("David Riley "); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/hisilicon/clocksource/timer.c b/drivers/hisilicon/clocksource/timer.c +new file mode 100644 +index 0000000..53106c1 +--- /dev/null ++++ b/drivers/hisilicon/clocksource/timer.c +@@ -0,0 +1,356 @@ ++/* ++ * ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/*****************************************************************************/ ++//TODO: ARM64 Timer ++#ifdef CONFIG_ARM64 ++#define IOMEM(x) ((void __force __iomem *)(x)) ++#endif ++ ++struct hisi_clocksource { ++ void __iomem *base; ++ struct clocksource clksrc; ++}; ++ ++struct hisi_clock_event_device { ++ struct clock_event_device evt; ++ void __iomem *base; ++ char name[10]; ++}; ++ ++static struct hisi_clocksource hisi_clocksource = {0}; ++static struct hisi_clock_event_device __percpu *hisi_local_timer_evt; ++static struct irqaction __percpu *hisi_event_irq; ++static void __iomem *hisi_timer_base[NR_CPUS] = {0}; ++static int hisi_timer_irqs[NR_CPUS] = {0}; ++static unsigned long hisi_clkevt_reload; ++static unsigned long hisi_clk_rate; ++/*****************************************************************************/ ++ ++static int hisi_set_next_event(unsigned long next, ++ struct clock_event_device *evt) ++{ ++ unsigned long ctrl; ++ struct hisi_clock_event_device *hisi_evt; ++ ++ hisi_evt = container_of(evt, struct hisi_clock_event_device, evt); ++ ctrl = readl(hisi_evt->base + TIMER_CTRL); ++ writel(next, hisi_evt->base + TIMER_LOAD); ++ writel(ctrl | TIMER_CTRL_ENABLE, hisi_evt->base + TIMER_CTRL); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static void hisi_set_mode(enum clock_event_mode mode, ++ struct clock_event_device *evt) ++{ ++ unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE; ++ struct hisi_clock_event_device *hisi_evt; ++ ++ hisi_evt = container_of(evt, struct hisi_clock_event_device, evt); ++ ++ writel(ctrl, hisi_evt->base + TIMER_CTRL); ++ ++ switch (mode) { ++ case CLOCK_EVT_MODE_PERIODIC: ++ writel(hisi_clkevt_reload, hisi_evt->base + TIMER_LOAD); ++ ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; ++ break; ++ ++ case CLOCK_EVT_MODE_ONESHOT: ++ /* period set, and timer enabled in 'next_event' hook */ ++ ctrl |= TIMER_CTRL_ONESHOT; ++ break; ++ ++ case CLOCK_EVT_MODE_UNUSED: ++ case CLOCK_EVT_MODE_SHUTDOWN: ++ default: ++ break; ++ } ++ ++ writel(ctrl, hisi_evt->base + TIMER_CTRL); ++} ++/*****************************************************************************/ ++ ++static irqreturn_t hisi_evt_isr(int irq, void *dev_id) ++{ ++ struct hisi_clock_event_device *hisi_evt = dev_id; ++ struct clock_event_device *evt = &hisi_evt->evt; ++ ++ /* clear the interrupt */ ++ writel(1, hisi_evt->base + TIMER_INTCLR); ++ ++ evt->event_handler(evt); ++ ++ return IRQ_HANDLED; ++} ++/*****************************************************************************/ ++ ++static inline struct hisi_clocksource *to_hisi_clksrc(struct clocksource *cs) ++{ ++ return container_of(cs, struct hisi_clocksource, clksrc); ++} ++/*****************************************************************************/ ++ ++static void hisi_clocksource_start(void __iomem *base) ++{ ++ writel(0, IOMEM(base + TIMER_CTRL)); ++ writel(0xffffffff, IOMEM(base + TIMER_LOAD)); ++ writel(0xffffffff, IOMEM(base + TIMER_VALUE)); ++ writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, ++ IOMEM(base + TIMER_CTRL)); ++} ++/*****************************************************************************/ ++ ++static cycle_t hisi_clocksource_read(struct clocksource *cs) ++{ ++ return ~readl_relaxed(to_hisi_clksrc(cs)->base + TIMER_VALUE); ++} ++/*****************************************************************************/ ++ ++static notrace u64 hisi_sched_clock_read(void) ++{ ++ u32 regval = ~readl_relaxed(hisi_clocksource.base + TIMER_VALUE); ++ ++ return (u64)regval; ++} ++/*****************************************************************************/ ++ ++static void hisi_clocksource_resume(struct clocksource *cs) ++{ ++ hisi_clocksource_start(to_hisi_clksrc(cs)->base); ++} ++/*****************************************************************************/ ++ ++static void __init hisi_clocksource_init(void __iomem *base, struct clk *clk) ++{ ++ struct clocksource *clksrc = &hisi_clocksource.clksrc; ++ ++ clksrc->name = clk->name; ++ clksrc->rating = 200; ++ clksrc->read = hisi_clocksource_read; ++ clksrc->mask = CLOCKSOURCE_MASK(32), ++ clksrc->flags = CLOCK_SOURCE_IS_CONTINUOUS, ++ clksrc->resume = hisi_clocksource_resume, ++ ++ hisi_clocksource.base = base; ++ ++ hisi_clocksource_start(base); ++ ++ clocksource_register_hz(clksrc, hisi_clk_rate); ++ sched_clock_register(hisi_sched_clock_read, 32, hisi_clk_rate); ++} ++//TODO: ARM64 Timer ++u64 hisi_get_clocksource_val(void) ++{ ++ struct clocksource *clksrc = &hisi_clocksource.clksrc; ++ if (!clksrc || !clksrc->read) ++ BUG(); ++ return clksrc->read(clksrc); ++} ++/*****************************************************************************/ ++ ++static int hisi_local_timer_setup(struct clock_event_device *clk) ++{ ++ struct hisi_clock_event_device *hisi_evt; ++ unsigned int cpu = smp_processor_id(); ++ struct irqaction *action = this_cpu_ptr(hisi_event_irq); ++ ++ hisi_evt = container_of(clk, struct hisi_clock_event_device, evt); ++ ++ hisi_evt->base = hisi_timer_base[cpu]; ++ snprintf(hisi_evt->name, sizeof(hisi_evt->name), "tick%d", cpu); ++ ++ clk->name = hisi_evt->name; ++ clk->cpumask = cpumask_of(cpu); ++ clk->set_next_event = hisi_set_next_event; ++ clk->set_mode = hisi_set_mode; ++ clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; ++ clk->rating = 450; ++ clk->irq = hisi_timer_irqs[cpu]; ++ clk->mode = CLOCK_EVT_MODE_UNUSED; ++ ++ action->name = clk->name; ++ action->dev_id = hisi_evt; ++ action->irq = clk->irq; ++ action->flags = IRQF_TIMER | IRQF_NOBALANCING; ++ action->handler = hisi_evt_isr; ++ BUG_ON(setup_irq(clk->irq, action)); ++ irq_force_affinity(clk->irq, clk->cpumask); ++ ++ clockevents_config_and_register(clk, hisi_clk_rate, 0xf, 0x7fffffff); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static void hisi_local_timer_stop(struct clock_event_device *clk) ++{ ++ pr_info("hisi_local_timer_teardown disable IRQ%d cpu #%d\n", ++ clk->irq, smp_processor_id()); ++ ++ disable_irq(clk->irq); ++ remove_irq(clk->irq, this_cpu_ptr(hisi_event_irq)); ++ ++ clk->set_mode(CLOCK_EVT_MODE_UNUSED, clk); ++} ++/*****************************************************************************/ ++ ++static int hisi_local_timer_cpu_notify(struct notifier_block *self, ++ unsigned long action, void *hcpu) ++{ ++ struct hisi_clock_event_device *hisi_evt; ++ /* ++ * Grab cpu pointer in each case to avoid spurious ++ * preemptible warnings ++ */ ++ switch (action & ~CPU_TASKS_FROZEN) { ++ case CPU_STARTING: ++ hisi_evt = this_cpu_ptr(hisi_local_timer_evt); ++ hisi_local_timer_setup(&hisi_evt->evt); ++ break; ++ case CPU_DYING: ++ hisi_evt = this_cpu_ptr(hisi_local_timer_evt); ++ hisi_local_timer_stop(&hisi_evt->evt); ++ break; ++ } ++ ++ return NOTIFY_OK; ++} ++/*****************************************************************************/ ++ ++static struct notifier_block hisi_local_timer_cpu_nb = { ++ .notifier_call = hisi_local_timer_cpu_notify, ++}; ++/*****************************************************************************/ ++static int __init hisi_local_timer_register(void) ++{ ++ int err; ++ int cpu = smp_processor_id(); ++ struct hisi_clock_event_device *hisi_evt; ++ ++ hisi_local_timer_evt = alloc_percpu(struct hisi_clock_event_device); ++ if (!hisi_local_timer_evt) { ++ err = -ENOMEM; ++ goto out; ++ } ++ ++ hisi_event_irq = alloc_percpu(struct irqaction); ++ if (!hisi_event_irq) { ++ err = -ENOMEM; ++ goto out_event_irq; ++ } ++ ++ irq_set_affinity(hisi_timer_irqs[cpu], cpumask_of(0)); ++ ++ err = register_cpu_notifier(&hisi_local_timer_cpu_nb); ++ if (err) ++ goto out_notifier; ++ ++ /* Immediately configure the timer on the boot CPU */ ++ hisi_evt = this_cpu_ptr(hisi_local_timer_evt); ++ hisi_local_timer_setup(&hisi_evt->evt); ++ ++ return 0; ++ ++out_notifier: ++ free_percpu(hisi_event_irq); ++ ++out_event_irq: ++ free_percpu(hisi_local_timer_evt); ++ ++out: ++ return err; ++} ++ ++static void __init hisi_timer_init(struct device_node *node) ++{ ++ u32 i, nr_irqs; ++ struct clk *clk; ++ void __iomem *base; ++ ++ nr_irqs = of_irq_count(node); ++ if (nr_irqs > num_possible_cpus()) ++ nr_irqs = num_possible_cpus(); ++ ++ for (i = 0; i < nr_irqs; i++) { ++ hisi_timer_irqs[i] = irq_of_parse_and_map(node, i); ++ hisi_timer_base[i] = of_iomap(node, i + 1); ++ if (!hisi_timer_base[i]) { ++ pr_err("can not iomap timer %d\n", i); ++ goto out_unmap; ++ } ++ } ++ ++ base = of_iomap(node, 0); ++ if (WARN_ON(!base)) ++ goto out_unmap; ++ ++ clk = of_clk_get(node, 0); ++ if (IS_ERR(clk)) ++ goto out_clk; ++ ++ clk_prepare_enable(clk); ++ ++ hisi_clk_rate = clk_get_rate(clk); ++ hisi_clkevt_reload = DIV_ROUND_CLOSEST(hisi_clk_rate, HZ); ++ ++ hisi_clocksource_init(base, clk); ++ hisi_local_timer_register(); ++ ++ return; ++ ++out_clk: ++ iounmap(base); ++ ++out_unmap: ++ for (i = 0; i < nr_irqs; i++) { ++ if (hisi_timer_base[i]) ++ iounmap(hisi_timer_base[i]); ++ } ++} ++//TODO: ARM64 Timer ++u32 hisi_timer_get_rate(void) ++{ ++ return hisi_clk_rate; ++} ++ ++CLOCKSOURCE_OF_DECLARE(hisi_timer, "hisilicon,timer", ++ hisi_timer_init); +diff --git a/drivers/hisilicon/cma/Kconfig b/drivers/hisilicon/cma/Kconfig +new file mode 100644 +index 0000000..7472dcc +--- /dev/null ++++ b/drivers/hisilicon/cma/Kconfig +@@ -0,0 +1,16 @@ ++ ++config CMA_MEM_SHARED ++ bool "Support sharing CMA memory with the heap" ++ depends on CMA && DMA_CMA ++ default no ++ help ++ Support sharing CMA memory with the heap. ++ ++config CMA_ADVANCE_SHARE ++ bool "Support cma advance share" ++ depends on CMA && DMA_CMA ++ select CMA_MEM_SHARED ++ default no ++ help ++ Support advance sharing CMA memory with the heap. ++ CMA Multiplex Ratio will be improved when this macro defined. +diff --git a/drivers/hisilicon/cma/Makefile b/drivers/hisilicon/cma/Makefile +new file mode 100644 +index 0000000..eefda7f +--- /dev/null ++++ b/drivers/hisilicon/cma/Makefile +@@ -0,0 +1,2 @@ ++ ++obj-$(CONFIG_CMA) += hi_cma.o +diff --git a/drivers/hisilicon/cma/hi_cma.c b/drivers/hisilicon/cma/hi_cma.c +new file mode 100644 +index 0000000..d0395ed +--- /dev/null ++++ b/drivers/hisilicon/cma/hi_cma.c +@@ -0,0 +1,141 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define NAME_LEN_MAX 64 ++#define ZONE_MAX 64 ++ ++struct cma_zone { ++ struct device pdev; ++ char name[NAME_LEN_MAX]; ++ u32 gfp; ++ u32 phys_start; ++ u32 nbytes; ++ u32 alloc_type; ++ u32 block_align; ++}; ++ ++static u32 num_zones; ++static struct cma_zone hisi_zone[ZONE_MAX]; ++ ++static int use_bootargs; ++ ++unsigned int get_cma_size(void) ++{ ++ int i; ++ u64 total = 0; ++ ++ for (i = 0; i < num_zones; i++) ++ total += hisi_zone[i].nbytes; ++ ++ /* unit is M */ ++ return (unsigned int)(total >> 20); ++} ++ ++static int __init hisi_mmz_parse_cmdline(char *s) ++{ ++ char *line, *tmp; ++ char tmpline[256]; ++ ++ if (NULL == s) { ++ pr_info("There is no cma zone!\n"); ++ return 0; ++ } ++ strncpy(tmpline, s, sizeof(tmpline)); ++ tmpline[sizeof(tmpline)-1] = '\0'; ++ tmp = tmpline; ++ ++ while ((line = strsep(&tmp, ":")) != NULL) { ++ int i; ++ char *argv[6]; ++ ++ for (i = 0; (argv[i] = strsep(&line, ",")) != NULL;) ++ if (++i == ARRAY_SIZE(argv)) ++ break; ++ ++ hisi_zone[num_zones].pdev.coherent_dma_mask = DMA_BIT_MASK(64); ++ if (i == 4) { ++ strlcpy(hisi_zone[num_zones].name, argv[0], NAME_LEN_MAX); ++ hisi_zone[num_zones].gfp = memparse(argv[1], NULL); ++ hisi_zone[num_zones].phys_start = memparse(argv[2], NULL); ++ hisi_zone[num_zones].nbytes = memparse(argv[3], NULL); ++ } ++ ++ else if (i == 6) { ++ strlcpy(hisi_zone[num_zones].name, argv[0], NAME_LEN_MAX); ++ hisi_zone[num_zones].gfp = memparse(argv[1], NULL); ++ hisi_zone[num_zones].phys_start = memparse(argv[2], NULL); ++ hisi_zone[num_zones].nbytes = memparse(argv[3], NULL); ++ hisi_zone[num_zones].alloc_type = memparse(argv[4], NULL); ++ hisi_zone[num_zones].block_align = memparse(argv[5], NULL); ++ } else { ++ pr_err("hisi ion parameter is not correct\n"); ++ continue; ++ } ++ ++ num_zones++; ++ } ++ if (num_zones != 0) ++ use_bootargs = 1; ++ ++ return 0; ++} ++early_param("mmz", hisi_mmz_parse_cmdline); ++ ++struct cma_zone *hisi_get_cma_zone(const char *name) ++{ ++ int i = 0; ++ ++ for (i = 0; i < num_zones; i++) ++ if (strcmp(hisi_zone[i].name, name) == 0) ++ break; ++ ++ if (i == num_zones) ++ return NULL; ++ ++ return &hisi_zone[i]; ++} ++EXPORT_SYMBOL(hisi_get_cma_zone); ++ ++struct device *hisi_get_cma_device(const char *name) ++{ ++ int i = 0; ++ ++ for (i = 0; i < num_zones; i++) ++ if (strcmp(hisi_zone[i].name, name) == 0) ++ break; ++ ++ if (i == num_zones) ++ return NULL; ++ ++ return &hisi_zone[i].pdev; ++} ++EXPORT_SYMBOL(hisi_get_cma_device); ++ ++int hisi_declare_heap_memory(void) ++{ ++ int i; ++ int ret = 0; ++ ++ if (use_bootargs == 0) { ++ pr_info("cmz zone is not set!\n"); ++ return ret; ++ } ++ ++ for (i = 0; i < num_zones; i++) { ++ ret = dma_declare_contiguous(&hisi_zone[i].pdev, ++ hisi_zone[i].nbytes, hisi_zone[i].phys_start, 0); ++ if (ret) ++ panic("declare cma zone %s base: %u size:%uMB failed. ret:%d", ++ hisi_zone[i].name, hisi_zone[i].phys_start, ++ hisi_zone[i].nbytes>>20, ret); ++ hisi_zone[i].phys_start = cma_get_base(hisi_zone[i].pdev.cma_area); ++ hisi_zone[i].nbytes = cma_get_size(hisi_zone[i].pdev.cma_area); ++ ++ /*FIXME need to fix dma_declare_contiguous return value &&value type*/ ++ } ++ return ret; ++} +diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c +index d16dbb3..e7c8bf9 100644 +--- a/drivers/hwmon/lm75.c ++++ b/drivers/hwmon/lm75.c +@@ -176,6 +176,10 @@ static struct attribute *lm75_attrs[] = { + }; + ATTRIBUTE_GROUPS(lm75); + ++static const struct thermal_zone_of_device_ops lm75_of_thermal_ops = { ++ .get_temp = lm75_read_temp, ++}; ++ + /*-----------------------------------------------------------------------*/ + + /* device probe and removal */ +@@ -291,10 +295,9 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) + if (IS_ERR(data->hwmon_dev)) + return PTR_ERR(data->hwmon_dev); + +- data->tz = thermal_zone_of_sensor_register(data->hwmon_dev, +- 0, ++ data->tz = thermal_zone_of_sensor_register(data->hwmon_dev, 0, + data->hwmon_dev, +- lm75_read_temp, NULL); ++ &lm75_of_thermal_ops); + if (IS_ERR(data->tz)) + data->tz = NULL; + +diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c +index 31597c5..b2c90bd 100644 +--- a/drivers/hwmon/ntc_thermistor.c ++++ b/drivers/hwmon/ntc_thermistor.c +@@ -495,6 +495,10 @@ static const struct attribute_group ntc_attr_group = { + .attrs = ntc_attributes, + }; + ++static const struct thermal_zone_of_device_ops ntc_of_thermal_ops = { ++ .get_temp = ntc_read_temp, ++}; ++ + static int ntc_thermistor_probe(struct platform_device *pdev) + { + const struct of_device_id *of_id = +@@ -588,7 +592,7 @@ static int ntc_thermistor_probe(struct platform_device *pdev) + pdev_id->name); + + data->tz = thermal_zone_of_sensor_register(data->dev, 0, data->dev, +- ntc_read_temp, NULL); ++ &ntc_of_thermal_ops); + if (IS_ERR(data->tz)) { + dev_dbg(&pdev->dev, "Failed to register to thermal fw.\n"); + data->tz = NULL; +diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c +index 5171995..ba9f478 100644 +--- a/drivers/hwmon/tmp102.c ++++ b/drivers/hwmon/tmp102.c +@@ -158,6 +158,10 @@ ATTRIBUTE_GROUPS(tmp102); + #define TMP102_CONFIG (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1) + #define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL) + ++static const struct thermal_zone_of_device_ops tmp102_of_thermal_ops = { ++ .get_temp = tmp102_read_temp, ++}; ++ + static int tmp102_probe(struct i2c_client *client, + const struct i2c_device_id *id) + { +@@ -215,7 +219,7 @@ static int tmp102_probe(struct i2c_client *client, + } + tmp102->hwmon_dev = hwmon_dev; + tmp102->tz = thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev, +- tmp102_read_temp, NULL); ++ &tmp102_of_thermal_ops); + if (IS_ERR(tmp102->tz)) + tmp102->tz = NULL; + +diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig +new file mode 100644 +index 0000000..fc1f1ae +--- /dev/null ++++ b/drivers/hwtracing/coresight/Kconfig +@@ -0,0 +1,61 @@ ++# ++# Coresight configuration ++# ++menuconfig CORESIGHT ++ bool "CoreSight Tracing Support" ++ select ARM_AMBA ++ help ++ This framework provides a kernel interface for the CoreSight debug ++ and trace drivers to register themselves with. It's intended to build ++ a topological view of the CoreSight components based on a DT ++ specification and configure the right serie of components when a ++ trace source gets enabled. ++ ++if CORESIGHT ++config CORESIGHT_LINKS_AND_SINKS ++ bool "CoreSight Link and Sink drivers" ++ help ++ This enables support for CoreSight link and sink drivers that are ++ responsible for transporting and collecting the trace data ++ respectively. Link and sinks are dynamically aggregated with a trace ++ entity at run time to form a complete trace path. ++ ++config CORESIGHT_LINK_AND_SINK_TMC ++ bool "Coresight generic TMC driver" ++ depends on CORESIGHT_LINKS_AND_SINKS ++ help ++ This enables support for the Trace Memory Controller driver. ++ Depending on its configuration the device can act as a link (embedded ++ trace router - ETR) or sink (embedded trace FIFO). The driver ++ complies with the generic implementation of the component without ++ special enhancement or added features. ++ ++config CORESIGHT_SINK_TPIU ++ bool "Coresight generic TPIU driver" ++ depends on CORESIGHT_LINKS_AND_SINKS ++ help ++ This enables support for the Trace Port Interface Unit driver, ++ responsible for bridging the gap between the on-chip coresight ++ components and a trace for bridging the gap between the on-chip ++ coresight components and a trace port collection engine, typically ++ connected to an external host for use case capturing more traces than ++ the on-board coresight memory can handle. ++ ++config CORESIGHT_SINK_ETBV10 ++ bool "Coresight ETBv1.0 driver" ++ depends on CORESIGHT_LINKS_AND_SINKS ++ help ++ This enables support for the Embedded Trace Buffer version 1.0 driver ++ that complies with the generic implementation of the component without ++ special enhancement or added features. ++ ++config CORESIGHT_SOURCE_ETM3X ++ bool "CoreSight Embedded Trace Macrocell 3.x driver" ++ depends on !ARM64 ++ select CORESIGHT_LINKS_AND_SINKS ++ help ++ This driver provides support for processor ETM3.x and PTM1.x modules, ++ which allows tracing the instructions that a processor is executing ++ This is primarily useful for instruction level tracing. Depending ++ the ETM version data tracing may also be available. ++endif +diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile +new file mode 100644 +index 0000000..4b4bec8 +--- /dev/null ++++ b/drivers/hwtracing/coresight/Makefile +@@ -0,0 +1,11 @@ ++# ++# Makefile for CoreSight drivers. ++# ++obj-$(CONFIG_CORESIGHT) += coresight.o ++obj-$(CONFIG_OF) += of_coresight.o ++obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o ++obj-$(CONFIG_CORESIGHT_SINK_TPIU) += coresight-tpiu.o ++obj-$(CONFIG_CORESIGHT_SINK_ETBV10) += coresight-etb10.o ++obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-funnel.o \ ++ coresight-replicator.o ++obj-$(CONFIG_CORESIGHT_SOURCE_ETM3X) += coresight-etm3x.o coresight-etm-cp14.o +diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c +new file mode 100644 +index 0000000..4004986 +--- /dev/null ++++ b/drivers/hwtracing/coresight/coresight-etb10.c +@@ -0,0 +1,527 @@ ++/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "coresight-priv.h" ++ ++#define ETB_RAM_DEPTH_REG 0x004 ++#define ETB_STATUS_REG 0x00c ++#define ETB_RAM_READ_DATA_REG 0x010 ++#define ETB_RAM_READ_POINTER 0x014 ++#define ETB_RAM_WRITE_POINTER 0x018 ++#define ETB_TRG 0x01c ++#define ETB_CTL_REG 0x020 ++#define ETB_RWD_REG 0x024 ++#define ETB_FFSR 0x300 ++#define ETB_FFCR 0x304 ++#define ETB_ITMISCOP0 0xee0 ++#define ETB_ITTRFLINACK 0xee4 ++#define ETB_ITTRFLIN 0xee8 ++#define ETB_ITATBDATA0 0xeeC ++#define ETB_ITATBCTR2 0xef0 ++#define ETB_ITATBCTR1 0xef4 ++#define ETB_ITATBCTR0 0xef8 ++ ++/* register description */ ++/* STS - 0x00C */ ++#define ETB_STATUS_RAM_FULL BIT(0) ++/* CTL - 0x020 */ ++#define ETB_CTL_CAPT_EN BIT(0) ++/* FFCR - 0x304 */ ++#define ETB_FFCR_EN_FTC BIT(0) ++#define ETB_FFCR_FON_MAN BIT(6) ++#define ETB_FFCR_STOP_FI BIT(12) ++#define ETB_FFCR_STOP_TRIGGER BIT(13) ++ ++#define ETB_FFCR_BIT 6 ++#define ETB_FFSR_BIT 1 ++#define ETB_FRAME_SIZE_WORDS 4 ++ ++/** ++ * struct etb_drvdata - specifics associated to an ETB component ++ * @base: memory mapped base address for this component. ++ * @dev: the device entity associated to this component. ++ * @csdev: component vitals needed by the framework. ++ * @miscdev: specifics to handle "/dev/xyz.etb" entry. ++ * @clk: the clock this component is associated to. ++ * @spinlock: only one at a time pls. ++ * @in_use: synchronise user space access to etb buffer. ++ * @buf: area of memory where ETB buffer content gets sent. ++ * @buffer_depth: size of @buf. ++ * @enable: this ETB is being used. ++ * @trigger_cntr: amount of words to store after a trigger. ++ */ ++struct etb_drvdata { ++ void __iomem *base; ++ struct device *dev; ++ struct coresight_device *csdev; ++ struct miscdevice miscdev; ++ struct clk *clk; ++ spinlock_t spinlock; ++ atomic_t in_use; ++ u8 *buf; ++ u32 buffer_depth; ++ bool enable; ++ u32 trigger_cntr; ++}; ++ ++static unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata) ++{ ++ int ret; ++ u32 depth = 0; ++ ++ ret = clk_prepare_enable(drvdata->clk); ++ if (ret) ++ return ret; ++ ++ /* RO registers don't need locking */ ++ depth = readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG); ++ ++ clk_disable_unprepare(drvdata->clk); ++ return depth; ++} ++ ++static void etb_enable_hw(struct etb_drvdata *drvdata) ++{ ++ int i; ++ u32 depth; ++ ++ CS_UNLOCK(drvdata->base); ++ ++ depth = drvdata->buffer_depth; ++ /* reset write RAM pointer address */ ++ writel_relaxed(0x0, drvdata->base + ETB_RAM_WRITE_POINTER); ++ /* clear entire RAM buffer */ ++ for (i = 0; i < depth; i++) ++ writel_relaxed(0x0, drvdata->base + ETB_RWD_REG); ++ ++ /* reset write RAM pointer address */ ++ writel_relaxed(0x0, drvdata->base + ETB_RAM_WRITE_POINTER); ++ /* reset read RAM pointer address */ ++ writel_relaxed(0x0, drvdata->base + ETB_RAM_READ_POINTER); ++ ++ writel_relaxed(drvdata->trigger_cntr, drvdata->base + ETB_TRG); ++ writel_relaxed(ETB_FFCR_EN_FTC | ETB_FFCR_STOP_TRIGGER, ++ drvdata->base + ETB_FFCR); ++ /* ETB trace capture enable */ ++ writel_relaxed(ETB_CTL_CAPT_EN, drvdata->base + ETB_CTL_REG); ++ ++ CS_LOCK(drvdata->base); ++} ++ ++static int etb_enable(struct coresight_device *csdev) ++{ ++ struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); ++ int ret; ++ unsigned long flags; ++ ++ ret = clk_prepare_enable(drvdata->clk); ++ if (ret) ++ return ret; ++ ++ spin_lock_irqsave(&drvdata->spinlock, flags); ++ etb_enable_hw(drvdata); ++ drvdata->enable = true; ++ spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ ++ dev_info(drvdata->dev, "ETB enabled\n"); ++ return 0; ++} ++ ++static void etb_disable_hw(struct etb_drvdata *drvdata) ++{ ++ u32 ffcr; ++ ++ CS_UNLOCK(drvdata->base); ++ ++ ffcr = readl_relaxed(drvdata->base + ETB_FFCR); ++ /* stop formatter when a stop has completed */ ++ ffcr |= ETB_FFCR_STOP_FI; ++ writel_relaxed(ffcr, drvdata->base + ETB_FFCR); ++ /* manually generate a flush of the system */ ++ ffcr |= ETB_FFCR_FON_MAN; ++ writel_relaxed(ffcr, drvdata->base + ETB_FFCR); ++ ++ if (coresight_timeout(drvdata->base, ETB_FFCR, ETB_FFCR_BIT, 0)) { ++ dev_err(drvdata->dev, ++ "timeout observed when probing at offset %#x\n", ++ ETB_FFCR); ++ } ++ ++ /* disable trace capture */ ++ writel_relaxed(0x0, drvdata->base + ETB_CTL_REG); ++ ++ if (coresight_timeout(drvdata->base, ETB_FFSR, ETB_FFSR_BIT, 1)) { ++ dev_err(drvdata->dev, ++ "timeout observed when probing at offset %#x\n", ++ ETB_FFCR); ++ } ++ ++ CS_LOCK(drvdata->base); ++} ++ ++static void etb_dump_hw(struct etb_drvdata *drvdata) ++{ ++ int i; ++ u8 *buf_ptr; ++ u32 read_data, depth; ++ u32 read_ptr, write_ptr; ++ u32 frame_off, frame_endoff; ++ ++ CS_UNLOCK(drvdata->base); ++ ++ read_ptr = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER); ++ write_ptr = readl_relaxed(drvdata->base + ETB_RAM_WRITE_POINTER); ++ ++ frame_off = write_ptr % ETB_FRAME_SIZE_WORDS; ++ frame_endoff = ETB_FRAME_SIZE_WORDS - frame_off; ++ if (frame_off) { ++ dev_err(drvdata->dev, ++ "write_ptr: %lu not aligned to formatter frame size\n", ++ (unsigned long)write_ptr); ++ dev_err(drvdata->dev, "frameoff: %lu, frame_endoff: %lu\n", ++ (unsigned long)frame_off, (unsigned long)frame_endoff); ++ write_ptr += frame_endoff; ++ } ++ ++ if ((readl_relaxed(drvdata->base + ETB_STATUS_REG) ++ & ETB_STATUS_RAM_FULL) == 0) ++ writel_relaxed(0x0, drvdata->base + ETB_RAM_READ_POINTER); ++ else ++ writel_relaxed(write_ptr, drvdata->base + ETB_RAM_READ_POINTER); ++ ++ depth = drvdata->buffer_depth; ++ buf_ptr = drvdata->buf; ++ for (i = 0; i < depth; i++) { ++ read_data = readl_relaxed(drvdata->base + ++ ETB_RAM_READ_DATA_REG); ++ *buf_ptr++ = read_data >> 0; ++ *buf_ptr++ = read_data >> 8; ++ *buf_ptr++ = read_data >> 16; ++ *buf_ptr++ = read_data >> 24; ++ } ++ ++ if (frame_off) { ++ buf_ptr -= (frame_endoff * 4); ++ for (i = 0; i < frame_endoff; i++) { ++ *buf_ptr++ = 0x0; ++ *buf_ptr++ = 0x0; ++ *buf_ptr++ = 0x0; ++ *buf_ptr++ = 0x0; ++ } ++ } ++ ++ writel_relaxed(read_ptr, drvdata->base + ETB_RAM_READ_POINTER); ++ ++ CS_LOCK(drvdata->base); ++} ++ ++static void etb_disable(struct coresight_device *csdev) ++{ ++ struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&drvdata->spinlock, flags); ++ etb_disable_hw(drvdata); ++ etb_dump_hw(drvdata); ++ drvdata->enable = false; ++ spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ ++ clk_disable_unprepare(drvdata->clk); ++ ++ dev_info(drvdata->dev, "ETB disabled\n"); ++} ++ ++static const struct coresight_ops_sink etb_sink_ops = { ++ .enable = etb_enable, ++ .disable = etb_disable, ++}; ++ ++static const struct coresight_ops etb_cs_ops = { ++ .sink_ops = &etb_sink_ops, ++}; ++ ++static void etb_dump(struct etb_drvdata *drvdata) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&drvdata->spinlock, flags); ++ if (drvdata->enable) { ++ etb_disable_hw(drvdata); ++ etb_dump_hw(drvdata); ++ etb_enable_hw(drvdata); ++ } ++ spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ ++ dev_info(drvdata->dev, "ETB dumped\n"); ++} ++ ++static int etb_open(struct inode *inode, struct file *file) ++{ ++ struct etb_drvdata *drvdata = container_of(file->private_data, ++ struct etb_drvdata, miscdev); ++ ++ if (atomic_cmpxchg(&drvdata->in_use, 0, 1)) ++ return -EBUSY; ++ ++ dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__); ++ return 0; ++} ++ ++static ssize_t etb_read(struct file *file, char __user *data, ++ size_t len, loff_t *ppos) ++{ ++ u32 depth; ++ struct etb_drvdata *drvdata = container_of(file->private_data, ++ struct etb_drvdata, miscdev); ++ ++ etb_dump(drvdata); ++ ++ depth = drvdata->buffer_depth; ++ if (*ppos + len > depth * 4) ++ len = depth * 4 - *ppos; ++ ++ if (copy_to_user(data, drvdata->buf + *ppos, len)) { ++ dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__); ++ return -EFAULT; ++ } ++ ++ *ppos += len; ++ ++ dev_dbg(drvdata->dev, "%s: %zu bytes copied, %d bytes left\n", ++ __func__, len, (int)(depth * 4 - *ppos)); ++ return len; ++} ++ ++static int etb_release(struct inode *inode, struct file *file) ++{ ++ struct etb_drvdata *drvdata = container_of(file->private_data, ++ struct etb_drvdata, miscdev); ++ atomic_set(&drvdata->in_use, 0); ++ ++ dev_dbg(drvdata->dev, "%s: released\n", __func__); ++ return 0; ++} ++ ++static const struct file_operations etb_fops = { ++ .owner = THIS_MODULE, ++ .open = etb_open, ++ .read = etb_read, ++ .release = etb_release, ++ .llseek = no_llseek, ++}; ++ ++static ssize_t status_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ int ret; ++ unsigned long flags; ++ u32 etb_rdr, etb_sr, etb_rrp, etb_rwp; ++ u32 etb_trg, etb_cr, etb_ffsr, etb_ffcr; ++ struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = clk_prepare_enable(drvdata->clk); ++ if (ret) ++ goto out; ++ ++ spin_lock_irqsave(&drvdata->spinlock, flags); ++ CS_UNLOCK(drvdata->base); ++ ++ etb_rdr = readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG); ++ etb_sr = readl_relaxed(drvdata->base + ETB_STATUS_REG); ++ etb_rrp = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER); ++ etb_rwp = readl_relaxed(drvdata->base + ETB_RAM_WRITE_POINTER); ++ etb_trg = readl_relaxed(drvdata->base + ETB_TRG); ++ etb_cr = readl_relaxed(drvdata->base + ETB_CTL_REG); ++ etb_ffsr = readl_relaxed(drvdata->base + ETB_FFSR); ++ etb_ffcr = readl_relaxed(drvdata->base + ETB_FFCR); ++ ++ CS_LOCK(drvdata->base); ++ spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ ++ clk_disable_unprepare(drvdata->clk); ++ ++ return sprintf(buf, ++ "Depth:\t\t0x%x\n" ++ "Status:\t\t0x%x\n" ++ "RAM read ptr:\t0x%x\n" ++ "RAM wrt ptr:\t0x%x\n" ++ "Trigger cnt:\t0x%x\n" ++ "Control:\t0x%x\n" ++ "Flush status:\t0x%x\n" ++ "Flush ctrl:\t0x%x\n", ++ etb_rdr, etb_sr, etb_rrp, etb_rwp, ++ etb_trg, etb_cr, etb_ffsr, etb_ffcr); ++out: ++ return -EINVAL; ++} ++static DEVICE_ATTR_RO(status); ++ ++static ssize_t trigger_cntr_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ unsigned long val = drvdata->trigger_cntr; ++ ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t trigger_cntr_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ drvdata->trigger_cntr = val; ++ return size; ++} ++static DEVICE_ATTR_RW(trigger_cntr); ++ ++static struct attribute *coresight_etb_attrs[] = { ++ &dev_attr_trigger_cntr.attr, ++ &dev_attr_status.attr, ++ NULL, ++}; ++ATTRIBUTE_GROUPS(coresight_etb); ++ ++static int etb_probe(struct amba_device *adev, const struct amba_id *id) ++{ ++ int ret; ++ void __iomem *base; ++ struct device *dev = &adev->dev; ++ struct coresight_platform_data *pdata = NULL; ++ struct etb_drvdata *drvdata; ++ struct resource *res = &adev->res; ++ struct coresight_desc *desc; ++ struct device_node *np = adev->dev.of_node; ++ ++ if (np) { ++ pdata = of_get_coresight_platform_data(dev, np); ++ if (IS_ERR(pdata)) ++ return PTR_ERR(pdata); ++ adev->dev.platform_data = pdata; ++ } ++ ++ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); ++ if (!drvdata) ++ return -ENOMEM; ++ ++ drvdata->dev = &adev->dev; ++ dev_set_drvdata(dev, drvdata); ++ ++ /* validity for the resource is already checked by the AMBA core */ ++ base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ drvdata->base = base; ++ ++ spin_lock_init(&drvdata->spinlock); ++ ++ drvdata->clk = adev->pclk; ++ ret = clk_prepare_enable(drvdata->clk); ++ if (ret) ++ return ret; ++ ++ drvdata->buffer_depth = etb_get_buffer_depth(drvdata); ++ clk_disable_unprepare(drvdata->clk); ++ ++ if (drvdata->buffer_depth < 0) ++ return -EINVAL; ++ ++ drvdata->buf = devm_kzalloc(dev, ++ drvdata->buffer_depth * 4, GFP_KERNEL); ++ if (!drvdata->buf) ++ return -ENOMEM; ++ ++ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); ++ if (!desc) ++ return -ENOMEM; ++ ++ desc->type = CORESIGHT_DEV_TYPE_SINK; ++ desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER; ++ desc->ops = &etb_cs_ops; ++ desc->pdata = pdata; ++ desc->dev = dev; ++ desc->groups = coresight_etb_groups; ++ drvdata->csdev = coresight_register(desc); ++ if (IS_ERR(drvdata->csdev)) ++ return PTR_ERR(drvdata->csdev); ++ ++ drvdata->miscdev.name = pdata->name; ++ drvdata->miscdev.minor = MISC_DYNAMIC_MINOR; ++ drvdata->miscdev.fops = &etb_fops; ++ ret = misc_register(&drvdata->miscdev); ++ if (ret) ++ goto err_misc_register; ++ ++ dev_info(dev, "ETB initialized\n"); ++ return 0; ++ ++err_misc_register: ++ coresight_unregister(drvdata->csdev); ++ return ret; ++} ++ ++static int etb_remove(struct amba_device *adev) ++{ ++ struct etb_drvdata *drvdata = amba_get_drvdata(adev); ++ ++ misc_deregister(&drvdata->miscdev); ++ coresight_unregister(drvdata->csdev); ++ return 0; ++} ++ ++static struct amba_id etb_ids[] = { ++ { ++ .id = 0x0003b907, ++ .mask = 0x0003ffff, ++ }, ++ { 0, 0}, ++}; ++ ++static struct amba_driver etb_driver = { ++ .drv = { ++ .name = "coresight-etb10", ++ .owner = THIS_MODULE, ++ }, ++ .probe = etb_probe, ++ .remove = etb_remove, ++ .id_table = etb_ids, ++}; ++ ++module_amba_driver(etb_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("CoreSight Embedded Trace Buffer driver"); +diff --git a/drivers/hwtracing/coresight/coresight-etm-cp14.c b/drivers/hwtracing/coresight/coresight-etm-cp14.c +new file mode 100644 +index 0000000..12a2206 +--- /dev/null ++++ b/drivers/hwtracing/coresight/coresight-etm-cp14.c +@@ -0,0 +1,591 @@ ++/* Copyright (c) 2012, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * 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 ++#include ++#include ++#include ++ ++#include "coresight-etm.h" ++ ++int etm_readl_cp14(u32 reg, unsigned int *val) ++{ ++ switch (reg) { ++ case ETMCR: ++ *val = etm_read(ETMCR); ++ return 0; ++ case ETMCCR: ++ *val = etm_read(ETMCCR); ++ return 0; ++ case ETMTRIGGER: ++ *val = etm_read(ETMTRIGGER); ++ return 0; ++ case ETMSR: ++ *val = etm_read(ETMSR); ++ return 0; ++ case ETMSCR: ++ *val = etm_read(ETMSCR); ++ return 0; ++ case ETMTSSCR: ++ *val = etm_read(ETMTSSCR); ++ return 0; ++ case ETMTEEVR: ++ *val = etm_read(ETMTEEVR); ++ return 0; ++ case ETMTECR1: ++ *val = etm_read(ETMTECR1); ++ return 0; ++ case ETMFFLR: ++ *val = etm_read(ETMFFLR); ++ return 0; ++ case ETMACVRn(0): ++ *val = etm_read(ETMACVR0); ++ return 0; ++ case ETMACVRn(1): ++ *val = etm_read(ETMACVR1); ++ return 0; ++ case ETMACVRn(2): ++ *val = etm_read(ETMACVR2); ++ return 0; ++ case ETMACVRn(3): ++ *val = etm_read(ETMACVR3); ++ return 0; ++ case ETMACVRn(4): ++ *val = etm_read(ETMACVR4); ++ return 0; ++ case ETMACVRn(5): ++ *val = etm_read(ETMACVR5); ++ return 0; ++ case ETMACVRn(6): ++ *val = etm_read(ETMACVR6); ++ return 0; ++ case ETMACVRn(7): ++ *val = etm_read(ETMACVR7); ++ return 0; ++ case ETMACVRn(8): ++ *val = etm_read(ETMACVR8); ++ return 0; ++ case ETMACVRn(9): ++ *val = etm_read(ETMACVR9); ++ return 0; ++ case ETMACVRn(10): ++ *val = etm_read(ETMACVR10); ++ return 0; ++ case ETMACVRn(11): ++ *val = etm_read(ETMACVR11); ++ return 0; ++ case ETMACVRn(12): ++ *val = etm_read(ETMACVR12); ++ return 0; ++ case ETMACVRn(13): ++ *val = etm_read(ETMACVR13); ++ return 0; ++ case ETMACVRn(14): ++ *val = etm_read(ETMACVR14); ++ return 0; ++ case ETMACVRn(15): ++ *val = etm_read(ETMACVR15); ++ return 0; ++ case ETMACTRn(0): ++ *val = etm_read(ETMACTR0); ++ return 0; ++ case ETMACTRn(1): ++ *val = etm_read(ETMACTR1); ++ return 0; ++ case ETMACTRn(2): ++ *val = etm_read(ETMACTR2); ++ return 0; ++ case ETMACTRn(3): ++ *val = etm_read(ETMACTR3); ++ return 0; ++ case ETMACTRn(4): ++ *val = etm_read(ETMACTR4); ++ return 0; ++ case ETMACTRn(5): ++ *val = etm_read(ETMACTR5); ++ return 0; ++ case ETMACTRn(6): ++ *val = etm_read(ETMACTR6); ++ return 0; ++ case ETMACTRn(7): ++ *val = etm_read(ETMACTR7); ++ return 0; ++ case ETMACTRn(8): ++ *val = etm_read(ETMACTR8); ++ return 0; ++ case ETMACTRn(9): ++ *val = etm_read(ETMACTR9); ++ return 0; ++ case ETMACTRn(10): ++ *val = etm_read(ETMACTR10); ++ return 0; ++ case ETMACTRn(11): ++ *val = etm_read(ETMACTR11); ++ return 0; ++ case ETMACTRn(12): ++ *val = etm_read(ETMACTR12); ++ return 0; ++ case ETMACTRn(13): ++ *val = etm_read(ETMACTR13); ++ return 0; ++ case ETMACTRn(14): ++ *val = etm_read(ETMACTR14); ++ return 0; ++ case ETMACTRn(15): ++ *val = etm_read(ETMACTR15); ++ return 0; ++ case ETMCNTRLDVRn(0): ++ *val = etm_read(ETMCNTRLDVR0); ++ return 0; ++ case ETMCNTRLDVRn(1): ++ *val = etm_read(ETMCNTRLDVR1); ++ return 0; ++ case ETMCNTRLDVRn(2): ++ *val = etm_read(ETMCNTRLDVR2); ++ return 0; ++ case ETMCNTRLDVRn(3): ++ *val = etm_read(ETMCNTRLDVR3); ++ return 0; ++ case ETMCNTENRn(0): ++ *val = etm_read(ETMCNTENR0); ++ return 0; ++ case ETMCNTENRn(1): ++ *val = etm_read(ETMCNTENR1); ++ return 0; ++ case ETMCNTENRn(2): ++ *val = etm_read(ETMCNTENR2); ++ return 0; ++ case ETMCNTENRn(3): ++ *val = etm_read(ETMCNTENR3); ++ return 0; ++ case ETMCNTRLDEVRn(0): ++ *val = etm_read(ETMCNTRLDEVR0); ++ return 0; ++ case ETMCNTRLDEVRn(1): ++ *val = etm_read(ETMCNTRLDEVR1); ++ return 0; ++ case ETMCNTRLDEVRn(2): ++ *val = etm_read(ETMCNTRLDEVR2); ++ return 0; ++ case ETMCNTRLDEVRn(3): ++ *val = etm_read(ETMCNTRLDEVR3); ++ return 0; ++ case ETMCNTVRn(0): ++ *val = etm_read(ETMCNTVR0); ++ return 0; ++ case ETMCNTVRn(1): ++ *val = etm_read(ETMCNTVR1); ++ return 0; ++ case ETMCNTVRn(2): ++ *val = etm_read(ETMCNTVR2); ++ return 0; ++ case ETMCNTVRn(3): ++ *val = etm_read(ETMCNTVR3); ++ return 0; ++ case ETMSQ12EVR: ++ *val = etm_read(ETMSQ12EVR); ++ return 0; ++ case ETMSQ21EVR: ++ *val = etm_read(ETMSQ21EVR); ++ return 0; ++ case ETMSQ23EVR: ++ *val = etm_read(ETMSQ23EVR); ++ return 0; ++ case ETMSQ31EVR: ++ *val = etm_read(ETMSQ31EVR); ++ return 0; ++ case ETMSQ32EVR: ++ *val = etm_read(ETMSQ32EVR); ++ return 0; ++ case ETMSQ13EVR: ++ *val = etm_read(ETMSQ13EVR); ++ return 0; ++ case ETMSQR: ++ *val = etm_read(ETMSQR); ++ return 0; ++ case ETMEXTOUTEVRn(0): ++ *val = etm_read(ETMEXTOUTEVR0); ++ return 0; ++ case ETMEXTOUTEVRn(1): ++ *val = etm_read(ETMEXTOUTEVR1); ++ return 0; ++ case ETMEXTOUTEVRn(2): ++ *val = etm_read(ETMEXTOUTEVR2); ++ return 0; ++ case ETMEXTOUTEVRn(3): ++ *val = etm_read(ETMEXTOUTEVR3); ++ return 0; ++ case ETMCIDCVRn(0): ++ *val = etm_read(ETMCIDCVR0); ++ return 0; ++ case ETMCIDCVRn(1): ++ *val = etm_read(ETMCIDCVR1); ++ return 0; ++ case ETMCIDCVRn(2): ++ *val = etm_read(ETMCIDCVR2); ++ return 0; ++ case ETMCIDCMR: ++ *val = etm_read(ETMCIDCMR); ++ return 0; ++ case ETMIMPSPEC0: ++ *val = etm_read(ETMIMPSPEC0); ++ return 0; ++ case ETMIMPSPEC1: ++ *val = etm_read(ETMIMPSPEC1); ++ return 0; ++ case ETMIMPSPEC2: ++ *val = etm_read(ETMIMPSPEC2); ++ return 0; ++ case ETMIMPSPEC3: ++ *val = etm_read(ETMIMPSPEC3); ++ return 0; ++ case ETMIMPSPEC4: ++ *val = etm_read(ETMIMPSPEC4); ++ return 0; ++ case ETMIMPSPEC5: ++ *val = etm_read(ETMIMPSPEC5); ++ return 0; ++ case ETMIMPSPEC6: ++ *val = etm_read(ETMIMPSPEC6); ++ return 0; ++ case ETMIMPSPEC7: ++ *val = etm_read(ETMIMPSPEC7); ++ return 0; ++ case ETMSYNCFR: ++ *val = etm_read(ETMSYNCFR); ++ return 0; ++ case ETMIDR: ++ *val = etm_read(ETMIDR); ++ return 0; ++ case ETMCCER: ++ *val = etm_read(ETMCCER); ++ return 0; ++ case ETMEXTINSELR: ++ *val = etm_read(ETMEXTINSELR); ++ return 0; ++ case ETMTESSEICR: ++ *val = etm_read(ETMTESSEICR); ++ return 0; ++ case ETMEIBCR: ++ *val = etm_read(ETMEIBCR); ++ return 0; ++ case ETMTSEVR: ++ *val = etm_read(ETMTSEVR); ++ return 0; ++ case ETMAUXCR: ++ *val = etm_read(ETMAUXCR); ++ return 0; ++ case ETMTRACEIDR: ++ *val = etm_read(ETMTRACEIDR); ++ return 0; ++ case ETMVMIDCVR: ++ *val = etm_read(ETMVMIDCVR); ++ return 0; ++ case ETMOSLSR: ++ *val = etm_read(ETMOSLSR); ++ return 0; ++ case ETMOSSRR: ++ *val = etm_read(ETMOSSRR); ++ return 0; ++ case ETMPDCR: ++ *val = etm_read(ETMPDCR); ++ return 0; ++ case ETMPDSR: ++ *val = etm_read(ETMPDSR); ++ return 0; ++ default: ++ *val = 0; ++ return -EINVAL; ++ } ++} ++ ++int etm_writel_cp14(u32 reg, u32 val) ++{ ++ switch (reg) { ++ case ETMCR: ++ etm_write(val, ETMCR); ++ break; ++ case ETMTRIGGER: ++ etm_write(val, ETMTRIGGER); ++ break; ++ case ETMSR: ++ etm_write(val, ETMSR); ++ break; ++ case ETMTSSCR: ++ etm_write(val, ETMTSSCR); ++ break; ++ case ETMTEEVR: ++ etm_write(val, ETMTEEVR); ++ break; ++ case ETMTECR1: ++ etm_write(val, ETMTECR1); ++ break; ++ case ETMFFLR: ++ etm_write(val, ETMFFLR); ++ break; ++ case ETMACVRn(0): ++ etm_write(val, ETMACVR0); ++ break; ++ case ETMACVRn(1): ++ etm_write(val, ETMACVR1); ++ break; ++ case ETMACVRn(2): ++ etm_write(val, ETMACVR2); ++ break; ++ case ETMACVRn(3): ++ etm_write(val, ETMACVR3); ++ break; ++ case ETMACVRn(4): ++ etm_write(val, ETMACVR4); ++ break; ++ case ETMACVRn(5): ++ etm_write(val, ETMACVR5); ++ break; ++ case ETMACVRn(6): ++ etm_write(val, ETMACVR6); ++ break; ++ case ETMACVRn(7): ++ etm_write(val, ETMACVR7); ++ break; ++ case ETMACVRn(8): ++ etm_write(val, ETMACVR8); ++ break; ++ case ETMACVRn(9): ++ etm_write(val, ETMACVR9); ++ break; ++ case ETMACVRn(10): ++ etm_write(val, ETMACVR10); ++ break; ++ case ETMACVRn(11): ++ etm_write(val, ETMACVR11); ++ break; ++ case ETMACVRn(12): ++ etm_write(val, ETMACVR12); ++ break; ++ case ETMACVRn(13): ++ etm_write(val, ETMACVR13); ++ break; ++ case ETMACVRn(14): ++ etm_write(val, ETMACVR14); ++ break; ++ case ETMACVRn(15): ++ etm_write(val, ETMACVR15); ++ break; ++ case ETMACTRn(0): ++ etm_write(val, ETMACTR0); ++ break; ++ case ETMACTRn(1): ++ etm_write(val, ETMACTR1); ++ break; ++ case ETMACTRn(2): ++ etm_write(val, ETMACTR2); ++ break; ++ case ETMACTRn(3): ++ etm_write(val, ETMACTR3); ++ break; ++ case ETMACTRn(4): ++ etm_write(val, ETMACTR4); ++ break; ++ case ETMACTRn(5): ++ etm_write(val, ETMACTR5); ++ break; ++ case ETMACTRn(6): ++ etm_write(val, ETMACTR6); ++ break; ++ case ETMACTRn(7): ++ etm_write(val, ETMACTR7); ++ break; ++ case ETMACTRn(8): ++ etm_write(val, ETMACTR8); ++ break; ++ case ETMACTRn(9): ++ etm_write(val, ETMACTR9); ++ break; ++ case ETMACTRn(10): ++ etm_write(val, ETMACTR10); ++ break; ++ case ETMACTRn(11): ++ etm_write(val, ETMACTR11); ++ break; ++ case ETMACTRn(12): ++ etm_write(val, ETMACTR12); ++ break; ++ case ETMACTRn(13): ++ etm_write(val, ETMACTR13); ++ break; ++ case ETMACTRn(14): ++ etm_write(val, ETMACTR14); ++ break; ++ case ETMACTRn(15): ++ etm_write(val, ETMACTR15); ++ break; ++ case ETMCNTRLDVRn(0): ++ etm_write(val, ETMCNTRLDVR0); ++ break; ++ case ETMCNTRLDVRn(1): ++ etm_write(val, ETMCNTRLDVR1); ++ break; ++ case ETMCNTRLDVRn(2): ++ etm_write(val, ETMCNTRLDVR2); ++ break; ++ case ETMCNTRLDVRn(3): ++ etm_write(val, ETMCNTRLDVR3); ++ break; ++ case ETMCNTENRn(0): ++ etm_write(val, ETMCNTENR0); ++ break; ++ case ETMCNTENRn(1): ++ etm_write(val, ETMCNTENR1); ++ break; ++ case ETMCNTENRn(2): ++ etm_write(val, ETMCNTENR2); ++ break; ++ case ETMCNTENRn(3): ++ etm_write(val, ETMCNTENR3); ++ break; ++ case ETMCNTRLDEVRn(0): ++ etm_write(val, ETMCNTRLDEVR0); ++ break; ++ case ETMCNTRLDEVRn(1): ++ etm_write(val, ETMCNTRLDEVR1); ++ break; ++ case ETMCNTRLDEVRn(2): ++ etm_write(val, ETMCNTRLDEVR2); ++ break; ++ case ETMCNTRLDEVRn(3): ++ etm_write(val, ETMCNTRLDEVR3); ++ break; ++ case ETMCNTVRn(0): ++ etm_write(val, ETMCNTVR0); ++ break; ++ case ETMCNTVRn(1): ++ etm_write(val, ETMCNTVR1); ++ break; ++ case ETMCNTVRn(2): ++ etm_write(val, ETMCNTVR2); ++ break; ++ case ETMCNTVRn(3): ++ etm_write(val, ETMCNTVR3); ++ break; ++ case ETMSQ12EVR: ++ etm_write(val, ETMSQ12EVR); ++ break; ++ case ETMSQ21EVR: ++ etm_write(val, ETMSQ21EVR); ++ break; ++ case ETMSQ23EVR: ++ etm_write(val, ETMSQ23EVR); ++ break; ++ case ETMSQ31EVR: ++ etm_write(val, ETMSQ31EVR); ++ break; ++ case ETMSQ32EVR: ++ etm_write(val, ETMSQ32EVR); ++ break; ++ case ETMSQ13EVR: ++ etm_write(val, ETMSQ13EVR); ++ break; ++ case ETMSQR: ++ etm_write(val, ETMSQR); ++ break; ++ case ETMEXTOUTEVRn(0): ++ etm_write(val, ETMEXTOUTEVR0); ++ break; ++ case ETMEXTOUTEVRn(1): ++ etm_write(val, ETMEXTOUTEVR1); ++ break; ++ case ETMEXTOUTEVRn(2): ++ etm_write(val, ETMEXTOUTEVR2); ++ break; ++ case ETMEXTOUTEVRn(3): ++ etm_write(val, ETMEXTOUTEVR3); ++ break; ++ case ETMCIDCVRn(0): ++ etm_write(val, ETMCIDCVR0); ++ break; ++ case ETMCIDCVRn(1): ++ etm_write(val, ETMCIDCVR1); ++ break; ++ case ETMCIDCVRn(2): ++ etm_write(val, ETMCIDCVR2); ++ break; ++ case ETMCIDCMR: ++ etm_write(val, ETMCIDCMR); ++ break; ++ case ETMIMPSPEC0: ++ etm_write(val, ETMIMPSPEC0); ++ break; ++ case ETMIMPSPEC1: ++ etm_write(val, ETMIMPSPEC1); ++ break; ++ case ETMIMPSPEC2: ++ etm_write(val, ETMIMPSPEC2); ++ break; ++ case ETMIMPSPEC3: ++ etm_write(val, ETMIMPSPEC3); ++ break; ++ case ETMIMPSPEC4: ++ etm_write(val, ETMIMPSPEC4); ++ break; ++ case ETMIMPSPEC5: ++ etm_write(val, ETMIMPSPEC5); ++ break; ++ case ETMIMPSPEC6: ++ etm_write(val, ETMIMPSPEC6); ++ break; ++ case ETMIMPSPEC7: ++ etm_write(val, ETMIMPSPEC7); ++ break; ++ case ETMSYNCFR: ++ etm_write(val, ETMSYNCFR); ++ break; ++ case ETMEXTINSELR: ++ etm_write(val, ETMEXTINSELR); ++ break; ++ case ETMTESSEICR: ++ etm_write(val, ETMTESSEICR); ++ break; ++ case ETMEIBCR: ++ etm_write(val, ETMEIBCR); ++ break; ++ case ETMTSEVR: ++ etm_write(val, ETMTSEVR); ++ break; ++ case ETMAUXCR: ++ etm_write(val, ETMAUXCR); ++ break; ++ case ETMTRACEIDR: ++ etm_write(val, ETMTRACEIDR); ++ break; ++ case ETMVMIDCVR: ++ etm_write(val, ETMVMIDCVR); ++ break; ++ case ETMOSLAR: ++ etm_write(val, ETMOSLAR); ++ break; ++ case ETMOSSRR: ++ etm_write(val, ETMOSSRR); ++ break; ++ case ETMPDCR: ++ etm_write(val, ETMPDCR); ++ break; ++ case ETMPDSR: ++ etm_write(val, ETMPDSR); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} +diff --git a/drivers/hwtracing/coresight/coresight-etm.h b/drivers/hwtracing/coresight/coresight-etm.h +new file mode 100644 +index 0000000..501c5fa +--- /dev/null ++++ b/drivers/hwtracing/coresight/coresight-etm.h +@@ -0,0 +1,251 @@ ++/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * 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 _CORESIGHT_CORESIGHT_ETM_H ++#define _CORESIGHT_CORESIGHT_ETM_H ++ ++#include ++#include "coresight-priv.h" ++ ++/* ++ * Device registers: ++ * 0x000 - 0x2FC: Trace registers ++ * 0x300 - 0x314: Management registers ++ * 0x318 - 0xEFC: Trace registers ++ * ++ * Coresight registers ++ * 0xF00 - 0xF9C: Management registers ++ * 0xFA0 - 0xFA4: Management registers in PFTv1.0 ++ * Trace registers in PFTv1.1 ++ * 0xFA8 - 0xFFC: Management registers ++ */ ++ ++/* Trace registers (0x000-0x2FC) */ ++#define ETMCR 0x000 ++#define ETMCCR 0x004 ++#define ETMTRIGGER 0x008 ++#define ETMSR 0x010 ++#define ETMSCR 0x014 ++#define ETMTSSCR 0x018 ++#define ETMTECR2 0x01c ++#define ETMTEEVR 0x020 ++#define ETMTECR1 0x024 ++#define ETMFFLR 0x02c ++#define ETMACVRn(n) (0x040 + (n * 4)) ++#define ETMACTRn(n) (0x080 + (n * 4)) ++#define ETMCNTRLDVRn(n) (0x140 + (n * 4)) ++#define ETMCNTENRn(n) (0x150 + (n * 4)) ++#define ETMCNTRLDEVRn(n) (0x160 + (n * 4)) ++#define ETMCNTVRn(n) (0x170 + (n * 4)) ++#define ETMSQ12EVR 0x180 ++#define ETMSQ21EVR 0x184 ++#define ETMSQ23EVR 0x188 ++#define ETMSQ31EVR 0x18c ++#define ETMSQ32EVR 0x190 ++#define ETMSQ13EVR 0x194 ++#define ETMSQR 0x19c ++#define ETMEXTOUTEVRn(n) (0x1a0 + (n * 4)) ++#define ETMCIDCVRn(n) (0x1b0 + (n * 4)) ++#define ETMCIDCMR 0x1bc ++#define ETMIMPSPEC0 0x1c0 ++#define ETMIMPSPEC1 0x1c4 ++#define ETMIMPSPEC2 0x1c8 ++#define ETMIMPSPEC3 0x1cc ++#define ETMIMPSPEC4 0x1d0 ++#define ETMIMPSPEC5 0x1d4 ++#define ETMIMPSPEC6 0x1d8 ++#define ETMIMPSPEC7 0x1dc ++#define ETMSYNCFR 0x1e0 ++#define ETMIDR 0x1e4 ++#define ETMCCER 0x1e8 ++#define ETMEXTINSELR 0x1ec ++#define ETMTESSEICR 0x1f0 ++#define ETMEIBCR 0x1f4 ++#define ETMTSEVR 0x1f8 ++#define ETMAUXCR 0x1fc ++#define ETMTRACEIDR 0x200 ++#define ETMVMIDCVR 0x240 ++/* Management registers (0x300-0x314) */ ++#define ETMOSLAR 0x300 ++#define ETMOSLSR 0x304 ++#define ETMOSSRR 0x308 ++#define ETMPDCR 0x310 ++#define ETMPDSR 0x314 ++#define ETM_MAX_ADDR_CMP 16 ++#define ETM_MAX_CNTR 4 ++#define ETM_MAX_CTXID_CMP 3 ++ ++/* Register definition */ ++/* ETMCR - 0x00 */ ++#define ETMCR_PWD_DWN BIT(0) ++#define ETMCR_STALL_MODE BIT(7) ++#define ETMCR_ETM_PRG BIT(10) ++#define ETMCR_ETM_EN BIT(11) ++#define ETMCR_CYC_ACC BIT(12) ++#define ETMCR_CTXID_SIZE (BIT(14)|BIT(15)) ++#define ETMCR_TIMESTAMP_EN BIT(28) ++/* ETMCCR - 0x04 */ ++#define ETMCCR_FIFOFULL BIT(23) ++/* ETMPDCR - 0x310 */ ++#define ETMPDCR_PWD_UP BIT(3) ++/* ETMTECR1 - 0x024 */ ++#define ETMTECR1_ADDR_COMP_1 BIT(0) ++#define ETMTECR1_INC_EXC BIT(24) ++#define ETMTECR1_START_STOP BIT(25) ++/* ETMCCER - 0x1E8 */ ++#define ETMCCER_TIMESTAMP BIT(22) ++ ++#define ETM_MODE_EXCLUDE BIT(0) ++#define ETM_MODE_CYCACC BIT(1) ++#define ETM_MODE_STALL BIT(2) ++#define ETM_MODE_TIMESTAMP BIT(3) ++#define ETM_MODE_CTXID BIT(4) ++#define ETM_MODE_ALL 0x1f ++ ++#define ETM_SQR_MASK 0x3 ++#define ETM_TRACEID_MASK 0x3f ++#define ETM_EVENT_MASK 0x1ffff ++#define ETM_SYNC_MASK 0xfff ++#define ETM_ALL_MASK 0xffffffff ++ ++#define ETMSR_PROG_BIT 1 ++#define ETM_SEQ_STATE_MAX_VAL (0x2) ++#define PORT_SIZE_MASK (GENMASK(21, 21) | GENMASK(6, 4)) ++ ++#define ETM_HARD_WIRE_RES_A /* Hard wired, always true */ \ ++ ((0x0f << 0) | \ ++ /* Resource index A */ \ ++ (0x06 << 4)) ++ ++#define ETM_ADD_COMP_0 /* Single addr comparator 1 */ \ ++ ((0x00 << 7) | \ ++ /* Resource index B */ \ ++ (0x00 << 11)) ++ ++#define ETM_EVENT_NOT_A BIT(14) /* NOT(A) */ ++ ++#define ETM_DEFAULT_EVENT_VAL (ETM_HARD_WIRE_RES_A | \ ++ ETM_ADD_COMP_0 | \ ++ ETM_EVENT_NOT_A) ++/** ++ * struct etm_drvdata - specifics associated to an ETM component ++ * @base: memory mapped base address for this component. ++ * @dev: the device entity associated to this component. ++ * @csdev: component vitals needed by the framework. ++ * @clk: the clock this component is associated to. ++ * @spinlock: only one at a time pls. ++ * @cpu: the cpu this component is affined to. ++ * @port_size: port size as reported by ETMCR bit 4-6 and 21. ++ * @arch: ETM/PTM version number. ++ * @use_cpu14: true if management registers need to be accessed via CP14. ++ * @enable: is this ETM/PTM currently tracing. ++ * @sticky_enable: true if ETM base configuration has been done. ++ * @boot_enable:true if we should start tracing at boot time. ++ * @os_unlock: true if access to management registers is allowed. ++ * @nr_addr_cmp:Number of pairs of address comparators as found in ETMCCR. ++ * @nr_cntr: Number of counters as found in ETMCCR bit 13-15. ++ * @nr_ext_inp: Number of external input as found in ETMCCR bit 17-19. ++ * @nr_ext_out: Number of external output as found in ETMCCR bit 20-22. ++ * @nr_ctxid_cmp: Number of contextID comparators as found in ETMCCR bit 24-25. ++ * @etmccr: value of register ETMCCR. ++ * @etmccer: value of register ETMCCER. ++ * @traceid: value of the current ID for this component. ++ * @mode: controls various modes supported by this ETM/PTM. ++ * @ctrl: used in conjunction with @mode. ++ * @trigger_event: setting for register ETMTRIGGER. ++ * @startstop_ctrl: setting for register ETMTSSCR. ++ * @enable_event: setting for register ETMTEEVR. ++ * @enable_ctrl1: setting for register ETMTECR1. ++ * @fifofull_level: setting for register ETMFFLR. ++ * @addr_idx: index for the address comparator selection. ++ * @addr_val: value for address comparator register. ++ * @addr_acctype: access type for address comparator register. ++ * @addr_type: current status of the comparator register. ++ * @cntr_idx: index for the counter register selection. ++ * @cntr_rld_val: reload value of a counter register. ++ * @cntr_event: control for counter enable register. ++ * @cntr_rld_event: value for counter reload event register. ++ * @cntr_val: counter value register. ++ * @seq_12_event: event causing the transition from 1 to 2. ++ * @seq_21_event: event causing the transition from 2 to 1. ++ * @seq_23_event: event causing the transition from 2 to 3. ++ * @seq_31_event: event causing the transition from 3 to 1. ++ * @seq_32_event: event causing the transition from 3 to 2. ++ * @seq_13_event: event causing the transition from 1 to 3. ++ * @seq_curr_state: current value of the sequencer register. ++ * @ctxid_idx: index for the context ID registers. ++ * @ctxid_val: value for the context ID to trigger on. ++ * @ctxid_mask: mask applicable to all the context IDs. ++ * @sync_freq: Synchronisation frequency. ++ * @timestamp_event: Defines an event that requests the insertion ++ of a timestamp into the trace stream. ++ */ ++struct etm_drvdata { ++ void __iomem *base; ++ struct device *dev; ++ struct coresight_device *csdev; ++ struct clk *clk; ++ spinlock_t spinlock; ++ int cpu; ++ int port_size; ++ u8 arch; ++ bool use_cp14; ++ bool enable; ++ bool sticky_enable; ++ bool boot_enable; ++ bool os_unlock; ++ u8 nr_addr_cmp; ++ u8 nr_cntr; ++ u8 nr_ext_inp; ++ u8 nr_ext_out; ++ u8 nr_ctxid_cmp; ++ u32 etmccr; ++ u32 etmccer; ++ u32 traceid; ++ u32 mode; ++ u32 ctrl; ++ u32 trigger_event; ++ u32 startstop_ctrl; ++ u32 enable_event; ++ u32 enable_ctrl1; ++ u32 fifofull_level; ++ u8 addr_idx; ++ u32 addr_val[ETM_MAX_ADDR_CMP]; ++ u32 addr_acctype[ETM_MAX_ADDR_CMP]; ++ u32 addr_type[ETM_MAX_ADDR_CMP]; ++ u8 cntr_idx; ++ u32 cntr_rld_val[ETM_MAX_CNTR]; ++ u32 cntr_event[ETM_MAX_CNTR]; ++ u32 cntr_rld_event[ETM_MAX_CNTR]; ++ u32 cntr_val[ETM_MAX_CNTR]; ++ u32 seq_12_event; ++ u32 seq_21_event; ++ u32 seq_23_event; ++ u32 seq_31_event; ++ u32 seq_32_event; ++ u32 seq_13_event; ++ u32 seq_curr_state; ++ u8 ctxid_idx; ++ u32 ctxid_val[ETM_MAX_CTXID_CMP]; ++ u32 ctxid_mask; ++ u32 sync_freq; ++ u32 timestamp_event; ++}; ++ ++enum etm_addr_type { ++ ETM_ADDR_TYPE_NONE, ++ ETM_ADDR_TYPE_SINGLE, ++ ETM_ADDR_TYPE_RANGE, ++ ETM_ADDR_TYPE_START, ++ ETM_ADDR_TYPE_STOP, ++}; ++#endif +diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c +new file mode 100644 +index 0000000..c965f57 +--- /dev/null ++++ b/drivers/hwtracing/coresight/coresight-etm3x.c +@@ -0,0 +1,1932 @@ ++/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "coresight-etm.h" ++ ++static int boot_enable; ++module_param_named(boot_enable, boot_enable, int, S_IRUGO); ++ ++/* The number of ETM/PTM currently registered */ ++static int etm_count; ++static struct etm_drvdata *etmdrvdata[NR_CPUS]; ++ ++static inline void etm_writel(struct etm_drvdata *drvdata, ++ u32 val, u32 off) ++{ ++ if (drvdata->use_cp14) { ++ if (etm_writel_cp14(off, val)) { ++ dev_err(drvdata->dev, ++ "invalid CP14 access to ETM reg: %#x", off); ++ } ++ } else { ++ writel_relaxed(val, drvdata->base + off); ++ } ++} ++ ++static inline unsigned int etm_readl(struct etm_drvdata *drvdata, u32 off) ++{ ++ u32 val; ++ ++ if (drvdata->use_cp14) { ++ if (etm_readl_cp14(off, &val)) { ++ dev_err(drvdata->dev, ++ "invalid CP14 access to ETM reg: %#x", off); ++ } ++ } else { ++ val = readl_relaxed(drvdata->base + off); ++ } ++ ++ return val; ++} ++ ++/* ++ * Memory mapped writes to clear os lock are not supported on some processors ++ * and OS lock must be unlocked before any memory mapped access on such ++ * processors, otherwise memory mapped reads/writes will be invalid. ++ */ ++static void etm_os_unlock(void *info) ++{ ++ struct etm_drvdata *drvdata = (struct etm_drvdata *)info; ++ /* Writing any value to ETMOSLAR unlocks the trace registers */ ++ etm_writel(drvdata, 0x0, ETMOSLAR); ++ isb(); ++} ++ ++static void etm_set_pwrdwn(struct etm_drvdata *drvdata) ++{ ++ u32 etmcr; ++ ++ /* Ensure pending cp14 accesses complete before setting pwrdwn */ ++ mb(); ++ isb(); ++ etmcr = etm_readl(drvdata, ETMCR); ++ etmcr |= ETMCR_PWD_DWN; ++ etm_writel(drvdata, etmcr, ETMCR); ++} ++ ++static void etm_clr_pwrdwn(struct etm_drvdata *drvdata) ++{ ++ u32 etmcr; ++ ++ etmcr = etm_readl(drvdata, ETMCR); ++ etmcr &= ~ETMCR_PWD_DWN; ++ etm_writel(drvdata, etmcr, ETMCR); ++ /* Ensure pwrup completes before subsequent cp14 accesses */ ++ mb(); ++ isb(); ++} ++ ++static void etm_set_pwrup(struct etm_drvdata *drvdata) ++{ ++ u32 etmpdcr; ++ ++ etmpdcr = readl_relaxed(drvdata->base + ETMPDCR); ++ etmpdcr |= ETMPDCR_PWD_UP; ++ writel_relaxed(etmpdcr, drvdata->base + ETMPDCR); ++ /* Ensure pwrup completes before subsequent cp14 accesses */ ++ mb(); ++ isb(); ++} ++ ++static void etm_clr_pwrup(struct etm_drvdata *drvdata) ++{ ++ u32 etmpdcr; ++ ++ /* Ensure pending cp14 accesses complete before clearing pwrup */ ++ mb(); ++ isb(); ++ etmpdcr = readl_relaxed(drvdata->base + ETMPDCR); ++ etmpdcr &= ~ETMPDCR_PWD_UP; ++ writel_relaxed(etmpdcr, drvdata->base + ETMPDCR); ++} ++ ++/** ++ * coresight_timeout_etm - loop until a bit has changed to a specific state. ++ * @drvdata: etm's private data structure. ++ * @offset: address of a register, starting from @addr. ++ * @position: the position of the bit of interest. ++ * @value: the value the bit should have. ++ * ++ * Basically the same as @coresight_timeout except for the register access ++ * method where we have to account for CP14 configurations. ++ ++ * Return: 0 as soon as the bit has taken the desired state or -EAGAIN if ++ * TIMEOUT_US has elapsed, which ever happens first. ++ */ ++ ++static int coresight_timeout_etm(struct etm_drvdata *drvdata, u32 offset, ++ int position, int value) ++{ ++ int i; ++ u32 val; ++ ++ for (i = TIMEOUT_US; i > 0; i--) { ++ val = etm_readl(drvdata, offset); ++ /* Waiting on the bit to go from 0 to 1 */ ++ if (value) { ++ if (val & BIT(position)) ++ return 0; ++ /* Waiting on the bit to go from 1 to 0 */ ++ } else { ++ if (!(val & BIT(position))) ++ return 0; ++ } ++ ++ /* ++ * Delay is arbitrary - the specification doesn't say how long ++ * we are expected to wait. Extra check required to make sure ++ * we don't wait needlessly on the last iteration. ++ */ ++ if (i - 1) ++ udelay(1); ++ } ++ ++ return -EAGAIN; ++} ++ ++ ++static void etm_set_prog(struct etm_drvdata *drvdata) ++{ ++ u32 etmcr; ++ ++ etmcr = etm_readl(drvdata, ETMCR); ++ etmcr |= ETMCR_ETM_PRG; ++ etm_writel(drvdata, etmcr, ETMCR); ++ /* ++ * Recommended by spec for cp14 accesses to ensure etmcr write is ++ * complete before polling etmsr ++ */ ++ isb(); ++ if (coresight_timeout_etm(drvdata, ETMSR, ETMSR_PROG_BIT, 1)) { ++ dev_err(drvdata->dev, ++ "timeout observed when probing at offset %#x\n", ETMSR); ++ } ++} ++ ++static void etm_clr_prog(struct etm_drvdata *drvdata) ++{ ++ u32 etmcr; ++ ++ etmcr = etm_readl(drvdata, ETMCR); ++ etmcr &= ~ETMCR_ETM_PRG; ++ etm_writel(drvdata, etmcr, ETMCR); ++ /* ++ * Recommended by spec for cp14 accesses to ensure etmcr write is ++ * complete before polling etmsr ++ */ ++ isb(); ++ if (coresight_timeout_etm(drvdata, ETMSR, ETMSR_PROG_BIT, 0)) { ++ dev_err(drvdata->dev, ++ "timeout observed when probing at offset %#x\n", ETMSR); ++ } ++} ++ ++static void etm_set_default(struct etm_drvdata *drvdata) ++{ ++ int i; ++ ++ drvdata->trigger_event = ETM_DEFAULT_EVENT_VAL; ++ drvdata->enable_event = ETM_HARD_WIRE_RES_A; ++ ++ drvdata->seq_12_event = ETM_DEFAULT_EVENT_VAL; ++ drvdata->seq_21_event = ETM_DEFAULT_EVENT_VAL; ++ drvdata->seq_23_event = ETM_DEFAULT_EVENT_VAL; ++ drvdata->seq_31_event = ETM_DEFAULT_EVENT_VAL; ++ drvdata->seq_32_event = ETM_DEFAULT_EVENT_VAL; ++ drvdata->seq_13_event = ETM_DEFAULT_EVENT_VAL; ++ drvdata->timestamp_event = ETM_DEFAULT_EVENT_VAL; ++ ++ for (i = 0; i < drvdata->nr_cntr; i++) { ++ drvdata->cntr_rld_val[i] = 0x0; ++ drvdata->cntr_event[i] = ETM_DEFAULT_EVENT_VAL; ++ drvdata->cntr_rld_event[i] = ETM_DEFAULT_EVENT_VAL; ++ drvdata->cntr_val[i] = 0x0; ++ } ++ ++ drvdata->seq_curr_state = 0x0; ++ drvdata->ctxid_idx = 0x0; ++ for (i = 0; i < drvdata->nr_ctxid_cmp; i++) ++ drvdata->ctxid_val[i] = 0x0; ++ drvdata->ctxid_mask = 0x0; ++} ++ ++static void etm_enable_hw(void *info) ++{ ++ int i; ++ u32 etmcr; ++ struct etm_drvdata *drvdata = info; ++ ++ CS_UNLOCK(drvdata->base); ++ ++ /* Turn engine on */ ++ etm_clr_pwrdwn(drvdata); ++ /* Apply power to trace registers */ ++ etm_set_pwrup(drvdata); ++ /* Make sure all registers are accessible */ ++ etm_os_unlock(drvdata); ++ ++ etm_set_prog(drvdata); ++ ++ etmcr = etm_readl(drvdata, ETMCR); ++ etmcr &= (ETMCR_PWD_DWN | ETMCR_ETM_PRG); ++ etmcr |= drvdata->port_size; ++ etm_writel(drvdata, drvdata->ctrl | etmcr, ETMCR); ++ etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER); ++ etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR); ++ etm_writel(drvdata, drvdata->enable_event, ETMTEEVR); ++ etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1); ++ etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR); ++ for (i = 0; i < drvdata->nr_addr_cmp; i++) { ++ etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i)); ++ etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i)); ++ } ++ for (i = 0; i < drvdata->nr_cntr; i++) { ++ etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i)); ++ etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i)); ++ etm_writel(drvdata, drvdata->cntr_rld_event[i], ++ ETMCNTRLDEVRn(i)); ++ etm_writel(drvdata, drvdata->cntr_val[i], ETMCNTVRn(i)); ++ } ++ etm_writel(drvdata, drvdata->seq_12_event, ETMSQ12EVR); ++ etm_writel(drvdata, drvdata->seq_21_event, ETMSQ21EVR); ++ etm_writel(drvdata, drvdata->seq_23_event, ETMSQ23EVR); ++ etm_writel(drvdata, drvdata->seq_31_event, ETMSQ31EVR); ++ etm_writel(drvdata, drvdata->seq_32_event, ETMSQ32EVR); ++ etm_writel(drvdata, drvdata->seq_13_event, ETMSQ13EVR); ++ etm_writel(drvdata, drvdata->seq_curr_state, ETMSQR); ++ for (i = 0; i < drvdata->nr_ext_out; i++) ++ etm_writel(drvdata, ETM_DEFAULT_EVENT_VAL, ETMEXTOUTEVRn(i)); ++ for (i = 0; i < drvdata->nr_ctxid_cmp; i++) ++ etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i)); ++ etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR); ++ etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR); ++ /* No external input selected */ ++ etm_writel(drvdata, 0x0, ETMEXTINSELR); ++ etm_writel(drvdata, drvdata->timestamp_event, ETMTSEVR); ++ /* No auxiliary control selected */ ++ etm_writel(drvdata, 0x0, ETMAUXCR); ++ etm_writel(drvdata, drvdata->traceid, ETMTRACEIDR); ++ /* No VMID comparator value selected */ ++ etm_writel(drvdata, 0x0, ETMVMIDCVR); ++ ++ /* Ensures trace output is enabled from this ETM */ ++ etm_writel(drvdata, drvdata->ctrl | ETMCR_ETM_EN | etmcr, ETMCR); ++ ++ etm_clr_prog(drvdata); ++ CS_LOCK(drvdata->base); ++ ++ dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu); ++} ++ ++static int etm_trace_id_simple(struct etm_drvdata *drvdata) ++{ ++ if (!drvdata->enable) ++ return drvdata->traceid; ++ ++ return (etm_readl(drvdata, ETMTRACEIDR) & ETM_TRACEID_MASK); ++} ++ ++static int etm_trace_id(struct coresight_device *csdev) ++{ ++ struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); ++ unsigned long flags; ++ int trace_id = -1; ++ ++ if (!drvdata->enable) ++ return drvdata->traceid; ++ ++ if (clk_prepare_enable(drvdata->clk)) ++ goto out; ++ ++ spin_lock_irqsave(&drvdata->spinlock, flags); ++ ++ CS_UNLOCK(drvdata->base); ++ trace_id = (etm_readl(drvdata, ETMTRACEIDR) & ETM_TRACEID_MASK); ++ CS_LOCK(drvdata->base); ++ ++ spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ clk_disable_unprepare(drvdata->clk); ++out: ++ return trace_id; ++} ++ ++static int etm_enable(struct coresight_device *csdev) ++{ ++ struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); ++ int ret; ++ ++ ret = clk_prepare_enable(drvdata->clk); ++ if (ret) ++ goto err_clk; ++ ++ spin_lock(&drvdata->spinlock); ++ ++ /* ++ * Configure the ETM only if the CPU is online. If it isn't online ++ * hw configuration will take place when 'CPU_STARTING' is received ++ * in @etm_cpu_callback. ++ */ ++ if (cpu_online(drvdata->cpu)) { ++ ret = smp_call_function_single(drvdata->cpu, ++ etm_enable_hw, drvdata, 1); ++ if (ret) ++ goto err; ++ } ++ ++ drvdata->enable = true; ++ drvdata->sticky_enable = true; ++ ++ spin_unlock(&drvdata->spinlock); ++ ++ dev_info(drvdata->dev, "ETM tracing enabled\n"); ++ return 0; ++err: ++ spin_unlock(&drvdata->spinlock); ++ clk_disable_unprepare(drvdata->clk); ++err_clk: ++ return ret; ++} ++ ++static void etm_disable_hw(void *info) ++{ ++ int i; ++ struct etm_drvdata *drvdata = info; ++ ++ CS_UNLOCK(drvdata->base); ++ etm_set_prog(drvdata); ++ ++ /* Program trace enable to low by using always false event */ ++ etm_writel(drvdata, ETM_HARD_WIRE_RES_A | ETM_EVENT_NOT_A, ETMTEEVR); ++ ++ /* Read back sequencer and counters for post trace analysis */ ++ drvdata->seq_curr_state = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK); ++ ++ for (i = 0; i < drvdata->nr_cntr; i++) ++ drvdata->cntr_val[i] = etm_readl(drvdata, ETMCNTVRn(i)); ++ ++ etm_set_pwrdwn(drvdata); ++ CS_LOCK(drvdata->base); ++ ++ dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu); ++} ++ ++static void etm_disable(struct coresight_device *csdev) ++{ ++ struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); ++ ++ /* ++ * Taking hotplug lock here protects from clocks getting disabled ++ * with tracing being left on (crash scenario) if user disable occurs ++ * after cpu online mask indicates the cpu is offline but before the ++ * DYING hotplug callback is serviced by the ETM driver. ++ */ ++ get_online_cpus(); ++ spin_lock(&drvdata->spinlock); ++ ++ /* ++ * Executing etm_disable_hw on the cpu whose ETM is being disabled ++ * ensures that register writes occur when cpu is powered. ++ */ ++ smp_call_function_single(drvdata->cpu, etm_disable_hw, drvdata, 1); ++ drvdata->enable = false; ++ ++ spin_unlock(&drvdata->spinlock); ++ put_online_cpus(); ++ ++ clk_disable_unprepare(drvdata->clk); ++ ++ dev_info(drvdata->dev, "ETM tracing disabled\n"); ++} ++ ++static const struct coresight_ops_source etm_source_ops = { ++ .trace_id = etm_trace_id, ++ .enable = etm_enable, ++ .disable = etm_disable, ++}; ++ ++static const struct coresight_ops etm_cs_ops = { ++ .source_ops = &etm_source_ops, ++}; ++ ++static ssize_t nr_addr_cmp_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->nr_addr_cmp; ++ return sprintf(buf, "%#lx\n", val); ++} ++static DEVICE_ATTR_RO(nr_addr_cmp); ++ ++static ssize_t nr_cntr_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->nr_cntr; ++ return sprintf(buf, "%#lx\n", val); ++} ++static DEVICE_ATTR_RO(nr_cntr); ++ ++static ssize_t nr_ctxid_cmp_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->nr_ctxid_cmp; ++ return sprintf(buf, "%#lx\n", val); ++} ++static DEVICE_ATTR_RO(nr_ctxid_cmp); ++ ++static ssize_t etmsr_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ int ret; ++ unsigned long flags, val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = clk_prepare_enable(drvdata->clk); ++ if (ret) ++ return ret; ++ ++ spin_lock_irqsave(&drvdata->spinlock, flags); ++ CS_UNLOCK(drvdata->base); ++ ++ val = etm_readl(drvdata, ETMSR); ++ ++ CS_LOCK(drvdata->base); ++ spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ clk_disable_unprepare(drvdata->clk); ++ ++ return sprintf(buf, "%#lx\n", val); ++} ++static DEVICE_ATTR_RO(etmsr); ++ ++static ssize_t reset_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int i, ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ if (val) { ++ spin_lock(&drvdata->spinlock); ++ drvdata->mode = ETM_MODE_EXCLUDE; ++ drvdata->ctrl = 0x0; ++ drvdata->trigger_event = ETM_DEFAULT_EVENT_VAL; ++ drvdata->startstop_ctrl = 0x0; ++ drvdata->addr_idx = 0x0; ++ for (i = 0; i < drvdata->nr_addr_cmp; i++) { ++ drvdata->addr_val[i] = 0x0; ++ drvdata->addr_acctype[i] = 0x0; ++ drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE; ++ } ++ drvdata->cntr_idx = 0x0; ++ ++ etm_set_default(drvdata); ++ spin_unlock(&drvdata->spinlock); ++ } ++ ++ return size; ++} ++static DEVICE_ATTR_WO(reset); ++ ++static ssize_t mode_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->mode; ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t mode_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ spin_lock(&drvdata->spinlock); ++ drvdata->mode = val & ETM_MODE_ALL; ++ ++ if (drvdata->mode & ETM_MODE_EXCLUDE) ++ drvdata->enable_ctrl1 |= ETMTECR1_INC_EXC; ++ else ++ drvdata->enable_ctrl1 &= ~ETMTECR1_INC_EXC; ++ ++ if (drvdata->mode & ETM_MODE_CYCACC) ++ drvdata->ctrl |= ETMCR_CYC_ACC; ++ else ++ drvdata->ctrl &= ~ETMCR_CYC_ACC; ++ ++ if (drvdata->mode & ETM_MODE_STALL) { ++ if (!(drvdata->etmccr & ETMCCR_FIFOFULL)) { ++ dev_warn(drvdata->dev, "stall mode not supported\n"); ++ ret = -EINVAL; ++ goto err_unlock; ++ } ++ drvdata->ctrl |= ETMCR_STALL_MODE; ++ } else ++ drvdata->ctrl &= ~ETMCR_STALL_MODE; ++ ++ if (drvdata->mode & ETM_MODE_TIMESTAMP) { ++ if (!(drvdata->etmccer & ETMCCER_TIMESTAMP)) { ++ dev_warn(drvdata->dev, "timestamp not supported\n"); ++ ret = -EINVAL; ++ goto err_unlock; ++ } ++ drvdata->ctrl |= ETMCR_TIMESTAMP_EN; ++ } else ++ drvdata->ctrl &= ~ETMCR_TIMESTAMP_EN; ++ ++ if (drvdata->mode & ETM_MODE_CTXID) ++ drvdata->ctrl |= ETMCR_CTXID_SIZE; ++ else ++ drvdata->ctrl &= ~ETMCR_CTXID_SIZE; ++ spin_unlock(&drvdata->spinlock); ++ ++ return size; ++ ++err_unlock: ++ spin_unlock(&drvdata->spinlock); ++ return ret; ++} ++static DEVICE_ATTR_RW(mode); ++ ++static ssize_t trigger_event_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->trigger_event; ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t trigger_event_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ drvdata->trigger_event = val & ETM_EVENT_MASK; ++ ++ return size; ++} ++static DEVICE_ATTR_RW(trigger_event); ++ ++static ssize_t enable_event_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->enable_event; ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t enable_event_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ drvdata->enable_event = val & ETM_EVENT_MASK; ++ ++ return size; ++} ++static DEVICE_ATTR_RW(enable_event); ++ ++static ssize_t fifofull_level_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->fifofull_level; ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t fifofull_level_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ drvdata->fifofull_level = val; ++ ++ return size; ++} ++static DEVICE_ATTR_RW(fifofull_level); ++ ++static ssize_t addr_idx_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->addr_idx; ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t addr_idx_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ if (val >= drvdata->nr_addr_cmp) ++ return -EINVAL; ++ ++ /* ++ * Use spinlock to ensure index doesn't change while it gets ++ * dereferenced multiple times within a spinlock block elsewhere. ++ */ ++ spin_lock(&drvdata->spinlock); ++ drvdata->addr_idx = val; ++ spin_unlock(&drvdata->spinlock); ++ ++ return size; ++} ++static DEVICE_ATTR_RW(addr_idx); ++ ++static ssize_t addr_single_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ u8 idx; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ spin_lock(&drvdata->spinlock); ++ idx = drvdata->addr_idx; ++ if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE || ++ drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) { ++ spin_unlock(&drvdata->spinlock); ++ return -EINVAL; ++ } ++ ++ val = drvdata->addr_val[idx]; ++ spin_unlock(&drvdata->spinlock); ++ ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t addr_single_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ u8 idx; ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ spin_lock(&drvdata->spinlock); ++ idx = drvdata->addr_idx; ++ if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE || ++ drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) { ++ spin_unlock(&drvdata->spinlock); ++ return -EINVAL; ++ } ++ ++ drvdata->addr_val[idx] = val; ++ drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE; ++ spin_unlock(&drvdata->spinlock); ++ ++ return size; ++} ++static DEVICE_ATTR_RW(addr_single); ++ ++static ssize_t addr_range_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ u8 idx; ++ unsigned long val1, val2; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ spin_lock(&drvdata->spinlock); ++ idx = drvdata->addr_idx; ++ if (idx % 2 != 0) { ++ spin_unlock(&drvdata->spinlock); ++ return -EPERM; ++ } ++ if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE && ++ drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) || ++ (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE && ++ drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) { ++ spin_unlock(&drvdata->spinlock); ++ return -EPERM; ++ } ++ ++ val1 = drvdata->addr_val[idx]; ++ val2 = drvdata->addr_val[idx + 1]; ++ spin_unlock(&drvdata->spinlock); ++ ++ return sprintf(buf, "%#lx %#lx\n", val1, val2); ++} ++ ++static ssize_t addr_range_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ u8 idx; ++ unsigned long val1, val2; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ if (sscanf(buf, "%lx %lx", &val1, &val2) != 2) ++ return -EINVAL; ++ /* Lower address comparator cannot have a higher address value */ ++ if (val1 > val2) ++ return -EINVAL; ++ ++ spin_lock(&drvdata->spinlock); ++ idx = drvdata->addr_idx; ++ if (idx % 2 != 0) { ++ spin_unlock(&drvdata->spinlock); ++ return -EPERM; ++ } ++ if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE && ++ drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) || ++ (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE && ++ drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) { ++ spin_unlock(&drvdata->spinlock); ++ return -EPERM; ++ } ++ ++ drvdata->addr_val[idx] = val1; ++ drvdata->addr_type[idx] = ETM_ADDR_TYPE_RANGE; ++ drvdata->addr_val[idx + 1] = val2; ++ drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE; ++ drvdata->enable_ctrl1 |= (1 << (idx/2)); ++ spin_unlock(&drvdata->spinlock); ++ ++ return size; ++} ++static DEVICE_ATTR_RW(addr_range); ++ ++static ssize_t addr_start_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ u8 idx; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ spin_lock(&drvdata->spinlock); ++ idx = drvdata->addr_idx; ++ if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE || ++ drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) { ++ spin_unlock(&drvdata->spinlock); ++ return -EPERM; ++ } ++ ++ val = drvdata->addr_val[idx]; ++ spin_unlock(&drvdata->spinlock); ++ ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t addr_start_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ u8 idx; ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ spin_lock(&drvdata->spinlock); ++ idx = drvdata->addr_idx; ++ if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE || ++ drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) { ++ spin_unlock(&drvdata->spinlock); ++ return -EPERM; ++ } ++ ++ drvdata->addr_val[idx] = val; ++ drvdata->addr_type[idx] = ETM_ADDR_TYPE_START; ++ drvdata->startstop_ctrl |= (1 << idx); ++ drvdata->enable_ctrl1 |= BIT(25); ++ spin_unlock(&drvdata->spinlock); ++ ++ return size; ++} ++static DEVICE_ATTR_RW(addr_start); ++ ++static ssize_t addr_stop_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ u8 idx; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ spin_lock(&drvdata->spinlock); ++ idx = drvdata->addr_idx; ++ if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE || ++ drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) { ++ spin_unlock(&drvdata->spinlock); ++ return -EPERM; ++ } ++ ++ val = drvdata->addr_val[idx]; ++ spin_unlock(&drvdata->spinlock); ++ ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t addr_stop_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ u8 idx; ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ spin_lock(&drvdata->spinlock); ++ idx = drvdata->addr_idx; ++ if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE || ++ drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) { ++ spin_unlock(&drvdata->spinlock); ++ return -EPERM; ++ } ++ ++ drvdata->addr_val[idx] = val; ++ drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP; ++ drvdata->startstop_ctrl |= (1 << (idx + 16)); ++ drvdata->enable_ctrl1 |= ETMTECR1_START_STOP; ++ spin_unlock(&drvdata->spinlock); ++ ++ return size; ++} ++static DEVICE_ATTR_RW(addr_stop); ++ ++static ssize_t addr_acctype_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ spin_lock(&drvdata->spinlock); ++ val = drvdata->addr_acctype[drvdata->addr_idx]; ++ spin_unlock(&drvdata->spinlock); ++ ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t addr_acctype_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ spin_lock(&drvdata->spinlock); ++ drvdata->addr_acctype[drvdata->addr_idx] = val; ++ spin_unlock(&drvdata->spinlock); ++ ++ return size; ++} ++static DEVICE_ATTR_RW(addr_acctype); ++ ++static ssize_t cntr_idx_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->cntr_idx; ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t cntr_idx_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ if (val >= drvdata->nr_cntr) ++ return -EINVAL; ++ /* ++ * Use spinlock to ensure index doesn't change while it gets ++ * dereferenced multiple times within a spinlock block elsewhere. ++ */ ++ spin_lock(&drvdata->spinlock); ++ drvdata->cntr_idx = val; ++ spin_unlock(&drvdata->spinlock); ++ ++ return size; ++} ++static DEVICE_ATTR_RW(cntr_idx); ++ ++static ssize_t cntr_rld_val_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ spin_lock(&drvdata->spinlock); ++ val = drvdata->cntr_rld_val[drvdata->cntr_idx]; ++ spin_unlock(&drvdata->spinlock); ++ ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t cntr_rld_val_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ spin_lock(&drvdata->spinlock); ++ drvdata->cntr_rld_val[drvdata->cntr_idx] = val; ++ spin_unlock(&drvdata->spinlock); ++ ++ return size; ++} ++static DEVICE_ATTR_RW(cntr_rld_val); ++ ++static ssize_t cntr_event_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ spin_lock(&drvdata->spinlock); ++ val = drvdata->cntr_event[drvdata->cntr_idx]; ++ spin_unlock(&drvdata->spinlock); ++ ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t cntr_event_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ spin_lock(&drvdata->spinlock); ++ drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK; ++ spin_unlock(&drvdata->spinlock); ++ ++ return size; ++} ++static DEVICE_ATTR_RW(cntr_event); ++ ++static ssize_t cntr_rld_event_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ spin_lock(&drvdata->spinlock); ++ val = drvdata->cntr_rld_event[drvdata->cntr_idx]; ++ spin_unlock(&drvdata->spinlock); ++ ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t cntr_rld_event_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ spin_lock(&drvdata->spinlock); ++ drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK; ++ spin_unlock(&drvdata->spinlock); ++ ++ return size; ++} ++static DEVICE_ATTR_RW(cntr_rld_event); ++ ++static ssize_t cntr_val_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ int i, ret = 0; ++ u32 val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ if (!drvdata->enable) { ++ spin_lock(&drvdata->spinlock); ++ for (i = 0; i < drvdata->nr_cntr; i++) ++ ret += sprintf(buf, "counter %d: %x\n", ++ i, drvdata->cntr_val[i]); ++ spin_unlock(&drvdata->spinlock); ++ return ret; ++ } ++ ++ for (i = 0; i < drvdata->nr_cntr; i++) { ++ val = etm_readl(drvdata, ETMCNTVRn(i)); ++ ret += sprintf(buf, "counter %d: %x\n", i, val); ++ } ++ ++ return ret; ++} ++ ++static ssize_t cntr_val_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ spin_lock(&drvdata->spinlock); ++ drvdata->cntr_val[drvdata->cntr_idx] = val; ++ spin_unlock(&drvdata->spinlock); ++ ++ return size; ++} ++static DEVICE_ATTR_RW(cntr_val); ++ ++static ssize_t seq_12_event_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->seq_12_event; ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t seq_12_event_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ drvdata->seq_12_event = val & ETM_EVENT_MASK; ++ return size; ++} ++static DEVICE_ATTR_RW(seq_12_event); ++ ++static ssize_t seq_21_event_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->seq_21_event; ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t seq_21_event_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ drvdata->seq_21_event = val & ETM_EVENT_MASK; ++ return size; ++} ++static DEVICE_ATTR_RW(seq_21_event); ++ ++static ssize_t seq_23_event_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->seq_23_event; ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t seq_23_event_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ drvdata->seq_23_event = val & ETM_EVENT_MASK; ++ return size; ++} ++static DEVICE_ATTR_RW(seq_23_event); ++ ++static ssize_t seq_31_event_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->seq_31_event; ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t seq_31_event_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ drvdata->seq_31_event = val & ETM_EVENT_MASK; ++ return size; ++} ++static DEVICE_ATTR_RW(seq_31_event); ++ ++static ssize_t seq_32_event_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->seq_32_event; ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t seq_32_event_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ drvdata->seq_32_event = val & ETM_EVENT_MASK; ++ return size; ++} ++static DEVICE_ATTR_RW(seq_32_event); ++ ++static ssize_t seq_13_event_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->seq_13_event; ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t seq_13_event_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ drvdata->seq_13_event = val & ETM_EVENT_MASK; ++ return size; ++} ++static DEVICE_ATTR_RW(seq_13_event); ++ ++static ssize_t seq_curr_state_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ int ret; ++ unsigned long val, flags; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ if (!drvdata->enable) { ++ val = drvdata->seq_curr_state; ++ goto out; ++ } ++ ++ ret = clk_prepare_enable(drvdata->clk); ++ if (ret) ++ return ret; ++ ++ spin_lock_irqsave(&drvdata->spinlock, flags); ++ ++ CS_UNLOCK(drvdata->base); ++ val = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK); ++ CS_LOCK(drvdata->base); ++ ++ spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ clk_disable_unprepare(drvdata->clk); ++out: ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t seq_curr_state_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ if (val > ETM_SEQ_STATE_MAX_VAL) ++ return -EINVAL; ++ ++ drvdata->seq_curr_state = val; ++ ++ return size; ++} ++static DEVICE_ATTR_RW(seq_curr_state); ++ ++static ssize_t ctxid_idx_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->ctxid_idx; ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t ctxid_idx_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ if (val >= drvdata->nr_ctxid_cmp) ++ return -EINVAL; ++ ++ /* ++ * Use spinlock to ensure index doesn't change while it gets ++ * dereferenced multiple times within a spinlock block elsewhere. ++ */ ++ spin_lock(&drvdata->spinlock); ++ drvdata->ctxid_idx = val; ++ spin_unlock(&drvdata->spinlock); ++ ++ return size; ++} ++static DEVICE_ATTR_RW(ctxid_idx); ++ ++static ssize_t ctxid_val_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ spin_lock(&drvdata->spinlock); ++ val = drvdata->ctxid_val[drvdata->ctxid_idx]; ++ spin_unlock(&drvdata->spinlock); ++ ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t ctxid_val_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ spin_lock(&drvdata->spinlock); ++ drvdata->ctxid_val[drvdata->ctxid_idx] = val; ++ spin_unlock(&drvdata->spinlock); ++ ++ return size; ++} ++static DEVICE_ATTR_RW(ctxid_val); ++ ++static ssize_t ctxid_mask_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->ctxid_mask; ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t ctxid_mask_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ drvdata->ctxid_mask = val; ++ return size; ++} ++static DEVICE_ATTR_RW(ctxid_mask); ++ ++static ssize_t sync_freq_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->sync_freq; ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t sync_freq_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ drvdata->sync_freq = val & ETM_SYNC_MASK; ++ return size; ++} ++static DEVICE_ATTR_RW(sync_freq); ++ ++static ssize_t timestamp_event_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ val = drvdata->timestamp_event; ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t timestamp_event_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ drvdata->timestamp_event = val & ETM_EVENT_MASK; ++ return size; ++} ++static DEVICE_ATTR_RW(timestamp_event); ++ ++static ssize_t status_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ int ret; ++ unsigned long flags; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = clk_prepare_enable(drvdata->clk); ++ if (ret) ++ return ret; ++ ++ spin_lock_irqsave(&drvdata->spinlock, flags); ++ ++ CS_UNLOCK(drvdata->base); ++ ret = sprintf(buf, ++ "ETMCCR: 0x%08x\n" ++ "ETMCCER: 0x%08x\n" ++ "ETMSCR: 0x%08x\n" ++ "ETMIDR: 0x%08x\n" ++ "ETMCR: 0x%08x\n" ++ "ETMTRACEIDR: 0x%08x\n" ++ "Enable event: 0x%08x\n" ++ "Enable start/stop: 0x%08x\n" ++ "Enable control: CR1 0x%08x CR2 0x%08x\n" ++ "CPU affinity: %d\n", ++ drvdata->etmccr, drvdata->etmccer, ++ etm_readl(drvdata, ETMSCR), etm_readl(drvdata, ETMIDR), ++ etm_readl(drvdata, ETMCR), etm_trace_id_simple(drvdata), ++ etm_readl(drvdata, ETMTEEVR), ++ etm_readl(drvdata, ETMTSSCR), ++ etm_readl(drvdata, ETMTECR1), ++ etm_readl(drvdata, ETMTECR2), ++ drvdata->cpu); ++ CS_LOCK(drvdata->base); ++ ++ spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ clk_disable_unprepare(drvdata->clk); ++ ++ return ret; ++} ++static DEVICE_ATTR_RO(status); ++ ++static ssize_t traceid_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ int ret; ++ unsigned long val, flags; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ if (!drvdata->enable) { ++ val = drvdata->traceid; ++ goto out; ++ } ++ ++ ret = clk_prepare_enable(drvdata->clk); ++ if (ret) ++ return ret; ++ ++ spin_lock_irqsave(&drvdata->spinlock, flags); ++ CS_UNLOCK(drvdata->base); ++ ++ val = (etm_readl(drvdata, ETMTRACEIDR) & ETM_TRACEID_MASK); ++ ++ CS_LOCK(drvdata->base); ++ spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ clk_disable_unprepare(drvdata->clk); ++out: ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t traceid_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ drvdata->traceid = val & ETM_TRACEID_MASK; ++ return size; ++} ++static DEVICE_ATTR_RW(traceid); ++ ++static struct attribute *coresight_etm_attrs[] = { ++ &dev_attr_nr_addr_cmp.attr, ++ &dev_attr_nr_cntr.attr, ++ &dev_attr_nr_ctxid_cmp.attr, ++ &dev_attr_etmsr.attr, ++ &dev_attr_reset.attr, ++ &dev_attr_mode.attr, ++ &dev_attr_trigger_event.attr, ++ &dev_attr_enable_event.attr, ++ &dev_attr_fifofull_level.attr, ++ &dev_attr_addr_idx.attr, ++ &dev_attr_addr_single.attr, ++ &dev_attr_addr_range.attr, ++ &dev_attr_addr_start.attr, ++ &dev_attr_addr_stop.attr, ++ &dev_attr_addr_acctype.attr, ++ &dev_attr_cntr_idx.attr, ++ &dev_attr_cntr_rld_val.attr, ++ &dev_attr_cntr_event.attr, ++ &dev_attr_cntr_rld_event.attr, ++ &dev_attr_cntr_val.attr, ++ &dev_attr_seq_12_event.attr, ++ &dev_attr_seq_21_event.attr, ++ &dev_attr_seq_23_event.attr, ++ &dev_attr_seq_31_event.attr, ++ &dev_attr_seq_32_event.attr, ++ &dev_attr_seq_13_event.attr, ++ &dev_attr_seq_curr_state.attr, ++ &dev_attr_ctxid_idx.attr, ++ &dev_attr_ctxid_val.attr, ++ &dev_attr_ctxid_mask.attr, ++ &dev_attr_sync_freq.attr, ++ &dev_attr_timestamp_event.attr, ++ &dev_attr_status.attr, ++ &dev_attr_traceid.attr, ++ NULL, ++}; ++ATTRIBUTE_GROUPS(coresight_etm); ++ ++static int etm_cpu_callback(struct notifier_block *nfb, unsigned long action, ++ void *hcpu) ++{ ++ unsigned int cpu = (unsigned long)hcpu; ++ ++ if (!etmdrvdata[cpu]) ++ goto out; ++ ++ switch (action & (~CPU_TASKS_FROZEN)) { ++ case CPU_STARTING: ++ spin_lock(&etmdrvdata[cpu]->spinlock); ++ if (!etmdrvdata[cpu]->os_unlock) { ++ etm_os_unlock(etmdrvdata[cpu]); ++ etmdrvdata[cpu]->os_unlock = true; ++ } ++ ++ if (etmdrvdata[cpu]->enable) ++ etm_enable_hw(etmdrvdata[cpu]); ++ spin_unlock(&etmdrvdata[cpu]->spinlock); ++ break; ++ ++ case CPU_ONLINE: ++ if (etmdrvdata[cpu]->boot_enable && ++ !etmdrvdata[cpu]->sticky_enable) ++ coresight_enable(etmdrvdata[cpu]->csdev); ++ break; ++ ++ case CPU_DYING: ++ spin_lock(&etmdrvdata[cpu]->spinlock); ++ if (etmdrvdata[cpu]->enable) ++ etm_disable_hw(etmdrvdata[cpu]); ++ spin_unlock(&etmdrvdata[cpu]->spinlock); ++ break; ++ } ++out: ++ return NOTIFY_OK; ++} ++ ++static struct notifier_block etm_cpu_notifier = { ++ .notifier_call = etm_cpu_callback, ++}; ++ ++static bool etm_arch_supported(u8 arch) ++{ ++ switch (arch) { ++ case ETM_ARCH_V3_3: ++ break; ++ case ETM_ARCH_V3_5: ++ break; ++ case PFT_ARCH_V1_0: ++ break; ++ case PFT_ARCH_V1_1: ++ break; ++ default: ++ return false; ++ } ++ return true; ++} ++ ++static void etm_init_arch_data(void *info) ++{ ++ u32 etmidr; ++ u32 etmccr; ++ struct etm_drvdata *drvdata = info; ++ ++ CS_UNLOCK(drvdata->base); ++ ++ /* First dummy read */ ++ (void)etm_readl(drvdata, ETMPDSR); ++ /* Provide power to ETM: ETMPDCR[3] == 1 */ ++ etm_set_pwrup(drvdata); ++ /* ++ * Clear power down bit since when this bit is set writes to ++ * certain registers might be ignored. ++ */ ++ etm_clr_pwrdwn(drvdata); ++ /* ++ * Set prog bit. It will be set from reset but this is included to ++ * ensure it is set ++ */ ++ etm_set_prog(drvdata); ++ ++ /* Find all capabilities */ ++ etmidr = etm_readl(drvdata, ETMIDR); ++ drvdata->arch = BMVAL(etmidr, 4, 11); ++ drvdata->port_size = etm_readl(drvdata, ETMCR) & PORT_SIZE_MASK; ++ ++ drvdata->etmccer = etm_readl(drvdata, ETMCCER); ++ etmccr = etm_readl(drvdata, ETMCCR); ++ drvdata->etmccr = etmccr; ++ drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2; ++ drvdata->nr_cntr = BMVAL(etmccr, 13, 15); ++ drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19); ++ drvdata->nr_ext_out = BMVAL(etmccr, 20, 22); ++ drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25); ++ ++ etm_set_pwrdwn(drvdata); ++ etm_clr_pwrup(drvdata); ++ CS_LOCK(drvdata->base); ++} ++ ++static void etm_init_default_data(struct etm_drvdata *drvdata) ++{ ++ /* ++ * A trace ID of value 0 is invalid, so let's start at some ++ * random value that fits in 7 bits and will be just as good. ++ */ ++ static int etm3x_traceid = 0x10; ++ ++ u32 flags = (1 << 0 | /* instruction execute*/ ++ 3 << 3 | /* ARM instruction */ ++ 0 << 5 | /* No data value comparison */ ++ 0 << 7 | /* No exact mach */ ++ 0 << 8 | /* Ignore context ID */ ++ 0 << 10); /* Security ignored */ ++ ++ /* ++ * Initial configuration only - guarantees sources handled by ++ * this driver have a unique ID at startup time but not between ++ * all other types of sources. For that we lean on the core ++ * framework. ++ */ ++ drvdata->traceid = etm3x_traceid++; ++ drvdata->ctrl = (ETMCR_CYC_ACC | ETMCR_TIMESTAMP_EN); ++ drvdata->enable_ctrl1 = ETMTECR1_ADDR_COMP_1; ++ if (drvdata->nr_addr_cmp >= 2) { ++ drvdata->addr_val[0] = (u32) _stext; ++ drvdata->addr_val[1] = (u32) _etext; ++ drvdata->addr_acctype[0] = flags; ++ drvdata->addr_acctype[1] = flags; ++ drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE; ++ drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE; ++ } ++ ++ etm_set_default(drvdata); ++} ++ ++static int etm_probe(struct amba_device *adev, const struct amba_id *id) ++{ ++ int ret; ++ void __iomem *base; ++ struct device *dev = &adev->dev; ++ struct coresight_platform_data *pdata = NULL; ++ struct etm_drvdata *drvdata; ++ struct resource *res = &adev->res; ++ struct coresight_desc *desc; ++ struct device_node *np = adev->dev.of_node; ++ ++ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); ++ if (!desc) ++ return -ENOMEM; ++ ++ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); ++ if (!drvdata) ++ return -ENOMEM; ++ ++ if (np) { ++ pdata = of_get_coresight_platform_data(dev, np); ++ if (IS_ERR(pdata)) ++ return PTR_ERR(pdata); ++ ++ adev->dev.platform_data = pdata; ++ drvdata->use_cp14 = of_property_read_bool(np, "arm,cp14"); ++ } ++ ++ drvdata->dev = &adev->dev; ++ dev_set_drvdata(dev, drvdata); ++ ++ /* Validity for the resource is already checked by the AMBA core */ ++ base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ drvdata->base = base; ++ ++ spin_lock_init(&drvdata->spinlock); ++ ++ drvdata->clk = adev->pclk; ++ ret = clk_prepare_enable(drvdata->clk); ++ if (ret) ++ return ret; ++ ++ drvdata->cpu = pdata ? pdata->cpu : 0; ++ ++ get_online_cpus(); ++ etmdrvdata[drvdata->cpu] = drvdata; ++ ++ if (!smp_call_function_single(drvdata->cpu, etm_os_unlock, drvdata, 1)) ++ drvdata->os_unlock = true; ++ ++ if (smp_call_function_single(drvdata->cpu, ++ etm_init_arch_data, drvdata, 1)) ++ dev_err(dev, "ETM arch init failed\n"); ++ ++ if (!etm_count++) ++ register_hotcpu_notifier(&etm_cpu_notifier); ++ ++ put_online_cpus(); ++ ++ if (etm_arch_supported(drvdata->arch) == false) { ++ ret = -EINVAL; ++ goto err_arch_supported; ++ } ++ etm_init_default_data(drvdata); ++ ++ clk_disable_unprepare(drvdata->clk); ++ ++ desc->type = CORESIGHT_DEV_TYPE_SOURCE; ++ desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC; ++ desc->ops = &etm_cs_ops; ++ desc->pdata = pdata; ++ desc->dev = dev; ++ desc->groups = coresight_etm_groups; ++ drvdata->csdev = coresight_register(desc); ++ if (IS_ERR(drvdata->csdev)) { ++ ret = PTR_ERR(drvdata->csdev); ++ goto err_arch_supported; ++ } ++ ++ dev_info(dev, "ETM initialized\n"); ++ ++ if (boot_enable) { ++ coresight_enable(drvdata->csdev); ++ drvdata->boot_enable = true; ++ } ++ ++ return 0; ++ ++err_arch_supported: ++ clk_disable_unprepare(drvdata->clk); ++ if (--etm_count == 0) ++ unregister_hotcpu_notifier(&etm_cpu_notifier); ++ return ret; ++} ++ ++static int etm_remove(struct amba_device *adev) ++{ ++ struct etm_drvdata *drvdata = amba_get_drvdata(adev); ++ ++ coresight_unregister(drvdata->csdev); ++ if (--etm_count == 0) ++ unregister_hotcpu_notifier(&etm_cpu_notifier); ++ ++ return 0; ++} ++ ++static struct amba_id etm_ids[] = { ++ { /* ETM 3.3 */ ++ .id = 0x0003b921, ++ .mask = 0x0003ffff, ++ }, ++ { /* ETM 3.5 */ ++ .id = 0x0003b956, ++ .mask = 0x0003ffff, ++ }, ++ { /* PTM 1.0 */ ++ .id = 0x0003b950, ++ .mask = 0x0003ffff, ++ }, ++ { /* PTM 1.1 */ ++ .id = 0x0003b95f, ++ .mask = 0x0003ffff, ++ }, ++ { 0, 0}, ++}; ++ ++static struct amba_driver etm_driver = { ++ .drv = { ++ .name = "coresight-etm3x", ++ .owner = THIS_MODULE, ++ }, ++ .probe = etm_probe, ++ .remove = etm_remove, ++ .id_table = etm_ids, ++}; ++ ++int __init etm_init(void) ++{ ++ return amba_driver_register(&etm_driver); ++} ++module_init(etm_init); ++ ++void __exit etm_exit(void) ++{ ++ amba_driver_unregister(&etm_driver); ++} ++module_exit(etm_exit); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("CoreSight Program Flow Trace driver"); +diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c +new file mode 100644 +index 0000000..3db36f7 +--- /dev/null ++++ b/drivers/hwtracing/coresight/coresight-funnel.c +@@ -0,0 +1,258 @@ ++/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "coresight-priv.h" ++ ++#define FUNNEL_FUNCTL 0x000 ++#define FUNNEL_PRICTL 0x004 ++ ++#define FUNNEL_HOLDTIME_MASK 0xf00 ++#define FUNNEL_HOLDTIME_SHFT 0x8 ++#define FUNNEL_HOLDTIME (0x7 << FUNNEL_HOLDTIME_SHFT) ++ ++/** ++ * struct funnel_drvdata - specifics associated to a funnel component ++ * @base: memory mapped base address for this component. ++ * @dev: the device entity associated to this component. ++ * @csdev: component vitals needed by the framework. ++ * @clk: the clock this component is associated to. ++ * @priority: port selection order. ++ */ ++struct funnel_drvdata { ++ void __iomem *base; ++ struct device *dev; ++ struct coresight_device *csdev; ++ struct clk *clk; ++ unsigned long priority; ++}; ++ ++static void funnel_enable_hw(struct funnel_drvdata *drvdata, int port) ++{ ++ u32 functl; ++ ++ CS_UNLOCK(drvdata->base); ++ ++ functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL); ++ functl &= ~FUNNEL_HOLDTIME_MASK; ++ functl |= FUNNEL_HOLDTIME; ++ functl |= (1 << port); ++ writel_relaxed(functl, drvdata->base + FUNNEL_FUNCTL); ++ writel_relaxed(drvdata->priority, drvdata->base + FUNNEL_PRICTL); ++ ++ CS_LOCK(drvdata->base); ++} ++ ++static int funnel_enable(struct coresight_device *csdev, int inport, ++ int outport) ++{ ++ struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); ++ int ret; ++ ++ ret = clk_prepare_enable(drvdata->clk); ++ if (ret) ++ return ret; ++ ++ funnel_enable_hw(drvdata, inport); ++ ++ dev_info(drvdata->dev, "FUNNEL inport %d enabled\n", inport); ++ return 0; ++} ++ ++static void funnel_disable_hw(struct funnel_drvdata *drvdata, int inport) ++{ ++ u32 functl; ++ ++ CS_UNLOCK(drvdata->base); ++ ++ functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL); ++ functl &= ~(1 << inport); ++ writel_relaxed(functl, drvdata->base + FUNNEL_FUNCTL); ++ ++ CS_LOCK(drvdata->base); ++} ++ ++static void funnel_disable(struct coresight_device *csdev, int inport, ++ int outport) ++{ ++ struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); ++ ++ funnel_disable_hw(drvdata, inport); ++ ++ clk_disable_unprepare(drvdata->clk); ++ ++ dev_info(drvdata->dev, "FUNNEL inport %d disabled\n", inport); ++} ++ ++static const struct coresight_ops_link funnel_link_ops = { ++ .enable = funnel_enable, ++ .disable = funnel_disable, ++}; ++ ++static const struct coresight_ops funnel_cs_ops = { ++ .link_ops = &funnel_link_ops, ++}; ++ ++static ssize_t priority_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ unsigned long val = drvdata->priority; ++ ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t priority_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ drvdata->priority = val; ++ return size; ++} ++static DEVICE_ATTR_RW(priority); ++ ++static u32 get_funnel_ctrl_hw(struct funnel_drvdata *drvdata) ++{ ++ u32 functl; ++ ++ CS_UNLOCK(drvdata->base); ++ functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL); ++ CS_LOCK(drvdata->base); ++ ++ return functl; ++} ++ ++static ssize_t funnel_ctrl_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ int ret; ++ u32 val; ++ struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = clk_prepare_enable(drvdata->clk); ++ if (ret) ++ return ret; ++ ++ val = get_funnel_ctrl_hw(drvdata); ++ clk_disable_unprepare(drvdata->clk); ++ ++ return sprintf(buf, "%#x\n", val); ++} ++static DEVICE_ATTR_RO(funnel_ctrl); ++ ++static struct attribute *coresight_funnel_attrs[] = { ++ &dev_attr_funnel_ctrl.attr, ++ &dev_attr_priority.attr, ++ NULL, ++}; ++ATTRIBUTE_GROUPS(coresight_funnel); ++ ++static int funnel_probe(struct amba_device *adev, const struct amba_id *id) ++{ ++ void __iomem *base; ++ struct device *dev = &adev->dev; ++ struct coresight_platform_data *pdata = NULL; ++ struct funnel_drvdata *drvdata; ++ struct resource *res = &adev->res; ++ struct coresight_desc *desc; ++ struct device_node *np = adev->dev.of_node; ++ ++ if (np) { ++ pdata = of_get_coresight_platform_data(dev, np); ++ if (IS_ERR(pdata)) ++ return PTR_ERR(pdata); ++ adev->dev.platform_data = pdata; ++ } ++ ++ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); ++ if (!drvdata) ++ return -ENOMEM; ++ ++ drvdata->dev = &adev->dev; ++ dev_set_drvdata(dev, drvdata); ++ ++ /* Validity for the resource is already checked by the AMBA core */ ++ base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ drvdata->base = base; ++ ++ drvdata->clk = adev->pclk; ++ ++ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); ++ if (!desc) ++ return -ENOMEM; ++ ++ desc->type = CORESIGHT_DEV_TYPE_LINK; ++ desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG; ++ desc->ops = &funnel_cs_ops; ++ desc->pdata = pdata; ++ desc->dev = dev; ++ desc->groups = coresight_funnel_groups; ++ drvdata->csdev = coresight_register(desc); ++ if (IS_ERR(drvdata->csdev)) ++ return PTR_ERR(drvdata->csdev); ++ ++ dev_info(dev, "FUNNEL initialized\n"); ++ return 0; ++} ++ ++static int funnel_remove(struct amba_device *adev) ++{ ++ struct funnel_drvdata *drvdata = amba_get_drvdata(adev); ++ ++ coresight_unregister(drvdata->csdev); ++ return 0; ++} ++ ++static struct amba_id funnel_ids[] = { ++ { ++ .id = 0x0003b908, ++ .mask = 0x0003ffff, ++ }, ++ { 0, 0}, ++}; ++ ++static struct amba_driver funnel_driver = { ++ .drv = { ++ .name = "coresight-funnel", ++ .owner = THIS_MODULE, ++ }, ++ .probe = funnel_probe, ++ .remove = funnel_remove, ++ .id_table = funnel_ids, ++}; ++ ++module_amba_driver(funnel_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("CoreSight Funnel driver"); +diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h +new file mode 100644 +index 0000000..62fcd98 +--- /dev/null ++++ b/drivers/hwtracing/coresight/coresight-priv.h +@@ -0,0 +1,63 @@ ++/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * 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 _CORESIGHT_PRIV_H ++#define _CORESIGHT_PRIV_H ++ ++#include ++#include ++#include ++ ++/* ++ * Coresight management registers (0xf00-0xfcc) ++ * 0xfa0 - 0xfa4: Management registers in PFTv1.0 ++ * Trace registers in PFTv1.1 ++ */ ++#define CORESIGHT_ITCTRL 0xf00 ++#define CORESIGHT_CLAIMSET 0xfa0 ++#define CORESIGHT_CLAIMCLR 0xfa4 ++#define CORESIGHT_LAR 0xfb0 ++#define CORESIGHT_LSR 0xfb4 ++#define CORESIGHT_AUTHSTATUS 0xfb8 ++#define CORESIGHT_DEVID 0xfc8 ++#define CORESIGHT_DEVTYPE 0xfcc ++ ++#define TIMEOUT_US 100 ++#define BMVAL(val, lsb, msb) ((val & GENMASK(msb, lsb)) >> lsb) ++ ++static inline void CS_LOCK(void __iomem *addr) ++{ ++ do { ++ /* Wait for things to settle */ ++ mb(); ++ writel_relaxed(0x0, addr + CORESIGHT_LAR); ++ } while (0); ++} ++ ++static inline void CS_UNLOCK(void __iomem *addr) ++{ ++ do { ++ writel_relaxed(CORESIGHT_UNLOCK, addr + CORESIGHT_LAR); ++ /* Make sure everyone has seen this */ ++ mb(); ++ } while (0); ++} ++ ++#ifdef CONFIG_CORESIGHT_SOURCE_ETM3X ++extern int etm_readl_cp14(u32 off, unsigned int *val); ++extern int etm_writel_cp14(u32 off, u32 val); ++#else ++static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; } ++static inline int etm_writel_cp14(u32 off, u32 val) { return 0; } ++#endif ++ ++#endif +diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c +new file mode 100644 +index 0000000..cdf0553 +--- /dev/null ++++ b/drivers/hwtracing/coresight/coresight-replicator.c +@@ -0,0 +1,137 @@ ++/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "coresight-priv.h" ++ ++/** ++ * struct replicator_drvdata - specifics associated to a replicator component ++ * @dev: the device entity associated with this component ++ * @csdev: component vitals needed by the framework ++ */ ++struct replicator_drvdata { ++ struct device *dev; ++ struct coresight_device *csdev; ++}; ++ ++static int replicator_enable(struct coresight_device *csdev, int inport, ++ int outport) ++{ ++ struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); ++ ++ dev_info(drvdata->dev, "REPLICATOR enabled\n"); ++ return 0; ++} ++ ++static void replicator_disable(struct coresight_device *csdev, int inport, ++ int outport) ++{ ++ struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); ++ ++ dev_info(drvdata->dev, "REPLICATOR disabled\n"); ++} ++ ++static const struct coresight_ops_link replicator_link_ops = { ++ .enable = replicator_enable, ++ .disable = replicator_disable, ++}; ++ ++static const struct coresight_ops replicator_cs_ops = { ++ .link_ops = &replicator_link_ops, ++}; ++ ++static int replicator_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct coresight_platform_data *pdata = NULL; ++ struct replicator_drvdata *drvdata; ++ struct coresight_desc *desc; ++ struct device_node *np = pdev->dev.of_node; ++ ++ if (np) { ++ pdata = of_get_coresight_platform_data(dev, np); ++ if (IS_ERR(pdata)) ++ return PTR_ERR(pdata); ++ pdev->dev.platform_data = pdata; ++ } ++ ++ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); ++ if (!drvdata) ++ return -ENOMEM; ++ ++ drvdata->dev = &pdev->dev; ++ platform_set_drvdata(pdev, drvdata); ++ ++ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); ++ if (!desc) ++ return -ENOMEM; ++ ++ desc->type = CORESIGHT_DEV_TYPE_LINK; ++ desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT; ++ desc->ops = &replicator_cs_ops; ++ desc->pdata = pdev->dev.platform_data; ++ desc->dev = &pdev->dev; ++ drvdata->csdev = coresight_register(desc); ++ if (IS_ERR(drvdata->csdev)) ++ return PTR_ERR(drvdata->csdev); ++ ++ dev_info(dev, "REPLICATOR initialized\n"); ++ return 0; ++} ++ ++static int replicator_remove(struct platform_device *pdev) ++{ ++ struct replicator_drvdata *drvdata = platform_get_drvdata(pdev); ++ ++ coresight_unregister(drvdata->csdev); ++ return 0; ++} ++ ++static struct of_device_id replicator_match[] = { ++ {.compatible = "arm,coresight-replicator"}, ++ {} ++}; ++ ++static struct platform_driver replicator_driver = { ++ .probe = replicator_probe, ++ .remove = replicator_remove, ++ .driver = { ++ .name = "coresight-replicator", ++ .of_match_table = replicator_match, ++ }, ++}; ++ ++static int __init replicator_init(void) ++{ ++ return platform_driver_register(&replicator_driver); ++} ++module_init(replicator_init); ++ ++static void __exit replicator_exit(void) ++{ ++ platform_driver_unregister(&replicator_driver); ++} ++module_exit(replicator_exit); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("CoreSight Replicator driver"); +diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c +new file mode 100644 +index 0000000..7147f3d +--- /dev/null ++++ b/drivers/hwtracing/coresight/coresight-tmc.c +@@ -0,0 +1,822 @@ ++/* Copyright (c) 2012, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "coresight-priv.h" ++ ++#define TMC_RSZ 0x004 ++#define TMC_STS 0x00c ++#define TMC_RRD 0x010 ++#define TMC_RRP 0x014 ++#define TMC_RWP 0x018 ++#define TMC_TRG 0x01c ++#define TMC_CTL 0x020 ++#define TMC_RWD 0x024 ++#define TMC_MODE 0x028 ++#define TMC_LBUFLEVEL 0x02c ++#define TMC_CBUFLEVEL 0x030 ++#define TMC_BUFWM 0x034 ++#define TMC_RRPHI 0x038 ++#define TMC_RWPHI 0x03c ++#define TMC_AXICTL 0x110 ++#define TMC_DBALO 0x118 ++#define TMC_DBAHI 0x11c ++#define TMC_FFSR 0x300 ++#define TMC_FFCR 0x304 ++#define TMC_PSCR 0x308 ++#define TMC_ITMISCOP0 0xee0 ++#define TMC_ITTRFLIN 0xee8 ++#define TMC_ITATBDATA0 0xeec ++#define TMC_ITATBCTR2 0xef0 ++#define TMC_ITATBCTR1 0xef4 ++#define TMC_ITATBCTR0 0xef8 ++ ++/* register description */ ++/* TMC_CTL - 0x020 */ ++#define TMC_CTL_CAPT_EN BIT(0) ++/* TMC_STS - 0x00C */ ++#define TMC_STS_TRIGGERED BIT(1) ++/* TMC_AXICTL - 0x110 */ ++#define TMC_AXICTL_PROT_CTL_B0 BIT(0) ++#define TMC_AXICTL_PROT_CTL_B1 BIT(1) ++#define TMC_AXICTL_SCT_GAT_MODE BIT(7) ++#define TMC_AXICTL_WR_BURST_LEN 0xF00 ++/* TMC_FFCR - 0x304 */ ++#define TMC_FFCR_EN_FMT BIT(0) ++#define TMC_FFCR_EN_TI BIT(1) ++#define TMC_FFCR_FON_FLIN BIT(4) ++#define TMC_FFCR_FON_TRIG_EVT BIT(5) ++#define TMC_FFCR_FLUSHMAN BIT(6) ++#define TMC_FFCR_TRIGON_TRIGIN BIT(8) ++#define TMC_FFCR_STOP_ON_FLUSH BIT(12) ++ ++#define TMC_STS_TRIGGERED_BIT 2 ++#define TMC_FFCR_FLUSHMAN_BIT 6 ++ ++enum tmc_config_type { ++ TMC_CONFIG_TYPE_ETB, ++ TMC_CONFIG_TYPE_ETR, ++ TMC_CONFIG_TYPE_ETF, ++}; ++ ++enum tmc_mode { ++ TMC_MODE_CIRCULAR_BUFFER, ++ TMC_MODE_SOFTWARE_FIFO, ++ TMC_MODE_HARDWARE_FIFO, ++}; ++ ++enum tmc_mem_intf_width { ++ TMC_MEM_INTF_WIDTH_32BITS = 0x2, ++ TMC_MEM_INTF_WIDTH_64BITS = 0x3, ++ TMC_MEM_INTF_WIDTH_128BITS = 0x4, ++ TMC_MEM_INTF_WIDTH_256BITS = 0x5, ++}; ++ ++/** ++ * struct tmc_drvdata - specifics associated to an TMC component ++ * @base: memory mapped base address for this component. ++ * @dev: the device entity associated to this component. ++ * @csdev: component vitals needed by the framework. ++ * @miscdev: specifics to handle "/dev/xyz.tmc" entry. ++ * @clk: the clock this component is associated to. ++ * @spinlock: only one at a time pls. ++ * @read_count: manages preparation of buffer for reading. ++ * @buf: area of memory where trace data get sent. ++ * @paddr: DMA start location in RAM. ++ * @vaddr: virtual representation of @paddr. ++ * @size: @buf size. ++ * @enable: this TMC is being used. ++ * @config_type: TMC variant, must be of type @tmc_config_type. ++ * @trigger_cntr: amount of words to store after a trigger. ++ */ ++struct tmc_drvdata { ++ void __iomem *base; ++ struct device *dev; ++ struct coresight_device *csdev; ++ struct miscdevice miscdev; ++ struct clk *clk; ++ spinlock_t spinlock; ++ int read_count; ++ bool reading; ++ char *buf; ++ dma_addr_t paddr; ++ void __iomem *vaddr; ++ u32 size; ++ bool enable; ++ enum tmc_config_type config_type; ++ u32 trigger_cntr; ++}; ++ ++static void tmc_wait_for_ready(struct tmc_drvdata *drvdata) ++{ ++ /* Ensure formatter, unformatter and hardware fifo are empty */ ++ if (coresight_timeout(drvdata->base, ++ TMC_STS, TMC_STS_TRIGGERED_BIT, 1)) { ++ dev_err(drvdata->dev, ++ "timeout observed when probing at offset %#x\n", ++ TMC_STS); ++ } ++} ++ ++static void tmc_flush_and_stop(struct tmc_drvdata *drvdata) ++{ ++ u32 ffcr; ++ ++ ffcr = readl_relaxed(drvdata->base + TMC_FFCR); ++ ffcr |= TMC_FFCR_STOP_ON_FLUSH; ++ writel_relaxed(ffcr, drvdata->base + TMC_FFCR); ++ ffcr |= TMC_FFCR_FLUSHMAN; ++ writel_relaxed(ffcr, drvdata->base + TMC_FFCR); ++ /* Ensure flush completes */ ++ if (coresight_timeout(drvdata->base, ++ TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) { ++ dev_err(drvdata->dev, ++ "timeout observed when probing at offset %#x\n", ++ TMC_FFCR); ++ } ++ ++ tmc_wait_for_ready(drvdata); ++} ++ ++static void tmc_enable_hw(struct tmc_drvdata *drvdata) ++{ ++ writel_relaxed(TMC_CTL_CAPT_EN, drvdata->base + TMC_CTL); ++} ++ ++static void tmc_disable_hw(struct tmc_drvdata *drvdata) ++{ ++ writel_relaxed(0x0, drvdata->base + TMC_CTL); ++} ++ ++static void tmc_etb_enable_hw(struct tmc_drvdata *drvdata) ++{ ++ /* Zero out the memory to help with debug */ ++ memset(drvdata->buf, 0, drvdata->size); ++ ++ CS_UNLOCK(drvdata->base); ++ ++ writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE); ++ writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI | ++ TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT | ++ TMC_FFCR_TRIGON_TRIGIN, ++ drvdata->base + TMC_FFCR); ++ ++ writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG); ++ tmc_enable_hw(drvdata); ++ ++ CS_LOCK(drvdata->base); ++} ++ ++static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata) ++{ ++ u32 axictl; ++ ++ /* Zero out the memory to help with debug */ ++ memset(drvdata->vaddr, 0, drvdata->size); ++ ++ CS_UNLOCK(drvdata->base); ++ ++ writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ); ++ writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE); ++ ++ axictl = readl_relaxed(drvdata->base + TMC_AXICTL); ++ axictl |= TMC_AXICTL_WR_BURST_LEN; ++ writel_relaxed(axictl, drvdata->base + TMC_AXICTL); ++ axictl &= ~TMC_AXICTL_SCT_GAT_MODE; ++ writel_relaxed(axictl, drvdata->base + TMC_AXICTL); ++ axictl = (axictl & ++ ~(TMC_AXICTL_PROT_CTL_B0 | TMC_AXICTL_PROT_CTL_B1)) | ++ TMC_AXICTL_PROT_CTL_B1; ++ writel_relaxed(axictl, drvdata->base + TMC_AXICTL); ++ ++ writel_relaxed(drvdata->paddr, drvdata->base + TMC_DBALO); ++ writel_relaxed(0x0, drvdata->base + TMC_DBAHI); ++ writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI | ++ TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT | ++ TMC_FFCR_TRIGON_TRIGIN, ++ drvdata->base + TMC_FFCR); ++ writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG); ++ tmc_enable_hw(drvdata); ++ ++ CS_LOCK(drvdata->base); ++} ++ ++static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata) ++{ ++ CS_UNLOCK(drvdata->base); ++ ++ writel_relaxed(TMC_MODE_HARDWARE_FIFO, drvdata->base + TMC_MODE); ++ writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI, ++ drvdata->base + TMC_FFCR); ++ writel_relaxed(0x0, drvdata->base + TMC_BUFWM); ++ tmc_enable_hw(drvdata); ++ ++ CS_LOCK(drvdata->base); ++} ++ ++static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode) ++{ ++ int ret; ++ unsigned long flags; ++ ++ ret = clk_prepare_enable(drvdata->clk); ++ if (ret) ++ return ret; ++ ++ spin_lock_irqsave(&drvdata->spinlock, flags); ++ if (drvdata->reading) { ++ spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ clk_disable_unprepare(drvdata->clk); ++ return -EBUSY; ++ } ++ ++ if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) { ++ tmc_etb_enable_hw(drvdata); ++ } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) { ++ tmc_etr_enable_hw(drvdata); ++ } else { ++ if (mode == TMC_MODE_CIRCULAR_BUFFER) ++ tmc_etb_enable_hw(drvdata); ++ else ++ tmc_etf_enable_hw(drvdata); ++ } ++ drvdata->enable = true; ++ spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ ++ dev_info(drvdata->dev, "TMC enabled\n"); ++ return 0; ++} ++ ++static int tmc_enable_sink(struct coresight_device *csdev) ++{ ++ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); ++ ++ return tmc_enable(drvdata, TMC_MODE_CIRCULAR_BUFFER); ++} ++ ++static int tmc_enable_link(struct coresight_device *csdev, int inport, ++ int outport) ++{ ++ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); ++ ++ return tmc_enable(drvdata, TMC_MODE_HARDWARE_FIFO); ++} ++ ++static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata) ++{ ++ enum tmc_mem_intf_width memwidth; ++ u8 memwords; ++ char *bufp; ++ u32 read_data; ++ int i; ++ ++ memwidth = BMVAL(readl_relaxed(drvdata->base + CORESIGHT_DEVID), 8, 10); ++ if (memwidth == TMC_MEM_INTF_WIDTH_32BITS) ++ memwords = 1; ++ else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS) ++ memwords = 2; ++ else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS) ++ memwords = 4; ++ else ++ memwords = 8; ++ ++ bufp = drvdata->buf; ++ while (1) { ++ for (i = 0; i < memwords; i++) { ++ read_data = readl_relaxed(drvdata->base + TMC_RRD); ++ if (read_data == 0xFFFFFFFF) ++ return; ++ memcpy(bufp, &read_data, 4); ++ bufp += 4; ++ } ++ } ++} ++ ++static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata) ++{ ++ CS_UNLOCK(drvdata->base); ++ ++ tmc_flush_and_stop(drvdata); ++ tmc_etb_dump_hw(drvdata); ++ tmc_disable_hw(drvdata); ++ ++ CS_LOCK(drvdata->base); ++} ++ ++static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata) ++{ ++ u32 rwp, val; ++ ++ rwp = readl_relaxed(drvdata->base + TMC_RWP); ++ val = readl_relaxed(drvdata->base + TMC_STS); ++ ++ /* How much memory do we still have */ ++ if (val & BIT(0)) ++ drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr; ++ else ++ drvdata->buf = drvdata->vaddr; ++} ++ ++static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata) ++{ ++ CS_UNLOCK(drvdata->base); ++ ++ tmc_flush_and_stop(drvdata); ++ tmc_etr_dump_hw(drvdata); ++ tmc_disable_hw(drvdata); ++ ++ CS_LOCK(drvdata->base); ++} ++ ++static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata) ++{ ++ CS_UNLOCK(drvdata->base); ++ ++ tmc_flush_and_stop(drvdata); ++ tmc_disable_hw(drvdata); ++ ++ CS_LOCK(drvdata->base); ++} ++ ++static void tmc_disable(struct tmc_drvdata *drvdata, enum tmc_mode mode) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&drvdata->spinlock, flags); ++ if (drvdata->reading) ++ goto out; ++ ++ if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) { ++ tmc_etb_disable_hw(drvdata); ++ } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) { ++ tmc_etr_disable_hw(drvdata); ++ } else { ++ if (mode == TMC_MODE_CIRCULAR_BUFFER) ++ tmc_etb_disable_hw(drvdata); ++ else ++ tmc_etf_disable_hw(drvdata); ++ } ++out: ++ drvdata->enable = false; ++ spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ ++ clk_disable_unprepare(drvdata->clk); ++ ++ dev_info(drvdata->dev, "TMC disabled\n"); ++} ++ ++static void tmc_disable_sink(struct coresight_device *csdev) ++{ ++ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); ++ ++ tmc_disable(drvdata, TMC_MODE_CIRCULAR_BUFFER); ++} ++ ++static void tmc_disable_link(struct coresight_device *csdev, int inport, ++ int outport) ++{ ++ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); ++ ++ tmc_disable(drvdata, TMC_MODE_HARDWARE_FIFO); ++} ++ ++static const struct coresight_ops_sink tmc_sink_ops = { ++ .enable = tmc_enable_sink, ++ .disable = tmc_disable_sink, ++}; ++ ++static const struct coresight_ops_link tmc_link_ops = { ++ .enable = tmc_enable_link, ++ .disable = tmc_disable_link, ++}; ++ ++static const struct coresight_ops tmc_etb_cs_ops = { ++ .sink_ops = &tmc_sink_ops, ++}; ++ ++static const struct coresight_ops tmc_etr_cs_ops = { ++ .sink_ops = &tmc_sink_ops, ++}; ++ ++static const struct coresight_ops tmc_etf_cs_ops = { ++ .sink_ops = &tmc_sink_ops, ++ .link_ops = &tmc_link_ops, ++}; ++ ++static int tmc_read_prepare(struct tmc_drvdata *drvdata) ++{ ++ int ret; ++ unsigned long flags; ++ enum tmc_mode mode; ++ ++ spin_lock_irqsave(&drvdata->spinlock, flags); ++ if (!drvdata->enable) ++ goto out; ++ ++ if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) { ++ tmc_etb_disable_hw(drvdata); ++ } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) { ++ tmc_etr_disable_hw(drvdata); ++ } else { ++ mode = readl_relaxed(drvdata->base + TMC_MODE); ++ if (mode == TMC_MODE_CIRCULAR_BUFFER) { ++ tmc_etb_disable_hw(drvdata); ++ } else { ++ ret = -ENODEV; ++ goto err; ++ } ++ } ++out: ++ drvdata->reading = true; ++ spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ ++ dev_info(drvdata->dev, "TMC read start\n"); ++ return 0; ++err: ++ spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ return ret; ++} ++ ++static void tmc_read_unprepare(struct tmc_drvdata *drvdata) ++{ ++ unsigned long flags; ++ enum tmc_mode mode; ++ ++ spin_lock_irqsave(&drvdata->spinlock, flags); ++ if (!drvdata->enable) ++ goto out; ++ ++ if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) { ++ tmc_etb_enable_hw(drvdata); ++ } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) { ++ tmc_etr_enable_hw(drvdata); ++ } else { ++ mode = readl_relaxed(drvdata->base + TMC_MODE); ++ if (mode == TMC_MODE_CIRCULAR_BUFFER) ++ tmc_etb_enable_hw(drvdata); ++ } ++out: ++ drvdata->reading = false; ++ spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ ++ dev_info(drvdata->dev, "TMC read end\n"); ++} ++ ++static int tmc_open(struct inode *inode, struct file *file) ++{ ++ struct tmc_drvdata *drvdata = container_of(file->private_data, ++ struct tmc_drvdata, miscdev); ++ int ret = 0; ++ ++ if (drvdata->read_count++) ++ goto out; ++ ++ ret = tmc_read_prepare(drvdata); ++ if (ret) ++ return ret; ++out: ++ nonseekable_open(inode, file); ++ ++ dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__); ++ return 0; ++} ++ ++static ssize_t tmc_read(struct file *file, char __user *data, size_t len, ++ loff_t *ppos) ++{ ++ struct tmc_drvdata *drvdata = container_of(file->private_data, ++ struct tmc_drvdata, miscdev); ++ char *bufp = drvdata->buf + *ppos; ++ ++ if (*ppos + len > drvdata->size) ++ len = drvdata->size - *ppos; ++ ++ if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) { ++ if (bufp == (char *)(drvdata->vaddr + drvdata->size)) ++ bufp = drvdata->vaddr; ++ else if (bufp > (char *)(drvdata->vaddr + drvdata->size)) ++ bufp -= drvdata->size; ++ if ((bufp + len) > (char *)(drvdata->vaddr + drvdata->size)) ++ len = (char *)(drvdata->vaddr + drvdata->size) - bufp; ++ } ++ ++ if (copy_to_user(data, bufp, len)) { ++ dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__); ++ return -EFAULT; ++ } ++ ++ *ppos += len; ++ ++ dev_dbg(drvdata->dev, "%s: %zu bytes copied, %d bytes left\n", ++ __func__, len, (int)(drvdata->size - *ppos)); ++ return len; ++} ++ ++static int tmc_release(struct inode *inode, struct file *file) ++{ ++ struct tmc_drvdata *drvdata = container_of(file->private_data, ++ struct tmc_drvdata, miscdev); ++ ++ if (--drvdata->read_count) { ++ if (drvdata->read_count < 0) { ++ dev_err(drvdata->dev, "mismatched close\n"); ++ drvdata->read_count = 0; ++ } ++ goto out; ++ } ++ ++ tmc_read_unprepare(drvdata); ++out: ++ dev_dbg(drvdata->dev, "%s: released\n", __func__); ++ return 0; ++} ++ ++static const struct file_operations tmc_fops = { ++ .owner = THIS_MODULE, ++ .open = tmc_open, ++ .read = tmc_read, ++ .release = tmc_release, ++ .llseek = no_llseek, ++}; ++ ++static ssize_t status_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ int ret; ++ unsigned long flags; ++ u32 tmc_rsz, tmc_sts, tmc_rrp, tmc_rwp, tmc_trg; ++ u32 tmc_ctl, tmc_ffsr, tmc_ffcr, tmc_mode, tmc_pscr; ++ u32 devid; ++ struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = clk_prepare_enable(drvdata->clk); ++ if (ret) ++ goto out; ++ ++ spin_lock_irqsave(&drvdata->spinlock, flags); ++ CS_UNLOCK(drvdata->base); ++ ++ tmc_rsz = readl_relaxed(drvdata->base + TMC_RSZ); ++ tmc_sts = readl_relaxed(drvdata->base + TMC_STS); ++ tmc_rrp = readl_relaxed(drvdata->base + TMC_RRP); ++ tmc_rwp = readl_relaxed(drvdata->base + TMC_RWP); ++ tmc_trg = readl_relaxed(drvdata->base + TMC_TRG); ++ tmc_ctl = readl_relaxed(drvdata->base + TMC_CTL); ++ tmc_ffsr = readl_relaxed(drvdata->base + TMC_FFSR); ++ tmc_ffcr = readl_relaxed(drvdata->base + TMC_FFCR); ++ tmc_mode = readl_relaxed(drvdata->base + TMC_MODE); ++ tmc_pscr = readl_relaxed(drvdata->base + TMC_PSCR); ++ devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID); ++ ++ CS_LOCK(drvdata->base); ++ spin_unlock_irqrestore(&drvdata->spinlock, flags); ++ ++ clk_disable_unprepare(drvdata->clk); ++ ++ return sprintf(buf, ++ "Depth:\t\t0x%x\n" ++ "Status:\t\t0x%x\n" ++ "RAM read ptr:\t0x%x\n" ++ "RAM wrt ptr:\t0x%x\n" ++ "Trigger cnt:\t0x%x\n" ++ "Control:\t0x%x\n" ++ "Flush status:\t0x%x\n" ++ "Flush ctrl:\t0x%x\n" ++ "Mode:\t\t0x%x\n" ++ "PSRC:\t\t0x%x\n" ++ "DEVID:\t\t0x%x\n", ++ tmc_rsz, tmc_sts, tmc_rrp, tmc_rwp, tmc_trg, ++ tmc_ctl, tmc_ffsr, tmc_ffcr, tmc_mode, tmc_pscr, devid); ++out: ++ return -EINVAL; ++} ++static DEVICE_ATTR_RO(status); ++ ++static ssize_t trigger_cntr_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ unsigned long val = drvdata->trigger_cntr; ++ ++ return sprintf(buf, "%#lx\n", val); ++} ++ ++static ssize_t trigger_cntr_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent); ++ ++ ret = kstrtoul(buf, 16, &val); ++ if (ret) ++ return ret; ++ ++ drvdata->trigger_cntr = val; ++ return size; ++} ++static DEVICE_ATTR_RW(trigger_cntr); ++ ++static struct attribute *coresight_etb_attrs[] = { ++ &dev_attr_trigger_cntr.attr, ++ &dev_attr_status.attr, ++ NULL, ++}; ++ATTRIBUTE_GROUPS(coresight_etb); ++ ++static struct attribute *coresight_etr_attrs[] = { ++ &dev_attr_trigger_cntr.attr, ++ &dev_attr_status.attr, ++ NULL, ++}; ++ATTRIBUTE_GROUPS(coresight_etr); ++ ++static struct attribute *coresight_etf_attrs[] = { ++ &dev_attr_trigger_cntr.attr, ++ &dev_attr_status.attr, ++ NULL, ++}; ++ATTRIBUTE_GROUPS(coresight_etf); ++ ++static int tmc_probe(struct amba_device *adev, const struct amba_id *id) ++{ ++ int ret = 0; ++ u32 devid; ++ void __iomem *base; ++ struct device *dev = &adev->dev; ++ struct coresight_platform_data *pdata = NULL; ++ struct tmc_drvdata *drvdata; ++ struct resource *res = &adev->res; ++ struct coresight_desc *desc; ++ struct device_node *np = adev->dev.of_node; ++ ++ if (np) { ++ pdata = of_get_coresight_platform_data(dev, np); ++ if (IS_ERR(pdata)) ++ return PTR_ERR(pdata); ++ adev->dev.platform_data = pdata; ++ } ++ ++ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); ++ if (!drvdata) ++ return -ENOMEM; ++ ++ drvdata->dev = &adev->dev; ++ dev_set_drvdata(dev, drvdata); ++ ++ /* Validity for the resource is already checked by the AMBA core */ ++ base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ drvdata->base = base; ++ ++ spin_lock_init(&drvdata->spinlock); ++ ++ drvdata->clk = adev->pclk; ++ ret = clk_prepare_enable(drvdata->clk); ++ if (ret) ++ return ret; ++ ++ devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID); ++ drvdata->config_type = BMVAL(devid, 6, 7); ++ ++ if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) { ++ if (np) ++ ret = of_property_read_u32(np, ++ "arm,buffer-size", ++ &drvdata->size); ++ if (ret) ++ drvdata->size = SZ_1M; ++ } else { ++ drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4; ++ } ++ ++ clk_disable_unprepare(drvdata->clk); ++ ++ if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) { ++ drvdata->vaddr = dma_alloc_coherent(dev, drvdata->size, ++ &drvdata->paddr, GFP_KERNEL); ++ if (!drvdata->vaddr) ++ return -ENOMEM; ++ ++ memset(drvdata->vaddr, 0, drvdata->size); ++ drvdata->buf = drvdata->vaddr; ++ } else { ++ drvdata->buf = devm_kzalloc(dev, drvdata->size, GFP_KERNEL); ++ if (!drvdata->buf) ++ return -ENOMEM; ++ } ++ ++ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); ++ if (!desc) { ++ ret = -ENOMEM; ++ goto err_devm_kzalloc; ++ } ++ ++ desc->pdata = pdata; ++ desc->dev = dev; ++ desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER; ++ ++ if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) { ++ desc->type = CORESIGHT_DEV_TYPE_SINK; ++ desc->ops = &tmc_etb_cs_ops; ++ desc->groups = coresight_etb_groups; ++ } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) { ++ desc->type = CORESIGHT_DEV_TYPE_SINK; ++ desc->ops = &tmc_etr_cs_ops; ++ desc->groups = coresight_etr_groups; ++ } else { ++ desc->type = CORESIGHT_DEV_TYPE_LINKSINK; ++ desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO; ++ desc->ops = &tmc_etf_cs_ops; ++ desc->groups = coresight_etf_groups; ++ } ++ ++ drvdata->csdev = coresight_register(desc); ++ if (IS_ERR(drvdata->csdev)) { ++ ret = PTR_ERR(drvdata->csdev); ++ goto err_devm_kzalloc; ++ } ++ ++ drvdata->miscdev.name = pdata->name; ++ drvdata->miscdev.minor = MISC_DYNAMIC_MINOR; ++ drvdata->miscdev.fops = &tmc_fops; ++ ret = misc_register(&drvdata->miscdev); ++ if (ret) ++ goto err_misc_register; ++ ++ dev_info(dev, "TMC initialized\n"); ++ return 0; ++ ++err_misc_register: ++ coresight_unregister(drvdata->csdev); ++err_devm_kzalloc: ++ if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) ++ dma_free_coherent(dev, drvdata->size, ++ &drvdata->paddr, GFP_KERNEL); ++ return ret; ++} ++ ++static int tmc_remove(struct amba_device *adev) ++{ ++ struct tmc_drvdata *drvdata = amba_get_drvdata(adev); ++ ++ misc_deregister(&drvdata->miscdev); ++ coresight_unregister(drvdata->csdev); ++ if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) ++ dma_free_coherent(drvdata->dev, drvdata->size, ++ &drvdata->paddr, GFP_KERNEL); ++ ++ return 0; ++} ++ ++static struct amba_id tmc_ids[] = { ++ { ++ .id = 0x0003b961, ++ .mask = 0x0003ffff, ++ }, ++ { 0, 0}, ++}; ++ ++static struct amba_driver tmc_driver = { ++ .drv = { ++ .name = "coresight-tmc", ++ .owner = THIS_MODULE, ++ }, ++ .probe = tmc_probe, ++ .remove = tmc_remove, ++ .id_table = tmc_ids, ++}; ++ ++module_amba_driver(tmc_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("CoreSight Trace Memory Controller driver"); +diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c +new file mode 100644 +index 0000000..3b33af2 +--- /dev/null ++++ b/drivers/hwtracing/coresight/coresight-tpiu.c +@@ -0,0 +1,207 @@ ++/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "coresight-priv.h" ++ ++#define TPIU_SUPP_PORTSZ 0x000 ++#define TPIU_CURR_PORTSZ 0x004 ++#define TPIU_SUPP_TRIGMODES 0x100 ++#define TPIU_TRIG_CNTRVAL 0x104 ++#define TPIU_TRIG_MULT 0x108 ++#define TPIU_SUPP_TESTPATM 0x200 ++#define TPIU_CURR_TESTPATM 0x204 ++#define TPIU_TEST_PATREPCNTR 0x208 ++#define TPIU_FFSR 0x300 ++#define TPIU_FFCR 0x304 ++#define TPIU_FSYNC_CNTR 0x308 ++#define TPIU_EXTCTL_INPORT 0x400 ++#define TPIU_EXTCTL_OUTPORT 0x404 ++#define TPIU_ITTRFLINACK 0xee4 ++#define TPIU_ITTRFLIN 0xee8 ++#define TPIU_ITATBDATA0 0xeec ++#define TPIU_ITATBCTR2 0xef0 ++#define TPIU_ITATBCTR1 0xef4 ++#define TPIU_ITATBCTR0 0xef8 ++ ++/** register definition **/ ++/* FFCR - 0x304 */ ++#define FFCR_FON_MAN BIT(6) ++ ++/** ++ * @base: memory mapped base address for this component. ++ * @dev: the device entity associated to this component. ++ * @csdev: component vitals needed by the framework. ++ * @clk: the clock this component is associated to. ++ */ ++struct tpiu_drvdata { ++ void __iomem *base; ++ struct device *dev; ++ struct coresight_device *csdev; ++ struct clk *clk; ++}; ++ ++static void tpiu_enable_hw(struct tpiu_drvdata *drvdata) ++{ ++ CS_UNLOCK(drvdata->base); ++ ++ /* TODO: fill this up */ ++ ++ CS_LOCK(drvdata->base); ++} ++ ++static int tpiu_enable(struct coresight_device *csdev) ++{ ++ struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); ++ int ret; ++ ++ ret = clk_prepare_enable(drvdata->clk); ++ if (ret) ++ return ret; ++ ++ tpiu_enable_hw(drvdata); ++ ++ dev_info(drvdata->dev, "TPIU enabled\n"); ++ return 0; ++} ++ ++static void tpiu_disable_hw(struct tpiu_drvdata *drvdata) ++{ ++ CS_UNLOCK(drvdata->base); ++ ++ /* Clear formatter controle reg. */ ++ writel_relaxed(0x0, drvdata->base + TPIU_FFCR); ++ /* Generate manual flush */ ++ writel_relaxed(FFCR_FON_MAN, drvdata->base + TPIU_FFCR); ++ ++ CS_LOCK(drvdata->base); ++} ++ ++static void tpiu_disable(struct coresight_device *csdev) ++{ ++ struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); ++ ++ tpiu_disable_hw(drvdata); ++ ++ clk_disable_unprepare(drvdata->clk); ++ ++ dev_info(drvdata->dev, "TPIU disabled\n"); ++} ++ ++static const struct coresight_ops_sink tpiu_sink_ops = { ++ .enable = tpiu_enable, ++ .disable = tpiu_disable, ++}; ++ ++static const struct coresight_ops tpiu_cs_ops = { ++ .sink_ops = &tpiu_sink_ops, ++}; ++ ++static int tpiu_probe(struct amba_device *adev, const struct amba_id *id) ++{ ++ int ret; ++ void __iomem *base; ++ struct device *dev = &adev->dev; ++ struct coresight_platform_data *pdata = NULL; ++ struct tpiu_drvdata *drvdata; ++ struct resource *res = &adev->res; ++ struct coresight_desc *desc; ++ struct device_node *np = adev->dev.of_node; ++ ++ if (np) { ++ pdata = of_get_coresight_platform_data(dev, np); ++ if (IS_ERR(pdata)) ++ return PTR_ERR(pdata); ++ adev->dev.platform_data = pdata; ++ } ++ ++ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); ++ if (!drvdata) ++ return -ENOMEM; ++ ++ drvdata->dev = &adev->dev; ++ dev_set_drvdata(dev, drvdata); ++ ++ /* Validity for the resource is already checked by the AMBA core */ ++ base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ drvdata->base = base; ++ ++ drvdata->clk = adev->pclk; ++ ret = clk_prepare_enable(drvdata->clk); ++ if (ret) ++ return ret; ++ ++ /* Disable tpiu to support older devices */ ++ tpiu_disable_hw(drvdata); ++ ++ clk_disable_unprepare(drvdata->clk); ++ ++ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); ++ if (!desc) ++ return -ENOMEM; ++ ++ desc->type = CORESIGHT_DEV_TYPE_SINK; ++ desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_PORT; ++ desc->ops = &tpiu_cs_ops; ++ desc->pdata = pdata; ++ desc->dev = dev; ++ drvdata->csdev = coresight_register(desc); ++ if (IS_ERR(drvdata->csdev)) ++ return PTR_ERR(drvdata->csdev); ++ ++ dev_info(dev, "TPIU initialized\n"); ++ return 0; ++} ++ ++static int tpiu_remove(struct amba_device *adev) ++{ ++ struct tpiu_drvdata *drvdata = amba_get_drvdata(adev); ++ ++ coresight_unregister(drvdata->csdev); ++ return 0; ++} ++ ++static struct amba_id tpiu_ids[] = { ++ { ++ .id = 0x0003b912, ++ .mask = 0x0003ffff, ++ }, ++ { 0, 0}, ++}; ++ ++static struct amba_driver tpiu_driver = { ++ .drv = { ++ .name = "coresight-tpiu", ++ .owner = THIS_MODULE, ++ }, ++ .probe = tpiu_probe, ++ .remove = tpiu_remove, ++ .id_table = tpiu_ids, ++}; ++ ++module_amba_driver(tpiu_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("CoreSight Trace Port Interface Unit driver"); +diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c +new file mode 100644 +index 0000000..894531d +--- /dev/null ++++ b/drivers/hwtracing/coresight/coresight.c +@@ -0,0 +1,720 @@ ++/* Copyright (c) 2012, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "coresight-priv.h" ++ ++static DEFINE_MUTEX(coresight_mutex); ++ ++static int coresight_id_match(struct device *dev, void *data) ++{ ++ int trace_id, i_trace_id; ++ struct coresight_device *csdev, *i_csdev; ++ ++ csdev = data; ++ i_csdev = to_coresight_device(dev); ++ ++ /* ++ * No need to care about oneself and components that are not ++ * sources or not enabled ++ */ ++ if (i_csdev == csdev || !i_csdev->enable || ++ i_csdev->type != CORESIGHT_DEV_TYPE_SOURCE) ++ return 0; ++ ++ /* Get the source ID for both compoment */ ++ trace_id = source_ops(csdev)->trace_id(csdev); ++ i_trace_id = source_ops(i_csdev)->trace_id(i_csdev); ++ ++ /* All you need is one */ ++ if (trace_id == i_trace_id) ++ return 1; ++ ++ return 0; ++} ++ ++static int coresight_source_is_unique(struct coresight_device *csdev) ++{ ++ int trace_id = source_ops(csdev)->trace_id(csdev); ++ ++ /* this shouldn't happen */ ++ if (trace_id < 0) ++ return 0; ++ ++ return !bus_for_each_dev(&coresight_bustype, NULL, ++ csdev, coresight_id_match); ++} ++ ++static int coresight_find_link_inport(struct coresight_device *csdev) ++{ ++ int i; ++ struct coresight_device *parent; ++ struct coresight_connection *conn; ++ ++ parent = container_of(csdev->path_link.next, ++ struct coresight_device, path_link); ++ ++ for (i = 0; i < parent->nr_outport; i++) { ++ conn = &parent->conns[i]; ++ if (conn->child_dev == csdev) ++ return conn->child_port; ++ } ++ ++ dev_err(&csdev->dev, "couldn't find inport, parent: %s, child: %s\n", ++ dev_name(&parent->dev), dev_name(&csdev->dev)); ++ ++ return 0; ++} ++ ++static int coresight_find_link_outport(struct coresight_device *csdev) ++{ ++ int i; ++ struct coresight_device *child; ++ struct coresight_connection *conn; ++ ++ child = container_of(csdev->path_link.prev, ++ struct coresight_device, path_link); ++ ++ for (i = 0; i < csdev->nr_outport; i++) { ++ conn = &csdev->conns[i]; ++ if (conn->child_dev == child) ++ return conn->outport; ++ } ++ ++ dev_err(&csdev->dev, "couldn't find outport, parent: %s, child: %s\n", ++ dev_name(&csdev->dev), dev_name(&child->dev)); ++ ++ return 0; ++} ++ ++static int coresight_enable_sink(struct coresight_device *csdev) ++{ ++ int ret; ++ ++ if (!csdev->enable) { ++ if (sink_ops(csdev)->enable) { ++ ret = sink_ops(csdev)->enable(csdev); ++ if (ret) ++ return ret; ++ } ++ csdev->enable = true; ++ } ++ ++ atomic_inc(csdev->refcnt); ++ ++ return 0; ++} ++ ++static void coresight_disable_sink(struct coresight_device *csdev) ++{ ++ if (atomic_dec_return(csdev->refcnt) == 0) { ++ if (sink_ops(csdev)->disable) { ++ sink_ops(csdev)->disable(csdev); ++ csdev->enable = false; ++ } ++ } ++} ++ ++static int coresight_enable_link(struct coresight_device *csdev) ++{ ++ int ret; ++ int link_subtype; ++ int refport, inport, outport; ++ ++ inport = coresight_find_link_inport(csdev); ++ outport = coresight_find_link_outport(csdev); ++ link_subtype = csdev->subtype.link_subtype; ++ ++ if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) ++ refport = inport; ++ else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) ++ refport = outport; ++ else ++ refport = 0; ++ ++ if (atomic_inc_return(&csdev->refcnt[refport]) == 1) { ++ if (link_ops(csdev)->enable) { ++ ret = link_ops(csdev)->enable(csdev, inport, outport); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ csdev->enable = true; ++ ++ return 0; ++} ++ ++static void coresight_disable_link(struct coresight_device *csdev) ++{ ++ int i, nr_conns; ++ int link_subtype; ++ int refport, inport, outport; ++ ++ inport = coresight_find_link_inport(csdev); ++ outport = coresight_find_link_outport(csdev); ++ link_subtype = csdev->subtype.link_subtype; ++ ++ if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) { ++ refport = inport; ++ nr_conns = csdev->nr_inport; ++ } else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) { ++ refport = outport; ++ nr_conns = csdev->nr_outport; ++ } else { ++ refport = 0; ++ nr_conns = 1; ++ } ++ ++ if (atomic_dec_return(&csdev->refcnt[refport]) == 0) { ++ if (link_ops(csdev)->disable) ++ link_ops(csdev)->disable(csdev, inport, outport); ++ } ++ ++ for (i = 0; i < nr_conns; i++) ++ if (atomic_read(&csdev->refcnt[i]) != 0) ++ return; ++ ++ csdev->enable = false; ++} ++ ++static int coresight_enable_source(struct coresight_device *csdev) ++{ ++ int ret; ++ ++ if (!coresight_source_is_unique(csdev)) { ++ dev_warn(&csdev->dev, "traceID %d not unique\n", ++ source_ops(csdev)->trace_id(csdev)); ++ return -EINVAL; ++ } ++ ++ if (!csdev->enable) { ++ if (source_ops(csdev)->enable) { ++ ret = source_ops(csdev)->enable(csdev); ++ if (ret) ++ return ret; ++ } ++ csdev->enable = true; ++ } ++ ++ atomic_inc(csdev->refcnt); ++ ++ return 0; ++} ++ ++static void coresight_disable_source(struct coresight_device *csdev) ++{ ++ if (atomic_dec_return(csdev->refcnt) == 0) { ++ if (source_ops(csdev)->disable) { ++ source_ops(csdev)->disable(csdev); ++ csdev->enable = false; ++ } ++ } ++} ++ ++static int coresight_enable_path(struct list_head *path) ++{ ++ int ret = 0; ++ struct coresight_device *cd; ++ ++ list_for_each_entry(cd, path, path_link) { ++ if (cd == list_first_entry(path, struct coresight_device, ++ path_link)) { ++ ret = coresight_enable_sink(cd); ++ } else if (list_is_last(&cd->path_link, path)) { ++ /* ++ * Don't enable the source just yet - this needs to ++ * happen at the very end when all links and sink ++ * along the path have been configured properly. ++ */ ++ ; ++ } else { ++ ret = coresight_enable_link(cd); ++ } ++ if (ret) ++ goto err; ++ } ++ ++ return 0; ++err: ++ list_for_each_entry_continue_reverse(cd, path, path_link) { ++ if (cd == list_first_entry(path, struct coresight_device, ++ path_link)) { ++ coresight_disable_sink(cd); ++ } else if (list_is_last(&cd->path_link, path)) { ++ ; ++ } else { ++ coresight_disable_link(cd); ++ } ++ } ++ ++ return ret; ++} ++ ++static int coresight_disable_path(struct list_head *path) ++{ ++ struct coresight_device *cd; ++ ++ list_for_each_entry_reverse(cd, path, path_link) { ++ if (cd == list_first_entry(path, struct coresight_device, ++ path_link)) { ++ coresight_disable_sink(cd); ++ } else if (list_is_last(&cd->path_link, path)) { ++ /* ++ * The source has already been stopped, no need ++ * to do it again here. ++ */ ++ ; ++ } else { ++ coresight_disable_link(cd); ++ } ++ } ++ ++ return 0; ++} ++ ++static int coresight_build_paths(struct coresight_device *csdev, ++ struct list_head *path, ++ bool enable) ++{ ++ int i, ret = -EINVAL; ++ struct coresight_connection *conn; ++ ++ list_add(&csdev->path_link, path); ++ ++ if ((csdev->type == CORESIGHT_DEV_TYPE_SINK || ++ csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) && ++ csdev->activated) { ++ if (enable) ++ ret = coresight_enable_path(path); ++ else ++ ret = coresight_disable_path(path); ++ } else { ++ for (i = 0; i < csdev->nr_outport; i++) { ++ conn = &csdev->conns[i]; ++ if (coresight_build_paths(conn->child_dev, ++ path, enable) == 0) ++ ret = 0; ++ } ++ } ++ ++ if (list_first_entry(path, struct coresight_device, path_link) != csdev) ++ dev_err(&csdev->dev, "wrong device in %s\n", __func__); ++ ++ list_del(&csdev->path_link); ++ ++ return ret; ++} ++ ++int coresight_enable(struct coresight_device *csdev) ++{ ++ int ret = 0; ++ LIST_HEAD(path); ++ ++ mutex_lock(&coresight_mutex); ++ if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) { ++ ret = -EINVAL; ++ dev_err(&csdev->dev, "wrong device type in %s\n", __func__); ++ goto out; ++ } ++ if (csdev->enable) ++ goto out; ++ ++ if (coresight_build_paths(csdev, &path, true)) { ++ dev_err(&csdev->dev, "building path(s) failed\n"); ++ goto out; ++ } ++ ++ if (coresight_enable_source(csdev)) ++ dev_err(&csdev->dev, "source enable failed\n"); ++out: ++ mutex_unlock(&coresight_mutex); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(coresight_enable); ++ ++void coresight_disable(struct coresight_device *csdev) ++{ ++ LIST_HEAD(path); ++ ++ mutex_lock(&coresight_mutex); ++ if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) { ++ dev_err(&csdev->dev, "wrong device type in %s\n", __func__); ++ goto out; ++ } ++ if (!csdev->enable) ++ goto out; ++ ++ coresight_disable_source(csdev); ++ if (coresight_build_paths(csdev, &path, false)) ++ dev_err(&csdev->dev, "releasing path(s) failed\n"); ++ ++out: ++ mutex_unlock(&coresight_mutex); ++} ++EXPORT_SYMBOL_GPL(coresight_disable); ++ ++static ssize_t enable_sink_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct coresight_device *csdev = to_coresight_device(dev); ++ ++ return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->activated); ++} ++ ++static ssize_t enable_sink_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret; ++ unsigned long val; ++ struct coresight_device *csdev = to_coresight_device(dev); ++ ++ ret = kstrtoul(buf, 10, &val); ++ if (ret) ++ return ret; ++ ++ if (val) ++ csdev->activated = true; ++ else ++ csdev->activated = false; ++ ++ return size; ++ ++} ++static DEVICE_ATTR_RW(enable_sink); ++ ++static ssize_t enable_source_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct coresight_device *csdev = to_coresight_device(dev); ++ ++ return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->enable); ++} ++ ++static ssize_t enable_source_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int ret = 0; ++ unsigned long val; ++ struct coresight_device *csdev = to_coresight_device(dev); ++ ++ ret = kstrtoul(buf, 10, &val); ++ if (ret) ++ return ret; ++ ++ if (val) { ++ ret = coresight_enable(csdev); ++ if (ret) ++ return ret; ++ } else { ++ coresight_disable(csdev); ++ } ++ ++ return size; ++} ++static DEVICE_ATTR_RW(enable_source); ++ ++static struct attribute *coresight_sink_attrs[] = { ++ &dev_attr_enable_sink.attr, ++ NULL, ++}; ++ATTRIBUTE_GROUPS(coresight_sink); ++ ++static struct attribute *coresight_source_attrs[] = { ++ &dev_attr_enable_source.attr, ++ NULL, ++}; ++ATTRIBUTE_GROUPS(coresight_source); ++ ++static struct device_type coresight_dev_type[] = { ++ { ++ .name = "none", ++ }, ++ { ++ .name = "sink", ++ .groups = coresight_sink_groups, ++ }, ++ { ++ .name = "link", ++ }, ++ { ++ .name = "linksink", ++ .groups = coresight_sink_groups, ++ }, ++ { ++ .name = "source", ++ .groups = coresight_source_groups, ++ }, ++}; ++ ++static void coresight_device_release(struct device *dev) ++{ ++ struct coresight_device *csdev = to_coresight_device(dev); ++ ++ kfree(csdev); ++} ++ ++static int coresight_orphan_match(struct device *dev, void *data) ++{ ++ int i; ++ bool still_orphan = false; ++ struct coresight_device *csdev, *i_csdev; ++ struct coresight_connection *conn; ++ ++ csdev = data; ++ i_csdev = to_coresight_device(dev); ++ ++ /* No need to check oneself */ ++ if (csdev == i_csdev) ++ return 0; ++ ++ /* Move on to another component if no connection is orphan */ ++ if (!i_csdev->orphan) ++ return 0; ++ /* ++ * Circle throuch all the connection of that component. If we find ++ * an orphan connection whose name matches @csdev, link it. ++ */ ++ for (i = 0; i < i_csdev->nr_outport; i++) { ++ conn = &i_csdev->conns[i]; ++ ++ /* We have found at least one orphan connection */ ++ if (conn->child_dev == NULL) { ++ /* Does it match this newly added device? */ ++ if (!strcmp(dev_name(&csdev->dev), conn->child_name)) { ++ conn->child_dev = csdev; ++ } else { ++ /* This component still has an orphan */ ++ still_orphan = true; ++ } ++ } ++ } ++ ++ i_csdev->orphan = still_orphan; ++ ++ /* ++ * Returning '0' ensures that all known component on the ++ * bus will be checked. ++ */ ++ return 0; ++} ++ ++static void coresight_fixup_orphan_conns(struct coresight_device *csdev) ++{ ++ /* ++ * No need to check for a return value as orphan connection(s) ++ * are hooked-up with each newly added component. ++ */ ++ bus_for_each_dev(&coresight_bustype, NULL, ++ csdev, coresight_orphan_match); ++} ++ ++ ++static int coresight_name_match(struct device *dev, void *data) ++{ ++ char *to_match; ++ struct coresight_device *i_csdev; ++ ++ to_match = data; ++ i_csdev = to_coresight_device(dev); ++ ++ if (!strcmp(to_match, dev_name(&i_csdev->dev))) ++ return 1; ++ ++ return 0; ++} ++ ++static void coresight_fixup_device_conns(struct coresight_device *csdev) ++{ ++ int i; ++ struct device *dev = NULL; ++ struct coresight_connection *conn; ++ ++ for (i = 0; i < csdev->nr_outport; i++) { ++ conn = &csdev->conns[i]; ++ dev = bus_find_device(&coresight_bustype, NULL, ++ (void *)conn->child_name, ++ coresight_name_match); ++ ++ if (dev) { ++ conn->child_dev = to_coresight_device(dev); ++ } else { ++ csdev->orphan = true; ++ conn->child_dev = NULL; ++ } ++ } ++} ++ ++/** ++ * coresight_timeout - loop until a bit has changed to a specific state. ++ * @addr: base address of the area of interest. ++ * @offset: address of a register, starting from @addr. ++ * @position: the position of the bit of interest. ++ * @value: the value the bit should have. ++ * ++ * Return: 0 as soon as the bit has taken the desired state or -EAGAIN if ++ * TIMEOUT_US has elapsed, which ever happens first. ++ */ ++ ++int coresight_timeout(void __iomem *addr, u32 offset, int position, int value) ++{ ++ int i; ++ u32 val; ++ ++ for (i = TIMEOUT_US; i > 0; i--) { ++ val = __raw_readl(addr + offset); ++ /* waiting on the bit to go from 0 to 1 */ ++ if (value) { ++ if (val & BIT(position)) ++ return 0; ++ /* waiting on the bit to go from 1 to 0 */ ++ } else { ++ if (!(val & BIT(position))) ++ return 0; ++ } ++ ++ /* ++ * Delay is arbitrary - the specification doesn't say how long ++ * we are expected to wait. Extra check required to make sure ++ * we don't wait needlessly on the last iteration. ++ */ ++ if (i - 1) ++ udelay(1); ++ } ++ ++ return -EAGAIN; ++} ++ ++struct bus_type coresight_bustype = { ++ .name = "coresight", ++}; ++ ++static int __init coresight_init(void) ++{ ++ return bus_register(&coresight_bustype); ++} ++postcore_initcall(coresight_init); ++ ++struct coresight_device *coresight_register(struct coresight_desc *desc) ++{ ++ int i; ++ int ret; ++ int link_subtype; ++ int nr_refcnts = 1; ++ atomic_t *refcnts = NULL; ++ struct coresight_device *csdev; ++ struct coresight_connection *conns; ++ ++ csdev = kzalloc(sizeof(*csdev), GFP_KERNEL); ++ if (!csdev) { ++ ret = -ENOMEM; ++ goto err_kzalloc_csdev; ++ } ++ ++ if (desc->type == CORESIGHT_DEV_TYPE_LINK || ++ desc->type == CORESIGHT_DEV_TYPE_LINKSINK) { ++ link_subtype = desc->subtype.link_subtype; ++ ++ if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) ++ nr_refcnts = desc->pdata->nr_inport; ++ else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) ++ nr_refcnts = desc->pdata->nr_outport; ++ } ++ ++ refcnts = kcalloc(nr_refcnts, sizeof(*refcnts), GFP_KERNEL); ++ if (!refcnts) { ++ ret = -ENOMEM; ++ goto err_kzalloc_refcnts; ++ } ++ ++ csdev->refcnt = refcnts; ++ ++ csdev->nr_inport = desc->pdata->nr_inport; ++ csdev->nr_outport = desc->pdata->nr_outport; ++ conns = kcalloc(csdev->nr_outport, sizeof(*conns), GFP_KERNEL); ++ if (!conns) { ++ ret = -ENOMEM; ++ goto err_kzalloc_conns; ++ } ++ ++ for (i = 0; i < csdev->nr_outport; i++) { ++ conns[i].outport = desc->pdata->outports[i]; ++ conns[i].child_name = desc->pdata->child_names[i]; ++ conns[i].child_port = desc->pdata->child_ports[i]; ++ } ++ ++ csdev->conns = conns; ++ ++ csdev->type = desc->type; ++ csdev->subtype = desc->subtype; ++ csdev->ops = desc->ops; ++ csdev->orphan = false; ++ ++ csdev->dev.type = &coresight_dev_type[desc->type]; ++ csdev->dev.groups = desc->groups; ++ csdev->dev.parent = desc->dev; ++ csdev->dev.release = coresight_device_release; ++ csdev->dev.bus = &coresight_bustype; ++ dev_set_name(&csdev->dev, "%s", desc->pdata->name); ++ ++ ret = device_register(&csdev->dev); ++ if (ret) ++ goto err_device_register; ++ ++ mutex_lock(&coresight_mutex); ++ ++ coresight_fixup_device_conns(csdev); ++ coresight_fixup_orphan_conns(csdev); ++ ++ mutex_unlock(&coresight_mutex); ++ ++ return csdev; ++ ++err_device_register: ++ kfree(conns); ++err_kzalloc_conns: ++ kfree(refcnts); ++err_kzalloc_refcnts: ++ kfree(csdev); ++err_kzalloc_csdev: ++ return ERR_PTR(ret); ++} ++EXPORT_SYMBOL_GPL(coresight_register); ++ ++void coresight_unregister(struct coresight_device *csdev) ++{ ++ mutex_lock(&coresight_mutex); ++ ++ kfree(csdev->conns); ++ device_unregister(&csdev->dev); ++ ++ mutex_unlock(&coresight_mutex); ++} ++EXPORT_SYMBOL_GPL(coresight_unregister); ++ ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/hwtracing/coresight/of_coresight.c b/drivers/hwtracing/coresight/of_coresight.c +new file mode 100644 +index 0000000..f3cc8e9 +--- /dev/null ++++ b/drivers/hwtracing/coresight/of_coresight.c +@@ -0,0 +1,200 @@ ++/* Copyright (c) 2012, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++static int of_dev_node_match(struct device *dev, void *data) ++{ ++ return dev->of_node == data; ++} ++ ++static struct device * ++of_coresight_get_endpoint_device(struct device_node *endpoint) ++{ ++ struct device *dev = NULL; ++ ++ /* ++ * If we have a non-configuable replicator, it will be found on the ++ * platform bus. ++ */ ++ dev = bus_find_device(&platform_bus_type, NULL, ++ endpoint, of_dev_node_match); ++ if (dev) ++ return dev; ++ ++ /* ++ * We have a configurable component - circle through the AMBA bus ++ * looking for the device that matches the endpoint node. ++ */ ++ return bus_find_device(&amba_bustype, NULL, ++ endpoint, of_dev_node_match); ++} ++ ++static struct device_node *of_get_coresight_endpoint( ++ const struct device_node *parent, struct device_node *prev) ++{ ++ struct device_node *node = of_graph_get_next_endpoint(parent, prev); ++ ++ of_node_put(prev); ++ return node; ++} ++ ++static void of_coresight_get_ports(struct device_node *node, ++ int *nr_inport, int *nr_outport) ++{ ++ struct device_node *ep = NULL; ++ int in = 0, out = 0; ++ ++ do { ++ ep = of_get_coresight_endpoint(node, ep); ++ if (!ep) ++ break; ++ ++ if (of_property_read_bool(ep, "slave-mode")) ++ in++; ++ else ++ out++; ++ ++ } while (ep); ++ ++ *nr_inport = in; ++ *nr_outport = out; ++} ++ ++static int of_coresight_alloc_memory(struct device *dev, ++ struct coresight_platform_data *pdata) ++{ ++ /* List of output port on this component */ ++ pdata->outports = devm_kzalloc(dev, pdata->nr_outport * ++ sizeof(*pdata->outports), ++ GFP_KERNEL); ++ if (!pdata->outports) ++ return -ENOMEM; ++ ++ /* Children connected to this component via @outports */ ++ pdata->child_names = devm_kzalloc(dev, pdata->nr_outport * ++ sizeof(*pdata->child_names), ++ GFP_KERNEL); ++ if (!pdata->child_names) ++ return -ENOMEM; ++ ++ /* Port number on the child this component is connected to */ ++ pdata->child_ports = devm_kzalloc(dev, pdata->nr_outport * ++ sizeof(*pdata->child_ports), ++ GFP_KERNEL); ++ if (!pdata->child_ports) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++struct coresight_platform_data *of_get_coresight_platform_data( ++ struct device *dev, struct device_node *node) ++{ ++ int i = 0, ret = 0, cpu; ++ struct coresight_platform_data *pdata; ++ struct of_endpoint endpoint, rendpoint; ++ struct device *rdev; ++ struct device_node *dn; ++ struct device_node *ep = NULL; ++ struct device_node *rparent = NULL; ++ struct device_node *rport = NULL; ++ ++ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) ++ return ERR_PTR(-ENOMEM); ++ ++ /* Use device name as sysfs handle */ ++ pdata->name = dev_name(dev); ++ ++ /* Get the number of input and output port for this component */ ++ of_coresight_get_ports(node, &pdata->nr_inport, &pdata->nr_outport); ++ ++ if (pdata->nr_outport) { ++ ret = of_coresight_alloc_memory(dev, pdata); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ /* Iterate through each port to discover topology */ ++ do { ++ /* Get a handle on a port */ ++ ep = of_get_coresight_endpoint(node, ep); ++ if (!ep) ++ break; ++ ++ /* ++ * No need to deal with input ports, processing for as ++ * processing for output ports will deal with them. ++ */ ++ if (of_find_property(ep, "slave-mode", NULL)) ++ continue; ++ ++ /* Get a handle on the local endpoint */ ++ ret = of_graph_parse_endpoint(ep, &endpoint); ++ ++ if (ret) ++ continue; ++ ++ /* The local out port number */ ++ pdata->outports[i] = endpoint.id; ++ ++ /* ++ * Get a handle on the remote port and parent ++ * attached to it. ++ */ ++ rparent = of_graph_get_remote_port_parent(ep); ++ rport = of_graph_get_remote_port(ep); ++ ++ if (!rparent || !rport) ++ continue; ++ ++ if (of_graph_parse_endpoint(rport, &rendpoint)) ++ continue; ++ ++ rdev = of_coresight_get_endpoint_device(rparent); ++ if (!rdev) ++ continue; ++ ++ pdata->child_names[i] = dev_name(rdev); ++ pdata->child_ports[i] = rendpoint.id; ++ ++ i++; ++ } while (ep); ++ } ++ ++ /* Affinity defaults to CPU0 */ ++ pdata->cpu = 0; ++ dn = of_parse_phandle(node, "cpu", 0); ++ for (cpu = 0; dn && cpu < nr_cpu_ids; cpu++) { ++ if (dn == of_get_cpu_node(cpu, NULL)) { ++ pdata->cpu = cpu; ++ break; ++ } ++ } ++ ++ return pdata; ++} ++EXPORT_SYMBOL_GPL(of_get_coresight_platform_data); +diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig +index 917c358..cec7392 100644 +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -501,6 +501,16 @@ config I2C_GPIO + This is a very simple bitbanging I2C driver utilizing the + arch-neutral GPIO API to control the SCL and SDA lines. + ++config I2C_HIBVT ++ tristate "Hisilicon BVT I2C Controller" ++ depends on ARCH_HISI ++ help ++ Say Y here to include support for Hisilicon BVT I2C controller in the ++ Hisilicon BVT SoCs. ++ ++ This driver can also be built as a module. If so, the module ++ will be called i2c-hibvt. ++ + config I2C_HIGHLANDER + tristate "Highlander FPGA SMBus interface" + depends on SH_HIGHLANDER +@@ -513,6 +523,16 @@ config I2C_HIGHLANDER + This driver can also be built as a module. If so, the module + will be called i2c-highlander. + ++config I2C_HISI_V110 ++ tristate "Hisilicon I2C V110 Controller" ++ depends on ARCH_HISI ++ help ++ Say Y here to include support for Hisilicon I2C V110 controller in the ++ Hisilicon BVT SoCs. ++ ++ This driver can also be built as a module. If so, the module ++ will be called i2c-hisiv110. ++ + config I2C_IBM_IIC + tristate "IBM PPC 4xx on-chip I2C interface" + depends on 4xx +@@ -1044,4 +1064,84 @@ config SCx200_ACB + This support is also available as a module. If so, the module + will be called scx200_acb. + ++config HI_I2C ++ tristate "Hisilicon I2C Controller support" ++ depends on (ARCH_HI3519 || ARCH_HI3531D || ARCH_HI3521D || ARCH_HI3536C) ++ help ++ Hisilicon I2C controller has 3 buses. ++ We can access some sensors though it. ++ This IP is only used in HI3519/HI3531D/HI3521D/HI3536C chip. ++ ++if HI_I2C ++config HI_I2C0_IO_BASE ++ hex "hi i2c0 register base address" ++ default "0x12110000" if ARCH_HI3519 ++ default "0x120c0000" if (ARCH_HI3531D || ARCH_HI3521D || ARCH_HI3536C) ++ ++config HI_I2C0_IO_SIZE ++ hex "hi i2c0 register size" ++ default "0x1000" if (ARCH_HI3519 || ARCH_HI3531D || ARCH_HI3521D|| ARCH_HI3536C) ++ ++config HI_I2C1_IO_BASE ++ hex "hi i2c1 register base address" ++ depends on (ARCH_HI3519 || ARCH_HI3531D) ++ default "0x12111000" if ARCH_HI3519 ++ default "0x122e0000" if ARCH_HI3531D ++ ++config HI_I2C1_IO_SIZE ++ hex "hi i2c1 register size" ++ depends on (ARCH_HI3519 || ARCH_HI3531D) ++ default "0x1000" if (ARCH_HI3519 || ARCH_HI3531D) ++ ++config HI_I2C2_IO_BASE ++ hex "hi i2c2 register base address" ++ depends on ARCH_HI3519 ++ default "0x12112000" if ARCH_HI3519 ++ ++config HI_I2C2_IO_SIZE ++ hex "hi i2c2 register size" ++ depends on ARCH_HI3519 ++ default "0x1000" if ARCH_HI3519 ++ ++config HI_I2C3_IO_BASE ++ hex "hi i2c3 register base address" ++ depends on ARCH_HI3519 ++ default "0x12113000" if ARCH_HI3519 ++ ++config HI_I2C3_IO_SIZE ++ hex "hi i2c3 register size" ++ depends on ARCH_HI3519 ++ default "0x1000" if ARCH_HI3519 ++ ++config HI_I2C_RETRIES ++ hex "hi i2c retry times" ++ default "0x1" if (ARCH_HI3519 || ARCH_HI3531D || ARCH_HI3521D || ARCH_HI3536C) ++ ++config HI_I2C_TX_FIFO ++ hex "hi i2c tx fifo" ++ default "0x8" if (ARCH_HI3519 || ARCH_HI3531D || ARCH_HI3521D || ARCH_HI3536C) ++ ++config HI_I2C_RX_FIFO ++ hex "hi i2c rx fifo" ++ default "0x8" if (ARCH_HI3519 || ARCH_HI3531D || ARCH_HI3521D || ARCH_HI3536C) ++ ++config HI_I2C0_CLK_LIMIT ++ int "hi i2c0 clock limit" ++ default "100000" if (ARCH_HI3519 || ARCH_HI3531D || ARCH_HI3521D || ARCH_HI3536C) ++ ++config HI_I2C1_CLK_LIMIT ++ int "hi i2c1 clock limit" ++ depends on (ARCH_HI3519 || ARCH_HI3531D) ++ default "100000" if (ARCH_HI3519 || ARCH_HI3531D) ++ ++config HI_I2C2_CLK_LIMIT ++ int "hi i2c2 clock limit" ++ depends on ARCH_HI3519 ++ default "100000" if ARCH_HI3519 ++ ++config HI_I2C3_CLK_LIMIT ++ int "hi i2c3 clock limit" ++ depends on ARCH_HI3519 ++ default "100000" if ARCH_HI3519 ++endif + endmenu +diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile +index 78d56c5..bdc2c01 100644 +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -47,7 +47,9 @@ obj-$(CONFIG_I2C_EFM32) += i2c-efm32.o + obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o + obj-$(CONFIG_I2C_EXYNOS5) += i2c-exynos5.o + obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o ++obj-$(CONFIG_I2C_HIBVT) += i2c-hibvt.o + obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o ++obj-$(CONFIG_I2C_HISI_V110) += i2c-hisi-v110.o + obj-$(CONFIG_I2C_HIX5HD2) += i2c-hix5hd2.o + obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o + obj-$(CONFIG_I2C_IMX) += i2c-imx.o +@@ -103,4 +105,5 @@ obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o + obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o + obj-$(CONFIG_SCx200_ACB) += scx200_acb.o + ++obj-$(CONFIG_HI_I2C) += i2c-hisilicon.o + ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG +diff --git a/drivers/i2c/busses/i2c-hibvt.c b/drivers/i2c/busses/i2c-hibvt.c +new file mode 100644 +index 0000000..478478b +--- /dev/null ++++ b/drivers/i2c/busses/i2c-hibvt.c +@@ -0,0 +1,920 @@ ++/* ++ * Hisilicon BVT I2C Controller Driver ++ * ++ * Copyright (c) 2016 HiSilicon Technologies Co., Ltd. ++ * ++ * Authors: wenpan@hisilicon.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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * I2C Registers offsets ++ */ ++#define HIBVT_I2C_GLB 0x0 ++#define HIBVT_I2C_SCL_H 0x4 ++#define HIBVT_I2C_SCL_L 0x8 ++#define HIBVT_I2C_DATA1 0x10 ++#define HIBVT_I2C_TXF 0x20 ++#define HIBVT_I2C_RXF 0x24 ++#define HIBVT_I2C_CMD_BASE 0x30 ++#define HIBVT_I2C_LOOP1 0xb0 ++#define HIBVT_I2C_DST1 0xb4 ++#define HIBVT_I2C_TX_WATER 0xc8 ++#define HIBVT_I2C_RX_WATER 0xcc ++#define HIBVT_I2C_CTRL1 0xd0 ++#define HIBVT_I2C_CTRL2 0xd4 ++#define HIBVT_I2C_STAT 0xd8 ++#define HIBVT_I2C_INTR_RAW 0xe0 ++#define HIBVT_I2C_INTR_EN 0xe4 ++#define HIBVT_I2C_INTR_STAT 0xe8 ++ ++/* ++ * I2C Global Config Register -- HIBVT_I2C_GLB ++ */ ++#define GLB_EN_MASK BIT(0) ++#define GLB_SDA_HOLD_MASK GENMASK(23, 8) ++#define GLB_SDA_HOLD_SHIFT (8) ++ ++/* ++ * I2C Timing CMD Register -- HIBVT_I2C_CMD_BASE + n * 4 (n = 0, 1, 2, ... 31) ++ */ ++#define CMD_EXIT 0x0 ++#define CMD_TX_S 0x1 ++#define CMD_TX_D1_2 0x4 ++#define CMD_TX_D1_1 0x5 ++#define CMD_TX_FIFO 0x9 ++#define CMD_RX_FIFO 0x12 ++#define CMD_RX_ACK 0x13 ++#define CMD_IGN_ACK 0x15 ++#define CMD_TX_ACK 0x16 ++#define CMD_TX_NACK 0x17 ++#define CMD_JMP1 0x18 ++#define CMD_UP_TXF 0x1d ++#define CMD_TX_RS 0x1e ++#define CMD_TX_P 0x1f ++ ++/* ++ * I2C Control Register 1 -- HIBVT_I2C_CTRL1 ++ */ ++#define CTRL1_CMD_START_MASK BIT(0) ++ ++/* ++ * I2C Status Register -- HIBVT_I2C_STAT ++ */ ++#define STAT_RXF_NOE_MASK BIT(16) /* RX FIFO not empty flag */ ++#define STAT_TXF_NOF_MASK BIT(19) /* TX FIFO not full flag */ ++ ++ ++/* ++ * I2C Interrupt status and mask Register -- ++ * HIBVT_I2C_INTR_RAW, HIBVT_I2C_STAT, HIBVT_I2C_INTR_STAT ++ */ ++#define INTR_ABORT_MASK (BIT(0) | BIT(11)) ++#define INTR_RX_MASK BIT(2) ++#define INTR_TX_MASK BIT(4) ++#define INTR_CMD_DONE_MASK BIT(12) ++#define INTR_USE_MASK (INTR_ABORT_MASK \ ++ |INTR_RX_MASK \ ++ | INTR_TX_MASK \ ++ | INTR_CMD_DONE_MASK) ++#define INTR_ALL_MASK GENMASK(31, 0) ++ ++#define I2C_DEFAULT_FREQUENCY 100000 ++#define I2C_TXF_DEPTH 64 ++#define I2C_RXF_DEPTH 64 ++#define I2C_TXF_WATER 32 ++#define I2C_RXF_WATER 32 ++#define I2C_WAIT_TIMEOUT 0x10000 ++#define I2C_IRQ_TIMEOUT (msecs_to_jiffies(1000)) ++ ++ ++struct hibvt_i2c_dev { ++ struct device *dev; ++ struct i2c_adapter adap; ++ void __iomem *base; ++ struct clk *clk; ++ int irq; ++ ++ unsigned int freq; ++ struct i2c_msg *msg; ++ unsigned int msg_num; ++ unsigned int msg_idx; ++ unsigned int msg_buf_ptr; ++ struct completion msg_complete; ++ ++ spinlock_t lock; ++ int status; ++}; ++static inline void hibvt_i2c_disable(struct hibvt_i2c_dev *i2c); ++static inline void hibvt_i2c_cfg_irq(struct hibvt_i2c_dev *i2c, ++ unsigned int flag); ++static inline unsigned int hibvt_i2c_clr_irq(struct hibvt_i2c_dev *i2c); ++static inline void hibvt_i2c_enable(struct hibvt_i2c_dev *i2c); ++ ++#define CHECK_SDA_IN_SHIFT (16) ++#define GPIO_MODE_SHIFT (8) ++#define FORCE_SCL_OEN_SHIFT (4) ++#define FORCE_SDA_OEN_SHIFT (0) ++ ++static void hibvt_i2c_rescue(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int val; ++ unsigned int time_cnt; ++ int index; ++ ++ hibvt_i2c_disable(i2c); ++ hibvt_i2c_cfg_irq(i2c, 0); ++ hibvt_i2c_clr_irq(i2c); ++ ++ val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT); ++ writel(val, i2c->base + HIBVT_I2C_CTRL2); ++ ++ time_cnt = 0; ++ do { ++ for (index = 0; index < 9; index++) { ++ val = (0x1 << GPIO_MODE_SHIFT) | 0x1; ++ writel(val, i2c->base + HIBVT_I2C_CTRL2); ++ ++ udelay(5); ++ ++ val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT); ++ writel(val, i2c->base + HIBVT_I2C_CTRL2); ++ ++ udelay(5); ++ } ++ ++ time_cnt++; ++ if (time_cnt > I2C_WAIT_TIMEOUT) { ++ dev_err(i2c->dev, "wait Timeout!\n"); ++ goto disable_rescue; ++ } ++ ++ val = readl(i2c->base + HIBVT_I2C_CTRL2); ++ } while(!(val & (0x1 << CHECK_SDA_IN_SHIFT))); ++ ++ ++ val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT); ++ writel(val, i2c->base + HIBVT_I2C_CTRL2); ++ ++ val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT); ++ writel(val, i2c->base + HIBVT_I2C_CTRL2); ++ ++ udelay(10); ++ ++ val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT); ++ writel(val, i2c->base + HIBVT_I2C_CTRL2); ++ ++disable_rescue: ++ val = (0x1 << FORCE_SCL_OEN_SHIFT) | 0x1; ++ writel(val, i2c->base + HIBVT_I2C_CTRL2); ++} ++ ++static inline void hibvt_i2c_disable(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int val; ++ ++ val = readl(i2c->base + HIBVT_I2C_GLB); ++ val &= ~GLB_EN_MASK; ++ writel(val, i2c->base + HIBVT_I2C_GLB); ++} ++ ++static inline void hibvt_i2c_enable(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int val; ++ ++ val = readl(i2c->base + HIBVT_I2C_GLB); ++ val |= GLB_EN_MASK; ++ writel(val, i2c->base + HIBVT_I2C_GLB); ++} ++ ++static inline void hibvt_i2c_cfg_irq(struct hibvt_i2c_dev *i2c, ++ unsigned int flag) ++{ ++ writel(flag, i2c->base + HIBVT_I2C_INTR_EN); ++} ++ ++static inline void hibvt_i2c_disable_irq(struct hibvt_i2c_dev *i2c, ++ unsigned int flag) ++{ ++ unsigned int val; ++ ++ val = readl(i2c->base + HIBVT_I2C_INTR_EN); ++ val &= ~flag; ++ writel(val, i2c->base + HIBVT_I2C_INTR_EN); ++} ++ ++static inline unsigned int hibvt_i2c_clr_irq(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int val; ++ ++ val = readl(i2c->base + HIBVT_I2C_INTR_STAT); ++ writel(INTR_ALL_MASK, i2c->base + HIBVT_I2C_INTR_RAW); ++ ++ return val; ++} ++ ++static inline void hibvt_i2c_cmdreg_set(struct hibvt_i2c_dev *i2c, ++ unsigned int cmd, unsigned int *offset) ++{ ++ dev_dbg(i2c->dev, "hii2c reg: offset=0x%x, cmd=0x%x...\n", ++ *offset * 4, cmd); ++ writel(cmd, i2c->base + HIBVT_I2C_CMD_BASE + *offset * 4); ++ (*offset)++; ++} ++ ++/* ++ * config i2c slave addr ++ */ ++static inline void hibvt_i2c_set_addr(struct hibvt_i2c_dev *i2c) ++{ ++ struct i2c_msg *msg = i2c->msg; ++ u16 addr; ++ ++ if (msg->flags & I2C_M_TEN) { ++ /* First byte is 11110XX0 where XX is upper 2 bits */ ++ addr = ((msg->addr & 0x300) << 1) | 0xf000; ++ if (msg->flags & I2C_M_RD) ++ addr |= 1 << 8; ++ ++ /* Second byte is the remaining 8 bits */ ++ addr |= msg->addr & 0xff; ++ } else { ++ addr = (msg->addr & 0x7f) << 1; ++ if (msg->flags & I2C_M_RD) ++ addr |= 1; ++ } ++ ++ writel(addr, i2c->base + HIBVT_I2C_DATA1); ++} ++ ++/* ++ * Start command sequence ++ */ ++static inline void hibvt_i2c_start_cmd(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int val; ++ ++ val = readl(i2c->base + HIBVT_I2C_CTRL1); ++ val |= CTRL1_CMD_START_MASK; ++ writel(val, i2c->base + HIBVT_I2C_CTRL1); ++} ++ ++static int hibvt_i2c_wait_rx_noempty(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int time_cnt = 0; ++ unsigned int val; ++ ++ do { ++ val = readl(i2c->base + HIBVT_I2C_STAT); ++ if (val & STAT_RXF_NOE_MASK) ++ return 0; ++ ++ udelay(50); ++ } while (time_cnt++ < I2C_WAIT_TIMEOUT); ++ ++ hibvt_i2c_rescue(i2c); ++ ++ dev_err(i2c->dev, "wait rx no empty timeout, RIS: 0x%x, SR: 0x%x\n", ++ readl(i2c->base + HIBVT_I2C_INTR_RAW), val); ++ return -EIO; ++} ++ ++static int hibvt_i2c_wait_tx_nofull(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int time_cnt = 0; ++ unsigned int val; ++ ++ do { ++ val = readl(i2c->base + HIBVT_I2C_STAT); ++ if (val & STAT_TXF_NOF_MASK) ++ return 0; ++ ++ udelay(50); ++ } while (time_cnt++ < I2C_WAIT_TIMEOUT); ++ ++ hibvt_i2c_rescue(i2c); ++ ++ dev_err(i2c->dev, "wait rx no empty timeout, RIS: 0x%x, SR: 0x%x\n", ++ readl(i2c->base + HIBVT_I2C_INTR_RAW), val); ++ return -EIO; ++} ++ ++static int hibvt_i2c_wait_idle(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int time_cnt = 0; ++ unsigned int val; ++ ++ do { ++ val = readl(i2c->base + HIBVT_I2C_INTR_RAW); ++ if (val & (INTR_ABORT_MASK)) { ++ dev_err(i2c->dev, "wait idle abort!, RIS: 0x%x\n", ++ val); ++ return -EIO; ++ } ++ ++ if (val & INTR_CMD_DONE_MASK) ++ return 0; ++ ++ udelay(50); ++ } while (time_cnt++ < I2C_WAIT_TIMEOUT); ++ ++ hibvt_i2c_rescue(i2c); ++ ++ dev_err(i2c->dev, "wait idle timeout, RIS: 0x%x, SR: 0x%x\n", ++ val, readl(i2c->base + HIBVT_I2C_STAT)); ++ ++ return -EIO; ++} ++ ++static void hibvt_i2c_set_freq(struct hibvt_i2c_dev *i2c) ++{ ++ unsigned int max_freq, freq; ++ unsigned int clk_rate; ++ unsigned int val; ++ ++ freq = i2c->freq; ++ clk_rate = clk_get_rate(i2c->clk); ++ max_freq = clk_rate >> 1; ++ ++ if (freq > max_freq) { ++ i2c->freq = max_freq; ++ freq = i2c->freq; ++ } ++ ++ if (!freq) { ++ pr_err("hibvt_i2c_set_freq:freq can't be zero!"); ++ return; ++ } ++ ++ /* set SCLH and SCLL depend on clk_rate and freq */ ++ if (freq <= 100000) { ++ /* in normal mode F_scl: freq ++ i2c_scl_hcnt = (F_i2c / F_scl) * 0.5 ++ i2c_scl_hcnt = (F_i2c / F_scl) * 0.5 ++ */ ++ val = clk_rate / (freq * 2); ++ writel(val, i2c->base + HIBVT_I2C_SCL_H); ++ writel(val, i2c->base + HIBVT_I2C_SCL_L); ++ } else { ++ /* in fast mode F_scl: freq ++ i2c_scl_hcnt = (F_i2c / F_scl) * 0.36 ++ i2c_scl_hcnt = (F_i2c / F_scl) * 0.64 ++ */ ++ val = ((clk_rate / 100) * 36) / freq; ++ writel(val, i2c->base + HIBVT_I2C_SCL_H); ++ val = ((clk_rate / 100) * 64) / freq; ++ writel(val, i2c->base + HIBVT_I2C_SCL_L); ++ } ++ ++ val = readl(i2c->base + HIBVT_I2C_GLB); ++ val &= ~GLB_SDA_HOLD_MASK; ++ val |= ((0xa << GLB_SDA_HOLD_SHIFT) & GLB_SDA_HOLD_MASK); ++ writel(val, i2c->base + HIBVT_I2C_GLB); ++} ++ ++/* ++ * set i2c controller TX and RX FIFO water ++ */ ++static inline void hibvt_i2c_set_water(struct hibvt_i2c_dev *i2c) ++{ ++ writel(I2C_TXF_WATER, i2c->base + HIBVT_I2C_TX_WATER); ++ writel(I2C_RXF_WATER, i2c->base + HIBVT_I2C_RX_WATER); ++} ++ ++/* ++ * initialise the controller, set i2c bus interface freq ++ */ ++static void hibvt_i2c_hw_init(struct hibvt_i2c_dev *i2c) ++{ ++ hibvt_i2c_disable(i2c); ++ hibvt_i2c_disable_irq(i2c, INTR_ALL_MASK); ++ hibvt_i2c_set_freq(i2c); ++ hibvt_i2c_set_water(i2c); ++} ++ ++/* ++ * hibvt_i2c_cfg_cmd - config i2c controller command sequence ++ * ++ * After all the timing command is configured, ++ * and then start the command, you can i2c communication, ++ * and then only need to read and write i2c fifo. ++ */ ++static void hibvt_i2c_cfg_cmd(struct hibvt_i2c_dev *i2c) ++{ ++ struct i2c_msg *msg = i2c->msg; ++ int offset = 0; ++ ++ if (i2c->msg_idx == 0) ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_S, &offset); ++ else ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_RS, &offset); ++ ++ if (msg->flags & I2C_M_TEN) { ++ if (i2c->msg_idx == 0) { ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_D1_2, &offset); ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_D1_1, &offset); ++ } else { ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_D1_2, &offset); ++ } ++ } else { ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_D1_1, &offset); ++ } ++ ++ if (msg->flags & I2C_M_IGNORE_NAK) ++ hibvt_i2c_cmdreg_set(i2c, CMD_IGN_ACK, &offset); ++ else ++ hibvt_i2c_cmdreg_set(i2c, CMD_RX_ACK, &offset); ++ ++ if (msg->flags & I2C_M_RD) { ++ if (msg->len >= 2) { ++ writel(offset, i2c->base + HIBVT_I2C_DST1); ++ writel(msg->len - 2, i2c->base + HIBVT_I2C_LOOP1); ++ hibvt_i2c_cmdreg_set(i2c, CMD_RX_FIFO, &offset); ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_ACK, &offset); ++ hibvt_i2c_cmdreg_set(i2c, CMD_JMP1, &offset); ++ } ++ hibvt_i2c_cmdreg_set(i2c, CMD_RX_FIFO, &offset); ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_NACK, &offset); ++ } else { ++ writel(offset, i2c->base + HIBVT_I2C_DST1); ++ writel(msg->len - 1, i2c->base + HIBVT_I2C_LOOP1); ++ hibvt_i2c_cmdreg_set(i2c, CMD_UP_TXF, &offset); ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_FIFO, &offset); ++ ++ if (msg->flags & I2C_M_IGNORE_NAK) ++ hibvt_i2c_cmdreg_set(i2c, CMD_IGN_ACK, &offset); ++ else ++ hibvt_i2c_cmdreg_set(i2c, CMD_RX_ACK, &offset); ++ ++ hibvt_i2c_cmdreg_set(i2c, CMD_JMP1, &offset); ++ } ++ ++ if ((i2c->msg_idx == (i2c->msg_num - 1)) || (msg->flags & I2C_M_STOP)) { ++ dev_dbg(i2c->dev, "run to %s %d...TX STOP\n", ++ __func__, __LINE__); ++ hibvt_i2c_cmdreg_set(i2c, CMD_TX_P, &offset); ++ } ++ ++ hibvt_i2c_cmdreg_set(i2c, CMD_EXIT, &offset); ++} ++ ++static int hibvt_i2c_polling_xfer_one_msg(struct hibvt_i2c_dev *i2c) ++{ ++ int status; ++ unsigned int val; ++ struct i2c_msg *msg = i2c->msg; ++ ++ dev_dbg(i2c->dev, "[%s,%d]msg->flags=0x%x, len=0x%x\n", ++ __func__, __LINE__, msg->flags, msg->len); ++ ++ hibvt_i2c_enable(i2c); ++ hibvt_i2c_clr_irq(i2c); ++ hibvt_i2c_set_addr(i2c); ++ hibvt_i2c_cfg_cmd(i2c); ++ hibvt_i2c_start_cmd(i2c); ++ ++ i2c->msg_buf_ptr = 0; ++ ++ if (msg->flags & I2C_M_RD) { ++ while (i2c->msg_buf_ptr < msg->len) { ++ status = hibvt_i2c_wait_rx_noempty(i2c); ++ if (status) ++ goto end; ++ ++ val = readl(i2c->base + HIBVT_I2C_RXF); ++ msg->buf[i2c->msg_buf_ptr] = val; ++ i2c->msg_buf_ptr++; ++ ++ } ++ } else { ++ while (i2c->msg_buf_ptr < msg->len) { ++ status = hibvt_i2c_wait_tx_nofull(i2c); ++ if (status) ++ goto end; ++ ++ val = msg->buf[i2c->msg_buf_ptr]; ++ writel(val, i2c->base + HIBVT_I2C_TXF); ++ i2c->msg_buf_ptr++; ++ } ++ } ++ ++ status = hibvt_i2c_wait_idle(i2c); ++end: ++ hibvt_i2c_disable(i2c); ++ ++ return status; ++} ++ ++static irqreturn_t hibvt_i2c_isr(int irq, void *dev_id) ++{ ++ struct hibvt_i2c_dev *i2c = dev_id; ++ unsigned int irq_status; ++ struct i2c_msg *msg = i2c->msg; ++ ++ spin_lock(&i2c->lock); ++ ++ irq_status = hibvt_i2c_clr_irq(i2c); ++ dev_dbg(i2c->dev, "%s RIS: 0x%x\n", __func__, irq_status); ++ ++ if (!irq_status) { ++ dev_dbg(i2c->dev, "no irq\n"); ++ goto end; ++ } ++ ++ if (irq_status & INTR_ABORT_MASK) { ++ dev_err(i2c->dev, "irq handle abort, RIS: 0x%x\n", ++ irq_status); ++ i2c->status = -EIO; ++ hibvt_i2c_disable_irq(i2c, INTR_ALL_MASK); ++ ++ complete(&i2c->msg_complete); ++ goto end; ++ } ++ ++ if (msg->flags & I2C_M_RD) { ++ while ((readl(i2c->base + HIBVT_I2C_STAT) & STAT_RXF_NOE_MASK) ++ && (i2c->msg_buf_ptr < msg->len)) { ++ msg->buf[i2c->msg_buf_ptr] = ++ readl(i2c->base + HIBVT_I2C_RXF); ++ i2c->msg_buf_ptr++; ++ } ++ } else { ++ while ((readl(i2c->base + HIBVT_I2C_STAT) & STAT_TXF_NOF_MASK) ++ && (i2c->msg_buf_ptr < msg->len)) { ++ writel(msg->buf[i2c->msg_buf_ptr], ++ i2c->base + HIBVT_I2C_TXF); ++ i2c->msg_buf_ptr++; ++ } ++ } ++ ++ if (i2c->msg_buf_ptr >= msg->len) ++ hibvt_i2c_disable_irq(i2c, INTR_TX_MASK | INTR_RX_MASK); ++ ++ if (irq_status & INTR_CMD_DONE_MASK) { ++ dev_dbg(i2c->dev, "cmd done\n"); ++ i2c->status = 0; ++ hibvt_i2c_disable_irq(i2c, INTR_ALL_MASK); ++ ++ complete(&i2c->msg_complete); ++ } ++ ++end: ++ spin_unlock(&i2c->lock); ++ ++ return IRQ_HANDLED; ++} ++ ++static int hibvt_i2c_interrupt_xfer_one_msg(struct hibvt_i2c_dev *i2c) ++{ ++ int status; ++ struct i2c_msg *msg = i2c->msg; ++ unsigned long timeout; ++ unsigned long flags; ++ ++ dev_dbg(i2c->dev, "[%s,%d]msg->flags=0x%x, len=0x%x\n", ++ __func__, __LINE__, msg->flags, msg->len); ++ ++ reinit_completion(&i2c->msg_complete); ++ i2c->msg_buf_ptr = 0; ++ i2c->status = -EIO; ++ ++ spin_lock_irqsave(&i2c->lock, flags); ++ hibvt_i2c_enable(i2c); ++ hibvt_i2c_clr_irq(i2c); ++ if (msg->flags & I2C_M_RD) ++ hibvt_i2c_cfg_irq(i2c, INTR_USE_MASK & ~INTR_TX_MASK); ++ else ++ hibvt_i2c_cfg_irq(i2c, INTR_USE_MASK & ~INTR_RX_MASK); ++ ++ hibvt_i2c_set_addr(i2c); ++ hibvt_i2c_cfg_cmd(i2c); ++ hibvt_i2c_start_cmd(i2c); ++ spin_unlock_irqrestore(&i2c->lock, flags); ++ ++ timeout = wait_for_completion_timeout(&i2c->msg_complete, ++ I2C_IRQ_TIMEOUT); ++ ++ if (timeout == 0) { ++ hibvt_i2c_disable_irq(i2c, INTR_ALL_MASK); ++ status = -EIO; ++ dev_err(i2c->dev, "%s timeout\n", ++ msg->flags & I2C_M_RD ? "rx" : "tx"); ++ } else { ++ status = i2c->status; ++ } ++ ++ hibvt_i2c_disable(i2c); ++ ++ return status; ++} ++ ++/* ++ * Master transfer function ++ */ ++static int hibvt_i2c_xfer(struct i2c_adapter *adap, ++ struct i2c_msg *msgs, int num) ++{ ++ struct hibvt_i2c_dev *i2c = i2c_get_adapdata(adap); ++ int status = -EINVAL; ++ unsigned long flags; ++ ++ if (!msgs || (num <= 0)) { ++ dev_err(i2c->dev, "msgs == NULL || num <= 0, Invalid argument!\n"); ++ return -EINVAL; ++ } ++ ++ spin_lock_irqsave(&i2c->lock, flags); ++ ++ i2c->msg = msgs; ++ i2c->msg_num = num; ++ i2c->msg_idx = 0; ++ ++ /* FIXME: The wait_for_completion_timeout in hibvt_i2c_interrupt_xfer_one_msg ++ * function can not be locked by spin_lock_irqsave. And actually I2C interrupt ++ * tranfer is rarely used, so we ignore the irq setting to limit the interrupt ++ * way. But we keep these codes below, reserve for future modifications */ ++ i2c->irq = -1; ++ ++ if (i2c->irq >= 0) { ++ while (i2c->msg_idx < i2c->msg_num) { ++ status = hibvt_i2c_interrupt_xfer_one_msg(i2c); ++ if (status) ++ break; ++ ++ i2c->msg++; ++ i2c->msg_idx++; ++ } ++ } else { ++ while (i2c->msg_idx < i2c->msg_num) { ++ status = hibvt_i2c_polling_xfer_one_msg(i2c); ++ if (status) ++ break; ++ ++ i2c->msg++; ++ i2c->msg_idx++; ++ } ++ } ++ ++ if (!status || i2c->msg_idx > 0) ++ status = i2c->msg_idx; ++ ++ spin_unlock_irqrestore(&i2c->lock, flags); ++ ++ return status; ++} ++ ++/* HI I2C READ * ++ * hi_i2c_master_recv - issue a single I2C message in master receive mode ++ * @client: Handle to slave device ++ * @buf: Where to store data read from slave ++ * @count: How many bytes to read, must be less than 64k since msg.len is u16 ++ * ++ * Returns negative errno, or else the number of bytes read. ++ */ ++int hi_i2c_master_recv(const struct i2c_client *client, char *buf, ++ int count) ++{ ++ printk("Wrong interface call." ++ "hi_i2c_transfer is the only interface to i2c read!!!\n"); ++ ++ return -EIO; ++} ++EXPORT_SYMBOL(hi_i2c_master_recv); ++ ++/*HI I2C WRITE* ++ * hi_i2c_master_send - issue a single I2C message in master transmit mode ++ * @client: Handle to slave device ++ * @buf: Data that will be written to the slave ++ * @count: How many bytes to write, must be less than 64k since msg.len is u16 ++ * ++ * Returns negative errno, or else the number of bytes written. ++ */ ++int hi_i2c_master_send(const struct i2c_client *client, ++ const char *buf, int count) ++{ ++ struct i2c_adapter *adap = client->adapter; ++ struct i2c_msg msg; ++ int msgs_count; ++ ++ if ((client->addr > 0x3ff) ++ || (((client->flags & I2C_M_TEN) == 0) && (client->addr > 0x7f))) { ++ printk(KERN_ERR "dev address out of range\n"); ++ return -EINVAL; ++ } ++ ++ msg.addr = client->addr; ++ msg.flags = client->flags; ++ msg.len = count; ++ ++ if (!buf) { ++ printk(KERN_ERR "Invalid buf == NULL!!!\n"); ++ return -EINVAL; ++ } ++ msg.buf = (__u8 *)buf; ++ ++ msgs_count = hibvt_i2c_xfer(adap, &msg, 1); ++ ++ return (msgs_count == 1) ? count : -EIO; ++} ++EXPORT_SYMBOL(hi_i2c_master_send); ++ ++/** ++ * hi_i2c_transfer - execute a single or combined I2C message ++ * @adap: Handle to I2C bus ++ * @msgs: One or more messages to execute before STOP is issued to ++ * terminate the operation; each message begins with a START. ++ * @num: Number of messages to be executed. ++ * ++ * Returns negative errno, else the number of messages executed. ++ * ++ * Note that there is no requirement that each message be sent to ++ * the same slave address, although that is the most common model. ++ */ ++int hi_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ++ int num) ++{ ++ int msgs_count; ++ ++ if ((msgs[0].addr > 0x3ff) ++ || (((msgs[0].flags & I2C_M_TEN) == 0) && (msgs[0].addr > 0x7f))) { ++ printk(KERN_ERR "msgs[0] dev address out of range\n"); ++ return -EINVAL; ++ } ++ ++ if ((msgs[1].addr > 0x3ff) ++ || (((msgs[1].flags & I2C_M_TEN) == 0) && (msgs[1].addr > 0x7f))) { ++ printk(KERN_ERR "msgs[1] dev address out of range\n"); ++ return -EINVAL; ++ } ++ ++ msgs_count = hibvt_i2c_xfer(adap, msgs, num); ++ ++ return msgs_count; ++} ++EXPORT_SYMBOL(hi_i2c_transfer); ++ ++static u32 hibvt_i2c_func(struct i2c_adapter *adap) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR ++ | I2C_FUNC_PROTOCOL_MANGLING; ++} ++ ++static const struct i2c_algorithm hibvt_i2c_algo = { ++ .master_xfer = hibvt_i2c_xfer, ++ .functionality = hibvt_i2c_func, ++}; ++ ++static int hibvt_i2c_probe(struct platform_device *pdev) ++{ ++ int status; ++ struct hibvt_i2c_dev *i2c; ++ struct i2c_adapter *adap; ++ struct resource *res; ++ ++ i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); ++ if (!i2c) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, i2c); ++ i2c->dev = &pdev->dev; ++ spin_lock_init(&i2c->lock); ++ init_completion(&i2c->msg_complete); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ i2c->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(i2c->base)) { ++ dev_err(i2c->dev, "cannot ioremap resource\n"); ++ return -ENOMEM; ++ } ++ ++ i2c->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(i2c->clk)) { ++ dev_err(i2c->dev, "cannot get clock\n"); ++ return -ENOENT; ++ } ++ clk_prepare_enable(i2c->clk); ++ ++ if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", ++ &i2c->freq)) { ++ dev_warn(i2c->dev, "setting default clock-frequency@%dHz\n", ++ I2C_DEFAULT_FREQUENCY); ++ i2c->freq = I2C_DEFAULT_FREQUENCY; ++ } ++ ++ /* i2c controller initialization, disable interrupt */ ++ hibvt_i2c_hw_init(i2c); ++ ++ i2c->irq = platform_get_irq(pdev, 0); ++ status = devm_request_irq(&pdev->dev, i2c->irq, hibvt_i2c_isr, ++ IRQF_SHARED, dev_name(&pdev->dev), i2c); ++ if (status) { ++ dev_dbg(i2c->dev, "falling back to polling mode"); ++ i2c->irq = -1; ++ } ++ ++ adap = &i2c->adap; ++ i2c_set_adapdata(adap, i2c); ++ adap->owner = THIS_MODULE; ++ strlcpy(adap->name, "hibvt-i2c", sizeof(adap->name)); ++ adap->dev.parent = &pdev->dev; ++ adap->dev.of_node = pdev->dev.of_node; ++ adap->algo = &hibvt_i2c_algo; ++ ++ /* Add the i2c adapter */ ++ status = i2c_add_adapter(adap); ++ if (status) { ++ dev_err(i2c->dev, "failed to add bus to i2c core\n"); ++ goto err_add_adapter; ++ } ++ ++ dev_info(i2c->dev, "%s%d@%dhz registered\n", ++ adap->name, adap->nr, i2c->freq); ++ ++ return 0; ++ ++err_add_adapter: ++ clk_disable_unprepare(i2c->clk); ++ return status; ++} ++ ++static int hibvt_i2c_remove(struct platform_device *pdev) ++{ ++ struct hibvt_i2c_dev *i2c = platform_get_drvdata(pdev); ++ ++ clk_disable_unprepare(i2c->clk); ++ i2c_del_adapter(&i2c->adap); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int hibvt_i2c_suspend(struct device *dev) ++{ ++ struct hibvt_i2c_dev *i2c = dev_get_drvdata(dev); ++ ++ i2c_lock_adapter(&i2c->adap); ++ clk_disable_unprepare(i2c->clk); ++ i2c_unlock_adapter(&i2c->adap); ++ ++ return 0; ++} ++ ++static int hibvt_i2c_resume(struct device *dev) ++{ ++ struct hibvt_i2c_dev *i2c = dev_get_drvdata(dev); ++ ++ i2c_lock_adapter(&i2c->adap); ++ clk_prepare_enable(i2c->clk); ++ hibvt_i2c_hw_init(i2c); ++ i2c_unlock_adapter(&i2c->adap); ++ ++ return 0; ++} ++#endif ++ ++static SIMPLE_DEV_PM_OPS(hibvt_i2c_dev_pm, hibvt_i2c_suspend, ++ hibvt_i2c_resume); ++ ++static const struct of_device_id hibvt_i2c_match[] = { ++ { .compatible = "hisilicon,hibvt-i2c"}, ++ { .compatible = "hisilicon,hi3516cv300-i2c"}, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, hibvt_i2c_match); ++ ++static struct platform_driver hibvt_i2c_driver = { ++ .driver = { ++ .name = "hibvt-i2c", ++ .of_match_table = hibvt_i2c_match, ++ .pm = &hibvt_i2c_dev_pm, ++ }, ++ .probe = hibvt_i2c_probe, ++ .remove = hibvt_i2c_remove, ++}; ++ ++module_platform_driver(hibvt_i2c_driver); ++ ++MODULE_AUTHOR("Pan Wen, "); ++MODULE_DESCRIPTION("HISILICON BVT I2C Bus driver"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/i2c/busses/i2c-hisi-v110.c b/drivers/i2c/busses/i2c-hisi-v110.c +new file mode 100644 +index 0000000..9e0e4ba +--- /dev/null ++++ b/drivers/i2c/busses/i2c-hisi-v110.c +@@ -0,0 +1,1263 @@ ++/* ++ * Hisilicon BVT I2C Controller Driver ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_HI_DMAC ++#include ++#include ++#endif ++ ++/* ++ * I2C Registers offsets ++ */ ++#define HII2C_CR 0x00 ++#define HII2C_TAR 0x04 ++#define I2C_DATA_CMD_REG 0x010 ++#define HII2C_SCL_H 0x1C ++#define HII2C_SCL_L 0x20 ++#define HII2C_IM 0x30 ++#define HII2C_RI 0x34 ++#define HII2C_IC 0x40 ++#define HII2C_EN 0x6C ++#define HII2C_SR 0x70 ++#define HII2C_SDA_HOLD 0x7C ++#define HII2C_TX_ABRT 0x80 ++#define I2C_DMA_CTRL_REG 0x088 ++#define I2C_DMA_TDLR 0x08C ++#define I2C_DMA_RDLR 0x090 ++#define HII2C_LOCK 0xAC ++#define HII2C_CR1 0xB0 ++#define HII2C_DATA 0xB4 ++#define HII2C_SEQU_CMD0 0xB8 ++#define I2C_DMA_CMD0 0x0B8 ++#define I2C_DMA_CMD1 0x0BC ++#define I2C_DMA_CMD2 0x0C0 ++ ++/* ++ * I2C Control Register -- HII2C_CR ++ */ ++#define CR_RESTART_EN (0x1 << 5) ++ ++/* ++ * I2C Slave Address Register -- HII2C_TAR ++ */ ++#define TAR_10BIT_MODE (0x1 << 12) ++#define TAR_SPECIAL (0x1 << 11) ++#define TAR_ADDR (0x3ff << 0) ++#define TAR_ADDR_SHIFT 0 ++ ++/* ++ * I2C Interrupt status and mask Register -- HII2C_IM ++ */ ++#define INT_TX_ABRT (1 << 6) ++#define MASK_ALL_INT 0xffffffff ++ ++/* ++ * I2C Status Register -- HII2C_SR ++ */ ++#define SR_BUSY (0x1 << 0) ++ ++ ++/* ++ * I2C Lock Register -- HII2C_LOCK ++ */ ++#define UNLOCK_VALUE 0x1ACCE551 ++ ++/* ++ * I2C Single Control Register -- HII2C_CR1 ++ */ ++#define CR1_SINGLE_MODE_EN (0x1 << 31) ++#define CR1_READ_MODE (0x1 << 30) ++#define CR1_H_WIDE (0x1 << 29) ++#define CR1_L_WIDE (0x1 << 28) ++#define CR1_STATUS_CLR (0xf << 24) ++#define CR1_TX_ABRT (0x1 << 23) ++#define CR1_TFNF (0x1 << 21) ++#define CR1_TFE (0x1 << 20) ++#define CR1_RFF (0x1 << 9) ++#define CR1_RFNE (0x1 << 8) ++ ++/* ++ * I2C Single CMD Register -- HII2C_DATA ++ */ ++#define DATA_H (0xffff << 16) ++#define DATA_L 0xffff ++#define DATA_H_SHIFT 16 ++#define DATA_L_SHIFT 0 ++ ++/* ++ * I2C Sequence CMD0 Register -- HII2C_SEQU_CMD0 ++ */ ++#define SEQU_MODE_EN (0x1 << 31) ++#define SEQU_MODE_WRITE (0x1 << 30) ++#define SEQU_ADDR_8BIT (0x0 << 28) ++#define SEQU_ADDR_16BIT (0x1 << 28) ++ ++#define HII2C_TIMEOUT 0x400 ++ ++unsigned int clk_rate = 0; ++ ++typedef enum i2c_mode { ++ I2C_MODE_SINGLE, ++ I2C_MODE_DMA, ++} i2c_mode_t; ++ ++struct hi_i2c { ++ struct platform_device *pdev; ++ struct i2c_adapter *adap; ++ struct device *dev; ++ resource_size_t phybase; ++ void __iomem *virtbase; ++ struct clk *clk; ++ ++ struct i2c_msg *msg; ++ ++ unsigned int frequency; ++ ++ __u16 last_slave_addr; ++ i2c_mode_t last_mode; ++ spinlock_t lock; ++}; ++ ++static inline void hi_i2c_disable(struct hi_i2c *i2c) ++{ ++ writel(0x0, i2c->virtbase + HII2C_EN); ++} ++ ++static inline void hi_i2c_enable(struct hi_i2c *i2c) ++{ ++ writel(0x1, i2c->virtbase + HII2C_EN); ++} ++ ++static inline void hi_i2c_disable_irq(struct hi_i2c *i2c, unsigned int flag) ++{ ++ unsigned int val; ++ ++ val = readl(i2c->virtbase + HII2C_IM); ++ val |= flag; ++ writel(val, i2c->virtbase + HII2C_IM); ++} ++ ++static inline void hi_i2c_set_slave_addr(struct hi_i2c *i2c, __u16 addr, ++ unsigned char ten_bit_flag) ++{ ++ unsigned int val; ++ ++ hi_i2c_disable(i2c); ++ ++ val = readl(i2c->virtbase + HII2C_TAR); ++ val &= ~TAR_ADDR; ++ val |= (addr << TAR_ADDR_SHIFT) & TAR_ADDR; ++ ++ if (ten_bit_flag) ++ val |= TAR_10BIT_MODE; ++ else ++ val &= ~TAR_10BIT_MODE; ++ ++ writel(val, i2c->virtbase + HII2C_TAR); ++ ++ i2c->last_slave_addr = addr; ++ ++ hi_i2c_enable(i2c); ++} ++ ++static inline void hi_i2c_set_mode(struct hi_i2c *i2c, i2c_mode_t mode) ++{ ++ unsigned int val; ++ ++ hi_i2c_disable(i2c); ++ ++ if (mode == I2C_MODE_SINGLE) { ++ val = readl(i2c->virtbase + HII2C_SEQU_CMD0); ++ val &= ~SEQU_MODE_EN; ++ writel(val, i2c->virtbase + HII2C_SEQU_CMD0); ++ ++ val = readl(i2c->virtbase + HII2C_CR1); ++ val |= CR1_SINGLE_MODE_EN; ++ writel(val, i2c->virtbase + HII2C_CR1); ++ } else { ++ val = readl(i2c->virtbase + HII2C_CR1); ++ val &= ~CR1_SINGLE_MODE_EN; ++ writel(val, i2c->virtbase + HII2C_CR1); ++ } ++ ++ i2c->last_mode = mode; ++ ++ hi_i2c_enable(i2c); ++} ++ ++static inline int hi_i2c_clr_status(struct hi_i2c *i2c) ++{ ++ unsigned int val; ++ ++ val = readl(i2c->virtbase + HII2C_CR1); ++ val |= CR1_STATUS_CLR; ++ writel(val & (~CR1_SINGLE_MODE_EN), i2c->virtbase + HII2C_CR1); ++ writel(val, i2c->virtbase + HII2C_CR1); ++ ++ writel(0x1, i2c->virtbase + HII2C_IC); ++ ++ hi_i2c_disable(i2c); ++ ++ hi_i2c_enable(i2c); ++ ++ return 0; ++} ++ ++static u32 hi_i2c_get_delay_val(struct hi_i2c *i2c) ++{ ++ unsigned int scl_l; ++ u32 val; ++ ++ scl_l = readl(i2c->virtbase + HII2C_SCL_L); ++ ++ /* delay_val = scl_l * 2.5 * 1000 * 1000 / clk_rate */ ++ val = (25 * 100000 / clk_rate) + 1;// +1 is to make the time plenty more ++ val = val * scl_l; ++ ++ return val; ++} ++ ++static int hi_i2c_wait_idle(struct hi_i2c *i2c) ++{ ++ unsigned int time_cnt; ++ unsigned int val; ++ struct device *dev = i2c->dev; ++ ++ time_cnt = 0; ++ do { ++ val = readl(i2c->virtbase + HII2C_RI); ++ if (val & INT_TX_ABRT) { ++ dev_err(dev, "%s: wait last fifo is empyt abort!", ++ __func__); ++ dev_err(dev, "RI: %#x\n", val); ++ val = readl(i2c->virtbase + HII2C_TX_ABRT); ++ dev_err(i2c->dev, "TX_ABRT:0x%x\n", val); ++ return -EIO; ++ } ++ ++ val = readl(i2c->virtbase + HII2C_CR1); ++ if (val & CR1_RFNE) ++ readl(i2c->virtbase + HII2C_DATA); ++ ++ if (val & CR1_TFE & (~CR1_RFNE)) ++ break; ++ ++ if (time_cnt >= HII2C_TIMEOUT) { ++ dev_err(dev, "%s: wit last fifo is empty timeout!", ++ __func__); ++ dev_err(dev, "CR1:0x%x\n", val); ++ return -EBUSY; ++ } ++ time_cnt++; ++ udelay(50); ++ } while (1); ++ ++ udelay(10); ++ ++ time_cnt = 0; ++ do { ++ val = readl(i2c->virtbase + HII2C_RI); ++ if (val & INT_TX_ABRT) { ++ dev_err(dev, "%s: wait last i2c is idle abort!", ++ __func__); ++ dev_err(dev, "RI: %#x\n", val); ++ val = readl(i2c->virtbase + HII2C_TX_ABRT); ++ dev_err(i2c->dev, "TX_ABRT:0x%x\n", val); ++ return -EIO; ++ } ++ ++ val = readl(i2c->virtbase + HII2C_SR); ++ if (!(val & SR_BUSY)) ++ break; ++ ++ if (time_cnt >= HII2C_TIMEOUT) { ++ dev_err(dev, "%s: wait last i2c is idle timeout!", ++ __func__); ++ dev_err(dev, "CR1:0x%x\n", val); ++ return -EBUSY; ++ } ++ time_cnt++; ++ udelay(50); ++ } while (1); ++ ++ return 0; ++} ++ ++static int hi_i2c_wait_tx_nofull(struct hi_i2c *i2c) ++{ ++ unsigned int val; ++ unsigned int time_cnt; ++ struct device *dev = i2c->dev; ++ ++ time_cnt = 0; ++ do { ++ val = readl(i2c->virtbase + HII2C_RI); ++ if (val & INT_TX_ABRT) { ++ dev_err(dev, "wait tx no full abort, last RI: %#x\n", ++ val); ++ val = readl(i2c->virtbase + HII2C_TX_ABRT); ++ dev_err(i2c->dev, "TX_ABRT:0x%x\n", val); ++ return -EIO; ++ } ++ ++ val = readl(i2c->virtbase + HII2C_CR1); ++ if (val & CR1_RFNE) ++ readl(i2c->virtbase + HII2C_DATA); ++ ++ if (val & CR1_TFNF) ++ break; ++ ++ if (time_cnt >= HII2C_TIMEOUT) { ++ dev_err(dev, "wait tx no full timeout, last CR1: %#x\n", ++ val); ++ return -EBUSY; ++ } ++ time_cnt++; ++ udelay(50); ++ } while (1); ++ ++ return 0; ++} ++ ++static int hi_i2c_wait_rx_noempty(struct hi_i2c *i2c) ++{ ++ unsigned int val; ++ unsigned int time_cnt; ++ struct device *dev = i2c->dev; ++ ++ time_cnt = 0; ++ do { ++ val = readl(i2c->virtbase + HII2C_RI); ++ if (val & INT_TX_ABRT) { ++ dev_err(dev, "wait rx no empty abort, RI: %#x\n", val); ++ val = readl(i2c->virtbase + HII2C_TX_ABRT); ++ dev_err(i2c->dev, "TX_ABRT:0x%x\n", val); ++ return -EIO; ++ } ++ ++ val = readl(i2c->virtbase + HII2C_CR1); ++ if (val & CR1_RFNE) ++ break; ++ ++ if (time_cnt >= HII2C_TIMEOUT) { ++ dev_err(dev, "\nwait rx no empty timeout, CR1: %#x\n", ++ val); ++ return -EBUSY; ++ } ++ time_cnt++; ++ udelay(50); ++ } while (1); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_HI_DMAC ++#define REVERT_HL_BYTE(value) ((value >> 8) | ((value & 0xFF) << 8)) ++ ++void hi_i2c_dma_start(struct hi_i2c *i2c, unsigned int dir) ++{ ++ writel((1 << dir), i2c->virtbase + I2C_DMA_CTRL_REG); ++} ++ ++void hi_i2c_dmac_config(struct hi_i2c *i2c, unsigned int dir) ++{ ++ /* 1. enable RX(0) or TX(1) in DMA mode */ ++ hi_i2c_dma_start(i2c, dir); ++ ++ /* 2. set dma fifo */ ++ writel(4, i2c->virtbase + I2C_DMA_TDLR); ++ writel(4, i2c->virtbase + I2C_DMA_RDLR); ++} ++ ++void hi_i2c_start_rx(struct hi_i2c *i2c, unsigned int reg_addr, ++ unsigned int length) ++{ ++ unsigned int reg; ++ ++ writel(reg_addr, i2c->virtbase + I2C_DMA_CMD1); ++ writel(length, i2c->virtbase + I2C_DMA_CMD2); ++ ++ reg = readl(i2c->virtbase + I2C_DMA_CMD0); ++ ++ /*start dma rx*/ ++ reg |= SEQU_MODE_EN; ++ reg &= ~SEQU_MODE_WRITE; ++ writel(reg, i2c->virtbase + I2C_DMA_CMD0); ++} ++ ++void hi_i2c_start_tx(struct hi_i2c *i2c, unsigned int reg_addr, ++ unsigned int length) ++{ ++ unsigned int reg; ++ ++ writel(reg_addr, i2c->virtbase + I2C_DMA_CMD1); ++ writel(length, i2c->virtbase + I2C_DMA_CMD2); ++ ++ reg = readl(i2c->virtbase + I2C_DMA_CMD0); ++ ++ /*start dma tx*/ ++ reg |= SEQU_MODE_EN; ++ reg |= SEQU_MODE_WRITE; ++ writel(reg, i2c->virtbase + I2C_DMA_CMD0); ++} ++ ++int dma_to_i2c(unsigned int src, unsigned int dst, unsigned int length) ++{ ++ int chan; ++ ++ chan = do_dma_m2p(src, dst, length); ++ if (chan == -1) ++ pr_err("dma_to_i2c error\n"); ++ ++ return chan; ++} ++ ++ ++int i2c_to_dma(unsigned int src, unsigned int dst, unsigned int length) ++{ ++ int chan; ++ ++ chan = do_dma_p2m(dst, src, length); ++ if (chan == -1) ++ pr_err("dma_p2m error...\n"); ++ ++ return chan; ++} ++ ++static int hi_i2c_do_dma_write(struct hi_i2c *i2c, ++ unsigned int reg_addr, unsigned int reg_addr_num, ++ unsigned int dma_buf, unsigned int len) ++{ ++ int chan; ++ struct i2c_msg *msg = i2c->msg; ++ unsigned int temp_reg = reg_addr; ++ ++ if ((msg->addr != i2c->last_slave_addr) ++ || (i2c->last_mode != I2C_MODE_DMA)) { ++ hi_i2c_set_slave_addr(i2c, msg->addr, msg->flags & I2C_M_TEN); ++ hi_i2c_set_mode(i2c, I2C_MODE_DMA); ++ } ++ ++ if (2 == reg_addr_num) { ++ /* switch high byte and low byte */ ++ temp_reg = REVERT_HL_BYTE(reg_addr); ++ writel(SEQU_ADDR_16BIT, i2c->virtbase + I2C_DMA_CMD0); ++ } else { ++ writel(SEQU_ADDR_8BIT, i2c->virtbase + I2C_DMA_CMD0); ++ } ++ ++ /* 2. config i2c into DMA mode */ ++ hi_i2c_dmac_config(i2c, 0x1); ++ ++ /* 3. start i2c logic to write */ ++ hi_i2c_start_tx(i2c, temp_reg, len - 1); ++ ++ /* 4. transmit DATA from DMAC to I2C in DMA mode */ ++ chan = dma_to_i2c(dma_buf, (i2c->phybase + I2C_DATA_CMD_REG), ++ len); ++ if (chan == -1) { ++ return -1; ++ } ++ ++ if (dmac_wait(chan) != DMAC_CHN_SUCCESS) { ++ dev_err(i2c->dev, "dma wait failed\n"); ++ hi_i2c_clr_status(i2c); ++ dmac_channel_free(chan); ++ return -1; ++ } ++ ++ hi_i2c_wait_idle(i2c); ++ hi_i2c_clr_status(i2c); ++ ++ dmac_channel_free(chan); ++ ++ return 0; ++} ++ ++static int hi_i2c_do_dma_read(struct hi_i2c *i2c, ++ unsigned int reg_addr, unsigned int reg_addr_num, ++ unsigned int dma_buf, unsigned int len) ++{ ++ int chan; ++ struct i2c_msg *msg = i2c->msg; ++ unsigned int temp_reg = reg_addr; ++ ++ if ((msg->addr != i2c->last_slave_addr) ++ || (I2C_MODE_DMA != i2c->last_mode)) { ++ hi_i2c_set_slave_addr(i2c, msg->addr, msg->flags & I2C_M_TEN); ++ hi_i2c_set_mode(i2c, I2C_MODE_DMA); ++ } ++ ++ if (2 == reg_addr_num) { ++ /* switch high byte and low byte */ ++ temp_reg = REVERT_HL_BYTE(reg_addr); ++ writel(SEQU_ADDR_16BIT, i2c->virtbase + I2C_DMA_CMD0); ++ } else { ++ writel(SEQU_ADDR_8BIT, i2c->virtbase + I2C_DMA_CMD0); ++ } ++ ++ /* 2. config i2c into DMA mode */ ++ hi_i2c_dmac_config(i2c, 0x0); ++ ++ /* 3. transmit DATA from I2C to DMAC in DMA mode */ ++ chan = i2c_to_dma((i2c->phybase + I2C_DATA_CMD_REG), ++ dma_buf, len); ++ if (chan == -1) { ++ return -1; ++ } ++ ++ /* 4. start i2c logic to read */ ++ hi_i2c_start_rx(i2c, temp_reg, len - 1); ++ ++ if (dmac_wait(chan) != DMAC_CHN_SUCCESS) { ++ dev_err(i2c->dev, "dma wait failed\n"); ++ hi_i2c_clr_status(i2c); ++ dmac_channel_free(chan); ++ return -1; ++ } ++ ++ hi_i2c_wait_idle(i2c); ++ hi_i2c_clr_status(i2c); ++ ++ dmac_channel_free(chan); ++ ++ return 0; ++} ++#else ++static int hi_i2c_do_dma_write(struct hi_i2c *i2c, ++ unsigned int reg_addr, unsigned int reg_addr_num, ++ unsigned int dma_buf, unsigned int len) ++{ ++ dev_err(i2c->dev, "DMA is not enabled!"); ++ return -1; ++} ++ ++static int hi_i2c_do_dma_read(struct hi_i2c *i2c, ++ unsigned int reg_addr, unsigned int reg_addr_num, ++ unsigned int dma_buf, unsigned int len) ++{ ++ dev_err(i2c->dev, "DMA is not enabled!"); ++ return -1; ++} ++#endif ++ ++int hi_i2c_dma_write(const struct i2c_client *client, unsigned int dma_buf, ++ unsigned int reg_addr, unsigned int reg_addr_num, ++ unsigned int len) ++{ ++ struct i2c_adapter *adap = client->adapter; ++ struct hi_i2c *i2c = i2c_get_adapdata(adap); ++ struct i2c_msg msg; ++ int status; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&i2c->lock, flags); ++ ++ memset(&msg, 0x0, sizeof(struct i2c_msg)); ++ msg.addr = client->addr; ++ msg.flags = client->flags; ++ msg.len = len; ++ ++ i2c->msg = &msg; ++ ++ status = hi_i2c_do_dma_write(i2c, reg_addr, reg_addr_num, dma_buf, len); ++ ++ spin_unlock_irqrestore(&i2c->lock, flags); ++ ++ return status; ++} ++EXPORT_SYMBOL(hi_i2c_dma_write); ++ ++int hi_i2c_dma_read(const struct i2c_client *client, unsigned int dma_buf, ++ unsigned int reg_addr, unsigned int reg_addr_num, ++ unsigned int len) ++{ ++ struct i2c_adapter *adap = client->adapter; ++ struct hi_i2c *i2c = i2c_get_adapdata(adap); ++ struct i2c_msg msg; ++ int status; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&i2c->lock, flags); ++ ++ memset(&msg, 0x0, sizeof(struct i2c_msg)); ++ msg.addr = client->addr; ++ msg.flags = client->flags; ++ msg.flags |= I2C_M_RD; ++ msg.len = len; ++ ++ i2c->msg = &msg; ++ ++ status = hi_i2c_do_dma_read(i2c, reg_addr, reg_addr_num, dma_buf, len); ++ ++ spin_unlock_irqrestore(&i2c->lock, flags); ++ ++ return status; ++} ++EXPORT_SYMBOL(hi_i2c_dma_read); ++ ++static void hi_i2c_set_rate(struct hi_i2c *i2c) ++{ ++ unsigned int max_frequency, freq; ++ unsigned int scl_h, scl_l, sda_hold; ++ ++ freq = i2c->frequency; ++ clk_rate = clk_get_rate(i2c->clk); ++ BUG_ON(!clk_rate); ++ ++ max_frequency = clk_rate >> 1; ++ ++ if (freq > max_frequency) { ++ i2c->frequency = max_frequency; ++ freq = i2c->frequency; ++ } ++ ++ if (!freq) { ++ pr_err("freq can not be zero...\n"); ++ return; ++ } ++ ++ /* set SCLH and SCLL depend on clk_rate and freq */ ++ if (freq <= 100000) { ++ /* in normal mode F_scl: freq ++ i2c_scl_hcnt = (F_i2c / F_scl) * 0.5 ++ i2c_scl_hcnt = (F_i2c / F_scl) * 0.5 ++ */ ++ scl_h = clk_rate / (freq * 2); ++ scl_l = scl_h; ++ } else { ++ /* in fast mode F_scl: freq ++ i2c_scl_hcnt = (F_i2c / F_scl) * 0.36 ++ i2c_scl_hcnt = (F_i2c / F_scl) * 0.64 ++ */ ++ scl_h = ((clk_rate / 100) * 36) / freq; ++ scl_l = ((clk_rate / 100) * 64) / freq; ++ } ++ ++ writel(scl_h, i2c->virtbase + HII2C_SCL_H); ++ writel(scl_l, i2c->virtbase + HII2C_SCL_L); ++ ++ sda_hold = scl_h / 2; ++ writel(sda_hold, i2c->virtbase + HII2C_SDA_HOLD); ++} ++ ++static void hi_i2c_hw_init(struct hi_i2c *i2c) ++{ ++ unsigned int val; ++ ++ /* unlock hi_i2c controller to access */ ++ writel(UNLOCK_VALUE, i2c->virtbase + HII2C_LOCK); ++ ++ hi_i2c_disable(i2c); ++ ++ val = readl(i2c->virtbase + HII2C_CR); ++ val |= CR_RESTART_EN; ++ writel(val, i2c->virtbase + HII2C_CR); ++ ++ hi_i2c_set_rate(i2c); ++ ++ hi_i2c_disable_irq(i2c, MASK_ALL_INT); ++ ++ writel(0x0, i2c->virtbase + HII2C_TAR); ++ hi_i2c_set_slave_addr(i2c, 0, 0); ++ hi_i2c_set_mode(i2c, I2C_MODE_SINGLE); ++ i2c->last_slave_addr = 0; ++ i2c->last_mode = I2C_MODE_SINGLE; ++ ++ hi_i2c_enable(i2c); ++} ++ ++static int hi_i2c_polling_xfer_one_msg(struct hi_i2c *i2c) ++{ ++ int status; ++ unsigned val; ++ struct i2c_msg *msg = i2c->msg; ++ unsigned int tmp; ++ unsigned int data_h = 0; ++ unsigned int data_l = 0; ++ ++ dev_dbg(i2c->dev, "[%s,%d]\n", __func__, __LINE__); ++ ++ tmp = !CR1_READ_MODE; ++ switch (msg->len) { ++ case 2: ++ tmp &= ~CR1_H_WIDE; ++ tmp &= ~CR1_L_WIDE; ++ ++ data_h = msg->buf[0]; ++ data_l = msg->buf[1]; ++ break; ++ case 3: ++ tmp |= CR1_H_WIDE; ++ tmp &= ~CR1_L_WIDE; ++ ++ data_h = msg->buf[0]; ++ data_h |= msg->buf[1] << 8; ++ data_l = msg->buf[2]; ++ break; ++ case 4: ++ tmp |= CR1_H_WIDE; ++ tmp |= CR1_L_WIDE; ++ ++ data_h = msg->buf[0]; ++ data_h |= msg->buf[1] << 8; ++ data_l = msg->buf[2]; ++ data_l |= msg->buf[3] << 8; ++ break; ++ default: ++ dev_err(i2c->dev, "Unsupported this length: %d!\n", msg->len); ++ return -EIO; ++ } ++ ++ if ((msg->addr != i2c->last_slave_addr) ++ || (I2C_MODE_SINGLE != i2c->last_mode)) { ++ hi_i2c_set_slave_addr(i2c, msg->addr, msg->flags & I2C_M_TEN); ++ hi_i2c_set_mode(i2c, I2C_MODE_SINGLE); ++ } ++ ++ val = readl(i2c->virtbase + HII2C_CR1); ++ val &= ~CR1_H_WIDE & ~CR1_L_WIDE & ~CR1_READ_MODE; ++ val |= tmp; ++ writel(val, i2c->virtbase + HII2C_CR1); ++ do { ++ status = hi_i2c_wait_tx_nofull(i2c); ++ if (status) ++ break; ++ ++ val = (data_h << DATA_H_SHIFT) | (data_l << DATA_L_SHIFT); ++ writel(val, i2c->virtbase + HII2C_DATA); ++ } while (0); ++ ++ udelay(hi_i2c_get_delay_val(i2c)); ++ ++ if (!status) ++ status = hi_i2c_wait_idle(i2c); ++ ++ hi_i2c_clr_status(i2c); ++ ++ return status; ++} ++ ++static int hi_i2c_polling_xfer_two_msg(struct hi_i2c *i2c) ++{ ++ int status; ++ unsigned val; ++ struct i2c_msg *msg = i2c->msg; ++ unsigned int tmp; ++ unsigned int data_h = 0; ++ unsigned int data_l = 0; ++ ++ ++ dev_dbg(i2c->dev, "[%s,%d]\n", __func__, __LINE__); ++ ++ tmp = CR1_READ_MODE; ++ switch (msg->len) { ++ case 1: ++ tmp &= ~CR1_H_WIDE; ++ ++ data_h = msg->buf[0]; ++ break; ++ case 2: ++ tmp |= CR1_H_WIDE; ++ ++ data_h = msg->buf[0]; ++ data_h |= msg->buf[1] << 8; ++ break; ++ default: ++ dev_err(i2c->dev, "Unsupported this length: %d!\n", msg->len); ++ return -EIO; ++ } ++ ++ msg++; ++ ++ switch (msg->len) { ++ case 1: ++ tmp &= ~CR1_L_WIDE; ++ break; ++ case 2: ++ tmp |= CR1_L_WIDE; ++ break; ++ default: ++ dev_err(i2c->dev, "Unsupported this length: %d!\n", msg->len); ++ return -EIO; ++ } ++ ++ if ((msg->addr != i2c->last_slave_addr) ++ || (I2C_MODE_SINGLE != i2c->last_mode)) { ++ hi_i2c_set_slave_addr(i2c, msg->addr, msg->flags & I2C_M_TEN); ++ hi_i2c_set_mode(i2c, I2C_MODE_SINGLE); ++ } ++ ++ val = readl(i2c->virtbase + HII2C_CR1); ++ val &= ~CR1_H_WIDE & ~CR1_L_WIDE & ~CR1_READ_MODE; ++ val |= tmp; ++ writel(val, i2c->virtbase + HII2C_CR1); ++ do { ++ status = hi_i2c_wait_tx_nofull(i2c); ++ if (status) ++ break; ++ ++ val = data_h << DATA_H_SHIFT; ++ writel(val, i2c->virtbase + HII2C_DATA); ++ ++ status = hi_i2c_wait_rx_noempty(i2c); ++ if (status) ++ break; ++ ++ data_l = readl(i2c->virtbase + HII2C_DATA) & DATA_L; ++ ++ switch (msg->len) { ++ case 1: ++ msg->buf[0] = data_l & 0xff; ++ break; ++ case 2: ++ msg->buf[0] = data_l & 0xff; ++ msg->buf[1] = (data_l >> 8) & 0xff; ++ break; ++ default: ++ status = -EIO; ++ dev_err(i2c->dev, "Unsupported this length: %d!\n", ++ msg->len); ++ break; ++ } ++ } while (0); ++ ++ if (!status) ++ status = hi_i2c_wait_idle(i2c); ++ ++ hi_i2c_clr_status(i2c); ++ ++ return status; ++} ++ ++static int hi_i2c_dma_xfer_one_msg(struct hi_i2c *i2c) ++{ ++ int status; ++ struct i2c_msg *msg = i2c->msg; ++ dma_addr_t dma_buf; ++ unsigned int reg_addr; ++ unsigned int reg_width; ++ ++ dev_dbg(i2c->dev, "[%s,%d]\n", __func__, __LINE__); ++ ++ if (msg->len < 2) { ++ dev_err(i2c->dev, "Unsupported this length: %d!\n", msg->len); ++ return -EIO; ++ } ++ reg_addr = msg->buf[0]; ++ reg_width = 1; ++ ++ dma_buf = dma_map_single(i2c->dev, msg->buf, msg->len, DMA_TO_DEVICE); ++ ++ if (dma_mapping_error(i2c->dev, dma_buf)) { ++ dev_err(i2c->dev, "DMA mapping failed\n"); ++ return -EINVAL; ++ } ++ ++ status = hi_i2c_do_dma_write(i2c, reg_addr, reg_width, ++ dma_buf + reg_width, msg->len - reg_width); ++ ++ dma_unmap_single(i2c->dev, dma_buf, msg->len, DMA_TO_DEVICE); ++ ++ return status; ++} ++ ++static int hi_i2c_dma_xfer_two_msg(struct hi_i2c *i2c) ++{ ++ int status; ++ struct i2c_msg *msg = i2c->msg; ++ dma_addr_t dma_buf; ++ unsigned int reg_addr; ++ unsigned int reg_width; ++ ++ dev_dbg(i2c->dev, "[%s,%d]\n", __func__, __LINE__); ++ ++ switch (msg->len) { ++ case 1: ++ reg_addr = msg->buf[0]; ++ reg_width = 1; ++ break; ++ case 2: ++ reg_addr = msg->buf[0] << 8; ++ reg_addr |= msg->buf[1]; ++ reg_width = 2; ++ break; ++ default: ++ dev_err(i2c->dev, "Unsupported this length: %d!\n", msg->len); ++ return -EIO; ++ } ++ ++ msg++; ++ ++ if (msg->len <= 0) { ++ dev_err(i2c->dev, "Unsupported this length: %d!\n", msg->len); ++ return -EIO; ++ } ++ ++ dma_buf = dma_map_single(i2c->dev, msg->buf, msg->len, DMA_FROM_DEVICE); ++ ++ if (dma_mapping_error(i2c->dev, dma_buf)) { ++ dev_err(i2c->dev, "DMA mapping failed\n"); ++ return -EINVAL; ++ } ++ ++ status = hi_i2c_do_dma_read(i2c, reg_addr, reg_width, dma_buf, ++ msg->len); ++ ++ dma_unmap_single(i2c->dev, dma_buf, msg->len, DMA_FROM_DEVICE); ++ ++ return status; ++} ++ ++static int hi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ++ int num) ++{ ++ struct hi_i2c *i2c = i2c_get_adapdata(adap); ++ int status; ++ struct i2c_msg *msg = i2c->msg; ++ unsigned int msg_idx; ++ unsigned long flags; ++ ++ if (!msgs || (num <= 0)) { ++ dev_err(i2c->dev, "msgs == NULL || num <= 0, Invalid argument!\n"); ++ return -EINVAL; ++ } ++ ++ spin_lock_irqsave(&i2c->lock, flags); ++ ++ i2c->msg = msgs; ++ msg_idx = 0; ++ ++ while (msg_idx < num) { ++ msg = i2c->msg; ++ ++ if (msg->flags & I2C_M_RD) { ++ status = -EIO; ++ dev_err(i2c->dev, "Unsupported read-only!\n"); ++ break; ++ } ++ ++ if ((msg_idx < (num - 1)) && ((msg + 1)->flags & I2C_M_RD)) { ++ if ((msg + 1)->len <= 2) ++ status = hi_i2c_polling_xfer_two_msg(i2c); ++ else ++ status = hi_i2c_dma_xfer_two_msg(i2c); ++ ++ if (status) ++ break; ++ ++ i2c->msg += 2; ++ msg_idx += 2; ++ } else { ++ if (msg->len <= 4) ++ status = hi_i2c_polling_xfer_one_msg(i2c); ++ else ++ status = hi_i2c_dma_xfer_one_msg(i2c); ++ ++ if (status) ++ break; ++ ++ i2c->msg++; ++ msg_idx++; ++ } ++ } ++ ++ if (!status || msg_idx > 0) ++ status = msg_idx; ++ else ++ status = -EIO; ++ ++ spin_unlock_irqrestore(&i2c->lock, flags); ++ ++ return status; ++} ++ ++/* HI I2C READ * ++ * hi_i2c_master_recv - issue a single I2C message in master receive mode ++ * @client: Handle to slave device ++ * @buf: Where to store data read from slave ++ * @count: How many bytes to read, must be less than 64k since msg.len is u16 ++ * ++ * Returns negative errno, or else the number of bytes read. ++ */ ++int hi_i2c_master_recv(const struct i2c_client *client, char *buf, ++ int count) ++{ ++ printk("Wrong interface call." ++ "hi_i2c_transfer is the only interface to i2c read!!!\n"); ++ ++ return -EIO; ++} ++EXPORT_SYMBOL(hi_i2c_master_recv); ++ ++/*HI I2C WRITE* ++ * hi_i2c_master_send - issue a single I2C message in master transmit mode ++ * @client: Handle to slave device ++ * @buf: Data that will be written to the slave ++ * @count: How many bytes to write, must be less than 64k since msg.len is u16 ++ * ++ * Returns negative errno, or else the number of bytes written. ++ */ ++int hi_i2c_master_send(const struct i2c_client *client, ++ const char *buf, int count) ++{ ++ struct i2c_adapter *adap = client->adapter; ++ struct i2c_msg msg; ++ int msgs_count; ++ ++ if ((client->addr > 0x3ff) ++ || (((client->flags & I2C_M_TEN) == 0) && (client->addr > 0x7f))) { ++ printk(KERN_ERR "dev address out of range\n"); ++ return -EINVAL; ++ } ++ ++ msg.addr = client->addr; ++ msg.flags = client->flags; ++ msg.len = count; ++ ++ if (!buf) { ++ printk(KERN_ERR "Invalid buf == NULL!!!\n"); ++ return -EINVAL; ++ } ++ msg.buf = (__u8 *)buf; ++ ++ msgs_count = hi_i2c_xfer(adap, &msg, 1); ++ ++ return (msgs_count == 1) ? count : -EIO; ++} ++EXPORT_SYMBOL(hi_i2c_master_send); ++ ++/** ++ * hi_i2c_transfer - execute a single or combined I2C message ++ * @adap: Handle to I2C bus ++ * @msgs: One or more messages to execute before STOP is issued to ++ * terminate the operation; each message begins with a START. ++ * @num: Number of messages to be executed. ++ * ++ * Returns negative errno, else the number of messages executed. ++ * ++ * Note that there is no requirement that each message be sent to ++ * the same slave address, although that is the most common model. ++ */ ++ ++int hi_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ++ int num) ++{ ++ int msgs_count; ++ ++ if ((msgs[0].addr > 0x3ff) ++ || (((msgs[0].flags & I2C_M_TEN) == 0) && (msgs[0].addr > 0x7f))) { ++ printk(KERN_ERR "msgs[0] dev address out of range\n"); ++ return -EINVAL; ++ } ++ ++ if ((msgs[1].addr > 0x3ff) ++ || (((msgs[1].flags & I2C_M_TEN) == 0) && (msgs[1].addr > 0x7f))) { ++ printk(KERN_ERR "msgs[1] dev address out of range\n"); ++ return -EINVAL; ++ } ++ ++ msgs_count = hi_i2c_xfer(adap, msgs, num); ++ ++ return msgs_count; ++} ++EXPORT_SYMBOL(hi_i2c_transfer); ++ ++static u32 hi_i2c_func(struct i2c_adapter *adap) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR ++ | I2C_FUNC_PROTOCOL_MANGLING; ++} ++ ++static const struct i2c_algorithm hi_i2c_algorithm = { ++ .master_xfer = hi_i2c_xfer, ++ .functionality = hi_i2c_func, ++}; ++ ++/* hi_i2c_parse_dt ++ * ++ * Parse the device tree node. ++ */ ++static int hi_i2c_parse_dt(struct hi_i2c *i2c) ++{ ++ struct device *dev = i2c->dev; ++ struct device_node *np = dev->of_node; ++ ++ if (!np) { ++ dev_err(dev, "no dt node defined\n"); ++ return -ENODEV; ++ } ++ ++ if (of_property_read_u32(np, "clock-frequency", &i2c->frequency)) { ++ dev_dbg(dev, "of read error clock-frequency = %d\n", ++ i2c->frequency); ++ i2c->frequency = 4000000; ++ } ++ ++ return 0; ++} ++ ++static int hi_i2c_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct hi_i2c *i2c; ++ struct i2c_adapter *adap; ++ struct resource *res; ++ int status; ++ ++ dev_info(dev, "HISILICON I2C V110 bus driver\n"); ++ ++ adap = devm_kzalloc(&pdev->dev, ++ sizeof(struct i2c_adapter) + sizeof(struct hi_i2c), ++ GFP_KERNEL); ++ if (!adap) ++ return -ENOMEM; ++ ++ adap->dev.parent = dev; ++ adap->dev.of_node = dev->of_node; ++ i2c_set_adapdata(adap, &adap[1]); ++ ++ adap->owner = THIS_MODULE; ++ adap->class = I2C_CLASS_DEPRECATED; ++ adap->algo = &hi_i2c_algorithm; ++ strlcpy(adap->name, "hisi-i2c-v110", sizeof(adap->name)); ++ ++ i2c = i2c_get_adapdata(adap); ++ platform_set_drvdata(pdev, i2c); ++ spin_lock_init(&i2c->lock); ++ ++ i2c->pdev = pdev; ++ i2c->adap = adap; ++ i2c->dev = dev; ++ ++ status = hi_i2c_parse_dt(i2c); ++ if (status) ++ goto err_ioremap; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) ++ goto err_ioremap; ++ ++ i2c->virtbase = devm_ioremap_resource(dev, res); ++ if (i2c->virtbase == NULL) { ++ status = PTR_ERR(i2c->virtbase); ++ dev_err(dev, "cannot ioremap resource\n"); ++ goto err_ioremap; ++ } ++ i2c->phybase = res->start; ++ dev_info(dev, "mapped registers from 0x%x to 0x%p\n", ++ res->start, i2c->virtbase); ++ ++ /* find the clock and enable it */ ++ i2c->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(i2c->clk)) { ++ status = PTR_ERR(i2c->clk); ++ dev_err(dev, "cannot get clock\n"); ++ goto err_clk; ++ } ++ status = clk_prepare_enable(i2c->clk); ++ if (status) { ++ dev_err(dev, "could not enable clock\n"); ++ goto err_clk; ++ } ++ ++ hi_i2c_hw_init(i2c); ++ ++ status = i2c_add_adapter(i2c->adap); ++ if (status < 0) { ++ dev_err(dev, "failed to add bus to i2c core\n"); ++ goto err_add_adapter; ++ } ++ ++ return 0; ++ ++err_add_adapter: ++ clk_disable_unprepare(i2c->clk); ++err_clk: ++err_ioremap: ++ ++ return status; ++} ++ ++/* hi_i2c_remove ++ * ++ * called when device is removed from the bus ++ */ ++static int hi_i2c_remove(struct platform_device *pdev) ++{ ++ struct hi_i2c *i2c = platform_get_drvdata(pdev); ++ ++ clk_disable_unprepare(i2c->clk); ++ i2c_del_adapter(i2c->adap); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++static int hi_i2c_runtime_suspend(struct device *dev) ++{ ++ return 0; ++} ++ ++static int hi_i2c_runtime_resume(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct hi_i2c *i2c = platform_get_drvdata(pdev); ++ ++ hi_i2c_hw_init(i2c); ++ return 0; ++} ++#endif ++ ++static const struct dev_pm_ops hi_i2c_dev_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(hi_i2c_runtime_suspend, ++ hi_i2c_runtime_resume) ++}; ++ ++static const struct of_device_id hi_i2c_match[] = { ++ { .compatible = "hisilicon,hisi-i2c-v110"}, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, hi_i2c_match); ++ ++static struct platform_driver hi_i2c_driver = { ++ .probe = hi_i2c_probe, ++ .remove = hi_i2c_remove, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "hisi-i2c-v110", ++ .pm = &hi_i2c_dev_pm_ops, ++ .of_match_table = of_match_ptr(hi_i2c_match), ++ }, ++}; ++ ++module_platform_driver(hi_i2c_driver); ++ ++MODULE_DESCRIPTION("HISILICON I2C V110 Bus driver"); ++MODULE_AUTHOR("BVT OSDRV"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/i2c/busses/i2c-hisilicon.c b/drivers/i2c/busses/i2c-hisilicon.c +new file mode 100644 +index 0000000..66c5a0a +--- /dev/null ++++ b/drivers/i2c/busses/i2c-hisilicon.c +@@ -0,0 +1,1169 @@ ++/* linux/drivers/i2c/busses/i2c-hisilicon.c ++ * ++ * HISILICON I2C Controller ++ * ++ * Copyright (c) 2014 Hisilicon 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "i2c-hisilicon.h" ++#include ++ ++#ifdef CONFIG_HI_DMAC ++#include ++#endif ++ ++#define HI_I2C "hisi_i2c" ++ ++#define hi_err(x...) \ ++ do { \ ++ pr_alert("%s->%d: ", __func__, __LINE__); \ ++ pr_alert(x); \ ++ pr_alert("\n"); \ ++ } while (0) ++ ++/* #define HI_I2C_DEBUG */ ++ ++#ifdef HI_I2C_DEBUG ++ ++#define hi_msg(x...) \ ++ do { \ ++ pr_alert("%s (line:%d) ", __func__, __LINE__); \ ++ pr_alert(x); \ ++ } while (0) ++#else ++#define hi_msg(args...) do { } while (0) ++#endif ++ ++#define I2C_WAIT_TIME_OUT 20000 ++ ++#define I2C_DFT_RATE (100000) ++ ++struct hi_i2c { ++ unsigned char __iomem *regbase; ++ struct device *dev; ++ struct resource *mem; ++ unsigned int irq; ++ struct i2c_adapter adap; ++ struct i2c_msg *msgs; ++ __u16 msg_num; ++ __u16 msg_addr; ++ unsigned int msg_index; ++ struct hi_platform_i2c *pdata; ++ unsigned int g_last_dev_addr; ++ unsigned int g_last_mode; ++ spinlock_t spinlock; ++}; ++ ++unsigned int get_apb_clk(void); ++ ++static int hi_i2c_abortprocess(struct hi_i2c *pinfo) ++{ ++ unsigned int auto_status; ++ unsigned int tx_src; ++ ++ tx_src = readl(pinfo->regbase + I2C_TX_ABRT_SRC); ++ hi_err("tx_abrt_src is %x.\n", tx_src); ++ ++ auto_status = readl(pinfo->regbase + I2C_AUTO_REG); ++ ++ /* clear 0xB0 err status */ ++ /* auto_mst_tx_abrt_clr ++ auto_tx_cmd_fifo_over_clr ++ auto_rx_cmd_fifo_under_clr ++ auto_rx_cmd_fifo_over_clr ++ */ ++ auto_status |= 0x0f000000; ++ writel(auto_status, pinfo->regbase + I2C_AUTO_REG); ++ writel(0x1, pinfo->regbase + I2C_CLR_INTR_REG); ++ ++ /* disable i2c */ ++ writel(0, pinfo->regbase + I2C_ENABLE_REG); ++ ++ /* enable i2c */ ++ writel(0x1, pinfo->regbase + I2C_ENABLE_REG); ++ ++ return 0; ++} ++ ++void hi_i2c_set_rate(struct hi_i2c *pinfo) ++{ ++ unsigned int apb_clk, scl_h, scl_l, hold; ++ ++ /* get apb bus clk for diff plat */ ++ apb_clk = get_apb_clk(); ++ ++ /* set SCLH and SCLL depend on apb_clk and def_rate */ ++ if (pinfo->pdata->clk_limit <= I2C_DFT_RATE) { ++ /* in normal mode F_scl: def_rate ++ i2c_scl_hcnt = (F_i2c / F_scl) * 0.5 ++ i2c_scl_hcnt = (F_i2c / F_scl) * 0.5 ++ */ ++ scl_h = (apb_clk / I2C_DFT_RATE) / 2; ++ scl_l = scl_h; ++ } else { ++ /* in fast mode F_scl: def_rate ++ i2c_scl_hcnt = (F_i2c / F_scl) * 0.36 ++ i2c_scl_hcnt = (F_i2c / F_scl) * 0.64 ++ */ ++ scl_h = ((apb_clk / 100) * 36) / pinfo->pdata->clk_limit; ++ scl_l = ((apb_clk / 100) * 64) / pinfo->pdata->clk_limit; ++ } ++ ++ writel(scl_h, pinfo->regbase + I2C_SCL_H_REG); ++ writel(scl_l, pinfo->regbase + I2C_SCL_L_REG); ++ ++ /* set hi_i2c hold time */ ++ hold = scl_h / 2; ++ writel(hold, pinfo->regbase + I2C_SDA_HOLD_REG); ++} ++ ++void hi_i2c_hw_init(struct hi_i2c *pinfo) ++{ ++ unsigned int temp, rx_fifo, tx_fifo; ++ ++ /* unlock hi_i2c controller to access */ ++ writel(HI_I2C_UNLOCK_VALUE, pinfo->regbase + I2C_LOCK_REG); ++ ++ /* disable hi_i2c controller */ ++ temp = readl(pinfo->regbase + I2C_ENABLE_REG); ++ writel((temp & ~HI_I2C_ENABLE), pinfo->regbase + I2C_ENABLE_REG); ++ ++ /* disable hi_i2c auto_mode */ ++ writel(HI_I2C_AUTO_MODE_OFF, pinfo->regbase + I2C_AUTO_REG); ++ ++ /* set hi_i2c in fast mode */ ++ writel(HI_I2C_FAST_MODE, pinfo->regbase + I2C_CON_REG); ++ ++ /* set hi_i2c rate */ ++ hi_i2c_set_rate(pinfo); ++ ++ rx_fifo = CONFIG_HI_I2C_RX_FIFO; ++ tx_fifo = CONFIG_HI_I2C_TX_FIFO; ++ ++ /* set hi_i2c fifo */ ++ writel(rx_fifo, pinfo->regbase + I2C_RX_TL_REG); ++ writel(tx_fifo, pinfo->regbase + I2C_TX_TL_REG); ++ ++ /* enable interrupt mask */ ++ writel(DISABLE_ALL_INTERRUPTS, pinfo->regbase + I2C_INTR_MASK_REG); ++ ++ /* enable hi_i2c controller */ ++ temp = readl(pinfo->regbase + I2C_ENABLE_REG); ++ writel((temp | HI_I2C_ENABLE), pinfo->regbase + I2C_ENABLE_REG); ++ ++ pinfo->g_last_dev_addr = 0; ++ pinfo->g_last_mode = I2C_MODE_NONE; ++ ++ pinfo->msgs = NULL; ++ pinfo->msg_num = 0; ++} ++ ++#define HII2C_IC 0x40 ++#define HII2C_CR1 0xB0 ++#define HII2C_EN 0x6C ++#define CR1_SINGLE_MODE_EN (0x1 << 31) ++#define CR1_STATUS_CLR (0xf << 24) ++static inline void hi_i2c_disable(struct hi_i2c *i2c) ++{ ++ writel(0x0, i2c->regbase + HII2C_EN); ++} ++ ++static inline void hi_i2c_enable(struct hi_i2c *i2c) ++{ ++ writel(0x1, i2c->regbase + HII2C_EN); ++} ++ ++static inline int hi_i2c_clr_status(struct hi_i2c *i2c) ++{ ++ unsigned int val; ++ ++ val = readl(i2c->regbase + HII2C_CR1); ++ val |= CR1_STATUS_CLR; ++ writel(val & (~CR1_SINGLE_MODE_EN), i2c->regbase + HII2C_CR1); ++ writel(val, i2c->regbase + HII2C_CR1); ++ ++ writel(0x1, i2c->regbase + HII2C_IC); ++ ++ hi_i2c_disable(i2c); ++ ++ hi_i2c_enable(i2c); ++ ++ return 0; ++} ++ ++int hi_i2c_wait_idle(struct hi_i2c *pinfo) ++{ ++ unsigned int val; ++ unsigned int time_cnt; ++ ++ time_cnt = 0; ++ do { ++ val = readl(pinfo->regbase + I2C_INTR_RAW_REG); ++ if (val & I2C_RAW_TX_ABORT) { ++ hi_err("wait last i2c fifo is empty abort! "\ ++ "int_raw_status: %#x!\n", val); ++ return hi_i2c_abortprocess(pinfo); ++ } ++ ++ val = readl(pinfo->regbase + I2C_AUTO_REG); ++ if (!IS_RX_FIFO_EMPTY(val)) ++ readl(pinfo->regbase + I2C_TX_RX_REG); ++ ++ if (IS_FIFO_EMPTY(val)) ++ break; ++ ++ if (time_cnt > I2C_WAIT_TIME_OUT) { ++ hi_err("wait last i2c fifo is empty timeout! "\ ++ "auto_status: %#x\n", val); ++ return -EBUSY; ++ } ++ time_cnt++; ++ udelay(50); ++ } while (1); ++ ++ udelay(10); ++ ++ time_cnt = 0; ++ do { ++ val = readl(pinfo->regbase + I2C_INTR_RAW_REG); ++ if (val & I2C_RAW_TX_ABORT) { ++ hi_err("wait last i2c is idle abort! "\ ++ "int_raw_status: %#x!\n", val); ++ return hi_i2c_abortprocess(pinfo); ++ } ++ ++ val = readl(pinfo->regbase + I2C_STATUS_REG); ++ if (IS_I2C_IDLE(val)) ++ break; ++ ++ if (time_cnt > I2C_WAIT_TIME_OUT) { ++ hi_err("wait last i2c is idle timeout! "\ ++ "auto_status: %#x\n", val); ++ return -EBUSY; ++ } ++ time_cnt++; ++ udelay(50); ++ } while (1); ++ ++ return 0; ++} ++ ++/* wait until tx fifo is not full */ ++int hi_i2c_wait_txfifo_notfull(struct hi_i2c *pinfo) ++{ ++ unsigned int val; ++ unsigned int time_cnt; ++ ++ time_cnt = 0; ++ do { ++ val = readl(pinfo->regbase + I2C_INTR_RAW_REG); ++ if (val & I2C_RAW_TX_ABORT) { ++ hi_err("abort! last int_raw_status: %#x!\n", val); ++ return hi_i2c_abortprocess(pinfo); ++ } ++ ++ val = readl(pinfo->regbase + I2C_AUTO_REG); ++ if (!IS_RX_FIFO_EMPTY(val)) ++ readl(pinfo->regbase + I2C_TX_RX_REG); ++ ++ if (val & I2c_AUTO_TX_FIFO_NOT_FULL) ++ break; ++ ++ if (time_cnt > I2C_WAIT_TIME_OUT) { ++ hi_err("timeout! last auto_status: %#x\n", val); ++ return -EBUSY; ++ } ++ time_cnt++; ++ udelay(50); ++ } while (1); ++ ++ return 0; ++} ++ ++/* wait until tx fifo is not empty */ ++int hi_i2c_wait_rxfifo_notempty(struct hi_i2c *pinfo) ++{ ++ unsigned int val; ++ unsigned int time_cnt; ++ ++ time_cnt = 0; ++ do { ++ val = readl(pinfo->regbase + I2C_INTR_RAW_REG); ++ if ((val & I2C_RAW_TX_ABORT) == I2C_RAW_TX_ABORT) { ++ hi_err("abort! int_raw_status: %#x!\n", val); ++ hi_i2c_abortprocess(pinfo); ++ return -EIO; ++ } ++ ++ val = readl(pinfo->regbase + I2C_AUTO_REG); ++ if (!IS_RX_FIFO_EMPTY(val)) ++ break; ++ ++ if (time_cnt > I2C_WAIT_TIME_OUT) { ++ hi_err("timeout! auto_status: %#x\n", val); ++ hi_i2c_abortprocess(pinfo); ++ return -EBUSY; ++ } ++ time_cnt++; ++ udelay(50); ++ } while (1); ++ ++ return 0; ++} ++ ++static inline int hi_i2c_set_dev_addr_and_mode(struct hi_i2c *pinfo, ++ unsigned int work_mode) ++{ ++ unsigned int dev_addr = pinfo->msgs->addr; ++ ++ if ((pinfo->g_last_dev_addr == dev_addr) ++ && (pinfo->g_last_mode == work_mode)) ++ return 0; ++ ++ /* wait until all cmd in fifo is finished and i2c is idle */ ++ if (hi_i2c_wait_idle(pinfo) < 0) ++ return -1; ++ ++ /* disable i2c */ ++ writel(0x0, pinfo->regbase + I2C_ENABLE_REG); ++ /* clear interrupt */ ++ writel(0x1, pinfo->regbase + I2C_CLR_INTR_REG); ++ /* enable interrupt mask */ ++ writel(DISABLE_ALL_INTERRUPTS, pinfo->regbase + I2C_INTR_MASK_REG); ++ /* clear err status */ ++ writel(0x0f000000, pinfo->regbase + I2C_AUTO_REG); ++ ++ /* different device, need to reinit i2c ctrl */ ++ if ((pinfo->g_last_dev_addr) != dev_addr) { ++ /* set slave dev addr */ ++ writel((dev_addr & 0xff)>>1, pinfo->regbase + I2C_TAR_REG); ++ pinfo->g_last_dev_addr = dev_addr; ++ } ++ ++ if (pinfo->g_last_mode != work_mode) { ++ ++ /* set auto mode */ ++ if (work_mode == I2C_MODE_AUTO) { ++ writel(0x0, pinfo->regbase + I2C_DMA_CMD0); ++ writel(0x80000000, pinfo->regbase + I2C_AUTO_REG); ++ pinfo->g_last_mode = work_mode; ++ } else if (work_mode == I2C_MODE_DMA) { ++ writel(0x0, pinfo->regbase + I2C_AUTO_REG); ++ pinfo->g_last_mode = work_mode; ++ } else { ++ hi_err("invalid i2c mode\n"); ++ return -1; ++ } ++ } ++ ++ /* enable i2c */ ++ writel(0x1, pinfo->regbase + I2C_ENABLE_REG); ++ ++ hi_msg("\n@@@@@@@@@@\n"); ++ ++ return 0; ++} ++ ++int hi_i2c_write(struct hi_i2c *pinfo) ++{ ++ unsigned int reg_val; ++ unsigned int temp_reg; ++ unsigned int temp_data; ++ unsigned int temp_auto_reg; ++ unsigned int min_msgs_len = 0; ++ struct i2c_msg *msgs = pinfo->msgs; ++ ++ min_msgs_len = (msgs->flags & I2C_M_16BIT_REG) ? 2 : 1; ++ min_msgs_len += (msgs->flags & I2C_M_16BIT_DATA) ? 2 : 1; ++ if (msgs->len < min_msgs_len){ ++ hi_err("Unsupported this length: %d!\n", msgs->len); ++ return -1; ++ } ++ ++ if (hi_i2c_set_dev_addr_and_mode(pinfo, I2C_MODE_AUTO) < 0) ++ return -1; ++ ++ temp_auto_reg = HI_I2C_WRITE; ++ ++ if (msgs->flags & I2C_M_16BIT_REG) { ++ /* 16bit reg addr */ ++ temp_auto_reg |= I2C_AUTO_ADDR; ++ ++ /* switch high byte and low byte */ ++ temp_reg = msgs->buf[pinfo->msg_index] << 8; ++ ++ pinfo->msg_index++; ++ ++ temp_reg |= msgs->buf[pinfo->msg_index]; ++ ++ pinfo->msg_index++; ++ } else { ++ temp_reg = msgs->buf[pinfo->msg_index]; ++ pinfo->msg_index++; ++ } ++ ++ if (msgs->flags & I2C_M_16BIT_DATA) { ++ /* 16bit data */ ++ temp_auto_reg |= I2C_AUTO_DATA; ++ ++ /* switch high byte and low byte */ ++ temp_data = msgs->buf[pinfo->msg_index] << 8; ++ ++ pinfo->msg_index++; ++ ++ temp_data |= msgs->buf[pinfo->msg_index]; ++ ++ pinfo->msg_index++; ++ } else { ++ temp_data = msgs->buf[pinfo->msg_index]; ++ pinfo->msg_index++; ++ } ++ ++ writel(temp_auto_reg, pinfo->regbase + I2C_AUTO_REG); ++ hi_msg("temp_auto_reg: 0x%x\n", temp_auto_reg); ++ ++ /* set write reg&data */ ++ reg_val = (temp_reg << REG_SHIFT) | temp_data; ++ ++ /* wait until tx fifo not full */ ++ if (hi_i2c_wait_txfifo_notfull(pinfo) < 0) ++ return -1; ++ ++ hi_msg("reg_val = %x\n", reg_val); ++ ++ writel(reg_val, pinfo->regbase + I2C_TX_RX_REG); ++ ++ hi_msg("dev_addr =%x, reg_addr = %x, Data = %x\n", ++ pinfo->msgs->addr, pinfo->msgs->buf[0], pinfo->msgs->buf[1]); ++ ++ return pinfo->msg_index; ++} ++ ++unsigned int hi_i2c_read(struct hi_i2c *pinfo) ++{ ++ unsigned int reg_val; ++ unsigned int temp_reg; ++ unsigned int ret_data = 0xffff; ++ unsigned int temp_auto_reg; ++ unsigned int data_num = 0; ++ unsigned int min_msgs_len = 0; ++ struct i2c_msg *msgs = pinfo->msgs; ++ ++ min_msgs_len = (msgs->flags & I2C_M_16BIT_REG) ? 2 : 1; ++ if (msgs->len < min_msgs_len){ ++ hi_err("Unsupported this length: %d!\n", msgs->len); ++ return -1; ++ } ++ ++ if (hi_i2c_set_dev_addr_and_mode(pinfo, I2C_MODE_AUTO) < 0) ++ return -1; ++ ++ temp_auto_reg = HI_I2C_READ; ++ ++ if (msgs->flags & I2C_M_16BIT_REG) { ++ /* 16bit reg addr */ ++ temp_auto_reg |= I2C_AUTO_ADDR; ++ ++ /* switch high byte and low byte */ ++ temp_reg = msgs->buf[pinfo->msg_index] << 8; ++ pinfo->msg_index++; ++ temp_reg |= msgs->buf[pinfo->msg_index]; ++ } else { ++ temp_reg = msgs->buf[pinfo->msg_index]; ++ pinfo->msg_index++; ++ } ++ ++ if (msgs->flags & I2C_M_16BIT_DATA) ++ /* 16bit data */ ++ temp_auto_reg |= I2C_AUTO_DATA; ++ ++ writel(temp_auto_reg, pinfo->regbase + I2C_AUTO_REG); ++ hi_msg("temp_auto_reg: 0x%x\n", temp_auto_reg); ++ ++ /* 1. write addr */ ++ reg_val = temp_reg << REG_SHIFT; ++ hi_msg("reg_val %x\n", reg_val); ++ ++ /* wait until tx fifo not full */ ++ if (hi_i2c_wait_txfifo_notfull(pinfo) < 0) ++ return -1; ++ ++ /* regaddr */ ++ writel(reg_val, pinfo->regbase + I2C_TX_RX_REG); ++ ++ /* 2. read return data */ ++ /* wait until rx fifo not empty */ ++ if (hi_i2c_wait_rxfifo_notempty(pinfo) < 0) ++ return -1; ++ ++ ret_data = readl(pinfo->regbase + I2C_TX_RX_REG) & DATA_16BIT_MASK; ++ hi_msg("ret_data = %x\n", ret_data); ++ ++ if (msgs->flags & I2C_M_16BIT_DATA) { ++ pinfo->msgs->buf[0] = ret_data & DATA_8BIT_MASK; ++ pinfo->msgs->buf[1] = (ret_data >> 8) & DATA_8BIT_MASK; ++ data_num = 2; ++ } else { ++ pinfo->msgs->buf[0] = ret_data & DATA_8BIT_MASK; ++ data_num = 1; ++ } ++ ++ writel(0x1, pinfo->regbase + I2C_CLR_INTR_REG); ++ ++ return data_num; ++} ++ ++/************************************ ++ * dma functions * ++************************************/ ++#ifdef CONFIG_HI_DMAC ++void hi_i2c_dma_start(struct hi_i2c *pinfo, unsigned int dir) ++{ ++ writel((1 << dir), pinfo->regbase + I2C_DMA_CTRL_REG); ++} ++ ++void hi_i2c_dmac_config(struct hi_i2c *pinfo, unsigned int dir) ++{ ++ /* 1. enable RX(0) or TX(1) in DMA mode */ ++ hi_i2c_dma_start(pinfo, dir); ++ ++ /* 2. set dma fifo */ ++ writel(4, pinfo->regbase + I2C_DMA_TDLR); ++ writel(4, pinfo->regbase + I2C_DMA_RDLR); ++} ++ ++void hi_i2c_start_rx(struct hi_i2c *pinfo, unsigned int reg_addr, ++ unsigned int length) ++{ ++ unsigned int reg; ++ ++ writel(reg_addr, pinfo->regbase + I2C_DMA_CMD1); ++ writel(length, pinfo->regbase + I2C_DMA_CMD2); ++ ++ reg = readl(pinfo->regbase + I2C_DMA_CMD0); ++ ++ /*start tx*/ ++ reg &= ~0x40000000; ++ writel((0x80000000 | reg), pinfo->regbase + I2C_DMA_CMD0); ++} ++ ++void hi_i2c_start_tx(struct hi_i2c *pinfo, unsigned int reg_addr, ++ unsigned int length) ++{ ++ unsigned int reg; ++ ++ writel(reg_addr, pinfo->regbase + I2C_DMA_CMD1); ++ writel(length, pinfo->regbase + I2C_DMA_CMD2); ++ ++ reg = readl(pinfo->regbase + I2C_DMA_CMD0); ++ ++ /*start rx*/ ++ writel((0xc0000000 | reg), pinfo->regbase + I2C_DMA_CMD0); ++} ++ ++int dma_to_i2c(unsigned int src, unsigned int dst, unsigned int length) ++{ ++ int chan; ++ ++ chan = do_dma_m2p(src, dst, length); ++ if (chan == -1) ++ hi_err("dma_to_i2c error\n"); ++ ++ return chan; ++} ++ ++ ++int i2c_to_dma(unsigned int src, unsigned int dst, unsigned int length) ++{ ++ int chan; ++ ++ chan = do_dma_p2m(dst, src, length); ++ if (chan == -1) ++ hi_err("dma_p2m error...\n"); ++ ++ return chan; ++} ++ ++static int hi_i2c_do_dma_write(struct hi_i2c *pinfo, unsigned int reg_addr, ++ unsigned int reg_addr_num, unsigned int dma_buf, ++ unsigned int length) ++{ ++ unsigned int temp_reg = reg_addr; ++ int chan, ret = 0; ++ ++ /* 1. switch i2c devaddr and dma mode*/ ++ if (hi_i2c_set_dev_addr_and_mode(pinfo, I2C_MODE_DMA) < 0) { ++ hi_err("HI_I2C_Dma_Write error...\n"); ++ ret = -1; ++ } ++ ++ if (2 == reg_addr_num) { ++ /* switch high byte and low byte */ ++ temp_reg = REVERT_HL_BYTE(reg_addr); ++ writel(0x10000000, pinfo->regbase + I2C_DMA_CMD0); ++ } else { ++ writel(0x0, pinfo->regbase + I2C_DMA_CMD0); ++ } ++ ++ /* 2. config i2c into DMA mode */ ++ hi_i2c_dmac_config(pinfo, 0x1); ++ ++ /* 3. start i2c logic to write */ ++ hi_i2c_start_tx(pinfo, temp_reg, length - 1); ++ ++ /* 4. transmit DATA from DMAC to I2C in DMA mode */ ++ chan = dma_to_i2c(dma_buf, (pinfo->mem->start + I2C_DATA_CMD_REG), ++ length); ++ if (chan == -1) { ++ ret = -1; ++ goto fail_0; ++ } ++ ++ if (dmac_wait(chan) != DMAC_CHN_SUCCESS) { ++ hi_err("dma wait failed\n"); ++ ret = -1; ++ goto fail_1; ++ } ++ ++ ret = hi_i2c_wait_idle(pinfo); ++fail_1: ++ dmac_channel_free(chan); ++fail_0: ++ hi_i2c_clr_status(pinfo); ++ return ret; ++} ++ ++static int hi_i2c_do_dma_read(struct hi_i2c *pinfo, unsigned int reg_addr, ++ unsigned int reg_addr_num, unsigned int dma_buf, ++ unsigned int length) ++{ ++ unsigned int temp_reg = reg_addr; ++ int chan, ret = 0; ++ ++ /* 1. switch i2c devaddr and dma mode*/ ++ if (hi_i2c_set_dev_addr_and_mode(pinfo, I2C_MODE_DMA) < 0) { ++ ret = -1; ++ } ++ ++ if (2 == reg_addr_num) { ++ /* switch high byte and low byte */ ++ temp_reg = REVERT_HL_BYTE(reg_addr); ++ writel(0x10000000, pinfo->regbase + I2C_DMA_CMD0); ++ } else { ++ writel(0x0, pinfo->regbase + I2C_DMA_CMD0); ++ } ++ ++ /* 2. config i2c into DMA mode */ ++ hi_i2c_dmac_config(pinfo, 0x0); ++ ++ /* 3. transmit DATA from I2C to DMAC in DMA mode */ ++ chan = i2c_to_dma((pinfo->mem->start + I2C_DATA_CMD_REG), ++ dma_buf, length); ++ if (chan == -1) { ++ ret = -1; ++ goto fail_0; ++ } ++ ++ /* 4. start i2c logic to read */ ++ hi_i2c_start_rx(pinfo, temp_reg, length - 1); ++ ++ if (dmac_wait(chan) != DMAC_CHN_SUCCESS) { ++ hi_err("dma wait failed\n"); ++ ret = -1; ++ goto fail_1; ++ } ++ ++ ret = hi_i2c_wait_idle(pinfo); ++fail_1: ++ dmac_channel_free(chan); ++fail_0: ++ hi_i2c_clr_status(pinfo); ++ return ret; ++} ++ ++#else ++static int hi_i2c_do_dma_write(struct hi_i2c *pinfo, ++ unsigned int reg_addr, unsigned int reg_addr_num, ++ unsigned int dma_buf, unsigned int length) ++{ ++ hi_err("DMA is not enabled!"); ++ return -1; ++} ++ ++static int hi_i2c_do_dma_read(struct hi_i2c *pinfo, ++ unsigned int reg_addr, unsigned int reg_addr_num, ++ unsigned int dma_buf, unsigned int length) ++{ ++ hi_err("DMA is not enabled!"); ++ return -1; ++} ++#endif ++ ++int hi_i2c_dma_write(const struct i2c_client *client, unsigned int dma_buf, ++ unsigned int reg_addr, unsigned int reg_addr_num, ++ unsigned int length) ++{ ++ struct i2c_adapter *adap = client->adapter; ++ struct hi_i2c *pinfo = (struct hi_i2c *)i2c_get_adapdata(adap); ++ struct i2c_msg msgs; ++ int ret; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&pinfo->spinlock, flags); ++ ++ memset(&msgs, 0x0, sizeof(struct i2c_msg)); ++ msgs.addr = client->addr; ++ msgs.flags = client->flags; ++ msgs.len = length; ++ ++ pinfo->msgs = &msgs; ++ pinfo->msg_num = length; ++ pinfo->msg_index = 0; ++ ++ ret = hi_i2c_do_dma_write(pinfo, reg_addr, reg_addr_num, dma_buf, ++ length); ++ ++ spin_unlock_irqrestore(&pinfo->spinlock, flags); ++ ++ return ret; ++} ++EXPORT_SYMBOL(hi_i2c_dma_write); ++ ++int hi_i2c_dma_read(const struct i2c_client *client, unsigned int dma_buf, ++ unsigned int reg_addr, unsigned int reg_addr_num, ++ unsigned int length) ++{ ++ struct i2c_adapter *adap = client->adapter; ++ struct hi_i2c *pinfo = (struct hi_i2c *)i2c_get_adapdata(adap); ++ struct i2c_msg msgs; ++ int ret; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&pinfo->spinlock, flags); ++ ++ memset(&msgs, 0x0, sizeof(struct i2c_msg)); ++ msgs.addr = client->addr; ++ msgs.flags = client->flags; ++ msgs.flags |= I2C_M_RD; ++ msgs.len = length; ++ ++ pinfo->msgs = &msgs; ++ pinfo->msg_num = length; ++ pinfo->msg_index = 0; ++ ++ ret = hi_i2c_do_dma_read(pinfo, reg_addr, reg_addr_num, dma_buf, ++ length); ++ ++ spin_unlock_irqrestore(&pinfo->spinlock, flags); ++ ++ return ret; ++} ++EXPORT_SYMBOL(hi_i2c_dma_read); ++ ++static int hi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ++ int num) ++{ ++ struct hi_i2c *pinfo = (struct hi_i2c *)i2c_get_adapdata(adap); ++ dma_addr_t dma_buf; ++ __u16 len; ++ unsigned int reg_addr; ++ unsigned int reg_width; ++ int ret; ++ unsigned long flags; ++ ++ if (!msgs || (num <= 0)) { ++ hi_err("msgs == NULL || num <= 0, Invalid argument!\n"); ++ return -EINVAL; ++ } ++ ++ spin_lock_irqsave(&pinfo->spinlock, flags); ++ ++ pinfo->msgs = msgs; ++ pinfo->msg_num = num; ++ pinfo->msg_index = 0; ++ ++ len = pinfo->msgs->len; ++ if (pinfo->msgs->flags & I2C_M_16BIT_REG) { ++ reg_addr = pinfo->msgs->buf[0]; ++ reg_addr |= pinfo->msgs->buf[1] << 8; ++ reg_width = 2; ++ } else { ++ reg_addr = pinfo->msgs->buf[0]; ++ reg_width = 1; ++ } ++ ++ if (pinfo->msgs->flags & I2C_M_DMA) { ++ if (pinfo->msgs->flags & I2C_M_16BIT_DATA) { ++ hi_err("I2C DMA no support I2C_M_16BIT_DATA\n"); ++ ret = -EINVAL; ++ goto end; ++ } ++ ++ if (((pinfo->msgs->flags & I2C_M_RD) && (len <= 0)) || ++ (!(pinfo->msgs->flags & I2C_M_RD) && ++ (len <= reg_width))) { ++ hi_err("msgs->len == %d, Invalid argument!\n", ++ len); ++ ret = -EINVAL; ++ goto end; ++ } ++ ++ dma_buf = dma_map_single(pinfo->dev, ++ pinfo->msgs->buf, len, ++ DMA_BIDIRECTIONAL); ++ if (dma_mapping_error(pinfo->dev, dma_buf)) { ++ hi_err("DMA mapping failed\n"); ++ ret = -EINVAL; ++ goto end; ++ } ++ if (pinfo->msgs->flags & I2C_M_RD) ++ ret = hi_i2c_do_dma_read(pinfo, reg_addr, ++ reg_width, dma_buf, len); ++ else ++ ret = hi_i2c_do_dma_write(pinfo, reg_addr, ++ reg_width, dma_buf + reg_width, ++ len - reg_width); ++ ++ dma_unmap_single(pinfo->dev, dma_buf, len, ++ DMA_BIDIRECTIONAL); ++ ++ /*normally the ret = 0, so forced the return value to 1.*/ ++ if (ret) ++ ret = -EIO; ++ else ++ ret = 1; ++ } else { ++ if (pinfo->msgs->flags & I2C_M_RD){ ++ ret = hi_i2c_read(pinfo); ++ } else{ ++ ret = hi_i2c_write(pinfo); ++ } ++ /*(ret = data_num) or (ret = msg_index),so force the return value to 1, ++ * docking the upper interface. ++ */ ++ if (ret < 0) ++ ret = -EIO; ++ else ++ ret = 1; ++ } ++ ++end: ++ spin_unlock_irqrestore(&pinfo->spinlock, flags); ++ ++ /* ++ * If everything went ok (i.e. 1 msg transmitted), (ret = 1) means return #bytes ++ * transmitted, else return error code. see i2c-core.c ++ */ ++ return ret; ++} ++ ++/* HI I2C READ * ++ * hi_i2c_master_recv - issue a single I2C message in master receive mode ++ * @client: Handle to slave device ++ * @buf: Where to store data read from slave ++ * @count: How many bytes to read, must be less than 64k since msg.len is u16 ++ * ++ * Returns negative errno, or else the number of bytes read. ++ */ ++int hi_i2c_master_recv(const struct i2c_client *client, char *buf, ++ int count) ++{ ++ struct i2c_adapter *adap = client->adapter; ++ struct i2c_msg msgs; ++ unsigned int reg_width, data_width, max_width; ++ int msgs_count; ++ ++ memset(&msgs, 0x0, sizeof(struct i2c_msg)); ++ msgs.addr = client->addr; ++ msgs.flags = client->flags; ++ msgs.flags |= I2C_M_RD; ++ ++ if (client->flags & I2C_M_16BIT_REG) ++ reg_width = 2; ++ else ++ reg_width = 1; ++ ++ if (client->flags & I2C_M_16BIT_DATA) ++ data_width = 2; ++ else ++ data_width = 1; ++ ++ max_width = max_t(size_t, reg_width, data_width); ++ ++ if (count > max_width) { ++ msgs.flags |= I2C_M_DMA; ++ msgs.len = count; ++ } else if (count <= 0 ) { ++ hi_err("ERR. Invalid count: 0x%d!!!\n", count); ++ return -EINVAL; ++ } else ++ msgs.len = max_width; ++ ++ if (!buf) { ++ hi_err("ERR. Invalid buf == NULL!!!\n"); ++ return -EINVAL; ++ } ++ msgs.buf = buf; ++ ++ msgs_count = hi_i2c_xfer(adap, &msgs, 1); ++ ++ return (msgs_count == 1) ? count : -EIO; ++} ++EXPORT_SYMBOL(hi_i2c_master_recv); ++ ++/*HI I2C WRITE* ++ * hi_i2c_master_send - issue a single I2C message in master transmit mode ++ * @client: Handle to slave device ++ * @buf: Data that will be written to the slave ++ * @count: How many bytes to write, must be less than 64k since msg.len is u16 ++ * ++ * Returns negative errno, or else the number of bytes written. ++ */ ++int hi_i2c_master_send(const struct i2c_client *client, ++ const char *buf, int count) ++{ ++ struct i2c_adapter *adap = client->adapter; ++ struct i2c_msg msgs; ++ unsigned int reg_width, data_width; ++ int msgs_count; ++ ++ memset(&msgs, 0x0, sizeof(struct i2c_msg)); ++ msgs.addr = client->addr; ++ msgs.flags = client->flags; ++ ++ if (client->flags & I2C_M_16BIT_REG) ++ reg_width = 2; ++ else ++ reg_width = 1; ++ ++ if (client->flags & I2C_M_16BIT_DATA) ++ data_width = 2; ++ else ++ data_width = 1; ++ ++ if (count - reg_width > data_width) ++ msgs.flags |= I2C_M_DMA; ++ else if (count - reg_width < data_width) { ++ hi_err("ERR. Invalid count!!!\n"); ++ return -EINVAL; ++ } ++ ++ msgs.len = count; ++ ++ if (!buf) { ++ hi_err("ERR. Invalid buf! == NULL!!\n"); ++ return -EINVAL; ++ } ++ msgs.buf = (__u8 *)buf; ++ ++ msgs_count = hi_i2c_xfer(adap, &msgs, 1); ++ ++ return (msgs_count == 1) ? count : -EIO; ++} ++EXPORT_SYMBOL(hi_i2c_master_send); ++ ++/** ++ * hi_i2c_transfer - execute a single or combined I2C message ++ * @adap: Handle to I2C bus ++ * @msgs: One or more messages to execute before STOP is issued to ++ * terminate the operation; each message begins with a START. ++ * @num: Number of messages to be executed. ++ * ++ * Returns negative errno, else the number of messages executed. ++ * ++ * Note that there is no requirement that each message be sent to ++ * the same slave address, although that is the most common model. ++ */ ++int hi_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ++ int num) ++{ ++ printk("Wrong interface call." ++ "hi_i2c_master_recv is the only interface to i2c read!!!\n"); ++ ++ return -EIO; ++} ++EXPORT_SYMBOL(hi_i2c_transfer); ++/**************************************************************/ ++ ++static u32 hi_i2c_func(struct i2c_adapter *adap) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static const struct i2c_algorithm hi_i2c_algo = { ++ .master_xfer = hi_i2c_xfer, ++ .functionality = hi_i2c_func, ++}; ++ ++static int hi_i2c_probe(struct platform_device *pdev) ++{ ++ int errorcode; ++ struct hi_i2c *pinfo; ++ struct i2c_adapter *adap; ++ struct resource *mem; ++ struct hi_platform_i2c *platform_info; ++ ++ platform_info = ++ (struct hi_platform_i2c *)pdev->dev.platform_data; ++ if (platform_info == NULL) { ++ dev_err(&pdev->dev, "%s: Can't get platform_data!\n", ++ __func__); ++ errorcode = -EPERM; ++ goto i2c_errorcode_na; ++ } ++ ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (mem == NULL) { ++ dev_err(&pdev->dev, "Get I2C mem resource failed!\n"); ++ errorcode = -ENXIO; ++ goto i2c_errorcode_na; ++ } ++ ++ pinfo = kzalloc(sizeof(struct hi_i2c), GFP_KERNEL); ++ if (pinfo == NULL) { ++ dev_err(&pdev->dev, "Out of memory!\n"); ++ errorcode = -ENOMEM; ++ goto i2c_errorcode_na; ++ } ++ ++ pinfo->regbase = (unsigned char __iomem *)IO_ADDRESS(mem->start); ++ pinfo->mem = mem; ++ pinfo->dev = &pdev->dev; ++ pinfo->pdata = platform_info; ++ pinfo->g_last_dev_addr = 0; ++ ++ spin_lock_init(&pinfo->spinlock); ++ ++ hi_i2c_hw_init(pinfo); ++ ++ platform_set_drvdata(pdev, pinfo); ++ ++ adap = &pinfo->adap; ++ i2c_set_adapdata(adap, pinfo); ++ adap->owner = THIS_MODULE; ++ adap->class = platform_info->i2c_class; ++ strlcpy(adap->name, pdev->name, sizeof(adap->name)); ++ adap->algo = &hi_i2c_algo; ++ adap->dev.parent = &pdev->dev; ++ adap->nr = pdev->id; ++ adap->retries = CONFIG_HI_I2C_RETRIES; ++ errorcode = i2c_add_numbered_adapter(adap); ++ if (errorcode) { ++ dev_err(&pdev->dev, ++ "%s: Adding I2C adapter failed!\n", __func__); ++ goto i2c_errorcode_free_irq; ++ } ++ ++ dev_notice(&pdev->dev, ++ "Hisilicon [%s] probed!\n", ++ dev_name(&pinfo->adap.dev)); ++ ++ goto i2c_errorcode_na; ++ ++i2c_errorcode_free_irq: ++ free_irq(pinfo->irq, pinfo); ++ kfree(pinfo); ++ ++i2c_errorcode_na: ++ return errorcode; ++} ++ ++static int hi_i2c_remove(struct platform_device *pdev) ++{ ++ struct hi_i2c *pinfo = NULL; ++ ++ pinfo = platform_get_drvdata(pdev); ++ ++ if (pinfo) { ++ i2c_del_adapter(&pinfo->adap); ++ ++ free_irq(pinfo->irq, pinfo); ++ ++ kfree(pinfo); ++ } ++ ++ dev_notice(&pdev->dev, ++ "Remove Hisilicon Media Processor" ++ "I2C adapter.\n"); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++static int hi_i2c_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ struct hi_i2c *pinfo; ++ ++ pinfo = platform_get_drvdata(pdev); ++ ++ hi_i2c_abortprocess(pinfo); ++ ++ return 0; ++} ++ ++static int hi_i2c_resume(struct platform_device *pdev) ++{ ++ struct hi_i2c *pinfo; ++ ++ pinfo = platform_get_drvdata(pdev); ++ ++ hi_i2c_hw_init(pinfo); ++ ++ return 0; ++} ++#else ++#define hi_i2c_suspend NULL ++#define hi_i2c_resume NULL ++#endif ++ ++static struct platform_driver hi_i2c_driver = { ++ .probe = hi_i2c_probe, ++ .remove = hi_i2c_remove, ++ .suspend = hi_i2c_suspend, ++ .resume = hi_i2c_resume, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = HI_I2C, ++ }, ++}; ++ ++#ifdef CONFIG_ARCH_HI3519 ++#include "i2c_hi3519.c" ++#endif ++#ifdef CONFIG_ARCH_HI3536C ++#include "i2c_hi3536c.c" ++#endif ++#ifdef CONFIG_ARCH_HI3531D ++#include "i2c_hi3531d.c" ++#endif ++#ifdef CONFIG_ARCH_HI3521D ++#include "i2c_hi3521d.c" ++#endif ++ ++module_init(hi_i2c_module_init); ++module_exit(hi_i2c_module_exit); ++ ++MODULE_DESCRIPTION("HISILICON I2C Bus driver"); ++MODULE_AUTHOR("BVT OSDRV"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/i2c/busses/i2c-hisilicon.h b/drivers/i2c/busses/i2c-hisilicon.h +new file mode 100644 +index 0000000..778fa1f +--- /dev/null ++++ b/drivers/i2c/busses/i2c-hisilicon.h +@@ -0,0 +1,108 @@ ++#ifndef __HI_I2C_H__ ++#define __HI_I2C_H__ ++ ++#define I2C_CON_REG 0x000 ++#define I2C_TAR_REG 0x004 ++#define I2C_DATA_CMD_REG 0x010 ++#define I2C_SCL_H_REG 0x01C ++#define I2C_SCL_L_REG 0x020 ++#define I2C_INTR_STAT_REG 0x02C ++#define I2C_INTR_MASK_REG 0x030 ++#define I2C_INTR_RAW_REG 0x034 ++#define I2C_RX_TL_REG 0x038 ++#define I2C_TX_TL_REG 0x03C ++#define I2C_CLR_INTR_REG 0x040 ++#define I2C_CLR_RX_OVER_REG 0x048 ++#define I2C_CLR_TX_OVER_REG 0x04C ++#define I2C_ENABLE_REG 0x06C ++#define I2C_STATUS_REG 0x070 ++#define I2C_TXFLR_REG 0x074 ++#define I2C_RXFLR_REG 0x078 ++#define I2C_SDA_HOLD_REG 0x07C ++#define I2C_TX_ABRT_SRC 0x080 ++#define I2C_DMA_CTRL_REG 0x088 ++#define I2C_DMA_TDLR 0x08C ++#define I2C_DMA_RDLR 0x090 ++#define I2C_LPIF_STATE 0x0A8 ++#define I2C_LOCK_REG 0x0AC ++#define I2C_AUTO_REG 0x0B0 ++#define I2C_TX_RX_REG 0x0B4 ++#define I2C_DMA_CMD0 0x0B8 ++#define I2C_DMA_CMD1 0x0BC ++#define I2C_DMA_CMD2 0x0C0 ++#define I2C_ENABLE_STATUS_REG 0x09C ++ ++#define HI_I2C_FAST_MODE 0x65 ++ ++#define HI_I2C_UNLOCK_VALUE 0x1ACCE551 ++ ++#define HI_I2C_ENABLE (1 << 0) ++ ++#define HI_I2C_AUTO_MODE_OFF 0x0f000000 ++ ++#define HI_I2C_WRITE 0x80000000 ++#define HI_I2C_READ 0xc0000000 ++ ++#define READ_OPERATION (1) ++#define WRITE_OPERATION 0xfe ++ ++#define CMD_I2C_WRITE 0x01 ++#define CMD_I2C_READ 0x03 ++ ++/* I2C_COM_REG */ ++#define I2C_SEND_ACK (~(1 << 4)) ++#define I2C_START (1 << 3) ++#define I2C_READ (1 << 2) ++#define I2C_WRITE (1 << 1) ++#define I2C_STOP (1 << 0) ++ ++/* I2C_ENABLE_REG */ ++#define I2C_ENABLE (1 << 0) ++ ++#define I2C_RAW_TX_ABORT (1 << 6) ++ ++/*I2C_INTR_STAT_REG */ ++#define I2C_AUTO_RX_FIFO_NOT_EMPTY (1 << 8) ++#define I2C_AUTO_TX_FIFO_EMPTRY (1 << 20) ++#define I2c_AUTO_TX_FIFO_NOT_FULL (1 << 21) ++#define I2C_TX_ABRT (1 << 23) ++#define I2C_AUTO_DATA (1 << 28) ++#define I2C_AUTO_ADDR (1 << 29) ++ ++/* I2C_STATUS */ ++#define I2C_STATUS_WORKING (1 << 0) ++ ++#define IS_TX_FIFO_EMPTY(status) (((status) &\ ++ I2C_AUTO_TX_FIFO_EMPTRY) == I2C_AUTO_TX_FIFO_EMPTRY) ++#define IS_RX_FIFO_EMPTY(status) (((status) &\ ++ I2C_AUTO_RX_FIFO_NOT_EMPTY) == 0) ++#define IS_FIFO_EMPTY(status) (IS_RX_FIFO_EMPTY(status) &&\ ++ IS_TX_FIFO_EMPTY(status)) ++#define IS_I2C_IDLE(status) (((status) & I2C_STATUS_WORKING) == 0) ++ ++#define REG_SHIFT 16 ++#define DATA_16BIT_MASK 0xFFFF ++#define DATA_8BIT_MASK 0xFFFF ++ ++#define REVERT_HL_BYTE(value) ((value >> 8) | ((value & 0xFF) << 8)) ++ ++/* ++ * I2C Interrupt related Macros ++ */ ++#define DEFAULT_I2C_REG_IMSC 0x0UL ++#define DISABLE_ALL_INTERRUPTS ((~DEFAULT_I2C_REG_IMSC) & 0xfff) ++#define ENABLE_ALL_INTERRUPTS DEFAULT_I2C_REG_IMSC ++ ++typedef enum i2c_mode_e { ++ I2C_MODE_AUTO, ++ I2C_MODE_DMA, ++ I2C_MODE_NONE, ++} i2c_mode_e; ++ ++struct hi_platform_i2c { ++ int clk_limit; ++ unsigned int i2c_class; ++ unsigned int clk_rate; ++}; ++ ++#endif +diff --git a/drivers/i2c/busses/i2c_hi3519.c b/drivers/i2c/busses/i2c_hi3519.c +new file mode 100644 +index 0000000..b15ae88 +--- /dev/null ++++ b/drivers/i2c/busses/i2c_hi3519.c +@@ -0,0 +1,147 @@ ++#include "i2c_hi3519.h" ++ ++unsigned int get_apb_clk(void) ++{ ++ unsigned int apb_clk; ++ ++ apb_clk = get_bus_clk() / 4; ++ ++ return apb_clk; ++} ++ ++static struct resource hi_i2c0_resources[] = { ++ [0] = { ++ .start = CONFIG_HI_I2C0_IO_BASE, ++ .end = CONFIG_HI_I2C0_IO_BASE ++ + CONFIG_HI_I2C0_IO_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++struct hi_platform_i2c hi_i2c0_platform_data = { ++ .clk_limit = CONFIG_HI_I2C0_CLK_LIMIT, ++ .i2c_class = I2C_CLASS_DDC, ++}; ++ ++struct platform_device hi_i2c0_device = { ++ .name = HI_I2C, ++ .id = 0, ++ .resource = hi_i2c0_resources, ++ .num_resources = ARRAY_SIZE(hi_i2c0_resources), ++ .dev = { ++ .platform_data = &hi_i2c0_platform_data, ++ } ++}; ++ ++static struct resource hi_i2c1_resources[] = { ++ [0] = { ++ .start = CONFIG_HI_I2C1_IO_BASE, ++ .end = CONFIG_HI_I2C1_IO_BASE ++ + CONFIG_HI_I2C1_IO_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++struct hi_platform_i2c hi_i2c1_platform_data = { ++ .clk_limit = CONFIG_HI_I2C1_CLK_LIMIT, ++ .i2c_class = I2C_CLASS_DDC, ++}; ++ ++struct platform_device hi_i2c1_device = { ++ .name = HI_I2C, ++ .id = 1, ++ .resource = hi_i2c1_resources, ++ .num_resources = ARRAY_SIZE(hi_i2c1_resources), ++ .dev = { ++ .platform_data = &hi_i2c1_platform_data, ++ } ++}; ++ ++static struct resource hi_i2c2_resources[] = { ++ [0] = { ++ .start = CONFIG_HI_I2C2_IO_BASE, ++ .end = CONFIG_HI_I2C2_IO_BASE ++ + CONFIG_HI_I2C2_IO_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++struct hi_platform_i2c hi_i2c2_platform_data = { ++ .clk_limit = CONFIG_HI_I2C2_CLK_LIMIT, ++ .i2c_class = I2C_CLASS_DDC, ++}; ++ ++struct platform_device hi_i2c2_device = { ++ .name = HI_I2C, ++ .id = 2, ++ .resource = hi_i2c2_resources, ++ .num_resources = ARRAY_SIZE(hi_i2c2_resources), ++ .dev = { ++ .platform_data = &hi_i2c2_platform_data, ++ } ++}; ++ ++static struct resource hi_i2c3_resources[] = { ++ [0] = { ++ .start = CONFIG_HI_I2C3_IO_BASE, ++ .end = CONFIG_HI_I2C3_IO_BASE ++ + CONFIG_HI_I2C3_IO_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++struct hi_platform_i2c hi_i2c3_platform_data = { ++ .clk_limit = CONFIG_HI_I2C3_CLK_LIMIT, ++ .i2c_class = I2C_CLASS_DDC, ++}; ++ ++struct platform_device hi_i2c3_device = { ++ .name = HI_I2C, ++ .id = 3, ++ .resource = hi_i2c3_resources, ++ .num_resources = ARRAY_SIZE(hi_i2c3_resources), ++ .dev = { ++ .platform_data = &hi_i2c3_platform_data, ++ } ++}; ++ ++static struct platform_device *hi_i2c_devices[] __initdata = { ++ &hi_i2c0_device, ++ &hi_i2c1_device, ++ &hi_i2c2_device, ++ &hi_i2c3_device, ++}; ++ ++static int __init hi_i2c_module_init(void) ++{ ++ int ret; ++ ++ ++ ret = platform_add_devices(hi_i2c_devices, ARRAY_SIZE(hi_i2c_devices)); ++ if (ret) { ++ hi_err("i2c device register failed!\n"); ++ return ret; ++ } ++ ++ ret = platform_driver_register(&hi_i2c_driver); ++ if (ret) { ++ platform_device_unregister(&hi_i2c3_device); ++ platform_device_unregister(&hi_i2c2_device); ++ platform_device_unregister(&hi_i2c1_device); ++ platform_device_unregister(&hi_i2c0_device); ++ hi_err("i2c driver register failed!\n"); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++static void __exit hi_i2c_module_exit(void) ++{ ++ platform_driver_unregister(&hi_i2c_driver); ++ ++ platform_device_unregister(&hi_i2c3_device); ++ platform_device_unregister(&hi_i2c2_device); ++ platform_device_unregister(&hi_i2c1_device); ++ platform_device_unregister(&hi_i2c0_device); ++} +diff --git a/drivers/i2c/busses/i2c_hi3519.h b/drivers/i2c/busses/i2c_hi3519.h +new file mode 100644 +index 0000000..898668e +--- /dev/null ++++ b/drivers/i2c/busses/i2c_hi3519.h +@@ -0,0 +1,12 @@ ++#include ++ ++#define CRG_REG_BASE 0x12010000 ++#define A7_AXI_SCALE_REG IO_ADDRESS(CRG_REG_BASE + 0x34) ++ ++#define get_bus_clk() ({\ ++ unsigned long tmp_reg, busclk = 0;\ ++ tmp_reg = readl((void *)A7_AXI_SCALE_REG);\ ++ if (0x1 == ((tmp_reg >> 12) & 0x3))\ ++ busclk = 200000000;\ ++ busclk;\ ++ }) +diff --git a/drivers/i2c/busses/i2c_hi3521d.c b/drivers/i2c/busses/i2c_hi3521d.c +new file mode 100644 +index 0000000..6223a41 +--- /dev/null ++++ b/drivers/i2c/busses/i2c_hi3521d.c +@@ -0,0 +1,66 @@ ++#include ++ ++unsigned int get_apb_clk(void) ++{ ++ unsigned int apb_clk; ++ ++ apb_clk = get_bus_clk() / CFG_TIMER_PER ; ++ ++ return apb_clk; ++} ++ ++static struct resource hi_i2c0_resources[] = { ++ [0] = { ++ .start = CONFIG_HI_I2C0_IO_BASE, ++ .end = CONFIG_HI_I2C0_IO_BASE ++ + CONFIG_HI_I2C0_IO_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++struct hi_platform_i2c hi_i2c0_platform_data = { ++ .clk_limit = CONFIG_HI_I2C0_CLK_LIMIT, ++ .i2c_class = I2C_CLASS_DDC, ++}; ++ ++struct platform_device hi_i2c0_device = { ++ .name = HI_I2C, ++ .id = 0, ++ .resource = hi_i2c0_resources, ++ .num_resources = ARRAY_SIZE(hi_i2c0_resources), ++ .dev = { ++ .platform_data = &hi_i2c0_platform_data, ++ } ++}; ++ ++static struct platform_device *hi_i2c_devices[] __initdata = { ++ &hi_i2c0_device, ++}; ++ ++static int __init hi_i2c_module_init(void) ++{ ++ int ret; ++ ++ ++ ret = platform_add_devices(hi_i2c_devices, ARRAY_SIZE(hi_i2c_devices)); ++ if (ret) { ++ hi_err("i2c device register failed!\n"); ++ return ret; ++ } ++ ++ ret = platform_driver_register(&hi_i2c_driver); ++ if (ret) { ++ platform_device_unregister(&hi_i2c0_device); ++ hi_err("i2c driver register failed!\n"); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++static void __exit hi_i2c_module_exit(void) ++{ ++ platform_driver_unregister(&hi_i2c_driver); ++ ++ platform_device_unregister(&hi_i2c0_device); ++} +diff --git a/drivers/i2c/busses/i2c_hi3531d.c b/drivers/i2c/busses/i2c_hi3531d.c +new file mode 100644 +index 0000000..fdabe84 +--- /dev/null ++++ b/drivers/i2c/busses/i2c_hi3531d.c +@@ -0,0 +1,93 @@ ++#include ++ ++unsigned int get_apb_clk(void) ++{ ++ unsigned int apb_clk; ++ ++ apb_clk = get_bus_clk() / CFG_TIMER_PER ; ++ ++ return apb_clk; ++} ++ ++static struct resource hi_i2c0_resources[] = { ++ [0] = { ++ .start = CONFIG_HI_I2C0_IO_BASE, ++ .end = CONFIG_HI_I2C0_IO_BASE ++ + CONFIG_HI_I2C0_IO_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++struct hi_platform_i2c hi_i2c0_platform_data = { ++ .clk_limit = CONFIG_HI_I2C0_CLK_LIMIT, ++ .i2c_class = I2C_CLASS_DDC, ++}; ++ ++struct platform_device hi_i2c0_device = { ++ .name = HI_I2C, ++ .id = 0, ++ .resource = hi_i2c0_resources, ++ .num_resources = ARRAY_SIZE(hi_i2c0_resources), ++ .dev = { ++ .platform_data = &hi_i2c0_platform_data, ++ } ++}; ++ ++static struct resource hi_i2c1_resources[] = { ++ [0] = { ++ .start = CONFIG_HI_I2C1_IO_BASE, ++ .end = CONFIG_HI_I2C1_IO_BASE ++ + CONFIG_HI_I2C1_IO_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++struct hi_platform_i2c hi_i2c1_platform_data = { ++ .clk_limit = CONFIG_HI_I2C1_CLK_LIMIT, ++ .i2c_class = I2C_CLASS_DDC, ++}; ++ ++struct platform_device hi_i2c1_device = { ++ .name = HI_I2C, ++ .id = 1, ++ .resource = hi_i2c1_resources, ++ .num_resources = ARRAY_SIZE(hi_i2c1_resources), ++ .dev = { ++ .platform_data = &hi_i2c1_platform_data, ++ } ++}; ++ ++static struct platform_device *hi_i2c_devices[] __initdata = { ++ &hi_i2c0_device, ++ &hi_i2c1_device, ++}; ++ ++static int __init hi_i2c_module_init(void) ++{ ++ int ret; ++ ++ ++ ret = platform_add_devices(hi_i2c_devices, ARRAY_SIZE(hi_i2c_devices)); ++ if (ret) { ++ hi_err("i2c device register failed!\n"); ++ return ret; ++ } ++ ++ ret = platform_driver_register(&hi_i2c_driver); ++ if (ret) { ++ platform_device_unregister(&hi_i2c1_device); ++ platform_device_unregister(&hi_i2c0_device); ++ hi_err("i2c driver register failed!\n"); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++static void __exit hi_i2c_module_exit(void) ++{ ++ platform_driver_unregister(&hi_i2c_driver); ++ ++ platform_device_unregister(&hi_i2c1_device); ++ platform_device_unregister(&hi_i2c0_device); ++} +diff --git a/drivers/i2c/busses/i2c_hi3536c.c b/drivers/i2c/busses/i2c_hi3536c.c +new file mode 100644 +index 0000000..6223a41 +--- /dev/null ++++ b/drivers/i2c/busses/i2c_hi3536c.c +@@ -0,0 +1,66 @@ ++#include ++ ++unsigned int get_apb_clk(void) ++{ ++ unsigned int apb_clk; ++ ++ apb_clk = get_bus_clk() / CFG_TIMER_PER ; ++ ++ return apb_clk; ++} ++ ++static struct resource hi_i2c0_resources[] = { ++ [0] = { ++ .start = CONFIG_HI_I2C0_IO_BASE, ++ .end = CONFIG_HI_I2C0_IO_BASE ++ + CONFIG_HI_I2C0_IO_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++struct hi_platform_i2c hi_i2c0_platform_data = { ++ .clk_limit = CONFIG_HI_I2C0_CLK_LIMIT, ++ .i2c_class = I2C_CLASS_DDC, ++}; ++ ++struct platform_device hi_i2c0_device = { ++ .name = HI_I2C, ++ .id = 0, ++ .resource = hi_i2c0_resources, ++ .num_resources = ARRAY_SIZE(hi_i2c0_resources), ++ .dev = { ++ .platform_data = &hi_i2c0_platform_data, ++ } ++}; ++ ++static struct platform_device *hi_i2c_devices[] __initdata = { ++ &hi_i2c0_device, ++}; ++ ++static int __init hi_i2c_module_init(void) ++{ ++ int ret; ++ ++ ++ ret = platform_add_devices(hi_i2c_devices, ARRAY_SIZE(hi_i2c_devices)); ++ if (ret) { ++ hi_err("i2c device register failed!\n"); ++ return ret; ++ } ++ ++ ret = platform_driver_register(&hi_i2c_driver); ++ if (ret) { ++ platform_device_unregister(&hi_i2c0_device); ++ hi_err("i2c driver register failed!\n"); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++static void __exit hi_i2c_module_exit(void) ++{ ++ platform_driver_unregister(&hi_i2c_driver); ++ ++ platform_device_unregister(&hi_i2c0_device); ++} +diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c +index 7bd1b5cf..b5ec010 100644 +--- a/drivers/i2c/i2c-core.c ++++ b/drivers/i2c/i2c-core.c +@@ -881,9 +881,14 @@ static int i2c_check_client_addr_validity(const struct i2c_client *client) + if (client->addr > 0x3ff) + return -EINVAL; + } else { ++#ifdef CONFIG_HI_I2C + /* 7-bit address, reject the general call address */ ++ if (client->addr == 0x00 || client->addr > 0xfe) ++ return -EINVAL; ++#else + if (client->addr == 0x00 || client->addr > 0x7f) + return -EINVAL; ++#endif + } + return 0; + } +@@ -2123,7 +2128,11 @@ int i2c_master_send(const struct i2c_client *client, const char *buf, int count) + struct i2c_msg msg; + + msg.addr = client->addr; ++#ifdef CONFIG_HI_I2C ++ msg.flags = client->flags; ++#else + msg.flags = client->flags & I2C_M_TEN; ++#endif + msg.len = count; + msg.buf = (char *)buf; + +@@ -2152,7 +2161,11 @@ int i2c_master_recv(const struct i2c_client *client, char *buf, int count) + int ret; + + msg.addr = client->addr; ++#ifdef CONFIG_HI_I2C ++ msg.flags = client->flags; ++#else + msg.flags = client->flags & I2C_M_TEN; ++#endif + msg.flags |= I2C_M_RD; + msg.len = count; + msg.buf = buf; +diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c +index 71c7a39..d9dd11c 100644 +--- a/drivers/i2c/i2c-dev.c ++++ b/drivers/i2c/i2c-dev.c +@@ -138,22 +138,69 @@ static ssize_t i2cdev_read(struct file *file, char __user *buf, size_t count, + { + char *tmp; + int ret; +- ++#ifdef CONFIG_HI_I2C ++ unsigned reg_width; ++ unsigned data_width; ++#endif + struct i2c_client *client = file->private_data; + + if (count > 8192) + count = 8192; + ++#ifdef CONFIG_HI_I2C ++ if (client->flags & I2C_M_16BIT_REG) ++ reg_width = 2; ++ else ++ reg_width = 1; ++ ++ if (client->flags & I2C_M_16BIT_DATA) ++ data_width = 2; ++ else ++ data_width = 1; ++ ++ if (client->flags & I2C_M_DMA) ++ tmp = kmalloc(max_t(size_t, reg_width, count), ++ GFP_KERNEL); ++ else ++ tmp = kmalloc(max_t(size_t, reg_width, data_width), ++ GFP_KERNEL); ++ ++ if (tmp == NULL) ++ return -ENOMEM; ++ ++ if (copy_from_user(tmp, buf, reg_width)) ++ return -EFAULT; ++#else + tmp = kmalloc(count, GFP_KERNEL); + if (tmp == NULL) + return -ENOMEM; ++#endif + + pr_debug("i2c-dev: i2c-%d reading %zu bytes.\n", + iminor(file_inode(file)), count); + ++#ifdef CONFIG_HI_I2C ++ if (client->flags & I2C_M_DMA) ++ ret = i2c_master_recv(client, tmp, ++ max_t(size_t, reg_width, count)); ++ else ++ ret = i2c_master_recv(client, tmp, ++ max_t(size_t, reg_width, data_width)); ++#else + ret = i2c_master_recv(client, tmp, count); ++#endif ++ ++#ifdef CONFIG_HI_I2C ++ if (ret >= 0) { ++ if (client->flags & I2C_M_DMA) ++ ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret; ++ else ++ ret = copy_to_user(buf, tmp, data_width) ? -EFAULT : ret; ++ } ++#else + if (ret >= 0) + ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret; ++#endif + kfree(tmp); + return ret; + } +@@ -168,6 +215,9 @@ static ssize_t i2cdev_write(struct file *file, const char __user *buf, + if (count > 8192) + count = 8192; + ++ if (count == 0) ++ return -EINVAL; ++ + tmp = memdup_user(buf, count); + if (IS_ERR(tmp)) + return PTR_ERR(tmp); +@@ -272,6 +322,11 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, + break; + } + ++ if (rdwr_pa[i].len == 0) { ++ res = -EINVAL; ++ break; ++ } ++ + data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; + rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len); + if (IS_ERR(rdwr_pa[i].buf)) { +@@ -431,8 +486,13 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + * the PEC flag already set, the i2c-dev driver won't see + * (or use) this setting. + */ ++#ifdef CONFIG_HI_I2C ++ if ((arg > 0x3ff) || ++ (((client->flags & I2C_M_TEN) == 0) && arg > 0xfe)) ++#else + if ((arg > 0x3ff) || + (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f)) ++#endif + return -EINVAL; + if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg)) + return -EBUSY; +@@ -451,6 +511,26 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + else + client->flags &= ~I2C_CLIENT_PEC; + return 0; ++#ifdef CONFIG_HI_I2C ++ case I2C_16BIT_REG: ++ if (arg) ++ client->flags |= I2C_M_16BIT_REG; ++ else ++ client->flags &= ~I2C_M_16BIT_REG; ++ return 0; ++ case I2C_16BIT_DATA: ++ if (arg) ++ client->flags |= I2C_M_16BIT_DATA; ++ else ++ client->flags &= ~I2C_M_16BIT_DATA; ++ return 0; ++ case I2C_DMA: ++ if (arg) ++ client->flags |= I2C_M_DMA; ++ else ++ client->flags &= ~I2C_M_DMA; ++ return 0; ++#endif + case I2C_FUNCS: + funcs = i2c_get_functionality(client->adapter); + return put_user(funcs, (unsigned long __user *)arg); +diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c +index 35c02ae..6da5492 100644 +--- a/drivers/iio/industrialio-event.c ++++ b/drivers/iio/industrialio-event.c +@@ -492,6 +492,7 @@ int iio_device_register_eventset(struct iio_dev *indio_dev) + + error_free_setup_event_lines: + iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list); ++ mutex_destroy(&indio_dev->event_interface->read_lock); + kfree(indio_dev->event_interface); + indio_dev->event_interface = NULL; + return ret; +@@ -517,5 +518,6 @@ void iio_device_unregister_eventset(struct iio_dev *indio_dev) + return; + iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list); + kfree(indio_dev->event_interface->group.attrs); ++ mutex_destroy(&indio_dev->event_interface->read_lock); + kfree(indio_dev->event_interface); + } +diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig +index a11ff74..518efa2 100644 +--- a/drivers/input/Kconfig ++++ b/drivers/input/Kconfig +@@ -174,6 +174,25 @@ config INPUT_APMPOWER + To compile this driver as a module, choose M here: the + module will be called apm-power. + ++config INPUT_KEYRESET ++ tristate "Reset key" ++ depends on INPUT ++ select INPUT_KEYCOMBO ++ ---help--- ++ Say Y here if you want to reboot when some keys are pressed; ++ ++ To compile this driver as a module, choose M here: the ++ module will be called keyreset. ++ ++config INPUT_KEYCOMBO ++ tristate "Key combo" ++ depends on INPUT ++ ---help--- ++ Say Y here if you want to take action when some keys are pressed; ++ ++ To compile this driver as a module, choose M here: the ++ module will be called keycombo. ++ + comment "Input Device Drivers" + + source "drivers/input/keyboard/Kconfig" +diff --git a/drivers/input/Makefile b/drivers/input/Makefile +index 5ca3f63..ee4c0652 100644 +--- a/drivers/input/Makefile ++++ b/drivers/input/Makefile +@@ -25,3 +25,6 @@ obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/ + obj-$(CONFIG_INPUT_MISC) += misc/ + + obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o ++obj-$(CONFIG_INPUT_KEYRESET) += keyreset.o ++obj-$(CONFIG_INPUT_KEYCOMBO) += keycombo.o ++ +diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c +index 8afa28e..738a2a3 100644 +--- a/drivers/input/evdev.c ++++ b/drivers/input/evdev.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include "input-compat.h" + + struct evdev { +@@ -46,6 +47,9 @@ struct evdev_client { + unsigned int tail; + unsigned int packet_head; /* [future] position of the first element of next packet */ + spinlock_t buffer_lock; /* protects access to buffer, head and tail */ ++ struct wake_lock wake_lock; ++ bool use_wake_lock; ++ char name[28]; + struct fasync_struct *fasync; + struct evdev *evdev; + struct list_head node; +@@ -149,10 +153,14 @@ static void __pass_event(struct evdev_client *client, + client->buffer[client->tail].value = 0; + + client->packet_head = client->tail; ++ if (client->use_wake_lock) ++ wake_unlock(&client->wake_lock); + } + + if (event->type == EV_SYN && event->code == SYN_REPORT) { + client->packet_head = client->head; ++ if (client->use_wake_lock) ++ wake_lock(&client->wake_lock); + kill_fasync(&client->fasync, SIGIO, POLL_IN); + } + } +@@ -371,6 +379,9 @@ static int evdev_release(struct inode *inode, struct file *file) + + evdev_detach_client(evdev, client); + ++ if (client->use_wake_lock) ++ wake_lock_destroy(&client->wake_lock); ++ + if (is_vmalloc_addr(client)) + vfree(client); + else +@@ -407,6 +418,8 @@ static int evdev_open(struct inode *inode, struct file *file) + + client->bufsize = bufsize; + spin_lock_init(&client->buffer_lock); ++ snprintf(client->name, sizeof(client->name), "%s-%d", ++ dev_name(&evdev->dev), task_tgid_vnr(current)); + client->evdev = evdev; + evdev_attach_client(evdev, client); + +@@ -473,6 +486,9 @@ static int evdev_fetch_next_event(struct evdev_client *client, + if (have_event) { + *event = client->buffer[client->tail++]; + client->tail &= client->bufsize - 1; ++ if (client->use_wake_lock && ++ client->packet_head == client->tail) ++ wake_unlock(&client->wake_lock); + } + + spin_unlock_irq(&client->buffer_lock); +@@ -795,6 +811,11 @@ static int evdev_handle_mt_request(struct input_dev *dev, + return 0; + } + ++/* ++ * HACK: disable conflicting EVIOCREVOKE until Android userspace stops using ++ * EVIOCSSUSPENDBLOCK ++ */ ++/* + static int evdev_revoke(struct evdev *evdev, struct evdev_client *client, + struct file *file) + { +@@ -805,6 +826,36 @@ static int evdev_revoke(struct evdev *evdev, struct evdev_client *client, + + return 0; + } ++*/ ++ ++static int evdev_enable_suspend_block(struct evdev *evdev, ++ struct evdev_client *client) ++{ ++ if (client->use_wake_lock) ++ return 0; ++ ++ spin_lock_irq(&client->buffer_lock); ++ wake_lock_init(&client->wake_lock, WAKE_LOCK_SUSPEND, client->name); ++ client->use_wake_lock = true; ++ if (client->packet_head != client->tail) ++ wake_lock(&client->wake_lock); ++ spin_unlock_irq(&client->buffer_lock); ++ return 0; ++} ++ ++static int evdev_disable_suspend_block(struct evdev *evdev, ++ struct evdev_client *client) ++{ ++ if (!client->use_wake_lock) ++ return 0; ++ ++ spin_lock_irq(&client->buffer_lock); ++ client->use_wake_lock = false; ++ wake_lock_destroy(&client->wake_lock); ++ spin_unlock_irq(&client->buffer_lock); ++ ++ return 0; ++} + + static long evdev_do_ioctl(struct file *file, unsigned int cmd, + void __user *p, int compat_mode) +@@ -868,12 +919,17 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, + else + return evdev_ungrab(evdev, client); + ++ /* ++ * HACK: disable conflicting EVIOCREVOKE until Android userspace stops ++ * using EVIOCSSUSPENDBLOCK ++ */ ++ /* + case EVIOCREVOKE: + if (p) + return -EINVAL; + else + return evdev_revoke(evdev, client, file); +- ++ */ + case EVIOCSCLOCKID: + if (copy_from_user(&i, p, sizeof(unsigned int))) + return -EFAULT; +@@ -893,6 +949,15 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, + + case EVIOCSKEYCODE_V2: + return evdev_handle_set_keycode_v2(dev, p); ++ ++ case EVIOCGSUSPENDBLOCK: ++ return put_user(client->use_wake_lock, ip); ++ ++ case EVIOCSSUSPENDBLOCK: ++ if (p) ++ return evdev_enable_suspend_block(evdev, client); ++ else ++ return evdev_disable_suspend_block(evdev, client); + } + + size = _IOC_SIZE(cmd); +diff --git a/drivers/input/keycombo.c b/drivers/input/keycombo.c +new file mode 100644 +index 0000000..2fba451 +--- /dev/null ++++ b/drivers/input/keycombo.c +@@ -0,0 +1,261 @@ ++/* drivers/input/keycombo.c ++ * ++ * Copyright (C) 2014 Google, 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. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct keycombo_state { ++ struct input_handler input_handler; ++ unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; ++ unsigned long upbit[BITS_TO_LONGS(KEY_CNT)]; ++ unsigned long key[BITS_TO_LONGS(KEY_CNT)]; ++ spinlock_t lock; ++ struct workqueue_struct *wq; ++ int key_down_target; ++ int key_down; ++ int key_up; ++ struct delayed_work key_down_work; ++ int delay; ++ struct work_struct key_up_work; ++ void (*key_up_fn)(void *); ++ void (*key_down_fn)(void *); ++ void *priv; ++ int key_is_down; ++ struct wakeup_source combo_held_wake_source; ++ struct wakeup_source combo_up_wake_source; ++}; ++ ++static void do_key_down(struct work_struct *work) ++{ ++ struct delayed_work *dwork = container_of(work, struct delayed_work, ++ work); ++ struct keycombo_state *state = container_of(dwork, ++ struct keycombo_state, key_down_work); ++ if (state->key_down_fn) ++ state->key_down_fn(state->priv); ++} ++ ++static void do_key_up(struct work_struct *work) ++{ ++ struct keycombo_state *state = container_of(work, struct keycombo_state, ++ key_up_work); ++ if (state->key_up_fn) ++ state->key_up_fn(state->priv); ++ __pm_relax(&state->combo_up_wake_source); ++} ++ ++static void keycombo_event(struct input_handle *handle, unsigned int type, ++ unsigned int code, int value) ++{ ++ unsigned long flags; ++ struct keycombo_state *state = handle->private; ++ ++ if (type != EV_KEY) ++ return; ++ ++ if (code >= KEY_MAX) ++ return; ++ ++ if (!test_bit(code, state->keybit)) ++ return; ++ ++ spin_lock_irqsave(&state->lock, flags); ++ if (!test_bit(code, state->key) == !value) ++ goto done; ++ __change_bit(code, state->key); ++ if (test_bit(code, state->upbit)) { ++ if (value) ++ state->key_up++; ++ else ++ state->key_up--; ++ } else { ++ if (value) ++ state->key_down++; ++ else ++ state->key_down--; ++ } ++ if (state->key_down == state->key_down_target && state->key_up == 0) { ++ __pm_stay_awake(&state->combo_held_wake_source); ++ state->key_is_down = 1; ++ if (queue_delayed_work(state->wq, &state->key_down_work, ++ state->delay)) ++ pr_debug("Key down work already queued!"); ++ } else if (state->key_is_down) { ++ if (!cancel_delayed_work(&state->key_down_work)) { ++ __pm_stay_awake(&state->combo_up_wake_source); ++ queue_work(state->wq, &state->key_up_work); ++ } ++ __pm_relax(&state->combo_held_wake_source); ++ state->key_is_down = 0; ++ } ++done: ++ spin_unlock_irqrestore(&state->lock, flags); ++} ++ ++static int keycombo_connect(struct input_handler *handler, ++ struct input_dev *dev, ++ const struct input_device_id *id) ++{ ++ int i; ++ int ret; ++ struct input_handle *handle; ++ struct keycombo_state *state = ++ container_of(handler, struct keycombo_state, input_handler); ++ for (i = 0; i < KEY_MAX; i++) { ++ if (test_bit(i, state->keybit) && test_bit(i, dev->keybit)) ++ break; ++ } ++ if (i == KEY_MAX) ++ return -ENODEV; ++ ++ handle = kzalloc(sizeof(*handle), GFP_KERNEL); ++ if (!handle) ++ return -ENOMEM; ++ ++ handle->dev = dev; ++ handle->handler = handler; ++ handle->name = KEYCOMBO_NAME; ++ handle->private = state; ++ ++ ret = input_register_handle(handle); ++ if (ret) ++ goto err_input_register_handle; ++ ++ ret = input_open_device(handle); ++ if (ret) ++ goto err_input_open_device; ++ ++ return 0; ++ ++err_input_open_device: ++ input_unregister_handle(handle); ++err_input_register_handle: ++ kfree(handle); ++ return ret; ++} ++ ++static void keycombo_disconnect(struct input_handle *handle) ++{ ++ input_close_device(handle); ++ input_unregister_handle(handle); ++ kfree(handle); ++} ++ ++static const struct input_device_id keycombo_ids[] = { ++ { ++ .flags = INPUT_DEVICE_ID_MATCH_EVBIT, ++ .evbit = { BIT_MASK(EV_KEY) }, ++ }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(input, keycombo_ids); ++ ++static int keycombo_probe(struct platform_device *pdev) ++{ ++ int ret; ++ int key, *keyp; ++ struct keycombo_state *state; ++ struct keycombo_platform_data *pdata = pdev->dev.platform_data; ++ ++ if (!pdata) ++ return -EINVAL; ++ ++ state = kzalloc(sizeof(*state), GFP_KERNEL); ++ if (!state) ++ return -ENOMEM; ++ ++ spin_lock_init(&state->lock); ++ keyp = pdata->keys_down; ++ while ((key = *keyp++)) { ++ if (key >= KEY_MAX) ++ continue; ++ state->key_down_target++; ++ __set_bit(key, state->keybit); ++ } ++ if (pdata->keys_up) { ++ keyp = pdata->keys_up; ++ while ((key = *keyp++)) { ++ if (key >= KEY_MAX) ++ continue; ++ __set_bit(key, state->keybit); ++ __set_bit(key, state->upbit); ++ } ++ } ++ ++ state->wq = alloc_ordered_workqueue("keycombo", 0); ++ if (!state->wq) ++ return -ENOMEM; ++ ++ state->priv = pdata->priv; ++ ++ if (pdata->key_down_fn) ++ state->key_down_fn = pdata->key_down_fn; ++ INIT_DELAYED_WORK(&state->key_down_work, do_key_down); ++ ++ if (pdata->key_up_fn) ++ state->key_up_fn = pdata->key_up_fn; ++ INIT_WORK(&state->key_up_work, do_key_up); ++ ++ wakeup_source_init(&state->combo_held_wake_source, "key combo"); ++ wakeup_source_init(&state->combo_up_wake_source, "key combo up"); ++ state->delay = msecs_to_jiffies(pdata->key_down_delay); ++ ++ state->input_handler.event = keycombo_event; ++ state->input_handler.connect = keycombo_connect; ++ state->input_handler.disconnect = keycombo_disconnect; ++ state->input_handler.name = KEYCOMBO_NAME; ++ state->input_handler.id_table = keycombo_ids; ++ ret = input_register_handler(&state->input_handler); ++ if (ret) { ++ kfree(state); ++ return ret; ++ } ++ platform_set_drvdata(pdev, state); ++ return 0; ++} ++ ++int keycombo_remove(struct platform_device *pdev) ++{ ++ struct keycombo_state *state = platform_get_drvdata(pdev); ++ input_unregister_handler(&state->input_handler); ++ destroy_workqueue(state->wq); ++ kfree(state); ++ return 0; ++} ++ ++ ++struct platform_driver keycombo_driver = { ++ .driver.name = KEYCOMBO_NAME, ++ .probe = keycombo_probe, ++ .remove = keycombo_remove, ++}; ++ ++static int __init keycombo_init(void) ++{ ++ return platform_driver_register(&keycombo_driver); ++} ++ ++static void __exit keycombo_exit(void) ++{ ++ return platform_driver_unregister(&keycombo_driver); ++} ++ ++module_init(keycombo_init); ++module_exit(keycombo_exit); +diff --git a/drivers/input/keyreset.c b/drivers/input/keyreset.c +new file mode 100644 +index 0000000..7fbf724 +--- /dev/null ++++ b/drivers/input/keyreset.c +@@ -0,0 +1,145 @@ ++/* drivers/input/keyreset.c ++ * ++ * Copyright (C) 2014 Google, 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. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct keyreset_state { ++ int restart_requested; ++ int (*reset_fn)(void); ++ struct platform_device *pdev_child; ++ struct work_struct restart_work; ++}; ++ ++static void do_restart(struct work_struct *unused) ++{ ++ sys_sync(); ++ kernel_restart(NULL); ++} ++ ++static void do_reset_fn(void *priv) ++{ ++ struct keyreset_state *state = priv; ++ if (state->restart_requested) ++ panic("keyboard reset failed, %d", state->restart_requested); ++ if (state->reset_fn) { ++ state->restart_requested = state->reset_fn(); ++ } else { ++ pr_info("keyboard reset\n"); ++ schedule_work(&state->restart_work); ++ state->restart_requested = 1; ++ } ++} ++ ++static int keyreset_probe(struct platform_device *pdev) ++{ ++ int ret = -ENOMEM; ++ struct keycombo_platform_data *pdata_child; ++ struct keyreset_platform_data *pdata = pdev->dev.platform_data; ++ int up_size = 0, down_size = 0, size; ++ int key, *keyp; ++ struct keyreset_state *state; ++ ++ if (!pdata) ++ return -EINVAL; ++ state = devm_kzalloc(&pdev->dev, sizeof(*state), GFP_KERNEL); ++ if (!state) ++ return -ENOMEM; ++ ++ state->pdev_child = platform_device_alloc(KEYCOMBO_NAME, ++ PLATFORM_DEVID_AUTO); ++ if (!state->pdev_child) ++ return -ENOMEM; ++ state->pdev_child->dev.parent = &pdev->dev; ++ INIT_WORK(&state->restart_work, do_restart); ++ ++ keyp = pdata->keys_down; ++ while ((key = *keyp++)) { ++ if (key >= KEY_MAX) ++ continue; ++ down_size++; ++ } ++ if (pdata->keys_up) { ++ keyp = pdata->keys_up; ++ while ((key = *keyp++)) { ++ if (key >= KEY_MAX) ++ continue; ++ up_size++; ++ } ++ } ++ size = sizeof(struct keycombo_platform_data) ++ + sizeof(int) * (down_size + 1); ++ pdata_child = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); ++ if (!pdata_child) ++ goto error; ++ memcpy(pdata_child->keys_down, pdata->keys_down, ++ sizeof(int) * down_size); ++ if (up_size > 0) { ++ pdata_child->keys_up = devm_kzalloc(&pdev->dev, up_size + 1, ++ GFP_KERNEL); ++ if (!pdata_child->keys_up) ++ goto error; ++ memcpy(pdata_child->keys_up, pdata->keys_up, ++ sizeof(int) * up_size); ++ if (!pdata_child->keys_up) ++ goto error; ++ } ++ state->reset_fn = pdata->reset_fn; ++ pdata_child->key_down_fn = do_reset_fn; ++ pdata_child->priv = state; ++ pdata_child->key_down_delay = pdata->key_down_delay; ++ ret = platform_device_add_data(state->pdev_child, pdata_child, size); ++ if (ret) ++ goto error; ++ platform_set_drvdata(pdev, state); ++ return platform_device_add(state->pdev_child); ++error: ++ platform_device_put(state->pdev_child); ++ return ret; ++} ++ ++int keyreset_remove(struct platform_device *pdev) ++{ ++ struct keyreset_state *state = platform_get_drvdata(pdev); ++ platform_device_put(state->pdev_child); ++ return 0; ++} ++ ++ ++struct platform_driver keyreset_driver = { ++ .driver.name = KEYRESET_NAME, ++ .probe = keyreset_probe, ++ .remove = keyreset_remove, ++}; ++ ++static int __init keyreset_init(void) ++{ ++ return platform_driver_register(&keyreset_driver); ++} ++ ++static void __exit keyreset_exit(void) ++{ ++ return platform_driver_unregister(&keyreset_driver); ++} ++ ++module_init(keyreset_init); ++module_exit(keyreset_exit); +diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig +index 23297ab..838824b 100644 +--- a/drivers/input/misc/Kconfig ++++ b/drivers/input/misc/Kconfig +@@ -319,6 +319,17 @@ config INPUT_ATI_REMOTE2 + To compile this driver as a module, choose M here: the module will be + called ati_remote2. + ++config INPUT_KEYCHORD ++ tristate "Key chord input driver support" ++ help ++ Say Y here if you want to enable the key chord driver ++ accessible at /dev/keychord. This driver can be used ++ for receiving notifications when client specified key ++ combinations are pressed. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called keychord. ++ + config INPUT_KEYSPAN_REMOTE + tristate "Keyspan DMR USB remote control" + depends on USB_ARCH_HAS_HCD +@@ -454,6 +465,11 @@ config INPUT_SGI_BTNS + To compile this driver as a module, choose M here: the + module will be called sgi_btns. + ++config INPUT_GPIO ++ tristate "GPIO driver support" ++ help ++ Say Y here if you want to support gpio based keys, wheels etc... ++ + config HP_SDC_RTC + tristate "HP SDC Real Time Clock" + depends on (GSC || HP300) && SERIO +diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile +index 19c7603..f77268e 100644 +--- a/drivers/input/misc/Makefile ++++ b/drivers/input/misc/Makefile +@@ -31,9 +31,11 @@ obj-$(CONFIG_INPUT_DRV2667_HAPTICS) += drv2667.o + obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o + obj-$(CONFIG_INPUT_GPIO_BEEPER) += gpio-beeper.o + obj-$(CONFIG_INPUT_GPIO_TILT_POLLED) += gpio_tilt_polled.o ++obj-$(CONFIG_INPUT_GPIO) += gpio_event.o gpio_matrix.o gpio_input.o gpio_output.o gpio_axis.o + obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o + obj-$(CONFIG_INPUT_IMS_PCU) += ims-pcu.o + obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o ++obj-$(CONFIG_INPUT_KEYCHORD) += keychord.o + obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o + obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o + obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o +diff --git a/drivers/input/misc/gpio_axis.c b/drivers/input/misc/gpio_axis.c +new file mode 100644 +index 0000000..0acf4a5 +--- /dev/null ++++ b/drivers/input/misc/gpio_axis.c +@@ -0,0 +1,192 @@ ++/* drivers/input/misc/gpio_axis.c ++ * ++ * Copyright (C) 2007 Google, 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. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++struct gpio_axis_state { ++ struct gpio_event_input_devs *input_devs; ++ struct gpio_event_axis_info *info; ++ uint32_t pos; ++}; ++ ++uint16_t gpio_axis_4bit_gray_map_table[] = { ++ [0x0] = 0x0, [0x1] = 0x1, /* 0000 0001 */ ++ [0x3] = 0x2, [0x2] = 0x3, /* 0011 0010 */ ++ [0x6] = 0x4, [0x7] = 0x5, /* 0110 0111 */ ++ [0x5] = 0x6, [0x4] = 0x7, /* 0101 0100 */ ++ [0xc] = 0x8, [0xd] = 0x9, /* 1100 1101 */ ++ [0xf] = 0xa, [0xe] = 0xb, /* 1111 1110 */ ++ [0xa] = 0xc, [0xb] = 0xd, /* 1010 1011 */ ++ [0x9] = 0xe, [0x8] = 0xf, /* 1001 1000 */ ++}; ++uint16_t gpio_axis_4bit_gray_map(struct gpio_event_axis_info *info, uint16_t in) ++{ ++ return gpio_axis_4bit_gray_map_table[in]; ++} ++ ++uint16_t gpio_axis_5bit_singletrack_map_table[] = { ++ [0x10] = 0x00, [0x14] = 0x01, [0x1c] = 0x02, /* 10000 10100 11100 */ ++ [0x1e] = 0x03, [0x1a] = 0x04, [0x18] = 0x05, /* 11110 11010 11000 */ ++ [0x08] = 0x06, [0x0a] = 0x07, [0x0e] = 0x08, /* 01000 01010 01110 */ ++ [0x0f] = 0x09, [0x0d] = 0x0a, [0x0c] = 0x0b, /* 01111 01101 01100 */ ++ [0x04] = 0x0c, [0x05] = 0x0d, [0x07] = 0x0e, /* 00100 00101 00111 */ ++ [0x17] = 0x0f, [0x16] = 0x10, [0x06] = 0x11, /* 10111 10110 00110 */ ++ [0x02] = 0x12, [0x12] = 0x13, [0x13] = 0x14, /* 00010 10010 10011 */ ++ [0x1b] = 0x15, [0x0b] = 0x16, [0x03] = 0x17, /* 11011 01011 00011 */ ++ [0x01] = 0x18, [0x09] = 0x19, [0x19] = 0x1a, /* 00001 01001 11001 */ ++ [0x1d] = 0x1b, [0x15] = 0x1c, [0x11] = 0x1d, /* 11101 10101 10001 */ ++}; ++uint16_t gpio_axis_5bit_singletrack_map( ++ struct gpio_event_axis_info *info, uint16_t in) ++{ ++ return gpio_axis_5bit_singletrack_map_table[in]; ++} ++ ++static void gpio_event_update_axis(struct gpio_axis_state *as, int report) ++{ ++ struct gpio_event_axis_info *ai = as->info; ++ int i; ++ int change; ++ uint16_t state = 0; ++ uint16_t pos; ++ uint16_t old_pos = as->pos; ++ for (i = ai->count - 1; i >= 0; i--) ++ state = (state << 1) | gpio_get_value(ai->gpio[i]); ++ pos = ai->map(ai, state); ++ if (ai->flags & GPIOEAF_PRINT_RAW) ++ pr_info("axis %d-%d raw %x, pos %d -> %d\n", ++ ai->type, ai->code, state, old_pos, pos); ++ if (report && pos != old_pos) { ++ if (ai->type == EV_REL) { ++ change = (ai->decoded_size + pos - old_pos) % ++ ai->decoded_size; ++ if (change > ai->decoded_size / 2) ++ change -= ai->decoded_size; ++ if (change == ai->decoded_size / 2) { ++ if (ai->flags & GPIOEAF_PRINT_EVENT) ++ pr_info("axis %d-%d unknown direction, " ++ "pos %d -> %d\n", ai->type, ++ ai->code, old_pos, pos); ++ change = 0; /* no closest direction */ ++ } ++ if (ai->flags & GPIOEAF_PRINT_EVENT) ++ pr_info("axis %d-%d change %d\n", ++ ai->type, ai->code, change); ++ input_report_rel(as->input_devs->dev[ai->dev], ++ ai->code, change); ++ } else { ++ if (ai->flags & GPIOEAF_PRINT_EVENT) ++ pr_info("axis %d-%d now %d\n", ++ ai->type, ai->code, pos); ++ input_event(as->input_devs->dev[ai->dev], ++ ai->type, ai->code, pos); ++ } ++ input_sync(as->input_devs->dev[ai->dev]); ++ } ++ as->pos = pos; ++} ++ ++static irqreturn_t gpio_axis_irq_handler(int irq, void *dev_id) ++{ ++ struct gpio_axis_state *as = dev_id; ++ gpio_event_update_axis(as, 1); ++ return IRQ_HANDLED; ++} ++ ++int gpio_event_axis_func(struct gpio_event_input_devs *input_devs, ++ struct gpio_event_info *info, void **data, int func) ++{ ++ int ret; ++ int i; ++ int irq; ++ struct gpio_event_axis_info *ai; ++ struct gpio_axis_state *as; ++ ++ ai = container_of(info, struct gpio_event_axis_info, info); ++ if (func == GPIO_EVENT_FUNC_SUSPEND) { ++ for (i = 0; i < ai->count; i++) ++ disable_irq(gpio_to_irq(ai->gpio[i])); ++ return 0; ++ } ++ if (func == GPIO_EVENT_FUNC_RESUME) { ++ for (i = 0; i < ai->count; i++) ++ enable_irq(gpio_to_irq(ai->gpio[i])); ++ return 0; ++ } ++ ++ if (func == GPIO_EVENT_FUNC_INIT) { ++ *data = as = kmalloc(sizeof(*as), GFP_KERNEL); ++ if (as == NULL) { ++ ret = -ENOMEM; ++ goto err_alloc_axis_state_failed; ++ } ++ as->input_devs = input_devs; ++ as->info = ai; ++ if (ai->dev >= input_devs->count) { ++ pr_err("gpio_event_axis: bad device index %d >= %d " ++ "for %d:%d\n", ai->dev, input_devs->count, ++ ai->type, ai->code); ++ ret = -EINVAL; ++ goto err_bad_device_index; ++ } ++ ++ input_set_capability(input_devs->dev[ai->dev], ++ ai->type, ai->code); ++ if (ai->type == EV_ABS) { ++ input_set_abs_params(input_devs->dev[ai->dev], ai->code, ++ 0, ai->decoded_size - 1, 0, 0); ++ } ++ for (i = 0; i < ai->count; i++) { ++ ret = gpio_request(ai->gpio[i], "gpio_event_axis"); ++ if (ret < 0) ++ goto err_request_gpio_failed; ++ ret = gpio_direction_input(ai->gpio[i]); ++ if (ret < 0) ++ goto err_gpio_direction_input_failed; ++ ret = irq = gpio_to_irq(ai->gpio[i]); ++ if (ret < 0) ++ goto err_get_irq_num_failed; ++ ret = request_irq(irq, gpio_axis_irq_handler, ++ IRQF_TRIGGER_RISING | ++ IRQF_TRIGGER_FALLING, ++ "gpio_event_axis", as); ++ if (ret < 0) ++ goto err_request_irq_failed; ++ } ++ gpio_event_update_axis(as, 0); ++ return 0; ++ } ++ ++ ret = 0; ++ as = *data; ++ for (i = ai->count - 1; i >= 0; i--) { ++ free_irq(gpio_to_irq(ai->gpio[i]), as); ++err_request_irq_failed: ++err_get_irq_num_failed: ++err_gpio_direction_input_failed: ++ gpio_free(ai->gpio[i]); ++err_request_gpio_failed: ++ ; ++ } ++err_bad_device_index: ++ kfree(as); ++ *data = NULL; ++err_alloc_axis_state_failed: ++ return ret; ++} +diff --git a/drivers/input/misc/gpio_event.c b/drivers/input/misc/gpio_event.c +new file mode 100644 +index 0000000..90f07eb +--- /dev/null ++++ b/drivers/input/misc/gpio_event.c +@@ -0,0 +1,228 @@ ++/* drivers/input/misc/gpio_event.c ++ * ++ * Copyright (C) 2007 Google, 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. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct gpio_event { ++ struct gpio_event_input_devs *input_devs; ++ const struct gpio_event_platform_data *info; ++ void *state[0]; ++}; ++ ++static int gpio_input_event( ++ struct input_dev *dev, unsigned int type, unsigned int code, int value) ++{ ++ int i; ++ int devnr; ++ int ret = 0; ++ int tmp_ret; ++ struct gpio_event_info **ii; ++ struct gpio_event *ip = input_get_drvdata(dev); ++ ++ for (devnr = 0; devnr < ip->input_devs->count; devnr++) ++ if (ip->input_devs->dev[devnr] == dev) ++ break; ++ if (devnr == ip->input_devs->count) { ++ pr_err("gpio_input_event: unknown device %p\n", dev); ++ return -EIO; ++ } ++ ++ for (i = 0, ii = ip->info->info; i < ip->info->info_count; i++, ii++) { ++ if ((*ii)->event) { ++ tmp_ret = (*ii)->event(ip->input_devs, *ii, ++ &ip->state[i], ++ devnr, type, code, value); ++ if (tmp_ret) ++ ret = tmp_ret; ++ } ++ } ++ return ret; ++} ++ ++static int gpio_event_call_all_func(struct gpio_event *ip, int func) ++{ ++ int i; ++ int ret; ++ struct gpio_event_info **ii; ++ ++ if (func == GPIO_EVENT_FUNC_INIT || func == GPIO_EVENT_FUNC_RESUME) { ++ ii = ip->info->info; ++ for (i = 0; i < ip->info->info_count; i++, ii++) { ++ if ((*ii)->func == NULL) { ++ ret = -ENODEV; ++ pr_err("gpio_event_probe: Incomplete pdata, " ++ "no function\n"); ++ goto err_no_func; ++ } ++ if (func == GPIO_EVENT_FUNC_RESUME && (*ii)->no_suspend) ++ continue; ++ ret = (*ii)->func(ip->input_devs, *ii, &ip->state[i], ++ func); ++ if (ret) { ++ pr_err("gpio_event_probe: function failed\n"); ++ goto err_func_failed; ++ } ++ } ++ return 0; ++ } ++ ++ ret = 0; ++ i = ip->info->info_count; ++ ii = ip->info->info + i; ++ while (i > 0) { ++ i--; ++ ii--; ++ if ((func & ~1) == GPIO_EVENT_FUNC_SUSPEND && (*ii)->no_suspend) ++ continue; ++ (*ii)->func(ip->input_devs, *ii, &ip->state[i], func & ~1); ++err_func_failed: ++err_no_func: ++ ; ++ } ++ return ret; ++} ++ ++static void __maybe_unused gpio_event_suspend(struct gpio_event *ip) ++{ ++ gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_SUSPEND); ++ if (ip->info->power) ++ ip->info->power(ip->info, 0); ++} ++ ++static void __maybe_unused gpio_event_resume(struct gpio_event *ip) ++{ ++ if (ip->info->power) ++ ip->info->power(ip->info, 1); ++ gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_RESUME); ++} ++ ++static int gpio_event_probe(struct platform_device *pdev) ++{ ++ int err; ++ struct gpio_event *ip; ++ struct gpio_event_platform_data *event_info; ++ int dev_count = 1; ++ int i; ++ int registered = 0; ++ ++ event_info = pdev->dev.platform_data; ++ if (event_info == NULL) { ++ pr_err("gpio_event_probe: No pdata\n"); ++ return -ENODEV; ++ } ++ if ((!event_info->name && !event_info->names[0]) || ++ !event_info->info || !event_info->info_count) { ++ pr_err("gpio_event_probe: Incomplete pdata\n"); ++ return -ENODEV; ++ } ++ if (!event_info->name) ++ while (event_info->names[dev_count]) ++ dev_count++; ++ ip = kzalloc(sizeof(*ip) + ++ sizeof(ip->state[0]) * event_info->info_count + ++ sizeof(*ip->input_devs) + ++ sizeof(ip->input_devs->dev[0]) * dev_count, GFP_KERNEL); ++ if (ip == NULL) { ++ err = -ENOMEM; ++ pr_err("gpio_event_probe: Failed to allocate private data\n"); ++ goto err_kp_alloc_failed; ++ } ++ ip->input_devs = (void*)&ip->state[event_info->info_count]; ++ platform_set_drvdata(pdev, ip); ++ ++ for (i = 0; i < dev_count; i++) { ++ struct input_dev *input_dev = input_allocate_device(); ++ if (input_dev == NULL) { ++ err = -ENOMEM; ++ pr_err("gpio_event_probe: " ++ "Failed to allocate input device\n"); ++ goto err_input_dev_alloc_failed; ++ } ++ input_set_drvdata(input_dev, ip); ++ input_dev->name = event_info->name ? ++ event_info->name : event_info->names[i]; ++ input_dev->event = gpio_input_event; ++ ip->input_devs->dev[i] = input_dev; ++ } ++ ip->input_devs->count = dev_count; ++ ip->info = event_info; ++ if (event_info->power) ++ ip->info->power(ip->info, 1); ++ ++ err = gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_INIT); ++ if (err) ++ goto err_call_all_func_failed; ++ ++ for (i = 0; i < dev_count; i++) { ++ err = input_register_device(ip->input_devs->dev[i]); ++ if (err) { ++ pr_err("gpio_event_probe: Unable to register %s " ++ "input device\n", ip->input_devs->dev[i]->name); ++ goto err_input_register_device_failed; ++ } ++ registered++; ++ } ++ ++ return 0; ++ ++err_input_register_device_failed: ++ gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_UNINIT); ++err_call_all_func_failed: ++ if (event_info->power) ++ ip->info->power(ip->info, 0); ++ for (i = 0; i < registered; i++) ++ input_unregister_device(ip->input_devs->dev[i]); ++ for (i = dev_count - 1; i >= registered; i--) { ++ input_free_device(ip->input_devs->dev[i]); ++err_input_dev_alloc_failed: ++ ; ++ } ++ kfree(ip); ++err_kp_alloc_failed: ++ return err; ++} ++ ++static int gpio_event_remove(struct platform_device *pdev) ++{ ++ struct gpio_event *ip = platform_get_drvdata(pdev); ++ int i; ++ ++ gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_UNINIT); ++ if (ip->info->power) ++ ip->info->power(ip->info, 0); ++ for (i = 0; i < ip->input_devs->count; i++) ++ input_unregister_device(ip->input_devs->dev[i]); ++ kfree(ip); ++ return 0; ++} ++ ++static struct platform_driver gpio_event_driver = { ++ .probe = gpio_event_probe, ++ .remove = gpio_event_remove, ++ .driver = { ++ .name = GPIO_EVENT_DEV_NAME, ++ }, ++}; ++ ++module_platform_driver(gpio_event_driver); ++ ++MODULE_DESCRIPTION("GPIO Event Driver"); ++MODULE_LICENSE("GPL"); ++ +diff --git a/drivers/input/misc/gpio_input.c b/drivers/input/misc/gpio_input.c +new file mode 100644 +index 0000000..eefd027 +--- /dev/null ++++ b/drivers/input/misc/gpio_input.c +@@ -0,0 +1,390 @@ ++/* drivers/input/misc/gpio_input.c ++ * ++ * Copyright (C) 2007 Google, 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. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++enum { ++ DEBOUNCE_UNSTABLE = BIT(0), /* Got irq, while debouncing */ ++ DEBOUNCE_PRESSED = BIT(1), ++ DEBOUNCE_NOTPRESSED = BIT(2), ++ DEBOUNCE_WAIT_IRQ = BIT(3), /* Stable irq state */ ++ DEBOUNCE_POLL = BIT(4), /* Stable polling state */ ++ ++ DEBOUNCE_UNKNOWN = ++ DEBOUNCE_PRESSED | DEBOUNCE_NOTPRESSED, ++}; ++ ++struct gpio_key_state { ++ struct gpio_input_state *ds; ++ uint8_t debounce; ++}; ++ ++struct gpio_input_state { ++ struct gpio_event_input_devs *input_devs; ++ const struct gpio_event_input_info *info; ++ struct hrtimer timer; ++ int use_irq; ++ int debounce_count; ++ spinlock_t irq_lock; ++ struct wakeup_source *ws; ++ struct gpio_key_state key_state[0]; ++}; ++ ++static enum hrtimer_restart gpio_event_input_timer_func(struct hrtimer *timer) ++{ ++ int i; ++ int pressed; ++ struct gpio_input_state *ds = ++ container_of(timer, struct gpio_input_state, timer); ++ unsigned gpio_flags = ds->info->flags; ++ unsigned npolarity; ++ int nkeys = ds->info->keymap_size; ++ const struct gpio_event_direct_entry *key_entry; ++ struct gpio_key_state *key_state; ++ unsigned long irqflags; ++ uint8_t debounce; ++ bool sync_needed; ++ ++#if 0 ++ key_entry = kp->keys_info->keymap; ++ key_state = kp->key_state; ++ for (i = 0; i < nkeys; i++, key_entry++, key_state++) ++ pr_info("gpio_read_detect_status %d %d\n", key_entry->gpio, ++ gpio_read_detect_status(key_entry->gpio)); ++#endif ++ key_entry = ds->info->keymap; ++ key_state = ds->key_state; ++ sync_needed = false; ++ spin_lock_irqsave(&ds->irq_lock, irqflags); ++ for (i = 0; i < nkeys; i++, key_entry++, key_state++) { ++ debounce = key_state->debounce; ++ if (debounce & DEBOUNCE_WAIT_IRQ) ++ continue; ++ if (key_state->debounce & DEBOUNCE_UNSTABLE) { ++ debounce = key_state->debounce = DEBOUNCE_UNKNOWN; ++ enable_irq(gpio_to_irq(key_entry->gpio)); ++ if (gpio_flags & GPIOEDF_PRINT_KEY_UNSTABLE) ++ pr_info("gpio_keys_scan_keys: key %x-%x, %d " ++ "(%d) continue debounce\n", ++ ds->info->type, key_entry->code, ++ i, key_entry->gpio); ++ } ++ npolarity = !(gpio_flags & GPIOEDF_ACTIVE_HIGH); ++ pressed = gpio_get_value(key_entry->gpio) ^ npolarity; ++ if (debounce & DEBOUNCE_POLL) { ++ if (pressed == !(debounce & DEBOUNCE_PRESSED)) { ++ ds->debounce_count++; ++ key_state->debounce = DEBOUNCE_UNKNOWN; ++ if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE) ++ pr_info("gpio_keys_scan_keys: key %x-" ++ "%x, %d (%d) start debounce\n", ++ ds->info->type, key_entry->code, ++ i, key_entry->gpio); ++ } ++ continue; ++ } ++ if (pressed && (debounce & DEBOUNCE_NOTPRESSED)) { ++ if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE) ++ pr_info("gpio_keys_scan_keys: key %x-%x, %d " ++ "(%d) debounce pressed 1\n", ++ ds->info->type, key_entry->code, ++ i, key_entry->gpio); ++ key_state->debounce = DEBOUNCE_PRESSED; ++ continue; ++ } ++ if (!pressed && (debounce & DEBOUNCE_PRESSED)) { ++ if (gpio_flags & GPIOEDF_PRINT_KEY_DEBOUNCE) ++ pr_info("gpio_keys_scan_keys: key %x-%x, %d " ++ "(%d) debounce pressed 0\n", ++ ds->info->type, key_entry->code, ++ i, key_entry->gpio); ++ key_state->debounce = DEBOUNCE_NOTPRESSED; ++ continue; ++ } ++ /* key is stable */ ++ ds->debounce_count--; ++ if (ds->use_irq) ++ key_state->debounce |= DEBOUNCE_WAIT_IRQ; ++ else ++ key_state->debounce |= DEBOUNCE_POLL; ++ if (gpio_flags & GPIOEDF_PRINT_KEYS) ++ pr_info("gpio_keys_scan_keys: key %x-%x, %d (%d) " ++ "changed to %d\n", ds->info->type, ++ key_entry->code, i, key_entry->gpio, pressed); ++ input_event(ds->input_devs->dev[key_entry->dev], ds->info->type, ++ key_entry->code, pressed); ++ sync_needed = true; ++ } ++ if (sync_needed) { ++ for (i = 0; i < ds->input_devs->count; i++) ++ input_sync(ds->input_devs->dev[i]); ++ } ++ ++#if 0 ++ key_entry = kp->keys_info->keymap; ++ key_state = kp->key_state; ++ for (i = 0; i < nkeys; i++, key_entry++, key_state++) { ++ pr_info("gpio_read_detect_status %d %d\n", key_entry->gpio, ++ gpio_read_detect_status(key_entry->gpio)); ++ } ++#endif ++ ++ if (ds->debounce_count) ++ hrtimer_start(timer, ds->info->debounce_time, HRTIMER_MODE_REL); ++ else if (!ds->use_irq) ++ hrtimer_start(timer, ds->info->poll_time, HRTIMER_MODE_REL); ++ else ++ __pm_relax(ds->ws); ++ ++ spin_unlock_irqrestore(&ds->irq_lock, irqflags); ++ ++ return HRTIMER_NORESTART; ++} ++ ++static irqreturn_t gpio_event_input_irq_handler(int irq, void *dev_id) ++{ ++ struct gpio_key_state *ks = dev_id; ++ struct gpio_input_state *ds = ks->ds; ++ int keymap_index = ks - ds->key_state; ++ const struct gpio_event_direct_entry *key_entry; ++ unsigned long irqflags; ++ int pressed; ++ ++ if (!ds->use_irq) ++ return IRQ_HANDLED; ++ ++ key_entry = &ds->info->keymap[keymap_index]; ++ ++ if (ds->info->debounce_time.tv64) { ++ spin_lock_irqsave(&ds->irq_lock, irqflags); ++ if (ks->debounce & DEBOUNCE_WAIT_IRQ) { ++ ks->debounce = DEBOUNCE_UNKNOWN; ++ if (ds->debounce_count++ == 0) { ++ __pm_stay_awake(ds->ws); ++ hrtimer_start( ++ &ds->timer, ds->info->debounce_time, ++ HRTIMER_MODE_REL); ++ } ++ if (ds->info->flags & GPIOEDF_PRINT_KEY_DEBOUNCE) ++ pr_info("gpio_event_input_irq_handler: " ++ "key %x-%x, %d (%d) start debounce\n", ++ ds->info->type, key_entry->code, ++ keymap_index, key_entry->gpio); ++ } else { ++ disable_irq_nosync(irq); ++ ks->debounce = DEBOUNCE_UNSTABLE; ++ } ++ spin_unlock_irqrestore(&ds->irq_lock, irqflags); ++ } else { ++ pressed = gpio_get_value(key_entry->gpio) ^ ++ !(ds->info->flags & GPIOEDF_ACTIVE_HIGH); ++ if (ds->info->flags & GPIOEDF_PRINT_KEYS) ++ pr_info("gpio_event_input_irq_handler: key %x-%x, %d " ++ "(%d) changed to %d\n", ++ ds->info->type, key_entry->code, keymap_index, ++ key_entry->gpio, pressed); ++ input_event(ds->input_devs->dev[key_entry->dev], ds->info->type, ++ key_entry->code, pressed); ++ input_sync(ds->input_devs->dev[key_entry->dev]); ++ } ++ return IRQ_HANDLED; ++} ++ ++static int gpio_event_input_request_irqs(struct gpio_input_state *ds) ++{ ++ int i; ++ int err; ++ unsigned int irq; ++ unsigned long req_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; ++ ++ for (i = 0; i < ds->info->keymap_size; i++) { ++ err = irq = gpio_to_irq(ds->info->keymap[i].gpio); ++ if (err < 0) ++ goto err_gpio_get_irq_num_failed; ++ err = request_irq(irq, gpio_event_input_irq_handler, ++ req_flags, "gpio_keys", &ds->key_state[i]); ++ if (err) { ++ pr_err("gpio_event_input_request_irqs: request_irq " ++ "failed for input %d, irq %d\n", ++ ds->info->keymap[i].gpio, irq); ++ goto err_request_irq_failed; ++ } ++ if (ds->info->info.no_suspend) { ++ err = enable_irq_wake(irq); ++ if (err) { ++ pr_err("gpio_event_input_request_irqs: " ++ "enable_irq_wake failed for input %d, " ++ "irq %d\n", ++ ds->info->keymap[i].gpio, irq); ++ goto err_enable_irq_wake_failed; ++ } ++ } ++ } ++ return 0; ++ ++ for (i = ds->info->keymap_size - 1; i >= 0; i--) { ++ irq = gpio_to_irq(ds->info->keymap[i].gpio); ++ if (ds->info->info.no_suspend) ++ disable_irq_wake(irq); ++err_enable_irq_wake_failed: ++ free_irq(irq, &ds->key_state[i]); ++err_request_irq_failed: ++err_gpio_get_irq_num_failed: ++ ; ++ } ++ return err; ++} ++ ++int gpio_event_input_func(struct gpio_event_input_devs *input_devs, ++ struct gpio_event_info *info, void **data, int func) ++{ ++ int ret; ++ int i; ++ unsigned long irqflags; ++ struct gpio_event_input_info *di; ++ struct gpio_input_state *ds = *data; ++ char *wlname; ++ ++ di = container_of(info, struct gpio_event_input_info, info); ++ ++ if (func == GPIO_EVENT_FUNC_SUSPEND) { ++ if (ds->use_irq) ++ for (i = 0; i < di->keymap_size; i++) ++ disable_irq(gpio_to_irq(di->keymap[i].gpio)); ++ hrtimer_cancel(&ds->timer); ++ return 0; ++ } ++ if (func == GPIO_EVENT_FUNC_RESUME) { ++ spin_lock_irqsave(&ds->irq_lock, irqflags); ++ if (ds->use_irq) ++ for (i = 0; i < di->keymap_size; i++) ++ enable_irq(gpio_to_irq(di->keymap[i].gpio)); ++ hrtimer_start(&ds->timer, ktime_set(0, 0), HRTIMER_MODE_REL); ++ spin_unlock_irqrestore(&ds->irq_lock, irqflags); ++ return 0; ++ } ++ ++ if (func == GPIO_EVENT_FUNC_INIT) { ++ if (ktime_to_ns(di->poll_time) <= 0) ++ di->poll_time = ktime_set(0, 20 * NSEC_PER_MSEC); ++ ++ *data = ds = kzalloc(sizeof(*ds) + sizeof(ds->key_state[0]) * ++ di->keymap_size, GFP_KERNEL); ++ if (ds == NULL) { ++ ret = -ENOMEM; ++ pr_err("gpio_event_input_func: " ++ "Failed to allocate private data\n"); ++ goto err_ds_alloc_failed; ++ } ++ ds->debounce_count = di->keymap_size; ++ ds->input_devs = input_devs; ++ ds->info = di; ++ wlname = kasprintf(GFP_KERNEL, "gpio_input:%s%s", ++ input_devs->dev[0]->name, ++ (input_devs->count > 1) ? "..." : ""); ++ ++ ds->ws = wakeup_source_register(wlname); ++ kfree(wlname); ++ if (!ds->ws) { ++ ret = -ENOMEM; ++ pr_err("gpio_event_input_func: " ++ "Failed to allocate wakeup source\n"); ++ goto err_ws_failed; ++ } ++ ++ spin_lock_init(&ds->irq_lock); ++ ++ for (i = 0; i < di->keymap_size; i++) { ++ int dev = di->keymap[i].dev; ++ if (dev >= input_devs->count) { ++ pr_err("gpio_event_input_func: bad device " ++ "index %d >= %d for key code %d\n", ++ dev, input_devs->count, ++ di->keymap[i].code); ++ ret = -EINVAL; ++ goto err_bad_keymap; ++ } ++ input_set_capability(input_devs->dev[dev], di->type, ++ di->keymap[i].code); ++ ds->key_state[i].ds = ds; ++ ds->key_state[i].debounce = DEBOUNCE_UNKNOWN; ++ } ++ ++ for (i = 0; i < di->keymap_size; i++) { ++ ret = gpio_request(di->keymap[i].gpio, "gpio_kp_in"); ++ if (ret) { ++ pr_err("gpio_event_input_func: gpio_request " ++ "failed for %d\n", di->keymap[i].gpio); ++ goto err_gpio_request_failed; ++ } ++ ret = gpio_direction_input(di->keymap[i].gpio); ++ if (ret) { ++ pr_err("gpio_event_input_func: " ++ "gpio_direction_input failed for %d\n", ++ di->keymap[i].gpio); ++ goto err_gpio_configure_failed; ++ } ++ } ++ ++ ret = gpio_event_input_request_irqs(ds); ++ ++ spin_lock_irqsave(&ds->irq_lock, irqflags); ++ ds->use_irq = ret == 0; ++ ++ pr_info("GPIO Input Driver: Start gpio inputs for %s%s in %s " ++ "mode\n", input_devs->dev[0]->name, ++ (input_devs->count > 1) ? "..." : "", ++ ret == 0 ? "interrupt" : "polling"); ++ ++ hrtimer_init(&ds->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ ds->timer.function = gpio_event_input_timer_func; ++ hrtimer_start(&ds->timer, ktime_set(0, 0), HRTIMER_MODE_REL); ++ spin_unlock_irqrestore(&ds->irq_lock, irqflags); ++ return 0; ++ } ++ ++ ret = 0; ++ spin_lock_irqsave(&ds->irq_lock, irqflags); ++ hrtimer_cancel(&ds->timer); ++ if (ds->use_irq) { ++ for (i = di->keymap_size - 1; i >= 0; i--) { ++ int irq = gpio_to_irq(di->keymap[i].gpio); ++ if (ds->info->info.no_suspend) ++ disable_irq_wake(irq); ++ free_irq(irq, &ds->key_state[i]); ++ } ++ } ++ spin_unlock_irqrestore(&ds->irq_lock, irqflags); ++ ++ for (i = di->keymap_size - 1; i >= 0; i--) { ++err_gpio_configure_failed: ++ gpio_free(di->keymap[i].gpio); ++err_gpio_request_failed: ++ ; ++ } ++err_bad_keymap: ++ wakeup_source_unregister(ds->ws); ++err_ws_failed: ++ kfree(ds); ++err_ds_alloc_failed: ++ return ret; ++} +diff --git a/drivers/input/misc/gpio_matrix.c b/drivers/input/misc/gpio_matrix.c +new file mode 100644 +index 0000000..eaa9e89 +--- /dev/null ++++ b/drivers/input/misc/gpio_matrix.c +@@ -0,0 +1,441 @@ ++/* drivers/input/misc/gpio_matrix.c ++ * ++ * Copyright (C) 2007 Google, 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. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct gpio_kp { ++ struct gpio_event_input_devs *input_devs; ++ struct gpio_event_matrix_info *keypad_info; ++ struct hrtimer timer; ++ struct wake_lock wake_lock; ++ int current_output; ++ unsigned int use_irq:1; ++ unsigned int key_state_changed:1; ++ unsigned int last_key_state_changed:1; ++ unsigned int some_keys_pressed:2; ++ unsigned int disabled_irq:1; ++ unsigned long keys_pressed[0]; ++}; ++ ++static void clear_phantom_key(struct gpio_kp *kp, int out, int in) ++{ ++ struct gpio_event_matrix_info *mi = kp->keypad_info; ++ int key_index = out * mi->ninputs + in; ++ unsigned short keyentry = mi->keymap[key_index]; ++ unsigned short keycode = keyentry & MATRIX_KEY_MASK; ++ unsigned short dev = keyentry >> MATRIX_CODE_BITS; ++ ++ if (!test_bit(keycode, kp->input_devs->dev[dev]->key)) { ++ if (mi->flags & GPIOKPF_PRINT_PHANTOM_KEYS) ++ pr_info("gpiomatrix: phantom key %x, %d-%d (%d-%d) " ++ "cleared\n", keycode, out, in, ++ mi->output_gpios[out], mi->input_gpios[in]); ++ __clear_bit(key_index, kp->keys_pressed); ++ } else { ++ if (mi->flags & GPIOKPF_PRINT_PHANTOM_KEYS) ++ pr_info("gpiomatrix: phantom key %x, %d-%d (%d-%d) " ++ "not cleared\n", keycode, out, in, ++ mi->output_gpios[out], mi->input_gpios[in]); ++ } ++} ++ ++static int restore_keys_for_input(struct gpio_kp *kp, int out, int in) ++{ ++ int rv = 0; ++ int key_index; ++ ++ key_index = out * kp->keypad_info->ninputs + in; ++ while (out < kp->keypad_info->noutputs) { ++ if (test_bit(key_index, kp->keys_pressed)) { ++ rv = 1; ++ clear_phantom_key(kp, out, in); ++ } ++ key_index += kp->keypad_info->ninputs; ++ out++; ++ } ++ return rv; ++} ++ ++static void remove_phantom_keys(struct gpio_kp *kp) ++{ ++ int out, in, inp; ++ int key_index; ++ ++ if (kp->some_keys_pressed < 3) ++ return; ++ ++ for (out = 0; out < kp->keypad_info->noutputs; out++) { ++ inp = -1; ++ key_index = out * kp->keypad_info->ninputs; ++ for (in = 0; in < kp->keypad_info->ninputs; in++, key_index++) { ++ if (test_bit(key_index, kp->keys_pressed)) { ++ if (inp == -1) { ++ inp = in; ++ continue; ++ } ++ if (inp >= 0) { ++ if (!restore_keys_for_input(kp, out + 1, ++ inp)) ++ break; ++ clear_phantom_key(kp, out, inp); ++ inp = -2; ++ } ++ restore_keys_for_input(kp, out, in); ++ } ++ } ++ } ++} ++ ++static void report_key(struct gpio_kp *kp, int key_index, int out, int in) ++{ ++ struct gpio_event_matrix_info *mi = kp->keypad_info; ++ int pressed = test_bit(key_index, kp->keys_pressed); ++ unsigned short keyentry = mi->keymap[key_index]; ++ unsigned short keycode = keyentry & MATRIX_KEY_MASK; ++ unsigned short dev = keyentry >> MATRIX_CODE_BITS; ++ ++ if (pressed != test_bit(keycode, kp->input_devs->dev[dev]->key)) { ++ if (keycode == KEY_RESERVED) { ++ if (mi->flags & GPIOKPF_PRINT_UNMAPPED_KEYS) ++ pr_info("gpiomatrix: unmapped key, %d-%d " ++ "(%d-%d) changed to %d\n", ++ out, in, mi->output_gpios[out], ++ mi->input_gpios[in], pressed); ++ } else { ++ if (mi->flags & GPIOKPF_PRINT_MAPPED_KEYS) ++ pr_info("gpiomatrix: key %x, %d-%d (%d-%d) " ++ "changed to %d\n", keycode, ++ out, in, mi->output_gpios[out], ++ mi->input_gpios[in], pressed); ++ input_report_key(kp->input_devs->dev[dev], keycode, pressed); ++ } ++ } ++} ++ ++static void report_sync(struct gpio_kp *kp) ++{ ++ int i; ++ ++ for (i = 0; i < kp->input_devs->count; i++) ++ input_sync(kp->input_devs->dev[i]); ++} ++ ++static enum hrtimer_restart gpio_keypad_timer_func(struct hrtimer *timer) ++{ ++ int out, in; ++ int key_index; ++ int gpio; ++ struct gpio_kp *kp = container_of(timer, struct gpio_kp, timer); ++ struct gpio_event_matrix_info *mi = kp->keypad_info; ++ unsigned gpio_keypad_flags = mi->flags; ++ unsigned polarity = !!(gpio_keypad_flags & GPIOKPF_ACTIVE_HIGH); ++ ++ out = kp->current_output; ++ if (out == mi->noutputs) { ++ out = 0; ++ kp->last_key_state_changed = kp->key_state_changed; ++ kp->key_state_changed = 0; ++ kp->some_keys_pressed = 0; ++ } else { ++ key_index = out * mi->ninputs; ++ for (in = 0; in < mi->ninputs; in++, key_index++) { ++ gpio = mi->input_gpios[in]; ++ if (gpio_get_value(gpio) ^ !polarity) { ++ if (kp->some_keys_pressed < 3) ++ kp->some_keys_pressed++; ++ kp->key_state_changed |= !__test_and_set_bit( ++ key_index, kp->keys_pressed); ++ } else ++ kp->key_state_changed |= __test_and_clear_bit( ++ key_index, kp->keys_pressed); ++ } ++ gpio = mi->output_gpios[out]; ++ if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE) ++ gpio_set_value(gpio, !polarity); ++ else ++ gpio_direction_input(gpio); ++ out++; ++ } ++ kp->current_output = out; ++ if (out < mi->noutputs) { ++ gpio = mi->output_gpios[out]; ++ if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE) ++ gpio_set_value(gpio, polarity); ++ else ++ gpio_direction_output(gpio, polarity); ++ hrtimer_start(timer, mi->settle_time, HRTIMER_MODE_REL); ++ return HRTIMER_NORESTART; ++ } ++ if (gpio_keypad_flags & GPIOKPF_DEBOUNCE) { ++ if (kp->key_state_changed) { ++ hrtimer_start(&kp->timer, mi->debounce_delay, ++ HRTIMER_MODE_REL); ++ return HRTIMER_NORESTART; ++ } ++ kp->key_state_changed = kp->last_key_state_changed; ++ } ++ if (kp->key_state_changed) { ++ if (gpio_keypad_flags & GPIOKPF_REMOVE_SOME_PHANTOM_KEYS) ++ remove_phantom_keys(kp); ++ key_index = 0; ++ for (out = 0; out < mi->noutputs; out++) ++ for (in = 0; in < mi->ninputs; in++, key_index++) ++ report_key(kp, key_index, out, in); ++ report_sync(kp); ++ } ++ if (!kp->use_irq || kp->some_keys_pressed) { ++ hrtimer_start(timer, mi->poll_time, HRTIMER_MODE_REL); ++ return HRTIMER_NORESTART; ++ } ++ ++ /* No keys are pressed, reenable interrupt */ ++ for (out = 0; out < mi->noutputs; out++) { ++ if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE) ++ gpio_set_value(mi->output_gpios[out], polarity); ++ else ++ gpio_direction_output(mi->output_gpios[out], polarity); ++ } ++ for (in = 0; in < mi->ninputs; in++) ++ enable_irq(gpio_to_irq(mi->input_gpios[in])); ++ wake_unlock(&kp->wake_lock); ++ return HRTIMER_NORESTART; ++} ++ ++static irqreturn_t gpio_keypad_irq_handler(int irq_in, void *dev_id) ++{ ++ int i; ++ struct gpio_kp *kp = dev_id; ++ struct gpio_event_matrix_info *mi = kp->keypad_info; ++ unsigned gpio_keypad_flags = mi->flags; ++ ++ if (!kp->use_irq) { ++ /* ignore interrupt while registering the handler */ ++ kp->disabled_irq = 1; ++ disable_irq_nosync(irq_in); ++ return IRQ_HANDLED; ++ } ++ ++ for (i = 0; i < mi->ninputs; i++) ++ disable_irq_nosync(gpio_to_irq(mi->input_gpios[i])); ++ for (i = 0; i < mi->noutputs; i++) { ++ if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE) ++ gpio_set_value(mi->output_gpios[i], ++ !(gpio_keypad_flags & GPIOKPF_ACTIVE_HIGH)); ++ else ++ gpio_direction_input(mi->output_gpios[i]); ++ } ++ wake_lock(&kp->wake_lock); ++ hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL); ++ return IRQ_HANDLED; ++} ++ ++static int gpio_keypad_request_irqs(struct gpio_kp *kp) ++{ ++ int i; ++ int err; ++ unsigned int irq; ++ unsigned long request_flags; ++ struct gpio_event_matrix_info *mi = kp->keypad_info; ++ ++ switch (mi->flags & (GPIOKPF_ACTIVE_HIGH|GPIOKPF_LEVEL_TRIGGERED_IRQ)) { ++ default: ++ request_flags = IRQF_TRIGGER_FALLING; ++ break; ++ case GPIOKPF_ACTIVE_HIGH: ++ request_flags = IRQF_TRIGGER_RISING; ++ break; ++ case GPIOKPF_LEVEL_TRIGGERED_IRQ: ++ request_flags = IRQF_TRIGGER_LOW; ++ break; ++ case GPIOKPF_LEVEL_TRIGGERED_IRQ | GPIOKPF_ACTIVE_HIGH: ++ request_flags = IRQF_TRIGGER_HIGH; ++ break; ++ } ++ ++ for (i = 0; i < mi->ninputs; i++) { ++ err = irq = gpio_to_irq(mi->input_gpios[i]); ++ if (err < 0) ++ goto err_gpio_get_irq_num_failed; ++ err = request_irq(irq, gpio_keypad_irq_handler, request_flags, ++ "gpio_kp", kp); ++ if (err) { ++ pr_err("gpiomatrix: request_irq failed for input %d, " ++ "irq %d\n", mi->input_gpios[i], irq); ++ goto err_request_irq_failed; ++ } ++ err = enable_irq_wake(irq); ++ if (err) { ++ pr_err("gpiomatrix: set_irq_wake failed for input %d, " ++ "irq %d\n", mi->input_gpios[i], irq); ++ } ++ disable_irq(irq); ++ if (kp->disabled_irq) { ++ kp->disabled_irq = 0; ++ enable_irq(irq); ++ } ++ } ++ return 0; ++ ++ for (i = mi->noutputs - 1; i >= 0; i--) { ++ free_irq(gpio_to_irq(mi->input_gpios[i]), kp); ++err_request_irq_failed: ++err_gpio_get_irq_num_failed: ++ ; ++ } ++ return err; ++} ++ ++int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs, ++ struct gpio_event_info *info, void **data, int func) ++{ ++ int i; ++ int err; ++ int key_count; ++ struct gpio_kp *kp; ++ struct gpio_event_matrix_info *mi; ++ ++ mi = container_of(info, struct gpio_event_matrix_info, info); ++ if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) { ++ /* TODO: disable scanning */ ++ return 0; ++ } ++ ++ if (func == GPIO_EVENT_FUNC_INIT) { ++ if (mi->keymap == NULL || ++ mi->input_gpios == NULL || ++ mi->output_gpios == NULL) { ++ err = -ENODEV; ++ pr_err("gpiomatrix: Incomplete pdata\n"); ++ goto err_invalid_platform_data; ++ } ++ key_count = mi->ninputs * mi->noutputs; ++ ++ *data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) * ++ BITS_TO_LONGS(key_count), GFP_KERNEL); ++ if (kp == NULL) { ++ err = -ENOMEM; ++ pr_err("gpiomatrix: Failed to allocate private data\n"); ++ goto err_kp_alloc_failed; ++ } ++ kp->input_devs = input_devs; ++ kp->keypad_info = mi; ++ for (i = 0; i < key_count; i++) { ++ unsigned short keyentry = mi->keymap[i]; ++ unsigned short keycode = keyentry & MATRIX_KEY_MASK; ++ unsigned short dev = keyentry >> MATRIX_CODE_BITS; ++ if (dev >= input_devs->count) { ++ pr_err("gpiomatrix: bad device index %d >= " ++ "%d for key code %d\n", ++ dev, input_devs->count, keycode); ++ err = -EINVAL; ++ goto err_bad_keymap; ++ } ++ if (keycode && keycode <= KEY_MAX) ++ input_set_capability(input_devs->dev[dev], ++ EV_KEY, keycode); ++ } ++ ++ for (i = 0; i < mi->noutputs; i++) { ++ err = gpio_request(mi->output_gpios[i], "gpio_kp_out"); ++ if (err) { ++ pr_err("gpiomatrix: gpio_request failed for " ++ "output %d\n", mi->output_gpios[i]); ++ goto err_request_output_gpio_failed; ++ } ++ if (gpio_cansleep(mi->output_gpios[i])) { ++ pr_err("gpiomatrix: unsupported output gpio %d," ++ " can sleep\n", mi->output_gpios[i]); ++ err = -EINVAL; ++ goto err_output_gpio_configure_failed; ++ } ++ if (mi->flags & GPIOKPF_DRIVE_INACTIVE) ++ err = gpio_direction_output(mi->output_gpios[i], ++ !(mi->flags & GPIOKPF_ACTIVE_HIGH)); ++ else ++ err = gpio_direction_input(mi->output_gpios[i]); ++ if (err) { ++ pr_err("gpiomatrix: gpio_configure failed for " ++ "output %d\n", mi->output_gpios[i]); ++ goto err_output_gpio_configure_failed; ++ } ++ } ++ for (i = 0; i < mi->ninputs; i++) { ++ err = gpio_request(mi->input_gpios[i], "gpio_kp_in"); ++ if (err) { ++ pr_err("gpiomatrix: gpio_request failed for " ++ "input %d\n", mi->input_gpios[i]); ++ goto err_request_input_gpio_failed; ++ } ++ err = gpio_direction_input(mi->input_gpios[i]); ++ if (err) { ++ pr_err("gpiomatrix: gpio_direction_input failed" ++ " for input %d\n", mi->input_gpios[i]); ++ goto err_gpio_direction_input_failed; ++ } ++ } ++ kp->current_output = mi->noutputs; ++ kp->key_state_changed = 1; ++ ++ hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ kp->timer.function = gpio_keypad_timer_func; ++ wake_lock_init(&kp->wake_lock, WAKE_LOCK_SUSPEND, "gpio_kp"); ++ err = gpio_keypad_request_irqs(kp); ++ kp->use_irq = err == 0; ++ ++ pr_info("GPIO Matrix Keypad Driver: Start keypad matrix for " ++ "%s%s in %s mode\n", input_devs->dev[0]->name, ++ (input_devs->count > 1) ? "..." : "", ++ kp->use_irq ? "interrupt" : "polling"); ++ ++ if (kp->use_irq) ++ wake_lock(&kp->wake_lock); ++ hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL); ++ ++ return 0; ++ } ++ ++ err = 0; ++ kp = *data; ++ ++ if (kp->use_irq) ++ for (i = mi->noutputs - 1; i >= 0; i--) ++ free_irq(gpio_to_irq(mi->input_gpios[i]), kp); ++ ++ hrtimer_cancel(&kp->timer); ++ wake_lock_destroy(&kp->wake_lock); ++ for (i = mi->noutputs - 1; i >= 0; i--) { ++err_gpio_direction_input_failed: ++ gpio_free(mi->input_gpios[i]); ++err_request_input_gpio_failed: ++ ; ++ } ++ for (i = mi->noutputs - 1; i >= 0; i--) { ++err_output_gpio_configure_failed: ++ gpio_free(mi->output_gpios[i]); ++err_request_output_gpio_failed: ++ ; ++ } ++err_bad_keymap: ++ kfree(kp); ++err_kp_alloc_failed: ++err_invalid_platform_data: ++ return err; ++} +diff --git a/drivers/input/misc/gpio_output.c b/drivers/input/misc/gpio_output.c +new file mode 100644 +index 0000000..2aac2fa +--- /dev/null ++++ b/drivers/input/misc/gpio_output.c +@@ -0,0 +1,97 @@ ++/* drivers/input/misc/gpio_output.c ++ * ++ * Copyright (C) 2007 Google, 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. ++ * ++ */ ++ ++#include ++#include ++#include ++ ++int gpio_event_output_event( ++ struct gpio_event_input_devs *input_devs, struct gpio_event_info *info, ++ void **data, unsigned int dev, unsigned int type, ++ unsigned int code, int value) ++{ ++ int i; ++ struct gpio_event_output_info *oi; ++ oi = container_of(info, struct gpio_event_output_info, info); ++ if (type != oi->type) ++ return 0; ++ if (!(oi->flags & GPIOEDF_ACTIVE_HIGH)) ++ value = !value; ++ for (i = 0; i < oi->keymap_size; i++) ++ if (dev == oi->keymap[i].dev && code == oi->keymap[i].code) ++ gpio_set_value(oi->keymap[i].gpio, value); ++ return 0; ++} ++ ++int gpio_event_output_func( ++ struct gpio_event_input_devs *input_devs, struct gpio_event_info *info, ++ void **data, int func) ++{ ++ int ret; ++ int i; ++ struct gpio_event_output_info *oi; ++ oi = container_of(info, struct gpio_event_output_info, info); ++ ++ if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) ++ return 0; ++ ++ if (func == GPIO_EVENT_FUNC_INIT) { ++ int output_level = !(oi->flags & GPIOEDF_ACTIVE_HIGH); ++ ++ for (i = 0; i < oi->keymap_size; i++) { ++ int dev = oi->keymap[i].dev; ++ if (dev >= input_devs->count) { ++ pr_err("gpio_event_output_func: bad device " ++ "index %d >= %d for key code %d\n", ++ dev, input_devs->count, ++ oi->keymap[i].code); ++ ret = -EINVAL; ++ goto err_bad_keymap; ++ } ++ input_set_capability(input_devs->dev[dev], oi->type, ++ oi->keymap[i].code); ++ } ++ ++ for (i = 0; i < oi->keymap_size; i++) { ++ ret = gpio_request(oi->keymap[i].gpio, ++ "gpio_event_output"); ++ if (ret) { ++ pr_err("gpio_event_output_func: gpio_request " ++ "failed for %d\n", oi->keymap[i].gpio); ++ goto err_gpio_request_failed; ++ } ++ ret = gpio_direction_output(oi->keymap[i].gpio, ++ output_level); ++ if (ret) { ++ pr_err("gpio_event_output_func: " ++ "gpio_direction_output failed for %d\n", ++ oi->keymap[i].gpio); ++ goto err_gpio_direction_output_failed; ++ } ++ } ++ return 0; ++ } ++ ++ ret = 0; ++ for (i = oi->keymap_size - 1; i >= 0; i--) { ++err_gpio_direction_output_failed: ++ gpio_free(oi->keymap[i].gpio); ++err_gpio_request_failed: ++ ; ++ } ++err_bad_keymap: ++ return ret; ++} ++ +diff --git a/drivers/input/misc/keychord.c b/drivers/input/misc/keychord.c +new file mode 100644 +index 0000000..a5ea27a +--- /dev/null ++++ b/drivers/input/misc/keychord.c +@@ -0,0 +1,391 @@ ++/* ++ * drivers/input/misc/keychord.c ++ * ++ * Copyright (C) 2008 Google, Inc. ++ * Author: Mike Lockwood ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define KEYCHORD_NAME "keychord" ++#define BUFFER_SIZE 16 ++ ++MODULE_AUTHOR("Mike Lockwood "); ++MODULE_DESCRIPTION("Key chord input driver"); ++MODULE_SUPPORTED_DEVICE("keychord"); ++MODULE_LICENSE("GPL"); ++ ++#define NEXT_KEYCHORD(kc) ((struct input_keychord *) \ ++ ((char *)kc + sizeof(struct input_keychord) + \ ++ kc->count * sizeof(kc->keycodes[0]))) ++ ++struct keychord_device { ++ struct input_handler input_handler; ++ int registered; ++ ++ /* list of keychords to monitor */ ++ struct input_keychord *keychords; ++ int keychord_count; ++ ++ /* bitmask of keys contained in our keychords */ ++ unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; ++ /* current state of the keys */ ++ unsigned long keystate[BITS_TO_LONGS(KEY_CNT)]; ++ /* number of keys that are currently pressed */ ++ int key_down; ++ ++ /* second input_device_id is needed for null termination */ ++ struct input_device_id device_ids[2]; ++ ++ spinlock_t lock; ++ wait_queue_head_t waitq; ++ unsigned char head; ++ unsigned char tail; ++ __u16 buff[BUFFER_SIZE]; ++}; ++ ++static int check_keychord(struct keychord_device *kdev, ++ struct input_keychord *keychord) ++{ ++ int i; ++ ++ if (keychord->count != kdev->key_down) ++ return 0; ++ ++ for (i = 0; i < keychord->count; i++) { ++ if (!test_bit(keychord->keycodes[i], kdev->keystate)) ++ return 0; ++ } ++ ++ /* we have a match */ ++ return 1; ++} ++ ++static void keychord_event(struct input_handle *handle, unsigned int type, ++ unsigned int code, int value) ++{ ++ struct keychord_device *kdev = handle->private; ++ struct input_keychord *keychord; ++ unsigned long flags; ++ int i, got_chord = 0; ++ ++ if (type != EV_KEY || code >= KEY_MAX) ++ return; ++ ++ spin_lock_irqsave(&kdev->lock, flags); ++ /* do nothing if key state did not change */ ++ if (!test_bit(code, kdev->keystate) == !value) ++ goto done; ++ __change_bit(code, kdev->keystate); ++ if (value) ++ kdev->key_down++; ++ else ++ kdev->key_down--; ++ ++ /* don't notify on key up */ ++ if (!value) ++ goto done; ++ /* ignore this event if it is not one of the keys we are monitoring */ ++ if (!test_bit(code, kdev->keybit)) ++ goto done; ++ ++ keychord = kdev->keychords; ++ if (!keychord) ++ goto done; ++ ++ /* check to see if the keyboard state matches any keychords */ ++ for (i = 0; i < kdev->keychord_count; i++) { ++ if (check_keychord(kdev, keychord)) { ++ kdev->buff[kdev->head] = keychord->id; ++ kdev->head = (kdev->head + 1) % BUFFER_SIZE; ++ got_chord = 1; ++ break; ++ } ++ /* skip to next keychord */ ++ keychord = NEXT_KEYCHORD(keychord); ++ } ++ ++done: ++ spin_unlock_irqrestore(&kdev->lock, flags); ++ ++ if (got_chord) { ++ pr_info("keychord: got keychord id %d. Any tasks: %d\n", ++ keychord->id, ++ !list_empty_careful(&kdev->waitq.task_list)); ++ wake_up_interruptible(&kdev->waitq); ++ } ++} ++ ++static int keychord_connect(struct input_handler *handler, ++ struct input_dev *dev, ++ const struct input_device_id *id) ++{ ++ int i, ret; ++ struct input_handle *handle; ++ struct keychord_device *kdev = ++ container_of(handler, struct keychord_device, input_handler); ++ ++ /* ++ * ignore this input device if it does not contain any keycodes ++ * that we are monitoring ++ */ ++ for (i = 0; i < KEY_MAX; i++) { ++ if (test_bit(i, kdev->keybit) && test_bit(i, dev->keybit)) ++ break; ++ } ++ if (i == KEY_MAX) ++ return -ENODEV; ++ ++ handle = kzalloc(sizeof(*handle), GFP_KERNEL); ++ if (!handle) ++ return -ENOMEM; ++ ++ handle->dev = dev; ++ handle->handler = handler; ++ handle->name = KEYCHORD_NAME; ++ handle->private = kdev; ++ ++ ret = input_register_handle(handle); ++ if (ret) ++ goto err_input_register_handle; ++ ++ ret = input_open_device(handle); ++ if (ret) ++ goto err_input_open_device; ++ ++ pr_info("keychord: using input dev %s for fevent\n", dev->name); ++ ++ return 0; ++ ++err_input_open_device: ++ input_unregister_handle(handle); ++err_input_register_handle: ++ kfree(handle); ++ return ret; ++} ++ ++static void keychord_disconnect(struct input_handle *handle) ++{ ++ input_close_device(handle); ++ input_unregister_handle(handle); ++ kfree(handle); ++} ++ ++/* ++ * keychord_read is used to read keychord events from the driver ++ */ ++static ssize_t keychord_read(struct file *file, char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ struct keychord_device *kdev = file->private_data; ++ __u16 id; ++ int retval; ++ unsigned long flags; ++ ++ if (count < sizeof(id)) ++ return -EINVAL; ++ count = sizeof(id); ++ ++ if (kdev->head == kdev->tail && (file->f_flags & O_NONBLOCK)) ++ return -EAGAIN; ++ ++ retval = wait_event_interruptible(kdev->waitq, ++ kdev->head != kdev->tail); ++ if (retval) ++ return retval; ++ ++ spin_lock_irqsave(&kdev->lock, flags); ++ /* pop a keychord ID off the queue */ ++ id = kdev->buff[kdev->tail]; ++ kdev->tail = (kdev->tail + 1) % BUFFER_SIZE; ++ spin_unlock_irqrestore(&kdev->lock, flags); ++ ++ if (copy_to_user(buffer, &id, count)) ++ return -EFAULT; ++ ++ return count; ++} ++ ++/* ++ * keychord_write is used to configure the driver ++ */ ++static ssize_t keychord_write(struct file *file, const char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ struct keychord_device *kdev = file->private_data; ++ struct input_keychord *keychords = 0; ++ struct input_keychord *keychord, *next, *end; ++ int ret, i, key; ++ unsigned long flags; ++ ++ if (count < sizeof(struct input_keychord)) ++ return -EINVAL; ++ keychords = kzalloc(count, GFP_KERNEL); ++ if (!keychords) ++ return -ENOMEM; ++ ++ /* read list of keychords from userspace */ ++ if (copy_from_user(keychords, buffer, count)) { ++ kfree(keychords); ++ return -EFAULT; ++ } ++ ++ /* unregister handler before changing configuration */ ++ if (kdev->registered) { ++ input_unregister_handler(&kdev->input_handler); ++ kdev->registered = 0; ++ } ++ ++ spin_lock_irqsave(&kdev->lock, flags); ++ /* clear any existing configuration */ ++ kfree(kdev->keychords); ++ kdev->keychords = 0; ++ kdev->keychord_count = 0; ++ kdev->key_down = 0; ++ memset(kdev->keybit, 0, sizeof(kdev->keybit)); ++ memset(kdev->keystate, 0, sizeof(kdev->keystate)); ++ kdev->head = kdev->tail = 0; ++ ++ keychord = keychords; ++ end = (struct input_keychord *)((char *)keychord + count); ++ ++ while (keychord < end) { ++ next = NEXT_KEYCHORD(keychord); ++ if (keychord->count <= 0 || next > end) { ++ pr_err("keychord: invalid keycode count %d\n", ++ keychord->count); ++ goto err_unlock_return; ++ } ++ if (keychord->version != KEYCHORD_VERSION) { ++ pr_err("keychord: unsupported version %d\n", ++ keychord->version); ++ goto err_unlock_return; ++ } ++ ++ /* keep track of the keys we are monitoring in keybit */ ++ for (i = 0; i < keychord->count; i++) { ++ key = keychord->keycodes[i]; ++ if (key < 0 || key >= KEY_CNT) { ++ pr_err("keychord: keycode %d out of range\n", ++ key); ++ goto err_unlock_return; ++ } ++ __set_bit(key, kdev->keybit); ++ } ++ ++ kdev->keychord_count++; ++ keychord = next; ++ } ++ ++ kdev->keychords = keychords; ++ spin_unlock_irqrestore(&kdev->lock, flags); ++ ++ ret = input_register_handler(&kdev->input_handler); ++ if (ret) { ++ kfree(keychords); ++ kdev->keychords = 0; ++ return ret; ++ } ++ kdev->registered = 1; ++ ++ return count; ++ ++err_unlock_return: ++ spin_unlock_irqrestore(&kdev->lock, flags); ++ kfree(keychords); ++ return -EINVAL; ++} ++ ++static unsigned int keychord_poll(struct file *file, poll_table *wait) ++{ ++ struct keychord_device *kdev = file->private_data; ++ ++ poll_wait(file, &kdev->waitq, wait); ++ ++ if (kdev->head != kdev->tail) ++ return POLLIN | POLLRDNORM; ++ ++ return 0; ++} ++ ++static int keychord_open(struct inode *inode, struct file *file) ++{ ++ struct keychord_device *kdev; ++ ++ kdev = kzalloc(sizeof(struct keychord_device), GFP_KERNEL); ++ if (!kdev) ++ return -ENOMEM; ++ ++ spin_lock_init(&kdev->lock); ++ init_waitqueue_head(&kdev->waitq); ++ ++ kdev->input_handler.event = keychord_event; ++ kdev->input_handler.connect = keychord_connect; ++ kdev->input_handler.disconnect = keychord_disconnect; ++ kdev->input_handler.name = KEYCHORD_NAME; ++ kdev->input_handler.id_table = kdev->device_ids; ++ ++ kdev->device_ids[0].flags = INPUT_DEVICE_ID_MATCH_EVBIT; ++ __set_bit(EV_KEY, kdev->device_ids[0].evbit); ++ ++ file->private_data = kdev; ++ ++ return 0; ++} ++ ++static int keychord_release(struct inode *inode, struct file *file) ++{ ++ struct keychord_device *kdev = file->private_data; ++ ++ if (kdev->registered) ++ input_unregister_handler(&kdev->input_handler); ++ kfree(kdev); ++ ++ return 0; ++} ++ ++static const struct file_operations keychord_fops = { ++ .owner = THIS_MODULE, ++ .open = keychord_open, ++ .release = keychord_release, ++ .read = keychord_read, ++ .write = keychord_write, ++ .poll = keychord_poll, ++}; ++ ++static struct miscdevice keychord_misc = { ++ .fops = &keychord_fops, ++ .name = KEYCHORD_NAME, ++ .minor = MISC_DYNAMIC_MINOR, ++}; ++ ++static int __init keychord_init(void) ++{ ++ return misc_register(&keychord_misc); ++} ++ ++static void __exit keychord_exit(void) ++{ ++ misc_deregister(&keychord_misc); ++} ++ ++module_init(keychord_init); ++module_exit(keychord_exit); +diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c +index 38493ff..7aae78e 100644 +--- a/drivers/irqchip/irq-gic.c ++++ b/drivers/irqchip/irq-gic.c +@@ -81,6 +81,23 @@ static DEFINE_RAW_SPINLOCK(irq_controller_lock); + static u8 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly; + + /* ++ *Uesed to process gic sgi interrupt * ++ */ ++#if defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) ++#define DIS_IRQ_CNT 6 ++#else ++#define DIS_IRQ_CNT 2 ++#endif ++struct gic_sgi_handle { ++ unsigned int irq; ++ void (*handle)(unsigned int cpu_intrf, ++ unsigned int irq_num, ++ struct pt_regs *regs); ++}; ++struct gic_sgi_handle dis_irq_handle[DIS_IRQ_CNT]; ++EXPORT_SYMBOL(dis_irq_handle); ++ ++/* + * Supported arch specific GIC irq extension. + * Default make them NULL. + */ +@@ -258,6 +275,22 @@ static int gic_set_wake(struct irq_data *d, unsigned int on) + #else + #define gic_set_wake NULL + #endif ++/* used to process dis irq */ ++int dis_irq_proc(u32 irqnr, u32 irqstat, struct pt_regs *regs) ++{ ++ u32 idx; ++ ++ for (idx = 0; idx < DIS_IRQ_CNT; idx++) { ++ if ((irqnr == dis_irq_handle[idx].irq) ++ && (dis_irq_handle[idx].handle)) { ++ dis_irq_handle[idx].handle(((irqstat >> 10) & 0x7), ++ irqnr, regs); ++ return 1; ++ } ++ } ++ ++ return 0; ++} + + static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) + { +@@ -273,13 +306,19 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) + handle_domain_irq(gic->domain, irqnr, regs); + continue; + } ++ + if (irqnr < 16) { + writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); ++ ++ /*Call dis irq proccess func*/ ++ if (dis_irq_proc(irqnr, irqstat, regs)) ++ continue; + #ifdef CONFIG_SMP + handle_IPI(irqnr, regs); + #endif + continue; + } ++ + break; + } while (1); + } +@@ -366,7 +405,6 @@ static void gic_cpu_if_up(void) + writel_relaxed(bypass | GICC_ENABLE, cpu_base + GIC_CPU_CTRL); + } + +- + static void __init gic_dist_init(struct gic_chip_data *gic) + { + unsigned int i; +@@ -1001,7 +1039,28 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, + } + + gic_chip.flags |= gic_arch_extn.flags; ++#if !defined(CONFIG_ARCH_HI3559) && !defined(CONFIG_ARCH_HI3556) + gic_dist_init(gic); ++#else ++ { ++ /* 0x47444946('G''D''I''F') is abbreviation of GIC_DIST_INIT_FLAG */ ++ /* hi3559/hi3556 runs 2 OS, another OS distributes the IRQ. */ ++ /* when another OS has distributed the IRQ, sysctrl(0x12020130) */ ++ /* register will be set to 0x47444946 */ ++ /* if another OS did not distribute the IRQ, this OS will do it. */ ++ ++#define GIC_DIST_INIT_FLAG 0x47444946 ++#define GIC_DIST_INIT_FLAG_OFFSET 0x0130 ++ struct device_node *np; ++ int gic_dist_init_flag; ++ ++ np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl"); ++ gic_dist_init_flag = readl(of_iomap(np, 0) + GIC_DIST_INIT_FLAG_OFFSET); ++ ++ if(gic_dist_init_flag != GIC_DIST_INIT_FLAG) ++ gic_dist_init(gic); ++ } ++#endif + gic_cpu_init(gic); + gic_pm_init(gic); + } +diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c +index 08981be..5503e43 100644 +--- a/drivers/md/dm-crypt.c ++++ b/drivers/md/dm-crypt.c +@@ -18,9 +18,11 @@ + #include + #include + #include ++#include + #include + #include + #include ++#include + #include + #include + #include +@@ -58,7 +60,8 @@ struct dm_crypt_io { + atomic_t io_pending; + int error; + sector_t sector; +- struct dm_crypt_io *base_io; ++ ++ struct rb_node rb_node; + } CRYPTO_MINALIGN_ATTR; + + struct dm_crypt_request { +@@ -108,7 +111,8 @@ struct iv_tcw_private { + * Crypt: maps a linear range of a block device + * and encrypts / decrypts at the same time. + */ +-enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID }; ++enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID, ++ DM_CRYPT_SAME_CPU, DM_CRYPT_NO_OFFLOAD }; + + /* + * The fields in here must be read only after initialization. +@@ -121,14 +125,18 @@ struct crypt_config { + * pool for per bio private data, crypto requests and + * encryption requeusts/buffer pages + */ +- mempool_t *io_pool; + mempool_t *req_pool; + mempool_t *page_pool; + struct bio_set *bs; ++ struct mutex bio_alloc_lock; + + struct workqueue_struct *io_queue; + struct workqueue_struct *crypt_queue; + ++ struct task_struct *write_thread; ++ wait_queue_head_t write_thread_wait; ++ struct rb_root write_tree; ++ + char *cipher; + char *cipher_string; + +@@ -172,9 +180,6 @@ struct crypt_config { + }; + + #define MIN_IOS 16 +-#define MIN_POOL_PAGES 32 +- +-static struct kmem_cache *_crypt_io_pool; + + static void clone_init(struct dm_crypt_io *, struct bio *); + static void kcryptd_queue_crypt(struct dm_crypt_io *io); +@@ -223,7 +228,7 @@ static struct crypto_ablkcipher *any_tfm(struct crypt_config *cc) + * + * tcw: Compatible implementation of the block chaining mode used + * by the TrueCrypt device encryption system (prior to version 4.1). +- * For more info see: http://www.truecrypt.org ++ * For more info see: https://gitlab.com/cryptsetup/cryptsetup/wikis/TrueCryptOnDiskFormat + * It operates on full 512 byte sectors and uses CBC + * with an IV derived from initial key and the sector number. + * In addition, whitening value is applied on every sector, whitening +@@ -946,57 +951,70 @@ static int crypt_convert(struct crypt_config *cc, + return 0; + } + ++static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone); ++ + /* + * Generate a new unfragmented bio with the given size + * This should never violate the device limitations +- * May return a smaller bio when running out of pages, indicated by +- * *out_of_pages set to 1. ++ * ++ * This function may be called concurrently. If we allocate from the mempool ++ * concurrently, there is a possibility of deadlock. For example, if we have ++ * mempool of 256 pages, two processes, each wanting 256, pages allocate from ++ * the mempool concurrently, it may deadlock in a situation where both processes ++ * have allocated 128 pages and the mempool is exhausted. ++ * ++ * In order to avoid this scenario we allocate the pages under a mutex. ++ * ++ * In order to not degrade performance with excessive locking, we try ++ * non-blocking allocations without a mutex first but on failure we fallback ++ * to blocking allocations with a mutex. + */ +-static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size, +- unsigned *out_of_pages) ++static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size) + { + struct crypt_config *cc = io->cc; + struct bio *clone; + unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; +- gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM; +- unsigned i, len; ++ gfp_t gfp_mask = GFP_NOWAIT | __GFP_HIGHMEM; ++ unsigned i, len, remaining_size; + struct page *page; ++ struct bio_vec *bvec; ++ ++retry: ++ if (unlikely(gfp_mask & __GFP_WAIT)) ++ mutex_lock(&cc->bio_alloc_lock); + + clone = bio_alloc_bioset(GFP_NOIO, nr_iovecs, cc->bs); + if (!clone) +- return NULL; ++ goto return_clone; + + clone_init(io, clone); +- *out_of_pages = 0; ++ ++ remaining_size = size; + + for (i = 0; i < nr_iovecs; i++) { + page = mempool_alloc(cc->page_pool, gfp_mask); + if (!page) { +- *out_of_pages = 1; +- break; ++ crypt_free_buffer_pages(cc, clone); ++ bio_put(clone); ++ gfp_mask |= __GFP_WAIT; ++ goto retry; + } + +- /* +- * If additional pages cannot be allocated without waiting, +- * return a partially-allocated bio. The caller will then try +- * to allocate more bios while submitting this partial bio. +- */ +- gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT; ++ len = (remaining_size > PAGE_SIZE) ? PAGE_SIZE : remaining_size; + +- len = (size > PAGE_SIZE) ? PAGE_SIZE : size; ++ bvec = &clone->bi_io_vec[clone->bi_vcnt++]; ++ bvec->bv_page = page; ++ bvec->bv_len = len; ++ bvec->bv_offset = 0; + +- if (!bio_add_page(clone, page, len, 0)) { +- mempool_free(page, cc->page_pool); +- break; +- } ++ clone->bi_iter.bi_size += len; + +- size -= len; ++ remaining_size -= len; + } + +- if (!clone->bi_iter.bi_size) { +- bio_put(clone); +- return NULL; +- } ++return_clone: ++ if (unlikely(gfp_mask & __GFP_WAIT)) ++ mutex_unlock(&cc->bio_alloc_lock); + + return clone; + } +@@ -1020,7 +1038,6 @@ static void crypt_io_init(struct dm_crypt_io *io, struct crypt_config *cc, + io->base_bio = bio; + io->sector = sector; + io->error = 0; +- io->base_io = NULL; + io->ctx.req = NULL; + atomic_set(&io->io_pending, 0); + } +@@ -1033,13 +1050,11 @@ static void crypt_inc_pending(struct dm_crypt_io *io) + /* + * One of the bios was finished. Check for completion of + * the whole request and correctly clean up the buffer. +- * If base_io is set, wait for the last fragment to complete. + */ + static void crypt_dec_pending(struct dm_crypt_io *io) + { + struct crypt_config *cc = io->cc; + struct bio *base_bio = io->base_bio; +- struct dm_crypt_io *base_io = io->base_io; + int error = io->error; + + if (!atomic_dec_and_test(&io->io_pending)) +@@ -1047,16 +1062,8 @@ static void crypt_dec_pending(struct dm_crypt_io *io) + + if (io->ctx.req) + crypt_free_req(cc, io->ctx.req, base_bio); +- if (io != dm_per_bio_data(base_bio, cc->per_bio_data_size)) +- mempool_free(io, cc->io_pool); +- +- if (likely(!base_io)) +- bio_endio(base_bio, error); +- else { +- if (error && !base_io->error) +- base_io->error = error; +- crypt_dec_pending(base_io); +- } ++ ++ bio_endio(base_bio, error); + } + + /* +@@ -1117,15 +1124,15 @@ static void clone_init(struct dm_crypt_io *io, struct bio *clone) + static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp) + { + struct crypt_config *cc = io->cc; +- struct bio *base_bio = io->base_bio; + struct bio *clone; + + /* +- * The block layer might modify the bvec array, so always +- * copy the required bvecs because we need the original +- * one in order to decrypt the whole bio data *afterwards*. ++ * We need the original biovec array in order to decrypt ++ * the whole bio data *afterwards* -- thanks to immutable ++ * biovecs we don't need to worry about the block layer ++ * modifying the biovec array; so leverage bio_clone_fast(). + */ +- clone = bio_clone_bioset(base_bio, gfp, cc->bs); ++ clone = bio_clone_fast(io->base_bio, gfp, cc->bs); + if (!clone) + return 1; + +@@ -1138,37 +1145,97 @@ static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp) + return 0; + } + ++static void kcryptd_io_read_work(struct work_struct *work) ++{ ++ struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work); ++ ++ crypt_inc_pending(io); ++ if (kcryptd_io_read(io, GFP_NOIO)) ++ io->error = -ENOMEM; ++ crypt_dec_pending(io); ++} ++ ++static void kcryptd_queue_read(struct dm_crypt_io *io) ++{ ++ struct crypt_config *cc = io->cc; ++ ++ INIT_WORK(&io->work, kcryptd_io_read_work); ++ queue_work(cc->io_queue, &io->work); ++} ++ + static void kcryptd_io_write(struct dm_crypt_io *io) + { + struct bio *clone = io->ctx.bio_out; ++ + generic_make_request(clone); + } + +-static void kcryptd_io(struct work_struct *work) ++#define crypt_io_from_node(node) rb_entry((node), struct dm_crypt_io, rb_node) ++ ++static int dmcrypt_write(void *data) + { +- struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work); ++ struct crypt_config *cc = data; ++ struct dm_crypt_io *io; + +- if (bio_data_dir(io->base_bio) == READ) { +- crypt_inc_pending(io); +- if (kcryptd_io_read(io, GFP_NOIO)) +- io->error = -ENOMEM; +- crypt_dec_pending(io); +- } else +- kcryptd_io_write(io); +-} ++ while (1) { ++ struct rb_root write_tree; ++ struct blk_plug plug; + +-static void kcryptd_queue_io(struct dm_crypt_io *io) +-{ +- struct crypt_config *cc = io->cc; ++ DECLARE_WAITQUEUE(wait, current); + +- INIT_WORK(&io->work, kcryptd_io); +- queue_work(cc->io_queue, &io->work); ++ spin_lock_irq(&cc->write_thread_wait.lock); ++continue_locked: ++ ++ if (!RB_EMPTY_ROOT(&cc->write_tree)) ++ goto pop_from_list; ++ ++ __set_current_state(TASK_INTERRUPTIBLE); ++ __add_wait_queue(&cc->write_thread_wait, &wait); ++ ++ spin_unlock_irq(&cc->write_thread_wait.lock); ++ ++ if (unlikely(kthread_should_stop())) { ++ set_task_state(current, TASK_RUNNING); ++ remove_wait_queue(&cc->write_thread_wait, &wait); ++ break; ++ } ++ ++ schedule(); ++ ++ set_task_state(current, TASK_RUNNING); ++ spin_lock_irq(&cc->write_thread_wait.lock); ++ __remove_wait_queue(&cc->write_thread_wait, &wait); ++ goto continue_locked; ++ ++pop_from_list: ++ write_tree = cc->write_tree; ++ cc->write_tree = RB_ROOT; ++ spin_unlock_irq(&cc->write_thread_wait.lock); ++ ++ BUG_ON(rb_parent(write_tree.rb_node)); ++ ++ /* ++ * Note: we cannot walk the tree here with rb_next because ++ * the structures may be freed when kcryptd_io_write is called. ++ */ ++ blk_start_plug(&plug); ++ do { ++ io = crypt_io_from_node(rb_first(&write_tree)); ++ rb_erase(&io->rb_node, &write_tree); ++ kcryptd_io_write(io); ++ } while (!RB_EMPTY_ROOT(&write_tree)); ++ blk_finish_plug(&plug); ++ } ++ return 0; + } + + static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async) + { + struct bio *clone = io->ctx.bio_out; + struct crypt_config *cc = io->cc; ++ unsigned long flags; ++ sector_t sector; ++ struct rb_node **rbp, *parent; + + if (unlikely(io->error < 0)) { + crypt_free_buffer_pages(cc, clone); +@@ -1182,20 +1249,34 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async) + + clone->bi_iter.bi_sector = cc->start + io->sector; + +- if (async) +- kcryptd_queue_io(io); +- else ++ if (likely(!async) && test_bit(DM_CRYPT_NO_OFFLOAD, &cc->flags)) { + generic_make_request(clone); ++ return; ++ } ++ ++ spin_lock_irqsave(&cc->write_thread_wait.lock, flags); ++ rbp = &cc->write_tree.rb_node; ++ parent = NULL; ++ sector = io->sector; ++ while (*rbp) { ++ parent = *rbp; ++ if (sector < crypt_io_from_node(parent)->sector) ++ rbp = &(*rbp)->rb_left; ++ else ++ rbp = &(*rbp)->rb_right; ++ } ++ rb_link_node(&io->rb_node, parent, rbp); ++ rb_insert_color(&io->rb_node, &cc->write_tree); ++ ++ wake_up_locked(&cc->write_thread_wait); ++ spin_unlock_irqrestore(&cc->write_thread_wait.lock, flags); + } + + static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) + { + struct crypt_config *cc = io->cc; + struct bio *clone; +- struct dm_crypt_io *new_io; + int crypt_finished; +- unsigned out_of_pages = 0; +- unsigned remaining = io->base_bio->bi_iter.bi_size; + sector_t sector = io->sector; + int r; + +@@ -1205,80 +1286,30 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) + crypt_inc_pending(io); + crypt_convert_init(cc, &io->ctx, NULL, io->base_bio, sector); + +- /* +- * The allocated buffers can be smaller than the whole bio, +- * so repeat the whole process until all the data can be handled. +- */ +- while (remaining) { +- clone = crypt_alloc_buffer(io, remaining, &out_of_pages); +- if (unlikely(!clone)) { +- io->error = -ENOMEM; +- break; +- } +- +- io->ctx.bio_out = clone; +- io->ctx.iter_out = clone->bi_iter; +- +- remaining -= clone->bi_iter.bi_size; +- sector += bio_sectors(clone); +- +- crypt_inc_pending(io); +- +- r = crypt_convert(cc, &io->ctx); +- if (r < 0) +- io->error = -EIO; +- +- crypt_finished = atomic_dec_and_test(&io->ctx.cc_pending); +- +- /* Encryption was already finished, submit io now */ +- if (crypt_finished) { +- kcryptd_crypt_write_io_submit(io, 0); ++ clone = crypt_alloc_buffer(io, io->base_bio->bi_iter.bi_size); ++ if (unlikely(!clone)) { ++ io->error = -EIO; ++ goto dec; ++ } + +- /* +- * If there was an error, do not try next fragments. +- * For async, error is processed in async handler. +- */ +- if (unlikely(r < 0)) +- break; ++ io->ctx.bio_out = clone; ++ io->ctx.iter_out = clone->bi_iter; + +- io->sector = sector; +- } ++ sector += bio_sectors(clone); + +- /* +- * Out of memory -> run queues +- * But don't wait if split was due to the io size restriction +- */ +- if (unlikely(out_of_pages)) +- congestion_wait(BLK_RW_ASYNC, HZ/100); +- +- /* +- * With async crypto it is unsafe to share the crypto context +- * between fragments, so switch to a new dm_crypt_io structure. +- */ +- if (unlikely(!crypt_finished && remaining)) { +- new_io = mempool_alloc(cc->io_pool, GFP_NOIO); +- crypt_io_init(new_io, io->cc, io->base_bio, sector); +- crypt_inc_pending(new_io); +- crypt_convert_init(cc, &new_io->ctx, NULL, +- io->base_bio, sector); +- new_io->ctx.iter_in = io->ctx.iter_in; +- +- /* +- * Fragments after the first use the base_io +- * pending count. +- */ +- if (!io->base_io) +- new_io->base_io = io; +- else { +- new_io->base_io = io->base_io; +- crypt_inc_pending(io->base_io); +- crypt_dec_pending(io); +- } ++ crypt_inc_pending(io); ++ r = crypt_convert(cc, &io->ctx); ++ if (r) ++ io->error = -EIO; ++ crypt_finished = atomic_dec_and_test(&io->ctx.cc_pending); + +- io = new_io; +- } ++ /* Encryption was already finished, submit io now */ ++ if (crypt_finished) { ++ kcryptd_crypt_write_io_submit(io, 0); ++ io->sector = sector; + } + ++dec: + crypt_dec_pending(io); + } + +@@ -1481,6 +1512,9 @@ static void crypt_dtr(struct dm_target *ti) + if (!cc) + return; + ++ if (cc->write_thread) ++ kthread_stop(cc->write_thread); ++ + if (cc->io_queue) + destroy_workqueue(cc->io_queue); + if (cc->crypt_queue) +@@ -1495,8 +1529,6 @@ static void crypt_dtr(struct dm_target *ti) + mempool_destroy(cc->page_pool); + if (cc->req_pool) + mempool_destroy(cc->req_pool); +- if (cc->io_pool) +- mempool_destroy(cc->io_pool); + + if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) + cc->iv_gen_ops->dtr(cc); +@@ -1688,7 +1720,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) + char dummy; + + static struct dm_arg _args[] = { +- {0, 1, "Invalid number of feature args"}, ++ {0, 3, "Invalid number of feature args"}, + }; + + if (argc < 5) { +@@ -1710,13 +1742,6 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) + if (ret < 0) + goto bad; + +- ret = -ENOMEM; +- cc->io_pool = mempool_create_slab_pool(MIN_IOS, _crypt_io_pool); +- if (!cc->io_pool) { +- ti->error = "Cannot allocate crypt io mempool"; +- goto bad; +- } +- + cc->dmreq_start = sizeof(struct ablkcipher_request); + cc->dmreq_start += crypto_ablkcipher_reqsize(any_tfm(cc)); + cc->dmreq_start = ALIGN(cc->dmreq_start, __alignof__(struct dm_crypt_request)); +@@ -1734,6 +1759,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) + iv_size_padding = crypto_ablkcipher_alignmask(any_tfm(cc)); + } + ++ ret = -ENOMEM; + cc->req_pool = mempool_create_kmalloc_pool(MIN_IOS, cc->dmreq_start + + sizeof(struct dm_crypt_request) + iv_size_padding + cc->iv_size); + if (!cc->req_pool) { +@@ -1746,7 +1772,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) + sizeof(struct dm_crypt_request) + iv_size_padding + cc->iv_size, + ARCH_KMALLOC_MINALIGN); + +- cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0); ++ cc->page_pool = mempool_create_page_pool(BIO_MAX_PAGES, 0); + if (!cc->page_pool) { + ti->error = "Cannot allocate page mempool"; + goto bad; +@@ -1758,6 +1784,8 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) + goto bad; + } + ++ mutex_init(&cc->bio_alloc_lock); ++ + ret = -EINVAL; + if (sscanf(argv[2], "%llu%c", &tmpll, &dummy) != 1) { + ti->error = "Invalid iv_offset sector"; +@@ -1788,15 +1816,27 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) + if (ret) + goto bad; + +- opt_string = dm_shift_arg(&as); ++ ret = -EINVAL; ++ while (opt_params--) { ++ opt_string = dm_shift_arg(&as); ++ if (!opt_string) { ++ ti->error = "Not enough feature arguments"; ++ goto bad; ++ } + +- if (opt_params == 1 && opt_string && +- !strcasecmp(opt_string, "allow_discards")) +- ti->num_discard_bios = 1; +- else if (opt_params) { +- ret = -EINVAL; +- ti->error = "Invalid feature arguments"; +- goto bad; ++ if (!strcasecmp(opt_string, "allow_discards")) ++ ti->num_discard_bios = 1; ++ ++ else if (!strcasecmp(opt_string, "same_cpu_crypt")) ++ set_bit(DM_CRYPT_SAME_CPU, &cc->flags); ++ ++ else if (!strcasecmp(opt_string, "submit_from_crypt_cpus")) ++ set_bit(DM_CRYPT_NO_OFFLOAD, &cc->flags); ++ ++ else { ++ ti->error = "Invalid feature arguments"; ++ goto bad; ++ } + } + } + +@@ -1807,13 +1847,28 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) + goto bad; + } + +- cc->crypt_queue = alloc_workqueue("kcryptd", +- WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM, 1); ++ if (test_bit(DM_CRYPT_SAME_CPU, &cc->flags)) ++ cc->crypt_queue = alloc_workqueue("kcryptd", WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM, 1); ++ else ++ cc->crypt_queue = alloc_workqueue("kcryptd", WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM | WQ_UNBOUND, ++ num_online_cpus()); + if (!cc->crypt_queue) { + ti->error = "Couldn't create kcryptd queue"; + goto bad; + } + ++ init_waitqueue_head(&cc->write_thread_wait); ++ cc->write_tree = RB_ROOT; ++ ++ cc->write_thread = kthread_create(dmcrypt_write, cc, "dmcrypt_write"); ++ if (IS_ERR(cc->write_thread)) { ++ ret = PTR_ERR(cc->write_thread); ++ cc->write_thread = NULL; ++ ti->error = "Couldn't spawn write thread"; ++ goto bad; ++ } ++ wake_up_process(cc->write_thread); ++ + ti->num_flush_bios = 1; + ti->discard_zeroes_data_unsupported = true; + +@@ -1848,7 +1903,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio) + + if (bio_data_dir(io->base_bio) == READ) { + if (kcryptd_io_read(io, GFP_NOWAIT)) +- kcryptd_queue_io(io); ++ kcryptd_queue_read(io); + } else + kcryptd_queue_crypt(io); + +@@ -1860,6 +1915,7 @@ static void crypt_status(struct dm_target *ti, status_type_t type, + { + struct crypt_config *cc = ti->private; + unsigned i, sz = 0; ++ int num_feature_args = 0; + + switch (type) { + case STATUSTYPE_INFO: +@@ -1878,8 +1934,18 @@ static void crypt_status(struct dm_target *ti, status_type_t type, + DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset, + cc->dev->name, (unsigned long long)cc->start); + +- if (ti->num_discard_bios) +- DMEMIT(" 1 allow_discards"); ++ num_feature_args += !!ti->num_discard_bios; ++ num_feature_args += test_bit(DM_CRYPT_SAME_CPU, &cc->flags); ++ num_feature_args += test_bit(DM_CRYPT_NO_OFFLOAD, &cc->flags); ++ if (num_feature_args) { ++ DMEMIT(" %d", num_feature_args); ++ if (ti->num_discard_bios) ++ DMEMIT(" allow_discards"); ++ if (test_bit(DM_CRYPT_SAME_CPU, &cc->flags)) ++ DMEMIT(" same_cpu_crypt"); ++ if (test_bit(DM_CRYPT_NO_OFFLOAD, &cc->flags)) ++ DMEMIT(" submit_from_crypt_cpus"); ++ } + + break; + } +@@ -1976,7 +2042,7 @@ static int crypt_iterate_devices(struct dm_target *ti, + + static struct target_type crypt_target = { + .name = "crypt", +- .version = {1, 13, 0}, ++ .version = {1, 14, 0}, + .module = THIS_MODULE, + .ctr = crypt_ctr, + .dtr = crypt_dtr, +@@ -1994,15 +2060,9 @@ static int __init dm_crypt_init(void) + { + int r; + +- _crypt_io_pool = KMEM_CACHE(dm_crypt_io, 0); +- if (!_crypt_io_pool) +- return -ENOMEM; +- + r = dm_register_target(&crypt_target); +- if (r < 0) { ++ if (r < 0) + DMERR("register failed %d", r); +- kmem_cache_destroy(_crypt_io_pool); +- } + + return r; + } +@@ -2010,7 +2070,6 @@ static int __init dm_crypt_init(void) + static void __exit dm_crypt_exit(void) + { + dm_unregister_target(&crypt_target); +- kmem_cache_destroy(_crypt_io_pool); + } + + module_init(dm_crypt_init); +diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c +index cc9537e..c59f939 100644 +--- a/drivers/media/v4l2-core/videobuf2-core.c ++++ b/drivers/media/v4l2-core/videobuf2-core.c +@@ -3221,7 +3221,6 @@ EXPORT_SYMBOL_GPL(vb2_thread_start); + int vb2_thread_stop(struct vb2_queue *q) + { + struct vb2_threadio_data *threadio = q->threadio; +- struct vb2_fileio_data *fileio = q->fileio; + int err; + + if (threadio == NULL) +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index 1456ea7..da983a7 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -223,6 +223,18 @@ config MFD_HI6421_PMIC + menus in order to enable them. + We communicate with the Hi6421 via memory-mapped I/O. + ++config MFD_HISI_FMC ++ tristate "Hisilicon Flash Memory Controller" ++ depends on OF ++ select MFD_CORE ++ select REGMAP_MMIO ++ default y if (HIFMC_SPI_NAND && SPI_HISI_SFC && HIFMC_NAND) ++ help ++ If you need to use SPI nor flash or SPI nand flash at same time, ++ enable this option for swap controller. if your enable ++ HIFMC_SPI_NAND and SPI_HISI_SFC at same time, this function should ++ be select. ++ + config HTC_EGPIO + bool "HTC EGPIO support" + depends on GPIOLIB && ARM +diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile +index 8bd54b1..70a68ac 100644 +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -174,6 +174,7 @@ obj-$(CONFIG_MFD_STW481X) += stw481x.o + obj-$(CONFIG_MFD_IPAQ_MICRO) += ipaq-micro.o + obj-$(CONFIG_MFD_MENF21BMC) += menf21bmc.o + obj-$(CONFIG_MFD_HI6421_PMIC) += hi6421-pmic-core.o ++obj-$(CONFIG_MFD_HISI_FMC) += hisi_fmc.o + + intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o + obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o +diff --git a/drivers/mfd/hisi_fmc.c b/drivers/mfd/hisi_fmc.c +new file mode 100644 +index 0000000..43b771c +--- /dev/null ++++ b/drivers/mfd/hisi_fmc.c +@@ -0,0 +1,114 @@ ++/* HiSilicon Flash Memory Controller Driver ++ * ++ * Copyright (c) 2016 Hisilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++unsigned char hifmc_cs_user[HIFMC_MAX_CHIP_NUM]; ++ ++DEFINE_MUTEX(fmc_switch_mutex); ++EXPORT_SYMBOL_GPL(fmc_switch_mutex); ++ ++/* ------------------------------------------------------------------------ */ ++static const struct mfd_cell hisi_fmc_devs[] = { ++ { ++ .name = "hisi_spi_nor", ++ .of_compatible = "hisilicon,hisi-sfc", ++ }, ++ { ++ .name = "hisi_spi_nand", ++ .of_compatible = "hisilicon,hisi-spi-nand", ++ }, ++ { ++ .name = "hisi_nand", ++ .of_compatible = "hisilicon,hisi-nand", ++ }, ++}; ++ ++static int hisi_fmc_probe(struct platform_device *pdev) ++{ ++ int ret; ++ struct hisi_fmc *fmc; ++ struct resource *res; ++ ++ fmc = devm_kzalloc(&pdev->dev, sizeof(*fmc), GFP_KERNEL); ++ if (!fmc) ++ return -ENOMEM; ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control"); ++ fmc->regbase = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(fmc->regbase)) ++ return PTR_ERR(fmc->regbase); ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory"); ++ fmc->iobase = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(fmc->iobase)) ++ return PTR_ERR(fmc->iobase); ++ ++ fmc->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(fmc->clk)) ++ return PTR_ERR(fmc->clk); ++ ++ mutex_init(&fmc->lock); ++ ++ platform_set_drvdata(pdev, fmc); ++ ++ ret = mfd_add_devices(&pdev->dev, 0, hisi_fmc_devs, ++ ARRAY_SIZE(hisi_fmc_devs), NULL, 0, NULL); ++ if (ret) { ++ dev_err(&pdev->dev, "add mfd devices failed: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int hisi_fmc_remove(struct platform_device *pdev) ++{ ++ struct hisi_fmc *fmc = platform_get_drvdata(pdev); ++ ++ mfd_remove_devices(&pdev->dev); ++ mutex_destroy(&fmc->lock); ++ ++ return 0; ++} ++ ++static const struct of_device_id hisi_fmc_of_match[] = { ++ { .compatible = "hisilicon,hisi-fmc"}, ++ { } ++}; ++ ++static struct platform_driver hisi_fmc_driver = { ++ .driver = { ++ .name = "hifmc", ++ .of_match_table = hisi_fmc_of_match, ++ }, ++ .probe = hisi_fmc_probe, ++ .remove = hisi_fmc_remove, ++}; ++module_platform_driver(hisi_fmc_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("HiSilicon Flash Memory Controller Driver"); +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig +index bbeb451..14ba5bc 100644 +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -402,6 +402,10 @@ config TI_DAC7512 + This driver can also be built as a module. If so, the module + will be called ti_dac7512. + ++config UID_STAT ++ bool "UID based statistics tracking exported to /proc/uid_stat" ++ default n ++ + config VMWARE_BALLOON + tristate "VMware Balloon Driver" + depends on X86 && HYPERVISOR_GUEST +@@ -515,6 +519,12 @@ config VEXPRESS_SYSCFG + bus. System Configuration interface is one of the possible means + of generating transactions on this bus. + ++config UID_CPUTIME ++ tristate "Per-UID cpu time statistics" ++ depends on PROFILING ++ help ++ Per UID based cpu time statistics exported to /proc/uid_cputime ++ + source "drivers/misc/c2port/Kconfig" + source "drivers/misc/eeprom/Kconfig" + source "drivers/misc/cb710/Kconfig" +@@ -528,4 +538,5 @@ source "drivers/misc/mic/Kconfig" + source "drivers/misc/genwqe/Kconfig" + source "drivers/misc/echo/Kconfig" + source "drivers/misc/cxl/Kconfig" ++source "drivers/misc/hi_reg/Kconfig" + endmenu +diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile +index 7d5c4cd..ecf313b 100644 +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -34,6 +34,7 @@ obj-$(CONFIG_ISL29020) += isl29020.o + obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o + obj-$(CONFIG_DS1682) += ds1682.o + obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o ++obj-$(CONFIG_UID_STAT) += uid_stat.o + obj-$(CONFIG_C2PORT) += c2port/ + obj-$(CONFIG_HMC6352) += hmc6352.o + obj-y += eeprom/ +@@ -56,3 +57,5 @@ obj-$(CONFIG_GENWQE) += genwqe/ + obj-$(CONFIG_ECHO) += echo/ + obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o + obj-$(CONFIG_CXL_BASE) += cxl/ ++obj-$(CONFIG_UID_CPUTIME) += uid_cputime.o ++obj-y += hi_reg/ +diff --git a/drivers/misc/hi_reg/Kconfig b/drivers/misc/hi_reg/Kconfig +new file mode 100644 +index 0000000..76c8741 +--- /dev/null ++++ b/drivers/misc/hi_reg/Kconfig +@@ -0,0 +1,13 @@ ++menu "hisi 'himm/himd.l/himc'support" ++ ++config HISI_REG ++ tristate "hisi \"himd\" \"himm\" \"himc\" support" ++ default y if (ARCH_HI3519) ++ default y if (ARCH_HI3519V101) ++ help ++ This selects the Hisilicon io register access support ++ If you want use "himd" "himm" "himc" command, ++ Say Y or M here. ++ ++ Default is Y. ++endmenu +diff --git a/drivers/misc/hi_reg/Makefile b/drivers/misc/hi_reg/Makefile +new file mode 100644 +index 0000000..5c66458 +--- /dev/null ++++ b/drivers/misc/hi_reg/Makefile +@@ -0,0 +1 @@ ++obj-$(CONFIG_HISI_REG) += hi_reg.o +diff --git a/drivers/misc/hi_reg/hi_reg.c b/drivers/misc/hi_reg/hi_reg.c +new file mode 100644 +index 0000000..3dbdfd1 +--- /dev/null ++++ b/drivers/misc/hi_reg/hi_reg.c +@@ -0,0 +1,164 @@ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "hi_reg_user.h" ++ ++static int hi_reg_open(struct inode *inode, struct file *file) ++{ ++ return 0; ++} ++ ++static int hi_reg_release(struct inode *inode, struct file *file) ++{ ++ return 0; ++} ++ ++static int hi_reg_read(struct file *file, char __user *buf, ++ size_t count, loff_t *f_pos) ++{ ++ return 0; ++} ++ ++static int hi_reg_write(struct file *file, const char __user *buf, ++ size_t count, loff_t *f_pos) ++{ ++ return 0; ++} ++ ++ ++static long hi_reg_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ void __iomem *virt_addr; ++ struct hi_reg_handle handle; ++ int valid_addr = 0; ++ unsigned int new_value = 0; ++ ++ if (copy_from_user((void *)&handle, (void *)arg, ++ sizeof(struct hi_reg_handle))) { ++ printk(KERN_ERR"hi reg copy from user error!\n"); ++ return -EFAULT; ++ } ++ ++ /* phys addr must be aligned by 4 bytes */ ++ if (!handle.phys_addr || (handle.phys_addr & (sizeof(u32) - 1))) { ++ printk(KERN_ERR"phys addr not aligned by 4 bytes,which is [0x%08x]!\n", ++ handle.phys_addr); ++ return -EFAULT; ++ } ++ ++#ifdef CONFIG_ARCH_HI3516AV200 ++ /* phys addr must be in IO_ADDRESS */ ++ if ((handle.phys_addr >= HI3516AV200_IOCH3_PHYS) ++ && (handle.phys_addr < HI3516AV200_IOCH3_PHYS + HI3516AV200_IOCH3_SIZE)) { ++ valid_addr = 1; ++ } else if ((handle.phys_addr >= HI3516AV200_IOCH2_PHYS) ++ && (handle.phys_addr < HI3516AV200_IOCH2_PHYS + HI3516AV200_IOCH2_SIZE)) { ++ valid_addr = 1; ++ } else if ((handle.phys_addr >= HI3516AV200_IOCH1_PHYS) ++ && (handle.phys_addr < HI3516AV200_IOCH1_PHYS + HI3516AV200_IOCH1_SIZE)) { ++ valid_addr = 1; ++ } ++#endif ++ ++#if defined(CONFIG_ARCH_HI3519) || defined(CONFIG_ARCH_HI3519V101) ++ /* phys addr must be in IO_ADDRESS */ ++ if ((handle.phys_addr >= HI3519_IOCH3_PHYS) ++ && (handle.phys_addr < HI3519_IOCH3_PHYS + HI3519_IOCH3_SIZE)) { ++ valid_addr = 1; ++ } else if ((handle.phys_addr >= HI3519_IOCH2_PHYS) ++ && (handle.phys_addr < HI3519_IOCH2_PHYS + HI3519_IOCH2_SIZE)) { ++ valid_addr = 1; ++ } else if ((handle.phys_addr >= HI3519_IOCH1_PHYS) ++ && (handle.phys_addr < HI3519_IOCH1_PHYS + HI3519_IOCH1_SIZE)) { ++ valid_addr = 1; ++ } ++#endif ++ ++ if (!valid_addr) { ++ printk(KERN_ERR"invalid addr, which is [0x%08x]!\n", ++ handle.phys_addr); ++ return -EFAULT; ++ } ++ if ('R' == _IOC_TYPE(cmd)) { ++ switch (_IOC_NR(cmd)) { ++ case _IOC_NR(HI_REG_READ): ++ virt_addr = (void *)IO_ADDRESS(handle.phys_addr); ++ new_value = hi_readl(virt_addr); ++ handle.data = (void *)new_value; ++ if (copy_to_user((void *)arg, (void *)&handle, ++ sizeof(struct hi_reg_handle))) { ++ printk(KERN_ERR"hi reg copy to user error!\n"); ++ return -EFAULT; ++ } ++ break; ++ ++ case _IOC_NR(HI_REG_WRITE): ++ virt_addr = (void *)IO_ADDRESS(handle.phys_addr); ++ ++ if (sizeof(u32) == handle.size) { ++ hi_writel((u32)handle.data, virt_addr); ++ } else if (sizeof(u16) == handle.size) { ++ hi_writew(((u32)handle.data & 0xFFFF), virt_addr); ++ } else if (sizeof(u8) == handle.size) { ++ hi_writeb(((u32)handle.data & 0xFF), virt_addr); ++ } else { ++ printk(KERN_ERR"%d, write size should be 1, 2 or 4!\n", __LINE__); ++ } ++ break; ++ ++ default: ++ printk(KERN_ERR"%d, hi reg unknow cmd!\n", __LINE__); ++ break; ++ } ++ } else { ++ printk(KERN_ERR"%d, hi reg unknow cmd!\n", __LINE__); ++ } ++ return 0; ++} ++ ++static const struct file_operations hi_reg_fops = { ++ .owner = THIS_MODULE, ++ .open = hi_reg_open, ++ .release = hi_reg_release, ++ .unlocked_ioctl = hi_reg_ioctl, ++ .write = hi_reg_write, ++ .read = hi_reg_read ++}; ++ ++static struct miscdevice hi_reg_dev = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .fops = &hi_reg_fops, ++ .name = "hi_reg" ++}; ++ ++static int __init hi_reg_init(void) ++{ ++ int ret; ++ ret = misc_register(&hi_reg_dev); ++ if (ret) { ++ printk("register hi_reg device failed!"); ++ } ++ return ret; ++} ++ ++void __exit hi_reg_exit(void) ++{ ++ misc_deregister(&hi_reg_dev); ++} ++#ifndef MODULE ++subsys_initcall(hi_reg_init); ++#else ++module_init(hi_reg_init); ++#endif ++module_exit(hi_reg_exit); ++ ++MODULE_DESCRIPTION("Driver for himd/himm/himc"); ++MODULE_AUTHOR("ou jinsong"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/misc/hi_reg/hi_reg_user.h b/drivers/misc/hi_reg/hi_reg_user.h +new file mode 100644 +index 0000000..21e2e76 +--- /dev/null ++++ b/drivers/misc/hi_reg/hi_reg_user.h +@@ -0,0 +1,21 @@ ++#include ++ ++#ifndef __HI_REG_USER_H__ ++#define __HI_REG_USER_H__ ++ ++struct hi_reg_handle { ++ unsigned int phys_addr; ++ unsigned int size; ++ void *data; ++ int flags; ++}; ++ ++ ++#define HI_REG_BASE 'R' ++ ++#define HI_REG_READ \ ++ _IOW(HI_REG_BASE, 1, struct hi_reg_handle) ++#define HI_REG_WRITE \ ++ _IOW(HI_REG_BASE, 2, struct hi_reg_handle) ++ ++#endif /* __HI_REG_USER_H__ */ +diff --git a/drivers/misc/uid_cputime.c b/drivers/misc/uid_cputime.c +new file mode 100644 +index 0000000..43298a4 +--- /dev/null ++++ b/drivers/misc/uid_cputime.c +@@ -0,0 +1,253 @@ ++/* drivers/misc/uid_cputime.c ++ * ++ * Copyright (C) 2014 - 2015 Google, 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. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define UID_HASH_BITS 10 ++DECLARE_HASHTABLE(hash_table, UID_HASH_BITS); ++ ++static DEFINE_MUTEX(uid_lock); ++static struct proc_dir_entry *parent; ++ ++struct uid_entry { ++ uid_t uid; ++ cputime_t utime; ++ cputime_t stime; ++ cputime_t active_utime; ++ cputime_t active_stime; ++ unsigned long long active_power; ++ unsigned long long power; ++ struct hlist_node hash; ++}; ++ ++static struct uid_entry *find_uid_entry(uid_t uid) ++{ ++ struct uid_entry *uid_entry; ++ hash_for_each_possible(hash_table, uid_entry, hash, uid) { ++ if (uid_entry->uid == uid) ++ return uid_entry; ++ } ++ return NULL; ++} ++ ++static struct uid_entry *find_or_register_uid(uid_t uid) ++{ ++ struct uid_entry *uid_entry; ++ ++ uid_entry = find_uid_entry(uid); ++ if (uid_entry) ++ return uid_entry; ++ ++ uid_entry = kzalloc(sizeof(struct uid_entry), GFP_ATOMIC); ++ if (!uid_entry) ++ return NULL; ++ ++ uid_entry->uid = uid; ++ ++ hash_add(hash_table, &uid_entry->hash, uid); ++ ++ return uid_entry; ++} ++ ++static int uid_stat_show(struct seq_file *m, void *v) ++{ ++ struct uid_entry *uid_entry; ++ struct task_struct *task, *temp; ++ cputime_t utime; ++ cputime_t stime; ++ unsigned long bkt; ++ ++ mutex_lock(&uid_lock); ++ ++ hash_for_each(hash_table, bkt, uid_entry, hash) { ++ uid_entry->active_stime = 0; ++ uid_entry->active_utime = 0; ++ uid_entry->active_power = 0; ++ } ++ ++ read_lock(&tasklist_lock); ++ do_each_thread(temp, task) { ++ uid_entry = find_or_register_uid(from_kuid_munged( ++ current_user_ns(), task_uid(task))); ++ if (!uid_entry) { ++ read_unlock(&tasklist_lock); ++ mutex_unlock(&uid_lock); ++ pr_err("%s: failed to find the uid_entry for uid %d\n", ++ __func__, from_kuid_munged(current_user_ns(), ++ task_uid(task))); ++ return -ENOMEM; ++ } ++ /* if this task is exiting, we have already accounted for the ++ * time and power. ++ */ ++ if (task->cpu_power == ULLONG_MAX) ++ continue; ++ task_cputime_adjusted(task, &utime, &stime); ++ uid_entry->active_utime += utime; ++ uid_entry->active_stime += stime; ++ uid_entry->active_power += task->cpu_power; ++ } while_each_thread(temp, task); ++ read_unlock(&tasklist_lock); ++ ++ hash_for_each(hash_table, bkt, uid_entry, hash) { ++ cputime_t total_utime = uid_entry->utime + ++ uid_entry->active_utime; ++ cputime_t total_stime = uid_entry->stime + ++ uid_entry->active_stime; ++ unsigned long long total_power = uid_entry->power + ++ uid_entry->active_power; ++ seq_printf(m, "%d: %llu %llu %llu\n", uid_entry->uid, ++ (unsigned long long)jiffies_to_msecs( ++ cputime_to_jiffies(total_utime)) * USEC_PER_MSEC, ++ (unsigned long long)jiffies_to_msecs( ++ cputime_to_jiffies(total_stime)) * USEC_PER_MSEC, ++ total_power); ++ } ++ ++ mutex_unlock(&uid_lock); ++ return 0; ++} ++ ++static int uid_stat_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, uid_stat_show, PDE_DATA(inode)); ++} ++ ++static const struct file_operations uid_stat_fops = { ++ .open = uid_stat_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int uid_remove_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, NULL, NULL); ++} ++ ++static ssize_t uid_remove_write(struct file *file, ++ const char __user *buffer, size_t count, loff_t *ppos) ++{ ++ struct uid_entry *uid_entry; ++ struct hlist_node *tmp; ++ char uids[128]; ++ char *start_uid, *end_uid = NULL; ++ long int uid_start = 0, uid_end = 0; ++ ++ if (count >= sizeof(uids)) ++ count = sizeof(uids) - 1; ++ ++ if (copy_from_user(uids, buffer, count)) ++ return -EFAULT; ++ ++ uids[count] = '\0'; ++ end_uid = uids; ++ start_uid = strsep(&end_uid, "-"); ++ ++ if (!start_uid || !end_uid) ++ return -EINVAL; ++ ++ if (kstrtol(start_uid, 10, &uid_start) != 0 || ++ kstrtol(end_uid, 10, &uid_end) != 0) { ++ return -EINVAL; ++ } ++ ++ mutex_lock(&uid_lock); ++ ++ for (; uid_start <= uid_end; uid_start++) { ++ hash_for_each_possible_safe(hash_table, uid_entry, tmp, ++ hash, uid_start) { ++ hash_del(&uid_entry->hash); ++ kfree(uid_entry); ++ } ++ } ++ ++ mutex_unlock(&uid_lock); ++ return count; ++} ++ ++static const struct file_operations uid_remove_fops = { ++ .open = uid_remove_open, ++ .release = single_release, ++ .write = uid_remove_write, ++}; ++ ++static int process_notifier(struct notifier_block *self, ++ unsigned long cmd, void *v) ++{ ++ struct task_struct *task = v; ++ struct uid_entry *uid_entry; ++ cputime_t utime, stime; ++ uid_t uid; ++ ++ if (!task) ++ return NOTIFY_OK; ++ ++ mutex_lock(&uid_lock); ++ uid = from_kuid_munged(current_user_ns(), task_uid(task)); ++ uid_entry = find_or_register_uid(uid); ++ if (!uid_entry) { ++ pr_err("%s: failed to find uid %d\n", __func__, uid); ++ goto exit; ++ } ++ ++ task_cputime_adjusted(task, &utime, &stime); ++ uid_entry->utime += utime; ++ uid_entry->stime += stime; ++ uid_entry->power += task->cpu_power; ++ task->cpu_power = ULLONG_MAX; ++ ++exit: ++ mutex_unlock(&uid_lock); ++ return NOTIFY_OK; ++} ++ ++static struct notifier_block process_notifier_block = { ++ .notifier_call = process_notifier, ++}; ++ ++static int __init proc_uid_cputime_init(void) ++{ ++ hash_init(hash_table); ++ ++ parent = proc_mkdir("uid_cputime", NULL); ++ if (!parent) { ++ pr_err("%s: failed to create proc entry\n", __func__); ++ return -ENOMEM; ++ } ++ ++ proc_create_data("remove_uid_range", S_IWUGO, parent, &uid_remove_fops, ++ NULL); ++ ++ proc_create_data("show_uid_stat", S_IRUGO, parent, &uid_stat_fops, ++ NULL); ++ ++ profile_event_register(PROFILE_TASK_EXIT, &process_notifier_block); ++ ++ return 0; ++} ++ ++early_initcall(proc_uid_cputime_init); +diff --git a/drivers/misc/uid_stat.c b/drivers/misc/uid_stat.c +new file mode 100644 +index 0000000..4766c1f +--- /dev/null ++++ b/drivers/misc/uid_stat.c +@@ -0,0 +1,152 @@ ++/* drivers/misc/uid_stat.c ++ * ++ * Copyright (C) 2008 - 2009 Google, 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. ++ * ++ */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static DEFINE_SPINLOCK(uid_lock); ++static LIST_HEAD(uid_list); ++static struct proc_dir_entry *parent; ++ ++struct uid_stat { ++ struct list_head link; ++ uid_t uid; ++ atomic_t tcp_rcv; ++ atomic_t tcp_snd; ++}; ++ ++static struct uid_stat *find_uid_stat(uid_t uid) { ++ struct uid_stat *entry; ++ ++ list_for_each_entry(entry, &uid_list, link) { ++ if (entry->uid == uid) { ++ return entry; ++ } ++ } ++ return NULL; ++} ++ ++static int uid_stat_atomic_int_show(struct seq_file *m, void *v) ++{ ++ unsigned int bytes; ++ atomic_t *counter = m->private; ++ ++ bytes = (unsigned int) (atomic_read(counter) + INT_MIN); ++ return seq_printf(m, "%u\n", bytes); ++} ++ ++static int uid_stat_read_atomic_int_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, uid_stat_atomic_int_show, PDE_DATA(inode)); ++} ++ ++static const struct file_operations uid_stat_read_atomic_int_fops = { ++ .open = uid_stat_read_atomic_int_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = seq_release, ++}; ++ ++/* Create a new entry for tracking the specified uid. */ ++static struct uid_stat *create_stat(uid_t uid) { ++ struct uid_stat *new_uid; ++ /* Create the uid stat struct and append it to the list. */ ++ new_uid = kmalloc(sizeof(struct uid_stat), GFP_ATOMIC); ++ if (!new_uid) ++ return NULL; ++ ++ new_uid->uid = uid; ++ /* Counters start at INT_MIN, so we can track 4GB of network traffic. */ ++ atomic_set(&new_uid->tcp_rcv, INT_MIN); ++ atomic_set(&new_uid->tcp_snd, INT_MIN); ++ ++ list_add_tail(&new_uid->link, &uid_list); ++ return new_uid; ++} ++ ++static void create_stat_proc(struct uid_stat *new_uid) ++{ ++ char uid_s[32]; ++ struct proc_dir_entry *entry; ++ sprintf(uid_s, "%d", new_uid->uid); ++ entry = proc_mkdir(uid_s, parent); ++ ++ /* Keep reference to uid_stat so we know what uid to read stats from. */ ++ proc_create_data("tcp_snd", S_IRUGO, entry, ++ &uid_stat_read_atomic_int_fops, &new_uid->tcp_snd); ++ ++ proc_create_data("tcp_rcv", S_IRUGO, entry, ++ &uid_stat_read_atomic_int_fops, &new_uid->tcp_rcv); ++} ++ ++static struct uid_stat *find_or_create_uid_stat(uid_t uid) ++{ ++ struct uid_stat *entry; ++ unsigned long flags; ++ spin_lock_irqsave(&uid_lock, flags); ++ entry = find_uid_stat(uid); ++ if (entry) { ++ spin_unlock_irqrestore(&uid_lock, flags); ++ return entry; ++ } ++ entry = create_stat(uid); ++ spin_unlock_irqrestore(&uid_lock, flags); ++ if (entry) ++ create_stat_proc(entry); ++ return entry; ++} ++ ++int uid_stat_tcp_snd(uid_t uid, int size) { ++ struct uid_stat *entry; ++ activity_stats_update(); ++ entry = find_or_create_uid_stat(uid); ++ if (!entry) ++ return -1; ++ atomic_add(size, &entry->tcp_snd); ++ return 0; ++} ++ ++int uid_stat_tcp_rcv(uid_t uid, int size) { ++ struct uid_stat *entry; ++ activity_stats_update(); ++ entry = find_or_create_uid_stat(uid); ++ if (!entry) ++ return -1; ++ atomic_add(size, &entry->tcp_rcv); ++ return 0; ++} ++ ++static int __init uid_stat_init(void) ++{ ++ parent = proc_mkdir("uid_stat", NULL); ++ if (!parent) { ++ pr_err("uid_stat: failed to create proc entry\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++__initcall(uid_stat_init); +diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig +index 5562308..79d8212 100644 +--- a/drivers/mmc/card/Kconfig ++++ b/drivers/mmc/card/Kconfig +@@ -50,6 +50,15 @@ config MMC_BLOCK_BOUNCE + + If unsure, say Y here. + ++config MMC_BLOCK_DEFERRED_RESUME ++ bool "Deferr MMC layer resume until I/O is requested" ++ depends on MMC_BLOCK ++ default n ++ help ++ Say Y here to enable deferred MMC resume until I/O ++ is requested. This will reduce overall resume latency and ++ save power when theres an SD card inserted but not being used. ++ + config SDIO_UART + tristate "SDIO UART/GPS class support" + depends on TTY +diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c +index 10ecc0a..fd8f4b3 100644 +--- a/drivers/mmc/card/block.c ++++ b/drivers/mmc/card/block.c +@@ -36,6 +36,9 @@ + #include + #include + ++#define CREATE_TRACE_POINTS ++#include ++ + #include + #include + #include +@@ -136,6 +139,7 @@ static inline int mmc_blk_part_switch(struct mmc_card *card, + struct mmc_blk_data *md); + static int get_card_status(struct mmc_card *card, u32 *status, int retries); + ++#if 0 + static inline void mmc_blk_clear_packed(struct mmc_queue_req *mqrq) + { + struct mmc_packed *packed = mqrq->packed; +@@ -148,6 +152,7 @@ static inline void mmc_blk_clear_packed(struct mmc_queue_req *mqrq) + packed->retries = 0; + packed->blocks = 0; + } ++#endif + + static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) + { +@@ -166,11 +171,7 @@ static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) + + static inline int mmc_get_devidx(struct gendisk *disk) + { +- int devmaj = MAJOR(disk_devt(disk)); +- int devidx = MINOR(disk_devt(disk)) / perdev_minors; +- +- if (!devmaj) +- devidx = disk->first_minor / perdev_minors; ++ int devidx = disk->first_minor / perdev_minors; + return devidx; + } + +@@ -427,9 +428,11 @@ static int ioctl_do_sanitize(struct mmc_card *card) + pr_debug("%s: %s - SANITIZE IN PROGRESS...\n", + mmc_hostname(card->host), __func__); + ++ trace_mmc_blk_erase_start(EXT_CSD_SANITIZE_START, 0, 0); + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_SANITIZE_START, 1, + MMC_SANITIZE_REQ_TIMEOUT); ++ trace_mmc_blk_erase_end(EXT_CSD_SANITIZE_START, 0, 0); + + if (err) + pr_err("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n", +@@ -668,6 +671,7 @@ static inline int mmc_blk_part_switch(struct mmc_card *card, + return 0; + } + ++#if 0 + static u32 mmc_sd_num_wr_blocks(struct mmc_card *card) + { + int err; +@@ -722,6 +726,7 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card) + + return result; + } ++#endif + + static int get_card_status(struct mmc_card *card, u32 *status, int retries) + { +@@ -852,18 +857,22 @@ static int mmc_blk_cmd_error(struct request *req, const char *name, int error, + req->rq_disk->disk_name, "timed out", name, status); + + /* If the status cmd initially failed, retry the r/w cmd */ +- if (!status_valid) ++ if (!status_valid) { ++ pr_err("%s: status not valid, retrying timeout\n", req->rq_disk->disk_name); + return ERR_RETRY; +- ++ } + /* + * If it was a r/w cmd crc error, or illegal command + * (eg, issued in wrong state) then retry - we should + * have corrected the state problem above. + */ +- if (status & (R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND)) ++ if (status & (R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND)) { ++ pr_err("%s: command error, retrying timeout\n", req->rq_disk->disk_name); + return ERR_RETRY; ++ } + + /* Otherwise abort the command */ ++ pr_err("%s: not retrying timeout\n", req->rq_disk->disk_name); + return ERR_ABORT; + + default: +@@ -1003,6 +1012,14 @@ static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host, + return -EEXIST; + + md->reset_done |= type; ++ ++#if !defined(CONFIG_ARCH_HI3559) && !defined(CONFIG_ARCH_HI3556) ++ /*Step1: try to software reset*/ ++ if (mmc_sw_reset(host) == 0) ++ return 0; ++#endif ++ ++ /*Step2: try to hardware reset*/ + err = mmc_hw_reset(host); + /* Ensure we switch back to the correct partition */ + if (err != -EOPNOTSUPP) { +@@ -1195,13 +1212,11 @@ static inline void mmc_apply_rel_rw(struct mmc_blk_request *brq, + R1_CC_ERROR | /* Card controller error */ \ + R1_ERROR) /* General/unknown error */ + +-static int mmc_blk_err_check(struct mmc_card *card, +- struct mmc_async_req *areq) ++int mmc_blk_err_check(struct mmc_card *card, ++ struct mmc_req_mrq *req_mrq) + { +- struct mmc_queue_req *mq_mrq = container_of(areq, struct mmc_queue_req, +- mmc_active); +- struct mmc_blk_request *brq = &mq_mrq->brq; +- struct request *req = mq_mrq->req; ++ struct mmc_blk_request *brq = &req_mrq->brq; ++ struct request *req = req_mrq->req; + int ecc_err = 0, gen_err = 0; + + /* +@@ -1287,19 +1302,13 @@ static int mmc_blk_err_check(struct mmc_card *card, + if (!brq->data.bytes_xfered) + return MMC_BLK_RETRY; + +- if (mmc_packed_cmd(mq_mrq->cmd_type)) { +- if (unlikely(brq->data.blocks << 9 != brq->data.bytes_xfered)) +- return MMC_BLK_PARTIAL; +- else +- return MMC_BLK_SUCCESS; +- } +- + if (blk_rq_bytes(req) != brq->data.bytes_xfered) + return MMC_BLK_PARTIAL; + + return MMC_BLK_SUCCESS; + } + ++#if 0 + static int mmc_blk_packed_err_check(struct mmc_card *card, + struct mmc_async_req *areq) + { +@@ -2021,61 +2030,470 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) + + return 0; + } ++#endif ++ ++static int mmc_send_reqs(struct mmc_req_mrq *req_mrq, ++ struct mmc_card *card, ++ struct mmc_queue *mq) ++{ ++ u32 readcmd, writecmd; ++ struct mmc_queue_req *mqrq = mq->mqrq_cur; ++ struct mmc_blk_request *brq; ++ struct request *req = req_mrq->req; ++ struct mmc_blk_data *md = mq->data; ++ bool do_data_tag; ++ int err = 0; ++ ++ /* ++ * Reliable writes are used to implement Forced Unit Access and ++ * REQ_META accesses, and are supported only on MMCs. ++ * ++ * XXX: this really needs a good explanation of why REQ_META ++ * is treated special. ++ */ ++ bool do_rel_wr = ((req->cmd_flags & REQ_FUA) || ++ (req->cmd_flags & REQ_META)) && ++ (rq_data_dir(req) == WRITE) && ++ (md->flags & MMC_BLK_REL_WR); ++ ++ /* ++ * prepare for each request ++ */ ++ mqrq->req = req; ++ brq = &req_mrq->brq; ++ ++ brq->mrq.cmd = &brq->cmd; ++ brq->mrq.data = &brq->data; ++ brq->cmd.data = &brq->data; ++ brq->cmd.mrq = &brq->mrq; ++ ++ brq->cmd.arg = blk_rq_pos(req); ++ if (!mmc_card_blockaddr(card)) ++ brq->cmd.arg <<= 9; ++ brq->cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; ++ brq->cmd.flags |= MMC_CMD_TYPE_RW; ++ brq->data.blksz = 512; ++ brq->stop.opcode = MMC_STOP_TRANSMISSION; ++ brq->stop.arg = 0; ++ brq->data.blocks = blk_rq_sectors(req); ++ ++ /* ++ * The block layer doesn't support all sector count ++ * restrictions, so we need to be prepared for too big ++ * requests. ++ */ ++ if (brq->data.blocks > card->host->max_blk_count) ++ brq->data.blocks = card->host->max_blk_count; ++ ++ if (brq->data.blocks > 1) { ++ /* ++ * Some controllers have HW issues while operating ++ * in multiple I/O mode ++ */ ++ if (card->host->ops->multi_io_quirk) ++ brq->data.blocks = card->host->ops->multi_io_quirk(card, ++ (rq_data_dir(req) == READ) ? ++ MMC_DATA_READ : MMC_DATA_WRITE, ++ brq->data.blocks); ++ } ++ ++ if (brq->data.blocks > 1 || do_rel_wr) { ++ /* SPI multiblock writes terminate using a special ++ * token, not a STOP_TRANSMISSION request. ++ */ ++ if (!mmc_host_is_spi(card->host) || ++ rq_data_dir(req) == READ) ++ brq->mrq.stop = &brq->stop; ++ readcmd = MMC_READ_MULTIPLE_BLOCK; ++ writecmd = MMC_WRITE_MULTIPLE_BLOCK; ++ } else { ++ brq->mrq.stop = NULL; ++ readcmd = MMC_READ_SINGLE_BLOCK; ++ writecmd = MMC_WRITE_BLOCK; ++ } ++ if (rq_data_dir(req) == READ) { ++ brq->cmd.opcode = readcmd; ++ brq->data.flags |= MMC_DATA_READ; ++ if (brq->mrq.stop) ++ brq->stop.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | ++ MMC_CMD_AC; ++ } else { ++ brq->cmd.opcode = writecmd; ++ brq->data.flags |= MMC_DATA_WRITE; ++ if (brq->mrq.stop) ++ brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | ++ MMC_CMD_AC; ++ } ++ ++ if (do_rel_wr) ++ mmc_apply_rel_rw(brq, card, req); ++ /* ++ * When 4KB native sector is enabled, only 8 blocks ++ * multiple read or write is allowed ++ */ ++ if ((brq->data.blocks & 0x07) && ++ (card->ext_csd.data_sector_size == 4096)) { ++ pr_err("%s: Transfer size is not 4KB sector size aligned\n", ++ req->rq_disk->disk_name); ++ err = -EMEDIUMTYPE; ++ goto prep_err; ++ } ++ ++ /* ++ * Data tag is used only during writing meta data to speed ++ * up write and any subsequent read of this meta data ++ */ ++ do_data_tag = (card->ext_csd.data_tag_unit_size) && ++ (req->cmd_flags & REQ_META) && ++ (rq_data_dir(req) == WRITE) && ++ ((brq->data.blocks * brq->data.blksz) >= ++ card->ext_csd.data_tag_unit_size); ++ ++ /* ++ * Pre-defined multi-block transfers are preferable to ++ * open ended-ones (and necessary for reliable writes). ++ * However, it is not sufficient to just send CMD23, ++ * and avoid the final CMD12, as on an error condition ++ * CMD12 (stop) needs to be sent anyway. This, coupled ++ * with Auto-CMD23 enhancements provided by some ++ * hosts, means that the complexity of dealing ++ * with this is best left to the host. If CMD23 is ++ * supported by card and host, we'll fill sbc in and let ++ * the host deal with handling it correctly. This means ++ * that for hosts that don't expose MMC_CAP_CMD23, no ++ * change of behavior will be observed. ++ * ++ * N.B: Some MMC cards experience perf degradation. ++ * We'll avoid using CMD23-bounded multiblock writes for ++ * these, while retaining features like reliable writes. ++ */ ++ if ((md->flags & MMC_BLK_CMD23) && mmc_op_multi(brq->cmd.opcode) && ++ (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23) || ++ do_data_tag)) { ++ brq->sbc.opcode = MMC_SET_BLOCK_COUNT; ++ brq->sbc.arg = brq->data.blocks | ++ (do_rel_wr ? (1 << 31) : 0) | ++ (do_data_tag ? (1 << 29) : 0); ++ brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC; ++ brq->mrq.sbc = &brq->sbc; ++ } ++ ++ mmc_set_data_timeout(&brq->data, card); ++ ++ mqrq->sg = req_mrq->sg; ++ brq->data.sg = req_mrq->sg; ++ brq->data.sg_len = mmc_queue_map_sg(mq, mqrq); ++ ++ /* ++ * Adjust the sg list so it is the same size as the ++ * request. ++ */ ++ if (brq->data.blocks != blk_rq_sectors(req)) { ++ int i, data_size = brq->data.blocks << 9; ++ struct scatterlist *sg; ++ ++ for_each_sg(brq->data.sg, sg, brq->data.sg_len, i) { ++ data_size -= sg->length; ++ if (data_size <= 0) { ++ sg->length += data_size; ++ i++; ++ break; ++ } ++ } ++ brq->data.sg_len = i; ++ } ++ ++ err = __mmc_start_data_req(card->host, &brq->mrq); ++ ++ if (err) { ++ mmc_trace(3, "send mrq fail!\n"); ++ goto prep_err; ++ } else { ++ req_mrq->wr_pos = brq->mrq.wr_pos; ++ mmc_trace(3, "write pos is %d", req_mrq->wr_pos); ++ return 0; ++ } ++prep_err: ++ return err; ++} ++ ++/* ++ * mmc_wait_reqs_done() - wait multi packet intr to wake up ++ * @host: MMC host to prepare the command. ++ * Blocks MMC context till host controller will ack intr of multi-pactet ++ */ ++void mmc_wait_reqs_done(struct mmc_host *host) ++{ ++ struct mmc_context_info *context_info = &host->context_info; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&context_info->lock, flags); ++ context_info->is_waiting_last_req = true; ++ spin_unlock_irqrestore(&context_info->lock, flags); ++ ++ mmc_trace(3, "wait intr..."); ++ wait_event_interruptible(context_info->wait, ++ (context_info->is_done_rcv || ++ context_info->is_new_req)); ++ mmc_trace(3, "intr wake up"); ++ ++ spin_lock_irqsave(&context_info->lock, flags); ++ context_info->is_waiting_last_req = false; ++ context_info->is_done_rcv = false; ++ context_info->is_new_req = false; ++ spin_unlock_irqrestore(&context_info->lock, flags); ++} ++ ++#define MMC_CMD_SUCCESS (0) ++#define MMC_CMD_ABORT (1) ++/* ++ * mmc_req_retrieve() - retrieve all of request that has completed ++ * @mq: request queue that has attached to card. ++ * @host: MMC host to prepare the command. ++ * @drain: retrieve all request if true. ++ * Blocks MMC context till host controller will ack end of data request ++ * execution or new request notification arrives from the block layer. ++ * Handles command retries. ++ * ++ * Returns enum mmc_blk_status of checking errors. ++ */ ++int mmc_blk_retrieve_reqs(struct mmc_queue *mq, ++ struct mmc_host *host, bool drain) ++{ ++ struct mmc_blk_data *md = mq->data; ++ struct mmc_card *card = md->queue.card; ++ struct request *req; ++ struct mmc_blk_request *brq; ++ struct mmc_req_mrq *req_mrq; ++ struct mmc_xmited *xmited = &mq->xmited; ++ enum mmc_blk_status status = MMC_BLK_SUCCESS; ++ bool res = false; ++ int rd_pos, type; ++ unsigned int cmd_flags; ++ ++ while (!mmc_xmited_empty(xmited)) { ++ rd_pos = host->ops->get_rd(host); ++ req_mrq = xmited->rq_buf[xmited->start]; ++ mmc_trace(3, "remain %d, cmd ptr %d, read ptr %d", ++ xmited->used, req_mrq->wr_pos, rd_pos); ++ mmc_trace(3, "status = %d", host->status); ++ if (!host->status && (req_mrq->wr_pos == rd_pos)) { ++ mmc_trace(3, "no new request complete"); ++ if (drain) { ++ if (!(req_mrq->brq.cmd.flags & MMC_CMD_NON_BLOCKING)) ++ mmc_wait_reqs_done(host); ++ continue; ++ } else { ++ break; ++ } ++ } ++ req = req_mrq->req; ++ brq = &req_mrq->brq; ++ ++ if (brq->cmd.resp[0] & CMD_ERRORS || brq->cmd.error || brq->data.error) { ++ pr_info("%s: req failed (CMD%u) cmd %d data %d cmd resp:%x\n", ++ mmc_hostname(host), brq->cmd.opcode, ++ brq->cmd.error, brq->data.error, brq->cmd.resp[0]); ++ status = xmited->err_check(card, req_mrq); ++ } else { ++ host->ops->post_req(host, &brq->mrq, 0); ++ res = blk_end_request(req, 0, brq->data.bytes_xfered); ++ mmc_put_rbuf(xmited, req_mrq); ++ if (res) { ++ pr_info("%s BUG d_totel %d d_xfer %d\n", ++ __func__, blk_rq_bytes(req), ++ brq->data.bytes_xfered); ++ blk_requeue_request(mq->queue, req); ++ } ++ } ++ ++ type = rq_data_dir(req) == READ ? ++ MMC_BLK_READ : MMC_BLK_WRITE; ++ switch (status) { ++ case MMC_BLK_SUCCESS: ++ case MMC_BLK_PARTIAL: ++ /* ++ * A block was successfully transferred. ++ */ ++ mmc_blk_reset_success(md, type); ++ continue; ++ case MMC_BLK_CMD_ERR: ++ if (!mmc_blk_reset(md, card->host, type)) ++ goto cmd_restart; ++ goto cmd_abort; ++ case MMC_BLK_RETRY: ++ ++ /* Fall through */ ++ case MMC_BLK_ABORT: ++ if (!mmc_blk_reset(md, card->host, type) && req->retries++ < 5) ++ goto cmd_restart; ++ goto cmd_abort; ++ case MMC_BLK_ECC_ERR: ++ case MMC_BLK_DATA_ERR: { ++ int error; ++ ++ error = mmc_blk_reset(md, card->host, type); ++ if (!error) ++ goto cmd_restart; ++ if (error == -ENODEV) ++ goto cmd_abort; ++ } ++ /* Fall through */ ++ case MMC_BLK_NOMEDIUM: ++ goto cmd_abort; ++ default: ++ pr_err("%s: Unhandled return value (%d)", ++ req->rq_disk->disk_name, status); ++ goto cmd_abort; ++ } ++ } ++ return MMC_CMD_SUCCESS; ++ ++cmd_abort: ++ pr_err("%s: error, req abort\n", mmc_hostname(card->host)); ++ ++ cmd_flags = mmc_card_removed(card) ? REQ_QUIET : 0; ++ mmc_xmited_abort(xmited, cmd_flags); ++ mmc_xmited_reset(xmited); ++ card->host->status = MMC_HOST_OK; ++ return MMC_CMD_ABORT; ++ ++cmd_restart: ++ /* ++ * putback all incomplete request. ++ * when error fixed, restart ++ */ ++ pr_info("%s: error fixed, restart...\n", mmc_hostname(card->host)); ++ mmc_xmited_requeue(mq->queue, xmited); ++ mmc_xmited_reset(xmited); ++ card->host->status = MMC_HOST_OK; ++ return MMC_CMD_SUCCESS; ++} ++ ++/** ++ * mmc_blk_xmit_reqs - fetch request from queue then transmit it. ++ * @mq: mmc queue ++ * @card: mmc card to attach this queue ++ * @req: new req that should xmited ++ * return: the count of request send this time. ++ * ++ * transmit the request till can't fetch ++ */ ++static int mmc_blk_xmit_reqs(struct mmc_queue *mq, ++ struct mmc_card *card, struct request *req) ++{ ++ struct request *cur; ++ struct mmc_host *host = card->host; ++ struct mmc_req_mrq *req_mrq = NULL; ++ struct request_queue *q = mq->queue; ++ struct mmc_xmited *xmited = &mq->xmited; ++#if !defined(CONFIG_ARCH_HI3559) && !defined(CONFIG_ARCH_HI3556) ++ u32 intr_step = 4; ++#endif ++ /*u32 max_send_reqs = 16;*/ ++ u32 reqs = 0; ++ int ret = 0; ++ unsigned int cmd_flags; ++ ++ do { ++ cur = req; ++ if (cur && mmc_xmited_full(xmited)) { ++ blk_requeue_request(q, cur); ++ return reqs; ++ } ++ /* In case sepecial request(discard, flush), we must be sure ++ * all of request has finished. ++ */ ++ cmd_flags = cur ? cur->cmd_flags : 0; ++ if (cmd_flags & REQ_DISCARD) { ++ /* complete ongoing async transfer ++ * before issuing discard ++ */ ++ if (!mmc_xmited_empty(xmited)) ++ mmc_blk_retrieve_reqs(mq, host, true); ++ if (cur->cmd_flags & REQ_SECURE) ++ ret = mmc_blk_issue_secdiscard_rq(mq, cur); ++ else ++ ret = mmc_blk_issue_discard_rq(mq, cur); ++ } else if (cmd_flags & REQ_FLUSH) { ++ /* complete ongoing async transfer ++ * before issuing flush ++ */ ++ if (!mmc_xmited_empty(xmited)) ++ mmc_blk_retrieve_reqs(mq, host, true); ++ ret = mmc_blk_issue_flush(mq, cur); ++ } else if (cur) { ++ req_mrq = mmc_get_rbuf(xmited); ++ memset(&req_mrq->brq, 0, ++ sizeof(struct mmc_blk_request)); ++ req_mrq->req = cur; ++ reqs++; ++ } ++ ++ /* fetch next request */ ++ spin_lock_irq(q->queue_lock); ++ req = blk_fetch_request(q); ++ spin_unlock_irq(q->queue_lock); ++ ++ if (req_mrq) { ++#if !defined(CONFIG_ARCH_HI3559) && !defined(CONFIG_ARCH_HI3556) ++ if (((reqs % intr_step) != 1) && req) ++ req_mrq->brq.cmd.flags |= MMC_CMD_NON_BLOCKING; ++#endif ++ ++ ret = mmc_send_reqs(req_mrq, card, mq); ++ req_mrq = NULL; ++ if (ret) ++ goto cmd_abort; ++ } ++ } while (req); ++ ++ return reqs; ++ ++cmd_abort: ++ pr_err("%s: send cmd fail. abort...\n", ++ mmc_hostname(card->host)); ++ cmd_flags = mmc_card_removed(card) ? REQ_QUIET : 0; ++ mmc_xmited_abort(xmited, cmd_flags); ++ mmc_xmited_reset(xmited); ++ if (req) { ++ req->cmd_flags |= cmd_flags; ++ blk_end_request_all(req, -EIO); ++ } ++ return 0; ++} + + static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) + { +- int ret; ++ int ret, reqs; + struct mmc_blk_data *md = mq->data; + struct mmc_card *card = md->queue.card; + struct mmc_host *host = card->host; +- unsigned long flags; +- unsigned int cmd_flags = req ? req->cmd_flags : 0; ++ struct mmc_xmited *xmited = &mq->xmited; + +- if (req && !mq->mqrq_prev->req) ++ set_current_state(TASK_RUNNING); ++#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME ++ if (mmc_bus_needs_resume(card->host)) ++ mmc_resume_bus(card->host); ++#endif ++ ++ if (mmc_xmited_empty(xmited)) + /* claim host only for the first request */ + mmc_get_card(card); + + ret = mmc_blk_part_switch(card, md); + if (ret) { +- if (req) { +- blk_end_request_all(req, -EIO); +- } +- ret = 0; + goto out; + } + +- mq->flags &= ~MMC_QUEUE_NEW_REQUEST; +- if (cmd_flags & REQ_DISCARD) { +- /* complete ongoing async transfer before issuing discard */ +- if (card->host->areq) +- mmc_blk_issue_rw_rq(mq, NULL); +- if (req->cmd_flags & REQ_SECURE) +- ret = mmc_blk_issue_secdiscard_rq(mq, req); +- else +- ret = mmc_blk_issue_discard_rq(mq, req); +- } else if (cmd_flags & REQ_FLUSH) { +- /* complete ongoing async transfer before issuing flush */ +- if (card->host->areq) +- mmc_blk_issue_rw_rq(mq, NULL); +- ret = mmc_blk_issue_flush(mq, req); +- } else { +- if (!req && host->areq) { +- spin_lock_irqsave(&host->context_info.lock, flags); +- host->context_info.is_waiting_last_req = true; +- spin_unlock_irqrestore(&host->context_info.lock, flags); +- } +- ret = mmc_blk_issue_rw_rq(mq, req); +- } ++ mmc_blk_retrieve_reqs(mq, card->host, false); + ++ reqs = mmc_blk_xmit_reqs(mq, card, req); ++ if (!reqs && !mmc_xmited_empty(xmited)) ++ mmc_wait_reqs_done(host); + out: +- if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) || +- (cmd_flags & MMC_REQ_SPECIAL_MASK)) +- /* +- * Release host when there are no more requests +- * and after special request(discard, flush) is done. +- * In case sepecial request, there is no reentry to +- * the 'mmc_blk_issue_rq' with 'mqrq_prev->req'. +- */ ++ if (mmc_xmited_empty(xmited)) ++ /* Release host when there are no more requests */ + mmc_put_card(card); + return ret; + } +@@ -2152,6 +2570,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, + md->disk->queue = md->queue.queue; + md->disk->driverfs_dev = parent; + set_disk_ro(md->disk, md->read_only || default_ro); ++ md->disk->flags = GENHD_FL_EXT_DEVT; + if (area_type & (MMC_BLK_DATA_AREA_RPMB | MMC_BLK_DATA_AREA_BOOT)) + md->disk->flags |= GENHD_FL_NO_PART_SCAN; + +@@ -2193,14 +2612,6 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, + blk_queue_flush(md->queue.queue, REQ_FLUSH | REQ_FUA); + } + +- if (mmc_card_mmc(card) && +- (area_type == MMC_BLK_DATA_AREA_MAIN) && +- (md->flags & MMC_BLK_CMD23) && +- card->ext_csd.packed_event_en) { +- if (!mmc_packed_init(&md->queue, card)) +- md->flags |= MMC_BLK_PACKED_CMD; +- } +- + return md; + + err_putdisk: +@@ -2302,8 +2713,6 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md) + */ + card = md->queue.card; + mmc_cleanup_queue(&md->queue); +- if (md->flags & MMC_BLK_PACKED_CMD) +- mmc_packed_clean(&md->queue); + if (md->disk->flags & GENHD_FL_UP) { + device_remove_file(disk_to_dev(md->disk), &md->force_ro); + if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) && +@@ -2469,6 +2878,9 @@ static int mmc_blk_probe(struct mmc_card *card) + + mmc_set_drvdata(card, md); + ++#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME ++ mmc_set_bus_resume_policy(card->host, 1); ++#endif + if (mmc_add_disk(md)) + goto out; + +@@ -2511,6 +2923,9 @@ static void mmc_blk_remove(struct mmc_card *card) + pm_runtime_put_noidle(&card->dev); + mmc_blk_remove_req(md); + mmc_set_drvdata(card, NULL); ++#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME ++ mmc_set_bus_resume_policy(card->host, 0); ++#endif + } + + static int _mmc_blk_suspend(struct mmc_card *card) +diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c +index 7a41a22..1003139 100644 +--- a/drivers/mmc/card/queue.c ++++ b/drivers/mmc/card/queue.c +@@ -23,6 +23,9 @@ + + #define MMC_QUEUE_BOUNCESZ 65536 + ++extern int mmc_blk_err_check(struct mmc_card *card, ++ struct mmc_req_mrq *req_mrq); ++ + /* + * Prepare a MMC request. This just filters out odd stuff. + */ +@@ -50,14 +53,13 @@ static int mmc_queue_thread(void *d) + { + struct mmc_queue *mq = d; + struct request_queue *q = mq->queue; ++ struct mmc_xmited *xmited = &mq->xmited; + + current->flags |= PF_MEMALLOC; + + down(&mq->thread_sem); + do { + struct request *req = NULL; +- struct mmc_queue_req *tmp; +- unsigned int cmd_flags = 0; + + spin_lock_irq(q->queue_lock); + set_current_state(TASK_INTERRUPTIBLE); +@@ -65,30 +67,8 @@ static int mmc_queue_thread(void *d) + mq->mqrq_cur->req = req; + spin_unlock_irq(q->queue_lock); + +- if (req || mq->mqrq_prev->req) { +- set_current_state(TASK_RUNNING); +- cmd_flags = req ? req->cmd_flags : 0; ++ if (req || (!mmc_xmited_empty(xmited))) { + mq->issue_fn(mq, req); +- if (mq->flags & MMC_QUEUE_NEW_REQUEST) { +- mq->flags &= ~MMC_QUEUE_NEW_REQUEST; +- continue; /* fetch again */ +- } +- +- /* +- * Current request becomes previous request +- * and vice versa. +- * In case of special requests, current request +- * has been finished. Do not assign it to previous +- * request. +- */ +- if (cmd_flags & MMC_REQ_SPECIAL_MASK) +- mq->mqrq_cur->req = NULL; +- +- mq->mqrq_prev->brq.mrq.data = NULL; +- mq->mqrq_prev->req = NULL; +- tmp = mq->mqrq_prev; +- mq->mqrq_prev = mq->mqrq_cur; +- mq->mqrq_cur = tmp; + } else { + if (kthread_should_stop()) { + set_current_state(TASK_RUNNING); +@@ -126,7 +106,7 @@ static void mmc_request_fn(struct request_queue *q) + } + + cntx = &mq->card->host->context_info; +- if (!mq->mqrq_cur->req && mq->mqrq_prev->req) { ++ if (!mmc_xmited_empty(&mq->xmited)) { + /* + * New MMC request arrived when MMC thread may be + * blocked on the previous request to be complete +@@ -138,7 +118,7 @@ static void mmc_request_fn(struct request_queue *q) + wake_up_interruptible(&cntx->wait); + } + spin_unlock_irqrestore(&cntx->lock, flags); +- } else if (!mq->mqrq_cur->req && !mq->mqrq_prev->req) ++ } else + wake_up_process(mq->thread); + } + +@@ -178,6 +158,14 @@ static void mmc_queue_setup_discard(struct request_queue *q, + queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, q); + } + ++void mmc_xmited_reset(struct mmc_xmited *xmited) ++{ ++ xmited->start = 0; ++ xmited->end = 0; ++ xmited->used = 0; ++ xmited->capacity = MMC_MAX_REQS_SEND_ONCE; ++} ++ + /** + * mmc_init_queue - initialise a queue structure. + * @mq: mmc queue +@@ -191,10 +179,10 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, + spinlock_t *lock, const char *subname) + { + struct mmc_host *host = card->host; ++ struct mmc_xmited *xmited = &mq->xmited; + u64 limit = BLK_BOUNCE_HIGH; +- int ret; +- struct mmc_queue_req *mqrq_cur = &mq->mqrq[0]; +- struct mmc_queue_req *mqrq_prev = &mq->mqrq[1]; ++ int ret, i; ++ struct mmc_queue_req *mqrq_cur = &mq->mqrq; + + if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) + limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT; +@@ -205,9 +193,11 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, + return -ENOMEM; + + mq->mqrq_cur = mqrq_cur; +- mq->mqrq_prev = mqrq_prev; + mq->queue->queuedata = mq; + ++ mmc_xmited_reset(xmited); ++ xmited->err_check = mmc_blk_err_check; ++ + blk_queue_prep_rq(mq->queue, mmc_prep_request); + queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue); + queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, mq->queue); +@@ -233,57 +223,46 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, + pr_warn("%s: unable to allocate bounce cur buffer\n", + mmc_card_name(card)); + } +- mqrq_prev->bounce_buf = kmalloc(bouncesz, GFP_KERNEL); +- if (!mqrq_prev->bounce_buf) { +- pr_warn("%s: unable to allocate bounce prev buffer\n", +- mmc_card_name(card)); +- kfree(mqrq_cur->bounce_buf); +- mqrq_cur->bounce_buf = NULL; +- } + } + +- if (mqrq_cur->bounce_buf && mqrq_prev->bounce_buf) { ++ if (mqrq_cur->bounce_buf) { + blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY); + blk_queue_max_hw_sectors(mq->queue, bouncesz / 512); + blk_queue_max_segments(mq->queue, bouncesz / 512); + blk_queue_max_segment_size(mq->queue, bouncesz); + +- mqrq_cur->sg = mmc_alloc_sg(1, &ret); +- if (ret) +- goto cleanup_queue; +- + mqrq_cur->bounce_sg = + mmc_alloc_sg(bouncesz / 512, &ret); + if (ret) + goto cleanup_queue; +- +- mqrq_prev->sg = mmc_alloc_sg(1, &ret); +- if (ret) +- goto cleanup_queue; +- +- mqrq_prev->bounce_sg = +- mmc_alloc_sg(bouncesz / 512, &ret); +- if (ret) +- goto cleanup_queue; + } + } + #endif + +- if (!mqrq_cur->bounce_buf && !mqrq_prev->bounce_buf) { ++ if (!mqrq_cur->bounce_buf) { + blk_queue_bounce_limit(mq->queue, limit); + blk_queue_max_hw_sectors(mq->queue, + min(host->max_blk_count, host->max_req_size / 512)); + blk_queue_max_segments(mq->queue, host->max_segs); + blk_queue_max_segment_size(mq->queue, host->max_seg_size); + +- mqrq_cur->sg = mmc_alloc_sg(host->max_segs, &ret); +- if (ret) +- goto cleanup_queue; +- ++ memset(xmited->sg_buf, 0, sizeof(struct scatterlist *) ++ * MMC_MAX_REQS_SEND_ONCE); ++ memset(xmited->rq_buf, 0, sizeof(struct mmc_req_mrq *) ++ * MMC_MAX_REQS_SEND_ONCE); + +- mqrq_prev->sg = mmc_alloc_sg(host->max_segs, &ret); +- if (ret) +- goto cleanup_queue; ++ for (i = 0; i < MMC_MAX_REQS_SEND_ONCE; i++) { ++ xmited->sg_buf[i] = mmc_alloc_sg(host->max_segs, &ret); ++ if (ret) ++ goto cleanup_buf; ++ xmited->rq_buf[i] = (struct mmc_req_mrq *) ++ kmalloc(sizeof(struct mmc_req_mrq), GFP_KERNEL); ++ if (!xmited->rq_buf[i]) { ++ kfree(xmited->sg_buf[i]); ++ goto cleanup_buf; ++ } ++ xmited->rq_buf[i]->sg = xmited->sg_buf[i]; ++ } + } + + sema_init(&mq->thread_sem, 1); +@@ -297,23 +276,25 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, + } + + return 0; +- free_bounce_sg: ++free_bounce_sg: + kfree(mqrq_cur->bounce_sg); + mqrq_cur->bounce_sg = NULL; +- kfree(mqrq_prev->bounce_sg); +- mqrq_prev->bounce_sg = NULL; + +- cleanup_queue: +- kfree(mqrq_cur->sg); ++cleanup_buf: ++ if (!mqrq_cur->bounce_buf) { ++ for (i--; i >= 0; i--) { ++ kfree(xmited->sg_buf[i]); ++ xmited->sg_buf[i] = NULL; ++ kfree(xmited->rq_buf[i]); ++ xmited->rq_buf[i] = NULL; ++ } ++ } ++ ++cleanup_queue: + mqrq_cur->sg = NULL; + kfree(mqrq_cur->bounce_buf); + mqrq_cur->bounce_buf = NULL; + +- kfree(mqrq_prev->sg); +- mqrq_prev->sg = NULL; +- kfree(mqrq_prev->bounce_buf); +- mqrq_prev->bounce_buf = NULL; +- + blk_cleanup_queue(mq->queue); + return ret; + } +@@ -321,9 +302,10 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, + void mmc_cleanup_queue(struct mmc_queue *mq) + { + struct request_queue *q = mq->queue; ++ struct mmc_xmited *xmited = &mq->xmited; + unsigned long flags; ++ int i; + struct mmc_queue_req *mqrq_cur = mq->mqrq_cur; +- struct mmc_queue_req *mqrq_prev = mq->mqrq_prev; + + /* Make sure the queue isn't suspended, as that will deadlock */ + mmc_queue_resume(mq); +@@ -340,25 +322,22 @@ void mmc_cleanup_queue(struct mmc_queue *mq) + kfree(mqrq_cur->bounce_sg); + mqrq_cur->bounce_sg = NULL; + +- kfree(mqrq_cur->sg); + mqrq_cur->sg = NULL; + + kfree(mqrq_cur->bounce_buf); + mqrq_cur->bounce_buf = NULL; + +- kfree(mqrq_prev->bounce_sg); +- mqrq_prev->bounce_sg = NULL; +- +- kfree(mqrq_prev->sg); +- mqrq_prev->sg = NULL; +- +- kfree(mqrq_prev->bounce_buf); +- mqrq_prev->bounce_buf = NULL; +- ++ for (i = 0; i < MMC_MAX_REQS_SEND_ONCE; i++) { ++ kfree(xmited->sg_buf[i]); ++ xmited->sg_buf[i] = NULL; ++ kfree(xmited->rq_buf[i]); ++ xmited->rq_buf[i] = NULL; ++ } + mq->card = NULL; + } + EXPORT_SYMBOL(mmc_cleanup_queue); + ++#if 0 + int mmc_packed_init(struct mmc_queue *mq, struct mmc_card *card) + { + struct mmc_queue_req *mqrq_cur = &mq->mqrq[0]; +@@ -401,6 +380,7 @@ void mmc_packed_clean(struct mmc_queue *mq) + kfree(mqrq_prev->packed); + mqrq_prev->packed = NULL; + } ++#endif + + /** + * mmc_queue_suspend - suspend a MMC request queue +@@ -446,6 +426,7 @@ void mmc_queue_resume(struct mmc_queue *mq) + } + } + ++#if 0 + static unsigned int mmc_queue_packed_map_sg(struct mmc_queue *mq, + struct mmc_packed *packed, + struct scatterlist *sg, +@@ -480,6 +461,7 @@ static unsigned int mmc_queue_packed_map_sg(struct mmc_queue *mq, + sg_mark_end(sg + (sg_len - 1)); + return sg_len; + } ++#endif + + /* + * Prepare the sg list(s) to be handed of to the host driver +@@ -495,20 +477,12 @@ unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq) + cmd_type = mqrq->cmd_type; + + if (!mqrq->bounce_buf) { +- if (mmc_packed_cmd(cmd_type)) +- return mmc_queue_packed_map_sg(mq, mqrq->packed, +- mqrq->sg, cmd_type); +- else + return blk_rq_map_sg(mq->queue, mqrq->req, mqrq->sg); + } + + BUG_ON(!mqrq->bounce_sg); + +- if (mmc_packed_cmd(cmd_type)) +- sg_len = mmc_queue_packed_map_sg(mq, mqrq->packed, +- mqrq->bounce_sg, cmd_type); +- else +- sg_len = blk_rq_map_sg(mq->queue, mqrq->req, mqrq->bounce_sg); ++ sg_len = blk_rq_map_sg(mq->queue, mqrq->req, mqrq->bounce_sg); + + mqrq->bounce_sg_len = sg_len; + +@@ -552,3 +526,69 @@ void mmc_queue_bounce_post(struct mmc_queue_req *mqrq) + sg_copy_from_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len, + mqrq->bounce_buf, mqrq->sg[0].length); + } ++ ++/** ++ * mmc_get_rbuf - get next idle mmc_req_mrq from buf pool. ++ * @xmited: mmc queue pool ++ */ ++struct mmc_req_mrq *mmc_get_rbuf(struct mmc_xmited *xmited) ++{ ++ struct mmc_req_mrq *req_mrq = NULL; ++ ++ if (xmited->used == (xmited->capacity - 2)) { ++ req_mrq = NULL; ++ } else { ++ req_mrq = xmited->rq_buf[xmited->end]; ++ xmited->end++; ++ xmited->end %= xmited->capacity; ++ xmited->used++; ++ } ++ return req_mrq; ++} ++ ++/** ++ * mmc_put_rbuf - release an mmc_req_mrq to buf pool. ++ * @mq: mmc queue ++ * return 0 ok -1 failed 1 confuse ++ */ ++int mmc_put_rbuf(struct mmc_xmited *xmited, struct mmc_req_mrq *req_mrq) ++{ ++ int ret = 0; ++ ++ if (xmited->used <= 0) { ++ ret = -1; ++ } else if (xmited->rq_buf[xmited->start] == req_mrq) { ++ xmited->start++; ++ xmited->start %= xmited->capacity; ++ xmited->used--; ++ ret = 0; ++ } else { ++ ret = 1; ++ } ++ return ret; ++} ++ ++void mmc_xmited_abort(struct mmc_xmited *xmited, unsigned int flags) ++{ ++ struct request *req; ++ struct mmc_req_mrq *req_mrq; ++ ++ while (!mmc_xmited_empty(xmited)) { ++ req_mrq = xmited->rq_buf[xmited->start]; ++ req = req_mrq->req; ++ req->cmd_flags |= flags; ++ blk_end_request_all(req_mrq->req, -EIO); ++ mmc_put_rbuf(xmited, req_mrq); ++ } ++} ++ ++void mmc_xmited_requeue(struct request_queue *q, struct mmc_xmited *xmited) ++{ ++ struct mmc_req_mrq *req_mrq; ++ ++ while (!mmc_xmited_empty(xmited)) { ++ req_mrq = xmited->rq_buf[xmited->start]; ++ blk_requeue_request(q, req_mrq->req); ++ mmc_put_rbuf(xmited, req_mrq); ++ } ++} +diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h +index 99e6521..e40a65d 100644 +--- a/drivers/mmc/card/queue.h ++++ b/drivers/mmc/card/queue.h +@@ -33,7 +33,7 @@ struct mmc_packed { + + struct mmc_queue_req { + struct request *req; +- struct mmc_blk_request brq; ++ struct mmc_blk_request *brq; + struct scatterlist *sg; + char *bounce_buf; + struct scatterlist *bounce_sg; +@@ -43,6 +43,29 @@ struct mmc_queue_req { + struct mmc_packed *packed; + }; + ++#define MMC_REQ_FRESH (0x1<<0) ++#define MMC_REQ_PREP (0x1<<1) ++#define MMC_REQ_SEND (0x1<<2) ++#define MMC_REQ_DONE (0x1<<3) ++#define MMC_REQ_FAIL (0x1<<4) ++struct mmc_req_mrq { ++ struct request *req; ++ struct mmc_blk_request brq; ++ struct scatterlist *sg; ++ u32 wr_pos; ++}; ++ ++#define MMC_MAX_REQS_SEND_ONCE (32) ++struct mmc_xmited { ++ struct scatterlist *sg_buf[MMC_MAX_REQS_SEND_ONCE]; ++ struct mmc_req_mrq *rq_buf[MMC_MAX_REQS_SEND_ONCE]; ++ u32 capacity; ++ u32 used; ++ u32 start; ++ u32 end; ++ int (*err_check)(struct mmc_card *, struct mmc_req_mrq *); ++}; ++ + struct mmc_queue { + struct mmc_card *card; + struct task_struct *thread; +@@ -54,9 +77,9 @@ struct mmc_queue { + int (*issue_fn)(struct mmc_queue *, struct request *); + void *data; + struct request_queue *queue; +- struct mmc_queue_req mqrq[2]; ++ struct mmc_queue_req mqrq; + struct mmc_queue_req *mqrq_cur; +- struct mmc_queue_req *mqrq_prev; ++ struct mmc_xmited xmited; + }; + + extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *, +@@ -75,4 +98,14 @@ extern void mmc_packed_clean(struct mmc_queue *); + + extern int mmc_access_rpmb(struct mmc_queue *); + ++#define mmc_xmited_empty(x) (!((x)->used)) ++#define mmc_xmited_full(x) ((x)->used >= ((x)->capacity-2)) ++ ++void mmc_xmited_reset(struct mmc_xmited *); ++ ++struct mmc_req_mrq *mmc_get_rbuf(struct mmc_xmited *); ++int mmc_put_rbuf(struct mmc_xmited *, struct mmc_req_mrq *); ++ ++void mmc_xmited_requeue(struct request_queue *, struct mmc_xmited *); ++void mmc_xmited_abort(struct mmc_xmited *, unsigned int); + #endif +diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig +index 9ebee72..f771bc3 100644 +--- a/drivers/mmc/core/Kconfig ++++ b/drivers/mmc/core/Kconfig +@@ -11,3 +11,18 @@ config MMC_CLKGATE + support handling this in order for it to be of any use. + + If unsure, say N. ++ ++config MMC_EMBEDDED_SDIO ++ boolean "MMC embedded SDIO device support (EXPERIMENTAL)" ++ help ++ If you say Y here, support will be added for embedded SDIO ++ devices which do not contain the necessary enumeration ++ support in hardware to be properly detected. ++ ++config MMC_PARANOID_SD_INIT ++ bool "Enable paranoid SD card initialization (EXPERIMENTAL)" ++ help ++ If you say Y here, the MMC layer will be extra paranoid ++ about re-trying SD init requests. This can be a useful ++ work-around for buggy controllers and hardware. Enable ++ if you are experiencing issues with SD detection. +diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c +index 297b4f9..b850534 100644 +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -29,6 +29,9 @@ + #include + #include + #include ++#include ++ ++#include + + #include + #include +@@ -55,6 +58,7 @@ + #define MMC_BKOPS_MAX_TIMEOUT (4 * 60 * 1000) /* max time to wait in ms */ + + static struct workqueue_struct *workqueue; ++static struct wake_lock mmc_delayed_work_wake_lock; + static const unsigned freqs[] = { 400000, 300000, 200000, 100000 }; + + /* +@@ -71,6 +75,7 @@ module_param(use_spi_crc, bool, 0); + static int mmc_schedule_delayed_work(struct delayed_work *work, + unsigned long delay) + { ++ wake_lock(&mmc_delayed_work_wake_lock); + return queue_delayed_work(workqueue, work, delay); + } + +@@ -158,6 +163,7 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) + pr_debug("%s: %d bytes transferred: %d\n", + mmc_hostname(host), + mrq->data->bytes_xfered, mrq->data->error); ++ trace_mmc_blk_rw_end(cmd->opcode, cmd->arg, mrq->data); + } + + if (mrq->stop) { +@@ -331,7 +337,7 @@ static void mmc_wait_done(struct mmc_request *mrq) + * Sets the done callback to be called when request is completed by the card. + * Starts data mmc request execution + */ +-static int __mmc_start_data_req(struct mmc_host *host, struct mmc_request *mrq) ++int __mmc_start_data_req(struct mmc_host *host, struct mmc_request *mrq) + { + mrq->done = mmc_wait_data_done; + mrq->host = host; +@@ -344,6 +350,7 @@ static int __mmc_start_data_req(struct mmc_host *host, struct mmc_request *mrq) + + return 0; + } ++EXPORT_SYMBOL(__mmc_start_data_req); + + static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq) + { +@@ -358,6 +365,7 @@ static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq) + return 0; + } + ++#if 0 + /* + * mmc_wait_for_data_req_done() - wait for request completed + * @host: MMC host to prepare the command. +@@ -414,6 +422,7 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host, + } + return err; + } ++#endif + + static void mmc_wait_for_req_done(struct mmc_host *host, + struct mmc_request *mrq) +@@ -454,6 +463,7 @@ static void mmc_wait_for_req_done(struct mmc_host *host, + } + } + ++#if 0 + /** + * mmc_pre_req - Prepare for a new request + * @host: MMC host to prepare command +@@ -474,6 +484,7 @@ static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq, + mmc_host_clk_release(host); + } + } ++#endif + + /** + * mmc_post_req - Post process a completed request +@@ -484,7 +495,7 @@ static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq, + * Let the host post process a completed request. Post processing of + * a request may be performed while another reuqest is running. + */ +-static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq, ++void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq, + int err) + { + if (host->ops->post_req) { +@@ -494,6 +505,7 @@ static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq, + } + } + ++#if 0 + /** + * mmc_start_req - start a non-blocking request + * @host: MMC host to start command +@@ -542,8 +554,12 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host, + mmc_start_bkops(host->card, true); + } + +- if (!err && areq) ++ if (!err && areq) { ++ trace_mmc_blk_rw_start(areq->mrq->cmd->opcode, ++ areq->mrq->cmd->arg, ++ areq->mrq->data); + start_err = __mmc_start_data_req(host, areq->mrq); ++ } + + if (host->areq) + mmc_post_req(host, host->areq->mrq, 0); +@@ -562,6 +578,7 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host, + return data; + } + EXPORT_SYMBOL(mmc_start_req); ++#endif + + /** + * mmc_wait_for_req - start a request and wait for completion +@@ -745,6 +762,9 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) + { + unsigned int mult; + ++ if (!card) ++ return; ++ + /* + * SDIO cards only define an upper 1 s limit on access. + */ +@@ -1879,8 +1899,13 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, + struct mmc_command cmd = {0}; + unsigned int qty = 0; + unsigned long timeout; ++ unsigned int fr, nr; + int err; + ++ fr = from; ++ nr = to - from + 1; ++ trace_mmc_blk_erase_start(arg, fr, nr); ++ + /* + * qty is used to calculate the erase timeout which depends on how many + * erase groups (or allocation units in SD terminology) are affected. +@@ -1984,6 +2009,8 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, + } while (!(cmd.resp[0] & R1_READY_FOR_DATA) || + (R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG)); + out: ++ ++ trace_mmc_blk_erase_end(arg, fr, nr); + return err; + } + +@@ -2295,6 +2322,22 @@ int mmc_hw_reset(struct mmc_host *host) + } + EXPORT_SYMBOL(mmc_hw_reset); + ++int mmc_sw_reset(struct mmc_host *host) ++{ ++ ++ if (!mmc_card_sd(host->card) || !host->ops->sw_reset) ++ return -EOPNOTSUPP; ++ ++ host->ios.bus_width = MMC_BUS_WIDTH_1; ++ host->ios.timing = MMC_TIMING_LEGACY; ++ host->ios.clock = host->f_init; ++ mmc_set_ios(host); ++ host->ops->sw_reset(host); ++ ++ return host->bus_ops->power_restore(host); ++} ++EXPORT_SYMBOL(mmc_sw_reset); ++ + int mmc_hw_reset_check(struct mmc_host *host) + { + return mmc_do_hw_reset(host, 1); +@@ -2411,6 +2454,7 @@ void mmc_rescan(struct work_struct *work) + struct mmc_host *host = + container_of(work, struct mmc_host, detect.work); + int i; ++ bool extend_wakelock = false; + + if (host->trigger_card_event && host->ops->card_event) { + host->ops->card_event(host); +@@ -2437,6 +2481,12 @@ void mmc_rescan(struct work_struct *work) + + host->detect_change = 0; + ++ /* If the card was removed the bus will be marked ++ * as dead - extend the wakelock so userspace ++ * can respond */ ++ if (host->bus_dead) ++ extend_wakelock = 1; ++ + /* + * Let mmc_bus_put() free the bus/bus_ops if we've found that + * the card is no longer present. +@@ -2460,20 +2510,30 @@ void mmc_rescan(struct work_struct *work) + host->ops->get_cd(host) == 0) { + mmc_claim_host(host); + mmc_power_off(host); ++ if (host->ops->card_info_save) ++ host->ops->card_info_save(host); + mmc_release_host(host); + goto out; + } + + mmc_claim_host(host); + for (i = 0; i < ARRAY_SIZE(freqs); i++) { +- if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min))) ++ if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min))) { ++ extend_wakelock = true; ++ if (host->ops->card_info_save) ++ host->ops->card_info_save(host); + break; ++ } + if (freqs[i] <= host->f_min) + break; + } + mmc_release_host(host); + + out: ++ if (extend_wakelock) ++ wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2); ++ else ++ wake_unlock(&mmc_delayed_work_wake_lock); + if (host->caps & MMC_CAP_NEEDS_POLL) + mmc_schedule_delayed_work(&host->detect, HZ); + } +@@ -2671,6 +2731,22 @@ void mmc_init_context_info(struct mmc_host *host) + init_waitqueue_head(&host->context_info.wait); + } + ++#ifdef CONFIG_MMC_EMBEDDED_SDIO ++void mmc_set_embedded_sdio_data(struct mmc_host *host, ++ struct sdio_cis *cis, ++ struct sdio_cccr *cccr, ++ struct sdio_embedded_func *funcs, ++ int num_funcs) ++{ ++ host->embedded_sdio_data.cis = cis; ++ host->embedded_sdio_data.cccr = cccr; ++ host->embedded_sdio_data.funcs = funcs; ++ host->embedded_sdio_data.num_funcs = num_funcs; ++} ++ ++EXPORT_SYMBOL(mmc_set_embedded_sdio_data); ++#endif ++ + static int __init mmc_init(void) + { + int ret; +@@ -2679,6 +2755,9 @@ static int __init mmc_init(void) + if (!workqueue) + return -ENOMEM; + ++ wake_lock_init(&mmc_delayed_work_wake_lock, WAKE_LOCK_SUSPEND, ++ "mmc_delayed_work"); ++ + ret = mmc_register_bus(); + if (ret) + goto destroy_workqueue; +@@ -2699,6 +2778,7 @@ unregister_bus: + mmc_unregister_bus(); + destroy_workqueue: + destroy_workqueue(workqueue); ++ wake_lock_destroy(&mmc_delayed_work_wake_lock); + + return ret; + } +@@ -2709,6 +2789,7 @@ static void __exit mmc_exit(void) + mmc_unregister_host_class(); + mmc_unregister_bus(); + destroy_workqueue(workqueue); ++ wake_lock_destroy(&mmc_delayed_work_wake_lock); + } + + subsys_initcall(mmc_init); +diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c +index 270d58a..08e11cb 100644 +--- a/drivers/mmc/core/host.c ++++ b/drivers/mmc/core/host.c +@@ -371,7 +371,7 @@ int mmc_of_parse(struct mmc_host *host) + if (ret == -EPROBE_DEFER) + return ret; + if (ret != -ENOENT) { +- dev_err(host->parent, ++ dev_dbg(host->parent, + "Failed to request CD GPIO: %d\n", + ret); + } +@@ -401,7 +401,7 @@ int mmc_of_parse(struct mmc_host *host) + if (ret == -EPROBE_DEFER) + goto out; + if (ret != -ENOENT) { +- dev_err(host->parent, ++ dev_dbg(host->parent, + "Failed to request WP GPIO: %d\n", + ret); + } +@@ -560,7 +560,8 @@ int mmc_add_host(struct mmc_host *host) + mmc_host_clk_sysfs_init(host); + + mmc_start_host(host); +- register_pm_notifier(&host->pm_notify); ++ if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY)) ++ register_pm_notifier(&host->pm_notify); + + return 0; + } +@@ -577,7 +578,9 @@ EXPORT_SYMBOL(mmc_add_host); + */ + void mmc_remove_host(struct mmc_host *host) + { +- unregister_pm_notifier(&host->pm_notify); ++ if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY)) ++ unregister_pm_notifier(&host->pm_notify); ++ + mmc_stop_host(host); + + #ifdef CONFIG_DEBUG_FS +diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c +index a301a78..f4b9bf0 100644 +--- a/drivers/mmc/core/mmc.c ++++ b/drivers/mmc/core/mmc.c +@@ -1175,38 +1175,6 @@ bus_speed: + return err; + } + +-const u8 tuning_blk_pattern_4bit[MMC_TUNING_BLK_PATTERN_4BIT_SIZE] = { +- 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, +-}; +-EXPORT_SYMBOL(tuning_blk_pattern_4bit); +- +-const u8 tuning_blk_pattern_8bit[MMC_TUNING_BLK_PATTERN_8BIT_SIZE] = { +- 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, +-}; +-EXPORT_SYMBOL(tuning_blk_pattern_8bit); +- + /* + * Execute tuning sequence to seek the proper bus operating + * conditions for HS200 and HS400, which sends CMD21 to the device. +@@ -1239,6 +1207,34 @@ static int mmc_hs200_tuning(struct mmc_card *card) + return err; + } + ++static int mmc_hs400_tuning(struct mmc_card *card) ++{ ++ struct mmc_host *host = card->host; ++ int err = 0; ++ ++ /* ++ * Timing should be adjusted to the HS400 target ++ * operation frequency for tuning process ++ */ ++ if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 && ++ host->ios.bus_width == MMC_BUS_WIDTH_8) ++ if (host->ops->prepare_hs400_tuning) ++ host->ops->prepare_hs400_tuning(host, &host->ios); ++ ++ if (host->ops->execute_tuning) { ++ mmc_host_clk_hold(host); ++ err = host->ops->execute_tuning(host, ++ MMC_SEND_EXT_CSD); ++ mmc_host_clk_release(host); ++ ++ if (err) ++ pr_warn("%s: tuning execution failed\n", ++ mmc_hostname(host)); ++ } ++ ++ return err; ++} ++ + /* + * Handle the detection and initialisation of a card. + * +@@ -1463,6 +1459,12 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, + err = mmc_select_hs400(card); + if (err) + goto err; ++ ++ if (mmc_card_hs400(card)) { ++ err = mmc_hs400_tuning(card); ++ if (err) ++ goto err; ++ } + } else if (mmc_card_hs(card)) { + /* Select the desired bus width optionally */ + err = mmc_select_bus_width(card); +diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c +index 7911e05..2692021 100644 +--- a/drivers/mmc/core/mmc_ops.c ++++ b/drivers/mmc/core/mmc_ops.c +@@ -23,6 +23,36 @@ + + #define MMC_OPS_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ + ++static const u8 tuning_blk_pattern_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_pattern_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, ++}; ++ + static inline int __mmc_send_status(struct mmc_card *card, u32 *status, + bool ignore_crc) + { +@@ -543,6 +573,93 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, + } + EXPORT_SYMBOL_GPL(mmc_switch); + ++int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error) ++{ ++ struct mmc_request mrq = {NULL}; ++ struct mmc_command cmd = {0}; ++ struct mmc_data data = {0}; ++ struct scatterlist sg; ++ struct mmc_ios *ios = &host->ios; ++ const u8 *tuning_block_pattern; ++ int size, err = 0; ++ u8 *data_buf; ++ ++ if (ios->bus_width == MMC_BUS_WIDTH_8) { ++ tuning_block_pattern = tuning_blk_pattern_8bit; ++ size = sizeof(tuning_blk_pattern_8bit); ++ } else if (ios->bus_width == MMC_BUS_WIDTH_4) { ++ tuning_block_pattern = tuning_blk_pattern_4bit; ++ size = sizeof(tuning_blk_pattern_4bit); ++ } else ++ return -EINVAL; ++ ++ data_buf = kzalloc(size, GFP_KERNEL); ++ if (!data_buf) ++ return -ENOMEM; ++ ++ mrq.cmd = &cmd; ++ mrq.data = &data; ++ ++ cmd.opcode = opcode; ++ cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; ++ ++ data.blksz = size; ++ data.blocks = 1; ++ data.flags = MMC_DATA_READ; ++ ++ /* ++ * According to the tuning specs, Tuning process ++ * is normally shorter 40 executions of CMD19, ++ * and timeout value should be shorter than 150 ms ++ */ ++ data.timeout_ns = 150 * NSEC_PER_MSEC; ++ ++ data.sg = &sg; ++ data.sg_len = 1; ++ sg_init_one(&sg, data_buf, size); ++ ++ mmc_wait_for_req(host, &mrq); ++ ++ if (cmd_error) ++ *cmd_error = cmd.error; ++ ++ if (cmd.error) { ++ err = cmd.error; ++ goto out; ++ } ++ ++ if (data.error) { ++ err = data.error; ++ goto out; ++ } ++ ++ if (memcmp(data_buf, tuning_block_pattern, size)) ++ err = -EIO; ++ ++out: ++ kfree(data_buf); ++ return err; ++} ++EXPORT_SYMBOL_GPL(mmc_send_tuning); ++ ++int mmc_send_dll_tuning(struct mmc_host *host) ++{ ++ u8 *ext_csd; ++ int err = 0; ++ ++ ext_csd = kzalloc(512, GFP_KERNEL); ++ if (!ext_csd) ++ return -ENOMEM; ++ ++ err = mmc_send_cxd_data(NULL, host, MMC_SEND_EXT_CSD, ++ ext_csd, 512); ++ ++ kfree(ext_csd); ++ ++ return err; ++} ++EXPORT_SYMBOL_GPL(mmc_send_dll_tuning); ++ + static int + mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode, + u8 len) +diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c +index d90a6de..a9e09ce 100644 +--- a/drivers/mmc/core/sd.c ++++ b/drivers/mmc/core/sd.c +@@ -246,8 +246,10 @@ static int mmc_read_ssr(struct mmc_card *card) + goto out; + } + +- for (i = 0; i < 16; i++) ++ for (i = 0; i < 16; i++) { + ssr[i] = be32_to_cpu(ssr[i]); ++ card->c_ssr[i] = ssr[i]; ++ } + + /* + * UNSTUFF_BITS only works with four u32s so we have to offset the +@@ -813,6 +815,9 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, + bool reinit) + { + int err; ++#ifdef CONFIG_MMC_PARANOID_SD_INIT ++ int retries; ++#endif + + if (!reinit) { + /* +@@ -839,7 +844,26 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, + /* + * Fetch switch information from card. + */ ++#ifdef CONFIG_MMC_PARANOID_SD_INIT ++ for (retries = 1; retries <= 3; retries++) { ++ err = mmc_read_switch(card); ++ if (!err) { ++ if (retries > 1) { ++ printk(KERN_WARNING ++ "%s: recovered\n", ++ mmc_hostname(host)); ++ } ++ break; ++ } else { ++ printk(KERN_WARNING ++ "%s: read switch failed (attempt %d)\n", ++ mmc_hostname(host), retries); ++ } ++ } ++#else + err = mmc_read_switch(card); ++#endif ++ + if (err) + return err; + } +@@ -969,6 +993,15 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, + if (err) + goto free_card; + ++ /* check have been set bus speed*/ ++ if (card->sd_bus_speed != 0) { ++ err = mmc_sd_init_uhs_card(card); ++ if (err) ++ goto free_card; ++ ++ goto done; ++ } ++ + /* Initialization sequence for UHS-I cards */ + if (rocr & SD_ROCR_S18A) { + err = mmc_sd_init_uhs_card(card); +@@ -1002,6 +1035,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, + } + } + ++done: + host->card = card; + return 0; + +@@ -1037,7 +1071,10 @@ static int mmc_sd_alive(struct mmc_host *host) + */ + static void mmc_sd_detect(struct mmc_host *host) + { +- int err; ++ int err = 0; ++#ifdef CONFIG_MMC_PARANOID_SD_INIT ++ int retries = 5; ++#endif + + BUG_ON(!host); + BUG_ON(!host->card); +@@ -1047,7 +1084,23 @@ static void mmc_sd_detect(struct mmc_host *host) + /* + * Just check if our card has been removed. + */ ++#ifdef CONFIG_MMC_PARANOID_SD_INIT ++ while(retries) { ++ err = mmc_send_status(host->card, NULL); ++ if (err) { ++ retries--; ++ udelay(5); ++ continue; ++ } ++ break; ++ } ++ if (!retries) { ++ printk(KERN_ERR "%s(%s): Unable to re-detect card (%d)\n", ++ __func__, mmc_hostname(host), err); ++ } ++#else + err = _mmc_detect_card_removed(host); ++#endif + + mmc_put_card(host->card); + +@@ -1109,6 +1162,9 @@ static int mmc_sd_suspend(struct mmc_host *host) + static int _mmc_sd_resume(struct mmc_host *host) + { + int err = 0; ++#ifdef CONFIG_MMC_PARANOID_SD_INIT ++ int retries; ++#endif + + BUG_ON(!host); + BUG_ON(!host->card); +@@ -1119,7 +1175,23 @@ static int _mmc_sd_resume(struct mmc_host *host) + goto out; + + mmc_power_up(host, host->card->ocr); ++#ifdef CONFIG_MMC_PARANOID_SD_INIT ++ retries = 5; ++ while (retries) { ++ err = mmc_sd_init_card(host, host->card->ocr, host->card); ++ ++ if (err) { ++ printk(KERN_ERR "%s: Re-init card rc = %d (retries = %d)\n", ++ mmc_hostname(host), err, retries); ++ mdelay(5); ++ retries--; ++ continue; ++ } ++ break; ++ } ++#else + err = mmc_sd_init_card(host, host->card->ocr, host->card); ++#endif + mmc_card_clr_suspended(host->card); + + out: +@@ -1210,6 +1282,9 @@ int mmc_attach_sd(struct mmc_host *host) + { + int err; + u32 ocr, rocr; ++#ifdef CONFIG_MMC_PARANOID_SD_INIT ++ int retries; ++#endif + + BUG_ON(!host); + WARN_ON(!host->claimed); +@@ -1246,9 +1321,27 @@ int mmc_attach_sd(struct mmc_host *host) + /* + * Detect and init the card. + */ ++#ifdef CONFIG_MMC_PARANOID_SD_INIT ++ retries = 5; ++ while (retries) { ++ err = mmc_sd_init_card(host, rocr, NULL); ++ if (err) { ++ retries--; ++ continue; ++ } ++ break; ++ } ++ ++ if (!retries) { ++ printk(KERN_ERR "%s: mmc_sd_init_card() failure (err = %d)\n", ++ mmc_hostname(host), err); ++ goto err; ++ } ++#else + err = mmc_sd_init_card(host, rocr, NULL); + if (err) + goto err; ++#endif + + mmc_release_host(host); + err = mmc_add_card(host->card); +diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c +index 48d0c93..e608af5 100644 +--- a/drivers/mmc/core/sd_ops.c ++++ b/drivers/mmc/core/sd_ops.c +@@ -393,3 +393,4 @@ int mmc_app_sd_status(struct mmc_card *card, void *ssr) + + return 0; + } ++EXPORT_SYMBOL(mmc_app_sd_status); +diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c +index 2439e71..7c7e544 100644 +--- a/drivers/mmc/core/sdio.c ++++ b/drivers/mmc/core/sdio.c +@@ -10,6 +10,7 @@ + */ + + #include ++#include + #include + + #include +@@ -28,6 +29,10 @@ + #include "sdio_ops.h" + #include "sdio_cis.h" + ++#ifdef CONFIG_MMC_EMBEDDED_SDIO ++#include ++#endif ++ + static int sdio_read_fbr(struct sdio_func *func) + { + int ret; +@@ -738,19 +743,35 @@ try_again: + goto finish; + } + +- /* +- * Read the common registers. +- */ +- err = sdio_read_cccr(card, ocr); +- if (err) +- goto remove; ++#ifdef CONFIG_MMC_EMBEDDED_SDIO ++ if (host->embedded_sdio_data.cccr) ++ memcpy(&card->cccr, host->embedded_sdio_data.cccr, sizeof(struct sdio_cccr)); ++ else { ++#endif ++ /* ++ * Read the common registers. ++ */ ++ err = sdio_read_cccr(card, ocr); ++ if (err) ++ goto remove; ++#ifdef CONFIG_MMC_EMBEDDED_SDIO ++ } ++#endif + +- /* +- * Read the common CIS tuples. +- */ +- err = sdio_read_common_cis(card); +- if (err) +- goto remove; ++#ifdef CONFIG_MMC_EMBEDDED_SDIO ++ if (host->embedded_sdio_data.cis) ++ memcpy(&card->cis, host->embedded_sdio_data.cis, sizeof(struct sdio_cis)); ++ else { ++#endif ++ /* ++ * Read the common CIS tuples. ++ */ ++ err = sdio_read_common_cis(card); ++ if (err) ++ goto remove; ++#ifdef CONFIG_MMC_EMBEDDED_SDIO ++ } ++#endif + + if (oldcard) { + int same = (card->cis.vendor == oldcard->cis.vendor && +@@ -1143,14 +1164,36 @@ int mmc_attach_sdio(struct mmc_host *host) + funcs = (ocr & 0x70000000) >> 28; + card->sdio_funcs = 0; + ++#ifdef CONFIG_MMC_EMBEDDED_SDIO ++ if (host->embedded_sdio_data.funcs) ++ card->sdio_funcs = funcs = host->embedded_sdio_data.num_funcs; ++#endif ++ + /* + * Initialize (but don't add) all present functions. + */ + for (i = 0; i < funcs; i++, card->sdio_funcs++) { +- err = sdio_init_func(host->card, i + 1); +- if (err) +- goto remove; +- ++#ifdef CONFIG_MMC_EMBEDDED_SDIO ++ if (host->embedded_sdio_data.funcs) { ++ struct sdio_func *tmp; ++ ++ tmp = sdio_alloc_func(host->card); ++ if (IS_ERR(tmp)) ++ goto remove; ++ tmp->num = (i + 1); ++ card->sdio_func[i] = tmp; ++ tmp->class = host->embedded_sdio_data.funcs[i].f_class; ++ tmp->max_blksize = host->embedded_sdio_data.funcs[i].f_maxblksize; ++ tmp->vendor = card->cis.vendor; ++ tmp->device = card->cis.device; ++ } else { ++#endif ++ err = sdio_init_func(host->card, i + 1); ++ if (err) ++ goto remove; ++#ifdef CONFIG_MMC_EMBEDDED_SDIO ++ } ++#endif + /* + * Enable Runtime PM for this func (if supported) + */ +@@ -1198,3 +1241,40 @@ err: + return err; + } + ++int sdio_reset_comm(struct mmc_card *card) ++{ ++ struct mmc_host *host = card->host; ++ u32 ocr; ++ u32 rocr; ++ int err; ++ ++ printk("%s():\n", __func__); ++ mmc_claim_host(host); ++ ++ mmc_go_idle(host); ++ ++ mmc_set_clock(host, host->f_min); ++ ++ err = mmc_send_io_op_cond(host, 0, &ocr); ++ if (err) ++ goto err; ++ ++ rocr = mmc_select_voltage(host, ocr); ++ if (!rocr) { ++ err = -EINVAL; ++ goto err; ++ } ++ ++ err = mmc_sdio_init_card(host, rocr, card, 0); ++ if (err) ++ goto err; ++ ++ mmc_release_host(host); ++ return 0; ++err: ++ printk("%s: Error resetting SDIO communications (%d)\n", ++ mmc_hostname(host), err); ++ mmc_release_host(host); ++ return err; ++} ++EXPORT_SYMBOL(sdio_reset_comm); +diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c +index 6da97b1..a735f89 100644 +--- a/drivers/mmc/core/sdio_bus.c ++++ b/drivers/mmc/core/sdio_bus.c +@@ -26,6 +26,10 @@ + #include "sdio_cis.h" + #include "sdio_bus.h" + ++#ifdef CONFIG_MMC_EMBEDDED_SDIO ++#include ++#endif ++ + /* show configuration fields */ + #define sdio_config_attr(field, format_string) \ + static ssize_t \ +@@ -262,7 +266,14 @@ static void sdio_release_func(struct device *dev) + { + struct sdio_func *func = dev_to_sdio_func(dev); + +- sdio_free_func_cis(func); ++#ifdef CONFIG_MMC_EMBEDDED_SDIO ++ /* ++ * If this device is embedded then we never allocated ++ * cis tables for this func ++ */ ++ if (!func->card->host->embedded_sdio_data.funcs) ++#endif ++ sdio_free_func_cis(func); + + kfree(func->info); + +diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c +old mode 100644 +new mode 100755 +index 78cb4d5..8fdeb07 +--- a/drivers/mmc/core/sdio_io.c ++++ b/drivers/mmc/core/sdio_io.c +@@ -384,6 +384,39 @@ u8 sdio_readb(struct sdio_func *func, unsigned int addr, int *err_ret) + EXPORT_SYMBOL_GPL(sdio_readb); + + /** ++ * sdio_readb_ext - read a single byte from a SDIO function ++ * @func: SDIO function to access ++ * @addr: address to read ++ * @err_ret: optional status value from transfer ++ * @in: value to add to argument ++ * ++ * Reads a single byte from the address space of a given SDIO ++ * function. If there is a problem reading the address, 0xff ++ * is returned and @err_ret will contain the error code. ++ */ ++unsigned char sdio_readb_ext(struct sdio_func *func, unsigned int addr, ++ int *err_ret, unsigned in) ++{ ++ int ret; ++ unsigned char val; ++ ++ BUG_ON(!func); ++ ++ if (err_ret) ++ *err_ret = 0; ++ ++ ret = mmc_io_rw_direct(func->card, 0, func->num, addr, (u8)in, &val); ++ if (ret) { ++ if (err_ret) ++ *err_ret = ret; ++ return 0xFF; ++ } ++ ++ return val; ++} ++EXPORT_SYMBOL_GPL(sdio_readb_ext); ++ ++/** + * sdio_writeb - write a single byte to a SDIO function + * @func: SDIO function to access + * @b: byte to write +diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig +index 1386065..9629e12 100644 +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -748,3 +748,5 @@ config MMC_SUNXI + help + This selects support for the SD/MMC Host Controller on + Allwinner sunxi SoCs. ++ ++source "drivers/mmc/host/himciv200/Kconfig" +diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile +index b09ecfb..8999d29 100644 +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -75,3 +75,4 @@ obj-$(CONFIG_MMC_SDHCI_ST) += sdhci-st.o + ifeq ($(CONFIG_CB710_DEBUG),y) + CFLAGS-cb710-mmc += -DDEBUG + endif ++obj-$(CONFIG_HIMCIV200) += himciv200/ +diff --git a/drivers/mmc/host/himciv200/Kconfig b/drivers/mmc/host/himciv200/Kconfig +new file mode 100644 +index 0000000..323a5dd +--- /dev/null ++++ b/drivers/mmc/host/himciv200/Kconfig +@@ -0,0 +1,38 @@ ++# ++# himci v200 device configuration ++# ++menuconfig HIMCIV200 ++ tristate "himci v200 eMMC/SDXC/SDIO device support" ++ depends on (ARCH_HI3516CV300 || ARCH_HI3519 || ARCH_HI3519V101 || ARCH_HI3559 || ARCH_HI3556 || ARCH_HI3516AV200) ++ default y if (ARCH_HI3516CV300) ++ default y if (ARCH_HI3519) ++ default y if (ARCH_HI3519V101) ++ default y if (ARCH_HI3516AV200) ++ default y if (ARCH_HI3559) ++ default y if (ARCH_HI3556) ++ select MMC_UNSAFE_RESUME ++ select MMC_EMBEDDED_SDIO ++ select MMC_BLOCK ++ select MMC_BLOCK_BOUNCE ++ help ++ This selects the Hisilicon Synopsys MultiMedia Card Driver ++ support. If you want use SD/MMC/SDIO driver, ++ Say Y or M here. ++ ++ default is Y. ++ ++config SEND_AUTO_STOP ++ bool "Send Auto Stop to terminate data transfer between host and SD card" ++ depends on (ARCH_HI3516CV300 || ARCH_HI3519 || ARCH_HI3519V101 || ARCH_HI3559 || ARCH_HI3556 || ARCH_HI3516AV200) && HIMCIV200 ++ default y ++ ++config DETECT_CARD_TIME ++ int "The Period to detect whether Card is pluged or unpluged." ++ depends on (ARCH_HI3516CV300 || ARCH_HI3519 || ARCH_HI3519V101 || ARCH_HI3559 || ARCH_HI3556 || ARCH_HI3516AV200) && HIMCIV200 ++ range 10 500 ++ default 200 ++ help ++ Set the Period Time to detect the card, which the unit is ms. ++ Should set it between 10 and 500. ++ ++ Default is 200 here. +diff --git a/drivers/mmc/host/himciv200/Makefile b/drivers/mmc/host/himciv200/Makefile +new file mode 100644 +index 0000000..6ba3ce4 +--- /dev/null ++++ b/drivers/mmc/host/himciv200/Makefile +@@ -0,0 +1,2 @@ ++obj-$(CONFIG_HIMCIV200) += himciv200.o ++himciv200-objs := himci.o himci_proc.o +diff --git a/drivers/mmc/host/himciv200/himci.c b/drivers/mmc/host/himciv200/himci.c +new file mode 100644 +index 0000000..51b5343 +--- /dev/null ++++ b/drivers/mmc/host/himciv200/himci.c +@@ -0,0 +1,2237 @@ ++/* ++ * himci.c - hisilicon MMC Host 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. ++ */ ++#define pr_fmt(fmt) "himci: " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "himci_reg.h" ++#include "himci.h" ++#include "himci_dbg.h" ++#include "himci_acl.h" ++#include "himci_proc.h" ++ ++/*************************************************************************/ ++#ifdef CONFIG_ARCH_HI3516CV300 ++#include "himci_hi3516cv300.c" ++#endif ++ ++#ifdef CONFIG_ARCH_HI3519 ++#include "himci_hi3519.c" ++#endif ++ ++#ifdef CONFIG_ARCH_HI3519V101 ++#include "himci_hi3519v101.c" ++#endif ++ ++#ifdef CONFIG_ARCH_HI3516AV200 ++#include "himci_hi3516av200.c" ++#endif ++ ++#if defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) ++#include "himci_hi3559.c" ++#endif ++ ++#if defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) ++ #define PERF_OPT_RATIO 8 ++ #define MAX_SEGS 4096 ++#else ++ #define PERF_OPT_RATIO 1 ++ #define MAX_SEGS 1024 ++#endif ++ ++/*************************************************************************/ ++#define DRIVER_NAME "himci" ++ ++#ifdef CONFIG_DETECT_CARD_TIME ++static unsigned int detect_time = HZ*CONFIG_DETECT_CARD_TIME/1000; ++#else ++static unsigned int detect_time = HI_MCI_DETECT_TIMEOUT; ++#endif ++ ++static unsigned int retry_count = MAX_RETRY_COUNT; ++static unsigned int request_timeout = HI_MCI_REQUEST_TIMEOUT; ++int trace_level = HIMCI_TRACE_LEVEL; ++unsigned int slot_index = 0; ++struct himci_host *mci_host[HIMCI_SLOT_NUM] = {NULL}; ++ ++#ifdef MODULE ++ ++module_param(detect_time, uint, 0600); ++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, "HIMCI_TRACE_LEVEL"); ++ ++#endif ++ ++/* reset MMC host controller */ ++static void himciv200_sys_reset(struct himci_host *host) ++{ ++ unsigned int reg_value; ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ++ reg_value = himci_readl(host->base + MCI_BMOD); ++ reg_value |= BMOD_SWR; ++ himci_writel(reg_value, host->base + MCI_BMOD); ++ mdelay(10); ++ ++ reg_value = himci_readl(host->base + MCI_BMOD); ++ reg_value |= BURST_16 | BURST_INCR; ++ himci_writel(reg_value, host->base + MCI_BMOD); ++ ++ reg_value = himci_readl(host->base + MCI_CTRL); ++ reg_value |= CTRL_RESET | FIFO_RESET | DMA_RESET; ++ himci_writel(reg_value, host->base + MCI_CTRL); ++ ++ local_irq_restore(flags); ++} ++ ++static void himci_ctrl_power(struct himci_host *host, ++ unsigned int flag, unsigned int force) ++{ ++ unsigned int port; ++ ++ himci_trace(2, "begin"); ++ ++ port = host->cur_port; ++ ++ if (host->power_status != flag || force == FORCE_ENABLE) { ++ unsigned int reg_value; ++ ++ if (flag == POWER_OFF) { ++ reg_value = himci_readl(host->base + MCI_RESET_N); ++ reg_value &= ~(MMC_RST_N << port); ++ himci_writel(reg_value, host->base + MCI_RESET_N); ++ } ++ ++ reg_value = himci_readl(host->base + MCI_PWREN); ++ if (flag == POWER_OFF) ++ reg_value &= ~(0x1 << port); ++ else ++ reg_value |= (0x1 << port); ++ ++ himci_writel(reg_value, host->base + MCI_PWREN); ++ ++ if (flag == POWER_ON) { ++ reg_value = himci_readl(host->base + MCI_RESET_N); ++ reg_value |= (MMC_RST_N << port); ++ himci_writel(reg_value, host->base + MCI_RESET_N); ++ } ++ ++ if (in_interrupt()) ++ mdelay(100); ++ else ++ msleep(100); ++ ++ host->power_status = flag; ++ } ++} ++ ++static void himciv200_host_power(struct himci_host *host, unsigned int power_on, ++ unsigned int force) ++{ ++ if (host->power_status != power_on || force) { ++ if (!power_on) { ++ himci_writel(0, host->base + MCI_RESET_N); ++ himci_writel(0, host->base + MCI_PWREN); ++ } else { ++ himci_writel(1, host->base + MCI_PWREN); ++ himci_writel(1, host->base + MCI_RESET_N); ++ } ++ ++ mdelay(100); ++ ++ host->power_status = power_on; ++ } ++} ++ ++static void himci_idma_start(struct himci_host *host) ++{ ++ unsigned int tmp; ++ ++ himci_trace(2, "begin"); ++ ++ tmp = himci_readl(host->base + MCI_BMOD); ++ tmp |= BMOD_DMA_EN; ++ himci_writel(tmp, host->base + MCI_BMOD); ++} ++ ++/********************************************** ++ *1: card off ++ *0: card on ++ ***********************************************/ ++static unsigned int himci_sys_card_detect(struct himci_host *host) ++{ ++ unsigned int card_status; ++ ++ card_status = himci_readl(host->base + MCI_CDETECT); ++ ++ /* eMMC need't detect, but we check if eMMC controller available */ ++ if (!(host->mmc->caps & MMC_CAP_SD_HIGHSPEED)) ++ return himci_check_emmc(host); ++ ++ card_status &= HIMCI_CARD0; ++ return card_status; ++} ++ ++/********************************************** ++ *1: card readonly ++ *0: card read/write ++ ***********************************************/ ++static unsigned int himci_ctrl_card_readonly(struct himci_host *host) ++{ ++ unsigned int card_value = himci_readl(host->base + MCI_WRTPRT); ++ unsigned int port = host->cur_port; ++ ++ return card_value & (HIMCI_CARD0 << port); ++} ++ ++static int himci_wait_cmd(struct himci_host *host) ++{ ++ int wait_retry_count = 0; ++ unsigned int reg_data = 0; ++ unsigned long flags; ++ ++ 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 = himci_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 = himci_readl(host->base + MCI_RINTSTS); ++ if (reg_data & HLE_INT_STATUS) { ++ reg_data |= HLE_INT_STATUS; ++ himci_writel(reg_data, host->base + MCI_RINTSTS); ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ himci_trace(5, "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) { ++ himci_trace(3, "send cmd is timeout!"); ++ return -1; ++ } ++ } ++} ++ ++static void himci_control_cclk(struct himci_host *host, unsigned int flag) ++{ ++ unsigned int reg; ++ union cmd_arg_u cmd_reg; ++ unsigned int port = host->cur_port; ++ ++ himci_trace(2, "begin"); ++ himci_assert(host); ++ ++ reg = himci_readl(host->base + MCI_CLKENA); ++ if (flag == ENABLE) { ++ reg |= (CCLK_ENABLE << port); ++ reg |= (0x10000 << port); ++ } else { ++ reg &= ~(CCLK_ENABLE << port); ++ reg &= ~(0x10000 << port); ++ } ++ ++ himci_writel(reg, host->base + MCI_CLKENA); ++ cmd_reg.cmd_arg = himci_readl(host->base + MCI_CMD); ++ cmd_reg.bits.start_cmd = 1; ++ cmd_reg.bits.card_number = port; ++ cmd_reg.bits.cmd_index = 0; ++ cmd_reg.bits.data_transfer_expected = 0; ++ cmd_reg.bits.update_clk_reg_only = 1; ++ cmd_reg.bits.response_expect = 0; ++ cmd_reg.bits.send_auto_stop = 0; ++ cmd_reg.bits.wait_prvdata_complete = 0; ++ cmd_reg.bits.check_response_crc = 0; ++ himci_writel(cmd_reg.cmd_arg, host->base + MCI_CMD); ++ if (himci_wait_cmd(host) != 0) ++ himci_trace(3, "disable or enable clk is timeout!"); ++} ++ ++static void himci_set_cclk(struct himci_host *host, unsigned int cclk) ++{ ++ unsigned int reg_value = 0; ++ union cmd_arg_u clk_cmd; ++ unsigned int port = host->cur_port; ++ unsigned int hclk; ++ unsigned int clk_rate; ++ int ret; ++ ++ himci_trace(2, "begin"); ++ himci_assert(host); ++ himci_assert(cclk); ++ ++ clk_rate = cclk > MMC_CRG_MIN ? cclk : MMC_CRG_MIN; ++ ret = clk_set_rate(host->clk, clk_rate); ++ if (ret) ++ dev_warn(mmc_dev(host->mmc), ++ "failed to set rate %uHz\n", clk_rate); ++ ++ hclk = clk_get_rate(host->clk); ++ ++ /* ++ * set card clk divider value, ++ * clk_divider = Fmmcclk/(Fmmc_cclk * 2) ++ */ ++ reg_value = hclk / (cclk * 2); ++ if ((hclk % (cclk * 2)) && (hclk > cclk)) ++ reg_value++; ++ if (reg_value > 0xFF) ++ reg_value = 0xFF; ++ ++ host->hclk = hclk; ++ host->cclk = reg_value ? (hclk / (reg_value * 2)) : hclk; ++ himci_writel(reg_value, host->base + MCI_CLKDIV); ++ clk_cmd.cmd_arg = himci_readl(host->base + MCI_CMD); ++ clk_cmd.bits.start_cmd = 1; ++ clk_cmd.bits.card_number = port; ++ clk_cmd.bits.update_clk_reg_only = 1; ++ clk_cmd.bits.cmd_index = 0; ++ clk_cmd.bits.data_transfer_expected = 0; ++ clk_cmd.bits.response_expect = 0; ++ himci_writel(clk_cmd.cmd_arg, host->base + MCI_CMD); ++ if (himci_wait_cmd(host) != 0) ++ himci_trace(3, "set card clk divider is failed!"); ++} ++ ++static void himci_pre_init_host(struct himci_host *host) ++{ ++#if !defined(CONFIG_ARCH_HI3516CV300) ++ unsigned int shift[] = {13, 5, 21}; ++ unsigned int reg; ++ ++ reg = himci_readl(PERI_CRG49); ++ reg |= 0x1 << shift[host->devid]; ++ himci_writel(reg, PERI_CRG49); ++ ++ if (!(host->mmc->caps & MMC_CAP_SD_HIGHSPEED)) { ++ himci_writel(0x10, EMMC_DLL_CTRL); ++ reg = himci_readl(PERI_CRG49); ++ reg |= 0x1 << 22; ++ himci_writel(reg, PERI_CRG49); ++ } ++#endif ++} ++ ++static void himci_init_host(struct himci_host *host) ++{ ++ unsigned int tmp_reg = 0; ++ struct mmc_host *mmc; ++ ++ himci_trace(3, "begin init card"); ++ himci_assert(host); ++ ++ mmc = host->mmc; ++ host->error_count = 0; ++ /* controller config gpio */ ++ himci_writel(CMD_OUT_EN_FIX_BYPASS | DTO_FIX_BYPASS, ++ host->base + MCI_GPIO); ++ ++ himciv200_sys_reset(host); ++ ++ himci_pre_init_host(host); ++ ++ /* set drv/smpl phase shift */ ++ if (mmc->caps & MMC_CAP_HW_RESET) ++ tmp_reg |= EMMC_SMPL_PHASE_DFLT | EMMC_DRV_PHASE_DFLT; ++ else ++ tmp_reg |= SMPL_PHASE_DFLT | DRV_PHASE_DFLT; ++ ++ himci_writel(tmp_reg, host->base + MCI_UHS_REG_EXT); ++ ++ /* set card read threshold */ ++ himci_writel(RW_THRESHOLD_SIZE, host->base + MCI_CARDTHRCTL); ++ ++ /* clear MMC host intr */ ++ himci_writel(ALL_INT_CLR, host->base + MCI_RINTSTS); ++ tmp_reg = himci_readl(host->base + MCI_IDSTS); ++ tmp_reg |= ALL_ADMA_INT_CLR; ++ himci_writel(tmp_reg, host->base + MCI_IDSTS); ++ ++ /* MASK MMC all host intr */ ++ tmp_reg = himci_readl(host->base + MCI_INTMASK); ++ tmp_reg &= ~ALL_INT_MASK; ++ himci_writel(tmp_reg, host->base + MCI_INTMASK); ++ ++ /* enable inner DMA mode and close intr of MMC host controller */ ++ tmp_reg = himci_readl(host->base + MCI_CTRL); ++ tmp_reg &= ~INTR_EN; ++ tmp_reg |= USE_INTERNAL_DMA | INTR_EN; ++ himci_writel(tmp_reg, host->base + MCI_CTRL); ++ ++ /* set timeout param */ ++ himci_writel(DATA_TIMEOUT | RESPONSE_TIMEOUT, host->base + MCI_TIMEOUT); ++ ++ /* set FIFO param */ ++ tmp_reg = 0; ++ tmp_reg |= BURST_SIZE | RX_WMARK | TX_WMARK; ++ himci_writel(tmp_reg, host->base + MCI_FIFOTH); ++ ++ /* ADMA3: disable ADMA Func */ ++ himci_writel(0x0, host->base + ADMA_CTRL); ++ ++ /* ADMA3: set entire des addr and quene deepth */ ++ himci_writel(host->entire_paddr, host->base + ADMA_Q_ADDR); /* */ ++ himci_writel(ADMA_QUEUE_DEEPTH, host->base + ADMA_Q_DEEPTH); ++ ++ /* ADMA3: reset queue read/write ptr */ ++ tmp_reg = himci_readl(host->base + ADMA_CTRL); ++ tmp_reg |= RDPTR_MOD_EN; ++ himci_writel(tmp_reg, host->base + ADMA_CTRL); ++ himci_writel(0x0, host->base + ADMA_Q_RDPTR); ++ himci_writel(0x0, host->base + ADMA_Q_WRPTR); ++ tmp_reg = himci_readl(host->base + ADMA_CTRL); ++ tmp_reg &= ~RDPTR_MOD_EN; ++ himci_writel(tmp_reg, host->base + ADMA_CTRL); ++ ++ /* ADMA3: set queue timeout value */ ++ himci_writel(0xffffffff, host->base + ADMA_Q_TO); ++ ++ /* ADMA3: enable ADMA intr */ ++ tmp_reg = (CMD_LOCK_ERR | OWNBIT_ERR | QUEUE_OVERFLOW ++ | RESP_CHECK_ERR | PACKET_INT | PACKET_TO_INT ++ | AUTO_STOP_ERR | QUEUE_FULL | CES | DU | FBE); ++ ++ himci_writel(tmp_reg, host->base + MCI_IDINTEN); ++ /* ADMA3: clear ADMA3 intr */ ++ tmp_reg = (CMD_LOCK_ERR | OWNBIT_ERR | QUEUE_OVERFLOW ++ | RESP_CHECK_ERR | PACKET_INT | PACKET_TO_INT ++ | AUTO_STOP_ERR | QUEUE_FULL | QUEUE_EMPTY | CES ++ | DU | FBE); ++ himci_writel(tmp_reg, host->base + MCI_IDSTS); ++ ++ /* ADMA3: enable ADMA Func */ ++ tmp_reg = PACKET_INT_EN | ADMA3_EN; ++ himci_writel(tmp_reg, host->base + ADMA_CTRL); ++ ++ himci_idma_start(host); ++ host->mmc->status = MMC_HOST_OK; ++} ++ ++void himci_sw_reset(struct mmc_host *mmc) ++{ ++ struct himci_host *host = mmc_priv(mmc); ++ int i; ++ ++ clk_prepare_enable(host->clk); ++ himci_init_host(host); ++ ++ for (i = 0; i < ADMA_QUEUE_DEEPTH ; i++) ++ host->pmrq[i] = NULL; ++} ++ ++static void himci_detect_card(unsigned long arg) ++{ ++ struct himci_host *host = (struct himci_host *)arg; ++ unsigned int i, curr_status, status[3], detect_retry_count = 0; ++ ++ himci_assert(host); ++ ++ while (1) { ++ for (i = 0; i < 3; i++) { ++ status[i] = himci_sys_card_detect(host); ++ udelay(10); ++ } ++ if ((status[0] == status[1]) && (status[0] == status[2])) ++ break; ++ detect_retry_count++; ++ if (detect_retry_count >= retry_count) { ++ himci_error("this is a dithering, card detect error!"); ++ goto err; ++ } ++ } ++ curr_status = status[0]; ++ if (curr_status != host->card_status) { ++ himci_trace(2, "begin card_status = %d\n", host->card_status); ++ host->card_status = curr_status; ++ if (curr_status != CARD_UNPLUGED) { ++ himci_init_host(host); ++ pr_info("card connected!\n"); ++ } else { ++ pr_info("card disconnected!\n"); ++ host->mmc->status = MMC_HOST_ERR; ++ } ++ ++ mmc_detect_change(host->mmc, 0); ++ } ++err: ++ mod_timer(&host->timer, jiffies + detect_time); ++} ++ ++static int himci_prep_data(struct himci_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 himci_dma_des *dma_des; ++ struct himci_dma_des *des; ++ unsigned int *dma_paddr; ++ unsigned int dma_dir; ++ ++ himci_trace(2, "begin"); ++ himci_assert(host); ++ himci_assert(data); ++ ++ host->data = data; ++ ++ if (data->flags & MMC_DATA_READ) ++ dma_dir = DMA_FROM_DEVICE; ++ else ++ 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, dma_dir); ++ himci_assert(host->dma_sg_num); ++ himci_trace(2, "sg_num is %d\n", host->dma_sg_num); ++ ++ data_size = data->blksz * data->blocks; ++ if (data_size > (DMA_BUFFER * MAX_DMA_DES)) { ++ himci_error("mci request data_size is too big!\n"); ++ ret = -1; ++ goto out; ++ } ++ ++ himci_trace(2, "host->dma_paddr is 0x%08X,host->dma_addr is 0x%08X\n", ++ (unsigned int)host->dma_paddr, ++ (unsigned int)host->dma_addr); ++ ++ max_des = PERF_OPT_RATIO * PAGE_SIZE / sizeof(struct himci_dma_des) - 1; ++ ++ /* dma descriptor is followed by cmd descriptor */ ++ dma_des = (struct himci_dma_des *)(host->wr_cmd_des + 1); ++ dma_paddr = (unsigned int *)(host->cmd_paddr + PERF_OPT_RATIO * PAGE_SIZE * host->wr_pos ++ + sizeof(struct himci_cmd_des)); ++ ++ des = dma_des; ++ 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]); ++ himci_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 = (unsigned long) ++ (dma_paddr + (des_cnt + 1) * 4); ++ ++ /* buffer size <= 4k */ ++ if (sg_length >= 0x1000) { ++ des[des_cnt].idmac_des_buf_size = 0x1000; ++ sg_length -= 0x1000; ++ sg_phyaddr += 0x1000; ++ } else { ++ /* data alignment */ ++ des[des_cnt].idmac_des_buf_size = sg_length; ++ sg_length = 0; ++ } ++ himci_trace(2, "des[%d] vaddr is 0x%08X", ++ des_cnt, (unsigned int)&des[des_cnt]); ++ himci_trace(2, "des[%d].idmac_des_ctrl is 0x%08X", ++ des_cnt, (unsigned int) ++ des[des_cnt].idmac_des_ctrl); ++ himci_trace(2, "des[%d].idmac_des_buf_size is 0x%08X", ++ des_cnt, (unsigned int) ++ des[des_cnt].idmac_des_buf_size); ++ himci_trace(2, "des[%d].idmac_des_buf_addr 0x%08X", ++ des_cnt, ++ (unsigned int)des[des_cnt].idmac_des_buf_addr); ++ himci_trace(2, "des[%d].idmac_des_next_addr is 0x%08X", ++ des_cnt, (unsigned int) ++ des[des_cnt].idmac_des_next_addr); ++ des_cnt++; ++ } ++ ++ himci_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; ++ himci_trace(2, "des[%d].idmac_des_ctrl is 0x%08X", ++ des_cnt-1, (unsigned int)des[des_cnt-1].idmac_des_ctrl); ++out: ++ return ret; ++} ++ ++static int himci_prep_cmd(struct himci_host *host, struct mmc_command *cmd, ++ struct mmc_data *data) ++{ ++ volatile union cmd_arg_u cmd_regs; ++ unsigned int port = host->cur_port; ++ struct himci_cmd_des *cmd_des; ++ ++ himci_trace(2, "begin"); ++ himci_assert(host); ++ himci_assert(cmd); ++ ++ host->cmd = cmd; ++ ++ cmd_des = host->wr_cmd_des; ++ cmd_des->arg = cmd->arg; ++ ++ himci_trace(3, "arg_reg 0x%x, val 0x%x\n", MCI_CMDARG, cmd->arg); ++ cmd_regs.cmd_arg = DEFAULT_CMD_VALUE; ++ 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; ++ } ++ ++#ifdef CONFIG_SEND_AUTO_STOP ++ if (host->mrq->stop) ++ cmd_regs.bits.send_auto_stop = 1; ++#endif ++ ++ if (cmd->opcode == MMC_STOP_TRANSMISSION) { ++ 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: ++ case MMC_RSP_R1 & (~MMC_RSP_CRC): ++ cmd_regs.bits.response_expect = 1; ++ cmd_regs.bits.response_length = 0; ++ cmd_regs.bits.check_response_crc = 0; ++ break; ++ default: ++ host->cmd->error = -EINVAL; ++ himci_error("himci: unhandled response type %02x\n", ++ mmc_resp_type(cmd)); ++ return -EINVAL; ++ } ++ ++ himci_trace(4, "cmd->opcode = %d cmd->arg = 0x%X\n", ++ cmd->opcode, cmd->arg); ++ ++ if (cmd->opcode == SD_SWITCH_VOLTAGE) ++ cmd_regs.bits.volt_switch = 1; ++ else ++ cmd_regs.bits.volt_switch = 0; ++ ++ cmd_regs.bits.send_initialization = 1; ++ cmd_regs.bits.card_number = port; ++ cmd_regs.bits.cmd_index = cmd->opcode; ++ cmd_regs.bits.start_cmd = 1; ++ cmd_regs.bits.update_clk_reg_only = 0; ++ ++ cmd_des->cmd = cmd_regs.cmd_arg; ++ ++ himci_trace(4, "cmd_reg 0x%x, val 0x%x\n", MCI_CMD, cmd_regs.cmd_arg); ++ ++ return 0; ++} ++ ++static void himci_data_done(struct mmc_host *host, ++ struct mmc_request *mrq, int err) ++{ ++ struct mmc_data *data = mrq->data; ++ unsigned int dma_dir; ++ ++ if (!data) ++ return; ++ if (data->flags & MMC_DATA_READ) ++ dma_dir = DMA_FROM_DEVICE; ++ else ++ dma_dir = DMA_TO_DEVICE; ++ dma_unmap_sg(mmc_dev(host), data->sg, data->sg_len, dma_dir); ++ ++ if (!data->error) ++ data->bytes_xfered = data->blocks * data->blksz; ++ else ++ data->bytes_xfered = 0; ++ ++} ++ ++static void himci_finish_request(struct himci_host *host, ++ struct mmc_request *mrq) ++{ ++ himci_trace(2, "begin"); ++ himci_assert(host); ++ himci_assert(mrq); ++ ++ himci_data_done(host->mmc, mrq, 0); ++ mmc_request_done(host->mmc, mrq); ++} ++ ++static void himci_cmd_done(struct mmc_request *mrq, unsigned int stat) ++{ ++ struct mmc_command *cmd = mrq->cmd; ++ ++ himci_trace(2, "begin"); ++ himci_assert(cmd); ++ ++ if (stat & RTO_INT_STATUS) { ++ cmd->error = -ETIMEDOUT; ++ himci_trace(3, "irq cmd status stat = 0x%x is timeout error!", ++ stat); ++ } else if (stat & (RCRC_INT_STATUS | RE_INT_STATUS)) { ++ cmd->error = -EILSEQ; ++ himci_error("irq cmd status stat = 0x%x is response error!", ++ stat); ++ } ++} ++ ++#define CMD_ERRORS \ ++ (R1_OUT_OF_RANGE | /* Command argument out of range */ \ ++ R1_ADDRESS_ERROR | /* Misaligned address */ \ ++ R1_BLOCK_LEN_ERROR | /* Transferred block length incorrect */\ ++ R1_WP_VIOLATION | /* Tried to write to protected block */ \ ++ R1_CC_ERROR | /* Card controller error */ \ ++ R1_ERROR) /* General/unknown error */ ++ ++static void himci_read_response(struct himci_host *host, ++ struct mmc_command *cmd) ++{ ++ /* Read response of the card */ ++ if (cmd->flags & MMC_RSP_PRESENT) { ++ if (cmd->flags & MMC_RSP_136) { ++ cmd->resp[3] = himci_readl(host->base + MCI_RESP0); ++ cmd->resp[2] = himci_readl(host->base + MCI_RESP1); ++ cmd->resp[1] = himci_readl(host->base + MCI_RESP2); ++ cmd->resp[0] = himci_readl(host->base + MCI_RESP3); ++ } else { ++ cmd->resp[0] = himci_readl(host->base + MCI_RESP0); ++ cmd->resp[1] = 0; ++ cmd->resp[2] = 0; ++ cmd->resp[3] = 0; ++ } ++ } ++ if ((cmd->flags & MMC_CMD_TYPE_RW) && (cmd->resp[0] & CMD_ERRORS)) ++ host->error_count++; ++} ++ ++static void himci_reset_host(struct himci_host *host) ++{ ++ unsigned int i = 0, reg_value; ++ ++ /* DMA Controller resets */ ++ reg_value = himci_readl(host->base + ADMA_CTRL); ++ reg_value &= ~(ADMA3_EN); ++ himci_writel(reg_value, host->base + ADMA_CTRL); ++ reg_value = himci_readl(host->base + MCI_BMOD); ++ reg_value |= BMOD_SWR; ++ himci_writel(reg_value, host->base + MCI_BMOD); ++ himci_writel(0xFFFFFFFF, host->base + MCI_IDSTS); ++ ++ /* ADMA3: reset queue R/W ptr */ ++ reg_value = himci_readl(host->base + ADMA_CTRL); ++ reg_value |= (RDPTR_MOD_EN); ++ reg_value &= ~(ADMA3_EN); ++ himci_writel(reg_value, host->base + ADMA_CTRL); ++ himci_writel(0, host->base + ADMA_Q_WRPTR); ++ himci_writel(0, host->base + ADMA_Q_RDPTR); ++ for (i = 0; i < ADMA_QUEUE_DEEPTH ; i++) ++ host->pmrq[i] = NULL; ++ ++ himci_writel(0xFFFFFFFF, host->base + MCI_RINTSTS); ++ udelay(800); ++ ++ reg_value = himci_readl(host->base + ADMA_CTRL); ++ reg_value &= ~RDPTR_MOD_EN; ++ reg_value |= (ADMA3_EN); ++ himci_writel(reg_value, host->base + ADMA_CTRL); ++ ++ /* ADMA3: restart */ ++ reg_value = himci_readl(host->base + ADMA_CTRL); ++ reg_value |= ADMA3_RESTART; ++ himci_writel(reg_value, host->base + ADMA_CTRL); ++ ++ /* dma enable */ ++ himci_idma_start(host); ++} ++ ++static void himci_err_check(struct himci_host *host, ++ unsigned int qstat, unsigned int rstat, ++ unsigned int *cmd_err, unsigned int *data_err) ++{ ++ *cmd_err = 0; ++ *data_err = 0; ++ ++ if (!(qstat & (ADMA_INT_ERR | CES))) ++ return; ++ ++ if (qstat & ADMA_INT_ERR) { ++ himci_trace(4, "ADMA err! qstat:%x rstat:%x\n", qstat, rstat); ++ *cmd_err = -ETIMEDOUT; ++ } ++ ++ if (qstat & CES) { ++ himci_trace(4, "CES err! qstat:%x rstat:%x\n", qstat, rstat); ++ if (rstat & RTO_INT_STATUS) { ++ himci_trace(3, "response timeout error!"); ++ *cmd_err = -ETIMEDOUT; ++ } else if (rstat & (RCRC_INT_STATUS | RE_INT_STATUS)) { ++ himci_trace(3, "response crc error!"); ++ *cmd_err = -EILSEQ; ++ } ++ ++ if (rstat & (HTO_INT_STATUS | DRTO_INT_STATUS)) { ++ himci_trace(3, "data transfer timeout error!"); ++ *data_err = -ETIMEDOUT; ++ } else if (rstat & (EBE_INT_STATUS | SBE_INT_STATUS | ++ FRUN_INT_STATUS | DCRC_INT_STATUS)) { ++ himci_trace(3, "data transfer error!"); ++ *data_err = -EILSEQ; ++ } ++ } ++ ++ if (*cmd_err || *data_err) ++ himci_reset_host(host); ++} ++ ++static int himci_wait_voltage_switch(struct himci_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; ++ ++ himci_trace(2, "begin"); ++ himci_assert(host); ++ himci_assert(cmd); ++ ++ himci_trace(3, "wait voltage switch..."); ++ cmd_jiffies_timeout = jiffies + request_timeout; ++ while (1) { ++ do { ++ spin_lock_irqsave(&host->lock, flags); ++ cmd_irq_reg = himci_readl(host->base + MCI_RINTSTS); ++ if (cmd_irq_reg & VOLT_SWITCH_INT_STATUS) { ++ himci_writel(VOLT_SWITCH_INT_STATUS, ++ host->base + MCI_RINTSTS); ++ spin_unlock_irqrestore(&host->lock, flags); ++ himci_cmd_done(host->mrq, cmd_irq_reg); ++ goto switch_succeed; ++ } ++ 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) { ++ cmd->error = -ETIMEDOUT; ++ return -1; ++ } ++ ++ if (!time_before(jiffies, cmd_jiffies_timeout)) { ++ unsigned int i = 0; ++ ++ for (i = 0; i < 4; i++) { ++ cmd->resp[i] = himci_readl(host->base ++ + MCI_RESP0 + i * 0x4); ++ } ++ cmd->error = -ETIMEDOUT; ++ himci_trace(3, "wait cmd request complete is timeout!"); ++ return -1; ++ } ++ ++ schedule(); ++ } ++switch_succeed: ++ /* bugfix: synopsys will trigger sdio intr when send cmd11, ++ * it's a bug and must be cleared ++ */ ++ himci_writel(SDIO_INT_STATUS, host->base + MCI_RINTSTS); ++ return 0; ++} ++ ++/* Prepare the entire descriptor */ ++static void himci_prep_entire(struct himci_host *host, ++ struct mmc_request *mrq) ++{ ++ struct himci_entire_des *ent_des; ++ struct himci_cmd_des *cmd_des; ++ unsigned int wr_pos; ++ ++ wr_pos = himci_readl(host->base + ADMA_Q_WRPTR); ++ mrq->wr_pos = wr_pos; /* only for ADMA3 R/W */ ++ host->pmrq[wr_pos] = mrq; /* save send mrq */ ++ host->wr_pos = wr_pos; ++ ++ himci_trace(3, "write des to position %d", wr_pos); ++ /* select entire descriptor */ ++ ent_des = (struct himci_entire_des *)(host->entire_addr); ++ ent_des = ent_des + wr_pos; ++ host->wr_ent_des = ent_des; ++ ++ /* config entire descriptor */ ++ ent_des->cmd_des_addr = host->cmd_paddr + PERF_OPT_RATIO * PAGE_SIZE * wr_pos; ++ ++ if ((host->cmd->flags & MMC_CMD_NON_BLOCKING) ++ || (mrq->cmd->opcode == SD_SWITCH_VOLTAGE)) { ++ /* non-blocking command needn't issue intr */ ++ himci_trace(2, "command is non-blocking"); ++ ent_des->ctrl = 0x80000000; ++ } else { ++ himci_trace(2, "command is block"); ++ ent_des->ctrl = 0xa0000000; ++ } ++ himci_trace(2, "ent des addr: 0x%x", host->entire_paddr ++ + sizeof(struct himci_entire_des) * wr_pos); ++ ++ /* select command descriptor */ ++ cmd_des = (struct himci_cmd_des *)(host->cmd_addr); ++ cmd_des = cmd_des + (PERF_OPT_RATIO * 256 * wr_pos); ++ host->wr_cmd_des = cmd_des; ++} ++ ++static void himci_request(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct himci_host *host = mmc_priv(mmc); ++ unsigned int byte_cnt = 0; ++ unsigned int status; ++ int ret = 0, i = 0; ++ struct himci_cmd_des *cmd_des; ++ unsigned int rd_pos; ++ ++ himci_trace(2, "begin"); ++ himci_assert(mmc); ++ himci_assert(mrq); ++ himci_assert(host); ++ ++ host->mrq = mrq; ++ host->cmd = mrq->cmd; ++ host->data = mrq->data; ++ ++ /* prepare entire des */ ++ himci_prep_entire(host, mrq); ++ cmd_des = host->wr_cmd_des; ++ ++ /* prepare data des */ ++ if (mrq->data) { ++ ret = himci_prep_data(host, mrq->data); ++ if (ret) { ++ mrq->data->error = ret; ++ himci_trace(3, "data setup is error!"); ++ goto request_done; ++ } ++ ++ byte_cnt = mrq->data->blksz * mrq->data->blocks; ++ cmd_des->blk_sz = mrq->data->blksz; ++ cmd_des->byte_cnt = byte_cnt; ++ himci_trace(3, "blk_sz:%d blk_cnt:%d", ++ mrq->data->blksz, mrq->data->blocks); ++ } else { ++ cmd_des->blk_sz = 0; ++ cmd_des->byte_cnt = 0; ++ } ++ ++ /* prepare command des */ ++ ret = himci_prep_cmd(host, mrq->cmd, mrq->data); ++ if (ret) ++ goto request_done; ++ ++ if (mmc->caps & MMC_CAP_SD_HIGHSPEED) { ++ status = himci_sys_card_detect(host); ++ if (status == CARD_UNPLUGED) { ++ for (i = 0; i < ADMA_QUEUE_DEEPTH ; i++) ++ host->pmrq[i] = NULL; ++ host->cmd->error = -ETIMEDOUT; ++ if (host->cmd->flags & MMC_CMD_TYPE_RW) ++ host->mmc->status = MMC_HOST_ERR; ++ goto request_done; ++ } ++ } ++ ++ /* update des write pointer */ ++ host->wr_pos++; ++ host->wr_pos %= ADMA_QUEUE_DEEPTH; ++ himci_writel(host->wr_pos, host->base + ADMA_Q_WRPTR); ++ ++ if (host->cmd->opcode == SD_SWITCH_VOLTAGE) { ++ ret = himci_wait_voltage_switch(host); ++ if (ret) ++ himci_trace(5, "voltage switch failed!"); ++ rd_pos = host->wr_pos ? host->wr_pos - 1 ++ : ADMA_QUEUE_DEEPTH - 1; ++ host->pmrq[rd_pos] = NULL; ++ goto request_done; ++ } ++ ++ if (!(host->cmd->flags & MMC_CMD_TYPE_RW)) { ++ long time; ++ ++ time = wait_event_timeout(host->intr_wait, host->cmd_done, HZ); ++ if (time <= 0) { ++ unsigned int rstat; ++ unsigned int qstat; ++ unsigned int cmd_err; ++ unsigned int data_err; ++ ++ rstat = himci_readl(host->base + MCI_RINTSTS); ++ qstat = himci_readl(host->base + MCI_IDSTS); ++ himci_err_check(host, qstat, rstat, ++ &cmd_err, &data_err); ++ mrq->cmd->error = -ETIMEDOUT; ++ himci_trace(5, "CMD%u wait event timeout", mrq->cmd->opcode); ++ } ++ ++ host->cmd_done = 0; ++ rd_pos = host->wr_pos ? host->wr_pos - 1 ++ : ADMA_QUEUE_DEEPTH - 1; ++ host->pmrq[rd_pos] = NULL; ++ himci_read_response(host, mrq->cmd); ++ goto request_done; ++ } ++ return; ++ ++request_done: ++ himci_finish_request(host, mrq); ++} ++ ++static int himci_do_voltage_switch(struct himci_host *host, ++ struct mmc_ios *ios) ++{ ++ struct mmc_host *mmc = host->mmc; ++ u32 ctrl; ++ unsigned int port = host->cur_port; ++ /* ++ * 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 = himci_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 */ ++ himci_trace(3, "switch voltage 330"); ++ ctrl &= ~(HI_SDXC_CTRL_VDD_180 << port); ++ himci_writel(ctrl, host->base + MCI_UHS_REG); ++ ++ /* Wait for 5ms */ ++ usleep_range(5000, 5500); ++ ++ /* 3.3V regulator output should be stable within 5ms */ ++ ctrl = himci_readl(host->base + MCI_UHS_REG); ++ if (!(ctrl & (HI_SDXC_CTRL_VDD_180 << port))) { ++ return 0; ++ } else { ++ himci_error(": Switching to 3.3V "); ++ himci_error("signalling voltage failed\n"); ++ return -EIO; ++ } ++ } else if (!(ctrl & (HI_SDXC_CTRL_VDD_180 << port)) && ++ (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)) { ++ /* Stop SDCLK */ ++ himci_trace(3, "switch voltage 180"); ++ himci_control_cclk(host, DISABLE); ++ ++ /* ++ * Enable 1.8V Signal Enable in the MCI_UHS_REG ++ */ ++ ctrl |= (HI_SDXC_CTRL_VDD_180 << port); ++ himci_writel(ctrl, host->base + MCI_UHS_REG); ++ ++ /* Wait for 8ms */ ++ usleep_range(8000, 8500); ++ ++ ctrl = himci_readl(host->base + MCI_UHS_REG); ++ if (ctrl & (HI_SDXC_CTRL_VDD_180 << port)) { ++ /* Provide SDCLK again and wait for 1ms */ ++ himci_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 = himci_readl(host->base + MCI_RINTSTS); ++ if ((ctrl & VOLT_SWITCH_INT_STATUS) ++ && (ctrl & CD_INT_STATUS)) { ++ himci_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 &= ~(HI_SDXC_CTRL_VDD_180 << port); ++ himci_writel(ctrl, host->base + MCI_UHS_REG); ++ ++ /* Wait for 5ms */ ++ usleep_range(5000, 5500); ++ ++ himci_ctrl_power(host, POWER_OFF, FORCE_DISABLE); ++ /* Wait for 1ms as per the spec */ ++ usleep_range(1000, 1500); ++ himci_ctrl_power(host, POWER_ON, FORCE_DISABLE); ++ ++ himci_control_cclk(host, DISABLE); ++ /* Wait for 1ms as per the spec */ ++ usleep_range(1000, 1500); ++ himci_control_cclk(host, ENABLE); ++ ++ himci_error(": Switching to 1.8V signalling "); ++ himci_error("voltage failed, retrying with S18R set to 0\n"); ++ return -EAGAIN; ++ } else ++ /* No signal voltage switch required */ ++ return 0; ++} ++ ++static int himci_start_signal_voltage_switch(struct mmc_host *mmc, ++ struct mmc_ios *ios) ++{ ++ struct himci_host *host = mmc_priv(mmc); ++ int err; ++ ++ err = himci_do_voltage_switch(host, ios); ++ return err; ++} ++ ++static int himci_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; ++} ++ ++#if defined(CONFIG_ARCH_HI3516CV300) ++static void himci_edge_tuning_enable(struct himci_host *host) ++{ ++ unsigned int val; ++ ++ val = himci_readl(host->base + MCI_TUNING_CTRL); ++ val |= HW_TUNING_EN; ++ himci_writel(val, host->base + MCI_TUNING_CTRL); ++} ++ ++static void himci_edge_tuning_disable(struct himci_host *host) ++{ ++ unsigned int val; ++ ++ val = himci_readl(host->base + MCI_TUNING_CTRL); ++ val &= ~HW_TUNING_EN; ++ himci_writel(val, host->base + MCI_TUNING_CTRL); ++} ++ ++static void himci_set_sap_phase(struct himci_host *host, u32 phase) ++{ ++ unsigned int val; ++ unsigned int phase_a; ++ ++ phase_a = phase >= 2 ? phase - 2 : phase + 6; ++ val = himci_readl(host->base + MCI_UHS_REG_EXT); ++ val &= ~(CLK_SMPL_PHS_MASK | CLK_SMPLA_PHS_MASK); ++ val |= (phase << CLK_SMPL_PHS_SHIFT) | (phase_a << CLK_SMPLA_PHS_SHIFT); ++ himci_writel(val, host->base + MCI_UHS_REG_EXT); ++ val = himci_readl(host->base + MCI_UHS_REG_EXT); ++} ++ ++static int himci_execute_edge_tuning(struct mmc_host *mmc, u32 opcode) ++{ ++ struct himci_host *host = mmc_priv(mmc); ++ unsigned int index, val; ++ unsigned int found = 0, prev_found = 0, prev_point = 0; ++ unsigned int start_point = NOT_FOUND, end_point = NOT_FOUND; ++ unsigned int phase = 0; ++ ++ himci_trace(3, "begin"); ++ ++ himci_edge_tuning_enable(host); ++ ++ for (index = 0; index < HIMCI_PHASE_SCALE; index++) { ++ himci_set_sap_phase(host, index); ++ ++ mmc_send_tuning(mmc, opcode, NULL); ++ ++ himci_send_stop(mmc); ++ ++ val = himci_readl(host->base + MCI_TUNING_CTRL); ++ found = val & FOUND_EDGE; ++ ++ himci_trace(3, "try phase:%02d, found:0x%x\n", index, found); ++ ++ if (prev_found && !found) { ++ end_point = prev_point; ++ } else if (!prev_found && found) { ++ if (index != 0) ++ start_point = index; ++ } ++ if ((start_point != NOT_FOUND) && (end_point != NOT_FOUND)) ++ goto scan_out; ++ ++ prev_point = index; ++ prev_found = found; ++ found = 0; ++ } ++ ++scan_out: ++ if ((start_point == NOT_FOUND) && (end_point == NOT_FOUND)) { ++ himci_trace(5, "%s: no valid phase shift! use default", ++ mmc_hostname(mmc)); ++ return 0; ++ } ++ ++ if (start_point == NOT_FOUND) ++ start_point = end_point; ++ ++ if (end_point == NOT_FOUND) ++ end_point = start_point; ++ ++ pr_info("tuning %s: found edge on (s:%d, e:%d)", ++ mmc_hostname(mmc), start_point, end_point); ++ ++ if (start_point > end_point) ++ end_point += HIMCI_PHASE_SCALE; ++ ++ phase = ((start_point + end_point) / 2) % HIMCI_PHASE_SCALE; ++ ++ phase += HIMCI_PHASE_SCALE / 2; ++ phase %= HIMCI_PHASE_SCALE; ++ ++ himci_set_sap_phase(host, phase); ++ ++ himci_edge_tuning_disable(host); ++ ++ himci_writel(ALL_INT_CLR, host->base + MCI_RINTSTS); ++ ++ pr_info("determing final phase %d\n", phase); ++ ++ return 0; ++} ++#else ++#if defined(CONFIG_ARCH_HI3519V101) || defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) || \ ++ defined(CONFIG_ARCH_HI3516AV200) ++static int himci_set_sd_drv_strength(struct mmc_host *mmc, ++ unsigned int drv_type) ++{ ++ struct mmc_request mrq = {NULL}; ++ struct mmc_command cmd = {0}; ++ struct mmc_data data = {0}; ++ struct scatterlist sg; ++ u8 *status; ++ ++ status = kmalloc(64, GFP_KERNEL); ++ if (!status) ++ return -ENOMEM; ++ ++ drv_type &= 0xF; ++ ++ mrq.cmd = &cmd; ++ mrq.data = &data; ++ ++ cmd.opcode = SD_SWITCH; ++ cmd.arg = 0x1 << 31 | 0x00FFFFFF; ++ cmd.arg &= ~(0xF << 8); ++ cmd.arg |= drv_type << 8; ++ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; ++ ++ data.blksz = 64; ++ data.blocks = 1; ++ data.flags = MMC_DATA_READ; ++ data.sg = &sg; ++ data.sg_len = 1; ++ ++ sg_init_one(&sg, status, 64); ++ ++ mmc_wait_for_req(mmc, &mrq); ++ ++ kfree(status); ++ if (cmd.error) ++ return cmd.error; ++ if (data.error) ++ return data.error; ++ ++ return 0; ++} ++ ++static int himci_set_mmc_drv_strength(struct mmc_host *mmc, ++ unsigned int drv_type) ++{ ++ int err; ++ struct mmc_command cmd = {0}; ++ unsigned int value; ++ ++ drv_type &= 0xF; ++ value = EXT_CSD_TIMING_HS200 | (drv_type << 4); ++ ++ cmd.opcode = MMC_SWITCH; ++ cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | ++ (EXT_CSD_HS_TIMING << 16) | ++ (value << 8) | ++ EXT_CSD_CMD_SET_NORMAL; ++ cmd.flags = MMC_CMD_AC | MMC_RSP_SPI_R1B | MMC_RSP_R1B; ++ ++ err = mmc_wait_for_cmd(mmc, &cmd, 0); ++ ++ return err; ++} ++#endif ++static void himci_set_sap_phase(struct himci_host *host, ++ u32 phase, u32 hs400_tuning) ++{ ++ unsigned int reg_value; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&host->lock, flags); ++ if (hs400_tuning) { ++ phase = (phase < 8) ? (8 - phase) : phase; ++ reg_value = himci_readl(EMMC_DLL_CTRL); ++ reg_value &= ~0xF; ++ reg_value |= phase; ++ himci_writel(reg_value, EMMC_DLL_CTRL); ++ host->dll_phase = phase; ++ } else { ++ reg_value = himci_readl(host->base + MCI_UHS_REG_EXT); ++ reg_value &= ~CLK_SMPL_PHS_MASK; ++ reg_value |= (phase << CLK_SMPL_PHS_SHIFT); ++ himci_writel(reg_value, host->base + MCI_UHS_REG_EXT); ++ host->phase = phase; ++ } ++ spin_unlock_irqrestore(&host->lock, flags); ++} ++ ++/* ++ * 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 himci_execute_tuning(struct mmc_host *mmc, u32 opcode) ++{ ++ struct himci_host *host; ++ unsigned int index, count; ++ unsigned int err = 0; ++ unsigned int found = 0; /* identify if we have found a valid phase */ ++ 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; ++ unsigned int hs400_tuning; ++ int phase, ret, send_cmd_num = 1; ++#if defined(CONFIG_ARCH_HI3519V101) || defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) || \ ++ defined(CONFIG_ARCH_HI3516AV200) ++ int retry = 0; ++#endif ++ ++ if (opcode == MMC_SEND_EXT_CSD) { ++ start_point = HS400_TUNING_START_PHASE; ++ end_point = HS400_TUNING_END_PHASE; ++ hs400_tuning = 1; ++ } else { ++ start_point = TUNING_START_PHASE; ++ end_point = TUNING_END_PHASE; ++ hs400_tuning = 0; ++ } ++ ++ host = mmc_priv(mmc); ++ ++ himci_trace(3, "start sd3.0 phase tuning..."); ++ ++#if defined(CONFIG_ARCH_HI3519V101) || defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) || \ ++ defined(CONFIG_ARCH_HI3516AV200) ++ if (!hs400_tuning && (mmc->caps & MMC_CAP_UHS_SDR104)) ++ himci_set_sd_drv_strength(mmc, SD_STRENGTH_TYPE_C); ++try_again: ++#endif ++ ++ for (index = start_point; index <= end_point; index++) { ++ /* set sample clk phase shift */ ++ himci_set_sap_phase(host, index, hs400_tuning); ++ ++ count = 0; ++ do { ++ if (hs400_tuning) { ++ ret = mmc_send_dll_tuning(mmc); ++ } else { ++ ret = mmc_send_tuning(mmc, opcode, NULL); ++ himci_send_stop(mmc); /* send soft_stop tail */ ++ } ++ ++ if (ret) { ++ himci_trace(3, "send tuning CMD%u fail! phase:%d err:%d\n", ++ opcode, index, ret); ++ err = 1; ++ break; ++ } ++ count++; ++ } while (count < send_cmd_num); ++ ++ if (!err) ++ found = 1; /* found a valid phase */ ++ ++ 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; ++ } ++ ++#if defined(CONFIG_ARCH_HI3519V101) || defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) || \ ++ defined(CONFIG_ARCH_HI3516AV200) ++ if ((NOT_FOUND == raise_point) && (NOT_FOUND == fall_point) ++ && !hs400_tuning && !retry) { ++ if (mmc->caps & MMC_CAP_UHS_SDR104) ++ himci_set_sd_drv_strength(mmc, SD_STRENGTH_TYPE_D); ++ else if (mmc->caps2 & MMC_CAP2_HS200) ++ himci_set_mmc_drv_strength(mmc, MMC_STRENGTH_TYPE_3); ++ ++ prev_err = NOT_FOUND; ++ send_cmd_num = 40; ++ retry = 1; ++ goto try_again; ++ } ++#endif ++ ++tuning_out: ++ if (!found) { ++ himci_trace(5, "%s: no valid phase shift! use default", ++ mmc_hostname(mmc)); ++ if (!hs400_tuning) ++ himci_set_sap_phase(host, DEFAULT_SMPL_PHASE, hs400_tuning); ++ } else { ++ himci_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) { ++#ifdef CONFIG_ARCH_HI3519 ++ if (fall_point - start_point > end_point - raise_point) ++ phase = (fall_point + start_point) / 2; ++ else ++ phase = (end_point + raise_point) / 2; ++#else ++ phase = (raise_point + fall_point) / 2; ++ phase = phase - (HIMCI_PHASE_SCALE / 2); ++ phase = (phase < 0) ? (HIMCI_PHASE_SCALE + phase) : phase; ++#endif ++ } else ++ phase = (raise_point + fall_point) / 2; ++ ++ himci_set_sap_phase(host, phase, hs400_tuning); ++ ++ pr_info("%stuning %s: valid phase shift [%d, %d] Final Phase %d\n", ++ hs400_tuning ? "HS400 " : "", mmc_hostname(mmc), ++ raise_point, fall_point, phase); ++ } ++ ++#if defined(CONFIG_ARCH_HI3519V101) || defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) || \ ++ defined(CONFIG_ARCH_HI3516AV200) ++ if (retry) { ++ if (mmc->caps & MMC_CAP_UHS_SDR104) ++ himci_set_sd_drv_strength(mmc, SD_STRENGTH_TYPE_C); ++ else if (mmc->caps2 & MMC_CAP2_HS200) ++ himci_set_mmc_drv_strength(mmc, MMC_STRENGTH_TYPE_0); ++ } ++#endif ++ return 0; ++} ++#endif ++ ++static void himci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct himci_host *host = mmc_priv(mmc); ++ unsigned int tmp_reg; ++ unsigned int port = host->cur_port; ++ u32 ctrl = 0; ++ ++ himci_trace(2, "begin"); ++ himci_assert(mmc); ++ himci_assert(ios); ++ himci_assert(host); ++ ++ himci_trace(3, "ios->power_mode = %d ", ios->power_mode); ++ if (!ios->clock) ++ himci_control_cclk(host, DISABLE); ++ ++ switch (ios->power_mode) { ++ case MMC_POWER_OFF: ++ himci_ctrl_power(host, POWER_OFF, FORCE_DISABLE); ++ break; ++ case MMC_POWER_UP: ++ case MMC_POWER_ON: ++ himci_ctrl_power(host, POWER_ON, FORCE_DISABLE); ++ break; ++ } ++ himci_trace(3, "ios->clock = %d ", ios->clock); ++ if (ios->clock) { ++ himci_control_cclk(host, DISABLE); ++ himci_set_cclk(host, ios->clock); ++ himci_control_cclk(host, ENABLE); ++ ++ /* speed mode check ,if it is DDR50 set DDR mode */ ++ if (ios->timing == MMC_TIMING_UHS_DDR50) { ++ ctrl = himci_readl(host->base + MCI_UHS_REG); ++ if (!((HI_SDXC_CTRL_DDR_REG << port) & ctrl)) { ++ ctrl |= (HI_SDXC_CTRL_DDR_REG << port); ++ himci_writel(ctrl, host->base + MCI_UHS_REG); ++ } ++ } ++ ++ if (ios->timing == MMC_TIMING_MMC_HS400) { ++ ctrl = himci_readl(host->base + MCI_EMMC_DDR_REG); ++ if (!(HI_EMMC_HS400_MODE & ctrl)) { ++ ctrl |= HI_EMMC_HS400_MODE; ++ himci_writel(ctrl, ++ host->base + MCI_EMMC_DDR_REG); ++ } ++ } ++ } else { ++ himci_control_cclk(host, DISABLE); ++ if (ios->timing != MMC_TIMING_UHS_DDR50) { ++ ctrl = himci_readl(host->base + MCI_UHS_REG); ++ if ((HI_SDXC_CTRL_DDR_REG << port) & ctrl) { ++ ctrl &= ~(HI_SDXC_CTRL_DDR_REG << port); ++ himci_writel(ctrl, host->base + MCI_UHS_REG); ++ } ++ } ++ ++ if (ios->timing != MMC_TIMING_MMC_HS400) { ++ ctrl = himci_readl(host->base + MCI_EMMC_DDR_REG); ++ if (HI_EMMC_HS400_MODE & ctrl) { ++ ctrl &= ~HI_EMMC_HS400_MODE; ++ himci_writel(ctrl, ++ host->base + MCI_EMMC_DDR_REG); ++ } ++ } ++ } ++ ++ himci_set_drv_cap(host, ios); ++ ++ /* set bus_width */ ++ himci_trace(3, "ios->bus_width = %d ", ios->bus_width); ++ ++ /* clear bus width to 1bit first */ ++ tmp_reg = himci_readl(host->base + MCI_CTYPE); ++ tmp_reg &= ~((CARD_WIDTH_0 | CARD_WIDTH_1) << port); ++ ++ if (ios->bus_width == MMC_BUS_WIDTH_8) { ++ tmp_reg |= (CARD_WIDTH_0 << port); ++ himci_writel(tmp_reg, host->base + MCI_CTYPE); ++ } else if (ios->bus_width == MMC_BUS_WIDTH_4) { ++ tmp_reg |= (CARD_WIDTH_1 << port); ++ himci_writel(tmp_reg, host->base + MCI_CTYPE); ++ } else { ++ himci_writel(tmp_reg, host->base + MCI_CTYPE); ++ } ++} ++ ++static void himci_enable_sdio_irq(struct mmc_host *mmc, int enable) ++{ ++ struct himci_host *host = mmc_priv(mmc); ++ unsigned int reg_value; ++ ++ reg_value = himci_readl(host->base + MCI_INTMASK); ++ if (enable) ++ reg_value |= SDIO_INT_MASK; ++ else ++ reg_value &= ~SDIO_INT_MASK; ++ himci_writel(reg_value, host->base + MCI_INTMASK); ++} ++ ++static int himci_get_card_detect(struct mmc_host *mmc) ++{ ++ unsigned ret; ++ struct himci_host *host = mmc_priv(mmc); ++ ++ himci_trace(2, "begin"); ++ ret = himci_sys_card_detect(host); ++ ++ if (ret) ++ return 0; ++ else ++ return 1; ++} ++ ++static int himci_get_ro(struct mmc_host *mmc) ++{ ++ unsigned ret; ++ struct himci_host *host = mmc_priv(mmc); ++ ++ himci_trace(2, "begin"); ++ himci_assert(mmc); ++ ++ ret = himci_ctrl_card_readonly(host); ++ ++ return ret; ++} ++ ++static unsigned int himci_get_rdptr(struct mmc_host *mmc) ++{ ++ unsigned int cur; ++ struct himci_host *host = mmc_priv(mmc); ++ ++ himci_trace(2, "begin"); ++ himci_assert(mmc); ++ ++ cur = himci_readl(host->base + ADMA_Q_RDPTR); ++ ++ return cur; ++} ++ ++static void himci_hw_reset(struct mmc_host *mmc) ++{ ++ unsigned int reg_value; ++ struct himci_host *host = mmc_priv(mmc); ++ unsigned int port = host->cur_port; ++ ++ reg_value = himci_readl(host->base + MCI_RESET_N); ++ reg_value &= ~(MMC_RST_N << port); ++ himci_writel(reg_value, host->base + MCI_RESET_N); ++ /* For eMMC, minimum is 1us but give it 10us for good measure */ ++ udelay(10); ++ reg_value = himci_readl(host->base + MCI_RESET_N); ++ reg_value |= (MMC_RST_N << port); ++ himci_writel(reg_value, host->base + MCI_RESET_N); ++ /* For eMMC, minimum is 200us but give it 300us for good measure */ ++ usleep_range(300, 1000); ++} ++ ++static int himci_select_drv_strength(unsigned int max_dtr, ++ int host_drv, int card_drv) ++{ ++ if ((host_drv & SD_DRIVER_TYPE_C) && ++ (card_drv & SD_DRIVER_TYPE_C)) ++ return SD_STRENGTH_TYPE_C; ++ else ++ return SD_STRENGTH_TYPE_B; ++} ++ ++static int himci_card_info_save(struct mmc_host *mmc) ++{ ++ struct mmc_card *card = mmc->card; ++ struct himci_host * host= mmc_priv(mmc); ++ struct card_info * c_info = &host->c_info; ++ ++ if (!card) { ++ memset(c_info,0,sizeof(struct card_info)); ++ c_info->card_connect = CARD_DISCONNECT; ++ goto out; ++ } ++ ++ c_info->card_type = card->type; ++ c_info->card_state = card->state; ++ ++ c_info->timing = mmc->ios.timing; ++ c_info->card_support_clock = mmc->ios.clock; ++ ++ c_info->sd_bus_speed = card->sd_bus_speed; ++ ++ memcpy(c_info->ssr, card->c_ssr, ARRAY_SIZE(c_info->ssr)); ++ ++ c_info->card_connect = CARD_CONNECT; ++out: ++ return 0; ++} ++ ++static const struct mmc_host_ops himci_ops = { ++ .request = himci_request, ++ .post_req = himci_data_done, ++ .set_ios = himci_set_ios, ++ .get_rd = himci_get_rdptr, ++ .get_ro = himci_get_ro, ++ .start_signal_voltage_switch = himci_start_signal_voltage_switch, ++#if defined(CONFIG_ARCH_HI3516CV300) ++ .execute_tuning = himci_execute_edge_tuning, ++#else ++ .execute_tuning = himci_execute_tuning, ++#endif ++ .enable_sdio_irq = himci_enable_sdio_irq, ++ .select_drive_strength = himci_select_drv_strength, ++ .hw_reset = himci_hw_reset, ++ .sw_reset = himci_sw_reset, ++ .get_cd = himci_get_card_detect, ++ .card_info_save = himci_card_info_save, ++}; ++ ++static void himci_check_sdio_irq(struct himci_host *host, unsigned int rstat) ++{ ++ u32 mstate; ++ ++ if ((host->mmc->card != NULL) ++ && (host->mmc->card->type == MMC_TYPE_SDIO)) { ++ mstate = himci_readl(host->base + MCI_INTMASK); ++ if ((rstat & SDIO_INT_STATUS) && (mstate & SDIO_INT_MASK)) { ++ spin_lock(&host->lock); ++ himci_writel(SDIO_INT_STATUS, ++ host->base + MCI_RINTSTS); ++ spin_unlock(&host->lock); ++ mmc_signal_sdio_irq(host->mmc); ++ } ++ } ++} ++ ++static unsigned int himci_get_stable_rd_pos(struct himci_host *host, ++ unsigned int qstat, unsigned int rstat) ++{ ++ unsigned int rd_pos; ++ unsigned int fsm_stat; ++ volatile unsigned int new_pos; ++ volatile unsigned int new_fsm; ++ unsigned int count = 0; ++ int try = 1000; ++ ++ rd_pos = himci_readl(host->base + ADMA_Q_RDPTR); ++ fsm_stat = himci_readl(host->base + MCI_IDSTS); ++ while (try > 0) { ++ new_pos = himci_readl(host->base + ADMA_Q_RDPTR); ++ new_fsm = himci_readl(host->base + MCI_IDSTS); ++ if ((rd_pos == new_pos) && (fsm_stat == new_fsm)) { ++ count++; ++ } else { ++ rd_pos = new_pos; ++ fsm_stat = new_fsm; ++ count = 0; ++ } ++ ++ if (count == 3) ++ break; ++ try--; ++ } ++ ++ /* when error occur, whether the read ptr jump next is depend on ++ * host's state machine when CES && ADMA3_FSM=4 && FSM!=0, ++ *rdptr don't jump next ++ */ ++ if (!(qstat & PACKET_TO_INT)) { ++ if (!((qstat & CES) && ++ (((fsm_stat >> ADMA3_FSM_SHIFT) & 0xF) == 4) && ++ ((fsm_stat >> FSM_SHIFT) & 0xF))) ++ rd_pos = rd_pos ? (rd_pos - 1) ++ : (ADMA_QUEUE_DEEPTH - 1); ++ } ++ ++ return rd_pos; ++} ++ ++static irqreturn_t hisd_irq(int irq, void *dev_id) ++{ ++ struct himci_host *host = dev_id; ++ struct mmc_request *mrq; ++ u32 rd_pos = 0; ++ u32 rstat = 0; ++ u32 qstat = 0; ++ int cmd_err = 0; ++ int data_err = 0; ++ ++ rstat = himci_readl(host->base + MCI_RINTSTS); /* read RAW intr */ ++ qstat = himci_readl(host->base + MCI_IDSTS); /* clear ADMA3 intr */ ++ himci_writel(qstat, host->base + MCI_IDSTS); ++ himci_trace(3, "queue state:0x%x raw state:0x%x", qstat, rstat); ++ ++ if (!(qstat & ADMA_INT_ALL) && !(rstat & SDIO_INT_STATUS)) { ++ himci_trace(5, "##### no irq, should never be here! ######"); ++ return IRQ_NONE; ++ } ++ ++ /* bugfix: when send soft stop to SD Card, Host will report ++ sdio interrupt, This situation needs to be avoided */ ++ if (host->mmc->caps & MMC_CAP_SDIO_IRQ) ++ himci_check_sdio_irq(host, rstat); ++ ++ rd_pos = himci_get_stable_rd_pos(host, qstat, rstat); ++ ++ mrq = host->pmrq[rd_pos]; ++ himci_err_check(host, qstat, rstat, &cmd_err, &data_err); ++ ++ host->pmrq[rd_pos] = NULL; ++ if (!mrq || !mrq->cmd) { ++ himci_trace(4, "##################"); ++ himci_trace(4, "queue state:0x%x raw state:0x%x", qstat, rstat); ++ himci_trace(4, "current rd:%d", rd_pos); ++ return IRQ_HANDLED; ++ } ++ ++ if (cmd_err || data_err) { ++ if (mrq->cmd->flags & MMC_CMD_TYPE_RW) { ++ himci_trace(5, "R/W CMD%u error, qstat:0x%x rstat:0x%x", ++ mrq->cmd->opcode, qstat, rstat); ++ host->error_count++; ++ host->mmc->status = MMC_HOST_ERR; ++ } ++ mrq->cmd->error = cmd_err; ++ if (mrq->data) ++ mrq->data->error = data_err; ++ } ++ ++ /* finish each mrq */ ++ if (mrq->cmd->flags & MMC_CMD_TYPE_RW) { ++ himci_read_response(host, mrq->cmd); ++ mmc_request_done(host->mmc, mrq); ++ } else { ++ host->cmd_done = 1; ++ wake_up(&host->intr_wait); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static int himci_of_parse(struct device_node *np, struct mmc_host *mmc) ++{ ++ struct himci_host *host = mmc_priv(mmc); ++ int ret = mmc_of_parse(mmc); ++ int len; ++ ++ if (ret) ++ return ret; ++ ++ if (of_property_read_u32(np, "min-frequency", &mmc->f_min)) ++ mmc->f_min = MMC_CCLK_MIN; ++ ++ if (of_property_read_u32(np, "devid", &host->devid)) ++ return -EINVAL; ++ ++ if (of_find_property(np, "cap-mmc-hw-reset", &len)) ++ mmc->caps |= MMC_CAP_HW_RESET; ++ ++ return 0; ++} ++ ++static int __init himci_probe(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc; ++ struct himci_host *host = NULL; ++ struct resource *host_ioaddr_res = NULL; ++ int ret = 0, irq; ++ struct device_node *np = pdev->dev.of_node; ++ ++ himci_trace(2, "begin"); ++ pr_info("mmc host probe\n"); ++ himci_assert(pdev); ++ ++ mmc = mmc_alloc_host(sizeof(struct himci_host), &pdev->dev); ++ if (!mmc) { ++ himci_error("no mem for hi mci host controller!\n"); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ platform_set_drvdata(pdev, mmc); ++ ++ mmc->ops = &himci_ops; ++ ++ host_ioaddr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (NULL == host_ioaddr_res) { ++ himci_error("no ioaddr rescources config!\n"); ++ ret = -ENODEV; ++ goto out; ++ } ++ ++ if (himci_of_parse(np, mmc)) { ++ himci_error("failed to parse mmc dts!\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* reload by this controller */ ++ mmc->max_blk_count = 2048; ++ mmc->max_segs = MAX_SEGS; ++ 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->status = MMC_HOST_OK; ++ ++ host = mmc_priv(mmc); ++ mci_host[slot_index++] = host; ++ pdev->id = host->devid; ++ host->pdev = pdev; ++ host->mmc = mmc; ++ ++ /* ADMA3 buffer alloc */ ++ host->entire_addr = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, ++ &host->entire_paddr, GFP_KERNEL); ++ if (!host->entire_addr) { ++ himci_error("no mem for himci dma!\n"); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ host->cmd_addr = dma_alloc_coherent(&pdev->dev, ++ PERF_OPT_RATIO * PAGE_SIZE * ADMA_QUEUE_DEEPTH, ++ &host->cmd_paddr, GFP_KERNEL); ++ if (!host->cmd_addr) { ++ himci_error("no mem for himci dma!\n"); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ host->base = devm_ioremap_resource(&pdev->dev, host_ioaddr_res); ++ if (IS_ERR_OR_NULL(host->base)) { ++ himci_error("no mem for himci base!\n"); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ spin_lock_init(&host->lock); ++ ++ host->clk = devm_clk_get(&pdev->dev, "mmc_clk"); ++ if (IS_ERR_OR_NULL(host->clk)) { ++ himci_error("get clock fail.\n"); ++ ret = PTR_ERR(host->clk); ++ goto out; ++ } ++ ++ clk_prepare_enable(host->clk); ++ ++ host->power_status = POWER_OFF; ++ host->cur_port = 0; ++ ++ /* enable card */ ++ himci_init_host(host); ++ host->card_status = himci_sys_card_detect(host); ++ ++ if (mmc->caps & MMC_CAP_SD_HIGHSPEED) { ++ init_timer(&host->timer); ++ host->timer.function = himci_detect_card; ++ host->timer.data = (unsigned long)host; ++ host->timer.expires = jiffies + detect_time; ++ add_timer(&host->timer); ++ } ++ ++ host->cmd_done = 0; ++ init_waitqueue_head(&host->intr_wait); ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ goto out; ++ ++ host->irq = irq; ++ ret = request_irq(irq, hisd_irq, 0, DRIVER_NAME, host); ++ if (ret) ++ goto out; ++ ++ mmc_add_host(mmc); ++ return 0; ++out: ++ if (host) { ++ if (mmc->caps & MMC_CAP_SD_HIGHSPEED) ++ del_timer(&host->timer); ++ ++ if (host->base) ++ devm_iounmap(&pdev->dev, host->base); ++ ++ if (host->entire_addr) ++ dma_free_coherent(&pdev->dev, PAGE_SIZE, ++ host->entire_addr, host->entire_paddr); ++ if (host->cmd_addr) ++ dma_free_coherent(&pdev->dev, ++ PERF_OPT_RATIO * PAGE_SIZE * ADMA_QUEUE_DEEPTH, ++ host->cmd_addr, host->cmd_paddr); ++ } ++ if (mmc) ++ mmc_free_host(mmc); ++ return ret; ++} ++ ++static int __exit himci_remove(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc = platform_get_drvdata(pdev); ++ ++ himci_trace(2, "begin"); ++ himci_assert(pdev); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ if (mmc) { ++ struct himci_host *host = mmc_priv(mmc); ++ ++ mmc_remove_host(mmc); ++ free_irq(host->irq, host); ++ if (mmc->caps & MMC_CAP_SD_HIGHSPEED) ++ del_timer_sync(&host->timer); ++ himci_ctrl_power(host, POWER_OFF, FORCE_DISABLE); ++ himci_control_cclk(host, DISABLE); ++ devm_iounmap(&pdev->dev, host->base); ++ dma_free_coherent(&pdev->dev, PAGE_SIZE, ++ host->entire_addr, host->entire_paddr); ++ dma_free_coherent(&pdev->dev, ++ PERF_OPT_RATIO * PAGE_SIZE * ADMA_QUEUE_DEEPTH, ++ host->cmd_addr, host->cmd_paddr); ++ mmc_free_host(mmc); ++ } ++ return 0; ++} ++ ++static void himci_shutdown(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc = platform_get_drvdata(pdev); ++ ++ himci_trace(3, "shutdown"); ++ if (mmc) { ++ unsigned int val; ++ struct himci_host *host = mmc_priv(mmc); ++ ++ /* bugfix: host reset can trigger error intr */ ++ himci_writel(0, host->base + MCI_IDINTEN); ++ himci_writel(0, host->base + MCI_INTMASK); ++ ++ val = himci_readl(host->base + MCI_CTRL); ++ val |= CTRL_RESET | FIFO_RESET | DMA_RESET; ++ himci_writel(val, host->base + MCI_CTRL); ++ ++ himciv200_host_power(host, POWER_OFF, FORCE_DISABLE); ++ } ++} ++ ++#ifdef CONFIG_PM ++static int himciv200_pltm_suspend(struct platform_device *pdev, ++ pm_message_t state) ++{ ++ struct mmc_host *mmc = platform_get_drvdata(pdev); ++ struct himci_host *host; ++ int ret = 0; ++ ++ if (mmc) { ++ host = mmc_priv(mmc); ++ if (mmc->caps & MMC_CAP_SD_HIGHSPEED) ++ del_timer_sync(&host->timer); ++ ++ if (__clk_is_enabled(host->clk)) ++ clk_disable_unprepare(host->clk); ++ } ++ ++ return ret; ++} ++/******************************************************************************/ ++ ++static int himciv200_pltm_resume(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc = platform_get_drvdata(pdev); ++ struct himci_host *host; ++ int ret = 0; ++ ++ if (mmc) { ++ host = mmc_priv(mmc); ++ ++ if (!__clk_is_enabled(host->clk)) ++ clk_prepare_enable(host->clk); ++ ++ himci_init_host(host); ++ ++ if (mmc->caps & MMC_CAP_SD_HIGHSPEED) ++ add_timer(&host->timer); ++ } ++ ++ return ret; ++} ++#else ++#define himciv200_pltm_suspend NULL ++#define himciv200_pltm_resume NULL ++#endif ++ ++void himci_mmc_rescan(int slot) ++{ ++ struct mmc_host *mmc; ++ struct himci_host *host; ++ ++ host = mci_host[slot]; ++ if (!host || !host->mmc) { ++ himci_trace(5, "mmc%d: invalid slot!\n", slot); ++ return; ++ } ++ ++ mmc = host->mmc; ++ if (mmc->caps & MMC_CAP_SD_HIGHSPEED) ++ del_timer_sync(&host->timer); ++ ++ mmc_remove_host(mmc); ++ ++ mmc_add_host(mmc); ++ ++ if (mmc->caps & MMC_CAP_SD_HIGHSPEED) ++ add_timer(&host->timer); ++} ++EXPORT_SYMBOL(himci_mmc_rescan); ++ ++static const struct of_device_id ++himciv200_match[] __maybe_unused = { ++ {.compatible = "hisilicon,hi3516cv300-himciv200"}, ++ {.compatible = "hisilicon,hi3519-himciv200"}, ++ {.compatible = "hisilicon,hi3516av200-himciv200"}, ++ {.compatible = "hisilicon,hi3559-himciv200"}, ++ {.compatible = "hisilicon,hi3556-himciv200"}, ++ {}, ++}; ++ ++static struct platform_driver himci_driver = { ++ .probe = himci_probe, ++ .remove = himci_remove, ++ .shutdown = himci_shutdown, ++ .suspend = himciv200_pltm_suspend, ++ .resume = himciv200_pltm_resume, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(himciv200_match), ++ }, ++}; ++ ++static int __init himci_init(void) ++{ ++ int ret; ++ ++ himci_trace(2, "begin"); ++ ++ /* ++ * We should register SDIO1 first to make sure that ++ * the eMMC device,which connected to SDIO1 is mmcblk0. ++ */ ++ ++ ret = platform_driver_register(&himci_driver); ++ if (ret) { ++ platform_driver_unregister(&himci_driver); ++ himci_error("Himci driver register failed!"); ++ return ret; ++ } ++ ++ /* device proc entry */ ++ ret = mci_proc_init(HIMCI_SLOT_NUM); ++ if (ret) ++ himci_error("device proc init is failed!"); ++ ++ return ret; ++} ++ ++static void __exit himci_exit(void) ++{ ++ himci_trace(2, "begin"); ++ ++ mci_proc_shutdown(); ++ ++ platform_driver_unregister(&himci_driver); ++} ++ ++module_init(himci_init); ++module_exit(himci_exit); ++ ++#ifdef MODULE ++MODULE_AUTHOR("Hisilicon Drive Group"); ++MODULE_DESCRIPTION("MMC/SD driver for the Hisilicon MMC/SD Host Controller"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/mmc/host/himciv200/himci.h b/drivers/mmc/host/himciv200/himci.h +new file mode 100644 +index 0000000..7b78611 +--- /dev/null ++++ b/drivers/mmc/host/himciv200/himci.h +@@ -0,0 +1,192 @@ ++#ifndef _HI_MCI_H_ ++#define _HI_MCI_H_ ++ ++#include ++ ++extern int trace_level; ++#define HIMCI_TRACE_LEVEL 5 ++/* ++ 0 - all message ++ 1 - dump all register read/write ++ 2 - flow trace ++ 3 - timeouut err and protocol err ++ */ ++ ++#define HIMCI_TRACE_FMT KERN_INFO ++/* #define HIMCI_TRACE_FMT KERN_DEBUG */ ++ ++#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 SD_STRENGTH_TYPE_B 0 ++#define SD_STRENGTH_TYPE_C 2 ++#define SD_STRENGTH_TYPE_D 3 ++#define MMC_STRENGTH_TYPE_0 0 ++#define MMC_STRENGTH_TYPE_3 3 ++ ++#define HI_MCI_DETECT_TIMEOUT (HZ / 5) ++#define HI_MCI_REQUEST_TIMEOUT (5 * HZ) ++#define MAX_RETRY_COUNT 100 ++ ++#define MMC_CCLK_MIN 100000 ++ ++#define ADMA_QUEUE_DEEPTH (32) ++ ++/* Base address of SD card register */ ++#define HI_MCI_INTR (48+32) ++ ++#define himci_trace(level, msg...) do { \ ++ if ((level) >= trace_level) { \ ++ printk(HIMCI_TRACE_FMT "%s:%d: ", __func__, __LINE__); \ ++ printk(msg); \ ++ printk("\n"); \ ++ } \ ++} while (0) ++ ++#define himci_assert(cond) do { \ ++ if (!(cond)) {\ ++ printk(KERN_ERR "Assert:himci:%s:%d\n", \ ++ __func__, \ ++ __LINE__); \ ++ BUG(); \ ++ } \ ++} while (0) ++ ++#define himci_error(s...) do { \ ++ printk(KERN_ERR "himci:%s:%d: ", __func__, __LINE__); \ ++ printk(s); \ ++ printk("\n"); \ ++} while (0) ++ ++#define himci_readl(addr) ({unsigned int reg = hi_readl(IOMEM(addr)); \ ++ himci_trace(1, "readl(0x%04X) = 0x%08X", (unsigned int)addr, reg); \ ++ reg; }) ++ ++#define himci_writel(v, addr) do { hi_writel(v, IOMEM(addr)); \ ++ himci_trace(1, "writel(0x%04X) = 0x%08X", (unsigned int)addr, \ ++ (unsigned int)(v)); \ ++} while (0) ++ ++struct himci_queue_info { ++ unsigned long end; ++ unsigned long cur; ++ unsigned int status; ++}; ++ ++struct himci_entire_des { ++ unsigned long ctrl; ++ unsigned long cmd_des_addr; ++ unsigned long response; ++ unsigned long reserved; ++}; ++ ++struct himci_cmd_des { ++ unsigned long blk_sz; ++ unsigned long byte_cnt; ++ unsigned long arg; ++ unsigned long cmd; ++}; ++ ++struct himci_dma_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 card_info { ++ unsigned int card_type; ++ unsigned char timing; ++ unsigned char card_connect; ++#define CARD_CONNECT 1 ++#define CARD_DISCONNECT 0 ++ unsigned int card_support_clock; /* clock rate */ ++ unsigned int card_state; /* (our) card state */ ++ unsigned int sd_bus_speed; ++ unsigned int ssr[16]; ++}; ++ ++struct himci_host { ++ struct mmc_host *mmc; ++ struct platform_device *pdev; ++ spinlock_t lock; ++ struct mmc_request *mrq; ++ struct mmc_command *cmd; ++ struct mmc_data *data; ++ void __iomem *base; ++ void *sys_regmap; ++ struct scatterlist *dma_sg; ++ ++ dma_addr_t entire_paddr; ++ dma_addr_t cmd_paddr; ++ dma_addr_t dma_paddr; ++ unsigned int *entire_addr; ++ unsigned int *cmd_addr; ++ unsigned int *dma_addr; ++ unsigned int dma_sg_num; ++ struct himci_entire_des *wr_ent_des; ++ struct himci_cmd_des *wr_cmd_des; ++ /* save the pointer of send mrq */ ++ struct mmc_request *pmrq[ADMA_QUEUE_DEEPTH]; ++ struct timer_list timer; ++ wait_queue_head_t intr_wait; ++ unsigned int cmd_done; ++ unsigned int irq; ++ unsigned int irq_status; ++ unsigned int power_status; ++ unsigned int card_status; ++ unsigned int devid; ++ unsigned int cur_port; ++ unsigned int wr_pos; ++ unsigned int hclk; ++ unsigned int cclk; ++ unsigned int phase; ++ unsigned int dll_phase; ++ struct clk *clk; ++ unsigned int error_count; ++ struct card_info c_info; ++}; ++ ++union cmd_arg_u { ++ 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; ++}; ++ ++struct mmc_host *get_mmchost(int hostid); ++#endif +diff --git a/drivers/mmc/host/himciv200/himci_acl.c b/drivers/mmc/host/himciv200/himci_acl.c +new file mode 100644 +index 0000000..43e8b43 +--- /dev/null ++++ b/drivers/mmc/host/himciv200/himci_acl.c +@@ -0,0 +1,139 @@ ++/****************************************************************************** ++ * Copyright (C) 2014 Hisilicon STB Development Dept ++ * All rights reserved. ++ * *** ++ * Create by Czyong ++ * ++******************************************************************************/ ++#define pr_fmt(fmt) "mmcacl: " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct part_t { ++ u32 start; ++ u32 end; ++ int part; ++}; ++ ++static int mmcacl_devid = -1; ++extern char *get_blkdevparts(void); ++ ++static struct part_t ro_parts[64]; ++static int nr_ro_parts; ++ ++static int mmcadd_part(int slot, struct cmdline_subpart *subpart, void *param) ++{ ++ u32 start = (u32)(subpart->from >> 9); ++ u32 end = start + (u32)(subpart->size >> 9); ++ struct part_t *part = (struct part_t *)param; ++ ++ if (subpart->flags & PF_RDONLY) { ++ if (nr_ro_parts < 64) { ++ part[nr_ro_parts].start = start; ++ part[nr_ro_parts].end = end; ++ part[nr_ro_parts].part = slot; ++ nr_ro_parts++; ++ } else { ++ pr_err("too many ro partition. please increase ro_parts\n"); ++ } ++ } ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int mmcpart_part(char *cmdline) ++{ ++ struct cmdline_parts *bdev_parts = NULL; ++ ++ if (cmdline_parts_parse(&bdev_parts, cmdline)) ++ return -1; ++ ++ cmdline_parts_set(bdev_parts, (sector_t)0x1000000000ULL, 0, mmcadd_part, ++ (void *)ro_parts); ++ ++ cmdline_parts_free(&bdev_parts); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++int himci_acl_init(int devid) ++{ ++ char *cmdline = NULL; ++ ++ if (mmcacl_devid != -1) ++ return 0; ++ ++ mmcacl_devid = devid; ++ ++ cmdline = get_blkdevparts(); ++ if (!cmdline) ++ return 0; ++ ++ mmcpart_part(cmdline); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++struct part_t *part_find(struct part_t *part, ++ u32 nr_part, u32 ofblk, u32 endblk) ++{ ++ u32 min = 0; ++ u32 max = nr_part; ++ u32 pos = (min + max) >> 1; ++ ++ do { ++ if (endblk <= part[pos].start) { ++ max = pos; ++ goto next; ++ } ++ ++ if (part[pos].end <= ofblk) { ++ min = pos; ++ goto next; ++ } ++ ++ break; ++next: ++ pos = (min + max) >> 1; ++ } while (pos != min && pos != max); ++ ++ return (endblk <= part[pos].start || part[pos].end <= ofblk) ? ++ NULL : &part[pos]; ++} ++/*****************************************************************************/ ++ ++int himci_acl_rw(int devid, int is_write, u32 ofblk, u32 nrblk) ++{ ++ struct part_t *part; ++ ++ if (mmcacl_devid != devid) ++ return 0; ++ ++ if (!is_write) ++ return 0; ++ ++ if (!nr_ro_parts) ++ return 0; ++ ++ part = part_find(ro_parts, nr_ro_parts, ofblk, ofblk + nrblk); ++ if (part) { ++ pr_warn("attempt to write ro area, offset:0x%08x, count:0x%08x.\n", ++ ofblk, nrblk); ++ return 1; ++ } ++ ++ return 0; ++} +diff --git a/drivers/mmc/host/himciv200/himci_acl.h b/drivers/mmc/host/himciv200/himci_acl.h +new file mode 100644 +index 0000000..fee8229 +--- /dev/null ++++ b/drivers/mmc/host/himciv200/himci_acl.h +@@ -0,0 +1,15 @@ ++/****************************************************************************** ++ * Copyright (C) 2014 Hisilicon STB Development Dept ++ * All rights reserved. ++ * *** ++ * Create by Czyong ++ * ++******************************************************************************/ ++#ifndef HIMCI_ACL_H ++#define HIMCI_ACL_H ++ ++int himci_acl_init(int devid); ++ ++int himci_acl_rw(int devid, int is_write, u32 ofblk, u32 nrblk); ++ ++#endif +diff --git a/drivers/mmc/host/himciv200/himci_dbg.c b/drivers/mmc/host/himciv200/himci_dbg.c +new file mode 100644 +index 0000000..8fb3f27 +--- /dev/null ++++ b/drivers/mmc/host/himciv200/himci_dbg.c +@@ -0,0 +1,662 @@ ++/****************************************************************************** ++ * Copyright (C) 2014 Hisilicon STB Development Dept ++ * All rights reserved. ++ * *** ++ * Create by Czyong ++ * ++******************************************************************************/ ++#define pr_fmt(fmt) "mmcdbg: " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MMC_MAX_BLK 0x2000000 /* 32M block, 16G size */ ++#define MMC_CHUNK_SIZE_SHIFT 11 /* 2K blocks, 1M size */ ++ ++#define MMC_CHUNK_SIZE (1 << MMC_CHUNK_SIZE_SHIFT) ++#define MMC_CHUNK_SIZE_MASK (MMC_CHUNK_SIZE - 1) ++#define MMC_NUM_CHUNK (MMC_MAX_BLK / MMC_CHUNK_SIZE) ++ ++#define NUM_PER_LINE 8 ++#define MAX_BUF ((NUM_PER_LINE + 1) * 9 + 24) ++#define MAX_PATH_LEN 260 ++ ++static DEFINE_MUTEX(mutex_rwcount); ++static DEFINE_MUTEX(mutex_notice); ++ ++static volatile unsigned int *rw_chunk[2][MMC_NUM_CHUNK] = { {0}, {0} }; ++ ++#define GET_CHUNK(_rw, _ofblk) rw_chunk[_rw][(_ofblk) >> MMC_CHUNK_SIZE_SHIFT] ++ ++static char *mmcdbg_options_string; ++static char mmcdbg_helper[MAX_PATH_LEN] = {0}; ++static int mmcdbg_rcount_enable; ++static int mmcdbg_wcount_enable; ++static int mmcdbg_devid = -1; ++ ++struct fo_data_t { ++ int is_write; ++ unsigned int ofblk; ++ int state; ++}; ++/******************************************************************************/ ++ ++static int mmcdbg_rw_count(int is_write, unsigned int ofblk, unsigned int nrblk) ++{ ++ int ret = -1; ++ int rw = is_write ? 1 : 0; ++ ++ if (!nrblk) ++ return 0; ++ ++ if (ofblk + nrblk > MMC_MAX_BLK) { ++ pr_err("out of block count.\n"); ++ return -1; ++ } ++ ++ mutex_lock(&mutex_rwcount); ++ ++ while (nrblk-- > 0) { ++ volatile unsigned int *entry = GET_CHUNK(rw, ofblk); ++ ++ if (!entry) { ++ entry = vmalloc(MMC_CHUNK_SIZE << 2); ++ if (!entry) { ++ pr_err("out of memory.\n"); ++ goto fail; ++ } ++ memset((void *)entry, 0, MMC_CHUNK_SIZE << 2); ++ ++ GET_CHUNK(rw, ofblk) = entry; ++ } ++ entry[ofblk & MMC_CHUNK_SIZE_MASK]++; ++ ofblk++; ++ } ++ ret = 0; ++fail: ++ mutex_unlock(&mutex_rwcount); ++ ++ return ret; ++} ++/******************************************************************************/ ++ ++static int mmcdbg_rw_free(int is_write) ++{ ++ unsigned int blk; ++ int rw = is_write ? 1 : 0; ++ ++ mutex_lock(&mutex_rwcount); ++ ++ for (blk = 0; blk < MMC_MAX_BLK; blk += MMC_CHUNK_SIZE) { ++ volatile unsigned int *entry = GET_CHUNK(rw, blk); ++ ++ if (entry) { ++ GET_CHUNK(rw, blk) = NULL; ++ vfree((void *)entry); ++ } ++ } ++ ++ mutex_unlock(&mutex_rwcount); ++ ++ return 0; ++} ++/******************************************************************************/ ++ ++static void dump_line(unsigned int ofblk, unsigned int *value, char **buf, ++ unsigned int *sz_buf, int state) ++{ ++ int ret; ++ ++ if (state == 0 || state == 1) { ++ int ix; ++ unsigned int tmp[NUM_PER_LINE] = {0}; ++ unsigned int *v = (value == NULL ? tmp : value); ++ ++ ret = snprintf(*buf, *sz_buf, "%08x:", ofblk); ++ *buf += ret; ++ *sz_buf -= ret; ++ ++ for (ix = 0; ix < NUM_PER_LINE; ix++) { ++ ret = snprintf(*buf, *sz_buf, " %04x", v[ix]); ++ *buf += ret; ++ *sz_buf -= ret; ++ } ++ ++ } else if (state == 2) { ++ ret = snprintf(*buf, *sz_buf, "..."); ++ *buf += ret; ++ *sz_buf -= ret; ++ ++ } else if (state == 3) { ++ ret = snprintf(*buf, *sz_buf, "%08x:", ofblk); ++ *buf += ret; ++ *sz_buf -= ret; ++ ++ } ++ ++ ret = snprintf(*buf, *sz_buf, "\n"); ++ *buf += ret; ++ *sz_buf -= ret; ++} ++/******************************************************************************/ ++ ++static int mmcdbg_rw_dump_buf(int is_write, unsigned int *ofblk, char *buf, ++ unsigned int sz_buf, int *state) ++{ ++ char *pbuf = buf; ++ unsigned int index; ++ unsigned int blk = *ofblk; ++ int rw = is_write ? 1 : 0; ++ ++ if (*state == 3) ++ return 0; ++ ++ sz_buf--; /* for trailing end '\0' */ ++ ++ while (blk < MMC_MAX_BLK) { ++ unsigned int *entry = (unsigned int *)GET_CHUNK(rw, blk); ++ ++ if (!entry) { ++ if (sz_buf < MAX_BUF) ++ goto no_buf; ++ ++ if (*state == 0) { ++ /* XXXXXXX: 0000 0000 0000 0000 0000 0000 0000 0000 */ ++ *state = 1; ++ dump_line(blk, NULL, &pbuf, &sz_buf, *state); ++ } ++ ++ if (*state == 1) { ++ /* ... */ ++ *state = 2; ++ dump_line(blk, NULL, &pbuf, &sz_buf, *state); ++ } ++ ++ blk += MMC_CHUNK_SIZE; ++ continue; ++ } ++ ++ index = blk & MMC_CHUNK_SIZE_MASK; ++ blk = blk & ~MMC_CHUNK_SIZE_MASK; ++ ++ while (index < MMC_CHUNK_SIZE) { ++ int ix, ret; ++ ++ if (sz_buf < MAX_BUF) { ++ blk += index; ++ goto no_buf; ++ } ++ ++ ret = 0; ++ for (ix = 0; ix < NUM_PER_LINE; ix++) ++ ret |= entry[ix + index]; ++ ++ if (!ret) { ++ if (*state == 0) { ++ *state = 1; ++ dump_line(blk + index, NULL, &pbuf, ++ &sz_buf, *state); ++ } else if (*state == 1) { ++ *state = 2; ++ dump_line(blk + index, NULL, &pbuf, ++ &sz_buf, *state); ++ } ++ } else { ++ if (*state) ++ *state = 0; ++ ++ dump_line(blk + index, &entry[index], ++ &pbuf, &sz_buf, *state); ++ } ++ ++ index += NUM_PER_LINE; ++ } ++ ++ blk += MMC_CHUNK_SIZE; ++ } ++ ++ if (*state == 2) { ++ *state = 3; ++ dump_line(blk, NULL, &pbuf, &sz_buf, *state); ++ } ++ ++no_buf: ++ *ofblk = blk; ++ ++ pbuf[0] = '\0'; ++ ++ return pbuf - buf; ++} ++/******************************************************************************/ ++ ++static int mmcdbg_rw_notice(int is_write, u32 ofblk, u32 nrblk) ++{ ++ int retval = 0; ++ char *argv[2]; ++ struct kobj_uevent_env *env; ++ char *rwstr = is_write ? "write" : "read"; ++ ++ env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL); ++ if (!env) ++ return -ENOMEM; ++ ++ retval = add_uevent_var(env, "RW=%s", rwstr); ++ if (retval) ++ goto exit; ++ ++ retval = add_uevent_var(env, "OFFSET=0x%08x", ofblk); ++ if (retval) ++ goto exit; ++ ++ retval = add_uevent_var(env, "COUNT=0x%08x", nrblk); ++ if (retval) ++ goto exit; ++ ++ retval = add_uevent_var(env, "PID=%d", current->pid); ++ if (retval) ++ goto exit; ++ ++ retval = add_uevent_var(env, "COMM=%s", current->comm); ++ if (retval) ++ goto exit; ++ ++ argv[0] = mmcdbg_helper; ++ argv[1] = NULL; ++ ++ retval = add_uevent_var(env, "PATH=/sbin:/bin:/usr/sbin:/usr/bin"); ++ if (retval) ++ goto exit; ++ ++ retval = call_usermodehelper(argv[0], argv, ++ env->envp, UMH_WAIT_EXEC); ++exit: ++ kfree(env); ++ return retval; ++} ++/******************************************************************************/ ++ ++static ssize_t fo_dump_rwcount_read(struct file *filp, char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ int ret; ++ char buf[256] = {0}; ++ char __user *pusrbuf = buffer; ++ struct fo_data_t *data = (struct fo_data_t *)filp->private_data; ++ ++ if (*ppos == 2) ++ return 0; ++ ++ if (data->is_write && !mmcdbg_wcount_enable) { ++ *ppos = 2; ++ ++ ret = snprintf(buf, sizeof(buf), "mmc write count is disable.\n" ++ "input \"echo 1 > write\" to enable.\n"); ++ ++ if (copy_to_user(pusrbuf, buf, ret)) ++ return -EFAULT; ++ ++ pusrbuf += ret; ++ ++ return pusrbuf - buffer; ++ } ++ ++ if (!data->is_write && !mmcdbg_rcount_enable) { ++ *ppos = 2; ++ ++ ret = snprintf(buf, sizeof(buf), "mmc read count is disable.\n" ++ "input \"echo 1 > read\" to enable\n"); ++ ++ if (copy_to_user(pusrbuf, buf, ret)) ++ return -EFAULT; ++ ++ pusrbuf += ret; ++ ++ return pusrbuf - buffer; ++ } ++ ++ do { ++ if (count < sizeof(buf)) { ++ *ppos = 1; ++ break; ++ } ++ ++ mutex_lock(&mutex_rwcount); ++ ++ ret = mmcdbg_rw_dump_buf(data->is_write, &data->ofblk, buf, ++ sizeof(buf), &data->state); ++ ++ mutex_unlock(&mutex_rwcount); ++ ++ if (!ret) { ++ *ppos = 2; ++ break; ++ } ++ ++ if (copy_to_user(pusrbuf, buf, ret)) ++ return -EFAULT; ++ ++ pusrbuf += ret; ++ count -= ret; ++ ++ } while (ret); ++ ++ return pusrbuf - buffer; ++} ++/******************************************************************************/ ++ ++static ssize_t fo_dump_rwcount_write(struct file *filp, ++ const char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ char *enstr; ++ long enable = 0; ++ char buf[32] = {0}; ++ unsigned int sz_buf = sizeof(buf) - 1; ++ struct fo_data_t *data = (struct fo_data_t *)filp->private_data; ++ int rw = data->is_write ? 1 : 0; ++ ++ if (count < sz_buf) ++ sz_buf = count; ++ ++ if (copy_from_user(buf, buffer, sz_buf)) ++ return -EFAULT; ++ ++ buf[sz_buf] = '\0'; ++ if (kstrtol(buf, 0, &enable)) { ++ pr_err("input error :%s\n", buf); ++ enable = rw ? mmcdbg_wcount_enable : mmcdbg_rcount_enable; ++ } ++ ++ enstr = enable ? "enable" : "disable"; ++ ++ if (rw) { ++ if (enable != mmcdbg_wcount_enable) { ++ mmcdbg_wcount_enable = enable; ++ if (!mmcdbg_wcount_enable) ++ mmcdbg_rw_free(rw); ++ pr_info("%s write count.\n", enstr); ++ } ++ } else { ++ if (enable != mmcdbg_rcount_enable) { ++ mmcdbg_rcount_enable = enable; ++ if (!mmcdbg_rcount_enable) ++ mmcdbg_rw_free(rw); ++ pr_info("%s read count.\n", enstr); ++ } ++ } ++ ++ return count; ++} ++/******************************************************************************/ ++ ++static int fo_dump_rcount_open(struct inode *inode, struct file *file) ++{ ++ struct fo_data_t *data; ++ ++ data = vmalloc(sizeof(struct fo_data_t)); ++ if (!data) { ++ pr_err("out of memory.\n"); ++ return -ENOMEM; ++ } ++ ++ data->is_write = 0; ++ data->ofblk = 0; ++ data->state = 0; ++ ++ file->private_data = (void *)data; ++ ++ return 0; ++} ++/******************************************************************************/ ++ ++static int fo_dump_wcount_open(struct inode *inode, struct file *file) ++{ ++ struct fo_data_t *data; ++ ++ data = vmalloc(sizeof(struct fo_data_t)); ++ if (!data) { ++ pr_err("out of memory.\n"); ++ return -ENOMEM; ++ } ++ ++ data->is_write = 1; ++ data->ofblk = 0; ++ data->state = 0; ++ ++ file->private_data = (void *)data; ++ ++ return 0; ++} ++/******************************************************************************/ ++ ++static int fp_dump_rwcount_release(struct inode *inode, struct file *file) ++{ ++ struct fo_data_t *data = (struct fo_data_t *)file->private_data; ++ ++ if (data) ++ vfree(data); ++ ++ file->private_data = NULL; ++ ++ return 0; ++} ++/******************************************************************************/ ++ ++static ssize_t fo_rw_notice_read(struct file *filp, char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ int ret = 0; ++ char *kbuf; ++ ++ if (*ppos == 1) ++ return 0; ++ ++ *ppos = 1; ++ ++ kbuf = vmalloc(sizeof(mmcdbg_helper) + 4); ++ if (!kbuf) { ++ pr_err("out of memory.\n"); ++ return -ENOMEM; ++ } ++ ++ ret = snprintf(kbuf, sizeof(mmcdbg_helper) + 4, ++ "<%s>\n", mmcdbg_helper); ++ if (copy_to_user(buffer, kbuf, ret)) { ++ vfree(kbuf); ++ return -EFAULT; ++ } ++ ++ vfree(kbuf); ++ ++ return ret; ++} ++/******************************************************************************/ ++ ++static ssize_t fo_rw_notice_write(struct file *filp, const char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ char *kbuf; ++ char *pkbuf; ++ int size = count; ++ ++ if (size >= sizeof(mmcdbg_helper)) ++ size = sizeof(mmcdbg_helper) - 1; ++ ++ kbuf = vmalloc(size + 1); ++ if (!kbuf) { ++ pr_err("out of memory.\n"); ++ return -ENOMEM; ++ } ++ ++ if (copy_from_user(kbuf, buffer, size)) { ++ vfree(kbuf); ++ return -EFAULT; ++ } ++ ++ kbuf[size] = '\0'; ++ ++ pkbuf = strim(kbuf); ++ ++ mutex_lock(&mutex_notice); ++ ++ strncpy(mmcdbg_helper, pkbuf, size); ++ ++ mutex_unlock(&mutex_notice); ++ ++ vfree(kbuf); ++ ++ return count; ++} ++/******************************************************************************/ ++ ++static const struct file_operations fo_dump_rcount = { ++ .owner = THIS_MODULE, ++ .open = fo_dump_rcount_open, ++ .read = fo_dump_rwcount_read, ++ .write = fo_dump_rwcount_write, ++ .release = fp_dump_rwcount_release, ++}; ++ ++static const struct file_operations fo_dump_wcount = { ++ .owner = THIS_MODULE, ++ .open = fo_dump_wcount_open, ++ .read = fo_dump_rwcount_read, ++ .write = fo_dump_rwcount_write, ++ .release = fp_dump_rwcount_release, ++}; ++ ++static const struct file_operations fo_rw_notice = { ++ .owner = THIS_MODULE, ++ .read = fo_rw_notice_read, ++ .write = fo_rw_notice_write, ++}; ++/******************************************************************************/ ++ ++static void mmcdbg_options(const char *string) ++{ ++ int enable; ++ const char *pos, *cmd; ++ ++ pos = string; ++ ++ while (*pos) { ++ while (*pos && *pos != '+' && *pos != '-') ++ pos++; ++ ++ switch (*pos++) { ++ case '+': ++ enable = 1; ++ break; ++ case '-': ++ enable = 0; ++ break; ++ default: ++ return; ++ } ++ ++ cmd = pos; ++ ++ while (*pos == '_' || isalpha(*pos)) ++ pos++; ++ ++ if (*cmd && pos > cmd) { ++ int size = pos - cmd; ++ char *enstr = enable ? "enable" : "disable"; ++ ++ if (!strncmp(cmd, "read", size)) { ++ mmcdbg_rcount_enable = enable; ++ pr_info("%s read count.\n", enstr); ++ } else if (!strncmp(cmd, "write", size)) { ++ mmcdbg_wcount_enable = enable; ++ pr_info("%s write count.\n", enstr); ++ } ++ } ++ ++ while (isspace(*pos) || *pos == ',' || *pos == ';') ++ pos++; ++ } ++} ++/******************************************************************************/ ++ ++int himci_dbg_rw(int devid, int is_write, u32 ofblk, u32 nrblk) ++{ ++ if (mmcdbg_devid != devid) ++ return 0; ++ ++ if (is_write && mmcdbg_wcount_enable) ++ mmcdbg_rw_count(is_write, ofblk, nrblk); ++ ++ if (!is_write && mmcdbg_rcount_enable) ++ mmcdbg_rw_count(is_write, ofblk, nrblk); ++ ++ if (mmcdbg_helper[0]) { ++ mutex_lock(&mutex_notice); ++ ++ mmcdbg_rw_notice(is_write, ofblk, nrblk); ++ ++ mutex_unlock(&mutex_notice); ++ } ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++int himci_dbg_init(int devid) ++{ ++ char buf[16]; ++ struct dentry *root = NULL; ++ struct dentry *ret = NULL; ++ unsigned int mode = S_IFREG | S_IRUSR | S_IWUSR; ++ ++ snprintf(buf, sizeof(buf), "himci%d", devid); ++ root = debugfs_create_dir(buf, NULL); ++ if (!root) { ++ pr_err("Can't create '%s' dir.\n", buf); ++ return -ENOENT; ++ } ++ ++ ret = debugfs_create_file("read", mode, root, NULL, &fo_dump_rcount); ++ if (!ret) { ++ pr_err("Can't create 'read' file.\n"); ++ goto fail; ++ } ++ ++ ret = debugfs_create_file("write", mode, root, NULL, &fo_dump_wcount); ++ if (!ret) { ++ pr_err("Can't create 'write' file.\n"); ++ goto fail; ++ } ++ ++ ret = debugfs_create_file("notice", mode, root, NULL, &fo_rw_notice); ++ if (!ret) { ++ pr_err("Can't create 'notice' file.\n"); ++ goto fail; ++ } ++ ++ if (mmcdbg_options_string) ++ mmcdbg_options(mmcdbg_options_string); ++ ++ mmcdbg_devid = devid; ++ ++ return 0; ++fail: ++ debugfs_remove_recursive(root); ++ ++ return -ENOENT; ++} ++/*****************************************************************************/ ++ ++static int __init mmcdbg_options_setup(char *s) ++{ ++ mmcdbg_options_string = s; ++ return 1; ++} ++__setup("mmcdbg=", mmcdbg_options_setup); +diff --git a/drivers/mmc/host/himciv200/himci_dbg.h b/drivers/mmc/host/himciv200/himci_dbg.h +new file mode 100644 +index 0000000..45adb29 +--- /dev/null ++++ b/drivers/mmc/host/himciv200/himci_dbg.h +@@ -0,0 +1,15 @@ ++/****************************************************************************** ++ * Copyright (C) 2014 Hisilicon STB Development Dept ++ * All rights reserved. ++ * *** ++ * Create by Czyong ++ * ++******************************************************************************/ ++#ifndef HIMCI_DBG_H ++#define HIMCI_DBG_H ++ ++int himci_dbg_init(int devid); ++ ++int himci_dbg_rw(int devid, int is_write, u32 ofblk, u32 nrblk); ++ ++#endif +diff --git a/drivers/mmc/host/himciv200/himci_hi3516av200.c b/drivers/mmc/host/himciv200/himci_hi3516av200.c +new file mode 100644 +index 0000000..f505bf5 +--- /dev/null ++++ b/drivers/mmc/host/himciv200/himci_hi3516av200.c +@@ -0,0 +1,210 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++#include ++ ++#define MMC_CRG_MIN 12500000 ++ ++#define PERI_CRG49 IO_ADDRESS(0x120100c4) ++#define EMMC_DLL_CTRL IO_ADDRESS(0x12030140) ++ ++#define TUNING_START_PHASE 0 ++#define TUNING_END_PHASE 15 ++#define HIMCI_PHASE_SCALE 16 ++#define DRV_PHASE_DFLT (0x6<<23) ++#define SMPL_PHASE_DFLT (0x0<<16) ++ ++#define EMMC_DRV_PHASE_DFLT (0x4<<23) ++#define EMMC_SMPL_PHASE_DFLT SMPL_PHASE_DFLT ++ ++#define REG_PAD_CTRL 0x12040800 ++#define REG_CTRL_SDIO0_CCLK 0xc4 ++#define REG_CTRL_SDIO0_CCMD 0xc8 ++#define REG_CTRL_SDIO0_CDATA0 0xcc ++#define REG_CTRL_SDIO0_CDATA1 0xd0 ++#define REG_CTRL_SDIO0_CDATA2 0xd4 ++#define REG_CTRL_SDIO0_CDATA3 0xd8 ++ ++#define REG_CTRL_SDIO1_CCLK 0xe8 ++#define REG_CTRL_SDIO1_CCMD 0xec ++#define REG_CTRL_SDIO1_CDATA0 0xf0 ++#define REG_CTRL_SDIO1_CDATA1 0xf4 ++#define REG_CTRL_SDIO1_CDATA2 0xf8 ++#define REG_CTRL_SDIO1_CDATA3 0xfc ++ ++#define REG_CTRL_EMMC_CLK 0x1ac ++#define REG_CTRL_EMMC_CMD 0x1c8 ++#define REG_CTRL_EMMC_DATA0 0x1b0 ++#define REG_CTRL_EMMC_DATA1 0x1cc ++#define REG_CTRL_EMMC_DATA2 0x1b4 ++#define REG_CTRL_EMMC_DATA3 0x1bc ++#define REG_CTRL_EMMC_DATA4 0x1c0 ++#define REG_CTRL_EMMC_DATA5 0x1a8 ++#define REG_CTRL_EMMC_DATA6 0x1dc ++#define REG_CTRL_EMMC_DATA7 0x1b8 ++ ++#define EMMC_CLK_DS_3V3 0xd0 ++#define EMMC_CMD_DS_3V3 0xd0 ++#define EMMC_DATA0_DS_3V3 0xd0 ++#define EMMC_DATA1_DS_3V3 0xd0 ++#define EMMC_DATA2_DS_3V3 0xd0 ++#define EMMC_DATA3_DS_3V3 0xd0 ++#define EMMC_DATA4_DS_3V3 0xd0 ++#define EMMC_DATA5_DS_3V3 0xd0 ++#define EMMC_DATA6_DS_3V3 0xd0 ++#define EMMC_DATA7_DS_3V3 0xd0 ++ ++#define EMMC_CLK_DS_1V8 0xc0 ++#define EMMC_CMD_DS_1V8 0xc0 ++#define EMMC_DATA0_DS_1V8 0xc0 ++#define EMMC_DATA1_DS_1V8 0xc0 ++#define EMMC_DATA2_DS_1V8 0xc0 ++#define EMMC_DATA3_DS_1V8 0xc0 ++#define EMMC_DATA4_DS_1V8 0xc0 ++#define EMMC_DATA5_DS_1V8 0xc0 ++#define EMMC_DATA6_DS_1V8 0xc0 ++#define EMMC_DATA7_DS_1V8 0xc0 ++ ++struct sdio_drv_cap { ++ unsigned int reg_addr[2]; ++ unsigned int ds; ++}; ++ ++#define SDIO_DRV_CAP(ofst1, ofst2, v) { \ ++ .reg_addr[0] = (REG_PAD_CTRL + ofst1), \ ++ .reg_addr[1] = (REG_PAD_CTRL + ofst2), \ ++ .ds = v} ++static struct sdio_drv_cap sdio_ds_hs[] = { ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCLK, REG_CTRL_SDIO1_CCLK, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCMD, REG_CTRL_SDIO1_CCMD, 0x1e0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA0, REG_CTRL_SDIO1_CDATA0, 0x1e0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA1, REG_CTRL_SDIO1_CDATA1, 0x1e0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA2, REG_CTRL_SDIO1_CDATA2, 0x1e0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA3, REG_CTRL_SDIO1_CDATA3, 0x1e0) ++}; ++ ++static struct sdio_drv_cap sdio_ds_ddr50[] = { ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCLK, REG_CTRL_SDIO1_CCLK, 0x1b0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCMD, REG_CTRL_SDIO1_CCMD, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA0, REG_CTRL_SDIO1_CDATA0, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA1, REG_CTRL_SDIO1_CDATA1, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA2, REG_CTRL_SDIO1_CDATA2, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA3, REG_CTRL_SDIO1_CDATA3, 0x1c0) ++}; ++ ++static struct sdio_drv_cap sdio_ds_sdr50[] = { ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCLK, REG_CTRL_SDIO1_CCLK, 0x80), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCMD, REG_CTRL_SDIO1_CCMD, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA0, REG_CTRL_SDIO1_CDATA0, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA1, REG_CTRL_SDIO1_CDATA1, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA2, REG_CTRL_SDIO1_CDATA2, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA3, REG_CTRL_SDIO1_CDATA3, 0x1c0) ++}; ++ ++static struct sdio_drv_cap sdio_ds_sdr104[] = { ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCLK, REG_CTRL_SDIO1_CCLK, 0x0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCMD, REG_CTRL_SDIO1_CCMD, 0xc0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA0, REG_CTRL_SDIO1_CDATA0, 0xc0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA1, REG_CTRL_SDIO1_CDATA1, 0xc0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA2, REG_CTRL_SDIO1_CDATA2, 0xc0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA3, REG_CTRL_SDIO1_CDATA3, 0xc0) ++}; ++ ++struct emmc_drv_cap { ++ unsigned int reg_addr; ++ unsigned int ds[2]; ++}; ++ ++#define EMMC_DRV_CAP(ofst, v1, v2) { \ ++ .reg_addr = (REG_PAD_CTRL + ofst), \ ++ .ds[0] = v1, \ ++ .ds[1] = v2} ++static struct emmc_drv_cap emmc_ds[] = { ++ EMMC_DRV_CAP(REG_CTRL_EMMC_CLK, EMMC_CLK_DS_3V3, EMMC_CLK_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_CMD, EMMC_CMD_DS_3V3, EMMC_CMD_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA0, EMMC_DATA0_DS_3V3, EMMC_DATA0_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA1, EMMC_DATA1_DS_3V3, EMMC_DATA1_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA2, EMMC_DATA2_DS_3V3, EMMC_DATA2_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA3, EMMC_DATA3_DS_3V3, EMMC_DATA3_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA4, EMMC_DATA4_DS_3V3, EMMC_DATA4_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA5, EMMC_DATA5_DS_3V3, EMMC_DATA5_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA6, EMMC_DATA6_DS_3V3, EMMC_DATA6_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA7, EMMC_DATA7_DS_3V3, EMMC_DATA7_DS_1V8), ++}; ++ ++static void himci_set_pin_drv_cap(struct himci_host *host, unsigned int flag, ++ unsigned char timing) ++{ ++ struct sdio_drv_cap *sdio_ds; ++ unsigned int i; ++ ++ if (host->devid == 2) { ++ for (i = 0; i < ARRAY_SIZE(emmc_ds); i++) ++ himci_writel(emmc_ds[i].ds[flag], IO_ADDRESS(emmc_ds[i].reg_addr)); ++ } else { ++ if (timing == MMC_TIMING_UHS_SDR104) ++ sdio_ds = sdio_ds_sdr104; ++ else if (timing == MMC_TIMING_UHS_SDR50) ++ sdio_ds = sdio_ds_sdr50; ++ else if (timing == MMC_TIMING_UHS_DDR50) ++ sdio_ds = sdio_ds_ddr50; ++ else ++ sdio_ds = sdio_ds_hs; ++ ++ for (i = 0; i < ARRAY_SIZE(sdio_ds_hs); i++) ++ himci_writel(sdio_ds[i].ds, ++ IO_ADDRESS(sdio_ds[i].reg_addr[host->devid])); ++ } ++} ++ ++static void himci_set_drv_cap(struct himci_host *host, struct mmc_ios *ios) ++{ ++ unsigned int tmp_reg; ++ ++ if (ios->timing == MMC_TIMING_UHS_DDR50) { ++ tmp_reg = himci_readl(host->base + MCI_UHS_REG_EXT); ++ tmp_reg &= ~CLK_SMPL_PHS_MASK; ++ tmp_reg |= (0x4 << CLK_SMPL_PHS_SHIFT); ++ himci_writel(tmp_reg, host->base + MCI_UHS_REG_EXT); ++ } else if (ios->timing == MMC_TIMING_MMC_HS) { ++ tmp_reg = himci_readl(host->base + MCI_UHS_REG_EXT); ++ tmp_reg &= ~CLK_SMPL_PHS_MASK; ++ tmp_reg |= SMPL_PHASE_DFLT; ++ himci_writel(tmp_reg, host->base + MCI_UHS_REG_EXT); ++ } else if (ios->timing == MMC_TIMING_MMC_HS400) { ++ tmp_reg = himci_readl(host->base + MCI_UHS_REG_EXT); ++ tmp_reg &= ~CLK_SMPL_PHS_MASK; ++ tmp_reg |= (host->phase << CLK_SMPL_PHS_SHIFT); ++ himci_writel(tmp_reg, host->base + MCI_UHS_REG_EXT); ++ } ++ ++ /* set pin drive capability */ ++ if (ios->timing == MMC_TIMING_MMC_HS200 || ++ ios->timing == MMC_TIMING_MMC_HS400) ++ himci_set_pin_drv_cap(host, 1, ios->timing); ++ else ++ himci_set_pin_drv_cap(host, 0, ios->timing); ++} ++ ++static int himci_check_emmc(struct himci_host *host) ++{ ++ unsigned int val; ++ ++ val = himci_readl(IO_ADDRESS(SYS_CTRL_BASE + REG_SC_STAT)); ++ ++ return !(GET_SYS_BOOT_MODE(val) == BOOT_FROM_EMMC); ++} +diff --git a/drivers/mmc/host/himciv200/himci_hi3516cv300.c b/drivers/mmc/host/himciv200/himci_hi3516cv300.c +new file mode 100644 +index 0000000..ea35c2b +--- /dev/null ++++ b/drivers/mmc/host/himciv200/himci_hi3516cv300.c +@@ -0,0 +1,119 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++#include ++#include ++ ++#define MMC_CRG_MIN 49500000 ++ ++#define TUNING_START_PHASE 0 ++#define TUNING_END_PHASE 7 ++#define HIMCI_PHASE_SCALE 8 ++#define DRV_PHASE_DFLT (0x4<<23) ++#define SMPL_PHASE_DFLT (0x1<<16) ++ ++#define EMMC_DRV_PHASE_DFLT DRV_PHASE_DFLT ++#define EMMC_SMPL_PHASE_DFLT SMPL_PHASE_DFLT ++ ++#define GET_SYS_BOOT_MODE(_reg) (((_reg) >> 0x4) & 0x1) ++#define BOOT_FROM_EMMC 0x1 ++ ++#define REG_PAD_CTRL 0x12040800 ++ ++#define REG_CTRL_EMMC_CLK 0xa0 ++#define REG_CTRL_EMMC_CMD 0x9c ++#define REG_CTRL_EMMC_DATA0 0x90 ++#define REG_CTRL_EMMC_DATA1 0x98 ++#define REG_CTRL_EMMC_DATA2 0xa4 ++#define REG_CTRL_EMMC_DATA3 0x8c ++ ++#define EMMC_CLK_DS_1V8 0xc0 ++#define EMMC_CMD_DS_1V8 0x150 ++#define EMMC_DATA0_DS_1V8 0x1d0 ++#define EMMC_DATA1_DS_1V8 0x1d0 ++#define EMMC_DATA2_DS_1V8 0x1d0 ++#define EMMC_DATA3_DS_1V8 0x1d0 ++ ++struct emmc_drv_cap { ++ unsigned int reg_addr; ++ unsigned int ds; ++}; ++ ++#define EMMC_DRV_CAP(ofst, v) { \ ++ .reg_addr = ofst, \ ++ .ds = v} ++static struct emmc_drv_cap emmc_ds[] = { ++ EMMC_DRV_CAP(REG_CTRL_EMMC_CLK, EMMC_CLK_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_CMD, EMMC_CMD_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA0, EMMC_DATA0_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA1, EMMC_DATA1_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA2, EMMC_DATA2_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA3, EMMC_DATA3_DS_1V8), ++}; ++ ++static void himci_set_drv_cap(struct himci_host *host, struct mmc_ios *ios) ++{ ++ static void *pad_ctrl = NULL; ++ unsigned int i, tmp_reg; ++ ++ if (ios->timing == MMC_TIMING_MMC_DDR52) { ++ tmp_reg = himci_readl(host->base + MCI_UHS_REG_EXT); ++ tmp_reg &= ~CLK_DRV_PHS_MASK; ++ tmp_reg |= (0x2 << CLK_DRV_PHS_SHIFT); ++ himci_writel(tmp_reg, host->base + MCI_UHS_REG_EXT); ++ } ++ ++ if (ios->timing == MMC_TIMING_MMC_HS200) { ++ tmp_reg = himci_readl(host->base + MCI_UHS_REG_EXT); ++ tmp_reg &= ~(CLK_DRV_PHS_MASK); ++ tmp_reg |= (0x3 << CLK_DRV_PHS_SHIFT); ++ himci_writel(tmp_reg, host->base + MCI_UHS_REG_EXT); ++ } ++ ++ if (host->mmc->caps & MMC_CAP_SD_HIGHSPEED ++ || ios->timing == MMC_TIMING_LEGACY) ++ return; ++ ++ if (!pad_ctrl) ++ pad_ctrl = ioremap(REG_PAD_CTRL, 0x1000); ++ ++ if (!pad_ctrl) ++ return; ++ ++ for (i = 0; i < ARRAY_SIZE(emmc_ds); i++) ++ himci_writel(emmc_ds[i].ds, pad_ctrl + emmc_ds[i].reg_addr); ++} ++ ++static int himci_check_emmc(struct himci_host *host) ++{ ++ struct device *dev = &(host->pdev->dev); ++ unsigned int val; ++ ++ if (!host->sys_regmap) { ++ host->sys_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, ++ "regmap"); ++ if (IS_ERR(host->sys_regmap)) { ++ host->sys_regmap = NULL; ++ return 1; ++ } ++ } ++ ++ if (regmap_read(host->sys_regmap, 0x8c, &val)) ++ return 1; ++ ++ return !(GET_SYS_BOOT_MODE(val) == BOOT_FROM_EMMC); ++} +diff --git a/drivers/mmc/host/himciv200/himci_hi3519.c b/drivers/mmc/host/himciv200/himci_hi3519.c +new file mode 100644 +index 0000000..03bfafe +--- /dev/null ++++ b/drivers/mmc/host/himciv200/himci_hi3519.c +@@ -0,0 +1,192 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++#include ++ ++#define MMC_CRG_MIN 12500000 ++ ++#define PERI_CRG49 IO_ADDRESS(0x120100c4) ++#define TUNING_START_PHASE 2 ++#define TUNING_END_PHASE 14 ++ ++#define EMMC_DLL_CTRL IO_ADDRESS(0x12030140) ++#define REG_PAD_CTRL 0x12040800 ++#define DRV_PHASE_DFLT (0x6<<23) ++#define SMPL_PHASE_DFLT (0x0<<16) ++ ++#define EMMC_DRV_PHASE_DFLT DRV_PHASE_DFLT ++#define EMMC_SMPL_PHASE_DFLT SMPL_PHASE_DFLT ++ ++#define REG_CTRL_SDIO0_CCLK IO_ADDRESS(REG_PAD_CTRL + 0x114) ++#define REG_CTRL_SDIO0_CCMD IO_ADDRESS(REG_PAD_CTRL + 0x118) ++#define REG_CTRL_SDIO0_CDATA0 IO_ADDRESS(REG_PAD_CTRL + 0x11c) ++#define REG_CTRL_SDIO0_CDATA1 IO_ADDRESS(REG_PAD_CTRL + 0x120) ++#define REG_CTRL_SDIO0_CDATA2 IO_ADDRESS(REG_PAD_CTRL + 0x124) ++#define REG_CTRL_SDIO0_CDATA3 IO_ADDRESS(REG_PAD_CTRL + 0x128) ++ ++#define REG_CTRL_SDIO1_CCLK IO_ADDRESS(REG_PAD_CTRL + 0x138) ++#define REG_CTRL_SDIO1_CCMD IO_ADDRESS(REG_PAD_CTRL + 0x13c) ++#define REG_CTRL_SDIO1_CDATA0 IO_ADDRESS(REG_PAD_CTRL + 0x140) ++#define REG_CTRL_SDIO1_CDATA1 IO_ADDRESS(REG_PAD_CTRL + 0x144) ++#define REG_CTRL_SDIO1_CDATA2 IO_ADDRESS(REG_PAD_CTRL + 0x148) ++#define REG_CTRL_SDIO1_CDATA3 IO_ADDRESS(REG_PAD_CTRL + 0x14c) ++ ++#define REG_CTRL_EMMC_DS IO_ADDRESS(REG_PAD_CTRL + 0x17c) ++#define REG_CTRL_EMMC_CLK IO_ADDRESS(REG_PAD_CTRL + 0x154) ++#define REG_CTRL_EMMC_CMD IO_ADDRESS(REG_PAD_CTRL + 0x170) ++#define REG_CTRL_EMMC_DATA0 IO_ADDRESS(REG_PAD_CTRL + 0x158) ++#define REG_CTRL_EMMC_DATA1 IO_ADDRESS(REG_PAD_CTRL + 0x174) ++#define REG_CTRL_EMMC_DATA2 IO_ADDRESS(REG_PAD_CTRL + 0x15c) ++#define REG_CTRL_EMMC_DATA3 IO_ADDRESS(REG_PAD_CTRL + 0x164) ++#define REG_CTRL_EMMC_DATA4 IO_ADDRESS(REG_PAD_CTRL + 0x168) ++#define REG_CTRL_EMMC_DATA5 IO_ADDRESS(REG_PAD_CTRL + 0x150) ++#define REG_CTRL_EMMC_DATA6 IO_ADDRESS(REG_PAD_CTRL + 0x184) ++#define REG_CTRL_EMMC_DATA7 IO_ADDRESS(REG_PAD_CTRL + 0x160) ++ ++#define SDIO_CCLK_DS_3V3 0x1c0 ++#define SDIO_CCMD_DS_3V3 0x140 ++#define SDIO_CDATA0_DS_3V3 0x140 ++#define SDIO_CDATA1_DS_3V3 0x140 ++#define SDIO_CDATA2_DS_3V3 0x140 ++#define SDIO_CDATA3_DS_3V3 0x140 ++ ++#define SDIO_CCLK_DS_1V8 0x0 ++#define SDIO_CCMD_DS_1V8 0x120 ++#define SDIO_CDATA0_DS_1V8 0x120 ++#define SDIO_CDATA1_DS_1V8 0x120 ++#define SDIO_CDATA2_DS_1V8 0x120 ++#define SDIO_CDATA3_DS_1V8 0x120 ++ ++#define EMMC_DS_DS_3V3 0x120 ++#define EMMC_CLK_DS_3V3 0x1c0 ++#define EMMC_CMD_DS_3V3 0x1d0 ++#define EMMC_DATA0_DS_3V3 0x1e0 ++#define EMMC_DATA1_DS_3V3 0x1d0 ++#define EMMC_DATA2_DS_3V3 0x1d0 ++#define EMMC_DATA3_DS_3V3 0x1e0 ++#define EMMC_DATA4_DS_3V3 0x1e0 ++#define EMMC_DATA5_DS_3V3 0x1d0 ++#define EMMC_DATA6_DS_3V3 0x1e0 ++#define EMMC_DATA7_DS_3V3 0x1e0 ++ ++#define EMMC_DS_DS_1V8 0x100 ++#define EMMC_CLK_DS_1V8 0x160 ++#define EMMC_CMD_DS_1V8 0x180 ++#define EMMC_DATA0_DS_1V8 0x180 ++#define EMMC_DATA1_DS_1V8 0x180 ++#define EMMC_DATA2_DS_1V8 0x180 ++#define EMMC_DATA3_DS_1V8 0x180 ++#define EMMC_DATA4_DS_1V8 0x180 ++#define EMMC_DATA5_DS_1V8 0x180 ++#define EMMC_DATA6_DS_1V8 0x180 ++#define EMMC_DATA7_DS_1V8 0x180 ++ ++static void himci_set_pin_drv_cap(struct himci_host *host, unsigned int flag) ++{ ++ if (flag) { ++ if (0 == host->devid) { ++ himci_writel(SDIO_CCLK_DS_1V8, REG_CTRL_SDIO0_CCLK); ++ himci_writel(SDIO_CCMD_DS_1V8, REG_CTRL_SDIO0_CCMD); ++ himci_writel(SDIO_CDATA0_DS_1V8, REG_CTRL_SDIO0_CDATA0); ++ himci_writel(SDIO_CDATA1_DS_1V8, REG_CTRL_SDIO0_CDATA1); ++ himci_writel(SDIO_CDATA2_DS_1V8, REG_CTRL_SDIO0_CDATA2); ++ himci_writel(SDIO_CDATA3_DS_1V8, REG_CTRL_SDIO0_CDATA3); ++ } else if (1 == host->devid) { ++ himci_writel(SDIO_CCLK_DS_1V8, REG_CTRL_SDIO1_CCLK); ++ himci_writel(SDIO_CCMD_DS_1V8, REG_CTRL_SDIO1_CCMD); ++ himci_writel(SDIO_CDATA0_DS_1V8, REG_CTRL_SDIO1_CDATA0); ++ himci_writel(SDIO_CDATA1_DS_1V8, REG_CTRL_SDIO1_CDATA1); ++ himci_writel(SDIO_CDATA2_DS_1V8, REG_CTRL_SDIO1_CDATA2); ++ himci_writel(SDIO_CDATA3_DS_1V8, REG_CTRL_SDIO1_CDATA3); ++ } else if (2 == host->devid) { ++ himci_writel(EMMC_DS_DS_1V8, REG_CTRL_EMMC_DS); ++ himci_writel(EMMC_CLK_DS_1V8, REG_CTRL_EMMC_CLK); ++ himci_writel(EMMC_CMD_DS_1V8, REG_CTRL_EMMC_CMD); ++ himci_writel(EMMC_DATA0_DS_1V8, REG_CTRL_EMMC_DATA0); ++ himci_writel(EMMC_DATA1_DS_1V8, REG_CTRL_EMMC_DATA1); ++ himci_writel(EMMC_DATA2_DS_1V8, REG_CTRL_EMMC_DATA2); ++ himci_writel(EMMC_DATA3_DS_1V8, REG_CTRL_EMMC_DATA3); ++ himci_writel(EMMC_DATA4_DS_1V8, REG_CTRL_EMMC_DATA4); ++ himci_writel(EMMC_DATA5_DS_1V8, REG_CTRL_EMMC_DATA5); ++ himci_writel(EMMC_DATA6_DS_1V8, REG_CTRL_EMMC_DATA6); ++ himci_writel(EMMC_DATA7_DS_1V8, REG_CTRL_EMMC_DATA7); ++ } ++ } else { ++ /* config Pin drive capability */ ++ if (0 == host->devid) { ++ himci_writel(SDIO_CCLK_DS_3V3, REG_CTRL_SDIO0_CCLK); ++ himci_writel(SDIO_CCMD_DS_3V3, REG_CTRL_SDIO0_CCMD); ++ himci_writel(SDIO_CDATA0_DS_3V3, REG_CTRL_SDIO0_CDATA0); ++ himci_writel(SDIO_CDATA1_DS_3V3, REG_CTRL_SDIO0_CDATA1); ++ himci_writel(SDIO_CDATA2_DS_3V3, REG_CTRL_SDIO0_CDATA2); ++ himci_writel(SDIO_CDATA3_DS_3V3, REG_CTRL_SDIO0_CDATA3); ++ } else if (1 == host->devid) { ++ himci_writel(SDIO_CCLK_DS_3V3, REG_CTRL_SDIO1_CCLK); ++ himci_writel(SDIO_CCMD_DS_3V3, REG_CTRL_SDIO1_CCMD); ++ himci_writel(SDIO_CDATA0_DS_3V3, REG_CTRL_SDIO1_CDATA0); ++ himci_writel(SDIO_CDATA1_DS_3V3, REG_CTRL_SDIO1_CDATA1); ++ himci_writel(SDIO_CDATA2_DS_3V3, REG_CTRL_SDIO1_CDATA2); ++ himci_writel(SDIO_CDATA3_DS_3V3, REG_CTRL_SDIO1_CDATA3); ++ } else if (2 == host->devid) { ++ himci_writel(EMMC_DS_DS_3V3, REG_CTRL_EMMC_DS); ++ himci_writel(EMMC_CLK_DS_3V3, REG_CTRL_EMMC_CLK); ++ himci_writel(EMMC_CMD_DS_3V3, REG_CTRL_EMMC_CMD); ++ himci_writel(EMMC_DATA0_DS_3V3, REG_CTRL_EMMC_DATA0); ++ himci_writel(EMMC_DATA1_DS_3V3, REG_CTRL_EMMC_DATA1); ++ himci_writel(EMMC_DATA2_DS_3V3, REG_CTRL_EMMC_DATA2); ++ himci_writel(EMMC_DATA3_DS_3V3, REG_CTRL_EMMC_DATA3); ++ himci_writel(EMMC_DATA4_DS_3V3, REG_CTRL_EMMC_DATA4); ++ himci_writel(EMMC_DATA5_DS_3V3, REG_CTRL_EMMC_DATA5); ++ himci_writel(EMMC_DATA6_DS_3V3, REG_CTRL_EMMC_DATA6); ++ himci_writel(EMMC_DATA7_DS_3V3, REG_CTRL_EMMC_DATA7); ++ } ++ } ++} ++ ++static void himci_set_drv_cap(struct himci_host *host, struct mmc_ios *ios) ++{ ++ unsigned int tmp_reg; ++ ++ if (ios->timing == MMC_TIMING_UHS_DDR50) { ++ tmp_reg = himci_readl(host->base + MCI_UHS_REG_EXT); ++ tmp_reg &= ~CLK_SMPL_PHS_MASK; ++ tmp_reg |= (0x4 << 16); ++ himci_writel(tmp_reg, host->base + MCI_UHS_REG_EXT); ++ } else if (ios->timing == MMC_TIMING_UHS_SDR104) { ++ tmp_reg = himci_readl(host->base + MCI_UHS_REG_EXT); ++ tmp_reg &= ~CLK_DRV_PHS_MASK; ++ tmp_reg |= (0x4 << 23); ++ himci_writel(tmp_reg, host->base + MCI_UHS_REG_EXT); ++ } ++ ++ /* set pin drive capability */ ++ if (ios->timing == MMC_TIMING_MMC_HS200 || ++ ios->timing == MMC_TIMING_MMC_HS400 || ++ ios->timing == MMC_TIMING_UHS_SDR104) ++ himci_set_pin_drv_cap(host, 1); ++ else ++ himci_set_pin_drv_cap(host, 0); ++} ++ ++static int himci_check_emmc(struct himci_host *host) ++{ ++ unsigned int val; ++ ++ val = himci_readl(IO_ADDRESS(SYS_CTRL_BASE + REG_SC_STAT)); ++ ++ return !(GET_SYS_BOOT_MODE(val) == BOOT_FROM_EMMC); ++} +diff --git a/drivers/mmc/host/himciv200/himci_hi3519v101.c b/drivers/mmc/host/himciv200/himci_hi3519v101.c +new file mode 100644 +index 0000000..f505bf5 +--- /dev/null ++++ b/drivers/mmc/host/himciv200/himci_hi3519v101.c +@@ -0,0 +1,210 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++#include ++ ++#define MMC_CRG_MIN 12500000 ++ ++#define PERI_CRG49 IO_ADDRESS(0x120100c4) ++#define EMMC_DLL_CTRL IO_ADDRESS(0x12030140) ++ ++#define TUNING_START_PHASE 0 ++#define TUNING_END_PHASE 15 ++#define HIMCI_PHASE_SCALE 16 ++#define DRV_PHASE_DFLT (0x6<<23) ++#define SMPL_PHASE_DFLT (0x0<<16) ++ ++#define EMMC_DRV_PHASE_DFLT (0x4<<23) ++#define EMMC_SMPL_PHASE_DFLT SMPL_PHASE_DFLT ++ ++#define REG_PAD_CTRL 0x12040800 ++#define REG_CTRL_SDIO0_CCLK 0xc4 ++#define REG_CTRL_SDIO0_CCMD 0xc8 ++#define REG_CTRL_SDIO0_CDATA0 0xcc ++#define REG_CTRL_SDIO0_CDATA1 0xd0 ++#define REG_CTRL_SDIO0_CDATA2 0xd4 ++#define REG_CTRL_SDIO0_CDATA3 0xd8 ++ ++#define REG_CTRL_SDIO1_CCLK 0xe8 ++#define REG_CTRL_SDIO1_CCMD 0xec ++#define REG_CTRL_SDIO1_CDATA0 0xf0 ++#define REG_CTRL_SDIO1_CDATA1 0xf4 ++#define REG_CTRL_SDIO1_CDATA2 0xf8 ++#define REG_CTRL_SDIO1_CDATA3 0xfc ++ ++#define REG_CTRL_EMMC_CLK 0x1ac ++#define REG_CTRL_EMMC_CMD 0x1c8 ++#define REG_CTRL_EMMC_DATA0 0x1b0 ++#define REG_CTRL_EMMC_DATA1 0x1cc ++#define REG_CTRL_EMMC_DATA2 0x1b4 ++#define REG_CTRL_EMMC_DATA3 0x1bc ++#define REG_CTRL_EMMC_DATA4 0x1c0 ++#define REG_CTRL_EMMC_DATA5 0x1a8 ++#define REG_CTRL_EMMC_DATA6 0x1dc ++#define REG_CTRL_EMMC_DATA7 0x1b8 ++ ++#define EMMC_CLK_DS_3V3 0xd0 ++#define EMMC_CMD_DS_3V3 0xd0 ++#define EMMC_DATA0_DS_3V3 0xd0 ++#define EMMC_DATA1_DS_3V3 0xd0 ++#define EMMC_DATA2_DS_3V3 0xd0 ++#define EMMC_DATA3_DS_3V3 0xd0 ++#define EMMC_DATA4_DS_3V3 0xd0 ++#define EMMC_DATA5_DS_3V3 0xd0 ++#define EMMC_DATA6_DS_3V3 0xd0 ++#define EMMC_DATA7_DS_3V3 0xd0 ++ ++#define EMMC_CLK_DS_1V8 0xc0 ++#define EMMC_CMD_DS_1V8 0xc0 ++#define EMMC_DATA0_DS_1V8 0xc0 ++#define EMMC_DATA1_DS_1V8 0xc0 ++#define EMMC_DATA2_DS_1V8 0xc0 ++#define EMMC_DATA3_DS_1V8 0xc0 ++#define EMMC_DATA4_DS_1V8 0xc0 ++#define EMMC_DATA5_DS_1V8 0xc0 ++#define EMMC_DATA6_DS_1V8 0xc0 ++#define EMMC_DATA7_DS_1V8 0xc0 ++ ++struct sdio_drv_cap { ++ unsigned int reg_addr[2]; ++ unsigned int ds; ++}; ++ ++#define SDIO_DRV_CAP(ofst1, ofst2, v) { \ ++ .reg_addr[0] = (REG_PAD_CTRL + ofst1), \ ++ .reg_addr[1] = (REG_PAD_CTRL + ofst2), \ ++ .ds = v} ++static struct sdio_drv_cap sdio_ds_hs[] = { ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCLK, REG_CTRL_SDIO1_CCLK, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCMD, REG_CTRL_SDIO1_CCMD, 0x1e0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA0, REG_CTRL_SDIO1_CDATA0, 0x1e0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA1, REG_CTRL_SDIO1_CDATA1, 0x1e0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA2, REG_CTRL_SDIO1_CDATA2, 0x1e0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA3, REG_CTRL_SDIO1_CDATA3, 0x1e0) ++}; ++ ++static struct sdio_drv_cap sdio_ds_ddr50[] = { ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCLK, REG_CTRL_SDIO1_CCLK, 0x1b0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCMD, REG_CTRL_SDIO1_CCMD, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA0, REG_CTRL_SDIO1_CDATA0, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA1, REG_CTRL_SDIO1_CDATA1, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA2, REG_CTRL_SDIO1_CDATA2, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA3, REG_CTRL_SDIO1_CDATA3, 0x1c0) ++}; ++ ++static struct sdio_drv_cap sdio_ds_sdr50[] = { ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCLK, REG_CTRL_SDIO1_CCLK, 0x80), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCMD, REG_CTRL_SDIO1_CCMD, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA0, REG_CTRL_SDIO1_CDATA0, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA1, REG_CTRL_SDIO1_CDATA1, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA2, REG_CTRL_SDIO1_CDATA2, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA3, REG_CTRL_SDIO1_CDATA3, 0x1c0) ++}; ++ ++static struct sdio_drv_cap sdio_ds_sdr104[] = { ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCLK, REG_CTRL_SDIO1_CCLK, 0x0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCMD, REG_CTRL_SDIO1_CCMD, 0xc0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA0, REG_CTRL_SDIO1_CDATA0, 0xc0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA1, REG_CTRL_SDIO1_CDATA1, 0xc0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA2, REG_CTRL_SDIO1_CDATA2, 0xc0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA3, REG_CTRL_SDIO1_CDATA3, 0xc0) ++}; ++ ++struct emmc_drv_cap { ++ unsigned int reg_addr; ++ unsigned int ds[2]; ++}; ++ ++#define EMMC_DRV_CAP(ofst, v1, v2) { \ ++ .reg_addr = (REG_PAD_CTRL + ofst), \ ++ .ds[0] = v1, \ ++ .ds[1] = v2} ++static struct emmc_drv_cap emmc_ds[] = { ++ EMMC_DRV_CAP(REG_CTRL_EMMC_CLK, EMMC_CLK_DS_3V3, EMMC_CLK_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_CMD, EMMC_CMD_DS_3V3, EMMC_CMD_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA0, EMMC_DATA0_DS_3V3, EMMC_DATA0_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA1, EMMC_DATA1_DS_3V3, EMMC_DATA1_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA2, EMMC_DATA2_DS_3V3, EMMC_DATA2_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA3, EMMC_DATA3_DS_3V3, EMMC_DATA3_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA4, EMMC_DATA4_DS_3V3, EMMC_DATA4_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA5, EMMC_DATA5_DS_3V3, EMMC_DATA5_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA6, EMMC_DATA6_DS_3V3, EMMC_DATA6_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA7, EMMC_DATA7_DS_3V3, EMMC_DATA7_DS_1V8), ++}; ++ ++static void himci_set_pin_drv_cap(struct himci_host *host, unsigned int flag, ++ unsigned char timing) ++{ ++ struct sdio_drv_cap *sdio_ds; ++ unsigned int i; ++ ++ if (host->devid == 2) { ++ for (i = 0; i < ARRAY_SIZE(emmc_ds); i++) ++ himci_writel(emmc_ds[i].ds[flag], IO_ADDRESS(emmc_ds[i].reg_addr)); ++ } else { ++ if (timing == MMC_TIMING_UHS_SDR104) ++ sdio_ds = sdio_ds_sdr104; ++ else if (timing == MMC_TIMING_UHS_SDR50) ++ sdio_ds = sdio_ds_sdr50; ++ else if (timing == MMC_TIMING_UHS_DDR50) ++ sdio_ds = sdio_ds_ddr50; ++ else ++ sdio_ds = sdio_ds_hs; ++ ++ for (i = 0; i < ARRAY_SIZE(sdio_ds_hs); i++) ++ himci_writel(sdio_ds[i].ds, ++ IO_ADDRESS(sdio_ds[i].reg_addr[host->devid])); ++ } ++} ++ ++static void himci_set_drv_cap(struct himci_host *host, struct mmc_ios *ios) ++{ ++ unsigned int tmp_reg; ++ ++ if (ios->timing == MMC_TIMING_UHS_DDR50) { ++ tmp_reg = himci_readl(host->base + MCI_UHS_REG_EXT); ++ tmp_reg &= ~CLK_SMPL_PHS_MASK; ++ tmp_reg |= (0x4 << CLK_SMPL_PHS_SHIFT); ++ himci_writel(tmp_reg, host->base + MCI_UHS_REG_EXT); ++ } else if (ios->timing == MMC_TIMING_MMC_HS) { ++ tmp_reg = himci_readl(host->base + MCI_UHS_REG_EXT); ++ tmp_reg &= ~CLK_SMPL_PHS_MASK; ++ tmp_reg |= SMPL_PHASE_DFLT; ++ himci_writel(tmp_reg, host->base + MCI_UHS_REG_EXT); ++ } else if (ios->timing == MMC_TIMING_MMC_HS400) { ++ tmp_reg = himci_readl(host->base + MCI_UHS_REG_EXT); ++ tmp_reg &= ~CLK_SMPL_PHS_MASK; ++ tmp_reg |= (host->phase << CLK_SMPL_PHS_SHIFT); ++ himci_writel(tmp_reg, host->base + MCI_UHS_REG_EXT); ++ } ++ ++ /* set pin drive capability */ ++ if (ios->timing == MMC_TIMING_MMC_HS200 || ++ ios->timing == MMC_TIMING_MMC_HS400) ++ himci_set_pin_drv_cap(host, 1, ios->timing); ++ else ++ himci_set_pin_drv_cap(host, 0, ios->timing); ++} ++ ++static int himci_check_emmc(struct himci_host *host) ++{ ++ unsigned int val; ++ ++ val = himci_readl(IO_ADDRESS(SYS_CTRL_BASE + REG_SC_STAT)); ++ ++ return !(GET_SYS_BOOT_MODE(val) == BOOT_FROM_EMMC); ++} +diff --git a/drivers/mmc/host/himciv200/himci_hi3559.c b/drivers/mmc/host/himciv200/himci_hi3559.c +new file mode 100644 +index 0000000..f505bf5 +--- /dev/null ++++ b/drivers/mmc/host/himciv200/himci_hi3559.c +@@ -0,0 +1,210 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++#include ++ ++#define MMC_CRG_MIN 12500000 ++ ++#define PERI_CRG49 IO_ADDRESS(0x120100c4) ++#define EMMC_DLL_CTRL IO_ADDRESS(0x12030140) ++ ++#define TUNING_START_PHASE 0 ++#define TUNING_END_PHASE 15 ++#define HIMCI_PHASE_SCALE 16 ++#define DRV_PHASE_DFLT (0x6<<23) ++#define SMPL_PHASE_DFLT (0x0<<16) ++ ++#define EMMC_DRV_PHASE_DFLT (0x4<<23) ++#define EMMC_SMPL_PHASE_DFLT SMPL_PHASE_DFLT ++ ++#define REG_PAD_CTRL 0x12040800 ++#define REG_CTRL_SDIO0_CCLK 0xc4 ++#define REG_CTRL_SDIO0_CCMD 0xc8 ++#define REG_CTRL_SDIO0_CDATA0 0xcc ++#define REG_CTRL_SDIO0_CDATA1 0xd0 ++#define REG_CTRL_SDIO0_CDATA2 0xd4 ++#define REG_CTRL_SDIO0_CDATA3 0xd8 ++ ++#define REG_CTRL_SDIO1_CCLK 0xe8 ++#define REG_CTRL_SDIO1_CCMD 0xec ++#define REG_CTRL_SDIO1_CDATA0 0xf0 ++#define REG_CTRL_SDIO1_CDATA1 0xf4 ++#define REG_CTRL_SDIO1_CDATA2 0xf8 ++#define REG_CTRL_SDIO1_CDATA3 0xfc ++ ++#define REG_CTRL_EMMC_CLK 0x1ac ++#define REG_CTRL_EMMC_CMD 0x1c8 ++#define REG_CTRL_EMMC_DATA0 0x1b0 ++#define REG_CTRL_EMMC_DATA1 0x1cc ++#define REG_CTRL_EMMC_DATA2 0x1b4 ++#define REG_CTRL_EMMC_DATA3 0x1bc ++#define REG_CTRL_EMMC_DATA4 0x1c0 ++#define REG_CTRL_EMMC_DATA5 0x1a8 ++#define REG_CTRL_EMMC_DATA6 0x1dc ++#define REG_CTRL_EMMC_DATA7 0x1b8 ++ ++#define EMMC_CLK_DS_3V3 0xd0 ++#define EMMC_CMD_DS_3V3 0xd0 ++#define EMMC_DATA0_DS_3V3 0xd0 ++#define EMMC_DATA1_DS_3V3 0xd0 ++#define EMMC_DATA2_DS_3V3 0xd0 ++#define EMMC_DATA3_DS_3V3 0xd0 ++#define EMMC_DATA4_DS_3V3 0xd0 ++#define EMMC_DATA5_DS_3V3 0xd0 ++#define EMMC_DATA6_DS_3V3 0xd0 ++#define EMMC_DATA7_DS_3V3 0xd0 ++ ++#define EMMC_CLK_DS_1V8 0xc0 ++#define EMMC_CMD_DS_1V8 0xc0 ++#define EMMC_DATA0_DS_1V8 0xc0 ++#define EMMC_DATA1_DS_1V8 0xc0 ++#define EMMC_DATA2_DS_1V8 0xc0 ++#define EMMC_DATA3_DS_1V8 0xc0 ++#define EMMC_DATA4_DS_1V8 0xc0 ++#define EMMC_DATA5_DS_1V8 0xc0 ++#define EMMC_DATA6_DS_1V8 0xc0 ++#define EMMC_DATA7_DS_1V8 0xc0 ++ ++struct sdio_drv_cap { ++ unsigned int reg_addr[2]; ++ unsigned int ds; ++}; ++ ++#define SDIO_DRV_CAP(ofst1, ofst2, v) { \ ++ .reg_addr[0] = (REG_PAD_CTRL + ofst1), \ ++ .reg_addr[1] = (REG_PAD_CTRL + ofst2), \ ++ .ds = v} ++static struct sdio_drv_cap sdio_ds_hs[] = { ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCLK, REG_CTRL_SDIO1_CCLK, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCMD, REG_CTRL_SDIO1_CCMD, 0x1e0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA0, REG_CTRL_SDIO1_CDATA0, 0x1e0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA1, REG_CTRL_SDIO1_CDATA1, 0x1e0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA2, REG_CTRL_SDIO1_CDATA2, 0x1e0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA3, REG_CTRL_SDIO1_CDATA3, 0x1e0) ++}; ++ ++static struct sdio_drv_cap sdio_ds_ddr50[] = { ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCLK, REG_CTRL_SDIO1_CCLK, 0x1b0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCMD, REG_CTRL_SDIO1_CCMD, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA0, REG_CTRL_SDIO1_CDATA0, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA1, REG_CTRL_SDIO1_CDATA1, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA2, REG_CTRL_SDIO1_CDATA2, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA3, REG_CTRL_SDIO1_CDATA3, 0x1c0) ++}; ++ ++static struct sdio_drv_cap sdio_ds_sdr50[] = { ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCLK, REG_CTRL_SDIO1_CCLK, 0x80), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCMD, REG_CTRL_SDIO1_CCMD, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA0, REG_CTRL_SDIO1_CDATA0, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA1, REG_CTRL_SDIO1_CDATA1, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA2, REG_CTRL_SDIO1_CDATA2, 0x1c0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA3, REG_CTRL_SDIO1_CDATA3, 0x1c0) ++}; ++ ++static struct sdio_drv_cap sdio_ds_sdr104[] = { ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCLK, REG_CTRL_SDIO1_CCLK, 0x0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CCMD, REG_CTRL_SDIO1_CCMD, 0xc0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA0, REG_CTRL_SDIO1_CDATA0, 0xc0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA1, REG_CTRL_SDIO1_CDATA1, 0xc0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA2, REG_CTRL_SDIO1_CDATA2, 0xc0), ++ SDIO_DRV_CAP(REG_CTRL_SDIO0_CDATA3, REG_CTRL_SDIO1_CDATA3, 0xc0) ++}; ++ ++struct emmc_drv_cap { ++ unsigned int reg_addr; ++ unsigned int ds[2]; ++}; ++ ++#define EMMC_DRV_CAP(ofst, v1, v2) { \ ++ .reg_addr = (REG_PAD_CTRL + ofst), \ ++ .ds[0] = v1, \ ++ .ds[1] = v2} ++static struct emmc_drv_cap emmc_ds[] = { ++ EMMC_DRV_CAP(REG_CTRL_EMMC_CLK, EMMC_CLK_DS_3V3, EMMC_CLK_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_CMD, EMMC_CMD_DS_3V3, EMMC_CMD_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA0, EMMC_DATA0_DS_3V3, EMMC_DATA0_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA1, EMMC_DATA1_DS_3V3, EMMC_DATA1_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA2, EMMC_DATA2_DS_3V3, EMMC_DATA2_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA3, EMMC_DATA3_DS_3V3, EMMC_DATA3_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA4, EMMC_DATA4_DS_3V3, EMMC_DATA4_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA5, EMMC_DATA5_DS_3V3, EMMC_DATA5_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA6, EMMC_DATA6_DS_3V3, EMMC_DATA6_DS_1V8), ++ EMMC_DRV_CAP(REG_CTRL_EMMC_DATA7, EMMC_DATA7_DS_3V3, EMMC_DATA7_DS_1V8), ++}; ++ ++static void himci_set_pin_drv_cap(struct himci_host *host, unsigned int flag, ++ unsigned char timing) ++{ ++ struct sdio_drv_cap *sdio_ds; ++ unsigned int i; ++ ++ if (host->devid == 2) { ++ for (i = 0; i < ARRAY_SIZE(emmc_ds); i++) ++ himci_writel(emmc_ds[i].ds[flag], IO_ADDRESS(emmc_ds[i].reg_addr)); ++ } else { ++ if (timing == MMC_TIMING_UHS_SDR104) ++ sdio_ds = sdio_ds_sdr104; ++ else if (timing == MMC_TIMING_UHS_SDR50) ++ sdio_ds = sdio_ds_sdr50; ++ else if (timing == MMC_TIMING_UHS_DDR50) ++ sdio_ds = sdio_ds_ddr50; ++ else ++ sdio_ds = sdio_ds_hs; ++ ++ for (i = 0; i < ARRAY_SIZE(sdio_ds_hs); i++) ++ himci_writel(sdio_ds[i].ds, ++ IO_ADDRESS(sdio_ds[i].reg_addr[host->devid])); ++ } ++} ++ ++static void himci_set_drv_cap(struct himci_host *host, struct mmc_ios *ios) ++{ ++ unsigned int tmp_reg; ++ ++ if (ios->timing == MMC_TIMING_UHS_DDR50) { ++ tmp_reg = himci_readl(host->base + MCI_UHS_REG_EXT); ++ tmp_reg &= ~CLK_SMPL_PHS_MASK; ++ tmp_reg |= (0x4 << CLK_SMPL_PHS_SHIFT); ++ himci_writel(tmp_reg, host->base + MCI_UHS_REG_EXT); ++ } else if (ios->timing == MMC_TIMING_MMC_HS) { ++ tmp_reg = himci_readl(host->base + MCI_UHS_REG_EXT); ++ tmp_reg &= ~CLK_SMPL_PHS_MASK; ++ tmp_reg |= SMPL_PHASE_DFLT; ++ himci_writel(tmp_reg, host->base + MCI_UHS_REG_EXT); ++ } else if (ios->timing == MMC_TIMING_MMC_HS400) { ++ tmp_reg = himci_readl(host->base + MCI_UHS_REG_EXT); ++ tmp_reg &= ~CLK_SMPL_PHS_MASK; ++ tmp_reg |= (host->phase << CLK_SMPL_PHS_SHIFT); ++ himci_writel(tmp_reg, host->base + MCI_UHS_REG_EXT); ++ } ++ ++ /* set pin drive capability */ ++ if (ios->timing == MMC_TIMING_MMC_HS200 || ++ ios->timing == MMC_TIMING_MMC_HS400) ++ himci_set_pin_drv_cap(host, 1, ios->timing); ++ else ++ himci_set_pin_drv_cap(host, 0, ios->timing); ++} ++ ++static int himci_check_emmc(struct himci_host *host) ++{ ++ unsigned int val; ++ ++ val = himci_readl(IO_ADDRESS(SYS_CTRL_BASE + REG_SC_STAT)); ++ ++ return !(GET_SYS_BOOT_MODE(val) == BOOT_FROM_EMMC); ++} +diff --git a/drivers/mmc/host/himciv200/himci_proc.c b/drivers/mmc/host/himciv200/himci_proc.c +new file mode 100644 +index 0000000..280f24f +--- /dev/null ++++ b/drivers/mmc/host/himciv200/himci_proc.c +@@ -0,0 +1,290 @@ ++/***************************************************************************** ++ * This is the driver for the host mci SOC. ++ * ++ * Copyright (C) Hisilicon. All rights reserved. ++ * ++ ******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include "himci.h" ++#include "himci_reg.h" ++#include "himci_proc.h" ++ ++#define MCI_PARENT "mci" ++#define MCI_STATS_PROC "mci_info" ++#define MAX_CLOCK_SCALE (4) ++#define UNSTUFF_BITS(resp,start,size) \ ++ ({ \ ++ const int __size = size; \ ++ const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \ ++ const int __off = 3 - ((start) / 32); \ ++ const int __shft = (start) & 31; \ ++ u32 __res; \ ++ \ ++ __res = resp[__off] >> __shft; \ ++ if (__size + __shft > 32) \ ++ __res |= resp[__off-1] << ((32 - __shft) % 32); \ ++ __res & __mask; \ ++ }) ++ ++static struct proc_dir_entry *proc_mci_dir; ++static unsigned int mci_max_connections; ++static char *card_type[MAX_CARD_TYPE + 1] = { ++ "MMC card", ++ "SD card", ++ "SDIO card", ++ "SD combo (IO+mem) card", ++ "unknown" ++}; ++static char *clock_unit[4] = { ++ "Hz", ++ "KHz", ++ "MHz", ++ "GHz" ++}; ++ ++static char *mci_get_card_type(unsigned int sd_type) ++{ ++ if (MAX_CARD_TYPE <= sd_type) ++ return card_type[MAX_CARD_TYPE]; ++ else ++ return card_type[sd_type]; ++} ++ ++static unsigned int analyze_clock_scale(unsigned int clock, ++ unsigned int *clock_val) ++{ ++ unsigned int scale = 0; ++ unsigned int tmp = clock; ++ ++ while (1) { ++ tmp = tmp / 1000; ++ if (0 < tmp) { ++ *clock_val = tmp; ++ scale++; ++ } else { ++ break; ++ } ++ } ++ return scale; ++} ++ ++static inline int is_card_uhs(unsigned char timing) ++{ ++ return timing >= MMC_TIMING_UHS_SDR12 && ++ timing <= MMC_TIMING_UHS_DDR50; ++} ++ ++static inline int is_card_hs(unsigned char timing) ++{ ++ return timing == MMC_TIMING_SD_HS || timing == MMC_TIMING_MMC_HS; ++} ++ ++static void mci_stats_seq_printout(struct seq_file *s) ++{ ++ unsigned int index_mci; ++ unsigned int clock; ++ unsigned int clock_scale; ++ unsigned int clock_value = 0; ++ const char *type; ++ struct himci_host *host; ++ struct card_info * c_info; ++ const char *uhs_bus_speed_mode = ""; ++ u32 speed_class, grade_speed_uhs; ++ static const char *const uhs_speeds[] = { ++ [UHS_SDR12_BUS_SPEED] = "SDR12 ", ++ [UHS_SDR25_BUS_SPEED] = "SDR25 ", ++ [UHS_SDR50_BUS_SPEED] = "SDR50 ", ++ [UHS_SDR104_BUS_SPEED] = "SDR104 ", ++ [UHS_DDR50_BUS_SPEED] = "DDR50 ", ++ }; ++ ++ ++ for (index_mci = 0; index_mci < HIMCI_SLOT_NUM; index_mci++) { ++ host = mci_host[index_mci]; ++ c_info = &host->c_info; ++ if (!host || !host->mmc) { ++ seq_printf(s, "MCI%d: invalid\n", index_mci); ++ continue; ++ } else { ++ seq_printf(s, "MCI%d", index_mci); ++ } ++ ++ if (CARD_PLUGED == host->card_status) { ++ seq_puts(s, ": pluged"); ++ } else { ++ seq_puts(s, ": unplugged"); ++ } ++ ++ if (CARD_CONNECT != c_info->card_connect) { ++ seq_puts(s, "_disconnected\n"); ++ } else { ++ seq_puts(s, "_connected\n"); ++ ++ seq_printf(s, ++ "\tType: %s", ++ mci_get_card_type(c_info->card_type) ++ ); ++ ++ if (c_info->card_state & MMC_STATE_BLOCKADDR) { ++ if (c_info->card_state & MMC_CARD_SDXC) ++ type = "SDXC"; ++ else ++ type = "SDHC"; ++ seq_printf(s, "(%s)\n", type); ++ } ++ ++ if (is_card_uhs(c_info->timing) && ++ c_info->sd_bus_speed < ARRAY_SIZE(uhs_speeds)) ++ uhs_bus_speed_mode = uhs_speeds[c_info->sd_bus_speed]; ++ ++ seq_printf(s, "\tMode: %s%s%s%s\n", ++ is_card_uhs(c_info->timing) ? "UHS " : ++ (is_card_hs(c_info->timing) ? "HS " : ""), ++ c_info->timing == MMC_TIMING_MMC_HS400 ? "HS400 " : ++ (c_info->timing == MMC_TIMING_MMC_HS200 ? "HS200 " : ""), ++ c_info->timing == MMC_TIMING_MMC_DDR52 ? "DDR " : "", ++ uhs_bus_speed_mode); ++ ++ speed_class = UNSTUFF_BITS(c_info->ssr, 440 - 384, 8); ++ grade_speed_uhs = UNSTUFF_BITS(c_info->ssr, 396 - 384, 4); ++ seq_printf(s, "\tSpeed Class: Class %s\n", ++ (0x00 == speed_class) ? "0": ++ (0x01 == speed_class) ? "2": ++ (0x02 == speed_class) ? "4": ++ (0x03 == speed_class) ? "6": ++ (0x04 == speed_class) ? "10": ++ "Reserved"); ++ seq_printf(s, "\tUhs Speed Grade: %s\n", ++ (0x00 == grade_speed_uhs)? ++ "Less than 10MB/sec(0h)" : ++ (0x01 == grade_speed_uhs)? ++ "10MB/sec and above(1h)": ++ "Reserved"); ++ ++ clock = host->hclk; ++ clock_scale = analyze_clock_scale(clock, &clock_value); ++ seq_printf(s, "\tHost work clock: %d%s\n", ++ clock_value, clock_unit[clock_scale]); ++ ++ clock = c_info->card_support_clock; ++ clock_scale = analyze_clock_scale(clock, &clock_value); ++ seq_printf(s, "\tCard support clock: %d%s\n", ++ clock_value, clock_unit[clock_scale]); ++ ++ clock = host->cclk; ++ clock_scale = analyze_clock_scale(clock, &clock_value); ++ seq_printf(s, "\tCard work clock: %d%s\n", ++ clock_value, clock_unit[clock_scale]); ++ /* add card read/write error count */ ++ seq_printf(s, "\tCard error count: %d\n", ++ host->error_count); ++ } ++ } ++} ++ ++/* proc interface setup */ ++static void *mci_seq_start(struct seq_file *s, loff_t *pos) ++{ ++ /* counter is used to tracking multi proc interfaces ++ * We have only one interface so return zero ++ * pointer to start the sequence. ++ */ ++ static unsigned long counter; ++ ++ if (*pos == 0) ++ return &counter; ++ ++ *pos = 0; ++ return NULL; ++} ++ ++/* proc interface next */ ++static void *mci_seq_next(struct seq_file *s, void *v, loff_t *pos) ++{ ++ (*pos)++; ++ if (*pos >= HIMCI_SLOT_NUM) ++ return NULL; ++ ++ return NULL; ++} ++ ++/* define parameters where showed in proc file */ ++static int mci_stats_seq_show(struct seq_file *s, void *v) ++{ ++ mci_stats_seq_printout(s); ++ return 0; ++} ++ ++/* proc interface stop */ ++static void mci_seq_stop(struct seq_file *s, void *v) ++{ ++} ++ ++/* proc interface operation */ ++static const struct seq_operations mci_stats_seq_ops = { ++ .start = mci_seq_start, ++ .next = mci_seq_next, ++ .stop = mci_seq_stop, ++ .show = mci_stats_seq_show ++}; ++ ++/* proc file open*/ ++static int mci_stats_proc_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &mci_stats_seq_ops); ++}; ++ ++/* proc file operation */ ++static const struct file_operations mci_stats_proc_ops = { ++ .owner = THIS_MODULE, ++ .open = mci_stats_proc_open, ++ .read = seq_read, ++ .release = seq_release ++}; ++ ++int mci_proc_init(unsigned int max_connections) ++{ ++ struct proc_dir_entry *proc_stats_entry; ++ ++ mci_max_connections = max_connections; ++ ++ proc_mci_dir = proc_mkdir(MCI_PARENT, NULL); ++ if (!proc_mci_dir) { ++ pr_err("%s: failed to create proc file %s\n", ++ __func__, MCI_PARENT); ++ return 1; ++ } ++ ++ proc_stats_entry = proc_create(MCI_STATS_PROC, ++ 0, proc_mci_dir, &mci_stats_proc_ops); ++ if (!proc_stats_entry) { ++ pr_err("%s: failed to create proc file %s\n", ++ __func__, MCI_STATS_PROC); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++int mci_proc_shutdown(void) ++{ ++ if (proc_mci_dir) { ++ if (mci_max_connections > 0) ++ remove_proc_entry(MCI_STATS_PROC, proc_mci_dir); ++ ++ remove_proc_entry(MCI_PARENT, NULL); ++ proc_mci_dir = NULL; ++ } ++ ++ return 0; ++} +diff --git a/drivers/mmc/host/himciv200/himci_proc.h b/drivers/mmc/host/himciv200/himci_proc.h +new file mode 100644 +index 0000000..989d6e4 +--- /dev/null ++++ b/drivers/mmc/host/himciv200/himci_proc.h +@@ -0,0 +1,25 @@ ++/* ++ * MCI connection table manager ++ */ ++#ifndef __MCI_PROC_H__ ++#define __MCI_PROC_H__ ++ ++#include ++ ++#define MAX_CARD_TYPE 4 ++#define MAX_SPEED_MODE 5 ++ ++#ifdef CONFIG_ARCH_HI3516CV300 ++ #define HIMCI_SLOT_NUM 4 ++#endif ++ ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101 || defined CONFIG_ARCH_HI3559 || defined CONFIG_ARCH_HI3556 || \ ++ defined CONFIG_ARCH_HI3516AV200) ++ #define HIMCI_SLOT_NUM 3 ++#endif ++ ++extern struct himci_host *mci_host[HIMCI_SLOT_NUM]; ++int mci_proc_init(unsigned int max_connections); ++int mci_proc_shutdown(void); ++ ++#endif /* __MCI_PROC_H__ */ +diff --git a/drivers/mmc/host/himciv200/himci_reg.h b/drivers/mmc/host/himciv200/himci_reg.h +new file mode 100644 +index 0000000..8ecb3ed +--- /dev/null ++++ b/drivers/mmc/host/himciv200/himci_reg.h +@@ -0,0 +1,252 @@ ++#ifndef _HI_MCI_REG_H_ ++#define _HI_MCI_REG_H_ ++ ++#define HI_MCI_IO_SIZE 0x1000 ++ ++#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_RESET_N 0x78 ++#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 ADMA_CTRL 0xb0 ++#define ADMA_Q_ADDR 0xb4 ++#define ADMA_Q_DEEPTH 0xb8 ++#define ADMA_Q_RDPTR 0xbc ++#define ADMA_Q_WRPTR 0xc0 ++#define ADMA_Q_TO 0xc4 ++#define MCI_CARDTHRCTL 0x100 ++#define MCI_UHS_REG_EXT 0x108 ++#define MCI_EMMC_DDR_REG 0x10c ++#define MCI_TUNING_CTRL 0x118 ++ ++/* MCI_IDSTS(0x8c) detals */ ++#define CMD_LOCK_ERR (0x1<<29) ++#define OWNBIT_ERR (0x1<<28) ++#define QUEUE_OVERFLOW (0x1<<27) ++#define RESP_CHECK_ERR (0x1<<26) ++#define PACKET_INT (0x1<<25) ++#define PACKET_TO_INT (0x1<<24) ++#define AUTO_STOP_ERR (0x1<<23) ++#define QUEUE_FULL (0x1<<22) ++#define QUEUE_EMPTY (0x1<<21) ++#define ADMA3_FSM_SHIFT (17) ++#define FSM_SHIFT (13) ++#define CES (0x1<<5) ++#define DU (0x1<<4) ++#define FBE (0x1<<2) ++ ++#define ADMA_INT_ERR (CMD_LOCK_ERR | OWNBIT_ERR | QUEUE_OVERFLOW \ ++ | AUTO_STOP_ERR | PACKET_TO_INT | DU | FBE) ++ ++#define ADMA_INT_ALL (CMD_LOCK_ERR | OWNBIT_ERR | QUEUE_OVERFLOW \ ++ | RESP_CHECK_ERR | PACKET_INT \ ++ | PACKET_TO_INT | AUTO_STOP_ERR \ ++ | QUEUE_FULL | CES | DU | FBE) ++#define RESP_CHK_EN (0x1<<4) ++#define RDPTR_MOD_EN (0x1<<3) ++#define PACKET_INT_EN (0x1<<2) ++#define ADMA3_RESTART (0x1<<1) ++#define ADMA3_EN (0x1<<0) ++ ++/* GPIO config */ ++#define DTO_FIX_BYPASS (0x1<<23) ++#define CMD_OUT_EN_FIX_BYPASS (0x1<<8) ++ ++/* MCI_UHS_REG(0x74) details */ ++#define HI_EMMC_CTRL_VDD_180 (0x2<<0) ++#define HI_EMMC_CTRL_DDR_REG (0x2<<16) ++#define HI_SDXC_CTRL_VDD_180 (0x1<<0) ++#define HI_SDXC_CTRL_DDR_REG (0x1<<16) ++ ++/* MCI_BMOD(0x80) details */ ++#define BMOD_SWR (0x1<<0) ++#define BURST_INCR (0x1<<1) ++#define BMOD_DMA_EN (0x1<<7) ++#define BURST_8 (0x2<<8) ++#define BURST_16 (0x3<<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) ++ ++/* 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_CDETECT(0x50) details */ ++#define HIMCI_CARD0 (0x1<<0) ++#define HIMCI_CARD_MASK (0x3<<0) ++#define HIMCI_CARD_EMMC (0x1<<1) ++#define HIMCI_CARD_SD (0x1<<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 ++ ++/* MCI_CLKENA(0x10) details */ ++#define CCLK_ENABLE (0x1<<0) /* bit 0: enable of card clk*/ ++ ++/* MCI_CTYPE(0x18) details */ ++#define EMMC_CARD_WIDTH_1 (0x2<<0) ++#define EMMC_CARD_WIDTH_0 (0x2<<16) ++#define CARD_WIDTH_1 (0x1<<0) ++#define CARD_WIDTH_0 (0x1<<16) ++ ++/* MCI_CARDTHRCTL(0x100) details */ ++#define RW_THRESHOLD_SIZE (0x2000005) ++ ++/* MCI_SRC(0x0C) details */ ++#define EMMC_CLK_SOURCE (0x1<<2) ++ ++/* MCI_EMMC_DDR_REG(0x10c) details */ ++#define HI_EMMC_HS400_MODE (0x1<<31) ++ ++/* MCI_RESET_N(0x78) details */ ++#define MMC_RST_N (0x1<<0) /* control reset*/ ++ ++/* MCI_INTMASK(0x24) details: ++ bit 16-1: mask MMC host controller each interrupt ++*/ ++#define ALL_INT_MASK 0x1ffff ++#define DTO_INT_MASK (0x1<<3) ++#define SDIO_INT_MASK (0x1<<16) ++ ++/* MCI_UHS_REG_EXT(0x108) details */ ++/* bit[19:16] sampling phase */ ++#define CLK_SMPL_PHS_SHIFT (16) ++#define CLK_SMPL_PHS_MASK (0xF<<16) ++#define CLK_SMPLA_PHS_SHIFT (9) ++#define CLK_SMPLA_PHS_MASK (0x7<<9) ++/* bit[26:23] drv phase */ ++#define CLK_DRV_PHS_SHIFT (23) ++#define CLK_DRV_PHS_MASK (0xF<<23) ++#define DEFAULT_SMPL_PHASE (0x5) ++ ++/* MCI_CMD(0x2c) details: ++ bit 31: cmd execute or load start param of interface clk bit ++*/ ++#define START_CMD (0x1<<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 CMD_INT_MASK (RTO_INT_STATUS | RCRC_INT_STATUS | RE_INT_STATUS) ++#define DATA_INT_MASK (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 ALL_ADMA_INT_CLR (0xffe<<21) ++ ++/* MCI_STATUS(0x48) details */ ++#define DATA_BUSY (0x1<<9) ++ ++/* MCI_FIFOTH(0x4c) details */ ++#define BURST_SIZE (0x6<<28) ++#define RX_WMARK (0x7f<<16) ++#define TX_WMARK (0x80) ++ ++/* MCI_TUNING_CTRL(0x118) details */ ++#define HW_TUNING_EN (0x1 << 0) ++#define EDGE_CTRL (0x1 << 1) ++#define FOUND_EDGE (0x1 << 5) ++ ++#define DEFAULT_CMD_VALUE 0x20000000 ++ ++#endif +diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig +index 94b8210..13771e4 100644 +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -258,7 +258,7 @@ config INFTL + not use it. + + config RFD_FTL +- tristate "Resident Flash Disk (Flash Translation Layer) support" ++ tristate "Resident Flash Disk (Flash Translation Layer) support" + depends on BLOCK + select MTD_BLKDEVS + ---help--- +@@ -305,10 +305,59 @@ config MTD_SWAP + select MTD_BLKDEVS + help + Provides volatile block device driver on top of mtd partition +- suitable for swapping. The mapping of written blocks is not saved. ++ suitable for swapping. The mapping of written blocks is not saved. + The driver provides wear leveling by storing erase counter into the + OOB. + ++config HIFMC ++ bool "Enable HIFMC - Hisilicon Flash Memory Controller" ++ depends on MTD ++ default y if ARCH_HI3516CV300 ++ default y if ARCH_HI3519 ++ default y if ARCH_HI3519V101 ++ default y if ARCH_HI3516AV200 ++ default y if ARCH_HI3559 ++ default y if ARCH_HI3556 ++ default y if ARCH_HI3536C ++ default y if ARCH_HI3531D ++ default y if ARCH_HI3521D ++ help ++ Hisilicon Flash Memory Controller support SPI Nor SPI Nand and parallel ++ Nand Flash. often used on embedded chip. This option will provide the ++ generic support for FMC drivers to register ++ ++if HIFMC ++ ++config HIFMC_SPI_NAND ++ bool "Enable SPI nand flash Support on HIFMC" ++ depends on ARCH_HI3516CV300 || ARCH_HI3519 || ARCH_HI3519V101 || ARCH_HI3559 || ARCH_HI3556 || ARCH_HI3516AV200 || ARCH_HI3536C || ARCH_HI3521D || ARCH_HI3531D ++ select MTD_NAND ++ select HIFMC100_SPI_NAND ++ default y if ARCH_HI3516CV300 ++ default y if ARCH_HI3519 ++ default y if ARCH_HI3519V101 ++ default y if ARCH_HI3516AV200 ++ default y if ARCH_HI3559 ++ default y if ARCH_HI3556 ++ default y if ARCH_HI3536C ++ default y if ARCH_HI3531D ++ default y if ARCH_HI3521D ++ help ++ Hisilicon Flash Memory Controller is called hifmc for short. ++ This option enable hifmc support SPI nand flash. ++ If your enadle this option, HIFMC100_SPI_NAND should be select ++ ++config HIFMC_NAND ++ bool "Enable Nand flash Support on HIFMC" ++ select MTD_NAND ++ select HIFMC100_NAND ++ help ++ Hisilicon Flash Memory Controller is called hifmc for short. ++ This option enable hifmc support Nand flash. ++ If your choice this option, HIFMC100_NAND should be select ++ ++endif # End of HIFMC ++ + source "drivers/mtd/chips/Kconfig" + + source "drivers/mtd/maps/Kconfig" +diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile +index 99bb9a1..da61523 100644 +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile +@@ -7,8 +7,8 @@ obj-$(CONFIG_MTD) += mtd.o + mtd-y := mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o mtdchar.o + + obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o +-obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o +-obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o ++obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o ++obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o + obj-$(CONFIG_MTD_AFS_PARTS) += afs.o + obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o + obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o +@@ -30,7 +30,7 @@ obj-$(CONFIG_MTD_SWAP) += mtdswap.o + nftl-objs := nftlcore.o nftlmount.o + inftl-objs := inftlcore.o inftlmount.o + ++obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/ + obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/ + +-obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/ + obj-$(CONFIG_MTD_UBI) += ubi/ +diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile +index f0b0e61..da80a3d 100644 +--- a/drivers/mtd/devices/Makefile ++++ b/drivers/mtd/devices/Makefile +@@ -17,5 +17,4 @@ obj-$(CONFIG_MTD_SST25L) += sst25l.o + obj-$(CONFIG_MTD_BCM47XXSFLASH) += bcm47xxsflash.o + obj-$(CONFIG_MTD_ST_SPI_FSM) += st_spi_fsm.o + +- + CFLAGS_docg3.o += -I$(src) +diff --git a/drivers/mtd/devices/spi_ids.h b/drivers/mtd/devices/spi_ids.h +new file mode 100644 +index 0000000..f082969 +--- /dev/null ++++ b/drivers/mtd/devices/spi_ids.h +@@ -0,0 +1,185 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef SPI_IDSH ++#define SPI_IDSH ++ ++/*****************************************************************************/ ++ ++#define _1K (0x400) ++#define _2K (0x800) ++ ++#define _4K (0x1000) ++#define _8K (0x2000) ++#define _16K (0x4000) ++#define _32K (0x8000) ++ ++#define _64K (0x10000) ++#define _128K (0x20000) ++#define _256K (0x40000) ++#define _512K (0x80000) ++ ++#define _1M (0x100000) ++#define _2M (0x200000) ++#define _4M (0x400000) ++#define _8M (0x800000) ++ ++#define _16M (0x1000000) ++#define _32M (0x2000000) ++#define _64M (0x4000000) ++ ++#define INFINITE (0xFFFFFFFF) ++/*****************************************************************************/ ++ ++#define SPI_IF_READ_STD (0x01) ++#define SPI_IF_READ_FAST (0x02) ++#define SPI_IF_READ_DUAL (0x04) ++#define SPI_IF_READ_DUAL_ADDR (0x08) ++#define SPI_IF_READ_QUAD (0x10) ++#define SPI_IF_READ_QUAD_ADDR (0x20) ++ ++#define SPI_IF_WRITE_STD (0x01) ++#define SPI_IF_WRITE_DUAL (0x02) ++#define SPI_IF_WRITE_DUAL_ADDR (0x04) ++#define SPI_IF_WRITE_QUAD (0x08) ++#define SPI_IF_WRITE_QUAD_ADDR (0x10) ++ ++#define SPI_IF_ERASE_SECTOR (0x01) /* sector erase, 64K */ ++#define SPI_IF_ERASE_CHIP (0x02) /* chip erase */ ++#define SPI_IF_ERASE_4K (0x04) /* 4K */ ++#define SPI_IF_ERASE_8K (0x08) /* 8K */ ++ ++#define SPI_IF_ERASE_SECTOR_4K (0x01) /* 4K */ ++#define SPI_IF_ERASE_SECTOR_32K (0x02) /* 32K */ ++#define SPI_IF_ERASE_SECTOR_64K (0x04) /* 64K */ ++#define SPI_IF_ERASE_SECTOR_128K (0x08) /* 128K */ ++#define SPI_IF_ERASE_SECTOR_256K (0x10) /* 256K */ ++/*****************************************************************************/ ++#define SPI_CMD_BRWR (0x17) /*write value to BAR*/ ++#define SPI_EN4B_VALUE (0x80) /*the enable 4Byte addr len value*/ ++#define SPI_EX4B_VALUE (0x00) /*the disable 4Byte addr len value*/ ++#define SPI_4BYTE_ADDR_LEN (4) /*address len 4Byte*/ ++/*****************************************************************************/ ++ ++#define SPI_CMD_WREN 0x06 /* Write Enable */ ++#define SPI_CMD_WRDI 0x04 /* Write Disable */ ++/*****************************************************************************/ ++#define SPI_CMD_SE_4K 0x20 /* 4KB sector Erase */ ++#define SPI_CMD_SE_32K 0x52 /* 32KB sector Erase */ ++ ++#define SPI_CMD_SE_64K 0xD8 /* 64KB sector Erase */ ++#define SPI_CMD_SE_128K 0xD8 /* 128KB sector Erase */ ++#define SPI_CMD_SE_256K 0xD8 /* 256KB sector Erase */ ++ ++#define SPI_CMD_SE 0xD8 /* 64KB Sector Erase */ ++#define SPI_CMD_BE 0xC7 /* chip erase */ ++/*****************************************************************************/ ++#define SPI_CMD_WRSR 0x01 /* Write Status Register */ ++#define SPI_CMD_WRSR2 0x31 /* Write Status Register-2 */ ++#define SPI_CMD_WRSR3 0x11 /* Write Status Register-3 */ ++ ++#define SPI_CMD_RDSR 0x05 /* Read Status Register */ ++#define SPI_CMD_GET_FEATURES 0x0F /* Get Features */ ++#define SPI_CMD_SET_FEATURES 0x1F /* Set Features */ ++#define SPI_CMD_RDSR2 0x35 /* Read Status Register-2 */ ++#define SPI_CMD_RDSR3 0x15 /* Read Status Register-3 */ ++ ++#define SPI_CMD_RDCR 0x35 /* Read Config Register */ ++ ++#define SPI_CMD_RDID 0x9F /* Read Identification */ ++#define SPI_CMD_RESET 0xff /* Reset the device */ ++/*****************************************************************************/ ++#define SPI_CMD_PP 0x02 /* Page Programming */ ++#define SPI_CMD_WRITE_DUAL 0xA2 /* fast program dual input */ ++#define SPI_CMD_WRITE_QUAD 0x32 /* fast program quad input */ ++#define SPI_CMD_WRITE_DUAL_ADDR 0xD2 /* Dual I/O High Performance Write */ ++#define SPI_CMD_WRITE_QUAD_ADDR 0x12 /* Quad I/O High Performance Write */ ++/*****************************************************************************/ ++#define SPI_CMD_PAGE_READ 0x13 /* Page Read to Cache */ ++#define SPI_CMD_READ 0x03 /* Read Data bytes */ ++#define SPI_CMD_FAST_READ 0x0B /* Read Data Bytes at Higher Speed */ ++#define SPI_CMD_READ_DUAL 0x3B /* fast read dual output */ ++#define SPI_CMD_READ_QUAD 0x6B /* fast read quad output */ ++#define SPI_CMD_READ_DUAL_ADDR 0xBB /* Dual I/O High Performance Read */ ++#define SPI_CMD_READ_QUAD_ADDR 0xEB /* Quad I/O High Performance Read */ ++/*****************************************************************************/ ++#define SPI_CMD_SR_WIP 1 /* Write in Progress */ ++#define SPI_CMD_SR_WEL 2 /* Write Enable Latch */ ++#define SPI_CMD_SR_QE (1 << 9) /* quad enable */ ++#define SPI_CMD_SR_XQE (0 << 9) /* quad disable */ ++/*****************************************************************************/ ++#define SPI_CMD_EN4B 0xB7 /* enter 4 bytes mode and set 4 byte bit as '1' */ ++#define SPI_CMD_EX4B 0xE9 /* exit 4 bytes mode and clear 4 byte bit */ ++/*****************************************************************************/ ++ ++/*****************************************************************************/ ++#ifndef DBG_BUG ++#define DBG_BUG(fmt, args...) \ ++ do { \ ++ pr_err("%s(%d): BUG !!! " fmt, __FILE__, \ ++ __LINE__, ##args); \ ++ while (1) \ ++ ; \ ++ } while (0) ++#endif ++ ++/*****************************************************************************/ ++struct spi_operation { ++ unsigned char iftype; ++ unsigned char cmd; ++ unsigned char dummy; ++ unsigned int size; ++ unsigned int clock; ++}; ++ ++struct spi_info { ++ char *name; ++ ++ unsigned char id[8]; ++ unsigned int id_len; ++ ++ unsigned long chipsize; ++ unsigned int erasesize; ++ unsigned int addrcycle; ++ ++#define MAX_SPI_OP (8) ++ struct spi_operation *read[8]; ++ struct spi_operation *write[8]; ++ struct spi_operation *erase[8]; ++#ifndef CONFIG_MTD_HISFC300 ++ struct spi_driver *driver; ++#endif ++}; ++/*****************************************************************************/ ++ ++struct spi_info *spi_serach_ids(unsigned char ids[8]); ++ ++void spi_search_rw(struct spi_info *spiinfo, struct spi_operation *spiop_rw, ++ unsigned int iftype, unsigned int max_dummy, int is_read); ++ ++#ifndef CONFIG_MTD_HISFC300 ++void spi_get_erase(struct spi_info *spiinfo, struct spi_operation *spiop_erase); ++#else ++void spi_get_erase(struct spi_info *spiinfo, struct spi_operation *spiop_erase, ++ unsigned int *erasesize); ++#endif ++/******************************************************************************/ ++ ++extern struct spi_info spi_info_table[]; ++/******************************************************************************/ ++#endif /* SPI_IDSH */ +diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig +index dd10646..be09cf3 100644 +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -1,3 +1,10 @@ ++config MTD_NAND_IDS ++ tristate "Include chip ids for known NAND devices." ++ depends on MTD ++ help ++ Useful for NAND drivers that do not use the NAND subsystem but ++ still like to take advantage of the known chip information. ++ + config MTD_NAND_ECC + tristate + +@@ -109,9 +116,6 @@ config MTD_NAND_OMAP_BCH + config MTD_NAND_OMAP_BCH_BUILD + def_tristate MTD_NAND_OMAP2 && MTD_NAND_OMAP_BCH + +-config MTD_NAND_IDS +- tristate +- + config MTD_NAND_RICOH + tristate "Ricoh xD card reader" + default n +@@ -516,4 +520,21 @@ config MTD_NAND_XWAY + Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached + to the External Bus Unit (EBU). + ++config HISI_NAND_FS_MAY_NO_YAFFS2 ++ bool "Remove the restraintion of 16bit ecc type on yaffs2 to HiSilicon" ++ default n ++ help ++ The ecc type: 16bit is limited by the HiSilicon flash memory controller, ++ as the yaffs2 tag of hisi rootfs limits the min size of CTRL len is 28. ++ ++config HISI_NAND_ECC_STATUS_REPORT ++ bool "Report the ecc status to MTD for HiSilicon Nand Driver" ++ default n ++ help ++ Flash Memory Controller V100 reports the ecc status include ECC error ++ and ECC corrected to MTD to monitor the aging of devices. ++ ++source "drivers/mtd/nand/hinfc610/Kconfig" ++source "drivers/mtd/nand/hifmc100_nand/Kconfig" ++source "drivers/mtd/nand/hifmc100/Kconfig" + endif # MTD_NAND +diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile +index 9c847e4..63877fd 100644 +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -8,6 +8,9 @@ obj-$(CONFIG_MTD_NAND_BCH) += nand_bch.o + obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o + obj-$(CONFIG_MTD_SM_COMMON) += sm_common.o + ++obj-$(CONFIG_MTD_NAND_HINFC610) += hinfc610/ ++obj-$(CONFIG_HIFMC_NAND) += hifmc100_nand/ ++obj-$(CONFIG_HIFMC_SPI_NAND) += hifmc100/ + obj-$(CONFIG_MTD_NAND_CAFE) += cafe_nand.o + obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o + obj-$(CONFIG_MTD_NAND_DENALI) += denali.o +@@ -51,4 +54,4 @@ obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/ + obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o + obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ + +-nand-objs := nand_base.o nand_bbt.o nand_timings.o ++nand-objs := nand_base.o nand_bbt.o nand_timings.o hinfc_gen.o hinfc_spl_ids.o match_table.o +diff --git a/drivers/mtd/nand/hifmc100/Kconfig b/drivers/mtd/nand/hifmc100/Kconfig +new file mode 100644 +index 0000000..92a7c77 +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100/Kconfig +@@ -0,0 +1,79 @@ ++# ++# hisilicon flash memory controller SPI nand device driver version 100 ++# drivers/mtd/nand/hifmc100/Kconfig ++# add by hisilicon 2015.5.7 ++# ++ ++menuconfig HIFMC100_SPI_NAND ++ tristate "Hisilicon Flash Memory Controller v100 SPI Nand device Support" ++ depends on HIFMC ++ depends on MTD_NAND ++ depends on HIFMC_SPI_NAND ++ default n if ARCH_HI3516CV300 ++ default n if ARCH_HI3519 ++ default n if ARCH_HI3519V101 ++ default n if ARCH_HI3559 ++ default n if ARCH_HI3556 ++ default n if ARCH_HI3536C ++ default n if ARCH_HI3531D ++ default n if ARCH_HI3521D ++ select MISC_FILESYSTEMS ++ select MTD_BLOCK ++ help ++ Hisilicon Flash Memory Controller device version 100 driver Support ++ Hisilicon Flash Memory Controller version 100 is called hifmc100 for ++ short. The controller driver support registers and DMA transfers ++ while reading or writing the SPI nand flash. ++ ++if HIFMC100_SPI_NAND ++ ++config SPI_NAND_MAX_CHIP_NUM ++ int "Support max number of SPI Nand flash chip (1, 2)" ++ default 1 if ARCH_HI3516CV300 ++ default 1 if ARCH_HI3519 ++ default 1 if ARCH_HI3519V101 ++ default 1 if ARCH_HI3559 ++ default 1 if ARCH_HI3556 ++ default 1 if ARCH_HI3536C ++ default 1 if ARCH_HI3531D ++ default 1 if ARCH_HI3521D ++ help ++ flash memory controller v100 device only support 1 or 2 SPI nand flash ++ chip, your should not config other value. ++ ++choice ++ prompt "Page Size and Ecc Type Select" ++ default HIFMC100_AUTO_PAGESIZE_ECC if ARCH_HI3516CV300 ++ default HIFMC100_AUTO_PAGESIZE_ECC if ARCH_HI3519 ++ default HIFMC100_AUTO_PAGESIZE_ECC if ARCH_HI3519V101 ++ default HIFMC100_AUTO_PAGESIZE_ECC if ARCH_HI3559 ++ default HIFMC100_AUTO_PAGESIZE_ECC if ARCH_HI3556 ++ default HIFMC100_AUTO_PAGESIZE_ECC if ARCH_HI3536C ++ default HIFMC100_AUTO_PAGESIZE_ECC if ARCH_HI3531D ++ default HIFMC100_AUTO_PAGESIZE_ECC if ARCH_HI3521D ++ ++config HIFMC100_HARDWARE_PAGESIZE_ECC ++ bool "Hardware" ++ help ++ the configure of page size and ecc type lie on switch on the board. ++ so the page size and ecc type is controlled by Hardware see demo ++ board of SOC. ++ ++config HIFMC100_AUTO_PAGESIZE_ECC ++ bool "Auto" ++ help ++ auto-sensed the page size and ecc type value. driver will try each of ++ page size and ecc type one by one till flash can be read and wrote ++ accurately. so the page size and ecc type is match adaptively without ++ switch on the board ++ ++config HIFMC100_PAGESIZE_AUTO_ECC_NONE ++ bool "Pagesize Auto, Ecc None" ++ help ++ auto-sensed the page size and select ecc none. driver will try each ++ of page size one by one till flash can be read and wrote accurately. ++ so the page size is match adaptively without switch on the board ++ ++endchoice ++ ++endif # End of HIFMC100_SPI_NAND +diff --git a/drivers/mtd/nand/hifmc100/Makefile b/drivers/mtd/nand/hifmc100/Makefile +new file mode 100644 +index 0000000..72f7661 +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100/Makefile +@@ -0,0 +1,26 @@ ++# ++# The Flash Memory Controller v100 Device Driver for hisilicon ++# ++# Copyright (c) 2016 HiSilicon Technologies 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. ++# ++# 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, see . ++# ++# ++ ++# ++# drivers/mtd/nand/hifmc100/Makefile ++# ++ ++obj-$(CONFIG_HIFMC_SPI_NAND) += hifmc_spi_nand_ids.o ++obj-$(CONFIG_HIFMC100_SPI_NAND) += hifmc100.o hifmc100_os.o +diff --git a/drivers/mtd/nand/hifmc100/hifmc100.c b/drivers/mtd/nand/hifmc100/hifmc100.c +new file mode 100644 +index 0000000..c798bd0 +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100/hifmc100.c +@@ -0,0 +1,1174 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../hinfc_gen.h" ++#include "hifmc100_os.h" ++#include "hifmc100.h" ++#include ++ ++/*****************************************************************************/ ++static void hifmc100_switch_to_spi_nand(struct hifmc_host *host) ++{ ++ int reg; ++ ++ reg = hifmc_readl(host, FMC_CFG); ++ reg &= ~FLASH_TYPE_SEL_MASK; ++ reg |= FMC_CFG_FLASH_SEL(FLASH_TYPE_SPI_NAND); ++ hifmc_writel(host, FMC_CFG, reg); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_set_str_mode(struct hifmc_host *host) ++{ ++ int reg; ++ ++ reg = hifmc_readl(host, FMC_GLOBAL_CFG); ++ reg &= (~FMC_GLOBAL_CFG_DTR_MODE); ++ hifmc_writel(host, FMC_GLOBAL_CFG, reg); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_operation_config(struct hifmc_host *host, int op) ++{ ++ int ret, clkrate = 0; ++ struct hifmc_spi *spi = host->spi; ++ ++ hifmc100_switch_to_spi_nand(host); ++ clk_prepare_enable(host->clk); ++ switch (op) { ++ case OP_STYPE_WRITE: ++ clkrate = min((u_long)host->clkrate, ++ (u_long)CLK_FMC_TO_CRG_MHZ(spi->write->clock)); ++ break; ++ case OP_STYPE_READ: ++ clkrate = min((u_long)host->clkrate, ++ (u_long)CLK_FMC_TO_CRG_MHZ(spi->read->clock)); ++ break; ++ case OP_STYPE_ERASE: ++ clkrate = min((u_long)host->clkrate, ++ (u_long)CLK_FMC_TO_CRG_MHZ(spi->erase->clock)); ++ break; ++ default: ++ break; ++ } ++ ++ ret = clk_set_rate(host->clk, clkrate); ++ BUG_ON(ret); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_write(struct hifmc_host *host) ++{ ++ unsigned char pages_per_block_shift; ++ unsigned int reg, block_num, block_num_h, page_num; ++ struct hifmc_spi *spi = host->spi; ++ struct nand_chip *chip = host->chip; ++#ifdef HIFMC100_SPI_NAND_SUPPORT_REG_WRITE ++ const char *op = "Reg"; ++#else ++ const char *op = "Dma"; ++#endif ++ ++ if (WR_DBG) ++ pr_info("\n"); ++ FMC_PR(WR_DBG, "*-Start send %s page write command\n", op); ++ ++ mutex_lock(host->lock); ++ hifmc100_operation_config(host, OP_STYPE_WRITE); ++ ++ reg = spi->driver->wait_ready(spi); ++ if (reg) { ++ DB_MSG("Error: %s program wait ready failed! status: %#x\n", ++ op, reg); ++ goto end; ++ } ++ ++ reg = spi->driver->write_enable(spi); ++ if (reg) { ++ DB_MSG("Error: %s program write enable failed! reg: %#x\n", ++ op, reg); ++ goto end; ++ } ++ ++ reg = FMC_INT_CLR_ALL; ++ hifmc_writel(host, FMC_INT_CLR, reg); ++ FMC_PR(WR_DBG, "|-Set INT_CLR[%#x]%#x\n", FMC_INT_CLR, reg); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) ++ | OP_CFG_MEM_IF_TYPE(spi->write->iftype); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(WR_DBG, "|-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ pages_per_block_shift = chip->phys_erase_shift - chip->page_shift; ++ block_num = host->addr_value[1] >> pages_per_block_shift; ++ block_num_h = block_num >> REG_CNT_HIGH_BLOCK_NUM_SHIFT; ++ reg = FMC_ADDRH_SET(block_num_h); ++ hifmc_writel(host, FMC_ADDRH, reg); ++ FMC_PR(WR_DBG, "|-Set ADDRH[%#x]%#x\n", FMC_ADDRH, reg); ++ ++ page_num = host->addr_value[1] - (block_num << pages_per_block_shift); ++ reg = ((block_num & REG_CNT_BLOCK_NUM_MASK) << REG_CNT_BLOCK_NUM_SHIFT) ++ | ((page_num & REG_CNT_PAGE_NUM_MASK) << REG_CNT_PAGE_NUM_SHIFT); ++ hifmc_writel(host, FMC_ADDRL, reg); ++ FMC_PR(WR_DBG, "|-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg); ++ ++ *host->epm = 0x0000; ++ ++#ifndef HIFMC100_SPI_NAND_SUPPORT_REG_WRITE ++ reg = host->dma_buffer; ++ hifmc_writel(host, FMC_DMA_SADDR_D0, reg); ++ FMC_PR(WR_DBG, "|-Set DMA_SADDR_D[0x40]%#x\n", reg); ++ ++ reg = host->dma_oob; ++ hifmc_writel(host, FMC_DMA_SADDR_OOB, reg); ++ FMC_PR(WR_DBG, "|-Set DMA_SADDR_OOB[%#x]%#x\n", FMC_DMA_SADDR_OOB, reg); ++#endif ++ ++ reg = OP_CTRL_WR_OPCODE(spi->write->cmd) ++#ifdef HIFMC100_SPI_NAND_SUPPORT_REG_WRITE ++ | OP_CTRL_DMA_OP(OP_TYPE_REG) ++#else ++ | OP_CTRL_DMA_OP(OP_TYPE_DMA) ++#endif ++ | OP_CTRL_RW_OP(RW_OP_WRITE) ++ | OP_CTRL_DMA_OP_READY; ++ hifmc_writel(host, FMC_OP_CTRL, reg); ++ FMC_PR(WR_DBG, "|-Set OP_CTRL[%#x]%#x\n", FMC_OP_CTRL, reg); ++ ++ FMC_DMA_WAIT_INT_FINISH(host); ++ ++end: ++ mutex_unlock(host->lock); ++ FMC_PR(WR_DBG, "*-End %s page program!\n", op); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_status(struct hifmc_host *host) ++{ ++ unsigned char status, addr = STATUS_ADDR; ++ struct hifmc_spi *spi = host->spi; ++ ++ if (host->cmd_op.l_cmd == NAND_CMD_GET_FEATURES) ++ addr = PROTECT_ADDR; ++ ++ status = spi_nand_feature_op(spi, GET_OP, addr, 0); ++ FMC_PR((ER_DBG || WR_DBG), "\t*-Get status[%#x]: %#x\n", addr, status); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_read(struct hifmc_host *host) ++{ ++ unsigned char pages_per_block_shift, only_oob = 0; ++ unsigned short wrap = 0; ++ unsigned int reg, block_num, block_num_h, page_num, addr_of = 0; ++ struct hifmc_spi *spi = host->spi; ++ struct nand_chip *chip = host->chip; ++#ifdef HIFMC100_SPI_NAND_SUPPORT_REG_READ ++ char *op = "Reg"; ++#else ++ char *op = "Dma"; ++#endif ++ ++ if (RD_DBG) ++ pr_info("\n"); ++ FMC_PR(RD_DBG, "\t*-Start %s page read\n", op); ++ ++ if ((host->addr_value[0] == host->cache_addr_value[0]) ++ && (host->addr_value[1] == host->cache_addr_value[1])) { ++ FMC_PR(RD_DBG, "\t*-%s read cache hit, addr[%#x %#x]\n", ++ op, host->addr_value[1], host->addr_value[0]); ++ return; ++ } ++ ++ mutex_lock(host->lock); ++ hifmc100_operation_config(host, OP_STYPE_READ); ++ ++ FMC_PR(RD_DBG, "\t|-Wait ready before %s page read\n", op); ++ reg = spi->driver->wait_ready(spi); ++ if (reg) { ++ DB_MSG("Error: %s read wait ready fail! reg: %#x\n", op, reg); ++ goto end; ++ } ++ ++ reg = FMC_INT_CLR_ALL; ++ hifmc_writel(host, FMC_INT_CLR, reg); ++ FMC_PR(RD_DBG, "\t|-Set INT_CLR[%#x]%#x\n", FMC_INT_CLR, reg); ++ ++ if (host->cmd_op.l_cmd == NAND_CMD_READOOB) { ++ only_oob = 1; ++ host->cmd_op.op_cfg = OP_CTRL_RD_OP_SEL(RD_OP_READ_OOB); ++ } else ++ host->cmd_op.op_cfg = OP_CTRL_RD_OP_SEL(RD_OP_READ_ALL_PAGE); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) ++ | OP_CFG_MEM_IF_TYPE(spi->read->iftype) ++ | OP_CFG_DUMMY_NUM(spi->read->dummy); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(RD_DBG, "\t|-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ pages_per_block_shift = chip->phys_erase_shift - chip->page_shift; ++ block_num = host->addr_value[1] >> pages_per_block_shift; ++ block_num_h = block_num >> REG_CNT_HIGH_BLOCK_NUM_SHIFT; ++ ++ reg = FMC_ADDRH_SET(block_num_h); ++ hifmc_writel(host, FMC_ADDRH, reg); ++ FMC_PR(RD_DBG, "\t|-Set ADDRH[%#x]%#x\n", FMC_ADDRH, reg); ++ ++ page_num = host->addr_value[1] - (block_num << pages_per_block_shift); ++ if (only_oob) ++ switch (host->ecctype) { ++ case NAND_ECC_8BIT: ++ addr_of = REG_CNT_ECC_8BIT_OFFSET; ++ break; ++ case NAND_ECC_16BIT: ++ addr_of = REG_CNT_ECC_16BIT_OFFSET; ++ break; ++ case NAND_ECC_24BIT: ++ addr_of = REG_CNT_ECC_24BIT_OFFSET; ++ break; ++ case NAND_ECC_0BIT: ++ default: ++ break; ++ } ++ ++ reg = ((block_num & REG_CNT_BLOCK_NUM_MASK) << REG_CNT_BLOCK_NUM_SHIFT) ++ | ((page_num & REG_CNT_PAGE_NUM_MASK) << REG_CNT_PAGE_NUM_SHIFT) ++ | ((wrap & REG_CNT_WRAP_MASK) << REG_CNT_WRAP_SHIFT) ++ | (addr_of & REG_CNT_ECC_OFFSET_MASK); ++ hifmc_writel(host, FMC_ADDRL, reg); ++ FMC_PR(RD_DBG, "\t|-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg); ++ ++#ifndef HIFMC100_SPI_NAND_SUPPORT_REG_READ ++ reg = host->dma_buffer; ++ hifmc_writel(host, FMC_DMA_SADDR_D0, reg); ++ FMC_PR(RD_DBG, "\t|-Set DMA_SADDR_D0[%#x]%#x\n", FMC_DMA_SADDR_D0, reg); ++ ++ reg = host->dma_oob; ++ hifmc_writel(host, FMC_DMA_SADDR_OOB, reg); ++ FMC_PR(RD_DBG, "\t|-Set DMA_SADDR_OOB[%#x]%#x\n", FMC_DMA_SADDR_OOB, ++ reg); ++#endif ++ ++ reg = OP_CTRL_RD_OPCODE(spi->read->cmd) | host->cmd_op.op_cfg ++#ifdef HIFMC100_SPI_NAND_SUPPORT_REG_READ ++ | OP_CTRL_DMA_OP(OP_TYPE_REG) ++#else ++ | OP_CTRL_DMA_OP(OP_TYPE_DMA) ++#endif ++ | OP_CTRL_RW_OP(RW_OP_READ) | OP_CTRL_DMA_OP_READY; ++ hifmc_writel(host, FMC_OP_CTRL, reg); ++ FMC_PR(RD_DBG, "\t|-Set OP_CTRL[%#x]%#x\n", FMC_OP_CTRL, reg); ++ ++ FMC_DMA_WAIT_INT_FINISH(host); ++ ++ host->cache_addr_value[0] = host->addr_value[0]; ++ host->cache_addr_value[1] = host->addr_value[1]; ++ ++end: ++ mutex_unlock(host->lock); ++ FMC_PR(RD_DBG, "\t*-End %s page read\n", op); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_erase(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ struct hifmc_spi *spi = host->spi; ++ ++ if (ER_DBG) ++ pr_info("\n"); ++ FMC_PR(ER_DBG, "\t*-Start send cmd erase!\n"); ++ ++ mutex_lock(host->lock); ++ hifmc100_operation_config(host, OP_STYPE_ERASE); ++ ++ reg = spi->driver->wait_ready(spi); ++ FMC_PR(ER_DBG, "\t|-Erase wait ready, reg: %#x\n", reg); ++ if (reg) { ++ DB_MSG("Error: Erase wait ready fail! status: %#x\n", reg); ++ goto end; ++ } ++ ++ reg = spi->driver->write_enable(spi); ++ if (reg) { ++ DB_MSG("Error: Erase write enable failed! reg: %#x\n", reg); ++ goto end; ++ } ++ ++ reg = FMC_INT_CLR_ALL; ++ hifmc_writel(host, FMC_INT_CLR, reg); ++ FMC_PR(ER_DBG, "\t|-Set INT_CLR[%#x]%#x\n", FMC_INT_CLR, reg); ++ ++ reg = spi->erase->cmd; ++ hifmc_writel(host, FMC_CMD, FMC_CMD_CMD1(reg)); ++ FMC_PR(ER_DBG, "\t|-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ reg = FMC_ADDRL_BLOCK_H_MASK(host->addr_value[1]) ++ | FMC_ADDRL_BLOCK_L_MASK(host->addr_value[0]); ++ hifmc_writel(host, FMC_ADDRL, reg); ++ FMC_PR(ER_DBG, "\t|-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) ++ | OP_CFG_MEM_IF_TYPE(spi->erase->iftype) ++ | OP_CFG_ADDR_NUM(STD_OP_ADDR_NUM) ++ | OP_CFG_DUMMY_NUM(spi->erase->dummy); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(ER_DBG, "\t|-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ reg = FMC_OP_CMD1_EN ++ | FMC_OP_ADDR_EN ++ | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(ER_DBG, "\t|-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++end: ++ mutex_unlock(host->lock); ++ FMC_PR(ER_DBG, "\t*-End send cmd erase!\n"); ++} ++ ++/*****************************************************************************/ ++void hifmc100_ecc0_switch(struct hifmc_host *host, unsigned char op) ++{ ++ unsigned int config; ++#if EC_DBG ++ unsigned int cmp_cfg; ++ ++ config = hifmc_readl(host, FMC_CFG); ++ FMC_PR(EC_DBG, "\t *-Get CFG[%#x]%#x\n", FMC_CFG, config); ++ ++ if (op) ++ cmp_cfg = host->fmc_cfg; ++ else ++ cmp_cfg = host->fmc_cfg_ecc0; ++ ++ if (cmp_cfg != config) ++ DB_MSG("Warning: FMC config[%#x] is different.\n", ++ cmp_cfg); ++#endif ++ ++ if (op == ENABLE) ++ config = host->fmc_cfg_ecc0; ++ else if (op == DISABLE) ++ config = host->fmc_cfg; ++ else { ++ DB_MSG("Error: Invalid opcode: %d\n", op); ++ return; ++ } ++ ++ hifmc_writel(host, FMC_CFG, config); ++ FMC_PR(EC_DBG, "\t *-Set CFG[%#x]%#x\n", FMC_CFG, config); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_readid(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ FMC_PR(BT_DBG, "\t|*-Start send cmd read ID\n"); ++ ++ hifmc100_ecc0_switch(host, ENABLE); ++ ++ reg = FMC_CMD_CMD1(SPI_CMD_RDID); ++ hifmc_writel(host, FMC_CMD, reg); ++ FMC_PR(BT_DBG, "\t||-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ reg = READ_ID_ADDR; ++ hifmc_writel(host, FMC_ADDRL, reg); ++ FMC_PR(BT_DBG, "\t||-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) ++ | OP_CFG_ADDR_NUM(READ_ID_ADDR_NUM); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(BT_DBG, "\t||-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ reg = FMC_DATA_NUM_CNT(MAX_SPI_NAND_ID_LEN); ++ hifmc_writel(host, FMC_DATA_NUM, reg); ++ FMC_PR(BT_DBG, "\t||-Set DATA_NUM[%#x]%#x\n", FMC_DATA_NUM, reg); ++ ++ reg = FMC_OP_CMD1_EN ++ | FMC_OP_ADDR_EN ++ | FMC_OP_READ_DATA_EN ++ | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(BT_DBG, "\t||-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ host->addr_cycle = 0x0; ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++ hifmc100_ecc0_switch(host, DISABLE); ++ ++ FMC_PR(BT_DBG, "\t|*-End read flash ID\n"); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_reset(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ FMC_PR(BT_DBG, "\t|*-Start send cmd reset\n"); ++ ++ reg = FMC_CMD_CMD1(SPI_CMD_RESET); ++ hifmc_writel(host, FMC_CMD, reg); ++ FMC_PR(BT_DBG, "\t||-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(BT_DBG, "\t||-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ reg = FMC_OP_CMD1_EN | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(BT_DBG, "\t||-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++ FMC_PR(BT_DBG, "\t|*-End send cmd reset\n"); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_host_init(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ FMC_PR(BT_DBG, "\t||*-Start SPI Nand host init\n"); ++ ++ reg = hifmc_readl(host, FMC_CFG); ++ if ((reg & FMC_CFG_OP_MODE_MASK) == FMC_CFG_OP_MODE_BOOT) { ++ reg |= FMC_CFG_OP_MODE(FMC_CFG_OP_MODE_NORMAL); ++ hifmc_writel(host, FMC_CFG, reg); ++ FMC_PR(BT_DBG, "\t|||-Set CFG[%#x]%#x\n", FMC_CFG, reg); ++ } ++ ++ host->fmc_cfg = reg; ++ host->fmc_cfg_ecc0 = (reg & ~ECC_TYPE_MASK) | ECC_TYPE_0BIT; ++ ++ reg = hifmc_readl(host, FMC_GLOBAL_CFG); ++ if (reg & FMC_GLOBAL_CFG_WP_ENABLE) { ++ reg &= ~FMC_GLOBAL_CFG_WP_ENABLE; ++ hifmc_writel(host, FMC_GLOBAL_CFG, reg); ++ } ++ ++ host->addr_cycle = 0; ++ host->addr_value[0] = 0; ++ host->addr_value[1] = 0; ++ host->cache_addr_value[0] = ~0; ++ host->cache_addr_value[1] = ~0; ++ ++ host->send_cmd_write = hifmc100_send_cmd_write; ++ host->send_cmd_status = hifmc100_send_cmd_status; ++ host->send_cmd_read = hifmc100_send_cmd_read; ++ host->send_cmd_erase = hifmc100_send_cmd_erase; ++ host->send_cmd_readid = hifmc100_send_cmd_readid; ++ host->send_cmd_reset = hifmc100_send_cmd_reset; ++#ifdef CONFIG_PM ++ host->suspend = hifmc100_suspend; ++ host->resume = hifmc100_resume; ++#endif ++ ++ reg = TIMING_CFG_TCSH(CS_HOLD_TIME) ++ | TIMING_CFG_TCSS(CS_SETUP_TIME) ++ | TIMING_CFG_TSHSL(CS_DESELECT_TIME); ++ hifmc_writel(host, FMC_SPI_TIMING_CFG, reg); ++ ++ reg = ALL_BURST_ENABLE; ++ hifmc_writel(host, FMC_DMA_AHB_CTRL, reg); ++ ++ FMC_PR(BT_DBG, "\t||*-End SPI Nand host init\n"); ++} ++ ++/*****************************************************************************/ ++static unsigned char hifmc100_read_byte(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct hifmc_host *host = chip->priv; ++ unsigned char value, ret_val = 0; ++ ++ if (host->cmd_op.l_cmd == NAND_CMD_READID) { ++ value = hifmc_readb(host->iobase + host->offset); ++ host->offset++; ++ if (host->cmd_op.data_no == host->offset) ++ host->cmd_op.l_cmd = 0; ++ return value; ++ } ++ ++ if (host->cmd_op.cmd == NAND_CMD_STATUS) { ++ value = hifmc_readl(host, FMC_STATUS); ++ if (host->cmd_op.l_cmd == NAND_CMD_GET_FEATURES) { ++ FMC_PR((ER_DBG || WR_DBG), "\t\tRead BP status:%#x\n", ++ value); ++ if (ANY_BP_ENABLE(value)) ++ ret_val |= NAND_STATUS_WP; ++ ++ host->cmd_op.l_cmd = NAND_CMD_STATUS; ++ } ++ ++ if (!(value & STATUS_OIP_MASK)) ++ ret_val |= NAND_STATUS_READY; ++ ++ if (value & STATUS_E_FAIL_MASK) { ++ FMC_PR(ER_DBG, "\t\tGet erase status: %#x\n", value); ++ ret_val |= NAND_STATUS_FAIL; ++ } ++ ++ if (value & STATUS_P_FAIL_MASK) { ++ FMC_PR(WR_DBG, "\t\tGet write status: %#x\n", value); ++ ret_val |= NAND_STATUS_FAIL; ++ } ++ ++ return ret_val; ++ } ++ ++ if (host->cmd_op.l_cmd == NAND_CMD_READOOB) { ++ value = hifmc_readb(host->buffer + host->pagesize + host->offset); ++ host->offset++; ++ return value; ++ } ++ ++ host->offset++; ++ ++ return hifmc_readb(host->buffer + host->column + host->offset - 1); ++} ++ ++/*****************************************************************************/ ++static unsigned short hifmc100_read_word(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct hifmc_host *host = chip->priv; ++ ++ host->offset += 2; ++ return hifmc_readw(host->buffer + host->column + host->offset - 2); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_write_buf(struct mtd_info *mtd, ++ const u_char *buf, int len) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct hifmc_host *host = chip->priv; ++ ++#ifdef HIFMC100_SPI_NAND_SUPPORT_REG_WRITE ++ if (buf == chip->oob_poi) ++ memcpy((char *)host->iobase + host->pagesize, buf, len); ++ else ++ memcpy((char *)host->iobase, buf, len); ++#else ++ if (buf == chip->oob_poi) ++ memcpy((char *)(host->buffer + host->pagesize), buf, len); ++ else ++ memcpy((char *)host->buffer, buf, len); ++#endif ++ return; ++} ++ ++/*****************************************************************************/ ++static void hifmc100_read_buf(struct mtd_info *mtd, u_char *buf, int len) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct hifmc_host *host = chip->priv; ++ ++#ifdef HIFMC100_SPI_NAND_SUPPORT_REG_READ ++ if (buf == chip->oob_poi) ++ memcpy(buf, (char *)host->iobase + host->pagesize, len); ++ else ++ memcpy(buf, (char *)host->iobase, len); ++#else ++ if (buf == chip->oob_poi) ++ memcpy(buf, (char *)host->buffer + host->pagesize, len); ++ else ++ memcpy(buf, (char *)host->buffer, len); ++#endif ++ ++#ifdef CONFIG_HISI_NAND_ECC_STATUS_REPORT ++ if (buf != chip->oob_poi) { ++ u_int reg, ecc_step = host->pagesize >> 10; ++ ++ reg = hifmc_readl(host, HIFMC100_ECC_ERR_NUM0_BUF0); ++ while (ecc_step) { ++ u_char err_num; ++ ++ err_num = GET_ECC_ERR_NUM(--ecc_step, reg); ++ if (err_num == 0xff) ++ mtd->ecc_stats.failed++; ++ else ++ mtd->ecc_stats.corrected += err_num; ++ } ++ } ++#endif ++ ++ return; ++} ++ ++/*****************************************************************************/ ++static void hifmc100_select_chip(struct mtd_info *mtd, int chipselect) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct hifmc_host *host = chip->priv; ++ ++ if (chipselect < 0) { ++ mutex_unlock(&fmc_switch_mutex); ++ return; ++ } ++ ++ mutex_lock(&fmc_switch_mutex); ++ ++ if (chipselect > CONFIG_SPI_NAND_MAX_CHIP_NUM) ++ DB_BUG("Error: Invalid chipselect: %d\n", chipselect); ++ ++ if (host->mtd != mtd) { ++ host->mtd = mtd; ++ host->cmd_op.cs = chipselect; ++ } ++ ++ if (!(chip->options & NAND_BROKEN_XD)) { ++ if ((chip->state == FL_ERASING) || (chip->state == FL_WRITING)) ++ host->cmd_op.l_cmd = NAND_CMD_GET_FEATURES; ++ } ++} ++ ++/*****************************************************************************/ ++static void hifmc100_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned ctrl) ++{ ++ unsigned char cmd; ++ int is_cache_invalid = 1; ++ struct nand_chip *chip = mtd->priv; ++ struct hifmc_host *host = chip->priv; ++ ++ if (ctrl & NAND_ALE) { ++ unsigned int addr_value = 0; ++ unsigned int addr_offset = 0; ++ ++ if (ctrl & NAND_CTRL_CHANGE) { ++ host->addr_cycle = 0x0; ++ host->addr_value[0] = 0x0; ++ host->addr_value[1] = 0x0; ++ } ++ addr_offset = host->addr_cycle << 3; ++ ++ if (host->addr_cycle >= HIFMC100_ADDR_CYCLE_MASK) { ++ addr_offset = (host->addr_cycle - ++ HIFMC100_ADDR_CYCLE_MASK) << 3; ++ addr_value = 1; ++ } ++ ++ host->addr_value[addr_value] |= ++ ((dat & 0xff) << addr_offset); ++ ++ host->addr_cycle++; ++ } ++ ++ if ((ctrl & NAND_CLE) && (ctrl & NAND_CTRL_CHANGE)) { ++ cmd = dat & 0xff; ++ host->cmd_op.cmd = cmd; ++ switch (cmd) { ++ case NAND_CMD_PAGEPROG: ++ host->offset = 0; ++ host->send_cmd_write(host); ++ break; ++ ++ case NAND_CMD_READSTART: ++ is_cache_invalid = 0; ++ if (host->addr_value[0] == host->pagesize) ++ host->cmd_op.l_cmd = NAND_CMD_READOOB; ++ host->send_cmd_read(host); ++ break; ++ ++ case NAND_CMD_ERASE2: ++ host->send_cmd_erase(host); ++ break; ++ ++ case NAND_CMD_READID: ++ memset((u_char *)(host->iobase), 0, ++ MAX_SPI_NAND_ID_LEN); ++ host->cmd_op.l_cmd = cmd; ++ host->cmd_op.data_no = MAX_SPI_NAND_ID_LEN; ++ host->send_cmd_readid(host); ++ break; ++ ++ case NAND_CMD_STATUS: ++ host->send_cmd_status(host); ++ break; ++ ++ case NAND_CMD_READ0: ++ host->cmd_op.l_cmd = cmd; ++ break; ++ ++ case NAND_CMD_RESET: ++ host->send_cmd_reset(host); ++ break; ++ ++ case NAND_CMD_SEQIN: ++ case NAND_CMD_ERASE1: ++ default: ++ break; ++ } ++ } ++ ++ if ((dat == NAND_CMD_NONE) && host->addr_cycle) { ++ if (host->cmd_op.cmd == NAND_CMD_SEQIN ++ || host->cmd_op.cmd == NAND_CMD_READ0 ++ || host->cmd_op.cmd == NAND_CMD_READID) { ++ host->offset = 0x0; ++ host->column = (host->addr_value[0] & 0xffff); ++ } ++ } ++ ++ if (is_cache_invalid) { ++ host->cache_addr_value[0] = ~0; ++ host->cache_addr_value[1] = ~0; ++ } ++} ++ ++/*****************************************************************************/ ++static int hifmc100_dev_ready(struct mtd_info *mtd) ++{ ++ unsigned int reg; ++ unsigned long deadline = jiffies + FMC_MAX_READY_WAIT_JIFFIES; ++ struct nand_chip *chip = mtd->priv; ++ struct hifmc_host *host = chip->priv; ++ ++ do { ++ reg = OP_CFG_FM_CS(host->cmd_op.cs); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ ++ reg = FMC_OP_READ_STATUS_EN | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++ reg = hifmc_readl(host, FMC_STATUS); ++ ++ if (!(reg & STATUS_OIP_MASK)) ++ return NAND_STATUS_READY; ++ ++ cond_resched(); ++ ++ } while (!time_after_eq(jiffies, deadline)); ++ ++ if (!(chip->options & NAND_SCAN_SILENT_NODEV)) ++ pr_warn("Wait SPI nand ready timeout, status: %#x\n", reg); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++/* ++ * 'host->epm' only use the first oobfree[0] field, it looks very simple, But... ++ */ ++static struct nand_ecclayout nand_ecc_default = { ++ .oobfree = {{2, 30} } ++}; ++#ifdef CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 ++static struct nand_ecclayout nand_ecc_2k16bit = { ++ .oobfree = {{2, 6} } ++}; ++ ++static struct nand_ecclayout nand_ecc_4k16bit = { ++ .oobfree = {{2, 14} } ++}; ++#endif ++ ++/*****************************************************************************/ ++static struct nand_config_info hifmc_spi_nand_config_table[] = { ++ {NAND_PAGE_4K, NAND_ECC_24BIT, 200, &nand_ecc_default}, ++#ifdef CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 ++ {NAND_PAGE_4K, NAND_ECC_16BIT, 128, &nand_ecc_4k16bit}, ++#endif ++ {NAND_PAGE_4K, NAND_ECC_8BIT, 88, &nand_ecc_default}, ++ {NAND_PAGE_4K, NAND_ECC_0BIT, 32, &nand_ecc_default}, ++ ++ {NAND_PAGE_2K, NAND_ECC_24BIT, 128, &nand_ecc_default}, ++#ifdef CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 ++ {NAND_PAGE_2K, NAND_ECC_16BIT, 64, &nand_ecc_2k16bit}, ++#endif ++ {NAND_PAGE_2K, NAND_ECC_8BIT, 64, &nand_ecc_default}, ++ {NAND_PAGE_2K, NAND_ECC_0BIT, 32, &nand_ecc_default}, ++ ++ {0, 0, 0, NULL}, ++}; ++ ++/*****************************************************************************/ ++/* used the best correct arithmetic. */ ++static struct nand_config_info *hifmc100_get_best_ecc(struct mtd_info *mtd) ++{ ++ struct nand_config_info *best = NULL; ++ struct nand_config_info *info = hifmc_spi_nand_config_table; ++ ++ for (; info->layout; info++) { ++ if (match_page_type_to_size(info->pagetype) != mtd->writesize) ++ continue; ++ ++ if (mtd->oobsize < info->oobsize) ++ continue; ++ ++ if (!best || (best->ecctype < info->ecctype)) ++ best = info; ++ } ++ ++ if (!best) ++ DB_BUG(ERR_STR_DRIVER "pagesize: %d and oobsize: %d.\n", ++ mtd->writesize, mtd->oobsize); ++ return best; ++} ++ ++#if defined(CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE) \ ++ || defined(CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC) ++/*****************************************************************************/ ++/* force the pagesize and ecctype */ ++static struct nand_config_info *hifmc100_force_ecc(struct mtd_info *mtd, ++ int pagetype, int ecctype, char *cfgmsg, int allow_pagediv) ++{ ++ int pagesize; ++ struct nand_config_info *fit = NULL; ++ struct nand_config_info *info = hifmc_spi_nand_config_table; ++ ++ for (; info->layout; info++) { ++ if (info->pagetype == pagetype && info->ecctype == ecctype) { ++ fit = info; ++ break; ++ } ++ } ++ ++ if (!fit) { ++ DB_MSG("Driver(%s) can't find this configure\n", cfgmsg); ++ DB_BUG(ERR_STR_DRIVER "pagesize: %s, ecctype: %s\n", ++ nand_page_name(pagetype), nand_ecc_name(ecctype)); ++ return NULL; ++ } ++ ++ pagesize = match_page_type_to_size(pagetype); ++ if ((pagesize != mtd->writesize) ++ && (pagesize > mtd->writesize || !allow_pagediv)) { ++ DB_MSG("This SPI Nand Flash pageszie: %d\n", mtd->writesize); ++ DB_BUG("But (%s) configure pagesize: %d" ERR_STR_CHECK "\n", ++ cfgmsg, pagesize); ++ return NULL; ++ } ++ ++ if (fit->oobsize > mtd->oobsize) { ++ DB_MSG("This SPI Nand Flash offer space area is %dB\n", ++ mtd->oobsize); ++ DB_BUG("But (%s) the controller request %dB in ecc %s.", ++ cfgmsg, fit->oobsize, nand_ecc_name(ecctype)); ++ return NULL; ++ } ++ ++ return fit; ++} ++#endif ++ ++/*****************************************************************************/ ++static void hifmc100_chip_init(struct nand_chip *chip) ++{ ++ chip->read_byte = hifmc100_read_byte; ++ chip->read_word = hifmc100_read_word; ++ chip->write_buf = hifmc100_write_buf; ++ chip->read_buf = hifmc100_read_buf; ++ ++ chip->select_chip = hifmc100_select_chip; ++ ++ chip->cmd_ctrl = hifmc100_cmd_ctrl; ++ chip->dev_ready = hifmc100_dev_ready; ++ ++ chip->chip_delay = FMC_CHIP_DELAY; ++ ++ chip->options = NAND_NO_AUTOINCR | NAND_SKIP_BBTSCAN | NAND_BROKEN_XD ++ | NAND_SCAN_SILENT_NODEV; ++ ++ chip->ecc.layout = NULL; ++ chip->ecc.mode = NAND_ECC_NONE; ++} ++ ++/*****************************************************************************/ ++static int hifmc100_ecc_probe(struct mtd_info *mtd, struct nand_chip *chip, ++ struct nand_dev_t *nand_dev) ++{ ++ unsigned char page_reg, pagetype, ecc_reg, ecctype, block_reg = 0; ++ unsigned int reg, page_per_block; ++ char *start_type = "unknown"; ++ struct nand_config_info *best = NULL; ++ struct hifmc_host *host = chip->priv; ++ ++ FMC_PR(BT_DBG, "\t*-Start match PageSize and EccType\n"); ++ ++ reg = hifmc_readl(host, FMC_CFG); ++ FMC_PR(BT_DBG, "\t|-Get FMC_CFG[%#x] config: %#x\n", FMC_CFG, reg); ++ ++#ifdef CONFIG_HIFMC100_AUTO_PAGESIZE_ECC ++ best = hifmc100_get_best_ecc(mtd); ++ if (!best) ++ DB_BUG("Can't found any configure for SPI Nand Flash\n"); ++ ++ start_type = "Auto"; ++ ++ pagetype = best->pagetype; ++ ecctype = best->ecctype; ++ ++ page_reg = match_page_type_to_reg(pagetype); ++ reg &= ~PAGE_SIZE_MASK; ++ reg |= FMC_CFG_PAGE_SIZE(page_reg); ++ FMC_PR(BT_DBG, "\t|-%s Config, PageSize %s EccType %s OobSize %d\n", ++ start_type, nand_page_name(pagetype), ++ nand_ecc_name(ecctype), best->oobsize); ++ ++ ecc_reg = match_ecc_type_to_reg(ecctype); ++ reg &= ~ECC_TYPE_MASK; ++ reg |= FMC_CFG_ECC_TYPE(ecc_reg); ++ FMC_PR(BT_DBG, "\t|-%s Config best EccType: %s\n", start_type, ++ nand_ecc_name(best->ecctype)); ++ ++ page_per_block = mtd->erasesize / match_page_type_to_size(pagetype); ++ switch (page_per_block) { ++ case 64: ++ block_reg = BLOCK_SIZE_64_PAGE; ++ break; ++ case 128: ++ block_reg = BLOCK_SIZE_128_PAGE; ++ break; ++ case 256: ++ block_reg = BLOCK_SIZE_256_PAGE; ++ break; ++ case 512: ++ block_reg = BLOCK_SIZE_512_PAGE; ++ break; ++ default: ++ DB_MSG("Can't support block %#x and page %#x size\n", ++ mtd->erasesize, mtd->writesize); ++ } ++ reg &= ~BLOCK_SIZE_MASK; ++ reg |= FMC_CFG_BLOCK_SIZE(block_reg); ++ ++ hifmc_writel(host, FMC_CFG, reg); ++ FMC_PR(BT_DBG, "\t|-Set FMC_CFG[%#x] config: %#x\n", FMC_CFG, reg); ++#endif ++ ++ host->fmc_cfg = reg; ++ FMC_PR(BT_DBG, "\t|-Save FMC_CFG config: %#x\n", reg); ++ ++#ifdef CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC ++ #ifdef CONFIG_HIFMC100_AUTO_PAGESIZE_ECC ++ #error you SHOULD NOT define CONFIG_HIFMC100_AUTO_PAGESIZE_ECC \ ++ and CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC at the same time ++ #endif ++ ++ page_reg = (host->fmc_cfg & PAGE_SIZE_MASK) >> PAGE_SIZE_SHIFT; ++ pagetype = match_page_reg_to_type(page_reg); ++ FMC_PR(BT_DBG, "\t|-Get Hardware Config PageSize: %s\n", ++ nand_page_name(pagetype)); ++ ++ ecc_reg = (host->fmc_cfg & ECC_TYPE_MASK) >> ECC_TYPE_SHIFT; ++ ecctype = match_ecc_reg_to_type(ecc_reg); ++ FMC_PR(BT_DBG, "\t|-Get Hardware Config EccType: %s\n", ++ match_ecc_type_to_str(ecctype)); ++ ++ FMC_PR(BT_DBG, "\t|-Check FMC_CFG Config with Hardware Config\n"); ++ best = hifmc100_force_ecc(mtd, pagetype, ecctype, ++ "hardware config mode", 0); ++ if (!best) ++ DB_BUG("Can't found any configure for SPI Nand Flash\n"); ++ ++ start_type = "Hardware"; ++#endif ++ ++#ifdef CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE ++ ++ #ifdef CONFIG_HIFMC100_AUTO_PAGESIZE_ECC ++ #error you SHOULD NOT define CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE \ ++ and CONFIG_HIFMC100_AUTO_PAGESIZE_ECC at the same time ++ #endif ++ ++ #ifdef CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC ++ #error you SHOULD NOT define CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE \ ++ and CONFIG_HIFMC100_HARDWARE_PAGESIZE_ECC at the same time ++ #endif ++ ++ pagetype = match_page_size_to_type(mtd->writesize); ++ ++ best = hifmc100_force_ecc(mtd, pagetype, NAND_ECC_0BIT, ++ "force config mode", 0); ++ if (!best) ++ DB_BUG("Can't found any configure for SPI Nand Flash\n"); ++ ++ start_type = "AutoForce"; ++ FMC_PR(BT_DBG, "\t|-Check PageSize %s Config\n", start_type); ++ ++ page_reg = match_page_type_to_reg(best->pagetype); ++ ++ reg &= ~(PAGE_SIZE_MASK | ECC_TYPE_MASK); ++ reg |= FMC_CFG_PAGE_SIZE(page_reg); ++ reg |= FMC_CFG_ECC_TYPE(ECC_TYPE_0BIT); ++ host->fmc_cfg = reg; ++ FMC_PR(BT_DBG, "\t|-Save FMC_CFG config: %#x\n", reg); ++#endif /* End of CONFIG_HIFMC100_PAGESIZE_AUTO_ECC_NONE */ ++ ++ if (!best) ++ DB_BUG("Can't found any configure for SPI Nand Flash\n"); ++ ++ if (best->ecctype != NAND_ECC_0BIT) ++ mtd->oobsize = best->oobsize; ++ ++ chip->ecc.layout = best->layout; ++ ++ host->ecctype = best->ecctype; ++ host->pagesize = match_page_type_to_size(best->pagetype); ++ host->oobsize = mtd->oobsize; ++ ++ FMC_PR(BT_DBG, "\t|-%s Config end, best OOB Size: %d\n", start_type, ++ best->oobsize); ++ ++ host->block_page_mask = ((mtd->erasesize / mtd->writesize) - 1); ++ host->dma_oob = host->dma_buffer + host->pagesize; ++ host->bbm = (u_char *)(host->buffer + host->pagesize ++ + HIFMC_BAD_BLOCK_POS); ++ ++ /* EB bits locate in the bottom two of CTRL(30) */ ++ host->epm = (u_short *)(host->buffer + host->pagesize ++ + chip->ecc.layout->oobfree[0].offset + 28); ++ ++#ifdef CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 ++ if (best->ecctype == NAND_ECC_16BIT) { ++ if (host->pagesize == _2K) { ++ /* EB bits locate in the bottom two of CTRL(4) */ ++ host->epm = (u_short *)(host->buffer + host->pagesize ++ + chip->ecc.layout->oobfree[0].offset + 4); ++ } else if (host->pagesize == _4K) { ++ /* EB bit locate in the bottom two of CTRL(14) */ ++ host->epm = (u_short *)(host->buffer + host->pagesize ++ + chip->ecc.layout->oobfree[0].offset + 12); ++ } ++ } ++#endif ++ ++ host->fmc_cfg_ecc0 = (host->fmc_cfg & ~ECC_TYPE_MASK) | ECC_TYPE_0BIT; ++ ++ if (mtd->writesize > SPI_NAND_MAX_PAGESIZE ++ || mtd->oobsize > SPI_NAND_MAX_OOBSIZE) { ++ DB_MSG(ERR_STR_DRIVER "pageszie: %d and oobsize: %d\n", ++ mtd->writesize, mtd->oobsize); ++ DB_BUG("Please increase MAX PAGESIZE and OOBSIZE.\n"); ++ } ++ ++ if (mtd->writesize != host->pagesize) { ++ unsigned int shift = 0; ++ unsigned int writesize = mtd->writesize; ++ while (writesize > host->pagesize) { ++ writesize >>= 1; ++ shift++; ++ } ++ chip->chipsize = chip->chipsize >> shift; ++ mtd->erasesize = mtd->erasesize >> shift; ++ mtd->writesize = host->pagesize; ++ DB_MSG("SPI Nand divide into 1/%u\n", (1 << shift)); ++ } ++ ++ nand_dev->start_type = start_type; ++ nand_dev->oobsize = host->oobsize; ++ nand_dev->ecctype = host->ecctype; ++ ++ FMC_PR(BT_DBG, "\t*-End match PageSize and EccType\n"); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++int hifmc100_spi_nand_init(struct nand_chip *chip) ++{ ++ struct hifmc_host *host = chip->priv; ++ ++ FMC_PR(BT_DBG, "\t|*-Start hifmc100 SPI Nand init\n"); ++ ++ /* Set system clock and enable controller */ ++ clk_prepare_enable(host->clk); ++ ++ /* Switch SPI type to SPI nand */ ++ hifmc100_switch_to_spi_nand(host); ++ ++ /* hold on STR mode */ ++ hifmc100_set_str_mode(host); ++ ++ /* Hifmc host init */ ++ hifmc100_host_init(host); ++ host->chip = chip; ++ ++ /* Hifmc nand_chip struct init */ ++ hifmc100_chip_init(chip); ++ ++ hifmc_spi_nand_ids_register(); ++ hinfc_param_adjust = hifmc100_ecc_probe; ++ ++ FMC_PR(BT_DBG, "\t|*-End hifmc100 SPI Nand init\n"); ++ ++ return 0; ++} ++#ifdef CONFIG_PM ++/*****************************************************************************/ ++int hifmc100_suspend(struct platform_device *pltdev, pm_message_t state) ++{ ++ unsigned int ret; ++ struct hifmc_host *host = platform_get_drvdata(pltdev); ++ struct hifmc_spi *spi = host->spi; ++ ++ mutex_lock(host->lock); ++ hifmc100_switch_to_spi_nand(host); ++ ++ ret = spi->driver->wait_ready(spi); ++ if (ret) { ++ DB_MSG("Error: wait ready failed!"); ++ return 0; ++ } ++ ++ clk_disable_unprepare(host->clk); ++ mutex_unlock(host->lock); ++ ++ return 0; ++} ++/*****************************************************************************/ ++int hifmc100_resume(struct platform_device *pltdev) ++{ ++ int cs; ++ struct hifmc_host *host = platform_get_drvdata(pltdev); ++ struct nand_chip *chip = host->chip; ++ ++ mutex_lock(host->lock); ++ hifmc100_switch_to_spi_nand(host); ++ clk_prepare_enable(host->clk); ++ ++ for (cs = 0; cs < chip->numchips; cs++) ++ host->send_cmd_reset(host); ++ ++ hifmc100_spi_nand_config(host); ++ ++ mutex_unlock(host->lock); ++ return 0; ++} ++#endif ++ +diff --git a/drivers/mtd/nand/hifmc100/hifmc100.h b/drivers/mtd/nand/hifmc100/hifmc100.h +new file mode 100644 +index 0000000..7d04635 +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100/hifmc100.h +@@ -0,0 +1,386 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef __HIFMC100_H__ ++#define __HIFMC100_H__ ++ ++/*****************************************************************************/ ++#include ++#include ++ ++/*****************************************************************************/ ++#define INFINITE (0xFFFFFFFF) ++ ++/*****************************************************************************/ ++#define SPI_IF_READ_STD (0x01) ++#define SPI_IF_READ_FAST (0x02) ++#define SPI_IF_READ_DUAL (0x04) ++#define SPI_IF_READ_DUAL_ADDR (0x08) ++#define SPI_IF_READ_QUAD (0x10) ++#define SPI_IF_READ_QUAD_ADDR (0x20) ++ ++#define SPI_IF_WRITE_STD (0x01) ++#define SPI_IF_WRITE_DUAL (0x02) ++#define SPI_IF_WRITE_DUAL_ADDR (0x04) ++#define SPI_IF_WRITE_QUAD (0x08) ++#define SPI_IF_WRITE_QUAD_ADDR (0x10) ++ ++#define SPI_IF_ERASE_SECTOR_4K (0x01) ++#define SPI_IF_ERASE_SECTOR_32K (0x02) ++#define SPI_IF_ERASE_SECTOR_64K (0x04) ++#define SPI_IF_ERASE_SECTOR_128K (0x08) ++#define SPI_IF_ERASE_SECTOR_256K (0x10) ++ ++/******************************************************************************/ ++#define HIFMC_SPI_NAND_SUPPORT_READ (SPI_IF_READ_STD \ ++ | SPI_IF_READ_FAST \ ++ | SPI_IF_READ_DUAL \ ++ | SPI_IF_READ_DUAL_ADDR \ ++ | SPI_IF_READ_QUAD \ ++ | SPI_IF_READ_QUAD_ADDR) ++ ++#define HIFMC_SPI_NAND_SUPPORT_WRITE (SPI_IF_WRITE_STD | SPI_IF_WRITE_QUAD) ++ ++#define HIFMC_SPI_NAND_SUPPORT_MAX_DUMMY 8 ++ ++/*****************************************************************************/ ++#define SPI_CMD_READ_STD 0x03 /* Standard read cache */ ++#define SPI_CMD_READ_FAST 0x0B /* Higher speed read cache */ ++#define SPI_CMD_READ_DUAL 0x3B /* 2 IO read cache only date */ ++#define SPI_CMD_READ_DUAL_ADDR 0xBB /* 2 IO read cache date&addr */ ++#define SPI_CMD_READ_QUAD 0x6B /* 4 IO read cache only date */ ++#define SPI_CMD_READ_QUAD_ADDR 0xEB /* 4 IO read cache date&addr */ ++ ++#define SPI_CMD_WRITE_STD 0x02 /* Standard page program */ ++#define SPI_CMD_WRITE_DUAL 0xA2 /* 2 IO program only date */ ++#define SPI_CMD_WRITE_DUAL_ADDR 0xD2 /* 2 IO program date&addr */ ++#define SPI_CMD_WRITE_QUAD 0x32 /* 4 IO program only date */ ++#define SPI_CMD_WRITE_QUAD_ADDR 0x12 /* 4 IO program date&addr */ ++ ++#define SPI_CMD_SE_4K 0x20 /* 4KB sector Erase */ ++#define SPI_CMD_SE_32K 0x52 /* 32KB sector Erase */ ++#define SPI_CMD_SE_64K 0xD8 /* 64KB sector Erase */ ++#define SPI_CMD_SE_128K 0xD8 /* 128KB sector Erase */ ++#define SPI_CMD_SE_256K 0xD8 /* 256KB sector Erase */ ++ ++/*****************************************************************************/ ++#define SET_READ_STD(_dummy_, _size_, _clk_) \ ++ static struct spi_op read_std_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_STD, SPI_CMD_READ_STD, _dummy_, _size_, _clk_ } ++ ++#define SET_READ_FAST(_dummy_, _size_, _clk_) \ ++ static struct spi_op read_fast_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_FAST, SPI_CMD_READ_FAST, _dummy_, _size_, _clk_ } ++ ++#define SET_READ_DUAL(_dummy_, _size_, _clk_) \ ++ static struct spi_op read_dual_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_DUAL, SPI_CMD_READ_DUAL, _dummy_, _size_, _clk_ } ++ ++#define SET_READ_DUAL_ADDR(_dummy_, _size_, _clk_) \ ++ static struct spi_op read_dual_addr_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_DUAL_ADDR, SPI_CMD_READ_DUAL_ADDR, _dummy_, _size_, _clk_ } ++ ++#define SET_READ_QUAD(_dummy_, _size_, _clk_) \ ++ static struct spi_op read_quad_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_QUAD, SPI_CMD_READ_QUAD, _dummy_, _size_, _clk_ } ++ ++#define SET_READ_QUAD_ADDR(_dummy_, _size_, _clk_) \ ++ static struct spi_op read_quad_addr_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_READ_QUAD_ADDR, SPI_CMD_READ_QUAD_ADDR, _dummy_, _size_, _clk_ } ++ ++/*****************************************************************************/ ++#define SET_WRITE_STD(_dummy_, _size_, _clk_) \ ++ static struct spi_op write_std_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_WRITE_STD, SPI_CMD_WRITE_STD, _dummy_, _size_, _clk_ } ++ ++#define SET_WRITE_DUAL(_dummy_, _size_, _clk_) \ ++ static struct spi_op write_dual_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_WRITE_DUAL, SPI_CMD_WRITE_DUAL, _dummy_, _size_, _clk_ } ++ ++#define SET_WRITE_DUAL_ADDR(_dummy_, _size_, _clk_) \ ++ static struct spi_op write_dual_addr_##_dummy_##_size_##_clk_ = { \ ++SPI_IF_WRITE_DUAL_ADDR, SPI_CMD_WRITE_DUAL_ADDR, _dummy_, _size_, _clk_ } ++ ++#define SET_WRITE_QUAD(_dummy_, _size_, _clk_) \ ++ static struct spi_op write_quad_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_WRITE_QUAD, SPI_CMD_WRITE_QUAD, _dummy_, _size_, _clk_ } ++ ++#define SET_WRITE_QUAD_ADDR(_dummy_, _size_, _clk_) \ ++ static struct spi_op write_quad_addr_##_dummy_##_size_##_clk_ = { \ ++SPI_IF_WRITE_QUAD_ADDR, SPI_CMD_WRITE_QUAD_ADDR, _dummy_, _size_, _clk_ } ++ ++/*****************************************************************************/ ++#define SET_ERASE_SECTOR_4K(_dummy_, _size_, _clk_) \ ++ static struct spi_op erase_sector_4k_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_ERASE_SECTOR_4K, SPI_CMD_SE_4K, _dummy_, _size_, _clk_ } ++ ++#define SET_ERASE_SECTOR_32K(_dummy_, _size_, _clk_) \ ++ static struct spi_op erase_sector_32k_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_ERASE_SECTOR_32K, SPI_CMD_SE_32K, _dummy_, _size_, _clk_ } ++ ++#define SET_ERASE_SECTOR_64K(_dummy_, _size_, _clk_) \ ++ static struct spi_op erase_sector_64k_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_ERASE_SECTOR_64K, SPI_CMD_SE_64K, _dummy_, _size_, _clk_ } ++ ++#define SET_ERASE_SECTOR_128K(_dummy_, _size_, _clk_) \ ++ static struct spi_op erase_sector_128k_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_ERASE_SECTOR_128K, SPI_CMD_SE_128K, _dummy_, _size_, _clk_ } ++ ++#define SET_ERASE_SECTOR_256K(_dummy_, _size_, _clk_) \ ++ static struct spi_op erase_sector_256k_##_dummy_##_size_##_clk_ = { \ ++ SPI_IF_ERASE_SECTOR_256K, SPI_CMD_SE_256K, _dummy_, _size_, _clk_ } ++ ++/*****************************************************************************/ ++#define READ_STD(_dummy_, _size_, _clk_) read_std_##_dummy_##_size_##_clk_ ++#define READ_FAST(_dummy_, _size_, _clk_) read_fast_##_dummy_##_size_##_clk_ ++#define READ_DUAL(_dummy_, _size_, _clk_) read_dual_##_dummy_##_size_##_clk_ ++#define READ_DUAL_ADDR(_dummy_, _size_, _clk_) \ ++ read_dual_addr_##_dummy_##_size_##_clk_ ++#define READ_QUAD(_dummy_, _size_, _clk_) read_quad_##_dummy_##_size_##_clk_ ++#define READ_QUAD_ADDR(_dummy_, _size_, _clk_) \ ++ read_quad_addr_##_dummy_##_size_##_clk_ ++ ++/*****************************************************************************/ ++#define WRITE_STD(_dummy_, _size_, _clk_) write_std_##_dummy_##_size_##_clk_ ++#define WRITE_DUAL(_dummy_, _size_, _clk_) write_dual_##_dummy_##_size_##_clk_ ++#define WRITE_DUAL_ADDR(_dummy_, _size_, _clk_) \ ++ write_dual_addr_##_dummy_##_size_##_clk_ ++#define WRITE_QUAD(_dummy_, _size_, _clk_) write_quad_##_dummy_##_size_##_clk_ ++#define WRITE_QUAD_ADDR(_dummy_, _size_, _clk_) \ ++ write_quad_addr_##_dummy_##_size_##_clk_ ++ ++/*****************************************************************************/ ++#define ERASE_SECTOR_4K(_dummy_, _size_, _clk_) \ ++ erase_sector_4k_##_dummy_##_size_##_clk_ ++#define ERASE_SECTOR_32K(_dummy_, _size_, _clk_) \ ++ erase_sector_32k_##_dummy_##_size_##_clk_ ++#define ERASE_SECTOR_64K(_dummy_, _size_, _clk_) \ ++ erase_sector_64k_##_dummy_##_size_##_clk_ ++#define ERASE_SECTOR_128K(_dummy_, _size_, _clk_) \ ++ erase_sector_128k_##_dummy_##_size_##_clk_ ++#define ERASE_SECTOR_256K(_dummy_, _size_, _clk_) \ ++ erase_sector_256k_##_dummy_##_size_##_clk_ ++ ++/*****************************************************************************/ ++#define SPI_CMD_WREN 0x06 /* Write Enable */ ++#define SPI_CMD_WRDI 0x04 /* Write Disable */ ++ ++#define SPI_CMD_RDID 0x9F /* Read Identification */ ++ ++/*****************************************************************************/ ++#define SPI_CMD_GET_FEATURES 0x0F /* Get Features */ ++#define SPI_CMD_SET_FEATURE 0x1F /* Set Feature */ ++ ++#define SPI_CMD_PAGE_READ 0x13 /* Page Read to Cache */ ++ ++#define SPI_CMD_RESET 0xff /* Reset the device */ ++ ++/*****************************************************************************/ ++/* These macroes are for debug only, reg option is slower then dma option */ ++#undef HIFMC100_SPI_NAND_SUPPORT_REG_READ ++/* #define HIFMC100_SPI_NAND_SUPPORT_REG_READ */ ++ ++#undef HIFMC100_SPI_NAND_SUPPORT_REG_WRITE ++/* #define HIFMC100_SPI_NAND_SUPPORT_REG_WRITE */ ++ ++#ifdef CONFIG_HISI_NAND_ECC_STATUS_REPORT ++/*****************************************************************************/ ++#define HIFMC100_ECC_ERR_NUM0_BUF0 0xc0 ++ ++#define GET_ECC_ERR_NUM(_i, _reg) (((_reg) >> ((_i) * 8)) & 0xff) ++#endif ++/*****************************************************************************/ ++#define REG_CNT_HIGH_BLOCK_NUM_SHIFT 10 ++ ++#define REG_CNT_BLOCK_NUM_MASK 0x3ff ++#define REG_CNT_BLOCK_NUM_SHIFT 22 ++ ++#define REG_CNT_PAGE_NUM_MASK 0x3f ++#define REG_CNT_PAGE_NUM_SHIFT 16 ++ ++#define REG_CNT_WRAP_MASK 0xf ++#define REG_CNT_WRAP_SHIFT 12 ++ ++#define REG_CNT_ECC_OFFSET_MASK 0xfff ++#define REG_CNT_ECC_8BIT_OFFSET 1054 ++#define REG_CNT_ECC_16BIT_OFFSET 1056 ++#define REG_CNT_ECC_24BIT_OFFSET 1082 ++ ++#define ERR_STR_DRIVER "Driver does not support this configure " ++#define ERR_STR_CHECK "Please make sure the hardware configuration is correct" ++ ++/*****************************************************************************/ ++#define HIFMC100_ADDR_CYCLE_MASK 0x2 ++ ++/*****************************************************************************/ ++#define OP_STYPE_NONE 0x0 ++#define OP_STYPE_READ 0x01 ++#define OP_STYPE_WRITE 0x02 ++#define OP_STYPE_ERASE 0x04 ++#define CLK_FMC_TO_CRG_MHZ(_clk) ((_clk) * 2000000) ++ ++/*****************************************************************************/ ++#define MAX_SPI_OP 8 ++ ++/*****************************************************************************/ ++/* SPI general operation parameter */ ++struct spi_op { ++ unsigned char iftype; ++ unsigned char cmd; ++ unsigned char dummy; ++ unsigned int size; ++ unsigned int clock; ++}; ++ ++struct spi_drv; ++ ++/* SPI interface all operation */ ++struct hifmc_spi { ++ char *name; ++ int chipselect; ++ unsigned long long chipsize; ++ unsigned int erasesize; ++#define SPI_NOR_3BYTE_ADDR_LEN 3 /* address len 3Bytes */ ++#define SPI_NOR_4BYTE_ADDR_LEN 4 /* address len 4Bytes for 32MB */ ++ unsigned int addrcycle; ++ ++ struct spi_op read[1]; ++ struct spi_op write[1]; ++ struct spi_op erase[MAX_SPI_OP]; ++ ++ void *host; ++ ++ struct spi_drv *driver; ++}; ++ ++/* SPI interface special operation function hook */ ++struct spi_drv { ++ int (*wait_ready)(struct hifmc_spi *spi); ++ int (*write_enable)(struct hifmc_spi *spi); ++ int (*qe_enable)(struct hifmc_spi *spi); ++ int (*bus_prepare)(struct hifmc_spi *spi, int op); ++ int (*entry_4addr)(struct hifmc_spi *spi, int en); ++}; ++ ++struct spi_nand_info { ++ char *name; ++ unsigned char id[MAX_SPI_NAND_ID_LEN]; ++ unsigned char id_len; ++ unsigned long long chipsize; ++ unsigned int erasesize; ++ unsigned int pagesize; ++ unsigned int oobsize; ++#define BBP_LAST_PAGE 0x01 ++#define BBP_FIRST_PAGE 0x02 ++ unsigned int badblock_pos; ++ struct spi_op *read[MAX_SPI_OP]; ++ struct spi_op *write[MAX_SPI_OP]; ++ struct spi_op *erase[MAX_SPI_OP]; ++ struct spi_drv *driver; ++}; ++ ++/*****************************************************************************/ ++extern u_char spi_nand_feature_op(struct hifmc_spi *spi, u_char op, u_char addr, ++ u_char val); ++ ++/*****************************************************************************/ ++struct hifmc_host { ++ struct mtd_info *mtd; ++ struct nand_chip *chip; ++ struct hifmc_spi spi[CONFIG_SPI_NAND_MAX_CHIP_NUM]; ++ struct hifmc_cmd_op cmd_op; ++ ++ void __iomem *iobase; ++ void __iomem *regbase; ++ struct clk *clk; ++ u32 clkrate; ++ ++ unsigned int fmc_cfg; ++ unsigned int fmc_cfg_ecc0; ++ ++ unsigned int offset; ++ ++ struct device *dev; ++ struct mutex *lock; ++ ++ /* This is maybe an un-aligment address, only for malloc or free */ ++ char *buforg; ++ char *buffer; ++ ++ unsigned int dma_buffer; ++ unsigned int dma_oob; ++ ++ unsigned int addr_cycle; ++ unsigned int addr_value[2]; ++ unsigned int cache_addr_value[2]; ++ ++ unsigned int column; ++ unsigned int block_page_mask; ++ ++ unsigned int ecctype; ++ unsigned int pagesize; ++ unsigned int oobsize; ++ ++ int add_partition; ++ ++ int need_rr_data; ++#define HIFMC100_READ_RETRY_DATA_LEN 128 ++ char rr_data[HIFMC100_READ_RETRY_DATA_LEN]; ++ struct read_retry_t *read_retry; ++ ++ int version; ++ ++ /* BOOTROM read two bytes to detect the bad block flag */ ++#define HIFMC_BAD_BLOCK_POS 0 ++ unsigned char *bbm; /* nand bad block mark */ ++ unsigned short *epm; /* nand empty page mark */ ++ ++ unsigned int uc_er; ++ ++ void (*send_cmd_write)(struct hifmc_host *host); ++ void (*send_cmd_status)(struct hifmc_host *host); ++ void (*send_cmd_read)(struct hifmc_host *host); ++ void (*send_cmd_erase)(struct hifmc_host *host); ++ void (*send_cmd_readid)(struct hifmc_host *host); ++ void (*send_cmd_reset)(struct hifmc_host *host); ++#ifdef CONFIG_PM ++ int (*suspend)(struct platform_device *pltdev, pm_message_t state); ++ int (*resume)(struct platform_device *pltdev); ++#endif ++}; ++ ++/*****************************************************************************/ ++void hifmc100_ecc0_switch(struct hifmc_host *host, unsigned char op); ++ ++int hifmc100_spi_nand_init(struct nand_chip *chip); ++ ++/*****************************************************************************/ ++extern void hifmc_spi_nand_ids_register(void); ++ ++extern void hifmc_set_nand_system_clock(struct spi_op *op, int clk_en); ++ ++/*****************************************************************************/ ++#ifdef CONFIG_PM ++int hifmc100_suspend(struct platform_device *pltdev, pm_message_t state); ++int hifmc100_resume(struct platform_device *pltdev); ++void hifmc100_spi_nand_config(struct hifmc_host *host); ++#endif ++ ++#endif /* End of __HIFMC100_H__ */ +diff --git a/drivers/mtd/nand/hifmc100/hifmc100_os.c b/drivers/mtd/nand/hifmc100/hifmc100_os.c +new file mode 100644 +index 0000000..f699e8f +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100/hifmc100_os.c +@@ -0,0 +1,330 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "../../mtdcore.h" ++#include "hifmc100.h" ++#include "hifmc100_os.h" ++ ++/*****************************************************************************/ ++#define MAX_MTD_PARTITIONS (32) ++ ++struct partition_entry { ++ char name[16]; ++ unsigned long long start; ++ unsigned long long length; ++ unsigned int flags; ++}; ++ ++struct partition_info { ++ int parts_num; ++ struct partition_entry entry[MAX_MTD_PARTITIONS]; ++ struct mtd_partition parts[MAX_MTD_PARTITIONS]; ++}; ++ ++static struct partition_info ptn_info = {0}; ++ ++/*****************************************************************************/ ++static int __init parse_nand_partitions(const struct tag *tag) ++{ ++ int i, len; ++ ++ if (tag->hdr.size <= 2) { ++ pr_info("tag->hdr.size <= 2\n"); ++ return 0; ++ } ++ ++ len = sizeof(struct partition_entry) / sizeof(int); ++ ptn_info.parts_num = (tag->hdr.size - 2) / len; ++ ++ len = ptn_info.parts_num * sizeof(struct partition_entry); ++ memcpy(ptn_info.entry, &tag->u, len); ++ ++ for (i = 0; i < ptn_info.parts_num; i++) { ++ ptn_info.parts[i].name = ptn_info.entry[i].name; ++ ptn_info.parts[i].size = (ptn_info.entry[i].length); ++ ptn_info.parts[i].offset = (ptn_info.entry[i].start); ++ ptn_info.parts[i].mask_flags = 0; ++ ptn_info.parts[i].ecclayout = 0; ++ } ++ ++ return 0; ++} ++ ++/* turn to ascii is "HiNp" */ ++__tagtable(0x48694E70, parse_nand_partitions); ++ ++/*****************************************************************************/ ++static int hifmc100_spi_nand_pre_probe(struct nand_chip *chip) ++{ ++ uint8_t nand_maf_id; ++ struct hifmc_host *host = chip->priv; ++ ++ /* Reset the chip first */ ++ host->send_cmd_reset(host); ++ udelay(1000); ++ ++ /* Check the ID */ ++ host->offset = 0; ++ memset((unsigned char *)(chip->IO_ADDR_R), 0, 0x10); ++ host->send_cmd_readid(host); ++ nand_maf_id = hifmc_readb(chip->IO_ADDR_R); ++ ++ if (nand_maf_id == 0x00 || nand_maf_id == 0xff) { ++ printk("Cannot found a valid SPI Nand Device\n"); ++ return 1; ++ } ++ ++ return 0; ++} ++/*****************************************************************************/ ++static int hifmc_nand_scan(struct mtd_info *mtd) ++{ ++ int result = 0; ++ unsigned char cs, chip_num = CONFIG_SPI_NAND_MAX_CHIP_NUM; ++ struct nand_chip *chip = mtd->priv; ++ struct hifmc_host *host = chip->priv; ++ ++ for (cs = 0; chip_num && (cs < HIFMC_MAX_CHIP_NUM); cs++) { ++ if (hifmc_cs_user[cs]) { ++ FMC_PR(BT_DBG, "\t\t*-Current CS(%d) is occupied.\n", ++ cs); ++ continue; ++ } ++ ++ host->cmd_op.cs = cs; ++ ++ if (hifmc100_spi_nand_pre_probe(chip)) ++ return -ENODEV; ++ ++ FMC_PR(BT_DBG, "\t\t*-Scan SPI nand flash on CS: %d\n", cs); ++ if (nand_scan(mtd, chip_num)) ++ continue; ++ chip_num--; ++ } ++ ++ if (chip_num == CONFIG_SPI_NAND_MAX_CHIP_NUM) ++ result = -ENXIO; ++ else ++ result = 0; ++ ++ return result; ++} ++ ++/*****************************************************************************/ ++static int hifmc_os_add_paratitions(struct hifmc_host *host) ++{ ++ int ix; ++ int nr_parts = 0; ++ struct mtd_partition *parts = NULL; ++ int ret; ++ ++#ifdef CONFIG_MTD_CMDLINE_PARTS ++ static const char *part_probes[] = {"cmdlinepart", NULL, }; ++ nr_parts = parse_mtd_partitions(host->mtd, part_probes, &parts, 0); ++#endif ++ ++ /* (1) if nr_parts > 0, Using commandline partition definition ++ * (2) if nr_parts = 0, Using board partition definition, or parse ++ * the parameter from __tag. ++ */ ++ if (!nr_parts) { ++ nr_parts = ptn_info.parts_num; ++ parts = ptn_info.parts; ++ } ++ ++ if (nr_parts <= 0) ++ return 0; ++ ++ if (BT_DBG) ++ for (ix = 0; ix < nr_parts; ix++) { ++ DB_MSG("partitions[%d] = {.name = %s, ", ++ ix, parts[ix].name); ++ DB_MSG(".offset = 0x%.8x, .size = 0x%08x (%uMB) }\n", ++ (unsigned int)parts[ix].offset, ++ (unsigned int)parts[ix].size, ++ (unsigned int)parts[ix].size / (1024 * 1024)); ++ } ++ ++ host->add_partition = 1; ++ ++ ret = mtd_device_register(host->mtd, parts, nr_parts); ++ ++ return (1 == ret) ? -ENODEV : 0; ++} ++ ++/*****************************************************************************/ ++static int hisi_spi_nand_probe(struct platform_device *pltdev) ++{ ++ int len, result = 0; ++ struct hifmc_host *host; ++ struct nand_chip *chip; ++ struct mtd_info *mtd; ++ struct device *dev = &pltdev->dev; ++ struct device_node *np = NULL; ++ struct hisi_fmc *fmc = dev_get_drvdata(dev->parent); ++ ++ FMC_PR(BT_DBG, "\t*-Start SPI Nand flash driver probe\n"); ++ ++ len = sizeof(struct hifmc_host) + sizeof(struct nand_chip) ++ + sizeof(struct mtd_info); ++ host = devm_kzalloc(dev, len, GFP_KERNEL); ++ if (!host) ++ return -ENOMEM; ++ memset((char *)host, 0, len); ++ ++ platform_set_drvdata(pltdev, host); ++ host->dev = &pltdev->dev; ++ ++ host->chip = chip = (struct nand_chip *)&host[1]; ++ host->mtd = mtd = (struct mtd_info *)&chip[1]; ++ ++ host->regbase = fmc->regbase; ++ host->iobase = fmc->iobase; ++ host->clk = fmc->clk; ++ host->lock = &fmc->lock; ++ ++ memset((char *)host->iobase, 0xff, SPI_NAND_BUFFER_LEN); ++ chip->IO_ADDR_R = chip->IO_ADDR_W = host->iobase; ++ ++ host->buffer = dmam_alloc_coherent(host->dev, SPI_NAND_BUFFER_LEN, ++ &host->dma_buffer, GFP_KERNEL); ++ if (!host->buffer) { ++ DB_MSG("Error: Can't allocate memory for dma buffer."); ++ result = -EIO; ++ goto fail; ++ } ++ memset(host->buffer, 0xff, SPI_NAND_BUFFER_LEN); ++ ++ chip->priv = host; ++ result = hifmc100_spi_nand_init(chip); ++ if (result) { ++ FMC_PR(BT_DBG, "\t|-SPI Nand init failed, ret: %d\n", result); ++ result = -ENODEV; ++ goto fail; ++ } ++ ++ np = of_get_next_available_child(dev->of_node, NULL); ++ mtd->name = np->name; ++ mtd->type = MTD_NANDFLASH; ++ mtd->priv = chip; ++ mtd->owner = THIS_MODULE; ++ ++ result = of_property_read_u32(np, "spi-max-frequency", &host->clkrate); ++ if (result) ++ goto fail; ++ ++ result = hifmc_nand_scan(mtd); ++ if (result) { ++ FMC_PR(BT_DBG, "\t|-Scan SPI Nand failed.\n"); ++ goto fail; ++ } ++ ++ result = hifmc_os_add_paratitions(host); ++ if (host->add_partition) ++ goto end; ++ ++ if (!add_mtd_device(host->mtd)) { ++ result = 0; ++ goto end; ++ } ++ ++ result = -ENODEV; ++ DB_MSG("Error: MTD partition register failed! result: %d\n", ++ result); ++fail: ++ nand_release(mtd); ++ clk_disable_unprepare(host->clk); ++end: ++ FMC_PR(BT_DBG, "\t*-End driver probe, result: %d\n", result); ++ return result; ++} ++ ++/*****************************************************************************/ ++static int hisi_spi_nand_remove(struct platform_device *pltdev) ++{ ++ struct hifmc_host *host = platform_get_drvdata(pltdev); ++ ++ clk_disable_unprepare(host->clk); ++ nand_release(host->mtd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++/*****************************************************************************/ ++static int hifmc100_os_suspend(struct platform_device *pltdev, ++ pm_message_t state) ++{ ++ struct hifmc_host *host = platform_get_drvdata(pltdev); ++ ++ if (host && host->suspend) ++ return (host->suspend)(pltdev, state); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++static int hifmc100_os_resume(struct platform_device *pltdev) ++{ ++ struct hifmc_host *host = platform_get_drvdata(pltdev); ++ ++ if (host && host->resume) ++ return (host->resume)(pltdev); ++ ++ return 0; ++} ++#endif /* End of CONFIG_PM */ ++/*****************************************************************************/ ++static const struct of_device_id hisi_spi_nand_dt_ids[] = { ++ { .compatible = "hisilicon,hisi-spi-nand"}, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, hisi_spi_nand_dt_ids); ++ ++static struct platform_driver hisi_spi_nand_driver = { ++ .driver = { ++ .name = "hisi_spi_nand", ++ .of_match_table = hisi_spi_nand_dt_ids, ++ }, ++ .probe = hisi_spi_nand_probe, ++ .remove = hisi_spi_nand_remove, ++#ifdef CONFIG_PM ++ .suspend = hifmc100_os_suspend, ++ .resume = hifmc100_os_resume, ++#endif ++}; ++module_platform_driver(hisi_spi_nand_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("BVT_BSP"); ++MODULE_DESCRIPTION("Hisilicon Flash Memory Controller V100 SPI Nand Driver"); +diff --git a/drivers/mtd/nand/hifmc100/hifmc100_os.h b/drivers/mtd/nand/hifmc100/hifmc100_os.h +new file mode 100644 +index 0000000..9c720b4 +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100/hifmc100_os.h +@@ -0,0 +1,37 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef __HIFMC100_OS_H__ ++#define __HIFMC100_OS_H__ ++ ++/*****************************************************************************/ ++#ifndef CONFIG_SPI_NAND_MAX_CHIP_NUM ++ #define CONFIG_SPI_NAND_MAX_CHIP_NUM (1) ++ #warning NOT config CONFIG_SPI_NAND_MAX_CHIP_NUM, \ ++ used default value, maybe invalid. ++#endif ++ ++/*****************************************************************************/ ++#define SPI_NAND_MAX_PAGESIZE 4096 ++#define SPI_NAND_MAX_OOBSIZE 256 ++ ++#define SPI_NAND_BUFFER_LEN (SPI_NAND_MAX_PAGESIZE + SPI_NAND_MAX_OOBSIZE) ++ ++#endif /* End of __HIFMC100_OS_H__ */ +diff --git a/drivers/mtd/nand/hifmc100/hifmc100_spi_general.c b/drivers/mtd/nand/hifmc100/hifmc100_spi_general.c +new file mode 100644 +index 0000000..6fef356 +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100/hifmc100_spi_general.c +@@ -0,0 +1,260 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++/* ++ Send set/get features command to SPI Nand flash ++*/ ++u_char spi_nand_feature_op(struct hifmc_spi *spi, u_char op, u_char addr, ++ u_char val) ++{ ++ unsigned int reg; ++ const char *str[] = {"Get", "Set"}; ++ struct hifmc_host *host = (struct hifmc_host *)spi->host; ++ ++ if ((GET_OP == op) && (STATUS_ADDR == addr)) { ++ if (SR_DBG) ++ pr_info("\n"); ++ FMC_PR(SR_DBG, "\t\t|*-Start Get Status\n"); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(SR_DBG, "\t\t||-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ reg = FMC_OP_READ_STATUS_EN | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(SR_DBG, "\t\t||-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++ val = hifmc_readl(host, FMC_STATUS); ++ FMC_PR(SR_DBG, "\t\t|*-End Get Status, result: %#x\n", val); ++ ++ return val; ++ } ++ ++ FMC_PR(FT_DBG, "\t|||*-Start %s feature, addr[%#x]\n", str[op], addr); ++ ++ hifmc100_ecc0_switch(host, ENABLE); ++ ++ reg = FMC_CMD_CMD1(op ? SPI_CMD_SET_FEATURE : SPI_CMD_GET_FEATURES); ++ hifmc_writel(host, FMC_CMD, reg); ++ FMC_PR(FT_DBG, "\t||||-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ hifmc_writel(host, FMC_ADDRL, addr); ++ FMC_PR(FT_DBG, "\t||||-Set ADDRL[%#x]%#x\n", FMC_ADDRL, addr); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) ++ | OP_CFG_ADDR_NUM(FEATURES_OP_ADDR_NUM); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(FT_DBG, "\t||||-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ reg = FMC_DATA_NUM_CNT(FEATURES_DATA_LEN); ++ hifmc_writel(host, FMC_DATA_NUM, reg); ++ FMC_PR(FT_DBG, "\t||||-Set DATA_NUM[%#x]%#x\n", FMC_DATA_NUM, reg); ++ ++ reg = FMC_OP_CMD1_EN ++ | FMC_OP_ADDR_EN ++ | FMC_OP_REG_OP_START; ++ ++ if (SET_OP == op) { ++ reg |= FMC_OP_WRITE_DATA_EN; ++ hifmc_writeb(val, host->iobase); ++ FMC_PR(FT_DBG, "\t||||-Write IO[%#x]%#x\n", (u_int)host->iobase, ++ *(u_char *)host->iobase); ++ } else ++ reg |= FMC_OP_READ_DATA_EN; ++ ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(FT_DBG, "\t||||-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++ if (GET_OP == op) { ++ val = hifmc_readb(host->iobase); ++ FMC_PR(FT_DBG, "\t||||-Read IO[%#x]%#x\n", (u_int)host->iobase, ++ *(u_char *)host->iobase); ++ } ++ ++ hifmc100_ecc0_switch(host, DISABLE); ++ ++ FMC_PR(FT_DBG, "\t|||*-End %s Feature[%#x]:%#x\n", str[op], addr, val); ++ ++ return val; ++} ++ ++/*****************************************************************************/ ++/* ++ Read status[C0H]:[0]bit OIP, judge whether the device is busy or not ++*/ ++static int spi_general_wait_ready(struct hifmc_spi *spi) ++{ ++ unsigned char status; ++ unsigned long deadline = jiffies + FMC_MAX_READY_WAIT_JIFFIES; ++ struct hifmc_host *host = (struct hifmc_host *)spi->host; ++ ++ do { ++ status = spi_nand_feature_op(spi, GET_OP, STATUS_ADDR, 0); ++ if (!(status & STATUS_OIP_MASK)) { ++ if ((host->cmd_op.l_cmd == NAND_CMD_ERASE2) ++ && (status & STATUS_E_FAIL_MASK)) ++ return status; ++ if ((host->cmd_op.l_cmd == NAND_CMD_PAGEPROG) ++ && (status & STATUS_P_FAIL_MASK)) ++ return status; ++ return 0; ++ } ++ ++ cond_resched(); ++ ++ } while (!time_after_eq(jiffies, deadline)); ++ ++ DB_MSG("Error: SPI Nand wait ready timeout, status: %#x\n", status); ++ ++ return 1; ++} ++ ++/*****************************************************************************/ ++/* ++ Send write enable cmd to SPI Nand, status[C0H]:[2]bit WEL must be set 1 ++*/ ++static int spi_general_write_enable(struct hifmc_spi *spi) ++{ ++ unsigned int reg; ++ struct hifmc_host *host = (struct hifmc_host *)spi->host; ++ ++ if (WE_DBG) ++ pr_info("\n"); ++ FMC_PR(WE_DBG, "\t|*-Start Write Enable\n"); ++ ++ reg = spi_nand_feature_op(spi, GET_OP, STATUS_ADDR, 0); ++ if (reg & STATUS_WEL_MASK) { ++ FMC_PR(WE_DBG, "\t||-Write Enable was opened! reg: %#x\n", ++ reg); ++ return 0; ++ } ++ ++ reg = hifmc_readl(host, FMC_GLOBAL_CFG); ++ FMC_PR(WE_DBG, "\t||-Get GLOBAL_CFG[%#x]%#x\n", FMC_GLOBAL_CFG, reg); ++ if (reg & FMC_GLOBAL_CFG_WP_ENABLE) { ++ reg &= ~FMC_GLOBAL_CFG_WP_ENABLE; ++ hifmc_writel(host, FMC_GLOBAL_CFG, reg); ++ FMC_PR(WE_DBG, "\t||-Set GLOBAL_CFG[%#x]%#x\n", ++ FMC_GLOBAL_CFG, reg); ++ } ++ ++ reg = FMC_CMD_CMD1(SPI_CMD_WREN); ++ hifmc_writel(host, FMC_CMD, reg); ++ FMC_PR(WE_DBG, "\t||-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(WE_DBG, "\t||-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ reg = FMC_OP_CMD1_EN | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(WE_DBG, "\t||-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++#if WE_DBG ++ spi->driver->wait_ready(spi); ++ ++ reg = spi_nand_feature_op(spi, GET_OP, STATUS_ADDR, 0); ++ if (reg & STATUS_WEL_MASK) ++ FMC_PR(WE_DBG, "\t||-Write Enable success. reg: %#x\n", reg); ++ else { ++ DB_MSG("Error: Write Enable failed! reg: %#x\n", reg); ++ return reg; ++ } ++#endif ++ ++ FMC_PR(WE_DBG, "\t|*-End Write Enable\n"); ++ return 0; ++} ++ ++/*****************************************************************************/ ++/* ++ judge whether SPI Nand support QUAD read/write or not ++*/ ++static int spi_is_quad(struct hifmc_spi *spi) ++{ ++ const char *if_str[] = {"STD", "DUAL", "DIO", "QUAD", "QIO"}; ++ ++ FMC_PR(QE_DBG, "\t\t|||*-SPI read iftype: %s write iftype: %s\n", ++ if_str[spi->read->iftype], if_str[spi->write->iftype]); ++ ++ if ((IF_TYPE_QUAD == spi->read->iftype) ++ || (IF_TYPE_QIO == spi->read->iftype) ++ || (IF_TYPE_QUAD == spi->write->iftype) ++ || (IF_TYPE_QIO == spi->write->iftype)) ++ return 1; ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++/* ++ Send set features cmd to SPI Nand, feature[B0H]:[0]bit QE would be set ++*/ ++static int spi_general_qe_enable(struct hifmc_spi *spi) ++{ ++ unsigned int reg, op; ++ const char *str[] = {"Disable", "Enable"}; ++ ++ FMC_PR(QE_DBG, "\t||*-Start SPI Nand flash QE\n"); ++ ++ op = spi_is_quad(spi); ++ ++ FMC_PR(QE_DBG, "\t|||*-End Quad check, SPI Nand %s Quad.\n", str[op]); ++ ++ reg = spi_nand_feature_op(spi, GET_OP, FEATURE_ADDR, 0); ++ FMC_PR(QE_DBG, "\t|||-Get [%#x]feature: %#x\n", FEATURE_ADDR, reg); ++ if ((reg & FEATURE_QE_ENABLE) == op) { ++ FMC_PR(QE_DBG, "\t||*-SPI Nand quad was %sd!\n", str[op]); ++ return op; ++ } ++ ++ if (op == ENABLE) ++ reg |= FEATURE_QE_ENABLE; ++ else ++ reg &= ~FEATURE_QE_ENABLE; ++ ++ spi_nand_feature_op(spi, SET_OP, FEATURE_ADDR, reg); ++ FMC_PR(QE_DBG, "\t|||-SPI Nand %s Quad\n", str[op]); ++ ++ spi->driver->wait_ready(spi); ++ ++ reg = spi_nand_feature_op(spi, GET_OP, FEATURE_ADDR, 0); ++ if ((reg & FEATURE_QE_ENABLE) == op) ++ FMC_PR(QE_DBG, "\t|||-SPI Nand %s Quad succeed!\n", str[op]); ++ else ++ DB_MSG("Error: %s Quad failed! reg: %#x\n", str[op], reg); ++ ++ FMC_PR(QE_DBG, "\t||*-End SPI Nand %s Quad.\n", str[op]); ++ ++ return op; ++} ++ ++/****************************************************************************/ ++/* some spi nand flash don't QUAD enable */ ++static int spi_do_not_qe_enable(struct hifmc_spi *spi) ++{ ++ return 0; ++} +diff --git a/drivers/mtd/nand/hifmc100/hifmc_spi_nand_ids.c b/drivers/mtd/nand/hifmc100/hifmc_spi_nand_ids.c +new file mode 100644 +index 0000000..e3803a5 +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100/hifmc_spi_nand_ids.c +@@ -0,0 +1,1365 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../hinfc_gen.h" ++#include "hifmc100.h" ++ ++/*****************************************************************************/ ++SET_READ_STD(1, INFINITE, 24); ++ ++SET_READ_FAST(1, INFINITE, 75); ++SET_READ_FAST(1, INFINITE, 80); ++SET_READ_FAST(1, INFINITE, 104); ++SET_READ_FAST(1, INFINITE, 108); ++SET_READ_FAST(1, INFINITE, 120); ++ ++SET_READ_DUAL(1, INFINITE, 75); ++SET_READ_DUAL(1, INFINITE, 80); ++SET_READ_DUAL(1, INFINITE, 104); ++SET_READ_DUAL(1, INFINITE, 108); ++SET_READ_DUAL(1, INFINITE, 120); ++ ++SET_READ_DUAL_ADDR(1, INFINITE, 75); ++SET_READ_DUAL_ADDR(1, INFINITE, 80); ++SET_READ_DUAL_ADDR(1, INFINITE, 104); ++SET_READ_DUAL_ADDR(1, INFINITE, 108); ++SET_READ_DUAL_ADDR(1, INFINITE, 120); ++ ++SET_READ_QUAD(1, INFINITE, 75); ++SET_READ_QUAD(1, INFINITE, 80); ++SET_READ_QUAD(1, INFINITE, 104); ++SET_READ_QUAD(1, INFINITE, 108); ++SET_READ_QUAD(1, INFINITE, 120); ++ ++SET_READ_QUAD_ADDR(1, INFINITE, 75); ++SET_READ_QUAD_ADDR(2, INFINITE, 75); ++SET_READ_QUAD_ADDR(1, INFINITE, 80); ++SET_READ_QUAD_ADDR(2, INFINITE, 80); ++SET_READ_QUAD_ADDR(2, INFINITE, 104); ++SET_READ_QUAD_ADDR(1, INFINITE, 108); ++SET_READ_QUAD_ADDR(1, INFINITE, 120); ++ ++/*****************************************************************************/ ++SET_WRITE_STD(0, 256, 24); ++SET_WRITE_STD(0, 256, 75); ++SET_WRITE_STD(0, 256, 80); ++SET_WRITE_STD(0, 256, 104); ++ ++SET_WRITE_QUAD(0, 256, 75); ++SET_WRITE_QUAD(0, 256, 80); ++SET_WRITE_QUAD(0, 256, 104); ++SET_WRITE_QUAD(0, 256, 108); ++SET_WRITE_QUAD(0, 256, 120); ++ ++/*****************************************************************************/ ++SET_ERASE_SECTOR_128K(0, _128K, 24); ++SET_ERASE_SECTOR_128K(0, _128K, 75); ++SET_ERASE_SECTOR_128K(0, _128K, 80); ++SET_ERASE_SECTOR_128K(0, _128K, 104); ++ ++SET_ERASE_SECTOR_256K(0, _256K, 24); ++SET_ERASE_SECTOR_256K(0, _256K, 75); ++SET_ERASE_SECTOR_256K(0, _256K, 80); ++SET_ERASE_SECTOR_256K(0, _256K, 104); ++ ++/*****************************************************************************/ ++#include "hifmc100_spi_general.c" ++static struct spi_drv spi_driver_general = { ++ .wait_ready = spi_general_wait_ready, ++ .write_enable = spi_general_write_enable, ++ .qe_enable = spi_general_qe_enable, ++}; ++ ++static struct spi_drv spi_driver_no_qe = { ++ .wait_ready = spi_general_wait_ready, ++ .write_enable = spi_general_write_enable, ++ .qe_enable = spi_do_not_qe_enable, ++}; ++ ++/*****************************************************************************/ ++#define SPI_NAND_ID_TAB_VER "2.4" ++ ++/******* SPI Nand ID Table *************************************************** ++* Version Manufacturer Chip Name Size Operation ++* 1.0 ESMT F50L512M41A 64MB Add 5 chip ++* GD 5F1GQ4UAYIG 128MB ++* GD 5F2GQ4UAYIG 256MB ++* GD 5F4GQ4UAYIG 512MB ++* GD 5F4GQ4UBYIG 512MB ++* 1.1 ESMT F50L1G41A 128MB Add 2 chip ++* Winbond W25N01GV 128MB ++* 1.2 GD 5F1GQ4UBYIG 128MB Add 2 chip ++* GD 5F2GQ4UBYIG 256MB ++* 1.3 ATO ATO25D1GA 128MB Add 1 chip ++* 1.4 MXIC MX35LF1GE4AB 128MB Add 2 chip ++* MXIC MX35LF2GE4AB 256MB (SOP-16Pin) ++* 1.5 Paragon PN26G01A 128MB Add 1 chip ++* 1.6 All-flash AFS1GQ4UAC 128MB Add 1 chip ++* 1.7 TOSHIBA TC58CVG0S3H 128MB Add 2 chip ++* TOSHIBA TC58CVG2S0H 512MB ++* 1.8 ALL-flash AFS2GQ4UAD 256MB Add 2 chip ++* Paragon PN26G02A 256MB ++* 1.9 TOSHIBA TC58CVG1S3H 256MB Add 1 chip ++* 2.0 HeYangTek HYF1GQ4UAACAE 128MB Add 3 chip ++* HeYangTek HYF2GQ4UAACAE 256MB ++* HeYangTek HYF4GQ4UAACBE 512MB ++* 2.1 Micron MT29F1G01ABA 128MB Add 5 chip ++ Paragon 1.8V PN26Q01AWSIUG 128MB ++ TOSHIBA 1.8V TC58CYG0S3H 128MB ++ TOSHIBA 1.8V TC58CYG1S3H 256MB ++ TOSHIBA 1.8V TC58CYG2S0H 512MB ++* 2.2 Micron MT29F2G01ABA 256MB Add 1 chip ++* 2.3 MXIC MX35LF2G14AC 256MB Add 1 chip ++* 2.4 GD 1.8V 5F4GQ4RAYIG 512MB Add 1 chip ++* 2.5 Winbond W25N01GW 128MB Add 1 chip ++* MXIC MX35UF1G14AC 128MB Add 1 chip ++******************************************************************************/ ++struct spi_nand_info hifmc_spi_nand_flash_table[] = { ++ /* Micron MT29F1G01ABA 1GBit */ ++ { ++ .name = "MT29F1G01ABA", ++ .id = {0x2C, 0x14}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(2, INFINITE, 80), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 80), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* Micron MT29F2G01ABA 2GBit */ ++ { ++ .name = "MT29F2G01ABA", ++ .id = {0x2C, 0x24}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 108), ++ &READ_DUAL(1, INFINITE, 108), ++ &READ_DUAL_ADDR(1, INFINITE, 108), ++ &READ_QUAD(1, INFINITE, 108), ++ &READ_QUAD_ADDR(2, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 108), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 80), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* ESMT F50L512M41A 512Mbit */ ++ { ++ .name = "F50L512M41A", ++ .id = {0xC8, 0x20}, ++ .id_len = 2, ++ .chipsize = _64M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* ESMT F50L1G41A 1Gbit */ ++ { ++ .name = "F50L1G41A", ++ .id = {0xC8, 0x21}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* GD 5F1GQ4UAYIG 1Gbit */ ++ { ++ .name = "5F1GQ4UAYIG", ++ .id = {0xc8, 0xf1}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 120), ++ &READ_DUAL(1, INFINITE, 120), ++ &READ_DUAL_ADDR(1, INFINITE, 120), ++ &READ_QUAD(1, INFINITE, 120), ++ &READ_QUAD_ADDR(1, INFINITE, 120), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 120), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* GD 5F1GQ4UBYIG 1Gbit */ ++ { ++ .name = "5F1GQ4UBYIG", ++ .id = {0xc8, 0xd1}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 120), ++ &READ_DUAL(1, INFINITE, 120), ++ &READ_DUAL_ADDR(1, INFINITE, 120), ++ &READ_QUAD(1, INFINITE, 120), ++ &READ_QUAD_ADDR(1, INFINITE, 120), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 120), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* GD 5F2GQ4UAYIG 2Gbit */ ++ { ++ .name = "5F2GQ4UAYIG", ++ .id = {0xc8, 0xf2}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 120), ++ &READ_DUAL(1, INFINITE, 120), ++ &READ_DUAL_ADDR(1, INFINITE, 120), ++ &READ_QUAD(1, INFINITE, 120), ++ &READ_QUAD_ADDR(1, INFINITE, 120), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 120), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* GD 5F2GQ4UBYIG 2Gbit */ ++ { ++ .name = "5F2GQ4UBYIG", ++ .id = {0xc8, 0xd2}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 120), ++ &READ_DUAL(1, INFINITE, 120), ++ &READ_DUAL_ADDR(1, INFINITE, 120), ++ &READ_QUAD(1, INFINITE, 120), ++ &READ_QUAD_ADDR(1, INFINITE, 120), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 120), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* GD 5F4GQ4UAYIG 4Gbit */ ++ { ++ .name = "5F4GQ4UAYIG", ++ .id = {0xc8, 0xf4}, ++ .id_len = 2, ++ .chipsize = _512M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 120), ++ &READ_DUAL(1, INFINITE, 120), ++ &READ_DUAL_ADDR(1, INFINITE, 120), ++ &READ_QUAD(1, INFINITE, 120), ++ &READ_QUAD_ADDR(1, INFINITE, 120), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 120), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* GD 5F4GQ4UBYIG 4Gbit */ ++ { ++ .name = "5F4GQ4UBYIG", ++ .id = {0xc8, 0xd4}, ++ .id_len = 2, ++ .chipsize = _512M, ++ .erasesize = _256K, ++ .pagesize = _4K, ++ .oobsize = 256, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 120), ++ &READ_DUAL(1, INFINITE, 120), ++ &READ_DUAL_ADDR(1, INFINITE, 120), ++ &READ_QUAD(1, INFINITE, 120), ++ &READ_QUAD_ADDR(1, INFINITE, 120), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 120), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_256K(0, _256K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* GD 1.8V 5F4GQ4RAYIG 4Gbit */ ++ { ++ .name = "5F4GQ4RAYIG", ++ .id = {0xc8, 0xe4}, ++ .id_len = 2, ++ .chipsize = _512M, ++ .erasesize = _256K, ++ .pagesize = _4K, ++ .oobsize = 256, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 75), ++ &READ_DUAL(1, INFINITE, 75), ++ &READ_DUAL_ADDR(1, INFINITE, 75), ++ &READ_QUAD(1, INFINITE, 75), ++ &READ_QUAD_ADDR(1, INFINITE, 75), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 75), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_256K(0, _256K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* Winbond W25N01GV 1Gbit */ ++ { ++ .name = "W25N01GV", ++ .id = {0xef, 0xaa, 0x21}, ++ .id_len = 3, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_DUAL_ADDR(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ &READ_QUAD_ADDR(2, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* Winbond W25N01GW 1Gbit 1.8V */ ++ { ++ .name = "W25N01GW", ++ .id = {0xef, 0xba, 0x21}, ++ .id_len = 3, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 75), ++ &READ_DUAL(1, INFINITE, 75), ++ &READ_DUAL_ADDR(1, INFINITE, 75), ++ &READ_QUAD(1, INFINITE, 75), ++ &READ_QUAD_ADDR(2, INFINITE, 75), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 75), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* ATO ATO25D1GA 1Gbit */ ++ { ++ .name = "ATO25D1GA", ++ .id = {0x9b, 0x12}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* MXIC MX35LF1GE4AB 1Gbit */ ++ { ++ .name = "MX35LF1GE4AB", ++ .id = {0xc2, 0x12}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* MXIC MX35LF2GE4AB 2Gbit SOP-16Pin */ ++ { ++ .name = "MX35LF2GE4AB", ++ .id = {0xc2, 0x22}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* MXIC MX35LF2G14AC 2GBit */ ++ { ++ .name = "MX35LF2G14AC", ++ .id = {0xc2, 0x20}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* MXIC MX35UF1G14AC 1GBit 1.8V */ ++ { ++ .name = "MX35UF1G14AC", ++ .id = {0xc2, 0x90}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 64, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 75), ++ &READ_QUAD(1, INFINITE, 75), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 75), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* Paragon PN26G01AWSIUG 1Gbit 1.8V */ ++ { ++ .name = "PN26G01AW", ++ .id = {0xa1, 0xc1}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 75), ++ &READ_DUAL(1, INFINITE, 75), ++ &READ_DUAL_ADDR(1, INFINITE, 75), ++ &READ_QUAD(1, INFINITE, 75), ++ &READ_QUAD_ADDR(1, INFINITE, 75), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 75), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 75), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* Paragon PN26G01A 1Gbit */ ++ { ++ .name = "PN26G01A", ++ .id = {0xa1, 0xe1}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 108), ++ &READ_DUAL(1, INFINITE, 108), ++ &READ_DUAL_ADDR(1, INFINITE, 108), ++ &READ_QUAD(1, INFINITE, 108), ++ &READ_QUAD_ADDR(1, INFINITE, 108), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 108), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* Paragon PN26G02A 2Gbit */ ++ { ++ .name = "PN26G02A", ++ .id = {0xa1, 0xe2}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 108), ++ &READ_DUAL(1, INFINITE, 108), ++ &READ_DUAL_ADDR(1, INFINITE, 108), ++ &READ_QUAD(1, INFINITE, 108), ++ &READ_QUAD_ADDR(1, INFINITE, 108), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 108), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* All-flash AFS1GQ4UAC 1Gbit */ ++ { ++ .name = "AFS1GQ4UAC", ++ .id = {0xc1, 0x51}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(1, INFINITE, 80), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* All-flash AFS2GQ4UAD 2Gbit */ ++ { ++ .name = "AFS2GQ4UAD", ++ .id = {0xc1, 0x52}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(1, INFINITE, 80), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 24), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 24), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* TOSHIBA TC58CVG0S3H 1Gbit */ ++ { ++ .name = "TC58CVG0S3H", ++ .id = {0x98, 0xc2}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 104), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* TOSHIBA TC58CYG0S3H 1.8V 1Gbit */ ++ { ++ .name = "TC58CYG0S3H", ++ .id = {0x98, 0xb2}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 75), ++ &READ_DUAL(1, INFINITE, 75), ++ &READ_QUAD(1, INFINITE, 75), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 75), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 75), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* TOSHIBA TC58CVG1S3H 2Gbit */ ++ { ++ .name = "TC58CVG1S3H", ++ .id = {0x98, 0xcb}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 104), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* TOSHIBA TC58CYG1S3H 1.8V 2Gbit */ ++ { ++ .name = "TC58CYG1S3H", ++ .id = {0x98, 0xbb}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 75), ++ &READ_DUAL(1, INFINITE, 75), ++ &READ_QUAD(1, INFINITE, 75), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 75), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 75), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* TOSHIBA TC58CVG2S0H 4Gbit */ ++ { ++ .name = "TC58CVG2S0H", ++ .id = {0x98, 0xcd}, ++ .id_len = 2, ++ .chipsize = _512M, ++ .erasesize = _256K, ++ .pagesize = _4K, ++ .oobsize = 256, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 104), ++ &READ_DUAL(1, INFINITE, 104), ++ &READ_QUAD(1, INFINITE, 104), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 104), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_256K(0, _256K, 104), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* TOSHIBA TC58CYG2S0H 1.8V 4Gbit */ ++ { ++ .name = "TC58CYG2S0H", ++ .id = {0x98, 0xbd}, ++ .id_len = 2, ++ .chipsize = _512M, ++ .erasesize = _256K, ++ .pagesize = _4K, ++ .oobsize = 256, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 75), ++ &READ_DUAL(1, INFINITE, 75), ++ &READ_QUAD(1, INFINITE, 75), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 75), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_256K(0, _256K, 75), ++ 0 ++ }, ++ .driver = &spi_driver_no_qe, ++ }, ++ ++ /* HeYangTek HYF1GQ4UAACAE 1Gbit */ ++ { ++ .name = "HYF1GQ4UAACAE", ++ .id = {0xc9, 0x51}, ++ .id_len = 2, ++ .chipsize = _128M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(1, INFINITE, 80), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 80), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* HeYangTek HYF2GQ4UAACAE 2Gbit */ ++ { ++ .name = "HYF2GQ4UAACAE", ++ .id = {0xc9, 0x52}, ++ .id_len = 2, ++ .chipsize = _256M, ++ .erasesize = _128K, ++ .pagesize = _2K, ++ .oobsize = 128, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(1, INFINITE, 80), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_128K(0, _128K, 80), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ /* HeYangTek HYF4GQ4UAACBE 4Gbit */ ++ { ++ .name = "HYF4GQ4UAACBE", ++ .id = {0xc9, 0xd4}, ++ .id_len = 2, ++ .chipsize = _512M, ++ .erasesize = _256K, ++ .pagesize = _4K, ++ .oobsize = 256, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .read = { ++ &READ_STD(1, INFINITE, 24), ++ &READ_FAST(1, INFINITE, 80), ++ &READ_DUAL(1, INFINITE, 80), ++ &READ_DUAL_ADDR(1, INFINITE, 80), ++ &READ_QUAD(1, INFINITE, 80), ++ &READ_QUAD_ADDR(1, INFINITE, 80), ++ 0 ++ }, ++ .write = { ++ &WRITE_STD(0, 256, 80), ++ &WRITE_QUAD(0, 256, 80), ++ 0 ++ }, ++ .erase = { ++ &ERASE_SECTOR_256K(0, _256K, 80), ++ 0 ++ }, ++ .driver = &spi_driver_general, ++ }, ++ ++ { .id_len = 0, }, ++}; ++ ++/*****************************************************************************/ ++static void hifmc100_spi_nand_search_rw(struct spi_nand_info *spiinfo, ++ struct spi_op *spiop_rw, u_int iftype, u_int max_dummy, int rw_type) ++{ ++ int ix = 0; ++ struct spi_op **spiop, **fitspiop; ++ ++ for (fitspiop = spiop = (rw_type ? spiinfo->write : spiinfo->read); ++ (*spiop) && ix < MAX_SPI_OP; spiop++, ix++) { ++ if (((*spiop)->iftype & iftype) ++ && ((*spiop)->dummy <= max_dummy) ++ && (*fitspiop)->iftype < (*spiop)->iftype) ++ fitspiop = spiop; ++ } ++ memcpy(spiop_rw, (*fitspiop), sizeof(struct spi_op)); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_spi_nand_get_erase(struct spi_nand_info *spiinfo, ++ struct spi_op *spiop_erase) ++{ ++ int ix; ++ ++ spiop_erase->size = 0; ++ for (ix = 0; ix < MAX_SPI_OP; ix++) { ++ if (spiinfo->erase[ix] == NULL) ++ break; ++ if (spiinfo->erasesize == spiinfo->erase[ix]->size) { ++ memcpy(&spiop_erase[ix], spiinfo->erase[ix], ++ sizeof(struct spi_op)); ++ break; ++ } ++ } ++} ++ ++/*****************************************************************************/ ++static void hifmc100_map_spi_op(struct hifmc_spi *spi) ++{ ++ unsigned char ix; ++ const int iftype_read[] = { ++ SPI_IF_READ_STD, IF_TYPE_STD, ++ SPI_IF_READ_FAST, IF_TYPE_STD, ++ SPI_IF_READ_DUAL, IF_TYPE_DUAL, ++ SPI_IF_READ_DUAL_ADDR, IF_TYPE_DIO, ++ SPI_IF_READ_QUAD, IF_TYPE_QUAD, ++ SPI_IF_READ_QUAD_ADDR, IF_TYPE_QIO, ++ 0, 0, ++ }; ++ const int iftype_write[] = { ++ SPI_IF_WRITE_STD, IF_TYPE_STD, ++ SPI_IF_WRITE_QUAD, IF_TYPE_QUAD, ++ 0, 0, ++ }; ++ const char *if_str[] = {"STD", "DUAL", "DIO", "QUAD", "QIO"}; ++ ++ FMC_PR(BT_DBG, "\t||*-Start Get SPI operation iftype\n"); ++ ++ for (ix = 0; iftype_write[ix]; ix += 2) { ++ if (spi->write->iftype == iftype_write[ix]) { ++ spi->write->iftype = iftype_write[ix + 1]; ++ break; ++ } ++ } ++ FMC_PR(BT_DBG, "\t|||-Get best write iftype: %s \n", ++ if_str[spi->write->iftype]); ++ ++ for (ix = 0; iftype_read[ix]; ix += 2) { ++ if (spi->read->iftype == iftype_read[ix]) { ++ spi->read->iftype = iftype_read[ix + 1]; ++ break; ++ } ++ } ++ FMC_PR(BT_DBG, "\t|||-Get best read iftype: %s \n", ++ if_str[spi->read->iftype]); ++ ++ spi->erase->iftype = IF_TYPE_STD; ++ FMC_PR(BT_DBG, "\t|||-Get best erase iftype: %s \n", ++ if_str[spi->erase->iftype]); ++ ++ FMC_PR(BT_DBG, "\t||*-End Get SPI operation iftype \n"); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_spi_ids_probe(struct mtd_info *mtd, ++ struct spi_nand_info *spi_dev) ++{ ++ unsigned int reg; ++ struct nand_chip *chip = mtd->priv; ++ struct hifmc_host *host = chip->priv; ++ struct hifmc_spi *spi = host->spi; ++ ++ FMC_PR(BT_DBG, "\t|*-Start match SPI operation & chip init\n"); ++ ++ spi->host = host; ++ spi->name = spi_dev->name; ++ spi->driver = spi_dev->driver; ++ ++ hifmc100_spi_nand_search_rw(spi_dev, spi->read, ++ HIFMC_SPI_NAND_SUPPORT_READ, ++ HIFMC_SPI_NAND_SUPPORT_MAX_DUMMY, RW_OP_READ); ++ FMC_PR(BT_DBG, "\t||-Save spi->read op cmd:%#x\n", spi->read->cmd); ++ ++ hifmc100_spi_nand_search_rw(spi_dev, spi->write, ++ HIFMC_SPI_NAND_SUPPORT_WRITE, ++ HIFMC_SPI_NAND_SUPPORT_MAX_DUMMY, RW_OP_WRITE); ++ FMC_PR(BT_DBG, "\t||-Save spi->write op cmd:%#x\n", spi->write->cmd); ++ ++ hifmc100_spi_nand_get_erase(spi_dev, spi->erase); ++ FMC_PR(BT_DBG, "\t||-Save spi->erase op cmd:%#x\n", spi->erase->cmd); ++ ++ hifmc100_map_spi_op(spi); ++ ++ spi->driver->qe_enable(spi); ++ ++ /* Disable write protection */ ++ reg = spi_nand_feature_op(spi, GET_OP, PROTECT_ADDR, 0); ++ FMC_PR(BT_DBG, "\t||-Get protect status[%#x]: %#x\n", PROTECT_ADDR, ++ reg); ++ if (ANY_BP_ENABLE(reg)) { ++ reg &= ~ALL_BP_MASK; ++ spi_nand_feature_op(spi, SET_OP, PROTECT_ADDR, reg); ++ FMC_PR(BT_DBG, "\t||-Set [%#x]FT %#x\n", PROTECT_ADDR, reg); ++ ++ spi->driver->wait_ready(spi); ++ ++ reg = spi_nand_feature_op(spi, GET_OP, PROTECT_ADDR, 0); ++ FMC_PR(BT_DBG, "\t||-Check BP disable result: %#x\n", reg); ++ if (ANY_BP_ENABLE(reg)) ++ DB_MSG("Error: Write protection disable failed!\n"); ++ } ++ ++ /* Disable chip internal ECC */ ++ reg = spi_nand_feature_op(spi, GET_OP, FEATURE_ADDR, 0); ++ FMC_PR(BT_DBG, "\t||-Get feature status[%#x]: %#x\n", FEATURE_ADDR, ++ reg); ++ if (reg & FEATURE_ECC_ENABLE) { ++ reg &= ~FEATURE_ECC_ENABLE; ++ spi_nand_feature_op(spi, SET_OP, FEATURE_ADDR, reg); ++ FMC_PR(BT_DBG, "\t||-Set [%#x]FT: %#x\n", FEATURE_ADDR, reg); ++ ++ spi->driver->wait_ready(spi); ++ ++ reg = spi_nand_feature_op(spi, GET_OP, FEATURE_ADDR, 0); ++ FMC_PR(BT_DBG, "\t||-Check internal ECC disable result: %#x\n", ++ reg); ++ if (reg & FEATURE_ECC_ENABLE) ++ DB_MSG("Error: Chip internal ECC disable failed!\n"); ++ } ++ ++ hifmc_cs_user[host->cmd_op.cs]++; ++ ++ FMC_PR(BT_DBG, "\t|*-End match SPI operation & chip init\n"); ++} ++ ++static struct nand_flash_dev spi_nand_dev; ++/*****************************************************************************/ ++static struct nand_flash_dev *spi_nand_get_flash_info(struct mtd_info *mtd, ++ unsigned char *id) ++{ ++ unsigned char ix, len = 0; ++ char buffer[100]; ++ struct nand_chip *chip = mtd->priv; ++ struct hifmc_host *host = chip->priv; ++ struct spi_nand_info *spi_dev = hifmc_spi_nand_flash_table; ++ struct nand_flash_dev *type = &spi_nand_dev; ++ ++ FMC_PR(BT_DBG, "\t*-Start find SPI Nand flash\n"); ++ ++ len = sprintf(buffer, "SPI Nand(cs %d) ID: %#x %#x", ++ host->cmd_op.cs, id[0], id[1]); ++ ++ for (; spi_dev->id_len; spi_dev++) { ++ if (memcmp(id, spi_dev->id, spi_dev->id_len)) ++ continue; ++ ++ for (ix = 2; ix < spi_dev->id_len; ix++) ++ len += sprintf(buffer + len, " %#x", id[ix]); ++ pr_info("%s\n", buffer); ++ ++ FMC_PR(BT_DBG, "\t||-CS(%d) found SPI Nand: %s\n", ++ host->cmd_op.cs, spi_dev->name); ++ ++ type->name = spi_dev->name; ++ memcpy(type->id, spi_dev->id, spi_dev->id_len); ++ type->pagesize = spi_dev->pagesize; ++ type->chipsize = spi_dev->chipsize >> 20; ++ type->erasesize = spi_dev->erasesize; ++ type->id_len = spi_dev->id_len; ++ type->oobsize = spi_dev->oobsize; ++ FMC_PR(BT_DBG, "\t|-Save struct nand_flash_dev info\n"); ++ ++ mtd->size = spi_dev->chipsize; ++ ++ hifmc100_spi_ids_probe(mtd, spi_dev); ++ ++ FMC_PR(BT_DBG, "\t*-Found SPI nand: %s\n", spi_dev->name); ++ ++ return type; ++ } ++ ++ FMC_PR(BT_DBG, "\t*-Not found SPI nand flash, %s\n", buffer); ++ ++ return NULL; ++} ++ ++/*****************************************************************************/ ++void hifmc_spi_nand_ids_register(void) ++{ ++ pr_info("SPI Nand ID Table Version %s\n", SPI_NAND_ID_TAB_VER); ++ get_spi_nand_flash_type_hook = spi_nand_get_flash_info; ++} ++ ++#ifdef CONFIG_PM ++/*****************************************************************************/ ++void hifmc100_spi_nand_config(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ struct hifmc_spi *spi = host->spi; ++ static const char const *str[] = {"STD", "DUAL", "DIO", "QUAD", "QIO"}; ++ ++ /* judge whether support QUAD read/write or not, set it if yes */ ++ FMC_PR(PM_DBG, "\t|-SPI read iftype: %s write iftype: %s\n", ++ str[spi->read->iftype], str[spi->write->iftype]); ++ spi->driver->qe_enable(spi); ++ ++ /* Disable write protection */ ++ reg = spi_nand_feature_op(spi, GET_OP, PROTECT_ADDR, 0); ++ FMC_PR(PM_DBG, "\t|-Get protect status[%#x]: %#x\n", PROTECT_ADDR, ++ reg); ++ if (ANY_BP_ENABLE(reg)) { ++ reg &= ~ALL_BP_MASK; ++ spi_nand_feature_op(spi, SET_OP, PROTECT_ADDR, reg); ++ FMC_PR(PM_DBG, "\t|-Set [%#x]FT %#x\n", PROTECT_ADDR, reg); ++ ++ spi->driver->wait_ready(spi); ++ ++ reg = spi_nand_feature_op(spi, GET_OP, PROTECT_ADDR, 0); ++ FMC_PR(PM_DBG, "\t|-Check BP disable result: %#x\n", reg); ++ if (ANY_BP_ENABLE(reg)) ++ DB_MSG("Error: Write protection disable failed!\n"); ++ } ++ ++ /* Disable chip internal ECC */ ++ reg = spi_nand_feature_op(spi, GET_OP, FEATURE_ADDR, 0); ++ FMC_PR(PM_DBG, "\t|-Get feature status[%#x]: %#x\n", FEATURE_ADDR, ++ reg); ++ if (reg & FEATURE_ECC_ENABLE) { ++ reg &= ~FEATURE_ECC_ENABLE; ++ spi_nand_feature_op(spi, SET_OP, FEATURE_ADDR, reg); ++ FMC_PR(PM_DBG, "\t|-Set [%#x]FT: %#x\n", FEATURE_ADDR, reg); ++ ++ spi->driver->wait_ready(spi); ++ ++ reg = spi_nand_feature_op(spi, GET_OP, FEATURE_ADDR, 0); ++ FMC_PR(PM_DBG, "\t|-Check internal ECC disable result: %#x\n", ++ reg); ++ if (reg & FEATURE_ECC_ENABLE) ++ DB_MSG("Error: Chip internal ECC disable failed!\n"); ++ } ++} ++/*****************************************************************************/ ++#endif /* CONFIG_PM */ +diff --git a/drivers/mtd/nand/hifmc100_nand/Kconfig b/drivers/mtd/nand/hifmc100_nand/Kconfig +new file mode 100644 +index 0000000..976db6a +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100_nand/Kconfig +@@ -0,0 +1,104 @@ ++# ++# drivers/mtd/nand/hifmc100_nand/Kconfig ++# add by hisilicon 2015.5.7 ++# ++ ++menuconfig HIFMC100_NAND ++ tristate "Hisilicon Flash Memory Controller v100 Nand device Support" ++ depends on HIFMC ++ depends on MTD_NAND ++ default n if ARCH_HI3519 ++ default n if ARCH_HI3519V101 ++ default n if ARCH_HI3559 ++ default n if ARCH_HI3556 ++ select MISC_FILESYSTEMS ++ select MTD_BLOCK ++ help ++ Hisilicon Flash Memory Controller device version 100 driver Support ++ Hisilicon Flash Memory Controller version 100 is called hifmc100 for ++ short. The controller support DMA transfers while reading or writing ++ the Nand flash. ++ ++if HIFMC100_NAND ++ ++config HIFMC100_MAX_NAND_CHIP ++ int "number of Nand flash chip (1, 2)" ++ default 1 if ARCH_HI3519 ++ default 1 if ARCH_HI3519V101 ++ default 1 if ARCH_HI3559 ++ default 1 if ARCH_HI3556 ++ help ++ flash memory controller v100 device only support 1 or 2 Nand flash ++ chip, your should not config other value. ++ ++config HIFMC100_NAND_EDO_MODE ++ bool "the Extended Data Out(EDO) mode" ++ help ++ In Extended data out (EDO), a new data cycle is started while the data ++ output of the previous cycle is still active. This process of cycle ++ overlapping, called pipelining, increases processing speed by about ++ 10 nanoseconds per cycle,increasing computer performance by about 5 ++ percent compared to performance using FMP. ++ ++config RW_H_WIDTH ++ int "the width of Read/Write HIGH Hold Time (0 to 15)" ++ range 0 15 ++ default 10 if ARCH_HI3519 ++ default 10 if ARCH_HI3519V101 ++ default 10 if ARCH_HI3559 ++ default 10 if ARCH_HI3556 ++ help ++ the Read/Write HIGH Hold Time of nand flash ++ ++config R_L_WIDTH ++ int "the Read pulse width (0 to 15)" ++ range 0 15 ++ default 10 if ARCH_HI3519 ++ default 10 if ARCH_HI3519V101 ++ default 10 if ARCH_HI3559 ++ default 10 if ARCH_HI3556 ++ help ++ the Read/Write LOW Hold Time of nand flash ++ ++config W_L_WIDTH ++ int "the Write pulse width (0 to 15)" ++ range 0 15 ++ default 10 if ARCH_HI3519 ++ default 10 if ARCH_HI3519V101 ++ default 10 if ARCH_HI3559 ++ default 10 if ARCH_HI3556 ++ help ++ the Read/Write LOW Hold Time of nand flash ++ ++choice ++ prompt "Page Size and Ecc Type Select" ++ default HIFMC100_NAND_AUTO_PAGESIZE_ECC if ARCH_HI3519 ++ default HIFMC100_NAND_AUTO_PAGESIZE_ECC if ARCH_HI3519V101 ++ default HIFMC100_NAND_AUTO_PAGESIZE_ECC if ARCH_HI3559 ++ default HIFMC100_NAND_AUTO_PAGESIZE_ECC if ARCH_HI3556 ++ ++config HIFMC100_NAND_HARDWARE_PAGESIZE_ECC ++ bool "Hardware" ++ help ++ the configure of page size and ecc type lie on switch on the board. ++ so the page size and ecc type is controlled by Hardware see demo ++ board of SOC. ++ ++config HIFMC100_NAND_AUTO_PAGESIZE_ECC ++ bool "Auto" ++ help ++ auto-sensed the page size and ecc type value. driver will try each of ++ page size and ecc type one by one till flash can be read and wrote ++ accurately. so the page size and ecc type is match adaptively without ++ switch on the board ++ ++config HIFMC100_NAND_PAGESIZE_AUTO_ECC_NONE ++ bool "Pagesize Auto, Ecc None" ++ help ++ auto-sensed the page size and select ecc none. driver will try each ++ of page size one by one till flash can be read and wrote accurately. ++ so the page size is match adaptively without switch on the board ++ ++endchoice ++ ++endif # End of HIFMC100_NAND +diff --git a/drivers/mtd/nand/hifmc100_nand/Makefile b/drivers/mtd/nand/hifmc100_nand/Makefile +new file mode 100644 +index 0000000..b046e8d +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100_nand/Makefile +@@ -0,0 +1,26 @@ ++# ++# The Flash Memory Controller v100 Device Driver for hisilicon ++# ++# Copyright (c) 2016 HiSilicon Technologies 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. ++# ++# 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, see . ++# ++# ++ ++# ++# drivers/mtd/nand/hifmc100_nand/Makefile ++# ++ ++obj-$(CONFIG_HIFMC_NAND) += hifmc_nand_spl_ids.o ++obj-$(CONFIG_HIFMC_NAND) += hifmc100_nand.o hifmc100_nand_os.o +diff --git a/drivers/mtd/nand/hifmc100_nand/hifmc100_nand.c b/drivers/mtd/nand/hifmc100_nand/hifmc100_nand.c +new file mode 100644 +index 0000000..d4fa8fe +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100_nand/hifmc100_nand.c +@@ -0,0 +1,1102 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../hinfc_gen.h" ++#include "hifmc100_nand_os.h" ++#include "hifmc100_nand.h" ++ ++#include ++/*****************************************************************************/ ++static void hifmc100_dma_transfer(struct hifmc_host *host, int todev) ++{ ++ unsigned int reg = (unsigned int)host->dma_buffer; ++ char *op = todev ? "write" : "read"; ++ ++ FMC_PR(DMA_DB, "\t\t *-Start %s page dma transfer\n", op); ++ ++ hifmc_writel(host, FMC_DMA_SADDR_D0, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set ADDR0[%#x]%#x\n", FMC_DMA_SADDR_D0, reg); ++ ++ reg += FMC_DMA_ADDR_OFFSET; ++ hifmc_writel(host, FMC_DMA_SADDR_D1, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set ADDR1[%#x]%#x\n", FMC_DMA_SADDR_D1, reg); ++ ++ reg += FMC_DMA_ADDR_OFFSET; ++ hifmc_writel(host, FMC_DMA_SADDR_D2, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set ADDR2[%#x]%#x\n", FMC_DMA_SADDR_D2, reg); ++ ++ reg += FMC_DMA_ADDR_OFFSET; ++ hifmc_writel(host, FMC_DMA_SADDR_D3, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set ADDR3[%#x]%#x\n", FMC_DMA_SADDR_D3, reg); ++ ++ reg = host->dma_oob; ++ hifmc_writel(host, FMC_DMA_SADDR_OOB, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set OOB[%#x]%#x\n", FMC_DMA_SADDR_OOB, reg); ++ ++ if (host->ecctype == NAND_ECC_0BIT) { ++ hifmc_writel(host, FMC_DMA_LEN, FMC_DMA_LEN_SET(host->oobsize)); ++ FMC_PR(DMA_DB, "\t\t |-Set LEN[%#x]%#x\n", FMC_DMA_LEN, reg); ++ } ++ reg = FMC_OP_READ_DATA_EN | FMC_OP_WRITE_DATA_EN; ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ reg = FMC_DMA_AHB_CTRL_DMA_PP_EN ++ | FMC_DMA_AHB_CTRL_BURST16_EN ++ | FMC_DMA_AHB_CTRL_BURST8_EN ++ | FMC_DMA_AHB_CTRL_BURST4_EN; ++ hifmc_writel(host, FMC_DMA_AHB_CTRL, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set AHBCTRL[%#x]%#x\n", FMC_DMA_AHB_CTRL, reg); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) ++ | OP_CFG_ADDR_NUM(host->addr_cycle); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ reg = OP_CTRL_DMA_OP_READY; ++ if (todev) ++ reg |= OP_CTRL_RW_OP(todev); ++ hifmc_writel(host, FMC_OP_CTRL, reg); ++ FMC_PR(DMA_DB, "\t\t |-Set OP_CTRL[%#x]%#x\n", FMC_OP_CTRL, reg); ++ ++ FMC_DMA_WAIT_CPU_FINISH(host); ++ ++ FMC_PR(DMA_DB, "\t\t *-End %s page dma transfer\n", op); ++ ++ return; ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_write(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ FMC_PR(WR_DBG, "\t|*-Start send page programme cmd\n"); ++ ++ if (*host->bbm != 0xFF && *host->bbm != 0x00) ++ pr_info("WARNING: attempt to write an invalid bbm. " \ ++ "page: 0x%08x, mark: 0x%02x,\n", ++ GET_PAGE_INDEX(host), *host->bbm); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ reg = host->addr_value[1]; ++ hifmc_writel(host, FMC_ADDRH, reg); ++ FMC_PR(WR_DBG, "\t||-Set ADDRH[%#x]%#x\n", FMC_ADDRH, reg); ++ ++ reg = host->addr_value[0] & 0xffff0000; ++ hifmc_writel(host, FMC_ADDRL, reg); ++ FMC_PR(WR_DBG, "\t||-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg); ++ ++ reg = FMC_CMD_CMD2(NAND_CMD_PAGEPROG) | FMC_CMD_CMD1(NAND_CMD_SEQIN); ++ hifmc_writel(host, FMC_CMD, reg); ++ FMC_PR(WR_DBG, "\t||-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ *host->epm = 0x0000; ++ ++ hifmc100_dma_transfer(host, RW_OP_WRITE); ++ ++ FMC_PR(WR_DBG, "\t|*-End send page read cmd\n"); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_read(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ FMC_PR(RD_DBG, "\t*-Start send page read cmd\n"); ++ ++ if ((host->addr_value[0] == host->cache_addr_value[0]) ++ && (host->addr_value[1] == host->cache_addr_value[1])) { ++ FMC_PR(RD_DBG, "\t*-Cache hit! addr1[%#x], addr0[%#x]\n", ++ host->addr_value[1], host->addr_value[0]); ++ return; ++ } ++ ++ host->page_status = 0; ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ reg = FMC_INT_CLR_ALL; ++ hifmc_writel(host, FMC_INT_CLR, reg); ++ FMC_PR(RD_DBG, "\t|-Set INT_CLR[%#x]%#x\n", FMC_INT_CLR, reg); ++ ++ reg = host->nand_cfg; ++ hifmc_writel(host, FMC_CFG, reg); ++ FMC_PR(RD_DBG, "\t|-Set CFG[%#x]%#x\n", FMC_CFG, reg); ++ ++ reg = host->addr_value[1]; ++ hifmc_writel(host, FMC_ADDRH, reg); ++ FMC_PR(RD_DBG, "\t|-Set ADDRH[%#x]%#x\n", FMC_ADDRH, reg); ++ ++ reg = host->addr_value[0] & 0xffff0000; ++ hifmc_writel(host, FMC_ADDRL, reg); ++ FMC_PR(RD_DBG, "\t|-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg); ++ ++ reg = FMC_CMD_CMD2(NAND_CMD_READSTART) | FMC_CMD_CMD1(NAND_CMD_READ0); ++ hifmc_writel(host, FMC_CMD, reg); ++ FMC_PR(RD_DBG, "\t|-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ hifmc100_dma_transfer(host, RW_OP_READ); ++ ++ if (hifmc_readl(host, FMC_INT) & FMC_INT_ERR_INVALID) ++ host->page_status |= HIFMC100_PS_UC_ECC; ++ ++ host->cache_addr_value[0] = host->addr_value[0]; ++ host->cache_addr_value[1] = host->addr_value[1]; ++ ++ FMC_PR(RD_DBG, "\t*-End send page read cmd\n"); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_erase(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ FMC_PR(ER_DBG, "\t *-Start send cmd erase\n"); ++ ++ /* Don't case the read retry config */ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ reg = host->addr_value[0]; ++ hifmc_writel(host, FMC_ADDRL, reg); ++ FMC_PR(ER_DBG, "\t |-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg); ++ ++ reg = FMC_CMD_CMD2(NAND_CMD_ERASE2) | FMC_CMD_CMD1(NAND_CMD_ERASE1); ++ hifmc_writel(host, FMC_CMD, reg); ++ FMC_PR(ER_DBG, "\t |-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) ++ | OP_CFG_ADDR_NUM(host->addr_cycle); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(ER_DBG, "\t |-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ /* need to config WAIT_READY_EN */ ++ reg = FMC_OP_WAIT_READY_EN ++ | FMC_OP_CMD1_EN ++ | FMC_OP_CMD2_EN ++ | FMC_OP_ADDR_EN ++ | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(ER_DBG, "\t |-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++ FMC_PR(ER_DBG, "\t |*-End send cmd erase\n"); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_ecc_randomizer(struct hifmc_host *host, int ecc_en, ++ int randomizer_en) ++{ ++ unsigned int old_reg, reg, change = 0; ++ char *ecc_op = ecc_en ? "Quit" : "Enter"; ++ char *rand_op = randomizer_en ? "Enable" : "Disable"; ++ ++ if (IS_NAND_RANDOM(host)) { ++ reg = old_reg = hifmc_readl(host, FMC_GLOBAL_CFG); ++ if (randomizer_en) ++ reg |= FMC_GLOBAL_CFG_RANDOMIZER_EN; ++ else ++ reg &= ~FMC_GLOBAL_CFG_RANDOMIZER_EN; ++ ++ if (old_reg != reg) { ++ FMC_PR(EC_DBG, "\t |*-Start %s randomizer\n", rand_op); ++ FMC_PR(EC_DBG, "\t ||-Get global CFG[%#x]%#x\n", ++ FMC_GLOBAL_CFG, old_reg); ++ hifmc_writel(host, FMC_GLOBAL_CFG, reg); ++ FMC_PR(EC_DBG, "\t ||-Set global CFG[%#x]%#x\n", ++ FMC_GLOBAL_CFG, reg); ++ change++; ++ } ++ } ++ ++ old_reg = hifmc_readl(host, FMC_CFG); ++ reg = (ecc_en ? host->nand_cfg : host->nand_cfg_ecc0); ++ ++ if (old_reg != reg) { ++ FMC_PR(EC_DBG, "\t |%s-Start %s ECC0 mode\n", change ? "|":"*", ++ ecc_op); ++ FMC_PR(EC_DBG, "\t ||-Get CFG[%#x]%#x\n", FMC_CFG, old_reg); ++ hifmc_writel(host, FMC_CFG, reg); ++ FMC_PR(EC_DBG, "\t ||-Set CFG[%#x]%#x\n", FMC_CFG, reg); ++ change++; ++ } ++ ++ if (EC_DBG && change) ++ FMC_PR(EC_DBG, "\t |*-End randomizer and ECC0 mode config\n"); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_status(struct hifmc_host *host) ++{ ++ unsigned int regval; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ regval = OP_CFG_FM_CS(host->cmd_op.cs); ++ hifmc_writel(host, FMC_OP_CFG, regval); ++ ++ regval = FMC_OP_READ_STATUS_EN | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, regval); ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_readid(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ FMC_PR(BT_DBG, "\t *-Start read nand flash ID\n"); ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ reg = FMC_DATA_NUM_CNT(host->cmd_op.data_no); ++ hifmc_writel(host, FMC_DATA_NUM, reg); ++ FMC_PR(BT_DBG, "\t |-Set DATA_NUM[%#x]%#x\n", FMC_DATA_NUM, reg); ++ ++ reg = FMC_CMD_CMD1(NAND_CMD_READID); ++ hifmc_writel(host, FMC_CMD, reg); ++ FMC_PR(BT_DBG, "\t |-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ reg = 0; ++ hifmc_writel(host, FMC_ADDRL, reg); ++ FMC_PR(BT_DBG, "\t |-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs) ++ | OP_CFG_ADDR_NUM(READ_ID_ADDR_NUM); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(BT_DBG, "\t |-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ reg = FMC_OP_CMD1_EN ++ | FMC_OP_ADDR_EN ++ | FMC_OP_READ_DATA_EN ++ | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(BT_DBG, "\t |-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ host->addr_cycle = 0x0; ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++ FMC_PR(BT_DBG, "\t *-End read nand flash ID\n"); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_send_cmd_reset(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ FMC_PR(BT_DBG, "\t *-Start reset nand flash\n"); ++ ++ reg = FMC_CMD_CMD1(NAND_CMD_RESET); ++ hifmc_writel(host, FMC_CMD, reg); ++ FMC_PR(BT_DBG, "\t |-Set CMD[%#x]%#x\n", FMC_CMD, reg); ++ ++ reg = OP_CFG_FM_CS(host->cmd_op.cs); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ FMC_PR(BT_DBG, "\t |-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg); ++ ++ reg = FMC_OP_CMD1_EN ++ | FMC_OP_WAIT_READY_EN ++ | FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ FMC_PR(BT_DBG, "\t |-Set OP[%#x]%#x\n", FMC_OP, reg); ++ ++ FMC_CMD_WAIT_CPU_FINISH(host); ++ ++ FMC_PR(BT_DBG, "\t *-End reset nand flash\n"); ++} ++ ++/*****************************************************************************/ ++static unsigned char hifmc100_read_byte(struct mtd_info *mtd) ++{ ++ unsigned char value = 0; ++ struct nand_chip *chip = mtd->priv; ++ struct hifmc_host *host = chip->priv; ++ ++ if (host->cmd_op.l_cmd == NAND_CMD_READID) { ++ value = hifmc_readb((void __iomem *)(chip->IO_ADDR_R + host->offset)); ++ host->offset++; ++ if (host->cmd_op.data_no == host->offset) ++ host->cmd_op.l_cmd = 0; ++ return value; ++ } ++ ++ if (host->cmd_op.cmd == NAND_CMD_STATUS) { ++ value = hifmc_readl(host, FMC_STATUS); ++ if (host->cmd_op.l_cmd == NAND_CMD_ERASE1) ++ FMC_PR(ER_DBG, "\t*-Erase WP status: %#x\n", value); ++ if (host->cmd_op.l_cmd == NAND_CMD_PAGEPROG) ++ FMC_PR(WR_DBG, "\t*-Write WP status: %#x\n", value); ++ return value; ++ } ++ ++ if (host->cmd_op.l_cmd == NAND_CMD_READOOB) { ++ value = hifmc_readb((void __iomem *)(host->buffer + host->pagesize ++ + host->offset)); ++ host->offset++; ++ return value; ++ } ++ ++ host->offset++; ++ ++ return hifmc_readb((void __iomem *)(host->buffer + host->column \ ++ + host->offset - 1)); ++} ++ ++/*****************************************************************************/ ++static unsigned short hifmc100_read_word(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct hifmc_host *host = chip->priv; ++ ++ host->offset += 2; ++ return hifmc_readw(host->buffer + host->column + host->offset - 2); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_write_buf(struct mtd_info *mtd, ++ const u_char *buf, int len) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct hifmc_host *host = chip->priv; ++ ++#ifdef HIFMC100_NAND_SUPPORT_REG_WRITE ++ if (buf == chip->oob_poi) ++ memcpy((char *)host->iobase + host->pagesize, buf, len); ++ else ++ memcpy((char *)host->iobase, buf, len); ++#else ++ if (buf == chip->oob_poi) ++ memcpy((char *)host->buffer + host->pagesize, buf, len); ++ else ++ memcpy((char *)host->buffer, buf, len); ++#endif ++ return; ++} ++ ++#ifdef CONFIG_HISI_NAND_ECC_STATUS_REPORT ++/*****************************************************************************/ ++static void hifmc100_ecc_err_num_count(struct mtd_info *mtd, ++ u_int ecc_st, u_int reg) ++{ ++ u_char err_num; ++ ++ if (ecc_st > 4) ++ ecc_st = 4; ++ ++ while (ecc_st) { ++ err_num = GET_ECC_ERR_NUM(--ecc_st, reg); ++ if (err_num == 0xff) ++ mtd->ecc_stats.failed++; ++ else ++ mtd->ecc_stats.corrected += err_num; ++ } ++} ++#endif ++ ++/*****************************************************************************/ ++static void hifmc100_read_buf(struct mtd_info *mtd, u_char *buf, int len) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct hifmc_host *host = chip->priv; ++ ++#ifdef HIFMC100_NAND_SUPPORT_REG_READ ++ if (buf == chip->oob_poi) ++ memcpy(buf, (char *)host->iobase + host->pagesize, len); ++ else ++ memcpy(buf, (char *)host->iobase, len); ++#else ++ if (buf == chip->oob_poi) ++ memcpy(buf, (char *)host->buffer + host->pagesize, len); ++ else ++ memcpy(buf, (char *)host->buffer, len); ++#endif ++ ++#ifdef CONFIG_HISI_NAND_ECC_STATUS_REPORT ++ if (buf != chip->oob_poi) { ++ u_int reg, ecc_step = host->pagesize >> 10; ++ ++ /* 2K or 4K or 8K(1) or 16K(1-1) pagesize */ ++ reg = hifmc_readl(host, HIFMC100_ECC_ERR_NUM0_BUF0); ++ hifmc100_ecc_err_num_count(mtd, ecc_step, reg); ++ ++ if (ecc_step > 4) { ++ /* 8K(2) or 16K(1-2) pagesize */ ++ reg = hifmc_readl(host, HIFMC100_ECC_ERR_NUM1_BUF0); ++ hifmc100_ecc_err_num_count(mtd, ecc_step, reg); ++ if (ecc_step > 8) { ++ /* 16K(2-1) pagesize */ ++ reg = hifmc_readl(host, ++ HIFMC100_ECC_ERR_NUM0_BUF1); ++ hifmc100_ecc_err_num_count(mtd, ecc_step, reg); ++ /* 16K(2-2) pagesize */ ++ reg = hifmc_readl(host, ++ HIFMC100_ECC_ERR_NUM1_BUF1); ++ hifmc100_ecc_err_num_count(mtd, ecc_step, reg); ++ } ++ } ++ } ++#endif ++ ++ return; ++} ++ ++/*****************************************************************************/ ++static void hifmc100_select_chip(struct mtd_info *mtd, int chipselect) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct hifmc_host *host = chip->priv; ++ ++ if (chipselect < 0) { ++ mutex_unlock(&fmc_switch_mutex); ++ return; ++ } ++ ++ mutex_lock(&fmc_switch_mutex); ++ ++ if (chipselect > CONFIG_HIFMC100_MAX_NAND_CHIP) ++ DB_BUG("Error: Invalid chip select: %d\n", chipselect); ++ ++ host->cmd_op.cs = chipselect; ++ if (host->mtd != mtd) ++ host->mtd = mtd; ++ ++ switch (chip->state) { ++ case FL_ERASING: ++ host->cmd_op.l_cmd = NAND_CMD_ERASE1; ++ if (ER_DBG) ++ pr_info("\n"); ++ FMC_PR(ER_DBG, "\t*-Erase chip: %d\n", chipselect); ++ break; ++ case FL_WRITING: ++ host->cmd_op.l_cmd = NAND_CMD_PAGEPROG; ++ if (WR_DBG) ++ pr_info("\n"); ++ FMC_PR(WR_DBG, "\t*-Write chip: %d\n", chipselect); ++ break; ++ case FL_READING: ++ host->cmd_op.l_cmd = NAND_CMD_READ0; ++ if (RD_DBG) ++ pr_info("\n"); ++ FMC_PR(RD_DBG, "\t*-Read chip: %d\n", chipselect); ++ break; ++ default: ++ break; ++ } ++} ++ ++/*****************************************************************************/ ++static void hifmc100_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned ctrl) ++{ ++ unsigned char cmd; ++ int is_cache_invalid = 1; ++ struct nand_chip *chip = mtd->priv; ++ struct hifmc_host *host = chip->priv; ++ ++ if (ctrl & NAND_ALE) { ++ unsigned int addr_value = 0; ++ unsigned int addr_offset = 0; ++ ++ if (ctrl & NAND_CTRL_CHANGE) { ++ host->addr_cycle = 0x0; ++ host->addr_value[0] = 0x0; ++ host->addr_value[1] = 0x0; ++ } ++ addr_offset = host->addr_cycle << 3; ++ ++ if (host->addr_cycle >= HIFMC100_ADDR_CYCLE_MASK) { ++ addr_offset = (host->addr_cycle - ++ HIFMC100_ADDR_CYCLE_MASK) << 3; ++ addr_value = 1; ++ } ++ ++ host->addr_value[addr_value] |= ++ ((dat & 0xff) << addr_offset); ++ ++ host->addr_cycle++; ++ } ++ ++ if ((ctrl & NAND_CLE) && (ctrl & NAND_CTRL_CHANGE)) { ++ cmd = dat & 0xff; ++ host->cmd_op.cmd = cmd; ++ switch (cmd) { ++ case NAND_CMD_PAGEPROG: ++ host->offset = 0; ++ host->send_cmd_pageprog(host); ++ break; ++ ++ case NAND_CMD_READSTART: ++ is_cache_invalid = 0; ++ if (host->addr_value[0] == host->pagesize) ++ host->cmd_op.l_cmd = NAND_CMD_READOOB; ++ host->send_cmd_readstart(host); ++ break; ++ ++ case NAND_CMD_ERASE2: ++ host->cmd_op.l_cmd = cmd; ++ host->send_cmd_erase(host); ++ break; ++ ++ case NAND_CMD_READID: ++ memset((u_char *)(chip->IO_ADDR_R), 0, MAX_NAND_ID_LEN); ++ host->cmd_op.l_cmd = cmd; ++ host->cmd_op.data_no = MAX_NAND_ID_LEN; ++ host->send_cmd_readid(host); ++ break; ++ ++ case NAND_CMD_STATUS: ++ host->send_cmd_status(host); ++ break; ++ ++ case NAND_CMD_READ0: ++ host->cmd_op.l_cmd = cmd; ++ break; ++ ++ case NAND_CMD_RESET: ++ host->send_cmd_reset(host); ++ break; ++ ++ case NAND_CMD_SEQIN: ++ case NAND_CMD_ERASE1: ++ default: ++ break; ++ } ++ } ++ ++ /* pass pagesize and ecctype to kernel when startup. */ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ if ((dat == NAND_CMD_NONE) && host->addr_cycle) { ++ if (host->cmd_op.cmd == NAND_CMD_SEQIN ++ || host->cmd_op.cmd == NAND_CMD_READ0 ++ || host->cmd_op.cmd == NAND_CMD_READID) { ++ host->offset = 0x0; ++ host->column = (host->addr_value[0] & 0xffff); ++ } ++ } ++ ++ if (is_cache_invalid) { ++ host->cache_addr_value[0] = ~0; ++ host->cache_addr_value[1] = ~0; ++ } ++} ++ ++/*****************************************************************************/ ++static int hifmc100_dev_ready(struct mtd_info *mtd) ++{ ++ return 0x1; ++} ++ ++/*****************************************************************************/ ++/* ++ * 'host->epm' only use the first oobfree[0] field, it looks very simple, But... ++ */ ++static struct nand_ecclayout nand_ecc_default = { ++ .oobfree = {{2, 30} } ++}; ++ ++#ifdef CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 ++static struct nand_ecclayout nand_ecc_2k16bit = { ++ .oobfree = {{2, 6} } ++}; ++ ++static struct nand_ecclayout nand_ecc_4k16bit = { ++ .oobfree = {{2, 14} } ++}; ++#endif ++/*****************************************************************************/ ++/* ecc/pagesize get from CPU PIN. */ ++static struct nand_config_info hifmc100_nand_hw_pin_config_table[] = { ++ {NAND_PAGE_16K, NAND_ECC_64BIT, 1824/*1824*/, &nand_ecc_default}, ++ {NAND_PAGE_16K, NAND_ECC_40BIT, 1152/*1152*/, &nand_ecc_default}, ++ {NAND_PAGE_16K, NAND_ECC_0BIT, 32 , &nand_ecc_default}, ++ ++ {NAND_PAGE_8K, NAND_ECC_64BIT, 928 /*928*/, &nand_ecc_default}, ++ {NAND_PAGE_8K, NAND_ECC_40BIT, 592 /*592 */, &nand_ecc_default}, ++ {NAND_PAGE_8K, NAND_ECC_24BIT, 368 /*368*/, &nand_ecc_default}, ++ {NAND_PAGE_8K, NAND_ECC_0BIT, 32, &nand_ecc_default}, ++ ++ {NAND_PAGE_4K, NAND_ECC_24BIT, 200 /*200*/, &nand_ecc_default}, ++#ifdef CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 ++ {NAND_PAGE_4K, NAND_ECC_16BIT, 128 /*128*/, &nand_ecc_4k16bit}, ++#endif ++ {NAND_PAGE_4K, NAND_ECC_8BIT, 88 /*88*/, &nand_ecc_default}, ++ {NAND_PAGE_4K, NAND_ECC_0BIT, 32, &nand_ecc_default}, ++ ++ {NAND_PAGE_2K, NAND_ECC_24BIT, 116 /*116*/, &nand_ecc_default}, ++#ifdef CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 ++ {NAND_PAGE_2K, NAND_ECC_16BIT, 64 /*64*/, &nand_ecc_2k16bit}, ++#endif ++ {NAND_PAGE_2K, NAND_ECC_8BIT, 60 /*60*/, &nand_ecc_default}, ++ {NAND_PAGE_2K, NAND_ECC_0BIT, 32, &nand_ecc_default}, ++ ++ {0, 0, 0, NULL}, ++}; ++ ++/*****************************************************************************/ ++/* ecc/pagesize get from NAND controller */ ++static struct nand_config_info hifmc100_nand_hw_auto_config_table[] = { ++ {NAND_PAGE_16K, NAND_ECC_64BIT, 1824/*1824*/, &nand_ecc_default}, ++ {NAND_PAGE_16K, NAND_ECC_40BIT, 1200/*1152*/, &nand_ecc_default}, ++ {NAND_PAGE_16K, NAND_ECC_0BIT, 32 , &nand_ecc_default}, ++ ++ {NAND_PAGE_8K, NAND_ECC_64BIT, 928 /*928*/, &nand_ecc_default}, ++ {NAND_PAGE_8K, NAND_ECC_40BIT, 600 /*592*/, &nand_ecc_default}, ++ {NAND_PAGE_8K, NAND_ECC_24BIT, 368 /*368*/, &nand_ecc_default}, ++ {NAND_PAGE_8K, NAND_ECC_0BIT, 32, &nand_ecc_default}, ++ ++ {NAND_PAGE_4K, NAND_ECC_24BIT, 200 /*200*/, &nand_ecc_default}, ++#ifdef CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 ++ {NAND_PAGE_4K, NAND_ECC_16BIT, 128 /*128*/, &nand_ecc_default}, ++#endif ++ {NAND_PAGE_4K, NAND_ECC_8BIT, 128 /*88*/, &nand_ecc_default}, ++ {NAND_PAGE_4K, NAND_ECC_0BIT, 32, &nand_ecc_default}, ++ ++ {NAND_PAGE_2K, NAND_ECC_24BIT, 128 /*116*/, &nand_ecc_default}, ++#ifdef CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 ++ {NAND_PAGE_2K, NAND_ECC_16BIT, 64 /*64*/, &nand_ecc_default}, ++#endif ++ {NAND_PAGE_2K, NAND_ECC_8BIT, 64 /*60*/, &nand_ecc_default}, ++ {NAND_PAGE_2K, NAND_ECC_0BIT, 32, &nand_ecc_default}, ++ ++ {0, 0, 0, NULL}, ++}; ++ ++/*****************************************************************************/ ++/* ++ * 0 - This NAND NOT support randomizer ++ * 1 - This NAND support randomizer. ++ */ ++static int hifmc100_nand_support_randomizer(u_int pageisze, u_int ecctype) ++{ ++ switch (pageisze) { ++ case _8K: ++ return (ecctype >= NAND_ECC_24BIT && ecctype <= NAND_ECC_80BIT); ++ case _16K: ++ return (ecctype >= NAND_ECC_40BIT && ecctype <= NAND_ECC_80BIT); ++ case _32K: ++ return (ecctype >= NAND_ECC_40BIT && ecctype <= NAND_ECC_80BIT); ++ default: ++ return 0; ++ } ++} ++ ++/*****************************************************************************/ ++/* used the best correct arithmetic. */ ++static struct nand_config_info *hifmc100_get_best_ecc( ++ struct nand_config_info *config, struct mtd_info *mtd) ++{ ++ struct nand_config_info *best = NULL; ++ ++ for (; config->layout; config++) { ++ if (match_page_type_to_size(config->pagetype) != mtd->writesize) ++ continue; ++ ++ if (mtd->oobsize < config->oobsize) ++ continue; ++ ++ if (!best || (best->ecctype < config->ecctype)) ++ best = config; ++ } ++ ++ if (!best) ++ DB_BUG(ERSTR_DRIVER " the pagesize(%d) and oobsize(%d).\n", ++ mtd->writesize, mtd->oobsize); ++ return best; ++} ++ ++/*****************************************************************************/ ++static void debug_register_dump(struct hifmc_host *host) ++{ ++ int ix; ++ ++ pr_info("Register dump:"); ++ for (ix = 0; ix <= 0x98; ix += 0x04) { ++ if (!(ix & 0x0F)) ++ pr_info("\n0x%08X: ", ++ (unsigned int)(host->regbase + ix)); ++ pr_info("%08X ", hifmc_readl(host, ix)); ++ } ++ pr_info("\n"); ++} ++ ++/*****************************************************************************/ ++static void hifmc100_check_config(struct hifmc_host *host, ++ struct nand_dev_t *flash_dev_ex, ++ struct nand_config_info *best, int is_hw_auto) ++{ ++ unsigned char page_reg, pagetype, ecc_reg, ecctype; ++ int isdump = 0; ++ ++ FMC_PR(BT_DBG, "\t *-Start check best and controller auto config\n"); ++ ++ page_reg = (host->nand_cfg & PAGE_SIZE_MASK) >> PAGE_SIZE_SHIFT; ++ pagetype = match_page_reg_to_type(page_reg); ++ ++ ecc_reg = (host->nand_cfg & ECC_TYPE_MASK) >> ECC_TYPE_SHIFT; ++ ecctype = match_ecc_reg_to_type(ecc_reg); ++ ++ if (pagetype != best->pagetype) { ++ if (!isdump++) ++ debug_register_dump(host); ++ if (is_hw_auto) { ++ DB_BUG("!!! warning: Hardware configure pagesize %s" \ ++ ", but the Nand Flash pageszie is %s. Update" \ ++ " fastboot will resolve this problem.\n", ++ match_page_type_to_str(pagetype), ++ match_page_type_to_str(best->pagetype)); ++ } else { ++ DB_BUG("!!! warning: Hardware configure pagesize %s" \ ++ ", but the Nand Flash pageszie is %s. Modify" \ ++ "hardware pin will resolve this problem.\n", ++ match_page_type_to_str(pagetype), ++ match_page_type_to_str(best->pagetype)); ++ } ++ } ++ ++ if (ecctype < best->ecctype) { ++ if (!is_hw_auto) ++ best->ecctype = ecctype; ++ } else if (ecctype > best->ecctype) { ++ DB_BUG("!!! warning: Hardware configure ecctype %s, " \ ++ "but %s is more suitable for this Nand Flash." \ ++ "Modify hardware pin will resolve this problem.\n", ++ match_ecc_type_to_str(ecctype), ++ match_ecc_type_to_str(best->ecctype)); ++ } ++ ++ if (IS_NAND_RANDOM(flash_dev_ex) && !IS_NAND_RANDOM(host)) { ++ if (is_hw_auto) { ++ DB_BUG("Hardware is't configure randomizer, but it "\ ++ "is more suitable for this Nand Flash. Update"\ ++ " fastboot will resolve this problem\n"); ++ } else { ++ DB_BUG("Hardware is't configure randomizer, but it" \ ++ "is more suitable for this Nand Flash. Modify"\ ++ "hardware pin will resolve this problem.\n"); ++ } ++ } ++ ++ FMC_PR(BT_DBG, "\t *-End check, PageSize: %s, EccType: %s\n", ++ match_page_type_to_str(pagetype), match_ecc_type_to_str(ecctype)); ++} ++ ++/*****************************************************************************/ ++static int hifmc100_ecc_probe(struct mtd_info *mtd, struct nand_chip *chip, ++ struct nand_dev_t *dev) ++{ ++ int regval, buffer_len; ++ char *start_type = "unknown"; ++ struct nand_config_info *best = NULL; ++ struct nand_config_info *config = NULL; ++ struct hifmc_host *host = chip->priv; ++ struct nand_dev_t *nand_dev = &g_nand_dev; ++ ++ FMC_PR(BT_DBG, "\t *-Start match PageSize and EccType\n"); ++ ++ if (IS_NANDC_HW_AUTO(host)) { ++ FMC_PR(BT_DBG, "\t |-Get hardware auto config\n"); ++ config = hifmc100_nand_hw_auto_config_table; ++ ++ start_type = "HW-Auto"; ++ best = hifmc100_get_best_ecc(config, mtd); ++ } else { ++ FMC_PR(BT_DBG, "\t |-Get config from CPU PIN\n"); ++ config = hifmc100_nand_hw_pin_config_table; ++ start_type = "HW-Pin"; ++ best = hifmc100_get_best_ecc(config, mtd); ++ hifmc100_check_config(host, nand_dev, best, 0); ++ } ++ ++ nand_dev->flags |= (IS_NANDC_HW_AUTO(host) ++ | IS_NANDC_CONFIG_DONE(host)); ++ ++ if (!best) ++ DB_BUG(ERSTR_HARDWARE ++ "Please configure Nand Flash pagesize and ecctype!\n"); ++ ++ if (best->ecctype != NAND_ECC_0BIT) ++ mtd->oobsize = best->oobsize; ++ mtd->oobavail = HIFMC100_NAND_OOBSIZE_FOR_YAFFS; ++ chip->ecc.layout = best->layout; ++ ++ host->ecctype = best->ecctype; ++ FMC_PR(BT_DBG, "\t |-Save best EccType %d(%s)\n", host->ecctype, ++ match_ecc_type_to_str(best->ecctype)); ++ host->pagesize = match_page_type_to_size(best->pagetype); ++ FMC_PR(BT_DBG, "\t |-Save best PageSize %d(%s)\n", host->pagesize, ++ match_page_type_to_str(best->pagetype)); ++ ++ if (hifmc100_nand_support_randomizer(host->pagesize, host->ecctype)) ++ host->flags |= IS_NAND_RANDOM(nand_dev); ++ ++ host->oobsize = mtd->oobsize; ++ host->block_page_mask = ((mtd->erasesize / mtd->writesize) - 1); ++ ++ buffer_len = host->pagesize + host->oobsize; ++ host->buffer = dmam_alloc_coherent(host->dev, buffer_len, ++ &host->dma_buffer, GFP_KERNEL); ++ if (!host->buffer) { ++ DB_MSG("Error: Can't malloc memory for hifmc100 driver.\n"); ++ return -ENOMEM; ++ } ++ memset(host->buffer, 0xff, buffer_len); ++ host->dma_oob = host->dma_buffer + host->pagesize; ++ ++ host->bbm = (unsigned char *)(host->buffer + host->pagesize ++ + HIFMC100_BAD_BLOCK_POS); ++ ++ host->epm = (unsigned short *)(host->buffer + host->pagesize ++ + chip->ecc.layout->oobfree[0].offset + 28); ++ ++#ifdef CONFIG_HISI_NAND_FS_MAY_NO_YAFFS2 ++ if (best->ecctype == NAND_ECC_16BIT) { ++ if (host->pagesize == _2K) { ++ /* EB bits locate in the bottom two of CTRL(4) */ ++ host->epm = (u_short *)(host->buffer + host->pagesize ++ + chip->ecc.layout->oobfree[0].offset + 4); ++ } else if (host->pagesize == _4K) { ++ /* EB bit locate in the bottom two of CTRL(14) */ ++ host->epm = (u_short *)(host->buffer + host->pagesize ++ + chip->ecc.layout->oobfree[0].offset + 12); ++ } ++ } ++#endif ++ ++ host->nand_cfg &= ~PAGE_SIZE_MASK; ++ host->nand_cfg_ecc0 &= ~PAGE_SIZE_MASK; ++ regval = match_page_type_to_reg(best->pagetype); ++ host->nand_cfg |= FMC_CFG_PAGE_SIZE(regval); ++ host->nand_cfg_ecc0 |= FMC_CFG_PAGE_SIZE(regval); ++ ++ host->nand_cfg &= ~ECC_TYPE_MASK; ++ host->nand_cfg_ecc0 &= ~ECC_TYPE_MASK; ++ regval = match_ecc_type_to_reg(best->ecctype); ++ host->nand_cfg |= FMC_CFG_ECC_TYPE(regval); ++ ++ /* pass pagesize and ecctype to kernel when spiflash startup. */ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ if (mtd->writesize > NAND_MAX_PAGESIZE ++ || mtd->oobsize > NAND_MAX_OOBSIZE) { ++ DB_BUG(ERSTR_DRIVER ++ "Driver does not support this Nand Flash. Please " \ ++ "increase NAND_MAX_PAGESIZE and NAND_MAX_OOBSIZE.\n"); ++ } ++ ++ if (mtd->writesize != host->pagesize) { ++ unsigned int shift = 0; ++ unsigned int writesize = mtd->writesize; ++ ++ while (writesize > host->pagesize) { ++ writesize >>= 1; ++ shift++; ++ } ++ chip->chipsize = chip->chipsize >> shift; ++ mtd->erasesize = mtd->erasesize >> shift; ++ mtd->writesize = host->pagesize; ++ pr_info("Nand divide into 1/%u\n", (1 << shift)); ++ } ++ ++ nand_dev->start_type = start_type; ++ dev->start_type = nand_dev->start_type; ++ nand_dev->ecctype = host->ecctype; ++ dev->ecctype = nand_dev->ecctype; ++ ++ host->read_retry = NULL; ++ ++ /* ++ * If it want to support the 'read retry' feature, the 'randomizer' ++ * feature must be support first. ++ */ ++ if (host->read_retry && !IS_NAND_RANDOM(host)) { ++ DB_BUG(ERSTR_HARDWARE ++ "This Nand flash need to enable 'randomizer' feature. " ++ "Please configure hardware randomizer PIN."); ++ } ++ ++ /* ++ * Check if hardware enable randomizer PIN, But NAND does not need ++ * randomizer. We will notice user. ++ */ ++ if (IS_NAND_RANDOM(host) && ++ !hifmc100_nand_support_randomizer(host->pagesize, host->ecctype)) ++ DB_BUG(ERSTR_HARDWARE ++ "This NAND flash does not support `randomizer`, " ++ "Please don't configure hardware randomizer PIN."); ++ ++ FMC_PR(BT_DBG, "\t *-End match ecctype\n"); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++static void hifmc100_chip_init(struct nand_chip *chip) ++{ ++ memset((char *)chip->IO_ADDR_R, 0xff, NAND_BUFFER_LEN); ++ ++ chip->read_byte = hifmc100_read_byte; ++ chip->read_word = hifmc100_read_word; ++ chip->write_buf = hifmc100_write_buf; ++ chip->read_buf = hifmc100_read_buf; ++ ++ chip->select_chip = hifmc100_select_chip; ++ ++ chip->cmd_ctrl = hifmc100_cmd_ctrl; ++ chip->dev_ready = hifmc100_dev_ready; ++ ++ chip->chip_delay = FMC_CHIP_DELAY; ++ ++ chip->options = NAND_NO_AUTOINCR | NAND_NEED_READRDY | NAND_BROKEN_XD ++ | NAND_SKIP_BBTSCAN; ++ ++ chip->ecc.layout = NULL; ++ chip->ecc.mode = NAND_ECC_NONE; ++} ++ ++/*****************************************************************************/ ++static int hifmc100_host_init(struct hifmc_host *host) ++{ ++ unsigned int addr, reg, flash_type; ++ ++ FMC_PR(BT_DBG, "\t *-Start nand host init\n"); ++ ++ addr = (unsigned int)host->regbase + FMC_CFG; ++ reg = hifmc_readl(host, FMC_CFG); ++ FMC_PR(BT_DBG, "\t |-Read FMC CFG[%#x]%#x\n", addr, reg); ++ flash_type = GET_SPI_FLASH_TYPE(reg); ++ if (flash_type != FLASH_TYPE_NAND) { ++ DB_MSG("Error: Flash type isn't Nand flash. reg[%#x]\n", reg); ++ reg |= FMC_CFG_FLASH_SEL(FLASH_TYPE_NAND); ++ FMC_PR(BT_DBG, "\t |-Change flash type to Nand flash\n"); ++ } ++ ++ if ((reg & FMC_CFG_OP_MODE_MASK) == FMC_CFG_OP_MODE_BOOT) { ++ reg |= FMC_CFG_OP_MODE(FMC_CFG_OP_MODE_NORMAL); ++ FMC_PR(BT_DBG, "\t |-Controller enter normal mode\n"); ++ } ++ hifmc_writel(host, FMC_CFG, reg); ++ FMC_PR(BT_DBG, "\t |-Set CFG[%#x]%#x\n", addr, reg); ++ ++ host->nand_cfg = reg; ++ host->nand_cfg_ecc0 = (reg & ~ECC_TYPE_MASK) | ECC_TYPE_0BIT; ++ ++ addr = (unsigned int)host->regbase + FMC_GLOBAL_CFG; ++ reg = hifmc_readl(host, FMC_GLOBAL_CFG); ++ FMC_PR(BT_DBG, "\t |-Read global CFG[%#x]%#x\n", addr, reg); ++ if (reg & FMC_GLOBAL_CFG_RANDOMIZER_EN) { ++ host->flags &= ~NAND_RANDOMIZER; ++ FMC_PR(BT_DBG, "\t |-Default disable randomizer\n"); ++ reg &= ~FMC_GLOBAL_CFG_RANDOMIZER_EN; ++ hifmc_writel(host, FMC_GLOBAL_CFG, reg); ++ FMC_PR(BT_DBG, "\t |-Set global CFG[%#x]%#x\n", addr, reg); ++ } ++ ++#ifdef CONFIG_HIFMC100_NAND_EDO_MODE ++ /* enable EDO node */ ++ reg = hifmc_readl(host, FMC_GLOBAL_CFG); ++ hifmc_writel(host, FMC_GLOBAL_CFG, SET_NAND_EDO_MODE_EN(reg)); ++#endif ++ ++ host->addr_cycle = 0; ++ host->addr_value[0] = 0; ++ host->addr_value[1] = 0; ++ host->cache_addr_value[0] = ~0; ++ host->cache_addr_value[1] = ~0; ++ ++ host->send_cmd_pageprog = hifmc100_send_cmd_write; ++ host->send_cmd_status = hifmc100_send_cmd_status; ++ host->send_cmd_readstart = hifmc100_send_cmd_read; ++ host->send_cmd_erase = hifmc100_send_cmd_erase; ++ host->send_cmd_readid = hifmc100_send_cmd_readid; ++ host->send_cmd_reset = hifmc100_send_cmd_reset; ++ ++ /* ++ * check if start from nand. ++ * This register REG_SYSSTAT is set in start.S ++ * When start in NAND (Auto), the ECC/PAGESIZE driver don't detect. ++ */ ++ host->flags |= NANDC_HW_AUTO; ++ ++ if (GET_SYS_BOOT_MODE(reg) == BOOT_FROM_NAND) { ++ host->flags |= NANDC_CONFIG_DONE; ++ FMC_PR(BT_DBG, "\t |-Auto config pagesize and ecctype\n"); ++ } ++ ++ host->enable_ecc_randomizer = hifmc100_ecc_randomizer; ++ ++ FMC_PR(BT_DBG, "\t *-End nand host init\n"); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++int hifmc100_nand_init(struct nand_chip *chip) ++{ ++ struct hifmc_host *host = chip->priv; ++ ++ /* enable and set system clock */ ++ clk_prepare_enable(host->clk); ++ ++ /* fmc ip version check */ ++ host->version = hifmc_readl(host, FMC_VERSION); ++ if (host->version != HIFMC_VER_100) ++ return -EFAULT; ++ pr_info("Found Flash Memory Controller v100 Nand Driver\n"); ++ ++ /* hifmc host init */ ++ if (hifmc100_host_init(host)) { ++ DB_MSG("Error: Nand host init failed!\n"); ++ return -EFAULT; ++ } ++ host->chip = chip; ++ ++ hifmc_writel(host, FMC_PND_PWIDTH_CFG, PWIDTH_CFG_RW_HCNT(CONFIG_RW_H_WIDTH) ++ | PWIDTH_CFG_R_LCNT(CONFIG_R_L_WIDTH) ++ | PWIDTH_CFG_W_LCNT(CONFIG_W_L_WIDTH)); ++ ++ /* hifmc nand_chip struct init */ ++ hifmc100_chip_init(chip); ++ ++ hifmc_spl_ids_register(); ++ hinfc_param_adjust = hifmc100_ecc_probe; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++/*****************************************************************************/ ++void hifmc100_nand_config(struct hifmc_host *host) ++{ ++ /* enable system clock */ ++ clk_prepare_enable(host->clk); ++ FMC_PR(PM_DBG, "\t |-enable system clock\n"); ++} ++#endif /* CONFIG_PM */ +diff --git a/drivers/mtd/nand/hifmc100_nand/hifmc100_nand.h b/drivers/mtd/nand/hifmc100_nand/hifmc100_nand.h +new file mode 100644 +index 0000000..469e562 +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100_nand/hifmc100_nand.h +@@ -0,0 +1,159 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef __HIFMC100_NAND_H__ ++#define __HIFMC100_NAND_H__ ++ ++#include ++ ++/******************************************************************************/ ++/* These macroes are for debug only, reg option is slower then dma option */ ++#undef HIFMC100_NAND_SUPPORT_REG_READ ++/* #define HIFMC100_NAND_SUPPORT_REG_READ */ ++ ++#undef HIFMC100_NAND_SUPPORT_REG_WRITE ++/* #define HIFMC100_NAND_SUPPORT_REG_WRITE */ ++ ++#ifdef CONFIG_HISI_NAND_ECC_STATUS_REPORT ++/*****************************************************************************/ ++#define HIFMC100_ECC_ERR_NUM0_BUF0 0xc0 ++#define HIFMC100_ECC_ERR_NUM1_BUF0 0xc4 ++#define HIFMC100_ECC_ERR_NUM0_BUF1 0xc8 ++#define HIFMC100_ECC_ERR_NUM1_BUF1 0xcc ++ ++#define GET_ECC_ERR_NUM(_i, _reg) (((_reg) >> ((_i) * 8)) & 0xff) ++#endif ++/*****************************************************************************/ ++#define NAND_MAX_PAGESIZE 32768 ++#define NAND_MAX_OOBSIZE 4800 ++ ++#define HIFMC100_NAND_OOBSIZE_FOR_YAFFS 32 ++ ++/*****************************************************************************/ ++#define REG_CNT_HIGH_BLOCK_NUM_SHIFT 10 ++ ++#define REG_CNT_BLOCK_NUM_MASK 0x3ff ++#define REG_CNT_BLOCK_NUM_SHIFT 22 ++ ++#define REG_CNT_PAGE_NUM_MASK 0x3f ++#define REG_CNT_PAGE_NUM_SHIFT 16 ++ ++#define REG_CNT_WRAP_MASK 0xf ++#define REG_CNT_WRAP_SHIFT 12 ++ ++#define REG_CNT_ECC_OFFSET_MASK 0xfff ++#define REG_CNT_ECC_8BIT_OFFSET 1054 ++#define REG_CNT_ECC_16BIT_OFFSET 1056 ++#define REG_CNT_ECC_24BIT_OFFSET 1082 ++ ++/*****************************************************************************/ ++#define HIFMC100_ADDR_CYCLE_MASK 0x4 ++ ++#define NAND_EDO_MODE_SHIFT 9 ++#define NAND_EDO_MODE_MASK (1<. ++ * ++ */ ++ ++#include ++ ++#include "hifmc100_nand_os.h" ++#include "hifmc100_nand.h" ++#include ++ ++/*****************************************************************************/ ++static inline int mtd_has_partitions(void) { return 1; } ++ ++/*****************************************************************************/ ++static int hisi_nand_os_probe(struct platform_device *pltdev) ++{ ++ int len, result = 0; ++ struct hifmc_host *host; ++ struct nand_chip *chip; ++ struct mtd_info *mtd; ++ int nr_parts = 0; ++ struct mtd_partition *parts = NULL; ++ struct device *dev = &pltdev->dev; ++ struct device_node *np = NULL; ++ struct hisi_fmc *fmc = dev_get_drvdata(dev->parent); ++ ++ len = sizeof(struct hifmc_host) + sizeof(struct nand_chip) ++ + sizeof(struct mtd_info); ++ host = devm_kzalloc(dev, len, GFP_KERNEL); ++ if (!host) ++ return -ENOMEM; ++ memset((char *)host, 0, len); ++ platform_set_drvdata(pltdev, host); ++ ++ host->dev = &pltdev->dev; ++ host->chip = chip = (struct nand_chip *)&host[1]; ++ host->mtd = mtd = (struct mtd_info *)&chip[1]; ++ host->regbase = fmc->regbase; ++ host->iobase = fmc->iobase; ++ host->clk = fmc->clk; ++ chip->IO_ADDR_R = chip->IO_ADDR_W = host->iobase; ++ ++ /* hifmc Nand host init */ ++ chip->priv = host; ++ result = hifmc100_nand_init(chip); ++ if (result) { ++ DB_MSG("Error: host init failed! result: %d\n", result); ++ goto fail; ++ } ++ ++ np = of_get_next_available_child(dev->of_node, NULL); ++ mtd->name = np->name; ++ mtd->type = MTD_NANDFLASH; ++ mtd->priv = chip; ++ mtd->flags = MTD_CAP_NANDFLASH; ++ mtd->owner = THIS_MODULE; ++ ++ if (nand_scan(mtd, CONFIG_HIFMC100_MAX_NAND_CHIP)) { ++ result = -ENXIO; ++ goto fail; ++ } ++ ++ if (mtd_has_partitions()) { ++ static char const *part_probes[] = { ++ "cmdlinepart", ++ NULL, ++ }; ++ ++ nr_parts = parse_mtd_partitions(host->mtd, ++ part_probes, &parts, 0); ++ FMC_PR(BT_DBG, "parse mtd partitions: %d\n", nr_parts); ++ if (nr_parts > 0) ++ host->add_partition = 1; ++ } ++ ++ result = mtd_device_register(host->mtd, parts, nr_parts); ++ if (result) { ++ kfree(parts); ++ parts = NULL; ++ } ++ ++ return (1 == result) ? -ENODEV : 0; ++ ++fail: ++ nand_release(mtd); ++ clk_disable_unprepare(host->clk); ++ return result; ++} ++ ++/*****************************************************************************/ ++static int hisi_nand_os_remove(struct platform_device *pltdev) ++{ ++ struct hifmc_host *host = platform_get_drvdata(pltdev); ++ ++ clk_disable_unprepare(host->clk); ++ nand_release(host->mtd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++/*****************************************************************************/ ++static int hifmc100_nand_os_suspend(struct platform_device *pltdev, ++ pm_message_t state) ++{ ++ struct hifmc_host *host = platform_get_drvdata(pltdev); ++ if (!host) ++ return 0; ++ ++ while ((hifmc_readl(host, FMC_OP) & FMC_OP_REG_OP_START)) ++ _cond_resched(); ++ ++ while ((hifmc_readl(host, FMC_OP_CTRL) & OP_CTRL_DMA_OP_READY)) ++ _cond_resched(); ++ ++ clk_disable_unprepare(host->clk); ++ FMC_PR(PM_DBG, "\t|-disable system clock\n"); ++ return 0; ++} ++ ++/*****************************************************************************/ ++static int hifmc100_nand_os_resume(struct platform_device *pltdev) ++{ ++ int cs; ++ struct hifmc_host *host = platform_get_drvdata(pltdev); ++ struct nand_chip *chip; ++ ++ if (!host) ++ return 0; ++ ++ chip = host->chip; ++ ++ for (cs = 0; cs < chip->numchips; cs++) ++ host->send_cmd_reset(host); ++ ++ hifmc100_nand_config(host); ++ return 0; ++} ++#endif /* CONFIG_PM */ ++ ++/*****************************************************************************/ ++static const struct of_device_id hisi_nand_dt_ids[] = { ++ { .compatible = "hisilicon,hisi-nand" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, hisi_nand_dt_ids); ++ ++static struct platform_driver hisi_nand_driver = { ++ .driver = { ++ .name = "hisi-nand", ++ .of_match_table = hisi_nand_dt_ids, ++ }, ++ .probe = hisi_nand_os_probe, ++ .remove = hisi_nand_os_remove, ++#ifdef CONFIG_PM ++ .suspend = hifmc100_nand_os_suspend, ++ .resume = hifmc100_nand_os_resume, ++#endif ++}; ++module_platform_driver(hisi_nand_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("BVT_BSP"); ++MODULE_DESCRIPTION("Hisilicon Flash Memory Controller V100 Nand Driver"); +diff --git a/drivers/mtd/nand/hifmc100_nand/hifmc100_nand_os.h b/drivers/mtd/nand/hifmc100_nand/hifmc100_nand_os.h +new file mode 100644 +index 0000000..063fef8 +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100_nand/hifmc100_nand_os.h +@@ -0,0 +1,80 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef __HIFMC100_NAND_OS_H__ ++#define __HIFMC100_NAND_OS_H__ ++ ++/*****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 5)) ++ #include "../../mtdcore.h" ++#endif ++ ++/*****************************************************************************/ ++#define DEFAULT_NAND_PAGESIZE 2048 ++#define DEFAULT_NAND_OOBSIZE 64 ++ ++#define NAND_BUFFER_LEN (DEFAULT_NAND_PAGESIZE + DEFAULT_NAND_OOBSIZE) ++ ++/*****************************************************************************/ ++#ifndef CONFIG_HIFMC100_MAX_NAND_CHIP ++ #define CONFIG_HIFMC100_MAX_NAND_CHIP (1) ++ #warning NOT config CONFIG_HIFMC100_MAX_NAND_CHIP, \ ++ used default value, maybe invalid. ++#endif ++ ++#ifndef CONFIG_RW_H_WIDTH ++ #define CONFIG_RW_H_WIDTH (10) ++ #warning NOT config CONFIG_RW_H_WIDTH, used default value, maybe invalid. ++#endif ++ ++#ifndef CONFIG_R_L_WIDTH ++ #define CONFIG_R_L_WIDTH (10) ++ #warning NOT config CONFIG_R_L_WIDTH, used default value, maybe invalid. ++#endif ++ ++#ifndef CONFIG_W_L_WIDTH ++ #define CONFIG_W_L_WIDTH (10) ++ #warning NOT config CONFIG_W_L_WIDTH, used default value, maybe invalid. ++#endif ++ ++extern void hifmc100_nand_controller_enable(int enable); ++ ++#endif /* End of __HIFMC100_NAND_OS_H__ */ +diff --git a/drivers/mtd/nand/hifmc100_nand/hifmc_nand_spl_ids.c b/drivers/mtd/nand/hifmc100_nand/hifmc_nand_spl_ids.c +new file mode 100644 +index 0000000..5b34c02 +--- /dev/null ++++ b/drivers/mtd/nand/hifmc100_nand/hifmc_nand_spl_ids.c +@@ -0,0 +1,925 @@ ++/* ++ * The Flash Memory Controller v100 Device Driver for hisilicon ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++ ++#include "../hinfc_gen.h" ++#include "hifmc100_nand.h" ++ ++/*****************************************************************************/ ++#define _768K (_256K + _512K) ++ ++/*****************************************************************************/ ++struct nand_flash_special_dev { ++ unsigned char id[8]; ++ int length; /* length of id. */ ++ unsigned long long chipsize; ++ struct nand_flash_dev *(*probe)(unsigned char *id); ++ char *name; ++ ++ unsigned long pagesize; ++ unsigned long erasesize; ++ unsigned long oobsize; ++ unsigned long options; ++ unsigned int read_retry_type; ++ ++#define BBP_LAST_PAGE 0x01 ++#define BBP_FIRST_PAGE 0x02 ++ unsigned int badblock_pos; ++ int flags; ++}; ++ ++/*****************************************************************************/ ++/* this is nand probe function. */ ++/*****************************************************************************/ ++ ++static struct nand_flash_dev *hynix_probe_v02(unsigned char *id) ++{ ++ struct nand_flash_dev *type = &g_nand_dev.flash_dev; ++ ++ int pagesizes[] = {_2K, _4K, _8K, 0}; ++ int oobsizes[] = {128, 224, 448, 0, 0, 0, 0, 0}; ++ int blocksizes[] = {_128K, _256K, _512K, _768K, _1M, _2M, 0, 0}; ++ ++ int blocktype = (((id[3] >> 5) & 0x04) | ((id[3] >> 4) & 0x03)); ++ int oobtype = (((id[3] >> 2) & 0x03) | ((id[3] >> 4) & 0x04)); ++ ++ type->options = 0; ++ type->pagesize = pagesizes[(id[3] & 0x03)]; ++ type->erasesize = blocksizes[blocktype]; ++ type->oobsize = oobsizes[oobtype]; ++ ++ return type; ++} ++ ++/*****************************************************************************/ ++static struct nand_flash_dev *samsung_probe_v02(unsigned char *id) ++{ ++ struct nand_flash_dev *type = &g_nand_dev.flash_dev; ++ ++ int pagesizes[] = {_2K, _4K, _8K, 0}; ++ int oobsizes[] = {0, 128, 218, 400, 436, 0, 0, 0}; ++ int blocksizes[] = {_128K, _256K, _512K, _1M, 0, 0, 0, 0}; ++ ++ int blocktype = (((id[3] >> 5) & 0x04) | ((id[3] >> 4) & 0x03)); ++ int oobtype = (((id[3] >> 4) & 0x04) | ((id[3] >> 2) & 0x03)); ++ ++ type->options = 0; ++ type->pagesize = pagesizes[(id[3] & 0x03)]; ++ type->erasesize = blocksizes[blocktype]; ++ type->oobsize = oobsizes[oobtype]; ++ ++ return type; ++} ++ ++/*****************************************************************************/ ++ ++#define DRV_VERSION "1.38" ++ ++/*****************************************************************************/ ++/* ++ * samsung: 27nm need randomizer, 21nm need read retry; ++ * micron: 25nm need read retry, datasheet will explain read retry. ++ * toshaba 32nm need randomizer, 24nm need read retry. ++ * hynix: 2xnm need read retry. ++ * ++ * The special nand flash ID table version 1.38 ++ * ++ * manufactory | type | name | ecc_type | version_tag ++ * Micron | MLC | MT29F64G08CBABA | 40bit/1k | 1.36 ++ * Micron | MLC | MT29F32G08CBADA | 40bit/1k | ++ * Micron | SLC | MT29F8G08ABxBA | 4bit/512 | ++ * Micron | MLC | MT29F16G08CBABx | 12bit/512 | ++ * Micron | MLC | MT29F16G08CBACA | 24bit/1k | ++ * Micron | MLC | MT29F32G08CBACA | 24bit/1k | ++ * Micron | MLC | MT29F64G08CxxAA | 24bit/1k | ++ * Micron | MLC | MT29F256G08CJAAA | 24bit/1k | 2CE ++ * Micron | MLC | MT29F256G08CMCBB | 24bit/1k | ++ * Micron | SLC | MT29F8G08ABACA | 8bit/512 | ++ * Micron | SLC | MT29F4G08ABAEA | 8bit/512 | ++ * Micron | SLC | MT29F2G08ABAFA | 8bit/512 | ++ * Micron | SLC | MT29F16G08ABACA | 8bit/512 | ++ * Toshiba | MLC | TC58NVG4D2FTA00 | 24bit/1k | ++ * Toshiba | MLC | TH58NVG6D2FTA20 | 24bit/1k | 2CE ++ * Toshiba | MLC | TC58NVG5D2HTA00 | 40bit/1k | ++ * Toshiba | MLC | TC58NVG6D2GTA00 | 40bit/1k | ++ * Toshiba | MLC | TC58NVG6DCJTA00 | | ++ * Toshiba | MLC | TC58TEG5DCJTA00 | | ++ * Toshiba | SLC | TC58NVG0S3HTA00 | 8bit/512 | ++ * Toshiba | SLC | TC58NVG1S3HTA00 | 8bit/512 | ++ * Toshiba | SLC | TC58NVG1S3ETA00 | 4bit/512 | ++ * Toshiba | SLC | TC58NVG3S0FTA00 | 4bit/512 | ++ * Toshiba | SLC | TC58NVG2S0FTA00 | 4bit/512 | ++ * Toshiba | SLC | TH58NVG2S3HTA00 | 4bit/512 | ++ * Toshiba | TLC | TC58NVG5T2JTA00 | 60bit/1k | ++ * Toshiba | TLC | TC58TEG5DCKTAx0 | 60bit/1k | ++ * Toshiba | MLC | Tx58TEGxDDKTAx0 | | ++ * Samsung | MLC | K9LB(HC/PD/MD)G08U0(1)D | 8bit/512B | ++ * Samsung | MLC | K9GAG08U0E | 24bit/1KB | ++ * Samsung | MLC | K9LBG08U0E | 24bit/1KB | ++ * Samsung | MLC | K9G8G08U0C | 24bit/1KB | ++ * Samsung | MLC | K9GAG08U0F | 24bit/1KB | ++ * Samsung | MLC | K9LBG08U0M | | ++ * Samsung | MLC | K9GBG08U0A | 24bit/1KB | ++ * Samsung | MLC | K9GBG08U0B | 40bit/1KB | ++ * Hynix | MLC | H27UAG8T2A | | ++ * Hynix | MLC | H27UAG8T2B | | ++ * Hynix | MLC | H27UBG8T2A | | ++ * Hynix | MLC | H27UBG8T2BTR | 24bit/1KB | ++ * Hynix | MLC | H27UCG8T2A | 40bit/1KB | ++ * Hynix | MLC | H27UBG8T2C | 40bit/1KB | ++ * MISC | MLC | P1UAGA30AT-GCA | 8bit/512 | ++ * MISC | MLC | PSU8GA30AT-GIA/ASU8GA30IT-G30CA | 4bit/512 | ++ * MISC | SLC | PSU2GA30AT | 1bit/512 | 1.36 ++ * Toshiba | SLC | TC58NVG2S0HTA00 | 24bit/1K | 1.37 ++ * Toshiba | SLC | TC58NVG3S0HTA00 | 24bit/1K | 1.37 ++ * Micron | SLC | MT29F2G08ABAEA | 4bit/512 | ++ * Spansion | SLC | S34ML02G200TFI000 | 24bit/1K | ++ * Spansion | SLC | S34ML04G200TFI000 | 24bit/1K | 1.38 ++ * ++ */ ++static struct nand_flash_special_dev nand_flash_special_table[] = { ++ ++ /****************************** Spansion *******************************/ ++ ++ { /* SLC S34ML02G200TFI000 */ ++ .name = "S34ML02G200TFI000", ++ .id = {0x01, 0xDA, 0x90, 0x95, 0x46, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _256M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ ++ { /* SLC S34ML04G200TFI000 */ ++ .name = "S34ML04G200TFI000", ++ .id = {0x01, 0xDC, 0x90, 0x95, 0x56, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _512M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ ++ /****************************** Micron *******************************/ ++ ++ { /* MLC 40bit/1k */ ++ .name = "MT29F64G08CBABA", ++ .id = {0x2C, 0x64, 0x44, 0x4B, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _2M, ++ .oobsize = 744, ++ .options = 0, ++ .read_retry_type = NAND_RR_MICRON, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = NAND_RANDOMIZER | NAND_CHIP_MICRON, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "MT29F32G08CBADA", ++ .id = {0x2C, 0x44, 0x44, 0x4B, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _2M, ++ .oobsize = 744, ++ .options = 0, ++ .read_retry_type = NAND_RR_MICRON, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "MT29F8G08ABxBA", ++ .id = {0x2C, 0x38, 0x00, 0x26, 0x85, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _1G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _512K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 12bit/512 */ ++ .name = "MT29F16G08CBABx", ++ .id = {0x2C, 0x48, 0x04, 0x46, 0x85, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _2G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _1M, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "MT29F16G08CBACA", ++ .id = {0x2C, 0x48, 0x04, 0x4A, 0xA5, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _2G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _1M, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "MT29F32G08CBACA", ++ .id = {0x2C, 0x68, 0x04, 0x4A, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _1M, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "MT29F64G08CxxAA", ++ .id = {0x2C, 0x88, 0x04, 0x4B, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _2M, ++ .oobsize = 448, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 24bit/1k 2CE */ ++ .name = "MT29F256G08CJAAA", ++ .id = {0x2C, 0xA8, 0x05, 0xCB, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _16G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _2M, ++ .oobsize = 448, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "MT29F256G08CMCBB", ++ .id = {0x2C, 0x64, 0x44, 0x4B, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _2M, ++ .oobsize = 744, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "MT29F8G08ABACA", ++ .id = {0x2C, 0xD3, 0x90, 0xA6, 0x64, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _1G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _256K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "MT29F4G08ABAEA", ++ .id = {0x2C, 0xDC, 0x90, 0xA6, 0x54, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _512M, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _256K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "MT29F2G08ABAFA", ++ .id = {0x2C, 0xDA, 0x90, 0x95, 0x04, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _256M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC MT29F2G08ABAEA */ ++ .name = "MT29F2G08ABAEA", ++ .id = {0x2C, 0xDA, 0x90, 0x95, 0x06, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _256M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 64, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "MT29F16G08ABACA", ++ .id = {0x2C, 0x48, 0x00, 0x26, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _2G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _512K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ ++ /****************************** Toshaba *******************************/ ++ ++ { /* MLC 24bit/1k 32nm */ ++ .name = "TC58NVG4D2FTA00", ++ .id = {0x98, 0xD5, 0x94, 0x32, 0x76, 0x55, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _2G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _1M, ++ .oobsize = 448, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k 32nm 2CE*/ ++ .name = "TH58NVG6D2FTA20", ++ .id = {0x98, 0xD7, 0x94, 0x32, 0x76, 0x55, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _1M, ++ .oobsize = 448, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 40bit/1k 24nm */ ++ .name = "TC58NVG5D2HTA00 24nm", ++ .id = {0x98, 0xD7, 0x94, 0x32, 0x76, 0x56, 0x08, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _1M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_24nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "TC58NVG6D2GTA00", ++ .id = {0x98, 0xDE, 0x94, 0x82, 0x76, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _2M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 19nm */ ++ .name = "TC58NVG6DCJTA00 19nm", ++ .id = {0x98, 0xDE, 0x84, 0x93, 0x72, 0x57, 0x08, 0x04}, ++ .length = 8, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = _16K, ++ .erasesize = _4M, ++ .oobsize = 1280, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_24nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 19nm */ ++ .name = "TC58TEG5DCJTA00 19nm", ++ .id = {0x98, 0xD7, 0x84, 0x93, 0x72, 0x57, 0x08, 0x04}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _16K, ++ .erasesize = _4M, ++ .oobsize = 1280, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_24nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER | NAND_CHIP_TOSHIBA_TOGGLE_10, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "TC58NVG0S3HTA00", ++ .id = {0x98, 0xF1, 0x80, 0x15, 0x72, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _128M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ /* ++ * Datasheet: read one column of any page in each block. If the ++ * data of the column is 00 (Hex), define the block as a bad ++ * block. ++ */ ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "TC58NVG1S3HTA00", ++ .id = {0x98, 0xDA, 0x90, 0x15, 0x76, 0x16, 0x08, 0x00}, ++ .length = 7, ++ .chipsize = _256M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "TC58NVG1S3ETA00", ++ .id = {0x98, 0xDA, 0x90, 0x15, 0x76, 0x14, 0x03, 0x00}, ++ .length = 7, ++ .chipsize = _256M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 64, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "TC58NVG3S0FTA00", ++ .id = {0x98, 0xD3, 0x90, 0x26, 0x76, 0x15, 0x02, 0x08}, ++ .length = 8, ++ .chipsize = _1G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _256K, ++ .oobsize = 232, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 24bit/1k */ ++ .name = "TC58NVG3S0HTA00", ++ .id = {0x98, 0xD3, 0x91, 0x26, 0x76, 0x16, 0x08, 0x00}, ++ .length = 8, ++ .chipsize = _1G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _256K, ++ .oobsize = 256, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 24bit/1k */ ++ .name = "TC58NVG2S0HTA00", ++ .id = {0x98, 0xDC, 0x90, 0x26, 0x76, 0x16, 0x08, 0x00}, ++ .length = 8, ++ .chipsize = _512M, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _256K, ++ .oobsize = 256, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "TC58NVG2S0FTA00", ++ .id = {0x98, 0xDC, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08}, ++ .length = 8, ++ .chipsize = _512M, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _256K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "TH58NVG2S3HTA00", ++ .id = {0x98, 0xDC, 0x91, 0x15, 0x76}, ++ .length = 5, ++ .chipsize = _512M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* TLC 60bit/1k 19nm */ ++ .name = "TC58NVG5T2JTA00 19nm TLC", ++ /* datasheet says 6 ids id data, but really has 8 ids. */ ++ .id = {0x98, 0xD7, 0x98, 0x92, 0x72, 0x57, 0x08, 0x10}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _4M, ++ .oobsize = 1024, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_24nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* TLC 60bit/1k 19nm */ ++ .name = "TC58TEG5DCKTAx0 19nm MLC", ++ /* datasheet says 6 ids id data, but really has 8 ids. */ ++ .id = {0x98, 0xD7, 0x84, 0x93, 0x72, 0x50, 0x08, 0x04}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _16K, ++ .erasesize = _4M, ++ .oobsize = 1280, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_19nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { ++ .name = "Tx58TEGxDDKTAx0 19nm MLC", ++ .id = {0x98, 0xDE, 0x94, 0x93, 0x76, 0x50}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _16K, ++ .erasesize = _4M, ++ .oobsize = 1280, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_19nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ /******************************* Samsung ******************************/ ++ { /* MLC 8bit/512B */ ++ .name = "K9LB(HC/PD/MD)G08U0(1)D", ++ .id = {0xEC, 0xD7, 0xD5, 0x29, 0x38, 0x41, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = samsung_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1KB */ ++ .name = "K9GAG08U0E", ++ .id = {0xEC, 0xD5, 0x84, 0x72, 0x50, 0x42, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _2G, ++ .probe = samsung_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1KB */ ++ .name = "K9LBG08U0E", ++ .id = {0xEC, 0xD7, 0xC5, 0x72, 0x54, 0x42, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = samsung_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1KB */ ++ .name = "K9G8G08U0C", ++ .id = {0xEC, 0xD3, 0x84, 0x72, 0x50, 0x42, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _1G, ++ .probe = samsung_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "K9GAG08U0F", ++ .id = {0xEC, 0xD5, 0x94, 0x76, 0x54, 0x43, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _2G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _1M, ++ .oobsize = 512, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC */ ++ .name = "K9LBG08U0M", ++ .id = {0xEC, 0xD7, 0x55, 0xB6, 0x78, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _512K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "K9GBG08U0A 20nm", ++ .id = {0xEC, 0xD7, 0x94, 0x7A, 0x54, 0x43, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _1M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_SAMSUNG, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "K9GBG08U0B", ++ .id = {0xEC, 0xD7, 0x94, 0x7E, 0x64, 0x44, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _1M, ++ .oobsize = 1024, ++ .options = 0, ++ .read_retry_type = NAND_RR_SAMSUNG, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ ++ /*********************************** Hynix ****************************/ ++ { /* MLC */ ++ .name = "H27UAG8T2A", ++ .id = {0xAD, 0xD5, 0x94, 0x25, 0x44, 0x41, }, ++ .length = 6, ++ .chipsize = _2G, ++ .probe = hynix_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC */ ++ .name = "H27UAG8T2B", ++ .id = {0xAD, 0xD5, 0x94, 0x9A, 0x74, 0x42, }, ++ .length = 6, ++ .chipsize = _2G, ++ .probe = hynix_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC */ ++ .name = "H27UBG8T2A", ++ .id = {0xAD, 0xD7, 0x94, 0x9A, 0x74, 0x42, }, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = hynix_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1K, 26nm TODO: Need read retry, chip is EOS */ ++ .name = "H27UBG8T2BTR 26nm", ++ .id = {0xAD, 0xD7, 0x94, 0xDA, 0x74, 0xC3, }, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _2M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_HYNIX_BG_BDIE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "H27UCG8T2A", ++ .id = {0xAD, 0xDE, 0x94, 0xDA, 0x74, 0xC4, }, ++ .length = 6, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _2M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_HYNIX_CG_ADIE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "H27UBG8T2C", ++ .id = {0xAD, 0xD7, 0x94, 0x91, 0x60, 0x44, }, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = _8K, ++ .erasesize = _2M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_HYNIX_BG_CDIE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ ++ /********************** MISC ******************************************/ ++ { /* MLC 8bit/512 */ ++ .name = "P1UAGA30AT-GCA", ++ .id = {0xC8, 0xD5, 0x14, 0x29, 0x34, 0x01, }, ++ .length = 6, ++ .chipsize = _2G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _512K, ++ .oobsize = 218, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 4bit/512 */ ++ /* ++ * PowerFlash ASU8GA30IT-G30CA ID and MIRA PSU8GA30AT-GIA ID are ++ * the same ID ++ */ ++ .name = "PSU8GA30AT-GIA/ASU8GA30IT-G30CA", ++ .id = {0xC8, 0xD3, 0x90, 0x19, 0x34, 0x01, }, ++ .length = 6, ++ .chipsize = _1G, ++ .probe = NULL, ++ .pagesize = _4K, ++ .erasesize = _256K, ++ .oobsize = 218, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 1bit/512 */ ++ .name = "PSU2GA30AT", ++ .id = {0x7F, 0x7F, 0x7F, 0x7F, 0xC8, 0xDA, 0x00, 0x15, }, ++ .length = 8, ++ .chipsize = _256M, ++ .probe = NULL, ++ .pagesize = _2K, ++ .erasesize = _128K, ++ .oobsize = 64, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ {{0}, 0, 0, 0, 0, 0, 0, 0, 0}, ++}; ++ ++struct nand_dev_t g_nand_dev; ++/*****************************************************************************/ ++struct nand_flash_dev *hifmc_get_spl_flash_type(struct mtd_info *mtd, ++ unsigned char *id) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct nand_flash_special_dev *spl_dev = nand_flash_special_table; ++ struct nand_flash_dev *type = &g_nand_dev.flash_dev; ++ struct nand_dev_t *nand_dev = &g_nand_dev; ++ ++ FMC_PR(BT_DBG, "\t *-Start find special nand flash\n"); ++ ++ pr_info("Nand ID: %#X %#X %#X %#X %#X %#X %#X %#X\n", id[0], id[1], ++ id[2], id[3], id[4], id[5], id[6], id[7]); ++ ++ for (; spl_dev->length; spl_dev++) { ++ if (memcmp(id, spl_dev->id, spl_dev->length)) ++ continue; ++ ++ FMC_PR(BT_DBG, "\t |-Found special Nand flash: %s\n", ++ spl_dev->name); ++ ++ if (spl_dev->probe) { ++ type = spl_dev->probe(id); ++ } else { ++ type->options = spl_dev->options; ++ type->pagesize = spl_dev->pagesize; ++ type->erasesize = spl_dev->erasesize; ++ type->oobsize = spl_dev->oobsize; ++ } ++ ++ type->name = spl_dev->name; ++ type->id_len = spl_dev->length; ++ memcpy(type->id, id, type->id_len); ++ type->chipsize = (unsigned int)(spl_dev->chipsize >> 20); ++ FMC_PR(BT_DBG, "\t |-Save struct nand_flash_dev info\n"); ++ ++ memcpy(nand_dev->ids, id, MAX_NAND_ID_LEN); ++ nand_dev->oobsize = type->oobsize; ++ nand_dev->flags = spl_dev->flags; ++ nand_dev->read_retry_type = spl_dev->read_retry_type; ++ FMC_PR(BT_DBG, "\t |-Save struct nand_dev_t information\n"); ++ ++ mtd->size = spl_dev->chipsize; ++ ++ return type; ++ } ++ nand_dev->read_retry_type = NAND_RR_NONE; ++ ++ chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); ++ chip->read_byte(mtd); ++ chip->read_byte(mtd); ++ ++ FMC_PR(BT_DBG, "\t *-Not found special nand flash\n"); ++ ++ return NULL; ++} ++ ++/*****************************************************************************/ ++void hifmc_spl_ids_register(void) ++{ ++ pr_info("Special NAND id table Version %s\n", DRV_VERSION); ++ get_spi_nand_flash_type_hook = hifmc_get_spl_flash_type; ++} +diff --git a/drivers/mtd/nand/hinfc610/Kconfig b/drivers/mtd/nand/hinfc610/Kconfig +new file mode 100644 +index 0000000..7d9dbbe +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/Kconfig +@@ -0,0 +1,100 @@ ++menuconfig MTD_NAND_HINFC610 ++ tristate "Hisilicon NAND Controller v610 device Support" ++ depends on MTD_NAND ++ default y if ARCH_HI3531D ++ select YAFFS_FS ++ select MISC_FILESYSTEMS ++ select MTD_BLOCK ++ select YAFFS_YAFFS2 ++ help ++ When the config is set, the kernel will support Hisilicon ++ NAND Controller v610 device. It means that the kernel would ++ control the nand flash with the nand controller v610 device ++ in operation. ++ ++if MTD_NAND_HINFC610 ++ ++config MTD_PARTITION_FROM_DTS ++ bool "get the mtd partition from devicetree" ++ default n ++ help ++ Get the mtd partition info from devicetree list. ++ ++config HINFC610_MAX_CHIP ++ int "number of nand flash chip (1,4)" ++ default 1 ++ help ++ nand controller v610 device only support 1 or 2 nand flash chip, ++ your should not config other value. ++ ++config HINFC610_DBG_NAND_DEBUG ++ bool "Debug: create debug file to control debug type" ++ default y ++ help ++ When the config is set, the kernel will add the "debug" file ++ to control debug type. When the config is set, we could choose ++ the debugging type to display the informations of the nand controller ++ v610 device in operation. ++ ++config HINFC610_DBG_NAND_DUMP ++ bool "Debug: display read/write/erase process nand data" ++ depends on HINFC610_DBG_NAND_DEBUG ++ default y ++ default n if (ARCH_HI3531D) ++ help ++ When the config is set, the kernel will add "dump" file to ++ display all nand operation and data.When the "HINFC610_DBG_NAND_DEBUG" ++ has been set, the nand controller v610 device will display ++ all the operations and data. ++ ++config HINFC610_DBG_NAND_ERASE_COUNT ++ bool "Debug: display last erase count" ++ depends on HINFC610_DBG_NAND_DEBUG ++ default y ++ default n if (ARCH_HI3531D) ++ help ++ When the config is set, the kernel will add "erase_count" file ++ to display last erase count. When the "HINFC610_DBG_NAND_DEBUG" ++ has been set, the nand controller v610 device will display ++ the last erase count. ++ ++config HINFC610_DBG_NAND_ECC_COUNT ++ bool "Debug: display last ecc count." ++ depends on HINFC610_DBG_NAND_DEBUG ++ default y ++ default n if (ARCH_HI3531D) ++ help ++ When the config is set, the kernel will add "ecc_count" ++ to display last ecc count. When the "HINFC610_DBG_NAND_DEBUG" ++ has been set, the nand controller v610 device will display ++ the last ecc count. ++ ++config HINFC610_DBG_NAND_READ_RETRY ++ bool "Debug: display read_retry process" ++ depends on HINFC610_DBG_NAND_DEBUG ++ default y ++ default n if (ARCH_HI3531D) ++ help ++ When the config is set, the kernel will add read_retry file ++ to display read_retry process. ++ ++choice ++ prompt "Pagesize and Ecc Type Select" ++ default HINFC610_AUTO_PAGESIZE_ECC if ARCH_HI3531D ++ ++config HINFC610_AUTO_PAGESIZE_ECC ++ bool "Auto" ++ help ++ When the config is set, pagesize and ecc type will use ++ hardware config. When we replace the flash, the ++ controller will identify the pagesize and ecc type of ++ the flash. ++ ++config HINFC610_PAGESIZE_AUTO_ECC_NONE ++ bool "Pagesize Auto, Ecc None" ++ help ++ select pagesize 2K, ecc none. ++ ++endchoice ++ ++endif # MTD_NAND_HINFC610 +diff --git a/drivers/mtd/nand/hinfc610/Makefile b/drivers/mtd/nand/hinfc610/Makefile +new file mode 100644 +index 0000000..9ef9acd +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/Makefile +@@ -0,0 +1,19 @@ ++ ++obj-$(CONFIG_MTD_NAND_HINFC610) += hinfc610.o hinfc610_os.o hinfc610_gen.o \ ++ hinfc620_gen.o hinfc610_dbg_inf.o \ ++ hinfc610_read_retry_hynix_bg_cdie.o \ ++ hinfc610_read_retry_hynix_bg_bdie.o \ ++ hinfc610_read_retry_hynix_cg_adie.o \ ++ hinfc610_read_retry_micron.o \ ++ hinfc610_read_retry_samsung.o \ ++ hinfc610_read_retry_toshiba.o \ ++ hinfc610_read_retry.o \ ++ hinfc610_sync.o \ ++ hinfc610_sync_onfi_23.o \ ++ hinfc610_sync_toggle.o ++ ++obj-$(CONFIG_HINFC610_DBG_NAND_DEBUG) += hinfc610_dbg.o hinfc610_dbg_ecc_dump.o ++obj-$(CONFIG_HINFC610_DBG_NAND_DUMP) += hinfc610_dbg_dump.o ++obj-$(CONFIG_HINFC610_DBG_NAND_ERASE_COUNT) += hinfc610_dbg_erase_count.o ++obj-$(CONFIG_HINFC610_DBG_NAND_ECC_COUNT) += hinfc610_dbg_ecc_count.o ++obj-$(CONFIG_HINFC610_DBG_NAND_READ_RETRY) += hinfc610_dbg_read_retry.o +diff --git a/drivers/mtd/nand/hinfc610/hinfc610.c b/drivers/mtd/nand/hinfc610/hinfc610.c +new file mode 100644 +index 0000000..4be2451 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610.c +@@ -0,0 +1,1154 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#define pr_fmt(fmt) "hinfc610: " fmt ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++#include "hinfc610_dbg_inf.h" ++#include "hinfc610_gen.h" ++#include "hinfc620_gen.h" ++#include "hinfc610_sync.h" ++#include "hinfc610_read_retry.h" ++ ++/*****************************************************************************/ ++static unsigned int get_8bits(unsigned char byte) ++{ ++ int ix = 0; ++ int num = 0; ++ ++ if (byte == 0xFF) ++ return 8; ++ if (!byte) ++ return 0; ++ ++ while (ix++ < 8) { ++ if ((byte & 1)) ++ num++; ++ byte = (byte >> 1); ++ } ++ return num; ++} ++/*****************************************************************************/ ++ ++static unsigned int get_16bits(unsigned short byte) ++{ ++ int ix = 0; ++ int num = 0; ++ ++ if (byte == 0xFFFF) ++ return 16; ++ if (!byte) ++ return 0; ++ ++ while (ix++ < 16) { ++ if ((byte & 1)) ++ num++; ++ byte = (byte >> 1); ++ } ++ return num; ++} ++/*****************************************************************************/ ++ ++static void hinfc610_dma_transfer(struct hinfc_host *host, int todev) ++{ ++ unsigned long reg_val; ++ unsigned int dma_addr = (unsigned int)host->dma_buffer; ++ ++ hinfc_write(host, dma_addr, HINFC610_DMA_ADDR_DATA); ++ ++ dma_addr += HINFC610_DMA_ADDR_OFFSET; ++ hinfc_write(host, dma_addr, HINFC610_DMA_ADDR_DATA1); ++ ++ dma_addr += HINFC610_DMA_ADDR_OFFSET; ++ hinfc_write(host, dma_addr, HINFC610_DMA_ADDR_DATA2); ++ ++ dma_addr += HINFC610_DMA_ADDR_OFFSET; ++ hinfc_write(host, dma_addr, HINFC610_DMA_ADDR_DATA3); ++ ++ /* 32K PAGESIZE need below. */ ++ dma_addr += HINFC610_DMA_ADDR_OFFSET; ++ hinfc_write(host, dma_addr, HINFC610_DMA_ADDR_DATA4); ++ ++ dma_addr += HINFC610_DMA_ADDR_OFFSET; ++ hinfc_write(host, dma_addr, HINFC610_DMA_ADDR_DATA5); ++ ++ dma_addr += HINFC610_DMA_ADDR_OFFSET; ++ hinfc_write(host, dma_addr, HINFC610_DMA_ADDR_DATA6); ++ ++ dma_addr += HINFC610_DMA_ADDR_OFFSET; ++ hinfc_write(host, dma_addr, HINFC610_DMA_ADDR_DATA7); ++ ++ hinfc_write(host, host->dma_oob, HINFC610_DMA_ADDR_OOB); ++ ++ if (host->ecctype == NAND_ECC_NONE) { ++ hinfc_write(host, ++ ((host->oobsize & HINFC610_DMA_LEN_OOB_MASK) ++ << HINFC610_DMA_LEN_OOB_SHIFT), ++ HINFC610_DMA_LEN); ++ ++ hinfc_write(host, ++ HINFC610_DMA_PARA_DATA_RW_EN ++ | HINFC610_DMA_PARA_OOB_RW_EN, ++ HINFC610_DMA_PARA); ++ } else ++ hinfc_write(host, ++ HINFC610_DMA_PARA_DATA_RW_EN ++ | HINFC610_DMA_PARA_OOB_RW_EN ++ | HINFC610_DMA_PARA_DATA_EDC_EN ++ | HINFC610_DMA_PARA_OOB_EDC_EN, ++ HINFC610_DMA_PARA); ++ ++ reg_val = (HINFC610_DMA_CTRL_DMA_START ++ | HINFC610_DMA_CTRL_BURST4_EN ++ | HINFC610_DMA_CTRL_BURST8_EN ++ | HINFC610_DMA_CTRL_BURST16_EN ++ | ((host->addr_cycle == 4 ? 1 : 0) ++ << HINFC610_DMA_CTRL_ADDR_NUM_SHIFT) ++ | (((unsigned int)host->chipselect & HINFC610_DMA_CTRL_CS_MASK) ++ << HINFC610_DMA_CTRL_CS_SHIFT)); ++ ++ if (todev) ++ reg_val |= HINFC610_DMA_CTRL_WE; ++ ++ hinfc_write(host, reg_val, HINFC610_DMA_CTRL); ++ ++ do { ++ unsigned int timeout = 0xF0000000; ++ ++ while ((hinfc_read(host, HINFC610_DMA_CTRL)) ++ & HINFC610_DMA_CTRL_DMA_START && timeout) { ++ _cond_resched(); ++ timeout--; ++ } ++ if (!timeout) ++ PR_BUG("Wait DMA finish timeout.\n"); ++ } while (0); ++} ++/*****************************************************************************/ ++ ++static void hinfc610_sync_entry(struct hinfc_host *host) ++{ ++ struct nand_sync *sync = host->sync; ++ struct nand_chip *chip = host->chip; ++ ++ if (!sync) { ++ PR_BUG("this NAND not support sync feature.\n"); ++ return; ++ } ++ ++ if (HINFC610_IS_SYNC(host)) { ++ PR_BUG("this NAND not support sync feature.\n"); ++ return; ++ } ++ ++ if (sync->enable) ++ sync->enable(chip); ++ ++ clk_prepare_enable(host->clk); ++ ++ switch (sync->type) { ++ case NAND_TYPE_TOGGLE_10: ++ host->NFC_CON |= HINFC610_CON_NF_MODE_TOGGLE; ++ host->NFC_CON_ECC_NONE |= HINFC610_CON_NF_MODE_TOGGLE; ++ break; ++ ++ case NAND_TYPE_ONFI_23: ++ host->NFC_CON |= HINFC610_CON_NF_MODE_ONFI_23; ++ host->NFC_CON_ECC_NONE |= HINFC610_CON_NF_MODE_ONFI_23; ++ break; ++ ++ case NAND_TYPE_ONFI_30: ++ host->NFC_CON |= HINFC610_CON_NF_MODE_ONFI_30; ++ host->NFC_CON_ECC_NONE |= HINFC610_CON_NF_MODE_ONFI_30; ++ break; ++ ++ default: ++ PR_BUG("Unsupport sync type 0x%08X.\n", sync->type); ++ break; ++ } ++} ++/*****************************************************************************/ ++ ++static void hinfc610_sync_exit(struct hinfc_host *host) ++{ ++ struct nand_sync *sync = host->sync; ++ struct nand_chip *chip = host->chip; ++ ++ if (!HINFC610_IS_SYNC(host)) { ++ PR_BUG("Current already exit from sync feature.\n"); ++ return; ++ } ++ ++ if (sync->disable) ++ sync->disable(chip); ++ ++ host->NFC_CON &= ~HINFC610_CON_NF_MODE_MASK; ++ host->NFC_CON_ECC_NONE &= ~HINFC610_CON_NF_MODE_MASK; ++ ++ clk_disable_unprepare(host->clk); ++} ++/*****************************************************************************/ ++ ++void hinfc610_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) ++{ ++ int is_cache_invalid = 1; ++ struct nand_chip *chip = mtd->priv; ++ struct hinfc_host *host = chip->priv; ++ ++ if (ctrl & NAND_ALE) { ++ unsigned int addr_value = 0; ++ unsigned int addr_offset = 0; ++ ++ if (ctrl & NAND_CTRL_CHANGE) { ++ host->addr_cycle = 0x0; ++ host->addr_value[0] = 0x0; ++ host->addr_value[1] = 0x0; ++ } ++ addr_offset = host->addr_cycle << 3; ++ ++ if (host->addr_cycle >= HINFC610_ADDR_CYCLE_MASK) { ++ addr_offset = ++ (host->addr_cycle - HINFC610_ADDR_CYCLE_MASK) << 3; ++ addr_value = 1; ++ } ++ ++ host->addr_value[addr_value] |= ++ ((dat & 0xff) << addr_offset); ++ ++ host->addr_cycle++; ++ } ++ ++ if ((ctrl & NAND_CLE) && (ctrl & NAND_CTRL_CHANGE)) { ++ host->command = dat & 0xff; ++ switch (host->command) { ++ case NAND_CMD_PAGEPROG: ++ host->send_cmd_pageprog(host); ++ hinfc610_dbg_write(host); ++ break; ++ ++ case NAND_CMD_READSTART: ++ is_cache_invalid = 0; ++ host->send_cmd_readstart(host); ++ hinfc610_dbg_read(host); ++ ++ break; ++ ++ case NAND_CMD_ERASE2: ++ host->send_cmd_erase(host); ++ hinfc610_dbg_erase(host); ++ ++ break; ++ ++ case NAND_CMD_READID: ++ memset((unsigned char *)(chip->IO_ADDR_R), 0, 0x10); ++ host->send_cmd_readid(host); ++ break; ++ ++ case NAND_CMD_STATUS: ++ host->send_cmd_status(host); ++ break; ++ ++ case NAND_CMD_SEQIN: ++ case NAND_CMD_ERASE1: ++ case NAND_CMD_READ0: ++ break; ++ case NAND_CMD_RESET: ++ host->send_cmd_reset(host, host->chipselect); ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ if ((dat == NAND_CMD_NONE) && host->addr_cycle) { ++ if (host->command == NAND_CMD_SEQIN || ++ host->command == NAND_CMD_READ0 || ++ host->command == NAND_CMD_READID) { ++ host->offset = 0x0; ++ host->column = (host->addr_value[0] & 0xffff); ++ } ++ } ++ ++ if (is_cache_invalid) { ++ host->cache_addr_value[0] = ~0; ++ host->cache_addr_value[1] = ~0; ++ } ++} ++/*****************************************************************************/ ++ ++static int hinfc610_send_cmd_pageprog(struct hinfc_host *host) ++{ ++ if (*host->bbm != 0xFF && *host->bbm != 0x00) ++ pr_warn("Attempt to write an invalid bbm. page: 0x%08x, mark: 0x%02x, current process(pid): %s(%d).\n", ++ GET_PAGE_INDEX(host), *host->bbm, ++ current->comm, current->pid); ++ ++ if (IS_NAND_SYNC_ASYNC(host)) ++ hinfc610_sync_entry(host); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ hinfc_write(host, host->addr_value[0] & 0xffff0000, HINFC610_ADDRL); ++ hinfc_write(host, host->addr_value[1], HINFC610_ADDRH); ++ hinfc_write(host, ++ ((NAND_CMD_STATUS << 16) | (NAND_CMD_PAGEPROG << 8) | ++ NAND_CMD_SEQIN), ++ HINFC610_CMD); ++ ++ *host->epm = 0x0000; ++ ++ hinfc610_dma_transfer(host, 1); ++ ++ if (IS_NAND_SYNC_ASYNC(host)) ++ hinfc610_sync_exit(host); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_get_data_status(struct hinfc_host *host) ++{ ++ unsigned int page_status = 0; ++ ++ if (IS_PS_UN_ECC(host)) ++ page_status = HINFC610_PS_UC_ECC; ++ ++ /* this is block start address */ ++ if (!((host->addr_value[0] >> 16) & host->block_page_mask)) { ++ ++ /* it is a bad block */ ++ if (*host->bbm == 0x00) { ++ page_status |= HINFC610_PS_BAD_BLOCK; ++ goto out; ++ } ++ ++ if (*host->bbm != 0xFF) { ++ page_status |= HINFC610_PS_BBM_ERROR; ++ ++ /* ++ * if there are more than 2 bits flipping, it is ++ * maybe a bad block ++ */ ++ if (!IS_PS_UN_ECC(host) || get_8bits(*host->bbm) < 6) { ++ page_status |= HINFC610_PS_BAD_BLOCK; ++ goto out; ++ } ++ } ++ } ++ ++ if (*host->epm == 0x0000) ++ goto out; ++ ++ if (*host->epm == 0xFFFF) { ++ page_status |= HINFC610_PS_EMPTY_PAGE; ++ goto out; ++ } ++ ++ page_status |= HINFC610_PS_EPM_ERROR; ++ ++ if (IS_PS_UN_ECC(host) && get_16bits(*host->epm) > 12) { ++ page_status |= HINFC610_PS_EMPTY_PAGE; ++ goto out; ++ } ++ ++out: ++ return page_status; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_do_read_retry(struct hinfc_host *host) ++{ ++ int ix; ++ ++ for (ix = 1; IS_PS_UN_ECC(host) && ix < host->read_retry->count; ix++) { ++ ++ hinfc_write(host, HINFC610_INTCLR_UE | HINFC610_INTCLR_CE, ++ HINFC610_INTCLR); ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ host->read_retry->set_rr_param(host, ix); ++ ++ /* enable ecc and randomizer */ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ hinfc_write(host, HINFC610_INTCLR_UE | HINFC610_INTCLR_CE, ++ HINFC610_INTCLR); ++ hinfc_write(host, host->NFC_CON, HINFC610_CON); ++ hinfc_write(host, host->addr_value[0] & 0xffff0000, ++ HINFC610_ADDRL); ++ hinfc_write(host, host->addr_value[1], HINFC610_ADDRH); ++ hinfc_write(host, ++ HINFC_CMD_SEQ(NAND_CMD_READ0, NAND_CMD_READSTART), ++ HINFC610_CMD); ++ ++ hinfc610_dma_transfer(host, 0); ++ ++ if (hinfc_read(host, HINFC610_INTS) & HINFC610_INTS_UE) ++ host->page_status |= HINFC610_PS_UC_ECC; ++ else ++ host->page_status &= ~HINFC610_PS_UC_ECC; ++ } ++ ++ host->page_status = hinfc610_get_data_status(host); ++ ++ hinfc610_dbg_read_retry(host, ix); ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ host->read_retry->reset_rr_param(host); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_send_cmd_readstart(struct hinfc_host *host) ++{ ++ if ((host->addr_value[0] == host->cache_addr_value[0]) && ++ (host->addr_value[1] == host->cache_addr_value[1])) ++ return 0; ++ ++ if (IS_NAND_SYNC_ASYNC(host)) ++ hinfc610_sync_entry(host); ++ ++ host->page_status = 0; ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ hinfc_write(host, HINFC610_INTCLR_UE | HINFC610_INTCLR_CE, ++ HINFC610_INTCLR); ++ hinfc_write(host, host->NFC_CON, HINFC610_CON); ++ hinfc_write(host, host->addr_value[0] & 0xffff0000, HINFC610_ADDRL); ++ hinfc_write(host, host->addr_value[1], HINFC610_ADDRH); ++ hinfc_write(host, NAND_CMD_READSTART << 8 | NAND_CMD_READ0, ++ HINFC610_CMD); ++ ++ hinfc610_dma_transfer(host, 0); ++ ++ if (hinfc_read(host, HINFC610_INTS) & HINFC610_INTS_UE) ++ host->page_status |= HINFC610_PS_UC_ECC; ++ ++ if (host->read_retry || IS_NAND_RANDOM(host)) { ++ host->page_status |= hinfc610_get_data_status(host); ++ ++ if (IS_PS_EMPTY_PAGE(host)) { ++ /* ++ * oob area used by yaffs2 only 32 bytes, ++ * so we only fill 32 bytes. ++ */ ++ if (IS_NAND_RANDOM(host)) ++ memset(host->buffer, 0xFF, ++ host->pagesize + host->oobsize); ++ ++ } else if (!IS_PS_BAD_BLOCK(host)) { ++ /* if NAND chip support read retry */ ++ if (IS_PS_UN_ECC(host) && host->read_retry) ++ hinfc610_do_read_retry(host); ++ ++ } /* 'else' NAND have a bad block, do nothing. */ ++ } ++ ++ if (IS_NAND_SYNC_ASYNC(host)) ++ hinfc610_sync_exit(host); ++ ++ host->cache_addr_value[0] = host->addr_value[0]; ++ host->cache_addr_value[1] = host->addr_value[1]; ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_send_cmd_erase(struct hinfc_host *host) ++{ ++ unsigned int regval; ++ ++ /* Don't case the read retry config */ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, host->addr_value[0], HINFC610_ADDRL); ++ hinfc_write(host, (NAND_CMD_ERASE2 << 8) | NAND_CMD_ERASE1, ++ HINFC610_CMD); ++ ++ regval = HINFC610_OP_WAIT_READY_EN ++ | HINFC610_OP_CMD2_EN ++ | HINFC610_OP_CMD1_EN ++ | HINFC610_OP_ADDR_EN ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) ++ << HINFC610_OP_NF_CS_SHIFT) ++ | ((host->addr_cycle & HINFC610_OP_ADDR_CYCLE_MASK) ++ << HINFC610_OP_ADDR_CYCLE_SHIFT); ++ ++ hinfc_write(host, regval, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_send_cmd_sync_readid(struct hinfc_host *host) ++{ ++ unsigned int regval; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, HINFC610_NANDINFO_LEN, HINFC610_DATA_NUM); ++ hinfc_write(host, NAND_CMD_READID, HINFC610_CMD); ++ hinfc_write(host, 0, HINFC610_ADDRL); ++ ++ /* no need to config HINFC610_OP_WAIT_READY_EN, here not config. */ ++ regval = HINFC610_OP_CMD1_EN ++ | HINFC610_OP_ADDR_EN ++ | HINFC610_OP_READ_DATA_EN ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) ++ << HINFC610_OP_NF_CS_SHIFT) ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT) ++ | HINFC610_OP_READID_EN ++ | HINFC610_OP_RW_REG_EN; ++ ++ hinfc_write(host, regval, HINFC610_OP); ++ ++ host->addr_cycle = 0x0; ++ ++ WAIT_CONTROLLER_FINISH(); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_send_cmd_async_readid(struct hinfc_host *host) ++{ ++ unsigned int regval; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, HINFC610_NANDINFO_LEN, HINFC610_DATA_NUM); ++ hinfc_write(host, NAND_CMD_READID, HINFC610_CMD); ++ hinfc_write(host, 0, HINFC610_ADDRL); ++ ++ /* no need to config HINFC610_OP_WAIT_READY_EN, here not config. */ ++ regval = HINFC610_OP_CMD1_EN ++ | HINFC610_OP_ADDR_EN ++ | HINFC610_OP_READ_DATA_EN ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) ++ << HINFC610_OP_NF_CS_SHIFT) ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT); ++ ++ hinfc_write(host, regval, HINFC610_OP); ++ ++ host->addr_cycle = 0x0; ++ ++ WAIT_CONTROLLER_FINISH(); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_send_cmd_readid(struct hinfc_host *host) ++{ ++ if (HINFC610_IS_SYNC(host)) ++ return hinfc610_send_cmd_sync_readid(host); ++ else ++ return hinfc610_send_cmd_async_readid(host); ++} ++/*****************************************************************************/ ++ ++static int hinfc610_enable_ecc_randomizer(struct hinfc_host *host, int ecc_en, ++ int randomizer_en) ++{ ++ unsigned int nfc_con; ++ ++ if (IS_NAND_RANDOM(host)) { ++ if (randomizer_en) { ++ host->NFC_CON |= HINFC610_CON_RANDOMIZER_EN; ++ host->NFC_CON_ECC_NONE |= HINFC610_CON_RANDOMIZER_EN; ++ } else { ++ host->NFC_CON &= ~HINFC610_CON_RANDOMIZER_EN; ++ host->NFC_CON_ECC_NONE &= ~HINFC610_CON_RANDOMIZER_EN; ++ } ++ } ++ ++ nfc_con = (ecc_en ? host->NFC_CON : host->NFC_CON_ECC_NONE); ++ ++ hinfc_write(host, nfc_con, HINFC610_CON); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_send_cmd_status(struct hinfc_host *host) ++{ ++ unsigned int regval; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, HINFC610_NANDINFO_LEN, HINFC610_DATA_NUM); ++ hinfc_write(host, NAND_CMD_STATUS, HINFC610_CMD); ++ ++ /* no need config HINFC610_OP_WAIT_READY_EN, here not config */ ++ regval = HINFC610_OP_CMD1_EN ++ | HINFC610_OP_READ_DATA_EN ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) ++ << HINFC610_OP_NF_CS_SHIFT); ++ ++ hinfc_write(host, regval, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++static int hinfc610_send_cmd_async_reset(struct hinfc_host *host, ++ int chipselect) ++{ ++ unsigned int regval; ++ ++ hinfc_write(host, NAND_CMD_RESET, HINFC610_CMD); ++ ++ /* need to config HINFC610_OP_WAIT_READY_EN */ ++ regval = HINFC610_OP_CMD1_EN ++ | ((((unsigned int)chipselect & HINFC610_OP_NF_CS_MASK) ++ << HINFC610_OP_NF_CS_SHIFT) ++ | HINFC610_OP_WAIT_READY_EN); ++ ++ hinfc_write(host, regval, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_send_cmd_sync_reset(struct hinfc_host *host, ++ int chipselect) ++{ ++ unsigned int regval; ++ ++ /* ++ * Regarding the ONFI chip sync mode, ++ * NAND_CMD_SYNC_RESET make chip remain sync mode. ++ * But NAND_CMD_RESET will change chip mode to async mode. ++ */ ++ hinfc_write(host, NAND_CMD_SYNC_RESET, HINFC610_CMD); ++ ++ /* need to config HINFC610_OP_WAIT_READY_EN */ ++ regval = HINFC610_OP_CMD1_EN ++ | (((unsigned int)chipselect & HINFC610_OP_NF_CS_MASK) ++ << HINFC610_OP_NF_CS_SHIFT) ++ | HINFC610_OP_WAIT_READY_EN; ++ ++ hinfc_write(host, regval, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_send_cmd_reset(struct hinfc_host *host, int chipselect) ++{ ++ if (HINFC610_IS_SYNC(host)) ++ return hinfc610_send_cmd_sync_reset(host, chipselect); ++ else ++ return hinfc610_send_cmd_async_reset(host, chipselect); ++} ++/*****************************************************************************/ ++ ++int hinfc610_dev_ready(struct mtd_info *mtd) ++{ ++ return 0x1; ++} ++/*****************************************************************************/ ++ ++void hinfc610_select_chip(struct mtd_info *mtd, int chipselect) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct hinfc_host *host = chip->priv; ++ ++ if (chipselect < 0) ++ return; ++ ++ if (chipselect > CONFIG_HINFC610_MAX_CHIP) ++ PR_BUG("invalid chipselect: %d\n", chipselect); ++ ++ host->chipselect = chipselect; ++} ++/*****************************************************************************/ ++ ++uint8_t hinfc610_read_byte(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct hinfc_host *host = chip->priv; ++ ++ if (host->command == NAND_CMD_STATUS) ++ return readb(chip->IO_ADDR_R); ++ ++ host->offset++; ++ ++ if (host->command == NAND_CMD_READID) ++ return readb(chip->IO_ADDR_R + host->offset - 1); ++ ++ return readb(host->buffer + host->column + host->offset - 1); ++} ++/*****************************************************************************/ ++ ++u16 hinfc610_read_word(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct hinfc_host *host = chip->priv; ++ ++ host->offset += 2; ++ return readw(host->buffer + host->column + host->offset - 2); ++} ++/*****************************************************************************/ ++ ++void hinfc610_write_buf(struct mtd_info *mtd, const uint8_t *buf, ++ int len) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct hinfc_host *host = chip->priv; ++ ++ memcpy(host->buffer + host->column + host->offset, buf, len); ++ host->offset += len; ++} ++/*****************************************************************************/ ++static void hinfc610_ecc_err_num_count(struct mtd_info *mtd, ++ uint8_t ecc_st, int reg) ++{ ++ u_char err_num; ++ ++ if (ecc_st > 4) ++ ecc_st = 4; ++ ++ while (ecc_st) { ++ err_num = GET_ECC_ERR_NUM(--ecc_st, reg); ++ if (err_num == 0xff) ++ mtd->ecc_stats.failed++; ++ else ++ mtd->ecc_stats.corrected += err_num; ++ } ++} ++ ++/*****************************************************************************/ ++ ++void hinfc610_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct hinfc_host *host = chip->priv; ++ int reg; ++ uint8_t ecc_step = host->pagesize >> 10; ++ ++ memcpy(buf, host->buffer + host->column + host->offset, len); ++ host->offset += len; ++ ++ /* 2K or 4K or 8K(1) or 16K(1-1) pagesize */ ++ reg = hinfc_read(host, HINFC_ECC_ERR_NUM0_BUF0); ++ hinfc610_ecc_err_num_count(mtd, ecc_step, reg); ++ ++ if (ecc_step > 4) { ++ /* 8K(2) or 16K(1-2) pagesize */ ++ reg = hinfc_read(host, HINFC_ECC_ERR_NUM1_BUF0); ++ hinfc610_ecc_err_num_count(mtd, ecc_step, reg); ++ if (ecc_step > 8) { ++ /* 16K(2-1) pagesize */ ++ reg = hinfc_read(host, HINFC_ECC_ERR_NUM0_BUF1); ++ hinfc610_ecc_err_num_count(mtd, ecc_step, reg); ++ /* 16K(2-2) pagesize */ ++ reg = hinfc_read(host, HINFC_ECC_ERR_NUM1_BUF1); ++ hinfc610_ecc_err_num_count(mtd, ecc_step, reg); ++ } ++ } ++} ++/*****************************************************************************/ ++/* ++ * 'host->epm' only use the first oobfree[0] field, it looks very simple, But... ++ */ ++static struct nand_ecclayout nand_ecc_default = { ++ .oobfree = {{2, 30} } ++}; ++ ++/*****************************************************************************/ ++ ++static struct nand_config_info hinfc610_soft_auto_config_table[] = { ++ {NAND_PAGE_16K, NAND_ECC_64BIT, 1824/*1824*/, &nand_ecc_default}, ++ {NAND_PAGE_16K, NAND_ECC_40BIT, 1200/*1152*/, &nand_ecc_default}, ++ {NAND_PAGE_16K, NAND_ECC_NONE, 32 , &nand_ecc_default}, ++ ++ {NAND_PAGE_8K, NAND_ECC_64BIT, 928 /*928*/, &nand_ecc_default}, ++ {NAND_PAGE_8K, NAND_ECC_40BIT, 600 /*592*/, &nand_ecc_default}, ++ {NAND_PAGE_8K, NAND_ECC_24BIT, 368 /*368*/, &nand_ecc_default}, ++ {NAND_PAGE_8K, NAND_ECC_NONE, 32, &nand_ecc_default}, ++ ++ {NAND_PAGE_4K, NAND_ECC_24BIT, 200 /*200*/, &nand_ecc_default}, ++ {NAND_PAGE_4K, NAND_ECC_4BIT_512, 128 /*88*/, &nand_ecc_default}, ++ {NAND_PAGE_4K, NAND_ECC_NONE, 32, &nand_ecc_default}, ++ ++ {NAND_PAGE_2K, NAND_ECC_24BIT, 128 /*116*/, &nand_ecc_default}, ++ {NAND_PAGE_2K, NAND_ECC_4BIT_512, 64 /*60*/, &nand_ecc_default}, ++ {NAND_PAGE_2K, NAND_ECC_NONE, 32, &nand_ecc_default}, ++ ++ {0, 0, 0, NULL}, ++}; ++/*****************************************************************************/ ++/* used the best correct arithmetic. */ ++struct nand_config_info *hinfc610_get_best_ecc(struct mtd_info *mtd) ++{ ++ struct nand_config_info *best = NULL; ++ struct nand_config_info *config = hinfc610_soft_auto_config_table; ++ ++ for (; config->layout; config++) { ++ if (nandpage_type2size(config->pagetype) != mtd->writesize) ++ continue; ++ ++ if (mtd->oobsize < config->oobsize) ++ continue; ++ ++ if (!best || (best->ecctype < config->ecctype)) ++ best = config; ++ } ++ ++ if (!best) ++ PR_BUG(ERSTR_DRIVER ++ "Driver does not support the pagesize(%d) " ++ "and oobsize(%d).\n", ++ mtd->writesize, mtd->oobsize); ++ ++ return best; ++} ++/*****************************************************************************/ ++/* force the pagesize and ecctype */ ++struct nand_config_info *hinfc610_force_ecc(struct mtd_info *mtd, int pagetype, ++ int oobsize, char *cfgmsg, ++ int allow_pagediv) ++{ ++ struct nand_config_info *fit = NULL; ++ struct nand_config_info *config = hinfc610_soft_auto_config_table; ++ ++ for (; config->layout; config++) { ++ if (config->pagetype == pagetype ++ && config->oobsize <= oobsize) { ++ fit = config; ++ break; ++ } ++ } ++ ++ if (!fit) { ++ PR_BUG(ERSTR_DRIVER ++ "Driver(%s mode) does not support this Nand Flash " ++ "pagesize:%s, oobsize:%d\n", ++ cfgmsg, ++ nand_page_name(pagetype), ++ oobsize); ++ return NULL; ++ } ++ return fit; ++} ++/*****************************************************************************/ ++static unsigned int nand_otp_len; ++static unsigned char nand_otp[128] = {0}; ++ ++/* Get NAND parameter table. */ ++static int __init parse_nand_param(const struct tag *tag) ++{ ++ if (tag->hdr.size <= 2) ++ return 0; ++ ++ nand_otp_len = ((tag->hdr.size << 2) - sizeof(struct tag_header)); ++ ++ if (nand_otp_len > sizeof(nand_otp)) { ++ pr_warn("%s(%d): Get Nand OTP from tag fail.\n", ++ __func__, __LINE__); ++ return 0; ++ } ++ memcpy(nand_otp, &tag->u, nand_otp_len); ++ return 0; ++} ++/* 0x48694E77 equal to fastoot ATAG_NAND_PARAM */ ++__tagtable(0x48694E77, parse_nand_param); ++ ++/*****************************************************************************/ ++int hinfc610_ecc_type2reg_intf(int type, struct hinfc_host *host) ++{ ++ if (HINFC_VER_620 == host->version) ++ return hinfc620_ecc_type2reg(type); ++ else ++ return hinfc610_ecc_type2reg(type); ++} ++/*****************************************************************************/ ++int hinfc610_ecc_reg2type_intf(int reg, struct hinfc_host *host) ++{ ++ if (HINFC_VER_620 == host->version) ++ return hinfc620_ecc_reg2type(reg); ++ else ++ return hinfc610_ecc_reg2type(reg); ++} ++ ++/*****************************************************************************/ ++static int hinfc610_param_adjust(struct mtd_info *mtd, struct nand_chip *chip, ++ struct nand_dev_t *nand_dev) ++{ ++ int pagetype; ++ int oobsize; ++ int regval; ++ char *start_type = "unknown"; ++ struct nand_config_info *best = NULL; ++ struct hinfc_host *host = chip->priv; ++ ++ if (IS_NANDC_HW_AUTO(host)) ++ start_type = "HW-Auto"; ++ else ++ start_type = "HW-Reg"; ++ ++ if ((mtd->writesize == SZ_8K) ++ || (mtd->writesize == SZ_16K) ++ || (mtd->writesize == SZ_32K)) ++ host->flags |= NAND_RANDOMIZER; ++ ++ pagetype = nandpage_size2type(mtd->writesize); ++ oobsize = mtd->oobsize; ++ ++ best = hinfc610_force_ecc(mtd, pagetype, oobsize, ++ start_type, 0); ++ ++#ifdef CONFIG_HINFC610_PAGESIZE_AUTO_ECC_NONE ++# ifdef CONFIG_HINFC610_AUTO_PAGESIZE_ECC ++# error you SHOULD NOT define CONFIG_HINFC610_PAGESIZE_AUTO_ECC_NONE \ ++ and CONFIG_HINFC610_AUTO_PAGESIZE_ECC at the same time ++# endif ++# ifdef CONFIG_HINFC610_HARDWARE_PAGESIZE_ECC ++# error you SHOULD NOT define CONFIG_HINFC610_PAGESIZE_AUTO_ECC_NONE \ ++ and CONFIG_HINFC610_HARDWARE_PAGESIZE_ECC at the same time ++# endif ++ ++ pagetype = nandpage_size2type(mtd->writesize); ++ oobsize = 32; ++ best = hinfc610_force_ecc(mtd, pagetype, oobsize, ++ "force config", 0); ++ start_type = "AutoForce"; ++ ++#endif /* CONFIG_HINFC610_PAGESIZE_AUTO_ECC_NONE */ ++ ++ if (!best) { ++ PR_BUG(ERSTR_HARDWARE ++ "Please configure Nand Flash pagesize and ecctype!\n"); ++ return -1; ++ } ++ ++ /* only in case fastboot check randomizer failed. ++ * Update fastboot or configure hardware randomizer pin ++ * fix this problem. ++ */ ++ if (IS_NAND_RANDOM(nand_dev) && !(IS_NAND_RANDOM(host))) ++ PR_BUG(ERSTR_HARDWARE ++ "Hardware is not configure randomizer, " ++ "but it is more suitable for this Nand Flash. " ++ "1. Please configure hardware randomizer PIN." ++ "2. Please updata fastboot.\n"); ++ ++ host->flags |= (IS_NAND_RANDOM(nand_dev) | ++ IS_NAND_SYNC_ASYNC(nand_dev) | ++ IS_NAND_ONLY_SYNC(nand_dev) | ++ IS_NAND_ONFI(nand_dev)); ++ ++ /* only for print nand info. */ ++ nand_dev->flags |= (IS_NANDC_HW_AUTO(host) | ++ IS_NANDC_SYNC_BOOT(host)); ++ ++ /* only in case fastboot check sync boot pin failed. ++ * Update fastboot or configure hardware sync boot pin fix this problem. ++ */ ++ if (IS_NANDC_SYNC_BOOT(host)) { ++ /* But NAND do not support sync mode, warning ! */ ++ if (!IS_NAND_ONLY_SYNC(nand_dev)) ++ PR_BUG(ERSTR_HARDWARE ++ "Hardware SYNC BOOT PIN has configured sync mode, " ++ "but the Nand Flash is async mode.\n" ++ "1. DO NOT configure SYNC BOOT PIN. " ++ "2. Update fastboot.\n"); ++ } else { ++ if (IS_NAND_ONLY_SYNC(nand_dev)) ++ PR_BUG(ERSTR_HARDWARE ++ "Hardware SYNC BOOT PIN has configured async mode, " ++ "but the Nand Flash only support sync mode.\n" ++ "1. Please configure SYNC BOOT PIN." ++ "2. Update fastboot.\n"); ++ } ++ ++ if (IS_NAND_SYNC_ASYNC(nand_dev)) ++ hinfc610_get_sync_info(host); ++ ++ if (best->ecctype != NAND_ECC_NONE) ++ mtd->oobsize = best->oobsize; ++ chip->ecc.layout = best->layout; ++ ++ host->ecctype = best->ecctype; ++ host->pagesize = nandpage_type2size(best->pagetype); ++ host->oobsize = mtd->oobsize; ++ host->block_page_mask = ((mtd->erasesize / mtd->writesize) - 1); ++ ++ host->buffer = dma_alloc_coherent(host->dev, ++ (host->pagesize + host->oobsize), ++ &host->dma_buffer, GFP_KERNEL); ++ if (!host->buffer) { ++ PR_BUG("Can't malloc memory for NAND driver."); ++ return -EIO; ++ } ++ memset(host->buffer, 0xff, (host->pagesize + host->oobsize)); ++ ++ host->dma_oob = host->dma_buffer + host->pagesize; ++ host->bbm = (unsigned char *)(host->buffer ++ + host->pagesize + HINFC_BAD_BLOCK_POS); ++ ++ host->epm = (unsigned short *)(host->buffer ++ + host->pagesize + chip->ecc.layout->oobfree[0].offset + 28); ++ ++ regval = ~(HINFC610_CON_PAGESIZE_MASK << HINFC610_CON_PAGEISZE_SHIFT); ++ host->NFC_CON &= regval; ++ host->NFC_CON_ECC_NONE &= regval; ++ regval = (hinfc610_page_type2reg(best->pagetype) ++ & HINFC610_CON_PAGESIZE_MASK) << HINFC610_CON_PAGEISZE_SHIFT; ++ host->NFC_CON |= regval; ++ host->NFC_CON_ECC_NONE |= regval; ++ ++ regval = ~(HINFC610_CON_ECCTYPE_MASK << HINFC610_CON_ECCTYPE_SHIFT); ++ host->NFC_CON &= regval; ++ host->NFC_CON_ECC_NONE &= regval; ++ regval = (hinfc610_ecc_type2reg_intf(best->ecctype, host) ++ & HINFC610_CON_ECCTYPE_MASK) << HINFC610_CON_ECCTYPE_SHIFT; ++ host->NFC_CON |= regval; ++ ++ if (mtd->writesize > NAND_MAX_PAGESIZE || ++ mtd->oobsize > NAND_MAX_OOBSIZE) { ++ PR_BUG(ERSTR_DRIVER ++ "Driver does not support this Nand Flash. " ++ "Please increase NAND_MAX_PAGESIZE and NAND_MAX_OOBSIZE.\n"); ++ } ++ ++ if (mtd->writesize != host->pagesize) { ++ unsigned int shift = 0; ++ unsigned int writesize = mtd->writesize; ++ ++ while (writesize > host->pagesize) { ++ writesize >>= 1; ++ shift++; ++ } ++ chip->chipsize = chip->chipsize >> shift; ++ mtd->erasesize = mtd->erasesize >> shift; ++ mtd->writesize = host->pagesize; ++ PR_MSG("Nand divide into 1/%u\n", (1 << shift)); ++ } ++ ++ nand_dev->start_type = start_type; ++ nand_dev->ecctype = host->ecctype; ++ nand_dev->oobsize = mtd->oobsize; ++ ++ host->read_retry = NULL; ++ if (nand_dev->read_retry_type != NAND_RR_NONE) { ++ host->read_retry ++ = hinfc610_find_read_retry(nand_dev->read_retry_type); ++ if (!host->read_retry) { ++ PR_BUG(ERSTR_DRIVER ++ "This Nand Flash need to enable the " ++ "'read retry' feature. " ++ "but the driver dose not offer the feature"); ++ } ++ ++ if (nand_otp_len) ++ memcpy(host->rr_data, nand_otp, nand_otp_len); ++ } ++ ++ /* ++ * If it want to support the 'read retry' feature, the 'randomizer' ++ * feature must be support first. ++ */ ++ if (host->read_retry && !IS_NAND_RANDOM(host)) { ++ PR_BUG(ERSTR_HARDWARE ++ "This Nand flash need to enable 'randomizer' feature. " ++ "Please configure hardware randomizer PIN."); ++ } ++ ++ hinfc610_dbg_init(host); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++int hinfc610_nand_init(struct hinfc_host *host, struct nand_chip *chip) ++{ ++ unsigned int regval; ++ ++ host->version = hinfc_read(host, HINFC610_VERSION); ++ ++ host->addr_cycle = 0; ++ host->addr_value[0] = 0; ++ host->addr_value[1] = 0; ++ host->cache_addr_value[0] = ~0; ++ host->cache_addr_value[1] = ~0; ++ host->chipselect = 0; ++ ++ host->send_cmd_pageprog = hinfc610_send_cmd_pageprog; ++ host->send_cmd_readstart = hinfc610_send_cmd_readstart; ++ host->send_cmd_erase = hinfc610_send_cmd_erase; ++ host->send_cmd_readid = hinfc610_send_cmd_readid; ++ host->send_cmd_status = hinfc610_send_cmd_status; ++ host->send_cmd_reset = hinfc610_send_cmd_reset; ++ ++ host->flags = 0; ++ ++ regval = hinfc_read(host, HINFC610_CON); ++ ++ host->NFC_CON = (regval ++ | HINFC610_CON_OP_MODE_NORMAL ++ | HINFC610_CON_READY_BUSY_SEL); ++ ++ host->NFC_CON_ECC_NONE = host->NFC_CON ++ & (~(HINFC610_CON_ECCTYPE_MASK ++ << HINFC610_CON_ECCTYPE_SHIFT)) ++ & (~HINFC610_CON_RANDOMIZER_EN); ++ ++ hinfc_write(host, ++ (SET_HINFC610_PWIDTH(CONFIG_HINFC610_W_LATCH, ++ CONFIG_HINFC610_R_LATCH, ++ CONFIG_HINFC610_RW_LATCH)), ++ HINFC610_PWIDTH); ++ ++ host->flags |= NANDC_HW_AUTO; ++ ++ /* check if chip is sync mode. */ ++ if (regval & HINFC610_BOOT_CFG_SYC_NAND_PAD) { ++ host->flags |= NANDC_IS_SYNC_BOOT; ++ ++ /* ++ * NAND default is sync mode, and read id, reset in sync mode. ++ */ ++ host->NFC_CON |= HINFC610_CON_NF_MODE_TOGGLE; ++ host->NFC_CON_ECC_NONE |= HINFC610_CON_NF_MODE_TOGGLE; ++ ++ /* set synchronous clock and timing. */ ++ clk_prepare_enable(host->clk); ++ } ++ ++ memset((char *)chip->IO_ADDR_R, ++ 0xff, HINFC610_BUFFER_BASE_ADDRESS_LEN); ++ ++ host->enable_ecc_randomizer = hinfc610_enable_ecc_randomizer; ++ hinfc_param_adjust = hinfc610_param_adjust; ++ ++ return 0; ++} +diff --git a/drivers/mtd/nand/hinfc610/hinfc610.h b/drivers/mtd/nand/hinfc610/hinfc610.h +new file mode 100644 +index 0000000..18d90fd +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610.h +@@ -0,0 +1,512 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef HINFCV610H ++#define HINFCV610H ++/******************************************************************************/ ++ ++#ifndef CONFIG_HINFC610_W_LATCH ++ #define CONFIG_HINFC610_W_LATCH (5) ++#endif /* CONFIG_HINFC610_W_LATCH */ ++ ++#ifndef CONFIG_HINFC610_R_LATCH ++ #define CONFIG_HINFC610_R_LATCH (7) ++#endif /* CONFIG_HINFC610_R_LATCH */ ++ ++#ifndef CONFIG_HINFC610_RW_LATCH ++ #define CONFIG_HINFC610_RW_LATCH (3) ++#endif /* CONFIG_HINFC610_RW_LATCH */ ++ ++#ifndef CONFIG_HINFC610_MAX_CHIP ++ #define CONFIG_HINFC610_MAX_CHIP (1) ++ #warning NOT config CONFIG_HINFC610_MAX_CHIP, \ ++ used default value, maybe invalid. ++#endif /* CONFIG_HINFC610_MAX_CHIP */ ++/*****************************************************************************/ ++#define HINFC_ECC_ERR_NUM0_BUF0 0xa0 ++#define HINFC_ECC_ERR_NUM1_BUF0 0xa4 ++#define HINFC_ECC_ERR_NUM0_BUF1 0xa8 ++#define HINFC_ECC_ERR_NUM1_BUF1 0xcc ++ ++#define GET_ECC_ERR_NUM(_i, _reg) (((_reg) >> ((_i) * 8)) & 0xff) ++ ++/*****************************************************************************/ ++#define HINFC610_REG_BASE_ADDRESS_LEN (0x100) ++#define HINFC610_BUFFER_BASE_ADDRESS_LEN (2048 + 128) ++ ++#define HINFC610_CHIP_DELAY (25) ++ ++#define HINFC610_ADDR_CYCLE_MASK 0x4 ++#define HINFC610_DMA_ADDR_OFFSET 4096 ++/*****************************************************************************/ ++#define HINFC610_CON 0x00 ++#define HINFC610_CON_OP_MODE_NORMAL (1U << 0) ++#define HINFC610_CON_PAGEISZE_SHIFT (1) ++#define HINFC610_CON_PAGESIZE_MASK (0x07) ++#define HINFC610_CON_BUS_WIDTH (1U << 4) ++#define HINFC610_CON_READY_BUSY_SEL (1U << 8) ++#define HINFC610_CON_ECCTYPE_SHIFT (9) ++#define HINFC610_CON_ECCTYPE_MASK (0x0f) ++#define HINFC610_CON_RANDOMIZER_EN (1 << 14) ++#define HINFC610_CON_NF_MODE_SHIFT 15 ++#define HINFC610_CON_NF_MODE_MASK (3 << HINFC610_CON_NF_MODE_SHIFT) ++#define HINFC610_CON_NF_MODE_TOGGLE (1 << HINFC610_CON_NF_MODE_SHIFT) ++#define HINFC610_CON_NF_MODE_ONFI_23 (2 << HINFC610_CON_NF_MODE_SHIFT) ++#define HINFC610_CON_NF_MODE_ONFI_30 (3 << HINFC610_CON_NF_MODE_SHIFT) ++ ++#define HINFC610_PWIDTH 0x04 ++#define SET_HINFC610_PWIDTH(_w_lcnt, _r_lcnt, _rw_hcnt) \ ++ ((_w_lcnt) | (((_r_lcnt) & 0x0F) << 4) | (((_rw_hcnt) & 0x0F) << 8)) ++ ++#define HINFC610_CMD 0x0C ++#define HINFC610_ADDRL 0x10 ++#define HINFC610_ADDRH 0x14 ++#define HINFC610_DATA_NUM 0x18 ++ ++#define HINFC610_OP 0x1C ++#define HINFC610_OP_READ_STATUS_EN (1U << 0) ++#define HINFC610_OP_READ_DATA_EN (1U << 1) ++#define HINFC610_OP_WAIT_READY_EN (1U << 2) ++#define HINFC610_OP_CMD2_EN (1U << 3) ++#define HINFC610_OP_WRITE_DATA_EN (1U << 4) ++#define HINFC610_OP_ADDR_EN (1U << 5) ++#define HINFC610_OP_CMD1_EN (1U << 6) ++#define HINFC610_OP_NF_CS_SHIFT (7) ++#define HINFC610_OP_NF_CS_MASK (3) ++#define HINFC610_OP_ADDR_CYCLE_SHIFT (9) ++#define HINFC610_OP_ADDR_CYCLE_MASK (7) ++#define HINFC610_OP_READID_EN (1U << 12) ++#define HINFC610_OP_RW_REG_EN (1U << 13) ++ ++#define HINFC610_STATUS 0x20 ++ ++#define HINFC610_INTS 0x28 ++#define HINFC610_INTS_UE (1U << 6) ++#define HINFC610_INTCLR 0x2C ++#define HINFC610_INTCLR_UE (1U << 6) ++#define HINFC610_INTCLR_CE (1U << 5) ++ ++#define HINFC610_DMA_CTRL 0x60 ++#define HINFC610_DMA_CTRL_DMA_START (1U << 0) ++#define HINFC610_DMA_CTRL_WE (1U << 1) ++#define HINFC610_DMA_CTRL_BURST4_EN (1U << 4) ++#define HINFC610_DMA_CTRL_BURST8_EN (1U << 5) ++#define HINFC610_DMA_CTRL_BURST16_EN (1U << 6) ++#define HINFC610_DMA_CTRL_ADDR_NUM_SHIFT (7) ++#define HINFC610_DMA_CTRL_ADDR_NUM_MASK (1) ++#define HINFC610_DMA_CTRL_CS_SHIFT (8) ++#define HINFC610_DMA_CTRL_CS_MASK (0x03) ++ ++#define HINFC610_DMA_ADDR_DATA 0x64 ++#define HINFC610_DMA_ADDR_OOB 0x68 ++#define HINFC610_DMA_ADDR_DATA1 0xB4 ++#define HINFC610_DMA_ADDR_DATA2 0xB8 ++#define HINFC610_DMA_ADDR_DATA3 0xBC ++#define HINFC610_DMA_ADDR_DATA4 0xEC ++#define HINFC610_DMA_ADDR_DATA5 0xF0 ++#define HINFC610_DMA_ADDR_DATA6 0xF4 ++#define HINFC610_DMA_ADDR_DATA7 0xF8 ++ ++#define HINFC610_DMA_LEN 0x6C ++#define HINFC610_DMA_LEN_OOB_SHIFT (16) ++#define HINFC610_DMA_LEN_OOB_MASK (0x1FFF) ++ ++#define HINFC610_DMA_PARA 0x70 ++#define HINFC610_DMA_PARA_DATA_RW_EN (1U << 0) ++#define HINFC610_DMA_PARA_OOB_RW_EN (1U << 1) ++#define HINFC610_DMA_PARA_DATA_EDC_EN (1U << 2) ++#define HINFC610_DMA_PARA_OOB_EDC_EN (1U << 3) ++#define HINFC610_DMA_PARA_EXT_LEN_SHIFT (6) ++#define HINFC610_DMA_PARA_EXT_LEN_MASK (0x03) ++ ++#define HINFC610_VERSION 0x74 ++#define HINFC610_LOG_READ_ADDR 0x7C ++#define HINFC610_LOG_READ_LEN 0x80 ++ ++#define HINFC610_ECC_REG0 0xA0 ++#define HINFC610_ECC_REG1 0xA4 ++#define HINFC610_ECC_REG2 0xA8 ++#define HINFC610_ECC_REG3 0xAC ++ ++#define HINFC610_RANDOMIZER 0xC0 ++#define HINFC610_RANDOMIZER_PAD 0x02 ++#define HINFC610_RANDOMIZER_ENABLE 0x01 ++/* read nand id or nand status, return from nand data length */ ++#define HINFC610_NANDINFO_LEN 0x10 ++ ++#define HINFC610_BOOT_CFG 0xC4 ++#define HINFC610_BOOT_CFG_RANDOMIZER_PAD 0x01 ++#define HINFC610_BOOT_CFG_SAVE_PIN_MODE_SHIFT 13 ++#define HINFC610_BOOT_CFG_SAVE_PIN_MODE \ ++ (1U << HINFC610_BOOT_CFG_SAVE_PIN_MODE_SHIFT) ++#define HINFC610_BOOT_CFG_SYC_NAND_PAD_SHIFT 12 ++#define HINFC610_BOOT_CFG_SYC_NAND_PAD \ ++ (1U << HINFC610_BOOT_CFG_SYC_NAND_PAD_SHIFT) ++ ++#define HINFC610_SYNC_TIMING 0xD0 ++ ++/* ONFI: sync nand timing config */ ++#define HINFC610_SYNC_ONFI_T_CAD (0xF << 24) ++#define HINFC610_SYNC_ONFI_T_DQZ (0xF << 20) ++ ++/* TOGGLE: sync nand timing config */ ++#define HINFC610_SYNC_TOGGLE_PRE_RDQS (0xF << 16) ++#define HINFC610_SYNC_TOGGLE_POST_RDQS (0xF << 12) ++#define HINFC610_SYNC_TOGGLE_PRE_WDQS (0xF << 8) ++#define HINFC610_SYNC_TOGGLE_POST_WDQS (0xF << 4) ++#define HINFC610_SYNC_TOGGLE_RW_PSTH (0xF << 0) ++ ++/*****************************************************************************/ ++/* ++ * This constant declares the max. oobsize / page, which ++ * is supported now. If you add a chip with bigger oobsize/page ++ * adjust this accordingly. ++ */ ++#define NAND_MAX_OOBSIZE 4800 ++#define NAND_MAX_PAGESIZE 32768 ++ ++/* DMA address align with 32 bytes. */ ++#define HINFC610_DMA_ALIGN 64 ++/*****************************************************************************/ ++#include "../hinfc_gen.h" ++ ++#undef READ ++#define READ 1 ++ ++#undef WRITE ++#define WRITE 0 ++ ++#undef FALSE ++#define FALSE 0 ++ ++#undef TRUE ++#define TRUE 1 ++ ++#undef ENABLE ++#define ENABLE 1 ++ ++#undef DISABLE ++#define DISABLE 0 ++/*****************************************************************************/ ++ ++struct hinfc_host { ++ struct nand_chip *chip; ++ struct mtd_info *mtd; ++ void __iomem *iobase; ++ struct device *dev; ++ ++ unsigned int offset; ++ unsigned int command; ++ ++ int chipselect; ++ ++ unsigned int n24bit_ext_len; ++ int ecctype; ++ ++/* Current system has already gone to sync mode */ ++#define HINFC610_IS_SYNC(_host) ((_host)->NFC_CON & HINFC610_CON_NF_MODE_MASK) ++ unsigned long NFC_CON; ++ unsigned long NFC_CON_ECC_NONE; ++ ++ unsigned int addr_cycle; ++ unsigned int addr_value[2]; ++ unsigned int cache_addr_value[2]; ++ unsigned int column; ++ unsigned int block_page_mask; ++ ++ unsigned int dma_oob; ++ unsigned int dma_buffer; ++ unsigned int pagesize; ++ unsigned int oobsize; ++ /* This is maybe an un-aligment address, only for malloc or free */ ++ char *buforg; ++ char *buffer; ++ ++ int need_rr_data; ++#define HINFC_READ_RETRY_DATA_LEN 128 ++ char rr_data[HINFC_READ_RETRY_DATA_LEN]; ++ int version; ++ int add_partition; ++ ++ /* BOOTROM read two bytes to detect the bad block flag */ ++#define HINFC_BAD_BLOCK_POS 0 ++ unsigned char *bbm; /* nand bad block mark */ ++ unsigned short *epm; /* nand empty page mark */ ++ unsigned int flags; ++ ++#define HINFC610_PS_UC_ECC 0x01 /* page has ecc error */ ++#define HINFC610_PS_BAD_BLOCK 0x02 /* bad block */ ++#define HINFC610_PS_EMPTY_PAGE 0x04 /* page is empty */ ++#define HINFC610_PS_EPM_ERROR 0x0100 /* empty page mark word has ecc error*/ ++#define HINFC610_PS_BBM_ERROR 0x0200 /* bad block mark word has ecc error*/ ++ unsigned int page_status; ++ ++ struct clk *clk; ++ ++ int (*send_cmd_pageprog)(struct hinfc_host *host); ++ int (*send_cmd_status)(struct hinfc_host *host); ++ int (*send_cmd_readstart)(struct hinfc_host *host); ++ int (*send_cmd_erase)(struct hinfc_host *host); ++ int (*send_cmd_readid)(struct hinfc_host *host); ++ int (*send_cmd_reset)(struct hinfc_host *host, int chipselect); ++ int (*enable)(struct hinfc_host *host, int enable); ++ ++ int (*enable_ecc_randomizer)(struct hinfc_host *host, ++ int ecc_en, int randomizer_en); ++ ++ struct read_retry_t *read_retry; ++ struct nand_sync *sync; ++}; ++ ++#define HINFC610_UC_ECC 0x01 ++#define HINFC610_BAD_BLOCK 0x02 ++#define HINFC610_EMPTY_PAGE 0x04 ++ ++#define IS_PS_EMPTY_PAGE(_host) ((_host)->page_status & HINFC610_PS_EMPTY_PAGE) ++#define IS_PS_BAD_BLOCK(_host) ((_host)->page_status & HINFC610_PS_BAD_BLOCK) ++#define IS_PS_UN_ECC(_host) ((_host)->page_status & HINFC610_PS_UC_ECC) ++#define IS_PS_EPM_ERR(_host) ((_host)->page_status & HINFC610_PS_EPM_ERROR) ++#define IS_PS_BBM_ERR(_host) ((_host)->page_status & HINFC610_PS_BBM_ERROR) ++ ++/*****************************************************************************/ ++ ++#define HINFC610_READ_1CMD_0ADD_NODATA \ ++ (HINFC610_OP_CMD1_EN \ ++ | ((host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT)) ++ ++#define HINFC610_READ_1CMD_1ADD_DATA \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_READ_DATA_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_READ_1CMD_1ADD_DATA_WAIT_READY \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_READ_DATA_EN \ ++ | HINFC610_OP_WAIT_READY_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_READ_1CMD_1ADD_DATA_SYNC \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_READ_DATA_EN \ ++ | HINFC610_OP_WAIT_READY_EN \ ++ | HINFC610_OP_RW_REG_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_READ_2CMD_5ADD \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_CMD2_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_READ_DATA_EN \ ++ | HINFC610_OP_WAIT_READY_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (5 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_0CMD_1ADD_DATA \ ++ (HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_0CMD_1ADD_DATA_WAIT_READY \ ++ (HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | HINFC610_OP_WAIT_READY_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_0CMD_1ADD_DATA_SYNC \ ++ (HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | HINFC610_OP_RW_REG_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_0CMD_1ADD_DATA_SYNC_WAIT_READY \ ++ (HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | HINFC610_OP_RW_REG_EN \ ++ | HINFC610_OP_WAIT_READY_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_1CMD_1ADD_DATA \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_1CMD_1ADD_DATA_WAIT_READY \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | HINFC610_OP_WAIT_READY_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_1CMD_1ADD_DATA_SYNC \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | HINFC610_OP_RW_REG_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_1CMD_1ADD_DATA_SYNC_WAIT_READY \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | HINFC610_OP_WAIT_READY_EN \ ++ | HINFC610_OP_RW_REG_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (1 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_1CMD_2ADD_DATA \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (2 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_1CMD_2ADD_DATA_SYNC \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_ADDR_EN \ ++ | HINFC610_OP_WRITE_DATA_EN \ ++ | HINFC610_OP_RW_REG_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT) \ ++ | (2 << HINFC610_OP_ADDR_CYCLE_SHIFT)) ++ ++#define HINFC610_WRITE_2CMD_0ADD_NODATA \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_CMD2_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT)) ++ ++#define HINFC610_WRITE_2CMD_0ADD_NODATA_SYNC \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_CMD2_EN \ ++ | HINFC610_OP_RW_REG_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT)) ++ ++#define HINFC610_WRITE_1CMD_0ADD_NODATA \ ++ (HINFC610_OP_CMD1_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT)) ++ ++#define HINFC610_WRITE_1CMD_0ADD_NODATA_WAIT_READY \ ++ (HINFC610_OP_CMD1_EN \ ++ | HINFC610_OP_WAIT_READY_EN \ ++ | (((unsigned int)host->chipselect & HINFC610_OP_NF_CS_MASK) \ ++ << HINFC610_OP_NF_CS_SHIFT)) ++ ++/*****************************************************************************/ ++ ++#define WAIT_CONTROLLER_FINISH() \ ++do { \ ++ unsigned int timeout = 0x800000; \ ++ while ((hinfc_read(host, HINFC610_STATUS) & 0x1) == 0x0 && timeout) \ ++ timeout--; \ ++ if (!timeout) \ ++ PR_ERR("Wait NAND controller finish timeout.\n"); \ ++} while (0) ++ ++/*****************************************************************************/ ++ ++#define hinfc_read(_host, _reg) \ ++ readl((char *)_host->iobase + (_reg)) ++ ++#define hinfc_write(_host, _value, _reg) \ ++ writel((_value), (char *)_host->iobase + (_reg)) ++ ++#define HINFC_CMD_SEQ(_cmd0, _cmd1) \ ++ (((_cmd0) & 0xFF) | ((_cmd1) & 0xFF) << 8) ++/*****************************************************************************/ ++ ++#define GET_PAGE_INDEX(host) \ ++ ((host->addr_value[0] >> 16) | (host->addr_value[1] << 16)) ++ ++/*****************************************************************************/ ++ ++void hinfc610_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl); ++int hinfc610_dev_ready(struct mtd_info *mtd); ++void hinfc610_select_chip(struct mtd_info *mtd, int chipselect); ++uint8_t hinfc610_read_byte(struct mtd_info *mtd); ++u16 hinfc610_read_word(struct mtd_info *mtd); ++void hinfc610_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len); ++void hinfc610_read_buf(struct mtd_info *mtd, uint8_t *buf, int len); ++int hinfc610_nand_init(struct hinfc_host *host, struct nand_chip *chip); ++/******************************************************************************/ ++ ++extern struct nand_sync hinfc610_sync_onfi_23; ++extern struct nand_sync hinfc610_sync_onfi_30; ++extern struct nand_sync hinfc610_sync_toggle_10; ++extern struct read_retry_t hinfc610_hynix_bg_cdie_read_retry; ++extern struct read_retry_t hinfc610_hynix_bg_bdie_read_retry; ++extern struct read_retry_t hinfc610_hynix_cg_adie_read_retry; ++extern struct read_retry_t hinfc610_micron_read_retry; ++extern struct read_retry_t hinfc610_toshiba_24nm_read_retry; ++extern struct read_retry_t hinfc610_samsung_read_retry; ++ ++#if 0 ++#ifdef CONFIG_MTD_PART_CHANGE ++extern int register_mtd_partdev(struct mtd_info *mtd); ++extern int unregister_mtd_partdev(struct mtd_info *mtd); ++#else ++int register_mtd_partdev(struct mtd_info *mtd) ++{ ++ return 0; ++}; ++ ++int unregister_mtd_partdev(struct mtd_info *mtd) ++{ ++ return 0; ++}; ++#endif ++ ++void hinfc610_controller_enable(struct hinfc_host *host, int enable); ++#endif ++ ++extern int hinfc610_dbgfs_debug_init(struct hinfc_host *host); ++ ++#ifdef CONFIG_HINFC610_DBG_NAND_DEBUG ++extern struct hinfc610_dbg_inf_t *hinfc610_dbg_inf[]; ++#endif ++ ++#endif /* HINFCV610H */ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_dbg.c b/drivers/mtd/nand/hinfc610/hinfc610_dbg.c +new file mode 100644 +index 0000000..ee25956 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_dbg.c +@@ -0,0 +1,294 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++#include "hinfc610_dbg.h" ++ ++struct hinfc610_dbg_inf_t *hinfc610_dbg_inf[] = { ++ &hinfc610_dbg_inf_ecc_notice, ++ &hinfc610_dbg_inf_read_retry_notice, ++#ifdef CONFIG_HINFC610_DBG_NAND_DUMP ++ &hinfc610_dbg_inf_dump, ++#endif ++#ifdef CONFIG_HINFC610_DBG_NAND_ERASE_COUNT ++ &hinfc610_dbg_inf_erase_count, ++#endif ++#ifdef CONFIG_HINFC610_DBG_NAND_ECC_COUNT ++ &hinfc610_dbg_inf_ecc_count, ++#endif ++#ifdef CONFIG_HINFC610_DBG_NAND_READ_RETRY ++ &hinfc610_dbg_inf_read_retry, ++#endif ++ NULL, ++}; ++ ++static struct dentry *dbgfs_root; ++static struct hinfc_host *dbgfs_host; ++ ++/*****************************************************************************/ ++static ssize_t dbgfs_debug_read(struct file *filp, char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ char *msg, *p; ++ struct hinfc610_dbg_inf_t **inf; ++ ++ if (*ppos != 0) ++ return 0; ++ ++ msg = (char *)__get_free_page(GFP_TEMPORARY); ++ if (!msg) ++ return -ENOMEM; ++ ++ p = msg; ++ if (count > PAGE_SIZE) ++ count = PAGE_SIZE; ++ ++ for (inf = hinfc610_dbg_inf; *inf; inf++) { ++ if ((p - msg) + MAX_OPTION_SIZE + 2 > count) { ++ PR_ERR("Not enough memory.\n"); ++ break; ++ } ++ p += snprintf(p, (MAX_OPTION_SIZE + 2), "%c%s,", ++ ((*inf)->enable ? '+' : '-'), ++ (*inf)->name); ++ } ++ ++ p += sprintf(p, "\n"); ++ count = (p - msg); ++ if (copy_to_user(buffer, msg, count)) { ++ free_page((unsigned long) msg); ++ return -EFAULT; ++ } ++ ++ free_page((unsigned long) msg); ++ ++ *ppos += count; ++ return count; ++} ++/*****************************************************************************/ ++ ++static void dbgfs_debug_do_cmd(struct hinfc610_dbg_inf_t **dbg_inf, ++ const char *cmd, unsigned int length, int enable) ++{ ++ int ret = 0; ++ struct hinfc610_dbg_inf_t **inf; ++ ++ if (length >= sizeof((*inf)->name)) ++ return; ++ ++ for (inf = dbg_inf; *inf; inf++) { ++ if (!(*inf)->name[length] && ++ !memcmp((*inf)->name, cmd, length)) ++ break; ++ } ++ ++ if (!(*inf) || (*inf)->enable == enable) ++ return; ++ ++ if (enable) { ++ if ((*inf)->init) ++ ret = (*inf)->init(dbgfs_root, dbgfs_host); ++ } else { ++ if ((*inf)->uninit) ++ ret = (*inf)->uninit(); ++ } ++ ++ if (!ret) ++ (*inf)->enable = enable; ++} ++/*****************************************************************************/ ++ ++static void dbgfs_debug_ops(const char *options, ++ struct hinfc610_dbg_inf_t **dbg_inf) ++{ ++ int enable; ++ const char *pos, *cmd; ++ ++ pos = options; ++ ++ while (*pos) { ++ ++ while (*pos && *pos != '+' && *pos != '-') ++ pos++; ++ ++ switch (*pos++) { ++ case '+': ++ enable = 1; ++ break; ++ case '-': ++ enable = 0; ++ break; ++ default: ++ return; ++ } ++ ++ cmd = pos; ++ while (*pos == '_' || isalpha(*pos)) ++ pos++; ++ ++ if (*cmd && pos > cmd) ++ dbgfs_debug_do_cmd(dbg_inf, cmd, (pos - cmd), enable); ++ ++ while (isspace(*pos) || *pos == ',' || *pos == ';') ++ pos++; ++ } ++} ++/*****************************************************************************/ ++/* ++ * echo "+dump, +read_retry, +ecc_count, +erase_count" > debug ++ */ ++static ssize_t dbgfs_debug_write(struct file *filp, const char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ char *options; ++ size_t num = count; ++ ++ if (count > PAGE_SIZE) ++ num = (PAGE_SIZE - 1); ++ ++ options = (char *)__get_free_page(GFP_TEMPORARY); ++ if (!options) ++ return -ENOMEM; ++ ++ if (copy_from_user(options, buffer, num)) { ++ free_page((unsigned long) options); ++ return -EFAULT; ++ } ++ ++ options[num] = 0; ++ ++ dbgfs_debug_ops(options, hinfc610_dbg_inf); ++ ++ free_page((unsigned long) options); ++ ++ *ppos += count; ++ return count; ++} ++/*****************************************************************************/ ++ ++static const struct file_operations dbgfs_debug_fops = { ++ .owner = THIS_MODULE, ++ .read = dbgfs_debug_read, ++ .write = dbgfs_debug_write, ++}; ++/*****************************************************************************/ ++ ++int hinfc610_dbgfs_debug_init(struct hinfc_host *host) ++{ ++ struct dentry *dentry; ++ ++ if (dbgfs_root) ++ return 0; ++ ++ dbgfs_root = debugfs_create_dir("nand", NULL); ++ if (!dbgfs_root) { ++ PR_ERR("Can't create 'nand' dir.\n"); ++ return -ENOENT; ++ } ++ ++ dentry = debugfs_create_file("debug", S_IFREG | S_IRUSR | S_IWUSR, ++ dbgfs_root, NULL, &dbgfs_debug_fops); ++ if (!dentry) { ++ PR_ERR("Can't create 'debug' file.\n"); ++ goto fail; ++ } ++ ++ dbgfs_host = host; ++ ++ if (nand_dbgfs_options) ++ dbgfs_debug_ops(nand_dbgfs_options, hinfc610_dbg_inf); ++ ++ return 0; ++ ++fail: ++ debugfs_remove_recursive(dbgfs_root); ++ dbgfs_root = NULL; ++ ++ return -ENOENT; ++} ++/*****************************************************************************/ ++ ++static int dbgfs_read_retry_notice_init(struct dentry *root, ++ struct hinfc_host *host) ++{ ++ if (!host->read_retry) { ++ pr_warn("read_retry_notice: The NAND not support this interface.\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static void hinfc610_dbg_read_retry_notice(struct hinfc_host *host, int index) ++{ ++ pr_warn("Page 0x%08x do read retry (%d/%d) %s.\n", ++ GET_PAGE_INDEX(host), index, host->read_retry->count, ++ (IS_PS_UN_ECC(host) ? "Fail" : "Success")); ++} ++ ++struct hinfc610_dbg_inf_t hinfc610_dbg_inf_read_retry_notice = { ++ "read_retry_notice", 0, ++ dbgfs_read_retry_notice_init, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ hinfc610_dbg_read_retry_notice, ++}; ++/*****************************************************************************/ ++ ++static void hinfc610_dbg_ecc_notice_read(struct hinfc_host *host) ++{ ++ unsigned int pageindex = GET_PAGE_INDEX(host); ++ ++ if (IS_PS_BAD_BLOCK(host) || IS_PS_EMPTY_PAGE(host)) { ++ if (IS_PS_BBM_ERR(host)) ++ pr_warn("page 0x%08x bbm is corruption, bbm: 0x%x.\n", ++ pageindex, *host->bbm); ++ ++ if (IS_PS_EPM_ERR(host)) ++ pr_warn("page 0x%08x epm is corruption, epm: 0x%x.\n", ++ pageindex, *host->epm); ++ ++ return; ++ } ++ ++ if (IS_PS_UN_ECC(host)) ++ pr_warn("page 0x%08x has uncorrect ecc.\n", pageindex); ++} ++ ++struct hinfc610_dbg_inf_t hinfc610_dbg_inf_ecc_notice = { ++ "ecc_notice", 0, ++ NULL, ++ NULL, ++ hinfc610_dbg_ecc_notice_read, ++ NULL, ++ NULL, ++ NULL, ++}; ++/*****************************************************************************/ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_dbg.h b/drivers/mtd/nand/hinfc610/hinfc610_dbg.h +new file mode 100644 +index 0000000..8fd4deb +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_dbg.h +@@ -0,0 +1,63 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++ ++#ifndef HINFC610_DBGH ++#define HINFC610_DBGH ++/******************************************************************************/ ++ ++#define MAX_OPTION_SIZE 20 ++ ++struct hinfc610_dbg_inf_t { ++ const char name[MAX_OPTION_SIZE]; ++ int enable; ++ int (*init)(struct dentry *root, struct hinfc_host *host); ++ int (*uninit)(void); ++ ++ void (*read)(struct hinfc_host *host); ++ void (*write)(struct hinfc_host *host); ++ void (*erase)(struct hinfc_host *host); ++ ++ void (*read_retry)(struct hinfc_host *host, int index); ++}; ++ ++#define CMD_WORD_OFFSET "offset=" ++#define CMD_WORD_LENGTH "length=" ++#define CMD_WORD_CLEAN "clear" ++#define CMD_WORD_ON "on" ++#define CMD_WORD_OFF "off" ++ ++struct hinfc610_ecc_inf_t { ++ int pagesize; ++ int ecctype; ++ int section; ++ void (*ecc_inf)(struct hinfc_host *host, unsigned char ecc[]); ++}; ++ ++struct hinfc610_ecc_inf_t *hinfc610_get_ecc_inf(struct hinfc_host *host, ++ int pagesize, int ecctype); ++ ++extern struct hinfc610_dbg_inf_t hinfc610_dbg_inf_dump; ++extern struct hinfc610_dbg_inf_t hinfc610_dbg_inf_erase_count; ++extern struct hinfc610_dbg_inf_t hinfc610_dbg_inf_ecc_count; ++extern struct hinfc610_dbg_inf_t hinfc610_dbg_inf_read_retry; ++extern struct hinfc610_dbg_inf_t hinfc610_dbg_inf_read_retry_notice; ++extern struct hinfc610_dbg_inf_t hinfc610_dbg_inf_ecc_notice; ++ ++/******************************************************************************/ ++#endif /* HINFC610_DBGH */ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_dbg_dump.c b/drivers/mtd/nand/hinfc610/hinfc610_dbg_dump.c +new file mode 100644 +index 0000000..e330bb5 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_dbg_dump.c +@@ -0,0 +1,448 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++#include "hinfc610_dbg.h" ++ ++#ifndef CONFIG_HINFC610_DBG_NAND_NUM_OF_LOGS ++# define CONFIG_HINFC610_DBG_NAND_NUM_OF_LOGS (80) ++#endif /* CONFIG_HINFC610_DBG_NAND_NUM_OF_LOGS */ ++ ++#ifndef CONFIG_HINFC610_DBG_NAND_LOG_LENGTH ++# define CONFIG_HINFC610_DBG_NAND_LOG_LENGTH (40) ++#endif /* CONFIG_HINFC610_DBG_NAND_LOG_LENGTH */ ++ ++struct hinfc610_dbg_dump_item_t { ++ unsigned short hour; ++ unsigned short min; ++ unsigned short sec; ++ unsigned short msec; ++ ++ unsigned int cycle; ++ ++ unsigned long page; ++ unsigned long offset; ++ unsigned long length; ++ ++ char page_status[4]; ++ char op; ++ ++ unsigned char data[CONFIG_HINFC610_DBG_NAND_LOG_LENGTH]; ++}; ++ ++struct hinfc610_dbg_dump_t { ++ ++ struct dentry *dentry; ++ unsigned int index; /* current logs index */ ++ int count; /* number of logs */ ++ ++ unsigned long offset; ++ unsigned long length; ++ ++ struct hinfc610_dbg_dump_item_t ++ logs[CONFIG_HINFC610_DBG_NAND_NUM_OF_LOGS]; ++ ++ unsigned int read_index; ++}; ++ ++static DEFINE_MUTEX(dbg_dump_mutex); ++static struct hinfc610_dbg_dump_t *dbg_dump; ++ ++/*****************************************************************************/ ++ ++static void do_gettime(unsigned short *hour, unsigned short *min, ++ unsigned short *sec, unsigned short *msec) ++{ ++ long val; ++ struct timeval tv; ++ ++ do_gettimeofday(&tv); ++ val = tv.tv_sec % 86400; /* the second form 0 hour */ ++ ++ if (hour) ++ *hour = val / 3600; ++ val %= 3600; ++ if (min) ++ *min = val / 60; ++ if (sec) ++ *sec = val % 60; ++ if (msec) ++ *msec = tv.tv_usec / 1000; ++} ++/*****************************************************************************/ ++/* ++ * ++# cat ./debugfs/nand/dump ++Print parameter: "offset=0 length=8" ++UTC Clock op cylce page-offset data ++00:00:33.0321 W 5 0x0000258F-0000 31 18 10 06 18 EF FE 11 ++00:00:33.0325 W 5 0x00002740-0000 31 18 10 06 7C D4 B3 0C ++* ++*/ ++static ssize_t dbgfs_dump_read(struct file *filp, char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ int len = 0; ++ char buf[128] = {0}; ++ unsigned int read_index; ++ char __user *pusrbuf = buffer; ++ struct hinfc610_dbg_dump_item_t *logs; ++ ++ if (*ppos == 0) { ++ ++ if (dbg_dump->count ++ < CONFIG_HINFC610_DBG_NAND_NUM_OF_LOGS) ++ dbg_dump->read_index = 0; ++ else ++ dbg_dump->read_index ++ = (dbg_dump->index + 1); ++ ++ len = snprintf(buf, sizeof(buf), ++ "Print parameter: \"offset=%ld length=%ld\"\n", ++ dbg_dump->offset, dbg_dump->length); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ ++ pusrbuf += len; ++ ++ len += snprintf(buf, sizeof(buf), ++ " UTC Clock op cylce page-offset data\n"); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ ++ pusrbuf += len; ++ ++ } else if (dbg_dump->read_index == dbg_dump->index) ++ return 0; ++ ++ for (read_index = dbg_dump->read_index; ++ (read_index != dbg_dump->index); ++ ++read_index) { ++ ++ if (read_index >= CONFIG_HINFC610_DBG_NAND_NUM_OF_LOGS) ++ read_index = 0; ++ ++ logs = &dbg_dump->logs[read_index]; ++ ++ if ((count - (pusrbuf - buffer)) < (50 + logs->length * 3)) ++ break; ++ ++ len = snprintf(buf, sizeof(buf), ++ "%02d:%02d:%02d.%04d %c %-2u 0x%08lX-%04lX", ++ logs->hour, logs->min, logs->sec, logs->msec, ++ logs->op, logs->cycle, ++ logs->page, logs->offset); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ ++ pusrbuf += len; ++ ++ if (logs->op == 'E') { ++ ++ len = snprintf(buf, sizeof(buf), " ---"); ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ ++ } else { ++ ++ int ix; ++ ++ len = snprintf(buf, sizeof(buf), "%s", ++ logs->page_status); ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ ++ for (ix = 0; ix < logs->length; ix++) { ++ if ((ix % 16) == 15) { ++ len = snprintf(buf, sizeof(buf), ++ "%02X-", ++ logs->data[ix]); ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ } else { ++ len = snprintf(buf, sizeof(buf), ++ "%02X ", ++ logs->data[ix]); ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ } ++ } ++ } ++ len = snprintf(buf, sizeof(buf), "\n"); ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ } ++ ++ dbg_dump->read_index = read_index; ++ ++ *ppos += (pusrbuf - buffer); ++ return pusrbuf - buffer; ++} ++/*****************************************************************************/ ++ ++static ssize_t dbgfs_dump_write(struct file *filp, const char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ char *p; ++ int ret; ++ unsigned long value = 0; ++ char buf[128] = {0}; ++ unsigned long pos = 0; ++ ++ if (count > sizeof(buf)) ++ count = sizeof(buf); ++ ++ if (copy_from_user(buf, buffer, count)) ++ return -EFAULT; ++ ++ while (pos < count) { ++ ++ while (pos < count ++ && (buf[pos] == ' ' || ++ buf[pos] == ',' || buf[pos] == ';')) ++ pos++; ++ ++ if (pos >= count) ++ break; ++ ++ switch (buf[pos]) { ++ case 'o': ++ if (!memcmp(&buf[pos], CMD_WORD_OFFSET, ++ sizeof(CMD_WORD_OFFSET) - 1)) { ++ ++ pos += sizeof(CMD_WORD_OFFSET) - 1; ++ p = (char *)(buf + pos); ++ ret = kstrtoul(p, 10, &value); ++ if (ret < 0) ++ value = 0; ++ dbg_dump->offset = value; ++ } ++ break; ++ ++ case 'l': ++ if (!memcmp(&buf[pos], CMD_WORD_LENGTH, ++ sizeof(CMD_WORD_LENGTH) - 1)) { ++ ++ pos += sizeof(CMD_WORD_LENGTH) - 1; ++ p = (char *)(buf + pos); ++ ret = kstrtoul(p, 10, &value); ++ if (ret < 0) ++ value = 0; ++ dbg_dump->length = value; ++ } ++ break; ++ } ++ ++ while (pos < count && ++ (buf[pos] != ' ' && buf[pos] != ',' && buf[pos] != ';')) ++ pos++; ++ } ++ ++ *ppos += count; ++ return count; ++} ++/*****************************************************************************/ ++ ++static const struct file_operations dbgfs_dump_fops = { ++ .owner = THIS_MODULE, ++ .read = dbgfs_dump_read, ++ .write = dbgfs_dump_write, ++}; ++/*****************************************************************************/ ++ ++static int dbgfs_dump_init(struct dentry *root, struct hinfc_host *host) ++{ ++ struct hinfc610_dbg_dump_t *dump; ++ ++ if (dbg_dump) ++ return 0; ++ ++ dump = vmalloc(sizeof(struct hinfc610_dbg_dump_t)); ++ if (!dump) { ++ PR_ERR("Can't allocate memory.\n"); ++ return -ENOMEM; ++ } ++ memset(dump, 0, sizeof(struct hinfc610_dbg_dump_t)); ++ ++ dump->dentry = debugfs_create_file("dump", ++ S_IFREG | S_IRUSR | S_IWUSR, ++ root, NULL, &dbgfs_dump_fops); ++ if (!dump->dentry) { ++ PR_ERR("Can't create 'dump' file.\n"); ++ vfree(dump); ++ return -ENOENT; ++ } ++ ++ dump->length = 8; ++ ++ dbg_dump = dump; ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int dbgfs_dump_uninit(void) ++{ ++ if (!dbg_dump) ++ return 0; ++ ++ mutex_lock(&dbg_dump_mutex); ++ ++ debugfs_remove(dbg_dump->dentry); ++ ++ vfree(dbg_dump); ++ dbg_dump = NULL; ++ ++ mutex_unlock(&dbg_dump_mutex); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static void dbg_dump_rw(struct hinfc_host *host, char op) ++{ ++ unsigned long buflen; ++ struct hinfc610_dbg_dump_item_t *logs; ++ ++ mutex_lock(&dbg_dump_mutex); ++ ++ if (!dbg_dump) ++ goto exit; ++ ++ buflen = (host->pagesize + host->oobsize); ++ logs = &dbg_dump->logs[dbg_dump->index]; ++ ++ dbg_dump->count++; ++ ++ do_gettime(&logs->hour, &logs->min, &logs->sec, &logs->msec); ++ ++ memcpy(logs->page_status, "\x20\x20\x20\x00", 4); ++ ++ if (host->page_status) { ++ if (IS_PS_BAD_BLOCK(host)) ++ logs->page_status[0] = 'B'; ++ else if (IS_PS_EMPTY_PAGE(host)) ++ logs->page_status[0] = 'E'; ++ ++ if (IS_PS_UN_ECC(host)) ++ logs->page_status[1] = '*'; ++ ++ if (IS_PS_EPM_ERR(host) || IS_PS_BBM_ERR(host)) ++ logs->page_status[2] = '?'; ++ } ++ ++ logs->op = op; ++ logs->cycle = host->addr_cycle; ++ logs->length = dbg_dump->length; ++ logs->offset = (host->addr_value[0] & 0xFFFF); ++ logs->page = GET_PAGE_INDEX(host); ++ ++ if (!logs->offset) ++ logs->offset = dbg_dump->offset; ++ ++ if (logs->offset >= buflen) ++ logs->offset = 0; ++ ++ if (logs->length > (buflen - logs->offset)) ++ logs->length = (buflen - logs->offset); ++ ++ if (logs->length > CONFIG_HINFC610_DBG_NAND_LOG_LENGTH) ++ logs->length = CONFIG_HINFC610_DBG_NAND_LOG_LENGTH; ++ ++ memcpy(logs->data, (host->buffer + logs->offset), logs->length); ++ ++ if (++dbg_dump->index >= CONFIG_HINFC610_DBG_NAND_NUM_OF_LOGS) ++ dbg_dump->index = 0; ++ ++exit: ++ mutex_unlock(&dbg_dump_mutex); ++} ++/*****************************************************************************/ ++ ++static void dbg_dump_read(struct hinfc_host *host) ++{ ++ dbg_dump_rw(host, 'R'); ++} ++/*****************************************************************************/ ++ ++static void dbg_dump_write(struct hinfc_host *host) ++{ ++ dbg_dump_rw(host, 'W'); ++} ++/*****************************************************************************/ ++ ++static void dbg_dump_erase(struct hinfc_host *host) ++{ ++ struct hinfc610_dbg_dump_item_t *logs; ++ ++ mutex_lock(&dbg_dump_mutex); ++ ++ if (!dbg_dump) ++ goto exit; ++ ++ dbg_dump->count++; ++ logs = &dbg_dump->logs[dbg_dump->index]; ++ ++ do_gettime(&logs->hour, &logs->min, &logs->sec, &logs->msec); ++ ++ memcpy(logs->page_status, "\x20\x20\x20\x00", 4); ++ ++ logs->op = 'E'; ++ logs->cycle = host->addr_cycle; ++ logs->length = dbg_dump->length; ++ ++ logs->offset = 0; ++ logs->page = host->addr_value[0]; ++ logs->length = 0; ++ ++ if (++dbg_dump->index >= CONFIG_HINFC610_DBG_NAND_NUM_OF_LOGS) ++ dbg_dump->index = 0; ++ ++exit: ++ mutex_unlock(&dbg_dump_mutex); ++} ++/*****************************************************************************/ ++ ++struct hinfc610_dbg_inf_t hinfc610_dbg_inf_dump = { ++ "dump", 0, ++ dbgfs_dump_init, ++ dbgfs_dump_uninit, ++ dbg_dump_read, ++ dbg_dump_write, ++ dbg_dump_erase, ++ NULL, ++}; ++/*****************************************************************************/ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_dbg_ecc_count.c b/drivers/mtd/nand/hinfc610/hinfc610_dbg_ecc_count.c +new file mode 100644 +index 0000000..b7174ab +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_dbg_ecc_count.c +@@ -0,0 +1,401 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++#include "hinfc610_dbg.h" ++ ++#ifndef CONFIG_HINFC610_DBG_ECC_COUNT_NUM ++# define CONFIG_HINFC610_DBG_ECC_COUNT_NUM (100) ++#endif /* CONFIG_HINFC610_DBG_ECC_COUNT_NUM */ ++ ++struct hinfc610_dbg_ecc_count_item_t { ++ unsigned int page; ++ unsigned int page_status; /* the same as host->page_status */ ++ unsigned short hour; ++ unsigned short min; ++ unsigned short sec; ++ unsigned short msec; ++ ++ unsigned char ecc[4]; ++}; ++ ++struct hinfc610_dbg_ecc_count_t { ++ ++ struct dentry *dentry; ++ unsigned int index; /* current logs index */ ++ int count; /* number of logs */ ++ ++ struct hinfc610_ecc_inf_t *ecc_inf; ++ unsigned int offset; ++ unsigned int length; ++ unsigned int pagecount; ++ ++ unsigned char *item; ++ ++ unsigned int read_index; ++}; ++ ++#define GET_ITEM(_ecc_count, _index) \ ++ ((struct hinfc610_dbg_ecc_count_item_t *)((_ecc_count)->item + \ ++ ((sizeof(struct hinfc610_dbg_ecc_count_item_t) + \ ++ (_ecc_count)->ecc_inf->section) * (_index)))) ++ ++static DEFINE_MUTEX(dbg_ecc_count_mutex); ++static struct hinfc610_dbg_ecc_count_t *dbg_ecc_count; ++/*****************************************************************************/ ++ ++static void do_gettime(unsigned short *hour, unsigned short *min, ++ unsigned short *sec, unsigned short *msec) ++{ ++ long val; ++ struct timeval tv; ++ ++ do_gettimeofday(&tv); ++ val = tv.tv_sec % 86400; /* the second form 0 hour */ ++ ++ if (hour) ++ *hour = val / 3600; ++ val %= 3600; ++ if (min) ++ *min = val / 60; ++ if (sec) ++ *sec = val % 60; ++ if (msec) ++ *msec = tv.tv_usec / 1000; ++} ++/*****************************************************************************/ ++ ++static ssize_t dbgfs_ecc_count_read(struct file *filp, char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ int len = 0; ++ char buf[128] = {0}; ++ unsigned int read_index; ++ char __user *pusrbuf = buffer; ++ struct hinfc610_dbg_ecc_count_item_t *item; ++ ++ if (*ppos == 0) { ++ ++ if (dbg_ecc_count->count ++ < CONFIG_HINFC610_DBG_ECC_COUNT_NUM) ++ dbg_ecc_count->read_index = 0; ++ else ++ dbg_ecc_count->read_index ++ = (dbg_ecc_count->index + 1); ++ ++ len = snprintf(buf, sizeof(buf), ++ "Print parameter: \"offset=%d length=%d\"\n", ++ dbg_ecc_count->offset, ++ dbg_ecc_count->length); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ ++ pusrbuf += len; ++ ++ len = snprintf(buf, sizeof(buf), ++ " UTC Clock page ecc data\n"); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ ++ pusrbuf += len; ++ ++ } else if (dbg_ecc_count->read_index == dbg_ecc_count->index) ++ return 0; ++ ++ for (read_index = dbg_ecc_count->read_index; ++ (read_index != dbg_ecc_count->index); ++read_index) { ++ ++ if (read_index >= CONFIG_HINFC610_DBG_ECC_COUNT_NUM) ++ read_index = 0; ++ ++ item = GET_ITEM(dbg_ecc_count, read_index); ++ ++ if ((count - (pusrbuf - buffer)) < 80) ++ break; ++ ++ len = snprintf(buf, sizeof(buf), ++ "%02d:%02d:%02d.%04d 0x%08X ", ++ item->hour, item->min, item->sec, item->msec, ++ item->page); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ ++ pusrbuf += len; ++ ++ if (IS_PS_BAD_BLOCK(item) || IS_PS_EMPTY_PAGE(item) || ++ IS_PS_UN_ECC(item)) { ++ char *ptr = buf; ++ ++ if (IS_PS_BAD_BLOCK(item)) ++ ptr += snprintf(ptr, 16, "bb "); ++ else if (IS_PS_EMPTY_PAGE(item)) ++ ptr += snprintf(ptr, 16, "ep "); ++ ++ if (IS_PS_UN_ECC(item)) ++ ptr += snprintf(ptr, 16, "ecc "); ++ ++ if (IS_PS_EPM_ERR(item) || IS_PS_BBM_ERR(item)) ++ ptr += snprintf(ptr, 16, "? "); ++ ++ ptr += snprintf(ptr, 16, "\n"); ++ len = (ptr - buf); ++ ++ } else { ++ int ix; ++ char *ptr = buf; ++ ++ for (ix = 0; ix < dbg_ecc_count->ecc_inf->section; ix++) ++ ptr += snprintf(ptr, 16, "%d/", item->ecc[ix]); ++ ++ if (IS_PS_EPM_ERR(item)) ++ ptr += snprintf(ptr, 16, " ?"); ++ ++ ptr += snprintf(ptr, 16, "\n"); ++ len = (ptr - buf); ++ } ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ } ++ ++ dbg_ecc_count->read_index = read_index; ++ ++ *ppos += (pusrbuf - buffer); ++ return pusrbuf - buffer; ++} ++/******************************************************************************/ ++/* ++ * echo "offset=8192,length=102400" > ecc_count ++ * ++ */ ++static ssize_t dbgfs_ecc_count_write(struct file *filp, ++ const char __user *buffer, size_t count, ++ loff_t *ppos) ++{ ++ char *str; ++ char buf[128] = {0}; ++ int ret; ++ unsigned long value = 0; ++ unsigned long pos = 0; ++ ++ if (count > sizeof(buf)) ++ count = sizeof(buf); ++ ++ if (copy_from_user(buf, buffer, count)) ++ return -EFAULT; ++ ++ while (pos < count) { ++ while (pos < count && ++ (buf[pos] == ' ' || buf[pos] == ',' || buf[pos] == ';')) ++ pos++; ++ ++ if (pos >= count) ++ break; ++ ++ switch (buf[pos]) { ++ ++ case 'o': ++ ++ if (memcmp(&buf[pos], CMD_WORD_OFFSET, ++ sizeof(CMD_WORD_OFFSET) - 1)) ++ break; ++ ++ pos += sizeof(CMD_WORD_OFFSET) - 1; ++ str = (char *)(buf + pos); ++ ret = kstrtoul(str, 10, &value); ++ ++ if (ret < 0) ++ value = 0; ++ if (value >= dbg_ecc_count->pagecount) ++ value = 0; ++ ++ dbg_ecc_count->offset = (value & ~7); ++ ++ break; ++ ++ case 'l': ++ if (memcmp(&buf[pos], CMD_WORD_LENGTH, ++ sizeof(CMD_WORD_LENGTH) - 1)) ++ break; ++ ++ pos += sizeof(CMD_WORD_LENGTH) - 1; ++ str = (char *)(buf + pos); ++ ret = kstrtoul(str, 10, &value); ++ ++ if (ret < 0) ++ value = dbg_ecc_count->pagecount; ++ ++ value = ((value + 7) & ~7); ++ ++ if (dbg_ecc_count->offset + value > ++ dbg_ecc_count->pagecount) ++ value = dbg_ecc_count->pagecount ++ - dbg_ecc_count->offset; ++ ++ dbg_ecc_count->length = value; ++ ++ break; ++ } ++ ++ while (pos < count && ++ (buf[pos] != ' ' && buf[pos] != ',' && buf[pos] != ';')) ++ pos++; ++ } ++ ++ return count; ++} ++/******************************************************************************/ ++ ++static const struct file_operations dbgfs_ecc_count_fops = { ++ .owner = THIS_MODULE, ++ .read = dbgfs_ecc_count_read, ++ .write = dbgfs_ecc_count_write, ++}; ++/*****************************************************************************/ ++ ++static int dbgfs_ecc_count_init(struct dentry *root, struct hinfc_host *host) ++{ ++ unsigned int size; ++ unsigned int pagesize; ++ unsigned int chipsize; ++ struct hinfc610_ecc_inf_t *ecc_inf; ++ struct hinfc610_dbg_ecc_count_t *ecc_count; ++ ++ if (dbg_ecc_count) ++ return 0; ++ ++ ecc_inf = hinfc610_get_ecc_inf(host, host->pagesize, host->ecctype); ++ if (!ecc_inf) { ++ pr_warn("ecc_count: The NAND not support this interface.\n"); ++ return -1; ++ } ++ ++ size = sizeof(struct hinfc610_dbg_ecc_count_t); ++ size += CONFIG_HINFC610_DBG_ECC_COUNT_NUM * ++ (sizeof(struct hinfc610_dbg_ecc_count_item_t) ++ + ecc_inf->section); ++ ++ ecc_count = vmalloc(size); ++ if (!ecc_count) { ++ PR_ERR("Can't allocate memory.\n"); ++ return -ENOMEM; ++ } ++ memset(ecc_count, 0, size); ++ ++ ecc_count->item = (char *)ecc_count + ++ sizeof(struct hinfc610_dbg_ecc_count_t); ++ ecc_count->ecc_inf = ecc_inf; ++ ++ pagesize = (host->pagesize >> 10); ++ chipsize = (unsigned int)(host->chip->chipsize >> 10); ++ ecc_count->pagecount = (chipsize / pagesize); ++ ecc_count->length = ecc_count->pagecount; ++ ++ ecc_count->dentry = debugfs_create_file("ecc_count", ++ S_IFREG | S_IRUSR | S_IWUSR, ++ root, NULL, &dbgfs_ecc_count_fops); ++ if (!ecc_count->dentry) { ++ PR_ERR("Can't create 'ecc_count' file.\n"); ++ vfree(ecc_count); ++ return -ENOENT; ++ } ++ ++ dbg_ecc_count = ecc_count; ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int dbgfs_ecc_count_uninit(void) ++{ ++ if (!dbg_ecc_count) ++ return 0; ++ ++ mutex_lock(&dbg_ecc_count_mutex); ++ ++ debugfs_remove(dbg_ecc_count->dentry); ++ ++ vfree(dbg_ecc_count); ++ dbg_ecc_count = NULL; ++ ++ mutex_unlock(&dbg_ecc_count_mutex); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static void dbg_ecc_count_read(struct hinfc_host *host) ++{ ++ unsigned int page; ++ struct hinfc610_dbg_ecc_count_item_t *item; ++ ++ mutex_lock(&dbg_ecc_count_mutex); ++ ++ if (!dbg_ecc_count) ++ goto exit; ++ ++ page = GET_PAGE_INDEX(host); ++ ++ if (page < dbg_ecc_count->offset || ++ page > (dbg_ecc_count->offset + dbg_ecc_count->length)) ++ goto exit; ++ ++ item = GET_ITEM(dbg_ecc_count, dbg_ecc_count->index); ++ ++ dbg_ecc_count->count++; ++ ++ do_gettime(&item->hour, &item->min, &item->sec, &item->msec); ++ ++ item->page = page; ++ item->page_status = host->page_status; ++ ++ if (!IS_PS_UN_ECC(host)) ++ dbg_ecc_count->ecc_inf->ecc_inf(host, item->ecc); ++ ++ if (++dbg_ecc_count->index >= CONFIG_HINFC610_DBG_ECC_COUNT_NUM) ++ dbg_ecc_count->index = 0; ++ ++exit: ++ mutex_unlock(&dbg_ecc_count_mutex); ++} ++/*****************************************************************************/ ++ ++struct hinfc610_dbg_inf_t hinfc610_dbg_inf_ecc_count = { ++ "ecc_count", 0, ++ dbgfs_ecc_count_init, ++ dbgfs_ecc_count_uninit, ++ dbg_ecc_count_read, ++ NULL, ++ NULL, ++ NULL, ++}; ++/*****************************************************************************/ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_dbg_ecc_dump.c b/drivers/mtd/nand/hinfc610/hinfc610_dbg_ecc_dump.c +new file mode 100644 +index 0000000..a1b7eda +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_dbg_ecc_dump.c +@@ -0,0 +1,141 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++#include "hinfc610_dbg.h" ++ ++/*****************************************************************************/ ++static inline void hinfc610_detect_ecc(unsigned char ecc[], int begin, ++ int end, unsigned int reg) ++{ ++ while (begin < end) { ++ ecc[begin] = (reg & 0xff); ++ reg = (reg >> 8); ++ begin++; ++ } ++} ++/*****************************************************************************/ ++ ++static void hinfc610_ecc_32k(struct hinfc_host *host, unsigned char ecc[]) ++{ ++ int ix, jx, kx; ++ ++ for (ix = 0, jx = 0; ix < 4; ix ++, jx += 4) ++ hinfc610_detect_ecc(ecc, jx, jx + 4, ++ hinfc_read(host, 0xA0 + jx)); ++ kx = jx; ++ for (ix = 0, jx = 0; ix < 4; ix ++, jx += 4) ++ hinfc610_detect_ecc(ecc, kx, kx + 4, ++ hinfc_read(host, 0xDC + jx)); ++} ++/*****************************************************************************/ ++ ++static void hinfc610_ecc_16k(struct hinfc_host *host, unsigned char ecc[]) ++{ ++ int ix, jx; ++ ++ for (ix = 0, jx = 0; ix < 4; ix ++, jx += 4) ++ hinfc610_detect_ecc(ecc, jx, jx + 4, ++ hinfc_read(host, 0xA0 + jx)); ++} ++/*****************************************************************************/ ++ ++static void hinfc610_ecc_8k(struct hinfc_host *host, unsigned char ecc[]) ++{ ++ int ix, jx; ++ ++ for (ix = 0, jx = 0; ix < 2; ix ++, jx += 4) ++ hinfc610_detect_ecc(ecc, jx, jx + 4, ++ hinfc_read(host, 0xA0 + jx)); ++} ++/*****************************************************************************/ ++ ++static void hinfc610_ecc_4k(struct hinfc_host *host, unsigned char ecc[]) ++{ ++ hinfc610_detect_ecc(ecc, 0, 4, hinfc_read(host, 0xA0)); ++} ++/*****************************************************************************/ ++ ++static void hinfc610_ecc_2k(struct hinfc_host *host, unsigned char ecc[]) ++{ ++ hinfc610_detect_ecc(ecc, 0, 2, hinfc_read(host, 0xA0)); ++} ++/*****************************************************************************/ ++ ++static struct hinfc610_ecc_inf_t hinfc610_ecc_inf[] = { ++ ++ {32768, NAND_ECC_80BIT, 32, hinfc610_ecc_32k}, ++ {32768, NAND_ECC_72BIT, 32, hinfc610_ecc_32k}, ++ {32768, NAND_ECC_60BIT, 32, hinfc610_ecc_32k}, ++ {32768, NAND_ECC_48BIT, 32, hinfc610_ecc_32k}, ++ {32768, NAND_ECC_41BIT, 32, hinfc610_ecc_32k}, ++ ++ {16384, NAND_ECC_80BIT, 16, hinfc610_ecc_16k}, ++ {16384, NAND_ECC_72BIT, 16, hinfc610_ecc_16k}, ++ {16384, NAND_ECC_60BIT, 16, hinfc610_ecc_16k}, ++ {16384, NAND_ECC_48BIT, 16, hinfc610_ecc_16k}, ++ {16384, NAND_ECC_41BIT, 16, hinfc610_ecc_16k}, ++ ++ {8192, NAND_ECC_80BIT, 8, hinfc610_ecc_8k}, ++ {8192, NAND_ECC_72BIT, 8, hinfc610_ecc_8k}, ++ {8192, NAND_ECC_60BIT, 8, hinfc610_ecc_8k}, ++ {8192, NAND_ECC_48BIT, 8, hinfc610_ecc_8k}, ++ {8192, NAND_ECC_41BIT, 8, hinfc610_ecc_8k}, ++ {8192, NAND_ECC_32BIT, 8, hinfc610_ecc_8k}, ++ {8192, NAND_ECC_27BIT, 8, hinfc610_ecc_8k}, ++ {8192, NAND_ECC_24BIT, 8, hinfc610_ecc_8k}, ++ ++ ++ ++ {4096, NAND_ECC_32BIT, 4, hinfc610_ecc_4k}, ++ {4096, NAND_ECC_27BIT, 4, hinfc610_ecc_4k}, ++ {4096, NAND_ECC_24BIT, 4, hinfc610_ecc_4k}, ++ {4096, NAND_ECC_18BIT, 4, hinfc610_ecc_4k}, ++ {4096, NAND_ECC_13BIT, 4, hinfc610_ecc_4k}, ++ {4096, NAND_ECC_8BIT, 4, hinfc610_ecc_4k}, ++ ++ {2048, NAND_ECC_32BIT, 2, hinfc610_ecc_2k}, ++ {2048, NAND_ECC_27BIT, 2, hinfc610_ecc_2k}, ++ {2048, NAND_ECC_24BIT, 2, hinfc610_ecc_2k}, ++ {2048, NAND_ECC_18BIT, 2, hinfc610_ecc_2k}, ++ {2048, NAND_ECC_13BIT, 2, hinfc610_ecc_2k}, ++ {2048, NAND_ECC_8BIT, 2, hinfc610_ecc_2k}, ++ {0, 0, 0}, ++}; ++/*****************************************************************************/ ++ ++struct hinfc610_ecc_inf_t *hinfc610_get_ecc_inf(struct hinfc_host *host, ++ int pagesize, int ecctype) ++{ ++ struct hinfc610_ecc_inf_t *inf; ++ ++ for (inf = hinfc610_ecc_inf; inf->pagesize; inf++) ++ if (inf->pagesize == pagesize && inf->ecctype == ecctype) ++ return inf; ++ ++ return NULL; ++} +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_dbg_erase_count.c b/drivers/mtd/nand/hinfc610/hinfc610_dbg_erase_count.c +new file mode 100644 +index 0000000..eedbd2b +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_dbg_erase_count.c +@@ -0,0 +1,317 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++#include "hinfc610_dbg.h" ++ ++struct hinfc610_dbg_erase_count_t { ++ ++ unsigned int index; /* display pos */ ++ unsigned int offset; /* display offset */ ++ unsigned int length; /* display length */ ++ ++ struct dentry *dentry; ++ ++ unsigned int blocknum; ++ unsigned int page_per_block; ++ ++ unsigned int pe[1]; ++}; ++ ++static DEFINE_MUTEX(dbg_erase_count_mutex); ++static struct hinfc610_dbg_erase_count_t *dbg_erase_count; ++ ++/*****************************************************************************/ ++ ++static int dbgfs_erase_count_read(struct file *filp, char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ int len = 0; ++ int value = 0; ++ unsigned int *pe; ++ unsigned int index; ++ char buf[128] = {0}; ++ char __user *pusrbuf = buffer; ++ ++ if (*ppos == 0) { ++ dbg_erase_count->index = dbg_erase_count->offset; ++ ++ len = snprintf(buf, sizeof(buf), ++ "Print parameter: \"offset=%d length=%d\"\n", ++ dbg_erase_count->offset, ++ dbg_erase_count->length); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ ++ len = snprintf(buf, sizeof(buf), ++ "Block Index ---------------- " ++ "Erase count from system startup ----------------\n"); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ } ++ ++ for (index = dbg_erase_count->index; ++ index < (dbg_erase_count->offset + dbg_erase_count->length) && ++ ((pusrbuf - buffer) < (count - 100)); ++ index += 8) { ++ ++ pe = &dbg_erase_count->pe[index]; ++ ++ len = snprintf(buf, sizeof(buf), ++ "%4d: %8u %8u %8u %8u %8u %8u %8u %8u\n", ++ index, ++ pe[0], pe[1], pe[2], pe[3], ++ pe[4], pe[5], pe[6], pe[7]); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ } ++ ++ dbg_erase_count->index = index; ++ ++ *ppos += (pusrbuf - buffer); ++ value = pusrbuf - buffer; ++ return value; ++} ++/*****************************************************************************/ ++/* ++ * echo "offset=48,length=78" > /sys/kernel/debug/nand/erase_count ++ * echo "clear" > /sys/kernel/debug/nand/erase_count ++ * ++ ++ # cat ./debugfs/nand/erase_count ++ Print parameter: "offset=0 length=1024" ++ Block Index ---------------- Erase count from system startup ---------------- ++ 0: 0 0 0 0 0 0 0 0 ++ 8: 0 0 0 0 0 0 0 0 ++ 16: 0 0 0 0 0 0 0 0 ++ 24: 0 0 0 0 0 0 0 0 ++ 32: 0 0 0 0 0 0 0 0 ++ 40: 0 0 0 0 0 0 0 0 ++ 48: 0 0 0 0 0 0 0 0 ++ 56: 0 0 0 0 0 0 0 0 ++ 64: 0 0 0 0 0 0 0 0 ++ 72: 0 0 0 0 0 0 0 0 ++ 80: 0 0 0 0 0 0 0 0 ++ ++ */ ++static int dbgfs_erase_count_write(struct file *filp, ++ const char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ char *str; ++ char buf[128] = {0}; ++ int ret; ++ unsigned long value = 0; ++ unsigned long pos = 0; ++ ++ if (count > sizeof(buf)) ++ count = sizeof(buf); ++ ++ if (copy_from_user(buf, buffer, count)) ++ return -EFAULT; ++ ++ while (pos < count) { ++ while (pos < count && ++ (buf[pos] == ' ' || buf[pos] == ',' || buf[pos] == ';')) ++ pos++; ++ ++ if (pos >= count) ++ break; ++ ++ switch (buf[pos]) { ++ ++ case 'o': ++ ++ if (memcmp(&buf[pos], CMD_WORD_OFFSET, ++ sizeof(CMD_WORD_OFFSET) - 1)) ++ break; ++ ++ pos += sizeof(CMD_WORD_OFFSET) - 1; ++ str = (char *)(buf + pos); ++ ret = kstrtoul(str, 10, &value); ++ if (ret < 0) ++ value = 0; ++ if (value >= dbg_erase_count->blocknum) ++ value = 0; ++ ++ dbg_erase_count->offset = (value & ~7); ++ ++ break; ++ ++ case 'l': ++ if (memcmp(&buf[pos], CMD_WORD_LENGTH, ++ sizeof(CMD_WORD_LENGTH) - 1)) ++ break; ++ ++ pos += sizeof(CMD_WORD_LENGTH) - 1; ++ str = (char *)(buf + pos); ++ ret = kstrtoul(str, 10, &value); ++ if (ret < 0) ++ value = dbg_erase_count->blocknum; ++ ++ value = ((value + 7) & ~7); ++ ++ if (dbg_erase_count->offset + value ++ > dbg_erase_count->blocknum) ++ value = dbg_erase_count->blocknum ++ - dbg_erase_count->offset; ++ ++ dbg_erase_count->length = value; ++ ++ break; ++ ++ case 'c': ++ if (memcmp(&buf[pos], CMD_WORD_CLEAN, ++ sizeof(CMD_WORD_CLEAN) - 1)) ++ break; ++ ++ memset(dbg_erase_count->pe, 0, ++ dbg_erase_count->blocknum * ++ sizeof(struct hinfc610_dbg_erase_count_t)); ++ ++ return count; ++ } ++ ++ while (pos < count && ++ (buf[pos] != ' ' && buf[pos] != ',' && buf[pos] != ';')) ++ pos++; ++ } ++ ++ return count; ++} ++/*****************************************************************************/ ++ ++static const struct file_operations dbgfs_erase_count_fops = { ++ .owner = THIS_MODULE, ++ .read = dbgfs_erase_count_read, ++ .write = dbgfs_erase_count_write, ++}; ++/*****************************************************************************/ ++ ++static int dbgfs_erase_count_init(struct dentry *root, struct hinfc_host *host) ++{ ++ unsigned int size; ++ unsigned int blocknum; ++ unsigned int pagesize; ++ unsigned int blocksize; ++ unsigned int chipsize; ++ struct hinfc610_dbg_erase_count_t *erase_count; ++ ++ if (dbg_erase_count) ++ return 0; ++ ++ pagesize = (host->pagesize >> 10); ++ blocksize = (host->mtd->erasesize >> 10); ++ chipsize = (unsigned int)(host->chip->chipsize >> 10); ++ ++ blocknum = chipsize / blocksize; ++ size = sizeof(int) * blocknum ++ + sizeof(struct hinfc610_dbg_erase_count_t); ++ ++ erase_count = vmalloc(size); ++ if (!erase_count) { ++ PR_ERR("Can't allocate memory.\n"); ++ return -ENOMEM; ++ } ++ memset(erase_count, 0, size); ++ ++ erase_count->blocknum = blocknum; ++ erase_count->page_per_block = blocksize / pagesize; ++ erase_count->length = blocknum; ++ ++ erase_count->dentry = debugfs_create_file("erase_count", ++ S_IFREG | S_IRUSR | S_IWUSR, ++ root, NULL, &dbgfs_erase_count_fops); ++ if (!erase_count->dentry) { ++ PR_ERR("Can't create 'erase_count' file.\n"); ++ vfree(erase_count); ++ return -ENOENT; ++ } ++ ++ dbg_erase_count = erase_count; ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int dbgfs_erase_count_uninit(void) ++{ ++ if (!dbg_erase_count) ++ return 0; ++ ++ mutex_lock(&dbg_erase_count_mutex); ++ ++ debugfs_remove(dbg_erase_count->dentry); ++ ++ vfree(dbg_erase_count); ++ dbg_erase_count = NULL; ++ ++ mutex_unlock(&dbg_erase_count_mutex); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static void dbg_erase_count_erase(struct hinfc_host *host) ++{ ++ unsigned int block_index; ++ ++ mutex_lock(&dbg_erase_count_mutex); ++ ++ if (!dbg_erase_count) ++ goto exit; ++ ++ block_index = (host->addr_value[0] / dbg_erase_count->page_per_block); ++ ++ if (block_index > dbg_erase_count->blocknum) { ++ PR_ERR("Block out of range.\n"); ++ return; ++ } ++ ++ dbg_erase_count->pe[block_index]++; ++ ++exit: ++ mutex_unlock(&dbg_erase_count_mutex); ++} ++/*****************************************************************************/ ++ ++struct hinfc610_dbg_inf_t hinfc610_dbg_inf_erase_count = { ++ "erase_count", 0, ++ dbgfs_erase_count_init, ++ dbgfs_erase_count_uninit, ++ NULL, ++ NULL, ++ dbg_erase_count_erase, ++ NULL, ++}; +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_dbg_inf.c b/drivers/mtd/nand/hinfc610/hinfc610_dbg_inf.c +new file mode 100644 +index 0000000..f3e7140 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_dbg_inf.c +@@ -0,0 +1,81 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++#include "hinfc610_dbg.h" ++ ++void hinfc610_dbg_write(struct hinfc_host *host) ++{ ++#ifdef CONFIG_HINFC610_DBG_NAND_DEBUG ++ struct hinfc610_dbg_inf_t **inf; ++ ++ for (inf = hinfc610_dbg_inf; *inf; inf++) ++ if ((*inf)->enable && (*inf)->write) ++ (*inf)->write(host); ++#endif ++} ++ ++void hinfc610_dbg_erase(struct hinfc_host *host) ++{ ++#ifdef CONFIG_HINFC610_DBG_NAND_DEBUG ++ struct hinfc610_dbg_inf_t **inf; ++ ++ for (inf = hinfc610_dbg_inf; *inf; inf++) ++ if ((*inf)->enable && (*inf)->erase) ++ (*inf)->erase(host); ++#endif ++} ++ ++void hinfc610_dbg_read(struct hinfc_host *host) ++{ ++#ifdef CONFIG_HINFC610_DBG_NAND_DEBUG ++ struct hinfc610_dbg_inf_t **inf; ++ ++ for (inf = hinfc610_dbg_inf; *inf; inf++) ++ if ((*inf)->enable && (*inf)->read) ++ (*inf)->read(host); ++#endif ++} ++ ++void hinfc610_dbg_read_retry(struct hinfc_host *host, int index) ++{ ++#ifdef CONFIG_HINFC610_DBG_NAND_DEBUG ++ struct hinfc610_dbg_inf_t **inf; ++ ++ for (inf = hinfc610_dbg_inf; *inf; inf++) ++ if ((*inf)->enable && (*inf)->read_retry) ++ (*inf)->read_retry(host, index); ++#endif ++} ++ ++int hinfc610_dbg_init(struct hinfc_host *host) ++{ ++#ifdef CONFIG_HINFC610_DBG_NAND_DEBUG ++ return hinfc610_dbgfs_debug_init(host); ++#endif ++ return 0; ++} +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_dbg_inf.h b/drivers/mtd/nand/hinfc610/hinfc610_dbg_inf.h +new file mode 100644 +index 0000000..10ac797 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_dbg_inf.h +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef HINFC610_DBG_INFH ++#define HINFC610_DBG_INFH ++/******************************************************************************/ ++ ++int hinfc610_dbg_init(struct hinfc_host *host); ++ ++void hinfc610_dbg_write(struct hinfc_host *host); ++ ++void hinfc610_dbg_erase(struct hinfc_host *host); ++ ++void hinfc610_dbg_read(struct hinfc_host *host); ++ ++void hinfc610_dbg_read_retry(struct hinfc_host *host, int index); ++ ++/******************************************************************************/ ++#endif /* HINFC610_DBG_INFH */ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_dbg_read_retry.c b/drivers/mtd/nand/hinfc610/hinfc610_dbg_read_retry.c +new file mode 100644 +index 0000000..176d9c1 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_dbg_read_retry.c +@@ -0,0 +1,385 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++#include "hinfc610_dbg.h" ++ ++#ifndef CONFIG_HINFC610_DBG_READ_RETRY_NUM ++# define CONFIG_HINFC610_DBG_READ_RETRY_NUM (100) ++#endif /* CONFIG_HINFC610_DBG_READ_RETRY_NUM */ ++ ++struct hinfc610_dbg_read_retry_item_t { ++ unsigned int page; ++ ++ unsigned short hour; ++ unsigned short min; ++ unsigned short sec; ++ unsigned short msec; ++ ++ unsigned short retry; /* success retry */ ++ unsigned short ecc_err; ++}; ++ ++struct hinfc610_dbg_read_retry_t { ++ ++ struct dentry *dentry; ++ unsigned int index; /* current logs index */ ++ int count; /* number of logs */ ++ ++ unsigned int offset; ++ unsigned int length; ++ unsigned int pagecount; ++ ++ unsigned int read_index; ++ ++ unsigned int max_retry; /* the max read retry times */ ++ unsigned int retry[16]; ++ ++ struct hinfc610_dbg_read_retry_item_t ++ item[CONFIG_HINFC610_DBG_READ_RETRY_NUM]; ++}; ++ ++static DEFINE_MUTEX(dbg_read_retry_mutex); ++static struct hinfc610_dbg_read_retry_t *dbg_read_retry; ++/*****************************************************************************/ ++ ++static void do_gettime(unsigned short *hour, unsigned short *min, ++ unsigned short *sec, unsigned short *msec) ++{ ++ long val; ++ struct timeval tv; ++ ++ do_gettimeofday(&tv); ++ val = tv.tv_sec % 86400; /* the second form 0 hour */ ++ ++ if (hour) ++ *hour = val / 3600; ++ val %= 3600; ++ if (min) ++ *min = val / 60; ++ if (sec) ++ *sec = val % 60; ++ if (msec) ++ *msec = tv.tv_usec / 1000; ++} ++/*****************************************************************************/ ++ ++static ssize_t dbgfs_read_retry_read(struct file *filp, char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ int ix; ++ char *ptr; ++ int len = 0; ++ char buf[128] = {0}; ++ unsigned int read_index; ++ char __user *pusrbuf = buffer; ++ struct hinfc610_dbg_read_retry_item_t *item; ++ ++ if (*ppos == 0) { ++ ++ if (dbg_read_retry->count ++ < CONFIG_HINFC610_DBG_READ_RETRY_NUM) ++ dbg_read_retry->read_index = 0; ++ else ++ dbg_read_retry->read_index ++ = (dbg_read_retry->index + 1); ++ ++ len = snprintf(buf, sizeof(buf), ++ "Print parameter: \"offset=%d length=%d\"\n", ++ dbg_read_retry->offset, ++ dbg_read_retry->length); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ ++ len = snprintf(buf, sizeof(buf), ++ " UTC Clock page read retry (max: %d)\n", ++ dbg_read_retry->max_retry); ++ ++ ptr = buf; ++ ptr += sprintf(ptr, "Read retry: "); ++ for (ix = 1; ix <= dbg_read_retry->max_retry; ix++) ++ ptr += sprintf(ptr, "%d, ", dbg_read_retry->retry[ix]); ++ ptr += sprintf(ptr, "\n"); ++ ++ len = (ptr - buf); ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ ++ ++ len = snprintf(buf, sizeof(buf), ++ " UTC Clock page read retry (max: %d)\n", ++ dbg_read_retry->max_retry); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ ++ } else if (dbg_read_retry->read_index == dbg_read_retry->index) ++ return 0; ++ ++ for (read_index = dbg_read_retry->read_index; ++ (read_index != dbg_read_retry->index); ++read_index) { ++ ++ if (read_index >= CONFIG_HINFC610_DBG_READ_RETRY_NUM) ++ read_index = 0; ++ ++ item = &dbg_read_retry->item[read_index]; ++ ++ if ((count - (pusrbuf - buffer)) < 80) ++ break; ++ ++ len = snprintf(buf, sizeof(buf), ++ "%02d:%02d:%02d.%04d 0x%08X ", ++ item->hour, item->min, item->sec, item->msec, ++ item->page); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ ++ if (!item->ecc_err) ++ len = sprintf(buf, "%d\n", item->retry); ++ else ++ len = sprintf(buf, "fail\n"); ++ ++ if (copy_to_user(pusrbuf, buf, len)) ++ return -EFAULT; ++ pusrbuf += len; ++ } ++ ++ dbg_read_retry->read_index = read_index; ++ ++ *ppos += (pusrbuf - buffer); ++ return pusrbuf - buffer; ++} ++/******************************************************************************/ ++/* ++ * echo "offset=8192,length=102400" > read_retry ++ * ++ */ ++static ssize_t dbgfs_read_retry_write(struct file *filp, ++ const char __user *buffer, size_t count, ++ loff_t *ppos) ++{ ++ char *str; ++ char buf[128] = {0}; ++ int ret; ++ unsigned long value = 0; ++ unsigned long pos = 0; ++ ++ if (count > sizeof(buf)) ++ count = sizeof(buf); ++ ++ if (copy_from_user(buf, buffer, count)) ++ return -EFAULT; ++ ++ while (pos < count) { ++ while (pos < count && ++ (buf[pos] == ' ' || buf[pos] == ',' || buf[pos] == ';')) ++ pos++; ++ ++ if (pos >= count) ++ break; ++ ++ switch (buf[pos]) { ++ ++ case 'o': ++ ++ if (memcmp(&buf[pos], CMD_WORD_OFFSET, ++ sizeof(CMD_WORD_OFFSET) - 1)) ++ break; ++ ++ pos += sizeof(CMD_WORD_OFFSET) - 1; ++ str = (char *)(buf + pos); ++ ret = kstrtoul(str, 10, &value); ++ ++ if (ret < 0) ++ value = 0; ++ if (value >= dbg_read_retry->pagecount) ++ value = 0; ++ ++ dbg_read_retry->offset = (value & ~7); ++ ++ break; ++ ++ case 'l': ++ if (memcmp(&buf[pos], CMD_WORD_LENGTH, ++ sizeof(CMD_WORD_LENGTH) - 1)) ++ break; ++ ++ pos += sizeof(CMD_WORD_LENGTH) - 1; ++ str = (char *)(buf + pos); ++ ret = kstrtoul(str, 10, &value); ++ ++ if (ret < 0) ++ value = dbg_read_retry->pagecount; ++ ++ value = ((value + 7) & ~7); ++ ++ if (dbg_read_retry->offset + value > ++ dbg_read_retry->pagecount) ++ value = dbg_read_retry->pagecount ++ - dbg_read_retry->offset; ++ ++ dbg_read_retry->length = value; ++ ++ break; ++ } ++ ++ while (pos < count && ++ (buf[pos] != ' ' && buf[pos] != ',' && buf[pos] != ';')) ++ pos++; ++ } ++ ++ return count; ++} ++/******************************************************************************/ ++ ++static const struct file_operations dbgfs_read_retry_fops = { ++ .owner = THIS_MODULE, ++ .read = dbgfs_read_retry_read, ++ .write = dbgfs_read_retry_write, ++}; ++/*****************************************************************************/ ++ ++static int dbgfs_read_retry_init(struct dentry *root, struct hinfc_host *host) ++{ ++ unsigned int pagesize; ++ unsigned int chipsize; ++ struct hinfc610_dbg_read_retry_t *read_retry; ++ ++ if (dbg_read_retry) ++ return 0; ++ ++ if (!host->read_retry) { ++ pr_warn("read_retry: The NAND not support this interface.\n"); ++ return -1; ++ } ++ ++ read_retry = vmalloc(sizeof(struct hinfc610_dbg_read_retry_t)); ++ if (!read_retry) { ++ PR_ERR("Can't allocate memory.\n"); ++ return -ENOMEM; ++ } ++ memset(read_retry, 0, sizeof(struct hinfc610_dbg_read_retry_t)); ++ ++ pagesize = (host->pagesize >> 10); ++ chipsize = (unsigned int)(host->chip->chipsize >> 10); ++ read_retry->pagecount = (chipsize / pagesize); ++ read_retry->length = read_retry->pagecount; ++ read_retry->max_retry = host->read_retry->count; ++ ++ if (read_retry->max_retry > 16) { ++ vfree(read_retry); ++ PR_ERR("Bug, max_retry too small.\n"); ++ return -EFAULT; ++ } ++ ++ read_retry->dentry = debugfs_create_file("read_retry", ++ S_IFREG | S_IRUSR | S_IWUSR, ++ root, NULL, &dbgfs_read_retry_fops); ++ if (!read_retry->dentry) { ++ PR_ERR("Can't create 'read_retry' file.\n"); ++ vfree(read_retry); ++ return -ENOENT; ++ } ++ ++ dbg_read_retry = read_retry; ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int dbgfs_read_retry_uninit(void) ++{ ++ if (!dbg_read_retry) ++ return 0; ++ ++ mutex_lock(&dbg_read_retry_mutex); ++ ++ debugfs_remove(dbg_read_retry->dentry); ++ ++ vfree(dbg_read_retry); ++ dbg_read_retry = NULL; ++ ++ mutex_unlock(&dbg_read_retry_mutex); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static void hinfc610_dbg_read_retry_rr(struct hinfc_host *host, int index) ++{ ++ unsigned int page; ++ struct hinfc610_dbg_read_retry_item_t *item; ++ ++ mutex_lock(&dbg_read_retry_mutex); ++ ++ if (!dbg_read_retry) ++ goto exit; ++ ++ page = GET_PAGE_INDEX(host); ++ ++ if (page < dbg_read_retry->offset || ++ page > (dbg_read_retry->offset + dbg_read_retry->length)) ++ goto exit; ++ ++ item = &dbg_read_retry->item[dbg_read_retry->index]; ++ ++ dbg_read_retry->count++; ++ ++ do_gettime(&item->hour, &item->min, &item->sec, &item->msec); ++ ++ item->page = page; ++ item->retry = index; ++ ++ item->ecc_err = IS_PS_UN_ECC(host) ? 1 : 0; ++ if (!item->ecc_err) ++ dbg_read_retry->retry[index]++; ++ ++ if (++dbg_read_retry->index >= CONFIG_HINFC610_DBG_READ_RETRY_NUM) ++ dbg_read_retry->index = 0; ++ ++exit: ++ mutex_unlock(&dbg_read_retry_mutex); ++} ++/*****************************************************************************/ ++ ++struct hinfc610_dbg_inf_t hinfc610_dbg_inf_read_retry = { ++ "read_retry", 0, ++ dbgfs_read_retry_init, ++ dbgfs_read_retry_uninit, ++ NULL, ++ NULL, ++ NULL, ++ hinfc610_dbg_read_retry_rr, ++}; ++/*****************************************************************************/ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_gen.c b/drivers/mtd/nand/hinfc610/hinfc610_gen.c +new file mode 100644 +index 0000000..2b43cf9 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_gen.c +@@ -0,0 +1,85 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "../match_table.h" ++#include "hinfc610_gen.h" ++ ++/*****************************************************************************/ ++ ++static struct match_reg_type page_type2reg[] = { ++ { ++ hinfc610_pagesize_2K, NAND_PAGE_2K, ++ }, { ++ hinfc610_pagesize_4K, NAND_PAGE_4K, ++ }, { ++ hinfc610_pagesize_8K, NAND_PAGE_8K, ++ }, { ++ hinfc610_pagesize_16K, NAND_PAGE_16K, ++ }, { ++ hinfc610_pagesize_32K, NAND_PAGE_32K, ++ } ++}; ++ ++enum hinfc610_page_reg hinfc610_page_type2reg(int type) ++{ ++ return type2reg(page_type2reg, ARRAY_SIZE(page_type2reg), type, 0); ++} ++ ++int hinfc610_page_reg2type(enum hinfc610_page_reg reg) ++{ ++ return reg2type(page_type2reg, ARRAY_SIZE(page_type2reg), reg, 0); ++} ++/*****************************************************************************/ ++ ++static struct match_reg_type ecc_type2reg[] = { ++ { ++ hinfc610_ecc_none, NAND_ECC_NONE, ++ }, { ++ hinfc610_ecc_8bit, NAND_ECC_8BIT, ++ }, { ++ hinfc610_ecc_13bit, NAND_ECC_13BIT, ++ }, { ++ hinfc610_ecc_18bit, NAND_ECC_18BIT, ++ }, { ++ hinfc610_ecc_24bit, NAND_ECC_24BIT, ++ }, { ++ hinfc610_ecc_27bit, NAND_ECC_27BIT, ++ }, { ++ hinfc610_ecc_32bit, NAND_ECC_32BIT, ++ }, { ++ hinfc610_ecc_41bit, NAND_ECC_41BIT, ++ }, { ++ hinfc610_ecc_48bit, NAND_ECC_48BIT, ++ }, { ++ hinfc610_ecc_60bit, NAND_ECC_60BIT, ++ }, { ++ hinfc610_ecc_72bit, NAND_ECC_72BIT, ++ }, { ++ hinfc610_ecc_80bit, NAND_ECC_80BIT, ++ } ++}; ++ ++enum hinfc610_ecc_reg hinfc610_ecc_type2reg(int type) ++{ ++ return type2reg(ecc_type2reg, ARRAY_SIZE(ecc_type2reg), type, 0); ++} ++ ++int hinfc610_ecc_reg2type(enum hinfc610_ecc_reg reg) ++{ ++ return reg2type(ecc_type2reg, ARRAY_SIZE(ecc_type2reg), reg, 0); ++} +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_gen.h b/drivers/mtd/nand/hinfc610/hinfc610_gen.h +new file mode 100644 +index 0000000..c41ff6f +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_gen.h +@@ -0,0 +1,57 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef HINFC610_GENH ++#define HINFC610_GENH ++/******************************************************************************/ ++ ++#include "../hinfc_gen.h" ++ ++enum hinfc610_ecc_reg { ++ hinfc610_ecc_none = 0x00, ++ hinfc610_ecc_8bit = 0x01, ++ hinfc610_ecc_13bit = 0x02, ++ hinfc610_ecc_18bit = 0x03, ++ hinfc610_ecc_24bit = 0x04, ++ hinfc610_ecc_27bit = 0x05, ++ hinfc610_ecc_32bit = 0x06, ++ hinfc610_ecc_41bit = 0x07, ++ hinfc610_ecc_48bit = 0x08, ++ hinfc610_ecc_60bit = 0x09, ++ hinfc610_ecc_72bit = 0x0a, ++ hinfc610_ecc_80bit = 0x0b, ++}; ++ ++enum hinfc610_page_reg { ++ hinfc610_pagesize_2K = 0x01, ++ hinfc610_pagesize_4K = 0x02, ++ hinfc610_pagesize_8K = 0x03, ++ hinfc610_pagesize_16K = 0x04, ++ hinfc610_pagesize_32K = 0x05, ++}; ++ ++enum hinfc610_page_reg hinfc610_page_type2reg(int type); ++ ++int hinfc610_page_reg2type(enum hinfc610_page_reg reg); ++ ++enum hinfc610_ecc_reg hinfc610_ecc_type2reg(int type); ++ ++int hinfc610_ecc_reg2type(enum hinfc610_ecc_reg reg); ++ ++/******************************************************************************/ ++#endif /* HINFC610_GENH */ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_os.c b/drivers/mtd/nand/hinfc610/hinfc610_os.c +new file mode 100644 +index 0000000..449ec93 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_os.c +@@ -0,0 +1,394 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++ ++#ifdef CONFIG_MTD_PARTITION_FROM_DTS ++/*****************************************************************************/ ++static inline int mtd_has_partitions(void) { return 1; } ++#else ++ ++/*****************************************************************************/ ++#define MAX_MTD_PARTITIONS (32) ++ ++struct partition_entry { ++ char name[16]; ++ unsigned long long start; ++ unsigned long long length; ++ unsigned int flags; ++}; ++ ++struct partition_info { ++ int parts_num; ++ struct partition_entry entry[MAX_MTD_PARTITIONS]; ++ struct mtd_partition parts[MAX_MTD_PARTITIONS]; ++}; ++ ++static struct partition_info ptn_info = {0}; ++ ++static int __init parse_nand_partitions(const struct tag *tag) ++{ ++ int i; ++ ++ if (tag->hdr.size <= 2) { ++ PR_BUG("tag->hdr.size <= 2\n"); ++ return 0; ++ } ++ ptn_info.parts_num = (tag->hdr.size - 2) ++ / (sizeof(struct partition_entry)/sizeof(int)); ++ memcpy(ptn_info.entry, ++ &tag->u, ++ ptn_info.parts_num * sizeof(struct partition_entry)); ++ ++ for (i = 0; i < ptn_info.parts_num; i++) { ++ ptn_info.parts[i].name = ptn_info.entry[i].name; ++ ptn_info.parts[i].size = (ptn_info.entry[i].length); ++ ptn_info.parts[i].offset = (ptn_info.entry[i].start); ++ ptn_info.parts[i].mask_flags = 0; ++ ptn_info.parts[i].ecclayout = 0; ++ } ++ ++ return 0; ++} ++ ++/* turn to ascii is "HiNp" */ ++__tagtable(0x48694E70, parse_nand_partitions); ++/*****************************************************************************/ ++static int hinfc_os_add_paratitions(struct hinfc_host *host) ++{ ++ int ix; ++ int nr_parts = 0; ++ struct mtd_partition *parts = NULL; ++ int ret; ++ ++#ifdef CONFIG_MTD_CMDLINE_PARTS ++ static const char * const part_probes[] = {"cmdlinepart", NULL, }; ++ ++ nr_parts = parse_mtd_partitions(host->mtd, part_probes, &parts, 0); ++#endif ++ ++ if (!nr_parts) { ++ nr_parts = ptn_info.parts_num; ++ parts = ptn_info.parts; ++ } ++ ++ if (nr_parts <= 0) ++ return 0; ++ ++ for (ix = 0; ix < nr_parts; ix++) { ++ DBG_MSG("partitions[%d] = {.name = %s, .offset = 0x%.8x,", ++ ix, parts[ix].name, ++ (unsigned int)parts[ix].offset); ++ DBG_MSG(".size = 0x%08x (%uKiB) }\n", ++ (unsigned int)parts[ix].size, ++ (unsigned int)parts[ix].size/1024); ++ } ++ ++ host->add_partition = 1; ++ ++ ret = mtd_device_register(host->mtd, parts, nr_parts); ++ ++ kfree(parts); ++ parts = NULL; ++ ++ return (1 == ret) ? -ENODEV : 0; ++} ++/*****************************************************************************/ ++#endif /* CONFIG_MTD_PARTITION_FROM_DTS */ ++ ++static unsigned int nand_otp_len; ++static unsigned char nand_otp[128] = {0}; ++ ++/* Get NAND parameter table. */ ++static int __init parse_nand_param(const struct tag *tag) ++{ ++ if (tag->hdr.size <= 2) ++ return 0; ++ ++ nand_otp_len = ((tag->hdr.size << 2) - sizeof(struct tag_header)); ++ ++ if (nand_otp_len > sizeof(nand_otp)) { ++ PR_BUG("tag->hdr.size <= 2\n"); ++ return 0; ++ } ++ memcpy(nand_otp, &tag->u, nand_otp_len); ++ return 0; ++} ++/* 0x48694E77 equal to fastoot ATAG_NAND_PARAM */ ++__tagtable(0x48694E77, parse_nand_param); ++/*****************************************************************************/ ++ ++static int hinfc610_nand_pre_probe(struct nand_chip *chip) ++{ ++ uint8_t nand_maf_id; ++ struct hinfc_host *host = chip->priv; ++ ++ /* Reset the chip first */ ++ host->send_cmd_reset(host, 0); ++ ++ /* Check the ID */ ++ host->offset = 0; ++ memset((unsigned char *)(chip->IO_ADDR_R), 0, 0x10); ++ host->send_cmd_readid(host); ++ nand_maf_id = readb(chip->IO_ADDR_R); ++ ++ if (nand_maf_id == 0x00 || nand_maf_id == 0xff) { ++ PR_BUG("\nCannot found a valid Nand Device\n"); ++ return 1; ++ } ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_os_probe(struct platform_device *pltdev) ++{ ++ int size; ++ int result = 0; ++ struct hinfc_host *host; ++ struct nand_chip *chip; ++ struct mtd_info *mtd; ++ struct resource *rs_reg, *rs_io = NULL; ++ struct device *dev = &pltdev->dev; ++ struct device_node *np = NULL; ++#ifdef CONFIG_MTD_PARTITION_FROM_DTS ++ struct mtd_partition *parts = NULL; ++ int nr_parts = 0; ++#endif ++ ++ size = sizeof(struct hinfc_host) + sizeof(struct nand_chip) ++ + sizeof(struct mtd_info); ++ host = kmalloc(size, GFP_KERNEL); ++ if (!host) { ++ PR_BUG("failed to allocate device structure.\n"); ++ return -ENOMEM; ++ } ++ memset((char *)host, 0, size); ++ platform_set_drvdata(pltdev, host); ++ ++ host->dev = dev; ++ host->chip = chip = (struct nand_chip *)&host[1]; ++ host->mtd = mtd = (struct mtd_info *)&chip[1]; ++ ++ host->clk = devm_clk_get(dev, NULL); ++ if (IS_ERR(host->clk)) ++ return PTR_ERR(host->clk); ++ ++ /* enable and set system clock */ ++ clk_prepare_enable(host->clk); ++ ++ rs_reg = platform_get_resource_byname(pltdev, IORESOURCE_MEM, ++ "control"); ++ host->iobase = devm_ioremap_resource(dev, rs_reg); ++ if (IS_ERR(host->iobase)) { ++ PR_BUG("Error: Can't get resource for reg address.\n"); ++ result = -EIO; ++ goto fail; ++ } ++ ++ np = of_get_next_available_child(dev->of_node, NULL); ++ ++ mtd->type = MTD_NANDFLASH; ++ mtd->priv = chip; ++ mtd->flags = MTD_CAP_NANDFLASH; ++ mtd->owner = THIS_MODULE; ++ mtd->name = np->name; ++ ++ rs_io = platform_get_resource_byname(pltdev, IORESOURCE_MEM, ++ "memory"); ++ chip->IO_ADDR_R = chip->IO_ADDR_W = devm_ioremap_resource(dev, rs_io); ++ if (IS_ERR(chip->IO_ADDR_R)) { ++ PR_BUG("Error: Can't get resource for buffer address.\n"); ++ result = -EIO; ++ goto fail; ++ } ++ ++ host->buffer = dma_alloc_coherent(host->dev, ++ (NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE), ++ &host->dma_buffer, GFP_KERNEL); ++ if (!host->buffer) { ++ PR_BUG("Can't malloc memory for NAND driver."); ++ result = -EIO; ++ goto fail; ++ } ++ ++ chip->priv = host; ++ host->chip = chip; ++ chip->cmd_ctrl = hinfc610_cmd_ctrl; ++ chip->dev_ready = hinfc610_dev_ready; ++ chip->select_chip = hinfc610_select_chip; ++ chip->read_byte = hinfc610_read_byte; ++ chip->read_word = hinfc610_read_word; ++ chip->write_buf = hinfc610_write_buf; ++ chip->read_buf = hinfc610_read_buf; ++ ++ chip->chip_delay = HINFC610_CHIP_DELAY; ++ chip->options = NAND_NO_AUTOINCR ++ | NAND_NEED_READRDY ++ | NAND_BROKEN_XD ++ | NAND_SKIP_BBTSCAN; ++ chip->ecc.layout = NULL; ++ chip->ecc.mode = NAND_ECC_NONE; ++ ++ if (hinfc610_nand_init(host, chip)) { ++ PR_BUG("failed to allocate device buffer.\n"); ++ result = -EIO; ++ goto fail; ++ } ++ ++ if (hinfc610_nand_pre_probe(chip)) { ++ result = -EXDEV; ++ goto fail; ++ } ++ ++ if (nand_otp_len) { ++ PR_MSG("Copy Nand read retry parameter from boot,"); ++ PR_MSG(" parameter length %d.\n", nand_otp_len); ++ memcpy(host->rr_data, nand_otp, nand_otp_len); ++ } ++ ++ if (nand_scan(mtd, CONFIG_HINFC610_MAX_CHIP)) { ++ result = -ENXIO; ++ goto fail; ++ } ++ ++#ifdef CONFIG_MTD_PARTITION_FROM_DTS ++ if (mtd_has_partitions()) { ++ static char const *part_probes[] = { ++ "cmdlinepart", ++ NULL, ++ }; ++ ++ nr_parts = parse_mtd_partitions(host->mtd, ++ part_probes, &parts, 0); ++ PR_MSG("parse mtd partitions: %d\n", nr_parts); ++ if (nr_parts > 0) ++ host->add_partition = 1; ++ } ++ ++ result = mtd_device_register(host->mtd, parts, nr_parts); ++ if (result) { ++ kfree(parts); ++ parts = NULL; ++ } ++ return (1 == result) ? -ENODEV : 0; ++#else ++ result = hinfc_os_add_paratitions(host); ++ if (host->add_partition) ++ return result; ++ ++ if (!add_mtd_device(host->mtd)) ++ return 0; ++#endif ++ result = -ENODEV; ++fail: ++ if (host->buffer) { ++ dma_free_coherent(host->dev, ++ (NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE), ++ host->buffer, ++ host->dma_buffer); ++ host->buffer = NULL; ++ } ++ nand_release(host->mtd); ++ kfree(host); ++ platform_set_drvdata(pltdev, NULL); ++ ++ return result; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_os_remove(struct platform_device *pltdev) ++{ ++ struct hinfc_host *host = platform_get_drvdata(pltdev); ++ ++ clk_disable_unprepare(host->clk); ++ ++ nand_release(host->mtd); ++ ++ dma_free_coherent(host->dev, ++ (NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE), ++ host->buffer, ++ host->dma_buffer); ++ kfree(host); ++ platform_set_drvdata(pltdev, NULL); ++ ++ return 0; ++} ++/*****************************************************************************/ ++#ifdef CONFIG_PM ++static int hinfc610_os_suspend(struct platform_device *pltdev, ++ pm_message_t state) ++{ ++ struct hinfc_host *host = platform_get_drvdata(pltdev); ++ ++ while ((hinfc_read(host, HINFC610_STATUS) & 0x1) == 0x0) ++ ; ++ ++ while ((hinfc_read(host, HINFC610_DMA_CTRL)) ++ & HINFC610_DMA_CTRL_DMA_START) ++ _cond_resched(); ++ ++ clk_disable_unprepare(host->clk); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_os_resume(struct platform_device *pltdev) ++{ ++ int cs; ++ struct hinfc_host *host = platform_get_drvdata(pltdev); ++ struct nand_chip *chip = host->chip; ++ ++ clk_prepare_enable(host->clk); ++ for (cs = 0; cs < chip->numchips; cs++) ++ host->send_cmd_reset(host, cs); ++ hinfc_write(host, ++ SET_HINFC610_PWIDTH(CONFIG_HINFC610_W_LATCH, ++ CONFIG_HINFC610_R_LATCH, CONFIG_HINFC610_RW_LATCH), ++ HINFC610_PWIDTH); ++ ++ return 0; ++} ++#endif /* CONFIG_PM */ ++/*****************************************************************************/ ++static const struct of_device_id hisi_nand_dt_ids[] = { ++ { .compatible = "hisilicon,hinfc610-nand" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, hisi_nand_dt_ids); ++ ++static struct platform_driver hisi_nand_driver = { ++ .driver = { ++ .name = "hisi-nand", ++ .of_match_table = hisi_nand_dt_ids, ++ }, ++ .probe = hinfc610_os_probe, ++ .remove = hinfc610_os_remove, ++#ifdef CONFIG_PM ++ .suspend = hinfc610_os_suspend, ++ .resume = hinfc610_os_resume, ++#endif ++}; ++module_platform_driver(hisi_nand_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("BVT_BSP"); ++MODULE_DESCRIPTION("Hisilicon Flash Memory Controller NFC610 Nand Driver"); +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_os.h b/drivers/mtd/nand/hinfc610/hinfc610_os.h +new file mode 100644 +index 0000000..1dafd9e +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_os.h +@@ -0,0 +1,78 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++ ++#ifndef HINFC610_OSH ++#define HINFC610_OSH ++/******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../../mtdcore.h" ++ ++/*****************************************************************************/ ++ ++#define DUMP_DATA(_p, _n) do { \ ++ int ix; \ ++ unsigned char *rr = (unsigned char *)(_p); \ ++ for (ix = 0; ix < _n; ix++) { \ ++ pr_info("%02X ", rr[ix]); \ ++ if (!((ix + 1) % 16)) \ ++ pr_info("\n"); \ ++ } \ ++} while (0) ++ ++#define DBG_OUT(fmt, args...)\ ++ pr_warn("%s(%d): " fmt, __FILE__, __LINE__, ##args) \ ++ ++#if 1 ++# define DBG_MSG(_fmt, arg...) ++#else ++# define DBG_MSG(_fmt, arg...) \ ++ pr_info("%s(%d): " _fmt, __FILE__, __LINE__, ##arg) ++#endif ++ ++#define PR_BUG(fmt, args...) do {\ ++ pr_debug("%s(%d): bug " fmt, __FILE__, __LINE__, ##args); \ ++ asm("b ."); \ ++} while (0) ++ ++#define PR_ERR(fmt, args...)\ ++ pr_err("%s(%d): " fmt, __FILE__, __LINE__, ##args) \ ++ ++#define PR_MSG(_fmt, arg...) \ ++ printk(_fmt, ##arg) ++ ++/******************************************************************************/ ++#endif /* HINFC610_OSH */ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_read_retry.c b/drivers/mtd/nand/hinfc610/hinfc610_read_retry.c +new file mode 100644 +index 0000000..3f1a9f2 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_read_retry.c +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hinfc610_gen.h" ++#include "hinfc610.h" ++#include "hinfc610_read_retry.h" ++ ++static struct read_retry_t *read_retry_table[] = { ++ &hinfc610_hynix_bg_bdie_read_retry, ++ &hinfc610_hynix_bg_cdie_read_retry, ++ &hinfc610_hynix_cg_adie_read_retry, ++ &hinfc610_micron_read_retry, ++ &hinfc610_toshiba_24nm_read_retry, ++ &hinfc610_samsung_read_retry, ++ NULL, ++}; ++ ++struct read_retry_t *hinfc610_find_read_retry(int type) ++{ ++ struct read_retry_t **rr; ++ ++ for (rr = read_retry_table; rr; rr++) { ++ if ((*rr)->type == type) ++ return *rr; ++ } ++ ++ return NULL; ++} +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_read_retry.h b/drivers/mtd/nand/hinfc610/hinfc610_read_retry.h +new file mode 100644 +index 0000000..cfd8880 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_read_retry.h +@@ -0,0 +1,25 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef HINFC610_READ_RETRY_H ++#define HINFC610_READ_RETRY_H ++ ++struct read_retry_t *hinfc610_find_read_retry(int type); ++ ++#endif /* HINFC610_READ_RETRY_H */ ++ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_read_retry_hynix_bg_bdie.c b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_hynix_bg_bdie.c +new file mode 100644 +index 0000000..b6fb1a8 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_hynix_bg_bdie.c +@@ -0,0 +1,136 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++ ++/*****************************************************************************/ ++ ++static int hynix_bg_bdie_rr_org_exist; ++static char hynix_bg_bdie_rr_org[4] = {0}; ++ ++/*****************************************************************************/ ++ ++static int hinfc610_hynix_bg_bdie_set_rr_reg(struct hinfc_host *host, int index) ++{ ++ int ix; ++ char HYNIX_BG_BDIE_RR_REG[4] = {0xA7, 0xAD, 0xAE, 0xAF}; ++ char value_offset[7][4] = { ++ {0x00, 0x00, 0x00, 0x00}, ++ {0x00, 0x06, 0x0A, 0x06}, ++ {0x7F, -0x03, -0x07, -0x08}, ++ {0x7F, -0x06, -0x0D, -0x0F}, ++ {0x7F, -0x09, -0x14, -0x17}, ++ {0x7F, 0x7F, -0x1A, -0x1E}, ++ {0x7F, 0x7F, -0x20, -0x25} ++ }; ++ char *value = &value_offset[index][0]; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ hinfc_write(host, 1, HINFC610_DATA_NUM); ++ ++ if (!hynix_bg_bdie_rr_org_exist) { ++ ++ for (ix = 0; ix < 4; ix++) { ++ ++ memset(host->chip->IO_ADDR_R, 0xff, 32); ++ ++ hinfc_write(host, 0x37, HINFC610_CMD); ++ hinfc_write(host, HYNIX_BG_BDIE_RR_REG[ix], ++ HINFC610_ADDRL); ++ /* ++ * according to hynix doc, no need to config ++ * HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, HINFC610_READ_1CMD_1ADD_DATA, ++ HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ hynix_bg_bdie_rr_org[ix] ++ = (char)(readl(host->chip->IO_ADDR_R) & 0xff); ++ } ++ hynix_bg_bdie_rr_org_exist = 1; ++ } ++ ++ for (ix = 0; ix < 4; ix++) { ++ if (value[ix] == 0x7F) ++ value[ix] = 0x00; ++ else ++ value[ix] += hynix_bg_bdie_rr_org[ix]; ++ } ++ ++ writel(value[0], host->chip->IO_ADDR_W); ++ hinfc_write(host, HYNIX_BG_BDIE_RR_REG[0], HINFC610_ADDRL); ++ hinfc_write(host, 0x36, HINFC610_CMD); ++ /* ++ * according to hynix doc, no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ for (ix = 1; ix < 4; ix++) { ++ writel(value[ix], host->chip->IO_ADDR_W); ++ hinfc_write(host, HYNIX_BG_BDIE_RR_REG[ix], HINFC610_ADDRL); ++ /* ++ * according to hynix doc, no need to config ++ * HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ } ++ ++ hinfc_write(host, 0x16, HINFC610_CMD); ++ /* ++ * according to hynix doc, only 1 cmd: 0x16. ++ * And no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, HINFC610_WRITE_1CMD_0ADD_NODATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_hynix_bg_bdie_set_rr_param(struct hinfc_host *host, ++ int param) ++{ ++ if (!param) ++ return 0; ++ return hinfc610_hynix_bg_bdie_set_rr_reg(host, param); ++} ++/*****************************************************************************/ ++ ++static int hinfc610_hynix_bg_bdie_reset_rr_param(struct hinfc_host *host) ++{ ++ return hinfc610_hynix_bg_bdie_set_rr_param(host, 0); ++} ++/*****************************************************************************/ ++ ++struct read_retry_t hinfc610_hynix_bg_bdie_read_retry = { ++ .type = NAND_RR_HYNIX_BG_BDIE, ++ .count = 7, ++ .set_rr_param = hinfc610_hynix_bg_bdie_set_rr_param, ++ .get_rr_param = NULL, ++ .reset_rr_param = hinfc610_hynix_bg_bdie_reset_rr_param, ++}; +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_read_retry_hynix_bg_cdie.c b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_hynix_bg_cdie.c +new file mode 100644 +index 0000000..fc39d70 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_hynix_bg_cdie.c +@@ -0,0 +1,225 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++ ++/*****************************************************************************/ ++ ++static char *hinfc610_hynix_bg_cdie_otp_check(char *otp) ++{ ++ int index = 0; ++ int ix, jx; ++ char *ptr = NULL; ++ int min, cur; ++ char *otp_origin, *otp_inverse; ++ ++ min = 64; ++ for (ix = 0; ix < 8; ix++, otp += 128) { ++ ++ otp_origin = otp; ++ otp_inverse = otp + 64; ++ cur = 0; ++ ++ for (jx = 0; jx < 64; jx++, otp_origin++, otp_inverse++) { ++ if (((*otp_origin) ^ (*otp_inverse)) == 0xFF) ++ continue; ++ cur++; ++ } ++ ++ if (cur < min) { ++ min = cur; ++ index = ix; ++ ptr = otp; ++ if (!cur) ++ break; ++ } ++ } ++ ++ pr_info("RR select parameter %d from %d, error %d\n", ++ index, ix, min); ++ return ptr; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_hynix_bg_cdie_get_rr_param(struct hinfc_host *host) ++{ ++ char *otp; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ /* step1: reset the chip */ ++ host->send_cmd_reset(host, host->chipselect); ++ ++ /* step2: cmd: 0x36, address: 0xAE, data: 0x00 */ ++ hinfc_write(host, 1, HINFC610_DATA_NUM);/* data length 1 */ ++ writel(0x00, host->chip->IO_ADDR_R); /* data: 0x00 */ ++ hinfc_write(host, 0xAE, HINFC610_ADDRL);/* address: 0xAE */ ++ hinfc_write(host, 0x36, HINFC610_CMD); /* cmd: 0x36 */ ++ /* according to hynix doc, no need to config ++ * HINFC610_OP_WAIT_READY_EN */ ++ hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /* step3: address: 0xB0, data: 0x4D */ ++ hinfc_write(host, 1, HINFC610_DATA_NUM);/* data length 1 */ ++ writel(0x4D, host->chip->IO_ADDR_R); /* data: 0x4d */ ++ hinfc_write(host, 0xB0, HINFC610_ADDRL);/* address: 0xB0 */ ++ /* only address and data, without cmd */ ++ /* according to hynix doc, no need to config ++ * HINFC610_OP_WAIT_READY_EN */ ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /* step4: cmd: 0x16, 0x17, 0x04, 0x19 */ ++ hinfc_write(host, 0x17 << 8 | 0x16, HINFC610_CMD); ++ /* according to hynix doc, no need to config ++ * HINFC610_OP_WAIT_READY_EN */ ++ hinfc_write(host, HINFC610_WRITE_2CMD_0ADD_NODATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ hinfc_write(host, 0x19 << 8 | 0x04, HINFC610_CMD); ++ /* according to hynix doc, no need to config ++ * HINFC610_OP_WAIT_READY_EN */ ++ hinfc_write(host, HINFC610_WRITE_2CMD_0ADD_NODATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /* step5: cmd: 0x00 0x30, address: 0x02 00 00 00 */ ++ hinfc_write(host, 0x2000000, HINFC610_ADDRL); ++ hinfc_write(host, 0x00, HINFC610_ADDRH); ++ hinfc_write(host, 0x30 << 8 | 0x00, HINFC610_CMD); ++ hinfc_write(host, 0x800, HINFC610_DATA_NUM); ++ /* according to hynix doc, need to config ++ * HINFC610_OP_WAIT_READY_EN */ ++ hinfc_write(host, HINFC610_READ_2CMD_5ADD, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /*step6 save otp read retry table to mem*/ ++ otp = hinfc610_hynix_bg_cdie_otp_check(host->chip->IO_ADDR_R + 2); ++ if (!otp) { ++ pr_err("Read Retry select parameter failed, this Nand Chip maybe invalidation.\n"); ++ return -1; ++ } ++ memcpy(host->rr_data, otp, 64); ++ host->need_rr_data = 1; ++ ++ /* step7: reset the chip */ ++ host->send_cmd_reset(host, host->chipselect); ++ ++ /* step8: cmd: 0x38 */ ++ hinfc_write(host, 0x38, HINFC610_CMD); ++ /* according to hynix doc, need to config HINFC610_OP_WAIT_READY_EN */ ++ hinfc_write(host, HINFC610_WRITE_1CMD_0ADD_NODATA_WAIT_READY, ++ HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ /* get hynix otp table finish */ ++ return 0; ++} ++/*****************************************************************************/ ++static char hinfc610_hynix_bg_cdie_rr_reg[8] = { ++ 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7}; ++ ++static int hinfc610_hynix_bg_cdie_set_rr_reg(struct hinfc_host *host, ++ char *val) ++{ ++ int i; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ hinfc_write(host, 1, HINFC610_DATA_NUM);/* data length 1 */ ++ ++ for (i = 0; i <= 8; i++) { ++ switch (i) { ++ case 0: ++ writel(val[i], host->chip->IO_ADDR_R); ++ hinfc_write(host, ++ hinfc610_hynix_bg_cdie_rr_reg[i], ++ HINFC610_ADDRL); ++ hinfc_write(host, ++ 0x36, HINFC610_CMD); ++ /* ++ * no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, ++ HINFC610_WRITE_1CMD_1ADD_DATA, ++ HINFC610_OP); ++ break; ++ case 8: ++ hinfc_write(host, ++ 0x16, HINFC610_CMD); ++ /* ++ * according to hynix doc, only 1 cmd: 0x16. ++ * And no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, ++ HINFC610_WRITE_1CMD_0ADD_NODATA, ++ HINFC610_OP); ++ break; ++ default: ++ writel(val[i], host->chip->IO_ADDR_R); ++ hinfc_write(host, ++ hinfc610_hynix_bg_cdie_rr_reg[i], ++ HINFC610_ADDRL); ++ /* ++ * no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, ++ HINFC610_WRITE_0CMD_1ADD_DATA, ++ HINFC610_OP); ++ break; ++ } ++ WAIT_CONTROLLER_FINISH(); ++ } ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ return 0; ++} ++ ++/*****************************************************************************/ ++ ++static int hinfc610_hynix_bg_cdie_set_rr_param(struct hinfc_host *host, ++ int param) ++{ ++ unsigned char *rr; ++ ++ if (!(host->rr_data[0] | host->rr_data[1] ++ | host->rr_data[2] | host->rr_data[3]) || !param) ++ return -1; ++ ++ rr = (unsigned char *)&host->rr_data[((param & 0x07) << 3)]; ++ ++ /* set the read retry regs to adjust reading level */ ++ return hinfc610_hynix_bg_cdie_set_rr_reg(host, (char *)rr); ++} ++/*****************************************************************************/ ++ ++static int hinfc610_hynix_bg_cdie_reset_rr_param(struct hinfc_host *host) ++{ ++ return hinfc610_hynix_bg_cdie_set_rr_param(host, 0); ++} ++/*****************************************************************************/ ++ ++struct read_retry_t hinfc610_hynix_bg_cdie_read_retry = { ++ .type = NAND_RR_HYNIX_BG_CDIE, ++ .count = 8, ++ .set_rr_param = hinfc610_hynix_bg_cdie_set_rr_param, ++ .get_rr_param = hinfc610_hynix_bg_cdie_get_rr_param, ++ .reset_rr_param = hinfc610_hynix_bg_cdie_reset_rr_param, ++}; +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_read_retry_hynix_cg_adie.c b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_hynix_cg_adie.c +new file mode 100644 +index 0000000..b7444b8 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_hynix_cg_adie.c +@@ -0,0 +1,234 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++ ++/*****************************************************************************/ ++static char *hinfc610_hynix_cg_adie_otp_check(char *otp) ++{ ++ int index = 0; ++ int ix, jx; ++ char *ptr = NULL; ++ int min, cur; ++ char *otp_origin, *otp_inverse; ++ ++ min = 64; ++ for (ix = 0; ix < 8; ix++, otp += 128) { ++ ++ otp_origin = otp; ++ otp_inverse = otp + 64; ++ cur = 0; ++ ++ for (jx = 0; jx < 64; jx++, otp_origin++, otp_inverse++) { ++ if (((*otp_origin) ^ (*otp_inverse)) == 0xFF) ++ continue; ++ cur++; ++ } ++ ++ if (cur < min) { ++ min = cur; ++ index = ix; ++ ptr = otp; ++ if (!cur) ++ break; ++ } ++ } ++ ++ pr_info("RR select parameter %d from %d, error %d\n", ++ index, ix, min); ++ return ptr; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_hynix_cg_adie_get_rr_param(struct hinfc_host *host) ++{ ++ char *otp; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ /* step1: reset the chip */ ++ host->send_cmd_reset(host, host->chipselect); ++ ++ /* step2: cmd: 0x36, address: 0xFF, data: 0x40 */ ++ hinfc_write(host, 1, HINFC610_DATA_NUM);/* data length 1 */ ++ writel(0x40, host->chip->IO_ADDR_R); /* data: 0x00 */ ++ hinfc_write(host, 0xFF, HINFC610_ADDRL);/* address: 0xAE */ ++ hinfc_write(host, 0x36, HINFC610_CMD); /* cmd: 0x36 */ ++ /* ++ * no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /* step3: address: 0xCC, data: 0x4D */ ++ hinfc_write(host, 1, HINFC610_DATA_NUM);/* data length 1 */ ++ writel(0x4D, host->chip->IO_ADDR_R); /* data: 0x4d */ ++ hinfc_write(host, 0xCC, HINFC610_ADDRL);/* address: 0xB0 */ ++ /* ++ * no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ * only address and data, without cmd ++ */ ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /* step4: cmd: 0x16, 0x17, 0x04, 0x19 */ ++ hinfc_write(host, 0x17 << 8 | 0x16, HINFC610_CMD); ++ /* ++ * no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, HINFC610_WRITE_2CMD_0ADD_NODATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ hinfc_write(host, 0x19 << 8 | 0x04, HINFC610_CMD); ++ /* ++ * no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, HINFC610_WRITE_2CMD_0ADD_NODATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /* step5: cmd: 0x00 0x30, address: 0x02 00 00 00 */ ++ hinfc_write(host, 0x2000000, HINFC610_ADDRL); ++ hinfc_write(host, 0x00, HINFC610_ADDRH); ++ hinfc_write(host, 0x30 << 8 | 0x00, HINFC610_CMD); ++ hinfc_write(host, 0x800, HINFC610_DATA_NUM); ++ /* ++ * need to config HINFC610_OP_WAIT_READY_EN, here config this bit. ++ */ ++ hinfc_write(host, HINFC610_READ_2CMD_5ADD, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /*step6 save otp read retry table to mem*/ ++ otp = hinfc610_hynix_cg_adie_otp_check(host->chip->IO_ADDR_R + 2); ++ if (!otp) { ++ pr_err("Read Retry select parameter failed, this Nand Chip maybe invalidation.\n"); ++ return -1; ++ } ++ memcpy(host->rr_data, otp, 64); ++ host->need_rr_data = 1; ++ ++ /* step7: reset the chip */ ++ host->send_cmd_reset(host, host->chipselect); ++ ++ /* step8: cmd: 0x38 */ ++ hinfc_write(host, 0x38, HINFC610_CMD); ++ /* ++ * need to config HINFC610_OP_WAIT_READY_EN, here config this bit. ++ */ ++ hinfc_write(host, HINFC610_WRITE_1CMD_0ADD_NODATA_WAIT_READY, ++ HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ /* get hynix otp table finish */ ++ return 0; ++} ++/*****************************************************************************/ ++static char hinfc610_hynix_cg_adie__rr_reg[8] = { ++ 0xCC, 0xBF, 0xAA, 0xAB, 0xCD, 0xAD, 0xAE, 0xAF}; ++ ++static int hinfc610_hynix_cg_adie_set_rr_reg(struct hinfc_host *host, char *val) ++{ ++ int i; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ hinfc_write(host, 1, HINFC610_DATA_NUM);/* data length 1 */ ++ ++ for (i = 0; i <= 8; i++) { ++ switch (i) { ++ case 0: ++ writel(val[i], host->chip->IO_ADDR_R); ++ hinfc_write(host, ++ hinfc610_hynix_cg_adie__rr_reg[i], ++ HINFC610_ADDRL); ++ hinfc_write(host, ++ 0x36, HINFC610_CMD); ++ /* ++ * no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, ++ HINFC610_WRITE_1CMD_1ADD_DATA, ++ HINFC610_OP); ++ break; ++ case 8: ++ hinfc_write(host, ++ 0x16, HINFC610_CMD); ++ /* ++ * only have 1 cmd: 0x16 ++ * no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, ++ HINFC610_WRITE_1CMD_0ADD_NODATA, ++ HINFC610_OP); ++ break; ++ default: ++ writel(val[i], host->chip->IO_ADDR_R); ++ hinfc_write(host, ++ hinfc610_hynix_cg_adie__rr_reg[i], ++ HINFC610_ADDRL); ++ /* ++ * no need to config HINFC610_OP_WAIT_READY_EN, ++ * here not config this bit. ++ */ ++ hinfc_write(host, ++ HINFC610_WRITE_0CMD_1ADD_DATA, ++ HINFC610_OP); ++ break; ++ } ++ WAIT_CONTROLLER_FINISH(); ++ } ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ return 0; ++} ++ ++/*****************************************************************************/ ++ ++static int hinfc610_hynix_cg_adie_set_rr_param(struct hinfc_host *host, ++ int param) ++{ ++ unsigned char *rr; ++ ++ if (!(host->rr_data[0] | host->rr_data[1] ++ | host->rr_data[2] | host->rr_data[3]) || !param) ++ return -1; ++ ++ rr = (unsigned char *)&host->rr_data[((param & 0x07) << 3)]; ++ ++ /* set the read retry regs to adjust reading level */ ++ return hinfc610_hynix_cg_adie_set_rr_reg(host, (char *)rr); ++} ++/*****************************************************************************/ ++ ++static int hinfc610_hynix_cg_adie_reset_rr_param(struct hinfc_host *host) ++{ ++ return hinfc610_hynix_cg_adie_set_rr_param(host, 0); ++} ++/*****************************************************************************/ ++ ++struct read_retry_t hinfc610_hynix_cg_adie_read_retry = { ++ .type = NAND_RR_HYNIX_CG_ADIE, ++ .count = 8, ++ .set_rr_param = hinfc610_hynix_cg_adie_set_rr_param, ++ .get_rr_param = hinfc610_hynix_cg_adie_get_rr_param, ++ .reset_rr_param = hinfc610_hynix_cg_adie_reset_rr_param, ++}; +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_read_retry_micron.c b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_micron.c +new file mode 100644 +index 0000000..c4c0716 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_micron.c +@@ -0,0 +1,74 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++ ++/*****************************************************************************/ ++ ++#define MICRON_RR_ADDR 0x89 ++ ++static int hinfc610_micron_set_rr_reg(struct hinfc_host *host, int rr) ++{ ++ int regval; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, 1, HINFC610_DATA_NUM); ++ ++ writel(rr, host->chip->IO_ADDR_W); ++ hinfc_write(host, MICRON_RR_ADDR, HINFC610_ADDRL); ++ /* set read retry */ ++ hinfc_write(host, 0xEF, HINFC610_CMD); ++ ++ /* need to config WAIT_READY_EN, here config WAIT_READY_EN bit. */ ++ regval = (HINFC610_IS_SYNC(host) ? ++ HINFC610_WRITE_1CMD_1ADD_DATA_SYNC_WAIT_READY : ++ HINFC610_WRITE_1CMD_1ADD_DATA_WAIT_READY); ++ ++ hinfc_write(host, regval, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ return 0; ++} ++/*****************************************************************************/ ++#undef MICRON_RR_ADDR ++/*****************************************************************************/ ++ ++static int hinfc610_micron_set_rr_param(struct hinfc_host *host, int rr_option) ++{ ++ return hinfc610_micron_set_rr_reg(host, rr_option); ++} ++/*****************************************************************************/ ++ ++static int hinfc610_micron_reset_rr_param(struct hinfc_host *host) ++{ ++ return hinfc610_micron_set_rr_reg(host, 0); ++} ++/*****************************************************************************/ ++ ++struct read_retry_t hinfc610_micron_read_retry = { ++ .type = NAND_RR_MICRON, ++ .count = 8, ++ .set_rr_param = hinfc610_micron_set_rr_param, ++ .get_rr_param = NULL, ++ .reset_rr_param = hinfc610_micron_reset_rr_param, ++}; +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_read_retry_samsung.c b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_samsung.c +new file mode 100644 +index 0000000..6d9adcb +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_samsung.c +@@ -0,0 +1,109 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++ ++/*****************************************************************************/ ++ ++static int hinfc610_samsung_set_rr_reg(struct hinfc_host *host, int param) ++{ ++#define SAMSUNG_RR_CMD 0xA1 ++ int opval; ++ ++ unsigned char samsung_rr_params[15][4] = { ++ {0x00, 0x00, 0x00, 0x00}, ++ {0x05, 0x0A, 0x00, 0x00}, ++ {0x28, 0x00, 0xEC, 0xD8}, ++ {0xED, 0xF5, 0xED, 0xE6}, ++ {0x0A, 0x0F, 0x05, 0x00}, ++ {0x0F, 0x0A, 0xFB, 0xEC}, ++ {0xE8, 0xEF, 0xE8, 0xDC}, ++ {0xF1, 0xFB, 0xFE, 0xF0}, ++ {0x0A, 0x00, 0xFB, 0xEC}, ++ {0xD0, 0xE2, 0xD0, 0xC2}, ++ {0x14, 0x0F, 0xFB, 0xEC}, ++ {0xE8, 0xFB, 0xE8, 0xDC}, ++ {0x1E, 0x14, 0xFB, 0xEC}, ++ {0xFB, 0xFF, 0xFB, 0xF8}, ++ {0x07, 0x0C, 0x02, 0x00} ++ }; ++ ++ if (param >= 15) ++ param = (param % 15); ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ /* no need to config WAIT_READY_EN, here not config WAIT_READY_EN bit */ ++ opval = (HINFC610_IS_SYNC(host) ? HINFC610_WRITE_1CMD_2ADD_DATA_SYNC ++ : HINFC610_WRITE_1CMD_2ADD_DATA); ++ ++ hinfc_write(host, 1, HINFC610_DATA_NUM); ++ ++ writel(samsung_rr_params[param][0], host->chip->IO_ADDR_R); ++ hinfc_write(host, 0xA700, HINFC610_ADDRL); ++ hinfc_write(host, SAMSUNG_RR_CMD, HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(samsung_rr_params[param][1], host->chip->IO_ADDR_R); ++ hinfc_write(host, 0xA400, HINFC610_ADDRL); ++ hinfc_write(host, SAMSUNG_RR_CMD, HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(samsung_rr_params[param][2], host->chip->IO_ADDR_R); ++ hinfc_write(host, 0xA500, HINFC610_ADDRL); ++ hinfc_write(host, SAMSUNG_RR_CMD, HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(samsung_rr_params[param][3], host->chip->IO_ADDR_R); ++ hinfc_write(host, 0xA600, HINFC610_ADDRL); ++ hinfc_write(host, SAMSUNG_RR_CMD, HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ return 0; ++ ++#undef SAMSUNG_RR_CMD ++} ++/*****************************************************************************/ ++ ++static int hinfc610_samsung_set_rr_param(struct hinfc_host *host, int param) ++{ ++ return hinfc610_samsung_set_rr_reg(host, param); ++} ++/*****************************************************************************/ ++ ++static int hinfc610_samsung_reset_rr_param(struct hinfc_host *host) ++{ ++ return hinfc610_samsung_set_rr_reg(host, 0); ++} ++/*****************************************************************************/ ++ ++struct read_retry_t hinfc610_samsung_read_retry = { ++ .type = NAND_RR_SAMSUNG, ++ .count = 15, ++ .set_rr_param = hinfc610_samsung_set_rr_param, ++ .get_rr_param = NULL, ++ .reset_rr_param = hinfc610_samsung_reset_rr_param, ++}; ++ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_read_retry_toshiba.c b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_toshiba.c +new file mode 100644 +index 0000000..0a1a87e +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_read_retry_toshiba.c +@@ -0,0 +1,113 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++ ++/*****************************************************************************/ ++ ++static int hinfc610_toshiba_24nm_set_rr_reg(struct hinfc_host *host, int param) ++{ ++#define TOSHIBA_RR_CMD 0x55 ++ int opval; ++ static char toshiba_rr_param[] = {0x00, 0x04, 0x7c, 0x78, 0x74, 0x08}; ++ ++ if (!param) { ++ host->send_cmd_reset(host, host->chipselect); ++ return 0; ++ } ++ ++ if (param >= 6) ++ param = (param % 6); ++ ++ /* ++ * no need to config WAIT_READY_EN, here not config WAIT_READY_EN ++ */ ++ opval = (HINFC610_IS_SYNC(host) ? HINFC610_WRITE_1CMD_1ADD_DATA_SYNC ++ : HINFC610_WRITE_1CMD_1ADD_DATA); ++ ++ hinfc_write(host, 1, HINFC610_DATA_NUM); ++ ++ writel(toshiba_rr_param[param], host->chip->IO_ADDR_R); ++ hinfc_write(host, 0x4, HINFC610_ADDRL); ++ hinfc_write(host, TOSHIBA_RR_CMD, HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(toshiba_rr_param[param], host->chip->IO_ADDR_R); ++ hinfc_write(host, 0x5, HINFC610_ADDRL); ++ hinfc_write(host, TOSHIBA_RR_CMD, HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(toshiba_rr_param[param], host->chip->IO_ADDR_R); ++ hinfc_write(host, 0x6, HINFC610_ADDRL); ++ hinfc_write(host, TOSHIBA_RR_CMD, HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(toshiba_rr_param[param], host->chip->IO_ADDR_R); ++ hinfc_write(host, 0x7, HINFC610_ADDRL); ++ hinfc_write(host, TOSHIBA_RR_CMD, HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ return 0; ++ ++#undef TOSHIBA_RR_CMD ++} ++/*****************************************************************************/ ++ ++static int hinfc610_toshiba_24nm_set_rr_param(struct hinfc_host *host, ++ int param) ++{ ++ int opval; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ opval = (HINFC610_IS_SYNC(host) ? HINFC610_WRITE_2CMD_0ADD_NODATA_SYNC ++ : HINFC610_WRITE_2CMD_0ADD_NODATA); ++ ++ hinfc_write(host, HINFC_CMD_SEQ(0x5C, 0xC5), HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ hinfc610_toshiba_24nm_set_rr_reg(host, param); ++ ++ hinfc_write(host, HINFC_CMD_SEQ(0x26, 0x5D), HINFC610_CMD); ++ hinfc_write(host, opval, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_toshiba_24nm_reset_rr_param(struct hinfc_host *host) ++{ ++ return hinfc610_toshiba_24nm_set_rr_reg(host, 0); ++} ++/*****************************************************************************/ ++struct read_retry_t hinfc610_toshiba_24nm_read_retry = { ++ .type = NAND_RR_TOSHIBA_24nm, ++ .count = 6, ++ .set_rr_param = hinfc610_toshiba_24nm_set_rr_param, ++ .get_rr_param = NULL, ++ .reset_rr_param = hinfc610_toshiba_24nm_reset_rr_param, ++}; +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_sync.c b/drivers/mtd/nand/hinfc610/hinfc610_sync.c +new file mode 100644 +index 0000000..c389d98 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_sync.c +@@ -0,0 +1,187 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "hinfc610_os.h" ++#include "hinfc610_gen.h" ++#include "hinfc610.h" ++#include "hinfc610_sync.h" ++ ++static struct nand_sync *nand_sync_table[] = { ++ &hinfc610_sync_onfi_23, ++ &hinfc610_sync_onfi_30, ++ &hinfc610_sync_toggle_10, ++ NULL, ++}; ++ ++static struct nand_sync *hinfc610_find_sync_type(int type) ++{ ++ struct nand_sync **sync; ++ ++ for (sync = nand_sync_table; sync; sync++) { ++ if ((*sync)->type == type) ++ return *sync; ++ } ++ ++ return NULL; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_onfi_support_sync(struct hinfc_host *host) ++{ ++ char buf[6] = {0}; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, sizeof(buf), HINFC610_DATA_NUM); ++ hinfc_write(host, NAND_CMD_READID, HINFC610_CMD); ++ hinfc_write(host, 0x20, HINFC610_ADDRL); ++ hinfc_write(host, HINFC610_READ_1CMD_1ADD_DATA, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ memcpy(buf, host->chip->IO_ADDR_R, sizeof(buf)); ++ ++ if (memcmp(buf, "ONFI", 4)) ++ return 0; ++ ++ hinfc_write(host, sizeof(buf), HINFC610_DATA_NUM); ++ hinfc_write(host, NAND_CMD_READID, HINFC610_CMD); ++ hinfc_write(host, 0x40, HINFC610_ADDRL); ++ hinfc_write(host, HINFC610_READ_1CMD_1ADD_DATA, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ memcpy(buf, host->chip->IO_ADDR_R, sizeof(buf)); ++ ++ if (memcmp(buf, "JEDEC", 5)) ++ return 0; ++ ++ return (buf[5] == 0x05); ++} ++/*****************************************************************************/ ++ ++static int hinfc610_get_onfi_info(struct hinfc_host *host, int *type) ++{ ++ char buf[6] = {0}; ++ ++ *type = 0; ++ ++ if (!hinfc610_onfi_support_sync(host)) ++ return 0; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, sizeof(buf), HINFC610_DATA_NUM); ++ hinfc_write(host, NAND_CMD_PARAM, HINFC610_CMD); ++ hinfc_write(host, 0x00, HINFC610_ADDRL); ++ hinfc_write(host, HINFC610_READ_1CMD_1ADD_DATA, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ memcpy(buf, host->chip->IO_ADDR_R, sizeof(buf)); ++ ++ if (memcmp(buf, "ONFI", 4)) ++ return 0; ++ ++ if (buf[4] & (1 << 6)) ++ *type = NAND_TYPE_ONFI_30; ++ else if (buf[4] & (1 << 5) || ++ buf[4] & (1 << 4) || ++ buf[4] & (1 << 3) || ++ buf[4] & (1 << 2)) ++ *type = NAND_TYPE_ONFI_23; ++ ++ return 1; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_toggle_support_sync(struct hinfc_host *host) ++{ ++ char buf[6] = {0}; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, sizeof(buf), HINFC610_DATA_NUM); ++ hinfc_write(host, NAND_CMD_READID, HINFC610_CMD); ++ hinfc_write(host, 0x40, HINFC610_ADDRL); ++ hinfc_write(host, HINFC610_READ_1CMD_1ADD_DATA, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ ++ memcpy(buf, host->chip->IO_ADDR_R, sizeof(buf)); ++ ++ if (memcmp(buf, "JEDEC", 5)) ++ return 0; ++ ++ return 1; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_get_toggle_info(struct hinfc_host *host, int *type) ++{ ++ char buf[8] = {0}; ++ ++ *type = 0; ++ ++ if (!hinfc610_toggle_support_sync(host)) ++ return 0; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, sizeof(buf), HINFC610_DATA_NUM); ++ hinfc_write(host, NAND_CMD_PARAM, HINFC610_CMD); ++ hinfc_write(host, 0x40, HINFC610_ADDRL); ++ hinfc_write(host, HINFC610_READ_1CMD_1ADD_DATA, HINFC610_OP); ++ ++ WAIT_CONTROLLER_FINISH(); ++ ++ memcpy(buf, host->chip->IO_ADDR_R, sizeof(buf)); ++ ++ if (memcmp(buf, "JESD", 4)) ++ return 0; ++ ++ if (buf[4] & (1 << 1)) ++ /* supports revision 1.0 */ ++ *type = NAND_TYPE_TOGGLE_10; ++ else ++ pr_warn("sync NAND has unknown toggle revision.\n"); ++ ++ return 1; ++} ++/*****************************************************************************/ ++ ++int hinfc610_get_sync_info(struct hinfc_host *host) ++{ ++ int type = 0; ++ ++ if (IS_NAND_ONFI(host)) ++ hinfc610_get_onfi_info(host, &type); ++ else ++ hinfc610_get_toggle_info(host, &type); ++ ++ if (!type) { ++ host->flags &= ~NAND_MODE_SYNC_ASYNC; ++ return 0; ++ } ++ ++ host->sync = hinfc610_find_sync_type(type); ++ if (!host->sync) ++ PR_BUG(ERSTR_DRIVER ++ "This Nand Flash need to enable the 'synchronous' feature. " ++ "but the driver dose not offer the feature"); ++ ++ return 0; ++} ++/*****************************************************************************/ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_sync.h b/drivers/mtd/nand/hinfc610/hinfc610_sync.h +new file mode 100644 +index 0000000..906fd10 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_sync.h +@@ -0,0 +1,25 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef HINFC610_SYNC_H ++#define HINFC610_SYNC_H ++ ++int hinfc610_get_sync_info(struct hinfc_host *host); ++ ++#endif /* HINFC610_SYNC_H */ ++ +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_sync_onfi_23.c b/drivers/mtd/nand/hinfc610/hinfc610_sync_onfi_23.c +new file mode 100644 +index 0000000..8fba306 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_sync_onfi_23.c +@@ -0,0 +1,107 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++ ++/*****************************************************************************/ ++ ++static int hinfc610_onfi_enable_sync(struct nand_chip *chip) ++{ ++ struct hinfc_host *host = chip->priv; ++ unsigned char micron_sync_param[4] = { ++ 0x14, /* set sync mode timing */ 0x00, 0x00, 0x00, ++ }; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, 1, HINFC610_DATA_NUM); ++ hinfc_write(host, 0xEF, HINFC610_CMD); ++ hinfc_write(host, 0x01, HINFC610_ADDRL); ++ writel(micron_sync_param[0], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(micron_sync_param[1], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(micron_sync_param[2], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /* need to config WAIT_READY_EN, here config this bit. */ ++ writel(micron_sync_param[3], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_WAIT_READY, ++ HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++ ++static int hinfc610_onfi_disable_sync(struct nand_chip *chip) ++{ ++ struct hinfc_host *host = chip->priv; ++ unsigned char micron_sync_param[4] = { ++ 0x00, 0x00, 0x00, 0x00, ++ }; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, 1, HINFC610_DATA_NUM); ++ hinfc_write(host, 0xEF, HINFC610_CMD); ++ hinfc_write(host, 0x01, HINFC610_ADDRL); ++ writel(micron_sync_param[0], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA_SYNC, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(micron_sync_param[1], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_SYNC, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(micron_sync_param[2], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_SYNC, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(micron_sync_param[3], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_SYNC_WAIT_READY, ++ HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++struct nand_sync hinfc610_sync_onfi_23 = { ++ .type = NAND_TYPE_ONFI_23, ++ .enable = hinfc610_onfi_enable_sync, ++ .disable = hinfc610_onfi_disable_sync, ++}; ++ ++struct nand_sync hinfc610_sync_onfi_30 = { ++ .type = NAND_TYPE_ONFI_30, ++ .enable = hinfc610_onfi_enable_sync, ++ .disable = hinfc610_onfi_disable_sync, ++}; +diff --git a/drivers/mtd/nand/hinfc610/hinfc610_sync_toggle.c b/drivers/mtd/nand/hinfc610/hinfc610_sync_toggle.c +new file mode 100644 +index 0000000..918b210 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc610_sync_toggle.c +@@ -0,0 +1,101 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include "hinfc610_os.h" ++#include "hinfc610.h" ++ ++/*****************************************************************************/ ++ ++static int hinfc610_toggle_enable_sync(struct nand_chip *chip) ++{ ++ struct hinfc_host *host = chip->priv; ++ unsigned char toshiba_sync_param[4] = { ++ 0x00, 0x00, 0x00, 0x00, ++ }; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, 1, HINFC610_DATA_NUM); ++ hinfc_write(host, 0xEF, HINFC610_CMD); ++ hinfc_write(host, 0x80, HINFC610_ADDRL); ++ writel(toshiba_sync_param[0], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(toshiba_sync_param[1], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(toshiba_sync_param[2], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /* need to config WAIT_READY_EN. */ ++ writel(toshiba_sync_param[3], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_WAIT_READY, ++ HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++static int hinfc610_toggle_disable_sync(struct nand_chip *chip) ++{ ++ struct hinfc_host *host = chip->priv; ++ unsigned char toshiba_sync_param[4] = { ++ 0x01, 0x00, 0x00, 0x00, ++ }; ++ ++ host->enable_ecc_randomizer(host, DISABLE, DISABLE); ++ ++ hinfc_write(host, 1, HINFC610_DATA_NUM); ++ hinfc_write(host, 0xEF, HINFC610_CMD); ++ hinfc_write(host, 0x80, HINFC610_ADDRL); ++ writel(toshiba_sync_param[0], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA_SYNC, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(toshiba_sync_param[1], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_SYNC, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ writel(toshiba_sync_param[2], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_SYNC, HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ /* need to config WAIT_READY_EN */ ++ writel(toshiba_sync_param[3], host->chip->IO_ADDR_R); ++ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_SYNC_WAIT_READY, ++ HINFC610_OP); ++ WAIT_CONTROLLER_FINISH(); ++ ++ host->enable_ecc_randomizer(host, ENABLE, ENABLE); ++ ++ return 0; ++} ++/*****************************************************************************/ ++ ++struct nand_sync hinfc610_sync_toggle_10 = { ++ .type = NAND_TYPE_TOGGLE_10, ++ .enable = hinfc610_toggle_enable_sync, ++ .disable = hinfc610_toggle_disable_sync, ++}; +diff --git a/drivers/mtd/nand/hinfc610/hinfc620_gen.c b/drivers/mtd/nand/hinfc610/hinfc620_gen.c +new file mode 100644 +index 0000000..a1e68f8 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc620_gen.c +@@ -0,0 +1,78 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include "../match_table.h" ++#include "hinfc620_gen.h" ++ ++/*****************************************************************************/ ++ ++static struct match_reg_type page_type2reg[] = { ++ { ++ hinfc620_pagesize_2K, NAND_PAGE_2K, ++ }, { ++ hinfc620_pagesize_4K, NAND_PAGE_4K, ++ }, { ++ hinfc620_pagesize_8K, NAND_PAGE_8K, ++ }, { ++ hinfc620_pagesize_16K, NAND_PAGE_16K, ++ }, { ++ hinfc620_pagesize_32K, NAND_PAGE_32K, ++ } ++}; ++ ++enum hinfc620_page_reg hinfc620_page_type2reg(int type) ++{ ++ return type2reg(page_type2reg, ARRAY_SIZE(page_type2reg), type, 0); ++} ++ ++int hinfc620_page_reg2type(enum hinfc620_page_reg reg) ++{ ++ return reg2type(page_type2reg, ARRAY_SIZE(page_type2reg), reg, 0); ++} ++/*****************************************************************************/ ++ ++static struct match_reg_type ecc_type2reg[] = { ++ { ++ hinfc620_ecc_none, NAND_ECC_NONE, ++ }, { ++ hinfc620_ecc_8bit, NAND_ECC_4BIT_512, ++ }, { ++ hinfc620_ecc_16bit, NAND_ECC_8BIT_512, ++ }, { ++ hinfc620_ecc_24bit, NAND_ECC_24BIT, ++ }, { ++ hinfc620_ecc_40bit, NAND_ECC_40BIT, ++ }, { ++ hinfc620_ecc_64bit, NAND_ECC_64BIT, ++ }, { ++ hinfc620_ecc_28bit, NAND_ECC_28BIT, ++ }, { ++ hinfc620_ecc_42bit, NAND_ECC_42BIT, ++ } ++}; ++ ++enum hinfc620_ecc_reg hinfc620_ecc_type2reg(int type) ++{ ++ return type2reg(ecc_type2reg, ARRAY_SIZE(ecc_type2reg), type, 0); ++} ++ ++int hinfc620_ecc_reg2type(enum hinfc620_ecc_reg reg) ++{ ++ return reg2type(ecc_type2reg, ARRAY_SIZE(ecc_type2reg), reg, 0); ++} ++ +diff --git a/drivers/mtd/nand/hinfc610/hinfc620_gen.h b/drivers/mtd/nand/hinfc610/hinfc620_gen.h +new file mode 100644 +index 0000000..88fb1e4 +--- /dev/null ++++ b/drivers/mtd/nand/hinfc610/hinfc620_gen.h +@@ -0,0 +1,53 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef HINFC620_GENH ++#define HINFC620_GENH ++/******************************************************************************/ ++ ++#include "../hinfc_gen.h" ++ ++enum hinfc620_ecc_reg { ++ hinfc620_ecc_none = 0x00, ++ hinfc620_ecc_8bit = 0x02, ++ hinfc620_ecc_16bit = 0x03, ++ hinfc620_ecc_24bit = 0x04, ++ hinfc620_ecc_40bit = 0x05, ++ hinfc620_ecc_64bit = 0x06, ++ hinfc620_ecc_28bit = 0x07, ++ hinfc620_ecc_42bit = 0x08, ++}; ++ ++enum hinfc620_page_reg { ++ hinfc620_pagesize_2K = 0x01, ++ hinfc620_pagesize_4K = 0x02, ++ hinfc620_pagesize_8K = 0x03, ++ hinfc620_pagesize_16K = 0x04, ++ hinfc620_pagesize_32K = 0x05, ++}; ++ ++enum hinfc620_page_reg hinfc620_page_type2reg(int type); ++ ++int hinfc620_page_reg2type(enum hinfc620_page_reg reg); ++ ++enum hinfc620_ecc_reg hinfc620_ecc_type2reg(int type); ++ ++int hinfc620_ecc_reg2type(enum hinfc620_ecc_reg reg); ++ ++/******************************************************************************/ ++#endif /* HINFC620_GENH */ +diff --git a/drivers/mtd/nand/hinfc_gen.c b/drivers/mtd/nand/hinfc_gen.c +new file mode 100644 +index 0000000..7ecfb5a +--- /dev/null ++++ b/drivers/mtd/nand/hinfc_gen.c +@@ -0,0 +1,247 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include "match_table.h" ++#include "hinfc_gen.h" ++ ++/*****************************************************************************/ ++struct nand_flash_dev *(*nand_get_flash_type_func)(struct mtd_info *mtd, ++ struct nand_chip *chip, struct nand_dev_t *spinand_dev_t) = NULL; ++ ++struct nand_flash_dev *(*get_spi_nand_flash_type_hook)(struct mtd_info *mtd, ++ unsigned char *id) = NULL; ++ ++/*****************************************************************************/ ++static struct match_t match_ecc[] = { ++ MATCH_SET_TYPE_DATA(NAND_ECC_NONE, "none"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_0BIT, "none"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_1BIT_512, "1bit/512"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_4BIT, "4bit/512"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_4BIT_512, "4bit/512"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_4BYTE, "4byte/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_8BIT, "4bit/512"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_8BIT_512, "8bit/512"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_8BYTE, "8byte/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_13BIT, "13bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_16BIT, "8bit/512"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_18BIT, "18bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_24BIT, "24bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_27BIT, "27bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_32BIT, "32bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_40BIT, "40bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_41BIT, "41bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_48BIT, "48bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_60BIT, "60bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_72BIT, "72bit/1k"), ++ MATCH_SET_TYPE_DATA(NAND_ECC_80BIT, "80bit/1k"), ++}; ++ ++const char *nand_ecc_name(int type) ++{ ++ return (char *)match_type_to_data(match_ecc, ARRAY_SIZE(match_ecc), ++ type, "unknown"); ++} ++ ++char *get_ecctype_str(enum ecc_type ecctype) ++{ ++ static char *ecctype_string[] = { ++ "None", "1bit/512Byte", "4bits/512Byte", "8bits/512Byte", ++ "24bits/1K", "40bits/1K", "unknown", "unknown"}; ++ return ecctype_string[(ecctype & 0x07)]; ++} ++ ++/*****************************************************************************/ ++static struct match_type_str page2name[] = { ++ { NAND_PAGE_512B, "512" }, ++ { NAND_PAGE_2K, "2K" }, ++ { NAND_PAGE_4K, "4K" }, ++ { NAND_PAGE_8K, "8K" }, ++ { NAND_PAGE_16K, "16K" }, ++ { NAND_PAGE_32K, "32K" }, ++}; ++ ++const char *nand_page_name(int type) ++{ ++ return type2str(page2name, ARRAY_SIZE(page2name), type, "unknown"); ++} ++ ++char *get_pagesize_str(enum page_type pagetype) ++{ ++ static char *pagesize_str[] = { ++ "512", "2K", "4K", "8K", "16K", "unknown", ++ "unknown", "unknown"}; ++ return pagesize_str[(pagetype & 0x07)]; ++} ++ ++/*****************************************************************************/ ++static struct match_reg_type page2size[] = { ++ { _512B, NAND_PAGE_512B }, ++ { _2K, NAND_PAGE_2K }, ++ { _4K, NAND_PAGE_4K }, ++ { _8K, NAND_PAGE_8K }, ++ { _16K, NAND_PAGE_16K }, ++ { _32K, NAND_PAGE_32K }, ++}; ++ ++unsigned int get_pagesize(enum page_type pagetype) ++{ ++ unsigned int pagesize[] = { ++ _512B, _2K, _4K, _8K, _16K, 0, 0, 0}; ++ return pagesize[(pagetype & 0x07)]; ++} ++ ++int nandpage_size2type(int size) ++{ ++ return reg2type(page2size, ARRAY_SIZE(page2size), size, NAND_PAGE_2K); ++} ++ ++int nandpage_type2size(int size) ++{ ++ return type2reg(page2size, ARRAY_SIZE(page2size), size, NAND_PAGE_2K); ++} ++ ++char *nand_dbgfs_options; ++ ++static int __init dbgfs_options_setup(char *s) ++{ ++ nand_dbgfs_options = s; ++ return 1; ++} ++__setup("nanddbgfs=", dbgfs_options_setup); ++ ++/*****************************************************************************/ ++ ++int get_bits(unsigned int n) ++{ ++ int loop; ++ int ret = 0; ++ ++ if (!n) ++ return 0; ++ ++ if (n > 0xFFFF) ++ loop = n > 0xFFFFFF ? 32 : 24; ++ else ++ loop = n > 0xFF ? 16 : 8; ++ ++ while (loop-- > 0 && n) { ++ if (n & 1) ++ ret++; ++ n >>= 1; ++ } ++ return ret; ++} ++ ++/*****************************************************************************/ ++#define et_ecc_none 0x00 ++#define et_ecc_4bit 0x02 ++#define et_ecc_8bit 0x03 ++#define et_ecc_24bit1k 0x04 ++#define et_ecc_40bit1k 0x05 ++#define et_ecc_64bit1k 0x06 ++ ++static struct match_reg_type ecc_yaffs_type_t[] = { ++ {et_ecc_none, NAND_ECC_0BIT}, ++ {et_ecc_4bit, NAND_ECC_8BIT}, ++ {et_ecc_8bit, NAND_ECC_16BIT}, ++ {et_ecc_24bit1k, NAND_ECC_24BIT}, ++ {et_ecc_40bit1k, NAND_ECC_40BIT}, ++ {et_ecc_64bit1k, NAND_ECC_64BIT} ++}; ++ ++unsigned char match_ecc_type_to_yaffs(unsigned char type) ++{ ++ return type2reg(ecc_yaffs_type_t, ARRAY_SIZE(ecc_yaffs_type_t), type, ++ et_ecc_4bit); ++} ++ ++/*****************************************************************************/ ++static struct match_t page_table[] = { ++ {NAND_PAGE_2K, PAGE_SIZE_2KB, "2K"}, ++ {NAND_PAGE_4K, PAGE_SIZE_4KB, "4K"}, ++ {NAND_PAGE_8K, PAGE_SIZE_8KB, "8K"}, ++ {NAND_PAGE_16K, PAGE_SIZE_16KB, "16K"}, ++}; ++ ++unsigned char match_page_reg_to_type(unsigned char reg) ++{ ++ return match_reg_to_type(page_table, ARRAY_SIZE(page_table), reg, ++ NAND_PAGE_2K); ++} ++ ++unsigned char match_page_type_to_reg(unsigned char type) ++{ ++ return match_type_to_reg(page_table, ARRAY_SIZE(page_table), type, ++ PAGE_SIZE_2KB); ++} ++ ++const char *match_page_type_to_str(unsigned char type) ++{ ++ return match_type_to_data(page_table, ARRAY_SIZE(page_table), type, ++ "unknown"); ++} ++ ++/*****************************************************************************/ ++static struct match_t ecc_table[] = { ++ {NAND_ECC_0BIT, ECC_TYPE_0BIT, "none"}, ++ {NAND_ECC_8BIT, ECC_TYPE_8BIT, "4bit/512"}, ++ {NAND_ECC_16BIT, ECC_TYPE_16BIT, "8bit/512"}, ++ {NAND_ECC_24BIT, ECC_TYPE_24BIT, "24bit/1K"}, ++ {NAND_ECC_28BIT, ECC_TYPE_28BIT, "28bit/1K"}, ++ {NAND_ECC_40BIT, ECC_TYPE_40BIT, "40bit/1K"}, ++ {NAND_ECC_64BIT, ECC_TYPE_64BIT, "64bit/1K"}, ++}; ++ ++unsigned char match_ecc_reg_to_type(unsigned char reg) ++{ ++ return match_reg_to_type(ecc_table, ARRAY_SIZE(ecc_table), reg, ++ NAND_ECC_8BIT); ++} ++ ++unsigned char match_ecc_type_to_reg(unsigned char type) ++{ ++ return match_type_to_reg(ecc_table, ARRAY_SIZE(ecc_table), type, ++ ECC_TYPE_8BIT); ++} ++ ++const char *match_ecc_type_to_str(unsigned char type) ++{ ++ return match_type_to_data(ecc_table, ARRAY_SIZE(ecc_table), type, ++ "unknown"); ++} ++ ++/*****************************************************************************/ ++static struct match_t page_type_size_table[] = { ++ {NAND_PAGE_2K, _2K, NULL}, ++ {NAND_PAGE_4K, _4K, NULL}, ++ {NAND_PAGE_8K, _8K, NULL}, ++ {NAND_PAGE_16K, _16K, NULL}, ++}; ++ ++unsigned char match_page_size_to_type(unsigned int size) ++{ ++ return match_reg_to_type(page_type_size_table, ++ ARRAY_SIZE(page_type_size_table), size, NAND_PAGE_2K); ++} ++ ++unsigned int match_page_type_to_size(unsigned char type) ++{ ++ return match_type_to_reg(page_type_size_table, ++ ARRAY_SIZE(page_type_size_table), type, _2K); ++} +diff --git a/drivers/mtd/nand/hinfc_gen.h b/drivers/mtd/nand/hinfc_gen.h +new file mode 100644 +index 0000000..bc3658c +--- /dev/null ++++ b/drivers/mtd/nand/hinfc_gen.h +@@ -0,0 +1,288 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#ifndef __HINFC_GEN_H__ ++#define __HINFC_GEN_H__ ++ ++/*****************************************************************************/ ++#include ++#include ++#include ++#include ++#include ++ ++/*****************************************************************************/ ++#define HINFC_VER_300 (0x300) ++#define HINFC_VER_301 (0x301) ++#define HINFC_VER_310 (0x310) ++#define HINFC_VER_504 (0x504) ++#define HINFC_VER_505 (0x505) ++#define HINFC_VER_600 (0x600) ++#define HINFC_VER_610 (0x610) ++#define HINFC_VER_620 (0x620) ++ ++/*****************************************************************************/ ++#define NAND_PAGE_512B 0 ++#define NAND_PAGE_1K 1 ++#define NAND_PAGE_2K 2 ++#define NAND_PAGE_4K 3 ++#define NAND_PAGE_8K 4 ++#define NAND_PAGE_16K 5 ++#define NAND_PAGE_32K 6 ++ ++/*****************************************************************************/ ++#define NAND_ECC_NONE 0 ++#define NAND_ECC_0BIT 0 ++#define NAND_ECC_1BIT 1 ++#define NAND_ECC_1BIT_512 1 ++#define NAND_ECC_4BIT 2 ++#define NAND_ECC_4BIT_512 2 ++#define NAND_ECC_4BYTE 2 ++#define NAND_ECC_8BIT 2 ++#define NAND_ECC_8BIT_512 3 ++#define NAND_ECC_8BYTE 3 ++#define NAND_ECC_13BIT 4 ++#define NAND_ECC_16BIT 5 ++#define NAND_ECC_18BIT 6 ++#define NAND_ECC_24BIT 7 ++#define NAND_ECC_27BIT 8 ++#define NAND_ECC_28BIT 9 ++#define NAND_ECC_32BIT 10 ++#define NAND_ECC_40BIT 11 ++#define NAND_ECC_41BIT 12 ++#define NAND_ECC_42BIT 13 ++#define NAND_ECC_48BIT 14 ++#define NAND_ECC_60BIT 15 ++#define NAND_ECC_64BIT 16 ++#define NAND_ECC_72BIT 17 ++#define NAND_ECC_80BIT 18 ++ ++enum ecc_type { ++ et_ecc_none = 0x00, ++ et_ecc_1bit = 0x01, ++ et_ecc_4bit = 0x02, ++ et_ecc_8bit = 0x03, ++ et_ecc_24bit1k = 0x04, ++ et_ecc_40bit1k = 0x05, ++ et_ecc_64bit1k = 0x06, ++}; ++ ++enum page_type { ++ pt_pagesize_512 = 0x00, ++ pt_pagesize_2K = 0x01, ++ pt_pagesize_4K = 0x02, ++ pt_pagesize_8K = 0x03, ++ pt_pagesize_16K = 0x04, ++}; ++ ++/*****************************************************************************/ ++struct nand_config_info { ++ unsigned int pagetype; ++ unsigned int ecctype; ++ unsigned int oobsize; ++ struct nand_ecclayout *layout; ++}; ++ ++struct hinfc_host; ++ ++struct nand_sync { ++ ++#define SET_NAND_SYNC_TYPE(_mfr, _onfi, _version) \ ++ ((((_mfr) & 0xFF) << 16) | (((_version) & 0xFF) << 8) \ ++ | ((_onfi) & 0xFF)) ++ ++#define GET_NAND_SYNC_TYPE_MFR(_type) (((_type) >> 16) & 0xFF) ++#define GET_NAND_SYNC_TYPE_VER(_type) (((_type) >> 8) & 0xFF) ++#define GET_NAND_SYNC_TYPE_INF(_type) ((_type) & 0xFF) ++ ++#define NAND_TYPE_ONFI_23_MICRON \ ++ SET_NAND_SYNC_TYPE(NAND_MFR_MICRON, NAND_IS_ONFI, 0x23) ++#define NAND_TYPE_ONFI_30_MICRON \ ++ SET_NAND_SYNC_TYPE(NAND_MFR_MICRON, NAND_IS_ONFI, 0x30) ++#define NAND_TYPE_TOGGLE_TOSHIBA \ ++ SET_NAND_SYNC_TYPE(NAND_MFR_TOSHIBA, 0, 0) ++#define NAND_TYPE_TOGGLE_SAMSUNG \ ++ SET_NAND_SYNC_TYPE(NAND_MFR_SAMSUNG, 0, 0) ++ ++#define NAND_TYPE_TOGGLE_10 SET_NAND_SYNC_TYPE(0, 0, 0x10) ++#define NAND_TYPE_ONFI_30 SET_NAND_SYNC_TYPE(0, NAND_IS_ONFI, 0x30) ++#define NAND_TYPE_ONFI_23 SET_NAND_SYNC_TYPE(0, NAND_IS_ONFI, 0x23) ++ ++ int type; ++ int (*enable)(struct nand_chip *chip); ++ int (*disable)(struct nand_chip *chip); ++}; ++ ++struct read_retry_t { ++ int type; ++ int count; ++ int (*set_rr_param)(struct hinfc_host *host, int param); ++ int (*get_rr_param)(struct hinfc_host *host); ++ int (*reset_rr_param)(struct hinfc_host *host); ++}; ++ ++struct ecc_info_t { ++ int pagesize; ++ int ecctype; ++ int threshold; ++ int section; ++ void (*dump)(struct hinfc_host *host, unsigned char ecc[], ++ int *max_bitsflag); ++}; ++ ++struct nand_dev_t { ++ struct nand_flash_dev flash_dev; ++ ++ char *start_type; ++ unsigned char ids[8]; ++ int oobsize; ++ int ecctype; ++ ++ /* (Controller) support ecc/page detect, driver don't need detect */ ++#define NANDC_HW_AUTO 0x01 ++ /* (Controller) support ecc/page detect, ++ * and current ecc/page config finish */ ++#define NANDC_CONFIG_DONE 0x02 ++ /* (Controller) is sync, default is async */ ++#define NANDC_IS_SYNC_BOOT 0x04 ++ ++/* (NAND) need randomizer */ ++#define NAND_RANDOMIZER 0x10 ++/* (NAND) is ONFI interface, combine with sync/async symble */ ++#define NAND_IS_ONFI 0x20 ++/* (NAND) support async and sync, such micron onfi, toshiba toggle 1.0 */ ++#define NAND_MODE_SYNC_ASYNC 0x40 ++/* (NAND) support only sync, such samsung sync. */ ++#define NAND_MODE_ONLY_SYNC 0x80 ++ ++#define NAND_CHIP_MICRON (NAND_MODE_SYNC_ASYNC | NAND_IS_ONFI) ++/* This NAND is async, or sync/async, default is async mode, ++ * toggle1.0 interface */ ++#define NAND_CHIP_TOSHIBA_TOGGLE_10 (NAND_MODE_SYNC_ASYNC) ++/* This NAND is only sync mode, toggle2.0 interface */ ++#define NAND_CHIP_TOSHIBA_TOGGLE_20 (NAND_MODE_ONLY_SYNC) ++/* This NAND is only sync mode */ ++#define NAND_CHIP_SAMSUNG (NAND_MODE_ONLY_SYNC) ++ ++ unsigned int flags; ++ ++#define NAND_RR_NONE 0x00 ++#define NAND_RR_HYNIX_BG_BDIE 0x10 ++#define NAND_RR_HYNIX_BG_CDIE 0x11 ++#define NAND_RR_HYNIX_CG_ADIE 0x12 ++#define NAND_RR_MICRON 0x20 ++#define NAND_RR_SAMSUNG 0x30 ++#define NAND_RR_TOSHIBA_24nm 0x40 ++#define NAND_RR_TOSHIBA_19nm 0x41 ++ int read_retry_type; ++}; ++ ++/*****************************************************************************/ ++ ++#define IS_NANDC_HW_AUTO(_host) ((_host)->flags & NANDC_HW_AUTO) ++#define IS_NANDC_CONFIG_DONE(_host) ((_host)->flags & NANDC_CONFIG_DONE) ++#define IS_NANDC_SYNC_BOOT(_host) ((_host)->flags & NANDC_IS_SYNC_BOOT) ++ ++#define IS_NAND_RANDOM(_dev) ((_dev)->flags & NAND_RANDOMIZER) ++#define IS_NAND_ONLY_SYNC(_dev) ((_dev)->flags & NAND_MODE_ONLY_SYNC) ++#define IS_NAND_SYNC_ASYNC(_dev) ((_dev)->flags & NAND_MODE_SYNC_ASYNC) ++#define IS_NAND_ONFI(_dev) ((_dev)->flags & NAND_IS_ONFI) ++ ++#define ERSTR_HARDWARE "Hardware configuration error. " ++#define ERSTR_DRIVER "Driver does not support. " ++ ++#define ENABLE 1 ++#define DISABLE 0 ++ ++/*****************************************************************************/ ++ ++char *get_ecctype_str(enum ecc_type ecctype); ++ ++char *get_pagesize_str(enum page_type pagetype); ++ ++unsigned int get_pagesize(enum page_type pagetype); ++ ++const char *nand_ecc_name(int type); ++ ++const char *nand_page_name(int type); ++ ++int nandpage_size2type(int size); ++ ++int nandpage_type2size(int size); ++ ++/*****************************************************************************/ ++extern int (*hinfc_param_adjust)(struct mtd_info *mtd, struct nand_chip *chip, ++ struct nand_dev_t *nand_dev); ++ ++extern struct nand_flash_dev *(*nand_get_flash_type_func)(struct mtd_info *mtd, ++ struct nand_chip *chip, struct nand_dev_t *spinand_dev_t); ++ ++extern struct nand_flash_dev *(*get_spi_nand_flash_type_hook) ++ (struct mtd_info *mtd, unsigned char *id); ++ ++extern int (*hinfc_param_adjust)(struct mtd_info *, ++ struct nand_chip *, struct nand_dev_t *); ++ ++/*****************************************************************************/ ++struct nand_flash_dev *hinfc_get_flash_type(struct mtd_info *mtd, ++ struct nand_chip *chip, u8 *id_data, int *busw); ++ ++extern struct nand_flash_dev *(*get_spi_nand_flash_type_hook) ++ (struct mtd_info *mtd, unsigned char *id); ++ ++void hinfc_nand_param_adjust(struct mtd_info *mtd, struct nand_chip *chip); ++ ++void hinfc_show_info(struct mtd_info *mtd, char *vendor, char *chipname); ++ ++void hinfc_show_chipsize(struct nand_chip *chip); ++ ++int get_bits(unsigned int n); ++ ++/*****************************************************************************/ ++#define hinfc_pr_msg(_fmt, arg...) printk(_fmt, ##arg) ++ ++#define hinfc_pr_bug(fmt, args...) do { \ ++ printk("%s(%d): bug " fmt, __FILE__, __LINE__, ##args); \ ++ while (1) \ ++ ; \ ++} while (0) ++ ++extern char *nand_dbgfs_options; ++/*****************************************************************************/ ++extern unsigned char match_page_reg_to_type(unsigned char reg); ++ ++extern unsigned char match_page_type_to_reg(unsigned char type); ++ ++extern const char *match_page_type_to_str(unsigned char type); ++ ++/*****************************************************************************/ ++extern unsigned char match_ecc_reg_to_type(unsigned char reg); ++ ++extern unsigned char match_ecc_type_to_reg(unsigned char type); ++ ++extern const char *match_ecc_type_to_str(unsigned char type); ++ ++/*****************************************************************************/ ++extern unsigned char match_page_size_to_type(unsigned int size); ++ ++extern unsigned int match_page_type_to_size(unsigned char type); ++ ++const char *nand_ecc_name(int type); ++/*****************************************************************************/ ++ ++#endif /* End of __HINFC_GEN_H__ */ +diff --git a/drivers/mtd/nand/hinfc_spl_ids.c b/drivers/mtd/nand/hinfc_spl_ids.c +new file mode 100644 +index 0000000..ccc15de +--- /dev/null ++++ b/drivers/mtd/nand/hinfc_spl_ids.c +@@ -0,0 +1,979 @@ ++/* ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include "hinfc_gen.h" ++ ++/*****************************************************************************/ ++ ++struct nand_flash_special_dev { ++ unsigned char id[8]; ++ int length; /* length of id. */ ++ unsigned long long chipsize; ++ struct nand_flash_dev *(*probe)(struct nand_dev_t *nand_dev); ++ char *name; ++ ++ unsigned long pagesize; ++ unsigned long erasesize; ++ unsigned long oobsize; ++ unsigned long options; ++ unsigned int read_retry_type; ++ ++#define BBP_LAST_PAGE 0x01 ++#define BBP_FIRST_PAGE 0x02 ++ unsigned int badblock_pos; ++ unsigned int flags; ++}; ++ ++/*****************************************************************************/ ++/* this is nand probe function. */ ++/*****************************************************************************/ ++ ++static struct nand_flash_dev *hynix_probe_v02( ++ struct nand_dev_t *nand_dev) ++{ ++ unsigned char *id = nand_dev->ids; ++ struct nand_flash_dev *type = &nand_dev->flash_dev; ++ ++ int pagesizes[] = {SZ_2K, SZ_4K, SZ_8K, 0}; ++ int oobsizes[] = {128, 224, 448, 0, 0, 0, 0, 0}; ++ int blocksizes[] = {SZ_128K, SZ_256K, SZ_512K, ++ (SZ_256K + SZ_512K), SZ_1M, SZ_2M, 0, 0}; ++ ++ int blocktype = (((id[3] >> 5) & 0x04) | ((id[3] >> 4) & 0x03)); ++ int oobtype = (((id[3] >> 2) & 0x03) | ((id[3] >> 4) & 0x04)); ++ ++ type->options = 0; ++ type->pagesize = pagesizes[(id[3] & 0x03)]; ++ type->erasesize = blocksizes[blocktype]; ++ nand_dev->oobsize = oobsizes[oobtype]; ++ ++ return type; ++} ++/*****************************************************************************/ ++ ++static struct nand_flash_dev *samsung_probe_v02( ++ struct nand_dev_t *nand_dev) ++{ ++ unsigned char *id = nand_dev->ids; ++ struct nand_flash_dev *type = &nand_dev->flash_dev; ++ ++ int pagesizes[] = {SZ_2K, SZ_4K, SZ_8K, 0}; ++ int oobsizes[] = {0, 128, 218, 400, 436, 0, 0, 0}; ++ int blocksizes[] = {SZ_128K, SZ_256K, SZ_512K, SZ_1M, 0, 0, 0, 0}; ++ ++ int blocktype = (((id[3] >> 5) & 0x04) | ((id[3] >> 4) & 0x03)); ++ int oobtype = (((id[3] >> 4) & 0x04) | ((id[3] >> 2) & 0x03)); ++ ++ type->options = 0; ++ type->pagesize = pagesizes[(id[3] & 0x03)]; ++ type->erasesize = blocksizes[blocktype]; ++ nand_dev->oobsize = oobsizes[oobtype]; ++ ++ return type; ++} ++/*****************************************************************************/ ++ ++#define DRV_VERSION "1.38" ++ ++/*****************************************************************************/ ++/* ++ * samsung: 27nm need randomizer, 21nm need read retry; ++ * micron: 25nm need read retry, datasheet will explain read retry. ++ * toshaba 32nm need randomizer, 24nm need read retry. ++ * hynix: 2xnm need read retry. ++ * ++ * The special nand flash ID table version 1.37 ++ * ++ * manufactory | type | name | ecc_type | version_tag ++ * Micron | MLC | MT29F64G08CBABA | 40bit/1k | 1.36 ++ * Micron | MLC | MT29F32G08CBADA | 40bit/1k | ++ * Micron | SLC | MT29F8G08ABxBA | 4bit/512 | ++ * Micron | MLC | MT29F16G08CBABx | 12bit/512 | ++ * Micron | MLC | MT29F16G08CBACA | 24bit/1k | ++ * Micron | MLC | MT29F32G08CBACA | 24bit/1k | ++ * Micron | MLC | MT29F64G08CxxAA | 24bit/1k | ++ * Micron | MLC | MT29F256G08CJAAA | 24bit/1k | 2CE ++ * Micron | MLC | MT29F256G08CMCBB | 24bit/1k | ++ * Micron | SLC | MT29F8G08ABACA | 8bit/512 | ++ * Micron | SLC | MT29F4G08ABAEA | 8bit/512 | ++ * Micron | SLC | MT29F2G08ABAFA | 8bit/512 | ++ * Micron | SLC | MT29F16G08ABACA | 8bit/512 | ++ * Toshiba | MLC | TC58NVG4D2FTA00 | 24bit/1k | ++ * Toshiba | MLC | TH58NVG6D2FTA20 | 24bit/1k | 2CE ++ * Toshiba | MLC | TC58NVG5D2HTA00 | 40bit/1k | ++ * Toshiba | MLC | TC58NVG6D2GTA00 | 40bit/1k | ++ * Toshiba | MLC | TC58NVG6DCJTA00 | | ++ * Toshiba | MLC | TC58TEG5DCJTA00 | | ++ * Toshiba | SLC | TC58NVG0S3HTA00 | 8bit/512 | ++ * Toshiba | SLC | TC58NVG1S3HTA00 | 8bit/512 | ++ * Toshiba | SLC | TC58NVG1S3ETA00 | 4bit/512 | ++ * Toshiba | SLC | TC58NVG3S0FTA00 | 4bit/512 | ++ * Toshiba | SLC | TC58NVG2S0FTA00 | 4bit/512 | ++ * Toshiba | SLC | TH58NVG2S3HTA00 | 4bit/512 | ++ * Toshiba | TLC | TC58NVG5T2JTA00 | 60bit/1k | ++ * Toshiba | TLC | TC58TEG5DCKTAx0 | 60bit/1k | ++ * Toshiba | MLC | Tx58TEGxDDKTAx0 | | ++ * Samsung | MLC | K9LB(HC/PD/MD)G08U0(1)D | 8bit/512B | ++ * Samsung | MLC | K9GAG08U0E | 24bit/1KB | ++ * Samsung | MLC | K9LBG08U0E | 24bit/1KB | ++ * Samsung | MLC | K9G8G08U0C | 24bit/1KB | ++ * Samsung | MLC | K9GAG08U0F | 24bit/1KB | ++ * Samsung | MLC | K9LBG08U0M | | ++ * Samsung | MLC | K9GBG08U0A | 24bit/1KB | ++ * Samsung | MLC | K9GBG08U0B | 40bit/1KB | ++ * Hynix | MLC | H27UAG8T2A | | ++ * Hynix | MLC | H27UAG8T2B | | ++ * Hynix | MLC | H27UBG8T2A | | ++ * Hynix | MLC | H27UBG8T2BTR | 24bit/1KB | ++ * Hynix | MLC | H27UCG8T2A | 40bit/1KB | ++ * Hynix | MLC | H27UBG8T2C | 40bit/1KB | ++ * MISC | MLC | P1UAGA30AT-GCA | 8bit/512 | ++ * MISC | MLC | PSU8GA30AT-GIA/ASU8GA30IT-G30CA | 4bit/512 | ++ * MISC | SLC | PSU2GA30AT | 1bit/512 | 1.36 ++ * Toshiba | SLC | TC58NVG2S0HTA00 | 24bit/1K | 1.37 ++ * Toshiba | SLC | TC58NVG3S0HTA00 | 24bit/1K | 1.37 ++ * Micron | SLC | MT29F2G08ABAEA | 4bit/512 | ++ * Spansion | SLC | S34ML02G200TFI000 | 24bit/1K | ++ * Spansion | SLC | S34ML04G200TFI000 | 24bit/1K | 1.38 ++ * ++ */ ++ ++static struct nand_flash_special_dev nand_flash_special_dev[] = { ++ ++/****************************** Spansion *******************************/ ++ ++ { /* SLC S34ML02G200TFI000 */ ++ .name = "S34ML02G200TFI000", ++ .id = {0x01, 0xDA, 0x90, 0x95, 0x46, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _256M, ++ .probe = NULL, ++ .pagesize = SZ_2K, ++ .erasesize = SZ_128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ ++ { /* SLC S34ML04G200TFI000 */ ++ .name = "S34ML04G200TFI000", ++ .id = {0x01, 0xDC, 0x90, 0x95, 0x56, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _512M, ++ .probe = NULL, ++ .pagesize = SZ_2K, ++ .erasesize = SZ_128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ ++/****************************** Micron *******************************/ ++ { /* MLC 40bit/1k */ ++ .name = "MT29F64G08CBABA", ++ .id = {0x2C, 0x64, 0x44, 0x4B, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_2M, ++ .oobsize = 744, ++ .options = 0, ++ .read_retry_type = NAND_RR_MICRON, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = NAND_RANDOMIZER | NAND_CHIP_MICRON, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "MT29F32G08CBADA", ++ .id = {0x2C, 0x44, 0x44, 0x4B, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_2M, ++ .oobsize = 744, ++ .options = 0, ++ .read_retry_type = NAND_RR_MICRON, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "MT29F8G08ABxBA", ++ .id = {0x2C, 0x38, 0x00, 0x26, 0x85, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = SZ_1G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_512K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 12bit/512 */ ++ .name = "MT29F16G08CBABx", ++ .id = {0x2C, 0x48, 0x04, 0x46, 0x85, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = SZ_2G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_1M, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "MT29F16G08CBACA", ++ .id = {0x2C, 0x48, 0x04, 0x4A, 0xA5, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = SZ_2G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_1M, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "MT29F32G08CBACA", ++ .id = {0x2C, 0x68, 0x04, 0x4A, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_1M, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "MT29F64G08CxxAA", ++ .id = {0x2C, 0x88, 0x04, 0x4B, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_2M, ++ .oobsize = 448, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k 2CE */ ++ .name = "MT29F256G08CJAAA", ++ .id = {0x2C, 0xA8, 0x05, 0xCB, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _16G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_2M, ++ .oobsize = 448, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "MT29F256G08CMCBB", ++ .id = {0x2C, 0x64, 0x44, 0x4B, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 8, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_2M, ++ .oobsize = 744, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "MT29F8G08ABACA", ++ .id = {0x2C, 0xD3, 0x90, 0xA6, 0x64, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = SZ_1G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_256K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "MT29F4G08ABAEA", ++ .id = {0x2C, 0xDC, 0x90, 0xA6, 0x54, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = SZ_512M, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_256K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "MT29F2G08ABAFA", ++ .id = {0x2C, 0xDA, 0x90, 0x95, 0x04, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = SZ_256M, ++ .probe = NULL, ++ .pagesize = SZ_2K, ++ .erasesize = SZ_128K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC MT29F2G08ABAEA */ ++ .name = "MT29F2G08ABAEA", ++ .id = {0x2C, 0xDA, 0x90, 0x95, 0x06, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _256M, ++ .probe = NULL, ++ .pagesize = SZ_2K, ++ .erasesize = SZ_128K, ++ .oobsize = 64, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "MT29F16G08ABACA", ++ .id = {0x2C, 0x48, 0x00, 0x26, 0xA9, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = SZ_2G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_512K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ ++/****************************** Toshaba *******************************/ ++ ++ { /* MLC 24bit/1k 32nm */ ++ .name = "TC58NVG4D2FTA00", ++ .id = {0x98, 0xD5, 0x94, 0x32, 0x76, 0x55, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = SZ_2G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_1M, ++ .oobsize = 448, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k 32nm 2CE*/ ++ .name = "TH58NVG6D2FTA20", ++ .id = {0x98, 0xD7, 0x94, 0x32, 0x76, 0x55, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_1M, ++ .oobsize = 448, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 40bit/1k 24nm */ ++ .name = "TC58NVG5D2HTA00 24nm", ++ .id = {0x98, 0xD7, 0x94, 0x32, 0x76, 0x56, 0x08, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_1M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_24nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "TC58NVG6D2GTA00", ++ .id = {0x98, 0xDE, 0x94, 0x82, 0x76, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_2M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 19nm */ ++ .name = "TC58NVG6DCJTA00 19nm", ++ .id = {0x98, 0xDE, 0x84, 0x93, 0x72, 0x57, 0x08, 0x04}, ++ .length = 8, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = SZ_16K, ++ .erasesize = SZ_4M, ++ .oobsize = 1280, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_24nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 19nm */ ++ .name = "TC58TEG5DCJTA00 19nm", ++ .id = {0x98, 0xD7, 0x84, 0x93, 0x72, 0x57, 0x08, 0x04}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_16K, ++ .erasesize = SZ_4M, ++ .oobsize = 1280, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_24nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER | NAND_CHIP_TOSHIBA_TOGGLE_10, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "TC58NVG0S3HTA00", ++ .id = {0x98, 0xF1, 0x80, 0x15, 0x72, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = SZ_128M, ++ .probe = NULL, ++ .pagesize = SZ_2K, ++ .erasesize = SZ_128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ /* ++ * Datasheet: read one column of any page in each block. If the ++ * data of the column is 00 (Hex), define the block as a bad ++ * block. ++ */ ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 8bit/512 */ ++ .name = "TC58NVG1S3HTA00", ++ .id = {0x98, 0xDA, 0x90, 0x15, 0x76, 0x16, 0x08, 0x00}, ++ .length = 7, ++ .chipsize = SZ_256M, ++ .probe = NULL, ++ .pagesize = SZ_2K, ++ .erasesize = SZ_128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "TC58NVG1S3ETA00", ++ .id = {0x98, 0xDA, 0x90, 0x15, 0x76, 0x14, 0x03, 0x00}, ++ .length = 7, ++ .chipsize = SZ_256M, ++ .probe = NULL, ++ .pagesize = SZ_2K, ++ .erasesize = SZ_128K, ++ .oobsize = 64, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "TC58NVG3S0FTA00", ++ .id = {0x98, 0xD3, 0x90, 0x26, 0x76, 0x15, 0x02, 0x08}, ++ .length = 8, ++ .chipsize = SZ_1G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_256K, ++ .oobsize = 232, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "TC58NVG3S0HTA00", ++ .id = {0x98, 0xD3, 0x91, 0x26, 0x76, 0x16, 0x08, 0x00}, ++ .length = 8, ++ .chipsize = SZ_1G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_256K, ++ .oobsize = 256, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 24bit/1k */ ++ .name = "TC58NVG2S0HTA00", ++ .id = {0x98, 0xDC, 0x90, 0x26, 0x76, 0x16, 0x08, 0x00}, ++ .length = 8, ++ .chipsize = SZ_512M, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_256K, ++ .oobsize = 256, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "TC58NVG2S0FTA00", ++ .id = {0x98, 0xDC, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08}, ++ .length = 8, ++ .chipsize = SZ_512M, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_256K, ++ .oobsize = 224, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 4bit/512 */ ++ .name = "TH58NVG2S3HTA00", ++ .id = {0x98, 0xDC, 0x91, 0x15, 0x76}, ++ .length = 5, ++ .chipsize = SZ_512M, ++ .probe = NULL, ++ .pagesize = SZ_2K, ++ .erasesize = SZ_128K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE, ++ .flags = 0, ++ }, ++ { /* TLC 60bit/1k 19nm */ ++ .name = "TC58NVG5T2JTA00 19nm TLC", ++ .id = {0x98, 0xD7, 0x98, 0x92, 0x72, 0x57, 0x08, 0x10}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_4M, ++ .oobsize = 1024, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_24nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* TLC 60bit/1k 19nm */ ++ .name = "TC58TEG5DCKTAx0 19nm MLC", ++ /* datasheet says 6 ids id data, but really has 8 ids. */ ++ .id = {0x98, 0xD7, 0x84, 0x93, 0x72, 0x50, 0x08, 0x04}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_16K, ++ .erasesize = SZ_4M, ++ .oobsize = 1280, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_19nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { ++ .name = "Tx58TEGxDDKTAx0 19nm MLC", ++ .id = {0x98, 0xDE, 0x94, 0x93, 0x76, 0x50}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_16K, ++ .erasesize = SZ_4M, ++ .oobsize = 1280, ++ .options = 0, ++ .read_retry_type = NAND_RR_TOSHIBA_19nm, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++/******************************* Samsung ******************************/ ++ { /* MLC 8bit/512B */ ++ .name = "K9LB(HC/PD/MD)G08U0(1)D", ++ .id = {0xEC, 0xD7, 0xD5, 0x29, 0x38, 0x41, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = samsung_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1KB */ ++ .name = "K9GAG08U0E", ++ .id = {0xEC, 0xD5, 0x84, 0x72, 0x50, 0x42, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = SZ_2G, ++ .probe = samsung_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1KB */ ++ .name = "K9LBG08U0E", ++ .id = {0xEC, 0xD7, 0xC5, 0x72, 0x54, 0x42, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = samsung_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1KB */ ++ .name = "K9G8G08U0C", ++ .id = {0xEC, 0xD3, 0x84, 0x72, 0x50, 0x42, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = SZ_1G, ++ .probe = samsung_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "K9GAG08U0F", ++ .id = {0xEC, 0xD5, 0x94, 0x76, 0x54, 0x43, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = SZ_2G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_1M, ++ .oobsize = 512, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC */ ++ .name = "K9LBG08U0M", ++ .id = {0xEC, 0xD7, 0x55, 0xB6, 0x78, 0x00, 0x00, 0x00}, ++ .length = 5, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_512K, ++ .oobsize = 128, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1k */ ++ .name = "K9GBG08U0A 20nm", ++ .id = {0xEC, 0xD7, 0x94, 0x7A, 0x54, 0x43, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_1M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_SAMSUNG, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "K9GBG08U0B", ++ .id = {0xEC, 0xD7, 0x94, 0x7E, 0x64, 0x44, 0x00, 0x00}, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_1M, ++ .oobsize = 1024, ++ .options = 0, ++ .read_retry_type = NAND_RR_SAMSUNG, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ ++/*********************************** Hynix ****************************/ ++ { /* MLC */ ++ .name = "H27UAG8T2A", ++ .id = {0xAD, 0xD5, 0x94, 0x25, 0x44, 0x41, }, ++ .length = 6, ++ .chipsize = SZ_2G, ++ .probe = hynix_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC */ ++ .name = "H27UAG8T2B", ++ .id = {0xAD, 0xD5, 0x94, 0x9A, 0x74, 0x42, }, ++ .length = 6, ++ .chipsize = SZ_2G, ++ .probe = hynix_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC */ ++ .name = "H27UBG8T2A", ++ .id = {0xAD, 0xD7, 0x94, 0x9A, 0x74, 0x42, }, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = hynix_probe_v02, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 24bit/1K, 26nm TODO: Need read retry, chip is EOS */ ++ .name = "H27UBG8T2BTR 26nm", ++ .id = {0xAD, 0xD7, 0x94, 0xDA, 0x74, 0xC3, }, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_2M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_HYNIX_BG_BDIE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "H27UCG8T2A", ++ .id = {0xAD, 0xDE, 0x94, 0xDA, 0x74, 0xC4, }, ++ .length = 6, ++ .chipsize = _8G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_2M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_HYNIX_CG_ADIE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ { /* MLC 40bit/1k */ ++ .name = "H27UBG8T2C", ++ .id = {0xAD, 0xD7, 0x94, 0x91, 0x60, 0x44, }, ++ .length = 6, ++ .chipsize = _4G, ++ .probe = NULL, ++ .pagesize = SZ_8K, ++ .erasesize = SZ_2M, ++ .oobsize = 640, ++ .options = 0, ++ .read_retry_type = NAND_RR_HYNIX_BG_CDIE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = NAND_RANDOMIZER, ++ }, ++ ++/********************** MISC ******************************************/ ++ { /* MLC 8bit/512 */ ++ .name = "P1UAGA30AT-GCA", ++ .id = {0xC8, 0xD5, 0x14, 0x29, 0x34, 0x01, }, ++ .length = 6, ++ .chipsize = SZ_2G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_512K, ++ .oobsize = 218, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* MLC 4bit/512 */ ++ /* ++ * PowerFlash ASU8GA30IT-G30CA ID and MIRA PSU8GA30AT-GIA ID are ++ * the same ID ++ */ ++ .name = "PSU8GA30AT-GIA/ASU8GA30IT-G30CA", ++ .id = {0xC8, 0xD3, 0x90, 0x19, 0x34, 0x01, }, ++ .length = 6, ++ .chipsize = SZ_1G, ++ .probe = NULL, ++ .pagesize = SZ_4K, ++ .erasesize = SZ_256K, ++ .oobsize = 218, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ { /* SLC 1bit/512 */ ++ .name = "PSU2GA30AT", ++ .id = {0x7F, 0x7F, 0x7F, 0x7F, 0xC8, 0xDA, 0x00, 0x15, }, ++ .length = 8, ++ .chipsize = SZ_256M, ++ .probe = NULL, ++ .pagesize = SZ_2K, ++ .erasesize = SZ_128K, ++ .oobsize = 64, ++ .options = 0, ++ .read_retry_type = NAND_RR_NONE, ++ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE, ++ .flags = 0, ++ }, ++ {{0}, 0, 0, 0, 0, 0, 0, 0, 0}, ++}; ++ ++#define NUM_OF_SPECIAL_DEVICE \ ++ (sizeof(nand_flash_special_dev)/sizeof(struct nand_flash_special_dev)) ++ ++int (*hinfc_param_adjust)(struct mtd_info *, struct nand_chip *, ++ struct nand_dev_t *) = NULL; ++ ++static struct nand_dev_t __nand_dev; ++/*****************************************************************************/ ++ ++static struct nand_flash_dev *hinfc_nand_probe(struct mtd_info *mtd, ++ struct nand_chip *chip, ++ struct nand_dev_t *nand_dev) ++{ ++ struct nand_flash_special_dev *spl_dev; ++ unsigned char *byte = nand_dev->ids; ++ struct nand_flash_dev *type = &nand_dev->flash_dev; ++ ++ hinfc_pr_msg("Nand ID: 0x%02X 0x%02X 0x%02X 0x%02X", ++ byte[0], byte[1], byte[2], byte[3]); ++ hinfc_pr_msg(" 0x%02X 0x%02X 0x%02X 0x%02X\n", ++ byte[4], byte[5], byte[6], byte[7]); ++ ++ for (spl_dev = nand_flash_special_dev; spl_dev->length; spl_dev++) { ++ if (memcmp(byte, spl_dev->id, spl_dev->length)) ++ continue; ++ ++ hinfc_pr_msg("The Special NAND id table Version: %s\n", DRV_VERSION); ++ ++ if (spl_dev->probe) { ++ type = spl_dev->probe(nand_dev); ++ } else { ++ type->options = spl_dev->options; ++ type->pagesize = spl_dev->pagesize; ++ type->erasesize = spl_dev->erasesize; ++ nand_dev->oobsize = spl_dev->oobsize; ++ } ++ ++ nand_dev->read_retry_type = spl_dev->read_retry_type; ++ nand_dev->flags = spl_dev->flags; ++ ++ type->id[1] = byte[1]; ++ type->chipsize = (unsigned long)(spl_dev->chipsize >> 20); ++ type->name = spl_dev->name; ++ return type; ++ } ++ nand_dev->read_retry_type = NAND_RR_NONE; ++ ++ return NULL; ++} ++/*****************************************************************************/ ++ ++struct nand_flash_dev *hinfc_get_flash_type(struct mtd_info *mtd, ++ struct nand_chip *chip, ++ u8 *id_data, int *busw) ++{ ++ struct nand_flash_dev *type; ++ struct nand_dev_t *nand_dev = &__nand_dev; ++ ++ memset(nand_dev, 0, sizeof(struct nand_dev_t)); ++ memcpy(nand_dev->ids, id_data, 8); ++ ++ if (!hinfc_nand_probe(mtd, chip, nand_dev)) ++ return NULL; ++ ++ type = &nand_dev->flash_dev; ++ ++ if (!mtd->name) ++ mtd->name = type->name; ++ ++ chip->chipsize = (uint64_t)type->chipsize << 20; ++ mtd->erasesize = type->erasesize; ++ mtd->writesize = type->pagesize; ++ mtd->oobsize = nand_dev->oobsize; ++ *busw = (type->options & NAND_BUSWIDTH_16); ++ ++ return type; ++} ++/*****************************************************************************/ ++ ++void hinfc_nand_param_adjust(struct mtd_info *mtd, struct nand_chip *chip) ++{ ++ struct nand_dev_t *nand_dev = &__nand_dev; ++ ++ if (!nand_dev->oobsize) ++ nand_dev->oobsize = mtd->oobsize; ++ ++ if (hinfc_param_adjust) ++ hinfc_param_adjust(mtd, chip, nand_dev); ++} ++/*****************************************************************************/ ++ ++void hinfc_show_info(struct mtd_info *mtd, char *vendor, char *chipname) ++{ ++ /* char buf[20]; */ ++ struct nand_dev_t *nand_dev = &__nand_dev; ++ ++ /* hinfc_pr_msg("Nand: %s %s ", vendor, chipname); */ ++ ++ if (IS_NAND_RANDOM(nand_dev)) ++ hinfc_pr_msg("Randomizer \n"); ++ ++ if (nand_dev->read_retry_type != NAND_RR_NONE) ++ hinfc_pr_msg("Read-Retry \n"); ++ ++ if (nand_dev->start_type) ++ hinfc_pr_msg("Nand(%s): ", nand_dev->start_type); ++ else ++ hinfc_pr_msg("Nand: "); ++ ++ hinfc_pr_msg("OOB:%dB ", nand_dev->oobsize); ++ hinfc_pr_msg("ECC:%s ", nand_ecc_name(nand_dev->ecctype)); ++} ++/*****************************************************************************/ ++ ++void hinfc_show_chipsize(struct nand_chip *chip) ++{ ++ /*char buf[20];*/ ++ ++ /*hinfc_pr_msg("Chip:%sB*%d\n", ++ ultohstr(chip->chipsize, buf, sizeof(buf)), ++ chip->numchips);*/ ++} +diff --git a/drivers/mtd/nand/match_table.c b/drivers/mtd/nand/match_table.c +new file mode 100644 +index 0000000..271da05 +--- /dev/null ++++ b/drivers/mtd/nand/match_table.c +@@ -0,0 +1,96 @@ ++/****************************************************************************** ++ * COPYRIGHT (C) Hisilicon.2013 ++ * All rights reserved. ++ * *** ++ * Create by Hisilicon 2013-08-15 ++ * ++ *****************************************************************************/ ++ ++/*****************************************************************************/ ++#include ++#include "match_table.h" ++ ++/*****************************************************************************/ ++int reg2type(struct match_reg_type *table, int length, int reg, int def) ++{ ++ while (length-- > 0) { ++ if (table->reg == reg) ++ return table->type; ++ table++; ++ } ++ return def; ++} ++ ++int type2reg(struct match_reg_type *table, int length, int type, int def) ++{ ++ while (length-- > 0) { ++ if (table->type == type) ++ return table->reg; ++ table++; ++ } ++ return def; ++} ++ ++int str2type(struct match_type_str *table, int length, const char *str, ++ int size, int def) ++{ ++ while (length-- > 0) { ++ if (!strncmp(table->str, str, size)) ++ return table->type; ++ table++; ++ } ++ return def; ++} ++ ++const char *type2str(struct match_type_str *table, int length, int type, ++ const char *def) ++{ ++ while (length-- > 0) { ++ if (table->type == type) ++ return table->str; ++ table++; ++ } ++ return def; ++} ++ ++int match_reg_to_type(struct match_t *table, int nr_table, int reg, int def) ++{ ++ while (nr_table-- > 0) { ++ if (table->reg == reg) ++ return table->type; ++ table++; ++ } ++ return def; ++} ++ ++int match_type_to_reg(struct match_t *table, int nr_table, int type, int def) ++{ ++ while (nr_table-- > 0) { ++ if (table->type == type) ++ return table->reg; ++ table++; ++ } ++ return def; ++} ++ ++int match_data_to_type(struct match_t *table, int nr_table, char *data, ++ int size, int def) ++{ ++ while (nr_table-- > 0) { ++ if (!memcmp(table->data, data, size)) ++ return table->type; ++ table++; ++ } ++ return def; ++} ++ ++void *match_type_to_data(struct match_t *table, int nr_table, int type, ++ void *def) ++{ ++ while (nr_table-- > 0) { ++ if (table->type == type) ++ return table->data; ++ table++; ++ } ++ return def; ++} +diff --git a/drivers/mtd/nand/match_table.h b/drivers/mtd/nand/match_table.h +new file mode 100644 +index 0000000..6fb55cf +--- /dev/null ++++ b/drivers/mtd/nand/match_table.h +@@ -0,0 +1,56 @@ ++/****************************************************************************** ++ * COPYRIGHT (C) Hisilicon 2013 ++ * All rights reserved. ++ * *** ++ * Create by Hisilicon 2013-08-15 ++ * ++ *****************************************************************************/ ++#ifndef __MATCH_TABLE_H__ ++#define __MATCH_TABLE_H__ ++ ++/*****************************************************************************/ ++struct match_reg_type { ++ int reg; ++ int type; ++}; ++ ++struct match_type_str { ++ int type; ++ const char *str; ++}; ++ ++struct match_t { ++ int type; ++ int reg; ++ void *data; ++}; ++ ++/*****************************************************************************/ ++#define MATCH_SET_TYPE_REG(_type, _reg) {(_type), (_reg), (void *)0} ++#define MATCH_SET_TYPE_DATA(_type, _data) {(_type), 0, (void *)(_data)} ++#define MATCH_SET(_type, _reg, _data) {(_type), (_reg), (void *)(_data)} ++ ++/*****************************************************************************/ ++int reg2type(struct match_reg_type *table, int length, int reg, int def); ++ ++int type2reg(struct match_reg_type *table, int length, int type, int def); ++ ++int str2type(struct match_type_str *table, int length, const char *str, ++ int size, int def); ++ ++const char *type2str(struct match_type_str *table, int length, int type, ++ const char *def); ++ ++int match_reg_to_type(struct match_t *table, int nr_table, int reg, int def); ++ ++int match_type_to_reg(struct match_t *table, int nr_table, int type, int def); ++ ++int match_data_to_type(struct match_t *table, int nr_table, char *data, ++ int size, int def); ++ ++void *match_type_to_data(struct match_t *table, int nr_table, int type, ++ void *def); ++ ++/*****************************************************************************/ ++ ++#endif /* End of __MATCH_TABLE_H__ */ +diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c +index 5b5c627..7a754d2 100644 +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -49,6 +49,8 @@ + #include + #include + ++#include "hinfc_gen.h" ++ + /* Define default oob placement schemes for large and small page devices */ + static struct nand_ecclayout nand_oob_8 = { + .eccbytes = 3, +@@ -3570,7 +3572,7 @@ static void nand_decode_bbm_options(struct mtd_info *mtd, + maf_id == NAND_MFR_HYNIX || + maf_id == NAND_MFR_TOSHIBA || + maf_id == NAND_MFR_AMD || +- maf_id == NAND_MFR_MACRONIX)) || ++ maf_id == NAND_MFR_MXIC)) || + (mtd->writesize == 2048 && + maf_id == NAND_MFR_MICRON)) + chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; +@@ -3589,7 +3591,13 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip, + mtd->erasesize = type->erasesize; + mtd->oobsize = type->oobsize; + ++#ifdef CONFIG_HIFMC100_SPI_NAND ++ /* Hisilicon only support SLC spi nand devices */ ++ chip->bits_per_cell = 1; ++#else + chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]); ++#endif ++ + chip->chipsize = (uint64_t)type->chipsize << 20; + chip->options |= type->options; + chip->ecc_strength_ds = NAND_ECC_STRENGTH(type); +@@ -3615,7 +3623,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, + int *maf_id, int *dev_id, + struct nand_flash_dev *type) + { +- int busw; ++ int busw = 0; + int i, maf_idx; + u8 id_data[8]; + +@@ -3654,6 +3662,15 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, + return ERR_PTR(-ENODEV); + } + ++#ifdef CONFIG_HIFMC ++ if (get_spi_nand_flash_type_hook) ++ type = get_spi_nand_flash_type_hook(mtd, id_data); ++#else ++ type = hinfc_get_flash_type(mtd, chip, id_data, &busw); ++ if (type) ++ goto ident_done; ++#endif ++ + if (!type) + type = nand_flash_ids; + +@@ -3704,6 +3721,9 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, + if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize) + chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; + ident_done: ++#if defined(CONFIG_HIFMC) || defined(CONFIG_MTD_NAND_HINFC610) ++ hinfc_nand_param_adjust(mtd, chip); ++#endif + + /* Try to identify manufacturer */ + for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { +@@ -3765,9 +3785,13 @@ ident_done: + pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, + type->name); + +- pr_info("%dMiB, %s, page size: %d, OOB size: %d\n", ++ pr_info("%dMiB, %s, page size: %d\n", + (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC", +- mtd->writesize, mtd->oobsize); ++ mtd->writesize); ++ ++ /* Print ecc type and ecc mode about hisilicon flash controller */ ++ hinfc_show_info(mtd, nand_manuf_ids[maf_idx].name, type->name); ++ + return type; + } + +@@ -4047,7 +4071,7 @@ int nand_scan_tail(struct mtd_info *mtd) + break; + + case NAND_ECC_NONE: +- pr_warn("NAND_ECC_NONE selected by board driver. This is not recommended!\n"); ++ pr_warn(" ECC provided by Flash Memory Controller\n"); + ecc->read_page = nand_read_page_raw; + ecc->write_page = nand_write_page_raw; + ecc->read_oob = nand_read_oob_std; +diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c +index fbde8910..59b1fba 100644 +--- a/drivers/mtd/nand/nand_ids.c ++++ b/drivers/mtd/nand/nand_ids.c +@@ -165,19 +165,25 @@ struct nand_flash_dev nand_flash_ids[] = { + + /* Manufacturer IDs */ + struct nand_manufacturers nand_manuf_ids[] = { +- {NAND_MFR_TOSHIBA, "Toshiba"}, +- {NAND_MFR_SAMSUNG, "Samsung"}, +- {NAND_MFR_FUJITSU, "Fujitsu"}, +- {NAND_MFR_NATIONAL, "National"}, +- {NAND_MFR_RENESAS, "Renesas"}, +- {NAND_MFR_STMICRO, "ST Micro"}, +- {NAND_MFR_HYNIX, "Hynix"}, +- {NAND_MFR_MICRON, "Micron"}, +- {NAND_MFR_AMD, "AMD/Spansion"}, +- {NAND_MFR_MACRONIX, "Macronix"}, +- {NAND_MFR_EON, "Eon"}, ++ {NAND_MFR_TOSHIBA, "Toshiba"}, ++ {NAND_MFR_SAMSUNG, "Samsung"}, ++ {NAND_MFR_FUJITSU, "Fujitsu"}, ++ {NAND_MFR_NATIONAL, "National"}, ++ {NAND_MFR_RENESAS, "Renesas"}, ++ {NAND_MFR_ST_MICRO, "ST/Micro"}, ++ {NAND_MFR_HYNIX, "Hynix"}, ++ {NAND_MFR_MICRON, "Micron"}, ++ {NAND_MFR_AMD, "AMD/Spansion"}, ++ {NAND_MFR_GD_ESMT, "GD/ESMT"}, ++ {NAND_MFR_EON, "Eon"}, ++ {NAND_MFR_WINBOND, "Winbond"}, ++ {NAND_MFR_ATO, "ATO"}, ++ {NAND_MFR_MXIC, "MXIC"}, ++ {NAND_MFR_ALL_FLASH, "All-flash"}, ++ {NAND_MFR_PARAGON, "Paragon"}, + {NAND_MFR_SANDISK, "SanDisk"}, + {NAND_MFR_INTEL, "Intel"}, ++ {NAND_MFR_HEYANGTEK, "HeYangTek"}, + {0x0, "Unknown"} + }; + +diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig +index 64a4f0e..3d8abfc 100644 +--- a/drivers/mtd/spi-nor/Kconfig ++++ b/drivers/mtd/spi-nor/Kconfig +@@ -23,9 +23,35 @@ config MTD_SPI_NOR_USE_4K_SECTORS + + config SPI_FSL_QUADSPI + tristate "Freescale Quad SPI controller" +- depends on ARCH_MXC ++ depends on ARCH_MXC || COMPILE_TEST ++ depends on HAS_IOMEM + help + This enables support for the Quad SPI controller in master mode. +- We only connect the NOR to this controller now. ++ This controller does not support generic SPI. It only supports ++ SPI NOR. ++ ++config SPI_HISI_SFC ++ tristate "Hisilicon SPI-NOR Flash Controller(SFC)" ++ depends on ARCH_HISI ++ help ++ This enables support for hisilicon SPI-NOR flash controller. ++ ++config CLOSE_SPI_8PIN_4IO ++ bool "Hisilicon close SPI device Quad SPI mode for some 8PIN chip" ++ default y if ARCH_HISI ++ help ++ SFC support Quad SPI mode and Quad&addr SPI mode. ++ But some 8PIN chip does not support this mode when HOLD/IO3 PIN was ++ used by reset operation. Usually, your should not config this option. ++ ++config HISI_SPI_BLOCK_PROTECT ++ bool "Hisilicon Spi Nor Device BP(Block Protect) Support" ++ default y if ARCH_HISI ++ help ++ HISI SFC supports BP(Block Protect) feature to preestablish a series ++ area to avoid writing and erasing, except to reading. With this macro ++ definition we can get the BP info which was setted before. The ++ BOTTOM/TOP bit is setted to BOTTOM, it means the lock area starts ++ from 0 address. + + endif # MTD_SPI_NOR +diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile +index 6a7ce14..4544966 100644 +--- a/drivers/mtd/spi-nor/Makefile ++++ b/drivers/mtd/spi-nor/Makefile +@@ -1,2 +1,3 @@ + obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o + obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o ++obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o +diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c +index d5269a2..df8d001 100644 +--- a/drivers/mtd/spi-nor/fsl-quadspi.c ++++ b/drivers/mtd/spi-nor/fsl-quadspi.c +@@ -26,6 +26,21 @@ + #include + #include + #include ++#include ++#include ++#include ++ ++/* Controller needs driver to swap endian */ ++#define QUADSPI_QUIRK_SWAP_ENDIAN (1 << 0) ++/* Controller needs 4x internal clock */ ++#define QUADSPI_QUIRK_4X_INT_CLK (1 << 1) ++/* ++ * TKT253890, Controller needs driver to fill txfifo till 16 byte to ++ * trigger data transfer even though extern data will not transferred. ++ */ ++#define QUADSPI_QUIRK_TKT253890 (1 << 2) ++/* Controller cannot wake up from wait mode, TKT245618 */ ++#define QUADSPI_QUIRK_TKT245618 (1 << 3) + + /* The registers */ + #define QUADSPI_MCR 0x00 +@@ -57,7 +72,9 @@ + + #define QUADSPI_BUF3CR 0x1c + #define QUADSPI_BUF3CR_ALLMST_SHIFT 31 +-#define QUADSPI_BUF3CR_ALLMST (1 << QUADSPI_BUF3CR_ALLMST_SHIFT) ++#define QUADSPI_BUF3CR_ALLMST_MASK (1 << QUADSPI_BUF3CR_ALLMST_SHIFT) ++#define QUADSPI_BUF3CR_ADATSZ_SHIFT 8 ++#define QUADSPI_BUF3CR_ADATSZ_MASK (0xFF << QUADSPI_BUF3CR_ADATSZ_SHIFT) + + #define QUADSPI_BFGENCR 0x20 + #define QUADSPI_BFGENCR_PAR_EN_SHIFT 16 +@@ -138,15 +155,15 @@ + #define LUT_MODE 4 + #define LUT_MODE2 5 + #define LUT_MODE4 6 +-#define LUT_READ 7 +-#define LUT_WRITE 8 ++#define LUT_FSL_READ 7 ++#define LUT_FSL_WRITE 8 + #define LUT_JMP_ON_CS 9 + #define LUT_ADDR_DDR 10 + #define LUT_MODE_DDR 11 + #define LUT_MODE2_DDR 12 + #define LUT_MODE4_DDR 13 +-#define LUT_READ_DDR 14 +-#define LUT_WRITE_DDR 15 ++#define LUT_FSL_READ_DDR 14 ++#define LUT_FSL_WRITE_DDR 15 + #define LUT_DATA_LEARN 16 + + /* +@@ -189,36 +206,66 @@ + #define SEQID_EN4B 10 + #define SEQID_BRWR 11 + ++#define QUADSPI_MIN_IOMAP SZ_4M ++ + enum fsl_qspi_devtype { + FSL_QUADSPI_VYBRID, + FSL_QUADSPI_IMX6SX, ++ FSL_QUADSPI_IMX7D, ++ FSL_QUADSPI_IMX6UL, + }; + + struct fsl_qspi_devtype_data { + enum fsl_qspi_devtype devtype; + int rxfifo; + int txfifo; ++ int ahb_buf_size; ++ int driver_data; + }; + + static struct fsl_qspi_devtype_data vybrid_data = { + .devtype = FSL_QUADSPI_VYBRID, + .rxfifo = 128, +- .txfifo = 64 ++ .txfifo = 64, ++ .ahb_buf_size = 1024, ++ .driver_data = QUADSPI_QUIRK_SWAP_ENDIAN, + }; + + static struct fsl_qspi_devtype_data imx6sx_data = { + .devtype = FSL_QUADSPI_IMX6SX, + .rxfifo = 128, +- .txfifo = 512 ++ .txfifo = 512, ++ .ahb_buf_size = 1024, ++ .driver_data = QUADSPI_QUIRK_4X_INT_CLK ++ | QUADSPI_QUIRK_TKT245618, ++}; ++ ++static struct fsl_qspi_devtype_data imx7d_data = { ++ .devtype = FSL_QUADSPI_IMX7D, ++ .rxfifo = 512, ++ .txfifo = 512, ++ .ahb_buf_size = 1024, ++ .driver_data = QUADSPI_QUIRK_TKT253890 ++ | QUADSPI_QUIRK_4X_INT_CLK, ++}; ++ ++static struct fsl_qspi_devtype_data imx6ul_data = { ++ .devtype = FSL_QUADSPI_IMX6UL, ++ .rxfifo = 128, ++ .txfifo = 512, ++ .ahb_buf_size = 1024, ++ .driver_data = QUADSPI_QUIRK_TKT253890 ++ | QUADSPI_QUIRK_4X_INT_CLK, + }; + + #define FSL_QSPI_MAX_CHIP 4 + struct fsl_qspi { +- struct mtd_info mtd[FSL_QSPI_MAX_CHIP]; + struct spi_nor nor[FSL_QSPI_MAX_CHIP]; + void __iomem *iobase; +- void __iomem *ahb_base; /* Used when read from AHB bus */ ++ void __iomem *ahb_addr; + u32 memmap_phy; ++ u32 memmap_offs; ++ u32 memmap_len; + struct clk *clk, *clk_en; + struct device *dev; + struct completion c; +@@ -227,16 +274,29 @@ struct fsl_qspi { + u32 nor_num; + u32 clk_rate; + unsigned int chip_base_addr; /* We may support two chips. */ ++ bool has_second_chip; ++ struct mutex lock; ++ struct pm_qos_request pm_qos_req; + }; + +-static inline int is_vybrid_qspi(struct fsl_qspi *q) ++static inline int needs_swap_endian(struct fsl_qspi *q) + { +- return q->devtype_data->devtype == FSL_QUADSPI_VYBRID; ++ return q->devtype_data->driver_data & QUADSPI_QUIRK_SWAP_ENDIAN; + } + +-static inline int is_imx6sx_qspi(struct fsl_qspi *q) ++static inline int needs_4x_clock(struct fsl_qspi *q) + { +- return q->devtype_data->devtype == FSL_QUADSPI_IMX6SX; ++ return q->devtype_data->driver_data & QUADSPI_QUIRK_4X_INT_CLK; ++} ++ ++static inline int needs_fill_txfifo(struct fsl_qspi *q) ++{ ++ return q->devtype_data->driver_data & QUADSPI_QUIRK_TKT253890; ++} ++ ++static inline int needs_wakeup_wait_mode(struct fsl_qspi *q) ++{ ++ return q->devtype_data->driver_data & QUADSPI_QUIRK_TKT245618; + } + + /* +@@ -245,7 +305,7 @@ static inline int is_imx6sx_qspi(struct fsl_qspi *q) + */ + static inline u32 fsl_qspi_endian_xchg(struct fsl_qspi *q, u32 a) + { +- return is_vybrid_qspi(q) ? __swab32(a) : a; ++ return needs_swap_endian(q) ? __swab32(a) : a; + } + + static inline void fsl_qspi_unlock_lut(struct fsl_qspi *q) +@@ -306,7 +366,7 @@ static void fsl_qspi_init_lut(struct fsl_qspi *q) + + writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen), + base + QUADSPI_LUT(lut_base)); +- writel(LUT0(DUMMY, PAD1, dummy) | LUT1(READ, PAD4, rxfifo), ++ writel(LUT0(DUMMY, PAD1, dummy) | LUT1(FSL_READ, PAD4, rxfifo), + base + QUADSPI_LUT(lut_base + 1)); + + /* Write enable */ +@@ -327,24 +387,18 @@ static void fsl_qspi_init_lut(struct fsl_qspi *q) + + writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen), + base + QUADSPI_LUT(lut_base)); +- writel(LUT0(WRITE, PAD1, 0), base + QUADSPI_LUT(lut_base + 1)); ++ writel(LUT0(FSL_WRITE, PAD1, 0), base + QUADSPI_LUT(lut_base + 1)); + + /* Read Status */ + lut_base = SEQID_RDSR * 4; +- writel(LUT0(CMD, PAD1, SPINOR_OP_RDSR) | LUT1(READ, PAD1, 0x1), ++ writel(LUT0(CMD, PAD1, SPINOR_OP_RDSR) | LUT1(FSL_READ, PAD1, 0x1), + base + QUADSPI_LUT(lut_base)); + + /* Erase a sector */ + lut_base = SEQID_SE * 4; + +- if (q->nor_size <= SZ_16M) { +- cmd = SPINOR_OP_SE; +- addrlen = ADDR24BIT; +- } else { +- /* use the 4-byte address */ +- cmd = SPINOR_OP_SE; +- addrlen = ADDR32BIT; +- } ++ cmd = q->nor[0].erase_opcode; ++ addrlen = q->nor_size <= SZ_16M ? ADDR24BIT : ADDR32BIT; + + writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen), + base + QUADSPI_LUT(lut_base)); +@@ -356,17 +410,17 @@ static void fsl_qspi_init_lut(struct fsl_qspi *q) + + /* READ ID */ + lut_base = SEQID_RDID * 4; +- writel(LUT0(CMD, PAD1, SPINOR_OP_RDID) | LUT1(READ, PAD1, 0x8), ++ writel(LUT0(CMD, PAD1, SPINOR_OP_RDID) | LUT1(FSL_READ, PAD1, 0x8), + base + QUADSPI_LUT(lut_base)); + + /* Write Register */ + lut_base = SEQID_WRSR * 4; +- writel(LUT0(CMD, PAD1, SPINOR_OP_WRSR) | LUT1(WRITE, PAD1, 0x2), ++ writel(LUT0(CMD, PAD1, SPINOR_OP_WRSR) | LUT1(FSL_WRITE, PAD1, 0x2), + base + QUADSPI_LUT(lut_base)); + + /* Read Configuration Register */ + lut_base = SEQID_RDCR * 4; +- writel(LUT0(CMD, PAD1, SPINOR_OP_RDCR) | LUT1(READ, PAD1, 0x1), ++ writel(LUT0(CMD, PAD1, SPINOR_OP_RDCR) | LUT1(FSL_READ, PAD1, 0x1), + base + QUADSPI_LUT(lut_base)); + + /* Write disable */ +@@ -413,6 +467,8 @@ static int fsl_qspi_get_seqid(struct fsl_qspi *q, u8 cmd) + case SPINOR_OP_BRWR: + return SEQID_BRWR; + default: ++ if (cmd == q->nor[0].erase_opcode) ++ return SEQID_SE; + dev_err(q->dev, "Unsupported cmd 0x%.2x\n", cmd); + break; + } +@@ -454,8 +510,7 @@ fsl_qspi_runcmd(struct fsl_qspi *q, u8 cmd, unsigned int addr, int len) + writel((seqid << QUADSPI_IPCR_SEQID_SHIFT) | len, base + QUADSPI_IPCR); + + /* Wait for the interrupt. */ +- err = wait_for_completion_timeout(&q->c, msecs_to_jiffies(1000)); +- if (!err) { ++ if (!wait_for_completion_timeout(&q->c, msecs_to_jiffies(1000))) { + dev_err(q->dev, + "cmd 0x%.2x timeout, addr@%.8x, FR:0x%.8x, SR:0x%.8x\n", + cmd, addr, readl(base + QUADSPI_FR), +@@ -532,7 +587,7 @@ static int fsl_qspi_nor_write(struct fsl_qspi *q, struct spi_nor *nor, + + /* clear the TX FIFO. */ + tmp = readl(q->iobase + QUADSPI_MCR); +- writel(tmp | QUADSPI_MCR_CLR_RXF_MASK, q->iobase + QUADSPI_MCR); ++ writel(tmp | QUADSPI_MCR_CLR_TXF_MASK, q->iobase + QUADSPI_MCR); + + /* fill the TX data to the FIFO */ + for (j = 0, i = ((count + 3) / 4); j < i; j++) { +@@ -541,6 +596,11 @@ static int fsl_qspi_nor_write(struct fsl_qspi *q, struct spi_nor *nor, + txbuf++; + } + ++ /* fill the TXFIFO upto 16 bytes for i.MX7d */ ++ if (needs_fill_txfifo(q)) ++ for (; i < 4; i++) ++ writel(tmp, q->iobase + QUADSPI_TBDR); ++ + /* Trigger it */ + ret = fsl_qspi_runcmd(q, opcode, to, count); + +@@ -583,7 +643,12 @@ static void fsl_qspi_init_abh_read(struct fsl_qspi *q) + writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF0CR); + writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF1CR); + writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF2CR); +- writel(QUADSPI_BUF3CR_ALLMST, base + QUADSPI_BUF3CR); ++ /* ++ * Set ADATSZ with the maximum AHB buffer size to improve the ++ * read performance. ++ */ ++ writel(QUADSPI_BUF3CR_ALLMST_MASK | ((q->devtype_data->ahb_buf_size / 8) ++ << QUADSPI_BUF3CR_ADATSZ_SHIFT), base + QUADSPI_BUF3CR); + + /* We only use the buffer3 */ + writel(0, base + QUADSPI_BUF0IND); +@@ -596,6 +661,38 @@ static void fsl_qspi_init_abh_read(struct fsl_qspi *q) + q->iobase + QUADSPI_BFGENCR); + } + ++/* This function was used to prepare and enable QSPI clock */ ++static int fsl_qspi_clk_prep_enable(struct fsl_qspi *q) ++{ ++ int ret; ++ ++ ret = clk_prepare_enable(q->clk_en); ++ if (ret) ++ return ret; ++ ++ ret = clk_prepare_enable(q->clk); ++ if (ret) { ++ clk_disable_unprepare(q->clk_en); ++ return ret; ++ } ++ ++ if (needs_wakeup_wait_mode(q)) ++ pm_qos_add_request(&q->pm_qos_req, PM_QOS_CPU_DMA_LATENCY, 0); ++ ++ return 0; ++} ++ ++/* This function was used to disable and unprepare QSPI clock */ ++static void fsl_qspi_clk_disable_unprep(struct fsl_qspi *q) ++{ ++ if (needs_wakeup_wait_mode(q)) ++ pm_qos_remove_request(&q->pm_qos_req); ++ ++ clk_disable_unprepare(q->clk); ++ clk_disable_unprepare(q->clk_en); ++ ++} ++ + /* We use this function to do some basic init for spi_nor_scan(). */ + static int fsl_qspi_nor_setup(struct fsl_qspi *q) + { +@@ -603,11 +700,23 @@ static int fsl_qspi_nor_setup(struct fsl_qspi *q) + u32 reg; + int ret; + +- /* the default frequency, we will change it in the future.*/ ++ /* disable and unprepare clock to avoid glitch pass to controller */ ++ fsl_qspi_clk_disable_unprep(q); ++ ++ /* the default frequency, we will change it in the future. */ + ret = clk_set_rate(q->clk, 66000000); + if (ret) + return ret; + ++ ret = fsl_qspi_clk_prep_enable(q); ++ if (ret) ++ return ret; ++ ++ /* Reset the module */ ++ writel(QUADSPI_MCR_SWRSTSD_MASK | QUADSPI_MCR_SWRSTHD_MASK, ++ base + QUADSPI_MCR); ++ udelay(1); ++ + /* Init the LUT table. */ + fsl_qspi_init_lut(q); + +@@ -625,6 +734,9 @@ static int fsl_qspi_nor_setup(struct fsl_qspi *q) + writel(QUADSPI_MCR_RESERVED_MASK | QUADSPI_MCR_END_CFG_MASK, + base + QUADSPI_MCR); + ++ /* clear all interrupt status */ ++ writel(0xffffffff, q->iobase + QUADSPI_FR); ++ + /* enable the interrupt */ + writel(QUADSPI_RSER_TFIE, q->iobase + QUADSPI_RSER); + +@@ -636,13 +748,20 @@ static int fsl_qspi_nor_setup_last(struct fsl_qspi *q) + unsigned long rate = q->clk_rate; + int ret; + +- if (is_imx6sx_qspi(q)) ++ if (needs_4x_clock(q)) + rate *= 4; + ++ /* disable and unprepare clock to avoid glitch pass to controller */ ++ fsl_qspi_clk_disable_unprep(q); ++ + ret = clk_set_rate(q->clk, rate); + if (ret) + return ret; + ++ ret = fsl_qspi_clk_prep_enable(q); ++ if (ret) ++ return ret; ++ + /* Init the LUT table again. */ + fsl_qspi_init_lut(q); + +@@ -652,9 +771,11 @@ static int fsl_qspi_nor_setup_last(struct fsl_qspi *q) + return 0; + } + +-static struct of_device_id fsl_qspi_dt_ids[] = { ++static const struct of_device_id fsl_qspi_dt_ids[] = { + { .compatible = "fsl,vf610-qspi", .data = (void *)&vybrid_data, }, + { .compatible = "fsl,imx6sx-qspi", .data = (void *)&imx6sx_data, }, ++ { .compatible = "fsl,imx7d-qspi", .data = (void *)&imx7d_data, }, ++ { .compatible = "fsl,imx6ul-qspi", .data = (void *)&imx6ul_data, }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, fsl_qspi_dt_ids); +@@ -677,8 +798,7 @@ static int fsl_qspi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) + return 0; + } + +-static int fsl_qspi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len, +- int write_enable) ++static int fsl_qspi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) + { + struct fsl_qspi *q = nor->priv; + int ret; +@@ -719,18 +839,45 @@ static int fsl_qspi_read(struct spi_nor *nor, loff_t from, + { + struct fsl_qspi *q = nor->priv; + u8 cmd = nor->read_opcode; +- int ret; + +- dev_dbg(q->dev, "cmd [%x],read from (0x%p, 0x%.8x, 0x%.8x),len:%d\n", +- cmd, q->ahb_base, q->chip_base_addr, (unsigned int)from, len); ++ /* if necessary,ioremap buffer before AHB read, */ ++ if (!q->ahb_addr) { ++ q->memmap_offs = q->chip_base_addr + from; ++ q->memmap_len = ++ len > QUADSPI_MIN_IOMAP ? len : QUADSPI_MIN_IOMAP; ++ ++ q->ahb_addr = ioremap_nocache( ++ q->memmap_phy + q->memmap_offs, ++ q->memmap_len); ++ if (!q->ahb_addr) { ++ dev_err(q->dev, "ioremap failed\n"); ++ return -ENOMEM; ++ } ++ /* ioremap if the data requested is out of range */ ++ } else if (q->chip_base_addr + from < q->memmap_offs ++ || q->chip_base_addr + from + len > ++ q->memmap_offs + q->memmap_len) { ++ iounmap(q->ahb_addr); ++ ++ q->memmap_offs = q->chip_base_addr + from; ++ q->memmap_len = ++ len > QUADSPI_MIN_IOMAP ? len : QUADSPI_MIN_IOMAP; ++ q->ahb_addr = ioremap_nocache( ++ q->memmap_phy + q->memmap_offs, ++ q->memmap_len); ++ if (!q->ahb_addr) { ++ dev_err(q->dev, "ioremap failed\n"); ++ return -ENOMEM; ++ } ++ } + +- /* Wait until the previous command is finished. */ +- ret = nor->wait_till_ready(nor); +- if (ret) +- return ret; ++ dev_dbg(q->dev, "cmd [%x],read from %p, len:%zd\n", ++ cmd, q->ahb_addr + q->chip_base_addr + from - q->memmap_offs, ++ len); + + /* Read out the data directly from the AHB buffer.*/ +- memcpy(buf, q->ahb_base + q->chip_base_addr + from, len); ++ memcpy(buf, q->ahb_addr + q->chip_base_addr + from - q->memmap_offs, ++ len); + + *retlen += len; + return 0; +@@ -742,17 +889,7 @@ static int fsl_qspi_erase(struct spi_nor *nor, loff_t offs) + int ret; + + dev_dbg(nor->dev, "%dKiB at 0x%08x:0x%08x\n", +- nor->mtd->erasesize / 1024, q->chip_base_addr, (u32)offs); +- +- /* Wait until finished previous write command. */ +- ret = nor->wait_till_ready(nor); +- if (ret) +- return ret; +- +- /* Send write enable, then erase commands. */ +- ret = nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0, 0); +- if (ret) +- return ret; ++ nor->mtd.erasesize / 1024, q->chip_base_addr, (u32)offs); + + ret = fsl_qspi_runcmd(q, nor->erase_opcode, offs, 0); + if (ret) +@@ -767,26 +904,26 @@ static int fsl_qspi_prep(struct spi_nor *nor, enum spi_nor_ops ops) + struct fsl_qspi *q = nor->priv; + int ret; + +- ret = clk_enable(q->clk_en); +- if (ret) +- return ret; ++ mutex_lock(&q->lock); + +- ret = clk_enable(q->clk); +- if (ret) { +- clk_disable(q->clk_en); +- return ret; +- } ++ ret = fsl_qspi_clk_prep_enable(q); ++ if (ret) ++ goto err_mutex; + + fsl_qspi_set_base_addr(q, nor); + return 0; ++ ++err_mutex: ++ mutex_unlock(&q->lock); ++ return ret; + } + + static void fsl_qspi_unprep(struct spi_nor *nor, enum spi_nor_ops ops) + { + struct fsl_qspi *q = nor->priv; + +- clk_disable(q->clk); +- clk_disable(q->clk_en); ++ fsl_qspi_clk_disable_unprep(q); ++ mutex_unlock(&q->lock); + } + + static int fsl_qspi_probe(struct platform_device *pdev) +@@ -799,7 +936,6 @@ static int fsl_qspi_probe(struct platform_device *pdev) + struct spi_nor *nor; + struct mtd_info *mtd; + int ret, i = 0; +- bool has_second_chip = false; + const struct of_device_id *of_id = + of_match_device(fsl_qspi_dt_ids, &pdev->dev); + +@@ -811,89 +947,76 @@ static int fsl_qspi_probe(struct platform_device *pdev) + if (!q->nor_num || q->nor_num > FSL_QSPI_MAX_CHIP) + return -ENODEV; + ++ q->dev = dev; ++ q->devtype_data = (struct fsl_qspi_devtype_data *)of_id->data; ++ platform_set_drvdata(pdev, q); ++ + /* find the resources */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI"); + q->iobase = devm_ioremap_resource(dev, res); +- if (IS_ERR(q->iobase)) { +- ret = PTR_ERR(q->iobase); +- goto map_failed; +- } ++ if (IS_ERR(q->iobase)) ++ return PTR_ERR(q->iobase); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "QuadSPI-memory"); +- q->ahb_base = devm_ioremap_resource(dev, res); +- if (IS_ERR(q->ahb_base)) { +- ret = PTR_ERR(q->ahb_base); +- goto map_failed; ++ if (!devm_request_mem_region(dev, res->start, resource_size(res), ++ res->name)) { ++ dev_err(dev, "can't request region for resource %pR\n", res); ++ return -EBUSY; + } ++ + q->memmap_phy = res->start; + + /* find the clocks */ + q->clk_en = devm_clk_get(dev, "qspi_en"); +- if (IS_ERR(q->clk_en)) { +- ret = PTR_ERR(q->clk_en); +- goto map_failed; +- } ++ if (IS_ERR(q->clk_en)) ++ return PTR_ERR(q->clk_en); + + q->clk = devm_clk_get(dev, "qspi"); +- if (IS_ERR(q->clk)) { +- ret = PTR_ERR(q->clk); +- goto map_failed; +- } +- +- ret = clk_prepare_enable(q->clk_en); +- if (ret) { +- dev_err(dev, "can not enable the qspi_en clock\n"); +- goto map_failed; +- } ++ if (IS_ERR(q->clk)) ++ return PTR_ERR(q->clk); + +- ret = clk_prepare_enable(q->clk); ++ ret = fsl_qspi_clk_prep_enable(q); + if (ret) { +- clk_disable_unprepare(q->clk_en); +- dev_err(dev, "can not enable the qspi clock\n"); +- goto map_failed; ++ dev_err(dev, "can not enable the clock\n"); ++ goto clk_failed; + } + + /* find the irq */ + ret = platform_get_irq(pdev, 0); + if (ret < 0) { +- dev_err(dev, "failed to get the irq\n"); ++ dev_err(dev, "failed to get the irq: %d\n", ret); + goto irq_failed; + } + + ret = devm_request_irq(dev, ret, + fsl_qspi_irq_handler, 0, pdev->name, q); + if (ret) { +- dev_err(dev, "failed to request irq.\n"); ++ dev_err(dev, "failed to request irq: %d\n", ret); + goto irq_failed; + } + +- q->dev = dev; +- q->devtype_data = (struct fsl_qspi_devtype_data *)of_id->data; +- platform_set_drvdata(pdev, q); +- + ret = fsl_qspi_nor_setup(q); + if (ret) + goto irq_failed; + + if (of_get_property(np, "fsl,qspi-has-second-chip", NULL)) +- has_second_chip = true; ++ q->has_second_chip = true; ++ ++ mutex_init(&q->lock); + + /* iterate the subnodes. */ + for_each_available_child_of_node(dev->of_node, np) { +- char modalias[40]; +- + /* skip the holes */ +- if (!has_second_chip) ++ if (!q->has_second_chip) + i *= 2; + + nor = &q->nor[i]; +- mtd = &q->mtd[i]; ++ mtd = &nor->mtd; + +- nor->mtd = mtd; + nor->dev = dev; ++ nor->flash_node = np; + nor->priv = q; +- mtd->priv = nor; + + /* fill the hooks */ + nor->read_reg = fsl_qspi_read_reg; +@@ -905,25 +1028,22 @@ static int fsl_qspi_probe(struct platform_device *pdev) + nor->prepare = fsl_qspi_prep; + nor->unprepare = fsl_qspi_unprep; + +- if (of_modalias_node(np, modalias, sizeof(modalias)) < 0) +- goto map_failed; +- + ret = of_property_read_u32(np, "spi-max-frequency", + &q->clk_rate); + if (ret < 0) +- goto map_failed; ++ goto mutex_failed; + + /* set the chip address for READID */ + fsl_qspi_set_base_addr(q, nor); + +- ret = spi_nor_scan(nor, modalias, SPI_NOR_QUAD); ++ ret = spi_nor_scan(nor, NULL, SPI_NOR_QUAD); + if (ret) +- goto map_failed; ++ goto mutex_failed; + + ppdata.of_node = np; + ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); + if (ret) +- goto map_failed; ++ goto mutex_failed; + + /* Set the correct NOR size now. */ + if (q->nor_size == 0) { +@@ -953,19 +1073,21 @@ static int fsl_qspi_probe(struct platform_device *pdev) + if (ret) + goto last_init_failed; + +- clk_disable(q->clk); +- clk_disable(q->clk_en); +- dev_info(dev, "QuadSPI SPI NOR flash driver\n"); ++ fsl_qspi_clk_disable_unprep(q); + return 0; + + last_init_failed: +- for (i = 0; i < q->nor_num; i++) +- mtd_device_unregister(&q->mtd[i]); +- ++ for (i = 0; i < q->nor_num; i++) { ++ /* skip the holes */ ++ if (!q->has_second_chip) ++ i *= 2; ++ mtd_device_unregister(&q->nor[i].mtd); ++ } ++mutex_failed: ++ mutex_destroy(&q->lock); + irq_failed: +- clk_disable_unprepare(q->clk); +- clk_disable_unprepare(q->clk_en); +-map_failed: ++ fsl_qspi_clk_disable_unprep(q); ++clk_failed: + dev_err(dev, "Freescale QuadSPI probe failed\n"); + return ret; + } +@@ -975,15 +1097,45 @@ static int fsl_qspi_remove(struct platform_device *pdev) + struct fsl_qspi *q = platform_get_drvdata(pdev); + int i; + +- for (i = 0; i < q->nor_num; i++) +- mtd_device_unregister(&q->mtd[i]); ++ for (i = 0; i < q->nor_num; i++) { ++ /* skip the holes */ ++ if (!q->has_second_chip) ++ i *= 2; ++ mtd_device_unregister(&q->nor[i].mtd); ++ } + + /* disable the hardware */ + writel(QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR); + writel(0x0, q->iobase + QUADSPI_RSER); + +- clk_unprepare(q->clk); +- clk_unprepare(q->clk_en); ++ mutex_destroy(&q->lock); ++ ++ if (q->ahb_addr) ++ iounmap(q->ahb_addr); ++ ++ return 0; ++} ++ ++static int fsl_qspi_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ return 0; ++} ++ ++static int fsl_qspi_resume(struct platform_device *pdev) ++{ ++ int ret; ++ struct fsl_qspi *q = platform_get_drvdata(pdev); ++ ++ ret = fsl_qspi_clk_prep_enable(q); ++ if (ret) ++ return ret; ++ ++ fsl_qspi_nor_setup(q); ++ fsl_qspi_set_map_addr(q); ++ fsl_qspi_nor_setup_last(q); ++ ++ fsl_qspi_clk_disable_unprep(q); ++ + return 0; + } + +@@ -991,11 +1143,12 @@ static struct platform_driver fsl_qspi_driver = { + .driver = { + .name = "fsl-quadspi", + .bus = &platform_bus_type, +- .owner = THIS_MODULE, + .of_match_table = fsl_qspi_dt_ids, + }, + .probe = fsl_qspi_probe, + .remove = fsl_qspi_remove, ++ .suspend = fsl_qspi_suspend, ++ .resume = fsl_qspi_resume, + }; + module_platform_driver(fsl_qspi_driver); + +diff --git a/drivers/mtd/spi-nor/hisi-sfc.c b/drivers/mtd/spi-nor/hisi-sfc.c +new file mode 100644 +index 0000000..b7181ef +--- /dev/null ++++ b/drivers/mtd/spi-nor/hisi-sfc.c +@@ -0,0 +1,593 @@ ++/* ++ * HiSilicon SPI Nor Flash Controller Driver ++ * ++ * Copyright (c) 2015-2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../mtdcore.h" ++ ++#define FMC_OP_DMA 0x68 ++ ++struct hifmc_priv { ++ u32 chipselect; ++ u32 clkrate; ++ struct hifmc_host *host; ++}; ++ ++struct hifmc_host { ++ struct device *dev; ++ struct mutex *lock; ++ ++ void __iomem *regbase; ++ void __iomem *iobase; ++ struct clk *clk; ++ void *buffer; ++ dma_addr_t dma_buffer; ++ ++ struct spi_nor *nor[HIFMC_MAX_CHIP_NUM]; ++ struct hifmc_priv priv[HIFMC_MAX_CHIP_NUM]; ++ int num_chip; ++}; ++ ++/******************************************************************************/ ++static inline int wait_op_finish(struct hifmc_host *host) ++{ ++ unsigned int reg, timeout = FMC_WAIT_TIMEOUT; ++ ++ do { ++ reg = hifmc_readl(host, FMC_INT); ++ } while (!(reg & FMC_INT_OP_DONE) && --timeout); ++ ++ if (!timeout) { ++ dev_dbg(host->dev, "wait for operation finish timeout\n"); ++ return -EAGAIN; ++ } ++ ++ return 0; ++} ++ ++static int get_if_type(enum spi_nor_protocol mode) ++{ ++ enum hifmc_iftype if_type; ++ ++ switch (mode) { ++ case SNOR_PROTO_1_1_2: ++ if_type = IF_TYPE_DUAL; ++ break; ++ case SNOR_PROTO_1_2_2: ++ if_type = IF_TYPE_DIO; ++ break; ++ case SNOR_PROTO_1_1_4: ++ if_type = IF_TYPE_QUAD; ++ break; ++ case SNOR_PROTO_1_4_4: ++ if_type = IF_TYPE_QIO; ++ break; ++ case SNOR_PROTO_1_1_1: ++ default: ++ if_type = IF_TYPE_STD; ++ break; ++ } ++ ++ return if_type; ++} ++ ++/******************************************************************************/ ++static void spi_nor_switch_spi_type(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ reg = hifmc_readl(host, FMC_CFG); ++ reg &= ~FLASH_TYPE_SEL_MASK; ++ reg |= FMC_CFG_FLASH_SEL(0); ++ hifmc_writel(host, FMC_CFG, reg); ++} ++ ++/******************************************************************************/ ++static void hisi_spi_nor_init(struct hifmc_host *host) ++{ ++ unsigned int reg; ++ ++ /* switch the flash type to spi nor */ ++ spi_nor_switch_spi_type(host); ++ ++ /* set the boot mode to normal */ ++ reg = hifmc_readl(host, FMC_CFG); ++ if ((reg & FMC_CFG_OP_MODE_MASK) == FMC_CFG_OP_MODE_BOOT) { ++ reg |= FMC_CFG_OP_MODE(FMC_CFG_OP_MODE_NORMAL); ++ hifmc_writel(host, FMC_CFG, reg); ++ } ++ ++ /* hold on STR mode */ ++ reg = hifmc_readl(host, FMC_GLOBAL_CFG); ++ reg &= (~FMC_GLOBAL_CFG_DTR_MODE); ++ hifmc_writel(host, FMC_GLOBAL_CFG, reg); ++ ++ /* set timming */ ++ reg = TIMING_CFG_TCSH(CS_HOLD_TIME) ++ | TIMING_CFG_TCSS(CS_SETUP_TIME) ++ | TIMING_CFG_TSHSL(CS_DESELECT_TIME); ++ hifmc_writel(host, FMC_SPI_TIMING_CFG, reg); ++} ++ ++/******************************************************************************/ ++static int hisi_spi_nor_prep(struct spi_nor *nor, enum spi_nor_ops ops) ++{ ++ int ret; ++ u32 clkrate; ++ struct hifmc_priv *priv = nor->priv; ++ struct hifmc_host *host = priv->host; ++ ++ mutex_lock(&fmc_switch_mutex); ++ mutex_lock(host->lock); ++ ++ ret = clk_prepare_enable(host->clk); ++ if (ret) ++ goto out; ++ ++ clkrate = min_t(u32, priv->clkrate, nor->clkrate); ++ ret = clk_set_rate(host->clk, clkrate); ++ if (ret) ++ goto out; ++ ++ spi_nor_switch_spi_type(host); ++ ++ return 0; ++ ++out: ++ mutex_unlock(host->lock); ++ return ret; ++} ++ ++/******************************************************************************/ ++static void hisi_spi_nor_unprep(struct spi_nor *nor, enum spi_nor_ops ops) ++{ ++ struct hifmc_priv *priv = nor->priv; ++ struct hifmc_host *host = priv->host; ++ ++ clk_disable_unprepare(host->clk); ++ mutex_unlock(host->lock); ++ mutex_unlock(&fmc_switch_mutex); ++} ++ ++/******************************************************************************/ ++static int hisi_spi_nor_op_reg(struct spi_nor *nor, u8 opcode, int len, u8 optype) ++{ ++ struct hifmc_priv *priv = nor->priv; ++ struct hifmc_host *host = priv->host; ++ u32 reg; ++ ++ reg = FMC_CMD_CMD1(opcode); ++ hifmc_writel(host, FMC_CMD, reg); ++ ++ reg = FMC_DATA_NUM_CNT(len); ++ hifmc_writel(host, FMC_DATA_NUM, reg); ++ ++ reg = OP_CFG_FM_CS(priv->chipselect); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ ++ hifmc_writel(host, FMC_INT_CLR, 0xff); ++ reg = FMC_OP_CMD1_EN; ++ if (optype == FMC_OP_READ) ++ reg |= FMC_OP_READ_DATA_EN; ++ else ++ reg |= FMC_OP_WRITE_DATA_EN; ++ reg |= FMC_OP_REG_OP_START; ++ hifmc_writel(host, FMC_OP, reg); ++ ++ return wait_op_finish(host); ++} ++ ++/******************************************************************************/ ++static int hisi_spi_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, ++ int len) ++{ ++ struct hifmc_priv *priv = nor->priv; ++ struct hifmc_host *host = priv->host; ++ int ret; ++ ++ ret = hisi_spi_nor_op_reg(nor, opcode, len, FMC_OP_READ); ++ if (ret) ++ return ret; ++ ++ memcpy_fromio(buf, host->iobase, len); ++ return 0; ++} ++ ++/******************************************************************************/ ++static int hisi_spi_nor_write_reg(struct spi_nor *nor, u8 opcode, ++ u8 *buf, int len) ++{ ++ struct hifmc_priv *priv = nor->priv; ++ struct hifmc_host *host = priv->host; ++ ++ if (len) ++ memcpy_toio(host->iobase, buf, len); ++ ++ return hisi_spi_nor_op_reg(nor, opcode, len, FMC_OP_WRITE); ++} ++ ++/******************************************************************************/ ++static int hisi_spi_nor_dma_transfer(struct spi_nor *nor, loff_t start_off, ++ dma_addr_t dma_buf, size_t len, u8 op_type) ++{ ++ struct hifmc_priv *priv = nor->priv; ++ struct hifmc_host *host = priv->host; ++ u8 if_type = 0, dummy = 0; ++ u32 reg; ++ ++ reg = hifmc_readl(host, FMC_CFG); ++ reg &= ~SPI_NOR_ADDR_MODE_MASK; ++ if (nor->addr_width == 4) ++ reg |= SPI_NOR_ADDR_MODE_4BYTES; ++ else ++ reg |= SPI_NOR_ADDR_MODE_3BYTES; ++ hifmc_writel(host, FMC_CFG, reg); ++ hifmc_writel(host, FMC_ADDRL, start_off); ++ hifmc_writel(host, FMC_DMA_SADDR_D0, dma_buf); ++ hifmc_writel(host, FMC_DMA_LEN, FMC_DMA_LEN_SET(len)); ++ ++ reg = OP_CFG_FM_CS(priv->chipselect); ++ if (op_type == FMC_OP_READ) { ++ if_type = get_if_type(nor->read_proto); ++ dummy = nor->read_dummy >> 3; ++ } else { ++ if_type = get_if_type(nor->write_proto); ++ } ++ reg |= OP_CFG_MEM_IF_TYPE(if_type) ++ | OP_CFG_DUMMY_NUM(dummy); ++ hifmc_writel(host, FMC_OP_CFG, reg); ++ ++ hifmc_writel(host, FMC_INT_CLR, 0xff); ++ reg = OP_CTRL_RW_OP(op_type) | OP_CTRL_DMA_OP_READY; ++ if (op_type == FMC_OP_READ) ++ reg |= OP_CTRL_RD_OPCODE(nor->read_opcode); ++ else ++ reg |= OP_CTRL_WR_OPCODE(nor->program_opcode); ++ hifmc_writel(host, FMC_OP_DMA, reg); ++ ++ return wait_op_finish(host); ++} ++ ++/******************************************************************************/ ++static int hisi_spi_nor_read(struct spi_nor *nor, loff_t from, size_t len, ++ size_t *retlen, u_char *read_buf) ++{ ++ struct hifmc_priv *priv = nor->priv; ++ struct hifmc_host *host = priv->host; ++ size_t offset; ++ int ret; ++ ++ for (offset = 0; offset < len; offset += HIFMC_DMA_MAX_LEN) { ++ size_t trans = min_t(size_t, HIFMC_DMA_MAX_LEN, len - offset); ++ ++ ret = hisi_spi_nor_dma_transfer(nor, from + offset, ++ host->dma_buffer, trans, FMC_OP_READ); ++ if (ret) { ++ dev_warn(nor->dev, "DMA read timeout\n"); ++ return ret; ++ } ++ memcpy(read_buf + offset, host->buffer, trans); ++ *retlen += trans; ++ } ++ ++ return 0; ++} ++/******************************************************************************/ ++static void hisi_spi_nor_write(struct spi_nor *nor, loff_t to, ++ size_t len, size_t *retlen, const u_char *write_buf) ++{ ++ struct hifmc_priv *priv = nor->priv; ++ struct hifmc_host *host = priv->host; ++ int ret; ++ ++ memcpy(host->buffer, write_buf, len); ++ ret = hisi_spi_nor_dma_transfer(nor, to, host->dma_buffer, ++ len, FMC_OP_WRITE); ++ if (ret) { ++ dev_warn(nor->dev, "DMA write timeout\n"); ++ return; ++ } ++ *retlen += len; ++} ++ ++/** ++ * parse partitions info and register spi flash device as mtd device. ++ */ ++static int hisi_snor_device_register(struct mtd_info *mtd) ++{ ++ int nr_parts = 0; ++ struct mtd_partition *parts = NULL; ++ static const char *part_probes[] = {"cmdlinepart", NULL, }; ++ ++ /* We do not add the whole spi flash as a mtdblock device, ++ * To avoid the number of nand partition +1. ++ */ ++ nr_parts = parse_mtd_partitions(mtd, part_probes, &parts, 0); ++ ++ return nr_parts ? mtd_device_register(mtd, parts, nr_parts) : nr_parts; ++} ++ ++/** ++ * Get spi flash device information and register it as a mtd device. ++ */ ++static int hisi_spi_nor_register(struct device_node *np, ++ struct hifmc_host *host) ++{ ++ struct device *dev = host->dev; ++ struct spi_nor *nor; ++ struct hifmc_priv *priv = &host->priv[host->num_chip]; ++ struct mtd_info *mtd; ++ int ret; ++ struct spi_nor_modes modes = { ++ .rd_modes = SNOR_MODE_SLOW, ++ .wr_modes = SNOR_MODE_1_1_1, ++ }; ++ ++ nor = devm_kzalloc(dev, sizeof(*nor), GFP_KERNEL); ++ if (!nor) ++ return -ENOMEM; ++ ++ nor->dev = dev; ++ nor->flash_node = np; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ ret = of_property_read_u32(np, "reg", &priv->chipselect); ++ if (ret) { ++ dev_err(dev, "There's no reg property for %s\n", ++ np->full_name); ++ return ret; ++ } ++ ++ if (priv->chipselect != host->num_chip) { ++ dev_warn(dev, " The CS: %d states in device trees isn't real " \ ++ "chipselect on board\n, using CS: %d instead. ", ++ priv->chipselect, host->num_chip); ++ priv->chipselect = host->num_chip; ++ } ++ ++ ret = of_property_read_u32(np, "spi-max-frequency", ++ &priv->clkrate); ++ if (ret) { ++ dev_err(dev, "There's no spi-max-frequency property for %s\n", ++ np->full_name); ++ return ret; ++ } ++ priv->host = host; ++ nor->priv = priv; ++ ++ nor->prepare = hisi_spi_nor_prep; ++ nor->unprepare = hisi_spi_nor_unprep; ++ nor->read_reg = hisi_spi_nor_read_reg; ++ nor->write_reg = hisi_spi_nor_write_reg; ++ nor->read = hisi_spi_nor_read; ++ nor->write = hisi_spi_nor_write; ++ ++ modes.rd_modes |= SNOR_MODE_1_1_1 ++ | SNOR_MODE_1_1_2 ++ | SNOR_MODE_1_2_2; ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ modes.rd_modes |= SNOR_MODE_1_1_4 | SNOR_MODE_1_4_4; ++ modes.wr_modes |= SNOR_MODE_1_1_4 | SNOR_MODE_1_4_4; ++#endif ++ ret = spi_nor_scan(nor, NULL, &modes); ++ if (ret) ++ return ret; ++ ++ mtd = &nor->mtd; ++ mtd->name = np->name; ++ ret = hisi_snor_device_register(mtd); ++ if (ret) ++ return ret; ++ ++ /* current chipselect has scanned, to detect next chipselect */ ++ hifmc_cs_user[host->num_chip]++; ++ host->nor[host->num_chip] = nor; ++ host->num_chip++; ++ return 0; ++} ++ ++static void hisi_spi_nor_unregister_all(struct hifmc_host *host) ++{ ++ int i; ++ ++ for (i = 0; i < host->num_chip; i++) ++ mtd_device_unregister(&host->nor[i]->mtd); ++} ++ ++static int hisi_spi_nor_register_all(struct hifmc_host *host) ++{ ++ struct device *dev = host->dev; ++ struct device_node *np = NULL; ++ int ret; ++ ++ for_each_available_child_of_node(dev->of_node, np) { ++ if (hifmc_cs_user[host->num_chip]) { ++ dev_warn(dev, "Current CS(%d) is occupied.\n", ++ host->num_chip); ++ continue; ++ } ++ ret = hisi_spi_nor_register(np, host); ++ if (ret) ++ goto fail; ++ ++ if (host->num_chip == HIFMC_MAX_CHIP_NUM) { ++ dev_warn(dev, "Flash device number exceeds the " ++ "maximum chipselect number\n"); ++ break; ++ } ++ } ++ ++ return 0; ++ ++fail: ++ hisi_spi_nor_unregister_all(host); ++ return ret; ++} ++ ++/******************************************************************************/ ++static int hisi_spi_nor_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct hisi_fmc *fmc = dev_get_drvdata(dev->parent); ++ struct hifmc_host *host; ++ int ret; ++ ++ host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); ++ if (!host) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, host); ++ host->dev = dev; ++ ++ host->regbase = fmc->regbase; ++ host->iobase = fmc->iobase; ++ host->clk = fmc->clk; ++ host->lock = &fmc->lock; ++ ++ host->buffer = dmam_alloc_coherent(dev, HIFMC_DMA_MAX_LEN, ++ &host->dma_buffer, GFP_KERNEL); ++ if (!host->buffer) ++ return -ENOMEM; ++ ++ clk_prepare_enable(host->clk); ++ hisi_spi_nor_init(host); ++ ret = hisi_spi_nor_register_all(host); ++ if (ret) ++ dev_warn(dev, "spi nor register fail!\n"); ++ ++ clk_disable_unprepare(host->clk); ++ ++ return ret; ++} ++ ++/******************************************************************************/ ++static int hisi_spi_nor_remove(struct platform_device *pdev) ++{ ++ struct hifmc_host *host = platform_get_drvdata(pdev); ++ ++ hisi_spi_nor_unregister_all(host); ++ clk_disable_unprepare(host->clk); ++ return 0; ++} ++ ++/******************************************************************************/ ++static void hisi_spi_nor_driver_shutdown(struct platform_device *pdev) ++{ ++ int i; ++ struct hifmc_host *host = platform_get_drvdata(pdev); ++ ++ if (!host) ++ return; ++ ++ mutex_lock(host->lock); ++ clk_prepare_enable(host->clk); ++ ++ spi_nor_switch_spi_type(host); ++ for (i = 0; i < host->num_chip; i++) ++ spi_nor_driver_shutdown(host->nor[i]); ++ ++ clk_disable_unprepare(host->clk); ++ mutex_unlock(host->lock); ++ dev_dbg(host->dev, "End of driver shutdown\n"); ++} ++ ++#ifdef CONFIG_PM ++/******************************************************************************/ ++static int hisi_spi_nor_driver_suspend(struct platform_device *pdev, ++ pm_message_t state) ++{ ++ int i; ++ struct hifmc_host *host = platform_get_drvdata(pdev); ++ ++ if (!host) ++ return 0; ++ ++ mutex_lock(host->lock); ++ clk_prepare_enable(host->clk); ++ ++ spi_nor_switch_spi_type(host); ++ for (i = 0; i < host->num_chip; i++) ++ spi_nor_suspend(host->nor[i], state); ++ ++ clk_disable_unprepare(host->clk); ++ mutex_unlock(host->lock); ++ dev_dbg(host->dev, "End of suspend\n"); ++ ++ return 0; ++} ++ ++/******************************************************************************/ ++static int hisi_spi_nor_driver_resume(struct platform_device *pdev) ++{ ++ int i; ++ struct hifmc_host *host = platform_get_drvdata(pdev); ++ ++ if (!host) ++ return 0; ++ ++ mutex_lock(host->lock); ++ clk_prepare_enable(host->clk); ++ ++ spi_nor_switch_spi_type(host); ++ for (i = 0; i < host->num_chip; i++) ++ spi_nor_resume(host->nor[i]); ++ ++ mutex_unlock(host->lock); ++ dev_dbg(host->dev, "End of resume\n"); ++ ++ return 0; ++} ++#endif /* End of CONFIG_PM */ ++ ++/******************************************************************************/ ++static const struct of_device_id hisi_spi_nor_dt_ids[] = { ++ { .compatible = "hisilicon,hisi-sfc"}, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, hisi_spi_nor_dt_ids); ++ ++/******************************************************************************/ ++static struct platform_driver hisi_spi_nor_driver = { ++ .driver = { ++ .name = "hisi-sfc", ++ .of_match_table = hisi_spi_nor_dt_ids, ++ }, ++ .probe = hisi_spi_nor_probe, ++ .remove = hisi_spi_nor_remove, ++ .shutdown = hisi_spi_nor_driver_shutdown, ++#ifdef CONFIG_PM ++ .suspend = hisi_spi_nor_driver_suspend, ++ .resume = hisi_spi_nor_driver_resume, ++#endif ++}; ++module_platform_driver(hisi_spi_nor_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("HiSilicon SPI Nor Flash Controller Driver"); +diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c +index c51ee52..208e2a3 100644 +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -16,19 +16,77 @@ + #include + #include + #include ++#include + +-#include + #include + #include + #include + #include + + /* Define max times to check status register before we give up. */ +-#define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ + +-#define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16) ++/* ++ * For everything but full-chip erase; probably could be much smaller, but kept ++ * around for safety for now ++ */ ++#define DEFAULT_READY_WAIT_JIFFIES (40UL * HZ) ++ ++/* ++ * For full-chip erase, calibrated to a 2MB flash (M25P16); should be scaled up ++ * for larger flash ++ */ ++#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; ++ ++ /* 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 SPI_NOR_4B_OPCODES BIT(10) /* ++ * Use dedicated 4byte address op codes ++ * to support memory size above 128Mib. ++ */ ++ ++ const struct spi_nor_basic_flash_parameter *params; ++ u32 clkrate; ++}; ++ ++#define JEDEC_MFR(info) ((info)->id[0]) + +-static const struct spi_device_id *spi_nor_match_id(const char *name); ++static const struct flash_info *spi_nor_match_id(const char *name); + + /* + * Read the status register, returning its value in the location +@@ -88,31 +146,13 @@ static int read_cr(struct spi_nor *nor) + } + + /* +- * Dummy Cycle calculation for different type of read. +- * It can be used to support more commands with +- * different dummy cycle requirements. +- */ +-static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor) +-{ +- switch (nor->flash_read) { +- case SPI_NOR_FAST: +- case SPI_NOR_DUAL: +- case SPI_NOR_QUAD: +- return 1; +- case SPI_NOR_NORMAL: +- return 0; +- } +- return 0; +-} +- +-/* + * Write status register 1 byte + * Returns negative if error occurred. + */ + static inline int write_sr(struct spi_nor *nor, u8 val) + { + nor->cmd_buf[0] = val; +- return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0); ++ return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1); + } + + /* +@@ -121,7 +161,7 @@ static inline int write_sr(struct spi_nor *nor, u8 val) + */ + static inline int write_enable(struct spi_nor *nor) + { +- return nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0, 0); ++ return nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0); + } + + /* +@@ -129,7 +169,7 @@ static inline int write_enable(struct spi_nor *nor) + */ + static inline int write_disable(struct spi_nor *nor) + { +- return nor->write_reg(nor, SPINOR_OP_WRDI, NULL, 0, 0); ++ return nor->write_reg(nor, SPINOR_OP_WRDI, NULL, 0); + } + + static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd) +@@ -137,88 +177,186 @@ static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd) + return mtd->priv; + } + ++struct spi_nor_address_entry { ++ u8 src_opcode; ++ u8 dst_opcode; ++}; ++ ++static u8 spi_nor_convert_opcode(u8 opcode, ++ const struct spi_nor_address_entry *entries, ++ size_t num_entries) ++{ ++ int min, max; ++ ++ min = 0; ++ max = num_entries - 1; ++ while (min <= max) { ++ int mid = (min + max) >> 1; ++ const struct spi_nor_address_entry *entry = &entries[mid]; ++ ++ if (opcode == entry->src_opcode) ++ return entry->dst_opcode; ++ ++ if (opcode < entry->src_opcode) ++ max = mid - 1; ++ else ++ min = mid + 1; ++ } ++ ++ /* No conversion found */ ++ return opcode; ++} ++ ++static u8 spi_nor_3to4_opcode(u8 opcode) ++{ ++ /* MUST be sorted by 3byte opcode */ ++#define ENTRY_3TO4(_opcode) { _opcode, _opcode##_4B } ++ static const struct spi_nor_address_entry spi_nor_3to4_table[] = { ++ ENTRY_3TO4(SPINOR_OP_PP), /* 0x02 */ ++ ENTRY_3TO4(SPINOR_OP_READ), /* 0x03 */ ++ ENTRY_3TO4(SPINOR_OP_READ_FAST), /* 0x0b */ ++ ENTRY_3TO4(SPINOR_OP_BE_4K), /* 0x20 */ ++ ENTRY_3TO4(SPINOR_OP_PP_1_1_4), /* 0x32 */ ++ ENTRY_3TO4(SPINOR_OP_PP_1_4_4), /* 0x38 */ ++ ENTRY_3TO4(SPINOR_OP_READ_1_1_2), /* 0x3b */ ++ ENTRY_3TO4(SPINOR_OP_BE_32K), /* 0x52 */ ++ ENTRY_3TO4(SPINOR_OP_READ_1_1_4), /* 0x6b */ ++ ENTRY_3TO4(SPINOR_OP_READ_1_2_2), /* 0xbb */ ++ ENTRY_3TO4(SPINOR_OP_SE), /* 0xd8 */ ++ ENTRY_3TO4(SPINOR_OP_READ_1_4_4), /* 0xeb */ ++ }; ++#undef ENTRY_3TO4 ++ ++ return spi_nor_convert_opcode(opcode, spi_nor_3to4_table, ++ ARRAY_SIZE(spi_nor_3to4_table)); ++} ++ ++static void spi_nor_set_4byte_opcodes(struct spi_nor *nor, ++ const struct flash_info *info) ++{ ++ /* Do some manufacturer fixups first */ ++ switch (JEDEC_MFR(info)) { ++ case SNOR_MFR_SPANSION: ++ /* No small sector erase for 4-byte command set */ ++ nor->erase_opcode = SPINOR_OP_SE; ++ nor->mtd.erasesize = info->sector_size; ++ break; ++ ++ default: ++ break; ++ } ++ ++ nor->read_opcode = spi_nor_3to4_opcode(nor->read_opcode); ++ nor->program_opcode = spi_nor_3to4_opcode(nor->program_opcode); ++ nor->erase_opcode = spi_nor_3to4_opcode(nor->erase_opcode); ++} ++ + /* Enable/disable 4-byte addressing mode. */ +-static inline int set_4byte(struct spi_nor *nor, u32 jedec_id, int enable) ++static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info, ++ int enable) + { + int status; + bool need_wren = false; + u8 cmd; + +- switch (JEDEC_MFR(jedec_id)) { +- case CFI_MFR_ST: /* Micron, actually */ ++ switch (JEDEC_MFR(info)) { ++ case SNOR_MFR_MICRON: + /* Some Micron need WREN command; all will accept it */ + need_wren = true; +- case CFI_MFR_MACRONIX: +- case 0xEF /* winbond */: ++ case SNOR_MFR_MACRONIX: + if (need_wren) + write_enable(nor); + + cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B; +- status = nor->write_reg(nor, cmd, NULL, 0, 0); ++ status = nor->write_reg(nor, cmd, NULL, 0); ++ + if (need_wren) + write_disable(nor); + + return status; ++ case SNOR_MFR_WINBOND: ++ if (enable) ++ return nor->write_reg(nor, SPINOR_OP_EN4B, NULL, 0); ++ else { ++ /* w25q256fvfg must send reset to disable 4 byte mode */ ++ nor->write_reg(nor, SPINOR_ENABLE_RESET, NULL, 0); ++ nor->write_reg(nor, SPINOR_OP_RESET, NULL, 0); ++ udelay(30); ++ } ++ return 0; + default: + /* Spansion style */ + nor->cmd_buf[0] = enable << 7; +- return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1, 0); ++ return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1); + } + } +- +-static int spi_nor_wait_till_ready(struct spi_nor *nor) ++static inline int spi_nor_sr_ready(struct spi_nor *nor) + { +- unsigned long deadline; +- int sr; ++ int sr = read_sr(nor); + +- deadline = jiffies + MAX_READY_WAIT_JIFFIES; ++ if (sr < 0) ++ return sr; ++ else ++ return !(sr & SR_WIP); ++} + +- do { +- cond_resched(); ++static inline int spi_nor_fsr_ready(struct spi_nor *nor) ++{ ++ int fsr = read_fsr(nor); + +- sr = read_sr(nor); +- if (sr < 0) +- break; +- else if (!(sr & SR_WIP)) +- return 0; +- } while (!time_after_eq(jiffies, deadline)); ++ if (fsr < 0) ++ return fsr; ++ else ++ return fsr & FSR_READY; ++} + +- return -ETIMEDOUT; ++static int spi_nor_ready(struct spi_nor *nor) ++{ ++ int sr, fsr; ++ ++ sr = spi_nor_sr_ready(nor); ++ if (sr < 0) ++ return sr; ++ fsr = nor->flags & SNOR_F_USE_FSR ? spi_nor_fsr_ready(nor) : 1; ++ if (fsr < 0) ++ return fsr; ++ return sr && fsr; + } + +-static int spi_nor_wait_till_fsr_ready(struct spi_nor *nor) ++/* ++ * Service routine to read status register until ready, or timeout occurs. ++ * Returns non-zero if error. ++ */ ++static int spi_nor_wait_till_ready_with_timeout(struct spi_nor *nor, ++ unsigned long timeout_jiffies) + { + unsigned long deadline; +- int sr; +- int fsr; ++ int timeout = 0, ret; ++ ++ deadline = jiffies + timeout_jiffies; + +- deadline = jiffies + MAX_READY_WAIT_JIFFIES; ++ while (!timeout) { ++ if (time_after_eq(jiffies, deadline)) ++ timeout = 1; ++ ++ ret = spi_nor_ready(nor); ++ if (ret < 0) ++ return ret; ++ if (ret) ++ return 0; + +- do { + cond_resched(); ++ } + +- sr = read_sr(nor); +- if (sr < 0) { +- break; +- } else if (!(sr & SR_WIP)) { +- fsr = read_fsr(nor); +- if (fsr < 0) +- break; +- if (fsr & FSR_READY) +- return 0; +- } +- } while (!time_after_eq(jiffies, deadline)); ++ dev_err(nor->dev, "flash operation timed out\n"); + + return -ETIMEDOUT; + } + +-/* +- * Service routine to read status register until ready, or timeout occurs. +- * Returns non-zero if error. +- */ +-static int wait_till_ready(struct spi_nor *nor) ++static int spi_nor_wait_till_ready(struct spi_nor *nor) + { +- return nor->wait_till_ready(nor); ++ return spi_nor_wait_till_ready_with_timeout(nor, ++ DEFAULT_READY_WAIT_JIFFIES); + } + + /* +@@ -228,19 +366,9 @@ static int wait_till_ready(struct spi_nor *nor) + */ + static int erase_chip(struct spi_nor *nor) + { +- int ret; +- +- dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd->size >> 10)); +- +- /* Wait until finished previous write command. */ +- ret = wait_till_ready(nor); +- if (ret) +- return ret; +- +- /* Send write enable, then erase commands. */ +- write_enable(nor); ++ dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd.size >> 10)); + +- return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0, 0); ++ return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0); + } + + static int spi_nor_lock_and_prep(struct spi_nor *nor, enum spi_nor_ops ops) +@@ -268,6 +396,29 @@ static void spi_nor_unlock_and_unprep(struct spi_nor *nor, enum spi_nor_ops ops) + } + + /* ++ * Initiate the erasure of a single sector ++ */ ++static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr) ++{ ++ u8 buf[SPI_NOR_MAX_ADDR_WIDTH]; ++ int i; ++ ++ if (nor->erase) ++ return nor->erase(nor, addr); ++ ++ /* ++ * Default implementation, if driver doesn't have a specialized HW ++ * control ++ */ ++ for (i = nor->addr_width - 1; i >= 0; i--) { ++ buf[i] = addr & 0xff; ++ addr >>= 8; ++ } ++ ++ return nor->write_reg(nor, nor->erase_opcode, buf, nor->addr_width); ++} ++ ++/* + * Erase an address range on the nor chip. The address range may extend + * one or more erase sectors. Return an error is there is a problem erasing. + */ +@@ -292,13 +443,36 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) + if (ret) + return ret; + ++#ifdef CONFIG_HISI_SPI_BLOCK_PROTECT ++ if ((nor->level) && (addr < nor->end_addr)) { ++ dev_err(nor->dev, "Error: The erase area was locked\n"); ++ return -EINVAL; ++ } ++#endif + /* whole-chip erase? */ + if (len == mtd->size) { ++ unsigned long timeout; ++ ++ write_enable(nor); ++ + if (erase_chip(nor)) { + ret = -EIO; + goto erase_err; + } + ++ /* ++ * Scale the timeout linearly with the size of the flash, with ++ * a minimum calibrated to an old 2MB flash. We could try to ++ * pull these from CFI/SFDP, but these values should be good ++ * enough for now. ++ */ ++ timeout = max(CHIP_ERASE_2MB_READY_WAIT_JIFFIES, ++ CHIP_ERASE_2MB_READY_WAIT_JIFFIES * ++ (unsigned long)(mtd->size / SZ_2M)); ++ ret = spi_nor_wait_till_ready_with_timeout(nor, timeout); ++ if (ret) ++ goto erase_err; ++ + /* REVISIT in some cases we could speed up erasing large regions + * by using SPINOR_OP_SE instead of SPINOR_OP_BE_4K. We may have set up + * to use "small sector erase", but that's not always optimal. +@@ -307,276 +481,827 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) + /* "sector"-at-a-time erase */ + } else { + while (len) { +- if (nor->erase(nor, addr)) { +- ret = -EIO; ++ write_enable(nor); ++ ++ ret = spi_nor_erase_sector(nor, addr); ++ if (ret) + goto erase_err; +- } + + addr += mtd->erasesize; + len -= mtd->erasesize; ++ ++ ret = spi_nor_wait_till_ready(nor); ++ if (ret) ++ goto erase_err; + } + } + ++ write_disable(nor); ++ ++erase_err: + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); + +- instr->state = MTD_ERASE_DONE; ++ instr->state = ret ? MTD_ERASE_FAILED : MTD_ERASE_DONE; + mtd_erase_callback(instr); + + return ret; +- +-erase_err: +- spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); +- instr->state = MTD_ERASE_FAILED; +- return ret; + } + +-static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) ++static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs, ++ uint64_t *len) + { +- struct spi_nor *nor = mtd_to_spi_nor(mtd); +- uint32_t offset = ofs; +- uint8_t status_old, status_new; +- int ret = 0; ++ struct mtd_info *mtd = &nor->mtd; ++ u8 mask = SR_BP2 | SR_BP1 | SR_BP0; ++ int shift = ffs(mask) - 1; ++ int pow; ++ ++ if (!(sr & mask)) { ++ /* No protection */ ++ *ofs = 0; ++ *len = 0; ++ } else { ++ pow = ((sr & mask) ^ mask) >> shift; ++ *len = mtd->size >> pow; ++ if (nor->flags & SNOR_F_HAS_SR_TB && sr & SR_TB) ++ *ofs = 0; ++ else ++ *ofs = mtd->size - *len; ++ } ++} + +- ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_LOCK); +- if (ret) +- return ret; ++/* ++ * Return 1 if the entire region is locked (if @locked is true) or unlocked (if ++ * @locked is false); 0 otherwise ++ */ ++static int stm_check_lock_status_sr(struct spi_nor *nor, loff_t ofs, ++ uint64_t len, u8 sr, bool locked) ++{ ++ loff_t lock_offs; ++ uint64_t lock_len; + +- /* Wait until finished previous command */ +- ret = wait_till_ready(nor); +- if (ret) +- goto err; ++ if (!len) ++ return 1; + +- status_old = read_sr(nor); ++ stm_get_locked_range(nor, sr, &lock_offs, &lock_len); + +- if (offset < mtd->size - (mtd->size / 2)) +- status_new = status_old | SR_BP2 | SR_BP1 | SR_BP0; +- else if (offset < mtd->size - (mtd->size / 4)) +- status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1; +- else if (offset < mtd->size - (mtd->size / 8)) +- status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0; +- else if (offset < mtd->size - (mtd->size / 16)) +- status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2; +- else if (offset < mtd->size - (mtd->size / 32)) +- status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0; +- else if (offset < mtd->size - (mtd->size / 64)) +- status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1; ++ if (locked) ++ /* Requested range is a sub-range of locked range */ ++ return (ofs + len <= lock_offs + lock_len) ++ && (ofs >= lock_offs); + else +- status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0; ++ /* Requested range does not overlap with locked range */ ++ return (ofs >= lock_offs + lock_len) ++ || (ofs + len <= lock_offs); ++} + +- /* Only modify protection if it will not unlock other areas */ +- if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) > +- (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) { +- write_enable(nor); +- ret = write_sr(nor, status_new); +- if (ret) +- goto err; +- } ++static int stm_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, ++ u8 sr) ++{ ++ return stm_check_lock_status_sr(nor, ofs, len, sr, true); ++} + +-err: +- spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); +- return ret; ++static int stm_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, ++ u8 sr) ++{ ++ return stm_check_lock_status_sr(nor, ofs, len, sr, false); + } + +-static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) ++/* ++ * Lock a region of the flash. Compatible with ST Micro and similar flash. ++ * Supports the block protection bits BP{0,1,2} in the status register ++ * (SR). Does not support these features found in newer SR bitfields: ++ * - SEC: sector/block protect - only handle SEC=0 (block protect) ++ * - CMP: complement protect - only support CMP=0 (range is not complemented) ++ * ++ * Support for the following is provided conditionally for some flash: ++ * - TB: top/bottom protect ++ * ++ * Sample table portion for 8MB flash (Winbond w25q64fw): ++ * ++ * SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion ++ * -------------------------------------------------------------------------- ++ * X | X | 0 | 0 | 0 | NONE | NONE ++ * 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64 ++ * 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32 ++ * 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16 ++ * 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8 ++ * 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 ++ * 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 ++ * X | X | 1 | 1 | 1 | 8 MB | ALL ++ * ------|-------|-------|-------|-------|---------------|------------------- ++ * 0 | 1 | 0 | 0 | 1 | 128 KB | Lower 1/64 ++ * 0 | 1 | 0 | 1 | 0 | 256 KB | Lower 1/32 ++ * 0 | 1 | 0 | 1 | 1 | 512 KB | Lower 1/16 ++ * 0 | 1 | 1 | 0 | 0 | 1 MB | Lower 1/8 ++ * 0 | 1 | 1 | 0 | 1 | 2 MB | Lower 1/4 ++ * 0 | 1 | 1 | 1 | 0 | 4 MB | Lower 1/2 ++ * ++ * Returns negative on errors, 0 on success. ++ */ ++static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) + { +- struct spi_nor *nor = mtd_to_spi_nor(mtd); +- uint32_t offset = ofs; +- uint8_t status_old, status_new; +- int ret = 0; ++ struct mtd_info *mtd = &nor->mtd; ++ int status_old, status_new; ++ u8 mask = SR_BP2 | SR_BP1 | SR_BP0; ++ u8 shift = ffs(mask) - 1, pow, val; ++ loff_t lock_len; ++ bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; ++ bool use_top; ++ int ret; + +- ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK); +- if (ret) +- return ret; ++ status_old = read_sr(nor); ++ if (status_old < 0) ++ return status_old; + +- /* Wait until finished previous command */ +- ret = wait_till_ready(nor); +- if (ret) +- goto err; ++ /* If nothing in our range is unlocked, we don't need to do anything */ ++ if (stm_is_locked_sr(nor, ofs, len, status_old)) ++ return 0; + +- status_old = read_sr(nor); ++ /* If anything below us is unlocked, we can't use 'bottom' protection */ ++ if (!stm_is_locked_sr(nor, 0, ofs, status_old)) ++ can_be_bottom = false; + +- if (offset+len > mtd->size - (mtd->size / 64)) +- status_new = status_old & ~(SR_BP2 | SR_BP1 | SR_BP0); +- else if (offset+len > mtd->size - (mtd->size / 32)) +- status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0; +- else if (offset+len > mtd->size - (mtd->size / 16)) +- status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1; +- else if (offset+len > mtd->size - (mtd->size / 8)) +- status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0; +- else if (offset+len > mtd->size - (mtd->size / 4)) +- status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2; +- else if (offset+len > mtd->size - (mtd->size / 2)) +- status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0; +- else +- status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1; ++ /* If anything above us is unlocked, we can't use 'top' protection */ ++ if (!stm_is_locked_sr(nor, ofs + len, mtd->size - (ofs + len), ++ status_old)) ++ can_be_top = false; + +- /* Only modify protection if it will not lock other areas */ +- if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) < +- (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) { +- write_enable(nor); +- ret = write_sr(nor, status_new); +- if (ret) +- goto err; +- } ++ if (!can_be_bottom && !can_be_top) ++ return -EINVAL; + +-err: +- spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); +- return ret; +-} ++ /* Prefer top, if both are valid */ ++ use_top = can_be_top; + +-struct flash_info { +- /* JEDEC id zero means "no ID" (most older chips); otherwise it has +- * a high byte of zero plus three data bytes: the manufacturer id, +- * then a two byte device id. +- */ +- u32 jedec_id; +- u16 ext_id; ++ /* lock_len: length of region that should end up locked */ ++ if (use_top) ++ lock_len = mtd->size - ofs; ++ else ++ lock_len = ofs + len; + +- /* The size listed here is what works with SPINOR_OP_SE, which isn't +- * necessarily called a "sector" by the vendor. ++ /* ++ * Need smallest pow such that: ++ * ++ * 1 / (2^pow) <= (len / size) ++ * ++ * so (assuming power-of-2 size) we do: ++ * ++ * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) + */ +- unsigned sector_size; +- u16 n_sectors; ++ pow = ilog2(mtd->size) - ilog2(lock_len); ++ val = mask - (pow << shift); ++ if (val & ~mask) ++ return -EINVAL; ++ /* Don't "lock" with no region! */ ++ if (!(val & mask)) ++ return -EINVAL; + +- u16 page_size; +- u16 addr_width; ++ status_new = (status_old & ~mask & ~SR_TB) | val; + +- u16 flags; +-#define SECT_4K 0x01 /* SPINOR_OP_BE_4K works uniformly */ +-#define SPI_NOR_NO_ERASE 0x02 /* No erase command needed */ +-#define SST_WRITE 0x04 /* use SST byte programming */ +-#define SPI_NOR_NO_FR 0x08 /* Can't do fastread */ +-#define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */ +-#define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */ +-#define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */ +-#define USE_FSR 0x80 /* use flag status register */ +-}; ++ /* Disallow further writes if WP pin is asserted */ ++ status_new |= SR_SRWD; + +-#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ +- ((kernel_ulong_t)&(struct flash_info) { \ +- .jedec_id = (_jedec_id), \ +- .ext_id = (_ext_id), \ +- .sector_size = (_sector_size), \ +- .n_sectors = (_n_sectors), \ +- .page_size = 256, \ +- .flags = (_flags), \ +- }) ++ if (!use_top) ++ status_new |= SR_TB; + +-#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width, _flags) \ +- ((kernel_ulong_t)&(struct flash_info) { \ +- .sector_size = (_sector_size), \ +- .n_sectors = (_n_sectors), \ +- .page_size = (_page_size), \ +- .addr_width = (_addr_width), \ +- .flags = (_flags), \ +- }) ++ /* Don't bother if they're the same */ ++ if (status_new == status_old) ++ return 0; + +-/* NOTE: double check command sets and memory organization when you add +- * more nor chips. This current list focusses on newer chips, which +- * have been converging on command sets which including JEDEC ID. +- */ +-static const struct spi_device_id 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) }, ++ /* Only modify protection if it will not unlock other areas */ ++ if ((status_new & mask) < (status_old & mask)) ++ return -EINVAL; + +- { "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) }, ++ write_enable(nor); ++ ret = write_sr(nor, status_new); ++ if (ret) ++ return ret; ++ return spi_nor_wait_till_ready(nor); ++} + +- { "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) }, ++/* ++ * Unlock a region of the flash. See stm_lock() for more info ++ * ++ * Returns negative on errors, 0 on success. ++ */ ++static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) ++{ ++ struct mtd_info *mtd = &nor->mtd; ++ int status_old, status_new; ++ u8 mask = SR_BP2 | SR_BP1 | SR_BP0; ++ u8 shift = ffs(mask) - 1, pow, val; ++ loff_t lock_len; ++ bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; ++ bool use_top; ++ int ret; + +- { "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) }, ++ status_old = read_sr(nor); ++ if (status_old < 0) ++ return status_old; + +- /* 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) }, ++ /* If nothing in our range is locked, we don't need to do anything */ ++ if (stm_is_unlocked_sr(nor, ofs, len, status_old)) ++ return 0; + +- /* ESMT */ +- { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K) }, ++ /* If anything below us is locked, we can't use 'top' protection */ ++ if (!stm_is_unlocked_sr(nor, 0, ofs, status_old)) ++ can_be_top = false; + +- /* 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) }, ++ /* If anything above us is locked, we can't use 'bottom' protection */ ++ if (!stm_is_unlocked_sr(nor, ofs + len, mtd->size - (ofs + len), ++ status_old)) ++ can_be_bottom = false; + +- /* GigaDevice */ +- { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, +- { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, ++ if (!can_be_bottom && !can_be_top) ++ return -EINVAL; + +- /* 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) }, ++ /* Prefer top, if both are valid */ ++ use_top = can_be_top; + +- /* Macronix */ +- { "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, 0) }, +- { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) }, +- { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) }, +- { "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) }, +- +- /* Micron */ +- { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, +- { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) }, +- { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, +- { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) }, +- { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) }, +- { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR) }, +- { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR) }, ++ /* lock_len: length of region that should remain locked */ ++ if (use_top) ++ lock_len = mtd->size - (ofs + len); ++ else ++ lock_len = ofs; + +- /* 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) }, ++ /* ++ * Need largest pow such that: ++ * ++ * 1 / (2^pow) >= (len / size) ++ * ++ * so (assuming power-of-2 size) we do: ++ * ++ * pow = floor(log2(size / len)) = log2(size) - ceil(log2(len)) ++ */ ++ pow = ilog2(mtd->size) - order_base_2(lock_len); ++ if (lock_len == 0) { ++ val = 0; /* fully unlocked */ ++ } else { ++ val = mask - (pow << shift); ++ /* Some power-of-two sizes are not supported */ ++ if (val & ~mask) ++ return -EINVAL; ++ } ++ ++ status_new = (status_old & ~mask & ~SR_TB) | val; ++ ++ /* Don't protect status register if we're fully unlocked */ ++ if (lock_len == mtd->size) ++ status_new &= ~SR_SRWD; ++ ++ if (!use_top) ++ status_new |= SR_TB; ++ ++ /* Don't bother if they're the same */ ++ if (status_new == status_old) ++ return 0; ++ ++ /* Only modify protection if it will not lock other areas */ ++ if ((status_new & mask) > (status_old & mask)) ++ return -EINVAL; ++ ++ write_enable(nor); ++ ret = write_sr(nor, status_new); ++ if (ret) ++ return ret; ++ return spi_nor_wait_till_ready(nor); ++} ++ ++/* ++ * Check if a region of the flash is (completely) locked. See stm_lock() for ++ * more info. ++ * ++ * Returns 1 if entire region is locked, 0 if any portion is unlocked, and ++ * negative on errors. ++ */ ++static int stm_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len) ++{ ++ int status; ++ ++ status = read_sr(nor); ++ if (status < 0) ++ return status; ++ ++ return stm_is_locked_sr(nor, ofs, len, status); ++} ++ ++static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) ++{ ++ struct spi_nor *nor = mtd_to_spi_nor(mtd); ++ int ret; ++ ++ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_LOCK); ++ if (ret) ++ return ret; ++ ++ ret = nor->flash_lock(nor, ofs, len); ++ ++ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); ++ return ret; ++} ++ ++static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) ++{ ++ struct spi_nor *nor = mtd_to_spi_nor(mtd); ++ int ret; ++ ++ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK); ++ if (ret) ++ return ret; ++ ++ ret = nor->flash_unlock(nor, ofs, len); ++ ++ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); ++ return ret; ++} ++ ++static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) ++{ ++ struct spi_nor *nor = mtd_to_spi_nor(mtd); ++ int ret; ++ ++ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK); ++ if (ret) ++ return ret; ++ ++ ret = nor->flash_is_locked(nor, ofs, len); ++ ++ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); ++ return ret; ++} ++ ++#define SNOR_RD_MODES \ ++ (SNOR_MODE_SLOW | \ ++ SNOR_MODE_1_1_1 | \ ++ SNOR_MODE_1_1_2 | \ ++ SNOR_MODE_1_2_2 | \ ++ SNOR_MODE_1_1_4 | \ ++ SNOR_MODE_1_4_4) ++ ++#define SNOR_WR_MODES \ ++ (SNOR_MODE_1_1_1 | \ ++ SNOR_MODE_1_1_4) ++ ++static int spansion_quad_enable(struct spi_nor *nor); ++static int macronix_quad_enable(struct spi_nor *nor); ++static int gd_quad_enable(struct spi_nor *nor); ++ ++#define SNOR_EON_RD_MODES \ ++ (SNOR_MODE_SLOW | \ ++ SNOR_MODE_1_1_1 | \ ++ SNOR_MODE_1_1_2 | \ ++ SNOR_MODE_1_2_2) ++ ++#define SNOR_EON_WR_MODES \ ++ (SNOR_MODE_1_1_1) ++ ++static const struct spi_nor_basic_flash_parameter eon_params = { ++ .rd_modes = SNOR_EON_RD_MODES, ++ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ), ++ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST), ++ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2), ++ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(8, 0, SPINOR_OP_READ_1_2_2), ++ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4), ++ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4), ++ ++ .wr_modes = SNOR_EON_WR_MODES, ++ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP, ++ ++ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE), ++ ++}; ++ ++static const struct spi_nor_basic_flash_parameter esmt_params = { ++ .rd_modes = SNOR_RD_MODES, ++ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ), ++ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST), ++ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2), ++ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(8, 0, SPINOR_OP_READ_1_2_2), ++ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4), ++ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4), ++ ++ .wr_modes = SNOR_WR_MODES, ++ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP, ++ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4, ++ ++ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE), ++ ++ .enable_quad_io = macronix_quad_enable, ++ ++}; ++ ++#define SNOR_PARAGON_WR_MODES \ ++ (SNOR_MODE_1_1_1) ++ ++static const struct spi_nor_basic_flash_parameter paragon_params = { ++ .rd_modes = SNOR_RD_MODES, ++ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ), ++ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST), ++ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2), ++ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(8, 0, SPINOR_OP_READ_1_2_2), ++ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4), ++ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4), ++ ++ .wr_modes = SNOR_PARAGON_WR_MODES, ++ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP, ++ ++ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE), ++ ++ .enable_quad_io = spansion_quad_enable, ++ ++}; ++ ++static const struct spi_nor_basic_flash_parameter gd_params = { ++ .rd_modes = SNOR_RD_MODES, ++ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ), ++ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST), ++ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2), ++ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(8, 0, SPINOR_OP_READ_1_2_2), ++ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4), ++ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4), ++ ++ .wr_modes = SNOR_WR_MODES, ++ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP, ++ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4, ++ ++ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE), ++ ++ .enable_quad_io = gd_quad_enable, ++ ++}; ++ ++static const struct spi_nor_basic_flash_parameter winbond_params = { ++ .rd_modes = SNOR_RD_MODES, ++ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ), ++ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST), ++ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2), ++ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(8, 0, SPINOR_OP_READ_1_2_2), ++ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4), ++ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4), ++ ++ .wr_modes = SNOR_WR_MODES, ++ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP, ++ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4, ++ ++ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE), ++ ++ .enable_quad_io = spansion_quad_enable, ++ ++}; ++ ++static const struct spi_nor_basic_flash_parameter spansion_params = { ++ .rd_modes = SNOR_RD_MODES, ++ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ), ++ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST), ++ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2), ++ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_2_2), ++ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4), ++ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4), ++ ++ .wr_modes = SNOR_WR_MODES, ++ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP, ++ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4, ++ ++ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE), ++ ++ .enable_quad_io = spansion_quad_enable, ++ ++}; ++ ++#define SNOR_MXIC_WR_MODES \ ++ (SNOR_MODE_1_1_1 | \ ++ SNOR_MODE_1_4_4) ++ ++static const struct spi_nor_basic_flash_parameter mxic_params = { ++ .rd_modes = SNOR_RD_MODES, ++ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ), ++ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST), ++ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2), ++ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_2_2), ++ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4), ++ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4), ++ ++ .wr_modes = SNOR_MXIC_WR_MODES, ++ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP, ++ .page_programs[SNOR_MIDX_1_4_4] = SPINOR_OP_PP_1_4_4, ++ ++ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE), ++ ++ .enable_quad_io = macronix_quad_enable, ++ ++}; ++ ++static const struct spi_nor_basic_flash_parameter micron_params = { ++ .rd_modes = SNOR_RD_MODES, ++ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ), ++ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST), ++ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2), ++ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(8, 8, SPINOR_OP_READ_1_2_2), ++ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(1, 7, SPINOR_OP_READ_1_1_4), ++ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(0, 40, SPINOR_OP_READ_1_4_4), ++ ++ .wr_modes = SNOR_WR_MODES, ++ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP, ++ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4, ++ ++ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE), ++ ++}; ++ ++static const struct spi_nor_basic_flash_parameter micron_4k_params = { ++ .rd_modes = SNOR_RD_MODES, ++ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ), ++ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST), ++ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2), ++ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(1, 7, SPINOR_OP_READ_1_2_2), ++ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(1, 7, SPINOR_OP_READ_1_1_4), ++ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(1, 9, SPINOR_OP_READ_1_4_4), ++ ++ .wr_modes = SNOR_WR_MODES, ++ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP, ++ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4, ++ ++ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE), ++ .erase_types[1] = SNOR_OP_ERASE_4K(SPINOR_OP_BE_4K), ++}; ++ ++#define PARAMS(_name) .params = &_name##_params ++ ++/* Used when the "_ext_id" is two bytes at most */ ++#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ ++ .id = { \ ++ ((_jedec_id) >> 16) & 0xff, \ ++ ((_jedec_id) >> 8) & 0xff, \ ++ (_jedec_id) & 0xff, \ ++ ((_ext_id) >> 8) & 0xff, \ ++ (_ext_id) & 0xff, \ ++ }, \ ++ .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \ ++ .sector_size = (_sector_size), \ ++ .n_sectors = (_n_sectors), \ ++ .page_size = 256, \ ++ .flags = (_flags) ++ ++#define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ ++ .id = { \ ++ ((_jedec_id) >> 16) & 0xff, \ ++ ((_jedec_id) >> 8) & 0xff, \ ++ (_jedec_id) & 0xff, \ ++ ((_ext_id) >> 16) & 0xff, \ ++ ((_ext_id) >> 8) & 0xff, \ ++ (_ext_id) & 0xff, \ ++ }, \ ++ .id_len = 6, \ ++ .sector_size = (_sector_size), \ ++ .n_sectors = (_n_sectors), \ ++ .page_size = 256, \ ++ .flags = (_flags), ++ ++#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width, _flags) \ ++ .sector_size = (_sector_size), \ ++ .n_sectors = (_n_sectors), \ ++ .page_size = (_page_size), \ ++ .addr_width = (_addr_width), \ ++ .flags = (_flags), ++ ++/* Different from spi-max-frequency in DTS, the clk here stands for the clock ++ * rate on SPI interface, it is half of the FMC CRG configuration */ ++#define CLK_MHZ_2X(clk) .clkrate = (clk * 2000000), ++ ++/* NOTE: double check command sets and memory organization when you add ++ * more nor chips. This current list focusses on newer chips, which ++ * have been converging on command sets which including JEDEC ID. ++ * ++ * All newly added entries should describe *hardware* and should use SECT_4K ++ * (or SECT_4K_PMC) if hardware supports erasing 4 KiB sectors. For usage ++ * scenarios excluding small sectors there is config option that can be ++ * disabled: CONFIG_MTD_SPI_NOR_USE_4K_SECTORS. ++ * For historical (and compatibility) reasons (before we got above config) some ++ * old entries may be missing 4K flag. ++ */ ++ ++/******* SPI Nor ID Table ************************************************** ++ * Version Manufacturer Chip Name Chipsize Block Vol Operation ++ * 1.0 Macronix/MXIC MX25L1606E 2M 64K 3V3 ++ * Macronix/MXIC MX25L6436F 8M 64K 3V3 ++ * Macronix/MXIC MX25R6435F 8M 64K 1V8/3V3 Add 14chips ++ * Macronix/MXIC MX25U6435F 8M 64K 1V8 ++ * Macronix/MXIC MX25U12835F 16M 64K 1V8 ++ * Macronix/MXIC MX25F128XXX 16M 64K 3V3 ++ * Macronix/MXIC MX25U25635F/45G 32M 64K 1V8 25645G-DTR ++ * Macronix/MXIC MX25L(256/257) 32M 64K 3V3 25645G-DTR ++ * Spansion S25FL129P1 16M 64K 3V3 ++ * Spansion S25FL256S 32M 64K 3V3 ++ * Micron N25Q064A 8M 64K 3V3 ++ * Micron N25QL064A 8M 64K 3V3 ++ * Micron N25Q128A11/MT25QU128AB 16M 64K 1V8 ++ * Micron N25QL128A 16M 64K 3V3 ++ * Micron MT25QU256A 32M 64K 1V8 ++ * Micron MT25Q256A 32M 64K 3V3 ++ * Winbond W25Q16(B/C)V/S25FL016K 2M 64K 3V3 ++ * Winbond W25Q32(B/F)V 4M 64K 3V3 ++ * Winbond W25Q32FW 4M 64K 1V8 ++ * Winbond W25Q64FW 8M 64K 1V8 ++ * Winbond W25Q64FV 8M 64K 3V3 ++ * Winbond W25Q128FW 16M 64K 1V8 ++ * Winbond W25Q128(B/F)V 16M 64K 3V3 ++ * Winbond W25Q128JV 16M 64K 3V3 DTR ++ * ESMT/CFEON EN25Q32B 4M 64K 3V3 ++ * ESMT/CFEON EN25Q64 8M 64K 3V3 ++ * ESMT/CFEON EN25Q128 16M 64K 3V3 ++ * ESMT/CFEON F25L64QA 8M 64K 3V3 ++ * GD GD25Q64 8M 64K 3V3 ++ * GD GD25LQ128 16M 64K 1V8 ++ * GD GD25Q128 16M 64K 3V3 ++ * GD GD25LQ64C 8M 64K 1V8 ++ * GD GD25Q32 4M 64K 3V3 ++ * Paragon PN25F16S 2M 64K 3V3 ++ * Paragon PN25F32S 4M 64K 3V3 ++ *****************************************************************************/ ++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) }, ++ ++ /* 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, ++ SPI_NOR_QUAD_READ), PARAMS(eon), CLK_MHZ_2X(104) }, ++ { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, ++ { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, ++ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(eon), CLK_MHZ_2X(104) }, ++ { "en25q128", INFO(0x1c3018, 0, 64 * 1024, 256, ++ SPI_NOR_QUAD_READ), PARAMS(eon), CLK_MHZ_2X(104) }, ++ { "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) }, ++ ++ /* ESMT */ ++ { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K) }, ++ { "f25l64qa", INFO(0x8c4117, 0, 64 * 1024, 128, ++ SPI_NOR_QUAD_READ), PARAMS(esmt), CLK_MHZ_2X(84) }, ++ ++ /* 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) }, ++ ++ /* Fujitsu */ ++ { "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1, SPI_NOR_NO_ERASE) }, ++ ++ /* GigaDevice 3.3V */ ++ { "gd25q16c", INFO(0xc84015, 0, 64 * 1024, 32, ++ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(gd), CLK_MHZ_2X(120) }, ++ { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, ++ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(gd), CLK_MHZ_2X(120) }, ++ { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, ++ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(gd), CLK_MHZ_2X(120) }, ++ { "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, ++ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(gd), CLK_MHZ_2X(80) }, ++ /* GigaDevice 1.8V */ ++ { "gd25lq64", INFO(0xc86017, 0, 64 * 1024, 128, ++ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(gd), CLK_MHZ_2X(133) }, ++ { "gd25lq128", INFO(0xc86018, 0, 64 * 1024, 256, ++ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(gd), CLK_MHZ_2X(133) }, ++ ++ /* 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) }, ++ ++ /* ISSI */ ++ { "is25cd512", INFO(0x7f9d20, 0, 32 * 1024, 2, SECT_4K) }, ++ ++ /* Macronix/MXIC 3.3V */ ++ { "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 ++ | SPI_NOR_DUAL_READ), CLK_MHZ_2X(80) }, ++ { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) }, ++ { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) }, ++ { "mx25l6436f", INFO(0xc22017, 0, 64 * 1024, 128, ++ SPI_NOR_QUAD_READ), PARAMS(mxic), CLK_MHZ_2X(133) }, ++ { "mx25l12835f", INFO(0xc22018, 0, 64 * 1024, 256, ++ SPI_NOR_QUAD_READ), PARAMS(mxic), CLK_MHZ_2X(84) }, ++ { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, ++ { "mx25l25635f", INFO(0xc22019, 0, 64 * 1024, 512, ++ SPI_NOR_QUAD_READ), PARAMS(mxic), CLK_MHZ_2X(84) }, ++ { "mx25l25673g", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_QUAD_READ ++ | SPI_NOR_4B_OPCODES) }, ++ { "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)}, ++ { "mx25v1635f", INFO(0xc22315, 0, 64 * 1024, 32 , ++ SPI_NOR_QUAD_READ), PARAMS(mxic), CLK_MHZ_2X(80) }, ++ /* Macronix/MXIC Wide Voltage Range 1.65~3.6V */ ++ { "mx25r6435f", INFO(0xc22817, 0, 64 * 1024, 128, ++ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ), CLK_MHZ_2X(80) }, ++ /* Macronix/MXIC 1.8V */ ++ { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, ++ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(mxic), CLK_MHZ_2X(84) }, ++ { "mx25u12835f", INFO(0xc22538, 0, 64 * 1024, 256, ++ SPI_NOR_QUAD_READ), PARAMS(mxic), CLK_MHZ_2X(84) }, ++ { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, ++ SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES), PARAMS(mxic), CLK_MHZ_2X(84) }, ++ ++ /* Micron 3.3V */ ++ { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ), ++ PARAMS(micron), CLK_MHZ_2X(84) }, ++ { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SPI_NOR_QUAD_READ), ++ PARAMS(micron_4k), CLK_MHZ_2X(108) }, ++ { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ), ++ PARAMS(micron), CLK_MHZ_2X(108) }, ++ { "mt25ql256a/n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SPI_NOR_QUAD_READ), ++ PARAMS(micron), CLK_MHZ_2X(108) }, ++ { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR), ++ PARAMS(micron_4k) }, ++ { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR | SPI_NOR_QUAD_READ), ++ PARAMS(micron_4k), CLK_MHZ_2X(80) }, ++ /* Micron 1.8V */ ++ { "n25q032a", INFO(0x20bb16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ), ++ PARAMS(micron), CLK_MHZ_2X(108) }, ++ { "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128, SPI_NOR_QUAD_READ), ++ PARAMS(micron), CLK_MHZ_2X(108) }, ++ { "mt25qu128a/n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ), ++ PARAMS(micron), CLK_MHZ_2X(108) }, ++ { "mt25qu256a", INFO(0x20bb19, 0, 64 * 1024, 512, ++ SPI_NOR_QUAD_READ), PARAMS(micron), CLK_MHZ_2X(108) }, ++ { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, USE_FSR | SPI_NOR_QUAD_READ), ++ PARAMS(micron_4k), CLK_MHZ_2X(80) }, ++ ++ /* 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) }, + + /* 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, 0) }, ++ { "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) }, ++ { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, ++ SPI_NOR_4B_OPCODES | SPI_NOR_QUAD_READ), PARAMS(spansion), CLK_MHZ_2X(104) }, ++ { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, ++ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, ++ { "s25fl127s/129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, ++ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(spansion), CLK_MHZ_2X(108) }, + { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, + { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, +- { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, +- { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, +- { "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) }, +- { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, +- { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) }, +- { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, ++ { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K ++ | SPI_NOR_DUAL_READ | 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) }, ++ { "w25x16/s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, ++ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(winbond), CLK_MHZ_2X(84) }, ++ /* { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, 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) }, + + /* 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) }, ++ { "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) }, +- { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, ++ { "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)}, + + /* ST Microelectronics -- newer production may have feature updates */ + { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) }, +@@ -588,7 +1313,6 @@ static const struct spi_device_id spi_nor_ids[] = { + { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) }, + { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, + { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, +- { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) }, + + { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) }, + { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) }, +@@ -615,60 +1339,78 @@ static const struct spi_device_id spi_nor_ids[] = { + { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) }, + { "m25px80", INFO(0x207114, 0, 64 * 1024, 16, 0) }, + +- /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ ++ /* Winbond 3.3V-- 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) }, ++ { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K ++ | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "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) }, ++ { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, ++ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(winbond), CLK_MHZ_2X(80) }, + { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, +- { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, ++ { "w25q64/s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, ++ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(winbond), CLK_MHZ_2X(80) }, + { "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) }, ++ { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, ++ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(winbond), CLK_MHZ_2X(104) }, ++ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, ++ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(winbond), CLK_MHZ_2X(80) }, ++ /* Winbond 1.8V */ ++ { "w25q32fw", INFO(0xef6016, 0, 64 * 1024, 64, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | ++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB), PARAMS(winbond), CLK_MHZ_2X(80) }, ++ { "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), PARAMS(winbond), CLK_MHZ_2X(80) }, ++ { "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), PARAMS(winbond), CLK_MHZ_2X(80) }, + + /* 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) }, ++ { "cat25c03", CAT25_INFO(32, 8, 16, 2, SPI_NOR_NO_ERASE ++ | SPI_NOR_NO_FR) }, ++ { "cat25c09", CAT25_INFO(28, 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) }, ++ /* Paragon 3.3V */ ++ { "pn25f16s", INFO(0xe04015, 0, 64 * 1024, 32, ++ SPI_NOR_QUAD_READ), PARAMS(paragon), CLK_MHZ_2X(80) }, ++ { "pn25f32s", INFO(0xe04016, 0, 64 * 1024, 64, ++ SPI_NOR_QUAD_READ), PARAMS(paragon), CLK_MHZ_2X(80) }, ++ + { }, + }; + +-static const struct spi_device_id *spi_nor_read_id(struct spi_nor *nor) ++static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) + { + int tmp; +- u8 id[5]; +- u32 jedec; +- u16 ext_jedec; +- struct flash_info *info; ++ u8 id[SPI_NOR_MAX_ID_LEN]; ++ const struct flash_info *info; + +- tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, 5); ++ 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 ERR_PTR(tmp); + } +- jedec = id[0]; +- jedec = jedec << 8; +- jedec |= id[1]; +- jedec = jedec << 8; +- jedec |= id[2]; +- +- ext_jedec = id[3] << 8 | id[4]; + + for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { +- info = (void *)spi_nor_ids[tmp].driver_data; +- if (info->jedec_id == jedec) { +- if (info->ext_id == 0 || info->ext_id == ext_jedec) ++ info = &spi_nor_ids[tmp]; ++ if (info->id_len) { ++ if (!memcmp(info->id, id, info->id_len)) + return &spi_nor_ids[tmp]; + } + } +- dev_err(nor->dev, "unrecognized JEDEC id %06x\n", jedec); ++ dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n", ++ id[0], id[1], id[2]); + return ERR_PTR(-ENODEV); + } + +@@ -703,11 +1445,6 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, + if (ret) + return ret; + +- /* Wait until finished previous write command. */ +- ret = wait_till_ready(nor); +- if (ret) +- goto time_out; +- + write_enable(nor); + + nor->sst_write_second = false; +@@ -719,7 +1456,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, + + /* write one byte. */ + nor->write(nor, to, 1, retlen, buf); +- ret = wait_till_ready(nor); ++ ret = spi_nor_wait_till_ready(nor); + if (ret) + goto time_out; + } +@@ -731,7 +1468,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, + + /* write two bytes. */ + nor->write(nor, to, 2, retlen, buf + actual); +- ret = wait_till_ready(nor); ++ ret = spi_nor_wait_till_ready(nor); + if (ret) + goto time_out; + to += 2; +@@ -740,7 +1477,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, + nor->sst_write_second = false; + + write_disable(nor); +- ret = wait_till_ready(nor); ++ ret = spi_nor_wait_till_ready(nor); + if (ret) + goto time_out; + +@@ -751,7 +1488,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, + nor->program_opcode = SPINOR_OP_BP; + nor->write(nor, to, 1, retlen, buf + actual); + +- ret = wait_till_ready(nor); ++ ret = spi_nor_wait_till_ready(nor); + if (ret) + goto time_out; + write_disable(nor); +@@ -779,11 +1516,12 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, + if (ret) + return ret; + +- /* Wait until finished previous write command. */ +- ret = wait_till_ready(nor); +- if (ret) +- goto write_err; +- ++#ifdef CONFIG_HISI_SPI_BLOCK_PROTECT ++ if (nor->level && (to < nor->end_addr)) { ++ dev_err(nor->dev, "Error: The DMA write area was locked\n"); ++ return -EINVAL; ++ } ++#endif + write_enable(nor); + + page_offset = to & (nor->page_size - 1); +@@ -802,16 +1540,20 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, + if (page_size > nor->page_size) + page_size = nor->page_size; + +- wait_till_ready(nor); ++ ret = spi_nor_wait_till_ready(nor); ++ if (ret) ++ goto write_err; ++ + write_enable(nor); + + nor->write(nor, to + i, page_size, retlen, buf + i); + } + } + ++ ret = spi_nor_wait_till_ready(nor); + write_err: + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); +- return 0; ++ return ret; + } + + static int macronix_quad_enable(struct spi_nor *nor) +@@ -819,16 +1561,24 @@ static int macronix_quad_enable(struct spi_nor *nor) + int ret, val; + + val = read_sr(nor); ++ if (val < 0) ++ return val; ++ ++ if ((unsigned int)val & SR_QUAD_EN_MX) ++ return 0; ++ ++ /* Update the Quad Enable bit. */ ++ dev_info(nor->dev, "setting Macronix Quad Enable (non-volatile) bit\n"); ++ + write_enable(nor); + +- nor->cmd_buf[0] = val | SR_QUAD_EN_MX; +- nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0); ++ write_sr(nor, (u8)val | SR_QUAD_EN_MX); + +- if (wait_till_ready(nor)) ++ if (spi_nor_wait_till_ready(nor)) + return 1; + + ret = read_sr(nor); +- if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) { ++ if (!(ret > 0 && ((unsigned int)ret & SR_QUAD_EN_MX))) { + dev_err(nor->dev, "Macronix Quad bit not set\n"); + return -EINVAL; + } +@@ -847,23 +1597,38 @@ static int write_sr_cr(struct spi_nor *nor, u16 val) + nor->cmd_buf[0] = val & 0xff; + nor->cmd_buf[1] = (val >> 8); + +- return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2, 0); ++ return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2); + } + + static int spansion_quad_enable(struct spi_nor *nor) + { + int ret; +- int quad_en = CR_QUAD_EN_SPAN << 8; ++ u16 val; ++ ++ ret = read_cr(nor); ++ if (ret & CR_QUAD_EN_SPAN) ++ return 0; ++ ++ /* Update the Quad Enable bit. */ ++ dev_info(nor->dev, "setting Quad Enable (non-volatile) bit\n"); ++ ++ val = ((ret & 0xff) | CR_QUAD_EN_SPAN) << 8; ++ ++ ret = read_sr(nor); ++ val |= (ret & 0xff); + + write_enable(nor); + +- ret = write_sr_cr(nor, quad_en); ++ ret = write_sr_cr(nor, val); + if (ret < 0) { + dev_err(nor->dev, + "error while writing configuration register\n"); + return -EINVAL; + } + ++ if (spi_nor_wait_till_ready(nor)) ++ return 1; ++ + /* read back and check it */ + ret = read_cr(nor); + if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) { +@@ -874,18 +1639,128 @@ static int spansion_quad_enable(struct spi_nor *nor) + return 0; + } + +-static int set_quad_mode(struct spi_nor *nor, u32 jedec_id) ++static int micron_quad_enable(struct spi_nor *nor) ++{ ++ int ret; ++ u8 val; ++ ++ ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1); ++ if (ret < 0) { ++ dev_err(nor->dev, "error %d reading EVCR\n", ret); ++ return ret; ++ } ++ ++ write_enable(nor); ++ ++ /* set EVCR, enable quad I/O */ ++ nor->cmd_buf[0] = val & ~EVCR_QUAD_EN_MICRON; ++ ret = nor->write_reg(nor, SPINOR_OP_WD_EVCR, nor->cmd_buf, 1); ++ if (ret < 0) { ++ dev_err(nor->dev, "error while writing EVCR register\n"); ++ return ret; ++ } ++ ++ ret = spi_nor_wait_till_ready(nor); ++ if (ret) ++ return ret; ++ ++ /* read EVCR and check it */ ++ ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1); ++ if (ret < 0) { ++ dev_err(nor->dev, "error %d reading EVCR\n", ret); ++ return ret; ++ } ++ if (val & EVCR_QUAD_EN_MICRON) { ++ dev_err(nor->dev, "Micron EVCR Quad bit not clear\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int gd_quad_enable(struct spi_nor *nor) ++{ ++ int ret; ++ u16 val; ++ ++ /* First, Quad Enable for 16-Pin GD flash, use WRSR[01h] cmd */ ++ ret = read_cr(nor); ++ val = ((ret & 0xff) | CR_QUAD_EN_SPAN) << 8; ++ ++ ret = read_sr(nor); ++ val |= (ret & 0xff); ++ ++ write_enable(nor); ++ ++ ret = write_sr_cr(nor, val); ++ if (ret < 0) { ++ dev_err(nor->dev, ++ "error while writing config and status register\n"); ++ return -EINVAL; ++ } ++ ++ if (spi_nor_wait_till_ready(nor)) ++ return 1; ++ ++ /* read back and check it */ ++ ret = read_cr(nor); ++ if (ret & CR_QUAD_EN_SPAN) ++ return 0; ++ ++ /* Second, Quad Enable for 8-Pin GD flash, use WRCR[31h] cmd */ ++ ret = read_sr(nor); ++ if (!(ret & SR_WEL)) ++ write_enable(nor); ++ ++ ret = read_cr(nor); ++ nor->cmd_buf[0] = (ret & 0xff) | CR_QUAD_EN_SPAN; ++ ++ ret = nor->write_reg(nor, SPINOR_OP_WRCR, nor->cmd_buf, 1); ++ if (ret < 0) { ++ dev_err(nor->dev, "error while writing config register\n"); ++ return ret; ++ } ++ ++ if (spi_nor_wait_till_ready(nor)) ++ return 1; ++ ++ /* read back and check it */ ++ ret = read_cr(nor); ++ if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) { ++ dev_err(nor->dev, "GigaDevice Quad bit not set\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info) + { + int status; + +- switch (JEDEC_MFR(jedec_id)) { +- case CFI_MFR_MACRONIX: ++ switch (JEDEC_MFR(info)) { ++ case SNOR_MFR_ESMT: ++ case SNOR_MFR_MACRONIX: + status = macronix_quad_enable(nor); + if (status) { + dev_err(nor->dev, "Macronix quad-read not enabled\n"); + return -EINVAL; + } + return status; ++ case SNOR_MFR_MICRON: ++ status = micron_quad_enable(nor); ++ if (status) { ++ dev_err(nor->dev, "Micron quad-read not enabled\n"); ++ return -EINVAL; ++ } ++ return status; ++ case SNOR_MFR_GD: ++ status = gd_quad_enable(nor); ++ if (status) { ++ dev_err(nor->dev, "GD quad-read not enabled\n"); ++ return -EINVAL; ++ } ++ return status; + default: + status = spansion_quad_enable(nor); + if (status) { +@@ -899,26 +1774,362 @@ static int set_quad_mode(struct spi_nor *nor, u32 jedec_id) + static int spi_nor_check(struct spi_nor *nor) + { + if (!nor->dev || !nor->read || !nor->write || +- !nor->read_reg || !nor->write_reg || !nor->erase) { ++ !nor->read_reg || !nor->write_reg) { + pr_err("spi-nor: please fill all the necessary fields!\n"); + return -EINVAL; + } + +- if (!nor->read_id) +- nor->read_id = spi_nor_read_id; +- if (!nor->wait_till_ready) +- nor->wait_till_ready = spi_nor_wait_till_ready; ++ return 0; ++} ++ ++#ifdef CONFIG_HISI_SPI_BLOCK_PROTECT ++static void spi_lock_update_address(struct spi_nor *nor, const struct flash_info *info) ++{ ++ unsigned int lock_level_max, sectorsize, chipsize; ++ ++ if (!nor->level) { ++ nor->end_addr = 0; ++ dev_warn(nor->dev, "all blocks is unlocked.\n"); ++ return; ++ } ++ ++ sectorsize = info->sector_size; ++ chipsize = sectorsize * info->n_sectors; ++ lock_level_max = nor->lock_level_max; ++ ++ switch (JEDEC_MFR(info)) { ++ case SNOR_MFR_MACRONIX: ++ if (chipsize == _2M) { ++ if ((nor->level != lock_level_max) ++ && (nor->level != 1)) ++ nor->end_addr = chipsize - (sectorsize << ++ (lock_level_max - nor->level - 1)); ++ else ++ nor->end_addr = chipsize; ++ return; ++ } ++ ++ if (chipsize != _8M) ++ break; ++ case SNOR_MFR_ESMT: ++ /* this case is for ESMT and MXIC 8M devices */ ++ if (nor->level != lock_level_max) ++ nor->end_addr = chipsize - (sectorsize ++ << (lock_level_max - nor->level)); ++ else ++ nor->end_addr = chipsize; ++ return; ++ case SNOR_MFR_EON: ++ if (nor->level != lock_level_max) ++ nor->end_addr = chipsize - (sectorsize ++ << (nor->level - 1)); ++ else ++ nor->end_addr = chipsize; ++ return; ++ default: ++ break; ++ } ++ ++ /* general case */ ++ nor->end_addr = chipsize >> (lock_level_max - nor->level); ++} ++ ++static unsigned char hisi_bp_to_level(struct spi_nor *nor, ++ const struct flash_info *info, unsigned int bp_num) ++{ ++ int ret; ++ unsigned char val; ++ unsigned char level; ++ unsigned int chipsize; ++ ++ ret = spi_nor_wait_till_ready(nor); ++ BUG_ON(ret); ++ ++ ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val, 1); ++ if (ret < 0) { ++ dev_err(nor->dev, "error %d reading SR\n", ret); ++ return ret; ++ } ++ ++ if (bp_num == BP_NUM_3) ++ level = (val & SPI_NOR_SR_BP_MASK_3) >> SPI_NOR_SR_BP0_SHIFT; ++ else ++ level = (val & SPI_NOR_SR_BP_MASK_4) >> SPI_NOR_SR_BP0_SHIFT; ++ ++ /* dev_info(nor->dev, "the current level[%d]\n", level); */ ++ ++ if (bp_num == BP_NUM_4) { ++ nor->lock_level_max = LOCK_LEVEL_MAX(bp_num) - 5; ++ chipsize = info->sector_size * info->n_sectors; ++ if ((JEDEC_MFR(info) == SNOR_MFR_MACRONIX) ++ && (chipsize == _16M)) ++ nor->lock_level_max--; ++ } else ++ nor->lock_level_max = LOCK_LEVEL_MAX(bp_num); ++ /* dev_info(nor->dev, "Get the max bp level: [%d]\n", ++ * nor->lock_level_max); */ ++ ++ return level; ++} ++ ++static void hisi_get_spi_lock_info(struct spi_nor *nor, const struct flash_info *info) ++{ ++ unsigned int chipsize; ++ struct device *dev = nor->dev; ++ ++ chipsize = info->sector_size * info->n_sectors; ++ ++ /* read the BP bit in RDSR to check whether nor is lock or not */ ++ switch (JEDEC_MFR(info)) { ++ case SNOR_MFR_GD: ++ case SNOR_MFR_ESMT: ++ case SNOR_MFR_EON: ++ case SNOR_MFR_SPANSION: ++ /* BP bit convert to lock level */ ++ nor->level = hisi_bp_to_level(nor, info, BP_NUM_3); ++ break; ++ case SNOR_MFR_WINBOND: ++ /* BP bit convert to lock level */ ++ if (chipsize <= _16M) ++ nor->level = hisi_bp_to_level(nor, info, BP_NUM_3); ++ else ++ nor->level = hisi_bp_to_level(nor, info, BP_NUM_4); ++ break; ++ case SNOR_MFR_MACRONIX: ++ /* BP bit convert to lock level */ ++ if (chipsize <= _8M) ++ nor->level = hisi_bp_to_level(nor, info, BP_NUM_3); ++ else ++ nor->level = hisi_bp_to_level(nor, info, BP_NUM_4); ++ break; ++ default: ++ goto usage; ++ } ++ ++ spi_lock_update_address(nor, info); ++ if (nor->end_addr) ++ dev_info(dev, "Address range [0 => %#x] is locked.\n", ++ nor->end_addr); ++ return; ++usage: ++ dev_err(dev, "The ID: %#x isn't in the BP table," ++ " Current device can't not protect\n", ++ JEDEC_MFR(info)); ++} ++#endif/* CONFIG_HISI_SPI_BLOCK_PROTECT */ ++ ++static int spi_nor_midx2proto(int midx, enum spi_nor_protocol *proto) ++{ ++ switch (midx) { ++ case SNOR_MIDX_SLOW: ++ case SNOR_MIDX_1_1_1: ++ *proto = SNOR_PROTO_1_1_1; ++ break; ++ ++ case SNOR_MIDX_1_1_2: ++ *proto = SNOR_PROTO_1_1_2; ++ break; ++ ++ case SNOR_MIDX_1_2_2: ++ *proto = SNOR_PROTO_1_2_2; ++ break; ++ case SNOR_MIDX_1_1_4: ++ *proto = SNOR_PROTO_1_1_4; ++ break; ++ ++ case SNOR_MIDX_1_4_4: ++ *proto = SNOR_PROTO_1_4_4; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int spi_nor_sr3_to_reset(struct spi_nor *nor) ++{ ++ int ret; ++ unsigned char val; ++ ++ ret = nor->read_reg(nor, SPINOR_OP_RDSR3, &val, 1); ++ if (ret < 0) { ++ dev_err(nor->dev, "error %d reading Status Reg 3.\n", ret); ++ return ret; ++ } ++ ++ if (SPI_NOR_GET_RST(val)) { ++ dev_dbg(nor->dev, "Device has worked on RESET#.\n"); ++ return 0; ++ } ++ ++ dev_dbg(nor->dev, "Start to enable RESET# function.\n"); ++ val = SPI_NOR_SET_RST(val); ++ ++ nor->write_reg(nor, SPINOR_OP_WRSR3, &val, 1); ++ if (ret < 0) { ++ dev_err(nor->dev, "error while writing Status Reg 3.\n"); ++ return ret; ++ } ++ ++ dev_dbg(nor->dev, "Enable RESET# function success.\n"); ++ ++ return 0; ++} ++ ++static int spi_nor_reset_pin_enable(struct spi_nor *nor, ++ const struct flash_info *info) ++{ ++ switch (JEDEC_MFR(info)) { ++ case SNOR_MFR_WINBOND: ++ case SNOR_MFR_GD: ++ return spi_nor_sr3_to_reset(nor); ++ default: ++ return 0; ++ } ++} ++ ++static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info, ++ const struct spi_nor_basic_flash_parameter *params, ++ const struct spi_nor_modes *modes) ++{ ++ bool enable_quad_io; ++ u32 rd_modes, wr_modes; ++ const struct spi_nor_erase_type *erase_type; ++ const struct spi_nor_read_op *read; ++ int rd_midx, wr_midx, err = 0; ++ ++ rd_modes = modes->rd_modes; ++ wr_modes = modes->wr_modes; ++ ++ /* Setup read operation. */ ++ rd_midx = fls(params->rd_modes & rd_modes) - 1; ++ if (spi_nor_midx2proto(rd_midx, &nor->read_proto)) { ++ dev_err(nor->dev, "invalid (fast) read\n"); ++ return -EINVAL; ++ } ++ read = ¶ms->reads[rd_midx]; ++ nor->read_opcode = read->opcode; ++ nor->read_dummy = read->num_mode_clocks + read->num_wait_states; ++ ++ /* Set page program op code and protocol. */ ++ wr_midx = fls(params->wr_modes & wr_modes) - 1; ++ if (spi_nor_midx2proto(wr_midx, &nor->write_proto)) { ++ dev_err(nor->dev, "invalid page program\n"); ++ return -EINVAL; ++ } ++ nor->program_opcode = params->page_programs[wr_midx]; ++ ++ /* Set sector erase op code and size. */ ++ erase_type = ¶ms->erase_types[0]; ++#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS ++ for (i = 1; i < SNOR_MAX_ERASE_TYPES; ++i) ++ if (params->erase_types[i].size == 0x0c) ++ erase_type = ¶ms->erase_types[i]; ++#endif ++ nor->erase_opcode = erase_type->opcode; ++ nor->mtd.erasesize = (1 << erase_type->size); ++ ++ enable_quad_io = (SNOR_PROTO_DATA_FROM_PROTO(nor->read_proto) == 4 || ++ SNOR_PROTO_DATA_FROM_PROTO(nor->write_proto) == 4); ++ ++ /* Enable Quad I/O if needed. */ ++ if (enable_quad_io && params->enable_quad_io) { ++ err = params->enable_quad_io(nor); ++ if (err) { ++ dev_err(nor->dev, ++ "failed to enable the Quad I/O mode\n"); ++ return err; ++ } ++ } ++ ++ /* ++ * Fix erase protocol if needed, read and write protocols should ++ * already be valid. ++ */ ++ nor->erase_proto = SNOR_PROTO_1_1_1; ++ ++ dev_dbg(nor->dev, ++ "(Fast) Read: opcode=%02Xh, protocol=%03x, mode=%u, wait=%u\n", ++ nor->read_opcode, nor->read_proto, ++ read->num_mode_clocks, read->num_wait_states); ++ dev_dbg(nor->dev, ++ "Page Program: opcode=%02Xh, protocol=%03x\n", ++ nor->program_opcode, nor->write_proto); ++ dev_dbg(nor->dev, ++ "Sector Erase: opcode=%02Xh, protocol=%03x, sector size=%zu\n", ++ nor->erase_opcode, nor->erase_proto, nor->mtd.erasesize); ++ ++ return 0; ++} ++ ++static int spi_nor_config(struct spi_nor *nor, const struct flash_info *info, ++ const struct spi_nor_basic_flash_parameter *params, ++ struct spi_nor_modes *modes) ++{ ++ int ret; ++ ++ if (params) { ++ ret = spi_nor_setup(nor, info, params, modes); ++ if (ret) ++ return ret; ++ } else if (modes->rd_modes & SNOR_MODE_1_1_4 && ++ info->flags & SPI_NOR_QUAD_READ) { ++ /* ++ * This branch is spcially for some devices which can ++ * not be stated by params, but only SPI_NOR_QUAD_READ, ++ * it just supports the protocol 1_1_4. ++ */ ++ if (spi_nor_wait_till_ready(nor)) ++ return 1; ++ ++ ret = set_quad_mode(nor, info); ++ if (ret) { ++ dev_err(nor->dev, "quad mode not supported\n"); ++ return ret; ++ } ++ nor->read_proto = SNOR_PROTO_1_1_4; ++ nor->read_opcode = SPINOR_OP_READ_1_1_4; ++ nor->read_dummy = 8; ++ } else if (modes->rd_modes & SNOR_MODE_1_1_2 && ++ info->flags & SPI_NOR_DUAL_READ) { ++ /* ++ * This branch is spcially for some devices which can ++ * not be stated by params, but only SPI_NOR_DUAL_READ, ++ * it just supports the protocol 1_1_2. ++ */ ++ nor->read_proto = SNOR_PROTO_1_1_2; ++ nor->read_opcode = SPINOR_OP_READ_1_1_2; ++ nor->read_dummy = 8; ++ } else { ++ if (modes->rd_modes & SNOR_MODE_1_1_1) { ++ nor->read_opcode = SPINOR_OP_READ_FAST; ++ nor->read_dummy = 8; ++ } else { ++ nor->read_opcode = SPINOR_OP_READ; ++ nor->read_dummy = 0; ++ } ++ } ++ ++ if (!(modes->rd_modes & (SNOR_MODE_1_1_4 | SNOR_MODE_1_4_4))) { ++ ret = spi_nor_reset_pin_enable(nor, info); ++ if (ret < 0) { ++ dev_err(nor->dev, "Enable RESET# fail.\n"); ++ return ret; ++ } ++ } + + return 0; + } + +-int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) ++int spi_nor_scan(struct spi_nor *nor, const char *name, ++ struct spi_nor_modes *modes) + { +- const struct spi_device_id *id = NULL; +- struct flash_info *info; ++ const struct spi_nor_basic_flash_parameter *params = NULL; ++ const struct flash_info *info = NULL; + struct device *dev = nor->dev; +- struct mtd_info *mtd = nor->mtd; +- struct device_node *np = dev->of_node; ++ struct mtd_info *mtd = &nor->mtd; ++ struct device_node *np = nor->flash_node; + int ret; + int i; + +@@ -926,19 +2137,30 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) + if (ret) + return ret; + +- id = spi_nor_match_id(name); +- if (!id) ++ /* Reset SPI protocol for all commands */ ++ nor->erase_proto = SNOR_PROTO_1_1_1; ++ nor->read_proto = SNOR_PROTO_1_1_1; ++ nor->write_proto = SNOR_PROTO_1_1_1; ++ ++ if (name) ++ info = spi_nor_match_id(name); ++ /* Try to auto-detect if chip name wasn't specified or not found */ ++ if (!info) ++ info = spi_nor_read_id(nor); ++ if (IS_ERR_OR_NULL(info)) + return -ENOENT; + +- info = (void *)id->driver_data; +- +- if (info->jedec_id) { +- const struct spi_device_id *jid; ++ /* ++ * If caller has specified name of flash model that can normally be ++ * detected using JEDEC, let's verify it. ++ */ ++ if (name && info->id_len) { ++ const struct flash_info *jinfo; + +- jid = nor->read_id(nor); +- if (IS_ERR(jid)) { +- return PTR_ERR(jid); +- } else if (jid != id) { ++ jinfo = spi_nor_read_id(nor); ++ if (IS_ERR(jinfo)) { ++ return PTR_ERR(jinfo); ++ } else if (jinfo != info) { + /* + * JEDEC knows better, so overwrite platform ID. We + * can't trust partitions any longer, but we'll let +@@ -947,28 +2169,37 @@ 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", +- jid->name, id->name); +- id = jid; +- info = (void *)jid->driver_data; ++ jinfo->name, info->name); ++ info = jinfo; + } + } ++ if (info->params) ++ params = info->params; + + mutex_init(&nor->lock); + ++#ifdef CONFIG_HISI_SPI_BLOCK_PROTECT ++ /* NOR block protection support */ ++ hisi_get_spi_lock_info(nor, info); ++#else + /* +- * Atmel, SST and Intel/Numonyx serial nor tend to power +- * up with the software protection bits set ++ * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up ++ * with the software protection bits set + */ + +- if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ATMEL || +- JEDEC_MFR(info->jedec_id) == CFI_MFR_INTEL || +- JEDEC_MFR(info->jedec_id) == CFI_MFR_SST) { ++ if (JEDEC_MFR(info) == SNOR_MFR_ATMEL || ++ JEDEC_MFR(info) == SNOR_MFR_INTEL || ++ JEDEC_MFR(info) == SNOR_MFR_SST || ++ info->flags & SPI_NOR_HAS_LOCK) { + write_enable(nor); + write_sr(nor, 0); ++ spi_nor_wait_till_ready(nor); + } ++#endif + + if (!mtd->name) + mtd->name = dev_name(dev); ++ mtd->priv = nor; + mtd->type = MTD_NORFLASH; + mtd->writesize = 1; + mtd->flags = MTD_CAP_NORFLASH; +@@ -976,10 +2207,19 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) + mtd->_erase = spi_nor_erase; + mtd->_read = spi_nor_read; + +- /* nor protection support for STmicro chips */ +- if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) { ++ /* NOR protection support for STmicro/Micron chips and similar */ ++ if (JEDEC_MFR(info) == SNOR_MFR_MICRON || ++ JEDEC_MFR(info) == SNOR_MFR_WINBOND || ++ info->flags & SPI_NOR_HAS_LOCK) { ++ nor->flash_lock = stm_lock; ++ nor->flash_unlock = stm_unlock; ++ nor->flash_is_locked = stm_is_locked; ++ } ++ ++ if (nor->flash_lock && nor->flash_unlock && nor->flash_is_locked) { + mtd->_lock = spi_nor_lock; + mtd->_unlock = spi_nor_unlock; ++ mtd->_is_locked = spi_nor_is_locked; + } + + /* sst nor chips use AAI word program */ +@@ -988,9 +2228,10 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) + else + mtd->_write = spi_nor_write; + +- if ((info->flags & USE_FSR) && +- nor->wait_till_ready == spi_nor_wait_till_ready) +- nor->wait_till_ready = spi_nor_wait_till_fsr_ready; ++ if (info->flags & USE_FSR) ++ nor->flags |= SNOR_F_USE_FSR; ++ if (info->flags & SPI_NOR_HAS_TB) ++ nor->flags |= SNOR_F_HAS_SR_TB; + + #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS + /* prefer "small sector" erase if possible */ +@@ -1017,85 +2258,58 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) + if (np) { + /* If we were instantiated by DT, use it */ + if (of_property_read_bool(np, "m25p,fast-read")) +- nor->flash_read = SPI_NOR_FAST; ++ modes->rd_modes |= SNOR_MODE_1_1_1; + else +- nor->flash_read = SPI_NOR_NORMAL; ++ modes->rd_modes &= ~SNOR_MODE_1_1_1; + } else { + /* If we weren't instantiated by DT, default to fast-read */ +- nor->flash_read = SPI_NOR_FAST; ++ modes->rd_modes |= SNOR_MODE_1_1_1; + } + + /* Some devices cannot do fast-read, no matter what DT tells us */ + if (info->flags & SPI_NOR_NO_FR) +- nor->flash_read = SPI_NOR_NORMAL; +- +- /* Quad/Dual-read mode takes precedence over fast/normal */ +- if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) { +- ret = set_quad_mode(nor, info->jedec_id); +- if (ret) { +- dev_err(dev, "quad mode not supported\n"); +- return ret; +- } +- nor->flash_read = SPI_NOR_QUAD; +- } else if (mode == SPI_NOR_DUAL && info->flags & SPI_NOR_DUAL_READ) { +- nor->flash_read = SPI_NOR_DUAL; +- } +- +- /* Default commands */ +- switch (nor->flash_read) { +- case SPI_NOR_QUAD: +- nor->read_opcode = SPINOR_OP_READ_1_1_4; +- break; +- case SPI_NOR_DUAL: +- nor->read_opcode = SPINOR_OP_READ_1_1_2; +- break; +- case SPI_NOR_FAST: +- nor->read_opcode = SPINOR_OP_READ_FAST; +- break; +- case SPI_NOR_NORMAL: +- nor->read_opcode = SPINOR_OP_READ; +- break; +- default: +- dev_err(dev, "No Read opcode defined\n"); +- return -EINVAL; +- } ++ modes->rd_modes &= ~SNOR_MODE_1_1_1; + + nor->program_opcode = SPINOR_OP_PP; + ++ /* ++ * Configure the SPI memory: ++ * - select op codes for (Fast) Read, Page Program and Sector Erase. ++ * - set the number of dummy cycles (mode cycles + wait states). ++ * - set the SPI protocols for register and memory accesses. ++ * - set the Quad Enable bit if needed (required by SPI x-y-4 protos). ++ */ ++ ret = spi_nor_config(nor, info, params, modes); ++ if (ret) ++ return ret; ++ + if (info->addr_width) + nor->addr_width = info->addr_width; + else if (mtd->size > 0x1000000) { + /* enable 4-byte addressing if the device exceeds 16MiB */ + nor->addr_width = 4; +- if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) { +- /* Dedicated 4-byte command set */ +- switch (nor->flash_read) { +- case SPI_NOR_QUAD: +- nor->read_opcode = SPINOR_OP_READ4_1_1_4; +- break; +- case SPI_NOR_DUAL: +- nor->read_opcode = SPINOR_OP_READ4_1_1_2; +- break; +- case SPI_NOR_FAST: +- nor->read_opcode = SPINOR_OP_READ4_FAST; +- break; +- case SPI_NOR_NORMAL: +- nor->read_opcode = SPINOR_OP_READ4; +- break; +- } +- nor->program_opcode = SPINOR_OP_PP_4B; +- /* No small sector erase for 4-byte command set */ +- nor->erase_opcode = SPINOR_OP_SE_4B; +- mtd->erasesize = info->sector_size; +- } else +- set_4byte(nor, info->jedec_id, 1); ++ if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || ++ info->flags & SPI_NOR_4B_OPCODES) ++ spi_nor_set_4byte_opcodes(nor, info); ++ else ++ set_4byte(nor, info, 1); + } else { + nor->addr_width = 3; + } + +- nor->read_dummy = spi_nor_read_dummy_cycles(nor); ++ /* choose the suitable clockrate */ ++ if (info->clkrate && (modes->rd_modes != SNOR_MODE_1_1_1)) ++ nor->clkrate = info->clkrate; ++ else ++ nor->clkrate = 24000000; ++ ++ if (nor->addr_width > SPI_NOR_MAX_ADDR_WIDTH) { ++ dev_err(dev, "address width is too large: %u\n", ++ nor->addr_width); ++ return -EINVAL; ++ } + +- dev_info(dev, "%s (%lld Kbytes)\n", id->name, ++ dev_info(dev, "%s (%lld Kbytes)\n", info->name, + (long long)mtd->size >> 10); + + dev_dbg(dev, +@@ -1118,11 +2332,11 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) + } + EXPORT_SYMBOL_GPL(spi_nor_scan); + +-static const struct spi_device_id *spi_nor_match_id(const char *name) ++static const struct flash_info *spi_nor_match_id(const char *name) + { +- const struct spi_device_id *id = spi_nor_ids; ++ const struct flash_info *id = spi_nor_ids; + +- while (id->name[0]) { ++ while (id->name) { + if (!strcmp(name, id->name)) + return id; + id++; +@@ -1130,6 +2344,64 @@ static const struct spi_device_id *spi_nor_match_id(const char *name) + return NULL; + } + ++/******************************************************************************/ ++void spi_nor_driver_shutdown(struct spi_nor *nor) ++{ ++ /* disable 4-byte addressing if the device exceeds 16MiB */ ++ if (nor->addr_width == 4) { ++ const struct flash_info *info = NULL; ++ ++ info = spi_nor_read_id(nor); ++ set_4byte(nor, info, 0); ++ } ++ return; ++} ++ ++#ifdef CONFIG_PM ++/******************************************************************************/ ++int spi_nor_suspend(struct spi_nor *nor, pm_message_t state) ++{ ++ return spi_nor_wait_till_ready(nor); ++} ++ ++/******************************************************************************/ ++int spi_nor_resume(struct spi_nor *nor) ++{ ++ int ret; ++ const struct flash_info *info = NULL; ++ const struct spi_nor_basic_flash_parameter *params = NULL; ++ struct spi_nor_modes modes = { ++ .rd_modes = SNOR_MODE_SLOW, ++ .wr_modes = SNOR_MODE_1_1_1, ++ }; ++ ++ modes.rd_modes |= SNOR_MODE_1_1_1 ++ | SNOR_MODE_1_1_2 ++ | SNOR_MODE_1_2_2; ++#ifndef CONFIG_CLOSE_SPI_8PIN_4IO ++ modes.rd_modes |= SNOR_MODE_1_1_4 | SNOR_MODE_1_4_4; ++ modes.wr_modes |= SNOR_MODE_1_1_4 | SNOR_MODE_1_4_4; ++#endif ++ ++ if (!info) ++ info = spi_nor_read_id(nor); ++ ++ /* Quad mode takes precedence over fast/normal */ ++ if (info->params) ++ params = info->params; ++ ++ ret = spi_nor_config(nor, info, params, &modes); ++ if (ret) ++ return ret; ++ ++ /* enable 4-byte addressing if the device exceeds 16MiB */ ++ if (nor->addr_width == 4 && JEDEC_MFR(info) != SNOR_MFR_SPANSION) ++ set_4byte(nor, info, 1); ++ ++ return 0; ++} ++#endif /* End of CONFIG_PM */ ++ + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Huang Shijie "); + MODULE_AUTHOR("Mike Lavender"); +diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig +index e942173..1389b6c 100644 +--- a/drivers/net/ethernet/hisilicon/Kconfig ++++ b/drivers/net/ethernet/hisilicon/Kconfig +@@ -24,4 +24,19 @@ config HIX5HD2_GMAC + help + This selects the hix5hd2 mac family network device. + ++config HISI_FEMAC ++ tristate "Hisilicon Fast Ethernet MAC device support" ++ depends on HAS_IOMEM ++ select PHYLIB ++ select RESET_CONTROLLER ++ help ++ This selects the Hisilicon Fast Ethernet MAC device(FEMAC). ++ The FEMAC receives and transmits data over Ethernet ++ ports at 10/100 Mbps in full-duplex or half-duplex mode. ++ The FEMAC exchanges data with the CPU, and supports ++ the energy efficient Ethernet (EEE). ++ ++source "drivers/net/ethernet/hisilicon/higmac/Kconfig" ++source "drivers/net/ethernet/hisilicon/hieth/Kconfig" ++ + endif # NET_VENDOR_HISILICON +diff --git a/drivers/net/ethernet/hisilicon/Makefile b/drivers/net/ethernet/hisilicon/Makefile +index 9175e846..75126b4 100644 +--- a/drivers/net/ethernet/hisilicon/Makefile ++++ b/drivers/net/ethernet/hisilicon/Makefile +@@ -3,3 +3,6 @@ + # + + obj-$(CONFIG_HIX5HD2_GMAC) += hix5hd2_gmac.o ++obj-$(CONFIG_HISI_FEMAC) += hisi_femac.o ++obj-$(CONFIG_HIETH_GMAC) += higmac/ ++obj-$(CONFIG_HIETH_SWITCH_FABRIC) += hieth/ +diff --git a/drivers/net/ethernet/hisilicon/hieth/Kconfig b/drivers/net/ethernet/hisilicon/hieth/Kconfig +new file mode 100644 +index 0000000..2c359ce +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hieth/Kconfig +@@ -0,0 +1,57 @@ ++# ++# hieth family network device configuration ++# ++ ++menuconfig HIETH_SWITCH_FABRIC ++ tristate "hieth(switch fabric) family network device support" ++ select PHYLIB ++ select RESET_CONTROLLER ++ help ++ This selects the hieth family network device. ++ The hieth switch fabric (SF) receives and transmits data over two Ethernet ++ ports at 10/100 Mbit/s in full-duplex or half-duplex mode. ++ The Ethernet port exchanges data with the CPU port, and supports ++ the energy efficient Ethernet (EEE). ++ ++if HIETH_SWITCH_FABRIC ++ ++config HIETH_MAX_RX_POOLS ++ int "hieth max rx pool size" ++ default "1024" ++ help ++ hieth max static rx pool size. ++ ++config TX_FLOW_CTRL_SUPPORT ++ bool "tx flow ctrl supported" ++ default y ++ help ++ Tx flow ctrl supported, default is enabled. ++ When we has no buffer to receive packet, ++ we will send pause frame. ++ Rx flow ctrl default is enabled, cannot be disabled. ++ ++config TX_FLOW_CTRL_ACTIVE_THRESHOLD ++ int "tx flow ctrl active threshold" ++ default "3" ++ range 1 31 ++ help ++ The threshold for activing tx flow ctrl. ++ When the left amount of receive queue descriptors is below this threshold, ++ hardware will send pause frame immediately. ++ We advise this value is set between 1 and 10. Too bigger is not a good choice. ++ This value must be smaller than tx flow ctrl deactive threshold. ++ ++config TX_FLOW_CTRL_DEACTIVE_THRESHOLD ++ int "tx flow ctrl deactive threshold" ++ default "5" ++ range 1 31 ++ help ++ The threshold for deactiving tx flow ctrl. ++ When the left amount of receive queue descriptors is above or equal with this threshold, ++ hardware will exit flow control state. ++ We advise this value is set between 1 and 10. Too bigger is not a good choice. ++ This value must be larger than tx flow ctrl active threshold. ++ ++endif # HIETH_SWITCH_FABRIC ++ ++#vim: set ts=8 sw=8 tw=78: +diff --git a/drivers/net/ethernet/hisilicon/hieth/Makefile b/drivers/net/ethernet/hisilicon/hieth/Makefile +new file mode 100644 +index 0000000..28ddee5 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hieth/Makefile +@@ -0,0 +1,5 @@ ++# ++# Makefile for the hisilicon hieth device drivers. ++# ++ ++obj-$(CONFIG_HIETH_SWITCH_FABRIC) += mdio.o hieth.o phy.o autoeee.o proc.o +diff --git a/drivers/net/ethernet/hisilicon/hieth/autoeee.c b/drivers/net/ethernet/hisilicon/hieth/autoeee.c +new file mode 100644 +index 0000000..970ea04 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hieth/autoeee.c +@@ -0,0 +1,260 @@ ++#include ++#include "phy.h" ++#include "hieth.h" ++ ++/*----------------------------Macro definition-------------------------------*/ ++#define NO_EEE 0 ++#define MAC_EEE 1 ++#define PHY_EEE 2 ++#define PARTNER_EEE 2 ++ ++#define debug(fmt...) ++struct phy_info { ++ char *name; ++ int phy_id; ++ char eee_available;/* eee support by this phy */ ++ int (*eee_init)(struct phy_device *phy_dev); ++}; ++ ++/* GMAC register definition */ ++#define EEE_ENABLE 0x488 ++#define BIT_EEE_ENABLE (1 << 0) ++#define EEE_TIMER 0x48C ++#define EEE_LINK_STATUS 0x490 ++#define BIT_PHY_LINK_STATUS (1 << 0) ++#define EEE_TIME_CLK_CNT 0x494 ++ ++/* ----------------------------phy register-------------------------------*/ ++/* MMD: MDIO Manageable Device */ ++#define MACR 0x0D ++#define MAADR 0x0E ++#define EEE_DEV 0x3 ++#define EEE_CAPABILITY 0x14 ++#define EEELPAR_DEV 0x7 ++#define EEELPAR 0x3D /* EEE link partner ability register */ ++#define EEE_ADVERTISE 0x3c ++#define LP_1000BASE_EEE (1 << 2) ++#define LP_100BASE_EEE (1 << 1) ++ ++static struct phy_info phy_info_table[]; ++ ++static struct phy_info *phy_search_ids(int phy_id) ++{ ++ int i; ++ struct phy_info *fit_info = NULL; ++ ++ for (i = 0; phy_info_table[i].name != NULL; i++) { ++ if (phy_id == phy_info_table[i].phy_id) ++ fit_info = &phy_info_table[i]; ++ } ++ ++ return fit_info; ++} ++ ++static inline int phy_mmd_read(struct phy_device *phy_dev, ++ u32 mmd_device, u32 regnum) ++{ ++ phy_write(phy_dev, MACR, mmd_device);/* function = 00 address */ ++ phy_write(phy_dev, MAADR, regnum); ++ phy_write(phy_dev, MACR, 0x4000 | mmd_device);/* function = 01 data */ ++ ++ return phy_read(phy_dev, MAADR); ++} ++ ++static inline int phy_mmd_write(struct phy_device *phy_dev, ++ u32 mmd_device, u32 regnum, u16 val) ++{ ++ phy_write(phy_dev, MACR, mmd_device);/* function = 00 address */ ++ phy_write(phy_dev, MAADR, regnum); ++ phy_write(phy_dev, MACR, 0x4000 | mmd_device);/* function = 01 data */ ++ ++ return phy_write(phy_dev, MAADR, val); ++} ++ ++static int smsc_lan8740_init(struct phy_device *phy_dev) ++{ ++ static int first_time; ++ int v, eee_type = 0; ++ ++ if (!first_time) { ++ /* Realtek LAN 8740 start to enable eee */ ++ int eee_lan; ++ ++ eee_lan = phy_read(phy_dev, 0x10); ++ eee_lan |= 0x4; ++ phy_write(phy_dev, 0x10, eee_lan); ++ eee_lan = phy_read(phy_dev, 0x10); ++ debug("eee enable bit[45?] :%x\n", eee_lan); ++ /* auto negotiate after enable eee*/ ++ eee_lan = phy_read(phy_dev, 0x0); ++ eee_lan |= 0x200; ++ phy_write(phy_dev, 0x0, eee_lan); ++ first_time = 1; ++ } ++ ++ v = phy_mmd_read(phy_dev, EEELPAR_DEV, EEELPAR); ++ debug("EEELPAR = 0x%x\n", v); ++ ++ if (v & LP_100BASE_EEE) ++ eee_type |= HIETH_P_MAC_PORTSET_SPD_100M; ++ ++ return eee_type; ++} ++ ++#define RTL8211EG_MAC 0 ++#if RTL8211EG_MAC ++static int rtl8211EG_mac_init(struct phy_device *phy_dev) ++{ ++ static int first_time_rtl; ++ /* Realtek 8211EG start reset to change eee to mac */ ++ int v, eee_type = 0; ++ ++ if (!first_time_rtl) { ++ int tmp = 0; ++ ++ phy_write(phy_dev, 0x1f, 0x0); ++ phy_write(phy_dev, MII_BMCR, BMCR_RESET); /* reset phy */ ++ do { /* wait phy restart over */ ++ udelay(1); ++ tmp = phy_read(phy_dev, MII_BMSR); ++ /* no need to wait AN finished */ ++ tmp &= (BMSR_ANEGCOMPLETE | BMSR_ANEGCAPABLE); ++ } while (!tmp); ++ ++ phy_write(phy_dev, 0x1f, 0x7); ++ phy_write(phy_dev, 0x1e, 0x20); ++ phy_write(phy_dev, 0x1b, 0xa03a); ++ phy_write(phy_dev, 0x1f, 0x0); ++ ++ first_time_rtl = 1; ++ } ++ ++ v = phy_mmd_read(phy_dev, EEELPAR_DEV, EEELPAR); ++ ++ if (v & LP_100BASE_EEE) ++ eee_type |= HIETH_P_MAC_PORTSET_SPD_100M; ++ ++ return eee_type; ++} ++#else ++static int rtl8211EG_init(struct phy_device *phy_dev) ++{ ++ int eee_type = 0, v; ++ ++ v = phy_mmd_read(phy_dev, EEELPAR_DEV, EEELPAR); ++ debug("EEELPAR = 0x%x\n", v); ++ ++ if (v & LP_100BASE_EEE) ++ eee_type |= HIETH_P_MAC_PORTSET_SPD_100M; ++ ++ return eee_type; ++} ++#endif ++ ++static int festa_v200_init(struct phy_device *phy_dev) ++{ ++ static int first_time_init; ++ int v, eee_type = 0; ++ ++ if (!first_time_init) { ++ /* EEE_CAPABILITY register: support 100M-BaseT */ ++ v = phy_mmd_read(phy_dev, EEE_DEV, EEE_CAPABILITY); ++ phy_mmd_write(phy_dev, EEE_DEV, EEE_CAPABILITY, v|(1<<1)); ++ ++ /* EEE_ADVERTISEMENT register: advertising 100M-BaseT */ ++ v = phy_mmd_read(phy_dev, EEELPAR_DEV, EEE_ADVERTISE); ++ phy_mmd_write(phy_dev, EEELPAR_DEV, EEE_ADVERTISE, v|(1<<1)); ++ ++ v = phy_read(phy_dev, MII_BMCR); ++ v |= (BMCR_ANENABLE | BMCR_ANRESTART); ++ phy_write(phy_dev, MII_BMCR, v);/* auto-neg restart */ ++ ++ first_time_init = 1; ++ } ++ ++ v = phy_mmd_read(phy_dev, EEELPAR_DEV, EEELPAR); ++ debug("EEELPAR = 0x%x\n", v); ++ ++ if (v & LP_100BASE_EEE) ++ eee_type |= HIETH_P_MAC_PORTSET_SPD_100M; ++ ++ return eee_type; ++} ++ ++static struct phy_info phy_info_table[] = { ++ /* phy_name phy_id eee_available phy_driver */ ++ /* SMSC */ ++ {"SMSC LAN8740", 0x0007c110, MAC_EEE, &smsc_lan8740_init}, ++ /* Realtek */ ++#if RTL8211EG_MAC ++ {"Realtek 8211EG", 0x001cc915, MAC_EEE, &rtl8211EG_mac_init}, ++#else ++ {"Realtek 8211EG", 0x001cc915, PHY_EEE, &rtl8211EG_init}, ++#endif ++ {"Festa V200", HISILICON_PHY_ID_FESTAV200, MAC_EEE, &festa_v200_init}, ++ {"Festa V300", HISILICON_PHY_ID_FESTAV300, MAC_EEE, &festa_v200_init}, ++ {0, 0, 0, 0}, ++}; ++ ++void hieth_autoeee_init(struct hieth_netdev_priv *priv, int link_stat) ++{ ++ int phy_id = priv->phy->phy_id; ++ struct phy_info *phy_info; ++ ++ if (priv->eee_init) ++ goto eee_init; ++ ++ phy_info = phy_search_ids(phy_id); ++ if (phy_info) { ++ int eee_available, lp_eee_capable, v; ++ ++ eee_available = phy_info->eee_available; ++ debug("fit phy_id:0x%x, phy_name:%s, eee:%d\n", ++ phy_info->phy_id, phy_info->name, eee_available); ++ ++ if (!eee_available) ++ goto not_support; ++ ++ if (eee_available == PHY_EEE) { ++ debug("enter phy-EEE mode\n"); ++ v = readl(priv->glb_base + EEE_ENABLE); ++ v &= ~BIT_EEE_ENABLE;/* disable auto-EEE */ ++ writel(v, priv->glb_base + EEE_ENABLE); ++ return; ++ } ++ ++ priv->eee_init = phy_info->eee_init; ++eee_init: ++ lp_eee_capable = priv->eee_init(priv->phy); ++ if (link_stat & HIETH_P_MAC_PORTSET_LINKED) { ++ if (lp_eee_capable & link_stat) { ++ /* EEE_1us: 0x7c for 125M */ ++ writel(0x7c, priv->glb_base + EEE_TIME_CLK_CNT); ++ writel(0x4002710, priv->glb_base + EEE_TIMER); ++ ++ v = readl(priv->glb_base + EEE_LINK_STATUS); ++ v |= 0x3 << 1;/* auto EEE and ... */ ++ v |= BIT_PHY_LINK_STATUS;/* phy linkup */ ++ writel(v, priv->glb_base + EEE_LINK_STATUS); ++ ++ v = readl(priv->glb_base + EEE_ENABLE); ++ v |= BIT_EEE_ENABLE;/* enable EEE */ ++ writel(v, priv->glb_base + EEE_ENABLE); ++ ++ debug("enter auto-EEE mode\n"); ++ } else { ++ debug("link partner not support EEE\n"); ++ } ++ } else { ++ v = readl(priv->glb_base + EEE_LINK_STATUS); ++ v &= ~(BIT_PHY_LINK_STATUS);/* phy linkdown */ ++ writel(v, priv->glb_base + EEE_LINK_STATUS); ++ } ++ ++ return; ++ } ++ ++not_support: ++ priv->eee_init = NULL; ++ debug("non-EEE mode\n"); ++} +diff --git a/drivers/net/ethernet/hisilicon/hieth/hieth.c b/drivers/net/ethernet/hisilicon/hieth/hieth.c +new file mode 100644 +index 0000000..8b8ad4d +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hieth/hieth.c +@@ -0,0 +1,2016 @@ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "hieth.h" ++#include "mdio.h" ++#include "proc.h" ++#include "tso.h" ++ ++#ifdef HIETH_TSO_SUPPORTED ++#define E_MAC_TX_FAIL 2 ++#define E_MAC_SW_GSO 3 ++#endif ++ ++#define FCS_BYTES 4 ++ ++/*----------------------------Global variable-------------------------------*/ ++struct hieth_phy_param_s hieth_phy_param[HIETH_MAX_PORT]; ++ ++#define FC_ACTIVE_MIN 1 ++#define FC_ACTIVE_DEFAULT 3 ++#define FC_ACTIVE_MAX 31 ++#define FC_DEACTIVE_MIN 1 ++#define FC_DEACTIVE_DEFAULT 5 ++#define FC_DEACTIVE_MAX 31 ++ ++/*----------------------------Local variable-------------------------------*/ ++static struct net_device *hieth_devs_save[HIETH_MAX_PORT] = { NULL, NULL }; ++static struct hieth_netdev_priv hieth_priv; ++ ++/* real port count */ ++static int hieth_real_port_cnt; ++/* default, eth enable */ ++static bool hieth_disable; ++/* autoeee, enabled by dts */ ++static bool hieth_enable_autoeee; ++ ++static int __init hieth_noeth(char *str) ++{ ++ hieth_disable = true; ++ ++ return 0; ++} ++ ++early_param("noeth", hieth_noeth); ++ ++#include "pm.c" ++ ++static int hieth_hw_set_macaddress(struct hieth_netdev_priv *priv, ++ unsigned char *mac) ++{ ++ u32 reg; ++ ++ if (priv->port == HIETH_PORT_1) { ++ reg = hieth_readl(priv->glb_base, HIETH_GLB_DN_HOSTMAC_ENA); ++ reg |= HIETH_GLB_DN_HOSTMAC_ENA_BIT; ++ hieth_writel(priv->glb_base, reg, HIETH_GLB_DN_HOSTMAC_ENA); ++ } ++ ++ reg = mac[1] | (mac[0] << 8); ++ if (priv->port == HIETH_PORT_0) ++ hieth_writel(priv->glb_base, reg, HIETH_GLB_HOSTMAC_H16); ++ else ++ hieth_writel(priv->glb_base, reg, HIETH_GLB_DN_HOSTMAC_H16); ++ ++ reg = mac[5] | (mac[4] << 8) | (mac[3] << 16) | (mac[2] << 24); ++ if (priv->port == HIETH_PORT_0) ++ hieth_writel(priv->glb_base, reg, HIETH_GLB_HOSTMAC_L32); ++ else ++ hieth_writel(priv->glb_base, reg, HIETH_GLB_DN_HOSTMAC_L32); ++ ++ return 0; ++} ++ ++static void hieth_irq_enable(struct hieth_netdev_priv *priv, int irqs) ++{ ++ u32 val; ++ ++ local_lock(priv); ++ val = hieth_readl(priv->glb_base, HIETH_GLB_IRQ_ENA); ++ hieth_writel(priv->glb_base, val | irqs, HIETH_GLB_IRQ_ENA); ++ local_unlock(priv); ++} ++ ++static void hieth_irq_disable(struct hieth_netdev_priv *priv, int irqs) ++{ ++ u32 val; ++ ++ local_lock(priv); ++ val = hieth_readl(priv->glb_base, HIETH_GLB_IRQ_ENA); ++ hieth_writel(priv->glb_base, val & (~irqs), HIETH_GLB_IRQ_ENA); ++ local_unlock(priv); ++} ++ ++static void hieth_clear_irqstatus(struct hieth_netdev_priv *priv, int irqs) ++{ ++ local_lock(priv); ++ hieth_writel(priv->glb_base, irqs, HIETH_GLB_IRQ_RAW); ++ local_unlock(priv); ++} ++ ++static void hieth_set_flow_ctrl(struct hieth_netdev_priv *priv) ++{ ++ unsigned int pause_en; ++ unsigned int tx_flow_ctrl; ++ ++ tx_flow_ctrl = hieth_readl(priv->port_base, HIETH_P_GLB_FC_LEVEL); ++ tx_flow_ctrl &= ~BITS_THR_MASK; ++ tx_flow_ctrl |= priv->tx_pause_deactive_thresh; ++ tx_flow_ctrl &= ~(BITS_THR_MASK << BITS_FC_ACTIVE_THR_OFFSET); ++ tx_flow_ctrl |= priv->tx_pause_active_thresh << ++ BITS_FC_ACTIVE_THR_OFFSET; ++ ++ pause_en = hieth_readl(priv->port_base, HIETH_P_MAC_SET); ++ ++ if (priv->tx_pause_en) { ++ tx_flow_ctrl |= BIT_FC_EN; ++ pause_en |= BIT_PAUSE_EN; ++ } else { ++ tx_flow_ctrl &= ~BIT_FC_EN; ++ pause_en &= ~BIT_PAUSE_EN; ++ } ++ ++ hieth_writel(priv->port_base, tx_flow_ctrl, HIETH_P_GLB_FC_LEVEL); ++ ++ hieth_writel(priv->port_base, pause_en, HIETH_P_MAC_SET); ++} ++ ++static int hieth_port_reset(struct hieth_netdev_priv *priv) ++{ ++ u32 rst_bit = 0; ++ u32 val; ++ ++ if (hieth_real_port_cnt == 1) { ++ rst_bit = HIETH_GLB_SOFT_RESET_ALL; ++ } else { ++ if (priv->port == HIETH_PORT_0) ++ rst_bit |= HIETH_GLB_SOFT_RESET_P0; ++ else if (priv->port == HIETH_PORT_1) ++ rst_bit |= HIETH_GLB_SOFT_RESET_P1; ++ else ++ BUG(); ++ } ++ ++ val = hieth_readl(priv->glb_base, HIETH_GLB_SOFT_RESET); ++ ++ val |= rst_bit; ++ hieth_writel(priv->glb_base, val, HIETH_GLB_SOFT_RESET); ++ usleep_range(1000, 10000); ++ val &= ~rst_bit; ++ hieth_writel(priv->glb_base, val, HIETH_GLB_SOFT_RESET); ++ usleep_range(1000, 10000); ++ val |= rst_bit; ++ hieth_writel(priv->glb_base, val, HIETH_GLB_SOFT_RESET); ++ usleep_range(1000, 10000); ++ val &= ~rst_bit; ++ hieth_writel(priv->glb_base, val, HIETH_GLB_SOFT_RESET); ++ ++ return 0; ++} ++ ++static void hieth_port_init(struct hieth_netdev_priv *priv) ++{ ++ u32 val; ++ int phy_intf = (priv->phy_mode == PHY_INTERFACE_MODE_MII ? ++ HIETH_P_MAC_PORTSEL_MII : HIETH_P_MAC_PORTSEL_RMII); ++ ++ /* set little endian */ ++ val = hieth_readl(priv->glb_base, HIETH_GLB_ENDIAN_MOD); ++ val |= HIETH_GLB_ENDIAN_MOD_IN; ++ val |= HIETH_GLB_ENDIAN_MOD_OUT; ++ hieth_writel(priv->glb_base, val, HIETH_GLB_ENDIAN_MOD); ++ ++ /* set stat ctrl to cpuset, and MII or RMII mode */ ++ hieth_writel(priv->port_base, phy_intf | HIETH_P_MAC_PORTSEL_STAT_CPU, ++ HIETH_P_MAC_PORTSEL); ++ ++ /*clear all interrupt status */ ++ hieth_clear_irqstatus(priv, UD_BIT_NAME(HIETH_GLB_IRQ_ENA_BIT)); ++ ++ /*disable interrupts */ ++ hieth_irq_disable(priv, UD_BIT_NAME(HIETH_GLB_IRQ_ENA_BIT) | ++ UD_BIT_NAME(HIETH_GLB_IRQ_ENA_IEN)); ++ ++#ifdef HIETH_TSO_SUPPORTED ++ /* enable TSO debug for error handle */ ++ val = hieth_readl(priv->port_base, HIETH_P_GLB_TSO_DBG_EN); ++ val |= BITS_TSO_DBG_EN; ++ hieth_writel(priv->port_base, val, HIETH_P_GLB_TSO_DBG_EN); ++#endif ++ ++ /* disable vlan, enable UpEther<->CPU */ ++ val = hieth_readl(priv->glb_base, HIETH_GLB_FWCTRL); ++ val &= ~HIETH_GLB_FWCTRL_VLAN_ENABLE; ++ val |= UD_BIT_NAME(HIETH_GLB_FWCTRL_FW2CPU_ENA); ++ val &= ~(UD_BIT_NAME(HIETH_GLB_FWCTRL_FWALL2CPU)); ++ hieth_writel(priv->glb_base, val, HIETH_GLB_FWCTRL); ++ val = hieth_readl(priv->glb_base, HIETH_GLB_MACTCTRL); ++ val |= UD_BIT_NAME(HIETH_GLB_MACTCTRL_BROAD2CPU); ++ val |= UD_BIT_NAME(HIETH_GLB_MACTCTRL_MACT_ENA); ++ hieth_writel(priv->glb_base, val, HIETH_GLB_MACTCTRL); ++ ++ /* set pre count limit */ ++ val = hieth_readl(priv->port_base, HIETH_P_MAC_TX_IPGCTRL); ++ val &= ~HIETH_P_MAC_TX_IPGCTRL_PRE_CNT_LMT_MSK; ++ val |= 0; ++ hieth_writel(priv->port_base, val, HIETH_P_MAC_TX_IPGCTRL); ++ ++ /* set max receive length */ ++ val = hieth_readl(priv->port_base, HIETH_P_MAC_SET); ++ val &= ~HIETH_P_MAC_SET_LEN_MAX_MSK; ++ val |= HIETH_P_MAC_SET_LEN_MAX(HIETH_MAX_RCV_LEN); ++ hieth_writel(priv->port_base, val, HIETH_P_MAC_SET); ++ ++ hieth_set_flow_ctrl(priv); ++} ++ ++static void hieth_set_hwq_depth(struct hieth_netdev_priv *priv) ++{ ++ u32 val; ++ ++ val = hieth_readl(priv->port_base, HIETH_P_GLB_QLEN_SET); ++ val &= ~HIETH_P_GLB_QLEN_SET_TXQ_DEP_MSK; ++ val |= HIETH_P_GLB_QLEN_SET_TXQ_DEP(priv->depth.hw_xmitq); ++ val &= ~HIETH_P_GLB_QLEN_SET_RXQ_DEP_MSK; ++ val |= HIETH_P_GLB_QLEN_SET_RXQ_DEP(HIETH_MAX_QUEUE_DEPTH - ++ priv->depth.hw_xmitq); ++ hieth_writel(priv->port_base, val, HIETH_P_GLB_QLEN_SET); ++} ++ ++static int hieth_hw_xmitq_ready(struct hieth_netdev_priv *priv) ++{ ++ int ret; ++ ++ local_lock(priv); ++ ret = hieth_readl(priv->port_base, HIETH_P_GLB_RO_QUEUE_STAT); ++ ret &= HIETH_P_GLB_RO_QUEUE_STAT_XMITQ_RDY_MSK; ++ local_unlock(priv); ++ ++ return ret; ++} ++ ++#ifdef HIETH_TSO_SUPPORTED ++#ifdef HIETH_TSO_DEBUG ++unsigned int id_send; ++unsigned int id_free; ++struct send_pkt_info pkt_rec[MAX_RECORD]; ++#endif ++#endif ++ ++#ifdef HIETH_TSO_SUPPORTED ++static struct sk_buff *hieth_xmit_release_gso(struct hieth_netdev_priv *priv) ++{ ++ struct sk_buff *skb; ++ struct tx_pkt_info *txq_cur; ++ int pkt_type; ++ ++ txq_cur = priv->txq + priv->txq_tail; ++ ++ skb = txq_cur->skb; ++ ++ if (txq_cur->tx.info.sg_flag) ++ pkt_type = PKT_SG; ++ else ++ pkt_type = PKT_NORMAL; ++ ++ if (pkt_type == PKT_NORMAL) { ++ dma_addr_t dma_addr; ++ ++ dma_addr = txq_cur->tx_addr; ++ dma_unmap_single(priv->dev, dma_addr, skb->len, DMA_TO_DEVICE); ++ } else { /* TSO pkt */ ++ struct dma_tx_desc *desc_cur; ++ unsigned int desc_offset; ++ int nfrags = skb_shinfo(skb)->nr_frags; ++ int i; ++ ++ desc_offset = txq_cur->sg_desc_offset; ++ BUG_ON(desc_offset != priv->sg_tail); ++ desc_cur = priv->dma_tx + desc_offset; ++ ++ dma_unmap_single(priv->dev, desc_cur->linear_addr, ++ desc_cur->linear_len, DMA_TO_DEVICE); ++ for (i = 0; i < nfrags; i++) { ++ dma_unmap_page(priv->dev, desc_cur->frags[i].addr, ++ desc_cur->frags[i].size, DMA_TO_DEVICE); ++ } ++ ++ priv->sg_tail = (priv->sg_tail + 1) % priv->q_size; ++ } ++ ++ txq_cur->skb = NULL; ++ priv->txq_tail = (priv->txq_tail + 1) % priv->q_size; ++ ++#ifdef HIETH_TSO_DEBUG ++ pkt_rec[id_free].status = 0; ++ id_free++; ++ if (id_free == MAX_RECORD) ++ id_free = 0; ++#endif ++ ++ return skb; ++} ++#endif ++ ++static int hieth_xmit_release_skb(struct hieth_netdev_priv *priv) ++{ ++ u32 val; ++ int ret = 0; ++ struct sk_buff *skb; ++ ++ local_lock(priv); ++ ++ val = hieth_readl(priv->port_base, HIETH_P_GLB_RO_QUEUE_STAT) & ++ HIETH_P_GLB_RO_QUEUE_STAT_XMITQ_CNT_INUSE_MSK; ++ while (val < priv->tx_hw_cnt) { ++#ifdef HIETH_TSO_SUPPORTED ++ skb = hieth_xmit_release_gso(priv); ++#else ++ skb = skb_dequeue(&priv->tx_hw); ++#endif ++ ++ if (!skb) { ++ pr_err("hw_xmitq_cnt_inuse=%d, tx_hw_cnt=%d\n", ++ val, priv->tx_hw_cnt); ++ ++ BUG(); ++ ret = -1; ++ goto error_exit; ++ } ++ dev_kfree_skb_any(skb); ++ ++ priv->tx_hw_cnt--; ++ ++ val = hieth_readl(priv->port_base, HIETH_P_GLB_RO_QUEUE_STAT) & ++ HIETH_P_GLB_RO_QUEUE_STAT_XMITQ_CNT_INUSE_MSK; ++ } ++ ++error_exit: ++ local_unlock(priv); ++ return ret; ++} ++ ++#ifdef HIETH_TSO_SUPPORTED ++void hieth_get_tso_err_info(struct hieth_netdev_priv *priv) ++{ ++ unsigned int reg_addr, reg_tx_info, reg_tx_err; ++ unsigned int sg_index; ++ struct dma_tx_desc *sg_desc; ++ int *sg_word; ++ int i; ++ ++ reg_addr = hieth_readl(priv->port_base, HIETH_P_GLB_TSO_DBG_ADDR); ++ reg_tx_info = hieth_readl(priv->port_base, HIETH_P_GLB_TSO_DBG_TX_INFO); ++ reg_tx_err = hieth_readl(priv->port_base, HIETH_P_GLB_TSO_DBG_TX_ERR); ++ ++ WARN(1, "tx err=0x%x, tx_info=0x%x, addr=0x%x\n", ++ reg_tx_err, reg_tx_info, reg_addr); ++ ++ sg_index = (reg_addr - priv->dma_tx_phy) / sizeof(struct dma_tx_desc); ++ sg_desc = priv->dma_tx + sg_index; ++ sg_word = (int *)sg_desc; ++ for (i = 0; i < sizeof(struct dma_tx_desc) / sizeof(int); i++) ++ pr_err("%s,%d: sg_desc word[%d]=0x%x\n", ++ __func__, __LINE__, i, sg_word[i]); ++ ++ /* restart MAC to transmit next packet */ ++ hieth_irq_disable(priv, UD_BIT_NAME(HIETH_INT_TX_ERR)); ++#if 0 ++ hieth_readl(priv, HIETH_P_GLB_TSO_DBG_STATE)); ++ hieth_irq_enable(priv, UD_BIT_NAME(HIETH_INT_TX_ERR)); ++#endif ++} ++ ++static int hieth_xmit_real_send(struct hieth_netdev_priv *priv, ++ struct sk_buff *skb); ++ ++static int hieth_sw_gso(struct hieth_netdev_priv *priv, struct sk_buff *skb) ++{ ++ struct sk_buff *segs, *curr_skb; ++ struct net_device *ndev = hieth_devs_save[priv->port]; ++ int ret; ++ ++ segs = skb_gso_segment(skb, ndev->features & ++ ~(NETIF_F_ALL_CSUM | NETIF_F_GSO_SOFTWARE)); ++ if (IS_ERR(segs)) ++ goto sw_tso_end; ++ ++ do { ++ curr_skb = segs; ++ segs = segs->next; ++ curr_skb->next = NULL; ++ ret = hieth_xmit_real_send(priv, curr_skb); ++ if (ret < 0) { ++ dev_kfree_skb(curr_skb); ++ while (segs != NULL) { ++ curr_skb = segs; ++ segs = segs->next; ++ curr_skb->next = NULL; ++ dev_kfree_skb(curr_skb); ++ } ++ goto sw_tso_end; ++ } ++ } while (segs); ++ ++sw_tso_end: ++ dev_kfree_skb(skb); ++ ++ return 0; ++} ++ ++int hieth_get_pkt_info(struct sk_buff *skb, struct tx_pkt_info *txq_cur) ++{ ++ int nfrags = skb_shinfo(skb)->nr_frags; ++ ++ __be16 l3_proto; /* level 3 protocol */ ++ unsigned int l4_proto = IPPROTO_MAX; ++ unsigned char coe_enable = 0; ++ ++ if (skb->ip_summed == CHECKSUM_PARTIAL) ++ coe_enable = 1; ++ ++ txq_cur->tx.val = 0; ++ ++ if (skb_is_gso(skb)) { ++ txq_cur->tx.info.tso_flag = 1; ++ txq_cur->tx.info.sg_flag = 1; ++ } else if (nfrags) { ++ txq_cur->tx.info.sg_flag = 1; ++ } ++ ++ /* deal with VLAN flag */ ++ l3_proto = skb->protocol; ++ if (skb->protocol == htons(ETH_P_8021Q)) { ++ struct vlan_hdr *vhdr; ++ ++ vhdr = (struct vlan_hdr *)(skb->data + ETH_HLEN); ++ l3_proto = vhdr->h_vlan_encapsulated_proto; ++ txq_cur->tx.info.vlan_flag = 1; ++ } ++ ++ if (l3_proto == htons(ETH_P_IP)) { ++ const struct iphdr *iph; ++ ++ iph = ip_hdr(skb); ++ txq_cur->tx.info.ip_ver = PKT_IPV4; ++ txq_cur->tx.info.ip_hdr_len = iph->ihl; ++ ++ l4_proto = iph->protocol; ++ l4_proto = l4_proto & (MAX_INET_PROTOS - 1); ++ } else if (l3_proto == htons(ETH_P_IPV6)) { ++ const struct ipv6hdr *hdr; ++ ++ txq_cur->tx.info.ip_ver = PKT_IPV6; ++ txq_cur->tx.info.ip_hdr_len = PKT_IPV6_HDR_LEN; ++ hdr = ipv6_hdr(skb); ++ l4_proto = hdr->nexthdr; ++ } else { ++ coe_enable = 0; ++ /* pr_err("unknown level 3 prot=0x%x\n", ntohs(l3_proto)); */ ++ } ++ ++ if (l4_proto == IPPROTO_TCP) { ++ const struct tcphdr *th; ++ ++ th = tcp_hdr(skb); ++ txq_cur->tx.info.prot_type = PKT_TCP; ++ txq_cur->tx.info.prot_hdr_len = th->doff; ++ } else if (l4_proto == IPPROTO_UDP) { ++ txq_cur->tx.info.prot_type = PKT_UDP; ++ txq_cur->tx.info.prot_hdr_len = PKT_UDP_HDR_LEN; ++ } else { ++ coe_enable = 0; ++ /* pr_err("unknown level 4 prot=0x%x\n", l4_proto); */ ++ /* TODO: when l3_proto == ETH_P_IPV6, ++ * we need to deal with IPV6 next header. ++ */ ++ if (l3_proto == htons(ETH_P_IPV6) && ++ skb->ip_summed == CHECKSUM_PARTIAL) ++ return -E_MAC_SW_GSO; ++ } ++ ++ if (skb_is_gso(skb)) ++ txq_cur->tx.info.data_len ++ = skb_shinfo(skb)->gso_size; ++ else ++ txq_cur->tx.info.data_len = skb->len + FCS_BYTES; ++ ++ if (coe_enable) { ++ if (skb_is_gso(skb) && (l4_proto == IPPROTO_UDP)) { ++ /* TODO: self checksum caculate */ ++ int offset; ++ __wsum csum; ++ __sum16 udp_csum; ++ ++ offset = skb_checksum_start_offset(skb); ++ WARN_ON(offset >= skb_headlen(skb)); ++ csum = skb_checksum(skb, offset, skb->len - offset, 0); ++ ++ offset += skb->csum_offset; ++ BUG_ON(offset + sizeof(__sum16) > skb_headlen(skb)); ++ udp_csum = csum_fold(csum); ++ if (udp_csum == 0) ++ udp_csum = CSUM_MANGLED_0; ++ ++ *(__sum16 *)(skb->data + offset) = udp_csum; ++ ++ skb->ip_summed = CHECKSUM_NONE; ++ coe_enable = 0; ++ } ++ } ++ ++ txq_cur->tx.info.coe_flag = coe_enable; ++ txq_cur->tx.info.nfrags_num = nfrags; ++ ++ return 0; ++} ++ ++int hieth_xmit_gso(struct hieth_netdev_priv *priv, struct sk_buff *skb) ++{ ++ int pkt_type = PKT_NORMAL; ++ int nfrags = skb_shinfo(skb)->nr_frags; ++ struct tx_pkt_info *txq_cur; ++ int ret; ++ ++ if (((priv->txq_head + 1) % priv->q_size) == priv->txq_tail) { ++ /* txq full, stop */ ++ pr_err("WARNING: txq full."); ++ return -E_MAC_TX_FAIL; ++ } ++ ++ if (skb_is_gso(skb) || nfrags) { ++ /* TSO pkt or SG pkt */ ++ pkt_type = PKT_SG; ++ } else { /* Normal pkt */ ++ pkt_type = PKT_NORMAL; ++ } ++ ++ txq_cur = priv->txq + priv->txq_head; ++ ++ ret = hieth_get_pkt_info(skb, txq_cur); ++ if (unlikely(ret < 0)) ++ return ret; ++ ++ if (pkt_type == PKT_NORMAL) { ++ txq_cur->tx_addr = dma_map_single(priv->dev, skb->data, ++ skb->len, DMA_TO_DEVICE); ++ } else { /* TSO pkt */ ++ struct dma_tx_desc *desc_cur; ++ int i; ++ ++ if (unlikely(((priv->sg_head + 1) % priv->q_size) == ++ priv->sg_tail)) { ++ /* SG pkt, but sg desc all used */ ++ pr_err("WARNING: sg desc all used."); ++ return -E_MAC_TX_FAIL; ++ } ++ ++ desc_cur = priv->dma_tx + priv->sg_head; ++ ++ /* TODO: deal with ipv6_id */ ++ if (txq_cur->tx.info.tso_flag && ++ txq_cur->tx.info.ip_ver == PKT_IPV6 && ++ txq_cur->tx.info.prot_type == PKT_UDP) { ++ desc_cur->ipv6_id = ntohl(skb_shinfo(skb)->ip6_frag_id); ++ } ++ ++ desc_cur->total_len = skb->len; ++ desc_cur->linear_len = skb_headlen(skb); ++ desc_cur->linear_addr = dma_map_single(priv->dev, skb->data, ++ desc_cur->linear_len, DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(priv->dev, ++ desc_cur->linear_addr))) { ++ pr_err("DMA Mapping fail."); ++ return -E_MAC_TX_FAIL; ++ } ++ ++ for (i = 0; i < nfrags; i++) { ++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ++ int len = frag->size; ++ ++ WARN(len <= 0, "%s,%d: frag %d size %d. desc=%x\n", ++ __func__, __LINE__, i, len, txq_cur->tx.val); ++ ++ desc_cur->frags[i].addr = ++ skb_frag_dma_map(priv->dev, frag, 0, ++ len, DMA_TO_DEVICE); ++ ret = dma_mapping_error(priv->dev, ++ desc_cur->frags[i].addr); ++ if (unlikely(ret)) { ++ pr_err("skb frag DMA Mapping fail."); ++ return -E_MAC_TX_FAIL; ++ } ++ desc_cur->frags[i].size = len; ++ } ++ ++ txq_cur->tx_addr = priv->dma_tx_phy + ++ priv->sg_head * sizeof(struct dma_tx_desc); ++ txq_cur->sg_desc_offset = priv->sg_head; ++ ++ priv->sg_head = (priv->sg_head + 1) % priv->q_size; ++ ++ /* Ensure desc info writen to memory before config hardware */ ++ wmb(); ++ } ++ ++ txq_cur->skb = skb; ++ priv->txq_head = (priv->txq_head + 1) % priv->q_size; ++ ++#ifdef HIETH_TSO_DEBUG ++ pkt_rec[id_send].reg_addr = txq_cur->tx_addr; ++ pkt_rec[id_send].reg_pkt_info = txq_cur->tx.val; ++ pkt_rec[id_send].status = 1; ++ id_send++; ++ if (id_send == MAX_RECORD) ++ id_send = 0; ++#endif ++ hieth_writel(priv->port_base, txq_cur->tx_addr, HIETH_P_GLB_EQ_ADDR); ++ hieth_writel(priv->port_base, txq_cur->tx.val, HIETH_P_GLB_EQFRM_LEN); ++ ++ return 0; ++} ++#endif ++ ++static int hieth_xmit_real_send(struct hieth_netdev_priv *priv, ++ struct sk_buff *skb) ++{ ++ int ret = 0; ++ u32 val; ++ ++ local_lock(priv); ++ ++ val = hieth_readl(priv->port_base, HIETH_P_GLB_RO_QUEUE_STAT); ++ val &= HIETH_P_GLB_RO_QUEUE_STAT_XMITQ_RDY_MSK; ++ if (!val) { ++ pr_err("hw xmit queue is not ready\n"); ++ ret = -1; ++ goto _trans_exit; ++ } ++ ++#ifdef HIETH_TSO_SUPPORTED ++ /* TSO supported */ ++ ret = hieth_xmit_gso(priv, skb); ++ if (unlikely(ret < 0)) { ++ if (ret == -E_MAC_SW_GSO) { ++ local_unlock(priv); ++ return hieth_sw_gso(priv, skb); ++ } ++ ret = -1; ++ goto _trans_exit; ++ } ++#else ++ dma_map_single(priv->dev, skb->data, skb->len, DMA_TO_DEVICE); ++ /* for recalc CRC, 4 bytes more is needed */ ++ hieth_writel(priv->port_base, virt_to_phys(skb->data), ++ HIETH_P_GLB_EQ_ADDR); ++ hieth_writel(priv->port_base, skb->len + FCS_BYTES, ++ HIETH_P_GLB_EQFRM_LEN); ++ ++ skb_queue_tail(&priv->tx_hw, skb); ++#endif ++ ++ priv->tx_hw_cnt++; ++ ++_trans_exit: ++ local_unlock(priv); ++ ++ return ret; ++} ++ ++static struct sk_buff *hieth_platdev_alloc_skb(struct hieth_netdev_priv *priv) ++{ ++ struct sk_buff *skb; ++ ++ skb = priv->rx_pool.sk_pool[priv->rx_pool.next_free_skb++]; ++ ++ if (priv->rx_pool.next_free_skb == CONFIG_HIETH_MAX_RX_POOLS) ++ priv->rx_pool.next_free_skb = 0; ++ ++ /*current skb is used by kernel or other process,find another skb*/ ++ if (skb_shared(skb) || (atomic_read(&(skb_shinfo(skb)->dataref)) > 1)) { ++ int i; ++ ++ for (i = 0; i < CONFIG_HIETH_MAX_RX_POOLS; i++) { ++ skb = priv->rx_pool.sk_pool[priv-> ++ rx_pool.next_free_skb++]; ++ if (priv->rx_pool.next_free_skb == ++ CONFIG_HIETH_MAX_RX_POOLS) ++ priv->rx_pool.next_free_skb = 0; ++ ++ if ((skb_shared(skb) == 0) && ++ (atomic_read(&(skb_shinfo(skb)->dataref)) <= 1)) ++ break; ++ } ++ ++ if (i == CONFIG_HIETH_MAX_RX_POOLS) { ++ priv->stat.rx_pool_dry_times++; ++ pr_debug("%ld: no free skb\n", ++ priv->stat.rx_pool_dry_times); ++ skb = dev_alloc_skb(SKB_SIZE); ++ return skb; ++ } ++ } ++ memset(skb, 0, offsetof(struct sk_buff, tail)); ++ ++ skb->data = skb->head; ++ skb->tail = skb->head; ++ ++ skb_reserve(skb, NET_SKB_PAD); ++ skb->len = 0; ++ skb->data_len = 0; ++ skb->cloned = 0; ++ atomic_inc(&skb->users); ++ return skb; ++} ++ ++static int hieth_feed_hw(struct hieth_netdev_priv *priv) ++{ ++ struct sk_buff *skb; ++ int cnt = 0; ++ int rx_head_len; ++ ++ /* if skb occupied too much, then do not alloc any more. */ ++ rx_head_len = skb_queue_len(&priv->rx_head); ++ if (rx_head_len > HIETH_MAX_RX_HEAD_LEN) ++ return 0; ++ ++ local_lock(priv); ++ ++ while (hieth_readl(priv->port_base, HIETH_P_GLB_RO_QUEUE_STAT) & ++ HIETH_P_GLB_RO_QUEUE_STAT_RECVQ_RDY_MSK) { ++ skb = hieth_platdev_alloc_skb(priv); ++ if (!skb) ++ break; ++ ++ dma_map_single(priv->dev, skb->data, HIETH_MAX_FRAME_SIZE, ++ DMA_FROM_DEVICE); ++ hieth_writel(priv->port_base, virt_to_phys(skb->data + 2), ++ HIETH_P_GLB_IQ_ADDR); ++ skb_queue_tail(&priv->rx_hw, skb); ++ cnt++; ++ } ++ ++ local_unlock(priv); ++ return cnt; ++} ++ ++static int hieth_hw_recv_tryup(struct hieth_netdev_priv *priv) ++{ ++ struct sk_buff *skb; ++ u32 rlen; ++ int cnt = 0; ++ uint32_t rx_pkt_info; ++#ifdef HIETH_RXCSUM_SUPPORTED ++ struct net_device *ndev = hieth_devs_save[priv->port]; ++ int hdr_csum_done, hdr_csum_err; ++ int payload_csum_done, payload_csum_err; ++#endif ++ ++ local_lock(priv); ++ ++ while ((hieth_readl(priv->glb_base, HIETH_GLB_IRQ_RAW) & ++ (UD_BIT_NAME(HIETH_GLB_IRQ_INT_RX_RDY)))) { ++ rx_pkt_info = hieth_readl(priv->port_base, ++ HIETH_P_GLB_RO_IQFRM_DES); ++ rlen = rx_pkt_info & HIETH_P_GLB_RO_IQFRM_DES_FDIN_LEN_MSK; ++ rlen -= 4; /* remove FCS 4Bytes */ ++ ++ /* hw set rx pkg finish */ ++ hieth_writel(priv->glb_base, ++ UD_BIT_NAME(HIETH_GLB_IRQ_INT_RX_RDY), ++ HIETH_GLB_IRQ_RAW); ++ ++ skb = skb_dequeue(&priv->rx_hw); ++ if (!skb) { ++ pr_err("chip told receive pkg, but no packet find!\n"); ++ BUG(); ++ break; ++ } ++ ++ dma_map_single(priv->dev, skb->data, HIETH_MAX_FRAME_SIZE, ++ DMA_FROM_DEVICE); ++ skb_reserve(skb, 2); ++ skb_put(skb, rlen); ++#ifdef HIETH_RXCSUM_SUPPORTED ++ skb->ip_summed = CHECKSUM_NONE; ++ if (ndev->features & NETIF_F_RXCSUM) { ++ hdr_csum_done = ++ (rx_pkt_info >> BITS_HEADER_DONE_OFFSET) & ++ BITS_HEADER_DONE_MASK; ++ payload_csum_done = ++ (rx_pkt_info >> BITS_PAYLOAD_DONE_OFFSET) & ++ BITS_PAYLOAD_DONE_MASK; ++ hdr_csum_err = ++ (rx_pkt_info >> BITS_HEADER_ERR_OFFSET) & ++ BITS_HEADER_ERR_MASK; ++ payload_csum_err = ++ (rx_pkt_info >> BITS_PAYLOAD_ERR_OFFSET) & ++ BITS_PAYLOAD_ERR_MASK; ++ ++ if (hdr_csum_done && payload_csum_done) { ++ if (unlikely(hdr_csum_err || ++ payload_csum_err)) { ++ priv->stats.rx_errors++; ++ priv->stats.rx_crc_errors++; ++ dev_kfree_skb_any(skb); ++ continue; ++ } else { ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ } ++ } ++ } ++#endif ++ skb_queue_tail(&priv->rx_head, skb); ++ cnt++; ++ } ++ ++ local_unlock(priv); ++ ++ /* fill hardware receive queue again */ ++ hieth_feed_hw(priv); ++ return cnt; ++} ++ ++static void hieth_adjust_link(struct net_device *dev) ++{ ++ int stat = 0; ++ struct hieth_netdev_priv *priv = netdev_priv(dev); ++ ++ stat |= (priv->phy->link) ? HIETH_P_MAC_PORTSET_LINKED : 0; ++ stat |= (priv->phy->duplex == DUPLEX_FULL) ? ++ HIETH_P_MAC_PORTSET_DUP_FULL : 0; ++ stat |= (priv->phy->speed == SPEED_100) ? ++ HIETH_P_MAC_PORTSET_SPD_100M : 0; ++ ++ if ((stat != priv->link_stat) && ++ ((stat | priv->link_stat) & HIETH_P_MAC_PORTSET_LINKED)) { ++ hieth_writel(priv->port_base, stat, HIETH_P_MAC_PORTSET); ++ phy_print_status(priv->phy); ++ priv->link_stat = stat; ++ ++ priv->tx_pause_en = priv->phy->pause; ++ hieth_set_flow_ctrl(priv); ++ ++ if (hieth_enable_autoeee) ++ hieth_autoeee_init(priv, stat); ++ } ++} ++ ++static int hieth_init_skb_buffers(struct hieth_netdev_priv *priv) ++{ ++ int i; ++ struct sk_buff *skb; ++ ++ for (i = 0; i < CONFIG_HIETH_MAX_RX_POOLS; i++) { ++ skb = dev_alloc_skb(SKB_SIZE); ++ if (!skb) ++ break; ++ priv->rx_pool.sk_pool[i] = skb; ++ } ++ ++ if (i < CONFIG_HIETH_MAX_RX_POOLS) { ++ pr_err("no mem\n"); ++ for (i--; i > 0; i--) ++ dev_kfree_skb_any(priv->rx_pool.sk_pool[i]); ++ return -ENOMEM; ++ } ++ ++ priv->rx_pool.next_free_skb = 0; ++ priv->stat.rx_pool_dry_times = 0; ++ return 0; ++} ++ ++static void hieth_destroy_skb_buffers(struct hieth_netdev_priv *priv) ++{ ++ int i; ++ ++ for (i = 0; i < CONFIG_HIETH_MAX_RX_POOLS; i++) ++ dev_kfree_skb_any(priv->rx_pool.sk_pool[i]); ++ ++ priv->rx_pool.next_free_skb = 0; ++ priv->stat.rx_pool_dry_times = 0; ++} ++ ++static void hieth_bfproc_recv(unsigned long data) ++{ ++ int ret = 0; ++ struct net_device *dev = (void *)data; ++ struct hieth_netdev_priv *priv = netdev_priv(dev); ++ struct sk_buff *skb; ++ ++ hieth_hw_recv_tryup(priv); ++ ++ while ((skb = skb_dequeue(&priv->rx_head)) != NULL) { ++ skb->protocol = eth_type_trans(skb, dev); ++ if (HIETH_INVALID_RXPKG_LEN(skb->len)) { ++ pr_err("pkg len error\n"); ++ priv->stats.rx_errors++; ++ priv->stats.rx_length_errors++; ++ dev_kfree_skb_any(skb); ++ continue; ++ } ++ ++ priv->stats.rx_packets++; ++ priv->stats.rx_bytes += skb->len; ++ dev->last_rx = jiffies; ++ skb->dev = dev; ++ ++ ret = netif_rx(skb); ++ if (ret) ++ priv->stats.rx_dropped++; ++ } ++} ++ ++static void hieth_net_isr_proc(struct net_device *ndev, int ints) ++{ ++ struct hieth_netdev_priv *priv = netdev_priv(ndev); ++ ++ if ((ints & UD_BIT_NAME(HIETH_GLB_IRQ_INT_MULTI_RXRDY)) && ++ (hieth_hw_recv_tryup(priv) > 0)) { ++ tasklet_schedule(&priv->bf_recv); ++ } ++ ++ if (ints & UD_BIT_NAME(HIETH_GLB_IRQ_INT_TXQUE_RDY)) { ++ hieth_irq_disable(priv, ++ UD_BIT_NAME(HIETH_GLB_IRQ_INT_TXQUE_RDY)); ++ netif_wake_queue(ndev); ++ } ++} ++ ++static irqreturn_t hieth_net_isr(int irq, void *dev_id) ++{ ++ int ints; ++ struct net_device *dev = (struct net_device *)dev_id; ++ struct hieth_netdev_priv *priv = netdev_priv(dev); ++ ++ /*mask the all interrupt */ ++ hieth_irq_disable(priv, HIETH_GLB_IRQ_ENA_IEN_A); ++ ++ ints = hieth_readl(priv->glb_base, HIETH_GLB_IRQ_STAT); ++ ++ if ((HIETH_PORT_0 == priv->port) && ++ likely(ints & HIETH_GLB_IRQ_ENA_BIT_U)) { ++ hieth_net_isr_proc(dev, (ints & HIETH_GLB_IRQ_ENA_BIT_U)); ++ hieth_clear_irqstatus(priv, (ints & HIETH_GLB_IRQ_ENA_BIT_U)); ++ ints &= ~HIETH_GLB_IRQ_ENA_BIT_U; ++ } ++ ++ if ((HIETH_PORT_1 == priv->port) && ++ likely(ints & HIETH_GLB_IRQ_ENA_BIT_D)) { ++ hieth_net_isr_proc(dev, (ints & HIETH_GLB_IRQ_ENA_BIT_D)); ++ hieth_clear_irqstatus(priv, (ints & HIETH_GLB_IRQ_ENA_BIT_D)); ++ ints &= ~HIETH_GLB_IRQ_ENA_BIT_D; ++ } ++#ifdef HIETH_TSO_SUPPORTED ++ if (unlikely(ints & HIETH_INT_TX_ERR_U)) { ++ priv = netdev_priv(hieth_devs_save[HIETH_PORT_0]); ++ ++ hieth_get_tso_err_info(priv); ++ ints &= ~HIETH_INT_TX_ERR_U; ++ } ++ ++ if (unlikely(ints & HIETH_INT_TX_ERR_D)) { ++ priv = netdev_priv(hieth_devs_save[HIETH_PORT_1]); ++ ++ hieth_get_tso_err_info(priv); ++ ints &= ~HIETH_INT_TX_ERR_D; ++ } ++#endif ++ ++ /*unmask the all interrupt */ ++ hieth_irq_enable(priv, HIETH_GLB_IRQ_ENA_IEN_A); ++ ++ return IRQ_HANDLED; ++} ++ ++static void hieth_monitor_func(unsigned long arg) ++{ ++ struct net_device *dev = (struct net_device *)arg; ++ struct hieth_netdev_priv *priv = netdev_priv(dev); ++ ++ if (!priv || !netif_running(dev)) { ++ pr_debug("network driver is stopped.\n"); ++ return; ++ } ++ ++ hieth_feed_hw(priv); ++ hieth_xmit_release_skb(priv); ++ ++ priv->monitor.expires = ++ jiffies + msecs_to_jiffies(HIETH_MONITOR_TIMER); ++ add_timer(&priv->monitor); ++} ++ ++static int hieth_net_open(struct net_device *dev) ++{ ++ int ret = 0; ++ struct cpumask cpumask; ++ struct hieth_netdev_priv *priv = netdev_priv(dev); ++ ++ ret = request_irq(dev->irq, hieth_net_isr, IRQF_SHARED, ++ dev->name, dev); ++ if (ret) { ++ pr_err("request_irq %d failed!\n", dev->irq); ++ return ret; ++ } ++ ++ /* set irq affinity */ ++ if ((num_online_cpus() > 1) && cpu_online(HIETH_IRQ_AFFINITY_CPU)) { ++ cpumask_clear(&cpumask); ++ cpumask_set_cpu(HIETH_IRQ_AFFINITY_CPU, &cpumask); ++ irq_set_affinity(dev->irq, &cpumask); ++ } ++ ++ if (!is_valid_ether_addr(dev->dev_addr)) ++ random_ether_addr(dev->dev_addr); ++ ++ hieth_hw_set_macaddress(priv, dev->dev_addr); ++ ++ /* init tasklet */ ++ priv->bf_recv.next = NULL; ++ priv->bf_recv.state = 0; ++ priv->bf_recv.func = hieth_bfproc_recv; ++ priv->bf_recv.data = (unsigned long)dev; ++ atomic_set(&priv->bf_recv.count, 0); ++ ++ /* setup hardware */ ++ hieth_set_hwq_depth(priv); ++ hieth_clear_irqstatus(priv, UD_BIT_NAME(HIETH_GLB_IRQ_ENA_BIT)); ++ ++ netif_carrier_off(dev); ++ hieth_feed_hw(priv); ++ netif_start_queue(dev); ++ ++ priv->link_stat = 0; ++ if (priv->phy) ++ phy_start(priv->phy); ++ ++ hieth_irq_enable(priv, UD_BIT_NAME(HIETH_GLB_IRQ_INT_MULTI_RXRDY) | ++ UD_BIT_NAME(HIETH_GLB_IRQ_ENA_IEN) | ++ HIETH_GLB_IRQ_ENA_IEN_A); ++#ifdef HIETH_TSO_SUPPORTED ++ hieth_irq_enable(priv, UD_BIT_NAME(HIETH_INT_TX_ERR)); ++#endif ++ ++ priv->monitor.expires = ++ jiffies + msecs_to_jiffies(HIETH_MONITOR_TIMER); ++ add_timer(&priv->monitor); ++ ++ return 0; ++} ++ ++static int hieth_net_close(struct net_device *dev) ++{ ++ struct hieth_netdev_priv *priv = netdev_priv(dev); ++#ifdef HIETH_TSO_SUPPORTED ++ struct sk_buff *skb = NULL; ++#endif ++ ++ hieth_irq_disable(priv, UD_BIT_NAME(HIETH_GLB_IRQ_INT_MULTI_RXRDY)); ++#ifdef HIETH_TSO_SUPPORTED ++ hieth_irq_disable(priv, UD_BIT_NAME(HIETH_INT_TX_ERR)); ++#endif ++ ++ if (priv->phy) ++ phy_stop(priv->phy); ++ ++ del_timer_sync(&priv->monitor); ++ ++ /* delete tasklet */ ++ tasklet_kill(&priv->bf_recv); ++ ++ /* reset and init port */ ++ hieth_port_reset(priv); ++ ++ skb_queue_purge(&priv->rx_head); ++ skb_queue_purge(&priv->rx_hw); ++#ifdef HIETH_TSO_SUPPORTED ++ while (priv->txq_tail != priv->txq_head) { ++ skb = hieth_xmit_release_gso(priv); ++ BUG_ON(skb == NULL); ++ kfree_skb(skb); ++ } ++#else ++ skb_queue_purge(&priv->tx_hw); ++#endif ++ priv->tx_hw_cnt = 0; ++ ++ free_irq(dev->irq, dev); ++ return 0; ++} ++ ++static void hieth_net_timeout(struct net_device *dev) ++{ ++ pr_err("tx timeout\n"); ++} ++ ++static int hieth_net_hard_start_xmit(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ int ret; ++ struct hieth_netdev_priv *priv = netdev_priv(dev); ++ ++ hieth_xmit_release_skb(priv); ++ ++ ret = hieth_xmit_real_send(priv, skb); ++ if (ret < 0) { ++ priv->stats.tx_dropped++; ++ return NETDEV_TX_BUSY; ++ } ++ ++ dev->trans_start = jiffies; ++ priv->stats.tx_packets++; ++ priv->stats.tx_bytes += skb->len; ++ hieth_clear_irqstatus(priv, UD_BIT_NAME(HIETH_GLB_IRQ_INT_TXQUE_RDY)); ++ ++ if (!hieth_hw_xmitq_ready(priv)) { ++ netif_stop_queue(dev); ++ hieth_irq_enable(priv, ++ UD_BIT_NAME(HIETH_GLB_IRQ_INT_TXQUE_RDY)); ++ } ++ ++ return NETDEV_TX_OK; ++} ++ ++static struct net_device_stats *hieth_net_get_stats(struct net_device *dev) ++{ ++ struct hieth_netdev_priv *priv = netdev_priv(dev); ++ ++ return &priv->stats; ++} ++ ++static int hieth_net_set_mac_address(struct net_device *dev, void *p) ++{ ++ struct hieth_netdev_priv *priv = netdev_priv(dev); ++ struct sockaddr *skaddr = p; ++ ++ if (!is_valid_ether_addr(skaddr->sa_data)) ++ return -EADDRNOTAVAIL; ++ ++ memcpy(dev->dev_addr, skaddr->sa_data, dev->addr_len); ++ dev->addr_assign_type &= ~NET_ADDR_RANDOM; ++ ++ hieth_hw_set_macaddress(priv, dev->dev_addr); ++ ++ return 0; ++} ++ ++static inline void hieth_enable_mac_addr_filter(struct hieth_netdev_priv *priv, ++ unsigned int reg_n, int enable) ++{ ++ u32 val; ++ ++ val = hieth_readl(priv->glb_base, GLB_MAC_H16(priv->port, reg_n)); ++ if (enable) ++ val |= UD_BIT_NAME(HIETH_GLB_MACFLT_ENA); ++ else ++ val &= ~(UD_BIT_NAME(HIETH_GLB_MACFLT_ENA)); ++ hieth_writel(priv->glb_base, val, GLB_MAC_H16(priv->port, reg_n)); ++} ++ ++static void hieth_set_mac_addr(struct hieth_netdev_priv *priv, u8 addr[6], ++ unsigned int high, unsigned int low) ++{ ++ u32 val; ++ u32 data; ++ ++ val = hieth_readl(priv->glb_base, high); ++ val |= UD_BIT_NAME(HIETH_GLB_MACFLT_ENA); ++ hieth_writel(priv->glb_base, val, high); ++ ++ val &= ~HIETH_GLB_MACFLT_HI16; ++ val |= ((addr[0] << 8) | addr[1]); ++ hieth_writel(priv->glb_base, val, high); ++ ++ data = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | addr[5]; ++ hieth_writel(priv->glb_base, data, low); ++ ++ val |= UD_BIT_NAME(HIETH_GLB_MACFLT_FW2CPU); ++ hieth_writel(priv->glb_base, val, high); ++} ++ ++static inline void hieth_set_mac_addr_filter(struct hieth_netdev_priv *priv, ++ unsigned char *addr, ++ unsigned int reg_n) ++{ ++ hieth_set_mac_addr(priv, addr, GLB_MAC_H16(priv->port, reg_n), ++ GLB_MAC_L32(priv->port, reg_n)); ++} ++ ++static void hieth_net_set_rx_mode(struct net_device *dev) ++{ ++ u32 val; ++ struct hieth_netdev_priv *priv = netdev_priv(dev); ++ ++ local_lock(priv); ++ ++ val = hieth_readl(priv->glb_base, HIETH_GLB_FWCTRL); ++ if (dev->flags & IFF_PROMISC) { ++ val |= ((priv->port == HIETH_PORT_0) ? ++ HIETH_GLB_FWCTRL_FWALL2CPU_U : ++ HIETH_GLB_FWCTRL_FWALL2CPU_D); ++ hieth_writel(priv->glb_base, val, HIETH_GLB_FWCTRL); ++ } else { ++ val &= ~((priv->port == HIETH_PORT_0) ? ++ HIETH_GLB_FWCTRL_FWALL2CPU_U : ++ HIETH_GLB_FWCTRL_FWALL2CPU_D); ++ hieth_writel(priv->glb_base, val, HIETH_GLB_FWCTRL); ++ ++ val = hieth_readl(priv->glb_base, HIETH_GLB_MACTCTRL); ++ if ((netdev_mc_count(dev) > HIETH_MAX_MULTICAST_ADDRESSES) || ++ (dev->flags & IFF_ALLMULTI)) { ++ val |= UD_BIT_NAME(HIETH_GLB_MACTCTRL_MULTI2CPU); ++ } else { ++ int reg = HIETH_MAX_UNICAST_ADDRESSES; ++ int i; ++ struct netdev_hw_addr *ha; ++ ++ for (i = reg; i < HIETH_MAX_MAC_FILTER_NUM; i++) ++ hieth_enable_mac_addr_filter(priv, i, 0); ++ ++ netdev_for_each_mc_addr(ha, dev) { ++ hieth_set_mac_addr_filter(priv, ha->addr, reg); ++ reg++; ++ } ++ ++ val &= ~(UD_BIT_NAME(HIETH_GLB_MACTCTRL_MULTI2CPU)); ++ } ++ ++ /* Handle multiple unicast addresses (perfect filtering)*/ ++ if (netdev_uc_count(dev) > HIETH_MAX_UNICAST_ADDRESSES) { ++ val |= UD_BIT_NAME(HIETH_GLB_MACTCTRL_UNI2CPU); ++ } else { ++ int reg = 0; ++ int i; ++ struct netdev_hw_addr *ha; ++ ++ for (i = reg; i < HIETH_MAX_UNICAST_ADDRESSES; i++) ++ hieth_enable_mac_addr_filter(priv, i, 0); ++ ++ netdev_for_each_uc_addr(ha, dev) { ++ hieth_set_mac_addr_filter(priv, ha->addr, reg); ++ reg++; ++ } ++ ++ val &= ~(UD_BIT_NAME(HIETH_GLB_MACTCTRL_UNI2CPU)); ++ } ++ hieth_writel(priv->glb_base, val, HIETH_GLB_MACTCTRL); ++ } ++ ++ local_unlock(priv); ++} ++ ++static int hieth_net_ioctl(struct net_device *net_dev, ++ struct ifreq *ifreq, int cmd) ++{ ++ struct hieth_netdev_priv *priv = netdev_priv(net_dev); ++ struct hieth_pm_config pm_config; ++ ++ switch (cmd) { ++ case SIOCSETPM: ++ if (copy_from_user(&pm_config, ifreq->ifr_data, ++ sizeof(pm_config))) ++ return -EFAULT; ++ return hieth_pmt_config(&pm_config); ++ ++ default: ++ if (!netif_running(net_dev)) ++ return -EINVAL; ++ ++ if (!priv->phy) ++ return -EINVAL; ++ ++ return phy_mii_ioctl(priv->phy, ifreq, cmd); ++ } ++ ++ return 0; ++} ++ ++static void hieth_ethtools_get_drvinfo(struct net_device *net_dev, ++ struct ethtool_drvinfo *info) ++{ ++ strcpy(info->driver, "hieth driver"); ++ strcpy(info->version, "v300"); ++ strcpy(info->bus_info, "platform"); ++} ++ ++static u32 hieth_ethtools_get_link(struct net_device *net_dev) ++{ ++ struct hieth_netdev_priv *priv = netdev_priv(net_dev); ++ ++ return ((priv->phy->link) ? HIETH_P_MAC_PORTSET_LINKED : 0); ++} ++ ++static int hieth_ethtools_get_settings(struct net_device *net_dev, ++ struct ethtool_cmd *cmd) ++{ ++ struct hieth_netdev_priv *priv = netdev_priv(net_dev); ++ ++ if (priv->phy) ++ return phy_ethtool_gset(priv->phy, cmd); ++ ++ return -EINVAL; ++} ++ ++static int hieth_ethtools_set_settings(struct net_device *net_dev, ++ struct ethtool_cmd *cmd) ++{ ++ struct hieth_netdev_priv *priv = netdev_priv(net_dev); ++ ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ ++ if (priv->phy) ++ return phy_ethtool_sset(priv->phy, cmd); ++ ++ return -EINVAL; ++} ++ ++static void hieth_get_pauseparam(struct net_device *net_dev, ++ struct ethtool_pauseparam *pause) ++{ ++ struct hieth_netdev_priv *priv = netdev_priv(net_dev); ++ ++ pause->autoneg = priv->phy->autoneg; ++ pause->rx_pause = 1; ++ if (priv->tx_pause_en) ++ pause->tx_pause = 1; ++} ++ ++static int hieth_set_pauseparam(struct net_device *net_dev, ++ struct ethtool_pauseparam *pause) ++{ ++ struct hieth_netdev_priv *priv = netdev_priv(net_dev); ++ struct phy_device *phy = priv->phy; ++ int ret = 0; ++ ++ if (pause->rx_pause == 0) ++ return -EINVAL; ++ ++ if (pause->tx_pause != priv->tx_pause_en) { ++ priv->tx_pause_en = pause->tx_pause; ++ hieth_set_flow_ctrl(priv); ++ } ++ ++ if (phy->autoneg) { ++ if (netif_running(net_dev)) { ++ struct ethtool_cmd cmd; ++ /* auto-negotiation automatically restarted */ ++ cmd.cmd = ETHTOOL_NWAY_RST; ++ cmd.supported = phy->supported; ++ cmd.advertising = phy->advertising; ++ cmd.autoneg = phy->autoneg; ++ cmd.speed = phy->speed; ++ cmd.duplex = phy->duplex; ++ cmd.phy_address = phy->addr; ++ ret = phy_ethtool_sset(phy, &cmd); ++ } ++ } ++ ++ return ret; ++} ++ ++static inline void hieth_enable_rxcsum_drop(struct hieth_netdev_priv *priv, ++ bool drop) ++{ ++ unsigned int val; ++ ++ val = hieth_readl(priv->port_base, HIETH_P_GLB_RX_COE_CTRL); ++ if (drop) ++ val |= COE_ERR_DROP; ++ else ++ val &= ~COE_ERR_DROP; ++ hieth_writel(priv->port_base, val, HIETH_P_GLB_RX_COE_CTRL); ++} ++ ++static int hieth_set_features(struct net_device *dev, ++ netdev_features_t features) ++{ ++ struct hieth_netdev_priv *priv = netdev_priv(dev); ++ netdev_features_t changed = dev->features ^ features; ++ ++ if (changed & NETIF_F_RXCSUM) { ++ if (features & NETIF_F_RXCSUM) ++ hieth_enable_rxcsum_drop(priv, true); ++ else ++ hieth_enable_rxcsum_drop(priv, false); ++ } ++ ++ return 0; ++} ++ ++static struct ethtool_ops hieth_ethtools_ops = { ++ .get_drvinfo = hieth_ethtools_get_drvinfo, ++ .get_link = hieth_ethtools_get_link, ++ .get_settings = hieth_ethtools_get_settings, ++ .set_settings = hieth_ethtools_set_settings, ++ .get_pauseparam = hieth_get_pauseparam, ++ .set_pauseparam = hieth_set_pauseparam, ++}; ++ ++static const struct net_device_ops hieth_netdev_ops = { ++ .ndo_open = hieth_net_open, ++ .ndo_stop = hieth_net_close, ++ .ndo_start_xmit = hieth_net_hard_start_xmit, ++ .ndo_tx_timeout = hieth_net_timeout, ++ .ndo_do_ioctl = hieth_net_ioctl, ++ .ndo_set_mac_address = hieth_net_set_mac_address, ++ .ndo_set_rx_mode = hieth_net_set_rx_mode, ++ .ndo_change_mtu = eth_change_mtu, ++ .ndo_get_stats = hieth_net_get_stats, ++ .ndo_set_features = hieth_set_features, ++}; ++ ++static void hieth_verify_flow_ctrl_args(struct hieth_netdev_priv *priv) ++{ ++ if (priv->tx_pause_active_thresh < FC_ACTIVE_MIN || ++ priv->tx_pause_active_thresh > FC_ACTIVE_MAX) ++ priv->tx_pause_active_thresh = FC_ACTIVE_DEFAULT; ++ ++ if (priv->tx_pause_deactive_thresh < FC_DEACTIVE_MIN || ++ priv->tx_pause_deactive_thresh > FC_DEACTIVE_MAX) ++ priv->tx_pause_deactive_thresh = FC_DEACTIVE_DEFAULT; ++ ++ if (priv->tx_pause_active_thresh >= priv->tx_pause_deactive_thresh) { ++ priv->tx_pause_active_thresh = FC_ACTIVE_DEFAULT; ++ priv->tx_pause_deactive_thresh = FC_DEACTIVE_DEFAULT; ++ } ++} ++ ++static int hieth_platdev_probe_port(struct platform_device *pdev, ++ struct hieth_netdev_priv *com_priv, ++ int port) ++{ ++ int ret = -1; ++ struct net_device *netdev = NULL; ++ struct device *dev = &pdev->dev; ++ struct hieth_netdev_priv *priv; ++ ++ if ((HIETH_PORT_0 != port) && (HIETH_PORT_1 != port)) { ++ pr_err("port error!\n"); ++ ret = -ENODEV; ++ goto _error_exit; ++ } ++ ++ netdev = alloc_etherdev(sizeof(*priv)); ++ if (netdev == NULL) { ++ pr_err("alloc_etherdev fail!\n"); ++ ret = -ENOMEM; ++ goto _error_exit; ++ } ++ ++ platform_set_drvdata(pdev, netdev); ++ SET_NETDEV_DEV(netdev, &pdev->dev); ++ ++ netdev->irq = com_priv->irq; ++ ++ netdev->watchdog_timeo = 3 * HZ; ++ netdev->netdev_ops = &hieth_netdev_ops; ++ netdev->ethtool_ops = &hieth_ethtools_ops; ++ ++#ifdef HIETH_TSO_SUPPORTED ++ netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | ++ NETIF_F_UFO | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; ++#endif ++#ifdef HIETH_RXCSUM_SUPPORTED ++ netdev->hw_features |= NETIF_F_RXCSUM; ++#endif ++ netdev->features |= netdev->hw_features; ++ netdev->vlan_features |= netdev->features; ++ ++ netdev->priv_flags |= IFF_UNICAST_FLT; ++ ++ if (hieth_phy_param[port].macaddr) ++ ether_addr_copy(netdev->dev_addr, ++ hieth_phy_param[port].macaddr); ++ ++ if (!is_valid_ether_addr(netdev->dev_addr)) ++ eth_hw_addr_random(netdev); ++ ++ /* init hieth_global somethings... */ ++ hieth_devs_save[port] = netdev; ++ ++ /* init hieth_local_driver */ ++ priv = netdev_priv(netdev); ++ memset(priv, 0, sizeof(*priv)); ++ memcpy(priv, com_priv, sizeof(*priv)); ++ ++ local_lock_init(priv); ++ ++ priv->port = port; ++ ++ if (port == HIETH_PORT_0) ++ priv->port_base = priv->glb_base; ++ else ++ priv->port_base = priv->glb_base + 0x2000; ++ ++ priv->dev = dev; ++ ++ init_timer(&priv->monitor); ++ priv->monitor.function = hieth_monitor_func; ++ priv->monitor.data = (unsigned long)netdev; ++ priv->monitor.expires = ++ jiffies + msecs_to_jiffies(HIETH_MONITOR_TIMER); ++ ++ /* wol need */ ++ device_set_wakeup_capable(priv->dev, 1); ++ /* TODO: when we can let phy powerdown? ++ * In forcing fwd mode, we don't want phy powerdown, ++ * so I set wakeup enable all the time ++ */ ++ device_set_wakeup_enable(priv->dev, 1); ++ ++#ifdef CONFIG_TX_FLOW_CTRL_SUPPORT ++ priv->tx_pause_en = 1; ++#endif ++ priv->tx_pause_active_thresh = CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD; ++ priv->tx_pause_deactive_thresh = CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD; ++ ++ hieth_verify_flow_ctrl_args(priv); ++ ++ /* reset and init port */ ++ hieth_port_init(priv); ++ ++#ifdef HIETH_RXCSUM_SUPPORTED ++ hieth_enable_rxcsum_drop(priv, true); ++#endif ++ priv->depth.hw_xmitq = HIETH_HWQ_XMIT_DEPTH; ++ ++ priv->phy = of_phy_connect(netdev, priv->phy_node, ++ hieth_adjust_link, 0, priv->phy_mode); ++ if (!(priv->phy) || IS_ERR(priv->phy)) { ++ pr_info("connect to port[%d] PHY failed!\n", port); ++ priv->phy = NULL; ++ goto _error_phy_connect; ++ } ++ ++ priv->phy->advertising |= ADVERTISED_Pause; ++ priv->phy->supported |= ADVERTISED_Pause; ++ ++ pr_info("attached port %d PHY %d to driver %s, phy_mode=%s\n", ++ port, priv->phy->addr, priv->phy->drv->name, ++ phy_modes(priv->phy_mode)); ++ ++ if (hieth_enable_autoeee) ++ hieth_autoeee_init(priv, 0); ++ ++ skb_queue_head_init(&priv->rx_head); ++ skb_queue_head_init(&priv->rx_hw); ++#ifdef HIETH_TSO_SUPPORTED ++ priv->q_size = 2 * (priv->depth.hw_xmitq); ++ ++ priv->dma_tx = (struct dma_tx_desc *)dma_alloc_coherent(priv->dev, ++ priv->q_size * sizeof(struct dma_tx_desc), ++ &priv->dma_tx_phy, ++ GFP_KERNEL); ++ if (priv->dma_tx == NULL) { ++ pr_err("dma_alloc_coherent fail!\n"); ++ goto _error_alloc_dma_tx; ++ } ++ priv->sg_head = 0; ++ priv->sg_tail = 0; ++ ++ priv->txq = kmalloc_array(priv->q_size, sizeof(struct tx_pkt_info), ++ GFP_KERNEL); ++ if (priv->txq == NULL) ++ goto _error_alloc_txq; ++ priv->txq_head = 0; ++ priv->txq_tail = 0; ++#else ++ skb_queue_head_init(&priv->tx_hw); ++#endif ++ priv->tx_hw_cnt = 0; ++ ++ ret = hieth_init_skb_buffers(priv); ++ if (ret) { ++ pr_err("hieth_init_skb_buffers failed!\n"); ++ goto _error_init_skb_buffers; ++ } ++ ++ ret = register_netdev(netdev); ++ if (ret) { ++ pr_err("register_netdev %s failed!\n", netdev->name); ++ goto _error_register_netdev; ++ } ++ ++ return ret; ++ ++_error_register_netdev: ++ hieth_destroy_skb_buffers(priv); ++ ++_error_init_skb_buffers: ++#ifdef HIETH_TSO_SUPPORTED ++ kfree(priv->txq); ++_error_alloc_txq: ++ dma_free_coherent(priv->dev, ++ priv->q_size * sizeof(struct dma_tx_desc), ++ priv->dma_tx, priv->dma_tx_phy); ++_error_alloc_dma_tx: ++#endif ++ phy_disconnect(priv->phy); ++ priv->phy = NULL; ++ ++_error_phy_connect: ++ local_lock_exit(); ++ hieth_devs_save[port] = NULL; ++ free_netdev(netdev); ++ ++_error_exit: ++ return ret; ++} ++ ++static int hieth_platdev_remove_port(struct platform_device *pdev, int port) ++{ ++ struct net_device *ndev; ++ struct hieth_netdev_priv *priv; ++ ++ ndev = hieth_devs_save[port]; ++ ++ if (!ndev) ++ goto _ndev_exit; ++ ++ priv = netdev_priv(ndev); ++ ++ unregister_netdev(ndev); ++#ifdef HIETH_TSO_SUPPORTED ++ kfree(priv->txq); ++ dma_free_coherent(priv->dev, ++ priv->q_size * sizeof(struct dma_tx_desc), ++ priv->dma_tx, priv->dma_tx_phy); ++#endif ++ hieth_destroy_skb_buffers(priv); ++ ++ phy_disconnect(priv->phy); ++ priv->phy = NULL; ++ ++ iounmap((void *)priv->glb_base); ++ ++ local_lock_exit(); ++ ++ hieth_devs_save[port] = NULL; ++ free_netdev(ndev); ++ ++_ndev_exit: ++ return 0; ++} ++ ++static int hieth_of_get_param(struct device_node *node) ++{ ++ struct device_node *child = NULL; ++ int idx = 0; ++ int data; ++ ++ /* get auto eee */ ++ hieth_enable_autoeee = of_property_read_bool(node, "autoeee"); ++ ++ for_each_available_child_of_node(node, child) { ++ /* get phy-addr */ ++ if (of_property_read_u32(child, "reg", &data)) ++ return -EINVAL; ++ if ((data < 0) || (data >= PHY_MAX_ADDR)) { ++ pr_info("%s has invalid PHY address\n", ++ child->full_name); ++ data = HIETH_INVALID_PHY_ADDR; ++ } ++ ++ hieth_phy_param[idx].phy_addr = data; ++ if (data != HIETH_INVALID_PHY_ADDR) ++ hieth_phy_param[idx].isvalid = true; ++ ++ /* get phy_mode */ ++ hieth_phy_param[idx].phy_mode = of_get_phy_mode(child); ++ ++ /* get mac */ ++ hieth_phy_param[idx].macaddr = of_get_mac_address(child); ++ ++ /* get gpio_base and bit */ ++ of_property_read_u32(child, "phy-gpio-base", ++ (u32 *)(&hieth_phy_param[idx].gpio_base)); ++ of_property_read_u32(child, "phy-gpio-bit", ++ &hieth_phy_param[idx].gpio_bit); ++ ++ /* get internal flag */ ++ hieth_phy_param[idx].isinternal = ++ of_property_read_bool(child, "internal-phy"); ++ ++ if (++idx >= HIETH_MAX_PORT) ++ break; ++ } ++ ++ return 0; ++} ++ ++static void hieth_mac_core_reset(struct hieth_netdev_priv *priv) ++{ ++ /* undo reset */ ++ reset_control_deassert(priv->mac_rst); ++ usleep_range(50, 60); ++ ++ /* soft reset mac port */ ++ reset_control_assert(priv->mac_rst); ++ usleep_range(50, 60); ++ /* undo reset */ ++ reset_control_deassert(priv->mac_rst); ++} ++ ++void hieth_phy_get_reset_controller(struct device *dev) ++{ ++ int i; ++ struct hieth_phy_param_s *phy_param; ++ char *rst_name; ++ ++ for (i = 0; i < HIETH_MAX_PORT; i++) { ++ phy_param = &hieth_phy_param[i]; ++ ++ if (!phy_param->isvalid) ++ continue; ++ ++ if (i == 0) ++ rst_name = HIETH_PHY0_RST_NAME; ++ else ++ rst_name = HIETH_PHY1_RST_NAME; ++ ++ phy_param->phy_rst = devm_reset_control_get(dev, rst_name); ++ if (IS_ERR(phy_param->phy_rst)) ++ phy_param->phy_rst = NULL; ++ } ++} ++ ++static int hieth_plat_driver_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ int irq; ++ struct net_device *ndev = NULL; ++ struct device *dev = &pdev->dev; ++ struct device_node *node = dev->of_node; ++ struct resource *res; ++ struct hieth_netdev_priv *priv = &hieth_priv; ++ struct device_node *child = NULL; ++ int port = -1; ++ ++ memset(hieth_devs_save, 0, sizeof(hieth_devs_save)); ++ memset(hieth_phy_param, 0, sizeof(hieth_phy_param)); ++ memset(priv, 0, sizeof(*priv)); ++ ++ if (hieth_of_get_param(node)) { ++ pr_err("of get parameter fail\n"); ++ ret = -ENODEV; ++ goto exit; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ priv->glb_base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(priv->glb_base)) { ++ ret = PTR_ERR(priv->glb_base); ++ goto exit; ++ } ++ ++ priv->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(priv->clk)) { ++ pr_err("failed to get clk\n"); ++ ret = -ENODEV; ++ goto exit; ++ } ++ ++ ret = clk_prepare_enable(priv->clk); ++ if (ret < 0) { ++ pr_err("failed to enable clk %d\n", ret); ++ goto exit; ++ } ++ ++ priv->mac_rst = devm_reset_control_get(dev, HIETH_MAC_RST_NAME); ++ if (IS_ERR(priv->mac_rst)) { ++ ret = PTR_ERR(priv->mac_rst); ++ goto exit_clk_disable; ++ } ++ ++ hieth_mac_core_reset(priv); ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ pr_err("no IRQ defined!\n"); ++ ret = -ENODEV; ++ goto exit_clk_disable; ++ } ++ priv->irq = irq; ++ ++ hieth_phy_get_reset_controller(dev); ++ hieth_phy_reset(); ++ ++ if (hieth_mdiobus_driver_init(pdev, priv)) { ++ pr_err("mdio bus init error!\n"); ++ ret = -ENODEV; ++ goto exit_clk_disable; ++ } ++ ++ /* phy param */ ++ hieth_phy_register_fixups(); ++ ++ for_each_available_child_of_node(node, child) { ++ if (++port >= HIETH_MAX_PORT) ++ break; ++ ++ if (!hieth_phy_param[port].isvalid) ++ continue; ++ ++ priv->phy_node = of_parse_phandle(node, "phy-handle", port); ++ if (!priv->phy_node) { ++ pr_err("not find phy-handle [%d]\n", port); ++ continue; ++ } ++ ++ priv->phy_mode = hieth_phy_param[port].phy_mode; ++ ++ if (!hieth_platdev_probe_port(pdev, priv, port)) ++ hieth_real_port_cnt++; ++ } ++ ++ if (hieth_devs_save[HIETH_PORT_0]) ++ ndev = hieth_devs_save[HIETH_PORT_0]; ++ else if (hieth_devs_save[HIETH_PORT_1]) ++ ndev = hieth_devs_save[HIETH_PORT_1]; ++ ++ if (!ndev) { ++ pr_err("no dev probed!\n"); ++ ret = -ENODEV; ++ goto exit_mdiobus; ++ } ++ ++ return ret; ++ ++exit_mdiobus: ++ hieth_mdiobus_driver_exit(priv); ++ ++exit_clk_disable: ++ clk_disable_unprepare(priv->clk); ++ ++exit: ++ ++ return ret; ++} ++ ++static int hieth_plat_driver_remove(struct platform_device *pdev) ++{ ++ int i; ++ struct net_device *ndev = NULL; ++ struct hieth_netdev_priv *priv = netdev_priv(ndev); ++ ++ if (hieth_devs_save[HIETH_PORT_0]) ++ ndev = hieth_devs_save[HIETH_PORT_0]; ++ else if (hieth_devs_save[HIETH_PORT_1]) ++ ndev = hieth_devs_save[HIETH_PORT_1]; ++ ++ free_irq(ndev->irq, hieth_devs_save); ++ ++ for (i = 0; i < HIETH_MAX_PORT; i++) ++ hieth_platdev_remove_port(pdev, i); ++ ++ hieth_mdiobus_driver_exit(priv); ++ ++ clk_disable_unprepare(priv->clk); ++ ++ memset(hieth_devs_save, 0, sizeof(hieth_devs_save)); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++static int hieth_plat_driver_suspend_port(struct platform_device *pdev, ++ pm_message_t state, int port) ++{ ++ struct net_device *ndev = hieth_devs_save[port]; ++ ++ if (ndev) { ++ if (netif_running(ndev)) { ++ hieth_net_close(ndev); ++ netif_device_detach(ndev); ++ } ++ } ++ ++ return 0; ++} ++ ++int hieth_plat_driver_suspend(struct platform_device *pdev, ++ pm_message_t state) ++{ ++ int i; ++ bool power_off = true; ++ struct hieth_netdev_priv *priv = NULL; ++ ++ for (i = 0; i < HIETH_MAX_PORT; i++) ++ hieth_plat_driver_suspend_port(pdev, state, i); ++ ++ if (hieth_pmt_enter()) ++ power_off = false; ++ ++ if (power_off) { ++ for (i = 0; i < HIETH_MAX_PORT; i++) { ++ if (hieth_devs_save[i]) { ++ priv = netdev_priv(hieth_devs_save[i]); ++ genphy_suspend(priv->phy);/* power down phy */ ++ } ++ } ++ ++ /* need some time before phy suspend finished. */ ++ usleep_range(1000, 10000); ++ ++ if (priv) ++ clk_disable_unprepare(priv->clk); ++ } ++ ++ return 0; ++} ++ ++static int hieth_plat_driver_resume_port(struct platform_device *pdev, int port) ++{ ++ struct net_device *ndev = hieth_devs_save[port]; ++ struct hieth_netdev_priv *priv = netdev_priv(ndev); ++ ++ if (ndev) { ++ if (netif_running(ndev)) { ++ hieth_port_init(priv); ++ hieth_net_open(ndev); ++ netif_device_attach(ndev); ++ } ++ } ++ ++ return 0; ++} ++ ++int hieth_plat_driver_resume(struct platform_device *pdev) ++{ ++ int i; ++ struct hieth_netdev_priv *priv = &hieth_priv; ++ ++ /* enable clk */ ++ clk_prepare_enable(priv->clk); ++ hieth_phy_reset(); ++ ++ for (i = 0; i < HIETH_MAX_PORT; i++) ++ hieth_plat_driver_resume_port(pdev, i); ++ ++ hieth_pmt_exit(); ++ return 0; ++} ++#else ++# define hieth_plat_driver_suspend NULL ++# define hieth_plat_driver_resume NULL ++#endif ++ ++static const struct of_device_id hieth_of_match[] = { ++ {.compatible = "hisilicon,hieth", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, hieth_of_match); ++ ++static struct platform_driver hieth_platform_driver = { ++ .probe = hieth_plat_driver_probe, ++ .remove = hieth_plat_driver_remove, ++ .suspend = hieth_plat_driver_suspend, ++ .resume = hieth_plat_driver_resume, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = HIETH_DRIVER_NAME, ++ .bus = &platform_bus_type, ++ .of_match_table = of_match_ptr(hieth_of_match), ++ }, ++}; ++ ++static int hieth_mod_init(void) ++{ ++ int ret = 0; ++ ++ if (hieth_disable) ++ return 0; ++ ++ ret = platform_driver_register(&hieth_platform_driver); ++ if (ret) ++ pr_err("register platform driver failed!\n"); ++ ++ hieth_proc_create(); ++ ++ return ret; ++} ++ ++static void hieth_mod_exit(void) ++{ ++ if (hieth_disable) ++ return; ++ ++ hieth_proc_destroy(); ++ ++ platform_driver_unregister(&hieth_platform_driver); ++} ++ ++module_init(hieth_mod_init); ++module_exit(hieth_mod_exit); ++ ++MODULE_DESCRIPTION("Hisilicon ETH driver whith MDIO support"); ++MODULE_LICENSE("GPL"); ++ ++/* vim: set ts=8 sw=8 tw=78: */ +diff --git a/drivers/net/ethernet/hisilicon/hieth/hieth.h b/drivers/net/ethernet/hisilicon/hieth/hieth.h +new file mode 100644 +index 0000000..88334b9 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hieth/hieth.h +@@ -0,0 +1,418 @@ ++#ifndef __HIETH_H ++#define __HIETH_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define HIETH_MIIBUS_NAME "himii" ++#define HIETH_DRIVER_NAME "hieth" ++ ++#define HIETH_MAC_RST_NAME "mac_reset" ++#define HIETH_PHY0_RST_NAME "phy0_reset" ++#define HIETH_PHY1_RST_NAME "phy1_reset" ++ ++#define HIETH_TSO_SUPPORTED ++#define HIETH_TSO_DEBUG ++#define HIETH_RXCSUM_SUPPORTED ++ ++#ifdef HIETH_TSO_SUPPORTED ++#include "tso.h" ++#endif ++ ++/* hieth max port */ ++#define HIETH_MAX_PORT 2 ++ ++/* invalid phy addr */ ++#define HIETH_INVALID_PHY_ADDR 31 ++ ++/* hieth monitor timer, 10ms */ ++#define HIETH_MONITOR_TIMER 10 ++ ++/* hieth hardware queue send fifo depth, increase to optimize TX performance. */ ++#define HIETH_HWQ_XMIT_DEPTH 12 ++ ++/* set irq affinity to cpu1 when multi-processor */ ++#define HIETH_IRQ_AFFINITY_CPU 1 ++ ++#define HIETH_MAX_QUEUE_DEPTH 64 ++#define HIETH_MAX_RX_HEAD_LEN (10000) /* max skbs for rx */ ++#define HIETH_MAX_RCV_LEN 1535 /* max receive length */ ++ ++/* mmu should be less than 1600 Bytes ++ */ ++ ++#define HIETH_MAX_FRAME_SIZE (1600) ++#define HIETH_INVALID_RXPKG_LEN(len) (!((len) >= 42 && \ ++ (len) <= HIETH_MAX_FRAME_SIZE)) ++ ++#define HIETH_MAX_MAC_FILTER_NUM 8 ++#define HIETH_MAX_UNICAST_ADDRESSES 2 ++#define HIETH_MAX_MULTICAST_ADDRESSES (HIETH_MAX_MAC_FILTER_NUM - \ ++ HIETH_MAX_UNICAST_ADDRESSES) ++ ++/* Register Definition ++ */ ++/*------------------------- port register -----------------------------------*/ ++/* Mac port sel */ ++#define HIETH_P_MAC_PORTSEL 0x0200 ++#define HIETH_P_MAC_PORTSEL_STAT 0 ++#define HIETH_P_MAC_PORTSEL_STAT_MDIO 0 ++#define HIETH_P_MAC_PORTSEL_STAT_CPU 1 ++#define HIETH_P_MAC_PORTSEL_MII_MODE 1 ++#define HIETH_P_MAC_PORTSEL_MII ~BIT(1) ++#define HIETH_P_MAC_PORTSEL_RMII BIT(1) ++/* Mac ro status */ ++#define HIETH_P_MAC_RO_STAT 0x0204 ++/* Mac port status set */ ++#define HIETH_P_MAC_PORTSET 0x0208 ++#define HIETH_P_MAC_PORTSET_SPD_100M BIT(2) ++#define HIETH_P_MAC_PORTSET_LINKED BIT(1) ++#define HIETH_P_MAC_PORTSET_DUP_FULL BIT(0) ++/* Mac status change */ ++#define HIETH_P_MAC_STAT_CHANGE 0x020C ++/* Mac set */ ++#define HIETH_P_MAC_SET 0x0210 ++#define BIT_PAUSE_EN BIT(18) ++#define HIETH_P_MAC_SET_LEN_MAX(n) ((n) & 0x7FF) ++#define HIETH_P_MAC_SET_LEN_MAX_MSK GENMASK(10, 0) ++ ++#define HIETH_P_MAC_RX_IPGCTRL 0x0214 ++#define HIETH_P_MAC_TX_IPGCTRL 0x0218 ++#define HIETH_P_MAC_TX_IPGCTRL_PRE_CNT_LMT_SHIFT 23 ++#define HIETH_P_MAC_TX_IPGCTRL_PRE_CNT_LMT_MSK GENMASK(25, 23) ++/* queue length set */ ++#define HIETH_P_GLB_QLEN_SET 0x0344 ++#define HIETH_P_GLB_QLEN_SET_TXQ_DEP_MSK GENMASK(5, 0) ++#define HIETH_P_GLB_QLEN_SET_TXQ_DEP(n) ((n) << 0) ++#define HIETH_P_GLB_QLEN_SET_RXQ_DEP_MSK GENMASK(13, 8) ++#define HIETH_P_GLB_QLEN_SET_RXQ_DEP(n) ((n) << 8) ++/* 802.3x flow control register */ ++#define HIETH_P_GLB_FC_LEVEL 0x0348 ++#define BITS_FC_ACTIVE_THR_OFFSET 8 ++#define BIT_FC_EN BIT(14) ++#define BITS_THR_MASK 0x3F ++ ++/* Rx frame start addr */ ++#define HIETH_P_GLB_RXFRM_SADDR 0x0350 ++/* Rx (read only) Queue-ID and LEN */ ++#define HIETH_P_GLB_RO_IQFRM_DES 0x0354 ++#define HIETH_P_GLB_RO_IQFRM_DES_FDIN_LEN_MSK GENMASK(11, 0) ++#define BITS_PAYLOAD_ERR_OFFSET 20 ++#define BITS_PAYLOAD_ERR_MASK 0x1 ++#define BITS_HEADER_ERR_OFFSET 21 ++#define BITS_HEADER_ERR_MASK 0x1 ++#define BITS_PAYLOAD_DONE_OFFSET 22 ++#define BITS_PAYLOAD_DONE_MASK 0x1 ++#define BITS_HEADER_DONE_OFFSET 23 ++#define BITS_HEADER_DONE_MASK 0x1 ++ ++/* Rx ADDR */ ++#define HIETH_P_GLB_IQ_ADDR 0x0358 ++/* Tx ADDR and LEN */ ++#define HIETH_P_GLB_EQ_ADDR 0x0360 ++#define HIETH_P_GLB_EQFRM_LEN 0x0364 ++/* Rx/Tx Queue ID */ ++#define HIETH_P_GLB_RO_QUEUE_ID 0x0368 ++/* Rx/Tx Queue staus */ ++#define HIETH_P_GLB_RO_QUEUE_STAT 0x036C ++/* check this bit to see if we can add a Tx package */ ++#define HIETH_P_GLB_RO_QUEUE_STAT_XMITQ_RDY_MSK BIT(24) ++/* check this bit to see if we can add a Rx addr */ ++#define HIETH_P_GLB_RO_QUEUE_STAT_RECVQ_RDY_MSK BIT(25) ++/* counts in queue, include currently sending */ ++#define HIETH_P_GLB_RO_QUEUE_STAT_XMITQ_CNT_INUSE_MSK GENMASK(5, 0) ++ ++/* Rx COE control */ ++#define HIETH_P_GLB_RX_COE_CTRL 0x0380 ++#define BIT_COE_IPV6_UDP_ZERO_DROP BIT(13) ++#define BIT_COE_PAYLOAD_DROP BIT(14) ++#define BIT_COE_IPHDR_DROP BIT(15) ++#define COE_ERR_DROP (BIT_COE_IPHDR_DROP | BIT_COE_PAYLOAD_DROP | \ ++ BIT_COE_IPV6_UDP_ZERO_DROP) ++ ++#ifdef HIETH_TSO_SUPPORTED ++/* TSO debug enable */ ++#define HIETH_P_GLB_TSO_DBG_EN 0x03A4 ++#define BITS_TSO_DBG_EN BIT(31) ++/* TSO debug state */ ++#define HIETH_P_GLB_TSO_DBG_STATE 0x03A8 ++#define BITS_TSO_DBG_STATE BIT(31) ++/* TSO debug addr */ ++#define HIETH_P_GLB_TSO_DBG_ADDR 0x03AC ++/* TSO debug tx info */ ++#define HIETH_P_GLB_TSO_DBG_TX_INFO 0x03B0 ++/* TSO debug tx err */ ++#define HIETH_P_GLB_TSO_DBG_TX_ERR 0x03B4 ++#endif ++ ++/*------------------------- global register --------------------------------*/ ++/* host mac address */ ++#define HIETH_GLB_HOSTMAC_L32 0x1300 ++#define HIETH_GLB_HOSTMAC_H16 0x1304 ++/* soft reset */ ++#define HIETH_GLB_SOFT_RESET 0x1308 ++#define HIETH_GLB_SOFT_RESET_ALL BIT(0) ++#define HIETH_GLB_SOFT_RESET_P0 BIT(2) ++#define HIETH_GLB_SOFT_RESET_P1 BIT(3) ++/* forward contrl */ ++#define HIETH_GLB_FWCTRL 0x1310 ++#define HIETH_GLB_FWCTRL_VLAN_ENABLE BIT(0) ++#define HIETH_GLB_FWCTRL_FW2CPU_ENA_U BIT(5) ++#define HIETH_GLB_FWCTRL_FW2CPU_ENA_D BIT(9) ++#define HIETH_GLB_FWCTRL_FWALL2CPU_U BIT(7) ++#define HIETH_GLB_FWCTRL_FWALL2CPU_D BIT(11) ++#define HIETH_GLB_FWCTRL_FW2OTHPORT_ENA_U BIT(4) ++#define HIETH_GLB_FWCTRL_FW2OTHPORT_ENA_D BIT(8) ++#define HIETH_GLB_FWCTRL_FW2OTHPORT_FORCE_U BIT(6) ++#define HIETH_GLB_FWCTRL_FW2OTHPORT_FORCE_D BIT(10) ++/* Mac filter table control */ ++#define HIETH_GLB_MACTCTRL 0x1314 ++#define HIETH_GLB_MACTCTRL_MACT_ENA_U BIT(7) ++#define HIETH_GLB_MACTCTRL_MACT_ENA_D BIT(15) ++#define HIETH_GLB_MACTCTRL_BROAD2CPU_U BIT(5) ++#define HIETH_GLB_MACTCTRL_BROAD2CPU_D BIT(13) ++#define HIETH_GLB_MACTCTRL_BROAD2OTHPORT_U BIT(4) ++#define HIETH_GLB_MACTCTRL_BROAD2OTHPORT_D BIT(12) ++#define HIETH_GLB_MACTCTRL_MULTI2CPU_U BIT(3) ++#define HIETH_GLB_MACTCTRL_MULTI2CPU_D BIT(11) ++#define HIETH_GLB_MACTCTRL_MULTI2OTHPORT_U BIT(2) ++#define HIETH_GLB_MACTCTRL_MULTI2OTHPORT_D BIT(10) ++#define HIETH_GLB_MACTCTRL_UNI2CPU_U BIT(1) ++#define HIETH_GLB_MACTCTRL_UNI2CPU_D BIT(9) ++#define HIETH_GLB_MACTCTRL_UNI2OTHPORT_U BIT(0) ++#define HIETH_GLB_MACTCTRL_UNI2OTHPORT_D BIT(8) ++/* Host mac address */ ++#define HIETH_GLB_DN_HOSTMAC_L32 0x1340 ++#define HIETH_GLB_DN_HOSTMAC_H16 0x1344 ++#define HIETH_GLB_DN_HOSTMAC_ENA 0x1348 ++#define HIETH_GLB_DN_HOSTMAC_ENA_BIT BIT(0) ++/* Mac filter */ ++#define HIETH_GLB_MAC_L32_BASE 0x1400 ++#define HIETH_GLB_MAC_H16_BASE 0x1404 ++#define HIETH_GLB_MAC_L32_BASE_D (0x1400 + 16 * 0x8) ++#define HIETH_GLB_MAC_H16_BASE_D (0x1404 + 16 * 0x8) ++#define HIETH_GLB_MACFLT_HI16 GENMASK(15, 0) ++#define HIETH_GLB_MACFLT_FW2CPU_U BIT(21) ++#define HIETH_GLB_MACFLT_FW2CPU_D BIT(19) ++#define HIETH_GLB_MACFLT_FW2PORT_U BIT(20) ++#define HIETH_GLB_MACFLT_FW2PORT_D BIT(18) ++#define HIETH_GLB_MACFLT_ENA_U BIT(17) ++#define HIETH_GLB_MACFLT_ENA_D BIT(16) ++/* ENDIAN */ ++#define HIETH_GLB_ENDIAN_MOD 0x1318 ++#define HIETH_GLB_ENDIAN_MOD_IN BIT(1) ++#define HIETH_GLB_ENDIAN_MOD_OUT BIT(0) ++/* IRQs */ ++#define HIETH_GLB_IRQ_STAT 0x1330 ++#define HIETH_GLB_IRQ_ENA 0x1334 ++#define HIETH_GLB_IRQ_ENA_IEN_A BIT(19) ++#define HIETH_GLB_IRQ_ENA_IEN_U BIT(18) ++#define HIETH_GLB_IRQ_ENA_IEN_D BIT(17) ++#define HIETH_GLB_IRQ_ENA_BIT_U GENMASK(7, 0) ++#define HIETH_GLB_IRQ_ENA_BIT_D GENMASK(27, 20) ++#define HIETH_GLB_IRQ_RAW 0x1338 ++#define HIETH_GLB_IRQ_INT_MULTI_RXRDY_U BIT(7) ++#define HIETH_GLB_IRQ_INT_MULTI_RXRDY_D BIT(27) ++#define HIETH_GLB_IRQ_INT_TXQUE_RDY_U BIT(6) ++#define HIETH_GLB_IRQ_INT_TXQUE_RDY_D BIT(26) ++#define HIETH_GLB_IRQ_INT_RX_RDY_U BIT(0) ++#define HIETH_GLB_IRQ_INT_RX_RDY_D BIT(20) ++#define HIETH_INT_TX_ERR_U BIT(8) ++#define HIETH_INT_TX_ERR_D BIT(28) ++ ++/* *********************************************************** ++* ++* Only for internal used! ++* ++* *********************************************************** ++*/ ++ ++/* read/write IO */ ++#define hieth_readl(base, ofs) \ ++ readl(base + (ofs)) ++#define hieth_writel(base, v, ofs) \ ++ writel(v, base + (ofs)) ++ ++#define hieth_trace_level 8 ++#define hireg_trace(level, msg...) do { \ ++if ((level) >= hieth_trace_level) { \ ++ pr_info("hireg_trace:%s:%d: ", __func__, __LINE__); \ ++ pr_info(msg); \ ++ pr_info("\n"); \ ++} \ ++} while (0) ++ ++#define hireg_readl(base, ofs) ({ unsigned long reg = readl((base) + (ofs)); \ ++ hireg_trace(2, "_readl(0x%04X) = 0x%08lX", (ofs), reg); \ ++ reg; }) ++ ++#define hireg_writel(base, v, ofs) do { writel((v), (base) + (ofs)); \ ++ hireg_trace(2, "_writel(0x%04X) = 0x%08lX", \ ++ (ofs), (unsigned long)(v)); \ ++} while (0) ++ ++#define hieth_dump_buf(buf, len) do {\ ++ int i;\ ++ char *p = (void *)(buf);\ ++ pr_info("%s->%d, buf=0x%.8x, len=%d\n", \ ++ __func__, __LINE__, \ ++ (int)(buf), (int)(len)); \ ++ for (i = 0; i < (len); i++) {\ ++ pr_info("0x%.2x ", *(p+i));\ ++ if (!((i+1) & 0x07)) \ ++ pr_info("\n");\ ++ } \ ++ pr_info("\n");\ ++} while (0) ++ ++/* port */ ++enum hieth_port_e { ++ HIETH_PORT_0 = 0, ++ HIETH_PORT_1, ++ HIETH_PORT_NUM, ++}; ++ ++struct hieth_netdev_priv { ++ void __iomem *glb_base; /* virtual io global addr */ ++ void __iomem *port_base; /* virtual to port addr: ++ * port0-0; port1-0x2000 ++ */ ++ int port; /* 0 => up port, 1 => down port */ ++ int irq; ++ ++ struct device *dev; ++ struct net_device_stats stats; ++ struct phy_device *phy; ++ struct device_node *phy_node; ++ phy_interface_t phy_mode; ++ ++ struct mii_bus *mii_bus; ++ ++ struct sk_buff_head rx_head; /*received pkgs */ ++ struct sk_buff_head rx_hw; /*rx pkgs in hw */ ++#ifdef HIETH_TSO_SUPPORTED ++ struct dma_tx_desc *dma_tx ____cacheline_aligned; ++ dma_addr_t dma_tx_phy; ++ unsigned int sg_head; ++ unsigned int sg_tail; ++#endif ++#ifdef HIETH_TSO_SUPPORTED ++ struct tx_pkt_info *txq; ++ unsigned int txq_head; ++ unsigned int txq_tail; ++ int q_size; ++#else ++ struct sk_buff_head tx_hw; /*tx pkgs in hw */ ++#endif ++ u32 tx_hw_cnt; ++ ++ struct timer_list monitor; ++ ++ struct { ++ int hw_xmitq; ++ } depth; ++ ++ struct { ++ unsigned long rx_pool_dry_times; ++ } stat; ++ ++#define SKB_SIZE (HIETH_MAX_FRAME_SIZE) ++ struct rx_skb_pool { ++ struct sk_buff *sk_pool[CONFIG_HIETH_MAX_RX_POOLS];/*skb pool*/ ++ int next_free_skb; /*next free skb*/ ++ } rx_pool; ++ ++ struct tasklet_struct bf_recv; ++ ++ int link_stat; ++ int (*eee_init)(struct phy_device *phy_dev); ++ ++ spinlock_t lock; /* lock for reg rw */ ++ unsigned long lockflags; ++ ++ spinlock_t mdio_lock; /* lock for mdio reg */ ++ unsigned long mdio_lockflags; ++ ++ struct clk *clk; ++ struct reset_control *mac_rst; ++ struct reset_control *phy_rst; ++ /* 802.3x flow control */ ++ int tx_pause_en; ++ int tx_pause_active_thresh; ++ int tx_pause_deactive_thresh; ++}; ++ ++/* phy parameter */ ++struct hieth_phy_param_s { ++ bool isvalid; /* valid or not */ ++ bool isinternal; /* internal phy or external phy */ ++ int phy_addr; ++ phy_interface_t phy_mode; ++ const char *macaddr; ++ ++ struct reset_control *phy_rst; ++ ++ /* gpio reset pin if has */ ++ void __iomem *gpio_base; ++ u32 gpio_bit; ++}; ++ ++#ifdef HIETH_TSO_DEBUG ++#define MAX_RECORD (100) ++struct send_pkt_info { ++ u32 reg_addr; ++ u32 reg_pkt_info; ++ u32 status; ++}; ++ ++extern unsigned int id_send; ++extern unsigned int id_free; ++extern struct send_pkt_info pkt_rec[MAX_RECORD]; ++#endif ++ ++#define local_lock_init(priv) spin_lock_init(&(priv)->lock) ++#define local_lock_exit(priv) ++#define local_lock(priv) spin_lock_irqsave(&(priv)->lock, \ ++ (priv)->lockflags) ++#define local_unlock(priv) spin_unlock_irqrestore(&(priv)->lock, \ ++ (priv)->lockflags) ++ ++#define hieth_mdio_lock_init(priv) spin_lock_init(&(priv)->mdio_lock) ++#define hieth_mdio_lock_exit(priv) ++#define hieth_mdio_lock(priv) spin_lock_irqsave(&(priv)->mdio_lock, \ ++ (priv)->mdio_lockflags) ++#define hieth_mdio_unlock(priv) spin_unlock_irqrestore(&(priv)->mdio_lock, \ ++ (priv)->mdio_lockflags) ++ ++#define UD_BIT_NAME(name) ((priv->port == HIETH_PORT_0) ? \ ++ name##_U : name##_D) ++ ++#define GLB_MAC_H16(port, reg) ((((port) == HIETH_PORT_0) ? \ ++ HIETH_GLB_MAC_H16_BASE : \ ++ HIETH_GLB_MAC_H16_BASE_D) + (reg * 0x8)) ++#define GLB_MAC_L32(port, reg) ((((port) == HIETH_PORT_0) ? \ ++ HIETH_GLB_MAC_L32_BASE : \ ++ HIETH_GLB_MAC_L32_BASE_D) + (reg * 0x8)) ++ ++#define SIOCGETMODE (SIOCDEVPRIVATE) /* get work mode */ ++#define SIOCSETMODE (SIOCDEVPRIVATE + 1) /* set work mode */ ++#define SIOCGETFWD (SIOCDEVPRIVATE + 2) /* get forcing forward config */ ++#define SIOCSETFWD (SIOCDEVPRIVATE + 3) /* set forcing forward config */ ++#define SIOCSETPM (SIOCDEVPRIVATE + 4) /* set pmt wake up config */ ++#define SIOCSETSUSPEND (SIOCDEVPRIVATE + 5) /* call dev->suspend */ ++#define SIOCSETRESUME (SIOCDEVPRIVATE + 6) /* call dev->resume */ ++ ++extern struct hieth_phy_param_s hieth_phy_param[]; ++ ++void hieth_autoeee_init(struct hieth_netdev_priv *priv, int link_stat); ++void hieth_phy_register_fixups(void); ++void hieth_phy_reset(void); ++ ++#endif ++ ++/* vim: set ts=8 sw=8 tw=78: */ +diff --git a/drivers/net/ethernet/hisilicon/hieth/mdio.c b/drivers/net/ethernet/hisilicon/hieth/mdio.c +new file mode 100644 +index 0000000..bb63593 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hieth/mdio.c +@@ -0,0 +1,180 @@ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hieth.h" ++#include "mdio.h" ++ ++/* MDIO Bus Interface */ ++ ++static void hieth_mdio_init(struct hieth_netdev_priv *priv) ++{ ++ hieth_mdio_lock_init(priv); ++ mdio_reg_reset(priv); ++} ++ ++static void hieth_mdio_exit(struct hieth_netdev_priv *priv) ++{ ++ hieth_mdio_lock_exit(priv); ++} ++ ++static int hieth_wait_mdio_ready(struct hieth_netdev_priv *priv) ++{ ++ int timeout_us = 1000; ++ ++ while (--timeout_us && !mdio_test_ready(priv)) ++ udelay(1); ++ ++ return timeout_us; ++} ++ ++static int hieth_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum) ++{ ++ int val = 0; ++ struct hieth_netdev_priv *priv = bus->priv; ++ ++ hieth_mdio_lock(priv); ++ ++ if (!hieth_wait_mdio_ready(priv)) { ++ pr_err("mdio busy\n"); ++ goto error_exit; ++ } ++ ++ mdio_start_phyread(priv, phy_addr, regnum); ++ ++ if (hieth_wait_mdio_ready(priv)) ++ val = mdio_get_phyread_val(priv); ++ else ++ pr_err("read timeout\n"); ++ ++error_exit: ++ ++ hieth_mdio_unlock(priv); ++ ++ pr_debug("phy_addr = %d, regnum = %d, val = 0x%04x\n", ++ phy_addr, regnum, val); ++ ++ return val; ++} ++ ++static int hieth_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum, ++ u16 val) ++{ ++ int ret = 0; ++ struct hieth_netdev_priv *priv = bus->priv; ++ ++ pr_debug("phy_addr = %d, regnum = %d\n", phy_addr, regnum); ++ ++ hieth_mdio_lock(priv); ++ ++ if (!hieth_wait_mdio_ready(priv)) { ++ pr_err("mdio busy\n"); ++ ret = -1; ++ goto error_exit; ++ } ++ ++ mdio_phywrite(priv, phy_addr, regnum, val); ++ ++error_exit: ++ ++ hieth_mdio_unlock(priv); ++ ++ return ret; ++} ++ ++static int hieth_mdiobus_reset(struct mii_bus *bus) ++{ ++ struct hieth_netdev_priv *priv = bus->priv; ++ ++ mdio_reg_reset(priv); ++ return 0; ++} ++ ++int hieth_mdiobus_driver_init(struct platform_device *pdev, ++ struct hieth_netdev_priv *priv) ++{ ++ int phy, ret = 0; ++ struct mii_bus *bus; ++ struct device *dev = &pdev->dev; ++ struct device_node *node = dev->of_node; ++ ++ hieth_mdio_init(priv); ++ ++ /* register MII bus */ ++ bus = mdiobus_alloc(); ++ if (!bus) { ++ pr_err("get ioresource failed!\n"); ++ ret = -ENOMEM; ++ goto _error_exit; ++ } ++ ++ bus->name = HIETH_MIIBUS_NAME; ++ ++ snprintf(bus->id, MII_BUS_ID_SIZE, "%s", bus->name); ++ bus->read = hieth_mdiobus_read; ++ bus->write = hieth_mdiobus_write; ++ bus->reset = hieth_mdiobus_reset; ++ bus->priv = priv; ++ priv->mii_bus = bus; ++ bus->parent = &pdev->dev; /*for Power Management */ ++ ++ bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); ++ if (!bus->irq) { ++ ret = -ENOMEM; ++ goto _error_free_mdiobus; ++ } ++ ++ for (phy = 0; phy < PHY_MAX_ADDR; phy++) ++ bus->irq[phy] = PHY_POLL; ++ ++ ret = of_mdiobus_register(bus, node); ++ if (ret) { ++ pr_err("failed to register MDIO bus\n"); ++ goto _error_free_mdiobus; ++ } ++ ++ return 0; ++ ++_error_free_mdiobus: ++ kfree(bus->irq); ++ mdiobus_free(bus); ++ ++_error_exit: ++ return ret; ++} ++ ++void hieth_mdiobus_driver_exit(struct hieth_netdev_priv *priv) ++{ ++ struct mii_bus *bus = priv->mii_bus; ++ ++ mdiobus_unregister(bus); ++ kfree(bus->irq); ++ mdiobus_free(bus); ++ hieth_mdio_exit(priv); ++} ++ ++/* vim: set ts=8 sw=8 tw=78: */ +diff --git a/drivers/net/ethernet/hisilicon/hieth/mdio.h b/drivers/net/ethernet/hisilicon/hieth/mdio.h +new file mode 100644 +index 0000000..9bb13fb +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hieth/mdio.h +@@ -0,0 +1,61 @@ ++#ifndef __HIETH_MDIO_H ++#define __HIETH_MDIO_H ++ ++#define HIETH_MDIO_FRQDIV 2 ++ ++#define HIETH_MDIO_RWCTRL 0x1100 ++#define HIETH_MDIO_RO_DATA 0x1104 ++#define HIETH_U_MDIO_PHYADDR 0x0108 ++#define HIETH_D_MDIO_PHYADDR 0x2108 ++#define HIETH_U_MDIO_RO_STAT 0x010C ++#define HIETH_D_MDIO_RO_STAT 0x210C ++#define HIETH_U_MDIO_ANEG_CTRL 0x0110 ++#define HIETH_D_MDIO_ANEG_CTRL 0x2110 ++#define HIETH_U_MDIO_IRQENA 0x0114 ++#define HIETH_D_MDIO_IRQENA 0x2114 ++ ++#define MDIO_MK_RWCTL(cpu_data_in, finish, rw, phy_exaddr, frq_div, phy_regnum)\ ++ (((cpu_data_in) << 16) | \ ++ (((finish) & 0x01) << 15) | \ ++ (((rw) & 0x01) << 13) | \ ++ (((phy_exaddr) & 0x1F) << 8) | \ ++ (((frq_div) & 0x7) << 5) | \ ++ ((phy_regnum) & 0x1F)) ++ ++/* hardware set bit'15 of MDIO_REG(0) if mdio ready */ ++#define mdio_test_ready(priv) (hieth_readl(priv->glb_base, \ ++ HIETH_MDIO_RWCTRL) & (1 << 15)) ++ ++#define mdio_start_phyread(priv, phy_addr, regnum) \ ++ hieth_writel(priv->glb_base, \ ++ MDIO_MK_RWCTL(0, 0, 0, phy_addr, HIETH_MDIO_FRQDIV, \ ++ regnum), \ ++ HIETH_MDIO_RWCTRL) ++ ++#define mdio_get_phyread_val(priv) (hieth_readl(priv->glb_base, \ ++ HIETH_MDIO_RO_DATA) & 0xFFFF) ++ ++#define mdio_phywrite(priv, phy_addr, regnum, val) \ ++ hieth_writel(priv->glb_base, \ ++ MDIO_MK_RWCTL(val, 0, 1, phy_addr, HIETH_MDIO_FRQDIV, \ ++ regnum), \ ++ HIETH_MDIO_RWCTRL) ++ ++/* write mdio registers reset value */ ++#define mdio_reg_reset(priv) do { \ ++ hieth_writel(priv->glb_base, 0x00008000, HIETH_MDIO_RWCTRL); \ ++ hieth_writel(priv->glb_base, 0x00000001, HIETH_U_MDIO_PHYADDR); \ ++ hieth_writel(priv->glb_base, 0x00000001, HIETH_D_MDIO_PHYADDR); \ ++ hieth_writel(priv->glb_base, 0x04631EA9, HIETH_U_MDIO_ANEG_CTRL); \ ++ hieth_writel(priv->glb_base, 0x04631EA9, HIETH_D_MDIO_ANEG_CTRL); \ ++ hieth_writel(priv->glb_base, 0x00000000, HIETH_U_MDIO_IRQENA); \ ++ hieth_writel(priv->glb_base, 0x00000000, HIETH_D_MDIO_IRQENA); \ ++} while (0) ++ ++int hieth_mdiobus_driver_init(struct platform_device *pdev, ++ struct hieth_netdev_priv *priv); ++void hieth_mdiobus_driver_exit(struct hieth_netdev_priv *priv); ++ ++#endif ++ ++/* vim: set ts=8 sw=8 tw=78: */ +diff --git a/drivers/net/ethernet/hisilicon/hieth/phy.c b/drivers/net/ethernet/hisilicon/hieth/phy.c +new file mode 100644 +index 0000000..075a2c3 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hieth/phy.c +@@ -0,0 +1,89 @@ ++#include ++#include ++#include "hieth.h" ++#include "mdio.h" ++#include "phy.h" ++ ++static int KSZ8051MNL_phy_fix(struct phy_device *phy_dev) ++{ ++ u32 v; ++ ++ if (phy_dev->interface != PHY_INTERFACE_MODE_RMII) ++ return 0; ++ ++ v = phy_read(phy_dev, 0x1F); ++ v |= (1 << 7); /* set phy RMII 50MHz clk; */ ++ phy_write(phy_dev, 0x1F, v); ++ ++ v = phy_read(phy_dev, 0x16); ++ v |= (1 << 1); /* set phy RMII override; */ ++ phy_write(phy_dev, 0x16, v); ++ ++ return 0; ++} ++ ++static int KSZ8081RNB_phy_fix(struct phy_device *phy_dev) ++{ ++ u32 v; ++ ++ if (phy_dev->interface != PHY_INTERFACE_MODE_RMII) ++ return 0; ++ ++ v = phy_read(phy_dev, 0x1F); ++ v |= (1 << 7); /* set phy RMII 50MHz clk; */ ++ phy_write(phy_dev, 0x1F, v); ++ ++ return 0; ++} ++ ++void hieth_phy_register_fixups(void) ++{ ++ phy_register_fixup_for_uid(PHY_ID_KSZ8051MNL, ++ DEFAULT_PHY_MASK, KSZ8051MNL_phy_fix); ++ phy_register_fixup_for_uid(PHY_ID_KSZ8081RNB, ++ DEFAULT_PHY_MASK, KSZ8081RNB_phy_fix); ++} ++ ++static void hieth_internal_phy_reset(struct hieth_phy_param_s *phy_param) ++{ ++} ++ ++static void hieth_external_phy_reset(struct hieth_phy_param_s *phy_param) ++{ ++ if (phy_param->phy_rst) { ++ /* write 0 to cancel reset */ ++ reset_control_deassert(phy_param->phy_rst); ++ msleep(50); ++ ++ /* RST_BIT, write 1 to reset phy, write 0 to cancel reset */ ++ reset_control_assert(phy_param->phy_rst); ++ ++ /* delay some time to ensure reset ok, ++ * this depends on PHY hardware feature ++ */ ++ msleep(50); ++ ++ /* write 0 to cancel reset */ ++ reset_control_deassert(phy_param->phy_rst); ++ /* delay some time to ensure later MDIO access */ ++ msleep(50); ++ } ++} ++ ++void hieth_phy_reset(void) ++{ ++ int i; ++ struct hieth_phy_param_s *phy_param; ++ ++ for (i = 0; i < HIETH_MAX_PORT; i++) { ++ phy_param = &hieth_phy_param[i]; ++ ++ if (!phy_param->isvalid) ++ continue; ++ ++ if (phy_param->isinternal) ++ hieth_internal_phy_reset(phy_param); ++ else ++ hieth_external_phy_reset(phy_param); ++ } ++} +diff --git a/drivers/net/ethernet/hisilicon/hieth/phy.h b/drivers/net/ethernet/hisilicon/hieth/phy.h +new file mode 100644 +index 0000000..60de1bc +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hieth/phy.h +@@ -0,0 +1,18 @@ ++#ifndef __HIETH_FEPHY_FIX_H ++#define __HIETH_FEPHY_FIX_H ++ ++#define MII_EXPMD 0x1D ++#define MII_EXPMA 0x1E ++ ++#define HISILICON_PHY_ID_FESTAV200 (0x20669823) ++#define HISILICON_PHY_ID_FESTAV300 (0x20669833) ++#define HISILICON_PHY_MASK (0xfffffff0) ++ ++/* the following two copied from phy_quirk() ++ * in "./drivers/net/ethernet/hieth-sf/net.c" ++ */ ++#define PHY_ID_KSZ8051MNL (0x00221550) ++#define PHY_ID_KSZ8081RNB (0x00221560) ++#define DEFAULT_PHY_MASK (0xfffffff0) ++ ++#endif +diff --git a/drivers/net/ethernet/hisilicon/hieth/pm.c b/drivers/net/ethernet/hisilicon/hieth/pm.c +new file mode 100644 +index 0000000..2ace419 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hieth/pm.c +@@ -0,0 +1,323 @@ ++#include ++ ++#define HIETH_PM_N (31) ++#define HIETH_PM_FILTERS (4) ++ ++struct hieth_pm_config { ++ unsigned char index; /* bit0--eth0 bit1--eth1 */ ++ unsigned char uc_pkts_enable; ++ unsigned char magic_pkts_enable; ++ unsigned char wakeup_pkts_enable; ++ struct { ++ unsigned int mask_bytes : HIETH_PM_N; ++ unsigned int reserved : 1;/* userspace ignore this bit */ ++ unsigned char offset; /* >= 12 */ ++ unsigned char value[HIETH_PM_N];/* byte string */ ++ unsigned char valid; /* valid filter */ ++ } filter[HIETH_PM_FILTERS]; ++}; ++ ++#define HIETH_PMT_CTRL 0x0500 ++#define HIETH_PMT_MASK0 0x0504 ++#define HIETH_PMT_MASK1 0x0508 ++#define HIETH_PMT_MASK2 0x050c ++#define HIETH_PMT_MASK3 0x0510 ++#define HIETH_PMT_CMD 0x0514 ++#define HIETH_PMT_OFFSET 0x0518 ++#define HIETH_PMT_CRC1_0 0x051c ++#define HIETH_PMT_CRC3_2 0x0520 ++ ++static void hieth_init_crc_table(void); ++static unsigned short hieth_compute_crc(char *message, int n_bytes); ++static unsigned short calculate_crc16(char *buf, unsigned int mask) ++{ ++ char data[HIETH_PM_N]; ++ int i, len = 0; ++ ++ memset(data, 0, sizeof(data)); ++ ++ for (i = 0; i < HIETH_PM_N; i++) { ++ if (mask & 0x1) ++ data[len++] = buf[i]; ++ ++ mask >>= 1; ++ } ++ ++ return hieth_compute_crc(data, len); ++} ++ ++#define HIETH_PM_SET (1) ++#define HIETH_PM_CLEAR (0) ++static char pm_state[HIETH_MAX_PORT] = {HIETH_PM_CLEAR, HIETH_PM_CLEAR}; ++ ++int hieth_pmt_config_eth(struct hieth_pm_config *config, ++ struct hieth_netdev_priv *priv) ++{ ++ unsigned int v = 0, cmd = 0, offset = 0; ++ unsigned short crc[HIETH_PM_FILTERS] = {0}; ++ int reg_mask = 0; ++ int i; ++ ++ if (!priv) ++ return -EINVAL; ++ ++ local_lock(priv); ++ if (config->wakeup_pkts_enable) { ++ /* disable wakeup_pkts_enable before reconfig? */ ++ v = hieth_readl(priv->port_base, HIETH_PMT_CTRL); ++ v &= ~(1 << 2); ++ /* any side effect? */ ++ hieth_writel(priv->port_base, v, HIETH_PMT_CTRL); ++ } else { ++ goto config_ctrl; ++ } ++ ++/* filter.valid mask.valid mask_bytes effect ++ * 0 * * no use the filter ++ * 1 0 * all pkts can wake-up(non-exist) ++ * 1 1 0 all pkts can wake-up ++ * 1 1 !0 normal filter ++ */ ++ /* setup filter */ ++ for (i = 0; i < HIETH_PM_FILTERS; i++) { ++ if (config->filter[i].valid) { ++ if (config->filter[i].offset < 12) ++ continue; ++ /* offset and valid bit */ ++ offset |= config->filter[i].offset << (i * 8); ++ cmd |= 1 << (i * 8); /* valid bit */ ++ /* mask */ ++ reg_mask = HIETH_PMT_MASK0 + (i * 4); ++ ++ /* for logic, mask valid bit(bit31) must set to 0, ++ * 0 is enable ++ */ ++ v = config->filter[i].mask_bytes; ++ v &= ~(1 << 31); ++ hieth_writel(priv->port_base, v, reg_mask); ++ ++ /* crc */ ++ crc[i] = calculate_crc16(config->filter[i].value, v); ++ if (i <= 1) {/* for filter0 and filter 1 */ ++ v = hieth_readl(priv->port_base, ++ HIETH_PMT_CRC1_0); ++ v &= ~(0xFFFF << (16 * i)); ++ v |= crc[i] << (16 * i); ++ hieth_writel(priv->port_base, v, ++ HIETH_PMT_CRC1_0); ++ } else {/* filter2 and filter3 */ ++ v = hieth_readl(priv->port_base, ++ HIETH_PMT_CRC3_2); ++ v &= ~(0xFFFF << (16 * (i - 2))); ++ v |= crc[i] << (16 * (i - 2)); ++ hieth_writel(priv->port_base, v, ++ HIETH_PMT_CRC3_2); ++ } ++ } ++ } ++ ++ if (cmd) { ++ hieth_writel(priv->port_base, offset, HIETH_PMT_OFFSET); ++ hieth_writel(priv->port_base, cmd, HIETH_PMT_CMD); ++ } ++ ++config_ctrl: ++ v = 0; ++ if (config->uc_pkts_enable) ++ v |= 1 << 9; /* uc pkts wakeup */ ++ if (config->wakeup_pkts_enable) ++ v |= 1 << 2; /* use filter framework */ ++ if (config->magic_pkts_enable) ++ v |= 1 << 1; /* magic pkts wakeup */ ++ ++ v |= 3 << 5; /* clear irq status */ ++ hieth_writel(priv->port_base, v, HIETH_PMT_CTRL); ++ ++ local_unlock(priv); ++ ++ return 0; ++} ++ ++/* pmt_config will overwrite pre-config */ ++int hieth_pmt_config(struct hieth_pm_config *config) ++{ ++ static int init; ++ int map = config->index, i, ret = -EINVAL; ++ struct hieth_netdev_priv *priv; ++ ++ if (!init) ++ hieth_init_crc_table(); ++ ++ for (i = 0; i < HIETH_MAX_PORT; i++) { ++ if (!hieth_devs_save[i]) ++ continue; ++ ++ priv = netdev_priv(hieth_devs_save[i]); ++ ++ if (map & 0x1) { ++ ret = hieth_pmt_config_eth(config, priv); ++ if (ret) ++ return ret; ++ ++ pm_state[i] = HIETH_PM_SET; ++ device_set_wakeup_enable(priv->dev, 1); ++ } ++ map >>= 1; ++ } ++ ++ return ret; ++} ++ ++inline bool hieth_pmt_enter(void) ++{ ++ int i, v, pm = false; ++ struct hieth_netdev_priv *priv; ++ ++ for (i = 0; i < HIETH_MAX_PORT; i++) { ++ if (!hieth_devs_save[i]) ++ continue; ++ ++ priv = netdev_priv(hieth_devs_save[i]); ++ ++ local_lock(priv); ++ if (pm_state[i] == HIETH_PM_SET) { ++ v = hieth_readl(priv->port_base, HIETH_PMT_CTRL); ++ v |= 1 << 0; /* enter power down */ ++ v |= 1 << 3; /* enable wakeup irq */ ++ v |= 3 << 5; /* clear irq status */ ++ hieth_writel(priv->port_base, v, HIETH_PMT_CTRL); ++ ++ pm_state[i] = HIETH_PM_CLEAR; ++ pm = true; ++ } ++ local_unlock(priv); ++ } ++ return pm; ++} ++ ++inline void hieth_pmt_exit(void) ++{ ++ int i, v; ++ struct hieth_netdev_priv *priv; ++ ++ for (i = 0; i < HIETH_MAX_PORT; i++) { ++ if (!hieth_devs_save[i]) ++ continue; ++ ++ priv = netdev_priv(hieth_devs_save[i]); ++ ++ /* logic auto exit power down mode */ ++ local_lock(priv); ++ ++ v = hieth_readl(priv->port_base, HIETH_PMT_CTRL); ++ v &= ~(1 << 0); /* enter power down */ ++ v &= ~(1 << 3); /* enable wakeup irq */ ++ ++ v |= 3 << 5; /* clear irq status */ ++ hieth_writel(priv->port_base, v, HIETH_PMT_CTRL); ++ ++ local_unlock(priv); ++ } ++ ++ /* device_set_wakeup_enable(priv->dev, 0); */ ++} ++ ++/* ========the following code copy from Synopsys DWC_gmac_crc_example.c====== */ ++#define CRC16 /* Change it to CRC16 for CRC16 Computation*/ ++ ++#define FALSE 0 ++#define TRUE !FALSE ++ ++#if defined(CRC16) ++#define CRC_NAME "CRC-16" ++#define POLYNOMIAL 0x8005 ++#define INITIAL_REMAINDER 0xFFFF ++#define FINAL_XOR_VALUE 0x0000 ++#define REVERSE_DATA TRUE ++#define REVERSE_REMAINDER FALSE ++#endif ++ ++#define WIDTH (8 * sizeof(unsigned short)) ++#define TOPBIT (1 << (WIDTH - 1)) ++ ++#if (REVERSE_DATA) ++#undef REVERSE_DATA ++#define REVERSE_DATA(X) ((unsigned char)reverse((X), 8)) ++#else ++#undef REVERSE_DATA ++#define REVERSE_DATA(X) (X) ++#endif ++ ++#if (REVERSE_REMAINDER) ++#undef REVERSE_REMAINDER ++#define REVERSE_REMAINDER(X) ((unsigned short)reverse((X), WIDTH)) ++#else ++#undef REVERSE_REMAINDER ++#define REVERSE_REMAINDER(X) (X) ++#endif ++ ++static unsigned short crctable[256]; ++ ++/* Reverse the data ++ * ++ * Input1: Data to be reversed ++ * Input2: number of bits in the data ++ * Output: The reversed data ++ */ ++unsigned long reverse(unsigned long data, unsigned char nbits) ++{ ++ unsigned long reversed = 0x00000000; ++ unsigned char bit; ++ ++ /* Reverse the data about the center bit. */ ++ for (bit = 0; bit < nbits; ++bit) { ++ /* If the LSB bit is set, set the reflection of it. */ ++ if (data & 0x01) ++ reversed |= (1 << ((nbits - 1) - bit)); ++ ++ data = (data >> 1); ++ } ++ return reversed; ++} ++ ++/* This Initializes the partial CRC look up table */ ++static void hieth_init_crc_table(void) ++{ ++ unsigned short remainder; ++ int dividend; ++ unsigned char bit; ++ ++ /* Compute the remainder of each possible dividend. */ ++ for (dividend = 0; dividend < 256; ++dividend) { ++ /* Start with the dividend followed by zeros. */ ++ remainder = (unsigned short)(dividend << (WIDTH - 8)); ++ ++ /* Perform modulo-2 division, a bit at a time. */ ++ for (bit = 8; bit > 0; --bit) { ++ /* Try to divide the current data bit. */ ++ if (remainder & TOPBIT) ++ remainder = (remainder << 1) ^ POLYNOMIAL; ++ else ++ remainder = (remainder << 1); ++ } ++ ++ /* Store the result into the table. */ ++ crctable[dividend] = remainder; ++ } ++} ++ ++static unsigned short hieth_compute_crc(char *message, int n_bytes) ++{ ++ unsigned short remainder = INITIAL_REMAINDER; ++ int byte; ++ unsigned char data; ++ ++ /* Divide the message by the polynomial, a byte at a time. */ ++ for (byte = 0; byte < n_bytes; ++byte) { ++ data = REVERSE_DATA(message[byte]) ^ (remainder >> (WIDTH - 8)); ++ remainder = crctable[data] ^ (remainder << 8); ++ } ++ ++ /* The final remainder is the CRC. */ ++ return (REVERSE_REMAINDER(remainder) ^ FINAL_XOR_VALUE); ++} +diff --git a/drivers/net/ethernet/hisilicon/hieth/proc.c b/drivers/net/ethernet/hisilicon/hieth/proc.c +new file mode 100644 +index 0000000..54eea7b +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hieth/proc.c +@@ -0,0 +1,89 @@ ++#include ++ ++#include "hieth.h" ++#include "proc.h" ++ ++static int hieth_tx_info_read(struct seq_file *m, void *v) ++{ ++#ifdef HIETH_TSO_DEBUG ++ { ++ int i; ++ int id_now; ++ ++ if (id_send == 0) ++ id_now = MAX_RECORD-1; ++ else ++ id_now = id_send-1; ++ ++ for (i = id_now; i >= 0; i--) { ++ seq_printf(m, "%x,%x,%x\n", ++ pkt_rec[i].reg_addr, ++ pkt_rec[i].reg_pkt_info, ++ pkt_rec[i].status); ++ } ++ for (i = MAX_RECORD-1; i > id_now; i--) { ++ seq_printf(m, "%x,%x,%x\n", ++ pkt_rec[i].reg_addr, ++ pkt_rec[i].reg_pkt_info, ++ pkt_rec[i].status); ++ } ++ } ++#endif ++ return 0; ++} ++ ++static struct proc_dir_entry *hieth_proc_root; ++ ++#define proc_open(name) \ ++static int proc_open_##name(struct inode *inode, struct file *file) \ ++{ \ ++ return single_open(file, name, PDE_DATA(inode)); \ ++} \ ++ ++proc_open(hieth_tx_info_read); ++ ++static struct proc_file { ++ char *name; ++ const struct file_operations ops; ++} proc_file[] = { ++ { ++ .name = "tx_info", ++ .ops = { ++ .open = proc_open_hieth_tx_info_read, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ }, ++ }, ++}; ++ ++/* /proc/hieth/ ++ * |---tx_info ++ */ ++void hieth_proc_create(void) ++{ ++ int i; ++ ++ hieth_proc_root = proc_mkdir("hieth", NULL); ++ if (!hieth_proc_root) ++ return; ++ ++ for (i = 0; i < ARRAY_SIZE(proc_file); i++) { ++ struct proc_dir_entry *entry; ++ ++ entry = proc_create(proc_file[i].name, 0, hieth_proc_root, ++ &proc_file[i].ops); ++ if (!entry) ++ pr_err("failed to create %s\n", proc_file[i].name); ++ } ++} ++ ++void hieth_proc_destroy(void) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(proc_file); i++) ++ remove_proc_entry(proc_file[i].name, hieth_proc_root); ++ ++ remove_proc_entry("hieth", NULL); ++} +diff --git a/drivers/net/ethernet/hisilicon/hieth/proc.h b/drivers/net/ethernet/hisilicon/hieth/proc.h +new file mode 100644 +index 0000000..20cc8d4 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hieth/proc.h +@@ -0,0 +1,7 @@ ++#ifndef __HIETH_PROC_H ++#define __HIETH_PROC_H ++ ++void hieth_proc_create(void); ++void hieth_proc_destroy(void); ++ ++#endif +diff --git a/drivers/net/ethernet/hisilicon/hieth/tso.h b/drivers/net/ethernet/hisilicon/hieth/tso.h +new file mode 100644 +index 0000000..9929869 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hieth/tso.h +@@ -0,0 +1,76 @@ ++#ifndef __HIETH_TSO_H ++#define __HIETH_TSO_H ++ ++#define TSO_FLAG (1 << 31) ++#define VLAN_FLAG (1 << 30) ++#define IPV6_FLAG (1 << 29) ++#define UDP_FLAG (1 << 28) ++#define TX_CSUM_FLAG (1 << 27) ++#define SG_FLAG (1 << 26) ++ ++#define PKT_IPV6_HDR_LEN (10) ++#define PKT_UDP_HDR_LEN (2) ++#define WORD_TO_BYTE (4) ++ ++enum { ++ PKT_NORMAL, ++ PKT_SG ++}; ++ ++enum { ++ PKT_IPV4, ++ PKT_IPV6 ++}; ++ ++enum { ++ PKT_TCP, ++ PKT_UDP ++}; ++ ++struct frags_info { ++ /* Word(2*i+2) */ ++ u32 addr; ++ /* Word(2*i+3) */ ++ u32 size:16; ++ u32 reserved:16; ++}; ++ ++struct dma_tx_desc { ++ /* Word0 */ ++ u32 total_len:17; ++ u32 reserv:15; ++ /* Word1 */ ++ u32 ipv6_id; ++ /* Word2 */ ++ u32 linear_addr; ++ /* Word3 */ ++ u32 linear_len:16; ++ u32 reserv3:16; ++ /* MAX_SKB_FRAGS = 17 */ ++ struct frags_info frags[30]; ++ /* struct frags_info frags[MAX_SKB_FRAGS]; */ ++}; ++ ++struct tx_pkt_info { ++ union { ++ struct { ++ u32 data_len:11; ++ u32 nfrags_num:5; ++ u32 prot_hdr_len:4; ++ u32 ip_hdr_len:4; ++ u32 reserved:2; ++ u32 sg_flag:1; ++ u32 coe_flag:1; ++ u32 prot_type:1; ++ u32 ip_ver:1; ++ u32 vlan_flag:1; ++ u32 tso_flag:1; ++ } info; ++ u32 val; ++ } tx; ++ u32 tx_addr; /* normal pkt, skb->data */ ++ u32 sg_desc_offset; /* TSO pkt, desc addr */ ++ struct sk_buff *skb; ++}; ++ ++#endif +diff --git a/drivers/net/ethernet/hisilicon/higmac/Kconfig b/drivers/net/ethernet/hisilicon/higmac/Kconfig +new file mode 100644 +index 0000000..bda6f74 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/Kconfig +@@ -0,0 +1,96 @@ ++# ++# higmac family network device configuration ++# ++ ++menuconfig HIETH_GMAC ++ tristate "hieth gmac family network device support" ++ select PHYLIB ++ select RESET_CONTROLLER ++ help ++ This selects the hieth gmac family network device. ++ The gigabit switch fabric (GSF) receives and transmits data over Ethernet ++ ports at 10/100/1000 Mbit/s in full-duplex or half-duplex mode. ++ The Ethernet port exchanges data with the CPU port, and supports ++ the energy efficient Ethernet (EEE) and wake on LAN (WoL) functions. ++ ++if HIETH_GMAC ++ ++config HIGMAC_DESC_4WORD ++ bool "higmac descriptor size is 4 words" ++ default y ++ help ++ This define the size of higmac descriptor structure. ++ In the newest version, descriptor size is 4 words. ++ But in some old version, the size is 8 words. ++ The default value is true. ++ ++config HIGMAC_RXCSUM ++ bool "higmac Receive checksumming offload supported" ++ default y ++ help ++ This indicate MAC support Receive checksumming offload. ++ Support IPv4 and IPv6, tcp and udp. ++ The default value is enabled. ++ If old version MAC does not support, disable this option please. ++ ++config RX_FLOW_CTRL_SUPPORT ++ bool "rx flow ctrl supported" ++ default y ++ help ++ Rx flow ctrl supported, default is enabled. ++ When we received pause frame, ++ we will stop transmiting data frame for some time. ++ The stopping time is the time filled in pause frame. ++ ++config TX_FLOW_CTRL_SUPPORT ++ bool "tx flow ctrl supported" ++ default y ++ help ++ Tx flow ctrl supported, default is enabled. ++ When we has no buffer to receive packet, ++ we will send pause frame. ++ When buffer is available, we will send zero-quanta pause frame. ++ ++config TX_FLOW_CTRL_PAUSE_TIME ++ hex "tx flow ctrl pause time" ++ default "0xFFFF" ++ help ++ The pause time filled in the sending pause frame. ++ The unit is the time for transmiting 512 bit data. ++ This value is 16 bit, so its value is 0x0000~0xFFFF. ++ The default value is 0xFFFF. ++ ++config TX_FLOW_CTRL_PAUSE_INTERVAL ++ hex "tx flow ctrl pause interval" ++ default "0xFFFF" ++ help ++ The interval time for sending pause frame. ++ When the remainint amount of receive queue is below tx flow ctrl active threshold, ++ we will wait this time to transmiting pause frame. ++ The unit is the time for transmiting 512 bit data. ++ This value is 16 bit, so its value is 0x0000~0xFFFF. ++ The default value is 0xFFFF. ++ ++config TX_FLOW_CTRL_ACTIVE_THRESHOLD ++ int "tx flow ctrl active threshold" ++ default "16" ++ range 1 127 ++ help ++ The threshold for activing tx flow ctrl. ++ When the left amount of receive queue descriptors is below this threshold, ++ hardware will send pause frame immediately. ++ We advise this value is set smaller than 64. Too bigger is not a good choice. ++ This value must be smaller than tx flow ctrl deactive threshold. ++ ++config TX_FLOW_CTRL_DEACTIVE_THRESHOLD ++ int "tx flow ctrl deactive threshold" ++ default "32" ++ range 1 127 ++ help ++ The threshold for deactiving tx flow ctrl. ++ When the left amount of receive queue descriptors is above or equal with this threshold, ++ hardware will exit flow control state. ++ We advise this value is set smaller than 64. Too bigger is not a good choice. ++ This value must be larger than tx flow ctrl active threshold. ++ ++endif # HIETH_GMAC +diff --git a/drivers/net/ethernet/hisilicon/higmac/Makefile b/drivers/net/ethernet/hisilicon/higmac/Makefile +new file mode 100644 +index 0000000..e3d9c53 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/Makefile +@@ -0,0 +1,2 @@ ++obj-$(CONFIG_HIETH_GMAC) += hieth-gmac.o ++hieth-gmac-objs := board.o higmac.o autoeee/autoeee.o autoeee/phy_id_table.o +diff --git a/drivers/net/ethernet/hisilicon/higmac/autoeee/autoeee.c b/drivers/net/ethernet/hisilicon/higmac/autoeee/autoeee.c +new file mode 100644 +index 0000000..be12244 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/autoeee/autoeee.c +@@ -0,0 +1,125 @@ ++#include ++#include ++#include "../higmac.h" ++#include "autoeee.h" ++ ++void init_autoeee(struct higmac_netdev_local *ld) ++{ ++ int phy_id = ld->phy->phy_id; ++ struct phy_info *phy_info; ++ ++ if (ld->eee_init) ++ goto eee_init; ++ ++ phy_info = phy_search_ids(phy_id); ++ if (phy_info) { ++ int eee_available, lp_eee_capable, v; ++ u32 link_stat = 0; ++ ++ eee_available = phy_info->eee_available; ++ if (netif_msg_wol(ld)) ++ pr_info("fit phy_id:0x%x, phy_name:%s, eee:%d\n", ++ phy_info->phy_id, phy_info->name, ++ eee_available); ++ ++ if (!eee_available) ++ goto not_support; ++ ++ if (eee_available == PHY_EEE) { ++ if (netif_msg_wol(ld)) ++ pr_info("enter phy-EEE mode\n"); ++ ++ v = readl(ld->gmac_iobase + EEE_ENABLE); ++ v &= ~BIT_EEE_ENABLE; /* disable auto-EEE */ ++ writel(v, ld->gmac_iobase + EEE_ENABLE); ++ return; ++ } ++ ++ ld->eee_init = phy_info->eee_init; ++eee_init: ++ switch (ld->phy->speed) { ++ case SPEED_10: ++ link_stat |= HIGMAC_SPD_10M; ++ break; ++ case SPEED_100: ++ link_stat |= HIGMAC_SPD_100M; ++ break; ++ case SPEED_1000: ++ link_stat |= HIGMAC_SPD_1000M; ++ break; ++ default: ++ break; ++ } ++ ++ lp_eee_capable = ld->eee_init(ld->phy); ++ if (lp_eee_capable < 0) ++ return; ++ ++ if (ld->phy->link) { ++ if (((u32)lp_eee_capable) & link_stat) { ++ if ((phy_id & REALTEK_PHY_MASK) == ++ REALTEK_PHY_ID_8211E) { ++ v = readl(ld->gmac_iobase + EEE_CLK); ++ v &= ~MASK_EEE_CLK; ++ v |= BIT_DISABLE_TX_CLK; ++ writel(v, ld->gmac_iobase + EEE_CLK); ++ } else if ((phy_id & MICREL_PHY_ID_MASK) == ++ PHY_ID_KSZ9031) { ++ v = readl(ld->gmac_iobase + EEE_CLK); ++ v &= ~MASK_EEE_CLK; ++ v |= (BIT_DISABLE_TX_CLK | ++ BIT_PHY_KSZ9031); ++ writel(v, ld->gmac_iobase + EEE_CLK); ++ } ++ ++ /* EEE_1us: 0x7c for 125M */ ++ writel(0x7c, ld->gmac_iobase + ++ EEE_TIME_CLK_CNT); ++ writel(0x1e0400, ld->gmac_iobase + ++ EEE_TIMER);/* FIXME */ ++ ++ v = readl(ld->gmac_iobase + EEE_LINK_STATUS); ++ v |= 0x3 << 1; /* auto EEE and ... */ ++ v |= BIT_PHY_LINK_STATUS; /* phy linkup */ ++ writel(v, ld->gmac_iobase + EEE_LINK_STATUS); ++ ++ v = readl(ld->gmac_iobase + EEE_ENABLE); ++ v |= BIT_EEE_ENABLE; /* enable EEE */ ++ writel(v, ld->gmac_iobase + EEE_ENABLE); ++ ++ if (netif_msg_wol(ld)) ++ pr_info("enter auto-EEE mode\n"); ++ } else { ++ if (netif_msg_wol(ld)) ++ pr_info("link partner not support EEE\n"); ++ } ++ } else { ++ v = readl(ld->gmac_iobase + EEE_LINK_STATUS); ++ v &= ~(BIT_PHY_LINK_STATUS); /* phy linkdown */ ++ writel(v, ld->gmac_iobase + EEE_LINK_STATUS); ++ } ++ ++ return; ++ } ++ ++not_support: ++ ld->eee_init = NULL; ++ if (netif_msg_wol(ld)) ++ pr_info("non-EEE mode\n"); ++} ++ ++void eee_phy_linkdown(struct higmac_netdev_local *ld) ++{ ++ int v = readl(ld->gmac_iobase + EEE_LINK_STATUS); ++ /* update phy link state */ ++ v &= ~BIT_PHY_LINK_STATUS; ++ writel(v, ld->gmac_iobase + EEE_LINK_STATUS); ++} ++ ++void eee_phy_linkup(struct higmac_netdev_local *ld) ++{ ++ int v = readl(ld->gmac_iobase + EEE_LINK_STATUS); ++ /* update phy link state */ ++ v |= BIT_PHY_LINK_STATUS; ++ writel(v, ld->gmac_iobase + EEE_LINK_STATUS); ++} +diff --git a/drivers/net/ethernet/hisilicon/higmac/autoeee/autoeee.h b/drivers/net/ethernet/hisilicon/higmac/autoeee/autoeee.h +new file mode 100644 +index 0000000..8f75a7a +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/autoeee/autoeee.h +@@ -0,0 +1,42 @@ ++#ifndef _AUTO_EEE_H ++ ++#define NO_EEE 0 ++#define MAC_EEE 1 ++#define PHY_EEE 2 ++#define PARTNER_EEE 2 ++ ++struct phy_info { ++ char *name; ++ int phy_id; ++ char eee_available; /* eee support by this phy */ ++ int (*eee_init)(struct phy_device *phy_dev); ++}; ++ ++/* GMAC register definition */ ++#define EEE_CLK 0x800 ++#define MASK_EEE_CLK (0x3 << 20) ++#define BIT_DISABLE_TX_CLK BIT(21) ++#define BIT_PHY_KSZ9031 BIT(20) ++#define EEE_ENABLE 0x808 ++#define BIT_EEE_ENABLE BIT(0) ++#define EEE_TIMER 0x80C ++#define EEE_LINK_STATUS 0x810 ++#define BIT_PHY_LINK_STATUS BIT(0) ++#define EEE_TIME_CLK_CNT 0x814 ++ ++/* ----------------------------phy register-------------------------------*/ ++/* MMD: MDIO Manageable Device */ ++#define MACR 0x0D ++#define MAADR 0x0E ++#define EEE_DEV 0x3 ++#define EEE_CAPABILITY 0x14 ++#define EEELPAR_DEV 0x7 ++#define EEELPAR 0x3D /* EEE link partner ability register */ ++#define EEE_ADVERTISE 0x3c ++#define LP_1000BASE_EEE BIT(2) ++#define LP_100BASE_EEE BIT(1) ++ ++struct phy_info *phy_search_ids(int phy_id); ++void init_autoeee(struct higmac_netdev_local *ld); ++ ++#endif +diff --git a/drivers/net/ethernet/hisilicon/higmac/autoeee/phy_id_table.c b/drivers/net/ethernet/hisilicon/higmac/autoeee/phy_id_table.c +new file mode 100644 +index 0000000..8ffaf2a +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/autoeee/phy_id_table.c +@@ -0,0 +1,177 @@ ++#include ++#include ++#include ++#include "../higmac.h" ++#include "autoeee.h" ++ ++struct phy_info phy_info_table[]; ++ ++struct phy_info *phy_search_ids(int phy_id) ++{ ++ int i; ++ struct phy_info *fit_info = NULL; ++ ++ for (i = 0; phy_info_table[i].name; i++) { ++ if (phy_id == phy_info_table[i].phy_id) ++ fit_info = &phy_info_table[i]; ++ } ++ ++ return fit_info; ++} ++ ++static inline int phy_mmd_read(struct phy_device *phy_dev, ++ u32 mmd_device, u32 regnum) ++{ ++ phy_write(phy_dev, MACR, mmd_device); /* function = 00 address */ ++ phy_write(phy_dev, MAADR, regnum); ++ phy_write(phy_dev, MACR, 0x4000 | mmd_device); /* function = 01 data */ ++ ++ return phy_read(phy_dev, MAADR); ++} ++ ++static inline int phy_mmd_write(struct phy_device *phy_dev, u32 mmd_device, ++ u32 regnum, u16 val) ++{ ++ phy_write(phy_dev, MACR, mmd_device); /* function = 00 address */ ++ phy_write(phy_dev, MAADR, regnum); ++ phy_write(phy_dev, MACR, 0x4000 | mmd_device); /* function = 01 data */ ++ ++ return phy_write(phy_dev, MAADR, val); ++} ++ ++static int smsc_lan8740_init(struct phy_device *phy_dev) ++{ ++ static int first_time; ++ int v, eee_type = 0; ++ ++ if (!first_time) { ++ /* Realtek LAN 8740 start to enable eee */ ++ int eee_lan; ++ ++ eee_lan = phy_read(phy_dev, 0x10); ++ if (eee_lan < 0) ++ return eee_lan; ++ eee_lan |= 0x4; ++ phy_write(phy_dev, 0x10, eee_lan); ++ eee_lan = phy_read(phy_dev, 0x10); ++ if (eee_lan < 0) ++ return eee_lan; ++ /* auto negotiate after enable eee */ ++ eee_lan = phy_read(phy_dev, 0x0); ++ if (eee_lan < 0) ++ return eee_lan; ++ eee_lan |= 0x200; ++ phy_write(phy_dev, 0x0, eee_lan); ++ first_time = 1; ++ } ++ ++ v = phy_mmd_read(phy_dev, EEELPAR_DEV, EEELPAR); ++ ++ if (v & LP_1000BASE_EEE) ++ eee_type |= HIGMAC_SPD_1000M; ++ if (v & LP_100BASE_EEE) ++ eee_type |= HIGMAC_SPD_100M; ++ ++ return eee_type; ++} ++ ++#define RTL8211EG_MAC 0 ++#if RTL8211EG_MAC ++static int rtl8211EG_mac_init(struct phy_device *phy_dev) ++{ ++ static int first_time; ++ /* Realtek 8211EG start reset to change eee to mac */ ++ int v, eee_type = 0; ++ ++ if (!first_time) { ++ int tmp = 0; ++ ++ phy_write(phy_dev, 0x1f, 0x0); ++ phy_write(phy_dev, MII_BMCR, BMCR_RESET); /* reset phy */ ++ do { /* wait phy restart over */ ++ udelay(1); ++ tmp = phy_read(phy_dev, MII_BMSR); ++ /* no need to wait AN finished */ ++ tmp &= (BMSR_ANEGCOMPLETE | BMSR_ANEGCAPABLE); ++ } while (!tmp); ++ ++ phy_write(phy_dev, 0x1f, 0x7); ++ phy_write(phy_dev, 0x1e, 0x20); ++ phy_write(phy_dev, 0x1b, 0xa03a); ++ phy_write(phy_dev, 0x1f, 0x0); ++ ++ first_time = 1; ++ } ++ ++ v = phy_mmd_read(phy_dev, EEELPAR_DEV, EEELPAR); ++ ++ if (v & LP_1000BASE_EEE) ++ eee_type |= HIGMAC_SPD_1000M; ++ if (v & LP_100BASE_EEE) ++ eee_type |= HIGMAC_SPD_100M; ++ ++ return eee_type; ++} ++#else ++static int rtl8211EG_init(struct phy_device *phy_dev) ++{ ++ int eee_type = 0, v; ++ ++ v = phy_mmd_read(phy_dev, EEELPAR_DEV, EEELPAR); ++ ++ if (v & LP_1000BASE_EEE) ++ eee_type |= HIGMAC_SPD_1000M; ++ if (v & LP_100BASE_EEE) ++ eee_type |= HIGMAC_SPD_100M; ++ ++ return eee_type; ++} ++#endif ++ ++static int festa_v200_init(struct phy_device *phy_dev) ++{ ++ static int first_time_init; ++ int v, eee_type = 0; ++ ++ if (!first_time_init) { ++ /* EEE_CAPABILITY register: support 100M-BaseT */ ++ v = phy_mmd_read(phy_dev, EEE_DEV, EEE_CAPABILITY); ++ phy_mmd_write(phy_dev, EEE_DEV, EEE_CAPABILITY, ++ ((u32)v) | BIT(1)); ++ ++ /* EEE_ADVERTISEMENT register: advertising 100M-BaseT */ ++ v = phy_mmd_read(phy_dev, EEELPAR_DEV, EEE_ADVERTISE); ++ phy_mmd_write(phy_dev, EEELPAR_DEV, EEE_ADVERTISE, ++ ((u32)v) | BIT(1)); ++ ++ v = phy_read(phy_dev, MII_BMCR); ++ if (v < 0) ++ return v; ++ v |= (BMCR_ANENABLE | BMCR_ANRESTART); ++ phy_write(phy_dev, MII_BMCR, v); /* auto-neg restart */ ++ ++ first_time_init = 1; ++ } ++ ++ v = phy_mmd_read(phy_dev, EEELPAR_DEV, EEELPAR); ++ ++ if (v & LP_1000BASE_EEE) ++ eee_type |= HIGMAC_SPD_1000M; ++ if (v & LP_100BASE_EEE) ++ eee_type |= HIGMAC_SPD_100M; ++ ++ return eee_type; ++} ++ ++struct phy_info phy_info_table[] = { ++ /* phy_name phy_id eee_available phy_driver */ ++/* SMSC */ ++ {"SMSC LAN8740", 0x0007c110, MAC_EEE, &smsc_lan8740_init}, ++/* Realtek */ ++#if RTL8211EG_MAC ++ {"Realtek 8211EG", 0x001cc915, MAC_EEE, &rtl8211EG_mac_init}, ++#else ++ {"Realtek 8211EG", 0x001cc915, PHY_EEE, &rtl8211EG_init}, ++#endif ++ {"Festa V200", HISILICON_PHY_ID_FESTAV200, MAC_EEE, &festa_v200_init}, ++}; +diff --git a/drivers/net/ethernet/hisilicon/higmac/board.c b/drivers/net/ethernet/hisilicon/higmac/board.c +new file mode 100644 +index 0000000..89b9d16 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/board.c +@@ -0,0 +1,96 @@ ++#include ++#include ++#include ++#include "higmac.h" ++ ++void higmac_mac_core_reset(struct higmac_netdev_local *priv) ++{ ++ /* undo reset */ ++ reset_control_deassert(priv->port_rst); ++ usleep_range(50, 60); ++ ++ /* soft reset mac port */ ++ reset_control_assert(priv->port_rst); ++ usleep_range(50, 60); ++ /* undo reset */ ++ reset_control_deassert(priv->port_rst); ++} ++ ++void higmac_hw_internal_phy_reset(struct higmac_netdev_local *priv) ++{ ++} ++ ++void higmac_hw_phy_reset(struct higmac_netdev_local *priv) ++{ ++ if (priv->internal_phy) ++ higmac_hw_internal_phy_reset(priv); ++ else ++ higmac_hw_external_phy_reset(priv); ++} ++ ++void higmac_hw_external_phy_reset(struct higmac_netdev_local *priv) ++{ ++ if (priv->phy_rst) { ++ /* write 0 to cancel reset */ ++ reset_control_deassert(priv->phy_rst); ++ msleep(50); ++ ++ /* HIFONE or 98cv200 use CRG register to reset phy */ ++ /* RST_BIT, write 0 to reset phy, write 1 to cancel reset */ ++ reset_control_assert(priv->phy_rst); ++ ++ /* delay some time to ensure reset ok, ++ * this depends on PHY hardware feature ++ */ ++ msleep(50); ++ ++ /* write 0 to cancel reset */ ++ reset_control_deassert(priv->phy_rst); ++ /* delay some time to ensure later MDIO access */ ++ msleep(50); ++ } ++} ++ ++void higmac_internal_phy_clk_disable(struct higmac_netdev_local *priv) ++{ ++} ++ ++void higmac_internal_phy_clk_enable(struct higmac_netdev_local *priv) ++{ ++} ++ ++void higmac_hw_all_clk_disable(struct higmac_netdev_local *priv) ++{ ++ /* If macif clock is enabled when suspend, we should ++ * disable it here. ++ * Because when resume, PHY will link up again and ++ * macif clock will be enabled too. If we don't disable ++ * macif clock in suspend, macif clock will be enabled twice. ++ */ ++ if (priv->netdev->flags & IFF_UP) ++ clk_disable_unprepare(priv->macif_clk); ++ ++ /* This is called in suspend, when net device is down, ++ * MAC clk is disabled. ++ * So we need to judge whether MAC clk is enabled, ++ * otherwise kernel will WARNING if clk disable twice. ++ */ ++ if (priv->netdev->flags & IFF_UP) ++ clk_disable_unprepare(priv->clk); ++ ++ if (priv->internal_phy) ++ higmac_internal_phy_clk_disable(priv); ++} ++ ++void higmac_hw_all_clk_enable(struct higmac_netdev_local *priv) ++{ ++ if (priv->internal_phy) ++ higmac_internal_phy_clk_enable(priv); ++ ++ if (priv->netdev->flags & IFF_UP) ++ clk_prepare_enable(priv->macif_clk); ++ ++ /* If net device is down when suspend, we should not enable MAC clk. */ ++ if (priv->netdev->flags & IFF_UP) ++ clk_prepare_enable(priv->clk); ++} +diff --git a/drivers/net/ethernet/hisilicon/higmac/higmac.c b/drivers/net/ethernet/hisilicon/higmac/higmac.c +new file mode 100644 +index 0000000..135788f +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/higmac.c +@@ -0,0 +1,3120 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "util.h" ++#include "higmac.h" ++#include "autoeee/autoeee.h" ++#include "sockioctl.h" ++ ++#define HAS_TSO_CAP(hw_cap) ((((hw_cap) >> 28) & 0x3) == VER_TSO) ++#define HAS_RXHASH_CAP(hw_cap) ((hw_cap) & BIT(30)) ++#define HAS_RSS_CAP(hw_cap) ((hw_cap) & BIT(31)) ++ ++#define RGMII_SPEED_1000 0x2c ++#define RGMII_SPEED_100 0x2f ++#define RGMII_SPEED_10 0x2d ++#define MII_SPEED_100 0x0f ++#define MII_SPEED_10 0x0d ++#define RMII_SPEED_100 0x8f ++#define RMII_SPEED_10 0x8d ++#define GMAC_FULL_DUPLEX BIT(4) ++ ++static unsigned int flow_ctrl_en = FLOW_OFF; ++static int tx_flow_ctrl_pause_time = CONFIG_TX_FLOW_CTRL_PAUSE_TIME; ++static int tx_flow_ctrl_pause_interval = CONFIG_TX_FLOW_CTRL_PAUSE_INTERVAL; ++static int tx_flow_ctrl_active_threshold = CONFIG_TX_FLOW_CTRL_ACTIVE_THRESHOLD; ++static int tx_flow_ctrl_deactive_threshold = ++ CONFIG_TX_FLOW_CTRL_DEACTIVE_THRESHOLD; ++ ++#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK) ++static int debug = -1; ++module_param(debug, int, 0000); ++MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); ++ ++static void higmac_config_port(struct net_device *dev, u32 speed, u32 duplex) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(dev); ++ u32 val; ++ ++ switch (priv->phy_mode) { ++ case PHY_INTERFACE_MODE_RGMII: ++ if (speed == SPEED_1000) ++ val = RGMII_SPEED_1000; ++ else if (speed == SPEED_100) ++ val = RGMII_SPEED_100; ++ else ++ val = RGMII_SPEED_10; ++ break; ++ case PHY_INTERFACE_MODE_MII: ++ if (speed == SPEED_100) ++ val = MII_SPEED_100; ++ else ++ val = MII_SPEED_10; ++ break; ++ case PHY_INTERFACE_MODE_RMII: ++ if (speed == SPEED_100) ++ val = RMII_SPEED_100; ++ else ++ val = RMII_SPEED_10; ++ break; ++ default: ++ netdev_warn(dev, "not supported mode\n"); ++ val = MII_SPEED_10; ++ break; ++ } ++ ++ if (duplex) ++ val |= GMAC_FULL_DUPLEX; ++ ++ reset_control_assert(priv->macif_rst); ++ writel_relaxed(val, priv->macif_base); ++ reset_control_deassert(priv->macif_rst); ++ ++ writel_relaxed(BIT_MODE_CHANGE_EN, priv->gmac_iobase + MODE_CHANGE_EN); ++ if (speed == SPEED_1000) ++ val = GMAC_SPEED_1000; ++ else if (speed == SPEED_100) ++ val = GMAC_SPEED_100; ++ else ++ val = GMAC_SPEED_10; ++ writel_relaxed(val, priv->gmac_iobase + PORT_MODE); ++ writel_relaxed(0, priv->gmac_iobase + MODE_CHANGE_EN); ++ writel_relaxed(duplex, priv->gmac_iobase + MAC_DUPLEX_HALF_CTRL); ++} ++ ++static void higmac_set_desc_depth(struct higmac_netdev_local *priv, ++ u32 rx, u32 tx) ++{ ++ u32 reg; ++ int i; ++ ++ writel(BITS_RX_FQ_DEPTH_EN, priv->gmac_iobase + RX_FQ_REG_EN); ++ writel(rx << DESC_WORD_SHIFT, priv->gmac_iobase + RX_FQ_DEPTH); ++ writel(0, priv->gmac_iobase + RX_FQ_REG_EN); ++ ++ writel(BITS_RX_BQ_DEPTH_EN, priv->gmac_iobase + RX_BQ_REG_EN); ++ writel(rx << DESC_WORD_SHIFT, priv->gmac_iobase + RX_BQ_DEPTH); ++ for (i = 1; i < priv->num_rxqs; i++) { ++ reg = RX_BQ_DEPTH_QUEUE(i); ++ writel(rx << DESC_WORD_SHIFT, priv->gmac_iobase + reg); ++ } ++ writel(0, priv->gmac_iobase + RX_BQ_REG_EN); ++ ++ writel(BITS_TX_BQ_DEPTH_EN, priv->gmac_iobase + TX_BQ_REG_EN); ++ writel(tx << DESC_WORD_SHIFT, priv->gmac_iobase + TX_BQ_DEPTH); ++ writel(0, priv->gmac_iobase + TX_BQ_REG_EN); ++ ++ writel(BITS_TX_RQ_DEPTH_EN, priv->gmac_iobase + TX_RQ_REG_EN); ++ writel(tx << DESC_WORD_SHIFT, priv->gmac_iobase + TX_RQ_DEPTH); ++ writel(0, priv->gmac_iobase + TX_RQ_REG_EN); ++} ++ ++static void higmac_set_rx_fq(struct higmac_netdev_local *priv, ++ dma_addr_t phy_addr) ++{ ++ writel(BITS_RX_FQ_START_ADDR_EN, priv->gmac_iobase + RX_FQ_REG_EN); ++ writel(phy_addr, priv->gmac_iobase + RX_FQ_START_ADDR); ++ writel(0, priv->gmac_iobase + RX_FQ_REG_EN); ++} ++ ++static void higmac_set_rx_bq(struct higmac_netdev_local *priv, ++ dma_addr_t phy_addr) ++{ ++ writel(BITS_RX_BQ_START_ADDR_EN, priv->gmac_iobase + RX_BQ_REG_EN); ++ writel(phy_addr, priv->gmac_iobase + RX_BQ_START_ADDR); ++ writel(0, priv->gmac_iobase + RX_BQ_REG_EN); ++} ++ ++static void higmac_set_tx_bq(struct higmac_netdev_local *priv, ++ dma_addr_t phy_addr) ++{ ++ writel(BITS_TX_BQ_START_ADDR_EN, priv->gmac_iobase + TX_BQ_REG_EN); ++ writel(phy_addr, priv->gmac_iobase + TX_BQ_START_ADDR); ++ writel(0, priv->gmac_iobase + TX_BQ_REG_EN); ++} ++ ++static void higmac_set_tx_rq(struct higmac_netdev_local *priv, ++ dma_addr_t phy_addr) ++{ ++ writel(BITS_TX_RQ_START_ADDR_EN, priv->gmac_iobase + TX_RQ_REG_EN); ++ writel(phy_addr, priv->gmac_iobase + TX_RQ_START_ADDR); ++ writel(0, priv->gmac_iobase + TX_RQ_REG_EN); ++} ++ ++static void higmac_hw_set_desc_addr(struct higmac_netdev_local *priv) ++{ ++ u32 reg; ++ int i; ++ ++ higmac_set_rx_fq(priv, priv->rx_fq.phys_addr); ++ higmac_set_rx_bq(priv, priv->rx_bq.phys_addr); ++ higmac_set_tx_rq(priv, priv->tx_rq.phys_addr); ++ higmac_set_tx_bq(priv, priv->tx_bq.phys_addr); ++ ++ for (i = 1; i < priv->num_rxqs; i++) { ++ reg = RX_BQ_START_ADDR_QUEUE(i); ++ writel(BITS_RX_BQ_START_ADDR_EN, ++ priv->gmac_iobase + RX_BQ_REG_EN); ++ writel(priv->pool[3 + i].phys_addr, priv->gmac_iobase + reg); ++ writel(0, priv->gmac_iobase + RX_BQ_REG_EN); ++ } ++} ++ ++static void higmac_set_rss_cap(struct higmac_netdev_local *priv) ++{ ++ u32 val = 0; ++ ++ if (priv->has_rxhash_cap) ++ val |= BIT_RXHASH_CAP; ++ if (priv->has_rss_cap) ++ val |= BIT_RSS_CAP; ++ writel(val, priv->gmac_iobase + HW_CAP_EN); ++} ++ ++static void higmac_hw_init(struct higmac_netdev_local *priv) ++{ ++ u32 val; ++ u32 reg; ++ int i; ++ ++#if defined(CONFIG_ARCH_HI3519) || defined(CONFIG_ARCH_HI3519V101) || \ ++ defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) || \ ++ defined(CONFIG_ARCH_HI3516AV200) ++ /* config AXI parameter for better performance. */ ++ val = readl(priv->gmac_iobase + BURST_OUTSTANDING_REG); ++ val >>= BURST_OUTSTANDING_OFFSET; ++ if (!val) ++ writel(BURST4_OUTSTANDING1, priv->gmac_iobase + ++ BURST_OUTSTANDING_REG); ++#elif (defined(CONFIG_ARCH_HI3531D)) ++ /* config AXI parameter for better performance. */ ++ writel(BURST4_OUTSTANDING1, priv->gmac_iobase + ++ BURST_OUTSTANDING_REG); ++#endif ++ ++ /* disable and clear all interrupts */ ++ writel(0, priv->gmac_iobase + ENA_PMU_INT); ++ writel(~0, priv->gmac_iobase + RAW_PMU_INT); ++ ++ for (i = 1; i < priv->num_rxqs; i++) { ++ reg = RSS_ENA_INT_QUEUE(i); ++ writel(0, priv->gmac_iobase + reg); ++ } ++ writel(~0, priv->gmac_iobase + RSS_RAW_PMU_INT); ++ ++ /* enable CRC erro packets filter */ ++ val = readl(priv->gmac_iobase + REC_FILT_CONTROL); ++ val |= BIT_CRC_ERR_PASS; ++ writel(val, priv->gmac_iobase + REC_FILT_CONTROL); ++ ++ /* set tx min packet length */ ++ val = readl(priv->gmac_iobase + CRF_MIN_PACKET); ++ val &= ~BIT_MASK_TX_MIN_LEN; ++ val |= ETH_HLEN << BIT_OFFSET_TX_MIN_LEN; ++ writel(val, priv->gmac_iobase + CRF_MIN_PACKET); ++ ++ /* fix bug for udp and ip error check */ ++ writel(CONTROL_WORD_CONFIG, priv->gmac_iobase + CONTROL_WORD); ++ ++ writel(0, priv->gmac_iobase + COL_SLOT_TIME); ++ ++ writel(DUPLEX_HALF, priv->gmac_iobase + MAC_DUPLEX_HALF_CTRL); ++ ++ /* FIXME: interrupt when rcv packets >= RX_BQ_INT_THRESHOLD */ ++ val = RX_BQ_INT_THRESHOLD | ++ (TX_RQ_INT_THRESHOLD << BITS_OFFSET_TX_RQ_IN_TH); ++ writel(val, priv->gmac_iobase + IN_QUEUE_TH); ++ ++ /* FIXME: rx_bq/tx_rq in timeout threshold */ ++ writel(0x10000, priv->gmac_iobase + RX_BQ_IN_TIMEOUT_TH); ++ ++ writel(0x18000, priv->gmac_iobase + TX_RQ_IN_TIMEOUT_TH); ++ ++ higmac_set_desc_depth(priv, RX_DESC_NUM, TX_DESC_NUM); ++} ++ ++static inline void higmac_irq_enable(struct higmac_netdev_local *ld) ++{ ++ writel(RX_BQ_IN_INT | RX_BQ_IN_TIMEOUT_INT ++ | TX_RQ_IN_INT | TX_RQ_IN_TIMEOUT_INT, ++ ld->gmac_iobase + ENA_PMU_INT); ++} ++ ++static inline void higmac_irq_enable_queue(struct higmac_netdev_local *ld, ++ int rxq_id) ++{ ++ if (rxq_id) { ++ u32 reg; ++ ++ reg = RSS_ENA_INT_QUEUE(rxq_id); ++ writel(~0, ld->gmac_iobase + reg); ++ } else { ++ higmac_irq_enable(ld); ++ } ++} ++ ++static inline void higmac_irq_enable_all_queue(struct higmac_netdev_local *ld) ++{ ++ int i; ++ ++ for (i = 0; i < ld->num_rxqs; i++) ++ higmac_irq_enable_queue(ld, i); ++} ++ ++static inline void higmac_irq_disable(struct higmac_netdev_local *ld) ++{ ++ writel(0, ld->gmac_iobase + ENA_PMU_INT); ++} ++ ++static inline void higmac_irq_disable_queue(struct higmac_netdev_local *ld, ++ int rxq_id) ++{ ++ if (rxq_id) { ++ u32 reg; ++ ++ reg = RSS_ENA_INT_QUEUE(rxq_id); ++ writel(0, ld->gmac_iobase + reg); ++ } else { ++ higmac_irq_disable(ld); ++ } ++} ++ ++static inline void higmac_irq_disable_all_queue(struct higmac_netdev_local *ld) ++{ ++ int i; ++ ++ for (i = 0; i < ld->num_rxqs; i++) ++ higmac_irq_disable_queue(ld, i); ++} ++ ++static inline bool higmac_queue_irq_disabled(struct higmac_netdev_local *ld, ++ int rxq_id) ++{ ++ u32 reg, val; ++ ++ if (rxq_id) ++ reg = RSS_ENA_INT_QUEUE(rxq_id); ++ else ++ reg = ENA_PMU_INT; ++ val = readl(ld->gmac_iobase + reg); ++ ++ return !val; ++} ++ ++static inline void higmac_hw_desc_enable(struct higmac_netdev_local *ld) ++{ ++ writel(0xF, ld->gmac_iobase + DESC_WR_RD_ENA); ++} ++ ++static inline void higmac_hw_desc_disable(struct higmac_netdev_local *ld) ++{ ++ writel(0, ld->gmac_iobase + DESC_WR_RD_ENA); ++} ++ ++static inline void higmac_port_enable(struct higmac_netdev_local *ld) ++{ ++ writel(BITS_TX_EN | BITS_RX_EN, ld->gmac_iobase + PORT_EN); ++} ++ ++static inline void higmac_port_disable(struct higmac_netdev_local *ld) ++{ ++ writel(0, ld->gmac_iobase + PORT_EN); ++} ++ ++void higmac_set_flow_ctrl_params(struct higmac_netdev_local *ld) ++{ ++ unsigned int rx_fq_empty_th; ++ unsigned int rx_fq_full_th; ++ unsigned int rx_bq_empty_th; ++ unsigned int rx_bq_full_th; ++ unsigned int rec_filter; ++ ++ writel(ld->pause, ld->gmac_iobase + FC_TX_TIMER); ++ writel(ld->pause_interval, ld->gmac_iobase + PAUSE_THR); ++ ++ rx_fq_empty_th = readl(ld->gmac_iobase + RX_FQ_ALEMPTY_TH); ++ rx_fq_empty_th &= ~(BITS_Q_PAUSE_TH_MASK << BITS_Q_PAUSE_TH_OFFSET); ++ rx_fq_empty_th |= (ld->flow_ctrl_active_threshold << ++ BITS_Q_PAUSE_TH_OFFSET); ++ writel(rx_fq_empty_th, ld->gmac_iobase + RX_FQ_ALEMPTY_TH); ++ ++ rx_fq_full_th = readl(ld->gmac_iobase + RX_FQ_ALFULL_TH); ++ rx_fq_full_th &= ~(BITS_Q_PAUSE_TH_MASK << BITS_Q_PAUSE_TH_OFFSET); ++ rx_fq_full_th |= (ld->flow_ctrl_deactive_threshold << ++ BITS_Q_PAUSE_TH_OFFSET); ++ writel(rx_fq_full_th, ld->gmac_iobase + RX_FQ_ALFULL_TH); ++ ++ rx_bq_empty_th = readl(ld->gmac_iobase + RX_BQ_ALEMPTY_TH); ++ rx_bq_empty_th &= ~(BITS_Q_PAUSE_TH_MASK << BITS_Q_PAUSE_TH_OFFSET); ++ rx_bq_empty_th |= (ld->flow_ctrl_active_threshold << ++ BITS_Q_PAUSE_TH_OFFSET); ++ writel(rx_bq_empty_th, ld->gmac_iobase + RX_BQ_ALEMPTY_TH); ++ ++ rx_bq_full_th = readl(ld->gmac_iobase + RX_BQ_ALFULL_TH); ++ rx_bq_full_th &= ~(BITS_Q_PAUSE_TH_MASK << BITS_Q_PAUSE_TH_OFFSET); ++ rx_bq_full_th |= (ld->flow_ctrl_deactive_threshold << ++ BITS_Q_PAUSE_TH_OFFSET); ++ writel(rx_bq_full_th, ld->gmac_iobase + RX_BQ_ALFULL_TH); ++ ++ writel(0, ld->gmac_iobase + CRF_TX_PAUSE); ++ ++ rec_filter = readl(ld->gmac_iobase + REC_FILT_CONTROL); ++ rec_filter |= BIT_PAUSE_FRM_PASS; ++ writel(rec_filter, ld->gmac_iobase + REC_FILT_CONTROL); ++} ++ ++void higmac_set_flow_ctrl_state(struct higmac_netdev_local *ld, int pause) ++{ ++ unsigned int flow_rx_q_en; ++ unsigned int flow; ++ ++ flow_rx_q_en = readl(ld->gmac_iobase + RX_PAUSE_EN); ++ flow_rx_q_en &= ~(BIT_RX_FQ_PAUSE_EN | BIT_RX_BQ_PAUSE_EN); ++ if (pause && (ld->flow_ctrl & FLOW_TX)) ++ flow_rx_q_en |= (BIT_RX_FQ_PAUSE_EN | BIT_RX_BQ_PAUSE_EN); ++ writel(flow_rx_q_en, ld->gmac_iobase + RX_PAUSE_EN); ++ ++ flow = readl(ld->gmac_iobase + PAUSE_EN); ++ flow &= ~(BIT_RX_FDFC | BIT_TX_FDFC); ++ if (pause) { ++ if (ld->flow_ctrl & FLOW_RX) ++ flow |= BIT_RX_FDFC; ++ if (ld->flow_ctrl & FLOW_TX) ++ flow |= BIT_TX_FDFC; ++ } ++ writel(flow, ld->gmac_iobase + PAUSE_EN); ++} ++ ++static void higmac_set_flow_ctrl_args(struct higmac_netdev_local *ld) ++{ ++ ld->flow_ctrl = flow_ctrl_en; ++ ld->pause = tx_flow_ctrl_pause_time; ++ ld->pause_interval = tx_flow_ctrl_pause_interval; ++ ld->flow_ctrl_active_threshold = tx_flow_ctrl_active_threshold; ++ ld->flow_ctrl_deactive_threshold = tx_flow_ctrl_deactive_threshold; ++} ++ ++/* set gmac's multicast list, here we setup gmac's mc filter */ ++static void higmac_gmac_multicast_list(struct net_device *dev) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(dev); ++ unsigned int rec_filter; ++ ++ rec_filter = readl(ld->gmac_iobase + REC_FILT_CONTROL); ++ /* when set gmac in promisc mode ++ * a. dev in IFF_PROMISC mode ++ */ ++ if ((dev->flags & IFF_PROMISC)) { ++ /* promisc mode.received all pkgs. */ ++ rec_filter &= ~(BIT_BC_DROP_EN | BIT_MC_MATCH_EN | ++ BIT_UC_MATCH_EN); ++ } else { ++ /* drop uc pkgs with field 'DA' not match our's */ ++ rec_filter |= BIT_UC_MATCH_EN; ++ ++ if (dev->flags & IFF_BROADCAST) /* no broadcast */ ++ rec_filter &= ~BIT_BC_DROP_EN; ++ else ++ rec_filter |= BIT_BC_DROP_EN; ++ ++ if (netdev_mc_empty(dev) || !(dev->flags & IFF_MULTICAST)) { ++ /* haven't join any mc group */ ++ writel(0, ld->gmac_iobase + PORT_MC_ADDR_LOW); ++ writel(0, ld->gmac_iobase + PORT_MC_ADDR_HIGH); ++ rec_filter |= BIT_MC_MATCH_EN; ++ } else if (netdev_mc_count(dev) == 1 && ++ (dev->flags & IFF_MULTICAST)) { ++ struct netdev_hw_addr *ha; ++ unsigned int d = 0; ++ ++ netdev_for_each_mc_addr(ha, dev) { ++ d = (ha->addr[0] << 8) | (ha->addr[1]); ++ writel(d, ld->gmac_iobase + PORT_MC_ADDR_HIGH); ++ ++ d = (ha->addr[2] << 24) | (ha->addr[3] << 16) ++ | (ha->addr[4] << 8) | (ha->addr[5]); ++ writel(d, ld->gmac_iobase + PORT_MC_ADDR_LOW); ++ } ++ rec_filter |= BIT_MC_MATCH_EN; ++ } else { ++ rec_filter &= ~BIT_MC_MATCH_EN; ++ } ++ } ++ writel(rec_filter, ld->gmac_iobase + REC_FILT_CONTROL); ++} ++ ++/* the func stop the hw desc and relaim the software skb resource ++ * before reusing the gmac, you'd better reset the gmac ++ */ ++void higmac_reclaim_rx_tx_resource(struct higmac_netdev_local *ld) ++{ ++ unsigned long rxflags, txflags; ++ int rd_offset, wr_offset; ++ int i; ++ ++ higmac_irq_disable_all_queue(ld); ++ higmac_hw_desc_disable(ld); ++ writel(STOP_RX_TX, ld->gmac_iobase + STOP_CMD); ++ ++ spin_lock_irqsave(&ld->rxlock, rxflags); ++ /* rx_bq: logic write pointer */ ++ wr_offset = readl(ld->gmac_iobase + RX_BQ_WR_ADDR); ++ /* rx_bq: software read pointer */ ++ rd_offset = readl(ld->gmac_iobase + RX_BQ_RD_ADDR); ++ /* FIXME: prevent to reclaim skb in rx bottom half */ ++ writel(wr_offset, ld->gmac_iobase + RX_BQ_RD_ADDR); ++ ++ for (i = 1; i < ld->num_rxqs; i++) { ++ u32 rx_bq_wr_reg, rx_bq_rd_reg; ++ ++ rx_bq_wr_reg = RX_BQ_WR_ADDR_QUEUE(i); ++ rx_bq_rd_reg = RX_BQ_RD_ADDR_QUEUE(i); ++ ++ wr_offset = readl(ld->gmac_iobase + rx_bq_wr_reg); ++ writel(wr_offset, ld->gmac_iobase + rx_bq_rd_reg); ++ } ++ ++ /* rx_fq: software write pointer */ ++ wr_offset = readl(ld->gmac_iobase + RX_FQ_WR_ADDR); ++ /* rx_fq: logic read pointer */ ++ rd_offset = readl(ld->gmac_iobase + RX_FQ_RD_ADDR); ++ if (!rd_offset) ++ rd_offset = (RX_DESC_NUM - 1) << DESC_BYTE_SHIFT; ++ else ++ rd_offset -= DESC_SIZE; ++ /* FIXME: stop to feed hw desc */ ++ writel(rd_offset, ld->gmac_iobase + RX_FQ_WR_ADDR); ++ ++ for (i = 0; i < ld->rx_fq.count; i++) { ++ if (!ld->rx_fq.skb[i]) ++ ld->rx_fq.skb[i] = SKB_MAGIC; ++ } ++ spin_unlock_irqrestore(&ld->rxlock, rxflags); ++ ++ /* no need to wait pkts in tx_rq finish to free all skb, ++ * because higmac_xmit_reclaim is in the tx_lock, ++ */ ++ spin_lock_irqsave(&ld->txlock, txflags); ++ /* tx_rq: logic write */ ++ wr_offset = readl(ld->gmac_iobase + TX_RQ_WR_ADDR); ++ /* tx_rq: software read */ ++ rd_offset = readl(ld->gmac_iobase + TX_RQ_RD_ADDR); ++ /* FIXME: stop to reclaim tx skb */ ++ writel(wr_offset, ld->gmac_iobase + TX_RQ_RD_ADDR); ++ ++ /* tx_bq: logic read */ ++ rd_offset = readl(ld->gmac_iobase + TX_BQ_RD_ADDR); ++ if (!rd_offset) ++ rd_offset = (TX_DESC_NUM - 1) << DESC_BYTE_SHIFT; ++ else ++ rd_offset -= DESC_SIZE; ++ /* FIXME: stop software tx skb */ ++ writel(rd_offset, ld->gmac_iobase + TX_BQ_WR_ADDR); ++ ++ for (i = 0; i < ld->tx_bq.count; i++) { ++ if (!ld->tx_bq.skb[i]) ++ ld->tx_bq.skb[i] = SKB_MAGIC; ++ } ++ spin_unlock_irqrestore(&ld->txlock, txflags); ++} ++ ++static void higmac_monitor_func(unsigned long arg); ++static void higmac_set_multicast_list(struct net_device *dev); ++ ++static void higmac_hw_set_mac_addr(struct net_device *dev) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(dev); ++ unsigned char *mac = dev->dev_addr; ++ u32 val; ++ ++ val = mac[1] | (mac[0] << 8); ++ writel(val, priv->gmac_iobase + STATION_ADDR_HIGH); ++ ++ val = mac[5] | (mac[4] << 8) | (mac[3] << 16) | (mac[2] << 24); ++ writel(val, priv->gmac_iobase + STATION_ADDR_LOW); ++} ++ ++static u32 higmac_rx_refill(struct higmac_netdev_local *priv); ++ ++static void higmac_free_rx_skb(struct higmac_netdev_local *ld) ++{ ++ struct sk_buff *skb = NULL; ++ int i; ++ ++ for (i = 0; i < ld->rx_fq.count; i++) { ++ skb = ld->rx_fq.skb[i]; ++ if (skb) { ++ ld->rx_skb[i] = NULL; ++ ld->rx_fq.skb[i] = NULL; ++ if (skb == SKB_MAGIC) ++ continue; ++ dev_kfree_skb_any(skb); ++ /* TODO: need to unmap the skb here ++ * but there is no way to get the dma_addr here, ++ * and unmap(TO_DEVICE) ops do nothing in fact, ++ * so we ignore to call ++ * dma_unmap_single(dev, dma_addr, skb->len, ++ * DMA_TO_DEVICE) ++ */ ++ } ++ } ++} ++ ++static void higmac_free_tx_skb(struct higmac_netdev_local *ld) ++{ ++ struct sk_buff *skb = NULL; ++ int i; ++ ++ for (i = 0; i < ld->tx_bq.count; i++) { ++ skb = ld->tx_bq.skb[i]; ++ if (skb) { ++ ld->tx_skb[i] = NULL; ++ ld->tx_bq.skb[i] = NULL; ++ if (skb == SKB_MAGIC) ++ continue; ++ dev_kfree_skb_any(skb); ++ /* TODO: unmap the skb */ ++ } ++ } ++} ++ ++/* reset and re-config gmac */ ++void higmac_restart(struct higmac_netdev_local *ld) ++{ ++ unsigned long rxflags, txflags; ++ ++ /* restart hw engine now */ ++ higmac_mac_core_reset(ld); ++ ++ spin_lock_irqsave(&ld->rxlock, rxflags); ++ spin_lock_irqsave(&ld->txlock, txflags); ++ ++ higmac_free_rx_skb(ld); ++ higmac_free_tx_skb(ld); ++ ++ pmt_reg_restore(ld); ++ higmac_hw_init(ld); ++ higmac_hw_set_mac_addr(ld->netdev); ++ higmac_hw_set_desc_addr(ld); ++ ++ /* we don't set macif here, it will be set in adjust_link */ ++ if (ld->netdev->flags & IFF_UP) { ++ /* when resume, only do the following operations ++ * when dev is up before suspend. ++ */ ++ higmac_rx_refill(ld); ++ higmac_set_multicast_list(ld->netdev); ++ ++ higmac_hw_desc_enable(ld); ++ higmac_port_enable(ld); ++ higmac_irq_enable_all_queue(ld); ++ } ++ spin_unlock_irqrestore(&ld->txlock, txflags); ++ spin_unlock_irqrestore(&ld->rxlock, rxflags); ++} ++ ++static int higmac_net_set_mac_address(struct net_device *dev, void *p) ++{ ++ int ret; ++ ++ ret = eth_mac_addr(dev, p); ++ if (!ret) ++ higmac_hw_set_mac_addr(dev); ++ ++ return ret; ++} ++ ++#define HIGMAC_LINK_CHANGE_PROTECT ++#define HIGMAC_MAC_TX_RESET_IN_LINKUP ++ ++#ifdef HIGMAC_LINK_CHANGE_PROTECT ++#define HIGMAC_MS_TO_NS (1000000ULL) ++#define HIGMAC_FLUSH_WAIT_TIME (100*HIGMAC_MS_TO_NS) ++/* protect code */ ++static void higmac_linkup_flush(struct higmac_netdev_local *ld) ++{ ++ int tx_bq_wr_offset, tx_bq_rd_offset; ++ unsigned long long time_limit, time_now; ++ ++ time_now = sched_clock(); ++ time_limit = time_now + HIGMAC_FLUSH_WAIT_TIME; ++ ++ do { ++ tx_bq_wr_offset = readl(ld->gmac_iobase + TX_BQ_WR_ADDR); ++ tx_bq_rd_offset = readl(ld->gmac_iobase + TX_BQ_RD_ADDR); ++ ++ time_now = sched_clock(); ++ if (unlikely((long long)time_now - ++ (long long)time_limit >= 0)) ++ break; ++ } while (tx_bq_rd_offset != tx_bq_wr_offset); ++ ++ mdelay(1); ++} ++#endif ++ ++#ifdef HIGMAC_MAC_TX_RESET_IN_LINKUP ++static void higmac_mac_tx_state_engine_reset(struct higmac_netdev_local *priv) ++{ ++ u32 val; ++ ++ val = readl(priv->gmac_iobase + MAC_CLEAR); ++ val |= BIT_TX_SOFT_RESET; ++ writel(val, priv->gmac_iobase + MAC_CLEAR); ++ ++ mdelay(5); ++ ++ val = readl(priv->gmac_iobase + MAC_CLEAR); ++ val &= ~BIT_TX_SOFT_RESET; ++ writel(val, priv->gmac_iobase + MAC_CLEAR); ++} ++#endif ++ ++static void higmac_adjust_link(struct net_device *dev) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(dev); ++ struct phy_device *phy = priv->phy; ++ bool link_status_changed = false; ++ ++ if (phy->link) { ++ if ((priv->old_speed != phy->speed) || ++ (priv->old_duplex != phy->duplex)) { ++#ifdef HIGMAC_LINK_CHANGE_PROTECT ++ unsigned long txflags; ++ ++ spin_lock_irqsave(&priv->txlock, txflags); ++ ++ higmac_linkup_flush(priv); ++#endif ++ higmac_config_port(dev, phy->speed, phy->duplex); ++#ifdef HIGMAC_MAC_TX_RESET_IN_LINKUP ++ higmac_mac_tx_state_engine_reset(priv); ++#endif ++#ifdef HIGMAC_LINK_CHANGE_PROTECT ++ spin_unlock_irqrestore(&priv->txlock, txflags); ++#endif ++ higmac_set_flow_ctrl_state(priv, phy->pause); ++ ++ if (priv->autoeee) ++ init_autoeee(priv); ++ ++ link_status_changed = true; ++ priv->old_link = 1; ++ priv->old_speed = phy->speed; ++ priv->old_duplex = phy->duplex; ++ } ++ } else if (priv->old_link) { ++ link_status_changed = true; ++ priv->old_link = 0; ++ priv->old_speed = SPEED_UNKNOWN; ++ priv->old_duplex = DUPLEX_UNKNOWN; ++ } ++ ++ if (link_status_changed && netif_msg_link(priv)) ++ phy_print_status(phy); ++} ++ ++int higmac_tx_avail(struct higmac_netdev_local *ld) ++{ ++ int tx_bq_wr_offset, tx_bq_rd_offset; ++ ++ tx_bq_wr_offset = readl(ld->gmac_iobase + TX_BQ_WR_ADDR); ++ tx_bq_rd_offset = readl(ld->gmac_iobase + TX_BQ_RD_ADDR); ++ ++ return (tx_bq_rd_offset >> DESC_BYTE_SHIFT) + TX_DESC_NUM ++ - (tx_bq_wr_offset >> DESC_BYTE_SHIFT) - 1; ++} ++ ++static int higmac_init_sg_desc_queue(struct higmac_netdev_local *ld) ++{ ++ ld->sg_count = ld->tx_bq.count + HIGMAC_SG_DESC_ADD; ++ if (HAS_CAP_CCI(ld->hw_cap)) { ++ ld->dma_sg_desc = kmalloc_array(ld->sg_count, ++ sizeof(struct sg_desc), ++ GFP_KERNEL); ++ if (ld->dma_sg_desc) ++ ld->dma_sg_phy = virt_to_phys(ld->dma_sg_desc); ++ } else { ++ ld->dma_sg_desc = (struct sg_desc *)dma_alloc_coherent(ld->dev, ++ ld->sg_count * sizeof(struct sg_desc), ++ &ld->dma_sg_phy, GFP_KERNEL); ++ } ++ ++ if (!ld->dma_sg_desc) { ++ pr_err("alloc sg desc dma error!\n"); ++ return -ENOMEM; ++ } ++#ifdef HIGMAC_TSO_DEBUG ++ pr_info("Higmac dma_sg_phy: 0x%p\n", (void *)ld->dma_sg_phy); ++#endif ++ ++ ld->sg_head = 0; ++ ld->sg_tail = 0; ++ ++ return 0; ++} ++ ++static void higmac_destroy_sg_desc_queue(struct higmac_netdev_local *ld) ++{ ++ if (ld->dma_sg_desc) { ++ if (HAS_CAP_CCI(ld->hw_cap)) ++ kfree(ld->dma_sg_desc); ++ else ++ dma_free_coherent(ld->dev, ++ ld->sg_count * sizeof(struct sg_desc), ++ ld->dma_sg_desc, ld->dma_sg_phy); ++ ld->dma_sg_desc = NULL; ++ } ++} ++ ++static bool higmac_rx_fq_empty(struct higmac_netdev_local *priv) ++{ ++ u32 start, end; ++ ++ start = readl(priv->gmac_iobase + RX_FQ_WR_ADDR); ++ end = readl(priv->gmac_iobase + RX_FQ_RD_ADDR); ++ ++ if (start == end) ++ return true; ++ else ++ return false; ++} ++ ++static bool higmac_rxq_has_packets(struct higmac_netdev_local *priv, int rxq_id) ++{ ++ u32 rx_bq_rd_reg, rx_bq_wr_reg; ++ u32 start, end; ++ ++ rx_bq_rd_reg = RX_BQ_RD_ADDR_QUEUE(rxq_id); ++ rx_bq_wr_reg = RX_BQ_WR_ADDR_QUEUE(rxq_id); ++ ++ start = readl(priv->gmac_iobase + rx_bq_rd_reg); ++ end = readl(priv->gmac_iobase + rx_bq_wr_reg); ++ ++ if (start == end) ++ return false; ++ else ++ return true; ++} ++ ++static void higmac_monitor_func(unsigned long arg) ++{ ++ struct net_device *dev = (struct net_device *)arg; ++ struct higmac_netdev_local *ld = netdev_priv(dev); ++ u32 refill_cnt; ++ ++ if (!ld || !netif_running(dev)) { ++ higmac_trace(7, "network driver is stopped."); ++ return; ++ } ++ ++ spin_lock(&ld->rxlock); ++ refill_cnt = higmac_rx_refill(ld); ++ if (!refill_cnt && higmac_rx_fq_empty(ld)) { ++ int rxq_id; ++ ++ for (rxq_id = 0; rxq_id < ld->num_rxqs; rxq_id++) { ++ if (higmac_rxq_has_packets(ld, rxq_id)) ++ napi_schedule(&ld->q_napi[rxq_id].napi); ++ } ++ } ++ spin_unlock(&ld->rxlock); ++ ++ ld->monitor.expires = jiffies + HIGMAC_MONITOR_TIMER; ++ mod_timer(&ld->monitor, ld->monitor.expires); ++} ++ ++static u32 higmac_rx_refill(struct higmac_netdev_local *priv) ++{ ++ struct higmac_desc *desc; ++ struct sk_buff *skb; ++ u32 start, end, num, pos, i; ++ u32 len = HIETH_MAX_FRAME_SIZE; ++ dma_addr_t addr; ++ u32 refill_cnt = 0; ++ ++ /* software write pointer */ ++ start = dma_cnt(readl(priv->gmac_iobase + RX_FQ_WR_ADDR)); ++ /* logic read pointer */ ++ end = dma_cnt(readl(priv->gmac_iobase + RX_FQ_RD_ADDR)); ++ num = CIRC_SPACE(start, end, RX_DESC_NUM); ++ ++ for (i = 0, pos = start; i < num; i++) { ++ if (priv->rx_fq.skb[pos] || priv->rx_skb[pos]) ++ break; ++ ++ skb = netdev_alloc_skb_ip_align(priv->netdev, len); ++ if (unlikely(!skb)) ++ break; ++ ++ if (!HAS_CAP_CCI(priv->hw_cap)) { ++ addr = dma_map_single(priv->dev, skb->data, len, ++ DMA_FROM_DEVICE); ++ if (dma_mapping_error(priv->dev, addr)) { ++ dev_kfree_skb_any(skb); ++ break; ++ } ++ } else { ++ addr = virt_to_phys(skb->data); ++ } ++ ++ desc = priv->rx_fq.desc + pos; ++ desc->data_buff_addr = addr; ++ priv->rx_fq.skb[pos] = skb; ++ priv->rx_skb[pos] = skb; ++ ++ desc->buffer_len = len - 1; ++ desc->data_len = 0; ++ desc->fl = 0; ++ desc->descvid = DESC_VLD_FREE; ++ desc->skb_id = pos; ++ ++ refill_cnt++; ++ pos = dma_ring_incr(pos, RX_DESC_NUM); ++ } ++ ++ /* This barrier is important here. It is required to ensure ++ * the ARM CPU flushes it's DMA write buffers before proceeding ++ * to the next instruction, to ensure that GMAC will see ++ * our descriptor changes in memory ++ */ ++ HIGMAC_SYNC_BARRIER(); ++ ++ if (pos != start) ++ writel(dma_byte(pos), priv->gmac_iobase + RX_FQ_WR_ADDR); ++ ++ return refill_cnt; ++} ++ ++static int higmac_rx(struct net_device *dev, int limit, int rxq_id) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(dev); ++ struct sk_buff *skb; ++ struct higmac_desc *desc; ++ dma_addr_t addr; ++ u32 start, end, num, pos, i, len; ++ u32 rx_bq_rd_reg, rx_bq_wr_reg; ++ u16 skb_id; ++ ++ rx_bq_rd_reg = RX_BQ_RD_ADDR_QUEUE(rxq_id); ++ rx_bq_wr_reg = RX_BQ_WR_ADDR_QUEUE(rxq_id); ++ ++ /* software read pointer */ ++ start = dma_cnt(readl(ld->gmac_iobase + rx_bq_rd_reg)); ++ /* logic write pointer */ ++ end = dma_cnt(readl(ld->gmac_iobase + rx_bq_wr_reg)); ++ num = CIRC_CNT(end, start, RX_DESC_NUM); ++ if (num > limit) ++ num = limit; ++ ++ /* ensure get updated desc */ ++ rmb(); ++ for (i = 0, pos = start; i < num; i++) { ++ if (rxq_id) ++ desc = ld->pool[3 + rxq_id].desc + pos; ++ else ++ desc = ld->rx_bq.desc + pos; ++ skb_id = desc->skb_id; ++ ++ spin_lock(&ld->rxlock); ++ skb = ld->rx_skb[skb_id]; ++ if (unlikely(!skb)) { ++ spin_unlock(&ld->rxlock); ++ netdev_err(dev, "inconsistent rx_skb\n"); ++ break; ++ } ++ ++ /* data consistent check */ ++ if (unlikely(skb != ld->rx_fq.skb[skb_id])) { ++ netdev_err(dev, "desc->skb(0x%p),rx_fq.skb[%d](0x%p)\n", ++ skb, skb_id, ld->rx_fq.skb[skb_id]); ++ if (ld->rx_fq.skb[skb_id] == SKB_MAGIC) { ++ spin_unlock(&ld->rxlock); ++ goto next; ++ } ++ WARN_ON(1); ++ } else { ++ ld->rx_fq.skb[skb_id] = NULL; ++ } ++ spin_unlock(&ld->rxlock); ++ ++ len = desc->data_len; ++ ++ if (!HAS_CAP_CCI(ld->hw_cap)) { ++ addr = desc->data_buff_addr; ++ dma_unmap_single(ld->dev, addr, HIETH_MAX_FRAME_SIZE, ++ DMA_FROM_DEVICE); ++ } ++ ++ skb_put(skb, len); ++ if (skb->len > HIETH_MAX_FRAME_SIZE) { ++ netdev_err(dev, "rcv len err, len = %d\n", skb->len); ++ dev->stats.rx_errors++; ++ dev->stats.rx_length_errors++; ++ dev_kfree_skb_any(skb); ++ goto next; ++ } ++ ++ skb->protocol = eth_type_trans(skb, dev); ++ skb->ip_summed = CHECKSUM_NONE; ++#if defined(CONFIG_HIGMAC_RXCSUM) ++ if (dev->features & NETIF_F_RXCSUM) { ++ int hdr_csum_done = ++ desc->header_csum_done; ++ int payload_csum_done = ++ desc->payload_csum_done; ++ int hdr_csum_err = ++ desc->header_csum_err; ++ int payload_csum_err = ++ desc->payload_csum_err; ++ ++ if (hdr_csum_done && payload_csum_done) { ++ if (unlikely(hdr_csum_err || ++ payload_csum_err)) { ++ dev->stats.rx_errors++; ++ dev->stats.rx_crc_errors++; ++ dev_kfree_skb_any(skb); ++ goto next; ++ } else { ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ } ++ } ++ } ++#endif ++ if ((dev->features & NETIF_F_RXHASH) && desc->has_hash) ++ skb_set_hash(skb, desc->rxhash, desc->l3_hash ? ++ PKT_HASH_TYPE_L3 : PKT_HASH_TYPE_L4); ++ ++ skb_record_rx_queue(skb, rxq_id); ++ ++ napi_gro_receive(&ld->q_napi[rxq_id].napi, skb); ++ dev->stats.rx_packets++; ++ dev->stats.rx_bytes += len; ++ dev->last_rx = jiffies; ++next: ++ spin_lock(&ld->rxlock); ++ ld->rx_skb[skb_id] = NULL; ++ spin_unlock(&ld->rxlock); ++ pos = dma_ring_incr(pos, RX_DESC_NUM); ++ } ++ ++ if (pos != start) ++ writel(dma_byte(pos), ld->gmac_iobase + rx_bq_rd_reg); ++ ++ spin_lock(&ld->rxlock); ++ higmac_rx_refill(ld); ++ spin_unlock(&ld->rxlock); ++ ++ return num; ++} ++ ++#ifdef HIGMAC_TSO_DEBUG ++unsigned int id_send; ++unsigned int id_free; ++struct send_pkt_info pkt_rec[MAX_RECORD]; ++#endif ++ ++static int higmac_check_tx_err(struct higmac_netdev_local *ld, ++ struct higmac_tso_desc *tx_bq_desc, ++ unsigned int desc_pos) ++{ ++ unsigned int tx_err = tx_bq_desc->tx_err; ++ ++ if (unlikely(tx_err & ERR_ALL)) { ++ struct sg_desc *desc_cur; ++ int *sg_word; ++ int i; ++ ++ WARN((tx_err & ERR_ALL), ++ "TX ERR: desc1=0x%x, desc2=0x%x, desc5=0x%x\n", ++ tx_bq_desc->data_buff_addr, ++ tx_bq_desc->desc1.val, tx_bq_desc->tx_err); ++ ++ desc_cur = ld->dma_sg_desc + ld->tx_bq.sg_desc_offset[desc_pos]; ++ sg_word = (int *)desc_cur; ++ for (i = 0; i < sizeof(struct sg_desc) / sizeof(int); i++) ++ pr_err("%s,%d: sg_desc word[%d]=0x%x\n", ++ __func__, __LINE__, i, sg_word[i]); ++ ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int higmac_xmit_release_gso(struct higmac_netdev_local *ld, ++ struct higmac_tso_desc *tx_bq_desc, ++ unsigned int desc_pos) ++{ ++ int pkt_type; ++ int nfrags = tx_bq_desc->desc1.tx.nfrags_num; ++ dma_addr_t addr; ++ size_t len; ++ ++ if (unlikely(higmac_check_tx_err(ld, tx_bq_desc, desc_pos) < 0)) { ++ /* dev_close */ ++ higmac_irq_disable_all_queue(ld); ++ higmac_hw_desc_disable(ld); ++ ++ netif_carrier_off(ld->netdev); ++ netif_stop_queue(ld->netdev); ++ ++ phy_stop(ld->phy); ++ del_timer_sync(&ld->monitor); ++ return -1; ++ } ++ ++ if (tx_bq_desc->desc1.tx.tso_flag || nfrags) ++ pkt_type = PKT_SG; ++ else ++ pkt_type = PKT_NORMAL; ++ ++ if (pkt_type == PKT_NORMAL) { ++ if (!HAS_CAP_CCI(ld->hw_cap)) { ++ addr = tx_bq_desc->data_buff_addr; ++ len = tx_bq_desc->desc1.tx.data_len; ++ dma_unmap_single(ld->dev, addr, len, DMA_TO_DEVICE); ++ } ++ } else { ++ if (!HAS_CAP_CCI(ld->hw_cap)) { ++ struct sg_desc *desc_cur; ++ unsigned int desc_offset; ++ int i; ++ ++ desc_offset = ld->tx_bq.sg_desc_offset[desc_pos]; ++ WARN_ON(desc_offset != ld->sg_tail); ++ desc_cur = ld->dma_sg_desc + desc_offset; ++ ++ addr = desc_cur->linear_addr; ++ len = desc_cur->linear_len; ++ dma_unmap_single(ld->dev, addr, len, DMA_TO_DEVICE); ++ for (i = 0; i < nfrags; i++) { ++ addr = desc_cur->frags[i].addr; ++ len = desc_cur->frags[i].size; ++ dma_unmap_page(ld->dev, addr, len, ++ DMA_TO_DEVICE); ++ } ++ } ++ ++ ld->sg_tail = (ld->sg_tail + 1) % ld->sg_count; ++ } ++ ++#ifdef HIGMAC_TSO_DEBUG ++ pkt_rec[id_free].status = 0; ++ id_free++; ++ if (id_free == MAX_RECORD) ++ id_free = 0; ++#endif ++ ++ return 0; ++} ++ ++static void higmac_xmit_reclaim(struct net_device *dev) ++{ ++ struct sk_buff *skb; ++ struct higmac_desc *desc; ++ struct higmac_tso_desc *tso_desc; ++ struct higmac_netdev_local *priv = netdev_priv(dev); ++ unsigned int bytes_compl = 0, pkts_compl = 0; ++ u32 start, end, num, pos, i; ++ dma_addr_t addr; ++ int ret; ++ ++ spin_lock(&priv->txlock); ++ ++ /* software read */ ++ start = dma_cnt(readl(priv->gmac_iobase + TX_RQ_RD_ADDR)); ++ /* logic write */ ++ end = dma_cnt(readl(priv->gmac_iobase + TX_RQ_WR_ADDR)); ++ num = CIRC_CNT(end, start, TX_DESC_NUM); ++ ++ for (i = 0, pos = start; i < num; i++) { ++ skb = priv->tx_skb[pos]; ++ if (unlikely(!skb)) { ++ netdev_err(dev, "inconsistent tx_skb\n"); ++ break; ++ } ++ ++ if (skb != priv->tx_bq.skb[pos]) { ++ netdev_err(dev, "wired, tx skb[%d](%p) != skb(%p)\n", ++ pos, priv->tx_bq.skb[pos], skb); ++ if (priv->tx_bq.skb[pos] == SKB_MAGIC) ++ goto next; ++ } ++ ++ pkts_compl++; ++ bytes_compl += skb->len; ++ desc = priv->tx_rq.desc + pos; ++ if (priv->tso_supported) { ++ tso_desc = (struct higmac_tso_desc *)desc; ++ ret = higmac_xmit_release_gso(priv, tso_desc, pos); ++ if (ret < 0) ++ break; ++ } else if (!HAS_CAP_CCI(priv->hw_cap)) { ++ addr = desc->data_buff_addr; ++ dma_unmap_single(priv->dev, addr, skb->len, ++ DMA_TO_DEVICE); ++ } ++ priv->tx_bq.skb[pos] = NULL; ++next: ++ priv->tx_skb[pos] = NULL; ++ dev_consume_skb_any(skb); ++ pos = dma_ring_incr(pos, TX_DESC_NUM); ++ } ++ ++ if (pos != start) ++ writel(dma_byte(pos), priv->gmac_iobase + TX_RQ_RD_ADDR); ++ ++ if (pkts_compl || bytes_compl) ++ netdev_completed_queue(dev, pkts_compl, bytes_compl); ++ ++ if (unlikely(netif_queue_stopped(priv->netdev)) && pkts_compl) ++ netif_wake_queue(priv->netdev); ++ ++ spin_unlock(&priv->txlock); ++} ++ ++static int higmac_poll(struct napi_struct *napi, int budget) ++{ ++ struct higmac_napi *q_napi = container_of(napi, ++ struct higmac_napi, napi); ++ struct higmac_netdev_local *priv = q_napi->ndev_priv; ++ struct net_device *dev = priv->netdev; ++ int work_done = 0, task = budget; ++ u32 ints, num; ++ u32 raw_int_reg, raw_int_mask; ++ ++ if (q_napi->rxq_id) { ++ raw_int_reg = RSS_RAW_PMU_INT; ++ raw_int_mask = DEF_INT_MASK_QUEUE(q_napi->rxq_id); ++ } else { ++ raw_int_reg = RAW_PMU_INT; ++ raw_int_mask = DEF_INT_MASK; ++ } ++ ++ do { ++ if (!q_napi->rxq_id) ++ higmac_xmit_reclaim(dev); ++ num = higmac_rx(dev, task, q_napi->rxq_id); ++ work_done += num; ++ task -= num; ++ if (work_done >= budget) ++ break; ++ ++ ints = readl(priv->gmac_iobase + raw_int_reg); ++ ints &= raw_int_mask; ++ writel(ints, priv->gmac_iobase + raw_int_reg); ++ } while (ints || higmac_rxq_has_packets(priv, q_napi->rxq_id)); ++ ++ if (work_done < budget) { ++ napi_complete(napi); ++ higmac_irq_enable_queue(priv, q_napi->rxq_id); ++ } ++ ++ return work_done; ++} ++ ++static irqreturn_t higmac_interrupt(int irq, void *dev_id) ++{ ++ struct higmac_napi *q_napi = (struct higmac_napi *)dev_id; ++ struct higmac_netdev_local *ld = q_napi->ndev_priv; ++ u32 ints; ++ u32 raw_int_reg, raw_int_mask; ++ ++ if (higmac_queue_irq_disabled(ld, q_napi->rxq_id)) ++ return IRQ_NONE; ++ ++ if (q_napi->rxq_id) { ++ raw_int_reg = RSS_RAW_PMU_INT; ++ raw_int_mask = DEF_INT_MASK_QUEUE(q_napi->rxq_id); ++ } else { ++ raw_int_reg = RAW_PMU_INT; ++ raw_int_mask = DEF_INT_MASK; ++ } ++ ++ ints = readl(ld->gmac_iobase + raw_int_reg); ++ ints &= raw_int_mask; ++ writel(ints, ld->gmac_iobase + raw_int_reg); ++ ++ if (likely(ints || higmac_rxq_has_packets(ld, q_napi->rxq_id))) { ++ higmac_irq_disable_queue(ld, q_napi->rxq_id); ++ napi_schedule(&q_napi->napi); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static inline __be16 higmac_get_l3_proto(struct sk_buff *skb) ++{ ++ __be16 l3_proto; ++ ++ l3_proto = skb->protocol; ++ if (skb->protocol == htons(ETH_P_8021Q)) ++ l3_proto = vlan_get_protocol(skb); ++ ++ return l3_proto; ++} ++ ++static inline unsigned int higmac_get_l4_proto(struct sk_buff *skb) ++{ ++ __be16 l3_proto; ++ unsigned int l4_proto = IPPROTO_MAX; ++ ++ l3_proto = higmac_get_l3_proto(skb); ++ if (l3_proto == htons(ETH_P_IP)) ++ l4_proto = ip_hdr(skb)->protocol; ++ else if (l3_proto == htons(ETH_P_IPV6)) ++ l4_proto = ipv6_hdr(skb)->nexthdr; ++ ++ return l4_proto; ++} ++ ++static inline bool higmac_skb_is_ipv6(struct sk_buff *skb) ++{ ++ return (higmac_get_l3_proto(skb) == htons(ETH_P_IPV6)); ++} ++ ++static inline bool higmac_skb_is_udp(struct sk_buff *skb) ++{ ++ return (higmac_get_l4_proto(skb) == IPPROTO_UDP); ++} ++ ++static int higmac_check_hw_capability_for_udp(struct sk_buff *skb) ++{ ++ struct ethhdr *eth; ++ ++ /* hardware can't dea with UFO broadcast packet */ ++ eth = (struct ethhdr *)(skb->data); ++ if (skb_is_gso(skb) && is_broadcast_ether_addr(eth->h_dest)) ++ return -ENOTSUPP; ++ ++ return 0; ++} ++ ++static int higmac_check_hw_capability_for_ipv6(struct sk_buff *skb) ++{ ++ unsigned int l4_proto = IPPROTO_MAX; ++ ++ l4_proto = ipv6_hdr(skb)->nexthdr; ++ ++ if ((l4_proto != IPPROTO_TCP) && (l4_proto != IPPROTO_UDP)) { ++ /* when IPv6 next header is not tcp or udp, ++ * it means that IPv6 next header is extension header. ++ * Hardware can't deal with this case, ++ * so do checksumming by software or do GSO by software. ++ */ ++ if (skb_is_gso(skb)) ++ return -ENOTSUPP; ++ ++ if (skb->ip_summed == CHECKSUM_PARTIAL && ++ skb_checksum_help(skb)) ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++static inline bool higmac_skb_is_ipv4_with_options(struct sk_buff *skb) ++{ ++ return ((higmac_get_l3_proto(skb) == htons(ETH_P_IP)) && ++ (ip_hdr(skb)->ihl > 5)); ++} ++ ++static int higmac_check_hw_capability(struct sk_buff *skb) ++{ ++ int ret = 0; ++ ++ /* if tcp_mtu_probe() use (2 * tp->mss_cache) as probe_size, ++ * the linear data length will be larger than 2048, ++ * the MAC can't handle it, so let the software do it. ++ */ ++ if (skb_is_gso(skb) && (skb_headlen(skb) > 2048)) ++ return -ENOTSUPP; ++ ++ if (higmac_skb_is_ipv6(skb)) { ++ ret = higmac_check_hw_capability_for_ipv6(skb); ++ if (ret) ++ return ret; ++ } ++ ++ if (higmac_skb_is_udp(skb)) { ++ ret = higmac_check_hw_capability_for_udp(skb); ++ if (ret) ++ return ret; ++ } ++ ++ if (((skb->ip_summed == CHECKSUM_PARTIAL) || skb_is_gso(skb)) && ++ higmac_skb_is_ipv4_with_options(skb)) ++ return -ENOTSUPP; ++ ++ return 0; ++} ++ ++static void higmac_do_udp_checksum(struct sk_buff *skb) ++{ ++ int offset; ++ __wsum csum; ++ __sum16 udp_csum; ++ ++ offset = skb_checksum_start_offset(skb); ++ WARN_ON(offset >= skb_headlen(skb)); ++ csum = skb_checksum(skb, offset, skb->len - offset, 0); ++ ++ offset += skb->csum_offset; ++ WARN_ON(offset + sizeof(__sum16) > skb_headlen(skb)); ++ udp_csum = csum_fold(csum); ++ if (udp_csum == 0) ++ udp_csum = CSUM_MANGLED_0; ++ ++ *(__sum16 *)(skb->data + offset) = udp_csum; ++ ++ skb->ip_summed = CHECKSUM_NONE; ++} ++ ++static void higmac_get_pkt_info(struct higmac_netdev_local *ld, ++ struct sk_buff *skb, ++ struct higmac_tso_desc *tx_bq_desc) ++{ ++ int nfrags = skb_shinfo(skb)->nr_frags; ++ ++ __be16 l3_proto; /* level 3 protocol */ ++ unsigned int l4_proto = IPPROTO_MAX; ++ unsigned int max_mss = ETH_DATA_LEN; ++ unsigned char coe_enable = 0; ++ int max_data_len = skb->len - ETH_HLEN; ++ ++ if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) ++ coe_enable = 1; ++ ++ tx_bq_desc->desc1.val = 0; ++ ++ if (skb_is_gso(skb)) { ++ tx_bq_desc->desc1.tx.tso_flag = 1; ++ tx_bq_desc->desc1.tx.sg_flag = 1; ++ } else if (nfrags) { ++ tx_bq_desc->desc1.tx.sg_flag = 1; ++ } ++ ++ l3_proto = skb->protocol; ++ if (skb->protocol == htons(ETH_P_8021Q)) { ++ l3_proto = vlan_get_protocol(skb); ++ tx_bq_desc->desc1.tx.vlan_flag = 1; ++ max_data_len -= VLAN_HLEN; ++ } ++ ++ if (l3_proto == htons(ETH_P_IP)) { ++ struct iphdr *iph; ++ ++ iph = ip_hdr(skb); ++ tx_bq_desc->desc1.tx.ip_ver = PKT_IPV4; ++ tx_bq_desc->desc1.tx.ip_hdr_len = iph->ihl; ++ ++ if ((max_data_len >= GSO_MAX_SIZE) && ++ (ntohs(iph->tot_len) <= (iph->ihl << 2))) ++ iph->tot_len = htons(GSO_MAX_SIZE - 1); ++ ++ max_mss -= iph->ihl * WORD_TO_BYTE; ++ l4_proto = iph->protocol; ++ } else if (l3_proto == htons(ETH_P_IPV6)) { ++ tx_bq_desc->desc1.tx.ip_ver = PKT_IPV6; ++ tx_bq_desc->desc1.tx.ip_hdr_len = PKT_IPV6_HDR_LEN; ++ max_mss -= PKT_IPV6_HDR_LEN * WORD_TO_BYTE; ++ l4_proto = ipv6_hdr(skb)->nexthdr; ++ } else { ++ coe_enable = 0; ++ } ++ ++ if (l4_proto == IPPROTO_TCP) { ++ tx_bq_desc->desc1.tx.prot_type = PKT_TCP; ++ tx_bq_desc->desc1.tx.prot_hdr_len = tcp_hdr(skb)->doff; ++ max_mss -= tcp_hdr(skb)->doff * WORD_TO_BYTE; ++ } else if (l4_proto == IPPROTO_UDP) { ++ tx_bq_desc->desc1.tx.prot_type = PKT_UDP; ++ tx_bq_desc->desc1.tx.prot_hdr_len = PKT_UDP_HDR_LEN; ++ if (l3_proto == htons(ETH_P_IPV6)) ++ max_mss -= sizeof(struct frag_hdr); ++ } else { ++ coe_enable = 0; ++ } ++ ++ if (skb_is_gso(skb)) ++ tx_bq_desc->desc1.tx.data_len = ++ (skb_shinfo(skb)->gso_size > max_mss) ? max_mss : ++ skb_shinfo(skb)->gso_size; ++ else ++ tx_bq_desc->desc1.tx.data_len = skb->len; ++ ++ if (coe_enable && skb_is_gso(skb) && (l4_proto == IPPROTO_UDP)) ++ higmac_do_udp_checksum(skb); ++ ++ if (coe_enable) ++ tx_bq_desc->desc1.tx.coe_flag = 1; ++ ++ tx_bq_desc->desc1.tx.nfrags_num = nfrags; ++ ++ tx_bq_desc->desc1.tx.hw_own = DESC_VLD_BUSY; ++} ++ ++static int higmac_xmit_gso(struct higmac_netdev_local *ld, struct sk_buff *skb, ++ struct higmac_tso_desc *tx_bq_desc, ++ unsigned int desc_pos) ++{ ++ int pkt_type = PKT_NORMAL; ++ int nfrags = skb_shinfo(skb)->nr_frags; ++ dma_addr_t addr; ++ int ret; ++ ++ if (skb_is_gso(skb) || nfrags) { ++ /* TSO pkt or SG pkt */ ++ pkt_type = PKT_SG; ++ } else { /* Normal pkt */ ++ pkt_type = PKT_NORMAL; ++ } ++ ++ ret = higmac_check_hw_capability(skb); ++ if (unlikely(ret)) ++ return ret; ++ ++ higmac_get_pkt_info(ld, skb, tx_bq_desc); ++ ++ if (pkt_type == PKT_NORMAL) { ++ if (!HAS_CAP_CCI(ld->hw_cap)) { ++ addr = dma_map_single(ld->dev, skb->data, skb->len, ++ DMA_TO_DEVICE); ++ ret = dma_mapping_error(ld->dev, addr); ++ if (unlikely(ret)) { ++ pr_err("Normal Packet DMA Mapping fail.\n"); ++ return -EFAULT; ++ } ++ tx_bq_desc->data_buff_addr = addr; ++ } else { ++ tx_bq_desc->data_buff_addr = virt_to_phys(skb->data); ++ } ++ } else { ++ struct sg_desc *desc_cur; ++ int i; ++ ++ if (unlikely(((ld->sg_head + 1) % ld->sg_count) == ++ ld->sg_tail)) { ++ /* SG pkt, but sg desc all used */ ++ pr_err("WARNING: sg desc all used.\n"); ++ return -EBUSY; ++ } ++ ++ desc_cur = ld->dma_sg_desc + ld->sg_head; ++ ++ /* TODO: deal with ipv6_id */ ++ if (tx_bq_desc->desc1.tx.tso_flag && ++ tx_bq_desc->desc1.tx.ip_ver == PKT_IPV6 && ++ tx_bq_desc->desc1.tx.prot_type == PKT_UDP) { ++ desc_cur->ipv6_id = ntohl(skb_shinfo(skb)->ip6_frag_id); ++ } ++ ++ desc_cur->total_len = skb->len; ++ desc_cur->linear_len = skb_headlen(skb); ++ if (!HAS_CAP_CCI(ld->hw_cap)) { ++ addr = dma_map_single(ld->dev, skb->data, ++ desc_cur->linear_len, ++ DMA_TO_DEVICE); ++ ret = dma_mapping_error(ld->dev, addr); ++ if (unlikely(ret)) { ++ pr_err("DMA Mapping fail."); ++ return -EFAULT; ++ } ++ desc_cur->linear_addr = addr; ++ } else { ++ desc_cur->linear_addr = virt_to_phys(skb->data); ++ } ++ ++ for (i = 0; i < nfrags; i++) { ++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ++ int len = frag->size; ++ ++ if (!HAS_CAP_CCI(ld->hw_cap)) { ++ addr = skb_frag_dma_map(ld->dev, frag, 0, len, ++ DMA_TO_DEVICE); ++ ret = dma_mapping_error(ld->dev, addr); ++ if (unlikely(ret)) { ++ pr_err("skb frag DMA Mapping fail."); ++ return -EFAULT; ++ } ++ desc_cur->frags[i].addr = addr; ++ } else { ++ desc_cur->frags[i].addr = ++ page_to_phys(skb_frag_page(frag)) + ++ frag->page_offset; ++ } ++ desc_cur->frags[i].size = len; ++ } ++ tx_bq_desc->data_buff_addr = ld->dma_sg_phy + ++ ld->sg_head * sizeof(struct sg_desc); ++ ld->tx_bq.sg_desc_offset[desc_pos] = ld->sg_head; ++ ++ ld->sg_head = (ld->sg_head + 1) % ld->sg_count; ++ } ++ ++#ifdef HIGMAC_TSO_DEBUG ++ memcpy(&pkt_rec[id_send].desc, tx_bq_desc, ++ sizeof(struct higmac_tso_desc)); ++ pkt_rec[id_send].status = 1; ++ id_send++; ++ if (id_send == MAX_RECORD) ++ id_send = 0; ++#endif ++ return 0; ++} ++ ++static netdev_tx_t higmac_net_xmit(struct sk_buff *skb, struct net_device *dev); ++ ++static netdev_tx_t higmac_sw_gso(struct higmac_netdev_local *ld, ++ struct sk_buff *skb) ++{ ++ struct sk_buff *segs, *curr_skb; ++ int gso_segs = skb_shinfo(skb)->gso_segs; ++ ++ if (gso_segs == 0 && skb_shinfo(skb)->gso_size != 0) ++ gso_segs = DIV_ROUND_UP(skb->len, skb_shinfo(skb)->gso_size); ++ ++ /* Estimate the number of fragments in the worst case */ ++ if (unlikely(higmac_tx_avail(ld) < gso_segs)) { ++ netif_stop_queue(ld->netdev); ++ if (higmac_tx_avail(ld) < gso_segs) { ++ ld->netdev->stats.tx_dropped++; ++ ld->netdev->stats.tx_fifo_errors++; ++ return NETDEV_TX_BUSY; ++ } ++ ++ netif_wake_queue(ld->netdev); ++ } ++ ++ segs = skb_gso_segment(skb, ld->netdev->features & ~(NETIF_F_ALL_CSUM | ++ NETIF_F_SG | NETIF_F_GSO_SOFTWARE)); ++ ++ if (IS_ERR_OR_NULL(segs)) ++ goto drop; ++ ++ do { ++ curr_skb = segs; ++ segs = segs->next; ++ curr_skb->next = NULL; ++ higmac_net_xmit(curr_skb, ld->netdev); ++ } while (segs); ++ ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++ ++drop: ++ dev_kfree_skb_any(skb); ++ ld->netdev->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++} ++ ++static netdev_tx_t higmac_net_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(dev); ++ struct higmac_desc *desc; ++ dma_addr_t addr; ++ unsigned long txflags; ++ int ret; ++ u32 pos; ++ ++ if (skb->len < ETH_HLEN) { ++ dev_kfree_skb_any(skb); ++ dev->stats.tx_errors++; ++ dev->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++ } ++ ++ /* if adding higmac_xmit_reclaim here, iperf tcp client ++ * performance will be affected, from 550M(avg) to 513M~300M ++ */ ++ ++ /* software write pointer */ ++ pos = dma_cnt(readl(ld->gmac_iobase + TX_BQ_WR_ADDR)); ++ ++ spin_lock_irqsave(&ld->txlock, txflags); ++ ++ if (unlikely(ld->tx_skb[pos] || ld->tx_bq.skb[pos])) { ++ dev->stats.tx_dropped++; ++ dev->stats.tx_fifo_errors++; ++ netif_stop_queue(dev); ++ spin_unlock_irqrestore(&ld->txlock, txflags); ++ ++ return NETDEV_TX_BUSY; ++ } ++ ++ ld->tx_bq.skb[pos] = skb; ++ ld->tx_skb[pos] = skb; ++ ++ desc = ld->tx_bq.desc + pos; ++ ++ if (ld->tso_supported) { ++ ret = higmac_xmit_gso(ld, skb, ++ (struct higmac_tso_desc *)desc, ++ pos); ++ if (unlikely(ret < 0)) { ++ ld->tx_skb[pos] = NULL; ++ ld->tx_bq.skb[pos] = NULL; ++ spin_unlock_irqrestore(&ld->txlock, txflags); ++ ++ if (ret == -ENOTSUPP) ++ return higmac_sw_gso(ld, skb); ++ ++ dev_kfree_skb_any(skb); ++ dev->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++ } ++ } else { ++ if (!HAS_CAP_CCI(ld->hw_cap)) { ++ addr = dma_map_single(ld->dev, skb->data, skb->len, ++ DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(ld->dev, addr))) { ++ dev_kfree_skb_any(skb); ++ dev->stats.tx_dropped++; ++ ld->tx_skb[pos] = NULL; ++ ld->tx_bq.skb[pos] = NULL; ++ spin_unlock_irqrestore(&ld->txlock, txflags); ++ return NETDEV_TX_OK; ++ } ++ desc->data_buff_addr = addr; ++ } else { ++ desc->data_buff_addr = virt_to_phys(skb->data); ++ } ++ desc->buffer_len = HIETH_MAX_FRAME_SIZE - 1; ++ desc->data_len = skb->len; ++ desc->fl = DESC_FL_FULL; ++ desc->descvid = DESC_VLD_BUSY; ++ } ++ ++ /* This barrier is important here. It is required to ensure ++ * the ARM CPU flushes it's DMA write buffers before proceeding ++ * to the next instruction, to ensure that GMAC will see ++ * our descriptor changes in memory ++ */ ++ HIGMAC_SYNC_BARRIER(); ++ ++ pos = dma_ring_incr(pos, TX_DESC_NUM); ++ writel(dma_byte(pos), ld->gmac_iobase + TX_BQ_WR_ADDR); ++ ++ dev->trans_start = jiffies; ++ dev->stats.tx_packets++; ++ dev->stats.tx_bytes += skb->len; ++ netdev_sent_queue(dev, skb->len); ++ ++ spin_unlock_irqrestore(&ld->txlock, txflags); ++ ++ return NETDEV_TX_OK; ++} ++ ++void higmac_enable_napi(struct higmac_netdev_local *priv) ++{ ++ struct higmac_napi *q_napi; ++ int i; ++ ++ for (i = 0; i < priv->num_rxqs; i++) { ++ q_napi = &priv->q_napi[i]; ++ napi_enable(&q_napi->napi); ++ } ++} ++ ++void higmac_disable_napi(struct higmac_netdev_local *priv) ++{ ++ struct higmac_napi *q_napi; ++ int i; ++ ++ for (i = 0; i < priv->num_rxqs; i++) { ++ q_napi = &priv->q_napi[i]; ++ napi_disable(&q_napi->napi); ++ } ++} ++ ++static int higmac_net_open(struct net_device *dev) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(dev); ++ unsigned long flags; ++ ++ clk_prepare_enable(ld->macif_clk); ++ clk_prepare_enable(ld->clk); ++ ++ /* If we configure mac address by ++ * "ifconfig ethX hw ether XX:XX:XX:XX:XX:XX", ++ * the ethX must be down state and mac core clock is disabled ++ * which results the mac address has not been configured ++ * in mac core register. ++ * So we must set mac address again here, ++ * because mac core clock is enabled at this time ++ * and we can configure mac address to mac core register. ++ */ ++ higmac_hw_set_mac_addr(dev); ++ ++ /* We should use netif_carrier_off() here, ++ * because the default state should be off. ++ * And this call should before phy_start(). ++ */ ++ netif_carrier_off(dev); ++ higmac_enable_napi(ld); ++ phy_start(ld->phy); ++ ++ higmac_hw_desc_enable(ld); ++ higmac_port_enable(ld); ++ higmac_irq_enable_all_queue(ld); ++ ++ spin_lock_irqsave(&ld->rxlock, flags); ++ higmac_rx_refill(ld); ++ spin_unlock_irqrestore(&ld->rxlock, flags); ++ ++ ld->monitor.expires = jiffies + HIGMAC_MONITOR_TIMER; ++ mod_timer(&ld->monitor, ld->monitor.expires); ++ ++ netif_start_queue(dev); ++ ++ return 0; ++} ++ ++static int higmac_net_close(struct net_device *dev) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(dev); ++ ++ higmac_irq_disable_all_queue(ld); ++ higmac_hw_desc_disable(ld); ++ ++ higmac_disable_napi(ld); ++ ++ netif_carrier_off(dev); ++ netif_stop_queue(dev); ++ ++ phy_stop(ld->phy); ++ del_timer_sync(&ld->monitor); ++ ++ clk_disable_unprepare(ld->clk); ++ clk_disable_unprepare(ld->macif_clk); ++ ++ return 0; ++} ++ ++static void higmac_net_timeout(struct net_device *dev) ++{ ++ dev->stats.tx_errors++; ++ ++ pr_err("tx timeout!\n"); ++} ++ ++static void higmac_set_multicast_list(struct net_device *dev) ++{ ++ higmac_gmac_multicast_list(dev); ++} ++ ++static inline void higmac_enable_rxcsum_drop(struct higmac_netdev_local *ld, ++ bool drop) ++{ ++ unsigned int v; ++ ++ v = readl(ld->gmac_iobase + TSO_COE_CTRL); ++ if (drop) ++ v |= COE_ERR_DROP; ++ else ++ v &= ~COE_ERR_DROP; ++ writel(v, ld->gmac_iobase + TSO_COE_CTRL); ++} ++ ++static int higmac_set_features(struct net_device *dev, ++ netdev_features_t features) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(dev); ++ netdev_features_t changed = dev->features ^ features; ++ ++ if (changed & NETIF_F_RXCSUM) { ++ if (features & NETIF_F_RXCSUM) ++ higmac_enable_rxcsum_drop(ld, true); ++ else ++ higmac_enable_rxcsum_drop(ld, false); ++ } ++ ++ return 0; ++} ++ ++static struct net_device_stats *higmac_net_get_stats(struct net_device *dev) ++{ ++ return &dev->stats; ++} ++ ++static void higmac_get_drvinfo(struct net_device *net_dev, ++ struct ethtool_drvinfo *info) ++{ ++ strncpy(info->driver, "higmac driver", 15); ++ strncpy(info->version, "higmac v200", 15); ++ strncpy(info->bus_info, "platform", 15); ++} ++ ++static unsigned int higmac_get_link(struct net_device *net_dev) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(net_dev); ++ ++ return ld->phy->link ? HIGMAC_LINKED : 0; ++} ++ ++static int higmac_get_settings(struct net_device *net_dev, ++ struct ethtool_cmd *cmd) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(net_dev); ++ ++ if (ld->phy) ++ return phy_ethtool_gset(ld->phy, cmd); ++ ++ return -EINVAL; ++} ++ ++static int higmac_set_settings(struct net_device *net_dev, ++ struct ethtool_cmd *cmd) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(net_dev); ++ ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ ++ if (ld->phy) ++ return phy_ethtool_sset(ld->phy, cmd); ++ ++ return -EINVAL; ++} ++ ++static void higmac_get_pauseparam(struct net_device *net_dev, ++ struct ethtool_pauseparam *pause) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(net_dev); ++ ++ pause->rx_pause = 0; ++ pause->tx_pause = 0; ++ pause->autoneg = ld->phy->autoneg; ++ ++ if (ld->flow_ctrl & FLOW_RX) ++ pause->rx_pause = 1; ++ if (ld->flow_ctrl & FLOW_TX) ++ pause->tx_pause = 1; ++} ++ ++static int higmac_set_pauseparam(struct net_device *net_dev, ++ struct ethtool_pauseparam *pause) ++{ ++ struct higmac_netdev_local *ld = netdev_priv(net_dev); ++ struct phy_device *phy = ld->phy; ++ int new_pause = FLOW_OFF; ++ int ret = 0; ++ ++ if (pause->rx_pause) ++ new_pause |= FLOW_RX; ++ if (pause->tx_pause) ++ new_pause |= FLOW_TX; ++ ++ if (new_pause != ld->flow_ctrl) ++ ld->flow_ctrl = new_pause; ++ ++ higmac_set_flow_ctrl_state(ld, phy->pause); ++ phy->advertising &= ~SUPPORTED_Pause; ++ if (ld->flow_ctrl) ++ phy->advertising |= SUPPORTED_Pause; ++ ++ if (phy->autoneg) { ++ if (netif_running(net_dev)) ++ return phy_start_aneg(phy); ++ } ++ ++ return ret; ++} ++ ++static u32 higmac_ethtool_getmsglevel(struct net_device *ndev) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ ++ return priv->msg_enable; ++} ++ ++static void higmac_ethtool_setmsglevel(struct net_device *ndev, u32 level) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ ++ priv->msg_enable = level; ++} ++ ++static u32 higmac_get_rxfh_key_size(struct net_device *ndev) ++{ ++ return RSS_HASH_KEY_SIZE; ++} ++ ++static u32 higmac_get_rxfh_indir_size(struct net_device *ndev) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ ++ return priv->rss_info.ind_tbl_size; ++} ++ ++static int higmac_get_rxfh(struct net_device *ndev, u32 *indir, u8 *hkey) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ struct higmac_rss_info *rss = &priv->rss_info; ++ ++ if (hkey) ++ memcpy(hkey, rss->key, RSS_HASH_KEY_SIZE); ++ ++ if (indir) { ++ int i; ++ ++ for (i = 0; i < rss->ind_tbl_size; i++) ++ indir[i] = rss->ind_tbl[i]; ++ } ++ ++ return 0; ++} ++ ++static void higmac_get_rss_key(struct higmac_netdev_local *priv) ++{ ++ struct higmac_rss_info *rss = &priv->rss_info; ++ u32 hkey; ++ ++ hkey = readl(priv->gmac_iobase + RSS_HASH_KEY); ++ *((u32 *)rss->key) = hkey; ++} ++ ++static void higmac_set_rss_key(struct higmac_netdev_local *priv) ++{ ++ struct higmac_rss_info *rss = &priv->rss_info; ++ ++ writel(*((u32 *)rss->key), priv->gmac_iobase + RSS_HASH_KEY); ++} ++ ++static int higmac_wait_rss_ready(struct higmac_netdev_local *priv) ++{ ++ void __iomem *base = priv->gmac_iobase; ++ int i, timeout = 10000; ++ ++ for (i = 0; !(readl(base + RSS_IND_TBL) & BIT_IND_TBL_READY); i++) { ++ if (i == timeout) { ++ netdev_err(priv->netdev, "wait rss ready timeout!\n"); ++ return -ETIMEDOUT; ++ } ++ usleep_range(10, 20); ++ } ++ ++ return 0; ++} ++ ++static void higmac_config_rss(struct higmac_netdev_local *priv) ++{ ++ struct higmac_rss_info *rss = &priv->rss_info; ++ u32 rss_val; ++ int i; ++ ++ for (i = 0; i < rss->ind_tbl_size; i++) { ++ if (higmac_wait_rss_ready(priv)) ++ break; ++ rss_val = BIT_IND_TLB_WR | (rss->ind_tbl[i] << 8) | i; ++ writel(rss_val, priv->gmac_iobase + RSS_IND_TBL); ++ } ++} ++ ++static void higmac_get_rss(struct higmac_netdev_local *priv) ++{ ++ struct higmac_rss_info *rss = &priv->rss_info; ++ u32 rss_val; ++ int i; ++ ++ for (i = 0; i < rss->ind_tbl_size; i++) { ++ if (higmac_wait_rss_ready(priv)) ++ break; ++ writel(i, priv->gmac_iobase + RSS_IND_TBL); ++ if (higmac_wait_rss_ready(priv)) ++ break; ++ rss_val = readl(priv->gmac_iobase + RSS_IND_TBL); ++ rss->ind_tbl[i] = (rss_val >> 10) & 0x3; ++ } ++} ++ ++static int higmac_set_rxfh(struct net_device *ndev, const u32 *indir, ++ const u8 *hkey) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ struct higmac_rss_info *rss = &priv->rss_info; ++ ++ if (indir) { ++ int i; ++ ++ for (i = 0; i < rss->ind_tbl_size; i++) ++ rss->ind_tbl[i] = indir[i]; ++ } ++ ++ if (hkey) { ++ memcpy(rss->key, hkey, RSS_HASH_KEY_SIZE); ++ higmac_set_rss_key(priv); ++ } ++ ++ higmac_config_rss(priv); ++ ++ return 0; ++} ++ ++static int higmac_get_rss_hash_opts(struct higmac_netdev_local *priv, ++ struct ethtool_rxnfc *info) ++{ ++ u32 hash_cfg = priv->rss_info.hash_cfg; ++ ++ info->data = 0; ++ ++ switch (info->flow_type) { ++ case TCP_V4_FLOW: ++ if (hash_cfg & TCPV4_L3_HASH_EN) ++ info->data |= RXH_IP_SRC | RXH_IP_DST; ++ if (hash_cfg & TCPV4_L4_HASH_EN) ++ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; ++ if (hash_cfg & TCPV4_VLAN_HASH_EN) ++ info->data |= RXH_VLAN; ++ break; ++ case TCP_V6_FLOW: ++ if (hash_cfg & TCPV6_L3_HASH_EN) ++ info->data |= RXH_IP_SRC | RXH_IP_DST; ++ if (hash_cfg & TCPV6_L4_HASH_EN) ++ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; ++ if (hash_cfg & TCPV6_VLAN_HASH_EN) ++ info->data |= RXH_VLAN; ++ break; ++ case UDP_V4_FLOW: ++ if (hash_cfg & UDPV4_L3_HASH_EN) ++ info->data |= RXH_IP_SRC | RXH_IP_DST; ++ if (hash_cfg & UDPV4_L4_HASH_EN) ++ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; ++ if (hash_cfg & UDPV4_VLAN_HASH_EN) ++ info->data |= RXH_VLAN; ++ break; ++ case UDP_V6_FLOW: ++ if (hash_cfg & UDPV6_L3_HASH_EN) ++ info->data |= RXH_IP_SRC | RXH_IP_DST; ++ if (hash_cfg & UDPV6_L4_HASH_EN) ++ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; ++ if (hash_cfg & UDPV6_VLAN_HASH_EN) ++ info->data |= RXH_VLAN; ++ break; ++ case IPV4_FLOW: ++ if (hash_cfg & IPV4_L3_HASH_EN) ++ info->data |= RXH_IP_SRC | RXH_IP_DST; ++ if (hash_cfg & IPV4_VLAN_HASH_EN) ++ info->data |= RXH_VLAN; ++ break; ++ case IPV6_FLOW: ++ if (hash_cfg & IPV6_L3_HASH_EN) ++ info->data |= RXH_IP_SRC | RXH_IP_DST; ++ if (hash_cfg & IPV6_VLAN_HASH_EN) ++ info->data |= RXH_VLAN; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int higmac_get_rxnfc(struct net_device *ndev, ++ struct ethtool_rxnfc *info, u32 *rules) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ int ret = -EOPNOTSUPP; ++ ++ switch (info->cmd) { ++ case ETHTOOL_GRXRINGS: ++ info->data = priv->num_rxqs; ++ ret = 0; ++ break; ++ case ETHTOOL_GRXFH: ++ return higmac_get_rss_hash_opts(priv, info); ++ default: ++ break; ++ } ++ return ret; ++} ++ ++static void higmac_config_hash_policy(struct higmac_netdev_local *priv) ++{ ++ writel(priv->rss_info.hash_cfg, priv->gmac_iobase + RSS_HASH_CONFIG); ++} ++ ++static int higmac_set_rss_hash_opts(struct higmac_netdev_local *priv, ++ struct ethtool_rxnfc *info) ++{ ++ u32 hash_cfg = priv->rss_info.hash_cfg; ++ ++ netdev_info(priv->netdev, "Set RSS flow type = %d, data = %lld\n", ++ info->flow_type, info->data); ++ ++ if (!(info->data & RXH_IP_SRC) || !(info->data & RXH_IP_DST)) ++ return -EINVAL; ++ ++ switch (info->flow_type) { ++ case TCP_V4_FLOW: ++ switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { ++ case 0: ++ hash_cfg &= ~TCPV4_L4_HASH_EN; ++ break; ++ case (RXH_L4_B_0_1 | RXH_L4_B_2_3): ++ hash_cfg |= TCPV4_L4_HASH_EN; ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (info->data & RXH_VLAN) ++ hash_cfg |= TCPV4_VLAN_HASH_EN; ++ else ++ hash_cfg &= ~TCPV4_VLAN_HASH_EN; ++ break; ++ case TCP_V6_FLOW: ++ switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { ++ case 0: ++ hash_cfg &= ~TCPV6_L4_HASH_EN; ++ break; ++ case (RXH_L4_B_0_1 | RXH_L4_B_2_3): ++ hash_cfg |= TCPV6_L4_HASH_EN; ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (info->data & RXH_VLAN) ++ hash_cfg |= TCPV6_VLAN_HASH_EN; ++ else ++ hash_cfg &= ~TCPV6_VLAN_HASH_EN; ++ break; ++ case UDP_V4_FLOW: ++ switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { ++ case 0: ++ hash_cfg &= ~UDPV4_L4_HASH_EN; ++ break; ++ case (RXH_L4_B_0_1 | RXH_L4_B_2_3): ++ hash_cfg |= UDPV4_L4_HASH_EN; ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (info->data & RXH_VLAN) ++ hash_cfg |= UDPV4_VLAN_HASH_EN; ++ else ++ hash_cfg &= ~UDPV4_VLAN_HASH_EN; ++ break; ++ case UDP_V6_FLOW: ++ switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { ++ case 0: ++ hash_cfg &= ~UDPV6_L4_HASH_EN; ++ break; ++ case (RXH_L4_B_0_1 | RXH_L4_B_2_3): ++ hash_cfg |= UDPV6_L4_HASH_EN; ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (info->data & RXH_VLAN) ++ hash_cfg |= UDPV6_VLAN_HASH_EN; ++ else ++ hash_cfg &= ~UDPV6_VLAN_HASH_EN; ++ break; ++ case IPV4_FLOW: ++ if (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) ++ return -EINVAL; ++ if (info->data & RXH_VLAN) ++ hash_cfg |= IPV4_VLAN_HASH_EN; ++ else ++ hash_cfg &= ~IPV4_VLAN_HASH_EN; ++ break; ++ case IPV6_FLOW: ++ if (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) ++ return -EINVAL; ++ if (info->data & RXH_VLAN) ++ hash_cfg |= IPV6_VLAN_HASH_EN; ++ else ++ hash_cfg &= ~IPV6_VLAN_HASH_EN; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ priv->rss_info.hash_cfg = hash_cfg; ++ higmac_config_hash_policy(priv); ++ ++ return 0; ++} ++ ++static int higmac_set_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *info) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ ++ switch (info->cmd) { ++ case ETHTOOL_SRXFH: ++ return higmac_set_rss_hash_opts(priv, info); ++ default: ++ break; ++ } ++ return -EOPNOTSUPP; ++} ++ ++static const struct ethtool_ops hieth_ethtools_ops = { ++ .get_drvinfo = higmac_get_drvinfo, ++ .get_link = higmac_get_link, ++ .get_settings = higmac_get_settings, ++ .set_settings = higmac_set_settings, ++ .get_pauseparam = higmac_get_pauseparam, ++ .set_pauseparam = higmac_set_pauseparam, ++ .get_msglevel = higmac_ethtool_getmsglevel, ++ .set_msglevel = higmac_ethtool_setmsglevel, ++ .get_rxfh_key_size = higmac_get_rxfh_key_size, ++ .get_rxfh_indir_size = higmac_get_rxfh_indir_size, ++ .get_rxfh = higmac_get_rxfh, ++ .set_rxfh = higmac_set_rxfh, ++ .get_rxnfc = higmac_get_rxnfc, ++ .set_rxnfc = higmac_set_rxnfc, ++}; ++ ++static const struct net_device_ops hieth_netdev_ops = { ++ .ndo_open = higmac_net_open, ++ .ndo_stop = higmac_net_close, ++ .ndo_start_xmit = higmac_net_xmit, ++ .ndo_tx_timeout = higmac_net_timeout, ++ .ndo_set_rx_mode = higmac_set_multicast_list, ++ .ndo_set_features = higmac_set_features, ++ .ndo_do_ioctl = higmac_ioctl, ++ .ndo_set_mac_address = higmac_net_set_mac_address, ++ .ndo_change_mtu = eth_change_mtu, ++ .ndo_get_stats = higmac_net_get_stats, ++}; ++ ++static int higmac_of_get_param(struct higmac_netdev_local *ld, ++ struct device_node *node) ++{ ++ /* get auto eee */ ++ ld->autoeee = of_property_read_bool(node, "autoeee"); ++ /* get internal flag */ ++ ld->internal_phy = ++ of_property_read_bool(node, "internal-phy"); ++ ++ return 0; ++} ++ ++static int KSZ8051MNL_phy_fix(struct phy_device *phy_dev) ++{ ++ u32 v; ++ int ret; ++ ++ if (phy_dev->interface != PHY_INTERFACE_MODE_RMII) ++ return 0; ++ ++ ret = phy_read(phy_dev, 0x1F); ++ if (ret < 0) ++ return ret; ++ v = ret; ++ v |= (1 << 7); /* set phy RMII 50MHz clk; */ ++ phy_write(phy_dev, 0x1F, v); ++ ++ ret = phy_read(phy_dev, 0x16); ++ if (ret < 0) ++ return ret; ++ v = ret; ++ v |= (1 << 1); /* set phy RMII override; */ ++ phy_write(phy_dev, 0x16, v); ++ ++ return 0; ++} ++ ++static int KSZ8081RNB_phy_fix(struct phy_device *phy_dev) ++{ ++ u32 v; ++ int ret; ++ ++ if (phy_dev->interface != PHY_INTERFACE_MODE_RMII) ++ return 0; ++ ++ ret = phy_read(phy_dev, 0x1F); ++ if (ret < 0) ++ return ret; ++ v = ret; ++ v |= (1 << 7); /* set phy RMII 50MHz clk; */ ++ phy_write(phy_dev, 0x1F, v); ++ ++ return 0; ++} ++ ++static int rtl8211e_phy_fix(struct phy_device *phy_dev) ++{ ++ u32 v; ++ int ret; ++ ++ /* select Extension page */ ++ phy_write(phy_dev, 0x1f, 0x7); ++ /* switch ExtPage 164 */ ++ phy_write(phy_dev, 0x1e, 0xa4); ++ ++ /* config RGMII rx pin io driver max */ ++ ret = phy_read(phy_dev, 0x1c); ++ if (ret < 0) ++ return ret; ++ v = ret; ++ v = (v & 0xff03) | 0xfc; ++ phy_write(phy_dev, 0x1c, v); ++ ++ /* select to page 0 */ ++ phy_write(phy_dev, 0x1f, 0); ++ ++ return 0; ++} ++ ++static void phy_register_fixups(void) ++{ ++ phy_register_fixup_for_uid(PHY_ID_KSZ8051MNL, DEFAULT_PHY_MASK, ++ KSZ8051MNL_phy_fix); ++ phy_register_fixup_for_uid(PHY_ID_KSZ8081RNB, DEFAULT_PHY_MASK, ++ KSZ8081RNB_phy_fix); ++ phy_register_fixup_for_uid(REALTEK_PHY_ID_8211E, REALTEK_PHY_MASK, ++ rtl8211e_phy_fix); ++} ++ ++static void phy_unregister_fixups(void) ++{ ++ phy_unregister_fixup_for_uid(PHY_ID_KSZ8051MNL, DEFAULT_PHY_MASK); ++ phy_unregister_fixup_for_uid(PHY_ID_KSZ8081RNB, DEFAULT_PHY_MASK); ++ phy_unregister_fixup_for_uid(REALTEK_PHY_ID_8211E, REALTEK_PHY_MASK); ++} ++ ++static void higmac_verify_flow_ctrl_args(void) ++{ ++#if defined(CONFIG_TX_FLOW_CTRL_SUPPORT) ++ flow_ctrl_en |= FLOW_TX; ++#endif ++#if defined(CONFIG_RX_FLOW_CTRL_SUPPORT) ++ flow_ctrl_en |= FLOW_RX; ++#endif ++ if (tx_flow_ctrl_active_threshold < FC_ACTIVE_MIN || ++ tx_flow_ctrl_active_threshold > FC_ACTIVE_MAX) ++ tx_flow_ctrl_active_threshold = FC_ACTIVE_DEFAULT; ++ ++ if (tx_flow_ctrl_deactive_threshold < FC_DEACTIVE_MIN || ++ tx_flow_ctrl_deactive_threshold > FC_DEACTIVE_MAX) ++ tx_flow_ctrl_deactive_threshold = FC_DEACTIVE_DEFAULT; ++ ++ if (tx_flow_ctrl_active_threshold >= tx_flow_ctrl_deactive_threshold) { ++ tx_flow_ctrl_active_threshold = FC_ACTIVE_DEFAULT; ++ tx_flow_ctrl_deactive_threshold = FC_DEACTIVE_DEFAULT; ++ } ++ ++ if (tx_flow_ctrl_pause_time < 0 || ++ tx_flow_ctrl_pause_time > FC_PAUSE_TIME_MAX) ++ tx_flow_ctrl_pause_time = FC_PAUSE_TIME_DEFAULT; ++ ++ if (tx_flow_ctrl_pause_interval < 0 || ++ tx_flow_ctrl_pause_interval > FC_PAUSE_TIME_MAX) ++ tx_flow_ctrl_pause_interval = FC_PAUSE_INTERVAL_DEFAULT; ++ ++ /* pause interval should not bigger than pause time, ++ * but should not too smaller to avoid sending too many pause frame. ++ */ ++ if ((tx_flow_ctrl_pause_interval > tx_flow_ctrl_pause_time) || ++ (tx_flow_ctrl_pause_interval < (tx_flow_ctrl_pause_time >> 1))) ++ tx_flow_ctrl_pause_interval = tx_flow_ctrl_pause_time; ++} ++ ++static void higmac_destroy_hw_desc_queue(struct higmac_netdev_local *priv) ++{ ++ int i; ++ ++ for (i = 0; i < QUEUE_NUMS + RSS_NUM_RXQS - 1; i++) { ++ if (priv->pool[i].desc) { ++ if (HAS_CAP_CCI(priv->hw_cap)) ++ kfree(priv->pool[i].desc); ++ else ++ dma_free_coherent(priv->dev, priv->pool[i].size, ++ priv->pool[i].desc, ++ priv->pool[i].phys_addr); ++ priv->pool[i].desc = NULL; ++ } ++ } ++ ++ kfree(priv->rx_fq.skb); ++ kfree(priv->tx_bq.skb); ++ priv->rx_fq.skb = NULL; ++ priv->tx_bq.skb = NULL; ++ ++ if (priv->tso_supported) { ++ kfree(priv->tx_bq.sg_desc_offset); ++ priv->tx_bq.sg_desc_offset = NULL; ++ } ++ ++ kfree(priv->tx_skb); ++ priv->tx_skb = NULL; ++ ++ kfree(priv->rx_skb); ++ priv->rx_skb = NULL; ++} ++ ++static int higmac_init_hw_desc_queue(struct higmac_netdev_local *priv) ++{ ++ struct device *dev = priv->dev; ++ struct higmac_desc *virt_addr; ++ dma_addr_t phys_addr = 0; ++ int size, i; ++ ++ priv->rx_fq.count = RX_DESC_NUM; ++ priv->rx_bq.count = RX_DESC_NUM; ++ priv->tx_bq.count = TX_DESC_NUM; ++ priv->tx_rq.count = TX_DESC_NUM; ++ ++ for (i = 1; i < RSS_NUM_RXQS; i++) ++ priv->pool[3 + i].count = RX_DESC_NUM; ++ ++ for (i = 0; i < (QUEUE_NUMS + RSS_NUM_RXQS - 1); i++) { ++ size = priv->pool[i].count * sizeof(struct higmac_desc); ++ if (HAS_CAP_CCI(priv->hw_cap)) { ++ virt_addr = kmalloc(size, GFP_KERNEL); ++ if (virt_addr) ++ phys_addr = virt_to_phys(virt_addr); ++ } else { ++ virt_addr = dma_alloc_coherent(dev, size, &phys_addr, ++ GFP_KERNEL); ++ } ++ if (!virt_addr) ++ goto error_free_pool; ++ ++ memset(virt_addr, 0, size); ++ priv->pool[i].size = size; ++ priv->pool[i].desc = virt_addr; ++ priv->pool[i].phys_addr = phys_addr; ++ } ++ priv->rx_fq.skb = kzalloc(priv->rx_fq.count ++ * sizeof(struct sk_buff *), GFP_KERNEL); ++ if (!priv->rx_fq.skb) ++ goto error_free_pool; ++ ++ priv->rx_skb = kzalloc(priv->rx_fq.count ++ * sizeof(struct sk_buff *), GFP_KERNEL); ++ if (!priv->rx_skb) ++ goto error_free_pool; ++ ++ priv->tx_bq.skb = kzalloc(priv->tx_bq.count ++ * sizeof(struct sk_buff *), GFP_KERNEL); ++ if (!priv->tx_bq.skb) ++ goto error_free_pool; ++ ++ priv->tx_skb = kzalloc(priv->tx_bq.count ++ * sizeof(struct sk_buff *), GFP_KERNEL); ++ if (!priv->tx_skb) ++ goto error_free_pool; ++ ++ if (priv->tso_supported) { ++ priv->tx_bq.sg_desc_offset = kzalloc(priv->tx_bq.count ++ * sizeof(int), GFP_KERNEL); ++ if (!priv->tx_bq.sg_desc_offset) ++ goto error_free_pool; ++ } ++ ++ higmac_hw_set_desc_addr(priv); ++ if (HAS_CAP_CCI(priv->hw_cap)) ++ pr_info("higmac: ETH MAC supporte CCI.\n"); ++ ++ return 0; ++ ++error_free_pool: ++ higmac_destroy_hw_desc_queue(priv); ++ ++ return -ENOMEM; ++} ++ ++void higmac_init_napi(struct higmac_netdev_local *priv) ++{ ++ struct higmac_napi *q_napi; ++ int i; ++ ++ for (i = 0; i < priv->num_rxqs; i++) { ++ q_napi = &priv->q_napi[i]; ++ q_napi->rxq_id = i; ++ q_napi->ndev_priv = priv; ++ netif_napi_add(priv->netdev, &q_napi->napi, higmac_poll, ++ NAPI_POLL_WEIGHT); ++ } ++} ++ ++void higmac_destroy_napi(struct higmac_netdev_local *priv) ++{ ++ struct higmac_napi *q_napi; ++ int i; ++ ++ for (i = 0; i < priv->num_rxqs; i++) { ++ q_napi = &priv->q_napi[i]; ++ netif_napi_del(&q_napi->napi); ++ } ++} ++ ++int higmac_request_irqs(struct platform_device *pdev, ++ struct higmac_netdev_local *priv) ++{ ++ struct device *dev = priv->dev; ++ int ret; ++ int i; ++ ++ for (i = 0; i < priv->num_rxqs; i++) { ++ ret = platform_get_irq(pdev, i); ++ if (ret < 0) { ++ dev_err(dev, "No irq[%d] resource, ret=%d\n", i, ret); ++ return ret; ++ } ++ priv->irq[i] = ret; ++ ++ ret = devm_request_irq(dev, priv->irq[i], higmac_interrupt, ++ IRQF_SHARED, pdev->name, ++ &priv->q_napi[i]); ++ if (ret) { ++ dev_err(dev, "devm_request_irq failed, ret=%d\n", ret); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static int higmac_dev_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *node = dev->of_node; ++ struct net_device *ndev; ++ struct higmac_netdev_local *priv; ++ struct resource *res; ++ const char *mac_addr; ++ unsigned int hw_cap; ++ int ret; ++ int num_rxqs; ++ ++ higmac_verify_flow_ctrl_args(); ++ ++ if (of_device_is_compatible(node, "hisilicon,higmac-v5")) ++ num_rxqs = RSS_NUM_RXQS; ++ else ++ num_rxqs = 1; ++ ++ ndev = alloc_etherdev_mqs(sizeof(struct higmac_netdev_local), 1, ++ num_rxqs); ++ if (!ndev) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, ndev); ++ SET_NETDEV_DEV(ndev, dev); ++ ++ priv = netdev_priv(ndev); ++ priv->dev = dev; ++ priv->netdev = ndev; ++ priv->num_rxqs = num_rxqs; ++ ++ if (of_device_is_compatible(node, "hisilicon,higmac-v3")) ++ priv->hw_cap |= HW_CAP_CCI; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, MEM_GMAC_IOBASE); ++ priv->gmac_iobase = devm_ioremap_resource(dev, res); ++ if (IS_ERR(priv->gmac_iobase)) { ++ ret = PTR_ERR(priv->gmac_iobase); ++ goto out_free_netdev; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, ++ MEM_MACIF_IOBASE); ++ priv->macif_base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(priv->macif_base)) { ++ ret = PTR_ERR(priv->macif_base); ++ goto out_free_netdev; ++ } ++ ++ priv->port_rst = devm_reset_control_get(dev, HIGMAC_PORT_RST_NAME); ++ if (IS_ERR(priv->port_rst)) { ++ ret = PTR_ERR(priv->port_rst); ++ goto out_free_netdev; ++ } ++ ++ priv->macif_rst = devm_reset_control_get(dev, HIGMAC_MACIF_RST_NAME); ++ if (IS_ERR(priv->macif_rst)) { ++ ret = PTR_ERR(priv->macif_rst); ++ goto out_free_netdev; ++ } ++ ++ priv->phy_rst = devm_reset_control_get(dev, HIGMAC_PHY_RST_NAME); ++ if (IS_ERR(priv->phy_rst)) ++ priv->phy_rst = NULL; ++ ++ priv->clk = devm_clk_get(&pdev->dev, HIGMAC_MAC_CLK_NAME); ++ if (IS_ERR(priv->clk)) { ++ netdev_err(ndev, "failed to get clk\n"); ++ ret = -ENODEV; ++ goto out_free_netdev; ++ } ++ ++ ret = clk_prepare_enable(priv->clk); ++ if (ret < 0) { ++ netdev_err(ndev, "failed to enable clk %d\n", ret); ++ goto out_free_netdev; ++ } ++ ++ priv->macif_clk = devm_clk_get(&pdev->dev, HIGMAC_MACIF_CLK_NAME); ++ if (IS_ERR(priv->macif_clk)) ++ priv->macif_clk = NULL; ++ ++ if (priv->macif_clk) { ++ ret = clk_prepare_enable(priv->macif_clk); ++ if (ret < 0) { ++ netdev_err(ndev, "failed enable macif_clk %d\n", ret); ++ goto out_clk_disable; ++ } ++ } ++ ++ higmac_mac_core_reset(priv); ++ ++ /* phy reset, should be early than "of_mdiobus_register". ++ * becausue "of_mdiobus_register" will read PHY register by MDIO. ++ */ ++ higmac_hw_phy_reset(priv); ++ ++ higmac_of_get_param(priv, node); ++ ++ ret = of_get_phy_mode(node); ++ if (ret < 0) { ++ netdev_err(ndev, "not find phy-mode\n"); ++ goto out_macif_clk_disable; ++ } ++ priv->phy_mode = ret; ++ ++ priv->phy_node = of_parse_phandle(node, "phy-handle", 0); ++ if (!priv->phy_node) { ++ netdev_err(ndev, "not find phy-handle\n"); ++ ret = -EINVAL; ++ goto out_macif_clk_disable; ++ } ++ ++ mac_addr = of_get_mac_address(node); ++ if (mac_addr) ++ ether_addr_copy(ndev->dev_addr, mac_addr); ++ if (!is_valid_ether_addr(ndev->dev_addr)) { ++ eth_hw_addr_random(ndev); ++ netdev_warn(ndev, "using random MAC address %pM\n", ++ ndev->dev_addr); ++ } ++ ++ higmac_hw_set_mac_addr(ndev); ++ ++ hw_cap = readl(priv->gmac_iobase + CRF_MIN_PACKET); ++ priv->tso_supported = HAS_TSO_CAP(hw_cap); ++ priv->has_rxhash_cap = HAS_RXHASH_CAP(hw_cap); ++ priv->has_rss_cap = HAS_RSS_CAP(hw_cap); ++ ++ higmac_set_rss_cap(priv); ++ higmac_get_rss_key(priv); ++ if (priv->has_rss_cap) { ++ priv->rss_info.ind_tbl_size = RSS_INDIRECTION_TABLE_SIZE; ++ higmac_get_rss(priv); ++ } ++ ++ if (priv->has_rxhash_cap) { ++ priv->rss_info.hash_cfg = DEF_HASH_CFG; ++ higmac_config_hash_policy(priv); ++ } ++ ++ /* init hw controller */ ++ higmac_hw_init(priv); ++ ++ /* TODO: phy fix here?? other way ??? */ ++ phy_register_fixups(); ++ ++ priv->phy = of_phy_connect(ndev, priv->phy_node, ++ &higmac_adjust_link, 0, priv->phy_mode); ++ if (!priv->phy) { ++ ret = -ENODEV; ++ goto out_phy_node; ++ } ++ ++ /* If the phy_id is mostly Fs, there is no device there */ ++ if ((priv->phy->phy_id & 0x1fffffff) == 0x1fffffff || ++ priv->phy->phy_id == 0) { ++ pr_info("phy %d not found\n", priv->phy->addr); ++ ret = -ENODEV; ++ goto out_phy_disconnect; ++ } ++ ++ pr_info("attached PHY %d to driver %s, PHY_ID=0x%x\n", ++ priv->phy->addr, priv->phy->drv->name, priv->phy->phy_id); ++ ++ /* Stop Advertising 1000BASE Capability if interface is not RGMII */ ++ if ((priv->phy_mode == PHY_INTERFACE_MODE_MII) || ++ (priv->phy_mode == PHY_INTERFACE_MODE_RMII)) { ++ priv->phy->advertising &= ~(SUPPORTED_1000baseT_Half | ++ SUPPORTED_1000baseT_Full); ++ ++ /* Internal FE phy's reg BMSR bit8 is wrong, make the kernel ++ * believe it has the 1000base Capability, so fix it here ++ */ ++ if (priv->phy->phy_id == HISILICON_PHY_ID_FESTAV200) ++ priv->phy->supported &= ~(ADVERTISED_1000baseT_Full | ++ ADVERTISED_1000baseT_Half); ++ } ++ ++ higmac_set_flow_ctrl_args(priv); ++ higmac_set_flow_ctrl_params(priv); ++ priv->phy->supported |= SUPPORTED_Pause; ++ if (priv->flow_ctrl) ++ priv->phy->advertising |= SUPPORTED_Pause; ++ ++ if (priv->autoeee) ++ init_autoeee(priv); ++ ++ ret = higmac_request_irqs(pdev, priv); ++ if (ret) ++ goto out_phy_disconnect; ++ ++ higmac_init_napi(priv); ++ spin_lock_init(&priv->rxlock); ++ spin_lock_init(&priv->txlock); ++ spin_lock_init(&priv->pmtlock); ++ ++ /* init netdevice */ ++ ndev->irq = priv->irq[0]; ++ ndev->watchdog_timeo = 3 * HZ; ++ ndev->netdev_ops = &hieth_netdev_ops; ++ ndev->ethtool_ops = &hieth_ethtools_ops; ++ ++ if (priv->has_rxhash_cap) ++ ndev->hw_features |= NETIF_F_RXHASH; ++ if (priv->has_rss_cap) ++ ndev->hw_features |= NETIF_F_NTUPLE; ++ if (priv->tso_supported) { ++ ndev->hw_features |= NETIF_F_SG | ++ NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | ++ NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO; ++ } ++#if defined(CONFIG_HIGMAC_RXCSUM) ++ ndev->hw_features |= NETIF_F_RXCSUM; ++ higmac_enable_rxcsum_drop(priv, true); ++#endif ++ ++ ndev->features |= ndev->hw_features; ++ ndev->features |= NETIF_F_HIGHDMA | NETIF_F_GSO; ++ ndev->vlan_features |= ndev->features; ++ ++ init_timer(&priv->monitor); ++ priv->monitor.function = higmac_monitor_func; ++ priv->monitor.data = (unsigned long)ndev; ++ priv->monitor.expires = jiffies + HIGMAC_MONITOR_TIMER; ++ ++ device_set_wakeup_capable(priv->dev, 1); ++ /* TODO: when we can let phy powerdown? ++ * In some mode, we don't want phy powerdown, ++ * so I set wakeup enable all the time ++ */ ++ device_set_wakeup_enable(priv->dev, 1); ++ ++ priv->wol_enable = false; ++ ++ priv->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); ++ ++ /* init hw desc queue */ ++ ret = higmac_init_hw_desc_queue(priv); ++ if (ret) ++ goto _error_hw_desc_queue; ++ ++ if (priv->tso_supported) { ++ ret = higmac_init_sg_desc_queue(priv); ++ if (ret) ++ goto _error_sg_desc_queue; ++ } ++ ++ /* register netdevice */ ++ ret = register_netdev(priv->netdev); ++ if (ret) { ++ pr_err("register_ndev failed!"); ++ goto _error_sg_desc_queue; ++ } ++ ++ /* reset queue here to make BQL only reset once. ++ * if we put netdev_reset_queue() in higmac_net_open(), ++ * the BQL will be reset when ifconfig eth0 down and up, ++ * but the tx ring is not cleared before. ++ * As a result, the NAPI poll will call netdev_completed_queue() ++ * and BQL throw a bug. ++ */ ++ netdev_reset_queue(ndev); ++ ++ clk_disable_unprepare(priv->clk); ++ if (priv->macif_clk) ++ clk_disable_unprepare(priv->macif_clk); ++ ++ pr_info("ETH: %s, phy_addr=%d\n", ++ phy_modes(priv->phy_mode), priv->phy->addr); ++ ++ return ret; ++ ++_error_sg_desc_queue: ++ if (priv->tso_supported) ++ higmac_destroy_sg_desc_queue(priv); ++ ++_error_hw_desc_queue: ++ higmac_destroy_hw_desc_queue(priv); ++ higmac_destroy_napi(priv); ++out_phy_disconnect: ++ phy_disconnect(priv->phy); ++out_phy_node: ++ of_node_put(priv->phy_node); ++out_macif_clk_disable: ++ if (priv->macif_clk) ++ clk_disable_unprepare(priv->macif_clk); ++out_clk_disable: ++ clk_disable_unprepare(priv->clk); ++out_free_netdev: ++ free_netdev(ndev); ++ ++ return ret; ++} ++ ++static int higmac_dev_remove(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ ++ /* TODO: stop the gmac and free all resource */ ++ del_timer_sync(&priv->monitor); ++ higmac_destroy_napi(priv); ++ ++ unregister_netdev(ndev); ++ ++ higmac_reclaim_rx_tx_resource(priv); ++ higmac_free_rx_skb(priv); ++ higmac_free_tx_skb(priv); ++ ++ if (priv->tso_supported) ++ higmac_destroy_sg_desc_queue(priv); ++ higmac_destroy_hw_desc_queue(priv); ++ ++ phy_disconnect(priv->phy); ++ of_node_put(priv->phy_node); ++ ++ free_netdev(ndev); ++ ++ phy_unregister_fixups(); ++ ++ return 0; ++} ++ ++#include "pm.c" ++#ifdef CONFIG_PM ++ ++static void higmac_disable_irq(struct higmac_netdev_local *priv) ++{ ++ int i; ++ ++ for (i = 0; i < priv->num_rxqs; i++) ++ disable_irq(priv->irq[i]); ++} ++ ++static void higmac_enable_irq(struct higmac_netdev_local *priv) ++{ ++ int i; ++ ++ for (i = 0; i < priv->num_rxqs; i++) ++ enable_irq(priv->irq[i]); ++} ++ ++int higmac_dev_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ ++ higmac_disable_irq(priv); ++ /* If support Wake on LAN, we should not disconnect phy ++ * because it will call phy_suspend to power down phy. ++ */ ++ if (!priv->wol_enable) ++ phy_disconnect(priv->phy); ++ del_timer_sync(&priv->monitor); ++ /* If suspend when netif is not up, the napi_disable will run into ++ * dead loop and dpm_drv_timeout will give warning. ++ */ ++ if (netif_running(ndev)) ++ higmac_disable_napi(priv); ++ netif_device_detach(ndev); ++ ++ netif_carrier_off(ndev); ++ ++ /* If netdev is down, MAC clock is disabled. ++ * So if we want to reclaim MAC rx and tx resource, ++ * we must first enable MAC clock and then disable it. ++ */ ++ if (!(ndev->flags & IFF_UP)) ++ clk_prepare_enable(priv->clk); ++ ++ higmac_reclaim_rx_tx_resource(priv); ++ ++ if (!(ndev->flags & IFF_UP)) ++ clk_disable_unprepare(priv->clk); ++ ++ pmt_enter(priv); ++ ++ if (!priv->wol_enable) { /* if no WOL, then poweroff */ ++ /* pr_info("power off gmac.\n"); */ ++ /* no need to call genphy_resume() in resume, ++ * because we reset everything ++ */ ++ genphy_suspend(priv->phy); /* power down phy */ ++ msleep(20); ++ higmac_hw_all_clk_disable(priv); ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(higmac_dev_suspend); ++ ++int higmac_dev_resume(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ int ret = 0; ++ ++ /* If we support Wake on LAN, we doesn't call clk_disable. ++ * But when we resume, the uboot may off mac clock and reset phy ++ * by re-write the mac CRG register. ++ * So we first call clk_disable, and then clk_enable. ++ */ ++ if (priv->wol_enable) ++ higmac_hw_all_clk_disable(priv); ++ ++ higmac_hw_all_clk_enable(priv); ++ /* internal FE_PHY: enable clk and reset */ ++ higmac_hw_phy_reset(priv); ++ ++ /* If netdev is down, MAC clock is disabled. ++ * So if we want to restart MAC and re-initialize it, ++ * we must first enable MAC clock and then disable it. ++ */ ++ if (!(ndev->flags & IFF_UP)) ++ clk_prepare_enable(priv->clk); ++ ++ /* power on gmac */ ++ higmac_restart(priv); ++ ++ /* If support WoL, we didn't disconnect phy. ++ * But when we resume, we reset PHY, so we want to ++ * call phy_connect to make phy_fixup excuted. ++ * This is important for internal PHY fix. ++ */ ++ if (priv->wol_enable) ++ phy_disconnect(priv->phy); ++ ++ ret = phy_connect_direct(ndev, priv->phy, higmac_adjust_link, ++ priv->phy_mode); ++ if (ret) ++ return ret; ++ ++ /* If we suspend and resume when net device is down, ++ * some operations are unnecessary. ++ */ ++ if (ndev->flags & IFF_UP) { ++ priv->monitor.expires = jiffies + HIGMAC_MONITOR_TIMER; ++ mod_timer(&priv->monitor, priv->monitor.expires); ++ priv->old_link = 0; ++ priv->old_speed = SPEED_UNKNOWN; ++ priv->old_duplex = DUPLEX_UNKNOWN; ++ } ++ if (netif_running(ndev)) ++ higmac_enable_napi(priv); ++ netif_device_attach(ndev); ++ if (ndev->flags & IFF_UP) ++ phy_start(priv->phy); ++ higmac_enable_irq(priv); ++ ++ pmt_exit(priv); ++ ++ if (!(ndev->flags & IFF_UP)) ++ clk_disable_unprepare(priv->clk); ++ ++ return 0; ++} ++EXPORT_SYMBOL(higmac_dev_resume); ++#else ++#define higmac_dev_suspend NULL ++#define higmac_dev_resume NULL ++#endif ++ ++static const struct of_device_id higmac_of_match[] = { ++ {.compatible = "hisilicon,higmac",}, ++ {.compatible = "hisilicon,higmac-v1",}, ++ {.compatible = "hisilicon,higmac-v2",}, ++ {.compatible = "hisilicon,higmac-v3",}, ++ {.compatible = "hisilicon,higmac-v4",}, ++ {.compatible = "hisilicon,higmac-v5",}, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(of, higmac_of_match); ++ ++static struct platform_driver higmac_dev_driver = { ++ .probe = higmac_dev_probe, ++ .remove = higmac_dev_remove, ++ .suspend = higmac_dev_suspend, ++ .resume = higmac_dev_resume, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = HIGMAC_DRIVER_NAME, ++ .of_match_table = higmac_of_match, ++ }, ++}; ++ ++#include "proc-dev.c" ++ ++static int __init higmac_init(void) ++{ ++ int ret = 0; ++ ++ ret = platform_driver_register(&higmac_dev_driver); ++ if (ret) ++ return ret; ++ ++ higmac_proc_create(); ++ ++ return ret; ++} ++ ++static void __exit higmac_exit(void) ++{ ++ platform_driver_unregister(&higmac_dev_driver); ++ ++ higmac_proc_destroy(); ++} ++ ++module_init(higmac_init); ++module_exit(higmac_exit); ++ ++MODULE_AUTHOR("ZMJUN"); ++MODULE_DESCRIPTION("Hisilicon double GMAC driver, base on driver higmacv200 by CHH"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/net/ethernet/hisilicon/higmac/higmac.h b/drivers/net/ethernet/hisilicon/higmac/higmac.h +new file mode 100644 +index 0000000..df0295f +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/higmac.h +@@ -0,0 +1,615 @@ ++#ifndef __HIGMAC_H__ ++#define __HIGMAC_H__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define STATION_ADDR_LOW 0x0000 ++#define STATION_ADDR_HIGH 0x0004 ++#define MAC_DUPLEX_HALF_CTRL 0x0008 ++ ++#define PORT_MODE 0x0040 ++ ++#define PORT_EN 0x0044 ++#define BITS_TX_EN BIT(2) ++#define BITS_RX_EN BIT(1) ++ ++#define FC_TX_TIMER 0x001C ++ ++#define PAUSE_THR 0x0038 ++ ++#define PAUSE_EN 0x0048 ++#define BIT_RX_FDFC BIT(0) ++#define BIT_TX_FDFC BIT(1) ++ ++#define RX_PAUSE_EN 0x02A4 ++#define BIT_RX_FQ_PAUSE_EN BIT(0) ++#define BIT_RX_BQ_PAUSE_EN BIT(1) ++ ++#define CRF_TX_PAUSE 0x0340 ++ ++#define BITS_Q_PAUSE_TH_OFFSET 16 ++#define BITS_Q_PAUSE_TH_MASK 0xFFFF ++ ++#define REC_FILT_CONTROL 0x0064 ++#define BIT_CRC_ERR_PASS BIT(5) ++#define BIT_PAUSE_FRM_PASS BIT(4) ++#define BIT_VLAN_DROP_EN BIT(3) ++#define BIT_BC_DROP_EN BIT(2) ++#define BIT_MC_MATCH_EN BIT(1) ++#define BIT_UC_MATCH_EN BIT(0) ++ ++#define PORT_MC_ADDR_LOW 0x0068 ++#define PORT_MC_ADDR_HIGH 0x006C ++#define MAC_CLEAR 0x0070 ++#define BIT_TX_SOFT_RESET BIT(0) ++ ++#define MODE_CHANGE_EN 0x01b4 ++#define BIT_MODE_CHANGE_EN BIT(0) ++ ++#define COL_SLOT_TIME 0x01c0 ++ ++#define CRF_MIN_PACKET 0x0210 ++#define BIT_OFFSET_TX_MIN_LEN 8 ++#define BIT_MASK_TX_MIN_LEN GENMASK(13, 8) ++ ++#define CONTROL_WORD 0x0214 ++#define CONTROL_WORD_CONFIG 0x640 ++ ++#define TSO_COE_CTRL 0x02e8 ++#define BIT_COE_IPHDR_DROP BIT(4) ++#define BIT_COE_PAYLOAD_DROP BIT(5) ++#define BIT_COE_IPV6_UDP_ZERO_DROP BIT(6) ++#define COE_ERR_DROP (BIT_COE_IPHDR_DROP | \ ++ BIT_COE_PAYLOAD_DROP | \ ++ BIT_COE_IPV6_UDP_ZERO_DROP) ++ ++#define RX_FQ_START_ADDR 0x0500 ++#define RX_FQ_DEPTH 0x0504 ++#define RX_FQ_WR_ADDR 0x0508 ++#define BITS_RX_FQ_WR_ADDR MK_BITS(0, 21) ++#define RX_FQ_RD_ADDR 0x050c ++#define BITS_RX_FQ_RD_ADDR MK_BITS(0, 21) ++#define RX_FQ_VLDDESC_CNT 0x0510 ++#define BITS_RX_FQ_VLDDESC_CNT MK_BITS(0, 16) ++#define RX_FQ_ALEMPTY_TH 0x0514 ++#define BITS_RX_FQ_ALEMPTY_TH MK_BITS(0, 16) ++#define RX_FQ_REG_EN 0x0518 ++#define BITS_RX_FQ_START_ADDR_EN BIT(2) ++#define BITS_RX_FQ_DEPTH_EN BIT(1) ++#define BITS_RX_FQ_RD_ADDR_EN MK_BITS(0, 1) ++#define RX_FQ_ALFULL_TH 0x051c ++#define BITS_RX_FQ_ALFULL_TH MK_BITS(0, 16) ++ ++#define RX_BQ_START_ADDR 0x0520 ++#define RX_BQ_DEPTH 0x0524 ++#define RX_BQ_WR_ADDR 0x0528 ++#define RX_BQ_RD_ADDR 0x052c ++#define RX_BQ_FREE_DESC_CNT 0x0530 ++#define BITS_RX_BQ_FREE_DESC_CNT MK_BITS(0, 16) ++#define RX_BQ_ALEMPTY_TH 0x0534 ++#define BITS_RX_BQ_ALEMPTY_TH MK_BITS(0, 16) ++#define RX_BQ_REG_EN 0x0538 ++#define BITS_RX_BQ_START_ADDR_EN BIT(2) ++#define BITS_RX_BQ_DEPTH_EN BIT(1) ++#define BITS_RX_BQ_WR_ADDR_EN MK_BITS(0, 1) ++#define RX_BQ_ALFULL_TH 0x053c ++#define BITS_RX_BQ_ALFULL_TH MK_BITS(0, 16) ++ ++#define TX_BQ_START_ADDR 0x0580 ++#define TX_BQ_DEPTH 0x0584 ++#define TX_BQ_WR_ADDR 0x0588 ++#define BITS_TX_BQ_WR_ADDR MK_BITS(0, 21) ++#define TX_BQ_RD_ADDR 0x058c ++#define BITS_TX_BQ_RD_ADDR MK_BITS(0, 21) ++#define TX_BQ_VLDDESC_CNT 0x0590 ++#define BITS_TX_BQ_VLDDESC_CNT MK_BITS(0, 16) ++#define TX_BQ_ALEMPTY_TH 0x0594 ++#define BITS_TX_BQ_ALEMPTY_TH MK_BITS(0, 16) ++#define TX_BQ_REG_EN 0x0598 ++#define BITS_TX_BQ_START_ADDR_EN BIT(2) ++#define BITS_TX_BQ_DEPTH_EN BIT(1) ++#define BITS_TX_BQ_RD_ADDR_EN MK_BITS(0, 1) ++#define TX_BQ_ALFULL_TH 0x059c ++#define BITS_TX_BQ_ALFULL_TH MK_BITS(0, 16) ++ ++#define TX_RQ_START_ADDR 0x05a0 ++#define TX_RQ_DEPTH 0x05a4 ++#define TX_RQ_WR_ADDR 0x05a8 ++#define BITS_TX_RQ_WR_ADDR MK_BITS(0, 21) ++#define TX_RQ_RD_ADDR 0x05ac ++#define BITS_TX_RQ_RD_ADDR MK_BITS(0, 21) ++#define TX_RQ_FREE_DESC_CNT 0x05b0 ++#define BITS_TX_RQ_FREE_DESC_CNT MK_BITS(0, 16) ++#define TX_RQ_ALEMPTY_TH 0x05b4 ++#define BITS_TX_RQ_ALEMPTY_TH MK_BITS(0, 16) ++#define TX_RQ_REG_EN 0x05b8 ++#define BITS_TX_RQ_START_ADDR_EN BIT(2) ++#define BITS_TX_RQ_DEPTH_EN BIT(1) ++#define BITS_TX_RQ_WR_ADDR_EN MK_BITS(0, 1) ++#define TX_RQ_ALFULL_TH 0x05bc ++#define BITS_TX_RQ_ALFULL_TH MK_BITS(0, 16) ++ ++#define RAW_PMU_INT 0x05c0 ++#define ENA_PMU_INT 0x05c4 ++ ++#define DESC_WR_RD_ENA 0x05CC ++ ++#define IN_QUEUE_TH 0x05d8 ++#define BITS_OFFSET_TX_RQ_IN_TH 16 ++ ++#define RX_BQ_IN_TIMEOUT_TH 0x05E0 ++ ++#define TX_RQ_IN_TIMEOUT_TH 0x05e4 ++ ++#define STOP_CMD 0x05e8 ++#define BITS_TX_STOP_EN BIT(1) ++#define BITS_RX_STOP_EN BIT(0) ++#define STOP_RX_TX (BITS_TX_STOP_EN | BITS_RX_STOP_EN) ++ ++#define HW_CAP_EN 0x0c00 ++#define BIT_RSS_CAP BIT(0) ++#define BIT_RXHASH_CAP BIT(1) ++#define RSS_HASH_KEY 0x0c04 ++#define RSS_HASH_CONFIG 0x0c08 ++#define TCPV4_L3_HASH_EN BIT(0) ++#define TCPV4_L4_HASH_EN BIT(1) ++#define TCPV4_VLAN_HASH_EN BIT(2) ++#define UDPV4_L3_HASH_EN BIT(4) ++#define UDPV4_L4_HASH_EN BIT(5) ++#define UDPV4_VLAN_HASH_EN BIT(6) ++#define IPV4_L3_HASH_EN BIT(8) ++#define IPV4_VLAN_HASH_EN BIT(9) ++#define TCPV6_L3_HASH_EN BIT(12) ++#define TCPV6_L4_HASH_EN BIT(13) ++#define TCPV6_VLAN_HASH_EN BIT(14) ++#define UDPV6_L3_HASH_EN BIT(16) ++#define UDPV6_L4_HASH_EN BIT(17) ++#define UDPV6_VLAN_HASH_EN BIT(18) ++#define IPV6_L3_HASH_EN BIT(20) ++#define IPV6_VLAN_HASH_EN BIT(21) ++#define DEF_HASH_CFG 0x377377 ++ ++#define RSS_IND_TBL 0x0c0c ++#define BIT_IND_TBL_READY BIT(13) ++#define BIT_IND_TLB_WR BIT(12) ++#define RSS_RAW_PMU_INT 0x0c10 ++#define RSS_QUEUE1_START_ADDR 0x0c20 ++#define RX_BQ_START_ADDR_QUEUE(i) (RSS_QUEUE1_START_ADDR + \ ++ ((i) - 1) * 0x10) ++#define RSS_QUEUE1_DEPTH 0x0c24 ++#define RX_BQ_WR_ADDR_QUEUE1 0x0c28 ++#define RX_BQ_RD_ADDR_QUEUE1 0x0c2c ++#define RSS_QUEUE1_ENA_INT 0x0c90 ++#define RSS_ENA_INT_QUEUE(i) (RSS_QUEUE1_ENA_INT + ((i) - 1) * 0x4) ++#define RX_BQ_DEPTH_QUEUE(i) (RSS_QUEUE1_DEPTH + ((i) - 1) * 0x10) ++#define RX_BQ_WR_ADDR_QUEUE(i) ((i) ? (RX_BQ_WR_ADDR_QUEUE1 + \ ++ ((i) - 1) * 0x10) : RX_BQ_WR_ADDR) ++#define RX_BQ_RD_ADDR_QUEUE(i) ((i) ? (RX_BQ_RD_ADDR_QUEUE1 + \ ++ ((i) - 1) * 0x10) : RX_BQ_RD_ADDR) ++ ++#define DEF_INT_MASK_QUEUE(i) (0x3 << (2 * ((i) - 1))) ++ ++/* AXI burst and outstanding config */ ++#define BURST_OUTSTANDING_REG 0x3014 ++#define BURST4_OUTSTANDING1 0x81ff ++#define BURST_OUTSTANDING_OFFSET 16 ++ ++#define GMAC_SPEED_1000 0x05 ++#define GMAC_SPEED_100 0x01 ++#define GMAC_SPEED_10 0x00 ++ ++enum higmac_tx_err { ++ ERR_NONE = 0, ++ ERR_DESC_CFG = (1 << 0), ++ ERR_DATA_LEN = (1 << 1), ++ ERR_DESC_NFRAG_NUM = (1 << 2), ++ ERR_DESC_IP_HDR_LEN = (1 << 3), ++ ERR_DESC_PROT_HDR_LEN = (1 << 4), ++ ERR_DESC_MTU = (1 << 5), ++ ERR_LINK_SGPKT_LEN = (1 << 8), ++ ERR_LINK_TSOPKT_LINEAR = (1 << 9), ++ ERR_LINK_NFRAG_LEN = (1 << 10), ++ ERR_LINK_TOTAL_LEN = (1 << 11), ++ ERR_HDR_TCP_BCMC = (1 << 12), ++ ERR_HDR_UDP_BC = (1 << 13), ++ ERR_HDR_VLAN_IP_TYPE = (1 << 14), ++ ERR_HDR_IP_TYPE = (1 << 15), ++ ERR_HDR_IP_VERSION = (1 << 16), ++ ERR_HDR_IP_HDR_LEN = (1 << 17), ++ ERR_HDR_IP_TOTAL_LEN = (1 << 18), ++ ERR_HDR_IPV6_TTL_PROT = (1 << 19), ++ ERR_HDR_IPV4_OFFSET = (1 << 20), ++ ERR_HDR_IPV4_TTL_PROT = (1 << 21), ++ ERR_HDR_UDP_LEN = (1 << 22), ++ ERR_HDR_TCP_LEN = (1 << 23), ++ ERR_DESC = (ERR_DESC_CFG | ERR_DATA_LEN | ++ ERR_DESC_NFRAG_NUM | ERR_DESC_IP_HDR_LEN | ++ ERR_DESC_PROT_HDR_LEN | ERR_DESC_MTU), ++ ERR_LINK = (ERR_LINK_SGPKT_LEN | ERR_LINK_TSOPKT_LINEAR | ++ ERR_LINK_NFRAG_LEN | ERR_LINK_TOTAL_LEN), ++ ERR_HDR = (ERR_HDR_TCP_BCMC | ERR_HDR_UDP_BC | ++ ERR_HDR_VLAN_IP_TYPE | ERR_HDR_IP_TYPE | ++ ERR_HDR_IP_VERSION | ERR_HDR_IP_HDR_LEN | ++ ERR_HDR_IP_TOTAL_LEN | ERR_HDR_IPV6_TTL_PROT | ++ ERR_HDR_IPV4_OFFSET | ERR_HDR_IPV4_TTL_PROT | ++ ERR_HDR_UDP_LEN | ERR_HDR_TCP_LEN), ++ ERR_ALL = (ERR_DESC | ERR_LINK | ERR_HDR), ++}; ++ ++#define HIGMAC_DRIVER_NAME "hi_gmac_v200" ++ ++#define HIGMAC_MAC_CLK_NAME "higmac_clk" ++#define HIGMAC_MACIF_CLK_NAME "macif_clk" ++ ++#define HIGMAC_PORT_RST_NAME "port_reset" ++#define HIGMAC_MACIF_RST_NAME "macif_reset" ++#define HIGMAC_PHY_RST_NAME "phy_reset" ++ ++#define HIGMAC_TSO_DEBUG ++ ++#include "tso.h" ++ ++#if defined(CONFIG_ARCH_HI3519) || defined(CONFIG_ARCH_HI3519V101) || \ ++ defined(CONFIG_ARCH_HI3516AV200) ++#ifdef readl ++#undef readl ++#undef readl_relaxed ++#undef writel ++#undef writel_relaxed ++#define readl hi_readl ++#define readl_relaxed hi_readl_relaxed ++#define writel hi_writel ++#define writel_relaxed hi_writel_relaxed ++#endif /* readl */ ++#endif /* defined(CONFIG_ARCH_HI3519) || defined(CONFIG_HI3519V101) */ ++ ++#define HIGMAC_IOSIZE (0x1000) ++#define HIGMAC_OFFSET (HIGMAC_IOSIZE) ++ ++#define RX_BQ_IN_INT BIT(17) ++#define TX_RQ_IN_INT BIT(19) ++#define RX_BQ_IN_TIMEOUT_INT BIT(28) ++#define TX_RQ_IN_TIMEOUT_INT BIT(29) ++ ++#define DEF_INT_MASK (RX_BQ_IN_INT | RX_BQ_IN_TIMEOUT_INT | \ ++ TX_RQ_IN_INT | TX_RQ_IN_TIMEOUT_INT) ++ ++/* write or read descriptor need memory barrier */ ++#define HIGMAC_SYNC_BARRIER() do { isb(); smp_mb(); } while (0) ++ ++#define HISILICON_PHY_ID_FESTAV200 (0x20669823) ++#define PHY_ID_KSZ8051MNL (0x00221550) ++#define PHY_ID_KSZ8081RNB (0x00221560) ++#define DEFAULT_PHY_MASK (0xfffffff0) ++#define REALTEK_PHY_ID_8211E (0x001cc915) ++#define REALTEK_PHY_MASK (0x001fffff) ++ ++enum { ++ GMAC_PORT0, ++ GMAC_PORT1, ++ GMAC_MAX_PORT, ++}; ++ ++enum { ++ MEM_GMAC_IOBASE, ++ MEM_MACIF_IOBASE, ++ MEM_FWD_IOBASE, ++ MEM_CTRL_IOBASE, ++}; ++ ++#define HIGMAC_LINKED BIT(0) ++#define HIGMAC_DUP_FULL BIT(1) ++#define HIGMAC_SPD_10M BIT(2) ++#define HIGMAC_SPD_100M BIT(3) ++#define HIGMAC_SPD_1000M BIT(4) ++/* Flow Control defines */ ++#define FLOW_OFF 0 ++#define FLOW_RX 1 ++#define FLOW_TX 2 ++#define FLOW_AUTO (FLOW_TX | FLOW_RX) ++ ++#define FC_ACTIVE_MIN 1 ++#define FC_ACTIVE_DEFAULT 16 ++#define FC_ACTIVE_MAX 127 ++#define FC_DEACTIVE_MIN 1 ++#define FC_DEACTIVE_DEFAULT 32 ++#define FC_DEACTIVE_MAX 127 ++ ++#define FC_PAUSE_TIME_DEFAULT 0xFFFF ++#define FC_PAUSE_INTERVAL_DEFAULT 0xFFFF ++#define FC_PAUSE_TIME_MAX 0xFFFF ++ ++#define RX_BQ_INT_THRESHOLD 0x40 /* TODO: */ ++#define TX_RQ_INT_THRESHOLD 0x20 /* TODO: */ ++ ++#define HIGMAC_MONITOR_TIMER (msecs_to_jiffies(200)) ++ ++#define HIETH_MAX_FRAME_SIZE (1600 + 128) ++#define SKB_SIZE (HIETH_MAX_FRAME_SIZE) ++ ++#define DESC_VLD_FREE 0 ++#define DESC_VLD_BUSY 1 ++ ++#define DESC_FL_FIRST 2 ++#define DESC_FL_MID 0 ++#define DESC_FL_LAST 1 ++#define DESC_FL_FULL 3 ++ ++#if defined(CONFIG_HIGMAC_DESC_4WORD) ++#define DESC_WORD_SHIFT 2 ++#else ++#define DESC_WORD_SHIFT 3 ++#endif ++#define DESC_BYTE_SHIFT (DESC_WORD_SHIFT + 2) ++#define DESC_WORD_CNT (1 << DESC_WORD_SHIFT) ++#define DESC_SIZE (1 << DESC_BYTE_SHIFT) ++ ++#define RX_DESC_NUM 1024 ++#define TX_DESC_NUM 1024 ++ ++/* DMA descriptor ring helpers */ ++#define dma_ring_incr(n, s) (((n) + 1) & ((s) - 1)) ++#define dma_cnt(n) ((n) >> DESC_BYTE_SHIFT) ++#define dma_byte(n) ((n) << DESC_BYTE_SHIFT) ++ ++#define RSS_HASH_KEY_SIZE 4 ++#define RSS_INDIRECTION_TABLE_SIZE 128 ++#define RSS_NUM_RXQS 4 ++ ++#define HW_CAP_TSO BIT(0) ++#define HW_CAP_RXCSUM BIT(1) ++#define HW_CAP_CCI BIT(2) ++#define HAS_CAP_TSO(hw_cap) ((hw_cap) & HW_CAP_TSO) ++#define HAS_CAP_RXCSUM(hw_cap) ((hw_cap) & HW_CAP_RXCSUM) ++#define HAS_CAP_CCI(hw_cap) ((hw_cap) & HW_CAP_CCI) ++ ++#if defined(CONFIG_HIGMAC_DESC_4WORD) ++struct higmac_desc { ++ unsigned int data_buff_addr; ++ ++ unsigned int buffer_len:11; ++#if defined(CONFIG_HIGMAC_RXCSUM) ++ unsigned int reserve2:1; ++ unsigned int payload_csum_err:1; ++ unsigned int header_csum_err:1; ++ unsigned int payload_csum_done:1; ++ unsigned int header_csum_done:1; ++#else ++ unsigned int reserve2:5; ++#endif ++ unsigned int data_len:11; ++ unsigned int reserve1:2; ++ unsigned int fl:2; ++ unsigned int descvid:1; ++ ++ unsigned int rxhash; ++ unsigned int reserve3:8; ++ unsigned int l3_hash:1; ++ unsigned int has_hash:1; ++ unsigned int skb_id:14; ++ unsigned int reserve31:8; ++}; ++ ++struct higmac_tso_desc { ++ unsigned int data_buff_addr; ++ union { ++ struct { ++ unsigned int prot_hdr_len:4; ++ unsigned int ip_hdr_len:4; ++ unsigned int prot_type:1; ++ unsigned int ip_ver:1; ++ unsigned int vlan_flag:1; ++ unsigned int nfrags_num:5; ++ unsigned int data_len:11; ++ unsigned int reservel:1; ++ unsigned int tso_flag:1; ++ unsigned int coe_flag:1; ++ unsigned int sg_flag:1; ++ unsigned int hw_own:1; ++ } tx; ++ unsigned int val; ++ } desc1; ++ unsigned int reserve_desc2; ++ unsigned int tx_err; ++}; ++#else ++struct higmac_desc { ++ unsigned int data_buff_addr; ++ ++ unsigned int buffer_len:11; ++#if defined(CONFIG_HIGMAC_RXCSUM) ++ unsigned int reserve2:1; ++ unsigned int payload_csum_err:1; ++ unsigned int header_csum_err:1; ++ unsigned int payload_csum_done:1; ++#else ++ unsigned int reserve2:5; ++#endif ++ unsigned int data_len:11; ++ unsigned int reserve1:2; ++ unsigned int fl:2; ++ unsigned int descvid:1; ++ ++ unsigned int rxhash; ++ unsigned int reserve3:8; ++ unsigned int l3_hash:1; ++ unsigned int has_hash:1; ++ unsigned int skb_id:14; ++ unsigned int reserve31:8; ++ ++ unsigned int reserve4; ++ unsigned int reserve5; ++ unsigned int reserve6; ++ unsigned int reserve7; ++}; ++ ++struct higmac_tso_desc { ++ unsigned int data_buff_addr; ++ union { ++ struct { ++ unsigned int prot_hdr_len:4; ++ unsigned int ip_hdr_len:4; ++ unsigned int prot_type:1; ++ unsigned int ip_ver:1; ++ unsigned int vlan_flag:1; ++ unsigned int nfrags_num:5; ++ unsigned int data_len:11; ++ unsigned int reservel:1; ++ unsigned int tso_flag:1; ++ unsigned int coe_flag:1; ++ unsigned int sg_flag:1; ++ unsigned int hw_own:1; ++ } tx; ++ unsigned int val; ++ } desc1; ++ unsigned int reserve_desc2; ++ unsigned int reserve3; ++ ++ unsigned int tx_err; ++ unsigned int reserve5; ++ unsigned int reserve6; ++ unsigned int reserve7; ++}; ++#endif ++ ++#define SKB_MAGIC ((struct sk_buff *)0x5a) ++ ++struct higmac_napi { ++ struct napi_struct napi; ++ struct higmac_netdev_local *ndev_priv; ++ int rxq_id; ++}; ++ ++struct higmac_rss_info { ++ u32 hash_cfg; ++ u32 ind_tbl_size; ++ u8 ind_tbl[RSS_INDIRECTION_TABLE_SIZE]; ++ u8 key[RSS_HASH_KEY_SIZE]; ++}; ++ ++#define QUEUE_NUMS (4) ++struct higmac_netdev_local { ++#define HIGMAC_SG_DESC_ADD (64U) ++ struct sg_desc *dma_sg_desc ____cacheline_aligned; ++ dma_addr_t dma_sg_phy; ++ unsigned int sg_head; ++ unsigned int sg_tail; ++ unsigned int sg_count; ++ ++ void __iomem *gmac_iobase; ++ void __iomem *macif_base; ++ int index; /* 0 -- mac0, 1 -- mac1 */ ++ ++ u32 hw_cap; ++ bool tso_supported; ++ bool has_rxhash_cap; ++ bool has_rss_cap; ++ int num_rxqs; ++ struct higmac_napi q_napi[RSS_NUM_RXQS]; ++ int irq[RSS_NUM_RXQS]; ++ struct higmac_rss_info rss_info; ++ ++ struct reset_control *port_rst; ++ struct reset_control *macif_rst; ++ struct reset_control *phy_rst; ++ ++ struct { ++ struct higmac_desc *desc; ++ dma_addr_t phys_addr; ++ int *sg_desc_offset; ++ ++ /* how many desc in the desc pool */ ++ unsigned int count; ++ struct sk_buff **skb; ++ ++ /* sizeof(desc) * count */ ++ unsigned int size; ++ } pool[QUEUE_NUMS + RSS_NUM_RXQS - 1]; ++#define rx_fq pool[0] ++#define rx_bq pool[1] ++#define tx_bq pool[2] ++#define tx_rq pool[3] ++ ++ struct sk_buff **tx_skb; ++ struct sk_buff **rx_skb; ++ ++ struct device *dev; ++ struct net_device *netdev; ++ struct clk *clk; ++ struct clk *macif_clk; ++ ++ struct higmac_adapter *adapter; ++ ++ struct timer_list monitor; ++ ++ char phy_name[MII_BUS_ID_SIZE]; ++ struct phy_device *phy; ++ struct device_node *phy_node; ++ phy_interface_t phy_mode; ++ bool autoeee; ++ bool internal_phy; ++ int (*eee_init)(struct phy_device *phy_dev); ++ ++ unsigned int flow_ctrl; ++ unsigned int pause; ++ unsigned int pause_interval; ++ unsigned int flow_ctrl_active_threshold; ++ unsigned int flow_ctrl_deactive_threshold; ++ ++ int old_link; ++ int old_speed; ++ int old_duplex; ++ ++ /* receive packet lock */ ++ spinlock_t rxlock; ++ /* transmit packet lock */ ++ spinlock_t txlock; ++ /* power management lock */ ++ spinlock_t pmtlock; ++ ++ int dev_state; /* INIT/OPEN/CLOSE */ ++ char pm_state; ++ bool wol_enable; ++ u32 msg_enable; ++#define INIT (0) /* power off gmac */ ++#define OPEN (1) /* power on gmac */ ++#define CLOSE (2) /* power off gmac */ ++}; ++ ++enum tso_version { ++ VER_NO_TSO = 0x0, ++ VER_BYTE_SPLICE = 0x1, ++ VER_SG_COE = 0x2, ++ VER_TSO = 0x3, ++}; ++ ++#ifdef HIGMAC_TSO_DEBUG ++#define MAX_RECORD (100) ++struct send_pkt_info { ++ struct higmac_tso_desc desc; ++ int status; ++}; ++#endif ++ ++int higmac_tx_avail(struct higmac_netdev_local *ld); ++ ++/* board related func */ ++void higmac_mac_core_reset(struct higmac_netdev_local *priv); ++void higmac_hw_internal_phy_reset(struct higmac_netdev_local *priv); ++void higmac_hw_external_phy_reset(struct higmac_netdev_local *priv); ++void higmac_internal_phy_clk_disable(struct higmac_netdev_local *priv); ++void higmac_internal_phy_clk_enable(struct higmac_netdev_local *priv); ++void higmac_hw_all_clk_disable(struct higmac_netdev_local *priv); ++void higmac_hw_all_clk_enable(struct higmac_netdev_local *priv); ++ ++/* board independent func */ ++void higmac_hw_phy_reset(struct higmac_netdev_local *priv); ++ ++void pmt_reg_restore(struct higmac_netdev_local *ld); ++#endif +diff --git a/drivers/net/ethernet/hisilicon/higmac/pm.c b/drivers/net/ethernet/hisilicon/higmac/pm.c +new file mode 100644 +index 0000000..7620abe +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/pm.c +@@ -0,0 +1,359 @@ ++#include ++#include "higmac.h" ++ ++#define N (31) ++#define FILTERS (4) ++struct pm_config { ++ unsigned char index; /* bit0--eth0 bit1--eth1 */ ++ unsigned char uc_pkts_enable; ++ unsigned char magic_pkts_enable; ++ unsigned char wakeup_pkts_enable; ++ struct { ++ unsigned int mask_bytes:N; ++ unsigned int reserved:1; /* userspace ignore this bit */ ++ unsigned char offset; /* >= 12 */ ++ unsigned char value[N]; /* byte string */ ++ unsigned char valid; /* valid filter */ ++ } filter[FILTERS]; ++}; ++ ++struct pm_reg_config { ++ unsigned int pmt_ctrl; ++ unsigned int pmt_mask0; ++ unsigned int pmt_mask1; ++ unsigned int pmt_mask2; ++ unsigned int pmt_mask3; ++ unsigned int pmt_cmd; ++ unsigned int pmt_offset; ++ unsigned int pmt_crc1_0; ++ unsigned int pmt_crc3_2; ++}; ++ ++struct pm_reg_config pm_reg_config_backup; ++ ++#define PMT_CTRL 0xa00 ++#define PMT_MASK0 0xa04 ++#define PMT_MASK1 0xa08 ++#define PMT_MASK2 0xa0c ++#define PMT_MASK3 0xa10 ++#define PMT_CMD 0xa14 ++#define PMT_OFFSET 0xa18 ++#define PMT_CRC1_0 0xa1c ++#define PMT_CRC3_2 0xa20 ++#define MASK_INVALID_BIT BIT(31) ++ ++static void init_crc_table(void); ++static unsigned short compute_crc(char *message, int nbytes); ++static unsigned short calculate_crc16(char *buf, unsigned int mask) ++{ ++ char data[N]; ++ int i, len = 0; ++ ++ memset(data, 0, sizeof(data)); ++ ++ for (i = 0; i < N; i++) { ++ if (mask & 0x1) ++ data[len++] = buf[i]; ++ ++ mask >>= 1; ++ } ++ ++ return compute_crc(data, len); ++} ++ ++/* use this func in config pm func */ ++void _pmt_reg_backup(struct higmac_netdev_local *ld) ++{ ++ pm_reg_config_backup.pmt_ctrl = readl(ld->gmac_iobase + PMT_CTRL); ++ pm_reg_config_backup.pmt_mask0 = readl(ld->gmac_iobase + PMT_MASK0); ++ pm_reg_config_backup.pmt_mask1 = readl(ld->gmac_iobase + PMT_MASK1); ++ pm_reg_config_backup.pmt_mask2 = readl(ld->gmac_iobase + PMT_MASK2); ++ pm_reg_config_backup.pmt_mask3 = readl(ld->gmac_iobase + PMT_MASK3); ++ pm_reg_config_backup.pmt_cmd = readl(ld->gmac_iobase + PMT_CMD); ++ pm_reg_config_backup.pmt_offset = readl(ld->gmac_iobase + PMT_OFFSET); ++ pm_reg_config_backup.pmt_crc1_0 = readl(ld->gmac_iobase + PMT_CRC1_0); ++ pm_reg_config_backup.pmt_crc3_2 = readl(ld->gmac_iobase + PMT_CRC3_2); ++} ++ ++#define PM_SET (1) ++#define PM_CLEAR (0) ++ ++int pmt_config_gmac(struct pm_config *config, struct higmac_netdev_local *ld) ++{ ++ unsigned int v = 0, cmd = 0, offset = 0; ++ unsigned short crc[FILTERS] = { 0 }; ++ unsigned long flags; ++ int reg_mask = 0; ++ int i; ++ ++ if (!ld) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&ld->pmtlock, flags); ++ if (config->wakeup_pkts_enable) { ++ /* disable wakeup_pkts_enable before reconfig? */ ++ v = readl(ld->gmac_iobase + PMT_CTRL); ++ v &= ~BIT(2); ++ writel(v, ld->gmac_iobase + PMT_CTRL); /* any side effect? */ ++ } else { ++ goto config_ctrl; ++ } ++ ++/* filter.valid mask.valid mask_bytes effect ++ * 0 * * no use the filter ++ * 1 0 * all pkts can wake-up(non-exist) ++ * 1 1 0 all pkts can wake-up ++ * 1 1 !0 normal filter ++ */ ++ /* setup filter */ ++ for (i = 0; i < FILTERS; i++) { ++ if (config->filter[i].valid) { ++ if (config->filter[i].offset < 12) ++ continue; ++ /* offset and valid bit */ ++ offset |= config->filter[i].offset << (i * 8); ++ cmd |= BIT(i * 8); /* valid bit */ ++ /* mask */ ++ reg_mask = PMT_MASK0 + (i * 4); ++ ++ /* for logic, mask valid bit(bit31) must set to 0, ++ * 0 is enable ++ */ ++ v = config->filter[i].mask_bytes; ++ v &= ~BIT(31); ++ writel(v, ld->gmac_iobase + reg_mask); ++ ++ /* crc */ ++ crc[i] = calculate_crc16(config->filter[i].value, v); ++ if (i <= 1) { /* for filter0 and filter 1 */ ++ v = readl(ld->gmac_iobase + PMT_CRC1_0); ++ v &= ~(0xFFFF << (16 * i)); ++ v |= crc[i] << (16 * i); ++ writel(v, ld->gmac_iobase + PMT_CRC1_0); ++ } else { /* filter2 and filter3 */ ++ v = readl(ld->gmac_iobase + PMT_CRC3_2); ++ v &= ~(0xFFFF << (16 * (i - 2))); ++ v |= crc[i] << (16 * (i - 2)); ++ writel(v, ld->gmac_iobase + PMT_CRC3_2); ++ } ++ } ++ } ++ ++ if (cmd) { ++ writel(offset, ld->gmac_iobase + PMT_OFFSET); ++ writel(cmd, ld->gmac_iobase + PMT_CMD); ++ } ++ ++config_ctrl: ++ v = 0; ++ if (config->uc_pkts_enable) ++ v |= BIT(9); /* uc pkts wakeup */ ++ if (config->wakeup_pkts_enable) ++ v |= BIT(2); /* use filter framework */ ++ if (config->magic_pkts_enable) ++ v |= BIT(1); /* magic pkts wakeup */ ++ ++ v |= 3 << 5; /* clear irq status */ ++ writel(v, ld->gmac_iobase + PMT_CTRL); ++ ++ _pmt_reg_backup(ld); ++ ++ spin_unlock_irqrestore(&ld->pmtlock, flags); ++ ++ return 0; ++} ++ ++/* pmt_config will overwrite pre-config */ ++int pmt_config(struct net_device *ndev, struct pm_config *config) ++{ ++ static int init; ++ int ret = -EINVAL; ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ ++ if (!init) ++ init_crc_table(); ++ ++ ret = pmt_config_gmac(config, priv); ++ if (ret) ++ return ret; ++ ++ priv->pm_state = PM_SET; ++ priv->wol_enable = true; ++ device_set_wakeup_enable(priv->dev, 1); ++ ++ return ret; ++} ++ ++inline bool pmt_enter(struct higmac_netdev_local *ld) ++{ ++ int pm = false; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ld->pmtlock, flags); ++ if (ld->pm_state == PM_SET) { ++ int v; ++ ++ v = readl(ld->gmac_iobase + PMT_CTRL); ++ v |= BIT(0); /* enter power down */ ++ v |= BIT(3); /* enable wakeup irq */ ++ v |= 3 << 5; /* clear irq status */ ++ writel(v, ld->gmac_iobase + PMT_CTRL); ++ ++ ld->pm_state = PM_CLEAR; ++ pm = true; ++ } ++ spin_unlock_irqrestore(&ld->pmtlock, flags); ++ return pm; ++} ++ ++inline void pmt_exit(struct higmac_netdev_local *ld) ++{ ++ int v; ++ unsigned long flags; ++ ++ /* logic auto exit power down mode */ ++ spin_lock_irqsave(&ld->pmtlock, flags); ++ ++ v = readl(ld->gmac_iobase + PMT_CTRL); ++ v &= ~BIT(0); /* enter power down */ ++ v &= ~BIT(3); /* enable wakeup irq */ ++ ++ v |= 3 << 5; /* clear irq status */ ++ writel(v, ld->gmac_iobase + PMT_CTRL); ++ ++ spin_unlock_irqrestore(&ld->pmtlock, flags); ++ ++ ld->wol_enable = false; ++ /* device_set_wakeup_enable(ld->dev, 0); */ ++} ++ ++void pmt_reg_restore(struct higmac_netdev_local *ld) ++{ ++ unsigned int v; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ld->pmtlock, flags); ++ v = pm_reg_config_backup.pmt_mask0; ++ writel(v, ld->gmac_iobase + PMT_MASK0); ++ ++ v = pm_reg_config_backup.pmt_mask1; ++ writel(v, ld->gmac_iobase + PMT_MASK1); ++ ++ v = pm_reg_config_backup.pmt_mask2; ++ writel(v, ld->gmac_iobase + PMT_MASK2); ++ ++ v = pm_reg_config_backup.pmt_mask3; ++ writel(v, ld->gmac_iobase + PMT_MASK3); ++ ++ v = pm_reg_config_backup.pmt_cmd; ++ writel(v, ld->gmac_iobase + PMT_CMD); ++ ++ v = pm_reg_config_backup.pmt_offset; ++ writel(v, ld->gmac_iobase + PMT_OFFSET); ++ ++ v = pm_reg_config_backup.pmt_crc1_0; ++ writel(v, ld->gmac_iobase + PMT_CRC1_0); ++ ++ v = pm_reg_config_backup.pmt_crc3_2; ++ writel(v, ld->gmac_iobase + PMT_CRC3_2); ++ ++ v = pm_reg_config_backup.pmt_ctrl; ++ writel(v, ld->gmac_iobase + PMT_CTRL); ++ spin_unlock_irqrestore(&ld->pmtlock, flags); ++} ++ ++/* ========the following code copy from Synopsys DWC_gmac_crc_example.c====== */ ++#define CRC16 /* Change it to CRC16 for CRC16 Computation */ ++ ++#if defined(CRC16) ++#define CRC_NAME "CRC-16" ++#define POLYNOMIAL 0x8005 ++#define INITIAL_REMAINDER 0xFFFF ++#define FINAL_XOR_VALUE 0x0000 ++#define REVERSE_DATA ++#undef REVERSE_REMAINDER ++#endif ++ ++#define WIDTH (8 * sizeof(unsigned short)) ++#define TOPBIT BIT(WIDTH - 1) ++ ++#ifdef REVERSE_DATA ++#undef REVERSE_DATA ++#define REVERSE_DATA(X) ((unsigned char)reverse((X), 8)) ++#else ++#undef REVERSE_DATA ++#define REVERSE_DATA(X) (X) ++#endif ++ ++#ifdef REVERSE_REMAINDER ++#undef REVERSE_REMAINDER ++#define REVERSE_REMAINDER(X) ((unsigned short)reverse((X), WIDTH)) ++#else ++#undef REVERSE_REMAINDER ++#define REVERSE_REMAINDER(X) (X) ++#endif ++ ++static unsigned short crc_table[256]; ++ ++/* Reverse the data ++ * Input1: Data to be reversed ++ * Input2: number of bits in the data ++ * Output: The reversed data ++ */ ++static unsigned int reverse(unsigned int data, unsigned char nbits) ++{ ++ unsigned int reversed = 0x00000000; ++ unsigned char bit; ++ ++ /* Reverse the data about the center bit. */ ++ for (bit = 0; bit < nbits; ++bit) { ++ /* If the LSB bit is set, set the reflection of it. */ ++ if (data & 0x01) ++ reversed |= BIT((nbits - 1) - bit); ++ ++ data = (data >> 1); ++ } ++ return reversed; ++} ++ ++/* This Initializes the partial CRC look up table */ ++static void init_crc_table(void) ++{ ++ unsigned short remainder; ++ int dividend; ++ unsigned char bit; ++ ++ /* Compute the remainder of each possible dividend. */ ++ for (dividend = 0; dividend < 256; ++dividend) { ++ /* Start with the dividend followed by zeros. */ ++ remainder = (unsigned short)(dividend << (WIDTH - 8)); ++ ++ /* Perform modulo-2 division, a bit at a time. */ ++ for (bit = 8; bit > 0; --bit) { ++ /* Try to divide the current data bit. */ ++ if (remainder & TOPBIT) ++ remainder = (remainder << 1) ^ POLYNOMIAL; ++ else ++ remainder = (remainder << 1); ++ } ++ ++ /* Store the result into the table. */ ++ crc_table[dividend] = remainder; ++ } ++} ++ ++static unsigned short compute_crc(char *message, int nbytes) ++{ ++ unsigned short remainder = INITIAL_REMAINDER; ++ int byte; ++ unsigned char data; ++ ++ /* Divide the message by the polynomial, a byte at a time. */ ++ for (byte = 0; byte < nbytes; ++byte) { ++ data = REVERSE_DATA(message[byte]) ^ (remainder >> (WIDTH - 8)); ++ remainder = crc_table[data] ^ (remainder << 8); ++ } ++ ++ /* The final remainder is the CRC. */ ++ return (REVERSE_REMAINDER(remainder) ^ FINAL_XOR_VALUE); ++} +diff --git a/drivers/net/ethernet/hisilicon/higmac/proc-dev.c b/drivers/net/ethernet/hisilicon/higmac/proc-dev.c +new file mode 100644 +index 0000000..d522565 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/proc-dev.c +@@ -0,0 +1,111 @@ ++#include "sockioctl.h" ++ ++/* debug code */ ++static int set_suspend(int eth_n) ++{ ++ return 0; ++} ++ ++/* debug code */ ++static int set_resume(int eth_n) ++{ ++ /* higmac_dev_driver.resume(&higmac_platform_device); */ ++ return 0; ++} ++ ++static int hw_states_read(struct seq_file *m, void *v) ++{ ++ return 0; ++} ++ ++static struct proc_dir_entry *higmac_proc_root; ++ ++#define proc_open(name) \ ++static int proc_open_##name(struct inode *inode, struct file *file) \ ++{ \ ++ return single_open(file, name, PDE_DATA(inode)); \ ++} \ ++ ++proc_open(hw_states_read); ++ ++static struct proc_file { ++ char *name; ++ const struct file_operations ops; ++ ++} proc_file[] = { ++ { ++ .name = "hw_stats", ++ .ops = { ++ .open = proc_open_hw_states_read, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++ }, ++ } ++}; ++ ++/* /proc/higmac/ ++ * |---hw_stats ++ * |---skb_pools ++ */ ++void higmac_proc_create(void) ++{ ++ int i; ++ ++ higmac_proc_root = proc_mkdir("higmac", NULL); ++ if (!higmac_proc_root) ++ return; ++ ++ for (i = 0; i < ARRAY_SIZE(proc_file); i++) { ++ struct proc_dir_entry *entry; ++ ++ entry = proc_create(proc_file[i].name, 0000, higmac_proc_root, ++ &proc_file[i].ops); ++ if (!entry) ++ pr_err("failed to create %s\n", proc_file[i].name); ++ } ++} ++ ++void higmac_proc_destroy(void) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(proc_file); i++) ++ remove_proc_entry(proc_file[i].name, higmac_proc_root); ++ ++ remove_proc_entry("higmac", NULL); ++} ++ ++int higmac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) ++{ ++ struct higmac_netdev_local *priv = netdev_priv(ndev); ++ struct pm_config pm_config; ++ int val = 0; ++ ++ switch (cmd) { ++ case SIOCSETPM: ++ if (copy_from_user(&pm_config, rq->ifr_data, sizeof(pm_config))) ++ return -EFAULT; ++ return pmt_config(ndev, &pm_config); ++ ++ case SIOCSETSUSPEND: ++ if (copy_from_user(&val, rq->ifr_data, sizeof(val))) ++ return -EFAULT; ++ return set_suspend(val); ++ ++ case SIOCSETRESUME: ++ if (copy_from_user(&val, rq->ifr_data, sizeof(val))) ++ return -EFAULT; ++ return set_resume(val); ++ ++ default: ++ if (!netif_running(ndev)) ++ return -EINVAL; ++ ++ if (!priv->phy) ++ return -EINVAL; ++ ++ return phy_mii_ioctl(priv->phy, rq, cmd); ++ } ++ return 0; ++} +diff --git a/drivers/net/ethernet/hisilicon/higmac/sockioctl.h b/drivers/net/ethernet/hisilicon/higmac/sockioctl.h +new file mode 100644 +index 0000000..571c71a +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/sockioctl.h +@@ -0,0 +1,12 @@ ++#ifndef _SOCKIOCTL_H_ ++#define _SOCKIOCTL_H_ ++ ++#include ++ ++#define SIOCSETPM (SIOCDEVPRIVATE + 4) /* set pmt wake up config */ ++#define SIOCSETSUSPEND (SIOCDEVPRIVATE + 5) /* call dev->suspend, debug */ ++#define SIOCSETRESUME (SIOCDEVPRIVATE + 6) /* call dev->resume, debug */ ++ ++int higmac_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd); ++ ++#endif +diff --git a/drivers/net/ethernet/hisilicon/higmac/tso.h b/drivers/net/ethernet/hisilicon/higmac/tso.h +new file mode 100644 +index 0000000..6416eef +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/tso.h +@@ -0,0 +1,53 @@ ++#ifndef __HIETH_TSO_H ++#define __HIETH_TSO_H ++ ++#define SG_FLAG BIT(30) ++#define COE_FLAG BIT(29) ++#define TSO_FLAG BIT(28) ++#define VLAN_FLAG BIT(10) ++#define IPV6_FLAG BIT(9) ++#define UDP_FLAG BIT(8) ++ ++#define PKT_IPV6_HDR_LEN 10 ++#define PKT_UDP_HDR_LEN 2 ++#define WORD_TO_BYTE 4 ++enum { ++ PKT_NORMAL, ++ PKT_SG ++}; ++ ++enum { ++ PKT_IPV4, ++ PKT_IPV6 ++}; ++ ++enum { ++ PKT_TCP, ++ PKT_UDP ++}; ++ ++struct frags_info { ++ /* Word(2*i+2) */ ++ u32 addr; ++ /* Word(2*i+3) */ ++ u32 size:16; ++ u32 reserved:16; ++}; ++ ++struct sg_desc { ++ /* Word0 */ ++ u32 total_len:17; ++ u32 reserv:15; ++ /* Word1 */ ++ u32 ipv6_id; ++ /* Word2 */ ++ u32 linear_addr; ++ /* Word3 */ ++ u32 linear_len:16; ++ u32 reserv3:16; ++ /* MAX_SKB_FRAGS = 17 */ ++ struct frags_info frags[18]; ++ /* struct frags_info frags[MAX_SKB_FRAGS]; */ ++}; ++ ++#endif +diff --git a/drivers/net/ethernet/hisilicon/higmac/util.h b/drivers/net/ethernet/hisilicon/higmac/util.h +new file mode 100644 +index 0000000..f08cbf6 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/higmac/util.h +@@ -0,0 +1,29 @@ ++#ifndef __HIGMAC_UTIL_H__ ++#define __HIGMAC_UTIL_H__ ++ ++#define HIGMAC_TRACE_LEVEL 10 ++ ++#define higmac_trace(level, msg...) do { \ ++ if ((level) >= HIGMAC_TRACE_LEVEL) { \ ++ pr_info("higmac_trace:%s:%d: ", __FILE__, __LINE__); \ ++ printk(msg); \ ++ printk("\n"); \ ++ } \ ++} while (0) ++ ++#define higmac_error(args...) do { \ ++ pr_err("higmac:%s:%d: ", __FILE__, __LINE__); \ ++ printk(args); \ ++ printk("\n"); \ ++} while (0) ++ ++#define higmac_assert(cond) do { \ ++ if (!(cond)) \ ++ pr_alert("Assert:higmac:%s:%d\n", \ ++ __FILE__, \ ++ __LINE__);\ ++} while (0) ++ ++#define MK_BITS(shift, nbits) ((((shift) & 0x1F) << 16) | ((nbits) & 0x3F)) ++ ++#endif +diff --git a/drivers/net/ethernet/hisilicon/hisi_femac.c b/drivers/net/ethernet/hisilicon/hisi_femac.c +new file mode 100644 +index 0000000..2257832 +--- /dev/null ++++ b/drivers/net/ethernet/hisilicon/hisi_femac.c +@@ -0,0 +1,1705 @@ ++/* ++ * Hisilicon Fast Ethernet MAC Driver ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* MAC control register list */ ++#define MAC_PORTSEL 0x0200 ++#define MAC_PORTSEL_STAT_CPU BIT(0) ++#define MAC_PORTSEL_RMII BIT(1) ++#define MAC_PORTSET 0x0208 ++#define MAC_PORTSET_DUPLEX_FULL BIT(0) ++#define MAC_PORTSET_LINKED BIT(1) ++#define MAC_PORTSET_SPEED_100M BIT(2) ++#define MAC_SET 0x0210 ++#define MAX_FRAME_SIZE 1600 ++#define MAX_FRAME_SIZE_MASK GENMASK(10, 0) ++#define BIT_PAUSE_EN BIT(18) ++#define RX_COALESCE_SET 0x0340 ++#define RX_COALESCED_FRAME_OFFSET 24 ++#define RX_COALESCED_FRAMES 8 ++#define RX_COALESCED_TIMER 0x74 ++#define QLEN_SET 0x0344 ++#define RX_DEPTH_OFFSET 8 ++#define MAX_HW_FIFO_DEPTH 64 ++#define HW_TX_FIFO_DEPTH 12 ++#define HW_RX_FIFO_DEPTH (MAX_HW_FIFO_DEPTH - HW_TX_FIFO_DEPTH) ++#define FC_LEVEL 0x0348 ++#define BITS_FC_ACTIVE_THR_OFFSET 8 ++#define FC_DEACTIVE_THR_MASK GENMASK(5, 0) ++#define FC_ACTIVE_THR_MASK GENMASK(13, 8) ++#define BIT_FC_EN BIT(14) ++#define IQFRM_DES 0x0354 ++#define RX_FRAME_LEN_MASK GENMASK(11, 0) ++#define BITS_PAYLOAD_ERR_OFFSET 28 ++#define BITS_PAYLOAD_ERR_MASK 0x1 ++#define BITS_HEADER_ERR_OFFSET 29 ++#define BITS_HEADER_ERR_MASK 0x1 ++#define BITS_PAYLOAD_DONE_OFFSET 30 ++#define BITS_PAYLOAD_DONE_MASK 0x1 ++#define BITS_HEADER_DONE_OFFSET 31 ++#define BITS_HEADER_DONE_MASK 0x1 ++#define IQ_ADDR 0x0358 ++#define EQ_ADDR 0x0360 ++#define EQFRM_LEN 0x0364 ++#define ADDRQ_STAT 0x036C ++#define TX_CNT_INUSE_MASK GENMASK(5, 0) ++#define BIT_TX_READY BIT(24) ++#define BIT_RX_READY BIT(25) ++#define RX_COE_CTRL 0x0380 ++#define BIT_COE_IPV6_UDP_ZERO_DROP BIT(13) ++#define BIT_COE_PAYLOAD_DROP BIT(14) ++#define BIT_COE_IPHDR_DROP BIT(15) ++#define COE_ERR_DROP (BIT_COE_IPHDR_DROP | \ ++ BIT_COE_PAYLOAD_DROP | \ ++ BIT_COE_IPV6_UDP_ZERO_DROP) ++#define TSO_DBG_EN 0x03A4 ++#define BITS_TSO_DBG_EN BIT(31) ++#define TSO_DBG_STATE 0x03A8 ++#define TSO_DBG_ADDR 0x03AC ++#define TSO_DBG_TX_INFO 0x03B0 ++#define TSO_DBG_TX_ERR 0x03B4 ++/* global control register list */ ++#define GLB_HOSTMAC_L32 0x0000 ++#define GLB_HOSTMAC_H16 0x0004 ++#define GLB_SOFT_RESET 0x0008 ++#define SOFT_RESET_ALL BIT(0) ++#define GLB_FWCTRL 0x0010 ++#define FWCTRL_VLAN_ENABLE BIT(0) ++#define FWCTRL_FW2CPU_ENA BIT(5) ++#define FWCTRL_FWALL2CPU BIT(7) ++#define GLB_MACTCTRL 0x0014 ++#define MACTCTRL_UNI2CPU BIT(1) ++#define MACTCTRL_MULTI2CPU BIT(3) ++#define MACTCTRL_BROAD2CPU BIT(5) ++#define MACTCTRL_MACT_ENA BIT(7) ++#define GLB_IRQ_STAT 0x0030 ++#define GLB_IRQ_ENA 0x0034 ++#define IRQ_ENA_PORT0_MASK GENMASK(7, 0) ++#define IRQ_ENA_PORT0 BIT(18) ++#define IRQ_ENA_ALL BIT(19) ++#define GLB_IRQ_RAW 0x0038 ++#define IRQ_INT_RX_RDY BIT(0) ++#define IRQ_INT_TX_PER_PACKET BIT(1) ++#define IRQ_INT_TX_FIFO_EMPTY BIT(6) ++#define IRQ_INT_MULTI_RXRDY BIT(7) ++#define INT_TX_ERR BIT(8) ++#define DEF_INT_MASK (IRQ_INT_MULTI_RXRDY | \ ++ IRQ_INT_TX_PER_PACKET | \ ++ IRQ_INT_TX_FIFO_EMPTY) ++#define GLB_MAC_L32_BASE 0x0100 ++#define GLB_MAC_H16_BASE 0x0104 ++#define MACFLT_HI16_MASK GENMASK(15, 0) ++#define BIT_MACFLT_ENA BIT(17) ++#define BIT_MACFLT_FW2CPU BIT(21) ++#define GLB_MAC_H16(reg) (GLB_MAC_H16_BASE + ((reg) * 0x8)) ++#define GLB_MAC_L32(reg) (GLB_MAC_L32_BASE + ((reg) * 0x8)) ++#define MAX_MAC_FILTER_NUM 8 ++#define MAX_UNICAST_ADDRESSES 2 ++#define MAX_MULTICAST_ADDRESSES (MAX_MAC_FILTER_NUM - \ ++ MAX_UNICAST_ADDRESSES) ++/* software tx and rx queue number, should be power of 2 */ ++#define TXQ_NUM 64 ++#define RXQ_NUM 128 ++#define FEMAC_POLL_WEIGHT 16 ++#define HW_CAP_TSO BIT(0) ++#define HW_CAP_RXCSUM BIT(1) ++#define HAS_TSO_CAP(hw_cap) ((hw_cap) & HW_CAP_TSO) ++#define HAS_RXCSUM_CAP(hw_cap) ((hw_cap) & HW_CAP_RXCSUM) ++#define RXBUF_ADDR_ALIGN_SIZE 64UL ++/* UDP header len is 2 word */ ++#define UDP_HDR_LEN 2 ++/* IPv6 header len is 10 word */ ++#define IPV6_HDR_LEN 10 ++#define WORD_TO_BYTE 4 ++ ++#define BIT_OFFSET_NFRAGS_NUM 11 ++#define BIT_OFFSET_PROT_HEADER_LEN 16 ++#define BIT_OFFSET_IP_HEADER_LEN 20 ++#define BIT_FLAG_SG BIT(26) ++#define BIT_FLAG_TXCSUM BIT(27) ++#define BIT_FLAG_UDP BIT(28) ++#define BIT_FLAG_IPV6 BIT(29) ++#define BIT_FLAG_VLAN BIT(30) ++#define BIT_FLAG_TSO BIT(31) ++ ++#define PHY_RESET_DELAYS_PROPERTY "hisilicon,phy-reset-delays-us" ++ ++/* The threshold for activing tx flow ctrl. ++ * When the left amount of receive queue descriptors is below this threshold, ++ * hardware will send pause frame immediately. ++ * We advise this value is set between 1 and 10. ++ * Too bigger is not a good choice. ++ * This value must be smaller than tx flow ctrl deactive threshold. ++ */ ++#define TX_FLOW_CTRL_ACTIVE_THRESHOLD 3 ++/* The threshold for deactiving tx flow ctrl. ++ * When the left amount of receive queue descriptors is ++ * above or equal with this threshold, ++ * hardware will exit flow control state. ++ * We advise this value is set between 1 and 10. ++ * Too bigger is not a good choice. ++ * This value must be larger than tx flow ctrl active threshold. ++ */ ++#define TX_FLOW_CTRL_DEACTIVE_THRESHOLD 5 ++#define FC_ACTIVE_MIN 1 ++#define FC_ACTIVE_DEFAULT 3 ++#define FC_ACTIVE_MAX 31 ++#define FC_DEACTIVE_MIN 1 ++#define FC_DEACTIVE_DEFAULT 5 ++#define FC_DEACTIVE_MAX 31 ++ ++enum phy_reset_delays { ++ PRE_DELAY, ++ PULSE, ++ POST_DELAY, ++ DELAYS_NUM, ++}; ++ ++struct hisi_femac_queue { ++ struct sk_buff **skb; ++ dma_addr_t *dma_phys; ++ int num; ++ unsigned int head; ++ unsigned int tail; ++}; ++ ++struct hisi_femac_tx_desc_ring { ++ struct tx_desc *desc; ++ dma_addr_t dma_phys; ++}; ++ ++struct hisi_femac_priv { ++ void __iomem *port_base; ++ void __iomem *glb_base; ++ struct clk *clk; ++ struct reset_control *mac_rst; ++ struct reset_control *phy_rst; ++ u32 phy_reset_delays[DELAYS_NUM]; ++ u32 link_status; ++ ++ struct device *dev; ++ struct net_device *ndev; ++ ++ u32 hw_cap; ++ struct hisi_femac_queue txq; ++ struct hisi_femac_queue rxq; ++ struct hisi_femac_tx_desc_ring tx_ring; ++ u32 tx_fifo_used_cnt; ++ struct napi_struct napi; ++ ++ /* 802.3x flow control */ ++ bool tx_pause_en; ++ u32 tx_pause_active_thresh; ++ u32 tx_pause_deactive_thresh; ++}; ++ ++struct frags_info { ++ /* Word(2*i+2) */ ++ u32 addr; ++ /* Word(2*i+3) */ ++ u32 size:16; ++ u32 reserved:16; ++}; ++ ++struct tx_desc { ++ /* Word0 */ ++ u32 total_len:17; ++ u32 reserv:15; ++ /* Word1 */ ++ u32 ipv6_id; ++ /* Word2 */ ++ u32 linear_addr; ++ /* Word3 */ ++ u32 linear_len:16; ++ u32 reserv3:16; ++ /* MAX_SKB_FRAGS = 17 */ ++ struct frags_info frags[30]; ++ /* struct frags_info frags[MAX_SKB_FRAGS]; */ ++}; ++ ++static void hisi_femac_irq_enable(struct hisi_femac_priv *priv, u32 irqs) ++{ ++ u32 val; ++ ++ val = readl(priv->glb_base + GLB_IRQ_ENA); ++ writel(val | irqs, priv->glb_base + GLB_IRQ_ENA); ++} ++ ++static void hisi_femac_irq_disable(struct hisi_femac_priv *priv, u32 irqs) ++{ ++ u32 val; ++ ++ val = readl(priv->glb_base + GLB_IRQ_ENA); ++ writel(val & (~irqs), priv->glb_base + GLB_IRQ_ENA); ++} ++ ++static void hisi_femac_set_flow_ctrl(struct hisi_femac_priv *priv) ++{ ++ unsigned int pause_en; ++ unsigned int tx_flow_ctrl; ++ ++ tx_flow_ctrl = readl(priv->port_base + FC_LEVEL); ++ tx_flow_ctrl &= ~FC_DEACTIVE_THR_MASK; ++ tx_flow_ctrl |= priv->tx_pause_deactive_thresh; ++ tx_flow_ctrl &= ~FC_ACTIVE_THR_MASK; ++ tx_flow_ctrl |= priv->tx_pause_active_thresh << ++ BITS_FC_ACTIVE_THR_OFFSET; ++ ++ pause_en = readl(priv->port_base + MAC_SET); ++ ++ if (priv->tx_pause_en) { ++ tx_flow_ctrl |= BIT_FC_EN; ++ pause_en |= BIT_PAUSE_EN; ++ } else { ++ tx_flow_ctrl &= ~BIT_FC_EN; ++ pause_en &= ~BIT_PAUSE_EN; ++ } ++ ++ writel(tx_flow_ctrl, priv->port_base + FC_LEVEL); ++ ++ writel(pause_en, priv->port_base + MAC_SET); ++} ++ ++static void hisi_femac_tx_sg_dma_unmap(struct hisi_femac_priv *priv, ++ struct sk_buff *skb, unsigned int pos) ++{ ++ struct tx_desc *desc_cur; ++ dma_addr_t addr; ++ u32 len; ++ int i; ++ ++ desc_cur = priv->tx_ring.desc + pos; ++ ++ addr = desc_cur->linear_addr; ++ len = desc_cur->linear_len; ++ dma_unmap_single(priv->dev, addr, len, DMA_TO_DEVICE); ++ ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { ++ addr = desc_cur->frags[i].addr; ++ len = desc_cur->frags[i].size; ++ dma_unmap_page(priv->dev, addr, len, DMA_TO_DEVICE); ++ } ++} ++ ++static void hisi_femac_tx_dma_unmap(struct hisi_femac_priv *priv, ++ struct sk_buff *skb, unsigned int pos) ++{ ++ if (!(skb_is_gso(skb) || skb_shinfo(skb)->nr_frags)) { ++ dma_addr_t dma_addr; ++ ++ dma_addr = priv->txq.dma_phys[pos]; ++ dma_unmap_single(priv->dev, dma_addr, skb->len, DMA_TO_DEVICE); ++ } else { ++ hisi_femac_tx_sg_dma_unmap(priv, skb, pos); ++ } ++} ++ ++static void hisi_femac_xmit_reclaim(struct net_device *dev) ++{ ++ struct sk_buff *skb; ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ struct hisi_femac_queue *txq = &priv->txq; ++ unsigned int bytes_compl = 0, pkts_compl = 0; ++ u32 val; ++ ++ netif_tx_lock(dev); ++ ++ val = readl(priv->port_base + ADDRQ_STAT) & TX_CNT_INUSE_MASK; ++ while (val < priv->tx_fifo_used_cnt) { ++ skb = txq->skb[txq->tail]; ++ if (unlikely(!skb)) { ++ netdev_err(dev, "xmitq_cnt_inuse=%d, tx_fifo_used=%d\n", ++ val, priv->tx_fifo_used_cnt); ++ break; ++ } ++ hisi_femac_tx_dma_unmap(priv, skb, txq->tail); ++ pkts_compl++; ++ bytes_compl += skb->len; ++ dev_kfree_skb_any(skb); ++ ++ priv->tx_fifo_used_cnt--; ++ ++ val = readl(priv->port_base + ADDRQ_STAT) & TX_CNT_INUSE_MASK; ++ txq->skb[txq->tail] = NULL; ++ txq->tail = (txq->tail + 1) % txq->num; ++ } ++ ++ netdev_completed_queue(dev, pkts_compl, bytes_compl); ++ ++ if (unlikely(netif_queue_stopped(dev)) && pkts_compl) ++ netif_wake_queue(dev); ++ ++ netif_tx_unlock(dev); ++} ++ ++static void hisi_femac_get_tso_err_info(struct hisi_femac_priv *priv) ++{ ++ unsigned int reg_addr, reg_tx_info, reg_tx_err; ++ unsigned int sg_index; ++ struct tx_desc *sg_desc; ++ int *sg_word; ++ int i; ++ ++ reg_addr = readl(priv->port_base + TSO_DBG_ADDR); ++ reg_tx_info = readl(priv->port_base + TSO_DBG_TX_INFO); ++ reg_tx_err = readl(priv->port_base + TSO_DBG_TX_ERR); ++ ++ WARN(1, "tx err=0x%x, tx_info=0x%x, addr=0x%x\n", ++ reg_tx_err, reg_tx_info, reg_addr); ++ ++ sg_index = (reg_addr - priv->tx_ring.dma_phys) / sizeof(struct tx_desc); ++ sg_desc = priv->tx_ring.desc + sg_index; ++ sg_word = (int *)sg_desc; ++ for (i = 0; i < sizeof(struct tx_desc) / sizeof(int); i++) ++ pr_err("%s,%d: sg_desc word[%d]=0x%x\n", ++ __func__, __LINE__, i, sg_word[i]); ++ ++ /* restart MAC to transmit next packet */ ++ hisi_femac_irq_disable(priv, INT_TX_ERR); ++ /* The following is recovery code, ++ * allow netcard transmit packet again. ++ * But now we disable it for error debug. ++ */ ++#if 0 ++ readl(priv->port_base + TSO_DBG_STATE)); ++ hisi_femac_irq_enable(priv, INT_TX_ERR); ++#endif ++} ++ ++static netdev_tx_t hisi_femac_net_xmit(struct sk_buff *skb, ++ struct net_device *dev); ++ ++static netdev_tx_t hisi_femac_sw_gso(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ struct sk_buff *segs, *curr_skb; ++ netdev_features_t features = dev->features; ++ ++ features &= ~(NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | ++ NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO); ++ segs = skb_gso_segment(skb, features); ++ if (IS_ERR_OR_NULL(segs)) ++ goto drop; ++ ++ do { ++ curr_skb = segs; ++ segs = segs->next; ++ curr_skb->next = NULL; ++ if (hisi_femac_net_xmit(curr_skb, dev)) { ++ dev_kfree_skb(curr_skb); ++ while (segs) { ++ curr_skb = segs; ++ segs = segs->next; ++ curr_skb->next = NULL; ++ dev_kfree_skb_any(curr_skb); ++ } ++ goto drop; ++ } ++ } while (segs); ++ ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++ ++drop: ++ dev_kfree_skb_any(skb); ++ dev->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++} ++ ++static void hisi_femac_do_udp_checksum(struct sk_buff *skb) ++{ ++ int offset; ++ __wsum csum; ++ __sum16 udp_csum; ++ ++ offset = skb_checksum_start_offset(skb); ++ WARN_ON(offset >= skb_headlen(skb)); ++ csum = skb_checksum(skb, offset, skb->len - offset, 0); ++ ++ offset += skb->csum_offset; ++ WARN_ON(offset + sizeof(__sum16) > skb_headlen(skb)); ++ ++ udp_csum = csum_fold(csum); ++ if (udp_csum == 0) ++ udp_csum = CSUM_MANGLED_0; ++ ++ *(__sum16 *)(skb->data + offset) = udp_csum; ++ ++ skb->ip_summed = CHECKSUM_NONE; ++} ++ ++static inline __be16 hisi_femac_get_l3_proto(struct sk_buff *skb) ++{ ++ __be16 l3_proto; ++ ++ l3_proto = skb->protocol; ++ if (skb->protocol == htons(ETH_P_8021Q)) ++ l3_proto = vlan_get_protocol(skb); ++ ++ return l3_proto; ++} ++ ++static inline bool hisi_femac_skb_is_ipv6(struct sk_buff *skb) ++{ ++ return (hisi_femac_get_l3_proto(skb) == htons(ETH_P_IPV6)); ++} ++ ++static int hisi_femac_check_hw_capability_for_ipv6(struct sk_buff *skb) ++{ ++ unsigned int l4_proto = IPPROTO_MAX; ++ ++ l4_proto = ipv6_hdr(skb)->nexthdr; ++ ++ if ((l4_proto != IPPROTO_TCP) && (l4_proto != IPPROTO_UDP)) { ++ /* when IPv6 next header is not tcp or udp, ++ * it means that IPv6 next header is extension header. ++ * Hardware can't deal with this case, ++ * so do checksumming by software or do GSO by software. ++ */ ++ if (skb_is_gso(skb)) ++ return -ENOTSUPP; ++ ++ if (skb->ip_summed == CHECKSUM_PARTIAL && ++ skb_checksum_help(skb)) ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int hisi_femac_check_hw_capability(struct sk_buff *skb) ++{ ++ /* if tcp_mtu_probe() use (2 * tp->mss_cache) as probe_size, ++ * the linear data length will be larger than 2048, ++ * the MAC can't handle it, so let the software do it. ++ */ ++ if (skb_is_gso(skb) && (skb_headlen(skb) > 2048)) ++ return -ENOTSUPP; ++ ++ if (hisi_femac_skb_is_ipv6(skb)) ++ return hisi_femac_check_hw_capability_for_ipv6(skb); ++ ++ return 0; ++} ++ ++static u32 hisi_femac_get_pkt_info(struct sk_buff *skb) ++{ ++ __be16 l3_proto; ++ unsigned int l4_proto = IPPROTO_MAX; ++ bool do_txcsum = false; ++ int max_data_len = skb->len - ETH_HLEN; ++ unsigned int max_mss = ETH_DATA_LEN; ++ u32 pkt_info = 0; ++ ++ if (skb->ip_summed == CHECKSUM_PARTIAL) ++ do_txcsum = true; ++ ++ l3_proto = skb->protocol; ++ if (skb->protocol == htons(ETH_P_8021Q)) { ++ l3_proto = vlan_get_protocol(skb); ++ max_data_len -= VLAN_HLEN; ++ pkt_info |= BIT_FLAG_VLAN; ++ } ++ ++ if (l3_proto == htons(ETH_P_IP)) { ++ struct iphdr *iph = ip_hdr(skb); ++ ++ if ((max_data_len >= GSO_MAX_SIZE) && ++ (ntohs(iph->tot_len) <= (iph->ihl << 2))) ++ iph->tot_len = htons(GSO_MAX_SIZE - 1); ++ ++ max_mss -= iph->ihl * WORD_TO_BYTE; ++ pkt_info |= (iph->ihl << BIT_OFFSET_IP_HEADER_LEN); ++ l4_proto = iph->protocol; ++ } else if (l3_proto == htons(ETH_P_IPV6)) { ++ max_mss -= IPV6_HDR_LEN * WORD_TO_BYTE; ++ pkt_info |= BIT_FLAG_IPV6; ++ pkt_info |= (IPV6_HDR_LEN << BIT_OFFSET_IP_HEADER_LEN); ++ l4_proto = ipv6_hdr(skb)->nexthdr; ++ } else { ++ do_txcsum = false; ++ } ++ ++ if (l4_proto == IPPROTO_TCP) { ++ max_mss -= tcp_hdr(skb)->doff * WORD_TO_BYTE; ++ pkt_info |= (tcp_hdr(skb)->doff << BIT_OFFSET_PROT_HEADER_LEN); ++ } else if (l4_proto == IPPROTO_UDP) { ++ if (l3_proto == htons(ETH_P_IPV6)) ++ max_mss -= sizeof(struct frag_hdr); ++ pkt_info |= (BIT_FLAG_UDP | ++ (UDP_HDR_LEN << BIT_OFFSET_PROT_HEADER_LEN)); ++ } else { ++ do_txcsum = false; ++ } ++ ++ /* Although netcard support UFO feature, it can't deal with ++ * UDP header checksum. ++ * So the driver will do UDP header checksum and netcard will just ++ * fragment the packet. ++ */ ++ if (do_txcsum && skb_is_gso(skb) && (l4_proto == IPPROTO_UDP)) { ++ hisi_femac_do_udp_checksum(skb); ++ do_txcsum = false; ++ } ++ ++ if (do_txcsum) ++ pkt_info |= BIT_FLAG_TXCSUM; ++ ++ if (skb_is_gso(skb)) ++ pkt_info |= (BIT_FLAG_SG | BIT_FLAG_TSO); ++ else if (skb_shinfo(skb)->nr_frags) ++ pkt_info |= BIT_FLAG_SG; ++ ++ pkt_info |= (skb_shinfo(skb)->nr_frags << BIT_OFFSET_NFRAGS_NUM); ++ pkt_info |= (skb_is_gso(skb) ? ++ ((skb_shinfo(skb)->gso_size > max_mss) ? max_mss : ++ skb_shinfo(skb)->gso_size) : (skb->len + ETH_FCS_LEN)); ++ ++ return pkt_info; ++} ++ ++static int hisi_femac_fill_sg_desc(struct hisi_femac_priv *priv, ++ struct sk_buff *skb, unsigned int pos) ++{ ++ struct tx_desc *desc_cur; ++ dma_addr_t addr; ++ int ret; ++ int i; ++ ++ desc_cur = priv->tx_ring.desc + pos; ++ ++ desc_cur->ipv6_id = ntohl(skb_shinfo(skb)->ip6_frag_id); ++ ++ desc_cur->total_len = skb->len; ++ addr = dma_map_single(priv->dev, skb->data, skb_headlen(skb), ++ DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(priv->dev, addr))) ++ return -EINVAL; ++ desc_cur->linear_addr = addr; ++ desc_cur->linear_len = skb_headlen(skb); ++ ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { ++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ++ int len = frag->size; ++ ++ addr = skb_frag_dma_map(priv->dev, frag, 0, len, DMA_TO_DEVICE); ++ ret = dma_mapping_error(priv->dev, addr); ++ if (unlikely(ret)) ++ return -EINVAL; ++ desc_cur->frags[i].addr = addr; ++ desc_cur->frags[i].size = len; ++ } ++ ++ return 0; ++} ++ ++static void hisi_femac_adjust_link(struct net_device *dev) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ struct phy_device *phy = dev->phydev; ++ u32 status = 0; ++ ++ if (phy->link) ++ status |= MAC_PORTSET_LINKED; ++ if (phy->duplex == DUPLEX_FULL) ++ status |= MAC_PORTSET_DUPLEX_FULL; ++ if (phy->speed == SPEED_100) ++ status |= MAC_PORTSET_SPEED_100M; ++ ++ if ((status != priv->link_status) && ++ ((status | priv->link_status) & MAC_PORTSET_LINKED)) { ++ writel(status, priv->port_base + MAC_PORTSET); ++ priv->link_status = status; ++ phy_print_status(phy); ++ ++ priv->tx_pause_en = phy->pause; ++ hisi_femac_set_flow_ctrl(priv); ++ } ++} ++ ++static void hisi_femac_rx_refill(struct hisi_femac_priv *priv) ++{ ++ struct hisi_femac_queue *rxq = &priv->rxq; ++ struct sk_buff *skb; ++ u32 pos; ++ u32 len = MAX_FRAME_SIZE; ++ dma_addr_t addr; ++ u32 alloc_rxbuf_align = 0; ++ int reserve_room = 0; ++ ++ pos = rxq->head; ++ while (readl(priv->port_base + ADDRQ_STAT) & BIT_RX_READY) { ++ if (!CIRC_SPACE(pos, rxq->tail, rxq->num)) ++ break; ++ if (unlikely(rxq->skb[pos])) { ++ netdev_err(priv->ndev, "err skb[%d]=%p\n", ++ pos, rxq->skb[pos]); ++ break; ++ } ++ len = MAX_FRAME_SIZE + RXBUF_ADDR_ALIGN_SIZE; ++ skb = netdev_alloc_skb_ip_align(priv->ndev, len); ++ if (unlikely(!skb)) ++ break; ++ ++ alloc_rxbuf_align = ((unsigned long)skb->data - NET_IP_ALIGN) & ++ (RXBUF_ADDR_ALIGN_SIZE - 1); ++ if (alloc_rxbuf_align) { ++ reserve_room = RXBUF_ADDR_ALIGN_SIZE - alloc_rxbuf_align; ++ len -= reserve_room; ++ skb_reserve(skb, reserve_room); ++ } ++ ++ addr = dma_map_single(priv->dev, skb->data, len, ++ DMA_FROM_DEVICE); ++ if (dma_mapping_error(priv->dev, addr)) { ++ dev_kfree_skb_any(skb); ++ break; ++ } ++ rxq->dma_phys[pos] = addr; ++ rxq->skb[pos] = skb; ++ writel(addr, priv->port_base + IQ_ADDR); ++ pos = (pos + 1) % rxq->num; ++ } ++ rxq->head = pos; ++} ++ ++static u32 hisi_femac_rx(struct net_device *dev, int limit) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ struct hisi_femac_queue *rxq = &priv->rxq; ++ struct sk_buff *skb; ++ dma_addr_t addr; ++ u32 rx_pkt_info, pos, len, rx_pkts_num = 0; ++ int hdr_csum_done, hdr_csum_err; ++ int payload_csum_done, payload_csum_err; ++ ++ pos = rxq->tail; ++ while (readl(priv->glb_base + GLB_IRQ_RAW) & IRQ_INT_RX_RDY) { ++ rx_pkt_info = readl(priv->port_base + IQFRM_DES); ++ len = rx_pkt_info & RX_FRAME_LEN_MASK; ++ len -= ETH_FCS_LEN; ++ ++ /* tell hardware we will deal with this packet */ ++ writel(IRQ_INT_RX_RDY, priv->glb_base + GLB_IRQ_RAW); ++ ++ rx_pkts_num++; ++ ++ skb = rxq->skb[pos]; ++ if (unlikely(!skb)) { ++ netdev_err(dev, "rx skb NULL. pos=%d\n", pos); ++ break; ++ } ++ rxq->skb[pos] = NULL; ++ ++ addr = rxq->dma_phys[pos]; ++ dma_unmap_single(priv->dev, addr, MAX_FRAME_SIZE, ++ DMA_FROM_DEVICE); ++ skb_put(skb, len); ++ if (unlikely(skb->len > MAX_FRAME_SIZE)) { ++ netdev_err(dev, "rcv len err, len = %d\n", skb->len); ++ dev->stats.rx_errors++; ++ dev->stats.rx_length_errors++; ++ dev_kfree_skb_any(skb); ++ goto next; ++ } ++ ++ skb->ip_summed = CHECKSUM_NONE; ++ if (dev->features & NETIF_F_RXCSUM) { ++ hdr_csum_done = ++ (rx_pkt_info >> BITS_HEADER_DONE_OFFSET) & ++ BITS_HEADER_DONE_MASK; ++ payload_csum_done = ++ (rx_pkt_info >> BITS_PAYLOAD_DONE_OFFSET) & ++ BITS_PAYLOAD_DONE_MASK; ++ hdr_csum_err = ++ (rx_pkt_info >> BITS_HEADER_ERR_OFFSET) & ++ BITS_HEADER_ERR_MASK; ++ payload_csum_err = ++ (rx_pkt_info >> BITS_PAYLOAD_ERR_OFFSET) & ++ BITS_PAYLOAD_ERR_MASK; ++ ++ if (hdr_csum_done && payload_csum_done) { ++ if (unlikely(hdr_csum_err)) { ++ dev->stats.rx_errors++; ++ dev->stats.rx_crc_errors++; ++ dev_kfree_skb_any(skb); ++ goto next; ++ } else if (!payload_csum_err) { ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ } ++ } ++ } ++ ++ skb->protocol = eth_type_trans(skb, dev); ++ napi_gro_receive(&priv->napi, skb); ++ dev->stats.rx_packets++; ++ dev->stats.rx_bytes += len; ++next: ++ pos = (pos + 1) % rxq->num; ++ if (rx_pkts_num >= limit) ++ break; ++ } ++ rxq->tail = pos; ++ ++ hisi_femac_rx_refill(priv); ++ ++ return rx_pkts_num; ++} ++ ++static int hisi_femac_poll(struct napi_struct *napi, int budget) ++{ ++ struct hisi_femac_priv *priv = container_of(napi, ++ struct hisi_femac_priv, napi); ++ struct net_device *dev = priv->ndev; ++ int work_done = 0, task = budget; ++ u32 ints, num; ++ ++ do { ++ hisi_femac_xmit_reclaim(dev); ++ num = hisi_femac_rx(dev, task); ++ work_done += num; ++ task -= num; ++ if (work_done >= budget) ++ break; ++ ++ ints = readl(priv->glb_base + GLB_IRQ_RAW); ++ writel(ints & DEF_INT_MASK, ++ priv->glb_base + GLB_IRQ_RAW); ++ } while (ints & DEF_INT_MASK); ++ ++ if (work_done < budget) { ++ napi_complete(napi); ++ hisi_femac_irq_enable(priv, DEF_INT_MASK & ++ (~IRQ_INT_TX_PER_PACKET)); ++ } ++ ++ return work_done; ++} ++ ++static irqreturn_t hisi_femac_interrupt(int irq, void *dev_id) ++{ ++ u32 ints; ++ struct net_device *dev = (struct net_device *)dev_id; ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ ++ ints = readl(priv->glb_base + GLB_IRQ_RAW); ++ ++ if (likely(ints & DEF_INT_MASK)) { ++ writel(ints & DEF_INT_MASK, ++ priv->glb_base + GLB_IRQ_RAW); ++ hisi_femac_irq_disable(priv, DEF_INT_MASK); ++ napi_schedule(&priv->napi); ++ } ++ ++ if (HAS_TSO_CAP(priv->hw_cap) && ++ unlikely(ints & INT_TX_ERR)) ++ hisi_femac_get_tso_err_info(priv); ++ ++ return IRQ_HANDLED; ++} ++ ++static int hisi_femac_init_tx_descriptor_ring(struct hisi_femac_priv *priv) ++{ ++ priv->tx_ring.desc = (struct tx_desc *)dma_zalloc_coherent(priv->dev, ++ TXQ_NUM * sizeof(struct tx_desc), ++ &priv->tx_ring.dma_phys, ++ GFP_KERNEL); ++ if (!priv->tx_ring.desc) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++static void hisi_femac_destroy_tx_descriptor_ring(struct hisi_femac_priv *priv) ++{ ++ if (priv->tx_ring.desc) ++ dma_free_coherent(priv->dev, ++ TXQ_NUM * sizeof(struct tx_desc), ++ priv->tx_ring.desc, priv->tx_ring.dma_phys); ++ priv->tx_ring.desc = NULL; ++} ++ ++static int hisi_femac_init_queue(struct device *dev, ++ struct hisi_femac_queue *queue, ++ unsigned int num) ++{ ++ queue->skb = devm_kcalloc(dev, num, sizeof(struct sk_buff *), ++ GFP_KERNEL); ++ if (!queue->skb) ++ return -ENOMEM; ++ ++ queue->dma_phys = devm_kcalloc(dev, num, sizeof(dma_addr_t), ++ GFP_KERNEL); ++ if (!queue->dma_phys) ++ return -ENOMEM; ++ ++ queue->num = num; ++ queue->head = 0; ++ queue->tail = 0; ++ ++ return 0; ++} ++ ++static int hisi_femac_init_tx_and_rx_queues(struct hisi_femac_priv *priv) ++{ ++ int ret; ++ ++ ret = hisi_femac_init_queue(priv->dev, &priv->txq, TXQ_NUM); ++ if (ret) ++ return ret; ++ ++ ret = hisi_femac_init_queue(priv->dev, &priv->rxq, RXQ_NUM); ++ if (ret) ++ return ret; ++ ++ priv->tx_fifo_used_cnt = 0; ++ ++ return 0; ++} ++ ++static void hisi_femac_free_skb_rings(struct hisi_femac_priv *priv) ++{ ++ struct hisi_femac_queue *txq = &priv->txq; ++ struct hisi_femac_queue *rxq = &priv->rxq; ++ struct sk_buff *skb; ++ dma_addr_t dma_addr; ++ u32 pos; ++ ++ pos = rxq->tail; ++ while (pos != rxq->head) { ++ skb = rxq->skb[pos]; ++ if (unlikely(!skb)) { ++ netdev_err(priv->ndev, "NULL rx skb. pos=%d, head=%d\n", ++ pos, rxq->head); ++ continue; ++ } ++ ++ dma_addr = rxq->dma_phys[pos]; ++ dma_unmap_single(priv->dev, dma_addr, MAX_FRAME_SIZE, ++ DMA_FROM_DEVICE); ++ ++ dev_kfree_skb_any(skb); ++ rxq->skb[pos] = NULL; ++ pos = (pos + 1) % rxq->num; ++ } ++ rxq->tail = pos; ++ ++ pos = txq->tail; ++ while (pos != txq->head) { ++ skb = txq->skb[pos]; ++ if (unlikely(!skb)) { ++ netdev_err(priv->ndev, "NULL tx skb. pos=%d, head=%d\n", ++ pos, txq->head); ++ continue; ++ } ++ hisi_femac_tx_dma_unmap(priv, skb, pos); ++ dev_kfree_skb_any(skb); ++ txq->skb[pos] = NULL; ++ pos = (pos + 1) % txq->num; ++ } ++ txq->tail = pos; ++ priv->tx_fifo_used_cnt = 0; ++} ++ ++static int hisi_femac_set_hw_mac_addr(struct hisi_femac_priv *priv, ++ unsigned char *mac) ++{ ++ u32 reg; ++ ++ reg = mac[1] | (mac[0] << 8); ++ writel(reg, priv->glb_base + GLB_HOSTMAC_H16); ++ ++ reg = mac[5] | (mac[4] << 8) | (mac[3] << 16) | (mac[2] << 24); ++ writel(reg, priv->glb_base + GLB_HOSTMAC_L32); ++ ++ return 0; ++} ++ ++static int hisi_femac_port_reset(struct hisi_femac_priv *priv) ++{ ++ u32 val; ++ ++ val = readl(priv->glb_base + GLB_SOFT_RESET); ++ val |= SOFT_RESET_ALL; ++ writel(val, priv->glb_base + GLB_SOFT_RESET); ++ ++ usleep_range(500, 800); ++ ++ val &= ~SOFT_RESET_ALL; ++ writel(val, priv->glb_base + GLB_SOFT_RESET); ++ ++ return 0; ++} ++ ++static int hisi_femac_net_open(struct net_device *dev) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ ++ hisi_femac_set_hw_mac_addr(priv, dev->dev_addr); ++ /* clear interrupts will drop the first packet MAC have received, ++ * so do it before refill the rx free skbs. ++ */ ++ writel(IRQ_ENA_PORT0_MASK, priv->glb_base + GLB_IRQ_RAW); ++ hisi_femac_rx_refill(priv); ++ ++ netif_carrier_off(dev); ++ netdev_reset_queue(dev); ++ netif_start_queue(dev); ++ napi_enable(&priv->napi); ++ ++ priv->link_status = 0; ++ if (dev->phydev) ++ phy_start(dev->phydev); ++ ++ hisi_femac_irq_enable(priv, IRQ_ENA_ALL | IRQ_ENA_PORT0 | DEF_INT_MASK); ++ if (HAS_TSO_CAP(priv->hw_cap)) ++ hisi_femac_irq_enable(priv, INT_TX_ERR); ++ ++ return 0; ++} ++ ++static void hisi_femac_port_init(struct hisi_femac_priv *priv); ++ ++static int hisi_femac_net_close(struct net_device *dev) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ ++ hisi_femac_irq_disable(priv, IRQ_ENA_PORT0); ++ ++ if (dev->phydev) ++ phy_stop(dev->phydev); ++ ++ netif_stop_queue(dev); ++ napi_disable(&priv->napi); ++ ++ /* reset MAC port first before free skb rings ++ * to prevent potential risk of use-after-free. ++ */ ++ hisi_femac_port_reset(priv); ++ hisi_femac_port_init(priv); ++ ++ priv->tx_pause_en = false; ++ hisi_femac_set_flow_ctrl(priv); ++ hisi_femac_free_skb_rings(priv); ++ ++ return 0; ++} ++ ++static netdev_tx_t hisi_femac_net_xmit(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ struct hisi_femac_queue *txq = &priv->txq; ++ dma_addr_t addr; ++ int ret; ++ u32 pkt_info; ++ u32 val; ++ ++ val = readl(priv->port_base + ADDRQ_STAT); ++ val &= BIT_TX_READY; ++ if (!val) { ++ hisi_femac_irq_enable(priv, IRQ_INT_TX_PER_PACKET); ++ dev->stats.tx_dropped++; ++ dev->stats.tx_fifo_errors++; ++ netif_stop_queue(dev); ++ return NETDEV_TX_BUSY; ++ } ++ ++ if (unlikely(!CIRC_SPACE(txq->head, txq->tail, ++ txq->num))) { ++ hisi_femac_irq_enable(priv, IRQ_INT_TX_PER_PACKET); ++ dev->stats.tx_dropped++; ++ dev->stats.tx_fifo_errors++; ++ netif_stop_queue(dev); ++ return NETDEV_TX_BUSY; ++ } ++ ++ ret = hisi_femac_check_hw_capability(skb); ++ if (unlikely(ret)) { ++ if (ret == -ENOTSUPP) ++ return hisi_femac_sw_gso(skb, dev); ++ ++ dev_kfree_skb_any(skb); ++ dev->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++ } ++ ++ pkt_info = hisi_femac_get_pkt_info(skb); ++ ++ if (!(skb_is_gso(skb) || skb_shinfo(skb)->nr_frags)) { ++ addr = dma_map_single(priv->dev, skb->data, ++ skb->len, DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(priv->dev, addr))) { ++ dev_kfree_skb_any(skb); ++ dev->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++ } ++ } else { ++ ret = hisi_femac_fill_sg_desc(priv, skb, txq->head); ++ if (unlikely(ret)) { ++ dev_kfree_skb_any(skb); ++ dev->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++ } ++ ++ addr = priv->tx_ring.dma_phys + ++ txq->head * sizeof(struct tx_desc); ++ ++ /* Ensure desc info writen to memory before config hardware */ ++ wmb(); ++ } ++ txq->dma_phys[txq->head] = addr; ++ ++ txq->skb[txq->head] = skb; ++ txq->head = (txq->head + 1) % txq->num; ++ ++ writel(addr, priv->port_base + EQ_ADDR); ++ writel(pkt_info, priv->port_base + EQFRM_LEN); ++ ++ priv->tx_fifo_used_cnt++; ++ ++ dev->stats.tx_packets++; ++ dev->stats.tx_bytes += skb->len; ++ netdev_sent_queue(dev, skb->len); ++ ++ return NETDEV_TX_OK; ++} ++ ++static int hisi_femac_set_mac_address(struct net_device *dev, void *p) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ struct sockaddr *skaddr = p; ++ ++ if (!is_valid_ether_addr(skaddr->sa_data)) ++ return -EADDRNOTAVAIL; ++ ++ memcpy(dev->dev_addr, skaddr->sa_data, dev->addr_len); ++ dev->addr_assign_type &= ~NET_ADDR_RANDOM; ++ ++ hisi_femac_set_hw_mac_addr(priv, dev->dev_addr); ++ ++ return 0; ++} ++ ++static void hisi_femac_enable_hw_addr_filter(struct hisi_femac_priv *priv, ++ unsigned int reg_n, bool enable) ++{ ++ u32 val; ++ ++ val = readl(priv->glb_base + GLB_MAC_H16(reg_n)); ++ if (enable) ++ val |= BIT_MACFLT_ENA; ++ else ++ val &= ~BIT_MACFLT_ENA; ++ writel(val, priv->glb_base + GLB_MAC_H16(reg_n)); ++} ++ ++static void hisi_femac_set_hw_addr_filter(struct hisi_femac_priv *priv, ++ unsigned char *addr, ++ unsigned int reg_n) ++{ ++ unsigned int high, low; ++ u32 val; ++ ++ high = GLB_MAC_H16(reg_n); ++ low = GLB_MAC_L32(reg_n); ++ ++ val = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | addr[5]; ++ writel(val, priv->glb_base + low); ++ ++ val = readl(priv->glb_base + high); ++ val &= ~MACFLT_HI16_MASK; ++ val |= ((addr[0] << 8) | addr[1]); ++ val |= (BIT_MACFLT_ENA | BIT_MACFLT_FW2CPU); ++ writel(val, priv->glb_base + high); ++} ++ ++static void hisi_femac_set_promisc_mode(struct hisi_femac_priv *priv, ++ bool promisc_mode) ++{ ++ u32 val; ++ ++ val = readl(priv->glb_base + GLB_FWCTRL); ++ if (promisc_mode) ++ val |= FWCTRL_FWALL2CPU; ++ else ++ val &= ~FWCTRL_FWALL2CPU; ++ writel(val, priv->glb_base + GLB_FWCTRL); ++} ++ ++/* Handle multiple multicast addresses (perfect filtering)*/ ++static void hisi_femac_set_mc_addr_filter(struct hisi_femac_priv *priv) ++{ ++ struct net_device *dev = priv->ndev; ++ u32 val; ++ ++ val = readl(priv->glb_base + GLB_MACTCTRL); ++ if ((netdev_mc_count(dev) > MAX_MULTICAST_ADDRESSES) || ++ (dev->flags & IFF_ALLMULTI)) { ++ val |= MACTCTRL_MULTI2CPU; ++ } else { ++ int reg = MAX_UNICAST_ADDRESSES; ++ int i; ++ struct netdev_hw_addr *ha; ++ ++ for (i = reg; i < MAX_MAC_FILTER_NUM; i++) ++ hisi_femac_enable_hw_addr_filter(priv, i, false); ++ ++ netdev_for_each_mc_addr(ha, dev) { ++ hisi_femac_set_hw_addr_filter(priv, ha->addr, reg); ++ reg++; ++ } ++ val &= ~MACTCTRL_MULTI2CPU; ++ } ++ writel(val, priv->glb_base + GLB_MACTCTRL); ++} ++ ++/* Handle multiple unicast addresses (perfect filtering)*/ ++static void hisi_femac_set_uc_addr_filter(struct hisi_femac_priv *priv) ++{ ++ struct net_device *dev = priv->ndev; ++ u32 val; ++ ++ val = readl(priv->glb_base + GLB_MACTCTRL); ++ if (netdev_uc_count(dev) > MAX_UNICAST_ADDRESSES) { ++ val |= MACTCTRL_UNI2CPU; ++ } else { ++ int reg = 0; ++ int i; ++ struct netdev_hw_addr *ha; ++ ++ for (i = reg; i < MAX_UNICAST_ADDRESSES; i++) ++ hisi_femac_enable_hw_addr_filter(priv, i, false); ++ ++ netdev_for_each_uc_addr(ha, dev) { ++ hisi_femac_set_hw_addr_filter(priv, ha->addr, reg); ++ reg++; ++ } ++ val &= ~MACTCTRL_UNI2CPU; ++ } ++ writel(val, priv->glb_base + GLB_MACTCTRL); ++} ++ ++static void hisi_femac_net_set_rx_mode(struct net_device *dev) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ ++ if (dev->flags & IFF_PROMISC) { ++ hisi_femac_set_promisc_mode(priv, true); ++ } else { ++ hisi_femac_set_promisc_mode(priv, false); ++ hisi_femac_set_mc_addr_filter(priv); ++ hisi_femac_set_uc_addr_filter(priv); ++ } ++} ++ ++static int hisi_femac_net_ioctl(struct net_device *dev, ++ struct ifreq *ifreq, int cmd) ++{ ++ if (!netif_running(dev)) ++ return -EINVAL; ++ ++ if (!dev->phydev) ++ return -EINVAL; ++ ++ return phy_mii_ioctl(dev->phydev, ifreq, cmd); ++} ++ ++static void hisi_femac_get_pauseparam(struct net_device *dev, ++ struct ethtool_pauseparam *pause) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ ++ pause->autoneg = dev->phydev->autoneg; ++ pause->rx_pause = 1; ++ if (priv->tx_pause_en) ++ pause->tx_pause = 1; ++} ++ ++static int hisi_femac_set_pauseparam(struct net_device *dev, ++ struct ethtool_pauseparam *pause) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ struct phy_device *phy = dev->phydev; ++ int ret = 0; ++ ++ if (pause->rx_pause == 0) ++ return -EINVAL; ++ ++ if (pause->tx_pause != priv->tx_pause_en) { ++ priv->tx_pause_en = pause->tx_pause; ++ hisi_femac_set_flow_ctrl(priv); ++ } ++ ++ if (phy->autoneg) { ++ if (netif_running(dev)) { ++ struct ethtool_cmd cmd; ++ /* auto-negotiation automatically restarted */ ++ cmd.cmd = ETHTOOL_NWAY_RST; ++ cmd.supported = phy->supported; ++ cmd.advertising = phy->advertising; ++ cmd.autoneg = phy->autoneg; ++ cmd.speed = phy->speed; ++ cmd.duplex = phy->duplex; ++ cmd.phy_address = phy->addr; ++ ret = phy_ethtool_sset(phy, &cmd); ++ } ++ } ++ ++ return ret; ++} ++ ++static void hisi_femac_enable_rxcsum_drop(struct hisi_femac_priv *priv, ++ bool drop) ++{ ++ unsigned int val; ++ ++ val = readl(priv->port_base + RX_COE_CTRL); ++ val &= ~COE_ERR_DROP; ++ if (drop) ++ val |= (BIT_COE_IPHDR_DROP | BIT_COE_IPV6_UDP_ZERO_DROP); ++ writel(val, priv->port_base + RX_COE_CTRL); ++} ++ ++static int hisi_femac_set_features(struct net_device *dev, ++ netdev_features_t features) ++{ ++ struct hisi_femac_priv *priv = netdev_priv(dev); ++ netdev_features_t changed = dev->features ^ features; ++ ++ if (changed & NETIF_F_RXCSUM) { ++ if (features & NETIF_F_RXCSUM) ++ hisi_femac_enable_rxcsum_drop(priv, true); ++ else ++ hisi_femac_enable_rxcsum_drop(priv, false); ++ } ++ ++ return 0; ++} ++ ++static int hisi_femac_get_settings(struct net_device *ndev, ++ struct ethtool_cmd *cmd) ++{ ++ if (!ndev->phydev) ++ return -EINVAL; ++ ++ return phy_ethtool_gset(ndev->phydev, cmd); ++} ++ ++static int hisi_femac_set_settings(struct net_device *ndev, ++ struct ethtool_cmd *cmd) ++{ ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ ++ if (!ndev->phydev) ++ return -EINVAL; ++ ++ return phy_ethtool_sset(ndev->phydev, cmd); ++} ++ ++static struct ethtool_ops hisi_femac_ethtools_ops = { ++ .get_link = ethtool_op_get_link, ++ .get_settings = hisi_femac_get_settings, ++ .set_settings = hisi_femac_set_settings, ++ .get_pauseparam = hisi_femac_get_pauseparam, ++ .set_pauseparam = hisi_femac_set_pauseparam, ++}; ++ ++static const struct net_device_ops hisi_femac_netdev_ops = { ++ .ndo_open = hisi_femac_net_open, ++ .ndo_stop = hisi_femac_net_close, ++ .ndo_start_xmit = hisi_femac_net_xmit, ++ .ndo_do_ioctl = hisi_femac_net_ioctl, ++ .ndo_set_mac_address = hisi_femac_set_mac_address, ++ .ndo_set_rx_mode = hisi_femac_net_set_rx_mode, ++ .ndo_change_mtu = eth_change_mtu, ++ .ndo_set_features = hisi_femac_set_features, ++}; ++ ++static void hisi_femac_verify_flow_ctrl_args(struct hisi_femac_priv *priv) ++{ ++ if (priv->tx_pause_active_thresh < FC_ACTIVE_MIN || ++ priv->tx_pause_active_thresh > FC_ACTIVE_MAX) ++ priv->tx_pause_active_thresh = FC_ACTIVE_DEFAULT; ++ ++ if (priv->tx_pause_deactive_thresh < FC_DEACTIVE_MIN || ++ priv->tx_pause_deactive_thresh > FC_DEACTIVE_MAX) ++ priv->tx_pause_deactive_thresh = FC_DEACTIVE_DEFAULT; ++ ++ if (priv->tx_pause_active_thresh >= priv->tx_pause_deactive_thresh) { ++ priv->tx_pause_active_thresh = FC_ACTIVE_DEFAULT; ++ priv->tx_pause_deactive_thresh = FC_DEACTIVE_DEFAULT; ++ } ++} ++ ++static void hisi_femac_core_reset(struct hisi_femac_priv *priv) ++{ ++ reset_control_assert(priv->mac_rst); ++ reset_control_deassert(priv->mac_rst); ++} ++ ++static void hisi_femac_sleep_us(u32 time_us) ++{ ++ u32 time_ms; ++ ++ if (!time_us) ++ return; ++ ++ time_ms = DIV_ROUND_UP(time_us, 1000); ++ if (time_ms < 20) ++ usleep_range(time_us, time_us + 500); ++ else ++ msleep(time_ms); ++} ++ ++static void hisi_femac_phy_reset(struct hisi_femac_priv *priv) ++{ ++ /* To make sure PHY hardware reset success, ++ * we must keep PHY in deassert state first and ++ * then complete the hardware reset operation ++ */ ++ reset_control_deassert(priv->phy_rst); ++ hisi_femac_sleep_us(priv->phy_reset_delays[PRE_DELAY]); ++ ++ reset_control_assert(priv->phy_rst); ++ /* delay some time to ensure reset ok, ++ * this depends on PHY hardware feature ++ */ ++ hisi_femac_sleep_us(priv->phy_reset_delays[PULSE]); ++ reset_control_deassert(priv->phy_rst); ++ /* delay some time to ensure later MDIO access */ ++ hisi_femac_sleep_us(priv->phy_reset_delays[POST_DELAY]); ++} ++ ++static void hisi_femac_port_init(struct hisi_femac_priv *priv) ++{ ++ u32 val; ++ ++ /* MAC gets link status info and phy mode by software config */ ++ val = MAC_PORTSEL_STAT_CPU; ++ if (priv->ndev->phydev->interface == PHY_INTERFACE_MODE_RMII) ++ val |= MAC_PORTSEL_RMII; ++ writel(val, priv->port_base + MAC_PORTSEL); ++ ++ /*clear all interrupt status */ ++ writel(IRQ_ENA_PORT0_MASK, priv->glb_base + GLB_IRQ_RAW); ++ hisi_femac_irq_disable(priv, IRQ_ENA_PORT0_MASK | IRQ_ENA_PORT0); ++ ++ if (HAS_TSO_CAP(priv->hw_cap)) { ++ /* enable TSO debug for error handle */ ++ val = readl(priv->port_base + TSO_DBG_EN); ++ val |= BITS_TSO_DBG_EN; ++ writel(val, priv->port_base + TSO_DBG_EN); ++ } ++ ++ val = readl(priv->glb_base + GLB_FWCTRL); ++ val &= ~(FWCTRL_VLAN_ENABLE | FWCTRL_FWALL2CPU); ++ val |= FWCTRL_FW2CPU_ENA; ++ writel(val, priv->glb_base + GLB_FWCTRL); ++ ++ val = readl(priv->glb_base + GLB_MACTCTRL); ++ val |= (MACTCTRL_BROAD2CPU | MACTCTRL_MACT_ENA); ++ writel(val, priv->glb_base + GLB_MACTCTRL); ++ ++ val = readl(priv->port_base + MAC_SET); ++ val &= ~MAX_FRAME_SIZE_MASK; ++ val |= MAX_FRAME_SIZE; ++ writel(val, priv->port_base + MAC_SET); ++ ++ val = RX_COALESCED_TIMER | ++ (RX_COALESCED_FRAMES << RX_COALESCED_FRAME_OFFSET); ++ writel(val, priv->port_base + RX_COALESCE_SET); ++ ++ val = (HW_RX_FIFO_DEPTH << RX_DEPTH_OFFSET) | HW_TX_FIFO_DEPTH; ++ writel(val, priv->port_base + QLEN_SET); ++ ++ hisi_femac_set_flow_ctrl(priv); ++} ++ ++static int hisi_femac_drv_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *node = dev->of_node; ++ struct resource *res; ++ struct net_device *ndev; ++ struct hisi_femac_priv *priv; ++ struct phy_device *phy; ++ const char *mac_addr; ++ int ret; ++ ++ ndev = alloc_etherdev(sizeof(*priv)); ++ if (!ndev) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, ndev); ++ ++ priv = netdev_priv(ndev); ++ priv->dev = dev; ++ priv->ndev = ndev; ++ ++ if (of_device_is_compatible(node, "hisilicon,hisi-femac-v2")) ++ priv->hw_cap |= HW_CAP_TSO | HW_CAP_RXCSUM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ priv->port_base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(priv->port_base)) { ++ ret = PTR_ERR(priv->port_base); ++ goto out_free_netdev; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ priv->glb_base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(priv->glb_base)) { ++ ret = PTR_ERR(priv->glb_base); ++ goto out_free_netdev; ++ } ++ ++ priv->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(priv->clk)) { ++ dev_err(dev, "failed to get clk\n"); ++ ret = -ENODEV; ++ goto out_free_netdev; ++ } ++ ++ ret = clk_prepare_enable(priv->clk); ++ if (ret) { ++ dev_err(dev, "failed to enable clk %d\n", ret); ++ goto out_free_netdev; ++ } ++ ++ priv->mac_rst = devm_reset_control_get(dev, "mac"); ++ if (IS_ERR(priv->mac_rst)) { ++ ret = PTR_ERR(priv->mac_rst); ++ goto out_disable_clk; ++ } ++ hisi_femac_core_reset(priv); ++ ++ priv->phy_rst = devm_reset_control_get(dev, "phy"); ++ if (IS_ERR(priv->phy_rst)) { ++ priv->phy_rst = NULL; ++ } else { ++ ret = of_property_read_u32_array(node, ++ PHY_RESET_DELAYS_PROPERTY, ++ priv->phy_reset_delays, ++ DELAYS_NUM); ++ if (ret) ++ goto out_disable_clk; ++ hisi_femac_phy_reset(priv); ++ } ++ ++ phy = of_phy_get_and_connect(ndev, node, hisi_femac_adjust_link); ++ if (!phy) { ++ dev_err(dev, "connect to PHY failed!\n"); ++ ret = -ENODEV; ++ goto out_disable_clk; ++ } ++ ++ phy->advertising |= ADVERTISED_Pause; ++ phy->supported |= ADVERTISED_Pause; ++ ++ dev_info(dev, "phy_id=0x%.8lx, phy_addr=%d, phy_mode=%s\n", ++ (unsigned long)phy->phy_id, ++ phy->addr, ++ phy_modes(phy->interface)); ++ ++ mac_addr = of_get_mac_address(node); ++ if (mac_addr) ++ ether_addr_copy(ndev->dev_addr, mac_addr); ++ if (!is_valid_ether_addr(ndev->dev_addr)) { ++ eth_hw_addr_random(ndev); ++ dev_warn(dev, "using random MAC address %pM\n", ++ ndev->dev_addr); ++ } ++ ++ ndev->watchdog_timeo = 6 * HZ; ++ ndev->priv_flags |= IFF_UNICAST_FLT; ++ ndev->netdev_ops = &hisi_femac_netdev_ops; ++ ndev->ethtool_ops = &hisi_femac_ethtools_ops; ++ netif_napi_add(ndev, &priv->napi, hisi_femac_poll, FEMAC_POLL_WEIGHT); ++ SET_NETDEV_DEV(ndev, &pdev->dev); ++ ++ if (HAS_TSO_CAP(priv->hw_cap)) ++ ndev->hw_features |= NETIF_F_SG | ++ NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | ++ NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO; ++ ++ if (HAS_RXCSUM_CAP(priv->hw_cap)) ++ ndev->hw_features |= NETIF_F_RXCSUM; ++ ndev->features |= ndev->hw_features; ++ ndev->vlan_features |= ndev->features; ++ ++ device_set_wakeup_capable(priv->dev, true); ++ device_set_wakeup_enable(priv->dev, true); ++ ++ priv->tx_pause_en = true; ++ priv->tx_pause_active_thresh = TX_FLOW_CTRL_ACTIVE_THRESHOLD; ++ priv->tx_pause_deactive_thresh = TX_FLOW_CTRL_DEACTIVE_THRESHOLD; ++ ++ hisi_femac_verify_flow_ctrl_args(priv); ++ ++ hisi_femac_port_init(priv); ++ ++ if (HAS_RXCSUM_CAP(priv->hw_cap)) ++ hisi_femac_enable_rxcsum_drop(priv, true); ++ ++ ret = hisi_femac_init_tx_and_rx_queues(priv); ++ if (ret) ++ goto out_disconnect_phy; ++ ++ if (HAS_TSO_CAP(priv->hw_cap)) { ++ ret = hisi_femac_init_tx_descriptor_ring(priv); ++ if (ret) ++ goto out_disconnect_phy; ++ } ++ ++ ndev->irq = platform_get_irq(pdev, 0); ++ if (ndev->irq <= 0) { ++ dev_err(dev, "No irq resource\n"); ++ ret = -ENODEV; ++ goto out_destroy_descriptor; ++ } ++ ++ ret = devm_request_irq(dev, ndev->irq, hisi_femac_interrupt, ++ IRQF_SHARED, pdev->name, ndev); ++ if (ret) { ++ dev_err(dev, "devm_request_irq %d failed!\n", ndev->irq); ++ goto out_destroy_descriptor; ++ } ++ ++ ret = register_netdev(ndev); ++ if (ret) { ++ dev_err(dev, "register_netdev failed!\n"); ++ goto out_destroy_descriptor; ++ } ++ ++ return ret; ++ ++out_destroy_descriptor: ++ if (HAS_TSO_CAP(priv->hw_cap)) ++ hisi_femac_destroy_tx_descriptor_ring(priv); ++out_disconnect_phy: ++ netif_napi_del(&priv->napi); ++ phy_disconnect(phy); ++out_disable_clk: ++ clk_disable_unprepare(priv->clk); ++out_free_netdev: ++ free_netdev(ndev); ++ ++ return ret; ++} ++ ++static int hisi_femac_drv_remove(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct hisi_femac_priv *priv = netdev_priv(ndev); ++ ++ netif_napi_del(&priv->napi); ++ unregister_netdev(ndev); ++ if (HAS_TSO_CAP(priv->hw_cap)) ++ hisi_femac_destroy_tx_descriptor_ring(priv); ++ ++ phy_disconnect(ndev->phydev); ++ clk_disable_unprepare(priv->clk); ++ free_netdev(ndev); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++int hisi_femac_drv_suspend(struct platform_device *pdev, ++ pm_message_t state) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct hisi_femac_priv *priv = netdev_priv(ndev); ++ ++ disable_irq(ndev->irq); ++ if (netif_running(ndev)) { ++ hisi_femac_net_close(ndev); ++ netif_device_detach(ndev); ++ } ++ ++ clk_disable_unprepare(priv->clk); ++ ++ return 0; ++} ++ ++int hisi_femac_drv_resume(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct hisi_femac_priv *priv = netdev_priv(ndev); ++ ++ clk_prepare_enable(priv->clk); ++ if (priv->phy_rst) ++ hisi_femac_phy_reset(priv); ++ ++ if (netif_running(ndev)) { ++ hisi_femac_port_init(priv); ++ hisi_femac_net_open(ndev); ++ netif_device_attach(ndev); ++ } ++ enable_irq(ndev->irq); ++ ++ return 0; ++} ++#endif ++ ++static const struct of_device_id hisi_femac_match[] = { ++ {.compatible = "hisilicon,hisi-femac-v1",}, ++ {.compatible = "hisilicon,hisi-femac-v2",}, ++ {.compatible = "hisilicon,hi3516cv300-femac",}, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, hisi_femac_match); ++ ++static struct platform_driver hisi_femac_driver = { ++ .driver = { ++ .name = "hisi-femac", ++ .of_match_table = hisi_femac_match, ++ }, ++ .probe = hisi_femac_drv_probe, ++ .remove = hisi_femac_drv_remove, ++#ifdef CONFIG_PM ++ .suspend = hisi_femac_drv_suspend, ++ .resume = hisi_femac_drv_resume, ++#endif ++}; ++ ++module_platform_driver(hisi_femac_driver); ++ ++MODULE_DESCRIPTION("Hisilicon Fast Ethernet MAC driver"); ++MODULE_AUTHOR("Dongpo Li "); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:hisi-femac"); +diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig +index 75472cf7..faa78eb 100644 +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -212,6 +212,20 @@ config MDIO_BCM_UNIMAC + controllers as well as some Broadcom Ethernet switches such as the + Starfighter 2 switches. + ++config MDIO_HISI_FEMAC ++ tristate "Hisilicon FEMAC MDIO bus controller" ++ depends on HAS_IOMEM && OF_MDIO ++ help ++ This module provides a driver for the MDIO busses found in the ++ Hisilicon SoC that have an Fast Ethernet MAC. ++ ++config MDIO_HISI_GEMAC ++ tristate "Hisilicon GEMAC MDIO bus controller" ++ depends on HAS_IOMEM && OF_MDIO ++ help ++ This module provides a driver for the MDIO busses found in the ++ Hisilicon SoC that have an Gigabit Ethernet MAC. ++ + endif # PHYLIB + + config MICREL_KS8995MA +diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile +index eb3b18b..d1cc7c5 100644 +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -35,3 +35,5 @@ obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o + obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o + obj-$(CONFIG_AMD_XGBE_PHY) += amd-xgbe-phy.o + obj-$(CONFIG_MDIO_BCM_UNIMAC) += mdio-bcm-unimac.o ++obj-$(CONFIG_MDIO_HISI_FEMAC) += mdio-hisi-femac.o ++obj-$(CONFIG_MDIO_HISI_GEMAC) += mdio-hisi-gemac.o +diff --git a/drivers/net/phy/mdio-hisi-femac.c b/drivers/net/phy/mdio-hisi-femac.c +new file mode 100644 +index 0000000..186badd +--- /dev/null ++++ b/drivers/net/phy/mdio-hisi-femac.c +@@ -0,0 +1,166 @@ ++/* ++ * Hisilicon Fast Ethernet MDIO Bus Driver ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MDIO_RWCTRL 0x00 ++#define MDIO_RO_DATA 0x04 ++#define MDIO_WRITE BIT(13) ++#define MDIO_RW_FINISH BIT(15) ++#define BIT_PHY_ADDR_OFFSET 8 ++#define BIT_WR_DATA_OFFSET 16 ++ ++struct hisi_femac_mdio_data { ++ struct clk *clk; ++ void __iomem *membase; ++}; ++ ++static int hisi_femac_mdio_wait_ready(struct hisi_femac_mdio_data *data) ++{ ++ u32 val; ++ ++ return readl_poll_timeout(data->membase + MDIO_RWCTRL, ++ val, val & MDIO_RW_FINISH, 20, 10000); ++} ++ ++static int hisi_femac_mdio_read(struct mii_bus *bus, int mii_id, int regnum) ++{ ++ struct hisi_femac_mdio_data *data = bus->priv; ++ int ret; ++ ++ ret = hisi_femac_mdio_wait_ready(data); ++ if (ret) ++ return ret; ++ ++ writel((mii_id << BIT_PHY_ADDR_OFFSET) | ((u32)regnum), ++ data->membase + MDIO_RWCTRL); ++ ++ ret = hisi_femac_mdio_wait_ready(data); ++ if (ret) ++ return ret; ++ ++ return readl(data->membase + MDIO_RO_DATA) & 0xFFFF; ++} ++ ++static int hisi_femac_mdio_write(struct mii_bus *bus, int mii_id, int regnum, ++ u16 value) ++{ ++ struct hisi_femac_mdio_data *data = bus->priv; ++ int ret; ++ ++ ret = hisi_femac_mdio_wait_ready(data); ++ if (ret) ++ return ret; ++ ++ writel(MDIO_WRITE | (value << BIT_WR_DATA_OFFSET) | ++ (mii_id << BIT_PHY_ADDR_OFFSET) | ((u32)regnum), ++ data->membase + MDIO_RWCTRL); ++ ++ return hisi_femac_mdio_wait_ready(data); ++} ++ ++static int hisi_femac_mdio_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct mii_bus *bus; ++ struct hisi_femac_mdio_data *data; ++ struct resource *res; ++ int ret; ++ ++ bus = mdiobus_alloc_size(sizeof(*data)); ++ if (!bus) ++ return -ENOMEM; ++ ++ bus->name = "hisi_femac_mii_bus"; ++ bus->read = &hisi_femac_mdio_read; ++ bus->write = &hisi_femac_mdio_write; ++ snprintf(bus->id, MII_BUS_ID_SIZE, "%s", pdev->name); ++ bus->parent = &pdev->dev; ++ ++ data = bus->priv; ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ data->membase = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(data->membase)) { ++ ret = PTR_ERR(data->membase); ++ goto err_out_free_mdiobus; ++ } ++ ++ data->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(data->clk)) { ++ ret = PTR_ERR(data->clk); ++ goto err_out_free_mdiobus; ++ } ++ ++ ret = clk_prepare_enable(data->clk); ++ if (ret) ++ goto err_out_free_mdiobus; ++ ++ ret = of_mdiobus_register(bus, np); ++ if (ret) ++ goto err_out_disable_clk; ++ ++ platform_set_drvdata(pdev, bus); ++ ++ return 0; ++ ++err_out_disable_clk: ++ clk_disable_unprepare(data->clk); ++err_out_free_mdiobus: ++ mdiobus_free(bus); ++ return ret; ++} ++ ++static int hisi_femac_mdio_remove(struct platform_device *pdev) ++{ ++ struct mii_bus *bus = platform_get_drvdata(pdev); ++ struct hisi_femac_mdio_data *data = bus->priv; ++ ++ mdiobus_unregister(bus); ++ clk_disable_unprepare(data->clk); ++ mdiobus_free(bus); ++ ++ return 0; ++} ++ ++static const struct of_device_id hisi_femac_mdio_dt_ids[] = { ++ { .compatible = "hisilicon,hisi-femac-mdio" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, hisi_femac_mdio_dt_ids); ++ ++static struct platform_driver hisi_femac_mdio_driver = { ++ .probe = hisi_femac_mdio_probe, ++ .remove = hisi_femac_mdio_remove, ++ .driver = { ++ .name = "hisi-femac-mdio", ++ .of_match_table = hisi_femac_mdio_dt_ids, ++ }, ++}; ++ ++module_platform_driver(hisi_femac_mdio_driver); ++ ++MODULE_DESCRIPTION("Hisilicon Fast Ethernet MAC MDIO interface driver"); ++MODULE_AUTHOR("Dongpo Li "); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/net/phy/mdio-hisi-gemac.c b/drivers/net/phy/mdio-hisi-gemac.c +new file mode 100644 +index 0000000..efe0897 +--- /dev/null ++++ b/drivers/net/phy/mdio-hisi-gemac.c +@@ -0,0 +1,221 @@ ++/* ++ * Hisilicon Gigabit Ethernet MDIO Bus Driver ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(CONFIG_ARCH_HI3519) || defined(CONFIG_ARCH_HI3519V101) || defined(CONFIG_ARCH_HI3516AV200) ++#ifdef readl ++#undef readl ++#undef writel ++#define readl hi_readl ++#define writel hi_writel ++#endif ++#endif ++ ++#define MDIO_SINGLE_CMD 0x00 ++#define MDIO_SINGLE_DATA 0x04 ++#define MDIO_RDATA_STATUS 0x10 ++#define BIT_PHY_ADDR_OFFSET 8 ++#define MDIO_WRITE BIT(16) ++#define MDIO_READ BIT(17) ++#define MDIO_START BIT(20) ++#define MDIO_START_READ (MDIO_START | MDIO_READ) ++#define MDIO_START_WRITE (MDIO_START | MDIO_WRITE) ++ ++struct hisi_gemac_mdio_data { ++ struct clk *clk; ++ struct reset_control *phy_rst; ++ void __iomem *membase; ++}; ++ ++static int hisi_gemac_mdio_wait_ready(struct hisi_gemac_mdio_data *data) ++{ ++ u32 val; ++ ++ return readl_poll_timeout(data->membase + MDIO_SINGLE_CMD, ++ val, !(val & MDIO_START), 20, 10000); ++} ++ ++static int hisi_gemac_mdio_read(struct mii_bus *bus, int mii_id, int regnum) ++{ ++ struct hisi_gemac_mdio_data *data = bus->priv; ++ int ret; ++ ++ ret = hisi_gemac_mdio_wait_ready(data); ++ if (ret) ++ return ret; ++ ++ writel(MDIO_START_READ | ((u32)mii_id << BIT_PHY_ADDR_OFFSET) | ++ ((u32)regnum), ++ data->membase + MDIO_SINGLE_CMD); ++ ++ ret = hisi_gemac_mdio_wait_ready(data); ++ if (ret) ++ return ret; ++ ++ /* if read data is invalid, we just return 0 instead of -EAGAIN. ++ * This can make MDIO more robust when reading PHY status. ++ */ ++ if (readl(data->membase + MDIO_RDATA_STATUS)) ++ return 0; ++ ++ return readl(data->membase + MDIO_SINGLE_DATA) >> 16; ++} ++ ++static int hisi_gemac_mdio_write(struct mii_bus *bus, int mii_id, int regnum, ++ u16 value) ++{ ++ struct hisi_gemac_mdio_data *data = bus->priv; ++ int ret; ++ ++ ret = hisi_gemac_mdio_wait_ready(data); ++ if (ret) ++ return ret; ++ ++ writel(value, data->membase + MDIO_SINGLE_DATA); ++ writel(MDIO_START_WRITE | ((u32)mii_id << BIT_PHY_ADDR_OFFSET) | ++ ((u32)regnum), ++ data->membase + MDIO_SINGLE_CMD); ++ ++ return hisi_gemac_mdio_wait_ready(data); ++} ++ ++static void hisi_gemac_external_phy_reset(struct hisi_gemac_mdio_data *data) ++{ ++ if (data->phy_rst) { ++ /* write 0 to cancel reset */ ++ reset_control_deassert(data->phy_rst); ++ msleep(50); ++ ++ /* HIFONE or 98cv200 use CRG register to reset phy */ ++ /* RST_BIT, write 0 to reset phy, write 1 to cancel reset */ ++ reset_control_assert(data->phy_rst); ++ ++ /* delay some time to ensure reset ok, ++ * this depends on PHY hardware feature ++ */ ++ msleep(50); ++ ++ /* write 0 to cancel reset */ ++ reset_control_deassert(data->phy_rst); ++ /* delay some time to ensure later MDIO access */ ++ msleep(50); ++ } ++} ++ ++static int hisi_gemac_mdio_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct mii_bus *bus; ++ struct hisi_gemac_mdio_data *data; ++ struct resource *res; ++ int ret; ++ ++ bus = mdiobus_alloc_size(sizeof(*data)); ++ if (!bus) ++ return -ENOMEM; ++ ++ bus->name = "hisi_gemac_mii_bus"; ++ bus->read = &hisi_gemac_mdio_read; ++ bus->write = &hisi_gemac_mdio_write; ++ snprintf(bus->id, MII_BUS_ID_SIZE, "%s", pdev->name); ++ bus->parent = &pdev->dev; ++ ++ data = bus->priv; ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ ret = -ENXIO; ++ goto err_out_free_mdiobus; ++ } ++ data->membase = devm_ioremap(&pdev->dev, res->start, ++ resource_size(res)); ++ if (!data->membase) { ++ ret = -ENOMEM; ++ goto err_out_free_mdiobus; ++ } ++ ++ data->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(data->clk)) { ++ ret = PTR_ERR(data->clk); ++ goto err_out_free_mdiobus; ++ } ++ ++ ret = clk_prepare_enable(data->clk); ++ if (ret) ++ goto err_out_free_mdiobus; ++ ++ data->phy_rst = devm_reset_control_get(&pdev->dev, "phy_reset"); ++ if (IS_ERR(data->phy_rst)) ++ data->phy_rst = NULL; ++ hisi_gemac_external_phy_reset(data); ++ ++ ret = of_mdiobus_register(bus, np); ++ if (ret) ++ goto err_out_disable_clk; ++ ++ platform_set_drvdata(pdev, bus); ++ ++ return 0; ++ ++err_out_disable_clk: ++ clk_disable_unprepare(data->clk); ++err_out_free_mdiobus: ++ mdiobus_free(bus); ++ return ret; ++} ++ ++static int hisi_gemac_mdio_remove(struct platform_device *pdev) ++{ ++ struct mii_bus *bus = platform_get_drvdata(pdev); ++ struct hisi_gemac_mdio_data *data = bus->priv; ++ ++ mdiobus_unregister(bus); ++ clk_disable_unprepare(data->clk); ++ mdiobus_free(bus); ++ ++ return 0; ++} ++ ++static const struct of_device_id hisi_gemac_mdio_dt_ids[] = { ++ { .compatible = "hisilicon,hisi-gemac-mdio" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, hisi_gemac_mdio_dt_ids); ++ ++static struct platform_driver hisi_gemac_mdio_driver = { ++ .probe = hisi_gemac_mdio_probe, ++ .remove = hisi_gemac_mdio_remove, ++ .driver = { ++ .name = "hisi-gemac-mdio", ++ .of_match_table = hisi_gemac_mdio_dt_ids, ++ }, ++}; ++ ++module_platform_driver(hisi_gemac_mdio_driver); ++ ++MODULE_DESCRIPTION("Hisilicon Gigabit Ethernet MAC MDIO interface driver"); ++MODULE_AUTHOR("Dongpo Li "); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c +index 70a0d88..b599982 100644 +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -109,6 +109,53 @@ int phy_register_fixup_for_id(const char *bus_id, + } + EXPORT_SYMBOL(phy_register_fixup_for_id); + ++/** ++ * phy_unregister_fixup - remove a phy_fixup from the list ++ * @bus_id: A string matches fixup->bus_id (or PHY_ANY_ID) in phy_fixup_list ++ * @phy_uid: A phy id matches fixup->phy_id (or PHY_ANY_UID) in phy_fixup_list ++ * @phy_uid_mask: Applied to phy_uid and fixup->phy_uid before comparison ++ */ ++int phy_unregister_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask) ++{ ++ struct list_head *pos, *n; ++ struct phy_fixup *fixup; ++ int ret; ++ ++ ret = -ENODEV; ++ ++ mutex_lock(&phy_fixup_lock); ++ list_for_each_safe(pos, n, &phy_fixup_list) { ++ fixup = list_entry(pos, struct phy_fixup, list); ++ ++ if ((!strcmp(fixup->bus_id, bus_id)) && ++ ((fixup->phy_uid & phy_uid_mask) == ++ (phy_uid & phy_uid_mask))) { ++ list_del(&fixup->list); ++ kfree(fixup); ++ ret = 0; ++ break; ++ } ++ } ++ mutex_unlock(&phy_fixup_lock); ++ ++ return ret; ++} ++EXPORT_SYMBOL(phy_unregister_fixup); ++ ++/* Unregisters a fixup of any PHY with the UID in phy_uid */ ++int phy_unregister_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask) ++{ ++ return phy_unregister_fixup(PHY_ANY_ID, phy_uid, phy_uid_mask); ++} ++EXPORT_SYMBOL(phy_unregister_fixup_for_uid); ++ ++/* Unregisters a fixup of the PHY with id string bus_id */ ++int phy_unregister_fixup_for_id(const char *bus_id) ++{ ++ return phy_unregister_fixup(bus_id, PHY_ANY_UID, 0xffffffff); ++} ++EXPORT_SYMBOL(phy_unregister_fixup_for_id); ++ + /* Returns 1 if fixup matches phydev in bus_id and phy_uid. + * Fixups can be set to match any in one or more fields. + */ +diff --git a/drivers/net/ppp/Kconfig b/drivers/net/ppp/Kconfig +index 1373c6d..282aec4 100644 +--- a/drivers/net/ppp/Kconfig ++++ b/drivers/net/ppp/Kconfig +@@ -149,6 +149,23 @@ config PPPOL2TP + tunnels. L2TP is replacing PPTP for VPN uses. + if TTY + ++config PPPOLAC ++ tristate "PPP on L2TP Access Concentrator" ++ depends on PPP && INET ++ help ++ L2TP (RFC 2661) is a tunneling protocol widely used in virtual private ++ networks. This driver handles L2TP data packets between a UDP socket ++ and a PPP channel, but only permits one session per socket. Thus it is ++ fairly simple and suited for clients. ++ ++config PPPOPNS ++ tristate "PPP on PPTP Network Server" ++ depends on PPP && INET ++ help ++ PPTP (RFC 2637) is a tunneling protocol widely used in virtual private ++ networks. This driver handles PPTP data packets between a RAW socket ++ and a PPP channel. It is fairly simple and easy to use. ++ + config PPP_ASYNC + tristate "PPP support for async serial ports" + depends on PPP +diff --git a/drivers/net/ppp/Makefile b/drivers/net/ppp/Makefile +index a6b6297..d283d03c 100644 +--- a/drivers/net/ppp/Makefile ++++ b/drivers/net/ppp/Makefile +@@ -11,3 +11,5 @@ obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o + obj-$(CONFIG_PPPOE) += pppox.o pppoe.o + obj-$(CONFIG_PPPOL2TP) += pppox.o + obj-$(CONFIG_PPTP) += pppox.o pptp.o ++obj-$(CONFIG_PPPOLAC) += pppox.o pppolac.o ++obj-$(CONFIG_PPPOPNS) += pppox.o pppopns.o +diff --git a/drivers/net/ppp/pppolac.c b/drivers/net/ppp/pppolac.c +new file mode 100644 +index 0000000..a5d3d63 +--- /dev/null ++++ b/drivers/net/ppp/pppolac.c +@@ -0,0 +1,449 @@ ++/* drivers/net/pppolac.c ++ * ++ * Driver for PPP on L2TP Access Concentrator / PPPoLAC Socket (RFC 2661) ++ * ++ * Copyright (C) 2009 Google, 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. ++ */ ++ ++/* This driver handles L2TP data packets between a UDP socket and a PPP channel. ++ * The socket must keep connected, and only one session per socket is permitted. ++ * Sequencing of outgoing packets is controlled by LNS. Incoming packets with ++ * sequences are reordered within a sliding window of one second. Currently ++ * reordering only happens when a packet is received. It is done for simplicity ++ * since no additional locks or threads are required. This driver only works on ++ * IPv4 due to the lack of UDP encapsulation support in IPv6. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define L2TP_CONTROL_BIT 0x80 ++#define L2TP_LENGTH_BIT 0x40 ++#define L2TP_SEQUENCE_BIT 0x08 ++#define L2TP_OFFSET_BIT 0x02 ++#define L2TP_VERSION 0x02 ++#define L2TP_VERSION_MASK 0x0F ++ ++#define PPP_ADDR 0xFF ++#define PPP_CTRL 0x03 ++ ++union unaligned { ++ __u32 u32; ++} __attribute__((packed)); ++ ++static inline union unaligned *unaligned(void *ptr) ++{ ++ return (union unaligned *)ptr; ++} ++ ++struct meta { ++ __u32 sequence; ++ __u32 timestamp; ++}; ++ ++static inline struct meta *skb_meta(struct sk_buff *skb) ++{ ++ return (struct meta *)skb->cb; ++} ++ ++/******************************************************************************/ ++ ++static int pppolac_recv_core(struct sock *sk_udp, struct sk_buff *skb) ++{ ++ struct sock *sk = (struct sock *)sk_udp->sk_user_data; ++ struct pppolac_opt *opt = &pppox_sk(sk)->proto.lac; ++ struct meta *meta = skb_meta(skb); ++ __u32 now = jiffies; ++ __u8 bits; ++ __u8 *ptr; ++ ++ /* Drop the packet if L2TP header is missing. */ ++ if (skb->len < sizeof(struct udphdr) + 6) ++ goto drop; ++ ++ /* Put it back if it is a control packet. */ ++ if (skb->data[sizeof(struct udphdr)] & L2TP_CONTROL_BIT) ++ return opt->backlog_rcv(sk_udp, skb); ++ ++ /* Skip UDP header. */ ++ skb_pull(skb, sizeof(struct udphdr)); ++ ++ /* Check the version. */ ++ if ((skb->data[1] & L2TP_VERSION_MASK) != L2TP_VERSION) ++ goto drop; ++ bits = skb->data[0]; ++ ptr = &skb->data[2]; ++ ++ /* Check the length if it is present. */ ++ if (bits & L2TP_LENGTH_BIT) { ++ if ((ptr[0] << 8 | ptr[1]) != skb->len) ++ goto drop; ++ ptr += 2; ++ } ++ ++ /* Skip all fields including optional ones. */ ++ if (!skb_pull(skb, 6 + (bits & L2TP_SEQUENCE_BIT ? 4 : 0) + ++ (bits & L2TP_LENGTH_BIT ? 2 : 0) + ++ (bits & L2TP_OFFSET_BIT ? 2 : 0))) ++ goto drop; ++ ++ /* Skip the offset padding if it is present. */ ++ if (bits & L2TP_OFFSET_BIT && ++ !skb_pull(skb, skb->data[-2] << 8 | skb->data[-1])) ++ goto drop; ++ ++ /* Check the tunnel and the session. */ ++ if (unaligned(ptr)->u32 != opt->local) ++ goto drop; ++ ++ /* Check the sequence if it is present. */ ++ if (bits & L2TP_SEQUENCE_BIT) { ++ meta->sequence = ptr[4] << 8 | ptr[5]; ++ if ((__s16)(meta->sequence - opt->recv_sequence) < 0) ++ goto drop; ++ } ++ ++ /* Skip PPP address and control if they are present. */ ++ if (skb->len >= 2 && skb->data[0] == PPP_ADDR && ++ skb->data[1] == PPP_CTRL) ++ skb_pull(skb, 2); ++ ++ /* Fix PPP protocol if it is compressed. */ ++ if (skb->len >= 1 && skb->data[0] & 1) ++ skb_push(skb, 1)[0] = 0; ++ ++ /* Drop the packet if PPP protocol is missing. */ ++ if (skb->len < 2) ++ goto drop; ++ ++ /* Perform reordering if sequencing is enabled. */ ++ atomic_set(&opt->sequencing, bits & L2TP_SEQUENCE_BIT); ++ if (bits & L2TP_SEQUENCE_BIT) { ++ struct sk_buff *skb1; ++ ++ /* Insert the packet into receive queue in order. */ ++ skb_set_owner_r(skb, sk); ++ skb_queue_walk(&sk->sk_receive_queue, skb1) { ++ struct meta *meta1 = skb_meta(skb1); ++ __s16 order = meta->sequence - meta1->sequence; ++ if (order == 0) ++ goto drop; ++ if (order < 0) { ++ meta->timestamp = meta1->timestamp; ++ skb_insert(skb1, skb, &sk->sk_receive_queue); ++ skb = NULL; ++ break; ++ } ++ } ++ if (skb) { ++ meta->timestamp = now; ++ skb_queue_tail(&sk->sk_receive_queue, skb); ++ } ++ ++ /* Remove packets from receive queue as long as ++ * 1. the receive buffer is full, ++ * 2. they are queued longer than one second, or ++ * 3. there are no missing packets before them. */ ++ skb_queue_walk_safe(&sk->sk_receive_queue, skb, skb1) { ++ meta = skb_meta(skb); ++ if (atomic_read(&sk->sk_rmem_alloc) < sk->sk_rcvbuf && ++ now - meta->timestamp < HZ && ++ meta->sequence != opt->recv_sequence) ++ break; ++ skb_unlink(skb, &sk->sk_receive_queue); ++ opt->recv_sequence = (__u16)(meta->sequence + 1); ++ skb_orphan(skb); ++ ppp_input(&pppox_sk(sk)->chan, skb); ++ } ++ return NET_RX_SUCCESS; ++ } ++ ++ /* Flush receive queue if sequencing is disabled. */ ++ skb_queue_purge(&sk->sk_receive_queue); ++ skb_orphan(skb); ++ ppp_input(&pppox_sk(sk)->chan, skb); ++ return NET_RX_SUCCESS; ++drop: ++ kfree_skb(skb); ++ return NET_RX_DROP; ++} ++ ++static int pppolac_recv(struct sock *sk_udp, struct sk_buff *skb) ++{ ++ sock_hold(sk_udp); ++ sk_receive_skb(sk_udp, skb, 0); ++ return 0; ++} ++ ++static struct sk_buff_head delivery_queue; ++ ++static void pppolac_xmit_core(struct work_struct *delivery_work) ++{ ++ mm_segment_t old_fs = get_fs(); ++ struct sk_buff *skb; ++ ++ set_fs(KERNEL_DS); ++ while ((skb = skb_dequeue(&delivery_queue))) { ++ struct sock *sk_udp = skb->sk; ++ struct kvec iov = {.iov_base = skb->data, .iov_len = skb->len}; ++ struct msghdr msg = { ++ .msg_iov = (struct iovec *)&iov, ++ .msg_iovlen = 1, ++ .msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT, ++ }; ++ sk_udp->sk_prot->sendmsg(NULL, sk_udp, &msg, skb->len); ++ kfree_skb(skb); ++ } ++ set_fs(old_fs); ++} ++ ++static DECLARE_WORK(delivery_work, pppolac_xmit_core); ++ ++static int pppolac_xmit(struct ppp_channel *chan, struct sk_buff *skb) ++{ ++ struct sock *sk_udp = (struct sock *)chan->private; ++ struct pppolac_opt *opt = &pppox_sk(sk_udp->sk_user_data)->proto.lac; ++ ++ /* Install PPP address and control. */ ++ skb_push(skb, 2); ++ skb->data[0] = PPP_ADDR; ++ skb->data[1] = PPP_CTRL; ++ ++ /* Install L2TP header. */ ++ if (atomic_read(&opt->sequencing)) { ++ skb_push(skb, 10); ++ skb->data[0] = L2TP_SEQUENCE_BIT; ++ skb->data[6] = opt->xmit_sequence >> 8; ++ skb->data[7] = opt->xmit_sequence; ++ skb->data[8] = 0; ++ skb->data[9] = 0; ++ opt->xmit_sequence++; ++ } else { ++ skb_push(skb, 6); ++ skb->data[0] = 0; ++ } ++ skb->data[1] = L2TP_VERSION; ++ unaligned(&skb->data[2])->u32 = opt->remote; ++ ++ /* Now send the packet via the delivery queue. */ ++ skb_set_owner_w(skb, sk_udp); ++ skb_queue_tail(&delivery_queue, skb); ++ schedule_work(&delivery_work); ++ return 1; ++} ++ ++/******************************************************************************/ ++ ++static struct ppp_channel_ops pppolac_channel_ops = { ++ .start_xmit = pppolac_xmit, ++}; ++ ++static int pppolac_connect(struct socket *sock, struct sockaddr *useraddr, ++ int addrlen, int flags) ++{ ++ struct sock *sk = sock->sk; ++ struct pppox_sock *po = pppox_sk(sk); ++ struct sockaddr_pppolac *addr = (struct sockaddr_pppolac *)useraddr; ++ struct socket *sock_udp = NULL; ++ struct sock *sk_udp; ++ int error; ++ ++ if (addrlen != sizeof(struct sockaddr_pppolac) || ++ !addr->local.tunnel || !addr->local.session || ++ !addr->remote.tunnel || !addr->remote.session) { ++ return -EINVAL; ++ } ++ ++ lock_sock(sk); ++ error = -EALREADY; ++ if (sk->sk_state != PPPOX_NONE) ++ goto out; ++ ++ sock_udp = sockfd_lookup(addr->udp_socket, &error); ++ if (!sock_udp) ++ goto out; ++ sk_udp = sock_udp->sk; ++ lock_sock(sk_udp); ++ ++ /* Remove this check when IPv6 supports UDP encapsulation. */ ++ error = -EAFNOSUPPORT; ++ if (sk_udp->sk_family != AF_INET) ++ goto out; ++ error = -EPROTONOSUPPORT; ++ if (sk_udp->sk_protocol != IPPROTO_UDP) ++ goto out; ++ error = -EDESTADDRREQ; ++ if (sk_udp->sk_state != TCP_ESTABLISHED) ++ goto out; ++ error = -EBUSY; ++ if (udp_sk(sk_udp)->encap_type || sk_udp->sk_user_data) ++ goto out; ++ if (!sk_udp->sk_bound_dev_if) { ++ struct dst_entry *dst = sk_dst_get(sk_udp); ++ error = -ENODEV; ++ if (!dst) ++ goto out; ++ sk_udp->sk_bound_dev_if = dst->dev->ifindex; ++ dst_release(dst); ++ } ++ ++ po->chan.hdrlen = 12; ++ po->chan.private = sk_udp; ++ po->chan.ops = &pppolac_channel_ops; ++ po->chan.mtu = PPP_MRU - 80; ++ po->proto.lac.local = unaligned(&addr->local)->u32; ++ po->proto.lac.remote = unaligned(&addr->remote)->u32; ++ atomic_set(&po->proto.lac.sequencing, 1); ++ po->proto.lac.backlog_rcv = sk_udp->sk_backlog_rcv; ++ ++ error = ppp_register_channel(&po->chan); ++ if (error) ++ goto out; ++ ++ sk->sk_state = PPPOX_CONNECTED; ++ udp_sk(sk_udp)->encap_type = UDP_ENCAP_L2TPINUDP; ++ udp_sk(sk_udp)->encap_rcv = pppolac_recv; ++ sk_udp->sk_backlog_rcv = pppolac_recv_core; ++ sk_udp->sk_user_data = sk; ++out: ++ if (sock_udp) { ++ release_sock(sk_udp); ++ if (error) ++ sockfd_put(sock_udp); ++ } ++ release_sock(sk); ++ return error; ++} ++ ++static int pppolac_release(struct socket *sock) ++{ ++ struct sock *sk = sock->sk; ++ ++ if (!sk) ++ return 0; ++ ++ lock_sock(sk); ++ if (sock_flag(sk, SOCK_DEAD)) { ++ release_sock(sk); ++ return -EBADF; ++ } ++ ++ if (sk->sk_state != PPPOX_NONE) { ++ struct sock *sk_udp = (struct sock *)pppox_sk(sk)->chan.private; ++ lock_sock(sk_udp); ++ skb_queue_purge(&sk->sk_receive_queue); ++ pppox_unbind_sock(sk); ++ udp_sk(sk_udp)->encap_type = 0; ++ udp_sk(sk_udp)->encap_rcv = NULL; ++ sk_udp->sk_backlog_rcv = pppox_sk(sk)->proto.lac.backlog_rcv; ++ sk_udp->sk_user_data = NULL; ++ release_sock(sk_udp); ++ sockfd_put(sk_udp->sk_socket); ++ } ++ ++ sock_orphan(sk); ++ sock->sk = NULL; ++ release_sock(sk); ++ sock_put(sk); ++ return 0; ++} ++ ++/******************************************************************************/ ++ ++static struct proto pppolac_proto = { ++ .name = "PPPOLAC", ++ .owner = THIS_MODULE, ++ .obj_size = sizeof(struct pppox_sock), ++}; ++ ++static struct proto_ops pppolac_proto_ops = { ++ .family = PF_PPPOX, ++ .owner = THIS_MODULE, ++ .release = pppolac_release, ++ .bind = sock_no_bind, ++ .connect = pppolac_connect, ++ .socketpair = sock_no_socketpair, ++ .accept = sock_no_accept, ++ .getname = sock_no_getname, ++ .poll = sock_no_poll, ++ .ioctl = pppox_ioctl, ++ .listen = sock_no_listen, ++ .shutdown = sock_no_shutdown, ++ .setsockopt = sock_no_setsockopt, ++ .getsockopt = sock_no_getsockopt, ++ .sendmsg = sock_no_sendmsg, ++ .recvmsg = sock_no_recvmsg, ++ .mmap = sock_no_mmap, ++}; ++ ++static int pppolac_create(struct net *net, struct socket *sock) ++{ ++ struct sock *sk; ++ ++ sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppolac_proto); ++ if (!sk) ++ return -ENOMEM; ++ ++ sock_init_data(sock, sk); ++ sock->state = SS_UNCONNECTED; ++ sock->ops = &pppolac_proto_ops; ++ sk->sk_protocol = PX_PROTO_OLAC; ++ sk->sk_state = PPPOX_NONE; ++ return 0; ++} ++ ++/******************************************************************************/ ++ ++static struct pppox_proto pppolac_pppox_proto = { ++ .create = pppolac_create, ++ .owner = THIS_MODULE, ++}; ++ ++static int __init pppolac_init(void) ++{ ++ int error; ++ ++ error = proto_register(&pppolac_proto, 0); ++ if (error) ++ return error; ++ ++ error = register_pppox_proto(PX_PROTO_OLAC, &pppolac_pppox_proto); ++ if (error) ++ proto_unregister(&pppolac_proto); ++ else ++ skb_queue_head_init(&delivery_queue); ++ return error; ++} ++ ++static void __exit pppolac_exit(void) ++{ ++ unregister_pppox_proto(PX_PROTO_OLAC); ++ proto_unregister(&pppolac_proto); ++} ++ ++module_init(pppolac_init); ++module_exit(pppolac_exit); ++ ++MODULE_DESCRIPTION("PPP on L2TP Access Concentrator (PPPoLAC)"); ++MODULE_AUTHOR("Chia-chi Yeh "); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/net/ppp/pppopns.c b/drivers/net/ppp/pppopns.c +new file mode 100644 +index 0000000..dc15f97 +--- /dev/null ++++ b/drivers/net/ppp/pppopns.c +@@ -0,0 +1,428 @@ ++/* drivers/net/pppopns.c ++ * ++ * Driver for PPP on PPTP Network Server / PPPoPNS Socket (RFC 2637) ++ * ++ * Copyright (C) 2009 Google, 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. ++ */ ++ ++/* This driver handles PPTP data packets between a RAW socket and a PPP channel. ++ * The socket is created in the kernel space and connected to the same address ++ * of the control socket. Outgoing packets are always sent with sequences but ++ * without acknowledgements. Incoming packets with sequences are reordered ++ * within a sliding window of one second. Currently reordering only happens when ++ * a packet is received. It is done for simplicity since no additional locks or ++ * threads are required. This driver should work on both IPv4 and IPv6. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define GRE_HEADER_SIZE 8 ++ ++#define PPTP_GRE_BITS htons(0x2001) ++#define PPTP_GRE_BITS_MASK htons(0xEF7F) ++#define PPTP_GRE_SEQ_BIT htons(0x1000) ++#define PPTP_GRE_ACK_BIT htons(0x0080) ++#define PPTP_GRE_TYPE htons(0x880B) ++ ++#define PPP_ADDR 0xFF ++#define PPP_CTRL 0x03 ++ ++struct header { ++ __u16 bits; ++ __u16 type; ++ __u16 length; ++ __u16 call; ++ __u32 sequence; ++} __attribute__((packed)); ++ ++struct meta { ++ __u32 sequence; ++ __u32 timestamp; ++}; ++ ++static inline struct meta *skb_meta(struct sk_buff *skb) ++{ ++ return (struct meta *)skb->cb; ++} ++ ++/******************************************************************************/ ++ ++static int pppopns_recv_core(struct sock *sk_raw, struct sk_buff *skb) ++{ ++ struct sock *sk = (struct sock *)sk_raw->sk_user_data; ++ struct pppopns_opt *opt = &pppox_sk(sk)->proto.pns; ++ struct meta *meta = skb_meta(skb); ++ __u32 now = jiffies; ++ struct header *hdr; ++ ++ /* Skip transport header */ ++ skb_pull(skb, skb_transport_header(skb) - skb->data); ++ ++ /* Drop the packet if GRE header is missing. */ ++ if (skb->len < GRE_HEADER_SIZE) ++ goto drop; ++ hdr = (struct header *)skb->data; ++ ++ /* Check the header. */ ++ if (hdr->type != PPTP_GRE_TYPE || hdr->call != opt->local || ++ (hdr->bits & PPTP_GRE_BITS_MASK) != PPTP_GRE_BITS) ++ goto drop; ++ ++ /* Skip all fields including optional ones. */ ++ if (!skb_pull(skb, GRE_HEADER_SIZE + ++ (hdr->bits & PPTP_GRE_SEQ_BIT ? 4 : 0) + ++ (hdr->bits & PPTP_GRE_ACK_BIT ? 4 : 0))) ++ goto drop; ++ ++ /* Check the length. */ ++ if (skb->len != ntohs(hdr->length)) ++ goto drop; ++ ++ /* Check the sequence if it is present. */ ++ if (hdr->bits & PPTP_GRE_SEQ_BIT) { ++ meta->sequence = ntohl(hdr->sequence); ++ if ((__s32)(meta->sequence - opt->recv_sequence) < 0) ++ goto drop; ++ } ++ ++ /* Skip PPP address and control if they are present. */ ++ if (skb->len >= 2 && skb->data[0] == PPP_ADDR && ++ skb->data[1] == PPP_CTRL) ++ skb_pull(skb, 2); ++ ++ /* Fix PPP protocol if it is compressed. */ ++ if (skb->len >= 1 && skb->data[0] & 1) ++ skb_push(skb, 1)[0] = 0; ++ ++ /* Drop the packet if PPP protocol is missing. */ ++ if (skb->len < 2) ++ goto drop; ++ ++ /* Perform reordering if sequencing is enabled. */ ++ if (hdr->bits & PPTP_GRE_SEQ_BIT) { ++ struct sk_buff *skb1; ++ ++ /* Insert the packet into receive queue in order. */ ++ skb_set_owner_r(skb, sk); ++ skb_queue_walk(&sk->sk_receive_queue, skb1) { ++ struct meta *meta1 = skb_meta(skb1); ++ __s32 order = meta->sequence - meta1->sequence; ++ if (order == 0) ++ goto drop; ++ if (order < 0) { ++ meta->timestamp = meta1->timestamp; ++ skb_insert(skb1, skb, &sk->sk_receive_queue); ++ skb = NULL; ++ break; ++ } ++ } ++ if (skb) { ++ meta->timestamp = now; ++ skb_queue_tail(&sk->sk_receive_queue, skb); ++ } ++ ++ /* Remove packets from receive queue as long as ++ * 1. the receive buffer is full, ++ * 2. they are queued longer than one second, or ++ * 3. there are no missing packets before them. */ ++ skb_queue_walk_safe(&sk->sk_receive_queue, skb, skb1) { ++ meta = skb_meta(skb); ++ if (atomic_read(&sk->sk_rmem_alloc) < sk->sk_rcvbuf && ++ now - meta->timestamp < HZ && ++ meta->sequence != opt->recv_sequence) ++ break; ++ skb_unlink(skb, &sk->sk_receive_queue); ++ opt->recv_sequence = meta->sequence + 1; ++ skb_orphan(skb); ++ ppp_input(&pppox_sk(sk)->chan, skb); ++ } ++ return NET_RX_SUCCESS; ++ } ++ ++ /* Flush receive queue if sequencing is disabled. */ ++ skb_queue_purge(&sk->sk_receive_queue); ++ skb_orphan(skb); ++ ppp_input(&pppox_sk(sk)->chan, skb); ++ return NET_RX_SUCCESS; ++drop: ++ kfree_skb(skb); ++ return NET_RX_DROP; ++} ++ ++static void pppopns_recv(struct sock *sk_raw) ++{ ++ struct sk_buff *skb; ++ while ((skb = skb_dequeue(&sk_raw->sk_receive_queue))) { ++ sock_hold(sk_raw); ++ sk_receive_skb(sk_raw, skb, 0); ++ } ++} ++ ++static struct sk_buff_head delivery_queue; ++ ++static void pppopns_xmit_core(struct work_struct *delivery_work) ++{ ++ mm_segment_t old_fs = get_fs(); ++ struct sk_buff *skb; ++ ++ set_fs(KERNEL_DS); ++ while ((skb = skb_dequeue(&delivery_queue))) { ++ struct sock *sk_raw = skb->sk; ++ struct kvec iov = {.iov_base = skb->data, .iov_len = skb->len}; ++ struct msghdr msg = { ++ .msg_iov = (struct iovec *)&iov, ++ .msg_iovlen = 1, ++ .msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT, ++ }; ++ sk_raw->sk_prot->sendmsg(NULL, sk_raw, &msg, skb->len); ++ kfree_skb(skb); ++ } ++ set_fs(old_fs); ++} ++ ++static DECLARE_WORK(delivery_work, pppopns_xmit_core); ++ ++static int pppopns_xmit(struct ppp_channel *chan, struct sk_buff *skb) ++{ ++ struct sock *sk_raw = (struct sock *)chan->private; ++ struct pppopns_opt *opt = &pppox_sk(sk_raw->sk_user_data)->proto.pns; ++ struct header *hdr; ++ __u16 length; ++ ++ /* Install PPP address and control. */ ++ skb_push(skb, 2); ++ skb->data[0] = PPP_ADDR; ++ skb->data[1] = PPP_CTRL; ++ length = skb->len; ++ ++ /* Install PPTP GRE header. */ ++ hdr = (struct header *)skb_push(skb, 12); ++ hdr->bits = PPTP_GRE_BITS | PPTP_GRE_SEQ_BIT; ++ hdr->type = PPTP_GRE_TYPE; ++ hdr->length = htons(length); ++ hdr->call = opt->remote; ++ hdr->sequence = htonl(opt->xmit_sequence); ++ opt->xmit_sequence++; ++ ++ /* Now send the packet via the delivery queue. */ ++ skb_set_owner_w(skb, sk_raw); ++ skb_queue_tail(&delivery_queue, skb); ++ schedule_work(&delivery_work); ++ return 1; ++} ++ ++/******************************************************************************/ ++ ++static struct ppp_channel_ops pppopns_channel_ops = { ++ .start_xmit = pppopns_xmit, ++}; ++ ++static int pppopns_connect(struct socket *sock, struct sockaddr *useraddr, ++ int addrlen, int flags) ++{ ++ struct sock *sk = sock->sk; ++ struct pppox_sock *po = pppox_sk(sk); ++ struct sockaddr_pppopns *addr = (struct sockaddr_pppopns *)useraddr; ++ struct sockaddr_storage ss; ++ struct socket *sock_tcp = NULL; ++ struct socket *sock_raw = NULL; ++ struct sock *sk_tcp; ++ struct sock *sk_raw; ++ int error; ++ ++ if (addrlen != sizeof(struct sockaddr_pppopns)) ++ return -EINVAL; ++ ++ lock_sock(sk); ++ error = -EALREADY; ++ if (sk->sk_state != PPPOX_NONE) ++ goto out; ++ ++ sock_tcp = sockfd_lookup(addr->tcp_socket, &error); ++ if (!sock_tcp) ++ goto out; ++ sk_tcp = sock_tcp->sk; ++ error = -EPROTONOSUPPORT; ++ if (sk_tcp->sk_protocol != IPPROTO_TCP) ++ goto out; ++ addrlen = sizeof(struct sockaddr_storage); ++ error = kernel_getpeername(sock_tcp, (struct sockaddr *)&ss, &addrlen); ++ if (error) ++ goto out; ++ if (!sk_tcp->sk_bound_dev_if) { ++ struct dst_entry *dst = sk_dst_get(sk_tcp); ++ error = -ENODEV; ++ if (!dst) ++ goto out; ++ sk_tcp->sk_bound_dev_if = dst->dev->ifindex; ++ dst_release(dst); ++ } ++ ++ error = sock_create(ss.ss_family, SOCK_RAW, IPPROTO_GRE, &sock_raw); ++ if (error) ++ goto out; ++ sk_raw = sock_raw->sk; ++ sk_raw->sk_bound_dev_if = sk_tcp->sk_bound_dev_if; ++ error = kernel_connect(sock_raw, (struct sockaddr *)&ss, addrlen, 0); ++ if (error) ++ goto out; ++ ++ po->chan.hdrlen = 14; ++ po->chan.private = sk_raw; ++ po->chan.ops = &pppopns_channel_ops; ++ po->chan.mtu = PPP_MRU - 80; ++ po->proto.pns.local = addr->local; ++ po->proto.pns.remote = addr->remote; ++ po->proto.pns.data_ready = sk_raw->sk_data_ready; ++ po->proto.pns.backlog_rcv = sk_raw->sk_backlog_rcv; ++ ++ error = ppp_register_channel(&po->chan); ++ if (error) ++ goto out; ++ ++ sk->sk_state = PPPOX_CONNECTED; ++ lock_sock(sk_raw); ++ sk_raw->sk_data_ready = pppopns_recv; ++ sk_raw->sk_backlog_rcv = pppopns_recv_core; ++ sk_raw->sk_user_data = sk; ++ release_sock(sk_raw); ++out: ++ if (sock_tcp) ++ sockfd_put(sock_tcp); ++ if (error && sock_raw) ++ sock_release(sock_raw); ++ release_sock(sk); ++ return error; ++} ++ ++static int pppopns_release(struct socket *sock) ++{ ++ struct sock *sk = sock->sk; ++ ++ if (!sk) ++ return 0; ++ ++ lock_sock(sk); ++ if (sock_flag(sk, SOCK_DEAD)) { ++ release_sock(sk); ++ return -EBADF; ++ } ++ ++ if (sk->sk_state != PPPOX_NONE) { ++ struct sock *sk_raw = (struct sock *)pppox_sk(sk)->chan.private; ++ lock_sock(sk_raw); ++ skb_queue_purge(&sk->sk_receive_queue); ++ pppox_unbind_sock(sk); ++ sk_raw->sk_data_ready = pppox_sk(sk)->proto.pns.data_ready; ++ sk_raw->sk_backlog_rcv = pppox_sk(sk)->proto.pns.backlog_rcv; ++ sk_raw->sk_user_data = NULL; ++ release_sock(sk_raw); ++ sock_release(sk_raw->sk_socket); ++ } ++ ++ sock_orphan(sk); ++ sock->sk = NULL; ++ release_sock(sk); ++ sock_put(sk); ++ return 0; ++} ++ ++/******************************************************************************/ ++ ++static struct proto pppopns_proto = { ++ .name = "PPPOPNS", ++ .owner = THIS_MODULE, ++ .obj_size = sizeof(struct pppox_sock), ++}; ++ ++static struct proto_ops pppopns_proto_ops = { ++ .family = PF_PPPOX, ++ .owner = THIS_MODULE, ++ .release = pppopns_release, ++ .bind = sock_no_bind, ++ .connect = pppopns_connect, ++ .socketpair = sock_no_socketpair, ++ .accept = sock_no_accept, ++ .getname = sock_no_getname, ++ .poll = sock_no_poll, ++ .ioctl = pppox_ioctl, ++ .listen = sock_no_listen, ++ .shutdown = sock_no_shutdown, ++ .setsockopt = sock_no_setsockopt, ++ .getsockopt = sock_no_getsockopt, ++ .sendmsg = sock_no_sendmsg, ++ .recvmsg = sock_no_recvmsg, ++ .mmap = sock_no_mmap, ++}; ++ ++static int pppopns_create(struct net *net, struct socket *sock) ++{ ++ struct sock *sk; ++ ++ sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppopns_proto); ++ if (!sk) ++ return -ENOMEM; ++ ++ sock_init_data(sock, sk); ++ sock->state = SS_UNCONNECTED; ++ sock->ops = &pppopns_proto_ops; ++ sk->sk_protocol = PX_PROTO_OPNS; ++ sk->sk_state = PPPOX_NONE; ++ return 0; ++} ++ ++/******************************************************************************/ ++ ++static struct pppox_proto pppopns_pppox_proto = { ++ .create = pppopns_create, ++ .owner = THIS_MODULE, ++}; ++ ++static int __init pppopns_init(void) ++{ ++ int error; ++ ++ error = proto_register(&pppopns_proto, 0); ++ if (error) ++ return error; ++ ++ error = register_pppox_proto(PX_PROTO_OPNS, &pppopns_pppox_proto); ++ if (error) ++ proto_unregister(&pppopns_proto); ++ else ++ skb_queue_head_init(&delivery_queue); ++ return error; ++} ++ ++static void __exit pppopns_exit(void) ++{ ++ unregister_pppox_proto(PX_PROTO_OPNS); ++ proto_unregister(&pppopns_proto); ++} ++ ++module_init(pppopns_init); ++module_exit(pppopns_exit); ++ ++MODULE_DESCRIPTION("PPP on PPTP Network Server (PPPoPNS)"); ++MODULE_AUTHOR("Chia-chi Yeh "); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/net/tun.c b/drivers/net/tun.c +index 9dd3746..cae87f0 100644 +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -1881,6 +1881,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, + unsigned int ifindex; + int ret; + ++#ifdef CONFIG_ANDROID_PARANOID_NETWORK ++ if (cmd != TUNGETIFF && !capable(CAP_NET_ADMIN)) { ++ return -EPERM; ++ } ++#endif ++ + if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == 0x89) { + if (copy_from_user(&ifr, argp, ifreq_len)) + return -EFAULT; +diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig +index 16604bd..710733f 100644 +--- a/drivers/net/wireless/Kconfig ++++ b/drivers/net/wireless/Kconfig +@@ -265,6 +265,11 @@ config MWL8K + To compile this driver as a module, choose M here: the module + will be called mwl8k. If unsure, say N. + ++config WIFI_CONTROL_FUNC ++ bool "Enable WiFi control function abstraction" ++ help ++ Enables Power/Reset/Carddetect function abstraction ++ + source "drivers/net/wireless/ath/Kconfig" + source "drivers/net/wireless/b43/Kconfig" + source "drivers/net/wireless/b43legacy/Kconfig" +diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c +index d134710..821f6b5 100644 +--- a/drivers/of/fdt.c ++++ b/drivers/of/fdt.c +@@ -885,36 +885,66 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname, + return 0; + } + ++/* ++ * Convert configs to something easy to use in C code ++ */ ++#if defined(CONFIG_CMDLINE_FORCE) ++static const int overwrite_incoming_cmdline = 1; ++static const int read_dt_cmdline; ++static const int concat_cmdline; ++#elif defined(CONFIG_CMDLINE_EXTEND) ++static const int overwrite_incoming_cmdline; ++static const int read_dt_cmdline = 1; ++static const int concat_cmdline = 1; ++#else /* CMDLINE_FROM_BOOTLOADER */ ++static const int overwrite_incoming_cmdline; ++static const int read_dt_cmdline = 1; ++static const int concat_cmdline; ++#endif ++ ++#ifdef CONFIG_CMDLINE ++static const char *config_cmdline = CONFIG_CMDLINE; ++#else ++static const char *config_cmdline = ""; ++#endif ++ + int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, + int depth, void *data) + { +- int l; +- const char *p; ++ int l = 0; ++ const char *p = NULL; ++ char *cmdline = data; + + pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); + +- if (depth != 1 || !data || ++ if (depth != 1 || !cmdline || + (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) + return 0; + + early_init_dt_check_for_initrd(node); + +- /* Retrieve command line */ +- p = of_get_flat_dt_prop(node, "bootargs", &l); +- if (p != NULL && l > 0) +- strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); +- +- /* +- * CONFIG_CMDLINE is meant to be a default in case nothing else +- * managed to set the command line, unless CONFIG_CMDLINE_FORCE +- * is set in which case we override whatever was found earlier. +- */ +-#ifdef CONFIG_CMDLINE +-#ifndef CONFIG_CMDLINE_FORCE +- if (!((char *)data)[0]) +-#endif +- strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); +-#endif /* CONFIG_CMDLINE */ ++ /* Put CONFIG_CMDLINE in if forced or if data had nothing in it to start */ ++ if (overwrite_incoming_cmdline || !cmdline[0]) ++ strlcpy(cmdline, config_cmdline, COMMAND_LINE_SIZE); ++ ++ /* Retrieve command line unless forcing */ ++ if (read_dt_cmdline) ++ p = of_get_flat_dt_prop(node, "bootargs", &l); ++ ++ if (p != NULL && l > 0) { ++ if (concat_cmdline) { ++ int cmdline_len; ++ int copy_len; ++ strlcat(cmdline, " ", COMMAND_LINE_SIZE); ++ cmdline_len = strlen(cmdline); ++ copy_len = COMMAND_LINE_SIZE - cmdline_len - 1; ++ copy_len = min((int)l, copy_len); ++ strncpy(cmdline + cmdline_len, p, copy_len); ++ cmdline[cmdline_len + copy_len] = '\0'; ++ } else { ++ strlcpy(cmdline, p, min((int)l, COMMAND_LINE_SIZE)); ++ } ++ } + + pr_debug("Command line is: %s\n", (char*)data); + +diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c +index 1bd4305..a925f29 100644 +--- a/drivers/of/of_mdio.c ++++ b/drivers/of/of_mdio.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + + MODULE_AUTHOR("Grant Likely "); +@@ -231,6 +232,41 @@ struct phy_device *of_phy_connect(struct net_device *dev, + EXPORT_SYMBOL(of_phy_connect); + + /** ++ * of_phy_get_and_connect ++ * - Get phy node and connect to the phy described in the device tree ++ * @dev: pointer to net_device claiming the phy ++ * @np: Pointer to device tree node for the net_device claiming the phy ++ * @hndlr: Link state callback for the network device ++ * ++ * If successful, returns a pointer to the phy_device with the embedded ++ * struct device refcount incremented by one, or NULL on failure. The ++ * refcount must be dropped by calling phy_disconnect() or phy_detach(). ++ */ ++struct phy_device *of_phy_get_and_connect(struct net_device *dev, ++ struct device_node *np, ++ void (*hndlr)(struct net_device *)) ++{ ++ phy_interface_t iface; ++ struct device_node *phy_np; ++ struct phy_device *phy; ++ ++ iface = of_get_phy_mode(np); ++ if (iface < 0) ++ return NULL; ++ ++ phy_np = of_parse_phandle(np, "phy-handle", 0); ++ if (!phy_np) ++ return NULL; ++ ++ phy = of_phy_connect(dev, phy_np, hndlr, 0, iface); ++ ++ of_node_put(phy_np); ++ ++ return phy; ++} ++EXPORT_SYMBOL(of_phy_get_and_connect); ++ ++/** + * of_phy_attach - Attach to a PHY without starting the state machine + * @dev: pointer to net_device claiming the phy + * @phy_np: Node pointer for the PHY +diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile +index e04fe2d..0db2477 100644 +--- a/drivers/pci/Makefile ++++ b/drivers/pci/Makefile +@@ -9,6 +9,7 @@ obj-$(CONFIG_PROC_FS) += proc.o + obj-$(CONFIG_SYSFS) += slot.o + + obj-$(CONFIG_PCI_QUIRKS) += quirks.o ++obj-$(CONFIG_HIPCIE) += hipcie/ + + # Build PCI Express stuff if needed + obj-$(CONFIG_PCIEPORTBUS) += pcie/ +diff --git a/drivers/pci/hipcie/Kconfig b/drivers/pci/hipcie/Kconfig +new file mode 100644 +index 0000000..4e5cfc6 +--- /dev/null ++++ b/drivers/pci/hipcie/Kconfig +@@ -0,0 +1,119 @@ ++menuconfig HIPCIE ++ bool "Hisilicon PCI Express support" ++ depends on PCI && (ARCH_HI3519 || ARCH_HI3519V101 || ARCH_HI3559 || ARCH_HI3556 || ARCH_HI3516AV200 || ARCH_HI3531D) ++ default y if PCI ++ default n if !PCI ++ help ++ Hisilicon PCI Express support ++ Choose this selection to support PCI Express uses. ++ ++if HIPCIE ++ ++menu "PCI Express configs" ++ ++config PCIE0_SEL ++ int "PCI Express controller 0 sel" ++ range 0 1 ++ default "0" if !PCI ++ default "1" if PCI ++ depends on PCI ++ help ++ PCI Express controller 0 sel. ++ Set 0 to disable controller 0 as RC. ++ set 1 to enable controller 0 to work at RC mode. ++ ++config PCIE0_DEVICES_MEM_SIZE ++ hex "Total memory size of PCI Express EP devices" ++ range 0x0 0x10000000 if ARCH_HI3519 ++ range 0x0 0x10000000 if ARCH_HI3519V101 ++ range 0x0 0x10000000 if ARCH_HI3516AV200 ++ range 0x0 0x10000000 if ARCH_HI3559 ++ range 0x0 0x10000000 if ARCH_HI3556 ++ range 0x0 0x10000000 if ARCH_HI3531D ++ default "0x8000000" if ARCH_HI3519 ++ default "0x8000000" if ARCH_HI3519V101 ++ default "0x8000000" if ARCH_HI3516AV200 ++ default "0x8000000" if ARCH_HI3559 ++ default "0x8000000" if ARCH_HI3556 ++ default "0x8000000" if ARCH_HI3531D ++ depends on PCI ++ help ++ Memory available for all pcie EP devices in pci subsystem. ++ Hisilicon PCI Express controller provides up to 256MBytes address ++ space for its subordinated devices. ++ No IO address space is reserved, since to support PCI legacy devices ++ which required IO address space. ++ You can change this value as you please. ++ ++config PCIE0_DEVICES_CONFIG_SIZE ++ hex "Sum of configuration header size mapped for all PCIe EP devices" ++ range 0x0 0x10000000 if ARCH_HI3519 ++ range 0x0 0x10000000 if ARCH_HI3519V101 ++ range 0x0 0x10000000 if ARCH_HI3516AV200 ++ range 0x0 0x10000000 if ARCH_HI3559 ++ range 0x0 0x10000000 if ARCH_HI3556 ++ range 0x0 0x10000000 if ARCH_HI3531D ++ default 0x800000 if ARCH_HI3519 ++ default 0x800000 if ARCH_HI3519V101 ++ default 0x800000 if ARCH_HI3516AV200 ++ default 0x800000 if ARCH_HI3559 ++ default 0x800000 if ARCH_HI3556 ++ default 0x8000000 if ARCH_HI3531D ++ depends on PCI ++ help ++ As to the PCIe address space configuration, address space for all EPs ++ is up to 256Mbytes. But, normally people do not used that much. Each ++ EP device will use 4Kbytes virtual address space for PCIe configuration header. ++ Normally people will not use that much(256MB). ++ Enlarge this value will require more system virtual address space. ++ The DEFAULT value(8MB) is enough for most applications. ++ ++config LIMIT_MAX_RD_REQ_SIZE ++ bool "limit pcie max read request size" ++ default y ++ depends on PCI && HIPCIE ++ help ++ The default max read request size of pcie device is 512 Byte. When pcie use ++ the card of pcie-to-sata to connect to the sata disk, with the default max read ++ request size value of 512 byte, would cause the low bandwidth of VDP. If you enable ++ the LIMIT_MAX_RD_REQ_SIZE config, the max read request size of pcie device would be ++ set to 128 byte, and the problem of VDP low band width also be avoided. ++ ++config PCIE1_SEL ++ int "PCI Express controller 1 sel" ++ range 0 1 ++ default "0" ++ depends on (PCI && (ARCH_GODNET || ARCH_HI3531D)) ++ help ++ PCI Express controller 1 sel. ++ Set 0 to disable controller 1, ++ set 1 to enable controller 1 to work at RC mode. ++ ++config PCIE1_DEVICES_MEM_SIZE ++ hex "Total memory size of PCI Express EP devices" ++ range 0x0 0x8000000 ++ default "0x7800000" ++ depends on (PCI && ARCH_HI3531D) ++ help ++ All memory size required by all devices in pci subsystem. ++ Hisilicon PCI Express controller provide up to 128M memory ++ and io size for device. ++ Here we set memory size up to 120M, means that io size has at least 8M ++ You can change this depend on you device connected ++ to Hisilicon PCI Express controller. ++ ++config PCIE1_DEVICES_CONFIG_SIZE ++ hex "Total configuration header size of PCI Express system devices" ++ range 0x0 0x10000000 ++ default 0x800000 ++ depends on (PCI && ARCH_HI3531D) ++ help ++ All configuration size required by devices connnect to ++ Hisilicon PCI Express controller. ++ NOTE: This will alloc memory from kernel, ++ enlarge this will require the same memory. ++ The default value is enough for most applications. ++ ++endmenu ++ ++endif +diff --git a/drivers/pci/hipcie/Makefile b/drivers/pci/hipcie/Makefile +new file mode 100644 +index 0000000..0455420 +--- /dev/null ++++ b/drivers/pci/hipcie/Makefile +@@ -0,0 +1,8 @@ ++ ++obj-$(CONFIG_HIPCIE) += hipcie.o ++ ++hipcie-objs := pcie.o ++ ++ifeq ($(CONFIG_PCI_DEBUG),y) ++ EXTRA_CFLAGS += -DPCIE_DEBUG ++endif +diff --git a/drivers/pci/hipcie/pcie.c b/drivers/pci/hipcie/pcie.c +new file mode 100644 +index 0000000..2f1e9d1 +--- /dev/null ++++ b/drivers/pci/hipcie/pcie.c +@@ -0,0 +1,732 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define PCIE_DBG_REG 1 ++#define PCIE_DBG_FUNC 2 ++#define PCIE_DBG_MODULE 3 ++ ++#define PCIE_DEBUG_LEVEL PCIE_DBG_MODULE ++ ++/*#define PCIE_DEBUG*/ ++#ifdef PCIE_DEBUG ++#define pcie_debug(level, str, arg...)\ ++ do {\ ++ if ((level) <= PCIE_DEBUG_LEVEL) {\ ++ pr_debug("%s->%d," str "\n", \ ++ __func__, __LINE__, ##arg);\ ++ } \ ++ } while (0) ++#else ++#define pcie_debug(level, str, arg...) ++#endif ++ ++#define pcie_assert(con)\ ++ do {\ ++ if (!(con)) {\ ++ pr_err("%s->%d,assert fail!\n", \ ++ __func__, __LINE__);\ ++ } \ ++ } while (0) ++ ++#define pcie_error(str, arg...)\ ++ pr_err("%s->%d" str "\n", __func__, __LINE__, ##arg) ++ ++ ++#define __256MB__ 0x10000000 ++#define __128MB__ 0x8000000 ++#define __4KB__ 0x1000 ++#define __8KB__ 0x2000 ++ ++enum pcie_sel { ++ /* ++ * No controller selected. ++ */ ++ pcie_sel_none, ++ /* ++ * PCIE0 selected. ++ */ ++ pcie0_x1_sel, ++ /* ++ * PCIE1 selected. ++ */ ++ pcie1_x1_sel ++}; ++ ++enum pcie_rc_sel { ++ pcie_controller_unselected, ++ pcie_controller_selected ++}; ++ ++enum pcie_controller { ++ pcie_controller_none = -1, ++ pcie_controller_0 = 0, ++ pcie_controller_1 = 1 ++}; ++ ++struct pcie_iatu { ++ unsigned int viewport; /* iATU Viewport Register */ ++ unsigned int region_ctrl_1; /* Region Control 1 Register */ ++ unsigned int region_ctrl_2; /* Region Control 2 Register */ ++ unsigned int lbar; /* Lower Base Address Register */ ++ unsigned int ubar; /* Upper Base Address Register */ ++ unsigned int lar; /* Limit Address Register */ ++ unsigned int ltar; /* Lower Target Address Register */ ++ unsigned int utar; /* Upper Target Address Register */ ++}; ++ ++#define MAX_IATU_PER_CTRLLER (6) ++ ++struct pcie_info { ++ /* ++ * Root bus number ++ */ ++ u8 root_bus_nr; ++ enum pcie_controller controller; ++ ++ /* ++ * Devices configuration space base ++ */ ++ unsigned int base_addr; ++ ++ /* ++ * RC configuration space base ++ */ ++ unsigned int conf_base_addr; ++}; ++ ++static struct pcie_info pcie_info[2]; ++static int pcie_controllers_nr; ++ ++static unsigned int pcie0_sel = pcie_controller_unselected; ++static unsigned int pcie0_mem_space_size = 0x0; ++ ++static unsigned int pcie_errorvalue; ++ ++/* ++ * For number 22 bus err. ++ */ ++static int pcie_fault(unsigned long addr, unsigned int fsr, ++ struct pt_regs *regs) ++{ ++ pcie_errorvalue = 1; ++ return 0; ++} ++ ++static DEFINE_SPINLOCK(cw_lock); ++ ++#define PCIE0_MODE_SEL (1 << 0) ++#define PCIE1_MODE_SEL (1 << 1) ++ ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++#include "pcie_hi3519.c" ++#elif defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) ++#include "pcie_hi3559.c" ++#elif defined(CONFIG_ARCH_HI3516AV200) ++#include "pcie_hi3516av200.c" ++#elif defined(CONFIG_ARCH_HI3531D) ++#include "pcie_hi3531d.c" ++#else ++#error You must have defined either CONFIG_ARCH_HI3519 or CONFIG_ARCH_HI3559 or CONFIG_ARCH_HI3556 or CONFIG_ARCH_HI3516AV200... ++#endif ++ ++/* ++ * PCIE memory size bootargs: pcie0_mem_size=0xa00000;pcie1_mem_size=0xa00000 ++ */ ++static int __init pcie0_mem_size_parser(char *str) ++{ ++ unsigned int size; ++ ++ if (kstrtoul(str, 16, (long *)&size) < 0) ++ return 0; ++ ++ /* if size >= 256MB, set default 256MB */ ++ if (size >= 0x10000000) ++ size = 0x10000000; ++ pcie0_mem_space_size = size; ++ ++ return 1; ++} ++__setup("pcie0_mem_size=", pcie0_mem_size_parser); ++ ++/* ++ * PCIE sel bootargs: pcie0_sel=x1 pcie1=x1 or pcie1=x2 ++ * Any other value after "pcieX_sel=" prefix ++ * will be treated as none controller selected. ++ * e.g. "pcie0_sel=none" will be treated as no PCIE0 selected. ++ */ ++static int __init pcie0_sel_parser(char *str) ++{ ++ if (strncasecmp(str, "x1", 2) == 0) ++ pcie0_sel = pcie0_x1_sel; ++ else ++ pcie0_sel = pcie_sel_none; ++ ++ return 1; ++} ++__setup("pcie0_sel=", pcie0_sel_parser); ++ ++static void __init pcie_preinit(void) ++{ ++ pcie_debug(PCIE_DBG_FUNC, "!"); ++ __arch_pcie_preinit(); ++} ++ ++static int request_pcie_res(int controller, struct pci_sys_data *sys) ++{ ++ int ret; ++ struct resource *mem = NULL; ++ struct resource *io = NULL; ++ ++ __arch_get_pcie_res(controller, &mem, &io); ++ ++ ret = request_resource(&ioport_resource, io); ++ if (ret) { ++ pcie_error( ++ "request io resource failed,io->start=0x%x,io->end=0x%x", ++ io->start, io->end); ++ return ret; ++ } ++ ++ ret = request_resource(&iomem_resource, mem); ++ if (ret) { ++ pcie_error( ++ "request mem resource failed,mem->start=0x%x,mem->end=0x%x", ++ mem->start, mem->end); ++ ++ release_resource(io); ++ return ret; ++ } ++ ++ pci_add_resource_offset(&sys->resources, io, sys->io_offset); ++ pci_add_resource_offset(&sys->resources, mem, sys->mem_offset); ++ ++ return 0; ++} ++ ++static int __init pcie_setup(int nr, struct pci_sys_data *sys) ++{ ++ struct pcie_info *info; ++ int ret; ++ ++ pcie_debug(PCIE_DBG_FUNC, "nr %d, sys->busnr %d", ++ nr, sys->busnr); ++ if (nr >= pcie_controllers_nr) ++ return 0; ++ ++ info = &pcie_info[nr]; ++ info->root_bus_nr = sys->busnr; ++ sys->mem_offset = 0; ++ ++ /* ++ * Requeset resources for the right controller. ++ */ ++ ret = request_pcie_res(info->controller, sys); ++ if (ret) ++ return ret; ++ ++ __arch_config_iatu_tbl(info, sys); ++ ++ return 1; ++} ++ ++static struct pcie_info *bus_to_info(int busnr) ++{ ++ int i = pcie_controllers_nr - 1; ++ ++ for (; i >= 0; i--) { ++ if (pcie_info[i].controller != pcie_controller_none ++ && pcie_info[i].root_bus_nr <= busnr ++ && pcie_info[i].root_bus_nr != -1) ++ return &pcie_info[i]; ++ } ++ ++ return NULL; ++} ++ ++ ++static int __init pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ struct pcie_info *info = bus_to_info(dev->bus->number); ++ ++ if (unlikely(!info)) { ++ pcie_error( ++ "%s:Cannot find corresponding controller for appointed device!", __func__); ++ BUG(); ++ } ++ ++ pcie_debug(PCIE_DBG_FUNC, ++ "dev->bus->number %d, slot %d, pin %d", ++ dev->bus->number, slot, pin); ++ return __arch_get_int_irq(info, pin); ++ ++} ++ ++#define PCIE_CFG_BUS(busnr) ((busnr & 0xff) << 20) ++#define PCIE_CFG_DEV(devfn) ((devfn & 0xff) << 12) ++#define PCIE_CFG_REG(reg) (reg & 0xffc) /*set dword align*/ ++ ++static inline unsigned int to_pcie_address(struct pci_bus *bus, ++ unsigned int devfn, int where) ++{ ++ struct pcie_info *info = bus_to_info(bus->number); ++ unsigned int address = 0; ++ ++ if (unlikely(!info)) { ++ pcie_error( ++ "%s:Cannot find corresponding controller for appointed device!", __func__); ++ BUG(); ++ } ++ ++ address = info->base_addr + (PCIE_CFG_BUS(bus->number) ++ | PCIE_CFG_DEV(devfn) | PCIE_CFG_REG(where)); ++ ++ ++ return address; ++} ++ ++static inline int is_pcie_link_up(struct pcie_info *info) ++{ ++ int i; ++ ++ for (i = 0; i < 10000; i++) { ++ if (__arch_check_pcie_link(info)) ++ break; ++ udelay(100); ++ } ++ ++ return (i < 10000); ++} ++ ++static int pcie_read_from_device(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 *value) ++{ ++ struct pcie_info *info = bus_to_info(bus->number); ++ unsigned int val; ++ void __iomem *addr; ++ int i = 0; ++ ++ if (unlikely(!info)) { ++ pcie_error( ++ "%s:Cannot find corresponding controller for appointed device!", __func__); ++ BUG(); ++ } ++ ++ if (!is_pcie_link_up(info)) { ++ pcie_debug(PCIE_DBG_MODULE, "pcie %d not link up!", ++ info->controller); ++ return -1; ++ } ++ ++ addr = (void __iomem *)to_pcie_address(bus, devfn, where); ++ ++ val = readl(addr); ++ ++ i = 0; ++ while (i < 2000) { ++ __asm__ __volatile__("nop\n"); ++ i++; ++ } ++ ++ if (pcie_errorvalue == 1) { ++ pcie_errorvalue = 0; ++ val = 0xffffffff; ++ } ++ ++ if (size == 1) ++ *value = ((val >> ((where & 0x3) << 3)) & 0xff); ++ else if (size == 2) ++ *value = ((val >> ((where & 0x3) << 3)) & 0xffff); ++ else if (size == 4) ++ *value = val; ++ else{ ++ pcie_error("Unknown size(%d) for read ops", size); ++ BUG(); ++ } ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int pcie_read_from_dbi(struct pcie_info *info, unsigned int devfn, ++ int where, int size, u32 *value) ++{ ++ unsigned int val; ++ ++ /* ++ * For host-side config space read, ignore device func nr. ++ */ ++ if (devfn > 0) ++ return -EIO; ++ ++ val = (u32)readl((void *)(info->conf_base_addr + (where & (~0x3)))); ++ ++ if (1 == size) ++ *value = (val >> ((where & 0x3) << 3)) & 0xff; ++ else if (2 == size) ++ *value = (val >> ((where & 0x3) << 3)) & 0xffff; ++ else if (4 == size) ++ *value = val; ++ else { ++ pcie_error("Unknown size for config read operation!"); ++ BUG(); ++ } ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int pcie_read_conf(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 *value) ++{ ++ struct pcie_info *info = bus_to_info(bus->number); ++ int ret; ++ ++ if (unlikely(!info)) { ++ pcie_error( ++ "%s:Cannot find corresponding controller for appointed device!", __func__); ++ BUG(); ++ } ++ ++ if (bus->number == info->root_bus_nr) ++ ret = pcie_read_from_dbi(info, devfn, where, size, value); ++ else ++ ret = pcie_read_from_device(bus, devfn, where, size, value); ++ ++ pcie_debug(PCIE_DBG_REG, ++ "bus %d, devfn %d, where 0x%x, size 0x%x, value 0x%x", ++ bus->number & 0xff, devfn, where, size, *value); ++ ++ return ret; ++} ++ ++static int pcie_write_to_device(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 value) ++{ ++ struct pcie_info *info = bus_to_info(bus->number); ++ void __iomem *addr; ++ unsigned int org; ++ unsigned long flag; ++ ++ if (unlikely(!info)) { ++ pcie_error( ++ "%s:Cannot find corresponding controller for appointed device!", __func__); ++ BUG(); ++ } ++ ++ if (!is_pcie_link_up(info)) { ++ pcie_debug(PCIE_DBG_MODULE, "pcie %d not link up!", ++ info->controller); ++ return -1; ++ } ++ ++ spin_lock_irqsave(&cw_lock, flag); ++ ++ pcie_read_from_device(bus, devfn, where, 4, &org); ++ ++ addr = (void __iomem *)to_pcie_address(bus, devfn, where); ++ ++ if (size == 1) { ++ org &= (~(0xff << ((where & 0x3) << 3))); ++ org |= (value << ((where & 0x3) << 3)); ++ } else if (size == 2) { ++ org &= (~(0xffff << ((where & 0x3) << 3))); ++ org |= (value << ((where & 0x3) << 3)); ++ } else if (size == 4) { ++ org = value; ++ } else { ++ pcie_error("Unknown size(%d) for read ops", size); ++ BUG(); ++ } ++ writel(org, addr); ++ ++ spin_unlock_irqrestore(&cw_lock, flag); ++ ++ return PCIBIOS_SUCCESSFUL; ++ ++} ++ ++static int pcie_write_to_dbi(struct pcie_info *info, unsigned int devfn, ++ int where, int size, u32 value) ++{ ++ unsigned long flag; ++ unsigned int org; ++ ++ spin_lock_irqsave(&cw_lock, flag); ++ ++ if (pcie_read_from_dbi(info, devfn, where, 4, &org)) { ++ pcie_error("Cannot read from dbi! 0x%x:0x%x:0x%x!", ++ 0, devfn, where); ++ spin_unlock_irqrestore(&cw_lock, flag); ++ return -EIO; ++ } ++ if (size == 1) { ++ org &= (~(0xff << ((where & 0x3) << 3))); ++ org |= (value << ((where & 0x3) << 3)); ++ } else if (size == 2) { ++ org &= (~(0xffff << ((where & 0x3) << 3))); ++ org |= (value << ((where & 0x3) << 3)); ++ } else if (size == 4) { ++ org = value; ++ } else { ++ pcie_error("Unknown size(%d) for read ops", size); ++ BUG(); ++ } ++ writel(org, ((void __iomem *)info->conf_base_addr + (where & (~0x3)))); ++ ++ spin_unlock_irqrestore(&cw_lock, flag); ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int pcie_write_conf(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 value) ++{ ++ struct pcie_info *info = bus_to_info(bus->number); ++ ++ pcie_debug(PCIE_DBG_REG, ++ "bus %d, devfn %d, where 0x%x, size 0x%x, value 0x%x", ++ bus->number & 0xff, devfn, where, size, value); ++ ++ if (unlikely(!info)) { ++ pcie_error( ++ "%s:Cannot find corresponding controller for appointed device!", __func__); ++ BUG(); ++ } ++ ++ if (bus->number == info->root_bus_nr) ++ return pcie_write_to_dbi(info, devfn, where, size, value); ++ else ++ return pcie_write_to_device(bus, devfn, where, size, value); ++} ++ ++static struct pci_ops pcie_ops = { ++ .read = pcie_read_conf, ++ .write = pcie_write_conf, ++}; ++ ++void pci_set_max_rd_req_size(const struct pci_bus *bus) ++{ ++ struct pci_dev *dev; ++ struct pci_bus *child; ++ int pos; ++ unsigned short dev_contrl_reg_val = 0; ++ unsigned int max_rd_req_size = 0; ++ ++ list_for_each_entry(dev, &bus->devices, bus_list) { ++ ++ /* set device max read requset size*/ ++ pos = pci_find_capability(dev, PCI_CAP_ID_EXP); ++ if (pos) { ++ pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ++ &dev_contrl_reg_val); ++ max_rd_req_size = (dev_contrl_reg_val >> 12) & 0x7; ++ if (max_rd_req_size > 0x0) { ++ dev_contrl_reg_val &= ~(max_rd_req_size << 12); ++ pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, ++ dev_contrl_reg_val); ++ } ++ ++ } ++ } ++ ++ list_for_each_entry(dev, &bus->devices, bus_list) { ++ BUG_ON(!dev->is_added); ++ child = dev->subordinate; ++ if (child) ++ pci_set_max_rd_req_size(child); ++ } ++} ++ ++static struct pci_bus *__init pcie_scan_bus(int nr, struct pci_sys_data *sys) ++{ ++ struct pci_bus *bus; ++ ++ pcie_debug(PCIE_DBG_FUNC, ++ "nr %d, sys->busnr %d, sys->mem_offset 0x%llx, sys->io_offset 0x%lx", ++ nr, sys->busnr, sys->mem_offset, sys->io_offset); ++ if (nr < pcie_controllers_nr) { ++ bus = pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys, ++ &sys->resources); ++ } else { ++ bus = NULL; ++ pcie_error("Unknown controller nr :0x%x!", nr); ++ BUG(); ++ } ++ ++#ifdef CONFIG_LIMIT_MAX_RD_REQ_SIZE ++ if (bus) ++ pci_set_max_rd_req_size(bus); ++#endif ++ ++ return bus; ++} ++ ++ ++static struct hw_pci hipcie __initdata = { ++ .nr_controllers = 1, ++ .preinit = pcie_preinit, ++ .swizzle = pci_common_swizzle, ++ .setup = pcie_setup, ++ .scan = pcie_scan_bus, ++ .map_irq = pcie_map_irq, ++}; ++ ++ ++static int __init pcie_init(void) ++{ ++ pcie_info[0].root_bus_nr = -1; ++ pcie_info[1].root_bus_nr = -1; ++ ++ /* ++ * Scene: PCIe host(RC)<--->SWITCH<--->PCIe device(*) ++ * | ++ * |------->NULL SLOT ++ * PCIe will generate a DataAbort to ARM, when scanning NULL SLOT. ++ * Register hook to capture this exception and handle it. ++ */ ++ hook_fault_code(22, pcie_fault, 7, BUS_OBJERR, ++ "external abort on non-linefetch"); ++ ++ if (__arch_pcie_info_setup(pcie_info, &pcie_controllers_nr)) ++ return -EIO; ++ ++ if (__arch_pcie_sys_init(pcie_info)) ++ goto pcie_init_err; ++ hipcie.nr_controllers = pcie_controllers_nr; ++ pr_err("Number of PCIe controllers: %d\n", ++ hipcie.nr_controllers); ++ ++ pci_common_init(&hipcie); ++ ++ return 0; ++pcie_init_err: ++ __arch_pcie_info_release(pcie_info); ++ ++ return -EIO; ++} ++ ++static void __exit pcie_uinit(void) ++{ ++ __arch_pcie_info_release(pcie_info); ++} ++ ++#include ++#include ++ ++int hisi_pcie_plat_driver_probe(struct platform_device *pdev) ++{ ++ return 0; ++} ++int hisi_pcie_plat_driver_remove(struct platform_device *pdev) ++{ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++int hisi_pcie_plat_driver_suspend(struct device *dev) ++{ ++ __arch_pcie_sys_exit(); ++ return 0; ++} ++ ++int hisi_pcie_plat_driver_resume(struct device *dev) ++{ ++ return __arch_pcie_sys_init(pcie_info); ++} ++ ++const struct dev_pm_ops hisi_pcie_pm_ops = { ++ .suspend = NULL, ++ .suspend_noirq = hisi_pcie_plat_driver_suspend, ++ .resume = NULL, ++ .resume_noirq = hisi_pcie_plat_driver_resume ++}; ++ ++#define HISI_PCIE_PM_OPS (&hisi_pcie_pm_ops) ++#else ++#define HISI_PCIE_PM_OPS NULL ++#endif ++ ++#define PCIE_RC_DRV_NAME "hisi pcie root complex" ++ ++static struct platform_driver hisi_pcie_platform_driver = { ++ .probe = hisi_pcie_plat_driver_probe, ++ .remove = hisi_pcie_plat_driver_remove, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = PCIE_RC_DRV_NAME, ++ .bus = &platform_bus_type, ++ .pm = HISI_PCIE_PM_OPS ++ }, ++}; ++ ++static void hisi_pcie_platform_device_release(struct device *dev) ++{ ++} ++ ++static struct resource hisi_pcie_resources[] = { ++ [0] = { ++ .start = PCIE_DBI_BASE, ++ .end = PCIE_DBI_BASE + __8KB__ - 1, ++ .flags = IORESOURCE_REG, ++ } ++}; ++ ++static u64 hipcie_dmamask = DMA_BIT_MASK(32); ++ ++static struct platform_device hisi_pcie_platform_device = { ++ .name = PCIE_RC_DRV_NAME, ++ .id = 0, ++ .dev = { ++ .platform_data = NULL, ++ .dma_mask = &hipcie_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ .release = hisi_pcie_platform_device_release, ++ }, ++ .num_resources = ARRAY_SIZE(hisi_pcie_resources), ++ .resource = hisi_pcie_resources, ++}; ++ ++static int __init hisi_pcie_init(void) ++{ ++ int ret; ++ ++ ret = platform_device_register(&hisi_pcie_platform_device); ++ if (ret) ++ goto err_device; ++ ++ ret = platform_driver_register(&hisi_pcie_platform_driver); ++ if (ret) ++ goto err_driver; ++ ++ if (pcie_init()) { ++ pcie_error("pcie sys init failed!"); ++ goto err_init; ++ } ++ ++ return 0; ++err_init: ++ platform_driver_unregister(&hisi_pcie_platform_driver); ++err_driver: ++ platform_device_unregister(&hisi_pcie_platform_device); ++err_device: ++ return -1; ++} ++ ++static void __exit hisi_pcie_exit(void) ++{ ++ pcie_uinit(); ++ platform_device_unregister(&hisi_pcie_platform_device); ++ platform_driver_unregister(&hisi_pcie_platform_driver); ++} ++ ++subsys_initcall(hisi_pcie_init); ++module_exit(hisi_pcie_exit); ++ ++MODULE_DESCRIPTION("Hisilicon PCI-Express Root Complex driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/pci/hipcie/pcie_hi3516av200.c b/drivers/pci/hipcie/pcie_hi3516av200.c +new file mode 100644 +index 0000000..b8b85a7 +--- /dev/null ++++ b/drivers/pci/hipcie/pcie_hi3516av200.c +@@ -0,0 +1,319 @@ ++#include ++#include "pcie_hi3516av200.h" ++ ++static void *dbi_base; ++static int __arch_pcie_info_setup(struct pcie_info *info, int *controllers_nr); ++static int __arch_pcie_sys_init(struct pcie_info *info); ++static void __arch_pcie_info_release(struct pcie_info *info); ++ ++struct pcie_iatu iatu_table[] = { ++ { ++ .viewport = 0, ++ .region_ctrl_1 = 0x00000004, ++ .region_ctrl_2 = 0x90000000, ++ .lbar = PCIE_EP_CONF_BASE + (1<<20), ++ .ubar = 0x0, ++ .lar = PCIE_EP_CONF_BASE + (2<<20) - 1, ++ .ltar = 0x01000000, ++ .utar = 0x00000000, ++ }, ++ { ++ .viewport = 1, ++ .region_ctrl_1 = 0x00000005, ++ .region_ctrl_2 = 0x90000000, ++ .lbar = PCIE_EP_CONF_BASE + (2<<20), ++ .ubar = 0x0, ++ .lar = PCIE_EP_CONF_BASE + (__128MB__ - 1), ++ .ltar = 0x02000000, ++ .utar = 0x00000000, ++ }, ++}; ++ ++static void __arch_pcie_preinit(void) ++{ ++ ++} ++ ++static struct resource pcie_mem; ++static struct resource pcie_io; ++static void __arch_get_pcie_res(int controller, ++ struct resource **pmem, ++ struct resource **pio) ++{ ++ *pmem = &pcie_mem; ++ (*pmem)->start = PCIE_MEM_BASE; ++ (*pmem)->end = PCIE_MEM_BASE + __128MB__ - 0x100000 - 1; ++ (*pmem)->flags = IORESOURCE_MEM; ++ (*pmem)->name = "memory"; ++ ++ *pio = &pcie_io; ++ (*pio)->start = PCIE_MEM_BASE + __128MB__ - 0x100000; ++ (*pio)->end = PCIE_MEM_BASE + __128MB__ - 1; ++ (*pio)->flags = IORESOURCE_IO; ++ (*pio)->name = "io"; ++} ++ ++static int __arch_get_int_irq(struct pcie_info *info, u8 pin) ++{ ++ switch (pin) { ++ case PCIE_INTA_PIN: ++ return PCIE_IRQ_INTA; ++ case PCIE_INTB_PIN: ++ return PCIE_IRQ_INTB; ++ case PCIE_INTC_PIN: ++ return PCIE_IRQ_INTC; ++ case PCIE_INTD_PIN: ++ return PCIE_IRQ_INTD; ++ default: ++ pcie_error("Unknown pin for mapping irq!"); ++ return -1; ++ } ++} ++ ++static void __arch_config_iatu_tbl(struct pcie_info *info, ++ struct pci_sys_data *sys) ++{ ++ int i; ++ void __iomem *config_base = (void __iomem *)info->conf_base_addr; ++ struct pcie_iatu *ptable = iatu_table; ++ int table_size = ARRAY_SIZE(iatu_table); ++ ++ for (i = 0; i < table_size; i++) { ++ writel((ptable + i)->viewport, config_base + 0x900); ++ writel((ptable + i)->lbar, config_base + 0x90c); ++ writel((ptable + i)->ubar, config_base + 0x910); ++ writel((ptable + i)->lar, config_base + 0x914); ++ writel((ptable + i)->ltar, config_base + 0x918); ++ writel((ptable + i)->utar, config_base + 0x91c); ++ writel((ptable + i)->region_ctrl_1, config_base + 0x904); ++ writel((ptable + i)->region_ctrl_2, config_base + 0x908); ++ } ++ ++} ++ ++static inline int __arch_check_pcie_link(struct pcie_info *info) ++{ ++ int val; ++ ++ val = readl(dbi_base + PCIE_SYS_STATE0); ++ return ((val & (1 << PCIE_XMLH_LINK_UP)) ++ && (val & (1 << PCIE_RDLH_LINK_UP))) ? 1 : 0; ++} ++ ++/* ++ * ret: ++ */ ++static int __arch_pcie_info_setup(struct pcie_info *info, int *controllers_nr) ++{ ++ unsigned int mem_size = CONFIG_PCIE0_DEVICES_MEM_SIZE; ++ unsigned int cfg_size = CONFIG_PCIE0_DEVICES_CONFIG_SIZE; ++ ++ if ((mem_size > __128MB__) || (cfg_size > __128MB__)) { ++ pcie_error( ++ "Invalid parameter: pcie mem size[0x%x], pcie cfg size[0x%x]!", ++ mem_size, cfg_size); ++ return -EINVAL; ++ } ++ ++ info->controller = 0; ++ ++ /* RC configuration space */ ++ info->conf_base_addr = (unsigned int)ioremap_nocache(PCIE_DBI_BASE, ++ __8KB__); ++ if (!info->conf_base_addr) { ++ pcie_error("Address mapping for RC dbi failed!"); ++ return -EIO; ++ } ++ ++ /* Configuration space for all EPs */ ++ info->base_addr = (unsigned int)ioremap_nocache(PCIE_EP_CONF_BASE, ++ cfg_size); ++ if (!info->base_addr) { ++ iounmap((void *)info->conf_base_addr); ++ pcie_error("Address mapping for EPs cfg failed!"); ++ return -EIO; ++ } ++ ++ *controllers_nr = 1; ++ ++ return 0; ++ ++} ++ ++static void __arch_pcie_info_release(struct pcie_info *info) ++{ ++ if (info->base_addr) ++ iounmap((void *)info->base_addr); ++ ++ if (info->conf_base_addr) ++ iounmap((void *)info->conf_base_addr); ++} ++ ++void set_pcie_para(void *crg_base) ++{ ++ unsigned int val; ++ ++ void * misc_base = (void *)IO_ADDRESS(MISC_CTRL_BASE); ++ ++ val = readl(crg_base + PERI_CRG43); ++ val = val & (~(1 << 0)); ++ val = val | (1 << 1); ++ writel(val,crg_base + PERI_CRG43); ++ ++ writel(0x1506, misc_base + MISC_CTRL33); ++ writel(0x11506, misc_base + MISC_CTRL33); ++ writel(0x1506, misc_base + MISC_CTRL33); ++ writel(0x0, misc_base + MISC_CTRL33); ++ ++ writel(0x108, misc_base + MISC_CTRL33); ++ writel(0x10108, misc_base + MISC_CTRL33); ++ writel(0x108, misc_base + MISC_CTRL33); ++ writel(0x0, misc_base + MISC_CTRL33); ++} ++ ++static int __arch_pcie_sys_init(struct pcie_info *info) ++{ ++ unsigned int val; ++ void *crg_base = (void *)IO_ADDRESS(PERI_CRG_BASE); ++ ++ dbi_base = (void *)info->conf_base_addr; ++ ++#ifdef CONFIG_ARCH_HI3516AV200 ++ /*open pcie pad oe*/ ++ val = readl(crg_base + PERI_CRG44); ++ val &= ~(PCIE_PAD_OE_MASK); ++ writel(val, crg_base + PERI_CRG44); ++ ++ /* refclk output from phy */ ++ writel(PCIE_CLKREQ_FILTER_BYPASS, ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL34)); ++ mdelay(1); ++#endif ++ ++ /* ++ * Disable PCIE ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL7); ++ val &= (~(1 << PCIE_APP_LTSSM_ENBALE)); ++ val |= (1 << PCIE_ACCESS_ENABLE); ++ writel(val, dbi_base + PCIE_SYS_CTRL7); ++ ++ /* ++ * Reset ++ */ ++ val = readl(crg_base + PERI_CRG44); ++ val |= (1 << PCIE_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG44); ++ ++ /* ++ * Retreat from the reset state ++ */ ++ udelay(500); ++ val = readl(crg_base + PERI_CRG44); ++ val &= ~(1 << PCIE_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG44); ++ mdelay(10); ++ ++ ++ /* ++ * PCIE RC work mode ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL0); ++ val &= (~(0xf << PCIE_DEVICE_TYPE)); ++ val |= (PCIE_WM_RC << PCIE_DEVICE_TYPE); ++ writel(val, dbi_base + PCIE_SYS_CTRL0); ++ ++ /* ++ * Enable clk ++ */ ++ val = readl(crg_base + PERI_CRG44); ++ val |= ((1 << PCIE_X2_BUS_CKEN) ++ | (1 << PCIE_X2_SYS_CKEN) ++ | (1 << PCIE_X2_PIPE_CKEN) ++ | (1 << PCIE_X2_AUX_CKEN)); ++ writel(val, crg_base + PERI_CRG44); ++ ++ mdelay(10); ++ ++ ++ set_pcie_para(crg_base); ++ mdelay(10); ++ ++ /* ++ * Set PCIE controller class code to be PCI-PCI bridge device ++ */ ++ val = readl(dbi_base + PCI_CLASS_REVISION); ++ val &= ~(0xffffff00); ++ val |= (0x60400 << 8); ++ writel(val, dbi_base + PCI_CLASS_REVISION); ++ udelay(1000); ++ ++#ifdef CONFIG_ARCH_HI3516AV200 ++ /* phy always work at 5Gbps */ ++ writel(COM_PHY_TEST_VAL1, ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL33)); ++ writel(COM_PHY_TEST_VAL2, ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL33)); ++ writel(COM_PHY_TEST_VAL1, ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL33)); ++ writel(0x0, (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL33)); ++ ++ /* default deemphasis to -3.5 dB */ ++ writel(DEEMPHASIS_VAL, (void *)IO_ADDRESS(PCIE_DBI_BASE + DEEMPHASIS_REG)); ++#endif ++ ++ /* ++ * Enable controller ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL7); ++ val |= (1 << PCIE_APP_LTSSM_ENBALE); ++ writel(val, dbi_base + PCIE_SYS_CTRL7); ++ udelay(1000); ++ ++ val = readl(dbi_base + PCI_COMMAND); ++ val |= 7; ++ writel(val, dbi_base + PCI_COMMAND); ++ ++ /* set pcie to gen 1*/ ++#if 0 ++ writel(0x1, dbi_base + 0x8BC); ++ val = readl(dbi_base + 0x7C); ++ val = ((val >> 4) << 4) | 0x1; ++ writel(val, dbi_base + 0x7C); ++#endif ++ return 0; ++} ++ ++static void __arch_pcie_sys_exit(void) ++{ ++ unsigned int val; ++ void *crg_base = (void *)IO_ADDRESS(PERI_CRG_BASE); ++ ++ /* ++ * Disable PCIE ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL7); ++ val &= (~(1 << PCIE_APP_LTSSM_ENBALE)); ++ writel(val, dbi_base + PCIE_SYS_CTRL7); ++ ++ /* ++ * Reset ++ */ ++ val = readl(crg_base + PERI_CRG44); ++ val |= (1 << PCIE_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG44); ++ ++ udelay(1000); ++ ++ /* ++ * Disable clk ++ */ ++ val = readl(crg_base + PERI_CRG44); ++ val &= (~(1 << PCIE_X2_AUX_CKEN)); ++ val &= (~(1 << PCIE_X2_PIPE_CKEN)); ++ val &= (~(1 << PCIE_X2_SYS_CKEN)); ++ val &= (~(1 << PCIE_X2_BUS_CKEN)); ++ writel(val, crg_base + PERI_CRG44); ++ ++ udelay(1000); ++} +diff --git a/drivers/pci/hipcie/pcie_hi3516av200.h b/drivers/pci/hipcie/pcie_hi3516av200.h +new file mode 100644 +index 0000000..e185999 +--- /dev/null ++++ b/drivers/pci/hipcie/pcie_hi3516av200.h +@@ -0,0 +1,55 @@ ++#ifndef __HISI_PCIE_H__ ++#define __HISI_PCIE_H__ ++ ++#define MISC_CTRL_BASE 0x12030000 ++#define PCIE_MEM_BASE 0x28000000 ++#define PCIE_EP_CONF_BASE 0x20000000 ++#define PCIE_DBI_BASE 0x12160000 ++#define PERI_CRG_BASE 0x12010000 ++ ++#define PERI_CRG43 0xAC ++#define PERI_CRG44 0xB0 ++#define PCIE_X2_SRST_REQ 2 ++ ++#define PCIE_X2_AUX_CKEN 7 ++#define PCIE_X2_PIPE_CKEN 6 ++#define PCIE_X2_SYS_CKEN 5 ++#define PCIE_X2_BUS_CKEN 4 ++#define PCIE_PAD_OE_MASK (0x7 << 8) ++ ++#define PCIE_SYS_CTRL0 0x1000 ++#define PCIE_DEVICE_TYPE 28 ++#define PCIE_WM_EP 0x0 ++#define PCIE_WM_LEGACY 0x1 ++#define PCIE_WM_RC 0x4 ++ ++#define PCIE_SYS_CTRL7 0x101C ++#define PCIE_APP_LTSSM_ENBALE 11 ++#define PCIE_ACCESS_ENABLE 13 ++ ++#define PCIE_SYS_STATE0 0x1100 ++#define PCIE_XMLH_LINK_UP 15 ++#define PCIE_RDLH_LINK_UP 5 ++ ++#define PCIE_IRQ_INTA 89 ++#define PCIE_IRQ_INTB 90 ++#define PCIE_IRQ_INTC 91 ++#define PCIE_IRQ_INTD 92 ++#define PCIE_IRQ_EDMA 93 ++#define PCIE_IRQ_MSI 94 ++#define PCIE_IRQ_LINK_DOWN 95 ++ ++#define PCIE_INTA_PIN 1 ++#define PCIE_INTB_PIN 2 ++#define PCIE_INTC_PIN 3 ++#define PCIE_INTD_PIN 4 ++ ++#define MISC_CTRL33 0x84 ++#define MISC_CTRL34 0x88 ++#define DEEMPHASIS_REG 0xa0 ++#define PCIE_CLKREQ_FILTER_BYPASS 0x600 ++#define DEEMPHASIS_VAL 0x42 ++#define COM_PHY_TEST_VAL1 ((0x1 << 3) | (0x1 << 8)) ++#define COM_PHY_TEST_VAL2 ((0x1 << 16) | (0x1 << 3) | (0x1 << 8)) ++ ++#endif +diff --git a/drivers/pci/hipcie/pcie_hi3519.c b/drivers/pci/hipcie/pcie_hi3519.c +new file mode 100644 +index 0000000..fdfdf0a +--- /dev/null ++++ b/drivers/pci/hipcie/pcie_hi3519.c +@@ -0,0 +1,335 @@ ++#include ++#include "pcie_hi3519.h" ++ ++static void *dbi_base; ++static int __arch_pcie_info_setup(struct pcie_info *info, int *controllers_nr); ++static int __arch_pcie_sys_init(struct pcie_info *info); ++static void __arch_pcie_info_release(struct pcie_info *info); ++ ++struct pcie_iatu iatu_table[] = { ++ { ++ .viewport = 0, ++ .region_ctrl_1 = 0x00000004, ++ .region_ctrl_2 = 0x90000000, ++ .lbar = PCIE_EP_CONF_BASE + (1<<20), ++ .ubar = 0x0, ++ .lar = PCIE_EP_CONF_BASE + (2<<20) - 1, ++ .ltar = 0x01000000, ++ .utar = 0x00000000, ++ }, ++ { ++ .viewport = 1, ++ .region_ctrl_1 = 0x00000005, ++ .region_ctrl_2 = 0x90000000, ++ .lbar = PCIE_EP_CONF_BASE + (2<<20), ++ .ubar = 0x0, ++ .lar = PCIE_EP_CONF_BASE + (__128MB__ - 1), ++ .ltar = 0x02000000, ++ .utar = 0x00000000, ++ }, ++}; ++ ++static void __arch_pcie_preinit(void) ++{ ++ ++} ++ ++static struct resource pcie_mem; ++static struct resource pcie_io; ++static void __arch_get_pcie_res(int controller, ++ struct resource **pmem, ++ struct resource **pio) ++{ ++ *pmem = &pcie_mem; ++ (*pmem)->start = PCIE_MEM_BASE; ++ (*pmem)->end = PCIE_MEM_BASE + __128MB__ - 0x100000 - 1; ++ (*pmem)->flags = IORESOURCE_MEM; ++ (*pmem)->name = "memory"; ++ ++ *pio = &pcie_io; ++ (*pio)->start = PCIE_MEM_BASE + __128MB__ - 0x100000; ++ (*pio)->end = PCIE_MEM_BASE + __128MB__ - 1; ++ (*pio)->flags = IORESOURCE_IO; ++ (*pio)->name = "io"; ++} ++ ++static int __arch_get_int_irq(struct pcie_info *info, u8 pin) ++{ ++ switch (pin) { ++ case PCIE_INTA_PIN: ++ return PCIE_IRQ_INTA; ++ case PCIE_INTB_PIN: ++ return PCIE_IRQ_INTB; ++ case PCIE_INTC_PIN: ++ return PCIE_IRQ_INTC; ++ case PCIE_INTD_PIN: ++ return PCIE_IRQ_INTD; ++ default: ++ pcie_error("Unknown pin for mapping irq!"); ++ return -1; ++ } ++} ++ ++static void __arch_config_iatu_tbl(struct pcie_info *info, ++ struct pci_sys_data *sys) ++{ ++ int i; ++ void __iomem *config_base = (void __iomem *)info->conf_base_addr; ++ struct pcie_iatu *ptable = iatu_table; ++ int table_size = ARRAY_SIZE(iatu_table); ++ ++ for (i = 0; i < table_size; i++) { ++ writel((ptable + i)->viewport, config_base + 0x900); ++ writel((ptable + i)->lbar, config_base + 0x90c); ++ writel((ptable + i)->ubar, config_base + 0x910); ++ writel((ptable + i)->lar, config_base + 0x914); ++ writel((ptable + i)->ltar, config_base + 0x918); ++ writel((ptable + i)->utar, config_base + 0x91c); ++ writel((ptable + i)->region_ctrl_1, config_base + 0x904); ++ writel((ptable + i)->region_ctrl_2, config_base + 0x908); ++ } ++ ++} ++ ++static inline int __arch_check_pcie_link(struct pcie_info *info) ++{ ++ int val; ++ ++ val = readl(dbi_base + PCIE_SYS_STATE0); ++ return ((val & (1 << PCIE_XMLH_LINK_UP)) ++ && (val & (1 << PCIE_RDLH_LINK_UP))) ? 1 : 0; ++} ++ ++/* ++ * ret: ++ */ ++static int __arch_pcie_info_setup(struct pcie_info *info, int *controllers_nr) ++{ ++ unsigned int mem_size = CONFIG_PCIE0_DEVICES_MEM_SIZE; ++ unsigned int cfg_size = CONFIG_PCIE0_DEVICES_CONFIG_SIZE; ++ ++ if ((mem_size > __128MB__) || (cfg_size > __128MB__)) { ++ pcie_error( ++ "Invalid parameter: pcie mem size[0x%x], pcie cfg size[0x%x]!", ++ mem_size, cfg_size); ++ return -EINVAL; ++ } ++ ++ info->controller = 0; ++ ++ /* RC configuration space */ ++ info->conf_base_addr = (unsigned int)ioremap_nocache(PCIE_DBI_BASE, ++ __8KB__); ++ if (!info->conf_base_addr) { ++ pcie_error("Address mapping for RC dbi failed!"); ++ return -EIO; ++ } ++ ++ /* Configuration space for all EPs */ ++ info->base_addr = (unsigned int)ioremap_nocache(PCIE_EP_CONF_BASE, ++ cfg_size); ++ if (!info->base_addr) { ++ iounmap((void *)info->conf_base_addr); ++ pcie_error("Address mapping for EPs cfg failed!"); ++ return -EIO; ++ } ++ ++ *controllers_nr = 1; ++ ++ return 0; ++ ++} ++ ++static void __arch_pcie_info_release(struct pcie_info *info) ++{ ++ if (info->base_addr) ++ iounmap((void *)info->base_addr); ++ ++ if (info->conf_base_addr) ++ iounmap((void *)info->conf_base_addr); ++} ++ ++void set_pcie_para(void *crg_base) ++{ ++ unsigned int val; ++ ++ void * misc_base = (void *)IO_ADDRESS(MISC_CTRL_BASE); ++ ++ val = readl(crg_base + PERI_CRG43); ++ val = val & (~(1 << 0)); ++ val = val | (1 << 1); ++ writel(val,crg_base + PERI_CRG43); ++ ++#ifdef CONFIG_ARCH_HI3519V101 ++ writel(0x1506, misc_base + MISC_CTRL33); ++ writel(0x11506, misc_base + MISC_CTRL33); ++ writel(0x1506, misc_base + MISC_CTRL33); ++ writel(0x0, misc_base + MISC_CTRL33); ++ ++ writel(0x108, misc_base + MISC_CTRL33); ++ writel(0x10108, misc_base + MISC_CTRL33); ++ writel(0x108, misc_base + MISC_CTRL33); ++ writel(0x0, misc_base + MISC_CTRL33); ++#else ++ writel(0x1a04, misc_base + MISC_CTRL33); ++ writel(0x11a04, misc_base + MISC_CTRL33); ++ writel(0x1a04, misc_base + MISC_CTRL33); ++ writel(0x0, misc_base + MISC_CTRL33); ++ ++ writel(0xc09, misc_base + MISC_CTRL33); ++ writel(0x10c09, misc_base + MISC_CTRL33); ++ writel(0xc09, misc_base + MISC_CTRL33); ++ writel(0x0, misc_base + MISC_CTRL33); ++ ++ writel(0x303, misc_base + MISC_CTRL33); ++ writel(0x10303, misc_base + MISC_CTRL33); ++ writel(0x303, misc_base + MISC_CTRL33); ++ writel(0x0, misc_base + MISC_CTRL33); ++#endif ++} ++ ++static int __arch_pcie_sys_init(struct pcie_info *info) ++{ ++ unsigned int val; ++ void *crg_base = (void *)IO_ADDRESS(PERI_CRG_BASE); ++ ++ dbi_base = (void *)info->conf_base_addr; ++ ++#ifdef CONFIG_ARCH_HI3519V101 ++ /*open pcie pad oe*/ ++ val = readl(crg_base + PERI_CRG44); ++ val &= ~(PCIE_PAD_OE_MASK); ++ writel(val, crg_base + PERI_CRG44); ++ ++ /* refclk output from phy */ ++ writel(PCIE_CLKREQ_FILTER_BYPASS, ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL34)); ++ mdelay(1); ++#endif ++ ++ /* ++ * Disable PCIE ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL7); ++ val &= (~(1 << PCIE_APP_LTSSM_ENBALE)); ++ val |= (1 << PCIE_ACCESS_ENABLE); ++ writel(val, dbi_base + PCIE_SYS_CTRL7); ++ ++ /* ++ * Reset ++ */ ++ val = readl(crg_base + PERI_CRG44); ++ val |= (1 << PCIE_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG44); ++ ++ /* ++ * Retreat from the reset state ++ */ ++ udelay(500); ++ val = readl(crg_base + PERI_CRG44); ++ val &= ~(1 << PCIE_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG44); ++ mdelay(10); ++ ++ ++ /* ++ * PCIE RC work mode ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL0); ++ val &= (~(0xf << PCIE_DEVICE_TYPE)); ++ val |= (PCIE_WM_RC << PCIE_DEVICE_TYPE); ++ writel(val, dbi_base + PCIE_SYS_CTRL0); ++ ++ /* ++ * Enable clk ++ */ ++ val = readl(crg_base + PERI_CRG44); ++ val |= ((1 << PCIE_X2_BUS_CKEN) ++ | (1 << PCIE_X2_SYS_CKEN) ++ | (1 << PCIE_X2_PIPE_CKEN) ++ | (1 << PCIE_X2_AUX_CKEN)); ++ writel(val, crg_base + PERI_CRG44); ++ ++ mdelay(10); ++ ++ set_pcie_para(crg_base); ++ mdelay(10); ++ ++ /* ++ * Set PCIE controller class code to be PCI-PCI bridge device ++ */ ++ val = readl(dbi_base + PCI_CLASS_REVISION); ++ val &= ~(0xffffff00); ++ val |= (0x60400 << 8); ++ writel(val, dbi_base + PCI_CLASS_REVISION); ++ udelay(1000); ++ ++#ifdef CONFIG_ARCH_HI3519V101 ++ /* phy always work at 5Gbps */ ++ writel(COM_PHY_TEST_VAL1, ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL33)); ++ writel(COM_PHY_TEST_VAL2, ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL33)); ++ writel(COM_PHY_TEST_VAL1, ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL33)); ++ writel(0x0, (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL33)); ++ ++ /* default deemphasis to -3.5 dB */ ++ writel(DEEMPHASIS_VAL, (void *)IO_ADDRESS(PCIE_DBI_BASE + DEEMPHASIS_REG)); ++#endif ++ ++ /* ++ * Enable controller ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL7); ++ val |= (1 << PCIE_APP_LTSSM_ENBALE); ++ writel(val, dbi_base + PCIE_SYS_CTRL7); ++ udelay(1000); ++ ++ val = readl(dbi_base + PCI_COMMAND); ++ val |= 7; ++ writel(val, dbi_base + PCI_COMMAND); ++ ++ /* set pcie to gen 1*/ ++#if 0 ++ writel(0x1, dbi_base + 0x8BC); ++ val = readl(dbi_base + 0x7C); ++ val = ((val >> 4) << 4) | 0x1; ++ writel(val, dbi_base + 0x7C); ++#endif ++ return 0; ++} ++ ++static void __arch_pcie_sys_exit(void) ++{ ++ unsigned int val; ++ void *crg_base = (void *)IO_ADDRESS(PERI_CRG_BASE); ++ ++ /* ++ * Disable PCIE ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL7); ++ val &= (~(1 << PCIE_APP_LTSSM_ENBALE)); ++ writel(val, dbi_base + PCIE_SYS_CTRL7); ++ ++ /* ++ * Reset ++ */ ++ val = readl(crg_base + PERI_CRG44); ++ val |= (1 << PCIE_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG44); ++ ++ udelay(1000); ++ ++ /* ++ * Disable clk ++ */ ++ val = readl(crg_base + PERI_CRG44); ++ val &= (~(1 << PCIE_X2_AUX_CKEN)); ++ val &= (~(1 << PCIE_X2_PIPE_CKEN)); ++ val &= (~(1 << PCIE_X2_SYS_CKEN)); ++ val &= (~(1 << PCIE_X2_BUS_CKEN)); ++ writel(val, crg_base + PERI_CRG44); ++ ++ udelay(1000); ++} +diff --git a/drivers/pci/hipcie/pcie_hi3519.h b/drivers/pci/hipcie/pcie_hi3519.h +new file mode 100644 +index 0000000..e185999 +--- /dev/null ++++ b/drivers/pci/hipcie/pcie_hi3519.h +@@ -0,0 +1,55 @@ ++#ifndef __HISI_PCIE_H__ ++#define __HISI_PCIE_H__ ++ ++#define MISC_CTRL_BASE 0x12030000 ++#define PCIE_MEM_BASE 0x28000000 ++#define PCIE_EP_CONF_BASE 0x20000000 ++#define PCIE_DBI_BASE 0x12160000 ++#define PERI_CRG_BASE 0x12010000 ++ ++#define PERI_CRG43 0xAC ++#define PERI_CRG44 0xB0 ++#define PCIE_X2_SRST_REQ 2 ++ ++#define PCIE_X2_AUX_CKEN 7 ++#define PCIE_X2_PIPE_CKEN 6 ++#define PCIE_X2_SYS_CKEN 5 ++#define PCIE_X2_BUS_CKEN 4 ++#define PCIE_PAD_OE_MASK (0x7 << 8) ++ ++#define PCIE_SYS_CTRL0 0x1000 ++#define PCIE_DEVICE_TYPE 28 ++#define PCIE_WM_EP 0x0 ++#define PCIE_WM_LEGACY 0x1 ++#define PCIE_WM_RC 0x4 ++ ++#define PCIE_SYS_CTRL7 0x101C ++#define PCIE_APP_LTSSM_ENBALE 11 ++#define PCIE_ACCESS_ENABLE 13 ++ ++#define PCIE_SYS_STATE0 0x1100 ++#define PCIE_XMLH_LINK_UP 15 ++#define PCIE_RDLH_LINK_UP 5 ++ ++#define PCIE_IRQ_INTA 89 ++#define PCIE_IRQ_INTB 90 ++#define PCIE_IRQ_INTC 91 ++#define PCIE_IRQ_INTD 92 ++#define PCIE_IRQ_EDMA 93 ++#define PCIE_IRQ_MSI 94 ++#define PCIE_IRQ_LINK_DOWN 95 ++ ++#define PCIE_INTA_PIN 1 ++#define PCIE_INTB_PIN 2 ++#define PCIE_INTC_PIN 3 ++#define PCIE_INTD_PIN 4 ++ ++#define MISC_CTRL33 0x84 ++#define MISC_CTRL34 0x88 ++#define DEEMPHASIS_REG 0xa0 ++#define PCIE_CLKREQ_FILTER_BYPASS 0x600 ++#define DEEMPHASIS_VAL 0x42 ++#define COM_PHY_TEST_VAL1 ((0x1 << 3) | (0x1 << 8)) ++#define COM_PHY_TEST_VAL2 ((0x1 << 16) | (0x1 << 3) | (0x1 << 8)) ++ ++#endif +diff --git a/drivers/pci/hipcie/pcie_hi3531d.c b/drivers/pci/hipcie/pcie_hi3531d.c +new file mode 100644 +index 0000000..24c3a6d +--- /dev/null ++++ b/drivers/pci/hipcie/pcie_hi3531d.c +@@ -0,0 +1,641 @@ ++ ++#include "pcie_hi3531d.h" ++ ++static void *dbi_base_pcie0; ++static void *dbi_base_pcie1; ++static void *__iomem misc_ctrl_virt; ++static int __arch_pcie_info_setup(struct pcie_info *info, int *controllers_nr); ++static int __arch_pcie_sys_init(struct pcie_info *info); ++static void __arch_pcie_info_release(struct pcie_info *info); ++ ++struct pcie_iatu pcie0_iatu_table[] = { ++ { ++ .viewport = 0, ++ .region_ctrl_1 = 0x00000004, ++ .region_ctrl_2 = 0x90000000, ++ .lbar = PCIE0_EP_CONF_BASE + (1<<20), ++ .ubar = 0x0, ++ .lar = PCIE0_EP_CONF_BASE + (2<<20) - 1, ++ .ltar = 0x01000000, ++ .utar = 0x00000000, ++ }, ++ { ++ .viewport = 1, ++ .region_ctrl_1 = 0x00000005, ++ .region_ctrl_2 = 0x90000000, ++ .lbar = PCIE0_EP_CONF_BASE + (2<<20), ++ .ubar = 0x0, ++ .lar = PCIE0_EP_CONF_BASE + (__128MB__ - 1), ++ .ltar = 0x02000000, ++ .utar = 0x00000000, ++ }, ++}; ++ ++struct pcie_iatu pcie1_iatu_table[] = { ++ { ++ .viewport = 0, ++ .region_ctrl_1 = 0x00000004, ++ .region_ctrl_2 = 0x90000000, ++ .lbar = PCIE1_EP_CONF_BASE, ++ .ubar = 0x0, ++ .lar = PCIE1_EP_CONF_BASE + (1<<20) - 1, ++ .ltar = 0x01000000, ++ .utar = 0x00000000, ++ }, ++ { ++ .viewport = 1, ++ .region_ctrl_1 = 0x00000005, ++ .region_ctrl_2 = 0x90000000, ++ .lbar = PCIE1_EP_CONF_BASE, ++ .ubar = 0x0, ++ .lar = PCIE1_EP_CONF_BASE + (__128MB__ - 1), ++ .ltar = 0x02000000, ++ .utar = 0x00000000, ++ }, ++}; ++ ++static void __arch_pcie_preinit(void) ++{ ++ ++} ++ ++static struct resource pcie_mem[2]; ++static struct resource pcie_io[2]; ++static void __arch_get_pcie_res(int controller, ++ struct resource **pmem, ++ struct resource **pio) ++{ ++ if (controller >= 2) { ++ pcie_error("Pcie controller index(%d) error!", controller); ++ return; ++ } ++ ++ ++ *pmem = &pcie_mem[controller]; ++ *pio = &pcie_io[controller]; ++ ++ if (pcie_controller_0 == controller) { ++ (*pmem)->start = PCIE0_MEM_BASE; ++ (*pmem)->end = PCIE0_MEM_BASE + 0x8000000 - 1; ++ (*pmem)->flags = IORESOURCE_MEM; ++ (*pmem)->name = "memory"; ++ ++ (*pio)->start = 0x0; ++ (*pio)->end = 0x0; ++ (*pio)->flags = IORESOURCE_IO; ++ (*pio)->name = "io"; ++ } ++ ++ if (pcie_controller_1 == controller) { ++ ++ (*pmem)->start = PCIE1_MEM_BASE; ++ (*pmem)->end = PCIE1_MEM_BASE + 0x8000000 - 1; ++ (*pmem)->flags = IORESOURCE_MEM; ++ (*pmem)->name = "memory"; ++ ++ (*pio)->start = 0x1; ++ (*pio)->end = 0x1; ++ (*pio)->flags = IORESOURCE_IO; ++ (*pio)->name = "io"; ++ } ++} ++ ++static int __arch_get_int_irq(struct pcie_info *info, u8 pin) ++{ ++ if (pcie_controller_0 == info->controller) { ++ switch (pin) { ++ case PCIE_INTA_PIN: ++ return PCIE0_IRQ_INTA; ++ case PCIE_INTB_PIN: ++ return PCIE0_IRQ_INTB; ++ case PCIE_INTC_PIN: ++ return PCIE0_IRQ_INTC; ++ case PCIE_INTD_PIN: ++ return PCIE0_IRQ_INTD; ++ default: ++ pcie_error("Unknown pin for mapping irq!"); ++ return -1; ++ } ++ } ++ ++ if (pcie_controller_1 == info->controller) { ++ switch (pin) { ++ case PCIE_INTA_PIN: ++ return PCIE1_IRQ_INTA; ++ case PCIE_INTB_PIN: ++ return PCIE1_IRQ_INTB; ++ case PCIE_INTC_PIN: ++ return PCIE1_IRQ_INTC; ++ case PCIE_INTD_PIN: ++ return PCIE1_IRQ_INTD; ++ default: ++ pcie_error("Unknown pin for mapping irq!"); ++ return -1; ++ } ++ } ++ ++ return -1; ++} ++ ++static void __arch_config_iatu_tbl(struct pcie_info *info, ++ struct pci_sys_data *sys) ++{ ++ int i; ++ void __iomem *config_base; ++ struct pcie_iatu *ptable; ++ int table_size; ++ unsigned int ctl1_lbar_offset; ++ ++ config_base = (void __iomem *)info->conf_base_addr; ++ ++ if (pcie_controller_0 == info->controller) { ++ ptable = pcie0_iatu_table; ++ table_size = ARRAY_SIZE(pcie0_iatu_table); ++ } ++ ++ if (pcie_controller_1 == info->controller) { ++ ptable = pcie1_iatu_table; ++ table_size = ARRAY_SIZE(pcie1_iatu_table); ++ ++ ctl1_lbar_offset = (sys->busnr + 1) << 20; ++ ptable->lbar |= ctl1_lbar_offset; ++ ptable->lar |= ctl1_lbar_offset; ++ ++ ctl1_lbar_offset = (sys->busnr + 2) << 20; ++ (ptable + 1)->lbar |= ctl1_lbar_offset; ++ } ++ ++ for (i = 0; i < table_size; i++) { ++ writel((ptable + i)->viewport, config_base + 0x900); ++ writel((ptable + i)->lbar, config_base + 0x90c); ++ writel((ptable + i)->ubar, config_base + 0x910); ++ writel((ptable + i)->lar, config_base + 0x914); ++ writel((ptable + i)->ltar, config_base + 0x918); ++ writel((ptable + i)->utar, config_base + 0x91c); ++ writel((ptable + i)->region_ctrl_1, config_base + 0x904); ++ writel((ptable + i)->region_ctrl_2, config_base + 0x908); ++ } ++ ++} ++ ++static inline int __arch_check_pcie_link(struct pcie_info *info) ++{ ++ int val; ++ ++ if (pcie_controller_0 == info->controller) { ++ val = readl(dbi_base_pcie0 + PCIE_SYS_STATE0); ++ return ((val & (1 << PCIE_XMLH_LINK_UP)) ++ && (val & (1 << PCIE_RDLH_LINK_UP))) ? 1 : 0; ++ } ++ ++ if (pcie_controller_1 == info->controller) { ++ val = readl(dbi_base_pcie1 + PCIE_SYS_STATE0); ++ return ((val & (1 << PCIE_XMLH_LINK_UP)) ++ && (val & (1 << PCIE_RDLH_LINK_UP))) ? 1 : 0; ++ } ++ ++ return 0; ++} ++ ++/* ++ * ret: ++ */ ++static int __arch_pcie_info_set(struct pcie_info *info, int controller) ++{ ++ unsigned int pcie_mem_size; ++ unsigned int pcie_cfg_size; ++ unsigned int pcie_dbi_base; ++ unsigned int pcie_ep_conf_base; ++ ++#if CONFIG_PCIE0_SEL ++ if (pcie_controller_0 == controller) { ++ pcie_mem_size = CONFIG_PCIE0_DEVICES_MEM_SIZE; ++ pcie_cfg_size = CONFIG_PCIE0_DEVICES_CONFIG_SIZE; ++ pcie_dbi_base = PCIE0_DBI_BASE; ++ pcie_ep_conf_base = PCIE0_EP_CONF_BASE; ++ } ++#endif ++#if CONFIG_PCIE1_SEL ++ if (pcie_controller_1 == controller) { ++ pcie_mem_size = CONFIG_PCIE1_DEVICES_MEM_SIZE; ++ pcie_cfg_size = CONFIG_PCIE1_DEVICES_CONFIG_SIZE; ++ pcie_dbi_base = PCIE1_DBI_BASE; ++ pcie_ep_conf_base = PCIE1_EP_CONF_BASE; ++ } ++#endif ++ ++ if ((pcie_mem_size > __128MB__) || (pcie_cfg_size > __128MB__)) { ++ pcie_error( ++ "Invalid parameter: pcie mem size[0x%x], pcie cfg size[0x%x]!", ++ pcie_mem_size, pcie_cfg_size); ++ return -EINVAL; ++ } ++ ++ info->controller = controller; ++ ++ /* RC configuration space */ ++ info->conf_base_addr = (unsigned int)ioremap_nocache(pcie_dbi_base, ++ __8KB__); ++ if (!info->conf_base_addr) { ++ pcie_error("Address mapping for RC dbi failed!"); ++ return -EIO; ++ } ++ ++ /* Configuration space for all EPs */ ++ info->base_addr = (unsigned int)ioremap_nocache(pcie_ep_conf_base, ++ pcie_cfg_size); ++ if (!info->base_addr) { ++ iounmap((void *)info->conf_base_addr); ++ pcie_error("Address mapping for EPs cfg failed!"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static void __arch_pcie_info_clr(struct pcie_info *info) ++{ ++ if (info->base_addr) ++ iounmap((void *)info->base_addr); ++ ++ if (info->conf_base_addr) ++ iounmap((void *)info->conf_base_addr); ++} ++ ++static int __arch_get_port_nr(void) ++{ ++ unsigned int val, mode; ++ int nr; ++ ++ val = readl((void *)PCIE_SYS_STAT); ++ mode = (val >> 12) & 0xf; ++ switch (mode) { ++ case 0x1: ++ case 0x9: ++ nr = 1; ++ break; ++ ++ case 0x3: ++ case 0xb: ++ nr = 2; ++ break; ++ ++ default: ++ nr = 0; ++ break; ++ } ++ ++ return nr; ++} ++ ++static int __arch_pcie_info_setup(struct pcie_info *info, int *controllers_nr) ++{ ++ int nr; ++ ++ misc_ctrl_virt = (void *)IO_ADDRESS(MISC_CTRL_BASE); ++ ++ nr = __arch_get_port_nr(); ++ if (!nr) { ++ pr_err("Pcie port number: 0\n"); ++ return -EINVAL; ++ } ++ *controllers_nr = 0; ++ ++#if CONFIG_PCIE0_SEL ++ if (__arch_pcie_info_set(&info[*controllers_nr], pcie_controller_0)) ++ return -EIO; ++ (*controllers_nr)++; ++#endif ++#if CONFIG_PCIE1_SEL ++ if (nr < 2) { ++ pr_err("1-PCIE port mode, skip PCIE1 even config pcie1-sel!\n"); ++ return 0; ++ } ++ if (__arch_pcie_info_set(&info[*controllers_nr], pcie_controller_1)) { ++#if CONFIG_PCIE0_SEL ++ __arch_pcie_info_clr(&info[pcie_controller_0]); ++#endif ++ return -EIO; ++ } ++ (*controllers_nr)++; ++#endif ++ ++ return 0; ++} ++ ++static void __arch_pcie_info_release(struct pcie_info *info) ++{ ++ int nr; ++ ++ for (nr = 0; nr < pcie_controllers_nr; nr++) ++ __arch_pcie_info_clr(&info[nr]); ++} ++ ++void set_pcie0_para(void) ++{ ++ unsigned int val; ++ unsigned int flag; ++ ++ val = readl((void *)PCIE_SYS_STAT); ++ flag = (val >> 12) & 0xf; ++ ++ switch(flag) { ++ case 0x1: ++ case 0x3: ++ case 0x9: ++ case 0xb: ++ writel(0x615, misc_ctrl_virt + MISC_CTRL81); ++ writel(0x655, misc_ctrl_virt + MISC_CTRL81); ++ writel(0x615, misc_ctrl_virt + MISC_CTRL81); ++ writel(0x0, misc_ctrl_virt + MISC_CTRL81); ++ break; ++ default: ++ break; ++ ++ } ++} ++ ++void set_pcie1_para(void) ++{ ++ unsigned int val; ++ unsigned int flag; ++ ++ val = readl((void *)PCIE_SYS_STAT); ++ flag = (val >> 12) & 0xf; ++ ++ switch(flag) { ++ case 0x3: ++ case 0xb: ++ writel(0x615, misc_ctrl_virt + MISC_CTRL80); ++ writel(0x655, misc_ctrl_virt + MISC_CTRL80); ++ writel(0x615, misc_ctrl_virt + MISC_CTRL80); ++ writel(0x0, misc_ctrl_virt + MISC_CTRL80); ++ break; ++ default: ++ break; ++ ++ } ++} ++ ++static void __arch_pcie_sys_config(struct pcie_info *info) ++{ ++ static unsigned int loop_count = 0, comp_mode_nr = 0; ++ unsigned int val; ++ void *dbi_base = (void *)info->conf_base_addr; ++ void *crg_base = (void *)IO_ADDRESS(PERI_CRG_BASE); ++ ++ /* set pcie crg */ ++ writel(COMPHY_CLK_REST_VAL, crg_base + PERI_CRG_72); ++ ++ if (comp_mode_nr > 1) { ++ /* PCIE 1*/ ++ /* phy always work at 5Gbps */ ++ /* step1 addr/data enable: 0x901 */ ++ writel((PCIE_COMBPHY_TEST_ADDR_EN | PCIE_COMBPHY_TEST_DATA_EN), ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL80)); ++ /* step2 write enable: 0x941*/ ++ writel((PCIE_COMBPHY_TEST_ADDR_EN ++ | PCIE_COMBPHY_TEST_DATA_EN ++ | PCIE_COMBPHY_TEST_WR_EN), ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL80)); ++ /* step3 write release: 0x901 */ ++ writel((PCIE_COMBPHY_TEST_ADDR_EN | PCIE_COMBPHY_TEST_DATA_EN), ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL80)); ++ /* step4 status recovery */ ++ writel(PCIE_COMBPHY_RECOVER, ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL80)); ++ } ++ ++ if (loop_count == 0) { ++ comp_mode_nr = __arch_get_port_nr(); ++ if (comp_mode_nr) { ++ /*PCIE 0*/ ++ /* phy always work at 5Gbps */ ++ /* step1 addr/data enable: 0x901 */ ++ writel((PCIE_COMBPHY_TEST_ADDR_EN | PCIE_COMBPHY_TEST_DATA_EN), ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL81)); ++ /* step2 write enable: 0x941*/ ++ writel((PCIE_COMBPHY_TEST_ADDR_EN ++ | PCIE_COMBPHY_TEST_DATA_EN ++ | PCIE_COMBPHY_TEST_WR_EN), ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL81)); ++ /* step3 write release: 0x901 */ ++ writel((PCIE_COMBPHY_TEST_ADDR_EN | PCIE_COMBPHY_TEST_DATA_EN), ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL81)); ++ /* step4 status recovery */ ++ writel(PCIE_COMBPHY_RECOVER, ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL81)); ++ } ++ loop_count++; ++ } ++ ++#if CONFIG_PCIE0_SEL ++ /* refclk output from phy for PCIE0 */ ++ val = readl((void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL3)); ++ /* bit0 = 1: pad output enable; ++ * bit1 = 0: pad input disable; ++ * bit6 = 1: refclk from phy */ ++ val |= PCIE0_REGCLK_OUTPUT_EN | PCIE0_REGCLK_SRC_SEL_PHY; ++ val &= ~PCIE0_REGCLK_INPUT_EN; ++ writel(val, (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL3)); ++ mdelay(1); ++#endif ++ ++#if CONFIG_PCIE1_SEL ++ /* refclk output from phy for PCIE1 */ ++ val = readl((void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL3)); ++ /* bit2 = 1: pad output enable; ++ * bit3 = 0: pad input disable; ++ * bit7 = 1: refclk from phy */ ++ val |= PCIE1_REGCLK_OUTPUT_EN | PCIE1_REGCLK_SRC_SEL_PHY; ++ val &= ~PCIE1_REGCLK_INPUT_EN; ++ writel(val, (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL3)); ++ mdelay(1); ++#endif ++ ++ /* ++ * Disable PCIE ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL7); ++ val &= (~(1 << PCIE_APP_LTSSM_ENBALE)); ++ writel(val, dbi_base + PCIE_SYS_CTRL7); ++ ++ if (pcie_controller_0 == info->controller) { ++ ++ dbi_base_pcie0 = dbi_base; ++ /* ++ * Reset ++ */ ++ val = readl(crg_base + PERI_CRG73); ++ val |= (1 << PCIE0_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG73); ++ ++ /* ++ * Retreat from the reset state ++ */ ++ udelay(500); ++ val = readl(crg_base + PERI_CRG73); ++ val &= ~(1 << PCIE0_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG73); ++ mdelay(10); ++ ++ set_pcie0_para(); ++ mdelay(10); ++ } ++ ++ if (pcie_controller_1 == info->controller) { ++ ++ dbi_base_pcie1 = dbi_base; ++ /* ++ * Reset ++ */ ++ val = readl(crg_base + PERI_CRG73); ++ val |= (1 << PCIE1_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG73); ++ ++ /* ++ * Retreat from the reset state ++ */ ++ udelay(500); ++ val = readl(crg_base + PERI_CRG73); ++ val &= ~(1 << PCIE1_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG73); ++ mdelay(10); ++ ++ set_pcie1_para(); ++ mdelay(10); ++ } ++ ++ /* ++ * PCIE RC work mode ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL0); ++ val &= (~(0xf << PCIE_DEVICE_TYPE)); ++ val |= (PCIE_WM_RC << PCIE_DEVICE_TYPE); ++ writel(val, dbi_base + PCIE_SYS_CTRL0); ++ ++ if (pcie_controller_0 == info->controller) { ++ /* ++ * Enable clk ++ */ ++ val = readl(crg_base + PERI_CRG73); ++ val |= ((1 << PCIE0_X2_BUS_CKEN) ++ | (1 << PCIE0_X2_SYS_CKEN) ++ | (1 << PCIE0_X2_PIPE_CKEN) ++ | (1 << PCIE0_X2_AUX_CKEN)); ++ writel(val, crg_base + PERI_CRG73); ++ } ++ ++ if (pcie_controller_1 == info->controller) { ++ ++ /* ++ * Enable clk ++ */ ++ val = readl(crg_base + PERI_CRG73); ++ val |= ((1 << PCIE1_X2_BUS_CKEN) ++ | (1 << PCIE1_X2_SYS_CKEN) ++ | (1 << PCIE1_X2_PIPE_CKEN) ++ | (1 << PCIE1_X2_AUX_CKEN)); ++ writel(val, crg_base + PERI_CRG73); ++ } ++ ++ mdelay(10); ++ ++ /* ++ * Enable controller ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL7); ++ val |= (1 << PCIE_APP_LTSSM_ENBALE); ++ writel(val, dbi_base + PCIE_SYS_CTRL7); ++ udelay(1000); ++ ++ /* ++ * Set PCIE controller class code to be PCI-PCI bridge device ++ */ ++ val = readl(dbi_base + PCI_CLASS_REVISION); ++ val &= ~(0xffffff00); ++ val |= (0x60400 << 8); ++ writel(val, dbi_base + PCI_CLASS_REVISION); ++ udelay(1000); ++ ++ val = readl(dbi_base + PCI_COMMAND); ++ val |= 7; ++ writel(val, dbi_base + PCI_COMMAND); ++} ++ ++static int __arch_pcie_sys_init(struct pcie_info *info) ++{ ++ int nr; ++ ++ for (nr = 0; nr < pcie_controllers_nr; nr++) ++ __arch_pcie_sys_config(&info[nr]); ++ ++ return 0; ++} ++ ++static void __arch_pcie_sys_exit(void) ++{ ++ void *crg_base = (void *)IO_ADDRESS(PERI_CRG_BASE); ++ unsigned int val; ++ ++#ifdef CONFIG_PCIE0_SEL ++ /* ++ * Disable PCIE ++ */ ++ val = readl(dbi_base_pcie0 + PCIE_SYS_CTRL7); ++ val &= (~(1 << PCIE_APP_LTSSM_ENBALE)); ++ writel(val, dbi_base_pcie0 + PCIE_SYS_CTRL7); ++ ++ /* ++ * Reset ++ */ ++ val = readl(crg_base + PERI_CRG73); ++ val |= (1 << PCIE0_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG73); ++ ++ udelay(1000); ++ ++ /* ++ * Disable clk ++ */ ++ val = readl(crg_base + PERI_CRG73); ++ val &= (~(1 << PCIE0_X2_AUX_CKEN)); ++ val &= (~(1 << PCIE0_X2_PIPE_CKEN)); ++ val &= (~(1 << PCIE0_X2_SYS_CKEN)); ++ val &= (~(1 << PCIE0_X2_BUS_CKEN)); ++ writel(val, crg_base + PERI_CRG73); ++ ++ udelay(1000); ++#endif ++ ++#if CONFIG_PCIE1_SEL ++ /* ++ * Disable PCIE ++ */ ++ val = readl(dbi_base_pcie1 + PCIE_SYS_CTRL7); ++ val &= (~(1 << PCIE_APP_LTSSM_ENBALE)); ++ writel(val, dbi_base_pcie1 + PCIE_SYS_CTRL7); ++ ++ /* ++ * Reset ++ */ ++ val = readl(crg_base + PERI_CRG73); ++ val |= (1 << PCIE1_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG73); ++ ++ udelay(1000); ++ ++ /* ++ * Disable clk ++ */ ++ val = readl(crg_base + PERI_CRG73); ++ val &= (~(1 << PCIE1_X2_AUX_CKEN)); ++ val &= (~(1 << PCIE1_X2_PIPE_CKEN)); ++ val &= (~(1 << PCIE1_X2_SYS_CKEN)); ++ val &= (~(1 << PCIE1_X2_BUS_CKEN)); ++ writel(val, crg_base + PERI_CRG73); ++ ++ udelay(1000); ++#endif ++} ++ +diff --git a/drivers/pci/hipcie/pcie_hi3531d.h b/drivers/pci/hipcie/pcie_hi3531d.h +new file mode 100644 +index 0000000..4c95f07 +--- /dev/null ++++ b/drivers/pci/hipcie/pcie_hi3531d.h +@@ -0,0 +1,98 @@ ++#ifndef __HISI_PCIE_H__ ++#define __HISI_PCIE_H__ ++ ++#include ++ ++#define MISC_CTRL_BASE 0x12120000 ++#define PERI_CRG_BASE 0x12040000 ++#define PCIE_SYS_STAT IO_ADDRESS(0x1205008C) ++ ++#define PCIE0_MEM_BASE 0x28000000 ++#define PCIE0_EP_CONF_BASE 0x20000000 ++#define PCIE0_DBI_BASE 0x122F0000 ++#define PCIE_DBI_BASE PCIE0_MEM_BASE ++ ++#define PCIE1_MEM_BASE 0x38000000 ++#define PCIE1_EP_CONF_BASE 0x30000000 ++#define PCIE1_DBI_BASE 0x122F8000 ++ ++#define PERI_CRG_72 0x120 ++#define COMPHY_CLK_REST_VAL ((0x2 << 14) | (0x2 << 12) \ ++ | (0x1 << 9) | (0x1 << 8) \ ++ | (0x2 << 6) | (0x2 << 4) | 0x3) ++ ++#define PERI_CRG73 0x124 ++ ++#define PCIE0_X2_SRST_REQ 6 ++#define PCIE0_X2_AUX_CKEN 3 ++#define PCIE0_X2_PIPE_CKEN 2 ++#define PCIE0_X2_SYS_CKEN 1 ++#define PCIE0_X2_BUS_CKEN 0 ++ ++#define PCIE_PAD_OE_MASK (0x7 << 8) ++ ++#define PCIE1_X2_SRST_REQ 14 ++#define PCIE1_X2_AUX_CKEN 11 ++#define PCIE1_X2_PIPE_CKEN 10 ++#define PCIE1_X2_SYS_CKEN 9 ++#define PCIE1_X2_BUS_CKEN 8 ++ ++#define PCIE_SYS_CTRL0 0x1000 ++#define PCIE_DEVICE_TYPE 28 ++#define PCIE_WM_EP 0x0 ++#define PCIE_WM_LEGACY 0x1 ++#define PCIE_WM_RC 0x4 ++ ++#define PCIE_SYS_CTRL7 0x101C ++#define PCIE_APP_LTSSM_ENBALE 11 ++#define PCIE_ACCESS_ENABLE 13 ++ ++#define PCIE_SYS_STATE0 0x1100 ++#define PCIE_XMLH_LINK_UP 15 ++#define PCIE_RDLH_LINK_UP 5 ++ ++#define PCIE0_IRQ_INTA 94 ++#define PCIE0_IRQ_INTB 95 ++#define PCIE0_IRQ_INTC 96 ++#define PCIE0_IRQ_INTD 97 ++#define PCIE0_IRQ_EDMA 98 ++#define PCIE0_IRQ_MSI 99 ++#define PCIE0_IRQ_LINK_DOWN 100 ++ ++#define PCIE1_IRQ_INTA 101 ++#define PCIE1_IRQ_INTB 102 ++#define PCIE1_IRQ_INTC 103 ++#define PCIE1_IRQ_INTD 104 ++#define PCIE1_IRQ_EDMA 105 ++#define PCIE1_IRQ_MSI 106 ++#define PCIE1_IRQ_LINK_DOWN 107 ++ ++#define PCIE_INTA_PIN 1 ++#define PCIE_INTB_PIN 2 ++#define PCIE_INTC_PIN 3 ++#define PCIE_INTD_PIN 4 ++ ++#define MISC_CTRL3 0xC ++#define MISC_CTRL81 0x144 ++#define MISC_CTRL80 0x140 ++ ++#define PCIE_COMBPHY_TEST_ADDR_EN 0x1 ++#define PCIE_COMBPHY_TEST_DATA_EN (0x9 << 8) ++ ++#define PCIE_COMBPHY_TEST_WR_EN (0x1 << 6) ++#define PCIE_COMBPHY_RECOVER 0x0 ++ ++#define PCIE0_REGCLK_OUTPUT_EN (1 << 0) ++#define PCIE0_REGCLK_INPUT_EN (1 << 1) ++#define PCIE0_REGCLK_SRC_SEL_PHY (1 << 6) ++ ++#define PCIE1_REGCLK_OUTPUT_EN (1 << 2) ++#define PCIE1_REGCLK_INPUT_EN (1 << 3) ++#define PCIE1_REGCLK_SRC_SEL_PHY (1 << 7) ++ ++#define REG_GPIO_15_BASE 0x12240000 ++#define GPIO_15_DATA 0x4 ++#define GPIO_15_DIR 0x400 ++#define GPIO_15_DIR_SET_OUTPUT 1 ++ ++#endif +diff --git a/drivers/pci/hipcie/pcie_hi3559.c b/drivers/pci/hipcie/pcie_hi3559.c +new file mode 100644 +index 0000000..89d4fbe +--- /dev/null ++++ b/drivers/pci/hipcie/pcie_hi3559.c +@@ -0,0 +1,314 @@ ++#include ++#include "pcie_hi3559.h" ++ ++static void *dbi_base; ++static int __arch_pcie_info_setup(struct pcie_info *info, int *controllers_nr); ++static int __arch_pcie_sys_init(struct pcie_info *info); ++static void __arch_pcie_info_release(struct pcie_info *info); ++ ++struct pcie_iatu iatu_table[] = { ++ { ++ .viewport = 0, ++ .region_ctrl_1 = 0x00000004, ++ .region_ctrl_2 = 0x90000000, ++ .lbar = PCIE_EP_CONF_BASE + (1<<20), ++ .ubar = 0x0, ++ .lar = PCIE_EP_CONF_BASE + (2<<20) - 1, ++ .ltar = 0x01000000, ++ .utar = 0x00000000, ++ }, ++ { ++ .viewport = 1, ++ .region_ctrl_1 = 0x00000005, ++ .region_ctrl_2 = 0x90000000, ++ .lbar = PCIE_EP_CONF_BASE + (2<<20), ++ .ubar = 0x0, ++ .lar = PCIE_EP_CONF_BASE + (__128MB__ - 1), ++ .ltar = 0x02000000, ++ .utar = 0x00000000, ++ }, ++}; ++ ++static void __arch_pcie_preinit(void) ++{ ++ ++} ++ ++static struct resource pcie_mem; ++static struct resource pcie_io; ++static void __arch_get_pcie_res(int controller, ++ struct resource **pmem, ++ struct resource **pio) ++{ ++ *pmem = &pcie_mem; ++ (*pmem)->start = PCIE_MEM_BASE; ++ (*pmem)->end = PCIE_MEM_BASE + __128MB__ - 0x100000 - 1; ++ (*pmem)->flags = IORESOURCE_MEM; ++ (*pmem)->name = "memory"; ++ ++ *pio = &pcie_io; ++ (*pio)->start = PCIE_MEM_BASE + __128MB__ - 0x100000; ++ (*pio)->end = PCIE_MEM_BASE + __128MB__ - 1; ++ (*pio)->flags = IORESOURCE_IO; ++ (*pio)->name = "io"; ++} ++ ++static int __arch_get_int_irq(struct pcie_info *info, u8 pin) ++{ ++ switch (pin) { ++ case PCIE_INTA_PIN: ++ return PCIE_IRQ_INTA; ++ case PCIE_INTB_PIN: ++ return PCIE_IRQ_INTB; ++ case PCIE_INTC_PIN: ++ return PCIE_IRQ_INTC; ++ case PCIE_INTD_PIN: ++ return PCIE_IRQ_INTD; ++ default: ++ pcie_error("Unknown pin for mapping irq!"); ++ return -1; ++ } ++} ++ ++static void __arch_config_iatu_tbl(struct pcie_info *info, ++ struct pci_sys_data *sys) ++{ ++ int i; ++ void __iomem *config_base = (void __iomem *)info->conf_base_addr; ++ struct pcie_iatu *ptable = iatu_table; ++ int table_size = ARRAY_SIZE(iatu_table); ++ ++ for (i = 0; i < table_size; i++) { ++ writel((ptable + i)->viewport, config_base + 0x900); ++ writel((ptable + i)->lbar, config_base + 0x90c); ++ writel((ptable + i)->ubar, config_base + 0x910); ++ writel((ptable + i)->lar, config_base + 0x914); ++ writel((ptable + i)->ltar, config_base + 0x918); ++ writel((ptable + i)->utar, config_base + 0x91c); ++ writel((ptable + i)->region_ctrl_1, config_base + 0x904); ++ writel((ptable + i)->region_ctrl_2, config_base + 0x908); ++ } ++ ++} ++ ++static inline int __arch_check_pcie_link(struct pcie_info *info) ++{ ++ int val; ++ ++ val = readl(dbi_base + PCIE_SYS_STATE0); ++ return ((val & (1 << PCIE_XMLH_LINK_UP)) ++ && (val & (1 << PCIE_RDLH_LINK_UP))) ? 1 : 0; ++} ++ ++/* ++ * ret: ++ */ ++static int __arch_pcie_info_setup(struct pcie_info *info, int *controllers_nr) ++{ ++ unsigned int mem_size = CONFIG_PCIE0_DEVICES_MEM_SIZE; ++ unsigned int cfg_size = CONFIG_PCIE0_DEVICES_CONFIG_SIZE; ++ ++ if ((mem_size > __128MB__) || (cfg_size > __128MB__)) { ++ pcie_error( ++ "Invalid parameter: pcie mem size[0x%x], pcie cfg size[0x%x]!", ++ mem_size, cfg_size); ++ return -EINVAL; ++ } ++ ++ info->controller = 0; ++ ++ /* RC configuration space */ ++ info->conf_base_addr = (unsigned int)ioremap_nocache(PCIE_DBI_BASE, ++ __8KB__); ++ if (!info->conf_base_addr) { ++ pcie_error("Address mapping for RC dbi failed!"); ++ return -EIO; ++ } ++ ++ /* Configuration space for all EPs */ ++ info->base_addr = (unsigned int)ioremap_nocache(PCIE_EP_CONF_BASE, ++ cfg_size); ++ if (!info->base_addr) { ++ iounmap((void *)info->conf_base_addr); ++ pcie_error("Address mapping for EPs cfg failed!"); ++ return -EIO; ++ } ++ ++ *controllers_nr = 1; ++ ++ return 0; ++ ++} ++ ++static void __arch_pcie_info_release(struct pcie_info *info) ++{ ++ if (info->base_addr) ++ iounmap((void *)info->base_addr); ++ ++ if (info->conf_base_addr) ++ iounmap((void *)info->conf_base_addr); ++} ++ ++void set_pcie_para(void *crg_base) ++{ ++ unsigned int val; ++ ++ void * misc_base = (void *)IO_ADDRESS(MISC_CTRL_BASE); ++ ++ val = readl(crg_base + PERI_CRG43); ++ val = val & (~(1 << 0)); ++ val = val | (1 << 1); ++ writel(val,crg_base + PERI_CRG43); ++ ++ writel(0x1506, misc_base + MISC_CTRL33); ++ writel(0x11506, misc_base + MISC_CTRL33); ++ writel(0x1506, misc_base + MISC_CTRL33); ++ writel(0x0, misc_base + MISC_CTRL33); ++ ++ writel(0x108, misc_base + MISC_CTRL33); ++ writel(0x10108, misc_base + MISC_CTRL33); ++ writel(0x108, misc_base + MISC_CTRL33); ++ writel(0x0, misc_base + MISC_CTRL33); ++} ++ ++static int __arch_pcie_sys_init(struct pcie_info *info) ++{ ++ unsigned int val; ++ void *crg_base = (void *)IO_ADDRESS(PERI_CRG_BASE); ++ ++ dbi_base = (void *)info->conf_base_addr; ++ ++ /*open pcie pad oe*/ ++ val = readl(crg_base + PERI_CRG44); ++ val &= ~(PCIE_PAD_OE_MASK); ++ writel(val, crg_base + PERI_CRG44); ++ ++ /* refclk output from phy */ ++ writel(PCIE_CLKREQ_FILTER_BYPASS, ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL34)); ++ mdelay(1); ++ ++ /* ++ * Disable PCIE ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL7); ++ val &= (~(1 << PCIE_APP_LTSSM_ENBALE)); ++ val |= (1 << PCIE_ACCESS_ENABLE); ++ writel(val, dbi_base + PCIE_SYS_CTRL7); ++ ++ /* ++ * Reset ++ */ ++ val = readl(crg_base + PERI_CRG44); ++ val |= (1 << PCIE_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG44); ++ ++ /* ++ * Retreat from the reset state ++ */ ++ udelay(500); ++ val = readl(crg_base + PERI_CRG44); ++ val &= ~(1 << PCIE_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG44); ++ mdelay(10); ++ ++ ++ /* ++ * PCIE RC work mode ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL0); ++ val &= (~(0xf << PCIE_DEVICE_TYPE)); ++ val |= (PCIE_WM_RC << PCIE_DEVICE_TYPE); ++ writel(val, dbi_base + PCIE_SYS_CTRL0); ++ ++ /* ++ * Enable clk ++ */ ++ val = readl(crg_base + PERI_CRG44); ++ val |= ((1 << PCIE_X2_BUS_CKEN) ++ | (1 << PCIE_X2_SYS_CKEN) ++ | (1 << PCIE_X2_PIPE_CKEN) ++ | (1 << PCIE_X2_AUX_CKEN)); ++ writel(val, crg_base + PERI_CRG44); ++ ++ mdelay(10); ++ ++ set_pcie_para(crg_base); ++ mdelay(10); ++ ++ /* ++ * Set PCIE controller class code to be PCI-PCI bridge device ++ */ ++ val = readl(dbi_base + PCI_CLASS_REVISION); ++ val &= ~(0xffffff00); ++ val |= (0x60400 << 8); ++ writel(val, dbi_base + PCI_CLASS_REVISION); ++ udelay(1000); ++ ++ /* phy always work at 5Gbps */ ++ writel(COM_PHY_TEST_VAL1, ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL33)); ++ writel(COM_PHY_TEST_VAL2, ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL33)); ++ writel(COM_PHY_TEST_VAL1, ++ (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL33)); ++ writel(0x0, (void *)IO_ADDRESS(MISC_CTRL_BASE + MISC_CTRL33)); ++ ++ /* default deemphasis to -3.5 dB */ ++ writel(DEEMPHASIS_VAL, (void *)IO_ADDRESS(PCIE_DBI_BASE + DEEMPHASIS_REG)); ++ ++ /* ++ * Enable controller ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL7); ++ val |= (1 << PCIE_APP_LTSSM_ENBALE); ++ writel(val, dbi_base + PCIE_SYS_CTRL7); ++ udelay(1000); ++ ++ val = readl(dbi_base + PCI_COMMAND); ++ val |= 7; ++ writel(val, dbi_base + PCI_COMMAND); ++ ++ /* set pcie to gen 1*/ ++#if 0 ++ writel(0x1, dbi_base + 0x8BC); ++ val = readl(dbi_base + 0x7C); ++ val = ((val >> 4) << 4) | 0x1; ++ writel(val, dbi_base + 0x7C); ++#endif ++ return 0; ++} ++ ++static void __arch_pcie_sys_exit(void) ++{ ++ unsigned int val; ++ void *crg_base = (void *)IO_ADDRESS(PERI_CRG_BASE); ++ ++ /* ++ * Disable PCIE ++ */ ++ val = readl(dbi_base + PCIE_SYS_CTRL7); ++ val &= (~(1 << PCIE_APP_LTSSM_ENBALE)); ++ writel(val, dbi_base + PCIE_SYS_CTRL7); ++ ++ /* ++ * Reset ++ */ ++ val = readl(crg_base + PERI_CRG44); ++ val |= (1 << PCIE_X2_SRST_REQ); ++ writel(val, crg_base + PERI_CRG44); ++ ++ udelay(1000); ++ ++ /* ++ * Disable clk ++ */ ++ val = readl(crg_base + PERI_CRG44); ++ val &= (~(1 << PCIE_X2_AUX_CKEN)); ++ val &= (~(1 << PCIE_X2_PIPE_CKEN)); ++ val &= (~(1 << PCIE_X2_SYS_CKEN)); ++ val &= (~(1 << PCIE_X2_BUS_CKEN)); ++ writel(val, crg_base + PERI_CRG44); ++ ++ udelay(1000); ++} +diff --git a/drivers/pci/hipcie/pcie_hi3559.h b/drivers/pci/hipcie/pcie_hi3559.h +new file mode 100644 +index 0000000..e185999 +--- /dev/null ++++ b/drivers/pci/hipcie/pcie_hi3559.h +@@ -0,0 +1,55 @@ ++#ifndef __HISI_PCIE_H__ ++#define __HISI_PCIE_H__ ++ ++#define MISC_CTRL_BASE 0x12030000 ++#define PCIE_MEM_BASE 0x28000000 ++#define PCIE_EP_CONF_BASE 0x20000000 ++#define PCIE_DBI_BASE 0x12160000 ++#define PERI_CRG_BASE 0x12010000 ++ ++#define PERI_CRG43 0xAC ++#define PERI_CRG44 0xB0 ++#define PCIE_X2_SRST_REQ 2 ++ ++#define PCIE_X2_AUX_CKEN 7 ++#define PCIE_X2_PIPE_CKEN 6 ++#define PCIE_X2_SYS_CKEN 5 ++#define PCIE_X2_BUS_CKEN 4 ++#define PCIE_PAD_OE_MASK (0x7 << 8) ++ ++#define PCIE_SYS_CTRL0 0x1000 ++#define PCIE_DEVICE_TYPE 28 ++#define PCIE_WM_EP 0x0 ++#define PCIE_WM_LEGACY 0x1 ++#define PCIE_WM_RC 0x4 ++ ++#define PCIE_SYS_CTRL7 0x101C ++#define PCIE_APP_LTSSM_ENBALE 11 ++#define PCIE_ACCESS_ENABLE 13 ++ ++#define PCIE_SYS_STATE0 0x1100 ++#define PCIE_XMLH_LINK_UP 15 ++#define PCIE_RDLH_LINK_UP 5 ++ ++#define PCIE_IRQ_INTA 89 ++#define PCIE_IRQ_INTB 90 ++#define PCIE_IRQ_INTC 91 ++#define PCIE_IRQ_INTD 92 ++#define PCIE_IRQ_EDMA 93 ++#define PCIE_IRQ_MSI 94 ++#define PCIE_IRQ_LINK_DOWN 95 ++ ++#define PCIE_INTA_PIN 1 ++#define PCIE_INTB_PIN 2 ++#define PCIE_INTC_PIN 3 ++#define PCIE_INTD_PIN 4 ++ ++#define MISC_CTRL33 0x84 ++#define MISC_CTRL34 0x88 ++#define DEEMPHASIS_REG 0xa0 ++#define PCIE_CLKREQ_FILTER_BYPASS 0x600 ++#define DEEMPHASIS_VAL 0x42 ++#define COM_PHY_TEST_VAL1 ((0x1 << 3) | (0x1 << 8)) ++#define COM_PHY_TEST_VAL2 ((0x1 << 16) | (0x1 << 3) | (0x1 << 8)) ++ ++#endif +diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig +index 2a436e6..9564f35 100644 +--- a/drivers/phy/Kconfig ++++ b/drivers/phy/Kconfig +@@ -133,6 +133,30 @@ config PHY_EXYNOS5250_SATA + SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host + port to accept one SATA device. + ++config PHY_HISI_INNO_USB2 ++ tristate "Hisilicon Inno USB2 PHY support" ++ depends on OF && HAS_IOMEM && (USB_EHCI_HCD || HIUSB_DEVICE2_0) ++ select GENERIC_PHY ++ select MFD_SYSCON ++ default n ++ help ++ Support for INNO PHY on Hisilicon Socs. This Phy supports ++ USB 1.5Mb/s, USB 12Mb/s, USB 480Mb/s speeds. It suppots one ++ USB host port to accept one USB device. Support init the phy ++ and adjust phy Eye Diagram. ++ ++config PHY_HI35x1D_INNO_USB2 ++ tristate "Hisilicon 3531D&3521D Inno USB2 PHY support" ++ depends on (ARCH_HI3531D|| ARCH_HI3521D) && OF && HAS_IOMEM && (!PHY_HISI_INNO_USB2) ++ select GENERIC_PHY ++ select MFD_SYSCON ++ default y ++ help ++ Support for INNO PHY on Hisilicon Socs. This Phy supports ++ USB 1.5Mb/s, USB 12Mb/s, USB 480Mb/s speeds. It suppots one ++ USB host port to accept one USB device. Support init the phy ++ and adjust phy Eye Diagram. ++ + config PHY_HIX5HD2_SATA + tristate "HIX5HD2 SATA PHY Driver" + depends on ARCH_HIX5HD2 && OF && HAS_IOMEM +@@ -141,6 +165,28 @@ config PHY_HIX5HD2_SATA + help + Support for SATA PHY on Hisilicon hix5hd2 Soc. + ++config PHY_HISI_USB3 ++ tristate "HISI USB3 PHY Driver" ++ depends on (ARCH_HI3519 || ARCH_HI3519V101 || ARCH_HI3559 || ARCH_HI3556 || ARCH_HI3516AV200) && OF && HAS_IOMEM && USB_XHCI_HCD ++ select GENERIC_PHY ++ select MFD_SYSCON ++ help ++ Support for USB PHY on Hisilicon Soc. ++ Enable this to support the hisi USB 3.0 PHY driver for hisilicon ++ SoCs. This driver provides the interface for USB 3.0 PHY. Support ++ init the phy and adjust phy Eye Diagram. ++ ++config PHY_HI3531D_USB3 ++ tristate "HI3531D USB3 PHY Driver" ++ depends on ARCH_HI3531D && OF && HAS_IOMEM && USB_XHCI_HCD ++ select GENERIC_PHY ++ select MFD_SYSCON ++ help ++ Support for USB PHY on Hisilicon Soc. ++ Enable this to support the hisi USB 3.0 PHY driver for hisilicon ++ SoCs. This driver provides the interface for USB 3.0 PHY. Support ++ init the phy and adjust phy Eye Diagram. ++ + config PHY_SUN4I_USB + tristate "Allwinner sunxi SoC USB PHY driver" + depends on ARCH_SUNXI && HAS_IOMEM && OF +@@ -256,4 +302,31 @@ config PHY_STIH41X_USB + Enable this to support the USB transceiver that is part of + STMicroelectronics STiH41x SoC series. + ++config HI_NANO_PHY_SATA ++ tristate "hisilicon sata nano phy support" ++ depends on ((ARCH_HI3531D || ARCH_HI3536C || ARCH_HI3521D) && OF && HAS_IOMEM) ++ default y if (ARCH_HI3531D || ARCH_HI3536C ||ARCH_HI3521D) ++ select GENERIC_PHY ++ help ++ Enable this to support the sata nano phy that is part of ++ sata driver for hisilicon. ++ ++config HI_SATA_PORTS ++ int "hi sata port number" ++ depends on HI_NANO_PHY_SATA ++ range 1 4 if ARCH_HI3531D ++ range 1 2 if (ARCH_HI3536C || ARCH_HI3521D) ++ default "4" if ARCH_HI3531D ++ default "2" if (ARCH_HI3536C || ARCH_HI3521D) ++ help ++ hisilicon sata port number. ++ ++config HI_SATA_MODE ++ int "hi sata interworking speed mode(1.5G:0/3G:1/6G:2)" ++ depends on HI_NANO_PHY_SATA ++ range 0 2 if (ARCH_HI3536C || ARCH_HI3521D || ARCH_HI3531D) ++ default "1" if (ARCH_HI3536C || ARCH_HI3521D || ARCH_HI3531D) ++ help ++ hisilicon interworking speed mode. ++ + endmenu +diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile +index c4590fc..857f284 100644 +--- a/drivers/phy/Makefile ++++ b/drivers/phy/Makefile +@@ -16,6 +16,15 @@ obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o + obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o + obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o + obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o ++obj-$(CONFIG_HI_NANO_PHY_SATA) += phy-hisi-nano-phy-sata.o ++ifdef CONFIG_ARCH_HI3516CV300 ++obj-$(CONFIG_PHY_HISI_INNO_USB2) += phy-hisi-inno-usb2.o ++else ++obj-$(CONFIG_PHY_HISI_INNO_USB2) += phy-hisi-usb.o ++endif ++obj-$(CONFIG_PHY_HI35x1D_INNO_USB2) += phy-hi35x1d-usb.o ++obj-$(CONFIG_PHY_HI3531D_USB3) += phy-hi3531d-usb3.o ++obj-$(CONFIG_PHY_HISI_USB3) += phy-hisi-usb3.o + obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o + obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o + phy-exynos-usb2-y += phy-samsung-usb2.o +diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c +index 2733112..bfbbf43 100644 +--- a/drivers/phy/phy-core.c ++++ b/drivers/phy/phy-core.c +@@ -586,6 +586,38 @@ struct phy *devm_of_phy_get(struct device *dev, struct device_node *np, + EXPORT_SYMBOL_GPL(devm_of_phy_get); + + /** ++ * devm_of_phy_get_by_index() - lookup and obtain a reference to a phy by index. ++ * @dev: device that requests this phy ++ * @np: node containing the phy ++ * @index: index of the phy ++ * ++ * Gets the phy using _of_phy_get(), and associates a device with it using ++ * devres. On driver detach, release function is invoked on the devres data, ++ * then, devres data is freed. ++ * ++ */ ++struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np, ++ int index) ++{ ++ struct phy **ptr, *phy; ++ ++ ptr = devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL); ++ if (!ptr) ++ return ERR_PTR(-ENOMEM); ++ ++ phy = _of_phy_get(np, index); ++ if (!IS_ERR(phy)) { ++ *ptr = phy; ++ devres_add(dev, ptr); ++ } else { ++ devres_free(ptr); ++ } ++ ++ return phy; ++} ++EXPORT_SYMBOL_GPL(devm_of_phy_get_by_index); ++ ++/** + * phy_create() - create a new phy + * @dev: device that is creating the new phy + * @node: device node of the phy +diff --git a/drivers/phy/phy-hi3521d-sata.c b/drivers/phy/phy-hi3521d-sata.c +new file mode 100644 +index 0000000..8666605 +--- /dev/null ++++ b/drivers/phy/phy-hi3521d-sata.c +@@ -0,0 +1,415 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++unsigned int sata_port_map; ++ ++enum { ++ HI_SATA_PERI_CTRL = IO_ADDRESS(0x12040000), ++ HI_SATA_PERI_CRG72 = (HI_SATA_PERI_CTRL + 0x120), ++ HI_SATA_PERI_CRG74 = (HI_SATA_PERI_CTRL + 0x128), ++ ++ HI_SATA_PHY0_REFCLK_SEL_MASK = (0x3 << 4), ++ HI_SATA_PHY0_REFCLK_SEL = (0x1 << 4), ++ HI_SATA_PHY1_REFCLK_SEL_MASK = (0x3 << 6), ++ HI_SATA_PHY1_REFCLK_SEL = (0x1 << 6), ++ ++ HI_SATA_PHY0_CLK_EN = (1 << 0), ++ HI_SATA_PHY1_CLK_EN = (1 << 1), ++ ++ HI_SATA_PHY0_RST = (1 << 2), ++ HI_SATA_PHY1_RST = (1 << 3), ++ ++ HI_SATA_PHY_BACK_MASK_ALL = 0xf0, ++ HI_SATA_PHY1_RST_BACK_MASK = (1 << 5), ++ HI_SATA_PHY0_RST_BACK_MASK = (1 << 4), ++ ++ HI_SATA_BUS_CKEN = (1 << 0), ++ HI_SATA_BUS_SRST_REQ = (1 << 8), ++ HI_SATA_CKO_ALIVE_CKEN = (1 << 2), ++ HI_SATA_CKO_ALIVE_SRST_REQ = (1 << 9), ++ HI_SATA_RX0_CKEN = (1 << 1), ++ HI_SATA_TX0_CKEN = (1 << 3), ++ HI_SATA_RX0_SRST_REQ = (1 << 10), ++ HI_SATA0_SRST_REQ = (1 << 11), ++ HI_SATA_RX1_CKEN = (1 << 12), ++ HI_SATA_TX1_CKEN = (1 << 13), ++ HI_SATA_RX1_SRST_REQ = (1 << 14), ++ HI_SATA1_SRST_REQ = (1 << 15), ++ ++ HI_SATA_SYS_CTRL = IO_ADDRESS(0x1205008C), ++}; ++ ++static void hi_sata_poweron(void) ++{ ++ /* msleep(20); */ ++} ++ ++static void hi_sata_poweroff(void) ++{ ++} ++ ++void hisi_sata_reset_rxtx_assert(unsigned int port_no) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG74); ++ ++ if (port_no == 1) { ++ tmp_val |= HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ; ++ } else if (port_no == 0) { ++ tmp_val |= HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ; ++ } ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG74); ++} ++EXPORT_SYMBOL(hisi_sata_reset_rxtx_assert); ++ ++void hisi_sata_reset_rxtx_deassert(unsigned int port_no) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG74); ++ ++ if (port_no == 1) { ++ tmp_val &= ~(HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ); ++ } else if (port_no == 0) { ++ tmp_val &= ~(HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ); ++ } ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG74); ++} ++EXPORT_SYMBOL(hisi_sata_reset_rxtx_deassert); ++ ++static void hi_sata_reset(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG74); ++ ++ tmp_val |= HI_SATA_BUS_SRST_REQ | HI_SATA_CKO_ALIVE_SRST_REQ; ++ if (n_ports == 2) { ++ tmp_val |= HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ ++ | HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ; ++ } else if (n_ports == 1) { ++ tmp_val |= HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ; ++ } ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG74); ++} ++ ++static void hi_sata_unreset(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG74); ++ ++ tmp_val &= ~(HI_SATA_BUS_SRST_REQ | HI_SATA_CKO_ALIVE_SRST_REQ); ++ if (n_ports == 2) { ++ tmp_val &= ~(HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ ++ | HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ); ++ ++ } else if (n_ports == 1) { ++ tmp_val &= ~(HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ); ++ } ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG74); ++} ++ ++static void hi_sata_phy_reset(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG72); ++ ++ if (n_ports == 2) { ++ tmp_val |= HI_SATA_PHY0_RST ++ | HI_SATA_PHY1_RST; ++ ++ } else if (n_ports == 1) ++ tmp_val |= HI_SATA_PHY0_RST; ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG72); ++} ++ ++static void hi_sata_phy_unreset(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG72); ++ ++ if (n_ports == 2) { ++ tmp_val &= ~(HI_SATA_PHY0_RST ++ | HI_SATA_PHY1_RST); ++ } else if (n_ports == 1) ++ tmp_val &= ~HI_SATA_PHY0_RST; ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG72); ++} ++ ++static void hi_sata_clk_enable(void) ++{ ++ unsigned int tmp_val, tmp_reg; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG72); ++ tmp_reg = readl((void *)HI_SATA_PERI_CRG74); ++ ++ if (n_ports == 2) { ++ tmp_val |= HI_SATA_PHY0_CLK_EN; ++ tmp_val |= HI_SATA_PHY1_CLK_EN; ++ ++ tmp_reg |= HI_SATA_RX0_CKEN ++ | HI_SATA_TX0_CKEN ++ | HI_SATA_RX1_CKEN ++ | HI_SATA_TX1_CKEN; ++ ++ } else if (n_ports == 1) { ++ tmp_val |= HI_SATA_PHY0_CLK_EN; ++ ++ tmp_reg |= HI_SATA_RX0_CKEN ++ | HI_SATA_TX0_CKEN; ++ ++ } ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG72); ++ writel(tmp_reg, (void *)HI_SATA_PERI_CRG74); ++ ++} ++ ++static void hi_sata_clk_disable(void) ++{ ++} ++ ++static void hi_sata_clk_reset(void) ++{ ++} ++ ++static void hi_sata_phy_clk_sel(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG72); ++ ++ if (n_ports == 2) { ++ tmp_val &= ~HI_SATA_PHY0_REFCLK_SEL_MASK; ++ tmp_val &= ~HI_SATA_PHY1_REFCLK_SEL_MASK; ++ ++ tmp_val |= HI_SATA_PHY0_REFCLK_SEL; ++ tmp_val |= HI_SATA_PHY1_REFCLK_SEL; ++ ++ } else if (n_ports == 1) { ++ tmp_val &= ~HI_SATA_PHY1_REFCLK_SEL_MASK; ++ tmp_val |= HI_SATA_PHY1_REFCLK_SEL; ++ } ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG72); ++} ++ ++void hisata_v200_set_fifo(void *mmio, int n_ports) ++{ ++ int i; ++ ++ for (i = 0; i < n_ports; i++) ++ writel(HI_SATA_FIFOTH_VALUE, (mmio + 0x100 + i*0x80 ++ + HI_SATA_PORT_FIFOTH)); ++} ++ ++void hisata_phy_init(void *mmio, int phy_mode, int n_ports) ++{ ++ unsigned int tmp, phy_config = HI_SATA_PHY_3G; ++ unsigned int phy_sg = HI_SATA_PHY_SG_3G; ++ int i, port_no; ++ ++ if ((n_ports < 1) || (n_ports > 2)) ++ pr_err("ERROR: PORT num you set is WRONG!!!\n"); ++ ++ sata_port_map = (1 << n_ports) - 1; ++ hisata_v200_set_fifo(mmio, n_ports); ++ ++ tmp = readl(mmio + HI_SATA_PHY_CTL1); ++ tmp |= HI_SATA_BIGENDINE; ++ writel(tmp, (mmio + HI_SATA_PHY_CTL1)); ++ tmp = readl(mmio + HI_SATA_PHY_CTL2); ++ tmp |= HI_SATA_BIGENDINE; ++ writel(tmp, (mmio + HI_SATA_PHY_CTL2)); ++ ++ tmp = readl(mmio + HI_SATA_PHY_RST_BACK_MASK); ++ tmp |= HI_SATA_PHY_BACK_MASK_ALL; ++ if (n_ports == 1) ++ tmp &= ~HI_SATA_PHY1_RST_BACK_MASK; ++ else if (n_ports == 2) ++ /* Not need mask any port */ ++ ++ writel(tmp, (mmio + HI_SATA_PHY_RST_BACK_MASK)); ++ ++ if (phy_mode == HI_SATA_PHY_MODE_1_5G) { ++ phy_config = HI_SATA_PHY_1_5G; ++ phy_sg = HI_SATA_PHY_SG_1_5G; ++ } ++ ++ if (phy_mode == HI_SATA_PHY_MODE_3G) { ++ phy_config = HI_SATA_PHY_3G; ++ phy_sg = HI_SATA_PHY_SG_3G; ++ } ++ ++ if (phy_mode == HI_SATA_PHY_MODE_6G) { ++ phy_config = HI_SATA_PHY_6G; ++ phy_sg = HI_SATA_PHY_SG_6G; ++ } ++ ++ for (i = 0; i < n_ports; i++) { ++ port_no = i; ++ writel(phy_config, (mmio + 0x100 + port_no*0x80 ++ + HI_SATA_PORT_PHYCTL)); ++ ++ writel(phy_sg, (mmio + 0x100 + port_no*0x80 ++ + HI_SATA_PORT_PHYCTL1)); ++ } ++} ++ ++static void hi_sata_phy_reg_config(void) ++{ ++ unsigned int i, port_no; ++ ++ for (i = 0; i < n_ports; i++) { ++ port_no = i; ++ ++ if (port_no == 0) { ++ /* PLL always 6G & CDR <= RATE */ ++ writel(0xd01, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0xd41, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0xd01, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY0); ++ ++ /* disable SSC */ ++ writel(0x803, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x843, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x803, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY0); ++ ++ /* EQ set b010000 */ ++ writel(0x009, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x049, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x009, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY0); ++ ++ writel(0x508, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x548, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x508, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY0); ++ } else if (port_no == 1) { ++ /* PLL always 6G & CDR <= RATE */ ++ writel(0xd01, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0xd41, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0xd01, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY1); ++ ++ /* disable SSC */ ++ writel(0x803, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x843, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x803, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY1); ++ ++ /* EQ set b010000 */ ++ writel(0x009, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x049, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x009, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY1); ++ ++ writel(0x508, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x548, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x508, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY1); ++ } ++ } ++} ++ ++void hi_sata_eq_recovery(unsigned int port_no) ++{ ++ if (port_no == 0) { ++ /* EQ recovery */ ++ writel(0xf09, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0xf49, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0xf09, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY0); ++ ++ writel(0x308, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x348, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x308, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY0); ++ } else if (port_no == 1) { ++ /* EQ recovery */ ++ writel(0xf09, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0xf49, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0xf09, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY1); ++ ++ writel(0x308, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x348, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x308, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY1); ++ } ++} ++EXPORT_SYMBOL(hi_sata_eq_recovery); ++ ++void hi_sata_set_eq(unsigned int port_no) ++{ ++ if (port_no == 0) { ++ /* EQ set b010000 */ ++ writel(0x009, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x049, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x009, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY0); ++ ++ writel(0x508, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x548, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x508, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY0); ++ } else if (port_no == 1) { ++ /* EQ set b010000 */ ++ writel(0x009, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x049, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x009, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY1); ++ ++ writel(0x508, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x548, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x508, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY1); ++ } ++} ++EXPORT_SYMBOL(hi_sata_set_eq); ++ +diff --git a/drivers/phy/phy-hi3531d-sata.c b/drivers/phy/phy-hi3531d-sata.c +new file mode 100644 +index 0000000..8dc6dd4 +--- /dev/null ++++ b/drivers/phy/phy-hi3531d-sata.c +@@ -0,0 +1,814 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static unsigned int mplx_port0; ++static unsigned int sata_port_nr; ++ ++enum { ++ HI_SATA_PERI_CTRL = IO_ADDRESS(0x12040000), ++ HI_SATA_PERI_CRG72 = (HI_SATA_PERI_CTRL + 0x120), ++ HI_SATA_PERI_CRG74 = (HI_SATA_PERI_CTRL + 0x128), ++ ++ HI_SATA_PHY0_REFCLK_SEL_MASK = (0x3 << 4), ++ HI_SATA_PHY0_REFCLK_SEL = (0x1 << 4), ++ HI_SATA_PHY1_REFCLK_SEL_MASK = (0x3 << 6), ++ HI_SATA_PHY1_REFCLK_SEL = (0x1 << 6), ++ HI_SATA_PHY2_REFCLK_SEL_MASK = (0x3 << 12), ++ HI_SATA_PHY2_REFCLK_SEL = (0x1 << 12), ++ HI_SATA_PHY3_REFCLK_SEL_MASK = (0x3 << 14), ++ HI_SATA_PHY3_REFCLK_SEL = (0x1 << 14), ++ ++ HI_SATA_PHY0_CLK_EN = (1 << 0), ++ HI_SATA_PHY1_CLK_EN = (1 << 1), ++ HI_SATA_PHY2_CLK_EN = (1 << 8), ++ HI_SATA_PHY3_CLK_EN = (1 << 9), ++ ++ HI_SATA_PHY0_RST = (1 << 2), ++ HI_SATA_PHY1_RST = (1 << 3), ++ HI_SATA_PHY2_RST = (1 << 10), ++ HI_SATA_PHY3_RST = (1 << 11), ++ ++ HI_SATA_PHY3_RST_BACK_MASK = (1 << 7), ++ HI_SATA_PHY2_RST_BACK_MASK = (1 << 6), ++ HI_SATA_PHY1_RST_BACK_MASK = (1 << 5), ++ HI_SATA_PHY0_RST_BACK_MASK = (1 << 4), ++ ++ HI_SATA_BUS_CKEN = (1 << 0), ++ HI_SATA_BUS_SRST_REQ = (1 << 8), ++ HI_SATA_CKO_ALIVE_CKEN = (1 << 2), ++ HI_SATA_CKO_ALIVE_SRST_REQ = (1 << 9), ++ HI_SATA_RX0_CKEN = (1 << 1), ++ HI_SATA_TX0_CKEN = (1 << 3), ++ HI_SATA_RX0_SRST_REQ = (1 << 10), ++ HI_SATA0_SRST_REQ = (1 << 11), ++ HI_SATA_RX1_CKEN = (1 << 12), ++ HI_SATA_TX1_CKEN = (1 << 13), ++ HI_SATA_RX1_SRST_REQ = (1 << 14), ++ HI_SATA1_SRST_REQ = (1 << 15), ++ HI_SATA_RX2_CKEN = (1 << 16), ++ HI_SATA_TX2_CKEN = (1 << 17), ++ HI_SATA_RX2_SRST_REQ = (1 << 18), ++ HI_SATA2_SRST_REQ = (1 << 19), ++ HI_SATA_RX3_CKEN = (1 << 20), ++ HI_SATA_TX3_CKEN = (1 << 21), ++ HI_SATA_RX3_SRST_REQ = (1 << 22), ++ HI_SATA3_SRST_REQ = (1 << 23), ++ ++ HI_SATA_SYS_CTRL = IO_ADDRESS(0x1205008C), ++ HI_SATA_PCIE_MODE = 12, ++}; ++ ++ ++static unsigned int hi_sata_port_nr(void) ++{ ++ unsigned int val, mode, port_nr; ++ ++ val = readl((void *)HI_SATA_SYS_CTRL); ++ ++ mode = (val >> HI_SATA_PCIE_MODE) & 0xf; ++ switch (mode) { ++ case 0x0: ++ port_nr = 4; ++ sata_port_map = 0xf; ++ break; ++ ++ case 0x1: ++ port_nr = 3; ++ sata_port_map = 0x7; ++ break; ++ ++ case 0x3: ++ port_nr = 2; ++ sata_port_map = 0x3; ++ break; ++ ++ case 0x8: ++ port_nr = 3; ++ sata_port_map = 0xe; ++ break; ++ ++ case 0x9: ++ port_nr = 2; ++ sata_port_map = 0x6; ++ break; ++ ++ case 0xb: ++ port_nr = 1; ++ sata_port_map = 0x2; ++ break; ++ ++ default: ++ port_nr = 0; ++ break; ++ } ++ ++ mplx_port0 = (mode & 0x8) ? 1 : 0; ++ sata_port_nr = port_nr; ++ ++ return port_nr; ++} ++ ++static void hi_sata_poweron(void) ++{ ++ /* msleep(20); */ ++} ++ ++static void hi_sata_poweroff(void) ++{ ++} ++ ++void hisi_sata_reset_rxtx_assert(unsigned int port_no) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG74); ++ ++ if (port_no == 0) ++ tmp_val |= HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ; ++ else if (port_no == 1) ++ tmp_val |= HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ; ++ else if (port_no == 2) ++ tmp_val |= HI_SATA_RX2_SRST_REQ ++ | HI_SATA2_SRST_REQ; ++ else if (port_no == 3) ++ tmp_val |= HI_SATA_RX3_SRST_REQ ++ | HI_SATA3_SRST_REQ; ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG74); ++} ++EXPORT_SYMBOL(hisi_sata_reset_rxtx_assert); ++ ++void hisi_sata_reset_rxtx_deassert(unsigned int port_no) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG74); ++ ++ if (port_no == 0) ++ tmp_val &= ~(HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ); ++ else if (port_no == 1) ++ tmp_val &= ~(HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ); ++ else if (port_no == 2) ++ tmp_val &= ~(HI_SATA_RX2_SRST_REQ ++ | HI_SATA2_SRST_REQ); ++ else if (port_no == 3) ++ tmp_val &= ~(HI_SATA_RX3_SRST_REQ ++ | HI_SATA3_SRST_REQ); ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG74); ++} ++EXPORT_SYMBOL(hisi_sata_reset_rxtx_deassert); ++ ++static void hi_sata_reset(void) ++{ ++ unsigned int tmp_val, nport; ++ ++ nport = sata_port_nr; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG74); ++ ++ tmp_val |= HI_SATA_BUS_SRST_REQ | HI_SATA_CKO_ALIVE_SRST_REQ; ++ ++ if (nport == 4) { ++ tmp_val |= HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ ++ | HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ ++ | HI_SATA_RX2_SRST_REQ ++ | HI_SATA2_SRST_REQ ++ | HI_SATA_RX3_SRST_REQ ++ | HI_SATA3_SRST_REQ; ++ } else if (nport == 3) { ++ if (mplx_port0) { ++ tmp_val |= HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ ++ | HI_SATA_RX2_SRST_REQ ++ | HI_SATA2_SRST_REQ ++ | HI_SATA_RX3_SRST_REQ ++ | HI_SATA3_SRST_REQ; ++ } else { ++ tmp_val |= HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ ++ | HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ ++ | HI_SATA_RX2_SRST_REQ ++ | HI_SATA2_SRST_REQ; ++ } ++ } else if (nport == 2) { ++ if (mplx_port0) { ++ tmp_val |= HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ ++ | HI_SATA_RX2_SRST_REQ ++ | HI_SATA2_SRST_REQ; ++ } else { ++ tmp_val |= HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ ++ | HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ; ++ } ++ } else if (nport == 1) { ++ tmp_val |= HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ; ++ } ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG74); ++} ++ ++static void hi_sata_unreset(void) ++{ ++ unsigned int tmp_val, nport; ++ ++ nport = sata_port_nr; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG74); ++ ++ tmp_val &= ~(HI_SATA_BUS_SRST_REQ | HI_SATA_CKO_ALIVE_SRST_REQ); ++ ++ if (nport == 4) { ++ tmp_val &= ~(HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ ++ | HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ ++ | HI_SATA_RX2_SRST_REQ ++ | HI_SATA2_SRST_REQ ++ | HI_SATA_RX3_SRST_REQ ++ | HI_SATA3_SRST_REQ); ++ } else if (nport == 3) { ++ if (mplx_port0) { ++ tmp_val &= ~(HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ ++ | HI_SATA_RX2_SRST_REQ ++ | HI_SATA2_SRST_REQ ++ | HI_SATA_RX3_SRST_REQ ++ | HI_SATA3_SRST_REQ); ++ } else { ++ tmp_val &= ~(HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ ++ | HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ ++ | HI_SATA_RX2_SRST_REQ ++ | HI_SATA2_SRST_REQ); ++ } ++ } else if (nport == 2) { ++ if (mplx_port0) { ++ tmp_val &= ~(HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ ++ | HI_SATA_RX2_SRST_REQ ++ | HI_SATA2_SRST_REQ); ++ } else { ++ tmp_val &= ~(HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ ++ | HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ); ++ } ++ } else if (nport == 1) { ++ tmp_val &= ~(HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ); ++ } ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG74); ++} ++ ++static void hi_sata_phy_reset(void) ++{ ++ unsigned int tmp_val, nport; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG72); ++ ++ nport = sata_port_nr; ++ ++ if (nport == 4) { ++ tmp_val |= HI_SATA_PHY0_RST ++ | HI_SATA_PHY1_RST ++ | HI_SATA_PHY2_RST ++ | HI_SATA_PHY3_RST; ++ } else if (nport == 3) { ++ if (mplx_port0) { ++ tmp_val |= HI_SATA_PHY1_RST ++ | HI_SATA_PHY2_RST ++ | HI_SATA_PHY3_RST; ++ } else { ++ tmp_val |= HI_SATA_PHY0_RST ++ | HI_SATA_PHY1_RST ++ | HI_SATA_PHY2_RST; ++ } ++ } else if (nport == 2) { ++ if (mplx_port0) { ++ tmp_val |= HI_SATA_PHY1_RST ++ | HI_SATA_PHY2_RST; ++ } else { ++ tmp_val |= HI_SATA_PHY0_RST ++ | HI_SATA_PHY1_RST; ++ } ++ } else if (nport == 1) { ++ tmp_val |= HI_SATA_PHY1_RST; ++ } ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG72); ++} ++ ++static void hi_sata_phy_unreset(void) ++{ ++ unsigned int tmp_val, nport; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG72); ++ ++ nport = sata_port_nr; ++ ++ if (nport == 4) { ++ tmp_val &= ~(HI_SATA_PHY0_RST ++ | HI_SATA_PHY1_RST ++ | HI_SATA_PHY2_RST ++ | HI_SATA_PHY3_RST); ++ } else if (nport == 3) { ++ if (mplx_port0) { ++ tmp_val &= ~(HI_SATA_PHY1_RST ++ | HI_SATA_PHY2_RST ++ | HI_SATA_PHY3_RST); ++ } else { ++ tmp_val &= ~(HI_SATA_PHY0_RST ++ | HI_SATA_PHY1_RST ++ | HI_SATA_PHY2_RST); ++ } ++ } else if (nport == 2) { ++ if (mplx_port0) { ++ tmp_val &= ~(HI_SATA_PHY1_RST ++ | HI_SATA_PHY2_RST); ++ } else { ++ tmp_val &= ~(HI_SATA_PHY0_RST ++ | HI_SATA_PHY1_RST); ++ } ++ } else if (nport == 1) { ++ tmp_val &= ~HI_SATA_PHY1_RST; ++ } ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG72); ++} ++ ++static void hi_sata_clk_enable(void) ++{ ++ unsigned int tmp_val, tmp_reg, nport; ++ ++ nport = sata_port_nr; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG72); ++ tmp_reg = readl((void *)HI_SATA_PERI_CRG74); ++ ++ tmp_reg |= HI_SATA_BUS_CKEN ++ | HI_SATA_CKO_ALIVE_CKEN; ++ ++ if (nport == 4) { ++ tmp_val |= HI_SATA_PHY0_CLK_EN; ++ tmp_val |= HI_SATA_PHY1_CLK_EN; ++ tmp_val |= HI_SATA_PHY2_CLK_EN; ++ tmp_val |= HI_SATA_PHY3_CLK_EN; ++ ++ tmp_reg |= HI_SATA_RX0_CKEN ++ | HI_SATA_TX0_CKEN ++ | HI_SATA_RX1_CKEN ++ | HI_SATA_TX1_CKEN ++ | HI_SATA_RX2_CKEN ++ | HI_SATA_TX2_CKEN ++ | HI_SATA_RX3_CKEN ++ | HI_SATA_TX3_CKEN; ++ ++ } else if (nport == 3) { ++ if (mplx_port0) { ++ tmp_val |= HI_SATA_PHY1_CLK_EN; ++ tmp_val |= HI_SATA_PHY2_CLK_EN; ++ tmp_val |= HI_SATA_PHY3_CLK_EN; ++ ++ tmp_reg |= HI_SATA_RX1_CKEN ++ | HI_SATA_TX1_CKEN ++ | HI_SATA_RX2_CKEN ++ | HI_SATA_TX2_CKEN ++ | HI_SATA_RX3_CKEN ++ | HI_SATA_TX3_CKEN; ++ } else { ++ tmp_val |= HI_SATA_PHY0_CLK_EN; ++ tmp_val |= HI_SATA_PHY1_CLK_EN; ++ tmp_val |= HI_SATA_PHY2_CLK_EN; ++ ++ tmp_reg |= HI_SATA_RX0_CKEN ++ | HI_SATA_TX0_CKEN ++ | HI_SATA_RX1_CKEN ++ | HI_SATA_TX1_CKEN ++ | HI_SATA_RX2_CKEN ++ | HI_SATA_TX2_CKEN; ++ } ++ } else if (nport == 2) { ++ if (mplx_port0) { ++ tmp_val |= HI_SATA_PHY1_CLK_EN; ++ tmp_val |= HI_SATA_PHY2_CLK_EN; ++ ++ tmp_reg |= HI_SATA_RX1_CKEN ++ | HI_SATA_TX1_CKEN ++ | HI_SATA_RX2_CKEN ++ | HI_SATA_TX2_CKEN; ++ } else { ++ tmp_val |= HI_SATA_PHY0_CLK_EN; ++ tmp_val |= HI_SATA_PHY1_CLK_EN; ++ ++ tmp_reg |= HI_SATA_RX0_CKEN ++ | HI_SATA_TX0_CKEN ++ | HI_SATA_RX1_CKEN ++ | HI_SATA_TX1_CKEN; ++ } ++ } else if (nport == 1) { ++ tmp_val |= HI_SATA_PHY1_CLK_EN; ++ ++ tmp_reg |= HI_SATA_RX1_CKEN ++ | HI_SATA_TX1_CKEN; ++ } else ++ return; ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG72); ++ writel(tmp_reg, (void *)HI_SATA_PERI_CRG74); ++ ++} ++static void hi_sata_clk_disable(void) ++{ ++} ++ ++static void hi_sata_clk_reset(void) ++{ ++} ++ ++static void hi_sata_phy_clk_sel(void) ++{ ++ unsigned int tmp_val, nport; ++ ++ nport = sata_port_nr; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG72); ++ ++ if (nport == 4) { ++ tmp_val &= ~HI_SATA_PHY0_REFCLK_SEL_MASK; ++ tmp_val &= ~HI_SATA_PHY1_REFCLK_SEL_MASK; ++ tmp_val &= ~HI_SATA_PHY2_REFCLK_SEL_MASK; ++ tmp_val &= ~HI_SATA_PHY3_REFCLK_SEL_MASK; ++ ++ tmp_val |= HI_SATA_PHY0_REFCLK_SEL; ++ tmp_val |= HI_SATA_PHY1_REFCLK_SEL; ++ tmp_val |= HI_SATA_PHY2_REFCLK_SEL; ++ tmp_val |= HI_SATA_PHY3_REFCLK_SEL; ++ } else if (nport == 3) { ++ if (mplx_port0) { ++ tmp_val &= ~HI_SATA_PHY1_REFCLK_SEL_MASK; ++ tmp_val &= ~HI_SATA_PHY2_REFCLK_SEL_MASK; ++ tmp_val &= ~HI_SATA_PHY3_REFCLK_SEL_MASK; ++ ++ tmp_val |= HI_SATA_PHY1_REFCLK_SEL; ++ tmp_val |= HI_SATA_PHY2_REFCLK_SEL; ++ tmp_val |= HI_SATA_PHY3_REFCLK_SEL; ++ } else { ++ tmp_val &= ~HI_SATA_PHY0_REFCLK_SEL_MASK; ++ tmp_val &= ~HI_SATA_PHY1_REFCLK_SEL_MASK; ++ tmp_val &= ~HI_SATA_PHY2_REFCLK_SEL_MASK; ++ ++ tmp_val |= HI_SATA_PHY0_REFCLK_SEL; ++ tmp_val |= HI_SATA_PHY1_REFCLK_SEL; ++ tmp_val |= HI_SATA_PHY2_REFCLK_SEL; ++ } ++ } else if (nport == 2) { ++ if (mplx_port0) { ++ tmp_val &= ~HI_SATA_PHY1_REFCLK_SEL_MASK; ++ tmp_val &= ~HI_SATA_PHY2_REFCLK_SEL_MASK; ++ ++ tmp_val |= HI_SATA_PHY1_REFCLK_SEL; ++ tmp_val |= HI_SATA_PHY2_REFCLK_SEL; ++ } else { ++ tmp_val &= ~HI_SATA_PHY0_REFCLK_SEL_MASK; ++ tmp_val &= ~HI_SATA_PHY1_REFCLK_SEL_MASK; ++ ++ tmp_val |= HI_SATA_PHY0_REFCLK_SEL; ++ tmp_val |= HI_SATA_PHY1_REFCLK_SEL; ++ ++ } ++ } else if (nport == 1) { ++ tmp_val &= ~HI_SATA_PHY1_REFCLK_SEL_MASK; ++ tmp_val |= HI_SATA_PHY1_REFCLK_SEL; ++ } else ++ return; ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG72); ++} ++ ++void hisata_v200_set_fifo(void *mmio, int n_ports) ++{ ++ int i, port_no; ++ ++ for (i = 0; i < n_ports; i++) { ++ port_no = i; ++ if (mplx_port0) ++ port_no++; ++ ++ writel(HI_SATA_FIFOTH_VALUE, (mmio + 0x100 + port_no*0x80 ++ + HI_SATA_PORT_FIFOTH)); ++ } ++} ++ ++void hisata_phy_init(void *mmio, int phy_mode, int n_ports) ++{ ++ unsigned int tmp, phy_config = HI_SATA_PHY_3G; ++ unsigned int phy_sg = HI_SATA_PHY_SG_3G; ++ int i, port_no; ++ ++ hisata_v200_set_fifo(mmio, n_ports); ++ ++ tmp = readl(mmio + HI_SATA_PHY_CTL1); ++ tmp |= HI_SATA_BIGENDINE; ++ writel(tmp, (mmio + HI_SATA_PHY_CTL1)); ++ tmp = readl(mmio + HI_SATA_PHY_CTL2); ++ tmp |= HI_SATA_BIGENDINE; ++ writel(tmp, (mmio + HI_SATA_PHY_CTL2)); ++ ++ tmp = readl(mmio + HI_SATA_PHY_RST_BACK_MASK); ++ tmp &= 0xffffff0f; ++ if (n_ports == 1) { ++ tmp |= HI_SATA_PHY0_RST_BACK_MASK ++ | HI_SATA_PHY2_RST_BACK_MASK ++ | HI_SATA_PHY3_RST_BACK_MASK; ++ } else if (n_ports == 2) { ++ if (mplx_port0) { ++ tmp |= HI_SATA_PHY0_RST_BACK_MASK ++ | HI_SATA_PHY3_RST_BACK_MASK; ++ } else { ++ tmp |= HI_SATA_PHY2_RST_BACK_MASK ++ | HI_SATA_PHY3_RST_BACK_MASK; ++ } ++ } else if (n_ports == 3) { ++ if (mplx_port0) ++ tmp |= HI_SATA_PHY0_RST_BACK_MASK; ++ else ++ tmp |= HI_SATA_PHY3_RST_BACK_MASK; ++ } else if (n_ports == 4) { ++ /* Not need mask any port */ ++ } ++ writel(tmp, (mmio + HI_SATA_PHY_RST_BACK_MASK)); ++ ++ if (phy_mode == HI_SATA_PHY_MODE_1_5G) { ++ phy_config = HI_SATA_PHY_1_5G; ++ phy_sg = HI_SATA_PHY_SG_1_5G; ++ } ++ ++ if (phy_mode == HI_SATA_PHY_MODE_3G) { ++ phy_config = HI_SATA_PHY_3G; ++ phy_sg = HI_SATA_PHY_SG_3G; ++ } ++ ++ if (phy_mode == HI_SATA_PHY_MODE_6G) { ++ phy_config = HI_SATA_PHY_6G; ++ phy_sg = HI_SATA_PHY_SG_6G; ++ } ++ ++ for (i = 0; i < n_ports; i++) { ++ port_no = i; ++ if (mplx_port0) ++ port_no++; ++ ++ writel(phy_config, (mmio + 0x100 + port_no*0x80 ++ + HI_SATA_PORT_PHYCTL)); ++ ++ writel(phy_sg, (mmio + 0x100 + port_no*0x80 ++ + HI_SATA_PORT_PHYCTL1)); ++ } ++} ++ ++static void hi_sata_phy_reg_config(void) ++{ ++ unsigned int i, port_no; ++ ++ for (i = 0; i < sata_port_nr; i++) { ++ port_no = i; ++ if (mplx_port0) ++ port_no++; ++ ++ if (port_no == 0) { ++ /* PLL always 6G & CDR <= RATE */ ++ writel(0xd01, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0xd41, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0xd01, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY0); ++ ++ /* disable SSC */ ++ writel(0x803, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x843, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x803, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY0); ++ ++ /* EQ set 6'b010000 */ ++ writel(0x009, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x049, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x009, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY0); ++ ++ writel(0x508, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x548, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x508, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY0); ++ } else if (port_no == 1) { ++ /* PLL always 6G & CDR <= RATE */ ++ writel(0xd01, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0xd41, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0xd01, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY1); ++ ++ /* disable SSC */ ++ writel(0x803, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x843, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x803, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY1); ++ ++ /* EQ set 6'b010000 */ ++ writel(0x009, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x049, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x009, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY1); ++ ++ writel(0x508, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x548, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x508, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY1); ++ } else if (port_no == 2) { ++ /* PLL always 6G & CDR <= RATE */ ++ writel(0xd01, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0xd41, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0xd01, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY2); ++ ++ /* disable SSC */ ++ writel(0x803, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x843, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x803, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY2); ++ ++ /* EQ set 6'b010000 */ ++ writel(0x009, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x049, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x009, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY2); ++ ++ writel(0x508, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x548, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x508, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY2); ++ } else if (port_no == 3) { ++ /* PLL always 6G & CDR <= RATE */ ++ writel(0xd01, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0xd41, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0xd01, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY3); ++ ++ /* disable SSC */ ++ writel(0x803, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x843, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x803, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY3); ++ ++ /* EQ set 6'b010000 */ ++ writel(0x009, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x049, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x009, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY3); ++ ++ writel(0x508, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x548, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x508, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY3); ++ } ++ } ++} ++ ++void hi_sata_eq_recovery(unsigned int port_no) ++{ ++ if (port_no == 0) { ++ /* auto_eq */ ++ writel(0xf09, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0xf49, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0xf09, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY0); ++ ++ writel(0x308, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x348, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x308, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY0); ++ } else if (port_no == 1) { ++ /* auto_eq */ ++ writel(0xf09, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0xf49, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0xf09, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY1); ++ ++ writel(0x308, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x348, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x308, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY1); ++ } else if (port_no == 2) { ++ /* auto_eq */ ++ writel(0xf09, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0xf49, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0xf09, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY2); ++ ++ writel(0x308, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x348, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x308, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY2); ++ } else if (port_no == 3) { ++ /* auto_eq */ ++ writel(0xf09, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0xf49, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0xf09, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY3); ++ ++ writel(0x308, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x348, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x308, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY3); ++ } ++ ++ return; ++} ++EXPORT_SYMBOL(hi_sata_eq_recovery); ++ ++void hi_sata_set_eq(unsigned int port_no) ++{ ++ if (port_no == 0) { ++ /* EQ set 6'b010000 */ ++ writel(0x009, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x049, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x009, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY0); ++ ++ writel(0x508, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x548, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x508, (void *)HI_SATA_MISC_COMB_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY0); ++ } else if (port_no == 1) { ++ /* EQ set 6'b010000 */ ++ writel(0x009, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x049, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x009, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY1); ++ ++ writel(0x508, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x548, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x508, (void *)HI_SATA_MISC_COMB_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY1); ++ } else if (port_no == 2) { ++ /* EQ set 6'b010000 */ ++ writel(0x009, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x049, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x009, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY2); ++ ++ writel(0x508, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x548, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x508, (void *)HI_SATA_MISC_COMB_PHY2); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY2); ++ } else if (port_no == 3) { ++ /* EQ set 6'b010000 */ ++ writel(0x009, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x049, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x009, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY3); ++ ++ writel(0x508, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x548, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x508, (void *)HI_SATA_MISC_COMB_PHY3); ++ writel(0x0, (void *)HI_SATA_MISC_COMB_PHY3); ++ } ++ ++ return; ++} ++EXPORT_SYMBOL(hi_sata_set_eq); +diff --git a/drivers/phy/phy-hi3531d-usb3.c b/drivers/phy/phy-hi3531d-usb3.c +new file mode 100644 +index 0000000..1cc46c1 +--- /dev/null ++++ b/drivers/phy/phy-hi3531d-usb3.c +@@ -0,0 +1,309 @@ ++/* ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define SYS_CTRL 0x12050000 ++#define USB2_PHY1 0x16c ++#define USB2_PHY1_TEST_SRST_REQ BIT(10) ++#define USB2_PHY1_SRST_TREQ BIT(9) ++#define USB2_PHY1_SRST_REQ BIT(8) ++#define USB2_PHY1_REF_CLKEN BIT(0) ++ ++#define HOST_U3_DISABLE (1 << 3) ++#define USB3_U2_PHY 0x12c ++ ++#define USB3_CTRL 0x12c ++#define USB3_VCC_SRST_REQ BIT(13) ++#define USB3_UTMI_CLKEN BIT(12) ++#define USB3_PIPE_CLKEN BIT(11) ++#define USB3_SUSPEND_CLKEN BIT(10) ++#define USB3_REF_CLKEN BIT(9) ++#define USB3_BUS_CLKEN BIT(8) ++ ++#define USB3_COMBPHY 0x120 ++#define COMBPHY1_LANE0_REQ BIT(2) ++ ++#define GTXTHRCFG 0xc108 ++#define GRXTHRCFG 0xc10c ++#define REG_GCTL 0xc110 ++#define U2RSTECN (0x1 << 16) ++ ++#define REG_GUSB2PHYCFG0 0xC200 ++#define BIT_UTMI_ULPI (0x1 << 4) ++#define BIT_UTMI_8_16 (0x1 << 3) ++ ++#define REG_GUSB3PIPECTL0 0xc2c0 ++#define PCS_SSP_SOFT_RESET (0x1 << 31) ++#define TX_MARGIN_MASK (0x7 << 3) ++#define TX_MARGIN_VAL (0x2 << 3) ++ ++#define USB2_PHY0_CTLL 0x80 ++ ++#define USB3_PHY 0x88 ++#define COMBO_PHY_TX_DEEMP_MASK (0x7 << 12) ++#define COMBO_PHY_TX_DEEMP_VAL (0x1 << 12) ++ ++#define USB2_PHY_TEST_REG_ACCESS (1 << 20) ++ ++struct hisi_priv { ++ void __iomem *base; ++ void __iomem *dwc3_ctrl; /* 0x11000000 */ ++ void __iomem *peri_ctrl; /* 0x12040000 */ ++ void __iomem *misc_ctrl; /* 0x12120000 */ ++}; ++ ++static void hisi_usb3_phy_eye(struct phy *phy) ++{ ++ int reg; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ /* configuration method */ ++ reg = readl(priv->misc_ctrl + 0x10); ++ reg |= USB2_PHY_TEST_REG_ACCESS; ++ writel(reg, priv->misc_ctrl + 0x10); ++ udelay(100); ++ /* slew rate */ ++ writel(0xc4, priv->misc_ctrl + 0x8020); ++ udelay(20); ++ /* Calibration mode */ ++ writel(0xc1, priv->misc_ctrl + 0x8044); ++ udelay(20); ++ /* disconnect threshold value */ ++ writel(0x1b, priv->misc_ctrl + 0x8028); ++ udelay(20); ++ /* turn on pre-emphasis */ ++ writel(0x1c, priv->misc_ctrl + 0x8000); ++ udelay(20); ++ writel(0x92, priv->misc_ctrl + 0x8014); ++ udelay(20); ++ writel(0xd, priv->misc_ctrl + 0x8018); ++ udelay(20); ++ /* down 100mv 2017/2/13 by h292880*/ ++ writel(0x103, priv->misc_ctrl + 0x134); ++ udelay(20); ++ writel(0x143, priv->misc_ctrl + 0x134); ++ udelay(20); ++} ++ ++static int hisi_usb3_ctrl_phy_config(struct phy *phy) ++{ ++ int reg; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ reg = readl(priv->dwc3_ctrl + REG_GUSB3PIPECTL0); ++ reg |= PCS_SSP_SOFT_RESET; ++ writel(reg, priv->dwc3_ctrl + REG_GUSB3PIPECTL0); ++ ++ /*step 3: USB2 PHY chose ulpi 8bit interface */ ++ reg = readl(priv->dwc3_ctrl + REG_GUSB2PHYCFG0); ++ reg &= ~BIT_UTMI_ULPI; ++ reg &= ~(BIT_UTMI_8_16); ++ writel(reg, priv->dwc3_ctrl + REG_GUSB2PHYCFG0); ++ mdelay(20); ++ reg = readl(priv->dwc3_ctrl + REG_GCTL); ++ reg &= ~(0x3<<12); ++ reg |= (0x1<<12); /*[13:12] 01: Host; 10: Device; 11: OTG*/ ++ reg &= ~U2RSTECN; ++ writel(reg, priv->dwc3_ctrl + REG_GCTL); ++ mdelay(20); ++ ++ reg = readl(priv->dwc3_ctrl + REG_GUSB3PIPECTL0); ++ reg &= ~PCS_SSP_SOFT_RESET; ++ reg &= ~(1<<17); /* disable suspend */ ++ writel(reg, priv->dwc3_ctrl + REG_GUSB3PIPECTL0); ++ mdelay(100); ++ ++ writel(0x23100000, priv->dwc3_ctrl + GTXTHRCFG); ++ writel(0x23180000, priv->dwc3_ctrl + GRXTHRCFG); ++ mdelay(20); ++ ++ hisi_usb3_phy_eye(phy); ++ ++ return 0; ++} ++ ++static int hisi_usb3_phy_on(struct phy *phy) ++{ ++ int reg; ++ void __iomem *sys_base; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ sys_base = ioremap(SYS_CTRL, 0x1000); ++ reg = readl(sys_base + 0x8c); ++ if ((reg & (0x1 << 15)) != 0) { ++ reg = readl(priv->peri_ctrl + 0x120); ++ reg |= COMBPHY1_LANE0_REQ; ++ writel(reg, priv->peri_ctrl + 0x120); ++ mdelay(10); ++ ++ reg = readl_relaxed(priv->peri_ctrl + USB3_COMBPHY); ++ reg &= ~COMBPHY1_LANE0_REQ; ++ writel_relaxed(reg, priv->peri_ctrl + USB3_COMBPHY); ++ mdelay(10); ++ } else { ++ reg = readl(priv->misc_ctrl + 0x128); ++ reg |= HOST_U3_DISABLE; ++ writel(reg, priv->misc_ctrl + 0x128); ++ mdelay(1); ++ ++ pr_info("COMBPHY IS NOT USB\n"); ++ } ++ iounmap(sys_base); ++ ++ reg = readl_relaxed(priv->peri_ctrl + USB2_PHY1); ++ reg &= ~USB2_PHY1_TEST_SRST_REQ; ++ reg &= ~USB2_PHY1_SRST_TREQ; ++ reg &= ~USB2_PHY1_SRST_REQ; ++ reg |= USB2_PHY1_REF_CLKEN; ++ writel_relaxed(reg, priv->peri_ctrl + USB2_PHY1); ++ mdelay(10); ++ ++ reg = readl_relaxed(priv->peri_ctrl + USB3_CTRL); ++ reg |= USB3_UTMI_CLKEN; ++ reg |= USB3_PIPE_CLKEN; ++ reg |= USB3_SUSPEND_CLKEN; ++ reg |= USB3_REF_CLKEN; ++ reg |= USB3_BUS_CLKEN; ++ reg &= ~USB3_VCC_SRST_REQ; ++ writel_relaxed(reg, priv->peri_ctrl + USB3_CTRL); ++ mdelay(10); ++ ++ hisi_usb3_ctrl_phy_config(phy); ++ ++ return 0; ++} ++ ++static int hisi_usb3_phy_power_off(struct device *dev) ++{ ++ int reg; ++ struct phy *phy = dev_get_drvdata(dev); ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ reg = readl_relaxed(priv->peri_ctrl + USB3_COMBPHY); ++ reg |= COMBPHY1_LANE0_REQ; ++ writel_relaxed(reg, priv->peri_ctrl + USB3_COMBPHY); ++ mdelay(100); ++ ++ reg = readl_relaxed(priv->peri_ctrl + USB3_CTRL); ++ reg |= USB3_VCC_SRST_REQ; ++ writel_relaxed(reg, priv->peri_ctrl + USB3_CTRL); ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int hisi_usb3_phy_power_on(struct device *dev) ++{ ++ struct phy *phy = dev_get_drvdata(dev); ++ ++ hisi_usb3_phy_on(phy); ++ ++ return 0; ++} ++ ++static int hisi_usb3_phy_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct phy *phy; ++ struct hisi_priv *priv; ++ struct device_node *np = pdev->dev.of_node; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->dwc3_ctrl = of_iomap(np, 0); /* 0x11000000 */ ++ if (IS_ERR(priv->dwc3_ctrl)) ++ priv->dwc3_ctrl = NULL; ++ ++ priv->peri_ctrl = of_iomap(np, 1); /* 0x12040000 */ ++ if (IS_ERR(priv->peri_ctrl)) ++ priv->peri_ctrl = NULL; ++ ++ priv->misc_ctrl = of_iomap(np, 2); /* 0x12120000 */ ++ if (IS_ERR(priv->misc_ctrl)) ++ priv->misc_ctrl = NULL; ++ ++ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); ++ if (!phy) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, phy); ++ phy_set_drvdata(phy, priv); ++ hisi_usb3_phy_on(phy); ++ ++ return 0; ++} ++ ++static int hisi_usb3_phy_remove(struct platform_device *pdev) ++{ ++ int reg; ++ struct phy *phy = platform_get_drvdata(pdev); ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ reg = readl_relaxed(priv->peri_ctrl + USB3_CTRL); ++ reg &= ~USB3_UTMI_CLKEN; ++ reg &= ~USB3_PIPE_CLKEN; ++ reg &= ~USB3_SUSPEND_CLKEN; ++ reg &= ~USB3_REF_CLKEN; ++ reg &= ~USB3_BUS_CLKEN; ++ reg |= USB3_VCC_SRST_REQ; ++ writel_relaxed(reg, priv->peri_ctrl + USB3_CTRL); ++ mdelay(10); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops hisi_usb3_pmops = { ++ .suspend = hisi_usb3_phy_power_off, ++ .resume = hisi_usb3_phy_power_on, ++#if defined(CONFIG_PM_HIBERNATE) || defined(CONFIG_HISI_SNAPSHOT_BOOT) ++ .freeze = hisi_usb3_phy_power_off, ++ .thaw = hisi_usb3_phy_power_on, ++ .poweroff = hisi_usb3_phy_power_off, ++ .restore = hisi_usb3_phy_power_on, ++#endif ++}; ++ ++static const struct of_device_id hisi_usb3_phy_of_match[] = { ++ {.compatible = "hisilicon,hi3531d-usb3-phy",}, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, hisi_usb3_phy_of_match); ++ ++static struct platform_driver hisi_usb3_phy_driver = { ++ .probe = hisi_usb3_phy_probe, ++ .remove = hisi_usb3_phy_remove, ++ .driver = { ++ .name = "hisi-usb3-phy", ++ .of_match_table = hisi_usb3_phy_of_match, ++ .pm = &hisi_usb3_pmops, ++ } ++}; ++module_platform_driver(hisi_usb3_phy_driver); ++ ++MODULE_AUTHOR("Pengcheng Li "); ++MODULE_DESCRIPTION("HISILICON USB PHY driver"); ++MODULE_ALIAS("platform:hisi-usb3-phy"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/phy/phy-hi3536c-sata.c b/drivers/phy/phy-hi3536c-sata.c +new file mode 100644 +index 0000000..dbfba40 +--- /dev/null ++++ b/drivers/phy/phy-hi3536c-sata.c +@@ -0,0 +1,416 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++unsigned int sata_port_map; ++ ++enum { ++ HI_SATA_PERI_CTRL = IO_ADDRESS(0x12040000), ++ HI_SATA_PERI_CRG72 = (HI_SATA_PERI_CTRL + 0x120), ++ HI_SATA_PERI_CRG74 = (HI_SATA_PERI_CTRL + 0x128), ++ ++ HI_SATA_PHY0_REFCLK_SEL_MASK = (0x3 << 4), ++ HI_SATA_PHY0_REFCLK_SEL = (0x1 << 4), ++ HI_SATA_PHY1_REFCLK_SEL_MASK = (0x3 << 6), ++ HI_SATA_PHY1_REFCLK_SEL = (0x1 << 6), ++ ++ HI_SATA_PHY0_CLK_EN = (1 << 0), ++ HI_SATA_PHY1_CLK_EN = (1 << 1), ++ ++ HI_SATA_PHY0_RST = (1 << 2), ++ HI_SATA_PHY1_RST = (1 << 3), ++ ++ HI_SATA_PHY_BACK_MASK_ALL = 0xf0, ++ HI_SATA_PHY1_RST_BACK_MASK = (1 << 5), ++ HI_SATA_PHY0_RST_BACK_MASK = (1 << 4), ++ ++ HI_SATA_BUS_CKEN = (1 << 0), ++ HI_SATA_BUS_SRST_REQ = (1 << 8), ++ HI_SATA_CKO_ALIVE_CKEN = (1 << 2), ++ HI_SATA_CKO_ALIVE_SRST_REQ = (1 << 9), ++ HI_SATA_RX0_CKEN = (1 << 1), ++ HI_SATA_TX0_CKEN = (1 << 3), ++ HI_SATA_RX0_SRST_REQ = (1 << 10), ++ HI_SATA0_SRST_REQ = (1 << 11), ++ HI_SATA_RX1_CKEN = (1 << 12), ++ HI_SATA_TX1_CKEN = (1 << 13), ++ HI_SATA_RX1_SRST_REQ = (1 << 14), ++ HI_SATA1_SRST_REQ = (1 << 15), ++ ++ HI_SATA_SYS_CTRL = IO_ADDRESS(0x1205008C), ++}; ++ ++static void hi_sata_poweron(void) ++{ ++ /* msleep(20); */ ++} ++ ++static void hi_sata_poweroff(void) ++{ ++} ++ ++void hisi_sata_reset_rxtx_assert(unsigned int port_no) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG74); ++ ++ if (port_no == 1) { ++ tmp_val |= HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ; ++ } else if (port_no == 0) { ++ tmp_val |= HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ; ++ } ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG74); ++} ++EXPORT_SYMBOL(hisi_sata_reset_rxtx_assert); ++ ++void hisi_sata_reset_rxtx_deassert(unsigned int port_no) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG74); ++ ++ if (port_no == 1) { ++ tmp_val &= ~(HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ); ++ } else if (port_no == 0) { ++ tmp_val &= ~(HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ); ++ } ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG74); ++} ++EXPORT_SYMBOL(hisi_sata_reset_rxtx_deassert); ++ ++static void hi_sata_reset(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG74); ++ ++ tmp_val |= HI_SATA_BUS_SRST_REQ | HI_SATA_CKO_ALIVE_SRST_REQ; ++ if (n_ports == 2) { ++ tmp_val |= HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ ++ | HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ; ++ } else if (n_ports == 1) { ++ tmp_val |= HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ; ++ } ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG74); ++} ++ ++static void hi_sata_unreset(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG74); ++ ++ tmp_val &= ~(HI_SATA_BUS_SRST_REQ | HI_SATA_CKO_ALIVE_SRST_REQ); ++ if (n_ports == 2) { ++ tmp_val &= ~(HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ ++ | HI_SATA_RX1_SRST_REQ ++ | HI_SATA1_SRST_REQ); ++ ++ } else if (n_ports == 1) { ++ tmp_val &= ~(HI_SATA_RX0_SRST_REQ ++ | HI_SATA0_SRST_REQ); ++ } ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG74); ++} ++ ++static void hi_sata_phy_reset(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG72); ++ ++ if (n_ports == 2) { ++ tmp_val |= HI_SATA_PHY0_RST ++ | HI_SATA_PHY1_RST; ++ ++ } else if (n_ports == 1) ++ tmp_val |= HI_SATA_PHY0_RST; ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG72); ++} ++ ++static void hi_sata_phy_unreset(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG72); ++ ++ if (n_ports == 2) { ++ tmp_val &= ~(HI_SATA_PHY0_RST ++ | HI_SATA_PHY1_RST); ++ } else if (n_ports == 1) ++ tmp_val &= ~HI_SATA_PHY0_RST; ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG72); ++} ++ ++static void hi_sata_clk_enable(void) ++{ ++ unsigned int tmp_val, tmp_reg; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG72); ++ tmp_reg = readl((void *)HI_SATA_PERI_CRG74); ++ ++ if (n_ports == 2) { ++ tmp_val |= HI_SATA_PHY0_CLK_EN; ++ tmp_val |= HI_SATA_PHY1_CLK_EN; ++ ++ tmp_reg |= HI_SATA_RX0_CKEN ++ | HI_SATA_TX0_CKEN ++ | HI_SATA_RX1_CKEN ++ | HI_SATA_TX1_CKEN; ++ ++ } else if (n_ports == 1) { ++ tmp_val |= HI_SATA_PHY0_CLK_EN; ++ ++ tmp_reg |= HI_SATA_RX0_CKEN ++ | HI_SATA_TX0_CKEN; ++ ++ } ++ ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG72); ++ writel(tmp_reg, (void *)HI_SATA_PERI_CRG74); ++ ++} ++ ++static void hi_sata_clk_disable(void) ++{ ++} ++ ++static void hi_sata_clk_reset(void) ++{ ++} ++ ++static void hi_sata_phy_clk_sel(void) ++{ ++ unsigned int tmp_val; ++ ++ tmp_val = readl((void *)HI_SATA_PERI_CRG72); ++ ++ if (n_ports == 2) { ++ tmp_val &= ~HI_SATA_PHY0_REFCLK_SEL_MASK; ++ tmp_val &= ~HI_SATA_PHY1_REFCLK_SEL_MASK; ++ ++ tmp_val |= HI_SATA_PHY0_REFCLK_SEL; ++ tmp_val |= HI_SATA_PHY1_REFCLK_SEL; ++ ++ } else if (n_ports == 1) { ++ tmp_val &= ~HI_SATA_PHY1_REFCLK_SEL_MASK; ++ tmp_val |= HI_SATA_PHY1_REFCLK_SEL; ++ } ++ writel(tmp_val, (void *)HI_SATA_PERI_CRG72); ++} ++ ++void hisata_v200_set_fifo(void *mmio, int n_ports) ++{ ++ int i; ++ ++ for (i = 0; i < n_ports; i++) ++ writel(HI_SATA_FIFOTH_VALUE, (mmio + 0x100 + i*0x80 ++ + HI_SATA_PORT_FIFOTH)); ++} ++ ++void hisata_phy_init(void *mmio, int phy_mode, int n_ports) ++{ ++ unsigned int tmp, phy_config = HI_SATA_PHY_3G; ++ unsigned int phy_sg = HI_SATA_PHY_SG_3G; ++ int i, port_no; ++ ++ if ((n_ports < 1) || (n_ports > 2)) ++ pr_err("ERROR: PORT num you set is WRONG!!!\n"); ++ ++ sata_port_map = (1 << n_ports) - 1; ++ hisata_v200_set_fifo(mmio, n_ports); ++ ++ tmp = readl(mmio + HI_SATA_PHY_CTL1); ++ tmp |= HI_SATA_BIGENDINE; ++ writel(tmp, (mmio + HI_SATA_PHY_CTL1)); ++ tmp = readl(mmio + HI_SATA_PHY_CTL2); ++ tmp |= HI_SATA_BIGENDINE; ++ writel(tmp, (mmio + HI_SATA_PHY_CTL2)); ++ ++ tmp = readl(mmio + HI_SATA_PHY_RST_BACK_MASK); ++ tmp |= HI_SATA_PHY_BACK_MASK_ALL; ++ if (n_ports == 1) ++ tmp &= ~HI_SATA_PHY1_RST_BACK_MASK; ++ else if (n_ports == 2) ++ /* Not need mask any port */ ++ ++ writel(tmp, (mmio + HI_SATA_PHY_RST_BACK_MASK)); ++ ++ if (phy_mode == HI_SATA_PHY_MODE_1_5G) { ++ phy_config = HI_SATA_PHY_1_5G; ++ phy_sg = HI_SATA_PHY_SG_1_5G; ++ } ++ ++ if (phy_mode == HI_SATA_PHY_MODE_3G) { ++ phy_config = HI_SATA_PHY_3G; ++ phy_sg = HI_SATA_PHY_SG_3G; ++ } ++ ++ if (phy_mode == HI_SATA_PHY_MODE_6G) { ++ phy_config = HI_SATA_PHY_6G; ++ phy_sg = HI_SATA_PHY_SG_6G; ++ } ++ ++ for (i = 0; i < n_ports; i++) { ++ port_no = i; ++ writel(phy_config, (mmio + 0x100 + port_no*0x80 ++ + HI_SATA_PORT_PHYCTL)); ++ ++ writel(phy_sg, (mmio + 0x100 + port_no*0x80 ++ + HI_SATA_PORT_PHYCTL1)); ++ } ++} ++ ++static void hi_sata_phy_reg_config(void) ++{ ++ unsigned int i, port_no; ++ ++ for (i = 0; i < n_ports; i++) { ++ port_no = i; ++ ++ if (port_no == 0) { ++ /* PLL always 6G & CDR <= RATE */ ++ writel(0xd01, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0xd41, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0xd01, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY0); ++ ++ /* disable SSC */ ++ writel(0x803, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x843, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x803, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY0); ++ ++ /* EQ set b010000 */ ++ writel(0x009, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x049, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x009, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY0); ++ ++ writel(0x508, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x548, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x508, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY0); ++ } else if (port_no == 1) { ++ /* PLL always 6G & CDR <= RATE */ ++ writel(0xd01, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0xd41, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0xd01, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY1); ++ ++ /* disable SSC */ ++ writel(0x803, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x843, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x803, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY1); ++ ++ /* EQ set b010000 */ ++ writel(0x009, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x049, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x009, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY1); ++ ++ writel(0x508, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x548, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x508, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY1); ++ } ++ } ++} ++ ++void hi_sata_eq_recovery(unsigned int port_no) ++{ ++ if (port_no == 0) { ++ /* EQ recovery */ ++ writel(0xf09, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0xf49, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0xf09, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY0); ++ ++ writel(0x308, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x348, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x308, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY0); ++ } else if (port_no == 1) { ++ /* EQ recovery */ ++ writel(0xf09, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0xf49, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0xf09, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY1); ++ ++ writel(0x308, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x348, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x308, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY1); ++ } ++} ++EXPORT_SYMBOL(hi_sata_eq_recovery); ++ ++void hi_sata_set_eq(unsigned int port_no) ++{ ++ if (port_no == 0) { ++ /* EQ set b010000 */ ++ writel(0x009, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x049, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x009, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY0); ++ ++ writel(0x508, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x548, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x508, (void *)HI_SATA_MISC_SATA_PHY0); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY0); ++ } else if (port_no == 1) { ++ /* EQ set b010000 */ ++ writel(0x009, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x049, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x009, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY1); ++ ++ writel(0x508, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x548, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x508, (void *)HI_SATA_MISC_SATA_PHY1); ++ writel(0x0, (void *)HI_SATA_MISC_SATA_PHY1); ++ } ++} ++EXPORT_SYMBOL(hi_sata_set_eq); ++ +diff --git a/drivers/phy/phy-hi35x1d-usb.c b/drivers/phy/phy-hi35x1d-usb.c +new file mode 100644 +index 0000000..2fdf0ba +--- /dev/null ++++ b/drivers/phy/phy-hi35x1d-usb.c +@@ -0,0 +1,350 @@ ++/* ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define USB2_CTRL 0x130 ++#define USB2_BUS_CKEN (1 << 0) ++#define USB2_OHCI48M_CKEN (1 << 1) ++#define USB2_OHCI12M_CKEN (1 << 2) ++#define USB2_HST_PHY_CKEN (1 << 4) ++#define USB2_UTMI0_CKEN (1 << 5) ++#define USB2_UTMI1_CKEN (1 << 6) ++#define USB2_BUS_SRST_REQ (1 << 12) ++#define USB2_UTMI0_SRST_REQ (1 << 13) ++#define USB2_UTMI1_SRST_REQ (1 << 14) ++#define USB2_HST_PHY_SYST_REQ (1 << 16) ++ ++#define REG_USB2_PHY0 0x134 ++#define USB_PHY0_REF_CKEN (1 << 0) ++#define USB_PHY0_SRST_REQ (1 << 8) ++#define USB_PHY0_SRST_TREQ (1 << 9) ++#define USB_PHY1_SRST_TREQ (1 << 10) ++#define USB_PHY0_TEST_SRST_REQ (1 << 11) ++#define USB_PHY0_REFCLK_SEL (1 << 16) ++#ifdef CONFIG_ARCH_HI3531D ++#define USB1_CTRL0 0x90 ++#endif ++#if defined(CONFIG_ARCH_HI3521D) || defined(CONFIG_ARCH_HI3536C) ++#define USB1_CTRL0 0x50 ++#endif ++#define WORDINTERFACE (1 << 0) ++#define SS_BURST4_EN (1 << 7) ++#define SS_BURST8_EN (1 << 8) ++#define SS_BURST16_EN (1 << 9) ++ ++#define USB2_PHY_TEST_REG_ACCESS (1 << 20) ++ ++#define USB2_CTRL1 0x94 ++/* write(0x1 << 5) 0x6 to addr 0x4 */ ++#define CONFIG_CLK ((0x1 << 21) | (0x6 << 8) | (0x4 << 0)) ++ ++extern int otg_usbdev_stat; ++int otg_usbhost_stat; ++EXPORT_SYMBOL(otg_usbhost_stat); ++ ++struct hisi_priv { ++ void __iomem *base; ++ void __iomem *peri_ctrl; /* 0x12040000 */ ++ void __iomem *misc_ctrl; /* 0x12120000 */ ++}; ++ ++static int hisi_usb_phy_on(struct phy *phy) ++{ ++ int reg; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ /* reset enable */ ++ reg = readl(priv->peri_ctrl + USB2_CTRL); ++ reg |= (USB2_BUS_SRST_REQ ++ | USB2_UTMI0_SRST_REQ ++ | USB2_HST_PHY_SYST_REQ); ++#if defined(CONFIG_ARCH_HI3521D) || defined(CONFIG_ARCH_HI3536C) ++ reg |= USB2_UTMI1_SRST_REQ; ++#endif ++ ++ writel(reg, priv->peri_ctrl + USB2_CTRL); ++ udelay(200); ++ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg |= (USB_PHY0_SRST_REQ ++ | USB_PHY0_SRST_TREQ); ++#if defined(CONFIG_ARCH_HI3521D) || defined(CONFIG_ARCH_HI3536C) ++ reg |= USB_PHY1_SRST_TREQ; ++#endif ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(200); ++ reg = readl(priv->misc_ctrl + USB1_CTRL0); ++ reg &= ~(WORDINTERFACE); /* 8bit */ ++ reg &= ~(SS_BURST16_EN); /* 16 bit burst disable */ ++ writel(reg, priv->misc_ctrl + USB1_CTRL0); ++ udelay(100); ++ /* for ssk usb storage ok */ ++ msleep(20); ++ ++ /* open ref clock */ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg |= (USB_PHY0_REF_CKEN); ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(100); ++ ++ /* cancel power on reset */ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg &= ~(USB_PHY0_SRST_REQ); ++ reg &= ~(USB_PHY0_TEST_SRST_REQ); ++ writel(reg , priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(300); ++ ++ /* config type */ ++ reg = readl(priv->misc_ctrl + 0x10); ++ reg |= USB2_PHY_TEST_REG_ACCESS; ++ writel(reg, priv->misc_ctrl + 0x10); ++ udelay(2); ++#if defined(CONFIG_ARCH_HI3521D) || defined(CONFIG_ARCH_HI3536C) ++ /* config clock */ ++ writel(0xc, priv->misc_ctrl + 0x8018); ++ mdelay(2); ++ /* port0 IComp default 400 and disconnect 625mv */ ++ writel(0x1, priv->misc_ctrl + 0x8028); ++ udelay(20); ++ /* port1 IComp default400 and disconnect 625mv */ ++ writel(0x1, priv->misc_ctrl + 0x8428); ++ udelay(20); ++ /* comp 262mv */ ++ writel(0xc, priv->misc_ctrl + 0x8018); ++ udelay(20); ++ writel(0x92, priv->misc_ctrl + 0x8014); ++ udelay(20); ++ /* port0 pre-emphasis to adjust for 000 0x9[5:3] */ ++ writel(0x4, priv->misc_ctrl + 0x8024); ++ udelay(20); ++ /* port1 pre-emphasis to adjust for 000 0x9[5:3] */ ++ writel(0x4, priv->misc_ctrl + 0x8424); ++ udelay(20); ++ /* port 1 pre driver 011 */ ++ writel(0xc4, priv->misc_ctrl + 0x8420); ++ udelay(20); ++ /* port0 pre-emphasis to adjust for 000 0x9[5:3] */ ++ writel(0xc4, priv->misc_ctrl + 0x8020); ++ udelay(20); ++#endif ++#ifdef CONFIG_ARCH_HI3531D ++ /* config clock */ ++ writel(0xc, priv->misc_ctrl + 0x4018); ++ mdelay(2); ++ /* slew rate */ ++ writel(0xc4, priv->misc_ctrl + 0x4020); ++ udelay(20); ++ writel(0xc1, priv->misc_ctrl + 0x4044); ++ udelay(20); ++ /* disconnect */ ++ writel(0x1b, priv->misc_ctrl + 0x4028); ++ udelay(20); ++ writel(0x1c, priv->misc_ctrl + 0x4000); ++ udelay(20); ++ writel(0x92, priv->misc_ctrl + 0x4014); ++ udelay(20); ++ writel(0xe, priv->misc_ctrl + 0x4018); ++ udelay(20); ++ writel(0x4, priv->misc_ctrl + 0x4024); ++ udelay(20); ++#endif ++ /* cancel port reset */ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg &= ~(USB_PHY0_SRST_TREQ); ++#if defined(CONFIG_ARCH_HI3521D) || defined(CONFIG_ARCH_HI3536C) ++ reg &= ~(USB_PHY1_SRST_TREQ); ++#endif ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(300); ++ ++ /* cancel control reset */ ++ reg = readl(priv->peri_ctrl + USB2_CTRL); ++ reg &= ~(USB2_BUS_SRST_REQ ++ | USB2_UTMI0_SRST_REQ ++ | USB2_HST_PHY_SYST_REQ); ++#if defined(CONFIG_ARCH_HI3521D) || defined(CONFIG_ARCH_HI3536C) ++ reg &= ~USB2_UTMI1_SRST_REQ; ++#endif ++ ++ reg |= (USB2_BUS_CKEN ++ | USB2_OHCI48M_CKEN ++ | USB2_OHCI12M_CKEN ++ | USB2_HST_PHY_CKEN ++ | USB2_UTMI0_CKEN); ++#if defined(CONFIG_ARCH_HI3521D) || defined(CONFIG_ARCH_HI3536C) ++ reg |= USB2_UTMI1_CKEN; ++#endif ++ writel(reg, priv->peri_ctrl + USB2_CTRL); ++ udelay(200); ++ ++ return 0; ++} ++ ++static int hisi_usb_phy_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct phy *phy; ++ struct hisi_priv *priv; ++ struct device_node *np = pdev->dev.of_node; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->peri_ctrl = of_iomap(np, 0); /* 0x12040000 */ ++ if (IS_ERR(priv->peri_ctrl)) ++ priv->peri_ctrl = NULL; ++ ++ priv->misc_ctrl = of_iomap(np, 1); /* 0x12120000 */ ++ if (IS_ERR(priv->misc_ctrl)) ++ priv->misc_ctrl = NULL; ++ ++ ++ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); ++ if (!phy) ++ return -ENOMEM; ++ platform_set_drvdata(pdev, phy); ++ phy_set_drvdata(phy, priv); ++ hisi_usb_phy_on(phy); ++ ++ return 0; ++} ++ ++static int hisi_usb_phy_remove(struct platform_device *pdev) ++{ ++#if 1 ++ int reg; ++ struct phy *phy = platform_get_drvdata(pdev); ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg |= (USB_PHY0_SRST_REQ ++ | USB_PHY0_SRST_TREQ); ++#if defined(CONFIG_ARCH_HI3521D) || defined(CONFIG_ARCH_HI3536C) ++ reg |= USB_PHY1_SRST_TREQ; ++#endif ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(100); ++ ++ /* close clock */ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg &= ~(USB_PHY0_REFCLK_SEL ++ | USB_PHY0_REF_CKEN); ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(300); ++ ++ /* close clock */ ++ reg = readl(priv->peri_ctrl + USB2_CTRL); ++ reg &= ~(USB2_BUS_CKEN ++ | USB2_OHCI48M_CKEN ++ | USB2_OHCI12M_CKEN ++ | USB2_HST_PHY_CKEN ++ | USB2_UTMI0_CKEN); ++#if defined(CONFIG_ARCH_HI3521D) || defined(CONFIG_ARCH_HI3536C) ++ reg &= ~USB2_UTMI1_CKEN; ++#endif ++ writel(reg, priv->peri_ctrl + USB2_CTRL); ++ udelay(200); ++#endif ++ return 0; ++} ++ ++static const struct of_device_id hisi_usb_phy_of_match[] = { ++ {.compatible = "hisilicon,hi3531d-usb2-phy",}, ++ {.compatible = "hisilicon,hi3521d-usb2-phy",}, ++ {.compatible = "hisilicon,hi3536c-usb2-phy",}, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, hisi_usb_phy_of_match); ++ ++#ifdef CONFIG_PM_SLEEP ++ ++static int hisi_usb_phy_suspend(struct device *dev) ++{ ++ int reg; ++ struct phy *phy = dev_get_drvdata(dev); ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg |= (USB_PHY0_SRST_REQ ++ | USB_PHY0_SRST_TREQ); ++#if defined(CONFIG_ARCH_HI3521D) || defined(CONFIG_ARCH_HI3536C) ++ reg |= USB_PHY1_SRST_TREQ; ++#endif ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(100); ++ ++ /* close clock */ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg &= ~(USB_PHY0_REFCLK_SEL ++ | USB_PHY0_REF_CKEN); ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(300); ++ ++ /* close clock */ ++ reg = readl(priv->peri_ctrl + USB2_CTRL); ++ reg &= ~(USB2_BUS_CKEN ++ | USB2_OHCI48M_CKEN ++ | USB2_OHCI12M_CKEN ++ | USB2_HST_PHY_CKEN ++ | USB2_UTMI0_CKEN); ++#if defined(CONFIG_ARCH_HI3521D) || defined(CONFIG_ARCH_HI3536C) ++ reg &= ~USB2_UTMI1_CKEN; ++#endif ++ writel(reg, priv->peri_ctrl + USB2_CTRL); ++ udelay(200); ++ ++ return 0; ++} ++ ++static int hisi_usb_phy_resume(struct device *dev) ++{ ++ struct phy *phy = dev_get_drvdata(dev); ++ ++ hisi_usb_phy_on(phy); ++ return 0; ++} ++ ++#endif /* CONFIG_PM_SLEEP */ ++ ++static SIMPLE_DEV_PM_OPS(hisi_usb2_pm_ops, hisi_usb_phy_suspend, ++ hisi_usb_phy_resume); ++ ++static struct platform_driver hisi_usb_phy_driver = { ++ .probe = hisi_usb_phy_probe, ++ .remove = hisi_usb_phy_remove, ++ .driver = { ++ .name = "hisi-usb-phy", ++ .pm = &hisi_usb2_pm_ops, ++ .of_match_table = hisi_usb_phy_of_match, ++ } ++}; ++module_platform_driver(hisi_usb_phy_driver); ++ ++MODULE_AUTHOR("Pengcheng Li "); ++MODULE_DESCRIPTION("HISILICON USB PHY driver"); ++MODULE_ALIAS("platform:hisi-usb-phy"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/phy/phy-hisi-inno-usb2.c b/drivers/phy/phy-hisi-inno-usb2.c +new file mode 100644 +index 0000000..1a50295 +--- /dev/null ++++ b/drivers/phy/phy-hisi-inno-usb2.c +@@ -0,0 +1,489 @@ ++ /* ++ * HiSilicon INNO USB2 PHY Driver. ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define USB2_SWITCH_BASE ioremap_nocache(0x12020150, 0x4) ++#define USB2_OTG_BASE 0x5c ++#define USB2_PHY_SET 0x60 ++#define USB_PHY_REG_ACCESS (0x1 << 16) ++#define DWC_OTG_EN (1 << 31) ++#define USB2_PHY_DPPULL_DOWN (0x3 << 26) ++#define MAX_PORTS 4 ++#define PHY_CLK 0x18 ++ ++#define US2_CRG_BASE 0xb8 ++#define USB2_OHCI48M_CKEN (0x1 << 1) ++#define USB2_OHCI12M_CKEN (0x1 << 2) ++#define USB2_HST_PHY_CKEN (0x1 << 4) ++#define USB2_UTMI0_CKEN (0x1 << 5) ++#define USB2_PHY_CKEN (0x1 << 7) ++#define USB2_BUS_SRST_REQ (0x1 << 8) ++#define USB2_UTMI0_SRST_REQ (0x1 << 9) ++#define USB2_HST_PHY_SRST_REQ (0x1 << 11) ++#define USB2_PHY_REQ (0x1 << 13) ++#define USB2_PHY_PORT0_TREQ (0x1 << 14) ++#define USB2_PHY_CLKSEL (0x1 << 15) ++ ++struct hisi_inno_phy_port { ++ struct clk *utmi_clk; ++ struct reset_control *port_rst; ++ struct reset_control *utmi_rst; ++}; ++ ++struct hisi_inno_phy_priv { ++ void __iomem *peri_ctrl; /* 0x12030000 */ ++ void __iomem *phy_reg; /* 0x120d0000 */ ++ struct clk *ref_clk; ++ struct reset_control *test_rst; ++ struct reset_control *por_rst; ++ struct reg_sequence *reg_seq; ++ u32 reg_num; ++ struct hisi_inno_phy_port *ports; ++ u8 port_num; ++}; ++static struct task_struct *kusbotg_task; ++static int *usb2_switch_base; ++ ++extern void usb2_low_power(int); ++extern int otg_usbdev_stat; ++int otg_usbhost_stat; ++EXPORT_SYMBOL(otg_usbhost_stat); ++static void __iomem *peri_crg; /* 0x12010000 */ ++static void __iomem *sys_ctrl; ++#define SC_SYS_ID 0xEE0 ++ ++void hisi_switch_func(int otg) ++{ ++ int reg; ++ ++ reg = readl(usb2_switch_base); ++ if (otg) { ++ reg |= 0x1; ++ writel(reg, usb2_switch_base); ++ } else { ++ reg &= ~(0x1); ++ writel(reg, usb2_switch_base); ++ } ++} ++EXPORT_SYMBOL(hisi_switch_func); ++ ++void usb2_low_power(int portsc) ++{ ++#ifdef CONFIG_HIUSB_DEVICE2_0 ++ return; ++#else ++ int reg; ++ ++ if (portsc & 0x1) { ++ reg = readl(peri_crg + US2_CRG_BASE); ++ reg |= USB2_PHY_CKEN; ++ writel(reg, peri_crg + US2_CRG_BASE); ++ udelay(100); ++ reg = readl(peri_crg + US2_CRG_BASE); ++ reg &= ~USB2_PHY_REQ; ++ writel(reg, peri_crg + US2_CRG_BASE); ++ mdelay(1); ++ reg = readl(peri_crg + US2_CRG_BASE); ++ reg &= ~USB2_PHY_PORT0_TREQ; ++ writel(reg, peri_crg + US2_CRG_BASE); ++ udelay(10); ++ reg = readl(peri_crg + US2_CRG_BASE); ++ reg &= ~USB2_OHCI48M_CKEN; ++ reg &= ~USB2_OHCI12M_CKEN; ++ reg &= ~USB2_UTMI0_CKEN; ++ writel(reg, peri_crg + US2_CRG_BASE); ++ udelay(10); ++ reg = readl(peri_crg + US2_CRG_BASE); ++ reg &= ~USB2_PHY_CLKSEL; ++ writel(reg, peri_crg + US2_CRG_BASE); ++ udelay(10); ++ reg = readl(peri_crg + US2_CRG_BASE); ++ reg |= USB2_OHCI48M_CKEN; ++ reg |= USB2_OHCI12M_CKEN; ++ reg |= USB2_HST_PHY_CKEN; ++ reg |= USB2_UTMI0_CKEN; ++ writel(reg, peri_crg + US2_CRG_BASE); ++ } else { ++ reg = readl(peri_crg + US2_CRG_BASE); ++ reg &= ~USB2_OHCI48M_CKEN; ++ reg &= ~USB2_OHCI12M_CKEN; ++ reg &= ~USB2_HST_PHY_CKEN; ++ reg &= ~USB2_UTMI0_CKEN; ++ writel(reg, peri_crg + US2_CRG_BASE); ++ reg = readl(peri_crg + US2_CRG_BASE); ++ reg |= USB2_PHY_CLKSEL; ++ writel(reg, peri_crg + US2_CRG_BASE); ++ reg = readl(peri_crg + US2_CRG_BASE); ++ reg |= USB2_OHCI48M_CKEN; ++ reg |= USB2_OHCI12M_CKEN; ++ reg |= USB2_UTMI0_CKEN; ++ writel(reg, peri_crg + US2_CRG_BASE); ++ reg = readl(peri_crg + US2_CRG_BASE); ++ reg |= USB2_PHY_PORT0_TREQ; ++ reg |= USB2_PHY_REQ; ++ reg &= ~USB2_PHY_CKEN; ++ writel(reg, peri_crg + US2_CRG_BASE); ++ } ++#endif ++} ++ ++static int hisi_inno_phy_setup(struct hisi_inno_phy_priv *priv) ++{ ++ int reg; ++ /* config eye */ ++ reg = readl(priv->peri_ctrl + USB2_PHY_SET); ++ reg |= USB_PHY_REG_ACCESS; ++ writel(reg, priv->peri_ctrl + USB2_PHY_SET); ++ writel(0x4, priv->phy_reg + PHY_CLK); ++ mdelay(2); ++ ++ reg = readl(sys_ctrl + SC_SYS_ID); ++ if ((reg >> 24) == 0x4) /* hi3516ev100 */ ++ writel(0x1c, priv->phy_reg); ++ else ++ writel(0x18, priv->phy_reg); ++ udelay(20); ++ writel(0xc4, priv->phy_reg + 0x20); ++ udelay(20); ++ writel(0xc1, priv->phy_reg + 0x44); ++ udelay(20); ++ writel(0x1b, priv->phy_reg + 0x28); ++ udelay(20); ++ ++ return 0; ++} ++ ++static int hisi_inno_port_init(struct hisi_inno_phy_port *port) ++{ ++ int ret = 0; ++ ++ reset_control_deassert(port->port_rst); ++ mdelay(2); ++ ++ ret = clk_prepare_enable(port->utmi_clk); ++ if (ret) ++ return ret; ++ udelay(200); ++ ++ reset_control_deassert(port->utmi_rst); ++ udelay(200); ++ ++ return 0; ++} ++ ++static int hisi_inno_phy_init(struct phy *phy) ++{ ++ struct hisi_inno_phy_priv *priv = phy_get_drvdata(phy); ++ int ret, port; ++ ++ ret = clk_prepare_enable(priv->ref_clk); ++ if (ret) ++ return ret; ++ udelay(100); ++ ++ if (priv->test_rst) { ++ reset_control_deassert(priv->test_rst); ++ udelay(100); ++ } ++ ++ reset_control_deassert(priv->por_rst); ++ udelay(300); ++ ++ /* config phy clk and phy eye diagram */ ++ ret = hisi_inno_phy_setup(priv); ++ if (ret) ++ goto err_disable_ref_clk; ++ ++ for (port = 0; port < priv->port_num; port++) { ++ ret = hisi_inno_port_init(&priv->ports[port]); ++ if (ret) ++ goto err_disable_clks; ++ } ++ ++ return 0; ++ ++err_disable_clks: ++ while (--port >= 0) ++ clk_disable_unprepare(priv->ports[port].utmi_clk); ++err_disable_ref_clk: ++ clk_disable_unprepare(priv->ref_clk); ++ ++ return ret; ++} ++ ++static void hisi_inno_phy_disable(struct phy *phy) ++{ ++ struct hisi_inno_phy_priv *priv = phy_get_drvdata(phy); ++ int i; ++ ++ for (i = 0; i < priv->port_num; i++) ++ clk_disable_unprepare(priv->ports[i].utmi_clk); ++ ++ clk_disable_unprepare(priv->ref_clk); ++} ++ ++static int hisi_inno_phy_of_get_ports(struct device *dev, ++ struct hisi_inno_phy_priv *priv) ++{ ++ struct device_node *node = dev->of_node, *child; ++ int port = 0, ret = 0; ++ ++ priv->port_num = of_get_child_count(node); ++ if (priv->port_num > MAX_PORTS) { ++ dev_err(dev, "too many ports : %d (max = %d)\n", ++ priv->port_num, MAX_PORTS); ++ return -EINVAL; ++ } ++ ++ priv->ports = devm_kcalloc(dev, priv->port_num, ++ sizeof(struct hisi_inno_phy_port), GFP_KERNEL); ++ if (!priv->ports) ++ return -ENOMEM; ++ ++ for_each_child_of_node(node, child) { ++ struct hisi_inno_phy_port *phy_port = &priv->ports[port]; ++ ++ phy_port->utmi_clk = of_clk_get(child, 0); ++ if (IS_ERR(phy_port->utmi_clk)) { ++ ret = PTR_ERR(phy_port->utmi_clk); ++ goto fail; ++ } ++ ++ phy_port->port_rst = of_reset_control_get(child, "port_rst"); ++ if (IS_ERR(phy_port->port_rst)) { ++ ret = PTR_ERR(phy_port->port_rst); ++ clk_put(phy_port->utmi_clk); ++ goto fail; ++ } ++ ++ phy_port->utmi_rst = of_reset_control_get(child, "utmi_rst"); ++ if (IS_ERR(phy_port->utmi_rst)) { ++ ret = PTR_ERR(phy_port->utmi_rst); ++ reset_control_put(phy_port->port_rst); ++ clk_put(phy_port->utmi_clk); ++ goto fail; ++ } ++ port++; ++ } ++ ++ return ret; ++ ++fail: ++ while (--port >= 0) { ++ struct hisi_inno_phy_port *phy_port = &priv->ports[port]; ++ ++ reset_control_put(phy_port->utmi_rst); ++ reset_control_put(phy_port->port_rst); ++ clk_put(phy_port->utmi_clk); ++ } ++ of_node_put(child); ++ ++ return ret; ++} ++ ++/* hiotg run */ ++static void device_to_host(struct hisi_inno_phy_priv *priv) ++{ ++ int reg; ++ ++ reg = readl_relaxed(priv->peri_ctrl + USB2_OTG_BASE); ++ reg |= USB2_PHY_DPPULL_DOWN; ++ reg &= ~DWC_OTG_EN; ++ writel_relaxed(reg, priv->peri_ctrl + USB2_OTG_BASE); ++ ++} ++ ++static void host_to_device(struct hisi_inno_phy_priv *priv) ++{ ++ ++ int reg; ++ ++ reg = readl_relaxed(priv->peri_ctrl + USB2_OTG_BASE); ++ reg &= ~(USB2_PHY_DPPULL_DOWN); ++ reg |= DWC_OTG_EN; ++ writel_relaxed(reg, priv->peri_ctrl + USB2_OTG_BASE); ++ ++} ++ ++int otg_run(struct hisi_inno_phy_priv *priv) ++{ ++ int reg; ++ ++ reg = readl(priv->peri_ctrl + USB2_OTG_BASE); ++ ++ /* device -->host */ ++ if ((reg & DWC_OTG_EN) == DWC_OTG_EN) { ++ ++ if (otg_usbhost_stat == 1) ++ return 0; ++ device_to_host(priv); ++ ++ } else { /* host -->device */ ++ if (otg_usbdev_stat == 1) ++ return 0; ++ ++ host_to_device(priv); ++ } ++ ++ ++ return 0; ++ ++} ++ ++static int usbotg_thread(void *arg) ++{ ++#ifdef CONFIG_USB_AUTO_SWITCH ++ struct hisi_inno_phy_priv *priv = arg; ++ int reg; ++#endif ++ ++ writel(0x0, usb2_switch_base); ++#ifdef CONFIG_USB_AUTO_SWITCH ++ do { ++ reg = readl(usb2_switch_base); ++ if (!(reg & (0x1 << 1))) ++ otg_run(priv); ++ ++ msleep(1000); ++ ++ } while (1); ++#endif ++ ++ return 0; ++} ++ ++ ++static int hisi_inno_phy_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct phy *phy; ++ struct hisi_inno_phy_priv *priv; ++ struct device_node *node = dev->of_node; ++ int ret = 0; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->peri_ctrl = of_iomap(node, 0); /* 0x12030000 */ ++ priv->phy_reg = of_iomap(node, 1); /* 0x120d0000 */ ++ ++#ifdef CONFIG_HIUSB_DEVICE2_0 ++ peri_crg = NULL; ++#else ++ peri_crg = of_iomap(node, 2); /* 0x12010000 */ ++#endif ++ sys_ctrl = of_iomap(node, 3); ++ ++ priv->ref_clk = devm_clk_get(dev, NULL); ++ if (IS_ERR(priv->ref_clk)) ++ return PTR_ERR(priv->ref_clk); ++ ++ priv->por_rst = devm_reset_control_get(dev, "por_rst"); ++ if (IS_ERR(priv->por_rst)) ++ return PTR_ERR(priv->por_rst); ++ ++ priv->test_rst = devm_reset_control_get(dev, "test_rst"); ++ if (IS_ERR(priv->test_rst)) ++ priv->test_rst = NULL; ++ ++ ret = hisi_inno_phy_of_get_ports(dev, priv); ++ if (ret) ++ return ret; ++ ++ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); ++ if (!phy) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, phy); ++ phy_set_drvdata(phy, priv); ++ ret = hisi_inno_phy_init(phy); ++ ++ usb2_switch_base = (int *)USB2_SWITCH_BASE; ++ /* run hiotg */ ++ kusbotg_task = kthread_run(usbotg_thread, priv, "kusbotg"); ++ if (IS_ERR(kusbotg_task)) { ++ dev_err(dev, "can't start kusbotg\n"); ++ ++ return ret; ++ } ++ ++ return ret; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int hisi_inno_phy_suspend(struct device *dev) ++{ ++ struct phy *phy = dev_get_drvdata(dev); ++ ++ hisi_inno_phy_disable(phy); ++ ++ return 0; ++} ++ ++static int hisi_inno_phy_resume(struct device *dev) ++{ ++ struct phy *phy = dev_get_drvdata(dev); ++ int ret = 0; ++ ++ ret = hisi_inno_phy_init(phy); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++#endif /* CONFIG_PM_SLEEP */ ++ ++static const struct dev_pm_ops hisi_inno_phy_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(hisi_inno_phy_suspend, hisi_inno_phy_resume) ++}; ++ ++static const struct of_device_id hisi_inno_phy_of_match[] = { ++ {.compatible = "hisilicon,inno_usb2_phy",}, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, hisi_inno_phy_of_match); ++ ++static struct platform_driver hisi_inno_phy_driver = { ++ .probe = hisi_inno_phy_probe, ++ .driver = { ++ .name = "hisi-inno-phy", ++ .of_match_table = hisi_inno_phy_of_match, ++ .pm = &hisi_inno_phy_pm_ops, ++ } ++}; ++module_platform_driver(hisi_inno_phy_driver); ++ ++MODULE_AUTHOR("Pengcheng Li "); ++MODULE_DESCRIPTION("HISILICON USB PHY driver"); ++MODULE_ALIAS("platform:hisi-usb-phy"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/phy/phy-hisi-nano-phy-sata.c b/drivers/phy/phy-hisi-nano-phy-sata.c +new file mode 100644 +index 0000000..811cdbc +--- /dev/null ++++ b/drivers/phy/phy-hisi-nano-phy-sata.c +@@ -0,0 +1,182 @@ ++/* ++ * Copyright (c) 2016-2017 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int n_ports = CONFIG_HI_SATA_PORTS; ++static int phy_mode = CONFIG_HI_SATA_MODE; ++unsigned int sata_port_map; ++ ++#ifdef MODULE ++module_param(phy_config, uint, 0600); ++MODULE_PARM_DESC(phy_config, "sata phy config (default:0x0e180000)"); ++ ++module_param(n_ports, uint, 0600); ++MODULE_PARM_DESC(n_ports, "sata port number (default:2)"); ++module_param(mode_3g, uint, 0600); ++MODULE_PARM_DESC(phy_mode, "sata phy mode (0:1.5G;1:3G(default);2:6G)"); ++#endif ++ ++#ifdef CONFIG_ARCH_HI3536C ++#include "phy-hi3536c-sata.c" ++#endif ++ ++#ifdef CONFIG_ARCH_HI3521D ++#include "phy-hi3521d-sata.c" ++#endif ++ ++#ifdef CONFIG_ARCH_HI3531D ++#include "phy-hi3531d-sata.c" ++#endif ++ ++static int hisi_sata_phy_init(struct phy *phy) ++{ ++ void __iomem *mmio = phy_get_drvdata(phy); ++#ifdef CONFIG_ARCH_HI3531D ++ int port_num; ++ ++ port_num = hi_sata_port_nr(); ++ if ((port_num < 1) || (port_num > 4)) { ++ pr_err("sata ports number:%d WRONG!!!\n", n_ports); ++ return -EINVAL; ++ } ++ ++ n_ports = port_num; ++#endif ++ ++ hi_sata_poweron(); ++ hi_sata_reset(); ++ hi_sata_phy_reset(); ++ hi_sata_phy_clk_sel(); ++ hi_sata_clk_enable(); ++ msleep(20); ++ hi_sata_phy_unreset(); ++ msleep(20); ++ hi_sata_phy_reg_config(); ++ msleep(20); ++ hi_sata_unreset(); ++ msleep(20); ++ hisata_phy_init(mmio, phy_mode, n_ports); ++ ++ return 0; ++} ++ ++static int hisi_sata_phy_exit(struct phy *phy) ++{ ++ hi_sata_phy_reset(); ++ msleep(20); ++ hi_sata_reset(); ++ msleep(20); ++ hi_sata_clk_reset(); ++ msleep(20); ++ hi_sata_clk_disable(); ++ hi_sata_poweroff(); ++ msleep(20); ++ ++ return 0; ++} ++ ++static struct phy_ops hisi_sata_phy_ops = { ++ .init = hisi_sata_phy_init, ++ .exit = hisi_sata_phy_exit, ++ .owner = THIS_MODULE, ++}; ++ ++static int hisi_sata_phy_probe(struct platform_device *pdev) ++{ ++ struct phy_provider *phy_provider; ++ struct device *dev = &pdev->dev; ++ struct resource *res; ++ struct phy *phy; ++ void __iomem *mmio; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(dev, "failed to get reg base\n"); ++ return -ENOENT; ++ } ++ ++ mmio = devm_ioremap(dev, res->start, resource_size(res)); ++ if (!mmio) ++ return -ENOMEM; ++ ++ phy = devm_phy_create(dev, NULL, &hisi_sata_phy_ops, NULL); ++ if (IS_ERR(phy)) { ++ dev_err(dev, "failed to create PHY\n"); ++ return PTR_ERR(phy); ++ } ++ ++ phy_set_drvdata(phy, mmio); ++ ++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ if (IS_ERR(phy_provider)) ++ return PTR_ERR(phy_provider); ++ ++ return 0; ++} ++ ++static int hisi_sata_phy_suspend(struct platform_device *pdev, ++ pm_message_t state) ++{ ++ struct device *dev = &pdev->dev; ++ struct phy *phy = to_phy(dev); ++ ++ hisi_sata_phy_exit(phy); ++ ++ return 0; ++} ++ ++static int hisi_sata_phy_resume(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct phy *phy = to_phy(dev); ++ ++ hisi_sata_phy_init(phy); ++ ++ return 0; ++} ++ ++static const struct of_device_id hisi_sata_phy_of_match[] = { ++ {.compatible = "hisilicon,hisi-sata-nano-phy",}, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, hisi_sata_phy_of_match); ++ ++static struct platform_driver hisi_sata_phy_driver = { ++ .probe = hisi_sata_phy_probe, ++ .suspend = hisi_sata_phy_suspend, ++ .resume = hisi_sata_phy_resume, ++ .driver = { ++ .name = "hisi-sata-nano-phy", ++ .of_match_table = hisi_sata_phy_of_match, ++ } ++}; ++module_platform_driver(hisi_sata_phy_driver); ++ ++MODULE_AUTHOR("HiSilicon BVT"); ++MODULE_DESCRIPTION("HISILICON SATA NANO PHY driver"); ++MODULE_ALIAS("platform:hisi-sata-nano-phy"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/phy/phy-hisi-usb.c b/drivers/phy/phy-hisi-usb.c +new file mode 100644 +index 0000000..7890c80 +--- /dev/null ++++ b/drivers/phy/phy-hisi-usb.c +@@ -0,0 +1,550 @@ ++/* ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(CONFIG_ARCH_HI3519) || defined(CONFIG_ARCH_HI3519V101) || defined(CONFIG_ARCH_HI3516AV200) ++#ifdef readl ++#undef readl ++#undef readl_relaxed ++#undef writel ++#undef writel_relaxed ++#define readl hi_readl ++#define readl_relaxed hi_readl_relaxed ++#define writel hi_writel ++#define writel_relaxed hi_writel_relaxed ++#endif /* readl */ ++#endif /* defined(CONFIG_ARCH_HI3519) || defined(CONFIG_HI3519V101) || defined(CONFIG_ARCH_HI3516AV200)*/ ++ ++#define USB2_SWITCH_BASE ioremap_nocache(0x12020150, 0x4) ++#define USB2_OTG_BASE 0x78 ++#define DWC_OTG_EN (1 << 31) ++#define USB2_PHY_DPPULL_DOWN (0x3 << 26) ++ ++#define USB2_PHY0_RST 0xb4 ++ ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++#define HI3519_USB2_PHY_REQ BIT(1) ++#define HI3519_USB2_PHY_PORT0_TREQ BIT(2) ++#define HI3519_USB2_CTRL_HUB_REQ BIT(4) ++#define HI3519_USB_CKEN BIT(7) ++#endif ++ ++#if defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) ++#define HI3559_USB2_PHY_REQ BIT(1) ++#define HI3559_USB2_PHY_PORT0_TREQ BIT(2) ++#define HI3559_USB2_CTRL_HUB_REQ BIT(4) ++#define HI3559_USB_CKEN BIT(7) ++#endif ++ ++#ifdef CONFIG_ARCH_HI3516AV200 ++#define HI3516AV200_USB2_PHY_REQ BIT(1) ++#define HI3516AV200_USB2_PHY_PORT0_TREQ BIT(2) ++#define HI3516AV200_USB2_CTRL_HUB_REQ BIT(4) ++#define HI3516AV200_USB_CKEN BIT(7) ++#endif ++ ++#define USB2_PHY0_CTLL 0x80 ++ ++/* HI3536C */ ++#define USB2_CTRL 0x130 ++#define USB2_BUS_CKEN (1 << 0) ++#define USB2_OHCI48M_CKEN (1 << 1) ++#define USB2_OHCI12M_CKEN (1 << 2) ++#define USB2_HST_PHY_CKEN (1 << 4) ++#define USB2_UTMI0_CKEN (1 << 5) ++#define USB2_UTMI1_CKEN (1 << 6) ++#define USB2_BUS_SRST_REQ (1 << 12) ++#define USB2_UTMI0_SRST_REQ (1 << 13) ++#define USB2_UTMI1_SRST_REQ (1 << 14) ++#define USB2_HST_PHY_SYST_REQ (1 << 16) ++ ++#define REG_USB2_PHY0 0x134 ++#define USB_PHY0_REF_CKEN (1 << 0) ++#define USB_PHY0_SRST_REQ (1 << 8) ++#define USB_PHY0_SRST_TREQ (1 << 9) ++#define USB_PHY1_SRST_TREQ (1 << 10) ++#define USB_PHY0_TEST_SRST_REQ (1 << 11) ++#define USB_PHY0_REFCLK_SEL (1 << 16) ++#if (defined(CONFIG_ARCH_HI3536C)) ++#define USB1_CTRL0 0x50 ++#endif ++#define WORDINTERFACE (1 << 0) ++#define SS_BURST4_EN (1 << 7) ++#define SS_BURST8_EN (1 << 8) ++#define SS_BURST16_EN (1 << 9) ++ ++#define USB2_PHY_TEST_REG_ACCESS (1 << 20) ++ ++#define USB2_CTRL1 0x94 ++/* write(0x1 << 5) 0x6 to addr 0x4 */ ++#define CONFIG_CLK ((0x1 << 21) | (0x6 << 8) | (0x4 << 0)) ++/* END HI3536C */ ++ ++#if (!defined(CONFIG_ARCH_HI3536C)) ++static struct task_struct *kusbotg_task; ++static int *usb2_switch_base; ++ ++extern int otg_usbdev_stat; ++int otg_usbhost_stat; ++EXPORT_SYMBOL(otg_usbhost_stat); ++ ++void hisi_switch_func(int otg) ++{ ++ int reg; ++ ++ reg = readl(usb2_switch_base); ++ if (otg) { ++ reg |= 0x1; ++ writel(reg, usb2_switch_base); ++ } else { ++ reg &= ~(0x1); ++ writel(reg, usb2_switch_base); ++ } ++} ++EXPORT_SYMBOL(hisi_switch_func); ++#endif ++struct hisi_priv { ++ void __iomem *base; ++ void __iomem *misc_ctrl; /* 0x12030000 */ ++ void __iomem *peri_ctrl; /* 0x12010000 */ ++}; ++ ++#if (!defined(CONFIG_ARCH_HI3536C)) ++static int hisi_usb_phy_config(struct phy *phy) ++{ ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ writel_relaxed(0x80001c, priv->misc_ctrl + USB2_PHY0_CTLL); ++ writel_relaxed(0xa0001c, priv->misc_ctrl + USB2_PHY0_CTLL); ++ usleep_range(200, 250); ++ ++#if defined(CONFIG_ARCH_HI3519V101) \ ++ || defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) || defined(CONFIG_ARCH_HI3516AV200) ++ writel_relaxed(0x800acb, priv->misc_ctrl + USB2_PHY0_CTLL); ++ writel_relaxed(0xa00acb, priv->misc_ctrl + USB2_PHY0_CTLL); ++ usleep_range(200, 250); ++ ++ writel_relaxed(0x801181, priv->misc_ctrl + USB2_PHY0_CTLL); ++ writel_relaxed(0xa01181, priv->misc_ctrl + USB2_PHY0_CTLL); ++ usleep_range(200, 250); ++ ++ writel_relaxed(0x800592, priv->misc_ctrl + USB2_PHY0_CTLL); ++ writel_relaxed(0xa00592, priv->misc_ctrl + USB2_PHY0_CTLL); ++ usleep_range(200, 250); ++#endif ++ ++ writel_relaxed(0x800904, priv->misc_ctrl + USB2_PHY0_CTLL); ++ writel_relaxed(0xa00904, priv->misc_ctrl + USB2_PHY0_CTLL); ++ usleep_range(200, 250); ++ ++ writel_relaxed(0x80060f, priv->misc_ctrl + USB2_PHY0_CTLL); ++ writel_relaxed(0xa0060f, priv->misc_ctrl + USB2_PHY0_CTLL); ++ usleep_range(200, 250); ++ ++#ifdef CONFIG_ARCH_HI3519 ++ writel_relaxed(0x800a4b, priv->misc_ctrl + USB2_PHY0_CTLL); ++ writel_relaxed(0xa00a4b, priv->misc_ctrl + USB2_PHY0_CTLL); ++ usleep_range(200, 250); ++#endif ++ ++ writel_relaxed(0x801141, priv->misc_ctrl + USB2_PHY0_CTLL); ++ writel_relaxed(0xa01141, priv->misc_ctrl + USB2_PHY0_CTLL); ++ msleep(20); ++ ++ return 0; ++} ++#endif ++ ++static int hisi_usb_phy_on(struct phy *phy) ++{ ++ int reg; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++#if (defined(CONFIG_ARCH_HI3536C)) ++ reg = readl(priv->peri_ctrl + USB2_CTRL); ++ reg |= (USB2_BUS_SRST_REQ ++ | USB2_UTMI0_SRST_REQ ++ | USB2_HST_PHY_SYST_REQ); ++ reg |= USB2_UTMI1_SRST_REQ; ++ writel(reg, priv->peri_ctrl + USB2_CTRL); ++ udelay(200); ++ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg |= (USB_PHY0_SRST_REQ ++ | USB_PHY0_SRST_TREQ); ++ reg |= USB_PHY1_SRST_TREQ; ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(200); ++ reg = readl(priv->misc_ctrl + USB1_CTRL0); ++ reg &= ~(WORDINTERFACE); /* 8bit */ ++ reg &= ~(SS_BURST16_EN); /* 16 bit burst disable */ ++ writel(reg, priv->misc_ctrl + USB1_CTRL0); ++ udelay(100); ++ /* for ssk usb storage ok */ ++ msleep(20); ++ ++ /* open ref clock */ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg |= (USB_PHY0_REF_CKEN); ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(100); ++ ++ /* cancel power on reset */ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg &= ~(USB_PHY0_SRST_REQ); ++ reg &= ~(USB_PHY0_TEST_SRST_REQ); ++ writel(reg , priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(300); ++ ++ /* config type */ ++ reg = readl(priv->misc_ctrl + 0x10); ++ reg |= USB2_PHY_TEST_REG_ACCESS; ++ writel(reg, priv->misc_ctrl + 0x10); ++ udelay(2); ++ /* config clock */ ++ writel(0xc, priv->misc_ctrl + 0x8018); ++ mdelay(2); ++ /* cancel port reset */ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg &= ~(USB_PHY0_SRST_TREQ); ++ reg &= ~(USB_PHY1_SRST_TREQ); ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(300); ++ ++ /* cancel control reset */ ++ reg = readl(priv->peri_ctrl + USB2_CTRL); ++ reg &= ~(USB2_BUS_SRST_REQ ++ | USB2_UTMI0_SRST_REQ ++ | USB2_HST_PHY_SYST_REQ); ++ reg &= ~USB2_UTMI1_SRST_REQ; ++ ++ reg |= (USB2_BUS_CKEN ++ | USB2_OHCI48M_CKEN ++ | USB2_OHCI12M_CKEN ++ | USB2_HST_PHY_CKEN ++ | USB2_UTMI0_CKEN); ++ reg |= USB2_UTMI1_CKEN; ++ writel(reg, priv->peri_ctrl + USB2_CTRL); ++ udelay(200); ++ ++#else ++ reg = readl_relaxed(priv->peri_ctrl + USB2_PHY0_RST); ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++ reg &= ~HI3519_USB2_PHY_REQ; ++ reg &= ~HI3519_USB2_PHY_PORT0_TREQ; ++ reg &= ~HI3519_USB2_CTRL_HUB_REQ; ++ reg |= HI3519_USB_CKEN; ++#endif ++ ++#if defined(CONFIG_ARCH_HI3516AV200) ++ reg &= ~HI3516AV200_USB2_PHY_REQ; ++ reg &= ~HI3516AV200_USB2_PHY_PORT0_TREQ; ++ reg &= ~HI3516AV200_USB2_CTRL_HUB_REQ; ++ reg |= HI3516AV200_USB_CKEN; ++#endif ++ ++#if defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) ++ reg &= ~HI3559_USB2_PHY_REQ; ++ reg &= ~HI3559_USB2_PHY_PORT0_TREQ; ++ reg &= ~HI3559_USB2_CTRL_HUB_REQ; ++ reg |= HI3559_USB_CKEN; ++#endif ++ writel_relaxed(reg, priv->peri_ctrl + USB2_PHY0_RST); ++ mdelay(100); ++ ++ writel_relaxed(0x800000, priv->misc_ctrl + USB2_PHY0_CTLL); ++ mdelay(100); ++ writel_relaxed(0xa0060c, priv->misc_ctrl + USB2_PHY0_CTLL); ++ mdelay(100); ++ ++ hisi_usb_phy_config(phy); ++#endif ++ return 0; ++} ++ ++#if (!defined(CONFIG_ARCH_HI3536C)) ++/* hiotg run */ ++static void device_to_host(struct hisi_priv *priv) ++{ ++ int reg; ++ ++ reg = readl_relaxed(priv->misc_ctrl + USB2_OTG_BASE); ++ reg |= USB2_PHY_DPPULL_DOWN; ++ reg &= ~DWC_OTG_EN; ++ writel_relaxed(reg, priv->misc_ctrl + USB2_OTG_BASE); ++} ++ ++static void host_to_device(struct hisi_priv *priv) ++{ ++ int reg; ++ ++ reg = readl_relaxed(priv->misc_ctrl + USB2_OTG_BASE); ++ reg &= ~(USB2_PHY_DPPULL_DOWN); ++ reg |= DWC_OTG_EN; ++ writel_relaxed(reg, priv->misc_ctrl + USB2_OTG_BASE); ++} ++ ++int otg_run(struct hisi_priv *priv) ++{ ++ int reg; ++ ++ reg = readl(priv->misc_ctrl + USB2_OTG_BASE); ++ ++ /* device -->host */ ++ if ((reg & DWC_OTG_EN) == DWC_OTG_EN) { ++ ++ if (otg_usbhost_stat == 1) ++ return 0; ++ device_to_host(priv); ++ ++ } else { /* host -->device */ ++ if (otg_usbdev_stat == 1) ++ return 0; ++ ++ host_to_device(priv); ++ } ++ ++ ++ return 0; ++ ++} ++ ++static int usbotg_thread(void *arg) ++{ ++#ifdef CONFIG_USB_AUTO_SWITCH ++ struct hisi_priv *priv = arg; ++ int reg; ++#endif ++ ++ ++ writel_relaxed(0x0, usb2_switch_base); ++#ifdef CONFIG_USB_AUTO_SWITCH ++ do { ++ reg = readl_relaxed(usb2_switch_base); ++ if (!(reg & (0x1 << 1))) ++ otg_run(priv); ++ ++ msleep(1000); ++ ++ } while (1); ++#endif ++ ++ return 0; ++} ++#endif ++ ++static int hisi_usb_phy_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct phy *phy; ++ struct hisi_priv *priv; ++ struct device_node *np = pdev->dev.of_node; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->misc_ctrl = of_iomap(np, 0); /* 0x12030000 */ ++ if (IS_ERR(priv->misc_ctrl)) ++ priv->misc_ctrl = NULL; ++ ++ priv->peri_ctrl = of_iomap(np, 1); /* 0x12010000 */ ++ if (IS_ERR(priv->peri_ctrl)) ++ priv->peri_ctrl = NULL; ++ ++ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); ++ if (!phy) ++ return -ENOMEM; ++ platform_set_drvdata(pdev, phy); ++ phy_set_drvdata(phy, priv); ++ hisi_usb_phy_on(phy); ++ ++#if (!defined(CONFIG_ARCH_HI3536C)) ++ usb2_switch_base = (int *)USB2_SWITCH_BASE; ++ /* run hiotg */ ++ kusbotg_task = kthread_run(usbotg_thread, priv, "kusbotg"); ++ if (IS_ERR(kusbotg_task)) { ++ dev_err(dev, "can't start kusbotg\n"); ++ return -1; ++ } ++#endif ++ return 0; ++} ++ ++static int hisi_usb_phy_remove(struct platform_device *pdev) ++{ ++ int reg; ++ struct phy *phy = platform_get_drvdata(pdev); ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++#if (defined(CONFIG_ARCH_HI3536C)) ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg |= (USB_PHY0_SRST_REQ ++ | USB_PHY0_SRST_TREQ); ++ reg |= USB_PHY1_SRST_TREQ; ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(100); ++ ++ /* close clock */ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg &= ~(USB_PHY0_REFCLK_SEL ++ | USB_PHY0_REF_CKEN); ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(300); ++ ++ /* close clock */ ++ reg = readl(priv->peri_ctrl + USB2_CTRL); ++ reg &= ~(USB2_BUS_CKEN ++ | USB2_OHCI48M_CKEN ++ | USB2_OHCI12M_CKEN ++ | USB2_HST_PHY_CKEN ++ | USB2_UTMI0_CKEN); ++ reg &= ~USB2_UTMI1_CKEN; ++ writel(reg, priv->peri_ctrl + USB2_CTRL); ++ udelay(200); ++#else ++ reg = readl_relaxed(priv->peri_ctrl + USB2_PHY0_RST); ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++ reg |= HI3519_USB2_PHY_REQ; ++ reg |= HI3519_USB2_PHY_PORT0_TREQ; ++ reg |= HI3519_USB2_CTRL_HUB_REQ; ++ reg &= ~HI3519_USB_CKEN; ++#endif ++ ++#if defined(CONFIG_ARCH_HI3516AV200) ++ reg |= HI3516AV200_USB2_PHY_REQ; ++ reg |= HI3516AV200_USB2_PHY_PORT0_TREQ; ++ reg |= HI3516AV200_USB2_CTRL_HUB_REQ; ++ reg &= ~HI3516AV200_USB_CKEN; ++#endif ++ ++#if defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) ++ reg |= HI3559_USB2_PHY_REQ; ++ reg |= HI3559_USB2_PHY_PORT0_TREQ; ++ reg |= HI3559_USB2_CTRL_HUB_REQ; ++ reg &= ~HI3559_USB_CKEN; ++#endif ++ writel_relaxed(reg, priv->peri_ctrl + USB2_PHY0_RST); ++ mdelay(100); ++#endif ++ return 0; ++} ++ ++static const struct of_device_id hisi_usb_phy_of_match[] = { ++ {.compatible = "hisilicon,hisi-usb-phy",}, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, hisi_usb_phy_of_match); ++ ++#ifdef CONFIG_PM_SLEEP ++ ++static int hisi_usb_phy_suspend(struct device *dev) ++{ ++ int reg; ++ struct phy *phy = dev_get_drvdata(dev); ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++#if (defined(CONFIG_ARCH_HI3536C)) ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg |= (USB_PHY0_SRST_REQ ++ | USB_PHY0_SRST_TREQ); ++ reg |= USB_PHY1_SRST_TREQ; ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(100); ++ ++ /* close clock */ ++ reg = readl(priv->peri_ctrl + REG_USB2_PHY0); ++ reg &= ~(USB_PHY0_REFCLK_SEL ++ | USB_PHY0_REF_CKEN); ++ writel(reg, priv->peri_ctrl + REG_USB2_PHY0); ++ udelay(300); ++ ++ /* close clock */ ++ reg = readl(priv->peri_ctrl + USB2_CTRL); ++ reg &= ~(USB2_BUS_CKEN ++ | USB2_OHCI48M_CKEN ++ | USB2_OHCI12M_CKEN ++ | USB2_HST_PHY_CKEN ++ | USB2_UTMI0_CKEN); ++ reg &= ~USB2_UTMI1_CKEN; ++ writel(reg, priv->peri_ctrl + USB2_CTRL); ++ udelay(200); ++#else ++ reg = readl_relaxed(priv->peri_ctrl + USB2_PHY0_RST); ++#if (defined CONFIG_ARCH_HI3519 || defined CONFIG_ARCH_HI3519V101) ++ reg |= HI3519_USB2_PHY_REQ; ++ reg |= HI3519_USB2_PHY_PORT0_TREQ; ++ reg |= HI3519_USB2_CTRL_HUB_REQ; ++ reg &= ~HI3519_USB_CKEN; ++#endif ++ ++#if defined(CONFIG_ARCH_HI3516AV200) ++ reg |= HI3516AV200_USB2_PHY_REQ; ++ reg |= HI3516AV200_USB2_PHY_PORT0_TREQ; ++ reg |= HI3516AV200_USB2_CTRL_HUB_REQ; ++ reg &= ~HI3516AV200_USB_CKEN; ++#endif ++ ++#if defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) ++ reg |= HI3559_USB2_PHY_REQ; ++ reg |= HI3559_USB2_PHY_PORT0_TREQ; ++ reg |= HI3559_USB2_CTRL_HUB_REQ; ++ reg &= ~HI3559_USB_CKEN; ++#endif ++ writel_relaxed(reg, priv->peri_ctrl + USB2_PHY0_RST); ++ mdelay(100); ++#endif ++ return 0; ++} ++ ++static int hisi_usb_phy_resume(struct device *dev) ++{ ++ struct phy *phy = dev_get_drvdata(dev); ++ ++ hisi_usb_phy_on(phy); ++ return 0; ++} ++ ++#endif /* CONFIG_PM_SLEEP */ ++ ++static SIMPLE_DEV_PM_OPS(hisi_usb2_pm_ops, hisi_usb_phy_suspend, ++ hisi_usb_phy_resume); ++ ++static struct platform_driver hisi_usb_phy_driver = { ++ .probe = hisi_usb_phy_probe, ++ .remove = hisi_usb_phy_remove, ++ .driver = { ++ .name = "hisi-usb-phy", ++ .pm = &hisi_usb2_pm_ops, ++ .of_match_table = hisi_usb_phy_of_match, ++ } ++}; ++module_platform_driver(hisi_usb_phy_driver); ++ ++MODULE_AUTHOR("Pengcheng Li "); ++MODULE_DESCRIPTION("HISILICON USB PHY driver"); ++MODULE_ALIAS("platform:hisi-usb-phy"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/phy/phy-hisi-usb3.c b/drivers/phy/phy-hisi-usb3.c +new file mode 100644 +index 0000000..f8a6ff27 +--- /dev/null ++++ b/drivers/phy/phy-hisi-usb3.c +@@ -0,0 +1,313 @@ ++/* ++ * Copyright (c) 2015 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(CONFIG_ARCH_HI3519) || defined(CONFIG_ARCH_HI3519V101) || defined(CONFIG_ARCH_HI3516AV200) ++#ifdef readl ++#undef readl ++#undef readl_relaxed ++#undef writel ++#undef writel_relaxed ++#define readl hi_readl ++#define readl_relaxed hi_readl_relaxed ++#define writel hi_writel ++#define writel_relaxed hi_writel_relaxed ++#endif /* readl */ ++#endif /* defined(CONFIG_ARCH_HI3519) || defined(CONFIG_ARCH_HI3519V101) || defined(CONFIG_ARCH_HI3516AV200)*/ ++ ++#define USB3_CTRL 0xb8 ++#define USB3_UTMI_CLKSEL BIT(13) ++#define USB3_UTMI_CLKEN BIT(12) ++#define USB3_PIPE_CLKEN BIT(11) ++#define USB3_SUSPEND_CLKEN BIT(10) ++#define USB3_REF_CLKEN BIT(9) ++#define USB3_BUS_CLKEN BIT(8) ++#define USB3_VCC_SRST_REQ BIT(0) ++ ++#define USB3_COMBPHY 0xac ++#define HI3519_COMBPHY_SRST_REQ BIT(0) ++ ++#define GTXTHRCFG 0xc108 ++#define GRXTHRCFG 0xc10c ++#define REG_GCTL 0xc110 ++#define U2RSTECN (0x1 << 16) ++ ++#define REG_GUSB2PHYCFG0 0xC200 ++#define BIT_UTMI_ULPI (0x1 << 4) ++#define BIT_UTMI_8_16 (0x1 << 3) ++ ++#define REG_GUSB3PIPECTL0 0xc2c0 ++#define PCS_SSP_SOFT_RESET (0x1 << 31) ++#define TX_MARGIN_MASK (0x7 << 3) ++#define TX_MARGIN_VAL (0x2 << 3) ++ ++#define USB2_PHY0_CTLL 0x80 ++ ++#define USB3_PHY 0x88 ++#define COMBO_PHY_TX_DEEMP_MASK (0x7 << 12) ++#define COMBO_PHY_TX_DEEMP_VAL (0x1 << 12) ++#ifdef CONFIG_USB3_DEVICE_GPIO_CTRL ++#define GPIO_MODE __io_address(0x12040000) ++#define GPIO1_DIR __io_address(0x12141400) ++#define GPIO1_IBE __io_address(0x12141408) ++#define GPIO1_IC __io_address(0x1214141c) ++#define GPIO1_IE __io_address(0x12141410) ++#define GPIO1_0_DIR (1<<0) ++#define GPIO1_0_IBE (1<<0) ++#define GPIO1_0_IC (1<<0) ++#define GPIO1_0_IE (1<<0) ++#endif ++struct hisi_priv { ++ void __iomem *base; ++ void __iomem *dwc3_ctrl; /* 0x10180000 */ ++ void __iomem *peri_ctrl; /* 0x12010000 */ ++#if (defined CONFIG_ARCH_HI3519V101 || defined CONFIG_ARCH_HI3559 || defined CONFIG_ARCH_HI3556 || defined CONFIG_ARCH_HI3516AV200) ++ void __iomem *misc_ctrl; /* 0x12030000 */ ++#endif ++}; ++ ++static void hisi_usb3_phy_eye(struct phy *phy) ++{ ++ int reg; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++#if (defined CONFIG_ARCH_HI3519V101 || defined CONFIG_ARCH_HI3559 || defined CONFIG_ARCH_HI3556 || defined CONFIG_ARCH_HI3516AV200) ++ /* djustment LFPS AM */ ++ reg = readl(priv->dwc3_ctrl + REG_GUSB3PIPECTL0); ++ reg &= ~TX_MARGIN_MASK; ++ reg |= TX_MARGIN_VAL; ++ writel(reg, priv->dwc3_ctrl + REG_GUSB3PIPECTL0); ++ ++ /* de-emphasis -3.5dB */ ++ reg = readl(priv->misc_ctrl + USB3_PHY); ++ reg &= ~COMBO_PHY_TX_DEEMP_MASK; ++ reg |= COMBO_PHY_TX_DEEMP_VAL; ++ writel(reg, priv->misc_ctrl + USB3_PHY); ++#endif ++} ++ ++static int hisi_usb3_ctrl_phy_config(struct phy *phy) ++{ ++ int reg; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++#ifdef CONFIG_USB3_DEVICE_GPIO_CTRL ++ /* GPIO mode */ ++ hi_writel(0x0, GPIO_MODE); ++ ++ reg = hi_readl(GPIO1_DIR); ++ reg &= ~GPIO1_0_DIR; ++ hi_writel(reg, GPIO1_DIR); ++ mdelay(20); ++ /* falling edge */ ++ reg = hi_readl(GPIO1_IBE); ++ reg &= ~GPIO1_0_IBE; ++ hi_writel(reg, GPIO1_IBE); ++ mdelay(20); ++ /* clear */ ++ reg = hi_readl(GPIO1_IC); ++ reg |= GPIO1_0_IC; ++ hi_writel(reg, GPIO1_IC); ++ mdelay(20); ++ /* unmask */ ++ reg = hi_readl(GPIO1_IE); ++ reg |= GPIO1_0_IE; ++ hi_writel(reg, GPIO1_IE); ++ mdelay(20); ++#endif ++ reg = readl(priv->dwc3_ctrl + REG_GUSB3PIPECTL0); ++ reg |= PCS_SSP_SOFT_RESET; ++ writel(reg, priv->dwc3_ctrl + REG_GUSB3PIPECTL0); ++ ++ /*step 3: USB2 PHY chose ulpi 8bit interface */ ++ reg = readl(priv->dwc3_ctrl + REG_GUSB2PHYCFG0); ++ reg &= ~BIT_UTMI_ULPI; ++ reg &= ~(BIT_UTMI_8_16); ++ writel(reg, priv->dwc3_ctrl + REG_GUSB2PHYCFG0); ++ mdelay(20); ++ ++ reg = readl(priv->dwc3_ctrl + REG_GCTL); ++ reg &= ~(0x3<<12); ++ reg |= (0x1<<12); /*[13:12] 01: Host; 10: Device; 11: OTG*/ ++ reg &= ~U2RSTECN; ++ writel(reg, priv->dwc3_ctrl + REG_GCTL); ++ mdelay(20); ++ ++ reg = readl(priv->dwc3_ctrl + REG_GUSB3PIPECTL0); ++ reg &= ~PCS_SSP_SOFT_RESET; ++ reg &= ~(1<<17); /* disable suspend */ ++ writel(reg, priv->dwc3_ctrl + REG_GUSB3PIPECTL0); ++ mdelay(100); ++ ++ writel(0x23100000, priv->dwc3_ctrl + GTXTHRCFG); ++ writel(0x23180000, priv->dwc3_ctrl + GRXTHRCFG); ++ mdelay(20); ++ ++ hisi_usb3_phy_eye(phy); ++ ++ return 0; ++} ++ ++static int hisi_usb3_phy_on(struct phy *phy) ++{ ++ int reg; ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ reg = readl_relaxed(priv->peri_ctrl + USB3_CTRL); ++ reg |= USB3_UTMI_CLKSEL; ++ reg |= USB3_UTMI_CLKEN; ++ reg |= USB3_PIPE_CLKEN; ++ reg |= USB3_SUSPEND_CLKEN; ++ reg |= USB3_REF_CLKEN; ++ reg |= USB3_BUS_CLKEN; ++ reg &= ~USB3_VCC_SRST_REQ; ++ writel_relaxed(reg, priv->peri_ctrl + USB3_CTRL); ++ mdelay(10); ++ ++ reg = readl_relaxed(priv->peri_ctrl + USB3_COMBPHY); ++ reg &= ~HI3519_COMBPHY_SRST_REQ; ++ writel_relaxed(reg, priv->peri_ctrl + USB3_COMBPHY); ++ mdelay(10); ++ ++ hisi_usb3_ctrl_phy_config(phy); ++ ++ return 0; ++} ++ ++static int hisi_usb3_phy_power_off(struct device *dev) ++{ ++ int reg; ++ struct phy *phy = dev_get_drvdata(dev); ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ reg = readl_relaxed(priv->peri_ctrl + USB3_COMBPHY); ++ reg |= HI3519_COMBPHY_SRST_REQ; ++ writel_relaxed(reg, priv->peri_ctrl + USB3_COMBPHY); ++ mdelay(100); ++ ++ reg = readl_relaxed(priv->peri_ctrl + USB3_CTRL); ++ reg |= USB3_VCC_SRST_REQ; ++ writel_relaxed(reg, priv->peri_ctrl + USB3_CTRL); ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int hisi_usb3_phy_power_on(struct device *dev) ++{ ++ struct phy *phy = dev_get_drvdata(dev); ++ ++ hisi_usb3_phy_on(phy); ++ ++ return 0; ++} ++ ++static int hisi_usb3_phy_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct phy *phy; ++ struct hisi_priv *priv; ++ struct device_node *np = pdev->dev.of_node; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->dwc3_ctrl = of_iomap(np, 0); ++ if (IS_ERR(priv->dwc3_ctrl)) ++ priv->dwc3_ctrl = NULL; ++ ++ priv->peri_ctrl = of_iomap(np, 1); ++ if (IS_ERR(priv->peri_ctrl)) ++ priv->peri_ctrl = NULL; ++ ++#if (defined CONFIG_ARCH_HI3519V101 || defined CONFIG_ARCH_HI3559 || defined CONFIG_ARCH_HI3556 || defined CONFIG_ARCH_HI3516AV200) ++ priv->misc_ctrl = of_iomap(np, 2); ++ if (IS_ERR(priv->misc_ctrl)) ++ priv->misc_ctrl = NULL; ++#endif ++ ++ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); ++ if (!phy) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, phy); ++ phy_set_drvdata(phy, priv); ++ hisi_usb3_phy_on(phy); ++ ++ return 0; ++} ++ ++static int hisi_usb3_phy_remove(struct platform_device *pdev) ++{ ++ int reg; ++ struct phy *phy = platform_get_drvdata(pdev); ++ struct hisi_priv *priv = phy_get_drvdata(phy); ++ ++ reg = readl_relaxed(priv->peri_ctrl + USB3_CTRL); ++ reg |= USB3_UTMI_CLKSEL; ++ reg &= ~USB3_UTMI_CLKEN; ++ reg &= ~USB3_PIPE_CLKEN; ++ reg &= ~USB3_SUSPEND_CLKEN; ++ reg &= ~USB3_REF_CLKEN; ++ reg &= ~USB3_BUS_CLKEN; ++ reg |= USB3_VCC_SRST_REQ; ++ writel_relaxed(reg, priv->peri_ctrl + USB3_CTRL); ++ mdelay(10); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops hisi_usb3_pmops = { ++ .suspend = hisi_usb3_phy_power_off, ++ .resume = hisi_usb3_phy_power_on, ++#if defined(CONFIG_PM_HIBERNATE) || defined(CONFIG_HISI_SNAPSHOT_BOOT) ++ .freeze = hisi_usb3_phy_power_off, ++ .thaw = hisi_usb3_phy_power_on, ++ .poweroff = hisi_usb3_phy_power_off, ++ .restore = hisi_usb3_phy_power_on, ++#endif ++}; ++ ++static const struct of_device_id hisi_usb3_phy_of_match[] = { ++ {.compatible = "hisilicon,hisi-usb3-phy",}, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, hisi_usb3_phy_of_match); ++ ++static struct platform_driver hisi_usb3_phy_driver = { ++ .probe = hisi_usb3_phy_probe, ++ .remove = hisi_usb3_phy_remove, ++ .driver = { ++ .name = "hisi-usb3-phy", ++ .of_match_table = hisi_usb3_phy_of_match, ++ .pm = &hisi_usb3_pmops, ++ } ++}; ++module_platform_driver(hisi_usb3_phy_driver); ++ ++MODULE_AUTHOR("Pengcheng Li "); ++MODULE_DESCRIPTION("HISILICON USB PHY driver"); ++MODULE_ALIAS("platform:hisi-usb3-phy"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c +index f94467c..7f21f75 100644 +--- a/drivers/platform/x86/acerhdf.c ++++ b/drivers/platform/x86/acerhdf.c +@@ -330,7 +330,8 @@ static int acerhdf_bind(struct thermal_zone_device *thermal, + return 0; + + if (thermal_zone_bind_cooling_device(thermal, 0, cdev, +- THERMAL_NO_LIMIT, THERMAL_NO_LIMIT)) { ++ THERMAL_NO_LIMIT, THERMAL_NO_LIMIT, ++ THERMAL_WEIGHT_DEFAULT)) { + pr_err("error binding cooling dev\n"); + return -EINVAL; + } +diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c +index 62653f5..87a348cc 100644 +--- a/drivers/power/power_supply_sysfs.c ++++ b/drivers/power/power_supply_sysfs.c +@@ -106,7 +106,10 @@ static ssize_t power_supply_show_property(struct device *dev, + else if (off >= POWER_SUPPLY_PROP_MODEL_NAME) + return sprintf(buf, "%s\n", value.strval); + +- return sprintf(buf, "%d\n", value.intval); ++ if (off == POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT) ++ return sprintf(buf, "%lld\n", value.int64val); ++ else ++ return sprintf(buf, "%d\n", value.intval); + } + + static ssize_t power_supply_store_property(struct device *dev, +@@ -197,6 +200,12 @@ static struct device_attribute power_supply_attrs[] = { + POWER_SUPPLY_ATTR(scope), + POWER_SUPPLY_ATTR(charge_term_current), + POWER_SUPPLY_ATTR(calibrate), ++ /* Local extensions */ ++ POWER_SUPPLY_ATTR(usb_hc), ++ POWER_SUPPLY_ATTR(usb_otg), ++ POWER_SUPPLY_ATTR(charge_enabled), ++ /* Local extensions of type int64_t */ ++ POWER_SUPPLY_ATTR(charge_counter_ext), + /* Properties of type `const char *' */ + POWER_SUPPLY_ATTR(model_name), + POWER_SUPPLY_ATTR(manufacturer), +diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig +index ef2dd2e..c6e48b5 100644 +--- a/drivers/pwm/Kconfig ++++ b/drivers/pwm/Kconfig +@@ -110,6 +110,15 @@ config PWM_FSL_FTM + To compile this driver as a module, choose M here: the module + will be called pwm-fsl-ftm. + ++config PWM_HIBVT ++ tristate "HiSilicon BVT PWM support" ++ depends on ARCH_HISI || COMPILE_TEST ++ help ++ Generic PWM framework driver for HiSilicon BVT SoCs. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called pwm-hibvt. ++ + config PWM_IMX + tristate "i.MX PWM support" + depends on ARCH_MXC +diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile +index c458606..e90fbbe 100644 +--- a/drivers/pwm/Makefile ++++ b/drivers/pwm/Makefile +@@ -8,6 +8,7 @@ obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o + obj-$(CONFIG_PWM_CLPS711X) += pwm-clps711x.o + obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o + obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o ++obj-$(CONFIG_PWM_HIBVT) += pwm-hibvt.o + obj-$(CONFIG_PWM_IMX) += pwm-imx.o + obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o + obj-$(CONFIG_PWM_LP3943) += pwm-lp3943.o +diff --git a/drivers/pwm/pwm-hibvt.c b/drivers/pwm/pwm-hibvt.c +new file mode 100644 +index 0000000..89e9fe5 +--- /dev/null ++++ b/drivers/pwm/pwm-hibvt.c +@@ -0,0 +1,246 @@ ++/* ++ * PWM Controller Driver for HiSilicon BVT SoCs ++ * ++ * Copyright (c) 2016 HiSilicon Technologies 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define PWM_CFG0_ADDR(x) (((x) * 0x20) + 0x0) ++#define PWM_CFG1_ADDR(x) (((x) * 0x20) + 0x4) ++#define PWM_CFG2_ADDR(x) (((x) * 0x20) + 0x8) ++#define PWM_CTRL_ADDR(x) (((x) * 0x20) + 0xC) ++ ++#define PWM_ENABLE_SHIFT 0 ++#define PWM_ENABLE_MASK BIT(0) ++ ++#define PWM_POLARITY_SHIFT 1 ++#define PWM_POLARITY_MASK BIT(1) ++ ++#define PWM_KEEP_SHIFT 2 ++#define PWM_KEEP_MASK BIT(2) ++ ++#define PWM_PERIOD_MASK GENMASK(31, 0) ++#define PWM_DUTY_MASK GENMASK(31, 0) ++ ++struct hibvt_pwm_chip { ++ struct pwm_chip chip; ++ struct clk *clk; ++ void __iomem *base; ++ struct reset_control *rstc; ++}; ++ ++struct hibvt_pwm_soc { ++ u32 num_pwms; ++}; ++ ++static const struct hibvt_pwm_soc pwm_soc[2] = { ++ { .num_pwms = 4 }, ++ { .num_pwms = 8 }, ++}; ++ ++static inline struct hibvt_pwm_chip *to_hibvt_pwm_chip(struct pwm_chip *chip) ++{ ++ return container_of(chip, struct hibvt_pwm_chip, chip); ++} ++ ++static void hibvt_pwm_set_bits(void __iomem *base, u32 offset, ++ u32 mask, u32 data) ++{ ++ void __iomem *address = base + offset; ++ u32 value; ++ ++ value = readl(address); ++ value &= ~mask; ++ value |= (data & mask); ++ writel(value, address); ++} ++ ++static int hibvt_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct hibvt_pwm_chip *hi_pwm_chip = to_hibvt_pwm_chip(chip); ++ ++ hibvt_pwm_set_bits(hi_pwm_chip->base, PWM_CTRL_ADDR(pwm->hwpwm), ++ PWM_ENABLE_MASK, 0x1); ++ ++ return 0; ++} ++ ++static void hibvt_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct hibvt_pwm_chip *hi_pwm_chip = to_hibvt_pwm_chip(chip); ++ ++ hibvt_pwm_set_bits(hi_pwm_chip->base, PWM_CTRL_ADDR(pwm->hwpwm), ++ PWM_ENABLE_MASK, 0x0); ++} ++ ++static int hibvt_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, ++ int duty_cycle_ns, int period_ns) ++{ ++ struct hibvt_pwm_chip *hi_pwm_chip = to_hibvt_pwm_chip(chip); ++ u32 freq, period, duty; ++ ++ freq = div_u64(clk_get_rate(hi_pwm_chip->clk), 1000000); ++ ++ period = div_u64(freq * period_ns, 1000); ++ duty = div_u64(period * duty_cycle_ns, period_ns); ++ ++ hibvt_pwm_set_bits(hi_pwm_chip->base, PWM_CFG0_ADDR(pwm->hwpwm), ++ PWM_PERIOD_MASK, period); ++ ++ hibvt_pwm_set_bits(hi_pwm_chip->base, PWM_CFG1_ADDR(pwm->hwpwm), ++ PWM_DUTY_MASK, duty); ++ ++ return 0; ++} ++ ++static int hibvt_pwm_set_polarity(struct pwm_chip *chip, ++ struct pwm_device *pwm, ++ enum pwm_polarity polarity) ++{ ++ struct hibvt_pwm_chip *hi_pwm_chip = to_hibvt_pwm_chip(chip); ++ ++ if (polarity == PWM_POLARITY_INVERSED) ++ hibvt_pwm_set_bits(hi_pwm_chip->base, PWM_CTRL_ADDR(pwm->hwpwm), ++ PWM_POLARITY_MASK, (0x1 << PWM_POLARITY_SHIFT)); ++ else ++ hibvt_pwm_set_bits(hi_pwm_chip->base, PWM_CTRL_ADDR(pwm->hwpwm), ++ PWM_POLARITY_MASK, (0x0 << PWM_POLARITY_SHIFT)); ++ ++ return 0; ++} ++ ++static struct pwm_ops hibvt_pwm_ops = { ++ .enable = hibvt_pwm_enable, ++ .disable = hibvt_pwm_disable, ++ .config = hibvt_pwm_config, ++ .set_polarity = hibvt_pwm_set_polarity, ++ ++ .owner = THIS_MODULE, ++}; ++ ++static const struct of_device_id hibvt_pwm_of_match[] = { ++ { .compatible = "hisilicon,hi3516cv300-pwm", .data = &pwm_soc[0] }, ++ { .compatible = "hisilicon,hi3519v100-pwm", .data = &pwm_soc[1] }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, hibvt_pwm_of_match); ++ ++static int hibvt_pwm_probe(struct platform_device *pdev) ++{ ++ const struct hibvt_pwm_soc *soc; ++ const struct of_device_id *of_id = ++ of_match_device(hibvt_pwm_of_match, &pdev->dev); ++ struct hibvt_pwm_chip *pwm_chip; ++ struct resource *res; ++ int ret; ++ int i; ++ ++ if (!of_id) ++ return -ENODEV; ++ ++ pwm_chip = devm_kzalloc(&pdev->dev, sizeof(*pwm_chip), GFP_KERNEL); ++ if (pwm_chip == NULL) ++ return -ENOMEM; ++ ++ pwm_chip->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(pwm_chip->clk)) { ++ dev_err(&pdev->dev, "getting clock failed with %ld\n", ++ PTR_ERR(pwm_chip->clk)); ++ return PTR_ERR(pwm_chip->clk); ++ } ++ ++ soc = of_id->data; ++ ++ pwm_chip->chip.ops = &hibvt_pwm_ops; ++ pwm_chip->chip.dev = &pdev->dev; ++ pwm_chip->chip.base = -1; ++ pwm_chip->chip.npwm = soc->num_pwms; ++ pwm_chip->chip.of_xlate = of_pwm_xlate_with_flags; ++ pwm_chip->chip.of_pwm_n_cells = 3; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ pwm_chip->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(pwm_chip->base)) ++ return PTR_ERR(pwm_chip->base); ++ ++ ret = clk_prepare_enable(pwm_chip->clk); ++ if (ret < 0) ++ return ret; ++ ++ pwm_chip->rstc = devm_reset_control_get(&pdev->dev, NULL); ++ if (IS_ERR(pwm_chip->rstc)) { ++ clk_disable_unprepare(pwm_chip->clk); ++ return PTR_ERR(pwm_chip->rstc); ++ } ++ ++ reset_control_assert(pwm_chip->rstc); ++ msleep(30); ++ reset_control_deassert(pwm_chip->rstc); ++ ++ ret = pwmchip_add(&pwm_chip->chip); ++ if (ret < 0) { ++ clk_disable_unprepare(pwm_chip->clk); ++ return ret; ++ } ++ ++ for (i = 0; i < pwm_chip->chip.npwm; i++) { ++ hibvt_pwm_set_bits(pwm_chip->base, PWM_CTRL_ADDR(i), ++ PWM_KEEP_MASK, (0x1 << PWM_KEEP_SHIFT)); ++ } ++ ++ platform_set_drvdata(pdev, pwm_chip); ++ ++ return 0; ++} ++ ++static int hibvt_pwm_remove(struct platform_device *pdev) ++{ ++ struct hibvt_pwm_chip *pwm_chip; ++ ++ pwm_chip = platform_get_drvdata(pdev); ++ ++ reset_control_assert(pwm_chip->rstc); ++ msleep(30); ++ reset_control_deassert(pwm_chip->rstc); ++ ++ clk_disable_unprepare(pwm_chip->clk); ++ ++ return pwmchip_remove(&pwm_chip->chip); ++} ++ ++static struct platform_driver hibvt_pwm_driver = { ++ .driver = { ++ .name = "hibvt-pwm", ++ .owner = THIS_MODULE, ++ .of_match_table = hibvt_pwm_of_match, ++ }, ++ .probe = hibvt_pwm_probe, ++ .remove = hibvt_pwm_remove, ++}; ++module_platform_driver(hibvt_pwm_driver); ++ ++MODULE_AUTHOR("Jian Yuan"); ++MODULE_DESCRIPTION("HiSilicon BVT SoCs PWM driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index bc3d80f..9749ec1 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -1715,6 +1715,8 @@ static void regulator_ena_gpio_free(struct regulator_dev *rdev) + gpiod_put(pin->gpiod); + list_del(&pin->list); + kfree(pin); ++ rdev->ena_pin = NULL; ++ return; + } else { + pin->request_count--; + } +diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig +index 6dd12dd..7c88521 100644 +--- a/drivers/rtc/Kconfig ++++ b/drivers/rtc/Kconfig +@@ -701,6 +701,14 @@ endif # SPI_MASTER + + comment "Platform RTC drivers" + ++config RTC_DRV_HIBVT ++ tristate "HiSilicon BVT RTC support" ++ help ++ Generic RTC framework driver for HiSilicon BVT SoCs. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called rtc-hibvt. ++ + # this 'CMOS' RTC driver is arch dependent because + # requires defining CMOS_READ/CMOS_WRITE, and a + # global rtc_lock ... it's not yet just another platform_device. +diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile +index b188323..632f526 100644 +--- a/drivers/rtc/Makefile ++++ b/drivers/rtc/Makefile +@@ -149,3 +149,4 @@ obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o + obj-$(CONFIG_RTC_DRV_XGENE) += rtc-xgene.o + obj-$(CONFIG_RTC_DRV_SIRFSOC) += rtc-sirfsoc.o + obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o ++obj-$(CONFIG_RTC_DRV_HIBVT) += rtc-hibvt.o +diff --git a/drivers/rtc/rtc-hibvt.c b/drivers/rtc/rtc-hibvt.c +new file mode 100644 +index 0000000..28d0bae +--- /dev/null ++++ b/drivers/rtc/rtc-hibvt.c +@@ -0,0 +1,581 @@ ++/* ++ * RTC driver for Hisilicon BVT ++ * Copyright (C) 2016 HiSilicon Technologies 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. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++union u_spi_rw { ++ struct { ++ unsigned int spi_wdata : 8; /* [7:0] */ ++ unsigned int spi_rdata : 8; /* [15:8] */ ++ unsigned int spi_addr : 7; /* [22:16] */ ++ unsigned int spi_rw : 1; /* [23] */ ++ unsigned int spi_start : 1; /* [24] */ ++ unsigned int reserved : 6; /* [30:25] */ ++ unsigned int spi_busy : 1; /* [31] */ ++ } bits; ++ unsigned int u32; ++}; ++ ++#define SPI_CLK_DIV (0x000) ++#define SPI_RW (0x004) ++ ++#define SPI_WRITE (0) ++#define SPI_READ (1) ++ ++/* RTC REG */ ++#define RTC_10MS_COUN 0x00 ++#define RTC_S_COUNT 0x01 ++#define RTC_M_COUNT 0x02 ++#define RTC_H_COUNT 0x03 ++#define RTC_D_COUNT_L 0x04 ++#define RTC_D_COUNT_H 0x05 ++ ++#define RTC_MR_10MS 0x06 ++#define RTC_MR_S 0x07 ++#define RTC_MR_M 0x08 ++#define RTC_MR_H 0x09 ++#define RTC_MR_D_L 0x0A ++#define RTC_MR_D_H 0x0B ++ ++#define RTC_LR_10MS 0x0C ++#define RTC_LR_S 0x0D ++#define RTC_LR_M 0x0E ++#define RTC_LR_H 0x0F ++#define RTC_LR_D_L 0x10 ++#define RTC_LR_D_H 0x11 ++ ++#define RTC_LORD 0x12 ++ ++#define RTC_IMSC 0x13 ++#define RTC_INT_CLR 0x14 ++#define RTC_INT 0x15 ++#define RTC_INT_RAW 0x16 ++ ++#define RTC_CLK 0x17 ++#define RTC_POR_N 0x18 ++#define RTC_SAR_CTRL 0x1A ++#define RTC_CLK_CFG 0x1B ++ ++#define RTC_FREQ_H 0x51 ++#define RTC_FREQ_L 0x52 ++ ++#define FREQ_H_DEFAULT 0x8 ++#define FREQ_L_DEFAULT 0x1B ++ ++#define LV_CTL_DEFAULT 0x01 ++#define CLK_DIV_DEFAULT 0x4 ++#define INT_RST_DEFAULT 0x0 ++#define INT_MSK_DEFAULT 0x4 ++ ++#define AIE_INT_MASK BIT(0) ++#define LV_INT_MASK BIT(1) ++#define REG_LOAD_STAT BIT(0) ++#define REG_LOCK_STAT BIT(1) ++#define REG_LOCK_BYPASS BIT(2) ++ ++#define RETRY_CNT 500 ++ ++#define DATE_TO_SEC(d, h, m, s) (s + m*60 + h*60*60 + d*24*60*60) ++#define SEC_TO_DAY(s) (s/(60*60*24)) ++ ++struct hibvt_rtc { ++ struct rtc_device *rtc_dev; ++ void __iomem *regs; ++ int rtc_irq; ++}; ++ ++static int hibvt_spi_write(void *spi_reg, unsigned char reg, ++ unsigned char val) ++{ ++ union u_spi_rw w_data, r_data; ++ int cnt = RETRY_CNT; ++ ++ r_data.u32 = 0; ++ w_data.u32 = 0; ++ ++ w_data.bits.spi_wdata = val; ++ w_data.bits.spi_addr = reg; ++ w_data.bits.spi_rw = SPI_WRITE; ++ w_data.bits.spi_start = 0x1; ++ ++ writel(w_data.u32, (spi_reg+SPI_RW)); ++ ++ do ++ r_data.u32 = readl(spi_reg+SPI_RW); ++ while (r_data.bits.spi_busy && (--cnt)); ++ ++ if (r_data.bits.spi_busy) ++ return -EIO; ++ ++ return 0; ++} ++ ++ ++static int hibvt_spi_rtc_write(void *spi_reg, unsigned char reg, ++ unsigned char val) ++{ ++ return hibvt_spi_write(spi_reg, reg, val); ++} ++ ++static int hibvt_spi_read(void *spi_reg, unsigned char reg, ++ unsigned char *val) ++{ ++ union u_spi_rw w_data, r_data; ++ int cnt = RETRY_CNT; ++ ++ r_data.u32 = 0; ++ w_data.u32 = 0; ++ w_data.bits.spi_addr = reg; ++ w_data.bits.spi_rw = SPI_READ; ++ w_data.bits.spi_start = 0x1; ++ ++ writel(w_data.u32, (spi_reg+SPI_RW)); ++ ++ do ++ r_data.u32 = readl(spi_reg+SPI_RW); ++ while (r_data.bits.spi_busy && (--cnt)); ++ ++ if (r_data.bits.spi_busy) ++ return -EIO; ++ ++ *val = r_data.bits.spi_rdata; ++ ++ return 0; ++} ++ ++static int hibvt_spi_rtc_read(void *spi_reg, unsigned char reg, ++ unsigned char *val) ++{ ++ return hibvt_spi_read(spi_reg, reg, val); ++} ++ ++static int hibvt_rtc_read_time(struct device *dev, struct rtc_time *time) ++{ ++ struct hibvt_rtc *rtc = dev_get_drvdata(dev); ++ unsigned char dayl, dayh; ++ unsigned char second, minute, hour; ++ unsigned long seconds = 0; ++ unsigned int day; ++ unsigned char raw_value; ++ int cnt = RETRY_CNT; ++ int ret = 0; ++ ++ ret = hibvt_spi_rtc_read(rtc->regs, RTC_INT_RAW, &raw_value); ++ if (ret) { ++ dev_err(dev, "IO err.\n"); ++ return ret; ++ } ++ ++ if (raw_value & LV_INT_MASK) { ++ dev_err(dev, ++ "low voltage detected, date/time is not reliable.\n"); ++ hibvt_spi_write(rtc->regs, RTC_INT_CLR, 1); ++ return -EINVAL; ++ } ++ ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_LORD, &raw_value); ++ if (raw_value & REG_LOCK_BYPASS) ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LORD, ++ (~(REG_LOCK_BYPASS)) & raw_value); ++ ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_LORD, &raw_value); ++ /* lock the time */ ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LORD, ++ (REG_LOCK_STAT) | raw_value); ++ /* wait rtc load flag */ ++ do { ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_LORD, &raw_value); ++ msleep(20); ++ } while ((ret || (raw_value & REG_LOCK_STAT)) && (--cnt)); ++ ++ if (!ret && (raw_value & REG_LOCK_STAT)) ++ return -EBUSY; ++ ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_S_COUNT, &second); ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_M_COUNT, &minute); ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_H_COUNT, &hour); ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_D_COUNT_L, &dayl); ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_D_COUNT_H, &dayh); ++ ++ if (ret) { ++ dev_err(dev, "IO err.\n"); ++ return ret; ++ } ++ ++ day = (dayl | (dayh << 8)); ++ seconds = DATE_TO_SEC(day, hour, minute, second); ++ ++ rtc_time_to_tm(seconds, time); ++ ++ return rtc_valid_tm(time); ++} ++ ++static int hibvt_rtc_set_time(struct device *dev, struct rtc_time *time) ++{ ++ struct hibvt_rtc *rtc = dev_get_drvdata(dev); ++ unsigned char ret = 0; ++ unsigned int days; ++ unsigned long seconds = 0; ++ unsigned int cnt = RETRY_CNT; ++ unsigned char raw_value = 0; ++ ++ ret = rtc_tm_to_time(time, &seconds); ++ if (ret) ++ return ret; ++ days = SEC_TO_DAY(seconds); ++ ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LR_10MS, 0); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LR_S, time->tm_sec); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LR_M, time->tm_min); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LR_H, time->tm_hour); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LR_D_L, (days & 0xFF)); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LR_D_H, (days >> 8)); ++ ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_LORD, ++ (raw_value | REG_LOAD_STAT)); ++ /* wait rtc load flag */ ++ do { ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_LORD, &raw_value); ++ msleep(20); ++ } while ((ret || (raw_value & REG_LOAD_STAT)) && (--cnt)); ++ ++ if (!ret && (raw_value & REG_LOAD_STAT)) ++ return -EBUSY; ++ ++ if (ret) ++ dev_err(dev, "IO err.\n"); ++ ++ return ret; ++} ++ ++static int hibvt_rtc_read_alarm(struct device *dev, ++ struct rtc_wkalrm *alrm) ++{ ++ struct hibvt_rtc *rtc = dev_get_drvdata(dev); ++ unsigned char dayl, dayh; ++ unsigned char second, minute, hour; ++ unsigned long seconds = 0; ++ unsigned int day; ++ unsigned char int_state = 0; ++ int ret = 0; ++ ++ memset(alrm, 0, sizeof(struct rtc_wkalrm)); ++ ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_MR_S, &second); ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_MR_M, &minute); ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_MR_H, &hour); ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_MR_D_L, &dayl); ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_MR_D_H, &dayh); ++ ++ day = (unsigned int)(dayl | (dayh << 8)); ++ seconds = DATE_TO_SEC(day, hour, minute, second); ++ ++ rtc_time_to_tm(seconds, &alrm->time); ++ ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_IMSC, &int_state); ++ if (ret) { ++ dev_err(dev, "IO err.\n"); ++ return ret; ++ } ++ ++ alrm->enabled = !!(int_state & AIE_INT_MASK); ++ alrm->pending = alrm->enabled; ++ ++ return 0; ++} ++ ++static int hibvt_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ++{ ++ struct hibvt_rtc *rtc = dev_get_drvdata(dev); ++ unsigned int days; ++ unsigned long seconds = 0; ++ unsigned char val = 0; ++ int ret = 0; ++ ++ rtc_tm_to_time(&alrm->time, &seconds); ++ ++ days = SEC_TO_DAY(seconds); ++ ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_MR_10MS, 0); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_MR_S, alrm->time.tm_sec); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_MR_M, alrm->time.tm_min); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_MR_H, alrm->time.tm_hour); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_MR_D_L, (days & 0xFF)); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_MR_D_H, (days >> 8)); ++ ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_IMSC, &val); ++ if (alrm->enabled) ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_IMSC, ++ val | AIE_INT_MASK); ++ else ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_IMSC, ++ val & ~AIE_INT_MASK); ++ ++ if (ret) { ++ dev_err(dev, "IO err.\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int hibvt_rtc_alarm_irq_enable(struct device *dev, ++ unsigned int enabled) ++{ ++ struct hibvt_rtc *rtc = dev_get_drvdata(dev); ++ unsigned char val = 0; ++ int ret = 0; ++ ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_IMSC, &val); ++ if (enabled) ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_IMSC, ++ val | AIE_INT_MASK); ++ else ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_IMSC, ++ val & ~AIE_INT_MASK); ++ ++ if (ret) { ++ dev_err(dev, "IO err.\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++ ++/* ++ * interrupt function ++ * do nothing. left for future ++ */ ++static irqreturn_t hibvt_rtc_alm_interrupt(int irq, void *data) ++{ ++ struct hibvt_rtc *rtc = (struct hibvt_rtc *)data; ++ unsigned char val = 0; ++ int ret = 0; ++ ++ ret |= hibvt_spi_read(rtc->regs, RTC_INT, &val); ++ ret |= hibvt_spi_write(rtc->regs, RTC_INT_CLR, AIE_INT_MASK); ++ ++ if (ret) { ++ dev_err(&rtc->rtc_dev->dev, "IO err.\n"); ++ return ret; ++ } ++ ++ if (val & AIE_INT_MASK) ++ rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); ++ ++ return IRQ_HANDLED; ++} ++ ++#define FREQ_MAX_VAL 3277000 ++#define FREQ_MIN_VAL 3276000 ++ ++static int hibvt_rtc_ioctl(struct device *dev, ++ unsigned int cmd, unsigned long arg) ++{ ++ struct hibvt_rtc *rtc = dev_get_drvdata(dev); ++ int ret = 0; ++ ++ switch (cmd) { ++ case RTC_PLL_SET: ++ { ++ char freq_l, freq_h; ++ struct rtc_pll_info pll_info; ++ ++ if (copy_from_user(&pll_info, (struct rtc_pll_info *)arg, ++ sizeof(struct rtc_pll_info))) ++ return -EFAULT; ++ ++ /* freq = 32700 + (freq /3052)*100 */ ++ if (pll_info.pll_value > FREQ_MAX_VAL ++ || pll_info.pll_value < FREQ_MIN_VAL) ++ return -EINVAL; ++ ++ pll_info.pll_value = (pll_info.pll_value - 3270000) ++ * 3052 / 10000; ++ ++ freq_l = (char)(pll_info.pll_value & 0xff); ++ freq_h = (char)((pll_info.pll_value >> 8) & 0xf); ++ ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_FREQ_H, freq_h); ++ ret |= hibvt_spi_rtc_write(rtc->regs, RTC_FREQ_L, freq_l); ++ ++ if (ret) { ++ dev_err(dev, "IO err.\n"); ++ return ret; ++ } ++ ++ return 0; ++ } ++ case RTC_PLL_GET: ++ { ++ char freq_l, freq_h; ++ struct rtc_pll_info pll_info; ++ ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_FREQ_H, &freq_h); ++ ret |= hibvt_spi_rtc_read(rtc->regs, RTC_FREQ_L, &freq_l); ++ ++ if (ret) { ++ dev_err(dev, "IO err.\n"); ++ return ret; ++ } ++ ++ pll_info.pll_value = ((freq_h & 0xf) << 8) + freq_l; ++ pll_info.pll_value = 3270000 ++ + (pll_info.pll_value * 10000) / 3052; ++ ++ pll_info.pll_max = FREQ_MAX_VAL; ++ pll_info.pll_min = FREQ_MIN_VAL; ++ ++ if (copy_to_user((void __user *)arg, ++ &pll_info, sizeof(struct rtc_pll_info))) ++ return -EFAULT; ++ ++ return 0; ++ } ++ default: ++ return -ENOIOCTLCMD; ++ } ++} ++ ++static const struct rtc_class_ops hibvt_rtc_ops = { ++ .read_time = hibvt_rtc_read_time, ++ .set_time = hibvt_rtc_set_time, ++ .read_alarm = hibvt_rtc_read_alarm, ++ .set_alarm = hibvt_rtc_set_alarm, ++ .alarm_irq_enable = hibvt_rtc_alarm_irq_enable, ++ .ioctl = hibvt_rtc_ioctl, ++}; ++ ++static int hibvt_rtc_init(struct hibvt_rtc *rtc) ++{ ++ void *spi_reg = rtc->regs; ++ int ret = 0; ++ unsigned char val = 0; ++ /* ++ * clk div value = (apb_clk/spi_clk)/2-1, ++ * apb clk = 100MHz, spi_clk = 10MHz,so value= 0x4 ++ */ ++ writel(CLK_DIV_DEFAULT, (spi_reg+SPI_CLK_DIV)); ++ ++ ret |= hibvt_spi_rtc_write(spi_reg, RTC_IMSC, INT_MSK_DEFAULT); ++ ret |= hibvt_spi_rtc_write(spi_reg, RTC_SAR_CTRL, LV_CTL_DEFAULT); ++ ++ ++ ret |= hibvt_spi_rtc_write(spi_reg, RTC_CLK_CFG, 0x01); ++ ++ /* default FREQ COEF */ ++ ret |= hibvt_spi_rtc_write(spi_reg, RTC_FREQ_H, FREQ_H_DEFAULT); ++ ret |= hibvt_spi_rtc_write(spi_reg, RTC_FREQ_L, FREQ_L_DEFAULT); ++ ++ ret |= hibvt_spi_rtc_read(spi_reg, RTC_INT_RAW, &val); ++ //ret |= hibvt_spi_rtc_read(spi_reg, RTC_CLK_CFG, &val2); ++ if (ret) { ++ dev_err(&rtc->rtc_dev->dev, "IO err.\n"); ++ return ret; ++ } ++ ++ if (val & LV_INT_MASK) { ++ dev_err(&rtc->rtc_dev->dev, ++ "low voltage detected, date/time is not reliable.\n"); ++ hibvt_spi_write(rtc->regs, RTC_INT_CLR, 1); ++ } ++ ++ return ret; ++} ++ ++static int hibvt_rtc_probe(struct platform_device *pdev) ++{ ++ struct resource *mem; ++ struct hibvt_rtc *rtc; ++ int ret; ++ ++ rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); ++ if (!rtc) ++ return -ENOMEM; ++ ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ rtc->regs = devm_ioremap_resource(&pdev->dev, mem); ++ if (IS_ERR((const void *)rtc->regs)) { ++ dev_err(&pdev->dev, "could not map I/O memory\n"); ++ return PTR_ERR((const void *)rtc->regs); ++ } ++ ++ rtc->rtc_irq = platform_get_irq(pdev, 0); ++ ret = devm_request_irq(&pdev->dev, rtc->rtc_irq, ++ hibvt_rtc_alm_interrupt, 0, pdev->name, rtc); ++ if (ret) { ++ dev_err(&pdev->dev, "could not request irq %d\n", rtc->rtc_irq); ++ return ret; ++ } ++ ++ platform_set_drvdata(pdev, rtc); ++ rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name, ++ &hibvt_rtc_ops, THIS_MODULE); ++ if (IS_ERR(rtc->rtc_dev)) { ++ dev_err(&pdev->dev, "could not register rtc device\n"); ++ return PTR_ERR(rtc->rtc_dev); ++ } ++ ++ if (hibvt_rtc_init(rtc)) { ++ dev_err(&pdev->dev, "hibvt_rtc_init failed.\n"); ++ return -EIO; ++ } ++ ++ dev_info(&pdev->dev, "RTC driver for hibvt enabled\n"); ++ ++ return 0; ++} ++ ++static int hibvt_rtc_remove(struct platform_device *pdev) ++{ ++ return 0; ++} ++ ++static const struct of_device_id hibvt_rtc_match[] = { ++ { .compatible = "hisilicon,hi35xx-rtc" }, ++ {}, ++}; ++ ++static struct platform_driver hibvt_rtc_driver = { ++ .probe = hibvt_rtc_probe, ++ .remove = hibvt_rtc_remove, ++ .driver = { .name = "hibvt_rtc", ++ .of_match_table = hibvt_rtc_match, ++ }, ++}; ++ ++module_platform_driver(hibvt_rtc_driver); ++ ++#define OSDRV_MODULE_VERSION_STRING "HISI_rtc @HiMPP" ++ ++MODULE_AUTHOR("Hisilicon"); ++MODULE_DESCRIPTION("Hisilicon RTC driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_VERSION("HI_VERSION=" OSDRV_MODULE_VERSION_STRING); ++ +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index b1ab509..d0bc88d 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -1491,7 +1491,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q, + if (scsi_host_in_recovery(shost)) + return 0; + +- busy = atomic_inc_return(&shost->host_busy) - 1; ++ busy = atomic_read(&shost->host_busy); + if (atomic_read(&shost->host_blocked) > 0) { + if (busy) + goto starved; +@@ -1500,7 +1500,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q, + * unblock after host_blocked iterates to zero + */ + if (atomic_dec_return(&shost->host_blocked) > 0) +- goto out_dec; ++ goto out; + + SCSI_LOG_MLQUEUE(3, + shost_printk(KERN_INFO, shost, +@@ -1520,6 +1520,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q, + spin_unlock_irq(shost->host_lock); + } + ++ atomic_inc(&shost->host_busy); + return 1; + + starved: +@@ -1527,8 +1528,7 @@ starved: + if (list_empty(&sdev->starved_entry)) + list_add_tail(&sdev->starved_entry, &shost->starved_list); + spin_unlock_irq(shost->host_lock); +-out_dec: +- atomic_dec(&shost->host_busy); ++out: + return 0; + } + +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index 07b2ea1..b34be2a 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -592,6 +592,9 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) + sg_io_hdr_t *hp; + unsigned char cmnd[SG_MAX_CDB_SIZE]; + ++ if (unlikely(segment_eq(get_fs(), KERNEL_DS))) ++ return -EINVAL; ++ + if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) + return -ENXIO; + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, +@@ -787,8 +790,14 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, + return k; /* probably out of space --> ENOMEM */ + } + if (atomic_read(&sdp->detaching)) { +- if (srp->bio) ++ if (srp->bio) { ++ if (srp->rq->cmd != srp->rq->__cmd) ++ kfree(srp->rq->cmd); ++ + blk_end_request_all(srp->rq, -EIO); ++ srp->rq = NULL; ++ } ++ + sg_finish_rem_req(srp); + return -ENODEV; + } +@@ -1013,6 +1022,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) + result = get_user(val, ip); + if (result) + return result; ++ if (val > SG_MAX_CDB_SIZE) ++ return -ENOMEM; + sfp->next_cmd_len = (val > 0) ? val : 0; + return 0; + case SG_GET_VERSION_NUM: +@@ -1785,6 +1796,9 @@ sg_start_req(Sg_request *srp, unsigned char *cmd) + md->from_user = 0; + } + ++ if (unlikely(iov_count > UIO_MAXIOV)) ++ return -EINVAL; ++ + if (iov_count) { + int len, size = sizeof(struct sg_iovec) * iov_count; + struct iovec *iov; +diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c +index 11e1834..f295a8a 100644 +--- a/drivers/spi/spi-pl022.c ++++ b/drivers/spi/spi-pl022.c +@@ -43,6 +43,7 @@ + #include + #include + #include ++#include + + /* + * This macro is used to define some register default values. +@@ -137,6 +138,13 @@ + #define SSP_CR1_MASK_FBCLKDEL_ST (0x7UL << 13) + + /* ++ * The Hisilicon version of this block adds some bits ++ * in SSP_CR1 ++ */ ++#define SSP_CR1_MASK_BIGEND_HISI (0x1UL << 4) ++#define SSP_CR1_MASK_ALTASENS_HISI (0x1UL << 6) ++ ++/* + * SSP Status Register - SSP_SR + */ + #define SSP_SR_MASK_TFE (0x1UL << 0) /* Transmit FIFO empty */ +@@ -291,6 +299,8 @@ + + #define SPI_POLLING_TIMEOUT 1000 + ++#define PL022_IDS_INDEX_HISI 4 ++ + /* + * The type of reading going on on this chip + */ +@@ -332,6 +342,13 @@ struct vendor_data { + bool internal_cs_ctrl; + }; + ++struct cs_data { ++ struct resource res; ++ void __iomem *virt_addr; ++ unsigned int cs_sb; ++ unsigned int cs_mask_bit; ++}; ++ + /** + * struct pl022 - This is the private SSP driver data structure + * @adev: AMBA device model hookup +@@ -405,6 +422,7 @@ struct pl022 { + #endif + int cur_cs; + int *chipselects; ++ struct cs_data *cs_data; + }; + + /** +@@ -461,13 +479,37 @@ static void null_cs_control(u32 command) + static void internal_cs_control(struct pl022 *pl022, u32 command) + { + u32 tmp; ++ struct amba_device *adev = pl022->adev; ++ struct amba_driver *adrv = container_of(adev->dev.driver, ++ struct amba_driver, drv); ++ ++ if (pl022->vendor->extended_cr && (adev->periphid == ++ adrv->id_table[PL022_IDS_INDEX_HISI].id)) { ++ if (pl022->cs_data) { ++ tmp = readl(pl022->cs_data->virt_addr); ++ tmp &= ~(pl022->cs_data->cs_mask_bit); ++ tmp |= ((u32)pl022->cur_cs) << pl022->cs_data->cs_sb; ++ writel(tmp, pl022->cs_data->virt_addr); ++ } + +- tmp = readw(SSP_CSR(pl022->virtbase)); +- if (command == SSP_CHIP_SELECT) +- tmp &= ~BIT(pl022->cur_cs); +- else +- tmp |= BIT(pl022->cur_cs); +- writew(tmp, SSP_CSR(pl022->virtbase)); ++ if (command == SSP_CHIP_SELECT) ++ /* Enable SSP */ ++ writew((readw(SSP_CR1(pl022->virtbase)) | ++ SSP_CR1_MASK_SSE), ++ SSP_CR1(pl022->virtbase)); ++ else ++ /* disable SSP */ ++ writew((readw(SSP_CR1(pl022->virtbase)) & ++ (~SSP_CR1_MASK_SSE)), ++ SSP_CR1(pl022->virtbase)); ++ } else { ++ tmp = readw(SSP_CSR(pl022->virtbase)); ++ if (command == SSP_CHIP_SELECT) ++ tmp &= ~BIT((u32)pl022->cur_cs); ++ else ++ tmp |= BIT((u32)pl022->cur_cs); ++ writew(tmp, SSP_CSR(pl022->virtbase)); ++ } + } + + static void pl022_cs_control(struct pl022 *pl022, u32 command) +@@ -568,8 +610,12 @@ static int flush(struct pl022 *pl022) + static void restore_state(struct pl022 *pl022) + { + struct chip_data *chip = pl022->cur_chip; ++ struct amba_device *adev = pl022->adev; ++ struct amba_driver *adrv = container_of(adev->dev.driver, ++ struct amba_driver, drv); + +- if (pl022->vendor->extended_cr) ++ if (pl022->vendor->extended_cr && (adev->periphid != ++ adrv->id_table[PL022_IDS_INDEX_HISI].id)) + writel(chip->cr0, SSP_CR0(pl022->virtbase)); + else + writew(chip->cr0, SSP_CR0(pl022->virtbase)); +@@ -642,6 +688,13 @@ static void restore_state(struct pl022 *pl022) + GEN_MASK_BITS(SSP_FEEDBACK_CLK_DELAY_NONE, SSP_CR1_MASK_FBCLKDEL_ST, 13) \ + ) + ++/* Hisilicon versions extend this register to use all 16 bits */ ++#define DEFAULT_SSP_REG_CR1_HISI ( \ ++ DEFAULT_SSP_REG_CR1 | \ ++ GEN_MASK_BITS(SSP_RX_MSB, SSP_CR1_MASK_BIGEND_HISI, 4) | \ ++ GEN_MASK_BITS(0x1, SSP_CR1_MASK_ALTASENS_HISI, 6) \ ++) ++ + #define DEFAULT_SSP_REG_CPSR ( \ + GEN_MASK_BITS(SSP_DEFAULT_PRESCALE, SSP_CPSR_MASK_CPSDVSR, 0) \ + ) +@@ -657,12 +710,24 @@ static void restore_state(struct pl022 *pl022) + */ + static void load_ssp_default_config(struct pl022 *pl022) + { ++ struct amba_device *adev = pl022->adev; ++ struct amba_driver *adrv = container_of(adev->dev.driver, ++ struct amba_driver, drv); ++ + if (pl022->vendor->pl023) { + writel(DEFAULT_SSP_REG_CR0_ST_PL023, SSP_CR0(pl022->virtbase)); + writew(DEFAULT_SSP_REG_CR1_ST_PL023, SSP_CR1(pl022->virtbase)); + } else if (pl022->vendor->extended_cr) { +- writel(DEFAULT_SSP_REG_CR0_ST, SSP_CR0(pl022->virtbase)); +- writew(DEFAULT_SSP_REG_CR1_ST, SSP_CR1(pl022->virtbase)); ++ if (adev->periphid == adrv->id_table[PL022_IDS_INDEX_HISI].id) { ++ writew(DEFAULT_SSP_REG_CR0, SSP_CR0(pl022->virtbase)); ++ writew(DEFAULT_SSP_REG_CR1_HISI, ++ SSP_CR1(pl022->virtbase)); ++ } else { ++ writel(DEFAULT_SSP_REG_CR0_ST, ++ SSP_CR0(pl022->virtbase)); ++ writew(DEFAULT_SSP_REG_CR1_ST, ++ SSP_CR1(pl022->virtbase)); ++ } + } else { + writew(DEFAULT_SSP_REG_CR0, SSP_CR0(pl022->virtbase)); + writew(DEFAULT_SSP_REG_CR1, SSP_CR1(pl022->virtbase)); +@@ -1830,6 +1895,10 @@ static int pl022_setup(struct spi_device *spi) + unsigned int bits = spi->bits_per_word; + u32 tmp; + struct device_node *np = spi->dev.of_node; ++ struct amba_device *adev = pl022->adev; ++ struct amba_driver *adrv = container_of(adev->dev.driver, ++ struct amba_driver, drv); ++ + + if (!spi->max_speed_hz) + return -EINVAL; +@@ -1972,7 +2041,8 @@ static int pl022_setup(struct spi_device *spi) + chip->cpsr = clk_freq.cpsdvsr; + + /* Special setup for the ST micro extended control registers */ +- if (pl022->vendor->extended_cr) { ++ if (pl022->vendor->extended_cr && (adev->periphid != ++ adrv->id_table[PL022_IDS_INDEX_HISI].id)) { + u32 etx; + + if (pl022->vendor->pl023) { +@@ -2006,6 +2076,20 @@ static int pl022_setup(struct spi_device *spi) + SSP_CR1_MASK_RXIFLSEL_ST, 7); + SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig, + SSP_CR1_MASK_TXIFLSEL_ST, 10); ++ } else if (pl022->vendor->extended_cr && (adev->periphid == ++ adrv->id_table[PL022_IDS_INDEX_HISI].id)) { ++ SSP_WRITE_BITS(chip->cr0, bits - 1, ++ SSP_CR0_MASK_DSS, 0); ++ SSP_WRITE_BITS(chip->cr0, chip_info->iface, ++ SSP_CR0_MASK_FRF, 4); ++ ++ if (spi->mode & SPI_LSB_FIRST) ++ tmp = !!SPI_LSB_FIRST; ++ else ++ tmp = !SPI_LSB_FIRST; ++ ++ SSP_WRITE_BITS(chip->cr1, tmp, SSP_CR1_MASK_BIGEND_HISI, 4); ++ SSP_WRITE_BITS(chip->cr1, 0x1, SSP_CR1_MASK_ALTASENS_HISI, 6); + } else { + SSP_WRITE_BITS(chip->cr0, bits - 1, + SSP_CR0_MASK_DSS, 0); +@@ -2037,7 +2121,7 @@ static int pl022_setup(struct spi_device *spi) + } + SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1); + SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2); +- SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, ++ SSP_WRITE_BITS(chip->cr1, (unsigned int)chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, + 3); + + /* Save controller_state */ +@@ -2069,7 +2153,7 @@ pl022_platform_data_dt_get(struct device *dev) + { + struct device_node *np = dev->of_node; + struct pl022_ssp_controller *pd; +- u32 tmp; ++ u32 tmp = 0; + + if (!np) { + dev_err(dev, "no dt node defined\n"); +@@ -2094,6 +2178,8 @@ pl022_platform_data_dt_get(struct device *dev) + static int pl022_probe(struct amba_device *adev, const struct amba_id *id) + { + struct device *dev = &adev->dev; ++ struct amba_driver *adrv = container_of(adev->dev.driver, ++ struct amba_driver, drv); + struct pl022_ssp_controller *platform_info = + dev_get_platdata(&adev->dev); + struct spi_master *master; +@@ -2157,6 +2243,41 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) + } else if (pl022->vendor->internal_cs_ctrl) { + for (i = 0; i < num_cs; i++) + pl022->chipselects[i] = i; ++ ++ if ((adev->periphid == adrv->id_table[PL022_IDS_INDEX_HISI].id) ++ && pl022->vendor->extended_cr ++ && (num_cs > 1)) { ++ pl022->cs_data = devm_kzalloc(dev, ++ sizeof(struct cs_data), ++ GFP_KERNEL); ++ if (!pl022->cs_data) { ++ status = -ENOMEM; ++ goto err_no_mem; ++ } ++ ++ if (of_address_to_resource(np, 1, ++ &pl022->cs_data->res)) { ++ status = -EPROBE_DEFER; ++ goto err_no_gpio; ++ } ++ ++ if (of_property_read_u32(np, "hisi,spi_cs_sb", ++ &pl022->cs_data->cs_sb)) { ++ status = -EPROBE_DEFER; ++ goto err_no_gpio; ++ } ++ ++ if (of_property_read_u32(np, "hisi,spi_cs_mask_bit", ++ &pl022->cs_data->cs_mask_bit)) { ++ status = -EPROBE_DEFER; ++ goto err_no_gpio; ++ } ++ ++ pl022->cs_data->virt_addr = devm_ioremap(dev, ++ pl022->cs_data->res.start, ++ resource_size(&adev->res)); ++ } else ++ pl022->cs_data = NULL; + } else if (IS_ENABLED(CONFIG_OF)) { + for (i = 0; i < num_cs; i++) { + int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); +@@ -2279,6 +2400,10 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) + err_no_ioremap: + amba_release_regions(adev); + err_no_ioregion: ++ if (pl022->cs_data) ++ release_mem_region(pl022->cs_data->res.start, ++ resource_size(&pl022->cs_data->res)); ++ + err_no_gpio: + err_no_mem: + spi_master_put(master); +@@ -2305,6 +2430,10 @@ pl022_remove(struct amba_device *adev) + + clk_disable_unprepare(pl022->clk); + amba_release_regions(adev); ++ if (pl022->cs_data) ++ release_mem_region(pl022->cs_data->res.start, ++ resource_size(&pl022->cs_data->res)); ++ + tasklet_disable(&pl022->pump_transfers); + return 0; + } +@@ -2420,6 +2549,16 @@ static struct vendor_data vendor_lsi = { + .internal_cs_ctrl = true, + }; + ++static struct vendor_data vendor_hisi = { ++ .fifodepth = 256, ++ .max_bpw = 16, ++ .unidir = false, ++ .extended_cr = true, ++ .pl023 = false, ++ .loopback = true, ++ .internal_cs_ctrl = true, ++}; ++ + static struct amba_id pl022_ids[] = { + { + /* +@@ -2460,6 +2599,15 @@ static struct amba_id pl022_ids[] = { + .mask = 0x000fffff, + .data = &vendor_lsi, + }, ++ { ++ /* ++ * Hisilicon derivative, this has a 16bit wide ++ * and 256 locations deep TX/RX FIFO ++ */ ++ .id = 0x00800022, ++ .mask = 0xffffffff, ++ .data = &vendor_hisi, ++ }, + { 0, 0 }, + }; + +diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig +index 7a0e288..21bc8ec 100644 +--- a/drivers/staging/android/Kconfig ++++ b/drivers/staging/android/Kconfig +@@ -44,23 +44,6 @@ config ASHMEM + It is, in theory, a good memory allocator for low-memory devices, + because it can discard shared memory units when under memory pressure. + +-config ANDROID_LOGGER +- tristate "Android log driver" +- default n +- ---help--- +- This adds support for system-wide logging using four log buffers. +- +- These are: +- +- 1: main +- 2: events +- 3: radio +- 4: system +- +- Log reading and writing is performed via normal Linux reads and +- optimized writes. This optimization avoids logging having too +- much overhead in the system. +- + config ANDROID_TIMED_OUTPUT + bool "Timed output class driver" + default y +@@ -75,14 +58,14 @@ config ANDROID_LOW_MEMORY_KILLER + ---help--- + Registers processes to be killed when memory is low + +-config ANDROID_INTF_ALARM_DEV +- tristate "Android alarm driver" +- depends on RTC_CLASS +- default n ++config ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES ++ bool "Android Low Memory Killer: detect oom_adj values" ++ depends on ANDROID_LOW_MEMORY_KILLER ++ default y + ---help--- +- Provides non-wakeup and rtc backed wakeup alarms based on rtc or +- elapsed realtime, and a non-wakeup alarm on the monotonic clock. +- Also exports the alarm interface to user-space. ++ Detect oom_adj values written to ++ /sys/module/lowmemorykiller/parameters/adj and convert them ++ to oom_score_adj values. + + config SYNC + bool "Synchronization framework" +@@ -114,6 +97,8 @@ config SW_SYNC_USER + + source "drivers/staging/android/ion/Kconfig" + ++source "drivers/staging/android/fiq_debugger/Kconfig" ++ + endif # if ANDROID + + endmenu +diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile +index 517ad5f..b7b9980 100644 +--- a/drivers/staging/android/Makefile ++++ b/drivers/staging/android/Makefile +@@ -1,13 +1,12 @@ + ccflags-y += -I$(src) # needed for trace events + + obj-y += ion/ ++obj-$(CONFIG_FIQ_DEBUGGER) += fiq_debugger/ + + obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o + obj-$(CONFIG_ASHMEM) += ashmem.o +-obj-$(CONFIG_ANDROID_LOGGER) += logger.o + obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o + obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o + obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o +-obj-$(CONFIG_ANDROID_INTF_ALARM_DEV) += alarm-dev.o + obj-$(CONFIG_SYNC) += sync.o sync_debug.o + obj-$(CONFIG_SW_SYNC) += sw_sync.o +diff --git a/drivers/staging/android/TODO b/drivers/staging/android/TODO +deleted file mode 100644 +index b15fb0d..0000000 +--- a/drivers/staging/android/TODO ++++ /dev/null +@@ -1,10 +0,0 @@ +-TODO: +- - checkpatch.pl cleanups +- - sparse fixes +- - rename files to be not so "generic" +- - make sure things build as modules properly +- - add proper arch dependencies as needed +- - audit userspace interfaces to make sure they are sane +- +-Please send patches to Greg Kroah-Hartman and Cc: +-Brian Swetland +diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c +deleted file mode 100644 +index ff4b3e8..0000000 +--- a/drivers/staging/android/alarm-dev.c ++++ /dev/null +@@ -1,446 +0,0 @@ +-/* drivers/rtc/alarm-dev.c +- * +- * Copyright (C) 2007-2009 Google, 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. +- * +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include "android_alarm.h" +- +-#define ANDROID_ALARM_PRINT_INFO (1U << 0) +-#define ANDROID_ALARM_PRINT_IO (1U << 1) +-#define ANDROID_ALARM_PRINT_INT (1U << 2) +- +-static int debug_mask = ANDROID_ALARM_PRINT_INFO; +-module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); +- +-#define alarm_dbg(debug_level_mask, fmt, ...) \ +-do { \ +- if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) \ +- pr_info(fmt, ##__VA_ARGS__); \ +-} while (0) +- +-#define ANDROID_ALARM_WAKEUP_MASK ( \ +- ANDROID_ALARM_RTC_WAKEUP_MASK | \ +- ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK) +- +-static int alarm_opened; +-static DEFINE_SPINLOCK(alarm_slock); +-static struct wakeup_source alarm_wake_lock; +-static DECLARE_WAIT_QUEUE_HEAD(alarm_wait_queue); +-static uint32_t alarm_pending; +-static uint32_t alarm_enabled; +-static uint32_t wait_pending; +- +-struct devalarm { +- union { +- struct hrtimer hrt; +- struct alarm alrm; +- } u; +- enum android_alarm_type type; +-}; +- +-static struct devalarm alarms[ANDROID_ALARM_TYPE_COUNT]; +- +-/** +- * is_wakeup() - Checks to see if this alarm can wake the device +- * @type: The type of alarm being checked +- * +- * Return: 1 if this is a wakeup alarm, otherwise 0 +- */ +-static int is_wakeup(enum android_alarm_type type) +-{ +- return type == ANDROID_ALARM_RTC_WAKEUP || +- type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP; +-} +- +-static void devalarm_start(struct devalarm *alrm, ktime_t exp) +-{ +- if (is_wakeup(alrm->type)) +- alarm_start(&alrm->u.alrm, exp); +- else +- hrtimer_start(&alrm->u.hrt, exp, HRTIMER_MODE_ABS); +-} +- +-static int devalarm_try_to_cancel(struct devalarm *alrm) +-{ +- if (is_wakeup(alrm->type)) +- return alarm_try_to_cancel(&alrm->u.alrm); +- return hrtimer_try_to_cancel(&alrm->u.hrt); +-} +- +-static void devalarm_cancel(struct devalarm *alrm) +-{ +- if (is_wakeup(alrm->type)) +- alarm_cancel(&alrm->u.alrm); +- else +- hrtimer_cancel(&alrm->u.hrt); +-} +- +-static void alarm_clear(enum android_alarm_type alarm_type) +-{ +- uint32_t alarm_type_mask = 1U << alarm_type; +- unsigned long flags; +- +- spin_lock_irqsave(&alarm_slock, flags); +- alarm_dbg(IO, "alarm %d clear\n", alarm_type); +- devalarm_try_to_cancel(&alarms[alarm_type]); +- if (alarm_pending) { +- alarm_pending &= ~alarm_type_mask; +- if (!alarm_pending && !wait_pending) +- __pm_relax(&alarm_wake_lock); +- } +- alarm_enabled &= ~alarm_type_mask; +- spin_unlock_irqrestore(&alarm_slock, flags); +-} +- +-static void alarm_set(enum android_alarm_type alarm_type, +- struct timespec *ts) +-{ +- uint32_t alarm_type_mask = 1U << alarm_type; +- unsigned long flags; +- +- spin_lock_irqsave(&alarm_slock, flags); +- alarm_dbg(IO, "alarm %d set %ld.%09ld\n", +- alarm_type, ts->tv_sec, ts->tv_nsec); +- alarm_enabled |= alarm_type_mask; +- devalarm_start(&alarms[alarm_type], timespec_to_ktime(*ts)); +- spin_unlock_irqrestore(&alarm_slock, flags); +-} +- +-static int alarm_wait(void) +-{ +- unsigned long flags; +- int rv = 0; +- +- spin_lock_irqsave(&alarm_slock, flags); +- alarm_dbg(IO, "alarm wait\n"); +- if (!alarm_pending && wait_pending) { +- __pm_relax(&alarm_wake_lock); +- wait_pending = 0; +- } +- spin_unlock_irqrestore(&alarm_slock, flags); +- +- rv = wait_event_interruptible(alarm_wait_queue, alarm_pending); +- if (rv) +- return rv; +- +- spin_lock_irqsave(&alarm_slock, flags); +- rv = alarm_pending; +- wait_pending = 1; +- alarm_pending = 0; +- spin_unlock_irqrestore(&alarm_slock, flags); +- +- return rv; +-} +- +-static int alarm_set_rtc(struct timespec *ts) +-{ +- struct rtc_time new_rtc_tm; +- struct rtc_device *rtc_dev; +- unsigned long flags; +- int rv = 0; +- +- rtc_time_to_tm(ts->tv_sec, &new_rtc_tm); +- rtc_dev = alarmtimer_get_rtcdev(); +- rv = do_settimeofday(ts); +- if (rv < 0) +- return rv; +- if (rtc_dev) +- rv = rtc_set_time(rtc_dev, &new_rtc_tm); +- +- spin_lock_irqsave(&alarm_slock, flags); +- alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK; +- wake_up(&alarm_wait_queue); +- spin_unlock_irqrestore(&alarm_slock, flags); +- +- return rv; +-} +- +-static int alarm_get_time(enum android_alarm_type alarm_type, +- struct timespec *ts) +-{ +- int rv = 0; +- +- switch (alarm_type) { +- case ANDROID_ALARM_RTC_WAKEUP: +- case ANDROID_ALARM_RTC: +- getnstimeofday(ts); +- break; +- case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP: +- case ANDROID_ALARM_ELAPSED_REALTIME: +- get_monotonic_boottime(ts); +- break; +- case ANDROID_ALARM_SYSTEMTIME: +- ktime_get_ts(ts); +- break; +- default: +- rv = -EINVAL; +- } +- return rv; +-} +- +-static long alarm_do_ioctl(struct file *file, unsigned int cmd, +- struct timespec *ts) +-{ +- int rv = 0; +- unsigned long flags; +- enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd); +- +- if (alarm_type >= ANDROID_ALARM_TYPE_COUNT) +- return -EINVAL; +- +- if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) { +- if ((file->f_flags & O_ACCMODE) == O_RDONLY) +- return -EPERM; +- if (file->private_data == NULL && +- cmd != ANDROID_ALARM_SET_RTC) { +- spin_lock_irqsave(&alarm_slock, flags); +- if (alarm_opened) { +- spin_unlock_irqrestore(&alarm_slock, flags); +- return -EBUSY; +- } +- alarm_opened = 1; +- file->private_data = (void *)1; +- spin_unlock_irqrestore(&alarm_slock, flags); +- } +- } +- +- switch (ANDROID_ALARM_BASE_CMD(cmd)) { +- case ANDROID_ALARM_CLEAR(0): +- alarm_clear(alarm_type); +- break; +- case ANDROID_ALARM_SET(0): +- alarm_set(alarm_type, ts); +- break; +- case ANDROID_ALARM_SET_AND_WAIT(0): +- alarm_set(alarm_type, ts); +- /* fall though */ +- case ANDROID_ALARM_WAIT: +- rv = alarm_wait(); +- break; +- case ANDROID_ALARM_SET_RTC: +- rv = alarm_set_rtc(ts); +- break; +- case ANDROID_ALARM_GET_TIME(0): +- rv = alarm_get_time(alarm_type, ts); +- break; +- +- default: +- rv = -EINVAL; +- } +- return rv; +-} +- +-static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +-{ +- +- struct timespec ts; +- int rv; +- +- switch (ANDROID_ALARM_BASE_CMD(cmd)) { +- case ANDROID_ALARM_SET_AND_WAIT(0): +- case ANDROID_ALARM_SET(0): +- case ANDROID_ALARM_SET_RTC: +- if (copy_from_user(&ts, (void __user *)arg, sizeof(ts))) +- return -EFAULT; +- break; +- } +- +- rv = alarm_do_ioctl(file, cmd, &ts); +- if (rv) +- return rv; +- +- switch (ANDROID_ALARM_BASE_CMD(cmd)) { +- case ANDROID_ALARM_GET_TIME(0): +- if (copy_to_user((void __user *)arg, &ts, sizeof(ts))) +- return -EFAULT; +- break; +- } +- +- return 0; +-} +- +-#ifdef CONFIG_COMPAT +-static long alarm_compat_ioctl(struct file *file, unsigned int cmd, +- unsigned long arg) +-{ +- +- struct timespec ts; +- int rv; +- +- switch (ANDROID_ALARM_BASE_CMD(cmd)) { +- case ANDROID_ALARM_SET_AND_WAIT_COMPAT(0): +- case ANDROID_ALARM_SET_COMPAT(0): +- case ANDROID_ALARM_SET_RTC_COMPAT: +- if (compat_get_timespec(&ts, (void __user *)arg)) +- return -EFAULT; +- /* fall through */ +- case ANDROID_ALARM_GET_TIME_COMPAT(0): +- cmd = ANDROID_ALARM_COMPAT_TO_NORM(cmd); +- break; +- } +- +- rv = alarm_do_ioctl(file, cmd, &ts); +- if (rv) +- return rv; +- +- switch (ANDROID_ALARM_BASE_CMD(cmd)) { +- case ANDROID_ALARM_GET_TIME(0): /* NOTE: we modified cmd above */ +- if (compat_put_timespec(&ts, (void __user *)arg)) +- return -EFAULT; +- break; +- } +- +- return 0; +-} +-#endif +- +-static int alarm_open(struct inode *inode, struct file *file) +-{ +- file->private_data = NULL; +- return 0; +-} +- +-static int alarm_release(struct inode *inode, struct file *file) +-{ +- int i; +- unsigned long flags; +- +- spin_lock_irqsave(&alarm_slock, flags); +- if (file->private_data) { +- for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { +- uint32_t alarm_type_mask = 1U << i; +- +- if (alarm_enabled & alarm_type_mask) { +- alarm_dbg(INFO, +- "%s: clear alarm, pending %d\n", +- __func__, +- !!(alarm_pending & alarm_type_mask)); +- alarm_enabled &= ~alarm_type_mask; +- } +- spin_unlock_irqrestore(&alarm_slock, flags); +- devalarm_cancel(&alarms[i]); +- spin_lock_irqsave(&alarm_slock, flags); +- } +- if (alarm_pending | wait_pending) { +- if (alarm_pending) +- alarm_dbg(INFO, "%s: clear pending alarms %x\n", +- __func__, alarm_pending); +- __pm_relax(&alarm_wake_lock); +- wait_pending = 0; +- alarm_pending = 0; +- } +- alarm_opened = 0; +- } +- spin_unlock_irqrestore(&alarm_slock, flags); +- return 0; +-} +- +-static void devalarm_triggered(struct devalarm *alarm) +-{ +- unsigned long flags; +- uint32_t alarm_type_mask = 1U << alarm->type; +- +- alarm_dbg(INT, "%s: type %d\n", __func__, alarm->type); +- spin_lock_irqsave(&alarm_slock, flags); +- if (alarm_enabled & alarm_type_mask) { +- __pm_wakeup_event(&alarm_wake_lock, 5000); /* 5secs */ +- alarm_enabled &= ~alarm_type_mask; +- alarm_pending |= alarm_type_mask; +- wake_up(&alarm_wait_queue); +- } +- spin_unlock_irqrestore(&alarm_slock, flags); +-} +- +-static enum hrtimer_restart devalarm_hrthandler(struct hrtimer *hrt) +-{ +- struct devalarm *devalrm = container_of(hrt, struct devalarm, u.hrt); +- +- devalarm_triggered(devalrm); +- return HRTIMER_NORESTART; +-} +- +-static enum alarmtimer_restart devalarm_alarmhandler(struct alarm *alrm, +- ktime_t now) +-{ +- struct devalarm *devalrm = container_of(alrm, struct devalarm, u.alrm); +- +- devalarm_triggered(devalrm); +- return ALARMTIMER_NORESTART; +-} +- +- +-static const struct file_operations alarm_fops = { +- .owner = THIS_MODULE, +- .unlocked_ioctl = alarm_ioctl, +- .open = alarm_open, +- .release = alarm_release, +-#ifdef CONFIG_COMPAT +- .compat_ioctl = alarm_compat_ioctl, +-#endif +-}; +- +-static struct miscdevice alarm_device = { +- .minor = MISC_DYNAMIC_MINOR, +- .name = "alarm", +- .fops = &alarm_fops, +-}; +- +-static int __init alarm_dev_init(void) +-{ +- int err; +- int i; +- +- err = misc_register(&alarm_device); +- if (err) +- return err; +- +- alarm_init(&alarms[ANDROID_ALARM_RTC_WAKEUP].u.alrm, +- ALARM_REALTIME, devalarm_alarmhandler); +- hrtimer_init(&alarms[ANDROID_ALARM_RTC].u.hrt, +- CLOCK_REALTIME, HRTIMER_MODE_ABS); +- alarm_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].u.alrm, +- ALARM_BOOTTIME, devalarm_alarmhandler); +- hrtimer_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME].u.hrt, +- CLOCK_BOOTTIME, HRTIMER_MODE_ABS); +- hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].u.hrt, +- CLOCK_MONOTONIC, HRTIMER_MODE_ABS); +- +- for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { +- alarms[i].type = i; +- if (!is_wakeup(i)) +- alarms[i].u.hrt.function = devalarm_hrthandler; +- } +- +- wakeup_source_init(&alarm_wake_lock, "alarm"); +- return 0; +-} +- +-static void __exit alarm_dev_exit(void) +-{ +- misc_deregister(&alarm_device); +- wakeup_source_trash(&alarm_wake_lock); +-} +- +-module_init(alarm_dev_init); +-module_exit(alarm_dev_exit); +-MODULE_LICENSE("GPL"); +diff --git a/drivers/staging/android/android_alarm.h b/drivers/staging/android/android_alarm.h +deleted file mode 100644 +index 495b20c..0000000 +--- a/drivers/staging/android/android_alarm.h ++++ /dev/null +@@ -1,41 +0,0 @@ +-/* include/linux/android_alarm.h +- * +- * Copyright (C) 2006-2007 Google, 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. +- * +- */ +- +-#ifndef _LINUX_ANDROID_ALARM_H +-#define _LINUX_ANDROID_ALARM_H +- +-#include +-#include +- +-#include "uapi/android_alarm.h" +- +-#ifdef CONFIG_COMPAT +-#define ANDROID_ALARM_SET_COMPAT(type) ALARM_IOW(2, type, \ +- struct compat_timespec) +-#define ANDROID_ALARM_SET_AND_WAIT_COMPAT(type) ALARM_IOW(3, type, \ +- struct compat_timespec) +-#define ANDROID_ALARM_GET_TIME_COMPAT(type) ALARM_IOW(4, type, \ +- struct compat_timespec) +-#define ANDROID_ALARM_SET_RTC_COMPAT _IOW('a', 5, \ +- struct compat_timespec) +-#define ANDROID_ALARM_IOCTL_NR(cmd) (_IOC_NR(cmd) & ((1<<4)-1)) +-#define ANDROID_ALARM_COMPAT_TO_NORM(cmd) \ +- ALARM_IOW(ANDROID_ALARM_IOCTL_NR(cmd), \ +- ANDROID_ALARM_IOCTL_TO_TYPE(cmd), \ +- struct timespec) +- +-#endif +- +-#endif +diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c +index ad4f579..afee619 100644 +--- a/drivers/staging/android/ashmem.c ++++ b/drivers/staging/android/ashmem.c +@@ -396,22 +396,14 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma) + } + get_file(asma->file); + +- /* +- * XXX - Reworked to use shmem_zero_setup() instead of +- * shmem_set_file while we're in staging. -jstultz +- */ +- if (vma->vm_flags & VM_SHARED) { +- ret = shmem_zero_setup(vma); +- if (ret) { +- fput(asma->file); +- goto out; +- } ++ if (vma->vm_flags & VM_SHARED) ++ shmem_set_file(vma, asma->file); ++ else { ++ if (vma->vm_file) ++ fput(vma->vm_file); ++ vma->vm_file = asma->file; + } + +- if (vma->vm_file) +- fput(vma->vm_file); +- vma->vm_file = asma->file; +- + out: + mutex_unlock(&ashmem_mutex); + return ret; +@@ -441,12 +433,14 @@ ashmem_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) + if (!(sc->gfp_mask & __GFP_FS)) + return SHRINK_STOP; + +- mutex_lock(&ashmem_mutex); ++ if (!mutex_trylock(&ashmem_mutex)) ++ return -1; ++ + list_for_each_entry_safe(range, next, &ashmem_lru_list, lru) { + loff_t start = range->pgstart * PAGE_SIZE; + loff_t end = (range->pgend + 1) * PAGE_SIZE; + +- do_fallocate(range->asma->file, ++ range->asma->file->f_op->fallocate(range->asma->file, + FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, + start, end - start); + range->purged = ASHMEM_WAS_PURGED; +diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c +index c69c40d..710393a 100644 +--- a/drivers/staging/android/binder.c ++++ b/drivers/staging/android/binder.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -37,11 +38,12 @@ + #include + #include + #include ++#include + + #include "binder.h" + #include "binder_trace.h" + +-static DEFINE_MUTEX(binder_main_lock); ++static DEFINE_RT_MUTEX(binder_main_lock); + static DEFINE_MUTEX(binder_deferred_lock); + static DEFINE_MUTEX(binder_mmap_lock); + +@@ -421,14 +423,14 @@ static long task_close_fd(struct binder_proc *proc, unsigned int fd) + static inline void binder_lock(const char *tag) + { + trace_binder_lock(tag); +- mutex_lock(&binder_main_lock); ++ rt_mutex_lock(&binder_main_lock); + trace_binder_locked(tag); + } + + static inline void binder_unlock(const char *tag) + { + trace_binder_unlock(tag); +- mutex_unlock(&binder_main_lock); ++ rt_mutex_unlock(&binder_main_lock); + } + + static void binder_set_nice(long nice) +@@ -1316,6 +1318,7 @@ static void binder_transaction(struct binder_proc *proc, + struct binder_transaction *t; + struct binder_work *tcomplete; + binder_size_t *offp, *off_end; ++ binder_size_t off_min; + struct binder_proc *target_proc; + struct binder_thread *target_thread = NULL; + struct binder_node *target_node = NULL; +@@ -1396,6 +1399,10 @@ static void binder_transaction(struct binder_proc *proc, + return_error = BR_DEAD_REPLY; + goto err_dead_binder; + } ++ if (security_binder_transaction(proc->tsk, target_proc->tsk) < 0) { ++ return_error = BR_FAILED_REPLY; ++ goto err_invalid_target_handle; ++ } + if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) { + struct binder_transaction *tmp; + +@@ -1512,18 +1519,24 @@ static void binder_transaction(struct binder_proc *proc, + goto err_bad_offset; + } + off_end = (void *)offp + tr->offsets_size; ++ off_min = 0; + for (; offp < off_end; offp++) { + struct flat_binder_object *fp; + + if (*offp > t->buffer->data_size - sizeof(*fp) || ++ *offp < off_min || + t->buffer->data_size < sizeof(*fp) || + !IS_ALIGNED(*offp, sizeof(u32))) { +- binder_user_error("%d:%d got transaction with invalid offset, %lld\n", +- proc->pid, thread->pid, (u64)*offp); ++ binder_user_error("%d:%d got transaction with invalid offset, %lld (min %lld, max %lld)\n", ++ proc->pid, thread->pid, (u64)*offp, ++ (u64)off_min, ++ (u64)(t->buffer->data_size - ++ sizeof(*fp))); + return_error = BR_FAILED_REPLY; + goto err_bad_offset; + } + fp = (struct flat_binder_object *)(t->buffer->data + *offp); ++ off_min = *offp + sizeof(struct flat_binder_object); + switch (fp->type) { + case BINDER_TYPE_BINDER: + case BINDER_TYPE_WEAK_BINDER: { +@@ -1547,6 +1560,10 @@ static void binder_transaction(struct binder_proc *proc, + return_error = BR_FAILED_REPLY; + goto err_binder_get_ref_for_node_failed; + } ++ if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { ++ return_error = BR_FAILED_REPLY; ++ goto err_binder_get_ref_for_node_failed; ++ } + ref = binder_get_ref_for_node(target_proc, node); + if (ref == NULL) { + return_error = BR_FAILED_REPLY; +@@ -1577,6 +1594,10 @@ static void binder_transaction(struct binder_proc *proc, + return_error = BR_FAILED_REPLY; + goto err_binder_get_ref_failed; + } ++ if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { ++ return_error = BR_FAILED_REPLY; ++ goto err_binder_get_ref_failed; ++ } + if (ref->node->proc == target_proc) { + if (fp->type == BINDER_TYPE_HANDLE) + fp->type = BINDER_TYPE_BINDER; +@@ -1634,6 +1655,11 @@ static void binder_transaction(struct binder_proc *proc, + return_error = BR_FAILED_REPLY; + goto err_fget_failed; + } ++ if (security_binder_transfer_file(proc->tsk, target_proc->tsk, file) < 0) { ++ fput(file); ++ return_error = BR_FAILED_REPLY; ++ goto err_get_unused_fd_failed; ++ } + target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC); + if (target_fd < 0) { + fput(file); +@@ -2736,6 +2762,9 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + ret = binder_ioctl_set_ctx_mgr(filp); + if (ret) + goto err; ++ ret = security_binder_set_context_mgr(proc->tsk); ++ if (ret < 0) ++ goto err; + break; + case BINDER_THREAD_EXIT: + binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n", +diff --git a/drivers/staging/android/fiq_debugger/Kconfig b/drivers/staging/android/fiq_debugger/Kconfig +new file mode 100644 +index 0000000..56f7f99 +--- /dev/null ++++ b/drivers/staging/android/fiq_debugger/Kconfig +@@ -0,0 +1,49 @@ ++config FIQ_DEBUGGER ++ bool "FIQ Mode Serial Debugger" ++ default n ++ depends on ARM || ARM64 ++ help ++ The FIQ serial debugger can accept commands even when the ++ kernel is unresponsive due to being stuck with interrupts ++ disabled. ++ ++config FIQ_DEBUGGER_NO_SLEEP ++ bool "Keep serial debugger active" ++ depends on FIQ_DEBUGGER ++ default n ++ help ++ Enables the serial debugger at boot. Passing ++ fiq_debugger.no_sleep on the kernel commandline will ++ override this config option. ++ ++config FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON ++ bool "Don't disable wakeup IRQ when debugger is active" ++ depends on FIQ_DEBUGGER ++ default n ++ help ++ Don't disable the wakeup irq when enabling the uart clock. This will ++ cause extra interrupts, but it makes the serial debugger usable with ++ on some MSM radio builds that ignore the uart clock request in power ++ collapse. ++ ++config FIQ_DEBUGGER_CONSOLE ++ bool "Console on FIQ Serial Debugger port" ++ depends on FIQ_DEBUGGER ++ default n ++ help ++ Enables a console so that printk messages are displayed on ++ the debugger serial port as the occur. ++ ++config FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE ++ bool "Put the FIQ debugger into console mode by default" ++ depends on FIQ_DEBUGGER_CONSOLE ++ default n ++ help ++ If enabled, this puts the fiq debugger into console mode by default. ++ Otherwise, the fiq debugger will start out in debug mode. ++ ++config FIQ_WATCHDOG ++ bool ++ select FIQ_DEBUGGER ++ select PSTORE_RAM ++ default n +diff --git a/drivers/staging/android/fiq_debugger/Makefile b/drivers/staging/android/fiq_debugger/Makefile +new file mode 100644 +index 0000000..a7ca487 +--- /dev/null ++++ b/drivers/staging/android/fiq_debugger/Makefile +@@ -0,0 +1,4 @@ ++obj-y += fiq_debugger.o ++obj-$(CONFIG_ARM) += fiq_debugger_arm.o ++obj-$(CONFIG_ARM64) += fiq_debugger_arm64.o ++obj-$(CONFIG_FIQ_WATCHDOG) += fiq_watchdog.o +diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger.c b/drivers/staging/android/fiq_debugger/fiq_debugger.c +new file mode 100644 +index 0000000..52f6816 +--- /dev/null ++++ b/drivers/staging/android/fiq_debugger/fiq_debugger.c +@@ -0,0 +1,1212 @@ ++/* ++ * drivers/staging/android/fiq_debugger.c ++ * ++ * Serial Debugger Interface accessed through an FIQ interrupt. ++ * ++ * Copyright (C) 2008 Google, 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_FIQ_GLUE ++#include ++#endif ++ ++#include ++ ++#include "fiq_debugger.h" ++#include "fiq_debugger_priv.h" ++#include "fiq_debugger_ringbuf.h" ++ ++#define DEBUG_MAX 64 ++#define MAX_UNHANDLED_FIQ_COUNT 1000000 ++ ++#define MAX_FIQ_DEBUGGER_PORTS 4 ++ ++struct fiq_debugger_state { ++#ifdef CONFIG_FIQ_GLUE ++ struct fiq_glue_handler handler; ++#endif ++ struct fiq_debugger_output output; ++ ++ int fiq; ++ int uart_irq; ++ int signal_irq; ++ int wakeup_irq; ++ bool wakeup_irq_no_set_wake; ++ struct clk *clk; ++ struct fiq_debugger_pdata *pdata; ++ struct platform_device *pdev; ++ ++ char debug_cmd[DEBUG_MAX]; ++ int debug_busy; ++ int debug_abort; ++ ++ char debug_buf[DEBUG_MAX]; ++ int debug_count; ++ ++ bool no_sleep; ++ bool debug_enable; ++ bool ignore_next_wakeup_irq; ++ struct timer_list sleep_timer; ++ spinlock_t sleep_timer_lock; ++ bool uart_enabled; ++ struct wake_lock debugger_wake_lock; ++ bool console_enable; ++ int current_cpu; ++ atomic_t unhandled_fiq_count; ++ bool in_fiq; ++ ++ struct work_struct work; ++ spinlock_t work_lock; ++ char work_cmd[DEBUG_MAX]; ++ ++#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE ++ spinlock_t console_lock; ++ struct console console; ++ struct tty_port tty_port; ++ struct fiq_debugger_ringbuf *tty_rbuf; ++ bool syslog_dumping; ++#endif ++ ++ unsigned int last_irqs[NR_IRQS]; ++ unsigned int last_local_timer_irqs[NR_CPUS]; ++}; ++ ++#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE ++struct tty_driver *fiq_tty_driver; ++#endif ++ ++#ifdef CONFIG_FIQ_DEBUGGER_NO_SLEEP ++static bool initial_no_sleep = true; ++#else ++static bool initial_no_sleep; ++#endif ++ ++#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE ++static bool initial_debug_enable = true; ++static bool initial_console_enable = true; ++#else ++static bool initial_debug_enable; ++static bool initial_console_enable; ++#endif ++ ++static bool fiq_kgdb_enable; ++ ++module_param_named(no_sleep, initial_no_sleep, bool, 0644); ++module_param_named(debug_enable, initial_debug_enable, bool, 0644); ++module_param_named(console_enable, initial_console_enable, bool, 0644); ++module_param_named(kgdb_enable, fiq_kgdb_enable, bool, 0644); ++ ++#ifdef CONFIG_FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON ++static inline ++void fiq_debugger_enable_wakeup_irq(struct fiq_debugger_state *state) {} ++static inline ++void fiq_debugger_disable_wakeup_irq(struct fiq_debugger_state *state) {} ++#else ++static inline ++void fiq_debugger_enable_wakeup_irq(struct fiq_debugger_state *state) ++{ ++ if (state->wakeup_irq < 0) ++ return; ++ enable_irq(state->wakeup_irq); ++ if (!state->wakeup_irq_no_set_wake) ++ enable_irq_wake(state->wakeup_irq); ++} ++static inline ++void fiq_debugger_disable_wakeup_irq(struct fiq_debugger_state *state) ++{ ++ if (state->wakeup_irq < 0) ++ return; ++ disable_irq_nosync(state->wakeup_irq); ++ if (!state->wakeup_irq_no_set_wake) ++ disable_irq_wake(state->wakeup_irq); ++} ++#endif ++ ++static inline bool fiq_debugger_have_fiq(struct fiq_debugger_state *state) ++{ ++ return (state->fiq >= 0); ++} ++ ++#ifdef CONFIG_FIQ_GLUE ++static void fiq_debugger_force_irq(struct fiq_debugger_state *state) ++{ ++ unsigned int irq = state->signal_irq; ++ ++ if (WARN_ON(!fiq_debugger_have_fiq(state))) ++ return; ++ if (state->pdata->force_irq) { ++ state->pdata->force_irq(state->pdev, irq); ++ } else { ++ struct irq_chip *chip = irq_get_chip(irq); ++ if (chip && chip->irq_retrigger) ++ chip->irq_retrigger(irq_get_irq_data(irq)); ++ } ++} ++#endif ++ ++static void fiq_debugger_uart_enable(struct fiq_debugger_state *state) ++{ ++ if (state->clk) ++ clk_enable(state->clk); ++ if (state->pdata->uart_enable) ++ state->pdata->uart_enable(state->pdev); ++} ++ ++static void fiq_debugger_uart_disable(struct fiq_debugger_state *state) ++{ ++ if (state->pdata->uart_disable) ++ state->pdata->uart_disable(state->pdev); ++ if (state->clk) ++ clk_disable(state->clk); ++} ++ ++static void fiq_debugger_uart_flush(struct fiq_debugger_state *state) ++{ ++ if (state->pdata->uart_flush) ++ state->pdata->uart_flush(state->pdev); ++} ++ ++static void fiq_debugger_putc(struct fiq_debugger_state *state, char c) ++{ ++ state->pdata->uart_putc(state->pdev, c); ++} ++ ++static void fiq_debugger_puts(struct fiq_debugger_state *state, char *s) ++{ ++ unsigned c; ++ while ((c = *s++)) { ++ if (c == '\n') ++ fiq_debugger_putc(state, '\r'); ++ fiq_debugger_putc(state, c); ++ } ++} ++ ++static void fiq_debugger_prompt(struct fiq_debugger_state *state) ++{ ++ fiq_debugger_puts(state, "debug> "); ++} ++ ++static void fiq_debugger_dump_kernel_log(struct fiq_debugger_state *state) ++{ ++ char buf[512]; ++ size_t len; ++ struct kmsg_dumper dumper = { .active = true }; ++ ++ ++ kmsg_dump_rewind_nolock(&dumper); ++ while (kmsg_dump_get_line_nolock(&dumper, true, buf, ++ sizeof(buf) - 1, &len)) { ++ buf[len] = 0; ++ fiq_debugger_puts(state, buf); ++ } ++} ++ ++static void fiq_debugger_printf(struct fiq_debugger_output *output, ++ const char *fmt, ...) ++{ ++ struct fiq_debugger_state *state; ++ char buf[256]; ++ va_list ap; ++ ++ state = container_of(output, struct fiq_debugger_state, output); ++ va_start(ap, fmt); ++ vsnprintf(buf, sizeof(buf), fmt, ap); ++ va_end(ap); ++ ++ fiq_debugger_puts(state, buf); ++} ++ ++/* Safe outside fiq context */ ++static int fiq_debugger_printf_nfiq(void *cookie, const char *fmt, ...) ++{ ++ struct fiq_debugger_state *state = cookie; ++ char buf[256]; ++ va_list ap; ++ unsigned long irq_flags; ++ ++ va_start(ap, fmt); ++ vsnprintf(buf, 128, fmt, ap); ++ va_end(ap); ++ ++ local_irq_save(irq_flags); ++ fiq_debugger_puts(state, buf); ++ fiq_debugger_uart_flush(state); ++ local_irq_restore(irq_flags); ++ return state->debug_abort; ++} ++ ++static void fiq_debugger_dump_irqs(struct fiq_debugger_state *state) ++{ ++ int n; ++ struct irq_desc *desc; ++ ++ fiq_debugger_printf(&state->output, ++ "irqnr total since-last status name\n"); ++ for_each_irq_desc(n, desc) { ++ struct irqaction *act = desc->action; ++ if (!act && !kstat_irqs(n)) ++ continue; ++ fiq_debugger_printf(&state->output, "%5d: %10u %11u %8x %s\n", n, ++ kstat_irqs(n), ++ kstat_irqs(n) - state->last_irqs[n], ++ desc->status_use_accessors, ++ (act && act->name) ? act->name : "???"); ++ state->last_irqs[n] = kstat_irqs(n); ++ } ++} ++ ++static void fiq_debugger_do_ps(struct fiq_debugger_state *state) ++{ ++ struct task_struct *g; ++ struct task_struct *p; ++ unsigned task_state; ++ static const char stat_nam[] = "RSDTtZX"; ++ ++ fiq_debugger_printf(&state->output, "pid ppid prio task pc\n"); ++ read_lock(&tasklist_lock); ++ do_each_thread(g, p) { ++ task_state = p->state ? __ffs(p->state) + 1 : 0; ++ fiq_debugger_printf(&state->output, ++ "%5d %5d %4d ", p->pid, p->parent->pid, p->prio); ++ fiq_debugger_printf(&state->output, "%-13.13s %c", p->comm, ++ task_state >= sizeof(stat_nam) ? '?' : stat_nam[task_state]); ++ if (task_state == TASK_RUNNING) ++ fiq_debugger_printf(&state->output, " running\n"); ++ else ++ fiq_debugger_printf(&state->output, " %08lx\n", ++ thread_saved_pc(p)); ++ } while_each_thread(g, p); ++ read_unlock(&tasklist_lock); ++} ++ ++#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE ++static void fiq_debugger_begin_syslog_dump(struct fiq_debugger_state *state) ++{ ++ state->syslog_dumping = true; ++} ++ ++static void fiq_debugger_end_syslog_dump(struct fiq_debugger_state *state) ++{ ++ state->syslog_dumping = false; ++} ++#else ++extern int do_syslog(int type, char __user *bug, int count); ++static void fiq_debugger_begin_syslog_dump(struct fiq_debugger_state *state) ++{ ++ do_syslog(5 /* clear */, NULL, 0); ++} ++ ++static void fiq_debugger_end_syslog_dump(struct fiq_debugger_state *state) ++{ ++ fiq_debugger_dump_kernel_log(state); ++} ++#endif ++ ++static void fiq_debugger_do_sysrq(struct fiq_debugger_state *state, char rq) ++{ ++ if ((rq == 'g' || rq == 'G') && !fiq_kgdb_enable) { ++ fiq_debugger_printf(&state->output, "sysrq-g blocked\n"); ++ return; ++ } ++ fiq_debugger_begin_syslog_dump(state); ++ handle_sysrq(rq); ++ fiq_debugger_end_syslog_dump(state); ++} ++ ++#ifdef CONFIG_KGDB ++static void fiq_debugger_do_kgdb(struct fiq_debugger_state *state) ++{ ++ if (!fiq_kgdb_enable) { ++ fiq_debugger_printf(&state->output, "kgdb through fiq debugger not enabled\n"); ++ return; ++ } ++ ++ fiq_debugger_printf(&state->output, "enabling console and triggering kgdb\n"); ++ state->console_enable = true; ++ handle_sysrq('g'); ++} ++#endif ++ ++static void fiq_debugger_schedule_work(struct fiq_debugger_state *state, ++ char *cmd) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&state->work_lock, flags); ++ if (state->work_cmd[0] != '\0') { ++ fiq_debugger_printf(&state->output, "work command processor busy\n"); ++ spin_unlock_irqrestore(&state->work_lock, flags); ++ return; ++ } ++ ++ strlcpy(state->work_cmd, cmd, sizeof(state->work_cmd)); ++ spin_unlock_irqrestore(&state->work_lock, flags); ++ ++ schedule_work(&state->work); ++} ++ ++static void fiq_debugger_work(struct work_struct *work) ++{ ++ struct fiq_debugger_state *state; ++ char work_cmd[DEBUG_MAX]; ++ char *cmd; ++ unsigned long flags; ++ ++ state = container_of(work, struct fiq_debugger_state, work); ++ ++ spin_lock_irqsave(&state->work_lock, flags); ++ ++ strlcpy(work_cmd, state->work_cmd, sizeof(work_cmd)); ++ state->work_cmd[0] = '\0'; ++ ++ spin_unlock_irqrestore(&state->work_lock, flags); ++ ++ cmd = work_cmd; ++ if (!strncmp(cmd, "reboot", 6)) { ++ cmd += 6; ++ while (*cmd == ' ') ++ cmd++; ++ if (cmd != '\0') ++ kernel_restart(cmd); ++ else ++ kernel_restart(NULL); ++ } else { ++ fiq_debugger_printf(&state->output, "unknown work command '%s'\n", ++ work_cmd); ++ } ++} ++ ++/* This function CANNOT be called in FIQ context */ ++static void fiq_debugger_irq_exec(struct fiq_debugger_state *state, char *cmd) ++{ ++ if (!strcmp(cmd, "ps")) ++ fiq_debugger_do_ps(state); ++ if (!strcmp(cmd, "sysrq")) ++ fiq_debugger_do_sysrq(state, 'h'); ++ if (!strncmp(cmd, "sysrq ", 6)) ++ fiq_debugger_do_sysrq(state, cmd[6]); ++#ifdef CONFIG_KGDB ++ if (!strcmp(cmd, "kgdb")) ++ fiq_debugger_do_kgdb(state); ++#endif ++ if (!strncmp(cmd, "reboot", 6)) ++ fiq_debugger_schedule_work(state, cmd); ++} ++ ++static void fiq_debugger_help(struct fiq_debugger_state *state) ++{ ++ fiq_debugger_printf(&state->output, ++ "FIQ Debugger commands:\n" ++ " pc PC status\n" ++ " regs Register dump\n" ++ " allregs Extended Register dump\n" ++ " bt Stack trace\n" ++ " reboot [] Reboot with command \n" ++ " reset [] Hard reset with command \n" ++ " irqs Interupt status\n" ++ " kmsg Kernel log\n" ++ " version Kernel version\n"); ++ fiq_debugger_printf(&state->output, ++ " sleep Allow sleep while in FIQ\n" ++ " nosleep Disable sleep while in FIQ\n" ++ " console Switch terminal to console\n" ++ " cpu Current CPU\n" ++ " cpu Switch to CPU\n"); ++ fiq_debugger_printf(&state->output, ++ " ps Process list\n" ++ " sysrq sysrq options\n" ++ " sysrq Execute sysrq with \n"); ++#ifdef CONFIG_KGDB ++ fiq_debugger_printf(&state->output, ++ " kgdb Enter kernel debugger\n"); ++#endif ++} ++ ++static void fiq_debugger_take_affinity(void *info) ++{ ++ struct fiq_debugger_state *state = info; ++ struct cpumask cpumask; ++ ++ cpumask_clear(&cpumask); ++ cpumask_set_cpu(get_cpu(), &cpumask); ++ ++ irq_set_affinity(state->uart_irq, &cpumask); ++} ++ ++static void fiq_debugger_switch_cpu(struct fiq_debugger_state *state, int cpu) ++{ ++ if (!fiq_debugger_have_fiq(state)) ++ smp_call_function_single(cpu, fiq_debugger_take_affinity, state, ++ false); ++ state->current_cpu = cpu; ++} ++ ++static bool fiq_debugger_fiq_exec(struct fiq_debugger_state *state, ++ const char *cmd, const struct pt_regs *regs, ++ void *svc_sp) ++{ ++ bool signal_helper = false; ++ ++ if (!strcmp(cmd, "help") || !strcmp(cmd, "?")) { ++ fiq_debugger_help(state); ++ } else if (!strcmp(cmd, "pc")) { ++ fiq_debugger_dump_pc(&state->output, regs); ++ } else if (!strcmp(cmd, "regs")) { ++ fiq_debugger_dump_regs(&state->output, regs); ++ } else if (!strcmp(cmd, "allregs")) { ++ fiq_debugger_dump_allregs(&state->output, regs); ++ } else if (!strcmp(cmd, "bt")) { ++ fiq_debugger_dump_stacktrace(&state->output, regs, 100, svc_sp); ++ } else if (!strncmp(cmd, "reset", 5)) { ++ cmd += 5; ++ while (*cmd == ' ') ++ cmd++; ++ if (*cmd) { ++ char tmp_cmd[32]; ++ strlcpy(tmp_cmd, cmd, sizeof(tmp_cmd)); ++ machine_restart(tmp_cmd); ++ } else { ++ machine_restart(NULL); ++ } ++ } else if (!strcmp(cmd, "irqs")) { ++ fiq_debugger_dump_irqs(state); ++ } else if (!strcmp(cmd, "kmsg")) { ++ fiq_debugger_dump_kernel_log(state); ++ } else if (!strcmp(cmd, "version")) { ++ fiq_debugger_printf(&state->output, "%s\n", linux_banner); ++ } else if (!strcmp(cmd, "sleep")) { ++ state->no_sleep = false; ++ fiq_debugger_printf(&state->output, "enabling sleep\n"); ++ } else if (!strcmp(cmd, "nosleep")) { ++ state->no_sleep = true; ++ fiq_debugger_printf(&state->output, "disabling sleep\n"); ++ } else if (!strcmp(cmd, "console")) { ++ fiq_debugger_printf(&state->output, "console mode\n"); ++ fiq_debugger_uart_flush(state); ++ state->console_enable = true; ++ } else if (!strcmp(cmd, "cpu")) { ++ fiq_debugger_printf(&state->output, "cpu %d\n", state->current_cpu); ++ } else if (!strncmp(cmd, "cpu ", 4)) { ++ unsigned long cpu = 0; ++ if (kstrtoul(cmd + 4, 10, &cpu) == 0) ++ fiq_debugger_switch_cpu(state, cpu); ++ else ++ fiq_debugger_printf(&state->output, "invalid cpu\n"); ++ fiq_debugger_printf(&state->output, "cpu %d\n", state->current_cpu); ++ } else { ++ if (state->debug_busy) { ++ fiq_debugger_printf(&state->output, ++ "command processor busy. trying to abort.\n"); ++ state->debug_abort = -1; ++ } else { ++ strcpy(state->debug_cmd, cmd); ++ state->debug_busy = 1; ++ } ++ ++ return true; ++ } ++ if (!state->console_enable) ++ fiq_debugger_prompt(state); ++ ++ return signal_helper; ++} ++ ++static void fiq_debugger_sleep_timer_expired(unsigned long data) ++{ ++ struct fiq_debugger_state *state = (struct fiq_debugger_state *)data; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&state->sleep_timer_lock, flags); ++ if (state->uart_enabled && !state->no_sleep) { ++ if (state->debug_enable && !state->console_enable) { ++ state->debug_enable = false; ++ fiq_debugger_printf_nfiq(state, ++ "suspending fiq debugger\n"); ++ } ++ state->ignore_next_wakeup_irq = true; ++ fiq_debugger_uart_disable(state); ++ state->uart_enabled = false; ++ fiq_debugger_enable_wakeup_irq(state); ++ } ++ wake_unlock(&state->debugger_wake_lock); ++ spin_unlock_irqrestore(&state->sleep_timer_lock, flags); ++} ++ ++static void fiq_debugger_handle_wakeup(struct fiq_debugger_state *state) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&state->sleep_timer_lock, flags); ++ if (state->wakeup_irq >= 0 && state->ignore_next_wakeup_irq) { ++ state->ignore_next_wakeup_irq = false; ++ } else if (!state->uart_enabled) { ++ wake_lock(&state->debugger_wake_lock); ++ fiq_debugger_uart_enable(state); ++ state->uart_enabled = true; ++ fiq_debugger_disable_wakeup_irq(state); ++ mod_timer(&state->sleep_timer, jiffies + HZ / 2); ++ } ++ spin_unlock_irqrestore(&state->sleep_timer_lock, flags); ++} ++ ++static irqreturn_t fiq_debugger_wakeup_irq_handler(int irq, void *dev) ++{ ++ struct fiq_debugger_state *state = dev; ++ ++ if (!state->no_sleep) ++ fiq_debugger_puts(state, "WAKEUP\n"); ++ fiq_debugger_handle_wakeup(state); ++ ++ return IRQ_HANDLED; ++} ++ ++static ++void fiq_debugger_handle_console_irq_context(struct fiq_debugger_state *state) ++{ ++#if defined(CONFIG_FIQ_DEBUGGER_CONSOLE) ++ if (state->tty_port.ops) { ++ int i; ++ int count = fiq_debugger_ringbuf_level(state->tty_rbuf); ++ for (i = 0; i < count; i++) { ++ int c = fiq_debugger_ringbuf_peek(state->tty_rbuf, 0); ++ tty_insert_flip_char(&state->tty_port, c, TTY_NORMAL); ++ if (!fiq_debugger_ringbuf_consume(state->tty_rbuf, 1)) ++ pr_warn("fiq tty failed to consume byte\n"); ++ } ++ tty_flip_buffer_push(&state->tty_port); ++ } ++#endif ++} ++ ++static void fiq_debugger_handle_irq_context(struct fiq_debugger_state *state) ++{ ++ if (!state->no_sleep) { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&state->sleep_timer_lock, flags); ++ wake_lock(&state->debugger_wake_lock); ++ mod_timer(&state->sleep_timer, jiffies + HZ * 5); ++ spin_unlock_irqrestore(&state->sleep_timer_lock, flags); ++ } ++ fiq_debugger_handle_console_irq_context(state); ++ if (state->debug_busy) { ++ fiq_debugger_irq_exec(state, state->debug_cmd); ++ if (!state->console_enable) ++ fiq_debugger_prompt(state); ++ state->debug_busy = 0; ++ } ++} ++ ++static int fiq_debugger_getc(struct fiq_debugger_state *state) ++{ ++ return state->pdata->uart_getc(state->pdev); ++} ++ ++static bool fiq_debugger_handle_uart_interrupt(struct fiq_debugger_state *state, ++ int this_cpu, const struct pt_regs *regs, void *svc_sp) ++{ ++ int c; ++ static int last_c; ++ int count = 0; ++ bool signal_helper = false; ++ ++ if (this_cpu != state->current_cpu) { ++ if (state->in_fiq) ++ return false; ++ ++ if (atomic_inc_return(&state->unhandled_fiq_count) != ++ MAX_UNHANDLED_FIQ_COUNT) ++ return false; ++ ++ fiq_debugger_printf(&state->output, ++ "fiq_debugger: cpu %d not responding, " ++ "reverting to cpu %d\n", state->current_cpu, ++ this_cpu); ++ ++ atomic_set(&state->unhandled_fiq_count, 0); ++ fiq_debugger_switch_cpu(state, this_cpu); ++ return false; ++ } ++ ++ state->in_fiq = true; ++ ++ while ((c = fiq_debugger_getc(state)) != FIQ_DEBUGGER_NO_CHAR) { ++ count++; ++ if (!state->debug_enable) { ++ if ((c == 13) || (c == 10)) { ++ state->debug_enable = true; ++ state->debug_count = 0; ++ fiq_debugger_prompt(state); ++ } ++ } else if (c == FIQ_DEBUGGER_BREAK) { ++ state->console_enable = false; ++ fiq_debugger_puts(state, "fiq debugger mode\n"); ++ state->debug_count = 0; ++ fiq_debugger_prompt(state); ++#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE ++ } else if (state->console_enable && state->tty_rbuf) { ++ fiq_debugger_ringbuf_push(state->tty_rbuf, c); ++ signal_helper = true; ++#endif ++ } else if ((c >= ' ') && (c < 127)) { ++ if (state->debug_count < (DEBUG_MAX - 1)) { ++ state->debug_buf[state->debug_count++] = c; ++ fiq_debugger_putc(state, c); ++ } ++ } else if ((c == 8) || (c == 127)) { ++ if (state->debug_count > 0) { ++ state->debug_count--; ++ fiq_debugger_putc(state, 8); ++ fiq_debugger_putc(state, ' '); ++ fiq_debugger_putc(state, 8); ++ } ++ } else if ((c == 13) || (c == 10)) { ++ if (c == '\r' || (c == '\n' && last_c != '\r')) { ++ fiq_debugger_putc(state, '\r'); ++ fiq_debugger_putc(state, '\n'); ++ } ++ if (state->debug_count) { ++ state->debug_buf[state->debug_count] = 0; ++ state->debug_count = 0; ++ signal_helper |= ++ fiq_debugger_fiq_exec(state, ++ state->debug_buf, ++ regs, svc_sp); ++ } else { ++ fiq_debugger_prompt(state); ++ } ++ } ++ last_c = c; ++ } ++ if (!state->console_enable) ++ fiq_debugger_uart_flush(state); ++ if (state->pdata->fiq_ack) ++ state->pdata->fiq_ack(state->pdev, state->fiq); ++ ++ /* poke sleep timer if necessary */ ++ if (state->debug_enable && !state->no_sleep) ++ signal_helper = true; ++ ++ atomic_set(&state->unhandled_fiq_count, 0); ++ state->in_fiq = false; ++ ++ return signal_helper; ++} ++ ++#ifdef CONFIG_FIQ_GLUE ++static void fiq_debugger_fiq(struct fiq_glue_handler *h, ++ const struct pt_regs *regs, void *svc_sp) ++{ ++ struct fiq_debugger_state *state = ++ container_of(h, struct fiq_debugger_state, handler); ++ unsigned int this_cpu = THREAD_INFO(svc_sp)->cpu; ++ bool need_irq; ++ ++ need_irq = fiq_debugger_handle_uart_interrupt(state, this_cpu, regs, ++ svc_sp); ++ if (need_irq) ++ fiq_debugger_force_irq(state); ++} ++#endif ++ ++/* ++ * When not using FIQs, we only use this single interrupt as an entry point. ++ * This just effectively takes over the UART interrupt and does all the work ++ * in this context. ++ */ ++static irqreturn_t fiq_debugger_uart_irq(int irq, void *dev) ++{ ++ struct fiq_debugger_state *state = dev; ++ bool not_done; ++ ++ fiq_debugger_handle_wakeup(state); ++ ++ /* handle the debugger irq in regular context */ ++ not_done = fiq_debugger_handle_uart_interrupt(state, smp_processor_id(), ++ get_irq_regs(), ++ current_thread_info()); ++ if (not_done) ++ fiq_debugger_handle_irq_context(state); ++ ++ return IRQ_HANDLED; ++} ++ ++/* ++ * If FIQs are used, not everything can happen in fiq context. ++ * FIQ handler does what it can and then signals this interrupt to finish the ++ * job in irq context. ++ */ ++static irqreturn_t fiq_debugger_signal_irq(int irq, void *dev) ++{ ++ struct fiq_debugger_state *state = dev; ++ ++ if (state->pdata->force_irq_ack) ++ state->pdata->force_irq_ack(state->pdev, state->signal_irq); ++ ++ fiq_debugger_handle_irq_context(state); ++ ++ return IRQ_HANDLED; ++} ++ ++#ifdef CONFIG_FIQ_GLUE ++static void fiq_debugger_resume(struct fiq_glue_handler *h) ++{ ++ struct fiq_debugger_state *state = ++ container_of(h, struct fiq_debugger_state, handler); ++ if (state->pdata->uart_resume) ++ state->pdata->uart_resume(state->pdev); ++} ++#endif ++ ++#if defined(CONFIG_FIQ_DEBUGGER_CONSOLE) ++struct tty_driver *fiq_debugger_console_device(struct console *co, int *index) ++{ ++ *index = co->index; ++ return fiq_tty_driver; ++} ++ ++static void fiq_debugger_console_write(struct console *co, ++ const char *s, unsigned int count) ++{ ++ struct fiq_debugger_state *state; ++ unsigned long flags; ++ ++ state = container_of(co, struct fiq_debugger_state, console); ++ ++ if (!state->console_enable && !state->syslog_dumping) ++ return; ++ ++ fiq_debugger_uart_enable(state); ++ spin_lock_irqsave(&state->console_lock, flags); ++ while (count--) { ++ if (*s == '\n') ++ fiq_debugger_putc(state, '\r'); ++ fiq_debugger_putc(state, *s++); ++ } ++ fiq_debugger_uart_flush(state); ++ spin_unlock_irqrestore(&state->console_lock, flags); ++ fiq_debugger_uart_disable(state); ++} ++ ++static struct console fiq_debugger_console = { ++ .name = "ttyFIQ", ++ .device = fiq_debugger_console_device, ++ .write = fiq_debugger_console_write, ++ .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_ENABLED, ++}; ++ ++int fiq_tty_open(struct tty_struct *tty, struct file *filp) ++{ ++ int line = tty->index; ++ struct fiq_debugger_state **states = tty->driver->driver_state; ++ struct fiq_debugger_state *state = states[line]; ++ ++ return tty_port_open(&state->tty_port, tty, filp); ++} ++ ++void fiq_tty_close(struct tty_struct *tty, struct file *filp) ++{ ++ tty_port_close(tty->port, tty, filp); ++} ++ ++int fiq_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) ++{ ++ int i; ++ int line = tty->index; ++ struct fiq_debugger_state **states = tty->driver->driver_state; ++ struct fiq_debugger_state *state = states[line]; ++ ++ if (!state->console_enable) ++ return count; ++ ++ fiq_debugger_uart_enable(state); ++ spin_lock_irq(&state->console_lock); ++ for (i = 0; i < count; i++) ++ fiq_debugger_putc(state, *buf++); ++ spin_unlock_irq(&state->console_lock); ++ fiq_debugger_uart_disable(state); ++ ++ return count; ++} ++ ++int fiq_tty_write_room(struct tty_struct *tty) ++{ ++ return 16; ++} ++ ++#ifdef CONFIG_CONSOLE_POLL ++static int fiq_tty_poll_init(struct tty_driver *driver, int line, char *options) ++{ ++ return 0; ++} ++ ++static int fiq_tty_poll_get_char(struct tty_driver *driver, int line) ++{ ++ struct fiq_debugger_state **states = driver->driver_state; ++ struct fiq_debugger_state *state = states[line]; ++ int c = NO_POLL_CHAR; ++ ++ fiq_debugger_uart_enable(state); ++ if (fiq_debugger_have_fiq(state)) { ++ int count = fiq_debugger_ringbuf_level(state->tty_rbuf); ++ if (count > 0) { ++ c = fiq_debugger_ringbuf_peek(state->tty_rbuf, 0); ++ fiq_debugger_ringbuf_consume(state->tty_rbuf, 1); ++ } ++ } else { ++ c = fiq_debugger_getc(state); ++ if (c == FIQ_DEBUGGER_NO_CHAR) ++ c = NO_POLL_CHAR; ++ } ++ fiq_debugger_uart_disable(state); ++ ++ return c; ++} ++ ++static void fiq_tty_poll_put_char(struct tty_driver *driver, int line, char ch) ++{ ++ struct fiq_debugger_state **states = driver->driver_state; ++ struct fiq_debugger_state *state = states[line]; ++ fiq_debugger_uart_enable(state); ++ fiq_debugger_putc(state, ch); ++ fiq_debugger_uart_disable(state); ++} ++#endif ++ ++static const struct tty_port_operations fiq_tty_port_ops; ++ ++static const struct tty_operations fiq_tty_driver_ops = { ++ .write = fiq_tty_write, ++ .write_room = fiq_tty_write_room, ++ .open = fiq_tty_open, ++ .close = fiq_tty_close, ++#ifdef CONFIG_CONSOLE_POLL ++ .poll_init = fiq_tty_poll_init, ++ .poll_get_char = fiq_tty_poll_get_char, ++ .poll_put_char = fiq_tty_poll_put_char, ++#endif ++}; ++ ++static int fiq_debugger_tty_init(void) ++{ ++ int ret; ++ struct fiq_debugger_state **states = NULL; ++ ++ states = kzalloc(sizeof(*states) * MAX_FIQ_DEBUGGER_PORTS, GFP_KERNEL); ++ if (!states) { ++ pr_err("Failed to allocate fiq debugger state structres\n"); ++ return -ENOMEM; ++ } ++ ++ fiq_tty_driver = alloc_tty_driver(MAX_FIQ_DEBUGGER_PORTS); ++ if (!fiq_tty_driver) { ++ pr_err("Failed to allocate fiq debugger tty\n"); ++ ret = -ENOMEM; ++ goto err_free_state; ++ } ++ ++ fiq_tty_driver->owner = THIS_MODULE; ++ fiq_tty_driver->driver_name = "fiq-debugger"; ++ fiq_tty_driver->name = "ttyFIQ"; ++ fiq_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; ++ fiq_tty_driver->subtype = SERIAL_TYPE_NORMAL; ++ fiq_tty_driver->init_termios = tty_std_termios; ++ fiq_tty_driver->flags = TTY_DRIVER_REAL_RAW | ++ TTY_DRIVER_DYNAMIC_DEV; ++ fiq_tty_driver->driver_state = states; ++ ++ fiq_tty_driver->init_termios.c_cflag = ++ B115200 | CS8 | CREAD | HUPCL | CLOCAL; ++ fiq_tty_driver->init_termios.c_ispeed = 115200; ++ fiq_tty_driver->init_termios.c_ospeed = 115200; ++ ++ tty_set_operations(fiq_tty_driver, &fiq_tty_driver_ops); ++ ++ ret = tty_register_driver(fiq_tty_driver); ++ if (ret) { ++ pr_err("Failed to register fiq tty: %d\n", ret); ++ goto err_free_tty; ++ } ++ ++ pr_info("Registered FIQ tty driver\n"); ++ return 0; ++ ++err_free_tty: ++ put_tty_driver(fiq_tty_driver); ++ fiq_tty_driver = NULL; ++err_free_state: ++ kfree(states); ++ return ret; ++} ++ ++static int fiq_debugger_tty_init_one(struct fiq_debugger_state *state) ++{ ++ int ret; ++ struct device *tty_dev; ++ struct fiq_debugger_state **states = fiq_tty_driver->driver_state; ++ ++ states[state->pdev->id] = state; ++ ++ state->tty_rbuf = fiq_debugger_ringbuf_alloc(1024); ++ if (!state->tty_rbuf) { ++ pr_err("Failed to allocate fiq debugger ringbuf\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ tty_port_init(&state->tty_port); ++ state->tty_port.ops = &fiq_tty_port_ops; ++ ++ tty_dev = tty_port_register_device(&state->tty_port, fiq_tty_driver, ++ state->pdev->id, &state->pdev->dev); ++ if (IS_ERR(tty_dev)) { ++ pr_err("Failed to register fiq debugger tty device\n"); ++ ret = PTR_ERR(tty_dev); ++ goto err; ++ } ++ ++ device_set_wakeup_capable(tty_dev, 1); ++ ++ pr_info("Registered fiq debugger ttyFIQ%d\n", state->pdev->id); ++ ++ return 0; ++ ++err: ++ fiq_debugger_ringbuf_free(state->tty_rbuf); ++ state->tty_rbuf = NULL; ++ return ret; ++} ++#endif ++ ++static int fiq_debugger_dev_suspend(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct fiq_debugger_state *state = platform_get_drvdata(pdev); ++ ++ if (state->pdata->uart_dev_suspend) ++ return state->pdata->uart_dev_suspend(pdev); ++ return 0; ++} ++ ++static int fiq_debugger_dev_resume(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct fiq_debugger_state *state = platform_get_drvdata(pdev); ++ ++ if (state->pdata->uart_dev_resume) ++ return state->pdata->uart_dev_resume(pdev); ++ return 0; ++} ++ ++static int fiq_debugger_probe(struct platform_device *pdev) ++{ ++ int ret; ++ struct fiq_debugger_pdata *pdata = dev_get_platdata(&pdev->dev); ++ struct fiq_debugger_state *state; ++ int fiq; ++ int uart_irq; ++ ++ if (pdev->id >= MAX_FIQ_DEBUGGER_PORTS) ++ return -EINVAL; ++ ++ if (!pdata->uart_getc || !pdata->uart_putc) ++ return -EINVAL; ++ if ((pdata->uart_enable && !pdata->uart_disable) || ++ (!pdata->uart_enable && pdata->uart_disable)) ++ return -EINVAL; ++ ++ fiq = platform_get_irq_byname(pdev, "fiq"); ++ uart_irq = platform_get_irq_byname(pdev, "uart_irq"); ++ ++ /* uart_irq mode and fiq mode are mutually exclusive, but one of them ++ * is required */ ++ if ((uart_irq < 0 && fiq < 0) || (uart_irq >= 0 && fiq >= 0)) ++ return -EINVAL; ++ if (fiq >= 0 && !pdata->fiq_enable) ++ return -EINVAL; ++ ++ state = kzalloc(sizeof(*state), GFP_KERNEL); ++ state->output.printf = fiq_debugger_printf; ++ setup_timer(&state->sleep_timer, fiq_debugger_sleep_timer_expired, ++ (unsigned long)state); ++ state->pdata = pdata; ++ state->pdev = pdev; ++ state->no_sleep = initial_no_sleep; ++ state->debug_enable = initial_debug_enable; ++ state->console_enable = initial_console_enable; ++ ++ state->fiq = fiq; ++ state->uart_irq = uart_irq; ++ state->signal_irq = platform_get_irq_byname(pdev, "signal"); ++ state->wakeup_irq = platform_get_irq_byname(pdev, "wakeup"); ++ ++ INIT_WORK(&state->work, fiq_debugger_work); ++ spin_lock_init(&state->work_lock); ++ ++ platform_set_drvdata(pdev, state); ++ ++ spin_lock_init(&state->sleep_timer_lock); ++ ++ if (state->wakeup_irq < 0 && fiq_debugger_have_fiq(state)) ++ state->no_sleep = true; ++ state->ignore_next_wakeup_irq = !state->no_sleep; ++ ++ wake_lock_init(&state->debugger_wake_lock, ++ WAKE_LOCK_SUSPEND, "serial-debug"); ++ ++ state->clk = clk_get(&pdev->dev, NULL); ++ if (IS_ERR(state->clk)) ++ state->clk = NULL; ++ ++ /* do not call pdata->uart_enable here since uart_init may still ++ * need to do some initialization before uart_enable can work. ++ * So, only try to manage the clock during init. ++ */ ++ if (state->clk) ++ clk_enable(state->clk); ++ ++ if (pdata->uart_init) { ++ ret = pdata->uart_init(pdev); ++ if (ret) ++ goto err_uart_init; ++ } ++ ++ fiq_debugger_printf_nfiq(state, ++ "\n", ++ state->no_sleep ? "" : "twice "); ++ ++#ifdef CONFIG_FIQ_GLUE ++ if (fiq_debugger_have_fiq(state)) { ++ state->handler.fiq = fiq_debugger_fiq; ++ state->handler.resume = fiq_debugger_resume; ++ ret = fiq_glue_register_handler(&state->handler); ++ if (ret) { ++ pr_err("%s: could not install fiq handler\n", __func__); ++ goto err_register_irq; ++ } ++ ++ pdata->fiq_enable(pdev, state->fiq, 1); ++ } else ++#endif ++ { ++ ret = request_irq(state->uart_irq, fiq_debugger_uart_irq, ++ IRQF_NO_SUSPEND, "debug", state); ++ if (ret) { ++ pr_err("%s: could not install irq handler\n", __func__); ++ goto err_register_irq; ++ } ++ ++ /* for irq-only mode, we want this irq to wake us up, if it ++ * can. ++ */ ++ enable_irq_wake(state->uart_irq); ++ } ++ ++ if (state->clk) ++ clk_disable(state->clk); ++ ++ if (state->signal_irq >= 0) { ++ ret = request_irq(state->signal_irq, fiq_debugger_signal_irq, ++ IRQF_TRIGGER_RISING, "debug-signal", state); ++ if (ret) ++ pr_err("serial_debugger: could not install signal_irq"); ++ } ++ ++ if (state->wakeup_irq >= 0) { ++ ret = request_irq(state->wakeup_irq, ++ fiq_debugger_wakeup_irq_handler, ++ IRQF_TRIGGER_FALLING | IRQF_DISABLED, ++ "debug-wakeup", state); ++ if (ret) { ++ pr_err("serial_debugger: " ++ "could not install wakeup irq\n"); ++ state->wakeup_irq = -1; ++ } else { ++ ret = enable_irq_wake(state->wakeup_irq); ++ if (ret) { ++ pr_err("serial_debugger: " ++ "could not enable wakeup\n"); ++ state->wakeup_irq_no_set_wake = true; ++ } ++ } ++ } ++ if (state->no_sleep) ++ fiq_debugger_handle_wakeup(state); ++ ++#if defined(CONFIG_FIQ_DEBUGGER_CONSOLE) ++ spin_lock_init(&state->console_lock); ++ state->console = fiq_debugger_console; ++ state->console.index = pdev->id; ++ if (!console_set_on_cmdline) ++ add_preferred_console(state->console.name, ++ state->console.index, NULL); ++ register_console(&state->console); ++ fiq_debugger_tty_init_one(state); ++#endif ++ return 0; ++ ++err_register_irq: ++ if (pdata->uart_free) ++ pdata->uart_free(pdev); ++err_uart_init: ++ if (state->clk) ++ clk_disable(state->clk); ++ if (state->clk) ++ clk_put(state->clk); ++ wake_lock_destroy(&state->debugger_wake_lock); ++ platform_set_drvdata(pdev, NULL); ++ kfree(state); ++ return ret; ++} ++ ++static const struct dev_pm_ops fiq_debugger_dev_pm_ops = { ++ .suspend = fiq_debugger_dev_suspend, ++ .resume = fiq_debugger_dev_resume, ++}; ++ ++static struct platform_driver fiq_debugger_driver = { ++ .probe = fiq_debugger_probe, ++ .driver = { ++ .name = "fiq_debugger", ++ .pm = &fiq_debugger_dev_pm_ops, ++ }, ++}; ++ ++static int __init fiq_debugger_init(void) ++{ ++#if defined(CONFIG_FIQ_DEBUGGER_CONSOLE) ++ fiq_debugger_tty_init(); ++#endif ++ return platform_driver_register(&fiq_debugger_driver); ++} ++ ++postcore_initcall(fiq_debugger_init); +diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger.h b/drivers/staging/android/fiq_debugger/fiq_debugger.h +new file mode 100644 +index 0000000..c9ec4f8 +--- /dev/null ++++ b/drivers/staging/android/fiq_debugger/fiq_debugger.h +@@ -0,0 +1,64 @@ ++/* ++ * drivers/staging/android/fiq_debugger/fiq_debugger.h ++ * ++ * Copyright (C) 2010 Google, Inc. ++ * Author: Colin Cross ++ * ++ * 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 _ARCH_ARM_MACH_TEGRA_FIQ_DEBUGGER_H_ ++#define _ARCH_ARM_MACH_TEGRA_FIQ_DEBUGGER_H_ ++ ++#include ++ ++#define FIQ_DEBUGGER_NO_CHAR NO_POLL_CHAR ++#define FIQ_DEBUGGER_BREAK 0x00ff0100 ++ ++#define FIQ_DEBUGGER_FIQ_IRQ_NAME "fiq" ++#define FIQ_DEBUGGER_SIGNAL_IRQ_NAME "signal" ++#define FIQ_DEBUGGER_WAKEUP_IRQ_NAME "wakeup" ++ ++/** ++ * struct fiq_debugger_pdata - fiq debugger platform data ++ * @uart_resume: used to restore uart state right before enabling ++ * the fiq. ++ * @uart_enable: Do the work necessary to communicate with the uart ++ * hw (enable clocks, etc.). This must be ref-counted. ++ * @uart_disable: Do the work necessary to disable the uart hw ++ * (disable clocks, etc.). This must be ref-counted. ++ * @uart_dev_suspend: called during PM suspend, generally not needed ++ * for real fiq mode debugger. ++ * @uart_dev_resume: called during PM resume, generally not needed ++ * for real fiq mode debugger. ++ */ ++struct fiq_debugger_pdata { ++ int (*uart_init)(struct platform_device *pdev); ++ void (*uart_free)(struct platform_device *pdev); ++ int (*uart_resume)(struct platform_device *pdev); ++ int (*uart_getc)(struct platform_device *pdev); ++ void (*uart_putc)(struct platform_device *pdev, unsigned int c); ++ void (*uart_flush)(struct platform_device *pdev); ++ void (*uart_enable)(struct platform_device *pdev); ++ void (*uart_disable)(struct platform_device *pdev); ++ ++ int (*uart_dev_suspend)(struct platform_device *pdev); ++ int (*uart_dev_resume)(struct platform_device *pdev); ++ ++ void (*fiq_enable)(struct platform_device *pdev, unsigned int fiq, ++ bool enable); ++ void (*fiq_ack)(struct platform_device *pdev, unsigned int fiq); ++ ++ void (*force_irq)(struct platform_device *pdev, unsigned int irq); ++ void (*force_irq_ack)(struct platform_device *pdev, unsigned int irq); ++}; ++ ++#endif +diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger_arm.c b/drivers/staging/android/fiq_debugger/fiq_debugger_arm.c +new file mode 100644 +index 0000000..8b3e013 +--- /dev/null ++++ b/drivers/staging/android/fiq_debugger/fiq_debugger_arm.c +@@ -0,0 +1,240 @@ ++/* ++ * Copyright (C) 2014 Google, Inc. ++ * Author: Colin Cross ++ * ++ * 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 ++#include ++ ++#include ++ ++#include "fiq_debugger_priv.h" ++ ++static char *mode_name(unsigned cpsr) ++{ ++ switch (cpsr & MODE_MASK) { ++ case USR_MODE: return "USR"; ++ case FIQ_MODE: return "FIQ"; ++ case IRQ_MODE: return "IRQ"; ++ case SVC_MODE: return "SVC"; ++ case ABT_MODE: return "ABT"; ++ case UND_MODE: return "UND"; ++ case SYSTEM_MODE: return "SYS"; ++ default: return "???"; ++ } ++} ++ ++void fiq_debugger_dump_pc(struct fiq_debugger_output *output, ++ const struct pt_regs *regs) ++{ ++ output->printf(output, " pc %08x cpsr %08x mode %s\n", ++ regs->ARM_pc, regs->ARM_cpsr, mode_name(regs->ARM_cpsr)); ++} ++ ++void fiq_debugger_dump_regs(struct fiq_debugger_output *output, ++ const struct pt_regs *regs) ++{ ++ output->printf(output, ++ " r0 %08x r1 %08x r2 %08x r3 %08x\n", ++ regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3); ++ output->printf(output, ++ " r4 %08x r5 %08x r6 %08x r7 %08x\n", ++ regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7); ++ output->printf(output, ++ " r8 %08x r9 %08x r10 %08x r11 %08x mode %s\n", ++ regs->ARM_r8, regs->ARM_r9, regs->ARM_r10, regs->ARM_fp, ++ mode_name(regs->ARM_cpsr)); ++ output->printf(output, ++ " ip %08x sp %08x lr %08x pc %08x cpsr %08x\n", ++ regs->ARM_ip, regs->ARM_sp, regs->ARM_lr, regs->ARM_pc, ++ regs->ARM_cpsr); ++} ++ ++struct mode_regs { ++ unsigned long sp_svc; ++ unsigned long lr_svc; ++ unsigned long spsr_svc; ++ ++ unsigned long sp_abt; ++ unsigned long lr_abt; ++ unsigned long spsr_abt; ++ ++ unsigned long sp_und; ++ unsigned long lr_und; ++ unsigned long spsr_und; ++ ++ unsigned long sp_irq; ++ unsigned long lr_irq; ++ unsigned long spsr_irq; ++ ++ unsigned long r8_fiq; ++ unsigned long r9_fiq; ++ unsigned long r10_fiq; ++ unsigned long r11_fiq; ++ unsigned long r12_fiq; ++ unsigned long sp_fiq; ++ unsigned long lr_fiq; ++ unsigned long spsr_fiq; ++}; ++ ++static void __naked get_mode_regs(struct mode_regs *regs) ++{ ++ asm volatile ( ++ "mrs r1, cpsr\n" ++ "msr cpsr_c, #0xd3 @(SVC_MODE | PSR_I_BIT | PSR_F_BIT)\n" ++ "stmia r0!, {r13 - r14}\n" ++ "mrs r2, spsr\n" ++ "msr cpsr_c, #0xd7 @(ABT_MODE | PSR_I_BIT | PSR_F_BIT)\n" ++ "stmia r0!, {r2, r13 - r14}\n" ++ "mrs r2, spsr\n" ++ "msr cpsr_c, #0xdb @(UND_MODE | PSR_I_BIT | PSR_F_BIT)\n" ++ "stmia r0!, {r2, r13 - r14}\n" ++ "mrs r2, spsr\n" ++ "msr cpsr_c, #0xd2 @(IRQ_MODE | PSR_I_BIT | PSR_F_BIT)\n" ++ "stmia r0!, {r2, r13 - r14}\n" ++ "mrs r2, spsr\n" ++ "msr cpsr_c, #0xd1 @(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)\n" ++ "stmia r0!, {r2, r8 - r14}\n" ++ "mrs r2, spsr\n" ++ "stmia r0!, {r2}\n" ++ "msr cpsr_c, r1\n" ++ "bx lr\n"); ++} ++ ++ ++void fiq_debugger_dump_allregs(struct fiq_debugger_output *output, ++ const struct pt_regs *regs) ++{ ++ struct mode_regs mode_regs; ++ unsigned long mode = regs->ARM_cpsr & MODE_MASK; ++ ++ fiq_debugger_dump_regs(output, regs); ++ get_mode_regs(&mode_regs); ++ ++ output->printf(output, ++ "%csvc: sp %08x lr %08x spsr %08x\n", ++ mode == SVC_MODE ? '*' : ' ', ++ mode_regs.sp_svc, mode_regs.lr_svc, mode_regs.spsr_svc); ++ output->printf(output, ++ "%cabt: sp %08x lr %08x spsr %08x\n", ++ mode == ABT_MODE ? '*' : ' ', ++ mode_regs.sp_abt, mode_regs.lr_abt, mode_regs.spsr_abt); ++ output->printf(output, ++ "%cund: sp %08x lr %08x spsr %08x\n", ++ mode == UND_MODE ? '*' : ' ', ++ mode_regs.sp_und, mode_regs.lr_und, mode_regs.spsr_und); ++ output->printf(output, ++ "%cirq: sp %08x lr %08x spsr %08x\n", ++ mode == IRQ_MODE ? '*' : ' ', ++ mode_regs.sp_irq, mode_regs.lr_irq, mode_regs.spsr_irq); ++ output->printf(output, ++ "%cfiq: r8 %08x r9 %08x r10 %08x r11 %08x r12 %08x\n", ++ mode == FIQ_MODE ? '*' : ' ', ++ mode_regs.r8_fiq, mode_regs.r9_fiq, mode_regs.r10_fiq, ++ mode_regs.r11_fiq, mode_regs.r12_fiq); ++ output->printf(output, ++ " fiq: sp %08x lr %08x spsr %08x\n", ++ mode_regs.sp_fiq, mode_regs.lr_fiq, mode_regs.spsr_fiq); ++} ++ ++struct stacktrace_state { ++ struct fiq_debugger_output *output; ++ unsigned int depth; ++}; ++ ++static int report_trace(struct stackframe *frame, void *d) ++{ ++ struct stacktrace_state *sts = d; ++ ++ if (sts->depth) { ++ sts->output->printf(sts->output, ++ " pc: %p (%pF), lr %p (%pF), sp %p, fp %p\n", ++ frame->pc, frame->pc, frame->lr, frame->lr, ++ frame->sp, frame->fp); ++ sts->depth--; ++ return 0; ++ } ++ sts->output->printf(sts->output, " ...\n"); ++ ++ return sts->depth == 0; ++} ++ ++struct frame_tail { ++ struct frame_tail *fp; ++ unsigned long sp; ++ unsigned long lr; ++} __attribute__((packed)); ++ ++static struct frame_tail *user_backtrace(struct fiq_debugger_output *output, ++ struct frame_tail *tail) ++{ ++ struct frame_tail buftail[2]; ++ ++ /* Also check accessibility of one struct frame_tail beyond */ ++ if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) { ++ output->printf(output, " invalid frame pointer %p\n", ++ tail); ++ return NULL; ++ } ++ if (__copy_from_user_inatomic(buftail, tail, sizeof(buftail))) { ++ output->printf(output, ++ " failed to copy frame pointer %p\n", tail); ++ return NULL; ++ } ++ ++ output->printf(output, " %p\n", buftail[0].lr); ++ ++ /* frame pointers should strictly progress back up the stack ++ * (towards higher addresses) */ ++ if (tail >= buftail[0].fp) ++ return NULL; ++ ++ return buftail[0].fp-1; ++} ++ ++void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output, ++ const struct pt_regs *regs, unsigned int depth, void *ssp) ++{ ++ struct frame_tail *tail; ++ struct thread_info *real_thread_info = THREAD_INFO(ssp); ++ struct stacktrace_state sts; ++ ++ sts.depth = depth; ++ sts.output = output; ++ *current_thread_info() = *real_thread_info; ++ ++ if (!current) ++ output->printf(output, "current NULL\n"); ++ else ++ output->printf(output, "pid: %d comm: %s\n", ++ current->pid, current->comm); ++ fiq_debugger_dump_regs(output, regs); ++ ++ if (!user_mode(regs)) { ++ struct stackframe frame; ++ frame.fp = regs->ARM_fp; ++ frame.sp = regs->ARM_sp; ++ frame.lr = regs->ARM_lr; ++ frame.pc = regs->ARM_pc; ++ output->printf(output, ++ " pc: %p (%pF), lr %p (%pF), sp %p, fp %p\n", ++ regs->ARM_pc, regs->ARM_pc, regs->ARM_lr, regs->ARM_lr, ++ regs->ARM_sp, regs->ARM_fp); ++ walk_stackframe(&frame, report_trace, &sts); ++ return; ++ } ++ ++ tail = ((struct frame_tail *) regs->ARM_fp) - 1; ++ while (depth-- && tail && !((unsigned long) tail & 3)) ++ tail = user_backtrace(output, tail); ++} +diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger_arm64.c b/drivers/staging/android/fiq_debugger/fiq_debugger_arm64.c +new file mode 100644 +index 0000000..99c6584 +--- /dev/null ++++ b/drivers/staging/android/fiq_debugger/fiq_debugger_arm64.c +@@ -0,0 +1,202 @@ ++/* ++ * Copyright (C) 2014 Google, Inc. ++ * Author: Colin Cross ++ * ++ * 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 ++#include ++ ++#include "fiq_debugger_priv.h" ++ ++static char *mode_name(const struct pt_regs *regs) ++{ ++ if (compat_user_mode(regs)) { ++ return "USR"; ++ } else { ++ switch (processor_mode(regs)) { ++ case PSR_MODE_EL0t: return "EL0t"; ++ case PSR_MODE_EL1t: return "EL1t"; ++ case PSR_MODE_EL1h: return "EL1h"; ++ case PSR_MODE_EL2t: return "EL2t"; ++ case PSR_MODE_EL2h: return "EL2h"; ++ default: return "???"; ++ } ++ } ++} ++ ++void fiq_debugger_dump_pc(struct fiq_debugger_output *output, ++ const struct pt_regs *regs) ++{ ++ output->printf(output, " pc %016lx cpsr %08lx mode %s\n", ++ regs->pc, regs->pstate, mode_name(regs)); ++} ++ ++void fiq_debugger_dump_regs_aarch32(struct fiq_debugger_output *output, ++ const struct pt_regs *regs) ++{ ++ output->printf(output, " r0 %08x r1 %08x r2 %08x r3 %08x\n", ++ regs->compat_usr(0), regs->compat_usr(1), ++ regs->compat_usr(2), regs->compat_usr(3)); ++ output->printf(output, " r4 %08x r5 %08x r6 %08x r7 %08x\n", ++ regs->compat_usr(4), regs->compat_usr(5), ++ regs->compat_usr(6), regs->compat_usr(7)); ++ output->printf(output, " r8 %08x r9 %08x r10 %08x r11 %08x\n", ++ regs->compat_usr(8), regs->compat_usr(9), ++ regs->compat_usr(10), regs->compat_usr(11)); ++ output->printf(output, " ip %08x sp %08x lr %08x pc %08x\n", ++ regs->compat_usr(12), regs->compat_sp, ++ regs->compat_lr, regs->pc); ++ output->printf(output, " cpsr %08x (%s)\n", ++ regs->pstate, mode_name(regs)); ++} ++ ++void fiq_debugger_dump_regs_aarch64(struct fiq_debugger_output *output, ++ const struct pt_regs *regs) ++{ ++ ++ output->printf(output, " x0 %016lx x1 %016lx\n", ++ regs->regs[0], regs->regs[1]); ++ output->printf(output, " x2 %016lx x3 %016lx\n", ++ regs->regs[2], regs->regs[3]); ++ output->printf(output, " x4 %016lx x5 %016lx\n", ++ regs->regs[4], regs->regs[5]); ++ output->printf(output, " x6 %016lx x7 %016lx\n", ++ regs->regs[6], regs->regs[7]); ++ output->printf(output, " x8 %016lx x9 %016lx\n", ++ regs->regs[8], regs->regs[9]); ++ output->printf(output, " x10 %016lx x11 %016lx\n", ++ regs->regs[10], regs->regs[11]); ++ output->printf(output, " x12 %016lx x13 %016lx\n", ++ regs->regs[12], regs->regs[13]); ++ output->printf(output, " x14 %016lx x15 %016lx\n", ++ regs->regs[14], regs->regs[15]); ++ output->printf(output, " x16 %016lx x17 %016lx\n", ++ regs->regs[16], regs->regs[17]); ++ output->printf(output, " x18 %016lx x19 %016lx\n", ++ regs->regs[18], regs->regs[19]); ++ output->printf(output, " x20 %016lx x21 %016lx\n", ++ regs->regs[20], regs->regs[21]); ++ output->printf(output, " x22 %016lx x23 %016lx\n", ++ regs->regs[22], regs->regs[23]); ++ output->printf(output, " x24 %016lx x25 %016lx\n", ++ regs->regs[24], regs->regs[25]); ++ output->printf(output, " x26 %016lx x27 %016lx\n", ++ regs->regs[26], regs->regs[27]); ++ output->printf(output, " x28 %016lx x29 %016lx\n", ++ regs->regs[28], regs->regs[29]); ++ output->printf(output, " x30 %016lx sp %016lx\n", ++ regs->regs[30], regs->sp); ++ output->printf(output, " pc %016lx cpsr %08x (%s)\n", ++ regs->pc, regs->pstate, mode_name(regs)); ++} ++ ++void fiq_debugger_dump_regs(struct fiq_debugger_output *output, ++ const struct pt_regs *regs) ++{ ++ if (compat_user_mode(regs)) ++ fiq_debugger_dump_regs_aarch32(output, regs); ++ else ++ fiq_debugger_dump_regs_aarch64(output, regs); ++} ++ ++#define READ_SPECIAL_REG(x) ({ \ ++ u64 val; \ ++ asm volatile ("mrs %0, " # x : "=r"(val)); \ ++ val; \ ++}) ++ ++void fiq_debugger_dump_allregs(struct fiq_debugger_output *output, ++ const struct pt_regs *regs) ++{ ++ u32 pstate = READ_SPECIAL_REG(CurrentEl); ++ bool in_el2 = (pstate & PSR_MODE_MASK) >= PSR_MODE_EL2t; ++ ++ fiq_debugger_dump_regs(output, regs); ++ ++ output->printf(output, " sp_el0 %016lx\n", ++ READ_SPECIAL_REG(sp_el0)); ++ ++ if (in_el2) ++ output->printf(output, " sp_el1 %016lx\n", ++ READ_SPECIAL_REG(sp_el1)); ++ ++ output->printf(output, " elr_el1 %016lx\n", ++ READ_SPECIAL_REG(elr_el1)); ++ ++ output->printf(output, " spsr_el1 %08lx\n", ++ READ_SPECIAL_REG(spsr_el1)); ++ ++ if (in_el2) { ++ output->printf(output, " spsr_irq %08lx\n", ++ READ_SPECIAL_REG(spsr_irq)); ++ output->printf(output, " spsr_abt %08lx\n", ++ READ_SPECIAL_REG(spsr_abt)); ++ output->printf(output, " spsr_und %08lx\n", ++ READ_SPECIAL_REG(spsr_und)); ++ output->printf(output, " spsr_fiq %08lx\n", ++ READ_SPECIAL_REG(spsr_fiq)); ++ output->printf(output, " spsr_el2 %08lx\n", ++ READ_SPECIAL_REG(elr_el2)); ++ output->printf(output, " spsr_el2 %08lx\n", ++ READ_SPECIAL_REG(spsr_el2)); ++ } ++} ++ ++struct stacktrace_state { ++ struct fiq_debugger_output *output; ++ unsigned int depth; ++}; ++ ++static int report_trace(struct stackframe *frame, void *d) ++{ ++ struct stacktrace_state *sts = d; ++ ++ if (sts->depth) { ++ sts->output->printf(sts->output, "%pF:\n", frame->pc); ++ sts->output->printf(sts->output, ++ " pc %016lx sp %016lx fp %016lx\n", ++ frame->pc, frame->sp, frame->fp); ++ sts->depth--; ++ return 0; ++ } ++ sts->output->printf(sts->output, " ...\n"); ++ ++ return sts->depth == 0; ++} ++ ++void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output, ++ const struct pt_regs *regs, unsigned int depth, void *ssp) ++{ ++ struct thread_info *real_thread_info = THREAD_INFO(ssp); ++ struct stacktrace_state sts; ++ ++ sts.depth = depth; ++ sts.output = output; ++ *current_thread_info() = *real_thread_info; ++ ++ if (!current) ++ output->printf(output, "current NULL\n"); ++ else ++ output->printf(output, "pid: %d comm: %s\n", ++ current->pid, current->comm); ++ fiq_debugger_dump_regs(output, regs); ++ ++ if (!user_mode(regs)) { ++ struct stackframe frame; ++ frame.fp = regs->regs[29]; ++ frame.sp = regs->sp; ++ frame.pc = regs->pc; ++ output->printf(output, "\n"); ++ walk_stackframe(&frame, report_trace, &sts); ++ } ++} +diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger_priv.h b/drivers/staging/android/fiq_debugger/fiq_debugger_priv.h +new file mode 100644 +index 0000000..d5d051f +--- /dev/null ++++ b/drivers/staging/android/fiq_debugger/fiq_debugger_priv.h +@@ -0,0 +1,37 @@ ++/* ++ * Copyright (C) 2014 Google, Inc. ++ * Author: Colin Cross ++ * ++ * 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 _FIQ_DEBUGGER_PRIV_H_ ++#define _FIQ_DEBUGGER_PRIV_H_ ++ ++#define THREAD_INFO(sp) ((struct thread_info *) \ ++ ((unsigned long)(sp) & ~(THREAD_SIZE - 1))) ++ ++struct fiq_debugger_output { ++ void (*printf)(struct fiq_debugger_output *output, const char *fmt, ...); ++}; ++ ++struct pt_regs; ++ ++void fiq_debugger_dump_pc(struct fiq_debugger_output *output, ++ const struct pt_regs *regs); ++void fiq_debugger_dump_regs(struct fiq_debugger_output *output, ++ const struct pt_regs *regs); ++void fiq_debugger_dump_allregs(struct fiq_debugger_output *output, ++ const struct pt_regs *regs); ++void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output, ++ const struct pt_regs *regs, unsigned int depth, void *ssp); ++ ++#endif +diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger_ringbuf.h b/drivers/staging/android/fiq_debugger/fiq_debugger_ringbuf.h +new file mode 100644 +index 0000000..10c3c5d +--- /dev/null ++++ b/drivers/staging/android/fiq_debugger/fiq_debugger_ringbuf.h +@@ -0,0 +1,94 @@ ++/* ++ * drivers/staging/android/fiq_debugger/fiq_debugger_ringbuf.h ++ * ++ * simple lockless ringbuffer ++ * ++ * Copyright (C) 2010 Google, 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. ++ */ ++ ++#include ++#include ++ ++struct fiq_debugger_ringbuf { ++ int len; ++ int head; ++ int tail; ++ u8 buf[]; ++}; ++ ++ ++static inline struct fiq_debugger_ringbuf *fiq_debugger_ringbuf_alloc(int len) ++{ ++ struct fiq_debugger_ringbuf *rbuf; ++ ++ rbuf = kzalloc(sizeof(*rbuf) + len, GFP_KERNEL); ++ if (rbuf == NULL) ++ return NULL; ++ ++ rbuf->len = len; ++ rbuf->head = 0; ++ rbuf->tail = 0; ++ smp_mb(); ++ ++ return rbuf; ++} ++ ++static inline void fiq_debugger_ringbuf_free(struct fiq_debugger_ringbuf *rbuf) ++{ ++ kfree(rbuf); ++} ++ ++static inline int fiq_debugger_ringbuf_level(struct fiq_debugger_ringbuf *rbuf) ++{ ++ int level = rbuf->head - rbuf->tail; ++ ++ if (level < 0) ++ level = rbuf->len + level; ++ ++ return level; ++} ++ ++static inline int fiq_debugger_ringbuf_room(struct fiq_debugger_ringbuf *rbuf) ++{ ++ return rbuf->len - fiq_debugger_ringbuf_level(rbuf) - 1; ++} ++ ++static inline u8 ++fiq_debugger_ringbuf_peek(struct fiq_debugger_ringbuf *rbuf, int i) ++{ ++ return rbuf->buf[(rbuf->tail + i) % rbuf->len]; ++} ++ ++static inline int ++fiq_debugger_ringbuf_consume(struct fiq_debugger_ringbuf *rbuf, int count) ++{ ++ count = min(count, fiq_debugger_ringbuf_level(rbuf)); ++ ++ rbuf->tail = (rbuf->tail + count) % rbuf->len; ++ smp_mb(); ++ ++ return count; ++} ++ ++static inline int ++fiq_debugger_ringbuf_push(struct fiq_debugger_ringbuf *rbuf, u8 datum) ++{ ++ if (fiq_debugger_ringbuf_room(rbuf) == 0) ++ return 0; ++ ++ rbuf->buf[rbuf->head] = datum; ++ smp_mb(); ++ rbuf->head = (rbuf->head + 1) % rbuf->len; ++ smp_mb(); ++ ++ return 1; ++} +diff --git a/drivers/staging/android/fiq_debugger/fiq_watchdog.c b/drivers/staging/android/fiq_debugger/fiq_watchdog.c +new file mode 100644 +index 0000000..194b541 +--- /dev/null ++++ b/drivers/staging/android/fiq_debugger/fiq_watchdog.c +@@ -0,0 +1,56 @@ ++/* ++ * Copyright (C) 2014 Google, 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. ++ * ++ */ ++ ++#include ++#include ++#include ++ ++#include "fiq_watchdog.h" ++#include "fiq_debugger_priv.h" ++ ++static DEFINE_RAW_SPINLOCK(fiq_watchdog_lock); ++ ++static void fiq_watchdog_printf(struct fiq_debugger_output *output, ++ const char *fmt, ...) ++{ ++ char buf[256]; ++ va_list ap; ++ int len; ++ ++ va_start(ap, fmt); ++ len = vscnprintf(buf, sizeof(buf), fmt, ap); ++ va_end(ap); ++ ++ ramoops_console_write_buf(buf, len); ++} ++ ++struct fiq_debugger_output fiq_watchdog_output = { ++ .printf = fiq_watchdog_printf, ++}; ++ ++void fiq_watchdog_triggered(const struct pt_regs *regs, void *svc_sp) ++{ ++ char msg[24]; ++ int len; ++ ++ raw_spin_lock(&fiq_watchdog_lock); ++ ++ len = scnprintf(msg, sizeof(msg), "watchdog fiq cpu %d\n", ++ THREAD_INFO(svc_sp)->cpu); ++ ramoops_console_write_buf(msg, len); ++ ++ fiq_debugger_dump_stacktrace(&fiq_watchdog_output, regs, 100, svc_sp); ++ ++ raw_spin_unlock(&fiq_watchdog_lock); ++} +diff --git a/drivers/staging/android/fiq_debugger/fiq_watchdog.h b/drivers/staging/android/fiq_debugger/fiq_watchdog.h +new file mode 100644 +index 0000000..c6b507f +--- /dev/null ++++ b/drivers/staging/android/fiq_debugger/fiq_watchdog.h +@@ -0,0 +1,20 @@ ++/* ++ * Copyright (C) 2014 Google, 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. ++ * ++ */ ++ ++#ifndef _FIQ_WATCHDOG_H_ ++#define _FIQ_WATCHDOG_H_ ++ ++void fiq_watchdog_triggered(const struct pt_regs *regs, void *svc_sp); ++ ++#endif +diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig +index 3452346..301948c 100644 +--- a/drivers/staging/android/ion/Kconfig ++++ b/drivers/staging/android/ion/Kconfig +@@ -33,3 +33,10 @@ config ION_TEGRA + help + Choose this option if you wish to use ion on an nVidia Tegra. + ++config ION_POOL_CACHE_POLICY ++ bool "Ion set page pool cache policy" ++ depends on ION ++ default y if X86 ++ help ++ Choose this option if need to explicity set cache policy of the ++ pages in the page pool. +diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c +index 56604f4..8724ef8 100644 +--- a/drivers/staging/android/ion/ion.c ++++ b/drivers/staging/android/ion/ion.c +@@ -250,7 +250,7 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, + our systems the only dma_address space is physical addresses. + Additionally, we can't afford the overhead of invalidating every + allocation via dma_map_sg. The implicit contract here is that +- memory comming from the heaps is ready for dma, ie if it has a ++ memory coming from the heaps is ready for dma, ie if it has a + cached mapping that mapping has been invalidated */ + for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) + sg_dma_address(sg) = sg_phys(sg); +@@ -902,7 +902,7 @@ void ion_pages_sync_for_device(struct device *dev, struct page *page, + sg_set_page(&sg, page, size, 0); + /* + * This is not correct - sg_dma_address needs a dma_addr_t that is valid +- * for the the targeted device, but this works on the currently targeted ++ * for the targeted device, but this works on the currently targeted + * hardware. + */ + sg_dma_address(&sg) = page_to_phys(page); +diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h +index d305bb7..443db84 100644 +--- a/drivers/staging/android/ion/ion.h ++++ b/drivers/staging/android/ion/ion.h +@@ -76,7 +76,7 @@ struct ion_platform_data { + * size + * + * Calls memblock reserve to set aside memory for heaps that are +- * located at specific memory addresses or of specfic sizes not ++ * located at specific memory addresses or of specific sizes not + * managed by the kernel + */ + void ion_reserve(struct ion_platform_data *data); +diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c +old mode 100644 +new mode 100755 +index 9156d82..e702ce6 +--- a/drivers/staging/android/ion/ion_carveout_heap.c ++++ b/drivers/staging/android/ion/ion_carveout_heap.c +@@ -167,7 +167,7 @@ struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) + if (!carveout_heap) + return ERR_PTR(-ENOMEM); + +- carveout_heap->pool = gen_pool_create(12, -1); ++ carveout_heap->pool = gen_pool_create(PAGE_SHIFT, -1); + if (!carveout_heap->pool) { + kfree(carveout_heap); + return ERR_PTR(-ENOMEM); +diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c +index 5864f3d..b021748 100644 +--- a/drivers/staging/android/ion/ion_page_pool.c ++++ b/drivers/staging/android/ion/ion_page_pool.c +@@ -30,6 +30,8 @@ static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool) + + if (!page) + return NULL; ++ ion_page_pool_alloc_set_cache_policy(pool, page); ++ + ion_pages_sync_for_device(NULL, page, PAGE_SIZE << pool->order, + DMA_BIDIRECTIONAL); + return page; +@@ -38,6 +40,7 @@ static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool) + static void ion_page_pool_free_pages(struct ion_page_pool *pool, + struct page *page) + { ++ ion_page_pool_free_set_cache_policy(pool, page); + __free_pages(page, pool->order); + } + +@@ -103,6 +106,11 @@ void ion_page_pool_free(struct ion_page_pool *pool, struct page *page) + ion_page_pool_free_pages(pool, page); + } + ++void ion_page_pool_free_immediate(struct ion_page_pool *pool, struct page *page) ++{ ++ ion_page_pool_free_pages(pool, page); ++} ++ + static int ion_page_pool_total(struct ion_page_pool *pool, bool high) + { + int count = pool->low_count; +@@ -120,7 +128,7 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, + bool high; + + if (current_is_kswapd()) +- high = 1; ++ high = true; + else + high = !!(gfp_mask & __GFP_HIGHMEM); + +diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h +index c8f0175..0e3b8a6 100644 +--- a/drivers/staging/android/ion/ion_priv.h ++++ b/drivers/staging/android/ion/ion_priv.h +@@ -26,6 +26,9 @@ + #include + #include + #include ++#ifdef CONFIG_ION_POOL_CACHE_POLICY ++#include ++#endif + + #include "ion.h" + +@@ -345,7 +348,7 @@ void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, + * functions for creating and destroying a heap pool -- allows you + * to keep a pool of pre allocated memory to use from your heap. Keeping + * a pool of memory that is ready for dma, ie any cached mapping have been +- * invalidated from the cache, provides a significant peformance benefit on ++ * invalidated from the cache, provides a significant performance benefit on + * many systems */ + + /** +@@ -362,7 +365,7 @@ void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, + * + * Allows you to keep a pool of pre allocated pages to use from your heap. + * Keeping a pool of pages that is ready for dma, ie any cached mapping have +- * been invalidated from the cache, provides a significant peformance benefit ++ * been invalidated from the cache, provides a significant performance benefit + * on many systems + */ + struct ion_page_pool { +@@ -380,6 +383,37 @@ struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order); + void ion_page_pool_destroy(struct ion_page_pool *); + struct page *ion_page_pool_alloc(struct ion_page_pool *); + void ion_page_pool_free(struct ion_page_pool *, struct page *); ++void ion_page_pool_free_immediate(struct ion_page_pool *, struct page *); ++ ++#ifdef CONFIG_ION_POOL_CACHE_POLICY ++static inline void ion_page_pool_alloc_set_cache_policy ++ (struct ion_page_pool *pool, ++ struct page *page){ ++ void *va = page_address(page); ++ ++ if (va) ++ set_memory_wc((unsigned long)va, 1 << pool->order); ++} ++ ++static inline void ion_page_pool_free_set_cache_policy ++ (struct ion_page_pool *pool, ++ struct page *page){ ++ void *va = page_address(page); ++ ++ if (va) ++ set_memory_wb((unsigned long)va, 1 << pool->order); ++ ++} ++#else ++static inline void ion_page_pool_alloc_set_cache_policy ++ (struct ion_page_pool *pool, ++ struct page *page){ } ++ ++static inline void ion_page_pool_free_set_cache_policy ++ (struct ion_page_pool *pool, ++ struct page *page){ } ++#endif ++ + + /** ion_page_pool_shrink - shrinks the size of the memory cached in the pool + * @pool: the pool +diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c +index da2a63c..1f9feb7 100644 +--- a/drivers/staging/android/ion/ion_system_heap.c ++++ b/drivers/staging/android/ion/ion_system_heap.c +@@ -85,8 +85,10 @@ static void free_buffer_page(struct ion_system_heap *heap, + + if (!cached && !(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)) { + struct ion_page_pool *pool = heap->pools[order_to_index(order)]; +- +- ion_page_pool_free(pool, page); ++ if (buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE) ++ ion_page_pool_free_immediate(pool, page); ++ else ++ ion_page_pool_free(pool, page); + } else { + __free_pages(page, order); + } +diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c +deleted file mode 100644 +index a673ffa..0000000 +--- a/drivers/staging/android/logger.c ++++ /dev/null +@@ -1,808 +0,0 @@ +-/* +- * drivers/misc/logger.c +- * +- * A Logging Subsystem +- * +- * Copyright (C) 2007-2008 Google, Inc. +- * +- * Robert Love +- * +- * 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) "logger: " fmt +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include "logger.h" +- +-#include +- +-/** +- * struct logger_log - represents a specific log, such as 'main' or 'radio' +- * @buffer: The actual ring buffer +- * @misc: The "misc" device representing the log +- * @wq: The wait queue for @readers +- * @readers: This log's readers +- * @mutex: The mutex that protects the @buffer +- * @w_off: The current write head offset +- * @head: The head, or location that readers start reading at. +- * @size: The size of the log +- * @logs: The list of log channels +- * +- * This structure lives from module insertion until module removal, so it does +- * not need additional reference counting. The structure is protected by the +- * mutex 'mutex'. +- */ +-struct logger_log { +- unsigned char *buffer; +- struct miscdevice misc; +- wait_queue_head_t wq; +- struct list_head readers; +- struct mutex mutex; +- size_t w_off; +- size_t head; +- size_t size; +- struct list_head logs; +-}; +- +-static LIST_HEAD(log_list); +- +- +-/** +- * struct logger_reader - a logging device open for reading +- * @log: The associated log +- * @list: The associated entry in @logger_log's list +- * @r_off: The current read head offset. +- * @r_all: Reader can read all entries +- * @r_ver: Reader ABI version +- * +- * This object lives from open to release, so we don't need additional +- * reference counting. The structure is protected by log->mutex. +- */ +-struct logger_reader { +- struct logger_log *log; +- struct list_head list; +- size_t r_off; +- bool r_all; +- int r_ver; +-}; +- +-/* logger_offset - returns index 'n' into the log via (optimized) modulus */ +-static size_t logger_offset(struct logger_log *log, size_t n) +-{ +- return n & (log->size - 1); +-} +- +- +-/* +- * file_get_log - Given a file structure, return the associated log +- * +- * This isn't aesthetic. We have several goals: +- * +- * 1) Need to quickly obtain the associated log during an I/O operation +- * 2) Readers need to maintain state (logger_reader) +- * 3) Writers need to be very fast (open() should be a near no-op) +- * +- * In the reader case, we can trivially go file->logger_reader->logger_log. +- * For a writer, we don't want to maintain a logger_reader, so we just go +- * file->logger_log. Thus what file->private_data points at depends on whether +- * or not the file was opened for reading. This function hides that dirtiness. +- */ +-static inline struct logger_log *file_get_log(struct file *file) +-{ +- if (file->f_mode & FMODE_READ) { +- struct logger_reader *reader = file->private_data; +- +- return reader->log; +- } +- return file->private_data; +-} +- +-/* +- * get_entry_header - returns a pointer to the logger_entry header within +- * 'log' starting at offset 'off'. A temporary logger_entry 'scratch' must +- * be provided. Typically the return value will be a pointer within +- * 'logger->buf'. However, a pointer to 'scratch' may be returned if +- * the log entry spans the end and beginning of the circular buffer. +- */ +-static struct logger_entry *get_entry_header(struct logger_log *log, +- size_t off, struct logger_entry *scratch) +-{ +- size_t len = min(sizeof(struct logger_entry), log->size - off); +- +- if (len != sizeof(struct logger_entry)) { +- memcpy(((void *) scratch), log->buffer + off, len); +- memcpy(((void *) scratch) + len, log->buffer, +- sizeof(struct logger_entry) - len); +- return scratch; +- } +- +- return (struct logger_entry *) (log->buffer + off); +-} +- +-/* +- * get_entry_msg_len - Grabs the length of the message of the entry +- * starting from from 'off'. +- * +- * An entry length is 2 bytes (16 bits) in host endian order. +- * In the log, the length does not include the size of the log entry structure. +- * This function returns the size including the log entry structure. +- * +- * Caller needs to hold log->mutex. +- */ +-static __u32 get_entry_msg_len(struct logger_log *log, size_t off) +-{ +- struct logger_entry scratch; +- struct logger_entry *entry; +- +- entry = get_entry_header(log, off, &scratch); +- return entry->len; +-} +- +-static size_t get_user_hdr_len(int ver) +-{ +- if (ver < 2) +- return sizeof(struct user_logger_entry_compat); +- return sizeof(struct logger_entry); +-} +- +-static ssize_t copy_header_to_user(int ver, struct logger_entry *entry, +- char __user *buf) +-{ +- void *hdr; +- size_t hdr_len; +- struct user_logger_entry_compat v1; +- +- if (ver < 2) { +- v1.len = entry->len; +- v1.__pad = 0; +- v1.pid = entry->pid; +- v1.tid = entry->tid; +- v1.sec = entry->sec; +- v1.nsec = entry->nsec; +- hdr = &v1; +- hdr_len = sizeof(struct user_logger_entry_compat); +- } else { +- hdr = entry; +- hdr_len = sizeof(struct logger_entry); +- } +- +- return copy_to_user(buf, hdr, hdr_len); +-} +- +-/* +- * do_read_log_to_user - reads exactly 'count' bytes from 'log' into the +- * user-space buffer 'buf'. Returns 'count' on success. +- * +- * Caller must hold log->mutex. +- */ +-static ssize_t do_read_log_to_user(struct logger_log *log, +- struct logger_reader *reader, +- char __user *buf, +- size_t count) +-{ +- struct logger_entry scratch; +- struct logger_entry *entry; +- size_t len; +- size_t msg_start; +- +- /* +- * First, copy the header to userspace, using the version of +- * the header requested +- */ +- entry = get_entry_header(log, reader->r_off, &scratch); +- if (copy_header_to_user(reader->r_ver, entry, buf)) +- return -EFAULT; +- +- count -= get_user_hdr_len(reader->r_ver); +- buf += get_user_hdr_len(reader->r_ver); +- msg_start = logger_offset(log, +- reader->r_off + sizeof(struct logger_entry)); +- +- /* +- * We read from the msg in two disjoint operations. First, we read from +- * the current msg head offset up to 'count' bytes or to the end of +- * the log, whichever comes first. +- */ +- len = min(count, log->size - msg_start); +- if (copy_to_user(buf, log->buffer + msg_start, len)) +- return -EFAULT; +- +- /* +- * Second, we read any remaining bytes, starting back at the head of +- * the log. +- */ +- if (count != len) +- if (copy_to_user(buf + len, log->buffer, count - len)) +- return -EFAULT; +- +- reader->r_off = logger_offset(log, reader->r_off + +- sizeof(struct logger_entry) + count); +- +- return count + get_user_hdr_len(reader->r_ver); +-} +- +-/* +- * get_next_entry_by_uid - Starting at 'off', returns an offset into +- * 'log->buffer' which contains the first entry readable by 'euid' +- */ +-static size_t get_next_entry_by_uid(struct logger_log *log, +- size_t off, kuid_t euid) +-{ +- while (off != log->w_off) { +- struct logger_entry *entry; +- struct logger_entry scratch; +- size_t next_len; +- +- entry = get_entry_header(log, off, &scratch); +- +- if (uid_eq(entry->euid, euid)) +- return off; +- +- next_len = sizeof(struct logger_entry) + entry->len; +- off = logger_offset(log, off + next_len); +- } +- +- return off; +-} +- +-/* +- * logger_read - our log's read() method +- * +- * Behavior: +- * +- * - O_NONBLOCK works +- * - If there are no log entries to read, blocks until log is written to +- * - Atomically reads exactly one log entry +- * +- * Will set errno to EINVAL if read +- * buffer is insufficient to hold next entry. +- */ +-static ssize_t logger_read(struct file *file, char __user *buf, +- size_t count, loff_t *pos) +-{ +- struct logger_reader *reader = file->private_data; +- struct logger_log *log = reader->log; +- ssize_t ret; +- DEFINE_WAIT(wait); +- +-start: +- while (1) { +- mutex_lock(&log->mutex); +- +- prepare_to_wait(&log->wq, &wait, TASK_INTERRUPTIBLE); +- +- ret = (log->w_off == reader->r_off); +- mutex_unlock(&log->mutex); +- if (!ret) +- break; +- +- if (file->f_flags & O_NONBLOCK) { +- ret = -EAGAIN; +- break; +- } +- +- if (signal_pending(current)) { +- ret = -EINTR; +- break; +- } +- +- schedule(); +- } +- +- finish_wait(&log->wq, &wait); +- if (ret) +- return ret; +- +- mutex_lock(&log->mutex); +- +- if (!reader->r_all) +- reader->r_off = get_next_entry_by_uid(log, +- reader->r_off, current_euid()); +- +- /* is there still something to read or did we race? */ +- if (unlikely(log->w_off == reader->r_off)) { +- mutex_unlock(&log->mutex); +- goto start; +- } +- +- /* get the size of the next entry */ +- ret = get_user_hdr_len(reader->r_ver) + +- get_entry_msg_len(log, reader->r_off); +- if (count < ret) { +- ret = -EINVAL; +- goto out; +- } +- +- /* get exactly one entry from the log */ +- ret = do_read_log_to_user(log, reader, buf, ret); +- +-out: +- mutex_unlock(&log->mutex); +- +- return ret; +-} +- +-/* +- * get_next_entry - return the offset of the first valid entry at least 'len' +- * bytes after 'off'. +- * +- * Caller must hold log->mutex. +- */ +-static size_t get_next_entry(struct logger_log *log, size_t off, size_t len) +-{ +- size_t count = 0; +- +- do { +- size_t nr = sizeof(struct logger_entry) + +- get_entry_msg_len(log, off); +- off = logger_offset(log, off + nr); +- count += nr; +- } while (count < len); +- +- return off; +-} +- +-/* +- * is_between - is a < c < b, accounting for wrapping of a, b, and c +- * positions in the buffer +- * +- * That is, if ab, check for c outside (not between) a and b +- * +- * |------- a xxxxxxxx b --------| +- * c^ +- * +- * |xxxxx b --------- a xxxxxxxxx| +- * c^ +- * or c^ +- */ +-static inline int is_between(size_t a, size_t b, size_t c) +-{ +- if (a < b) { +- /* is c between a and b? */ +- if (a < c && c <= b) +- return 1; +- } else { +- /* is c outside of b through a? */ +- if (c <= b || a < c) +- return 1; +- } +- +- return 0; +-} +- +-/* +- * fix_up_readers - walk the list of all readers and "fix up" any who were +- * lapped by the writer; also do the same for the default "start head". +- * We do this by "pulling forward" the readers and start head to the first +- * entry after the new write head. +- * +- * The caller needs to hold log->mutex. +- */ +-static void fix_up_readers(struct logger_log *log, size_t len) +-{ +- size_t old = log->w_off; +- size_t new = logger_offset(log, old + len); +- struct logger_reader *reader; +- +- if (is_between(old, new, log->head)) +- log->head = get_next_entry(log, log->head, len); +- +- list_for_each_entry(reader, &log->readers, list) +- if (is_between(old, new, reader->r_off)) +- reader->r_off = get_next_entry(log, reader->r_off, len); +-} +- +-/* +- * logger_write_iter - our write method, implementing support for write(), +- * writev(), and aio_write(). Writes are our fast path, and we try to optimize +- * them above all else. +- */ +-static ssize_t logger_write_iter(struct kiocb *iocb, struct iov_iter *from) +-{ +- struct logger_log *log = file_get_log(iocb->ki_filp); +- struct logger_entry header; +- struct timespec now; +- size_t len, count, w_off; +- +- count = min_t(size_t, iocb->ki_nbytes, LOGGER_ENTRY_MAX_PAYLOAD); +- +- now = current_kernel_time(); +- +- header.pid = current->tgid; +- header.tid = current->pid; +- header.sec = now.tv_sec; +- header.nsec = now.tv_nsec; +- header.euid = current_euid(); +- header.len = count; +- header.hdr_size = sizeof(struct logger_entry); +- +- /* null writes succeed, return zero */ +- if (unlikely(!header.len)) +- return 0; +- +- mutex_lock(&log->mutex); +- +- /* +- * Fix up any readers, pulling them forward to the first readable +- * entry after (what will be) the new write offset. We do this now +- * because if we partially fail, we can end up with clobbered log +- * entries that encroach on readable buffer. +- */ +- fix_up_readers(log, sizeof(struct logger_entry) + header.len); +- +- len = min(sizeof(header), log->size - log->w_off); +- memcpy(log->buffer + log->w_off, &header, len); +- memcpy(log->buffer, (char *)&header + len, sizeof(header) - len); +- +- /* Work with a copy until we are ready to commit the whole entry */ +- w_off = logger_offset(log, log->w_off + sizeof(struct logger_entry)); +- +- len = min(count, log->size - w_off); +- +- if (copy_from_iter(log->buffer + w_off, len, from) != len) { +- /* +- * Note that by not updating log->w_off, this abandons the +- * portion of the new entry that *was* successfully +- * copied, just above. This is intentional to avoid +- * message corruption from missing fragments. +- */ +- mutex_unlock(&log->mutex); +- return -EFAULT; +- } +- +- if (copy_from_iter(log->buffer, count - len, from) != count - len) { +- mutex_unlock(&log->mutex); +- return -EFAULT; +- } +- +- log->w_off = logger_offset(log, w_off + count); +- mutex_unlock(&log->mutex); +- +- /* wake up any blocked readers */ +- wake_up_interruptible(&log->wq); +- +- return len; +-} +- +-static struct logger_log *get_log_from_minor(int minor) +-{ +- struct logger_log *log; +- +- list_for_each_entry(log, &log_list, logs) +- if (log->misc.minor == minor) +- return log; +- return NULL; +-} +- +-/* +- * logger_open - the log's open() file operation +- * +- * Note how near a no-op this is in the write-only case. Keep it that way! +- */ +-static int logger_open(struct inode *inode, struct file *file) +-{ +- struct logger_log *log; +- int ret; +- +- ret = nonseekable_open(inode, file); +- if (ret) +- return ret; +- +- log = get_log_from_minor(MINOR(inode->i_rdev)); +- if (!log) +- return -ENODEV; +- +- if (file->f_mode & FMODE_READ) { +- struct logger_reader *reader; +- +- reader = kmalloc(sizeof(struct logger_reader), GFP_KERNEL); +- if (!reader) +- return -ENOMEM; +- +- reader->log = log; +- reader->r_ver = 1; +- reader->r_all = in_egroup_p(inode->i_gid) || +- capable(CAP_SYSLOG); +- +- INIT_LIST_HEAD(&reader->list); +- +- mutex_lock(&log->mutex); +- reader->r_off = log->head; +- list_add_tail(&reader->list, &log->readers); +- mutex_unlock(&log->mutex); +- +- file->private_data = reader; +- } else +- file->private_data = log; +- +- return 0; +-} +- +-/* +- * logger_release - the log's release file operation +- * +- * Note this is a total no-op in the write-only case. Keep it that way! +- */ +-static int logger_release(struct inode *ignored, struct file *file) +-{ +- if (file->f_mode & FMODE_READ) { +- struct logger_reader *reader = file->private_data; +- struct logger_log *log = reader->log; +- +- mutex_lock(&log->mutex); +- list_del(&reader->list); +- mutex_unlock(&log->mutex); +- +- kfree(reader); +- } +- +- return 0; +-} +- +-/* +- * logger_poll - the log's poll file operation, for poll/select/epoll +- * +- * Note we always return POLLOUT, because you can always write() to the log. +- * Note also that, strictly speaking, a return value of POLLIN does not +- * guarantee that the log is readable without blocking, as there is a small +- * chance that the writer can lap the reader in the interim between poll() +- * returning and the read() request. +- */ +-static unsigned int logger_poll(struct file *file, poll_table *wait) +-{ +- struct logger_reader *reader; +- struct logger_log *log; +- unsigned int ret = POLLOUT | POLLWRNORM; +- +- if (!(file->f_mode & FMODE_READ)) +- return ret; +- +- reader = file->private_data; +- log = reader->log; +- +- poll_wait(file, &log->wq, wait); +- +- mutex_lock(&log->mutex); +- if (!reader->r_all) +- reader->r_off = get_next_entry_by_uid(log, +- reader->r_off, current_euid()); +- +- if (log->w_off != reader->r_off) +- ret |= POLLIN | POLLRDNORM; +- mutex_unlock(&log->mutex); +- +- return ret; +-} +- +-static long logger_set_version(struct logger_reader *reader, void __user *arg) +-{ +- int version; +- +- if (copy_from_user(&version, arg, sizeof(int))) +- return -EFAULT; +- +- if ((version < 1) || (version > 2)) +- return -EINVAL; +- +- reader->r_ver = version; +- return 0; +-} +- +-static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +-{ +- struct logger_log *log = file_get_log(file); +- struct logger_reader *reader; +- long ret = -EINVAL; +- void __user *argp = (void __user *) arg; +- +- mutex_lock(&log->mutex); +- +- switch (cmd) { +- case LOGGER_GET_LOG_BUF_SIZE: +- ret = log->size; +- break; +- case LOGGER_GET_LOG_LEN: +- if (!(file->f_mode & FMODE_READ)) { +- ret = -EBADF; +- break; +- } +- reader = file->private_data; +- if (log->w_off >= reader->r_off) +- ret = log->w_off - reader->r_off; +- else +- ret = (log->size - reader->r_off) + log->w_off; +- break; +- case LOGGER_GET_NEXT_ENTRY_LEN: +- if (!(file->f_mode & FMODE_READ)) { +- ret = -EBADF; +- break; +- } +- reader = file->private_data; +- +- if (!reader->r_all) +- reader->r_off = get_next_entry_by_uid(log, +- reader->r_off, current_euid()); +- +- if (log->w_off != reader->r_off) +- ret = get_user_hdr_len(reader->r_ver) + +- get_entry_msg_len(log, reader->r_off); +- else +- ret = 0; +- break; +- case LOGGER_FLUSH_LOG: +- if (!(file->f_mode & FMODE_WRITE)) { +- ret = -EBADF; +- break; +- } +- if (!(in_egroup_p(file_inode(file)->i_gid) || +- capable(CAP_SYSLOG))) { +- ret = -EPERM; +- break; +- } +- list_for_each_entry(reader, &log->readers, list) +- reader->r_off = log->w_off; +- log->head = log->w_off; +- ret = 0; +- break; +- case LOGGER_GET_VERSION: +- if (!(file->f_mode & FMODE_READ)) { +- ret = -EBADF; +- break; +- } +- reader = file->private_data; +- ret = reader->r_ver; +- break; +- case LOGGER_SET_VERSION: +- if (!(file->f_mode & FMODE_READ)) { +- ret = -EBADF; +- break; +- } +- reader = file->private_data; +- ret = logger_set_version(reader, argp); +- break; +- } +- +- mutex_unlock(&log->mutex); +- +- return ret; +-} +- +-static const struct file_operations logger_fops = { +- .owner = THIS_MODULE, +- .read = logger_read, +- .write_iter = logger_write_iter, +- .poll = logger_poll, +- .unlocked_ioctl = logger_ioctl, +- .compat_ioctl = logger_ioctl, +- .open = logger_open, +- .release = logger_release, +-}; +- +-/* +- * Log size must must be a power of two, and greater than +- * (LOGGER_ENTRY_MAX_PAYLOAD + sizeof(struct logger_entry)). +- */ +-static int __init create_log(char *log_name, int size) +-{ +- int ret = 0; +- struct logger_log *log; +- unsigned char *buffer; +- +- buffer = vmalloc(size); +- if (buffer == NULL) +- return -ENOMEM; +- +- log = kzalloc(sizeof(struct logger_log), GFP_KERNEL); +- if (log == NULL) { +- ret = -ENOMEM; +- goto out_free_buffer; +- } +- log->buffer = buffer; +- +- log->misc.minor = MISC_DYNAMIC_MINOR; +- log->misc.name = kstrdup(log_name, GFP_KERNEL); +- if (log->misc.name == NULL) { +- ret = -ENOMEM; +- goto out_free_log; +- } +- +- log->misc.fops = &logger_fops; +- log->misc.parent = NULL; +- +- init_waitqueue_head(&log->wq); +- INIT_LIST_HEAD(&log->readers); +- mutex_init(&log->mutex); +- log->w_off = 0; +- log->head = 0; +- log->size = size; +- +- INIT_LIST_HEAD(&log->logs); +- list_add_tail(&log->logs, &log_list); +- +- /* finally, initialize the misc device for this log */ +- ret = misc_register(&log->misc); +- if (unlikely(ret)) { +- pr_err("failed to register misc device for log '%s'!\n", +- log->misc.name); +- goto out_free_misc_name; +- } +- +- pr_info("created %luK log '%s'\n", +- (unsigned long) log->size >> 10, log->misc.name); +- +- return 0; +- +-out_free_misc_name: +- kfree(log->misc.name); +- +-out_free_log: +- kfree(log); +- +-out_free_buffer: +- vfree(buffer); +- return ret; +-} +- +-static int __init logger_init(void) +-{ +- int ret; +- +- ret = create_log(LOGGER_LOG_MAIN, 256*1024); +- if (unlikely(ret)) +- goto out; +- +- ret = create_log(LOGGER_LOG_EVENTS, 256*1024); +- if (unlikely(ret)) +- goto out; +- +- ret = create_log(LOGGER_LOG_RADIO, 256*1024); +- if (unlikely(ret)) +- goto out; +- +- ret = create_log(LOGGER_LOG_SYSTEM, 256*1024); +- if (unlikely(ret)) +- goto out; +- +-out: +- return ret; +-} +- +-static void __exit logger_exit(void) +-{ +- struct logger_log *current_log, *next_log; +- +- list_for_each_entry_safe(current_log, next_log, &log_list, logs) { +- /* we have to delete all the entry inside log_list */ +- misc_deregister(¤t_log->misc); +- vfree(current_log->buffer); +- kfree(current_log->misc.name); +- list_del(¤t_log->logs); +- kfree(current_log); +- } +-} +- +- +-device_initcall(logger_init); +-module_exit(logger_exit); +- +-MODULE_LICENSE("GPL"); +-MODULE_AUTHOR("Robert Love, "); +-MODULE_DESCRIPTION("Android Logger"); +diff --git a/drivers/staging/android/logger.h b/drivers/staging/android/logger.h +deleted file mode 100644 +index 70af7d8..0000000 +--- a/drivers/staging/android/logger.h ++++ /dev/null +@@ -1,89 +0,0 @@ +-/* include/linux/logger.h +- * +- * Copyright (C) 2007-2008 Google, Inc. +- * Author: Robert Love +- * +- * 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 _LINUX_LOGGER_H +-#define _LINUX_LOGGER_H +- +-#include +-#include +- +-/** +- * struct user_logger_entry_compat - defines a single entry that is given to a logger +- * @len: The length of the payload +- * @__pad: Two bytes of padding that appear to be required +- * @pid: The generating process' process ID +- * @tid: The generating process' thread ID +- * @sec: The number of seconds that have elapsed since the Epoch +- * @nsec: The number of nanoseconds that have elapsed since @sec +- * @msg: The message that is to be logged +- * +- * The userspace structure for version 1 of the logger_entry ABI. +- * This structure is returned to userspace unless the caller requests +- * an upgrade to a newer ABI version. +- */ +-struct user_logger_entry_compat { +- __u16 len; +- __u16 __pad; +- __s32 pid; +- __s32 tid; +- __s32 sec; +- __s32 nsec; +- char msg[0]; +-}; +- +-/** +- * struct logger_entry - defines a single entry that is given to a logger +- * @len: The length of the payload +- * @hdr_size: sizeof(struct logger_entry_v2) +- * @pid: The generating process' process ID +- * @tid: The generating process' thread ID +- * @sec: The number of seconds that have elapsed since the Epoch +- * @nsec: The number of nanoseconds that have elapsed since @sec +- * @euid: Effective UID of logger +- * @msg: The message that is to be logged +- * +- * The structure for version 2 of the logger_entry ABI. +- * This structure is returned to userspace if ioctl(LOGGER_SET_VERSION) +- * is called with version >= 2 +- */ +-struct logger_entry { +- __u16 len; +- __u16 hdr_size; +- __s32 pid; +- __s32 tid; +- __s32 sec; +- __s32 nsec; +- kuid_t euid; +- char msg[0]; +-}; +- +-#define LOGGER_LOG_RADIO "log_radio" /* radio-related messages */ +-#define LOGGER_LOG_EVENTS "log_events" /* system/hardware events */ +-#define LOGGER_LOG_SYSTEM "log_system" /* system/framework messages */ +-#define LOGGER_LOG_MAIN "log_main" /* everything else */ +- +-#define LOGGER_ENTRY_MAX_PAYLOAD 4076 +- +-#define __LOGGERIO 0xAE +- +-#define LOGGER_GET_LOG_BUF_SIZE _IO(__LOGGERIO, 1) /* size of log */ +-#define LOGGER_GET_LOG_LEN _IO(__LOGGERIO, 2) /* used log len */ +-#define LOGGER_GET_NEXT_ENTRY_LEN _IO(__LOGGERIO, 3) /* next entry len */ +-#define LOGGER_FLUSH_LOG _IO(__LOGGERIO, 4) /* flush log */ +-#define LOGGER_GET_VERSION _IO(__LOGGERIO, 5) /* abi version */ +-#define LOGGER_SET_VERSION _IO(__LOGGERIO, 6) /* abi version */ +- +-#endif /* _LINUX_LOGGER_H */ +diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c +index b545d3d..ca92b60 100644 +--- a/drivers/staging/android/lowmemorykiller.c ++++ b/drivers/staging/android/lowmemorykiller.c +@@ -39,7 +39,6 @@ + #include + #include + #include +-#include + #include + + static uint32_t lowmem_debug_level = 1; +@@ -83,6 +82,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) + int tasksize; + int i; + short min_score_adj = OOM_SCORE_ADJ_MAX + 1; ++ int minfree = 0; + int selected_tasksize = 0; + short selected_oom_score_adj; + int array_size = ARRAY_SIZE(lowmem_adj); +@@ -96,8 +96,8 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) + if (lowmem_minfree_size < array_size) + array_size = lowmem_minfree_size; + for (i = 0; i < array_size; i++) { +- if (other_free < lowmem_minfree[i] && +- other_file < lowmem_minfree[i]) { ++ minfree = lowmem_minfree[i]; ++ if (other_free < minfree && other_file < minfree) { + min_score_adj = lowmem_adj[i]; + break; + } +@@ -152,13 +152,22 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) + selected = p; + selected_tasksize = tasksize; + selected_oom_score_adj = oom_score_adj; +- lowmem_print(2, "select %d (%s), adj %hd, size %d, to kill\n", +- p->pid, p->comm, oom_score_adj, tasksize); ++ lowmem_print(2, "select '%s' (%d), adj %hd, size %d, to kill\n", ++ p->comm, p->pid, oom_score_adj, tasksize); + } + if (selected) { +- lowmem_print(1, "send sigkill to %d (%s), adj %hd, size %d\n", +- selected->pid, selected->comm, +- selected_oom_score_adj, selected_tasksize); ++ lowmem_print(1, "Killing '%s' (%d), adj %hd,\n" \ ++ " to free %ldkB on behalf of '%s' (%d) because\n" \ ++ " cache %ldkB is below limit %ldkB for oom_score_adj %hd\n" \ ++ " Free memory is %ldkB above reserved\n", ++ selected->comm, selected->pid, ++ selected_oom_score_adj, ++ selected_tasksize * (long)(PAGE_SIZE / 1024), ++ current->comm, current->pid, ++ other_file * (long)(PAGE_SIZE / 1024), ++ minfree * (long)(PAGE_SIZE / 1024), ++ min_score_adj, ++ other_free * (long)(PAGE_SIZE / 1024)); + lowmem_deathpending_timeout = jiffies + HZ; + set_tsk_thread_flag(selected, TIF_MEMDIE); + send_sig(SIGKILL, selected, 0); +@@ -188,9 +197,92 @@ static void __exit lowmem_exit(void) + unregister_shrinker(&lowmem_shrinker); + } + ++#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES ++static short lowmem_oom_adj_to_oom_score_adj(short oom_adj) ++{ ++ if (oom_adj == OOM_ADJUST_MAX) ++ return OOM_SCORE_ADJ_MAX; ++ else ++ return (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE; ++} ++ ++static void lowmem_autodetect_oom_adj_values(void) ++{ ++ int i; ++ short oom_adj; ++ short oom_score_adj; ++ int array_size = ARRAY_SIZE(lowmem_adj); ++ ++ if (lowmem_adj_size < array_size) ++ array_size = lowmem_adj_size; ++ ++ if (array_size <= 0) ++ return; ++ ++ oom_adj = lowmem_adj[array_size - 1]; ++ if (oom_adj > OOM_ADJUST_MAX) ++ return; ++ ++ oom_score_adj = lowmem_oom_adj_to_oom_score_adj(oom_adj); ++ if (oom_score_adj <= OOM_ADJUST_MAX) ++ return; ++ ++ lowmem_print(1, "lowmem_shrink: convert oom_adj to oom_score_adj:\n"); ++ for (i = 0; i < array_size; i++) { ++ oom_adj = lowmem_adj[i]; ++ oom_score_adj = lowmem_oom_adj_to_oom_score_adj(oom_adj); ++ lowmem_adj[i] = oom_score_adj; ++ lowmem_print(1, "oom_adj %d => oom_score_adj %d\n", ++ oom_adj, oom_score_adj); ++ } ++} ++ ++static int lowmem_adj_array_set(const char *val, const struct kernel_param *kp) ++{ ++ int ret; ++ ++ ret = param_array_ops.set(val, kp); ++ ++ /* HACK: Autodetect oom_adj values in lowmem_adj array */ ++ lowmem_autodetect_oom_adj_values(); ++ ++ return ret; ++} ++ ++static int lowmem_adj_array_get(char *buffer, const struct kernel_param *kp) ++{ ++ return param_array_ops.get(buffer, kp); ++} ++ ++static void lowmem_adj_array_free(void *arg) ++{ ++ param_array_ops.free(arg); ++} ++ ++static struct kernel_param_ops lowmem_adj_array_ops = { ++ .set = lowmem_adj_array_set, ++ .get = lowmem_adj_array_get, ++ .free = lowmem_adj_array_free, ++}; ++ ++static const struct kparam_array __param_arr_adj = { ++ .max = ARRAY_SIZE(lowmem_adj), ++ .num = &lowmem_adj_size, ++ .ops = ¶m_ops_short, ++ .elemsize = sizeof(lowmem_adj[0]), ++ .elem = lowmem_adj, ++}; ++#endif ++ + module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR); ++#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES ++module_param_cb(adj, &lowmem_adj_array_ops, ++ .arr = &__param_arr_adj, S_IRUGO | S_IWUSR); ++__MODULE_PARM_TYPE(adj, "array of short"); ++#else + module_param_array_named(adj, lowmem_adj, short, &lowmem_adj_size, + S_IRUGO | S_IWUSR); ++#endif + module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size, + S_IRUGO | S_IWUSR); + module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR); +diff --git a/drivers/staging/android/uapi/android_alarm.h b/drivers/staging/android/uapi/android_alarm.h +deleted file mode 100644 +index aa013f6..0000000 +--- a/drivers/staging/android/uapi/android_alarm.h ++++ /dev/null +@@ -1,62 +0,0 @@ +-/* drivers/staging/android/uapi/android_alarm.h +- * +- * Copyright (C) 2006-2007 Google, 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. +- * +- */ +- +-#ifndef _UAPI_LINUX_ANDROID_ALARM_H +-#define _UAPI_LINUX_ANDROID_ALARM_H +- +-#include +-#include +- +-enum android_alarm_type { +- /* return code bit numbers or set alarm arg */ +- ANDROID_ALARM_RTC_WAKEUP, +- ANDROID_ALARM_RTC, +- ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, +- ANDROID_ALARM_ELAPSED_REALTIME, +- ANDROID_ALARM_SYSTEMTIME, +- +- ANDROID_ALARM_TYPE_COUNT, +- +- /* return code bit numbers */ +- /* ANDROID_ALARM_TIME_CHANGE = 16 */ +-}; +- +-enum android_alarm_return_flags { +- ANDROID_ALARM_RTC_WAKEUP_MASK = 1U << ANDROID_ALARM_RTC_WAKEUP, +- ANDROID_ALARM_RTC_MASK = 1U << ANDROID_ALARM_RTC, +- ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK = +- 1U << ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, +- ANDROID_ALARM_ELAPSED_REALTIME_MASK = +- 1U << ANDROID_ALARM_ELAPSED_REALTIME, +- ANDROID_ALARM_SYSTEMTIME_MASK = 1U << ANDROID_ALARM_SYSTEMTIME, +- ANDROID_ALARM_TIME_CHANGE_MASK = 1U << 16 +-}; +- +-/* Disable alarm */ +-#define ANDROID_ALARM_CLEAR(type) _IO('a', 0 | ((type) << 4)) +- +-/* Ack last alarm and wait for next */ +-#define ANDROID_ALARM_WAIT _IO('a', 1) +- +-#define ALARM_IOW(c, type, size) _IOW('a', (c) | ((type) << 4), size) +-/* Set alarm */ +-#define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec) +-#define ANDROID_ALARM_SET_AND_WAIT(type) ALARM_IOW(3, type, struct timespec) +-#define ANDROID_ALARM_GET_TIME(type) ALARM_IOW(4, type, struct timespec) +-#define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec) +-#define ANDROID_ALARM_BASE_CMD(cmd) (cmd & ~(_IOC(0, 0, 0xf0, 0))) +-#define ANDROID_ALARM_IOCTL_TO_TYPE(cmd) (_IOC_NR(cmd) >> 4) +- +-#endif +diff --git a/drivers/staging/android/uapi/ashmem.h b/drivers/staging/android/uapi/ashmem.h +index ba4743c..13df42d 100644 +--- a/drivers/staging/android/uapi/ashmem.h ++++ b/drivers/staging/android/uapi/ashmem.h +@@ -13,6 +13,7 @@ + #define _UAPI_LINUX_ASHMEM_H + + #include ++#include + + #define ASHMEM_NAME_LEN 256 + +diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c +index f4ca7b7..d9797ba 100644 +--- a/drivers/staging/lustre/lustre/llite/llite_lib.c ++++ b/drivers/staging/lustre/lustre/llite/llite_lib.c +@@ -1434,6 +1434,10 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import) + spin_unlock(&lli->lli_lock); + } + ++ rc = setattr_killpriv(dentry, attr); ++ if (rc) ++ return rc; ++ + /* We always do an MDS RPC, even if we're only changing the size; + * only the MDS knows whether truncate() should fail with -ETXTBUSY */ + +diff --git a/drivers/switch/Kconfig b/drivers/switch/Kconfig +new file mode 100644 +index 0000000..19404b6 +--- /dev/null ++++ b/drivers/switch/Kconfig +@@ -0,0 +1,15 @@ ++menuconfig SWITCH ++ tristate "Switch class support" ++ help ++ Say Y here to enable switch class support. This allows ++ monitoring switches by userspace via sysfs and uevent. ++ ++if SWITCH ++ ++config SWITCH_GPIO ++ tristate "GPIO Swith support" ++ depends on GPIOLIB ++ help ++ Say Y here to enable GPIO based switch support. ++ ++endif # SWITCH +diff --git a/drivers/switch/Makefile b/drivers/switch/Makefile +new file mode 100644 +index 0000000..f7606ed +--- /dev/null ++++ b/drivers/switch/Makefile +@@ -0,0 +1,4 @@ ++# Switch Class Driver ++obj-$(CONFIG_SWITCH) += switch_class.o ++obj-$(CONFIG_SWITCH_GPIO) += switch_gpio.o ++ +diff --git a/drivers/switch/switch_class.c b/drivers/switch/switch_class.c +new file mode 100644 +index 0000000..e373b62 +--- /dev/null ++++ b/drivers/switch/switch_class.c +@@ -0,0 +1,174 @@ ++/* ++ * drivers/switch/switch_class.c ++ * ++ * Copyright (C) 2008 Google, Inc. ++ * Author: Mike Lockwood ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct class *switch_class; ++static atomic_t device_count; ++ ++static ssize_t state_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct switch_dev *sdev = (struct switch_dev *) ++ dev_get_drvdata(dev); ++ ++ if (sdev->print_state) { ++ int ret = sdev->print_state(sdev, buf); ++ if (ret >= 0) ++ return ret; ++ } ++ return sprintf(buf, "%d\n", sdev->state); ++} ++ ++static ssize_t name_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct switch_dev *sdev = (struct switch_dev *) ++ dev_get_drvdata(dev); ++ ++ if (sdev->print_name) { ++ int ret = sdev->print_name(sdev, buf); ++ if (ret >= 0) ++ return ret; ++ } ++ return sprintf(buf, "%s\n", sdev->name); ++} ++ ++static DEVICE_ATTR(state, S_IRUGO, state_show, NULL); ++static DEVICE_ATTR(name, S_IRUGO, name_show, NULL); ++ ++void switch_set_state(struct switch_dev *sdev, int state) ++{ ++ char name_buf[120]; ++ char state_buf[120]; ++ char *prop_buf; ++ char *envp[3]; ++ int env_offset = 0; ++ int length; ++ ++ if (sdev->state != state) { ++ sdev->state = state; ++ ++ prop_buf = (char *)get_zeroed_page(GFP_KERNEL); ++ if (prop_buf) { ++ length = name_show(sdev->dev, NULL, prop_buf); ++ if (length > 0) { ++ if (prop_buf[length - 1] == '\n') ++ prop_buf[length - 1] = 0; ++ snprintf(name_buf, sizeof(name_buf), ++ "SWITCH_NAME=%s", prop_buf); ++ envp[env_offset++] = name_buf; ++ } ++ length = state_show(sdev->dev, NULL, prop_buf); ++ if (length > 0) { ++ if (prop_buf[length - 1] == '\n') ++ prop_buf[length - 1] = 0; ++ snprintf(state_buf, sizeof(state_buf), ++ "SWITCH_STATE=%s", prop_buf); ++ envp[env_offset++] = state_buf; ++ } ++ envp[env_offset] = NULL; ++ kobject_uevent_env(&sdev->dev->kobj, KOBJ_CHANGE, envp); ++ free_page((unsigned long)prop_buf); ++ } else { ++ printk(KERN_ERR "out of memory in switch_set_state\n"); ++ kobject_uevent(&sdev->dev->kobj, KOBJ_CHANGE); ++ } ++ } ++} ++EXPORT_SYMBOL_GPL(switch_set_state); ++ ++static int create_switch_class(void) ++{ ++ if (!switch_class) { ++ switch_class = class_create(THIS_MODULE, "switch"); ++ if (IS_ERR(switch_class)) ++ return PTR_ERR(switch_class); ++ atomic_set(&device_count, 0); ++ } ++ ++ return 0; ++} ++ ++int switch_dev_register(struct switch_dev *sdev) ++{ ++ int ret; ++ ++ if (!switch_class) { ++ ret = create_switch_class(); ++ if (ret < 0) ++ return ret; ++ } ++ ++ sdev->index = atomic_inc_return(&device_count); ++ sdev->dev = device_create(switch_class, NULL, ++ MKDEV(0, sdev->index), NULL, sdev->name); ++ if (IS_ERR(sdev->dev)) ++ return PTR_ERR(sdev->dev); ++ ++ ret = device_create_file(sdev->dev, &dev_attr_state); ++ if (ret < 0) ++ goto err_create_file_1; ++ ret = device_create_file(sdev->dev, &dev_attr_name); ++ if (ret < 0) ++ goto err_create_file_2; ++ ++ dev_set_drvdata(sdev->dev, sdev); ++ sdev->state = 0; ++ return 0; ++ ++err_create_file_2: ++ device_remove_file(sdev->dev, &dev_attr_state); ++err_create_file_1: ++ device_destroy(switch_class, MKDEV(0, sdev->index)); ++ printk(KERN_ERR "switch: Failed to register driver %s\n", sdev->name); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(switch_dev_register); ++ ++void switch_dev_unregister(struct switch_dev *sdev) ++{ ++ device_remove_file(sdev->dev, &dev_attr_name); ++ device_remove_file(sdev->dev, &dev_attr_state); ++ device_destroy(switch_class, MKDEV(0, sdev->index)); ++ dev_set_drvdata(sdev->dev, NULL); ++} ++EXPORT_SYMBOL_GPL(switch_dev_unregister); ++ ++static int __init switch_class_init(void) ++{ ++ return create_switch_class(); ++} ++ ++static void __exit switch_class_exit(void) ++{ ++ class_destroy(switch_class); ++} ++ ++module_init(switch_class_init); ++module_exit(switch_class_exit); ++ ++MODULE_AUTHOR("Mike Lockwood "); ++MODULE_DESCRIPTION("Switch class driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/switch/switch_gpio.c b/drivers/switch/switch_gpio.c +new file mode 100644 +index 0000000..621d62d +--- /dev/null ++++ b/drivers/switch/switch_gpio.c +@@ -0,0 +1,172 @@ ++/* ++ * drivers/switch/switch_gpio.c ++ * ++ * Copyright (C) 2008 Google, Inc. ++ * Author: Mike Lockwood ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct gpio_switch_data { ++ struct switch_dev sdev; ++ unsigned gpio; ++ const char *name_on; ++ const char *name_off; ++ const char *state_on; ++ const char *state_off; ++ int irq; ++ struct work_struct work; ++}; ++ ++static void gpio_switch_work(struct work_struct *work) ++{ ++ int state; ++ struct gpio_switch_data *data = ++ container_of(work, struct gpio_switch_data, work); ++ ++ state = gpio_get_value(data->gpio); ++ switch_set_state(&data->sdev, state); ++} ++ ++static irqreturn_t gpio_irq_handler(int irq, void *dev_id) ++{ ++ struct gpio_switch_data *switch_data = ++ (struct gpio_switch_data *)dev_id; ++ ++ schedule_work(&switch_data->work); ++ return IRQ_HANDLED; ++} ++ ++static ssize_t switch_gpio_print_state(struct switch_dev *sdev, char *buf) ++{ ++ struct gpio_switch_data *switch_data = ++ container_of(sdev, struct gpio_switch_data, sdev); ++ const char *state; ++ if (switch_get_state(sdev)) ++ state = switch_data->state_on; ++ else ++ state = switch_data->state_off; ++ ++ if (state) ++ return sprintf(buf, "%s\n", state); ++ return -1; ++} ++ ++static int gpio_switch_probe(struct platform_device *pdev) ++{ ++ struct gpio_switch_platform_data *pdata = pdev->dev.platform_data; ++ struct gpio_switch_data *switch_data; ++ int ret = 0; ++ ++ if (!pdata) ++ return -EBUSY; ++ ++ switch_data = kzalloc(sizeof(struct gpio_switch_data), GFP_KERNEL); ++ if (!switch_data) ++ return -ENOMEM; ++ ++ switch_data->sdev.name = pdata->name; ++ switch_data->gpio = pdata->gpio; ++ switch_data->name_on = pdata->name_on; ++ switch_data->name_off = pdata->name_off; ++ switch_data->state_on = pdata->state_on; ++ switch_data->state_off = pdata->state_off; ++ switch_data->sdev.print_state = switch_gpio_print_state; ++ ++ ret = switch_dev_register(&switch_data->sdev); ++ if (ret < 0) ++ goto err_switch_dev_register; ++ ++ ret = gpio_request(switch_data->gpio, pdev->name); ++ if (ret < 0) ++ goto err_request_gpio; ++ ++ ret = gpio_direction_input(switch_data->gpio); ++ if (ret < 0) ++ goto err_set_gpio_input; ++ ++ INIT_WORK(&switch_data->work, gpio_switch_work); ++ ++ switch_data->irq = gpio_to_irq(switch_data->gpio); ++ if (switch_data->irq < 0) { ++ ret = switch_data->irq; ++ goto err_detect_irq_num_failed; ++ } ++ ++ ret = request_irq(switch_data->irq, gpio_irq_handler, ++ IRQF_TRIGGER_LOW, pdev->name, switch_data); ++ if (ret < 0) ++ goto err_request_irq; ++ ++ /* Perform initial detection */ ++ gpio_switch_work(&switch_data->work); ++ ++ return 0; ++ ++err_request_irq: ++err_detect_irq_num_failed: ++err_set_gpio_input: ++ gpio_free(switch_data->gpio); ++err_request_gpio: ++ switch_dev_unregister(&switch_data->sdev); ++err_switch_dev_register: ++ kfree(switch_data); ++ ++ return ret; ++} ++ ++static int gpio_switch_remove(struct platform_device *pdev) ++{ ++ struct gpio_switch_data *switch_data = platform_get_drvdata(pdev); ++ ++ cancel_work_sync(&switch_data->work); ++ gpio_free(switch_data->gpio); ++ switch_dev_unregister(&switch_data->sdev); ++ kfree(switch_data); ++ ++ return 0; ++} ++ ++static struct platform_driver gpio_switch_driver = { ++ .probe = gpio_switch_probe, ++ .remove = gpio_switch_remove, ++ .driver = { ++ .name = "switch-gpio", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init gpio_switch_init(void) ++{ ++ return platform_driver_register(&gpio_switch_driver); ++} ++ ++static void __exit gpio_switch_exit(void) ++{ ++ platform_driver_unregister(&gpio_switch_driver); ++} ++ ++module_init(gpio_switch_init); ++module_exit(gpio_switch_exit); ++ ++MODULE_AUTHOR("Mike Lockwood "); ++MODULE_DESCRIPTION("GPIO Switch driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig +index f554d25..8b7d47f 100644 +--- a/drivers/thermal/Kconfig ++++ b/drivers/thermal/Kconfig +@@ -42,6 +42,17 @@ config THERMAL_OF + Say 'Y' here if you need to build thermal infrastructure + based on device tree. + ++config THERMAL_WRITABLE_TRIPS ++ bool "Enable writable trip points" ++ help ++ This option allows the system integrator to choose whether ++ trip temperatures can be changed from userspace. The ++ writable trips need to be specified when setting up the ++ thermal zone but the choice here takes precedence. ++ ++ Say 'Y' here if you would like to allow userspace tools to ++ change trip temperatures. ++ + choice + prompt "Default Thermal governor" + default THERMAL_DEFAULT_GOV_STEP_WISE +@@ -71,6 +82,14 @@ config THERMAL_DEFAULT_GOV_USER_SPACE + Select this if you want to let the user space manage the + platform thermals. + ++config THERMAL_DEFAULT_GOV_POWER_ALLOCATOR ++ bool "power_allocator" ++ select THERMAL_GOV_POWER_ALLOCATOR ++ help ++ Select this if you want to control temperature based on ++ system and device power allocation. This governor can only ++ operate on cooling devices that implement the power API. ++ + endchoice + + config THERMAL_GOV_FAIR_SHARE +@@ -99,6 +118,13 @@ config THERMAL_GOV_USER_SPACE + help + Enable this to let the user space manage the platform thermals. + ++config THERMAL_GOV_POWER_ALLOCATOR ++ bool "Power allocator thermal governor" ++ select THERMAL_POWER_ACTOR ++ help ++ Enable this to manage platform thermals by dynamically ++ allocating and limiting power to devices. ++ + config CPU_THERMAL + bool "generic cpu cooling support" + depends on CPU_FREQ +@@ -112,6 +138,18 @@ config CPU_THERMAL + + If you want this support, you should say Y here. + ++config CLOCK_THERMAL ++ bool "Generic clock cooling support" ++ depends on COMMON_CLK ++ depends on PM_OPP ++ help ++ This entry implements the generic clock cooling mechanism through ++ frequency clipping. Typically used to cool off co-processors. The ++ device that is configured to use this cooling mechanism will be ++ controlled to reduce clock frequency whenever temperature is high. ++ ++ If you want this support, you should say Y here. ++ + config THERMAL_EMULATION + bool "Thermal emulation mode support" + help +@@ -185,6 +223,16 @@ config ARMADA_THERMAL + Enable this option if you want to have support for thermal management + controller present in Armada 370 and Armada XP SoC. + ++config TEGRA_SOCTHERM ++ tristate "Tegra SOCTHERM thermal management" ++ depends on ARCH_TEGRA ++ help ++ Enable this option for integrated thermal management support on NVIDIA ++ Tegra124 systems-on-chip. The driver supports four thermal zones ++ (CPU, GPU, MEM, PLLX). Cooling devices can be bound to the thermal ++ zones to manage temperatures. This option is also required for the ++ emergency thermal reset (thermtrip) feature to function. ++ + config DB8500_CPUFREQ_COOLING + tristate "DB8500 cpufreq cooling" + depends on ARCH_U8500 +diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile +index 39c4fe8..dae37c0 100644 +--- a/drivers/thermal/Makefile ++++ b/drivers/thermal/Makefile +@@ -14,10 +14,14 @@ thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += fair_share.o + thermal_sys-$(CONFIG_THERMAL_GOV_BANG_BANG) += gov_bang_bang.o + thermal_sys-$(CONFIG_THERMAL_GOV_STEP_WISE) += step_wise.o + thermal_sys-$(CONFIG_THERMAL_GOV_USER_SPACE) += user_space.o ++thermal_sys-$(CONFIG_THERMAL_GOV_POWER_ALLOCATOR) += power_allocator.o + + # cpufreq cooling + thermal_sys-$(CONFIG_CPU_THERMAL) += cpu_cooling.o + ++# clock cooling ++thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o ++ + # platform thermal drivers + obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o + obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o +@@ -34,3 +38,4 @@ obj-$(CONFIG_INTEL_SOC_DTS_THERMAL) += intel_soc_dts_thermal.o + obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/ + obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal/ + obj-$(CONFIG_ST_THERMAL) += st/ ++obj-$(CONFIG_TEGRA_SOCTHERM) += tegra_soctherm.o +diff --git a/drivers/thermal/clock_cooling.c b/drivers/thermal/clock_cooling.c +new file mode 100644 +index 0000000..1b4ff0f +--- /dev/null ++++ b/drivers/thermal/clock_cooling.c +@@ -0,0 +1,485 @@ ++/* ++ * drivers/thermal/clock_cooling.c ++ * ++ * Copyright (C) 2014 Eduardo Valentin ++ * ++ * Copyright (C) 2013 Texas Instruments Inc. ++ * Contact: Eduardo Valentin ++ * ++ * Highly based on cpu_cooling.c. ++ * Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com) ++ * Copyright (C) 2012 Amit Daniel ++ * ++ * 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 of the License. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/** ++ * struct clock_cooling_device - data for cooling device with clock ++ * @id: unique integer value corresponding to each clock_cooling_device ++ * registered. ++ * @dev: struct device pointer to the device being used to cool off using ++ * clock frequencies. ++ * @cdev: thermal_cooling_device pointer to keep track of the ++ * registered cooling device. ++ * @clk_rate_change_nb: reference to notifier block used to receive clock ++ * rate changes. ++ * @freq_table: frequency table used to keep track of available frequencies. ++ * @clock_state: integer value representing the current state of clock ++ * cooling devices. ++ * @clock_val: integer value representing the absolute value of the clipped ++ * frequency. ++ * @clk: struct clk reference used to enforce clock limits. ++ * @lock: mutex lock to protect this struct. ++ * ++ * This structure is required for keeping information of each ++ * clock_cooling_device registered. In order to prevent corruption of this a ++ * mutex @lock is used. ++ */ ++struct clock_cooling_device { ++ int id; ++ struct device *dev; ++ struct thermal_cooling_device *cdev; ++ struct notifier_block clk_rate_change_nb; ++ struct cpufreq_frequency_table *freq_table; ++ unsigned long clock_state; ++ unsigned long clock_val; ++ struct clk *clk; ++ struct mutex lock; /* lock to protect the content of this struct */ ++}; ++#define to_clock_cooling_device(x) \ ++ container_of(x, struct clock_cooling_device, clk_rate_change_nb) ++static DEFINE_IDR(clock_idr); ++static DEFINE_MUTEX(cooling_clock_lock); ++ ++/** ++ * clock_cooling_get_idr - function to get an unique id. ++ * @id: int * value generated by this function. ++ * ++ * This function will populate @id with an unique ++ * id, using the idr API. ++ * ++ * Return: 0 on success, an error code on failure. ++ */ ++static int clock_cooling_get_idr(int *id) ++{ ++ int ret; ++ ++ mutex_lock(&cooling_clock_lock); ++ ret = idr_alloc(&clock_idr, NULL, 0, 0, GFP_KERNEL); ++ mutex_unlock(&cooling_clock_lock); ++ if (unlikely(ret < 0)) ++ return ret; ++ *id = ret; ++ ++ return 0; ++} ++ ++/** ++ * release_idr - function to free the unique id. ++ * @id: int value representing the unique id. ++ */ ++static void release_idr(int id) ++{ ++ mutex_lock(&cooling_clock_lock); ++ idr_remove(&clock_idr, id); ++ mutex_unlock(&cooling_clock_lock); ++} ++ ++/* Below code defines functions to be used for clock as cooling device */ ++ ++enum clock_cooling_property { ++ GET_LEVEL, ++ GET_FREQ, ++ GET_MAXL, ++}; ++ ++/** ++ * clock_cooling_get_property - fetch a property of interest for a give cpu. ++ * @ccdev: clock cooling device reference ++ * @input: query parameter ++ * @output: query return ++ * @property: type of query (frequency, level, max level) ++ * ++ * This is the common function to ++ * 1. get maximum clock cooling states ++ * 2. translate frequency to cooling state ++ * 3. translate cooling state to frequency ++ * Note that the code may be not in good shape ++ * but it is written in this way in order to: ++ * a) reduce duplicate code as most of the code can be shared. ++ * b) make sure the logic is consistent when translating between ++ * cooling states and frequencies. ++ * ++ * Return: 0 on success, -EINVAL when invalid parameters are passed. ++ */ ++static int clock_cooling_get_property(struct clock_cooling_device *ccdev, ++ unsigned long input, ++ unsigned long *output, ++ enum clock_cooling_property property) ++{ ++ int i; ++ unsigned long max_level = 0, level = 0; ++ unsigned int freq = CPUFREQ_ENTRY_INVALID; ++ int descend = -1; ++ struct cpufreq_frequency_table *pos, *table = ccdev->freq_table; ++ ++ if (!output) ++ return -EINVAL; ++ ++ if (!table) ++ return -EINVAL; ++ ++ cpufreq_for_each_valid_entry(pos, table) { ++ /* ignore duplicate entry */ ++ if (freq == pos->frequency) ++ continue; ++ ++ /* get the frequency order */ ++ if (freq != CPUFREQ_ENTRY_INVALID && descend == -1) ++ descend = freq > pos->frequency; ++ ++ freq = pos->frequency; ++ max_level++; ++ } ++ ++ /* No valid cpu frequency entry */ ++ if (max_level == 0) ++ return -EINVAL; ++ ++ /* max_level is an index, not a counter */ ++ max_level--; ++ ++ /* get max level */ ++ if (property == GET_MAXL) { ++ *output = max_level; ++ return 0; ++ } ++ ++ if (property == GET_FREQ) ++ level = descend ? input : (max_level - input); ++ ++ i = 0; ++ cpufreq_for_each_valid_entry(pos, table) { ++ /* ignore duplicate entry */ ++ if (freq == pos->frequency) ++ continue; ++ ++ /* now we have a valid frequency entry */ ++ freq = pos->frequency; ++ ++ if (property == GET_LEVEL && (unsigned int)input == freq) { ++ /* get level by frequency */ ++ *output = descend ? i : (max_level - i); ++ return 0; ++ } ++ if (property == GET_FREQ && level == i) { ++ /* get frequency by level */ ++ *output = freq; ++ return 0; ++ } ++ i++; ++ } ++ ++ return -EINVAL; ++} ++ ++/** ++ * clock_cooling_get_level - return the cooling level of given clock cooling. ++ * @cdev: reference of a thermal cooling device of used as clock cooling device ++ * @freq: the frequency of interest ++ * ++ * This function will match the cooling level corresponding to the ++ * requested @freq and return it. ++ * ++ * Return: The matched cooling level on success or THERMAL_CSTATE_INVALID ++ * otherwise. ++ */ ++unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev, ++ unsigned long freq) ++{ ++ struct clock_cooling_device *ccdev = cdev->devdata; ++ unsigned long val; ++ ++ if (clock_cooling_get_property(ccdev, (unsigned long)freq, &val, ++ GET_LEVEL)) ++ return THERMAL_CSTATE_INVALID; ++ ++ return val; ++} ++EXPORT_SYMBOL_GPL(clock_cooling_get_level); ++ ++/** ++ * clock_cooling_get_frequency - get the absolute value of frequency from level. ++ * @ccdev: clock cooling device reference ++ * @level: cooling level ++ * ++ * This function matches cooling level with frequency. Based on a cooling level ++ * of frequency, equals cooling state of cpu cooling device, it will return ++ * the corresponding frequency. ++ * e.g level=0 --> 1st MAX FREQ, level=1 ---> 2nd MAX FREQ, .... etc ++ * ++ * Return: 0 on error, the corresponding frequency otherwise. ++ */ ++static unsigned long ++clock_cooling_get_frequency(struct clock_cooling_device *ccdev, ++ unsigned long level) ++{ ++ int ret = 0; ++ unsigned long freq; ++ ++ ret = clock_cooling_get_property(ccdev, level, &freq, GET_FREQ); ++ if (ret) ++ return 0; ++ ++ return freq; ++} ++ ++/** ++ * clock_cooling_apply - function to apply frequency clipping. ++ * @ccdev: clock_cooling_device pointer containing frequency clipping data. ++ * @cooling_state: value of the cooling state. ++ * ++ * Function used to make sure the clock layer is aware of current thermal ++ * limits. The limits are applied by updating the clock rate in case it is ++ * higher than the corresponding frequency based on the requested cooling_state. ++ * ++ * Return: 0 on success, an error code otherwise (-EINVAL in case wrong ++ * cooling state). ++ */ ++static int clock_cooling_apply(struct clock_cooling_device *ccdev, ++ unsigned long cooling_state) ++{ ++ unsigned long clip_freq, cur_freq; ++ int ret = 0; ++ ++ /* Here we write the clipping */ ++ /* Check if the old cooling action is same as new cooling action */ ++ if (ccdev->clock_state == cooling_state) ++ return 0; ++ ++ clip_freq = clock_cooling_get_frequency(ccdev, cooling_state); ++ if (!clip_freq) ++ return -EINVAL; ++ ++ cur_freq = clk_get_rate(ccdev->clk); ++ ++ mutex_lock(&ccdev->lock); ++ ccdev->clock_state = cooling_state; ++ ccdev->clock_val = clip_freq; ++ /* enforce clock level */ ++ if (cur_freq > clip_freq) ++ ret = clk_set_rate(ccdev->clk, clip_freq); ++ mutex_unlock(&ccdev->lock); ++ ++ return ret; ++} ++ ++/** ++ * clock_cooling_clock_notifier - notifier callback on clock rate changes. ++ * @nb: struct notifier_block * with callback info. ++ * @event: value showing clock event for which this function invoked. ++ * @data: callback-specific data ++ * ++ * Callback to hijack the notification on clock transition. ++ * Every time there is a clock change, we intercept all pre change events ++ * and block the transition in case the new rate infringes thermal limits. ++ * ++ * Return: NOTIFY_DONE (success) or NOTIFY_BAD (new_rate > thermal limit). ++ */ ++static int clock_cooling_clock_notifier(struct notifier_block *nb, ++ unsigned long event, void *data) ++{ ++ struct clk_notifier_data *ndata = data; ++ struct clock_cooling_device *ccdev = to_clock_cooling_device(nb); ++ ++ switch (event) { ++ case PRE_RATE_CHANGE: ++ /* ++ * checks on current state ++ * TODO: current method is not best we can find as it ++ * allows possibly voltage transitions, in case DVFS ++ * layer is also hijacking clock pre notifications. ++ */ ++ if (ndata->new_rate > ccdev->clock_val) ++ return NOTIFY_BAD; ++ /* fall through */ ++ case POST_RATE_CHANGE: ++ case ABORT_RATE_CHANGE: ++ default: ++ return NOTIFY_DONE; ++ } ++} ++ ++/* clock cooling device thermal callback functions are defined below */ ++ ++/** ++ * clock_cooling_get_max_state - callback function to get the max cooling state. ++ * @cdev: thermal cooling device pointer. ++ * @state: fill this variable with the max cooling state. ++ * ++ * Callback for the thermal cooling device to return the clock ++ * max cooling state. ++ * ++ * Return: 0 on success, an error code otherwise. ++ */ ++static int clock_cooling_get_max_state(struct thermal_cooling_device *cdev, ++ unsigned long *state) ++{ ++ struct clock_cooling_device *ccdev = cdev->devdata; ++ unsigned long count = 0; ++ int ret; ++ ++ ret = clock_cooling_get_property(ccdev, 0, &count, GET_MAXL); ++ if (!ret) ++ *state = count; ++ ++ return ret; ++} ++ ++/** ++ * clock_cooling_get_cur_state - function to get the current cooling state. ++ * @cdev: thermal cooling device pointer. ++ * @state: fill this variable with the current cooling state. ++ * ++ * Callback for the thermal cooling device to return the clock ++ * current cooling state. ++ * ++ * Return: 0 (success) ++ */ ++static int clock_cooling_get_cur_state(struct thermal_cooling_device *cdev, ++ unsigned long *state) ++{ ++ struct clock_cooling_device *ccdev = cdev->devdata; ++ ++ *state = ccdev->clock_state; ++ ++ return 0; ++} ++ ++/** ++ * clock_cooling_set_cur_state - function to set the current cooling state. ++ * @cdev: thermal cooling device pointer. ++ * @state: set this variable to the current cooling state. ++ * ++ * Callback for the thermal cooling device to change the clock cooling ++ * current cooling state. ++ * ++ * Return: 0 on success, an error code otherwise. ++ */ ++static int clock_cooling_set_cur_state(struct thermal_cooling_device *cdev, ++ unsigned long state) ++{ ++ struct clock_cooling_device *clock_device = cdev->devdata; ++ ++ return clock_cooling_apply(clock_device, state); ++} ++ ++/* Bind clock callbacks to thermal cooling device ops */ ++static struct thermal_cooling_device_ops const clock_cooling_ops = { ++ .get_max_state = clock_cooling_get_max_state, ++ .get_cur_state = clock_cooling_get_cur_state, ++ .set_cur_state = clock_cooling_set_cur_state, ++}; ++ ++/** ++ * clock_cooling_register - function to create clock cooling device. ++ * @dev: struct device pointer to the device used as clock cooling device. ++ * @clock_name: string containing the clock used as cooling mechanism. ++ * ++ * This interface function registers the clock cooling device with the name ++ * "thermal-clock-%x". The cooling device is based on clock frequencies. ++ * The struct device is assumed to be capable of DVFS transitions. ++ * The OPP layer is used to fetch and fill the available frequencies for ++ * the referred device. The ordered frequency table is used to control ++ * the clock cooling device cooling states and to limit clock transitions ++ * based on the cooling state requested by the thermal framework. ++ * ++ * Return: a valid struct thermal_cooling_device pointer on success, ++ * on failure, it returns a corresponding ERR_PTR(). ++ */ ++struct thermal_cooling_device * ++clock_cooling_register(struct device *dev, const char *clock_name) ++{ ++ struct thermal_cooling_device *cdev; ++ struct clock_cooling_device *ccdev = NULL; ++ char dev_name[THERMAL_NAME_LENGTH]; ++ int ret = 0; ++ ++ ccdev = devm_kzalloc(dev, sizeof(*ccdev), GFP_KERNEL); ++ if (!ccdev) ++ return ERR_PTR(-ENOMEM); ++ ++ ccdev->dev = dev; ++ ccdev->clk = devm_clk_get(dev, clock_name); ++ if (IS_ERR(ccdev->clk)) ++ return ERR_CAST(ccdev->clk); ++ ++ ret = clock_cooling_get_idr(&ccdev->id); ++ if (ret) ++ return ERR_PTR(-EINVAL); ++ ++ snprintf(dev_name, sizeof(dev_name), "thermal-clock-%d", ccdev->id); ++ ++ cdev = thermal_cooling_device_register(dev_name, ccdev, ++ &clock_cooling_ops); ++ if (IS_ERR(cdev)) { ++ release_idr(ccdev->id); ++ return ERR_PTR(-EINVAL); ++ } ++ ccdev->cdev = cdev; ++ ccdev->clk_rate_change_nb.notifier_call = clock_cooling_clock_notifier; ++ ++ /* Assuming someone has already filled the opp table for this device */ ++ ret = dev_pm_opp_init_cpufreq_table(dev, &ccdev->freq_table); ++ if (ret) { ++ release_idr(ccdev->id); ++ return ERR_PTR(ret); ++ } ++ ccdev->clock_state = 0; ++ ccdev->clock_val = clock_cooling_get_frequency(ccdev, 0); ++ ++ clk_notifier_register(ccdev->clk, &ccdev->clk_rate_change_nb); ++ ++ return cdev; ++} ++EXPORT_SYMBOL_GPL(clock_cooling_register); ++ ++/** ++ * clock_cooling_unregister - function to remove clock cooling device. ++ * @cdev: thermal cooling device pointer. ++ * ++ * This interface function unregisters the "thermal-clock-%x" cooling device. ++ */ ++void clock_cooling_unregister(struct thermal_cooling_device *cdev) ++{ ++ struct clock_cooling_device *ccdev; ++ ++ if (!cdev) ++ return; ++ ++ ccdev = cdev->devdata; ++ ++ clk_notifier_unregister(ccdev->clk, &ccdev->clk_rate_change_nb); ++ dev_pm_opp_free_cpufreq_table(ccdev->dev, &ccdev->freq_table); ++ ++ thermal_cooling_device_unregister(ccdev->cdev); ++ release_idr(ccdev->id); ++} ++EXPORT_SYMBOL_GPL(clock_cooling_unregister); +diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c +index ad09e51..6509c61 100644 +--- a/drivers/thermal/cpu_cooling.c ++++ b/drivers/thermal/cpu_cooling.c +@@ -4,6 +4,8 @@ + * Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com) + * Copyright (C) 2012 Amit Daniel + * ++ * Copyright (C) 2014 Viresh Kumar ++ * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * 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 +@@ -24,10 +26,40 @@ + #include + #include + #include ++#include + #include + #include + #include + ++#include ++ ++/* ++ * Cooling state <-> CPUFreq frequency ++ * ++ * Cooling states are translated to frequencies throughout this driver and this ++ * is the relation between them. ++ * ++ * Highest cooling state corresponds to lowest possible frequency. ++ * ++ * i.e. ++ * level 0 --> 1st Max Freq ++ * level 1 --> 2nd Max Freq ++ * ... ++ */ ++ ++/** ++ * struct power_table - frequency to power conversion ++ * @frequency: frequency in KHz ++ * @power: power in mW ++ * ++ * This structure is built when the cooling device registers and helps ++ * in translating frequency to power and viceversa. ++ */ ++struct power_table { ++ u32 frequency; ++ u32 power; ++}; ++ + /** + * struct cpufreq_cooling_device - data for cooling device with cpufreq + * @id: unique integer value corresponding to each cpufreq_cooling_device +@@ -38,25 +70,43 @@ + * cooling devices. + * @cpufreq_val: integer value representing the absolute value of the clipped + * frequency. ++ * @max_level: maximum cooling level. One less than total number of valid ++ * cpufreq frequencies. + * @allowed_cpus: all the cpus involved for this cpufreq_cooling_device. ++ * @node: list_head to link all cpufreq_cooling_device together. ++ * @last_load: load measured by the latest call to cpufreq_get_actual_power() ++ * @time_in_idle: previous reading of the absolute time that this cpu was idle ++ * @time_in_idle_timestamp: wall time of the last invocation of ++ * get_cpu_idle_time_us() ++ * @dyn_power_table: array of struct power_table for frequency to power ++ * conversion, sorted in ascending order. ++ * @dyn_power_table_entries: number of entries in the @dyn_power_table array ++ * @cpu_dev: the first cpu_device from @allowed_cpus that has OPPs registered ++ * @plat_get_static_power: callback to calculate the static power + * +- * This structure is required for keeping information of each +- * cpufreq_cooling_device registered. In order to prevent corruption of this a +- * mutex lock cooling_cpufreq_lock is used. ++ * This structure is required for keeping information of each registered ++ * cpufreq_cooling_device. + */ + struct cpufreq_cooling_device { + int id; + struct thermal_cooling_device *cool_dev; + unsigned int cpufreq_state; + unsigned int cpufreq_val; ++ unsigned int max_level; ++ unsigned int *freq_table; /* In descending order */ + struct cpumask allowed_cpus; + struct list_head node; ++ u32 last_load; ++ u64 *time_in_idle; ++ u64 *time_in_idle_timestamp; ++ struct power_table *dyn_power_table; ++ int dyn_power_table_entries; ++ struct device *cpu_dev; ++ get_static_t plat_get_static_power; + }; + static DEFINE_IDR(cpufreq_idr); + static DEFINE_MUTEX(cooling_cpufreq_lock); + +-static unsigned int cpufreq_dev_count; +- + static LIST_HEAD(cpufreq_dev_list); + + /** +@@ -98,120 +148,30 @@ static void release_idr(struct idr *idr, int id) + /* Below code defines functions to be used for cpufreq as cooling device */ + + /** +- * is_cpufreq_valid - function to check frequency transitioning capability. +- * @cpu: cpu for which check is needed. ++ * get_level: Find the level for a particular frequency ++ * @cpufreq_dev: cpufreq_dev for which the property is required ++ * @freq: Frequency + * +- * This function will check the current state of the system if +- * it is capable of changing the frequency for a given @cpu. +- * +- * Return: 0 if the system is not currently capable of changing +- * the frequency of given cpu. !0 in case the frequency is changeable. +- */ +-static int is_cpufreq_valid(int cpu) +-{ +- struct cpufreq_policy policy; +- +- return !cpufreq_get_policy(&policy, cpu); +-} +- +-enum cpufreq_cooling_property { +- GET_LEVEL, +- GET_FREQ, +- GET_MAXL, +-}; +- +-/** +- * get_property - fetch a property of interest for a give cpu. +- * @cpu: cpu for which the property is required +- * @input: query parameter +- * @output: query return +- * @property: type of query (frequency, level, max level) +- * +- * This is the common function to +- * 1. get maximum cpu cooling states +- * 2. translate frequency to cooling state +- * 3. translate cooling state to frequency +- * Note that the code may be not in good shape +- * but it is written in this way in order to: +- * a) reduce duplicate code as most of the code can be shared. +- * b) make sure the logic is consistent when translating between +- * cooling states and frequencies. +- * +- * Return: 0 on success, -EINVAL when invalid parameters are passed. ++ * Return: level on success, THERMAL_CSTATE_INVALID on error. + */ +-static int get_property(unsigned int cpu, unsigned long input, +- unsigned int *output, +- enum cpufreq_cooling_property property) ++static unsigned long get_level(struct cpufreq_cooling_device *cpufreq_dev, ++ unsigned int freq) + { +- int i; +- unsigned long max_level = 0, level = 0; +- unsigned int freq = CPUFREQ_ENTRY_INVALID; +- int descend = -1; +- struct cpufreq_frequency_table *pos, *table = +- cpufreq_frequency_get_table(cpu); +- +- if (!output) +- return -EINVAL; +- +- if (!table) +- return -EINVAL; +- +- cpufreq_for_each_valid_entry(pos, table) { +- /* ignore duplicate entry */ +- if (freq == pos->frequency) +- continue; +- +- /* get the frequency order */ +- if (freq != CPUFREQ_ENTRY_INVALID && descend == -1) +- descend = freq > pos->frequency; +- +- freq = pos->frequency; +- max_level++; +- } +- +- /* No valid cpu frequency entry */ +- if (max_level == 0) +- return -EINVAL; ++ unsigned long level; + +- /* max_level is an index, not a counter */ +- max_level--; +- +- /* get max level */ +- if (property == GET_MAXL) { +- *output = (unsigned int)max_level; +- return 0; +- } +- +- if (property == GET_FREQ) +- level = descend ? input : (max_level - input); +- +- i = 0; +- cpufreq_for_each_valid_entry(pos, table) { +- /* ignore duplicate entry */ +- if (freq == pos->frequency) +- continue; +- +- /* now we have a valid frequency entry */ +- freq = pos->frequency; ++ for (level = 0; level <= cpufreq_dev->max_level; level++) { ++ if (freq == cpufreq_dev->freq_table[level]) ++ return level; + +- if (property == GET_LEVEL && (unsigned int)input == freq) { +- /* get level by frequency */ +- *output = descend ? i : (max_level - i); +- return 0; +- } +- if (property == GET_FREQ && level == i) { +- /* get frequency by level */ +- *output = freq; +- return 0; +- } +- i++; ++ if (freq > cpufreq_dev->freq_table[level]) ++ break; + } + +- return -EINVAL; ++ return THERMAL_CSTATE_INVALID; + } + + /** +- * cpufreq_cooling_get_level - for a give cpu, return the cooling level. ++ * cpufreq_cooling_get_level - for a given cpu, return the cooling level. + * @cpu: cpu for which the level is required + * @freq: the frequency of interest + * +@@ -223,119 +183,272 @@ static int get_property(unsigned int cpu, unsigned long input, + */ + unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq) + { +- unsigned int val; ++ struct cpufreq_cooling_device *cpufreq_dev; + +- if (get_property(cpu, (unsigned long)freq, &val, GET_LEVEL)) +- return THERMAL_CSTATE_INVALID; ++ mutex_lock(&cooling_cpufreq_lock); ++ list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) { ++ if (cpumask_test_cpu(cpu, &cpufreq_dev->allowed_cpus)) { ++ mutex_unlock(&cooling_cpufreq_lock); ++ return get_level(cpufreq_dev, freq); ++ } ++ } ++ mutex_unlock(&cooling_cpufreq_lock); + +- return (unsigned long)val; ++ pr_err("%s: cpu:%d not part of any cooling device\n", __func__, cpu); ++ return THERMAL_CSTATE_INVALID; + } + EXPORT_SYMBOL_GPL(cpufreq_cooling_get_level); + + /** +- * get_cpu_frequency - get the absolute value of frequency from level. +- * @cpu: cpu for which frequency is fetched. +- * @level: cooling level ++ * cpufreq_thermal_notifier - notifier callback for cpufreq policy change. ++ * @nb: struct notifier_block * with callback info. ++ * @event: value showing cpufreq event for which this function invoked. ++ * @data: callback-specific data + * +- * This function matches cooling level with frequency. Based on a cooling level +- * of frequency, equals cooling state of cpu cooling device, it will return +- * the corresponding frequency. +- * e.g level=0 --> 1st MAX FREQ, level=1 ---> 2nd MAX FREQ, .... etc ++ * Callback to hijack the notification on cpufreq policy transition. ++ * Every time there is a change in policy, we will intercept and ++ * update the cpufreq policy with thermal constraints. + * +- * Return: 0 on error, the corresponding frequency otherwise. ++ * Return: 0 (success) + */ +-static unsigned int get_cpu_frequency(unsigned int cpu, unsigned long level) ++static int cpufreq_thermal_notifier(struct notifier_block *nb, ++ unsigned long event, void *data) + { +- int ret = 0; +- unsigned int freq; ++ struct cpufreq_policy *policy = data; ++ unsigned long max_freq = 0; ++ struct cpufreq_cooling_device *cpufreq_dev; + +- ret = get_property(cpu, level, &freq, GET_FREQ); +- if (ret) +- return 0; ++ switch (event) { ++ ++ case CPUFREQ_ADJUST: ++ mutex_lock(&cooling_cpufreq_lock); ++ list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) { ++ if (!cpumask_test_cpu(policy->cpu, ++ &cpufreq_dev->allowed_cpus)) ++ continue; + +- return freq; ++ max_freq = cpufreq_dev->cpufreq_val; ++ ++ if (policy->max != max_freq) ++ cpufreq_verify_within_limits(policy, 0, ++ max_freq); ++ } ++ mutex_unlock(&cooling_cpufreq_lock); ++ break; ++ default: ++ return NOTIFY_DONE; ++ } ++ ++ return NOTIFY_OK; + } + + /** +- * cpufreq_apply_cooling - function to apply frequency clipping. +- * @cpufreq_device: cpufreq_cooling_device pointer containing frequency +- * clipping data. +- * @cooling_state: value of the cooling state. ++ * build_dyn_power_table() - create a dynamic power to frequency table ++ * @cpufreq_device: the cpufreq cooling device in which to store the table ++ * @capacitance: dynamic power coefficient for these cpus + * +- * Function used to make sure the cpufreq layer is aware of current thermal +- * limits. The limits are applied by updating the cpufreq policy. ++ * Build a dynamic power to frequency table for this cpu and store it ++ * in @cpufreq_device. This table will be used in cpu_power_to_freq() and ++ * cpu_freq_to_power() to convert between power and frequency ++ * efficiently. Power is stored in mW, frequency in KHz. The ++ * resulting table is in ascending order. + * +- * Return: 0 on success, an error code otherwise (-EINVAL in case wrong +- * cooling state). ++ * Return: 0 on success, -E* on error. + */ +-static int cpufreq_apply_cooling(struct cpufreq_cooling_device *cpufreq_device, +- unsigned long cooling_state) ++static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_device, ++ u32 capacitance) + { +- unsigned int cpuid, clip_freq; +- struct cpumask *mask = &cpufreq_device->allowed_cpus; +- unsigned int cpu = cpumask_any(mask); ++ struct power_table *power_table; ++ struct dev_pm_opp *opp; ++ struct device *dev = NULL; ++ int num_opps = 0, cpu, i, ret = 0; ++ unsigned long freq; ++ ++ rcu_read_lock(); ++ ++ for_each_cpu(cpu, &cpufreq_device->allowed_cpus) { ++ dev = get_cpu_device(cpu); ++ if (!dev) { ++ dev_warn(&cpufreq_device->cool_dev->device, ++ "No cpu device for cpu %d\n", cpu); ++ continue; ++ } + ++ num_opps = dev_pm_opp_get_opp_count(dev); ++ if (num_opps > 0) { ++ break; ++ } else if (num_opps < 0) { ++ ret = num_opps; ++ goto unlock; ++ } ++ } + +- /* Check if the old cooling action is same as new cooling action */ +- if (cpufreq_device->cpufreq_state == cooling_state) +- return 0; ++ if (num_opps == 0) { ++ ret = -EINVAL; ++ goto unlock; ++ } + +- clip_freq = get_cpu_frequency(cpu, cooling_state); +- if (!clip_freq) +- return -EINVAL; ++ power_table = kcalloc(num_opps, sizeof(*power_table), GFP_KERNEL); ++ if (!power_table) { ++ ret = -ENOMEM; ++ goto unlock; ++ } + +- cpufreq_device->cpufreq_state = cooling_state; +- cpufreq_device->cpufreq_val = clip_freq; ++ for (freq = 0, i = 0; ++ opp = dev_pm_opp_find_freq_ceil(dev, &freq), !IS_ERR(opp); ++ freq++, i++) { ++ u32 freq_mhz, voltage_mv; ++ u64 power; ++ ++ freq_mhz = freq / 1000000; ++ voltage_mv = dev_pm_opp_get_voltage(opp) / 1000; ++ ++ /* ++ * Do the multiplication with MHz and millivolt so as ++ * to not overflow. ++ */ ++ power = (u64)capacitance * freq_mhz * voltage_mv * voltage_mv; ++ do_div(power, 1000000000); + +- for_each_cpu(cpuid, mask) { +- if (is_cpufreq_valid(cpuid)) +- cpufreq_update_policy(cpuid); ++ /* frequency is stored in power_table in KHz */ ++ power_table[i].frequency = freq / 1000; ++ ++ /* power is stored in mW */ ++ power_table[i].power = power; + } + +- return 0; ++ if (i == 0) { ++ ret = PTR_ERR(opp); ++ goto unlock; ++ } ++ ++ cpufreq_device->cpu_dev = dev; ++ cpufreq_device->dyn_power_table = power_table; ++ cpufreq_device->dyn_power_table_entries = i; ++ ++unlock: ++ rcu_read_unlock(); ++ return ret; ++} ++ ++static u32 cpu_freq_to_power(struct cpufreq_cooling_device *cpufreq_device, ++ u32 freq) ++{ ++ int i; ++ struct power_table *pt = cpufreq_device->dyn_power_table; ++ ++ for (i = 1; i < cpufreq_device->dyn_power_table_entries; i++) ++ if (freq < pt[i].frequency) ++ break; ++ ++ return pt[i - 1].power; ++} ++ ++static u32 cpu_power_to_freq(struct cpufreq_cooling_device *cpufreq_device, ++ u32 power) ++{ ++ int i; ++ struct power_table *pt = cpufreq_device->dyn_power_table; ++ ++ for (i = 1; i < cpufreq_device->dyn_power_table_entries; i++) ++ if (power < pt[i].power) ++ break; ++ ++ return pt[i - 1].frequency; + } + + /** +- * cpufreq_thermal_notifier - notifier callback for cpufreq policy change. +- * @nb: struct notifier_block * with callback info. +- * @event: value showing cpufreq event for which this function invoked. +- * @data: callback-specific data ++ * get_load() - get load for a cpu since last updated ++ * @cpufreq_device: &struct cpufreq_cooling_device for this cpu ++ * @cpu: cpu number + * +- * Callback to hijack the notification on cpufreq policy transition. +- * Every time there is a change in policy, we will intercept and +- * update the cpufreq policy with thermal constraints. +- * +- * Return: 0 (success) ++ * Return: The average load of cpu @cpu in percentage since this ++ * function was last called. + */ +-static int cpufreq_thermal_notifier(struct notifier_block *nb, +- unsigned long event, void *data) ++static u32 get_load(struct cpufreq_cooling_device *cpufreq_device, int cpu) + { +- struct cpufreq_policy *policy = data; +- unsigned long max_freq = 0; +- struct cpufreq_cooling_device *cpufreq_dev; ++ u32 load; ++ u64 now, now_idle, delta_time, delta_idle; ++ ++ now_idle = get_cpu_idle_time(cpu, &now, 0); ++ delta_idle = now_idle - cpufreq_device->time_in_idle[cpu]; ++ delta_time = now - cpufreq_device->time_in_idle_timestamp[cpu]; ++ ++ if (delta_time <= delta_idle) ++ load = 0; ++ else ++ load = div64_u64(100 * (delta_time - delta_idle), delta_time); + +- if (event != CPUFREQ_ADJUST) ++ cpufreq_device->time_in_idle[cpu] = now_idle; ++ cpufreq_device->time_in_idle_timestamp[cpu] = now; ++ ++ return load; ++} ++ ++/** ++ * get_static_power() - calculate the static power consumed by the cpus ++ * @cpufreq_device: struct &cpufreq_cooling_device for this cpu cdev ++ * @tz: thermal zone device in which we're operating ++ * @freq: frequency in KHz ++ * @power: pointer in which to store the calculated static power ++ * ++ * Calculate the static power consumed by the cpus described by ++ * @cpu_actor running at frequency @freq. This function relies on a ++ * platform specific function that should have been provided when the ++ * actor was registered. If it wasn't, the static power is assumed to ++ * be negligible. The calculated static power is stored in @power. ++ * ++ * Return: 0 on success, -E* on failure. ++ */ ++static int get_static_power(struct cpufreq_cooling_device *cpufreq_device, ++ struct thermal_zone_device *tz, unsigned long freq, ++ u32 *power) ++{ ++ struct dev_pm_opp *opp; ++ unsigned long voltage; ++ struct cpumask *cpumask = &cpufreq_device->allowed_cpus; ++ unsigned long freq_hz = freq * 1000; ++ ++ if (!cpufreq_device->plat_get_static_power || ++ !cpufreq_device->cpu_dev) { ++ *power = 0; + return 0; ++ } + +- mutex_lock(&cooling_cpufreq_lock); +- list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) { +- if (!cpumask_test_cpu(policy->cpu, +- &cpufreq_dev->allowed_cpus)) +- continue; ++ rcu_read_lock(); + +- if (!cpufreq_dev->cpufreq_val) +- cpufreq_dev->cpufreq_val = get_cpu_frequency( +- cpumask_any(&cpufreq_dev->allowed_cpus), +- cpufreq_dev->cpufreq_state); ++ opp = dev_pm_opp_find_freq_exact(cpufreq_device->cpu_dev, freq_hz, ++ true); ++ voltage = dev_pm_opp_get_voltage(opp); + +- max_freq = cpufreq_dev->cpufreq_val; ++ rcu_read_unlock(); + +- if (policy->max != max_freq) +- cpufreq_verify_within_limits(policy, 0, max_freq); ++ if (voltage == 0) { ++ dev_warn_ratelimited(cpufreq_device->cpu_dev, ++ "Failed to get voltage for frequency %lu: %ld\n", ++ freq_hz, IS_ERR(opp) ? PTR_ERR(opp) : 0); ++ return -EINVAL; + } +- mutex_unlock(&cooling_cpufreq_lock); + +- return 0; ++ return cpufreq_device->plat_get_static_power(cpumask, tz->passive_delay, ++ voltage, power); ++} ++ ++/** ++ * get_dynamic_power() - calculate the dynamic power ++ * @cpufreq_device: &cpufreq_cooling_device for this cdev ++ * @freq: current frequency ++ * ++ * Return: the dynamic power consumed by the cpus described by ++ * @cpufreq_device. ++ */ ++static u32 get_dynamic_power(struct cpufreq_cooling_device *cpufreq_device, ++ unsigned long freq) ++{ ++ u32 raw_cpu_power; ++ ++ raw_cpu_power = cpu_freq_to_power(cpufreq_device, freq); ++ return (raw_cpu_power * cpufreq_device->last_load) / 100; + } + + /* cpufreq cooling device callback functions are defined below */ +@@ -354,19 +467,9 @@ static int cpufreq_get_max_state(struct thermal_cooling_device *cdev, + unsigned long *state) + { + struct cpufreq_cooling_device *cpufreq_device = cdev->devdata; +- struct cpumask *mask = &cpufreq_device->allowed_cpus; +- unsigned int cpu; +- unsigned int count = 0; +- int ret; + +- cpu = cpumask_any(mask); +- +- ret = get_property(cpu, 0, &count, GET_MAXL); +- +- if (count > 0) +- *state = count; +- +- return ret; ++ *state = cpufreq_device->max_level; ++ return 0; + } + + /** +@@ -403,12 +506,225 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev, + unsigned long state) + { + struct cpufreq_cooling_device *cpufreq_device = cdev->devdata; ++ unsigned int cpu = cpumask_any(&cpufreq_device->allowed_cpus); ++ unsigned int clip_freq; ++ ++ /* Request state should be less than max_level */ ++ if (WARN_ON(state > cpufreq_device->max_level)) ++ return -EINVAL; ++ ++ /* Check if the old cooling action is same as new cooling action */ ++ if (cpufreq_device->cpufreq_state == state) ++ return 0; ++ ++ clip_freq = cpufreq_device->freq_table[state]; ++ cpufreq_device->cpufreq_state = state; ++ cpufreq_device->cpufreq_val = clip_freq; ++ ++ cpufreq_update_policy(cpu); ++ ++ return 0; ++} ++ ++/** ++ * cpufreq_get_requested_power() - get the current power ++ * @cdev: &thermal_cooling_device pointer ++ * @tz: a valid thermal zone device pointer ++ * @power: pointer in which to store the resulting power ++ * ++ * Calculate the current power consumption of the cpus in milliwatts ++ * and store it in @power. This function should actually calculate ++ * the requested power, but it's hard to get the frequency that ++ * cpufreq would have assigned if there were no thermal limits. ++ * Instead, we calculate the current power on the assumption that the ++ * immediate future will look like the immediate past. ++ * ++ * We use the current frequency and the average load since this ++ * function was last called. In reality, there could have been ++ * multiple opps since this function was last called and that affects ++ * the load calculation. While it's not perfectly accurate, this ++ * simplification is good enough and works. REVISIT this, as more ++ * complex code may be needed if experiments show that it's not ++ * accurate enough. ++ * ++ * Return: 0 on success, -E* if getting the static power failed. ++ */ ++static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev, ++ struct thermal_zone_device *tz, ++ u32 *power) ++{ ++ unsigned long freq; ++ int i = 0, cpu, ret; ++ u32 static_power, dynamic_power, total_load = 0; ++ struct cpufreq_cooling_device *cpufreq_device = cdev->devdata; ++ u32 *load_cpu = NULL; ++ ++ cpu = cpumask_any_and(&cpufreq_device->allowed_cpus, cpu_online_mask); ++ ++ /* ++ * All the CPUs are offline, thus the requested power by ++ * the cdev is 0 ++ */ ++ if (cpu >= nr_cpu_ids) { ++ *power = 0; ++ return 0; ++ } ++ ++ freq = cpufreq_quick_get(cpu); ++ ++ if (trace_thermal_power_cpu_get_power_enabled()) { ++ u32 ncpus = cpumask_weight(&cpufreq_device->allowed_cpus); ++ ++ load_cpu = devm_kcalloc(&cdev->device, ncpus, sizeof(*load_cpu), ++ GFP_KERNEL); ++ } ++ ++ for_each_cpu(cpu, &cpufreq_device->allowed_cpus) { ++ u32 load; ++ ++ if (cpu_online(cpu)) ++ load = get_load(cpufreq_device, cpu); ++ else ++ load = 0; ++ ++ total_load += load; ++ if (trace_thermal_power_cpu_limit_enabled() && load_cpu) ++ load_cpu[i] = load; ++ ++ i++; ++ } ++ ++ cpufreq_device->last_load = total_load; ++ ++ dynamic_power = get_dynamic_power(cpufreq_device, freq); ++ ret = get_static_power(cpufreq_device, tz, freq, &static_power); ++ if (ret) { ++ if (load_cpu) ++ devm_kfree(&cdev->device, load_cpu); ++ return ret; ++ } ++ ++ if (load_cpu) { ++ trace_thermal_power_cpu_get_power( ++ &cpufreq_device->allowed_cpus, ++ freq, load_cpu, i, dynamic_power, static_power); ++ ++ devm_kfree(&cdev->device, load_cpu); ++ } ++ ++ *power = static_power + dynamic_power; ++ return 0; ++} ++ ++/** ++ * cpufreq_state2power() - convert a cpu cdev state to power consumed ++ * @cdev: &thermal_cooling_device pointer ++ * @tz: a valid thermal zone device pointer ++ * @state: cooling device state to be converted ++ * @power: pointer in which to store the resulting power ++ * ++ * Convert cooling device state @state into power consumption in ++ * milliwatts assuming 100% load. Store the calculated power in ++ * @power. ++ * ++ * Return: 0 on success, -EINVAL if the cooling device state could not ++ * be converted into a frequency or other -E* if there was an error ++ * when calculating the static power. ++ */ ++static int cpufreq_state2power(struct thermal_cooling_device *cdev, ++ struct thermal_zone_device *tz, ++ unsigned long state, u32 *power) ++{ ++ unsigned int freq, num_cpus; ++ cpumask_t cpumask; ++ u32 static_power, dynamic_power; ++ int ret; ++ struct cpufreq_cooling_device *cpufreq_device = cdev->devdata; ++ ++ cpumask_and(&cpumask, &cpufreq_device->allowed_cpus, cpu_online_mask); ++ num_cpus = cpumask_weight(&cpumask); ++ ++ /* None of our cpus are online, so no power */ ++ if (num_cpus == 0) { ++ *power = 0; ++ return 0; ++ } ++ ++ freq = cpufreq_device->freq_table[state]; ++ if (!freq) ++ return -EINVAL; + +- return cpufreq_apply_cooling(cpufreq_device, state); ++ dynamic_power = cpu_freq_to_power(cpufreq_device, freq) * num_cpus; ++ ret = get_static_power(cpufreq_device, tz, freq, &static_power); ++ if (ret) ++ return ret; ++ ++ *power = static_power + dynamic_power; ++ return 0; ++} ++ ++/** ++ * cpufreq_power2state() - convert power to a cooling device state ++ * @cdev: &thermal_cooling_device pointer ++ * @tz: a valid thermal zone device pointer ++ * @power: power in milliwatts to be converted ++ * @state: pointer in which to store the resulting state ++ * ++ * Calculate a cooling device state for the cpus described by @cdev ++ * that would allow them to consume at most @power mW and store it in ++ * @state. Note that this calculation depends on external factors ++ * such as the cpu load or the current static power. Calling this ++ * function with the same power as input can yield different cooling ++ * device states depending on those external factors. ++ * ++ * Return: 0 on success, -ENODEV if no cpus are online or -EINVAL if ++ * the calculated frequency could not be converted to a valid state. ++ * The latter should not happen unless the frequencies available to ++ * cpufreq have changed since the initialization of the cpu cooling ++ * device. ++ */ ++static int cpufreq_power2state(struct thermal_cooling_device *cdev, ++ struct thermal_zone_device *tz, u32 power, ++ unsigned long *state) ++{ ++ unsigned int cpu, cur_freq, target_freq; ++ int ret; ++ s32 dyn_power; ++ u32 last_load, normalised_power, static_power; ++ struct cpufreq_cooling_device *cpufreq_device = cdev->devdata; ++ ++ cpu = cpumask_any_and(&cpufreq_device->allowed_cpus, cpu_online_mask); ++ ++ /* None of our cpus are online */ ++ if (cpu >= nr_cpu_ids) ++ return -ENODEV; ++ ++ cur_freq = cpufreq_quick_get(cpu); ++ ret = get_static_power(cpufreq_device, tz, cur_freq, &static_power); ++ if (ret) ++ return ret; ++ ++ dyn_power = power - static_power; ++ dyn_power = dyn_power > 0 ? dyn_power : 0; ++ last_load = cpufreq_device->last_load ?: 1; ++ normalised_power = (dyn_power * 100) / last_load; ++ target_freq = cpu_power_to_freq(cpufreq_device, normalised_power); ++ ++ *state = cpufreq_cooling_get_level(cpu, target_freq); ++ if (*state == THERMAL_CSTATE_INVALID) { ++ dev_warn_ratelimited(&cdev->device, ++ "Failed to convert %dKHz for cpu %d into a cdev state\n", ++ target_freq, cpu); ++ return -EINVAL; ++ } ++ ++ trace_thermal_power_cpu_limit(&cpufreq_device->allowed_cpus, ++ target_freq, *state, power); ++ return 0; + } + + /* Bind cpufreq callbacks to thermal cooling device ops */ +-static struct thermal_cooling_device_ops const cpufreq_cooling_ops = { ++static struct thermal_cooling_device_ops cpufreq_cooling_ops = { + .get_max_state = cpufreq_get_max_state, + .get_cur_state = cpufreq_get_cur_state, + .set_cur_state = cpufreq_set_cur_state, +@@ -419,10 +735,28 @@ static struct notifier_block thermal_cpufreq_notifier_block = { + .notifier_call = cpufreq_thermal_notifier, + }; + ++static unsigned int find_next_max(struct cpufreq_frequency_table *table, ++ unsigned int prev_max) ++{ ++ struct cpufreq_frequency_table *pos; ++ unsigned int max = 0; ++ ++ cpufreq_for_each_valid_entry(pos, table) { ++ if (pos->frequency > max && pos->frequency < prev_max) ++ max = pos->frequency; ++ } ++ ++ return max; ++} ++ + /** + * __cpufreq_cooling_register - helper function to create cpufreq cooling device + * @np: a valid struct device_node to the cooling device device tree node + * @clip_cpus: cpumask of cpus where the frequency constraints will happen. ++ * Normally this should be same as cpufreq policy->related_cpus. ++ * @capacitance: dynamic power coefficient for these cpus ++ * @plat_static_func: function to calculate the static power consumed by these ++ * cpus (optional) + * + * This interface function registers the cpufreq cooling device with the name + * "thermal-cpufreq-%x". This api can support multiple instances of cpufreq +@@ -434,40 +768,77 @@ static struct notifier_block thermal_cpufreq_notifier_block = { + */ + static struct thermal_cooling_device * + __cpufreq_cooling_register(struct device_node *np, +- const struct cpumask *clip_cpus) ++ const struct cpumask *clip_cpus, u32 capacitance, ++ get_static_t plat_static_func) + { + struct thermal_cooling_device *cool_dev; +- struct cpufreq_cooling_device *cpufreq_dev = NULL; +- unsigned int min = 0, max = 0; ++ struct cpufreq_cooling_device *cpufreq_dev; + char dev_name[THERMAL_NAME_LENGTH]; +- int ret = 0, i; +- struct cpufreq_policy policy; ++ struct cpufreq_frequency_table *pos, *table; ++ unsigned int freq, i, num_cpus; ++ int ret; + +- /* Verify that all the clip cpus have same freq_min, freq_max limit */ +- for_each_cpu(i, clip_cpus) { +- /* continue if cpufreq policy not found and not return error */ +- if (!cpufreq_get_policy(&policy, i)) +- continue; +- if (min == 0 && max == 0) { +- min = policy.cpuinfo.min_freq; +- max = policy.cpuinfo.max_freq; +- } else { +- if (min != policy.cpuinfo.min_freq || +- max != policy.cpuinfo.max_freq) +- return ERR_PTR(-EINVAL); +- } ++ table = cpufreq_frequency_get_table(cpumask_first(clip_cpus)); ++ if (!table) { ++ pr_debug("%s: CPUFreq table not found\n", __func__); ++ return ERR_PTR(-EPROBE_DEFER); + } +- cpufreq_dev = kzalloc(sizeof(struct cpufreq_cooling_device), +- GFP_KERNEL); ++ ++ cpufreq_dev = kzalloc(sizeof(*cpufreq_dev), GFP_KERNEL); + if (!cpufreq_dev) + return ERR_PTR(-ENOMEM); + ++ num_cpus = cpumask_weight(clip_cpus); ++ cpufreq_dev->time_in_idle = kcalloc(num_cpus, ++ sizeof(*cpufreq_dev->time_in_idle), ++ GFP_KERNEL); ++ if (!cpufreq_dev->time_in_idle) { ++ cool_dev = ERR_PTR(-ENOMEM); ++ goto free_cdev; ++ } ++ ++ cpufreq_dev->time_in_idle_timestamp = ++ kcalloc(num_cpus, sizeof(*cpufreq_dev->time_in_idle_timestamp), ++ GFP_KERNEL); ++ if (!cpufreq_dev->time_in_idle_timestamp) { ++ cool_dev = ERR_PTR(-ENOMEM); ++ goto free_time_in_idle; ++ } ++ ++ /* Find max levels */ ++ cpufreq_for_each_valid_entry(pos, table) ++ cpufreq_dev->max_level++; ++ ++ cpufreq_dev->freq_table = kmalloc(sizeof(*cpufreq_dev->freq_table) * ++ cpufreq_dev->max_level, GFP_KERNEL); ++ if (!cpufreq_dev->freq_table) { ++ cool_dev = ERR_PTR(-ENOMEM); ++ goto free_time_in_idle_timestamp; ++ } ++ ++ /* max_level is an index, not a counter */ ++ cpufreq_dev->max_level--; ++ + cpumask_copy(&cpufreq_dev->allowed_cpus, clip_cpus); + ++ if (capacitance) { ++ cpufreq_cooling_ops.get_requested_power = ++ cpufreq_get_requested_power; ++ cpufreq_cooling_ops.state2power = cpufreq_state2power; ++ cpufreq_cooling_ops.power2state = cpufreq_power2state; ++ cpufreq_dev->plat_get_static_power = plat_static_func; ++ ++ ret = build_dyn_power_table(cpufreq_dev, capacitance); ++ if (ret) { ++ cool_dev = ERR_PTR(ret); ++ goto free_table; ++ } ++ } ++ + ret = get_idr(&cpufreq_idr, &cpufreq_dev->id); + if (ret) { +- kfree(cpufreq_dev); +- return ERR_PTR(-EINVAL); ++ cool_dev = ERR_PTR(ret); ++ goto free_table; + } + + snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d", +@@ -475,25 +846,48 @@ __cpufreq_cooling_register(struct device_node *np, + + cool_dev = thermal_of_cooling_device_register(np, dev_name, cpufreq_dev, + &cpufreq_cooling_ops); +- if (IS_ERR(cool_dev)) { +- release_idr(&cpufreq_idr, cpufreq_dev->id); +- kfree(cpufreq_dev); +- return cool_dev; ++ if (IS_ERR(cool_dev)) ++ goto remove_idr; ++ ++ /* Fill freq-table in descending order of frequencies */ ++ for (i = 0, freq = -1; i <= cpufreq_dev->max_level; i++) { ++ freq = find_next_max(table, freq); ++ cpufreq_dev->freq_table[i] = freq; ++ ++ /* Warn for duplicate entries */ ++ if (!freq) ++ pr_warn("%s: table has duplicate entries\n", __func__); ++ else ++ pr_debug("%s: freq:%u KHz\n", __func__, freq); + } ++ ++ cpufreq_dev->cpufreq_val = cpufreq_dev->freq_table[0]; + cpufreq_dev->cool_dev = cool_dev; +- cpufreq_dev->cpufreq_state = 0; ++ + mutex_lock(&cooling_cpufreq_lock); + + /* Register the notifier for first cpufreq cooling device */ +- if (cpufreq_dev_count == 0) ++ if (list_empty(&cpufreq_dev_list)) + cpufreq_register_notifier(&thermal_cpufreq_notifier_block, + CPUFREQ_POLICY_NOTIFIER); +- cpufreq_dev_count++; + list_add(&cpufreq_dev->node, &cpufreq_dev_list); + + mutex_unlock(&cooling_cpufreq_lock); + + return cool_dev; ++ ++remove_idr: ++ release_idr(&cpufreq_idr, cpufreq_dev->id); ++free_table: ++ kfree(cpufreq_dev->freq_table); ++free_time_in_idle_timestamp: ++ kfree(cpufreq_dev->time_in_idle_timestamp); ++free_time_in_idle: ++ kfree(cpufreq_dev->time_in_idle); ++free_cdev: ++ kfree(cpufreq_dev); ++ ++ return cool_dev; + } + + /** +@@ -510,7 +904,7 @@ __cpufreq_cooling_register(struct device_node *np, + struct thermal_cooling_device * + cpufreq_cooling_register(const struct cpumask *clip_cpus) + { +- return __cpufreq_cooling_register(NULL, clip_cpus); ++ return __cpufreq_cooling_register(NULL, clip_cpus, 0, NULL); + } + EXPORT_SYMBOL_GPL(cpufreq_cooling_register); + +@@ -534,11 +928,78 @@ of_cpufreq_cooling_register(struct device_node *np, + if (!np) + return ERR_PTR(-EINVAL); + +- return __cpufreq_cooling_register(np, clip_cpus); ++ return __cpufreq_cooling_register(np, clip_cpus, 0, NULL); + } + EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register); + + /** ++ * cpufreq_power_cooling_register() - create cpufreq cooling device with power extensions ++ * @clip_cpus: cpumask of cpus where the frequency constraints will happen ++ * @capacitance: dynamic power coefficient for these cpus ++ * @plat_static_func: function to calculate the static power consumed by these ++ * cpus (optional) ++ * ++ * This interface function registers the cpufreq cooling device with ++ * the name "thermal-cpufreq-%x". This api can support multiple ++ * instances of cpufreq cooling devices. Using this function, the ++ * cooling device will implement the power extensions by using a ++ * simple cpu power model. The cpus must have registered their OPPs ++ * using the OPP library. ++ * ++ * An optional @plat_static_func may be provided to calculate the ++ * static power consumed by these cpus. If the platform's static ++ * power consumption is unknown or negligible, make it NULL. ++ * ++ * Return: a valid struct thermal_cooling_device pointer on success, ++ * on failure, it returns a corresponding ERR_PTR(). ++ */ ++struct thermal_cooling_device * ++cpufreq_power_cooling_register(const struct cpumask *clip_cpus, u32 capacitance, ++ get_static_t plat_static_func) ++{ ++ return __cpufreq_cooling_register(NULL, clip_cpus, capacitance, ++ plat_static_func); ++} ++EXPORT_SYMBOL(cpufreq_power_cooling_register); ++ ++/** ++ * of_cpufreq_power_cooling_register() - create cpufreq cooling device with power extensions ++ * @np: a valid struct device_node to the cooling device device tree node ++ * @clip_cpus: cpumask of cpus where the frequency constraints will happen ++ * @capacitance: dynamic power coefficient for these cpus ++ * @plat_static_func: function to calculate the static power consumed by these ++ * cpus (optional) ++ * ++ * This interface function registers the cpufreq cooling device with ++ * the name "thermal-cpufreq-%x". This api can support multiple ++ * instances of cpufreq cooling devices. Using this API, the cpufreq ++ * cooling device will be linked to the device tree node provided. ++ * Using this function, the cooling device will implement the power ++ * extensions by using a simple cpu power model. The cpus must have ++ * registered their OPPs using the OPP library. ++ * ++ * An optional @plat_static_func may be provided to calculate the ++ * static power consumed by these cpus. If the platform's static ++ * power consumption is unknown or negligible, make it NULL. ++ * ++ * Return: a valid struct thermal_cooling_device pointer on success, ++ * on failure, it returns a corresponding ERR_PTR(). ++ */ ++struct thermal_cooling_device * ++of_cpufreq_power_cooling_register(struct device_node *np, ++ const struct cpumask *clip_cpus, ++ u32 capacitance, ++ get_static_t plat_static_func) ++{ ++ if (!np) ++ return ERR_PTR(-EINVAL); ++ ++ return __cpufreq_cooling_register(np, clip_cpus, capacitance, ++ plat_static_func); ++} ++EXPORT_SYMBOL(of_cpufreq_power_cooling_register); ++ ++/** + * cpufreq_cooling_unregister - function to remove cpufreq cooling device. + * @cdev: thermal cooling device pointer. + * +@@ -554,16 +1015,18 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) + cpufreq_dev = cdev->devdata; + mutex_lock(&cooling_cpufreq_lock); + list_del(&cpufreq_dev->node); +- cpufreq_dev_count--; + + /* Unregister the notifier for the last cpufreq cooling device */ +- if (cpufreq_dev_count == 0) ++ if (list_empty(&cpufreq_dev_list)) + cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block, + CPUFREQ_POLICY_NOTIFIER); + mutex_unlock(&cooling_cpufreq_lock); + + thermal_cooling_device_unregister(cpufreq_dev->cool_dev); + release_idr(&cpufreq_idr, cpufreq_dev->id); ++ kfree(cpufreq_dev->time_in_idle_timestamp); ++ kfree(cpufreq_dev->time_in_idle); ++ kfree(cpufreq_dev->freq_table); + kfree(cpufreq_dev); + } + EXPORT_SYMBOL_GPL(cpufreq_cooling_unregister); +diff --git a/drivers/thermal/db8500_cpufreq_cooling.c b/drivers/thermal/db8500_cpufreq_cooling.c +index 786d192..1ac7ec6 100644 +--- a/drivers/thermal/db8500_cpufreq_cooling.c ++++ b/drivers/thermal/db8500_cpufreq_cooling.c +@@ -18,7 +18,6 @@ + */ + + #include +-#include + #include + #include + #include +@@ -30,10 +29,6 @@ static int db8500_cpufreq_cooling_probe(struct platform_device *pdev) + struct thermal_cooling_device *cdev; + struct cpumask mask_val; + +- /* make sure cpufreq driver has been initialized */ +- if (!cpufreq_frequency_get_table(0)) +- return -EPROBE_DEFER; +- + cpumask_set_cpu(0, &mask_val); + cdev = cpufreq_cooling_register(&mask_val); + +diff --git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c +index 1e3b3bf..e3ccc221 100644 +--- a/drivers/thermal/db8500_thermal.c ++++ b/drivers/thermal/db8500_thermal.c +@@ -76,7 +76,7 @@ static int db8500_cdev_bind(struct thermal_zone_device *thermal, + upper = lower = i > max_state ? max_state : i; + + ret = thermal_zone_bind_cooling_device(thermal, i, cdev, +- upper, lower); ++ upper, lower, THERMAL_WEIGHT_DEFAULT); + + dev_info(&cdev->device, "%s bind to %d: %d-%s\n", cdev->type, + i, ret, ret ? "fail" : "succeed"); +diff --git a/drivers/thermal/fair_share.c b/drivers/thermal/fair_share.c +index 6e0a3fb..8c50b8d 100644 +--- a/drivers/thermal/fair_share.c ++++ b/drivers/thermal/fair_share.c +@@ -59,13 +59,13 @@ static int get_trip_level(struct thermal_zone_device *tz) + } + + static long get_target_state(struct thermal_zone_device *tz, +- struct thermal_cooling_device *cdev, int weight, int level) ++ struct thermal_cooling_device *cdev, int percentage, int level) + { + unsigned long max_state; + + cdev->ops->get_max_state(cdev, &max_state); + +- return (long)(weight * level * max_state) / (100 * tz->trips); ++ return (long)(percentage * level * max_state) / (100 * tz->trips); + } + + /** +@@ -77,7 +77,7 @@ static long get_target_state(struct thermal_zone_device *tz, + * + * Parameters used for Throttling: + * P1. max_state: Maximum throttle state exposed by the cooling device. +- * P2. weight[i]/100: ++ * P2. percentage[i]/100: + * How 'effective' the 'i'th device is, in cooling the given zone. + * P3. cur_trip_level/max_no_of_trips: + * This describes the extent to which the devices should be throttled. +@@ -88,28 +88,33 @@ static long get_target_state(struct thermal_zone_device *tz, + */ + static int fair_share_throttle(struct thermal_zone_device *tz, int trip) + { +- const struct thermal_zone_params *tzp; +- struct thermal_cooling_device *cdev; + struct thermal_instance *instance; +- int i; ++ int total_weight = 0; ++ int total_instance = 0; + int cur_trip_level = get_trip_level(tz); + +- if (!tz->tzp || !tz->tzp->tbp) +- return -EINVAL; ++ list_for_each_entry(instance, &tz->thermal_instances, tz_node) { ++ if (instance->trip != trip) ++ continue; ++ ++ total_weight += instance->weight; ++ total_instance++; ++ } + +- tzp = tz->tzp; ++ list_for_each_entry(instance, &tz->thermal_instances, tz_node) { ++ int percentage; ++ struct thermal_cooling_device *cdev = instance->cdev; + +- for (i = 0; i < tzp->num_tbps; i++) { +- if (!tzp->tbp[i].cdev) ++ if (instance->trip != trip) + continue; + +- cdev = tzp->tbp[i].cdev; +- instance = get_thermal_instance(tz, cdev, trip); +- if (!instance) +- continue; ++ if (!total_weight) ++ percentage = 100 / total_instance; ++ else ++ percentage = (instance->weight * 100) / total_weight; + +- instance->target = get_target_state(tz, cdev, +- tzp->tbp[i].weight, cur_trip_level); ++ instance->target = get_target_state(tz, cdev, percentage, ++ cur_trip_level); + + instance->cdev->updated = false; + thermal_cdev_update(cdev); +diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c +index 5a1f107..31ada06 100644 +--- a/drivers/thermal/imx_thermal.c ++++ b/drivers/thermal/imx_thermal.c +@@ -9,7 +9,6 @@ + + #include + #include +-#include + #include + #include + #include +@@ -307,7 +306,8 @@ static int imx_bind(struct thermal_zone_device *tz, + + ret = thermal_zone_bind_cooling_device(tz, IMX_TRIP_PASSIVE, cdev, + THERMAL_NO_LIMIT, +- THERMAL_NO_LIMIT); ++ THERMAL_NO_LIMIT, ++ THERMAL_WEIGHT_DEFAULT); + if (ret) { + dev_err(&tz->device, + "binding zone %s with cdev %s failed:%d\n", +@@ -459,10 +459,6 @@ static int imx_thermal_probe(struct platform_device *pdev) + int measure_freq; + int ret; + +- if (!cpufreq_get_current_driver()) { +- dev_dbg(&pdev->dev, "no cpufreq driver!"); +- return -EPROBE_DEFER; +- } + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; +diff --git a/drivers/thermal/int340x_thermal/int3403_thermal.c b/drivers/thermal/int340x_thermal/int3403_thermal.c +index 6e9fb62..76910d3 100644 +--- a/drivers/thermal/int340x_thermal/int3403_thermal.c ++++ b/drivers/thermal/int340x_thermal/int3403_thermal.c +@@ -471,7 +471,6 @@ static struct platform_driver int3403_driver = { + .remove = int3403_remove, + .driver = { + .name = "int3403 thermal", +- .owner = THIS_MODULE, + .acpi_match_table = int3403_device_ids, + }, + }; +diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c +index 62143ba..b295b2b 100644 +--- a/drivers/thermal/of-thermal.c ++++ b/drivers/thermal/of-thermal.c +@@ -30,27 +30,13 @@ + #include + #include + #include ++#include + + #include "thermal_core.h" + + /*** Private data structures to represent thermal device tree data ***/ + + /** +- * struct __thermal_trip - representation of a point in temperature domain +- * @np: pointer to struct device_node that this trip point was created from +- * @temperature: temperature value in miliCelsius +- * @hysteresis: relative hysteresis in miliCelsius +- * @type: trip point type +- */ +- +-struct __thermal_trip { +- struct device_node *np; +- unsigned long int temperature; +- unsigned long int hysteresis; +- enum thermal_trip_type type; +-}; +- +-/** + * struct __thermal_bind_param - a match between trip and cooling device + * @cooling_device: a pointer to identify the referred cooling device + * @trip_id: the trip point index +@@ -72,23 +58,26 @@ struct __thermal_bind_params { + * @mode: current thermal zone device mode (enabled/disabled) + * @passive_delay: polling interval while passive cooling is activated + * @polling_delay: zone polling interval ++ * @slope: slope of the temperature adjustment curve ++ * @offset: offset of the temperature adjustment curve + * @ntrips: number of trip points + * @trips: an array of trip points (0..ntrips - 1) + * @num_tbps: number of thermal bind params + * @tbps: an array of thermal bind params (0..num_tbps - 1) + * @sensor_data: sensor private data used while reading temperature and trend +- * @get_temp: sensor callback to read temperature +- * @get_trend: sensor callback to read temperature trend ++ * @ops: set of callbacks to handle the thermal zone based on DT + */ + + struct __thermal_zone { + enum thermal_device_mode mode; + int passive_delay; + int polling_delay; ++ int slope; ++ int offset; + + /* trip data */ + int ntrips; +- struct __thermal_trip *trips; ++ struct thermal_trip *trips; + + /* cooling binding data */ + int num_tbps; +@@ -96,8 +85,7 @@ struct __thermal_zone { + + /* sensor interface */ + void *sensor_data; +- int (*get_temp)(void *, long *); +- int (*get_trend)(void *, long *); ++ const struct thermal_zone_of_device_ops *ops; + }; + + /*** DT thermal zone device callbacks ***/ +@@ -107,10 +95,96 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz, + { + struct __thermal_zone *data = tz->devdata; + +- if (!data->get_temp) ++ if (!data->ops->get_temp) + return -EINVAL; + +- return data->get_temp(data->sensor_data, temp); ++ return data->ops->get_temp(data->sensor_data, temp); ++} ++ ++/** ++ * of_thermal_get_ntrips - function to export number of available trip ++ * points. ++ * @tz: pointer to a thermal zone ++ * ++ * This function is a globally visible wrapper to get number of trip points ++ * stored in the local struct __thermal_zone ++ * ++ * Return: number of available trip points, -ENODEV when data not available ++ */ ++int of_thermal_get_ntrips(struct thermal_zone_device *tz) ++{ ++ struct __thermal_zone *data = tz->devdata; ++ ++ if (!data || IS_ERR(data)) ++ return -ENODEV; ++ ++ return data->ntrips; ++} ++EXPORT_SYMBOL_GPL(of_thermal_get_ntrips); ++ ++/** ++ * of_thermal_is_trip_valid - function to check if trip point is valid ++ * ++ * @tz: pointer to a thermal zone ++ * @trip: trip point to evaluate ++ * ++ * This function is responsible for checking if passed trip point is valid ++ * ++ * Return: true if trip point is valid, false otherwise ++ */ ++bool of_thermal_is_trip_valid(struct thermal_zone_device *tz, int trip) ++{ ++ struct __thermal_zone *data = tz->devdata; ++ ++ if (!data || trip >= data->ntrips || trip < 0) ++ return false; ++ ++ return true; ++} ++EXPORT_SYMBOL_GPL(of_thermal_is_trip_valid); ++ ++/** ++ * of_thermal_get_trip_points - function to get access to a globally exported ++ * trip points ++ * ++ * @tz: pointer to a thermal zone ++ * ++ * This function provides a pointer to trip points table ++ * ++ * Return: pointer to trip points table, NULL otherwise ++ */ ++const struct thermal_trip * ++of_thermal_get_trip_points(struct thermal_zone_device *tz) ++{ ++ struct __thermal_zone *data = tz->devdata; ++ ++ if (!data) ++ return NULL; ++ ++ return data->trips; ++} ++EXPORT_SYMBOL_GPL(of_thermal_get_trip_points); ++ ++/** ++ * of_thermal_set_emul_temp - function to set emulated temperature ++ * ++ * @tz: pointer to a thermal zone ++ * @temp: temperature to set ++ * ++ * This function gives the ability to set emulated value of temperature, ++ * which is handy for debugging ++ * ++ * Return: zero on success, error code otherwise ++ */ ++static int of_thermal_set_emul_temp(struct thermal_zone_device *tz, ++ unsigned long temp) ++{ ++ struct __thermal_zone *data = tz->devdata; ++ ++ if (!data->ops || !data->ops->set_emul_temp) ++ return -EINVAL; ++ ++ return data->ops->set_emul_temp(data->sensor_data, temp); + } + + static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip, +@@ -120,10 +194,10 @@ static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip, + long dev_trend; + int r; + +- if (!data->get_trend) ++ if (!data->ops->get_trend) + return -EINVAL; + +- r = data->get_trend(data->sensor_data, &dev_trend); ++ r = data->ops->get_trend(data->sensor_data, &dev_trend); + if (r) + return r; + +@@ -157,7 +231,8 @@ static int of_thermal_bind(struct thermal_zone_device *thermal, + ret = thermal_zone_bind_cooling_device(thermal, + tbp->trip_id, cdev, + tbp->max, +- tbp->min); ++ tbp->min, ++ tbp->usage); + if (ret) + return ret; + } +@@ -324,8 +399,7 @@ static struct thermal_zone_device_ops of_thermal_ops = { + static struct thermal_zone_device * + thermal_zone_of_add_sensor(struct device_node *zone, + struct device_node *sensor, void *data, +- int (*get_temp)(void *, long *), +- int (*get_trend)(void *, long *)) ++ const struct thermal_zone_of_device_ops *ops) + { + struct thermal_zone_device *tzd; + struct __thermal_zone *tz; +@@ -336,13 +410,16 @@ thermal_zone_of_add_sensor(struct device_node *zone, + + tz = tzd->devdata; + ++ if (!ops) ++ return ERR_PTR(-EINVAL); ++ + mutex_lock(&tzd->lock); +- tz->get_temp = get_temp; +- tz->get_trend = get_trend; ++ tz->ops = ops; + tz->sensor_data = data; + + tzd->ops->get_temp = of_thermal_get_temp; + tzd->ops->get_trend = of_thermal_get_trend; ++ tzd->ops->set_emul_temp = of_thermal_set_emul_temp; + mutex_unlock(&tzd->lock); + + return tzd; +@@ -356,8 +433,7 @@ thermal_zone_of_add_sensor(struct device_node *zone, + * than one sensors + * @data: a private pointer (owned by the caller) that will be passed + * back, when a temperature reading is needed. +- * @get_temp: a pointer to a function that reads the sensor temperature. +- * @get_trend: a pointer to a function that reads the sensor temperature trend. ++ * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp. + * + * This function will search the list of thermal zones described in device + * tree and look for the zone that refer to the sensor device pointed by +@@ -382,9 +458,8 @@ thermal_zone_of_add_sensor(struct device_node *zone, + * check the return value with help of IS_ERR() helper. + */ + struct thermal_zone_device * +-thermal_zone_of_sensor_register(struct device *dev, int sensor_id, +- void *data, int (*get_temp)(void *, long *), +- int (*get_trend)(void *, long *)) ++thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data, ++ const struct thermal_zone_of_device_ops *ops) + { + struct device_node *np, *child, *sensor_np; + struct thermal_zone_device *tzd = ERR_PTR(-ENODEV); +@@ -426,9 +501,10 @@ thermal_zone_of_sensor_register(struct device *dev, int sensor_id, + + if (sensor_specs.np == sensor_np && id == sensor_id) { + tzd = thermal_zone_of_add_sensor(child, sensor_np, +- data, +- get_temp, +- get_trend); ++ data, ops); ++ if (!IS_ERR(tzd)) ++ tzd->ops->set_mode(tzd, THERMAL_DEVICE_ENABLED); ++ + of_node_put(sensor_specs.np); + of_node_put(child); + goto exit; +@@ -475,9 +551,9 @@ void thermal_zone_of_sensor_unregister(struct device *dev, + mutex_lock(&tzd->lock); + tzd->ops->get_temp = NULL; + tzd->ops->get_trend = NULL; ++ tzd->ops->set_emul_temp = NULL; + +- tz->get_temp = NULL; +- tz->get_trend = NULL; ++ tz->ops = NULL; + tz->sensor_data = NULL; + mutex_unlock(&tzd->lock); + } +@@ -501,7 +577,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_unregister); + */ + static int thermal_of_populate_bind_params(struct device_node *np, + struct __thermal_bind_params *__tbp, +- struct __thermal_trip *trips, ++ struct thermal_trip *trips, + int ntrips) + { + struct of_phandle_args cooling_spec; +@@ -510,7 +586,7 @@ static int thermal_of_populate_bind_params(struct device_node *np, + u32 prop; + + /* Default weight. Usage is optional */ +- __tbp->usage = 0; ++ __tbp->usage = THERMAL_WEIGHT_DEFAULT; + ret = of_property_read_u32(np, "contribution", &prop); + if (ret == 0) + __tbp->usage = prop; +@@ -604,7 +680,7 @@ static int thermal_of_get_trip_type(struct device_node *np, + * Return: 0 on success, proper error code otherwise + */ + static int thermal_of_populate_trip(struct device_node *np, +- struct __thermal_trip *trip) ++ struct thermal_trip *trip) + { + int prop; + int ret; +@@ -644,7 +720,7 @@ static int thermal_of_populate_trip(struct device_node *np, + * @np parameter and fills the read data into a __thermal_zone data structure + * and return this pointer. + * +- * TODO: Missing properties to parse: thermal-sensor-names and coefficients ++ * TODO: Missing properties to parse: thermal-sensor-names + * + * Return: On success returns a valid struct __thermal_zone, + * otherwise, it returns a corresponding ERR_PTR(). Caller must +@@ -656,7 +732,7 @@ thermal_of_build_thermal_zone(struct device_node *np) + struct device_node *child = NULL, *gchild; + struct __thermal_zone *tz; + int ret, i; +- u32 prop; ++ u32 prop, coef[2]; + + if (!np) { + pr_err("no thermal zone np\n"); +@@ -681,6 +757,20 @@ thermal_of_build_thermal_zone(struct device_node *np) + } + tz->polling_delay = prop; + ++ /* ++ * REVIST: for now, the thermal framework supports only ++ * one sensor per thermal zone. Thus, we are considering ++ * only the first two values as slope and offset. ++ */ ++ ret = of_property_read_u32_array(np, "coefficients", coef, 2); ++ if (ret == 0) { ++ tz->slope = coef[0]; ++ tz->offset = coef[1]; ++ } else { ++ tz->slope = 1; ++ tz->offset = 0; ++ } ++ + /* trips */ + child = of_get_child_by_name(np, "trips"); + +@@ -794,6 +884,8 @@ int __init of_parse_thermal_zones(void) + for_each_child_of_node(np, child) { + struct thermal_zone_device *zone; + struct thermal_zone_params *tzp; ++ int i, mask = 0; ++ u32 prop; + + /* Check whether child is enabled or not */ + if (!of_device_is_available(child)) +@@ -820,8 +912,18 @@ int __init of_parse_thermal_zones(void) + /* No hwmon because there might be hwmon drivers registering */ + tzp->no_hwmon = true; + ++ if (!of_property_read_u32(child, "sustainable-power", &prop)) ++ tzp->sustainable_power = prop; ++ ++ for (i = 0; i < tz->ntrips; i++) ++ mask |= 1 << i; ++ ++ /* these two are left for temperature drivers to use */ ++ tzp->slope = tz->slope; ++ tzp->offset = tz->offset; ++ + zone = thermal_zone_device_register(child->name, tz->ntrips, +- 0, tz, ++ mask, tz, + ops, tzp, + tz->passive_delay, + tz->polling_delay); +diff --git a/drivers/thermal/power_allocator.c b/drivers/thermal/power_allocator.c +new file mode 100644 +index 0000000..2516769 +--- /dev/null ++++ b/drivers/thermal/power_allocator.c +@@ -0,0 +1,544 @@ ++/* ++ * A power allocator to manage temperature ++ * ++ * Copyright (C) 2014 ARM Ltd. ++ * ++ * 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 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. ++ */ ++ ++#define pr_fmt(fmt) "Power allocator: " fmt ++ ++#include ++#include ++#include ++ ++#define CREATE_TRACE_POINTS ++#include ++ ++#include "thermal_core.h" ++ ++#define FRAC_BITS 10 ++#define int_to_frac(x) ((x) << FRAC_BITS) ++#define frac_to_int(x) ((x) >> FRAC_BITS) ++ ++/** ++ * mul_frac() - multiply two fixed-point numbers ++ * @x: first multiplicand ++ * @y: second multiplicand ++ * ++ * Return: the result of multiplying two fixed-point numbers. The ++ * result is also a fixed-point number. ++ */ ++static inline s64 mul_frac(s64 x, s64 y) ++{ ++ return (x * y) >> FRAC_BITS; ++} ++ ++/** ++ * div_frac() - divide two fixed-point numbers ++ * @x: the dividend ++ * @y: the divisor ++ * ++ * Return: the result of dividing two fixed-point numbers. The ++ * result is also a fixed-point number. ++ */ ++static inline s64 div_frac(s64 x, s64 y) ++{ ++ return div_s64(x << FRAC_BITS, y); ++} ++ ++/** ++ * struct power_allocator_params - parameters for the power allocator governor ++ * @err_integral: accumulated error in the PID controller. ++ * @prev_err: error in the previous iteration of the PID controller. ++ * Used to calculate the derivative term. ++ * @trip_switch_on: first passive trip point of the thermal zone. The ++ * governor switches on when this trip point is crossed. ++ * @trip_max_desired_temperature: last passive trip point of the thermal ++ * zone. The temperature we are ++ * controlling for. ++ */ ++struct power_allocator_params { ++ s64 err_integral; ++ s32 prev_err; ++ int trip_switch_on; ++ int trip_max_desired_temperature; ++}; ++ ++/** ++ * pid_controller() - PID controller ++ * @tz: thermal zone we are operating in ++ * @current_temp: the current temperature in millicelsius ++ * @control_temp: the target temperature in millicelsius ++ * @max_allocatable_power: maximum allocatable power for this thermal zone ++ * ++ * This PID controller increases the available power budget so that the ++ * temperature of the thermal zone gets as close as possible to ++ * @control_temp and limits the power if it exceeds it. k_po is the ++ * proportional term when we are overshooting, k_pu is the ++ * proportional term when we are undershooting. integral_cutoff is a ++ * threshold below which we stop accumulating the error. The ++ * accumulated error is only valid if the requested power will make ++ * the system warmer. If the system is mostly idle, there's no point ++ * in accumulating positive error. ++ * ++ * Return: The power budget for the next period. ++ */ ++static u32 pid_controller(struct thermal_zone_device *tz, ++ unsigned long current_temp, ++ unsigned long control_temp, ++ u32 max_allocatable_power) ++{ ++ s64 p, i, d, power_range; ++ s32 err, max_power_frac; ++ struct power_allocator_params *params = tz->governor_data; ++ ++ max_power_frac = int_to_frac(max_allocatable_power); ++ ++ err = ((s32)control_temp - (s32)current_temp); ++ err = int_to_frac(err); ++ ++ /* Calculate the proportional term */ ++ p = mul_frac(err < 0 ? tz->tzp->k_po : tz->tzp->k_pu, err); ++ ++ /* ++ * Calculate the integral term ++ * ++ * if the error is less than cut off allow integration (but ++ * the integral is limited to max power) ++ */ ++ i = mul_frac(tz->tzp->k_i, params->err_integral); ++ ++ if (err < int_to_frac(tz->tzp->integral_cutoff)) { ++ s64 i_next = i + mul_frac(tz->tzp->k_i, err); ++ ++ if (abs64(i_next) < max_power_frac) { ++ i = i_next; ++ params->err_integral += err; ++ } ++ } ++ ++ /* ++ * Calculate the derivative term ++ * ++ * We do err - prev_err, so with a positive k_d, a decreasing ++ * error (i.e. driving closer to the line) results in less ++ * power being applied, slowing down the controller) ++ */ ++ d = mul_frac(tz->tzp->k_d, err - params->prev_err); ++ d = div_frac(d, tz->passive_delay); ++ params->prev_err = err; ++ ++ power_range = p + i + d; ++ ++ /* feed-forward the known sustainable dissipatable power */ ++ power_range = tz->tzp->sustainable_power + frac_to_int(power_range); ++ ++ power_range = clamp(power_range, (s64)0, (s64)max_allocatable_power); ++ ++ trace_thermal_power_allocator_pid(tz, frac_to_int(err), ++ frac_to_int(params->err_integral), ++ frac_to_int(p), frac_to_int(i), ++ frac_to_int(d), power_range); ++ ++ return power_range; ++} ++ ++/** ++ * divvy_up_power() - divvy the allocated power between the actors ++ * @req_power: each actor's requested power ++ * @max_power: each actor's maximum available power ++ * @num_actors: size of the @req_power, @max_power and @granted_power's array ++ * @total_req_power: sum of @req_power ++ * @power_range: total allocated power ++ * @granted_power: output array: each actor's granted power ++ * @extra_actor_power: an appropriately sized array to be used in the ++ * function as temporary storage of the extra power given ++ * to the actors ++ * ++ * This function divides the total allocated power (@power_range) ++ * fairly between the actors. It first tries to give each actor a ++ * share of the @power_range according to how much power it requested ++ * compared to the rest of the actors. For example, if only one actor ++ * requests power, then it receives all the @power_range. If ++ * three actors each requests 1mW, each receives a third of the ++ * @power_range. ++ * ++ * If any actor received more than their maximum power, then that ++ * surplus is re-divvied among the actors based on how far they are ++ * from their respective maximums. ++ * ++ * Granted power for each actor is written to @granted_power, which ++ * should've been allocated by the calling function. ++ */ ++static void divvy_up_power(u32 *req_power, u32 *max_power, int num_actors, ++ u32 total_req_power, u32 power_range, ++ u32 *granted_power, u32 *extra_actor_power) ++{ ++ u32 extra_power, capped_extra_power; ++ int i; ++ ++ /* ++ * Prevent division by 0 if none of the actors request power. ++ */ ++ if (!total_req_power) ++ total_req_power = 1; ++ ++ capped_extra_power = 0; ++ extra_power = 0; ++ for (i = 0; i < num_actors; i++) { ++ u64 req_range = req_power[i] * power_range; ++ ++ granted_power[i] = DIV_ROUND_CLOSEST_ULL(req_range, ++ total_req_power); ++ ++ if (granted_power[i] > max_power[i]) { ++ extra_power += granted_power[i] - max_power[i]; ++ granted_power[i] = max_power[i]; ++ } ++ ++ extra_actor_power[i] = max_power[i] - granted_power[i]; ++ capped_extra_power += extra_actor_power[i]; ++ } ++ ++ if (!extra_power) ++ return; ++ ++ /* ++ * Re-divvy the reclaimed extra among actors based on ++ * how far they are from the max ++ */ ++ extra_power = min(extra_power, capped_extra_power); ++ if (capped_extra_power > 0) ++ for (i = 0; i < num_actors; i++) ++ granted_power[i] += (extra_actor_power[i] * ++ extra_power) / capped_extra_power; ++} ++ ++static int allocate_power(struct thermal_zone_device *tz, ++ unsigned long current_temp, ++ unsigned long control_temp) ++{ ++ struct thermal_instance *instance; ++ struct power_allocator_params *params = tz->governor_data; ++ u32 *req_power, *max_power, *granted_power, *extra_actor_power; ++ u32 *weighted_req_power; ++ u32 total_req_power, max_allocatable_power, total_weighted_req_power; ++ u32 total_granted_power, power_range; ++ int i, num_actors, total_weight, ret = 0; ++ int trip_max_desired_temperature = params->trip_max_desired_temperature; ++ ++ mutex_lock(&tz->lock); ++ ++ num_actors = 0; ++ total_weight = 0; ++ list_for_each_entry(instance, &tz->thermal_instances, tz_node) { ++ if ((instance->trip == trip_max_desired_temperature) && ++ cdev_is_power_actor(instance->cdev)) { ++ num_actors++; ++ total_weight += instance->weight; ++ } ++ } ++ ++ /* ++ * We need to allocate five arrays of the same size: ++ * req_power, max_power, granted_power, extra_actor_power and ++ * weighted_req_power. They are going to be needed until this ++ * function returns. Allocate them all in one go to simplify ++ * the allocation and deallocation logic. ++ */ ++ BUILD_BUG_ON(sizeof(*req_power) != sizeof(*max_power)); ++ BUILD_BUG_ON(sizeof(*req_power) != sizeof(*granted_power)); ++ BUILD_BUG_ON(sizeof(*req_power) != sizeof(*extra_actor_power)); ++ BUILD_BUG_ON(sizeof(*req_power) != sizeof(*weighted_req_power)); ++ req_power = kcalloc(num_actors * 5, sizeof(*req_power), GFP_KERNEL); ++ if (!req_power) { ++ ret = -ENOMEM; ++ goto unlock; ++ } ++ ++ max_power = &req_power[num_actors]; ++ granted_power = &req_power[2 * num_actors]; ++ extra_actor_power = &req_power[3 * num_actors]; ++ weighted_req_power = &req_power[4 * num_actors]; ++ ++ i = 0; ++ total_weighted_req_power = 0; ++ total_req_power = 0; ++ max_allocatable_power = 0; ++ ++ list_for_each_entry(instance, &tz->thermal_instances, tz_node) { ++ int weight; ++ struct thermal_cooling_device *cdev = instance->cdev; ++ ++ if (instance->trip != trip_max_desired_temperature) ++ continue; ++ ++ if (!cdev_is_power_actor(cdev)) ++ continue; ++ ++ if (cdev->ops->get_requested_power(cdev, tz, &req_power[i])) ++ continue; ++ ++ if (!total_weight) ++ weight = 1 << FRAC_BITS; ++ else ++ weight = instance->weight; ++ ++ weighted_req_power[i] = frac_to_int(weight * req_power[i]); ++ ++ if (power_actor_get_max_power(cdev, tz, &max_power[i])) ++ continue; ++ ++ total_req_power += req_power[i]; ++ max_allocatable_power += max_power[i]; ++ total_weighted_req_power += weighted_req_power[i]; ++ ++ i++; ++ } ++ ++ power_range = pid_controller(tz, current_temp, control_temp, ++ max_allocatable_power); ++ ++ divvy_up_power(weighted_req_power, max_power, num_actors, ++ total_weighted_req_power, power_range, granted_power, ++ extra_actor_power); ++ ++ total_granted_power = 0; ++ i = 0; ++ list_for_each_entry(instance, &tz->thermal_instances, tz_node) { ++ if (instance->trip != trip_max_desired_temperature) ++ continue; ++ ++ if (!cdev_is_power_actor(instance->cdev)) ++ continue; ++ ++ power_actor_set_power(instance->cdev, instance, ++ granted_power[i]); ++ total_granted_power += granted_power[i]; ++ ++ i++; ++ } ++ ++ trace_thermal_power_allocator(tz, req_power, total_req_power, ++ granted_power, total_granted_power, ++ num_actors, power_range, ++ max_allocatable_power, current_temp, ++ (s32)control_temp - (s32)current_temp); ++ ++ kfree(req_power); ++unlock: ++ mutex_unlock(&tz->lock); ++ ++ return ret; ++} ++ ++static int get_governor_trips(struct thermal_zone_device *tz, ++ struct power_allocator_params *params) ++{ ++ int i, ret, last_passive; ++ bool found_first_passive; ++ ++ found_first_passive = false; ++ last_passive = -1; ++ ret = -EINVAL; ++ ++ for (i = 0; i < tz->trips; i++) { ++ enum thermal_trip_type type; ++ ++ ret = tz->ops->get_trip_type(tz, i, &type); ++ if (ret) ++ return ret; ++ ++ if (!found_first_passive) { ++ if (type == THERMAL_TRIP_PASSIVE) { ++ params->trip_switch_on = i; ++ found_first_passive = true; ++ } ++ } else if (type == THERMAL_TRIP_PASSIVE) { ++ last_passive = i; ++ } else { ++ break; ++ } ++ } ++ ++ if (last_passive != -1) { ++ params->trip_max_desired_temperature = last_passive; ++ ret = 0; ++ } else { ++ ret = -EINVAL; ++ } ++ ++ return ret; ++} ++ ++static void reset_pid_controller(struct power_allocator_params *params) ++{ ++ params->err_integral = 0; ++ params->prev_err = 0; ++} ++ ++static void allow_maximum_power(struct thermal_zone_device *tz) ++{ ++ struct thermal_instance *instance; ++ struct power_allocator_params *params = tz->governor_data; ++ ++ list_for_each_entry(instance, &tz->thermal_instances, tz_node) { ++ if ((instance->trip != params->trip_max_desired_temperature) || ++ (!cdev_is_power_actor(instance->cdev))) ++ continue; ++ ++ instance->target = 0; ++ instance->cdev->updated = false; ++ thermal_cdev_update(instance->cdev); ++ } ++} ++ ++/** ++ * power_allocator_bind() - bind the power_allocator governor to a thermal zone ++ * @tz: thermal zone to bind it to ++ * ++ * Check that the thermal zone is valid for this governor, that is, it ++ * has two thermal trips. If so, initialize the PID controller ++ * parameters and bind it to the thermal zone. ++ * ++ * Return: 0 on success, -EINVAL if the trips were invalid or -ENOMEM ++ * if we ran out of memory. ++ */ ++static int power_allocator_bind(struct thermal_zone_device *tz) ++{ ++ int ret; ++ struct power_allocator_params *params; ++ unsigned long switch_on_temp, control_temp; ++ u32 temperature_threshold; ++ ++ if (!tz->tzp || !tz->tzp->sustainable_power) { ++ dev_err(&tz->device, ++ "power_allocator: missing sustainable_power\n"); ++ return -EINVAL; ++ } ++ ++ params = kzalloc(sizeof(*params), GFP_KERNEL); ++ if (!params) ++ return -ENOMEM; ++ ++ ret = get_governor_trips(tz, params); ++ if (ret) { ++ dev_err(&tz->device, ++ "thermal zone %s has wrong trip setup for power allocator\n", ++ tz->type); ++ goto free; ++ } ++ ++ ret = tz->ops->get_trip_temp(tz, params->trip_switch_on, ++ &switch_on_temp); ++ if (ret) ++ goto free; ++ ++ ret = tz->ops->get_trip_temp(tz, params->trip_max_desired_temperature, ++ &control_temp); ++ if (ret) ++ goto free; ++ ++ temperature_threshold = control_temp - switch_on_temp; ++ ++ tz->tzp->k_po = tz->tzp->k_po ?: ++ int_to_frac(tz->tzp->sustainable_power) / temperature_threshold; ++ tz->tzp->k_pu = tz->tzp->k_pu ?: ++ int_to_frac(2 * tz->tzp->sustainable_power) / ++ temperature_threshold; ++ tz->tzp->k_i = tz->tzp->k_i ?: int_to_frac(10) / 1000; ++ /* ++ * The default for k_d and integral_cutoff is 0, so we can ++ * leave them as they are. ++ */ ++ ++ reset_pid_controller(params); ++ ++ tz->governor_data = params; ++ ++ return 0; ++ ++free: ++ kfree(params); ++ return ret; ++} ++ ++static void power_allocator_unbind(struct thermal_zone_device *tz) ++{ ++ dev_dbg(&tz->device, "Unbinding from thermal zone %d\n", tz->id); ++ kfree(tz->governor_data); ++ tz->governor_data = NULL; ++} ++ ++static int power_allocator_throttle(struct thermal_zone_device *tz, int trip) ++{ ++ int ret; ++ unsigned long switch_on_temp, control_temp, current_temp; ++ struct power_allocator_params *params = tz->governor_data; ++ ++ /* ++ * We get called for every trip point but we only need to do ++ * our calculations once ++ */ ++ if (trip != params->trip_max_desired_temperature) ++ return 0; ++ ++ ret = thermal_zone_get_temp(tz, ¤t_temp); ++ if (ret) { ++ dev_warn(&tz->device, "Failed to get temperature: %d\n", ret); ++ return ret; ++ } ++ ++ ret = tz->ops->get_trip_temp(tz, params->trip_switch_on, ++ &switch_on_temp); ++ if (ret) { ++ dev_warn(&tz->device, ++ "Failed to get switch on temperature: %d\n", ret); ++ return ret; ++ } ++ ++ if (current_temp < switch_on_temp) { ++ tz->passive = 0; ++ reset_pid_controller(params); ++ allow_maximum_power(tz); ++ return 0; ++ } ++ ++ tz->passive = 1; ++ ++ ret = tz->ops->get_trip_temp(tz, params->trip_max_desired_temperature, ++ &control_temp); ++ if (ret) { ++ dev_warn(&tz->device, ++ "Failed to get the maximum desired temperature: %d\n", ++ ret); ++ return ret; ++ } ++ ++ return allocate_power(tz, current_temp, control_temp); ++} ++ ++static struct thermal_governor thermal_gov_power_allocator = { ++ .name = "power_allocator", ++ .bind_to_tz = power_allocator_bind, ++ .unbind_from_tz = power_allocator_unbind, ++ .throttle = power_allocator_throttle, ++}; ++ ++int thermal_gov_power_allocator_register(void) ++{ ++ return thermal_register_governor(&thermal_gov_power_allocator); ++} ++ ++void thermal_gov_power_allocator_unregister(void) ++{ ++ thermal_unregister_governor(&thermal_gov_power_allocator); ++} +diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig +index f760389..c43306e 100644 +--- a/drivers/thermal/samsung/Kconfig ++++ b/drivers/thermal/samsung/Kconfig +@@ -1,6 +1,6 @@ + config EXYNOS_THERMAL + tristate "Exynos thermal management unit driver" +- depends on ARCH_HAS_BANDGAP && OF ++ depends on OF + help + If you say yes here you get support for the TMU (Thermal Management + Unit) driver for SAMSUNG EXYNOS series of SoCs. This driver initialises +diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c +index b6be572..7c97db1 100644 +--- a/drivers/thermal/samsung/exynos_thermal_common.c ++++ b/drivers/thermal/samsung/exynos_thermal_common.c +@@ -163,7 +163,7 @@ static int exynos_bind(struct thermal_zone_device *thermal, + case MONITOR_ZONE: + case WARN_ZONE: + if (thermal_zone_bind_cooling_device(thermal, i, cdev, +- level, 0)) { ++ level, 0, THERMAL_WEIGHT_DEFAULT)) { + dev_err(data->dev, + "error unbinding cdev inst=%d\n", i); + ret = -EINVAL; +@@ -371,9 +371,11 @@ int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) + th_zone->cool_dev[th_zone->cool_dev_size] = + cpufreq_cooling_register(&mask_val); + if (IS_ERR(th_zone->cool_dev[th_zone->cool_dev_size])) { +- dev_err(sensor_conf->dev, +- "Failed to register cpufreq cooling device\n"); +- ret = -EINVAL; ++ ret = PTR_ERR(th_zone->cool_dev[th_zone->cool_dev_size]); ++ if (ret != -EPROBE_DEFER) ++ dev_err(sensor_conf->dev, ++ "Failed to register cpufreq cooling device: %d\n", ++ ret); + goto err_unregister; + } + th_zone->cool_dev_size++; +diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c +index 49c0924..2afca9b 100644 +--- a/drivers/thermal/samsung/exynos_tmu.c ++++ b/drivers/thermal/samsung/exynos_tmu.c +@@ -683,7 +683,10 @@ static int exynos_tmu_probe(struct platform_device *pdev) + /* Register the sensor with thermal management interface */ + ret = exynos_register_thermal(sensor_conf); + if (ret) { +- dev_err(&pdev->dev, "Failed to register thermal interface\n"); ++ if (ret != -EPROBE_DEFER) ++ dev_err(&pdev->dev, ++ "Failed to register thermal interface: %d\n", ++ ret); + goto err_clk; + } + data->reg_conf = sensor_conf; +diff --git a/drivers/thermal/tegra_soctherm.c b/drivers/thermal/tegra_soctherm.c +new file mode 100644 +index 0000000..9197fc0 +--- /dev/null ++++ b/drivers/thermal/tegra_soctherm.c +@@ -0,0 +1,476 @@ ++/* ++ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. ++ * ++ * Author: ++ * Mikko Perttunen ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define SENSOR_CONFIG0 0 ++#define SENSOR_CONFIG0_STOP BIT(0) ++#define SENSOR_CONFIG0_TALL_SHIFT 8 ++#define SENSOR_CONFIG0_TCALC_OVER BIT(4) ++#define SENSOR_CONFIG0_OVER BIT(3) ++#define SENSOR_CONFIG0_CPTR_OVER BIT(2) ++ ++#define SENSOR_CONFIG1 4 ++#define SENSOR_CONFIG1_TSAMPLE_SHIFT 0 ++#define SENSOR_CONFIG1_TIDDQ_EN_SHIFT 15 ++#define SENSOR_CONFIG1_TEN_COUNT_SHIFT 24 ++#define SENSOR_CONFIG1_TEMP_ENABLE BIT(31) ++ ++#define SENSOR_CONFIG2 8 ++#define SENSOR_CONFIG2_THERMA_SHIFT 16 ++#define SENSOR_CONFIG2_THERMB_SHIFT 0 ++ ++#define SENSOR_PDIV 0x1c0 ++#define SENSOR_PDIV_T124 0x8888 ++#define SENSOR_HOTSPOT_OFF 0x1c4 ++#define SENSOR_HOTSPOT_OFF_T124 0x00060600 ++#define SENSOR_TEMP1 0x1c8 ++#define SENSOR_TEMP2 0x1cc ++ ++#define SENSOR_TEMP_MASK 0xffff ++#define READBACK_VALUE_MASK 0xff00 ++#define READBACK_VALUE_SHIFT 8 ++#define READBACK_ADD_HALF BIT(7) ++#define READBACK_NEGATE BIT(1) ++ ++#define FUSE_TSENSOR8_CALIB 0x180 ++#define FUSE_SPARE_REALIGNMENT_REG_0 0x1fc ++ ++#define FUSE_TSENSOR_CALIB_CP_TS_BASE_MASK 0x1fff ++#define FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK (0x1fff << 13) ++#define FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT 13 ++ ++#define FUSE_TSENSOR8_CALIB_CP_TS_BASE_MASK 0x3ff ++#define FUSE_TSENSOR8_CALIB_FT_TS_BASE_MASK (0x7ff << 10) ++#define FUSE_TSENSOR8_CALIB_FT_TS_BASE_SHIFT 10 ++ ++#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_CP_MASK 0x3f ++#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_MASK (0x1f << 21) ++#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_SHIFT 21 ++ ++#define NOMINAL_CALIB_FT_T124 105 ++#define NOMINAL_CALIB_CP_T124 25 ++ ++struct tegra_tsensor_configuration { ++ u32 tall, tsample, tiddq_en, ten_count, pdiv, tsample_ate, pdiv_ate; ++}; ++ ++struct tegra_tsensor { ++ const struct tegra_tsensor_configuration *config; ++ u32 base, calib_fuse_offset; ++ /* Correction values used to modify values read from calibration fuses */ ++ s32 fuse_corr_alpha, fuse_corr_beta; ++}; ++ ++struct tegra_thermctl_zone { ++ void __iomem *reg; ++ unsigned int shift; ++}; ++ ++static const struct tegra_tsensor_configuration t124_tsensor_config = { ++ .tall = 16300, ++ .tsample = 120, ++ .tiddq_en = 1, ++ .ten_count = 1, ++ .pdiv = 8, ++ .tsample_ate = 480, ++ .pdiv_ate = 8 ++}; ++ ++static const struct tegra_tsensor t124_tsensors[] = { ++ { ++ .config = &t124_tsensor_config, ++ .base = 0xc0, ++ .calib_fuse_offset = 0x098, ++ .fuse_corr_alpha = 1135400, ++ .fuse_corr_beta = -6266900, ++ }, ++ { ++ .config = &t124_tsensor_config, ++ .base = 0xe0, ++ .calib_fuse_offset = 0x084, ++ .fuse_corr_alpha = 1122220, ++ .fuse_corr_beta = -5700700, ++ }, ++ { ++ .config = &t124_tsensor_config, ++ .base = 0x100, ++ .calib_fuse_offset = 0x088, ++ .fuse_corr_alpha = 1127000, ++ .fuse_corr_beta = -6768200, ++ }, ++ { ++ .config = &t124_tsensor_config, ++ .base = 0x120, ++ .calib_fuse_offset = 0x12c, ++ .fuse_corr_alpha = 1110900, ++ .fuse_corr_beta = -6232000, ++ }, ++ { ++ .config = &t124_tsensor_config, ++ .base = 0x140, ++ .calib_fuse_offset = 0x158, ++ .fuse_corr_alpha = 1122300, ++ .fuse_corr_beta = -5936400, ++ }, ++ { ++ .config = &t124_tsensor_config, ++ .base = 0x160, ++ .calib_fuse_offset = 0x15c, ++ .fuse_corr_alpha = 1145700, ++ .fuse_corr_beta = -7124600, ++ }, ++ { ++ .config = &t124_tsensor_config, ++ .base = 0x180, ++ .calib_fuse_offset = 0x154, ++ .fuse_corr_alpha = 1120100, ++ .fuse_corr_beta = -6000500, ++ }, ++ { ++ .config = &t124_tsensor_config, ++ .base = 0x1a0, ++ .calib_fuse_offset = 0x160, ++ .fuse_corr_alpha = 1106500, ++ .fuse_corr_beta = -6729300, ++ }, ++}; ++ ++struct tegra_soctherm { ++ struct reset_control *reset; ++ struct clk *clock_tsensor; ++ struct clk *clock_soctherm; ++ void __iomem *regs; ++ ++ struct thermal_zone_device *thermctl_tzs[4]; ++}; ++ ++struct tsensor_shared_calibration { ++ u32 base_cp, base_ft; ++ u32 actual_temp_cp, actual_temp_ft; ++}; ++ ++static int calculate_shared_calibration(struct tsensor_shared_calibration *r) ++{ ++ u32 val, shifted_cp, shifted_ft; ++ int err; ++ ++ err = tegra_fuse_readl(FUSE_TSENSOR8_CALIB, &val); ++ if (err) ++ return err; ++ r->base_cp = val & FUSE_TSENSOR8_CALIB_CP_TS_BASE_MASK; ++ r->base_ft = (val & FUSE_TSENSOR8_CALIB_FT_TS_BASE_MASK) ++ >> FUSE_TSENSOR8_CALIB_FT_TS_BASE_SHIFT; ++ val = ((val & FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_MASK) ++ >> FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_SHIFT); ++ shifted_ft = sign_extend32(val, 4); ++ ++ err = tegra_fuse_readl(FUSE_SPARE_REALIGNMENT_REG_0, &val); ++ if (err) ++ return err; ++ shifted_cp = sign_extend32(val, 5); ++ ++ r->actual_temp_cp = 2 * NOMINAL_CALIB_CP_T124 + shifted_cp; ++ r->actual_temp_ft = 2 * NOMINAL_CALIB_FT_T124 + shifted_ft; ++ ++ return 0; ++} ++ ++static s64 div64_s64_precise(s64 a, s64 b) ++{ ++ s64 r, al; ++ ++ /* Scale up for increased precision division */ ++ al = a << 16; ++ ++ r = div64_s64(al * 2 + 1, 2 * b); ++ return r >> 16; ++} ++ ++static int ++calculate_tsensor_calibration(const struct tegra_tsensor *sensor, ++ const struct tsensor_shared_calibration *shared, ++ u32 *calib) ++{ ++ u32 val; ++ s32 actual_tsensor_ft, actual_tsensor_cp, delta_sens, delta_temp, ++ mult, div; ++ s16 therma, thermb; ++ s64 tmp; ++ int err; ++ ++ err = tegra_fuse_readl(sensor->calib_fuse_offset, &val); ++ if (err) ++ return err; ++ ++ actual_tsensor_cp = (shared->base_cp * 64) + sign_extend32(val, 12); ++ val = (val & FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK) ++ >> FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT; ++ actual_tsensor_ft = (shared->base_ft * 32) + sign_extend32(val, 12); ++ ++ delta_sens = actual_tsensor_ft - actual_tsensor_cp; ++ delta_temp = shared->actual_temp_ft - shared->actual_temp_cp; ++ ++ mult = sensor->config->pdiv * sensor->config->tsample_ate; ++ div = sensor->config->tsample * sensor->config->pdiv_ate; ++ ++ therma = div64_s64_precise((s64) delta_temp * (1LL << 13) * mult, ++ (s64) delta_sens * div); ++ ++ tmp = (s64)actual_tsensor_ft * shared->actual_temp_cp - ++ (s64)actual_tsensor_cp * shared->actual_temp_ft; ++ thermb = div64_s64_precise(tmp, (s64)delta_sens); ++ ++ therma = div64_s64_precise((s64)therma * sensor->fuse_corr_alpha, ++ (s64)1000000LL); ++ thermb = div64_s64_precise((s64)thermb * sensor->fuse_corr_alpha + ++ sensor->fuse_corr_beta, (s64)1000000LL); ++ ++ *calib = ((u16)therma << SENSOR_CONFIG2_THERMA_SHIFT) | ++ ((u16)thermb << SENSOR_CONFIG2_THERMB_SHIFT); ++ ++ return 0; ++} ++ ++static int enable_tsensor(struct tegra_soctherm *tegra, ++ const struct tegra_tsensor *sensor, ++ const struct tsensor_shared_calibration *shared) ++{ ++ void __iomem *base = tegra->regs + sensor->base; ++ unsigned int val; ++ u32 calib; ++ int err; ++ ++ err = calculate_tsensor_calibration(sensor, shared, &calib); ++ if (err) ++ return err; ++ ++ val = sensor->config->tall << SENSOR_CONFIG0_TALL_SHIFT; ++ writel(val, base + SENSOR_CONFIG0); ++ ++ val = (sensor->config->tsample - 1) << SENSOR_CONFIG1_TSAMPLE_SHIFT; ++ val |= sensor->config->tiddq_en << SENSOR_CONFIG1_TIDDQ_EN_SHIFT; ++ val |= sensor->config->ten_count << SENSOR_CONFIG1_TEN_COUNT_SHIFT; ++ val |= SENSOR_CONFIG1_TEMP_ENABLE; ++ writel(val, base + SENSOR_CONFIG1); ++ ++ writel(calib, base + SENSOR_CONFIG2); ++ ++ return 0; ++} ++ ++/* ++ * Translate from soctherm readback format to millicelsius. ++ * The soctherm readback format in bits is as follows: ++ * TTTTTTTT H______N ++ * where T's contain the temperature in Celsius, ++ * H denotes an addition of 0.5 Celsius and N denotes negation ++ * of the final value. ++ */ ++static long translate_temp(u16 val) ++{ ++ long t; ++ ++ t = ((val & READBACK_VALUE_MASK) >> READBACK_VALUE_SHIFT) * 1000; ++ if (val & READBACK_ADD_HALF) ++ t += 500; ++ if (val & READBACK_NEGATE) ++ t *= -1; ++ ++ return t; ++} ++ ++static int tegra_thermctl_get_temp(void *data, long *out_temp) ++{ ++ struct tegra_thermctl_zone *zone = data; ++ u32 val; ++ ++ val = (readl(zone->reg) >> zone->shift) & SENSOR_TEMP_MASK; ++ *out_temp = translate_temp(val); ++ ++ return 0; ++} ++ ++static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = { ++ .get_temp = tegra_thermctl_get_temp, ++}; ++ ++static const struct of_device_id tegra_soctherm_of_match[] = { ++ { .compatible = "nvidia,tegra124-soctherm" }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, tegra_soctherm_of_match); ++ ++struct thermctl_zone_desc { ++ unsigned int offset; ++ unsigned int shift; ++}; ++ ++static const struct thermctl_zone_desc t124_thermctl_temp_zones[] = { ++ { SENSOR_TEMP1, 16 }, ++ { SENSOR_TEMP2, 16 }, ++ { SENSOR_TEMP1, 0 }, ++ { SENSOR_TEMP2, 0 } ++}; ++ ++static int tegra_soctherm_probe(struct platform_device *pdev) ++{ ++ struct tegra_soctherm *tegra; ++ struct thermal_zone_device *tz; ++ struct tsensor_shared_calibration shared_calib; ++ struct resource *res; ++ unsigned int i; ++ int err; ++ ++ const struct tegra_tsensor *tsensors = t124_tsensors; ++ ++ tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL); ++ if (!tegra) ++ return -ENOMEM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ tegra->regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(tegra->regs)) ++ return PTR_ERR(tegra->regs); ++ ++ tegra->reset = devm_reset_control_get(&pdev->dev, "soctherm"); ++ if (IS_ERR(tegra->reset)) { ++ dev_err(&pdev->dev, "can't get soctherm reset\n"); ++ return PTR_ERR(tegra->reset); ++ } ++ ++ tegra->clock_tsensor = devm_clk_get(&pdev->dev, "tsensor"); ++ if (IS_ERR(tegra->clock_tsensor)) { ++ dev_err(&pdev->dev, "can't get tsensor clock\n"); ++ return PTR_ERR(tegra->clock_tsensor); ++ } ++ ++ tegra->clock_soctherm = devm_clk_get(&pdev->dev, "soctherm"); ++ if (IS_ERR(tegra->clock_soctherm)) { ++ dev_err(&pdev->dev, "can't get soctherm clock\n"); ++ return PTR_ERR(tegra->clock_soctherm); ++ } ++ ++ reset_control_assert(tegra->reset); ++ ++ err = clk_prepare_enable(tegra->clock_soctherm); ++ if (err) ++ return err; ++ ++ err = clk_prepare_enable(tegra->clock_tsensor); ++ if (err) { ++ clk_disable_unprepare(tegra->clock_soctherm); ++ return err; ++ } ++ ++ reset_control_deassert(tegra->reset); ++ ++ /* Initialize raw sensors */ ++ ++ err = calculate_shared_calibration(&shared_calib); ++ if (err) ++ goto disable_clocks; ++ ++ for (i = 0; i < ARRAY_SIZE(t124_tsensors); ++i) { ++ err = enable_tsensor(tegra, tsensors + i, &shared_calib); ++ if (err) ++ goto disable_clocks; ++ } ++ ++ writel(SENSOR_PDIV_T124, tegra->regs + SENSOR_PDIV); ++ writel(SENSOR_HOTSPOT_OFF_T124, tegra->regs + SENSOR_HOTSPOT_OFF); ++ ++ /* Initialize thermctl sensors */ ++ ++ for (i = 0; i < ARRAY_SIZE(tegra->thermctl_tzs); ++i) { ++ struct tegra_thermctl_zone *zone = ++ devm_kzalloc(&pdev->dev, sizeof(*zone), GFP_KERNEL); ++ if (!zone) { ++ err = -ENOMEM; ++ goto unregister_tzs; ++ } ++ ++ zone->reg = tegra->regs + t124_thermctl_temp_zones[i].offset; ++ zone->shift = t124_thermctl_temp_zones[i].shift; ++ ++ tz = thermal_zone_of_sensor_register(&pdev->dev, i, zone, ++ &tegra_of_thermal_ops); ++ if (IS_ERR(tz)) { ++ err = PTR_ERR(tz); ++ dev_err(&pdev->dev, "failed to register sensor: %d\n", ++ err); ++ goto unregister_tzs; ++ } ++ ++ tegra->thermctl_tzs[i] = tz; ++ } ++ ++ return 0; ++ ++unregister_tzs: ++ while (i--) ++ thermal_zone_of_sensor_unregister(&pdev->dev, ++ tegra->thermctl_tzs[i]); ++ ++disable_clocks: ++ clk_disable_unprepare(tegra->clock_tsensor); ++ clk_disable_unprepare(tegra->clock_soctherm); ++ ++ return err; ++} ++ ++static int tegra_soctherm_remove(struct platform_device *pdev) ++{ ++ struct tegra_soctherm *tegra = platform_get_drvdata(pdev); ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(tegra->thermctl_tzs); ++i) { ++ thermal_zone_of_sensor_unregister(&pdev->dev, ++ tegra->thermctl_tzs[i]); ++ } ++ ++ clk_disable_unprepare(tegra->clock_tsensor); ++ clk_disable_unprepare(tegra->clock_soctherm); ++ ++ return 0; ++} ++ ++static struct platform_driver tegra_soctherm_driver = { ++ .probe = tegra_soctherm_probe, ++ .remove = tegra_soctherm_remove, ++ .driver = { ++ .name = "tegra-soctherm", ++ .of_match_table = tegra_soctherm_of_match, ++ }, ++}; ++module_platform_driver(tegra_soctherm_driver); ++ ++MODULE_AUTHOR("Mikko Perttunen "); ++MODULE_DESCRIPTION("NVIDIA Tegra SOCTHERM thermal management driver"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c +index 488e9bf..249b612 100644 +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -75,6 +75,58 @@ static struct thermal_governor *__find_governor(const char *name) + return NULL; + } + ++/** ++ * bind_previous_governor() - bind the previous governor of the thermal zone ++ * @tz: a valid pointer to a struct thermal_zone_device ++ * @failed_gov_name: the name of the governor that failed to register ++ * ++ * Register the previous governor of the thermal zone after a new ++ * governor has failed to be bound. ++ */ ++static void bind_previous_governor(struct thermal_zone_device *tz, ++ const char *failed_gov_name) ++{ ++ if (tz->governor && tz->governor->bind_to_tz) { ++ if (tz->governor->bind_to_tz(tz)) { ++ dev_err(&tz->device, ++ "governor %s failed to bind and the previous one (%s) failed to bind again, thermal zone %s has no governor\n", ++ failed_gov_name, tz->governor->name, tz->type); ++ tz->governor = NULL; ++ } ++ } ++} ++ ++/** ++ * thermal_set_governor() - Switch to another governor ++ * @tz: a valid pointer to a struct thermal_zone_device ++ * @new_gov: pointer to the new governor ++ * ++ * Change the governor of thermal zone @tz. ++ * ++ * Return: 0 on success, an error if the new governor's bind_to_tz() failed. ++ */ ++static int thermal_set_governor(struct thermal_zone_device *tz, ++ struct thermal_governor *new_gov) ++{ ++ int ret = 0; ++ ++ if (tz->governor && tz->governor->unbind_from_tz) ++ tz->governor->unbind_from_tz(tz); ++ ++ if (new_gov && new_gov->bind_to_tz) { ++ ret = new_gov->bind_to_tz(tz); ++ if (ret) { ++ bind_previous_governor(tz, new_gov->name); ++ ++ return ret; ++ } ++ } ++ ++ tz->governor = new_gov; ++ ++ return ret; ++} ++ + int thermal_register_governor(struct thermal_governor *governor) + { + int err; +@@ -107,8 +159,15 @@ int thermal_register_governor(struct thermal_governor *governor) + + name = pos->tzp->governor_name; + +- if (!strncasecmp(name, governor->name, THERMAL_NAME_LENGTH)) +- pos->governor = governor; ++ if (!strncasecmp(name, governor->name, THERMAL_NAME_LENGTH)) { ++ int ret; ++ ++ ret = thermal_set_governor(pos, governor); ++ if (ret) ++ dev_err(&pos->device, ++ "Failed to set governor %s for thermal zone %s: %d\n", ++ governor->name, pos->type, ret); ++ } + } + + mutex_unlock(&thermal_list_lock); +@@ -134,7 +193,7 @@ void thermal_unregister_governor(struct thermal_governor *governor) + list_for_each_entry(pos, &thermal_tz_list, node) { + if (!strncasecmp(pos->governor->name, governor->name, + THERMAL_NAME_LENGTH)) +- pos->governor = NULL; ++ thermal_set_governor(pos, NULL); + } + + mutex_unlock(&thermal_list_lock); +@@ -218,7 +277,8 @@ static void print_bind_err_msg(struct thermal_zone_device *tz, + + static void __bind(struct thermal_zone_device *tz, int mask, + struct thermal_cooling_device *cdev, +- unsigned long *limits) ++ unsigned long *limits, ++ unsigned int weight) + { + int i, ret; + +@@ -233,7 +293,8 @@ static void __bind(struct thermal_zone_device *tz, int mask, + upper = limits[i * 2 + 1]; + } + ret = thermal_zone_bind_cooling_device(tz, i, cdev, +- upper, lower); ++ upper, lower, ++ weight); + if (ret) + print_bind_err_msg(tz, cdev, ret); + } +@@ -280,7 +341,8 @@ static void bind_cdev(struct thermal_cooling_device *cdev) + continue; + tzp->tbp[i].cdev = cdev; + __bind(pos, tzp->tbp[i].trip_mask, cdev, +- tzp->tbp[i].binding_limits); ++ tzp->tbp[i].binding_limits, ++ tzp->tbp[i].weight); + } + } + +@@ -319,7 +381,8 @@ static void bind_tz(struct thermal_zone_device *tz) + continue; + tzp->tbp[i].cdev = pos; + __bind(tz, tzp->tbp[i].trip_mask, pos, +- tzp->tbp[i].binding_limits); ++ tzp->tbp[i].binding_limits, ++ tzp->tbp[i].weight); + } + } + exit: +@@ -368,7 +431,7 @@ static void handle_critical_trips(struct thermal_zone_device *tz, + tz->ops->get_trip_temp(tz, trip, &trip_temp); + + /* If we have not crossed the trip_temp, we do not care. */ +- if (tz->temperature < trip_temp) ++ if (trip_temp <= 0 || tz->temperature < trip_temp) + return; + + trace_thermal_zone_trip(tz, trip, trip_type); +@@ -711,7 +774,8 @@ passive_store(struct device *dev, struct device_attribute *attr, + thermal_zone_bind_cooling_device(tz, + THERMAL_TRIPS_NONE, cdev, + THERMAL_NO_LIMIT, +- THERMAL_NO_LIMIT); ++ THERMAL_NO_LIMIT, ++ THERMAL_WEIGHT_DEFAULT); + } + mutex_unlock(&thermal_list_lock); + if (!tz->passive_delay) +@@ -757,15 +821,18 @@ policy_store(struct device *dev, struct device_attribute *attr, + snprintf(name, sizeof(name), "%s", buf); + + mutex_lock(&thermal_governor_lock); ++ mutex_lock(&tz->lock); + + gov = __find_governor(strim(name)); + if (!gov) + goto exit; + +- tz->governor = gov; +- ret = count; ++ ret = thermal_set_governor(tz, gov); ++ if (!ret) ++ ret = count; + + exit: ++ mutex_unlock(&tz->lock); + mutex_unlock(&thermal_governor_lock); + return ret; + } +@@ -806,6 +873,158 @@ emul_temp_store(struct device *dev, struct device_attribute *attr, + static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store); + #endif/*CONFIG_THERMAL_EMULATION*/ + ++static ssize_t ++sustainable_power_show(struct device *dev, struct device_attribute *devattr, ++ char *buf) ++{ ++ struct thermal_zone_device *tz = to_thermal_zone(dev); ++ ++ if (tz->tzp) ++ return sprintf(buf, "%u\n", tz->tzp->sustainable_power); ++ else ++ return -EIO; ++} ++ ++static ssize_t ++sustainable_power_store(struct device *dev, struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct thermal_zone_device *tz = to_thermal_zone(dev); ++ u32 sustainable_power; ++ ++ if (!tz->tzp) ++ return -EIO; ++ ++ if (kstrtou32(buf, 10, &sustainable_power)) ++ return -EINVAL; ++ ++ tz->tzp->sustainable_power = sustainable_power; ++ ++ return count; ++} ++static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show, ++ sustainable_power_store); ++ ++#define create_s32_tzp_attr(name) \ ++ static ssize_t \ ++ name##_show(struct device *dev, struct device_attribute *devattr, \ ++ char *buf) \ ++ { \ ++ struct thermal_zone_device *tz = to_thermal_zone(dev); \ ++ \ ++ if (tz->tzp) \ ++ return sprintf(buf, "%u\n", tz->tzp->name); \ ++ else \ ++ return -EIO; \ ++ } \ ++ \ ++ static ssize_t \ ++ name##_store(struct device *dev, struct device_attribute *devattr, \ ++ const char *buf, size_t count) \ ++ { \ ++ struct thermal_zone_device *tz = to_thermal_zone(dev); \ ++ s32 value; \ ++ \ ++ if (!tz->tzp) \ ++ return -EIO; \ ++ \ ++ if (kstrtos32(buf, 10, &value)) \ ++ return -EINVAL; \ ++ \ ++ tz->tzp->name = value; \ ++ \ ++ return count; \ ++ } \ ++ static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, name##_show, name##_store) ++ ++create_s32_tzp_attr(k_po); ++create_s32_tzp_attr(k_pu); ++create_s32_tzp_attr(k_i); ++create_s32_tzp_attr(k_d); ++create_s32_tzp_attr(integral_cutoff); ++create_s32_tzp_attr(slope); ++create_s32_tzp_attr(offset); ++#undef create_s32_tzp_attr ++ ++static struct device_attribute *dev_tzp_attrs[] = { ++ &dev_attr_sustainable_power, ++ &dev_attr_k_po, ++ &dev_attr_k_pu, ++ &dev_attr_k_i, ++ &dev_attr_k_d, ++ &dev_attr_integral_cutoff, ++ &dev_attr_slope, ++ &dev_attr_offset, ++}; ++ ++static int create_tzp_attrs(struct device *dev) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(dev_tzp_attrs); i++) { ++ int ret; ++ struct device_attribute *dev_attr = dev_tzp_attrs[i]; ++ ++ ret = device_create_file(dev, dev_attr); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/** ++ * power_actor_get_max_power() - get the maximum power that a cdev can consume ++ * @cdev: pointer to &thermal_cooling_device ++ * @tz: a valid thermal zone device pointer ++ * @max_power: pointer in which to store the maximum power ++ * ++ * Calculate the maximum power consumption in milliwats that the ++ * cooling device can currently consume and store it in @max_power. ++ * ++ * Return: 0 on success, -EINVAL if @cdev doesn't support the ++ * power_actor API or -E* on other error. ++ */ ++int power_actor_get_max_power(struct thermal_cooling_device *cdev, ++ struct thermal_zone_device *tz, u32 *max_power) ++{ ++ if (!cdev_is_power_actor(cdev)) ++ return -EINVAL; ++ ++ return cdev->ops->state2power(cdev, tz, 0, max_power); ++} ++ ++/** ++ * power_actor_set_power() - limit the maximum power that a cooling device can consume ++ * @cdev: pointer to &thermal_cooling_device ++ * @instance: thermal instance to update ++ * @power: the power in milliwatts ++ * ++ * Set the cooling device to consume at most @power milliwatts. ++ * ++ * Return: 0 on success, -EINVAL if the cooling device does not ++ * implement the power actor API or -E* for other failures. ++ */ ++int power_actor_set_power(struct thermal_cooling_device *cdev, ++ struct thermal_instance *instance, u32 power) ++{ ++ unsigned long state; ++ int ret; ++ ++ if (!cdev_is_power_actor(cdev)) ++ return -EINVAL; ++ ++ ret = cdev->ops->power2state(cdev, instance->tz, power, &state); ++ if (ret) ++ return ret; ++ ++ instance->target = state; ++ cdev->updated = false; ++ thermal_cdev_update(cdev); ++ ++ return 0; ++} ++ + static DEVICE_ATTR(type, 0444, type_show, NULL); + static DEVICE_ATTR(temp, 0444, temp_show, NULL); + static DEVICE_ATTR(mode, 0644, mode_show, mode_store); +@@ -897,6 +1116,50 @@ thermal_cooling_device_trip_point_show(struct device *dev, + return sprintf(buf, "%d\n", instance->trip); + } + ++static struct attribute *cooling_device_attrs[] = { ++ &dev_attr_cdev_type.attr, ++ &dev_attr_max_state.attr, ++ &dev_attr_cur_state.attr, ++ NULL, ++}; ++ ++static const struct attribute_group cooling_device_attr_group = { ++ .attrs = cooling_device_attrs, ++}; ++ ++static const struct attribute_group *cooling_device_attr_groups[] = { ++ &cooling_device_attr_group, ++ NULL, ++}; ++ ++static ssize_t ++thermal_cooling_device_weight_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct thermal_instance *instance; ++ ++ instance = container_of(attr, struct thermal_instance, weight_attr); ++ ++ return sprintf(buf, "%d\n", instance->weight); ++} ++ ++static ssize_t ++thermal_cooling_device_weight_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct thermal_instance *instance; ++ int ret, weight; ++ ++ ret = kstrtoint(buf, 0, &weight); ++ if (ret) ++ return ret; ++ ++ instance = container_of(attr, struct thermal_instance, weight_attr); ++ instance->weight = weight; ++ ++ return count; ++} + /* Device management */ + + /** +@@ -911,6 +1174,9 @@ thermal_cooling_device_trip_point_show(struct device *dev, + * @lower: the Minimum cooling state can be used for this trip point. + * THERMAL_NO_LIMIT means no lower limit, + * and the cooling device can be in cooling state 0. ++ * @weight: The weight of the cooling device to be bound to the ++ * thermal zone. Use THERMAL_WEIGHT_DEFAULT for the ++ * default value + * + * This interface function bind a thermal cooling device to the certain trip + * point of a thermal zone device. +@@ -921,7 +1187,8 @@ thermal_cooling_device_trip_point_show(struct device *dev, + int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, + int trip, + struct thermal_cooling_device *cdev, +- unsigned long upper, unsigned long lower) ++ unsigned long upper, unsigned long lower, ++ unsigned int weight) + { + struct thermal_instance *dev; + struct thermal_instance *pos; +@@ -964,6 +1231,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, + dev->upper = upper; + dev->lower = lower; + dev->target = THERMAL_NO_TARGET; ++ dev->weight = weight; + + result = get_idr(&tz->idr, &tz->lock, &dev->id); + if (result) +@@ -984,6 +1252,16 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, + if (result) + goto remove_symbol_link; + ++ sprintf(dev->weight_attr_name, "cdev%d_weight", dev->id); ++ sysfs_attr_init(&dev->weight_attr.attr); ++ dev->weight_attr.attr.name = dev->weight_attr_name; ++ dev->weight_attr.attr.mode = S_IWUSR | S_IRUGO; ++ dev->weight_attr.show = thermal_cooling_device_weight_show; ++ dev->weight_attr.store = thermal_cooling_device_weight_store; ++ result = device_create_file(&tz->device, &dev->weight_attr); ++ if (result) ++ goto remove_trip_file; ++ + mutex_lock(&tz->lock); + mutex_lock(&cdev->lock); + list_for_each_entry(pos, &tz->thermal_instances, tz_node) +@@ -1001,6 +1279,8 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, + if (!result) + return 0; + ++ device_remove_file(&tz->device, &dev->weight_attr); ++remove_trip_file: + device_remove_file(&tz->device, &dev->attr); + remove_symbol_link: + sysfs_remove_link(&tz->device.kobj, dev->name); +@@ -1126,6 +1406,7 @@ __thermal_cooling_device_register(struct device_node *np, + cdev->ops = ops; + cdev->updated = false; + cdev->device.class = &thermal_class; ++ cdev->device.groups = cooling_device_attr_groups; + cdev->devdata = devdata; + dev_set_name(&cdev->device, "cooling_device%d", cdev->id); + result = device_register(&cdev->device); +@@ -1135,21 +1416,6 @@ __thermal_cooling_device_register(struct device_node *np, + return ERR_PTR(result); + } + +- /* sys I/F */ +- if (type) { +- result = device_create_file(&cdev->device, &dev_attr_cdev_type); +- if (result) +- goto unregister; +- } +- +- result = device_create_file(&cdev->device, &dev_attr_max_state); +- if (result) +- goto unregister; +- +- result = device_create_file(&cdev->device, &dev_attr_cur_state); +- if (result) +- goto unregister; +- + /* Add 'this' new cdev to the global cdev list */ + mutex_lock(&thermal_list_lock); + list_add(&cdev->node, &thermal_cdev_list); +@@ -1159,11 +1425,6 @@ __thermal_cooling_device_register(struct device_node *np, + bind_cdev(cdev); + + return cdev; +- +-unregister: +- release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); +- device_unregister(&cdev->device); +- return ERR_PTR(result); + } + + /** +@@ -1374,7 +1635,8 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask) + tz->trip_temp_attrs[indx].name; + tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO; + tz->trip_temp_attrs[indx].attr.show = trip_point_temp_show; +- if (mask & (1 << indx)) { ++ if (IS_ENABLED(CONFIG_THERMAL_WRITABLE_TRIPS) && ++ mask & (1 << indx)) { + tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR; + tz->trip_temp_attrs[indx].attr.store = + trip_point_temp_store; +@@ -1451,7 +1713,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz) + struct thermal_zone_device *thermal_zone_device_register(const char *type, + int trips, int mask, void *devdata, + struct thermal_zone_device_ops *ops, +- const struct thermal_zone_params *tzp, ++ struct thermal_zone_params *tzp, + int passive_delay, int polling_delay) + { + struct thermal_zone_device *tz; +@@ -1459,6 +1721,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, + int result; + int count; + int passive = 0; ++ struct thermal_governor *governor; + + if (type && strlen(type) >= THERMAL_NAME_LENGTH) + return ERR_PTR(-EINVAL); +@@ -1545,13 +1808,24 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, + if (result) + goto unregister; + ++ /* Add thermal zone params */ ++ result = create_tzp_attrs(&tz->device); ++ if (result) ++ goto unregister; ++ + /* Update 'this' zone's governor information */ + mutex_lock(&thermal_governor_lock); + + if (tz->tzp) +- tz->governor = __find_governor(tz->tzp->governor_name); ++ governor = __find_governor(tz->tzp->governor_name); + else +- tz->governor = def_governor; ++ governor = def_governor; ++ ++ result = thermal_set_governor(tz, governor); ++ if (result) { ++ mutex_unlock(&thermal_governor_lock); ++ goto unregister; ++ } + + mutex_unlock(&thermal_governor_lock); + +@@ -1640,7 +1914,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) + device_remove_file(&tz->device, &dev_attr_mode); + device_remove_file(&tz->device, &dev_attr_policy); + remove_trip_attrs(tz); +- tz->governor = NULL; ++ thermal_set_governor(tz, NULL); + + thermal_remove_hwmon_sysfs(tz); + release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); +@@ -1800,7 +2074,11 @@ static int __init thermal_register_governors(void) + if (result) + return result; + +- return thermal_gov_user_space_register(); ++ result = thermal_gov_user_space_register(); ++ if (result) ++ return result; ++ ++ return thermal_gov_power_allocator_register(); + } + + static void thermal_unregister_governors(void) +@@ -1809,6 +2087,7 @@ static void thermal_unregister_governors(void) + thermal_gov_fair_share_unregister(); + thermal_gov_bang_bang_unregister(); + thermal_gov_user_space_unregister(); ++ thermal_gov_power_allocator_unregister(); + } + + static int __init thermal_init(void) +diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h +index d15d243..8a66244 100644 +--- a/drivers/thermal/thermal_core.h ++++ b/drivers/thermal/thermal_core.h +@@ -46,8 +46,11 @@ struct thermal_instance { + unsigned long target; /* expected cooling state */ + char attr_name[THERMAL_NAME_LENGTH]; + struct device_attribute attr; ++ char weight_attr_name[THERMAL_NAME_LENGTH]; ++ struct device_attribute weight_attr; + struct list_head tz_node; /* node in tz->thermal_instances */ + struct list_head cdev_node; /* node in cdev->thermal_instances */ ++ unsigned int weight; /* The weight of the cooling device */ + }; + + int thermal_register_governor(struct thermal_governor *); +@@ -85,13 +88,39 @@ static inline int thermal_gov_user_space_register(void) { return 0; } + static inline void thermal_gov_user_space_unregister(void) {} + #endif /* CONFIG_THERMAL_GOV_USER_SPACE */ + ++#ifdef CONFIG_THERMAL_GOV_POWER_ALLOCATOR ++int thermal_gov_power_allocator_register(void); ++void thermal_gov_power_allocator_unregister(void); ++#else ++static inline int thermal_gov_power_allocator_register(void) { return 0; } ++static inline void thermal_gov_power_allocator_unregister(void) {} ++#endif /* CONFIG_THERMAL_GOV_POWER_ALLOCATOR */ ++ + /* device tree support */ + #ifdef CONFIG_THERMAL_OF + int of_parse_thermal_zones(void); + void of_thermal_destroy_zones(void); ++int of_thermal_get_ntrips(struct thermal_zone_device *); ++bool of_thermal_is_trip_valid(struct thermal_zone_device *, int); ++const struct thermal_trip * ++of_thermal_get_trip_points(struct thermal_zone_device *); + #else + static inline int of_parse_thermal_zones(void) { return 0; } + static inline void of_thermal_destroy_zones(void) { } ++static inline int of_thermal_get_ntrips(struct thermal_zone_device *tz) ++{ ++ return 0; ++} ++static inline bool of_thermal_is_trip_valid(struct thermal_zone_device *tz, ++ int trip) ++{ ++ return 0; ++} ++static inline const struct thermal_trip * ++of_thermal_get_trip_points(struct thermal_zone_device *tz) ++{ ++ return NULL; ++} + #endif + + #endif /* __THERMAL_CORE_H__ */ +diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +index 9eec26d..68f53fc 100644 +--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c ++++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +@@ -28,7 +28,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -147,7 +146,8 @@ static int ti_thermal_bind(struct thermal_zone_device *thermal, + return thermal_zone_bind_cooling_device(thermal, 0, cdev, + /* bind with min and max states defined by cpu_cooling */ + THERMAL_NO_LIMIT, +- THERMAL_NO_LIMIT); ++ THERMAL_NO_LIMIT, ++ THERMAL_WEIGHT_DEFAULT); + } + + /* Unbind callback functions for thermal zone */ +@@ -286,6 +286,11 @@ static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal, + return ti_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp); + } + ++static const struct thermal_zone_of_device_ops ti_of_thermal_ops = { ++ .get_temp = __ti_thermal_get_temp, ++ .get_trend = __ti_thermal_get_trend, ++}; ++ + static struct thermal_zone_device_ops ti_thermal_ops = { + .get_temp = ti_thermal_get_temp, + .get_trend = ti_thermal_get_trend, +@@ -333,8 +338,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, + + /* in case this is specified by DT */ + data->ti_thermal = thermal_zone_of_sensor_register(bgp->dev, id, +- data, __ti_thermal_get_temp, +- __ti_thermal_get_trend); ++ data, &ti_of_thermal_ops); + if (IS_ERR(data->ti_thermal)) { + /* Create thermal zone */ + data->ti_thermal = thermal_zone_device_register(domain, +@@ -403,11 +407,6 @@ int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id) + if (!data) + return -EINVAL; + +- if (!cpufreq_get_current_driver()) { +- dev_dbg(bgp->dev, "no cpufreq driver yet\n"); +- return -EPROBE_DEFER; +- } +- + /* Register cooling device */ + data->cool_dev = cpufreq_cooling_register(cpu_present_mask); + if (IS_ERR(data->cool_dev)) { +diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c +index a28dee9..ec40c59 100644 +--- a/drivers/tty/serial/serial_core.c ++++ b/drivers/tty/serial/serial_core.c +@@ -95,6 +95,9 @@ static void __uart_start(struct tty_struct *tty) + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->uart_port; + ++ if (port->ops->wake_peer) ++ port->ops->wake_peer(port); ++ + if (!uart_tx_stopped(port)) + port->ops->start_tx(port); + } +diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c +index 0a0a630..dacf8d5 100644 +--- a/drivers/tty/tty_io.c ++++ b/drivers/tty/tty_io.c +@@ -2594,6 +2594,28 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) + } + + /** ++ * tiocgetd - get line discipline ++ * @tty: tty device ++ * @p: pointer to user data ++ * ++ * Retrieves the line discipline id directly from the ldisc. ++ * ++ * Locking: waits for ldisc reference (in case the line discipline ++ * is changing or the tty is being hungup) ++ */ ++ ++static int tiocgetd(struct tty_struct *tty, int __user *p) ++{ ++ struct tty_ldisc *ld; ++ int ret; ++ ++ ld = tty_ldisc_ref_wait(tty); ++ ret = put_user(ld->ops->num, p); ++ tty_ldisc_deref(ld); ++ return ret; ++} ++ ++/** + * send_break - performed time break + * @tty: device to break on + * @duration: timeout in mS +@@ -2807,7 +2829,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + case TIOCGSID: + return tiocgsid(tty, real_tty, p); + case TIOCGETD: +- return put_user(tty->ldisc->ops->num, (int __user *)p); ++ return tiocgetd(tty, p); + case TIOCSETD: + return tiocsetd(tty, p); + case TIOCVHANGUP: +diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c +index 2d822aa..a72e359 100644 +--- a/drivers/tty/tty_ldisc.c ++++ b/drivers/tty/tty_ldisc.c +@@ -414,6 +414,10 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); + * they are not on hot paths so a little discipline won't do + * any harm. + * ++ * The line discipline-related tty_struct fields are reset to ++ * prevent the ldisc driver from re-using stale information for ++ * the new ldisc instance. ++ * + * Locking: takes termios_rwsem + */ + +@@ -422,6 +426,9 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) + down_write(&tty->termios_rwsem); + tty->termios.c_line = num; + up_write(&tty->termios_rwsem); ++ ++ tty->disc_data = NULL; ++ tty->receive_room = 0; + } + + /** +diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c +index b2a540b..062a7c5 100644 +--- a/drivers/usb/core/config.c ++++ b/drivers/usb/core/config.c +@@ -520,15 +520,23 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx, + + } else if (header->bDescriptorType == + USB_DT_INTERFACE_ASSOCIATION) { ++ struct usb_interface_assoc_descriptor *d; ++ ++ d = (struct usb_interface_assoc_descriptor *)header; ++ if (d->bLength < USB_DT_INTERFACE_ASSOCIATION_SIZE) { ++ dev_warn(ddev, ++ "config %d has an invalid interface association descriptor of length %d, skipping\n", ++ cfgno, d->bLength); ++ continue; ++ } ++ + if (iad_num == USB_MAXIADS) { + dev_warn(ddev, "found more Interface " + "Association Descriptors " + "than allocated for in " + "configuration %d\n", cfgno); + } else { +- config->intf_assoc[iad_num] = +- (struct usb_interface_assoc_descriptor +- *)header; ++ config->intf_assoc[iad_num] = d; + iad_num++; + } + +@@ -633,18 +641,21 @@ void usb_destroy_configuration(struct usb_device *dev) + return; + + if (dev->rawdescriptors) { +- for (i = 0; i < dev->descriptor.bNumConfigurations; i++) ++ for (i = 0; i < dev->descriptor.bNumConfigurations && ++ i < USB_MAXCONFIG; i++) + kfree(dev->rawdescriptors[i]); + + kfree(dev->rawdescriptors); + dev->rawdescriptors = NULL; + } + +- for (c = 0; c < dev->descriptor.bNumConfigurations; c++) { ++ for (c = 0; c < dev->descriptor.bNumConfigurations && ++ c < USB_MAXCONFIG; c++) { + struct usb_host_config *cf = &dev->config[c]; + + kfree(cf->string); +- for (i = 0; i < cf->desc.bNumInterfaces; i++) { ++ for (i = 0; i < cf->desc.bNumInterfaces && ++ i < USB_MAXINTERFACES; i++) { + if (cf->intf_cache[i]) + kref_put(&cf->intf_cache[i]->ref, + usb_release_interface_cache); +@@ -829,10 +840,12 @@ int usb_get_bos_descriptor(struct usb_device *dev) + for (i = 0; i < num; i++) { + buffer += length; + cap = (struct usb_dev_cap_header *)buffer; +- length = cap->bLength; + +- if (total_len < length) ++ if (total_len < sizeof(*cap) || total_len < cap->bLength) { ++ dev->bos->desc->bNumDeviceCaps = i; + break; ++ } ++ length = cap->bLength; + total_len -= length; + + if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { +diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c +index a85eadf..dfcb5f8 100644 +--- a/drivers/usb/core/devio.c ++++ b/drivers/usb/core/devio.c +@@ -1202,10 +1202,11 @@ static int proc_getdriver(struct usb_dev_state *ps, void __user *arg) + + static int proc_connectinfo(struct usb_dev_state *ps, void __user *arg) + { +- struct usbdevfs_connectinfo ci = { +- .devnum = ps->dev->devnum, +- .slow = ps->dev->speed == USB_SPEED_LOW +- }; ++ struct usbdevfs_connectinfo ci; ++ ++ memset(&ci, 0, sizeof(ci)); ++ ci.devnum = ps->dev->devnum; ++ ci.slow = ps->dev->speed == USB_SPEED_LOW; + + if (copy_to_user(arg, &ci, sizeof(ci))) + return -EFAULT; +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 2222899..68c1112 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -36,6 +36,9 @@ + #define USB_VENDOR_GENESYS_LOGIC 0x05e3 + #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01 + ++int otg_usbdev_stat; ++EXPORT_SYMBOL(otg_usbdev_stat); ++ + /* Protect struct usb_device->state and ->children members + * Note: Both are also protected by ->dev.sem, except that ->state can + * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */ +@@ -1030,10 +1033,20 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) + unsigned delay; + + /* Continue a partial initialization */ +- if (type == HUB_INIT2) +- goto init2; +- if (type == HUB_INIT3) ++ if (type == HUB_INIT2 || type == HUB_INIT3) { ++ device_lock(hub->intfdev); ++ ++ /* Was the hub disconnected while we were waiting? */ ++ if (hub->disconnected) { ++ device_unlock(hub->intfdev); ++ kref_put(&hub->kref, hub_release); ++ return; ++ } ++ if (type == HUB_INIT2) ++ goto init2; + goto init3; ++ } ++ kref_get(&hub->kref); + + /* The superspeed hub except for root hub has to use Hub Depth + * value as an offset into the route string to locate the bits +@@ -1231,6 +1244,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) + queue_delayed_work(system_power_efficient_wq, + &hub->init_work, + msecs_to_jiffies(delay)); ++ device_unlock(hub->intfdev); + return; /* Continues at init3: below */ + } else { + msleep(delay); +@@ -1252,6 +1266,10 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) + /* Allow autosuspend if it was suppressed */ + if (type <= HUB_INIT3) + usb_autopm_put_interface_async(to_usb_interface(hub->intfdev)); ++ ++ if (type == HUB_INIT2 || type == HUB_INIT3) ++ device_unlock(hub->intfdev); ++ kref_put(&hub->kref, hub_release); + } + + /* Implement the continuations for the delays above */ +@@ -4953,9 +4971,19 @@ static void port_event(struct usb_hub *hub, int port1) + dev_dbg(&port_dev->dev, "do warm reset\n"); + if (!udev || !(portstatus & USB_PORT_STAT_CONNECTION) + || udev->state == USB_STATE_NOTATTACHED) { +- if (hub_port_reset(hub, port1, NULL, +- HUB_BH_RESET_TIME, true) < 0) ++ int ret; ++ ++ ret = hub_port_reset(hub, port1, NULL, ++ HUB_BH_RESET_TIME, true); ++ if (ret < 0) + hub_port_disable(hub, port1, 1); ++ ret = hub_port_status(hub, port1, ++ &portstatus, &portchange); ++ if (ret < 0) ++ return; ++ if ((portstatus & USB_PORT_STAT_CONNECTION) && !udev && ++ portstatus & USB_PORT_STAT_ENABLE) ++ connect_change = 1; + } else + reset_device = 1; + } +@@ -4984,6 +5012,10 @@ static void port_event(struct usb_hub *hub, int port1) + + if (connect_change) + hub_port_connect_change(hub, port1, portstatus, portchange); ++ ++ if (!(portstatus & USB_PORT_STAT_CONNECTION) ++ && (hdev->parent == NULL)) ++ otg_usbdev_stat = 0; + } + + static void hub_event(struct work_struct *work) +@@ -5060,6 +5092,7 @@ static void hub_event(struct work_struct *work) + * (powered-off), we leave it in that state, run + * an abbreviated port_event(), and move on. + */ ++ otg_usbdev_stat = 1; + pm_runtime_get_noresume(&port_dev->dev); + pm_runtime_barrier(&port_dev->dev); + usb_lock_port(port_dev); +diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig +index c4880fc..23814ec 100644 +--- a/drivers/usb/gadget/Kconfig ++++ b/drivers/usb/gadget/Kconfig +@@ -183,13 +183,28 @@ config USB_F_FS + + config USB_F_UAC1 + tristate +- ++ + config USB_F_UAC2 + tristate + + config USB_F_UVC + tristate + ++config USB_F_MTP ++ tristate ++ ++config USB_F_PTP ++ tristate ++ ++config USB_F_AUDIO_SRC ++ tristate ++ ++config USB_F_ACC ++ tristate ++ ++config USB_F_MIDI ++ tristate ++ + choice + tristate "USB Gadget Drivers" + default USB_ETH +@@ -362,6 +377,57 @@ config USB_CONFIGFS_F_FS + implemented in kernel space (for instance Ethernet, serial or + mass storage) and other are implemented in user space. + ++config USB_CONFIGFS_F_MTP ++ boolean "MTP gadget" ++ depends on USB_CONFIGFS ++ select USB_F_MTP ++ help ++ USB gadget MTP support ++ ++config USB_CONFIGFS_F_PTP ++ boolean "PTP gadget" ++ depends on USB_CONFIGFS && USB_CONFIGFS_F_MTP ++ select USB_F_PTP ++ help ++ USB gadget PTP support ++ ++config USB_CONFIGFS_F_ACC ++ boolean "Accessory gadget" ++ depends on USB_CONFIGFS ++ select USB_F_ACC ++ help ++ USB gadget Accessory support ++ ++config USB_CONFIGFS_F_AUDIO_SRC ++ boolean "Audio Source gadget" ++ depends on USB_CONFIGFS && USB_CONFIGFS_F_ACC ++ depends on SND_PCM ++ select USB_F_AUDIO_SRC ++ help ++ USB gadget Audio Source support ++ ++config USB_CONFIGFS_UEVENT ++ boolean "Uevent notification of Gadget state" ++ depends on USB_CONFIGFS ++ help ++ Enable uevent notifications to userspace when the gadget ++ state changes. The gadget can be in any of the following ++ three states: "CONNECTED/DISCONNECTED/CONFIGURED" ++ ++config USB_CONFIGFS_F_MIDI ++ boolean "MIDI function" ++ depends on USB_CONFIGFS ++ depends on SND ++ select USB_LIBCOMPOSITE ++ select SND_RAWMIDI ++ select USB_F_MIDI ++ help ++ The MIDI Function acts as a USB Audio device, with one MIDI ++ input and one MIDI output. These MIDI jacks appear as ++ a sound "card" in the ALSA sound system. Other MIDI ++ connections can then be made on the gadget system, using ++ ALSA's aconnect utility etc. ++ + source "drivers/usb/gadget/legacy/Kconfig" + + endchoice +diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c +index f6a51fd..e50ec807 100644 +--- a/drivers/usb/gadget/composite.c ++++ b/drivers/usb/gadget/composite.c +@@ -17,11 +17,42 @@ + #include + #include + #include ++#include ++#ifdef CONFIG_USB3_DEVICE_GPIO_CTRL ++#include ++#endif + + #include + #include ++#include + + #include "u_os_desc.h" ++#ifdef CONFIG_USB3_DEVICE_GPIO_CTRL ++#define GPIO_IRQ_NUM 75 ++#define GPIO1_0_IE (1<<0) ++#define GPIO1_0_IC (1<<0) ++#define GPIO1_IE __io_address(0x12141410) ++#define GPIO1_0_DATA __io_address(0x12141004) ++#define GPIO1_IC __io_address(0x1214141c) ++static int uvc_flag; ++static const char gpio_driver_name[] = "usb_gpio_irq"; ++#endif ++#if defined(CONFIG_ARCH_HI3519) || defined(CONFIG_ARCH_HI3519V101) \ ++ || defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) \ ++ || defined(CONFIG_ARCH_HI3516CV300) || defined(CONFIG_ARCH_HI3516AV200) ++#define USB2_BASE_REG 0x12030000 ++#define DWC_OTG_EN (1 << 31) ++#define USB2_PHY_DPPULL_DOWN (0x3 << 26) ++#endif ++ ++#ifdef CONFIG_ARCH_HI3516CV300 ++#define USB2_OTG_BASE 0x5c ++#endif ++ ++#if defined(CONFIG_ARCH_HI3519) || defined(CONFIG_ARCH_HI3519V101) \ ++ || defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) || defined(CONFIG_ARCH_HI3516AV200) ++#define USB2_OTG_BASE 0x78 ++#endif + + /** + * struct usb_os_string - represents OS String to be reported by a gadget +@@ -165,6 +196,8 @@ ep_found: + case USB_ENDPOINT_XFER_ISOC: + /* mult: bits 1:0 of bmAttributes */ + _ep->mult = comp_desc->bmAttributes & 0x3; ++ _ep->maxburst = comp_desc->bMaxBurst; ++ break; + case USB_ENDPOINT_XFER_BULK: + case USB_ENDPOINT_XFER_INT: + _ep->maxburst = comp_desc->bMaxBurst + 1; +@@ -278,10 +311,10 @@ int usb_function_deactivate(struct usb_function *function) + + spin_lock_irqsave(&cdev->lock, flags); + +- if (cdev->deactivations == 0) ++ if (cdev->deactivations == 0) { + status = usb_gadget_disconnect(cdev->gadget); +- if (status == 0) + cdev->deactivations++; ++ } + + spin_unlock_irqrestore(&cdev->lock, flags); + return status; +@@ -845,7 +878,7 @@ done: + } + EXPORT_SYMBOL_GPL(usb_add_config); + +-static void remove_config(struct usb_composite_dev *cdev, ++static void unbind_config(struct usb_composite_dev *cdev, + struct usb_configuration *config) + { + while (!list_empty(&config->functions)) { +@@ -860,7 +893,6 @@ static void remove_config(struct usb_composite_dev *cdev, + /* may free memory for "f" */ + } + } +- list_del(&config->list); + if (config->unbind) { + DBG(cdev, "unbind config '%s'/%p\n", config->label, config); + config->unbind(config); +@@ -887,9 +919,11 @@ void usb_remove_config(struct usb_composite_dev *cdev, + if (cdev->config == config) + reset_config(cdev); + ++ list_del(&config->list); ++ + spin_unlock_irqrestore(&cdev->lock, flags); + +- remove_config(cdev, config); ++ unbind_config(cdev, config); + } + + /*-------------------------------------------------------------------------*/ +@@ -1780,6 +1814,12 @@ void composite_disconnect(struct usb_gadget *gadget) + struct usb_composite_dev *cdev = get_gadget_data(gadget); + unsigned long flags; + ++ if (cdev == NULL) { ++ WARN(1, "%s: Calling disconnect on a Gadget that is \ ++ not connected\n", __func__); ++ return; ++ } ++ + /* REVISIT: should we have config and device level + * disconnect callbacks? + */ +@@ -1818,7 +1858,8 @@ static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver) + struct usb_configuration *c; + c = list_first_entry(&cdev->configs, + struct usb_configuration, list); +- remove_config(cdev, c); ++ list_del(&c->list); ++ unbind_config(cdev, c); + } + if (cdev->driver->unbind && unbind_driver) + cdev->driver->unbind(cdev); +@@ -1835,6 +1876,35 @@ static void composite_unbind(struct usb_gadget *gadget) + __composite_unbind(gadget, true); + } + ++#ifdef CONFIG_USB3_DEVICE_GPIO_CTRL ++static irqreturn_t dwc_usb3_gpio_irq(int irq, void *dev) ++{ ++ int reg; ++ /* mask */ ++ reg = hi_readl(GPIO1_IE); ++ reg &= ~GPIO1_0_IE; ++ hi_writel(reg, GPIO1_IE); ++ /* GPIO1_0 */ ++ if (0 == (hi_readl(GPIO1_0_DATA) & 0x1)) { ++ /* host */ ++ hi_writel(0x30c11004, __io_address(0x1018c110)); ++ udelay(200); ++ /* device */ ++ hi_writel(0x30c12004, __io_address(0x1018c110)); ++ udelay(200); ++ } ++ /* clear */ ++ reg = hi_readl(GPIO1_IC); ++ reg |= GPIO1_0_IC; ++ hi_writel(reg, GPIO1_IC); ++ /* unmask */ ++ reg = hi_readl(GPIO1_IE); ++ reg |= GPIO1_0_IE; ++ hi_writel(reg, GPIO1_IE); ++ return 0; ++} ++#endif ++ + static void update_unchanged_dev_desc(struct usb_device_descriptor *new, + const struct usb_device_descriptor *old) + { +@@ -1968,6 +2038,10 @@ static int composite_bind(struct usb_gadget *gadget, + struct usb_composite_dev *cdev; + struct usb_composite_driver *composite = to_cdriver(gdriver); + int status = -ENOMEM; ++#ifdef CONFIG_HIUSB_DEVICE2_0 ++ void __iomem *usb2_base_reg; ++ int usb2_reg; ++#endif + + cdev = kzalloc(sizeof *cdev, GFP_KERNEL); + if (!cdev) +@@ -1999,10 +2073,39 @@ static int composite_bind(struct usb_gadget *gadget, + + update_unchanged_dev_desc(&cdev->desc, composite->dev); + ++#ifdef CONFIG_USB3_DEVICE_GPIO_CTRL ++ /* uvc Vendor and Product */ ++ if (((cdev->desc).idVendor == 0x1d6b) ++ && ((cdev->desc).idProduct == 0x102)) { ++ int ret = 0; ++ ++ ret = request_irq(GPIO_IRQ_NUM, dwc_usb3_gpio_irq, ++ IRQF_SHARED | IRQF_DISABLED, ++ gpio_driver_name, cdev->driver); ++ uvc_flag = 1; ++ if (ret) ++ return ret; ++ } ++#endif + /* has userspace failed to provide a serial number? */ + if (composite->needs_serial && !cdev->desc.iSerialNumber) + WARNING(cdev, "userspace failed to provide iSerialNumber\n"); +- ++#ifdef CONFIG_HIUSB_SS_DEVICE ++ writel(0x8000, __io_address(0x12030004)); ++ mdelay(200); ++ writel(0x30c01004, __io_address(0x1018c110)); ++ mdelay(200); ++ writel(0x30c02004, __io_address(0x1018c110)); ++ mdelay(200); ++#endif ++#ifdef CONFIG_HIUSB_DEVICE2_0 ++ usb2_base_reg = ioremap_nocache(USB2_BASE_REG, 0x1000); ++ usb2_reg = readl(usb2_base_reg + USB2_OTG_BASE); ++ usb2_reg &= ~(USB2_PHY_DPPULL_DOWN); ++ usb2_reg |= DWC_OTG_EN; ++ writel(usb2_reg, usb2_base_reg + USB2_OTG_BASE); ++ iounmap(usb2_base_reg); ++#endif + INFO(cdev, "%s ready\n", composite->name); + return 0; + +@@ -2129,7 +2232,26 @@ EXPORT_SYMBOL_GPL(usb_composite_probe); + */ + void usb_composite_unregister(struct usb_composite_driver *driver) + { ++#ifdef CONFIG_HIUSB_DEVICE2_0 ++ void __iomem *usb2_base_reg; ++ int usb2_reg; ++#endif ++ + usb_gadget_unregister_driver(&driver->gadget_driver); ++#ifdef CONFIG_USB3_DEVICE_GPIO_CTRL ++ if (uvc_flag) { ++ free_irq(GPIO_IRQ_NUM, driver); ++ uvc_flag = 0; ++ } ++#endif ++#ifdef CONFIG_HIUSB_DEVICE2_0 ++ usb2_base_reg = ioremap_nocache(USB2_BASE_REG, 0x1000); ++ usb2_reg = readl(usb2_base_reg + USB2_OTG_BASE); ++ usb2_reg |= USB2_PHY_DPPULL_DOWN; ++ usb2_reg &= ~DWC_OTG_EN; ++ writel(usb2_reg, usb2_base_reg + USB2_OTG_BASE); ++ iounmap(usb2_base_reg); ++#endif + } + EXPORT_SYMBOL_GPL(usb_composite_unregister); + +diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c +index a7e1a96..fbf07ff 100644 +--- a/drivers/usb/gadget/configfs.c ++++ b/drivers/usb/gadget/configfs.c +@@ -9,6 +9,31 @@ + #include "u_f.h" + #include "u_os_desc.h" + ++#ifdef CONFIG_USB_CONFIGFS_UEVENT ++#include ++#include ++#include ++ ++#ifdef CONFIG_USB_CONFIGFS_F_ACC ++extern int acc_ctrlrequest(struct usb_composite_dev *cdev, ++ const struct usb_ctrlrequest *ctrl); ++void acc_disconnect(void); ++#endif ++static struct class *android_class; ++static struct device *android_device; ++static int index; ++ ++struct device *create_function_device(char *name) ++{ ++ if (android_device && !IS_ERR(android_device)) ++ return device_create(android_class, android_device, ++ MKDEV(0, index++), NULL, name); ++ else ++ return ERR_PTR(-EINVAL); ++} ++EXPORT_SYMBOL_GPL(create_function_device); ++#endif ++ + int check_user_usb_string(const char *name, + struct usb_gadget_strings *stringtab_dev) + { +@@ -63,6 +88,12 @@ struct gadget_info { + bool use_os_desc; + char b_vendor_code; + char qw_sign[OS_STRING_QW_SIGN_LEN]; ++#ifdef CONFIG_USB_CONFIGFS_UEVENT ++ bool connected; ++ bool sw_connected; ++ struct work_struct work; ++ struct device *dev; ++#endif + }; + + struct config_usb_cfg { +@@ -262,7 +293,7 @@ static ssize_t gadget_dev_desc_UDC_store(struct gadget_info *gi, + + mutex_lock(&gi->lock); + +- if (!strlen(name)) { ++ if (!strlen(name) || strcmp(name, "none") == 0) { + ret = unregister_gadget(gi); + if (ret) + goto err; +@@ -405,6 +436,11 @@ static int config_usb_cfg_link( + } + + f = usb_get_function(fi); ++ if (f == NULL) { ++ /* Are we trying to symlink PTP without MTP function? */ ++ ret = -EINVAL; /* Invalid Configuration */ ++ goto out; ++ } + if (IS_ERR(f)) { + ret = PTR_ERR(f); + goto out; +@@ -1427,6 +1463,60 @@ err_comp_cleanup: + return ret; + } + ++#ifdef CONFIG_USB_CONFIGFS_UEVENT ++static void android_work(struct work_struct *data) ++{ ++ struct gadget_info *gi = container_of(data, struct gadget_info, work); ++ struct usb_composite_dev *cdev = &gi->cdev; ++ char *disconnected[2] = { "USB_STATE=DISCONNECTED", NULL }; ++ char *connected[2] = { "USB_STATE=CONNECTED", NULL }; ++ char *configured[2] = { "USB_STATE=CONFIGURED", NULL }; ++ /* 0-connected 1-configured 2-disconnected*/ ++ bool status[3] = { false, false, false }; ++ unsigned long flags; ++ bool uevent_sent = false; ++ ++ spin_lock_irqsave(&cdev->lock, flags); ++ if (cdev->config) ++ status[1] = true; ++ ++ if (gi->connected != gi->sw_connected) { ++ if (gi->connected) ++ status[0] = true; ++ else ++ status[2] = true; ++ gi->sw_connected = gi->connected; ++ } ++ spin_unlock_irqrestore(&cdev->lock, flags); ++ ++ if (status[0]) { ++ kobject_uevent_env(&android_device->kobj, ++ KOBJ_CHANGE, connected); ++ pr_info("%s: sent uevent %s\n", __func__, connected[0]); ++ uevent_sent = true; ++ } ++ ++ if (status[1]) { ++ kobject_uevent_env(&android_device->kobj, ++ KOBJ_CHANGE, configured); ++ pr_info("%s: sent uevent %s\n", __func__, configured[0]); ++ uevent_sent = true; ++ } ++ ++ if (status[2]) { ++ kobject_uevent_env(&android_device->kobj, ++ KOBJ_CHANGE, disconnected); ++ pr_info("%s: sent uevent %s\n", __func__, disconnected[0]); ++ uevent_sent = true; ++ } ++ ++ if (!uevent_sent) { ++ pr_info("%s: did not send uevent (%d %d %p)\n", __func__, ++ gi->connected, gi->sw_connected, cdev->config); ++ } ++} ++#endif ++ + static void configfs_composite_unbind(struct usb_gadget *gadget) + { + struct usb_composite_dev *cdev; +@@ -1444,14 +1534,78 @@ static void configfs_composite_unbind(struct usb_gadget *gadget) + set_gadget_data(gadget, NULL); + } + ++#ifdef CONFIG_USB_CONFIGFS_UEVENT ++static int android_setup(struct usb_gadget *gadget, ++ const struct usb_ctrlrequest *c) ++{ ++ struct usb_composite_dev *cdev = get_gadget_data(gadget); ++ unsigned long flags; ++ struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev); ++ int value = -EOPNOTSUPP; ++ struct usb_function_instance *fi; ++ ++ spin_lock_irqsave(&cdev->lock, flags); ++ if (!gi->connected) { ++ gi->connected = 1; ++ schedule_work(&gi->work); ++ } ++ spin_unlock_irqrestore(&cdev->lock, flags); ++ list_for_each_entry(fi, &gi->available_func, cfs_list) { ++ if (fi != NULL && fi->f != NULL && fi->f->setup != NULL) { ++ value = fi->f->setup(fi->f, c); ++ if (value >= 0) ++ break; ++ } ++ } ++ ++#ifdef CONFIG_USB_CONFIGFS_F_ACC ++ if (value < 0) ++ value = acc_ctrlrequest(cdev, c); ++#endif ++ ++ if (value < 0) ++ value = composite_setup(gadget, c); ++ ++ spin_lock_irqsave(&cdev->lock, flags); ++ if (c->bRequest == USB_REQ_SET_CONFIGURATION && ++ cdev->config) { ++ schedule_work(&gi->work); ++ } ++ spin_unlock_irqrestore(&cdev->lock, flags); ++ ++ return value; ++} ++ ++static void android_disconnect(struct usb_gadget *gadget) ++{ ++ struct usb_composite_dev *cdev = get_gadget_data(gadget); ++ struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev); ++ ++ /* accessory HID support can be active while the ++ accessory function is not actually enabled, ++ so we need to inform it when we are disconnected. ++ */ ++ ++#ifdef CONFIG_USB_CONFIGFS_F_ACC ++ acc_disconnect(); ++#endif ++ gi->connected = 0; ++ schedule_work(&gi->work); ++ composite_disconnect(gadget); ++} ++#endif ++ + static const struct usb_gadget_driver configfs_driver_template = { + .bind = configfs_composite_bind, + .unbind = configfs_composite_unbind, +- ++#ifdef CONFIG_USB_CONFIGFS_UEVENT ++ .setup = android_setup, ++ .disconnect = android_disconnect, ++#else + .setup = composite_setup, + .reset = composite_disconnect, + .disconnect = composite_disconnect, +- ++#endif + .max_speed = USB_SPEED_SUPER, + .driver = { + .owner = THIS_MODULE, +@@ -1459,6 +1613,89 @@ static const struct usb_gadget_driver configfs_driver_template = { + }, + }; + ++#ifdef CONFIG_USB_CONFIGFS_UEVENT ++static ssize_t state_show(struct device *pdev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct gadget_info *dev = dev_get_drvdata(pdev); ++ struct usb_composite_dev *cdev; ++ char *state = "DISCONNECTED"; ++ unsigned long flags; ++ ++ if (!dev) ++ goto out; ++ ++ cdev = &dev->cdev; ++ ++ if (!cdev) ++ goto out; ++ ++ spin_lock_irqsave(&cdev->lock, flags); ++ if (cdev->config) ++ state = "CONFIGURED"; ++ else if (dev->connected) ++ state = "CONNECTED"; ++ spin_unlock_irqrestore(&cdev->lock, flags); ++out: ++ return sprintf(buf, "%s\n", state); ++} ++ ++static DEVICE_ATTR(state, S_IRUGO, state_show, NULL); ++ ++static struct device_attribute *android_usb_attributes[] = { ++ &dev_attr_state, ++ NULL ++}; ++ ++static int android_device_create(struct gadget_info *gi) ++{ ++ struct device_attribute **attrs; ++ struct device_attribute *attr; ++ ++ INIT_WORK(&gi->work, android_work); ++ android_device = device_create(android_class, NULL, ++ MKDEV(0, 0), NULL, "android0"); ++ if (IS_ERR(android_device)) ++ return PTR_ERR(android_device); ++ ++ dev_set_drvdata(android_device, gi); ++ ++ attrs = android_usb_attributes; ++ while ((attr = *attrs++)) { ++ int err; ++ ++ err = device_create_file(android_device, attr); ++ if (err) { ++ device_destroy(android_device->class, ++ android_device->devt); ++ return err; ++ } ++ } ++ ++ return 0; ++} ++ ++static void android_device_destroy(void) ++{ ++ struct device_attribute **attrs; ++ struct device_attribute *attr; ++ ++ attrs = android_usb_attributes; ++ while ((attr = *attrs++)) ++ device_remove_file(android_device, attr); ++ device_destroy(android_device->class, android_device->devt); ++} ++#else ++static inline int android_device_create(struct gadget_info *gi) ++{ ++ return 0; ++} ++ ++static inline void android_device_destroy(void) ++{ ++} ++#endif ++ + static struct config_group *gadgets_make( + struct config_group *group, + const char *name) +@@ -1468,7 +1705,6 @@ static struct config_group *gadgets_make( + gi = kzalloc(sizeof(*gi), GFP_KERNEL); + if (!gi) + return ERR_PTR(-ENOMEM); +- + gi->group.default_groups = gi->default_groups; + gi->group.default_groups[0] = &gi->functions_group; + gi->group.default_groups[1] = &gi->configs_group; +@@ -1507,6 +1743,9 @@ static struct config_group *gadgets_make( + if (!gi->composite.gadget_driver.function) + goto err; + ++ if (android_device_create(gi) < 0) ++ goto err; ++ + #ifdef CONFIG_USB_OTG + gi->otg.bLength = sizeof(struct usb_otg_descriptor); + gi->otg.bDescriptorType = USB_DT_OTG; +@@ -1516,6 +1755,7 @@ static struct config_group *gadgets_make( + config_group_init_type_name(&gi->group, name, + &gadget_root_type); + return &gi->group; ++ + err: + kfree(gi); + return ERR_PTR(-ENOMEM); +@@ -1524,6 +1764,7 @@ err: + static void gadgets_drop(struct config_group *group, struct config_item *item) + { + config_item_put(item); ++ android_device_destroy(); + } + + static struct configfs_group_operations gadgets_ops = { +@@ -1561,6 +1802,13 @@ static int __init gadget_cfs_init(void) + config_group_init(&gadget_subsys.su_group); + + ret = configfs_register_subsystem(&gadget_subsys); ++ ++#ifdef CONFIG_USB_CONFIGFS_UEVENT ++ android_class = class_create(THIS_MODULE, "android_usb"); ++ if (IS_ERR(android_class)) ++ return PTR_ERR(android_class); ++#endif ++ + return ret; + } + module_init(gadget_cfs_init); +@@ -1568,5 +1816,10 @@ module_init(gadget_cfs_init); + static void __exit gadget_cfs_exit(void) + { + configfs_unregister_subsystem(&gadget_subsys); ++#ifdef CONFIG_USB_CONFIGFS_UEVENT ++ if (!IS_ERR(android_class)) ++ class_destroy(android_class); ++#endif ++ + } + module_exit(gadget_cfs_exit); +diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c +index 0567cca..741d75b 100644 +--- a/drivers/usb/gadget/epautoconf.c ++++ b/drivers/usb/gadget/epautoconf.c +@@ -180,8 +180,8 @@ ep_matches ( + int size = ep->maxpacket_limit; + + /* min() doesn't work on bitfields with gcc-3.5 */ +- if (size > 64) +- size = 64; ++ if (size > 512) ++ size = 512; + desc->wMaxPacketSize = cpu_to_le16(size); + } + ep->address = desc->bEndpointAddress; +diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile +index 90701aa..4167a04 100644 +--- a/drivers/usb/gadget/function/Makefile ++++ b/drivers/usb/gadget/function/Makefile +@@ -32,9 +32,21 @@ usb_f_mass_storage-y := f_mass_storage.o storage_common.o + obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o + usb_f_fs-y := f_fs.o + obj-$(CONFIG_USB_F_FS) += usb_f_fs.o +-usb_f_uac1-y := f_uac1.o u_uac1.o ++usb_f_uac1-y := f_uac1.o uac_audio_ex.o uac_queue_ex.o uac_v4l2_ex.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 + obj-$(CONFIG_USB_F_UVC) += usb_f_uvc.o ++usb_f_mtp-y := f_mtp.o ++obj-$(CONFIG_USB_F_MTP) += usb_f_mtp.o ++usb_f_ptp-y := f_ptp.o ++obj-$(CONFIG_USB_F_PTP) += usb_f_ptp.o ++usb_f_audio_source-y := f_audio_source.o ++obj-$(CONFIG_USB_F_AUDIO_SRC) += usb_f_audio_source.o ++usb_f_accessory-y := f_accessory.o ++obj-$(CONFIG_USB_F_ACC) += usb_f_accessory.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_accessory.c b/drivers/usb/gadget/function/f_accessory.c +new file mode 100644 +index 0000000..95a7bbb +--- /dev/null ++++ b/drivers/usb/gadget/function/f_accessory.c +@@ -0,0 +1,1362 @@ ++/* ++ * Gadget Function Driver for Android USB accessories ++ * ++ * Copyright (C) 2011 Google, Inc. ++ * Author: Mike Lockwood ++ * ++ * 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 DEBUG */ ++/* #define VERBOSE_DEBUG */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define MAX_INST_NAME_LEN 40 ++#define BULK_BUFFER_SIZE 16384 ++#define ACC_STRING_SIZE 256 ++ ++#define PROTOCOL_VERSION 2 ++ ++/* String IDs */ ++#define INTERFACE_STRING_INDEX 0 ++ ++/* number of tx and rx requests to allocate */ ++#define TX_REQ_MAX 4 ++#define RX_REQ_MAX 2 ++ ++struct acc_hid_dev { ++ struct list_head list; ++ struct hid_device *hid; ++ struct acc_dev *dev; ++ /* accessory defined ID */ ++ int id; ++ /* HID report descriptor */ ++ u8 *report_desc; ++ /* length of HID report descriptor */ ++ int report_desc_len; ++ /* number of bytes of report_desc we have received so far */ ++ int report_desc_offset; ++}; ++ ++struct acc_dev { ++ struct usb_function function; ++ struct usb_composite_dev *cdev; ++ spinlock_t lock; ++ ++ struct usb_ep *ep_in; ++ struct usb_ep *ep_out; ++ ++ /* set to 1 when we connect */ ++ int online:1; ++ /* Set to 1 when we disconnect. ++ * Not cleared until our file is closed. ++ */ ++ int disconnected:1; ++ ++ /* strings sent by the host */ ++ char manufacturer[ACC_STRING_SIZE]; ++ char model[ACC_STRING_SIZE]; ++ char description[ACC_STRING_SIZE]; ++ char version[ACC_STRING_SIZE]; ++ char uri[ACC_STRING_SIZE]; ++ char serial[ACC_STRING_SIZE]; ++ ++ /* for acc_complete_set_string */ ++ int string_index; ++ ++ /* set to 1 if we have a pending start request */ ++ int start_requested; ++ ++ int audio_mode; ++ ++ /* synchronize access to our device file */ ++ atomic_t open_excl; ++ ++ struct list_head tx_idle; ++ ++ wait_queue_head_t read_wq; ++ wait_queue_head_t write_wq; ++ struct usb_request *rx_req[RX_REQ_MAX]; ++ int rx_done; ++ ++ /* delayed work for handling ACCESSORY_START */ ++ struct delayed_work start_work; ++ ++ /* worker for registering and unregistering hid devices */ ++ struct work_struct hid_work; ++ ++ /* list of active HID devices */ ++ struct list_head hid_list; ++ ++ /* list of new HID devices to register */ ++ struct list_head new_hid_list; ++ ++ /* list of dead HID devices to unregister */ ++ struct list_head dead_hid_list; ++}; ++ ++static struct usb_interface_descriptor acc_interface_desc = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bInterfaceNumber = 0, ++ .bNumEndpoints = 2, ++ .bInterfaceClass = USB_CLASS_VENDOR_SPEC, ++ .bInterfaceSubClass = USB_SUBCLASS_VENDOR_SPEC, ++ .bInterfaceProtocol = 0, ++}; ++ ++static struct usb_endpoint_descriptor acc_highspeed_in_desc = { ++ .bLength = USB_DT_ENDPOINT_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_IN, ++ .bmAttributes = USB_ENDPOINT_XFER_BULK, ++ .wMaxPacketSize = __constant_cpu_to_le16(512), ++}; ++ ++static struct usb_endpoint_descriptor acc_highspeed_out_desc = { ++ .bLength = USB_DT_ENDPOINT_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_OUT, ++ .bmAttributes = USB_ENDPOINT_XFER_BULK, ++ .wMaxPacketSize = __constant_cpu_to_le16(512), ++}; ++ ++static struct usb_endpoint_descriptor acc_fullspeed_in_desc = { ++ .bLength = USB_DT_ENDPOINT_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_IN, ++ .bmAttributes = USB_ENDPOINT_XFER_BULK, ++}; ++ ++static struct usb_endpoint_descriptor acc_fullspeed_out_desc = { ++ .bLength = USB_DT_ENDPOINT_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_OUT, ++ .bmAttributes = USB_ENDPOINT_XFER_BULK, ++}; ++ ++static struct usb_descriptor_header *fs_acc_descs[] = { ++ (struct usb_descriptor_header *) &acc_interface_desc, ++ (struct usb_descriptor_header *) &acc_fullspeed_in_desc, ++ (struct usb_descriptor_header *) &acc_fullspeed_out_desc, ++ NULL, ++}; ++ ++static struct usb_descriptor_header *hs_acc_descs[] = { ++ (struct usb_descriptor_header *) &acc_interface_desc, ++ (struct usb_descriptor_header *) &acc_highspeed_in_desc, ++ (struct usb_descriptor_header *) &acc_highspeed_out_desc, ++ NULL, ++}; ++ ++static struct usb_string acc_string_defs[] = { ++ [INTERFACE_STRING_INDEX].s = "Android Accessory Interface", ++ { }, /* end of list */ ++}; ++ ++static struct usb_gadget_strings acc_string_table = { ++ .language = 0x0409, /* en-US */ ++ .strings = acc_string_defs, ++}; ++ ++static struct usb_gadget_strings *acc_strings[] = { ++ &acc_string_table, ++ NULL, ++}; ++ ++/* temporary variable used between acc_open() and acc_gadget_bind() */ ++static struct acc_dev *_acc_dev; ++ ++struct acc_instance { ++ struct usb_function_instance func_inst; ++ const char *name; ++}; ++ ++static inline struct acc_dev *func_to_dev(struct usb_function *f) ++{ ++ return container_of(f, struct acc_dev, function); ++} ++ ++static struct usb_request *acc_request_new(struct usb_ep *ep, int buffer_size) ++{ ++ struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL); ++ if (!req) ++ return NULL; ++ ++ /* now allocate buffers for the requests */ ++ req->buf = kmalloc(buffer_size, GFP_KERNEL); ++ if (!req->buf) { ++ usb_ep_free_request(ep, req); ++ return NULL; ++ } ++ ++ return req; ++} ++ ++static void acc_request_free(struct usb_request *req, struct usb_ep *ep) ++{ ++ if (req) { ++ kfree(req->buf); ++ usb_ep_free_request(ep, req); ++ } ++} ++ ++/* add a request to the tail of a list */ ++static void req_put(struct acc_dev *dev, struct list_head *head, ++ struct usb_request *req) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ list_add_tail(&req->list, head); ++ spin_unlock_irqrestore(&dev->lock, flags); ++} ++ ++/* remove a request from the head of a list */ ++static struct usb_request *req_get(struct acc_dev *dev, struct list_head *head) ++{ ++ unsigned long flags; ++ struct usb_request *req; ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ if (list_empty(head)) { ++ req = 0; ++ } else { ++ req = list_first_entry(head, struct usb_request, list); ++ list_del(&req->list); ++ } ++ spin_unlock_irqrestore(&dev->lock, flags); ++ return req; ++} ++ ++static void acc_set_disconnected(struct acc_dev *dev) ++{ ++ dev->online = 0; ++ dev->disconnected = 1; ++} ++ ++static void acc_complete_in(struct usb_ep *ep, struct usb_request *req) ++{ ++ struct acc_dev *dev = _acc_dev; ++ ++ if (req->status == -ESHUTDOWN) { ++ pr_debug("acc_complete_in set disconnected"); ++ acc_set_disconnected(dev); ++ } ++ ++ req_put(dev, &dev->tx_idle, req); ++ ++ wake_up(&dev->write_wq); ++} ++ ++static void acc_complete_out(struct usb_ep *ep, struct usb_request *req) ++{ ++ struct acc_dev *dev = _acc_dev; ++ ++ dev->rx_done = 1; ++ if (req->status == -ESHUTDOWN) { ++ pr_debug("acc_complete_out set disconnected"); ++ acc_set_disconnected(dev); ++ } ++ ++ wake_up(&dev->read_wq); ++} ++ ++static void acc_complete_set_string(struct usb_ep *ep, struct usb_request *req) ++{ ++ struct acc_dev *dev = ep->driver_data; ++ char *string_dest = NULL; ++ int length = req->actual; ++ ++ if (req->status != 0) { ++ pr_err("acc_complete_set_string, err %d\n", req->status); ++ return; ++ } ++ ++ switch (dev->string_index) { ++ case ACCESSORY_STRING_MANUFACTURER: ++ string_dest = dev->manufacturer; ++ break; ++ case ACCESSORY_STRING_MODEL: ++ string_dest = dev->model; ++ break; ++ case ACCESSORY_STRING_DESCRIPTION: ++ string_dest = dev->description; ++ break; ++ case ACCESSORY_STRING_VERSION: ++ string_dest = dev->version; ++ break; ++ case ACCESSORY_STRING_URI: ++ string_dest = dev->uri; ++ break; ++ case ACCESSORY_STRING_SERIAL: ++ string_dest = dev->serial; ++ break; ++ } ++ if (string_dest) { ++ unsigned long flags; ++ ++ if (length >= ACC_STRING_SIZE) ++ length = ACC_STRING_SIZE - 1; ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ memcpy(string_dest, req->buf, length); ++ /* ensure zero termination */ ++ string_dest[length] = 0; ++ spin_unlock_irqrestore(&dev->lock, flags); ++ } else { ++ pr_err("unknown accessory string index %d\n", ++ dev->string_index); ++ } ++} ++ ++static void acc_complete_set_hid_report_desc(struct usb_ep *ep, ++ struct usb_request *req) ++{ ++ struct acc_hid_dev *hid = req->context; ++ struct acc_dev *dev = hid->dev; ++ int length = req->actual; ++ ++ if (req->status != 0) { ++ pr_err("acc_complete_set_hid_report_desc, err %d\n", ++ req->status); ++ return; ++ } ++ ++ memcpy(hid->report_desc + hid->report_desc_offset, req->buf, length); ++ hid->report_desc_offset += length; ++ if (hid->report_desc_offset == hid->report_desc_len) { ++ /* After we have received the entire report descriptor ++ * we schedule work to initialize the HID device ++ */ ++ schedule_work(&dev->hid_work); ++ } ++} ++ ++static void acc_complete_send_hid_event(struct usb_ep *ep, ++ struct usb_request *req) ++{ ++ struct acc_hid_dev *hid = req->context; ++ int length = req->actual; ++ ++ if (req->status != 0) { ++ pr_err("acc_complete_send_hid_event, err %d\n", req->status); ++ return; ++ } ++ ++ hid_report_raw_event(hid->hid, HID_INPUT_REPORT, req->buf, length, 1); ++} ++ ++static int acc_hid_parse(struct hid_device *hid) ++{ ++ struct acc_hid_dev *hdev = hid->driver_data; ++ ++ hid_parse_report(hid, hdev->report_desc, hdev->report_desc_len); ++ return 0; ++} ++ ++static int acc_hid_start(struct hid_device *hid) ++{ ++ return 0; ++} ++ ++static void acc_hid_stop(struct hid_device *hid) ++{ ++} ++ ++static int acc_hid_open(struct hid_device *hid) ++{ ++ return 0; ++} ++ ++static void acc_hid_close(struct hid_device *hid) ++{ ++} ++ ++static struct hid_ll_driver acc_hid_ll_driver = { ++ .parse = acc_hid_parse, ++ .start = acc_hid_start, ++ .stop = acc_hid_stop, ++ .open = acc_hid_open, ++ .close = acc_hid_close, ++}; ++ ++static struct acc_hid_dev *acc_hid_new(struct acc_dev *dev, ++ int id, int desc_len) ++{ ++ struct acc_hid_dev *hdev; ++ ++ hdev = kzalloc(sizeof(*hdev), GFP_ATOMIC); ++ if (!hdev) ++ return NULL; ++ hdev->report_desc = kzalloc(desc_len, GFP_ATOMIC); ++ if (!hdev->report_desc) { ++ kfree(hdev); ++ return NULL; ++ } ++ hdev->dev = dev; ++ hdev->id = id; ++ hdev->report_desc_len = desc_len; ++ ++ return hdev; ++} ++ ++static struct acc_hid_dev *acc_hid_get(struct list_head *list, int id) ++{ ++ struct acc_hid_dev *hid; ++ ++ list_for_each_entry(hid, list, list) { ++ if (hid->id == id) ++ return hid; ++ } ++ return NULL; ++} ++ ++static int acc_register_hid(struct acc_dev *dev, int id, int desc_length) ++{ ++ struct acc_hid_dev *hid; ++ unsigned long flags; ++ ++ /* report descriptor length must be > 0 */ ++ if (desc_length <= 0) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ /* replace HID if one already exists with this ID */ ++ hid = acc_hid_get(&dev->hid_list, id); ++ if (!hid) ++ hid = acc_hid_get(&dev->new_hid_list, id); ++ if (hid) ++ list_move(&hid->list, &dev->dead_hid_list); ++ ++ hid = acc_hid_new(dev, id, desc_length); ++ if (!hid) { ++ spin_unlock_irqrestore(&dev->lock, flags); ++ return -ENOMEM; ++ } ++ ++ list_add(&hid->list, &dev->new_hid_list); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ /* schedule work to register the HID device */ ++ schedule_work(&dev->hid_work); ++ return 0; ++} ++ ++static int acc_unregister_hid(struct acc_dev *dev, int id) ++{ ++ struct acc_hid_dev *hid; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ hid = acc_hid_get(&dev->hid_list, id); ++ if (!hid) ++ hid = acc_hid_get(&dev->new_hid_list, id); ++ if (!hid) { ++ spin_unlock_irqrestore(&dev->lock, flags); ++ return -EINVAL; ++ } ++ ++ list_move(&hid->list, &dev->dead_hid_list); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ schedule_work(&dev->hid_work); ++ return 0; ++} ++ ++static int create_bulk_endpoints(struct acc_dev *dev, ++ struct usb_endpoint_descriptor *in_desc, ++ struct usb_endpoint_descriptor *out_desc) ++{ ++ struct usb_composite_dev *cdev = dev->cdev; ++ struct usb_request *req; ++ struct usb_ep *ep; ++ int i; ++ ++ DBG(cdev, "create_bulk_endpoints dev: %p\n", dev); ++ ++ ep = usb_ep_autoconfig(cdev->gadget, in_desc); ++ if (!ep) { ++ DBG(cdev, "usb_ep_autoconfig for ep_in failed\n"); ++ return -ENODEV; ++ } ++ DBG(cdev, "usb_ep_autoconfig for ep_in got %s\n", ep->name); ++ ep->driver_data = dev; /* claim the endpoint */ ++ dev->ep_in = ep; ++ ++ ep = usb_ep_autoconfig(cdev->gadget, out_desc); ++ if (!ep) { ++ DBG(cdev, "usb_ep_autoconfig for ep_out failed\n"); ++ return -ENODEV; ++ } ++ DBG(cdev, "usb_ep_autoconfig for ep_out got %s\n", ep->name); ++ ep->driver_data = dev; /* claim the endpoint */ ++ dev->ep_out = ep; ++ ++ ep = usb_ep_autoconfig(cdev->gadget, out_desc); ++ if (!ep) { ++ DBG(cdev, "usb_ep_autoconfig for ep_out failed\n"); ++ return -ENODEV; ++ } ++ DBG(cdev, "usb_ep_autoconfig for ep_out got %s\n", ep->name); ++ ep->driver_data = dev; /* claim the endpoint */ ++ dev->ep_out = ep; ++ ++ /* now allocate requests for our endpoints */ ++ for (i = 0; i < TX_REQ_MAX; i++) { ++ req = acc_request_new(dev->ep_in, BULK_BUFFER_SIZE); ++ if (!req) ++ goto fail; ++ req->complete = acc_complete_in; ++ req_put(dev, &dev->tx_idle, req); ++ } ++ for (i = 0; i < RX_REQ_MAX; i++) { ++ req = acc_request_new(dev->ep_out, BULK_BUFFER_SIZE); ++ if (!req) ++ goto fail; ++ req->complete = acc_complete_out; ++ dev->rx_req[i] = req; ++ } ++ ++ return 0; ++ ++fail: ++ pr_err("acc_bind() could not allocate requests\n"); ++ while ((req = req_get(dev, &dev->tx_idle))) ++ acc_request_free(req, dev->ep_in); ++ for (i = 0; i < RX_REQ_MAX; i++) ++ acc_request_free(dev->rx_req[i], dev->ep_out); ++ return -1; ++} ++ ++static ssize_t acc_read(struct file *fp, char __user *buf, ++ size_t count, loff_t *pos) ++{ ++ struct acc_dev *dev = fp->private_data; ++ struct usb_request *req; ++ ssize_t r = count; ++ unsigned xfer; ++ int ret = 0; ++ ++ pr_debug("acc_read(%zu)\n", count); ++ ++ if (dev->disconnected) { ++ pr_debug("acc_read disconnected"); ++ return -ENODEV; ++ } ++ ++ if (count > BULK_BUFFER_SIZE) ++ count = BULK_BUFFER_SIZE; ++ ++ /* we will block until we're online */ ++ pr_debug("acc_read: waiting for online\n"); ++ ret = wait_event_interruptible(dev->read_wq, dev->online); ++ if (ret < 0) { ++ r = ret; ++ goto done; ++ } ++ ++ if (dev->rx_done) { ++ // last req cancelled. try to get it. ++ req = dev->rx_req[0]; ++ goto copy_data; ++ } ++ ++requeue_req: ++ /* queue a request */ ++ req = dev->rx_req[0]; ++ req->length = count; ++ dev->rx_done = 0; ++ ret = usb_ep_queue(dev->ep_out, req, GFP_KERNEL); ++ if (ret < 0) { ++ r = -EIO; ++ goto done; ++ } else { ++ pr_debug("rx %p queue\n", req); ++ } ++ ++ /* wait for a request to complete */ ++ ret = wait_event_interruptible(dev->read_wq, dev->rx_done); ++ if (ret < 0) { ++ r = ret; ++ ret = usb_ep_dequeue(dev->ep_out, req); ++ if (ret != 0) { ++ // cancel failed. There can be a data already received. ++ // it will be retrieved in the next read. ++ pr_debug("acc_read: cancelling failed %d", ret); ++ } ++ goto done; ++ } ++ ++copy_data: ++ dev->rx_done = 0; ++ if (dev->online) { ++ /* If we got a 0-len packet, throw it back and try again. */ ++ if (req->actual == 0) ++ goto requeue_req; ++ ++ pr_debug("rx %p %u\n", req, req->actual); ++ xfer = (req->actual < count) ? req->actual : count; ++ r = xfer; ++ if (copy_to_user(buf, req->buf, xfer)) ++ r = -EFAULT; ++ } else ++ r = -EIO; ++ ++done: ++ pr_debug("acc_read returning %zd\n", r); ++ return r; ++} ++ ++static ssize_t acc_write(struct file *fp, const char __user *buf, ++ size_t count, loff_t *pos) ++{ ++ struct acc_dev *dev = fp->private_data; ++ struct usb_request *req = 0; ++ ssize_t r = count; ++ unsigned xfer; ++ int ret; ++ ++ pr_debug("acc_write(%zu)\n", count); ++ ++ if (!dev->online || dev->disconnected) { ++ pr_debug("acc_write disconnected or not online"); ++ return -ENODEV; ++ } ++ ++ while (count > 0) { ++ if (!dev->online) { ++ pr_debug("acc_write dev->error\n"); ++ r = -EIO; ++ break; ++ } ++ ++ /* get an idle tx request to use */ ++ req = 0; ++ ret = wait_event_interruptible(dev->write_wq, ++ ((req = req_get(dev, &dev->tx_idle)) || !dev->online)); ++ if (!req) { ++ r = ret; ++ break; ++ } ++ ++ if (count > BULK_BUFFER_SIZE) { ++ xfer = BULK_BUFFER_SIZE; ++ /* ZLP, They will be more TX requests so not yet. */ ++ req->zero = 0; ++ } else { ++ xfer = count; ++ /* If the data length is a multple of the ++ * maxpacket size then send a zero length packet(ZLP). ++ */ ++ req->zero = ((xfer % dev->ep_in->maxpacket) == 0); ++ } ++ if (copy_from_user(req->buf, buf, xfer)) { ++ r = -EFAULT; ++ break; ++ } ++ ++ req->length = xfer; ++ ret = usb_ep_queue(dev->ep_in, req, GFP_KERNEL); ++ if (ret < 0) { ++ pr_debug("acc_write: xfer error %d\n", ret); ++ r = -EIO; ++ break; ++ } ++ ++ buf += xfer; ++ count -= xfer; ++ ++ /* zero this so we don't try to free it on error exit */ ++ req = 0; ++ } ++ ++ if (req) ++ req_put(dev, &dev->tx_idle, req); ++ ++ pr_debug("acc_write returning %zd\n", r); ++ return r; ++} ++ ++static long acc_ioctl(struct file *fp, unsigned code, unsigned long value) ++{ ++ struct acc_dev *dev = fp->private_data; ++ char *src = NULL; ++ int ret; ++ ++ switch (code) { ++ case ACCESSORY_GET_STRING_MANUFACTURER: ++ src = dev->manufacturer; ++ break; ++ case ACCESSORY_GET_STRING_MODEL: ++ src = dev->model; ++ break; ++ case ACCESSORY_GET_STRING_DESCRIPTION: ++ src = dev->description; ++ break; ++ case ACCESSORY_GET_STRING_VERSION: ++ src = dev->version; ++ break; ++ case ACCESSORY_GET_STRING_URI: ++ src = dev->uri; ++ break; ++ case ACCESSORY_GET_STRING_SERIAL: ++ src = dev->serial; ++ break; ++ case ACCESSORY_IS_START_REQUESTED: ++ return dev->start_requested; ++ case ACCESSORY_GET_AUDIO_MODE: ++ return dev->audio_mode; ++ } ++ if (!src) ++ return -EINVAL; ++ ++ ret = strlen(src) + 1; ++ if (copy_to_user((void __user *)value, src, ret)) ++ ret = -EFAULT; ++ return ret; ++} ++ ++static int acc_open(struct inode *ip, struct file *fp) ++{ ++ printk(KERN_INFO "acc_open\n"); ++ if (atomic_xchg(&_acc_dev->open_excl, 1)) ++ return -EBUSY; ++ ++ _acc_dev->disconnected = 0; ++ fp->private_data = _acc_dev; ++ return 0; ++} ++ ++static int acc_release(struct inode *ip, struct file *fp) ++{ ++ printk(KERN_INFO "acc_release\n"); ++ ++ WARN_ON(!atomic_xchg(&_acc_dev->open_excl, 0)); ++ _acc_dev->disconnected = 0; ++ return 0; ++} ++ ++/* file operations for /dev/usb_accessory */ ++static const struct file_operations acc_fops = { ++ .owner = THIS_MODULE, ++ .read = acc_read, ++ .write = acc_write, ++ .unlocked_ioctl = acc_ioctl, ++ .open = acc_open, ++ .release = acc_release, ++}; ++ ++static int acc_hid_probe(struct hid_device *hdev, ++ const struct hid_device_id *id) ++{ ++ int ret; ++ ++ ret = hid_parse(hdev); ++ if (ret) ++ return ret; ++ return hid_hw_start(hdev, HID_CONNECT_DEFAULT); ++} ++ ++static struct miscdevice acc_device = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = "usb_accessory", ++ .fops = &acc_fops, ++}; ++ ++static const struct hid_device_id acc_hid_table[] = { ++ { HID_USB_DEVICE(HID_ANY_ID, HID_ANY_ID) }, ++ { } ++}; ++ ++static struct hid_driver acc_hid_driver = { ++ .name = "USB accessory", ++ .id_table = acc_hid_table, ++ .probe = acc_hid_probe, ++}; ++ ++int acc_ctrlrequest(struct usb_composite_dev *cdev, ++ const struct usb_ctrlrequest *ctrl) ++{ ++ struct acc_dev *dev = _acc_dev; ++ int value = -EOPNOTSUPP; ++ struct acc_hid_dev *hid; ++ int offset; ++ u8 b_requestType = ctrl->bRequestType; ++ u8 b_request = ctrl->bRequest; ++ u16 w_index = le16_to_cpu(ctrl->wIndex); ++ u16 w_value = le16_to_cpu(ctrl->wValue); ++ u16 w_length = le16_to_cpu(ctrl->wLength); ++ unsigned long flags; ++ ++/* ++ printk(KERN_INFO "acc_ctrlrequest " ++ "%02x.%02x v%04x i%04x l%u\n", ++ b_requestType, b_request, ++ w_value, w_index, w_length); ++*/ ++ ++ if (b_requestType == (USB_DIR_OUT | USB_TYPE_VENDOR)) { ++ if (b_request == ACCESSORY_START) { ++ dev->start_requested = 1; ++ schedule_delayed_work( ++ &dev->start_work, msecs_to_jiffies(10)); ++ value = 0; ++ } else if (b_request == ACCESSORY_SEND_STRING) { ++ dev->string_index = w_index; ++ cdev->gadget->ep0->driver_data = dev; ++ cdev->req->complete = acc_complete_set_string; ++ value = w_length; ++ } else if (b_request == ACCESSORY_SET_AUDIO_MODE && ++ w_index == 0 && w_length == 0) { ++ dev->audio_mode = w_value; ++ value = 0; ++ } else if (b_request == ACCESSORY_REGISTER_HID) { ++ value = acc_register_hid(dev, w_value, w_index); ++ } else if (b_request == ACCESSORY_UNREGISTER_HID) { ++ value = acc_unregister_hid(dev, w_value); ++ } else if (b_request == ACCESSORY_SET_HID_REPORT_DESC) { ++ spin_lock_irqsave(&dev->lock, flags); ++ hid = acc_hid_get(&dev->new_hid_list, w_value); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ if (!hid) { ++ value = -EINVAL; ++ goto err; ++ } ++ offset = w_index; ++ if (offset != hid->report_desc_offset ++ || offset + w_length > hid->report_desc_len) { ++ value = -EINVAL; ++ goto err; ++ } ++ cdev->req->context = hid; ++ cdev->req->complete = acc_complete_set_hid_report_desc; ++ value = w_length; ++ } else if (b_request == ACCESSORY_SEND_HID_EVENT) { ++ spin_lock_irqsave(&dev->lock, flags); ++ hid = acc_hid_get(&dev->hid_list, w_value); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ if (!hid) { ++ value = -EINVAL; ++ goto err; ++ } ++ cdev->req->context = hid; ++ cdev->req->complete = acc_complete_send_hid_event; ++ value = w_length; ++ } ++ } else if (b_requestType == (USB_DIR_IN | USB_TYPE_VENDOR)) { ++ if (b_request == ACCESSORY_GET_PROTOCOL) { ++ *((u16 *)cdev->req->buf) = PROTOCOL_VERSION; ++ value = sizeof(u16); ++ ++ /* clear any string left over from a previous session */ ++ memset(dev->manufacturer, 0, sizeof(dev->manufacturer)); ++ memset(dev->model, 0, sizeof(dev->model)); ++ memset(dev->description, 0, sizeof(dev->description)); ++ memset(dev->version, 0, sizeof(dev->version)); ++ memset(dev->uri, 0, sizeof(dev->uri)); ++ memset(dev->serial, 0, sizeof(dev->serial)); ++ dev->start_requested = 0; ++ dev->audio_mode = 0; ++ } ++ } ++ ++ if (value >= 0) { ++ cdev->req->zero = 0; ++ cdev->req->length = value; ++ value = usb_ep_queue(cdev->gadget->ep0, cdev->req, GFP_ATOMIC); ++ if (value < 0) ++ ERROR(cdev, "%s setup response queue error\n", ++ __func__); ++ } ++ ++err: ++ if (value == -EOPNOTSUPP) ++ VDBG(cdev, ++ "unknown class-specific control req " ++ "%02x.%02x v%04x i%04x l%u\n", ++ ctrl->bRequestType, ctrl->bRequest, ++ w_value, w_index, w_length); ++ return value; ++} ++EXPORT_SYMBOL_GPL(acc_ctrlrequest); ++ ++static int ++__acc_function_bind(struct usb_configuration *c, ++ struct usb_function *f, bool configfs) ++{ ++ struct usb_composite_dev *cdev = c->cdev; ++ struct acc_dev *dev = func_to_dev(f); ++ int id; ++ int ret; ++ ++ DBG(cdev, "acc_function_bind dev: %p\n", dev); ++ ++ if (configfs) { ++ if (acc_string_defs[INTERFACE_STRING_INDEX].id == 0) { ++ ret = usb_string_id(c->cdev); ++ if (ret < 0) ++ return ret; ++ acc_string_defs[INTERFACE_STRING_INDEX].id = ret; ++ acc_interface_desc.iInterface = ret; ++ } ++ dev->cdev = c->cdev; ++ } ++ ret = hid_register_driver(&acc_hid_driver); ++ if (ret) ++ return ret; ++ ++ dev->start_requested = 0; ++ ++ /* allocate interface ID(s) */ ++ id = usb_interface_id(c, f); ++ if (id < 0) ++ return id; ++ acc_interface_desc.bInterfaceNumber = id; ++ ++ /* allocate endpoints */ ++ ret = create_bulk_endpoints(dev, &acc_fullspeed_in_desc, ++ &acc_fullspeed_out_desc); ++ if (ret) ++ return ret; ++ ++ /* support high speed hardware */ ++ if (gadget_is_dualspeed(c->cdev->gadget)) { ++ acc_highspeed_in_desc.bEndpointAddress = ++ acc_fullspeed_in_desc.bEndpointAddress; ++ acc_highspeed_out_desc.bEndpointAddress = ++ acc_fullspeed_out_desc.bEndpointAddress; ++ } ++ ++ DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n", ++ gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", ++ f->name, dev->ep_in->name, dev->ep_out->name); ++ return 0; ++} ++ ++static int ++acc_function_bind(struct usb_configuration *c, struct usb_function *f) { ++ return __acc_function_bind(c, f, false); ++} ++ ++static int ++acc_function_bind_configfs(struct usb_configuration *c, ++ struct usb_function *f) { ++ return __acc_function_bind(c, f, true); ++} ++ ++static void ++kill_all_hid_devices(struct acc_dev *dev) ++{ ++ struct acc_hid_dev *hid; ++ struct list_head *entry, *temp; ++ unsigned long flags; ++ ++ /* do nothing if usb accessory device doesn't exist */ ++ if (!dev) ++ return; ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ list_for_each_safe(entry, temp, &dev->hid_list) { ++ hid = list_entry(entry, struct acc_hid_dev, list); ++ list_del(&hid->list); ++ list_add(&hid->list, &dev->dead_hid_list); ++ } ++ list_for_each_safe(entry, temp, &dev->new_hid_list) { ++ hid = list_entry(entry, struct acc_hid_dev, list); ++ list_del(&hid->list); ++ list_add(&hid->list, &dev->dead_hid_list); ++ } ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ schedule_work(&dev->hid_work); ++} ++ ++static void ++acc_hid_unbind(struct acc_dev *dev) ++{ ++ hid_unregister_driver(&acc_hid_driver); ++ kill_all_hid_devices(dev); ++} ++ ++static void ++acc_function_unbind(struct usb_configuration *c, struct usb_function *f) ++{ ++ struct acc_dev *dev = func_to_dev(f); ++ struct usb_request *req; ++ int i; ++ ++ while ((req = req_get(dev, &dev->tx_idle))) ++ acc_request_free(req, dev->ep_in); ++ for (i = 0; i < RX_REQ_MAX; i++) ++ acc_request_free(dev->rx_req[i], dev->ep_out); ++ ++ acc_hid_unbind(dev); ++} ++ ++static void acc_start_work(struct work_struct *data) ++{ ++ char *envp[2] = { "ACCESSORY=START", NULL }; ++ kobject_uevent_env(&acc_device.this_device->kobj, KOBJ_CHANGE, envp); ++} ++ ++static int acc_hid_init(struct acc_hid_dev *hdev) ++{ ++ struct hid_device *hid; ++ int ret; ++ ++ hid = hid_allocate_device(); ++ if (IS_ERR(hid)) ++ return PTR_ERR(hid); ++ ++ hid->ll_driver = &acc_hid_ll_driver; ++ hid->dev.parent = acc_device.this_device; ++ ++ hid->bus = BUS_USB; ++ hid->vendor = HID_ANY_ID; ++ hid->product = HID_ANY_ID; ++ hid->driver_data = hdev; ++ ret = hid_add_device(hid); ++ if (ret) { ++ pr_err("can't add hid device: %d\n", ret); ++ hid_destroy_device(hid); ++ return ret; ++ } ++ ++ hdev->hid = hid; ++ return 0; ++} ++ ++static void acc_hid_delete(struct acc_hid_dev *hid) ++{ ++ kfree(hid->report_desc); ++ kfree(hid); ++} ++ ++static void acc_hid_work(struct work_struct *data) ++{ ++ struct acc_dev *dev = _acc_dev; ++ struct list_head *entry, *temp; ++ struct acc_hid_dev *hid; ++ struct list_head new_list, dead_list; ++ unsigned long flags; ++ ++ INIT_LIST_HEAD(&new_list); ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ /* copy hids that are ready for initialization to new_list */ ++ list_for_each_safe(entry, temp, &dev->new_hid_list) { ++ hid = list_entry(entry, struct acc_hid_dev, list); ++ if (hid->report_desc_offset == hid->report_desc_len) ++ list_move(&hid->list, &new_list); ++ } ++ ++ if (list_empty(&dev->dead_hid_list)) { ++ INIT_LIST_HEAD(&dead_list); ++ } else { ++ /* move all of dev->dead_hid_list to dead_list */ ++ dead_list.prev = dev->dead_hid_list.prev; ++ dead_list.next = dev->dead_hid_list.next; ++ dead_list.next->prev = &dead_list; ++ dead_list.prev->next = &dead_list; ++ INIT_LIST_HEAD(&dev->dead_hid_list); ++ } ++ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ /* register new HID devices */ ++ list_for_each_safe(entry, temp, &new_list) { ++ hid = list_entry(entry, struct acc_hid_dev, list); ++ if (acc_hid_init(hid)) { ++ pr_err("can't add HID device %p\n", hid); ++ acc_hid_delete(hid); ++ } else { ++ spin_lock_irqsave(&dev->lock, flags); ++ list_move(&hid->list, &dev->hid_list); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ } ++ } ++ ++ /* remove dead HID devices */ ++ list_for_each_safe(entry, temp, &dead_list) { ++ hid = list_entry(entry, struct acc_hid_dev, list); ++ list_del(&hid->list); ++ if (hid->hid) ++ hid_destroy_device(hid->hid); ++ acc_hid_delete(hid); ++ } ++} ++ ++static int acc_function_set_alt(struct usb_function *f, ++ unsigned intf, unsigned alt) ++{ ++ struct acc_dev *dev = func_to_dev(f); ++ struct usb_composite_dev *cdev = f->config->cdev; ++ int ret; ++ ++ DBG(cdev, "acc_function_set_alt intf: %d alt: %d\n", intf, alt); ++ ++ ret = config_ep_by_speed(cdev->gadget, f, dev->ep_in); ++ if (ret) ++ return ret; ++ ++ ret = usb_ep_enable(dev->ep_in); ++ if (ret) ++ return ret; ++ ++ ret = config_ep_by_speed(cdev->gadget, f, dev->ep_out); ++ if (ret) ++ return ret; ++ ++ ret = usb_ep_enable(dev->ep_out); ++ if (ret) { ++ usb_ep_disable(dev->ep_in); ++ return ret; ++ } ++ ++ dev->online = 1; ++ ++ /* readers may be blocked waiting for us to go online */ ++ wake_up(&dev->read_wq); ++ return 0; ++} ++ ++static void acc_function_disable(struct usb_function *f) ++{ ++ struct acc_dev *dev = func_to_dev(f); ++ struct usb_composite_dev *cdev = dev->cdev; ++ ++ DBG(cdev, "acc_function_disable\n"); ++ acc_set_disconnected(dev); ++ usb_ep_disable(dev->ep_in); ++ usb_ep_disable(dev->ep_out); ++ ++ /* readers may be blocked waiting for us to go online */ ++ wake_up(&dev->read_wq); ++ ++ VDBG(cdev, "%s disabled\n", dev->function.name); ++} ++ ++static int __maybe_unused acc_bind_config(struct usb_configuration *c) ++{ ++ struct acc_dev *dev = _acc_dev; ++ int ret; ++ ++ printk(KERN_INFO "acc_bind_config\n"); ++ ++ /* allocate a string ID for our interface */ ++ if (acc_string_defs[INTERFACE_STRING_INDEX].id == 0) { ++ ret = usb_string_id(c->cdev); ++ if (ret < 0) ++ return ret; ++ acc_string_defs[INTERFACE_STRING_INDEX].id = ret; ++ acc_interface_desc.iInterface = ret; ++ } ++ ++ dev->cdev = c->cdev; ++ dev->function.name = "accessory"; ++ dev->function.strings = acc_strings, ++ dev->function.fs_descriptors = fs_acc_descs; ++ dev->function.hs_descriptors = hs_acc_descs; ++ dev->function.bind = acc_function_bind; ++ dev->function.unbind = acc_function_unbind; ++ dev->function.set_alt = acc_function_set_alt; ++ dev->function.disable = acc_function_disable; ++ ++ return usb_add_function(c, &dev->function); ++} ++ ++static int acc_setup(void) ++{ ++ struct acc_dev *dev; ++ int ret; ++ ++ dev = kzalloc(sizeof(*dev), GFP_KERNEL); ++ if (!dev) ++ return -ENOMEM; ++ ++ spin_lock_init(&dev->lock); ++ init_waitqueue_head(&dev->read_wq); ++ init_waitqueue_head(&dev->write_wq); ++ atomic_set(&dev->open_excl, 0); ++ INIT_LIST_HEAD(&dev->tx_idle); ++ INIT_LIST_HEAD(&dev->hid_list); ++ INIT_LIST_HEAD(&dev->new_hid_list); ++ INIT_LIST_HEAD(&dev->dead_hid_list); ++ INIT_DELAYED_WORK(&dev->start_work, acc_start_work); ++ INIT_WORK(&dev->hid_work, acc_hid_work); ++ ++ /* _acc_dev must be set before calling usb_gadget_register_driver */ ++ _acc_dev = dev; ++ ++ ret = misc_register(&acc_device); ++ if (ret) ++ goto err; ++ ++ return 0; ++ ++err: ++ kfree(dev); ++ pr_err("USB accessory gadget driver failed to initialize\n"); ++ return ret; ++} ++ ++void acc_disconnect(void) ++{ ++ /* unregister all HID devices if USB is disconnected */ ++ kill_all_hid_devices(_acc_dev); ++} ++EXPORT_SYMBOL_GPL(acc_disconnect); ++ ++static void acc_cleanup(void) ++{ ++ misc_deregister(&acc_device); ++ kfree(_acc_dev); ++ _acc_dev = NULL; ++} ++static struct acc_instance *to_acc_instance(struct config_item *item) ++{ ++ return container_of(to_config_group(item), struct acc_instance, ++ func_inst.group); ++} ++ ++static void acc_attr_release(struct config_item *item) ++{ ++ struct acc_instance *fi_acc = to_acc_instance(item); ++ ++ usb_put_function_instance(&fi_acc->func_inst); ++} ++ ++static struct configfs_item_operations acc_item_ops = { ++ .release = acc_attr_release, ++}; ++ ++static struct config_item_type acc_func_type = { ++ .ct_item_ops = &acc_item_ops, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static struct acc_instance *to_fi_acc(struct usb_function_instance *fi) ++{ ++ return container_of(fi, struct acc_instance, func_inst); ++} ++ ++static int acc_set_inst_name(struct usb_function_instance *fi, const char *name) ++{ ++ struct acc_instance *fi_acc; ++ char *ptr; ++ int name_len; ++ ++ name_len = strlen(name) + 1; ++ if (name_len > MAX_INST_NAME_LEN) ++ return -ENAMETOOLONG; ++ ++ ptr = kstrndup(name, name_len, GFP_KERNEL); ++ if (!ptr) ++ return -ENOMEM; ++ ++ fi_acc = to_fi_acc(fi); ++ fi_acc->name = ptr; ++ return 0; ++} ++ ++static void acc_free_inst(struct usb_function_instance *fi) ++{ ++ struct acc_instance *fi_acc; ++ ++ fi_acc = to_fi_acc(fi); ++ kfree(fi_acc->name); ++ acc_cleanup(); ++} ++ ++static struct usb_function_instance *acc_alloc_inst(void) ++{ ++ struct acc_instance *fi_acc; ++ struct acc_dev *dev; ++ int err; ++ ++ fi_acc = kzalloc(sizeof(*fi_acc), GFP_KERNEL); ++ if (!fi_acc) ++ return ERR_PTR(-ENOMEM); ++ fi_acc->func_inst.set_inst_name = acc_set_inst_name; ++ fi_acc->func_inst.free_func_inst = acc_free_inst; ++ ++ err = acc_setup(); ++ if (err) { ++ kfree(fi_acc); ++ pr_err("Error setting ACCESSORY\n"); ++ return ERR_PTR(err); ++ } ++ ++ config_group_init_type_name(&fi_acc->func_inst.group, ++ "", &acc_func_type); ++ dev = _acc_dev; ++ return &fi_acc->func_inst; ++} ++ ++static void acc_free(struct usb_function *f) ++{ ++/*NO-OP: no function specific resource allocation in mtp_alloc*/ ++} ++ ++int acc_ctrlrequest_configfs(struct usb_function *f, ++ const struct usb_ctrlrequest *ctrl) { ++ if (f->config != NULL && f->config->cdev != NULL) ++ return acc_ctrlrequest(f->config->cdev, ctrl); ++ else ++ return -1; ++} ++ ++static struct usb_function *acc_alloc(struct usb_function_instance *fi) ++{ ++ struct acc_dev *dev = _acc_dev; ++ ++ pr_info("acc_alloc\n"); ++ ++ dev->function.name = "accessory"; ++ dev->function.strings = acc_strings, ++ dev->function.fs_descriptors = fs_acc_descs; ++ dev->function.hs_descriptors = hs_acc_descs; ++ dev->function.bind = acc_function_bind_configfs; ++ dev->function.unbind = acc_function_unbind; ++ dev->function.set_alt = acc_function_set_alt; ++ dev->function.disable = acc_function_disable; ++ dev->function.free_func = acc_free; ++ dev->function.setup = acc_ctrlrequest_configfs; ++ ++ return &dev->function; ++} ++DECLARE_USB_FUNCTION_INIT(accessory, acc_alloc_inst, acc_alloc); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/usb/gadget/function/f_audio_source.c b/drivers/usb/gadget/function/f_audio_source.c +new file mode 100644 +index 0000000..39645be +--- /dev/null ++++ b/drivers/usb/gadget/function/f_audio_source.c +@@ -0,0 +1,1054 @@ ++/* ++ * Gadget Function Driver for USB audio source device ++ * ++ * Copyright (C) 2012 Google, 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. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#define SAMPLE_RATE 44100 ++#define FRAMES_PER_MSEC (SAMPLE_RATE / 1000) ++ ++#define IN_EP_MAX_PACKET_SIZE 256 ++ ++/* Number of requests to allocate */ ++#define IN_EP_REQ_COUNT 4 ++ ++#define AUDIO_AC_INTERFACE 0 ++#define AUDIO_AS_INTERFACE 1 ++#define AUDIO_NUM_INTERFACES 2 ++#define MAX_INST_NAME_LEN 40 ++ ++/* B.3.1 Standard AC Interface Descriptor */ ++static struct usb_interface_descriptor ac_interface_desc = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bNumEndpoints = 0, ++ .bInterfaceClass = USB_CLASS_AUDIO, ++ .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, ++}; ++ ++DECLARE_UAC_AC_HEADER_DESCRIPTOR(2); ++ ++#define UAC_DT_AC_HEADER_LENGTH UAC_DT_AC_HEADER_SIZE(AUDIO_NUM_INTERFACES) ++/* 1 input terminal, 1 output terminal and 1 feature unit */ ++#define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH \ ++ + UAC_DT_INPUT_TERMINAL_SIZE + UAC_DT_OUTPUT_TERMINAL_SIZE \ ++ + UAC_DT_FEATURE_UNIT_SIZE(0)) ++/* B.3.2 Class-Specific AC Interface Descriptor */ ++static struct uac1_ac_header_descriptor_2 ac_header_desc = { ++ .bLength = UAC_DT_AC_HEADER_LENGTH, ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_HEADER, ++ .bcdADC = __constant_cpu_to_le16(0x0100), ++ .wTotalLength = __constant_cpu_to_le16(UAC_DT_TOTAL_LENGTH), ++ .bInCollection = AUDIO_NUM_INTERFACES, ++ .baInterfaceNr = { ++ [0] = AUDIO_AC_INTERFACE, ++ [1] = AUDIO_AS_INTERFACE, ++ } ++}; ++ ++#define INPUT_TERMINAL_ID 1 ++static struct uac_input_terminal_descriptor input_terminal_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, ++ .wChannelConfig = 0x3, ++}; ++ ++DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(0); ++ ++#define FEATURE_UNIT_ID 2 ++static struct uac_feature_unit_descriptor_0 feature_unit_desc = { ++ .bLength = UAC_DT_FEATURE_UNIT_SIZE(0), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_FEATURE_UNIT, ++ .bUnitID = FEATURE_UNIT_ID, ++ .bSourceID = INPUT_TERMINAL_ID, ++ .bControlSize = 2, ++}; ++ ++#define OUTPUT_TERMINAL_ID 3 ++static struct uac1_output_terminal_descriptor output_terminal_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 = FEATURE_UNIT_ID, ++ .bSourceID = FEATURE_UNIT_ID, ++}; ++ ++/* B.4.1 Standard AS Interface Descriptor */ ++static struct usb_interface_descriptor as_interface_alt_0_desc = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bAlternateSetting = 0, ++ .bNumEndpoints = 0, ++ .bInterfaceClass = USB_CLASS_AUDIO, ++ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, ++}; ++ ++static struct usb_interface_descriptor as_interface_alt_1_desc = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .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_header_desc = { ++ .bLength = UAC_DT_AS_HEADER_SIZE, ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_AS_GENERAL, ++ .bTerminalLink = INPUT_TERMINAL_ID, ++ .bDelay = 1, ++ .wFormatTag = UAC_FORMAT_TYPE_I_PCM, ++}; ++ ++DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(1); ++ ++static struct uac_format_type_i_discrete_descriptor_1 as_type_i_desc = { ++ .bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_FORMAT_TYPE, ++ .bFormatType = UAC_FORMAT_TYPE_I, ++ .bSubframeSize = 2, ++ .bBitResolution = 16, ++ .bSamFreqType = 1, ++}; ++ ++/* Standard ISO IN Endpoint Descriptor for highspeed */ ++static struct usb_endpoint_descriptor hs_as_in_ep_desc = { ++ .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_IN, ++ .bmAttributes = USB_ENDPOINT_SYNC_SYNC ++ | USB_ENDPOINT_XFER_ISOC, ++ .wMaxPacketSize = __constant_cpu_to_le16(IN_EP_MAX_PACKET_SIZE), ++ .bInterval = 4, /* poll 1 per millisecond */ ++}; ++ ++/* Standard ISO IN Endpoint Descriptor for highspeed */ ++static struct usb_endpoint_descriptor fs_as_in_ep_desc = { ++ .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_IN, ++ .bmAttributes = USB_ENDPOINT_SYNC_SYNC ++ | USB_ENDPOINT_XFER_ISOC, ++ .wMaxPacketSize = __constant_cpu_to_le16(IN_EP_MAX_PACKET_SIZE), ++ .bInterval = 1, /* poll 1 per millisecond */ ++}; ++ ++/* Class-specific AS ISO OUT Endpoint Descriptor */ ++static struct uac_iso_endpoint_descriptor as_iso_in_desc = { ++ .bLength = UAC_ISO_ENDPOINT_DESC_SIZE, ++ .bDescriptorType = USB_DT_CS_ENDPOINT, ++ .bDescriptorSubtype = UAC_EP_GENERAL, ++ .bmAttributes = 1, ++ .bLockDelayUnits = 1, ++ .wLockDelay = __constant_cpu_to_le16(1), ++}; ++ ++static struct usb_descriptor_header *hs_audio_desc[] = { ++ (struct usb_descriptor_header *)&ac_interface_desc, ++ (struct usb_descriptor_header *)&ac_header_desc, ++ ++ (struct usb_descriptor_header *)&input_terminal_desc, ++ (struct usb_descriptor_header *)&output_terminal_desc, ++ (struct usb_descriptor_header *)&feature_unit_desc, ++ ++ (struct usb_descriptor_header *)&as_interface_alt_0_desc, ++ (struct usb_descriptor_header *)&as_interface_alt_1_desc, ++ (struct usb_descriptor_header *)&as_header_desc, ++ ++ (struct usb_descriptor_header *)&as_type_i_desc, ++ ++ (struct usb_descriptor_header *)&hs_as_in_ep_desc, ++ (struct usb_descriptor_header *)&as_iso_in_desc, ++ NULL, ++}; ++ ++static struct usb_descriptor_header *fs_audio_desc[] = { ++ (struct usb_descriptor_header *)&ac_interface_desc, ++ (struct usb_descriptor_header *)&ac_header_desc, ++ ++ (struct usb_descriptor_header *)&input_terminal_desc, ++ (struct usb_descriptor_header *)&output_terminal_desc, ++ (struct usb_descriptor_header *)&feature_unit_desc, ++ ++ (struct usb_descriptor_header *)&as_interface_alt_0_desc, ++ (struct usb_descriptor_header *)&as_interface_alt_1_desc, ++ (struct usb_descriptor_header *)&as_header_desc, ++ ++ (struct usb_descriptor_header *)&as_type_i_desc, ++ ++ (struct usb_descriptor_header *)&fs_as_in_ep_desc, ++ (struct usb_descriptor_header *)&as_iso_in_desc, ++ NULL, ++}; ++ ++static struct snd_pcm_hardware audio_hw_info = { ++ .info = SNDRV_PCM_INFO_MMAP | ++ SNDRV_PCM_INFO_MMAP_VALID | ++ SNDRV_PCM_INFO_BATCH | ++ SNDRV_PCM_INFO_INTERLEAVED | ++ SNDRV_PCM_INFO_BLOCK_TRANSFER, ++ ++ .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ .channels_min = 2, ++ .channels_max = 2, ++ .rate_min = SAMPLE_RATE, ++ .rate_max = SAMPLE_RATE, ++ ++ .buffer_bytes_max = 1024 * 1024, ++ .period_bytes_min = 64, ++ .period_bytes_max = 512 * 1024, ++ .periods_min = 2, ++ .periods_max = 1024, ++}; ++ ++/*-------------------------------------------------------------------------*/ ++ ++struct audio_source_config { ++ int card; ++ int device; ++}; ++ ++struct audio_dev { ++ struct usb_function func; ++ struct snd_card *card; ++ struct snd_pcm *pcm; ++ struct snd_pcm_substream *substream; ++ ++ struct list_head idle_reqs; ++ struct usb_ep *in_ep; ++ ++ spinlock_t lock; ++ ++ /* beginning, end and current position in our buffer */ ++ void *buffer_start; ++ void *buffer_end; ++ void *buffer_pos; ++ ++ /* byte size of a "period" */ ++ unsigned int period; ++ /* bytes sent since last call to snd_pcm_period_elapsed */ ++ unsigned int period_offset; ++ /* time we started playing */ ++ ktime_t start_time; ++ /* number of frames sent since start_time */ ++ s64 frames_sent; ++ struct audio_source_config *config; ++}; ++ ++static inline struct audio_dev *func_to_audio(struct usb_function *f) ++{ ++ return container_of(f, struct audio_dev, func); ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++struct audio_source_instance { ++ struct usb_function_instance func_inst; ++ const char *name; ++ struct audio_source_config *config; ++ struct device *audio_device; ++}; ++ ++static void audio_source_attr_release(struct config_item *item); ++ ++static struct configfs_item_operations audio_source_item_ops = { ++ .release = audio_source_attr_release, ++}; ++ ++static struct config_item_type audio_source_func_type = { ++ .ct_item_ops = &audio_source_item_ops, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static ssize_t audio_source_pcm_show(struct device *dev, ++ struct device_attribute *attr, char *buf); ++ ++static DEVICE_ATTR(pcm, S_IRUGO, audio_source_pcm_show, NULL); ++ ++static struct device_attribute *audio_source_function_attributes[] = { ++ &dev_attr_pcm, ++ NULL ++}; ++ ++/*--------------------------------------------------------------------------*/ ++ ++static struct usb_request *audio_request_new(struct usb_ep *ep, int buffer_size) ++{ ++ struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL); ++ if (!req) ++ return NULL; ++ ++ req->buf = kmalloc(buffer_size, GFP_KERNEL); ++ if (!req->buf) { ++ usb_ep_free_request(ep, req); ++ return NULL; ++ } ++ req->length = buffer_size; ++ return req; ++} ++ ++static void audio_request_free(struct usb_request *req, struct usb_ep *ep) ++{ ++ if (req) { ++ kfree(req->buf); ++ usb_ep_free_request(ep, req); ++ } ++} ++ ++static void audio_req_put(struct audio_dev *audio, struct usb_request *req) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&audio->lock, flags); ++ list_add_tail(&req->list, &audio->idle_reqs); ++ spin_unlock_irqrestore(&audio->lock, flags); ++} ++ ++static struct usb_request *audio_req_get(struct audio_dev *audio) ++{ ++ unsigned long flags; ++ struct usb_request *req; ++ ++ spin_lock_irqsave(&audio->lock, flags); ++ if (list_empty(&audio->idle_reqs)) { ++ req = 0; ++ } else { ++ req = list_first_entry(&audio->idle_reqs, struct usb_request, ++ list); ++ list_del(&req->list); ++ } ++ spin_unlock_irqrestore(&audio->lock, flags); ++ return req; ++} ++ ++/* send the appropriate number of packets to match our bitrate */ ++static void audio_send(struct audio_dev *audio) ++{ ++ struct snd_pcm_runtime *runtime; ++ struct usb_request *req; ++ int length, length1, length2, ret; ++ s64 msecs; ++ s64 frames; ++ ktime_t now; ++ ++ /* audio->substream will be null if we have been closed */ ++ if (!audio->substream) ++ return; ++ /* audio->buffer_pos will be null if we have been stopped */ ++ if (!audio->buffer_pos) ++ return; ++ ++ runtime = audio->substream->runtime; ++ ++ /* compute number of frames to send */ ++ now = ktime_get(); ++ msecs = ktime_to_ns(now) - ktime_to_ns(audio->start_time); ++ do_div(msecs, 1000000); ++ frames = msecs * SAMPLE_RATE; ++ do_div(frames, 1000); ++ ++ /* Readjust our frames_sent if we fall too far behind. ++ * If we get too far behind it is better to drop some frames than ++ * to keep sending data too fast in an attempt to catch up. ++ */ ++ if (frames - audio->frames_sent > 10 * FRAMES_PER_MSEC) ++ audio->frames_sent = frames - FRAMES_PER_MSEC; ++ ++ frames -= audio->frames_sent; ++ ++ /* We need to send something to keep the pipeline going */ ++ if (frames <= 0) ++ frames = FRAMES_PER_MSEC; ++ ++ while (frames > 0) { ++ req = audio_req_get(audio); ++ if (!req) ++ break; ++ ++ length = frames_to_bytes(runtime, frames); ++ if (length > IN_EP_MAX_PACKET_SIZE) ++ length = IN_EP_MAX_PACKET_SIZE; ++ ++ if (audio->buffer_pos + length > audio->buffer_end) ++ length1 = audio->buffer_end - audio->buffer_pos; ++ else ++ length1 = length; ++ memcpy(req->buf, audio->buffer_pos, length1); ++ if (length1 < length) { ++ /* Wrap around and copy remaining length ++ * at beginning of buffer. ++ */ ++ length2 = length - length1; ++ memcpy(req->buf + length1, audio->buffer_start, ++ length2); ++ audio->buffer_pos = audio->buffer_start + length2; ++ } else { ++ audio->buffer_pos += length1; ++ if (audio->buffer_pos >= audio->buffer_end) ++ audio->buffer_pos = audio->buffer_start; ++ } ++ ++ req->length = length; ++ ret = usb_ep_queue(audio->in_ep, req, GFP_ATOMIC); ++ if (ret < 0) { ++ pr_err("usb_ep_queue failed ret: %d\n", ret); ++ audio_req_put(audio, req); ++ break; ++ } ++ ++ frames -= bytes_to_frames(runtime, length); ++ audio->frames_sent += bytes_to_frames(runtime, length); ++ } ++} ++ ++static void audio_control_complete(struct usb_ep *ep, struct usb_request *req) ++{ ++ /* nothing to do here */ ++} ++ ++static void audio_data_complete(struct usb_ep *ep, struct usb_request *req) ++{ ++ struct audio_dev *audio = req->context; ++ ++ pr_debug("audio_data_complete req->status %d req->actual %d\n", ++ req->status, req->actual); ++ ++ audio_req_put(audio, req); ++ ++ if (!audio->buffer_start || req->status) ++ return; ++ ++ audio->period_offset += req->actual; ++ if (audio->period_offset >= audio->period) { ++ snd_pcm_period_elapsed(audio->substream); ++ audio->period_offset = 0; ++ } ++ audio_send(audio); ++} ++ ++static int audio_set_endpoint_req(struct usb_function *f, ++ const struct usb_ctrlrequest *ctrl) ++{ ++ int value = -EOPNOTSUPP; ++ u16 ep = le16_to_cpu(ctrl->wIndex); ++ u16 len = le16_to_cpu(ctrl->wLength); ++ u16 w_value = le16_to_cpu(ctrl->wValue); ++ ++ pr_debug("bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n", ++ ctrl->bRequest, w_value, len, ep); ++ ++ switch (ctrl->bRequest) { ++ case UAC_SET_CUR: ++ case UAC_SET_MIN: ++ case UAC_SET_MAX: ++ case UAC_SET_RES: ++ value = len; ++ break; ++ default: ++ break; ++ } ++ ++ return value; ++} ++ ++static int audio_get_endpoint_req(struct usb_function *f, ++ const struct usb_ctrlrequest *ctrl) ++{ ++ struct usb_composite_dev *cdev = f->config->cdev; ++ int value = -EOPNOTSUPP; ++ u8 ep = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF); ++ u16 len = le16_to_cpu(ctrl->wLength); ++ u16 w_value = le16_to_cpu(ctrl->wValue); ++ u8 *buf = cdev->req->buf; ++ ++ pr_debug("bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n", ++ ctrl->bRequest, w_value, len, ep); ++ ++ if (w_value == UAC_EP_CS_ATTR_SAMPLE_RATE << 8) { ++ switch (ctrl->bRequest) { ++ case UAC_GET_CUR: ++ case UAC_GET_MIN: ++ case UAC_GET_MAX: ++ case UAC_GET_RES: ++ /* return our sample rate */ ++ buf[0] = (u8)SAMPLE_RATE; ++ buf[1] = (u8)(SAMPLE_RATE >> 8); ++ buf[2] = (u8)(SAMPLE_RATE >> 16); ++ value = 3; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ return value; ++} ++ ++static int ++audio_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); ++ ++ /* composite driver infrastructure handles everything; interface ++ * activation uses set_alt(). ++ */ ++ switch (ctrl->bRequestType) { ++ case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: ++ value = audio_set_endpoint_req(f, ctrl); ++ break; ++ ++ case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: ++ value = audio_get_endpoint_req(f, ctrl); ++ break; ++ } ++ ++ /* respond with data transfer or status phase? */ ++ if (value >= 0) { ++ pr_debug("audio req%02x.%02x v%04x i%04x l%d\n", ++ ctrl->bRequestType, ctrl->bRequest, ++ w_value, w_index, w_length); ++ req->zero = 0; ++ req->length = value; ++ req->complete = audio_control_complete; ++ value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); ++ if (value < 0) ++ pr_err("audio response on err %d\n", value); ++ } ++ ++ /* device either stalls (value < 0) or reports success */ ++ return value; ++} ++ ++static int audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt) ++{ ++ struct audio_dev *audio = func_to_audio(f); ++ struct usb_composite_dev *cdev = f->config->cdev; ++ int ret; ++ ++ pr_debug("audio_set_alt intf %d, alt %d\n", intf, alt); ++ ++ ret = config_ep_by_speed(cdev->gadget, f, audio->in_ep); ++ if (ret) ++ return ret; ++ ++ usb_ep_enable(audio->in_ep); ++ return 0; ++} ++ ++static void audio_disable(struct usb_function *f) ++{ ++ struct audio_dev *audio = func_to_audio(f); ++ ++ pr_debug("audio_disable\n"); ++ usb_ep_disable(audio->in_ep); ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static void audio_build_desc(struct audio_dev *audio) ++{ ++ u8 *sam_freq; ++ int rate; ++ ++ /* Set channel numbers */ ++ input_terminal_desc.bNrChannels = 2; ++ as_type_i_desc.bNrChannels = 2; ++ ++ /* Set sample rates */ ++ rate = SAMPLE_RATE; ++ sam_freq = as_type_i_desc.tSamFreq[0]; ++ memcpy(sam_freq, &rate, 3); ++} ++ ++ ++static int snd_card_setup(struct usb_configuration *c, ++ struct audio_source_config *config); ++static struct audio_source_instance *to_fi_audio_source( ++ const struct usb_function_instance *fi); ++ ++ ++/* audio function driver setup/binding */ ++static int ++audio_bind(struct usb_configuration *c, struct usb_function *f) ++{ ++ struct usb_composite_dev *cdev = c->cdev; ++ struct audio_dev *audio = func_to_audio(f); ++ int status; ++ struct usb_ep *ep; ++ struct usb_request *req; ++ int i; ++ int err; ++ ++ if (IS_ENABLED(CONFIG_USB_CONFIGFS)) { ++ struct audio_source_instance *fi_audio = ++ to_fi_audio_source(f->fi); ++ struct audio_source_config *config = ++ fi_audio->config; ++ ++ err = snd_card_setup(c, config); ++ if (err) ++ return err; ++ } ++ ++ audio_build_desc(audio); ++ ++ /* allocate instance-specific interface IDs, and patch descriptors */ ++ status = usb_interface_id(c, f); ++ if (status < 0) ++ goto fail; ++ ac_interface_desc.bInterfaceNumber = status; ++ ++ /* AUDIO_AC_INTERFACE */ ++ ac_header_desc.baInterfaceNr[0] = status; ++ ++ status = usb_interface_id(c, f); ++ if (status < 0) ++ goto fail; ++ as_interface_alt_0_desc.bInterfaceNumber = status; ++ as_interface_alt_1_desc.bInterfaceNumber = status; ++ ++ /* AUDIO_AS_INTERFACE */ ++ ac_header_desc.baInterfaceNr[1] = status; ++ ++ status = -ENODEV; ++ ++ /* allocate our endpoint */ ++ ep = usb_ep_autoconfig(cdev->gadget, &fs_as_in_ep_desc); ++ if (!ep) ++ goto fail; ++ audio->in_ep = ep; ++ ep->driver_data = audio; /* claim */ ++ ++ if (gadget_is_dualspeed(c->cdev->gadget)) ++ hs_as_in_ep_desc.bEndpointAddress = ++ fs_as_in_ep_desc.bEndpointAddress; ++ ++ f->fs_descriptors = fs_audio_desc; ++ f->hs_descriptors = hs_audio_desc; ++ ++ for (i = 0, status = 0; i < IN_EP_REQ_COUNT && status == 0; i++) { ++ req = audio_request_new(ep, IN_EP_MAX_PACKET_SIZE); ++ if (req) { ++ req->context = audio; ++ req->complete = audio_data_complete; ++ audio_req_put(audio, req); ++ } else ++ status = -ENOMEM; ++ } ++ ++fail: ++ return status; ++} ++ ++static void ++audio_unbind(struct usb_configuration *c, struct usb_function *f) ++{ ++ struct audio_dev *audio = func_to_audio(f); ++ struct usb_request *req; ++ ++ while ((req = audio_req_get(audio))) ++ audio_request_free(req, audio->in_ep); ++ ++ snd_card_free_when_closed(audio->card); ++ audio->card = NULL; ++ audio->pcm = NULL; ++ audio->substream = NULL; ++ audio->in_ep = NULL; ++ ++ if (IS_ENABLED(CONFIG_USB_CONFIGFS)) { ++ struct audio_source_instance *fi_audio = ++ to_fi_audio_source(f->fi); ++ struct audio_source_config *config = ++ fi_audio->config; ++ ++ config->card = -1; ++ config->device = -1; ++ } ++} ++ ++static void audio_pcm_playback_start(struct audio_dev *audio) ++{ ++ audio->start_time = ktime_get(); ++ audio->frames_sent = 0; ++ audio_send(audio); ++} ++ ++static void audio_pcm_playback_stop(struct audio_dev *audio) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&audio->lock, flags); ++ audio->buffer_start = 0; ++ audio->buffer_end = 0; ++ audio->buffer_pos = 0; ++ spin_unlock_irqrestore(&audio->lock, flags); ++} ++ ++static int audio_pcm_open(struct snd_pcm_substream *substream) ++{ ++ struct snd_pcm_runtime *runtime = substream->runtime; ++ struct audio_dev *audio = substream->private_data; ++ ++ runtime->private_data = audio; ++ runtime->hw = audio_hw_info; ++ snd_pcm_limit_hw_rates(runtime); ++ runtime->hw.channels_max = 2; ++ ++ audio->substream = substream; ++ return 0; ++} ++ ++static int audio_pcm_close(struct snd_pcm_substream *substream) ++{ ++ struct audio_dev *audio = substream->private_data; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&audio->lock, flags); ++ audio->substream = NULL; ++ spin_unlock_irqrestore(&audio->lock, flags); ++ ++ return 0; ++} ++ ++static int audio_pcm_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ unsigned int channels = params_channels(params); ++ unsigned int rate = params_rate(params); ++ ++ if (rate != SAMPLE_RATE) ++ return -EINVAL; ++ if (channels != 2) ++ return -EINVAL; ++ ++ return snd_pcm_lib_alloc_vmalloc_buffer(substream, ++ params_buffer_bytes(params)); ++} ++ ++static int audio_pcm_hw_free(struct snd_pcm_substream *substream) ++{ ++ return snd_pcm_lib_free_vmalloc_buffer(substream); ++} ++ ++static int audio_pcm_prepare(struct snd_pcm_substream *substream) ++{ ++ struct snd_pcm_runtime *runtime = substream->runtime; ++ struct audio_dev *audio = runtime->private_data; ++ ++ audio->period = snd_pcm_lib_period_bytes(substream); ++ audio->period_offset = 0; ++ audio->buffer_start = runtime->dma_area; ++ audio->buffer_end = audio->buffer_start ++ + snd_pcm_lib_buffer_bytes(substream); ++ audio->buffer_pos = audio->buffer_start; ++ ++ return 0; ++} ++ ++static snd_pcm_uframes_t audio_pcm_pointer(struct snd_pcm_substream *substream) ++{ ++ struct snd_pcm_runtime *runtime = substream->runtime; ++ struct audio_dev *audio = runtime->private_data; ++ ssize_t bytes = audio->buffer_pos - audio->buffer_start; ++ ++ /* return offset of next frame to fill in our buffer */ ++ return bytes_to_frames(runtime, bytes); ++} ++ ++static int audio_pcm_playback_trigger(struct snd_pcm_substream *substream, ++ int cmd) ++{ ++ struct audio_dev *audio = substream->runtime->private_data; ++ int ret = 0; ++ ++ switch (cmd) { ++ case SNDRV_PCM_TRIGGER_START: ++ case SNDRV_PCM_TRIGGER_RESUME: ++ audio_pcm_playback_start(audio); ++ break; ++ ++ case SNDRV_PCM_TRIGGER_STOP: ++ case SNDRV_PCM_TRIGGER_SUSPEND: ++ audio_pcm_playback_stop(audio); ++ break; ++ ++ default: ++ ret = -EINVAL; ++ } ++ ++ return ret; ++} ++ ++static struct audio_dev _audio_dev = { ++ .func = { ++ .name = "audio_source", ++ .bind = audio_bind, ++ .unbind = audio_unbind, ++ .set_alt = audio_set_alt, ++ .setup = audio_setup, ++ .disable = audio_disable, ++ }, ++ .lock = __SPIN_LOCK_UNLOCKED(_audio_dev.lock), ++ .idle_reqs = LIST_HEAD_INIT(_audio_dev.idle_reqs), ++}; ++ ++static struct snd_pcm_ops audio_playback_ops = { ++ .open = audio_pcm_open, ++ .close = audio_pcm_close, ++ .ioctl = snd_pcm_lib_ioctl, ++ .hw_params = audio_pcm_hw_params, ++ .hw_free = audio_pcm_hw_free, ++ .prepare = audio_pcm_prepare, ++ .trigger = audio_pcm_playback_trigger, ++ .pointer = audio_pcm_pointer, ++}; ++ ++int audio_source_bind_config(struct usb_configuration *c, ++ struct audio_source_config *config) ++{ ++ struct audio_dev *audio; ++ int err; ++ ++ config->card = -1; ++ config->device = -1; ++ ++ audio = &_audio_dev; ++ ++ err = snd_card_setup(c, config); ++ if (err) ++ return err; ++ ++ err = usb_add_function(c, &audio->func); ++ if (err) ++ goto add_fail; ++ ++ return 0; ++ ++add_fail: ++ snd_card_free(audio->card); ++ return err; ++} ++ ++static int snd_card_setup(struct usb_configuration *c, ++ struct audio_source_config *config) ++{ ++ struct audio_dev *audio; ++ struct snd_card *card; ++ struct snd_pcm *pcm; ++ int err; ++ ++ audio = &_audio_dev; ++ ++ err = snd_card_new(&c->cdev->gadget->dev, ++ SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, ++ THIS_MODULE, 0, &card); ++ if (err) ++ return err; ++ ++ err = snd_pcm_new(card, "USB audio source", 0, 1, 0, &pcm); ++ if (err) ++ goto pcm_fail; ++ ++ pcm->private_data = audio; ++ pcm->info_flags = 0; ++ audio->pcm = pcm; ++ ++ strlcpy(pcm->name, "USB gadget audio", sizeof(pcm->name)); ++ ++ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &audio_playback_ops); ++ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, ++ NULL, 0, 64 * 1024); ++ ++ strlcpy(card->driver, "audio_source", sizeof(card->driver)); ++ strlcpy(card->shortname, card->driver, sizeof(card->shortname)); ++ strlcpy(card->longname, "USB accessory audio source", ++ sizeof(card->longname)); ++ ++ err = snd_card_register(card); ++ if (err) ++ goto register_fail; ++ ++ config->card = pcm->card->number; ++ config->device = pcm->device; ++ audio->card = card; ++ return 0; ++ ++register_fail: ++pcm_fail: ++ snd_card_free(audio->card); ++ return err; ++} ++ ++static struct audio_source_instance *to_audio_source_instance( ++ struct config_item *item) ++{ ++ return container_of(to_config_group(item), struct audio_source_instance, ++ func_inst.group); ++} ++ ++static struct audio_source_instance *to_fi_audio_source( ++ const struct usb_function_instance *fi) ++{ ++ return container_of(fi, struct audio_source_instance, func_inst); ++} ++ ++static void audio_source_attr_release(struct config_item *item) ++{ ++ struct audio_source_instance *fi_audio = to_audio_source_instance(item); ++ ++ usb_put_function_instance(&fi_audio->func_inst); ++} ++ ++static int audio_source_set_inst_name(struct usb_function_instance *fi, ++ const char *name) ++{ ++ struct audio_source_instance *fi_audio; ++ char *ptr; ++ int name_len; ++ ++ name_len = strlen(name) + 1; ++ if (name_len > MAX_INST_NAME_LEN) ++ return -ENAMETOOLONG; ++ ++ ptr = kstrndup(name, name_len, GFP_KERNEL); ++ if (!ptr) ++ return -ENOMEM; ++ ++ fi_audio = to_fi_audio_source(fi); ++ fi_audio->name = ptr; ++ ++ return 0; ++} ++ ++static void audio_source_free_inst(struct usb_function_instance *fi) ++{ ++ struct audio_source_instance *fi_audio; ++ ++ fi_audio = to_fi_audio_source(fi); ++ device_destroy(fi_audio->audio_device->class, ++ fi_audio->audio_device->devt); ++ kfree(fi_audio->name); ++ kfree(fi_audio->config); ++} ++ ++static ssize_t audio_source_pcm_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct audio_source_instance *fi_audio = dev_get_drvdata(dev); ++ struct audio_source_config *config = fi_audio->config; ++ ++ /* print PCM card and device numbers */ ++ return sprintf(buf, "%d %d\n", config->card, config->device); ++} ++ ++struct device *create_function_device(char *name); ++ ++static struct usb_function_instance *audio_source_alloc_inst(void) ++{ ++ struct audio_source_instance *fi_audio; ++ struct device_attribute **attrs; ++ struct device_attribute *attr; ++ struct device *dev; ++ void *err_ptr; ++ int err = 0; ++ ++ fi_audio = kzalloc(sizeof(*fi_audio), GFP_KERNEL); ++ if (!fi_audio) ++ return ERR_PTR(-ENOMEM); ++ ++ fi_audio->func_inst.set_inst_name = audio_source_set_inst_name; ++ fi_audio->func_inst.free_func_inst = audio_source_free_inst; ++ ++ fi_audio->config = kzalloc(sizeof(struct audio_source_config), ++ GFP_KERNEL); ++ if (!fi_audio->config) { ++ err_ptr = ERR_PTR(-ENOMEM); ++ goto fail_audio; ++ } ++ ++ config_group_init_type_name(&fi_audio->func_inst.group, "", ++ &audio_source_func_type); ++ dev = create_function_device("f_audio_source"); ++ ++ if (IS_ERR(dev)) { ++ err_ptr = dev; ++ goto fail_audio_config; ++ } ++ ++ fi_audio->config->card = -1; ++ fi_audio->config->device = -1; ++ fi_audio->audio_device = dev; ++ ++ attrs = audio_source_function_attributes; ++ if (attrs) { ++ while ((attr = *attrs++) && !err) ++ err = device_create_file(dev, attr); ++ if (err) { ++ err_ptr = ERR_PTR(-EINVAL); ++ goto fail_device; ++ } ++ } ++ ++ dev_set_drvdata(dev, fi_audio); ++ _audio_dev.config = fi_audio->config; ++ ++ return &fi_audio->func_inst; ++ ++fail_device: ++ device_destroy(dev->class, dev->devt); ++fail_audio_config: ++ kfree(fi_audio->config); ++fail_audio: ++ kfree(fi_audio); ++ return err_ptr; ++ ++} ++ ++static struct usb_function *audio_source_alloc(struct usb_function_instance *fi) ++{ ++ return &_audio_dev.func; ++} ++ ++DECLARE_USB_FUNCTION_INIT(audio_source, audio_source_alloc_inst, ++ audio_source_alloc); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c +index ab9b7ac..45207e2 100644 +--- a/drivers/usb/gadget/function/f_fs.c ++++ b/drivers/usb/gadget/function/f_fs.c +@@ -86,12 +86,15 @@ ffs_setup_state_clear_cancelled(struct ffs_data *ffs) + cmpxchg(&ffs->setup_state, FFS_SETUP_CANCELLED, FFS_NO_SETUP); + } + ++static void ffs_func_free(struct ffs_function *func); + + static void ffs_func_eps_disable(struct ffs_function *func); + static int __must_check ffs_func_eps_enable(struct ffs_function *func); + + static int ffs_func_bind(struct usb_configuration *, + struct usb_function *); ++static void old_ffs_func_unbind(struct usb_configuration *, ++ struct usb_function *); + static int ffs_func_set_alt(struct usb_function *, unsigned, unsigned); + static void ffs_func_disable(struct usb_function *); + static int ffs_func_setup(struct usb_function *, +@@ -1616,6 +1619,71 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count) + kfree(epfiles); + } + ++static int functionfs_bind_config(struct usb_composite_dev *cdev, ++ struct usb_configuration *c, ++ struct ffs_data *ffs) ++{ ++ struct ffs_function *func; ++ int ret; ++ ++ ENTER(); ++ ++ func = kzalloc(sizeof *func, GFP_KERNEL); ++ if (unlikely(!func)) ++ return -ENOMEM; ++ ++ func->function.name = "Function FS Gadget"; ++ func->function.strings = ffs->stringtabs; ++ ++ func->function.bind = ffs_func_bind; ++ func->function.unbind = old_ffs_func_unbind; ++ func->function.set_alt = ffs_func_set_alt; ++ func->function.disable = ffs_func_disable; ++ func->function.setup = ffs_func_setup; ++ func->function.suspend = ffs_func_suspend; ++ func->function.resume = ffs_func_resume; ++ ++ func->conf = c; ++ func->gadget = cdev->gadget; ++ func->ffs = ffs; ++ ffs_data_get(ffs); ++ ++ ret = usb_add_function(c, &func->function); ++ if (unlikely(ret)) ++ ffs_func_free(func); ++ ++ return ret; ++} ++ ++static void ffs_func_free(struct ffs_function *func) ++{ ++ struct ffs_ep *ep = func->eps; ++ unsigned count = func->ffs->eps_count; ++ unsigned long flags; ++ ++ ENTER(); ++ ++ /* cleanup after autoconfig */ ++ spin_lock_irqsave(&func->ffs->eps_lock, flags); ++ do { ++ if (ep->ep && ep->req) ++ usb_ep_free_request(ep->ep, ep->req); ++ ep->req = NULL; ++ ++ep; ++ } while (--count); ++ spin_unlock_irqrestore(&func->ffs->eps_lock, flags); ++ ++ ffs_data_put(func->ffs); ++ ++ kfree(func->eps); ++ /* ++ * eps and interfaces_nums are allocated in the same chunk so ++ * only one free is required. Descriptors are also allocated ++ * in the same chunk. ++ */ ++ ++ kfree(func); ++} + + static void ffs_func_eps_disable(struct ffs_function *func) + { +@@ -2888,6 +2956,24 @@ static int ffs_func_bind(struct usb_configuration *c, + + /* Other USB function hooks *************************************************/ + ++static void old_ffs_func_unbind(struct usb_configuration *c, ++ struct usb_function *f) ++{ ++ struct ffs_function *func = ffs_func_from_usb(f); ++ struct ffs_data *ffs = func->ffs; ++ ++ ENTER(); ++ ++ if (ffs->func == func) { ++ ffs_func_eps_disable(func); ++ ffs->func = NULL; ++ } ++ ++ ffs_event_add(ffs, FUNCTIONFS_UNBIND); ++ ++ ffs_func_free(func); ++} ++ + static int ffs_func_set_alt(struct usb_function *f, + unsigned interface, unsigned alt) + { +diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c +index 59ab62c..6f71a69 100644 +--- a/drivers/usb/gadget/function/f_hid.c ++++ b/drivers/usb/gadget/function/f_hid.c +@@ -373,8 +373,9 @@ static int hidg_setup(struct usb_function *f, + value = __le16_to_cpu(ctrl->wValue); + length = __le16_to_cpu(ctrl->wLength); + +- VDBG(cdev, "hid_setup crtl_request : bRequestType:0x%x bRequest:0x%x " +- "Value:0x%x\n", ctrl->bRequestType, ctrl->bRequest, value); ++ VDBG(cdev, ++ "%s crtl_request : bRequestType:0x%x bRequest:0x%x Value:0x%x\n", ++ __func__, ctrl->bRequestType, ctrl->bRequest, value); + + switch ((ctrl->bRequestType << 8) | ctrl->bRequest) { + case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 +diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c +index 811929c..e4d3f6a 100644 +--- a/drivers/usb/gadget/function/f_mass_storage.c ++++ b/drivers/usb/gadget/function/f_mass_storage.c +@@ -253,6 +253,7 @@ static struct usb_gadget_strings *fsg_strings_array[] = { + + struct fsg_dev; + struct fsg_common; ++extern void hisi_switch_func(int otg); + + /* Data shared by all the FSG instances. */ + struct fsg_common { +@@ -1935,6 +1936,9 @@ static int do_scsi_command(struct fsg_common *common) + "READ CAPACITY"); + if (reply == 0) + reply = do_read_capacity(common, bh); ++ ++ hisi_switch_func(1); ++ + break; + + case READ_HEADER: +@@ -1978,6 +1982,9 @@ static int do_scsi_command(struct fsg_common *common) + "REQUEST SENSE"); + if (reply == 0) + reply = do_request_sense(common, bh); ++ ++ hisi_switch_func(1); ++ + break; + + case START_STOP: +diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c +index 807b31c..ee1bfc9 100644 +--- a/drivers/usb/gadget/function/f_midi.c ++++ b/drivers/usb/gadget/function/f_midi.c +@@ -20,6 +20,7 @@ + */ + + #include ++#include + #include + #include + +@@ -33,6 +34,7 @@ + #include + + #include "u_f.h" ++#include "u_midi.h" + + MODULE_AUTHOR("Ben Williamson"); + MODULE_LICENSE("GPL v2"); +@@ -99,7 +101,7 @@ DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1); + DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16); + + /* B.3.1 Standard AC Interface Descriptor */ +-static struct usb_interface_descriptor ac_interface_desc __initdata = { ++static struct usb_interface_descriptor ac_interface_desc = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + /* .bInterfaceNumber = DYNAMIC */ +@@ -110,7 +112,7 @@ static struct usb_interface_descriptor ac_interface_desc __initdata = { + }; + + /* B.3.2 Class-Specific AC Interface Descriptor */ +-static struct uac1_ac_header_descriptor_1 ac_header_desc __initdata = { ++static struct uac1_ac_header_descriptor_1 ac_header_desc = { + .bLength = UAC_DT_AC_HEADER_SIZE(1), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubtype = USB_MS_HEADER, +@@ -121,7 +123,7 @@ static struct uac1_ac_header_descriptor_1 ac_header_desc __initdata = { + }; + + /* B.4.1 Standard MS Interface Descriptor */ +-static struct usb_interface_descriptor ms_interface_desc __initdata = { ++static struct usb_interface_descriptor ms_interface_desc = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + /* .bInterfaceNumber = DYNAMIC */ +@@ -132,7 +134,7 @@ static struct usb_interface_descriptor ms_interface_desc __initdata = { + }; + + /* B.4.2 Class-Specific MS Interface Descriptor */ +-static struct usb_ms_header_descriptor ms_header_desc __initdata = { ++static struct usb_ms_header_descriptor ms_header_desc = { + .bLength = USB_DT_MS_HEADER_SIZE, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubtype = USB_MS_HEADER, +@@ -327,6 +329,10 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt) + unsigned i; + int err; + ++ /* For Control Device interface we do nothing */ ++ if (intf == 0) ++ return 0; ++ + err = f_midi_start_ep(midi, f, midi->in_ep); + if (err) + return err; +@@ -387,29 +393,6 @@ static void f_midi_disable(struct usb_function *f) + usb_ep_disable(midi->out_ep); + } + +-static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f) +-{ +- struct usb_composite_dev *cdev = f->config->cdev; +- struct f_midi *midi = func_to_midi(f); +- struct snd_card *card; +- +- DBG(cdev, "unbind\n"); +- +- /* just to be sure */ +- f_midi_disable(f); +- +- card = midi->card; +- midi->card = NULL; +- if (card) +- snd_card_free(card); +- +- kfree(midi->id); +- midi->id = NULL; +- +- usb_free_all_descriptors(f); +- kfree(midi); +-} +- + static int f_midi_snd_free(struct snd_device *device) + { + return 0; +@@ -541,7 +524,7 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req) + req = midi_alloc_ep_req(ep, midi->buflen); + + if (!req) { +- ERROR(midi, "gmidi_transmit: alloc_ep_request failed\n"); ++ ERROR(midi, "%s: alloc_ep_request failed\n", __func__); + return; + } + req->length = 0; +@@ -654,6 +637,14 @@ static struct snd_rawmidi_ops gmidi_out_ops = { + .trigger = f_midi_out_trigger + }; + ++static inline void f_midi_unregister_card(struct f_midi *midi) ++{ ++ if (midi->card) { ++ snd_card_free(midi->card); ++ midi->card = NULL; ++ } ++} ++ + /* register as a sound "card" */ + static int f_midi_register_card(struct f_midi *midi) + { +@@ -715,17 +706,13 @@ static int f_midi_register_card(struct f_midi *midi) + return 0; + + fail: +- if (midi->card) { +- snd_card_free(midi->card); +- midi->card = NULL; +- } ++ f_midi_unregister_card(midi); + return err; + } + + /* MIDI function driver setup/binding */ + +-static int __init +-f_midi_bind(struct usb_configuration *c, struct usb_function *f) ++static int f_midi_bind(struct usb_configuration *c, struct usb_function *f) + { + struct usb_descriptor_header **midi_function; + struct usb_midi_in_jack_descriptor jack_in_ext_desc[MAX_PORTS]; +@@ -734,15 +721,23 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f) + struct usb_midi_out_jack_descriptor_1 jack_out_emb_desc[MAX_PORTS]; + struct usb_composite_dev *cdev = c->cdev; + struct f_midi *midi = func_to_midi(f); ++ struct usb_string *us; + int status, n, jack = 1, i = 0; + ++ midi->gadget = cdev->gadget; ++ tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi); ++ status = f_midi_register_card(midi); ++ if (status < 0) ++ goto fail_register; ++ + /* maybe allocate device-global string ID */ +- if (midi_string_defs[0].id == 0) { +- status = usb_string_id(c->cdev); +- if (status < 0) +- goto fail; +- midi_string_defs[0].id = status; ++ us = usb_gstrings_attach(c->cdev, midi_strings, ++ ARRAY_SIZE(midi_string_defs)); ++ if (IS_ERR(us)) { ++ status = PTR_ERR(us); ++ goto fail; + } ++ ac_interface_desc.iInterface = us[STRING_FUNC_IDX].id; + + /* We have two interfaces, AudioControl and MIDIStreaming */ + status = usb_interface_id(c, f); +@@ -892,6 +887,8 @@ fail_f_midi: + kfree(midi_function); + usb_free_descriptors(f->hs_descriptors); + fail: ++ f_midi_unregister_card(midi); ++fail_register: + /* we might as well release our claims on endpoints */ + if (midi->out_ep) + midi->out_ep->driver_data = NULL; +@@ -903,42 +900,305 @@ fail: + return status; + } + +-/** +- * f_midi_bind_config - add USB MIDI function to a configuration +- * @c: the configuration to supcard the USB audio function +- * @index: the soundcard index to use for the ALSA device creation +- * @id: the soundcard id to use for the ALSA device creation +- * @buflen: the buffer length to use +- * @qlen the number of read requests to pre-allocate +- * Context: single threaded during gadget setup +- * +- * Returns zero on success, else negative errno. +- */ +-int __init f_midi_bind_config(struct usb_configuration *c, +- int index, char *id, +- unsigned int in_ports, +- unsigned int out_ports, +- unsigned int buflen, +- unsigned int qlen) ++static inline struct f_midi_opts *to_f_midi_opts(struct config_item *item) ++{ ++ return container_of(to_config_group(item), struct f_midi_opts, ++ func_inst.group); ++} ++ ++CONFIGFS_ATTR_STRUCT(f_midi_opts); ++CONFIGFS_ATTR_OPS(f_midi_opts); ++ ++static void midi_attr_release(struct config_item *item) ++{ ++ struct f_midi_opts *opts = to_f_midi_opts(item); ++ ++ usb_put_function_instance(&opts->func_inst); ++} ++ ++static struct configfs_item_operations midi_item_ops = { ++ .release = midi_attr_release, ++ .show_attribute = f_midi_opts_attr_show, ++ .store_attribute = f_midi_opts_attr_store, ++}; ++ ++#define F_MIDI_OPT(name, test_limit, limit) \ ++static ssize_t f_midi_opts_##name##_show(struct f_midi_opts *opts, char *page) \ ++{ \ ++ int result; \ ++ \ ++ mutex_lock(&opts->lock); \ ++ result = sprintf(page, "%d\n", opts->name); \ ++ mutex_unlock(&opts->lock); \ ++ \ ++ return result; \ ++} \ ++ \ ++static ssize_t f_midi_opts_##name##_store(struct f_midi_opts *opts, \ ++ const char *page, size_t len) \ ++{ \ ++ int ret; \ ++ u32 num; \ ++ \ ++ mutex_lock(&opts->lock); \ ++ if (opts->refcnt) { \ ++ ret = -EBUSY; \ ++ goto end; \ ++ } \ ++ \ ++ ret = kstrtou32(page, 0, &num); \ ++ if (ret) \ ++ goto end; \ ++ \ ++ if (test_limit && num > limit) { \ ++ ret = -EINVAL; \ ++ goto end; \ ++ } \ ++ opts->name = num; \ ++ ret = len; \ ++ \ ++end: \ ++ mutex_unlock(&opts->lock); \ ++ return ret; \ ++} \ ++ \ ++static struct f_midi_opts_attribute f_midi_opts_##name = \ ++ __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, f_midi_opts_##name##_show, \ ++ f_midi_opts_##name##_store) ++ ++F_MIDI_OPT(index, true, SNDRV_CARDS); ++F_MIDI_OPT(buflen, false, 0); ++F_MIDI_OPT(qlen, false, 0); ++F_MIDI_OPT(in_ports, true, MAX_PORTS); ++F_MIDI_OPT(out_ports, true, MAX_PORTS); ++ ++static ssize_t f_midi_opts_id_show(struct f_midi_opts *opts, char *page) ++{ ++ int result; ++ ++ mutex_lock(&opts->lock); ++ if (opts->id) { ++ result = strlcpy(page, opts->id, PAGE_SIZE); ++ } else { ++ page[0] = 0; ++ result = 0; ++ } ++ ++ mutex_unlock(&opts->lock); ++ ++ return result; ++} ++ ++static ssize_t f_midi_opts_id_store(struct f_midi_opts *opts, ++ const char *page, size_t len) ++{ ++ int ret; ++ char *c; ++ ++ mutex_lock(&opts->lock); ++ if (opts->refcnt) { ++ ret = -EBUSY; ++ goto end; ++ } ++ ++ c = kstrndup(page, len, GFP_KERNEL); ++ if (!c) { ++ ret = -ENOMEM; ++ goto end; ++ } ++ if (opts->id_allocated) ++ kfree(opts->id); ++ opts->id = c; ++ opts->id_allocated = true; ++ ret = len; ++end: ++ mutex_unlock(&opts->lock); ++ return ret; ++} ++ ++static struct f_midi_opts_attribute f_midi_opts_id = ++ __CONFIGFS_ATTR(id, S_IRUGO | S_IWUSR, f_midi_opts_id_show, ++ f_midi_opts_id_store); ++ ++static struct configfs_attribute *midi_attrs[] = { ++ &f_midi_opts_index.attr, ++ &f_midi_opts_buflen.attr, ++ &f_midi_opts_qlen.attr, ++ &f_midi_opts_in_ports.attr, ++ &f_midi_opts_out_ports.attr, ++ &f_midi_opts_id.attr, ++ NULL, ++}; ++ ++static struct config_item_type midi_func_type = { ++ .ct_item_ops = &midi_item_ops, ++ .ct_attrs = midi_attrs, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static void f_midi_free_inst(struct usb_function_instance *f) ++{ ++ struct f_midi_opts *opts; ++ ++ opts = container_of(f, struct f_midi_opts, func_inst); ++ ++ if (opts->id_allocated) ++ kfree(opts->id); ++ ++ kfree(opts); ++} ++ ++#ifdef CONFIG_USB_CONFIGFS_UEVENT ++extern struct device *create_function_device(char *name); ++static ssize_t alsa_show(struct device *dev, ++ struct device_attribute *attr, char *buf) + { ++ struct usb_function_instance *fi_midi = dev_get_drvdata(dev); + struct f_midi *midi; ++ ++ if (!fi_midi->f) ++ dev_warn(dev, "f_midi: function not set\n"); ++ ++ if (fi_midi && fi_midi->f) { ++ midi = func_to_midi(fi_midi->f); ++ if (midi->rmidi && midi->rmidi->card) ++ return sprintf(buf, "%d %d\n", ++ midi->rmidi->card->number, midi->rmidi->device); ++ } ++ ++ /* print PCM card and device numbers */ ++ return sprintf(buf, "%d %d\n", -1, -1); ++} ++ ++static DEVICE_ATTR(alsa, S_IRUGO, alsa_show, NULL); ++ ++static struct device_attribute *alsa_function_attributes[] = { ++ &dev_attr_alsa, ++ NULL ++}; ++ ++static int create_alsa_device(struct usb_function_instance *fi) ++{ ++ struct device *dev; ++ struct device_attribute **attrs; ++ struct device_attribute *attr; ++ int err = 0; ++ ++ dev = create_function_device("f_midi"); ++ if (IS_ERR(dev)) ++ return PTR_ERR(dev); ++ ++ attrs = alsa_function_attributes; ++ if (attrs) { ++ while ((attr = *attrs++) && !err) ++ err = device_create_file(dev, attr); ++ if (err) { ++ device_destroy(dev->class, dev->devt); ++ return -EINVAL; ++ } ++ } ++ dev_set_drvdata(dev, fi); ++ return 0; ++} ++#else ++static int create_alsa_device(struct usb_function_instance *fi) ++{ ++ return 0; ++} ++#endif ++ ++static struct usb_function_instance *f_midi_alloc_inst(void) ++{ ++ struct f_midi_opts *opts; ++ ++ opts = kzalloc(sizeof(*opts), GFP_KERNEL); ++ if (!opts) ++ return ERR_PTR(-ENOMEM); ++ ++ mutex_init(&opts->lock); ++ opts->func_inst.free_func_inst = f_midi_free_inst; ++ opts->index = SNDRV_DEFAULT_IDX1; ++ opts->id = SNDRV_DEFAULT_STR1; ++ opts->buflen = 256; ++ opts->qlen = 32; ++ opts->in_ports = 1; ++ opts->out_ports = 1; ++ ++ if (create_alsa_device(&opts->func_inst)) { ++ kfree(opts); ++ return ERR_PTR(-ENODEV); ++ } ++ ++ config_group_init_type_name(&opts->func_inst.group, "", ++ &midi_func_type); ++ ++ return &opts->func_inst; ++} ++ ++static void f_midi_free(struct usb_function *f) ++{ ++ struct f_midi *midi; ++ struct f_midi_opts *opts; ++ int i; ++ ++ midi = func_to_midi(f); ++ opts = container_of(f->fi, struct f_midi_opts, func_inst); ++ kfree(midi->id); ++ mutex_lock(&opts->lock); ++ for (i = opts->in_ports - 1; i >= 0; --i) ++ kfree(midi->in_port[i]); ++ kfree(midi); ++ --opts->refcnt; ++ mutex_unlock(&opts->lock); ++} ++ ++static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f) ++{ ++ struct usb_composite_dev *cdev = f->config->cdev; ++ struct f_midi *midi = func_to_midi(f); ++ struct snd_card *card; ++ ++ DBG(cdev, "unbind\n"); ++ ++ /* just to be sure */ ++ f_midi_disable(f); ++ ++ card = midi->card; ++ midi->card = NULL; ++ if (card) ++ snd_card_free(card); ++ ++ usb_free_all_descriptors(f); ++} ++ ++static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) ++{ ++ struct f_midi *midi; ++ struct f_midi_opts *opts; + int status, i; + ++ opts = container_of(fi, struct f_midi_opts, func_inst); ++ ++ mutex_lock(&opts->lock); + /* sanity check */ +- if (in_ports > MAX_PORTS || out_ports > MAX_PORTS) +- return -EINVAL; ++ if (opts->in_ports > MAX_PORTS || opts->out_ports > MAX_PORTS) { ++ mutex_unlock(&opts->lock); ++ return ERR_PTR(-EINVAL); ++ } + + /* allocate and initialize one new instance */ +- midi = kzalloc(sizeof *midi, GFP_KERNEL); ++ midi = kzalloc(sizeof(*midi), GFP_KERNEL); + if (!midi) { +- status = -ENOMEM; +- goto fail; ++ mutex_unlock(&opts->lock); ++ return ERR_PTR(-ENOMEM); + } + +- for (i = 0; i < in_ports; i++) { ++ for (i = 0; i < opts->in_ports; i++) { + struct gmidi_in_port *port = kzalloc(sizeof(*port), GFP_KERNEL); ++ + if (!port) { + status = -ENOMEM; ++ mutex_unlock(&opts->lock); + goto setup_fail; + } + +@@ -948,39 +1208,36 @@ int __init f_midi_bind_config(struct usb_configuration *c, + midi->in_port[i] = port; + } + +- midi->gadget = c->cdev->gadget; +- tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi); +- + /* set up ALSA midi devices */ +- midi->in_ports = in_ports; +- midi->out_ports = out_ports; +- status = f_midi_register_card(midi); +- if (status < 0) +- goto setup_fail; +- +- midi->func.name = "gmidi function"; +- midi->func.strings = midi_strings; +- midi->func.bind = f_midi_bind; +- midi->func.unbind = f_midi_unbind; +- midi->func.set_alt = f_midi_set_alt; +- midi->func.disable = f_midi_disable; +- +- midi->id = kstrdup(id, GFP_KERNEL); +- midi->index = index; +- midi->buflen = buflen; +- midi->qlen = qlen; +- +- status = usb_add_function(c, &midi->func); +- if (status) ++ midi->id = kstrdup(opts->id, GFP_KERNEL); ++ if (opts->id && !midi->id) { ++ status = -ENOMEM; ++ mutex_unlock(&opts->lock); + goto setup_fail; +- +- return 0; ++ } ++ midi->in_ports = opts->in_ports; ++ midi->out_ports = opts->out_ports; ++ midi->index = opts->index; ++ midi->buflen = opts->buflen; ++ midi->qlen = opts->qlen; ++ ++opts->refcnt; ++ mutex_unlock(&opts->lock); ++ ++ midi->func.name = "gmidi function"; ++ midi->func.bind = f_midi_bind; ++ midi->func.unbind = f_midi_unbind; ++ midi->func.set_alt = f_midi_set_alt; ++ midi->func.disable = f_midi_disable; ++ midi->func.free_func = f_midi_free; ++ ++ fi->f = &midi->func; ++ return &midi->func; + + setup_fail: + for (--i; i >= 0; i--) + kfree(midi->in_port[i]); + kfree(midi); +-fail: +- return status; ++ return ERR_PTR(status); + } + ++DECLARE_USB_FUNCTION_INIT(midi, f_midi_alloc_inst, f_midi_alloc); +diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c +new file mode 100644 +index 0000000..79053fd +--- /dev/null ++++ b/drivers/usb/gadget/function/f_mtp.c +@@ -0,0 +1,1473 @@ ++/* ++ * Gadget Function Driver for MTP ++ * ++ * Copyright (C) 2010 Google, Inc. ++ * Author: Mike Lockwood ++ * ++ * 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 DEBUG */ ++/* #define VERBOSE_DEBUG */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "configfs.h" ++ ++#define MTP_BULK_BUFFER_SIZE 16384 ++#define INTR_BUFFER_SIZE 28 ++#define MAX_INST_NAME_LEN 40 ++ ++/* String IDs */ ++#define INTERFACE_STRING_INDEX 0 ++ ++/* values for mtp_dev.state */ ++#define STATE_OFFLINE 0 /* initial state, disconnected */ ++#define STATE_READY 1 /* ready for userspace calls */ ++#define STATE_BUSY 2 /* processing userspace calls */ ++#define STATE_CANCELED 3 /* transaction canceled by host */ ++#define STATE_ERROR 4 /* error from completion routine */ ++ ++/* number of tx and rx requests to allocate */ ++#define TX_REQ_MAX 4 ++#define RX_REQ_MAX 2 ++#define INTR_REQ_MAX 5 ++ ++/* ID for Microsoft MTP OS String */ ++#define MTP_OS_STRING_ID 0xEE ++ ++/* MTP class reqeusts */ ++#define MTP_REQ_CANCEL 0x64 ++#define MTP_REQ_GET_EXT_EVENT_DATA 0x65 ++#define MTP_REQ_RESET 0x66 ++#define MTP_REQ_GET_DEVICE_STATUS 0x67 ++ ++/* constants for device status */ ++#define MTP_RESPONSE_OK 0x2001 ++#define MTP_RESPONSE_DEVICE_BUSY 0x2019 ++#define DRIVER_NAME "mtp" ++ ++static const char mtp_shortname[] = DRIVER_NAME "_usb"; ++ ++struct mtp_dev { ++ struct usb_function function; ++ struct usb_composite_dev *cdev; ++ spinlock_t lock; ++ ++ struct usb_ep *ep_in; ++ struct usb_ep *ep_out; ++ struct usb_ep *ep_intr; ++ ++ int state; ++ ++ /* synchronize access to our device file */ ++ atomic_t open_excl; ++ /* to enforce only one ioctl at a time */ ++ atomic_t ioctl_excl; ++ ++ struct list_head tx_idle; ++ struct list_head intr_idle; ++ ++ wait_queue_head_t read_wq; ++ wait_queue_head_t write_wq; ++ wait_queue_head_t intr_wq; ++ struct usb_request *rx_req[RX_REQ_MAX]; ++ int rx_done; ++ ++ /* for processing MTP_SEND_FILE, MTP_RECEIVE_FILE and ++ * MTP_SEND_FILE_WITH_HEADER ioctls on a work queue ++ */ ++ struct workqueue_struct *wq; ++ struct work_struct send_file_work; ++ struct work_struct receive_file_work; ++ struct file *xfer_file; ++ loff_t xfer_file_offset; ++ int64_t xfer_file_length; ++ unsigned xfer_send_header; ++ uint16_t xfer_command; ++ uint32_t xfer_transaction_id; ++ int xfer_result; ++}; ++ ++static struct usb_interface_descriptor mtp_interface_desc = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bInterfaceNumber = 0, ++ .bNumEndpoints = 3, ++ .bInterfaceClass = USB_CLASS_VENDOR_SPEC, ++ .bInterfaceSubClass = USB_SUBCLASS_VENDOR_SPEC, ++ .bInterfaceProtocol = 0, ++}; ++ ++static struct usb_interface_descriptor ptp_interface_desc = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bInterfaceNumber = 0, ++ .bNumEndpoints = 3, ++ .bInterfaceClass = USB_CLASS_STILL_IMAGE, ++ .bInterfaceSubClass = 1, ++ .bInterfaceProtocol = 1, ++}; ++ ++static struct usb_endpoint_descriptor mtp_highspeed_in_desc = { ++ .bLength = USB_DT_ENDPOINT_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_IN, ++ .bmAttributes = USB_ENDPOINT_XFER_BULK, ++ .wMaxPacketSize = __constant_cpu_to_le16(512), ++}; ++ ++static struct usb_endpoint_descriptor mtp_highspeed_out_desc = { ++ .bLength = USB_DT_ENDPOINT_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_OUT, ++ .bmAttributes = USB_ENDPOINT_XFER_BULK, ++ .wMaxPacketSize = __constant_cpu_to_le16(512), ++}; ++ ++static struct usb_endpoint_descriptor mtp_fullspeed_in_desc = { ++ .bLength = USB_DT_ENDPOINT_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_IN, ++ .bmAttributes = USB_ENDPOINT_XFER_BULK, ++}; ++ ++static struct usb_endpoint_descriptor mtp_fullspeed_out_desc = { ++ .bLength = USB_DT_ENDPOINT_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_OUT, ++ .bmAttributes = USB_ENDPOINT_XFER_BULK, ++}; ++ ++static struct usb_endpoint_descriptor mtp_intr_desc = { ++ .bLength = USB_DT_ENDPOINT_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_IN, ++ .bmAttributes = USB_ENDPOINT_XFER_INT, ++ .wMaxPacketSize = __constant_cpu_to_le16(INTR_BUFFER_SIZE), ++ .bInterval = 6, ++}; ++ ++static struct usb_descriptor_header *fs_mtp_descs[] = { ++ (struct usb_descriptor_header *) &mtp_interface_desc, ++ (struct usb_descriptor_header *) &mtp_fullspeed_in_desc, ++ (struct usb_descriptor_header *) &mtp_fullspeed_out_desc, ++ (struct usb_descriptor_header *) &mtp_intr_desc, ++ NULL, ++}; ++ ++static struct usb_descriptor_header *hs_mtp_descs[] = { ++ (struct usb_descriptor_header *) &mtp_interface_desc, ++ (struct usb_descriptor_header *) &mtp_highspeed_in_desc, ++ (struct usb_descriptor_header *) &mtp_highspeed_out_desc, ++ (struct usb_descriptor_header *) &mtp_intr_desc, ++ NULL, ++}; ++ ++static struct usb_descriptor_header *fs_ptp_descs[] = { ++ (struct usb_descriptor_header *) &ptp_interface_desc, ++ (struct usb_descriptor_header *) &mtp_fullspeed_in_desc, ++ (struct usb_descriptor_header *) &mtp_fullspeed_out_desc, ++ (struct usb_descriptor_header *) &mtp_intr_desc, ++ NULL, ++}; ++ ++static struct usb_descriptor_header *hs_ptp_descs[] = { ++ (struct usb_descriptor_header *) &ptp_interface_desc, ++ (struct usb_descriptor_header *) &mtp_highspeed_in_desc, ++ (struct usb_descriptor_header *) &mtp_highspeed_out_desc, ++ (struct usb_descriptor_header *) &mtp_intr_desc, ++ NULL, ++}; ++ ++static struct usb_string mtp_string_defs[] = { ++ /* Naming interface "MTP" so libmtp will recognize us */ ++ [INTERFACE_STRING_INDEX].s = "MTP", ++ { }, /* end of list */ ++}; ++ ++static struct usb_gadget_strings mtp_string_table = { ++ .language = 0x0409, /* en-US */ ++ .strings = mtp_string_defs, ++}; ++ ++static struct usb_gadget_strings *mtp_strings[] = { ++ &mtp_string_table, ++ NULL, ++}; ++ ++/* Microsoft MTP OS String */ ++static u8 mtp_os_string[] = { ++ 18, /* sizeof(mtp_os_string) */ ++ USB_DT_STRING, ++ /* Signature field: "MSFT100" */ ++ 'M', 0, 'S', 0, 'F', 0, 'T', 0, '1', 0, '0', 0, '0', 0, ++ /* vendor code */ ++ 1, ++ /* padding */ ++ 0 ++}; ++ ++/* Microsoft Extended Configuration Descriptor Header Section */ ++struct mtp_ext_config_desc_header { ++ __le32 dwLength; ++ __u16 bcdVersion; ++ __le16 wIndex; ++ __u8 bCount; ++ __u8 reserved[7]; ++}; ++ ++/* Microsoft Extended Configuration Descriptor Function Section */ ++struct mtp_ext_config_desc_function { ++ __u8 bFirstInterfaceNumber; ++ __u8 bInterfaceCount; ++ __u8 compatibleID[8]; ++ __u8 subCompatibleID[8]; ++ __u8 reserved[6]; ++}; ++ ++/* MTP Extended Configuration Descriptor */ ++struct { ++ struct mtp_ext_config_desc_header header; ++ struct mtp_ext_config_desc_function function; ++} mtp_ext_config_desc = { ++ .header = { ++ .dwLength = __constant_cpu_to_le32(sizeof(mtp_ext_config_desc)), ++ .bcdVersion = __constant_cpu_to_le16(0x0100), ++ .wIndex = __constant_cpu_to_le16(4), ++ .bCount = __constant_cpu_to_le16(1), ++ }, ++ .function = { ++ .bFirstInterfaceNumber = 0, ++ .bInterfaceCount = 1, ++ .compatibleID = { 'M', 'T', 'P' }, ++ }, ++}; ++ ++struct mtp_device_status { ++ __le16 wLength; ++ __le16 wCode; ++}; ++ ++struct mtp_data_header { ++ /* length of packet, including this header */ ++ __le32 length; ++ /* container type (2 for data packet) */ ++ __le16 type; ++ /* MTP command code */ ++ __le16 command; ++ /* MTP transaction ID */ ++ __le32 transaction_id; ++}; ++ ++struct mtp_instance { ++ struct usb_function_instance func_inst; ++ const char *name; ++ struct mtp_dev *dev; ++}; ++ ++/* temporary variable used between mtp_open() and mtp_gadget_bind() */ ++static struct mtp_dev *_mtp_dev; ++ ++static inline struct mtp_dev *func_to_mtp(struct usb_function *f) ++{ ++ return container_of(f, struct mtp_dev, function); ++} ++ ++static struct usb_request *mtp_request_new(struct usb_ep *ep, int buffer_size) ++{ ++ struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL); ++ if (!req) ++ return NULL; ++ ++ /* now allocate buffers for the requests */ ++ req->buf = kmalloc(buffer_size, GFP_KERNEL); ++ if (!req->buf) { ++ usb_ep_free_request(ep, req); ++ return NULL; ++ } ++ ++ return req; ++} ++ ++static void mtp_request_free(struct usb_request *req, struct usb_ep *ep) ++{ ++ if (req) { ++ kfree(req->buf); ++ usb_ep_free_request(ep, req); ++ } ++} ++ ++static inline int mtp_lock(atomic_t *excl) ++{ ++ if (atomic_inc_return(excl) == 1) { ++ return 0; ++ } else { ++ atomic_dec(excl); ++ return -1; ++ } ++} ++ ++static inline void mtp_unlock(atomic_t *excl) ++{ ++ atomic_dec(excl); ++} ++ ++/* add a request to the tail of a list */ ++static void mtp_req_put(struct mtp_dev *dev, struct list_head *head, ++ struct usb_request *req) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ list_add_tail(&req->list, head); ++ spin_unlock_irqrestore(&dev->lock, flags); ++} ++ ++/* remove a request from the head of a list */ ++static struct usb_request ++*mtp_req_get(struct mtp_dev *dev, struct list_head *head) ++{ ++ unsigned long flags; ++ struct usb_request *req; ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ if (list_empty(head)) { ++ req = 0; ++ } else { ++ req = list_first_entry(head, struct usb_request, list); ++ list_del(&req->list); ++ } ++ spin_unlock_irqrestore(&dev->lock, flags); ++ return req; ++} ++ ++static void mtp_complete_in(struct usb_ep *ep, struct usb_request *req) ++{ ++ struct mtp_dev *dev = _mtp_dev; ++ ++ if (req->status != 0) ++ dev->state = STATE_ERROR; ++ ++ mtp_req_put(dev, &dev->tx_idle, req); ++ ++ wake_up(&dev->write_wq); ++} ++ ++static void mtp_complete_out(struct usb_ep *ep, struct usb_request *req) ++{ ++ struct mtp_dev *dev = _mtp_dev; ++ ++ dev->rx_done = 1; ++ if (req->status != 0) ++ dev->state = STATE_ERROR; ++ ++ wake_up(&dev->read_wq); ++} ++ ++static void mtp_complete_intr(struct usb_ep *ep, struct usb_request *req) ++{ ++ struct mtp_dev *dev = _mtp_dev; ++ ++ if (req->status != 0) ++ dev->state = STATE_ERROR; ++ ++ mtp_req_put(dev, &dev->intr_idle, req); ++ ++ wake_up(&dev->intr_wq); ++} ++ ++static int mtp_create_bulk_endpoints(struct mtp_dev *dev, ++ struct usb_endpoint_descriptor *in_desc, ++ struct usb_endpoint_descriptor *out_desc, ++ struct usb_endpoint_descriptor *intr_desc) ++{ ++ struct usb_composite_dev *cdev = dev->cdev; ++ struct usb_request *req; ++ struct usb_ep *ep; ++ int i; ++ ++ DBG(cdev, "create_bulk_endpoints dev: %p\n", dev); ++ ++ ep = usb_ep_autoconfig(cdev->gadget, in_desc); ++ if (!ep) { ++ DBG(cdev, "usb_ep_autoconfig for ep_in failed\n"); ++ return -ENODEV; ++ } ++ DBG(cdev, "usb_ep_autoconfig for ep_in got %s\n", ep->name); ++ ep->driver_data = dev; /* claim the endpoint */ ++ dev->ep_in = ep; ++ ++ ep = usb_ep_autoconfig(cdev->gadget, out_desc); ++ if (!ep) { ++ DBG(cdev, "usb_ep_autoconfig for ep_out failed\n"); ++ return -ENODEV; ++ } ++ DBG(cdev, "usb_ep_autoconfig for mtp ep_out got %s\n", ep->name); ++ ep->driver_data = dev; /* claim the endpoint */ ++ dev->ep_out = ep; ++ ++ ep = usb_ep_autoconfig(cdev->gadget, intr_desc); ++ if (!ep) { ++ DBG(cdev, "usb_ep_autoconfig for ep_intr failed\n"); ++ return -ENODEV; ++ } ++ DBG(cdev, "usb_ep_autoconfig for mtp ep_intr got %s\n", ep->name); ++ ep->driver_data = dev; /* claim the endpoint */ ++ dev->ep_intr = ep; ++ ++ /* now allocate requests for our endpoints */ ++ for (i = 0; i < TX_REQ_MAX; i++) { ++ req = mtp_request_new(dev->ep_in, MTP_BULK_BUFFER_SIZE); ++ if (!req) ++ goto fail; ++ req->complete = mtp_complete_in; ++ mtp_req_put(dev, &dev->tx_idle, req); ++ } ++ for (i = 0; i < RX_REQ_MAX; i++) { ++ req = mtp_request_new(dev->ep_out, MTP_BULK_BUFFER_SIZE); ++ if (!req) ++ goto fail; ++ req->complete = mtp_complete_out; ++ dev->rx_req[i] = req; ++ } ++ for (i = 0; i < INTR_REQ_MAX; i++) { ++ req = mtp_request_new(dev->ep_intr, INTR_BUFFER_SIZE); ++ if (!req) ++ goto fail; ++ req->complete = mtp_complete_intr; ++ mtp_req_put(dev, &dev->intr_idle, req); ++ } ++ ++ return 0; ++ ++fail: ++ pr_err("mtp_bind() could not allocate requests\n"); ++ return -1; ++} ++ ++static ssize_t mtp_read(struct file *fp, char __user *buf, ++ size_t count, loff_t *pos) ++{ ++ struct mtp_dev *dev = fp->private_data; ++ struct usb_composite_dev *cdev = dev->cdev; ++ struct usb_request *req; ++ ssize_t r = count; ++ unsigned xfer; ++ int ret = 0; ++ ++ DBG(cdev, "mtp_read(%zu)\n", count); ++ ++ if (count > MTP_BULK_BUFFER_SIZE) ++ return -EINVAL; ++ ++ /* we will block until we're online */ ++ DBG(cdev, "mtp_read: waiting for online state\n"); ++ ret = wait_event_interruptible(dev->read_wq, ++ dev->state != STATE_OFFLINE); ++ if (ret < 0) { ++ r = ret; ++ goto done; ++ } ++ spin_lock_irq(&dev->lock); ++ if (dev->state == STATE_CANCELED) { ++ /* report cancelation to userspace */ ++ dev->state = STATE_READY; ++ spin_unlock_irq(&dev->lock); ++ return -ECANCELED; ++ } ++ dev->state = STATE_BUSY; ++ spin_unlock_irq(&dev->lock); ++ ++requeue_req: ++ /* queue a request */ ++ req = dev->rx_req[0]; ++ req->length = count; ++ dev->rx_done = 0; ++ ret = usb_ep_queue(dev->ep_out, req, GFP_KERNEL); ++ if (ret < 0) { ++ r = -EIO; ++ goto done; ++ } else { ++ DBG(cdev, "rx %p queue\n", req); ++ } ++ ++ /* wait for a request to complete */ ++ ret = wait_event_interruptible(dev->read_wq, dev->rx_done); ++ if (ret < 0) { ++ r = ret; ++ usb_ep_dequeue(dev->ep_out, req); ++ goto done; ++ } ++ if (dev->state == STATE_BUSY) { ++ /* If we got a 0-len packet, throw it back and try again. */ ++ if (req->actual == 0) ++ goto requeue_req; ++ ++ DBG(cdev, "rx %p %d\n", req, req->actual); ++ xfer = (req->actual < count) ? req->actual : count; ++ r = xfer; ++ if (copy_to_user(buf, req->buf, xfer)) ++ r = -EFAULT; ++ } else ++ r = -EIO; ++ ++done: ++ spin_lock_irq(&dev->lock); ++ if (dev->state == STATE_CANCELED) ++ r = -ECANCELED; ++ else if (dev->state != STATE_OFFLINE) ++ dev->state = STATE_READY; ++ spin_unlock_irq(&dev->lock); ++ ++ DBG(cdev, "mtp_read returning %zd\n", r); ++ return r; ++} ++ ++static ssize_t mtp_write(struct file *fp, const char __user *buf, ++ size_t count, loff_t *pos) ++{ ++ struct mtp_dev *dev = fp->private_data; ++ struct usb_composite_dev *cdev = dev->cdev; ++ struct usb_request *req = 0; ++ ssize_t r = count; ++ unsigned xfer; ++ int sendZLP = 0; ++ int ret; ++ ++ DBG(cdev, "mtp_write(%zu)\n", count); ++ ++ spin_lock_irq(&dev->lock); ++ if (dev->state == STATE_CANCELED) { ++ /* report cancelation to userspace */ ++ dev->state = STATE_READY; ++ spin_unlock_irq(&dev->lock); ++ return -ECANCELED; ++ } ++ if (dev->state == STATE_OFFLINE) { ++ spin_unlock_irq(&dev->lock); ++ return -ENODEV; ++ } ++ dev->state = STATE_BUSY; ++ spin_unlock_irq(&dev->lock); ++ ++ /* we need to send a zero length packet to signal the end of transfer ++ * if the transfer size is aligned to a packet boundary. ++ */ ++ if ((count & (dev->ep_in->maxpacket - 1)) == 0) ++ sendZLP = 1; ++ ++ while (count > 0 || sendZLP) { ++ /* so we exit after sending ZLP */ ++ if (count == 0) ++ sendZLP = 0; ++ ++ if (dev->state != STATE_BUSY) { ++ DBG(cdev, "mtp_write dev->error\n"); ++ r = -EIO; ++ break; ++ } ++ ++ /* get an idle tx request to use */ ++ req = 0; ++ ret = wait_event_interruptible(dev->write_wq, ++ ((req = mtp_req_get(dev, &dev->tx_idle)) ++ || dev->state != STATE_BUSY)); ++ if (!req) { ++ r = ret; ++ break; ++ } ++ ++ if (count > MTP_BULK_BUFFER_SIZE) ++ xfer = MTP_BULK_BUFFER_SIZE; ++ else ++ xfer = count; ++ if (xfer && copy_from_user(req->buf, buf, xfer)) { ++ r = -EFAULT; ++ break; ++ } ++ ++ req->length = xfer; ++ ret = usb_ep_queue(dev->ep_in, req, GFP_KERNEL); ++ if (ret < 0) { ++ DBG(cdev, "mtp_write: xfer error %d\n", ret); ++ r = -EIO; ++ break; ++ } ++ ++ buf += xfer; ++ count -= xfer; ++ ++ /* zero this so we don't try to free it on error exit */ ++ req = 0; ++ } ++ ++ if (req) ++ mtp_req_put(dev, &dev->tx_idle, req); ++ ++ spin_lock_irq(&dev->lock); ++ if (dev->state == STATE_CANCELED) ++ r = -ECANCELED; ++ else if (dev->state != STATE_OFFLINE) ++ dev->state = STATE_READY; ++ spin_unlock_irq(&dev->lock); ++ ++ DBG(cdev, "mtp_write returning %zd\n", r); ++ return r; ++} ++ ++/* read from a local file and write to USB */ ++static void send_file_work(struct work_struct *data) ++{ ++ struct mtp_dev *dev = container_of(data, struct mtp_dev, ++ send_file_work); ++ struct usb_composite_dev *cdev = dev->cdev; ++ struct usb_request *req = 0; ++ struct mtp_data_header *header; ++ struct file *filp; ++ loff_t offset; ++ int64_t count; ++ int xfer, ret, hdr_size; ++ int r = 0; ++ int sendZLP = 0; ++ ++ /* read our parameters */ ++ smp_rmb(); ++ filp = dev->xfer_file; ++ offset = dev->xfer_file_offset; ++ count = dev->xfer_file_length; ++ ++ DBG(cdev, "send_file_work(%lld %lld)\n", offset, count); ++ ++ if (dev->xfer_send_header) { ++ hdr_size = sizeof(struct mtp_data_header); ++ count += hdr_size; ++ } else { ++ hdr_size = 0; ++ } ++ ++ /* we need to send a zero length packet to signal the end of transfer ++ * if the transfer size is aligned to a packet boundary. ++ */ ++ if ((count & (dev->ep_in->maxpacket - 1)) == 0) ++ sendZLP = 1; ++ ++ while (count > 0 || sendZLP) { ++ /* so we exit after sending ZLP */ ++ if (count == 0) ++ sendZLP = 0; ++ ++ /* get an idle tx request to use */ ++ req = 0; ++ ret = wait_event_interruptible(dev->write_wq, ++ (req = mtp_req_get(dev, &dev->tx_idle)) ++ || dev->state != STATE_BUSY); ++ if (dev->state == STATE_CANCELED) { ++ r = -ECANCELED; ++ break; ++ } ++ if (!req) { ++ r = ret; ++ break; ++ } ++ ++ if (count > MTP_BULK_BUFFER_SIZE) ++ xfer = MTP_BULK_BUFFER_SIZE; ++ else ++ xfer = count; ++ ++ if (hdr_size) { ++ /* prepend MTP data header */ ++ header = (struct mtp_data_header *)req->buf; ++ header->length = __cpu_to_le32(count); ++ header->type = __cpu_to_le16(2); /* data packet */ ++ header->command = __cpu_to_le16(dev->xfer_command); ++ header->transaction_id = ++ __cpu_to_le32(dev->xfer_transaction_id); ++ } ++ ++ ret = vfs_read(filp, req->buf + hdr_size, xfer - hdr_size, ++ &offset); ++ if (ret < 0) { ++ r = ret; ++ break; ++ } ++ xfer = ret + hdr_size; ++ hdr_size = 0; ++ ++ req->length = xfer; ++ ret = usb_ep_queue(dev->ep_in, req, GFP_KERNEL); ++ if (ret < 0) { ++ DBG(cdev, "send_file_work: xfer error %d\n", ret); ++ dev->state = STATE_ERROR; ++ r = -EIO; ++ break; ++ } ++ ++ count -= xfer; ++ ++ /* zero this so we don't try to free it on error exit */ ++ req = 0; ++ } ++ ++ if (req) ++ mtp_req_put(dev, &dev->tx_idle, req); ++ ++ DBG(cdev, "send_file_work returning %d\n", r); ++ /* write the result */ ++ dev->xfer_result = r; ++ smp_wmb(); ++} ++ ++/* read from USB and write to a local file */ ++static void receive_file_work(struct work_struct *data) ++{ ++ struct mtp_dev *dev = container_of(data, struct mtp_dev, ++ receive_file_work); ++ struct usb_composite_dev *cdev = dev->cdev; ++ struct usb_request *read_req = NULL, *write_req = NULL; ++ struct file *filp; ++ loff_t offset; ++ int64_t count; ++ int ret, cur_buf = 0; ++ int r = 0; ++ ++ /* read our parameters */ ++ smp_rmb(); ++ filp = dev->xfer_file; ++ offset = dev->xfer_file_offset; ++ count = dev->xfer_file_length; ++ ++ DBG(cdev, "receive_file_work(%lld)\n", count); ++ ++ while (count > 0 || write_req) { ++ if (count > 0) { ++ /* queue a request */ ++ read_req = dev->rx_req[cur_buf]; ++ cur_buf = (cur_buf + 1) % RX_REQ_MAX; ++ ++ read_req->length = (count > MTP_BULK_BUFFER_SIZE ++ ? MTP_BULK_BUFFER_SIZE : count); ++ dev->rx_done = 0; ++ ret = usb_ep_queue(dev->ep_out, read_req, GFP_KERNEL); ++ if (ret < 0) { ++ r = -EIO; ++ dev->state = STATE_ERROR; ++ break; ++ } ++ } ++ ++ if (write_req) { ++ DBG(cdev, "rx %p %d\n", write_req, write_req->actual); ++ ret = vfs_write(filp, write_req->buf, write_req->actual, ++ &offset); ++ DBG(cdev, "vfs_write %d\n", ret); ++ if (ret != write_req->actual) { ++ r = -EIO; ++ dev->state = STATE_ERROR; ++ break; ++ } ++ write_req = NULL; ++ } ++ ++ if (read_req) { ++ /* wait for our last read to complete */ ++ ret = wait_event_interruptible(dev->read_wq, ++ dev->rx_done || dev->state != STATE_BUSY); ++ if (dev->state == STATE_CANCELED) { ++ r = -ECANCELED; ++ if (!dev->rx_done) ++ usb_ep_dequeue(dev->ep_out, read_req); ++ break; ++ } ++ /* if xfer_file_length is 0xFFFFFFFF, then we read until ++ * we get a zero length packet ++ */ ++ if (count != 0xFFFFFFFF) ++ count -= read_req->actual; ++ if (read_req->actual < read_req->length) { ++ /* ++ * short packet is used to signal EOF for ++ * sizes > 4 gig ++ */ ++ DBG(cdev, "got short packet\n"); ++ count = 0; ++ } ++ ++ write_req = read_req; ++ read_req = NULL; ++ } ++ } ++ ++ DBG(cdev, "receive_file_work returning %d\n", r); ++ /* write the result */ ++ dev->xfer_result = r; ++ smp_wmb(); ++} ++ ++static int mtp_send_event(struct mtp_dev *dev, struct mtp_event *event) ++{ ++ struct usb_request *req = NULL; ++ int ret; ++ int length = event->length; ++ ++ DBG(dev->cdev, "mtp_send_event(%zu)\n", event->length); ++ ++ if (length < 0 || length > INTR_BUFFER_SIZE) ++ return -EINVAL; ++ if (dev->state == STATE_OFFLINE) ++ return -ENODEV; ++ ++ ret = wait_event_interruptible_timeout(dev->intr_wq, ++ (req = mtp_req_get(dev, &dev->intr_idle)), ++ msecs_to_jiffies(1000)); ++ if (!req) ++ return -ETIME; ++ ++ if (copy_from_user(req->buf, (void __user *)event->data, length)) { ++ mtp_req_put(dev, &dev->intr_idle, req); ++ return -EFAULT; ++ } ++ req->length = length; ++ ret = usb_ep_queue(dev->ep_intr, req, GFP_KERNEL); ++ if (ret) ++ mtp_req_put(dev, &dev->intr_idle, req); ++ ++ return ret; ++} ++ ++static long mtp_ioctl(struct file *fp, unsigned code, unsigned long value) ++{ ++ struct mtp_dev *dev = fp->private_data; ++ struct file *filp = NULL; ++ int ret = -EINVAL; ++ ++ if (mtp_lock(&dev->ioctl_excl)) ++ return -EBUSY; ++ ++ switch (code) { ++ case MTP_SEND_FILE: ++ case MTP_RECEIVE_FILE: ++ case MTP_SEND_FILE_WITH_HEADER: ++ { ++ struct mtp_file_range mfr; ++ struct work_struct *work; ++ ++ spin_lock_irq(&dev->lock); ++ if (dev->state == STATE_CANCELED) { ++ /* report cancelation to userspace */ ++ dev->state = STATE_READY; ++ spin_unlock_irq(&dev->lock); ++ ret = -ECANCELED; ++ goto out; ++ } ++ if (dev->state == STATE_OFFLINE) { ++ spin_unlock_irq(&dev->lock); ++ ret = -ENODEV; ++ goto out; ++ } ++ dev->state = STATE_BUSY; ++ spin_unlock_irq(&dev->lock); ++ ++ if (copy_from_user(&mfr, (void __user *)value, sizeof(mfr))) { ++ ret = -EFAULT; ++ goto fail; ++ } ++ /* hold a reference to the file while we are working with it */ ++ filp = fget(mfr.fd); ++ if (!filp) { ++ ret = -EBADF; ++ goto fail; ++ } ++ ++ /* write the parameters */ ++ dev->xfer_file = filp; ++ dev->xfer_file_offset = mfr.offset; ++ dev->xfer_file_length = mfr.length; ++ smp_wmb(); ++ ++ if (code == MTP_SEND_FILE_WITH_HEADER) { ++ work = &dev->send_file_work; ++ dev->xfer_send_header = 1; ++ dev->xfer_command = mfr.command; ++ dev->xfer_transaction_id = mfr.transaction_id; ++ } else if (code == MTP_SEND_FILE) { ++ work = &dev->send_file_work; ++ dev->xfer_send_header = 0; ++ } else { ++ work = &dev->receive_file_work; ++ } ++ ++ /* We do the file transfer on a work queue so it will run ++ * in kernel context, which is necessary for vfs_read and ++ * vfs_write to use our buffers in the kernel address space. ++ */ ++ queue_work(dev->wq, work); ++ /* wait for operation to complete */ ++ flush_workqueue(dev->wq); ++ fput(filp); ++ ++ /* read the result */ ++ smp_rmb(); ++ ret = dev->xfer_result; ++ break; ++ } ++ case MTP_SEND_EVENT: ++ { ++ struct mtp_event event; ++ /* return here so we don't change dev->state below, ++ * which would interfere with bulk transfer state. ++ */ ++ if (copy_from_user(&event, (void __user *)value, sizeof(event))) ++ ret = -EFAULT; ++ else ++ ret = mtp_send_event(dev, &event); ++ goto out; ++ } ++ } ++ ++fail: ++ spin_lock_irq(&dev->lock); ++ if (dev->state == STATE_CANCELED) ++ ret = -ECANCELED; ++ else if (dev->state != STATE_OFFLINE) ++ dev->state = STATE_READY; ++ spin_unlock_irq(&dev->lock); ++out: ++ mtp_unlock(&dev->ioctl_excl); ++ DBG(dev->cdev, "ioctl returning %d\n", ret); ++ return ret; ++} ++ ++static int mtp_open(struct inode *ip, struct file *fp) ++{ ++ printk(KERN_INFO "mtp_open\n"); ++ if (mtp_lock(&_mtp_dev->open_excl)) ++ return -EBUSY; ++ ++ /* clear any error condition */ ++ if (_mtp_dev->state != STATE_OFFLINE) ++ _mtp_dev->state = STATE_READY; ++ ++ fp->private_data = _mtp_dev; ++ return 0; ++} ++ ++static int mtp_release(struct inode *ip, struct file *fp) ++{ ++ printk(KERN_INFO "mtp_release\n"); ++ ++ mtp_unlock(&_mtp_dev->open_excl); ++ return 0; ++} ++ ++/* file operations for /dev/mtp_usb */ ++static const struct file_operations mtp_fops = { ++ .owner = THIS_MODULE, ++ .read = mtp_read, ++ .write = mtp_write, ++ .unlocked_ioctl = mtp_ioctl, ++ .open = mtp_open, ++ .release = mtp_release, ++}; ++ ++static struct miscdevice mtp_device = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = mtp_shortname, ++ .fops = &mtp_fops, ++}; ++ ++static int mtp_ctrlrequest(struct usb_composite_dev *cdev, ++ const struct usb_ctrlrequest *ctrl) ++{ ++ struct mtp_dev *dev = _mtp_dev; ++ 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); ++ unsigned long flags; ++ ++ VDBG(cdev, "mtp_ctrlrequest " ++ "%02x.%02x v%04x i%04x l%u\n", ++ ctrl->bRequestType, ctrl->bRequest, ++ w_value, w_index, w_length); ++ ++ /* Handle MTP OS string */ ++ if (ctrl->bRequestType == ++ (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE) ++ && ctrl->bRequest == USB_REQ_GET_DESCRIPTOR ++ && (w_value >> 8) == USB_DT_STRING ++ && (w_value & 0xFF) == MTP_OS_STRING_ID) { ++ value = (w_length < sizeof(mtp_os_string) ++ ? w_length : sizeof(mtp_os_string)); ++ memcpy(cdev->req->buf, mtp_os_string, value); ++ } else if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_VENDOR) { ++ /* Handle MTP OS descriptor */ ++ DBG(cdev, "vendor request: %d index: %d value: %d length: %d\n", ++ ctrl->bRequest, w_index, w_value, w_length); ++ ++ if (ctrl->bRequest == 1 ++ && (ctrl->bRequestType & USB_DIR_IN) ++ && (w_index == 4 || w_index == 5)) { ++ value = (w_length < sizeof(mtp_ext_config_desc) ? ++ w_length : sizeof(mtp_ext_config_desc)); ++ memcpy(cdev->req->buf, &mtp_ext_config_desc, value); ++ } ++ } else if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS) { ++ DBG(cdev, "class request: %d index: %d value: %d length: %d\n", ++ ctrl->bRequest, w_index, w_value, w_length); ++ ++ if (ctrl->bRequest == MTP_REQ_CANCEL && w_index == 0 ++ && w_value == 0) { ++ DBG(cdev, "MTP_REQ_CANCEL\n"); ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ if (dev->state == STATE_BUSY) { ++ dev->state = STATE_CANCELED; ++ wake_up(&dev->read_wq); ++ wake_up(&dev->write_wq); ++ } ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ /* We need to queue a request to read the remaining ++ * bytes, but we don't actually need to look at ++ * the contents. ++ */ ++ value = w_length; ++ } else if (ctrl->bRequest == MTP_REQ_GET_DEVICE_STATUS ++ && w_index == 0 && w_value == 0) { ++ struct mtp_device_status *status = cdev->req->buf; ++ status->wLength = ++ __constant_cpu_to_le16(sizeof(*status)); ++ ++ DBG(cdev, "MTP_REQ_GET_DEVICE_STATUS\n"); ++ spin_lock_irqsave(&dev->lock, flags); ++ /* device status is "busy" until we report ++ * the cancelation to userspace ++ */ ++ if (dev->state == STATE_CANCELED) ++ status->wCode = ++ __cpu_to_le16(MTP_RESPONSE_DEVICE_BUSY); ++ else ++ status->wCode = ++ __cpu_to_le16(MTP_RESPONSE_OK); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ value = sizeof(*status); ++ } ++ } ++ ++ /* respond with data transfer or status phase? */ ++ if (value >= 0) { ++ int rc; ++ cdev->req->zero = value < w_length; ++ cdev->req->length = value; ++ rc = usb_ep_queue(cdev->gadget->ep0, cdev->req, GFP_ATOMIC); ++ if (rc < 0) ++ ERROR(cdev, "%s: response queue error\n", __func__); ++ } ++ return value; ++} ++ ++static int ++mtp_function_bind(struct usb_configuration *c, struct usb_function *f) ++{ ++ struct usb_composite_dev *cdev = c->cdev; ++ struct mtp_dev *dev = func_to_mtp(f); ++ int id; ++ int ret; ++ ++ dev->cdev = cdev; ++ DBG(cdev, "mtp_function_bind dev: %p\n", dev); ++ ++ /* allocate interface ID(s) */ ++ id = usb_interface_id(c, f); ++ if (id < 0) ++ return id; ++ mtp_interface_desc.bInterfaceNumber = id; ++ ++ if (mtp_string_defs[INTERFACE_STRING_INDEX].id == 0) { ++ ret = usb_string_id(c->cdev); ++ if (ret < 0) ++ return ret; ++ mtp_string_defs[INTERFACE_STRING_INDEX].id = ret; ++ mtp_interface_desc.iInterface = ret; ++ } ++ /* allocate endpoints */ ++ ret = mtp_create_bulk_endpoints(dev, &mtp_fullspeed_in_desc, ++ &mtp_fullspeed_out_desc, &mtp_intr_desc); ++ if (ret) ++ return ret; ++ ++ /* support high speed hardware */ ++ if (gadget_is_dualspeed(c->cdev->gadget)) { ++ mtp_highspeed_in_desc.bEndpointAddress = ++ mtp_fullspeed_in_desc.bEndpointAddress; ++ mtp_highspeed_out_desc.bEndpointAddress = ++ mtp_fullspeed_out_desc.bEndpointAddress; ++ } ++ ++ DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n", ++ gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", ++ f->name, dev->ep_in->name, dev->ep_out->name); ++ return 0; ++} ++ ++static void ++mtp_function_unbind(struct usb_configuration *c, struct usb_function *f) ++{ ++ struct mtp_dev *dev = func_to_mtp(f); ++ struct usb_request *req; ++ int i; ++ ++ mtp_string_defs[INTERFACE_STRING_INDEX].id = 0; ++ while ((req = mtp_req_get(dev, &dev->tx_idle))) ++ mtp_request_free(req, dev->ep_in); ++ for (i = 0; i < RX_REQ_MAX; i++) ++ mtp_request_free(dev->rx_req[i], dev->ep_out); ++ while ((req = mtp_req_get(dev, &dev->intr_idle))) ++ mtp_request_free(req, dev->ep_intr); ++ dev->state = STATE_OFFLINE; ++} ++ ++static int mtp_function_set_alt(struct usb_function *f, ++ unsigned intf, unsigned alt) ++{ ++ struct mtp_dev *dev = func_to_mtp(f); ++ struct usb_composite_dev *cdev = f->config->cdev; ++ int ret; ++ ++ DBG(cdev, "mtp_function_set_alt intf: %d alt: %d\n", intf, alt); ++ ++ ret = config_ep_by_speed(cdev->gadget, f, dev->ep_in); ++ if (ret) ++ return ret; ++ ++ ret = usb_ep_enable(dev->ep_in); ++ if (ret) ++ return ret; ++ ++ ret = config_ep_by_speed(cdev->gadget, f, dev->ep_out); ++ if (ret) ++ return ret; ++ ++ ret = usb_ep_enable(dev->ep_out); ++ if (ret) { ++ usb_ep_disable(dev->ep_in); ++ return ret; ++ } ++ ++ ret = config_ep_by_speed(cdev->gadget, f, dev->ep_intr); ++ if (ret) ++ return ret; ++ ++ ret = usb_ep_enable(dev->ep_intr); ++ if (ret) { ++ usb_ep_disable(dev->ep_out); ++ usb_ep_disable(dev->ep_in); ++ return ret; ++ } ++ dev->state = STATE_READY; ++ ++ /* readers may be blocked waiting for us to go online */ ++ wake_up(&dev->read_wq); ++ return 0; ++} ++ ++static void mtp_function_disable(struct usb_function *f) ++{ ++ struct mtp_dev *dev = func_to_mtp(f); ++ struct usb_composite_dev *cdev = dev->cdev; ++ ++ DBG(cdev, "mtp_function_disable\n"); ++ dev->state = STATE_OFFLINE; ++ usb_ep_disable(dev->ep_in); ++ usb_ep_disable(dev->ep_out); ++ usb_ep_disable(dev->ep_intr); ++ ++ /* readers may be blocked waiting for us to go online */ ++ wake_up(&dev->read_wq); ++ ++ VDBG(cdev, "%s disabled\n", dev->function.name); ++} ++ ++static int __maybe_unused mtp_bind_config(struct usb_configuration *c, bool ptp_config) ++{ ++ struct mtp_dev *dev = _mtp_dev; ++ int ret = 0; ++ ++ printk(KERN_INFO "mtp_bind_config\n"); ++ ++ /* allocate a string ID for our interface */ ++ if (mtp_string_defs[INTERFACE_STRING_INDEX].id == 0) { ++ ret = usb_string_id(c->cdev); ++ if (ret < 0) ++ return ret; ++ mtp_string_defs[INTERFACE_STRING_INDEX].id = ret; ++ mtp_interface_desc.iInterface = ret; ++ } ++ ++ dev->cdev = c->cdev; ++ dev->function.name = DRIVER_NAME; ++ dev->function.strings = mtp_strings; ++ if (ptp_config) { ++ dev->function.fs_descriptors = fs_ptp_descs; ++ dev->function.hs_descriptors = hs_ptp_descs; ++ } else { ++ dev->function.fs_descriptors = fs_mtp_descs; ++ dev->function.hs_descriptors = hs_mtp_descs; ++ } ++ dev->function.bind = mtp_function_bind; ++ dev->function.unbind = mtp_function_unbind; ++ dev->function.set_alt = mtp_function_set_alt; ++ dev->function.disable = mtp_function_disable; ++ ++ return usb_add_function(c, &dev->function); ++} ++ ++static int __mtp_setup(struct mtp_instance *fi_mtp) ++{ ++ struct mtp_dev *dev; ++ int ret; ++ ++ dev = kzalloc(sizeof(*dev), GFP_KERNEL); ++ ++ if (fi_mtp != NULL) ++ fi_mtp->dev = dev; ++ ++ if (!dev) ++ return -ENOMEM; ++ ++ spin_lock_init(&dev->lock); ++ init_waitqueue_head(&dev->read_wq); ++ init_waitqueue_head(&dev->write_wq); ++ init_waitqueue_head(&dev->intr_wq); ++ atomic_set(&dev->open_excl, 0); ++ atomic_set(&dev->ioctl_excl, 0); ++ INIT_LIST_HEAD(&dev->tx_idle); ++ INIT_LIST_HEAD(&dev->intr_idle); ++ ++ dev->wq = create_singlethread_workqueue("f_mtp"); ++ if (!dev->wq) { ++ ret = -ENOMEM; ++ goto err1; ++ } ++ INIT_WORK(&dev->send_file_work, send_file_work); ++ INIT_WORK(&dev->receive_file_work, receive_file_work); ++ ++ _mtp_dev = dev; ++ ++ ret = misc_register(&mtp_device); ++ if (ret) ++ goto err2; ++ ++ return 0; ++ ++err2: ++ destroy_workqueue(dev->wq); ++err1: ++ _mtp_dev = NULL; ++ kfree(dev); ++ printk(KERN_ERR "mtp gadget driver failed to initialize\n"); ++ return ret; ++} ++ ++static int __maybe_unused mtp_setup(void) ++{ ++ return __mtp_setup(NULL); ++} ++ ++static int mtp_setup_configfs(struct mtp_instance *fi_mtp) ++{ ++ return __mtp_setup(fi_mtp); ++} ++ ++ ++static void mtp_cleanup(void) ++{ ++ struct mtp_dev *dev = _mtp_dev; ++ ++ if (!dev) ++ return; ++ ++ misc_deregister(&mtp_device); ++ destroy_workqueue(dev->wq); ++ _mtp_dev = NULL; ++ kfree(dev); ++} ++ ++static struct mtp_instance *to_mtp_instance(struct config_item *item) ++{ ++ return container_of(to_config_group(item), struct mtp_instance, ++ func_inst.group); ++} ++ ++static void mtp_attr_release(struct config_item *item) ++{ ++ struct mtp_instance *fi_mtp = to_mtp_instance(item); ++ usb_put_function_instance(&fi_mtp->func_inst); ++} ++ ++static struct configfs_item_operations mtp_item_ops = { ++ .release = mtp_attr_release, ++}; ++ ++static struct config_item_type mtp_func_type = { ++ .ct_item_ops = &mtp_item_ops, ++ .ct_owner = THIS_MODULE, ++}; ++ ++ ++static struct mtp_instance *to_fi_mtp(struct usb_function_instance *fi) ++{ ++ return container_of(fi, struct mtp_instance, func_inst); ++} ++ ++static int mtp_set_inst_name(struct usb_function_instance *fi, const char *name) ++{ ++ struct mtp_instance *fi_mtp; ++ char *ptr; ++ int name_len; ++ ++ name_len = strlen(name) + 1; ++ if (name_len > MAX_INST_NAME_LEN) ++ return -ENAMETOOLONG; ++ ++ ptr = kstrndup(name, name_len, GFP_KERNEL); ++ if (!ptr) ++ return -ENOMEM; ++ ++ fi_mtp = to_fi_mtp(fi); ++ fi_mtp->name = ptr; ++ ++ return 0; ++} ++ ++static void mtp_free_inst(struct usb_function_instance *fi) ++{ ++ struct mtp_instance *fi_mtp; ++ ++ fi_mtp = to_fi_mtp(fi); ++ kfree(fi_mtp->name); ++ mtp_cleanup(); ++ kfree(fi_mtp); ++} ++ ++struct usb_function_instance *alloc_inst_mtp_ptp(bool mtp_config) ++{ ++ struct mtp_instance *fi_mtp; ++ int ret = 0; ++ ++ fi_mtp = kzalloc(sizeof(*fi_mtp), GFP_KERNEL); ++ if (!fi_mtp) ++ return ERR_PTR(-ENOMEM); ++ fi_mtp->func_inst.set_inst_name = mtp_set_inst_name; ++ fi_mtp->func_inst.free_func_inst = mtp_free_inst; ++ ++ if (mtp_config) { ++ ret = mtp_setup_configfs(fi_mtp); ++ if (ret) { ++ kfree(fi_mtp); ++ pr_err("Error setting MTP\n"); ++ return ERR_PTR(ret); ++ } ++ } else ++ fi_mtp->dev = _mtp_dev; ++ ++ config_group_init_type_name(&fi_mtp->func_inst.group, ++ "", &mtp_func_type); ++ ++ return &fi_mtp->func_inst; ++} ++EXPORT_SYMBOL_GPL(alloc_inst_mtp_ptp); ++ ++static struct usb_function_instance *mtp_alloc_inst(void) ++{ ++ return alloc_inst_mtp_ptp(true); ++} ++ ++static int mtp_ctrlreq_configfs(struct usb_function *f, ++ const struct usb_ctrlrequest *ctrl) ++{ ++ return mtp_ctrlrequest(f->config->cdev, ctrl); ++} ++ ++static void mtp_free(struct usb_function *f) ++{ ++ /*NO-OP: no function specific resource allocation in mtp_alloc*/ ++} ++ ++struct usb_function *function_alloc_mtp_ptp(struct usb_function_instance *fi, ++ bool mtp_config) ++{ ++ struct mtp_instance *fi_mtp = to_fi_mtp(fi); ++ struct mtp_dev *dev; ++ ++ /* ++ * PTP piggybacks on MTP function so make sure we have ++ * created MTP function before we associate this PTP ++ * function with a gadget configuration. ++ */ ++ if (fi_mtp->dev == NULL) { ++ pr_err("Error: Create MTP function before linking" ++ " PTP function with a gadget configuration\n"); ++ pr_err("\t1: Delete existing PTP function if any\n"); ++ pr_err("\t2: Create MTP function\n"); ++ pr_err("\t3: Create and symlink PTP function" ++ " with a gadget configuration\n"); ++ return NULL; ++ } ++ ++ dev = fi_mtp->dev; ++ dev->function.name = DRIVER_NAME; ++ dev->function.strings = mtp_strings; ++ if (mtp_config) { ++ dev->function.fs_descriptors = fs_mtp_descs; ++ dev->function.hs_descriptors = hs_mtp_descs; ++ } else { ++ dev->function.fs_descriptors = fs_ptp_descs; ++ dev->function.hs_descriptors = hs_ptp_descs; ++ } ++ dev->function.bind = mtp_function_bind; ++ dev->function.unbind = mtp_function_unbind; ++ dev->function.set_alt = mtp_function_set_alt; ++ dev->function.disable = mtp_function_disable; ++ dev->function.setup = mtp_ctrlreq_configfs; ++ dev->function.free_func = mtp_free; ++ ++ return &dev->function; ++} ++EXPORT_SYMBOL_GPL(function_alloc_mtp_ptp); ++ ++static struct usb_function *mtp_alloc(struct usb_function_instance *fi) ++{ ++ return function_alloc_mtp_ptp(fi, true); ++} ++ ++DECLARE_USB_FUNCTION_INIT(mtp, mtp_alloc_inst, mtp_alloc); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/usb/gadget/function/f_mtp.h b/drivers/usb/gadget/function/f_mtp.h +new file mode 100644 +index 0000000..7adb1ff +--- /dev/null ++++ b/drivers/usb/gadget/function/f_mtp.h +@@ -0,0 +1,18 @@ ++/* ++ * Copyright (C) 2014 Google, Inc. ++ * Author: Badhri Jagan Sridharan ++ * ++ * 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. ++ * ++ */ ++ ++extern struct usb_function_instance *alloc_inst_mtp_ptp(bool mtp_config); ++extern struct usb_function *function_alloc_mtp_ptp( ++ struct usb_function_instance *fi, bool mtp_config); +diff --git a/drivers/usb/gadget/function/f_ptp.c b/drivers/usb/gadget/function/f_ptp.c +new file mode 100644 +index 0000000..da3e4d5 +--- /dev/null ++++ b/drivers/usb/gadget/function/f_ptp.c +@@ -0,0 +1,38 @@ ++/* ++ * Gadget Function Driver for PTP ++ * ++ * Copyright (C) 2014 Google, Inc. ++ * Author: Badhri Jagan Sridharan ++ * ++ * 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 ++#include ++ ++#include ++#include ++ ++#include "f_mtp.h" ++ ++static struct usb_function_instance *ptp_alloc_inst(void) ++{ ++ return alloc_inst_mtp_ptp(false); ++} ++ ++static struct usb_function *ptp_alloc(struct usb_function_instance *fi) ++{ ++ return function_alloc_mtp_ptp(fi, false); ++} ++ ++DECLARE_USB_FUNCTION_INIT(ptp, ptp_alloc_inst, ptp_alloc); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Badhri Jagan Sridharan"); +diff --git a/drivers/usb/gadget/function/f_rndis.c b/drivers/usb/gadget/function/f_rndis.c +index f13fc6a..f4286a4 100644 +--- a/drivers/usb/gadget/function/f_rndis.c ++++ b/drivers/usb/gadget/function/f_rndis.c +@@ -70,6 +70,16 @@ + * - MS-Windows drivers sometimes emit undocumented requests. + */ + ++static unsigned int rndis_dl_max_pkt_per_xfer = 3; ++module_param(rndis_dl_max_pkt_per_xfer, uint, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(rndis_dl_max_pkt_per_xfer, ++ "Maximum packets per transfer for DL aggregation"); ++ ++static unsigned int rndis_ul_max_pkt_per_xfer = 3; ++module_param(rndis_ul_max_pkt_per_xfer, uint, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(rndis_ul_max_pkt_per_xfer, ++ "Maximum packets per transfer for UL aggregation"); ++ + struct f_rndis { + struct gether port; + u8 ctrl_id, data_id; +@@ -378,7 +388,7 @@ static struct sk_buff *rndis_add_header(struct gether *port, + if (skb2) + rndis_add_hdr(skb2); + +- dev_kfree_skb(skb); ++ dev_kfree_skb_irq(skb); + return skb2; + } + +@@ -451,6 +461,7 @@ static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req) + { + struct f_rndis *rndis = req->context; + int status; ++ rndis_init_msg_type *buf; + + /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */ + // spin_lock(&dev->lock); +@@ -458,6 +469,21 @@ static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req) + if (status < 0) + pr_err("RNDIS command error %d, %d/%d\n", + status, req->actual, req->length); ++ ++ buf = (rndis_init_msg_type *)req->buf; ++ ++ if (buf->MessageType == RNDIS_MSG_INIT) { ++ if (buf->MaxTransferSize > 2048) ++ rndis->port.multi_pkt_xfer = 1; ++ else ++ rndis->port.multi_pkt_xfer = 0; ++ pr_info_once("%s: MaxTransferSize: %d : Multi_pkt_txr: %s\n", ++ __func__, buf->MaxTransferSize, ++ rndis->port.multi_pkt_xfer ? "enabled" : ++ "disabled"); ++ if (rndis_dl_max_pkt_per_xfer <= 1) ++ rndis->port.multi_pkt_xfer = 0; ++ } + // spin_unlock(&dev->lock); + } + +@@ -799,6 +825,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) + + rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, 0); + rndis_set_host_mac(rndis->config, rndis->ethaddr); ++ rndis_set_max_pkt_xfer(rndis->config, rndis_ul_max_pkt_per_xfer); + + if (rndis->manufacturer && rndis->vendorID && + rndis_set_param_vendor(rndis->config, rndis->vendorID, +@@ -843,6 +870,62 @@ fail: + return status; + } + ++static void ++rndis_old_unbind(struct usb_configuration *c, struct usb_function *f) ++{ ++ struct f_rndis *rndis = func_to_rndis(f); ++ ++ rndis_deregister(rndis->config); ++ ++ usb_free_all_descriptors(f); ++ ++ kfree(rndis->notify_req->buf); ++ usb_ep_free_request(rndis->notify, rndis->notify_req); ++ ++ kfree(rndis); ++} ++ ++int ++rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], ++ u32 vendorID, const char *manufacturer, struct eth_dev *dev) ++{ ++ struct f_rndis *rndis; ++ int status; ++ ++ /* allocate and initialize one new instance */ ++ status = -ENOMEM; ++ rndis = kzalloc(sizeof *rndis, GFP_KERNEL); ++ if (!rndis) ++ goto fail; ++ ++ memcpy(rndis->ethaddr, ethaddr, ETH_ALEN); ++ rndis->vendorID = vendorID; ++ rndis->manufacturer = manufacturer; ++ ++ rndis->port.ioport = dev; ++ /* RNDIS activates when the host changes this filter */ ++ rndis->port.cdc_filter = 0; ++ ++ /* RNDIS has special (and complex) framing */ ++ rndis->port.header_len = sizeof(struct rndis_packet_msg_type); ++ rndis->port.wrap = rndis_add_header; ++ rndis->port.unwrap = rndis_rm_hdr; ++ ++ rndis->port.func.name = "rndis"; ++ /* descriptors are per-instance copies */ ++ rndis->port.func.bind = rndis_bind; ++ rndis->port.func.unbind = rndis_old_unbind; ++ rndis->port.func.set_alt = rndis_set_alt; ++ rndis->port.func.setup = rndis_setup; ++ rndis->port.func.disable = rndis_disable; ++ ++ status = usb_add_function(c, &rndis->port.func); ++ if (status) ++ kfree(rndis); ++fail: ++ return status; ++} ++ + void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net) + { + struct f_rndis_opts *opts; +@@ -993,6 +1076,8 @@ static struct usb_function *rndis_alloc(struct usb_function_instance *fi) + rndis->port.header_len = sizeof(struct rndis_packet_msg_type); + rndis->port.wrap = rndis_add_header; + rndis->port.unwrap = rndis_rm_hdr; ++ rndis->port.ul_max_pkts_per_xfer = rndis_ul_max_pkt_per_xfer; ++ rndis->port.dl_max_pkts_per_xfer = rndis_dl_max_pkt_per_xfer; + + rndis->port.func.name = "rndis"; + /* descriptors are per-instance copies */ +diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c +index f7b2032..4a4823b 100644 +--- a/drivers/usb/gadget/function/f_uac1.c ++++ b/drivers/usb/gadget/function/f_uac1.c +@@ -1,24 +1,61 @@ + /* +- * f_audio.c -- USB Audio class function driver +- * +- * Copyright (C) 2008 Bryan Wu +- * Copyright (C) 2008 Analog Devices, Inc ++ * f_uac1.c -- USB Audio Class 1.0 Function (using u_audio API) + * +- * Enter bugs at http://blackfin.uclinux.org/ ++ * Copyright (C) 2016 Ruslan Bilovol + * +- * Licensed under the GPL-2 or later. ++ * This driver doesn't expect any real Audio codec to be present ++ * on the device - the audio streams are simply sinked to and ++ * sourced from a virtual ALSA sound card created. ++ * ++ * This file is based on f_uac1.c which is ++ * Copyright (C) 2008 Bryan Wu ++ * Copyright (C) 2008 Analog Devices, 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. + */ + +-#include +-#include ++#include + #include +-#include +-#include + ++#include ++#include ++#include "uac_ex.h" ++#include "uac_v4l2_ex.h" + #include "u_uac1.h" + +-static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value); +-static int generic_get_cmd(struct usb_audio_control *con, u8 cmd); ++struct f_uac1 { ++ struct uac_device uac_dev; ++ u8 ac_intf, as_in_intf, as_out_intf; ++ u8 ac_alt, as_in_alt, as_out_alt; /* needed for get_alt() */ ++}; ++ ++struct uac1_format_type_ii_discrete_descriptor { ++ __u8 bLength; ++ __u8 bDescriptorType; ++ __u8 bDescriptorSubtype; ++ __u8 bFormatType; ++ __le16 wMaxBitRate; ++ __le16 wSamplesPerFrame; ++ __u8 bSamFreqType; ++ __u8 tSamFreq[4][3]; ++} __attribute__((packed)); ++ ++struct uac1_format_type_ii_ac3_descriptor { ++ __u8 bLength; ++ __u8 bDescriptorType; ++ __u8 bDescriptorSubtype; ++ __le16 wFormatTag; ++ __u8 bmBSID[4]; ++ __u8 bmAC3Features; ++} __attribute__((packed)); ++ ++static inline struct f_uac1 *func_to_uac1(struct usb_function *f) ++{ ++ return container_of(f, struct f_uac1, uac_dev.func); ++} + + /* + * DESCRIPTORS ... most are static, but strings and full +@@ -26,12 +63,28 @@ static int generic_get_cmd(struct usb_audio_control *con, u8 cmd); + */ + + /* +- * We have two interfaces- AudioControl and AudioStreaming +- * TODO: only supcard playback currently ++ * We have three interfaces - one AudioControl and two AudioStreaming ++ * ++ * The driver implements a simple UAC_1 topology. ++ * USB-OUT -> IT_1 -> OT_2 -> ALSA_Capture ++ * ALSA_Playback -> IT_3 -> OT_4 -> USB-IN + */ +-#define F_AUDIO_AC_INTERFACE 0 +-#define F_AUDIO_AS_INTERFACE 1 +-#define F_AUDIO_NUM_INTERFACES 2 ++#define F_AUDIO_AC_INTERFACE 0 ++#define F_AUDIO_AS_OUT_INTERFACE 1 ++#define F_AUDIO_AS_IN_INTERFACE 2 ++/* Number of streaming interfaces */ ++#define F_AUDIO_NUM_INTERFACES 1 ++ ++static struct usb_interface_assoc_descriptor uac_iad = { ++ .bLength = sizeof(uac_iad), ++ .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, ++ .bFirstInterface = 0, ++ .bInterfaceCount = 2, ++ .bFunctionClass = USB_CLASS_AUDIO, ++ .bFunctionSubClass = 0x00, ++ .bFunctionProtocol = 0x00, ++ .iFunction = 0, ++}; + + /* B.3.1 Standard AC Interface Descriptor */ + static struct usb_interface_descriptor ac_interface_desc = { +@@ -42,89 +95,96 @@ static struct usb_interface_descriptor ac_interface_desc = { + .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, + }; + +-DECLARE_UAC_AC_HEADER_DESCRIPTOR(2); ++/* ++ * The number of AudioStreaming and MIDIStreaming interfaces ++ * in the Audio Interface Collection ++ */ ++DECLARE_UAC_AC_HEADER_DESCRIPTOR(1); + + #define UAC_DT_AC_HEADER_LENGTH UAC_DT_AC_HEADER_SIZE(F_AUDIO_NUM_INTERFACES) +-/* 1 input terminal, 1 output terminal and 1 feature unit */ +-#define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH + UAC_DT_INPUT_TERMINAL_SIZE \ +- + UAC_DT_OUTPUT_TERMINAL_SIZE + UAC_DT_FEATURE_UNIT_SIZE(0)) ++ ++/* 2 input terminals and 2 output terminals */ ++#define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH \ ++ + 1*UAC_DT_INPUT_TERMINAL_SIZE + 1*UAC_DT_OUTPUT_TERMINAL_SIZE) ++ + /* B.3.2 Class-Specific AC Interface Descriptor */ +-static struct uac1_ac_header_descriptor_2 ac_header_desc = { ++static struct uac1_ac_header_descriptor_1 ac_header_desc = { + .bLength = UAC_DT_AC_HEADER_LENGTH, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubtype = UAC_HEADER, +- .bcdADC = __constant_cpu_to_le16(0x0100), +- .wTotalLength = __constant_cpu_to_le16(UAC_DT_TOTAL_LENGTH), ++ .bcdADC = cpu_to_le16(0x0100), ++ .wTotalLength = cpu_to_le16(UAC_DT_TOTAL_LENGTH), + .bInCollection = F_AUDIO_NUM_INTERFACES, + .baInterfaceNr = { +- [0] = F_AUDIO_AC_INTERFACE, +- [1] = F_AUDIO_AS_INTERFACE, ++ /* Interface number of the AudioStream interfaces */ ++ [0] = 1, + } + }; + +-#define INPUT_TERMINAL_ID 1 +-static struct uac_input_terminal_descriptor input_terminal_desc = { ++#define USB_OUT_IT_ID 1 ++static struct uac_input_terminal_descriptor usb_out_it_desc = { + .bLength = UAC_DT_INPUT_TERMINAL_SIZE, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubtype = UAC_INPUT_TERMINAL, +- .bTerminalID = INPUT_TERMINAL_ID, +- .wTerminalType = UAC_TERMINAL_STREAMING, ++ .bTerminalID = USB_OUT_IT_ID, ++ .wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING), + .bAssocTerminal = 0, +- .wChannelConfig = 0x3, ++ .wChannelConfig = cpu_to_le16(0x3), + }; + +-DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(0); +- +-#define FEATURE_UNIT_ID 2 +-static struct uac_feature_unit_descriptor_0 feature_unit_desc = { +- .bLength = UAC_DT_FEATURE_UNIT_SIZE(0), ++#define IO_OUT_OT_ID 2 ++static struct uac1_output_terminal_descriptor io_out_ot_desc = { ++ .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE, + .bDescriptorType = USB_DT_CS_INTERFACE, +- .bDescriptorSubtype = UAC_FEATURE_UNIT, +- .bUnitID = FEATURE_UNIT_ID, +- .bSourceID = INPUT_TERMINAL_ID, +- .bControlSize = 2, +- .bmaControls[0] = (UAC_FU_MUTE | UAC_FU_VOLUME), ++ .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, ++ .bTerminalID = IO_OUT_OT_ID, ++ .wTerminalType = cpu_to_le16(UAC_OUTPUT_TERMINAL_SPEAKER), ++ .bAssocTerminal = 0, ++ .bSourceID = USB_OUT_IT_ID, + }; + +-static struct usb_audio_control mute_control = { +- .list = LIST_HEAD_INIT(mute_control.list), +- .name = "Mute Control", +- .type = UAC_FU_MUTE, +- /* Todo: add real Mute control code */ +- .set = generic_set_cmd, +- .get = generic_get_cmd, ++#define IO_IN_IT_ID 3 ++static struct uac_input_terminal_descriptor io_in_it_desc = { ++ .bLength = UAC_DT_INPUT_TERMINAL_SIZE, ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_INPUT_TERMINAL, ++ .bTerminalID = IO_IN_IT_ID, ++ .wTerminalType = cpu_to_le16(UAC_INPUT_TERMINAL_MICROPHONE), ++ .bAssocTerminal = 0, ++ .wChannelConfig = cpu_to_le16(0x3), + }; + +-static struct usb_audio_control volume_control = { +- .list = LIST_HEAD_INIT(volume_control.list), +- .name = "Volume Control", +- .type = UAC_FU_VOLUME, +- /* Todo: add real Volume control code */ +- .set = generic_set_cmd, +- .get = generic_get_cmd, ++#define USB_IN_OT_ID 4 ++static struct uac1_output_terminal_descriptor usb_in_ot_desc = { ++ .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE, ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, ++ .bTerminalID = USB_IN_OT_ID, ++ .wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING), ++ .bAssocTerminal = 0, ++ .bSourceID = IO_IN_IT_ID, + }; + +-static struct usb_audio_control_selector feature_unit = { +- .list = LIST_HEAD_INIT(feature_unit.list), +- .id = FEATURE_UNIT_ID, +- .name = "Mute & Volume Control", +- .type = UAC_FEATURE_UNIT, +- .desc = (struct usb_descriptor_header *)&feature_unit_desc, ++/* B.4.1 Standard AS Interface Descriptor */ ++static struct usb_interface_descriptor as_out_interface_alt_0_desc = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bAlternateSetting = 0, ++ .bNumEndpoints = 0, ++ .bInterfaceClass = USB_CLASS_AUDIO, ++ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, + }; + +-#define OUTPUT_TERMINAL_ID 3 +-static struct uac1_output_terminal_descriptor output_terminal_desc = { +- .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE, +- .bDescriptorType = USB_DT_CS_INTERFACE, +- .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, +- .bTerminalID = OUTPUT_TERMINAL_ID, +- .wTerminalType = UAC_OUTPUT_TERMINAL_SPEAKER, +- .bAssocTerminal = FEATURE_UNIT_ID, +- .bSourceID = FEATURE_UNIT_ID, ++static struct usb_interface_descriptor as_out_interface_alt_1_desc = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bAlternateSetting = 1, ++ .bNumEndpoints = 1, ++ .bInterfaceClass = USB_CLASS_AUDIO, ++ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, + }; + +-/* B.4.1 Standard AS Interface Descriptor */ +-static struct usb_interface_descriptor as_interface_alt_0_desc = { ++static struct usb_interface_descriptor as_in_interface_alt_0_desc = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bAlternateSetting = 0, +@@ -133,7 +193,7 @@ static struct usb_interface_descriptor as_interface_alt_0_desc = { + .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, + }; + +-static struct usb_interface_descriptor as_interface_alt_1_desc = { ++static struct usb_interface_descriptor as_in_interface_alt_1_desc = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bAlternateSetting = 1, +@@ -142,26 +202,62 @@ static struct usb_interface_descriptor as_interface_alt_1_desc = { + .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, + }; + ++static struct usb_interface_descriptor as_in_interface_alt_2_desc = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bAlternateSetting = 2, ++ .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_header_desc = { ++static struct uac1_as_header_descriptor as_in_header_desc = { + .bLength = UAC_DT_AS_HEADER_SIZE, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubtype = UAC_AS_GENERAL, +- .bTerminalLink = INPUT_TERMINAL_ID, ++ .bTerminalLink = USB_IN_OT_ID, + .bDelay = 1, +- .wFormatTag = UAC_FORMAT_TYPE_I_PCM, ++ .wFormatTag = cpu_to_le16(UAC_FORMAT_TYPE_I_PCM), ++}; ++ ++/* B.4.2 Class-Specific AS Interface Descriptor */ ++static struct uac1_as_header_descriptor as_in_header_2_desc = { ++ .bLength = UAC_DT_AS_HEADER_SIZE, ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_AS_GENERAL, ++ .bTerminalLink = USB_IN_OT_ID, ++ .bDelay = 1, ++ .wFormatTag = cpu_to_le16(UAC_FORMAT_TYPE_II_AC3), ++}; ++ ++static struct uac1_format_type_ii_discrete_descriptor as_in_type_ii_ac3_desc = { ++ .bLength = sizeof(as_in_type_ii_ac3_desc), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_FORMAT_TYPE, ++ .bFormatType = UAC_FORMAT_TYPE_II, ++ .wMaxBitRate = 2, /*FIXME: how to set MaxBitRate value ?? */ ++ .wSamplesPerFrame = 16, /*FIXME: how to set SamplesPerFrame??*/ ++ .bSamFreqType = 4, ++}; ++ ++static struct uac1_format_type_ii_ac3_descriptor as_in_type_ii_ac3_spec_desc = { ++ .bLength = sizeof(as_in_type_ii_ac3_spec_desc), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_FORMAT_SPECIFIC, ++ .wFormatTag = cpu_to_le16(UAC_FORMAT_TYPE_II_AC3), + }; + +-DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(1); ++DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(4); + +-static struct uac_format_type_i_discrete_descriptor_1 as_type_i_desc = { +- .bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1), ++static struct uac_format_type_i_discrete_descriptor_4 as_out_type_i_desc = { ++ .bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(4), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubtype = UAC_FORMAT_TYPE, + .bFormatType = UAC_FORMAT_TYPE_I, + .bSubframeSize = 2, + .bBitResolution = 16, +- .bSamFreqType = 1, ++ .bSamFreqType = 4, + }; + + /* Standard ISO OUT Endpoint Descriptor */ +@@ -175,53 +271,86 @@ static struct usb_endpoint_descriptor as_out_ep_desc = { + .bInterval = 4, + }; + ++static struct uac_format_type_i_discrete_descriptor_4 as_in_type_i_desc = { ++ .bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(4), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_FORMAT_TYPE, ++ .bFormatType = UAC_FORMAT_TYPE_I, ++ .bSubframeSize = 2, ++ .bBitResolution = 16, ++ .bSamFreqType = 4, ++}; ++ ++/* Standard ISO OUT Endpoint Descriptor */ ++static struct usb_endpoint_descriptor as_in_ep_desc = { ++ .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_IN, ++ .bmAttributes = USB_ENDPOINT_SYNC_ASYNC ++ | USB_ENDPOINT_XFER_ISOC, ++ .wMaxPacketSize = cpu_to_le16(UAC1_OUT_EP_MAX_PACKET_SIZE), ++ .bInterval = 4, ++}; ++ + /* Class-specific AS ISO OUT Endpoint Descriptor */ +-static struct uac_iso_endpoint_descriptor as_iso_out_desc = { ++static struct uac_iso_endpoint_descriptor as_iso_in_desc = { + .bLength = UAC_ISO_ENDPOINT_DESC_SIZE, + .bDescriptorType = USB_DT_CS_ENDPOINT, + .bDescriptorSubtype = UAC_EP_GENERAL, +- .bmAttributes = 1, +- .bLockDelayUnits = 1, +- .wLockDelay = __constant_cpu_to_le16(1), ++ .bmAttributes = 1, ++ .bLockDelayUnits = 0, ++ .wLockDelay = 0, + }; + + static struct usb_descriptor_header *f_audio_desc[] = { ++ (struct usb_descriptor_header *)&uac_iad, + (struct usb_descriptor_header *)&ac_interface_desc, + (struct usb_descriptor_header *)&ac_header_desc, +- +- (struct usb_descriptor_header *)&input_terminal_desc, +- (struct usb_descriptor_header *)&output_terminal_desc, +- (struct usb_descriptor_header *)&feature_unit_desc, +- +- (struct usb_descriptor_header *)&as_interface_alt_0_desc, +- (struct usb_descriptor_header *)&as_interface_alt_1_desc, +- (struct usb_descriptor_header *)&as_header_desc, +- +- (struct usb_descriptor_header *)&as_type_i_desc, +- +- (struct usb_descriptor_header *)&as_out_ep_desc, +- (struct usb_descriptor_header *)&as_iso_out_desc, ++ (struct usb_descriptor_header *)&io_in_it_desc, ++ (struct usb_descriptor_header *)&usb_in_ot_desc, ++ (struct usb_descriptor_header *)&as_in_interface_alt_0_desc, ++ (struct usb_descriptor_header *)&as_in_interface_alt_1_desc, ++ (struct usb_descriptor_header *)&as_in_header_desc, ++ (struct usb_descriptor_header *)&as_in_type_i_desc, ++ (struct usb_descriptor_header *)&as_in_ep_desc, ++ (struct usb_descriptor_header *)&as_iso_in_desc, ++ (struct usb_descriptor_header *)&as_in_interface_alt_2_desc, ++ (struct usb_descriptor_header *)&as_in_header_2_desc, ++ (struct usb_descriptor_header *)&as_in_type_ii_ac3_desc, ++ (struct usb_descriptor_header *)&as_in_type_ii_ac3_spec_desc, ++ (struct usb_descriptor_header *)&as_in_ep_desc, ++ (struct usb_descriptor_header *)&as_iso_in_desc, + NULL, + }; + + enum { + STR_AC_IF, +- STR_INPUT_TERMINAL, +- STR_INPUT_TERMINAL_CH_NAMES, +- STR_FEAT_DESC_0, +- STR_OUTPUT_TERMINAL, +- STR_AS_IF_ALT0, +- STR_AS_IF_ALT1, ++ STR_USB_OUT_IT, ++ STR_USB_OUT_IT_CH_NAMES, ++ STR_IO_OUT_OT, ++ STR_IO_IN_IT, ++ STR_IO_IN_IT_CH_NAMES, ++ STR_USB_IN_OT, ++ STR_AS_OUT_IF_ALT0, ++ STR_AS_OUT_IF_ALT1, ++ STR_AS_IN_IF_ALT0, ++ STR_AS_IN_IF_ALT1, ++ STR_AS_IN_IF_ALT2, + }; + + static struct usb_string strings_uac1[] = { +- [STR_AC_IF].s = "AC Interface", +- [STR_INPUT_TERMINAL].s = "Input terminal", +- [STR_INPUT_TERMINAL_CH_NAMES].s = "Channels", +- [STR_FEAT_DESC_0].s = "Volume control & mute", +- [STR_OUTPUT_TERMINAL].s = "Output terminal", +- [STR_AS_IF_ALT0].s = "AS Interface", +- [STR_AS_IF_ALT1].s = "AS Interface", ++ [STR_AC_IF].s = "Hisilicon HD Audio", ++ [STR_USB_OUT_IT].s = "Playback Input terminal", ++ [STR_USB_OUT_IT_CH_NAMES].s = "Playback Channels", ++ [STR_IO_OUT_OT].s = "Playback Output terminal", ++ [STR_IO_IN_IT].s = "Capture Input terminal", ++ [STR_IO_IN_IT_CH_NAMES].s = "Capture Channels", ++ [STR_USB_IN_OT].s = "Capture Output terminal", ++ [STR_AS_OUT_IF_ALT0].s = "Playback Inactive", ++ [STR_AS_OUT_IF_ALT1].s = "Playback Active", ++ [STR_AS_IN_IF_ALT0].s = "Capture Inactive", ++ [STR_AS_IN_IF_ALT1].s = "Capture Active", ++ [STR_AS_IN_IF_ALT2].s = "Capture Active", + { }, + }; + +@@ -239,227 +368,23 @@ static struct usb_gadget_strings *uac1_strings[] = { + * This function is an ALSA sound card following USB Audio Class Spec 1.0. + */ + +-/*-------------------------------------------------------------------------*/ +-struct f_audio_buf { +- u8 *buf; +- int actual; +- struct list_head list; +-}; +- +-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) +- return ERR_PTR(-ENOMEM); +- +- copy_buf->buf = kzalloc(buf_size, GFP_ATOMIC); +- if (!copy_buf->buf) { +- kfree(copy_buf); +- return ERR_PTR(-ENOMEM); +- } +- +- return copy_buf; +-} +- +-static void f_audio_buffer_free(struct f_audio_buf *audio_buf) +-{ +- kfree(audio_buf->buf); +- kfree(audio_buf); +-} +-/*-------------------------------------------------------------------------*/ +- +-struct f_audio { +- struct gaudio card; +- +- /* endpoints handle full and/or high speeds */ +- struct usb_ep *out_ep; +- +- spinlock_t lock; +- struct f_audio_buf *copy_buf; +- struct work_struct playback_work; +- struct list_head play_queue; +- +- /* Control Set command */ +- struct list_head cs; +- u8 set_cmd; +- struct usb_audio_control *set_con; +-}; +- +-static inline struct f_audio *func_to_audio(struct usb_function *f) +-{ +- return container_of(f, struct f_audio, card.func); +-} +- +-/*-------------------------------------------------------------------------*/ +- +-static void f_audio_playback_work(struct work_struct *data) +-{ +- struct f_audio *audio = container_of(data, struct f_audio, +- playback_work); +- struct f_audio_buf *play_buf; +- +- spin_lock_irq(&audio->lock); +- if (list_empty(&audio->play_queue)) { +- spin_unlock_irq(&audio->lock); +- return; +- } +- play_buf = list_first_entry(&audio->play_queue, +- struct f_audio_buf, list); +- list_del(&play_buf->list); +- spin_unlock_irq(&audio->lock); +- +- u_audio_playback(&audio->card, play_buf->buf, play_buf->actual); +- f_audio_buffer_free(play_buf); +-} +- +-static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req) +-{ +- struct f_audio *audio = req->context; +- struct usb_composite_dev *cdev = audio->card.func.config->cdev; +- struct f_audio_buf *copy_buf = audio->copy_buf; +- struct f_uac1_opts *opts; +- int audio_buf_size; +- int err; +- +- opts = container_of(audio->card.func.fi, struct f_uac1_opts, +- func_inst); +- audio_buf_size = opts->audio_buf_size; +- +- if (!copy_buf) +- return -EINVAL; +- +- /* Copy buffer is full, add it to the play_queue */ +- if (audio_buf_size - copy_buf->actual < req->actual) { +- list_add_tail(©_buf->list, &audio->play_queue); +- schedule_work(&audio->playback_work); +- copy_buf = f_audio_buffer_alloc(audio_buf_size); +- if (IS_ERR(copy_buf)) +- 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) +- ERROR(cdev, "%s queue req: %d\n", ep->name, err); +- +- return 0; +- +-} +- +-static void f_audio_complete(struct usb_ep *ep, struct usb_request *req) +-{ +- struct f_audio *audio = req->context; +- int status = req->status; +- u32 data = 0; +- struct usb_ep *out_ep = audio->out_ep; +- +- switch (status) { +- +- case 0: /* normal completion? */ +- if (ep == out_ep) +- f_audio_out_ep_complete(ep, req); +- else if (audio->set_con) { +- memcpy(&data, req->buf, req->length); +- audio->set_con->set(audio->set_con, audio->set_cmd, +- le16_to_cpu(data)); +- audio->set_con = NULL; +- } +- break; +- default: +- break; +- } +-} +- +-static int audio_set_intf_req(struct usb_function *f, +- const struct usb_ctrlrequest *ctrl) +-{ +- struct f_audio *audio = func_to_audio(f); +- struct usb_composite_dev *cdev = f->config->cdev; +- struct usb_request *req = cdev->req; +- u8 id = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF); +- u16 len = le16_to_cpu(ctrl->wLength); +- u16 w_value = le16_to_cpu(ctrl->wValue); +- u8 con_sel = (w_value >> 8) & 0xFF; +- u8 cmd = (ctrl->bRequest & 0x0F); +- struct usb_audio_control_selector *cs; +- struct usb_audio_control *con; +- +- DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, entity %d\n", +- ctrl->bRequest, w_value, len, id); +- +- list_for_each_entry(cs, &audio->cs, list) { +- if (cs->id == id) { +- list_for_each_entry(con, &cs->control, list) { +- if (con->type == con_sel) { +- audio->set_con = con; +- break; +- } +- } +- break; +- } +- } +- +- audio->set_cmd = cmd; +- req->context = audio; +- req->complete = f_audio_complete; +- +- return len; +-} +- +-static int audio_get_intf_req(struct usb_function *f, +- const struct usb_ctrlrequest *ctrl) +-{ +- struct f_audio *audio = func_to_audio(f); +- struct usb_composite_dev *cdev = f->config->cdev; +- struct usb_request *req = cdev->req; +- int value = -EOPNOTSUPP; +- u8 id = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF); +- u16 len = le16_to_cpu(ctrl->wLength); +- u16 w_value = le16_to_cpu(ctrl->wValue); +- u8 con_sel = (w_value >> 8) & 0xFF; +- u8 cmd = (ctrl->bRequest & 0x0F); +- struct usb_audio_control_selector *cs; +- struct usb_audio_control *con; +- +- DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, entity %d\n", +- ctrl->bRequest, w_value, len, id); +- +- list_for_each_entry(cs, &audio->cs, list) { +- if (cs->id == id) { +- list_for_each_entry(con, &cs->control, list) { +- if (con->type == con_sel && con->get) { +- value = con->get(con, cmd); +- break; +- } +- } +- break; +- } +- } +- +- req->context = audio; +- req->complete = f_audio_complete; +- len = min_t(size_t, sizeof(value), len); +- memcpy(req->buf, &value, len); +- +- return len; +-} +- + static int audio_set_endpoint_req(struct usb_function *f, + const struct usb_ctrlrequest *ctrl) + { +- struct usb_composite_dev *cdev = f->config->cdev; ++ //struct usb_composite_dev *cdev = f->config->cdev; + int value = -EOPNOTSUPP; + u16 ep = le16_to_cpu(ctrl->wIndex); + u16 len = le16_to_cpu(ctrl->wLength); + u16 w_value = le16_to_cpu(ctrl->wValue); + +- DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n", +- ctrl->bRequest, w_value, len, ep); ++ printk(KERN_EMERG "%s:bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n", ++ __func__, ctrl->bRequest, w_value, len, ep); ++ ++ ++ if ((w_value >>8) != UAC_EP_CS_ATTR_SAMPLE_RATE) { ++ printk("!!!!! value = 0x%x\n", (w_value >>8)); ++ return value; ++ } + + switch (ctrl->bRequest) { + case UAC_SET_CUR: +@@ -489,16 +414,24 @@ static int audio_get_endpoint_req(struct usb_function *f, + const struct usb_ctrlrequest *ctrl) + { + struct usb_composite_dev *cdev = f->config->cdev; ++ struct f_uac1 *uac1 = func_to_uac1(f); ++ struct usb_request *req = uac1->uac_dev.control_req; ++ struct uac_device *uac = req->context; + int value = -EOPNOTSUPP; + u8 ep = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF); + u16 len = le16_to_cpu(ctrl->wLength); + u16 w_value = le16_to_cpu(ctrl->wValue); + +- DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n", +- ctrl->bRequest, w_value, len, ep); ++ printk(KERN_EMERG "%s:bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n", ++ __func__, ctrl->bRequest, w_value, len, ep); + + switch (ctrl->bRequest) { + case UAC_GET_CUR: ++ if ((w_value >>8) == UAC_EP_CS_ATTR_SAMPLE_RATE) { ++ memcpy(req->buf, &uac->params.p_srate, 3); ++ } ++ value = len; ++ break; + case UAC_GET_MIN: + case UAC_GET_MAX: + case UAC_GET_RES: +@@ -517,41 +450,25 @@ static int + f_audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) + { + struct usb_composite_dev *cdev = f->config->cdev; +- struct usb_request *req = cdev->req; ++ struct f_uac1 *uac1 = func_to_uac1(f); ++ struct usb_request *req = uac1->uac_dev.control_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); + ++ printk(KERN_EMERG "%s:\n", __func__); ++ + /* composite driver infrastructure handles everything; interface + * activation uses set_alt(). + */ + switch (ctrl->bRequestType) { +- case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE: +- value = audio_set_intf_req(f, ctrl); +- break; +- +- case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE: +- value = audio_get_intf_req(f, ctrl); +- break; +- + case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: +- value = audio_set_endpoint_req(f, ctrl); +- break; +- +- case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: +- value = audio_get_endpoint_req(f, ctrl); +- break; +- +- default: +- ERROR(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n", +- ctrl->bRequestType, ctrl->bRequest, +- w_value, w_index, w_length); +- } +- ++ { ++ value = audio_set_endpoint_req(f, ctrl); + /* respond with data transfer or status phase? */ + if (value >= 0) { +- DBG(cdev, "audio req%02x.%02x v%04x i%04x l%d\n", ++ printk(KERN_EMERG "audio req%02x.%02x v%04x i%04x l%d\n", + ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + req->zero = 0; +@@ -559,7 +476,29 @@ f_audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) + value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); + if (value < 0) + ERROR(cdev, "audio response on err %d\n", value); +- } ++ } ++ } ++ break; ++ ++ case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: ++ value = audio_get_endpoint_req(f, ctrl); ++ if (value >= 0) { ++ printk(KERN_EMERG "audio req%02x.%02x v%04x i%04x l%d\n", ++ ctrl->bRequestType, ctrl->bRequest, ++ w_value, w_index, w_length); ++ req->zero = 0; ++ req->length = value; ++ value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); ++ if (value < 0) ++ ERROR(cdev, "audio response on err %d\n", value); ++ } ++ break; ++ ++ default: ++ printk(KERN_EMERG "invalid control req%02x.%02x v%04x i%04x l%d\n", ++ ctrl->bRequestType, ctrl->bRequest, ++ w_value, w_index, w_length); ++ } + + /* device either stalls (value < 0) or reports success */ + return value; +@@ -567,343 +506,426 @@ f_audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) + + static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt) + { +- struct f_audio *audio = func_to_audio(f); +- struct usb_composite_dev *cdev = f->config->cdev; +- struct usb_ep *out_ep = audio->out_ep; +- struct usb_request *req; +- struct f_uac1_opts *opts; +- int req_buf_size, req_count, audio_buf_size; +- int i = 0, err = 0; ++ struct f_uac1 *uac1 = func_to_uac1(f); ++ int ret = 0; + +- DBG(cdev, "intf %d, alt %d\n", intf, alt); ++ printk(KERN_EMERG "%s:intf:%d alt=%d\n", __func__, intf, alt); + +- opts = container_of(f->fi, struct f_uac1_opts, func_inst); +- req_buf_size = opts->req_buf_size; +- req_count = opts->req_count; +- audio_buf_size = opts->audio_buf_size; +- +- if (intf == 1) { +- if (alt == 1) { +- usb_ep_enable(out_ep); +- out_ep->driver_data = audio; +- audio->copy_buf = f_audio_buffer_alloc(audio_buf_size); +- if (IS_ERR(audio->copy_buf)) +- return -ENOMEM; +- +- /* +- * allocate a bunch of read buffers +- * and queue them all at once. +- */ +- for (i = 0; i < req_count && err == 0; i++) { +- req = usb_ep_alloc_request(out_ep, GFP_ATOMIC); +- if (req) { +- req->buf = kzalloc(req_buf_size, +- GFP_ATOMIC); +- if (req->buf) { +- req->length = req_buf_size; +- req->context = audio; +- req->complete = +- f_audio_complete; +- err = usb_ep_queue(out_ep, +- req, GFP_ATOMIC); +- if (err) +- ERROR(cdev, +- "%s queue req: %d\n", +- out_ep->name, err); +- } else +- err = -ENOMEM; +- } else +- err = -ENOMEM; +- } ++ /* No i/f has more than 2 alt settings */ ++ if (alt > 1) { ++ printk(KERN_EMERG "%s:%d Error!\n", __func__, __LINE__); ++ return -EINVAL; ++ } + ++ if (intf == uac1->ac_intf) { ++ /* Control I/f has only 1 AltSetting - 0 */ ++ if (alt) { ++ printk(KERN_EMERG "%s:%d Error!\n", __func__, __LINE__); ++ return -EINVAL; ++ } ++ ++ /*FIXME: notify userpace uac has been connected*/ ++ { ++ struct uac_device *uac_dev = &uac1->uac_dev; ++ struct v4l2_event v4l2_event; ++ ++ memset(&v4l2_event, 0, sizeof(v4l2_event)); ++ v4l2_event.type = UAC_EVENT_CONNECT; ++ v4l2_event_queue(uac_dev->vdev, &v4l2_event); ++ ++ printk(KERN_EMERG "%s: trigger connect\n", __func__); ++ } ++ ++ return 0; ++ } ++ ++ if (intf == uac1->as_out_intf) { ++ uac1->as_out_alt = alt; ++ ++ if (alt) { + } else { +- struct f_audio_buf *copy_buf = audio->copy_buf; +- if (copy_buf) { +- list_add_tail(©_buf->list, +- &audio->play_queue); +- schedule_work(&audio->playback_work); +- } + } ++ } else if (intf == uac1->as_in_intf) { ++ uac1->as_in_alt = alt; ++ ++ if (alt) { ++ /*FIXME: notify userpace to start audio streaming*/ ++ { ++ struct uac_device *uac_dev = &uac1->uac_dev; ++ struct v4l2_event v4l2_event; ++ ++ memset(&v4l2_event, 0, sizeof(v4l2_event)); ++ v4l2_event.type = UAC_EVENT_STREAMON; ++ v4l2_event_queue(uac_dev->vdev, &v4l2_event); ++ ++ printk(KERN_EMERG "%s: trigger UAC_EVENT_STREAMON\n", __func__); ++ } ++ ++ ret = uac_device_start_playback(&uac1->uac_dev); ++ } else { ++ /*FIXME: notify userpace to start audio streaming*/ ++ { ++ struct uac_device *uac_dev = &uac1->uac_dev; ++ struct v4l2_event v4l2_event; ++ ++ memset(&v4l2_event, 0, sizeof(v4l2_event)); ++ v4l2_event.type = UAC_EVENT_STREAMOFF; ++ v4l2_event_queue(uac_dev->vdev, &v4l2_event); ++ ++ printk(KERN_EMERG "%s: trigger UAC_EVENT_STREAMOFF\n", __func__); ++ } ++ ++ uac_device_stop_playback(&uac1->uac_dev); ++ } ++ } else { ++ printk(KERN_EMERG "%s:%d Error!\n", __func__, __LINE__); ++ return -EINVAL; + } + +- return err; ++ return ret; + } + ++static int f_audio_get_alt(struct usb_function *f, unsigned intf) ++{ ++ struct f_uac1 *uac1 = func_to_uac1(f); ++ ++ printk(KERN_EMERG "%s:\n", __func__); ++ ++ if (intf == uac1->ac_intf) { ++ printk(KERN_EMERG "%s:ac_intf = %d\n", __func__, uac1->ac_intf); ++ return uac1->ac_alt; ++ } ++ else if (intf == uac1->as_out_intf) { ++ printk(KERN_EMERG "%s:as_out_intf = %d\n", __func__, uac1->as_out_intf); ++ return uac1->as_out_alt; ++ } ++ else if (intf == uac1->as_in_intf) { ++ printk(KERN_EMERG "%s:as_in_intf = %d\n", __func__, uac1->as_in_intf); ++ return uac1->as_in_alt; ++ } ++ else ++ printk(KERN_EMERG "%s:%d Invalid Interface %d!\n", ++ __func__, __LINE__, intf); ++ ++ return -EINVAL; ++} ++ ++ + static void f_audio_disable(struct usb_function *f) + { +- return; ++ struct f_uac1 *uac1 = func_to_uac1(f); ++ ++ uac1->as_out_alt = 0; ++ uac1->as_in_alt = 0; ++ ++ ++ /*FIXME: notify userpace to disconnect*/ ++ { ++ struct uac_device *uac_dev = &uac1->uac_dev; ++ struct v4l2_event v4l2_event; ++ ++ memset(&v4l2_event, 0, sizeof(v4l2_event)); ++ v4l2_event.type = UAC_EVENT_DISCONNECT; ++ v4l2_event_queue(uac_dev->vdev, &v4l2_event); ++ } + } + + /*-------------------------------------------------------------------------*/ + +-static void f_audio_build_desc(struct f_audio *audio) ++static int ++__uac_register_video(struct usb_composite_dev *dev, struct uac_device *uac_dev) + { +- struct gaudio *card = &audio->card; +- u8 *sam_freq; +- int rate; ++ struct usb_composite_dev *cdev = dev; ++ struct video_device *video; + +- /* Set channel numbers */ +- input_terminal_desc.bNrChannels = u_audio_get_playback_channels(card); +- as_type_i_desc.bNrChannels = u_audio_get_playback_channels(card); ++ /* TODO reference counting. */ ++ video = video_device_alloc(); ++ if (video == NULL) ++ return -ENOMEM; + +- /* Set sample rates */ +- rate = u_audio_get_playback_rate(card); +- sam_freq = as_type_i_desc.tSamFreq[0]; +- memcpy(sam_freq, &rate, 3); ++ video->v4l2_dev = &uac_dev->v4l2_dev; ++ video->fops = &uac_v4l2_fops; ++ video->ioctl_ops = &uac_v4l2_ioctl_ops; ++ video->release = video_device_release; ++ video->vfl_dir = VFL_DIR_TX; ++ strlcpy(video->name, cdev->gadget->name, sizeof(video->name)); ++ ++ uac_dev->vdev = video; ++ video_set_drvdata(video, uac_dev); ++ ++ return video_register_device(video, VFL_TYPE_GRABBER, -1); ++} + +- /* Todo: Set Sample bits and other parameters */ ++static void ++__uac_function_ep0_complete(struct usb_ep *ep, struct usb_request *req) ++{ ++ struct uac_device *uac = req->context; ++ struct v4l2_event v4l2_event; ++ struct uac_event *uac_event = (void *)&v4l2_event.u.data; ++ ++ /*FIXME: notify userpace to set audio resolution */ ++ if (req->actual == 3) ++ { ++ int rate = ((unsigned char*)req->buf)[0] | (((unsigned char*)req->buf)[1] << 8) | (((unsigned char*)req->buf)[2] << 16); ++ ++ uac->params.p_srate = rate; ++ uac->p_pktsize = (rate / 1000) * uac->params.p_ssize * num_channels(uac->params.p_chmask); + +- return; ++ memset(&v4l2_event, 0, sizeof(v4l2_event)); ++ v4l2_event.type = UAC_EVENT_DATA; ++ uac_event->data.length = req->actual; ++ memcpy(&uac_event->data.data, req->buf, req->actual); ++ v4l2_event_queue(uac->vdev, &v4l2_event); ++ ++ printk("%s:rate=%d srate = %d pkt_size=%d\n",__func__, rate, uac->params.p_srate, uac->p_pktsize); ++ } ++} ++ ++static void __print_params(struct uac_params *params) ++{ ++ printk(KERN_EMERG "pamrams: p_chmask=%d p_srate=%d(hz) p_ssize=%d \ ++ req_number=%d\n", ++ params->p_chmask, ++ params->p_srate, ++ params->p_ssize, ++ params->req_number ++ ); + } + + /* audio function driver setup/binding */ +-static int +-f_audio_bind(struct usb_configuration *c, struct usb_function *f) ++static int f_audio_bind(struct usb_configuration *c, struct usb_function *f) + { +- struct usb_composite_dev *cdev = c->cdev; +- struct f_audio *audio = func_to_audio(f); +- struct usb_string *us; +- int status; +- struct usb_ep *ep = NULL; +- struct f_uac1_opts *audio_opts; ++ struct usb_composite_dev *cdev = c->cdev; ++ struct usb_gadget *gadget = cdev->gadget; ++ struct f_uac1 *uac1 = func_to_uac1(f); ++ struct uac_device *uac_dev = &uac1->uac_dev; ++ struct f_uac1_opts *audio_opts; ++ struct usb_ep *ep = NULL; ++ struct usb_string *us; ++ u8 *sam_freq; ++ int rate; ++ int status; + + audio_opts = container_of(f->fi, struct f_uac1_opts, func_inst); +- audio->card.gadget = c->cdev->gadget; +- audio_opts->card = &audio->card; +- /* set up ASLA audio devices */ +- if (!audio_opts->bound) { +- status = gaudio_setup(&audio->card); +- if (status < 0) +- return status; +- audio_opts->bound = true; +- } ++ + us = usb_gstrings_attach(cdev, uac1_strings, ARRAY_SIZE(strings_uac1)); + if (IS_ERR(us)) + return PTR_ERR(us); ++ ++ uac_iad.iFunction = us[STR_AC_IF].id; + ac_interface_desc.iInterface = us[STR_AC_IF].id; +- input_terminal_desc.iTerminal = us[STR_INPUT_TERMINAL].id; +- input_terminal_desc.iChannelNames = us[STR_INPUT_TERMINAL_CH_NAMES].id; +- feature_unit_desc.iFeature = us[STR_FEAT_DESC_0].id; +- output_terminal_desc.iTerminal = us[STR_OUTPUT_TERMINAL].id; +- as_interface_alt_0_desc.iInterface = us[STR_AS_IF_ALT0].id; +- as_interface_alt_1_desc.iInterface = us[STR_AS_IF_ALT1].id; ++ usb_out_it_desc.iTerminal = us[STR_USB_OUT_IT].id; ++ usb_out_it_desc.iChannelNames = us[STR_USB_OUT_IT_CH_NAMES].id; ++ io_out_ot_desc.iTerminal = us[STR_IO_OUT_OT].id; ++ as_out_interface_alt_0_desc.iInterface = us[STR_AS_OUT_IF_ALT0].id; ++ as_out_interface_alt_1_desc.iInterface = us[STR_AS_OUT_IF_ALT1].id; ++ io_in_it_desc.iTerminal = us[STR_IO_IN_IT].id; ++ io_in_it_desc.iChannelNames = us[STR_IO_IN_IT_CH_NAMES].id; ++ usb_in_ot_desc.iTerminal = us[STR_USB_IN_OT].id; ++ as_in_interface_alt_0_desc.iInterface = us[STR_AS_IN_IF_ALT0].id; ++ as_in_interface_alt_1_desc.iInterface = us[STR_AS_IN_IF_ALT1].id; ++ as_in_interface_alt_2_desc.iInterface = us[STR_AS_IN_IF_ALT2].id; ++ ++ /* Set channel numbers */ ++ usb_out_it_desc.bNrChannels = num_channels(audio_opts->c_chmask); ++ usb_out_it_desc.wChannelConfig = cpu_to_le16(audio_opts->c_chmask); ++ as_out_type_i_desc.bNrChannels = num_channels(audio_opts->c_chmask); ++ as_out_type_i_desc.bSubframeSize = audio_opts->c_ssize; ++ as_out_type_i_desc.bBitResolution = audio_opts->c_ssize * 8; ++ io_in_it_desc.bNrChannels = num_channels(audio_opts->p_chmask); ++ io_in_it_desc.wChannelConfig = cpu_to_le16(audio_opts->p_chmask); ++ as_in_type_i_desc.bNrChannels = num_channels(audio_opts->p_chmask); ++ as_in_type_i_desc.bSubframeSize = audio_opts->p_ssize; ++ as_in_type_i_desc.bBitResolution = audio_opts->p_ssize * 8; ++ as_out_ep_desc.wMaxPacketSize = 48*audio_opts->c_ssize * num_channels(audio_opts->c_chmask); ++ /*FIXME: max_resolution * sample * channnel*/ ++ as_in_ep_desc.wMaxPacketSize = 48*audio_opts->p_ssize * num_channels(audio_opts->p_chmask); + + +- f_audio_build_desc(audio); ++ /* Set sample rates */ ++ /*rate = audio_opts->c_srate; ++ sam_freq = as_out_type_i_desc.tSamFreq[0]; ++ memcpy(sam_freq, &rate, 3); ++ rate = audio_opts->p_srate; ++ sam_freq = as_in_type_i_desc.tSamFreq[0]; ++ memcpy(sam_freq, &rate, 3); ++ */ ++ rate = 8000; ++ sam_freq = as_out_type_i_desc.tSamFreq[0]; ++ memcpy(sam_freq, &rate, 3); ++ sam_freq = as_in_type_i_desc.tSamFreq[0]; ++ memcpy(sam_freq, &rate, 3); ++ sam_freq = as_in_type_ii_ac3_desc.tSamFreq[0]; ++ memcpy(sam_freq, &rate, 3); ++ ++ rate = 16000; ++ sam_freq = as_out_type_i_desc.tSamFreq[1]; ++ memcpy(sam_freq, &rate, 3); ++ sam_freq = as_in_type_i_desc.tSamFreq[1]; ++ memcpy(sam_freq, &rate, 3); ++ sam_freq = as_in_type_ii_ac3_desc.tSamFreq[1]; ++ memcpy(sam_freq, &rate, 3); ++ ++ rate = 32000; ++ sam_freq = as_out_type_i_desc.tSamFreq[2]; ++ memcpy(sam_freq, &rate, 3); ++ sam_freq = as_in_type_i_desc.tSamFreq[2]; ++ memcpy(sam_freq, &rate, 3); ++ sam_freq = as_in_type_ii_ac3_desc.tSamFreq[2]; ++ memcpy(sam_freq, &rate, 3); ++ ++ rate = 48000; ++ sam_freq = as_out_type_i_desc.tSamFreq[3]; ++ memcpy(sam_freq, &rate, 3); ++ sam_freq = as_in_type_i_desc.tSamFreq[3]; ++ memcpy(sam_freq, &rate, 3); ++ sam_freq = as_in_type_ii_ac3_desc.tSamFreq[3]; ++ memcpy(sam_freq, &rate, 3); + + /* allocate instance-specific interface IDs, and patch descriptors */ + status = usb_interface_id(c, f); +- if (status < 0) ++ if (status < 0) { ++ printk(KERN_EMERG "%s:%d\n", __func__, __LINE__); + goto fail; ++ } ++ ++ uac_iad.bFirstInterface = status; + ac_interface_desc.bInterfaceNumber = status; ++ uac1->ac_intf = status; ++ uac1->ac_alt = 0; ++ printk(KERN_EMERG "ac_intf:%d\n", status); + + status = usb_interface_id(c, f); +- if (status < 0) ++ if (status < 0) { ++ printk(KERN_EMERG "%s:%d\n", __func__, __LINE__); + goto fail; +- as_interface_alt_0_desc.bInterfaceNumber = status; +- as_interface_alt_1_desc.bInterfaceNumber = status; ++ } ++ ++ as_in_interface_alt_0_desc.bInterfaceNumber = status; ++ as_in_interface_alt_1_desc.bInterfaceNumber = status; ++ as_in_interface_alt_2_desc.bInterfaceNumber = status; ++ ++ ac_header_desc.baInterfaceNr[0] = status; ++ ++ uac1->as_in_intf = status; ++ uac1->as_in_alt = 0; ++ ++ printk(KERN_EMERG "as_in_intf:%d\n", status); ++ ++ uac_dev->gadget = gadget; + + status = -ENODEV; + + /* allocate instance-specific endpoints */ + ep = usb_ep_autoconfig(cdev->gadget, &as_out_ep_desc); +- if (!ep) ++ if (!ep) { ++ printk(KERN_EMERG "%s:%d\n", __func__,__LINE__); + goto fail; +- audio->out_ep = ep; +- audio->out_ep->desc = &as_out_ep_desc; +- ep->driver_data = cdev; /* claim */ ++ } + +- status = -ENOMEM; ++ uac_dev->out_ep = ep; ++ uac_dev->out_ep->desc = &as_out_ep_desc; ++ ++ ep = usb_ep_autoconfig(cdev->gadget, &as_in_ep_desc); ++ if (!ep) { ++ printk(KERN_EMERG "%s:%d\n", __func__,__LINE__); ++ goto fail; ++ } ++ uac_dev->in_ep = ep; ++ uac_dev->in_ep->desc = &as_in_ep_desc; + + /* copy descriptors, and track endpoint copies */ + status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL); +- if (status) ++ if (status) { ++ printk(KERN_EMERG "%s:%d\n", __func__,__LINE__); + goto fail; +- return 0; ++ } + +-fail: +- gaudio_cleanup(&audio->card); +- if (ep) +- ep->driver_data = NULL; +- return status; +-} ++ uac_dev->out_ep_maxpsize = le16_to_cpu(as_out_ep_desc.wMaxPacketSize); ++ uac_dev->in_ep_maxpsize = le16_to_cpu(as_in_ep_desc.wMaxPacketSize); ++ uac_dev->params.c_chmask = audio_opts->c_chmask; ++ uac_dev->params.c_srate = audio_opts->c_srate; ++ uac_dev->params.c_ssize = audio_opts->c_ssize; ++ uac_dev->params.p_chmask = audio_opts->p_chmask; ++ uac_dev->params.p_srate = audio_opts->p_srate; ++ uac_dev->params.p_ssize = audio_opts->p_ssize; ++ uac_dev->params.req_number = audio_opts->req_number; + +-/*-------------------------------------------------------------------------*/ ++ __print_params(&uac_dev->params); + +-static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value) +-{ +- con->data[cmd] = value; ++ status = uac_device_setup(uac_dev); ++ if (status) ++ goto err_card_register; ++ ++ /* Preallocate control endpoint request. */ ++ uac_dev->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); ++ uac_dev->control_buf = kmalloc(64, GFP_KERNEL); ++ if (uac_dev->control_req == NULL || uac_dev->control_buf == NULL) { ++ status = -ENOMEM; ++ goto error; ++ } ++ ++ uac_dev->control_req->buf = uac_dev->control_buf; ++ uac_dev->control_req->complete = __uac_function_ep0_complete; ++ uac_dev->control_req->context = uac_dev; ++ ++ /*FIXME: add v4l2 interface*/ ++ { ++ struct uac_device *uac_dev = &uac1->uac_dev; ++ ++ if (uac_dev) { ++ if (v4l2_device_register(&cdev->gadget->dev, &(uac_dev->v4l2_dev))) { ++ printk(KERN_INFO "v4l2_device_register failed\n"); ++ goto error; ++ } + +- return 0; +-} ++ /* Initialise queue buffer. */ ++ status = uac_queue_init(&(uac_dev->queue)); ++ if (status < 0) ++ goto error; + +-static int generic_get_cmd(struct usb_audio_control *con, u8 cmd) +-{ +- return con->data[cmd]; +-} ++ /* Register a V4L2 device. */ ++ status = __uac_register_video(cdev, uac_dev); ++ if (status < 0) { ++ printk(KERN_INFO "Unable to register video device\n"); ++ goto error; ++ } ++ } ++ } + +-/* Todo: add more control selecotor dynamically */ +-static int control_selector_init(struct f_audio *audio) +-{ +- INIT_LIST_HEAD(&audio->cs); +- list_add(&feature_unit.list, &audio->cs); ++ return 0; + +- INIT_LIST_HEAD(&feature_unit.control); +- list_add(&mute_control.list, &feature_unit.control); +- list_add(&volume_control.list, &feature_unit.control); ++error: ++ if (&uac1->uac_dev) { ++ v4l2_device_unregister(&(uac1->uac_dev.v4l2_dev)); ++ if ((uac1->uac_dev.vdev)) ++ video_device_release((uac1->uac_dev.vdev)); ++ } + +- volume_control.data[UAC__CUR] = 0xffc0; +- volume_control.data[UAC__MIN] = 0xe3a0; +- volume_control.data[UAC__MAX] = 0xfff0; +- volume_control.data[UAC__RES] = 0x0030; ++ if (&uac1->uac_dev) { ++ usb_ep_free_request(cdev->gadget->ep0, uac_dev->control_req); ++ kfree(uac_dev->control_buf); ++ } + +- return 0; ++err_card_register: ++ usb_free_all_descriptors(f); ++fail: ++ return status; + } + ++/*-------------------------------------------------------------------------*/ ++ + static inline struct f_uac1_opts *to_f_uac1_opts(struct config_item *item) + { + return container_of(to_config_group(item), struct f_uac1_opts, +- func_inst.group); +-} +- +-CONFIGFS_ATTR_STRUCT(f_uac1_opts); +-CONFIGFS_ATTR_OPS(f_uac1_opts); +- +-static void f_uac1_attr_release(struct config_item *item) +-{ +- struct f_uac1_opts *opts = to_f_uac1_opts(item); +- +- usb_put_function_instance(&opts->func_inst); ++ func_inst.group); + } + +-static struct configfs_item_operations f_uac1_item_ops = { +- .release = f_uac1_attr_release, +- .show_attribute = f_uac1_opts_attr_show, +- .store_attribute = f_uac1_opts_attr_store, +-}; +- +-#define UAC1_INT_ATTRIBUTE(name) \ +-static ssize_t f_uac1_opts_##name##_show(struct f_uac1_opts *opts, \ +- char *page) \ +-{ \ +- int result; \ +- \ +- mutex_lock(&opts->lock); \ +- result = sprintf(page, "%u\n", opts->name); \ +- mutex_unlock(&opts->lock); \ +- \ +- return result; \ +-} \ +- \ +-static ssize_t f_uac1_opts_##name##_store(struct f_uac1_opts *opts, \ +- const char *page, size_t len) \ +-{ \ +- int ret; \ +- u32 num; \ +- \ +- mutex_lock(&opts->lock); \ +- if (opts->refcnt) { \ +- ret = -EBUSY; \ +- goto end; \ +- } \ +- \ +- ret = kstrtou32(page, 0, &num); \ +- if (ret) \ +- goto end; \ +- \ +- opts->name = num; \ +- ret = len; \ +- \ +-end: \ +- mutex_unlock(&opts->lock); \ +- return ret; \ +-} \ +- \ +-static struct f_uac1_opts_attribute f_uac1_opts_##name = \ +- __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \ +- f_uac1_opts_##name##_show, \ +- f_uac1_opts_##name##_store) +- +-UAC1_INT_ATTRIBUTE(req_buf_size); +-UAC1_INT_ATTRIBUTE(req_count); +-UAC1_INT_ATTRIBUTE(audio_buf_size); +- +-#define UAC1_STR_ATTRIBUTE(name) \ +-static ssize_t f_uac1_opts_##name##_show(struct f_uac1_opts *opts, \ +- char *page) \ +-{ \ +- int result; \ +- \ +- mutex_lock(&opts->lock); \ +- result = sprintf(page, "%s\n", opts->name); \ +- mutex_unlock(&opts->lock); \ +- \ +- return result; \ +-} \ +- \ +-static ssize_t f_uac1_opts_##name##_store(struct f_uac1_opts *opts, \ +- const char *page, size_t len) \ +-{ \ +- int ret = -EBUSY; \ +- char *tmp; \ +- \ +- mutex_lock(&opts->lock); \ +- if (opts->refcnt) \ +- goto end; \ +- \ +- tmp = kstrndup(page, len, GFP_KERNEL); \ +- if (tmp) { \ +- ret = -ENOMEM; \ +- goto end; \ +- } \ +- if (opts->name##_alloc) \ +- kfree(opts->name); \ +- opts->name##_alloc = true; \ +- opts->name = tmp; \ +- ret = len; \ +- \ +-end: \ +- mutex_unlock(&opts->lock); \ +- return ret; \ +-} \ +- \ +-static struct f_uac1_opts_attribute f_uac1_opts_##name = \ +- __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \ +- f_uac1_opts_##name##_show, \ +- f_uac1_opts_##name##_store) +- +-UAC1_STR_ATTRIBUTE(fn_play); +-UAC1_STR_ATTRIBUTE(fn_cap); +-UAC1_STR_ATTRIBUTE(fn_cntl); +- +-static struct configfs_attribute *f_uac1_attrs[] = { +- &f_uac1_opts_req_buf_size.attr, +- &f_uac1_opts_req_count.attr, +- &f_uac1_opts_audio_buf_size.attr, +- &f_uac1_opts_fn_play.attr, +- &f_uac1_opts_fn_cap.attr, +- &f_uac1_opts_fn_cntl.attr, +- NULL, +-}; +- +-static struct config_item_type f_uac1_func_type = { +- .ct_item_ops = &f_uac1_item_ops, +- .ct_attrs = f_uac1_attrs, +- .ct_owner = THIS_MODULE, +-}; +- + static void f_audio_free_inst(struct usb_function_instance *f) + { + struct f_uac1_opts *opts; + + opts = container_of(f, struct f_uac1_opts, func_inst); +- gaudio_cleanup(opts->card); +- if (opts->fn_play_alloc) +- kfree(opts->fn_play); +- if (opts->fn_cap_alloc) +- kfree(opts->fn_cap); +- if (opts->fn_cntl_alloc) +- kfree(opts->fn_cntl); + kfree(opts); + } + +@@ -918,68 +940,76 @@ static struct usb_function_instance *f_audio_alloc_inst(void) + mutex_init(&opts->lock); + opts->func_inst.free_func_inst = f_audio_free_inst; + +- config_group_init_type_name(&opts->func_inst.group, "", +- &f_uac1_func_type); +- +- opts->req_buf_size = UAC1_OUT_EP_MAX_PACKET_SIZE; +- opts->req_count = UAC1_REQ_COUNT; +- opts->audio_buf_size = UAC1_AUDIO_BUF_SIZE; +- opts->fn_play = FILE_PCM_PLAYBACK; +- opts->fn_cap = FILE_PCM_CAPTURE; +- opts->fn_cntl = FILE_CONTROL; ++ opts->c_chmask = UAC1_DEF_CCHMASK; ++ opts->c_srate = UAC1_DEF_CSRATE; ++ opts->c_ssize = UAC1_DEF_CSSIZE; ++ opts->p_chmask = UAC1_DEF_PCHMASK; ++ opts->p_srate = UAC1_DEF_PSRATE; ++ opts->p_ssize = UAC1_DEF_PSSIZE; ++ opts->req_number = UAC1_DEF_REQ_NUM; + return &opts->func_inst; + } + + static void f_audio_free(struct usb_function *f) + { +- struct f_audio *audio = func_to_audio(f); + struct f_uac1_opts *opts; ++ struct f_uac1 *uac1 = func_to_uac1(f); + + opts = container_of(f->fi, struct f_uac1_opts, func_inst); +- kfree(audio); + mutex_lock(&opts->lock); + --opts->refcnt; + mutex_unlock(&opts->lock); ++ ++ kfree(uac1); + } + + static void f_audio_unbind(struct usb_configuration *c, struct usb_function *f) + { ++ struct f_uac1 *uac1 = func_to_uac1(f); ++ struct uac_device *uac_dev = &uac1->uac_dev; ++ struct usb_composite_dev *cdev = c->cdev; ++ ++ uac_device_cleanup(uac_dev); + usb_free_all_descriptors(f); ++ ++ uac_dev->gadget = NULL; ++ ++ if (uac_dev) { /* release v4l2 device*/ ++ video_unregister_device(uac_dev->vdev); ++ v4l2_device_unregister(&(uac_dev->v4l2_dev)); ++ ++ usb_ep_free_request(cdev->gadget->ep0, uac_dev->control_req); ++ kfree(uac_dev->control_buf); ++ } + } + + static struct usb_function *f_audio_alloc(struct usb_function_instance *fi) + { +- struct f_audio *audio; ++ struct f_uac1 *uac1; + struct f_uac1_opts *opts; + + /* allocate and initialize one new instance */ +- audio = kzalloc(sizeof(*audio), GFP_KERNEL); +- if (!audio) ++ uac1 = kzalloc(sizeof(*uac1), GFP_KERNEL); ++ if (!uac1) + return ERR_PTR(-ENOMEM); + +- audio->card.func.name = "g_audio"; +- + opts = container_of(fi, struct f_uac1_opts, func_inst); + mutex_lock(&opts->lock); + ++opts->refcnt; + mutex_unlock(&opts->lock); +- INIT_LIST_HEAD(&audio->play_queue); +- spin_lock_init(&audio->lock); +- +- audio->card.func.bind = f_audio_bind; +- audio->card.func.unbind = f_audio_unbind; +- audio->card.func.set_alt = f_audio_set_alt; +- audio->card.func.setup = f_audio_setup; +- audio->card.func.disable = f_audio_disable; +- audio->card.func.free_func = f_audio_free; +- +- control_selector_init(audio); + +- INIT_WORK(&audio->playback_work, f_audio_playback_work); ++ uac1->uac_dev.func.name = "uac1_func"; ++ uac1->uac_dev.func.bind = f_audio_bind; ++ uac1->uac_dev.func.unbind = f_audio_unbind; ++ uac1->uac_dev.func.set_alt = f_audio_set_alt; ++ uac1->uac_dev.func.get_alt = f_audio_get_alt; ++ uac1->uac_dev.func.setup = f_audio_setup; ++ uac1->uac_dev.func.disable = f_audio_disable; ++ uac1->uac_dev.func.free_func = f_audio_free; + +- return &audio->card.func; ++ return &uac1->uac_dev.func; + } + + DECLARE_USB_FUNCTION_INIT(uac1, f_audio_alloc_inst, f_audio_alloc); + MODULE_LICENSE("GPL"); +-MODULE_AUTHOR("Bryan Wu"); ++MODULE_AUTHOR("Ruslan Bilovol"); +diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c +index 945b3bd..3d7fd51 100644 +--- a/drivers/usb/gadget/function/f_uvc.c ++++ b/drivers/usb/gadget/function/f_uvc.c +@@ -32,6 +32,17 @@ + #include "uvc_video.h" + #include "u_uvc.h" + ++ ++static unsigned int bulk_max_size = 1024; ++module_param(bulk_max_size, uint, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(bulk_max_size, "bulk max size"); ++ ++static bool bulk_streaming_ep; ++module_param(bulk_streaming_ep, bool, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(bulk_streaming_ep, "0 (Use ISOC video streaming ep) / " ++ "1 (Use BULK video streaming ep)"); ++ ++ + unsigned int uvc_gadget_trace_param; + + /* -------------------------------------------------------------------------- +@@ -197,6 +208,85 @@ static const struct usb_descriptor_header * const uvc_ss_streaming[] = { + NULL, + }; + ++static struct usb_interface_descriptor uvc_bulk_streaming_intf_alt0 = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bInterfaceNumber = UVC_INTF_VIDEO_STREAMING, ++ .bAlternateSetting = 0, ++ .bNumEndpoints = 1, ++ .bInterfaceClass = USB_CLASS_VIDEO, ++ .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING, ++ .bInterfaceProtocol = 0x00, ++ .iInterface = 0, ++}; ++ ++ ++static struct usb_endpoint_descriptor uvc_fs_bulk_streaming_ep = { ++ .bLength = USB_DT_ENDPOINT_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_IN, ++ .bmAttributes = USB_ENDPOINT_XFER_BULK, ++ /* The wMaxPacketSize and bInterval values will be initialized from ++ * module parameters. ++ */ ++ .wMaxPacketSize = 0, ++ .bInterval = 0, ++}; ++ ++ ++static struct usb_endpoint_descriptor uvc_hs_bulk_streaming_ep = { ++ .bLength = USB_DT_ENDPOINT_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_IN, ++ .bmAttributes = USB_ENDPOINT_XFER_BULK, ++ /* The wMaxPacketSize and bInterval values will be initialized from ++ * module parameters. ++ */ ++ .wMaxPacketSize = 0, ++ .bInterval = 0, ++}; ++ ++ ++static struct usb_endpoint_descriptor uvc_ss_bulk_streaming_ep = { ++ .bLength = USB_DT_ENDPOINT_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ ++ .bEndpointAddress = USB_DIR_IN, ++ .bmAttributes = USB_ENDPOINT_XFER_BULK, ++ /* The wMaxPacketSize and bInterval values will be initialized from ++ * module parameters. ++ */ ++ .wMaxPacketSize = 0, ++ .bInterval = 0, ++}; ++ ++ ++static struct usb_ss_ep_comp_descriptor uvc_ss_bulk_streaming_comp ++ = { ++ .bLength = sizeof(uvc_ss_bulk_streaming_comp), ++ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, ++ /* The following 3 values can be tweaked if necessary. */ ++ .bMaxBurst = 0, ++ .bmAttributes = 0, ++ .wBytesPerInterval = cpu_to_le16(1024), ++}; ++ ++static const struct usb_descriptor_header * const uvc_fs_bulk_streaming[] = { ++ (struct usb_descriptor_header *) &uvc_fs_bulk_streaming_ep, ++ NULL, ++}; ++ ++static const struct usb_descriptor_header * const uvc_hs_bulk_streaming[] = { ++ (struct usb_descriptor_header *) &uvc_hs_bulk_streaming_ep, ++ NULL, ++}; ++ ++static const struct usb_descriptor_header * const uvc_ss_bulk_streaming[] = { ++ (struct usb_descriptor_header *) &uvc_ss_bulk_streaming_ep, ++ (struct usb_descriptor_header *) &uvc_ss_bulk_streaming_comp, ++ NULL, ++}; ++ + void uvc_set_trace_param(unsigned int trace) + { + uvc_gadget_trace_param = trace; +@@ -278,8 +368,20 @@ uvc_function_get_alt(struct usb_function *f, unsigned interface) + return 0; + else if (interface != uvc->streaming_intf) + return -EINVAL; +- else +- return uvc->video.ep->driver_data ? 1 : 0; ++ else { ++ /* ++ * Alt settings in an interface are supported only for ++ * ISOC endpoints as there are different alt-settings for ++ * zero-bandwidth and full-bandwidth cases, but the same ++ * is not true for BULK endpoints, as they have a single ++ * alt-setting. ++ */ ++ if (!bulk_streaming_ep) ++ return uvc->state == UVC_STATE_STREAMING ? 1 : 0; ++ else ++ return 0; ++ } ++ + } + + static int +@@ -316,7 +418,10 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) + uvc_event->speed = cdev->gadget->speed; + v4l2_event_queue(uvc->vdev, &v4l2_event); + +- uvc->state = UVC_STATE_CONNECTED; ++ if (bulk_streaming_ep) ++ uvc->state = UVC_STATE_CONFIG; ++ else ++ uvc->state = UVC_STATE_CONNECTED; + } + + return 0; +@@ -325,55 +430,126 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) + if (interface != uvc->streaming_intf) + return -EINVAL; + +- /* TODO +- if (usb_endpoint_xfer_bulk(&uvc->desc.vs_ep)) +- return alt ? -EINVAL : 0; +- */ ++ if (!bulk_streaming_ep) { ++ switch (alt) { ++ case 0: ++ if (uvc->state != UVC_STATE_STREAMING) ++ return 0; + +- switch (alt) { +- case 0: +- if (uvc->state != UVC_STATE_STREAMING) ++ if (uvc->video.ep) { ++ usb_ep_disable(uvc->video.ep); ++ uvc->video.ep->driver_data = NULL; ++ } ++ ++ memset(&v4l2_event, 0, sizeof(v4l2_event)); ++ v4l2_event.type = UVC_EVENT_STREAMOFF; ++ v4l2_event_queue(uvc->vdev, &v4l2_event); ++ ++ uvc->state = UVC_STATE_CONNECTED; + return 0; + +- if (uvc->video.ep) { +- usb_ep_disable(uvc->video.ep); +- uvc->video.ep->driver_data = NULL; +- } ++ case 1: ++ if (uvc->state != UVC_STATE_CONNECTED) ++ return 0; + +- memset(&v4l2_event, 0, sizeof(v4l2_event)); +- v4l2_event.type = UVC_EVENT_STREAMOFF; +- v4l2_event_queue(uvc->vdev, &v4l2_event); ++ if (!uvc->video.ep) ++ return -EINVAL; + +- uvc->state = UVC_STATE_CONNECTED; +- return 0; ++ if (uvc->video.ep->driver_data) { ++ INFO(cdev, "reset UVC\n"); ++ usb_ep_disable(uvc->video.ep); ++ uvc->video.ep->driver_data = NULL; ++ } + +- case 1: +- if (uvc->state != UVC_STATE_CONNECTED) +- return 0; ++ ret = config_ep_by_speed(f->config->cdev->gadget, ++ &(uvc->func), uvc->video.ep); ++ if (ret) ++ return ret; ++ usb_ep_enable(uvc->video.ep); ++ uvc->video.ep->driver_data = uvc; + +- if (!uvc->video.ep) +- return -EINVAL; ++ 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; + +- if (uvc->video.ep->driver_data) { +- INFO(cdev, "reset UVC\n"); +- usb_ep_disable(uvc->video.ep); +- uvc->video.ep->driver_data = NULL; ++ default: ++ return -EINVAL; + } ++ } else { ++ switch (uvc->state) { ++ case UVC_STATE_CONFIG: ++ if (!uvc->video.ep->driver_data) { ++ /* ++ * Enable the video streaming endpoint, ++ * but don't change the 'uvc->state'. ++ */ ++ if (uvc->video.ep) { ++ ret = config_ep_by_speed ++ (f->config->cdev->gadget, ++ &(uvc->func), uvc->video.ep); ++ if (ret) ++ return ret; ++ ret = usb_ep_enable(uvc->video.ep); ++ if (ret) ++ return ret; ++ ++ uvc->video.ep->driver_data = uvc; ++ } ++ } + +- ret = config_ep_by_speed(f->config->cdev->gadget, +- &(uvc->func), uvc->video.ep); +- if (ret) +- return ret; +- usb_ep_enable(uvc->video.ep); +- uvc->video.ep->driver_data = uvc; ++ memset(&v4l2_event, 0, sizeof(v4l2_event)); ++ v4l2_event.type = UVC_EVENT_STREAMON; ++ v4l2_event_queue(uvc->vdev, &v4l2_event); + +- 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; ++ uvc->state = UVC_STATE_CONNECTED; ++ return 0; + +- default: +- return -EINVAL; ++ case UVC_STATE_CONNECTED: ++ ++ /* ++ * Enable the video streaming endpoint, ++ * but don't change the 'uvc->state'. ++ */ ++ if (uvc->video.ep) { ++ ret = config_ep_by_speed ++ (f->config->cdev->gadget, ++ &(uvc->func), uvc->video.ep); ++ if (ret) ++ return ret; ++ ret = usb_ep_enable(uvc->video.ep); ++ if (ret) ++ return ret; ++ ++ uvc->video.ep->driver_data = uvc; ++ } ++ ++ memset(&v4l2_event, 0, sizeof(v4l2_event)); ++ v4l2_event.type = UVC_EVENT_STREAMON; ++ v4l2_event_queue(uvc->vdev, &v4l2_event); ++ uvc->state = UVC_STATE_STREAMING; ++ return 0; ++ ++ case UVC_STATE_STREAMING: ++ if (uvc->video.ep->driver_data) { ++ if (uvc->video.ep) { ++ ret = usb_ep_disable(uvc->video.ep); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ memset(&v4l2_event, 0, sizeof(v4l2_event)); ++ v4l2_event.type = UVC_EVENT_STREAMOFF; ++ v4l2_event_queue(uvc->vdev, &v4l2_event); ++ uvc->state = UVC_STATE_CONNECTED; ++ INFO(cdev, "uvc_function_set_alt: state to streamoff\n"); ++ ++ return 0; ++ ++ default: ++ return -EINVAL; ++ } + } + } + +@@ -480,6 +656,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) + const struct uvc_descriptor_header * const *uvc_streaming_cls; + const struct usb_descriptor_header * const *uvc_streaming_std; + const struct usb_descriptor_header * const *src; ++ struct usb_interface_descriptor *streaming_intf_alt0; + struct usb_descriptor_header **dst; + struct usb_descriptor_header **hdr; + unsigned int control_size; +@@ -488,6 +665,11 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) + unsigned int bytes; + void *mem; + ++ if (!bulk_streaming_ep) ++ streaming_intf_alt0 = &uvc_streaming_intf_alt0; ++ else ++ streaming_intf_alt0 = &uvc_bulk_streaming_intf_alt0; ++ + switch (speed) { + case USB_SPEED_SUPER: + uvc_control_desc = uvc->desc.ss_control; +@@ -509,6 +691,22 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) + break; + } + ++ if (bulk_streaming_ep) { ++ switch (speed) { ++ case USB_SPEED_SUPER: ++ uvc_streaming_std = uvc_ss_bulk_streaming; ++ break; ++ ++ case USB_SPEED_HIGH: ++ uvc_streaming_std = uvc_hs_bulk_streaming; ++ break; ++ ++ case USB_SPEED_FULL: ++ default: ++ uvc_streaming_std = uvc_fs_bulk_streaming; ++ break; ++ } ++ } + /* Descriptors layout + * + * uvc_iad +@@ -526,8 +724,8 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) + control_size = 0; + streaming_size = 0; + bytes = uvc_iad.bLength + uvc_control_intf.bLength +- + uvc_control_ep.bLength + uvc_control_cs_ep.bLength +- + uvc_streaming_intf_alt0.bLength; ++ + uvc_control_ep.bLength + uvc_control_cs_ep.bLength ++ + streaming_intf_alt0->bLength; + + if (speed == USB_SPEED_SUPER) { + bytes += uvc_ss_control_comp.bLength; +@@ -537,13 +735,13 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) + } + + for (src = (const struct usb_descriptor_header **)uvc_control_desc; +- *src; ++src) { ++ *src; ++src) { + control_size += (*src)->bLength; + bytes += (*src)->bLength; + n_desc++; + } + for (src = (const struct usb_descriptor_header **)uvc_streaming_cls; +- *src; ++src) { ++ *src; ++src) { + streaming_size += (*src)->bLength; + bytes += (*src)->bLength; + n_desc++; +@@ -577,7 +775,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) + UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp); + + UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_cs_ep); +- UVC_COPY_DESCRIPTOR(mem, dst, &uvc_streaming_intf_alt0); ++ UVC_COPY_DESCRIPTOR(mem, dst, streaming_intf_alt0); + + uvc_streaming_header = mem; + UVC_COPY_DESCRIPTORS(mem, dst, +@@ -605,13 +803,21 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) + + INFO(cdev, "uvc_function_bind\n"); + ++ /* Use Bulk endpoint for video streaming?. */ ++ uvc->video.bulk_streaming_ep = bulk_streaming_ep; ++ uvc->video.bulk_max_size = bulk_max_size; ++ + opts = to_f_uvc_opts(f->fi); + /* Sanity check the streaming endpoint module parameters. + */ +- opts->streaming_interval = clamp(opts->streaming_interval, 1U, 16U); +- opts->streaming_maxpacket = clamp(opts->streaming_maxpacket, 1U, 3072U); +- opts->streaming_maxburst = min(opts->streaming_maxburst, 15U); +- ++ if (!bulk_streaming_ep) { ++ opts->streaming_interval = clamp(opts->streaming_interval, 1U, 16U); ++ opts->streaming_maxpacket = clamp(opts->streaming_maxpacket, 1U, 3072U); ++ opts->streaming_maxburst = min(opts->streaming_maxburst, 15U); ++ } else { ++ opts->streaming_maxpacket = clamp(opts->streaming_maxpacket, 1U, 1024U); ++ opts->streaming_maxburst = min(opts->streaming_maxburst, 15U); ++ } + /* Fill in the FS/HS/SS Video Streaming specific descriptors from the + * module parameters. + * +@@ -629,21 +835,33 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) + max_packet_size = opts->streaming_maxpacket / 3; + } + +- uvc_fs_streaming_ep.wMaxPacketSize = +- cpu_to_le16(min(opts->streaming_maxpacket, 1023U)); +- uvc_fs_streaming_ep.bInterval = opts->streaming_interval; ++ if (!bulk_streaming_ep) { ++ uvc_fs_streaming_ep.wMaxPacketSize = ++ cpu_to_le16(min(opts->streaming_maxpacket, 1023U)); ++ uvc_fs_streaming_ep.bInterval = opts->streaming_interval; ++ ++ uvc_hs_streaming_ep.wMaxPacketSize = ++ cpu_to_le16(max_packet_size | ((max_packet_mult - 1) << 11)); ++ uvc_hs_streaming_ep.bInterval = opts->streaming_interval; + +- uvc_hs_streaming_ep.wMaxPacketSize = +- cpu_to_le16(max_packet_size | ((max_packet_mult - 1) << 11)); +- uvc_hs_streaming_ep.bInterval = opts->streaming_interval; ++ uvc_ss_streaming_ep.wMaxPacketSize = cpu_to_le16(max_packet_size); ++ uvc_ss_streaming_ep.bInterval = opts->streaming_interval; ++ uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1; ++ uvc_ss_streaming_comp.bMaxBurst = opts->streaming_maxburst; ++ uvc_ss_streaming_comp.wBytesPerInterval = ++ cpu_to_le16(max_packet_size * max_packet_mult * ++ opts->streaming_maxburst); + +- uvc_ss_streaming_ep.wMaxPacketSize = cpu_to_le16(max_packet_size); +- uvc_ss_streaming_ep.bInterval = opts->streaming_interval; +- uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1; +- uvc_ss_streaming_comp.bMaxBurst = opts->streaming_maxburst; +- uvc_ss_streaming_comp.wBytesPerInterval = +- cpu_to_le16(max_packet_size * max_packet_mult * +- opts->streaming_maxburst); ++ } else { ++ uvc_fs_bulk_streaming_ep.wMaxPacketSize = ++ min(opts->streaming_maxpacket, 64U); ++ ++ uvc_hs_bulk_streaming_ep.wMaxPacketSize = 512; ++ uvc_ss_bulk_streaming_ep.wMaxPacketSize = max_packet_size; ++ uvc_ss_streaming_comp.bMaxBurst = opts->streaming_maxburst; ++ uvc_ss_streaming_comp.wBytesPerInterval = ++ max_packet_size * opts->streaming_maxburst; ++ } + + /* Allocate endpoints. */ + ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); +@@ -654,14 +872,31 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) + uvc->control_ep = ep; + ep->driver_data = uvc; + +- if (gadget_is_superspeed(c->cdev->gadget)) +- ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep, +- &uvc_ss_streaming_comp); +- else if (gadget_is_dualspeed(cdev->gadget)) +- ep = usb_ep_autoconfig(cdev->gadget, &uvc_hs_streaming_ep); +- else +- ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep); +- ++ if (gadget_is_superspeed(c->cdev->gadget)) { ++ if (!bulk_streaming_ep) ++ ep = usb_ep_autoconfig_ss(cdev->gadget, ++ &uvc_ss_streaming_ep, ++ &uvc_ss_streaming_comp); ++ else ++ ep = usb_ep_autoconfig_ss(cdev->gadget, ++ &uvc_ss_bulk_streaming_ep, ++ &uvc_ss_bulk_streaming_comp); ++ ++ } else if (gadget_is_dualspeed(cdev->gadget)) { ++ if (!bulk_streaming_ep) ++ ep = usb_ep_autoconfig(cdev->gadget, ++ &uvc_hs_streaming_ep); ++ else ++ ep = usb_ep_autoconfig(cdev->gadget, ++ &uvc_hs_bulk_streaming_ep); ++ } else { ++ if (!bulk_streaming_ep) ++ ep = usb_ep_autoconfig(cdev->gadget, ++ &uvc_fs_streaming_ep); ++ else ++ ep = usb_ep_autoconfig(cdev->gadget, ++ &uvc_fs_bulk_streaming_ep); ++ } + if (!ep) { + INFO(cdev, "Unable to allocate streaming EP\n"); + goto error; +@@ -669,9 +904,18 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) + uvc->video.ep = ep; + ep->driver_data = uvc; + +- uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address; +- uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address; +- uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address; ++ if (!bulk_streaming_ep) { ++ uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address; ++ uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address; ++ uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address; ++ } else { ++ uvc_fs_bulk_streaming_ep.bEndpointAddress = ++ uvc->video.ep->address; ++ uvc_hs_bulk_streaming_ep.bEndpointAddress = ++ uvc->video.ep->address; ++ uvc_ss_bulk_streaming_ep.bEndpointAddress = ++ uvc->video.ep->address; ++ } + + us = usb_gstrings_attach(cdev, uvc_function_strings, + ARRAY_SIZE(uvc_en_us_strings)); +@@ -682,8 +926,13 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) + uvc_iad.iFunction = us[UVC_STRING_CONTROL_IDX].id; + uvc_control_intf.iInterface = us[UVC_STRING_CONTROL_IDX].id; + ret = us[UVC_STRING_STREAMING_IDX].id; +- uvc_streaming_intf_alt0.iInterface = ret; +- uvc_streaming_intf_alt1.iInterface = ret; ++ ++ if (!bulk_streaming_ep) { ++ uvc_streaming_intf_alt0.iInterface = ret; ++ uvc_streaming_intf_alt1.iInterface = ret; ++ } else { ++ uvc_bulk_streaming_intf_alt0.iInterface = ret; ++ } + + /* Allocate interface IDs. */ + if ((ret = usb_interface_id(c, f)) < 0) +@@ -694,8 +943,15 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) + + if ((ret = usb_interface_id(c, f)) < 0) + goto error; +- uvc_streaming_intf_alt0.bInterfaceNumber = ret; +- uvc_streaming_intf_alt1.bInterfaceNumber = ret; ++ ++ if (!bulk_streaming_ep) { ++ ++ uvc_streaming_intf_alt0.bInterfaceNumber = ret; ++ uvc_streaming_intf_alt1.bInterfaceNumber = ret; ++ } else { ++ uvc_bulk_streaming_intf_alt0.bInterfaceNumber = ret; ++ } ++ + uvc->streaming_intf = ret; + + /* Copy descriptors */ +@@ -720,6 +976,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) + /* Avoid letting this gadget enumerate until the userspace server is + * active. + */ ++ + if ((ret = usb_function_deactivate(f)) < 0) + goto error; + +diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c +index 95d2324..6411667 100644 +--- a/drivers/usb/gadget/function/rndis.c ++++ b/drivers/usb/gadget/function/rndis.c +@@ -41,6 +41,24 @@ + + #include "rndis.h" + ++typedef enum ++{ ++ RNDIS_SKB_IDLE=0, ++ RNDIS_SKB_COMBINING, ++ RNDIS_SKB_COMBINED, ++}rndis_skb_status; ++ ++typedef struct{ ++ rndis_skb_status status; ++ int msgtype; ++ int msglen; ++ int halflen; ++ int datalen; ++ int dataoffset; ++ struct sk_buff *skb; ++}rndis_skb_recombine; ++rndis_skb_recombine g_skb[2]; ++ + + /* The driver for your USB chip needs to support ep0 OUT to work with + * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional). +@@ -59,6 +77,16 @@ MODULE_PARM_DESC (rndis_debug, "enable debugging"); + + #define RNDIS_MAX_CONFIGS 1 + ++int rndis_ul_max_pkt_per_xfer_rcvd; ++module_param(rndis_ul_max_pkt_per_xfer_rcvd, int, S_IRUGO); ++MODULE_PARM_DESC(rndis_ul_max_pkt_per_xfer_rcvd, ++ "Max num of REMOTE_NDIS_PACKET_MSGs received in a single transfer"); ++ ++int rndis_ul_max_xfer_size_rcvd; ++module_param(rndis_ul_max_xfer_size_rcvd, int, S_IRUGO); ++MODULE_PARM_DESC(rndis_ul_max_xfer_size_rcvd, ++ "Max size of bus transfer received"); ++ + + static rndis_params rndis_per_dev_params[RNDIS_MAX_CONFIGS]; + +@@ -585,12 +613,12 @@ static int rndis_init_response(int configNr, rndis_init_msg_type *buf) + resp->MinorVersion = cpu_to_le32(RNDIS_MINOR_VERSION); + resp->DeviceFlags = cpu_to_le32(RNDIS_DF_CONNECTIONLESS); + resp->Medium = cpu_to_le32(RNDIS_MEDIUM_802_3); +- resp->MaxPacketsPerTransfer = cpu_to_le32(1); +- resp->MaxTransferSize = cpu_to_le32( +- params->dev->mtu ++ resp->MaxPacketsPerTransfer = cpu_to_le32(params->max_pkt_per_xfer); ++ resp->MaxTransferSize = cpu_to_le32(params->max_pkt_per_xfer * ++ (params->dev->mtu + + sizeof(struct ethhdr) + + sizeof(struct rndis_packet_msg_type) +- + 22); ++ + 22)); + resp->PacketAlignmentFactor = cpu_to_le32(0); + resp->AFListOffset = cpu_to_le32(0); + resp->AFListSize = cpu_to_le32(0); +@@ -686,6 +714,12 @@ static int rndis_reset_response(int configNr, rndis_reset_msg_type *buf) + rndis_reset_cmplt_type *resp; + rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; ++ u32 length; ++ u8 *xbuf; ++ ++ /* drain the response queue */ ++ while ((xbuf = rndis_get_next_response(configNr, &length))) ++ rndis_free_response(configNr, xbuf); + + r = rndis_add_response(configNr, sizeof(rndis_reset_cmplt_type)); + if (!r) +@@ -917,6 +951,8 @@ int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter) + rndis_per_dev_params[configNr].dev = dev; + rndis_per_dev_params[configNr].filter = cdc_filter; + ++ rndis_ul_max_xfer_size_rcvd = 0; ++ rndis_ul_max_pkt_per_xfer_rcvd = 0; + return 0; + } + EXPORT_SYMBOL_GPL(rndis_set_param_dev); +@@ -946,6 +982,13 @@ int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed) + } + EXPORT_SYMBOL_GPL(rndis_set_param_medium); + ++void rndis_set_max_pkt_xfer(u8 configNr, u8 max_pkt_per_xfer) ++{ ++ pr_debug("%s:\n", __func__); ++ ++ rndis_per_dev_params[configNr].max_pkt_per_xfer = max_pkt_per_xfer; ++} ++ + void rndis_add_hdr(struct sk_buff *skb) + { + struct rndis_packet_msg_type *header; +@@ -1021,23 +1064,135 @@ int rndis_rm_hdr(struct gether *port, + struct sk_buff *skb, + struct sk_buff_head *list) + { +- /* tmp points to a struct rndis_packet_msg_type */ +- __le32 *tmp = (void *)skb->data; ++ int num_pkts = 1,i = 0; ++ ++ if (skb->len > rndis_ul_max_xfer_size_rcvd) ++ rndis_ul_max_xfer_size_rcvd = skb->len; ++ ++ while (skb->len) { ++ struct rndis_packet_msg_type *hdr; ++ struct sk_buff *skb2; ++ u32 msg_len, data_offset, data_len; ++ /*recombine broken packet and add to skb process queue*/ ++ int index = 0; ++ for(i=0;i< (sizeof(g_skb)/sizeof(rndis_skb_recombine));i++){ ++ if(RNDIS_SKB_COMBINING == g_skb[i].status){ ++ g_skb[i].status = RNDIS_SKB_COMBINED; ++ memcpy(g_skb[i].skb->data+g_skb[i].halflen,skb->data,g_skb[i].msglen-g_skb[i].halflen); ++ skb_pull(skb, g_skb[i].msglen-g_skb[i].halflen);//update skb ++ g_skb[i].skb->data += g_skb[i].dataoffset+8; ++ g_skb[i].skb->len = g_skb[i].datalen; ++ g_skb[i].skb->tail = g_skb[i].skb->data + g_skb[i].skb->len; ++ index = i + 1; ++ break; ++ } ++ } ++ if(index){ ++ if((g_skb[i].dataoffset + g_skb[i].datalen + 8) > g_skb[i].msglen){ ++ pr_err("invalid rndis message: %d/%d/%d/%d, len:%d\n", ++ g_skb[i].msgtype,g_skb[i].msglen, g_skb[i].dataoffset, g_skb[i].datalen, skb->len); ++ dev_kfree_skb_any(g_skb[i].skb); ++ continue; ++ } ++ if (g_skb[i].msgtype != RNDIS_MSG_PACKET) { ++ pr_err("invalid rndis message: %d/%d/%d/%d, len:%d\n", ++ g_skb[i].msgtype,g_skb[i].msglen, g_skb[i].dataoffset, g_skb[i].datalen, skb->len); ++ dev_kfree_skb_any(g_skb[i].skb); ++ continue; ++ } ++ skb_queue_tail(list, g_skb[i].skb); ++ num_pkts++; ++ continue; ++ } ++ /* some rndis hosts send extra byte to avoid zlp, ignore it */ ++ if (skb->len == 1) { ++ dev_kfree_skb_any(skb); ++ return 0; ++ } + +- /* MessageType, MessageLength */ +- if (cpu_to_le32(RNDIS_MSG_PACKET) +- != get_unaligned(tmp++)) { +- dev_kfree_skb_any(skb); +- return -EINVAL; +- } +- tmp++; ++ if (skb->len < sizeof *hdr) { ++ pr_err("invalid rndis pkt: skblen:%u hdr_len:%u", ++ skb->len, sizeof *hdr); ++ dev_kfree_skb_any(skb); ++ return -EINVAL; ++ } ++ ++ hdr = (void *)skb->data; ++ msg_len = le32_to_cpu(hdr->MessageLength); ++ data_offset = le32_to_cpu(hdr->DataOffset); ++ data_len = le32_to_cpu(hdr->DataLength); ++ /*backup the broken packet for recombining*/ ++ if(skb->len < msg_len){ ++ int size = 1558+20; ++ for(i=0;i< (sizeof(g_skb)/sizeof(rndis_skb_recombine));i++){ ++ if(RNDIS_SKB_IDLE == g_skb[i].status){ ++ g_skb[i].status = RNDIS_SKB_COMBINING; ++ g_skb[i].skb = alloc_skb(size + NET_IP_ALIGN, GFP_ATOMIC); ++ if (g_skb[i].skb == NULL) { ++ g_skb[i].status = RNDIS_SKB_IDLE; ++ return -EINVAL; ++ } ++ skb_reserve(g_skb[i].skb, NET_IP_ALIGN); ++ g_skb[i].msgtype = le32_to_cpu(hdr->MessageType); ++ g_skb[i].msglen = msg_len; ++ g_skb[i].dataoffset = data_offset; ++ g_skb[i].datalen = data_len; ++ g_skb[i].halflen = skb->len; ++ memcpy(g_skb[i].skb->data,skb->data,g_skb[i].halflen); ++ skb_pull(skb,g_skb[i].halflen); ++ break; ++ } ++ } ++ if(!skb->len) ++ break; ++ pr_err("invalid rndis message: %d/%d/%d/%d, len:%d\n", ++ le32_to_cpu(hdr->MessageType), ++ msg_len, data_offset, data_len, skb->len); ++ dev_kfree_skb_any(skb); ++ return -EOVERFLOW; ++ } ++ if((data_offset + data_len + 8) > msg_len){ ++ pr_err("invalid rndis message: %d/%d/%d/%d, len:%d\n", ++ le32_to_cpu(hdr->MessageType), ++ msg_len, data_offset, data_len, skb->len); ++ dev_kfree_skb_any(skb); ++ return -EOVERFLOW; ++ } ++ if (le32_to_cpu(hdr->MessageType) != RNDIS_MSG_PACKET) { ++ int len = skb->len; ++ skb_pull(skb,len); ++ break; ++ } + +- /* DataOffset, DataLength */ +- if (!skb_pull(skb, get_unaligned_le32(tmp++) + 8)) { +- dev_kfree_skb_any(skb); +- return -EOVERFLOW; ++ skb_pull(skb, data_offset + 8); ++ ++ if (msg_len == skb->len) { ++ skb_trim(skb, data_len); ++ break; ++ } ++ ++ skb2 = skb_clone(skb, GFP_ATOMIC); ++ if (!skb2) { ++ pr_err("%s:skb clone failed\n", __func__); ++ dev_kfree_skb_any(skb); ++ return -ENOMEM; ++ } ++ ++ skb_pull(skb, msg_len - sizeof *hdr); ++ skb_trim(skb2, data_len); ++ skb_queue_tail(list, skb2); ++ ++ num_pkts++; + } +- skb_trim(skb, get_unaligned_le32(tmp++)); ++ ++ if (num_pkts > rndis_ul_max_pkt_per_xfer_rcvd) ++ rndis_ul_max_pkt_per_xfer_rcvd = num_pkts; ++ /*recombinant is finished, update combining status*/ ++ ++ if(RNDIS_SKB_COMBINED == g_skb[0].status) ++ g_skb[0].status = RNDIS_SKB_IDLE; ++ if(RNDIS_SKB_COMBINED == g_skb[1].status) ++ g_skb[1].status = RNDIS_SKB_IDLE; + + skb_queue_tail(list, skb); + return 0; +diff --git a/drivers/usb/gadget/function/rndis.h b/drivers/usb/gadget/function/rndis.h +index 0f4abb4..145f01b 100644 +--- a/drivers/usb/gadget/function/rndis.h ++++ b/drivers/usb/gadget/function/rndis.h +@@ -190,6 +190,7 @@ typedef struct rndis_params + struct net_device *dev; + + u32 vendorID; ++ u8 max_pkt_per_xfer; + const char *vendorDescr; + void (*resp_avail)(void *v); + void *v; +@@ -205,6 +206,7 @@ int rndis_set_param_dev (u8 configNr, struct net_device *dev, + int rndis_set_param_vendor (u8 configNr, u32 vendorID, + const char *vendorDescr); + int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed); ++void rndis_set_max_pkt_xfer(u8 configNr, u8 max_pkt_per_xfer); + void rndis_add_hdr (struct sk_buff *skb); + int rndis_rm_hdr(struct gether *port, struct sk_buff *skb, + struct sk_buff_head *list); +diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c +index 6e6f876..f1fd777 100644 +--- a/drivers/usb/gadget/function/u_ether.c ++++ b/drivers/usb/gadget/function/u_ether.c +@@ -729,9 +729,7 @@ static int get_ether_addr_str(u8 dev_addr[ETH_ALEN], char *str, int len) + if (len < 18) + return -EINVAL; + +- snprintf(str, len, "%02x:%02x:%02x:%02x:%02x:%02x", +- dev_addr[0], dev_addr[1], dev_addr[2], +- dev_addr[3], dev_addr[4], dev_addr[5]); ++ snprintf(str, len, "%pM", dev_addr); + return 18; + } + +diff --git a/drivers/usb/gadget/function/u_ether.h b/drivers/usb/gadget/function/u_ether.h +index 334b389..f591f74 100644 +--- a/drivers/usb/gadget/function/u_ether.h ++++ b/drivers/usb/gadget/function/u_ether.h +@@ -75,6 +75,9 @@ struct gether { + bool is_fixed; + u32 fixed_out_len; + u32 fixed_in_len; ++ unsigned ul_max_pkts_per_xfer; ++ unsigned dl_max_pkts_per_xfer; ++ bool multi_pkt_xfer; + bool supports_multi_frame; + struct sk_buff *(*wrap)(struct gether *port, + struct sk_buff *skb); +diff --git a/drivers/usb/gadget/function/u_midi.h b/drivers/usb/gadget/function/u_midi.h +new file mode 100644 +index 0000000..2251018 +--- /dev/null ++++ b/drivers/usb/gadget/function/u_midi.h +@@ -0,0 +1,40 @@ ++/* ++ * u_midi.h ++ * ++ * Utility definitions for the midi function ++ * ++ * Copyright (c) 2014 Samsung Electronics Co., Ltd. ++ * http://www.samsung.com ++ * ++ * Author: Andrzej Pietrasiewicz ++ * ++ * 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 U_MIDI_H ++#define U_MIDI_H ++ ++#include ++ ++struct f_midi_opts { ++ struct usb_function_instance func_inst; ++ int index; ++ char *id; ++ bool id_allocated; ++ unsigned int in_ports; ++ unsigned int out_ports; ++ unsigned int buflen; ++ unsigned int qlen; ++ ++ /* ++ * Protect the data form concurrent access by read/write ++ * and create symlink/remove symlink. ++ */ ++ struct mutex lock; ++ int refcnt; ++}; ++ ++#endif /* U_MIDI_H */ ++ +diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c +index 491082a..d9b867a 100644 +--- a/drivers/usb/gadget/function/u_serial.c ++++ b/drivers/usb/gadget/function/u_serial.c +@@ -1122,6 +1122,7 @@ int gserial_alloc_line(unsigned char *line_num) + + tty_dev = tty_port_register_device(&ports[port_num].port->port, + gs_tty_driver, port_num, NULL); ++ + if (IS_ERR(tty_dev)) { + struct gs_port *port; + pr_err("%s: failed to register tty for port %d, err %ld\n", +diff --git a/drivers/usb/gadget/function/u_uac1.h b/drivers/usb/gadget/function/u_uac1.h +index f8b17fe..88bddfe 100644 +--- a/drivers/usb/gadget/function/u_uac1.h ++++ b/drivers/usb/gadget/function/u_uac1.h +@@ -1,85 +1,42 @@ + /* +- * u_uac1.h -- interface to USB gadget "ALSA AUDIO" utilities ++ * u_uac1.h - Utility definitions for UAC1 function + * +- * Copyright (C) 2008 Bryan Wu +- * Copyright (C) 2008 Analog Devices, Inc ++ * Copyright (C) 2016 Ruslan Bilovol + * +- * Enter bugs at http://blackfin.uclinux.org/ +- * +- * Licensed under the GPL-2 or later. ++ * 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 __U_AUDIO_H +-#define __U_AUDIO_H ++#ifndef __U_UAC1_H ++#define __U_UAC1_H + +-#include +-#include +-#include + #include + +-#include +-#include +-#include +- +-#include "gadget_chips.h" +- +-#define FILE_PCM_PLAYBACK "/dev/snd/pcmC0D0p" +-#define FILE_PCM_CAPTURE "/dev/snd/pcmC0D0c" +-#define FILE_CONTROL "/dev/snd/controlC0" + ++#define UAC1_DEF_CCHMASK 0x3 ++#define UAC1_DEF_CSRATE 48000 ++#define UAC1_DEF_CSSIZE 2 ++#define UAC1_DEF_PCHMASK 0x1//0x3 ++#define UAC1_DEF_PSRATE 8000//48000 ++#define UAC1_DEF_PSSIZE 2 + #define UAC1_OUT_EP_MAX_PACKET_SIZE 200 +-#define UAC1_REQ_COUNT 256 +-#define UAC1_AUDIO_BUF_SIZE 48000 +- +-/* +- * This represents the USB side of an audio card device, managed by a USB +- * function which provides control and stream interfaces. +- */ +- +-struct gaudio_snd_dev { +- struct gaudio *card; +- struct file *filp; +- struct snd_pcm_substream *substream; +- int access; +- int format; +- int channels; +- int rate; +-}; +- +-struct gaudio { +- struct usb_function func; +- struct usb_gadget *gadget; +- +- /* ALSA sound device interfaces */ +- struct gaudio_snd_dev control; +- struct gaudio_snd_dev playback; +- struct gaudio_snd_dev capture; +- +- /* TODO */ +-}; ++#define UAC1_DEF_REQ_NUM 1 + + struct f_uac1_opts { + struct usb_function_instance func_inst; +- int req_buf_size; +- int req_count; +- int audio_buf_size; +- char *fn_play; +- char *fn_cap; +- char *fn_cntl; ++ int c_chmask; ++ int c_srate; ++ int c_ssize; ++ int p_chmask; ++ int p_srate; ++ int p_ssize; ++ int req_number; ++ int req_buf_size; + unsigned bound:1; +- unsigned fn_play_alloc:1; +- unsigned fn_cap_alloc:1; +- unsigned fn_cntl_alloc:1; +- struct gaudio *card; ++ + struct mutex lock; + int refcnt; + }; + +-int gaudio_setup(struct gaudio *card); +-void gaudio_cleanup(struct gaudio *the_card); +- +-size_t u_audio_playback(struct gaudio *card, void *buf, size_t count); +-int u_audio_get_playback_channels(struct gaudio *card); +-int u_audio_get_playback_rate(struct gaudio *card); +- +-#endif /* __U_AUDIO_H */ ++#endif /* __U_UAC1_H */ +diff --git a/drivers/usb/gadget/function/uac_audio_ex.c b/drivers/usb/gadget/function/uac_audio_ex.c +new file mode 100644 +index 0000000..c7ef83b +--- /dev/null ++++ b/drivers/usb/gadget/function/uac_audio_ex.c +@@ -0,0 +1,275 @@ ++/* ++ * uac_device.c -- interface to USB gadget "ALSA sound card" utilities ++ * ++ * Copyright (C) 2016 ++ * Author: Ruslan Bilovol ++ * ++ * Sound card implementation was cut-and-pasted with changes ++ * from f_uac2.c and has: ++ * Copyright (C) 2011 ++ * Yadwinder Singh (yadi.brar01@gmail.com) ++ * Jaswinder Singh (jaswinder.singh@linaro.org) ++ * ++ * 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 ++#include ++#include ++#include ++ ++#include "uac_queue_ex.h" ++#include "uac_ex.h" ++ ++static void ++__uac_audio_complete(struct usb_ep *ep, struct usb_request *req) ++{ ++ struct uac_device *uac_dev = req->context; ++ struct uac_queue *queue = &uac_dev->queue; ++ struct uac_buffer *buf; ++ ++ unsigned long flags; ++ int ret; ++ ++ switch (req->status) { ++ case 0: ++ break; ++ ++ case -ESHUTDOWN: /* disconnect from host. */ ++ printk(KERN_DEBUG "AS request cancelled.\n"); ++ uac_queue_cancel(queue, 1); ++ goto err; ++ ++ default: ++ printk(KERN_INFO "AS request completed with status %d.\n", ++ req->status); ++ uac_queue_cancel(queue, 0); ++ goto err; ++ } ++ ++ spin_lock_irqsave(&uac_dev->queue.irqlock, flags); ++ buf = uac_queue_head(&uac_dev->queue); ++ if (buf == NULL) { ++ req->length = 0; ++ goto tran_zero; ++ } ++ ++ { ++ /* ++ * For each IN packet, take the quotient of the current data ++ * rate and the endpoint's interval as the base packet size. ++ * If there is a residue from this division, add it to the ++ * residue accumulator. ++ */ ++ req->length = uac_dev->p_pktsize; ++ uac_dev->p_residue += uac_dev->p_pktsize_residue; ++ ++ /* ++ * Whenever there are more bytes in the accumulator than we ++ * need to add one more sample frame, increase this packet's ++ * size and decrease the accumulator. ++ */ ++ ++ if (uac_dev->p_residue / uac_dev->p_interval >= uac_dev->p_framesize) ++ { ++ req->length += uac_dev->p_framesize; ++ uac_dev->p_residue -= uac_dev->p_framesize * ++ uac_dev->p_interval; ++ } ++ ++ req->actual = req->length; ++ } ++ ++ { ++ unsigned int nbytes; ++ void *mem; ++ ++ /* Copy video data to the USB buffer. */ ++ mem = buf->mem + queue->buf_used; ++ nbytes = min((unsigned int)req->length, buf->bytesused - queue->buf_used); ++ ++ memcpy(req->buf, mem, nbytes); ++ queue->buf_used += nbytes; ++ ++ req->length = nbytes; ++ req->actual = req->length; ++ ++ if (buf->bytesused == uac_dev->queue.buf_used) { ++ uac_dev->queue.buf_used = 0; ++ buf->state = UVC_BUF_STATE_DONE; ++ uac_queue_next_buffer(&uac_dev->queue, buf); ++ } ++ } ++ ++tran_zero: ++ ++ req->actual = req->length; ++ ++ if ((ret = usb_ep_queue(ep, req, GFP_ATOMIC)) < 0) { ++ printk(KERN_INFO "Failed to queue request (%d).\n", ret); ++ usb_ep_set_halt(ep); ++ spin_unlock_irqrestore(&uac_dev->queue.irqlock, flags); ++ uac_queue_cancel(queue, 0); ++ } ++ spin_unlock_irqrestore(&uac_dev->queue.irqlock, flags); ++ ++err: ++ return; ++} ++ ++static inline void free_ep(struct uac_device *dev, struct usb_ep *ep) ++{ ++ struct uac_params *params; ++ int i; ++ ++ if (!dev->ep_enabled) ++ return; ++ ++ dev->ep_enabled = false; ++ params = &dev->params; ++ ++ for (i = 0; i < params->req_number; i++) { ++ if (dev->ureq[i].req) { ++ usb_ep_dequeue(ep, dev->ureq[i].req); ++ usb_ep_free_request(ep, dev->ureq[i].req); ++ dev->ureq[i].req = NULL; ++ } ++ } ++ ++ if (usb_ep_disable(ep)) ++ printk(KERN_EMERG "%s:%d Error!\n", __func__, __LINE__); ++} ++ ++int uac_device_start_playback(struct uac_device *uac_dev) ++{ ++ struct usb_gadget *gadget = uac_dev->gadget; ++ struct usb_request *req; ++ struct usb_ep *ep; ++ struct uac_params *params = &uac_dev->params; ++ unsigned int factor, rate; ++ const struct usb_endpoint_descriptor *ep_desc; ++ int req_len, i; ++ ++ if (uac_dev->ep_enabled) ++ return 0; ++ ++ ep = uac_dev->in_ep; ++ config_ep_by_speed(gadget, &uac_dev->func, ep); ++ ep_desc = ep->desc; ++ ++ /* pre-calculate the playback endpoint's interval */ ++ if (gadget->speed == USB_SPEED_FULL) ++ factor = 1000; ++ else ++ factor = 8000; ++ ++ /* pre-compute some values for iso_complete() */ ++ uac_dev->p_framesize = params->p_ssize * ++ num_channels(params->p_chmask); ++ rate = params->p_srate * uac_dev->p_framesize; ++ uac_dev->p_interval = factor / (1 << (ep_desc->bInterval - 1)); ++ uac_dev->p_pktsize = min_t(unsigned int, rate / uac_dev->p_interval, ++ uac_dev->max_psize); ++ ++ if (uac_dev->p_pktsize < uac_dev->max_psize) ++ uac_dev->p_pktsize_residue = rate % uac_dev->p_interval; ++ else ++ uac_dev->p_pktsize_residue = 0; ++ ++ req_len = uac_dev->p_pktsize; ++ uac_dev->p_residue = 0; ++ ++ uac_dev->ep_enabled = true; ++ usb_ep_enable(ep); ++ ++ printk(KERN_EMERG "p_framesize=%d p_interval=%d p_pktsize=%d \ ++ p_pktsize_residue=%d m=%d\n", ++ uac_dev->p_framesize, ++ uac_dev->p_interval, ++ uac_dev->p_pktsize, ++ uac_dev->p_pktsize_residue, ++ uac_dev->max_psize); ++ ++ for (i = 0; i < params->req_number; i++) { ++ if (!uac_dev->ureq[i].req) { ++ req = usb_ep_alloc_request(ep, GFP_ATOMIC); ++ if (req == NULL) ++ return -ENOMEM; ++ ++ uac_dev->ureq[i].req = req; ++ uac_dev->ureq[i].dev = uac_dev; ++ ++ req->zero = 0; ++ req->context = uac_dev; ++ req->length = req_len; ++ req->complete = __uac_audio_complete; ++ req->buf = uac_dev->rbuf + i * uac_dev->max_psize; ++ } ++ ++ if (usb_ep_queue(ep, uac_dev->ureq[i].req, GFP_ATOMIC)) ++ printk(KERN_EMERG "%s:%d Error!\n", __func__, __LINE__); ++ } ++ ++ return 0; ++} ++ ++void uac_device_stop_playback(struct uac_device *uac_dev) ++{ ++ free_ep(uac_dev, uac_dev->in_ep); ++} ++ ++int uac_device_setup(struct uac_device *uac_dev) ++{ ++ struct uac_params *params; ++ int p_chmask; ++ int err = 0; ++ ++ if (!uac_dev) ++ return -EINVAL; ++ ++ params = &uac_dev->params; ++ p_chmask = params->p_chmask; ++ ++ if (p_chmask) { ++ uac_dev->max_psize = uac_dev->in_ep_maxpsize; ++ uac_dev->ureq = kcalloc(params->req_number, sizeof(struct uac_req), ++ GFP_KERNEL); ++ if (!uac_dev->ureq) { ++ err = -ENOMEM; ++ goto fail; ++ } ++ ++ uac_dev->rbuf = kcalloc(params->req_number, uac_dev->max_psize, ++ GFP_KERNEL); ++ if (!uac_dev->rbuf) { ++ uac_dev->max_psize = 0; ++ err = -ENOMEM; ++ goto fail; ++ } ++ } ++ ++ if (!err) ++ return 0; ++fail: ++ kfree(uac_dev->ureq); ++ kfree(uac_dev->rbuf); ++ ++ return err; ++} ++ ++void uac_device_cleanup(struct uac_device *uac_dev) ++{ ++ if (!uac_dev) ++ return; ++ ++ kfree(uac_dev->ureq); ++ kfree(uac_dev->rbuf); ++} +diff --git a/drivers/usb/gadget/function/uac_ex.h b/drivers/usb/gadget/function/uac_ex.h +new file mode 100644 +index 0000000..a62708c +--- /dev/null ++++ b/drivers/usb/gadget/function/uac_ex.h +@@ -0,0 +1,133 @@ ++/* ++ * The file defines UAC API for user space ++ */ ++ ++#ifndef _UAC_EX_H_ ++#define _UAC_EX_H_ ++ ++#include ++#include ++#include ++ ++#define UAC_EVENT_FIRST (V4L2_EVENT_PRIVATE_START + 0) ++#define UAC_EVENT_CONNECT (V4L2_EVENT_PRIVATE_START + 0) ++#define UAC_EVENT_DISCONNECT (V4L2_EVENT_PRIVATE_START + 1) ++#define UAC_EVENT_STREAMON (V4L2_EVENT_PRIVATE_START + 2) ++#define UAC_EVENT_STREAMOFF (V4L2_EVENT_PRIVATE_START + 3) ++#define UAC_EVENT_SETUP (V4L2_EVENT_PRIVATE_START + 4) ++#define UAC_EVENT_DATA (V4L2_EVENT_PRIVATE_START + 5) ++#define UAC_EVENT_LAST (V4L2_EVENT_PRIVATE_START + 5) ++ ++#ifdef __KERNEL__ ++ ++#include /* For usb_endpoint_* */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "uac_queue_ex.h" ++ ++struct uac_request_data ++{ ++ __s32 length; ++ __u8 data[60]; ++}; ++ ++struct uac_event ++{ ++ union { ++ struct uac_request_data data; ++ }; ++}; ++ ++/* ------------------------------------------------------------------------ ++ * Structures ++ */ ++ ++struct uac_params { ++ /* playback */ ++ int p_chmask; /* channel mask */ ++ int p_srate; /* rate in Hz */ ++ int p_ssize; /* sample size */ ++ ++ /* capture */ ++ int c_chmask; /* channel mask */ ++ int c_srate; /* rate in Hz */ ++ int c_ssize; /* sample size */ ++ ++ int req_number; /* number of preallocated requests */ ++}; ++ ++struct uac_req { ++ struct uac_device *dev; /* parent param */ ++ struct usb_request *req; ++}; ++ ++struct uac_device ++{ ++ struct usb_function func; ++ struct usb_gadget *gadget; ++ struct usb_ep *in_ep; ++ struct usb_ep *out_ep; ++ struct uac_params params; ++ struct video_device *vdev; ++ struct v4l2_device v4l2_dev; ++ struct uac_queue queue; ++ struct uac_req *ureq; ++ void *rbuf; ++ struct usb_request *control_req; ++ void *control_buf; ++ ++ unsigned int in_ep_maxpsize; ++ unsigned int out_ep_maxpsize; ++ bool ep_enabled; /* if the ep is enabled */ ++ unsigned max_psize; /* MaxPacketSize of endpoint */ ++ ++ /* timekeeping for the playback endpoint */ ++ unsigned int p_interval; ++ unsigned int p_residue; ++ ++ /* pre-calculated values for playback iso completion */ ++ unsigned int p_pktsize; ++ unsigned int p_pktsize_residue; ++ unsigned int p_framesize; ++}; ++ ++struct uac_file_handle ++{ ++ struct v4l2_fh vfh; ++ struct uac_device *dev; ++}; ++ ++#define to_uac_file_handle(handle) \ ++ container_of(handle, struct uac_file_handle, vfh) ++ ++static inline struct uac_device *func_to_uac_device(struct usb_function *f) ++{ ++ return container_of(f, struct uac_device, func); ++} ++ ++static inline uint num_channels(uint chanmask) ++{ ++ uint num = 0; ++ ++ while (chanmask) { ++ num += (chanmask & 1); ++ chanmask >>= 1; ++ } ++ ++ return num; ++} ++ ++int uac_device_setup(struct uac_device *uac_dev); ++void uac_device_cleanup(struct uac_device *g_audio); ++int uac_device_start_playback(struct uac_device *uac_dev); ++void uac_device_stop_playback(struct uac_device *uac_dev); ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* _UAC_EX_H_ */ ++ +diff --git a/drivers/usb/gadget/function/uac_queue_ex.c b/drivers/usb/gadget/function/uac_queue_ex.c +new file mode 100644 +index 0000000..89dcf6b +--- /dev/null ++++ b/drivers/usb/gadget/function/uac_queue_ex.c +@@ -0,0 +1,379 @@ ++/* ++ * uac_queue.c -- USB Video Class driver - Buffers management ++ * ++ * Copyright (C) 2005-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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "uac_ex.h" ++ ++/* ------------------------------------------------------------------------ ++ * Video buffers queue management. ++ * ++ * Video queues is initialized by uac_queue_init(). The function performs ++ * basic initialization of the uac_queue struct and never fails. ++ * ++ * Video buffers are managed by videobuf2. The driver uses a mutex to protect ++ * the videobuf2 queue operations by serializing calls to videobuf2 and a ++ * spinlock to protect the IRQ queue that holds the buffers to be processed by ++ * the driver. ++ */ ++ ++/* ----------------------------------------------------------------------------- ++ * videobuf2 queue operations ++ */ ++ ++static int uac_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, ++ unsigned int *nbuffers, unsigned int *nplanes, ++ unsigned int sizes[], void *alloc_ctxs[]) ++{ ++ if (*nbuffers > UVC_MAX_VIDEO_BUFFERS) ++ *nbuffers = UVC_MAX_VIDEO_BUFFERS; ++ ++ *nplanes = 1; ++ ++ sizes[0] = 1024; ++ ++ return 0; ++} ++ ++static int uac_buffer_prepare(struct vb2_buffer *vb) ++{ ++ struct uac_queue *queue = vb2_get_drv_priv(vb->vb2_queue); ++ struct uac_buffer *buf = container_of(vb, struct uac_buffer, buf); ++ ++ if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT && ++ vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) { ++ printk(KERN_EMERG "[E] Bytes used out of bounds.\n"); ++ return -EINVAL; ++ } ++ ++ if (unlikely(queue->flags & UVC_QUEUE_DISCONNECTED)) ++ return -ENODEV; ++ ++ buf->state = UVC_BUF_STATE_QUEUED; ++ buf->mem = vb2_plane_vaddr(vb, 0); ++ buf->length = vb2_plane_size(vb, 0); ++ if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ buf->bytesused = 0; ++ else ++ buf->bytesused = vb2_get_plane_payload(vb, 0); ++ ++ return 0; ++} ++ ++static void uac_buffer_queue(struct vb2_buffer *vb) ++{ ++ struct uac_queue *queue = vb2_get_drv_priv(vb->vb2_queue); ++ struct uac_buffer *buf = container_of(vb, struct uac_buffer, buf); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&queue->irqlock, flags); ++ ++ if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) { ++ list_add_tail(&buf->queue, &queue->irqqueue); ++ } else { ++ /* If the device is disconnected return the buffer to userspace ++ * directly. The next QBUF call will fail with -ENODEV. ++ */ ++ buf->state = UVC_BUF_STATE_ERROR; ++ vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR); ++ } ++ ++ spin_unlock_irqrestore(&queue->irqlock, flags); ++} ++ ++static void uac_wait_prepare(struct vb2_queue *vq) ++{ ++ struct uac_queue *queue = vb2_get_drv_priv(vq); ++ ++ mutex_unlock(&queue->mutex); ++} ++ ++static void uac_wait_finish(struct vb2_queue *vq) ++{ ++ struct uac_queue *queue = vb2_get_drv_priv(vq); ++ ++ mutex_lock(&queue->mutex); ++} ++ ++static void uac_stop_streaming(struct vb2_queue *vq) ++{ ++ struct uac_queue *queue = vb2_get_drv_priv(vq); ++ ++ uac_queue_cancel(queue, 0); ++} ++ ++static struct vb2_ops uac_queue_qops = { ++ .queue_setup = uac_queue_setup, ++ .buf_prepare = uac_buffer_prepare, ++ .buf_queue = uac_buffer_queue, ++ .wait_prepare = uac_wait_prepare, ++ .wait_finish = uac_wait_finish, ++ .stop_streaming = uac_stop_streaming, ++}; ++ ++int uac_queue_init(struct uac_queue *queue) ++{ ++ int ret; ++ ++ queue->queue.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ queue->queue.io_modes = VB2_USERPTR; ++ queue->queue.drv_priv = queue; ++ queue->queue.buf_struct_size = sizeof(struct uac_buffer); ++ queue->queue.ops = &uac_queue_qops; ++ queue->queue.mem_ops = &vb2_vmalloc_memops; ++ queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC ++ | V4L2_BUF_FLAG_TSTAMP_SRC_EOF; ++ ret = vb2_queue_init(&queue->queue); ++ if (ret) ++ return ret; ++ ++ mutex_init(&queue->mutex); ++ spin_lock_init(&queue->irqlock); ++ INIT_LIST_HEAD(&queue->irqqueue); ++ queue->flags = 0; ++ ++ return 0; ++} ++ ++/* ++ * Free the video buffers. ++ */ ++void uac_free_buffers(struct uac_queue *queue) ++{ ++ mutex_lock(&queue->mutex); ++ vb2_queue_release(&queue->queue); ++ mutex_unlock(&queue->mutex); ++} ++ ++/* ++ * Allocate the video buffers. ++ */ ++int uac_alloc_buffers(struct uac_queue *queue, ++ struct v4l2_requestbuffers *rb) ++{ ++ int ret; ++ ++ mutex_lock(&queue->mutex); ++ ret = vb2_reqbufs(&queue->queue, rb); ++ mutex_unlock(&queue->mutex); ++ ++ return ret ? ret : rb->count; ++} ++ ++int uac_query_buffer(struct uac_queue *queue, struct v4l2_buffer *buf) ++{ ++ int ret; ++ ++ mutex_lock(&queue->mutex); ++ ret = vb2_querybuf(&queue->queue, buf); ++ mutex_unlock(&queue->mutex); ++ ++ return ret; ++} ++ ++int uac_queue_buffer(struct uac_queue *queue, struct v4l2_buffer *buf) ++{ ++ unsigned long flags; ++ int ret; ++ ++ mutex_lock(&queue->mutex); ++ ret = vb2_qbuf(&queue->queue, buf); ++ if (ret < 0) ++ goto done; ++ ++ spin_lock_irqsave(&queue->irqlock, flags); ++ ret = (queue->flags & UVC_QUEUE_PAUSED) != 0; ++ queue->flags &= ~UVC_QUEUE_PAUSED; ++ spin_unlock_irqrestore(&queue->irqlock, flags); ++ ++done: ++ mutex_unlock(&queue->mutex); ++ return ret; ++} ++ ++/* ++ * Dequeue a video buffer. If nonblocking is false, block until a buffer is ++ * available. ++ */ ++int uac_dequeue_buffer(struct uac_queue *queue, struct v4l2_buffer *buf, ++ int nonblocking) ++{ ++ int ret; ++ ++ mutex_lock(&queue->mutex); ++ ret = vb2_dqbuf(&queue->queue, buf, nonblocking); ++ mutex_unlock(&queue->mutex); ++ ++ return ret; ++} ++ ++/* ++ * Poll the video queue. ++ * ++ * This function implements video queue polling and is intended to be used by ++ * the device poll handler. ++ */ ++unsigned int uac_queue_poll(struct uac_queue *queue, struct file *file, ++ poll_table *wait) ++{ ++ unsigned int ret; ++ ++ mutex_lock(&queue->mutex); ++ ret = vb2_poll(&queue->queue, file, wait); ++ mutex_unlock(&queue->mutex); ++ ++ return ret; ++} ++ ++/* ++ * Cancel the video buffers queue. ++ * ++ * Cancelling the queue marks all buffers on the irq queue as erroneous, ++ * wakes them up and removes them from the queue. ++ * ++ * If the disconnect parameter is set, further calls to uac_queue_buffer will ++ * fail with -ENODEV. ++ * ++ * This function acquires the irq spinlock and can be called from interrupt ++ * context. ++ */ ++void uac_queue_cancel(struct uac_queue *queue, int disconnect) ++{ ++ struct uac_buffer *buf; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&queue->irqlock, flags); ++ while (!list_empty(&queue->irqqueue)) { ++ buf = list_first_entry(&queue->irqqueue, struct uac_buffer, ++ queue); ++ list_del(&buf->queue); ++ buf->state = UVC_BUF_STATE_ERROR; ++ vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR); ++ } ++ /* This must be protected by the irqlock spinlock to avoid race ++ * conditions between uac_queue_buffer and the disconnection event that ++ * could result in an interruptible wait in uac_dequeue_buffer. Do not ++ * blindly replace this logic by checking for the UVC_DEV_DISCONNECTED ++ * state outside the queue code. ++ */ ++ if (disconnect) ++ queue->flags |= UVC_QUEUE_DISCONNECTED; ++ spin_unlock_irqrestore(&queue->irqlock, flags); ++} ++ ++/* ++ * Enable or disable the video buffers queue. ++ * ++ * The queue must be enabled before starting video acquisition and must be ++ * disabled after stopping it. This ensures that the video buffers queue ++ * state can be properly initialized before buffers are accessed from the ++ * interrupt handler. ++ * ++ * Enabling the video queue initializes parameters (such as sequence number, ++ * sync pattern, ...). If the queue is already enabled, return -EBUSY. ++ * ++ * Disabling the video queue cancels the queue and removes all buffers from ++ * the main queue. ++ * ++ * This function can't be called from interrupt context. Use ++ * uac_queue_cancel() instead. ++ */ ++int uac_queue_enable(struct uac_queue *queue, int enable) ++{ ++ unsigned long flags; ++ int ret = 0; ++ ++ mutex_lock(&queue->mutex); ++ if (enable) { ++ ret = vb2_streamon(&queue->queue, queue->queue.type); ++ if (ret < 0) ++ goto done; ++ ++ queue->sequence = 0; ++ queue->buf_used = 0; ++ } else { ++ ret = vb2_streamoff(&queue->queue, queue->queue.type); ++ if (ret < 0) ++ goto done; ++ ++ spin_lock_irqsave(&queue->irqlock, flags); ++ INIT_LIST_HEAD(&queue->irqqueue); ++ ++ /* ++ * FIXME: We need to clear the DISCONNECTED flag to ensure that ++ * applications will be able to queue buffers for the next ++ * streaming run. However, clearing it here doesn't guarantee ++ * that the device will be reconnected in the meantime. ++ */ ++ queue->flags &= ~UVC_QUEUE_DISCONNECTED; ++ spin_unlock_irqrestore(&queue->irqlock, flags); ++ } ++ ++done: ++ mutex_unlock(&queue->mutex); ++ return ret; ++} ++ ++/* called with &queue_irqlock held.. */ ++struct uac_buffer *uac_queue_next_buffer(struct uac_queue *queue, ++ struct uac_buffer *buf) ++{ ++ struct uac_buffer *nextbuf; ++ ++ if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) && ++ buf->length != buf->bytesused) { ++ buf->state = UVC_BUF_STATE_QUEUED; ++ vb2_set_plane_payload(&buf->buf, 0, 0); ++ return buf; ++ } ++ ++ list_del(&buf->queue); ++ if (!list_empty(&queue->irqqueue)) ++ nextbuf = list_first_entry(&queue->irqqueue, struct uac_buffer, ++ queue); ++ else ++ nextbuf = NULL; ++ ++ buf->buf.v4l2_buf.field = V4L2_FIELD_NONE; ++ buf->buf.v4l2_buf.sequence = queue->sequence++; ++ v4l2_get_timestamp(&buf->buf.v4l2_buf.timestamp); ++ ++ vb2_set_plane_payload(&buf->buf, 0, buf->bytesused); ++ vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE); ++ ++ return nextbuf; ++} ++ ++struct uac_buffer *uac_queue_head(struct uac_queue *queue) ++{ ++ struct uac_buffer *buf = NULL; ++ ++ if (!list_empty(&queue->irqqueue)) ++ buf = list_first_entry(&queue->irqqueue, struct uac_buffer, ++ queue); ++ else ++ queue->flags |= UVC_QUEUE_PAUSED; ++ ++ return buf; ++} ++ +diff --git a/drivers/usb/gadget/function/uac_queue_ex.h b/drivers/usb/gadget/function/uac_queue_ex.h +new file mode 100644 +index 0000000..4b5db20 +--- /dev/null ++++ b/drivers/usb/gadget/function/uac_queue_ex.h +@@ -0,0 +1,90 @@ ++#ifndef _UAC_QUEUE_H_ ++#define _UAC_QUEUE_H_ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include ++#include ++#include ++ ++/* Maximum frame size in bytes, for sanity checking. */ ++#define UVC_MAX_FRAME_SIZE (16*1024*1024) ++/* Maximum number of video buffers. */ ++#define UVC_MAX_VIDEO_BUFFERS 32 ++ ++/* ------------------------------------------------------------------------ ++ * Structures. ++ */ ++ ++enum uac_buffer_state { ++ UVC_BUF_STATE_IDLE = 0, ++ UVC_BUF_STATE_QUEUED = 1, ++ UVC_BUF_STATE_ACTIVE = 2, ++ UVC_BUF_STATE_DONE = 3, ++ UVC_BUF_STATE_ERROR = 4, ++}; ++ ++struct uac_buffer { ++ struct vb2_buffer buf; ++ struct list_head queue; ++ ++ enum uac_buffer_state state; ++ void *mem; ++ unsigned int length; ++ unsigned int bytesused; ++}; ++ ++#define UVC_QUEUE_DISCONNECTED (1 << 0) ++#define UVC_QUEUE_DROP_INCOMPLETE (1 << 1) ++#define UVC_QUEUE_PAUSED (1 << 2) ++ ++struct uac_queue { ++ struct vb2_queue queue; ++ struct mutex mutex; /* Protects queue */ ++ ++ unsigned int flags; ++ __u32 sequence; ++ ++ unsigned int buf_used; ++ ++ spinlock_t irqlock; /* Protects flags and irqqueue */ ++ struct list_head irqqueue; ++}; ++ ++static inline int uac_queue_streaming(struct uac_queue *queue) ++{ ++ return vb2_is_streaming(&queue->queue); ++} ++ ++int uac_queue_init(struct uac_queue *queue); ++ ++void uac_free_buffers(struct uac_queue *queue); ++ ++int uac_alloc_buffers(struct uac_queue *queue, ++ struct v4l2_requestbuffers *rb); ++ ++int uac_query_buffer(struct uac_queue *queue, struct v4l2_buffer *buf); ++ ++int uac_queue_buffer(struct uac_queue *queue, struct v4l2_buffer *buf); ++ ++int uac_dequeue_buffer(struct uac_queue *queue, ++ struct v4l2_buffer *buf, int nonblocking); ++ ++unsigned int uac_queue_poll(struct uac_queue *queue, ++ struct file *file, poll_table *wait); ++ ++ ++void uac_queue_cancel(struct uac_queue *queue, int disconnect); ++ ++int uac_queue_enable(struct uac_queue *queue, int enable); ++ ++struct uac_buffer *uac_queue_next_buffer(struct uac_queue *queue, ++ struct uac_buffer *buf); ++ ++struct uac_buffer *uac_queue_head(struct uac_queue *queue); ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* _UAC_QUEUE_H_ */ ++ +diff --git a/drivers/usb/gadget/function/uac_v4l2_ex.c b/drivers/usb/gadget/function/uac_v4l2_ex.c +new file mode 100644 +index 0000000..4570b7a +--- /dev/null ++++ b/drivers/usb/gadget/function/uac_v4l2_ex.c +@@ -0,0 +1,218 @@ ++/* ++ * uac_v4l2.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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "uac_ex.h" ++#include "uac_queue_ex.h" ++ ++static int ++uac_v4l2_querycap(struct file *file, void *fh, struct v4l2_capability *cap) ++{ ++ strlcpy(cap->driver, "g_uac", sizeof(cap->driver)); ++ strlcpy(cap->card, "g_uac", sizeof(cap->card)); ++ ++ cap->capabilities = V4L2_CAP_AUDIO; ++ ++ return 0; ++} ++static int ++uac_v4l2_get_format(struct file *file, void *fh, struct v4l2_format *fmt) ++{ ++ return 0; ++} ++ ++static int ++uac_v4l2_set_format(struct file *file, void *fh, struct v4l2_format *fmt) ++{ ++ return 0; ++} ++ ++static int ++uac_v4l2_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *b) ++{ ++ struct video_device *vdev = video_devdata(file); ++ struct uac_device *uac = video_get_drvdata(vdev); ++ ++ if (b->type != uac->queue.queue.type) ++ return -EINVAL; ++ ++ return uac_alloc_buffers(&uac->queue, b); ++} ++ ++static int ++uac_v4l2_querybuf(struct file *file, void *fh, struct v4l2_buffer *b) ++{ ++ struct video_device *vdev = video_devdata(file); ++ struct uac_device *uac = video_get_drvdata(vdev); ++ ++ return uac_query_buffer(&uac->queue, b); ++} ++ ++static int ++uac_v4l2_qbuf(struct file *file, void *fh, struct v4l2_buffer *b) ++{ ++ struct video_device *vdev = video_devdata(file); ++ struct uac_device *uac = video_get_drvdata(vdev); ++ ++ return uac_queue_buffer(&uac->queue, b); ++} ++ ++static int ++uac_v4l2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) ++{ ++ struct video_device *vdev = video_devdata(file); ++ struct uac_device *uac = video_get_drvdata(vdev); ++ ++ return uac_dequeue_buffer(&uac->queue, b, file->f_flags & O_NONBLOCK); ++} ++ ++static int ++uac_v4l2_streamon(struct file *file, void *fh, enum v4l2_buf_type type) ++{ ++ struct video_device *vdev = video_devdata(file); ++ struct uac_device *uac = video_get_drvdata(vdev); ++ ++ int ret; ++ ++ if (type != uac->queue.queue.type) ++ return -EINVAL; ++ ++ ret = uac_queue_enable(&uac->queue, 1); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int ++uac_v4l2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) ++{ ++ struct video_device *vdev = video_devdata(file); ++ struct uac_device *uac = video_get_drvdata(vdev); ++ ++ if (type != uac->queue.queue.type) ++ return -EINVAL; ++ ++ return uac_queue_enable(&uac->queue, 0); ++} ++ ++static int ++uac_v4l2_subscribe_event(struct v4l2_fh *fh, ++ const struct v4l2_event_subscription *sub) ++{ ++ if (sub->type < UAC_EVENT_FIRST || sub->type > UAC_EVENT_LAST) ++ return -EINVAL; ++ ++ return v4l2_event_subscribe(fh, sub, 2, NULL); ++} ++ ++static int ++uac_v4l2_unsubscribe_event(struct v4l2_fh *fh, ++ const struct v4l2_event_subscription *sub) ++{ ++ return v4l2_event_unsubscribe(fh, sub); ++} ++ ++static long ++uac_v4l2_ioctl_default(struct file *file, void *fh, bool valid_prio, ++ unsigned int cmd, void *arg) ++{ ++ switch (cmd) { ++ default: ++ return -ENOIOCTLCMD; ++ } ++} ++ ++const struct v4l2_ioctl_ops uac_v4l2_ioctl_ops = { ++ .vidioc_querycap = uac_v4l2_querycap, ++ .vidioc_reqbufs = uac_v4l2_reqbufs, ++ .vidioc_querybuf = uac_v4l2_querybuf, ++ .vidioc_g_fmt_vid_out = uac_v4l2_get_format, ++ .vidioc_s_fmt_vid_out = uac_v4l2_set_format, ++ .vidioc_qbuf = uac_v4l2_qbuf, ++ .vidioc_dqbuf = uac_v4l2_dqbuf, ++ .vidioc_streamon = uac_v4l2_streamon, ++ .vidioc_streamoff = uac_v4l2_streamoff, ++ .vidioc_subscribe_event = uac_v4l2_subscribe_event, ++ .vidioc_unsubscribe_event = uac_v4l2_unsubscribe_event, ++ .vidioc_default = uac_v4l2_ioctl_default, ++}; ++ ++/* -------------------------------------------------------------------------- ++ * V4L2 ++ */ ++ ++static int ++uac_v4l2_open(struct file *file) ++{ ++ struct video_device *vdev = video_devdata(file); ++ struct uac_device *uac_dev = video_get_drvdata(vdev); ++ struct uac_file_handle *handle; ++ ++ handle = kzalloc(sizeof(*handle), GFP_KERNEL); ++ if (handle == NULL) ++ return -ENOMEM; ++ ++ v4l2_fh_init(&handle->vfh, vdev); ++ v4l2_fh_add(&handle->vfh); ++ ++ handle->dev = uac_dev; ++ file->private_data = &handle->vfh; ++ ++ return 0; ++} ++ ++static int ++uac_v4l2_release(struct file *file) ++{ ++ struct uac_file_handle *handle = to_uac_file_handle(file->private_data); ++ struct uac_device *uac_dev = handle->dev; ++ ++ uac_queue_enable(&uac_dev->queue, 0); ++ uac_free_buffers(&uac_dev->queue); ++ ++ file->private_data = NULL; ++ v4l2_fh_del(&handle->vfh); ++ v4l2_fh_exit(&handle->vfh); ++ kfree(handle); ++ ++ return 0; ++} ++ ++static unsigned int ++uac_v4l2_poll(struct file *file, poll_table *wait) ++{ ++ struct video_device *vdev = video_devdata(file); ++ struct uac_device *uac = video_get_drvdata(vdev); ++ ++ return uac_queue_poll(&uac->queue, file, wait); ++} ++ ++struct v4l2_file_operations uac_v4l2_fops = { ++ .owner = THIS_MODULE, ++ .open = uac_v4l2_open, ++ .release = uac_v4l2_release, ++ .ioctl = video_ioctl2, ++ .poll = uac_v4l2_poll, ++}; +diff --git a/drivers/usb/gadget/function/uac_v4l2_ex.h b/drivers/usb/gadget/function/uac_v4l2_ex.h +new file mode 100644 +index 0000000..9df310f +--- /dev/null ++++ b/drivers/usb/gadget/function/uac_v4l2_ex.h +@@ -0,0 +1,22 @@ ++/* ++ * uvc_v4l2.h -- USB Video Class Gadget driver ++ * ++ * Copyright (C) 2009-2010 ++ * Laurent Pinchart (laurent.pinchart@ideasonboard.com) ++ * ++ * Copyright (c) 2013 Samsung Electronics Co., Ltd. ++ * http://www.samsung.com ++ * Author: Andrzej Pietrasiewicz ++ * ++ * 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 __UAC_V4L2_H__ ++#define __UAC_V4L2_H__ ++ ++extern const struct v4l2_ioctl_ops uac_v4l2_ioctl_ops; ++extern struct v4l2_file_operations uac_v4l2_fops; ++ ++#endif /* __UAC_V4L2_H__ */ +diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h +index f67695c..fcba11b 100644 +--- a/drivers/usb/gadget/function/uvc.h ++++ b/drivers/usb/gadget/function/uvc.h +@@ -96,8 +96,11 @@ extern unsigned int uvc_gadget_trace_param; + /* ------------------------------------------------------------------------ + * Driver specific constants + */ +- +-#define UVC_NUM_REQUESTS 4 ++#ifdef CONFIG_HIUSB_DEVICE2_0 ++#define UVC_NUM_REQUESTS 1 ++#else ++#define UVC_NUM_REQUESTS 32 ++#endif + #define UVC_MAX_REQUEST_SIZE 64 + #define UVC_MAX_EVENTS 4 + +@@ -132,6 +135,8 @@ struct uvc_video + + struct uvc_video_queue queue; + unsigned int fid; ++ bool bulk_streaming_ep; ++ unsigned int bulk_max_size; + }; + + enum uvc_state +@@ -139,6 +144,7 @@ enum uvc_state + UVC_STATE_DISCONNECTED, + UVC_STATE_CONNECTED, + UVC_STATE_STREAMING, ++ UVC_STATE_CONFIG, //just for bulk-xfer + }; + + struct uvc_device +diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c +index 5aad7fe..07f9442 100644 +--- a/drivers/usb/gadget/function/uvc_v4l2.c ++++ b/drivers/usb/gadget/function/uvc_v4l2.c +@@ -62,6 +62,7 @@ struct uvc_format + static struct uvc_format uvc_formats[] = { + { 16, V4L2_PIX_FMT_YUYV }, + { 0, V4L2_PIX_FMT_MJPEG }, ++ { 0, V4L2_PIX_FMT_H264 }, + }; + + static int +@@ -200,6 +201,9 @@ uvc_v4l2_streamon(struct file *file, void *fh, enum v4l2_buf_type type) + if (type != video->queue.queue.type) + return -EINVAL; + ++ if (video->bulk_streaming_ep) ++ uvc_function_connect(uvc); ++ + /* Enable UVC video. */ + ret = uvcg_video_enable(video, 1); + if (ret < 0) +@@ -209,8 +213,15 @@ uvc_v4l2_streamon(struct file *file, void *fh, enum v4l2_buf_type type) + * Complete the alternate setting selection setup phase now that + * userspace is ready to provide video frames. + */ +- uvc_function_setup_continue(uvc); +- uvc->state = UVC_STATE_STREAMING; ++ if (!video->bulk_streaming_ep) { ++ /* ++ * Complete the alternate setting selection setup ++ * phase now that userspace is ready to provide video ++ * frames. ++ */ ++ uvc_function_setup_continue(uvc); ++ uvc->state = UVC_STATE_STREAMING; ++ } + + return 0; + } +@@ -218,6 +229,7 @@ uvc_v4l2_streamon(struct file *file, void *fh, enum v4l2_buf_type type) + static int + uvc_v4l2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) + { ++ int code = 0; + struct video_device *vdev = video_devdata(file); + struct uvc_device *uvc = video_get_drvdata(vdev); + struct uvc_video *video = &uvc->video; +@@ -225,7 +237,12 @@ uvc_v4l2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) + if (type != video->queue.queue.type) + return -EINVAL; + +- return uvcg_video_enable(video, 0); ++ code = uvcg_video_enable(video, 0); ++ ++ if (video->bulk_streaming_ep) ++ uvc_function_disconnect(uvc); ++ ++ return code; + } + + static int +@@ -363,4 +380,3 @@ struct v4l2_file_operations uvc_v4l2_fops = { + .get_unmapped_area = uvcg_v4l2_get_unmapped_area, + #endif + }; +- +diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c +index 9cb86bc..754a321 100644 +--- a/drivers/usb/gadget/function/uvc_video.c ++++ b/drivers/usb/gadget/function/uvc_video.c +@@ -185,13 +185,26 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) + + spin_lock_irqsave(&video->queue.irqlock, flags); + buf = uvcg_queue_head(&video->queue); ++#ifdef CONFIG_ARCH_HISI ++ if (buf == NULL) { ++ if (video->bulk_streaming_ep) { ++ spin_unlock_irqrestore(&video->queue.irqlock, flags); ++ goto requeue; ++ } else { ++ req->length = 0; ++ goto tran_zero; ++ } ++ } ++#else + if (buf == NULL) { + spin_unlock_irqrestore(&video->queue.irqlock, flags); + goto requeue; + } ++#endif + + video->encode(req, video, buf); + ++tran_zero: + if ((ret = usb_ep_queue(ep, req, GFP_ATOMIC)) < 0) { + printk(KERN_INFO "Failed to queue request (%d).\n", ret); + usb_ep_set_halt(ep); +@@ -240,9 +253,13 @@ uvc_video_alloc_requests(struct uvc_video *video) + + BUG_ON(video->req_size); + +- req_size = video->ep->maxpacket +- * max_t(unsigned int, video->ep->maxburst, 1) +- * (video->ep->mult + 1); ++ if (!video->bulk_streaming_ep) ++ req_size = video->ep->maxpacket ++ * max_t(unsigned int, video->ep->maxburst, 1) ++ * (video->ep->mult + 1); ++ else ++ req_size = video->ep->maxpacket ++ * max_t(unsigned int, video->ep->maxburst, 1); + + for (i = 0; i < UVC_NUM_REQUESTS; ++i) { + video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL); +@@ -389,6 +406,10 @@ int uvcg_video_init(struct uvc_video *video) + video->height = 240; + video->imagesize = 320 * 240 * 2; + ++ if (video->bulk_streaming_ep) ++ video->max_payload_size = video->bulk_max_size; ++ ++ + /* Initialize the video buffers queue. */ + uvcg_queue_init(&video->queue, V4L2_BUF_TYPE_VIDEO_OUTPUT); + return 0; +diff --git a/drivers/usb/gadget/functions.c b/drivers/usb/gadget/functions.c +index b13f839..389c1f3 100644 +--- a/drivers/usb/gadget/functions.c ++++ b/drivers/usb/gadget/functions.c +@@ -58,7 +58,7 @@ struct usb_function *usb_get_function(struct usb_function_instance *fi) + struct usb_function *f; + + f = fi->fd->alloc_func(fi); +- if (IS_ERR(f)) ++ if ((f == NULL) || IS_ERR(f)) + return f; + f->fi = fi; + return f; +diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig +index 24392d2..6b3a349 100644 +--- a/drivers/usb/gadget/legacy/Kconfig ++++ b/drivers/usb/gadget/legacy/Kconfig +@@ -51,11 +51,8 @@ config USB_ZERO_HNPTEST + + config USB_AUDIO + tristate "Audio Gadget" +- depends on SND + select USB_LIBCOMPOSITE +- select SND_PCM + select USB_F_UAC1 if GADGET_UAC1 +- select USB_F_UAC2 if !GADGET_UAC1 + help + This Gadget Audio driver is compatible with USB Audio Class + specification 2.0. It implements 1 AudioControl interface, +@@ -75,6 +72,7 @@ config USB_AUDIO + config GADGET_UAC1 + bool "UAC 1.0 (Legacy)" + depends on USB_AUDIO ++ select USB_F_UAC1 + help + If you instead want older UAC Spec-1.0 driver that also has audio + paths hardwired to the Audio codec chip on-board and doesn't work +@@ -313,6 +311,26 @@ config USB_G_PRINTER + For more information, see Documentation/usb/gadget_printer.txt + which includes sample code for accessing the device file. + ++config USB_G_ANDROID ++ boolean "Android Composite Gadget" ++ select USB_F_ACM ++ select USB_LIBCOMPOSITE ++ select USB_U_SERIAL ++ select USB_F_MASS_STORAGE ++ select SND_PCM ++ help ++ The Android Composite Gadget supports multiple USB ++ functions: adb, acm, mass storage, mtp, accessory ++ and rndis. ++ Each function can be configured and enabled/disabled ++ dynamically from userspace through a sysfs interface. ++ ++config USB_ANDROID_RNDIS_DWORD_ALIGNED ++ boolean "Use double word aligned" ++ depends on USB_G_ANDROID ++ help ++ Provides dword aligned for DMA controller. ++ + if TTY + + config USB_CDC_COMPOSITE +@@ -476,3 +494,20 @@ config USB_G_WEBCAM + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "g_webcam". ++ ++# put drivers that need isochronous transfer support (for audio ++# or video class gadget drivers), or specific hardware, here. ++config USB_G_WEBCAM_AUDIO ++ tristate "USB Webcam+ Gadget(include audio)" ++ depends on VIDEO_DEV ++ select USB_LIBCOMPOSITE ++ select VIDEOBUF2_VMALLOC ++ select USB_F_UVC ++ help ++ The Webcam+ Gadget acts as a composite USB Audio and Video Class ++ device. It provides a userspace API to process UVC control requests ++ and stream video data to the host. ++ ++ Say "y" to link the driver statically, or "m" to build a ++ dynamically linked module called "g_webcam". ++ +diff --git a/drivers/usb/gadget/legacy/Makefile b/drivers/usb/gadget/legacy/Makefile +index 7f485f2..3e309aa 100644 +--- a/drivers/usb/gadget/legacy/Makefile ++++ b/drivers/usb/gadget/legacy/Makefile +@@ -20,8 +20,10 @@ g_hid-y := hid.o + g_dbgp-y := dbgp.o + g_nokia-y := nokia.o + g_webcam-y := webcam.o ++g_webcam_audio-y := webcam_audio.o + g_ncm-y := ncm.o + g_acm_ms-y := acm_ms.o ++g_android-y := android.o + g_tcm_usb_gadget-y := tcm_usb_gadget.o + + obj-$(CONFIG_USB_ZERO) += g_zero.o +@@ -39,6 +41,8 @@ obj-$(CONFIG_USB_G_DBGP) += g_dbgp.o + obj-$(CONFIG_USB_G_MULTI) += g_multi.o + obj-$(CONFIG_USB_G_NOKIA) += g_nokia.o + obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o ++obj-$(CONFIG_USB_G_WEBCAM_AUDIO) += g_webcam_audio.o + obj-$(CONFIG_USB_G_NCM) += g_ncm.o + obj-$(CONFIG_USB_G_ACM_MS) += g_acm_ms.o ++obj-$(CONFIG_USB_G_ANDROID) += g_android.o + obj-$(CONFIG_USB_GADGET_TARGET) += tcm_usb_gadget.o +diff --git a/drivers/usb/gadget/legacy/android.c b/drivers/usb/gadget/legacy/android.c +new file mode 100644 +index 0000000..1d38c8d +--- /dev/null ++++ b/drivers/usb/gadget/legacy/android.c +@@ -0,0 +1,1568 @@ ++/* ++ * Gadget Driver for Android ++ * ++ * Copyright (C) 2008 Google, Inc. ++ * Author: Mike Lockwood ++ * Benoit Goby ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "gadget_chips.h" ++ ++#include "f_fs.c" ++#include "f_audio_source.c" ++#include "f_mtp.c" ++#include "f_accessory.c" ++#define USB_ETH_RNDIS y ++#include "f_rndis.c" ++#include "rndis.c" ++#include "u_ether.c" ++ ++USB_ETHERNET_MODULE_PARAMETERS(); ++ ++MODULE_AUTHOR("Mike Lockwood"); ++MODULE_DESCRIPTION("Android Composite USB Driver"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION("1.0"); ++ ++static const char longname[] = "Gadget Android"; ++ ++/* Default vendor and product IDs, overridden by userspace */ ++#define VENDOR_ID 0x18D1 ++#define PRODUCT_ID 0x0001 ++ ++struct android_usb_function { ++ char *name; ++ void *config; ++ ++ struct device *dev; ++ char *dev_name; ++ struct device_attribute **attributes; ++ ++ /* for android_dev.enabled_functions */ ++ struct list_head enabled_list; ++ ++ /* Optional: initialization during gadget bind */ ++ int (*init)(struct android_usb_function *, struct usb_composite_dev *); ++ /* Optional: cleanup during gadget unbind */ ++ void (*cleanup)(struct android_usb_function *); ++ /* Optional: called when the function is added the list of ++ * enabled functions */ ++ void (*enable)(struct android_usb_function *); ++ /* Optional: called when it is removed */ ++ void (*disable)(struct android_usb_function *); ++ ++ int (*bind_config)(struct android_usb_function *, ++ struct usb_configuration *); ++ ++ /* Optional: called when the configuration is removed */ ++ void (*unbind_config)(struct android_usb_function *, ++ struct usb_configuration *); ++ /* Optional: handle ctrl requests before the device is configured */ ++ int (*ctrlrequest)(struct android_usb_function *, ++ struct usb_composite_dev *, ++ const struct usb_ctrlrequest *); ++}; ++ ++struct android_dev { ++ struct android_usb_function **functions; ++ struct list_head enabled_functions; ++ struct usb_composite_dev *cdev; ++ struct device *dev; ++ ++ void (*setup_complete)(struct usb_ep *ep, ++ struct usb_request *req); ++ ++ bool enabled; ++ int disable_depth; ++ struct mutex mutex; ++ bool connected; ++ bool sw_connected; ++ struct work_struct work; ++ char ffs_aliases[256]; ++}; ++ ++static struct class *android_class; ++static struct android_dev *_android_dev; ++static int android_bind_config(struct usb_configuration *c); ++static void android_unbind_config(struct usb_configuration *c); ++ ++/* string IDs are assigned dynamically */ ++#define STRING_MANUFACTURER_IDX 0 ++#define STRING_PRODUCT_IDX 1 ++#define STRING_SERIAL_IDX 2 ++ ++static char manufacturer_string[256]; ++static char product_string[256]; ++static char serial_string[256]; ++ ++/*---Copied from configfs.c to let this composite driver build---*/ ++static struct class *android_class; ++static struct device *android_device; ++static int index; ++ ++struct device *create_function_device(char *name) ++{ ++ if (android_device && !IS_ERR(android_device)) ++ return device_create(android_class, android_device, ++ MKDEV(0, index++), NULL, name); ++ else ++ return ERR_PTR(-EINVAL); ++} ++EXPORT_SYMBOL_GPL(create_function_device); ++/*---------------------------------------------------------------*/ ++ ++/* String Table */ ++static struct usb_string strings_dev[] = { ++ [STRING_MANUFACTURER_IDX].s = manufacturer_string, ++ [STRING_PRODUCT_IDX].s = product_string, ++ [STRING_SERIAL_IDX].s = serial_string, ++ { } /* end of list */ ++}; ++ ++static struct usb_gadget_strings stringtab_dev = { ++ .language = 0x0409, /* en-us */ ++ .strings = strings_dev, ++}; ++ ++static struct usb_gadget_strings *dev_strings[] = { ++ &stringtab_dev, ++ NULL, ++}; ++ ++static struct usb_device_descriptor device_desc = { ++ .bLength = sizeof(device_desc), ++ .bDescriptorType = USB_DT_DEVICE, ++ .bcdUSB = __constant_cpu_to_le16(0x0200), ++ .bDeviceClass = USB_CLASS_PER_INTERFACE, ++ .idVendor = __constant_cpu_to_le16(VENDOR_ID), ++ .idProduct = __constant_cpu_to_le16(PRODUCT_ID), ++ .bcdDevice = __constant_cpu_to_le16(0xffff), ++ .bNumConfigurations = 1, ++}; ++ ++static struct usb_configuration android_config_driver = { ++ .label = "android", ++ .unbind = android_unbind_config, ++ .bConfigurationValue = 1, ++ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, ++ .MaxPower = 500, /* 500ma */ ++}; ++ ++static void android_work(struct work_struct *data) ++{ ++ struct android_dev *dev = container_of(data, struct android_dev, work); ++ struct usb_composite_dev *cdev = dev->cdev; ++ char *disconnected[2] = { "USB_STATE=DISCONNECTED", NULL }; ++ char *connected[2] = { "USB_STATE=CONNECTED", NULL }; ++ char *configured[2] = { "USB_STATE=CONFIGURED", NULL }; ++ char **uevent_envp = NULL; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&cdev->lock, flags); ++ if (cdev->config) ++ uevent_envp = configured; ++ else if (dev->connected != dev->sw_connected) ++ uevent_envp = dev->connected ? connected : disconnected; ++ dev->sw_connected = dev->connected; ++ spin_unlock_irqrestore(&cdev->lock, flags); ++ ++ if (uevent_envp) { ++ kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE, uevent_envp); ++ pr_info("%s: sent uevent %s\n", __func__, uevent_envp[0]); ++ } else { ++ pr_info("%s: did not send uevent (%d %d %p)\n", __func__, ++ dev->connected, dev->sw_connected, cdev->config); ++ } ++} ++ ++static void android_enable(struct android_dev *dev) ++{ ++ struct usb_composite_dev *cdev = dev->cdev; ++ ++ if (WARN_ON(!dev->disable_depth)) ++ return; ++ ++ if (--dev->disable_depth == 0) { ++ usb_add_config(cdev, &android_config_driver, ++ android_bind_config); ++ usb_gadget_connect(cdev->gadget); ++ } ++} ++ ++static void android_disable(struct android_dev *dev) ++{ ++ struct usb_composite_dev *cdev = dev->cdev; ++ ++ if (dev->disable_depth++ == 0) { ++ usb_gadget_disconnect(cdev->gadget); ++ /* Cancel pending control requests */ ++ usb_ep_dequeue(cdev->gadget->ep0, cdev->req); ++ usb_remove_config(cdev, &android_config_driver); ++ } ++} ++ ++/*-------------------------------------------------------------------------*/ ++/* Supported functions initialization */ ++ ++struct functionfs_config { ++ bool opened; ++ bool enabled; ++ struct ffs_data *data; ++}; ++ ++static int ffs_function_init(struct android_usb_function *f, ++ struct usb_composite_dev *cdev) ++{ ++ f->config = kzalloc(sizeof(struct functionfs_config), GFP_KERNEL); ++ if (!f->config) ++ return -ENOMEM; ++ ++ return functionfs_init(); ++} ++ ++static void ffs_function_cleanup(struct android_usb_function *f) ++{ ++ functionfs_cleanup(); ++ kfree(f->config); ++} ++ ++static void ffs_function_enable(struct android_usb_function *f) ++{ ++ struct android_dev *dev = _android_dev; ++ struct functionfs_config *config = f->config; ++ ++ config->enabled = true; ++ ++ /* Disable the gadget until the function is ready */ ++ if (!config->opened) ++ android_disable(dev); ++} ++ ++static void ffs_function_disable(struct android_usb_function *f) ++{ ++ struct android_dev *dev = _android_dev; ++ struct functionfs_config *config = f->config; ++ ++ config->enabled = false; ++ ++ /* Balance the disable that was called in closed_callback */ ++ if (!config->opened) ++ android_enable(dev); ++} ++ ++static int ffs_function_bind_config(struct android_usb_function *f, ++ struct usb_configuration *c) ++{ ++ struct functionfs_config *config = f->config; ++ return functionfs_bind_config(c->cdev, c, config->data); ++} ++ ++static ssize_t ++ffs_aliases_show(struct device *pdev, struct device_attribute *attr, char *buf) ++{ ++ struct android_dev *dev = _android_dev; ++ int ret; ++ ++ mutex_lock(&dev->mutex); ++ ret = sprintf(buf, "%s\n", dev->ffs_aliases); ++ mutex_unlock(&dev->mutex); ++ ++ return ret; ++} ++ ++static ssize_t ++ffs_aliases_store(struct device *pdev, struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct android_dev *dev = _android_dev; ++ char buff[256]; ++ ++ mutex_lock(&dev->mutex); ++ ++ if (dev->enabled) { ++ mutex_unlock(&dev->mutex); ++ return -EBUSY; ++ } ++ ++ strlcpy(buff, buf, sizeof(buff)); ++ strlcpy(dev->ffs_aliases, strim(buff), sizeof(dev->ffs_aliases)); ++ ++ mutex_unlock(&dev->mutex); ++ ++ return size; ++} ++ ++static DEVICE_ATTR(aliases, S_IRUGO | S_IWUSR, ffs_aliases_show, ++ ffs_aliases_store); ++static struct device_attribute *ffs_function_attributes[] = { ++ &dev_attr_aliases, ++ NULL ++}; ++ ++static struct android_usb_function ffs_function = { ++ .name = "ffs", ++ .init = ffs_function_init, ++ .enable = ffs_function_enable, ++ .disable = ffs_function_disable, ++ .cleanup = ffs_function_cleanup, ++ .bind_config = ffs_function_bind_config, ++ .attributes = ffs_function_attributes, ++}; ++ ++static int functionfs_ready_callback(struct ffs_data *ffs) ++{ ++ struct android_dev *dev = _android_dev; ++ struct functionfs_config *config = ffs_function.config; ++ int ret = 0; ++ ++ mutex_lock(&dev->mutex); ++ ++ ret = functionfs_bind(ffs, dev->cdev); ++ if (ret) ++ goto err; ++ ++ config->data = ffs; ++ config->opened = true; ++ ++ if (config->enabled) ++ android_enable(dev); ++ ++err: ++ mutex_unlock(&dev->mutex); ++ return ret; ++} ++ ++static void functionfs_closed_callback(struct ffs_data *ffs) ++{ ++ struct android_dev *dev = _android_dev; ++ struct functionfs_config *config = ffs_function.config; ++ ++ mutex_lock(&dev->mutex); ++ ++ if (config->enabled) ++ android_disable(dev); ++ ++ config->opened = false; ++ config->data = NULL; ++ ++ functionfs_unbind(ffs); ++ ++ mutex_unlock(&dev->mutex); ++} ++ ++static void *functionfs_acquire_dev_callback(const char *dev_name) ++{ ++ return 0; ++} ++ ++static void functionfs_release_dev_callback(struct ffs_data *ffs_data) ++{ ++} ++ ++#define MAX_ACM_INSTANCES 4 ++struct acm_function_config { ++ int instances; ++ int instances_on; ++ struct usb_function *f_acm[MAX_ACM_INSTANCES]; ++ struct usb_function_instance *f_acm_inst[MAX_ACM_INSTANCES]; ++}; ++ ++static int ++acm_function_init(struct android_usb_function *f, ++ struct usb_composite_dev *cdev) ++{ ++ int i; ++ int ret; ++ struct acm_function_config *config; ++ ++ config = kzalloc(sizeof(struct acm_function_config), GFP_KERNEL); ++ if (!config) ++ return -ENOMEM; ++ f->config = config; ++ ++ for (i = 0; i < MAX_ACM_INSTANCES; i++) { ++ config->f_acm_inst[i] = usb_get_function_instance("acm"); ++ if (IS_ERR(config->f_acm_inst[i])) { ++ ret = PTR_ERR(config->f_acm_inst[i]); ++ goto err_usb_get_function_instance; ++ } ++ config->f_acm[i] = usb_get_function(config->f_acm_inst[i]); ++ if (IS_ERR(config->f_acm[i])) { ++ ret = PTR_ERR(config->f_acm[i]); ++ goto err_usb_get_function; ++ } ++ } ++ return 0; ++err_usb_get_function_instance: ++ while (i-- > 0) { ++ usb_put_function(config->f_acm[i]); ++err_usb_get_function: ++ usb_put_function_instance(config->f_acm_inst[i]); ++ } ++ return ret; ++} ++ ++static void acm_function_cleanup(struct android_usb_function *f) ++{ ++ int i; ++ struct acm_function_config *config = f->config; ++ ++ for (i = 0; i < MAX_ACM_INSTANCES; i++) { ++ usb_put_function(config->f_acm[i]); ++ usb_put_function_instance(config->f_acm_inst[i]); ++ } ++ kfree(f->config); ++ f->config = NULL; ++} ++ ++static int ++acm_function_bind_config(struct android_usb_function *f, ++ struct usb_configuration *c) ++{ ++ int i; ++ int ret = 0; ++ struct acm_function_config *config = f->config; ++ ++ config->instances_on = config->instances; ++ for (i = 0; i < config->instances_on; i++) { ++ ret = usb_add_function(c, config->f_acm[i]); ++ if (ret) { ++ pr_err("Could not bind acm%u config\n", i); ++ goto err_usb_add_function; ++ } ++ } ++ ++ return 0; ++ ++err_usb_add_function: ++ while (i-- > 0) ++ usb_remove_function(c, config->f_acm[i]); ++ return ret; ++} ++ ++static void acm_function_unbind_config(struct android_usb_function *f, ++ struct usb_configuration *c) ++{ ++ int i; ++ struct acm_function_config *config = f->config; ++ ++ for (i = 0; i < config->instances_on; i++) ++ usb_remove_function(c, config->f_acm[i]); ++} ++ ++static ssize_t acm_instances_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct android_usb_function *f = dev_get_drvdata(dev); ++ struct acm_function_config *config = f->config; ++ return sprintf(buf, "%d\n", config->instances); ++} ++ ++static ssize_t acm_instances_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct android_usb_function *f = dev_get_drvdata(dev); ++ struct acm_function_config *config = f->config; ++ int value; ++ ++ sscanf(buf, "%d", &value); ++ if (value > MAX_ACM_INSTANCES) ++ value = MAX_ACM_INSTANCES; ++ config->instances = value; ++ return size; ++} ++ ++static DEVICE_ATTR(instances, S_IRUGO | S_IWUSR, acm_instances_show, ++ acm_instances_store); ++static struct device_attribute *acm_function_attributes[] = { ++ &dev_attr_instances, ++ NULL ++}; ++ ++static struct android_usb_function acm_function = { ++ .name = "acm", ++ .init = acm_function_init, ++ .cleanup = acm_function_cleanup, ++ .bind_config = acm_function_bind_config, ++ .unbind_config = acm_function_unbind_config, ++ .attributes = acm_function_attributes, ++}; ++ ++ ++static int ++mtp_function_init(struct android_usb_function *f, ++ struct usb_composite_dev *cdev) ++{ ++ return mtp_setup(); ++} ++ ++static void mtp_function_cleanup(struct android_usb_function *f) ++{ ++ mtp_cleanup(); ++} ++ ++static int ++mtp_function_bind_config(struct android_usb_function *f, ++ struct usb_configuration *c) ++{ ++ return mtp_bind_config(c, false); ++} ++ ++static int ++ptp_function_init(struct android_usb_function *f, ++ struct usb_composite_dev *cdev) ++{ ++ /* nothing to do - initialization is handled by mtp_function_init */ ++ return 0; ++} ++ ++static void ptp_function_cleanup(struct android_usb_function *f) ++{ ++ /* nothing to do - cleanup is handled by mtp_function_cleanup */ ++} ++ ++static int ++ptp_function_bind_config(struct android_usb_function *f, ++ struct usb_configuration *c) ++{ ++ return mtp_bind_config(c, true); ++} ++ ++static int mtp_function_ctrlrequest(struct android_usb_function *f, ++ struct usb_composite_dev *cdev, ++ const struct usb_ctrlrequest *c) ++{ ++ return mtp_ctrlrequest(cdev, c); ++} ++ ++static struct android_usb_function mtp_function = { ++ .name = "mtp", ++ .init = mtp_function_init, ++ .cleanup = mtp_function_cleanup, ++ .bind_config = mtp_function_bind_config, ++ .ctrlrequest = mtp_function_ctrlrequest, ++}; ++ ++/* PTP function is same as MTP with slightly different interface descriptor */ ++static struct android_usb_function ptp_function = { ++ .name = "ptp", ++ .init = ptp_function_init, ++ .cleanup = ptp_function_cleanup, ++ .bind_config = ptp_function_bind_config, ++}; ++ ++ ++struct rndis_function_config { ++ u8 ethaddr[ETH_ALEN]; ++ u32 vendorID; ++ char manufacturer[256]; ++ /* "Wireless" RNDIS; auto-detected by Windows */ ++ bool wceis; ++ struct eth_dev *dev; ++}; ++ ++static int ++rndis_function_init(struct android_usb_function *f, ++ struct usb_composite_dev *cdev) ++{ ++ f->config = kzalloc(sizeof(struct rndis_function_config), GFP_KERNEL); ++ if (!f->config) ++ return -ENOMEM; ++ return 0; ++} ++ ++static void rndis_function_cleanup(struct android_usb_function *f) ++{ ++ kfree(f->config); ++ f->config = NULL; ++} ++ ++static int ++rndis_function_bind_config(struct android_usb_function *f, ++ struct usb_configuration *c) ++{ ++ int ret; ++ struct eth_dev *dev; ++ struct rndis_function_config *rndis = f->config; ++ ++ if (!rndis) { ++ pr_err("%s: rndis_pdata\n", __func__); ++ return -1; ++ } ++ ++ pr_info("%s MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", __func__, ++ rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2], ++ rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]); ++ ++ dev = gether_setup_name(c->cdev->gadget,dev_addr, host_addr, rndis->ethaddr, qmult, "rndis"); ++ if (IS_ERR(dev)) { ++ ret = PTR_ERR(dev); ++ pr_err("%s: gether_setup failed\n", __func__); ++ return ret; ++ } ++ rndis->dev = dev; ++ ++ if (rndis->wceis) { ++ /* "Wireless" RNDIS; auto-detected by Windows */ ++ rndis_iad_descriptor.bFunctionClass = ++ USB_CLASS_WIRELESS_CONTROLLER; ++ rndis_iad_descriptor.bFunctionSubClass = 0x01; ++ rndis_iad_descriptor.bFunctionProtocol = 0x03; ++ rndis_control_intf.bInterfaceClass = ++ USB_CLASS_WIRELESS_CONTROLLER; ++ rndis_control_intf.bInterfaceSubClass = 0x01; ++ rndis_control_intf.bInterfaceProtocol = 0x03; ++ } ++ ++ return rndis_bind_config_vendor(c, rndis->ethaddr, rndis->vendorID, ++ rndis->manufacturer, rndis->dev); ++} ++ ++static void rndis_function_unbind_config(struct android_usb_function *f, ++ struct usb_configuration *c) ++{ ++ struct rndis_function_config *rndis = f->config; ++ gether_cleanup(rndis->dev); ++} ++ ++static ssize_t rndis_manufacturer_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct android_usb_function *f = dev_get_drvdata(dev); ++ struct rndis_function_config *config = f->config; ++ return sprintf(buf, "%s\n", config->manufacturer); ++} ++ ++static ssize_t rndis_manufacturer_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct android_usb_function *f = dev_get_drvdata(dev); ++ struct rndis_function_config *config = f->config; ++ ++ if (size >= sizeof(config->manufacturer)) ++ return -EINVAL; ++ if (sscanf(buf, "%s", config->manufacturer) == 1) ++ return size; ++ return -1; ++} ++ ++static DEVICE_ATTR(manufacturer, S_IRUGO | S_IWUSR, rndis_manufacturer_show, ++ rndis_manufacturer_store); ++ ++static ssize_t rndis_wceis_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct android_usb_function *f = dev_get_drvdata(dev); ++ struct rndis_function_config *config = f->config; ++ return sprintf(buf, "%d\n", config->wceis); ++} ++ ++static ssize_t rndis_wceis_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct android_usb_function *f = dev_get_drvdata(dev); ++ struct rndis_function_config *config = f->config; ++ int value; ++ ++ if (sscanf(buf, "%d", &value) == 1) { ++ config->wceis = value; ++ return size; ++ } ++ return -EINVAL; ++} ++ ++static DEVICE_ATTR(wceis, S_IRUGO | S_IWUSR, rndis_wceis_show, ++ rndis_wceis_store); ++ ++static ssize_t rndis_ethaddr_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct android_usb_function *f = dev_get_drvdata(dev); ++ struct rndis_function_config *rndis = f->config; ++ return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2], ++ rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]); ++} ++ ++static ssize_t rndis_ethaddr_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct android_usb_function *f = dev_get_drvdata(dev); ++ struct rndis_function_config *rndis = f->config; ++ ++ if (sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ (int *)&rndis->ethaddr[0], (int *)&rndis->ethaddr[1], ++ (int *)&rndis->ethaddr[2], (int *)&rndis->ethaddr[3], ++ (int *)&rndis->ethaddr[4], (int *)&rndis->ethaddr[5]) == 6) ++ return size; ++ return -EINVAL; ++} ++ ++static DEVICE_ATTR(ethaddr, S_IRUGO | S_IWUSR, rndis_ethaddr_show, ++ rndis_ethaddr_store); ++ ++static ssize_t rndis_vendorID_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct android_usb_function *f = dev_get_drvdata(dev); ++ struct rndis_function_config *config = f->config; ++ return sprintf(buf, "%04x\n", config->vendorID); ++} ++ ++static ssize_t rndis_vendorID_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct android_usb_function *f = dev_get_drvdata(dev); ++ struct rndis_function_config *config = f->config; ++ int value; ++ ++ if (sscanf(buf, "%04x", &value) == 1) { ++ config->vendorID = value; ++ return size; ++ } ++ return -EINVAL; ++} ++ ++static DEVICE_ATTR(vendorID, S_IRUGO | S_IWUSR, rndis_vendorID_show, ++ rndis_vendorID_store); ++ ++static struct device_attribute *rndis_function_attributes[] = { ++ &dev_attr_manufacturer, ++ &dev_attr_wceis, ++ &dev_attr_ethaddr, ++ &dev_attr_vendorID, ++ NULL ++}; ++ ++static struct android_usb_function rndis_function = { ++ .name = "rndis", ++ .init = rndis_function_init, ++ .cleanup = rndis_function_cleanup, ++ .bind_config = rndis_function_bind_config, ++ .unbind_config = rndis_function_unbind_config, ++ .attributes = rndis_function_attributes, ++}; ++ ++ ++#define MAX_MS_INSTANCES 1 ++struct mass_storage_function_config { ++ int instances; ++ int instances_on; ++ struct usb_function *f_ms[MAX_MS_INSTANCES]; ++ struct usb_function_instance *f_ms_inst[MAX_MS_INSTANCES]; ++}; ++ ++static int mass_storage_function_init(struct android_usb_function *f, ++ struct usb_composite_dev *cdev) ++{ ++ struct mass_storage_function_config *config; ++ int i; ++ int ret; ++ ++ config = kzalloc(sizeof(struct mass_storage_function_config), ++ GFP_KERNEL); ++ if (!config) ++ return -ENOMEM; ++ f->config = config; ++ ++ for (i = 0; i < MAX_MS_INSTANCES; i++) { ++ config->f_ms_inst[i] = usb_get_function_instance("mass_storage"); ++ if (IS_ERR(config->f_ms_inst[i])) { ++ ret = PTR_ERR(config->f_ms_inst[i]); ++ goto err_usb_get_function_instance; ++ } ++ config->f_ms[i] = usb_get_function(config->f_ms_inst[i]); ++ if (IS_ERR(config->f_ms[i])) { ++ ret = PTR_ERR(config->f_ms[i]); ++ goto err_usb_get_function; ++ } ++ } ++ ++ return 0; ++err_usb_get_function_instance: ++ while (i-- > 0) { ++ usb_put_function(config->f_ms[i]); ++err_usb_get_function: ++ usb_put_function_instance(config->f_ms_inst[i]); ++ } ++ return ret; ++} ++ ++static void mass_storage_function_cleanup(struct android_usb_function *f) ++{ ++ struct mass_storage_function_config *config = f->config; ++ int i; ++ ++ for (i = 0; i < MAX_MS_INSTANCES; i++) { ++ usb_put_function(config->f_ms[i]); ++ usb_put_function_instance(config->f_ms_inst[i]); ++ } ++ kfree(f->config); ++ f->config = NULL; ++} ++ ++static int mass_storage_function_bind_config(struct android_usb_function *f, ++ struct usb_configuration *c) ++{ ++ struct mass_storage_function_config *config = f->config; ++ int ret = 0; ++ int i; ++ ++ config->instances_on = config->instances; ++ for (i = 0; i < config->instances_on; i++) { ++ ret = usb_add_function(c, config->f_ms[i]); ++ if (ret) { ++ pr_err("Could not bind ms%u config\n", i); ++ goto err_usb_add_function; ++ } ++ } ++ ++ return 0; ++ ++err_usb_add_function: ++ while (i-- > 0) ++ usb_remove_function(c, config->f_ms[i]); ++ return ret; ++} ++ ++static void mass_storage_function_unbind_config(struct android_usb_function *f, ++ struct usb_configuration *c) ++{ ++ int i; ++ struct mass_storage_function_config *config = f->config; ++ ++ for (i = 0; i < config->instances_on; i++) ++ usb_remove_function(c, config->f_ms[i]); ++} ++ ++static ssize_t mass_storage_inquiry_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct android_usb_function *f = dev_get_drvdata(dev); ++ struct mass_storage_function_config *config = f->config; ++ return sprintf(buf, "%d\n", config->instances); ++} ++ ++static ssize_t mass_storage_inquiry_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct android_usb_function *f = dev_get_drvdata(dev); ++ struct mass_storage_function_config *config = f->config; ++ int value; ++ ++ sscanf(buf, "%d", &value); ++ if (value > MAX_MS_INSTANCES) ++ value = MAX_MS_INSTANCES; ++ config->instances = value; ++ return size; ++} ++ ++static DEVICE_ATTR(inquiry_string, S_IRUGO | S_IWUSR, ++ mass_storage_inquiry_show, ++ mass_storage_inquiry_store); ++ ++static struct device_attribute *mass_storage_function_attributes[] = { ++ &dev_attr_inquiry_string, ++ NULL ++}; ++ ++static struct android_usb_function mass_storage_function = { ++ .name = "mass_storage", ++ .init = mass_storage_function_init, ++ .cleanup = mass_storage_function_cleanup, ++ .bind_config = mass_storage_function_bind_config, ++ .attributes = mass_storage_function_attributes, ++}; ++ ++ ++static int accessory_function_init(struct android_usb_function *f, ++ struct usb_composite_dev *cdev) ++{ ++ return acc_setup(); ++} ++ ++static void accessory_function_cleanup(struct android_usb_function *f) ++{ ++ acc_cleanup(); ++} ++ ++static int accessory_function_bind_config(struct android_usb_function *f, ++ struct usb_configuration *c) ++{ ++ return acc_bind_config(c); ++} ++ ++static int accessory_function_ctrlrequest(struct android_usb_function *f, ++ struct usb_composite_dev *cdev, ++ const struct usb_ctrlrequest *c) ++{ ++ return acc_ctrlrequest(cdev, c); ++} ++ ++static struct android_usb_function accessory_function = { ++ .name = "accessory", ++ .init = accessory_function_init, ++ .cleanup = accessory_function_cleanup, ++ .bind_config = accessory_function_bind_config, ++ .ctrlrequest = accessory_function_ctrlrequest, ++}; ++ ++static int audio_source_function_init(struct android_usb_function *f, ++ struct usb_composite_dev *cdev) ++{ ++ struct audio_source_config *config; ++ ++ config = kzalloc(sizeof(struct audio_source_config), GFP_KERNEL); ++ if (!config) ++ return -ENOMEM; ++ config->card = -1; ++ config->device = -1; ++ f->config = config; ++ return 0; ++} ++ ++static void audio_source_function_cleanup(struct android_usb_function *f) ++{ ++ kfree(f->config); ++} ++ ++static int audio_source_function_bind_config(struct android_usb_function *f, ++ struct usb_configuration *c) ++{ ++ struct audio_source_config *config = f->config; ++ ++ return audio_source_bind_config(c, config); ++} ++ ++static void audio_source_function_unbind_config(struct android_usb_function *f, ++ struct usb_configuration *c) ++{ ++ struct audio_source_config *config = f->config; ++ ++ config->card = -1; ++ config->device = -1; ++} ++ ++static struct android_usb_function audio_source_function = { ++ .name = "audio_source", ++ .init = audio_source_function_init, ++ .cleanup = audio_source_function_cleanup, ++ .bind_config = audio_source_function_bind_config, ++ .unbind_config = audio_source_function_unbind_config, ++ .attributes = audio_source_function_attributes, ++}; ++ ++static struct android_usb_function *supported_functions[] = { ++ &ffs_function, ++ &acm_function, ++ &mtp_function, ++ &ptp_function, ++ &rndis_function, ++ &mass_storage_function, ++ &accessory_function, ++ &audio_source_function, ++ NULL ++}; ++ ++ ++static int android_init_functions(struct android_usb_function **functions, ++ struct usb_composite_dev *cdev) ++{ ++ struct android_dev *dev = _android_dev; ++ struct android_usb_function *f; ++ struct device_attribute **attrs; ++ struct device_attribute *attr; ++ int err; ++ int index = 0; ++ ++ for (; (f = *functions++); index++) { ++ f->dev_name = kasprintf(GFP_KERNEL, "f_%s", f->name); ++ f->dev = device_create(android_class, dev->dev, ++ MKDEV(0, index), f, f->dev_name); ++ if (IS_ERR(f->dev)) { ++ pr_err("%s: Failed to create dev %s", __func__, ++ f->dev_name); ++ err = PTR_ERR(f->dev); ++ goto err_create; ++ } ++ ++ if (f->init) { ++ err = f->init(f, cdev); ++ if (err) { ++ pr_err("%s: Failed to init %s", __func__, ++ f->name); ++ goto err_out; ++ } ++ } ++ ++ attrs = f->attributes; ++ if (attrs) { ++ while ((attr = *attrs++) && !err) ++ err = device_create_file(f->dev, attr); ++ } ++ if (err) { ++ pr_err("%s: Failed to create function %s attributes", ++ __func__, f->name); ++ goto err_out; ++ } ++ } ++ return 0; ++ ++err_out: ++ device_destroy(android_class, f->dev->devt); ++err_create: ++ kfree(f->dev_name); ++ return err; ++} ++ ++static void android_cleanup_functions(struct android_usb_function **functions) ++{ ++ struct android_usb_function *f; ++ ++ while (*functions) { ++ f = *functions++; ++ ++ if (f->dev) { ++ device_destroy(android_class, f->dev->devt); ++ kfree(f->dev_name); ++ } ++ ++ if (f->cleanup) ++ f->cleanup(f); ++ } ++} ++ ++static int ++android_bind_enabled_functions(struct android_dev *dev, ++ struct usb_configuration *c) ++{ ++ struct android_usb_function *f; ++ int ret; ++ ++ list_for_each_entry(f, &dev->enabled_functions, enabled_list) { ++ ret = f->bind_config(f, c); ++ if (ret) { ++ pr_err("%s: %s failed", __func__, f->name); ++ return ret; ++ } ++ } ++ return 0; ++} ++ ++static void ++android_unbind_enabled_functions(struct android_dev *dev, ++ struct usb_configuration *c) ++{ ++ struct android_usb_function *f; ++ ++ list_for_each_entry(f, &dev->enabled_functions, enabled_list) { ++ if (f->unbind_config) ++ f->unbind_config(f, c); ++ } ++} ++ ++static int android_enable_function(struct android_dev *dev, char *name) ++{ ++ struct android_usb_function **functions = dev->functions; ++ struct android_usb_function *f; ++ while ((f = *functions++)) { ++ if (!strcmp(name, f->name)) { ++ list_add_tail(&f->enabled_list, ++ &dev->enabled_functions); ++ return 0; ++ } ++ } ++ return -EINVAL; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/* /sys/class/android_usb/android%d/ interface */ ++ ++static ssize_t ++functions_show(struct device *pdev, struct device_attribute *attr, char *buf) ++{ ++ struct android_dev *dev = dev_get_drvdata(pdev); ++ struct android_usb_function *f; ++ char *buff = buf; ++ ++ mutex_lock(&dev->mutex); ++ ++ list_for_each_entry(f, &dev->enabled_functions, enabled_list) ++ buff += sprintf(buff, "%s,", f->name); ++ ++ mutex_unlock(&dev->mutex); ++ ++ if (buff != buf) ++ *(buff-1) = '\n'; ++ return buff - buf; ++} ++ ++static ssize_t ++functions_store(struct device *pdev, struct device_attribute *attr, ++ const char *buff, size_t size) ++{ ++ struct android_dev *dev = dev_get_drvdata(pdev); ++ char *name; ++ char buf[256], *b; ++ char aliases[256], *a; ++ int err; ++ int is_ffs; ++ int ffs_enabled = 0; ++ ++ mutex_lock(&dev->mutex); ++ ++ if (dev->enabled) { ++ mutex_unlock(&dev->mutex); ++ return -EBUSY; ++ } ++ ++ INIT_LIST_HEAD(&dev->enabled_functions); ++ ++ strlcpy(buf, buff, sizeof(buf)); ++ b = strim(buf); ++ ++ while (b) { ++ name = strsep(&b, ","); ++ if (!name) ++ continue; ++ ++ is_ffs = 0; ++ strlcpy(aliases, dev->ffs_aliases, sizeof(aliases)); ++ a = aliases; ++ ++ while (a) { ++ char *alias = strsep(&a, ","); ++ if (alias && !strcmp(name, alias)) { ++ is_ffs = 1; ++ break; ++ } ++ } ++ ++ if (is_ffs) { ++ if (ffs_enabled) ++ continue; ++ err = android_enable_function(dev, "ffs"); ++ if (err) ++ pr_err("android_usb: Cannot enable ffs (%d)", ++ err); ++ else ++ ffs_enabled = 1; ++ continue; ++ } ++ ++ err = android_enable_function(dev, name); ++ if (err) ++ pr_err("android_usb: Cannot enable '%s' (%d)", ++ name, err); ++ } ++ ++ mutex_unlock(&dev->mutex); ++ ++ return size; ++} ++ ++static ssize_t enable_show(struct device *pdev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct android_dev *dev = dev_get_drvdata(pdev); ++ return sprintf(buf, "%d\n", dev->enabled); ++} ++ ++static ssize_t enable_store(struct device *pdev, struct device_attribute *attr, ++ const char *buff, size_t size) ++{ ++ struct android_dev *dev = dev_get_drvdata(pdev); ++ struct usb_composite_dev *cdev = dev->cdev; ++ struct android_usb_function *f; ++ int enabled = 0; ++ ++ ++ if (!cdev) ++ return -ENODEV; ++ ++ mutex_lock(&dev->mutex); ++ ++ sscanf(buff, "%d", &enabled); ++ if (enabled && !dev->enabled) { ++ cdev->next_string_id = 0; ++ /* ++ * Update values in composite driver's copy of ++ * device descriptor. ++ */ ++ cdev->desc.idVendor = device_desc.idVendor; ++ cdev->desc.idProduct = device_desc.idProduct; ++ cdev->desc.bcdDevice = device_desc.bcdDevice; ++ cdev->desc.bDeviceClass = device_desc.bDeviceClass; ++ cdev->desc.bDeviceSubClass = device_desc.bDeviceSubClass; ++ cdev->desc.bDeviceProtocol = device_desc.bDeviceProtocol; ++ list_for_each_entry(f, &dev->enabled_functions, enabled_list) { ++ if (f->enable) ++ f->enable(f); ++ } ++ android_enable(dev); ++ dev->enabled = true; ++ } else if (!enabled && dev->enabled) { ++ android_disable(dev); ++ list_for_each_entry(f, &dev->enabled_functions, enabled_list) { ++ if (f->disable) ++ f->disable(f); ++ } ++ dev->enabled = false; ++ } else { ++ pr_err("android_usb: already %s\n", ++ dev->enabled ? "enabled" : "disabled"); ++ } ++ ++ mutex_unlock(&dev->mutex); ++ return size; ++} ++ ++static ssize_t state_show(struct device *pdev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct android_dev *dev = dev_get_drvdata(pdev); ++ struct usb_composite_dev *cdev = dev->cdev; ++ char *state = "DISCONNECTED"; ++ unsigned long flags; ++ ++ if (!cdev) ++ goto out; ++ ++ spin_lock_irqsave(&cdev->lock, flags); ++ if (cdev->config) ++ state = "CONFIGURED"; ++ else if (dev->connected) ++ state = "CONNECTED"; ++ spin_unlock_irqrestore(&cdev->lock, flags); ++out: ++ return sprintf(buf, "%s\n", state); ++} ++ ++#define DESCRIPTOR_ATTR(field, format_string) \ ++static ssize_t \ ++field ## _show(struct device *dev, struct device_attribute *attr, \ ++ char *buf) \ ++{ \ ++ return sprintf(buf, format_string, device_desc.field); \ ++} \ ++static ssize_t \ ++field ## _store(struct device *dev, struct device_attribute *attr, \ ++ const char *buf, size_t size) \ ++{ \ ++ int value; \ ++ if (sscanf(buf, format_string, &value) == 1) { \ ++ device_desc.field = value; \ ++ return size; \ ++ } \ ++ return -1; \ ++} \ ++static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, field ## _show, field ## _store); ++ ++#define DESCRIPTOR_STRING_ATTR(field, buffer) \ ++static ssize_t \ ++field ## _show(struct device *dev, struct device_attribute *attr, \ ++ char *buf) \ ++{ \ ++ return sprintf(buf, "%s", buffer); \ ++} \ ++static ssize_t \ ++field ## _store(struct device *dev, struct device_attribute *attr, \ ++ const char *buf, size_t size) \ ++{ \ ++ if (size >= sizeof(buffer)) \ ++ return -EINVAL; \ ++ return strlcpy(buffer, buf, sizeof(buffer)); \ ++} \ ++static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, field ## _show, field ## _store); ++ ++ ++DESCRIPTOR_ATTR(idVendor, "%04x\n") ++DESCRIPTOR_ATTR(idProduct, "%04x\n") ++DESCRIPTOR_ATTR(bcdDevice, "%04x\n") ++DESCRIPTOR_ATTR(bDeviceClass, "%d\n") ++DESCRIPTOR_ATTR(bDeviceSubClass, "%d\n") ++DESCRIPTOR_ATTR(bDeviceProtocol, "%d\n") ++DESCRIPTOR_STRING_ATTR(iManufacturer, manufacturer_string) ++DESCRIPTOR_STRING_ATTR(iProduct, product_string) ++DESCRIPTOR_STRING_ATTR(iSerial, serial_string) ++ ++static DEVICE_ATTR(functions, S_IRUGO | S_IWUSR, functions_show, ++ functions_store); ++static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store); ++static DEVICE_ATTR(state, S_IRUGO, state_show, NULL); ++ ++static struct device_attribute *android_usb_attributes[] = { ++ &dev_attr_idVendor, ++ &dev_attr_idProduct, ++ &dev_attr_bcdDevice, ++ &dev_attr_bDeviceClass, ++ &dev_attr_bDeviceSubClass, ++ &dev_attr_bDeviceProtocol, ++ &dev_attr_iManufacturer, ++ &dev_attr_iProduct, ++ &dev_attr_iSerial, ++ &dev_attr_functions, ++ &dev_attr_enable, ++ &dev_attr_state, ++ NULL ++}; ++ ++/*-------------------------------------------------------------------------*/ ++/* Composite driver */ ++ ++static int android_bind_config(struct usb_configuration *c) ++{ ++ struct android_dev *dev = _android_dev; ++ int ret = 0; ++ ++ ret = android_bind_enabled_functions(dev, c); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static void android_unbind_config(struct usb_configuration *c) ++{ ++ struct android_dev *dev = _android_dev; ++ ++ android_unbind_enabled_functions(dev, c); ++} ++ ++static int android_bind(struct usb_composite_dev *cdev) ++{ ++ struct android_dev *dev = _android_dev; ++ struct usb_gadget *gadget = cdev->gadget; ++ int id, ret; ++ ++ /* Save the default handler */ ++ dev->setup_complete = cdev->req->complete; ++ ++ /* ++ * Start disconnected. Userspace will connect the gadget once ++ * it is done configuring the functions. ++ */ ++ usb_gadget_disconnect(gadget); ++ ++ ret = android_init_functions(dev->functions, cdev); ++ if (ret) ++ return ret; ++ ++ /* Allocate string descriptor numbers ... note that string ++ * contents can be overridden by the composite_dev glue. ++ */ ++ id = usb_string_id(cdev); ++ if (id < 0) ++ return id; ++ strings_dev[STRING_MANUFACTURER_IDX].id = id; ++ device_desc.iManufacturer = id; ++ ++ id = usb_string_id(cdev); ++ if (id < 0) ++ return id; ++ strings_dev[STRING_PRODUCT_IDX].id = id; ++ device_desc.iProduct = id; ++ ++ /* Default strings - should be updated by userspace */ ++ strncpy(manufacturer_string, "Android", sizeof(manufacturer_string)-1); ++ strncpy(product_string, "Android", sizeof(product_string) - 1); ++ strncpy(serial_string, "0123456789ABCDEF", sizeof(serial_string) - 1); ++ ++ id = usb_string_id(cdev); ++ if (id < 0) ++ return id; ++ strings_dev[STRING_SERIAL_IDX].id = id; ++ device_desc.iSerialNumber = id; ++ ++ usb_gadget_set_selfpowered(gadget); ++ dev->cdev = cdev; ++ ++ return 0; ++} ++ ++static int android_usb_unbind(struct usb_composite_dev *cdev) ++{ ++ struct android_dev *dev = _android_dev; ++ ++ cancel_work_sync(&dev->work); ++ android_cleanup_functions(dev->functions); ++ return 0; ++} ++ ++/* HACK: android needs to override setup for accessory to work */ ++static int (*composite_setup_func)(struct usb_gadget *gadget, const struct usb_ctrlrequest *c); ++ ++static int ++android_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *c) ++{ ++ struct android_dev *dev = _android_dev; ++ struct usb_composite_dev *cdev = get_gadget_data(gadget); ++ struct usb_request *req = cdev->req; ++ struct android_usb_function *f; ++ int value = -EOPNOTSUPP; ++ unsigned long flags; ++ ++ req->zero = 0; ++ req->length = 0; ++ req->complete = dev->setup_complete; ++ gadget->ep0->driver_data = cdev; ++ ++ list_for_each_entry(f, &dev->enabled_functions, enabled_list) { ++ if (f->ctrlrequest) { ++ value = f->ctrlrequest(f, cdev, c); ++ if (value >= 0) ++ break; ++ } ++ } ++ ++ /* Special case the accessory function. ++ * It needs to handle control requests before it is enabled. ++ */ ++ if (value < 0) ++ value = acc_ctrlrequest(cdev, c); ++ ++ if (value < 0) ++ value = composite_setup_func(gadget, c); ++ ++ spin_lock_irqsave(&cdev->lock, flags); ++ if (!dev->connected) { ++ dev->connected = 1; ++ schedule_work(&dev->work); ++ } else if (c->bRequest == USB_REQ_SET_CONFIGURATION && ++ cdev->config) { ++ schedule_work(&dev->work); ++ } ++ spin_unlock_irqrestore(&cdev->lock, flags); ++ ++ return value; ++} ++ ++static void android_disconnect(struct usb_composite_dev *cdev) ++{ ++ struct android_dev *dev = _android_dev; ++ ++ /* accessory HID support can be active while the ++ accessory function is not actually enabled, ++ so we need to inform it when we are disconnected. ++ */ ++ acc_disconnect(); ++ ++ dev->connected = 0; ++ schedule_work(&dev->work); ++} ++ ++static struct usb_composite_driver android_usb_driver = { ++ .name = "android_usb", ++ .dev = &device_desc, ++ .strings = dev_strings, ++ .bind = android_bind, ++ .unbind = android_usb_unbind, ++ .disconnect = android_disconnect, ++ .max_speed = USB_SPEED_HIGH, ++}; ++ ++static int android_create_device(struct android_dev *dev) ++{ ++ struct device_attribute **attrs = android_usb_attributes; ++ struct device_attribute *attr; ++ int err; ++ ++ dev->dev = device_create(android_class, NULL, ++ MKDEV(0, 0), NULL, "android0"); ++ if (IS_ERR(dev->dev)) ++ return PTR_ERR(dev->dev); ++ ++ dev_set_drvdata(dev->dev, dev); ++ ++ while ((attr = *attrs++)) { ++ err = device_create_file(dev->dev, attr); ++ if (err) { ++ device_destroy(android_class, dev->dev->devt); ++ return err; ++ } ++ } ++ return 0; ++} ++ ++ ++static int __init init(void) ++{ ++ struct android_dev *dev; ++ int err; ++ ++ android_class = class_create(THIS_MODULE, "android_usb"); ++ if (IS_ERR(android_class)) ++ return PTR_ERR(android_class); ++ ++ dev = kzalloc(sizeof(*dev), GFP_KERNEL); ++ if (!dev) { ++ err = -ENOMEM; ++ goto err_dev; ++ } ++ ++ dev->disable_depth = 1; ++ dev->functions = supported_functions; ++ INIT_LIST_HEAD(&dev->enabled_functions); ++ INIT_WORK(&dev->work, android_work); ++ mutex_init(&dev->mutex); ++ ++ err = android_create_device(dev); ++ if (err) { ++ pr_err("%s: failed to create android device %d", __func__, err); ++ goto err_create; ++ } ++ ++ _android_dev = dev; ++ ++ err = usb_composite_probe(&android_usb_driver); ++ if (err) { ++ pr_err("%s: failed to probe driver %d", __func__, err); ++ goto err_probe; ++ } ++ ++ /* HACK: exchange composite's setup with ours */ ++ composite_setup_func = android_usb_driver.gadget_driver.setup; ++ android_usb_driver.gadget_driver.setup = android_setup; ++ ++ return 0; ++ ++err_probe: ++ device_destroy(android_class, dev->dev->devt); ++err_create: ++ kfree(dev); ++err_dev: ++ class_destroy(android_class); ++ return err; ++} ++late_initcall(init); ++ ++static void __exit cleanup(void) ++{ ++ usb_composite_unregister(&android_usb_driver); ++ class_destroy(android_class); ++ kfree(_android_dev); ++ _android_dev = NULL; ++} ++module_exit(cleanup); +diff --git a/drivers/usb/gadget/legacy/audio.c b/drivers/usb/gadget/legacy/audio.c +index f46a395..1db5181 100644 +--- a/drivers/usb/gadget/legacy/audio.c ++++ b/drivers/usb/gadget/legacy/audio.c +@@ -15,7 +15,6 @@ + #include + #include + +-#include "gadget_chips.h" + #define DRIVER_DESC "Linux USB Audio Gadget" + #define DRIVER_VERSION "Feb 2, 2012" + +@@ -54,8 +53,51 @@ static int c_ssize = UAC2_DEF_CSSIZE; + module_param(c_ssize, uint, S_IRUGO); + MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)"); + #else ++#ifndef CONFIG_GADGET_UAC1_LEGACY + #include "u_uac1.h" + ++/* Playback(USB-IN) Default Stereo - Fl/Fr */ ++static int p_chmask = UAC1_DEF_PCHMASK; ++module_param(p_chmask, uint, S_IRUGO); ++MODULE_PARM_DESC(p_chmask, "Playback Channel Mask"); ++ ++/* Playback Default 48 KHz */ ++static int p_srate = UAC1_DEF_PSRATE; ++module_param(p_srate, uint, S_IRUGO); ++MODULE_PARM_DESC(p_srate, "Playback Sampling Rate"); ++ ++/* Playback Default 16bits/sample */ ++static int p_ssize = UAC1_DEF_PSSIZE; ++module_param(p_ssize, uint, S_IRUGO); ++MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)"); ++ ++/* Capture(USB-OUT) Default Stereo - Fl/Fr */ ++static int c_chmask = UAC1_DEF_CCHMASK; ++module_param(c_chmask, uint, S_IRUGO); ++MODULE_PARM_DESC(c_chmask, "Capture Channel Mask"); ++ ++/* Capture Default 48 KHz */ ++static int c_srate = UAC1_DEF_CSRATE; ++module_param(c_srate, uint, S_IRUGO); ++MODULE_PARM_DESC(c_srate, "Capture Sampling Rate"); ++ ++/* Capture Default 16bits/sample */ ++static int c_ssize = UAC1_DEF_CSSIZE; ++module_param(c_ssize, uint, S_IRUGO); ++MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)"); ++ ++/* req number */ ++static int req_num = UAC1_DEF_REQ_NUM; ++module_param(req_num, uint, S_IRUGO); ++MODULE_PARM_DESC(req_num, "req number"); ++ ++static int req_buf_size = UAC1_OUT_EP_MAX_PACKET_SIZE; ++module_param(req_buf_size, int, S_IRUGO); ++MODULE_PARM_DESC(req_buf_size, "ISO OUT endpoint request buffer size"); ++ ++#else /* CONFIG_GADGET_UAC1_LEGACY */ ++#include "u_uac1_legacy.h" ++ + static char *fn_play = FILE_PCM_PLAYBACK; + module_param(fn_play, charp, S_IRUGO); + MODULE_PARM_DESC(fn_play, "Playback PCM device file name"); +@@ -79,6 +121,7 @@ MODULE_PARM_DESC(req_count, "ISO OUT endpoint request count"); + static int audio_buf_size = UAC1_AUDIO_BUF_SIZE; + module_param(audio_buf_size, int, S_IRUGO); + MODULE_PARM_DESC(audio_buf_size, "Audio buffer size"); ++#endif /* CONFIG_GADGET_UAC1_LEGACY */ + #endif + + /* string IDs are assigned dynamically */ +@@ -124,9 +167,9 @@ static struct usb_device_descriptor device_desc = { + .bLength = sizeof device_desc, + .bDescriptorType = USB_DT_DEVICE, + +- .bcdUSB = __constant_cpu_to_le16(0x200), ++ /* .bcdUSB = DYNAMIC */ + +-#ifdef CONFIG_GADGET_UAC1 ++#ifdef CONFIG_GADGET_UAC1_LEGACY + .bDeviceClass = USB_CLASS_PER_INTERFACE, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, +@@ -141,8 +184,8 @@ static struct usb_device_descriptor device_desc = { + * we support. (As does bNumConfigurations.) These values can + * also be overridden by module parameters. + */ +- .idVendor = __constant_cpu_to_le16(AUDIO_VENDOR_NUM), +- .idProduct = __constant_cpu_to_le16(AUDIO_PRODUCT_NUM), ++ .idVendor = cpu_to_le16(AUDIO_VENDOR_NUM), ++ .idProduct = cpu_to_le16(AUDIO_PRODUCT_NUM), + /* .bcdDevice = f(hardware) */ + /* .iManufacturer = DYNAMIC */ + /* .iProduct = DYNAMIC */ +@@ -150,24 +193,11 @@ static struct usb_device_descriptor device_desc = { + .bNumConfigurations = 1, + }; + +-static struct usb_otg_descriptor otg_descriptor = { +- .bLength = sizeof otg_descriptor, +- .bDescriptorType = USB_DT_OTG, +- +- /* REVISIT SRP-only hardware is possible, although +- * it would not be called "OTG" ... +- */ +- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, +-}; +- +-static const struct usb_descriptor_header *otg_desc[] = { +- (struct usb_descriptor_header *) &otg_descriptor, +- NULL, +-}; ++static const struct usb_descriptor_header *otg_desc[2]; + + /*-------------------------------------------------------------------------*/ + +-static int __init audio_do_config(struct usb_configuration *c) ++static int audio_do_config(struct usb_configuration *c) + { + int status; + +@@ -216,12 +246,16 @@ static struct usb_configuration audio_config_driver = { + + /*-------------------------------------------------------------------------*/ + +-static int __init audio_bind(struct usb_composite_dev *cdev) ++static int audio_bind(struct usb_composite_dev *cdev) + { + #ifndef CONFIG_GADGET_UAC1 + struct f_uac2_opts *uac2_opts; + #else ++#ifndef CONFIG_GADGET_UAC1_LEGACY + struct f_uac1_opts *uac1_opts; ++#else ++ struct f_uac1_legacy_opts *uac1_opts; ++#endif + #endif + int status; + +@@ -230,7 +264,11 @@ static int __init audio_bind(struct usb_composite_dev *cdev) + if (IS_ERR(fi_uac2)) + return PTR_ERR(fi_uac2); + #else ++#ifndef CONFIG_GADGET_UAC1_LEGACY + fi_uac1 = usb_get_function_instance("uac1"); ++#else ++ fi_uac1 = usb_get_function_instance("uac1_legacy"); ++#endif + if (IS_ERR(fi_uac1)) + return PTR_ERR(fi_uac1); + #endif +@@ -243,14 +281,29 @@ static int __init audio_bind(struct usb_composite_dev *cdev) + uac2_opts->c_chmask = c_chmask; + uac2_opts->c_srate = c_srate; + uac2_opts->c_ssize = c_ssize; ++ uac2_opts->req_number = UAC2_DEF_REQ_NUM; + #else ++#ifndef CONFIG_GADGET_UAC1_LEGACY + uac1_opts = container_of(fi_uac1, struct f_uac1_opts, func_inst); ++ uac1_opts->p_chmask = p_chmask; ++ uac1_opts->p_srate = p_srate; ++ uac1_opts->p_ssize = p_ssize; ++ uac1_opts->c_chmask = c_chmask; ++ uac1_opts->c_srate = c_srate; ++ uac1_opts->c_ssize = c_ssize; ++ uac1_opts->req_number = UAC1_DEF_REQ_NUM; ++ uac1_opts->req_number = req_num; ++ uac1_opts->req_buf_size = req_buf_size; ++ ++#else /* CONFIG_GADGET_UAC1_LEGACY */ ++ uac1_opts = container_of(fi_uac1, struct f_uac1_legacy_opts, func_inst); + uac1_opts->fn_play = fn_play; + uac1_opts->fn_cap = fn_cap; + uac1_opts->fn_cntl = fn_cntl; + uac1_opts->req_buf_size = req_buf_size; + uac1_opts->req_count = req_count; + uac1_opts->audio_buf_size = audio_buf_size; ++#endif /* CONFIG_GADGET_UAC1_LEGACY */ + #endif + + status = usb_string_ids_tab(cdev, strings_dev); +@@ -259,14 +312,32 @@ static int __init audio_bind(struct usb_composite_dev *cdev) + device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; + ++#if 0 ++ if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) { ++ struct usb_descriptor_header *usb_desc; ++ ++ usb_desc = usb_otg_descriptor_alloc(cdev->gadget); ++ if (!usb_desc) ++ goto fail; ++ usb_otg_descriptor_init(cdev->gadget, usb_desc); ++ otg_desc[0] = usb_desc; ++ otg_desc[1] = NULL; ++ } ++#endif ++ ++#if 1 + status = usb_add_config(cdev, &audio_config_driver, audio_do_config); + if (status < 0) +- goto fail; ++ goto fail_otg_desc; + usb_composite_overwrite_options(cdev, &coverwrite); ++#endif + + INFO(cdev, "%s, version: %s\n", DRIVER_DESC, DRIVER_VERSION); + return 0; + ++fail_otg_desc: ++ kfree(otg_desc[0]); ++ otg_desc[0] = NULL; + fail: + #ifndef CONFIG_GADGET_UAC1 + usb_put_function_instance(fi_uac2); +@@ -276,7 +347,7 @@ fail: + return status; + } + +-static int __exit audio_unbind(struct usb_composite_dev *cdev) ++static int audio_unbind(struct usb_composite_dev *cdev) + { + #ifdef CONFIG_GADGET_UAC1 + if (!IS_ERR_OR_NULL(f_uac1)) +@@ -289,16 +360,20 @@ static int __exit audio_unbind(struct usb_composite_dev *cdev) + if (!IS_ERR_OR_NULL(fi_uac2)) + usb_put_function_instance(fi_uac2); + #endif ++ kfree(otg_desc[0]); ++ otg_desc[0] = NULL; ++ + return 0; + } + +-static __refdata struct usb_composite_driver audio_driver = { ++#if 1 ++static struct usb_composite_driver audio_driver = { + .name = "g_audio", + .dev = &device_desc, + .strings = audio_strings, + .max_speed = USB_SPEED_HIGH, + .bind = audio_bind, +- .unbind = __exit_p(audio_unbind), ++ .unbind = audio_unbind, + }; + + module_usb_composite_driver(audio_driver); +@@ -307,3 +382,5 @@ MODULE_DESCRIPTION(DRIVER_DESC); + MODULE_AUTHOR("Bryan Wu "); + MODULE_LICENSE("GPL"); + ++#endif ++ +diff --git a/drivers/usb/gadget/legacy/audio.inl b/drivers/usb/gadget/legacy/audio.inl +new file mode 100644 +index 0000000..6f31cbe +--- /dev/null ++++ b/drivers/usb/gadget/legacy/audio.inl +@@ -0,0 +1,328 @@ ++/* ++ * audio.c -- Audio gadget driver ++ * ++ * Copyright (C) 2008 Bryan Wu ++ * Copyright (C) 2008 Analog Devices, Inc ++ * ++ * Enter bugs at http://blackfin.uclinux.org/ ++ * ++ * Licensed under the GPL-2 or later. ++ */ ++ ++/* #define VERBOSE_DEBUG */ ++ ++#include ++#include ++#include ++ ++#define DRIVER_DESC "Linux USB Audio Gadget" ++#define DRIVER_VERSION "Feb 2, 2012" ++ ++ ++#ifndef CONFIG_GADGET_UAC1 ++#include "u_uac2.h" ++ ++/* Playback(USB-IN) Default Stereo - Fl/Fr */ ++static int p_chmask = UAC2_DEF_PCHMASK; ++module_param(p_chmask, uint, S_IRUGO); ++MODULE_PARM_DESC(p_chmask, "Playback Channel Mask"); ++ ++/* Playback Default 48 KHz */ ++static int p_srate = UAC2_DEF_PSRATE; ++module_param(p_srate, uint, S_IRUGO); ++MODULE_PARM_DESC(p_srate, "Playback Sampling Rate"); ++ ++/* Playback Default 16bits/sample */ ++static int p_ssize = UAC2_DEF_PSSIZE; ++module_param(p_ssize, uint, S_IRUGO); ++MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)"); ++ ++/* Capture(USB-OUT) Default Stereo - Fl/Fr */ ++static int c_chmask = UAC2_DEF_CCHMASK; ++module_param(c_chmask, uint, S_IRUGO); ++MODULE_PARM_DESC(c_chmask, "Capture Channel Mask"); ++ ++/* Capture Default 64 KHz */ ++static int c_srate = UAC2_DEF_CSRATE; ++module_param(c_srate, uint, S_IRUGO); ++MODULE_PARM_DESC(c_srate, "Capture Sampling Rate"); ++ ++/* Capture Default 16bits/sample */ ++static int c_ssize = UAC2_DEF_CSSIZE; ++module_param(c_ssize, uint, S_IRUGO); ++MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)"); ++#else ++#ifndef CONFIG_GADGET_UAC1_LEGACY ++#include "u_uac1.h" ++ ++/* Playback(USB-IN) Default Stereo - Fl/Fr */ ++static int p_chmask = UAC1_DEF_PCHMASK; ++module_param(p_chmask, uint, S_IRUGO); ++MODULE_PARM_DESC(p_chmask, "Playback Channel Mask"); ++ ++/* Playback Default 48 KHz */ ++static int p_srate = UAC1_DEF_PSRATE; ++module_param(p_srate, uint, S_IRUGO); ++MODULE_PARM_DESC(p_srate, "Playback Sampling Rate"); ++ ++/* Playback Default 16bits/sample */ ++static int p_ssize = UAC1_DEF_PSSIZE; ++module_param(p_ssize, uint, S_IRUGO); ++MODULE_PARM_DESC(p_ssize, "Playback Sample Size(bytes)"); ++ ++/* Capture(USB-OUT) Default Stereo - Fl/Fr */ ++static int c_chmask = UAC1_DEF_CCHMASK; ++module_param(c_chmask, uint, S_IRUGO); ++MODULE_PARM_DESC(c_chmask, "Capture Channel Mask"); ++ ++/* Capture Default 48 KHz */ ++static int c_srate = UAC1_DEF_CSRATE; ++module_param(c_srate, uint, S_IRUGO); ++MODULE_PARM_DESC(c_srate, "Capture Sampling Rate"); ++ ++/* Capture Default 16bits/sample */ ++static int c_ssize = UAC1_DEF_CSSIZE; ++module_param(c_ssize, uint, S_IRUGO); ++MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)"); ++ ++/* req number */ ++static int req_num = UAC1_DEF_REQ_NUM; ++module_param(req_num, uint, S_IRUGO); ++MODULE_PARM_DESC(req_num, "req number"); ++ ++static int req_buf_size = UAC1_OUT_EP_MAX_PACKET_SIZE; ++module_param(req_buf_size, int, S_IRUGO); ++MODULE_PARM_DESC(req_buf_size, "ISO OUT endpoint request buffer size"); ++ ++#else /* CONFIG_GADGET_UAC1_LEGACY */ ++#include "u_uac1_legacy.h" ++ ++static char *fn_play = FILE_PCM_PLAYBACK; ++module_param(fn_play, charp, S_IRUGO); ++MODULE_PARM_DESC(fn_play, "Playback PCM device file name"); ++ ++static char *fn_cap = FILE_PCM_CAPTURE; ++module_param(fn_cap, charp, S_IRUGO); ++MODULE_PARM_DESC(fn_cap, "Capture PCM device file name"); ++ ++static char *fn_cntl = FILE_CONTROL; ++module_param(fn_cntl, charp, S_IRUGO); ++MODULE_PARM_DESC(fn_cntl, "Control device file name"); ++ ++static int req_buf_size = UAC1_OUT_EP_MAX_PACKET_SIZE; ++module_param(req_buf_size, int, S_IRUGO); ++MODULE_PARM_DESC(req_buf_size, "ISO OUT endpoint request buffer size"); ++ ++static int req_count = UAC1_REQ_COUNT; ++module_param(req_count, int, S_IRUGO); ++MODULE_PARM_DESC(req_count, "ISO OUT endpoint request count"); ++ ++static int audio_buf_size = UAC1_AUDIO_BUF_SIZE; ++module_param(audio_buf_size, int, S_IRUGO); ++MODULE_PARM_DESC(audio_buf_size, "Audio buffer size"); ++#endif /* CONFIG_GADGET_UAC1_LEGACY */ ++#endif ++ ++/* string IDs are assigned dynamically */ ++ ++static struct usb_string strings_dev[] = { ++ [USB_GADGET_MANUFACTURER_IDX].s = "", ++ [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, ++ [USB_GADGET_SERIAL_IDX].s = "", ++ { } /* end of list */ ++}; ++ ++ ++ ++#ifndef CONFIG_GADGET_UAC1 ++static struct usb_function_instance *fi_uac2; ++static struct usb_function *f_uac2; ++#else ++static struct usb_function_instance *fi_uac1; ++static struct usb_function *f_uac1; ++#endif ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! ++ * Instead: allocate your own, using normal USB-IF procedures. ++ */ ++ ++/* Thanks to Linux Foundation for donating this product ID. */ ++#define AUDIO_VENDOR_NUM 0x1d6b /* Linux Foundation */ ++#define AUDIO_PRODUCT_NUM 0x0101 /* Linux-USB Audio Gadget */ ++ ++/*-------------------------------------------------------------------------*/ ++ ++static struct usb_device_descriptor device_desc = { ++ .bLength = sizeof device_desc, ++ .bDescriptorType = USB_DT_DEVICE, ++ ++ /* .bcdUSB = DYNAMIC */ ++ ++#ifdef CONFIG_GADGET_UAC1_LEGACY ++ .bDeviceClass = USB_CLASS_PER_INTERFACE, ++ .bDeviceSubClass = 0, ++ .bDeviceProtocol = 0, ++#else ++ .bDeviceClass = USB_CLASS_MISC, ++ .bDeviceSubClass = 0x02, ++ .bDeviceProtocol = 0x01, ++#endif ++ /* .bMaxPacketSize0 = f(hardware) */ ++ ++ /* Vendor and product id defaults change according to what configs ++ * we support. (As does bNumConfigurations.) These values can ++ * also be overridden by module parameters. ++ */ ++ .idVendor = cpu_to_le16(AUDIO_VENDOR_NUM), ++ .idProduct = cpu_to_le16(AUDIO_PRODUCT_NUM), ++ /* .bcdDevice = f(hardware) */ ++ /* .iManufacturer = DYNAMIC */ ++ /* .iProduct = DYNAMIC */ ++ /* NO SERIAL NUMBER */ ++ .bNumConfigurations = 1, ++}; ++ ++static const struct usb_descriptor_header *otg_desc[2]; ++ ++/*-------------------------------------------------------------------------*/ ++ ++static int audio_do_config(struct usb_configuration *c) ++{ ++ int status; ++ ++ /* FIXME alloc iConfiguration string, set it in c->strings */ ++ ++ if (gadget_is_otg(c->cdev->gadget)) { ++ c->descriptors = otg_desc; ++ c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; ++ } ++ ++#ifdef CONFIG_GADGET_UAC1 ++ f_uac1 = usb_get_function(fi_uac1); ++ if (IS_ERR(f_uac1)) { ++ status = PTR_ERR(f_uac1); ++ return status; ++ } ++ ++ status = usb_add_function(c, f_uac1); ++ if (status < 0) { ++ usb_put_function(f_uac1); ++ return status; ++ } ++#else ++ f_uac2 = usb_get_function(fi_uac2); ++ if (IS_ERR(f_uac2)) { ++ status = PTR_ERR(f_uac2); ++ return status; ++ } ++ ++ status = usb_add_function(c, f_uac2); ++ if (status < 0) { ++ usb_put_function(f_uac2); ++ return status; ++ } ++#endif ++ ++ return 0; ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static int audio_bind(struct usb_composite_dev *cdev) ++{ ++#ifndef CONFIG_GADGET_UAC1 ++ struct f_uac2_opts *uac2_opts; ++#else ++#ifndef CONFIG_GADGET_UAC1_LEGACY ++ struct f_uac1_opts *uac1_opts; ++#else ++ struct f_uac1_legacy_opts *uac1_opts; ++#endif ++#endif ++ int status; ++ ++#ifndef CONFIG_GADGET_UAC1 ++ fi_uac2 = usb_get_function_instance("uac2"); ++ if (IS_ERR(fi_uac2)) ++ return PTR_ERR(fi_uac2); ++#else ++#ifndef CONFIG_GADGET_UAC1_LEGACY ++ fi_uac1 = usb_get_function_instance("uac1"); ++#else ++ fi_uac1 = usb_get_function_instance("uac1_legacy"); ++#endif ++ if (IS_ERR(fi_uac1)) ++ return PTR_ERR(fi_uac1); ++#endif ++ ++#ifndef CONFIG_GADGET_UAC1 ++ uac2_opts = container_of(fi_uac2, struct f_uac2_opts, func_inst); ++ uac2_opts->p_chmask = p_chmask; ++ uac2_opts->p_srate = p_srate; ++ uac2_opts->p_ssize = p_ssize; ++ uac2_opts->c_chmask = c_chmask; ++ uac2_opts->c_srate = c_srate; ++ uac2_opts->c_ssize = c_ssize; ++ uac2_opts->req_number = UAC2_DEF_REQ_NUM; ++#else ++#ifndef CONFIG_GADGET_UAC1_LEGACY ++ uac1_opts = container_of(fi_uac1, struct f_uac1_opts, func_inst); ++ uac1_opts->p_chmask = p_chmask; ++ uac1_opts->p_srate = p_srate; ++ uac1_opts->p_ssize = p_ssize; ++ uac1_opts->c_chmask = c_chmask; ++ uac1_opts->c_srate = c_srate; ++ uac1_opts->c_ssize = c_ssize; ++ uac1_opts->req_number = UAC1_DEF_REQ_NUM; ++ uac1_opts->req_number = req_num; ++ uac1_opts->req_buf_size = req_buf_size; ++ ++#else /* CONFIG_GADGET_UAC1_LEGACY */ ++ uac1_opts = container_of(fi_uac1, struct f_uac1_legacy_opts, func_inst); ++ uac1_opts->fn_play = fn_play; ++ uac1_opts->fn_cap = fn_cap; ++ uac1_opts->fn_cntl = fn_cntl; ++ uac1_opts->req_buf_size = req_buf_size; ++ uac1_opts->req_count = req_count; ++ uac1_opts->audio_buf_size = audio_buf_size; ++#endif /* CONFIG_GADGET_UAC1_LEGACY */ ++#endif ++ ++ status = usb_string_ids_tab(cdev, strings_dev); ++ if (status < 0) ++ goto fail; ++ device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; ++ device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; ++ ++ INFO(cdev, "%s, version: %s\n", DRIVER_DESC, DRIVER_VERSION); ++ return 0; ++ ++fail: ++#ifndef CONFIG_GADGET_UAC1 ++ usb_put_function_instance(fi_uac2); ++#else ++ usb_put_function_instance(fi_uac1); ++#endif ++ return status; ++} ++ ++static int audio_unbind(struct usb_composite_dev *cdev) ++{ ++#ifdef CONFIG_GADGET_UAC1 ++ if (!IS_ERR_OR_NULL(f_uac1)) ++ usb_put_function(f_uac1); ++ if (!IS_ERR_OR_NULL(fi_uac1)) ++ usb_put_function_instance(fi_uac1); ++#else ++ if (!IS_ERR_OR_NULL(f_uac2)) ++ usb_put_function(f_uac2); ++ if (!IS_ERR_OR_NULL(fi_uac2)) ++ usb_put_function_instance(fi_uac2); ++#endif ++ ++ return 0; ++} ++ ++ +diff --git a/drivers/usb/gadget/legacy/gmidi.c b/drivers/usb/gadget/legacy/gmidi.c +index 3d696b8..b7c631d 100644 +--- a/drivers/usb/gadget/legacy/gmidi.c ++++ b/drivers/usb/gadget/legacy/gmidi.c +@@ -37,6 +37,7 @@ + + #include "gadget_chips.h" + ++#define USBF_MIDI_INCLUDED + #include "f_midi.c" + + /*-------------------------------------------------------------------------*/ +@@ -115,6 +116,9 @@ static struct usb_gadget_strings *dev_strings[] = { + NULL, + }; + ++static struct usb_function_instance *fi_midi; ++static struct usb_function *f_midi; ++ + static int __exit midi_unbind(struct usb_composite_dev *dev) + { + return 0; +diff --git a/drivers/usb/gadget/legacy/multi.c b/drivers/usb/gadget/legacy/multi.c +index 39d27bb..74b258e 100644 +--- a/drivers/usb/gadget/legacy/multi.c ++++ b/drivers/usb/gadget/legacy/multi.c +@@ -151,7 +151,9 @@ static struct usb_function *f_msg_rndis; + + static __init int rndis_do_config(struct usb_configuration *c) + { ++#if 0 + struct fsg_opts *fsg_opts; ++#endif + int ret; + + if (gadget_is_otg(c->cdev->gadget)) { +@@ -177,6 +179,7 @@ static __init int rndis_do_config(struct usb_configuration *c) + if (ret) + goto err_conf; + ++#if 0 + f_msg_rndis = usb_get_function(fi_msg); + if (IS_ERR(f_msg_rndis)) { + ret = PTR_ERR(f_msg_rndis); +@@ -192,11 +195,14 @@ static __init int rndis_do_config(struct usb_configuration *c) + if (ret) + goto err_run; + ++#endif + return 0; ++#if 0 + err_run: + usb_put_function(f_msg_rndis); + err_fsg: + usb_remove_function(c, f_acm_rndis); ++#endif + err_conf: + usb_put_function(f_acm_rndis); + err_func_acm: +@@ -265,7 +271,7 @@ static __init int cdc_do_config(struct usb_configuration *c) + ret = usb_add_function(c, f_acm_multi); + if (ret) + goto err_conf; +- ++#if 0 + f_msg_multi = usb_get_function(fi_msg); + if (IS_ERR(f_msg_multi)) { + ret = PTR_ERR(f_msg_multi); +@@ -280,6 +286,7 @@ static __init int cdc_do_config(struct usb_configuration *c) + ret = usb_add_function(c, f_msg_multi); + if (ret) + goto err_run; ++#endif + + return 0; + err_run: +@@ -330,8 +337,10 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) + #ifdef USB_ETH_RNDIS + struct f_rndis_opts *rndis_opts; + #endif ++#if 0 + struct fsg_opts *fsg_opts; + struct fsg_config config; ++#endif + int status; + + if (!can_support_ecm(cdev->gadget)) { +@@ -392,7 +401,7 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) + status = PTR_ERR(fi_acm); + goto fail0; + } +- ++#if 0 + /* set up mass storage function */ + fi_msg = usb_get_function_instance("mass_storage"); + if (IS_ERR(fi_msg)) { +@@ -422,7 +431,7 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) + + fsg_common_set_inquiry_string(fsg_opts->common, config.vendor_name, + config.product_name); +- ++#endif + /* allocate string IDs */ + status = usb_string_ids_tab(cdev, strings_dev); + if (unlikely(status < 0)) +@@ -446,6 +455,7 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) + + /* error recovery */ + fail_string_ids: ++#if 0 + fsg_common_remove_luns(fsg_opts->common); + fail_set_cdev: + fsg_common_free_luns(fsg_opts->common); +@@ -455,6 +465,7 @@ fail2: + usb_put_function_instance(fi_msg); + fail1: + usb_put_function_instance(fi_acm); ++#endif + fail0: + #ifdef USB_ETH_RNDIS + usb_put_function_instance(fi_rndis); +@@ -504,7 +515,7 @@ static __refdata struct usb_composite_driver multi_driver = { + .max_speed = USB_SPEED_HIGH, + .bind = multi_bind, + .unbind = __exit_p(multi_unbind), +- .needs_serial = 1, ++ .needs_serial = 0, + }; + + module_usb_composite_driver(multi_driver); +diff --git a/drivers/usb/gadget/legacy/webcam.c b/drivers/usb/gadget/legacy/webcam.c +index 04a3da2..e1fe6b2 100644 +--- a/drivers/usb/gadget/legacy/webcam.c ++++ b/drivers/usb/gadget/legacy/webcam.c +@@ -26,11 +26,11 @@ static unsigned int streaming_interval = 1; + module_param(streaming_interval, uint, S_IRUGO|S_IWUSR); + MODULE_PARM_DESC(streaming_interval, "1 - 16"); + +-static unsigned int streaming_maxpacket = 1024; ++static unsigned int streaming_maxpacket = 3072; + module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR); + MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)"); + +-static unsigned int streaming_maxburst; ++static unsigned int streaming_maxburst = 14; + module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR); + MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)"); + +@@ -49,6 +49,17 @@ static char webcam_vendor_label[] = "Linux Foundation"; + static char webcam_product_label[] = "Webcam gadget"; + static char webcam_config_label[] = "Video"; + ++/* GUID of the UVC H.264 extension unit: ++{A29E7641-DE04-47E3-8B2B-F4341AFF003B} */ ++#define GUID_UVCX_H264_XU {0x41, 0x76, 0x9E, 0xA2, 0x04, 0xDE, 0xE3, 0x47, \ ++ 0x8B, 0x2B, 0xF4, 0x34, 0x1A, 0xFF, 0x00, 0x3B} ++ ++#define UVC_GUID_HI_CAMERA {0x91, 0x72, 0x1e, 0x9a, 0x43, 0x68, 0x83, 0x46, \ ++ 0x6d, 0x92, 0x39, 0xbc, 0x79, 0x06, 0xee, 0x49} ++ ++#define UVC_GUID_FORMAT_H264 {0x48, 0x32, 0x36, 0x34, 0x00, 0x00, 0x10, 0x00, \ ++ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} ++ + /* string IDs are assigned dynamically */ + + #define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX +@@ -97,7 +108,7 @@ static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header = { + .bLength = UVC_DT_HEADER_SIZE(1), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = UVC_VC_HEADER, +- .bcdUVC = cpu_to_le16(0x0100), ++ .bcdUVC = cpu_to_le16(0x0110), + .wTotalLength = 0, /* dynamic */ + .dwClockFrequency = cpu_to_le32(48000000), + .bInCollection = 0, /* dynamic */ +@@ -108,7 +119,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 = 2, + .wTerminalType = cpu_to_le16(0x0201), + .bAssocTerminal = 0, + .iTerminal = 0, +@@ -116,24 +127,56 @@ 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[1] = 0, ++ .bmControls[0] = 0x1a, ++ .bmControls[1] = 0x00, + .bmControls[2] = 0, + }; + + static const struct uvc_processing_unit_descriptor uvc_processing = { +- .bLength = UVC_DT_PROCESSING_UNIT_SIZE(2), ++ .bLength = sizeof(uvc_processing), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = UVC_VC_PROCESSING_UNIT, +- .bUnitID = 2, ++ .bUnitID = 5, + .bSourceID = 1, + .wMaxMultiplier = cpu_to_le16(16*1024), + .bControlSize = 2, +- .bmControls[0] = 1, +- .bmControls[1] = 0, ++ .bmControls[0] = 0xff, ++ .bmControls[1] = 0xff, + .iProcessing = 0, + }; + ++DECLARE_UVC_EXTENSION_UNIT_DESCRIPTOR(1, 2); ++ ++static const struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 2) uvc_xu_h264_desc = { ++ .bLength = UVC_DT_EXTENSION_UNIT_SIZE(1, 2), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VC_EXTENSION_UNIT, ++ .bUnitID = 10, ++ .guidExtensionCode = GUID_UVCX_H264_XU, ++ .bNumControls = 15, ++ .bNrInPins = 1, ++ .baSourceID[0] = 2, ++ .bControlSize = 2, ++ .bmControls[0] = 0xff, ++ .bmControls[1] = 0xff, ++ .iExtension = 0, ++}; ++ ++static const struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 2) uvc_xu_hicamera_desc = { ++ .bLength = UVC_DT_EXTENSION_UNIT_SIZE(1, 2), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VC_EXTENSION_UNIT, ++ .bUnitID = 0x11, ++ .guidExtensionCode = UVC_GUID_HI_CAMERA, ++ .bNumControls = 15, ++ .bNrInPins = 1, ++ .baSourceID[0] = 10, ++ .bControlSize = 2, ++ .bmControls[0] = 0xff, ++ .bmControls[1] = 0xff, ++ .iExtension = 0, ++}; ++ + static const struct uvc_output_terminal_descriptor uvc_output_terminal = { + .bLength = UVC_DT_OUTPUT_TERMINAL_SIZE, + .bDescriptorType = USB_DT_CS_INTERFACE, +@@ -141,7 +184,7 @@ static const struct uvc_output_terminal_descriptor uvc_output_terminal = { + .bTerminalID = 3, + .wTerminalType = cpu_to_le16(0x0101), + .bAssocTerminal = 0, +- .bSourceID = 2, ++ .bSourceID = 0x11, + .iTerminal = 0, + }; + +@@ -169,7 +212,7 @@ static const struct uvc_format_uncompressed uvc_format_yuv = { + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED, + .bFormatIndex = 1, +- .bNumFrameDescriptors = 2, ++ .bNumFrameDescriptors = 5, + .guidFormat = + { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}, +@@ -183,39 +226,100 @@ static const struct uvc_format_uncompressed uvc_format_yuv = { + + 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), ++static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_144p = { ++ .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED, + .bFrameIndex = 1, + .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(176), ++ .wHeight = cpu_to_le16(144), ++ .dwMinBitRate = cpu_to_le32(56088), ++ .dwMaxBitRate = cpu_to_le32(56088), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_240p = { ++ .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(320), ++ .wHeight = cpu_to_le16(240), ++ .dwMinBitRate = cpu_to_le32(55296000), ++ .dwMaxBitRate = cpu_to_le32(55296000), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_288p = { ++ .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED, ++ .bFrameIndex = 3, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(352), ++ .wHeight = cpu_to_le16(288), ++ .dwMinBitRate = cpu_to_le32(55296000), ++ .dwMaxBitRate = cpu_to_le32(55296000), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_480p = { ++ .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED, ++ .bFrameIndex = 4, ++ .bmCapabilities = 0, + .wWidth = cpu_to_le16(640), +- .wHeight = cpu_to_le16(360), +- .dwMinBitRate = cpu_to_le32(18432000), ++ .wHeight = cpu_to_le16(480), ++ .dwMinBitRate = cpu_to_le32(55296000), + .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), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), + }; + + 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, ++ .bFrameIndex = 5, + .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), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_1080p = { ++ .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED, ++ .bFrameIndex = 6, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(1920), ++ .wHeight = cpu_to_le16(1080), ++ .dwMinBitRate = cpu_to_le32(29491200), ++ .dwMaxBitRate = cpu_to_le32(29491200), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(1843200), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), + .bFrameIntervalType = 1, +- .dwFrameInterval[0] = cpu_to_le32(5000000), ++ .dwFrameInterval[0] = cpu_to_le32(333333), + }; + + static const struct uvc_format_mjpeg uvc_format_mjpg = { +@@ -223,7 +327,7 @@ static const struct uvc_format_mjpeg uvc_format_mjpg = { + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = UVC_VS_FORMAT_MJPEG, + .bFormatIndex = 2, +- .bNumFrameDescriptors = 2, ++ .bNumFrameDescriptors = 6, + .bmFlags = 0, + .bDefaultFrameIndex = 1, + .bAspectRatioX = 0, +@@ -235,38 +339,230 @@ static const struct uvc_format_mjpeg uvc_format_mjpg = { + DECLARE_UVC_FRAME_MJPEG(1); + DECLARE_UVC_FRAME_MJPEG(3); + +-static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p = { +- .bLength = UVC_DT_FRAME_MJPEG_SIZE(3), ++static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_144p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = UVC_VS_FRAME_MJPEG, + .bFrameIndex = 1, + .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(176), ++ .wHeight = cpu_to_le16(144), ++ .dwMinBitRate = cpu_to_le32(55296000), ++ .dwMaxBitRate = cpu_to_le32(55296000), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_240p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_MJPEG, ++ .bFrameIndex = 2, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(320), ++ .wHeight = cpu_to_le16(240), ++ .dwMinBitRate = cpu_to_le32(55296000), ++ .dwMaxBitRate = cpu_to_le32(55296000), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_288p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_MJPEG, ++ .bFrameIndex = 3, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(352), ++ .wHeight = cpu_to_le16(288), ++ .dwMinBitRate = cpu_to_le32(55296000), ++ .dwMaxBitRate = cpu_to_le32(55296000), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++ ++static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_480p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_MJPEG, ++ .bFrameIndex = 4, ++ .bmCapabilities = 0, + .wWidth = cpu_to_le16(640), +- .wHeight = cpu_to_le16(360), +- .dwMinBitRate = cpu_to_le32(18432000), ++ .wHeight = cpu_to_le16(480), ++ .dwMinBitRate = cpu_to_le32(55296000), + .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), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), + }; + + static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p = { + .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = UVC_VS_FRAME_MJPEG, +- .bFrameIndex = 2, ++ .bFrameIndex = 5, + .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), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_1080p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_MJPEG, ++ .bFrameIndex = 6, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(1920), ++ .wHeight = cpu_to_le16(1080), ++ .dwMinBitRate = cpu_to_le32(29491200), ++ .dwMaxBitRate = cpu_to_le32(29491200), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(1843200), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct uvc_format_h264 uvc_format_h264 = { ++ .bLength = UVC_DT_FORMAT_H264_SIZE, ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FORMAT_H264, ++ .bFormatIndex = 3, ++ .bNumFrameDescriptors = 6, ++ .bmFlags = 0, ++ .bDefaultFrameIndex = 1, ++ .bAspectRatioX = 0, ++ .bAspectRatioY = 0, ++ .bmInterfaceFlags = 0, ++ .bCopyProtect = 0, ++}; ++ ++static const struct uvc_format_h264_base uvc_format_h264_base = { ++ .bLength = sizeof(uvc_format_h264_base), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FORMAT_FRAME_BASED, ++ .bFormatIndex = 3, ++ .bNumFrameDescriptors = 6, ++ .guidFormat = UVC_GUID_FORMAT_H264, ++ .bBitsPerPixel = 16, ++ .bDefaultFrameIndex = 1, ++ .bAspectRatioX = 0, ++ .bAspectRatioY = 0, ++ .bmInterfaceFlags = 0, ++ .bCopyProtect = 0, ++ .bVariableSize = 1, ++}; ++ ++DECLARE_UVC_FRAME_H264_BASE(1); ++DECLARE_UVC_FRAME_H264_BASE(3); ++ ++static const struct UVC_FRAME_H264_BASE(1) uvc_frame_h264_720p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED, ++ .bFrameIndex = 5, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(1280), ++ .wHeight = cpu_to_le16(720), ++ .dwMinBitRate = cpu_to_le32(55296000), ++ .dwMaxBitRate = cpu_to_le32(55296000), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), + .bFrameIntervalType = 1, +- .dwFrameInterval[0] = cpu_to_le32(5000000), ++ .dwBytesPerLine = 0, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_H264_BASE(1) uvc_frame_h264_1080p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED, ++ .bFrameIndex = 6, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(1920), ++ .wHeight = cpu_to_le16(1080), ++ .dwMinBitRate = cpu_to_le32(29491200), ++ .dwMaxBitRate = cpu_to_le32(29491200), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwBytesPerLine = 0, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_H264_BASE(1) uvc_frame_h264_480p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED, ++ .bFrameIndex = 4, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(640), ++ .wHeight = cpu_to_le16(480), ++ .dwMinBitRate = cpu_to_le32(29491200), ++ .dwMaxBitRate = cpu_to_le32(29491200), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwBytesPerLine = 0, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_H264_BASE(1) uvc_frame_h264_144p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED, ++ .bFrameIndex = 1, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(176), ++ .wHeight = cpu_to_le16(144), ++ .dwMinBitRate = cpu_to_le32(29491200), ++ .dwMaxBitRate = cpu_to_le32(29491200), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwBytesPerLine = 0, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_H264_BASE(1) uvc_frame_h264_240p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED, ++ .bFrameIndex = 2, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(320), ++ .wHeight = cpu_to_le16(240), ++ .dwMinBitRate = cpu_to_le32(29491200), ++ .dwMaxBitRate = cpu_to_le32(29491200), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwBytesPerLine = 0, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_H264_BASE(1) uvc_frame_h264_288p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED, ++ .bFrameIndex = 3, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(352), ++ .wHeight = cpu_to_le16(288), ++ .dwMinBitRate = cpu_to_le32(29491200), ++ .dwMaxBitRate = cpu_to_le32(29491200), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwBytesPerLine = 0, ++ .dwFrameInterval[0] = cpu_to_le32(333333), + }; + + static const struct uvc_color_matching_descriptor uvc_color_matching = { +@@ -282,6 +578,8 @@ 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 *) &uvc_xu_h264_desc, ++ (const struct uvc_descriptor_header *) &uvc_xu_hicamera_desc, + (const struct uvc_descriptor_header *) &uvc_output_terminal, + NULL, + }; +@@ -290,6 +588,8 @@ 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 *) &uvc_xu_h264_desc, ++ (const struct uvc_descriptor_header *) &uvc_xu_hicamera_desc, + (const struct uvc_descriptor_header *) &uvc_output_terminal, + NULL, + }; +@@ -297,11 +597,25 @@ static const struct uvc_descriptor_header * const uvc_ss_control_cls[] = { + 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_144p, ++ (const struct uvc_descriptor_header *) &uvc_frame_yuv_240p, ++ (const struct uvc_descriptor_header *) &uvc_frame_yuv_288p, ++ (const struct uvc_descriptor_header *) &uvc_frame_yuv_480p, + (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_144p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_240p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_288p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_480p, + (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_1080p, ++ (const struct uvc_descriptor_header *) &uvc_format_h264_base, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_720p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_1080p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_480p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_144p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_240p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_288p, + (const struct uvc_descriptor_header *) &uvc_color_matching, + NULL, + }; +@@ -309,11 +623,25 @@ 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_144p, ++ (const struct uvc_descriptor_header *) &uvc_frame_yuv_240p, ++ (const struct uvc_descriptor_header *) &uvc_frame_yuv_288p, ++ (const struct uvc_descriptor_header *) &uvc_frame_yuv_480p, + (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_144p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_240p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_288p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_480p, + (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_1080p, ++ (const struct uvc_descriptor_header *) &uvc_format_h264_base, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_720p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_1080p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_480p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_144p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_240p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_288p, + (const struct uvc_descriptor_header *) &uvc_color_matching, + NULL, + }; +@@ -321,11 +649,25 @@ 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_144p, ++ (const struct uvc_descriptor_header *) &uvc_frame_yuv_240p, ++ (const struct uvc_descriptor_header *) &uvc_frame_yuv_288p, ++ (const struct uvc_descriptor_header *) &uvc_frame_yuv_480p, + (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_144p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_240p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_288p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_480p, + (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_1080p, ++ (const struct uvc_descriptor_header *) &uvc_format_h264_base, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_720p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_1080p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_480p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_144p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_240p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_288p, + (const struct uvc_descriptor_header *) &uvc_color_matching, + NULL, + }; +@@ -346,7 +688,6 @@ webcam_config_bind(struct usb_configuration *c) + status = usb_add_function(c, f_uvc); + if (status < 0) + usb_put_function(f_uvc); +- + return status; + } + +diff --git a/drivers/usb/gadget/legacy/webcam_audio.c b/drivers/usb/gadget/legacy/webcam_audio.c +new file mode 100644 +index 0000000..826c65e +--- /dev/null ++++ b/drivers/usb/gadget/legacy/webcam_audio.c +@@ -0,0 +1,791 @@ ++/* ++ * webcam.c -- USB webcam 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 ++#include ++#include ++#include ++ ++#include "u_uvc.h" ++ ++USB_GADGET_COMPOSITE_OPTIONS(); ++ ++#include "audio.inl" ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* module parameters specific to the Video streaming endpoint */ ++static unsigned int streaming_interval = 1; ++module_param(streaming_interval, uint, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(streaming_interval, "1 - 16"); ++ ++static unsigned int streaming_maxpacket = 3072; ++module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)"); ++ ++static unsigned int streaming_maxburst = 14; ++module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)"); ++ ++static unsigned int trace; ++module_param(trace, uint, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(trace, "Trace level bitmask"); ++/* -------------------------------------------------------------------------- ++ * Device descriptor ++ */ ++ ++#define WEBCAM_VENDOR_ID 0x1d6b /* Linux Foundation */ ++#define WEBCAM_PRODUCT_ID 0x0102 /* Webcam A/V gadget */ ++#define WEBCAM_DEVICE_BCD 0x0010 /* 0.10 */ ++ ++static char webcam_vendor_label[] = "Linux Foundation"; ++static char webcam_product_label[] = "Webcam gadget"; ++static char webcam_config_label[] = "Video"; ++ ++/* GUID of the UVC H.264 extension unit: ++{A29E7641-DE04-47E3-8B2B-F4341AFF003B} */ ++#define GUID_UVCX_H264_XU {0x41, 0x76, 0x9E, 0xA2, 0x04, 0xDE, 0xE3, 0x47, \ ++ 0x8B, 0x2B, 0xF4, 0x34, 0x1A, 0xFF, 0x00, 0x3B} ++ ++#define UVC_GUID_HI_CAMERA {0x91, 0x72, 0x1e, 0x9a, 0x43, 0x68, 0x83, 0x46, \ ++ 0x6d, 0x92, 0x39, 0xbc, 0x79, 0x06, 0xee, 0x49} ++ ++#define UVC_GUID_FORMAT_H264 {0x48, 0x32, 0x36, 0x34, 0x00, 0x00, 0x10, 0x00, \ ++ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} ++ ++/* string IDs are assigned dynamically */ ++ ++#define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX ++ ++static struct usb_string webcam_strings[] = { ++ [USB_GADGET_MANUFACTURER_IDX].s = webcam_vendor_label, ++ [USB_GADGET_PRODUCT_IDX].s = webcam_product_label, ++ [USB_GADGET_SERIAL_IDX].s = "", ++ [STRING_DESCRIPTION_IDX].s = webcam_config_label, ++ { } ++}; ++ ++static struct usb_gadget_strings webcam_stringtab = { ++ .language = 0x0409, /* en-us */ ++ .strings = webcam_strings, ++}; ++ ++static struct usb_gadget_strings *webcam_device_strings[] = { ++ &webcam_stringtab, ++ NULL, ++}; ++ ++static struct usb_function_instance *fi_uvc; ++static struct usb_function *f_uvc; ++ ++static struct usb_device_descriptor webcam_device_descriptor = { ++ .bLength = USB_DT_DEVICE_SIZE, ++ .bDescriptorType = USB_DT_DEVICE, ++ .bcdUSB = cpu_to_le16(0x0200), ++ .bDeviceClass = USB_CLASS_MISC, ++ .bDeviceSubClass = 0x02, ++ .bDeviceProtocol = 0x01, ++ .bMaxPacketSize0 = 0, /* dynamic */ ++ .idVendor = cpu_to_le16(WEBCAM_VENDOR_ID), ++ .idProduct = cpu_to_le16(WEBCAM_PRODUCT_ID), ++ .bcdDevice = cpu_to_le16(WEBCAM_DEVICE_BCD), ++ .iManufacturer = 0, /* dynamic */ ++ .iProduct = 0, /* dynamic */ ++ .iSerialNumber = 0, /* dynamic */ ++ .bNumConfigurations = 0, /* dynamic */ ++}; ++ ++DECLARE_UVC_HEADER_DESCRIPTOR(1); ++ ++static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header = { ++ .bLength = UVC_DT_HEADER_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VC_HEADER, ++ .bcdUVC = cpu_to_le16(0x0110), ++ .wTotalLength = 0, /* dynamic */ ++ .dwClockFrequency = cpu_to_le32(48000000), ++ .bInCollection = 0, /* dynamic */ ++ .baInterfaceNr[0] = 0, /* dynamic */ ++}; ++ ++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 = 2, ++ .wTerminalType = cpu_to_le16(0x0201), ++ .bAssocTerminal = 0, ++ .iTerminal = 0, ++ .wObjectiveFocalLengthMin = cpu_to_le16(0), ++ .wObjectiveFocalLengthMax = cpu_to_le16(0), ++ .wOcularFocalLength = cpu_to_le16(0), ++ .bControlSize = 3, ++ .bmControls[0] = 0x1a, ++ .bmControls[1] = 0x00, ++ .bmControls[2] = 0, ++}; ++ ++static const struct uvc_processing_unit_descriptor uvc_processing = { ++ .bLength = sizeof(uvc_processing), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VC_PROCESSING_UNIT, ++ .bUnitID = 5, ++ .bSourceID = 1, ++ .wMaxMultiplier = cpu_to_le16(16*1024), ++ .bControlSize = 2, ++ .bmControls[0] = 0xff, ++ .bmControls[1] = 0xff, ++ .iProcessing = 0, ++}; ++ ++DECLARE_UVC_EXTENSION_UNIT_DESCRIPTOR(1, 2); ++ ++static const struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 2) uvc_xu_h264_desc = { ++ .bLength = UVC_DT_EXTENSION_UNIT_SIZE(1, 2), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VC_EXTENSION_UNIT, ++ .bUnitID = 10, ++ .guidExtensionCode = GUID_UVCX_H264_XU, ++ .bNumControls = 15, ++ .bNrInPins = 1, ++ .baSourceID[0] = 2, ++ .bControlSize = 2, ++ .bmControls[0] = 0xff, ++ .bmControls[1] = 0xff, ++ .iExtension = 0, ++}; ++ ++static const struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 2) uvc_xu_hicamera_desc = { ++ .bLength = UVC_DT_EXTENSION_UNIT_SIZE(1, 2), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VC_EXTENSION_UNIT, ++ .bUnitID = 0x11, ++ .guidExtensionCode = UVC_GUID_HI_CAMERA, ++ .bNumControls = 15, ++ .bNrInPins = 1, ++ .baSourceID[0] = 10, ++ .bControlSize = 2, ++ .bmControls[0] = 0xff, ++ .bmControls[1] = 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, ++ .wTerminalType = cpu_to_le16(0x0101), ++ .bAssocTerminal = 0, ++ .bSourceID = 0x11, ++ .iTerminal = 0, ++}; ++ ++DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2); ++ ++static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 2) uvc_input_header = { ++ .bLength = UVC_DT_INPUT_HEADER_SIZE(1, 2), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_INPUT_HEADER, ++ .bNumFormats = 2, ++ .wTotalLength = 0, /* dynamic */ ++ .bEndpointAddress = 0, /* dynamic */ ++ .bmInfo = 0, ++ .bTerminalLink = 3, ++ .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 = 5, ++ .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(1) uvc_frame_yuv_144p = { ++ .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED, ++ .bFrameIndex = 1, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(176), ++ .wHeight = cpu_to_le16(144), ++ .dwMinBitRate = cpu_to_le32(56088), ++ .dwMaxBitRate = cpu_to_le32(56088), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_240p = { ++ .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(320), ++ .wHeight = cpu_to_le16(240), ++ .dwMinBitRate = cpu_to_le32(55296000), ++ .dwMaxBitRate = cpu_to_le32(55296000), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_288p = { ++ .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED, ++ .bFrameIndex = 3, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(352), ++ .wHeight = cpu_to_le16(288), ++ .dwMinBitRate = cpu_to_le32(55296000), ++ .dwMaxBitRate = cpu_to_le32(55296000), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_480p = { ++ .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED, ++ .bFrameIndex = 4, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(640), ++ .wHeight = cpu_to_le16(480), ++ .dwMinBitRate = cpu_to_le32(55296000), ++ .dwMaxBitRate = cpu_to_le32(55296000), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++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 = 5, ++ .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(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_1080p = { ++ .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED, ++ .bFrameIndex = 6, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(1920), ++ .wHeight = cpu_to_le16(1080), ++ .dwMinBitRate = cpu_to_le32(29491200), ++ .dwMaxBitRate = cpu_to_le32(29491200), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(1843200), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++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 = 6, ++ .bmFlags = 0, ++ .bDefaultFrameIndex = 1, ++ .bAspectRatioX = 0, ++ .bAspectRatioY = 0, ++ .bmInterfaceFlags = 0, ++ .bCopyProtect = 0, ++}; ++ ++DECLARE_UVC_FRAME_MJPEG(1); ++DECLARE_UVC_FRAME_MJPEG(3); ++ ++static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_144p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_MJPEG, ++ .bFrameIndex = 1, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(176), ++ .wHeight = cpu_to_le16(144), ++ .dwMinBitRate = cpu_to_le32(55296000), ++ .dwMaxBitRate = cpu_to_le32(55296000), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_240p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_MJPEG, ++ .bFrameIndex = 2, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(320), ++ .wHeight = cpu_to_le16(240), ++ .dwMinBitRate = cpu_to_le32(55296000), ++ .dwMaxBitRate = cpu_to_le32(55296000), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_288p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_MJPEG, ++ .bFrameIndex = 3, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(352), ++ .wHeight = cpu_to_le16(288), ++ .dwMinBitRate = cpu_to_le32(55296000), ++ .dwMaxBitRate = cpu_to_le32(55296000), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++ ++static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_480p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_MJPEG, ++ .bFrameIndex = 4, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(640), ++ .wHeight = cpu_to_le16(480), ++ .dwMinBitRate = cpu_to_le32(55296000), ++ .dwMaxBitRate = cpu_to_le32(55296000), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_MJPEG, ++ .bFrameIndex = 5, ++ .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(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_1080p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_MJPEG, ++ .bFrameIndex = 6, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(1920), ++ .wHeight = cpu_to_le16(1080), ++ .dwMinBitRate = cpu_to_le32(29491200), ++ .dwMaxBitRate = cpu_to_le32(29491200), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(1843200), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct uvc_format_h264 uvc_format_h264 = { ++ .bLength = UVC_DT_FORMAT_H264_SIZE, ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FORMAT_H264, ++ .bFormatIndex = 3, ++ .bNumFrameDescriptors = 6, ++ .bmFlags = 0, ++ .bDefaultFrameIndex = 1, ++ .bAspectRatioX = 0, ++ .bAspectRatioY = 0, ++ .bmInterfaceFlags = 0, ++ .bCopyProtect = 0, ++}; ++ ++static const struct uvc_format_h264_base uvc_format_h264_base = { ++ .bLength = sizeof(uvc_format_h264_base), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FORMAT_FRAME_BASED, ++ .bFormatIndex = 3, ++ .bNumFrameDescriptors = 6, ++ .guidFormat = UVC_GUID_FORMAT_H264, ++ .bBitsPerPixel = 16, ++ .bDefaultFrameIndex = 1, ++ .bAspectRatioX = 0, ++ .bAspectRatioY = 0, ++ .bmInterfaceFlags = 0, ++ .bCopyProtect = 0, ++ .bVariableSize = 1, ++}; ++ ++DECLARE_UVC_FRAME_H264_BASE(1); ++DECLARE_UVC_FRAME_H264_BASE(3); ++ ++static const struct UVC_FRAME_H264_BASE(1) uvc_frame_h264_720p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED, ++ .bFrameIndex = 5, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(1280), ++ .wHeight = cpu_to_le16(720), ++ .dwMinBitRate = cpu_to_le32(55296000), ++ .dwMaxBitRate = cpu_to_le32(55296000), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwBytesPerLine = 0, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_H264_BASE(1) uvc_frame_h264_1080p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED, ++ .bFrameIndex = 6, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(1920), ++ .wHeight = cpu_to_le16(1080), ++ .dwMinBitRate = cpu_to_le32(29491200), ++ .dwMaxBitRate = cpu_to_le32(29491200), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwBytesPerLine = 0, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_H264_BASE(1) uvc_frame_h264_480p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED, ++ .bFrameIndex = 4, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(640), ++ .wHeight = cpu_to_le16(480), ++ .dwMinBitRate = cpu_to_le32(29491200), ++ .dwMaxBitRate = cpu_to_le32(29491200), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwBytesPerLine = 0, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_H264_BASE(1) uvc_frame_h264_144p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED, ++ .bFrameIndex = 1, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(176), ++ .wHeight = cpu_to_le16(144), ++ .dwMinBitRate = cpu_to_le32(29491200), ++ .dwMaxBitRate = cpu_to_le32(29491200), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwBytesPerLine = 0, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_H264_BASE(1) uvc_frame_h264_240p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED, ++ .bFrameIndex = 2, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(320), ++ .wHeight = cpu_to_le16(240), ++ .dwMinBitRate = cpu_to_le32(29491200), ++ .dwMaxBitRate = cpu_to_le32(29491200), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwBytesPerLine = 0, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++static const struct UVC_FRAME_H264_BASE(1) uvc_frame_h264_288p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED, ++ .bFrameIndex = 3, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(352), ++ .wHeight = cpu_to_le16(288), ++ .dwMinBitRate = cpu_to_le32(29491200), ++ .dwMaxBitRate = cpu_to_le32(29491200), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 1, ++ .dwBytesPerLine = 0, ++ .dwFrameInterval[0] = cpu_to_le32(333333), ++}; ++ ++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_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 *) &uvc_xu_h264_desc, ++ (const struct uvc_descriptor_header *) &uvc_xu_hicamera_desc, ++ (const struct uvc_descriptor_header *) &uvc_output_terminal, ++ NULL, ++}; ++ ++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 *) &uvc_xu_h264_desc, ++ (const struct uvc_descriptor_header *) &uvc_xu_hicamera_desc, ++ (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_144p, ++ (const struct uvc_descriptor_header *) &uvc_frame_yuv_240p, ++ (const struct uvc_descriptor_header *) &uvc_frame_yuv_288p, ++ (const struct uvc_descriptor_header *) &uvc_frame_yuv_480p, ++ (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_144p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_240p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_288p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_480p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_1080p, ++ (const struct uvc_descriptor_header *) &uvc_format_h264_base, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_720p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_1080p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_480p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_144p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_240p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_288p, ++ (const struct uvc_descriptor_header *) &uvc_color_matching, ++ NULL, ++}; ++ ++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_144p, ++ (const struct uvc_descriptor_header *) &uvc_frame_yuv_240p, ++ (const struct uvc_descriptor_header *) &uvc_frame_yuv_288p, ++ (const struct uvc_descriptor_header *) &uvc_frame_yuv_480p, ++ (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_144p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_240p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_288p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_480p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_1080p, ++ (const struct uvc_descriptor_header *) &uvc_format_h264_base, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_720p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_1080p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_480p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_144p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_240p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_288p, ++ (const struct uvc_descriptor_header *) &uvc_color_matching, ++ NULL, ++}; ++ ++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_144p, ++ (const struct uvc_descriptor_header *) &uvc_frame_yuv_240p, ++ (const struct uvc_descriptor_header *) &uvc_frame_yuv_288p, ++ (const struct uvc_descriptor_header *) &uvc_frame_yuv_480p, ++ (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_144p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_240p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_288p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_480p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_1080p, ++ (const struct uvc_descriptor_header *) &uvc_format_h264_base, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_720p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_1080p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_480p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_144p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_240p, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_288p, ++ (const struct uvc_descriptor_header *) &uvc_color_matching, ++ NULL, ++}; ++ ++/* -------------------------------------------------------------------------- ++ * USB configuration ++ */ ++static int __init ++webcam_config_bind(struct usb_configuration *c) ++{ ++ int status = 0; ++ ++ f_uvc = usb_get_function(fi_uvc); ++ if (IS_ERR(f_uvc)) ++ return PTR_ERR(f_uvc); ++ ++ status = usb_add_function(c, f_uvc); ++ if (status < 0) ++ usb_put_function(f_uvc); ++ ++ /* FIXME: add audio device*/ ++ audio_do_config(c); ++ ++ return status; ++} ++ ++static struct usb_configuration webcam_config_driver = { ++ .label = webcam_config_label, ++ .bConfigurationValue = 1, ++ .iConfiguration = 0, /* dynamic */ ++ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, ++ .MaxPower = CONFIG_USB_GADGET_VBUS_DRAW, ++}; ++ ++static int /* __init_or_exit */ ++webcam_unbind(struct usb_composite_dev *cdev) ++{ ++ /* FIXME: add audio device*/ ++ audio_unbind(cdev); ++ ++ if (!IS_ERR_OR_NULL(f_uvc)) ++ usb_put_function(f_uvc); ++ if (!IS_ERR_OR_NULL(fi_uvc)) ++ usb_put_function_instance(fi_uvc); ++ return 0; ++} ++ ++static int __init ++webcam_bind(struct usb_composite_dev *cdev) ++{ ++ struct f_uvc_opts *uvc_opts; ++ int ret; ++ ++ /* FIXME: add audio device*/ ++ audio_bind(cdev); ++ ++ fi_uvc = usb_get_function_instance("uvc"); ++ if (IS_ERR(fi_uvc)) ++ return PTR_ERR(fi_uvc); ++ ++ uvc_opts = container_of(fi_uvc, struct f_uvc_opts, func_inst); ++ ++ uvc_opts->streaming_interval = streaming_interval; ++ uvc_opts->streaming_maxpacket = streaming_maxpacket; ++ uvc_opts->streaming_maxburst = streaming_maxburst; ++ uvc_set_trace_param(trace); ++ ++ uvc_opts->fs_control = uvc_fs_control_cls; ++ uvc_opts->ss_control = uvc_ss_control_cls; ++ uvc_opts->fs_streaming = uvc_fs_streaming_cls; ++ uvc_opts->hs_streaming = uvc_hs_streaming_cls; ++ uvc_opts->ss_streaming = uvc_ss_streaming_cls; ++ ++ /* Allocate string descriptor numbers ... note that string contents ++ * can be overridden by the composite_dev glue. ++ */ ++ ret = usb_string_ids_tab(cdev, webcam_strings); ++ if (ret < 0) ++ goto error; ++ webcam_device_descriptor.iManufacturer = ++ webcam_strings[USB_GADGET_MANUFACTURER_IDX].id; ++ webcam_device_descriptor.iProduct = ++ webcam_strings[USB_GADGET_PRODUCT_IDX].id; ++ webcam_config_driver.iConfiguration = ++ webcam_strings[STRING_DESCRIPTION_IDX].id; ++ ++ /* Register our configuration. */ ++ if ((ret = usb_add_config(cdev, &webcam_config_driver, ++ webcam_config_bind)) < 0) ++ goto error; ++ ++ usb_composite_overwrite_options(cdev, &coverwrite); ++ INFO(cdev, "Webcam Video Gadget\n"); ++ return 0; ++ ++error: ++ usb_put_function_instance(fi_uvc); ++ return ret; ++} ++ ++/* -------------------------------------------------------------------------- ++ * Driver ++ */ ++ ++static __refdata struct usb_composite_driver webcam_driver = { ++ .name = "g_webcam", ++ .dev = &webcam_device_descriptor, ++ .strings = webcam_device_strings, ++ .max_speed = USB_SPEED_SUPER, ++ .bind = webcam_bind, ++ .unbind = webcam_unbind, ++}; ++ ++module_usb_composite_driver(webcam_driver); ++ ++MODULE_AUTHOR("Laurent Pinchart"); ++MODULE_DESCRIPTION("Webcam Video Gadget"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION("0.1.0"); +diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig +index 217365d..ed58012 100644 +--- a/drivers/usb/gadget/udc/Kconfig ++++ b/drivers/usb/gadget/udc/Kconfig +@@ -28,7 +28,7 @@ menu "USB Peripheral Controller" + # + # Integrated controllers + # +- ++#source "drivers/usb/gadget/udc/hiudc3/Kconfig" + config USB_AT91 + tristate "Atmel AT91 USB Device Port" + depends on ARCH_AT91 +@@ -219,6 +219,67 @@ config USB_MV_UDC + USB2.0 OTG controller, which can be configured as high speed or + full speed USB peripheral. + ++menuconfig HIUSB_DEVICE2_0 ++ bool "Hisilicon USB2.0 Device Controller SUPPORT" ++ help ++ This selects the usb(ehci/ohci) family usb device. ++ Say Y to enable hisi usb2.0 controller driver. ++ IF you do not use usb2.0 device in your board, ++ say N to get a smaller uImage. Mostly you need it. ++ ++if HIUSB_DEVICE2_0 ++ config USB_HISI_UDC ++ tristate "hisilicon highspeed device controller version 3.00a driver" ++ help ++ You can select device mode by the option. ++ Enable hisi ehci controller driver. ++ Say Y to enable hisi usb2.0 ehci controller driver. ++ IF you do not use usb2.0 ehci device in your board, say N to get a ++ smaller uImage. Mostly you need it. ++ ++config USB_AUTO_SWITCH ++ bool "Hisilicon USB2.0 Device auto switch" ++ depends on HAS_DMA ++ help ++ Hisilicon Socs include a high speed. The select can auto switch or ++ not. Default is auto switch. If you want to be auto switch ++ host/device, you can set 1 the 1st bit of 0x12020150. ++endif # HI_HS_DEVICE ++ ++menuconfig HIUSB_DEVICE3_0 ++ bool "Hisilicon USB3.0 Device Controller SUPPORT" ++ help ++ This selects the usb(ehci/ohci) family usb device. ++ Say Y to enable hisi usb3.0 controller driver. ++ IF you do not use usb3.0 device in your board, ++ say N to get a smaller uImage. Mostly you need it. ++ ++if HIUSB_DEVICE3_0 ++ config HIUSB_SS_DEVICE ++ boolean "hisilicon susperspeed device controller version 2.50a driver" ++ help ++ You can select device mode by the option. ++ Enable hisi ehci controller driver. ++ Say Y to enable hisi usb3.0 xhci controller driver. ++ IF you do not use usb3.0 xhci device in your board, say N to get a ++ smaller uImage. Mostly you need it. ++ ++config USB_HISI_UDC3 ++ tristate "Hisilicon USB3.0 Device Controller" ++ depends on HAS_DMA ++ help ++ Hisilicon Socs include a high speed ++ USB3.0 Device controller, which can be configured as susperspeed ++ USB peripheral. ++ ++config USB3_DEVICE_GPIO_CTRL ++ tristate "Hisilicon USB3.0 Device Support GPIO CTRL" ++ help ++ USB3.0 Device mode, it support device and host switch. When you ++ pull out the device, it can bring gpio interrupt and notify the sw ++ handle. The sw set the host mode and then set the device mode. ++endif # HI_SS_DEVICE ++ + config USB_MV_U3D + depends on HAS_DMA + tristate "MARVELL PXA2128 USB 3.0 controller" +diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile +index a7f4491..564a046 100644 +--- a/drivers/usb/gadget/udc/Makefile ++++ b/drivers/usb/gadget/udc/Makefile +@@ -1,7 +1,11 @@ + # + # USB peripheral controller drivers + # ++ifndef CONFIG_USB_HISI_UDC ++ifndef CONFIG_USB_HISI_UDC3 + obj-$(CONFIG_USB_GADGET) += udc-core.o ++endif ++endif + obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o + obj-$(CONFIG_USB_NET2272) += net2272.o + obj-$(CONFIG_USB_NET2280) += net2280.o +@@ -30,3 +34,6 @@ obj-$(CONFIG_USB_FOTG210_UDC) += fotg210-udc.o + obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o + obj-$(CONFIG_USB_GR_UDC) += gr_udc.o + obj-$(CONFIG_USB_GADGET_XILINX) += udc-xilinx.o ++obj-$(CONFIG_USB_HISI_UDC) += hiudc/ ++#obj-$(CONFIG_USB_HISI_UDC) += hiudc_bak/ ++obj-$(CONFIG_USB_HISI_UDC3) += hiudc3/ +diff --git a/drivers/usb/gadget/udc/hiudc/Makefile b/drivers/usb/gadget/udc/hiudc/Makefile +new file mode 100644 +index 0000000..28dd23c +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/Makefile +@@ -0,0 +1,21 @@ ++# ++# USB peripheral controller drivers ++# ++# Use the BUS_INTERFACE variable to compile the software for either ++# PCI(PCI_INTERFACE) or LM(LM_INTERFACE) bus. ++# Use one of the following flags to compile the software in host-only or ++# device-only mode. ++EXTRA_CFLAGS += -DDWC_DEVICE_ONLY ++EXTRA_CFLAGS += -DDWC_LINUX ++EXTRA_CFLAGS += -DLM_INTERFACE ++ ++obj-$(CONFIG_USB_HISI_UDC) += udc-hisi.o ++#obj-y += udc-hisi.o ++udc-hisi-objs := dwc_otg_driver.o dwc_otg_attr.o ++udc-hisi-objs += dwc_otg_cil.o dwc_otg_cil_intr.o ++udc-hisi-objs += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o ++udc-hisi-objs += dwc_otg_hcd.o dwc_otg_hcd_linux.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o dwc_otg_hcd_ddma.o ++udc-hisi-objs += dwc_otg_adp.o ++udc-hisi-objs += dwc_cc.o dwc_modpow.o dwc_dh.o \ ++ dwc_crypto.o dwc_notifier.o \ ++ dwc_common_linux.o dwc_mem.o +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_cc.c b/drivers/usb/gadget/udc/hiudc/dwc_cc.c +new file mode 100644 +index 0000000..a757f4f +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_cc.c +@@ -0,0 +1,532 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.c $ ++ * $Revision: #4 $ ++ * $Date: 2010/11/04 $ ++ * $Change: 1621692 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS 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. ++ * ========================================================================= */ ++#ifdef DWC_CCLIB ++ ++#include "dwc_cc.h" ++ ++typedef struct dwc_cc ++{ ++ uint32_t uid; ++ uint8_t chid[16]; ++ uint8_t cdid[16]; ++ uint8_t ck[16]; ++ uint8_t *name; ++ uint8_t length; ++ DWC_CIRCLEQ_ENTRY(dwc_cc) list_entry; ++} dwc_cc_t; ++ ++DWC_CIRCLEQ_HEAD(context_list, dwc_cc); ++ ++/** The main structure for CC management. */ ++struct dwc_cc_if ++{ ++ dwc_mutex_t *mutex; ++ char *filename; ++ ++ unsigned is_host:1; ++ ++ dwc_notifier_t *notifier; ++ ++ struct context_list list; ++}; ++ ++#ifdef DEBUG ++static inline void dump_bytes(char *name, uint8_t *bytes, int len) ++{ ++ int i; ++ DWC_PRINTF("%s: ", name); ++ for (i=0; ilength = length; ++ cc->name = dwc_alloc(mem_ctx, length); ++ if (!cc->name) { ++ dwc_free(mem_ctx, cc); ++ return NULL; ++ } ++ ++ DWC_MEMCPY(cc->name, name, length); ++ } ++ ++ return cc; ++} ++ ++static void free_cc(void *mem_ctx, dwc_cc_t *cc) ++{ ++ if (cc->name) { ++ dwc_free(mem_ctx, cc->name); ++ } ++ dwc_free(mem_ctx, cc); ++} ++ ++static uint32_t next_uid(dwc_cc_if_t *cc_if) ++{ ++ uint32_t uid = 0; ++ dwc_cc_t *cc; ++ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ if (cc->uid > uid) { ++ uid = cc->uid; ++ } ++ } ++ ++ if (uid == 0) { ++ uid = 255; ++ } ++ ++ return uid + 1; ++} ++ ++static dwc_cc_t *cc_find(dwc_cc_if_t *cc_if, uint32_t uid) ++{ ++ dwc_cc_t *cc; ++ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ if (cc->uid == uid) { ++ return cc; ++ } ++ } ++ return NULL; ++} ++ ++static unsigned int cc_data_size(dwc_cc_if_t *cc_if) ++{ ++ unsigned int size = 0; ++ dwc_cc_t *cc; ++ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ size += (48 + 1); ++ if (cc->name) { ++ size += cc->length; ++ } ++ } ++ return size; ++} ++ ++static uint32_t cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid) ++{ ++ uint32_t uid = 0; ++ dwc_cc_t *cc; ++ ++ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ if (DWC_MEMCMP(cc->chid, chid, 16) == 0) { ++ uid = cc->uid; ++ break; ++ } ++ } ++ return uid; ++} ++static uint32_t cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid) ++{ ++ uint32_t uid = 0; ++ dwc_cc_t *cc; ++ ++ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ if (DWC_MEMCMP(cc->cdid, cdid, 16) == 0) { ++ uid = cc->uid; ++ break; ++ } ++ } ++ return uid; ++} ++ ++/* Internal cc_add */ ++static int32_t cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) ++{ ++ dwc_cc_t *cc; ++ uint32_t uid; ++ ++ if (cc_if->is_host) { ++ uid = cc_match_cdid(cc_if, cdid); ++ } ++ else { ++ uid = cc_match_chid(cc_if, chid); ++ } ++ ++ if (uid) { ++ DWC_DEBUG("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length); ++ cc = cc_find(cc_if, uid); ++ } ++ else { ++ cc = alloc_cc(mem_ctx, name, length); ++ cc->uid = next_uid(cc_if); ++ DWC_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry); ++ } ++ ++ DWC_MEMCPY(&(cc->chid[0]), chid, 16); ++ DWC_MEMCPY(&(cc->cdid[0]), cdid, 16); ++ DWC_MEMCPY(&(cc->ck[0]), ck, 16); ++ ++ DWC_DEBUG("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length); ++ dump_bytes("CHID", cc->chid, 16); ++ dump_bytes("CDID", cc->cdid, 16); ++ dump_bytes("CK", cc->ck, 16); ++ return cc->uid; ++} ++ ++/* Internal cc_clear */ ++static void cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if) ++{ ++ while (!DWC_CIRCLEQ_EMPTY(&cc_if->list)) { ++ dwc_cc_t *cc = DWC_CIRCLEQ_FIRST(&cc_if->list); ++ DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry); ++ free_cc(mem_ctx, cc); ++ } ++} ++ ++dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx, ++ dwc_notifier_t *notifier, unsigned is_host) ++{ ++ dwc_cc_if_t *cc_if = NULL; ++ ++ /* Allocate a common_cc_if structure */ ++ cc_if = dwc_alloc(mem_ctx, sizeof(dwc_cc_if_t)); ++ ++ if (!cc_if) ++ return NULL; ++ ++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++ DWC_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex); ++#else ++ cc_if->mutex = dwc_mutex_alloc(mtx_ctx); ++#endif ++ if (!cc_if->mutex) { ++ dwc_free(mem_ctx, cc_if); ++ return NULL; ++ } ++ ++ DWC_CIRCLEQ_INIT(&cc_if->list); ++ cc_if->is_host = is_host; ++ cc_if->notifier = notifier; ++ return cc_if; ++} ++ ++void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if) ++{ ++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++ DWC_MUTEX_FREE(cc_if->mutex); ++#else ++ dwc_mutex_free(mtx_ctx, cc_if->mutex); ++#endif ++ cc_clear(mem_ctx, cc_if); ++ dwc_free(mem_ctx, cc_if); ++} ++ ++static void cc_changed(dwc_cc_if_t *cc_if) ++{ ++ if (cc_if->notifier) { ++ dwc_notify(cc_if->notifier, DWC_CC_LIST_CHANGED_NOTIFICATION, cc_if); ++ } ++} ++ ++void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if) ++{ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc_clear(mem_ctx, cc_if); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ cc_changed(cc_if); ++} ++ ++int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) ++{ ++ uint32_t uid; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ uid = cc_add(mem_ctx, cc_if, chid, cdid, ck, name, length); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ cc_changed(cc_if); ++ ++ return uid; ++} ++ ++void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) ++{ ++ dwc_cc_t* cc; ++ ++ DWC_DEBUG("Change connection context %d", id); ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (!cc) { ++ DWC_ERROR("Uid %d not found in cc list\n", id); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return; ++ } ++ ++ if (chid) { ++ DWC_MEMCPY(&(cc->chid[0]), chid, 16); ++ } ++ if (cdid) { ++ DWC_MEMCPY(&(cc->cdid[0]), cdid, 16); ++ } ++ if (ck) { ++ DWC_MEMCPY(&(cc->ck[0]), ck, 16); ++ } ++ ++ if (name) { ++ if (cc->name) { ++ dwc_free(mem_ctx, cc->name); ++ } ++ cc->name = dwc_alloc(mem_ctx, length); ++ if (!cc->name) { ++ DWC_ERROR("Out of memory in dwc_cc_change()\n"); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return; ++ } ++ cc->length = length; ++ DWC_MEMCPY(cc->name, name, length); ++ } ++ ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ cc_changed(cc_if); ++ ++ DWC_DEBUG("Changed connection context id=%d\n", id); ++ dump_bytes("New CHID", cc->chid, 16); ++ dump_bytes("New CDID", cc->cdid, 16); ++ dump_bytes("New CK", cc->ck, 16); ++} ++ ++void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id) ++{ ++ dwc_cc_t *cc; ++ ++ DWC_DEBUG("Removing connection context %d", id); ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (!cc) { ++ DWC_ERROR("Uid %d not found in cc list\n", id); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return; ++ } ++ ++ DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ free_cc(mem_ctx, cc); ++ ++ cc_changed(cc_if); ++} ++ ++uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, unsigned int *length) ++{ ++ uint8_t *buf, *x; ++ uint8_t zero = 0; ++ dwc_cc_t *cc; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ *length = cc_data_size(cc_if); ++ if (!(*length)) { ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return NULL; ++ } ++ ++ DWC_DEBUG("Creating data for saving (length=%d)", *length); ++ ++ buf = dwc_alloc(mem_ctx, *length); ++ if (!buf) { ++ *length = 0; ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return NULL; ++ } ++ ++ x = buf; ++ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ DWC_MEMCPY(x, cc->chid, 16); ++ x += 16; ++ DWC_MEMCPY(x, cc->cdid, 16); ++ x += 16; ++ DWC_MEMCPY(x, cc->ck, 16); ++ x += 16; ++ if (cc->name) { ++ DWC_MEMCPY(x, &cc->length, 1); ++ x += 1; ++ DWC_MEMCPY(x, cc->name, cc->length); ++ x += cc->length; ++ } ++ else { ++ DWC_MEMCPY(x, &zero, 1); ++ x += 1; ++ } ++ } ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return buf; ++} ++ ++void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length) ++{ ++ uint8_t name_length; ++ uint8_t *name; ++ uint8_t *chid; ++ uint8_t *cdid; ++ uint8_t *ck; ++ uint32_t i = 0; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc_clear(mem_ctx, cc_if); ++ ++ while (i < length) { ++ chid = &data[i]; ++ i += 16; ++ cdid = &data[i]; ++ i += 16; ++ ck = &data[i]; ++ i += 16; ++ ++ name_length = data[i]; ++ i ++; ++ ++ if (name_length) { ++ name = &data[i]; ++ i += name_length; ++ } ++ else { ++ name = NULL; ++ } ++ ++ /* check to see if we haven't overflown the buffer */ ++ if (i > length) { ++ DWC_ERROR("Data format error while attempting to load CCs " ++ "(nlen=%d, iter=%d, buflen=%d).\n", name_length, i, length); ++ break; ++ } ++ ++ cc_add(mem_ctx, cc_if, chid, cdid, ck, name, name_length); ++ } ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ cc_changed(cc_if); ++} ++ ++uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid) ++{ ++ uint32_t uid = 0; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ uid = cc_match_chid(cc_if, chid); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return uid; ++} ++uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid) ++{ ++ uint32_t uid = 0; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ uid = cc_match_cdid(cc_if, cdid); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return uid; ++} ++ ++uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id) ++{ ++ uint8_t *ck = NULL; ++ dwc_cc_t *cc; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (cc) { ++ ck = cc->ck; ++ } ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return ck; ++ ++} ++ ++uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id) ++{ ++ uint8_t *retval = NULL; ++ dwc_cc_t *cc; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (cc) { ++ retval = cc->chid; ++ } ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return retval; ++} ++ ++uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id) ++{ ++ uint8_t *retval = NULL; ++ dwc_cc_t *cc; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (cc) { ++ retval = cc->cdid; ++ } ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return retval; ++} ++ ++uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length) ++{ ++ uint8_t *retval = NULL; ++ dwc_cc_t *cc; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ *length = 0; ++ cc = cc_find(cc_if, id); ++ if (cc) { ++ *length = cc->length; ++ retval = cc->name; ++ } ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return retval; ++} ++ ++#endif /* DWC_CCLIB */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_cc.h b/drivers/usb/gadget/udc/hiudc/dwc_cc.h +new file mode 100644 +index 0000000..f86e6f2 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_cc.h +@@ -0,0 +1,224 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.h $ ++ * $Revision: #4 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS 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 _DWC_CC_H_ ++#define _DWC_CC_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ * ++ * This file defines the Context Context library. ++ * ++ * The main data structure is dwc_cc_if_t which is returned by either the ++ * dwc_cc_if_alloc function or returned by the module to the user via a provided ++ * function. The data structure is opaque and should only be manipulated via the ++ * functions provied in this API. ++ * ++ * It manages a list of connection contexts and operations can be performed to ++ * add, remove, query, search, and change, those contexts. Additionally, ++ * a dwc_notifier_t object can be requested from the manager so that ++ * the user can be notified whenever the context list has changed. ++ */ ++ ++#include "dwc_os.h" ++#include "dwc_list.h" ++#include "dwc_notifier.h" ++ ++ ++/* Notifications */ ++#define DWC_CC_LIST_CHANGED_NOTIFICATION "DWC_CC_LIST_CHANGED_NOTIFICATION" ++ ++struct dwc_cc_if; ++typedef struct dwc_cc_if dwc_cc_if_t; ++ ++ ++/** @name Connection Context Operations */ ++/** @{ */ ++ ++/** This function allocates memory for a dwc_cc_if_t structure, initializes ++ * fields to default values, and returns a pointer to the structure or NULL on ++ * error. */ ++extern dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx, ++ dwc_notifier_t *notifier, unsigned is_host); ++ ++/** Frees the memory for the specified CC structure allocated from ++ * dwc_cc_if_alloc(). */ ++extern void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if); ++ ++/** Removes all contexts from the connection context list */ ++extern void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if); ++ ++/** Adds a connection context (CHID, CK, CDID, Name) to the connection context list. ++ * If a CHID already exists, the CK and name are overwritten. Statistics are ++ * not overwritten. ++ * ++ * @param cc_if The cc_if structure. ++ * @param chid A pointer to the 16-byte CHID. This value will be copied. ++ * @param ck A pointer to the 16-byte CK. This value will be copied. ++ * @param cdid A pointer to the 16-byte CDID. This value will be copied. ++ * @param name An optional host friendly name as defined in the association model ++ * spec. Must be a UTF16-LE unicode string. Can be NULL to indicated no name. ++ * @param length The length othe unicode string. ++ * @return A unique identifier used to refer to this context that is valid for ++ * as long as this context is still in the list. */ ++extern int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, ++ uint8_t length); ++ ++/** Changes the CHID, CK, CDID, or Name values of a connection context in the ++ * list, preserving any accumulated statistics. This would typically be called ++ * if the host decideds to change the context with a SET_CONNECTION request. ++ * ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context. ++ * @param chid A pointer to the 16-byte CHID. This value will be copied. NULL ++ * indicates no change. ++ * @param cdid A pointer to the 16-byte CDID. This value will be copied. NULL ++ * indicates no change. ++ * @param ck A pointer to the 16-byte CK. This value will be copied. NULL ++ * indicates no change. ++ * @param name Host friendly name UTF16-LE. NULL indicates no change. ++ * @param length Length of name. */ ++extern void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, ++ uint8_t *chid, uint8_t *cdid, uint8_t *ck, ++ uint8_t *name, uint8_t length); ++ ++/** Remove the specified connection context. ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context to remove. */ ++extern void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id); ++ ++/** Get a binary block of data for the connection context list and attributes. ++ * This data can be used by the OS specific driver to save the connection ++ * context list into non-volatile memory. ++ * ++ * @param cc_if The cc_if structure. ++ * @param length Return the length of the data buffer. ++ * @return A pointer to the data buffer. The memory for this buffer should be ++ * freed with DWC_FREE() after use. */ ++extern uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, ++ unsigned int *length); ++ ++/** Restore the connection context list from the binary data that was previously ++ * returned from a call to dwc_cc_data_for_save. This can be used by the OS specific ++ * driver to load a connection context list from non-volatile memory. ++ * ++ * @param cc_if The cc_if structure. ++ * @param data The data bytes as returned from dwc_cc_data_for_save. ++ * @param length The length of the data. */ ++extern void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, ++ uint8_t *data, unsigned int length); ++ ++/** Find the connection context from the specified CHID. ++ * ++ * @param cc_if The cc_if structure. ++ * @param chid A pointer to the CHID data. ++ * @return A non-zero identifier of the connection context if the CHID matches. ++ * Otherwise returns 0. */ ++extern uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid); ++ ++/** Find the connection context from the specified CDID. ++ * ++ * @param cc_if The cc_if structure. ++ * @param cdid A pointer to the CDID data. ++ * @return A non-zero identifier of the connection context if the CHID matches. ++ * Otherwise returns 0. */ ++extern uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid); ++ ++/** Retrieve the CK from the specified connection context. ++ * ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context. ++ * @return A pointer to the CK data. The memory does not need to be freed. */ ++extern uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id); ++ ++/** Retrieve the CHID from the specified connection context. ++ * ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context. ++ * @return A pointer to the CHID data. The memory does not need to be freed. */ ++extern uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id); ++ ++/** Retrieve the CDID from the specified connection context. ++ * ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context. ++ * @return A pointer to the CDID data. The memory does not need to be freed. */ ++extern uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id); ++ ++extern uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length); ++ ++/** Checks a buffer for non-zero. ++ * @param id A pointer to a 16 byte buffer. ++ * @return true if the 16 byte value is non-zero. */ ++static inline unsigned dwc_assoc_is_not_zero_id(uint8_t *id) { ++ int i; ++ for (i=0; i<16; i++) { ++ if (id[i]) return 1; ++ } ++ return 0; ++} ++ ++/** Checks a buffer for zero. ++ * @param id A pointer to a 16 byte buffer. ++ * @return true if the 16 byte value is zero. */ ++static inline unsigned dwc_assoc_is_zero_id(uint8_t *id) { ++ return !dwc_assoc_is_not_zero_id(id); ++} ++ ++/** Prints an ASCII representation for the 16-byte chid, cdid, or ck, into ++ * buffer. */ ++static inline int dwc_print_id_string(char *buffer, uint8_t *id) { ++ char *ptr = buffer; ++ int i; ++ for (i=0; i<16; i++) { ++ ptr += DWC_SPRINTF(ptr, "%02x", id[i]); ++ if (i < 15) { ++ ptr += DWC_SPRINTF(ptr, " "); ++ } ++ } ++ return ptr - buffer; ++} ++ ++/** @} */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_CC_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_common_linux.c b/drivers/usb/gadget/udc/hiudc/dwc_common_linux.c +new file mode 100644 +index 0000000..1484a31 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_common_linux.c +@@ -0,0 +1,1425 @@ ++#include ++#include ++#include ++#include ++ ++#ifdef DWC_CCLIB ++# include "dwc_cc.h" ++#endif ++ ++#ifdef DWC_CRYPTOLIB ++# include "dwc_modpow.h" ++# include "dwc_dh.h" ++# include "dwc_crypto.h" ++#endif ++ ++#ifdef DWC_NOTIFYLIB ++# include "dwc_notifier.h" ++#endif ++ ++/* OS-Level Implementations */ ++ ++/* This is the Linux kernel implementation of the DWC platform library. */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) ++# include ++#else ++# include ++#endif ++ ++#include ++#include ++#include ++#include ++ ++#include "dwc_os.h" ++#include "dwc_list.h" ++ ++ ++/* MISC */ ++ ++void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size) ++{ ++ return memset(dest, byte, size); ++} ++ ++void *DWC_MEMCPY(void *dest, void const *src, uint32_t size) ++{ ++ return memcpy(dest, src, size); ++} ++ ++void *DWC_MEMMOVE(void *dest, void *src, uint32_t size) ++{ ++ return memmove(dest, src, size); ++} ++ ++int DWC_MEMCMP(void *m1, void *m2, uint32_t size) ++{ ++ return memcmp(m1, m2, size); ++} ++ ++int DWC_STRNCMP(void *s1, void *s2, uint32_t size) ++{ ++ return strncmp(s1, s2, size); ++} ++ ++int DWC_STRCMP(void *s1, void *s2) ++{ ++ return strcmp(s1, s2); ++} ++ ++int DWC_STRLEN(char const *str) ++{ ++ return strlen(str); ++} ++ ++char *DWC_STRCPY(char *to, char const *from) ++{ ++ return strcpy(to, from); ++} ++ ++char *DWC_STRDUP(char const *str) ++{ ++ int len = DWC_STRLEN(str) + 1; ++ char *new = DWC_ALLOC_ATOMIC(len); ++ ++ if (!new) { ++ return NULL; ++ } ++ ++ DWC_MEMCPY(new, str, len); ++ return new; ++} ++ ++int DWC_ATOI(const char *str, int32_t *value) ++{ ++ char *end = NULL; ++ ++ *value = simple_strtol(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++int DWC_ATOUI(const char *str, uint32_t *value) ++{ ++ char *end = NULL; ++ ++ *value = simple_strtoul(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++ ++#ifdef DWC_UTFLIB ++/* From usbstring.c */ ++ ++int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len) ++{ ++ int count = 0; ++ u8 c; ++ u16 uchar; ++ ++ /* this insists on correct encodings, though not minimal ones. ++ * BUT it currently rejects legit 4-byte UTF-8 code points, ++ * which need surrogate pairs. (Unicode 3.1 can use them.) ++ */ ++ while (len != 0 && (c = (u8) *s++) != 0) { ++ if (unlikely(c & 0x80)) { ++ // 2-byte sequence: ++ // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx ++ if ((c & 0xe0) == 0xc0) { ++ uchar = (c & 0x1f) << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ // 3-byte sequence (most CJKV characters): ++ // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx ++ } else if ((c & 0xf0) == 0xe0) { ++ uchar = (c & 0x0f) << 12; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ /* no bogus surrogates */ ++ if (0xd800 <= uchar && uchar <= 0xdfff) ++ goto fail; ++ ++ // 4-byte sequence (surrogate pairs, currently rare): ++ // 11101110wwwwzzzzyy + 110111yyyyxxxxxx ++ // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx ++ // (uuuuu = wwww + 1) ++ // FIXME accept the surrogate code points (only) ++ } else ++ goto fail; ++ } else ++ uchar = c; ++ put_unaligned (cpu_to_le16 (uchar), cp++); ++ count++; ++ len--; ++ } ++ return count; ++fail: ++ return -1; ++} ++#endif /* DWC_UTFLIB */ ++ ++ ++/* dwc_debug.h */ ++ ++dwc_bool_t DWC_IN_IRQ(void) ++{ ++ return in_irq(); ++} ++ ++dwc_bool_t DWC_IN_BH(void) ++{ ++ return in_softirq(); ++} ++ ++void DWC_VPRINTF(char *format, va_list args) ++{ ++ vprintk(format, args); ++} ++ ++int DWC_VSNPRINTF(char *str, int size, char *format, va_list args) ++{ ++ return vsnprintf(str, size, format, args); ++} ++ ++void DWC_PRINTF(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++int DWC_SPRINTF(char *buffer, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsprintf(buffer, format, args); ++ va_end(args); ++ return retval; ++} ++ ++int DWC_SNPRINTF(char *buffer, int size, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsnprintf(buffer, size, format, args); ++ va_end(args); ++ return retval; ++} ++ ++void __DWC_WARN(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_PRINTF(KERN_WARNING); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void __DWC_ERROR(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_PRINTF(KERN_ERR); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void DWC_EXCEPTION(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_PRINTF(KERN_ERR); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++ BUG_ON(1); ++} ++ ++#ifdef DEBUG ++void __DWC_DEBUG(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_PRINTF(KERN_DEBUG); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++#endif ++ ++ ++/* dwc_mem.h */ ++ ++#if 0 ++dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, ++ uint32_t align, ++ uint32_t alloc) ++{ ++ struct dma_pool *pool = dma_pool_create("Pool", NULL, ++ size, align, alloc); ++ return (dwc_pool_t *)pool; ++} ++ ++void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool) ++{ ++ dma_pool_destroy((struct dma_pool *)pool); ++} ++ ++void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr) ++{ ++ return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr); ++} ++ ++void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr) ++{ ++ void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr); ++ memset(..); ++} ++ ++void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr) ++{ ++ dma_pool_free(pool, vaddr, daddr); ++} ++#endif ++ ++void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) ++{ ++#ifdef xxCOSIM /* Only works for 32-bit cosim */ ++ void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL); ++#else ++// void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL | GFP_DMA32); ++ void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC); ++#endif ++ if (!buf) { ++ return NULL; ++ } ++ ++ memset(buf, 0, (size_t)size); ++ return buf; ++} ++ ++void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) ++{ ++ void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC); ++ if (!buf) { ++ return NULL; ++ } ++ memset(buf, 0, (size_t)size); ++ return buf; ++} ++ ++void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr) ++{ ++ dma_free_coherent(dma_ctx, size, virt_addr, dma_addr); ++} ++ ++void *__DWC_ALLOC(void *mem_ctx, uint32_t size) ++{ ++ return kzalloc(size, GFP_KERNEL); ++} ++ ++void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size) ++{ ++ return kzalloc(size, GFP_ATOMIC); ++} ++ ++void __DWC_FREE(void *mem_ctx, void *addr) ++{ ++ kfree(addr); ++} ++ ++ ++#ifdef DWC_CRYPTOLIB ++/* dwc_crypto.h */ ++ ++void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length) ++{ ++ get_random_bytes(buffer, length); ++} ++ ++int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out) ++{ ++ struct crypto_blkcipher *tfm; ++ struct blkcipher_desc desc; ++ struct scatterlist sgd; ++ struct scatterlist sgs; ++ ++ tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); ++ if (tfm == NULL) { ++ printk("failed to load transform for aes CBC\n"); ++ return -1; ++ } ++ ++ crypto_blkcipher_setkey(tfm, key, keylen); ++ crypto_blkcipher_set_iv(tfm, iv, 16); ++ ++ sg_init_one(&sgd, out, messagelen); ++ sg_init_one(&sgs, message, messagelen); ++ ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) { ++ crypto_free_blkcipher(tfm); ++ DWC_ERROR("AES CBC encryption failed"); ++ return -1; ++ } ++ ++ crypto_free_blkcipher(tfm); ++ return 0; ++} ++ ++int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ DWC_ERROR("Failed to load transform for sha256: %ld\n", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, len); ++ crypto_hash_digest(&desc, &sg, len, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++ ++int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, ++ uint8_t *key, uint32_t keylen, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ DWC_ERROR("Failed to load transform for hmac(sha256): %ld\n", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, messagelen); ++ crypto_hash_setkey(tfm, key, keylen); ++ crypto_hash_digest(&desc, &sg, messagelen, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++#endif /* DWC_CRYPTOLIB */ ++ ++ ++/* Byte Ordering Conversions */ ++ ++uint32_t DWC_CPU_TO_LE32(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_CPU_TO_BE32(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_LE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_BE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint16_t DWC_CPU_TO_LE16(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_CPU_TO_BE16(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_LE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_BE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++ ++/* Registers */ ++ ++uint32_t DWC_READ_REG32(uint32_t volatile *reg) ++{ ++ return readl(reg); ++} ++ ++#if 0 ++uint64_t DWC_READ_REG64(uint64_t volatile *reg) ++{ ++} ++#endif ++ ++void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value) ++{ ++ writel(value, reg); ++} ++ ++#if 0 ++void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value) ++{ ++} ++#endif ++ ++void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask) ++{ ++ writel((readl(reg) & ~clear_mask) | set_mask, reg); ++} ++ ++#if 0 ++void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask) ++{ ++} ++#endif ++ ++ ++/* Locking */ ++ ++dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void) ++{ ++ spinlock_t *sl = (spinlock_t *)1; ++ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ sl = DWC_ALLOC(sizeof(*sl)); ++ if (!sl) { ++ DWC_ERROR("Cannot allocate memory for spinlock\n"); ++ return NULL; ++ } ++ ++ spin_lock_init(sl); ++#endif ++ return (dwc_spinlock_t *)sl; ++} ++ ++void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock) ++{ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ DWC_FREE(lock); ++#endif ++} ++ ++void DWC_SPINLOCK(dwc_spinlock_t *lock) ++{ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ spin_lock((spinlock_t *)lock); ++#endif ++} ++ ++void DWC_SPINUNLOCK(dwc_spinlock_t *lock) ++{ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ spin_unlock((spinlock_t *)lock); ++#endif ++} ++ ++void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags) ++{ ++ dwc_irqflags_t f; ++ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ spin_lock_irqsave((spinlock_t *)lock, f); ++#else ++ local_irq_save(f); ++#endif ++ *flags = f; ++} ++ ++void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags) ++{ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ spin_unlock_irqrestore((spinlock_t *)lock, flags); ++#else ++ local_irq_restore(flags); ++#endif ++} ++ ++dwc_mutex_t *DWC_MUTEX_ALLOC(void) ++{ ++ struct mutex *m; ++ dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); ++ ++ if (!mutex) { ++ DWC_ERROR("Cannot allocate memory for mutex\n"); ++ return NULL; ++ } ++ ++ m = (struct mutex *)mutex; ++ mutex_init(m); ++ return mutex; ++} ++ ++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++#else ++void DWC_MUTEX_FREE(dwc_mutex_t *mutex) ++{ ++ mutex_destroy((struct mutex *)mutex); ++ DWC_FREE(mutex); ++} ++#endif ++ ++void DWC_MUTEX_LOCK(dwc_mutex_t *mutex) ++{ ++ struct mutex *m = (struct mutex *)mutex; ++ mutex_lock(m); ++} ++ ++int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex) ++{ ++ struct mutex *m = (struct mutex *)mutex; ++ return mutex_trylock(m); ++} ++ ++void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex) ++{ ++ struct mutex *m = (struct mutex *)mutex; ++ mutex_unlock(m); ++} ++ ++ ++/* Timing */ ++ ++void DWC_UDELAY(uint32_t usecs) ++{ ++ udelay(usecs); ++} ++ ++void DWC_MDELAY(uint32_t msecs) ++{ ++ if (in_interrupt()) ++ mdelay(msecs); ++ else ++ msleep(msecs); ++} ++ ++void DWC_MSLEEP(uint32_t msecs) ++{ ++ msleep(msecs); ++} ++ ++uint32_t DWC_TIME(void) ++{ ++ return jiffies_to_msecs(jiffies); ++} ++ ++ ++/* Timers */ ++ ++struct dwc_timer { ++ struct timer_list *t; ++ char *name; ++ dwc_timer_callback_t cb; ++ void *data; ++ uint8_t scheduled; ++ dwc_spinlock_t *lock; ++}; ++ ++static void timer_callback(unsigned long data) ++{ ++ dwc_timer_t *timer = (dwc_timer_t *)data; ++ dwc_irqflags_t flags; ++ ++ DWC_SPINLOCK_IRQSAVE(timer->lock, &flags); ++ timer->scheduled = 0; ++ DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags); ++ DWC_DEBUG("Timer %s callback", timer->name); ++ timer->cb(timer->data); ++} ++ ++dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data) ++{ ++ dwc_timer_t *t = DWC_ALLOC(sizeof(*t)); ++ ++ if (!t) { ++ DWC_ERROR("Cannot allocate memory for timer"); ++ return NULL; ++ } ++ ++ t->t = DWC_ALLOC(sizeof(*t->t)); ++ if (!t->t) { ++ DWC_ERROR("Cannot allocate memory for timer->t"); ++ goto no_timer; ++ } ++ ++ t->name = DWC_STRDUP(name); ++ if (!t->name) { ++ DWC_ERROR("Cannot allocate memory for timer->name"); ++ goto no_name; ++ } ++ ++ t->lock = DWC_SPINLOCK_ALLOC(); ++ if (!t->lock) { ++ DWC_ERROR("Cannot allocate memory for lock"); ++ goto no_lock; ++ } ++ ++ t->scheduled = 0; ++ t->t->base = &boot_tvec_bases; ++ t->t->expires = jiffies; ++ setup_timer(t->t, timer_callback, (unsigned long)t); ++ ++ t->cb = cb; ++ t->data = data; ++ ++ return t; ++ ++ no_lock: ++ DWC_FREE(t->name); ++ no_name: ++ DWC_FREE(t->t); ++ no_timer: ++ DWC_FREE(t); ++ return NULL; ++} ++ ++void DWC_TIMER_FREE(dwc_timer_t *timer) ++{ ++ dwc_irqflags_t flags; ++ ++ DWC_SPINLOCK_IRQSAVE(timer->lock, &flags); ++ ++ if (timer->scheduled) { ++ del_timer(timer->t); ++ timer->scheduled = 0; ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags); ++ DWC_SPINLOCK_FREE(timer->lock); ++ DWC_FREE(timer->t); ++ DWC_FREE(timer->name); ++ DWC_FREE(timer); ++} ++ ++void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time) ++{ ++ dwc_irqflags_t flags; ++ ++ DWC_SPINLOCK_IRQSAVE(timer->lock, &flags); ++ ++ if (!timer->scheduled) { ++ timer->scheduled = 1; ++ DWC_DEBUG("Scheduling timer %s to expire in +%d msec", timer->name, time); ++ timer->t->expires = jiffies + msecs_to_jiffies(time); ++ add_timer(timer->t); ++ } else { ++ DWC_DEBUG("Modifying timer %s to expire in +%d msec", timer->name, time); ++ mod_timer(timer->t, jiffies + msecs_to_jiffies(time)); ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags); ++} ++ ++void DWC_TIMER_CANCEL(dwc_timer_t *timer) ++{ ++ del_timer(timer->t); ++} ++ ++ ++/* Wait Queues */ ++ ++struct dwc_waitq { ++ wait_queue_head_t queue; ++ int abort; ++}; ++ ++dwc_waitq_t *DWC_WAITQ_ALLOC(void) ++{ ++ dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ DWC_ERROR("Cannot allocate memory for waitqueue\n"); ++ return NULL; ++ } ++ ++ init_waitqueue_head(&wq->queue); ++ wq->abort = 0; ++ return wq; ++} ++ ++void DWC_WAITQ_FREE(dwc_waitq_t *wq) ++{ ++ DWC_FREE(wq); ++} ++ ++int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data) ++{ ++ int result = wait_event_interruptible(wq->queue, ++ cond(data) || wq->abort); ++ if (result == -ERESTARTSYS) { ++ wq->abort = 0; ++ return -DWC_E_RESTART; ++ } ++ ++ if (wq->abort == 1) { ++ wq->abort = 0; ++ return -DWC_E_ABORT; ++ } ++ ++ wq->abort = 0; ++ ++ if (result == 0) { ++ return 0; ++ } ++ ++ return -DWC_E_UNKNOWN; ++} ++ ++int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, ++ void *data, int32_t msecs) ++{ ++ int32_t tmsecs; ++ int result = wait_event_interruptible_timeout(wq->queue, ++ cond(data) || wq->abort, ++ msecs_to_jiffies(msecs)); ++ if (result == -ERESTARTSYS) { ++ wq->abort = 0; ++ return -DWC_E_RESTART; ++ } ++ ++ if (wq->abort == 1) { ++ wq->abort = 0; ++ return -DWC_E_ABORT; ++ } ++ ++ wq->abort = 0; ++ ++ if (result > 0) { ++ tmsecs = jiffies_to_msecs(result); ++ if (!tmsecs) { ++ return 1; ++ } ++ ++ return tmsecs; ++ } ++ ++ if (result == 0) { ++ return -DWC_E_TIMEOUT; ++ } ++ ++ return -DWC_E_UNKNOWN; ++} ++ ++void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq) ++{ ++ wq->abort = 0; ++ wake_up_interruptible(&wq->queue); ++} ++ ++void DWC_WAITQ_ABORT(dwc_waitq_t *wq) ++{ ++ wq->abort = 1; ++ wake_up_interruptible(&wq->queue); ++} ++ ++ ++/* Threading */ ++ ++dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data) ++{ ++ struct task_struct *thread = kthread_run(func, data, name); ++ ++ if (thread == ERR_PTR(-ENOMEM)) { ++ return NULL; ++ } ++ ++ return (dwc_thread_t *)thread; ++} ++ ++int DWC_THREAD_STOP(dwc_thread_t *thread) ++{ ++ return kthread_stop((struct task_struct *)thread); ++} ++ ++dwc_bool_t DWC_THREAD_SHOULD_STOP(void) ++{ ++ return kthread_should_stop(); ++} ++ ++ ++/* tasklets ++ - run in interrupt context (cannot sleep) ++ - each tasklet runs on a single CPU ++ - different tasklets can be running simultaneously on different CPUs ++ */ ++struct dwc_tasklet { ++ struct tasklet_struct t; ++ dwc_tasklet_callback_t cb; ++ void *data; ++}; ++ ++static void tasklet_callback(unsigned long data) ++{ ++ dwc_tasklet_t *t = (dwc_tasklet_t *)data; ++ t->cb(t->data); ++} ++ ++dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data) ++{ ++ dwc_tasklet_t *t = DWC_ALLOC(sizeof(*t)); ++ ++ if (t) { ++ t->cb = cb; ++ t->data = data; ++ tasklet_init(&t->t, tasklet_callback, (unsigned long)t); ++ } else { ++ DWC_ERROR("Cannot allocate memory for tasklet\n"); ++ } ++ ++ return t; ++} ++ ++void DWC_TASK_FREE(dwc_tasklet_t *task) ++{ ++ DWC_FREE(task); ++} ++ ++void DWC_TASK_SCHEDULE(dwc_tasklet_t *task) ++{ ++ tasklet_schedule(&task->t); ++} ++ ++ ++/* workqueues ++ - run in process context (can sleep) ++ */ ++typedef struct work_container { ++ dwc_work_callback_t cb; ++ void *data; ++ dwc_workq_t *wq; ++ char *name; ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_ENTRY(work_container) entry; ++#endif ++ struct delayed_work work; ++} work_container_t; ++ ++#ifdef DEBUG ++DWC_CIRCLEQ_HEAD(work_container_queue, work_container); ++#endif ++ ++struct dwc_workq { ++ struct workqueue_struct *wq; ++ dwc_spinlock_t *lock; ++ dwc_waitq_t *waitq; ++ int pending; ++ ++#ifdef DEBUG ++ struct work_container_queue entries; ++#endif ++}; ++ ++static void do_work(struct work_struct *work) ++{ ++ dwc_irqflags_t flags; ++ struct delayed_work *dw = container_of(work, struct delayed_work, work); ++ work_container_t *container = container_of(dw, struct work_container, work); ++ dwc_workq_t *wq = container->wq; ++ ++ container->cb(container->data); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry); ++#endif ++ DWC_DEBUG("Work done: %s, container=%p", container->name, container); ++ if (container->name) { ++ DWC_FREE(container->name); ++ } ++ DWC_FREE(container); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending--; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++} ++ ++static int work_done(void *data) ++{ ++ dwc_workq_t *workq = (dwc_workq_t *)data; ++ return workq->pending == 0; ++} ++ ++int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout) ++{ ++ return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout); ++} ++ ++dwc_workq_t *DWC_WORKQ_ALLOC(char *name) ++{ ++ dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ return NULL; ++ } ++ ++ wq->wq = create_singlethread_workqueue(name); ++ if (!wq->wq) { ++ goto no_wq; ++ } ++ ++ wq->pending = 0; ++ ++ wq->lock = DWC_SPINLOCK_ALLOC(); ++ if (!wq->lock) { ++ goto no_lock; ++ } ++ ++ wq->waitq = DWC_WAITQ_ALLOC(); ++ if (!wq->waitq) { ++ goto no_waitq; ++ } ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_INIT(&wq->entries); ++#endif ++ return wq; ++ ++ no_waitq: ++ DWC_SPINLOCK_FREE(wq->lock); ++ no_lock: ++ destroy_workqueue(wq->wq); ++ no_wq: ++ DWC_FREE(wq); ++ ++ return NULL; ++} ++ ++void DWC_WORKQ_FREE(dwc_workq_t *wq) ++{ ++#ifdef DEBUG ++ if (wq->pending != 0) { ++ struct work_container *wc; ++ DWC_ERROR("Destroying work queue with pending work"); ++ DWC_CIRCLEQ_FOREACH(wc, &wq->entries, entry) { ++ DWC_ERROR("Work %s still pending", wc->name); ++ } ++ } ++#endif ++ destroy_workqueue(wq->wq); ++ DWC_SPINLOCK_FREE(wq->lock); ++ DWC_WAITQ_FREE(wq->waitq); ++ DWC_FREE(wq); ++} ++ ++void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data, ++ char *format, ...) ++{ ++ dwc_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++ ++ container = DWC_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ DWC_ERROR("Cannot allocate memory for container\n"); ++ return; ++ } ++ ++ container->name = DWC_STRDUP(name); ++ if (!container->name) { ++ DWC_ERROR("Cannot allocate memory for container->name\n"); ++ DWC_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ DWC_DEBUG("Queueing work: %s, container=%p", container->name, container); ++ INIT_WORK(&container->work.work, do_work); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); ++#endif ++ queue_work(wq->wq, &container->work.work); ++} ++ ++void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb, ++ void *data, uint32_t time, char *format, ...) ++{ ++ dwc_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++ ++ container = DWC_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ DWC_ERROR("Cannot allocate memory for container\n"); ++ return; ++ } ++ ++ container->name = DWC_STRDUP(name); ++ if (!container->name) { ++ DWC_ERROR("Cannot allocate memory for container->name\n"); ++ DWC_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ DWC_DEBUG("Queueing work: %s, container=%p", container->name, container); ++ INIT_DELAYED_WORK(&container->work, do_work); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); ++#endif ++ queue_delayed_work(wq->wq, &container->work, msecs_to_jiffies(time)); ++} ++ ++int DWC_WORKQ_PENDING(dwc_workq_t *wq) ++{ ++ return wq->pending; ++} ++ ++ ++#ifdef DWC_LIBMODULE ++ ++#ifdef DWC_CCLIB ++/* CC */ ++EXPORT_SYMBOL(dwc_cc_if_alloc); ++EXPORT_SYMBOL(dwc_cc_if_free); ++EXPORT_SYMBOL(dwc_cc_clear); ++EXPORT_SYMBOL(dwc_cc_add); ++EXPORT_SYMBOL(dwc_cc_remove); ++EXPORT_SYMBOL(dwc_cc_change); ++EXPORT_SYMBOL(dwc_cc_data_for_save); ++EXPORT_SYMBOL(dwc_cc_restore_from_data); ++EXPORT_SYMBOL(dwc_cc_match_chid); ++EXPORT_SYMBOL(dwc_cc_match_cdid); ++EXPORT_SYMBOL(dwc_cc_ck); ++EXPORT_SYMBOL(dwc_cc_chid); ++EXPORT_SYMBOL(dwc_cc_cdid); ++EXPORT_SYMBOL(dwc_cc_name); ++#endif /* DWC_CCLIB */ ++ ++#ifdef DWC_CRYPTOLIB ++# ifndef CONFIG_MACH_IPMATE ++/* Modpow */ ++EXPORT_SYMBOL(dwc_modpow); ++ ++/* DH */ ++EXPORT_SYMBOL(dwc_dh_modpow); ++EXPORT_SYMBOL(dwc_dh_derive_keys); ++EXPORT_SYMBOL(dwc_dh_pk); ++# endif /* CONFIG_MACH_IPMATE */ ++ ++/* Crypto */ ++EXPORT_SYMBOL(dwc_wusb_aes_encrypt); ++EXPORT_SYMBOL(dwc_wusb_cmf); ++EXPORT_SYMBOL(dwc_wusb_prf); ++EXPORT_SYMBOL(dwc_wusb_fill_ccm_nonce); ++EXPORT_SYMBOL(dwc_wusb_gen_nonce); ++EXPORT_SYMBOL(dwc_wusb_gen_key); ++EXPORT_SYMBOL(dwc_wusb_gen_mic); ++#endif /* DWC_CRYPTOLIB */ ++ ++/* Notification */ ++#ifdef DWC_NOTIFYLIB ++EXPORT_SYMBOL(dwc_alloc_notification_manager); ++EXPORT_SYMBOL(dwc_free_notification_manager); ++EXPORT_SYMBOL(dwc_register_notifier); ++EXPORT_SYMBOL(dwc_unregister_notifier); ++EXPORT_SYMBOL(dwc_add_observer); ++EXPORT_SYMBOL(dwc_remove_observer); ++EXPORT_SYMBOL(dwc_notify); ++#endif ++ ++/* Memory Debugging Routines */ ++#ifdef DWC_DEBUG_MEMORY ++EXPORT_SYMBOL(dwc_alloc_debug); ++EXPORT_SYMBOL(dwc_alloc_atomic_debug); ++EXPORT_SYMBOL(dwc_free_debug); ++EXPORT_SYMBOL(dwc_dma_alloc_debug); ++EXPORT_SYMBOL(dwc_dma_free_debug); ++#endif ++ ++EXPORT_SYMBOL(DWC_MEMSET); ++EXPORT_SYMBOL(DWC_MEMCPY); ++EXPORT_SYMBOL(DWC_MEMMOVE); ++EXPORT_SYMBOL(DWC_MEMCMP); ++EXPORT_SYMBOL(DWC_STRNCMP); ++EXPORT_SYMBOL(DWC_STRCMP); ++EXPORT_SYMBOL(DWC_STRLEN); ++EXPORT_SYMBOL(DWC_STRCPY); ++EXPORT_SYMBOL(DWC_STRDUP); ++EXPORT_SYMBOL(DWC_ATOI); ++EXPORT_SYMBOL(DWC_ATOUI); ++ ++#ifdef DWC_UTFLIB ++EXPORT_SYMBOL(DWC_UTF8_TO_UTF16LE); ++#endif /* DWC_UTFLIB */ ++ ++EXPORT_SYMBOL(DWC_IN_IRQ); ++EXPORT_SYMBOL(DWC_IN_BH); ++EXPORT_SYMBOL(DWC_VPRINTF); ++EXPORT_SYMBOL(DWC_VSNPRINTF); ++EXPORT_SYMBOL(DWC_PRINTF); ++EXPORT_SYMBOL(DWC_SPRINTF); ++EXPORT_SYMBOL(DWC_SNPRINTF); ++EXPORT_SYMBOL(__DWC_WARN); ++EXPORT_SYMBOL(__DWC_ERROR); ++EXPORT_SYMBOL(DWC_EXCEPTION); ++ ++#ifdef DEBUG ++EXPORT_SYMBOL(__DWC_DEBUG); ++#endif ++ ++EXPORT_SYMBOL(__DWC_DMA_ALLOC); ++EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC); ++EXPORT_SYMBOL(__DWC_DMA_FREE); ++EXPORT_SYMBOL(__DWC_ALLOC); ++EXPORT_SYMBOL(__DWC_ALLOC_ATOMIC); ++EXPORT_SYMBOL(__DWC_FREE); ++ ++#ifdef DWC_CRYPTOLIB ++EXPORT_SYMBOL(DWC_RANDOM_BYTES); ++EXPORT_SYMBOL(DWC_AES_CBC); ++EXPORT_SYMBOL(DWC_SHA256); ++EXPORT_SYMBOL(DWC_HMAC_SHA256); ++#endif ++ ++EXPORT_SYMBOL(DWC_CPU_TO_LE32); ++EXPORT_SYMBOL(DWC_CPU_TO_BE32); ++EXPORT_SYMBOL(DWC_LE32_TO_CPU); ++EXPORT_SYMBOL(DWC_BE32_TO_CPU); ++EXPORT_SYMBOL(DWC_CPU_TO_LE16); ++EXPORT_SYMBOL(DWC_CPU_TO_BE16); ++EXPORT_SYMBOL(DWC_LE16_TO_CPU); ++EXPORT_SYMBOL(DWC_BE16_TO_CPU); ++EXPORT_SYMBOL(DWC_READ_REG32); ++EXPORT_SYMBOL(DWC_WRITE_REG32); ++EXPORT_SYMBOL(DWC_MODIFY_REG32); ++ ++#if 0 ++EXPORT_SYMBOL(DWC_READ_REG64); ++EXPORT_SYMBOL(DWC_WRITE_REG64); ++EXPORT_SYMBOL(DWC_MODIFY_REG64); ++#endif ++ ++EXPORT_SYMBOL(DWC_SPINLOCK_ALLOC); ++EXPORT_SYMBOL(DWC_SPINLOCK_FREE); ++EXPORT_SYMBOL(DWC_SPINLOCK); ++EXPORT_SYMBOL(DWC_SPINUNLOCK); ++EXPORT_SYMBOL(DWC_SPINLOCK_IRQSAVE); ++EXPORT_SYMBOL(DWC_SPINUNLOCK_IRQRESTORE); ++EXPORT_SYMBOL(DWC_MUTEX_ALLOC); ++ ++#if (!defined(DWC_LINUX) || !defined(CONFIG_DEBUG_MUTEXES)) ++EXPORT_SYMBOL(DWC_MUTEX_FREE); ++#endif ++ ++EXPORT_SYMBOL(DWC_MUTEX_LOCK); ++EXPORT_SYMBOL(DWC_MUTEX_TRYLOCK); ++EXPORT_SYMBOL(DWC_MUTEX_UNLOCK); ++EXPORT_SYMBOL(DWC_UDELAY); ++EXPORT_SYMBOL(DWC_MDELAY); ++EXPORT_SYMBOL(DWC_MSLEEP); ++EXPORT_SYMBOL(DWC_TIME); ++EXPORT_SYMBOL(DWC_TIMER_ALLOC); ++EXPORT_SYMBOL(DWC_TIMER_FREE); ++EXPORT_SYMBOL(DWC_TIMER_SCHEDULE); ++EXPORT_SYMBOL(DWC_TIMER_CANCEL); ++EXPORT_SYMBOL(DWC_WAITQ_ALLOC); ++EXPORT_SYMBOL(DWC_WAITQ_FREE); ++EXPORT_SYMBOL(DWC_WAITQ_WAIT); ++EXPORT_SYMBOL(DWC_WAITQ_WAIT_TIMEOUT); ++EXPORT_SYMBOL(DWC_WAITQ_TRIGGER); ++EXPORT_SYMBOL(DWC_WAITQ_ABORT); ++EXPORT_SYMBOL(DWC_THREAD_RUN); ++EXPORT_SYMBOL(DWC_THREAD_STOP); ++EXPORT_SYMBOL(DWC_THREAD_SHOULD_STOP); ++EXPORT_SYMBOL(DWC_TASK_ALLOC); ++EXPORT_SYMBOL(DWC_TASK_FREE); ++EXPORT_SYMBOL(DWC_TASK_SCHEDULE); ++EXPORT_SYMBOL(DWC_WORKQ_WAIT_WORK_DONE); ++EXPORT_SYMBOL(DWC_WORKQ_ALLOC); ++EXPORT_SYMBOL(DWC_WORKQ_FREE); ++EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE); ++EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE_DELAYED); ++EXPORT_SYMBOL(DWC_WORKQ_PENDING); ++ ++static int dwc_common_port_init_module(void) ++{ ++ int result = 0; ++ ++ printk(KERN_DEBUG "Module dwc_common_port init\n" ); ++ ++#ifdef DWC_DEBUG_MEMORY ++ result = dwc_memory_debug_start(NULL); ++ if (result) { ++ printk(KERN_ERR ++ "dwc_memory_debug_start() failed with error %d\n", ++ result); ++ return result; ++ } ++#endif ++ ++#ifdef DWC_NOTIFYLIB ++ result = dwc_alloc_notification_manager(NULL, NULL); ++ if (result) { ++ printk(KERN_ERR ++ "dwc_alloc_notification_manager() failed with error %d\n", ++ result); ++ return result; ++ } ++#endif ++ return result; ++} ++ ++static void dwc_common_port_exit_module(void) ++{ ++ printk(KERN_DEBUG "Module dwc_common_port exit\n" ); ++ ++#ifdef DWC_NOTIFYLIB ++ dwc_free_notification_manager(); ++#endif ++ ++#ifdef DWC_DEBUG_MEMORY ++ dwc_memory_debug_stop(); ++#endif ++} ++ ++module_init(dwc_common_port_init_module); ++module_exit(dwc_common_port_exit_module); ++ ++MODULE_DESCRIPTION("DWC Common Library - Portable version"); ++MODULE_AUTHOR("Synopsys Inc."); ++MODULE_LICENSE ("GPL"); ++ ++#endif /* DWC_LIBMODULE */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_crypto.c b/drivers/usb/gadget/udc/hiudc/dwc_crypto.c +new file mode 100644 +index 0000000..3b03532 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_crypto.c +@@ -0,0 +1,308 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.c $ ++ * $Revision: #5 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS 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. ++ * ========================================================================= */ ++ ++/** @file ++ * This file contains the WUSB cryptographic routines. ++ */ ++ ++#ifdef DWC_CRYPTOLIB ++ ++#include "dwc_crypto.h" ++#include "usb.h" ++ ++#ifdef DEBUG ++static inline void dump_bytes(char *name, uint8_t *bytes, int len) ++{ ++ int i; ++ DWC_PRINTF("%s: ", name); ++ for (i=0; idst == src, then the bytes will be encrypted ++ * in-place. ++ * ++ * @return 0 on success, negative error code on error. ++ */ ++int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst) ++{ ++ u8 block_t[16]; ++ DWC_MEMSET(block_t, 0, 16); ++ ++ return DWC_AES_CBC(src, 16, key, 16, block_t, dst); ++} ++ ++/** ++ * The CCM-MAC-FUNCTION described in section 6.5 of the WUSB spec. ++ * This function takes a data string and returns the encrypted CBC ++ * Counter-mode MIC. ++ * ++ * @param key The 128-bit symmetric key. ++ * @param nonce The CCM nonce. ++ * @param label The unique 14-byte ASCII text label. ++ * @param bytes The byte array to be encrypted. ++ * @param len Length of the byte array. ++ * @param result Byte array to receive the 8-byte encrypted MIC. ++ */ ++void dwc_wusb_cmf(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ u8 block_m[16]; ++ u8 block_x[16]; ++ u8 block_t[8]; ++ int idx, blkNum; ++ u16 la = (u16)(len + 14); ++ ++ /* Set the AES-128 key */ ++ //dwc_aes_setkey(tfm, key, 16); ++ ++ /* Fill block B0 from flags = 0x59, N, and l(m) = 0 */ ++ block_m[0] = 0x59; ++ for (idx = 0; idx < 13; idx++) ++ block_m[idx + 1] = nonce[idx]; ++ block_m[14] = 0; ++ block_m[15] = 0; ++ ++ /* Produce the CBC IV */ ++ dwc_wusb_aes_encrypt(block_m, key, block_x); ++ show_block(block_m, "CBC IV in: ", "\n", 0); ++ show_block(block_x, "CBC IV out:", "\n", 0); ++ ++ /* Fill block B1 from l(a) = Blen + 14, and A */ ++ block_x[0] ^= (u8)(la >> 8); ++ block_x[1] ^= (u8)la; ++ for (idx = 0; idx < 14; idx++) ++ block_x[idx + 2] ^= label[idx]; ++ show_block(block_x, "After xor: ", "b1\n", 16); ++ ++ dwc_wusb_aes_encrypt(block_x, key, block_x); ++ show_block(block_x, "After AES: ", "b1\n", 16); ++ ++ idx = 0; ++ blkNum = 0; ++ ++ /* Fill remaining blocks with B */ ++ while (len-- > 0) { ++ block_x[idx] ^= *bytes++; ++ if (++idx >= 16) { ++ idx = 0; ++ show_block(block_x, "After xor: ", "\n", blkNum); ++ dwc_wusb_aes_encrypt(block_x, key, block_x); ++ show_block(block_x, "After AES: ", "\n", blkNum); ++ blkNum++; ++ } ++ } ++ ++ /* Handle partial last block */ ++ if (idx > 0) { ++ show_block(block_x, "After xor: ", "\n", blkNum); ++ dwc_wusb_aes_encrypt(block_x, key, block_x); ++ show_block(block_x, "After AES: ", "\n", blkNum); ++ } ++ ++ /* Save the MIC tag */ ++ DWC_MEMCPY(block_t, block_x, 8); ++ show_block(block_t, "MIC tag : ", NULL, 8); ++ ++ /* Fill block A0 from flags = 0x01, N, and counter = 0 */ ++ block_m[0] = 0x01; ++ block_m[14] = 0; ++ block_m[15] = 0; ++ ++ /* Encrypt the counter */ ++ dwc_wusb_aes_encrypt(block_m, key, block_x); ++ show_block(block_x, "CTR[MIC] : ", NULL, 8); ++ ++ /* XOR with MIC tag */ ++ for (idx = 0; idx < 8; idx++) { ++ block_t[idx] ^= block_x[idx]; ++ } ++ ++ /* Return result to caller */ ++ DWC_MEMCPY(result, block_t, 8); ++ show_block(result, "CCM-MIC : ", NULL, 8); ++ ++} ++ ++/** ++ * The PRF function described in section 6.5 of the WUSB spec. This function ++ * concatenates MIC values returned from dwc_cmf() to create a value of ++ * the requested length. ++ * ++ * @param prf_len Length of the PRF function in bits (64, 128, or 256). ++ * @param key, nonce, label, bytes, len Same as for dwc_cmf(). ++ * @param result Byte array to receive the result. ++ */ ++void dwc_wusb_prf(int prf_len, u8 *key, ++ u8 *nonce, char *label, u8 *bytes, int len, u8 *result) ++{ ++ int i; ++ ++ nonce[0] = 0; ++ for (i = 0; i < prf_len >> 6; i++, nonce[0]++) { ++ dwc_wusb_cmf(key, nonce, label, bytes, len, result); ++ result += 8; ++ } ++} ++ ++/** ++ * Fills in CCM Nonce per the WUSB spec. ++ * ++ * @param[in] haddr Host address. ++ * @param[in] daddr Device address. ++ * @param[in] tkid Session Key(PTK) identifier. ++ * @param[out] nonce Pointer to where the CCM Nonce output is to be written. ++ */ ++void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid, ++ uint8_t *nonce) ++{ ++ ++ DWC_DEBUG("%s %x %x\n", __func__, daddr, haddr); ++ ++ DWC_MEMSET(&nonce[0], 0, 16); ++ ++ DWC_MEMCPY(&nonce[6], tkid, 3); ++ nonce[9] = daddr & 0xFF; ++ nonce[10] = (daddr >> 8) & 0xFF; ++ nonce[11] = haddr & 0xFF; ++ nonce[12] = (haddr >> 8) & 0xFF; ++ ++ dump_bytes("CCM nonce", nonce, 16); ++} ++ ++/** ++ * Generates a 16-byte cryptographic-grade random number for the Host/Device ++ * Nonce. ++ */ ++void dwc_wusb_gen_nonce(uint16_t addr, uint8_t *nonce) ++{ ++ uint8_t inonce[16]; ++ uint32_t temp[4]; ++ ++ /* Fill in the Nonce */ ++ DWC_MEMSET(&inonce[0], 0, sizeof(inonce)); ++ inonce[9] = addr & 0xFF; ++ inonce[10] = (addr >> 8) & 0xFF; ++ inonce[11] = inonce[9]; ++ inonce[12] = inonce[10]; ++ ++ /* Collect "randomness samples" */ ++ DWC_RANDOM_BYTES((uint8_t *)temp, 16); ++ ++ dwc_wusb_prf_128((uint8_t *)temp, nonce, ++ "Random Numbers", (uint8_t *)temp, sizeof(temp), ++ nonce); ++} ++ ++/** ++ * Generates the Session Key (PTK) and Key Confirmation Key (KCK) per the ++ * WUSB spec. ++ * ++ * @param[in] ccm_nonce Pointer to CCM Nonce. ++ * @param[in] mk Master Key to derive the session from ++ * @param[in] hnonce Pointer to Host Nonce. ++ * @param[in] dnonce Pointer to Device Nonce. ++ * @param[out] kck Pointer to where the KCK output is to be written. ++ * @param[out] ptk Pointer to where the PTK output is to be written. ++ */ ++void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, uint8_t *hnonce, ++ uint8_t *dnonce, uint8_t *kck, uint8_t *ptk) ++{ ++ uint8_t idata[32]; ++ uint8_t odata[32]; ++ ++ dump_bytes("ck", mk, 16); ++ dump_bytes("hnonce", hnonce, 16); ++ dump_bytes("dnonce", dnonce, 16); ++ ++ /* The data is the HNonce and DNonce concatenated */ ++ DWC_MEMCPY(&idata[0], hnonce, 16); ++ DWC_MEMCPY(&idata[16], dnonce, 16); ++ ++ dwc_wusb_prf_256(mk, ccm_nonce, "Pair-wise keys", idata, 32, odata); ++ ++ /* Low 16 bytes of the result is the KCK, high 16 is the PTK */ ++ DWC_MEMCPY(kck, &odata[0], 16); ++ DWC_MEMCPY(ptk, &odata[16], 16); ++ ++ dump_bytes("kck", kck, 16); ++ dump_bytes("ptk", ptk, 16); ++} ++ ++/** ++ * Generates the Message Integrity Code over the Handshake data per the ++ * WUSB spec. ++ * ++ * @param ccm_nonce Pointer to CCM Nonce. ++ * @param kck Pointer to Key Confirmation Key. ++ * @param data Pointer to Handshake data to be checked. ++ * @param mic Pointer to where the MIC output is to be written. ++ */ ++void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t *kck, ++ uint8_t *data, uint8_t *mic) ++{ ++ ++ dwc_wusb_prf_64(kck, ccm_nonce, "out-of-bandMIC", ++ data, WUSB_HANDSHAKE_LEN_FOR_MIC, mic); ++} ++ ++#endif /* DWC_CRYPTOLIB */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_crypto.h b/drivers/usb/gadget/udc/hiudc/dwc_crypto.h +new file mode 100644 +index 0000000..26fcddc +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_crypto.h +@@ -0,0 +1,111 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.h $ ++ * $Revision: #3 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS 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 _DWC_CRYPTO_H_ ++#define _DWC_CRYPTO_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ * ++ * This file contains declarations for the WUSB Cryptographic routines as ++ * defined in the WUSB spec. They are only to be used internally by the DWC UWB ++ * modules. ++ */ ++ ++#include "dwc_os.h" ++ ++int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst); ++ ++void dwc_wusb_cmf(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result); ++void dwc_wusb_prf(int prf_len, u8 *key, ++ u8 *nonce, char *label, u8 *bytes, int len, u8 *result); ++ ++/** ++ * The PRF-64 function described in section 6.5 of the WUSB spec. ++ * ++ * @param key, nonce, label, bytes, len, result Same as for dwc_prf(). ++ */ ++static inline void dwc_wusb_prf_64(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ dwc_wusb_prf(64, key, nonce, label, bytes, len, result); ++} ++ ++/** ++ * The PRF-128 function described in section 6.5 of the WUSB spec. ++ * ++ * @param key, nonce, label, bytes, len, result Same as for dwc_prf(). ++ */ ++static inline void dwc_wusb_prf_128(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ dwc_wusb_prf(128, key, nonce, label, bytes, len, result); ++} ++ ++/** ++ * The PRF-256 function described in section 6.5 of the WUSB spec. ++ * ++ * @param key, nonce, label, bytes, len, result Same as for dwc_prf(). ++ */ ++static inline void dwc_wusb_prf_256(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ dwc_wusb_prf(256, key, nonce, label, bytes, len, result); ++} ++ ++ ++void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid, ++ uint8_t *nonce); ++void dwc_wusb_gen_nonce(uint16_t addr, ++ uint8_t *nonce); ++ ++void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, ++ uint8_t *hnonce, uint8_t *dnonce, ++ uint8_t *kck, uint8_t *ptk); ++ ++ ++void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t ++ *kck, uint8_t *data, uint8_t *mic); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_CRYPTO_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_dh.c b/drivers/usb/gadget/udc/hiudc/dwc_dh.c +new file mode 100644 +index 0000000..2b429a3 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_dh.c +@@ -0,0 +1,291 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.c $ ++ * $Revision: #3 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS 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. ++ * ========================================================================= */ ++#ifdef DWC_CRYPTOLIB ++ ++#ifndef CONFIG_MACH_IPMATE ++ ++#include "dwc_dh.h" ++#include "dwc_modpow.h" ++ ++#ifdef DEBUG ++/* This function prints out a buffer in the format described in the Association ++ * Model specification. */ ++static void dh_dump(char *str, void *_num, int len) ++{ ++ uint8_t *num = _num; ++ int i; ++ DWC_PRINTF("%s\n", str); ++ for (i = 0; i < len; i ++) { ++ DWC_PRINTF("%02x", num[i]); ++ if (((i + 1) % 2) == 0) DWC_PRINTF(" "); ++ if (((i + 1) % 26) == 0) DWC_PRINTF("\n"); ++ } ++ ++ DWC_PRINTF("\n"); ++} ++#else ++#define dh_dump(_x...) do {; } while(0) ++#endif ++ ++/* Constant g value */ ++static __u32 dh_g[] = { ++ 0x02000000, ++}; ++ ++/* Constant p value */ ++static __u32 dh_p[] = { ++ 0xFFFFFFFF, 0xFFFFFFFF, 0xA2DA0FC9, 0x34C26821, 0x8B62C6C4, 0xD11CDC80, 0x084E0229, 0x74CC678A, ++ 0xA6BE0B02, 0x229B133B, 0x79084A51, 0xDD04348E, 0xB31995EF, 0x1B433ACD, 0x6D0A2B30, 0x37145FF2, ++ 0x6D35E14F, 0x45C2516D, 0x76B585E4, 0xC67E5E62, 0xE9424CF4, 0x6BED37A6, 0xB65CFF0B, 0xEDB706F4, ++ 0xFB6B38EE, 0xA59F895A, 0x11249FAE, 0xE61F4B7C, 0x51662849, 0x3D5BE4EC, 0xB87C00C2, 0x05BF63A1, ++ 0x3648DA98, 0x9AD3551C, 0xA83F1669, 0x5FCF24FD, 0x235D6583, 0x96ADA3DC, 0x56F3621C, 0xBB528520, ++ 0x0729D59E, 0x6D969670, 0x4E350C67, 0x0498BC4A, 0x086C74F1, 0x7C2118CA, 0x465E9032, 0x3BCE362E, ++ 0x2C779EE3, 0x03860E18, 0xA283279B, 0x8FA207EC, 0xF05DC5B5, 0xC9524C6F, 0xF6CB2BDE, 0x18175895, ++ 0x7C499539, 0xE56A95EA, 0x1826D215, 0x1005FA98, 0x5A8E7215, 0x2DC4AA8A, 0x0D1733AD, 0x337A5004, ++ 0xAB2155A8, 0x64BA1CDF, 0x0485FBEC, 0x0AEFDB58, 0x5771EA8A, 0x7D0C065D, 0x850F97B3, 0xC7E4E1A6, ++ 0x8CAEF5AB, 0xD73309DB, 0xE0948C1E, 0x9D61254A, 0x26D2E3CE, 0x6BEED21A, 0x06FA2FF1, 0x64088AD9, ++ 0x730276D8, 0x646AC83E, 0x182B1F52, 0x0C207B17, 0x5717E1BB, 0x6C5D617A, 0xC0880977, 0xE246D9BA, ++ 0xA04FE208, 0x31ABE574, 0xFC5BDB43, 0x8E10FDE0, 0x20D1824B, 0xCAD23AA9, 0xFFFFFFFF, 0xFFFFFFFF, ++}; ++ ++static void dh_swap_bytes(void *_in, void *_out, uint32_t len) ++{ ++ uint8_t *in = _in; ++ uint8_t *out = _out; ++ int i; ++ for (i=0; inext = (link); \ ++ (link)->prev = (link); \ ++} while (0) ++ ++#define DWC_LIST_FIRST(link) ((link)->next) ++#define DWC_LIST_LAST(link) ((link)->prev) ++#define DWC_LIST_END(link) (link) ++#define DWC_LIST_NEXT(link) ((link)->next) ++#define DWC_LIST_PREV(link) ((link)->prev) ++#define DWC_LIST_EMPTY(link) \ ++ (DWC_LIST_FIRST(link) == DWC_LIST_END(link)) ++#define DWC_LIST_ENTRY(link, type, field) \ ++ (type *)((uint8_t *)(link) - (size_t)(&((type *)0)->field)) ++ ++#if 0 ++#define DWC_LIST_INSERT_HEAD(list, link) do { \ ++ (link)->next = (list)->next; \ ++ (link)->prev = (list); \ ++ (list)->next->prev = (link); \ ++ (list)->next = (link); \ ++} while (0) ++ ++#define DWC_LIST_INSERT_TAIL(list, link) do { \ ++ (link)->next = (list); \ ++ (link)->prev = (list)->prev; \ ++ (list)->prev->next = (link); \ ++ (list)->prev = (link); \ ++} while (0) ++#else ++#define DWC_LIST_INSERT_HEAD(list, link) do { \ ++ dwc_list_link_t *__next__ = (list)->next; \ ++ __next__->prev = (link); \ ++ (link)->next = __next__; \ ++ (link)->prev = (list); \ ++ (list)->next = (link); \ ++} while (0) ++ ++#define DWC_LIST_INSERT_TAIL(list, link) do { \ ++ dwc_list_link_t *__prev__ = (list)->prev; \ ++ (list)->prev = (link); \ ++ (link)->next = (list); \ ++ (link)->prev = __prev__; \ ++ __prev__->next = (link); \ ++} while (0) ++#endif ++ ++#if 0 ++static inline void __list_add(struct list_head *new, ++ struct list_head *prev, ++ struct list_head *next) ++{ ++ next->prev = new; ++ new->next = next; ++ new->prev = prev; ++ prev->next = new; ++} ++ ++static inline void list_add(struct list_head *new, struct list_head *head) ++{ ++ __list_add(new, head, head->next); ++} ++ ++static inline void list_add_tail(struct list_head *new, struct list_head *head) ++{ ++ __list_add(new, head->prev, head); ++} ++ ++static inline void __list_del(struct list_head * prev, struct list_head * next) ++{ ++ next->prev = prev; ++ prev->next = next; ++} ++ ++static inline void list_del(struct list_head *entry) ++{ ++ __list_del(entry->prev, entry->next); ++ entry->next = LIST_POISON1; ++ entry->prev = LIST_POISON2; ++} ++#endif ++ ++#define DWC_LIST_REMOVE(link) do { \ ++ (link)->next->prev = (link)->prev; \ ++ (link)->prev->next = (link)->next; \ ++} while (0) ++ ++#define DWC_LIST_REMOVE_INIT(link) do { \ ++ DWC_LIST_REMOVE(link); \ ++ DWC_LIST_INIT(link); \ ++} while (0) ++ ++#define DWC_LIST_MOVE_HEAD(list, link) do { \ ++ DWC_LIST_REMOVE(link); \ ++ DWC_LIST_INSERT_HEAD(list, link); \ ++} while (0) ++ ++#define DWC_LIST_MOVE_TAIL(list, link) do { \ ++ DWC_LIST_REMOVE(link); \ ++ DWC_LIST_INSERT_TAIL(list, link); \ ++} while (0) ++ ++#define DWC_LIST_FOREACH(var, list) \ ++ for((var) = DWC_LIST_FIRST(list); \ ++ (var) != DWC_LIST_END(list); \ ++ (var) = DWC_LIST_NEXT(var)) ++ ++#define DWC_LIST_FOREACH_SAFE(var, var2, list) \ ++ for((var) = DWC_LIST_FIRST(list), (var2) = DWC_LIST_NEXT(var); \ ++ (var) != DWC_LIST_END(list); \ ++ (var) = (var2), (var2) = DWC_LIST_NEXT(var2)) ++ ++#define DWC_LIST_FOREACH_REVERSE(var, list) \ ++ for((var) = DWC_LIST_LAST(list); \ ++ (var) != DWC_LIST_END(list); \ ++ (var) = DWC_LIST_PREV(var)) ++ ++/* ++ * Singly-linked List definitions. ++ */ ++#define DWC_SLIST_HEAD(name, type) \ ++struct name { \ ++ struct type *slh_first; /* first element */ \ ++} ++ ++#define DWC_SLIST_HEAD_INITIALIZER(head) \ ++ { NULL } ++ ++#define DWC_SLIST_ENTRY(type) \ ++struct { \ ++ struct type *sle_next; /* next element */ \ ++} ++ ++/* ++ * Singly-linked List access methods. ++ */ ++#define DWC_SLIST_FIRST(head) ((head)->slh_first) ++#define DWC_SLIST_END(head) NULL ++#define DWC_SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) ++#define DWC_SLIST_NEXT(elm, field) ((elm)->field.sle_next) ++ ++#define DWC_SLIST_FOREACH(var, head, field) \ ++ for((var) = SLIST_FIRST(head); \ ++ (var) != SLIST_END(head); \ ++ (var) = SLIST_NEXT(var, field)) ++ ++#define DWC_SLIST_FOREACH_PREVPTR(var, varp, head, field) \ ++ for((varp) = &SLIST_FIRST((head)); \ ++ ((var) = *(varp)) != SLIST_END(head); \ ++ (varp) = &SLIST_NEXT((var), field)) ++ ++/* ++ * Singly-linked List functions. ++ */ ++#define DWC_SLIST_INIT(head) { \ ++ SLIST_FIRST(head) = SLIST_END(head); \ ++} ++ ++#define DWC_SLIST_INSERT_AFTER(slistelm, elm, field) do { \ ++ (elm)->field.sle_next = (slistelm)->field.sle_next; \ ++ (slistelm)->field.sle_next = (elm); \ ++} while (0) ++ ++#define DWC_SLIST_INSERT_HEAD(head, elm, field) do { \ ++ (elm)->field.sle_next = (head)->slh_first; \ ++ (head)->slh_first = (elm); \ ++} while (0) ++ ++#define DWC_SLIST_REMOVE_NEXT(head, elm, field) do { \ ++ (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ ++} while (0) ++ ++#define DWC_SLIST_REMOVE_HEAD(head, field) do { \ ++ (head)->slh_first = (head)->slh_first->field.sle_next; \ ++} while (0) ++ ++#define DWC_SLIST_REMOVE(head, elm, type, field) do { \ ++ if ((head)->slh_first == (elm)) { \ ++ SLIST_REMOVE_HEAD((head), field); \ ++ } \ ++ else { \ ++ struct type *curelm = (head)->slh_first; \ ++ while( curelm->field.sle_next != (elm) ) \ ++ curelm = curelm->field.sle_next; \ ++ curelm->field.sle_next = \ ++ curelm->field.sle_next->field.sle_next; \ ++ } \ ++} while (0) ++ ++/* ++ * Simple queue definitions. ++ */ ++#define DWC_SIMPLEQ_HEAD(name, type) \ ++struct name { \ ++ struct type *sqh_first; /* first element */ \ ++ struct type **sqh_last; /* addr of last next element */ \ ++} ++ ++#define DWC_SIMPLEQ_HEAD_INITIALIZER(head) \ ++ { NULL, &(head).sqh_first } ++ ++#define DWC_SIMPLEQ_ENTRY(type) \ ++struct { \ ++ struct type *sqe_next; /* next element */ \ ++} ++ ++/* ++ * Simple queue access methods. ++ */ ++#define DWC_SIMPLEQ_FIRST(head) ((head)->sqh_first) ++#define DWC_SIMPLEQ_END(head) NULL ++#define DWC_SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) ++#define DWC_SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) ++ ++#define DWC_SIMPLEQ_FOREACH(var, head, field) \ ++ for((var) = SIMPLEQ_FIRST(head); \ ++ (var) != SIMPLEQ_END(head); \ ++ (var) = SIMPLEQ_NEXT(var, field)) ++ ++/* ++ * Simple queue functions. ++ */ ++#define DWC_SIMPLEQ_INIT(head) do { \ ++ (head)->sqh_first = NULL; \ ++ (head)->sqh_last = &(head)->sqh_first; \ ++} while (0) ++ ++#define DWC_SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ ++ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ ++ (head)->sqh_last = &(elm)->field.sqe_next; \ ++ (head)->sqh_first = (elm); \ ++} while (0) ++ ++#define DWC_SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ ++ (elm)->field.sqe_next = NULL; \ ++ *(head)->sqh_last = (elm); \ ++ (head)->sqh_last = &(elm)->field.sqe_next; \ ++} while (0) ++ ++#define DWC_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ ++ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ ++ (head)->sqh_last = &(elm)->field.sqe_next; \ ++ (listelm)->field.sqe_next = (elm); \ ++} while (0) ++ ++#define DWC_SIMPLEQ_REMOVE_HEAD(head, field) do { \ ++ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ ++ (head)->sqh_last = &(head)->sqh_first; \ ++} while (0) ++ ++/* ++ * Tail queue definitions. ++ */ ++#define DWC_TAILQ_HEAD(name, type) \ ++struct name { \ ++ struct type *tqh_first; /* first element */ \ ++ struct type **tqh_last; /* addr of last next element */ \ ++} ++ ++#define DWC_TAILQ_HEAD_INITIALIZER(head) \ ++ { NULL, &(head).tqh_first } ++ ++#define DWC_TAILQ_ENTRY(type) \ ++struct { \ ++ struct type *tqe_next; /* next element */ \ ++ struct type **tqe_prev; /* address of previous next element */ \ ++} ++ ++/* ++ * tail queue access methods ++ */ ++#define DWC_TAILQ_FIRST(head) ((head)->tqh_first) ++#define DWC_TAILQ_END(head) NULL ++#define DWC_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) ++#define DWC_TAILQ_LAST(head, headname) \ ++ (*(((struct headname *)((head)->tqh_last))->tqh_last)) ++/* XXX */ ++#define DWC_TAILQ_PREV(elm, headname, field) \ ++ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) ++#define DWC_TAILQ_EMPTY(head) \ ++ (TAILQ_FIRST(head) == TAILQ_END(head)) ++ ++#define DWC_TAILQ_FOREACH(var, head, field) \ ++ for((var) = TAILQ_FIRST(head); \ ++ (var) != TAILQ_END(head); \ ++ (var) = TAILQ_NEXT(var, field)) ++ ++#define DWC_TAILQ_FOREACH_REVERSE(var, head, headname, field) \ ++ for((var) = TAILQ_LAST(head, headname); \ ++ (var) != TAILQ_END(head); \ ++ (var) = TAILQ_PREV(var, headname, field)) ++ ++/* ++ * Tail queue functions. ++ */ ++#define DWC_TAILQ_INIT(head) do { \ ++ (head)->tqh_first = NULL; \ ++ (head)->tqh_last = &(head)->tqh_first; \ ++} while (0) ++ ++#define DWC_TAILQ_INSERT_HEAD(head, elm, field) do { \ ++ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ ++ (head)->tqh_first->field.tqe_prev = \ ++ &(elm)->field.tqe_next; \ ++ else \ ++ (head)->tqh_last = &(elm)->field.tqe_next; \ ++ (head)->tqh_first = (elm); \ ++ (elm)->field.tqe_prev = &(head)->tqh_first; \ ++} while (0) ++ ++#define DWC_TAILQ_INSERT_TAIL(head, elm, field) do { \ ++ (elm)->field.tqe_next = NULL; \ ++ (elm)->field.tqe_prev = (head)->tqh_last; \ ++ *(head)->tqh_last = (elm); \ ++ (head)->tqh_last = &(elm)->field.tqe_next; \ ++} while (0) ++ ++#define DWC_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ ++ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ ++ (elm)->field.tqe_next->field.tqe_prev = \ ++ &(elm)->field.tqe_next; \ ++ else \ ++ (head)->tqh_last = &(elm)->field.tqe_next; \ ++ (listelm)->field.tqe_next = (elm); \ ++ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ ++} while (0) ++ ++#define DWC_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ ++ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ ++ (elm)->field.tqe_next = (listelm); \ ++ *(listelm)->field.tqe_prev = (elm); \ ++ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ ++} while (0) ++ ++#define DWC_TAILQ_REMOVE(head, elm, field) do { \ ++ if (((elm)->field.tqe_next) != NULL) \ ++ (elm)->field.tqe_next->field.tqe_prev = \ ++ (elm)->field.tqe_prev; \ ++ else \ ++ (head)->tqh_last = (elm)->field.tqe_prev; \ ++ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ ++} while (0) ++ ++#define DWC_TAILQ_REPLACE(head, elm, elm2, field) do { \ ++ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ ++ (elm2)->field.tqe_next->field.tqe_prev = \ ++ &(elm2)->field.tqe_next; \ ++ else \ ++ (head)->tqh_last = &(elm2)->field.tqe_next; \ ++ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ ++ *(elm2)->field.tqe_prev = (elm2); \ ++} while (0) ++ ++/* ++ * Circular queue definitions. ++ */ ++#define DWC_CIRCLEQ_HEAD(name, type) \ ++struct name { \ ++ struct type *cqh_first; /* first element */ \ ++ struct type *cqh_last; /* last element */ \ ++} ++ ++#define DWC_CIRCLEQ_HEAD_INITIALIZER(head) \ ++ { DWC_CIRCLEQ_END(&head), DWC_CIRCLEQ_END(&head) } ++ ++#define DWC_CIRCLEQ_ENTRY(type) \ ++struct { \ ++ struct type *cqe_next; /* next element */ \ ++ struct type *cqe_prev; /* previous element */ \ ++} ++ ++/* ++ * Circular queue access methods ++ */ ++#define DWC_CIRCLEQ_FIRST(head) ((head)->cqh_first) ++#define DWC_CIRCLEQ_LAST(head) ((head)->cqh_last) ++#define DWC_CIRCLEQ_END(head) ((void *)(head)) ++#define DWC_CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) ++#define DWC_CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) ++#define DWC_CIRCLEQ_EMPTY(head) \ ++ (DWC_CIRCLEQ_FIRST(head) == DWC_CIRCLEQ_END(head)) ++ ++#define DWC_CIRCLEQ_EMPTY_ENTRY(elm, field) (((elm)->field.cqe_next == NULL) && ((elm)->field.cqe_prev == NULL)) ++ ++#define DWC_CIRCLEQ_FOREACH(var, head, field) \ ++ for((var) = DWC_CIRCLEQ_FIRST(head); \ ++ (var) != DWC_CIRCLEQ_END(head); \ ++ (var) = DWC_CIRCLEQ_NEXT(var, field)) ++ ++#define DWC_CIRCLEQ_FOREACH_SAFE(var, var2, head, field) \ ++ for((var) = DWC_CIRCLEQ_FIRST(head), var2 = DWC_CIRCLEQ_NEXT(var, field); \ ++ (var) != DWC_CIRCLEQ_END(head); \ ++ (var) = var2, var2 = DWC_CIRCLEQ_NEXT(var, field)) ++ ++#define DWC_CIRCLEQ_FOREACH_REVERSE(var, head, field) \ ++ for((var) = DWC_CIRCLEQ_LAST(head); \ ++ (var) != DWC_CIRCLEQ_END(head); \ ++ (var) = DWC_CIRCLEQ_PREV(var, field)) ++ ++/* ++ * Circular queue functions. ++ */ ++#define DWC_CIRCLEQ_INIT(head) do { \ ++ (head)->cqh_first = DWC_CIRCLEQ_END(head); \ ++ (head)->cqh_last = DWC_CIRCLEQ_END(head); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INIT_ENTRY(elm, field) do { \ ++ (elm)->field.cqe_next = NULL; \ ++ (elm)->field.cqe_prev = NULL; \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ ++ (elm)->field.cqe_next = (listelm)->field.cqe_next; \ ++ (elm)->field.cqe_prev = (listelm); \ ++ if ((listelm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_last = (elm); \ ++ else \ ++ (listelm)->field.cqe_next->field.cqe_prev = (elm); \ ++ (listelm)->field.cqe_next = (elm); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ ++ (elm)->field.cqe_next = (listelm); \ ++ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ ++ if ((listelm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_first = (elm); \ ++ else \ ++ (listelm)->field.cqe_prev->field.cqe_next = (elm); \ ++ (listelm)->field.cqe_prev = (elm); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ ++ (elm)->field.cqe_next = (head)->cqh_first; \ ++ (elm)->field.cqe_prev = DWC_CIRCLEQ_END(head); \ ++ if ((head)->cqh_last == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_last = (elm); \ ++ else \ ++ (head)->cqh_first->field.cqe_prev = (elm); \ ++ (head)->cqh_first = (elm); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ ++ (elm)->field.cqe_next = DWC_CIRCLEQ_END(head); \ ++ (elm)->field.cqe_prev = (head)->cqh_last; \ ++ if ((head)->cqh_first == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_first = (elm); \ ++ else \ ++ (head)->cqh_last->field.cqe_next = (elm); \ ++ (head)->cqh_last = (elm); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_REMOVE(head, elm, field) do { \ ++ if ((elm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_last = (elm)->field.cqe_prev; \ ++ else \ ++ (elm)->field.cqe_next->field.cqe_prev = \ ++ (elm)->field.cqe_prev; \ ++ if ((elm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_first = (elm)->field.cqe_next; \ ++ else \ ++ (elm)->field.cqe_prev->field.cqe_next = \ ++ (elm)->field.cqe_next; \ ++} while (0) ++ ++#define DWC_CIRCLEQ_REMOVE_INIT(head, elm, field) do { \ ++ DWC_CIRCLEQ_REMOVE(head, elm, field); \ ++ DWC_CIRCLEQ_INIT_ENTRY(elm, field); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ ++ if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ ++ DWC_CIRCLEQ_END(head)) \ ++ (head).cqh_last = (elm2); \ ++ else \ ++ (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ ++ if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ ++ DWC_CIRCLEQ_END(head)) \ ++ (head).cqh_first = (elm2); \ ++ else \ ++ (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ ++} while (0) ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_LIST_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_mem.c b/drivers/usb/gadget/udc/hiudc/dwc_mem.c +new file mode 100644 +index 0000000..ad645ff +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_mem.c +@@ -0,0 +1,245 @@ ++/* Memory Debugging */ ++#ifdef DWC_DEBUG_MEMORY ++ ++#include "dwc_os.h" ++#include "dwc_list.h" ++ ++struct allocation { ++ void *addr; ++ void *ctx; ++ char *func; ++ int line; ++ uint32_t size; ++ int dma; ++ DWC_CIRCLEQ_ENTRY(allocation) entry; ++}; ++ ++DWC_CIRCLEQ_HEAD(allocation_queue, allocation); ++ ++struct allocation_manager { ++ void *mem_ctx; ++ struct allocation_queue allocations; ++ ++ /* statistics */ ++ int num; ++ int num_freed; ++ int num_active; ++ uint32_t total; ++ uint32_t cur; ++ uint32_t max; ++}; ++ ++static struct allocation_manager *manager = NULL; ++ ++static int add_allocation(void *ctx, uint32_t size, char const *func, int line, void *addr, ++ int dma) ++{ ++ struct allocation *a; ++ ++ DWC_ASSERT(manager != NULL, "manager not allocated"); ++ ++ a = __DWC_ALLOC_ATOMIC(manager->mem_ctx, sizeof(*a)); ++ if (!a) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ a->func = __DWC_ALLOC_ATOMIC(manager->mem_ctx, DWC_STRLEN(func) + 1); ++ if (!a->func) { ++ __DWC_FREE(manager->mem_ctx, a); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ DWC_MEMCPY(a->func, func, DWC_STRLEN(func) + 1); ++ a->addr = addr; ++ a->ctx = ctx; ++ a->line = line; ++ a->size = size; ++ a->dma = dma; ++ DWC_CIRCLEQ_INSERT_TAIL(&manager->allocations, a, entry); ++ ++ /* Update stats */ ++ manager->num++; ++ manager->num_active++; ++ manager->total += size; ++ manager->cur += size; ++ ++ if (manager->max < manager->cur) { ++ manager->max = manager->cur; ++ } ++ ++ return 0; ++} ++ ++static struct allocation *find_allocation(void *ctx, void *addr) ++{ ++ struct allocation *a; ++ ++ DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { ++ if (a->ctx == ctx && a->addr == addr) { ++ return a; ++ } ++ } ++ ++ return NULL; ++} ++ ++static void free_allocation(void *ctx, void *addr, char const *func, int line) ++{ ++ struct allocation *a = find_allocation(ctx, addr); ++ ++ if (!a) { ++ DWC_ASSERT(0, ++ "Free of address %p that was never allocated or already freed %s:%d", ++ addr, func, line); ++ return; ++ } ++ ++ DWC_CIRCLEQ_REMOVE(&manager->allocations, a, entry); ++ ++ manager->num_active--; ++ manager->num_freed++; ++ manager->cur -= a->size; ++ __DWC_FREE(manager->mem_ctx, a->func); ++ __DWC_FREE(manager->mem_ctx, a); ++} ++ ++int dwc_memory_debug_start(void *mem_ctx) ++{ ++ DWC_ASSERT(manager == NULL, "Memory debugging has already started\n"); ++ ++ if (manager) { ++ return -DWC_E_BUSY; ++ } ++ ++ manager = __DWC_ALLOC(mem_ctx, sizeof(*manager)); ++ if (!manager) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ DWC_CIRCLEQ_INIT(&manager->allocations); ++ manager->mem_ctx = mem_ctx; ++ manager->num = 0; ++ manager->num_freed = 0; ++ manager->num_active = 0; ++ manager->total = 0; ++ manager->cur = 0; ++ manager->max = 0; ++ ++ return 0; ++} ++ ++void dwc_memory_debug_stop(void) ++{ ++ struct allocation *a; ++ ++ dwc_memory_debug_report(); ++ ++ DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { ++ DWC_ERROR("Memory leaked from %s:%d\n", a->func, a->line); ++ free_allocation(a->ctx, a->addr, NULL, -1); ++ } ++ ++ __DWC_FREE(manager->mem_ctx, manager); ++} ++ ++void dwc_memory_debug_report(void) ++{ ++ struct allocation *a; ++ ++ DWC_PRINTF("\n\n\n----------------- Memory Debugging Report -----------------\n\n"); ++ DWC_PRINTF("Num Allocations = %d\n", manager->num); ++ DWC_PRINTF("Freed = %d\n", manager->num_freed); ++ DWC_PRINTF("Active = %d\n", manager->num_active); ++ DWC_PRINTF("Current Memory Used = %d\n", manager->cur); ++ DWC_PRINTF("Total Memory Used = %d\n", manager->total); ++ DWC_PRINTF("Maximum Memory Used at Once = %d\n", manager->max); ++ DWC_PRINTF("Unfreed allocations:\n"); ++ ++ DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { ++ DWC_PRINTF(" addr=%p, size=%d from %s:%d, DMA=%d\n", ++ a->addr, a->size, a->func, a->line, a->dma); ++ } ++} ++ ++/* The replacement functions */ ++void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line) ++{ ++ void *addr = __DWC_ALLOC(mem_ctx, size); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(mem_ctx, size, func, line, addr, 0)) { ++ __DWC_FREE(mem_ctx, addr); ++ return NULL; ++ } ++ ++ return addr; ++} ++ ++void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, ++ int line) ++{ ++ void *addr = __DWC_ALLOC_ATOMIC(mem_ctx, size); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(mem_ctx, size, func, line, addr, 0)) { ++ __DWC_FREE(mem_ctx, addr); ++ return NULL; ++ } ++ ++ return addr; ++} ++ ++void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line) ++{ ++ free_allocation(mem_ctx, addr, func, line); ++ __DWC_FREE(mem_ctx, addr); ++} ++ ++void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr, ++ char const *func, int line) ++{ ++ void *addr = __DWC_DMA_ALLOC(dma_ctx, size, dma_addr); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(dma_ctx, size, func, line, addr, 1)) { ++ __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr); ++ return NULL; ++ } ++ ++ return addr; ++} ++ ++void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, ++ dwc_dma_t *dma_addr, char const *func, int line) ++{ ++ void *addr = __DWC_DMA_ALLOC_ATOMIC(dma_ctx, size, dma_addr); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(dma_ctx, size, func, line, addr, 1)) { ++ __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr); ++ return NULL; ++ } ++ ++ return addr; ++} ++ ++void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr, ++ dwc_dma_t dma_addr, char const *func, int line) ++{ ++ free_allocation(dma_ctx, virt_addr, func, line); ++ __DWC_DMA_FREE(dma_ctx, size, virt_addr, dma_addr); ++} ++ ++#endif /* DWC_DEBUG_MEMORY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_modpow.c b/drivers/usb/gadget/udc/hiudc/dwc_modpow.c +new file mode 100644 +index 0000000..307dbdf +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_modpow.c +@@ -0,0 +1,633 @@ ++/* Bignum routines adapted from PUTTY sources. PuTTY copyright notice follows. ++ * ++ * PuTTY is copyright 1997-2007 Simon Tatham. ++ * ++ * Portions copyright Robert de Bath, Joris van Rantwijk, Delian ++ * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, ++ * Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus ++ * Kuhn, and CORE SDI S.A. ++ * ++ * Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation files ++ * (the "Software"), to deal in the Software without restriction, ++ * including without limitation the rights to use, copy, modify, merge, ++ * publish, distribute, sublicense, and/or sell copies of the Software, ++ * and to permit persons to whom the Software is furnished to do so, ++ * subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE ++ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF ++ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ * ++ */ ++#ifdef DWC_CRYPTOLIB ++ ++#ifndef CONFIG_MACH_IPMATE ++ ++#include "dwc_modpow.h" ++ ++#define BIGNUM_INT_MASK 0xFFFFFFFFUL ++#define BIGNUM_TOP_BIT 0x80000000UL ++#define BIGNUM_INT_BITS 32 ++ ++ ++static void *snmalloc(void *mem_ctx, size_t n, size_t size) ++{ ++ void *p; ++ size *= n; ++ if (size == 0) size = 1; ++ p = dwc_alloc(mem_ctx, size); ++ return p; ++} ++ ++#define snewn(ctx, n, type) ((type *)snmalloc((ctx), (n), sizeof(type))) ++#define sfree dwc_free ++ ++/* ++ * Usage notes: ++ * * Do not call the DIVMOD_WORD macro with expressions such as array ++ * subscripts, as some implementations object to this (see below). ++ * * Note that none of the division methods below will cope if the ++ * quotient won't fit into BIGNUM_INT_BITS. Callers should be careful ++ * to avoid this case. ++ * If this condition occurs, in the case of the x86 DIV instruction, ++ * an overflow exception will occur, which (according to a correspondent) ++ * will manifest on Windows as something like ++ * 0xC0000095: Integer overflow ++ * The C variant won't give the right answer, either. ++ */ ++ ++#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2) ++ ++#if defined __GNUC__ && defined __i386__ ++#define DIVMOD_WORD(q, r, hi, lo, w) \ ++ __asm__("div %2" : \ ++ "=d" (r), "=a" (q) : \ ++ "r" (w), "d" (hi), "a" (lo)) ++#else ++#define DIVMOD_WORD(q, r, hi, lo, w) do { \ ++ BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \ ++ q = n / w; \ ++ r = n % w; \ ++} while (0) ++#endif ++ ++#define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8) ++ ++#define BIGNUM_INTERNAL ++ ++static Bignum newbn(void *mem_ctx, int length) ++{ ++ Bignum b = snewn(mem_ctx, length + 1, BignumInt); ++ //if (!b) ++ //abort(); /* FIXME */ ++ DWC_MEMSET(b, 0, (length + 1) * sizeof(*b)); ++ b[0] = length; ++ return b; ++} ++ ++void freebn(void *mem_ctx, Bignum b) ++{ ++ /* ++ * Burn the evidence, just in case. ++ */ ++ DWC_MEMSET(b, 0, sizeof(b[0]) * (b[0] + 1)); ++ sfree(mem_ctx, b); ++} ++ ++/* ++ * Compute c = a * b. ++ * Input is in the first len words of a and b. ++ * Result is returned in the first 2*len words of c. ++ */ ++static void internal_mul(BignumInt *a, BignumInt *b, ++ BignumInt *c, int len) ++{ ++ int i, j; ++ BignumDblInt t; ++ ++ for (j = 0; j < 2 * len; j++) ++ c[j] = 0; ++ ++ for (i = len - 1; i >= 0; i--) { ++ t = 0; ++ for (j = len - 1; j >= 0; j--) { ++ t += MUL_WORD(a[i], (BignumDblInt) b[j]); ++ t += (BignumDblInt) c[i + j + 1]; ++ c[i + j + 1] = (BignumInt) t; ++ t = t >> BIGNUM_INT_BITS; ++ } ++ c[i] = (BignumInt) t; ++ } ++} ++ ++static void internal_add_shifted(BignumInt *number, ++ unsigned n, int shift) ++{ ++ int word = 1 + (shift / BIGNUM_INT_BITS); ++ int bshift = shift % BIGNUM_INT_BITS; ++ BignumDblInt addend; ++ ++ addend = (BignumDblInt)n << bshift; ++ ++ while (addend) { ++ addend += number[word]; ++ number[word] = (BignumInt) addend & BIGNUM_INT_MASK; ++ addend >>= BIGNUM_INT_BITS; ++ word++; ++ } ++} ++ ++/* ++ * Compute a = a % m. ++ * Input in first alen words of a and first mlen words of m. ++ * Output in first alen words of a ++ * (of which first alen-mlen words will be zero). ++ * The MSW of m MUST have its high bit set. ++ * Quotient is accumulated in the `quotient' array, which is a Bignum ++ * rather than the internal bigendian format. Quotient parts are shifted ++ * left by `qshift' before adding into quot. ++ */ ++static void internal_mod(BignumInt *a, int alen, ++ BignumInt *m, int mlen, ++ BignumInt *quot, int qshift) ++{ ++ BignumInt m0, m1; ++ unsigned int h; ++ int i, k; ++ ++ m0 = m[0]; ++ if (mlen > 1) ++ m1 = m[1]; ++ else ++ m1 = 0; ++ ++ for (i = 0; i <= alen - mlen; i++) { ++ BignumDblInt t; ++ unsigned int q, r, c, ai1; ++ ++ if (i == 0) { ++ h = 0; ++ } else { ++ h = a[i - 1]; ++ a[i - 1] = 0; ++ } ++ ++ if (i == alen - 1) ++ ai1 = 0; ++ else ++ ai1 = a[i + 1]; ++ ++ /* Find q = h:a[i] / m0 */ ++ if (h >= m0) { ++ /* ++ * Special case. ++ * ++ * To illustrate it, suppose a BignumInt is 8 bits, and ++ * we are dividing (say) A1:23:45:67 by A1:B2:C3. Then ++ * our initial division will be 0xA123 / 0xA1, which ++ * will give a quotient of 0x100 and a divide overflow. ++ * However, the invariants in this division algorithm ++ * are not violated, since the full number A1:23:... is ++ * _less_ than the quotient prefix A1:B2:... and so the ++ * following correction loop would have sorted it out. ++ * ++ * In this situation we set q to be the largest ++ * quotient we _can_ stomach (0xFF, of course). ++ */ ++ q = BIGNUM_INT_MASK; ++ } else { ++ /* Macro doesn't want an array subscript expression passed ++ * into it (see definition), so use a temporary. */ ++ BignumInt tmplo = a[i]; ++ DIVMOD_WORD(q, r, h, tmplo, m0); ++ ++ /* Refine our estimate of q by looking at ++ h:a[i]:a[i+1] / m0:m1 */ ++ t = MUL_WORD(m1, q); ++ if (t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) { ++ q--; ++ t -= m1; ++ r = (r + m0) & BIGNUM_INT_MASK; /* overflow? */ ++ if (r >= (BignumDblInt) m0 && ++ t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) q--; ++ } ++ } ++ ++ /* Subtract q * m from a[i...] */ ++ c = 0; ++ for (k = mlen - 1; k >= 0; k--) { ++ t = MUL_WORD(q, m[k]); ++ t += c; ++ c = (unsigned)(t >> BIGNUM_INT_BITS); ++ if ((BignumInt) t > a[i + k]) ++ c++; ++ a[i + k] -= (BignumInt) t; ++ } ++ ++ /* Add back m in case of borrow */ ++ if (c != h) { ++ t = 0; ++ for (k = mlen - 1; k >= 0; k--) { ++ t += m[k]; ++ t += a[i + k]; ++ a[i + k] = (BignumInt) t; ++ t = t >> BIGNUM_INT_BITS; ++ } ++ q--; ++ } ++ if (quot) ++ internal_add_shifted(quot, q, qshift + BIGNUM_INT_BITS * (alen - mlen - i)); ++ } ++} ++ ++/* ++ * Compute p % mod. ++ * The most significant word of mod MUST be non-zero. ++ * We assume that the result array is the same size as the mod array. ++ * We optionally write out a quotient if `quotient' is non-NULL. ++ * We can avoid writing out the result if `result' is NULL. ++ */ ++void bigdivmod(void *mem_ctx, Bignum p, Bignum mod, Bignum result, Bignum quotient) ++{ ++ BignumInt *n, *m; ++ int mshift; ++ int plen, mlen, i, j; ++ ++ /* Allocate m of size mlen, copy mod to m */ ++ /* We use big endian internally */ ++ mlen = mod[0]; ++ m = snewn(mem_ctx, mlen, BignumInt); ++ //if (!m) ++ //abort(); /* FIXME */ ++ for (j = 0; j < mlen; j++) ++ m[j] = mod[mod[0] - j]; ++ ++ /* Shift m left to make msb bit set */ ++ for (mshift = 0; mshift < BIGNUM_INT_BITS-1; mshift++) ++ if ((m[0] << mshift) & BIGNUM_TOP_BIT) ++ break; ++ if (mshift) { ++ for (i = 0; i < mlen - 1; i++) ++ m[i] = (m[i] << mshift) | (m[i + 1] >> (BIGNUM_INT_BITS - mshift)); ++ m[mlen - 1] = m[mlen - 1] << mshift; ++ } ++ ++ plen = p[0]; ++ /* Ensure plen > mlen */ ++ if (plen <= mlen) ++ plen = mlen + 1; ++ ++ /* Allocate n of size plen, copy p to n */ ++ n = snewn(mem_ctx, plen, BignumInt); ++ //if (!n) ++ //abort(); /* FIXME */ ++ for (j = 0; j < plen; j++) ++ n[j] = 0; ++ for (j = 1; j <= (int)p[0]; j++) ++ n[plen - j] = p[j]; ++ ++ /* Main computation */ ++ internal_mod(n, plen, m, mlen, quotient, mshift); ++ ++ /* Fixup result in case the modulus was shifted */ ++ if (mshift) { ++ for (i = plen - mlen - 1; i < plen - 1; i++) ++ n[i] = (n[i] << mshift) | (n[i + 1] >> (BIGNUM_INT_BITS - mshift)); ++ n[plen - 1] = n[plen - 1] << mshift; ++ internal_mod(n, plen, m, mlen, quotient, 0); ++ for (i = plen - 1; i >= plen - mlen; i--) ++ n[i] = (n[i] >> mshift) | (n[i - 1] << (BIGNUM_INT_BITS - mshift)); ++ } ++ ++ /* Copy result to buffer */ ++ if (result) { ++ for (i = 1; i <= (int)result[0]; i++) { ++ int j = plen - i; ++ result[i] = j >= 0 ? n[j] : 0; ++ } ++ } ++ ++ /* Free temporary arrays */ ++ for (i = 0; i < mlen; i++) ++ m[i] = 0; ++ sfree(mem_ctx, m); ++ for (i = 0; i < plen; i++) ++ n[i] = 0; ++ sfree(mem_ctx, n); ++} ++ ++/* ++ * Simple remainder. ++ */ ++Bignum bigmod(void *mem_ctx, Bignum a, Bignum b) ++{ ++ Bignum r = newbn(mem_ctx, b[0]); ++ bigdivmod(mem_ctx, a, b, r, NULL); ++ return r; ++} ++ ++/* ++ * Compute (base ^ exp) % mod. ++ */ ++Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod) ++{ ++ BignumInt *a, *b, *n, *m; ++ int mshift; ++ int mlen, i, j; ++ Bignum base, result; ++ ++ /* ++ * The most significant word of mod needs to be non-zero. It ++ * should already be, but let's make sure. ++ */ ++ //assert(mod[mod[0]] != 0); ++ ++ /* ++ * Make sure the base is smaller than the modulus, by reducing ++ * it modulo the modulus if not. ++ */ ++ base = bigmod(mem_ctx, base_in, mod); ++ ++ /* Allocate m of size mlen, copy mod to m */ ++ /* We use big endian internally */ ++ mlen = mod[0]; ++ m = snewn(mem_ctx, mlen, BignumInt); ++ //if (!m) ++ //abort(); /* FIXME */ ++ for (j = 0; j < mlen; j++) ++ m[j] = mod[mod[0] - j]; ++ ++ /* Shift m left to make msb bit set */ ++ for (mshift = 0; mshift < BIGNUM_INT_BITS - 1; mshift++) ++ if ((m[0] << mshift) & BIGNUM_TOP_BIT) ++ break; ++ if (mshift) { ++ for (i = 0; i < mlen - 1; i++) ++ m[i] = ++ (m[i] << mshift) | (m[i + 1] >> ++ (BIGNUM_INT_BITS - mshift)); ++ m[mlen - 1] = m[mlen - 1] << mshift; ++ } ++ ++ /* Allocate n of size mlen, copy base to n */ ++ n = snewn(mem_ctx, mlen, BignumInt); ++ //if (!n) ++ //abort(); /* FIXME */ ++ i = mlen - base[0]; ++ for (j = 0; j < i; j++) ++ n[j] = 0; ++ for (j = 0; j < base[0]; j++) ++ n[i + j] = base[base[0] - j]; ++ ++ /* Allocate a and b of size 2*mlen. Set a = 1 */ ++ a = snewn(mem_ctx, 2 * mlen, BignumInt); ++ //if (!a) ++ //abort(); /* FIXME */ ++ b = snewn(mem_ctx, 2 * mlen, BignumInt); ++ //if (!b) ++ //abort(); /* FIXME */ ++ for (i = 0; i < 2 * mlen; i++) ++ a[i] = 0; ++ a[2 * mlen - 1] = 1; ++ ++ /* Skip leading zero bits of exp. */ ++ i = 0; ++ j = BIGNUM_INT_BITS - 1; ++ while (i < exp[0] && (exp[exp[0] - i] & (1 << j)) == 0) { ++ j--; ++ if (j < 0) { ++ i++; ++ j = BIGNUM_INT_BITS - 1; ++ } ++ } ++ ++ /* Main computation */ ++ while (i < exp[0]) { ++ while (j >= 0) { ++ internal_mul(a + mlen, a + mlen, b, mlen); ++ internal_mod(b, mlen * 2, m, mlen, NULL, 0); ++ if ((exp[exp[0] - i] & (1 << j)) != 0) { ++ internal_mul(b + mlen, n, a, mlen); ++ internal_mod(a, mlen * 2, m, mlen, NULL, 0); ++ } else { ++ BignumInt *t; ++ t = a; ++ a = b; ++ b = t; ++ } ++ j--; ++ } ++ i++; ++ j = BIGNUM_INT_BITS - 1; ++ } ++ ++ /* Fixup result in case the modulus was shifted */ ++ if (mshift) { ++ for (i = mlen - 1; i < 2 * mlen - 1; i++) ++ a[i] = ++ (a[i] << mshift) | (a[i + 1] >> ++ (BIGNUM_INT_BITS - mshift)); ++ a[2 * mlen - 1] = a[2 * mlen - 1] << mshift; ++ internal_mod(a, mlen * 2, m, mlen, NULL, 0); ++ for (i = 2 * mlen - 1; i >= mlen; i--) ++ a[i] = ++ (a[i] >> mshift) | (a[i - 1] << ++ (BIGNUM_INT_BITS - mshift)); ++ } ++ ++ /* Copy result to buffer */ ++ result = newbn(mem_ctx, mod[0]); ++ for (i = 0; i < mlen; i++) ++ result[result[0] - i] = a[i + mlen]; ++ while (result[0] > 1 && result[result[0]] == 0) ++ result[0]--; ++ ++ /* Free temporary arrays */ ++ for (i = 0; i < 2 * mlen; i++) ++ a[i] = 0; ++ sfree(mem_ctx, a); ++ for (i = 0; i < 2 * mlen; i++) ++ b[i] = 0; ++ sfree(mem_ctx, b); ++ for (i = 0; i < mlen; i++) ++ m[i] = 0; ++ sfree(mem_ctx, m); ++ for (i = 0; i < mlen; i++) ++ n[i] = 0; ++ sfree(mem_ctx, n); ++ ++ freebn(mem_ctx, base); ++ ++ return result; ++} ++ ++ ++#ifdef UNITTEST ++ ++static __u32 dh_p[] = { ++ 96, ++ 0xFFFFFFFF, ++ 0xFFFFFFFF, ++ 0xA93AD2CA, ++ 0x4B82D120, ++ 0xE0FD108E, ++ 0x43DB5BFC, ++ 0x74E5AB31, ++ 0x08E24FA0, ++ 0xBAD946E2, ++ 0x770988C0, ++ 0x7A615D6C, ++ 0xBBE11757, ++ 0x177B200C, ++ 0x521F2B18, ++ 0x3EC86A64, ++ 0xD8760273, ++ 0xD98A0864, ++ 0xF12FFA06, ++ 0x1AD2EE6B, ++ 0xCEE3D226, ++ 0x4A25619D, ++ 0x1E8C94E0, ++ 0xDB0933D7, ++ 0xABF5AE8C, ++ 0xA6E1E4C7, ++ 0xB3970F85, ++ 0x5D060C7D, ++ 0x8AEA7157, ++ 0x58DBEF0A, ++ 0xECFB8504, ++ 0xDF1CBA64, ++ 0xA85521AB, ++ 0x04507A33, ++ 0xAD33170D, ++ 0x8AAAC42D, ++ 0x15728E5A, ++ 0x98FA0510, ++ 0x15D22618, ++ 0xEA956AE5, ++ 0x3995497C, ++ 0x95581718, ++ 0xDE2BCBF6, ++ 0x6F4C52C9, ++ 0xB5C55DF0, ++ 0xEC07A28F, ++ 0x9B2783A2, ++ 0x180E8603, ++ 0xE39E772C, ++ 0x2E36CE3B, ++ 0x32905E46, ++ 0xCA18217C, ++ 0xF1746C08, ++ 0x4ABC9804, ++ 0x670C354E, ++ 0x7096966D, ++ 0x9ED52907, ++ 0x208552BB, ++ 0x1C62F356, ++ 0xDCA3AD96, ++ 0x83655D23, ++ 0xFD24CF5F, ++ 0x69163FA8, ++ 0x1C55D39A, ++ 0x98DA4836, ++ 0xA163BF05, ++ 0xC2007CB8, ++ 0xECE45B3D, ++ 0x49286651, ++ 0x7C4B1FE6, ++ 0xAE9F2411, ++ 0x5A899FA5, ++ 0xEE386BFB, ++ 0xF406B7ED, ++ 0x0BFF5CB6, ++ 0xA637ED6B, ++ 0xF44C42E9, ++ 0x625E7EC6, ++ 0xE485B576, ++ 0x6D51C245, ++ 0x4FE1356D, ++ 0xF25F1437, ++ 0x302B0A6D, ++ 0xCD3A431B, ++ 0xEF9519B3, ++ 0x8E3404DD, ++ 0x514A0879, ++ 0x3B139B22, ++ 0x020BBEA6, ++ 0x8A67CC74, ++ 0x29024E08, ++ 0x80DC1CD1, ++ 0xC4C6628B, ++ 0x2168C234, ++ 0xC90FDAA2, ++ 0xFFFFFFFF, ++ 0xFFFFFFFF, ++}; ++ ++static __u32 dh_a[] = { ++ 8, ++ 0xdf367516, ++ 0x86459caa, ++ 0xe2d459a4, ++ 0xd910dae0, ++ 0x8a8b5e37, ++ 0x67ab31c6, ++ 0xf0b55ea9, ++ 0x440051d6, ++}; ++ ++static __u32 dh_b[] = { ++ 8, ++ 0xded92656, ++ 0xe07a048a, ++ 0x6fa452cd, ++ 0x2df89d30, ++ 0xc75f1b0f, ++ 0x8ce3578f, ++ 0x7980a324, ++ 0x5daec786, ++}; ++ ++static __u32 dh_g[] = { ++ 1, ++ 2, ++}; ++ ++int main(void) ++{ ++ int i; ++ __u32 *k; ++ k = dwc_modpow(NULL, dh_g, dh_a, dh_p); ++ ++ printf("\n\n"); ++ for (i=0; i> 16; ++ printf("%04x %04x ", m, l); ++ if (!((i + 1)%13)) printf("\n"); ++ } ++ printf("\n\n"); ++ ++ if ((k[0] == 0x60) && (k[1] == 0x28e490e5) && (k[0x60] == 0x5a0d3d4e)) { ++ printf("PASS\n\n"); ++ } ++ else { ++ printf("FAIL\n\n"); ++ } ++ ++} ++ ++#endif /* UNITTEST */ ++ ++#endif /* CONFIG_MACH_IPMATE */ ++ ++#endif /*DWC_CRYPTOLIB */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_modpow.h b/drivers/usb/gadget/udc/hiudc/dwc_modpow.h +new file mode 100644 +index 0000000..64f00c2 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_modpow.h +@@ -0,0 +1,34 @@ ++/* ++ * dwc_modpow.h ++ * See dwc_modpow.c for license and changes ++ */ ++#ifndef _DWC_MODPOW_H ++#define _DWC_MODPOW_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "dwc_os.h" ++ ++/** @file ++ * ++ * This file defines the module exponentiation function which is only used ++ * internally by the DWC UWB modules for calculation of PKs during numeric ++ * association. The routine is taken from the PUTTY, an open source terminal ++ * emulator. The PUTTY License is preserved in the dwc_modpow.c file. ++ * ++ */ ++ ++typedef uint32_t BignumInt; ++typedef uint64_t BignumDblInt; ++typedef BignumInt *Bignum; ++ ++/* Compute modular exponentiaion */ ++extern Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _LINUX_BIGNUM_H */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_notifier.c b/drivers/usb/gadget/udc/hiudc/dwc_notifier.c +new file mode 100644 +index 0000000..d3dadce +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_notifier.c +@@ -0,0 +1,319 @@ ++#ifdef DWC_NOTIFYLIB ++ ++#include "dwc_notifier.h" ++#include "dwc_list.h" ++ ++typedef struct dwc_observer { ++ void *observer; ++ dwc_notifier_callback_t callback; ++ void *data; ++ char *notification; ++ DWC_CIRCLEQ_ENTRY(dwc_observer) list_entry; ++} observer_t; ++ ++DWC_CIRCLEQ_HEAD(observer_queue, dwc_observer); ++ ++typedef struct dwc_notifier { ++ void *mem_ctx; ++ void *object; ++ struct observer_queue observers; ++ DWC_CIRCLEQ_ENTRY(dwc_notifier) list_entry; ++} notifier_t; ++ ++DWC_CIRCLEQ_HEAD(notifier_queue, dwc_notifier); ++ ++typedef struct manager { ++ void *mem_ctx; ++ void *wkq_ctx; ++ dwc_workq_t *wq; ++// dwc_mutex_t *mutex; ++ struct notifier_queue notifiers; ++} manager_t; ++ ++static manager_t *manager = NULL; ++ ++static int create_manager(void *mem_ctx, void *wkq_ctx) ++{ ++ manager = dwc_alloc(mem_ctx, sizeof(manager_t)); ++ if (!manager) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ DWC_CIRCLEQ_INIT(&manager->notifiers); ++ ++ manager->wq = dwc_workq_alloc(wkq_ctx, "DWC Notification WorkQ"); ++ if (!manager->wq) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ return 0; ++} ++ ++static void free_manager(void) ++{ ++ dwc_workq_free(manager->wq); ++ ++ /* All notifiers must have unregistered themselves before this module ++ * can be removed. Hitting this assertion indicates a programmer ++ * error. */ ++ DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&manager->notifiers), ++ "Notification manager being freed before all notifiers have been removed"); ++ dwc_free(manager->mem_ctx, manager); ++} ++ ++#ifdef DEBUG ++static void dump_manager(void) ++{ ++ notifier_t *n; ++ observer_t *o; ++ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ ++ DWC_DEBUG("List of all notifiers and observers:\n"); ++ DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) { ++ DWC_DEBUG("Notifier %p has observers:\n", n->object); ++ DWC_CIRCLEQ_FOREACH(o, &n->observers, list_entry) { ++ DWC_DEBUG(" %p watching %s\n", o->observer, o->notification); ++ } ++ } ++} ++#else ++#define dump_manager(...) ++#endif ++ ++static observer_t *alloc_observer(void *mem_ctx, void *observer, char *notification, ++ dwc_notifier_callback_t callback, void *data) ++{ ++ observer_t *new_observer = dwc_alloc(mem_ctx, sizeof(observer_t)); ++ ++ if (!new_observer) { ++ return NULL; ++ } ++ ++ DWC_CIRCLEQ_INIT_ENTRY(new_observer, list_entry); ++ new_observer->observer = observer; ++ new_observer->notification = notification; ++ new_observer->callback = callback; ++ new_observer->data = data; ++ return new_observer; ++} ++ ++static void free_observer(void *mem_ctx, observer_t *observer) ++{ ++ dwc_free(mem_ctx, observer); ++} ++ ++static notifier_t *alloc_notifier(void *mem_ctx, void *object) ++{ ++ notifier_t *notifier; ++ ++ if (!object) { ++ return NULL; ++ } ++ ++ notifier = dwc_alloc(mem_ctx, sizeof(notifier_t)); ++ if (!notifier) { ++ return NULL; ++ } ++ ++ DWC_CIRCLEQ_INIT(¬ifier->observers); ++ DWC_CIRCLEQ_INIT_ENTRY(notifier, list_entry); ++ ++ notifier->mem_ctx = mem_ctx; ++ notifier->object = object; ++ return notifier; ++} ++ ++static void free_notifier(notifier_t *notifier) ++{ ++ observer_t *observer; ++ ++ DWC_CIRCLEQ_FOREACH(observer, ¬ifier->observers, list_entry) { ++ free_observer(notifier->mem_ctx, observer); ++ } ++ ++ dwc_free(notifier->mem_ctx, notifier); ++} ++ ++static notifier_t *find_notifier(void *object) ++{ ++ notifier_t *notifier; ++ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ ++ if (!object) { ++ return NULL; ++ } ++ ++ DWC_CIRCLEQ_FOREACH(notifier, &manager->notifiers, list_entry) { ++ if (notifier->object == object) { ++ return notifier; ++ } ++ } ++ ++ return NULL; ++} ++ ++int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx) ++{ ++ return create_manager(mem_ctx, wkq_ctx); ++} ++ ++void dwc_free_notification_manager(void) ++{ ++ free_manager(); ++} ++ ++dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object) ++{ ++ notifier_t *notifier; ++ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ ++ notifier = find_notifier(object); ++ if (notifier) { ++ DWC_ERROR("Notifier %p is already registered\n", object); ++ return NULL; ++ } ++ ++ notifier = alloc_notifier(mem_ctx, object); ++ if (!notifier) { ++ return NULL; ++ } ++ ++ DWC_CIRCLEQ_INSERT_TAIL(&manager->notifiers, notifier, list_entry); ++ ++ DWC_INFO("Notifier %p registered", object); ++ dump_manager(); ++ ++ return notifier; ++} ++ ++void dwc_unregister_notifier(dwc_notifier_t *notifier) ++{ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ ++ if (!DWC_CIRCLEQ_EMPTY(¬ifier->observers)) { ++ observer_t *o; ++ ++ DWC_ERROR("Notifier %p has active observers when removing\n", notifier->object); ++ DWC_CIRCLEQ_FOREACH(o, ¬ifier->observers, list_entry) { ++ DWC_DEBUG(" %p watching %s\n", o->observer, o->notification); ++ } ++ ++ DWC_ASSERT(DWC_CIRCLEQ_EMPTY(¬ifier->observers), ++ "Notifier %p has active observers when removing", notifier); ++ } ++ ++ DWC_CIRCLEQ_REMOVE_INIT(&manager->notifiers, notifier, list_entry); ++ free_notifier(notifier); ++ ++ DWC_INFO("Notifier unregistered"); ++ dump_manager(); ++} ++ ++/* Add an observer to observe the notifier for a particular state, event, or notification. */ ++int dwc_add_observer(void *observer, void *object, char *notification, ++ dwc_notifier_callback_t callback, void *data) ++{ ++ notifier_t *notifier = find_notifier(object); ++ observer_t *new_observer; ++ ++ if (!notifier) { ++ DWC_ERROR("Notifier %p is not found when adding observer\n", object); ++ return -DWC_E_INVALID; ++ } ++ ++ new_observer = alloc_observer(notifier->mem_ctx, observer, notification, callback, data); ++ if (!new_observer) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ DWC_CIRCLEQ_INSERT_TAIL(¬ifier->observers, new_observer, list_entry); ++ ++ DWC_INFO("Added observer %p to notifier %p observing notification %s, callback=%p, data=%p", ++ observer, object, notification, callback, data); ++ ++ dump_manager(); ++ return 0; ++} ++ ++int dwc_remove_observer(void *observer) ++{ ++ notifier_t *n; ++ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ ++ DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) { ++ observer_t *o; ++ observer_t *o2; ++ ++ DWC_CIRCLEQ_FOREACH_SAFE(o, o2, &n->observers, list_entry) { ++ if (o->observer == observer) { ++ DWC_CIRCLEQ_REMOVE_INIT(&n->observers, o, list_entry); ++ DWC_INFO("Removing observer %p from notifier %p watching notification %s:", ++ o->observer, n->object, o->notification); ++ free_observer(n->mem_ctx, o); ++ } ++ } ++ } ++ ++ dump_manager(); ++ return 0; ++} ++ ++typedef struct callback_data { ++ void *mem_ctx; ++ dwc_notifier_callback_t cb; ++ void *observer; ++ void *data; ++ void *object; ++ char *notification; ++ void *notification_data; ++} cb_data_t; ++ ++static void cb_task(void *data) ++{ ++ cb_data_t *cb = (cb_data_t *)data; ++ ++ cb->cb(cb->object, cb->notification, cb->observer, cb->notification_data, cb->data); ++ dwc_free(cb->mem_ctx, cb); ++} ++ ++void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data) ++{ ++ observer_t *o; ++ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ ++ DWC_CIRCLEQ_FOREACH(o, ¬ifier->observers, list_entry) { ++ int len = DWC_STRLEN(notification); ++ ++ if (DWC_STRLEN(o->notification) != len) { ++ continue; ++ } ++ ++ if (DWC_STRNCMP(o->notification, notification, len) == 0) { ++ cb_data_t *cb_data = dwc_alloc(notifier->mem_ctx, sizeof(cb_data_t)); ++ ++ if (!cb_data) { ++ DWC_ERROR("Failed to allocate callback data\n"); ++ return; ++ } ++ ++ cb_data->mem_ctx = notifier->mem_ctx; ++ cb_data->cb = o->callback; ++ cb_data->observer = o->observer; ++ cb_data->data = o->data; ++ cb_data->object = notifier->object; ++ cb_data->notification = notification; ++ cb_data->notification_data = notification_data; ++ DWC_DEBUG("Observer found %p for notification %s\n", o->observer, notification); ++ DWC_WORKQ_SCHEDULE(manager->wq, cb_task, cb_data, ++ "Notify callback from %p for Notification %s, to observer %p", ++ cb_data->object, notification, cb_data->observer); ++ } ++ } ++} ++ ++#endif /* DWC_NOTIFYLIB */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_notifier.h b/drivers/usb/gadget/udc/hiudc/dwc_notifier.h +new file mode 100644 +index 0000000..4a8cdfe +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_notifier.h +@@ -0,0 +1,122 @@ ++ ++#ifndef __DWC_NOTIFIER_H__ ++#define __DWC_NOTIFIER_H__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "dwc_os.h" ++ ++/** @file ++ * ++ * A simple implementation of the Observer pattern. Any "module" can ++ * register as an observer or notifier. The notion of "module" is abstract and ++ * can mean anything used to identify either an observer or notifier. Usually ++ * it will be a pointer to a data structure which contains some state, ie an ++ * object. ++ * ++ * Before any notifiers can be added, the global notification manager must be ++ * brought up with dwc_alloc_notification_manager(). ++ * dwc_free_notification_manager() will bring it down and free all resources. ++ * These would typically be called upon module load and unload. The ++ * notification manager is a single global instance that handles all registered ++ * observable modules and observers so this should be done only once. ++ * ++ * A module can be observable by using Notifications to publicize some general ++ * information about it's state or operation. It does not care who listens, or ++ * even if anyone listens, or what they do with the information. The observable ++ * modules do not need to know any information about it's observers or their ++ * interface, or their state or data. ++ * ++ * Any module can register to emit Notifications. It should publish a list of ++ * notifications that it can emit and their behavior, such as when they will get ++ * triggered, and what information will be provided to the observer. Then it ++ * should register itself as an observable module. See dwc_register_notifier(). ++ * ++ * Any module can observe any observable, registered module, provided it has a ++ * handle to the other module and knows what notifications to observe. See ++ * dwc_add_observer(). ++ * ++ * A function of type dwc_notifier_callback_t is called whenever a notification ++ * is triggered with one or more observers observing it. This function is ++ * called in it's own process so it may sleep or block if needed. It is ++ * guaranteed to be called sometime after the notification has occurred and will ++ * be called once per each time the notification is triggered. It will NOT be ++ * called in the same process context used to trigger the notification. ++ * ++ * @section Limitiations ++ * ++ * Keep in mind that Notifications that can be triggered in rapid sucession may ++ * schedule too many processes too handle. Be aware of this limitation when ++ * designing to use notifications, and only add notifications for appropriate ++ * observable information. ++ * ++ * Also Notification callbacks are not synchronous. If you need to synchronize ++ * the behavior between module/observer you must use other means. And perhaps ++ * that will mean Notifications are not the proper solution. ++ */ ++ ++struct dwc_notifier; ++typedef struct dwc_notifier dwc_notifier_t; ++ ++/** The callback function must be of this type. ++ * ++ * @param object This is the object that is being observed. ++ * @param notification This is the notification that was triggered. ++ * @param observer This is the observer ++ * @param notification_data This is notification-specific data that the notifier ++ * has included in this notification. The value of this should be published in ++ * the documentation of the observable module with the notifications. ++ * @param user_data This is any custom data that the observer provided when ++ * adding itself as an observer to the notification. */ ++typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer, ++ void *notification_data, void *user_data); ++ ++/** Brings up the notification manager. */ ++extern int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx); ++/** Brings down the notification manager. */ ++extern void dwc_free_notification_manager(void); ++ ++/** This function registers an observable module. A dwc_notifier_t object is ++ * returned to the observable module. This is an opaque object that is used by ++ * the observable module to trigger notifications. This object should only be ++ * accessible to functions that are authorized to trigger notifications for this ++ * module. Observers do not need this object. */ ++extern dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object); ++ ++/** This function unregisters an observable module. All observers have to be ++ * removed prior to unregistration. */ ++extern void dwc_unregister_notifier(dwc_notifier_t *notifier); ++ ++/** Add a module as an observer to the observable module. The observable module ++ * needs to have previously registered with the notification manager. ++ * ++ * @param observer The observer module ++ * @param object The module to observe ++ * @param notification The notification to observe ++ * @param callback The callback function to call ++ * @param user_data Any additional user data to pass into the callback function */ ++extern int dwc_add_observer(void *observer, void *object, char *notification, ++ dwc_notifier_callback_t callback, void *user_data); ++ ++/** Removes the specified observer from all notifications that it is currently ++ * observing. */ ++extern int dwc_remove_observer(void *observer); ++ ++/** This function triggers a Notification. It should be called by the ++ * observable module, or any module or library which the observable module ++ * allows to trigger notification on it's behalf. Such as the dwc_cc_t. ++ * ++ * dwc_notify is a non-blocking function. Callbacks are scheduled called in ++ * their own process context for each trigger. Callbacks can be blocking. ++ * dwc_notify can be called from interrupt context if needed. ++ * ++ */ ++void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __DWC_NOTIFIER_H__ */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_os.h b/drivers/usb/gadget/udc/hiudc/dwc_os.h +new file mode 100644 +index 0000000..a64c49a +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_os.h +@@ -0,0 +1,1237 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_os.h $ ++ * $Revision: #14 $ ++ * $Date: 2010/11/04 $ ++ * $Change: 1621695 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS 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 _DWC_OS_H_ ++#define _DWC_OS_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ * ++ * DWC portability library, low level os-wrapper functions ++ * ++ */ ++ ++/* These basic types need to be defined by some OS header file or custom header ++ * file for your specific target architecture. ++ * ++ * uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t ++ * ++ * Any custom or alternate header file must be added and enabled here. ++ */ ++ ++#ifdef DWC_LINUX ++# include ++# ifdef CONFIG_DEBUG_MUTEXES ++# include ++# endif ++# include ++# include ++#endif ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++# include ++#endif ++ ++ ++/** @name Primitive Types and Values */ ++ ++/** We define a boolean type for consistency. Can be either YES or NO */ ++typedef uint8_t dwc_bool_t; ++#define YES 1 ++#define NO 0 ++ ++#ifdef DWC_LINUX ++ ++/** @name Error Codes */ ++#define DWC_E_INVALID EINVAL ++#define DWC_E_NO_MEMORY ENOMEM ++#define DWC_E_NO_DEVICE ENODEV ++#define DWC_E_NOT_SUPPORTED EOPNOTSUPP ++#define DWC_E_TIMEOUT ETIMEDOUT ++#define DWC_E_BUSY EBUSY ++#define DWC_E_AGAIN EAGAIN ++#define DWC_E_RESTART ERESTART ++#define DWC_E_ABORT ECONNABORTED ++#define DWC_E_SHUTDOWN ESHUTDOWN ++#define DWC_E_NO_DATA ENODATA ++#define DWC_E_DISCONNECT ECONNRESET ++#define DWC_E_UNKNOWN EINVAL ++#define DWC_E_NO_STREAM_RES ENOSR ++#define DWC_E_COMMUNICATION ECOMM ++#define DWC_E_OVERFLOW EOVERFLOW ++#define DWC_E_PROTOCOL EPROTO ++#define DWC_E_IN_PROGRESS EINPROGRESS ++#define DWC_E_PIPE EPIPE ++#define DWC_E_IO EIO ++#define DWC_E_NO_SPACE ENOSPC ++ ++#else ++ ++/** @name Error Codes */ ++#define DWC_E_INVALID 1001 ++#define DWC_E_NO_MEMORY 1002 ++#define DWC_E_NO_DEVICE 1003 ++#define DWC_E_NOT_SUPPORTED 1004 ++#define DWC_E_TIMEOUT 1005 ++#define DWC_E_BUSY 1006 ++#define DWC_E_AGAIN 1007 ++#define DWC_E_RESTART 1008 ++#define DWC_E_ABORT 1009 ++#define DWC_E_SHUTDOWN 1010 ++#define DWC_E_NO_DATA 1011 ++#define DWC_E_DISCONNECT 2000 ++#define DWC_E_UNKNOWN 3000 ++#define DWC_E_NO_STREAM_RES 4001 ++#define DWC_E_COMMUNICATION 4002 ++#define DWC_E_OVERFLOW 4003 ++#define DWC_E_PROTOCOL 4004 ++#define DWC_E_IN_PROGRESS 4005 ++#define DWC_E_PIPE 4006 ++#define DWC_E_IO 4007 ++#define DWC_E_NO_SPACE 4008 ++ ++#endif ++ ++ ++/** @name Tracing/Logging Functions ++ * ++ * These function provide the capability to add tracing, debugging, and error ++ * messages, as well exceptions as assertions. The WUDEV uses these ++ * extensively. These could be logged to the main console, the serial port, an ++ * internal buffer, etc. These functions could also be no-op if they are too ++ * expensive on your system. By default undefining the DEBUG macro already ++ * no-ops some of these functions. */ ++ ++/** Returns non-zero if in interrupt context. */ ++extern dwc_bool_t DWC_IN_IRQ(void); ++#define dwc_in_irq DWC_IN_IRQ ++ ++/** Returns "IRQ" if DWC_IN_IRQ is true. */ ++static inline char *dwc_irq(void) { ++ return DWC_IN_IRQ() ? "IRQ" : ""; ++} ++ ++/** Returns non-zero if in bottom-half context. */ ++extern dwc_bool_t DWC_IN_BH(void); ++#define dwc_in_bh DWC_IN_BH ++ ++/** Returns "BH" if DWC_IN_BH is true. */ ++static inline char *dwc_bh(void) { ++ return DWC_IN_BH() ? "BH" : ""; ++} ++ ++/** ++ * A vprintf() clone. Just call vprintf if you've got it. ++ */ ++extern void DWC_VPRINTF(char *format, va_list args); ++#define dwc_vprintf DWC_VPRINTF ++ ++/** ++ * A vsnprintf() clone. Just call vprintf if you've got it. ++ */ ++extern int DWC_VSNPRINTF(char *str, int size, char *format, va_list args); ++#define dwc_vsnprintf DWC_VSNPRINTF ++ ++/** ++ * printf() clone. Just call printf if you've go it. ++ */ ++extern void DWC_PRINTF(char *format, ...) ++/* This provides compiler level static checking of the parameters if you're ++ * using GCC. */ ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++#define dwc_printf DWC_PRINTF ++ ++/** ++ * sprintf() clone. Just call sprintf if you've got it. ++ */ ++extern int DWC_SPRINTF(char *string, char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 2, 3))); ++#else ++ ; ++#endif ++#define dwc_sprintf DWC_SPRINTF ++ ++/** ++ * snprintf() clone. Just call snprintf if you've got it. ++ */ ++extern int DWC_SNPRINTF(char *string, int size, char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 3, 4))); ++#else ++ ; ++#endif ++#define dwc_snprintf DWC_SNPRINTF ++ ++/** ++ * Prints a WARNING message. On systems that don't differentiate between ++ * warnings and regular log messages, just print it. Indicates that something ++ * may be wrong with the driver. Works like printf(). ++ * ++ * Use the DWC_WARN macro to call this function. ++ */ ++extern void __DWC_WARN(char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++ ++/** ++ * Prints an error message. On systems that don't differentiate between errors ++ * and regular log messages, just print it. Indicates that something went wrong ++ * with the driver. Works like printf(). ++ * ++ * Use the DWC_ERROR macro to call this function. ++ */ ++extern void __DWC_ERROR(char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++ ++/** ++ * Prints an exception error message and takes some user-defined action such as ++ * print out a backtrace or trigger a breakpoint. Indicates that something went ++ * abnormally wrong with the driver such as programmer error, or other ++ * exceptional condition. It should not be ignored so even on systems without ++ * printing capability, some action should be taken to notify the developer of ++ * it. Works like printf(). ++ */ ++extern void DWC_EXCEPTION(char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++#define dwc_exception DWC_EXCEPTION ++ ++#ifdef DEBUG ++/** ++ * Prints out a debug message. Used for logging/trace messages. ++ * ++ * Use the DWC_DEBUG macro to call this function ++ */ ++extern void __DWC_DEBUG(char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++#else ++#define __DWC_DEBUG(...) ++#endif ++ ++/** ++ * Prints out a Debug message. ++ */ ++#define DWC_DEBUG(_format, _args...) __DWC_DEBUG("DEBUG:%s:%s: " _format "\n", \ ++ __func__, dwc_irq(), ## _args) ++#define dwc_debug DWC_DEBUG ++/** ++ * Prints out an informative message. ++ */ ++#define DWC_INFO(_format, _args...) DWC_PRINTF("INFO:%s: " _format "\n", \ ++ dwc_irq(), ## _args) ++#define dwc_info DWC_INFO ++/** ++ * Prints out a warning message. ++ */ ++#define DWC_WARN(_format, _args...) __DWC_WARN("WARN:%s:%s:%d: " _format "\n", \ ++ dwc_irq(), __func__, __LINE__, ## _args) ++#define dwc_warn DWC_WARN ++/** ++ * Prints out an error message. ++ */ ++#define DWC_ERROR(_format, _args...) __DWC_ERROR("ERROR:%s:%s:%d: " _format "\n", \ ++ dwc_irq(), __func__, __LINE__, ## _args) ++#define dwc_error DWC_ERROR ++ ++#define DWC_PROTO_ERROR(_format, _args...) __DWC_WARN("ERROR:%s:%s:%d: " _format "\n", \ ++ dwc_irq(), __func__, __LINE__, ## _args) ++#define dwc_proto_error DWC_PROTO_ERROR ++ ++#ifdef DEBUG ++/** Prints out a exception error message if the _expr expression fails. Disabled ++ * if DEBUG is not enabled. */ ++#define DWC_ASSERT(_expr, _format, _args...) do { \ ++ if (!(_expr)) { DWC_EXCEPTION("%s:%s:%d: " _format "\n", dwc_irq(), \ ++ __FILE__, __LINE__, ## _args); } \ ++ } while (0) ++#else ++#define DWC_ASSERT(_x...) ++#endif ++#define dwc_assert DWC_ASSERT ++ ++ ++/** @name Byte Ordering ++ * The following functions are for conversions between processor's byte ordering ++ * and specific ordering you want. ++ */ ++ ++/** Converts 32 bit data in CPU byte ordering to little endian. */ ++extern uint32_t DWC_CPU_TO_LE32(uint32_t *p); ++#define dwc_cpu_to_le32 DWC_CPU_TO_LE32 ++ ++/** Converts 32 bit data in CPU byte orderint to big endian. */ ++extern uint32_t DWC_CPU_TO_BE32(uint32_t *p); ++#define dwc_cpu_to_be32 DWC_CPU_TO_BE32 ++ ++/** Converts 32 bit little endian data to CPU byte ordering. */ ++extern uint32_t DWC_LE32_TO_CPU(uint32_t *p); ++#define dwc_le32_to_cpu DWC_LE32_TO_CPU ++ ++/** Converts 32 bit big endian data to CPU byte ordering. */ ++extern uint32_t DWC_BE32_TO_CPU(uint32_t *p); ++#define dwc_be32_to_cpu DWC_BE32_TO_CPU ++ ++/** Converts 16 bit data in CPU byte ordering to little endian. */ ++extern uint16_t DWC_CPU_TO_LE16(uint16_t *p); ++#define dwc_cpu_to_le16 DWC_CPU_TO_LE16 ++ ++/** Converts 16 bit data in CPU byte orderint to big endian. */ ++extern uint16_t DWC_CPU_TO_BE16(uint16_t *p); ++#define dwc_cpu_to_be16 DWC_CPU_TO_BE16 ++ ++/** Converts 16 bit little endian data to CPU byte ordering. */ ++extern uint16_t DWC_LE16_TO_CPU(uint16_t *p); ++#define dwc_le16_to_cpu DWC_LE16_TO_CPU ++ ++/** Converts 16 bit bi endian data to CPU byte ordering. */ ++extern uint16_t DWC_BE16_TO_CPU(uint16_t *p); ++#define dwc_be16_to_cpu DWC_BE16_TO_CPU ++ ++ ++/** @name Register Read/Write ++ * ++ * The following six functions should be implemented to read/write registers of ++ * 32-bit and 64-bit sizes. All modules use this to read/write register values. ++ * The reg value is a pointer to the register calculated from the void *base ++ * variable passed into the driver when it is started. */ ++ ++#ifdef DWC_LINUX ++/* Linux doesn't need any extra parameters for register read/write, so we ++ * just throw away the IO context parameter. ++ */ ++/** Reads the content of a 32-bit register. */ ++extern uint32_t DWC_READ_REG32(uint32_t volatile *reg); ++#define dwc_read_reg32(_ctx_,_reg_) DWC_READ_REG32(_reg_) ++ ++/** Reads the content of a 64-bit register. */ ++extern uint64_t DWC_READ_REG64(uint64_t volatile *reg); ++#define dwc_read_reg64(_ctx_,_reg_) DWC_READ_REG64(_reg_) ++ ++/** Writes to a 32-bit register. */ ++extern void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value); ++#define dwc_write_reg32(_ctx_,_reg_,_val_) DWC_WRITE_REG32(_reg_, _val_) ++ ++/** Writes to a 64-bit register. */ ++extern void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value); ++#define dwc_write_reg64(_ctx_,_reg_,_val_) DWC_WRITE_REG64(_reg_, _val_) ++ ++/** ++ * Modify bit values in a register. Using the ++ * algorithm: (reg_contents & ~clear_mask) | set_mask. ++ */ ++extern void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask); ++#define dwc_modify_reg32(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG32(_reg_,_cmsk_,_smsk_) ++extern void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask); ++#define dwc_modify_reg64(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG64(_reg_,_cmsk_,_smsk_) ++ ++#endif /* DWC_LINUX */ ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++typedef struct dwc_ioctx { ++ struct device *dev; ++ bus_space_tag_t iot; ++ bus_space_handle_t ioh; ++} dwc_ioctx_t; ++ ++/** BSD needs two extra parameters for register read/write, so we pass ++ * them in using the IO context parameter. ++ */ ++/** Reads the content of a 32-bit register. */ ++extern uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg); ++#define dwc_read_reg32 DWC_READ_REG32 ++ ++/** Reads the content of a 64-bit register. */ ++extern uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg); ++#define dwc_read_reg64 DWC_READ_REG64 ++ ++/** Writes to a 32-bit register. */ ++extern void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value); ++#define dwc_write_reg32 DWC_WRITE_REG32 ++ ++/** Writes to a 64-bit register. */ ++extern void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value); ++#define dwc_write_reg64 DWC_WRITE_REG64 ++ ++/** ++ * Modify bit values in a register. Using the ++ * algorithm: (reg_contents & ~clear_mask) | set_mask. ++ */ ++extern void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask); ++#define dwc_modify_reg32 DWC_MODIFY_REG32 ++extern void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask); ++#define dwc_modify_reg64 DWC_MODIFY_REG64 ++ ++#endif /* DWC_FREEBSD || DWC_NETBSD */ ++ ++/** @cond */ ++ ++/** @name Some convenience MACROS used internally. Define DWC_DEBUG_REGS to log the ++ * register writes. */ ++ ++#ifdef DWC_LINUX ++ ++# ifdef DWC_DEBUG_REGS ++ ++#define dwc_define_read_write_reg_n(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \ ++ return DWC_READ_REG32(&container->regs->_reg[num]); \ ++} \ ++static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \ ++ DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \ ++ &(((uint32_t*)container->regs->_reg)[num]), data); \ ++ DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \ ++} ++ ++#define dwc_define_read_write_reg(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg(_container_type *container) { \ ++ return DWC_READ_REG32(&container->regs->_reg); \ ++} \ ++static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \ ++ DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \ ++ DWC_WRITE_REG32(&container->regs->_reg, data); \ ++} ++ ++# else /* DWC_DEBUG_REGS */ ++ ++#define dwc_define_read_write_reg_n(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \ ++ return DWC_READ_REG32(&container->regs->_reg[num]); \ ++} \ ++static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \ ++ DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \ ++} ++ ++#define dwc_define_read_write_reg(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg(_container_type *container) { \ ++ return DWC_READ_REG32(&container->regs->_reg); \ ++} \ ++static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \ ++ DWC_WRITE_REG32(&container->regs->_reg, data); \ ++} ++ ++# endif /* DWC_DEBUG_REGS */ ++ ++#endif /* DWC_LINUX */ ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++ ++# ifdef DWC_DEBUG_REGS ++ ++#define dwc_define_read_write_reg_n(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \ ++ return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \ ++} \ ++static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \ ++ DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \ ++ &(((uint32_t*)container->regs->_reg)[num]), data); \ ++ DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \ ++} ++ ++#define dwc_define_read_write_reg(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \ ++ return DWC_READ_REG32(io_ctx, &container->regs->_reg); \ ++} \ ++static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \ ++ DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \ ++ DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \ ++} ++ ++# else /* DWC_DEBUG_REGS */ ++ ++#define dwc_define_read_write_reg_n(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \ ++ return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \ ++} \ ++static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \ ++ DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \ ++} ++ ++#define dwc_define_read_write_reg(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \ ++ return DWC_READ_REG32(io_ctx, &container->regs->_reg); \ ++} \ ++static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \ ++ DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \ ++} ++ ++# endif /* DWC_DEBUG_REGS */ ++ ++#endif /* DWC_FREEBSD || DWC_NETBSD */ ++ ++/** @endcond */ ++ ++ ++#ifdef DWC_CRYPTOLIB ++/** @name Crypto Functions ++ * ++ * These are the low-level cryptographic functions used by the driver. */ ++ ++/** Perform AES CBC */ ++extern int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out); ++#define dwc_aes_cbc DWC_AES_CBC ++ ++/** Fill the provided buffer with random bytes. These should be cryptographic grade random numbers. */ ++extern void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length); ++#define dwc_random_bytes DWC_RANDOM_BYTES ++ ++/** Perform the SHA-256 hash function */ ++extern int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out); ++#define dwc_sha256 DWC_SHA256 ++ ++/** Calculated the HMAC-SHA256 */ ++extern int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t *out); ++#define dwc_hmac_sha256 DWC_HMAC_SHA256 ++ ++#endif /* DWC_CRYPTOLIB */ ++ ++ ++/** @name Memory Allocation ++ * ++ * These function provide access to memory allocation. There are only 2 DMA ++ * functions and 3 Regular memory functions that need to be implemented. None ++ * of the memory debugging routines need to be implemented. The allocation ++ * routines all ZERO the contents of the memory. ++ * ++ * Defining DWC_DEBUG_MEMORY turns on memory debugging and statistic gathering. ++ * This checks for memory leaks, keeping track of alloc/free pairs. It also ++ * keeps track of how much memory the driver is using at any given time. */ ++ ++#define DWC_PAGE_SIZE 4096 ++#define DWC_PAGE_OFFSET(addr) (((uint32_t)addr) & 0xfff) ++#define DWC_PAGE_ALIGNED(addr) ((((uint32_t)addr) & 0xfff) == 0) ++ ++#define DWC_INVALID_DMA_ADDR 0x0 ++ ++#ifdef DWC_LINUX ++/** Type for a DMA address */ ++typedef dma_addr_t dwc_dma_t; ++#endif ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++typedef bus_addr_t dwc_dma_t; ++#endif ++ ++#ifdef DWC_FREEBSD ++typedef struct dwc_dmactx { ++ struct device *dev; ++ bus_dma_tag_t dma_tag; ++ bus_dmamap_t dma_map; ++ bus_addr_t dma_paddr; ++ void *dma_vaddr; ++} dwc_dmactx_t; ++#endif ++ ++#ifdef DWC_NETBSD ++typedef struct dwc_dmactx { ++ struct device *dev; ++ bus_dma_tag_t dma_tag; ++ bus_dmamap_t dma_map; ++ bus_dma_segment_t segs[1]; ++ int nsegs; ++ bus_addr_t dma_paddr; ++ void *dma_vaddr; ++} dwc_dmactx_t; ++#endif ++ ++/* @todo these functions will be added in the future */ ++#if 0 ++/** ++ * Creates a DMA pool from which you can allocate DMA buffers. Buffers ++ * allocated from this pool will be guaranteed to meet the size, alignment, and ++ * boundary requirements specified. ++ * ++ * @param[in] size Specifies the size of the buffers that will be allocated from ++ * this pool. ++ * @param[in] align Specifies the byte alignment requirements of the buffers ++ * allocated from this pool. Must be a power of 2. ++ * @param[in] boundary Specifies the N-byte boundary that buffers allocated from ++ * this pool must not cross. ++ * ++ * @returns A pointer to an internal opaque structure which is not to be ++ * accessed outside of these library functions. Use this handle to specify ++ * which pools to allocate/free DMA buffers from and also to destroy the pool, ++ * when you are done with it. ++ */ ++extern dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, uint32_t align, uint32_t boundary); ++ ++/** ++ * Destroy a DMA pool. All buffers allocated from that pool must be freed first. ++ */ ++extern void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool); ++ ++/** ++ * Allocate a buffer from the specified DMA pool and zeros its contents. ++ */ ++extern void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr); ++ ++/** ++ * Free a previously allocated buffer from the DMA pool. ++ */ ++extern void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr); ++#endif ++ ++/** Allocates a DMA capable buffer and zeroes its contents. */ ++extern void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr); ++ ++/** Allocates a DMA capable buffer and zeroes its contents in atomic contest */ ++extern void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr); ++ ++/** Frees a previously allocated buffer. */ ++extern void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr); ++ ++/** Allocates a block of memory and zeroes its contents. */ ++extern void *__DWC_ALLOC(void *mem_ctx, uint32_t size); ++ ++/** Allocates a block of memory and zeroes its contents, in an atomic manner ++ * which can be used inside interrupt context. The size should be sufficiently ++ * small, a few KB at most, such that failures are not likely to occur. Can just call ++ * __DWC_ALLOC if it is atomic. */ ++extern void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size); ++ ++/** Frees a previously allocated buffer. */ ++extern void __DWC_FREE(void *mem_ctx, void *addr); ++ ++#ifndef DWC_DEBUG_MEMORY ++ ++#define DWC_ALLOC(_size_) __DWC_ALLOC(NULL, _size_) ++#define DWC_ALLOC_ATOMIC(_size_) __DWC_ALLOC_ATOMIC(NULL, _size_) ++#define DWC_FREE(_addr_) __DWC_FREE(NULL, _addr_) ++ ++# ifdef DWC_LINUX ++#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(NULL, _size_, _dma_) ++#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(NULL, _size_,_dma_) ++#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(NULL, _size_, _virt_, _dma_) ++# endif ++ ++# if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++#define DWC_DMA_ALLOC __DWC_DMA_ALLOC ++#define DWC_DMA_FREE __DWC_DMA_FREE ++# endif ++ ++#else /* DWC_DEBUG_MEMORY */ ++ ++extern void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line); ++extern void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, int line); ++extern void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line); ++extern void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr, ++ char const *func, int line); ++extern void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr, ++ char const *func, int line); ++extern void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr, ++ dwc_dma_t dma_addr, char const *func, int line); ++ ++extern int dwc_memory_debug_start(void *mem_ctx); ++extern void dwc_memory_debug_stop(void); ++extern void dwc_memory_debug_report(void); ++ ++#define DWC_ALLOC(_size_) dwc_alloc_debug(NULL, _size_, __func__, __LINE__) ++#define DWC_ALLOC_ATOMIC(_size_) dwc_alloc_atomic_debug(NULL, _size_, \ ++ __func__, __LINE__) ++#define DWC_FREE(_addr_) dwc_free_debug(NULL, _addr_, __func__, __LINE__) ++ ++# ifdef DWC_LINUX ++#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(NULL, _size_, \ ++ _dma_, __func__, __LINE__) ++#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(NULL, _size_, \ ++ _dma_, __func__, __LINE__) ++#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(NULL, _size_, \ ++ _virt_, _dma_, __func__, __LINE__) ++# endif ++ ++# if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++#define DWC_DMA_ALLOC(_ctx_,_size_,_dma_) dwc_dma_alloc_debug(_ctx_, _size_, \ ++ _dma_, __func__, __LINE__) ++#define DWC_DMA_FREE(_ctx_,_size_,_virt_,_dma_) dwc_dma_free_debug(_ctx_, _size_, \ ++ _virt_, _dma_, __func__, __LINE__) ++# endif ++ ++#endif /* DWC_DEBUG_MEMORY */ ++ ++#define dwc_alloc(_ctx_,_size_) DWC_ALLOC(_size_) ++#define dwc_alloc_atomic(_ctx_,_size_) DWC_ALLOC_ATOMIC(_size_) ++#define dwc_free(_ctx_,_addr_) DWC_FREE(_addr_) ++ ++#ifdef DWC_LINUX ++/* Linux doesn't need any extra parameters for DMA buffer allocation, so we ++ * just throw away the DMA context parameter. ++ */ ++#define dwc_dma_alloc(_ctx_,_size_,_dma_) DWC_DMA_ALLOC(_size_, _dma_) ++#define dwc_dma_alloc_atomic(_ctx_,_size_,_dma_) DWC_DMA_ALLOC_ATOMIC(_size_, _dma_) ++#define dwc_dma_free(_ctx_,_size_,_virt_,_dma_) DWC_DMA_FREE(_size_, _virt_, _dma_) ++#endif ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++/** BSD needs several extra parameters for DMA buffer allocation, so we pass ++ * them in using the DMA context parameter. ++ */ ++#define dwc_dma_alloc DWC_DMA_ALLOC ++#define dwc_dma_free DWC_DMA_FREE ++#endif ++ ++ ++/** @name Memory and String Processing */ ++ ++/** memset() clone */ ++extern void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size); ++#define dwc_memset DWC_MEMSET ++ ++/** memcpy() clone */ ++extern void *DWC_MEMCPY(void *dest, void const *src, uint32_t size); ++#define dwc_memcpy DWC_MEMCPY ++ ++/** memmove() clone */ ++extern void *DWC_MEMMOVE(void *dest, void *src, uint32_t size); ++#define dwc_memmove DWC_MEMMOVE ++ ++/** memcmp() clone */ ++extern int DWC_MEMCMP(void *m1, void *m2, uint32_t size); ++#define dwc_memcmp DWC_MEMCMP ++ ++/** strcmp() clone */ ++extern int DWC_STRCMP(void *s1, void *s2); ++#define dwc_strcmp DWC_STRCMP ++ ++/** strncmp() clone */ ++extern int DWC_STRNCMP(void *s1, void *s2, uint32_t size); ++#define dwc_strncmp DWC_STRNCMP ++ ++/** strlen() clone, for NULL terminated ASCII strings */ ++extern int DWC_STRLEN(char const *str); ++#define dwc_strlen DWC_STRLEN ++ ++/** strcpy() clone, for NULL terminated ASCII strings */ ++extern char *DWC_STRCPY(char *to, const char *from); ++#define dwc_strcpy DWC_STRCPY ++ ++/** strdup() clone. If you wish to use memory allocation debugging, this ++ * implementation of strdup should use the DWC_* memory routines instead of ++ * calling a predefined strdup. Otherwise the memory allocated by this routine ++ * will not be seen by the debugging routines. */ ++extern char *DWC_STRDUP(char const *str); ++#define dwc_strdup(_ctx_,_str_) DWC_STRDUP(_str_) ++ ++/** NOT an atoi() clone. Read the description carefully. Returns an integer ++ * converted from the string str in base 10 unless the string begins with a "0x" ++ * in which case it is base 16. String must be a NULL terminated sequence of ++ * ASCII characters and may optionally begin with whitespace, a + or -, and a ++ * "0x" prefix if base 16. The remaining characters must be valid digits for ++ * the number and end with a NULL character. If any invalid characters are ++ * encountered or it returns with a negative error code and the results of the ++ * conversion are undefined. On sucess it returns 0. Overflow conditions are ++ * undefined. An example implementation using atoi() can be referenced from the ++ * Linux implementation. */ ++extern int DWC_ATOI(const char *str, int32_t *value); ++#define dwc_atoi DWC_ATOI ++ ++/** Same as above but for unsigned. */ ++extern int DWC_ATOUI(const char *str, uint32_t *value); ++#define dwc_atoui DWC_ATOUI ++ ++#ifdef DWC_UTFLIB ++/** This routine returns a UTF16LE unicode encoded string from a UTF8 string. */ ++extern int DWC_UTF8_TO_UTF16LE(uint8_t const *utf8string, uint16_t *utf16string, unsigned len); ++#define dwc_utf8_to_utf16le DWC_UTF8_TO_UTF16LE ++#endif ++ ++ ++/** @name Wait queues ++ * ++ * Wait queues provide a means of synchronizing between threads or processes. A ++ * process can block on a waitq if some condition is not true, waiting for it to ++ * become true. When the waitq is triggered all waiting process will get ++ * unblocked and the condition will be check again. Waitqs should be triggered ++ * every time a condition can potentially change.*/ ++struct dwc_waitq; ++ ++/** Type for a waitq */ ++typedef struct dwc_waitq dwc_waitq_t; ++ ++/** The type of waitq condition callback function. This is called every time ++ * condition is evaluated. */ ++typedef int (*dwc_waitq_condition_t)(void *data); ++ ++/** Allocate a waitq */ ++extern dwc_waitq_t *DWC_WAITQ_ALLOC(void); ++#define dwc_waitq_alloc(_ctx_) DWC_WAITQ_ALLOC() ++ ++/** Free a waitq */ ++extern void DWC_WAITQ_FREE(dwc_waitq_t *wq); ++#define dwc_waitq_free DWC_WAITQ_FREE ++ ++/** Check the condition and if it is false, block on the waitq. When unblocked, check the ++ * condition again. The function returns when the condition becomes true. The return value ++ * is 0 on condition true, DWC_WAITQ_ABORTED on abort or killed, or DWC_WAITQ_UNKNOWN on error. */ ++extern int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data); ++#define dwc_waitq_wait DWC_WAITQ_WAIT ++ ++/** Check the condition and if it is false, block on the waitq. When unblocked, ++ * check the condition again. The function returns when the condition become ++ * true or the timeout has passed. The return value is 0 on condition true or ++ * DWC_TIMED_OUT on timeout, or DWC_WAITQ_ABORTED, or DWC_WAITQ_UNKNOWN on ++ * error. */ ++extern int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, ++ void *data, int32_t msecs); ++#define dwc_waitq_wait_timeout DWC_WAITQ_WAIT_TIMEOUT ++ ++/** Trigger a waitq, unblocking all processes. This should be called whenever a condition ++ * has potentially changed. */ ++extern void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq); ++#define dwc_waitq_trigger DWC_WAITQ_TRIGGER ++ ++/** Unblock all processes waiting on the waitq with an ABORTED result. */ ++extern void DWC_WAITQ_ABORT(dwc_waitq_t *wq); ++#define dwc_waitq_abort DWC_WAITQ_ABORT ++ ++ ++/** @name Threads ++ * ++ * A thread must be explicitly stopped. It must check DWC_THREAD_SHOULD_STOP ++ * whenever it is woken up, and then return. The DWC_THREAD_STOP function ++ * returns the value from the thread. ++ */ ++ ++struct dwc_thread; ++ ++/** Type for a thread */ ++typedef struct dwc_thread dwc_thread_t; ++ ++/** The thread function */ ++typedef int (*dwc_thread_function_t)(void *data); ++ ++/** Create a thread and start it running the thread_function. Returns a handle ++ * to the thread */ ++extern dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data); ++#define dwc_thread_run(_ctx_,_func_,_name_,_data_) DWC_THREAD_RUN(_func_, _name_, _data_) ++ ++/** Stops a thread. Return the value returned by the thread. Or will return ++ * DWC_ABORT if the thread never started. */ ++extern int DWC_THREAD_STOP(dwc_thread_t *thread); ++#define dwc_thread_stop DWC_THREAD_STOP ++ ++/** Signifies to the thread that it must stop. */ ++#ifdef DWC_LINUX ++/* Linux doesn't need any parameters for kthread_should_stop() */ ++extern dwc_bool_t DWC_THREAD_SHOULD_STOP(void); ++#define dwc_thread_should_stop(_thrd_) DWC_THREAD_SHOULD_STOP() ++ ++/* No thread_exit function in Linux */ ++#define dwc_thread_exit(_thrd_) ++#endif ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++/** BSD needs the thread pointer for kthread_suspend_check() */ ++extern dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread); ++#define dwc_thread_should_stop DWC_THREAD_SHOULD_STOP ++ ++/** The thread must call this to exit. */ ++extern void DWC_THREAD_EXIT(dwc_thread_t *thread); ++#define dwc_thread_exit DWC_THREAD_EXIT ++#endif ++ ++ ++/** @name Work queues ++ * ++ * Workqs are used to queue a callback function to be called at some later time, ++ * in another thread. */ ++struct dwc_workq; ++ ++/** Type for a workq */ ++typedef struct dwc_workq dwc_workq_t; ++ ++/** The type of the callback function to be called. */ ++typedef void (*dwc_work_callback_t)(void *data); ++ ++/** Allocate a workq */ ++extern dwc_workq_t *DWC_WORKQ_ALLOC(char *name); ++#define dwc_workq_alloc(_ctx_,_name_) DWC_WORKQ_ALLOC(_name_) ++ ++/** Free a workq. All work must be completed before being freed. */ ++extern void DWC_WORKQ_FREE(dwc_workq_t *workq); ++#define dwc_workq_free DWC_WORKQ_FREE ++ ++/** Schedule a callback on the workq, passing in data. The function will be ++ * scheduled at some later time. */ ++extern void DWC_WORKQ_SCHEDULE(dwc_workq_t *workq, dwc_work_callback_t cb, ++ void *data, char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 4, 5))); ++#else ++ ; ++#endif ++#define dwc_workq_schedule DWC_WORKQ_SCHEDULE ++ ++/** Schedule a callback on the workq, that will be called until at least ++ * given number miliseconds have passed. */ ++extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t cb, ++ void *data, uint32_t time, char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 5, 6))); ++#else ++ ; ++#endif ++#define dwc_workq_schedule_delayed DWC_WORKQ_SCHEDULE_DELAYED ++ ++/** The number of processes in the workq */ ++extern int DWC_WORKQ_PENDING(dwc_workq_t *workq); ++#define dwc_workq_pending DWC_WORKQ_PENDING ++ ++/** Blocks until all the work in the workq is complete or timed out. Returns < ++ * 0 on timeout. */ ++extern int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout); ++#define dwc_workq_wait_work_done DWC_WORKQ_WAIT_WORK_DONE ++ ++ ++/** @name Tasklets ++ * ++ */ ++struct dwc_tasklet; ++ ++/** Type for a tasklet */ ++typedef struct dwc_tasklet dwc_tasklet_t; ++ ++/** The type of the callback function to be called */ ++typedef void (*dwc_tasklet_callback_t)(void *data); ++ ++/** Allocates a tasklet */ ++extern dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data); ++#define dwc_task_alloc(_ctx_,_name_,_cb_,_data_) DWC_TASK_ALLOC(_name_, _cb_, _data_) ++ ++/** Frees a tasklet */ ++extern void DWC_TASK_FREE(dwc_tasklet_t *task); ++#define dwc_task_free DWC_TASK_FREE ++ ++/** Schedules a tasklet to run */ ++extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task); ++#define dwc_task_schedule DWC_TASK_SCHEDULE ++ ++ ++/** @name Timer ++ * ++ * Callbacks must be small and atomic. ++ */ ++struct dwc_timer; ++ ++/** Type for a timer */ ++typedef struct dwc_timer dwc_timer_t; ++ ++/** The type of the callback function to be called */ ++typedef void (*dwc_timer_callback_t)(void *data); ++ ++/** Allocates a timer */ ++extern dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data); ++#define dwc_timer_alloc(_ctx_,_name_,_cb_,_data_) DWC_TIMER_ALLOC(_name_,_cb_,_data_) ++ ++/** Frees a timer */ ++extern void DWC_TIMER_FREE(dwc_timer_t *timer); ++#define dwc_timer_free DWC_TIMER_FREE ++ ++/** Schedules the timer to run at time ms from now. And will repeat at every ++ * repeat_interval msec therafter ++ * ++ * Modifies a timer that is still awaiting execution to a new expiration time. ++ * The mod_time is added to the old time. */ ++extern void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time); ++#define dwc_timer_schedule DWC_TIMER_SCHEDULE ++ ++/** Disables the timer from execution. */ ++extern void DWC_TIMER_CANCEL(dwc_timer_t *timer); ++#define dwc_timer_cancel DWC_TIMER_CANCEL ++ ++ ++/** @name Spinlocks ++ * ++ * These locks are used when the work between the lock/unlock is atomic and ++ * short. Interrupts are also disabled during the lock/unlock and thus they are ++ * suitable to lock between interrupt/non-interrupt context. They also lock ++ * between processes if you have multiple CPUs or Preemption. If you don't have ++ * multiple CPUS or Preemption, then the you can simply implement the ++ * DWC_SPINLOCK and DWC_SPINUNLOCK to disable and enable interrupts. Because ++ * the work between the lock/unlock is atomic, the process context will never ++ * change, and so you never have to lock between processes. */ ++ ++struct dwc_spinlock; ++ ++/** Type for a spinlock */ ++typedef struct dwc_spinlock dwc_spinlock_t; ++ ++/** Type for the 'flags' argument to spinlock funtions */ ++typedef unsigned long dwc_irqflags_t; ++ ++/** Returns an initialized lock variable. This function should allocate and ++ * initialize the OS-specific data structure used for locking. This data ++ * structure is to be used for the DWC_LOCK and DWC_UNLOCK functions and should ++ * be freed by the DWC_FREE_LOCK when it is no longer used. */ ++extern dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void); ++#define dwc_spinlock_alloc(_ctx_) DWC_SPINLOCK_ALLOC() ++ ++/** Frees an initialized lock variable. */ ++extern void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock); ++#define dwc_spinlock_free(_ctx_,_lock_) DWC_SPINLOCK_FREE(_lock_) ++ ++/** Disables interrupts and blocks until it acquires the lock. ++ * ++ * @param lock Pointer to the spinlock. ++ * @param flags Unsigned long for irq flags storage. ++ */ ++extern void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags); ++#define dwc_spinlock_irqsave DWC_SPINLOCK_IRQSAVE ++ ++/** Re-enables the interrupt and releases the lock. ++ * ++ * @param lock Pointer to the spinlock. ++ * @param flags Unsigned long for irq flags storage. Must be the same as was ++ * passed into DWC_LOCK. ++ */ ++extern void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags); ++#define dwc_spinunlock_irqrestore DWC_SPINUNLOCK_IRQRESTORE ++ ++/** Blocks until it acquires the lock. ++ * ++ * @param lock Pointer to the spinlock. ++ */ ++extern void DWC_SPINLOCK(dwc_spinlock_t *lock); ++#define dwc_spinlock DWC_SPINLOCK ++ ++/** Releases the lock. ++ * ++ * @param lock Pointer to the spinlock. ++ */ ++extern void DWC_SPINUNLOCK(dwc_spinlock_t *lock); ++#define dwc_spinunlock DWC_SPINUNLOCK ++ ++ ++/** @name Mutexes ++ * ++ * Unlike spinlocks Mutexes lock only between processes and the work between the ++ * lock/unlock CAN block, therefore it CANNOT be called from interrupt context. ++ */ ++ ++struct dwc_mutex; ++ ++/** Type for a mutex */ ++typedef struct dwc_mutex dwc_mutex_t; ++ ++/* For Linux Mutex Debugging make it inline because the debugging routines use ++ * the symbol to determine recursive locking. This makes it falsely think ++ * recursive locking occurs. */ ++#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES) ++#define DWC_MUTEX_ALLOC_LINUX_DEBUG(__mutexp) ({ \ ++ __mutexp = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); \ ++ mutex_init((struct mutex *)__mutexp); \ ++}) ++#endif ++ ++/** Allocate a mutex */ ++extern dwc_mutex_t *DWC_MUTEX_ALLOC(void); ++#define dwc_mutex_alloc(_ctx_) DWC_MUTEX_ALLOC() ++ ++/* For memory leak debugging when using Linux Mutex Debugging */ ++#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES) ++#define DWC_MUTEX_FREE(__mutexp) do { \ ++ mutex_destroy((struct mutex *)__mutexp); \ ++ DWC_FREE(__mutexp); \ ++} while(0) ++#else ++/** Free a mutex */ ++extern void DWC_MUTEX_FREE(dwc_mutex_t *mutex); ++#define dwc_mutex_free(_ctx_,_mutex_) DWC_MUTEX_FREE(_mutex_) ++#endif ++ ++/** Lock a mutex */ ++extern void DWC_MUTEX_LOCK(dwc_mutex_t *mutex); ++#define dwc_mutex_lock DWC_MUTEX_LOCK ++ ++/** Non-blocking lock returns 1 on successful lock. */ ++extern int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex); ++#define dwc_mutex_trylock DWC_MUTEX_TRYLOCK ++ ++/** Unlock a mutex */ ++extern void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex); ++#define dwc_mutex_unlock DWC_MUTEX_UNLOCK ++ ++ ++/** @name Time */ ++ ++/** Microsecond delay. ++ * ++ * @param usecs Microseconds to delay. ++ */ ++extern void DWC_UDELAY(uint32_t usecs); ++#define dwc_udelay DWC_UDELAY ++ ++/** Millisecond delay. ++ * ++ * @param msecs Milliseconds to delay. ++ */ ++extern void DWC_MDELAY(uint32_t msecs); ++#define dwc_mdelay DWC_MDELAY ++ ++/** Non-busy waiting. ++ * Sleeps for specified number of milliseconds. ++ * ++ * @param msecs Milliseconds to sleep. ++ */ ++extern void DWC_MSLEEP(uint32_t msecs); ++#define dwc_msleep DWC_MSLEEP ++ ++/** ++ * Returns number of milliseconds since boot. ++ */ ++extern uint32_t DWC_TIME(void); ++#define dwc_time DWC_TIME ++ ++ ++ ++ ++/* @mainpage DWC Portability and Common Library ++ * ++ * This is the documentation for the DWC Portability and Common Library. ++ * ++ * @section intro Introduction ++ * ++ * The DWC Portability library consists of wrapper calls and data structures to ++ * all low-level functions which are typically provided by the OS. The WUDEV ++ * driver uses only these functions. In order to port the WUDEV driver, only ++ * the functions in this library need to be re-implemented, with the same ++ * behavior as documented here. ++ * ++ * The Common library consists of higher level functions, which rely only on ++ * calling the functions from the DWC Portability library. These common ++ * routines are shared across modules. Some of the common libraries need to be ++ * used directly by the driver programmer when porting WUDEV. Such as the ++ * parameter and notification libraries. ++ * ++ * @section low Portability Library OS Wrapper Functions ++ * ++ * Any function starting with DWC and in all CAPS is a low-level OS-wrapper that ++ * needs to be implemented when porting, for example DWC_MUTEX_ALLOC(). All of ++ * these functions are included in the dwc_os.h file. ++ * ++ * There are many functions here covering a wide array of OS services. Please ++ * see dwc_os.h for details, and implementation notes for each function. ++ * ++ * @section common Common Library Functions ++ * ++ * Any function starting with dwc and in all lowercase is a common library ++ * routine. These functions have a portable implementation and do not need to ++ * be reimplemented when porting. The common routines can be used by any ++ * driver, and some must be used by the end user to control the drivers. For ++ * example, you must use the Parameter common library in order to set the ++ * parameters in the WUDEV module. ++ * ++ * The common libraries consist of the following: ++ * ++ * - Connection Contexts - Used internally and can be used by end-user. See dwc_cc.h ++ * - Parameters - Used internally and can be used by end-user. See dwc_params.h ++ * - Notifications - Used internally and can be used by end-user. See dwc_notifier.h ++ * - Lists - Used internally and can be used by end-user. See dwc_list.h ++ * - Memory Debugging - Used internally and can be used by end-user. See dwc_os.h ++ * - Modpow - Used internally only. See dwc_modpow.h ++ * - DH - Used internally only. See dwc_dh.h ++ * - Crypto - Used internally only. See dwc_crypto.h ++ * ++ * ++ * @section prereq Prerequistes For dwc_os.h ++ * @subsection types Data Types ++ * ++ * The dwc_os.h file assumes that several low-level data types are pre defined for the ++ * compilation environment. These data types are: ++ * ++ * - uint8_t - unsigned 8-bit data type ++ * - int8_t - signed 8-bit data type ++ * - uint16_t - unsigned 16-bit data type ++ * - int16_t - signed 16-bit data type ++ * - uint32_t - unsigned 32-bit data type ++ * - int32_t - signed 32-bit data type ++ * - uint64_t - unsigned 64-bit data type ++ * - int64_t - signed 64-bit data type ++ * ++ * Ensure that these are defined before using dwc_os.h. The easiest way to do ++ * that is to modify the top of the file to include the appropriate header. ++ * This is already done for the Linux environment. If the DWC_LINUX macro is ++ * defined, the correct header will be added. A standard header is ++ * also used for environments where standard C headers are available. ++ * ++ * @subsection stdarg Variable Arguments ++ * ++ * Variable arguments are provided by a standard C header . it is ++ * available in Both the Linux and ANSI C enviornment. An equivalent must be ++ * provided in your enviornment in order to use dwc_os.h with the debug and ++ * tracing message functionality. ++ * ++ * @subsection thread Threading ++ * ++ * WUDEV Core must be run on an operating system that provides for multiple ++ * threads/processes. Threading can be implemented in many ways, even in ++ * embedded systems without an operating system. At the bare minimum, the ++ * system should be able to start any number of processes at any time to handle ++ * special work. It need not be a pre-emptive system. Process context can ++ * change upon a call to a blocking function. The hardware interrupt context ++ * that calls the module's ISR() function must be differentiable from process ++ * context, even if your processes are impemented via a hardware interrupt. ++ * Further locking mechanism between process must exist (or be implemented), and ++ * process context must have a way to disable interrupts for a period of time to ++ * lock them out. If all of this exists, the functions in dwc_os.h related to ++ * threading should be able to be implemented with the defined behavior. ++ * ++ */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_OS_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_adp.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_adp.c +new file mode 100644 +index 0000000..db309f3 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_adp.c +@@ -0,0 +1,908 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $ ++ * $Revision: #16 $ ++ * $Date: 2013/04/22 $ ++ * $Change: 2211149 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++#include "dwc_os.h" ++#include "dwc_otg_regs.h" ++#include "dwc_otg_cil.h" ++#include "dwc_otg_adp.h" ++ ++/** @file ++ * ++ * This file contains the most of the Attach Detect Protocol implementation for ++ * the driver to support OTG Rev2.0. ++ * ++ */ ++ ++void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value) ++{ ++ adpctl_data_t adpctl; ++ ++ adpctl.d32 = value; ++ adpctl.b.ar = 0x2; ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32); ++ ++ while (adpctl.b.ar) { ++ adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl); ++ } ++ ++} ++ ++/** ++ * Function is called to read ADP registers ++ */ ++uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ adpctl.d32 = 0; ++ adpctl.b.ar = 0x1; ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32); ++ ++ while (adpctl.b.ar) { ++ adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl); ++ } ++ ++ return adpctl.d32; ++} ++ ++/** ++ * Function is called to read ADPCTL register and filter Write-clear bits ++ */ ++uint32_t dwc_otg_adp_read_reg_filter(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ adpctl.b.adp_tmout_int = 0; ++ adpctl.b.adp_prb_int = 0; ++ adpctl.b.adp_tmout_int = 0; ++ ++ return adpctl.d32; ++} ++ ++/** ++ * Function is called to write ADP registers ++ */ ++void dwc_otg_adp_modify_reg(dwc_otg_core_if_t * core_if, uint32_t clr, ++ uint32_t set) ++{ ++ dwc_otg_adp_write_reg(core_if, ++ (dwc_otg_adp_read_reg(core_if) & (~clr)) | set); ++} ++ ++static void adp_probe_func(void * ptr) ++{ ++ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; ++ dwc_otg_adp_probe_start(core_if); ++} ++ ++static void adp_sense_timeout(void *ptr) ++{ ++ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; ++ core_if->adp.sense_timer_started = 0; ++ DWC_DEBUGPL(DBG_PCD, "ADP SENSE TIMEOUT\n"); ++ if (core_if->adp_enable) { ++ dwc_otg_adp_sense_stop(core_if); ++ DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg, adp_probe_func, ++ core_if, 100 , "start probe"); ++ } ++} ++ ++/** ++ * This function is called when the ADP vbus timer expires. Timeout is 1.1s. ++ */ ++static void adp_vbuson_timeout(void *ptr) ++{ ++ gpwrdn_data_t gpwrdn; ++ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ DWC_PRINTF("%s: 1.1 seconds expire after turning on VBUS\n",__FUNCTION__); ++ if (core_if) { ++ core_if->adp.vbuson_timer_started = 0; ++ if(dwc_otg_is_host_mode(core_if)) { ++ /* Turn off vbus */ ++ hprt0.b.prtpwr = 1; ++ DWC_MODIFY_REG32(core_if->host_if->hprt0, hprt0.d32, 0); ++ cil_hcd_disconnect(core_if); ++ } ++ gpwrdn.d32 = 0; ++ ++ /* Power off the core */ ++ if (core_if->power_down == 2) { ++ /* Enable Wakeup Logic */ ++// gpwrdn.b.wkupactiv = 1; ++ gpwrdn.b.pmuactv = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, ++ gpwrdn.d32); ++ ++ /* Suspend the Phy Clock */ ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ /* Switch on VDD */ ++// gpwrdn.b.wkupactiv = 1; ++ gpwrdn.b.pmuactv = 1; ++ gpwrdn.b.pwrdnrstn = 1; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, ++ gpwrdn.d32); ++ } else { ++ /* Enable Power Down Logic */ ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ if(dwc_otg_is_host_mode(core_if)) ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ /* Power off the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ } ++ ++ /* Unmask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ ++ dwc_mdelay(220); ++ dwc_otg_adp_probe_start(core_if); ++ } ++ ++} ++ ++/** ++ * Start the ADP Initial Probe timer to detect if Port Connected interrupt is ++ * not asserted within 1.1 seconds. ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++void dwc_otg_adp_vbuson_timer_start(dwc_otg_core_if_t * core_if) ++{ ++ core_if->adp.vbuson_timer_started = 1; ++ if (core_if->adp.vbuson_timer) ++ { ++ DWC_PRINTF("SCHEDULING VBUSON TIMER\n"); ++ /* 1.1 secs + 60ms necessary for cil_hcd_start*/ ++ DWC_TIMER_SCHEDULE(core_if->adp.vbuson_timer, 1160); ++ } else { ++ DWC_WARN("VBUSON_TIMER = %p\n",core_if->adp.vbuson_timer); ++ } ++} ++ ++#if 0 ++/** ++ * Masks all DWC OTG core interrupts ++ * ++ */ ++static void mask_all_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ int i; ++ gahbcfg_data_t ahbcfg = {.d32 = 0 }; ++ ++ /* Mask Host Interrupts */ ++ ++ /* Clear and disable HCINTs */ ++ for (i = 0; i < core_if->core_params->host_channels; i++) { ++ DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, 0); ++ DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcint, 0xFFFFFFFF); ++ ++ } ++ ++ /* Clear and disable HAINT */ ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, 0x0000); ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haint, 0xFFFFFFFF); ++ ++ /* Mask Device Interrupts */ ++ if (!core_if->multiproc_int_enable) { ++ /* Clear and disable IN Endpoint interrupts */ ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, 0); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]-> ++ diepint, 0xFFFFFFFF); ++ } ++ ++ /* Clear and disable OUT Endpoint interrupts */ ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, 0); ++ for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]-> ++ doepint, 0xFFFFFFFF); ++ } ++ ++ /* Clear and disable DAINT */ ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daint, ++ 0xFFFFFFFF); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, 0); ++ } else { ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs-> ++ diepeachintmsk[i], 0); ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]-> ++ diepint, 0xFFFFFFFF); ++ } ++ ++ for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[i], 0); ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]-> ++ doepint, 0xFFFFFFFF); ++ } ++ ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachintmsk, ++ 0); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachint, ++ 0xFFFFFFFF); ++ ++ } ++ ++ /* Disable interrupts */ ++ ahbcfg.b.glblintrmsk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0); ++ ++ /* Disable all interrupts. */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0); ++ ++ /* Clear any pending interrupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Clear any pending OTG Interrupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, 0xFFFFFFFF); ++} ++ ++/** ++ * Unmask Port Connection Detected interrupt ++ * ++ */ ++static void unmask_conn_det_intr(dwc_otg_core_if_t * core_if) ++{ ++ gintmsk_data_t gintmsk = {.d32 = 0,.b.portintr = 1 }; ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32); ++} ++#endif ++ ++/** ++ * Starts the ADP Probing ++ * ++ * @param core_if the pointer to core_if structure. ++ */ ++uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if) ++{ ++ ++ adpctl_data_t adpctl = {.d32 = 0}; ++ gpwrdn_data_t gpwrdn; ++#if 0 ++ adpctl_data_t adpctl_int = {.d32 = 0, .b.adp_prb_int = 1, ++ .b.adp_sns_int = 1, b.adp_tmout_int}; ++#endif ++ if (core_if->stop_adpprb) { ++ core_if->stop_adpprb = 0; ++ return 0; ++ } ++ ++ dwc_otg_disable_global_interrupts(core_if); ++ DWC_DEBUGPL(DBG_ANY, "ADP Probe Start\n"); ++ core_if->adp.probe_enabled = 1; ++ ++ adpctl.b.adpres = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ while (adpctl.b.adpres) { ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ } ++ ++ adpctl.d32 = 0; ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ /* In Host mode unmask SRP detected interrupt also change the ++ * probe preiod accordingly */ ++ if (!gpwrdn.b.idsts) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ adpctl.b.prb_per = 0; ++ } ++ else { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ gpwrdn.d32 = 0; ++ gpwrdn.b.sts_chngint_msk = 1; ++ adpctl.b.prb_per = 1; ++ } ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ ++ adpctl.b.adp_tmout_int_msk = 1; ++ adpctl.b.adp_prb_int_msk = 1; ++ adpctl.b.prb_dschg = 1; ++ adpctl.b.prb_delta = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ adpctl.b.adpen = 1; ++ adpctl.b.enaprb = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ DWC_DEBUGPL(DBG_ANY, "ADP Probe Finish\n"); ++ ++ return 0; ++} ++ ++/** ++ * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted ++ * within 3 seconds. ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++void dwc_otg_adp_sense_timer_start(dwc_otg_core_if_t * core_if) ++{ ++ core_if->adp.sense_timer_started = 1; ++ DWC_TIMER_SCHEDULE(core_if->adp.sense_timer, 3300 /* 3.3 secs */ ); ++} ++ ++/** ++ * Starts the ADP Sense ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ DWC_DEBUGPL(DBG_PCD, "ADP Sense Start\n"); ++ ++ /* Set ADP reset bit*/ ++ adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if); ++ adpctl.b.adpres = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ while (adpctl.b.adpres) { ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ } ++ ++ /* Unmask ADP sense interrupt and mask all other from the core */ ++ adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if); ++ adpctl.b.adp_sns_int_msk = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ dwc_otg_disable_global_interrupts(core_if); ++ ++ adpctl.b.adpres = 0; ++ adpctl.b.adpen = 1; ++ adpctl.b.enasns = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ dwc_otg_adp_sense_timer_start(core_if); ++ ++ return 0; ++} ++ ++/** ++ * Stops the ADP Probing ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if) ++{ ++ ++ adpctl_data_t adpctl; ++ DWC_DEBUGPL(DBG_ANY, "Stop ADP probe\n"); ++ core_if->adp.probe_enabled = 0; ++ //core_if->adp.probe_counter = 0; ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ ++ adpctl.b.adpen = 0; ++ adpctl.b.adp_prb_int = 1; ++ adpctl.b.adp_tmout_int = 1; ++ adpctl.b.adp_sns_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * Stops the ADP Sensing ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ core_if->adp.sense_enabled = 0; ++ ++ adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if); ++ adpctl.b.enasns = 0; ++ adpctl.b.adp_sns_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * Called to turn on the VBUS after initial ADP probe in host mode. ++ * If port power was already enabled in cil_hcd_start function then ++ * only schedule a timer. ++ * ++ * @param core_if the pointer to core_if structure. ++ */ ++void dwc_otg_adp_turnon_vbus(dwc_otg_core_if_t * core_if) ++{ ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ DWC_PRINTF("Turn on VBUS for 1.1s, port power is %d\n", hprt0.b.prtpwr); ++ ++ if (hprt0.b.prtpwr == 0) { ++ hprt0.b.prtpwr = 1; ++ //DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } ++ ++ dwc_otg_adp_vbuson_timer_start(core_if); ++} ++ ++/** ++ * Called right after driver is loaded ++ * to perform initial actions for ADP ++ * ++ * @param core_if the pointer to core_if structure. ++ * @param is_host - flag for current mode of operation either from GINTSTS or GPWRDN ++ */ ++void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host) ++{ ++ gpwrdn_data_t gpwrdn; ++ ++ DWC_DEBUGPL(DBG_ANY, "ADP Initial Start\n"); ++ core_if->adp.adp_started = 1; ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ dwc_otg_disable_global_interrupts(core_if); ++ if (is_host) { ++ DWC_PRINTF("HOST MODE\n"); ++ //core_if->op_state = A_HOST; - vahrama, modified checking in hcd_start() ++ /* Enable Power Down Logic Interrupt*/ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ /* Initialize first ADP probe to obtain Ramp Time value */ ++ core_if->adp.initial_probe = 1; ++ dwc_otg_adp_probe_start(core_if); ++ } else { ++ gotgctl_data_t gotgctl; ++ gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ DWC_DEBUGPL(DBG_ANY, "DEVICE MODE\n"); ++ //dwc_otg_core_init(core_if); ++ if (gotgctl.b.bsesvld == 0) { ++ /* Enable Power Down Logic Interrupt*/ ++ gpwrdn.d32 = 0; ++ DWC_DEBUGPL(DBG_ANY, "VBUS is not valid - start ADP probe\n"); ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ /* Do not need to return to inital probe if we are coming back to ++ * the device mode after HNP */ ++ if (core_if->op_state != B_HOST) ++ core_if->adp.initial_probe = 1; ++ dwc_otg_adp_probe_start(core_if); ++ } else { ++ DWC_PRINTF("VBUS is valid - initialize core as a Device\n"); ++ core_if->op_state = B_PERIPHERAL; ++ //dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ dwc_otg_dump_global_registers(core_if); ++ dwc_otg_dump_dev_registers(core_if); ++ } ++ } ++} ++ ++void dwc_otg_adp_init(dwc_otg_core_if_t * core_if) ++{ ++ core_if->adp.adp_started = 0; ++ core_if->adp.initial_probe = 0; ++ core_if->adp.probe_timer_values[0] = -1; ++ core_if->adp.probe_timer_values[1] = -1; ++ core_if->adp.probe_enabled = 0; ++ core_if->adp.sense_enabled = 0; ++ core_if->adp.sense_timer_started = 0; ++ core_if->adp.vbuson_timer_started = 0; ++ core_if->adp.probe_counter = 0; ++ core_if->adp.gpwrdn = 0; ++ core_if->adp.attached = DWC_OTG_ADP_UNKOWN; ++ /* Initialize timers */ ++ core_if->adp.sense_timer = ++ DWC_TIMER_ALLOC("ADP SENSE TIMER", adp_sense_timeout, core_if); ++ core_if->adp.vbuson_timer = ++ DWC_TIMER_ALLOC("ADP VBUS ON TIMER", adp_vbuson_timeout, core_if); ++ if (!core_if->adp.sense_timer || !core_if->adp.vbuson_timer) ++ { ++ DWC_ERROR("Could not allocate memory for ADP timers\n"); ++ } ++} ++ ++void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = { .d32 = 0 }; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ if (core_if->adp.probe_enabled) ++ dwc_otg_adp_probe_stop(core_if); ++ if (core_if->adp.sense_enabled) ++ dwc_otg_adp_sense_stop(core_if); ++ if (core_if->adp.sense_timer_started) ++ DWC_TIMER_CANCEL(core_if->adp.sense_timer); ++ if (core_if->adp.vbuson_timer_started) ++ DWC_TIMER_CANCEL(core_if->adp.vbuson_timer); ++ DWC_TIMER_FREE(core_if->adp.sense_timer); ++ DWC_TIMER_FREE(core_if->adp.vbuson_timer); ++} ++ ++///////////////////////////////////////////////////////////////////// ++////////////// ADP Interrupt Handlers /////////////////////////////// ++///////////////////////////////////////////////////////////////////// ++/** ++ * This function sets Ramp Timer values ++ */ ++static uint32_t set_timer_value(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ if (core_if->adp.probe_timer_values[0] == -1) { ++ core_if->adp.probe_timer_values[0] = val; ++ core_if->adp.probe_timer_values[1] = -1; ++ return 1; ++ } else { ++ core_if->adp.probe_timer_values[1] = ++ core_if->adp.probe_timer_values[0]; ++ core_if->adp.probe_timer_values[0] = val; ++ return 0; ++ } ++} ++ ++/** ++ * This function compares Ramp Timer values ++ */ ++static uint32_t compare_timer_values(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t diff; ++ uint32_t thres; ++ gpwrdn_data_t gpwrdn; ++ ++ /* RTIM difference thresold differs for host and device modes */ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (!gpwrdn.b.idsts) ++ thres = HOST_RTIM_THRESHOLD; ++ else ++ thres = DEVICE_RTIM_THRESHOLD; ++ ++ DWC_DEBUGPL(DBG_ANY, "timer value 0 %d timer value 1 %d\n", ++ core_if->adp.probe_timer_values[0], core_if->adp.probe_timer_values[1]); ++ if (core_if->adp.probe_timer_values[0] >= core_if->adp.probe_timer_values[1]) ++ diff = core_if->adp.probe_timer_values[0] - core_if->adp.probe_timer_values[1]; ++ else ++ diff = core_if->adp.probe_timer_values[1] - core_if->adp.probe_timer_values[0]; ++ if (diff < thres) ++ return 0; ++ else ++ return 1; ++} ++ ++/** ++ * This function handles ADP Probe Interrupts ++ */ ++static int32_t dwc_otg_adp_handle_prb_intr(dwc_otg_core_if_t * core_if, ++ uint32_t val) ++{ ++ adpctl_data_t adpctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn, temp; ++ adpctl.d32 = val; ++ ++ temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ core_if->adp.gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (adpctl.b.rtim == 0 /*&& !temp.b.idsts*/){ ++ DWC_PRINTF("RTIM value is 0\n"); ++ goto exit; ++ } ++ core_if->adp.probe_counter++; ++ ++ if (set_timer_value(core_if, adpctl.b.rtim) && ++ core_if->adp.initial_probe) { ++ core_if->adp.initial_probe = 0; ++ dwc_otg_adp_probe_stop(core_if); ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* check which value is for device mode and which for Host mode */ ++ if (!temp.b.idsts) { /* considered host mode value is 0 */ ++ /* Choose right op_state depending on previous one */ ++ if (core_if->op_state == B_PERIPHERAL) ++ core_if->op_state = B_HOST; ++ else ++ core_if->op_state = A_HOST; ++ dwc_otg_enable_global_interrupts(core_if); ++ /* ++ * Turn on VBUS after initial ADP probe. ++ */ ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_hcd_start(core_if); ++ dwc_otg_adp_turnon_vbus(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ } else { ++ /* ++ * Initiate SRP after initial ADP probe. ++ */ ++ dwc_otg_enable_global_interrupts(core_if); ++ dwc_otg_initiate_srp(core_if); ++ } ++ } else if (core_if->adp.probe_counter > 2){ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (compare_timer_values(core_if)) { ++ DWC_PRINTF("Difference in timer values !!! \n"); ++// core_if->adp.attached = DWC_OTG_ADP_ATTACHED; ++ dwc_otg_adp_probe_stop(core_if); ++ ++ /* Power on the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ /* check which value is for device mode and which for Host mode */ ++ if (!temp.b.idsts) { /* considered host mode value is 0 */ ++ /* Disable Interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Host mode. ++ * Choose right op_state depending on previous one ++ */ ++ if (core_if->op_state == B_PERIPHERAL) ++ core_if->op_state = B_HOST; ++ else ++ core_if->op_state = A_HOST; ++ ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ dwc_otg_adp_turnon_vbus(core_if); ++ } else { ++ gotgctl_data_t gotgctl; ++ /* Mask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* Disable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Device mode. ++ */ ++ core_if->op_state = B_PERIPHERAL; ++ //dwc_otg_core_init(core_if); ++ cil_pcd_start(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ ++ gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ if (!gotgctl.b.bsesvld) ++ dwc_otg_initiate_srp(core_if); ++ } ++ } ++ if (core_if->power_down == 2) { ++ if (gpwrdn.b.bsessvld) { ++ /* Mask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Disable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Device mode. ++ */ ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } ++ } ++ } ++exit: ++ /* Clear interrupt */ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ adpctl.b.adp_prb_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * This function hadles ADP Sense Interrupt ++ */ ++static int32_t dwc_otg_adp_handle_sns_intr(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ /* Stop ADP Sense timer */ ++ DWC_TIMER_CANCEL(core_if->adp.sense_timer); ++ ++ /* Restart ADP Sense timer */ ++ dwc_otg_adp_sense_timer_start(core_if); ++ ++ /* Clear interrupt */ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ adpctl.b.adp_sns_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * This function handles ADP Probe Interrupts ++ */ ++static int32_t dwc_otg_adp_handle_prb_tmout_intr(dwc_otg_core_if_t * core_if, ++ uint32_t val) ++{ ++ adpctl_data_t adpctl = {.d32 = 0 }; ++ adpctl.d32 = val; ++ set_timer_value(core_if, adpctl.b.rtim); ++ ++ /* Clear interrupt */ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ adpctl.b.adp_tmout_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * ADP Interrupt handler. ++ * ++ */ ++int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if) ++{ ++ int retval = 0; ++ adpctl_data_t adpctl = {.d32 = 0}; ++ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ DWC_DEBUGPL(DBG_ANY, "ADPCTL = %08x RAMP TIME = %d\n", adpctl.d32, adpctl.b.rtim); ++ ++ if (adpctl.b.adp_sns_int & adpctl.b.adp_sns_int_msk) { ++ DWC_DEBUGPL(DBG_ANY, "ADP Sense interrupt\n"); ++ retval |= dwc_otg_adp_handle_sns_intr(core_if); ++ } ++ if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) { ++ DWC_DEBUGPL(DBG_ANY, "ADP timeout interrupt\n"); ++ retval |= dwc_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32); ++ } ++ if (adpctl.b.adp_prb_int & adpctl.b.adp_prb_int_msk) { ++ DWC_DEBUGPL(DBG_ANY, "ADP Probe interrupt\n"); ++ adpctl.b.adp_prb_int = 1; ++ retval |= dwc_otg_adp_handle_prb_intr(core_if, adpctl.d32); ++ } ++ ++// dwc_otg_adp_modify_reg(core_if, adpctl.d32, 0); ++ //dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ DWC_DEBUGPL(DBG_ANY, "RETURN FROM ADP ISR\n"); ++ ++ return retval; ++} ++ ++/** ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if) ++{ ++ ++#ifndef DWC_HOST_ONLY ++ hprt0_data_t hprt0; ++ gpwrdn_data_t gpwrdn; ++ DWC_DEBUGPL(DBG_ANY, "++ Power Down Logic Session Request Interrupt++\n"); ++ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ /* check which value is for device mode and which for Host mode */ ++ if (!gpwrdn.b.idsts) { /* considered host mode value is 0 */ ++ DWC_PRINTF("SRP: Host mode\n"); ++ ++ if (core_if->adp_enable) { ++ dwc_otg_adp_probe_stop(core_if); ++ ++ /* Power on the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++ ++ /* Turn on the port power bit. */ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* Start the Connection timer. So a message can be displayed ++ * if connect does not occur within 10 seconds. */ ++ cil_hcd_session_start(core_if); ++ } else { ++ DWC_DEBUGPL(DBG_PCD, "SRP: Device mode %s\n", __FUNCTION__); ++ if (core_if->adp_enable) { ++ dwc_otg_adp_probe_stop(core_if); ++ ++ /* Power on the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 0; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, ++ gpwrdn.d32); ++ ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } ++ } ++#endif ++ return 1; ++} +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_adp.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_adp.h +new file mode 100644 +index 0000000..c21b2f0 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_adp.h +@@ -0,0 +1,82 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.h $ ++ * $Revision: #8 $ ++ * $Date: 2013/04/09 $ ++ * $Change: 2201932 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 __DWC_OTG_ADP_H__ ++#define __DWC_OTG_ADP_H__ ++ ++/** ++ * @file ++ * ++ * This file contains the Attach Detect Protocol interfaces and defines ++ * (functions) and structures for Linux. ++ * ++ */ ++ ++#define DWC_OTG_ADP_UNATTACHED 0 ++#define DWC_OTG_ADP_ATTACHED 1 ++#define DWC_OTG_ADP_UNKOWN 2 ++#define HOST_RTIM_THRESHOLD 5 ++#define DEVICE_RTIM_THRESHOLD 3 ++ ++typedef struct dwc_otg_adp { ++ uint32_t adp_started; ++ uint32_t initial_probe; ++ int32_t probe_timer_values[2]; ++ uint32_t probe_enabled; ++ uint32_t sense_enabled; ++ dwc_timer_t *sense_timer; ++ uint32_t sense_timer_started; ++ dwc_timer_t *vbuson_timer; ++ uint32_t vbuson_timer_started; ++ uint32_t attached; ++ uint32_t probe_counter; ++ uint32_t gpwrdn; ++} dwc_otg_adp_t; ++ ++/** ++ * Attach Detect Protocol functions ++ */ ++ ++extern void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value); ++extern uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if); ++extern uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if); ++extern uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if); ++extern uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if); ++extern uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host); ++extern void dwc_otg_adp_init(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if); ++extern int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if); ++extern int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if); ++ ++#endif //__DWC_OTG_ADP_H__ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_attr.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_attr.c +new file mode 100644 +index 0000000..73fc330 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_attr.c +@@ -0,0 +1,1311 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.c $ ++ * $Revision: #46 $ ++ * $Date: 2012/12/12 $ ++ * $Change: 2124654 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ * The diagnostic interface will provide access to the controller for ++ * bringing up the hardware and testing. The Linux driver attributes ++ * feature will be used to provide the Linux Diagnostic ++ * Interface. These attributes are accessed through sysfs. ++ */ ++ ++/** @page "Linux Module Attributes" ++ * ++ * The Linux module attributes feature is used to provide the Linux ++ * Diagnostic Interface. These attributes are accessed through sysfs. ++ * The diagnostic interface will provide access to the controller for ++ * bringing up the hardware and testing. ++ ++ The following table shows the attributes. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
Name Description Access
mode Returns the current mode: 0 for device mode, 1 for host mode Read
hnpcapable Gets or sets the "HNP-capable" bit in the Core USB Configuraton Register. ++ Read returns the current value. Read/Write
srpcapable Gets or sets the "SRP-capable" bit in the Core USB Configuraton Register. ++ Read returns the current value. Read/Write
hsic_connect Gets or sets the "HSIC-Connect" bit in the GLPMCFG Register. ++ Read returns the current value. Read/Write
inv_sel_hsic Gets or sets the "Invert Select HSIC" bit in the GLPMFG Register. ++ Read returns the current value. Read/Write
hnp Initiates the Host Negotiation Protocol. Read returns the status. Read/Write
srp Initiates the Session Request Protocol. Read returns the status. Read/Write
buspower Gets or sets the Power State of the bus (0 - Off or 1 - On) Read/Write
bussuspend Suspends the USB bus. Read/Write
busconnected Gets the connection status of the bus Read
gotgctl Gets or sets the Core Control Status Register. Read/Write
gusbcfg Gets or sets the Core USB Configuration Register Read/Write
grxfsiz Gets or sets the Receive FIFO Size Register Read/Write
gnptxfsiz Gets or sets the non-periodic Transmit Size Register Read/Write
gpvndctl Gets or sets the PHY Vendor Control Register Read/Write
ggpio Gets the value in the lower 16-bits of the General Purpose IO Register ++ or sets the upper 16 bits. Read/Write
guid Gets or sets the value of the User ID Register Read/Write
gsnpsid Gets the value of the Synopsys ID Regester Read
devspeed Gets or sets the device speed setting in the DCFG register Read/Write
enumspeed Gets the device enumeration Speed. Read
hptxfsiz Gets the value of the Host Periodic Transmit FIFO Read
hprt0 Gets or sets the value in the Host Port Control and Status Register Read/Write
regoffset Sets the register offset for the next Register Access Read/Write
regvalue Gets or sets the value of the register at the offset in the regoffset attribute. Read/Write
remote_wakeup On read, shows the status of Remote Wakeup. On write, initiates a remote ++ wakeup of the host. When bit 0 is 1 and Remote Wakeup is enabled, the Remote ++ Wakeup signalling bit in the Device Control Register is set for 1 ++ milli-second. Read/Write
rem_wakeup_pwrdn On read, shows the status core - hibernated or not. On write, initiates ++ a remote wakeup of the device from Hibernation. Read/Write
mode_ch_tim_en This bit is used to enable or disable the host core to wait for 200 PHY ++ clock cycles at the end of Resume to change the opmode signal to the PHY to 00 ++ after Suspend or LPM. Read/Write
fr_interval On read, shows the value of HFIR Frame Interval. On write, dynamically ++ reload HFIR register during runtime. The application can write a value to this ++ register only after the Port Enable bit of the Host Port Control and Status ++ register (HPRT.PrtEnaPort) has been set Read/Write
disconnect_us On read, shows the status of disconnect_device_us. On write, sets disconnect_us ++ which causes soft disconnect for 100us. Applicable only for device mode of operation. Read/Write
regdump Dumps the contents of core registers. Read
spramdump Dumps the contents of core registers. Read
hcddump Dumps the current HCD state. Read
hcd_frrem Shows the average value of the Frame Remaining ++ field in the Host Frame Number/Frame Remaining register when an SOF interrupt ++ occurs. This can be used to determine the average interrupt latency. Also ++ shows the average Frame Remaining value for start_transfer and the "a" and ++ "b" sample points. The "a" and "b" sample points may be used during debugging ++ bto determine how long it takes to execute a section of the HCD code. Read
rd_reg_test Displays the time required to read the GNPTXFSIZ register many times ++ (the output shows the number of times the register is read). ++ Read
wr_reg_test Displays the time required to write the GNPTXFSIZ register many times ++ (the output shows the number of times the register is written). ++ Read
lpm_response Gets or sets lpm_response mode. Applicable only in device mode. ++ Write
sleep_status Shows sleep status of device. ++ Read
hird_thres Gets or sets the "HIRD_Thres[3:0]" bits in the Core LPM Configuration Register. ++ Read/Write
besl_reject Gets or sets the "besl_reject" bit in the Device Control Register. ++ Read/Write
++ ++ Example usage: ++ To get the current mode: ++ cat /sys/devices/lm0/mode ++ ++ To power down the USB: ++ echo 0 > /sys/devices/lm0/buspower ++ */ ++ ++#include "dwc_otg_os_dep.h" ++#include "dwc_os.h" ++#include "dwc_otg_driver.h" ++#include "dwc_otg_attr.h" ++#include "dwc_otg_core_if.h" ++#include "dwc_otg_pcd_if.h" ++#include "dwc_otg_hcd_if.h" ++ ++/* ++ * MACROs for defining sysfs attribute ++ */ ++ ++ ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); \ ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); \ ++ uint32_t val; \ ++ val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ ++ return sprintf (buf, "%s = 0x%x\n", _string_, val); \ ++} ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); \ ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); \ ++ uint32_t set = simple_strtoul(buf, NULL, 16); \ ++ dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\ ++ return count; \ ++} ++ ++ ++/* ++ * MACROs for defining sysfs attribute for 32-bit registers ++ */ ++#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); \ ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); \ ++ uint32_t val; \ ++ val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ ++ return sprintf (buf, "%s = 0x%08x\n", _string_, val); \ ++} ++#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); \ ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); \ ++ uint32_t val = simple_strtoul(buf, NULL, 16); \ ++ dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \ ++ return count; \ ++} ++ ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_,_string_) \ ++DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ ++DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \ ++DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store); ++ ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_,_string_) \ ++DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ ++DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL); ++ ++#define DWC_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_,_addr_,_string_) \ ++DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ ++DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \ ++DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store); ++ ++#define DWC_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_,_addr_,_string_) \ ++DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ ++DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL); ++ ++/** @name Functions for Show/Store of Attributes */ ++/**@{*/ ++ ++/** ++ * Show the register offset of the Register Access. ++ */ ++static ssize_t regoffset_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ return snprintf(buf, sizeof("0xFFFFFFFF\n") + 1, "0x%08x\n", ++ otg_dev->os_dep.reg_offset); ++} ++ ++/** ++ * Set the register offset for the next Register Access Read/Write ++ */ ++static ssize_t regoffset_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ uint32_t offset = simple_strtoul(buf, NULL, 16); ++ if (offset < SZ_256K) { ++ otg_dev->os_dep.reg_offset = offset; ++ } else { ++ dev_err(_dev, "invalid offset\n"); ++ } ++ ++ return count; ++} ++ ++DEVICE_ATTR(regoffset, S_IRUGO | S_IWUSR, regoffset_show, regoffset_store); ++ ++/** ++ * Show the value of the register at the offset in the reg_offset ++ * attribute. ++ */ ++static ssize_t regvalue_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ uint32_t val; ++ volatile uint32_t *addr; ++ ++ if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) { ++ /* Calculate the address */ ++ addr = (uint32_t *) (otg_dev->os_dep.reg_offset + ++ (uint8_t *) otg_dev->os_dep.base); ++ val = DWC_READ_REG32(addr); ++ return snprintf(buf, ++ sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n") + 1, ++ "Reg@0x%06x = 0x%08x\n", otg_dev->os_dep.reg_offset, ++ val); ++ } else { ++ dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->os_dep.reg_offset); ++ return sprintf(buf, "invalid offset\n"); ++ } ++} ++ ++/** ++ * Store the value in the register at the offset in the reg_offset ++ * attribute. ++ * ++ */ ++static ssize_t regvalue_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ volatile uint32_t *addr; ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ //dev_dbg(_dev, "Offset=0x%08x Val=0x%08x\n", otg_dev->reg_offset, val); ++ if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) { ++ /* Calculate the address */ ++ addr = (uint32_t *) (otg_dev->os_dep.reg_offset + ++ (uint8_t *) otg_dev->os_dep.base); ++ DWC_WRITE_REG32(addr, val); ++ } else { ++ dev_err(_dev, "Invalid Register Offset (0x%08x)\n", ++ otg_dev->os_dep.reg_offset); ++ } ++ return count; ++} ++ ++DEVICE_ATTR(regvalue, S_IRUGO | S_IWUSR, regvalue_show, regvalue_store); ++ ++/* ++ * Attributes ++ */ ++DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode, "Mode"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable, "HNPCapable"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, "SRPCapable"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hsic_connect, "HSIC Connect"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(inv_sel_hsic, "Invert Select HSIC"); ++ ++//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(buspower,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode"); ++//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(bussuspend,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected, "Bus Connected"); ++ ++DWC_OTG_DEVICE_ATTR_REG32_RW(gotgctl, 0, "GOTGCTL"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(gusbcfg, ++ &(otg_dev->core_if->core_global_regs->gusbcfg), ++ "GUSBCFG"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(grxfsiz, ++ &(otg_dev->core_if->core_global_regs->grxfsiz), ++ "GRXFSIZ"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz, ++ &(otg_dev->core_if->core_global_regs->gnptxfsiz), ++ "GNPTXFSIZ"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(gpvndctl, ++ &(otg_dev->core_if->core_global_regs->gpvndctl), ++ "GPVNDCTL"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(ggpio, ++ &(otg_dev->core_if->core_global_regs->ggpio), ++ "GGPIO"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(guid, &(otg_dev->core_if->core_global_regs->guid), ++ "GUID"); ++DWC_OTG_DEVICE_ATTR_REG32_RO(gsnpsid, ++ &(otg_dev->core_if->core_global_regs->gsnpsid), ++ "GSNPSID"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed, "Device Speed"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed, "Device Enumeration Speed"); ++ ++DWC_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz, ++ &(otg_dev->core_if->core_global_regs->hptxfsiz), ++ "HPTXFSIZ"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(hprt0, otg_dev->core_if->host_if->hprt0, "HPRT0"); ++ ++/** ++ * @todo Add code to initiate the HNP. ++ */ ++/** ++ * Show the HNP status bit ++ */ ++static ssize_t hnp_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ return sprintf(buf, "HstNegScs = 0x%x\n", ++ dwc_otg_get_hnpstatus(otg_dev->core_if)); ++} ++ ++/** ++ * Set the HNP Request bit ++ */ ++static ssize_t hnp_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ uint32_t in = simple_strtoul(buf, NULL, 16); ++ dwc_otg_set_hnpreq(otg_dev->core_if, in); ++ return count; ++} ++ ++DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store); ++ ++/** ++ * @todo Add code to initiate the SRP. ++ */ ++/** ++ * Show the SRP status bit ++ */ ++static ssize_t srp_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef DWC_HOST_ONLY ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ return sprintf(buf, "SesReqScs = 0x%x\n", ++ dwc_otg_get_srpstatus(otg_dev->core_if)); ++#else ++ return sprintf(buf, "Host Only Mode!\n"); ++#endif ++} ++ ++/** ++ * Set the SRP Request bit ++ */ ++static ssize_t srp_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifndef DWC_HOST_ONLY ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ dwc_otg_pcd_initiate_srp(otg_dev->pcd); ++#endif ++ return count; ++} ++ ++DEVICE_ATTR(srp, 0644, srp_show, srp_store); ++ ++/** ++ * @todo Need to do more for power on/off? ++ */ ++/** ++ * Show the Bus Power status ++ */ ++static ssize_t buspower_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ return sprintf(buf, "Bus Power = 0x%x\n", ++ dwc_otg_get_prtpower(otg_dev->core_if)); ++} ++ ++/** ++ * Set the Bus Power status ++ */ ++static ssize_t buspower_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ uint32_t on = simple_strtoul(buf, NULL, 16); ++ dwc_otg_set_prtpower(otg_dev->core_if, on); ++ return count; ++} ++ ++DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store); ++ ++/** ++ * @todo Need to do more for suspend? ++ */ ++/** ++ * Show the Bus Suspend status ++ */ ++static ssize_t bussuspend_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ return sprintf(buf, "Bus Suspend = 0x%x\n", ++ dwc_otg_get_prtsuspend(otg_dev->core_if)); ++} ++ ++/** ++ * Set the Bus Suspend status ++ */ ++static ssize_t bussuspend_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ uint32_t in = simple_strtoul(buf, NULL, 16); ++ dwc_otg_set_prtsuspend(otg_dev->core_if, in); ++ return count; ++} ++ ++DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store); ++ ++/** ++ * Show the Mode Change Ready Timer status ++ */ ++static ssize_t mode_ch_tim_en_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ return sprintf(buf, "Mode Change Ready Timer Enable = 0x%x\n", ++ dwc_otg_get_mode_ch_tim(otg_dev->core_if)); ++} ++ ++/** ++ * Set the Mode Change Ready Timer status ++ */ ++static ssize_t mode_ch_tim_en_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ uint32_t in = simple_strtoul(buf, NULL, 16); ++ dwc_otg_set_mode_ch_tim(otg_dev->core_if, in); ++ return count; ++} ++ ++DEVICE_ATTR(mode_ch_tim_en, 0644, mode_ch_tim_en_show, mode_ch_tim_en_store); ++ ++/** ++ * Show the value of HFIR Frame Interval bitfield ++ */ ++static ssize_t fr_interval_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ return sprintf(buf, "Frame Interval = 0x%x\n", ++ dwc_otg_get_fr_interval(otg_dev->core_if)); ++} ++ ++/** ++ * Set the HFIR Frame Interval value ++ */ ++static ssize_t fr_interval_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ uint32_t in = simple_strtoul(buf, NULL, 10); ++ dwc_otg_set_fr_interval(otg_dev->core_if, in); ++ return count; ++} ++ ++DEVICE_ATTR(fr_interval, 0644, fr_interval_show, fr_interval_store); ++ ++/** ++ * Show the status of Remote Wakeup. ++ */ ++static ssize_t remote_wakeup_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef DWC_HOST_ONLY ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev =platform_get_drvdata(lm_dev); ++ ++ ++ return sprintf(buf, ++ "Remote Wakeup Sig = %d Enabled = %d LPM Remote Wakeup = %d\n", ++ dwc_otg_get_remotewakesig(otg_dev->core_if), ++ dwc_otg_pcd_get_rmwkup_enable(otg_dev->pcd), ++ dwc_otg_get_lpm_remotewakeenabled(otg_dev->core_if)); ++#else ++ return sprintf(buf, "Host Only Mode!\n"); ++#endif /* DWC_HOST_ONLY */ ++} ++ ++/** ++ * Initiate a remote wakeup of the host. The Device control register ++ * Remote Wakeup Signal bit is written if the PCD Remote wakeup enable ++ * flag is set. ++ * ++ */ ++static ssize_t remote_wakeup_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifndef DWC_HOST_ONLY ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ ++ if (val & 1) { ++ dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 1); ++ } else { ++ dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 0); ++ } ++#endif /* DWC_HOST_ONLY */ ++ return count; ++} ++ ++DEVICE_ATTR(remote_wakeup, S_IRUGO | S_IWUSR, remote_wakeup_show, ++ remote_wakeup_store); ++ ++/** ++ * Show the whether core is hibernated or not. ++ */ ++static ssize_t rem_wakeup_pwrdn_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef DWC_HOST_ONLY ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ if (dwc_otg_get_core_state(otg_dev->core_if)) { ++ DWC_PRINTF("Core is in hibernation\n"); ++ } else { ++ DWC_PRINTF("Core is not in hibernation\n"); ++ } ++#endif /* DWC_HOST_ONLY */ ++ return 0; ++} ++ ++extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int rem_wakeup, int reset); ++ ++/** ++ * Initiate a remote wakeup of the device to exit from hibernation. ++ */ ++static ssize_t rem_wakeup_pwrdn_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifndef DWC_HOST_ONLY ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ dwc_otg_device_hibernation_restore(otg_dev->core_if, 1, 0); ++#endif ++ return count; ++} ++ ++DEVICE_ATTR(rem_wakeup_pwrdn, S_IRUGO | S_IWUSR, rem_wakeup_pwrdn_show, ++ rem_wakeup_pwrdn_store); ++ ++static ssize_t disconnect_us(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++#ifndef DWC_HOST_ONLY ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ DWC_PRINTF("The Passed value is %04x\n", val); ++ ++ dwc_otg_pcd_disconnect_us(otg_dev->pcd, 50); ++ ++#endif /* DWC_HOST_ONLY */ ++ return count; ++} ++ ++DEVICE_ATTR(disconnect_us, S_IWUSR, 0, disconnect_us); ++ ++/** ++ * Dump global registers and either host or device registers (depending on the ++ * current mode of the core). ++ */ ++static ssize_t regdump_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ dwc_otg_dump_global_registers(otg_dev->core_if); ++ if (dwc_otg_is_host_mode(otg_dev->core_if)) { ++ dwc_otg_dump_host_registers(otg_dev->core_if); ++ } else { ++ dwc_otg_dump_dev_registers(otg_dev->core_if); ++ ++ } ++ return sprintf(buf, "Register Dump\n"); ++} ++ ++DEVICE_ATTR(regdump, S_IRUGO | S_IWUSR, regdump_show, 0); ++ ++/** ++ * Dump global registers and either host or device registers (depending on the ++ * current mode of the core). ++ */ ++static ssize_t spramdump_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ dwc_otg_dump_spram(otg_dev->core_if); ++ ++ return sprintf(buf, "SPRAM Dump\n"); ++} ++ ++DEVICE_ATTR(spramdump, S_IRUGO | S_IWUSR, spramdump_show, 0); ++ ++/** ++ * Dump the current hcd state. ++ */ ++static ssize_t hcddump_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef DWC_DEVICE_ONLY ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev =platform_get_drvdata(lm_dev); ++ ++ ++ dwc_otg_hcd_dump_state(otg_dev->hcd); ++#endif /* DWC_DEVICE_ONLY */ ++ return sprintf(buf, "HCD Dump\n"); ++} ++ ++DEVICE_ATTR(hcddump, S_IRUGO | S_IWUSR, hcddump_show, 0); ++ ++/** ++ * Dump the average frame remaining at SOF. This can be used to ++ * determine average interrupt latency. Frame remaining is also shown for ++ * start transfer and two additional sample points. ++ */ ++static ssize_t hcd_frrem_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef DWC_DEVICE_ONLY ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ dwc_otg_hcd_dump_frrem(otg_dev->hcd); ++#endif /* DWC_DEVICE_ONLY */ ++ return sprintf(buf, "HCD Dump Frame Remaining\n"); ++} ++ ++DEVICE_ATTR(hcd_frrem, S_IRUGO | S_IWUSR, hcd_frrem_show, 0); ++ ++/** ++ * Displays the time required to read the GNPTXFSIZ register many times (the ++ * output shows the number of times the register is read). ++ */ ++#define RW_REG_COUNT 10000000 ++#define MSEC_PER_JIFFIE 1000/HZ ++static ssize_t rd_reg_test_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ int i; ++ int time; ++ int start_jiffies; ++ ++ printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n", ++ HZ, MSEC_PER_JIFFIE, loops_per_jiffy); ++ start_jiffies = jiffies; ++ for (i = 0; i < RW_REG_COUNT; i++) { ++ dwc_otg_get_gnptxfsiz(otg_dev->core_if); ++ } ++ time = jiffies - start_jiffies; ++ return sprintf(buf, ++ "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n", ++ RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); ++} ++ ++DEVICE_ATTR(rd_reg_test, S_IRUGO | S_IWUSR, rd_reg_test_show, 0); ++ ++/** ++ * Displays the time required to write the GNPTXFSIZ register many times (the ++ * output shows the number of times the register is written). ++ */ ++static ssize_t wr_reg_test_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ uint32_t reg_val; ++ int i; ++ int time; ++ int start_jiffies; ++ ++ printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n", ++ HZ, MSEC_PER_JIFFIE, loops_per_jiffy); ++ reg_val = dwc_otg_get_gnptxfsiz(otg_dev->core_if); ++ start_jiffies = jiffies; ++ for (i = 0; i < RW_REG_COUNT; i++) { ++ dwc_otg_set_gnptxfsiz(otg_dev->core_if, reg_val); ++ } ++ time = jiffies - start_jiffies; ++ return sprintf(buf, ++ "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n", ++ RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); ++} ++ ++DEVICE_ATTR(wr_reg_test, S_IRUGO | S_IWUSR, wr_reg_test_show, 0); ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ ++/** ++* Show the lpm_response attribute. ++*/ ++static ssize_t lpmresp_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) ++ return sprintf(buf, "** LPM is DISABLED **\n"); ++ ++ if (!dwc_otg_is_device_mode(otg_dev->core_if)) { ++ return sprintf(buf, "** Current mode is not device mode\n"); ++ } ++ return sprintf(buf, "lpm_response = %d\n", ++ dwc_otg_get_lpmresponse(otg_dev->core_if)); ++} ++ ++/** ++* Store the lpm_response attribute. ++*/ ++static ssize_t lpmresp_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ ++ if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ if (!dwc_otg_is_device_mode(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ dwc_otg_set_lpmresponse(otg_dev->core_if, val); ++ return count; ++} ++ ++DEVICE_ATTR(lpm_response, S_IRUGO | S_IWUSR, lpmresp_show, lpmresp_store); ++ ++/** ++* Show the besl_reject attribute. ++*/ ++static ssize_t beslreject_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) ++ return sprintf(buf, "** LPM is DISABLED **\n"); ++ if (!dwc_otg_get_param_besl_enable(otg_dev->core_if)) ++ return sprintf(buf, "** EnBesl is DISABLED **\n"); ++ ++ if (!dwc_otg_is_device_mode(otg_dev->core_if)) { ++ return sprintf(buf, "** Current mode is not device mode\n"); ++ } ++ ++ return sprintf(buf, "besl_reject = %d\n", ++ dwc_otg_get_beslreject(otg_dev->core_if)); ++} ++ ++/** ++* Store the besl_reject attribute. ++*/ ++static ssize_t beslreject_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ ++ if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ if (!dwc_otg_get_param_besl_enable(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ if (!dwc_otg_is_device_mode(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ dwc_otg_set_beslreject(otg_dev->core_if,val); ++ ++ return count; ++} ++ ++DEVICE_ATTR(besl_reject, S_IRUGO | S_IWUSR, beslreject_show, beslreject_store); ++ ++/** ++* Show the hird_thresh attribute. ++*/ ++static ssize_t hirdthresh_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) ++ return sprintf(buf, "** LPM is DISABLED **\n"); ++ ++ if (!dwc_otg_is_device_mode(otg_dev->core_if)) { ++ return sprintf(buf, "** Current mode is not device mode\n"); ++ } ++ ++ return sprintf(buf, "hirdthresh = 0x%x\n", ++ dwc_otg_get_hirdthresh(otg_dev->core_if)); ++} ++ ++/** ++* Store the hird_thresh attribute. ++*/ ++static ssize_t hirdthresh_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ ++ if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ if (!dwc_otg_is_device_mode(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ dwc_otg_set_hirdthresh(otg_dev->core_if,val); ++ ++ return count; ++} ++ ++DEVICE_ATTR(hird_thres, S_IRUGO | S_IWUSR, hirdthresh_show, hirdthresh_store); ++ ++/** ++* Show the sleep_status attribute. ++*/ ++static ssize_t sleepstatus_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ return sprintf(buf, "Sleep Status = %d\n", ++ dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)); ++} ++ ++/** ++ * Store the sleep_status attribure. ++ */ ++static ssize_t sleepstatus_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct platform_device *lm_dev = container_of(_dev, struct platform_device, dev); ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(lm_dev); ++ ++ ++ dwc_otg_core_if_t *core_if = otg_dev->core_if; ++ ++ if (dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)) { ++ if (dwc_otg_is_host_mode(core_if)) { ++ ++ DWC_PRINTF("Host initiated resume\n"); ++ dwc_otg_set_prtresume(otg_dev->core_if, 1); ++ } ++ } ++ ++ return count; ++} ++ ++DEVICE_ATTR(sleep_status, S_IRUGO | S_IWUSR, sleepstatus_show, ++ sleepstatus_store); ++ ++#endif /* CONFIG_USB_DWC_OTG_LPM_ENABLE */ ++ ++/**@}*/ ++ ++/** ++ * Create the device files ++ */ ++void dwc_otg_attr_create(struct platform_device *dev) ++{ ++ int error; ++ ++ error = device_create_file(&dev->dev, &dev_attr_regoffset); ++ error = device_create_file(&dev->dev, &dev_attr_regvalue); ++ error = device_create_file(&dev->dev, &dev_attr_mode); ++ error = device_create_file(&dev->dev, &dev_attr_hnpcapable); ++ error = device_create_file(&dev->dev, &dev_attr_srpcapable); ++ error = device_create_file(&dev->dev, &dev_attr_hsic_connect); ++ error = device_create_file(&dev->dev, &dev_attr_inv_sel_hsic); ++ error = device_create_file(&dev->dev, &dev_attr_hnp); ++ error = device_create_file(&dev->dev, &dev_attr_srp); ++ error = device_create_file(&dev->dev, &dev_attr_buspower); ++ error = device_create_file(&dev->dev, &dev_attr_bussuspend); ++ error = device_create_file(&dev->dev, &dev_attr_mode_ch_tim_en); ++ error = device_create_file(&dev->dev, &dev_attr_fr_interval); ++ error = device_create_file(&dev->dev, &dev_attr_busconnected); ++ error = device_create_file(&dev->dev, &dev_attr_gotgctl); ++ error = device_create_file(&dev->dev, &dev_attr_gusbcfg); ++ error = device_create_file(&dev->dev, &dev_attr_grxfsiz); ++ error = device_create_file(&dev->dev, &dev_attr_gnptxfsiz); ++ error = device_create_file(&dev->dev, &dev_attr_gpvndctl); ++ error = device_create_file(&dev->dev, &dev_attr_ggpio); ++ error = device_create_file(&dev->dev, &dev_attr_guid); ++ error = device_create_file(&dev->dev, &dev_attr_gsnpsid); ++ error = device_create_file(&dev->dev, &dev_attr_devspeed); ++ error = device_create_file(&dev->dev, &dev_attr_enumspeed); ++ error = device_create_file(&dev->dev, &dev_attr_hptxfsiz); ++ error = device_create_file(&dev->dev, &dev_attr_hprt0); ++ error = device_create_file(&dev->dev, &dev_attr_remote_wakeup); ++ error = device_create_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn); ++ error = device_create_file(&dev->dev, &dev_attr_disconnect_us); ++ error = device_create_file(&dev->dev, &dev_attr_regdump); ++ error = device_create_file(&dev->dev, &dev_attr_spramdump); ++ error = device_create_file(&dev->dev, &dev_attr_hcddump); ++ error = device_create_file(&dev->dev, &dev_attr_hcd_frrem); ++ error = device_create_file(&dev->dev, &dev_attr_rd_reg_test); ++ error = device_create_file(&dev->dev, &dev_attr_wr_reg_test); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ error = device_create_file(&dev->dev, &dev_attr_lpm_response); ++ error = device_create_file(&dev->dev, &dev_attr_sleep_status); ++ error = device_create_file(&dev->dev, &dev_attr_besl_reject); ++ error = device_create_file(&dev->dev, &dev_attr_hird_thres); ++#endif ++} ++ ++/** ++ * Remove the device files ++ */ ++void dwc_otg_attr_remove(struct platform_device *dev ++ ++ ) ++{ ++ device_remove_file(&dev->dev, &dev_attr_regoffset); ++ device_remove_file(&dev->dev, &dev_attr_regvalue); ++ device_remove_file(&dev->dev, &dev_attr_mode); ++ device_remove_file(&dev->dev, &dev_attr_hnpcapable); ++ device_remove_file(&dev->dev, &dev_attr_srpcapable); ++ device_remove_file(&dev->dev, &dev_attr_hsic_connect); ++ device_remove_file(&dev->dev, &dev_attr_inv_sel_hsic); ++ device_remove_file(&dev->dev, &dev_attr_hnp); ++ device_remove_file(&dev->dev, &dev_attr_srp); ++ device_remove_file(&dev->dev, &dev_attr_buspower); ++ device_remove_file(&dev->dev, &dev_attr_bussuspend); ++ device_remove_file(&dev->dev, &dev_attr_mode_ch_tim_en); ++ device_remove_file(&dev->dev, &dev_attr_fr_interval); ++ device_remove_file(&dev->dev, &dev_attr_busconnected); ++ device_remove_file(&dev->dev, &dev_attr_gotgctl); ++ device_remove_file(&dev->dev, &dev_attr_gusbcfg); ++ device_remove_file(&dev->dev, &dev_attr_grxfsiz); ++ device_remove_file(&dev->dev, &dev_attr_gnptxfsiz); ++ device_remove_file(&dev->dev, &dev_attr_gpvndctl); ++ device_remove_file(&dev->dev, &dev_attr_ggpio); ++ device_remove_file(&dev->dev, &dev_attr_guid); ++ device_remove_file(&dev->dev, &dev_attr_gsnpsid); ++ device_remove_file(&dev->dev, &dev_attr_devspeed); ++ device_remove_file(&dev->dev, &dev_attr_enumspeed); ++ device_remove_file(&dev->dev, &dev_attr_hptxfsiz); ++ device_remove_file(&dev->dev, &dev_attr_hprt0); ++ device_remove_file(&dev->dev, &dev_attr_remote_wakeup); ++ device_remove_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn); ++ device_remove_file(&dev->dev, &dev_attr_disconnect_us); ++ device_remove_file(&dev->dev, &dev_attr_regdump); ++ device_remove_file(&dev->dev, &dev_attr_spramdump); ++ device_remove_file(&dev->dev, &dev_attr_hcddump); ++ device_remove_file(&dev->dev, &dev_attr_hcd_frrem); ++ device_remove_file(&dev->dev, &dev_attr_rd_reg_test); ++ device_remove_file(&dev->dev, &dev_attr_wr_reg_test); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ device_remove_file(&dev->dev, &dev_attr_lpm_response); ++ device_remove_file(&dev->dev, &dev_attr_sleep_status); ++ device_remove_file(&dev->dev, &dev_attr_besl_reject); ++ device_remove_file(&dev->dev, &dev_attr_hird_thres); ++#endif ++} +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_attr.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_attr.h +new file mode 100644 +index 0000000..4d43296 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_attr.h +@@ -0,0 +1,78 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.h $ ++ * $Revision: #13 $ ++ * $Date: 2010/06/21 $ ++ * $Change: 1532021 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++#if !defined(__DWC_OTG_ATTR_H__) ++#define __DWC_OTG_ATTR_H__ ++ ++#include ++ ++/** @file ++ * This file contains the interface to the Linux device attributes. ++ */ ++extern struct device_attribute dev_attr_regoffset; ++extern struct device_attribute dev_attr_regvalue; ++ ++extern struct device_attribute dev_attr_mode; ++extern struct device_attribute dev_attr_hnpcapable; ++extern struct device_attribute dev_attr_srpcapable; ++extern struct device_attribute dev_attr_hnp; ++extern struct device_attribute dev_attr_srp; ++extern struct device_attribute dev_attr_buspower; ++extern struct device_attribute dev_attr_bussuspend; ++extern struct device_attribute dev_attr_mode_ch_tim_en; ++extern struct device_attribute dev_attr_fr_interval; ++extern struct device_attribute dev_attr_busconnected; ++extern struct device_attribute dev_attr_gotgctl; ++extern struct device_attribute dev_attr_gusbcfg; ++extern struct device_attribute dev_attr_grxfsiz; ++extern struct device_attribute dev_attr_gnptxfsiz; ++extern struct device_attribute dev_attr_gpvndctl; ++extern struct device_attribute dev_attr_ggpio; ++extern struct device_attribute dev_attr_guid; ++extern struct device_attribute dev_attr_gsnpsid; ++extern struct device_attribute dev_attr_devspeed; ++extern struct device_attribute dev_attr_enumspeed; ++extern struct device_attribute dev_attr_hptxfsiz; ++extern struct device_attribute dev_attr_hprt0; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++extern struct device_attribute dev_attr_lpm_response; ++extern struct device_attribute devi_attr_sleep_status; ++#endif ++ ++void dwc_otg_attr_create(struct platform_device *dev ++ ); ++ ++void dwc_otg_attr_remove(struct platform_device *dev ++ ++ ); ++#endif +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_cfi.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_cfi.c +new file mode 100644 +index 0000000..bbb3d32 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_cfi.c +@@ -0,0 +1,1876 @@ ++/* ========================================================================== ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ * This file contains the most of the CFI(Core Feature Interface) ++ * implementation for the OTG. ++ */ ++ ++#ifdef DWC_UTE_CFI ++ ++#include "dwc_otg_pcd.h" ++#include "dwc_otg_cfi.h" ++ ++/** This definition should actually migrate to the Portability Library */ ++#define DWC_CONSTANT_CPU_TO_LE16(x) (x) ++ ++extern dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex); ++ ++static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen); ++static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen, ++ struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *ctrl_req); ++static int cfi_set_feature_value(struct dwc_otg_pcd *pcd); ++static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req); ++static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req); ++static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req); ++static int cfi_preproc_reset(struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req); ++static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep); ++ ++static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if); ++static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue); ++static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue); ++ ++static uint8_t resize_fifos(dwc_otg_core_if_t * core_if); ++ ++/** This is the header of the all features descriptor */ ++static cfi_all_features_header_t all_props_desc_header = { ++ .wVersion = DWC_CONSTANT_CPU_TO_LE16(0x100), ++ .wCoreID = DWC_CONSTANT_CPU_TO_LE16(CFI_CORE_ID_OTG), ++ .wNumFeatures = DWC_CONSTANT_CPU_TO_LE16(9), ++}; ++ ++/** This is an array of statically allocated feature descriptors */ ++static cfi_feature_desc_header_t prop_descs[] = { ++ ++ /* FT_ID_DMA_MODE */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_MODE), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(1), ++ }, ++ ++ /* FT_ID_DMA_BUFFER_SETUP */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFFER_SETUP), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6), ++ }, ++ ++ /* FT_ID_DMA_BUFF_ALIGN */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFF_ALIGN), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2), ++ }, ++ ++ /* FT_ID_DMA_CONCAT_SETUP */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CONCAT_SETUP), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ //.wDataLength = DWC_CONSTANT_CPU_TO_LE16(6), ++ }, ++ ++ /* FT_ID_DMA_CIRCULAR */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CIRCULAR), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6), ++ }, ++ ++ /* FT_ID_THRESHOLD_SETUP */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_THRESHOLD_SETUP), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6), ++ }, ++ ++ /* FT_ID_DFIFO_DEPTH */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DFIFO_DEPTH), ++ .bmAttributes = CFI_FEATURE_ATTR_RO, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2), ++ }, ++ ++ /* FT_ID_TX_FIFO_DEPTH */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_TX_FIFO_DEPTH), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2), ++ }, ++ ++ /* FT_ID_RX_FIFO_DEPTH */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_RX_FIFO_DEPTH), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2), ++ } ++}; ++ ++/** The table of feature names */ ++cfi_string_t prop_name_table[] = { ++ {FT_ID_DMA_MODE, "dma_mode"}, ++ {FT_ID_DMA_BUFFER_SETUP, "buffer_setup"}, ++ {FT_ID_DMA_BUFF_ALIGN, "buffer_align"}, ++ {FT_ID_DMA_CONCAT_SETUP, "concat_setup"}, ++ {FT_ID_DMA_CIRCULAR, "buffer_circular"}, ++ {FT_ID_THRESHOLD_SETUP, "threshold_setup"}, ++ {FT_ID_DFIFO_DEPTH, "dfifo_depth"}, ++ {FT_ID_TX_FIFO_DEPTH, "txfifo_depth"}, ++ {FT_ID_RX_FIFO_DEPTH, "rxfifo_depth"}, ++ {} ++}; ++ ++/************************************************************************/ ++ ++/** ++ * Returns the name of the feature by its ID ++ * or NULL if no featute ID matches. ++ * ++ */ ++const uint8_t *get_prop_name(uint16_t prop_id, int *len) ++{ ++ cfi_string_t *pstr; ++ *len = 0; ++ ++ for (pstr = prop_name_table; pstr && pstr->s; pstr++) { ++ if (pstr->id == prop_id) { ++ *len = DWC_STRLEN(pstr->s); ++ return pstr->s; ++ } ++ } ++ return NULL; ++} ++ ++/** ++ * This function handles all CFI specific control requests. ++ * ++ * Return a negative value to stall the DCE. ++ */ ++int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl) ++{ ++ int retval = 0; ++ dwc_otg_pcd_ep_t *ep = NULL; ++ cfiobject_t *cfi = pcd->cfi; ++ struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd); ++ uint16_t wLen = DWC_LE16_TO_CPU(&ctrl->wLength); ++ uint16_t wValue = DWC_LE16_TO_CPU(&ctrl->wValue); ++ uint16_t wIndex = DWC_LE16_TO_CPU(&ctrl->wIndex); ++ uint32_t regaddr = 0; ++ uint32_t regval = 0; ++ ++ /* Save this Control Request in the CFI object. ++ * The data field will be assigned in the data stage completion CB function. ++ */ ++ cfi->ctrl_req = *ctrl; ++ cfi->ctrl_req.data = NULL; ++ ++ cfi->need_gadget_att = 0; ++ cfi->need_status_in_complete = 0; ++ ++ switch (ctrl->bRequest) { ++ case VEN_CORE_GET_FEATURES: ++ retval = cfi_core_features_buf(cfi->buf_in.buf, CFI_IN_BUF_LEN); ++ if (retval >= 0) { ++ //dump_msg(cfi->buf_in.buf, retval); ++ ep = &pcd->ep0; ++ ++ retval = min((uint16_t) retval, wLen); ++ /* Transfer this buffer to the host through the EP0-IN EP */ ++ ep->dwc_ep.dma_addr = cfi->buf_in.addr; ++ ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf; ++ ep->dwc_ep.xfer_buff = cfi->buf_in.buf; ++ ep->dwc_ep.xfer_len = retval; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); ++ } ++ retval = 0; ++ break; ++ ++ case VEN_CORE_GET_FEATURE: ++ CFI_INFO("VEN_CORE_GET_FEATURE\n"); ++ retval = cfi_get_feature_value(cfi->buf_in.buf, CFI_IN_BUF_LEN, ++ pcd, ctrl); ++ if (retval >= 0) { ++ ep = &pcd->ep0; ++ ++ retval = min((uint16_t) retval, wLen); ++ /* Transfer this buffer to the host through the EP0-IN EP */ ++ ep->dwc_ep.dma_addr = cfi->buf_in.addr; ++ ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf; ++ ep->dwc_ep.xfer_buff = cfi->buf_in.buf; ++ ep->dwc_ep.xfer_len = retval; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); ++ } ++ CFI_INFO("VEN_CORE_GET_FEATURE=%d\n", retval); ++ dump_msg(cfi->buf_in.buf, retval); ++ break; ++ ++ case VEN_CORE_SET_FEATURE: ++ CFI_INFO("VEN_CORE_SET_FEATURE\n"); ++ /* Set up an XFER to get the data stage of the control request, ++ * which is the new value of the feature to be modified. ++ */ ++ ep = &pcd->ep0; ++ ep->dwc_ep.is_in = 0; ++ ep->dwc_ep.dma_addr = cfi->buf_out.addr; ++ ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf; ++ ep->dwc_ep.xfer_buff = cfi->buf_out.buf; ++ ep->dwc_ep.xfer_len = wLen; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ /* Read the control write's data stage */ ++ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); ++ retval = 0; ++ break; ++ ++ case VEN_CORE_RESET_FEATURES: ++ CFI_INFO("VEN_CORE_RESET_FEATURES\n"); ++ cfi->need_gadget_att = 1; ++ cfi->need_status_in_complete = 1; ++ retval = cfi_preproc_reset(pcd, ctrl); ++ CFI_INFO("VEN_CORE_RESET_FEATURES = (%d)\n", retval); ++ break; ++ ++ case VEN_CORE_ACTIVATE_FEATURES: ++ CFI_INFO("VEN_CORE_ACTIVATE_FEATURES\n"); ++ break; ++ ++ case VEN_CORE_READ_REGISTER: ++ CFI_INFO("VEN_CORE_READ_REGISTER\n"); ++ /* wValue optionally contains the HI WORD of the register offset and ++ * wIndex contains the LOW WORD of the register offset ++ */ ++ if (wValue == 0) { ++ /* @TODO - MAS - fix the access to the base field */ ++ regaddr = 0; ++ //regaddr = (uint32_t) pcd->otg_dev->os_dep.base; ++ //GET_CORE_IF(pcd)->co ++ regaddr |= wIndex; ++ } else { ++ regaddr = (wValue << 16) | wIndex; ++ } ++ ++ /* Read a 32-bit value of the memory at the regaddr */ ++ regval = DWC_READ_REG32((uint32_t *) regaddr); ++ ++ ep = &pcd->ep0; ++ dwc_memcpy(cfi->buf_in.buf, ®val, sizeof(uint32_t)); ++ ep->dwc_ep.is_in = 1; ++ ep->dwc_ep.dma_addr = cfi->buf_in.addr; ++ ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf; ++ ep->dwc_ep.xfer_buff = cfi->buf_in.buf; ++ ep->dwc_ep.xfer_len = wLen; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); ++ cfi->need_gadget_att = 0; ++ retval = 0; ++ break; ++ ++ case VEN_CORE_WRITE_REGISTER: ++ CFI_INFO("VEN_CORE_WRITE_REGISTER\n"); ++ /* Set up an XFER to get the data stage of the control request, ++ * which is the new value of the register to be modified. ++ */ ++ ep = &pcd->ep0; ++ ep->dwc_ep.is_in = 0; ++ ep->dwc_ep.dma_addr = cfi->buf_out.addr; ++ ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf; ++ ep->dwc_ep.xfer_buff = cfi->buf_out.buf; ++ ep->dwc_ep.xfer_len = wLen; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ /* Read the control write's data stage */ ++ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); ++ retval = 0; ++ break; ++ ++ default: ++ retval = -DWC_E_NOT_SUPPORTED; ++ break; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function prepares the core features descriptors and copies its ++ * raw representation into the buffer . ++ * ++ * The buffer structure is as follows: ++ * all_features_header (8 bytes) ++ * features_#1 (8 bytes + feature name string length) ++ * features_#2 (8 bytes + feature name string length) ++ * ..... ++ * features_#n - where n=the total count of feature descriptors ++ */ ++static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen) ++{ ++ cfi_feature_desc_header_t *prop_hdr = prop_descs; ++ cfi_feature_desc_header_t *prop; ++ cfi_all_features_header_t *all_props_hdr = &all_props_desc_header; ++ cfi_all_features_header_t *tmp; ++ uint8_t *tmpbuf = buf; ++ const uint8_t *pname = NULL; ++ int i, j, namelen = 0, totlen; ++ ++ /* Prepare and copy the core features into the buffer */ ++ CFI_INFO("%s:\n", __func__); ++ ++ tmp = (cfi_all_features_header_t *) tmpbuf; ++ *tmp = *all_props_hdr; ++ tmpbuf += CFI_ALL_FEATURES_HDR_LEN; ++ ++ j = sizeof(prop_descs) / sizeof(cfi_all_features_header_t); ++ for (i = 0; i < j; i++, prop_hdr++) { ++ pname = get_prop_name(prop_hdr->wFeatureID, &namelen); ++ prop = (cfi_feature_desc_header_t *) tmpbuf; ++ *prop = *prop_hdr; ++ ++ prop->bNameLen = namelen; ++ prop->wLength = ++ DWC_CONSTANT_CPU_TO_LE16(CFI_FEATURE_DESC_HDR_LEN + ++ namelen); ++ ++ tmpbuf += CFI_FEATURE_DESC_HDR_LEN; ++ dwc_memcpy(tmpbuf, pname, namelen); ++ tmpbuf += namelen; ++ } ++ ++ totlen = tmpbuf - buf; ++ ++ if (totlen > 0) { ++ tmp = (cfi_all_features_header_t *) buf; ++ tmp->wTotalLen = DWC_CONSTANT_CPU_TO_LE16(totlen); ++ } ++ ++ return totlen; ++} ++ ++/** ++ * This function releases all the dynamic memory in the CFI object. ++ */ ++static void cfi_release(cfiobject_t * cfiobj) ++{ ++ cfi_ep_t *cfiep; ++ dwc_list_link_t *tmp; ++ ++ CFI_INFO("%s\n", __func__); ++ ++ if (cfiobj->buf_in.buf) { ++ DWC_DMA_FREE(CFI_IN_BUF_LEN, cfiobj->buf_in.buf, ++ cfiobj->buf_in.addr); ++ cfiobj->buf_in.buf = NULL; ++ } ++ ++ if (cfiobj->buf_out.buf) { ++ DWC_DMA_FREE(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf, ++ cfiobj->buf_out.addr); ++ cfiobj->buf_out.buf = NULL; ++ } ++ ++ /* Free the Buffer Setup values for each EP */ ++ //list_for_each_entry(cfiep, &cfiobj->active_eps, lh) { ++ DWC_LIST_FOREACH(tmp, &cfiobj->active_eps) { ++ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ cfi_free_ep_bs_dyn_data(cfiep); ++ } ++} ++ ++/** ++ * This function frees the dynamically allocated EP buffer setup data. ++ */ ++static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep) ++{ ++ if (cfiep->bm_sg) { ++ DWC_FREE(cfiep->bm_sg); ++ cfiep->bm_sg = NULL; ++ } ++ ++ if (cfiep->bm_align) { ++ DWC_FREE(cfiep->bm_align); ++ cfiep->bm_align = NULL; ++ } ++ ++ if (cfiep->bm_concat) { ++ if (NULL != cfiep->bm_concat->wTxBytes) { ++ DWC_FREE(cfiep->bm_concat->wTxBytes); ++ cfiep->bm_concat->wTxBytes = NULL; ++ } ++ DWC_FREE(cfiep->bm_concat); ++ cfiep->bm_concat = NULL; ++ } ++} ++ ++/** ++ * This function initializes the default values of the features ++ * for a specific endpoint and should be called only once when ++ * the EP is enabled first time. ++ */ ++static int cfi_ep_init_defaults(struct dwc_otg_pcd *pcd, cfi_ep_t * cfiep) ++{ ++ int retval = 0; ++ ++ cfiep->bm_sg = DWC_ALLOC(sizeof(ddma_sg_buffer_setup_t)); ++ if (NULL == cfiep->bm_sg) { ++ CFI_INFO("Failed to allocate memory for SG feature value\n"); ++ return -DWC_E_NO_MEMORY; ++ } ++ dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t)); ++ ++ /* For the Concatenation feature's default value we do not allocate ++ * memory for the wTxBytes field - it will be done in the set_feature_value ++ * request handler. ++ */ ++ cfiep->bm_concat = DWC_ALLOC(sizeof(ddma_concat_buffer_setup_t)); ++ if (NULL == cfiep->bm_concat) { ++ CFI_INFO ++ ("Failed to allocate memory for CONCATENATION feature value\n"); ++ DWC_FREE(cfiep->bm_sg); ++ return -DWC_E_NO_MEMORY; ++ } ++ dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t)); ++ ++ cfiep->bm_align = DWC_ALLOC(sizeof(ddma_align_buffer_setup_t)); ++ if (NULL == cfiep->bm_align) { ++ CFI_INFO ++ ("Failed to allocate memory for Alignment feature value\n"); ++ DWC_FREE(cfiep->bm_sg); ++ DWC_FREE(cfiep->bm_concat); ++ return -DWC_E_NO_MEMORY; ++ } ++ dwc_memset(cfiep->bm_align, 0, sizeof(ddma_align_buffer_setup_t)); ++ ++ return retval; ++} ++ ++/** ++ * The callback function that notifies the CFI on the activation of ++ * an endpoint in the PCD. The following steps are done in this function: ++ * ++ * Create a dynamically allocated cfi_ep_t object (a CFI wrapper to the PCD's ++ * active endpoint) ++ * Create MAX_DMA_DESCS_PER_EP count DMA Descriptors for the EP ++ * Set the Buffer Mode to standard ++ * Initialize the default values for all EP modes (SG, Circular, Concat, Align) ++ * Add the cfi_ep_t object to the list of active endpoints in the CFI object ++ */ ++static int cfi_ep_enable(struct cfiobject *cfi, struct dwc_otg_pcd *pcd, ++ struct dwc_otg_pcd_ep *ep) ++{ ++ cfi_ep_t *cfiep; ++ int retval = -DWC_E_NOT_SUPPORTED; ++ ++ CFI_INFO("%s: epname=%s; epnum=0x%02x\n", __func__, ++ "EP_" /*ep->ep.name */ , ep->desc->bEndpointAddress); ++ /* MAS - Check whether this endpoint already is in the list */ ++ cfiep = get_cfi_ep_by_pcd_ep(cfi, ep); ++ ++ if (NULL == cfiep) { ++ /* Allocate a cfi_ep_t object */ ++ cfiep = DWC_ALLOC(sizeof(cfi_ep_t)); ++ if (NULL == cfiep) { ++ CFI_INFO ++ ("Unable to allocate memory for in function %s\n", ++ __func__); ++ return -DWC_E_NO_MEMORY; ++ } ++ dwc_memset(cfiep, 0, sizeof(cfi_ep_t)); ++ ++ /* Save the dwc_otg_pcd_ep pointer in the cfiep object */ ++ cfiep->ep = ep; ++ ++ /* Allocate the DMA Descriptors chain of MAX_DMA_DESCS_PER_EP count */ ++ ep->dwc_ep.descs = ++ DWC_DMA_ALLOC(MAX_DMA_DESCS_PER_EP * ++ sizeof(dwc_otg_dma_desc_t), ++ &ep->dwc_ep.descs_dma_addr); ++ ++ if (NULL == ep->dwc_ep.descs) { ++ DWC_FREE(cfiep); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ DWC_LIST_INIT(&cfiep->lh); ++ ++ /* Set the buffer mode to BM_STANDARD. It will be modified ++ * when building descriptors for a specific buffer mode */ ++ ep->dwc_ep.buff_mode = BM_STANDARD; ++ ++ /* Create and initialize the default values for this EP's Buffer modes */ ++ if ((retval = cfi_ep_init_defaults(pcd, cfiep)) < 0) ++ return retval; ++ ++ /* Add the cfi_ep_t object to the CFI object's list of active endpoints */ ++ DWC_LIST_INSERT_TAIL(&cfi->active_eps, &cfiep->lh); ++ retval = 0; ++ } else { /* The sought EP already is in the list */ ++ CFI_INFO("%s: The sought EP already is in the list\n", ++ __func__); ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function is called when the data stage of a 3-stage Control Write request ++ * is complete. ++ * ++ */ ++static int cfi_ctrl_write_complete(struct cfiobject *cfi, ++ struct dwc_otg_pcd *pcd) ++{ ++ uint32_t addr, reg_value; ++ uint16_t wIndex, wValue; ++ uint8_t bRequest; ++ uint8_t *buf = cfi->buf_out.buf; ++ //struct usb_ctrlrequest *ctrl_req = &cfi->ctrl_req_saved; ++ struct cfi_usb_ctrlrequest *ctrl_req = &cfi->ctrl_req; ++ int retval = -DWC_E_NOT_SUPPORTED; ++ ++ CFI_INFO("%s\n", __func__); ++ ++ bRequest = ctrl_req->bRequest; ++ wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex); ++ wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue); ++ ++ /* ++ * Save the pointer to the data stage in the ctrl_req's field. ++ * The request should be already saved in the command stage by now. ++ */ ++ ctrl_req->data = cfi->buf_out.buf; ++ cfi->need_status_in_complete = 0; ++ cfi->need_gadget_att = 0; ++ ++ switch (bRequest) { ++ case VEN_CORE_WRITE_REGISTER: ++ /* The buffer contains raw data of the new value for the register */ ++ reg_value = *((uint32_t *) buf); ++ if (wValue == 0) { ++ addr = 0; ++ //addr = (uint32_t) pcd->otg_dev->os_dep.base; ++ addr += wIndex; ++ } else { ++ addr = (wValue << 16) | wIndex; ++ } ++ ++ //writel(reg_value, addr); ++ ++ retval = 0; ++ cfi->need_status_in_complete = 1; ++ break; ++ ++ case VEN_CORE_SET_FEATURE: ++ /* The buffer contains raw data of the new value of the feature */ ++ retval = cfi_set_feature_value(pcd); ++ if (retval < 0) ++ return retval; ++ ++ cfi->need_status_in_complete = 1; ++ break; ++ ++ default: ++ break; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function builds the DMA descriptors for the SG buffer mode. ++ */ ++static void cfi_build_sg_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, ++ dwc_otg_pcd_request_t * req) ++{ ++ struct dwc_otg_pcd_ep *ep = cfiep->ep; ++ ddma_sg_buffer_setup_t *sgval = cfiep->bm_sg; ++ struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs; ++ struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs; ++ dma_addr_t buff_addr = req->dma; ++ int i; ++ uint32_t txsize, off; ++ ++ txsize = sgval->wSize; ++ off = sgval->bOffset; ++ ++// CFI_INFO("%s: %s TXSIZE=0x%08x; OFFSET=0x%08x\n", ++// __func__, cfiep->ep->ep.name, txsize, off); ++ ++ for (i = 0; i < sgval->bCount; i++) { ++ desc->status.b.bs = BS_HOST_BUSY; ++ desc->buf = buff_addr; ++ desc->status.b.l = 0; ++ desc->status.b.ioc = 0; ++ desc->status.b.sp = 0; ++ desc->status.b.bytes = txsize; ++ desc->status.b.bs = BS_HOST_READY; ++ ++ /* Set the next address of the buffer */ ++ buff_addr += txsize + off; ++ desc_last = desc; ++ desc++; ++ } ++ ++ /* Set the last, ioc and sp bits on the Last DMA Descriptor */ ++ desc_last->status.b.l = 1; ++ desc_last->status.b.ioc = 1; ++ desc_last->status.b.sp = ep->dwc_ep.sent_zlp; ++ /* Save the last DMA descriptor pointer */ ++ cfiep->dma_desc_last = desc_last; ++ cfiep->desc_count = sgval->bCount; ++} ++ ++/** ++ * This function builds the DMA descriptors for the Concatenation buffer mode. ++ */ ++static void cfi_build_concat_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, ++ dwc_otg_pcd_request_t * req) ++{ ++ struct dwc_otg_pcd_ep *ep = cfiep->ep; ++ ddma_concat_buffer_setup_t *concatval = cfiep->bm_concat; ++ struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs; ++ struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs; ++ dma_addr_t buff_addr = req->dma; ++ int i; ++ uint16_t *txsize; ++ ++ txsize = concatval->wTxBytes; ++ ++ for (i = 0; i < concatval->hdr.bDescCount; i++) { ++ desc->buf = buff_addr; ++ desc->status.b.bs = BS_HOST_BUSY; ++ desc->status.b.l = 0; ++ desc->status.b.ioc = 0; ++ desc->status.b.sp = 0; ++ desc->status.b.bytes = *txsize; ++ desc->status.b.bs = BS_HOST_READY; ++ ++ txsize++; ++ /* Set the next address of the buffer */ ++ buff_addr += UGETW(ep->desc->wMaxPacketSize); ++ desc_last = desc; ++ desc++; ++ } ++ ++ /* Set the last, ioc and sp bits on the Last DMA Descriptor */ ++ desc_last->status.b.l = 1; ++ desc_last->status.b.ioc = 1; ++ desc_last->status.b.sp = ep->dwc_ep.sent_zlp; ++ cfiep->dma_desc_last = desc_last; ++ cfiep->desc_count = concatval->hdr.bDescCount; ++} ++ ++/** ++ * This function builds the DMA descriptors for the Circular buffer mode ++ */ ++static void cfi_build_circ_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, ++ dwc_otg_pcd_request_t * req) ++{ ++ /* @todo: MAS - add implementation when this feature needs to be tested */ ++} ++ ++/** ++ * This function builds the DMA descriptors for the Alignment buffer mode ++ */ ++static void cfi_build_align_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, ++ dwc_otg_pcd_request_t * req) ++{ ++ struct dwc_otg_pcd_ep *ep = cfiep->ep; ++ ddma_align_buffer_setup_t *alignval = cfiep->bm_align; ++ struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs; ++ dma_addr_t buff_addr = req->dma; ++ ++ desc->status.b.bs = BS_HOST_BUSY; ++ desc->status.b.l = 1; ++ desc->status.b.ioc = 1; ++ desc->status.b.sp = ep->dwc_ep.sent_zlp; ++ desc->status.b.bytes = req->length; ++ /* Adjust the buffer alignment */ ++ desc->buf = (buff_addr + alignval->bAlign); ++ desc->status.b.bs = BS_HOST_READY; ++ cfiep->dma_desc_last = desc; ++ cfiep->desc_count = 1; ++} ++ ++/** ++ * This function builds the DMA descriptors chain for different modes of the ++ * buffer setup of an endpoint. ++ */ ++static void cfi_build_descriptors(struct cfiobject *cfi, ++ struct dwc_otg_pcd *pcd, ++ struct dwc_otg_pcd_ep *ep, ++ dwc_otg_pcd_request_t * req) ++{ ++ cfi_ep_t *cfiep; ++ ++ /* Get the cfiep by the dwc_otg_pcd_ep */ ++ cfiep = get_cfi_ep_by_pcd_ep(cfi, ep); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Unable to find a matching active endpoint\n", ++ __func__); ++ return; ++ } ++ ++ cfiep->xfer_len = req->length; ++ ++ /* Iterate through all the DMA descriptors */ ++ switch (cfiep->ep->dwc_ep.buff_mode) { ++ case BM_SG: ++ cfi_build_sg_descs(cfi, cfiep, req); ++ break; ++ ++ case BM_CONCAT: ++ cfi_build_concat_descs(cfi, cfiep, req); ++ break; ++ ++ case BM_CIRCULAR: ++ cfi_build_circ_descs(cfi, cfiep, req); ++ break; ++ ++ case BM_ALIGN: ++ cfi_build_align_descs(cfi, cfiep, req); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++/** ++ * Allocate DMA buffer for different Buffer modes. ++ */ ++static void *cfi_ep_alloc_buf(struct cfiobject *cfi, struct dwc_otg_pcd *pcd, ++ struct dwc_otg_pcd_ep *ep, dma_addr_t * dma, ++ unsigned size, gfp_t flags) ++{ ++ return DWC_DMA_ALLOC(size, dma); ++} ++ ++/** ++ * This function initializes the CFI object. ++ */ ++int init_cfi(cfiobject_t * cfiobj) ++{ ++ CFI_INFO("%s\n", __func__); ++ ++ /* Allocate a buffer for IN XFERs */ ++ cfiobj->buf_in.buf = ++ DWC_DMA_ALLOC(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr); ++ if (NULL == cfiobj->buf_in.buf) { ++ CFI_INFO("Unable to allocate buffer for INs\n"); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ /* Allocate a buffer for OUT XFERs */ ++ cfiobj->buf_out.buf = ++ DWC_DMA_ALLOC(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr); ++ if (NULL == cfiobj->buf_out.buf) { ++ CFI_INFO("Unable to allocate buffer for OUT\n"); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ /* Initialize the callback function pointers */ ++ cfiobj->ops.release = cfi_release; ++ cfiobj->ops.ep_enable = cfi_ep_enable; ++ cfiobj->ops.ctrl_write_complete = cfi_ctrl_write_complete; ++ cfiobj->ops.build_descriptors = cfi_build_descriptors; ++ cfiobj->ops.ep_alloc_buf = cfi_ep_alloc_buf; ++ ++ /* Initialize the list of active endpoints in the CFI object */ ++ DWC_LIST_INIT(&cfiobj->active_eps); ++ ++ return 0; ++} ++ ++/** ++ * This function reads the required feature's current value into the buffer ++ * ++ * @retval: Returns negative as error, or the data length of the feature ++ */ ++static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen, ++ struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *ctrl_req) ++{ ++ int retval = -DWC_E_NOT_SUPPORTED; ++ struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd); ++ uint16_t dfifo, rxfifo, txfifo; ++ ++ switch (ctrl_req->wIndex) { ++ /* Whether the DDMA is enabled or not */ ++ case FT_ID_DMA_MODE: ++ *buf = (coreif->dma_enable && coreif->dma_desc_enable) ? 1 : 0; ++ retval = 1; ++ break; ++ ++ case FT_ID_DMA_BUFFER_SETUP: ++ retval = cfi_ep_get_sg_val(buf, pcd, ctrl_req); ++ break; ++ ++ case FT_ID_DMA_BUFF_ALIGN: ++ retval = cfi_ep_get_align_val(buf, pcd, ctrl_req); ++ break; ++ ++ case FT_ID_DMA_CONCAT_SETUP: ++ retval = cfi_ep_get_concat_val(buf, pcd, ctrl_req); ++ break; ++ ++ case FT_ID_DMA_CIRCULAR: ++ CFI_INFO("GetFeature value (FT_ID_DMA_CIRCULAR)\n"); ++ break; ++ ++ case FT_ID_THRESHOLD_SETUP: ++ CFI_INFO("GetFeature value (FT_ID_THRESHOLD_SETUP)\n"); ++ break; ++ ++ case FT_ID_DFIFO_DEPTH: ++ dfifo = get_dfifo_size(coreif); ++ *((uint16_t *) buf) = dfifo; ++ retval = sizeof(uint16_t); ++ break; ++ ++ case FT_ID_TX_FIFO_DEPTH: ++ retval = get_txfifo_size(pcd, ctrl_req->wValue); ++ if (retval >= 0) { ++ txfifo = retval; ++ *((uint16_t *) buf) = txfifo; ++ retval = sizeof(uint16_t); ++ } ++ break; ++ ++ case FT_ID_RX_FIFO_DEPTH: ++ retval = get_rxfifo_size(coreif, ctrl_req->wValue); ++ if (retval >= 0) { ++ rxfifo = retval; ++ *((uint16_t *) buf) = rxfifo; ++ retval = sizeof(uint16_t); ++ } ++ break; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function resets the SG for the specified EP to its default value ++ */ ++static int cfi_reset_sg_val(cfi_ep_t * cfiep) ++{ ++ dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t)); ++ return 0; ++} ++ ++/** ++ * This function resets the Alignment for the specified EP to its default value ++ */ ++static int cfi_reset_align_val(cfi_ep_t * cfiep) ++{ ++ dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t)); ++ return 0; ++} ++ ++/** ++ * This function resets the Concatenation for the specified EP to its default value ++ * This function will also set the value of the wTxBytes field to NULL after ++ * freeing the memory previously allocated for this field. ++ */ ++static int cfi_reset_concat_val(cfi_ep_t * cfiep) ++{ ++ /* First we need to free the wTxBytes field */ ++ if (cfiep->bm_concat->wTxBytes) { ++ DWC_FREE(cfiep->bm_concat->wTxBytes); ++ cfiep->bm_concat->wTxBytes = NULL; ++ } ++ ++ dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t)); ++ return 0; ++} ++ ++/** ++ * This function resets all the buffer setups of the specified endpoint ++ */ ++static int cfi_ep_reset_all_setup_vals(cfi_ep_t * cfiep) ++{ ++ cfi_reset_sg_val(cfiep); ++ cfi_reset_align_val(cfiep); ++ cfi_reset_concat_val(cfiep); ++ return 0; ++} ++ ++static int cfi_handle_reset_fifo_val(struct dwc_otg_pcd *pcd, uint8_t ep_addr, ++ uint8_t rx_rst, uint8_t tx_rst) ++{ ++ int retval = -DWC_E_INVALID; ++ uint16_t tx_siz[15]; ++ uint16_t rx_siz = 0; ++ dwc_otg_pcd_ep_t *ep = NULL; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params; ++ ++ if (rx_rst) { ++ rx_siz = params->dev_rx_fifo_size; ++ params->dev_rx_fifo_size = GET_CORE_IF(pcd)->init_rxfsiz; ++ } ++ ++ if (tx_rst) { ++ if (ep_addr == 0) { ++ int i; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ tx_siz[i] = ++ core_if->core_params->dev_tx_fifo_size[i]; ++ core_if->core_params->dev_tx_fifo_size[i] = ++ core_if->init_txfsiz[i]; ++ } ++ } else { ++ ++ ep = get_ep_by_addr(pcd, ep_addr); ++ ++ if (NULL == ep) { ++ CFI_INFO ++ ("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, ep_addr); ++ return -DWC_E_INVALID; ++ } ++ ++ tx_siz[0] = ++ params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - ++ 1]; ++ params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = ++ GET_CORE_IF(pcd)->init_txfsiz[ep-> ++ dwc_ep.tx_fifo_num - ++ 1]; ++ } ++ } ++ ++ if (resize_fifos(GET_CORE_IF(pcd))) { ++ retval = 0; ++ } else { ++ CFI_INFO ++ ("%s: Error resetting the feature Reset All(FIFO size)\n", ++ __func__); ++ if (rx_rst) { ++ params->dev_rx_fifo_size = rx_siz; ++ } ++ ++ if (tx_rst) { ++ if (ep_addr == 0) { ++ int i; ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++ i++) { ++ core_if-> ++ core_params->dev_tx_fifo_size[i] = ++ tx_siz[i]; ++ } ++ } else { ++ params->dev_tx_fifo_size[ep-> ++ dwc_ep.tx_fifo_num - ++ 1] = tx_siz[0]; ++ } ++ } ++ retval = -DWC_E_INVALID; ++ } ++ return retval; ++} ++ ++static int cfi_handle_reset_all(struct dwc_otg_pcd *pcd, uint8_t addr) ++{ ++ int retval = 0; ++ cfi_ep_t *cfiep; ++ cfiobject_t *cfi = pcd->cfi; ++ dwc_list_link_t *tmp; ++ ++ retval = cfi_handle_reset_fifo_val(pcd, addr, 1, 1); ++ if (retval < 0) { ++ return retval; ++ } ++ ++ /* If the EP address is known then reset the features for only that EP */ ++ if (addr) { ++ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Error getting the EP address 0x%02x\n", ++ __func__, addr); ++ return -DWC_E_INVALID; ++ } ++ retval = cfi_ep_reset_all_setup_vals(cfiep); ++ cfiep->ep->dwc_ep.buff_mode = BM_STANDARD; ++ } ++ /* Otherwise (wValue == 0), reset all features of all EP's */ ++ else { ++ /* Traverse all the active EP's and reset the feature(s) value(s) */ ++ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { ++ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { ++ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ retval = cfi_ep_reset_all_setup_vals(cfiep); ++ cfiep->ep->dwc_ep.buff_mode = BM_STANDARD; ++ if (retval < 0) { ++ CFI_INFO ++ ("%s: Error resetting the feature Reset All\n", ++ __func__); ++ return retval; ++ } ++ } ++ } ++ return retval; ++} ++ ++static int cfi_handle_reset_dma_buff_setup(struct dwc_otg_pcd *pcd, ++ uint8_t addr) ++{ ++ int retval = 0; ++ cfi_ep_t *cfiep; ++ cfiobject_t *cfi = pcd->cfi; ++ dwc_list_link_t *tmp; ++ ++ /* If the EP address is known then reset the features for only that EP */ ++ if (addr) { ++ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Error getting the EP address 0x%02x\n", ++ __func__, addr); ++ return -DWC_E_INVALID; ++ } ++ retval = cfi_reset_sg_val(cfiep); ++ } ++ /* Otherwise (wValue == 0), reset all features of all EP's */ ++ else { ++ /* Traverse all the active EP's and reset the feature(s) value(s) */ ++ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { ++ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { ++ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ retval = cfi_reset_sg_val(cfiep); ++ if (retval < 0) { ++ CFI_INFO ++ ("%s: Error resetting the feature Buffer Setup\n", ++ __func__); ++ return retval; ++ } ++ } ++ } ++ return retval; ++} ++ ++static int cfi_handle_reset_concat_val(struct dwc_otg_pcd *pcd, uint8_t addr) ++{ ++ int retval = 0; ++ cfi_ep_t *cfiep; ++ cfiobject_t *cfi = pcd->cfi; ++ dwc_list_link_t *tmp; ++ ++ /* If the EP address is known then reset the features for only that EP */ ++ if (addr) { ++ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Error getting the EP address 0x%02x\n", ++ __func__, addr); ++ return -DWC_E_INVALID; ++ } ++ retval = cfi_reset_concat_val(cfiep); ++ } ++ /* Otherwise (wValue == 0), reset all features of all EP's */ ++ else { ++ /* Traverse all the active EP's and reset the feature(s) value(s) */ ++ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { ++ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { ++ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ retval = cfi_reset_concat_val(cfiep); ++ if (retval < 0) { ++ CFI_INFO ++ ("%s: Error resetting the feature Concatenation Value\n", ++ __func__); ++ return retval; ++ } ++ } ++ } ++ return retval; ++} ++ ++static int cfi_handle_reset_align_val(struct dwc_otg_pcd *pcd, uint8_t addr) ++{ ++ int retval = 0; ++ cfi_ep_t *cfiep; ++ cfiobject_t *cfi = pcd->cfi; ++ dwc_list_link_t *tmp; ++ ++ /* If the EP address is known then reset the features for only that EP */ ++ if (addr) { ++ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Error getting the EP address 0x%02x\n", ++ __func__, addr); ++ return -DWC_E_INVALID; ++ } ++ retval = cfi_reset_align_val(cfiep); ++ } ++ /* Otherwise (wValue == 0), reset all features of all EP's */ ++ else { ++ /* Traverse all the active EP's and reset the feature(s) value(s) */ ++ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { ++ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { ++ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ retval = cfi_reset_align_val(cfiep); ++ if (retval < 0) { ++ CFI_INFO ++ ("%s: Error resetting the feature Aliignment Value\n", ++ __func__); ++ return retval; ++ } ++ } ++ } ++ return retval; ++ ++} ++ ++static int cfi_preproc_reset(struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req) ++{ ++ int retval = 0; ++ ++ switch (req->wIndex) { ++ case 0: ++ /* Reset all features */ ++ retval = cfi_handle_reset_all(pcd, req->wValue & 0xff); ++ break; ++ ++ case FT_ID_DMA_BUFFER_SETUP: ++ /* Reset the SG buffer setup */ ++ retval = ++ cfi_handle_reset_dma_buff_setup(pcd, req->wValue & 0xff); ++ break; ++ ++ case FT_ID_DMA_CONCAT_SETUP: ++ /* Reset the Concatenation buffer setup */ ++ retval = cfi_handle_reset_concat_val(pcd, req->wValue & 0xff); ++ break; ++ ++ case FT_ID_DMA_BUFF_ALIGN: ++ /* Reset the Alignment buffer setup */ ++ retval = cfi_handle_reset_align_val(pcd, req->wValue & 0xff); ++ break; ++ ++ case FT_ID_TX_FIFO_DEPTH: ++ retval = ++ cfi_handle_reset_fifo_val(pcd, req->wValue & 0xff, 0, 1); ++ pcd->cfi->need_gadget_att = 0; ++ break; ++ ++ case FT_ID_RX_FIFO_DEPTH: ++ retval = cfi_handle_reset_fifo_val(pcd, 0, 1, 0); ++ pcd->cfi->need_gadget_att = 0; ++ break; ++ default: ++ break; ++ } ++ return retval; ++} ++ ++/** ++ * This function sets a new value for the SG buffer setup. ++ */ ++static int cfi_ep_set_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd) ++{ ++ uint8_t inaddr, outaddr; ++ cfi_ep_t *epin, *epout; ++ ddma_sg_buffer_setup_t *psgval; ++ uint32_t desccount, size; ++ ++ CFI_INFO("%s\n", __func__); ++ ++ psgval = (ddma_sg_buffer_setup_t *) buf; ++ desccount = (uint32_t) psgval->bCount; ++ size = (uint32_t) psgval->wSize; ++ ++ /* Check the DMA descriptor count */ ++ if ((desccount > MAX_DMA_DESCS_PER_EP) || (desccount == 0)) { ++ CFI_INFO ++ ("%s: The count of DMA Descriptors should be between 1 and %d\n", ++ __func__, MAX_DMA_DESCS_PER_EP); ++ return -DWC_E_INVALID; ++ } ++ ++ /* Check the DMA descriptor count */ ++ ++ if (size == 0) { ++ ++ CFI_INFO("%s: The transfer size should be at least 1 byte\n", ++ __func__); ++ ++ return -DWC_E_INVALID; ++ ++ } ++ ++ inaddr = psgval->bInEndpointAddress; ++ outaddr = psgval->bOutEndpointAddress; ++ ++ epin = get_cfi_ep_by_addr(pcd->cfi, inaddr); ++ epout = get_cfi_ep_by_addr(pcd->cfi, outaddr); ++ ++ if (NULL == epin || NULL == epout) { ++ CFI_INFO ++ ("%s: Unable to get the endpoints inaddr=0x%02x outaddr=0x%02x\n", ++ __func__, inaddr, outaddr); ++ return -DWC_E_INVALID; ++ } ++ ++ epin->ep->dwc_ep.buff_mode = BM_SG; ++ dwc_memcpy(epin->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t)); ++ ++ epout->ep->dwc_ep.buff_mode = BM_SG; ++ dwc_memcpy(epout->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t)); ++ ++ return 0; ++} ++ ++/** ++ * This function sets a new value for the buffer Alignment setup. ++ */ ++static int cfi_ep_set_alignment_val(uint8_t * buf, struct dwc_otg_pcd *pcd) ++{ ++ cfi_ep_t *ep; ++ uint8_t addr; ++ ddma_align_buffer_setup_t *palignval; ++ ++ palignval = (ddma_align_buffer_setup_t *) buf; ++ addr = palignval->bEndpointAddress; ++ ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, addr); ++ return -DWC_E_INVALID; ++ } ++ ++ ep->ep->dwc_ep.buff_mode = BM_ALIGN; ++ dwc_memcpy(ep->bm_align, palignval, sizeof(ddma_align_buffer_setup_t)); ++ ++ return 0; ++} ++ ++/** ++ * This function sets a new value for the Concatenation buffer setup. ++ */ ++static int cfi_ep_set_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd) ++{ ++ uint8_t addr; ++ cfi_ep_t *ep; ++ struct _ddma_concat_buffer_setup_hdr *pConcatValHdr; ++ uint16_t *pVals; ++ uint32_t desccount; ++ int i; ++ uint16_t mps; ++ ++ pConcatValHdr = (struct _ddma_concat_buffer_setup_hdr *)buf; ++ desccount = (uint32_t) pConcatValHdr->bDescCount; ++ pVals = (uint16_t *) (buf + BS_CONCAT_VAL_HDR_LEN); ++ ++ /* Check the DMA descriptor count */ ++ if (desccount > MAX_DMA_DESCS_PER_EP) { ++ CFI_INFO("%s: Maximum DMA Descriptor count should be %d\n", ++ __func__, MAX_DMA_DESCS_PER_EP); ++ return -DWC_E_INVALID; ++ } ++ ++ addr = pConcatValHdr->bEndpointAddress; ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, addr); ++ return -DWC_E_INVALID; ++ } ++ ++ mps = UGETW(ep->ep->desc->wMaxPacketSize); ++ ++#if 0 ++ for (i = 0; i < desccount; i++) { ++ CFI_INFO("%s: wTxSize[%d]=0x%04x\n", __func__, i, pVals[i]); ++ } ++ CFI_INFO("%s: epname=%s; mps=%d\n", __func__, ep->ep->ep.name, mps); ++#endif ++ ++ /* Check the wTxSizes to be less than or equal to the mps */ ++ for (i = 0; i < desccount; i++) { ++ if (pVals[i] > mps) { ++ CFI_INFO ++ ("%s: ERROR - the wTxSize[%d] should be <= MPS (wTxSize=%d)\n", ++ __func__, i, pVals[i]); ++ return -DWC_E_INVALID; ++ } ++ } ++ ++ ep->ep->dwc_ep.buff_mode = BM_CONCAT; ++ dwc_memcpy(ep->bm_concat, pConcatValHdr, BS_CONCAT_VAL_HDR_LEN); ++ ++ /* Free the previously allocated storage for the wTxBytes */ ++ if (ep->bm_concat->wTxBytes) { ++ DWC_FREE(ep->bm_concat->wTxBytes); ++ } ++ ++ /* Allocate a new storage for the wTxBytes field */ ++ ep->bm_concat->wTxBytes = ++ DWC_ALLOC(sizeof(uint16_t) * pConcatValHdr->bDescCount); ++ if (NULL == ep->bm_concat->wTxBytes) { ++ CFI_INFO("%s: Unable to allocate memory\n", __func__); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ /* Copy the new values into the wTxBytes filed */ ++ dwc_memcpy(ep->bm_concat->wTxBytes, buf + BS_CONCAT_VAL_HDR_LEN, ++ sizeof(uint16_t) * pConcatValHdr->bDescCount); ++ ++ return 0; ++} ++ ++/** ++ * This function calculates the total of all FIFO sizes ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ * @return The total of data FIFO sizes. ++ * ++ */ ++static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_params_t *params = core_if->core_params; ++ uint16_t dfifo_total = 0; ++ int i; ++ ++ /* The shared RxFIFO size */ ++ dfifo_total = ++ params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size; ++ ++ /* Add up each TxFIFO size to the total */ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ dfifo_total += params->dev_tx_fifo_size[i]; ++ } ++ ++ return dfifo_total; ++} ++ ++/** ++ * This function returns Rx FIFO size ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ * @return The total of data FIFO sizes. ++ * ++ */ ++static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue) ++{ ++ switch (wValue >> 8) { ++ case 0: ++ return (core_if->pwron_rxfsiz < ++ 32768) ? core_if->pwron_rxfsiz : 32768; ++ break; ++ case 1: ++ return core_if->core_params->dev_rx_fifo_size; ++ break; ++ default: ++ return -DWC_E_INVALID; ++ break; ++ } ++} ++ ++/** ++ * This function returns Tx FIFO size for IN EP ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ * @return The total of data FIFO sizes. ++ * ++ */ ++static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ ++ ep = get_ep_by_addr(pcd, wValue & 0xff); ++ ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, wValue & 0xff); ++ return -DWC_E_INVALID; ++ } ++ ++ if (!ep->dwc_ep.is_in) { ++ CFI_INFO ++ ("%s: No Tx FIFO assingned to the Out endpoint addr=0x%02x\n", ++ __func__, wValue & 0xff); ++ return -DWC_E_INVALID; ++ } ++ ++ switch (wValue >> 8) { ++ case 0: ++ return (GET_CORE_IF(pcd)->pwron_txfsiz ++ [ep->dwc_ep.tx_fifo_num - 1] < ++ 768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep-> ++ dwc_ep.tx_fifo_num ++ - 1] : 32768; ++ break; ++ case 1: ++ return GET_CORE_IF(pcd)->core_params-> ++ dev_tx_fifo_size[ep->dwc_ep.num - 1]; ++ break; ++ default: ++ return -DWC_E_INVALID; ++ break; ++ } ++} ++ ++/** ++ * This function checks if the submitted combination of ++ * device mode FIFO sizes is possible or not. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ * @return 1 if possible, 0 otherwise. ++ * ++ */ ++static uint8_t check_fifo_sizes(dwc_otg_core_if_t * core_if) ++{ ++ uint16_t dfifo_actual = 0; ++ dwc_otg_core_params_t *params = core_if->core_params; ++ uint16_t start_addr = 0; ++ int i; ++ ++ dfifo_actual = ++ params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ dfifo_actual += params->dev_tx_fifo_size[i]; ++ } ++ ++ if (dfifo_actual > core_if->total_fifo_size) { ++ return 0; ++ } ++ ++ if (params->dev_rx_fifo_size > 32768 || params->dev_rx_fifo_size < 16) ++ return 0; ++ ++ if (params->dev_nperio_tx_fifo_size > 32768 ++ || params->dev_nperio_tx_fifo_size < 16) ++ return 0; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ ++ if (params->dev_tx_fifo_size[i] > 768 ++ || params->dev_tx_fifo_size[i] < 4) ++ return 0; ++ } ++ ++ if (params->dev_rx_fifo_size > core_if->pwron_rxfsiz) ++ return 0; ++ start_addr = params->dev_rx_fifo_size; ++ ++ if (params->dev_nperio_tx_fifo_size > core_if->pwron_gnptxfsiz) ++ return 0; ++ start_addr += params->dev_nperio_tx_fifo_size; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ ++ if (params->dev_tx_fifo_size[i] > core_if->pwron_txfsiz[i]) ++ return 0; ++ start_addr += params->dev_tx_fifo_size[i]; ++ } ++ ++ return 1; ++} ++ ++/** ++ * This function resizes Device mode FIFOs ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ * @return 1 if successful, 0 otherwise ++ * ++ */ ++static uint8_t resize_fifos(dwc_otg_core_if_t * core_if) ++{ ++ int i = 0; ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ dwc_otg_core_params_t *params = core_if->core_params; ++ uint32_t rx_fifo_size; ++ fifosize_data_t nptxfifosize; ++ fifosize_data_t txfifosize[15]; ++ ++ uint32_t rx_fsz_bak; ++ uint32_t nptxfsz_bak; ++ uint32_t txfsz_bak[15]; ++ ++ uint16_t start_address; ++ uint8_t retval = 1; ++ ++ if (!check_fifo_sizes(core_if)) { ++ return 0; ++ } ++ ++ /* Configure data FIFO sizes */ ++ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { ++ rx_fsz_bak = DWC_READ_REG32(&global_regs->grxfsiz); ++ rx_fifo_size = params->dev_rx_fifo_size; ++ DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size); ++ ++ /* ++ * Tx FIFOs These FIFOs are numbered from 1 to 15. ++ * Indexes of the FIFO size module parameters in the ++ * dev_tx_fifo_size array and the FIFO size registers in ++ * the dtxfsiz array run from 0 to 14. ++ */ ++ ++ /* Non-periodic Tx FIFO */ ++ nptxfsz_bak = DWC_READ_REG32(&global_regs->gnptxfsiz); ++ nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; ++ start_address = params->dev_rx_fifo_size; ++ nptxfifosize.b.startaddr = start_address; ++ ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32); ++ ++ start_address += nptxfifosize.b.depth; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ txfsz_bak[i] = DWC_READ_REG32(&global_regs->dtxfsiz[i]); ++ ++ txfifosize[i].b.depth = params->dev_tx_fifo_size[i]; ++ txfifosize[i].b.startaddr = start_address; ++ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], ++ txfifosize[i].d32); ++ ++ start_address += txfifosize[i].b.depth; ++ } ++ ++ /** Check if register values are set correctly */ ++ if (rx_fifo_size != DWC_READ_REG32(&global_regs->grxfsiz)) { ++ retval = 0; ++ } ++ ++ if (nptxfifosize.d32 != DWC_READ_REG32(&global_regs->gnptxfsiz)) { ++ retval = 0; ++ } ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ if (txfifosize[i].d32 != ++ DWC_READ_REG32(&global_regs->dtxfsiz[i])) { ++ retval = 0; ++ } ++ } ++ ++ /** If register values are not set correctly, reset old values */ ++ if (retval == 0) { ++ DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fsz_bak); ++ ++ /* Non-periodic Tx FIFO */ ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfsz_bak); ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], ++ txfsz_bak[i]); ++ } ++ } ++ } else { ++ return 0; ++ } ++ ++ /* Flush the FIFOs */ ++ dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ ++ dwc_otg_flush_rx_fifo(core_if); ++ ++ return retval; ++} ++ ++/** ++ * This function sets a new value for the buffer Alignment setup. ++ */ ++static int cfi_ep_set_tx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd) ++{ ++ int retval; ++ uint32_t fsiz; ++ uint16_t size; ++ uint16_t ep_addr; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params; ++ tx_fifo_size_setup_t *ptxfifoval; ++ ++ ptxfifoval = (tx_fifo_size_setup_t *) buf; ++ ep_addr = ptxfifoval->bEndpointAddress; ++ size = ptxfifoval->wDepth; ++ ++ ep = get_ep_by_addr(pcd, ep_addr); ++ ++ CFI_INFO ++ ("%s: Set Tx FIFO size: endpoint addr=0x%02x, depth=%d, FIFO Num=%d\n", ++ __func__, ep_addr, size, ep->dwc_ep.tx_fifo_num); ++ ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, ep_addr); ++ return -DWC_E_INVALID; ++ } ++ ++ fsiz = params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1]; ++ params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = size; ++ ++ if (resize_fifos(GET_CORE_IF(pcd))) { ++ retval = 0; ++ } else { ++ CFI_INFO ++ ("%s: Error setting the feature Tx FIFO Size for EP%d\n", ++ __func__, ep_addr); ++ params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = fsiz; ++ retval = -DWC_E_INVALID; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function sets a new value for the buffer Alignment setup. ++ */ ++static int cfi_set_rx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd) ++{ ++ int retval; ++ uint32_t fsiz; ++ uint16_t size; ++ dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params; ++ rx_fifo_size_setup_t *prxfifoval; ++ ++ prxfifoval = (rx_fifo_size_setup_t *) buf; ++ size = prxfifoval->wDepth; ++ ++ fsiz = params->dev_rx_fifo_size; ++ params->dev_rx_fifo_size = size; ++ ++ if (resize_fifos(GET_CORE_IF(pcd))) { ++ retval = 0; ++ } else { ++ CFI_INFO("%s: Error setting the feature Rx FIFO Size\n", ++ __func__); ++ params->dev_rx_fifo_size = fsiz; ++ retval = -DWC_E_INVALID; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function reads the SG of an EP's buffer setup into the buffer buf ++ */ ++static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req) ++{ ++ int retval = -DWC_E_INVALID; ++ uint8_t addr; ++ cfi_ep_t *ep; ++ ++ /* The Low Byte of the wValue contains a non-zero address of the endpoint */ ++ addr = req->wValue & 0xFF; ++ if (addr == 0) /* The address should be non-zero */ ++ return retval; ++ ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n", ++ __func__, addr); ++ return retval; ++ } ++ ++ dwc_memcpy(buf, ep->bm_sg, BS_SG_VAL_DESC_LEN); ++ retval = BS_SG_VAL_DESC_LEN; ++ return retval; ++} ++ ++/** ++ * This function reads the Concatenation value of an EP's buffer mode into ++ * the buffer buf ++ */ ++static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req) ++{ ++ int retval = -DWC_E_INVALID; ++ uint8_t addr; ++ cfi_ep_t *ep; ++ uint8_t desc_count; ++ ++ /* The Low Byte of the wValue contains a non-zero address of the endpoint */ ++ addr = req->wValue & 0xFF; ++ if (addr == 0) /* The address should be non-zero */ ++ return retval; ++ ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n", ++ __func__, addr); ++ return retval; ++ } ++ ++ /* Copy the header to the buffer */ ++ dwc_memcpy(buf, ep->bm_concat, BS_CONCAT_VAL_HDR_LEN); ++ /* Advance the buffer pointer by the header size */ ++ buf += BS_CONCAT_VAL_HDR_LEN; ++ ++ desc_count = ep->bm_concat->hdr.bDescCount; ++ /* Copy alll the wTxBytes to the buffer */ ++ dwc_memcpy(buf, ep->bm_concat->wTxBytes, sizeof(uid16_t) * desc_count); ++ ++ retval = BS_CONCAT_VAL_HDR_LEN + sizeof(uid16_t) * desc_count; ++ return retval; ++} ++ ++/** ++ * This function reads the buffer Alignment value of an EP's buffer mode into ++ * the buffer buf ++ * ++ * @return The total number of bytes copied to the buffer or negative error code. ++ */ ++static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req) ++{ ++ int retval = -DWC_E_INVALID; ++ uint8_t addr; ++ cfi_ep_t *ep; ++ ++ /* The Low Byte of the wValue contains a non-zero address of the endpoint */ ++ addr = req->wValue & 0xFF; ++ if (addr == 0) /* The address should be non-zero */ ++ return retval; ++ ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n", ++ __func__, addr); ++ return retval; ++ } ++ ++ dwc_memcpy(buf, ep->bm_align, BS_ALIGN_VAL_HDR_LEN); ++ retval = BS_ALIGN_VAL_HDR_LEN; ++ ++ return retval; ++} ++ ++/** ++ * This function sets a new value for the specified feature ++ * ++ * @param pcd A pointer to the PCD object ++ * ++ * @return 0 if successful, negative error code otherwise to stall the DCE. ++ */ ++static int cfi_set_feature_value(struct dwc_otg_pcd *pcd) ++{ ++ int retval = -DWC_E_NOT_SUPPORTED; ++ uint16_t wIndex, wValue; ++ uint8_t bRequest; ++ struct dwc_otg_core_if *coreif; ++ cfiobject_t *cfi = pcd->cfi; ++ struct cfi_usb_ctrlrequest *ctrl_req; ++ uint8_t *buf; ++ ctrl_req = &cfi->ctrl_req; ++ ++ buf = pcd->cfi->ctrl_req.data; ++ ++ coreif = GET_CORE_IF(pcd); ++ bRequest = ctrl_req->bRequest; ++ wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex); ++ wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue); ++ ++ /* See which feature is to be modified */ ++ switch (wIndex) { ++ case FT_ID_DMA_BUFFER_SETUP: ++ /* Modify the feature */ ++ if ((retval = cfi_ep_set_sg_val(buf, pcd)) < 0) ++ return retval; ++ ++ /* And send this request to the gadget */ ++ cfi->need_gadget_att = 1; ++ break; ++ ++ case FT_ID_DMA_BUFF_ALIGN: ++ if ((retval = cfi_ep_set_alignment_val(buf, pcd)) < 0) ++ return retval; ++ cfi->need_gadget_att = 1; ++ break; ++ ++ case FT_ID_DMA_CONCAT_SETUP: ++ /* Modify the feature */ ++ if ((retval = cfi_ep_set_concat_val(buf, pcd)) < 0) ++ return retval; ++ cfi->need_gadget_att = 1; ++ break; ++ ++ case FT_ID_DMA_CIRCULAR: ++ CFI_INFO("FT_ID_DMA_CIRCULAR\n"); ++ break; ++ ++ case FT_ID_THRESHOLD_SETUP: ++ CFI_INFO("FT_ID_THRESHOLD_SETUP\n"); ++ break; ++ ++ case FT_ID_DFIFO_DEPTH: ++ CFI_INFO("FT_ID_DFIFO_DEPTH\n"); ++ break; ++ ++ case FT_ID_TX_FIFO_DEPTH: ++ CFI_INFO("FT_ID_TX_FIFO_DEPTH\n"); ++ if ((retval = cfi_ep_set_tx_fifo_val(buf, pcd)) < 0) ++ return retval; ++ cfi->need_gadget_att = 0; ++ break; ++ ++ case FT_ID_RX_FIFO_DEPTH: ++ CFI_INFO("FT_ID_RX_FIFO_DEPTH\n"); ++ if ((retval = cfi_set_rx_fifo_val(buf, pcd)) < 0) ++ return retval; ++ cfi->need_gadget_att = 0; ++ break; ++ } ++ ++ return retval; ++} ++ ++#endif //DWC_UTE_CFI +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_cfi.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_cfi.h +new file mode 100644 +index 0000000..55fd337 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_cfi.h +@@ -0,0 +1,320 @@ ++/* ========================================================================== ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++#if !defined(__DWC_OTG_CFI_H__) ++#define __DWC_OTG_CFI_H__ ++ ++#include "dwc_otg_pcd.h" ++#include "dwc_cfi_common.h" ++ ++/** ++ * @file ++ * This file contains the CFI related OTG PCD specific common constants, ++ * interfaces(functions and macros) and data structures.The CFI Protocol is an ++ * optional interface for internal testing purposes that a DUT may implement to ++ * support testing of configurable features. ++ * ++ */ ++ ++struct dwc_otg_pcd; ++struct dwc_otg_pcd_ep; ++ ++/** OTG CFI Features (properties) ID constants */ ++/** This is a request for all Core Features */ ++#define FT_ID_DMA_MODE 0x0001 ++#define FT_ID_DMA_BUFFER_SETUP 0x0002 ++#define FT_ID_DMA_BUFF_ALIGN 0x0003 ++#define FT_ID_DMA_CONCAT_SETUP 0x0004 ++#define FT_ID_DMA_CIRCULAR 0x0005 ++#define FT_ID_THRESHOLD_SETUP 0x0006 ++#define FT_ID_DFIFO_DEPTH 0x0007 ++#define FT_ID_TX_FIFO_DEPTH 0x0008 ++#define FT_ID_RX_FIFO_DEPTH 0x0009 ++ ++/**********************************************************/ ++#define CFI_INFO_DEF ++ ++#ifdef CFI_INFO_DEF ++#define CFI_INFO(fmt...) DWC_PRINTF("CFI: " fmt); ++#else ++#define CFI_INFO(fmt...) ++#endif ++ ++#define min(x,y) ({ \ ++ x < y ? x : y; }) ++ ++#define max(x,y) ({ \ ++ x > y ? x : y; }) ++ ++/** ++ * Descriptor DMA SG Buffer setup structure (SG buffer). This structure is ++ * also used for setting up a buffer for Circular DDMA. ++ */ ++struct _ddma_sg_buffer_setup { ++#define BS_SG_VAL_DESC_LEN 6 ++ /* The OUT EP address */ ++ uint8_t bOutEndpointAddress; ++ /* The IN EP address */ ++ uint8_t bInEndpointAddress; ++ /* Number of bytes to put between transfer segments (must be DWORD boundaries) */ ++ uint8_t bOffset; ++ /* The number of transfer segments (a DMA descriptors per each segment) */ ++ uint8_t bCount; ++ /* Size (in byte) of each transfer segment */ ++ uint16_t wSize; ++} __attribute__ ((packed)); ++typedef struct _ddma_sg_buffer_setup ddma_sg_buffer_setup_t; ++ ++/** Descriptor DMA Concatenation Buffer setup structure */ ++struct _ddma_concat_buffer_setup_hdr { ++#define BS_CONCAT_VAL_HDR_LEN 4 ++ /* The endpoint for which the buffer is to be set up */ ++ uint8_t bEndpointAddress; ++ /* The count of descriptors to be used */ ++ uint8_t bDescCount; ++ /* The total size of the transfer */ ++ uint16_t wSize; ++} __attribute__ ((packed)); ++typedef struct _ddma_concat_buffer_setup_hdr ddma_concat_buffer_setup_hdr_t; ++ ++/** Descriptor DMA Concatenation Buffer setup structure */ ++struct _ddma_concat_buffer_setup { ++ /* The SG header */ ++ ddma_concat_buffer_setup_hdr_t hdr; ++ ++ /* The XFER sizes pointer (allocated dynamically) */ ++ uint16_t *wTxBytes; ++} __attribute__ ((packed)); ++typedef struct _ddma_concat_buffer_setup ddma_concat_buffer_setup_t; ++ ++/** Descriptor DMA Alignment Buffer setup structure */ ++struct _ddma_align_buffer_setup { ++#define BS_ALIGN_VAL_HDR_LEN 2 ++ uint8_t bEndpointAddress; ++ uint8_t bAlign; ++} __attribute__ ((packed)); ++typedef struct _ddma_align_buffer_setup ddma_align_buffer_setup_t; ++ ++/** Transmit FIFO Size setup structure */ ++struct _tx_fifo_size_setup { ++ uint8_t bEndpointAddress; ++ uint16_t wDepth; ++} __attribute__ ((packed)); ++typedef struct _tx_fifo_size_setup tx_fifo_size_setup_t; ++ ++/** Transmit FIFO Size setup structure */ ++struct _rx_fifo_size_setup { ++ uint16_t wDepth; ++} __attribute__ ((packed)); ++typedef struct _rx_fifo_size_setup rx_fifo_size_setup_t; ++ ++/** ++ * struct cfi_usb_ctrlrequest - the CFI implementation of the struct usb_ctrlrequest ++ * This structure encapsulates the standard usb_ctrlrequest and adds a pointer ++ * to the data returned in the data stage of a 3-stage Control Write requests. ++ */ ++struct cfi_usb_ctrlrequest { ++ uint8_t bRequestType; ++ uint8_t bRequest; ++ uint16_t wValue; ++ uint16_t wIndex; ++ uint16_t wLength; ++ uint8_t *data; ++} UPACKED; ++ ++/*---------------------------------------------------------------------------*/ ++ ++/** ++ * The CFI wrapper of the enabled and activated dwc_otg_pcd_ep structures. ++ * This structure is used to store the buffer setup data for any ++ * enabled endpoint in the PCD. ++ */ ++struct cfi_ep { ++ /* Entry for the list container */ ++ dwc_list_link_t lh; ++ /* Pointer to the active PCD endpoint structure */ ++ struct dwc_otg_pcd_ep *ep; ++ /* The last descriptor in the chain of DMA descriptors of the endpoint */ ++ struct dwc_otg_dma_desc *dma_desc_last; ++ /* The SG feature value */ ++ ddma_sg_buffer_setup_t *bm_sg; ++ /* The Circular feature value */ ++ ddma_sg_buffer_setup_t *bm_circ; ++ /* The Concatenation feature value */ ++ ddma_concat_buffer_setup_t *bm_concat; ++ /* The Alignment feature value */ ++ ddma_align_buffer_setup_t *bm_align; ++ /* XFER length */ ++ uint32_t xfer_len; ++ /* ++ * Count of DMA descriptors currently used. ++ * The total should not exceed the MAX_DMA_DESCS_PER_EP value ++ * defined in the dwc_otg_cil.h ++ */ ++ uint32_t desc_count; ++}; ++typedef struct cfi_ep cfi_ep_t; ++ ++typedef struct cfi_dma_buff { ++#define CFI_IN_BUF_LEN 1024 ++#define CFI_OUT_BUF_LEN 1024 ++ dma_addr_t addr; ++ uint8_t *buf; ++} cfi_dma_buff_t; ++ ++struct cfiobject; ++ ++/** ++ * This is the interface for the CFI operations. ++ * ++ * @param ep_enable Called when any endpoint is enabled and activated. ++ * @param release Called when the CFI object is released and it needs to correctly ++ * deallocate the dynamic memory ++ * @param ctrl_write_complete Called when the data stage of the request is complete ++ */ ++typedef struct cfi_ops { ++ int (*ep_enable) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd, ++ struct dwc_otg_pcd_ep * ep); ++ void *(*ep_alloc_buf) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd, ++ struct dwc_otg_pcd_ep * ep, dma_addr_t * dma, ++ unsigned size, gfp_t flags); ++ void (*release) (struct cfiobject * cfi); ++ int (*ctrl_write_complete) (struct cfiobject * cfi, ++ struct dwc_otg_pcd * pcd); ++ void (*build_descriptors) (struct cfiobject * cfi, ++ struct dwc_otg_pcd * pcd, ++ struct dwc_otg_pcd_ep * ep, ++ dwc_otg_pcd_request_t * req); ++} cfi_ops_t; ++ ++struct cfiobject { ++ cfi_ops_t ops; ++ struct dwc_otg_pcd *pcd; ++ struct usb_gadget *gadget; ++ ++ /* Buffers used to send/receive CFI-related request data */ ++ cfi_dma_buff_t buf_in; ++ cfi_dma_buff_t buf_out; ++ ++ /* CFI specific Control request wrapper */ ++ struct cfi_usb_ctrlrequest ctrl_req; ++ ++ /* The list of active EP's in the PCD of type cfi_ep_t */ ++ dwc_list_link_t active_eps; ++ ++ /* This flag shall control the propagation of a specific request ++ * to the gadget's processing routines. ++ * 0 - no gadget handling ++ * 1 - the gadget needs to know about this request (w/o completing a status ++ * phase - just return a 0 to the _setup callback) ++ */ ++ uint8_t need_gadget_att; ++ ++ /* Flag indicating whether the status IN phase needs to be ++ * completed by the PCD ++ */ ++ uint8_t need_status_in_complete; ++}; ++typedef struct cfiobject cfiobject_t; ++ ++#define DUMP_MSG ++ ++#if defined(DUMP_MSG) ++static inline void dump_msg(const u8 * buf, unsigned int length) ++{ ++ unsigned int start, num, i; ++ char line[52], *p; ++ ++ if (length >= 512) ++ return; ++ ++ start = 0; ++ while (length > 0) { ++ num = min(length, 16u); ++ p = line; ++ for (i = 0; i < num; ++i) { ++ if (i == 8) ++ *p++ = ' '; ++ DWC_SPRINTF(p, " %02x", buf[i]); ++ p += 3; ++ } ++ *p = 0; ++ DWC_DEBUG("%6x: %s\n", start, line); ++ buf += num; ++ start += num; ++ length -= num; ++ } ++} ++#else ++static inline void dump_msg(const u8 * buf, unsigned int length) ++{ ++} ++#endif ++ ++/** ++ * This function returns a pointer to cfi_ep_t object with the addr address. ++ */ ++static inline struct cfi_ep *get_cfi_ep_by_addr(struct cfiobject *cfi, ++ uint8_t addr) ++{ ++ struct cfi_ep *pcfiep; ++ dwc_list_link_t *tmp; ++ ++ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { ++ pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ ++ if (pcfiep->ep->desc->bEndpointAddress == addr) { ++ return pcfiep; ++ } ++ } ++ ++ return NULL; ++} ++ ++/** ++ * This function returns a pointer to cfi_ep_t object that matches ++ * the dwc_otg_pcd_ep object. ++ */ ++static inline struct cfi_ep *get_cfi_ep_by_pcd_ep(struct cfiobject *cfi, ++ struct dwc_otg_pcd_ep *ep) ++{ ++ struct cfi_ep *pcfiep = NULL; ++ dwc_list_link_t *tmp; ++ ++ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { ++ pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ if (pcfiep->ep == ep) { ++ return pcfiep; ++ } ++ } ++ return NULL; ++} ++ ++int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl); ++ ++#endif /* (__DWC_OTG_CFI_H__) */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_cil.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_cil.c +new file mode 100644 +index 0000000..60dc3c6 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_cil.c +@@ -0,0 +1,7375 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $ ++ * $Revision: #203 $ ++ * $Date: 2013/05/16 $ ++ * $Change: 2231774 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ * The Core Interface Layer provides basic services for accessing and ++ * managing the DWC_otg hardware. These services are used by both the ++ * Host Controller Driver and the Peripheral Controller Driver. ++ * ++ * The CIL manages the memory map for the core so that the HCD and PCD ++ * don't have to do this separately. It also handles basic tasks like ++ * reading/writing the registers and data FIFOs in the controller. ++ * Some of the data access functions provide encapsulation of several ++ * operations required to perform a task, such as writing multiple ++ * registers to start a transfer. Finally, the CIL performs basic ++ * services that are not specific to either the host or device modes ++ * of operation. These services include management of the OTG Host ++ * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A ++ * Diagnostic API is also provided to allow testing of the controller ++ * hardware. ++ * ++ * The Core Interface Layer has the following requirements: ++ * - Provides basic controller operations. ++ * - Minimal use of OS services. ++ * - The OS services used will be abstracted by using inline functions ++ * or macros. ++ * ++ */ ++ ++#include "dwc_os.h" ++#include "dwc_otg_regs.h" ++#include "dwc_otg_cil.h" ++ ++static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if); ++ ++/** ++ * This function is called to initialize the DWC_otg CSR data ++ * structures. The register addresses in the device and host ++ * structures are initialized from the base address supplied by the ++ * caller. The calling function must make the OS calls to get the ++ * base address of the DWC_otg controller registers. The core_params ++ * argument holds the parameters that specify how the core should be ++ * configured. ++ * ++ * @param reg_base_addr Base address of DWC_otg core registers ++ * ++ */ ++dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr) ++{ ++ dwc_otg_core_if_t *core_if = 0; ++ dwc_otg_dev_if_t *dev_if = 0; ++ dwc_otg_host_if_t *host_if = 0; ++ uint8_t *reg_base = (uint8_t *) reg_base_addr; ++ int i = 0; ++ ++ DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, reg_base_addr); ++ ++ core_if = DWC_ALLOC(sizeof(dwc_otg_core_if_t)); ++ ++ if (core_if == NULL) { ++ DWC_DEBUGPL(DBG_CIL, ++ "Allocation of dwc_otg_core_if_t failed\n"); ++ return 0; ++ } ++ core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base; ++ ++ /* ++ * Allocate the Device Mode structures. ++ */ ++ dev_if = DWC_ALLOC(sizeof(dwc_otg_dev_if_t)); ++ ++ if (dev_if == NULL) { ++ DWC_DEBUGPL(DBG_CIL, "Allocation of dwc_otg_dev_if_t failed\n"); ++ DWC_FREE(core_if); ++ return 0; ++ } ++ ++ dev_if->dev_global_regs = ++ (dwc_otg_device_global_regs_t *) (reg_base + ++ DWC_DEV_GLOBAL_REG_OFFSET); ++ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ dev_if->in_ep_regs[i] = (dwc_otg_dev_in_ep_regs_t *) ++ (reg_base + DWC_DEV_IN_EP_REG_OFFSET + ++ (i * DWC_EP_REG_OFFSET)); ++ ++ dev_if->out_ep_regs[i] = (dwc_otg_dev_out_ep_regs_t *) ++ (reg_base + DWC_DEV_OUT_EP_REG_OFFSET + ++ (i * DWC_EP_REG_OFFSET)); ++ DWC_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p\n", ++ i, &dev_if->in_ep_regs[i]->diepctl); ++ DWC_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p\n", ++ i, &dev_if->out_ep_regs[i]->doepctl); ++ } ++ ++ dev_if->speed = 0; // unknown ++ ++ core_if->dev_if = dev_if; ++ ++ /* ++ * Allocate the Host Mode structures. ++ */ ++ host_if = DWC_ALLOC(sizeof(dwc_otg_host_if_t)); ++ ++ if (host_if == NULL) { ++ DWC_DEBUGPL(DBG_CIL, ++ "Allocation of dwc_otg_host_if_t failed\n"); ++ DWC_FREE(dev_if); ++ DWC_FREE(core_if); ++ return 0; ++ } ++ ++ host_if->host_global_regs = (dwc_otg_host_global_regs_t *) ++ (reg_base + DWC_OTG_HOST_GLOBAL_REG_OFFSET); ++ ++ host_if->hprt0 = ++ (uint32_t *) (reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET); ++ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ host_if->hc_regs[i] = (dwc_otg_hc_regs_t *) ++ (reg_base + DWC_OTG_HOST_CHAN_REGS_OFFSET + ++ (i * DWC_OTG_CHAN_REGS_OFFSET)); ++ DWC_DEBUGPL(DBG_CILV, "hc_reg[%d]->hcchar=%p\n", ++ i, &host_if->hc_regs[i]->hcchar); ++ } ++ ++ host_if->num_host_channels = MAX_EPS_CHANNELS; ++ core_if->host_if = host_if; ++ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ core_if->data_fifo[i] = ++ (uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET + ++ (i * DWC_OTG_DATA_FIFO_SIZE)); ++ DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08lx\n", ++ i, (unsigned long)core_if->data_fifo[i]); ++ } ++ ++ core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET); ++ ++ /* Initiate lx_state to L3 disconnected state */ ++ core_if->lx_state = DWC_OTG_L3; ++ /* ++ * Store the contents of the hardware configuration registers here for ++ * easy access later. ++ */ ++ core_if->hwcfg1.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->ghwcfg1); ++ core_if->hwcfg2.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2); ++ core_if->hwcfg3.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->ghwcfg3); ++ core_if->hwcfg4.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4); ++ ++ /* Force host mode to get HPTXFSIZ exact power on value */ ++ { ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gusbcfg.b.force_host_mode = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ dwc_mdelay(10); ++ core_if->hptxfsiz.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz); ++ gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gusbcfg.b.force_host_mode = 0; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ dwc_mdelay(10); ++ ++ gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gusbcfg.b.force_dev_mode = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ dwc_mdelay(10); ++ } ++ ++ DWC_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32); ++ DWC_DEBUGPL(DBG_CILV, "hwcfg2=%08x\n", core_if->hwcfg2.d32); ++ DWC_DEBUGPL(DBG_CILV, "hwcfg3=%08x\n", core_if->hwcfg3.d32); ++ DWC_DEBUGPL(DBG_CILV, "hwcfg4=%08x\n", core_if->hwcfg4.d32); ++ ++ core_if->hcfg.d32 = ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ core_if->dcfg.d32 = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ ++ DWC_DEBUGPL(DBG_CILV, "hcfg=%08x\n", core_if->hcfg.d32); ++ DWC_DEBUGPL(DBG_CILV, "dcfg=%08x\n", core_if->dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_CILV, "op_mode=%0x\n", core_if->hwcfg2.b.op_mode); ++ DWC_DEBUGPL(DBG_CILV, "arch=%0x\n", core_if->hwcfg2.b.architecture); ++ DWC_DEBUGPL(DBG_CILV, "num_dev_ep=%d\n", core_if->hwcfg2.b.num_dev_ep); ++ DWC_DEBUGPL(DBG_CILV, "num_host_chan=%d\n", ++ core_if->hwcfg2.b.num_host_chan); ++ DWC_DEBUGPL(DBG_CILV, "nonperio_tx_q_depth=0x%0x\n", ++ core_if->hwcfg2.b.nonperio_tx_q_depth); ++ DWC_DEBUGPL(DBG_CILV, "host_perio_tx_q_depth=0x%0x\n", ++ core_if->hwcfg2.b.host_perio_tx_q_depth); ++ DWC_DEBUGPL(DBG_CILV, "dev_token_q_depth=0x%0x\n", ++ core_if->hwcfg2.b.dev_token_q_depth); ++ ++ DWC_DEBUGPL(DBG_CILV, "Total FIFO SZ=%d\n", ++ core_if->hwcfg3.b.dfifo_depth); ++ DWC_DEBUGPL(DBG_CILV, "xfer_size_cntr_width=%0x\n", ++ core_if->hwcfg3.b.xfer_size_cntr_width); ++ ++ /* ++ * Set the SRP sucess bit for FS-I2c ++ */ ++ core_if->srp_success = 0; ++ core_if->srp_timer_started = 0; ++ ++ /* ++ * Create new workqueue and init works ++ */ ++ core_if->wq_otg = DWC_WORKQ_ALLOC("dwc_otg"); ++ if (core_if->wq_otg == 0) { ++ DWC_WARN("DWC_WORKQ_ALLOC failed\n"); ++ DWC_FREE(host_if); ++ DWC_FREE(dev_if); ++ DWC_FREE(core_if); ++ return 0; ++ } ++ ++ core_if->snpsid = DWC_READ_REG32(&core_if->core_global_regs->gsnpsid); ++ ++ DWC_PRINTF("Core Release: %x.%x%x%x\n", ++ (core_if->snpsid >> 12 & 0xF), ++ (core_if->snpsid >> 8 & 0xF), ++ (core_if->snpsid >> 4 & 0xF), (core_if->snpsid & 0xF)); ++ ++ core_if->wkp_timer = DWC_TIMER_ALLOC("Wake Up Timer", ++ w_wakeup_detected, core_if); ++ if (core_if->wkp_timer == 0) { ++ DWC_WARN("DWC_TIMER_ALLOC failed\n"); ++ DWC_FREE(host_if); ++ DWC_FREE(dev_if); ++ DWC_WORKQ_FREE(core_if->wq_otg); ++ DWC_FREE(core_if); ++ return 0; ++ } ++ ++ if (dwc_otg_setup_params(core_if)) { ++ DWC_WARN("Error while setting core params\n"); ++ } ++ ++ core_if->hibernation_suspend = 0; ++ if (core_if->otg_ver) ++ core_if->test_mode = 0; ++ ++ /** ADP initialization */ ++ dwc_otg_adp_init(core_if); ++ ++ return core_if; ++} ++ ++/** ++ * This function frees the structures allocated by dwc_otg_cil_init(). ++ * ++ * @param core_if The core interface pointer returned from ++ * dwc_otg_cil_init(). ++ * ++ */ ++void dwc_otg_cil_remove(dwc_otg_core_if_t * core_if) ++{ ++ dctl_data_t dctl = {.d32 = 0 }; ++ /* Disable all interrupts */ ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 1, 0); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0); ++ ++ dctl.b.sftdiscon = 1; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, ++ dctl.d32); ++ } ++ ++ if (core_if->wq_otg) { ++ DWC_WORKQ_WAIT_WORK_DONE(core_if->wq_otg, 500); ++ DWC_WORKQ_FREE(core_if->wq_otg); ++ } ++ if (core_if->dev_if) { ++ DWC_FREE(core_if->dev_if); ++ } ++ if (core_if->host_if) { ++ DWC_FREE(core_if->host_if); ++ } ++ ++ /** Remove ADP Stuff */ ++ dwc_otg_adp_remove(core_if); ++ if (core_if->core_params) { ++ DWC_FREE(core_if->core_params); ++ } ++ if (core_if->wkp_timer) { ++ DWC_TIMER_FREE(core_if->wkp_timer); ++ } ++ if (core_if->srp_timer) { ++ DWC_TIMER_FREE(core_if->srp_timer); ++ } ++ DWC_FREE(core_if); ++} ++ ++/** ++ * This function enables the controller's Global Interrupt in the AHB Config ++ * register. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ gahbcfg_data_t ahbcfg = {.d32 = 0 }; ++ ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32); ++} ++ ++/** ++ * This function disables the controller's Global Interrupt in the AHB Config ++ * register. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ gahbcfg_data_t ahbcfg = {.d32 = 0 }; ++ ahbcfg.b.glblintrmsk = 1; /* Disable interrupts */ ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0); ++} ++ ++/** ++ * This function initializes the commmon interrupts, used in both ++ * device and host modes. ++ * ++ * @param core_if Programming view of the DWC_otg controller ++ * ++ */ ++static void dwc_otg_enable_common_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ /* Clear any pending OTG Interrupts */ ++ DWC_WRITE_REG32(&global_regs->gotgint, 0xFFFFFFFF); ++ ++ /* Clear any pending interrupts */ ++ DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* ++ * Enable the interrupts in the GINTMSK. ++ */ ++ if (!core_if->core_params->otg_ver) ++ /* To avoid system hang during OTG 2.0 role switch */ ++ intr_mask.b.modemismatch = 1; ++ intr_mask.b.otgintr = 1; ++ ++ if (!core_if->dma_enable) { ++ intr_mask.b.rxstsqlvl = 1; ++ } ++ ++ intr_mask.b.conidstschng = 1; ++ intr_mask.b.wkupintr = 1; ++ intr_mask.b.disconnect = 0; ++ intr_mask.b.usbsuspend = 1; ++ intr_mask.b.sessreqintr = 1; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ if (core_if->core_params->lpm_enable) { ++ intr_mask.b.lpmtranrcvd = 1; ++ } ++#endif ++ DWC_WRITE_REG32(&global_regs->gintmsk, intr_mask.d32); ++} ++ ++/* ++ * The restore operation is modified to support Synopsys Emulated Powerdown and ++ * Hibernation. This function is for exiting from Device mode hibernation by ++ * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup. ++ * @param core_if Programming view of DWC_otg controller. ++ * @param rem_wakeup - indicates whether resume is initiated by Device or Host. ++ * @param reset - indicates whether resume is initiated by Reset. ++ */ ++int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int rem_wakeup, int reset) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ ++ int timeout = 2000; ++ ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "%s called\n", __FUNCTION__); ++ /* Switch-on voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Assert Restore signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ if (rem_wakeup) { ++ dwc_udelay(70); ++ } ++ ++ /* Deassert Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Mask interrupts from gpwrdn */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.connect_det_msk = 1; ++ gpwrdn.b.srp_det_msk = 1; ++ gpwrdn.b.disconn_det_msk = 1; ++ gpwrdn.b.rst_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Indicates that we are going out from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* ++ * Set Restore Essential Regs bit in PCGCCTL register, restore_mode = 1 ++ * indicates restore from remote_wakeup ++ */ ++ restore_essential_regs(core_if, rem_wakeup, 0); ++ ++ /* ++ * Wait a little for seeing new value of variable hibernation_suspend if ++ * Restore done interrupt received before polling ++ */ ++ dwc_udelay(10); ++ ++ if (core_if->hibernation_suspend == 0) { ++ /* ++ * Wait For Restore_done Interrupt. This mechanism of polling the ++ * interrupt is introduced to avoid any possible race conditions ++ */ ++ do { ++ gintsts_data_t gintsts; ++ gintsts.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (gintsts.b.restoredone) { ++ gintsts.d32 = 0; ++ gintsts.b.restoredone = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, gintsts.d32); ++ DWC_PRINTF("Restore Done Interrupt seen\n"); ++ break; ++ } ++ dwc_udelay(10); ++ } while (--timeout); ++ if (!timeout) { ++ DWC_PRINTF("Restore Done interrupt wasn't generated here\n"); ++ } ++ } ++ /* Clear all pending interupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* De-assert Restore */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ if (!rem_wakeup) { ++ pcgcctl.d32 = 0; ++ pcgcctl.b.rstpdwnmodule = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ } ++ ++ /* Restore GUSBCFG and DCFG */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, ++ core_if->gr_backup->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, ++ core_if->dr_backup->dcfg); ++ ++ /* De-assert Wakeup Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ if (!rem_wakeup) { ++ /* Set Device programming done bit */ ++ dctl.b.pwronprgdone = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } else { ++ /* Start Remote Wakeup Signaling */ ++ dctl.d32 = core_if->dr_backup->dctl; ++ dctl.b.rmtwkupsig = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++ } ++ ++ dwc_mdelay(2); ++ /* Clear all pending interupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Restore global registers */ ++ dwc_otg_restore_global_regs(core_if); ++ /* Restore device global registers */ ++ dwc_otg_restore_dev_regs(core_if, rem_wakeup); ++ ++ if (rem_wakeup) { ++ dwc_mdelay(7); ++ dctl.d32 = 0; ++ dctl.b.rmtwkupsig = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); ++ } ++ ++ core_if->hibernation_suspend = 0; ++ /* The core will be in ON STATE */ ++ core_if->lx_state = DWC_OTG_L0; ++ DWC_PRINTF("Hibernation recovery completes here\n"); ++ ++ return 1; ++} ++ ++/* ++ * The restore operation is modified to support Synopsys Emulated Powerdown and ++ * Hibernation. This function is for exiting from Host mode hibernation by ++ * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup. ++ * @param core_if Programming view of DWC_otg controller. ++ * @param rem_wakeup - indicates whether resume is initiated by Device or Host. ++ * @param reset - indicates whether resume is initiated by Reset. ++ */ ++int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int rem_wakeup, int reset) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ ++ int timeout = 2000; ++ ++ DWC_DEBUGPL(DBG_HCD, "%s called\n", __FUNCTION__); ++ /* Switch-on voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Assert Restore signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ if (!rem_wakeup) { ++ dwc_udelay(50); ++ } ++ ++ /* Deassert Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.connect_det_msk = 1; ++ gpwrdn.b.srp_det_msk = 1; ++ gpwrdn.b.disconn_det_msk = 1; ++ gpwrdn.b.rst_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Indicates that we are going out from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Set Restore Essential Regs bit in PCGCCTL register */ ++ restore_essential_regs(core_if, rem_wakeup, 1); ++ ++ /* Wait a little for seeing new value of variable hibernation_suspend if ++ * Restore done interrupt received before polling */ ++ dwc_udelay(10); ++ ++ if (core_if->hibernation_suspend == 0) { ++ /* Wait For Restore_done Interrupt. This mechanism of polling the ++ * interrupt is introduced to avoid any possible race conditions ++ */ ++ do { ++ gintsts_data_t gintsts; ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (gintsts.b.restoredone) { ++ gintsts.d32 = 0; ++ gintsts.b.restoredone = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ DWC_DEBUGPL(DBG_HCD,"Restore Done Interrupt seen\n"); ++ break; ++ } ++ dwc_udelay(10); ++ } while (--timeout); ++ if (!timeout) { ++ DWC_WARN("Restore Done interrupt wasn't generated\n"); ++ } ++ } ++ ++ /* Set the flag's value to 0 again after receiving restore done interrupt */ ++ core_if->hibernation_suspend = 0; ++ ++ /* This step is not described in functional spec but if not wait for this ++ * delay, mismatch interrupts occurred because just after restore core is ++ * in Device mode(gintsts.curmode == 0) */ ++ dwc_mdelay(100); ++ ++ /* Clear all pending interrupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* De-assert Restore */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Restore GUSBCFG and HCFG */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, ++ core_if->gr_backup->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, ++ core_if->hr_backup->hcfg_local); ++ ++ /* De-assert Wakeup Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Start the Resume operation by programming HPRT0 */ ++ hprt0.d32 = core_if->hr_backup->hprt0_local; ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtena = 0; ++ hprt0.b.prtsusp = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ DWC_PRINTF("Resume Starts Now\n"); ++ if (!reset) { // Indicates it is Resume Operation ++ hprt0.d32 = core_if->hr_backup->hprt0_local; ++ hprt0.b.prtres = 1; ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtena = 0; ++ hprt0.b.prtsusp = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ if (!rem_wakeup) ++ hprt0.b.prtres = 0; ++ /* Wait for Resume time and then program HPRT again */ ++ dwc_mdelay(100); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ } else { // Indicates it is Reset Operation ++ hprt0.d32 = core_if->hr_backup->hprt0_local; ++ hprt0.b.prtrst = 1; ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtena = 0; ++ hprt0.b.prtsusp = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ /* Wait for Reset time and then program HPRT again */ ++ dwc_mdelay(60); ++ hprt0.b.prtrst = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } ++ /* Clear all interrupt status */ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtconndet = 1; ++ hprt0.b.prtenchng = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* Clear all pending interupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Restore global registers */ ++ dwc_otg_restore_global_regs(core_if); ++ /* Restore host global registers */ ++ dwc_otg_restore_host_regs(core_if, reset); ++ ++ /* The core will be in ON STATE */ ++ core_if->lx_state = DWC_OTG_L0; ++ DWC_PRINTF("Hibernation recovery is complete here\n"); ++ return 0; ++} ++ ++/** Saves some register values into system memory. */ ++int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ int i; ++ ++ gr = core_if->gr_backup; ++ if (!gr) { ++ gr = DWC_ALLOC(sizeof(*gr)); ++ if (!gr) { ++ return -DWC_E_NO_MEMORY; ++ } ++ core_if->gr_backup = gr; ++ } ++ ++ gr->gotgctl_local = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ gr->gahbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg); ++ gr->gusbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gr->grxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); ++ gr->gnptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz); ++ gr->hptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ gr->glpmcfg_local = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++#endif ++ gr->gi2cctl_local = DWC_READ_REG32(&core_if->core_global_regs->gi2cctl); ++ gr->pcgcctl_local = DWC_READ_REG32(core_if->pcgcctl); ++ gr->gdfifocfg_local = ++ DWC_READ_REG32(&core_if->core_global_regs->gdfifocfg); ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ gr->dtxfsiz_local[i] = ++ DWC_READ_REG32(&(core_if->core_global_regs->dtxfsiz[i])); ++ } ++ ++ DWC_DEBUGPL(DBG_ANY, "===========Backing Global registers==========\n"); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gotgctl = %08x\n", gr->gotgctl_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk = %08x\n", gr->gintmsk_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gahbcfg = %08x\n", gr->gahbcfg_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gusbcfg = %08x\n", gr->gusbcfg_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up grxfsiz = %08x\n", gr->grxfsiz_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gnptxfsiz = %08x\n", ++ gr->gnptxfsiz_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up hptxfsiz = %08x\n", ++ gr->hptxfsiz_local); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ DWC_DEBUGPL(DBG_ANY, "Backed up glpmcfg = %08x\n", gr->glpmcfg_local); ++#endif ++ DWC_DEBUGPL(DBG_ANY, "Backed up gi2cctl = %08x\n", gr->gi2cctl_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up pcgcctl = %08x\n", gr->pcgcctl_local); ++ DWC_DEBUGPL(DBG_ANY,"Backed up gdfifocfg = %08x\n",gr->gdfifocfg_local); ++ ++ return 0; ++} ++ ++/** Saves GINTMSK register before setting the msk bits. */ ++int dwc_otg_save_gintmsk_reg(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ ++ gr = core_if->gr_backup; ++ if (!gr) { ++ gr = DWC_ALLOC(sizeof(*gr)); ++ if (!gr) { ++ return -DWC_E_NO_MEMORY; ++ } ++ core_if->gr_backup = gr; ++ } ++ ++ gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ ++ DWC_DEBUGPL(DBG_ANY,"=============Backing GINTMSK registers============\n"); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk = %08x\n", gr->gintmsk_local); ++ ++ return 0; ++} ++ ++int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_dev_regs_backup *dr; ++ int i; ++ ++ dr = core_if->dr_backup; ++ if (!dr) { ++ dr = DWC_ALLOC(sizeof(*dr)); ++ if (!dr) { ++ return -DWC_E_NO_MEMORY; ++ } ++ core_if->dr_backup = dr; ++ } ++ ++ dr->dcfg = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ dr->dctl = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ dr->daintmsk = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk); ++ dr->diepmsk = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->diepmsk); ++ dr->doepmsk = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->doepmsk); ++ ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ dr->diepctl[i] = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl); ++ dr->dieptsiz[i] = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz); ++ dr->diepdma[i] = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma); ++ } ++ ++ DWC_DEBUGPL(DBG_ANY, ++ "=============Backing Host registers==============\n"); ++ DWC_DEBUGPL(DBG_ANY, "Backed up dcfg = %08x\n", dr->dcfg); ++ DWC_DEBUGPL(DBG_ANY, "Backed up dctl = %08x\n", dr->dctl); ++ DWC_DEBUGPL(DBG_ANY, "Backed up daintmsk = %08x\n", ++ dr->daintmsk); ++ DWC_DEBUGPL(DBG_ANY, "Backed up diepmsk = %08x\n", dr->diepmsk); ++ DWC_DEBUGPL(DBG_ANY, "Backed up doepmsk = %08x\n", dr->doepmsk); ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ DWC_DEBUGPL(DBG_ANY, "Backed up diepctl[%d] = %08x\n", i, ++ dr->diepctl[i]); ++ DWC_DEBUGPL(DBG_ANY, "Backed up dieptsiz[%d] = %08x\n", ++ i, dr->dieptsiz[i]); ++ DWC_DEBUGPL(DBG_ANY, "Backed up diepdma[%d] = %08x\n", i, ++ dr->diepdma[i]); ++ } ++ ++ return 0; ++} ++ ++int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_host_regs_backup *hr; ++ int i; ++ ++ hr = core_if->hr_backup; ++ if (!hr) { ++ hr = DWC_ALLOC(sizeof(*hr)); ++ if (!hr) { ++ return -DWC_E_NO_MEMORY; ++ } ++ core_if->hr_backup = hr; ++ } ++ ++ hr->hcfg_local = ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ hr->haintmsk_local = ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk); ++ for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) { ++ hr->hcintmsk_local[i] = ++ DWC_READ_REG32(&core_if->host_if->hc_regs[i]->hcintmsk); ++ } ++ hr->hprt0_local = DWC_READ_REG32(core_if->host_if->hprt0); ++ hr->hfir_local = ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir); ++ ++ DWC_DEBUGPL(DBG_ANY, ++ "=============Backing Host registers===============\n"); ++ DWC_DEBUGPL(DBG_ANY, "Backed up hcfg = %08x\n", ++ hr->hcfg_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up haintmsk = %08x\n", hr->haintmsk_local); ++ for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) { ++ DWC_DEBUGPL(DBG_ANY, "Backed up hcintmsk[%02d]=%08x\n", i, ++ hr->hcintmsk_local[i]); ++ } ++ DWC_DEBUGPL(DBG_ANY, "Backed up hprt0 = %08x\n", ++ hr->hprt0_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up hfir = %08x\n", ++ hr->hfir_local); ++ ++ return 0; ++} ++ ++int dwc_otg_restore_global_regs(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ int i; ++ ++ gr = core_if->gr_backup; ++ if (!gr) { ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, gr->gotgctl_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gr->gintmsk_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gr->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gr->gahbcfg_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, gr->grxfsiz_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, ++ gr->gnptxfsiz_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->hptxfsiz, ++ gr->hptxfsiz_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gdfifocfg, ++ gr->gdfifocfg_local); ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ DWC_WRITE_REG32(&core_if->core_global_regs->dtxfsiz[i], ++ gr->dtxfsiz_local[i]); ++ } ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, 0x0000100A); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, ++ (gr->gahbcfg_local)); ++ return 0; ++} ++ ++int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, int rem_wakeup) ++{ ++ struct dwc_otg_dev_regs_backup *dr; ++ int i; ++ ++ dr = core_if->dr_backup; ++ ++ if (!dr) { ++ return -DWC_E_INVALID; ++ } ++ ++ if (!rem_wakeup) { ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ dr->dctl); ++ } ++ ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, dr->daintmsk); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, dr->diepmsk); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, dr->doepmsk); ++ ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz, dr->dieptsiz[i]); ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma, dr->diepdma[i]); ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl, dr->diepctl[i]); ++ } ++ ++ return 0; ++} ++ ++int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset) ++{ ++ struct dwc_otg_host_regs_backup *hr; ++ int i; ++ hr = core_if->hr_backup; ++ ++ if (!hr) { ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hr->hcfg_local); ++ //if (!reset) ++ //{ ++ // DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hr->hfir_local); ++ //} ++ ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, ++ hr->haintmsk_local); ++ for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) { ++ DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, ++ hr->hcintmsk_local[i]); ++ } ++ ++ return 0; ++} ++ ++int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ ++ gr = core_if->gr_backup; ++ ++ /* Restore values for LPM and I2C */ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, gr->glpmcfg_local); ++#endif ++ DWC_WRITE_REG32(&core_if->core_global_regs->gi2cctl, gr->gi2cctl_local); ++ ++ return 0; ++} ++ ++int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode, int is_host) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gahbcfg_data_t gahbcfg = {.d32 = 0 }; ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ /* Restore LPM and I2C registers */ ++ restore_lpm_i2c_regs(core_if); ++ ++ /* Set PCGCCTL to 0 */ ++ DWC_WRITE_REG32(core_if->pcgcctl, 0x00000000); ++ ++ gr = core_if->gr_backup; ++ /* Load restore values for [31:14] bits */ ++ DWC_WRITE_REG32(core_if->pcgcctl, ++ ((gr->pcgcctl_local & 0xffffc000) | 0x00020000)); ++ ++ /* Umnask global Interrupt in GAHBCFG and restore it */ ++ gahbcfg.d32 = gr->gahbcfg_local; ++ gahbcfg.b.glblintrmsk = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32); ++ ++ /* Clear all pending interupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Unmask restore done interrupt */ ++ gintmsk.b.restoredone = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32); ++ ++ /* Restore GUSBCFG and HCFG/DCFG */ ++ gusbcfg.d32 = core_if->gr_backup->gusbcfg_local; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ ++ if (is_host) { ++ hcfg_data_t hcfg = {.d32 = 0 }; ++ hcfg.d32 = core_if->hr_backup->hcfg_local; ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, ++ hcfg.d32); ++ ++ /* Load restore values for [31:14] bits */ ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local | 0x00020000; ++ ++ if (rmode) ++ pcgcctl.b.restoremode = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ dwc_udelay(10); ++ ++ /* Load restore values for [31:14] bits and set EssRegRestored bit */ ++ pcgcctl.d32 = gr->pcgcctl_local | 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.b.ess_reg_restored = 1; ++ if (rmode) ++ pcgcctl.b.restoremode = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ } else { ++ dcfg_data_t dcfg = {.d32 = 0 }; ++ dcfg.d32 = core_if->dr_backup->dcfg; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ /* Load restore values for [31:14] bits */ ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local | 0x00020000; ++ if (!rmode) { ++ pcgcctl.d32 |= 0x208; ++ } ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ dwc_udelay(10); ++ ++ /* Load restore values for [31:14] bits */ ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local | 0x00020000; ++ pcgcctl.b.ess_reg_restored = 1; ++ if (!rmode) ++ pcgcctl.d32 |= 0x208; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ } ++ ++ return 0; ++} ++ ++/** ++ * Initializes the FSLSPClkSel field of the HCFG register depending on the PHY ++ * type. ++ */ ++static void init_fslspclksel(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t val; ++ hcfg_data_t hcfg; ++ ++ if (((core_if->hwcfg2.b.hs_phy_type == 2) && ++ (core_if->hwcfg2.b.fs_phy_type == 1) && ++ (core_if->core_params->ulpi_fs_ls)) || ++ (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) { ++ /* Full speed PHY */ ++ val = DWC_HCFG_48_MHZ; ++ } else { ++ /* High speed PHY running at full speed or high speed */ ++ val = DWC_HCFG_30_60_MHZ; ++ } ++ ++ DWC_DEBUGPL(DBG_CIL, "Initializing HCFG.FSLSPClkSel to 0x%1x\n", val); ++ hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ hcfg.b.fslspclksel = val; ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++} ++ ++/** ++ * Initializes the DevSpd field of the DCFG register depending on the PHY type ++ * and the enumeration speed of the device. ++ */ ++static void init_devspd(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t val; ++ dcfg_data_t dcfg; ++ ++ if (((core_if->hwcfg2.b.hs_phy_type == 2) && ++ (core_if->hwcfg2.b.fs_phy_type == 1) && ++ (core_if->core_params->ulpi_fs_ls)) || ++ (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) { ++ /* Full speed PHY */ ++ val = 0x3; ++ } else if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) { ++ /* High speed PHY running at full speed */ ++ val = 0x1; ++ } else { ++ /* High speed PHY running at high speed */ ++ val = 0x0; ++ } ++ ++ DWC_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val); ++ ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ dcfg.b.devspd = val; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); ++} ++ ++/** ++ * This function calculates the number of IN EPS ++ * using GHWCFG1 and GHWCFG2 registers values ++ * ++ * @param core_if Programming view of the DWC_otg controller ++ */ ++static uint32_t calc_num_in_eps(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t num_in_eps = 0; ++ uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep; ++ uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 3; ++ uint32_t num_tx_fifos = core_if->hwcfg4.b.num_in_eps; ++ int i; ++ ++ for (i = 0; i < num_eps; ++i) { ++ if (!(hwcfg1 & 0x1)) ++ num_in_eps++; ++ ++ hwcfg1 >>= 2; ++ } ++ ++ if (core_if->hwcfg4.b.ded_fifo_en) { ++ num_in_eps = ++ (num_in_eps > num_tx_fifos) ? num_tx_fifos : num_in_eps; ++ } ++ ++ return num_in_eps; ++} ++ ++/** ++ * This function calculates the number of OUT EPS ++ * using GHWCFG1 and GHWCFG2 registers values ++ * ++ * @param core_if Programming view of the DWC_otg controller ++ */ ++static uint32_t calc_num_out_eps(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t num_out_eps = 0; ++ uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep; ++ uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 2; ++ int i; ++ ++ for (i = 0; i < num_eps; ++i) { ++ if (!(hwcfg1 & 0x1)) ++ num_out_eps++; ++ ++ hwcfg1 >>= 2; ++ } ++ return num_out_eps; ++} ++ ++/** ++ * This function initializes the DWC_otg controller registers and ++ * prepares the core for device mode or host mode operation. ++ * ++ * @param core_if Programming view of the DWC_otg controller ++ * ++ */ ++void dwc_otg_core_init(dwc_otg_core_if_t * core_if) ++{ ++ int i = 0; ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ gahbcfg_data_t ahbcfg = {.d32 = 0 }; ++ gusbcfg_data_t usbcfg = {.d32 = 0 }; ++ gi2cctl_data_t i2cctl = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_CILV, "dwc_otg_core_init(%p)\n", core_if); ++ ++ /* Common Initialization */ ++ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); ++ ++ /* Program the ULPI External VBUS bit if needed */ ++ usbcfg.b.ulpi_ext_vbus_drv = ++ (core_if->core_params->phy_ulpi_ext_vbus == ++ DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0; ++ ++ /* Set external TS Dline pulsing */ ++ usbcfg.b.term_sel_dl_pulse = ++ (core_if->core_params->ts_dline == 1) ? 1 : 0; ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ ++ /* Reset the Controller */ ++ dwc_otg_core_reset(core_if); ++ ++ core_if->adp_enable = core_if->core_params->adp_supp_enable; ++ core_if->power_down = core_if->core_params->power_down; ++ ++ /* Initialize parameters from Hardware configuration registers. */ ++ dev_if->num_in_eps = calc_num_in_eps(core_if); ++ dev_if->num_out_eps = calc_num_out_eps(core_if); ++ ++ DWC_DEBUGPL(DBG_CIL, "num_dev_perio_in_ep=%d\n", ++ core_if->hwcfg4.b.num_dev_perio_in_ep); ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { ++ dev_if->perio_tx_fifo_size[i] = ++ DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16; ++ DWC_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n", ++ i, dev_if->perio_tx_fifo_size[i]); ++ } ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ dev_if->tx_fifo_size[i] = ++ DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16; ++ DWC_DEBUGPL(DBG_CIL, "Tx FIFO SZ #%d=0x%0x\n", ++ i, dev_if->tx_fifo_size[i]); ++ } ++ ++ core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth; ++ core_if->rx_fifo_size = DWC_READ_REG32(&global_regs->grxfsiz); ++ core_if->nperio_tx_fifo_size = ++ DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16; ++ ++ DWC_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", core_if->total_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", core_if->rx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO SZ=%d\n", ++ core_if->nperio_tx_fifo_size); ++ ++ /* This programming sequence needs to happen in FS mode before any other ++ * programming occurs */ ++ if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) && ++ (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) { ++ /* If FS mode with FS PHY */ ++ ++ /* core_init() is now called on every switch so only call the ++ * following for the first time through. */ ++ if (!core_if->phy_init_done) { ++ core_if->phy_init_done = 1; ++ DWC_DEBUGPL(DBG_CIL, "FS_PHY detected\n"); ++ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); ++ usbcfg.b.physel = 1; ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ ++ /* Reset after a PHY select */ ++ dwc_otg_core_reset(core_if); ++ } ++ ++ /* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also ++ * do this on HNP Dev/Host mode switches (done in dev_init and ++ * host_init). */ ++ if (dwc_otg_is_host_mode(core_if)) { ++ init_fslspclksel(core_if); ++ } else { ++ init_devspd(core_if); ++ } ++ ++ if (core_if->core_params->i2c_enable) { ++ DWC_DEBUGPL(DBG_CIL, "FS_PHY Enabling I2c\n"); ++ /* Program GUSBCFG.OtgUtmifsSel to I2C */ ++ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); ++ usbcfg.b.otgutmifssel = 1; ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ ++ /* Program GI2CCTL.I2CEn */ ++ i2cctl.d32 = DWC_READ_REG32(&global_regs->gi2cctl); ++ i2cctl.b.i2cdevaddr = 1; ++ i2cctl.b.i2cen = 0; ++ DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32); ++ i2cctl.b.i2cen = 1; ++ DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32); ++ } ++ ++ } /* endif speed == DWC_SPEED_PARAM_FULL */ ++ else { ++ /* High speed PHY. */ ++ if (!core_if->phy_init_done) { ++ core_if->phy_init_done = 1; ++ /* HS PHY parameters. These parameters are preserved ++ * during soft reset so only program the first time. Do ++ * a soft reset immediately after setting phyif. */ ++ ++ if (core_if->core_params->phy_type == 2) { ++ /* ULPI interface */ ++ usbcfg.b.ulpi_utmi_sel = 1; ++ usbcfg.b.phyif = 0; ++ usbcfg.b.ddrsel = ++ core_if->core_params->phy_ulpi_ddr; ++ } else if (core_if->core_params->phy_type == 1) { ++ /* UTMI+ interface */ ++ usbcfg.b.ulpi_utmi_sel = 0; ++ if (core_if->core_params->phy_utmi_width == 16) { ++ usbcfg.b.phyif = 1; ++ ++ } else { ++ usbcfg.b.phyif = 0; ++ } ++ } else { ++ DWC_ERROR("FS PHY TYPE\n"); ++ } ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ /* Reset after setting the PHY parameters */ ++ dwc_otg_core_reset(core_if); ++ } ++ } ++ ++ if ((core_if->hwcfg2.b.hs_phy_type == 2) && ++ (core_if->hwcfg2.b.fs_phy_type == 1) && ++ (core_if->core_params->ulpi_fs_ls)) { ++ DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS\n"); ++ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); ++ usbcfg.b.ulpi_fsls = 1; ++ usbcfg.b.ulpi_clk_sus_m = 1; ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ } else { ++ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); ++ usbcfg.b.ulpi_fsls = 0; ++ usbcfg.b.ulpi_clk_sus_m = 0; ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ } ++ ++ /* Program the GAHBCFG Register. */ ++ switch (core_if->hwcfg2.b.architecture) { ++ ++ case DWC_SLAVE_ONLY_ARCH: ++ DWC_DEBUGPL(DBG_CIL, "Slave Only Mode\n"); ++ ahbcfg.b.nptxfemplvl_txfemplvl = ++ DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY; ++ ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY; ++ core_if->dma_enable = 0; ++ core_if->dma_desc_enable = 0; ++ break; ++ ++ case DWC_EXT_DMA_ARCH: ++ DWC_DEBUGPL(DBG_CIL, "External DMA Mode\n"); ++ { ++ uint8_t brst_sz = core_if->core_params->dma_burst_size; ++ ahbcfg.b.hburstlen = 0; ++ while (brst_sz > 1) { ++ ahbcfg.b.hburstlen++; ++ brst_sz >>= 1; ++ } ++ } ++ core_if->dma_enable = (core_if->core_params->dma_enable != 0); ++ core_if->dma_desc_enable = ++ (core_if->core_params->dma_desc_enable != 0); ++ break; ++ ++ case DWC_INT_DMA_ARCH: ++ DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n"); ++ /* Old value was DWC_GAHBCFG_INT_DMA_BURST_INCR - done for ++ Host mode ISOC in issue fix - vahrama */ ++ ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR4; ++ core_if->dma_enable = (core_if->core_params->dma_enable != 0); ++ core_if->dma_desc_enable = ++ (core_if->core_params->dma_desc_enable != 0); ++ break; ++ ++ } ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ DWC_PRINTF("Using Descriptor DMA mode\n"); ++ } else { ++ DWC_PRINTF("Using Buffer DMA mode\n"); ++ } ++ } else { ++ DWC_PRINTF("Using Slave mode\n"); ++ core_if->dma_desc_enable = 0; ++ } ++ ++ if (core_if->core_params->ahb_single) { ++ ahbcfg.b.ahbsingle = 1; ++ } ++ ++ ahbcfg.b.dmaenable = core_if->dma_enable; ++ DWC_WRITE_REG32(&global_regs->gahbcfg, ahbcfg.d32); ++ ++ core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en; ++ ++ core_if->pti_enh_enable = core_if->core_params->pti_enable != 0; ++ core_if->multiproc_int_enable = core_if->core_params->mpi_enable; ++ ++ /* ++ * Program the GUSBCFG register. ++ */ ++ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); ++ ++ switch (core_if->hwcfg2.b.op_mode) { ++ case DWC_MODE_HNP_SRP_CAPABLE: ++ usbcfg.b.hnpcap = (core_if->core_params->otg_cap == ++ DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE); ++ usbcfg.b.srpcap = (core_if->core_params->otg_cap != ++ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ break; ++ ++ case DWC_MODE_SRP_ONLY_CAPABLE: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = (core_if->core_params->otg_cap != ++ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ break; ++ ++ case DWC_MODE_NO_HNP_SRP_CAPABLE: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = 0; ++ break; ++ ++ case DWC_MODE_SRP_CAPABLE_DEVICE: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = (core_if->core_params->otg_cap != ++ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ break; ++ ++ case DWC_MODE_NO_SRP_CAPABLE_DEVICE: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = 0; ++ break; ++ ++ case DWC_MODE_SRP_CAPABLE_HOST: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = (core_if->core_params->otg_cap != ++ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ break; ++ ++ case DWC_MODE_NO_SRP_CAPABLE_HOST: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = 0; ++ break; ++ } ++ ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ if (core_if->core_params->lpm_enable) { ++ glpmcfg_data_t lpmcfg = {.d32 = 0 }; ++ ++ /* To enable LPM support set lpm_cap_en bit */ ++ lpmcfg.b.lpm_cap_en = 1; ++ ++ /* Make AppL1Res ACK */ ++ lpmcfg.b.appl_resp = 1; ++ ++ /* Retry 3 times */ ++ lpmcfg.b.retry_count = 3; ++ ++ DWC_MODIFY_REG32(&core_if->core_global_regs->glpmcfg, ++ 0, lpmcfg.d32); ++ ++ } ++#endif ++ if (core_if->core_params->ic_usb_cap) { ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ gusbcfg.b.ic_usb_cap = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gusbcfg, ++ 0, gusbcfg.d32); ++ } ++ { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gotgctl.b.otgver = core_if->core_params->otg_ver; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, 0, ++ gotgctl.d32); ++ /* Set OTG version supported */ ++ core_if->otg_ver = core_if->core_params->otg_ver; ++ } ++ ++ /* Enable common interrupts */ ++ dwc_otg_enable_common_interrupts(core_if); ++ ++ /* Do device or host intialization based on mode during PCD ++ * and HCD initialization */ ++ if (dwc_otg_is_host_mode(core_if)) { ++ DWC_DEBUGPL(DBG_ANY, "Host Mode\n"); ++ core_if->op_state = A_HOST; ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "Device Mode\n"); ++ core_if->op_state = B_PERIPHERAL; ++#ifdef DWC_DEVICE_ONLY ++ dwc_otg_core_dev_init(core_if); ++#endif ++ } ++} ++ ++/** ++ * This function enables the Device mode interrupts. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ */ ++void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ ++ DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__); ++ ++ /* Disable all interrupts. */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* Clear any pending interrupts */ ++ DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Enable the common interrupts */ ++ dwc_otg_enable_common_interrupts(core_if); ++ ++ /* Enable interrupts */ ++ intr_mask.b.usbreset = 1; ++ intr_mask.b.enumdone = 1; ++ /* Disable Disconnect interrupt in Device mode */ ++ intr_mask.b.disconnect = 0; ++ ++ if (!core_if->multiproc_int_enable) { ++ intr_mask.b.inepintr = 1; ++ intr_mask.b.outepintr = 1; ++ } ++ ++ intr_mask.b.erlysuspend = 1; ++ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.epmismatch = 1; ++ } ++ ++ //intr_mask.b.incomplisoout = 1; ++ if (!core_if->dma_desc_enable) ++ intr_mask.b.incomplisoin = 1; ++ ++/* Enable the ignore frame number for ISOC xfers - MAS */ ++/* Disable to support high bandwith ISOC transfers - manukz */ ++#if 0 ++#ifdef DWC_UTE_PER_IO ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ dctl_data_t dctl1 = {.d32 = 0 }; ++ dctl1.b.ifrmnum = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, 0, dctl1.d32); ++ DWC_DEBUG("----Enabled Ignore frame number (0x%08x)", ++ DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dctl)); ++ } ++ } ++#endif ++#endif ++#ifdef DWC_EN_ISOC ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ if (core_if->pti_enh_enable) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.b.ifrmnum = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dctl, ++ 0, dctl.d32); ++ } else { ++ intr_mask.b.incomplisoin = 1; ++ intr_mask.b.incomplisoout = 1; ++ } ++ } ++ } else { ++ intr_mask.b.incomplisoin = 1; ++ intr_mask.b.incomplisoout = 1; ++ } ++#endif /* DWC_EN_ISOC */ ++ ++ /** @todo NGS: Should this be a module parameter? */ ++#ifdef USE_PERIODIC_EP ++ intr_mask.b.isooutdrop = 1; ++ intr_mask.b.eopframe = 1; ++ intr_mask.b.incomplisoin = 1; ++ intr_mask.b.incomplisoout = 1; ++#endif ++ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); ++ ++ DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__, ++ DWC_READ_REG32(&global_regs->gintmsk)); ++} ++ ++/** ++ * This function initializes the DWC_otg controller registers for ++ * device mode. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ */ ++void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if) ++{ ++ int i; ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dwc_otg_core_params_t *params = core_if->core_params; ++ dcfg_data_t dcfg = {.d32 = 0 }; ++ depctl_data_t diepctl = {.d32 = 0 }; ++ grstctl_t resetctl = {.d32 = 0 }; ++ uint32_t rx_fifo_size; ++ fifosize_data_t nptxfifosize; ++ fifosize_data_t txfifosize; ++ dthrctl_data_t dthrctl; ++ fifosize_data_t ptxfifosize; ++ uint16_t rxfsiz, nptxfsiz; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ hwcfg3_data_t hwcfg3 = {.d32 = 0 }; ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ ++ /* Restart the Phy Clock */ ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ /* Restart the Phy Clock */ ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ dwc_udelay(10); ++ ++ /* Device configuration register */ ++ init_devspd(core_if); ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.descdma = (core_if->dma_desc_enable) ? 1 : 0; ++ dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_95; ++ /* Enable Device OUT NAK in case of DDMA mode */ ++ if (core_if->core_params->dev_out_nak) { ++ dcfg.b.endevoutnak = 1; ++ } ++ ++ if (core_if->core_params->cont_on_bna) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.b.encontonbna = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } ++ /** should be done before every reset */ ++ if (core_if->otg_ver) { ++ core_if->otg_sts = 0; ++ gotgctl.b.devhnpen = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, gotgctl.d32, 0); ++ } ++ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ /* Configure data FIFO sizes */ ++ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { ++ DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n", ++ core_if->total_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n", ++ params->dev_rx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n", ++ params->dev_nperio_tx_fifo_size); ++ ++ /* Rx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->grxfsiz)); ++ ++#ifdef DWC_UTE_CFI ++ core_if->pwron_rxfsiz = DWC_READ_REG32(&global_regs->grxfsiz); ++ core_if->init_rxfsiz = params->dev_rx_fifo_size; ++#endif ++ rx_fifo_size = params->dev_rx_fifo_size; ++ DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size); ++ ++ DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->grxfsiz)); ++ ++ /** Set Periodic Tx FIFO Mask all bits 0 */ ++ core_if->p_tx_msk = 0; ++ ++ /** Set Tx FIFO Mask all bits 0 */ ++ core_if->tx_msk = 0; ++ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ /* Non-periodic Tx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); ++ ++ nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; ++ nptxfifosize.b.startaddr = params->dev_rx_fifo_size; ++ ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, ++ nptxfifosize.d32); ++ ++ DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); ++ ++ /**@todo NGS: Fix Periodic FIFO Sizing! */ ++ /* ++ * Periodic Tx FIFOs These FIFOs are numbered from 1 to 15. ++ * Indexes of the FIFO size module parameters in the ++ * dev_perio_tx_fifo_size array and the FIFO size registers in ++ * the dptxfsiz array run from 0 to 14. ++ */ ++ /** @todo Finish debug of this */ ++ ptxfifosize.b.startaddr = ++ nptxfifosize.b.startaddr + nptxfifosize.b.depth; ++ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { ++ ptxfifosize.b.depth = ++ params->dev_perio_tx_fifo_size[i]; ++ DWC_DEBUGPL(DBG_CIL, ++ "initial dtxfsiz[%d]=%08x\n", i, ++ DWC_READ_REG32(&global_regs->dtxfsiz ++ [i])); ++ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], ++ ptxfifosize.d32); ++ DWC_DEBUGPL(DBG_CIL, "new dtxfsiz[%d]=%08x\n", ++ i, ++ DWC_READ_REG32(&global_regs->dtxfsiz ++ [i])); ++ ptxfifosize.b.startaddr += ptxfifosize.b.depth; ++ } ++ } else { ++ /* ++ * Tx FIFOs These FIFOs are numbered from 1 to 15. ++ * Indexes of the FIFO size module parameters in the ++ * dev_tx_fifo_size array and the FIFO size registers in ++ * the dtxfsiz array run from 0 to 14. ++ */ ++ ++ /* Non-periodic Tx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); ++ ++#ifdef DWC_UTE_CFI ++ core_if->pwron_gnptxfsiz = ++ (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16); ++ core_if->init_gnptxfsiz = ++ params->dev_nperio_tx_fifo_size; ++#endif ++ nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; ++ nptxfifosize.b.startaddr = params->dev_rx_fifo_size; ++ ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, ++ nptxfifosize.d32); ++ ++ DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); ++ ++ txfifosize.b.startaddr = ++ nptxfifosize.b.startaddr + nptxfifosize.b.depth; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ ++ txfifosize.b.depth = ++ params->dev_tx_fifo_size[i]; ++ ++ DWC_DEBUGPL(DBG_CIL, ++ "initial dtxfsiz[%d]=%08x\n", ++ i, ++ DWC_READ_REG32(&global_regs->dtxfsiz ++ [i])); ++ ++#ifdef DWC_UTE_CFI ++ core_if->pwron_txfsiz[i] = ++ (DWC_READ_REG32 ++ (&global_regs->dtxfsiz[i]) >> 16); ++ core_if->init_txfsiz[i] = ++ params->dev_tx_fifo_size[i]; ++#endif ++ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], ++ txfifosize.d32); ++ ++ DWC_DEBUGPL(DBG_CIL, ++ "new dtxfsiz[%d]=%08x\n", ++ i, ++ DWC_READ_REG32(&global_regs->dtxfsiz ++ [i])); ++ ++ txfifosize.b.startaddr += txfifosize.b.depth; ++ } ++ ++ /* Calculating DFIFOCFG for Device mode to include RxFIFO and NPTXFIFO ++ * Before 3.00a EpInfoBase was being configured in ep enable/disable ++ * routine as well. Starting from 3.00a it will be set to the end of ++ * allocated FIFO space here due to ep 0 OUT always keeping enabled ++ */ ++ gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg); ++ hwcfg3.d32 = DWC_READ_REG32(&global_regs->ghwcfg3); ++ gdfifocfg.b.gdfifocfg = (DWC_READ_REG32(&global_regs->ghwcfg3) >> 16); ++ DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) { ++ rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff); ++ nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16); ++ gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz; ++ } else { ++ gdfifocfg.b.epinfobase = txfifosize.b.startaddr; ++ } ++ DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); ++ } ++ } ++ ++ /* Flush the FIFOs */ ++ dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ ++ dwc_otg_flush_rx_fifo(core_if); ++ ++ /* Flush the Learning Queue. */ ++ resetctl.b.intknqflsh = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); ++ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) { ++ core_if->start_predict = 0; ++ for (i = 0; i <= core_if->dev_if->num_in_eps; ++i) { ++ core_if->nextep_seq[i] = 0xff; // 0xff - EP not active ++ } ++ core_if->nextep_seq[0] = 0; ++ core_if->first_in_nextep_seq = 0; ++ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); ++ diepctl.b.nextep = 0; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); ++ ++ /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */ ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt = 2; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_CILV, ++ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_CILV, "%2d ", core_if->nextep_seq[i]); ++ } ++ DWC_DEBUGPL(DBG_CILV, "\n"); ++ } ++ ++ /* Clear all pending Device Interrupts */ ++ /** @todo - if the condition needed to be checked ++ * or in any case all pending interrutps should be cleared? ++ */ ++ if (core_if->multiproc_int_enable) { ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ DWC_WRITE_REG32(&dev_if->dev_global_regs-> ++ diepeachintmsk[i], 0); ++ } ++ ++ for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { ++ DWC_WRITE_REG32(&dev_if->dev_global_regs-> ++ doepeachintmsk[i], 0); ++ } ++ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->deachint, 0xFFFFFFFF); ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, 0); ++ } else { ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, 0); ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, 0); ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF); ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, 0); ++ } ++ ++ for (i = 0; i <= dev_if->num_in_eps; i++) { ++ depctl_data_t depctl; ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (depctl.b.epena) { ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ } else { ++ depctl.d32 = 0; ++ depctl.b.snak = 1; ++ } ++ ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); ++ ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, 0); ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, 0); ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepint, 0xFF); ++ } ++ ++ for (i = 1; i <= dev_if->num_out_eps; i++) { ++ depctl_data_t depctl; ++ depctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); ++ if (depctl.b.epena) { ++ int j = 0; ++ dctl_data_t dctl = {.d32 = 0 }; ++ gintmsk_data_t gintsts = {.d32 = 0 }; ++ doepint_data_t doepint = {.d32 = 0 }; ++ device_grxsts_data_t status; ++ dctl.b.sgoutnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ if (!core_if->dma_enable) { ++ do { ++ j++; ++ dwc_udelay(10); ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (j == 100000) { ++ DWC_ERROR("SNAK is not set during 10s\n"); ++ break; ++ } ++ } while (!gintsts.b.rxstsqlvl); ++ status.d32 = DWC_READ_REG32(&global_regs->grxstsp); ++ if (status.b.pktsts == DWC_DSTS_GOUT_NAK) ++ DWC_DEBUGPL(DBG_PCDV, "Global OUT NAK\n"); ++ gintsts.d32 = 0; ++ gintsts.b.rxstsqlvl = 1; ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ } ++ j = 0; ++ do { ++ j++; ++ dwc_udelay(10); ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (j == 100000) { ++ DWC_ERROR("SNAK is not set during 10s\n"); ++ break; ++ } ++ } while (!gintsts.b.goutnakeff); ++ gintsts.d32 = 0; ++ gintsts.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ j = 0; ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepctl, depctl.d32); ++ do { ++ dwc_udelay(10); ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[i]->doepint); ++ if (j == 100000) { ++ DWC_ERROR("EPDIS was not set during 10s\n"); ++ break; ++ } ++ } while (!doepint.b.epdisabled); ++ ++ doepint.b.epdisabled = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepint, doepint.d32); ++ ++ dctl.d32 = 0; ++ dctl.b.cgoutnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } else { ++ depctl.d32 = 0; ++ depctl.b.snak = 1; ++ } ++ ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32); ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doeptsiz, 0); ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepdma, 0); ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepint, 0xFF); ++ } ++ ++ if (core_if->en_multiple_tx_fifo && core_if->dma_enable) { ++ dev_if->non_iso_tx_thr_en = params->thr_ctl & 0x1; ++ dev_if->iso_tx_thr_en = (params->thr_ctl >> 1) & 0x1; ++ dev_if->rx_thr_en = (params->thr_ctl >> 2) & 0x1; ++ ++ dev_if->rx_thr_length = params->rx_thr_length; ++ dev_if->tx_thr_length = params->tx_thr_length; ++ ++ dev_if->setup_desc_index = 0; ++ ++ dthrctl.d32 = 0; ++ dthrctl.b.non_iso_thr_en = dev_if->non_iso_tx_thr_en; ++ dthrctl.b.iso_thr_en = dev_if->iso_tx_thr_en; ++ dthrctl.b.tx_thr_len = dev_if->tx_thr_length; ++ dthrctl.b.rx_thr_en = dev_if->rx_thr_en; ++ dthrctl.b.rx_thr_len = dev_if->rx_thr_length; ++ dthrctl.b.ahb_thr_ratio = params->ahb_thr_ratio; ++ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dtknqr3_dthrctl, ++ dthrctl.d32); ++ ++ DWC_DEBUGPL(DBG_CIL, ++ "Non ISO Tx Thr - %d\nISO Tx Thr - %d\nRx Thr - %d\nTx Thr Len - %d\nRx Thr Len - %d\n", ++ dthrctl.b.non_iso_thr_en, dthrctl.b.iso_thr_en, ++ dthrctl.b.rx_thr_en, dthrctl.b.tx_thr_len, ++ dthrctl.b.rx_thr_len); ++ ++ } ++ ++ dwc_otg_enable_device_interrupts(core_if); ++ ++ { ++ diepmsk_data_t msk = {.d32 = 0 }; ++ msk.b.txfifoundrn = 1; ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs-> ++ diepeachintmsk[0], msk.d32, msk.d32); ++ } else { ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, ++ msk.d32, msk.d32); ++ } ++ } ++ ++ if (core_if->multiproc_int_enable) { ++ /* Set NAK on Babble */ ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.b.nakonbble = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } ++ ++ if (core_if->snpsid >= OTG_CORE_REV_2_94a) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl); ++ dctl.b.sftdiscon = 0; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32); ++ } ++} ++ ++/** ++ * This function enables the Host mode interrupts. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ */ ++void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__); ++ ++ /* Disable all interrupts. */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* Clear any pending interrupts. */ ++ DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Enable the common interrupts */ ++ dwc_otg_enable_common_interrupts(core_if); ++ ++ /* ++ * Enable host mode interrupts without disturbing common ++ * interrupts. ++ */ ++ ++ intr_mask.b.disconnect = 1; ++ intr_mask.b.portintr = 1; ++ intr_mask.b.hcintr = 1; ++ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); ++} ++ ++/** ++ * This function disables the Host Mode interrupts. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ */ ++void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_CILV, "%s()\n", __func__); ++ ++ /* ++ * Disable host mode interrupts without disturbing common ++ * interrupts. ++ */ ++ intr_mask.b.sofintr = 1; ++ intr_mask.b.portintr = 1; ++ intr_mask.b.hcintr = 1; ++ intr_mask.b.ptxfempty = 1; ++ intr_mask.b.nptxfempty = 1; ++ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, 0); ++} ++ ++/** ++ * This function initializes the DWC_otg controller registers for ++ * host mode. ++ * ++ * This function flushes the Tx and Rx FIFOs and it flushes any entries in the ++ * request queues. Host channels are reset to ensure that they are ready for ++ * performing transfers. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ */ ++void dwc_otg_core_host_init(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ dwc_otg_host_if_t *host_if = core_if->host_if; ++ dwc_otg_core_params_t *params = core_if->core_params; ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ fifosize_data_t nptxfifosize; ++ fifosize_data_t ptxfifosize; ++ uint16_t rxfsiz, nptxfsiz, hptxfsiz; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ int i; ++ hcchar_data_t hcchar; ++ hcfg_data_t hcfg; ++ hfir_data_t hfir; ++ dwc_otg_hc_regs_t *hc_regs; ++ int num_channels; ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if); ++ ++ /* Restart the Phy Clock */ ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ dwc_udelay(10); ++ ++ if ((core_if->otg_ver == 1) && (core_if->op_state == A_HOST)) { ++ DWC_PRINTF("Init: Port Power? op_state=%d\n", core_if->op_state); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ DWC_PRINTF("Init: Power Port (%d)\n", hprt0.b.prtpwr); ++ if (hprt0.b.prtpwr == 0) { ++ hprt0.b.prtpwr = 1; ++ DWC_WRITE_REG32(host_if->hprt0, hprt0.d32); ++ } ++ } ++ ++ /* Initialize Host Configuration Register */ ++ init_fslspclksel(core_if); ++ if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) { ++ hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg); ++ hcfg.b.fslssupp = 1; ++ DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32); ++ ++ } ++ ++ /* This bit allows dynamic reloading of the HFIR register ++ * during runtime. This bit needs to be programmed during ++ * initial configuration and its value must not be changed ++ * during runtime.*/ ++ if (core_if->core_params->reload_ctl == 1) { ++ hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir); ++ hfir.b.hfirrldctrl = 1; ++ DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32); ++ } ++ ++ if (core_if->core_params->dma_desc_enable) { ++ uint8_t op_mode = core_if->hwcfg2.b.op_mode; ++ if (! ++ (core_if->hwcfg4.b.desc_dma ++ && (core_if->snpsid >= OTG_CORE_REV_2_90a) ++ && ((op_mode == DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ++ || (op_mode == DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) ++ || (op_mode == ++ DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG) ++ || (op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST) ++ || (op_mode == ++ DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST)))) { ++ ++ DWC_ERROR("Host can't operate in Descriptor DMA mode.\n" ++ "Either core version is below 2.90a or " ++ "GHWCFG2, GHWCFG4 registers' values do not allow Descriptor DMA in host mode.\n" ++ "To run the driver in Buffer DMA host mode set dma_desc_enable " ++ "module parameter to 0.\n"); ++ return; ++ } ++ hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg); ++ hcfg.b.descdma = 1; ++ DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32); ++ } ++ ++ /* Configure data FIFO sizes */ ++ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { ++ DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n", ++ core_if->total_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n", ++ params->host_rx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n", ++ params->host_nperio_tx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "P Tx FIFO Size=%d\n", ++ params->host_perio_tx_fifo_size); ++ ++ /* Rx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->grxfsiz)); ++ DWC_WRITE_REG32(&global_regs->grxfsiz, ++ params->host_rx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->grxfsiz)); ++ ++ /* Non-periodic Tx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); ++ nptxfifosize.b.depth = params->host_nperio_tx_fifo_size; ++ nptxfifosize.b.startaddr = params->host_rx_fifo_size; ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32); ++ DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); ++ ++ /* Periodic Tx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial hptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->hptxfsiz)); ++ ptxfifosize.b.depth = params->host_perio_tx_fifo_size; ++ ptxfifosize.b.startaddr = ++ nptxfifosize.b.startaddr + nptxfifosize.b.depth; ++ DWC_WRITE_REG32(&global_regs->hptxfsiz, ptxfifosize.d32); ++ DWC_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->hptxfsiz)); ++ ++ if (core_if->en_multiple_tx_fifo) { ++ /* Global DFIFOCFG calculation for Host mode - include RxFIFO, NPTXFIFO and HPTXFIFO */ ++ gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg); ++ rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff); ++ nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16); ++ hptxfsiz = (DWC_READ_REG32(&global_regs->hptxfsiz) >> 16); ++ gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz + hptxfsiz; ++ DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); ++ } ++ } ++ ++ /* TODO - check this */ ++ /* Clear Host Set HNP Enable in the OTG Control Register */ ++ gotgctl.b.hstsethnpen = 1; ++ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ /* Make sure the FIFOs are flushed. */ ++ dwc_otg_flush_tx_fifo(core_if, 0x10 /* all TX FIFOs */ ); ++ dwc_otg_flush_rx_fifo(core_if); ++ ++ /* Clear Host Set HNP Enable in the OTG Control Register */ ++ gotgctl.b.hstsethnpen = 1; ++ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ ++ if (!core_if->core_params->dma_desc_enable) { ++ /* Flush out any leftover queued requests. */ ++ num_channels = core_if->core_params->host_channels; ++ ++ for (i = 0; i < num_channels; i++) { ++ hc_regs = core_if->host_if->hc_regs[i]; ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.chen = 0; ++ hcchar.b.chdis = 1; ++ hcchar.b.epdir = 0; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ } ++ ++ /* Halt all channels to put them into a known state. */ ++ for (i = 0; i < num_channels; i++) { ++ int count = 0; ++ hc_regs = core_if->host_if->hc_regs[i]; ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 1; ++ hcchar.b.epdir = 0; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ DWC_DEBUGPL(DBG_HCDV, "%s: Halt channel %d\n", __func__, i); ++ do { ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (++count > 1000) { ++ DWC_ERROR ++ ("%s: Unable to clear halt on channel %d\n", ++ __func__, i); ++ break; ++ } ++ dwc_udelay(1); ++ } while (hcchar.b.chen); ++ } ++ } ++ ++ /* Turn on the vbus power. */ ++ if ((core_if->otg_ver == 0) && (core_if->op_state == A_HOST)) { ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ DWC_PRINTF("Init: Power Port (%d)\n", hprt0.b.prtpwr); ++ if (hprt0.b.prtpwr == 0) { ++ hprt0.b.prtpwr = 1; ++ DWC_WRITE_REG32(host_if->hprt0, hprt0.d32); ++ } ++ } ++ ++ dwc_otg_enable_host_interrupts(core_if); ++} ++ ++/** ++ * Prepares a host channel for transferring packets to/from a specific ++ * endpoint. The HCCHARn register is set up with the characteristics specified ++ * in _hc. Host channel interrupts that may need to be serviced while this ++ * transfer is in progress are enabled. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * @param hc Information needed to initialize the host channel ++ */ ++void dwc_otg_hc_init(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ uint32_t intr_enable; ++ hcintmsk_data_t hc_intr_mask; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ hcchar_data_t hcchar; ++ hcsplt_data_t hcsplt; ++ ++ uint8_t hc_num = hc->hc_num; ++ dwc_otg_host_if_t *host_if = core_if->host_if; ++ dwc_otg_hc_regs_t *hc_regs = host_if->hc_regs[hc_num]; ++ ++ /* Clear old interrupt conditions for this host channel. */ ++ hc_intr_mask.d32 = 0xFFFFFFFF; ++ hc_intr_mask.b.reserved14_31 = 0; ++ DWC_WRITE_REG32(&hc_regs->hcint, hc_intr_mask.d32); ++ ++ /* Enable channel interrupts required for this transfer. */ ++ hc_intr_mask.d32 = 0; ++ hc_intr_mask.b.chhltd = 1; ++ if (core_if->dma_enable) { ++ /* For Descriptor DMA mode core halts the channel on AHB error. Interrupt is not required */ ++ if (!core_if->dma_desc_enable) ++ hc_intr_mask.b.ahberr = 1; ++ else { ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) ++ hc_intr_mask.b.xfercompl = 1; ++ } ++ ++ if (hc->error_state && !hc->do_split && ++ hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { ++ hc_intr_mask.b.ack = 1; ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.datatglerr = 1; ++ if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) { ++ hc_intr_mask.b.nak = 1; ++ } ++ } ++ } ++ } else { ++ switch (hc->ep_type) { ++ case DWC_OTG_EP_TYPE_CONTROL: ++ case DWC_OTG_EP_TYPE_BULK: ++ hc_intr_mask.b.xfercompl = 1; ++ hc_intr_mask.b.stall = 1; ++ hc_intr_mask.b.xacterr = 1; ++ hc_intr_mask.b.datatglerr = 1; ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.bblerr = 1; ++ } else { ++ hc_intr_mask.b.nak = 1; ++ hc_intr_mask.b.nyet = 1; ++ if (hc->do_ping) { ++ hc_intr_mask.b.ack = 1; ++ } ++ } ++ ++ if (hc->do_split) { ++ hc_intr_mask.b.nak = 1; ++ if (hc->complete_split) { ++ hc_intr_mask.b.nyet = 1; ++ } else { ++ hc_intr_mask.b.ack = 1; ++ } ++ } ++ ++ if (hc->error_state) { ++ hc_intr_mask.b.ack = 1; ++ } ++ break; ++ case DWC_OTG_EP_TYPE_INTR: ++ hc_intr_mask.b.xfercompl = 1; ++ hc_intr_mask.b.nak = 1; ++ hc_intr_mask.b.stall = 1; ++ hc_intr_mask.b.xacterr = 1; ++ hc_intr_mask.b.datatglerr = 1; ++ hc_intr_mask.b.frmovrun = 1; ++ ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.bblerr = 1; ++ } ++ if (hc->error_state) { ++ hc_intr_mask.b.ack = 1; ++ } ++ if (hc->do_split) { ++ if (hc->complete_split) { ++ hc_intr_mask.b.nyet = 1; ++ } else { ++ hc_intr_mask.b.ack = 1; ++ } ++ } ++ break; ++ case DWC_OTG_EP_TYPE_ISOC: ++ hc_intr_mask.b.xfercompl = 1; ++ hc_intr_mask.b.frmovrun = 1; ++ hc_intr_mask.b.ack = 1; ++ ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.xacterr = 1; ++ hc_intr_mask.b.bblerr = 1; ++ } ++ break; ++ } ++ } ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, hc_intr_mask.d32); ++ ++ /* Enable the top level host channel interrupt. */ ++ intr_enable = (1 << hc_num); ++ DWC_MODIFY_REG32(&host_if->host_global_regs->haintmsk, 0, intr_enable); ++ ++ /* Make sure host channel interrupts are enabled. */ ++ gintmsk.b.hcintr = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32); ++ ++ /* ++ * Program the HCCHARn register with the endpoint characteristics for ++ * the current transfer. ++ */ ++ hcchar.d32 = 0; ++ hcchar.b.devaddr = hc->dev_addr; ++ hcchar.b.epnum = hc->ep_num; ++ hcchar.b.epdir = hc->ep_is_in; ++ hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW); ++ hcchar.b.eptype = hc->ep_type; ++ hcchar.b.mps = hc->max_packet; ++ ++ DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32); ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " Dev Addr: %d\n", hcchar.b.devaddr); ++ DWC_DEBUGPL(DBG_HCDV, " Ep Num: %d\n", hcchar.b.epnum); ++ DWC_DEBUGPL(DBG_HCDV, " Is In: %d\n", hcchar.b.epdir); ++ DWC_DEBUGPL(DBG_HCDV, " Is Low Speed: %d\n", hcchar.b.lspddev); ++ DWC_DEBUGPL(DBG_HCDV, " Ep Type: %d\n", hcchar.b.eptype); ++ DWC_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n", hcchar.b.mps); ++ DWC_DEBUGPL(DBG_HCDV, " Multi Cnt: %d\n", hcchar.b.multicnt); ++ ++ /* ++ * Program the HCSPLIT register for SPLITs ++ */ ++ hcsplt.d32 = 0; ++ if (hc->do_split) { ++ DWC_DEBUGPL(DBG_HCDV, "Programming HC %d with split --> %s\n", ++ hc->hc_num, ++ hc->complete_split ? "CSPLIT" : "SSPLIT"); ++ hcsplt.b.compsplt = hc->complete_split; ++ hcsplt.b.xactpos = hc->xact_pos; ++ hcsplt.b.hubaddr = hc->hub_addr; ++ hcsplt.b.prtaddr = hc->port_addr; ++ DWC_DEBUGPL(DBG_HCDV, " comp split %d\n", hc->complete_split); ++ DWC_DEBUGPL(DBG_HCDV, " xact pos %d\n", hc->xact_pos); ++ DWC_DEBUGPL(DBG_HCDV, " hub addr %d\n", hc->hub_addr); ++ DWC_DEBUGPL(DBG_HCDV, " port addr %d\n", hc->port_addr); ++ DWC_DEBUGPL(DBG_HCDV, " is_in %d\n", hc->ep_is_in); ++ DWC_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n", hcchar.b.mps); ++ DWC_DEBUGPL(DBG_HCDV, " xferlen: %d\n", hc->xfer_len); ++ } ++ DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32); ++ ++} ++ ++/** ++ * Attempts to halt a host channel. This function should only be called in ++ * Slave mode or to abort a transfer in either Slave mode or DMA mode. Under ++ * normal circumstances in DMA mode, the controller halts the channel when the ++ * transfer is complete or a condition occurs that requires application ++ * intervention. ++ * ++ * In slave mode, checks for a free request queue entry, then sets the Channel ++ * Enable and Channel Disable bits of the Host Channel Characteristics ++ * register of the specified channel to intiate the halt. If there is no free ++ * request queue entry, sets only the Channel Disable bit of the HCCHARn ++ * register to flush requests for this channel. In the latter case, sets a ++ * flag to indicate that the host channel needs to be halted when a request ++ * queue slot is open. ++ * ++ * In DMA mode, always sets the Channel Enable and Channel Disable bits of the ++ * HCCHARn register. The controller ensures there is space in the request ++ * queue before submitting the halt request. ++ * ++ * Some time may elapse before the core flushes any posted requests for this ++ * host channel and halts. The Channel Halted interrupt handler completes the ++ * deactivation of the host channel. ++ * ++ * @param core_if Controller register interface. ++ * @param hc Host channel to halt. ++ * @param halt_status Reason for halting the channel. ++ */ ++void dwc_otg_hc_halt(dwc_otg_core_if_t * core_if, ++ dwc_hc_t * hc, dwc_otg_halt_status_e halt_status) ++{ ++ gnptxsts_data_t nptxsts; ++ hptxsts_data_t hptxsts; ++ hcchar_data_t hcchar; ++ dwc_otg_hc_regs_t *hc_regs; ++ dwc_otg_core_global_regs_t *global_regs; ++ dwc_otg_host_global_regs_t *host_global_regs; ++ ++ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ global_regs = core_if->core_global_regs; ++ host_global_regs = core_if->host_if->host_global_regs; ++ ++ DWC_ASSERT(!(halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS), ++ "halt_status = %d\n", halt_status); ++ ++ if (halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE || ++ halt_status == DWC_OTG_HC_XFER_AHB_ERR) { ++ /* ++ * Disable all channel interrupts except Ch Halted. The QTD ++ * and QH state associated with this transfer has been cleared ++ * (in the case of URB_DEQUEUE), so the channel needs to be ++ * shut down carefully to prevent crashes. ++ */ ++ hcintmsk_data_t hcintmsk; ++ hcintmsk.d32 = 0; ++ hcintmsk.b.chhltd = 1; ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, hcintmsk.d32); ++ ++ /* ++ * Make sure no other interrupts besides halt are currently ++ * pending. Handling another interrupt could cause a crash due ++ * to the QTD and QH state. ++ */ ++ DWC_WRITE_REG32(&hc_regs->hcint, ~hcintmsk.d32); ++ ++ /* ++ * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR ++ * even if the channel was already halted for some other ++ * reason. ++ */ ++ hc->halt_status = halt_status; ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen == 0) { ++ /* ++ * The channel is either already halted or it hasn't ++ * started yet. In DMA mode, the transfer may halt if ++ * it finishes normally or a condition occurs that ++ * requires driver intervention. Don't want to halt ++ * the channel again. In either Slave or DMA mode, ++ * it's possible that the transfer has been assigned ++ * to a channel, but not started yet when an URB is ++ * dequeued. Don't want to halt a channel that hasn't ++ * started yet. ++ */ ++ return; ++ } ++ } ++ if (hc->halt_pending) { ++ /* ++ * A halt has already been issued for this channel. This might ++ * happen when a transfer is aborted by a higher level in ++ * the stack. ++ */ ++#ifdef DEBUG ++ DWC_PRINTF ++ ("*** %s: Channel %d, _hc->halt_pending already set ***\n", ++ __func__, hc->hc_num); ++ ++#endif ++ return; ++ } ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* No need to set the bit in DDMA for disabling the channel */ ++ //TODO check it everywhere channel is disabled ++ if (!core_if->core_params->dma_desc_enable) ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 1; ++ ++ if (!core_if->dma_enable) { ++ /* Check for space in the request queue to issue the halt. */ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || ++ hc->ep_type == DWC_OTG_EP_TYPE_BULK) { ++ nptxsts.d32 = DWC_READ_REG32(&global_regs->gnptxsts); ++ if (nptxsts.b.nptxqspcavail == 0) { ++ hcchar.b.chen = 0; ++ } ++ } else { ++ hptxsts.d32 = ++ DWC_READ_REG32(&host_global_regs->hptxsts); ++ if ((hptxsts.b.ptxqspcavail == 0) ++ || (core_if->queuing_high_bandwidth)) { ++ hcchar.b.chen = 0; ++ } ++ } ++ } ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ hc->halt_status = halt_status; ++ ++ if (hcchar.b.chen) { ++ hc->halt_pending = 1; ++ hc->halt_on_queue = 0; ++ } else { ++ hc->halt_on_queue = 1; ++ } ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " hcchar: 0x%08x\n", hcchar.d32); ++ DWC_DEBUGPL(DBG_HCDV, " halt_pending: %d\n", hc->halt_pending); ++ DWC_DEBUGPL(DBG_HCDV, " halt_on_queue: %d\n", hc->halt_on_queue); ++ DWC_DEBUGPL(DBG_HCDV, " halt_status: %d\n", hc->halt_status); ++ ++ return; ++} ++ ++/** ++ * Clears the transfer state for a host channel. This function is normally ++ * called after a transfer is done and the host channel is being released. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param hc Identifies the host channel to clean up. ++ */ ++void dwc_otg_hc_cleanup(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ dwc_otg_hc_regs_t *hc_regs; ++ ++ hc->xfer_started = 0; ++ ++ /* ++ * Clear channel interrupt enables and any unhandled channel interrupt ++ * conditions. ++ */ ++ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0); ++ DWC_WRITE_REG32(&hc_regs->hcint, 0xFFFFFFFF); ++#ifdef DEBUG ++ DWC_TIMER_CANCEL(core_if->hc_xfer_timer[hc->hc_num]); ++#endif ++} ++ ++/** ++ * Sets the channel property that indicates in which frame a periodic transfer ++ * should occur. This is always set to the _next_ frame. This function has no ++ * effect on non-periodic transfers. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param hc Identifies the host channel to set up and its properties. ++ * @param hcchar Current value of the HCCHAR register for the specified host ++ * channel. ++ */ ++static inline void hc_set_even_odd_frame(dwc_otg_core_if_t * core_if, ++ dwc_hc_t * hc, hcchar_data_t * hcchar) ++{ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ hfnum_data_t hfnum; ++ hfnum.d32 = ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->hfnum); ++ ++ /* 1 if _next_ frame is odd, 0 if it's even */ ++ hcchar->b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1; ++#ifdef DEBUG ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR && hc->do_split ++ && !hc->complete_split) { ++ switch (hfnum.b.frnum & 0x7) { ++ case 7: ++ core_if->hfnum_7_samples++; ++ core_if->hfnum_7_frrem_accum += hfnum.b.frrem; ++ break; ++ case 0: ++ core_if->hfnum_0_samples++; ++ core_if->hfnum_0_frrem_accum += hfnum.b.frrem; ++ break; ++ default: ++ core_if->hfnum_other_samples++; ++ core_if->hfnum_other_frrem_accum += ++ hfnum.b.frrem; ++ break; ++ } ++ } ++#endif ++ } ++} ++ ++#ifdef DEBUG ++void hc_xfer_timeout(void *ptr) ++{ ++ hc_xfer_info_t *xfer_info = NULL; ++ int hc_num = 0; ++ ++ if (ptr) ++ xfer_info = (hc_xfer_info_t *) ptr; ++ ++ if (!xfer_info) ++ return; ++ ++ if (!xfer_info->hc) { ++ DWC_ERROR("xfer_info->hc = %p\n", xfer_info->hc); ++ return; ++ } ++ ++ hc_num = xfer_info->hc->hc_num; ++ DWC_WARN("%s: timeout on channel %d\n", __func__, hc_num); ++ DWC_WARN(" start_hcchar_val 0x%08x\n", ++ xfer_info->core_if->start_hcchar_val[hc_num]); ++} ++#endif ++ ++void ep_xfer_timeout(void *ptr) ++{ ++ ep_xfer_info_t *xfer_info = NULL; ++ int ep_num = 0; ++ dctl_data_t dctl = {.d32 = 0 }; ++ gintsts_data_t gintsts = {.d32 = 0 }; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ if (ptr) ++ xfer_info = (ep_xfer_info_t *) ptr; ++ ++ if (!xfer_info->ep) { ++ DWC_ERROR("xfer_info->ep = %p\n", xfer_info->ep); ++ return; ++ } ++ ++ ep_num = xfer_info->ep->num; ++ DWC_WARN("%s: timeout on endpoit %d\n", __func__, ep_num); ++ /* Put the sate to 2 as it was time outed */ ++ xfer_info->state = 2; ++ ++ dctl.d32 = ++ DWC_READ_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl); ++ gintsts.d32 = ++ DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintsts); ++ gintmsk.d32 = ++ DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintmsk); ++ ++ if (!gintmsk.b.goutnakeff) { ++ /* Unmask it */ ++ gintmsk.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&xfer_info->core_if->core_global_regs->gintmsk, ++ gintmsk.d32); ++ ++ } ++ ++ if (!gintsts.b.goutnakeff) { ++ dctl.b.sgoutnak = 1; ++ } ++ DWC_WRITE_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ ++} ++ ++void set_pid_isoc(dwc_hc_t * hc) ++{ ++ /* Set up the initial PID for the transfer. */ ++ if (hc->speed == DWC_OTG_EP_SPEED_HIGH) { ++ if (hc->ep_is_in) { ++ if (hc->multi_count == 1) { ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA0; ++ } else if (hc->multi_count == 2) { ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA1; ++ } else { ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA2; ++ } ++ } else { ++ if (hc->multi_count == 1) { ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA0; ++ } else { ++ hc->data_pid_start = DWC_OTG_HC_PID_MDATA; ++ } ++ } ++ } else { ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA0; ++ } ++} ++ ++/** ++ * This function does the setup for a data transfer for a host channel and ++ * starts the transfer. May be called in either Slave mode or DMA mode. In ++ * Slave mode, the caller must ensure that there is sufficient space in the ++ * request queue and Tx Data FIFO. ++ * ++ * For an OUT transfer in Slave mode, it loads a data packet into the ++ * appropriate FIFO. If necessary, additional data packets will be loaded in ++ * the Host ISR. ++ * ++ * For an IN transfer in Slave mode, a data packet is requested. The data ++ * packets are unloaded from the Rx FIFO in the Host ISR. If necessary, ++ * additional data packets are requested in the Host ISR. ++ * ++ * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ ++ * register along with a packet count of 1 and the channel is enabled. This ++ * causes a single PING transaction to occur. Other fields in HCTSIZ are ++ * simply set to 0 since no data transfer occurs in this case. ++ * ++ * For a PING transfer in DMA mode, the HCTSIZ register is initialized with ++ * all the information required to perform the subsequent data transfer. In ++ * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the ++ * controller performs the entire PING protocol, then starts the data ++ * transfer. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param hc Information needed to initialize the host channel. The xfer_len ++ * value may be reduced to accommodate the max widths of the XferSize and ++ * PktCnt fields in the HCTSIZn register. The multi_count value may be changed ++ * to reflect the final xfer_len value. ++ */ ++void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ uint16_t num_packets; ++ uint32_t max_hc_xfer_size = core_if->core_params->max_transfer_size; ++ uint16_t max_hc_pkt_count = core_if->core_params->max_packet_count; ++ dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ ++ hctsiz.d32 = 0; ++ ++ if (hc->do_ping) { ++ if (!core_if->dma_enable) { ++ dwc_otg_hc_do_ping(core_if, hc); ++ hc->xfer_started = 1; ++ return; ++ } else { ++ hctsiz.b.dopng = 1; ++ } ++ } ++ ++ if (hc->do_split) { ++ num_packets = 1; ++ ++ if (hc->complete_split && !hc->ep_is_in) { ++ /* For CSPLIT OUT Transfer, set the size to 0 so the ++ * core doesn't expect any data written to the FIFO */ ++ hc->xfer_len = 0; ++ } else if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) { ++ hc->xfer_len = hc->max_packet; ++ } else if (!hc->ep_is_in && (hc->xfer_len > 188)) { ++ hc->xfer_len = 188; ++ } ++ ++ hctsiz.b.xfersize = hc->xfer_len; ++ } else { ++ /* ++ * Ensure that the transfer length and packet count will fit ++ * in the widths allocated for them in the HCTSIZn register. ++ */ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * Make sure the transfer size is no larger than one ++ * (micro)frame's worth of data. (A check was done ++ * when the periodic transfer was accepted to ensure ++ * that a (micro)frame's worth of data can be ++ * programmed into a channel.) ++ */ ++ uint32_t max_periodic_len = ++ hc->multi_count * hc->max_packet; ++ if (hc->xfer_len > max_periodic_len) { ++ hc->xfer_len = max_periodic_len; ++ } else { ++ } ++ } else if (hc->xfer_len > max_hc_xfer_size) { ++ /* Make sure that xfer_len is a multiple of max packet size. */ ++ hc->xfer_len = max_hc_xfer_size - hc->max_packet + 1; ++ } ++ ++ if (hc->xfer_len > 0) { ++ num_packets = ++ (hc->xfer_len + hc->max_packet - ++ 1) / hc->max_packet; ++ if (num_packets > max_hc_pkt_count) { ++ num_packets = max_hc_pkt_count; ++ hc->xfer_len = num_packets * hc->max_packet; ++ } ++ } else { ++ /* Need 1 packet for transfer length of 0. */ ++ num_packets = 1; ++ } ++ ++ if (hc->ep_is_in) { ++ /* Always program an integral # of max packets for IN transfers. */ ++ hc->xfer_len = num_packets * hc->max_packet; ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * Make sure that the multi_count field matches the ++ * actual transfer length. ++ */ ++ hc->multi_count = num_packets; ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) ++ set_pid_isoc(hc); ++ ++ hctsiz.b.xfersize = hc->xfer_len; ++ } ++ ++ hc->start_pkt_count = num_packets; ++ hctsiz.b.pktcnt = num_packets; ++ hctsiz.b.pid = hc->data_pid_start; ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " Xfer Size: %d\n", hctsiz.b.xfersize); ++ DWC_DEBUGPL(DBG_HCDV, " Num Pkts: %d\n", hctsiz.b.pktcnt); ++ DWC_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid); ++ ++ if (core_if->dma_enable) { ++ dwc_dma_t dma_addr; ++ if (hc->align_buff) { ++ dma_addr = hc->align_buff; ++ } else { ++ dma_addr = ((unsigned long)hc->xfer_buff & 0xffffffff); ++ } ++ DWC_WRITE_REG32(&hc_regs->hcdma, dma_addr); ++ } ++ ++ /* Start the split */ ++ if (hc->do_split) { ++ hcsplt_data_t hcsplt; ++ hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt); ++ hcsplt.b.spltena = 1; ++ DWC_WRITE_REG32(&hc_regs->hcsplt, hcsplt.d32); ++ } ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.multicnt = hc->multi_count; ++ hc_set_even_odd_frame(core_if, hc, &hcchar); ++#ifdef DEBUG ++ core_if->start_hcchar_val[hc->hc_num] = hcchar.d32; ++ if (hcchar.b.chdis) { ++ DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n", ++ __func__, hc->hc_num, hcchar.d32); ++ } ++#endif ++ ++ /* Set host channel enable after all other setup is complete. */ ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 0; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ hc->xfer_started = 1; ++ hc->requests++; ++ ++ if (!core_if->dma_enable && !hc->ep_is_in && hc->xfer_len > 0) { ++ /* Load OUT packet into the appropriate Tx FIFO. */ ++ dwc_otg_hc_write_packet(core_if, hc); ++ } ++#ifdef DEBUG ++ if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) { ++ core_if->hc_xfer_info[hc->hc_num].core_if = core_if; ++ core_if->hc_xfer_info[hc->hc_num].hc = hc; ++ ++ /* Start a timer for this transfer. */ ++ DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000); ++ } ++#endif ++} ++ ++/** ++ * This function does the setup for a data transfer for a host channel ++ * and starts the transfer in Descriptor DMA mode. ++ * ++ * Initializes HCTSIZ register. For a PING transfer the Do Ping bit is set. ++ * Sets PID and NTD values. For periodic transfers ++ * initializes SCHED_INFO field with micro-frame bitmap. ++ * ++ * Initializes HCDMA register with descriptor list address and CTD value ++ * then starts the transfer via enabling the channel. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param hc Information needed to initialize the host channel. ++ */ ++void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ hcdma_data_t hcdma; ++ ++ hctsiz.d32 = 0; ++ ++ if (hc->do_ping) ++ hctsiz.b_ddma.dopng = 1; ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) ++ set_pid_isoc(hc); ++ ++ /* Packet Count and Xfer Size are not used in Descriptor DMA mode */ ++ hctsiz.b_ddma.pid = hc->data_pid_start; ++ hctsiz.b_ddma.ntd = hc->ntd - 1; /* 0 - 1 descriptor, 1 - 2 descriptors, etc. */ ++ hctsiz.b_ddma.schinfo = hc->schinfo; /* Non-zero only for high-speed interrupt endpoints */ ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid); ++ DWC_DEBUGPL(DBG_HCDV, " NTD: %d\n", hctsiz.b_ddma.ntd); ++ ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ hcdma.d32 = 0; ++ hcdma.b.dma_addr = ((uint32_t) hc->desc_list_addr) >> 11; ++ ++ /* Always start from first descriptor. */ ++ hcdma.b.ctd = 0; ++ DWC_WRITE_REG32(&hc_regs->hcdma, hcdma.d32); ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.multicnt = hc->multi_count; ++ ++#ifdef DEBUG ++ core_if->start_hcchar_val[hc->hc_num] = hcchar.d32; ++ if (hcchar.b.chdis) { ++ DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n", ++ __func__, hc->hc_num, hcchar.d32); ++ } ++#endif ++ ++ /* Set host channel enable after all other setup is complete. */ ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 0; ++ ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ hc->xfer_started = 1; ++ hc->requests++; ++ ++#ifdef DEBUG ++ if ((hc->ep_type != DWC_OTG_EP_TYPE_INTR) ++ && (hc->ep_type != DWC_OTG_EP_TYPE_ISOC)) { ++ core_if->hc_xfer_info[hc->hc_num].core_if = core_if; ++ core_if->hc_xfer_info[hc->hc_num].hc = hc; ++ /* Start a timer for this transfer. */ ++ DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000); ++ } ++#endif ++ ++} ++ ++/** ++ * This function continues a data transfer that was started by previous call ++ * to dwc_otg_hc_start_transfer. The caller must ensure there is ++ * sufficient space in the request queue and Tx Data FIFO. This function ++ * should only be called in Slave mode. In DMA mode, the controller acts ++ * autonomously to complete transfers programmed to a host channel. ++ * ++ * For an OUT transfer, a new data packet is loaded into the appropriate FIFO ++ * if there is any data remaining to be queued. For an IN transfer, another ++ * data packet is always requested. For the SETUP phase of a control transfer, ++ * this function does nothing. ++ * ++ * @return 1 if a new request is queued, 0 if no more requests are required ++ * for this transfer. ++ */ ++int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ ++ if (hc->do_split) { ++ /* SPLITs always queue just once per channel */ ++ return 0; ++ } else if (hc->data_pid_start == DWC_OTG_HC_PID_SETUP) { ++ /* SETUPs are queued only once since they can't be NAKed. */ ++ return 0; ++ } else if (hc->ep_is_in) { ++ /* ++ * Always queue another request for other IN transfers. If ++ * back-to-back INs are issued and NAKs are received for both, ++ * the driver may still be processing the first NAK when the ++ * second NAK is received. When the interrupt handler clears ++ * the NAK interrupt for the first NAK, the second NAK will ++ * not be seen. So we can't depend on the NAK interrupt ++ * handler to requeue a NAKed request. Instead, IN requests ++ * are issued each time this function is called. When the ++ * transfer completes, the extra requests for the channel will ++ * be flushed. ++ */ ++ hcchar_data_t hcchar; ++ dwc_otg_hc_regs_t *hc_regs = ++ core_if->host_if->hc_regs[hc->hc_num]; ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hc_set_even_odd_frame(core_if, hc, &hcchar); ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 0; ++ DWC_DEBUGPL(DBG_HCDV, " IN xfer: hcchar = 0x%08x\n", ++ hcchar.d32); ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ hc->requests++; ++ return 1; ++ } else { ++ /* OUT transfers. */ ++ if (hc->xfer_count < hc->xfer_len) { ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ hcchar_data_t hcchar; ++ dwc_otg_hc_regs_t *hc_regs; ++ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hc_set_even_odd_frame(core_if, hc, &hcchar); ++ } ++ ++ /* Load OUT packet into the appropriate Tx FIFO. */ ++ dwc_otg_hc_write_packet(core_if, hc); ++ hc->requests++; ++ return 1; ++ } else { ++ return 0; ++ } ++ } ++} ++ ++/** ++ * Starts a PING transfer. This function should only be called in Slave mode. ++ * The Do Ping bit is set in the HCTSIZ register, then the channel is enabled. ++ */ ++void dwc_otg_hc_do_ping(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ ++ hctsiz.d32 = 0; ++ hctsiz.b.dopng = 1; ++ hctsiz.b.pktcnt = 1; ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 0; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++} ++ ++/* ++ * This function writes a packet into the Tx FIFO associated with the Host ++ * Channel. For a channel associated with a non-periodic EP, the non-periodic ++ * Tx FIFO is written. For a channel associated with a periodic EP, the ++ * periodic Tx FIFO is written. This function should only be called in Slave ++ * mode. ++ * ++ * Upon return the xfer_buff and xfer_count fields in _hc are incremented by ++ * then number of bytes written to the Tx FIFO. ++ */ ++void dwc_otg_hc_write_packet(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ uint32_t i; ++ uint32_t remaining_count; ++ uint32_t byte_count; ++ uint32_t dword_count; ++ ++ uint32_t *data_buff = (uint32_t *) (hc->xfer_buff); ++ uint32_t *data_fifo = core_if->data_fifo[hc->hc_num]; ++ ++ remaining_count = hc->xfer_len - hc->xfer_count; ++ if (remaining_count > hc->max_packet) { ++ byte_count = hc->max_packet; ++ } else { ++ byte_count = remaining_count; ++ } ++ ++ dword_count = (byte_count + 3) / 4; ++ ++ if ((((unsigned long)data_buff) & 0x3) == 0) { ++ /* xfer_buff is DWORD aligned. */ ++ for (i = 0; i < dword_count; i++, data_buff++) { ++ DWC_WRITE_REG32(data_fifo, *data_buff); ++ } ++ } else { ++ /* xfer_buff is not DWORD aligned. */ ++ for (i = 0; i < dword_count; i++, data_buff++) { ++ uint32_t data; ++ data = ++ (data_buff[0] | data_buff[1] << 8 | data_buff[2] << ++ 16 | data_buff[3] << 24); ++ DWC_WRITE_REG32(data_fifo, data); ++ } ++ } ++ ++ hc->xfer_count += byte_count; ++ hc->xfer_buff += byte_count; ++} ++ ++/** ++ * Gets the current USB frame number. This is the frame number from the last ++ * SOF packet. ++ */ ++uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * core_if) ++{ ++ dsts_data_t dsts; ++ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ /* read current frame/microframe number from DSTS register */ ++ return dsts.b.soffn; ++} ++ ++/** ++ * Calculates and gets the frame Interval value of HFIR register according PHY ++ * type and speed.The application can modify a value of HFIR register only after ++ * the Port Enable bit of the Host Port Control and Status register ++ * (HPRT.PrtEnaPort) has been set. ++*/ ++ ++uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if) ++{ ++ gusbcfg_data_t usbcfg; ++ hwcfg2_data_t hwcfg2; ++ hprt0_data_t hprt0; ++ int clock = 60; // default value ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ hwcfg2.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2); ++ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); ++ if (!usbcfg.b.physel && usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif) ++ clock = 60; ++ if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 3) ++ clock = 48; ++ if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel && ++ !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif) ++ clock = 30; ++ if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel && ++ !usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif) ++ clock = 60; ++ if (usbcfg.b.phylpwrclksel && !usbcfg.b.physel && ++ !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif) ++ clock = 48; ++ if (usbcfg.b.physel && !usbcfg.b.phyif && hwcfg2.b.fs_phy_type == 2) ++ clock = 48; ++ if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 1) ++ clock = 48; ++ if (hprt0.b.prtspd == 0) ++ /* High speed case */ ++ return 125 * clock; ++ else ++ /* FS/LS case */ ++ return 1000 * clock; ++} ++ ++/** ++ * This function reads a setup packet from the Rx FIFO into the destination ++ * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl) ++ * Interrupt routine when a SETUP packet has been received in Slave mode. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param dest Destination buffer for packet data. ++ */ ++void dwc_otg_read_setup_packet(dwc_otg_core_if_t * core_if, uint32_t * dest) ++{ ++ device_grxsts_data_t status; ++ /* Get the 8 bytes of a setup transaction data */ ++ ++ /* Pop 2 DWORDS off the receive data FIFO into memory */ ++ dest[0] = DWC_READ_REG32(core_if->data_fifo[0]); ++ dest[1] = DWC_READ_REG32(core_if->data_fifo[0]); ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ status.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->grxstsp); ++ DWC_DEBUGPL(DBG_ANY, ++ "EP:%d BCnt:%d " "pktsts:%x Frame:%d(0x%0x)\n", ++ status.b.epnum, status.b.bcnt, status.b.pktsts, ++ status.b.fn, status.b.fn); ++ } ++} ++ ++/** ++ * This function enables EP0 OUT to receive SETUP packets and configures EP0 ++ * IN for transmitting packets. It is normally called when the ++ * "Enumeration Done" interrupt occurs. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP0 data. ++ */ ++void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dsts_data_t dsts; ++ depctl_data_t diepctl, depctl_tmp; ++ depctl_data_t doepctl; ++ dctl_data_t dctl = {.d32 = 0 }; ++ uint8_t i; ++ ++ ep->stp_rollover = 0; ++ /* Read the Device Status and Endpoint 0 Control registers */ ++ dsts.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dsts); ++ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); ++ doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl); ++ ++ /* Set the MPS of the IN EP based on the enumeration speed */ ++ switch (dsts.b.enumspd) { ++ case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: ++ case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: ++ case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ: ++ diepctl.b.mps = DWC_DEP0CTL_MPS_64; ++ break; ++ case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ: ++ diepctl.b.mps = DWC_DEP0CTL_MPS_8; ++ break; ++ } ++ ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); ++ ++ /* Enable OUT EP for receive */ ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) { ++ doepctl.b.epena = 1; ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); ++ } ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n", ++ DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl)); ++ DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n", ++ DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl)); ++#endif ++ dctl.b.cgnpinnak = 1; ++ ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ DWC_DEBUGPL(DBG_PCDV, "dctl=%0x\n", ++ DWC_READ_REG32(&dev_if->dev_global_regs->dctl)); ++ ++ for (i = 1; i <= core_if->dev_if->num_in_eps; i++) { ++ depctl_tmp.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (depctl_tmp.b.epena) { ++ depctl_tmp.d32 = 0; ++ depctl_tmp.b.epdis = 1; ++ depctl_tmp.b.snak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]-> ++ diepctl, depctl_tmp.d32); ++ } ++ } ++} ++ ++/** ++ * This function activates an EP. The Device EP control register for ++ * the EP is configured as defined in the ep structure. Note: This ++ * function is not used for EP0. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to activate. ++ */ ++void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ depctl_data_t depctl; ++ volatile uint32_t *addr; ++ daint_data_t daintmsk = {.d32 = 0 }; ++ dcfg_data_t dcfg; ++ uint8_t i; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s() EP%d-%s\n", __func__, ep->num, ++ (ep->is_in ? "IN" : "OUT")); ++ ++#ifdef DWC_UTE_PER_IO ++ ep->xiso_frame_num = 0xFFFFFFFF; ++ ep->xiso_active_xfers = 0; ++ ep->xiso_queued_xfers = 0; ++#endif ++ /* Read DEPCTLn register */ ++ if (ep->is_in == 1) { ++ addr = &dev_if->in_ep_regs[ep->num]->diepctl; ++ daintmsk.ep.in = 1 << ep->num; ++ } else { ++ addr = &dev_if->out_ep_regs[ep->num]->doepctl; ++ daintmsk.ep.out = 1 << ep->num; ++ } ++ ++ /* If the EP is already active don't change the EP Control ++ * register. */ ++ depctl.d32 = DWC_READ_REG32(addr); ++ if (!depctl.b.usbactep) { ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (((ep->num == 4) || (ep->num == 6)) && (ep->maxpacket < 256)) { ++ depctl_data_t depctl_tmp; ++ volatile uint32_t *addr_tmp; ++ ep->maxpacket = 256; ++ addr_tmp = &dev_if->in_ep_regs[3]->diepctl; ++ depctl_tmp.d32 = DWC_READ_REG32(addr_tmp); ++ if (depctl_tmp.b.eptype == 0x2) { ++ dctl_data_t dctl; ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ dctl.b.ifrmnum = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++ } ++ } ++ } ++ depctl.b.mps = ep->maxpacket; ++ depctl.b.eptype = ep->type; ++ ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (ep->num == 3) ++ ep->tx_fifo_num = 0x2; ++ if (ep->num == 4) ++ ep->tx_fifo_num = 0x3; ++ } ++ depctl.b.txfnum = ep->tx_fifo_num; ++ ++ /* ++ there are some rootcase have to be confirm with SNPS ++ whether ISOC-xfer need depctl.b.setd0pid = 1. ++ as current version ,we have to keep the follow opteration. ++ so, just remove if else, keep depctl.b.setd0pid = 1; ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ depctl.b.setd0pid = 1; // ??? ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ depctl.b.usbactep = 1; ++ */ ++ depctl.b.usbactep = 1; ++ ++ /* Update nextep_seq array and EPMSCNT in DCFG */ ++ if (!(depctl.b.eptype & 1) && (ep->is_in == 1)) { // NP IN EP ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ if (core_if->nextep_seq[i] == core_if->first_in_nextep_seq) ++ break; ++ } ++ core_if->nextep_seq[i] = ep->num; ++ core_if->nextep_seq[ep->num] = core_if->first_in_nextep_seq; ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt++; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_PCDV, "%2d\n", ++ core_if->nextep_seq[i]); ++ } ++ ++ } ++ ++ ++ DWC_WRITE_REG32(addr, depctl.d32); ++ DWC_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", DWC_READ_REG32(addr)); ++ } ++ ++ /* Enable the Interrupt for this EP */ ++ if (core_if->multiproc_int_enable) { ++ if (ep->is_in == 1) { ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ diepmsk.b.xfercompl = 1; ++ diepmsk.b.timeout = 1; ++ diepmsk.b.epdisabled = 1; ++ diepmsk.b.ahberr = 1; ++ diepmsk.b.intknepmis = 1; ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) ++ diepmsk.b.intknepmis = 0; ++ diepmsk.b.txfifoundrn = 1; //????? ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ diepmsk.b.nak = 1; ++ } ++ ++/* ++ if (core_if->dma_desc_enable) { ++ diepmsk.b.bna = 1; ++ } ++*/ ++/* ++ if (core_if->dma_enable) { ++ doepmsk.b.nak = 1; ++ } ++*/ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs-> ++ diepeachintmsk[ep->num], diepmsk.d32); ++ ++ } else { ++ doepmsk_data_t doepmsk = {.d32 = 0 }; ++ doepmsk.b.xfercompl = 1; ++ doepmsk.b.ahberr = 1; ++ doepmsk.b.epdisabled = 1; ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) ++ doepmsk.b.outtknepdis = 1; ++ ++/* ++ ++ if (core_if->dma_desc_enable) { ++ doepmsk.b.bna = 1; ++ } ++*/ ++/* ++ doepmsk.b.babble = 1; ++ doepmsk.b.nyet = 1; ++ doepmsk.b.nak = 1; ++*/ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs-> ++ doepeachintmsk[ep->num], doepmsk.d32); ++ } ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->deachintmsk, ++ 0, daintmsk.d32); ++ } else { ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (ep->is_in) { ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ diepmsk.b.nak = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32); ++ } else { ++ doepmsk_data_t doepmsk = {.d32 = 0 }; ++ doepmsk.b.outtknepdis = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->doepmsk, 0, doepmsk.d32); ++ } ++ } ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->daintmsk, ++ 0, daintmsk.d32); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "DAINTMSK=%0x\n", ++ DWC_READ_REG32(&dev_if->dev_global_regs->daintmsk)); ++ ++ ep->stall_clear_flag = 0; ++ ++ return; ++} ++ ++/** ++ * This function deactivates an EP. This is done by clearing the USB Active ++ * EP bit in the Device EP control register. Note: This function is not used ++ * for EP0. EP0 cannot be deactivated. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to deactivate. ++ */ ++void dwc_otg_ep_deactivate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ daint_data_t daintmsk = {.d32 = 0 }; ++ dcfg_data_t dcfg; ++ uint8_t i = 0; ++ ++#ifdef DWC_UTE_PER_IO ++ ep->xiso_frame_num = 0xFFFFFFFF; ++ ep->xiso_active_xfers = 0; ++ ep->xiso_queued_xfers = 0; ++#endif ++ ++ /* Read DEPCTLn register */ ++ if (ep->is_in == 1) { ++ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; ++ daintmsk.ep.in = 1 << ep->num; ++ } else { ++ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; ++ daintmsk.ep.out = 1 << ep->num; ++ } ++ ++ depctl.d32 = DWC_READ_REG32(addr); ++ ++ depctl.b.usbactep = 0; ++ ++ /* Update nextep_seq array and EPMSCNT in DCFG */ ++ if (!(depctl.b.eptype & 1) && ep->is_in == 1) { // NP EP IN ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ if (core_if->nextep_seq[i] == ep->num) ++ break; ++ } ++ core_if->nextep_seq[i] = core_if->nextep_seq[ep->num]; ++ if (core_if->first_in_nextep_seq == ep->num) ++ core_if->first_in_nextep_seq = i; ++ core_if->nextep_seq[ep->num] = 0xff; ++ depctl.b.nextep = 0; ++ dcfg.d32 = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt--; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, ++ dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); ++ } ++ } ++ ++ if (ep->is_in == 1) ++ depctl.b.txfnum = 0; ++ ++ if (core_if->dma_desc_enable) ++ depctl.b.epdis = 1; ++ ++ DWC_WRITE_REG32(addr, depctl.d32); ++ depctl.d32 = DWC_READ_REG32(addr); ++ if (core_if->dma_enable && depctl.b.epena) { ++ depctl_data_t depctl = {.d32 = 0 }; ++ if (ep->is_in) { ++ diepint_data_t diepint = {.d32 = 0 }; ++ ++ depctl.b.snak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepctl, depctl.d32); ++/* do { */ ++ dwc_udelay(10); ++ diepint.d32 = ++ DWC_READ_REG32(&core_if-> ++ dev_if->in_ep_regs[ep->num]-> ++ diepint); ++/* } while (!diepint.b.inepnakeff); */ ++ diepint.b.inepnakeff = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepint, diepint.d32); ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepctl, depctl.d32); ++/* do { */ ++ dwc_udelay(10); ++ diepint.d32 = ++ DWC_READ_REG32(&core_if-> ++ dev_if->in_ep_regs[ep->num]-> ++ diepint); ++/* } while (!diepint.b.epdisabled); */ ++ diepint.b.epdisabled = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepint, diepint.d32); ++ } else if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ dctl_data_t dctl = {.d32 = 0}; ++ gintmsk_data_t gintsts = {.d32 = 0}; ++ doepint_data_t doepint = {.d32 = 0}; ++ dctl.b.sgoutnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, 0, dctl.d32); ++ do { ++ dwc_udelay(10); ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ } while (!gintsts.b.goutnakeff); ++ gintsts.d32 = 0; ++ gintsts.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepctl, depctl.d32); ++ do ++ { ++ dwc_udelay(10); ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->num]->doepint); ++ } while (!doepint.b.epdisabled); ++ ++ doepint.b.epdisabled = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepint, doepint.d32); ++ ++ dctl.d32 = 0; ++ dctl.b.cgoutnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } ++ } ++ ++ /* Disable the Interrupt for this EP */ ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->deachintmsk, ++ daintmsk.d32, 0); ++ ++ if (ep->is_in == 1) { ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs-> ++ diepeachintmsk[ep->num], 0); ++ } else { ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[ep->num], 0); ++ } ++ } else { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->daintmsk, ++ daintmsk.d32, 0); ++ } ++ ++} ++ ++/** ++ * This function initializes dma descriptor chain. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++static void init_dma_desc_chain(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ uint32_t offset; ++ uint32_t xfer_est; ++ int i; ++ unsigned maxxfer_local, total_len; ++ ++ if (!ep->is_in && ep->type == DWC_OTG_EP_TYPE_INTR && ++ (ep->maxpacket % 4)) { ++ maxxfer_local = ep->maxpacket; ++ total_len = ep->xfer_len; ++ } else { ++ maxxfer_local = ep->maxxfer; ++ total_len = ep->total_len; ++ } ++ ++ ep->desc_cnt = (total_len / maxxfer_local) + ++ ((total_len % maxxfer_local) ? 1 : 0); ++ ++ if (!ep->desc_cnt) ++ ep->desc_cnt = 1; ++ ++ if (ep->desc_cnt > MAX_DMA_DESC_CNT) ++ ep->desc_cnt = MAX_DMA_DESC_CNT; ++ ++ dma_desc = ep->desc_addr; ++ if (maxxfer_local == ep->maxpacket) { ++ if ((total_len % maxxfer_local) && ++ (total_len / maxxfer_local < MAX_DMA_DESC_CNT)) { ++ xfer_est = (ep->desc_cnt - 1) * maxxfer_local + ++ (total_len % maxxfer_local); ++ } else ++ xfer_est = ep->desc_cnt * maxxfer_local; ++ } else ++ xfer_est = total_len; ++ offset = 0; ++ for (i = 0; i < ep->desc_cnt; ++i) { ++ /** DMA Descriptor Setup */ ++ if (xfer_est > maxxfer_local) { ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 0; ++ dma_desc->status.b.ioc = 0; ++ dma_desc->status.b.sp = 0; ++ dma_desc->status.b.bytes = maxxfer_local; ++ dma_desc->buf = ep->dma_addr + offset; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ xfer_est -= maxxfer_local; ++ offset += maxxfer_local; ++ } else { ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ if (ep->is_in) { ++ dma_desc->status.b.sp = ++ (xfer_est % ++ ep->maxpacket) ? 1 : ((ep-> ++ sent_zlp) ? 1 : 0); ++ dma_desc->status.b.bytes = xfer_est; ++ } else { ++ if (maxxfer_local == ep->maxpacket) ++ dma_desc->status.b.bytes = xfer_est; ++ else ++ dma_desc->status.b.bytes = ++ xfer_est + ((4 - (xfer_est & 0x3)) & 0x3); ++ } ++ ++ dma_desc->buf = ep->dma_addr + offset; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ } ++ dma_desc++; ++ } ++} ++ ++/** ++ * This function is called when to write ISOC data into appropriate dedicated ++ * periodic FIFO. ++ */ ++static int32_t write_isoc_tx_fifo(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep) ++{ ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dwc_otg_dev_in_ep_regs_t *ep_regs; ++ dtxfsts_data_t txstatus = {.d32 = 0 }; ++ uint32_t len = 0; ++ int epnum = dwc_ep->num; ++ int dwords; ++ ++ DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum); ++ ++ ep_regs = core_if->dev_if->in_ep_regs[epnum]; ++ ++ len = dwc_ep->xfer_len - dwc_ep->xfer_count; ++ ++ if (len > dwc_ep->maxpacket) { ++ len = dwc_ep->maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ ++ /* While there is space in the queue and space in the FIFO and ++ * More data to tranfer, Write packets to the Tx FIFO */ ++ txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32); ++ ++ while (txstatus.b.txfspcavail >= dwords && ++ dwc_ep->xfer_count < dwc_ep->xfer_len && dwc_ep->xfer_len != 0) { ++ /* Write the FIFO */ ++ dwc_otg_ep_write_packet(core_if, dwc_ep, 0); ++ ++ len = dwc_ep->xfer_len - dwc_ep->xfer_count; ++ if (len > dwc_ep->maxpacket) { ++ len = dwc_ep->maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ txstatus.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum, ++ txstatus.d32); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts)); ++ ++ return 1; ++} ++ ++/** ++ * This function does the setup for a data transfer for an EP and ++ * starts the transfer. For an IN transfer, the packets will be ++ * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers, ++ * the packets are unloaded from the Rx FIFO in the ISR. the ISR. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++ ++void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ deptsiz_data_t deptsiz; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__); ++ DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d " ++ "xfer_buff=%p start_xfer_buff=%p, total_len = %d\n", ++ ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len, ++ ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff, ++ ep->total_len); ++ /* IN endpoint */ ++ if (ep->is_in == 1) { ++ dwc_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[ep->num]; ++ ++ gnptxsts_data_t gtxstatus; ++ ++ gtxstatus.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gnptxsts); ++ ++ if (core_if->en_multiple_tx_fifo == 0 ++ && gtxstatus.b.nptxqspcavail == 0 && !core_if->dma_enable) { ++#ifdef DEBUG ++ DWC_PRINTF("TX Queue Full (0x%0x)\n", gtxstatus.d32); ++#endif ++ return; ++ } ++ ++ depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl)); ++ deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz)); ++ ++ if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT) ++ ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? ++ ep->maxxfer : (ep->total_len - ep->xfer_len); ++ else ++ ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ? ++ MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len); ++ ++ ++ /* Zero Length Packet? */ ++ if ((ep->xfer_len - ep->xfer_count) == 0) { ++ deptsiz.b.xfersize = 0; ++ deptsiz.b.pktcnt = 1; ++ } else { ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count; ++ deptsiz.b.pktcnt = ++ (ep->xfer_len - ep->xfer_count - 1 + ++ ep->maxpacket) / ep->maxpacket; ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) ++ deptsiz.b.mc = deptsiz.b.pktcnt; ++ } ++ ++ /* Write the DMA register */ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ if (ep->type != DWC_OTG_EP_TYPE_ISOC) ++ deptsiz.b.mc = 1; ++ DWC_WRITE_REG32(&in_regs->dieptsiz, ++ deptsiz.d32); ++ DWC_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } else { ++#ifdef DWC_UTE_CFI ++ /* The descriptor chain should be already initialized by now */ ++ if (ep->buff_mode != BM_STANDARD) { ++ DWC_WRITE_REG32(&in_regs->diepdma, ++ ep->descs_dma_addr); ++ } else { ++#endif ++ init_dma_desc_chain(core_if, ep); ++ /** DIEPDMAn Register write */ ++ DWC_WRITE_REG32(&in_regs->diepdma, ++ ep->dma_desc_addr); ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ } ++ } else { ++ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); ++ if (ep->type != DWC_OTG_EP_TYPE_ISOC) { ++ /** ++ * Enable the Non-Periodic Tx FIFO empty interrupt, ++ * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode, ++ * the data will be written into the fifo by the ISR. ++ */ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32 ++ (&core_if->core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } else { ++ /* Enable the Tx FIFO Empty Interrupt for this EP */ ++ if (ep->xfer_len > 0) { ++ uint32_t fifoemptymsk = 0; ++ fifoemptymsk = 1 << ep->num; ++ DWC_MODIFY_REG32 ++ (&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ 0, fifoemptymsk); ++ ++ } ++ } ++ } ++ } ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ dsts_data_t dsts = {.d32 = 0 }; ++ if (ep->bInterval == 1) { ++ dsts.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dsts); ++ ep->frame_num = dsts.b.soffn + ep->bInterval; ++ if (ep->frame_num > 0x3FFF) { ++ ep->frm_overrun = 1; ++ ep->frame_num &= 0x3FFF; ++ } else ++ ep->frm_overrun = 0; ++ if (ep->frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ } ++ } ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); ++ ++ if (!core_if->dma_enable && ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ write_isoc_tx_fifo(core_if, ep); ++ } ++ ++ } else { ++ /* OUT endpoint */ ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[ep->num]; ++ ++ depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl)); ++ deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz)); ++ ++ if (!core_if->dma_desc_enable) { ++ if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT) ++ ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? ++ ep->maxxfer : (ep->total_len - ep->xfer_len); ++ else ++ ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len ++ - ep->xfer_len)) ? MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len); ++ } ++ ++ /* Program the transfer size and packet count as follows: ++ * ++ * pktcnt = N ++ * xfersize = N * maxpacket ++ */ ++ if ((ep->xfer_len - ep->xfer_count) == 0) { ++ /* Zero Length Packet */ ++ deptsiz.b.xfersize = ep->maxpacket; ++ deptsiz.b.pktcnt = 1; ++ } else { ++ deptsiz.b.pktcnt = ++ (ep->xfer_len - ep->xfer_count + ++ (ep->maxpacket - 1)) / ep->maxpacket; ++ if (!core_if->dma_desc_enable) { ++ ep->xfer_len = ++ deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count; ++ } ++ deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count; ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "ep%d xfersize=%d pktcnt=%d\n", ++ ep->num, deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ ++ if (core_if->dma_enable) { ++ if (!core_if->dma_desc_enable) { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, ++ deptsiz.d32); ++ ++ DWC_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) ep->dma_addr); ++ } else { ++#ifdef DWC_UTE_CFI ++ /* The descriptor chain should be already initialized by now */ ++ if (ep->buff_mode != BM_STANDARD) { ++ DWC_WRITE_REG32(&out_regs->doepdma, ++ ep->descs_dma_addr); ++ } else { ++#endif ++ /** This is used for interrupt out transfers*/ ++ if (!ep->xfer_len) ++ ep->xfer_len = ep->total_len; ++ init_dma_desc_chain(core_if, ep); ++ ++ if (core_if->core_params->dev_out_nak) { ++ if (ep->type == DWC_OTG_EP_TYPE_BULK) { ++ deptsiz.b.pktcnt = (ep->total_len + ++ (ep->maxpacket - 1)) / ep->maxpacket; ++ deptsiz.b.xfersize = ep->total_len; ++ /* Remember initial value of doeptsiz */ ++ core_if->start_doeptsiz_val[ep->num] = deptsiz.d32; ++ DWC_WRITE_REG32(&out_regs->doeptsiz, ++ deptsiz.d32); ++ } ++ } ++ /** DOEPDMAn Register write */ ++ DWC_WRITE_REG32(&out_regs->doepdma, ++ ep->dma_desc_addr); ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ } ++ } else { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); ++ } ++ ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ dsts_data_t dsts = {.d32 = 0 }; ++ if (ep->bInterval == 1) { ++ dsts.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dsts); ++ ep->frame_num = dsts.b.soffn + ep->bInterval; ++ if (ep->frame_num > 0x3FFF) { ++ ep->frm_overrun = 1; ++ ep->frame_num &= 0x3FFF; ++ } else ++ ep->frm_overrun = 0; ++ ++ if (ep->frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ } ++ } ++ ++ /* EP enable */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ ++ DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32); ++ ++ DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n", ++ DWC_READ_REG32(&out_regs->doepctl), ++ DWC_READ_REG32(&out_regs->doeptsiz)); ++ DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n", ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs-> ++ daintmsk), ++ DWC_READ_REG32(&core_if->core_global_regs-> ++ gintmsk)); ++ ++ /* Timer is scheduling only for out bulk transfers for ++ * "Device DDMA OUT NAK Enhancement" feature to inform user ++ * about received data payload in case of timeout ++ */ ++ if (core_if->core_params->dev_out_nak) { ++ if (ep->type == DWC_OTG_EP_TYPE_BULK) { ++ core_if->ep_xfer_info[ep->num].core_if = core_if; ++ core_if->ep_xfer_info[ep->num].ep = ep; ++ core_if->ep_xfer_info[ep->num].state = 1; ++ ++ /* Start a timer for this transfer. */ ++ DWC_TIMER_SCHEDULE(core_if->ep_xfer_timer[ep->num], 10000); ++ } ++ } ++ } ++} ++ ++/** ++ * This function setup a zero length transfer in Buffer DMA and ++ * Slave modes for usb requests with zero field set ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ ++ depctl_data_t depctl; ++ deptsiz_data_t deptsiz; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__); ++ DWC_PRINTF("zero length transfer is called\n"); ++ ++ /* IN endpoint */ ++ if (ep->is_in == 1) { ++ dwc_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[ep->num]; ++ ++ depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl)); ++ deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz)); ++ ++ deptsiz.b.xfersize = 0; ++ deptsiz.b.pktcnt = 1; ++ ++ /* Write the DMA register */ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ deptsiz.b.mc = 1; ++ DWC_WRITE_REG32(&in_regs->dieptsiz, ++ deptsiz.d32); ++ DWC_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ } else { ++ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); ++ /** ++ * Enable the Non-Periodic Tx FIFO empty interrupt, ++ * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode, ++ * the data will be written into the fifo by the ISR. ++ */ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } else { ++ /* Enable the Tx FIFO Empty Interrupt for this EP */ ++ if (ep->xfer_len > 0) { ++ uint32_t fifoemptymsk = 0; ++ fifoemptymsk = 1 << ep->num; ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ 0, fifoemptymsk); ++ } ++ } ++ } ++ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); ++ ++ } else { ++ /* OUT endpoint */ ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[ep->num]; ++ ++ depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl)); ++ deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz)); ++ ++ /* Zero Length Packet */ ++ deptsiz.b.xfersize = ep->maxpacket; ++ deptsiz.b.pktcnt = 1; ++ ++ if (core_if->dma_enable) { ++ if (!core_if->dma_desc_enable) { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, ++ deptsiz.d32); ++ ++ DWC_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ } else { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); ++ } ++ ++ /* EP enable */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ ++ DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32); ++ ++ } ++} ++ ++/** ++ * This function does the setup for a data transfer for EP0 and starts ++ * the transfer. For an IN transfer, the packets will be loaded into ++ * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are ++ * unloaded from the Rx FIFO in the ISR. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP0 data. ++ */ ++void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ deptsiz0_data_t deptsiz; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ ++ DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d " ++ "xfer_buff=%p start_xfer_buff=%p \n", ++ ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len, ++ ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff); ++ ++ ep->total_len = ep->xfer_len; ++ ++ /* IN endpoint */ ++ if (ep->is_in == 1) { ++ dwc_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[0]; ++ ++ gnptxsts_data_t gtxstatus; ++ ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ depctl.d32 = DWC_READ_REG32(&in_regs->diepctl); ++ if (depctl.b.epena) ++ return; ++ } ++ ++ gtxstatus.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gnptxsts); ++ ++ /* If dedicated FIFO every time flush fifo before enable ep*/ ++ if (core_if->en_multiple_tx_fifo == 0 ++ && gtxstatus.b.nptxqspcavail == 0 ++ && !core_if->dma_enable) { ++#ifdef DEBUG ++ deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz); ++ DWC_DEBUGPL(DBG_PCD, "DIEPCTL0=%0x\n", ++ DWC_READ_REG32(&in_regs->diepctl)); ++ DWC_DEBUGPL(DBG_PCD, "DIEPTSIZ0=%0x (sz=%d, pcnt=%d)\n", ++ deptsiz.d32, ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ DWC_PRINTF("TX Queue or FIFO Full (0x%0x)\n", ++ gtxstatus.d32); ++#endif ++ return; ++ } ++ ++ depctl.d32 = DWC_READ_REG32(&in_regs->diepctl); ++ deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz); ++ ++ /* Zero Length Packet? */ ++ if (ep->xfer_len == 0) { ++ deptsiz.b.xfersize = 0; ++ deptsiz.b.pktcnt = 1; ++ } else { ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ if (core_if->dma_enable && core_if->dma_desc_enable) { ++ /* ++ To be fixed... ++ Enumeration process, host request 255byte configuraton desc, ++ device response 256byte. discuss with SNPS engineer, ++ the better method is to use single descriptor for a transfer. ++ to avoid any inconsistency in the driver code preparing multiple ++ descriptors after one is serviced. ++ So we would keep xfersize equal this request total length. ++ */ ++ deptsiz.b.xfersize = ep->xfer_len; ++ } else { ++ if (ep->xfer_len > ep->maxpacket) { ++ ep->xfer_len = ep->maxpacket; ++ deptsiz.b.xfersize = ep->maxpacket; ++ } else { ++ deptsiz.b.xfersize = ep->xfer_len; ++ } ++ } ++ deptsiz.b.pktcnt = 1; ++ ++ } ++ DWC_DEBUGPL(DBG_PCDV, ++ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", ++ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, ++ deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ DWC_WRITE_REG32(&in_regs->dieptsiz, ++ deptsiz.d32); ++ ++ DWC_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } else { ++ dma_desc = core_if->dev_if->in_desc_addr; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.sp = ++ (ep->xfer_len == ep->maxpacket) ? 0 : 1; ++ dma_desc->status.b.bytes = ep->xfer_len; ++ dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DIEPDMA0 Register write */ ++ DWC_WRITE_REG32(&in_regs->diepdma, ++ core_if-> ++ dev_if->dma_in_desc_addr); ++ } ++ } else { ++ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); ++ } ++ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); ++ ++ /** ++ * Enable the Non-Periodic Tx FIFO empty interrupt, the ++ * data will be written into the fifo by the ISR. ++ */ ++ if (!core_if->dma_enable) { ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } else { ++ /* Enable the Tx FIFO Empty Interrupt for this EP */ ++ if (ep->xfer_len > 0) { ++ uint32_t fifoemptymsk = 0; ++ fifoemptymsk |= 1 << ep->num; ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ 0, fifoemptymsk); ++ } ++ } ++ } ++ } else { ++ /* OUT endpoint */ ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[0]; ++ ++ depctl.d32 = DWC_READ_REG32(&out_regs->doepctl); ++ deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz); ++ ++ /* Program the transfer size and packet count as follows: ++ * xfersize = N * (maxpacket + 4 - (maxpacket % 4)) ++ * pktcnt = N */ ++ /* Zero Length Packet */ ++ deptsiz.b.xfersize = ep->maxpacket; ++ deptsiz.b.pktcnt = 1; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) ++ deptsiz.b.supcnt = 3; ++ ++ DWC_DEBUGPL(DBG_PCDV, "len=%d xfersize=%d pktcnt=%d\n", ++ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ ++ if (core_if->dma_enable) { ++ if (!core_if->dma_desc_enable) { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, ++ deptsiz.d32); ++ ++ DWC_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) ep->dma_addr); ++ } else { ++ dma_desc = core_if->dev_if->out_desc_addr; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ dma_desc->status.b.mtrf = 0; ++ dma_desc->status.b.sr = 0; ++ } ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.bytes = ep->maxpacket; ++ dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DOEPDMA0 Register write */ ++ DWC_WRITE_REG32(&out_regs->doepdma, ++ core_if->dev_if-> ++ dma_out_desc_addr); ++ } ++ } else { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); ++ } ++ ++ /* EP enable */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ DWC_WRITE_REG32(&(out_regs->doepctl), depctl.d32); ++ } ++} ++ ++/** ++ * This function continues control IN transfers started by ++ * dwc_otg_ep0_start_transfer, when the transfer does not fit in a ++ * single packet. NOTE: The DIEPCTL0/DOEPCTL0 registers only have one ++ * bit for the packet count. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP0 data. ++ */ ++void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ deptsiz0_data_t deptsiz; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ ++ if (ep->is_in == 1) { ++ dwc_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[0]; ++ gnptxsts_data_t tx_status = {.d32 = 0 }; ++ ++ tx_status.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gnptxsts); ++ /** @todo Should there be check for room in the Tx ++ * Status Queue. If not remove the code above this comment. */ ++ ++ depctl.d32 = DWC_READ_REG32(&in_regs->diepctl); ++ deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz); ++ ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ ++ if (core_if->dma_desc_enable == 0) { ++ deptsiz.b.xfersize = ++ (ep->total_len - ep->xfer_count) > ++ ep->maxpacket ? ep->maxpacket : (ep->total_len - ++ ep->xfer_count); ++ deptsiz.b.pktcnt = 1; ++ if (core_if->dma_enable == 0) { ++ ep->xfer_len += deptsiz.b.xfersize; ++ } else { ++ ep->xfer_len = deptsiz.b.xfersize; ++ } ++ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); ++ } else { ++ ep->xfer_len = ++ (ep->total_len - ep->xfer_count) > ++ ep->maxpacket ? ep->maxpacket : (ep->total_len - ++ ep->xfer_count); ++ ++ dma_desc = core_if->dev_if->in_desc_addr; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.sp = ++ (ep->xfer_len == ep->maxpacket) ? 0 : 1; ++ dma_desc->status.b.bytes = ep->xfer_len; ++ dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DIEPDMA0 Register write */ ++ DWC_WRITE_REG32(&in_regs->diepdma, ++ core_if->dev_if->dma_in_desc_addr); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", ++ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, ++ deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) { ++ if (core_if->dma_desc_enable == 0) ++ DWC_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); ++ ++ /** ++ * Enable the Non-Periodic Tx FIFO empty interrupt, the ++ * data will be written into the fifo by the ISR. ++ */ ++ if (!core_if->dma_enable) { ++ if (core_if->en_multiple_tx_fifo == 0) { ++ /* First clear it from GINTSTS */ ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ ++ } else { ++ /* Enable the Tx FIFO Empty Interrupt for this EP */ ++ if (ep->xfer_len > 0) { ++ uint32_t fifoemptymsk = 0; ++ fifoemptymsk |= 1 << ep->num; ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ 0, fifoemptymsk); ++ } ++ } ++ } ++ } else { ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[0]; ++ ++ depctl.d32 = DWC_READ_REG32(&out_regs->doepctl); ++ deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz); ++ ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ deptsiz.b.xfersize = ep->maxpacket; ++ deptsiz.b.pktcnt = 1; ++ ++ if (core_if->dma_desc_enable == 0) { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); ++ } else { ++ dma_desc = core_if->dev_if->out_desc_addr; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.bytes = ep->maxpacket; ++ dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DOEPDMA0 Register write */ ++ DWC_WRITE_REG32(&out_regs->doepdma, ++ core_if->dev_if->dma_out_desc_addr); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", ++ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, ++ deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) { ++ if (core_if->dma_desc_enable == 0) ++ DWC_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) ep->dma_addr); ++ ++ } ++ ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32); ++ ++ } ++} ++ ++#ifdef DEBUG ++void dump_msg(const u8 * buf, unsigned int length) ++{ ++ unsigned int start, num, i; ++ char line[52], *p; ++ ++ if (length >= 512) ++ return; ++ start = 0; ++ while (length > 0) { ++ num = length < 16u ? length : 16u; ++ p = line; ++ for (i = 0; i < num; ++i) { ++ if (i == 8) ++ *p++ = ' '; ++ DWC_SPRINTF(p, " %02x", buf[i]); ++ p += 3; ++ } ++ *p = 0; ++ DWC_PRINTF("%6x: %s\n", start, line); ++ buf += num; ++ start += num; ++ length -= num; ++ } ++} ++#else ++static inline void dump_msg(const u8 * buf, unsigned int length) ++{ ++} ++#endif ++ ++/** ++ * This function writes a packet into the Tx FIFO associated with the ++ * EP. For non-periodic EPs the non-periodic Tx FIFO is written. For ++ * periodic EPs the periodic Tx FIFO associated with the EP is written ++ * with all packets for the next micro-frame. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to write packet for. ++ * @param dma Indicates if DMA is being used. ++ */ ++void dwc_otg_ep_write_packet(dwc_otg_core_if_t * core_if, dwc_ep_t * ep, ++ int dma) ++{ ++ /** ++ * The buffer is padded to DWORD on a per packet basis in ++ * slave/dma mode if the MPS is not DWORD aligned. The last ++ * packet, if short, is also padded to a multiple of DWORD. ++ * ++ * ep->xfer_buff always starts DWORD aligned in memory and is a ++ * multiple of DWORD in length ++ * ++ * ep->xfer_len can be any number of bytes ++ * ++ * ep->xfer_count is a multiple of ep->maxpacket until the last ++ * packet ++ * ++ * FIFO access is DWORD */ ++ ++ uint32_t i; ++ uint32_t byte_count; ++ uint32_t dword_count; ++ uint32_t *fifo; ++ uint32_t *data_buff = (uint32_t *) ep->xfer_buff; ++ ++ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p)\n", __func__, core_if, ++ ep); ++ if (ep->xfer_count >= ep->xfer_len) { ++ DWC_WARN("%s() No data for EP%d!!!\n", __func__, ep->num); ++ return; ++ } ++ ++ /* Find the byte length of the packet either short packet or MPS */ ++ if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket) { ++ byte_count = ep->xfer_len - ep->xfer_count; ++ } else { ++ byte_count = ep->maxpacket; ++ } ++ ++ /* Find the DWORD length, padded by extra bytes as neccessary if MPS ++ * is not a multiple of DWORD */ ++ dword_count = (byte_count + 3) / 4; ++ ++#ifdef VERBOSE ++ dump_msg(ep->xfer_buff, byte_count); ++#endif ++ ++ /**@todo NGS Where are the Periodic Tx FIFO addresses ++ * intialized? What should this be? */ ++ ++ fifo = core_if->data_fifo[ep->num]; ++ ++ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "fifo=%p buff=%p *p=%08x bc=%d\n", ++ fifo, data_buff, *data_buff, byte_count); ++ ++ if (!dma) { ++ for (i = 0; i < dword_count; i++, data_buff++) { ++ DWC_WRITE_REG32(fifo, *data_buff); ++ } ++ } ++ ++ ep->xfer_count += byte_count; ++ ep->xfer_buff += byte_count; ++ ep->dma_addr += byte_count; ++} ++ ++/** ++ * Set the EP STALL. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to set the stall on. ++ */ ++void dwc_otg_ep_set_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ volatile uint32_t *depctl_addr; ++ ++ DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num, ++ (ep->is_in ? "IN" : "OUT")); ++ ++ if (ep->is_in == 1) { ++ depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl); ++ depctl.d32 = DWC_READ_REG32(depctl_addr); ++ ++ /* set the disable and stall bits */ ++ if (depctl.b.epena) { ++ depctl.b.epdis = 1; ++ } ++ depctl.b.stall = 1; ++ DWC_WRITE_REG32(depctl_addr, depctl.d32); ++ } else { ++ depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl); ++ depctl.d32 = DWC_READ_REG32(depctl_addr); ++ ++ /* set the stall bit */ ++ depctl.b.stall = 1; ++ DWC_WRITE_REG32(depctl_addr, depctl.d32); ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr)); ++ ++ return; ++} ++ ++/** ++ * Clear the EP STALL. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to clear stall from. ++ */ ++void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ volatile uint32_t *depctl_addr; ++ ++ DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num, ++ (ep->is_in ? "IN" : "OUT")); ++ ++ if (ep->is_in == 1) { ++ depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl); ++ } else { ++ depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl); ++ } ++ ++ depctl.d32 = DWC_READ_REG32(depctl_addr); ++ ++ /* clear the stall bits */ ++ depctl.b.stall = 0; ++ ++ /* ++ * USB Spec 9.4.5: For endpoints using data toggle, regardless ++ * of whether an endpoint has the Halt feature set, a ++ * ClearFeature(ENDPOINT_HALT) request always results in the ++ * data toggle being reinitialized to DATA0. ++ */ ++ if (ep->type == DWC_OTG_EP_TYPE_INTR || ++ ep->type == DWC_OTG_EP_TYPE_BULK) { ++ depctl.b.setd0pid = 1; /* DATA0 */ ++ } ++ ++ DWC_WRITE_REG32(depctl_addr, depctl.d32); ++ DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr)); ++ return; ++} ++ ++/** ++ * This function reads a packet from the Rx FIFO into the destination ++ * buffer. To read SETUP data use dwc_otg_read_setup_packet. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param dest Destination buffer for the packet. ++ * @param bytes Number of bytes to copy to the destination. ++ */ ++void dwc_otg_read_packet(dwc_otg_core_if_t * core_if, ++ uint8_t * dest, uint16_t bytes) ++{ ++ int i; ++ int word_count = (bytes + 3) / 4; ++ ++ volatile uint32_t *fifo = core_if->data_fifo[0]; ++ uint32_t *data_buff = (uint32_t *) dest; ++ ++ /** ++ * @todo Account for the case where _dest is not dword aligned. This ++ * requires reading data from the FIFO into a uint32_t temp buffer, ++ * then moving it into the data buffer. ++ */ ++ ++ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p,%d)\n", __func__, ++ core_if, dest, bytes); ++ ++ for (i = 0; i < word_count; i++, data_buff++) { ++ *data_buff = DWC_READ_REG32(fifo); ++ } ++ ++ return; ++} ++ ++/** ++ * This functions reads the device registers and prints them ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * core_if) ++{ ++ int i; ++ volatile uint32_t *addr; ++ ++ DWC_PRINTF("Device Global Registers\n"); ++ addr = &core_if->dev_if->dev_global_regs->dcfg; ++ DWC_PRINTF("DCFG @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->dctl; ++ DWC_PRINTF("DCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->dsts; ++ DWC_PRINTF("DSTS @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->diepmsk; ++ DWC_PRINTF("DIEPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->doepmsk; ++ DWC_PRINTF("DOEPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->daint; ++ DWC_PRINTF("DAINT @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->daintmsk; ++ DWC_PRINTF("DAINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->dtknqr1; ++ DWC_PRINTF("DTKNQR1 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ if (core_if->hwcfg2.b.dev_token_q_depth > 6) { ++ addr = &core_if->dev_if->dev_global_regs->dtknqr2; ++ DWC_PRINTF("DTKNQR2 @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } ++ ++ addr = &core_if->dev_if->dev_global_regs->dvbusdis; ++ DWC_PRINTF("DVBUSID @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ ++ addr = &core_if->dev_if->dev_global_regs->dvbuspulse; ++ DWC_PRINTF("DVBUSPULSE @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ ++ addr = &core_if->dev_if->dev_global_regs->dtknqr3_dthrctl; ++ DWC_PRINTF("DTKNQR3_DTHRCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ ++ if (core_if->hwcfg2.b.dev_token_q_depth > 22) { ++ addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk; ++ DWC_PRINTF("DTKNQR4 @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } ++ ++ addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk; ++ DWC_PRINTF("FIFOEMPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ ++ if (core_if->hwcfg2.b.multi_proc_int) { ++ ++ addr = &core_if->dev_if->dev_global_regs->deachint; ++ DWC_PRINTF("DEACHINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->deachintmsk; ++ DWC_PRINTF("DEACHINTMSK @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ addr = ++ &core_if->dev_if-> ++ dev_global_regs->diepeachintmsk[i]; ++ DWC_PRINTF("DIEPEACHINTMSK[%d] @0x%08lX : 0x%08X\n", ++ i, (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ } ++ ++ for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { ++ addr = ++ &core_if->dev_if-> ++ dev_global_regs->doepeachintmsk[i]; ++ DWC_PRINTF("DOEPEACHINTMSK[%d] @0x%08lX : 0x%08X\n", ++ i, (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ } ++ } ++ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_PRINTF("Device IN EP %d Registers\n", i); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepctl; ++ DWC_PRINTF("DIEPCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepint; ++ DWC_PRINTF("DIEPINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->dieptsiz; ++ DWC_PRINTF("DIETSIZ @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepdma; ++ DWC_PRINTF("DIEPDMA @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->dtxfsts; ++ DWC_PRINTF("DTXFSTS @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepdmab; ++ DWC_PRINTF("DIEPDMAB @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, 0 /*DWC_READ_REG32(addr) */ ); ++ } ++ ++ for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { ++ DWC_PRINTF("Device OUT EP %d Registers\n", i); ++ addr = &core_if->dev_if->out_ep_regs[i]->doepctl; ++ DWC_PRINTF("DOEPCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->out_ep_regs[i]->doepint; ++ DWC_PRINTF("DOEPINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->out_ep_regs[i]->doeptsiz; ++ DWC_PRINTF("DOETSIZ @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->out_ep_regs[i]->doepdma; ++ DWC_PRINTF("DOEPDMA @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ if (core_if->dma_enable) { /* Don't access this register in SLAVE mode */ ++ addr = &core_if->dev_if->out_ep_regs[i]->doepdmab; ++ DWC_PRINTF("DOEPDMAB @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } ++ ++ } ++} ++ ++/** ++ * This functions reads the SPRAM and prints its content ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_dump_spram(dwc_otg_core_if_t * core_if) ++{ ++ volatile uint8_t *addr, *start_addr, *end_addr; ++ ++ DWC_PRINTF("SPRAM Data:\n"); ++ start_addr = (void *)core_if->core_global_regs; ++ DWC_PRINTF("Base Address: 0x%8lX\n", (unsigned long)start_addr); ++ start_addr += 0x00028000; ++ end_addr = (void *)core_if->core_global_regs; ++ end_addr += 0x000280e0; ++ ++ for (addr = start_addr; addr < end_addr; addr += 16) { ++ DWC_PRINTF ++ ("0x%8lX:\t%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\n", ++ (unsigned long)addr, addr[0], addr[1], addr[2], addr[3], ++ addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], ++ addr[10], addr[11], addr[12], addr[13], addr[14], addr[15] ++ ); ++ } ++ ++ return; ++} ++ ++/** ++ * This function reads the host registers and prints them ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_dump_host_registers(dwc_otg_core_if_t * core_if) ++{ ++ int i; ++ volatile uint32_t *addr; ++ ++ DWC_PRINTF("Host Global Registers\n"); ++ addr = &core_if->host_if->host_global_regs->hcfg; ++ DWC_PRINTF("HCFG @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->hfir; ++ DWC_PRINTF("HFIR @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->hfnum; ++ DWC_PRINTF("HFNUM @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->hptxsts; ++ DWC_PRINTF("HPTXSTS @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->haint; ++ DWC_PRINTF("HAINT @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->haintmsk; ++ DWC_PRINTF("HAINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ if (core_if->dma_desc_enable) { ++ addr = &core_if->host_if->host_global_regs->hflbaddr; ++ DWC_PRINTF("HFLBADDR @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } ++ ++ addr = core_if->host_if->hprt0; ++ DWC_PRINTF("HPRT0 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ ++ for (i = 0; i < core_if->core_params->host_channels; i++) { ++ DWC_PRINTF("Host Channel %d Specific Registers\n", i); ++ addr = &core_if->host_if->hc_regs[i]->hcchar; ++ DWC_PRINTF("HCCHAR @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcsplt; ++ DWC_PRINTF("HCSPLT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcint; ++ DWC_PRINTF("HCINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcintmsk; ++ DWC_PRINTF("HCINTMSK @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hctsiz; ++ DWC_PRINTF("HCTSIZ @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcdma; ++ DWC_PRINTF("HCDMA @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ if (core_if->dma_desc_enable) { ++ addr = &core_if->host_if->hc_regs[i]->hcdmab; ++ DWC_PRINTF("HCDMAB @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } ++ ++ } ++ return; ++} ++ ++/** ++ * This function reads the core global registers and prints them ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_dump_global_registers(dwc_otg_core_if_t * core_if) ++{ ++ int i, ep_num; ++ volatile uint32_t *addr; ++ char *txfsiz; ++ ++ DWC_PRINTF("Core Global Registers\n"); ++ addr = &core_if->core_global_regs->gotgctl; ++ DWC_PRINTF("GOTGCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gotgint; ++ DWC_PRINTF("GOTGINT @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gahbcfg; ++ DWC_PRINTF("GAHBCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gusbcfg; ++ DWC_PRINTF("GUSBCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->grstctl; ++ DWC_PRINTF("GRSTCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gintsts; ++ DWC_PRINTF("GINTSTS @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gintmsk; ++ DWC_PRINTF("GINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->grxstsr; ++ DWC_PRINTF("GRXSTSR @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->grxfsiz; ++ DWC_PRINTF("GRXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gnptxfsiz; ++ DWC_PRINTF("GNPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gnptxsts; ++ DWC_PRINTF("GNPTXSTS @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gi2cctl; ++ DWC_PRINTF("GI2CCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gpvndctl; ++ DWC_PRINTF("GPVNDCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ggpio; ++ DWC_PRINTF("GGPIO @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->guid; ++ DWC_PRINTF("GUID @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gsnpsid; ++ DWC_PRINTF("GSNPSID @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg1; ++ DWC_PRINTF("GHWCFG1 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg2; ++ DWC_PRINTF("GHWCFG2 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg3; ++ DWC_PRINTF("GHWCFG3 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg4; ++ DWC_PRINTF("GHWCFG4 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->glpmcfg; ++ DWC_PRINTF("GLPMCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gpwrdn; ++ DWC_PRINTF("GPWRDN @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gdfifocfg; ++ DWC_PRINTF("GDFIFOCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->adpctl; ++ DWC_PRINTF("ADPCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ dwc_otg_adp_read_reg(core_if)); ++ addr = &core_if->core_global_regs->hptxfsiz; ++ DWC_PRINTF("HPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ ep_num = core_if->hwcfg4.b.num_dev_perio_in_ep; ++ txfsiz = "DPTXFSIZ"; ++ } else { ++ ep_num = core_if->hwcfg4.b.num_in_eps; ++ txfsiz = "DIENPTXF"; ++ } ++ for (i = 0; i < ep_num; i++) { ++ addr = &core_if->core_global_regs->dtxfsiz[i]; ++ DWC_PRINTF("%s[%d] @0x%08lX : 0x%08X\n", txfsiz, i + 1, ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } ++ addr = core_if->pcgcctl; ++ DWC_PRINTF("PCGCCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++} ++ ++/** ++ * Flush a Tx FIFO. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param num Tx FIFO to flush. ++ */ ++void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * core_if, const int num) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ volatile grstctl_t greset = {.d32 = 0 }; ++ int count = 0; ++ ++ DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "Flush Tx FIFO %d\n", num); ++ ++ greset.b.txfflsh = 1; ++ greset.b.txfnum = num; ++ DWC_WRITE_REG32(&global_regs->grstctl, greset.d32); ++ ++ do { ++ greset.d32 = DWC_READ_REG32(&global_regs->grstctl); ++ if (++count > 10000) { ++ DWC_WARN("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n", ++ __func__, greset.d32, ++ DWC_READ_REG32(&global_regs->gnptxsts)); ++ break; ++ } ++ dwc_udelay(1); ++ } while (greset.b.txfflsh == 1); ++ ++ /* Wait for 3 PHY Clocks */ ++ dwc_udelay(1); ++} ++ ++/** ++ * Flush Rx FIFO. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ volatile grstctl_t greset = {.d32 = 0 }; ++ int count = 0; ++ ++ DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "%s\n", __func__); ++ /* ++ * ++ */ ++ greset.b.rxfflsh = 1; ++ DWC_WRITE_REG32(&global_regs->grstctl, greset.d32); ++ ++ do { ++ greset.d32 = DWC_READ_REG32(&global_regs->grstctl); ++ if (++count > 10000) { ++ DWC_WARN("%s() HANG! GRSTCTL=%0x\n", __func__, ++ greset.d32); ++ break; ++ } ++ dwc_udelay(1); ++ } while (greset.b.rxfflsh == 1); ++ ++ /* Wait for 3 PHY Clocks */ ++ dwc_udelay(1); ++} ++ ++/** ++ * Do core a soft reset of the core. Be careful with this because it ++ * resets all the internal state machines of the core. ++ */ ++void dwc_otg_core_reset(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ volatile grstctl_t greset = {.d32 = 0 }; ++ int count = 0; ++ ++ DWC_DEBUGPL(DBG_CILV, "%s\n", __func__); ++ /* Wait for AHB master IDLE state. */ ++ do { ++ dwc_udelay(10); ++ greset.d32 = DWC_READ_REG32(&global_regs->grstctl); ++ if (++count > 100000) { ++ DWC_WARN("%s() HANG! AHB Idle GRSTCTL=%0x\n", __func__, ++ greset.d32); ++ return; ++ } ++ } ++ while (greset.b.ahbidle == 0); ++ ++ /* Core Soft Reset */ ++ count = 0; ++ greset.b.csftrst = 1; ++ DWC_WRITE_REG32(&global_regs->grstctl, greset.d32); ++ do { ++ greset.d32 = DWC_READ_REG32(&global_regs->grstctl); ++ if (++count > 10000) { ++ DWC_WARN("%s() HANG! Soft Reset GRSTCTL=%0x\n", ++ __func__, greset.d32); ++ break; ++ } ++ dwc_udelay(1); ++ } ++ while (greset.b.csftrst == 1); ++ ++ /* Wait for 3 PHY Clocks */ ++ dwc_mdelay(100); ++} ++ ++uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if) ++{ ++ return (dwc_otg_mode(_core_if) != DWC_HOST_MODE); ++} ++ ++uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if) ++{ ++ return (dwc_otg_mode(_core_if) == DWC_HOST_MODE); ++} ++ ++/** ++ * Register HCD callbacks. The callbacks are used to start and stop ++ * the HCD for interrupt processing. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param cb the HCD callback structure. ++ * @param p pointer to be passed to callback function (usb_hcd*). ++ */ ++void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * core_if, ++ dwc_otg_cil_callbacks_t * cb, void *p) ++{ ++ core_if->hcd_cb = cb; ++ cb->p = p; ++} ++ ++/** ++ * Register PCD callbacks. The callbacks are used to start and stop ++ * the PCD for interrupt processing. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param cb the PCD callback structure. ++ * @param p pointer to be passed to callback function (pcd*). ++ */ ++void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * core_if, ++ dwc_otg_cil_callbacks_t * cb, void *p) ++{ ++ core_if->pcd_cb = cb; ++ cb->p = p; ++} ++ ++#ifdef DWC_EN_ISOC ++ ++/** ++ * This function writes isoc data per 1 (micro)frame into tx fifo ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void write_isoc_frame_data(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ dwc_otg_dev_in_ep_regs_t *ep_regs; ++ dtxfsts_data_t txstatus = {.d32 = 0 }; ++ uint32_t len = 0; ++ uint32_t dwords; ++ ++ ep->xfer_len = ep->data_per_frame; ++ ep->xfer_count = 0; ++ ++ ep_regs = core_if->dev_if->in_ep_regs[ep->num]; ++ ++ len = ep->xfer_len - ep->xfer_count; ++ ++ if (len > ep->maxpacket) { ++ len = ep->maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ ++ /* While there is space in the queue and space in the FIFO and ++ * More data to tranfer, Write packets to the Tx FIFO */ ++ txstatus.d32 = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", ep->num, txstatus.d32); ++ ++ while (txstatus.b.txfspcavail > dwords && ++ ep->xfer_count < ep->xfer_len && ep->xfer_len != 0) { ++ /* Write the FIFO */ ++ dwc_otg_ep_write_packet(core_if, ep, 0); ++ ++ len = ep->xfer_len - ep->xfer_count; ++ if (len > ep->maxpacket) { ++ len = ep->maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ txstatus.d32 = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", ep->num, ++ txstatus.d32); ++ } ++} ++ ++/** ++ * This function initializes a descriptor chain for Isochronous transfer ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * ep) ++{ ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dsts_data_t dsts = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ ++ if (ep->is_in) { ++ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; ++ } else { ++ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; ++ } ++ ++ ep->xfer_len = ep->data_per_frame; ++ ep->xfer_count = 0; ++ ep->xfer_buff = ep->cur_pkt_addr; ++ ep->dma_addr = ep->cur_pkt_dma_addr; ++ ++ if (ep->is_in) { ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ deptsiz.b.xfersize = ep->xfer_len; ++ deptsiz.b.pktcnt = ++ (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; ++ deptsiz.b.mc = deptsiz.b.pktcnt; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz, ++ deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->dma_enable) { ++ DWC_WRITE_REG32(& ++ (core_if->dev_if->in_ep_regs[ep->num]-> ++ diepdma), (uint32_t) ep->dma_addr); ++ } ++ } else { ++ deptsiz.b.pktcnt = ++ (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket; ++ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; ++ ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->num]->doeptsiz, deptsiz.d32); ++ ++ if (core_if->dma_enable) { ++ DWC_WRITE_REG32(& ++ (core_if->dev_if-> ++ out_ep_regs[ep->num]->doepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ } ++ ++ /** Enable endpoint, clear nak */ ++ ++ depctl.d32 = 0; ++ if (ep->bInterval == 1) { ++ dsts.d32 = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ep->next_frame = dsts.b.soffn + ep->bInterval; ++ ++ if (ep->next_frame & 0x1) { ++ depctl.b.setd1pid = 1; ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ } else { ++ ep->next_frame += ep->bInterval; ++ ++ if (ep->next_frame & 0x1) { ++ depctl.b.setd1pid = 1; ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ } ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ ++ DWC_MODIFY_REG32(addr, 0, depctl.d32); ++ depctl.d32 = DWC_READ_REG32(addr); ++ ++ if (ep->is_in && core_if->dma_enable == 0) { ++ write_isoc_frame_data(core_if, ep); ++ } ++ ++} ++#endif /* DWC_EN_ISOC */ ++ ++static void dwc_otg_set_uninitialized(int32_t * p, int size) ++{ ++ int i; ++ for (i = 0; i < size; i++) { ++ p[i] = -1; ++ } ++} ++ ++static int dwc_otg_param_initialized(int32_t val) ++{ ++ return val != -1; ++} ++ ++static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if) ++{ ++ int i; ++ gintsts_data_t gintsts; ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ ++ core_if->core_params = DWC_ALLOC(sizeof(*core_if->core_params)); ++ if (!core_if->core_params) { ++ return -DWC_E_NO_MEMORY; ++ } ++ dwc_otg_set_uninitialized((int32_t *) core_if->core_params, ++ sizeof(*core_if->core_params) / ++ sizeof(int32_t)); ++ DWC_PRINTF("Setting default values for core params\n"); ++ dwc_otg_set_param_otg_cap(core_if, dwc_param_otg_cap_default); ++ dwc_otg_set_param_dma_enable(core_if, dwc_param_dma_enable_default); ++ dwc_otg_set_param_dma_desc_enable(core_if, ++ dwc_param_dma_desc_enable_default); ++ dwc_otg_set_param_opt(core_if, dwc_param_opt_default); ++ dwc_otg_set_param_dma_burst_size(core_if, ++ dwc_param_dma_burst_size_default); ++ dwc_otg_set_param_host_support_fs_ls_low_power(core_if, ++ dwc_param_host_support_fs_ls_low_power_default); ++ dwc_otg_set_param_enable_dynamic_fifo(core_if, ++ dwc_param_enable_dynamic_fifo_default); ++ dwc_otg_set_param_data_fifo_size(core_if, ++ dwc_param_data_fifo_size_default); ++ dwc_otg_set_param_dev_rx_fifo_size(core_if, ++ dwc_param_dev_rx_fifo_size_default); ++ dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if, ++ dwc_param_dev_nperio_tx_fifo_size_default); ++ dwc_otg_set_param_host_rx_fifo_size(core_if, ++ dwc_param_host_rx_fifo_size_default); ++ dwc_otg_set_param_host_nperio_tx_fifo_size(core_if, ++ dwc_param_host_nperio_tx_fifo_size_default); ++ dwc_otg_set_param_host_perio_tx_fifo_size(core_if, ++ dwc_param_host_perio_tx_fifo_size_default); ++ dwc_otg_set_param_max_transfer_size(core_if, ++ dwc_param_max_transfer_size_default); ++ dwc_otg_set_param_max_packet_count(core_if, ++ dwc_param_max_packet_count_default); ++ dwc_otg_set_param_host_channels(core_if, ++ dwc_param_host_channels_default); ++ dwc_otg_set_param_dev_endpoints(core_if, ++ dwc_param_dev_endpoints_default); ++ dwc_otg_set_param_phy_type(core_if, dwc_param_phy_type_default); ++ dwc_otg_set_param_speed(core_if, dwc_param_speed_default); ++ dwc_otg_set_param_host_ls_low_power_phy_clk(core_if, ++ dwc_param_host_ls_low_power_phy_clk_default); ++ dwc_otg_set_param_phy_ulpi_ddr(core_if, dwc_param_phy_ulpi_ddr_default); ++ dwc_otg_set_param_phy_ulpi_ext_vbus(core_if, ++ dwc_param_phy_ulpi_ext_vbus_default); ++ dwc_otg_set_param_phy_utmi_width(core_if, ++ dwc_param_phy_utmi_width_default); ++ dwc_otg_set_param_ts_dline(core_if, dwc_param_ts_dline_default); ++ dwc_otg_set_param_i2c_enable(core_if, dwc_param_i2c_enable_default); ++ dwc_otg_set_param_ulpi_fs_ls(core_if, dwc_param_ulpi_fs_ls_default); ++ dwc_otg_set_param_en_multiple_tx_fifo(core_if, ++ dwc_param_en_multiple_tx_fifo_default); ++ ++ if (gintsts.b.curmode) { ++ /* Force device mode to get power-on values of device FIFOs */ ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gusbcfg.b.force_dev_mode = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ dwc_mdelay(100); ++ for (i = 0; i < 15; i++) { ++ dwc_otg_set_param_dev_perio_tx_fifo_size(core_if, ++ dwc_param_dev_perio_tx_fifo_size_default, i); ++ } ++ for (i = 0; i < 15; i++) { ++ dwc_otg_set_param_dev_tx_fifo_size(core_if, ++ dwc_param_dev_tx_fifo_size_default, i); ++ } ++ gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gusbcfg.b.force_dev_mode = 0; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ dwc_mdelay(100); ++ } else { ++ for (i = 0; i < 15; i++) { ++ dwc_otg_set_param_dev_perio_tx_fifo_size(core_if, ++ dwc_param_dev_perio_tx_fifo_size_default, i); ++ } ++ for (i = 0; i < 15; i++) { ++ dwc_otg_set_param_dev_tx_fifo_size(core_if, ++ dwc_param_dev_tx_fifo_size_default, i); ++ } ++ } ++ ++ dwc_otg_set_param_thr_ctl(core_if, dwc_param_thr_ctl_default); ++ dwc_otg_set_param_mpi_enable(core_if, dwc_param_mpi_enable_default); ++ dwc_otg_set_param_pti_enable(core_if, dwc_param_pti_enable_default); ++ dwc_otg_set_param_lpm_enable(core_if, dwc_param_lpm_enable_default); ++ ++ dwc_otg_set_param_besl_enable(core_if, dwc_param_besl_enable_default); ++ dwc_otg_set_param_baseline_besl(core_if, dwc_param_baseline_besl_default); ++ dwc_otg_set_param_deep_besl(core_if, dwc_param_deep_besl_default); ++ ++ dwc_otg_set_param_ic_usb_cap(core_if, dwc_param_ic_usb_cap_default); ++ dwc_otg_set_param_tx_thr_length(core_if, ++ dwc_param_tx_thr_length_default); ++ dwc_otg_set_param_rx_thr_length(core_if, ++ dwc_param_rx_thr_length_default); ++ dwc_otg_set_param_ahb_thr_ratio(core_if, ++ dwc_param_ahb_thr_ratio_default); ++ dwc_otg_set_param_power_down(core_if, dwc_param_power_down_default); ++ dwc_otg_set_param_reload_ctl(core_if, dwc_param_reload_ctl_default); ++ dwc_otg_set_param_dev_out_nak(core_if, dwc_param_dev_out_nak_default); ++ dwc_otg_set_param_cont_on_bna(core_if, dwc_param_cont_on_bna_default); ++ dwc_otg_set_param_ahb_single(core_if, dwc_param_ahb_single_default); ++ dwc_otg_set_param_otg_ver(core_if, dwc_param_otg_ver_default); ++ dwc_otg_set_param_adp_enable(core_if, dwc_param_adp_enable_default); ++ return 0; ++} ++ ++uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->dma_enable; ++} ++ ++/* Checks if the parameter is outside of its valid range of values */ ++#define DWC_OTG_PARAM_TEST(_param_, _low_, _high_) \ ++ (((_param_) < (_low_)) || \ ++ ((_param_) > (_high_))) ++ ++/* Parameter access functions */ ++int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int valid; ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 2)) { ++ DWC_WARN("Wrong value for otg_cap parameter\n"); ++ DWC_WARN("otg_cap parameter must be 0,1 or 2\n"); ++ retval = -DWC_E_INVALID; ++ goto out; ++ } ++ ++ valid = 1; ++ switch (val) { ++ case DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE: ++ if (core_if->hwcfg2.b.op_mode != ++ DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ++ valid = 0; ++ break; ++ case DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE: ++ if ((core_if->hwcfg2.b.op_mode != ++ DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ++ && (core_if->hwcfg2.b.op_mode != ++ DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) ++ && (core_if->hwcfg2.b.op_mode != ++ DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE) ++ && (core_if->hwcfg2.b.op_mode != ++ DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) { ++ valid = 0; ++ } ++ break; ++ case DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE: ++ /* always valid */ ++ break; ++ } ++ if (!valid) { ++ if (dwc_otg_param_initialized(core_if->core_params->otg_cap)) { ++ DWC_ERROR ++ ("%d invalid for otg_cap paremter. Check HW configuration.\n", ++ val); ++ } ++ val = ++ (((core_if->hwcfg2.b.op_mode == ++ DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ++ || (core_if->hwcfg2.b.op_mode == ++ DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) ++ || (core_if->hwcfg2.b.op_mode == ++ DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE) ++ || (core_if->hwcfg2.b.op_mode == ++ DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) ? ++ DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE : ++ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->otg_cap = val; ++out: ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->otg_cap; ++} ++ ++int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong value for opt parameter\n"); ++ return -DWC_E_INVALID; ++ } ++ core_if->core_params->opt = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->opt; ++} ++ ++int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong value for dma enable\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && (core_if->hwcfg2.b.architecture == 0)) { ++ if (dwc_otg_param_initialized(core_if->core_params->dma_enable)) { ++ DWC_ERROR ++ ("%d invalid for dma_enable paremter. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->dma_enable = val; ++ if (val == 0) { ++ dwc_otg_set_param_dma_desc_enable(core_if, 0); ++ } ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dma_enable; ++} ++ ++int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong value for dma_enable\n"); ++ DWC_WARN("dma_desc_enable must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) ++ && ((dwc_otg_get_param_dma_enable(core_if) == 0) ++ || (core_if->hwcfg4.b.desc_dma == 0))) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->dma_desc_enable)) { ++ DWC_ERROR ++ ("%d invalid for dma_desc_enable paremter. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++ core_if->core_params->dma_desc_enable = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dma_desc_enable; ++} ++ ++int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong value for host_support_fs_low_power\n"); ++ DWC_WARN("host_support_fs_low_power must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ core_if->core_params->host_support_fs_ls_low_power = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t * ++ core_if) ++{ ++ return core_if->core_params->host_support_fs_ls_low_power; ++} ++ ++int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong value for enable_dynamic_fifo\n"); ++ DWC_WARN("enable_dynamic_fifo must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && (core_if->hwcfg2.b.dynamic_fifo == 0)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->enable_dynamic_fifo)) { ++ DWC_ERROR ++ ("%d invalid for enable_dynamic_fifo paremter. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++ core_if->core_params->enable_dynamic_fifo = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->enable_dynamic_fifo; ++} ++ ++int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 32, 32768)) { ++ DWC_WARN("Wrong value for data_fifo_size\n"); ++ DWC_WARN("data_fifo_size must be 32-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > core_if->hwcfg3.b.dfifo_depth) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->data_fifo_size)) { ++ DWC_ERROR ++ ("%d invalid for data_fifo_size parameter. Check HW configuration.\n", ++ val); ++ } ++ val = core_if->hwcfg3.b.dfifo_depth; ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->data_fifo_size = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->data_fifo_size; ++} ++ ++int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) { ++ DWC_WARN("Wrong value for dev_rx_fifo_size\n"); ++ DWC_WARN("dev_rx_fifo_size must be 16-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) { ++ if (dwc_otg_param_initialized(core_if->core_params->dev_rx_fifo_size)) { ++ DWC_WARN("%d invalid for dev_rx_fifo_size parameter\n", val); ++ } ++ val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->dev_rx_fifo_size = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dev_rx_fifo_size; ++} ++ ++int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) { ++ DWC_WARN("Wrong value for dev_nperio_tx_fifo\n"); ++ DWC_WARN("dev_nperio_tx_fifo must be 16-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->dev_nperio_tx_fifo_size)) { ++ DWC_ERROR ++ ("%d invalid for dev_nperio_tx_fifo_size. Check HW configuration.\n", ++ val); ++ } ++ val = ++ (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> ++ 16); ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->dev_nperio_tx_fifo_size = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dev_nperio_tx_fifo_size; ++} ++ ++int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) { ++ DWC_WARN("Wrong value for host_rx_fifo_size\n"); ++ DWC_WARN("host_rx_fifo_size must be 16-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->host_rx_fifo_size)) { ++ DWC_ERROR ++ ("%d invalid for host_rx_fifo_size. Check HW configuration.\n", ++ val); ++ } ++ val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->host_rx_fifo_size = val; ++ return retval; ++ ++} ++ ++int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->host_rx_fifo_size; ++} ++ ++int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) { ++ DWC_WARN("Wrong value for host_nperio_tx_fifo_size\n"); ++ DWC_WARN("host_nperio_tx_fifo_size must be 16-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->host_nperio_tx_fifo_size)) { ++ DWC_ERROR ++ ("%d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n", ++ val); ++ } ++ val = ++ (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> ++ 16); ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->host_nperio_tx_fifo_size = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->host_nperio_tx_fifo_size; ++} ++ ++int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) { ++ DWC_WARN("Wrong value for host_perio_tx_fifo_size\n"); ++ DWC_WARN("host_perio_tx_fifo_size must be 16-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > ((core_if->hptxfsiz.d32) >> 16)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->host_perio_tx_fifo_size)) { ++ DWC_ERROR ++ ("%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n", ++ val); ++ } ++ val = (core_if->hptxfsiz.d32) >> 16; ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->host_perio_tx_fifo_size = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->host_perio_tx_fifo_size; ++} ++ ++int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 2047, 524288)) { ++ DWC_WARN("Wrong value for max_transfer_size\n"); ++ DWC_WARN("max_transfer_size must be 2047-524288\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val >= (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11))) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->max_transfer_size)) { ++ DWC_ERROR ++ ("%d invalid for max_transfer_size. Check HW configuration.\n", ++ val); ++ } ++ val = ++ ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 11)) - ++ 1); ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->max_transfer_size = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->max_transfer_size; ++} ++ ++int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 15, 511)) { ++ DWC_WARN("Wrong value for max_packet_count\n"); ++ DWC_WARN("max_packet_count must be 15-511\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4))) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->max_packet_count)) { ++ DWC_ERROR ++ ("%d invalid for max_packet_count. Check HW configuration.\n", ++ val); ++ } ++ val = ++ ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1); ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->max_packet_count = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->max_packet_count; ++} ++ ++int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 1, 16)) { ++ DWC_WARN("Wrong value for host_channels\n"); ++ DWC_WARN("host_channels must be 1-16\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > (core_if->hwcfg2.b.num_host_chan + 1)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->host_channels)) { ++ DWC_ERROR ++ ("%d invalid for host_channels. Check HW configurations.\n", ++ val); ++ } ++ val = (core_if->hwcfg2.b.num_host_chan + 1); ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->host_channels = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->host_channels; ++} ++ ++int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 1, 15)) { ++ DWC_WARN("Wrong value for dev_endpoints\n"); ++ DWC_WARN("dev_endpoints must be 1-15\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > (core_if->hwcfg2.b.num_dev_ep)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->dev_endpoints)) { ++ DWC_ERROR ++ ("%d invalid for dev_endpoints. Check HW configurations.\n", ++ val); ++ } ++ val = core_if->hwcfg2.b.num_dev_ep; ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->dev_endpoints = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dev_endpoints; ++} ++ ++int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 2)) { ++ DWC_WARN("Wrong value for phy_type\n"); ++ DWC_WARN("phy_type must be 0,1 or 2\n"); ++ return -DWC_E_INVALID; ++ } ++#ifndef NO_FS_PHY_HW_CHECKS ++ if ((val == DWC_PHY_TYPE_PARAM_UTMI) && ++ ((core_if->hwcfg2.b.hs_phy_type == 1) || ++ (core_if->hwcfg2.b.hs_phy_type == 3))) { ++ valid = 1; ++ } else if ((val == DWC_PHY_TYPE_PARAM_ULPI) && ++ ((core_if->hwcfg2.b.hs_phy_type == 2) || ++ (core_if->hwcfg2.b.hs_phy_type == 3))) { ++ valid = 1; ++ } else if ((val == DWC_PHY_TYPE_PARAM_FS) && ++ (core_if->hwcfg2.b.fs_phy_type == 1)) { ++ valid = 1; ++ } ++ if (!valid) { ++ if (dwc_otg_param_initialized(core_if->core_params->phy_type)) { ++ DWC_ERROR ++ ("%d invalid for phy_type. Check HW configurations.\n", ++ val); ++ } ++ if (core_if->hwcfg2.b.hs_phy_type) { ++ if ((core_if->hwcfg2.b.hs_phy_type == 3) || ++ (core_if->hwcfg2.b.hs_phy_type == 1)) { ++ val = DWC_PHY_TYPE_PARAM_UTMI; ++ } else { ++ val = DWC_PHY_TYPE_PARAM_ULPI; ++ } ++ } ++ retval = -DWC_E_INVALID; ++ } ++#endif ++ core_if->core_params->phy_type = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->phy_type; ++} ++ ++int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong value for speed parameter\n"); ++ DWC_WARN("max_speed parameter must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ if ((val == 0) ++ && dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS) { ++ if (dwc_otg_param_initialized(core_if->core_params->speed)) { ++ DWC_ERROR ++ ("%d invalid for speed paremter. Check HW configuration.\n", ++ val); ++ } ++ val = ++ (dwc_otg_get_param_phy_type(core_if) == ++ DWC_PHY_TYPE_PARAM_FS ? 1 : 0); ++ retval = -DWC_E_INVALID; ++ } ++ core_if->core_params->speed = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->speed; ++} ++ ++int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN ++ ("Wrong value for host_ls_low_power_phy_clk parameter\n"); ++ DWC_WARN("host_ls_low_power_phy_clk must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ) ++ && (dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->host_ls_low_power_phy_clk)) { ++ DWC_ERROR ++ ("%d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n", ++ val); ++ } ++ val = ++ (dwc_otg_get_param_phy_type(core_if) == ++ DWC_PHY_TYPE_PARAM_FS) ? ++ DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ : ++ DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ; ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->host_ls_low_power_phy_clk = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->host_ls_low_power_phy_clk; ++} ++ ++int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong value for phy_ulpi_ddr\n"); ++ DWC_WARN("phy_upli_ddr must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->phy_ulpi_ddr = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->phy_ulpi_ddr; ++} ++ ++int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong valaue for phy_ulpi_ext_vbus\n"); ++ DWC_WARN("phy_ulpi_ext_vbus must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->phy_ulpi_ext_vbus = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->phy_ulpi_ext_vbus; ++} ++ ++int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 8, 8) && DWC_OTG_PARAM_TEST(val, 16, 16)) { ++ DWC_WARN("Wrong valaue for phy_utmi_width\n"); ++ DWC_WARN("phy_utmi_width must be 8 or 16\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->phy_utmi_width = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->phy_utmi_width; ++} ++ ++int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong valaue for ulpi_fs_ls\n"); ++ DWC_WARN("ulpi_fs_ls must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->ulpi_fs_ls = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->ulpi_fs_ls; ++} ++ ++int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong valaue for ts_dline\n"); ++ DWC_WARN("ts_dline must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->ts_dline = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->ts_dline; ++} ++ ++int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong valaue for i2c_enable\n"); ++ DWC_WARN("i2c_enable must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++#ifndef NO_FS_PHY_HW_CHECK ++ if (val == 1 && core_if->hwcfg3.b.i2c == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->i2c_enable)) { ++ DWC_ERROR ++ ("%d invalid for i2c_enable. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++#endif ++ ++ core_if->core_params->i2c_enable = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->i2c_enable; ++} ++ ++int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if, ++ int32_t val, int fifo_num) ++{ ++ int retval = 0; ++ gintsts_data_t gintsts; ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ ++ if (DWC_OTG_PARAM_TEST(val, 4, 768)) { ++ DWC_WARN("Wrong value for dev_perio_tx_fifo_size\n"); ++ DWC_WARN("dev_perio_tx_fifo_size must be 4-768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > ++ (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]) >> 16)) { ++ DWC_WARN("Value is larger then power-on FIFO size\n"); ++ if (dwc_otg_param_initialized ++ (core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) { ++ DWC_ERROR ++ ("`%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n", ++ val, fifo_num); ++ } ++ val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]) >> 16); ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->dev_perio_tx_fifo_size[fifo_num] = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if, ++ int fifo_num) ++{ ++ return core_if->core_params->dev_perio_tx_fifo_size[fifo_num]; ++} ++ ++int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong valaue for en_multiple_tx_fifo,\n"); ++ DWC_WARN("en_multiple_tx_fifo must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val == 1 && core_if->hwcfg4.b.ded_fifo_en == 0) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->en_multiple_tx_fifo)) { ++ DWC_ERROR ++ ("%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->en_multiple_tx_fifo = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->en_multiple_tx_fifo; ++} ++ ++int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val, ++ int fifo_num) ++{ ++ int retval = 0; ++ fifosize_data_t txfifosize; ++ txfifosize.d32 = DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]); ++ ++ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) { ++ DWC_WARN("Wrong value for dev_tx_fifo_size\n"); ++ DWC_WARN("dev_tx_fifo_size must be 16-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > txfifosize.b.depth) { ++ DWC_WARN("Value is larger then power-on FIFO size\n"); ++ if (dwc_otg_param_initialized ++ (core_if->core_params->dev_tx_fifo_size[fifo_num])) { ++ DWC_ERROR ++ ("`%d' invalid for parameter `dev_tx_fifo_size_%d'. Check HW configuration.\n", ++ val, fifo_num); ++ } ++ val = txfifosize.b.depth; ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->dev_tx_fifo_size[fifo_num] = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if, ++ int fifo_num) ++{ ++ return core_if->core_params->dev_tx_fifo_size[fifo_num]; ++} ++ ++int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 7)) { ++ DWC_WARN("Wrong value for thr_ctl\n"); ++ DWC_WARN("thr_ctl must be 0-7\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val != 0) && ++ (!dwc_otg_get_param_dma_enable(core_if) || ++ !core_if->hwcfg4.b.ded_fifo_en)) { ++ if (dwc_otg_param_initialized(core_if->core_params->thr_ctl)) { ++ DWC_ERROR ++ ("%d invalid for parameter thr_ctl. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->thr_ctl = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_thr_ctl(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->thr_ctl; ++} ++ ++int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong value for lpm_enable\n"); ++ DWC_WARN("lpm_enable must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val && !core_if->hwcfg3.b.otg_lpm_en) { ++ if (dwc_otg_param_initialized(core_if->core_params->lpm_enable)) { ++ DWC_ERROR ++ ("%d invalid for parameter lpm_enable. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->lpm_enable = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->lpm_enable; ++} ++ ++int dwc_otg_set_param_besl_enable(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("Wrong value for besl_enable\n"); ++ DWC_WARN("besl_enable must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->besl_enable = val; ++ ++ if(val) ++ { ++ retval += dwc_otg_set_param_lpm_enable(core_if,val); ++ } ++ ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_besl_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->besl_enable; ++} ++ ++int dwc_otg_set_param_baseline_besl(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 15)) { ++ DWC_WARN("Wrong value for baseline_besl\n"); ++ DWC_WARN("baseline_besl must be 0-15\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->baseline_besl = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_baseline_besl(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->baseline_besl; ++} ++ ++int dwc_otg_set_param_deep_besl(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 15)) { ++ DWC_WARN("Wrong value for deep_besl\n"); ++ DWC_WARN("deep_besl must be 0-15\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->deep_besl = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_deep_besl(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->deep_besl; ++} ++ ++int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 8, 128)) { ++ DWC_WARN("Wrong valaue for tx_thr_length\n"); ++ DWC_WARN("tx_thr_length must be 8 - 128\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->tx_thr_length = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_tx_thr_length(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->tx_thr_length; ++} ++ ++int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 8, 128)) { ++ DWC_WARN("Wrong valaue for rx_thr_length\n"); ++ DWC_WARN("rx_thr_length must be 8 - 128\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->rx_thr_length = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_rx_thr_length(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->rx_thr_length; ++} ++ ++int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ if (DWC_OTG_PARAM_TEST(val, 1, 1) && ++ DWC_OTG_PARAM_TEST(val, 4, 4) && ++ DWC_OTG_PARAM_TEST(val, 8, 8) && ++ DWC_OTG_PARAM_TEST(val, 16, 16) && ++ DWC_OTG_PARAM_TEST(val, 32, 32) && ++ DWC_OTG_PARAM_TEST(val, 64, 64) && ++ DWC_OTG_PARAM_TEST(val, 128, 128) && ++ DWC_OTG_PARAM_TEST(val, 256, 256)) { ++ DWC_WARN("`%d' invalid for parameter `dma_burst_size'\n", val); ++ return -DWC_E_INVALID; ++ } ++ core_if->core_params->dma_burst_size = val; ++ return 0; ++} ++ ++int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dma_burst_size; ++} ++ ++int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `pti_enable'\n", val); ++ return -DWC_E_INVALID; ++ } ++ if (val && (core_if->snpsid < OTG_CORE_REV_2_72a)) { ++ if (dwc_otg_param_initialized(core_if->core_params->pti_enable)) { ++ DWC_ERROR ++ ("%d invalid for parameter pti_enable. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->pti_enable = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->pti_enable; ++} ++ ++int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `mpi_enable'\n", val); ++ return -DWC_E_INVALID; ++ } ++ if (val && (core_if->hwcfg2.b.multi_proc_int == 0)) { ++ if (dwc_otg_param_initialized(core_if->core_params->mpi_enable)) { ++ DWC_ERROR ++ ("%d invalid for parameter mpi_enable. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->mpi_enable = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->mpi_enable; ++} ++ ++int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `adp_enable'\n", val); ++ return -DWC_E_INVALID; ++ } ++ if (val && (core_if->hwcfg3.b.adp_supp == 0)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->adp_supp_enable)) { ++ DWC_ERROR ++ ("%d invalid for parameter adp_enable. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->adp_supp_enable = val; ++ /* Set OTG version 2.0 in case of enabling ADP */ ++ if (val) ++ dwc_otg_set_param_otg_ver(core_if, 1); ++ ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->adp_supp_enable; ++} ++ ++int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `ic_usb_cap'\n", val); ++ DWC_WARN("ic_usb_cap must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val && (core_if->hwcfg2.b.otg_enable_ic_usb == 0)) { ++ if (dwc_otg_param_initialized(core_if->core_params->ic_usb_cap)) { ++ DWC_ERROR ++ ("%d invalid for parameter ic_usb_cap. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->ic_usb_cap = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->ic_usb_cap; ++} ++ ++int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 3)) { ++ DWC_WARN("`%d' invalid for parameter `ahb_thr_ratio'\n", val); ++ DWC_WARN("ahb_thr_ratio must be 0 - 3\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val ++ && (core_if->snpsid < OTG_CORE_REV_2_81a ++ || !dwc_otg_get_param_thr_ctl(core_if))) { ++ valid = 0; ++ } else if (val ++ && ((dwc_otg_get_param_tx_thr_length(core_if) / (1 << val)) < ++ 4)) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->ahb_thr_ratio)) { ++ DWC_ERROR ++ ("%d invalid for parameter ahb_thr_ratio. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ ++ core_if->core_params->ahb_thr_ratio = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->ahb_thr_ratio; ++} ++ ++int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ hwcfg4_data_t hwcfg4 = {.d32 = 0 }; ++ hwcfg4.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4); ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 3)) { ++ DWC_WARN("`%d' invalid for parameter `power_down'\n", val); ++ DWC_WARN("power_down must be 0 - 2\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 2) && (core_if->snpsid < OTG_CORE_REV_2_91a)) { ++ valid = 0; ++ } ++ if ((val == 3) ++ && ((core_if->snpsid < OTG_CORE_REV_3_00a) ++ || (hwcfg4.b.xhiber == 0))) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->power_down)) { ++ DWC_ERROR ++ ("%d invalid for parameter power_down. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->power_down = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->power_down; ++} ++ ++int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `reload_ctl'\n", val); ++ DWC_WARN("reload_ctl must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_92a)) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->reload_ctl)) { ++ DWC_ERROR("%d invalid for parameter reload_ctl." ++ "Check HW configuration.\n", val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->reload_ctl = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->reload_ctl; ++} ++ ++int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `dev_out_nak'\n", val); ++ DWC_WARN("dev_out_nak must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_93a) || ++ !(core_if->core_params->dma_desc_enable))) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->dev_out_nak)) { ++ DWC_ERROR("%d invalid for parameter dev_out_nak." ++ "Check HW configuration.\n", val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->dev_out_nak = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dev_out_nak; ++} ++ ++int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `cont_on_bna'\n", val); ++ DWC_WARN("cont_on_bna must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_94a) || ++ !(core_if->core_params->dma_desc_enable))) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->cont_on_bna)) { ++ DWC_ERROR("%d invalid for parameter cont_on_bna." ++ "Check HW configuration.\n", val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->cont_on_bna = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->cont_on_bna; ++} ++ ++int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `ahb_single'\n", val); ++ DWC_WARN("ahb_single must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_94a)) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->ahb_single)) { ++ DWC_ERROR("%d invalid for parameter ahb_single." ++ "Check HW configuration.\n", val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->ahb_single = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->ahb_single; ++} ++ ++int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `otg_ver'\n", val); ++ DWC_WARN ++ ("otg_ver must be 0(for OTG 1.3 support) or 1(for OTG 2.0 support)\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->otg_ver = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->otg_ver; ++} ++ ++uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if) ++{ ++ gotgctl_data_t otgctl; ++ otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ return otgctl.b.hstnegscs; ++} ++ ++uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if) ++{ ++ gotgctl_data_t otgctl; ++ otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ return otgctl.b.sesreqscs; ++} ++ ++void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ if(core_if->otg_ver == 0) { ++ gotgctl_data_t otgctl; ++ otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ otgctl.b.hnpreq = val; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, otgctl.d32); ++ } else { ++ core_if->otg_sts = val; ++ } ++} ++ ++uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->snpsid; ++} ++ ++uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ return gintsts.b.curmode; ++} ++ ++uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if) ++{ ++ gusbcfg_data_t usbcfg; ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ return usbcfg.b.hnpcap; ++} ++ ++void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ gusbcfg_data_t usbcfg; ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ usbcfg.b.hnpcap = val; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32); ++} ++ ++uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if) ++{ ++ gusbcfg_data_t usbcfg; ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ return usbcfg.b.srpcap; ++} ++ ++void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ gusbcfg_data_t usbcfg; ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ usbcfg.b.srpcap = val; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32); ++} ++ ++uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if) ++{ ++ dcfg_data_t dcfg; ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ return dcfg.b.devspd; ++} ++ ++void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ dcfg_data_t dcfg; ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ dcfg.b.devspd = val; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); ++} ++ ++uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); ++ return hprt0.b.prtconnsts; ++} ++ ++uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if) ++{ ++ dsts_data_t dsts; ++ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ return dsts.b.enumspd; ++} ++ ++uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); ++ return hprt0.b.prtpwr; ++ ++} ++ ++uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->hibernation_suspend; ++} ++ ++void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = val; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++} ++ ++uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); ++ return hprt0.b.prtsusp; ++ ++} ++ ++void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = val; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++} ++ ++uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if) ++{ ++ hfir_data_t hfir; ++ hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir); ++ return hfir.b.frint; ++ ++} ++ ++void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ hfir_data_t hfir; ++ uint32_t fram_int; ++ fram_int = calc_frame_interval(core_if); ++ hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir); ++ if (!core_if->core_params->reload_ctl) { ++ DWC_WARN("\nCannot reload HFIR register.HFIR.HFIRRldCtrl bit is" ++ "not set to 1.\nShould load driver with reload_ctl=1" ++ " module parameter\n"); ++ return; ++ } ++ switch (fram_int) { ++ case 3750: ++ if ((val < 3350) || (val > 4150)) { ++ DWC_WARN("HFIR interval for HS core and 30 MHz" ++ "clock freq should be from 3350 to 4150\n"); ++ return; ++ } ++ break; ++ case 30000: ++ if ((val < 26820) || (val > 33180)) { ++ DWC_WARN("HFIR interval for FS/LS core and 30 MHz" ++ "clock freq should be from 26820 to 33180\n"); ++ return; ++ } ++ break; ++ case 6000: ++ if ((val < 5360) || (val > 6640)) { ++ DWC_WARN("HFIR interval for HS core and 48 MHz" ++ "clock freq should be from 5360 to 6640\n"); ++ return; ++ } ++ break; ++ case 48000: ++ if ((val < 42912) || (val > 53088)) { ++ DWC_WARN("HFIR interval for FS/LS core and 48 MHz" ++ "clock freq should be from 42912 to 53088\n"); ++ return; ++ } ++ break; ++ case 7500: ++ if ((val < 6700) || (val > 8300)) { ++ DWC_WARN("HFIR interval for HS core and 60 MHz" ++ "clock freq should be from 6700 to 8300\n"); ++ return; ++ } ++ break; ++ case 60000: ++ if ((val < 53640) || (val > 65536)) { ++ DWC_WARN("HFIR interval for FS/LS core and 60 MHz" ++ "clock freq should be from 53640 to 65536\n"); ++ return; ++ } ++ break; ++ default: ++ DWC_WARN("Unknown frame interval\n"); ++ return; ++ break; ++ ++ } ++ hfir.b.frint = val; ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hfir.d32); ++} ++ ++uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if) ++{ ++ hcfg_data_t hcfg; ++ hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ return hcfg.b.modechtimen; ++ ++} ++ ++void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ hcfg_data_t hcfg; ++ hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ hcfg.b.modechtimen = val; ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++} ++ ++void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtres = val; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++} ++ ++uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if) ++{ ++ dctl_data_t dctl; ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ return dctl.b.rmtwkupsig; ++} ++ ++uint32_t dwc_otg_get_beslreject(dwc_otg_core_if_t * core_if) ++{ ++ dctl_data_t dctl; ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ return dctl.b.besl_reject; ++} ++ ++void dwc_otg_set_beslreject(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ dctl_data_t dctl; ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ dctl.b.besl_reject = val; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++} ++uint32_t dwc_otg_get_hirdthresh(dwc_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ return lpmcfg.b.hird_thres; ++} ++ ++void dwc_otg_set_hirdthresh(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ glpmcfg_data_t lpmcfg; ++ ++ if (val > 15) { ++ DWC_WARN("Wrong valaue for hird_thres\n"); ++ DWC_WARN("hird_thres must be 0-f\n"); ++ return ; ++ } ++ ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.hird_thres &= (1<<4); ++ lpmcfg.b.hird_thres |= val; ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++} ++ ++uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ ++ DWC_ASSERT(! ++ ((core_if->lx_state == DWC_OTG_L1) ^ lpmcfg.b.prt_sleep_sts), ++ "lx_state = %d, lmpcfg.prt_sleep_sts = %d\n", ++ core_if->lx_state, lpmcfg.b.prt_sleep_sts); ++ ++ return lpmcfg.b.prt_sleep_sts; ++} ++ ++uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ return lpmcfg.b.rem_wkup_en; ++} ++ ++uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ return lpmcfg.b.appl_resp; ++} ++ ++void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.appl_resp = val; ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++} ++ ++uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ return lpmcfg.b.hsic_connect; ++} ++ ++void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.hsic_connect = val; ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++} ++ ++uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ return lpmcfg.b.inv_sel_hsic; ++ ++} ++ ++void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.inv_sel_hsic = val; ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++} ++ ++uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if) ++{ ++ return DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++} ++ ++void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, val); ++} ++ ++uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if) ++{ ++ return DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++} ++ ++void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, val); ++} ++ ++uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if) ++{ ++ return DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); ++} ++ ++void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, val); ++} ++ ++uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if) ++{ ++ return DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz); ++} ++ ++void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, val); ++} ++ ++uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if) ++{ ++ return DWC_READ_REG32(&core_if->core_global_regs->gpvndctl); ++} ++ ++void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gpvndctl, val); ++} ++ ++uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if) ++{ ++ return DWC_READ_REG32(&core_if->core_global_regs->ggpio); ++} ++ ++void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, val); ++} ++ ++uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if) ++{ ++ return DWC_READ_REG32(core_if->host_if->hprt0); ++ ++} ++ ++void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ DWC_WRITE_REG32(core_if->host_if->hprt0, val); ++} ++ ++uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if) ++{ ++ return DWC_READ_REG32(&core_if->core_global_regs->guid); ++} ++ ++void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ DWC_WRITE_REG32(&core_if->core_global_regs->guid, val); ++} ++ ++uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if) ++{ ++ return DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz); ++} ++ ++uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if) ++{ ++ return ((core_if->otg_ver == 1) ? (uint16_t)0x0200 : (uint16_t)0x0103); ++} ++ ++/** ++ * Start the SRP timer to detect when the SRP does not complete within ++ * 6 seconds. ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++void dwc_otg_pcd_start_srp_timer(dwc_otg_core_if_t * core_if) ++{ ++ core_if->srp_timer_started = 1; ++ DWC_TIMER_SCHEDULE(core_if->srp_timer, 6000 /* 6 secs */ ); ++} ++ ++void dwc_otg_initiate_srp(void * p) ++{ ++ dwc_otg_core_if_t * core_if = p; ++ uint32_t *addr = (uint32_t *) & (core_if->core_global_regs->gotgctl); ++ gotgctl_data_t mem; ++ gotgctl_data_t val; ++ ++ val.d32 = DWC_READ_REG32(addr); ++ if (val.b.sesreq) { ++ DWC_ERROR("Session Request Already active!\n"); ++ return; ++ } ++ ++ DWC_INFO("Session Request Initated\n"); //NOTICE ++ mem.d32 = DWC_READ_REG32(addr); ++ mem.b.sesreq = 1; ++ DWC_WRITE_REG32(addr, mem.d32); ++ ++ /* Start the SRP timer */ ++ dwc_otg_pcd_start_srp_timer(core_if); ++ return; ++} ++ ++int dwc_otg_check_haps_status(dwc_otg_core_if_t * core_if) ++{ ++ int retval = 0; ++ ++ if(DWC_READ_REG32(&core_if->core_global_regs->gsnpsid) == 0xffffffff) ++ { ++ return -1; ++ } else { ++ return retval; ++ } ++ ++} +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_cil.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_cil.h +new file mode 100644 +index 0000000..b52a280 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_cil.h +@@ -0,0 +1,1498 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $ ++ * $Revision: #128 $ ++ * $Date: 2013/05/16 $ ++ * $Change: 2231774 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++#if !defined(__DWC_CIL_H__) ++#define __DWC_CIL_H__ ++ ++#include "dwc_list.h" ++#include "dwc_otg_dbg.h" ++#include "dwc_otg_regs.h" ++ ++#include "dwc_otg_core_if.h" ++#include "dwc_otg_adp.h" ++ ++/** ++ * @file ++ * This file contains the interface to the Core Interface Layer. ++ */ ++ ++#ifdef DWC_UTE_CFI ++ ++#define MAX_DMA_DESCS_PER_EP 256 ++ ++/** ++ * Enumeration for the data buffer mode ++ */ ++typedef enum _data_buffer_mode { ++ BM_STANDARD = 0, /* data buffer is in normal mode */ ++ BM_SG = 1, /* data buffer uses the scatter/gather mode */ ++ BM_CONCAT = 2, /* data buffer uses the concatenation mode */ ++ BM_CIRCULAR = 3, /* data buffer uses the circular DMA mode */ ++ BM_ALIGN = 4 /* data buffer is in buffer alignment mode */ ++} data_buffer_mode_e; ++#endif //DWC_UTE_CFI ++ ++/** Macros defined for DWC OTG HW Release version */ ++ ++#define OTG_CORE_REV_2_60a 0x4F54260A ++#define OTG_CORE_REV_2_71a 0x4F54271A ++#define OTG_CORE_REV_2_72a 0x4F54272A ++#define OTG_CORE_REV_2_80a 0x4F54280A ++#define OTG_CORE_REV_2_81a 0x4F54281A ++#define OTG_CORE_REV_2_90a 0x4F54290A ++#define OTG_CORE_REV_2_91a 0x4F54291A ++#define OTG_CORE_REV_2_92a 0x4F54292A ++#define OTG_CORE_REV_2_93a 0x4F54293A ++#define OTG_CORE_REV_2_94a 0x4F54294A ++#define OTG_CORE_REV_3_00a 0x4F54300A ++#define OTG_CORE_REV_3_10a 0x4F54310A ++ ++/** ++ * Information for each ISOC packet. ++ */ ++typedef struct iso_pkt_info { ++ uint32_t offset; ++ uint32_t length; ++ int32_t status; ++} iso_pkt_info_t; ++ ++/** ++ * The dwc_ep structure represents the state of a single ++ * endpoint when acting in device mode. It contains the data items ++ * needed for an endpoint to be activated and transfer packets. ++ */ ++typedef struct dwc_ep { ++ /** EP number used for register address lookup */ ++ uint8_t num; ++ /** EP direction 0 = OUT */ ++ unsigned is_in:1; ++ /** EP active. */ ++ unsigned active:1; ++ ++ /** ++ * Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic ++ * Tx FIFO. If dedicated Tx FIFOs are enabled Tx FIFO # FOR IN EPs*/ ++ unsigned tx_fifo_num:4; ++ /** EP type: 0 - Control, 1 - ISOC, 2 - BULK, 3 - INTR */ ++ unsigned type:2; ++#define DWC_OTG_EP_TYPE_CONTROL 0 ++#define DWC_OTG_EP_TYPE_ISOC 1 ++#define DWC_OTG_EP_TYPE_BULK 2 ++#define DWC_OTG_EP_TYPE_INTR 3 ++ ++ /** DATA start PID for INTR and BULK EP */ ++ unsigned data_pid_start:1; ++ /** Frame (even/odd) for ISOC EP */ ++ unsigned even_odd_frame:1; ++ /** Max Packet bytes */ ++ unsigned maxpacket:11; ++ ++ /** Max Transfer size */ ++ uint32_t maxxfer; ++ ++ /** @name Transfer state */ ++ /** @{ */ ++ ++ /** ++ * Pointer to the beginning of the transfer buffer -- do not modify ++ * during transfer. ++ */ ++ dwc_dma_t dma_addr; ++ ++ dwc_dma_t dma_desc_addr; ++ dwc_otg_dev_dma_desc_t *desc_addr; ++ ++ /* Additional desc chain for ISO transfers */ ++ dwc_dma_t dma_desc_addr1; ++ dwc_otg_dev_dma_desc_t *desc_addr1; ++ /* Flag indicating which one of two ISO desc chains currently is in use */ ++ uint8_t use_add_buf; ++ ++ uint8_t *start_xfer_buff; ++ /** pointer to the transfer buffer */ ++ uint8_t *xfer_buff; ++ /** Number of bytes to transfer */ ++ unsigned xfer_len:19; ++ /** Number of bytes transferred. */ ++ unsigned xfer_count:19; ++ /** Sent ZLP */ ++ unsigned sent_zlp:1; ++ /** Total len for control transfer */ ++ unsigned total_len:19; ++ ++ /** stall clear flag */ ++ unsigned stall_clear_flag:1; ++ ++ /** SETUP pkt cnt rollover flag for EP0 out*/ ++ unsigned stp_rollover; ++ ++#ifdef DWC_UTE_CFI ++ /* The buffer mode */ ++ data_buffer_mode_e buff_mode; ++ ++ /* The chain of DMA descriptors. ++ * MAX_DMA_DESCS_PER_EP will be allocated for each active EP. ++ */ ++ dwc_otg_dma_desc_t *descs; ++ ++ /* The DMA address of the descriptors chain start */ ++ dma_addr_t descs_dma_addr; ++ /** This variable stores the length of the last enqueued request */ ++ uint32_t cfi_req_len; ++#endif //DWC_UTE_CFI ++ ++/** Max DMA Descriptor count for any EP */ ++#define MAX_DMA_DESC_CNT 256 ++ /** Allocated DMA Desc count */ ++ uint32_t desc_cnt; ++ ++ /** First ISO Desc in use in the first chain*/ ++ uint32_t iso_desc_first; ++ /** Last ISO Desc in use in the second chain */ ++ uint32_t iso_desc_second; ++ /** Flag indicated that iso transfers were started */ ++ uint8_t iso_transfer_started; ++ ++ /** bInterval */ ++ uint32_t bInterval; ++ /** Next frame num to setup next ISOC transfer */ ++ uint32_t frame_num; ++ /** Indicates SOF number overrun in DSTS */ ++ uint8_t frm_overrun; ++ ++#ifdef DWC_UTE_PER_IO ++ /** Next frame num for which will be setup DMA Desc */ ++ uint32_t xiso_frame_num; ++ /** bInterval */ ++ uint32_t xiso_bInterval; ++ /** Count of currently active transfers - shall be either 0 or 1 */ ++ int xiso_active_xfers; ++ int xiso_queued_xfers; ++#endif ++#ifdef DWC_EN_ISOC ++ /** ++ * Variables specific for ISOC EPs ++ * ++ */ ++ /** DMA addresses of ISOC buffers */ ++ dwc_dma_t dma_addr0; ++ dwc_dma_t dma_addr1; ++ ++ dwc_dma_t iso_dma_desc_addr; ++ dwc_otg_dev_dma_desc_t *iso_desc_addr; ++ ++ /** pointer to the transfer buffers */ ++ uint8_t *xfer_buff0; ++ uint8_t *xfer_buff1; ++ ++ /** number of ISOC Buffer is processing */ ++ uint32_t proc_buf_num; ++ /** Interval of ISOC Buffer processing */ ++ uint32_t buf_proc_intrvl; ++ /** Data size for regular frame */ ++ uint32_t data_per_frame; ++ ++ /* todo - pattern data support is to be implemented in the future */ ++ /** Data size for pattern frame */ ++ uint32_t data_pattern_frame; ++ /** Frame number of pattern data */ ++ uint32_t sync_frame; ++ ++ /** bInterval */ ++ uint32_t bInterval; ++ /** ISO Packet number per frame */ ++ uint32_t pkt_per_frm; ++ /** Next frame num for which will be setup DMA Desc */ ++ uint32_t next_frame; ++ /** Number of packets per buffer processing */ ++ uint32_t pkt_cnt; ++ /** Info for all isoc packets */ ++ iso_pkt_info_t *pkt_info; ++ /** current pkt number */ ++ uint32_t cur_pkt; ++ /** current pkt number */ ++ uint8_t *cur_pkt_addr; ++ /** current pkt number */ ++ uint32_t cur_pkt_dma_addr; ++#endif /* DWC_EN_ISOC */ ++ ++/** @} */ ++} dwc_ep_t; ++ ++/* ++ * Reasons for halting a host channel. ++ */ ++typedef enum dwc_otg_halt_status { ++ DWC_OTG_HC_XFER_NO_HALT_STATUS, ++ DWC_OTG_HC_XFER_COMPLETE, ++ DWC_OTG_HC_XFER_URB_COMPLETE, ++ DWC_OTG_HC_XFER_ACK, ++ DWC_OTG_HC_XFER_NAK, ++ DWC_OTG_HC_XFER_NYET, ++ DWC_OTG_HC_XFER_STALL, ++ DWC_OTG_HC_XFER_XACT_ERR, ++ DWC_OTG_HC_XFER_FRAME_OVERRUN, ++ DWC_OTG_HC_XFER_BABBLE_ERR, ++ DWC_OTG_HC_XFER_DATA_TOGGLE_ERR, ++ DWC_OTG_HC_XFER_AHB_ERR, ++ DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE, ++ DWC_OTG_HC_XFER_URB_DEQUEUE ++} dwc_otg_halt_status_e; ++ ++/** ++ * Host channel descriptor. This structure represents the state of a single ++ * host channel when acting in host mode. It contains the data items needed to ++ * transfer packets to an endpoint via a host channel. ++ */ ++typedef struct dwc_hc { ++ /** Host channel number used for register address lookup */ ++ uint8_t hc_num; ++ ++ /** Device to access */ ++ unsigned dev_addr:7; ++ ++ /** EP to access */ ++ unsigned ep_num:4; ++ ++ /** EP direction. 0: OUT, 1: IN */ ++ unsigned ep_is_in:1; ++ ++ /** ++ * EP speed. ++ * One of the following values: ++ * - DWC_OTG_EP_SPEED_LOW ++ * - DWC_OTG_EP_SPEED_FULL ++ * - DWC_OTG_EP_SPEED_HIGH ++ */ ++ unsigned speed:2; ++#define DWC_OTG_EP_SPEED_LOW 0 ++#define DWC_OTG_EP_SPEED_FULL 1 ++#define DWC_OTG_EP_SPEED_HIGH 2 ++ ++ /** ++ * Endpoint type. ++ * One of the following values: ++ * - DWC_OTG_EP_TYPE_CONTROL: 0 ++ * - DWC_OTG_EP_TYPE_ISOC: 1 ++ * - DWC_OTG_EP_TYPE_BULK: 2 ++ * - DWC_OTG_EP_TYPE_INTR: 3 ++ */ ++ unsigned ep_type:2; ++ ++ /** Max packet size in bytes */ ++ unsigned max_packet:11; ++ ++ /** ++ * PID for initial transaction. ++ * 0: DATA0,
++ * 1: DATA2,
++ * 2: DATA1,
++ * 3: MDATA (non-Control EP), ++ * SETUP (Control EP) ++ */ ++ unsigned data_pid_start:2; ++#define DWC_OTG_HC_PID_DATA0 0 ++#define DWC_OTG_HC_PID_DATA2 1 ++#define DWC_OTG_HC_PID_DATA1 2 ++#define DWC_OTG_HC_PID_MDATA 3 ++#define DWC_OTG_HC_PID_SETUP 3 ++ ++ /** Number of periodic transactions per (micro)frame */ ++ unsigned multi_count:2; ++ ++ /** @name Transfer State */ ++ /** @{ */ ++ ++ /** Pointer to the current transfer buffer position. */ ++ uint8_t *xfer_buff; ++ /** ++ * In Buffer DMA mode this buffer will be used ++ * if xfer_buff is not DWORD aligned. ++ */ ++ dwc_dma_t align_buff; ++ /** Total number of bytes to transfer. */ ++ uint32_t xfer_len; ++ /** Number of bytes transferred so far. */ ++ uint32_t xfer_count; ++ /** Packet count at start of transfer.*/ ++ uint16_t start_pkt_count; ++ ++ /** ++ * Flag to indicate whether the transfer has been started. Set to 1 if ++ * it has been started, 0 otherwise. ++ */ ++ uint8_t xfer_started; ++ ++ /** ++ * Set to 1 to indicate that a PING request should be issued on this ++ * channel. If 0, process normally. ++ */ ++ uint8_t do_ping; ++ ++ /** ++ * Set to 1 to indicate that the error count for this transaction is ++ * non-zero. Set to 0 if the error count is 0. ++ */ ++ uint8_t error_state; ++ ++ /** ++ * Set to 1 to indicate that this channel should be halted the next ++ * time a request is queued for the channel. This is necessary in ++ * slave mode if no request queue space is available when an attempt ++ * is made to halt the channel. ++ */ ++ uint8_t halt_on_queue; ++ ++ /** ++ * Set to 1 if the host channel has been halted, but the core is not ++ * finished flushing queued requests. Otherwise 0. ++ */ ++ uint8_t halt_pending; ++ ++ /** ++ * Reason for halting the host channel. ++ */ ++ dwc_otg_halt_status_e halt_status; ++ ++ /* ++ * Split settings for the host channel ++ */ ++ uint8_t do_split; /**< Enable split for the channel */ ++ uint8_t complete_split; /**< Enable complete split */ ++ uint8_t hub_addr; /**< Address of high speed hub */ ++ ++ uint8_t port_addr; /**< Port of the low/full speed device */ ++ /** Split transaction position ++ * One of the following values: ++ * - DWC_HCSPLIT_XACTPOS_MID ++ * - DWC_HCSPLIT_XACTPOS_BEGIN ++ * - DWC_HCSPLIT_XACTPOS_END ++ * - DWC_HCSPLIT_XACTPOS_ALL */ ++ uint8_t xact_pos; ++ ++ /** Set when the host channel does a short read. */ ++ uint8_t short_read; ++ ++ /** ++ * Number of requests issued for this channel since it was assigned to ++ * the current transfer (not counting PINGs). ++ */ ++ uint8_t requests; ++ ++ /** ++ * Queue Head for the transfer being processed by this channel. ++ */ ++ struct dwc_otg_qh *qh; ++ ++ /** @} */ ++ ++ /** Entry in list of host channels. */ ++ DWC_CIRCLEQ_ENTRY(dwc_hc) hc_list_entry; ++ ++ /** @name Descriptor DMA support */ ++ /** @{ */ ++ ++ /** Number of Transfer Descriptors */ ++ uint16_t ntd; ++ ++ /** Descriptor List DMA address */ ++ dwc_dma_t desc_list_addr; ++ ++ /** Scheduling micro-frame bitmap. */ ++ uint8_t schinfo; ++ ++ /** @} */ ++} dwc_hc_t; ++ ++/** ++ * The following parameters may be specified when starting the module. These ++ * parameters define how the DWC_otg controller should be configured. ++ */ ++typedef struct dwc_otg_core_params { ++ int32_t opt; ++ ++ /** ++ * Specifies the OTG capabilities. The driver will automatically ++ * detect the value for this parameter if none is specified. ++ * 0 - HNP and SRP capable (default) ++ * 1 - SRP Only capable ++ * 2 - No HNP/SRP capable ++ */ ++ int32_t otg_cap; ++ ++ /** ++ * Specifies whether to use slave or DMA mode for accessing the data ++ * FIFOs. The driver will automatically detect the value for this ++ * parameter if none is specified. ++ * 0 - Slave ++ * 1 - DMA (default, if available) ++ */ ++ int32_t dma_enable; ++ ++ /** ++ * When DMA mode is enabled specifies whether to use address DMA or DMA ++ * Descriptor mode for accessing the data FIFOs in device mode. The driver ++ * will automatically detect the value for this if none is specified. ++ * 0 - address DMA ++ * 1 - DMA Descriptor(default, if available) ++ */ ++ int32_t dma_desc_enable; ++ /** The DMA Burst size (applicable only for External DMA ++ * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32) ++ */ ++ int32_t dma_burst_size; /* Translate this to GAHBCFG values */ ++ ++ /** ++ * Specifies the maximum speed of operation in host and device mode. ++ * The actual speed depends on the speed of the attached device and ++ * the value of phy_type. The actual speed depends on the speed of the ++ * attached device. ++ * 0 - High Speed (default) ++ * 1 - Full Speed ++ */ ++ int32_t speed; ++ /** Specifies whether low power mode is supported when attached ++ * to a Full Speed or Low Speed device in host mode. ++ * 0 - Don't support low power mode (default) ++ * 1 - Support low power mode ++ */ ++ int32_t host_support_fs_ls_low_power; ++ ++ /** Specifies the PHY clock rate in low power mode when connected to a ++ * Low Speed device in host mode. This parameter is applicable only if ++ * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS ++ * then defaults to 6 MHZ otherwise 48 MHZ. ++ * ++ * 0 - 48 MHz ++ * 1 - 6 MHz ++ */ ++ int32_t host_ls_low_power_phy_clk; ++ ++ /** ++ * 0 - Use cC FIFO size parameters ++ * 1 - Allow dynamic FIFO sizing (default) ++ */ ++ int32_t enable_dynamic_fifo; ++ ++ /** Total number of 4-byte words in the data FIFO memory. This ++ * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic ++ * Tx FIFOs. ++ * 32 to 32768 (default 8192) ++ * Note: The total FIFO memory depth in the FPGA configuration is 8192. ++ */ ++ int32_t data_fifo_size; ++ ++ /** Number of 4-byte words in the Rx FIFO in device mode when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1064) ++ */ ++ int32_t dev_rx_fifo_size; ++ ++ /** Number of 4-byte words in the non-periodic Tx FIFO in device mode ++ * when dynamic FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++ int32_t dev_nperio_tx_fifo_size; ++ ++ /** Number of 4-byte words in each of the periodic Tx FIFOs in device ++ * mode when dynamic FIFO sizing is enabled. ++ * 4 to 768 (default 256) ++ */ ++ uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS]; ++ ++ /** Number of 4-byte words in the Rx FIFO in host mode when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++ int32_t host_rx_fifo_size; ++ ++ /** Number of 4-byte words in the non-periodic Tx FIFO in host mode ++ * when Dynamic FIFO sizing is enabled in the core. ++ * 16 to 32768 (default 1024) ++ */ ++ int32_t host_nperio_tx_fifo_size; ++ ++ /** Number of 4-byte words in the host periodic Tx FIFO when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++ int32_t host_perio_tx_fifo_size; ++ ++ /** The maximum transfer size supported in bytes. ++ * 2047 to 65,535 (default 65,535) ++ */ ++ int32_t max_transfer_size; ++ ++ /** The maximum number of packets in a transfer. ++ * 15 to 511 (default 511) ++ */ ++ int32_t max_packet_count; ++ ++ /** The number of host channel registers to use. ++ * 1 to 16 (default 12) ++ * Note: The FPGA configuration supports a maximum of 12 host channels. ++ */ ++ int32_t host_channels; ++ ++ /** The number of endpoints in addition to EP0 available for device ++ * mode operations. ++ * 1 to 15 (default 6 IN and OUT) ++ * Note: The FPGA configuration supports a maximum of 6 IN and OUT ++ * endpoints in addition to EP0. ++ */ ++ int32_t dev_endpoints; ++ ++ /** ++ * Specifies the type of PHY interface to use. By default, the driver ++ * will automatically detect the phy_type. ++ * ++ * 0 - Full Speed PHY ++ * 1 - UTMI+ (default) ++ * 2 - ULPI ++ */ ++ int32_t phy_type; ++ ++ /** ++ * Specifies the UTMI+ Data Width. This parameter is ++ * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI ++ * PHY_TYPE, this parameter indicates the data width between ++ * the MAC and the ULPI Wrapper.) Also, this parameter is ++ * applicable only if the OTG_HSPHY_WIDTH cC parameter was set ++ * to "8 and 16 bits", meaning that the core has been ++ * configured to work at either data path width. ++ * ++ * 8 or 16 bits (default 16) ++ */ ++ int32_t phy_utmi_width; ++ ++ /** ++ * Specifies whether the ULPI operates at double or single ++ * data rate. This parameter is only applicable if PHY_TYPE is ++ * ULPI. ++ * ++ * 0 - single data rate ULPI interface with 8 bit wide data ++ * bus (default) ++ * 1 - double data rate ULPI interface with 4 bit wide data ++ * bus ++ */ ++ int32_t phy_ulpi_ddr; ++ ++ /** ++ * Specifies whether to use the internal or external supply to ++ * drive the vbus with a ULPI phy. ++ */ ++ int32_t phy_ulpi_ext_vbus; ++ ++ /** ++ * Specifies whether to use the I2Cinterface for full speed PHY. This ++ * parameter is only applicable if PHY_TYPE is FS. ++ * 0 - No (default) ++ * 1 - Yes ++ */ ++ int32_t i2c_enable; ++ ++ int32_t ulpi_fs_ls; ++ ++ int32_t ts_dline; ++ ++ /** ++ * Specifies whether dedicated transmit FIFOs are ++ * enabled for non periodic IN endpoints in device mode ++ * 0 - No ++ * 1 - Yes ++ */ ++ int32_t en_multiple_tx_fifo; ++ ++ /** Number of 4-byte words in each of the Tx FIFOs in device ++ * mode when dynamic FIFO sizing is enabled. ++ * 4 to 768 (default 256) ++ */ ++ uint32_t dev_tx_fifo_size[MAX_TX_FIFOS]; ++ ++ /** Thresholding enable flag- ++ * bit 0 - enable non-ISO Tx thresholding ++ * bit 1 - enable ISO Tx thresholding ++ * bit 2 - enable Rx thresholding ++ */ ++ uint32_t thr_ctl; ++ ++ /** Thresholding length for Tx ++ * FIFOs in 32 bit DWORDs ++ */ ++ uint32_t tx_thr_length; ++ ++ /** Thresholding length for Rx ++ * FIFOs in 32 bit DWORDs ++ */ ++ uint32_t rx_thr_length; ++ ++ /** ++ * Specifies whether LPM (Link Power Management) support is enabled ++ */ ++ int32_t lpm_enable; ++ ++ /** ++ * Specifies whether LPM Errata (Link Power Management) support is enabled ++ */ ++ int32_t besl_enable; ++ ++ /** ++ * Specifies the baseline besl value ++ */ ++ int32_t baseline_besl; ++ ++ /** ++ * Specifies the deep besl value ++ */ ++ int32_t deep_besl; ++ /** Per Transfer Interrupt ++ * mode enable flag ++ * 1 - Enabled ++ * 0 - Disabled ++ */ ++ int32_t pti_enable; ++ ++ /** Multi Processor Interrupt ++ * mode enable flag ++ * 1 - Enabled ++ * 0 - Disabled ++ */ ++ int32_t mpi_enable; ++ ++ /** IS_USB Capability ++ * 1 - Enabled ++ * 0 - Disabled ++ */ ++ int32_t ic_usb_cap; ++ ++ /** AHB Threshold Ratio ++ * 2'b00 AHB Threshold = MAC Threshold ++ * 2'b01 AHB Threshold = 1/2 MAC Threshold ++ * 2'b10 AHB Threshold = 1/4 MAC Threshold ++ * 2'b11 AHB Threshold = 1/8 MAC Threshold ++ */ ++ int32_t ahb_thr_ratio; ++ ++ /** ADP Support ++ * 1 - Enabled ++ * 0 - Disabled ++ */ ++ int32_t adp_supp_enable; ++ ++ /** HFIR Reload Control ++ * 0 - The HFIR cannot be reloaded dynamically. ++ * 1 - Allow dynamic reloading of the HFIR register during runtime. ++ */ ++ int32_t reload_ctl; ++ ++ /** DCFG: Enable device Out NAK ++ * 0 - The core does not set NAK after Bulk Out transfer complete. ++ * 1 - The core sets NAK after Bulk OUT transfer complete. ++ */ ++ int32_t dev_out_nak; ++ ++ /** DCFG: Enable Continue on BNA ++ * After receiving BNA interrupt the core disables the endpoint,when the ++ * endpoint is re-enabled by the application the core starts processing ++ * 0 - from the DOEPDMA descriptor ++ * 1 - from the descriptor which received the BNA. ++ */ ++ int32_t cont_on_bna; ++ ++ /** GAHBCFG: AHB Single Support ++ * This bit when programmed supports SINGLE transfers for remainder ++ * data in a transfer for DMA mode of operation. ++ * 0 - in this case the remainder data will be sent using INCR burst size. ++ * 1 - in this case the remainder data will be sent using SINGLE burst size. ++ */ ++ int32_t ahb_single; ++ ++ /** Core Power down mode ++ * 0 - No Power Down is enabled ++ * 1 - Reserved ++ * 2 - Complete Power Down (Hibernation) ++ */ ++ int32_t power_down; ++ ++ /** OTG revision supported ++ * 0 - OTG 1.3 revision ++ * 1 - OTG 2.0 revision ++ */ ++ int32_t otg_ver; ++ ++} dwc_otg_core_params_t; ++ ++#ifdef DEBUG ++struct dwc_otg_core_if; ++typedef struct hc_xfer_info { ++ struct dwc_otg_core_if *core_if; ++ dwc_hc_t *hc; ++} hc_xfer_info_t; ++#endif ++ ++typedef struct ep_xfer_info { ++ struct dwc_otg_core_if *core_if; ++ dwc_ep_t *ep; ++ uint8_t state; ++} ep_xfer_info_t; ++/* ++ * Device States ++ */ ++typedef enum dwc_otg_lx_state { ++ /** On state */ ++ DWC_OTG_L0, ++ /** LPM sleep state*/ ++ DWC_OTG_L1, ++ /** USB suspend state*/ ++ DWC_OTG_L2, ++ /** Off state*/ ++ DWC_OTG_L3 ++} dwc_otg_lx_state_e; ++ ++struct dwc_otg_global_regs_backup { ++ uint32_t gotgctl_local; ++ uint32_t gintmsk_local; ++ uint32_t gahbcfg_local; ++ uint32_t gusbcfg_local; ++ uint32_t grxfsiz_local; ++ uint32_t gnptxfsiz_local; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ uint32_t glpmcfg_local; ++#endif ++ uint32_t gi2cctl_local; ++ uint32_t hptxfsiz_local; ++ uint32_t pcgcctl_local; ++ uint32_t gdfifocfg_local; ++ uint32_t dtxfsiz_local[MAX_EPS_CHANNELS]; ++ uint32_t gpwrdn_local; ++ uint32_t xhib_pcgcctl; ++ uint32_t xhib_gpwrdn; ++}; ++ ++struct dwc_otg_host_regs_backup { ++ uint32_t hcfg_local; ++ uint32_t haintmsk_local; ++ uint32_t hcintmsk_local[MAX_EPS_CHANNELS]; ++ uint32_t hprt0_local; ++ uint32_t hfir_local; ++}; ++ ++struct dwc_otg_dev_regs_backup { ++ uint32_t dcfg; ++ uint32_t dctl; ++ uint32_t daintmsk; ++ uint32_t diepmsk; ++ uint32_t doepmsk; ++ uint32_t diepctl[MAX_EPS_CHANNELS]; ++ uint32_t dieptsiz[MAX_EPS_CHANNELS]; ++ uint32_t diepdma[MAX_EPS_CHANNELS]; ++}; ++/** ++ * The dwc_otg_core_if structure contains information needed to manage ++ * the DWC_otg controller acting in either host or device mode. It ++ * represents the programming view of the controller as a whole. ++ */ ++struct dwc_otg_core_if { ++ /** Parameters that define how the core should be configured.*/ ++ dwc_otg_core_params_t *core_params; ++ ++ /** Core Global registers starting at offset 000h. */ ++ dwc_otg_core_global_regs_t *core_global_regs; ++ ++ /** Device-specific information */ ++ dwc_otg_dev_if_t *dev_if; ++ /** Host-specific information */ ++ dwc_otg_host_if_t *host_if; ++ ++ /** Value from SNPSID register */ ++ uint32_t snpsid; ++ ++ /* ++ * Set to 1 if the core PHY interface bits in USBCFG have been ++ * initialized. ++ */ ++ uint8_t phy_init_done; ++ ++ /* ++ * SRP Success flag, set by srp success interrupt in FS I2C mode ++ */ ++ uint8_t srp_success; ++ uint8_t srp_timer_started; ++ /** Timer for SRP. If it expires before SRP is successful ++ * clear the SRP. */ ++ dwc_timer_t *srp_timer; ++ ++#ifdef DWC_DEV_SRPCAP ++ /* This timer is needed to power on the hibernated host core if SRP is not ++ * initiated on connected SRP capable device for limited period of time ++ */ ++ uint8_t pwron_timer_started; ++ dwc_timer_t *pwron_timer; ++#endif ++ /* Common configuration information */ ++ /** Power and Clock Gating Control Register */ ++ volatile uint32_t *pcgcctl; ++#define DWC_OTG_PCGCCTL_OFFSET 0xE00 ++ ++ /** Push/pop addresses for endpoints or host channels.*/ ++ uint32_t *data_fifo[MAX_EPS_CHANNELS]; ++#define DWC_OTG_DATA_FIFO_OFFSET 0x1000 ++#define DWC_OTG_DATA_FIFO_SIZE 0x1000 ++ ++ /** Total RAM for FIFOs (Bytes) */ ++ uint16_t total_fifo_size; ++ /** Size of Rx FIFO (Bytes) */ ++ uint16_t rx_fifo_size; ++ /** Size of Non-periodic Tx FIFO (Bytes) */ ++ uint16_t nperio_tx_fifo_size; ++ ++ /** 1 if DMA is enabled, 0 otherwise. */ ++ uint8_t dma_enable; ++ ++ /** 1 if DMA descriptor is enabled, 0 otherwise. */ ++ uint8_t dma_desc_enable; ++ ++ /** 1 if PTI Enhancement mode is enabled, 0 otherwise. */ ++ uint8_t pti_enh_enable; ++ ++ /** 1 if MPI Enhancement mode is enabled, 0 otherwise. */ ++ uint8_t multiproc_int_enable; ++ ++ /** 1 if dedicated Tx FIFOs are enabled, 0 otherwise. */ ++ uint8_t en_multiple_tx_fifo; ++ ++ /** Set to 1 if multiple packets of a high-bandwidth transfer is in ++ * process of being queued */ ++ uint8_t queuing_high_bandwidth; ++ ++ /** Hardware Configuration -- stored here for convenience.*/ ++ hwcfg1_data_t hwcfg1; ++ hwcfg2_data_t hwcfg2; ++ hwcfg3_data_t hwcfg3; ++ hwcfg4_data_t hwcfg4; ++ fifosize_data_t hptxfsiz; ++ ++ /** Host and Device Configuration -- stored here for convenience.*/ ++ hcfg_data_t hcfg; ++ dcfg_data_t dcfg; ++ ++ /** The operational State, during transations ++ * (a_host>>a_peripherial and b_device=>b_host) this may not ++ * match the core but allows the software to determine ++ * transitions. ++ */ ++ uint8_t op_state; ++ ++ /** Test mode for PET testing */ ++ uint8_t test_mode; ++ ++ /** ++ * Set to 1 if the HCD needs to be restarted on a session request ++ * interrupt. This is required if no connector ID status change has ++ * occurred since the HCD was last disconnected. ++ */ ++ uint8_t restart_hcd_on_session_req; ++ ++ /** HCD callbacks */ ++ /** A-Device is a_host */ ++#define A_HOST (1) ++ /** A-Device is a_suspend */ ++#define A_SUSPEND (2) ++ /** A-Device is a_peripherial */ ++#define A_PERIPHERAL (3) ++ /** B-Device is operating as a Peripheral. */ ++#define B_PERIPHERAL (4) ++ /** B-Device is operating as a Host. */ ++#define B_HOST (5) ++ ++ /** HCD callbacks */ ++ struct dwc_otg_cil_callbacks *hcd_cb; ++ /** PCD callbacks */ ++ struct dwc_otg_cil_callbacks *pcd_cb; ++ ++ /** Device mode Periodic Tx FIFO Mask */ ++ uint32_t p_tx_msk; ++ /** Device mode Periodic Tx FIFO Mask */ ++ uint32_t tx_msk; ++ ++ /** Workqueue object used for handling several interrupts */ ++ dwc_workq_t *wq_otg; ++ ++ /** Timer object used for handling "Wakeup Detected" Interrupt */ ++ dwc_timer_t *wkp_timer; ++ /** This arrays used for debug purposes for DEV OUT NAK enhancement */ ++ uint32_t start_doeptsiz_val[MAX_EPS_CHANNELS]; ++ ep_xfer_info_t ep_xfer_info[MAX_EPS_CHANNELS]; ++ dwc_timer_t *ep_xfer_timer[MAX_EPS_CHANNELS]; ++#ifdef DEBUG ++ uint32_t start_hcchar_val[MAX_EPS_CHANNELS]; ++ ++ hc_xfer_info_t hc_xfer_info[MAX_EPS_CHANNELS]; ++ dwc_timer_t *hc_xfer_timer[MAX_EPS_CHANNELS]; ++ ++ uint32_t hfnum_7_samples; ++ uint64_t hfnum_7_frrem_accum; ++ uint32_t hfnum_0_samples; ++ uint64_t hfnum_0_frrem_accum; ++ uint32_t hfnum_other_samples; ++ uint64_t hfnum_other_frrem_accum; ++#endif ++ ++#ifdef DWC_UTE_CFI ++ uint16_t pwron_rxfsiz; ++ uint16_t pwron_gnptxfsiz; ++ uint16_t pwron_txfsiz[15]; ++ ++ uint16_t init_rxfsiz; ++ uint16_t init_gnptxfsiz; ++ uint16_t init_txfsiz[15]; ++#endif ++ ++ /** Lx state of device */ ++ dwc_otg_lx_state_e lx_state; ++ ++ /** Saved Core Global registers */ ++ struct dwc_otg_global_regs_backup *gr_backup; ++ /** Saved Host registers */ ++ struct dwc_otg_host_regs_backup *hr_backup; ++ /** Saved Device registers */ ++ struct dwc_otg_dev_regs_backup *dr_backup; ++ ++ /** Power Down Enable */ ++ uint32_t power_down; ++ ++ /** ADP support Enable */ ++ uint32_t adp_enable; ++ ++ /** ADP structure object */ ++ dwc_otg_adp_t adp; ++ ++ /** hibernation/suspend flag */ ++ int hibernation_suspend; ++ ++ /** Device mode extended hibernation flag */ ++ int xhib; ++ ++ /** OTG revision supported */ ++ uint32_t otg_ver; ++ ++ /** OTG status flag used for HNP polling */ ++ uint8_t otg_sts; ++ ++ /** Pointer to either hcd->lock or pcd->lock */ ++ dwc_spinlock_t *lock; ++ ++ /** Start predict NextEP based on Learning Queue if equal 1, ++ * also used as counter of disabled NP IN EP's */ ++ uint8_t start_predict; ++ ++ /** NextEp sequence, including EP0: nextep_seq[] = EP if non-periodic and ++ * active, 0xff otherwise */ ++ uint8_t nextep_seq[MAX_EPS_CHANNELS]; ++ ++ /** Index of fisrt EP in nextep_seq array which should be re-enabled **/ ++ uint8_t first_in_nextep_seq; ++ ++ /** Frame number while entering to ISR - needed for ISOCs **/ ++ uint32_t frame_num; ++ ++ /** Flag to not perform ADP probing if IDSTS event happened */ ++ uint8_t stop_adpprb; ++ ++}; ++ ++#ifdef DEBUG ++/* ++ * This function is called when transfer is timed out. ++ */ ++extern void hc_xfer_timeout(void *ptr); ++#endif ++ ++/* ++ * This function is called when transfer is timed out on endpoint. ++ */ ++extern void ep_xfer_timeout(void *ptr); ++ ++/* ++ * The following functions are functions for works ++ * using during handling some interrupts ++ */ ++extern void w_conn_id_status_change(void *p); ++ ++extern void w_wakeup_detected(void *p); ++ ++/** Saves global register values into system memory. */ ++extern int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if); ++/** Saves device register values into system memory. */ ++extern int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if); ++/** Saves host register values into system memory. */ ++extern int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if); ++/** Restore global register values. */ ++extern int dwc_otg_restore_global_regs(dwc_otg_core_if_t * core_if); ++/** Restore host register values. */ ++extern int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset); ++/** Restore device register values. */ ++extern int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, ++ int rem_wakeup); ++extern int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if); ++extern int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode, ++ int is_host); ++ ++extern int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int restore_mode, int reset); ++extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int rem_wakeup, int reset); ++ ++/* ++ * The following functions support initialization of the CIL driver component ++ * and the DWC_otg controller. ++ */ ++extern void dwc_otg_core_host_init(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_core_dev_init(dwc_otg_core_if_t * _core_if); ++ ++/** @name Device CIL Functions ++ * The following functions support managing the DWC_otg controller in device ++ * mode. ++ */ ++/**@{*/ ++extern void dwc_otg_wakeup(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_read_setup_packet(dwc_otg_core_if_t * _core_if, ++ uint32_t * _dest); ++extern uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_ep0_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep); ++extern void dwc_otg_ep_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep); ++extern void dwc_otg_ep_deactivate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep); ++extern void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * _core_if, ++ dwc_ep_t * _ep); ++extern void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * _core_if, ++ dwc_ep_t * _ep); ++extern void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * _core_if, ++ dwc_ep_t * _ep); ++extern void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * _core_if, ++ dwc_ep_t * _ep); ++extern void dwc_otg_ep_write_packet(dwc_otg_core_if_t * _core_if, ++ dwc_ep_t * _ep, int _dma); ++extern void dwc_otg_ep_set_stall(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep); ++extern void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * _core_if, ++ dwc_ep_t * _ep); ++extern void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * _core_if); ++ ++#ifdef DWC_EN_ISOC ++extern void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * ep); ++extern void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * ep); ++#endif /* DWC_EN_ISOC */ ++/**@}*/ ++ ++/** @name Host CIL Functions ++ * The following functions support managing the DWC_otg controller in host ++ * mode. ++ */ ++/**@{*/ ++extern void dwc_otg_hc_init(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc); ++extern void dwc_otg_hc_halt(dwc_otg_core_if_t * _core_if, ++ dwc_hc_t * _hc, dwc_otg_halt_status_e _halt_status); ++extern void dwc_otg_hc_cleanup(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc); ++extern void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * _core_if, ++ dwc_hc_t * _hc); ++extern int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * _core_if, ++ dwc_hc_t * _hc); ++extern void dwc_otg_hc_do_ping(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc); ++extern void dwc_otg_hc_write_packet(dwc_otg_core_if_t * _core_if, ++ dwc_hc_t * _hc); ++extern void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * _core_if); ++ ++extern void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, ++ dwc_hc_t * hc); ++ ++extern uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if); ++extern int dwc_otg_check_haps_status(dwc_otg_core_if_t * core_if); ++ ++/* Macro used to clear one channel interrupt */ ++#define clear_hc_int(_hc_regs_, _intr_) \ ++do { \ ++ hcint_data_t hcint_clear = {.d32 = 0}; \ ++ hcint_clear.b._intr_ = 1; \ ++ DWC_WRITE_REG32(&(_hc_regs_)->hcint, hcint_clear.d32); \ ++} while (0) ++ ++/* ++ * Macro used to disable one channel interrupt. Channel interrupts are ++ * disabled when the channel is halted or released by the interrupt handler. ++ * There is no need to handle further interrupts of that type until the ++ * channel is re-assigned. In fact, subsequent handling may cause crashes ++ * because the channel structures are cleaned up when the channel is released. ++ */ ++#define disable_hc_int(_hc_regs_, _intr_) \ ++do { \ ++ hcintmsk_data_t hcintmsk = {.d32 = 0}; \ ++ hcintmsk.b._intr_ = 1; \ ++ DWC_MODIFY_REG32(&(_hc_regs_)->hcintmsk, hcintmsk.d32, 0); \ ++} while (0) ++ ++/** ++ * This function Reads HPRT0 in preparation to modify. It keeps the ++ * WC bits 0 so that if they are read as 1, they won't clear when you ++ * write it back ++ */ ++static inline uint32_t dwc_otg_read_hprt0(dwc_otg_core_if_t * _core_if) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = DWC_READ_REG32(_core_if->host_if->hprt0); ++ hprt0.b.prtena = 0; ++ hprt0.b.prtconndet = 0; ++ hprt0.b.prtenchng = 0; ++ hprt0.b.prtovrcurrchng = 0; ++ return hprt0.d32; ++} ++ ++/**@}*/ ++ ++/** @name Common CIL Functions ++ * The following functions support managing the DWC_otg controller in either ++ * device or host mode. ++ */ ++/**@{*/ ++ ++extern void dwc_otg_read_packet(dwc_otg_core_if_t * core_if, ++ uint8_t * dest, uint16_t bytes); ++ ++extern void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * _core_if, const int _num); ++extern void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_core_reset(dwc_otg_core_if_t * _core_if); ++ ++/** ++ * This function returns the Core Interrupt register. ++ */ ++static inline uint32_t dwc_otg_read_core_intr(dwc_otg_core_if_t * core_if) ++{ ++ return (DWC_READ_REG32(&core_if->core_global_regs->gintsts) & ++ DWC_READ_REG32(&core_if->core_global_regs->gintmsk)); ++} ++ ++/** ++ * This function returns the OTG Interrupt register. ++ */ ++static inline uint32_t dwc_otg_read_otg_intr(dwc_otg_core_if_t * core_if) ++{ ++ return (DWC_READ_REG32(&core_if->core_global_regs->gotgint)); ++} ++ ++/** ++ * This function reads the Device All Endpoints Interrupt register and ++ * returns the IN endpoint interrupt bits. ++ */ ++static inline uint32_t dwc_otg_read_dev_all_in_ep_intr(dwc_otg_core_if_t * ++ core_if) ++{ ++ ++ uint32_t v; ++ ++ if (core_if->multiproc_int_enable) { ++ v = DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->deachint) & ++ DWC_READ_REG32(&core_if-> ++ dev_if->dev_global_regs->deachintmsk); ++ } else { ++ v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) & ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk); ++ } ++ return (v & 0xffff); ++} ++ ++/** ++ * This function reads the Device All Endpoints Interrupt register and ++ * returns the OUT endpoint interrupt bits. ++ */ ++static inline uint32_t dwc_otg_read_dev_all_out_ep_intr(dwc_otg_core_if_t * ++ core_if) ++{ ++ uint32_t v; ++ ++ if (core_if->multiproc_int_enable) { ++ v = DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->deachint) & ++ DWC_READ_REG32(&core_if-> ++ dev_if->dev_global_regs->deachintmsk); ++ } else { ++ v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) & ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk); ++ } ++ ++ return ((v & 0xffff0000) >> 16); ++} ++ ++/** ++ * This function returns the Device IN EP Interrupt register ++ */ ++static inline uint32_t dwc_otg_read_dev_in_ep_intr(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * ep) ++{ ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ uint32_t v, msk, emp; ++ ++ if (core_if->multiproc_int_enable) { ++ msk = ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->diepeachintmsk[ep->num]); ++ emp = ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->dtknqr4_fifoemptymsk); ++ msk |= ((emp >> ep->num) & 0x1) << 7; ++ v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk; ++ } else { ++ msk = DWC_READ_REG32(&dev_if->dev_global_regs->diepmsk); ++ emp = ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->dtknqr4_fifoemptymsk); ++ msk |= ((emp >> ep->num) & 0x1) << 7; ++ v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk; ++ } ++ ++ return v; ++} ++ ++/** ++ * This function returns the Device OUT EP Interrupt register ++ */ ++static inline uint32_t dwc_otg_read_dev_out_ep_intr(dwc_otg_core_if_t * ++ _core_if, dwc_ep_t * _ep) ++{ ++ dwc_otg_dev_if_t *dev_if = _core_if->dev_if; ++ uint32_t v; ++ doepmsk_data_t msk = {.d32 = 0 }; ++ ++ if (_core_if->multiproc_int_enable) { ++ msk.d32 = ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->doepeachintmsk[_ep->num]); ++ if (_core_if->pti_enh_enable) { ++ msk.b.pktdrpsts = 1; ++ } ++ v = DWC_READ_REG32(&dev_if-> ++ out_ep_regs[_ep->num]->doepint) & msk.d32; ++ } else { ++ msk.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->doepmsk); ++ if (_core_if->pti_enh_enable) { ++ msk.b.pktdrpsts = 1; ++ } ++ v = DWC_READ_REG32(&dev_if-> ++ out_ep_regs[_ep->num]->doepint) & msk.d32; ++ } ++ return v; ++} ++ ++/** ++ * This function returns the Host All Channel Interrupt register ++ */ ++static inline uint32_t dwc_otg_read_host_all_channels_intr(dwc_otg_core_if_t * ++ _core_if) ++{ ++ return (DWC_READ_REG32(&_core_if->host_if->host_global_regs->haint)); ++} ++ ++static inline uint32_t dwc_otg_read_host_channel_intr(dwc_otg_core_if_t * ++ _core_if, dwc_hc_t * _hc) ++{ ++ return (DWC_READ_REG32 ++ (&_core_if->host_if->hc_regs[_hc->hc_num]->hcint)); ++} ++ ++/** ++ * This function returns the mode of the operation, host or device. ++ * ++ * @return 0 - Device Mode, 1 - Host Mode ++ */ ++static inline uint32_t dwc_otg_mode(dwc_otg_core_if_t * _core_if) ++{ ++ return (DWC_READ_REG32(&_core_if->core_global_regs->gintsts) & 0x1); ++} ++ ++/**@}*/ ++ ++/** ++ * DWC_otg CIL callback structure. This structure allows the HCD and ++ * PCD to register functions used for starting and stopping the PCD ++ * and HCD for role change on for a DRD. ++ */ ++typedef struct dwc_otg_cil_callbacks { ++ /** Start function for role change */ ++ int (*start) (void *_p); ++ /** Stop Function for role change */ ++ int (*stop) (void *_p); ++ /** Disconnect Function for role change */ ++ int (*disconnect) (void *_p); ++ /** Resume/Remote wakeup Function */ ++ int (*resume_wakeup) (void *_p); ++ /** Suspend function */ ++ int (*suspend) (void *_p); ++ /** Session Start (SRP) */ ++ int (*session_start) (void *_p); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ /** Sleep (switch to L0 state) */ ++ int (*sleep) (void *_p); ++#endif ++ /** Pointer passed to start() and stop() */ ++ void *p; ++} dwc_otg_cil_callbacks_t; ++ ++extern void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * _core_if, ++ dwc_otg_cil_callbacks_t * _cb, ++ void *_p); ++extern void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * _core_if, ++ dwc_otg_cil_callbacks_t * _cb, ++ void *_p); ++ ++void dwc_otg_initiate_srp(void * core_if); ++ ++////////////////////////////////////////////////////////////////////// ++/** Start the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_start(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->start) { ++ core_if->hcd_cb->start(core_if->hcd_cb->p); ++ } ++} ++ ++/** Stop the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_stop(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->stop) { ++ core_if->hcd_cb->stop(core_if->hcd_cb->p); ++ } ++} ++ ++/** Disconnect the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_disconnect(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->disconnect) { ++ core_if->hcd_cb->disconnect(core_if->hcd_cb->p); ++ } ++} ++ ++/** Inform the HCD the a New Session has begun. Helper function for ++ * using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_session_start(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->session_start) { ++ core_if->hcd_cb->session_start(core_if->hcd_cb->p); ++ } ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++/** ++ * Inform the HCD about LPM sleep. ++ * Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_sleep(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->sleep) { ++ core_if->hcd_cb->sleep(core_if->hcd_cb->p); ++ } ++} ++#endif ++ ++/** Resume the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_resume(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->resume_wakeup) { ++ core_if->hcd_cb->resume_wakeup(core_if->hcd_cb->p); ++ } ++} ++ ++/** Start the PCD. Helper function for using the PCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_pcd_start(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->start) { ++ core_if->pcd_cb->start(core_if->pcd_cb->p); ++ } ++} ++ ++/** Stop the PCD. Helper function for using the PCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_pcd_stop(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->stop) { ++ core_if->pcd_cb->stop(core_if->pcd_cb->p); ++ } ++} ++ ++/** Suspend the PCD. Helper function for using the PCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_pcd_suspend(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->suspend) { ++ core_if->pcd_cb->suspend(core_if->pcd_cb->p); ++ } ++} ++ ++/** Resume the PCD. Helper function for using the PCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_pcd_resume(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); ++ } ++} ++ ++////////////////////////////////////////////////////////////////////// ++ ++#endif +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_cil_intr.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_cil_intr.c +new file mode 100644 +index 0000000..46c4692 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_cil_intr.c +@@ -0,0 +1,1738 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $ ++ * $Revision: #37 $ ++ * $Date: 2013/04/16 $ ++ * $Change: 2207267 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ * The Core Interface Layer provides basic services for accessing and ++ * managing the DWC_otg hardware. These services are used by both the ++ * Host Controller Driver and the Peripheral Controller Driver. ++ * ++ * This file contains the Common Interrupt handlers. ++ */ ++#include "dwc_os.h" ++#include "dwc_otg_regs.h" ++#include "dwc_otg_cil.h" ++#include "dwc_otg_driver.h" ++#include "dwc_otg_pcd.h" ++#include "dwc_otg_hcd.h" ++ ++#ifdef DEBUG ++inline const char *op_state_str(dwc_otg_core_if_t * core_if) ++{ ++ return (core_if->op_state == A_HOST ? "a_host" : ++ (core_if->op_state == A_SUSPEND ? "a_suspend" : ++ (core_if->op_state == A_PERIPHERAL ? "a_peripheral" : ++ (core_if->op_state == B_PERIPHERAL ? "b_peripheral" : ++ (core_if->op_state == B_HOST ? "b_host" : "unknown"))))); ++} ++#endif ++ ++/** This function will log a debug message ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_handle_mode_mismatch_intr(dwc_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ DWC_WARN("Mode Mismatch Interrupt: currently in %s mode\n", ++ dwc_otg_mode(core_if) ? "Host" : "Device"); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.modemismatch = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This function handles the OTG Interrupts. It reads the OTG ++ * Interrupt Register (GOTGINT) to determine what interrupt has ++ * occurred. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gotgint_data_t gotgint; ++ gotgctl_data_t gotgctl; ++ gintmsk_data_t gintmsk; ++ gpwrdn_data_t gpwrdn; ++ ++ gotgint.d32 = DWC_READ_REG32(&global_regs->gotgint); ++ gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); ++ DWC_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32, ++ op_state_str(core_if)); ++ ++ if (gotgint.b.sesenddet) { ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "Session End Detected++ (%s)\n", ++ op_state_str(core_if)); ++ gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); ++ ++ if (core_if->op_state == B_HOST) { ++ if (core_if->adp_enable && DWC_WORKQ_PENDING(core_if->wq_otg)) { ++ ++ /* During ST_B_ADP test after HNP HSOTG tries to go to B_HOST ++ * mode but PET is not expecting fully functional host at that ++ * point and switches off the VBUS expecting immediate ADP probe */ ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_mdelay(20); ++ dwc_otg_adp_probe_start(core_if); ++ goto exit_interrupt; ++ } ++ cil_pcd_start(core_if); ++ core_if->op_state = B_PERIPHERAL; ++ } else { ++ /* If not B_HOST and Device HNP still set. HNP ++ * Did not succeed!*/ ++ if (gotgctl.b.devhnpen) { ++ DWC_DEBUGPL(DBG_ANY, "Session End Detected\n"); ++ __DWC_ERROR("Device Not Connected/Responding!\n"); ++ } ++ ++ /* If Session End Detected the B-Cable has ++ * been disconnected. */ ++ /* Reset PCD and Gadget driver to a ++ * clean state. */ ++ core_if->lx_state = DWC_OTG_L0; ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ ++ if (core_if->otg_ver) { ++ /** PET testing*/ ++ gotgctl.d32 = 0; ++ gotgctl.b.devhnpen = 1; ++ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ if (core_if->test_mode == 6) { ++ DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg, dwc_otg_initiate_srp, ++ core_if, 3000, "initate SRP"); //manukz: old value was 50 ++ core_if->test_mode = 0; ++ } else if (core_if->adp_enable) { ++ if (core_if->power_down == 2) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ } ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_otg_adp_sense_start(core_if); ++ } ++ } ++ } ++exit_interrupt: ++ if (core_if->otg_ver == 0) { ++ gotgctl.d32 = 0; ++ gotgctl.b.devhnpen = 1; ++ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ } ++ } ++ if (gotgint.b.sesreqsucstschng) { ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "Session Reqeust Success Status Change++\n"); ++ gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); ++ if (gotgctl.b.sesreqscs) { ++ ++ if ((core_if->core_params->phy_type == ++ DWC_PHY_TYPE_PARAM_FS) && (core_if->core_params->i2c_enable)) { ++ core_if->srp_success = 1; ++ } else { ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_resume(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ /* Clear Session Request */ ++ gotgctl.d32 = 0; ++ gotgctl.b.sesreq = 1; ++ DWC_MODIFY_REG32(&global_regs->gotgctl, ++ gotgctl.d32, 0); ++ } ++ } ++ } ++ if (gotgint.b.hstnegsucstschng) { ++ /* Print statements during the HNP interrupt handling ++ * can cause it to fail.*/ ++ gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); ++ /* WA for 3.00a- HW is not setting cur_mode, even sometimes ++ * this does not help*/ ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) ++ dwc_udelay(100); ++ if (gotgctl.b.hstnegscs) { ++ if (dwc_otg_is_host_mode(core_if)) { ++ core_if->op_state = B_HOST; ++ /* ++ * Need to disable SOF interrupt immediately. ++ * When switching from device to host, the PCD ++ * interrupt handler won't handle the ++ * interrupt if host mode is already set. The ++ * HCD interrupt handler won't get called if ++ * the HCD state is HALT. This means that the ++ * interrupt does not get handled and Linux ++ * complains loudly. ++ */ ++ gintmsk.d32 = 0; ++ gintmsk.b.sofintr = 1; ++ /* To avoid multiple USB Suspend interrupts during ++ * OTG 2.0 role change */ ++ if (core_if->otg_ver) ++ gintmsk.b.usbsuspend = 1; ++ DWC_MODIFY_REG32(&global_regs->gintmsk, ++ gintmsk.d32, 0); ++ /* Call callback function with spin lock released */ ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ /* ++ * Initialize the Core for Host mode. ++ */ ++ if (core_if->otg_ver) { ++ dwc_mdelay(100); ++ cil_hcd_start(core_if); ++ cil_hcd_session_start(core_if); ++ } else { ++ cil_hcd_start(core_if); ++ } ++ DWC_SPINLOCK(core_if->lock); ++ } ++ } else { ++ gotgctl.d32 = 0; ++ gotgctl.b.hnpreq = 1; ++ gotgctl.b.devhnpen = 1; ++ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ DWC_DEBUGPL(DBG_ANY, "HNP Failed\n"); ++ __DWC_ERROR("Device Not Connected/Responding\n"); ++ } ++ } ++ if (gotgint.b.hstnegdet) { ++ /* The disconnect interrupt is set at the same time as ++ * Host Negotiation Detected. During the mode ++ * switch all interrupts are cleared so the disconnect ++ * interrupt handler will not get executed. ++ */ ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "Host Negotiation Detected++ (%s)\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : ++ "Device")); ++ if (dwc_otg_is_device_mode(core_if)) { ++ DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n", ++ core_if->op_state); ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_hcd_disconnect(core_if); ++ cil_pcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ core_if->op_state = A_PERIPHERAL; ++ } else { ++ /* ++ * Need to disable SOF interrupt immediately. When ++ * switching from device to host, the PCD interrupt ++ * handler won't handle the interrupt if host mode is ++ * already set. The HCD interrupt handler won't get ++ * called if the HCD state is HALT. This means that ++ * the interrupt does not get handled and Linux ++ * complains loudly. ++ */ ++ gintmsk.d32 = 0; ++ gintmsk.b.sofintr = 1; ++ DWC_MODIFY_REG32(&global_regs->gintmsk, gintmsk.d32, 0); ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ cil_hcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ core_if->op_state = A_HOST; ++ } ++ } ++ if (gotgint.b.adevtoutchng) { ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "A-Device Timeout Change++\n"); ++ } ++ if (gotgint.b.debdone) { ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " "Debounce Done++\n"); ++ /* Need to power off VBUS after 10s if OTG2 non-hnp capable host*/ ++ if (core_if->otg_ver && core_if->op_state == A_PERIPHERAL) { ++ DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n"); ++ /* Clear the a_peripheral flag, back to a_host. */ ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ cil_hcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ core_if->op_state = A_HOST; ++ } ++ ++ if(core_if->otg_ver == 1) ++ cil_hcd_session_start(core_if); ++ } ++ ++ /* Clear GOTGINT */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, gotgint.d32); ++ ++ return 1; ++} ++ ++void w_conn_id_status_change(void *p) ++{ ++ dwc_otg_core_if_t *core_if = p; ++ uint32_t count = 0; ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ ++ gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32); ++ DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts); ++ ++ /* B-Device connector (Device Mode) */ ++ if (gotgctl.b.conidsts) { ++ gotgctl_data_t gotgctl_local; ++ /* Wait for switch to device mode. */ ++ while (!dwc_otg_is_device_mode(core_if)) { ++ gotgctl_local.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ DWC_DEBUGPL(DBG_ANY, "Waiting for Peripheral Mode, Mode=%s count = %d gotgctl=%08x\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : ++ "Peripheral"), count, gotgctl_local.d32); ++ dwc_mdelay(1); //vahrama previous value was 100 ++ if(!gotgctl_local.b.conidsts) ++ goto host; ++ if (++count > 10000) ++ break; ++ } ++ DWC_ASSERT(++count < 10000, ++ "Connection id status change timed out"); ++ core_if->op_state = B_PERIPHERAL; ++ if(core_if->otg_ver == 0) ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } else { ++host: ++ /* A-Device connector (Host Mode) */ ++ while (!dwc_otg_is_host_mode(core_if)) { ++ DWC_DEBUGPL(DBG_ANY,"Waiting for Host Mode, Mode=%s\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : ++ "Peripheral")); ++ dwc_mdelay(1); //vahrama previously was 100 ++ if (++count > 10000) ++ break; ++ } ++ DWC_ASSERT(++count < 10000, ++ "Connection id status change timed out"); ++ core_if->op_state = A_HOST; ++ /* ++ * Initialize the Core for Host mode. ++ */ ++ if (core_if->otg_ver) ++ /* To power off the bus in 10s from the beginning ++ * of test while denounce has not come yet */ ++ cil_hcd_session_start(core_if); ++ else ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++} ++ ++/** ++ * This function handles the Connector ID Status Change Interrupt. It ++ * reads the OTG Interrupt Register (GOTCTL) to determine whether this ++ * is a Device to Host Mode transition or a Host Mode to Device ++ * Transition. ++ * ++ * This only occurs when the cable is connected/removed from the PHY ++ * connector. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t * core_if) ++{ ++ ++ /* ++ * Need to disable SOF interrupt immediately. If switching from device ++ * to host, the PCD interrupt handler won't handle the interrupt if ++ * host mode is already set. The HCD interrupt handler won't get ++ * called if the HCD state is HALT. This means that the interrupt does ++ * not get handled and Linux complains loudly. ++ */ ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ gintsts_data_t gintsts = {.d32 = 0 }; ++ ++ gintmsk.b.sofintr = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0); ++ ++ DWC_DEBUGPL(DBG_CIL, ++ " ++Connector ID Status Change Interrupt++ (%s)\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : "Device")); ++ ++ DWC_SPINUNLOCK(core_if->lock); ++ ++ /* Needed to avoit conn_id_status change duplication */ ++ //if (core_if->otg_ver) ++ //dwc_mdelay(50); ++ /* ++ * Need to schedule a work, as there are possible DELAY function calls ++ * Release lock before scheduling workq as it holds spinlock during scheduling ++ */ ++ ++ DWC_WORKQ_SCHEDULE(core_if->wq_otg, w_conn_id_status_change, ++ core_if, "connection id status change"); ++ DWC_SPINLOCK(core_if->lock); ++ ++ /* Set flag and clear interrupt */ ++ gintsts.b.conidstschng = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that a device is initiating the Session ++ * Request Protocol to request the host to turn on bus power so a new ++ * session can begin. The handler responds by turning on bus power. If ++ * the DWC_otg controller is in low power mode, the handler brings the ++ * controller out of low power mode before turning on bus power. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ ++#ifndef DWC_HOST_ONLY ++ DWC_DEBUGPL(DBG_ANY, "++Session Request Interrupt++\n"); ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ DWC_DEBUGPL(DBG_PCD, "SRP: Device mode\n"); ++ gotgctl.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ if (gotgctl.b.sesreqscs) ++ DWC_PRINTF("SRP Success\n"); ++ else ++ DWC_PRINTF("SRP Fail\n"); ++ if (core_if->otg_ver) { ++ gotgctl.d32 = 0 ; ++ gotgctl.b.devhnpen = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, gotgctl.d32, 0); ++ } ++ } else { ++ hprt0_data_t hprt0; ++ DWC_PRINTF("SRP: Host mode\n"); ++ ++ /* Turn on the port power bit. */ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* Start the Connection timer. So a message can be displayed ++ * if connect does not occur within 10 seconds. */ ++ cil_hcd_session_start(core_if); ++ } ++#endif ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.sessreqintr = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++void w_wakeup_detected(void *p) ++{ ++ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) p; ++ /* ++ * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms ++ * so that OPT tests pass with all PHYs). ++ */ ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++#if 0 ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ /* Restart the Phy Clock */ ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ dwc_udelay(10); ++#endif //0 ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ DWC_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32); ++// dwc_mdelay(70); ++ hprt0.b.prtres = 0; /* Resume */ ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ DWC_DEBUGPL(DBG_ANY, "Clear Resume: HPRT0=%0x\n", ++ DWC_READ_REG32(core_if->host_if->hprt0)); ++ ++ cil_hcd_resume(core_if); ++ ++ /** Change to L0 state*/ ++ core_if->lx_state = DWC_OTG_L0; ++} ++ ++/** ++ * This interrupt indicates that the DWC_otg controller has detected a ++ * resume or remote wakeup sequence. If the DWC_otg controller is in ++ * low power mode, the handler must brings the controller out of low ++ * power mode. The controller automatically begins resume ++ * signaling. The handler schedules a time to stop resume signaling. ++ */ ++int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ ++ DWC_DEBUGPL(DBG_ANY, ++ "++Resume and Remote Wakeup Detected Interrupt++\n"); ++ ++ DWC_PRINTF("%s lxstate = %d\n", __func__, core_if->lx_state); ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs-> ++ dsts)); ++ if (core_if->lx_state == DWC_OTG_L2) { ++#ifdef PARTIAL_POWER_DOWN ++ if (core_if->hwcfg4.b.power_optimiz) { ++ pcgcctl_data_t power = {.d32 = 0 }; ++ ++ power.d32 = DWC_READ_REG32(core_if->pcgcctl); ++ DWC_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n", ++ power.d32); ++ ++ power.b.stoppclk = 0; ++ DWC_WRITE_REG32(core_if->pcgcctl, power.d32); ++ ++ power.b.pwrclmp = 0; ++ DWC_WRITE_REG32(core_if->pcgcctl, power.d32); ++ ++ power.b.rstpdwnmodule = 0; ++ DWC_WRITE_REG32(core_if->pcgcctl, power.d32); ++ } ++#endif ++ /* Clear the Remote Wakeup Signaling */ ++ dctl.b.rmtwkupsig = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, dctl.d32, 0); ++ ++ DWC_SPINUNLOCK(core_if->lock); ++ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); ++ } ++ DWC_SPINLOCK(core_if->lock); ++ } else { ++ glpmcfg_data_t lpmcfg; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ ++ lpmcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.hird_thres &= (~(1 << 4)); ++ lpmcfg.b.en_utmi_sleep = 0; ++ ++ /* Clear Enbl_L1Gating bit. */ ++ pcgcctl.b.enbl_sleep_gating = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,0); ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, ++ lpmcfg.d32); ++ } ++ /** Change to L0 state*/ ++ core_if->lx_state = DWC_OTG_L0; ++ } else { ++ if (core_if->lx_state != DWC_OTG_L1) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ ++ /* Restart the Phy Clock */ ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ DWC_TIMER_SCHEDULE(core_if->wkp_timer, 71); ++ } else { ++ /** Change to L0 state*/ ++ core_if->lx_state = DWC_OTG_L0; ++ } ++ } ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.wkupintr = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * Device disconnect. ++ */ ++static int32_t dwc_otg_handle_pwrdn_disconnect_intr(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn_temp = {.d32 = 0 }; ++ gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ DWC_PRINTF("%s called\n", __FUNCTION__); ++ ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ if (gpwrdn_temp.b.idsts) { ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } else { ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * remote wakeup sequence. ++ */ ++static int32_t dwc_otg_handle_pwrdn_wakeup_detected_intr(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ DWC_DEBUGPL(DBG_ANY, ++ "++Powerdown Remote Wakeup Detected Interrupt++\n"); ++ ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (gpwrdn.b.idsts) { // Device Mode ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ dwc_otg_device_hibernation_restore(core_if, 0, 0); ++ } ++ } else { ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ dwc_otg_host_hibernation_restore(core_if, 1, 0); ++ } ++ } ++ return 1; ++} ++ ++static int32_t dwc_otg_handle_pwrdn_idsts_change(dwc_otg_device_t * otg_dev) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn_temp = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if = otg_dev->core_if; ++ ++ DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); ++ gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (core_if->power_down == 2) { ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ DWC_DEBUGPL(DBG_ANY, "Exit from hibernation on ID sts change\n"); ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /*Indicates that we are exiting from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ gpwrdn.d32 = core_if->gr_backup->gpwrdn_local; ++ if (gpwrdn.b.dis_vbus == 1) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ } ++ ++ if (gpwrdn_temp.b.idsts) { ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } else { ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++ } ++ ++ if (core_if->adp_enable) { ++ uint8_t is_host = 0; ++ DWC_SPINUNLOCK(core_if->lock); ++ /* Change the core_if's lock to hcd/pcd lock depend on mode? */ ++#ifndef DWC_HOST_ONLY ++ if (gpwrdn_temp.b.idsts) ++ core_if->lock = otg_dev->pcd->lock; ++#endif ++#ifndef DWC_DEVICE_ONLY ++ if (!gpwrdn_temp.b.idsts) { ++ core_if->lock = otg_dev->hcd->lock; ++ is_host = 1; ++ } ++#endif ++ DWC_DEBUGPL(DBG_ANY, "RESTART ADP\n"); ++ if (core_if->adp.probe_enabled) ++ dwc_otg_adp_probe_stop(core_if); ++ if (core_if->adp.sense_enabled) ++ dwc_otg_adp_sense_stop(core_if); ++ if (core_if->adp.sense_timer_started) ++ DWC_TIMER_CANCEL(core_if->adp.sense_timer); ++ if (core_if->adp.vbuson_timer_started) ++ DWC_TIMER_CANCEL(core_if->adp.vbuson_timer); ++ /* Do not need to reset ADP if we are coming back ++ * to the device mode after HNP. This is needed ++ * not to perform SRP after reverse, just do ADP ++ * probe and compare the RTIM values with the one ++ * before HNP */ ++ if (core_if->op_state != B_HOST) { ++ core_if->adp.probe_timer_values[0] = -1; ++ core_if->adp.probe_timer_values[1] = -1; ++ core_if->adp.probe_counter = 0; ++ core_if->adp.gpwrdn = 0; ++ } ++ core_if->adp.sense_timer_started = 0; ++ core_if->adp.vbuson_timer_started = 0; ++ ++ /* Disable PMU and restart ADP */ ++ gpwrdn_temp.d32 = 0; ++ gpwrdn_temp.b.pmuactv = 1; ++ gpwrdn_temp.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_mdelay(110); ++ dwc_otg_adp_start(core_if, is_host); ++ DWC_SPINLOCK(core_if->lock); ++ } ++ ++ return 1; ++} ++ ++static int32_t dwc_otg_handle_pwrdn_session_change(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ int32_t otg_cap_param = core_if->core_params->otg_cap; ++ DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); ++ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (core_if->power_down == 2) { ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ if (gpwrdn.b.bsessvld == 0) { ++ /* Save gpwrdn register for further usage if stschng interrupt */ ++ core_if->gr_backup->gpwrdn_local = ++ DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ /*Exit from ISR and wait for stschng interrupt with bsessvld = 1 */ ++ return 1; ++ } ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /*Indicates that we are exiting from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ ++ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE || ++ otg_cap_param == DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) { ++ /* ++ * Initiate SRP after initial ADP probe. ++ */ ++ dwc_otg_initiate_srp(core_if); ++ } ++ } else if (core_if->adp_enable && core_if->op_state != A_HOST){ ++ dwc_otg_adp_probe_stop(core_if); ++ if (DWC_WORKQ_PENDING(core_if->wq_otg)) ++ core_if->stop_adpprb = 1; ++ /* Disable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Device mode. ++ */ ++ core_if->op_state = B_PERIPHERAL; ++ cil_pcd_start(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ } ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * status change either on IDDIG or BSessVld. ++ */ ++static uint32_t dwc_otg_handle_pwrdn_stschng_intr(dwc_otg_device_t * otg_dev) ++{ ++ int retval = 0; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn_temp = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if = otg_dev->core_if; ++ ++ DWC_DEBUGPL(DBG_CIL, "%s called\n", __FUNCTION__); ++ ++ if (core_if->power_down == 2) { ++ if (core_if->hibernation_suspend <= 0) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } else ++ gpwrdn_temp.d32 = core_if->gr_backup->gpwrdn_local; ++ ++ } else { ++ gpwrdn_temp.d32 = core_if->adp.gpwrdn; ++ } ++ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ if (gpwrdn.b.idsts ^ gpwrdn_temp.b.idsts) { ++ retval = dwc_otg_handle_pwrdn_idsts_change(otg_dev); ++ } else if (gpwrdn.b.bsessvld ^ gpwrdn_temp.b.bsessvld) { ++ retval = dwc_otg_handle_pwrdn_session_change(core_if); ++ } ++ ++ return retval; ++} ++ ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * SRP. ++ */ ++static int32_t dwc_otg_handle_pwrdn_srp_intr(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ ++ DWC_PRINTF("%s called\n", __FUNCTION__); ++ ++ if (core_if->power_down == 2) { ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++#ifdef DWC_DEV_SRPCAP ++ if (core_if->pwron_timer_started) { ++ core_if->pwron_timer_started = 0; ++ DWC_TIMER_CANCEL(core_if->pwron_timer); ++ } ++#endif ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Indicates that we are exiting from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Programm Disable VBUS to 0 */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /*Initialize the core as Host */ ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++ /* Do not need to du anything if this is "old" SRP and we are already ++ * in the normal mode of operation */ ++ if(core_if->adp_enable) { ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (!gpwrdn.b.pmuactv) { ++ return 1; ++ } ++ ++ dwc_otg_adp_probe_stop(core_if); ++ /* Disable Interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Host mode. ++ */ ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ /* Start the Connection timer. So a message can be displayed ++ * if connect does not occur within 10 seconds. */ ++ cil_hcd_session_start(core_if); ++ } ++ ++ return 1; ++} ++ ++/** This interrupt indicates that restore command after Hibernation ++ * was completed by the core. */ ++int32_t dwc_otg_handle_restore_done_intr(dwc_otg_core_if_t * core_if) ++{ ++ pcgcctl_data_t pcgcctl; ++ DWC_DEBUGPL(DBG_ANY, "++Restore Done Interrupt++\n"); ++ ++ //TODO De-assert restore signal. 8.a ++ pcgcctl.d32 = DWC_READ_REG32(core_if->pcgcctl); ++ if (pcgcctl.b.restoremode == 1) { ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ /* ++ * If restore mode is Remote Wakeup, ++ * unmask Remote Wakeup interrupt. ++ */ ++ gintmsk.b.wkupintr = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, ++ 0, gintmsk.d32); ++ } ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that a device has been disconnected from ++ * the root port. ++ */ ++int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ ++ DWC_DEBUGPL(DBG_ANY, "++Disconnect Detected Interrupt++ (%s) %s\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"), ++ op_state_str(core_if)); ++ ++/** @todo Consolidate this if statement. */ ++#ifndef DWC_HOST_ONLY ++ if (core_if->op_state == B_HOST) { ++ /* If in device mode Disconnect and stop the HCD, then ++ * start the PCD. */ ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_hcd_disconnect(core_if); ++ cil_pcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ core_if->op_state = B_PERIPHERAL; ++ } else if (dwc_otg_is_device_mode(core_if)) { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gotgctl.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ if (gotgctl.b.hstsethnpen == 1) { ++ /* Do nothing, if HNP in process the OTG ++ * interrupt "Host Negotiation Detected" ++ * interrupt will do the mode switch. ++ */ ++ } else if (gotgctl.b.devhnpen == 0) { ++ /* If in device mode Disconnect and stop the HCD, then ++ * start the PCD. */ ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_hcd_disconnect(core_if); ++ cil_pcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ core_if->op_state = B_PERIPHERAL; ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n"); ++ } ++ } else { ++ if (core_if->op_state == A_HOST) { ++ /* A-Cable still connected but device disconnected. */ ++ cil_hcd_disconnect(core_if); ++ if (core_if->adp_enable) { ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ cil_hcd_stop(core_if); ++ /* Enable Power Down Logic */ ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_otg_adp_probe_start(core_if); ++ ++ /* Power off the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32 ++ (&core_if->core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ } ++ } ++ } ++ } ++#endif ++ /* Change to L3(OFF) state */ ++ core_if->lx_state = DWC_OTG_L3; ++ ++ gintsts.d32 = 0; ++ gintsts.b.disconnect = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that SUSPEND state has been detected on ++ * the USB. ++ * ++ * For HNP the USB Suspend interrupt signals the change from ++ * "a_peripheral" to "a_host". ++ * ++ * When power management is enabled the core will be put in low power ++ * mode. ++ */ ++extern int otg_usbhost_stat; ++int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if) ++{ ++ dsts_data_t dsts; ++ gintsts_data_t gintsts; ++ dcfg_data_t dcfg; ++ ++ DWC_DEBUGPL(DBG_ANY, "USB SUSPEND\n"); ++ otg_usbhost_stat = 0; ++ ++ if ((core_if->otg_ver == 1) && (core_if->op_state == A_PERIPHERAL)) { ++ core_if->lx_state = DWC_OTG_L2; ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.usbsuspend = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++ } ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ /* Check the Device status register to determine if the Suspend ++ * state is active. */ ++ dsts.d32 = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32); ++ DWC_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d " ++ "HWCFG4.power Optimize=%d\n", ++ dsts.b.suspsts, core_if->hwcfg4.b.power_optimiz); ++ ++#ifdef PARTIAL_POWER_DOWN ++/** @todo Add a module parameter for power management. */ ++ ++ if (dsts.b.suspsts && core_if->hwcfg4.b.power_optimiz) { ++ pcgcctl_data_t power = {.d32 = 0 }; ++ DWC_DEBUGPL(DBG_CIL, "suspend\n"); ++ ++ power.b.pwrclmp = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, power.d32); ++ ++ power.b.rstpdwnmodule = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32); ++ ++ power.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32); ++ ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "disconnect?\n"); ++ } ++#endif ++ /* PCD callback for suspend. Release the lock inside of callback function */ ++ cil_pcd_suspend(core_if); ++ if (core_if->power_down == 2) { ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ DWC_DEBUGPL(DBG_ANY,"lx_state = %08x\n",core_if->lx_state); ++ DWC_DEBUGPL(DBG_ANY," device address = %08d\n",dcfg.b.devaddr); ++ ++ if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ ++ /* Change to L2(suspend) state */ ++ core_if->lx_state = DWC_OTG_L2; ++ ++ /* Clear interrupt in gintsts */ ++ gintsts.d32 = 0; ++ gintsts.b.usbsuspend = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, gintsts.d32); ++ DWC_PRINTF("Start of hibernation completed\n"); ++ dwc_otg_save_global_regs(core_if); ++ dwc_otg_save_dev_regs(core_if); ++ ++ gusbcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs-> ++ gusbcfg); ++ if (gusbcfg.b.ulpi_utmi_sel == 1) { ++ /* ULPI interface */ ++ /* Suspend the Phy Clock */ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ dwc_udelay(10); ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } else { ++ /* UTMI+ Interface */ ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ dwc_udelay(10); ++ } ++ ++ /* Set flag to indicate that we are in hibernation */ ++ core_if->hibernation_suspend = 1; ++ /* Enable interrupts from wake up logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Unmask device mode interrupts in GPWRDN */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.rst_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ gpwrdn.b.sts_chngint_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Enable Power Down Clamp */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Switch off VDD */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++ /* Save gpwrdn register for further usage if stschng interrupt */ ++ core_if->gr_backup->gpwrdn_local = ++ DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ DWC_PRINTF("Hibernation completed\n"); ++ ++ return 1; ++ } ++ } else if (core_if->power_down == 3) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ DWC_DEBUGPL(DBG_ANY, "lx_state = %08x\n",core_if->lx_state); ++ DWC_DEBUGPL(DBG_ANY, " device address = %08d\n",dcfg.b.devaddr); ++ ++ if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) { ++ DWC_DEBUGPL(DBG_ANY, "Start entering to extended hibernation\n"); ++ core_if->xhib = 1; ++ ++ /* Clear interrupt in gintsts */ ++ gintsts.d32 = 0; ++ gintsts.b.usbsuspend = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, gintsts.d32); ++ ++ dwc_otg_save_global_regs(core_if); ++ dwc_otg_save_dev_regs(core_if); ++ ++ /* Wait for 10 PHY clocks */ ++ dwc_udelay(10); ++ ++ /* Program GPIO register while entering to xHib */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x1); ++ ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.extnd_hiber_pwrclmp = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.extnd_hiber_switch = 1; ++ core_if->gr_backup->xhib_gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ core_if->gr_backup->xhib_pcgcctl = DWC_READ_REG32(core_if->pcgcctl) | pcgcctl.d32; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ DWC_DEBUGPL(DBG_ANY, "Finished entering to extended hibernation\n"); ++ ++ return 1; ++ } ++ } ++ if ((core_if->otg_ver == 1) && (core_if->core_params->otg_cap == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE)) { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ if (gotgctl.b.devhnpen && core_if->otg_ver == 1){ ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ dwc_mdelay(5); ++ /**@todo Is the gotgctl.devhnpen cleared ++ * by a USB Reset? */ ++ gotgctl.b.devhnpen = 1; ++ gotgctl.b.hnpreq = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, ++ gotgctl.d32); ++ } ++ } ++ } else { ++ if (core_if->op_state == A_PERIPHERAL) { ++ DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n"); ++ /* Clear the a_peripheral flag, back to a_host. */ ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ cil_hcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ core_if->op_state = A_HOST; ++ } ++ } ++ ++ /* Change to L2(suspend) state */ ++ core_if->lx_state = DWC_OTG_L2; ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.usbsuspend = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++static int32_t dwc_otg_handle_xhib_exit_intr(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gahbcfg_data_t gahbcfg = {.d32 = 0 }; ++ ++ dwc_udelay(10); ++ ++ /* Program GPIO register while entering to xHib */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x0); ++ ++ pcgcctl.d32 = core_if->gr_backup->xhib_pcgcctl; ++ pcgcctl.b.extnd_hiber_pwrclmp = 0; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ dwc_udelay(10); ++ ++ gpwrdn.d32 = core_if->gr_backup->xhib_gpwrdn; ++ gpwrdn.b.restore = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ restore_lpm_i2c_regs(core_if); ++ ++ pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14); ++ pcgcctl.b.max_xcvrselect = 1; ++ pcgcctl.b.ess_reg_restored = 0; ++ pcgcctl.b.extnd_hiber_switch = 0; ++ pcgcctl.b.extnd_hiber_pwrclmp = 0; ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ ++ gahbcfg.d32 = core_if->gr_backup->gahbcfg_local; ++ gahbcfg.b.glblintrmsk = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32); ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0x1 << 16); ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, ++ core_if->gr_backup->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, ++ core_if->dr_backup->dcfg); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14); ++ pcgcctl.b.max_xcvrselect = 1; ++ pcgcctl.d32 |= 0x608; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ dwc_udelay(10); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14); ++ pcgcctl.b.max_xcvrselect = 1; ++ pcgcctl.b.ess_reg_restored = 1; ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ pcgcctl.b.rstpdwnmodule = 1; ++ pcgcctl.b.restoremode = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ ++ DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); ++ ++ return 1; ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++/** ++ * This function hadles LPM transaction received interrupt. ++ */ ++static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ gintsts_data_t gintsts; ++ ++ if (!core_if->core_params->lpm_enable) { ++ DWC_PRINTF("Unexpected LPM interrupt\n"); ++ } ++ ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ DWC_PRINTF("LPM config register = 0x%08x\n", lpmcfg.d32); ++ ++ if (dwc_otg_is_host_mode(core_if)) { ++ cil_hcd_sleep(core_if); ++ } else { ++ ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ ++ lpmcfg.b.hird_thres |= (1 << 4); ++ lpmcfg.b.en_utmi_sleep = 1; ++ ++ pcgcctl.b.enbl_sleep_gating = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl,0,pcgcctl.d32); ++ ++ if(dwc_otg_get_param_besl_enable(core_if)) { ++ lpmcfg.b.en_besl = 1; ++ } ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, ++ lpmcfg.d32); ++ } ++ ++ /* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */ ++ dwc_udelay(10); ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ if (lpmcfg.b.prt_sleep_sts) { ++ /* Save the current state */ ++ core_if->lx_state = DWC_OTG_L1; ++ } ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.lpmtranrcvd = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ return 1; ++} ++#endif /* CONFIG_USB_DWC_OTG_LPM */ ++ ++/** ++ * This function returns the Core Interrupt register. ++ */ ++static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if) ++{ ++ gahbcfg_data_t gahbcfg = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ gintmsk_data_t gintmsk; ++ gintmsk_data_t gintmsk_common = {.d32 = 0 }; ++ gintmsk_common.b.wkupintr = 1; ++ gintmsk_common.b.sessreqintr = 1; ++ gintmsk_common.b.conidstschng = 1; ++ gintmsk_common.b.otgintr = 1; ++ gintmsk_common.b.modemismatch = 1; ++ gintmsk_common.b.disconnect = 1; ++ gintmsk_common.b.usbsuspend = 1; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ gintmsk_common.b.lpmtranrcvd = 1; ++#endif ++ gintmsk_common.b.restoredone = 1; ++ /** @todo: The port interrupt occurs while in device ++ * mode. Added code to CIL to clear the interrupt for now! ++ */ ++ gintmsk_common.b.portintr = 1; ++ ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg); ++ ++#ifdef DEBUG ++ /* if any common interrupts set */ ++ if (gintsts.d32 & gintmsk_common.d32) { ++ DWC_DEBUGPL(DBG_ANY, "gintsts=%08x gintmsk=%08x\n", ++ gintsts.d32, gintmsk.d32); ++ } ++#endif ++ if (gahbcfg.b.glblintrmsk) ++ return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32); ++ else ++ return 0; ++ ++} ++ ++/* MACRO for clearing interupt bits in GPWRDN register */ ++#define CLEAR_GPWRDN_INTR(__core_if,__intr) \ ++do { \ ++ gpwrdn_data_t gpwrdn = {.d32=0}; \ ++ gpwrdn.b.__intr = 1; \ ++ DWC_MODIFY_REG32(&__core_if->core_global_regs->gpwrdn, \ ++ 0, gpwrdn.d32); \ ++} while (0) ++ ++/** ++ * Common interrupt handler. ++ * ++ * The common interrupts are those that occur in both Host and Device mode. ++ * This handler handles the following interrupts: ++ * - Mode Mismatch Interrupt ++ * - Disconnect Interrupt ++ * - OTG Interrupt ++ * - Connector ID Status Change Interrupt ++ * - Session Request Interrupt. ++ * - Resume / Remote Wakeup Detected Interrupt. ++ * - LPM Transaction Received Interrupt ++ * - ADP Transaction Received Interrupt ++ * ++ */ ++int32_t dwc_otg_handle_common_intr(void *dev) ++{ ++ int retval = 0; ++ gintsts_data_t gintsts; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ dwc_otg_device_t *otg_dev = dev; ++ dwc_otg_core_if_t *core_if = otg_dev->core_if; ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ if (dwc_otg_check_haps_status(core_if) == -1 ) { ++ DWC_WARN("HAPS is disconnected"); ++ return retval; ++ } ++ ++ if (dwc_otg_is_device_mode(core_if)) ++ core_if->frame_num = dwc_otg_get_frame_number(core_if); ++ ++ if (core_if->lock) ++ DWC_SPINLOCK(core_if->lock); ++ ++ if (core_if->power_down == 3 && core_if->xhib == 1) { ++ DWC_DEBUGPL(DBG_ANY, "Exiting from xHIB state\n"); ++ retval |= dwc_otg_handle_xhib_exit_intr(core_if); ++ core_if->xhib = 2; ++ if (core_if->lock) ++ DWC_SPINUNLOCK(core_if->lock); ++ ++ return retval; ++ } ++ ++ if (core_if->hibernation_suspend <= 0) { ++ gintsts.d32 = dwc_otg_read_common_intr(core_if); ++ ++ if (gintsts.b.modemismatch) { ++ retval |= dwc_otg_handle_mode_mismatch_intr(core_if); ++ } ++ if (gintsts.b.otgintr) { ++ retval |= dwc_otg_handle_otg_intr(core_if); ++ } ++ if (gintsts.b.conidstschng) { ++ retval |= ++ dwc_otg_handle_conn_id_status_change_intr(core_if); ++ } ++ if (gintsts.b.disconnect) { ++ retval |= dwc_otg_handle_disconnect_intr(core_if); ++ } ++ if (gintsts.b.sessreqintr) { ++ retval |= dwc_otg_handle_session_req_intr(core_if); ++ } ++ if (gintsts.b.wkupintr) { ++ retval |= dwc_otg_handle_wakeup_detected_intr(core_if); ++ } ++ if (gintsts.b.usbsuspend) { ++ retval |= dwc_otg_handle_usb_suspend_intr(core_if); ++ } ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ if (gintsts.b.lpmtranrcvd) { ++ retval |= dwc_otg_handle_lpm_intr(core_if); ++ } ++#endif ++ if (gintsts.b.restoredone) { ++ gintsts.d32 = 0; ++ if (core_if->power_down == 2) ++ core_if->hibernation_suspend = -1; ++ else if (core_if->power_down == 3 && core_if->xhib == 2) { ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, 0xFFFFFFFF); ++ ++ DWC_DEBUGPL(DBG_ANY, ++ "RESTORE DONE generated\n"); ++ ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ pcgcctl.b.rstpdwnmodule = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, core_if->gr_backup->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, core_if->dr_backup->dcfg); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, core_if->dr_backup->dctl); ++ dwc_udelay(50); ++ ++ dctl.b.pwronprgdone = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ dwc_udelay(10); ++ ++ dwc_otg_restore_global_regs(core_if); ++ dwc_otg_restore_dev_regs(core_if, 0); ++ ++ dctl.d32 = 0; ++ dctl.b.pwronprgdone = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); ++ dwc_udelay(10); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ ++ /* The core will be in ON STATE */ ++ core_if->lx_state = DWC_OTG_L0; ++ core_if->xhib = 0; ++ ++ DWC_SPINUNLOCK(core_if->lock); ++ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); ++ } ++ DWC_SPINLOCK(core_if->lock); ++ ++ } ++ ++ gintsts.b.restoredone = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32); ++ DWC_PRINTF(" --Restore done interrupt received-- \n"); ++ retval |= 1; ++ } ++ if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) { ++ /* The port interrupt occurs while in device mode with HPRT0 ++ * Port Enable/Disable. ++ */ ++ gintsts.d32 = 0; ++ gintsts.b.portintr = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32); ++ retval |= 1; ++ ++ } ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32); ++ ++ if (gpwrdn.b.disconn_det && gpwrdn.b.disconn_det_msk) { ++ CLEAR_GPWRDN_INTR(core_if, disconn_det); ++ if (gpwrdn.b.linestate == 0) { ++ dwc_otg_handle_pwrdn_disconnect_intr(core_if); ++ } else { ++ DWC_PRINTF("Disconnect detected while linestate is not 0\n"); ++ } ++ ++ retval |= 1; ++ } ++ if (gpwrdn.b.lnstschng && gpwrdn.b.lnstchng_msk) { ++ CLEAR_GPWRDN_INTR(core_if, lnstschng); ++ /* remote wakeup from hibernation */ ++ if (gpwrdn.b.linestate == 2 || gpwrdn.b.linestate == 1) { ++ dwc_otg_handle_pwrdn_wakeup_detected_intr(core_if); ++ } else { ++ DWC_PRINTF("gpwrdn.linestate = %d\n", gpwrdn.b.linestate); ++ } ++ retval |= 1; ++ } ++ if (gpwrdn.b.rst_det && gpwrdn.b.rst_det_msk) { ++ CLEAR_GPWRDN_INTR(core_if, rst_det); ++ if (gpwrdn.b.linestate == 0) { ++ DWC_PRINTF("Reset detected\n"); ++ retval |= dwc_otg_device_hibernation_restore(core_if, 0, 1); ++ } ++ } ++ if (gpwrdn.b.srp_det && gpwrdn.b.srp_det_msk) { ++ CLEAR_GPWRDN_INTR(core_if, srp_det); ++ dwc_otg_handle_pwrdn_srp_intr(core_if); ++ retval |= 1; ++ } ++ } ++ /* Handle ADP interrupt here */ ++ if (gpwrdn.b.adp_int) { ++ CLEAR_GPWRDN_INTR(core_if, adp_int); ++ dwc_otg_adp_handle_intr(core_if); ++ retval |= 1; ++ } ++ if (gpwrdn.b.sts_chngint && gpwrdn.b.sts_chngint_msk) { ++ CLEAR_GPWRDN_INTR(core_if, sts_chngint); ++ dwc_otg_handle_pwrdn_stschng_intr(otg_dev); ++ ++ retval |= 1; ++ } ++ if (gpwrdn.b.srp_det && gpwrdn.b.srp_det_msk) { ++ CLEAR_GPWRDN_INTR(core_if, srp_det); ++ dwc_otg_handle_pwrdn_srp_intr(core_if); ++ retval |= 1; ++ } ++ if (core_if->lock) ++ DWC_SPINUNLOCK(core_if->lock); ++ ++ return retval; ++} +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_core_if.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_core_if.h +new file mode 100644 +index 0000000..c9ab2e5 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_core_if.h +@@ -0,0 +1,743 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $ ++ * $Revision: #15 $ ++ * $Date: 2012/12/10 $ ++ * $Change: 2123206 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++#if !defined(__DWC_CORE_IF_H__) ++#define __DWC_CORE_IF_H__ ++ ++#include "dwc_os.h" ++ ++/** @file ++ * This file defines DWC_OTG Core API ++ */ ++ ++struct dwc_otg_core_if; ++typedef struct dwc_otg_core_if dwc_otg_core_if_t; ++ ++/** Maximum number of Periodic FIFOs */ ++#define MAX_PERIO_FIFOS 15 ++/** Maximum number of Periodic FIFOs */ ++#define MAX_TX_FIFOS 15 ++ ++/** Maximum number of Endpoints/HostChannels */ ++#define MAX_EPS_CHANNELS 16 ++ ++extern dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * _reg_base_addr); ++extern void dwc_otg_core_init(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_cil_remove(dwc_otg_core_if_t * _core_if); ++ ++extern void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * _core_if); ++ ++extern uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if); ++extern uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if); ++ ++extern uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if); ++ ++/** This function should be called on every hardware interrupt. */ ++extern int32_t dwc_otg_handle_common_intr(void *otg_dev); ++ ++/** @name OTG Core Parameters */ ++/** @{ */ ++ ++/** ++ * Specifies the OTG capabilities. The driver will automatically ++ * detect the value for this parameter if none is specified. ++ * 0 - HNP and SRP capable (default) ++ * 1 - SRP Only capable ++ * 2 - No HNP/SRP capable ++ */ ++extern int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val); ++extern int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if); ++#define DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE 0 ++#define DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE 1 ++#define DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE 2 ++#define dwc_param_otg_cap_default DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ++ ++extern int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val); ++extern int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if); ++#define dwc_param_opt_default 1 ++ ++/** ++ * Specifies whether to use slave or DMA mode for accessing the data ++ * FIFOs. The driver will automatically detect the value for this ++ * parameter if none is specified. ++ * 0 - Slave ++ * 1 - DMA (default, if available) ++ */ ++extern int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if); ++#define dwc_param_dma_enable_default 1 ++ ++/** ++ * When DMA mode is enabled specifies whether to use ++ * address DMA or DMA Descritor mode for accessing the data ++ * FIFOs in device mode. The driver will automatically detect ++ * the value for this parameter if none is specified. ++ * 0 - address DMA ++ * 1 - DMA Descriptor(default, if available) ++ */ ++extern int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if); ++#define dwc_param_dma_desc_enable_default 1 ++ ++/** The DMA Burst size (applicable only for External DMA ++ * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32) ++ */ ++extern int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if); ++#define dwc_param_dma_burst_size_default 32 ++ ++/** ++ * Specifies the maximum speed of operation in host and device mode. ++ * The actual speed depends on the speed of the attached device and ++ * the value of phy_type. The actual speed depends on the speed of the ++ * attached device. ++ * 0 - High Speed (default) ++ * 1 - Full Speed ++ */ ++extern int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val); ++extern int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if); ++#define dwc_param_speed_default 0 ++#define DWC_SPEED_PARAM_HIGH 0 ++#define DWC_SPEED_PARAM_FULL 1 ++ ++/** Specifies whether low power mode is supported when attached ++ * to a Full Speed or Low Speed device in host mode. ++ * 0 - Don't support low power mode (default) ++ * 1 - Support low power mode ++ */ ++extern int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t * ++ core_if, int32_t val); ++extern int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t ++ * core_if); ++#define dwc_param_host_support_fs_ls_low_power_default 0 ++ ++/** Specifies the PHY clock rate in low power mode when connected to a ++ * Low Speed device in host mode. This parameter is applicable only if ++ * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS ++ * then defaults to 6 MHZ otherwise 48 MHZ. ++ * ++ * 0 - 48 MHz ++ * 1 - 6 MHz ++ */ ++extern int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * ++ core_if, int32_t val); ++extern int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * ++ core_if); ++#define dwc_param_host_ls_low_power_phy_clk_default 0 ++#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0 ++#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1 ++ ++/** ++ * 0 - Use cC FIFO size parameters ++ * 1 - Allow dynamic FIFO sizing (default) ++ */ ++extern int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t * ++ core_if); ++#define dwc_param_enable_dynamic_fifo_default 1 ++ ++/** Total number of 4-byte words in the data FIFO memory. This ++ * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic ++ * Tx FIFOs. ++ * 32 to 32768 (default 8192) ++ * Note: The total FIFO memory depth in the FPGA configuration is 8192. ++ */ ++extern int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if); ++#define dwc_param_data_fifo_size_default 8192 ++ ++/** Number of 4-byte words in the Rx FIFO in device mode when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1064) ++ */ ++extern int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if); ++#define dwc_param_dev_rx_fifo_size_default 1064 ++ ++/** Number of 4-byte words in the non-periodic Tx FIFO in device mode ++ * when dynamic FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++extern int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * ++ core_if, int32_t val); ++extern int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * ++ core_if); ++#define dwc_param_dev_nperio_tx_fifo_size_default 1024 ++ ++/** Number of 4-byte words in each of the periodic Tx FIFOs in device ++ * mode when dynamic FIFO sizing is enabled. ++ * 4 to 768 (default 256) ++ */ ++extern int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if, ++ int32_t val, int fifo_num); ++extern int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * ++ core_if, int fifo_num); ++#define dwc_param_dev_perio_tx_fifo_size_default 256 ++ ++/** Number of 4-byte words in the Rx FIFO in host mode when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++extern int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if); ++#define dwc_param_host_rx_fifo_size_default 1024 ++ ++/** Number of 4-byte words in the non-periodic Tx FIFO in host mode ++ * when Dynamic FIFO sizing is enabled in the core. ++ * 16 to 32768 (default 1024) ++ */ ++extern int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * ++ core_if, int32_t val); ++extern int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * ++ core_if); ++#define dwc_param_host_nperio_tx_fifo_size_default 1024 ++ ++/** Number of 4-byte words in the host periodic Tx FIFO when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++extern int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * ++ core_if, int32_t val); ++extern int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * ++ core_if); ++#define dwc_param_host_perio_tx_fifo_size_default 1024 ++ ++/** The maximum transfer size supported in bytes. ++ * 2047 to 65,535 (default 65,535) ++ */ ++extern int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if); ++#define dwc_param_max_transfer_size_default 65535 ++ ++/** The maximum number of packets in a transfer. ++ * 15 to 511 (default 511) ++ */ ++extern int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if); ++#define dwc_param_max_packet_count_default 511 ++ ++/** The number of host channel registers to use. ++ * 1 to 16 (default 12) ++ * Note: The FPGA configuration supports a maximum of 12 host channels. ++ */ ++extern int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if); ++#define dwc_param_host_channels_default 12 ++ ++/** The number of endpoints in addition to EP0 available for device ++ * mode operations. ++ * 1 to 15 (default 6 IN and OUT) ++ * Note: The FPGA configuration supports a maximum of 6 IN and OUT ++ * endpoints in addition to EP0. ++ */ ++extern int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if); ++#define dwc_param_dev_endpoints_default 6 ++ ++/** ++ * Specifies the type of PHY interface to use. By default, the driver ++ * will automatically detect the phy_type. ++ * ++ * 0 - Full Speed PHY ++ * 1 - UTMI+ (default) ++ * 2 - ULPI ++ */ ++extern int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val); ++extern int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if); ++#define DWC_PHY_TYPE_PARAM_FS 0 ++#define DWC_PHY_TYPE_PARAM_UTMI 1 ++#define DWC_PHY_TYPE_PARAM_ULPI 2 ++#define dwc_param_phy_type_default DWC_PHY_TYPE_PARAM_UTMI ++ ++/** ++ * Specifies the UTMI+ Data Width. This parameter is ++ * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI ++ * PHY_TYPE, this parameter indicates the data width between ++ * the MAC and the ULPI Wrapper.) Also, this parameter is ++ * applicable only if the OTG_HSPHY_WIDTH cC parameter was set ++ * to "8 and 16 bits", meaning that the core has been ++ * configured to work at either data path width. ++ * ++ * 8 or 16 bits (default 16) ++ */ ++extern int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if); ++#define dwc_param_phy_utmi_width_default 16 ++ ++/** ++ * Specifies whether the ULPI operates at double or single ++ * data rate. This parameter is only applicable if PHY_TYPE is ++ * ULPI. ++ * ++ * 0 - single data rate ULPI interface with 8 bit wide data ++ * bus (default) ++ * 1 - double data rate ULPI interface with 4 bit wide data ++ * bus ++ */ ++extern int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if); ++#define dwc_param_phy_ulpi_ddr_default 0 ++ ++/** ++ * Specifies whether to use the internal or external supply to ++ * drive the vbus with a ULPI phy. ++ */ ++extern int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if); ++#define DWC_PHY_ULPI_INTERNAL_VBUS 0 ++#define DWC_PHY_ULPI_EXTERNAL_VBUS 1 ++#define dwc_param_phy_ulpi_ext_vbus_default DWC_PHY_ULPI_INTERNAL_VBUS ++ ++/** ++ * Specifies whether to use the I2Cinterface for full speed PHY. This ++ * parameter is only applicable if PHY_TYPE is FS. ++ * 0 - No (default) ++ * 1 - Yes ++ */ ++extern int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if); ++#define dwc_param_i2c_enable_default 0 ++ ++extern int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if); ++#define dwc_param_ulpi_fs_ls_default 0 ++ ++extern int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val); ++extern int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if); ++#define dwc_param_ts_dline_default 0 ++ ++/** ++ * Specifies whether dedicated transmit FIFOs are ++ * enabled for non periodic IN endpoints in device mode ++ * 0 - No ++ * 1 - Yes ++ */ ++extern int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t * ++ core_if); ++#define dwc_param_en_multiple_tx_fifo_default 1 ++ ++/** Number of 4-byte words in each of the Tx FIFOs in device ++ * mode when dynamic FIFO sizing is enabled. ++ * 4 to 768 (default 256) ++ */ ++extern int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if, ++ int fifo_num, int32_t val); ++extern int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if, ++ int fifo_num); ++#define dwc_param_dev_tx_fifo_size_default 256 ++ ++/** Thresholding enable flag- ++ * bit 0 - enable non-ISO Tx thresholding ++ * bit 1 - enable ISO Tx thresholding ++ * bit 2 - enable Rx thresholding ++ */ ++extern int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val); ++extern int32_t dwc_otg_get_thr_ctl(dwc_otg_core_if_t * core_if, int fifo_num); ++#define dwc_param_thr_ctl_default 0 ++ ++/** Thresholding length for Tx ++ * FIFOs in 32 bit DWORDs ++ */ ++extern int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_tx_thr_length(dwc_otg_core_if_t * core_if); ++#define dwc_param_tx_thr_length_default 64 ++ ++/** Thresholding length for Rx ++ * FIFOs in 32 bit DWORDs ++ */ ++extern int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_rx_thr_length(dwc_otg_core_if_t * core_if); ++#define dwc_param_rx_thr_length_default 64 ++ ++/** ++ * Specifies whether LPM (Link Power Management) support is enabled ++ */ ++extern int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if); ++#define dwc_param_lpm_enable_default 1 ++ ++/** ++ * Specifies whether LPM Errata (Link Power Management) support is enabled ++ */ ++extern int dwc_otg_set_param_besl_enable(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_besl_enable(dwc_otg_core_if_t * core_if); ++#define dwc_param_besl_enable_default 0 ++ ++/** ++ * Specifies baseline_besl default value ++ */ ++extern int dwc_otg_set_param_baseline_besl(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_baseline_besl(dwc_otg_core_if_t * core_if); ++#define dwc_param_baseline_besl_default 0 ++ ++/** ++ * Specifies deep_besl default value ++ */ ++extern int dwc_otg_set_param_deep_besl(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_deep_besl(dwc_otg_core_if_t * core_if); ++#define dwc_param_deep_besl_default 15 ++ ++/** ++ * Specifies whether PTI enhancement is enabled ++ */ ++extern int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if); ++#define dwc_param_pti_enable_default 0 ++ ++/** ++ * Specifies whether MPI enhancement is enabled ++ */ ++extern int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if); ++#define dwc_param_mpi_enable_default 0 ++ ++/** ++ * Specifies whether ADP capability is enabled ++ */ ++extern int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if); ++#define dwc_param_adp_enable_default 0 ++ ++/** ++ * Specifies whether IC_USB capability is enabled ++ */ ++ ++extern int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if); ++#define dwc_param_ic_usb_cap_default 0 ++ ++extern int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if); ++#define dwc_param_ahb_thr_ratio_default 0 ++ ++extern int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if); ++#define dwc_param_power_down_default 0 ++ ++extern int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if); ++#define dwc_param_reload_ctl_default 0 ++ ++extern int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if); ++#define dwc_param_dev_out_nak_default 0 ++ ++extern int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if); ++#define dwc_param_cont_on_bna_default 0 ++ ++extern int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if); ++#define dwc_param_ahb_single_default 0 ++ ++extern int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val); ++extern int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if); ++#define dwc_param_otg_ver_default 0 ++ ++/** @} */ ++ ++/** @name Access to registers and bit-fields */ ++ ++/** ++ * Dump core registers and SPRAM ++ */ ++extern void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_dump_spram(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_dump_host_registers(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_dump_global_registers(dwc_otg_core_if_t * _core_if); ++ ++/** ++ * Get host negotiation status. ++ */ ++extern uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Get srp status ++ */ ++extern uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Set hnpreq bit in the GOTGCTL register. ++ */ ++extern void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get Content of SNPSID register. ++ */ ++extern uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Get current mode. ++ * Returns 0 if in device mode, and 1 if in host mode. ++ */ ++extern uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Get value of hnpcapable field in the GUSBCFG register ++ */ ++extern uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of hnpcapable field in the GUSBCFG register ++ */ ++extern void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of srpcapable field in the GUSBCFG register ++ */ ++extern uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of srpcapable field in the GUSBCFG register ++ */ ++extern void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of devspeed field in the DCFG register ++ */ ++extern uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of devspeed field in the DCFG register ++ */ ++extern void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get the value of busconnected field from the HPRT0 register ++ */ ++extern uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Gets the device enumeration Speed. ++ */ ++extern uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Get value of prtpwr field from the HPRT0 register ++ */ ++extern uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Get value of flag indicating core state - hibernated or not ++ */ ++extern uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Set value of prtpwr field from the HPRT0 register ++ */ ++extern void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of prtsusp field from the HPRT0 regsiter ++ */ ++extern uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of prtpwr field from the HPRT0 register ++ */ ++extern void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of ModeChTimEn field from the HCFG regsiter ++ */ ++extern uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of ModeChTimEn field from the HCFG regsiter ++ */ ++extern void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of Fram Interval field from the HFIR regsiter ++ */ ++extern uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of Frame Interval field from the HFIR regsiter ++ */ ++extern void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Set value of prtres field from the HPRT0 register ++ *FIXME Remove? ++ */ ++extern void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of rmtwkupsig bit in DCTL register ++ */ ++extern uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Get value of besl_reject bit in DCTL register ++ */ ++ ++extern uint32_t dwc_otg_get_beslreject(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Set value of besl_reject bit in DCTL register ++ */ ++ ++extern void dwc_otg_set_beslreject(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of prt_sleep_sts field from the GLPMCFG register ++ */ ++extern uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Get value of rem_wkup_en field from the GLPMCFG register ++ */ ++extern uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Get value of appl_resp field from the GLPMCFG register ++ */ ++extern uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of appl_resp field from the GLPMCFG register ++ */ ++extern void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of hsic_connect field from the GLPMCFG register ++ */ ++extern uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of hsic_connect field from the GLPMCFG register ++ */ ++extern void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of inv_sel_hsic field from the GLPMCFG register. ++ */ ++extern uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of inv_sel_hsic field from the GLPMFG register. ++ */ ++extern void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val); ++/** ++ * Set value of hird_thresh field from the GLPMFG register. ++ */ ++extern void dwc_otg_set_hirdthresh(dwc_otg_core_if_t * core_if, uint32_t val); ++/** ++ * Get value of hird_thresh field from the GLPMFG register. ++ */ ++extern uint32_t dwc_otg_get_hirdthresh(dwc_otg_core_if_t * core_if); ++ ++ ++/* ++ * Some functions for accessing registers ++ */ ++ ++/** ++ * GOTGCTL register ++ */ ++extern uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * GUSBCFG register ++ */ ++extern uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * GRXFSIZ register ++ */ ++extern uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * GNPTXFSIZ register ++ */ ++extern uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++extern uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * GGPIO register ++ */ ++extern uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * GUID register ++ */ ++extern uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * HPRT0 register ++ */ ++extern uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * GHPTXFSIZE ++ */ ++extern uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if); ++ ++/** @} */ ++ ++#endif /* __DWC_CORE_IF_H__ */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_dbg.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_dbg.h +new file mode 100644 +index 0000000..32c7d10 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_dbg.h +@@ -0,0 +1,113 @@ ++/* ========================================================================== ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 __DWC_OTG_DBG_H__ ++#define __DWC_OTG_DBG_H__ ++ ++/** @file ++ * This file defines debug levels. ++ * Debugging support vanishes in non-debug builds. ++ */ ++ ++/** ++ * The Debug Level bit-mask variable. ++ */ ++extern uint32_t g_dbg_lvl; ++/** ++ * Set the Debug Level variable. ++ */ ++static inline uint32_t SET_DEBUG_LEVEL(const uint32_t new) ++{ ++ uint32_t old = g_dbg_lvl; ++ g_dbg_lvl = new; ++ return old; ++} ++ ++/** When debug level has the DBG_CIL bit set, display CIL Debug messages. */ ++#define DBG_CIL (0x2) ++/** When debug level has the DBG_CILV bit set, display CIL Verbose debug ++ * messages */ ++#define DBG_CILV (0x20) ++/** When debug level has the DBG_PCD bit set, display PCD (Device) debug ++ * messages */ ++#define DBG_PCD (0x4) ++/** When debug level has the DBG_PCDV set, display PCD (Device) Verbose debug ++ * messages */ ++#define DBG_PCDV (0x40) ++/** When debug level has the DBG_HCD bit set, display Host debug messages */ ++#define DBG_HCD (0x8) ++/** When debug level has the DBG_HCDV bit set, display Verbose Host debug ++ * messages */ ++#define DBG_HCDV (0x80) ++/** When debug level has the DBG_HCD_URB bit set, display enqueued URBs in host ++ * mode. */ ++#define DBG_HCD_URB (0x800) ++ ++/** When debug level has any bit set, display debug messages */ ++#define DBG_ANY (0xFF) ++ ++/** All debug messages off */ ++#define DBG_OFF 0 ++ ++/** Prefix string for DWC_DEBUG print macros. */ ++#define USB_DWC "DWC_otg: " ++ ++/** ++ * Print a debug message when the Global debug level variable contains ++ * the bit defined in lvl. ++ * ++ * @param[in] lvl - Debug level, use one of the DBG_ constants above. ++ * @param[in] x - like printf ++ * ++ * Example:

++ * ++ * DWC_DEBUGPL( DBG_ANY, "%s(%p)\n", __func__, _reg_base_addr); ++ * ++ *
++ * results in:
++ * ++ * usb-DWC_otg: dwc_otg_cil_init(ca867000) ++ * ++ */ ++#ifdef DEBUG ++ ++# define DWC_DEBUGPL(lvl, x...) do{ if ((lvl)&g_dbg_lvl)__DWC_DEBUG(USB_DWC x ); }while(0) ++# define DWC_DEBUGP(x...) DWC_DEBUGPL(DBG_ANY, x ) ++ ++# define CHK_DEBUG_LEVEL(level) ((level) & g_dbg_lvl) ++ ++#else ++ ++# define DWC_DEBUGPL(lvl, x...) do{}while(0) ++# define DWC_DEBUGP(x...) ++ ++# define CHK_DEBUG_LEVEL(level) (0) ++ ++#endif /*DEBUG*/ ++#endif +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_driver.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_driver.c +new file mode 100644 +index 0000000..7f291c4 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_driver.c +@@ -0,0 +1,812 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $ ++ * $Revision: #96 $ ++ * $Date: 2013/05/20 $ ++ * $Change: 2234037 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++/** @file ++ * The dwc_otg_driver module provides the initialization and cleanup entry ++ * points for the DWC_otg driver. This module will be dynamically installed ++ * after Linux is booted using the insmod command. When the module is ++ * installed, the dwc_otg_driver_init function is called. When the module is ++ * removed (using rmmod), the dwc_otg_driver_cleanup function is called. ++ * ++ * This module also defines a data structure for the dwc_otg_driver, which is ++ * used in conjunction with the standard ARM lm_device structure. These ++ * structures allow the OTG driver to comply with the standard Linux driver ++ * model in which devices and drivers are registered with a bus driver. This ++ * has the benefit that Linux can expose attributes of the driver and device ++ * in its special sysfs file system. Users can then read or write files in ++ * this file system to perform diagnostics on the driver components or the ++ * device. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dwc_otg_os_dep.h" ++#include "dwc_os.h" ++#include "dwc_otg_dbg.h" ++#include "dwc_otg_driver.h" ++#include "dwc_otg_attr.h" ++#include "dwc_otg_core_if.h" ++#include "dwc_otg_pcd_if.h" ++#include "dwc_otg_hcd_if.h" ++ ++ ++#define DWC_DRIVER_VERSION "3.00a 10-AUG-2012" ++ ++static const char driver_name[] = "hiudc"; ++ ++extern int pcd_init( struct platform_device *_dev , int irqnum); ++extern int hcd_init( struct platform_device *_dev ); ++extern int pcd_remove( struct platform_device *_dev ); ++extern void hcd_remove( struct platform_device *_dev ); ++extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host); ++ ++/******************************************************************************/ ++ ++/* Encapsulate the module parameter settings */ ++ ++struct dwc_otg_driver_module_params { ++ int32_t opt; ++ int32_t otg_cap; ++ int32_t dma_enable; ++ int32_t dma_desc_enable; ++ int32_t dma_burst_size; ++ int32_t speed; ++ int32_t host_support_fs_ls_low_power; ++ int32_t host_ls_low_power_phy_clk; ++ int32_t enable_dynamic_fifo; ++ int32_t data_fifo_size; ++ int32_t dev_rx_fifo_size; ++ int32_t dev_nperio_tx_fifo_size; ++ uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS]; ++ int32_t host_rx_fifo_size; ++ int32_t host_nperio_tx_fifo_size; ++ int32_t host_perio_tx_fifo_size; ++ int32_t max_transfer_size; ++ int32_t max_packet_count; ++ int32_t host_channels; ++ int32_t dev_endpoints; ++ int32_t phy_type; ++ int32_t phy_utmi_width; ++ int32_t phy_ulpi_ddr; ++ int32_t phy_ulpi_ext_vbus; ++ int32_t i2c_enable; ++ int32_t ulpi_fs_ls; ++ int32_t ts_dline; ++ int32_t en_multiple_tx_fifo; ++ uint32_t dev_tx_fifo_size[MAX_TX_FIFOS]; ++ uint32_t thr_ctl; ++ uint32_t tx_thr_length; ++ uint32_t rx_thr_length; ++ int32_t pti_enable; ++ int32_t mpi_enable; ++ int32_t lpm_enable; ++ int32_t besl_enable; ++ int32_t baseline_besl; ++ int32_t deep_besl; ++ int32_t ic_usb_cap; ++ int32_t ahb_thr_ratio; ++ int32_t power_down; ++ int32_t reload_ctl; ++ int32_t dev_out_nak; ++ int32_t cont_on_bna; ++ int32_t ahb_single; ++ int32_t otg_ver; ++ int32_t adp_enable; ++}; ++/******************************************************************************/ ++ ++static struct dwc_otg_driver_module_params dwc_otg_module_params = { ++ .opt = -1, ++ .otg_cap = 2, /*non-hnp/srp-capable*/ ++ .dma_enable = 1, /* enable */ ++ .dma_desc_enable = 1, ++ .dma_burst_size = -1, ++ .speed = -1,/*high-speed*/ ++ .host_support_fs_ls_low_power = -1, /* lowpower mode isn't supported */ ++ .host_ls_low_power_phy_clk = -1, ++ .enable_dynamic_fifo = -1, /* use coreconsultant fifo size */ ++ .data_fifo_size = -1, ++ .dev_rx_fifo_size = -1, ++ .dev_nperio_tx_fifo_size = -1, ++ .dev_perio_tx_fifo_size = { ++ /* dev_perio_tx_fifo_size_1 */ ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1 ++ /* 15 */ ++ }, ++ .host_rx_fifo_size = -1, ++ .host_nperio_tx_fifo_size = -1, ++ .host_perio_tx_fifo_size = -1, ++ .max_transfer_size = -1, ++ .max_packet_count = -1, ++ .host_channels = -1, ++ .dev_endpoints = -1, ++ .phy_type = -1,/*utmi+*/ ++ .phy_utmi_width = 8, ++ .phy_ulpi_ddr = -1, ++ .phy_ulpi_ext_vbus = -1, ++ .i2c_enable = -1, ++ .ulpi_fs_ls = -1, ++ .ts_dline = -1, ++ .en_multiple_tx_fifo = -1, ++ .dev_tx_fifo_size = { ++ /* dev_tx_fifo_size */ ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1 ++ /* 15 */ ++ }, ++ .thr_ctl = -1, ++ .tx_thr_length = -1, ++ .rx_thr_length = -1, ++ .pti_enable = -1, ++ .mpi_enable = -1, ++ .lpm_enable = -1, ++ .besl_enable = -1, ++ .baseline_besl = -1, ++ .deep_besl = -1, ++ .ic_usb_cap = -1, ++ .ahb_thr_ratio = -1, ++ .power_down = -1, ++ .reload_ctl = -1, ++ .dev_out_nak = -1, ++ .cont_on_bna = -1, ++ .ahb_single = -1, ++ .otg_ver = -1, ++ .adp_enable = -1, ++}; ++/******************************************************************************/ ++ ++/** ++ * This function is called during module intialization ++ * to pass module parameters to the DWC_OTG CORE. ++ */ ++static int set_parameters(dwc_otg_core_if_t * core_if) ++{ ++ int retval = 0; ++ int i; ++ ++ if (dwc_otg_module_params.otg_cap != -1) { ++ retval += ++ dwc_otg_set_param_otg_cap(core_if, ++ dwc_otg_module_params.otg_cap); ++ } ++ if (dwc_otg_module_params.dma_enable != -1) { ++ retval += ++ dwc_otg_set_param_dma_enable(core_if, ++ dwc_otg_module_params. ++ dma_enable); ++ } ++ if (dwc_otg_module_params.dma_desc_enable != -1) { ++ retval += ++ dwc_otg_set_param_dma_desc_enable(core_if, ++ dwc_otg_module_params. ++ dma_desc_enable); ++ } ++ if (dwc_otg_module_params.opt != -1) { ++ retval += ++ dwc_otg_set_param_opt(core_if, dwc_otg_module_params.opt); ++ } ++ if (dwc_otg_module_params.dma_burst_size != -1) { ++ retval += ++ dwc_otg_set_param_dma_burst_size(core_if, ++ dwc_otg_module_params. ++ dma_burst_size); ++ } ++ if (dwc_otg_module_params.host_support_fs_ls_low_power != -1) { ++ retval += ++ dwc_otg_set_param_host_support_fs_ls_low_power(core_if, ++ dwc_otg_module_params. ++ host_support_fs_ls_low_power); ++ } ++ if (dwc_otg_module_params.enable_dynamic_fifo != -1) { ++ retval += ++ dwc_otg_set_param_enable_dynamic_fifo(core_if, ++ dwc_otg_module_params. ++ enable_dynamic_fifo); ++ } ++ if (dwc_otg_module_params.data_fifo_size != -1) { ++ retval += ++ dwc_otg_set_param_data_fifo_size(core_if, ++ dwc_otg_module_params. ++ data_fifo_size); ++ } ++ if (dwc_otg_module_params.dev_rx_fifo_size != -1) { ++ retval += ++ dwc_otg_set_param_dev_rx_fifo_size(core_if, ++ dwc_otg_module_params. ++ dev_rx_fifo_size); ++ } ++ if (dwc_otg_module_params.dev_nperio_tx_fifo_size != -1) { ++ retval += ++ dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if, ++ dwc_otg_module_params. ++ dev_nperio_tx_fifo_size); ++ } ++ if (dwc_otg_module_params.host_rx_fifo_size != -1) { ++ retval += ++ dwc_otg_set_param_host_rx_fifo_size(core_if, ++ dwc_otg_module_params.host_rx_fifo_size); ++ } ++ if (dwc_otg_module_params.host_nperio_tx_fifo_size != -1) { ++ retval += ++ dwc_otg_set_param_host_nperio_tx_fifo_size(core_if, ++ dwc_otg_module_params. ++ host_nperio_tx_fifo_size); ++ } ++ if (dwc_otg_module_params.host_perio_tx_fifo_size != -1) { ++ retval += ++ dwc_otg_set_param_host_perio_tx_fifo_size(core_if, ++ dwc_otg_module_params. ++ host_perio_tx_fifo_size); ++ } ++ if (dwc_otg_module_params.max_transfer_size != -1) { ++ retval += ++ dwc_otg_set_param_max_transfer_size(core_if, ++ dwc_otg_module_params. ++ max_transfer_size); ++ } ++ if (dwc_otg_module_params.max_packet_count != -1) { ++ retval += ++ dwc_otg_set_param_max_packet_count(core_if, ++ dwc_otg_module_params. ++ max_packet_count); ++ } ++ if (dwc_otg_module_params.host_channels != -1) { ++ retval += ++ dwc_otg_set_param_host_channels(core_if, ++ dwc_otg_module_params. ++ host_channels); ++ } ++ if (dwc_otg_module_params.dev_endpoints != -1) { ++ retval += ++ dwc_otg_set_param_dev_endpoints(core_if, ++ dwc_otg_module_params. ++ dev_endpoints); ++ } ++ if (dwc_otg_module_params.phy_type != -1) { ++ retval += ++ dwc_otg_set_param_phy_type(core_if, ++ dwc_otg_module_params.phy_type); ++ } ++ if (dwc_otg_module_params.speed != -1) { ++ retval += ++ dwc_otg_set_param_speed(core_if, ++ dwc_otg_module_params.speed); ++ } ++ if (dwc_otg_module_params.host_ls_low_power_phy_clk != -1) { ++ retval += ++ dwc_otg_set_param_host_ls_low_power_phy_clk(core_if, ++ dwc_otg_module_params. ++ host_ls_low_power_phy_clk); ++ } ++ if (dwc_otg_module_params.phy_ulpi_ddr != -1) { ++ retval += ++ dwc_otg_set_param_phy_ulpi_ddr(core_if, ++ dwc_otg_module_params. ++ phy_ulpi_ddr); ++ } ++ if (dwc_otg_module_params.phy_ulpi_ext_vbus != -1) { ++ retval += ++ dwc_otg_set_param_phy_ulpi_ext_vbus(core_if, ++ dwc_otg_module_params. ++ phy_ulpi_ext_vbus); ++ } ++ if (dwc_otg_module_params.phy_utmi_width != -1) { ++ retval += ++ dwc_otg_set_param_phy_utmi_width(core_if, ++ dwc_otg_module_params. ++ phy_utmi_width); ++ } ++ if (dwc_otg_module_params.ulpi_fs_ls != -1) { ++ retval += ++ dwc_otg_set_param_ulpi_fs_ls(core_if, ++ dwc_otg_module_params.ulpi_fs_ls); ++ } ++ if (dwc_otg_module_params.ts_dline != -1) { ++ retval += ++ dwc_otg_set_param_ts_dline(core_if, ++ dwc_otg_module_params.ts_dline); ++ } ++ if (dwc_otg_module_params.i2c_enable != -1) { ++ retval += ++ dwc_otg_set_param_i2c_enable(core_if, ++ dwc_otg_module_params. ++ i2c_enable); ++ } ++ if (dwc_otg_module_params.en_multiple_tx_fifo != -1) { ++ retval += ++ dwc_otg_set_param_en_multiple_tx_fifo(core_if, ++ dwc_otg_module_params. ++ en_multiple_tx_fifo); ++ } ++ for (i = 0; i < 15; i++) { ++ if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] != -1) { ++ retval += ++ dwc_otg_set_param_dev_perio_tx_fifo_size(core_if, ++ dwc_otg_module_params. ++ dev_perio_tx_fifo_size ++ [i], i); ++ } ++ } ++ ++ for (i = 0; i < 15; i++) { ++ if (dwc_otg_module_params.dev_tx_fifo_size[i] != -1) { ++ retval += dwc_otg_set_param_dev_tx_fifo_size(core_if, ++ dwc_otg_module_params. ++ dev_tx_fifo_size ++ [i], i); ++ } ++ } ++ if (dwc_otg_module_params.thr_ctl != -1) { ++ retval += ++ dwc_otg_set_param_thr_ctl(core_if, ++ dwc_otg_module_params.thr_ctl); ++ } ++ if (dwc_otg_module_params.mpi_enable != -1) { ++ retval += ++ dwc_otg_set_param_mpi_enable(core_if, ++ dwc_otg_module_params. ++ mpi_enable); ++ } ++ if (dwc_otg_module_params.pti_enable != -1) { ++ retval += ++ dwc_otg_set_param_pti_enable(core_if, ++ dwc_otg_module_params. ++ pti_enable); ++ } ++ if (dwc_otg_module_params.lpm_enable != -1) { ++ retval += ++ dwc_otg_set_param_lpm_enable(core_if, ++ dwc_otg_module_params. ++ lpm_enable); ++ } ++ if (dwc_otg_module_params.besl_enable != -1) { ++ retval += ++ dwc_otg_set_param_besl_enable(core_if, ++ dwc_otg_module_params. ++ besl_enable); ++ } ++ if (dwc_otg_module_params.baseline_besl != -1) { ++ retval += ++ dwc_otg_set_param_baseline_besl(core_if, ++ dwc_otg_module_params. ++ baseline_besl); ++ } ++ if (dwc_otg_module_params.deep_besl != -1) { ++ retval += ++ dwc_otg_set_param_deep_besl(core_if, ++ dwc_otg_module_params. ++ deep_besl); ++ } ++ if (dwc_otg_module_params.ic_usb_cap != -1) { ++ retval += ++ dwc_otg_set_param_ic_usb_cap(core_if, ++ dwc_otg_module_params. ++ ic_usb_cap); ++ } ++ if (dwc_otg_module_params.tx_thr_length != -1) { ++ retval += ++ dwc_otg_set_param_tx_thr_length(core_if, ++ dwc_otg_module_params.tx_thr_length); ++ } ++ if (dwc_otg_module_params.rx_thr_length != -1) { ++ retval += ++ dwc_otg_set_param_rx_thr_length(core_if, ++ dwc_otg_module_params. ++ rx_thr_length); ++ } ++ if (dwc_otg_module_params.ahb_thr_ratio != -1) { ++ retval += ++ dwc_otg_set_param_ahb_thr_ratio(core_if, ++ dwc_otg_module_params.ahb_thr_ratio); ++ } ++ if (dwc_otg_module_params.power_down != -1) { ++ retval += ++ dwc_otg_set_param_power_down(core_if, ++ dwc_otg_module_params.power_down); ++ } ++ if (dwc_otg_module_params.reload_ctl != -1) { ++ retval += ++ dwc_otg_set_param_reload_ctl(core_if, ++ dwc_otg_module_params.reload_ctl); ++ } ++ ++ if (dwc_otg_module_params.dev_out_nak != -1) { ++ retval += ++ dwc_otg_set_param_dev_out_nak(core_if, ++ dwc_otg_module_params.dev_out_nak); ++ } ++ ++ if (dwc_otg_module_params.cont_on_bna != -1) { ++ retval += ++ dwc_otg_set_param_cont_on_bna(core_if, ++ dwc_otg_module_params.cont_on_bna); ++ } ++ ++ if (dwc_otg_module_params.ahb_single != -1) { ++ retval += ++ dwc_otg_set_param_ahb_single(core_if, ++ dwc_otg_module_params.ahb_single); ++ } ++ ++ if (dwc_otg_module_params.otg_ver != -1) { ++ retval += ++ dwc_otg_set_param_otg_ver(core_if, ++ dwc_otg_module_params.otg_ver); ++ } ++ if (dwc_otg_module_params.adp_enable != -1) { ++ retval += ++ dwc_otg_set_param_adp_enable(core_if, ++ dwc_otg_module_params. ++ adp_enable); ++ } ++ return retval; ++} ++/******************************************************************************/ ++ ++/** ++ * This function is the top level interrupt handler for the Common ++ * (Device and host modes) interrupts. ++ */ ++static irqreturn_t dwc_otg_common_irq(int irq, void *dev) ++{ ++ int32_t retval = IRQ_NONE; ++ ++ retval = dwc_otg_handle_common_intr(dev); ++ ++ return IRQ_RETVAL(retval); ++} ++/******************************************************************************/ ++ ++static int hisi_udc_remove( struct platform_device *_dev) ++{ ++ ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); ++ ++ DWC_DEBUGPL(DBG_ANY, "%s(%p)\n", __func__, _dev); ++ ++ if (!otg_dev) { ++ /* Memory allocation for the dwc_otg_device failed. */ ++ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__); ++ return -1; ++ } ++ ++ if (otg_dev->pcd) { ++ pcd_remove(_dev); ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->pcd NULL!\n", __func__); ++ return -1; ++ } ++ ++ /* ++ * Free the IRQ ++ */ ++ if (otg_dev->common_irq_installed) { ++ free_irq(_dev->resource[1].start, otg_dev); ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__); ++ return -1; ++ } ++ ++ if (otg_dev->core_if) { ++ dwc_otg_cil_remove(otg_dev->core_if); ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->core_if NULL!\n", __func__); ++ return -1; ++ } ++ ++ /* ++ * Return the memory. ++ */ ++ if (otg_dev->os_dep.base) { ++ iounmap(otg_dev->os_dep.base); ++ } ++ ++ clk_disable_unprepare(otg_dev->clk); ++ DWC_FREE(otg_dev); ++ /* ++ * Clear the drvdata pointer. ++ */ ++ platform_set_drvdata(_dev, NULL); ++ ++ return 0; ++ ++} ++/******************************************************************************/ ++ ++static int hisi_udc_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ dwc_otg_device_t *dwc_otg_device; ++ int irq; ++ int ret; ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(&pdev->dev, "no irq provided"); ++ return irq; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "no memory resource provided"); ++ return -ENXIO; ++ } ++ ++ dwc_otg_device = DWC_ALLOC(sizeof(dwc_otg_device_t)); ++ ++ if (!dwc_otg_device) { ++ dev_err(&pdev->dev, "kmalloc of dwc_otg_device failed\n"); ++ return -ENOMEM; ++ } ++ ++ memset(dwc_otg_device, 0, sizeof(*dwc_otg_device)); ++ dwc_otg_device->os_dep.reg_offset = 0xFFFFFFFF; ++ ++ /* ++ * Map the DWC_otg Core memory into virtual address space. ++ */ ++ dwc_otg_device->os_dep.res_start = res->start; ++ dwc_otg_device->os_dep.base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(dwc_otg_device->os_dep.base)) { ++ DWC_FREE(dwc_otg_device); ++ return -ENOMEM; ++ } ++ ++ dev_dbg(&pdev->dev, "base=0x%08x\n",(unsigned)dwc_otg_device->os_dep.base); ++ ++ ++ dwc_otg_device->clk = devm_clk_get(&pdev->dev, "clk"); ++ if (IS_ERR_OR_NULL(dwc_otg_device->clk)) { ++ dev_err(&pdev->dev, "get clock fail.\n"); ++ ret = PTR_ERR(dwc_otg_device->clk); ++ DWC_FREE(dwc_otg_device); ++ return ret; ++ } ++ clk_prepare_enable(dwc_otg_device->clk); ++ ++ /* ++ * Initialize driver data to point to the global DWC_otg ++ * Device structure. ++ */ ++ platform_set_drvdata(pdev, dwc_otg_device); ++ ++ ++ dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->os_dep.base); ++ if (!dwc_otg_device->core_if) { ++ dev_err(&pdev->dev, "CIL initialization failed!\n"); ++ ret = -ENOMEM; ++ goto fail; ++ ++ } ++ ++ /* ++ * Attempt to ensure this device is really a DWC_otg Controller. ++ * Read and verify the SNPSID register contents. The value should be ++ * 0x45F42XXX or 0x45F42XXX, which corresponds to either "OT2" or "OTG3", ++ * as in "OTG version 2.XX" or "OTG version 3.XX". ++ */ ++ ++ if (((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F542000) && ++ ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) { ++ dev_err(&pdev->dev, "Bad value for SNPSID: 0x%08x\n", ++ dwc_otg_get_gsnpsid(dwc_otg_device->core_if)); ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ /* ++ * Validate parameter values. ++ */ ++ if (set_parameters(dwc_otg_device->core_if)) { ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ ++ /* ++ * Disable the global interrupt until all the interrupt ++ * handlers are installed. ++ */ ++ dwc_otg_disable_global_interrupts(dwc_otg_device->core_if); ++ ++ ++ /* ++ * Install the interrupt handler for the common interrupts before ++ * enabling common interrupts in core_init below. ++ */ ++ DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n", ++ pdev->resource[1].start); ++ ret = request_irq(irq, dwc_otg_common_irq, ++ IRQF_SHARED | IRQF_DISABLED | IRQ_LEVEL, "dwc_otg", ++ dwc_otg_device); ++ if (ret) { ++ dev_err(&pdev->dev,"request of irq%d failed\n",irq); ++ ret = -EBUSY; ++ goto fail; ++ } else { ++ dwc_otg_device->common_irq_installed = 1; ++ } ++ ++ ++ /* ++ * Initialize the DWC_otg core. ++ */ ++ dwc_otg_core_init(dwc_otg_device->core_if); ++ ++ /* ++ * Initialize the PCD ++ */ ++ ret = pcd_init(pdev, irq); ++ if (ret != 0) { ++ dev_err(&pdev->dev,"pcd_init failed\n"); ++ dwc_otg_device->pcd = NULL; ++ goto fail; ++ } ++ ++ ++ /* ++ * Enable the global interrupt after all the interrupt ++ * handlers are installed if there is no ADP support else ++ * perform initial actions required for Internal ADP logic. ++ */ ++ if (!dwc_otg_get_param_adp_enable(dwc_otg_device->core_if)) ++ dwc_otg_enable_global_interrupts(dwc_otg_device->core_if); ++ else ++ dwc_otg_adp_start(dwc_otg_device->core_if, ++ dwc_otg_is_host_mode(dwc_otg_device->core_if)); ++ ++ return 0; ++ ++fail: ++ hisi_udc_remove(pdev); ++ return ret; ++} ++/******************************************************************************/ ++ ++#ifdef CONFIG_PM ++static int hisi_udc_suspend(struct device *dev) ++{ ++ dwc_otg_device_t *dwc_otg_device = dev_get_drvdata(dev); ++ int rc = 0; ++ ++ dwc_otg_disable_global_interrupts(dwc_otg_device->core_if); ++ clk_disable_unprepare(dwc_otg_device->clk); ++ ++ return rc; ++} ++/******************************************************************************/ ++ ++static int hisi_udc_resume(struct device *dev) ++{ ++ dwc_otg_device_t *dwc_otg_device = dev_get_drvdata(dev); ++ ++ clk_prepare_enable(dwc_otg_device->clk); ++ dwc_otg_core_init(dwc_otg_device->core_if); ++ dwc_otg_enable_global_interrupts(dwc_otg_device->core_if); ++ return 0; ++} ++#else ++#define hisi_udc_suspend NULL; ++#define hisi_udc_resume NULL; ++#endif ++/******************************************************************************/ ++ ++static const struct dev_pm_ops hisi_udc_pmops = { ++ .suspend = hisi_udc_suspend, ++ .resume = hisi_udc_resume, ++#if defined(CONFIG_PM_HIBERNATE) || defined(CONFIG_HISI_SNAPSHOT_BOOT) ++ .freeze = hisi_udc_suspend, ++ .thaw = hisi_udc_resume, ++ .poweroff = hisi_udc_suspend, ++ .restore = hisi_udc_resume, ++#endif ++}; ++ ++static const struct of_device_id hisi_udc_ids[] = { ++ { .compatible = "hiudc", }, ++ { /* null */ } ++}; ++MODULE_DEVICE_TABLE(of, hisi_udc_ids); ++ ++static struct platform_driver hisi_udc_pltfrm_driver = { ++ .probe = hisi_udc_probe, ++ .remove = hisi_udc_remove, ++ .driver = { ++ .name = (char *)driver_name, ++ .owner = THIS_MODULE, ++ .of_match_table = hisi_udc_ids, ++ .pm = &hisi_udc_pmops, ++ }, ++}; ++/******************************************************************************/ ++ ++static int __init hisi_udc_module_init(void) ++{ ++ int ret; ++ ++ printk(KERN_INFO "%s: version %s\n", driver_name, ++ DWC_DRIVER_VERSION); ++ ++ ret = platform_driver_register(&hisi_udc_pltfrm_driver); ++ ++ return ret; ++} ++module_init(hisi_udc_module_init); ++/******************************************************************************/ ++ ++static void __exit hisi_udc_module_exit (void) ++{ ++ ++ platform_driver_unregister(&hisi_udc_pltfrm_driver); ++ ++ printk(KERN_INFO "%s module removed\n", driver_name); ++} ++module_exit(hisi_udc_module_exit); ++ ++MODULE_AUTHOR("Hisilicon"); ++MODULE_DESCRIPTION("Hisilcon USB Device Controller driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_driver.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_driver.h +new file mode 100644 +index 0000000..63df919 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_driver.h +@@ -0,0 +1,89 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $ ++ * $Revision: #19 $ ++ * $Date: 2010/11/15 $ ++ * $Change: 1627671 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 __DWC_OTG_DRIVER_H__ ++#define __DWC_OTG_DRIVER_H__ ++ ++/** @file ++ * This file contains the interface to the Linux driver. ++ */ ++#include "dwc_otg_os_dep.h" ++#include "dwc_otg_core_if.h" ++#include ++ ++/* Type declarations */ ++struct dwc_otg_pcd; ++struct dwc_otg_hcd; ++ ++/** ++ * This structure is a wrapper that encapsulates the driver components used to ++ * manage a single DWC_otg controller. ++ */ ++typedef struct dwc_otg_device { ++ /** Structure containing OS-dependent stuff. KEEP THIS STRUCT AT THE ++ * VERY BEGINNING OF THE DEVICE STRUCT. OSes such as FreeBSD and NetBSD ++ * require this. */ ++ struct os_dependent os_dep; ++ ++ /** Pointer to the core interface structure. */ ++ dwc_otg_core_if_t *core_if; ++ ++ /** Pointer to the PCD structure. */ ++ struct dwc_otg_pcd *pcd; ++ ++ /** Pointer to the HCD structure. */ ++ struct dwc_otg_hcd *hcd; ++ ++ struct clk *clk; ++ ++ /** Flag to indicate whether the common IRQ handler is installed. */ ++ uint8_t common_irq_installed; ++ ++} dwc_otg_device_t; ++ ++/*We must clear S3C24XX_EINTPEND external interrupt register ++ * because after clearing in this register trigerred IRQ from ++ * H/W core in kernel interrupt can be occured again before OTG ++ * handlers clear all IRQ sources of Core registers because of ++ * timing latencies and Low Level IRQ Type. ++ */ ++#ifdef CONFIG_MACH_IPMATE ++#define S3C2410X_CLEAR_EINTPEND() \ ++do { \ ++ __raw_writel(1UL << 11,S3C24XX_EINTPEND); \ ++} while (0) ++#else ++#define S3C2410X_CLEAR_EINTPEND() do { } while (0) ++#endif ++ ++#endif +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd.c +new file mode 100644 +index 0000000..baebe82 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd.c +@@ -0,0 +1,3431 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $ ++ * $Revision: #110 $ ++ * $Date: 2013/05/19 $ ++ * $Change: 2234022 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_DEVICE_ONLY ++ ++/** @file ++ * This file implements HCD Core. All code in this file is portable and doesn't ++ * use any OS specific functions. ++ * Interface provided by HCD Core is defined in ++ * header file. ++ */ ++ ++#include "dwc_otg_hcd.h" ++#include "dwc_otg_regs.h" ++ ++dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void) ++{ ++ return DWC_ALLOC(sizeof(dwc_otg_hcd_t)); ++} ++ ++/** ++ * Connection timeout function. An OTG host is required to display a ++ * message if the device does not connect within 10 seconds. ++ */ ++void dwc_otg_hcd_connect_timeout(void *ptr) ++{ ++ dwc_otg_hcd_t *hcd; ++ gpwrdn_data_t gpwrdn; ++ DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, ptr); ++ DWC_PRINTF("Connect Timeout\n"); ++ __DWC_ERROR("Device Not Connected/Responding\n"); ++ /** Remove buspower after 10s */ ++ hcd = ptr; ++ if (hcd->core_if->otg_ver) ++ dwc_otg_set_prtpower(hcd->core_if, 0); ++ if (hcd->core_if->adp_enable && !hcd->core_if->adp.probe_enabled) { ++ cil_hcd_disconnect(hcd->core_if); ++ gpwrdn.d32 = 0; ++ /* Enable Power Down Logic */ ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ ++ /* Unmask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ ++ dwc_mdelay(220); ++ dwc_otg_adp_probe_start(hcd->core_if); ++ } ++} ++ ++#ifdef DEBUG ++static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ if (qh->channel != NULL) { ++ dwc_hc_t *hc = qh->channel; ++ dwc_list_link_t *item; ++ dwc_otg_qh_t *qh_item; ++ int num_channels = hcd->core_if->core_params->host_channels; ++ int i; ++ ++ dwc_otg_hc_regs_t *hc_regs; ++ hcchar_data_t hcchar; ++ hcsplt_data_t hcsplt; ++ hctsiz_data_t hctsiz; ++ uint32_t hcdma; ++ ++ hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num]; ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt); ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ hcdma = DWC_READ_REG32(&hc_regs->hcdma); ++ ++ DWC_PRINTF(" Assigned to channel %p:\n", hc); ++ DWC_PRINTF(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, ++ hcsplt.d32); ++ DWC_PRINTF(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, ++ hcdma); ++ DWC_PRINTF(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n", ++ hc->dev_addr, hc->ep_num, hc->ep_is_in); ++ DWC_PRINTF(" ep_type: %d\n", hc->ep_type); ++ DWC_PRINTF(" max_packet: %d\n", hc->max_packet); ++ DWC_PRINTF(" data_pid_start: %d\n", hc->data_pid_start); ++ DWC_PRINTF(" xfer_started: %d\n", hc->xfer_started); ++ DWC_PRINTF(" halt_status: %d\n", hc->halt_status); ++ DWC_PRINTF(" xfer_buff: %p\n", hc->xfer_buff); ++ DWC_PRINTF(" xfer_len: %d\n", hc->xfer_len); ++ DWC_PRINTF(" qh: %p\n", hc->qh); ++ DWC_PRINTF(" NP inactive sched:\n"); ++ DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_inactive) { ++ qh_item = ++ DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry); ++ DWC_PRINTF(" %p\n", qh_item); ++ } ++ DWC_PRINTF(" NP active sched:\n"); ++ DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_active) { ++ qh_item = ++ DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry); ++ DWC_PRINTF(" %p\n", qh_item); ++ } ++ DWC_PRINTF(" Channels: \n"); ++ for (i = 0; i < num_channels; i++) { ++ dwc_hc_t *hc = hcd->hc_ptr_array[i]; ++ DWC_PRINTF(" %2d: %p\n", i, hc); ++ } ++ } ++} ++#endif /* DEBUG */ ++ ++/** ++ * Work queue function for starting the HCD when A-Cable is connected. ++ * The hcd_start() must be called in a process context. ++ */ ++static void hcd_start_func(void *_vp) ++{ ++ dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) _vp; ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, hcd); ++ if (hcd) { ++ hcd->fops->start(hcd); ++ } ++} ++ ++static void del_xfer_timers(dwc_otg_hcd_t * hcd) ++{ ++#ifdef DEBUG ++ int i; ++ int num_channels = hcd->core_if->core_params->host_channels; ++ for (i = 0; i < num_channels; i++) { ++ DWC_TIMER_CANCEL(hcd->core_if->hc_xfer_timer[i]); ++ } ++#endif ++} ++ ++static void del_timers(dwc_otg_hcd_t * hcd) ++{ ++ del_xfer_timers(hcd); ++ DWC_TIMER_CANCEL(hcd->conn_timer); ++} ++ ++/** ++ * Processes all the URBs in a single list of QHs. Completes them with ++ * -ETIMEDOUT and frees the QTD. ++ */ ++static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list) ++{ ++ dwc_list_link_t *qh_item; ++ dwc_otg_qh_t *qh; ++ dwc_otg_qtd_t *qtd, *qtd_tmp; ++ ++ DWC_LIST_FOREACH(qh_item, qh_list) { ++ qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry); ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, ++ &qh->qtd_list, qtd_list_entry) { ++ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); ++ if (qtd->urb != NULL) { ++ if(!qtd->urb->priv) { ++ DWC_ERROR("urb->priv is NULL !!!!\n"); ++ return; ++ } ++ if(!hcd->fops) ++ DWC_ERROR("hcd->fops is NULL !!!!!\n"); ++ if(!hcd->fops->complete) ++ DWC_ERROR("fops->complete is NULL !!!!\n"); ++ hcd->fops->complete(hcd, qtd->urb->priv, ++ qtd->urb, -DWC_E_TIMEOUT); ++ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ } ++ ++ } ++ } ++} ++ ++/** ++ * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic ++ * and periodic schedules. The QTD associated with each URB is removed from ++ * the schedule and freed. This function may be called when a disconnect is ++ * detected or when the HCD is being stopped. ++ */ ++static void kill_all_urbs(dwc_otg_hcd_t * hcd) ++{ ++ kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive); ++ kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued); ++} ++ ++/** ++ * Start the connection timer. An OTG host is required to display a ++ * message if the device does not connect within 10 seconds. The ++ * timer is deleted if a port connect interrupt occurs before the ++ * timer expires. ++ */ ++static void dwc_otg_hcd_start_connect_timer(dwc_otg_hcd_t * hcd) ++{ ++ DWC_TIMER_SCHEDULE(hcd->conn_timer, 10000 /* 10 secs */ ); ++} ++ ++/** ++ * HCD Callback function for disconnect of the HCD. ++ * ++ * @param p void pointer to the struct usb_hcd ++ */ ++static int32_t dwc_otg_hcd_session_start_cb(void *p) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd; ++ DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p); ++ dwc_otg_hcd = p; ++ dwc_otg_hcd_start_connect_timer(dwc_otg_hcd); ++ return 1; ++} ++ ++/** ++ * HCD Callback function for starting the HCD when A-Cable is ++ * connected. ++ * ++ * @param p void pointer to the struct usb_hcd ++ */ ++static int32_t dwc_otg_hcd_start_cb(void *p) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = p; ++ dwc_otg_core_if_t *core_if; ++ hprt0_data_t hprt0; ++ uint32_t timeout = 50; ++ ++ core_if = dwc_otg_hcd->core_if; ++ /**@todo vahrama: Check the timeout value for OTG 2.0 */ ++ if (core_if->otg_ver) ++ timeout = 25; ++ if (core_if->op_state == B_HOST) { ++ /* ++ * Reset the port. During a HNP mode switch the reset ++ * needs to occur within 1ms and have a duration of at ++ * least 50ms. ++ */ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtrst = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ if (core_if->otg_ver) { ++ dwc_mdelay(60); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtrst = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } ++ } ++ DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg, ++ hcd_start_func, dwc_otg_hcd, timeout, ++ "start hcd"); ++ ++ return 1; ++} ++ ++/** ++ * HCD Callback function for disconnect of the HCD. ++ * ++ * @param p void pointer to the struct usb_hcd ++ */ ++static int32_t dwc_otg_hcd_disconnect_cb(void *p) ++{ ++ gintsts_data_t intr; ++ dwc_otg_hcd_t *dwc_otg_hcd = p; ++ ++ /* ++ * Set status flags for the hub driver. ++ */ ++ dwc_otg_hcd->flags.b.port_connect_status_change = 1; ++ dwc_otg_hcd->flags.b.port_connect_status = 0; ++ ++ /* ++ * Shutdown any transfers in process by clearing the Tx FIFO Empty ++ * interrupt mask and status bits and disabling subsequent host ++ * channel interrupts. ++ */ ++ intr.d32 = 0; ++ intr.b.nptxfempty = 1; ++ intr.b.ptxfempty = 1; ++ intr.b.hcintr = 1; ++ DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, ++ intr.d32, 0); ++ DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintsts, ++ intr.d32, 0); ++ ++ /* ++ * Turn off the vbus power only if the core has transitioned to device ++ * mode. If still in host mode, need to keep power on to detect a ++ * reconnection. ++ */ ++ if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) { ++ if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) { ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ DWC_PRINTF("Disconnect: PortPower off\n"); ++ hprt0.b.prtpwr = 0; ++ DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, ++ hprt0.d32); ++ } ++ /** Delete timers if become device */ ++ del_timers(dwc_otg_hcd); ++ dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if); ++ } ++ ++ /* Respond with an error status to all URBs in the schedule. */ ++ kill_all_urbs(dwc_otg_hcd); ++ ++ if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) { ++ /* Clean up any host channels that were in use. */ ++ int num_channels; ++ int i; ++ dwc_hc_t *channel; ++ dwc_otg_hc_regs_t *hc_regs; ++ hcchar_data_t hcchar; ++ ++ if (dwc_otg_hcd->core_if->otg_ver == 1) ++ del_xfer_timers(dwc_otg_hcd); ++ else ++ del_timers(dwc_otg_hcd); ++ ++ num_channels = dwc_otg_hcd->core_if->core_params->host_channels; ++ ++ if (!dwc_otg_hcd->core_if->dma_enable) { ++ /* Flush out any channel requests in slave mode. */ ++ for (i = 0; i < num_channels; i++) { ++ channel = dwc_otg_hcd->hc_ptr_array[i]; ++ if (DWC_CIRCLEQ_EMPTY_ENTRY ++ (channel, hc_list_entry)) { ++ hc_regs = ++ dwc_otg_hcd->core_if-> ++ host_if->hc_regs[i]; ++ hcchar.d32 = ++ DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chen = 0; ++ hcchar.b.chdis = 1; ++ hcchar.b.epdir = 0; ++ DWC_WRITE_REG32 ++ (&hc_regs->hcchar, ++ hcchar.d32); ++ } ++ } ++ } ++ } ++ ++ for (i = 0; i < num_channels; i++) { ++ channel = dwc_otg_hcd->hc_ptr_array[i]; ++ if (DWC_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) { ++ hc_regs = ++ dwc_otg_hcd->core_if->host_if->hc_regs[i]; ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ /* Halt the channel. */ ++ hcchar.b.chdis = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, ++ hcchar.d32); ++ } ++ ++ dwc_otg_hc_cleanup(dwc_otg_hcd->core_if, ++ channel); ++ DWC_CIRCLEQ_INSERT_TAIL ++ (&dwc_otg_hcd->free_hc_list, channel, ++ hc_list_entry); ++ /* ++ * Added for Descriptor DMA to prevent channel double cleanup ++ * in release_channel_ddma(). Which called from ep_disable ++ * when device disconnect. ++ */ ++ channel->qh = NULL; ++ } ++ } ++ } ++ ++ if (dwc_otg_hcd->fops->disconnect) { ++ dwc_otg_hcd->fops->disconnect(dwc_otg_hcd); ++ } ++ ++ return 1; ++} ++ ++/** ++ * HCD Callback function for stopping the HCD. ++ * ++ * @param p void pointer to the struct usb_hcd ++ */ ++static int32_t dwc_otg_hcd_stop_cb(void *p) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = p; ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p); ++ dwc_otg_hcd_stop(dwc_otg_hcd); ++ return 1; ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++/** ++ * HCD Callback function for sleep of HCD. ++ * ++ * @param p void pointer to the struct usb_hcd ++ */ ++static int dwc_otg_hcd_sleep_cb(void *p) ++{ ++ dwc_otg_hcd_t *hcd = p; ++ ++ dwc_otg_hcd_free_hc_from_lpm(hcd); ++ ++ return 0; ++} ++#endif ++ ++/** ++ * HCD Callback function for Remote Wakeup. ++ * ++ * @param p void pointer to the struct usb_hcd ++ */ ++static int dwc_otg_hcd_rem_wakeup_cb(void *p) ++{ ++ dwc_otg_hcd_t *hcd = p; ++ ++ if (hcd->core_if->lx_state == DWC_OTG_L2) { ++ hcd->flags.b.port_suspend_change = 1; ++ } ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ else { ++ hcd->flags.b.port_l1_change = 1; ++ } ++#endif ++ return 0; ++} ++ ++/** ++ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are ++ * stopped. ++ */ ++void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd) ++{ ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n"); ++ ++ /* ++ * The root hub should be disconnected before this function is called. ++ * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue) ++ * and the QH lists (via ..._hcd_endpoint_disable). ++ */ ++ ++ /* Turn off all host-specific interrupts. */ ++ dwc_otg_disable_host_interrupts(hcd->core_if); ++ ++ /* Turn off the vbus power */ ++ DWC_PRINTF("PortPower off\n"); ++ hprt0.b.prtpwr = 0; ++ DWC_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32); ++ dwc_mdelay(1); ++} ++ ++int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd, ++ dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle, ++ int atomic_alloc) ++{ ++ dwc_irqflags_t flags; ++ int retval = 0; ++ dwc_otg_qtd_t *qtd; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ if (!hcd->flags.b.port_connect_status) { ++ /* No longer connected. */ ++ DWC_ERROR("Not connected\n"); ++ return -DWC_E_NO_DEVICE; ++ } ++ ++ qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc); ++ if (qtd == NULL) { ++ DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n"); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ retval = ++ dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc); ++ if (retval < 0) { ++ DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. " ++ "Error status %d\n", retval); ++ dwc_otg_hcd_qtd_free(qtd); ++ } else { ++ qtd->qh = *ep_handle; ++ } ++ intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk); ++ if (!intr_mask.b.sofintr && retval == 0) { ++ dwc_otg_transaction_type_e tr_type; ++ if ((qtd->qh->ep_type == UE_BULK) ++ && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) { ++ /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */ ++ return 0; ++ } ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ tr_type = dwc_otg_hcd_select_transactions(hcd); ++ if (tr_type != DWC_OTG_TRANSACTION_NONE) { ++ dwc_otg_hcd_queue_transactions(hcd, tr_type); ++ } ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ } ++ ++ return retval; ++} ++ ++int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd, ++ dwc_otg_hcd_urb_t * dwc_otg_urb) ++{ ++ dwc_otg_qh_t *qh; ++ dwc_otg_qtd_t *urb_qtd; ++ ++ urb_qtd = dwc_otg_urb->qtd; ++ qh = urb_qtd->qh; ++#ifdef DEBUG ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ if (urb_qtd->in_process) { ++ dump_channel_info(hcd, qh); ++ } ++ } ++#endif ++ if (urb_qtd->in_process && qh->channel) { ++ /* The QTD is in process (it has been assigned to a channel). */ ++ if (hcd->flags.b.port_connect_status) { ++ /* ++ * If still connected (i.e. in host mode), halt the ++ * channel so it can be used for other transfers. If ++ * no longer connected, the host registers can't be ++ * written to halt the channel since the core is in ++ * device mode. ++ */ ++ dwc_otg_hc_halt(hcd->core_if, qh->channel, ++ DWC_OTG_HC_XFER_URB_DEQUEUE); ++ } ++ } ++ ++ /* ++ * Free the QTD and clean up the associated QH. Leave the QH in the ++ * schedule if it has any remaining QTDs. ++ */ ++ ++ if (!hcd->core_if->dma_desc_enable) { ++ uint8_t b = urb_qtd->in_process; ++ dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh); ++ if (b) { ++ dwc_otg_hcd_qh_deactivate(hcd, qh, 0); ++ qh->channel = NULL; ++ } else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ } ++ } else { ++ dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh); ++ } ++ return 0; ++} ++ ++int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle, ++ int retry) ++{ ++ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; ++ int retval = 0; ++ dwc_irqflags_t flags; ++ ++ if (retry < 0) { ++ retval = -DWC_E_INVALID; ++ goto done; ++ } ++ ++ if (!qh) { ++ retval = -DWC_E_INVALID; ++ goto done; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ ++ while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) { ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ retry--; ++ dwc_msleep(5); ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ } ++ ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ /* ++ * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove ++ * and qh_free to prevent stack dump on DWC_DMA_FREE() with ++ * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free() ++ * and dwc_otg_hcd_frame_list_alloc(). ++ */ ++ dwc_otg_hcd_qh_free(hcd, qh); ++ ++done: ++ return retval; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle) ++{ ++ int retval = 0; ++ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; ++ if (!qh) ++ return -DWC_E_INVALID; ++ ++ qh->data_toggle = DWC_OTG_HC_PID_DATA0; ++ return retval; ++} ++#endif ++ ++/** ++ * HCD Callback structure for handling mode switching. ++ */ ++static dwc_otg_cil_callbacks_t hcd_cil_callbacks = { ++ .start = dwc_otg_hcd_start_cb, ++ .stop = dwc_otg_hcd_stop_cb, ++ .disconnect = dwc_otg_hcd_disconnect_cb, ++ .session_start = dwc_otg_hcd_session_start_cb, ++ .resume_wakeup = dwc_otg_hcd_rem_wakeup_cb, ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ .sleep = dwc_otg_hcd_sleep_cb, ++#endif ++ .p = 0, ++}; ++ ++/** ++ * Reset tasklet function ++ */ ++static void reset_tasklet_func(void *data) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *) data; ++ dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; ++ hprt0_data_t hprt0; ++ ++ DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n"); ++ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtrst = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ dwc_mdelay(60); ++ ++ hprt0.b.prtrst = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ dwc_otg_hcd->flags.b.port_reset_change = 1; ++} ++ ++static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list) ++{ ++ dwc_list_link_t *item; ++ dwc_otg_qh_t *qh; ++ dwc_irqflags_t flags; ++ ++ if (!qh_list->next) { ++ /* The list hasn't been initialized yet. */ ++ return; ++ } ++ /* ++ * Hold spinlock here. Not needed in that case if bellow ++ * function is being called from ISR ++ */ ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ /* Ensure there are no QTDs or URBs left. */ ++ kill_urbs_in_qh_list(hcd, qh_list); ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ ++ DWC_LIST_FOREACH(item, qh_list) { ++ qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry); ++ dwc_otg_hcd_qh_remove_and_free(hcd, qh); ++ } ++} ++ ++/** ++ * Exit from Hibernation if Host did not detect SRP from connected SRP capable ++ * Device during SRP time by host power up. ++ */ ++void dwc_otg_hcd_power_up(void *ptr) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; ++ ++ DWC_PRINTF("%s called\n", __FUNCTION__); ++ ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return; ++ } ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Enable VBUS */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++} ++ ++/** ++ * Frees secondary storage associated with the dwc_otg_hcd structure contained ++ * in the struct usb_hcd field. ++ */ ++static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ int i; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n"); ++ ++ del_timers(dwc_otg_hcd); ++ ++ /* Free memory for QH/QTD lists */ ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued); ++ ++ /* Free memory for the host channels. */ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ dwc_hc_t *hc = dwc_otg_hcd->hc_ptr_array[i]; ++ ++#ifdef DEBUG ++ if (dwc_otg_hcd->core_if->hc_xfer_timer[i]) { ++ DWC_TIMER_FREE(dwc_otg_hcd->core_if->hc_xfer_timer[i]); ++ } ++#endif ++ if (hc != NULL) { ++ DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n", ++ i, hc); ++ DWC_FREE(hc); ++ } ++ } ++ ++ if (dwc_otg_hcd->core_if->dma_enable) { ++ if (dwc_otg_hcd->status_buf_dma) { ++ DWC_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE, ++ dwc_otg_hcd->status_buf, ++ dwc_otg_hcd->status_buf_dma); ++ } ++ } else if (dwc_otg_hcd->status_buf != NULL) { ++ DWC_FREE(dwc_otg_hcd->status_buf); ++ } ++ DWC_SPINLOCK_FREE(dwc_otg_hcd->lock); ++ /* Set core_if's lock pointer to NULL */ ++ dwc_otg_hcd->core_if->lock = NULL; ++ ++ DWC_TIMER_FREE(dwc_otg_hcd->conn_timer); ++ DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet); ++ ++#ifdef DWC_DEV_SRPCAP ++ if (dwc_otg_hcd->core_if->power_down == 2 && ++ dwc_otg_hcd->core_if->pwron_timer) { ++ DWC_TIMER_FREE(dwc_otg_hcd->core_if->pwron_timer); ++ } ++#endif ++ DWC_FREE(dwc_otg_hcd); ++} ++ ++int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) ++{ ++ int retval = 0; ++ int num_channels; ++ int i; ++ dwc_hc_t *channel; ++ ++ hcd->lock = DWC_SPINLOCK_ALLOC(); ++ if (!hcd->lock) { ++ DWC_ERROR("Could not allocate lock for pcd"); ++ DWC_FREE(hcd); ++ retval = -DWC_E_NO_MEMORY; ++ goto out; ++ } ++ hcd->core_if = core_if; ++ ++ /* Register the HCD CIL Callbacks */ ++ dwc_otg_cil_register_hcd_callbacks(hcd->core_if, ++ &hcd_cil_callbacks, hcd); ++ ++ /* Initialize the non-periodic schedule. */ ++ DWC_LIST_INIT(&hcd->non_periodic_sched_inactive); ++ DWC_LIST_INIT(&hcd->non_periodic_sched_active); ++ ++ /* Initialize the periodic schedule. */ ++ DWC_LIST_INIT(&hcd->periodic_sched_inactive); ++ DWC_LIST_INIT(&hcd->periodic_sched_ready); ++ DWC_LIST_INIT(&hcd->periodic_sched_assigned); ++ DWC_LIST_INIT(&hcd->periodic_sched_queued); ++ ++ /* ++ * Create a host channel descriptor for each host channel implemented ++ * in the controller. Initialize the channel descriptor array. ++ */ ++ DWC_CIRCLEQ_INIT(&hcd->free_hc_list); ++ num_channels = hcd->core_if->core_params->host_channels; ++ DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array)); ++ for (i = 0; i < num_channels; i++) { ++ channel = DWC_ALLOC(sizeof(dwc_hc_t)); ++ if (channel == NULL) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR("%s: host channel allocation failed\n", ++ __func__); ++ dwc_otg_hcd_free(hcd); ++ goto out; ++ } ++ channel->hc_num = i; ++ hcd->hc_ptr_array[i] = channel; ++#ifdef DEBUG ++ hcd->core_if->hc_xfer_timer[i] = ++ DWC_TIMER_ALLOC("hc timer", hc_xfer_timeout, ++ &hcd->core_if->hc_xfer_info[i]); ++#endif ++ DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i, ++ channel); ++ } ++ ++ /* Initialize the Connection timeout timer. */ ++ hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer", ++ dwc_otg_hcd_connect_timeout, hcd); ++ ++ /* Initialize reset tasklet. */ ++ hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd); ++#ifdef DWC_DEV_SRPCAP ++ if (hcd->core_if->power_down == 2) { ++ /* Initialize Power on timer for Host power up in case hibernation */ ++ hcd->core_if->pwron_timer = DWC_TIMER_ALLOC("PWRON TIMER", ++ dwc_otg_hcd_power_up, core_if); ++ } ++#endif ++ ++ /* ++ * Allocate space for storing data on status transactions. Normally no ++ * data is sent, but this space acts as a bit bucket. This must be ++ * done after usb_add_hcd since that function allocates the DMA buffer ++ * pool. ++ */ ++ if (hcd->core_if->dma_enable) { ++ hcd->status_buf = ++ DWC_DMA_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE, ++ &hcd->status_buf_dma); ++ } else { ++ hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE); ++ } ++ if (!hcd->status_buf) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR("%s: status_buf allocation failed\n", __func__); ++ dwc_otg_hcd_free(hcd); ++ goto out; ++ } ++ ++ hcd->otg_port = 1; ++ hcd->frame_list = NULL; ++ hcd->frame_list_dma = 0; ++ hcd->periodic_qh_count = 0; ++out: ++ return retval; ++} ++ ++void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd) ++{ ++ /* Turn off all host-specific interrupts. */ ++ dwc_otg_disable_host_interrupts(hcd->core_if); ++ ++ dwc_otg_hcd_free(hcd); ++} ++ ++/** ++ * Initializes dynamic portions of the DWC_otg HCD state. ++ */ ++static void dwc_otg_hcd_reinit(dwc_otg_hcd_t * hcd) ++{ ++ int num_channels; ++ int i; ++ dwc_hc_t *channel; ++ dwc_hc_t *channel_tmp; ++ ++ hcd->flags.d32 = 0; ++ ++ hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active; ++ hcd->non_periodic_channels = 0; ++ hcd->periodic_channels = 0; ++ ++ /* ++ * Put all channels in the free channel list and clean up channel ++ * states. ++ */ ++ DWC_CIRCLEQ_FOREACH_SAFE(channel, channel_tmp, ++ &hcd->free_hc_list, hc_list_entry) { ++ DWC_CIRCLEQ_REMOVE(&hcd->free_hc_list, channel, hc_list_entry); ++ } ++ ++ num_channels = hcd->core_if->core_params->host_channels; ++ for (i = 0; i < num_channels; i++) { ++ channel = hcd->hc_ptr_array[i]; ++ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, channel, ++ hc_list_entry); ++ dwc_otg_hc_cleanup(hcd->core_if, channel); ++ } ++ ++ /* Initialize the DWC core for host mode operation. */ ++ dwc_otg_core_host_init(hcd->core_if); ++ ++ /* Set core_if's lock pointer to the hcd->lock */ ++ hcd->core_if->lock = hcd->lock; ++} ++ ++/** ++ * Assigns transactions from a QTD to a free host channel and initializes the ++ * host channel to perform the transactions. The host channel is removed from ++ * the free list. ++ * ++ * @param hcd The HCD state structure. ++ * @param qh Transactions from the first QTD for this QH are selected and ++ * assigned to a free host channel. ++ */ ++static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ dwc_hc_t *hc = NULL; ++ dwc_otg_qtd_t *qtd; ++ dwc_otg_hcd_urb_t *urb; ++ void* ptr = NULL; ++ hcchar_data_t hcchar; ++ int num_channels; ++ int i; ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p)\n", __func__, hcd, qh); ++ ++ num_channels = hcd->core_if->core_params->host_channels; ++ ++ /* WA to not select channel with chdis bit set, this was ++ * observed after role switch as part of OTG 2.0 HNP ++ */ ++ for (i = 0; i < num_channels; i++) { ++ hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list); ++ hcchar.d32 = DWC_READ_REG32(&hcd->core_if->host_if->hc_regs[hc->hc_num]->hcchar); ++ DWC_DEBUGPL(DBG_HCDV, "HC num = %d HCCHAR %08x\n", hc->hc_num, hcchar.d32); ++ if(!hcchar.b.chdis && !hcchar.b.chen) ++ break; ++ DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry); ++ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); ++ hc = NULL; ++ } ++ if (!hc) { ++ DWC_ERROR("No free channel with en and dis bits 0\n"); ++ return; ++ } ++ ++ ++ ++ /* Remove the host channel from the free list. */ ++ DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry); ++ ++ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); ++ ++ urb = qtd->urb; ++ qh->channel = hc; ++ ++ qtd->in_process = 1; ++ ++ /* ++ * Use usb_pipedevice to determine device address. This address is ++ * 0 before the SET_ADDRESS command and the correct address afterward. ++ */ ++ hc->dev_addr = dwc_otg_hcd_get_dev_addr(&urb->pipe_info); ++ hc->ep_num = dwc_otg_hcd_get_ep_num(&urb->pipe_info); ++ hc->speed = qh->dev_speed; ++ hc->max_packet = dwc_max_packet(qh->maxp); ++ ++ hc->xfer_started = 0; ++ hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS; ++ hc->error_state = (qtd->error_count > 0); ++ hc->halt_on_queue = 0; ++ hc->halt_pending = 0; ++ hc->requests = 0; ++ ++ /* ++ * The following values may be modified in the transfer type section ++ * below. The xfer_len value may be reduced when the transfer is ++ * started to accommodate the max widths of the XferSize and PktCnt ++ * fields in the HCTSIZn register. ++ */ ++ ++ hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0); ++ if (hc->ep_is_in) { ++ hc->do_ping = 0; ++ } else { ++ hc->do_ping = qh->ping_state; ++ } ++ ++ hc->data_pid_start = qh->data_toggle; ++ hc->multi_count = 1; ++ ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length; ++ ++ /* For non-dword aligned case */ ++ if (((unsigned long)hc->xfer_buff & 0x3) ++ && !hcd->core_if->dma_desc_enable) { ++ ptr = (uint8_t *) urb->buf + urb->actual_length; ++ } ++ } else { ++ hc->xfer_buff = (uint8_t *) urb->buf + urb->actual_length; ++ } ++ hc->xfer_len = urb->length - urb->actual_length; ++ hc->xfer_count = 0; ++ ++ /* ++ * Set the split attributes ++ */ ++ hc->do_split = 0; ++ if (qh->do_split) { ++ uint32_t hub_addr, port_addr; ++ hc->do_split = 1; ++ hc->xact_pos = qtd->isoc_split_pos; ++ hc->complete_split = qtd->complete_split; ++ hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr); ++ hc->hub_addr = (uint8_t) hub_addr; ++ hc->port_addr = (uint8_t) port_addr; ++ } ++ ++ switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) { ++ case UE_CONTROL: ++ hc->ep_type = DWC_OTG_EP_TYPE_CONTROL; ++ switch (qtd->control_phase) { ++ case DWC_OTG_CONTROL_SETUP: ++ DWC_DEBUGPL(DBG_HCDV, " Control setup transaction\n"); ++ hc->do_ping = 0; ++ hc->ep_is_in = 0; ++ hc->data_pid_start = DWC_OTG_HC_PID_SETUP; ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = (uint8_t *) urb->setup_dma; ++ } else { ++ hc->xfer_buff = (uint8_t *) urb->setup_packet; ++ } ++ hc->xfer_len = 8; ++ ptr = NULL; ++ break; ++ case DWC_OTG_CONTROL_DATA: ++ DWC_DEBUGPL(DBG_HCDV, " Control data transaction\n"); ++ hc->data_pid_start = qtd->data_toggle; ++ break; ++ case DWC_OTG_CONTROL_STATUS: ++ /* ++ * Direction is opposite of data direction or IN if no ++ * data. ++ */ ++ DWC_DEBUGPL(DBG_HCDV, " Control status transaction\n"); ++ if (urb->length == 0) { ++ hc->ep_is_in = 1; ++ } else { ++ hc->ep_is_in = ++ dwc_otg_hcd_is_pipe_out(&urb->pipe_info); ++ } ++ if (hc->ep_is_in) { ++ hc->do_ping = 0; ++ } ++ ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA1; ++ ++ hc->xfer_len = 0; ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = (uint8_t *) hcd->status_buf_dma; ++ } else { ++ hc->xfer_buff = (uint8_t *) hcd->status_buf; ++ } ++ ptr = NULL; ++ break; ++ } ++ break; ++ case UE_BULK: ++ hc->ep_type = DWC_OTG_EP_TYPE_BULK; ++ break; ++ case UE_INTERRUPT: ++ hc->ep_type = DWC_OTG_EP_TYPE_INTR; ++ break; ++ case UE_ISOCHRONOUS: ++ { ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc; ++ ++ hc->ep_type = DWC_OTG_EP_TYPE_ISOC; ++ ++ if (hcd->core_if->dma_desc_enable) ++ break; ++ ++ frame_desc = &urb->iso_descs[qtd->isoc_frame_index]; ++ ++ frame_desc->status = 0; ++ ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = (uint8_t *) urb->dma; ++ } else { ++ hc->xfer_buff = (uint8_t *) urb->buf; ++ } ++ hc->xfer_buff += ++ frame_desc->offset + qtd->isoc_split_offset; ++ hc->xfer_len = ++ frame_desc->length - qtd->isoc_split_offset; ++ ++ /* For non-dword aligned buffers */ ++ if (((unsigned long)hc->xfer_buff & 0x3) ++ && hcd->core_if->dma_enable) { ++ ptr = ++ (uint8_t *) urb->buf + frame_desc->offset + ++ qtd->isoc_split_offset; ++ } else ++ ptr = NULL; ++ ++ if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) { ++ if (hc->xfer_len <= 188) { ++ hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL; ++ } else { ++ hc->xact_pos = ++ DWC_HCSPLIT_XACTPOS_BEGIN; ++ } ++ } ++ } ++ break; ++ } ++ /* non DWORD-aligned buffer case */ ++ if (ptr) { ++ uint32_t buf_size; ++ if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { ++ buf_size = hcd->core_if->core_params->max_transfer_size; ++ } else { ++ buf_size = 4096; ++ } ++ if (!qh->dw_align_buf) { ++ qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(buf_size, ++ &qh->dw_align_buf_dma); ++ if (!qh->dw_align_buf) { ++ DWC_ERROR ++ ("%s: Failed to allocate memory to handle " ++ "non-dword aligned buffer case\n", ++ __func__); ++ return; ++ } ++ } ++ if (!hc->ep_is_in) { ++ dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len); ++ } ++ hc->align_buff = qh->dw_align_buf_dma; ++ } else { ++ hc->align_buff = 0; ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * This value may be modified when the transfer is started to ++ * reflect the actual transfer length. ++ */ ++ hc->multi_count = dwc_hb_mult(qh->maxp); ++ } ++ ++ if (hcd->core_if->dma_desc_enable) ++ hc->desc_list_addr = qh->desc_list_dma; ++ ++ dwc_otg_hc_init(hcd->core_if, hc); ++ hc->qh = qh; ++} ++ ++/** ++ * This function selects transactions from the HCD transfer schedule and ++ * assigns them to available host channels. It is called from HCD interrupt ++ * handler functions. ++ * ++ * @param hcd The HCD state structure. ++ * ++ * @return The types of new transactions that were assigned to host channels. ++ */ ++dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) ++{ ++ dwc_list_link_t *qh_ptr; ++ dwc_otg_qh_t *qh; ++ int num_channels; ++ dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE; ++ ++#ifdef DEBUG_SOF ++ DWC_DEBUGPL(DBG_HCD, " Select Transactions\n"); ++#endif ++ ++ /* Process entries in the periodic ready list. */ ++ qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready); ++ ++ while (qh_ptr != &hcd->periodic_sched_ready && ++ !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { ++ ++ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); ++ assign_and_init_hc(hcd, qh); ++ ++ /* ++ * Move the QH from the periodic ready schedule to the ++ * periodic assigned schedule. ++ */ ++ qh_ptr = DWC_LIST_NEXT(qh_ptr); ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, ++ &qh->qh_list_entry); ++ ++ ret_val = DWC_OTG_TRANSACTION_PERIODIC; ++ } ++ ++ /* ++ * Process entries in the inactive portion of the non-periodic ++ * schedule. Some free host channels may not be used if they are ++ * reserved for periodic transfers. ++ */ ++ qh_ptr = hcd->non_periodic_sched_inactive.next; ++ num_channels = hcd->core_if->core_params->host_channels; ++ while (qh_ptr != &hcd->non_periodic_sched_inactive && ++ (hcd->non_periodic_channels < ++ num_channels - hcd->periodic_channels) && ++ !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { ++ ++ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); ++ ++ assign_and_init_hc(hcd, qh); ++ ++ /* ++ * Move the QH from the non-periodic inactive schedule to the ++ * non-periodic active schedule. ++ */ ++ qh_ptr = DWC_LIST_NEXT(qh_ptr); ++ DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active, ++ &qh->qh_list_entry); ++ ++ if (ret_val == DWC_OTG_TRANSACTION_NONE) { ++ ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC; ++ } else { ++ ret_val = DWC_OTG_TRANSACTION_ALL; ++ } ++ ++ hcd->non_periodic_channels++; ++ } ++ ++ return ret_val; ++} ++ ++/** ++ * Attempts to queue a single transaction request for a host channel ++ * associated with either a periodic or non-periodic transfer. This function ++ * assumes that there is space available in the appropriate request queue. For ++ * an OUT transfer or SETUP transaction in Slave mode, it checks whether space ++ * is available in the appropriate Tx FIFO. ++ * ++ * @param hcd The HCD state structure. ++ * @param hc Host channel descriptor associated with either a periodic or ++ * non-periodic transfer. ++ * @param fifo_dwords_avail Number of DWORDs available in the periodic Tx ++ * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic ++ * transfers. ++ * ++ * @return 1 if a request is queued and more requests may be needed to ++ * complete the transfer, 0 if no more requests are required for this ++ * transfer, -1 if there is insufficient space in the Tx FIFO. ++ */ ++static int queue_transaction(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, uint16_t fifo_dwords_avail) ++{ ++ int retval; ++ ++ if (hcd->core_if->dma_enable) { ++ if (hcd->core_if->dma_desc_enable) { ++ if (!hc->xfer_started ++ || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) { ++ dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh); ++ hc->qh->ping_state = 0; ++ } ++ } else if (!hc->xfer_started) { ++ dwc_otg_hc_start_transfer(hcd->core_if, hc); ++ hc->qh->ping_state = 0; ++ } ++ retval = 0; ++ } else if (hc->halt_pending) { ++ /* Don't queue a request if the channel has been halted. */ ++ retval = 0; ++ } else if (hc->halt_on_queue) { ++ dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status); ++ retval = 0; ++ } else if (hc->do_ping) { ++ if (!hc->xfer_started) { ++ dwc_otg_hc_start_transfer(hcd->core_if, hc); ++ } ++ retval = 0; ++ } else if (!hc->ep_is_in || hc->data_pid_start == DWC_OTG_HC_PID_SETUP) { ++ if ((fifo_dwords_avail * 4) >= hc->max_packet) { ++ if (!hc->xfer_started) { ++ dwc_otg_hc_start_transfer(hcd->core_if, hc); ++ retval = 1; ++ } else { ++ retval = ++ dwc_otg_hc_continue_transfer(hcd->core_if, ++ hc); ++ } ++ } else { ++ retval = -1; ++ } ++ } else { ++ if (!hc->xfer_started) { ++ dwc_otg_hc_start_transfer(hcd->core_if, hc); ++ retval = 1; ++ } else { ++ retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc); ++ } ++ } ++ ++ return retval; ++} ++ ++/** ++ * Processes periodic channels for the next frame and queues transactions for ++ * these channels to the DWC_otg controller. After queueing transactions, the ++ * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions ++ * to queue as Periodic Tx FIFO or request queue space becomes available. ++ * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled. ++ */ ++static void process_periodic_channels(dwc_otg_hcd_t * hcd) ++{ ++ hptxsts_data_t tx_status; ++ dwc_list_link_t *qh_ptr; ++ dwc_otg_qh_t *qh; ++ int status; ++ int no_queue_space = 0; ++ int no_fifo_space = 0; ++ ++ dwc_otg_host_global_regs_t *host_regs; ++ host_regs = hcd->core_if->host_if->host_global_regs; ++ ++ DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n"); ++#ifdef DEBUG ++ tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts); ++ DWC_DEBUGPL(DBG_HCDV, ++ " P Tx Req Queue Space Avail (before queue): %d\n", ++ tx_status.b.ptxqspcavail); ++ DWC_DEBUGPL(DBG_HCDV, " P Tx FIFO Space Avail (before queue): %d\n", ++ tx_status.b.ptxfspcavail); ++#endif ++ ++ qh_ptr = hcd->periodic_sched_assigned.next; ++ while (qh_ptr != &hcd->periodic_sched_assigned) { ++ tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts); ++ if (tx_status.b.ptxqspcavail == 0) { ++ no_queue_space = 1; ++ break; ++ } ++ ++ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); ++ ++ /* ++ * Set a flag if we're queuing high-bandwidth in slave mode. ++ * The flag prevents any halts to get into the request queue in ++ * the middle of multiple high-bandwidth packets getting queued. ++ */ ++ if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) { ++ hcd->core_if->queuing_high_bandwidth = 1; ++ } ++ status = ++ queue_transaction(hcd, qh->channel, ++ tx_status.b.ptxfspcavail); ++ if (status < 0) { ++ no_fifo_space = 1; ++ break; ++ } ++ ++ /* ++ * In Slave mode, stay on the current transfer until there is ++ * nothing more to do or the high-bandwidth request count is ++ * reached. In DMA mode, only need to queue one request. The ++ * controller automatically handles multiple packets for ++ * high-bandwidth transfers. ++ */ ++ if (hcd->core_if->dma_enable || status == 0 || ++ qh->channel->requests == qh->channel->multi_count) { ++ qh_ptr = qh_ptr->next; ++ /* ++ * Move the QH from the periodic assigned schedule to ++ * the periodic queued schedule. ++ */ ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_queued, ++ &qh->qh_list_entry); ++ ++ /* done queuing high bandwidth */ ++ hcd->core_if->queuing_high_bandwidth = 0; ++ } ++ } ++ ++ if (!hcd->core_if->dma_enable) { ++ dwc_otg_core_global_regs_t *global_regs; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ global_regs = hcd->core_if->core_global_regs; ++ intr_mask.b.ptxfempty = 1; ++#ifdef DEBUG ++ tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts); ++ DWC_DEBUGPL(DBG_HCDV, ++ " P Tx Req Queue Space Avail (after queue): %d\n", ++ tx_status.b.ptxqspcavail); ++ DWC_DEBUGPL(DBG_HCDV, ++ " P Tx FIFO Space Avail (after queue): %d\n", ++ tx_status.b.ptxfspcavail); ++#endif ++ if (!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned) || ++ no_queue_space || no_fifo_space) { ++ /* ++ * May need to queue more transactions as the request ++ * queue or Tx FIFO empties. Enable the periodic Tx ++ * FIFO empty interrupt. (Always use the half-empty ++ * level to ensure that new requests are loaded as ++ * soon as possible.) ++ */ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, ++ intr_mask.d32); ++ } else { ++ /* ++ * Disable the Tx FIFO empty interrupt since there are ++ * no more transactions that need to be queued right ++ * now. This function is called from interrupt ++ * handlers to queue more transactions as transfer ++ * states change. ++ */ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, ++ 0); ++ } ++ } ++} ++ ++/** ++ * Processes active non-periodic channels and queues transactions for these ++ * channels to the DWC_otg controller. After queueing transactions, the NP Tx ++ * FIFO Empty interrupt is enabled if there are more transactions to queue as ++ * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx ++ * FIFO Empty interrupt is disabled. ++ */ ++static void process_non_periodic_channels(dwc_otg_hcd_t * hcd) ++{ ++ gnptxsts_data_t tx_status; ++ dwc_list_link_t *orig_qh_ptr; ++ dwc_otg_qh_t *qh; ++ int status; ++ int no_queue_space = 0; ++ int no_fifo_space = 0; ++ int more_to_do = 0; ++ ++ dwc_otg_core_global_regs_t *global_regs = ++ hcd->core_if->core_global_regs; ++ ++ DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n"); ++#ifdef DEBUG ++ tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts); ++ DWC_DEBUGPL(DBG_HCDV, ++ " NP Tx Req Queue Space Avail (before queue): %d\n", ++ tx_status.b.nptxqspcavail); ++ DWC_DEBUGPL(DBG_HCDV, " NP Tx FIFO Space Avail (before queue): %d\n", ++ tx_status.b.nptxfspcavail); ++#endif ++ /* ++ * Keep track of the starting point. Skip over the start-of-list ++ * entry. ++ */ ++ if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) { ++ hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; ++ } ++ orig_qh_ptr = hcd->non_periodic_qh_ptr; ++ ++ /* ++ * Process once through the active list or until no more space is ++ * available in the request queue or the Tx FIFO. ++ */ ++ do { ++ tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts); ++ if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) { ++ no_queue_space = 1; ++ break; ++ } ++ ++ qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t, ++ qh_list_entry); ++ status = ++ queue_transaction(hcd, qh->channel, ++ tx_status.b.nptxfspcavail); ++ ++ if (status > 0) { ++ more_to_do = 1; ++ } else if (status < 0) { ++ no_fifo_space = 1; ++ break; ++ } ++ ++ /* Advance to next QH, skipping start-of-list entry. */ ++ hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; ++ if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) { ++ hcd->non_periodic_qh_ptr = ++ hcd->non_periodic_qh_ptr->next; ++ } ++ ++ } while (hcd->non_periodic_qh_ptr != orig_qh_ptr); ++ ++ if (!hcd->core_if->dma_enable) { ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ intr_mask.b.nptxfempty = 1; ++ ++#ifdef DEBUG ++ tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts); ++ DWC_DEBUGPL(DBG_HCDV, ++ " NP Tx Req Queue Space Avail (after queue): %d\n", ++ tx_status.b.nptxqspcavail); ++ DWC_DEBUGPL(DBG_HCDV, ++ " NP Tx FIFO Space Avail (after queue): %d\n", ++ tx_status.b.nptxfspcavail); ++#endif ++ if (more_to_do || no_queue_space || no_fifo_space) { ++ /* ++ * May need to queue more transactions as the request ++ * queue or Tx FIFO empties. Enable the non-periodic ++ * Tx FIFO empty interrupt. (Always use the half-empty ++ * level to ensure that new requests are loaded as ++ * soon as possible.) ++ */ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, ++ intr_mask.d32); ++ } else { ++ /* ++ * Disable the Tx FIFO empty interrupt since there are ++ * no more transactions that need to be queued right ++ * now. This function is called from interrupt ++ * handlers to queue more transactions as transfer ++ * states change. ++ */ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, ++ 0); ++ } ++ } ++} ++ ++/** ++ * This function processes the currently active host channels and queues ++ * transactions for these channels to the DWC_otg controller. It is called ++ * from HCD interrupt handler functions. ++ * ++ * @param hcd The HCD state structure. ++ * @param tr_type The type(s) of transactions to queue (non-periodic, ++ * periodic, or both). ++ */ ++void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd, ++ dwc_otg_transaction_type_e tr_type) ++{ ++#ifdef DEBUG_SOF ++ DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n"); ++#endif ++ /* Process host channels associated with periodic transfers. */ ++ if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC || ++ tr_type == DWC_OTG_TRANSACTION_ALL) && ++ !DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) { ++ ++ process_periodic_channels(hcd); ++ } ++ ++ /* Process host channels associated with non-periodic transfers. */ ++ if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC || ++ tr_type == DWC_OTG_TRANSACTION_ALL) { ++ if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) { ++ process_non_periodic_channels(hcd); ++ } else { ++ /* ++ * Ensure NP Tx FIFO empty interrupt is disabled when ++ * there are no non-periodic transfers to process. ++ */ ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ gintmsk.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&hcd->core_if-> ++ core_global_regs->gintmsk, gintmsk.d32, ++ 0); ++ } ++ } ++} ++ ++#ifdef DWC_HS_ELECT_TST ++/* ++ * Quick and dirty hack to implement the HS Electrical Test ++ * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature. ++ * ++ * This code was copied from our userspace app "hset". It sends a ++ * Get Device Descriptor control sequence in two parts, first the ++ * Setup packet by itself, followed some time later by the In and ++ * Ack packets. Rather than trying to figure out how to add this ++ * functionality to the normal driver code, we just hijack the ++ * hardware, using these two function to drive the hardware ++ * directly. ++ */ ++ ++static dwc_otg_core_global_regs_t *global_regs; ++static dwc_otg_host_global_regs_t *hc_global_regs; ++static dwc_otg_hc_regs_t *hc_regs; ++static uint32_t *data_fifo; ++ ++static void do_setup(void) ++{ ++ gintsts_data_t gintsts; ++ hctsiz_data_t hctsiz; ++ hcchar_data_t hcchar; ++ haint_data_t haint; ++ hcint_data_t hcint; ++ ++ /* Enable HAINTs */ ++ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001); ++ ++ /* Enable HCINTs */ ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* ++ * Send Setup packet (Get Device Descriptor) ++ */ ++ ++ /* Make sure channel is disabled */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chdis = 1; ++// hcchar.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ //sleep(1); ++ dwc_mdelay(1000); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ } ++ ++ /* Set HCTSIZ */ ++ hctsiz.d32 = 0; ++ hctsiz.b.xfersize = 8; ++ hctsiz.b.pktcnt = 1; ++ hctsiz.b.pid = DWC_OTG_HC_PID_SETUP; ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ /* Set HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; ++ hcchar.b.epdir = 0; ++ hcchar.b.epnum = 0; ++ hcchar.b.mps = 8; ++ hcchar.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ /* Fill FIFO with Setup data for Get Device Descriptor */ ++ data_fifo = (uint32_t *) ((char *)global_regs + 0x1000); ++ DWC_WRITE_REG32(data_fifo++, 0x01000680); ++ DWC_WRITE_REG32(data_fifo++, 0x00080000); ++ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for host channel interrupt */ ++ do { ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.hcintr == 0); ++ ++ /* Disable HCINTs */ ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000); ++ ++ /* Disable HAINTs */ ++ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++} ++ ++static void do_in_ack(void) ++{ ++ gintsts_data_t gintsts; ++ hctsiz_data_t hctsiz; ++ hcchar_data_t hcchar; ++ haint_data_t haint; ++ hcint_data_t hcint; ++ host_grxsts_data_t grxsts; ++ ++ /* Enable HAINTs */ ++ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001); ++ ++ /* Enable HCINTs */ ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* ++ * Receive Control In packet ++ */ ++ ++ /* Make sure channel is disabled */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chdis = 1; ++ hcchar.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ //sleep(1); ++ dwc_mdelay(1000); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ } ++ ++ /* Set HCTSIZ */ ++ hctsiz.d32 = 0; ++ hctsiz.b.xfersize = 8; ++ hctsiz.b.pktcnt = 1; ++ hctsiz.b.pid = DWC_OTG_HC_PID_DATA1; ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ /* Set HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; ++ hcchar.b.epdir = 1; ++ hcchar.b.epnum = 0; ++ hcchar.b.mps = 8; ++ hcchar.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for receive status queue interrupt */ ++ do { ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.rxstsqlvl == 0); ++ ++ /* Read RXSTS */ ++ grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp); ++ ++ /* Clear RXSTSQLVL in GINTSTS */ ++ gintsts.d32 = 0; ++ gintsts.b.rxstsqlvl = 1; ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ switch (grxsts.b.pktsts) { ++ case DWC_GRXSTS_PKTSTS_IN: ++ /* Read the data into the host buffer */ ++ if (grxsts.b.bcnt > 0) { ++ int i; ++ int word_count = (grxsts.b.bcnt + 3) / 4; ++ ++ data_fifo = (uint32_t *) ((char *)global_regs + 0x1000); ++ ++ for (i = 0; i < word_count; i++) { ++ (void)DWC_READ_REG32(data_fifo++); ++ } ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for receive status queue interrupt */ ++ do { ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.rxstsqlvl == 0); ++ ++ /* Read RXSTS */ ++ grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp); ++ ++ /* Clear RXSTSQLVL in GINTSTS */ ++ gintsts.d32 = 0; ++ gintsts.b.rxstsqlvl = 1; ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ switch (grxsts.b.pktsts) { ++ case DWC_GRXSTS_PKTSTS_IN_XFER_COMP: ++ break; ++ ++ default: ++ break; ++ } ++ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for host channel interrupt */ ++ do { ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.hcintr == 0); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++// usleep(100000); ++// mdelay(100); ++ dwc_mdelay(1); ++ ++ /* ++ * Send handshake packet ++ */ ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Make sure channel is disabled */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chdis = 1; ++ hcchar.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ //sleep(1); ++ dwc_mdelay(1000); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ } ++ ++ /* Set HCTSIZ */ ++ hctsiz.d32 = 0; ++ hctsiz.b.xfersize = 0; ++ hctsiz.b.pktcnt = 1; ++ hctsiz.b.pid = DWC_OTG_HC_PID_DATA1; ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ /* Set HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; ++ hcchar.b.epdir = 0; ++ hcchar.b.epnum = 0; ++ hcchar.b.mps = 8; ++ hcchar.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for host channel interrupt */ ++ do { ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.hcintr == 0); ++ ++ /* Disable HCINTs */ ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000); ++ ++ /* Disable HAINTs */ ++ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++} ++#endif ++ ++/** Handles hub class-specific requests. */ ++int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, ++ uint16_t typeReq, ++ uint16_t wValue, ++ uint16_t wIndex, uint8_t * buf, uint16_t wLength) ++{ ++ int retval = 0; ++ ++ dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; ++ usb_hub_descriptor_t *hub_desc; ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ ++ uint32_t port_status; ++ ++ switch (typeReq) { ++ case UCR_CLEAR_HUB_FEATURE: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearHubFeature 0x%x\n", wValue); ++ switch (wValue) { ++ case UHF_C_HUB_LOCAL_POWER: ++ case UHF_C_HUB_OVER_CURRENT: ++ /* Nothing required here */ ++ break; ++ default: ++ retval = -DWC_E_INVALID; ++ DWC_ERROR("DWC OTG HCD - " ++ "ClearHubFeature request %xh unknown\n", ++ wValue); ++ } ++ break; ++ case UCR_CLEAR_PORT_FEATURE: ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ if (wValue != UHF_PORT_L1) ++#endif ++ if (!wIndex || wIndex > 1) ++ goto error; ++ ++ switch (wValue) { ++ case UHF_PORT_ENABLE: ++ DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_ENABLE\n"); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtena = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ break; ++ case UHF_PORT_SUSPEND: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_SUSPEND\n"); ++ ++ if (core_if->power_down == 2) { ++ dwc_otg_host_hibernation_restore(core_if, 0, 0); ++ } else { ++ DWC_WRITE_REG32(core_if->pcgcctl, 0); ++ dwc_mdelay(5); ++ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtres = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ hprt0.b.prtsusp = 0; ++ /* Clear Resume bit */ ++ dwc_mdelay(100); ++ hprt0.b.prtres = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } ++ break; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ case UHF_PORT_L1: ++ { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ glpmcfg_data_t lpmcfg = {.d32 = 0 }; ++ ++ lpmcfg.d32 = ++ DWC_READ_REG32(&core_if-> ++ core_global_regs->glpmcfg); ++ lpmcfg.b.en_utmi_sleep = 0; ++ lpmcfg.b.hird_thres &= (~(1 << 4)); ++ lpmcfg.b.prt_sleep_sts = 1; ++ DWC_WRITE_REG32(&core_if-> ++ core_global_regs->glpmcfg, ++ lpmcfg.d32); ++ ++ /* Clear Enbl_L1Gating bit. */ ++ pcgcctl.b.enbl_sleep_gating = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, ++ 0); ++ ++ dwc_mdelay(5); ++ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtres = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, ++ hprt0.d32); ++ /* This bit will be cleared in wakeup interrupt handle */ ++ break; ++ } ++#endif ++ case UHF_PORT_POWER: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_POWER\n"); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ break; ++ case UHF_PORT_INDICATOR: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_INDICATOR\n"); ++ /* Port inidicator not supported */ ++ break; ++ case UHF_C_PORT_CONNECTION: ++ /* Clears drivers internal connect status change ++ * flag */ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n"); ++ dwc_otg_hcd->flags.b.port_connect_status_change = 0; ++ break; ++ case UHF_C_PORT_RESET: ++ /* Clears the driver's internal Port Reset Change ++ * flag */ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_RESET\n"); ++ dwc_otg_hcd->flags.b.port_reset_change = 0; ++ break; ++ case UHF_C_PORT_ENABLE: ++ /* Clears the driver's internal Port ++ * Enable/Disable Change flag */ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n"); ++ dwc_otg_hcd->flags.b.port_enable_change = 0; ++ break; ++ case UHF_C_PORT_SUSPEND: ++ /* Clears the driver's internal Port Suspend ++ * Change flag, which is set when resume signaling on ++ * the host port is complete */ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n"); ++ dwc_otg_hcd->flags.b.port_suspend_change = 0; ++ break; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ case UHF_C_PORT_L1: ++ dwc_otg_hcd->flags.b.port_l1_change = 0; ++ break; ++#endif ++ case UHF_C_PORT_OVER_CURRENT: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n"); ++ dwc_otg_hcd->flags.b.port_over_current_change = 0; ++ break; ++ default: ++ retval = -DWC_E_INVALID; ++ DWC_ERROR("DWC OTG HCD - " ++ "ClearPortFeature request %xh " ++ "unknown or unsupported\n", wValue); ++ } ++ break; ++ case UCR_GET_HUB_DESCRIPTOR: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "GetHubDescriptor\n"); ++ hub_desc = (usb_hub_descriptor_t *) buf; ++ hub_desc->bDescLength = 9; ++ hub_desc->bDescriptorType = 0x29; ++ hub_desc->bNbrPorts = 1; ++ USETW(hub_desc->wHubCharacteristics, 0x08); ++ hub_desc->bPwrOn2PwrGood = 1; ++ hub_desc->bHubContrCurrent = 0; ++ hub_desc->DeviceRemovable[0] = 0; ++ hub_desc->DeviceRemovable[1] = 0xff; ++ break; ++ case UCR_GET_HUB_STATUS: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "GetHubStatus\n"); ++ DWC_MEMSET(buf, 0, 4); ++ break; ++ case UCR_GET_PORT_STATUS: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "GetPortStatus wIndex = 0x%04x FLAGS=0x%08x\n", ++ wIndex, dwc_otg_hcd->flags.d32); ++ if (!wIndex || wIndex > 1) ++ goto error; ++ ++ port_status = 0; ++ ++ if (dwc_otg_hcd->flags.b.port_connect_status_change) ++ port_status |= (1 << UHF_C_PORT_CONNECTION); ++ ++ if (dwc_otg_hcd->flags.b.port_enable_change) ++ port_status |= (1 << UHF_C_PORT_ENABLE); ++ ++ if (dwc_otg_hcd->flags.b.port_suspend_change) ++ port_status |= (1 << UHF_C_PORT_SUSPEND); ++ ++ if (dwc_otg_hcd->flags.b.port_l1_change) ++ port_status |= (1 << UHF_C_PORT_L1); ++ ++ if (dwc_otg_hcd->flags.b.port_reset_change) { ++ port_status |= (1 << UHF_C_PORT_RESET); ++ } ++ ++ if (dwc_otg_hcd->flags.b.port_over_current_change) { ++ DWC_WARN("Overcurrent change detected\n"); ++ port_status |= (1 << UHF_C_PORT_OVER_CURRENT); ++ } ++ ++ if (!dwc_otg_hcd->flags.b.port_connect_status) { ++ /* ++ * The port is disconnected, which means the core is ++ * either in device mode or it soon will be. Just ++ * return 0's for the remainder of the port status ++ * since the port register can't be read if the core ++ * is in device mode. ++ */ ++ *((__le32 *) buf) = dwc_cpu_to_le32(&port_status); ++ break; ++ } ++ ++ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); ++ DWC_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32); ++ ++ if (hprt0.b.prtconnsts) ++ port_status |= (1 << UHF_PORT_CONNECTION); ++ ++ if (hprt0.b.prtena) ++ port_status |= (1 << UHF_PORT_ENABLE); ++ ++ if (hprt0.b.prtsusp) ++ port_status |= (1 << UHF_PORT_SUSPEND); ++ ++ if (hprt0.b.prtovrcurract) ++ port_status |= (1 << UHF_PORT_OVER_CURRENT); ++ ++ if (hprt0.b.prtrst) ++ port_status |= (1 << UHF_PORT_RESET); ++ ++ if (hprt0.b.prtpwr) ++ port_status |= (1 << UHF_PORT_POWER); ++ ++ if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) ++ port_status |= (1 << UHF_PORT_HIGH_SPEED); ++ else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED) ++ port_status |= (1 << UHF_PORT_LOW_SPEED); ++ ++ if (hprt0.b.prttstctl) ++ port_status |= (1 << UHF_PORT_TEST); ++ if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) { ++ port_status |= (1 << UHF_PORT_L1); ++ } ++ /* ++ For Synopsys HW emulation of Power down wkup_control asserts the ++ hreset_n and prst_n on suspned. This causes the HPRT0 to be zero. ++ We intentionally tell the software that port is in L2Suspend state. ++ Only for STE. ++ */ ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ port_status |= (1 << UHF_PORT_SUSPEND); ++ } ++ /* USB_PORT_FEAT_INDICATOR unsupported always 0 */ ++ ++ *((__le32 *) buf) = dwc_cpu_to_le32(&port_status); ++ ++ break; ++ case UCR_SET_HUB_FEATURE: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "SetHubFeature\n"); ++ /* No HUB features supported */ ++ break; ++ case UCR_SET_PORT_FEATURE: ++ if (wValue != UHF_PORT_TEST && (!wIndex || wIndex > 1)) ++ goto error; ++ ++ if (!dwc_otg_hcd->flags.b.port_connect_status) { ++ /* ++ * The port is disconnected, which means the core is ++ * either in device mode or it soon will be. Just ++ * return without doing anything since the port ++ * register can't be written if the core is in device ++ * mode. ++ */ ++ break; ++ } ++ ++ switch (wValue) { ++ case UHF_PORT_SUSPEND: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_SUSPEND\n"); ++ if (dwc_otg_hcd_otg_port(dwc_otg_hcd) != wIndex) { ++ goto error; ++ } ++ if (core_if->power_down == 2) { ++ int timeout = 300; ++ dwc_irqflags_t flags; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++#ifdef DWC_DEV_SRPCAP ++ int32_t otg_cap_param = core_if->core_params->otg_cap; ++#endif ++ DWC_PRINTF("Preparing for complete power-off\n"); ++ ++ /* Save registers before hibernation */ ++ dwc_otg_save_global_regs(core_if); ++ dwc_otg_save_host_regs(core_if); ++ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 1; ++ hprt0.b.prtena = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ /* Spin hprt0.b.prtsusp to became 1 */ ++ do { ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ if (hprt0.b.prtsusp) { ++ break; ++ } ++ dwc_mdelay(1); ++ } while (--timeout); ++ if (!timeout) { ++ DWC_WARN("Suspend wasn't genereted\n"); ++ } ++ dwc_udelay(10); ++ ++ /* ++ * We need to disable interrupts to prevent servicing of any IRQ ++ * during going to hibernation ++ */ ++ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); ++ core_if->lx_state = DWC_OTG_L2; ++#ifdef DWC_DEV_SRPCAP ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 0; ++ hprt0.b.prtena = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, ++ hprt0.d32); ++#endif ++ gusbcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs-> ++ gusbcfg); ++ if (gusbcfg.b.ulpi_utmi_sel == 1) { ++ /* ULPI interface */ ++ /* Suspend the Phy Clock */ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ dwc_udelay(10); ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } else { ++ /* UTMI+ Interface */ ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ dwc_udelay(10); ++ } ++#ifdef DWC_DEV_SRPCAP ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++#endif ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ gpwrdn.d32 = 0; ++#ifdef DWC_DEV_SRPCAP ++ gpwrdn.b.srp_det_msk = 1; ++#endif ++ gpwrdn.b.disconn_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ gpwrdn.b.sts_chngint_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Enable Power Down Clamp and all interrupts in GPWRDN */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Switch off VDD */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++#ifdef DWC_DEV_SRPCAP ++ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) ++ { ++ core_if->pwron_timer_started = 1; ++ DWC_TIMER_SCHEDULE(core_if->pwron_timer, 6000 /* 6 secs */ ); ++ } ++#endif ++ /* Save gpwrdn register for further usage if stschng interrupt */ ++ core_if->gr_backup->gpwrdn_local = ++ DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ /* Set flag to indicate that we are in hibernation */ ++ core_if->hibernation_suspend = 1; ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock,flags); ++ ++ DWC_PRINTF("Host hibernation completed\n"); ++ // Exit from case statement ++ break; ++ ++ } ++ if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex && ++ dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gotgctl.b.hstsethnpen = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gotgctl, 0, gotgctl.d32); ++ core_if->op_state = A_SUSPEND; ++ } ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ { ++ dwc_irqflags_t flags; ++ /* Update lx_state */ ++ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); ++ core_if->lx_state = DWC_OTG_L2; ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); ++ } ++ /* Suspend the Phy Clock */ ++ if (core_if->otg_ver == 0) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ dwc_udelay(10); ++ } ++ ++ /* For HNP the bus must be suspended for at least 200ms. */ ++ if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) { ++ if (core_if->otg_ver) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ } ++ dwc_mdelay(200); ++ } ++ ++ /** @todo - check how sw can wait for 1 sec to check asesvld??? */ ++#if 0 //vahrama !!!!!!!!!!!!!!!!!! ++ if (core_if->adp_enable) { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn; ++ ++ while (gotgctl.b.asesvld == 1) { ++ gotgctl.d32 = ++ DWC_READ_REG32(&core_if-> ++ core_global_regs-> ++ gotgctl); ++ dwc_mdelay(100); ++ } ++ ++ /* Enable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++ /* Unmask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++ dwc_otg_adp_probe_start(core_if); ++ } ++#endif ++ break; ++ case UHF_PORT_POWER: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_POWER\n"); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ break; ++ case UHF_PORT_RESET: ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ /* If we are going to exit from Hibernated ++ * state via USB RESET. ++ */ ++ dwc_otg_host_hibernation_restore(core_if, 0, 1); ++ } else { ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ ++ DWC_DEBUGPL(DBG_HCD, ++ "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_RESET\n"); ++ { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ pcgcctl.b.enbl_sleep_gating = 1; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ DWC_WRITE_REG32(core_if->pcgcctl, 0); ++ } ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ { ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ if (lpmcfg.b.prt_sleep_sts) { ++ lpmcfg.b.en_utmi_sleep = 0; ++ lpmcfg.b.hird_thres &= (~(1 << 4)); ++ DWC_WRITE_REG32 ++ (&core_if->core_global_regs->glpmcfg, ++ lpmcfg.d32); ++ dwc_mdelay(1); ++ } ++ } ++#endif ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ /* Clear suspend bit if resetting from suspended state. */ ++ hprt0.b.prtsusp = 0; ++ /* When B-Host the Port reset bit is set in ++ * the Start HCD Callback function, so that ++ * the reset is started within 1ms of the HNP ++ * success interrupt. */ ++ if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) { ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtrst = 1; ++ DWC_PRINTF("Indeed it is in host mode hprt0 = %08x\n",hprt0.d32); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, ++ hprt0.d32); ++ } ++ /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */ ++ dwc_mdelay(60); ++ hprt0.b.prtrst = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ core_if->lx_state = DWC_OTG_L0; /* Now back to the on state */ ++ } ++ break; ++#ifdef DWC_HS_ELECT_TST ++ case UHF_PORT_TEST: ++ { ++ uint32_t t; ++ gintmsk_data_t gintmsk; ++ ++ t = (wIndex >> 8); /* MSB wIndex USB */ ++ DWC_DEBUGPL(DBG_HCD, ++ "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_TEST %d\n", ++ t); ++ DWC_WARN("USB_PORT_FEAT_TEST %d\n", t); ++ if (t < 6) { ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prttstctl = t; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, ++ hprt0.d32); ++ } else { ++ /* Setup global vars with reg addresses (quick and ++ * dirty hack, should be cleaned up) ++ */ ++ global_regs = core_if->core_global_regs; ++ hc_global_regs = ++ core_if->host_if->host_global_regs; ++ hc_regs = ++ (dwc_otg_hc_regs_t *) ((char *) ++ global_regs + ++ 0x500); ++ data_fifo = ++ (uint32_t *) ((char *)global_regs + ++ 0x1000); ++ ++ if (t == 6) { /* HS_HOST_PORT_SUSPEND_RESUME */ ++ /* Save current interrupt mask */ ++ gintmsk.d32 = ++ DWC_READ_REG32 ++ (&global_regs->gintmsk); ++ ++ /* Disable all interrupts while we muck with ++ * the hardware directly ++ */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* 15 second delay per the test spec */ ++ dwc_mdelay(15000); ++ ++ /* Drive suspend on the root port */ ++ hprt0.d32 = ++ dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 1; ++ hprt0.b.prtres = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* 15 second delay per the test spec */ ++ dwc_mdelay(15000); ++ ++ /* Drive resume on the root port */ ++ hprt0.d32 = ++ dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 0; ++ hprt0.b.prtres = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ dwc_mdelay(100); ++ ++ /* Clear the resume bit */ ++ hprt0.b.prtres = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* Restore interrupts */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32); ++ } else if (t == 7) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */ ++ /* Save current interrupt mask */ ++ gintmsk.d32 = ++ DWC_READ_REG32 ++ (&global_regs->gintmsk); ++ ++ /* Disable all interrupts while we muck with ++ * the hardware directly ++ */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* 15 second delay per the test spec */ ++ dwc_mdelay(15000); ++ ++ /* Send the Setup packet */ ++ do_setup(); ++ ++ /* 15 second delay so nothing else happens for awhile */ ++ dwc_mdelay(15000); ++ ++ /* Restore interrupts */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32); ++ } else if (t == 8) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */ ++ /* Save current interrupt mask */ ++ gintmsk.d32 = ++ DWC_READ_REG32 ++ (&global_regs->gintmsk); ++ ++ /* Disable all interrupts while we muck with ++ * the hardware directly ++ */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* Send the Setup packet */ ++ do_setup(); ++ ++ /* 15 second delay so nothing else happens for awhile */ ++ dwc_mdelay(15000); ++ ++ /* Send the In and Ack packets */ ++ do_in_ack(); ++ ++ /* 15 second delay so nothing else happens for awhile */ ++ dwc_mdelay(15000); ++ ++ /* Restore interrupts */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32); ++ } ++ } ++ break; ++ } ++#endif /* DWC_HS_ELECT_TST */ ++ ++ case UHF_PORT_INDICATOR: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_INDICATOR\n"); ++ /* Not supported */ ++ break; ++ default: ++ retval = -DWC_E_INVALID; ++ DWC_ERROR("DWC OTG HCD - " ++ "SetPortFeature request %xh " ++ "unknown or unsupported\n", wValue); ++ break; ++ } ++ break; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ case UCR_SET_AND_TEST_PORT_FEATURE: ++ if (wValue != UHF_PORT_L1) { ++ goto error; ++ } ++ { ++ int portnum, hird, devaddr, remwake; ++ glpmcfg_data_t lpmcfg; ++ uint32_t time_usecs; ++ gintsts_data_t gintsts; ++ gintmsk_data_t gintmsk; ++ ++ if (!dwc_otg_get_param_lpm_enable(core_if)) { ++ goto error; ++ } ++ if (wValue != UHF_PORT_L1 || wLength != 1) { ++ goto error; ++ } ++ /* Check if the port currently is in SLEEP state */ ++ lpmcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ if (lpmcfg.b.prt_sleep_sts) { ++ DWC_INFO("Port is already in sleep mode\n"); ++ buf[0] = 0; /* Return success */ ++ break; ++ } ++ ++ portnum = wIndex & 0xf; ++ hird = (wIndex >> 4) & 0xf; ++ devaddr = (wIndex >> 8) & 0x7f; ++ remwake = (wIndex >> 15); ++ ++ if (portnum != 1) { ++ retval = -DWC_E_INVALID; ++ DWC_WARN ++ ("Wrong port number(%d) in SetandTestPortFeature request\n", ++ portnum); ++ break; ++ } ++ ++ DWC_PRINTF ++ ("SetandTestPortFeature request: portnum = %d, hird = %d, devaddr = %d, rewake = %d\n", ++ portnum, hird, devaddr, remwake); ++ /* Disable LPM interrupt */ ++ gintmsk.d32 = 0; ++ gintmsk.b.lpmtranrcvd = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, ++ gintmsk.d32, 0); ++ ++ if (dwc_otg_hcd_send_lpm ++ (dwc_otg_hcd, devaddr, hird, remwake)) { ++ retval = -DWC_E_INVALID; ++ break; ++ } ++ ++ time_usecs = 10 * (lpmcfg.b.retry_count + 1); ++ /* We will consider timeout if time_usecs microseconds pass, ++ * and we don't receive LPM transaction status. ++ * After receiving non-error responce(ACK/NYET/STALL) from device, ++ * core will set lpmtranrcvd bit. ++ */ ++ do { ++ gintsts.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (gintsts.b.lpmtranrcvd) { ++ break; ++ } ++ dwc_udelay(1); ++ } while (--time_usecs); ++ /* lpm_int bit will be cleared in LPM interrupt handler */ ++ ++ /* Now fill status ++ * 0x00 - Success ++ * 0x10 - NYET ++ * 0x11 - Timeout ++ */ ++ if (!gintsts.b.lpmtranrcvd) { ++ buf[0] = 0x3; /* Completion code is Timeout */ ++ dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd); ++ } else { ++ lpmcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ if (lpmcfg.b.lpm_resp == 0x3) { ++ /* ACK responce from the device */ ++ buf[0] = 0x00; /* Success */ ++ } else if (lpmcfg.b.lpm_resp == 0x2) { ++ /* NYET responce from the device */ ++ buf[0] = 0x2; ++ } else { ++ /* Otherwise responce with Timeout */ ++ buf[0] = 0x3; ++ } ++ } ++ DWC_PRINTF("Device responce to LPM trans is %x\n", ++ lpmcfg.b.lpm_resp); ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, ++ gintmsk.d32); ++ ++ break; ++ } ++#endif /* CONFIG_USB_DWC_OTG_LPM */ ++ default: ++error: ++ retval = -DWC_E_INVALID; ++ DWC_WARN("DWC OTG HCD - " ++ "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n", ++ typeReq, wIndex, wValue); ++ break; ++ } ++ ++ return retval; ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++/** Returns index of host channel to perform LPM transaction. */ ++int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, uint8_t devaddr) ++{ ++ dwc_otg_core_if_t *core_if = hcd->core_if; ++ dwc_hc_t *hc; ++ hcchar_data_t hcchar; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ if (DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { ++ DWC_PRINTF("No free channel to select for LPM transaction\n"); ++ return -1; ++ } ++ ++ hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list); ++ ++ /* Mask host channel interrupts. */ ++ gintmsk.b.hcintr = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0); ++ ++ /* Fill fields that core needs for LPM transaction */ ++ hcchar.b.devaddr = devaddr; ++ hcchar.b.epnum = 0; ++ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; ++ hcchar.b.mps = 64; ++ hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW); ++ hcchar.b.epdir = 0; /* OUT */ ++ DWC_WRITE_REG32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar, ++ hcchar.d32); ++ ++ /* Remove the host channel from the free list. */ ++ DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry); ++ ++ DWC_PRINTF("hcnum = %d devaddr = %d\n", hc->hc_num, devaddr); ++ ++ return hc->hc_num; ++} ++ ++/** Release hc after performing LPM transaction */ ++void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd) ++{ ++ dwc_hc_t *hc; ++ glpmcfg_data_t lpmcfg; ++ uint8_t hc_num; ++ ++ lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg); ++ hc_num = lpmcfg.b.lpm_chan_index; ++ ++ hc = hcd->hc_ptr_array[hc_num]; ++ ++ DWC_PRINTF("Freeing channel %d after LPM\n", hc_num); ++ /* Return host channel to free list */ ++ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); ++} ++ ++int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, uint8_t hird, ++ uint8_t bRemoteWake) ++{ ++ glpmcfg_data_t lpmcfg; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ int channel; ++ ++ channel = dwc_otg_hcd_get_hc_for_lpm_tran(hcd, devaddr); ++ if (channel < 0) { ++ return channel; ++ } ++ ++ pcgcctl.b.enbl_sleep_gating = 1; ++ DWC_MODIFY_REG32(hcd->core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ /* Read LPM config register */ ++ lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg); ++ ++ /* Program LPM transaction fields */ ++ lpmcfg.b.rem_wkup_en = bRemoteWake; ++ lpmcfg.b.hird = hird; ++ ++ if(dwc_otg_get_param_besl_enable(hcd->core_if)) { ++ lpmcfg.b.hird_thres = 0x16; ++ lpmcfg.b.en_besl = 1; ++ } else { ++ lpmcfg.b.hird_thres = 0x1c; ++ } ++ ++ lpmcfg.b.lpm_chan_index = channel; ++ lpmcfg.b.en_utmi_sleep = 1; ++ /* Program LPM config register */ ++ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++ ++ /* Send LPM transaction */ ++ lpmcfg.b.send_lpm = 1; ++ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++ ++ return 0; ++} ++ ++#endif /* CONFIG_USB_DWC_OTG_LPM */ ++ ++int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port) ++{ ++ int retval; ++ ++ if (port != 1) { ++ return -DWC_E_INVALID; ++ } ++ ++ retval = (hcd->flags.b.port_connect_status_change || ++ hcd->flags.b.port_reset_change || ++ hcd->flags.b.port_enable_change || ++ hcd->flags.b.port_suspend_change || ++ hcd->flags.b.port_over_current_change); ++#ifdef DEBUG ++ if (retval) { ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:" ++ " Root port status changed\n"); ++ DWC_DEBUGPL(DBG_HCDV, " port_connect_status_change: %d\n", ++ hcd->flags.b.port_connect_status_change); ++ DWC_DEBUGPL(DBG_HCDV, " port_reset_change: %d\n", ++ hcd->flags.b.port_reset_change); ++ DWC_DEBUGPL(DBG_HCDV, " port_enable_change: %d\n", ++ hcd->flags.b.port_enable_change); ++ DWC_DEBUGPL(DBG_HCDV, " port_suspend_change: %d\n", ++ hcd->flags.b.port_suspend_change); ++ DWC_DEBUGPL(DBG_HCDV, " port_over_current_change: %d\n", ++ hcd->flags.b.port_over_current_change); ++ } ++#endif ++ return retval; ++} ++ ++int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ hfnum_data_t hfnum; ++ hfnum.d32 = ++ DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs-> ++ hfnum); ++ ++#ifdef DEBUG_SOF ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n", ++ hfnum.b.frnum); ++#endif ++ return hfnum.b.frnum; ++} ++ ++int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd, ++ struct dwc_otg_hcd_function_ops *fops) ++{ ++ int retval = 0; ++ hprt0_data_t hprt0; ++ ++ hcd->fops = fops; ++ if (!dwc_otg_is_device_mode(hcd->core_if) && ++ (!hcd->core_if->adp_enable || hcd->core_if->adp.adp_started)) { ++ dwc_otg_hcd_reinit(hcd); ++ } else { ++ if (hcd->core_if->adp_enable) { ++ /* Clear any interrupt pending in the HPRT, sometimes ++ * Port Connect Detected is not being cleared*/ ++ hprt0.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0); ++ DWC_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32); ++ } ++ retval = -DWC_E_NO_DEVICE; ++ } ++ ++ return retval; ++} ++ ++void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd) ++{ ++ return hcd->priv; ++} ++ ++void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data) ++{ ++ hcd->priv = priv_data; ++} ++ ++uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd) ++{ ++ return hcd->otg_port; ++} ++ ++uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd) ++{ ++ uint32_t is_b_host; ++ if (hcd->core_if->op_state == B_HOST) { ++ is_b_host = 1; ++ } else { ++ is_b_host = 0; ++ } ++ ++ return is_b_host; ++} ++ ++dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd, ++ int iso_desc_count, int atomic_alloc) ++{ ++ dwc_otg_hcd_urb_t *dwc_otg_urb; ++ uint32_t size; ++ ++ size = ++ sizeof(*dwc_otg_urb) + ++ iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc); ++ if (atomic_alloc) ++ dwc_otg_urb = DWC_ALLOC_ATOMIC(size); ++ else ++ dwc_otg_urb = DWC_ALLOC(size); ++ ++ dwc_otg_urb->packet_count = iso_desc_count; ++ ++ return dwc_otg_urb; ++} ++ ++void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * dwc_otg_urb, ++ uint8_t dev_addr, uint8_t ep_num, ++ uint8_t ep_type, uint8_t ep_dir, uint16_t mps) ++{ ++ dwc_otg_hcd_fill_pipe(&dwc_otg_urb->pipe_info, dev_addr, ep_num, ++ ep_type, ep_dir, mps); ++#if 0 ++ DWC_PRINTF ++ ("addr = %d, ep_num = %d, ep_dir = 0x%x, ep_type = 0x%x, mps = %d\n", ++ dev_addr, ep_num, ep_dir, ep_type, mps); ++#endif ++} ++ ++void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * dwc_otg_urb, ++ void *urb_handle, void *buf, dwc_dma_t dma, ++ uint32_t buflen, void *setup_packet, ++ dwc_dma_t setup_dma, uint32_t flags, ++ uint16_t interval) ++{ ++ dwc_otg_urb->priv = urb_handle; ++ dwc_otg_urb->buf = buf; ++ dwc_otg_urb->dma = dma; ++ dwc_otg_urb->length = buflen; ++ dwc_otg_urb->setup_packet = setup_packet; ++ dwc_otg_urb->setup_dma = setup_dma; ++ dwc_otg_urb->flags = flags; ++ dwc_otg_urb->interval = interval; ++ dwc_otg_urb->status = -DWC_E_IN_PROGRESS; ++} ++ ++uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb) ++{ ++ return dwc_otg_urb->status; ++} ++ ++uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * dwc_otg_urb) ++{ ++ return dwc_otg_urb->actual_length; ++} ++ ++uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * dwc_otg_urb) ++{ ++ return dwc_otg_urb->error_count; ++} ++ ++void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb, ++ int desc_num, uint32_t offset, ++ uint32_t length) ++{ ++ dwc_otg_urb->iso_descs[desc_num].offset = offset; ++ dwc_otg_urb->iso_descs[desc_num].length = length; ++} ++ ++uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * dwc_otg_urb, ++ int desc_num) ++{ ++ return dwc_otg_urb->iso_descs[desc_num].status; ++} ++ ++uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t * ++ dwc_otg_urb, int desc_num) ++{ ++ return dwc_otg_urb->iso_descs[desc_num].actual_length; ++} ++ ++int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, void *ep_handle) ++{ ++ int allocated = 0; ++ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; ++ ++ if (qh) { ++ if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) { ++ allocated = 1; ++ } ++ } ++ return allocated; ++} ++ ++int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle) ++{ ++ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; ++ int freed = 0; ++ DWC_ASSERT(qh, "qh is not allocated\n"); ++ ++ if (DWC_LIST_EMPTY(&qh->qh_list_entry)) { ++ freed = 1; ++ } ++ ++ return freed; ++} ++ ++uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, void *ep_handle) ++{ ++ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; ++ DWC_ASSERT(qh, "qh is not allocated\n"); ++ return qh->usecs; ++} ++ ++void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd) ++{ ++#ifdef DEBUG ++ int num_channels; ++ int i; ++ gnptxsts_data_t np_tx_status; ++ hptxsts_data_t p_tx_status; ++ ++ num_channels = hcd->core_if->core_params->host_channels; ++ DWC_PRINTF("\n"); ++ DWC_PRINTF ++ ("************************************************************\n"); ++ DWC_PRINTF("HCD State:\n"); ++ DWC_PRINTF(" Num channels: %d\n", num_channels); ++ for (i = 0; i < num_channels; i++) { ++ dwc_hc_t *hc = hcd->hc_ptr_array[i]; ++ DWC_PRINTF(" Channel %d:\n", i); ++ DWC_PRINTF(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n", ++ hc->dev_addr, hc->ep_num, hc->ep_is_in); ++ DWC_PRINTF(" speed: %d\n", hc->speed); ++ DWC_PRINTF(" ep_type: %d\n", hc->ep_type); ++ DWC_PRINTF(" max_packet: %d\n", hc->max_packet); ++ DWC_PRINTF(" data_pid_start: %d\n", hc->data_pid_start); ++ DWC_PRINTF(" multi_count: %d\n", hc->multi_count); ++ DWC_PRINTF(" xfer_started: %d\n", hc->xfer_started); ++ DWC_PRINTF(" xfer_buff: %p\n", hc->xfer_buff); ++ DWC_PRINTF(" xfer_len: %d\n", hc->xfer_len); ++ DWC_PRINTF(" xfer_count: %d\n", hc->xfer_count); ++ DWC_PRINTF(" halt_on_queue: %d\n", hc->halt_on_queue); ++ DWC_PRINTF(" halt_pending: %d\n", hc->halt_pending); ++ DWC_PRINTF(" halt_status: %d\n", hc->halt_status); ++ DWC_PRINTF(" do_split: %d\n", hc->do_split); ++ DWC_PRINTF(" complete_split: %d\n", hc->complete_split); ++ DWC_PRINTF(" hub_addr: %d\n", hc->hub_addr); ++ DWC_PRINTF(" port_addr: %d\n", hc->port_addr); ++ DWC_PRINTF(" xact_pos: %d\n", hc->xact_pos); ++ DWC_PRINTF(" requests: %d\n", hc->requests); ++ DWC_PRINTF(" qh: %p\n", hc->qh); ++ if (hc->xfer_started) { ++ hfnum_data_t hfnum; ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; ++ hfnum.d32 = ++ DWC_READ_REG32(&hcd->core_if-> ++ host_if->host_global_regs->hfnum); ++ hcchar.d32 = ++ DWC_READ_REG32(&hcd->core_if->host_if-> ++ hc_regs[i]->hcchar); ++ hctsiz.d32 = ++ DWC_READ_REG32(&hcd->core_if->host_if-> ++ hc_regs[i]->hctsiz); ++ hcint.d32 = ++ DWC_READ_REG32(&hcd->core_if->host_if-> ++ hc_regs[i]->hcint); ++ hcintmsk.d32 = ++ DWC_READ_REG32(&hcd->core_if->host_if-> ++ hc_regs[i]->hcintmsk); ++ DWC_PRINTF(" hfnum: 0x%08x\n", hfnum.d32); ++ DWC_PRINTF(" hcchar: 0x%08x\n", hcchar.d32); ++ DWC_PRINTF(" hctsiz: 0x%08x\n", hctsiz.d32); ++ DWC_PRINTF(" hcint: 0x%08x\n", hcint.d32); ++ DWC_PRINTF(" hcintmsk: 0x%08x\n", hcintmsk.d32); ++ } ++ if (hc->xfer_started && hc->qh) { ++ dwc_otg_qtd_t *qtd; ++ dwc_otg_hcd_urb_t *urb; ++ ++ DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list, qtd_list_entry) { ++ if (!qtd->in_process) ++ break; ++ ++ urb = qtd->urb; ++ DWC_PRINTF(" URB Info:\n"); ++ DWC_PRINTF(" qtd: %p, urb: %p\n", qtd, urb); ++ if (urb) { ++ DWC_PRINTF(" Dev: %d, EP: %d %s\n", ++ dwc_otg_hcd_get_dev_addr(&urb-> ++ pipe_info), ++ dwc_otg_hcd_get_ep_num(&urb-> ++ pipe_info), ++ dwc_otg_hcd_is_pipe_in(&urb-> ++ pipe_info) ? ++ "IN" : "OUT"); ++ DWC_PRINTF(" Max packet size: %d\n", ++ dwc_otg_hcd_get_mps(&urb-> ++ pipe_info)); ++ DWC_PRINTF(" transfer_buffer: %p\n", ++ urb->buf); ++ DWC_PRINTF(" transfer_dma: %p\n", ++ (void *)urb->dma); ++ DWC_PRINTF(" transfer_buffer_length: %d\n", ++ urb->length); ++ DWC_PRINTF(" actual_length: %d\n", ++ urb->actual_length); ++ } ++ } ++ } ++ } ++ DWC_PRINTF(" non_periodic_channels: %d\n", hcd->non_periodic_channels); ++ DWC_PRINTF(" periodic_channels: %d\n", hcd->periodic_channels); ++ DWC_PRINTF(" periodic_usecs: %d\n", hcd->periodic_usecs); ++ np_tx_status.d32 = ++ DWC_READ_REG32(&hcd->core_if->core_global_regs->gnptxsts); ++ DWC_PRINTF(" NP Tx Req Queue Space Avail: %d\n", ++ np_tx_status.b.nptxqspcavail); ++ DWC_PRINTF(" NP Tx FIFO Space Avail: %d\n", ++ np_tx_status.b.nptxfspcavail); ++ p_tx_status.d32 = ++ DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hptxsts); ++ DWC_PRINTF(" P Tx Req Queue Space Avail: %d\n", ++ p_tx_status.b.ptxqspcavail); ++ DWC_PRINTF(" P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail); ++ dwc_otg_hcd_dump_frrem(hcd); ++ dwc_otg_dump_global_registers(hcd->core_if); ++ dwc_otg_dump_host_registers(hcd->core_if); ++ DWC_PRINTF ++ ("************************************************************\n"); ++ DWC_PRINTF("\n"); ++#endif ++} ++ ++#ifdef DEBUG ++void dwc_print_setup_data(uint8_t * setup) ++{ ++ int i; ++ if (CHK_DEBUG_LEVEL(DBG_HCD)) { ++ DWC_PRINTF("Setup Data = MSB "); ++ for (i = 7; i >= 0; i--) ++ DWC_PRINTF("%02x ", setup[i]); ++ DWC_PRINTF("\n"); ++ DWC_PRINTF(" bmRequestType Tranfer = %s\n", ++ (setup[0] & 0x80) ? "Device-to-Host" : ++ "Host-to-Device"); ++ DWC_PRINTF(" bmRequestType Type = "); ++ switch ((setup[0] & 0x60) >> 5) { ++ case 0: ++ DWC_PRINTF("Standard\n"); ++ break; ++ case 1: ++ DWC_PRINTF("Class\n"); ++ break; ++ case 2: ++ DWC_PRINTF("Vendor\n"); ++ break; ++ case 3: ++ DWC_PRINTF("Reserved\n"); ++ break; ++ } ++ DWC_PRINTF(" bmRequestType Recipient = "); ++ switch (setup[0] & 0x1f) { ++ case 0: ++ DWC_PRINTF("Device\n"); ++ break; ++ case 1: ++ DWC_PRINTF("Interface\n"); ++ break; ++ case 2: ++ DWC_PRINTF("Endpoint\n"); ++ break; ++ case 3: ++ DWC_PRINTF("Other\n"); ++ break; ++ default: ++ DWC_PRINTF("Reserved\n"); ++ break; ++ } ++ DWC_PRINTF(" bRequest = 0x%0x\n", setup[1]); ++ DWC_PRINTF(" wValue = 0x%0x\n", *((uint16_t *) & setup[2])); ++ DWC_PRINTF(" wIndex = 0x%0x\n", *((uint16_t *) & setup[4])); ++ DWC_PRINTF(" wLength = 0x%0x\n\n", *((uint16_t *) & setup[6])); ++ } ++} ++#endif ++ ++void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd) ++{ ++#if 0 ++ DWC_PRINTF("Frame remaining at SOF:\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->frrem_samples, hcd->frrem_accum, ++ (hcd->frrem_samples > 0) ? ++ hcd->frrem_accum / hcd->frrem_samples : 0); ++ ++ DWC_PRINTF("\n"); ++ DWC_PRINTF("Frame remaining at start_transfer (uframe 7):\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->core_if->hfnum_7_samples, ++ hcd->core_if->hfnum_7_frrem_accum, ++ (hcd->core_if->hfnum_7_samples > ++ 0) ? hcd->core_if->hfnum_7_frrem_accum / ++ hcd->core_if->hfnum_7_samples : 0); ++ DWC_PRINTF("Frame remaining at start_transfer (uframe 0):\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->core_if->hfnum_0_samples, ++ hcd->core_if->hfnum_0_frrem_accum, ++ (hcd->core_if->hfnum_0_samples > ++ 0) ? hcd->core_if->hfnum_0_frrem_accum / ++ hcd->core_if->hfnum_0_samples : 0); ++ DWC_PRINTF("Frame remaining at start_transfer (uframe 1-6):\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->core_if->hfnum_other_samples, ++ hcd->core_if->hfnum_other_frrem_accum, ++ (hcd->core_if->hfnum_other_samples > ++ 0) ? hcd->core_if->hfnum_other_frrem_accum / ++ hcd->core_if->hfnum_other_samples : 0); ++ ++ DWC_PRINTF("\n"); ++ DWC_PRINTF("Frame remaining at sample point A (uframe 7):\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a, ++ (hcd->hfnum_7_samples_a > 0) ? ++ hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0); ++ DWC_PRINTF("Frame remaining at sample point A (uframe 0):\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a, ++ (hcd->hfnum_0_samples_a > 0) ? ++ hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0); ++ DWC_PRINTF("Frame remaining at sample point A (uframe 1-6):\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a, ++ (hcd->hfnum_other_samples_a > 0) ? ++ hcd->hfnum_other_frrem_accum_a / ++ hcd->hfnum_other_samples_a : 0); ++ ++ DWC_PRINTF("\n"); ++ DWC_PRINTF("Frame remaining at sample point B (uframe 7):\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b, ++ (hcd->hfnum_7_samples_b > 0) ? ++ hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0); ++ DWC_PRINTF("Frame remaining at sample point B (uframe 0):\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b, ++ (hcd->hfnum_0_samples_b > 0) ? ++ hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0); ++ DWC_PRINTF("Frame remaining at sample point B (uframe 1-6):\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b, ++ (hcd->hfnum_other_samples_b > 0) ? ++ hcd->hfnum_other_frrem_accum_b / ++ hcd->hfnum_other_samples_b : 0); ++#endif ++} ++ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd.h +new file mode 100644 +index 0000000..23eea36 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd.h +@@ -0,0 +1,803 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $ ++ * $Revision: #58 $ ++ * $Date: 2011/09/15 $ ++ * $Change: 1846647 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_DEVICE_ONLY ++#ifndef __DWC_HCD_H__ ++#define __DWC_HCD_H__ ++ ++#include "dwc_otg_os_dep.h" ++#include "usb.h" ++#include "dwc_otg_hcd_if.h" ++#include "dwc_otg_core_if.h" ++#include "dwc_list.h" ++#include "dwc_otg_cil.h" ++ ++/** ++ * @file ++ * ++ * This file contains the structures, constants, and interfaces for ++ * the Host Contoller Driver (HCD). ++ * ++ * The Host Controller Driver (HCD) is responsible for translating requests ++ * from the USB Driver into the appropriate actions on the DWC_otg controller. ++ * It isolates the USBD from the specifics of the controller by providing an ++ * API to the USBD. ++ */ ++ ++struct dwc_otg_hcd_pipe_info { ++ uint8_t dev_addr; ++ uint8_t ep_num; ++ uint8_t pipe_type; ++ uint8_t pipe_dir; ++ uint16_t mps; ++}; ++ ++struct dwc_otg_hcd_iso_packet_desc { ++ uint32_t offset; ++ uint32_t length; ++ uint32_t actual_length; ++ uint32_t status; ++}; ++ ++struct dwc_otg_qtd; ++ ++struct dwc_otg_hcd_urb { ++ void *priv; ++ struct dwc_otg_qtd *qtd; ++ void *buf; ++ dwc_dma_t dma; ++ void *setup_packet; ++ dwc_dma_t setup_dma; ++ uint32_t length; ++ uint32_t actual_length; ++ uint32_t status; ++ uint32_t error_count; ++ uint32_t packet_count; ++ uint32_t flags; ++ uint16_t interval; ++ struct dwc_otg_hcd_pipe_info pipe_info; ++ struct dwc_otg_hcd_iso_packet_desc iso_descs[0]; ++}; ++ ++static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe) ++{ ++ return pipe->ep_num; ++} ++ ++static inline uint8_t dwc_otg_hcd_get_pipe_type(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return pipe->pipe_type; ++} ++ ++static inline uint16_t dwc_otg_hcd_get_mps(struct dwc_otg_hcd_pipe_info *pipe) ++{ ++ return pipe->mps; ++} ++ ++static inline uint8_t dwc_otg_hcd_get_dev_addr(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return pipe->dev_addr; ++} ++ ++static inline uint8_t dwc_otg_hcd_is_pipe_isoc(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (pipe->pipe_type == UE_ISOCHRONOUS); ++} ++ ++static inline uint8_t dwc_otg_hcd_is_pipe_int(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (pipe->pipe_type == UE_INTERRUPT); ++} ++ ++static inline uint8_t dwc_otg_hcd_is_pipe_bulk(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (pipe->pipe_type == UE_BULK); ++} ++ ++static inline uint8_t dwc_otg_hcd_is_pipe_control(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (pipe->pipe_type == UE_CONTROL); ++} ++ ++static inline uint8_t dwc_otg_hcd_is_pipe_in(struct dwc_otg_hcd_pipe_info *pipe) ++{ ++ return (pipe->pipe_dir == UE_DIR_IN); ++} ++ ++static inline uint8_t dwc_otg_hcd_is_pipe_out(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (!dwc_otg_hcd_is_pipe_in(pipe)); ++} ++ ++static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe, ++ uint8_t devaddr, uint8_t ep_num, ++ uint8_t pipe_type, uint8_t pipe_dir, ++ uint16_t mps) ++{ ++ pipe->dev_addr = devaddr; ++ pipe->ep_num = ep_num; ++ pipe->pipe_type = pipe_type; ++ pipe->pipe_dir = pipe_dir; ++ pipe->mps = mps; ++} ++ ++/** ++ * Phases for control transfers. ++ */ ++typedef enum dwc_otg_control_phase { ++ DWC_OTG_CONTROL_SETUP, ++ DWC_OTG_CONTROL_DATA, ++ DWC_OTG_CONTROL_STATUS ++} dwc_otg_control_phase_e; ++ ++/** Transaction types. */ ++typedef enum dwc_otg_transaction_type { ++ DWC_OTG_TRANSACTION_NONE, ++ DWC_OTG_TRANSACTION_PERIODIC, ++ DWC_OTG_TRANSACTION_NON_PERIODIC, ++ DWC_OTG_TRANSACTION_ALL ++} dwc_otg_transaction_type_e; ++ ++struct dwc_otg_qh; ++ ++/** ++ * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control, ++ * interrupt, or isochronous transfer. A single QTD is created for each URB ++ * (of one of these types) submitted to the HCD. The transfer associated with ++ * a QTD may require one or multiple transactions. ++ * ++ * A QTD is linked to a Queue Head, which is entered in either the ++ * non-periodic or periodic schedule for execution. When a QTD is chosen for ++ * execution, some or all of its transactions may be executed. After ++ * execution, the state of the QTD is updated. The QTD may be retired if all ++ * its transactions are complete or if an error occurred. Otherwise, it ++ * remains in the schedule so more transactions can be executed later. ++ */ ++typedef struct dwc_otg_qtd { ++ /** ++ * Determines the PID of the next data packet for the data phase of ++ * control transfers. Ignored for other transfer types.
++ * One of the following values: ++ * - DWC_OTG_HC_PID_DATA0 ++ * - DWC_OTG_HC_PID_DATA1 ++ */ ++ uint8_t data_toggle; ++ ++ /** Current phase for control transfers (Setup, Data, or Status). */ ++ dwc_otg_control_phase_e control_phase; ++ ++ /** Keep track of the current split type ++ * for FS/LS endpoints on a HS Hub */ ++ uint8_t complete_split; ++ ++ /** How many bytes transferred during SSPLIT OUT */ ++ uint32_t ssplit_out_xfer_count; ++ ++ /** ++ * Holds the number of bus errors that have occurred for a transaction ++ * within this transfer. ++ */ ++ uint8_t error_count; ++ ++ /** ++ * Index of the next frame descriptor for an isochronous transfer. A ++ * frame descriptor describes the buffer position and length of the ++ * data to be transferred in the next scheduled (micro)frame of an ++ * isochronous transfer. It also holds status for that transaction. ++ * The frame index starts at 0. ++ */ ++ uint16_t isoc_frame_index; ++ ++ /** Position of the ISOC split on full/low speed */ ++ uint8_t isoc_split_pos; ++ ++ /** Position of the ISOC split in the buffer for the current frame */ ++ uint16_t isoc_split_offset; ++ ++ /** URB for this transfer */ ++ struct dwc_otg_hcd_urb *urb; ++ ++ struct dwc_otg_qh *qh; ++ ++ /** This list of QTDs */ ++ DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry; ++ ++ /** Indicates if this QTD is currently processed by HW. */ ++ uint8_t in_process; ++ ++ /** Number of DMA descriptors for this QTD */ ++ uint8_t n_desc; ++ ++ /** ++ * Last activated frame(packet) index. ++ * Used in Descriptor DMA mode only. ++ */ ++ uint16_t isoc_frame_index_last; ++ ++} dwc_otg_qtd_t; ++ ++DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd); ++ ++/** ++ * A Queue Head (QH) holds the static characteristics of an endpoint and ++ * maintains a list of transfers (QTDs) for that endpoint. A QH structure may ++ * be entered in either the non-periodic or periodic schedule. ++ */ ++typedef struct dwc_otg_qh { ++ /** ++ * Endpoint type. ++ * One of the following values: ++ * - UE_CONTROL ++ * - UE_BULK ++ * - UE_INTERRUPT ++ * - UE_ISOCHRONOUS ++ */ ++ uint8_t ep_type; ++ uint8_t ep_is_in; ++ ++ /** wMaxPacketSize Field of Endpoint Descriptor. */ ++ uint16_t maxp; ++ ++ /** ++ * Device speed. ++ * One of the following values: ++ * - DWC_OTG_EP_SPEED_LOW ++ * - DWC_OTG_EP_SPEED_FULL ++ * - DWC_OTG_EP_SPEED_HIGH ++ */ ++ uint8_t dev_speed; ++ ++ /** ++ * Determines the PID of the next data packet for non-control ++ * transfers. Ignored for control transfers.
++ * One of the following values: ++ * - DWC_OTG_HC_PID_DATA0 ++ * - DWC_OTG_HC_PID_DATA1 ++ */ ++ uint8_t data_toggle; ++ ++ /** Ping state if 1. */ ++ uint8_t ping_state; ++ ++ /** ++ * List of QTDs for this QH. ++ */ ++ struct dwc_otg_qtd_list qtd_list; ++ ++ /** Host channel currently processing transfers for this QH. */ ++ struct dwc_hc *channel; ++ ++ /** Full/low speed endpoint on high-speed hub requires split. */ ++ uint8_t do_split; ++ ++ /** @name Periodic schedule information */ ++ /** @{ */ ++ ++ /** Bandwidth in microseconds per (micro)frame. */ ++ uint16_t usecs; ++ ++ /** Interval between transfers in (micro)frames. */ ++ uint16_t interval; ++ ++ /** ++ * (micro)frame to initialize a periodic transfer. The transfer ++ * executes in the following (micro)frame. ++ */ ++ uint16_t sched_frame; ++ ++ /** (micro)frame at which last start split was initialized. */ ++ uint16_t start_split_frame; ++ ++ /** @} */ ++ ++ /** ++ * Used instead of original buffer if ++ * it(physical address) is not dword-aligned. ++ */ ++ uint8_t *dw_align_buf; ++ dwc_dma_t dw_align_buf_dma; ++ ++ /** Entry for QH in either the periodic or non-periodic schedule. */ ++ dwc_list_link_t qh_list_entry; ++ ++ /** @name Descriptor DMA support */ ++ /** @{ */ ++ ++ /** Descriptor List. */ ++ dwc_otg_host_dma_desc_t *desc_list; ++ ++ /** Descriptor List physical address. */ ++ dwc_dma_t desc_list_dma; ++ ++ /** ++ * Xfer Bytes array. ++ * Each element corresponds to a descriptor and indicates ++ * original XferSize size value for the descriptor. ++ */ ++ uint32_t *n_bytes; ++ ++ /** Actual number of transfer descriptors in a list. */ ++ uint16_t ntd; ++ ++ /** First activated isochronous transfer descriptor index. */ ++ uint8_t td_first; ++ /** Last activated isochronous transfer descriptor index. */ ++ uint8_t td_last; ++ ++ /** @} */ ++ ++} dwc_otg_qh_t; ++ ++DWC_CIRCLEQ_HEAD(hc_list, dwc_hc); ++ ++/** ++ * This structure holds the state of the HCD, including the non-periodic and ++ * periodic schedules. ++ */ ++struct dwc_otg_hcd { ++ /** The DWC otg device pointer */ ++ struct dwc_otg_device *otg_dev; ++ /** DWC OTG Core Interface Layer */ ++ dwc_otg_core_if_t *core_if; ++ ++ /** Function HCD driver callbacks */ ++ struct dwc_otg_hcd_function_ops *fops; ++ ++ /** Internal DWC HCD Flags */ ++ volatile union dwc_otg_hcd_internal_flags { ++ uint32_t d32; ++ struct { ++ unsigned port_connect_status_change:1; ++ unsigned port_connect_status:1; ++ unsigned port_reset_change:1; ++ unsigned port_enable_change:1; ++ unsigned port_suspend_change:1; ++ unsigned port_over_current_change:1; ++ unsigned port_l1_change:1; ++ unsigned reserved:26; ++ } b; ++ } flags; ++ ++ /** ++ * Inactive items in the non-periodic schedule. This is a list of ++ * Queue Heads. Transfers associated with these Queue Heads are not ++ * currently assigned to a host channel. ++ */ ++ dwc_list_link_t non_periodic_sched_inactive; ++ ++ /** ++ * Active items in the non-periodic schedule. This is a list of ++ * Queue Heads. Transfers associated with these Queue Heads are ++ * currently assigned to a host channel. ++ */ ++ dwc_list_link_t non_periodic_sched_active; ++ ++ /** ++ * Pointer to the next Queue Head to process in the active ++ * non-periodic schedule. ++ */ ++ dwc_list_link_t *non_periodic_qh_ptr; ++ ++ /** ++ * Inactive items in the periodic schedule. This is a list of QHs for ++ * periodic transfers that are _not_ scheduled for the next frame. ++ * Each QH in the list has an interval counter that determines when it ++ * needs to be scheduled for execution. This scheduling mechanism ++ * allows only a simple calculation for periodic bandwidth used (i.e. ++ * must assume that all periodic transfers may need to execute in the ++ * same frame). However, it greatly simplifies scheduling and should ++ * be sufficient for the vast majority of OTG hosts, which need to ++ * connect to a small number of peripherals at one time. ++ * ++ * Items move from this list to periodic_sched_ready when the QH ++ * interval counter is 0 at SOF. ++ */ ++ dwc_list_link_t periodic_sched_inactive; ++ ++ /** ++ * List of periodic QHs that are ready for execution in the next ++ * frame, but have not yet been assigned to host channels. ++ * ++ * Items move from this list to periodic_sched_assigned as host ++ * channels become available during the current frame. ++ */ ++ dwc_list_link_t periodic_sched_ready; ++ ++ /** ++ * List of periodic QHs to be executed in the next frame that are ++ * assigned to host channels. ++ * ++ * Items move from this list to periodic_sched_queued as the ++ * transactions for the QH are queued to the DWC_otg controller. ++ */ ++ dwc_list_link_t periodic_sched_assigned; ++ ++ /** ++ * List of periodic QHs that have been queued for execution. ++ * ++ * Items move from this list to either periodic_sched_inactive or ++ * periodic_sched_ready when the channel associated with the transfer ++ * is released. If the interval for the QH is 1, the item moves to ++ * periodic_sched_ready because it must be rescheduled for the next ++ * frame. Otherwise, the item moves to periodic_sched_inactive. ++ */ ++ dwc_list_link_t periodic_sched_queued; ++ ++ /** ++ * Total bandwidth claimed so far for periodic transfers. This value ++ * is in microseconds per (micro)frame. The assumption is that all ++ * periodic transfers may occur in the same (micro)frame. ++ */ ++ uint16_t periodic_usecs; ++ ++ /** ++ * Frame number read from the core at SOF. The value ranges from 0 to ++ * DWC_HFNUM_MAX_FRNUM. ++ */ ++ uint16_t frame_number; ++ ++ /** ++ * Count of periodic QHs, if using several eps. For SOF enable/disable. ++ */ ++ uint16_t periodic_qh_count; ++ ++ /** ++ * Free host channels in the controller. This is a list of ++ * dwc_hc_t items. ++ */ ++ struct hc_list free_hc_list; ++ /** ++ * Number of host channels assigned to periodic transfers. Currently ++ * assuming that there is a dedicated host channel for each periodic ++ * transaction and at least one host channel available for ++ * non-periodic transactions. ++ */ ++ int periodic_channels; ++ ++ /** ++ * Number of host channels assigned to non-periodic transfers. ++ */ ++ int non_periodic_channels; ++ ++ /** ++ * Array of pointers to the host channel descriptors. Allows accessing ++ * a host channel descriptor given the host channel number. This is ++ * useful in interrupt handlers. ++ */ ++ struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS]; ++ ++ /** ++ * Buffer to use for any data received during the status phase of a ++ * control transfer. Normally no data is transferred during the status ++ * phase. This buffer is used as a bit bucket. ++ */ ++ uint8_t *status_buf; ++ ++ /** ++ * DMA address for status_buf. ++ */ ++ dma_addr_t status_buf_dma; ++#define DWC_OTG_HCD_STATUS_BUF_SIZE 64 ++ ++ /** ++ * Connection timer. An OTG host must display a message if the device ++ * does not connect. Started when the VBus power is turned on via ++ * sysfs attribute "buspower". ++ */ ++ dwc_timer_t *conn_timer; ++ ++ /* Tasket to do a reset */ ++ dwc_tasklet_t *reset_tasklet; ++ ++ /* */ ++ dwc_spinlock_t *lock; ++ ++ /** ++ * Private data that could be used by OS wrapper. ++ */ ++ void *priv; ++ ++ uint8_t otg_port; ++ ++ /** Frame List */ ++ uint32_t *frame_list; ++ ++ /** Frame List DMA address */ ++ dma_addr_t frame_list_dma; ++ ++#ifdef DEBUG ++ uint32_t frrem_samples; ++ uint64_t frrem_accum; ++ ++ uint32_t hfnum_7_samples_a; ++ uint64_t hfnum_7_frrem_accum_a; ++ uint32_t hfnum_0_samples_a; ++ uint64_t hfnum_0_frrem_accum_a; ++ uint32_t hfnum_other_samples_a; ++ uint64_t hfnum_other_frrem_accum_a; ++ ++ uint32_t hfnum_7_samples_b; ++ uint64_t hfnum_7_frrem_accum_b; ++ uint32_t hfnum_0_samples_b; ++ uint64_t hfnum_0_frrem_accum_b; ++ uint32_t hfnum_other_samples_b; ++ uint64_t hfnum_other_frrem_accum_b; ++#endif ++}; ++ ++/** @name Transaction Execution Functions */ ++/** @{ */ ++extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t ++ * hcd); ++extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd, ++ dwc_otg_transaction_type_e tr_type); ++ ++/** @} */ ++ ++/** @name Interrupt Handler Functions */ ++/** @{ */ ++extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * ++ dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * ++ dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * ++ dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t * ++ dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t * ++ dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, ++ uint32_t num); ++extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t * ++ dwc_otg_hcd); ++/** @} */ ++ ++/** @name Schedule Queue Functions */ ++/** @{ */ ++ ++/* Implemented in dwc_otg_hcd_queue.c */ ++extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd, ++ dwc_otg_hcd_urb_t * urb, int atomic_alloc); ++extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); ++extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); ++extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); ++extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, ++ int sched_csplit); ++ ++/** Remove and free a QH */ ++static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd, ++ dwc_otg_qh_t * qh) ++{ ++ dwc_irqflags_t flags; ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ dwc_otg_hcd_qh_free(hcd, qh); ++} ++ ++/** Allocates memory for a QH structure. ++ * @return Returns the memory allocate or NULL on error. */ ++static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(int atomic_alloc) ++{ ++ if (atomic_alloc) ++ return (dwc_otg_qh_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qh_t)); ++ else ++ return (dwc_otg_qh_t *) DWC_ALLOC(sizeof(dwc_otg_qh_t)); ++} ++ ++extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, ++ int atomic_alloc); ++extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb); ++extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd, ++ dwc_otg_qh_t ** qh, int atomic_alloc); ++ ++/** Allocates memory for a QTD structure. ++ * @return Returns the memory allocate or NULL on error. */ ++static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(int atomic_alloc) ++{ ++ if (atomic_alloc) ++ return (dwc_otg_qtd_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qtd_t)); ++ else ++ return (dwc_otg_qtd_t *) DWC_ALLOC(sizeof(dwc_otg_qtd_t)); ++} ++ ++/** Frees the memory for a QTD structure. QTD should already be removed from ++ * list. ++ * @param qtd QTD to free.*/ ++static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd) ++{ ++ DWC_FREE(qtd); ++} ++ ++/** Removes a QTD from list. ++ * @param hcd HCD instance. ++ * @param qtd QTD to remove from list. ++ * @param qh QTD belongs to. ++ */ ++static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t * hcd, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_qh_t * qh) ++{ ++ DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry); ++} ++ ++/** Remove and free a QTD ++ * Need to disable IRQ and hold hcd lock while calling this function out of ++ * interrupt servicing chain */ ++static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_qh_t * qh) ++{ ++ dwc_otg_hcd_qtd_remove(hcd, qtd, qh); ++ dwc_otg_hcd_qtd_free(qtd); ++} ++ ++/** @} */ ++ ++/** @name Descriptor DMA Supporting Functions */ ++/** @{ */ ++ ++extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); ++extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_halt_status_e halt_status); ++ ++extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); ++extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); ++ ++/** @} */ ++ ++/** @name Internal Functions */ ++/** @{ */ ++dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb); ++/** @} */ ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++extern int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, ++ uint8_t devaddr); ++extern void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd); ++#endif ++ ++/** Gets the QH that contains the list_head */ ++#define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry) ++ ++/** Gets the QTD that contains the list_head */ ++#define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry) ++ ++/** Check if QH is non-periodic */ ++#define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \ ++ (_qh_ptr_->ep_type == UE_CONTROL)) ++ ++/** High bandwidth multiplier as encoded in highspeed endpoint descriptors */ ++#define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) ++ ++/** Packet size for any kind of endpoint descriptor */ ++#define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) ++ ++/** ++ * Returns true if _frame1 is less than or equal to _frame2. The comparison is ++ * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the ++ * frame number when the max frame number is reached. ++ */ ++static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2) ++{ ++ return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <= ++ (DWC_HFNUM_MAX_FRNUM >> 1); ++} ++ ++/** ++ * Returns true if _frame1 is greater than _frame2. The comparison is done ++ * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame ++ * number when the max frame number is reached. ++ */ ++static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2) ++{ ++ return (frame1 != frame2) && ++ (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) < ++ (DWC_HFNUM_MAX_FRNUM >> 1)); ++} ++ ++/** ++ * Increments _frame by the amount specified by _inc. The addition is done ++ * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value. ++ */ ++static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc) ++{ ++ return (frame + inc) & DWC_HFNUM_MAX_FRNUM; ++} ++ ++static inline uint16_t dwc_full_frame_num(uint16_t frame) ++{ ++ return (frame & DWC_HFNUM_MAX_FRNUM) >> 3; ++} ++ ++static inline uint16_t dwc_micro_frame_num(uint16_t frame) ++{ ++ return frame & 0x7; ++} ++ ++void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd); ++ ++#ifdef DEBUG ++/** ++ * Macro to sample the remaining PHY clocks left in the current frame. This ++ * may be used during debugging to determine the average time it takes to ++ * execute sections of code. There are two possible sample points, "a" and ++ * "b", so the _letter argument must be one of these values. ++ * ++ * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For ++ * example, "cat /sys/devices/lm0/hcd_frrem". ++ */ ++#define dwc_sample_frrem(_hcd, _qh, _letter) \ ++{ \ ++ hfnum_data_t hfnum; \ ++ dwc_otg_qtd_t *qtd; \ ++ qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \ ++ if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \ ++ hfnum.d32 = DWC_READ_REG32(&_hcd->core_if->host_if->host_global_regs->hfnum); \ ++ switch (hfnum.b.frnum & 0x7) { \ ++ case 7: \ ++ _hcd->hfnum_7_samples_##_letter++; \ ++ _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \ ++ break; \ ++ case 0: \ ++ _hcd->hfnum_0_samples_##_letter++; \ ++ _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \ ++ break; \ ++ default: \ ++ _hcd->hfnum_other_samples_##_letter++; \ ++ _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \ ++ break; \ ++ } \ ++ } \ ++} ++#else ++#define dwc_sample_frrem(_hcd, _qh, _letter) ++#endif ++#endif ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_ddma.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_ddma.c +new file mode 100644 +index 0000000..fd20354 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_ddma.c +@@ -0,0 +1,1122 @@ ++/*========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $ ++ * $Revision: #11 $ ++ * $Date: 2013/01/24 $ ++ * $Change: 2150761 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_DEVICE_ONLY ++ ++/** @file ++ * This file contains Descriptor DMA support implementation for host mode. ++ */ ++ ++#include "dwc_otg_hcd.h" ++#include "dwc_otg_regs.h" ++ ++static inline uint8_t frame_list_idx(uint16_t frame) ++{ ++ return (frame & (MAX_FRLIST_EN_NUM - 1)); ++} ++ ++static inline uint16_t desclist_idx_inc(uint16_t idx, uint16_t inc, uint8_t speed) ++{ ++ return (idx + inc) & ++ (((speed == ++ DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : ++ MAX_DMA_DESC_NUM_GENERIC) - 1); ++} ++ ++static inline uint16_t desclist_idx_dec(uint16_t idx, uint16_t inc, uint8_t speed) ++{ ++ return (idx - inc) & ++ (((speed == ++ DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : ++ MAX_DMA_DESC_NUM_GENERIC) - 1); ++} ++ ++static inline uint16_t max_desc_num(dwc_otg_qh_t * qh) ++{ ++ return (((qh->ep_type == UE_ISOCHRONOUS) ++ && (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH)) ++ ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC); ++} ++static inline uint16_t frame_incr_val(dwc_otg_qh_t * qh) ++{ ++ return ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) ++ ? ((qh->interval + 8 - 1) / 8) ++ : qh->interval); ++} ++ ++static int desc_list_alloc(dwc_otg_qh_t * qh) ++{ ++ int retval = 0; ++ ++ qh->desc_list = (dwc_otg_host_dma_desc_t *) ++ DWC_DMA_ALLOC(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh), ++ &qh->desc_list_dma); ++ ++ if (!qh->desc_list) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR("%s: DMA descriptor list allocation failed\n", __func__); ++ ++ } ++ ++ dwc_memset(qh->desc_list, 0x00, ++ sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh)); ++ ++ qh->n_bytes = ++ (uint32_t *) DWC_ALLOC(sizeof(uint32_t) * max_desc_num(qh)); ++ ++ if (!qh->n_bytes) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR ++ ("%s: Failed to allocate array for descriptors' size actual values\n", ++ __func__); ++ ++ } ++ return retval; ++ ++} ++ ++static void desc_list_free(dwc_otg_qh_t * qh) ++{ ++ if (qh->desc_list) { ++ DWC_DMA_FREE(max_desc_num(qh), qh->desc_list, ++ qh->desc_list_dma); ++ qh->desc_list = NULL; ++ } ++ ++ if (qh->n_bytes) { ++ DWC_FREE(qh->n_bytes); ++ qh->n_bytes = NULL; ++ } ++} ++ ++static int frame_list_alloc(dwc_otg_hcd_t * hcd) ++{ ++ int retval = 0; ++ if (hcd->frame_list) ++ return 0; ++ ++ hcd->frame_list = DWC_DMA_ALLOC(4 * MAX_FRLIST_EN_NUM, ++ &hcd->frame_list_dma); ++ if (!hcd->frame_list) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR("%s: Frame List allocation failed\n", __func__); ++ } ++ ++ dwc_memset(hcd->frame_list, 0x00, 4 * MAX_FRLIST_EN_NUM); ++ ++ return retval; ++} ++ ++static void frame_list_free(dwc_otg_hcd_t * hcd) ++{ ++ if (!hcd->frame_list) ++ return; ++ ++ DWC_DMA_FREE(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma); ++ hcd->frame_list = NULL; ++} ++ ++static void per_sched_enable(dwc_otg_hcd_t * hcd, uint16_t fr_list_en) ++{ ++ ++ hcfg_data_t hcfg; ++ ++ hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg); ++ ++ if (hcfg.b.perschedena) { ++ /* already enabled */ ++ return; ++ } ++ ++ DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hflbaddr, ++ hcd->frame_list_dma); ++ ++ switch (fr_list_en) { ++ case 64: ++ hcfg.b.frlisten = 3; ++ break; ++ case 32: ++ hcfg.b.frlisten = 2; ++ break; ++ case 16: ++ hcfg.b.frlisten = 1; ++ break; ++ case 8: ++ hcfg.b.frlisten = 0; ++ break; ++ default: ++ break; ++ } ++ ++ hcfg.b.perschedena = 1; ++ ++ DWC_DEBUGPL(DBG_HCD, "Enabling Periodic schedule\n"); ++ DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++ ++} ++ ++static void per_sched_disable(dwc_otg_hcd_t * hcd) ++{ ++ hcfg_data_t hcfg; ++ ++ hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg); ++ ++ if (!hcfg.b.perschedena) { ++ /* already disabled */ ++ return; ++ } ++ hcfg.b.perschedena = 0; ++ ++ DWC_DEBUGPL(DBG_HCD, "Disabling Periodic schedule\n"); ++ DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++} ++ ++/* ++ * Activates/Deactivates FrameList entries for the channel ++ * based on endpoint servicing period. ++ */ ++void update_frame_list(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t enable) ++{ ++ uint16_t i, j, inc; ++ dwc_hc_t *hc = NULL; ++ ++ if (!qh->channel) { ++ DWC_ERROR("qh->channel = %p", qh->channel); ++ return; ++ } ++ ++ if (!hcd) { ++ DWC_ERROR("------hcd = %p", hcd); ++ return; ++ } ++ ++ if (!hcd->frame_list) { ++ DWC_ERROR("-------hcd->frame_list = %p", hcd->frame_list); ++ return; ++ } ++ ++ hc = qh->channel; ++ inc = frame_incr_val(qh); ++ if (qh->ep_type == UE_ISOCHRONOUS) ++ i = frame_list_idx(qh->sched_frame); ++ else ++ i = 0; ++ ++ j = i; ++ do { ++ if (enable) ++ hcd->frame_list[j] |= (1 << hc->hc_num); ++ else ++ hcd->frame_list[j] &= ~(1 << hc->hc_num); ++ j = (j + inc) & (MAX_FRLIST_EN_NUM - 1); ++ } ++ while (j != i); ++ if (!enable) ++ return; ++ hc->schinfo = 0; ++ if (qh->channel->speed == DWC_OTG_EP_SPEED_HIGH) { ++ j = 1; ++ /* TODO - check this */ ++ inc = (8 + qh->interval - 1) / qh->interval; ++ for (i = 0; i < inc; i++) { ++ hc->schinfo |= j; ++ j = j << qh->interval; ++ } ++ } else { ++ hc->schinfo = 0xff; ++ } ++} ++ ++#if 1 ++void dump_frame_list(dwc_otg_hcd_t * hcd) ++{ ++ int i = 0; ++ DWC_PRINTF("--FRAME LIST (hex) --\n"); ++ for (i = 0; i < MAX_FRLIST_EN_NUM; i++) { ++ DWC_PRINTF("%x\t", hcd->frame_list[i]); ++ if (!(i % 8) && i) ++ DWC_PRINTF("\n"); ++ } ++ DWC_PRINTF("\n----\n"); ++ ++} ++#endif ++ ++static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ dwc_hc_t *hc = qh->channel; ++ if (dwc_qh_is_non_per(qh)) ++ hcd->non_periodic_channels--; ++ else ++ update_frame_list(hcd, qh, 0); ++ ++ /* ++ * The condition is added to prevent double cleanup try in case of device ++ * disconnect. See channel cleanup in dwc_otg_hcd_disconnect_cb(). ++ */ ++ if (hc->qh) { ++ dwc_otg_hc_cleanup(hcd->core_if, hc); ++ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); ++ hc->qh = NULL; ++ } ++ ++ qh->channel = NULL; ++ qh->ntd = 0; ++ ++ if (qh->desc_list) { ++ dwc_memset(qh->desc_list, 0x00, ++ sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh)); ++ } ++} ++ ++/** ++ * Initializes a QH structure's Descriptor DMA related members. ++ * Allocates memory for descriptor list. ++ * On first periodic QH, allocates memory for FrameList ++ * and enables periodic scheduling. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh The QH to init. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ int retval = 0; ++ ++ if (qh->do_split) { ++ DWC_ERROR("SPLIT Transfers are not supported in Descriptor DMA.\n"); ++ return -1; ++ } ++ ++ retval = desc_list_alloc(qh); ++ ++ if ((retval == 0) ++ && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) { ++ if (!hcd->frame_list) { ++ retval = frame_list_alloc(hcd); ++ /* Enable periodic schedule on first periodic QH */ ++ if (retval == 0) ++ per_sched_enable(hcd, MAX_FRLIST_EN_NUM); ++ } ++ } ++ ++ qh->ntd = 0; ++ ++ return retval; ++} ++ ++/** ++ * Frees descriptor list memory associated with the QH. ++ * If QH is periodic and the last, frees FrameList memory ++ * and disables periodic scheduling. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh The QH to init. ++ */ ++void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ desc_list_free(qh); ++ ++ /* ++ * Channel still assigned due to some reasons. ++ * Seen on Isoc URB dequeue. Channel halted but no subsequent ++ * ChHalted interrupt to release the channel. Afterwards ++ * when it comes here from endpoint disable routine ++ * channel remains assigned. ++ */ ++ if (qh->channel) ++ release_channel_ddma(hcd, qh); ++ ++ if ((qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT) ++ && !hcd->periodic_channels && hcd->frame_list) { ++ ++ per_sched_disable(hcd); ++ frame_list_free(hcd); ++ } ++} ++ ++static uint8_t frame_to_desc_idx(dwc_otg_qh_t * qh, uint16_t frame_idx) ++{ ++ if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) { ++ /* ++ * Descriptor set(8 descriptors) index ++ * which is 8-aligned. ++ */ ++ return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8; ++ } else { ++ return (frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1)); ++ } ++} ++ ++/* ++ * Determine starting frame for Isochronous transfer. ++ * Few frames skipped to prevent race condition with HC. ++ */ ++static uint8_t calc_starting_frame(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, ++ uint8_t * skip_frames) ++{ ++ uint16_t frame = 0; ++ hcd->frame_number = dwc_otg_hcd_get_frame_number(hcd); ++ ++ /* sched_frame is always frame number(not uFrame) both in FS and HS !! */ ++ ++ /* ++ * skip_frames is used to limit activated descriptors number ++ * to avoid the situation when HC services the last activated ++ * descriptor firstly. ++ * Example for FS: ++ * Current frame is 1, scheduled frame is 3. Since HC always fetches the descriptor ++ * corresponding to curr_frame+1, the descriptor corresponding to frame 2 ++ * will be fetched. If the number of descriptors is max=64 (or greather) the ++ * list will be fully programmed with Active descriptors and it is possible ++ * case(rare) that the latest descriptor(considering rollback) corresponding ++ * to frame 2 will be serviced first. HS case is more probable because, in fact, ++ * up to 11 uframes(16 in the code) may be skipped. ++ */ ++ if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) { ++ /* ++ * Consider uframe counter also, to start xfer asap. ++ * If half of the frame elapsed skip 2 frames otherwise ++ * just 1 frame. ++ * Starting descriptor index must be 8-aligned, so ++ * if the current frame is near to complete the next one ++ * is skipped as well. ++ */ ++ ++ if (dwc_micro_frame_num(hcd->frame_number) >= 5) { ++ *skip_frames = 2 * 8; ++ frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames); ++ } else { ++ *skip_frames = 1 * 8; ++ frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames); ++ } ++ ++ frame = dwc_full_frame_num(frame); ++ } else { ++ /* ++ * Two frames are skipped for FS - the current and the next. ++ * But for descriptor programming, 1 frame(descriptor) is enough, ++ * see example above. ++ */ ++ *skip_frames = 1; ++ frame = dwc_frame_num_inc(hcd->frame_number, 2); ++ } ++ ++ return frame; ++} ++ ++/* ++ * Calculate initial descriptor index for isochronous transfer ++ * based on scheduled frame. ++ */ ++static uint8_t recalc_initial_desc_idx(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ uint16_t frame = 0, fr_idx, fr_idx_tmp; ++ uint8_t skip_frames = 0; ++ /* ++ * With current ISOC processing algorithm the channel is being ++ * released when no more QTDs in the list(qh->ntd == 0). ++ * Thus this function is called only when qh->ntd == 0 and qh->channel == 0. ++ * ++ * So qh->channel != NULL branch is not used and just not removed from the ++ * source file. It is required for another possible approach which is, ++ * do not disable and release the channel when ISOC session completed, ++ * just move QH to inactive schedule until new QTD arrives. ++ * On new QTD, the QH moved back to 'ready' schedule, ++ * starting frame and therefore starting desc_index are recalculated. ++ * In this case channel is released only on ep_disable. ++ */ ++ ++ /* Calculate starting descriptor index. For INTERRUPT endpoint it is always 0. */ ++ if (qh->channel) { ++ frame = calc_starting_frame(hcd, qh, &skip_frames); ++ /* ++ * Calculate initial descriptor index based on FrameList current bitmap ++ * and servicing period. ++ */ ++ fr_idx_tmp = frame_list_idx(frame); ++ fr_idx = ++ (MAX_FRLIST_EN_NUM + frame_list_idx(qh->sched_frame) - ++ fr_idx_tmp) ++ % frame_incr_val(qh); ++ fr_idx = (fr_idx + fr_idx_tmp) % MAX_FRLIST_EN_NUM; ++ } else { ++ qh->sched_frame = calc_starting_frame(hcd, qh, &skip_frames); ++ fr_idx = frame_list_idx(qh->sched_frame); ++ } ++ ++ qh->td_first = qh->td_last = frame_to_desc_idx(qh, fr_idx); ++ ++ return skip_frames; ++} ++ ++#define ISOC_URB_GIVEBACK_ASAP ++ ++#define MAX_ISOC_XFER_SIZE_FS 1023 ++#define MAX_ISOC_XFER_SIZE_HS 3072 ++#define DESCNUM_THRESHOLD 4 ++ ++static void init_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, ++ uint8_t skip_frames) ++{ ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc; ++ dwc_otg_qtd_t *qtd; ++ dwc_otg_host_dma_desc_t *dma_desc; ++ uint16_t idx, inc, n_desc, ntd_max, max_xfer_size; ++ ++ idx = qh->td_last; ++ inc = qh->interval; ++ n_desc = 0; ++ ++ ntd_max = (max_desc_num(qh) + qh->interval - 1) / qh->interval; ++ if (skip_frames && !qh->channel) ++ ntd_max = ntd_max - skip_frames / qh->interval; ++ ++ max_xfer_size = ++ (qh->dev_speed == ++ DWC_OTG_EP_SPEED_HIGH) ? MAX_ISOC_XFER_SIZE_HS : ++ MAX_ISOC_XFER_SIZE_FS; ++ ++ DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) { ++ while ((qh->ntd < ntd_max) ++ && (qtd->isoc_frame_index_last < ++ qtd->urb->packet_count)) { ++ ++ dma_desc = &qh->desc_list[idx]; ++ dwc_memset(dma_desc, 0x00, sizeof(dwc_otg_host_dma_desc_t)); ++ ++ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last]; ++ ++ if (frame_desc->length > max_xfer_size) ++ qh->n_bytes[idx] = max_xfer_size; ++ else ++ qh->n_bytes[idx] = frame_desc->length; ++ dma_desc->status.b_isoc.n_bytes = qh->n_bytes[idx]; ++ dma_desc->status.b_isoc.a = 1; ++ dma_desc->status.b_isoc.sts = 0; ++ ++ dma_desc->buf = qtd->urb->dma + frame_desc->offset; ++ ++ qh->ntd++; ++ ++ qtd->isoc_frame_index_last++; ++ ++#ifdef ISOC_URB_GIVEBACK_ASAP ++ /* ++ * Set IOC for each descriptor corresponding to the ++ * last frame of the URB. ++ */ ++ if (qtd->isoc_frame_index_last == ++ qtd->urb->packet_count) ++ dma_desc->status.b_isoc.ioc = 1; ++ ++#endif ++ idx = desclist_idx_inc(idx, inc, qh->dev_speed); ++ n_desc++; ++ ++ } ++ qtd->in_process = 1; ++ } ++ ++ qh->td_last = idx; ++ ++#ifdef ISOC_URB_GIVEBACK_ASAP ++ /* Set IOC for the last descriptor if descriptor list is full */ ++ if (qh->ntd == ntd_max) { ++ idx = desclist_idx_dec(qh->td_last, inc, qh->dev_speed); ++ qh->desc_list[idx].status.b_isoc.ioc = 1; ++ } ++#else ++ /* ++ * Set IOC bit only for one descriptor. ++ * Always try to be ahead of HW processing, ++ * i.e. on IOC generation driver activates next descriptors but ++ * core continues to process descriptors followed the one with IOC set. ++ */ ++ ++ if (n_desc > DESCNUM_THRESHOLD) { ++ /* ++ * Move IOC "up". Required even if there is only one QTD ++ * in the list, cause QTDs migth continue to be queued, ++ * but during the activation it was only one queued. ++ * Actually more than one QTD might be in the list if this function called ++ * from XferCompletion - QTDs was queued during HW processing of the previous ++ * descriptor chunk. ++ */ ++ idx = dwc_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2), qh->dev_speed); ++ } else { ++ /* ++ * Set the IOC for the latest descriptor ++ * if either number of descriptor is not greather than threshold ++ * or no more new descriptors activated. ++ */ ++ idx = dwc_desclist_idx_dec(qh->td_last, inc, qh->dev_speed); ++ } ++ ++ qh->desc_list[idx].status.b_isoc.ioc = 1; ++#endif ++} ++ ++static void init_non_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ ++ dwc_hc_t *hc; ++ dwc_otg_host_dma_desc_t *dma_desc; ++ dwc_otg_qtd_t *qtd; ++ int num_packets, len, n_desc = 0; ++ ++ hc = qh->channel; ++ ++ /* ++ * Start with hc->xfer_buff initialized in ++ * assign_and_init_hc(), then if SG transfer consists of multiple URBs, ++ * this pointer re-assigned to the buffer of the currently processed QTD. ++ * For non-SG request there is always one QTD active. ++ */ ++ ++ DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) { ++ ++ if (n_desc) { ++ /* SG request - more than 1 QTDs */ ++ hc->xfer_buff = (uint8_t *)qtd->urb->dma + qtd->urb->actual_length; ++ hc->xfer_len = qtd->urb->length - qtd->urb->actual_length; ++ } ++ ++ qtd->n_desc = 0; ++ ++ do { ++ dma_desc = &qh->desc_list[n_desc]; ++ len = hc->xfer_len; ++ ++ if (len > MAX_DMA_DESC_SIZE) ++ len = MAX_DMA_DESC_SIZE - hc->max_packet + 1; ++ ++ if (hc->ep_is_in) { ++ if (len > 0) { ++ num_packets = (len + hc->max_packet - 1) / hc->max_packet; ++ } else { ++ /* Need 1 packet for transfer length of 0. */ ++ num_packets = 1; ++ } ++ /* Always program an integral # of max packets for IN transfers. */ ++ len = num_packets * hc->max_packet; ++ } ++ ++ dma_desc->status.b.n_bytes = len; ++ ++ qh->n_bytes[n_desc] = len; ++ ++ if ((qh->ep_type == UE_CONTROL) ++ && (qtd->control_phase == DWC_OTG_CONTROL_SETUP)) ++ dma_desc->status.b.sup = 1; /* Setup Packet */ ++ ++ dma_desc->status.b.a = 1; /* Active descriptor */ ++ dma_desc->status.b.sts = 0; ++ ++ dma_desc->buf = ++ ((unsigned long)hc->xfer_buff & 0xffffffff); ++ ++ /* ++ * Last descriptor(or single) of IN transfer ++ * with actual size less than MaxPacket. ++ */ ++ if (len > hc->xfer_len) { ++ hc->xfer_len = 0; ++ } else { ++ hc->xfer_buff += len; ++ hc->xfer_len -= len; ++ } ++ ++ qtd->n_desc++; ++ n_desc++; ++ } ++ while ((hc->xfer_len > 0) && (n_desc != MAX_DMA_DESC_NUM_GENERIC)); ++ ++ ++ qtd->in_process = 1; ++ ++ if (qh->ep_type == UE_CONTROL) ++ break; ++ ++ if (n_desc == MAX_DMA_DESC_NUM_GENERIC) ++ break; ++ } ++ ++ if (n_desc) { ++ /* Request Transfer Complete interrupt for the last descriptor */ ++ qh->desc_list[n_desc - 1].status.b.ioc = 1; ++ /* End of List indicator */ ++ qh->desc_list[n_desc - 1].status.b.eol = 1; ++ ++ hc->ntd = n_desc; ++ } ++} ++ ++/** ++ * For Control and Bulk endpoints initializes descriptor list ++ * and starts the transfer. ++ * ++ * For Interrupt and Isochronous endpoints initializes descriptor list ++ * then updates FrameList, marking appropriate entries as active. ++ * In case of Isochronous, the starting descriptor index is calculated based ++ * on the scheduled frame, but only on the first transfer descriptor within a session. ++ * Then starts the transfer via enabling the channel. ++ * For Isochronous endpoint the channel is not halted on XferComplete ++ * interrupt so remains assigned to the endpoint(QH) until session is done. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh The QH to init. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ /* Channel is already assigned */ ++ dwc_hc_t *hc = qh->channel; ++ uint8_t skip_frames = 0; ++ ++ switch (hc->ep_type) { ++ case DWC_OTG_EP_TYPE_CONTROL: ++ case DWC_OTG_EP_TYPE_BULK: ++ init_non_isoc_dma_desc(hcd, qh); ++ ++ dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); ++ break; ++ case DWC_OTG_EP_TYPE_INTR: ++ init_non_isoc_dma_desc(hcd, qh); ++ ++ update_frame_list(hcd, qh, 1); ++ ++ dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); ++ break; ++ case DWC_OTG_EP_TYPE_ISOC: ++ ++ if (!qh->ntd) ++ skip_frames = recalc_initial_desc_idx(hcd, qh); ++ ++ init_isoc_dma_desc(hcd, qh, skip_frames); ++ ++ if (!hc->xfer_started) { ++ ++ update_frame_list(hcd, qh, 1); ++ ++ /* ++ * Always set to max, instead of actual size. ++ * Otherwise ntd will be changed with ++ * channel being enabled. Not recommended. ++ * ++ */ ++ hc->ntd = max_desc_num(qh); ++ /* Enable channel only once for ISOC */ ++ dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); ++ } ++ ++ break; ++ default: ++ ++ break; ++ } ++} ++ ++static void complete_isoc_xfer_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_halt_status_e halt_status) ++{ ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc; ++ dwc_otg_qtd_t *qtd, *qtd_tmp; ++ dwc_otg_qh_t *qh; ++ dwc_otg_host_dma_desc_t *dma_desc; ++ uint16_t idx, remain; ++ uint8_t urb_compl; ++ ++ qh = hc->qh; ++ idx = qh->td_first; ++ ++ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) ++ qtd->in_process = 0; ++ return; ++ } else if ((halt_status == DWC_OTG_HC_XFER_AHB_ERR) || ++ (halt_status == DWC_OTG_HC_XFER_BABBLE_ERR)) { ++ /* ++ * Channel is halted in these error cases. ++ * Considered as serious issues. ++ * Complete all URBs marking all frames as failed, ++ * irrespective whether some of the descriptors(frames) succeeded or no. ++ * Pass error code to completion routine as well, to ++ * update urb->status, some of class drivers might use it to stop ++ * queing transfer requests. ++ */ ++ int err = (halt_status == DWC_OTG_HC_XFER_AHB_ERR) ++ ? (-DWC_E_IO) ++ : (-DWC_E_OVERFLOW); ++ ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { ++ for (idx = 0; idx < qtd->urb->packet_count; idx++) { ++ frame_desc = &qtd->urb->iso_descs[idx]; ++ frame_desc->status = err; ++ } ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, err); ++ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ } ++ return; ++ } ++ ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { ++ ++ if (!qtd->in_process) ++ break; ++ ++ urb_compl = 0; ++ ++ do { ++ ++ dma_desc = &qh->desc_list[idx]; ++ ++ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; ++ remain = hc->ep_is_in ? dma_desc->status.b_isoc.n_bytes : 0; ++ ++ if (dma_desc->status.b_isoc.sts == DMA_DESC_STS_PKTERR) { ++ /* ++ * XactError or, unable to complete all the transactions ++ * in the scheduled micro-frame/frame, ++ * both indicated by DMA_DESC_STS_PKTERR. ++ */ ++ qtd->urb->error_count++; ++ frame_desc->actual_length = qh->n_bytes[idx] - remain; ++ frame_desc->status = -DWC_E_PROTOCOL; ++ } else { ++ /* Success */ ++ ++ frame_desc->actual_length = qh->n_bytes[idx] - remain; ++ frame_desc->status = 0; ++ } ++ ++ if (++qtd->isoc_frame_index == qtd->urb->packet_count) { ++ /* ++ * urb->status is not used for isoc transfers here. ++ * The individual frame_desc status are used instead. ++ */ ++ ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); ++ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ ++ /* ++ * This check is necessary because urb_dequeue can be called ++ * from urb complete callback(sound driver example). ++ * All pending URBs are dequeued there, so no need for ++ * further processing. ++ */ ++ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { ++ return; ++ } ++ ++ urb_compl = 1; ++ ++ } ++ ++ qh->ntd--; ++ ++ /* Stop if IOC requested descriptor reached */ ++ if (dma_desc->status.b_isoc.ioc) { ++ idx = desclist_idx_inc(idx, qh->interval, hc->speed); ++ goto stop_scan; ++ } ++ ++ idx = desclist_idx_inc(idx, qh->interval, hc->speed); ++ ++ if (urb_compl) ++ break; ++ } ++ while (idx != qh->td_first); ++ } ++stop_scan: ++ qh->td_first = idx; ++} ++ ++uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_host_dma_desc_t * dma_desc, ++ dwc_otg_halt_status_e halt_status, ++ uint32_t n_bytes, uint8_t * xfer_done) ++{ ++ ++ uint16_t remain = hc->ep_is_in ? dma_desc->status.b.n_bytes : 0; ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ ++ if (halt_status == DWC_OTG_HC_XFER_AHB_ERR) { ++ urb->status = -DWC_E_IO; ++ return 1; ++ } ++ if (dma_desc->status.b.sts == DMA_DESC_STS_PKTERR) { ++ switch (halt_status) { ++ case DWC_OTG_HC_XFER_STALL: ++ urb->status = -DWC_E_PIPE; ++ break; ++ case DWC_OTG_HC_XFER_BABBLE_ERR: ++ urb->status = -DWC_E_OVERFLOW; ++ break; ++ case DWC_OTG_HC_XFER_XACT_ERR: ++ urb->status = -DWC_E_PROTOCOL; ++ break; ++ default: ++ DWC_ERROR("%s: Unhandled descriptor error status (%d)\n", __func__, ++ halt_status); ++ break; ++ } ++ return 1; ++ } ++ ++ if (dma_desc->status.b.a == 1) { ++ DWC_DEBUGPL(DBG_HCDV, ++ "Active descriptor encountered on channel %d\n", ++ hc->hc_num); ++ return 0; ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL) { ++ if (qtd->control_phase == DWC_OTG_CONTROL_DATA) { ++ urb->actual_length += n_bytes - remain; ++ if (remain || urb->actual_length == urb->length) { ++ /* ++ * For Control Data stage do not set urb->status=0 to prevent ++ * URB callback. Set it when Status phase done. See below. ++ */ ++ *xfer_done = 1; ++ } ++ ++ } else if (qtd->control_phase == DWC_OTG_CONTROL_STATUS) { ++ urb->status = 0; ++ *xfer_done = 1; ++ } ++ /* No handling for SETUP stage */ ++ } else { ++ /* BULK and INTR */ ++ urb->actual_length += n_bytes - remain; ++ if (remain || urb->actual_length == urb->length) { ++ urb->status = 0; ++ *xfer_done = 1; ++ } ++ } ++ ++ return 0; ++} ++ ++static void complete_non_isoc_xfer_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_halt_status_e halt_status) ++{ ++ dwc_otg_hcd_urb_t *urb = NULL; ++ dwc_otg_qtd_t *qtd, *qtd_tmp; ++ dwc_otg_qh_t *qh; ++ dwc_otg_host_dma_desc_t *dma_desc; ++ uint32_t n_bytes, n_desc, i; ++ uint8_t failed = 0, xfer_done; ++ ++ n_desc = 0; ++ ++ qh = hc->qh; ++ ++ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { ++ qtd->in_process = 0; ++ } ++ return; ++ } ++ ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { ++ ++ urb = qtd->urb; ++ ++ n_bytes = 0; ++ xfer_done = 0; ++ ++ for (i = 0; i < qtd->n_desc; i++) { ++ dma_desc = &qh->desc_list[n_desc]; ++ ++ n_bytes = qh->n_bytes[n_desc]; ++ ++ failed = ++ update_non_isoc_urb_state_ddma(hcd, hc, qtd, ++ dma_desc, ++ halt_status, n_bytes, ++ &xfer_done); ++ ++ if (failed ++ || (xfer_done ++ && (urb->status != -DWC_E_IN_PROGRESS))) { ++ ++ hcd->fops->complete(hcd, urb->priv, urb, ++ urb->status); ++ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ ++ if (failed) ++ goto stop_scan; ++ } else if (qh->ep_type == UE_CONTROL) { ++ if (qtd->control_phase == DWC_OTG_CONTROL_SETUP) { ++ if (urb->length > 0) { ++ qtd->control_phase = DWC_OTG_CONTROL_DATA; ++ } else { ++ qtd->control_phase = DWC_OTG_CONTROL_STATUS; ++ } ++ DWC_DEBUGPL(DBG_HCDV, " Control setup transaction done\n"); ++ } else if (qtd->control_phase == DWC_OTG_CONTROL_DATA) { ++ if (xfer_done) { ++ qtd->control_phase = DWC_OTG_CONTROL_STATUS; ++ DWC_DEBUGPL(DBG_HCDV, " Control data transfer done\n"); ++ } else if (i + 1 == qtd->n_desc) { ++ /* ++ * Last descriptor for Control data stage which is ++ * not completed yet. ++ */ ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ } ++ } ++ } ++ ++ n_desc++; ++ } ++ ++ } ++ ++stop_scan: ++ ++ if (qh->ep_type != UE_CONTROL) { ++ /* ++ * Resetting the data toggle for bulk ++ * and interrupt endpoints in case of stall. See handle_hc_stall_intr() ++ */ ++ if (halt_status == DWC_OTG_HC_XFER_STALL) ++ qh->data_toggle = DWC_OTG_HC_PID_DATA0; ++ else ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ } ++ ++ if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { ++ hcint_data_t hcint; ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ if (hcint.b.nyet) { ++ /* ++ * Got a NYET on the last transaction of the transfer. It ++ * means that the endpoint should be in the PING state at the ++ * beginning of the next transfer. ++ */ ++ qh->ping_state = 1; ++ clear_hc_int(hc_regs, nyet); ++ } ++ ++ } ++ ++} ++ ++/** ++ * This function is called from interrupt handlers. ++ * Scans the descriptor list, updates URB's status and ++ * calls completion routine for the URB if it's done. ++ * Releases the channel to be used by other transfers. ++ * In case of Isochronous endpoint the channel is not halted until ++ * the end of the session, i.e. QTD list is empty. ++ * If periodic channel released the FrameList is updated accordingly. ++ * ++ * Calls transaction selection routines to activate pending transfers. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param hc Host channel, the transfer is completed on. ++ * @param hc_regs Host channel registers. ++ * @param halt_status Reason the channel is being halted, ++ * or just XferComplete for isochronous transfer ++ */ ++void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_halt_status_e halt_status) ++{ ++ uint8_t continue_isoc_xfer = 0; ++ dwc_otg_transaction_type_e tr_type; ++ dwc_otg_qh_t *qh = hc->qh; ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ ++ complete_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status); ++ ++ /* Release the channel if halted or session completed */ ++ if (halt_status != DWC_OTG_HC_XFER_COMPLETE || ++ DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ ++ /* Halt the channel if session completed */ ++ if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { ++ dwc_otg_hc_halt(hcd->core_if, hc, halt_status); ++ } ++ ++ release_channel_ddma(hcd, qh); ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ } else { ++ /* Keep in assigned schedule to continue transfer */ ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, ++ &qh->qh_list_entry); ++ continue_isoc_xfer = 1; ++ ++ } ++ /** @todo Consider the case when period exceeds FrameList size. ++ * Frame Rollover interrupt should be used. ++ */ ++ } else { ++ /* Scan descriptor list to complete the URB(s), then release the channel */ ++ complete_non_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status); ++ ++ release_channel_ddma(hcd, qh); ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ ++ if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ /* Add back to inactive non-periodic schedule on normal completion */ ++ dwc_otg_hcd_qh_add(hcd, qh); ++ } ++ ++ } ++ tr_type = dwc_otg_hcd_select_transactions(hcd); ++ if (tr_type != DWC_OTG_TRANSACTION_NONE || continue_isoc_xfer) { ++ if (continue_isoc_xfer) { ++ if (tr_type == DWC_OTG_TRANSACTION_NONE) { ++ tr_type = DWC_OTG_TRANSACTION_PERIODIC; ++ } else if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC) { ++ tr_type = DWC_OTG_TRANSACTION_ALL; ++ } ++ } ++ dwc_otg_hcd_queue_transactions(hcd, tr_type); ++ } ++} ++ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_if.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_if.h +new file mode 100644 +index 0000000..4823167 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_if.h +@@ -0,0 +1,412 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_if.h $ ++ * $Revision: #12 $ ++ * $Date: 2011/10/26 $ ++ * $Change: 1873028 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_DEVICE_ONLY ++#ifndef __DWC_HCD_IF_H__ ++#define __DWC_HCD_IF_H__ ++ ++#include "dwc_otg_core_if.h" ++ ++/** @file ++ * This file defines DWC_OTG HCD Core API. ++ */ ++ ++struct dwc_otg_hcd; ++typedef struct dwc_otg_hcd dwc_otg_hcd_t; ++ ++struct dwc_otg_hcd_urb; ++typedef struct dwc_otg_hcd_urb dwc_otg_hcd_urb_t; ++ ++/** @name HCD Function Driver Callbacks */ ++/** @{ */ ++ ++/** This function is called whenever core switches to host mode. */ ++typedef int (*dwc_otg_hcd_start_cb_t) (dwc_otg_hcd_t * hcd); ++ ++/** This function is called when device has been disconnected */ ++typedef int (*dwc_otg_hcd_disconnect_cb_t) (dwc_otg_hcd_t * hcd); ++ ++/** Wrapper provides this function to HCD to core, so it can get hub information to which device is connected */ ++typedef int (*dwc_otg_hcd_hub_info_from_urb_cb_t) (dwc_otg_hcd_t * hcd, ++ void *urb_handle, ++ uint32_t * hub_addr, ++ uint32_t * port_addr); ++/** Via this function HCD core gets device speed */ ++typedef int (*dwc_otg_hcd_speed_from_urb_cb_t) (dwc_otg_hcd_t * hcd, ++ void *urb_handle); ++ ++/** This function is called when urb is completed */ ++typedef int (*dwc_otg_hcd_complete_urb_cb_t) (dwc_otg_hcd_t * hcd, ++ void *urb_handle, ++ dwc_otg_hcd_urb_t * dwc_otg_urb, ++ int32_t status); ++ ++/** Via this function HCD core gets b_hnp_enable parameter */ ++typedef int (*dwc_otg_hcd_get_b_hnp_enable) (dwc_otg_hcd_t * hcd); ++ ++struct dwc_otg_hcd_function_ops { ++ dwc_otg_hcd_start_cb_t start; ++ dwc_otg_hcd_disconnect_cb_t disconnect; ++ dwc_otg_hcd_hub_info_from_urb_cb_t hub_info; ++ dwc_otg_hcd_speed_from_urb_cb_t speed; ++ dwc_otg_hcd_complete_urb_cb_t complete; ++ dwc_otg_hcd_get_b_hnp_enable get_b_hnp_enable; ++}; ++/** @} */ ++ ++/** @name HCD Core API */ ++/** @{ */ ++/** This function allocates dwc_otg_hcd structure and returns pointer on it. */ ++extern dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void); ++ ++/** This function should be called to initiate HCD Core. ++ * ++ * @param hcd The HCD ++ * @param core_if The DWC_OTG Core ++ * ++ * Returns -DWC_E_NO_MEMORY if no enough memory. ++ * Returns 0 on success ++ */ ++extern int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if); ++ ++/** Frees HCD ++ * ++ * @param hcd The HCD ++ */ ++extern void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd); ++ ++/** This function should be called on every hardware interrupt. ++ * ++ * @param dwc_otg_hcd The HCD ++ * ++ * Returns non zero if interrupt is handled ++ * Return 0 if interrupt is not handled ++ */ ++extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++ ++/** ++ * Returns private data set by ++ * dwc_otg_hcd_set_priv_data function. ++ * ++ * @param hcd The HCD ++ */ ++extern void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Set private data. ++ * ++ * @param hcd The HCD ++ * @param priv_data pointer to be stored in private data ++ */ ++extern void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data); ++ ++/** ++ * This function initializes the HCD Core. ++ * ++ * @param hcd The HCD ++ * @param fops The Function Driver Operations data structure containing pointers to all callbacks. ++ * ++ * Returns -DWC_E_NO_DEVICE if Core is currently is in device mode. ++ * Returns 0 on success ++ */ ++extern int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd, ++ struct dwc_otg_hcd_function_ops *fops); ++ ++/** ++ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are ++ * stopped. ++ * ++ * @param hcd The HCD ++ */ ++extern void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Handles hub class-specific requests. ++ * ++ * @param dwc_otg_hcd The HCD ++ * @param typeReq Request Type ++ * @param wValue wValue from control request ++ * @param wIndex wIndex from control request ++ * @param buf data buffer ++ * @param wLength data buffer length ++ * ++ * Returns -DWC_E_INVALID if invalid argument is passed ++ * Returns 0 on success ++ */ ++extern int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, ++ uint16_t typeReq, uint16_t wValue, ++ uint16_t wIndex, uint8_t * buf, ++ uint16_t wLength); ++ ++/** ++ * Returns otg port number. ++ * ++ * @param hcd The HCD ++ */ ++extern uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Returns OTG version - either 1.3 or 2.0. ++ * ++ * @param core_if The core_if structure pointer ++ */ ++extern uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Returns 1 if currently core is acting as B host, and 0 otherwise. ++ * ++ * @param hcd The HCD ++ */ ++extern uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Returns current frame number. ++ * ++ * @param hcd The HCD ++ */ ++extern int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Dumps hcd state. ++ * ++ * @param hcd The HCD ++ */ ++extern void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Dump the average frame remaining at SOF. This can be used to ++ * determine average interrupt latency. Frame remaining is also shown for ++ * start transfer and two additional sample points. ++ * Currently this function is not implemented. ++ * ++ * @param hcd The HCD ++ */ ++extern void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Sends LPM transaction to the local device. ++ * ++ * @param hcd The HCD ++ * @param devaddr Device Address ++ * @param hird Host initiated resume duration ++ * @param bRemoteWake Value of bRemoteWake field in LPM transaction ++ * ++ * Returns negative value if sending LPM transaction was not succeeded. ++ * Returns 0 on success. ++ */ ++extern int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, ++ uint8_t hird, uint8_t bRemoteWake); ++ ++/* URB interface */ ++ ++/** ++ * Allocates memory for dwc_otg_hcd_urb structure. ++ * Allocated memory should be freed by call of DWC_FREE. ++ * ++ * @param hcd The HCD ++ * @param iso_desc_count Count of ISOC descriptors ++ * @param atomic_alloc Specefies whether to perform atomic allocation. ++ */ ++extern dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd, ++ int iso_desc_count, ++ int atomic_alloc); ++ ++/** ++ * Set pipe information in URB. ++ * ++ * @param hcd_urb DWC_OTG URB ++ * @param devaddr Device Address ++ * @param ep_num Endpoint Number ++ * @param ep_type Endpoint Type ++ * @param ep_dir Endpoint Direction ++ * @param mps Max Packet Size ++ */ ++extern void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * hcd_urb, ++ uint8_t devaddr, uint8_t ep_num, ++ uint8_t ep_type, uint8_t ep_dir, ++ uint16_t mps); ++ ++/* Transfer flags */ ++#define URB_GIVEBACK_ASAP 0x1 ++#define URB_SEND_ZERO_PACKET 0x2 ++ ++/** ++ * Sets dwc_otg_hcd_urb parameters. ++ * ++ * @param urb DWC_OTG URB allocated by dwc_otg_hcd_urb_alloc function. ++ * @param urb_handle Unique handle for request, this will be passed back ++ * to function driver in completion callback. ++ * @param buf The buffer for the data ++ * @param dma The DMA buffer for the data ++ * @param buflen Transfer length ++ * @param sp Buffer for setup data ++ * @param sp_dma DMA address of setup data buffer ++ * @param flags Transfer flags ++ * @param interval Polling interval for interrupt or isochronous transfers. ++ */ ++extern void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * urb, ++ void *urb_handle, void *buf, ++ dwc_dma_t dma, uint32_t buflen, void *sp, ++ dwc_dma_t sp_dma, uint32_t flags, ++ uint16_t interval); ++ ++/** Gets status from dwc_otg_hcd_urb ++ * ++ * @param dwc_otg_urb DWC_OTG URB ++ */ ++extern uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb); ++ ++/** Gets actual length from dwc_otg_hcd_urb ++ * ++ * @param dwc_otg_urb DWC_OTG URB ++ */ ++extern uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * ++ dwc_otg_urb); ++ ++/** Gets error count from dwc_otg_hcd_urb. Only for ISOC URBs ++ * ++ * @param dwc_otg_urb DWC_OTG URB ++ */ ++extern uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * ++ dwc_otg_urb); ++ ++/** Set ISOC descriptor offset and length ++ * ++ * @param dwc_otg_urb DWC_OTG URB ++ * @param desc_num ISOC descriptor number ++ * @param offset Offset from beginig of buffer. ++ * @param length Transaction length ++ */ ++extern void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb, ++ int desc_num, uint32_t offset, ++ uint32_t length); ++ ++/** Get status of ISOC descriptor, specified by desc_num ++ * ++ * @param dwc_otg_urb DWC_OTG URB ++ * @param desc_num ISOC descriptor number ++ */ ++extern uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * ++ dwc_otg_urb, int desc_num); ++ ++/** Get actual length of ISOC descriptor, specified by desc_num ++ * ++ * @param dwc_otg_urb DWC_OTG URB ++ * @param desc_num ISOC descriptor number ++ */ ++extern uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t * ++ dwc_otg_urb, ++ int desc_num); ++ ++/** Queue URB. After transfer is completes, the complete callback will be called with the URB status ++ * ++ * @param dwc_otg_hcd The HCD ++ * @param dwc_otg_urb DWC_OTG URB ++ * @param ep_handle Out parameter for returning endpoint handle ++ * @param atomic_alloc Flag to do atomic allocation if needed ++ * ++ * Returns -DWC_E_NO_DEVICE if no device is connected. ++ * Returns -DWC_E_NO_MEMORY if there is no enough memory. ++ * Returns 0 on success. ++ */ ++extern int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * dwc_otg_hcd, ++ dwc_otg_hcd_urb_t * dwc_otg_urb, ++ void **ep_handle, int atomic_alloc); ++ ++/** De-queue the specified URB ++ * ++ * @param dwc_otg_hcd The HCD ++ * @param dwc_otg_urb DWC_OTG URB ++ */ ++extern int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * dwc_otg_hcd, ++ dwc_otg_hcd_urb_t * dwc_otg_urb); ++ ++/** Frees resources in the DWC_otg controller related to a given endpoint. ++ * Any URBs for the endpoint must already be dequeued. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function ++ * @param retry Number of retries if there are queued transfers. ++ * ++ * Returns -DWC_E_INVALID if invalid arguments are passed. ++ * Returns 0 on success ++ */ ++extern int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle, ++ int retry); ++ ++/* Resets the data toggle in qh structure. This function can be called from ++ * usb_clear_halt routine. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function ++ * ++ * Returns -DWC_E_INVALID if invalid arguments are passed. ++ * Returns 0 on success ++ */ ++extern int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle); ++ ++/** Returns 1 if status of specified port is changed and 0 otherwise. ++ * ++ * @param hcd The HCD ++ * @param port Port number ++ */ ++extern int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port); ++ ++/** Call this function to check if bandwidth was allocated for specified endpoint. ++ * Only for ISOC and INTERRUPT endpoints. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle ++ */ ++extern int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, ++ void *ep_handle); ++ ++/** Call this function to check if bandwidth was freed for specified endpoint. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle ++ */ ++extern int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle); ++ ++/** Returns bandwidth allocated for specified endpoint in microseconds. ++ * Only for ISOC and INTERRUPT endpoints. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle ++ */ ++extern uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, ++ void *ep_handle); ++ ++/** @} */ ++ ++#endif /* __DWC_HCD_IF_H__ */ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_intr.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_intr.c +new file mode 100644 +index 0000000..23b1d9d +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_intr.c +@@ -0,0 +1,2105 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $ ++ * $Revision: #94 $ ++ * $Date: 2013/01/31 $ ++ * $Change: 2155605 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_DEVICE_ONLY ++ ++#include "dwc_otg_hcd.h" ++#include "dwc_otg_regs.h" ++ ++/** @file ++ * This file contains the implementation of the HCD Interrupt handlers. ++ */ ++ ++/** This function handles interrupts for the HCD. */ ++int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ int retval = 0; ++ ++ dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; ++ gintsts_data_t gintsts; ++#ifdef DEBUG ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++#endif ++ ++ if (dwc_otg_check_haps_status(core_if) == -1 ) { ++ DWC_WARN("HAPS is disconnected"); ++ return retval; ++ } ++ ++ /* Exit from ISR if core is hibernated */ ++ if (core_if->hibernation_suspend == 1) { ++ return retval; ++ } ++ DWC_SPINLOCK(dwc_otg_hcd->lock); ++ /* Check if HOST Mode */ ++ if (dwc_otg_is_host_mode(core_if)) { ++ gintsts.d32 = dwc_otg_read_core_intr(core_if); ++ if (!gintsts.d32) { ++ DWC_SPINUNLOCK(dwc_otg_hcd->lock); ++ return 0; ++ } ++#ifdef DEBUG ++ /* Don't print debug message in the interrupt handler on SOF */ ++#ifndef DEBUG_SOF ++ if (gintsts.d32 != DWC_SOF_INTR_MASK) ++#endif ++ DWC_DEBUGPL(DBG_HCD, "\n"); ++#endif ++ ++#ifdef DEBUG ++#ifndef DEBUG_SOF ++ if (gintsts.d32 != DWC_SOF_INTR_MASK) ++#endif ++ DWC_DEBUGPL(DBG_HCD, ++ "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x\n", ++ gintsts.d32); ++#endif ++ ++ if (gintsts.b.sofintr) { ++ retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd); ++ } ++ if (gintsts.b.rxstsqlvl) { ++ retval |= ++ dwc_otg_hcd_handle_rx_status_q_level_intr ++ (dwc_otg_hcd); ++ } ++ if (gintsts.b.nptxfempty) { ++ retval |= ++ dwc_otg_hcd_handle_np_tx_fifo_empty_intr ++ (dwc_otg_hcd); ++ } ++ if (gintsts.b.i2cintr) { ++ /** @todo Implement i2cintr handler. */ ++ } ++ if (gintsts.b.portintr) { ++ retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd); ++ } ++ if (gintsts.b.hcintr) { ++ retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd); ++ } ++ if (gintsts.b.ptxfempty) { ++ retval |= ++ dwc_otg_hcd_handle_perio_tx_fifo_empty_intr ++ (dwc_otg_hcd); ++ } ++#ifdef DEBUG ++#ifndef DEBUG_SOF ++ if (gintsts.d32 != DWC_SOF_INTR_MASK) ++#endif ++ { ++ DWC_DEBUGPL(DBG_HCD, ++ "DWC OTG HCD Finished Servicing Interrupts\n"); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintsts=0x%08x\n", ++ DWC_READ_REG32(&global_regs->gintsts)); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintmsk=0x%08x\n", ++ DWC_READ_REG32(&global_regs->gintmsk)); ++ } ++#endif ++ ++#ifdef DEBUG ++#ifndef DEBUG_SOF ++ if (gintsts.d32 != DWC_SOF_INTR_MASK) ++#endif ++ DWC_DEBUGPL(DBG_HCD, "\n"); ++#endif ++ ++ } ++ DWC_SPINUNLOCK(dwc_otg_hcd->lock); ++ return retval; ++} ++ ++#ifdef DWC_TRACK_MISSED_SOFS ++#warning Compiling code to track missed SOFs ++#define FRAME_NUM_ARRAY_SIZE 1000 ++/** ++ * This function is for debug only. ++ */ ++static inline void track_missed_sofs(uint16_t curr_frame_number) ++{ ++ static uint16_t frame_num_array[FRAME_NUM_ARRAY_SIZE]; ++ static uint16_t last_frame_num_array[FRAME_NUM_ARRAY_SIZE]; ++ static int frame_num_idx = 0; ++ static uint16_t last_frame_num = DWC_HFNUM_MAX_FRNUM; ++ static int dumped_frame_num_array = 0; ++ ++ if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) { ++ if (((last_frame_num + 1) & DWC_HFNUM_MAX_FRNUM) != ++ curr_frame_number) { ++ frame_num_array[frame_num_idx] = curr_frame_number; ++ last_frame_num_array[frame_num_idx++] = last_frame_num; ++ } ++ } else if (!dumped_frame_num_array) { ++ int i; ++ DWC_PRINTF("Frame Last Frame\n"); ++ DWC_PRINTF("----- ----------\n"); ++ for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) { ++ DWC_PRINTF("0x%04x 0x%04x\n", ++ frame_num_array[i], last_frame_num_array[i]); ++ } ++ dumped_frame_num_array = 1; ++ } ++ last_frame_num = curr_frame_number; ++} ++#endif ++ ++/** ++ * Handles the start-of-frame interrupt in host mode. Non-periodic ++ * transactions may be queued to the DWC_otg controller for the current ++ * (micro)frame. Periodic transactions may be queued to the controller for the ++ * next (micro)frame. ++ */ ++int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd) ++{ ++ hfnum_data_t hfnum; ++ dwc_list_link_t *qh_entry; ++ dwc_otg_qh_t *qh; ++ dwc_otg_transaction_type_e tr_type; ++ gintsts_data_t gintsts = {.d32 = 0 }; ++ ++ hfnum.d32 = ++ DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum); ++ ++#ifdef DEBUG_SOF ++ DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n"); ++#endif ++ hcd->frame_number = hfnum.b.frnum; ++ ++#ifdef DEBUG ++ hcd->frrem_accum += hfnum.b.frrem; ++ hcd->frrem_samples++; ++#endif ++ ++#ifdef DWC_TRACK_MISSED_SOFS ++ track_missed_sofs(hcd->frame_number); ++#endif ++ /* Determine whether any periodic QHs should be executed. */ ++ qh_entry = DWC_LIST_FIRST(&hcd->periodic_sched_inactive); ++ while (qh_entry != &hcd->periodic_sched_inactive) { ++ qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry); ++ qh_entry = qh_entry->next; ++ if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) { ++ /* ++ * Move QH to the ready list to be executed next ++ * (micro)frame. ++ */ ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready, ++ &qh->qh_list_entry); ++ } ++ } ++ tr_type = dwc_otg_hcd_select_transactions(hcd); ++ if (tr_type != DWC_OTG_TRANSACTION_NONE) { ++ dwc_otg_hcd_queue_transactions(hcd, tr_type); ++ } ++ ++ /* Clear interrupt */ ++ gintsts.b.sofintr = 1; ++ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** Handles the Rx Status Queue Level Interrupt, which indicates that there is at ++ * least one packet in the Rx FIFO. The packets are moved from the FIFO to ++ * memory if the DWC_otg controller is operating in Slave mode. */ ++int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ host_grxsts_data_t grxsts; ++ dwc_hc_t *hc = NULL; ++ ++ DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n"); ++ ++ grxsts.d32 = ++ DWC_READ_REG32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp); ++ ++ hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum]; ++ if (!hc) { ++ DWC_ERROR("Unable to get corresponding channel\n"); ++ return 0; ++ } ++ ++ /* Packet Status */ ++ DWC_DEBUGPL(DBG_HCDV, " Ch num = %d\n", grxsts.b.chnum); ++ DWC_DEBUGPL(DBG_HCDV, " Count = %d\n", grxsts.b.bcnt); ++ DWC_DEBUGPL(DBG_HCDV, " DPID = %d, hc.dpid = %d\n", grxsts.b.dpid, ++ hc->data_pid_start); ++ DWC_DEBUGPL(DBG_HCDV, " PStatus = %d\n", grxsts.b.pktsts); ++ ++ switch (grxsts.b.pktsts) { ++ case DWC_GRXSTS_PKTSTS_IN: ++ /* Read the data into the host buffer. */ ++ if (grxsts.b.bcnt > 0) { ++ dwc_otg_read_packet(dwc_otg_hcd->core_if, ++ hc->xfer_buff, grxsts.b.bcnt); ++ ++ /* Update the HC fields for the next packet received. */ ++ hc->xfer_count += grxsts.b.bcnt; ++ hc->xfer_buff += grxsts.b.bcnt; ++ } ++ ++ case DWC_GRXSTS_PKTSTS_IN_XFER_COMP: ++ case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR: ++ case DWC_GRXSTS_PKTSTS_CH_HALTED: ++ /* Handled in interrupt, just ignore data */ ++ break; ++ default: ++ DWC_ERROR("RX_STS_Q Interrupt: Unknown status %d\n", ++ grxsts.b.pktsts); ++ break; ++ } ++ ++ return 1; ++} ++ ++/** This interrupt occurs when the non-periodic Tx FIFO is half-empty. More ++ * data packets may be written to the FIFO for OUT transfers. More requests ++ * may be written to the non-periodic request queue for IN transfers. This ++ * interrupt is enabled only in Slave mode. */ ++int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Non-Periodic TxFIFO Empty Interrupt--\n"); ++ dwc_otg_hcd_queue_transactions(dwc_otg_hcd, ++ DWC_OTG_TRANSACTION_NON_PERIODIC); ++ return 1; ++} ++ ++/** This interrupt occurs when the periodic Tx FIFO is half-empty. More data ++ * packets may be written to the FIFO for OUT transfers. More requests may be ++ * written to the periodic request queue for IN transfers. This interrupt is ++ * enabled only in Slave mode. */ ++int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n"); ++ dwc_otg_hcd_queue_transactions(dwc_otg_hcd, ++ DWC_OTG_TRANSACTION_PERIODIC); ++ return 1; ++} ++ ++/** There are multiple conditions that can cause a port interrupt. This function ++ * determines which interrupt conditions have occurred and handles them ++ * appropriately. */ ++int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ int retval = 0; ++ hprt0_data_t hprt0; ++ hprt0_data_t hprt0_modify; ++ ++ hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0); ++ hprt0_modify.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0); ++ ++ /* Clear appropriate bits in HPRT0 to clear the interrupt bit in ++ * GINTSTS */ ++ ++ hprt0_modify.b.prtena = 0; ++ hprt0_modify.b.prtconndet = 0; ++ hprt0_modify.b.prtenchng = 0; ++ hprt0_modify.b.prtovrcurrchng = 0; ++ ++ /* Port Connect Detected ++ * Set flag and clear if detected */ ++ if (dwc_otg_hcd->core_if->hibernation_suspend == 1) { ++ // Dont modify port status if we are in hibernation state ++ hprt0_modify.b.prtconndet = 1; ++ hprt0_modify.b.prtenchng = 1; ++ DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32); ++ hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0); ++ return retval; ++ } ++ ++ if (hprt0.b.prtconndet) { ++ /** @todo - check if steps performed in 'else' block should be perfromed regardles adp */ ++ if (dwc_otg_hcd->core_if->adp_enable && ++ dwc_otg_hcd->core_if->adp.vbuson_timer_started == 1) { ++ DWC_PRINTF("PORT CONNECT DETECTED ----------------\n"); ++ DWC_TIMER_CANCEL(dwc_otg_hcd->core_if->adp.vbuson_timer); ++ dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0; ++ /* TODO - check if this is required, as ++ * host initialization was already performed ++ * after initial ADP probing ++ */ ++ /*dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0; ++ dwc_otg_core_init(dwc_otg_hcd->core_if); ++ dwc_otg_enable_global_interrupts(dwc_otg_hcd->core_if); ++ cil_hcd_start(dwc_otg_hcd->core_if);*/ ++ } else { ++ hprt0_data_t hprt0_local; ++ DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x " ++ "Port Connect Detected--\n", hprt0.d32); ++ dwc_otg_hcd->flags.b.port_connect_status_change = 1; ++ dwc_otg_hcd->flags.b.port_connect_status = 1; ++ hprt0_modify.b.prtconndet = 1; ++ /* PET testing */ ++ if (dwc_otg_hcd->core_if->otg_ver && (dwc_otg_hcd->core_if->test_mode == 7)) { ++ hprt0_local.d32 = dwc_otg_read_hprt0(dwc_otg_hcd->core_if); ++ hprt0_local.b.prtrst = 1; ++ DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_local.d32); ++ dwc_mdelay(60); ++ hprt0.d32 = dwc_otg_read_hprt0(dwc_otg_hcd->core_if); ++ hprt0.b.prtrst = 0; ++ DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0.d32); ++ } ++ ++ /* B-Device has connected, Delete the connection timer. */ ++ DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer); ++ } ++ /* The Hub driver asserts a reset when it sees port connect ++ * status change flag */ ++ retval |= 1; ++ } ++ ++ /* Port Enable Changed ++ * Clear if detected - Set internal flag if disabled */ ++ if (hprt0.b.prtenchng) { ++ DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x " ++ "Port Enable Changed--\n", hprt0.d32); ++ hprt0_modify.b.prtenchng = 1; ++ if (hprt0.b.prtena == 1) { ++ hfir_data_t hfir; ++ int do_reset = 0; ++ dwc_otg_core_params_t *params = ++ dwc_otg_hcd->core_if->core_params; ++ dwc_otg_core_global_regs_t *global_regs = ++ dwc_otg_hcd->core_if->core_global_regs; ++ dwc_otg_host_if_t *host_if = ++ dwc_otg_hcd->core_if->host_if; ++ ++ /* Every time when port enables calculate ++ * HFIR.FrInterval ++ */ ++ hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir); ++ hfir.b.frint = calc_frame_interval(dwc_otg_hcd->core_if); ++ DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32); ++ ++ /* Check if we need to adjust the PHY clock speed for ++ * low power and adjust it */ ++ if (params->host_support_fs_ls_low_power) { ++ gusbcfg_data_t usbcfg; ++ ++ usbcfg.d32 = ++ DWC_READ_REG32(&global_regs->gusbcfg); ++ ++ if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED ++ || hprt0.b.prtspd == ++ DWC_HPRT0_PRTSPD_FULL_SPEED) { ++ /* ++ * Low power ++ */ ++ hcfg_data_t hcfg; ++ if (usbcfg.b.phylpwrclksel == 0) { ++ /* Set PHY low power clock select for FS/LS devices */ ++ usbcfg.b.phylpwrclksel = 1; ++ DWC_WRITE_REG32 ++ (&global_regs->gusbcfg, ++ usbcfg.d32); ++ do_reset = 1; ++ } ++ ++ hcfg.d32 = ++ DWC_READ_REG32 ++ (&host_if->host_global_regs->hcfg); ++ ++ if (hprt0.b.prtspd == ++ DWC_HPRT0_PRTSPD_LOW_SPEED ++ && params->host_ls_low_power_phy_clk ++ == ++ DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ) ++ { ++ /* 6 MHZ */ ++ DWC_DEBUGPL(DBG_CIL, ++ "FS_PHY programming HCFG to 6 MHz (Low Power)\n"); ++ if (hcfg.b.fslspclksel != ++ DWC_HCFG_6_MHZ) { ++ hcfg.b.fslspclksel = ++ DWC_HCFG_6_MHZ; ++ DWC_WRITE_REG32 ++ (&host_if->host_global_regs->hcfg, ++ hcfg.d32); ++ do_reset = 1; ++ } ++ } else { ++ /* 48 MHZ */ ++ DWC_DEBUGPL(DBG_CIL, ++ "FS_PHY programming HCFG to 48 MHz ()\n"); ++ if (hcfg.b.fslspclksel != ++ DWC_HCFG_48_MHZ) { ++ hcfg.b.fslspclksel = ++ DWC_HCFG_48_MHZ; ++ DWC_WRITE_REG32 ++ (&host_if->host_global_regs->hcfg, ++ hcfg.d32); ++ do_reset = 1; ++ } ++ } ++ } else { ++ /* ++ * Not low power ++ */ ++ if (usbcfg.b.phylpwrclksel == 1) { ++ usbcfg.b.phylpwrclksel = 0; ++ DWC_WRITE_REG32 ++ (&global_regs->gusbcfg, ++ usbcfg.d32); ++ do_reset = 1; ++ } ++ } ++ ++ if (do_reset) { ++ DWC_TASK_SCHEDULE(dwc_otg_hcd->reset_tasklet); ++ } ++ } ++ ++ if (!do_reset) { ++ /* Port has been enabled set the reset change flag */ ++ dwc_otg_hcd->flags.b.port_reset_change = 1; ++ } ++ } else { ++ dwc_otg_hcd->flags.b.port_enable_change = 1; ++ } ++ retval |= 1; ++ } ++ ++ /** Overcurrent Change Interrupt */ ++ if (hprt0.b.prtovrcurrchng) { ++ DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x " ++ "Port Overcurrent Changed--\n", hprt0.d32); ++ dwc_otg_hcd->flags.b.port_over_current_change = 1; ++ hprt0_modify.b.prtovrcurrchng = 1; ++ retval |= 1; ++ } ++ ++ /* Clear Port Interrupts */ ++ DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32); ++ ++ return retval; ++} ++ ++/** This interrupt indicates that one or more host channels has a pending ++ * interrupt. There are multiple conditions that can cause each host channel ++ * interrupt. This function determines which conditions have occurred for each ++ * host channel interrupt and handles them appropriately. */ ++int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ int i; ++ int retval = 0; ++ haint_data_t haint; ++ ++ /* Clear appropriate bits in HCINTn to clear the interrupt bit in ++ * GINTSTS */ ++ ++ haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if); ++ ++ for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) { ++ if (haint.b2.chint & (1 << i)) { ++ retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i); ++ } ++ } ++ ++ return retval; ++} ++ ++/** ++ * Gets the actual length of a transfer after the transfer halts. _halt_status ++ * holds the reason for the halt. ++ * ++ * For IN transfers where halt_status is DWC_OTG_HC_XFER_COMPLETE, ++ * *short_read is set to 1 upon return if less than the requested ++ * number of bytes were transferred. Otherwise, *short_read is set to 0 upon ++ * return. short_read may also be NULL on entry, in which case it remains ++ * unchanged. ++ */ ++static uint32_t get_actual_xfer_length(dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_halt_status_e halt_status, ++ int *short_read) ++{ ++ hctsiz_data_t hctsiz; ++ uint32_t length; ++ ++ if (short_read != NULL) { ++ *short_read = 0; ++ } ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ ++ if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { ++ if (hc->ep_is_in) { ++ length = hc->xfer_len - hctsiz.b.xfersize; ++ if (short_read != NULL) { ++ *short_read = (hctsiz.b.xfersize != 0); ++ } ++ } else if (hc->qh->do_split) { ++ length = qtd->ssplit_out_xfer_count; ++ } else { ++ length = hc->xfer_len; ++ } ++ } else { ++ /* ++ * Must use the hctsiz.pktcnt field to determine how much data ++ * has been transferred. This field reflects the number of ++ * packets that have been transferred via the USB. This is ++ * always an integral number of packets if the transfer was ++ * halted before its normal completion. (Can't use the ++ * hctsiz.xfersize field because that reflects the number of ++ * bytes transferred via the AHB, not the USB). ++ */ ++ length = ++ (hc->start_pkt_count - hctsiz.b.pktcnt) * hc->max_packet; ++ } ++ ++ return length; ++} ++ ++/** ++ * Updates the state of the URB after a Transfer Complete interrupt on the ++ * host channel. Updates the actual_length field of the URB based on the ++ * number of bytes transferred via the host channel. Sets the URB status ++ * if the data transfer is finished. ++ * ++ * @return 1 if the data transfer specified by the URB is completely finished, ++ * 0 otherwise. ++ */ ++static int update_urb_state_xfer_comp(dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_hcd_urb_t * urb, ++ dwc_otg_qtd_t * qtd) ++{ ++ int xfer_done = 0; ++ int short_read = 0; ++ ++ int xfer_length; ++ ++ xfer_length = get_actual_xfer_length(hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_COMPLETE, ++ &short_read); ++ ++ ++ /* non DWORD-aligned buffer case handling. */ ++ if (hc->align_buff && xfer_length && hc->ep_is_in) { ++ dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, ++ xfer_length); ++ } ++ ++ urb->actual_length += xfer_length; ++ ++ if (xfer_length && (hc->ep_type == DWC_OTG_EP_TYPE_BULK) && ++ (urb->flags & URB_SEND_ZERO_PACKET) ++ && (urb->actual_length == urb->length) ++ && !(urb->length % hc->max_packet)) { ++ xfer_done = 0; ++ } else if (short_read || urb->actual_length == urb->length) { ++ xfer_done = 1; ++ urb->status = 0; ++ } ++ ++#ifdef DEBUG ++ { ++ hctsiz_data_t hctsiz; ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n", ++ __func__, (hc->ep_is_in ? "IN" : "OUT"), ++ hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " hc->xfer_len %d\n", hc->xfer_len); ++ DWC_DEBUGPL(DBG_HCDV, " hctsiz.xfersize %d\n", ++ hctsiz.b.xfersize); ++ DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n", ++ urb->length); ++ DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n", ++ urb->actual_length); ++ DWC_DEBUGPL(DBG_HCDV, " short_read %d, xfer_done %d\n", ++ short_read, xfer_done); ++ } ++#endif ++ ++ return xfer_done; ++} ++ ++/* ++ * Save the starting data toggle for the next transfer. The data toggle is ++ * saved in the QH for non-control transfers and it's saved in the QTD for ++ * control transfers. ++ */ ++void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, dwc_otg_qtd_t * qtd) ++{ ++ hctsiz_data_t hctsiz; ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ ++ if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) { ++ dwc_otg_qh_t *qh = hc->qh; ++ if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) { ++ qh->data_toggle = DWC_OTG_HC_PID_DATA0; ++ } else { ++ qh->data_toggle = DWC_OTG_HC_PID_DATA1; ++ } ++ } else { ++ if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) { ++ qtd->data_toggle = DWC_OTG_HC_PID_DATA0; ++ } else { ++ qtd->data_toggle = DWC_OTG_HC_PID_DATA1; ++ } ++ } ++} ++ ++/** ++ * Updates the state of an Isochronous URB when the transfer is stopped for ++ * any reason. The fields of the current entry in the frame descriptor array ++ * are set based on the transfer state and the input _halt_status. Completes ++ * the Isochronous URB if all the URB frames have been completed. ++ * ++ * @return DWC_OTG_HC_XFER_COMPLETE if there are more frames remaining to be ++ * transferred in the URB. Otherwise return DWC_OTG_HC_XFER_URB_COMPLETE. ++ */ ++static dwc_otg_halt_status_e ++update_isoc_urb_state(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status) ++{ ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ dwc_otg_halt_status_e ret_val = halt_status; ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc; ++ ++ frame_desc = &urb->iso_descs[qtd->isoc_frame_index]; ++ switch (halt_status) { ++ case DWC_OTG_HC_XFER_COMPLETE: ++ frame_desc->status = 0; ++ frame_desc->actual_length = ++ get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL); ++ ++ /* non DWORD-aligned buffer case handling. */ ++ if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) { ++ dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, ++ hc->qh->dw_align_buf, frame_desc->actual_length); ++ } ++ ++ break; ++ case DWC_OTG_HC_XFER_FRAME_OVERRUN: ++ urb->error_count++; ++ if (hc->ep_is_in) { ++ frame_desc->status = -DWC_E_NO_STREAM_RES; ++ } else { ++ frame_desc->status = -DWC_E_COMMUNICATION; ++ } ++ frame_desc->actual_length = 0; ++ break; ++ case DWC_OTG_HC_XFER_BABBLE_ERR: ++ urb->error_count++; ++ frame_desc->status = -DWC_E_OVERFLOW; ++ /* Don't need to update actual_length in this case. */ ++ break; ++ case DWC_OTG_HC_XFER_XACT_ERR: ++ urb->error_count++; ++ frame_desc->status = -DWC_E_PROTOCOL; ++ frame_desc->actual_length = ++ get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL); ++ ++ /* non DWORD-aligned buffer case handling. */ ++ if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) { ++ dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, ++ hc->qh->dw_align_buf, frame_desc->actual_length); ++ } ++ /* Skip whole frame */ ++ if (hc->qh->do_split && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && ++ hc->ep_is_in && hcd->core_if->dma_enable) { ++ qtd->complete_split = 0; ++ qtd->isoc_split_offset = 0; ++ } ++ ++ break; ++ default: ++ DWC_ASSERT(1, "Unhandled _halt_status (%d)\n", halt_status); ++ break; ++ } ++ if (++qtd->isoc_frame_index == urb->packet_count) { ++ /* ++ * urb->status is not used for isoc transfers. ++ * The individual frame_desc statuses are used instead. ++ */ ++ hcd->fops->complete(hcd, urb->priv, urb, 0); ++ ret_val = DWC_OTG_HC_XFER_URB_COMPLETE; ++ } else { ++ ret_val = DWC_OTG_HC_XFER_COMPLETE; ++ } ++ return ret_val; ++} ++ ++/** ++ * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic ++ * QHs, removes the QH from the active non-periodic schedule. If any QTDs are ++ * still linked to the QH, the QH is added to the end of the inactive ++ * non-periodic schedule. For periodic QHs, removes the QH from the periodic ++ * schedule if no more QTDs are linked to the QH. ++ */ ++static void deactivate_qh(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, int free_qtd) ++{ ++ int continue_split = 0; ++ dwc_otg_qtd_t *qtd; ++ ++ DWC_DEBUGPL(DBG_HCDV, " %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd); ++ ++ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); ++ ++ if (qtd->complete_split) { ++ continue_split = 1; ++ } else if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID || ++ qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END) { ++ continue_split = 1; ++ } ++ ++ if (free_qtd) { ++ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ continue_split = 0; ++ } ++ ++ qh->channel = NULL; ++ dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split); ++} ++ ++/** ++ * Releases a host channel for use by other transfers. Attempts to select and ++ * queue more transactions since at least one host channel is available. ++ * ++ * @param hcd The HCD state structure. ++ * @param hc The host channel to release. ++ * @param qtd The QTD associated with the host channel. This QTD may be freed ++ * if the transfer is complete or an error has occurred. ++ * @param halt_status Reason the channel is being released. This status ++ * determines the actions taken by this function. ++ */ ++static void release_channel(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_halt_status_e halt_status) ++{ ++ dwc_otg_transaction_type_e tr_type; ++ int free_qtd; ++ ++ DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d\n", ++ __func__, hc->hc_num, halt_status); ++ ++ switch (halt_status) { ++ case DWC_OTG_HC_XFER_URB_COMPLETE: ++ free_qtd = 1; ++ break; ++ case DWC_OTG_HC_XFER_AHB_ERR: ++ case DWC_OTG_HC_XFER_STALL: ++ case DWC_OTG_HC_XFER_BABBLE_ERR: ++ free_qtd = 1; ++ break; ++ case DWC_OTG_HC_XFER_XACT_ERR: ++ if (qtd->error_count >= 3) { ++ DWC_DEBUGPL(DBG_HCDV, ++ " Complete URB with transaction error\n"); ++ free_qtd = 1; ++ qtd->urb->status = -DWC_E_PROTOCOL; ++ hcd->fops->complete(hcd, qtd->urb->priv, ++ qtd->urb, -DWC_E_PROTOCOL); ++ } else { ++ free_qtd = 0; ++ } ++ break; ++ case DWC_OTG_HC_XFER_URB_DEQUEUE: ++ /* ++ * The QTD has already been removed and the QH has been ++ * deactivated. Don't want to do anything except release the ++ * host channel and try to queue more transfers. ++ */ ++ goto cleanup; ++ case DWC_OTG_HC_XFER_NO_HALT_STATUS: ++ free_qtd = 0; ++ break; ++ case DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE: ++ DWC_DEBUGPL(DBG_HCDV, ++ " Complete URB with I/O error\n"); ++ free_qtd = 1; ++ qtd->urb->status = -DWC_E_IO; ++ hcd->fops->complete(hcd, qtd->urb->priv, ++ qtd->urb, -DWC_E_IO); ++ break; ++ default: ++ free_qtd = 0; ++ break; ++ } ++ ++ deactivate_qh(hcd, hc->qh, free_qtd); ++ ++cleanup: ++ /* ++ * Release the host channel for use by other transfers. The cleanup ++ * function clears the channel interrupt enables and conditions, so ++ * there's no need to clear the Channel Halted interrupt separately. ++ */ ++ dwc_otg_hc_cleanup(hcd->core_if, hc); ++ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); ++ ++ switch (hc->ep_type) { ++ case DWC_OTG_EP_TYPE_CONTROL: ++ case DWC_OTG_EP_TYPE_BULK: ++ hcd->non_periodic_channels--; ++ break; ++ ++ default: ++ /* ++ * Don't release reservations for periodic channels here. ++ * That's done when a periodic transfer is descheduled (i.e. ++ * when the QH is removed from the periodic schedule). ++ */ ++ break; ++ } ++ ++ /* Try to queue more transfers now that there's a free channel. */ ++ tr_type = dwc_otg_hcd_select_transactions(hcd); ++ if (tr_type != DWC_OTG_TRANSACTION_NONE) { ++ dwc_otg_hcd_queue_transactions(hcd, tr_type); ++ } ++} ++ ++/** ++ * Halts a host channel. If the channel cannot be halted immediately because ++ * the request queue is full, this function ensures that the FIFO empty ++ * interrupt for the appropriate queue is enabled so that the halt request can ++ * be queued when there is space in the request queue. ++ * ++ * This function may also be called in DMA mode. In that case, the channel is ++ * simply released since the core always halts the channel automatically in ++ * DMA mode. ++ */ ++static void halt_channel(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status) ++{ ++ if (hcd->core_if->dma_enable) { ++ release_channel(hcd, hc, qtd, halt_status); ++ return; ++ } ++ ++ /* Slave mode processing... */ ++ dwc_otg_hc_halt(hcd->core_if, hc, halt_status); ++ ++ if (hc->halt_on_queue) { ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ dwc_otg_core_global_regs_t *global_regs; ++ global_regs = hcd->core_if->core_global_regs; ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || ++ hc->ep_type == DWC_OTG_EP_TYPE_BULK) { ++ /* ++ * Make sure the Non-periodic Tx FIFO empty interrupt ++ * is enabled so that the non-periodic schedule will ++ * be processed. ++ */ ++ gintmsk.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); ++ } else { ++ /* ++ * Move the QH from the periodic queued schedule to ++ * the periodic assigned schedule. This allows the ++ * halt to be queued when the periodic schedule is ++ * processed. ++ */ ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, ++ &hc->qh->qh_list_entry); ++ ++ /* ++ * Make sure the Periodic Tx FIFO Empty interrupt is ++ * enabled so that the periodic schedule will be ++ * processed. ++ */ ++ gintmsk.b.ptxfempty = 1; ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); ++ } ++ } ++} ++ ++/** ++ * Performs common cleanup for non-periodic transfers after a Transfer ++ * Complete interrupt. This function should be called after any endpoint type ++ * specific handling is finished to release the host channel. ++ */ ++static void complete_non_periodic_xfer(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_halt_status_e halt_status) ++{ ++ hcint_data_t hcint; ++ ++ qtd->error_count = 0; ++ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ if (hcint.b.nyet) { ++ /* ++ * Got a NYET on the last transaction of the transfer. This ++ * means that the endpoint should be in the PING state at the ++ * beginning of the next transfer. ++ */ ++ hc->qh->ping_state = 1; ++ clear_hc_int(hc_regs, nyet); ++ } ++ ++ /* ++ * Always halt and release the host channel to make it available for ++ * more transfers. There may still be more phases for a control ++ * transfer or more data packets for a bulk transfer at this point, ++ * but the host channel is still halted. A channel will be reassigned ++ * to the transfer when the non-periodic schedule is processed after ++ * the channel is released. This allows transactions to be queued ++ * properly via dwc_otg_hcd_queue_transactions, which also enables the ++ * Tx FIFO Empty interrupt if necessary. ++ */ ++ if (hc->ep_is_in) { ++ /* ++ * IN transfers in Slave mode require an explicit disable to ++ * halt the channel. (In DMA mode, this call simply releases ++ * the channel.) ++ */ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } else { ++ /* ++ * The channel is automatically disabled by the core for OUT ++ * transfers in Slave mode. ++ */ ++ release_channel(hcd, hc, qtd, halt_status); ++ } ++} ++ ++/** ++ * Performs common cleanup for periodic transfers after a Transfer Complete ++ * interrupt. This function should be called after any endpoint type specific ++ * handling is finished to release the host channel. ++ */ ++static void complete_periodic_xfer(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_halt_status_e halt_status) ++{ ++ hctsiz_data_t hctsiz; ++ qtd->error_count = 0; ++ ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) { ++ /* Core halts channel in these cases. */ ++ release_channel(hcd, hc, qtd, halt_status); ++ } else { ++ /* Flush any outstanding requests from the Tx queue. */ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++} ++ ++static int32_t handle_xfercomp_isoc_split_in(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ uint32_t len; ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc; ++ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; ++ ++ len = get_actual_xfer_length(hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_COMPLETE, NULL); ++ ++ if (!len) { ++ qtd->complete_split = 0; ++ qtd->isoc_split_offset = 0; ++ return 0; ++ } ++ frame_desc->actual_length += len; ++ ++ if (hc->align_buff && len) ++ dwc_memcpy(qtd->urb->buf + frame_desc->offset + ++ qtd->isoc_split_offset, hc->qh->dw_align_buf, len); ++ qtd->isoc_split_offset += len; ++ ++ if (frame_desc->length == frame_desc->actual_length) { ++ frame_desc->status = 0; ++ qtd->isoc_frame_index++; ++ qtd->complete_split = 0; ++ qtd->isoc_split_offset = 0; ++ } ++ ++ if (qtd->isoc_frame_index == qtd->urb->packet_count) { ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); ++ } else { ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS); ++ } ++ ++ return 1; /* Indicates that channel released */ ++} ++ ++/** ++ * Handles a host channel Transfer Complete interrupt. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ int urb_xfer_done; ++ dwc_otg_halt_status_e halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info); ++ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Transfer Complete--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_desc_enable) { ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, halt_status); ++ if (pipe_type == UE_ISOCHRONOUS) { ++ /* Do not disable the interrupt, just clear it */ ++ clear_hc_int(hc_regs, xfercomp); ++ return 1; ++ } ++ goto handle_xfercomp_done; ++ } ++ ++ /* ++ * Handle xfer complete on CSPLIT. ++ */ ++ ++ if (hc->qh->do_split) { ++ if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hc->ep_is_in ++ && hcd->core_if->dma_enable) { ++ if (qtd->complete_split ++ && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs, ++ qtd)) ++ goto handle_xfercomp_done; ++ } else { ++ qtd->complete_split = 0; ++ } ++ } ++ ++ /* Update the QTD and URB states. */ ++ switch (pipe_type) { ++ case UE_CONTROL: ++ switch (qtd->control_phase) { ++ case DWC_OTG_CONTROL_SETUP: ++ if (urb->length > 0) { ++ qtd->control_phase = DWC_OTG_CONTROL_DATA; ++ } else { ++ qtd->control_phase = DWC_OTG_CONTROL_STATUS; ++ } ++ DWC_DEBUGPL(DBG_HCDV, ++ " Control setup transaction done\n"); ++ halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ break; ++ case DWC_OTG_CONTROL_DATA:{ ++ urb_xfer_done = ++ update_urb_state_xfer_comp(hc, hc_regs, urb, ++ qtd); ++ if (urb_xfer_done) { ++ qtd->control_phase = ++ DWC_OTG_CONTROL_STATUS; ++ DWC_DEBUGPL(DBG_HCDV, ++ " Control data transfer done\n"); ++ } else { ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ } ++ halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ break; ++ } ++ case DWC_OTG_CONTROL_STATUS: ++ DWC_DEBUGPL(DBG_HCDV, " Control transfer complete\n"); ++ if (urb->status == -DWC_E_IN_PROGRESS) { ++ urb->status = 0; ++ } ++ hcd->fops->complete(hcd, urb->priv, urb, urb->status); ++ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; ++ if (!hcd->core_if->dma_enable && hcd->core_if->otg_ver == 1) ++ qtd->urb = NULL; ++ break; ++ } ++ ++ complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); ++ break; ++ case UE_BULK: ++ DWC_DEBUGPL(DBG_HCDV, " Bulk transfer complete\n"); ++ urb_xfer_done = ++ update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); ++ if (urb_xfer_done) { ++ hcd->fops->complete(hcd, urb->priv, urb, urb->status); ++ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; ++ } else { ++ halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ } ++ ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); ++ break; ++ case UE_INTERRUPT: ++ DWC_DEBUGPL(DBG_HCDV, " Interrupt transfer complete\n"); ++ urb_xfer_done = ++ update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); ++ ++ /* ++ * Interrupt URB is done on the first transfer complete ++ * interrupt. ++ */ ++ if (urb_xfer_done) { ++ hcd->fops->complete(hcd, urb->priv, urb, urb->status); ++ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; ++ } else { ++ halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ } ++ ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); ++ break; ++ case UE_ISOCHRONOUS: ++ DWC_DEBUGPL(DBG_HCDV, " Isochronous transfer complete\n"); ++ if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) { ++ halt_status = ++ update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_COMPLETE); ++ } ++ complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); ++ break; ++ } ++ ++handle_xfercomp_done: ++ disable_hc_int(hc_regs, xfercompl); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel STALL interrupt. This handler may be called in ++ * either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_stall_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info); ++ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "STALL Received--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_desc_enable) { ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_STALL); ++ goto handle_stall_done; ++ } ++ ++ if (pipe_type == UE_CONTROL) { ++ hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE); ++ } ++ ++ if (pipe_type == UE_BULK || pipe_type == UE_INTERRUPT) { ++ hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE); ++ /* ++ * USB protocol requires resetting the data toggle for bulk ++ * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT) ++ * setup command is issued to the endpoint. Anticipate the ++ * CLEAR_FEATURE command since a STALL has occurred and reset ++ * the data toggle now. ++ */ ++ hc->qh->data_toggle = 0; ++ } ++ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL); ++ ++handle_stall_done: ++ disable_hc_int(hc_regs, stall); ++ ++ return 1; ++} ++ ++/* ++ * Updates the state of the URB when a transfer has been stopped due to an ++ * abnormal condition before the transfer completes. Modifies the ++ * actual_length field of the URB to reflect the number of bytes that have ++ * actually been transferred via the host channel. ++ */ ++static void update_urb_state_xfer_intr(dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_hcd_urb_t * urb, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_halt_status_e halt_status) ++{ ++ uint32_t bytes_transferred = get_actual_xfer_length(hc, hc_regs, qtd, ++ halt_status, NULL); ++ /* non DWORD-aligned buffer case handling. */ ++ if (hc->align_buff && bytes_transferred && hc->ep_is_in) { ++ dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, ++ bytes_transferred); ++ } ++ ++ urb->actual_length += bytes_transferred; ++ ++#ifdef DEBUG ++ { ++ hctsiz_data_t hctsiz; ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n", ++ __func__, (hc->ep_is_in ? "IN" : "OUT"), ++ hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " hc->start_pkt_count %d\n", ++ hc->start_pkt_count); ++ DWC_DEBUGPL(DBG_HCDV, " hctsiz.pktcnt %d\n", hctsiz.b.pktcnt); ++ DWC_DEBUGPL(DBG_HCDV, " hc->max_packet %d\n", hc->max_packet); ++ DWC_DEBUGPL(DBG_HCDV, " bytes_transferred %d\n", ++ bytes_transferred); ++ DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n", ++ urb->actual_length); ++ DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n", ++ urb->length); ++ } ++#endif ++} ++ ++/** ++ * Handles a host channel NAK interrupt. This handler may be called in either ++ * DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "NAK Received--\n", hc->hc_num); ++ ++ /* ++ * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and ++ * interrupt. Re-start the SSPLIT transfer. ++ */ ++ if (hc->do_split) { ++ if (hc->complete_split) { ++ qtd->error_count = 0; ++ } ++ qtd->complete_split = 0; ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); ++ goto handle_nak_done; ++ } ++ ++ switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { ++ case UE_CONTROL: ++ case UE_BULK: ++ if (hcd->core_if->dma_enable && hc->ep_is_in) { ++ /* ++ * NAK interrupts are enabled on bulk/control IN ++ * transfers in DMA mode for the sole purpose of ++ * resetting the error count after a transaction error ++ * occurs. The core will continue transferring data. ++ */ ++ qtd->error_count = 0; ++ goto handle_nak_done; ++ } ++ ++ /* ++ * NAK interrupts normally occur during OUT transfers in DMA ++ * or Slave mode. For IN transfers, more requests will be ++ * queued as request queue space is available. ++ */ ++ qtd->error_count = 0; ++ ++ if (!hc->qh->ping_state) { ++ update_urb_state_xfer_intr(hc, hc_regs, ++ qtd->urb, qtd, ++ DWC_OTG_HC_XFER_NAK); ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ ++ if (hc->speed == DWC_OTG_EP_SPEED_HIGH) ++ hc->qh->ping_state = 1; ++ } ++ ++ /* ++ * Halt the channel so the transfer can be re-started from ++ * the appropriate point or the PING protocol will ++ * start/continue. ++ */ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); ++ break; ++ case UE_INTERRUPT: ++ qtd->error_count = 0; ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); ++ break; ++ case UE_ISOCHRONOUS: ++ /* Should never get called for isochronous transfers. */ ++ DWC_ASSERT(1, "NACK interrupt for ISOC transfer\n"); ++ break; ++ } ++ ++handle_nak_done: ++ disable_hc_int(hc_regs, nak); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel ACK interrupt. This interrupt is enabled when ++ * performing the PING protocol in Slave mode, when errors occur during ++ * either Slave mode or DMA mode, and during Start Split transactions. ++ */ ++static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "ACK Received--\n", hc->hc_num); ++ ++ if (hc->do_split) { ++ /* ++ * Handle ACK on SSPLIT. ++ * ACK should not occur in CSPLIT. ++ */ ++ if (!hc->ep_is_in && hc->data_pid_start != DWC_OTG_HC_PID_SETUP) { ++ qtd->ssplit_out_xfer_count = hc->xfer_len; ++ } ++ if (!(hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)) { ++ /* Don't need complete for isochronous out transfers. */ ++ qtd->complete_split = 1; ++ } ++ ++ /* ISOC OUT */ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) { ++ switch (hc->xact_pos) { ++ case DWC_HCSPLIT_XACTPOS_ALL: ++ break; ++ case DWC_HCSPLIT_XACTPOS_END: ++ qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL; ++ qtd->isoc_split_offset = 0; ++ break; ++ case DWC_HCSPLIT_XACTPOS_BEGIN: ++ case DWC_HCSPLIT_XACTPOS_MID: ++ /* ++ * For BEGIN or MID, calculate the length for ++ * the next microframe to determine the correct ++ * SSPLIT token, either MID or END. ++ */ ++ { ++ struct dwc_otg_hcd_iso_packet_desc ++ *frame_desc; ++ ++ frame_desc = ++ &qtd->urb-> ++ iso_descs[qtd->isoc_frame_index]; ++ qtd->isoc_split_offset += 188; ++ ++ if ((frame_desc->length - ++ qtd->isoc_split_offset) <= 188) { ++ qtd->isoc_split_pos = ++ DWC_HCSPLIT_XACTPOS_END; ++ } else { ++ qtd->isoc_split_pos = ++ DWC_HCSPLIT_XACTPOS_MID; ++ } ++ ++ } ++ break; ++ } ++ } else { ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK); ++ } ++ } else { ++ qtd->error_count = 0; ++ ++ if (hc->qh->ping_state) { ++ hc->qh->ping_state = 0; ++ /* ++ * Halt the channel so the transfer can be re-started ++ * from the appropriate point. This only happens in ++ * Slave mode. In DMA mode, the ping_state is cleared ++ * when the transfer is started because the core ++ * automatically executes the PING, then the transfer. ++ */ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK); ++ } ++ } ++ ++ /* ++ * If the ACK occurred when _not_ in the PING state, let the channel ++ * continue transferring data after clearing the error count. ++ */ ++ ++ disable_hc_int(hc_regs, ack); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel NYET interrupt. This interrupt should only occur on ++ * Bulk and Control OUT endpoints and for complete split transactions. If a ++ * NYET occurs at the same time as a Transfer Complete interrupt, it is ++ * handled in the xfercomp interrupt handler, not here. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "NYET Received--\n", hc->hc_num); ++ ++ /* ++ * NYET on CSPLIT ++ * re-do the CSPLIT immediately on non-periodic ++ */ ++ if (hc->do_split && hc->complete_split) { ++ if (hc->ep_is_in && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) ++ && hcd->core_if->dma_enable) { ++ qtd->complete_split = 0; ++ qtd->isoc_split_offset = 0; ++ if (++qtd->isoc_frame_index == qtd->urb->packet_count) { ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); ++ } ++ else ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS); ++ goto handle_nyet_done; ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ int frnum = dwc_otg_hcd_get_frame_number(hcd); ++ ++ if (dwc_full_frame_num(frnum) != ++ dwc_full_frame_num(hc->qh->sched_frame)) { ++ /* ++ * No longer in the same full speed frame. ++ * Treat this as a transaction error. ++ */ ++#if 0 ++ /** @todo Fix system performance so this can ++ * be treated as an error. Right now complete ++ * splits cannot be scheduled precisely enough ++ * due to other system activity, so this error ++ * occurs regularly in Slave mode. ++ */ ++ qtd->error_count++; ++#endif ++ qtd->complete_split = 0; ++ halt_channel(hcd, hc, qtd, ++ DWC_OTG_HC_XFER_XACT_ERR); ++ /** @todo add support for isoc release */ ++ goto handle_nyet_done; ++ } ++ } ++ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET); ++ goto handle_nyet_done; ++ } ++ ++ hc->qh->ping_state = 1; ++ qtd->error_count = 0; ++ ++ update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd, ++ DWC_OTG_HC_XFER_NYET); ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ ++ /* ++ * Halt the channel and re-start the transfer so the PING ++ * protocol will start. ++ */ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET); ++ ++handle_nyet_done: ++ disable_hc_int(hc_regs, nyet); ++ return 1; ++} ++ ++/** ++ * Handles a host channel babble interrupt. This handler may be called in ++ * either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_babble_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Babble Error--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_desc_enable) { ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ DWC_OTG_HC_XFER_BABBLE_ERR); ++ goto handle_babble_done; ++ } ++ ++ if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { ++ hcd->fops->complete(hcd, qtd->urb->priv, ++ qtd->urb, -DWC_E_OVERFLOW); ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_BABBLE_ERR); ++ } else { ++ dwc_otg_halt_status_e halt_status; ++ halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_BABBLE_ERR); ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++ ++handle_babble_done: ++ disable_hc_int(hc_regs, bblerr); ++ return 1; ++} ++ ++/** ++ * Handles a host channel AHB error interrupt. This handler is only called in ++ * DMA mode. ++ */ ++static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ hcchar_data_t hcchar; ++ hcsplt_data_t hcsplt; ++ hctsiz_data_t hctsiz; ++ uint32_t hcdma; ++ char *pipetype, *speed; ++ ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "AHB Error--\n", hc->hc_num); ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt); ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ hcdma = DWC_READ_REG32(&hc_regs->hcdma); ++ ++ DWC_ERROR("AHB ERROR, Channel %d\n", hc->hc_num); ++ DWC_ERROR(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32); ++ DWC_ERROR(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma); ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Enqueue\n"); ++ DWC_ERROR(" Device address: %d\n", ++ dwc_otg_hcd_get_dev_addr(&urb->pipe_info)); ++ DWC_ERROR(" Endpoint: %d, %s\n", ++ dwc_otg_hcd_get_ep_num(&urb->pipe_info), ++ (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT")); ++ ++ switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) { ++ case UE_CONTROL: ++ pipetype = "CONTROL"; ++ break; ++ case UE_BULK: ++ pipetype = "BULK"; ++ break; ++ case UE_INTERRUPT: ++ pipetype = "INTERRUPT"; ++ break; ++ case UE_ISOCHRONOUS: ++ pipetype = "ISOCHRONOUS"; ++ break; ++ default: ++ pipetype = "UNKNOWN"; ++ break; ++ } ++ ++ DWC_ERROR(" Endpoint type: %s\n", pipetype); ++ ++ switch (hc->speed) { ++ case DWC_OTG_EP_SPEED_HIGH: ++ speed = "HIGH"; ++ break; ++ case DWC_OTG_EP_SPEED_FULL: ++ speed = "FULL"; ++ break; ++ case DWC_OTG_EP_SPEED_LOW: ++ speed = "LOW"; ++ break; ++ default: ++ speed = "UNKNOWN"; ++ break; ++ }; ++ ++ DWC_ERROR(" Speed: %s\n", speed); ++ ++ DWC_ERROR(" Max packet size: %d\n", ++ dwc_otg_hcd_get_mps(&urb->pipe_info)); ++ DWC_ERROR(" Data buffer length: %d\n", urb->length); ++ DWC_ERROR(" Transfer buffer: %p, Transfer DMA: %p\n", ++ urb->buf, (void *)urb->dma); ++ DWC_ERROR(" Setup buffer: %p, Setup DMA: %p\n", ++ urb->setup_packet, (void *)urb->setup_dma); ++ DWC_ERROR(" Interval: %d\n", urb->interval); ++ ++ /* Core haltes the channel for Descriptor DMA mode */ ++ if (hcd->core_if->dma_desc_enable) { ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ DWC_OTG_HC_XFER_AHB_ERR); ++ goto handle_ahberr_done; ++ } ++ ++ hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_IO); ++ ++ /* ++ * Force a channel halt. Don't call halt_channel because that won't ++ * write to the HCCHARn register in DMA mode to force the halt. ++ */ ++ dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR); ++handle_ahberr_done: ++ disable_hc_int(hc_regs, ahberr); ++ return 1; ++} ++ ++/** ++ * Handles a host channel transaction error interrupt. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_xacterr_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Transaction Error--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_desc_enable) { ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ DWC_OTG_HC_XFER_XACT_ERR); ++ goto handle_xacterr_done; ++ } ++ ++ switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { ++ case UE_CONTROL: ++ case UE_BULK: ++ qtd->error_count++; ++ if (!hc->qh->ping_state) { ++ ++ update_urb_state_xfer_intr(hc, hc_regs, ++ qtd->urb, qtd, ++ DWC_OTG_HC_XFER_XACT_ERR); ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ if (!hc->ep_is_in && hc->speed == DWC_OTG_EP_SPEED_HIGH) { ++ hc->qh->ping_state = 1; ++ } ++ } ++ ++ /* ++ * Halt the channel so the transfer can be re-started from ++ * the appropriate point or the PING protocol will start. ++ */ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR); ++ break; ++ case UE_INTERRUPT: ++ qtd->error_count++; ++ if (hc->do_split && hc->complete_split) { ++ qtd->complete_split = 0; ++ } ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR); ++ break; ++ case UE_ISOCHRONOUS: ++ { ++ dwc_otg_halt_status_e halt_status; ++ halt_status = ++ update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_XACT_ERR); ++ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++ break; ++ } ++handle_xacterr_done: ++ disable_hc_int(hc_regs, xacterr); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel frame overrun interrupt. This handler may be called ++ * in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_frmovrun_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Frame Overrun--\n", hc->hc_num); ++ ++ switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { ++ case UE_CONTROL: ++ case UE_BULK: ++ break; ++ case UE_INTERRUPT: ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN); ++ break; ++ case UE_ISOCHRONOUS: ++ { ++ dwc_otg_halt_status_e halt_status; ++ halt_status = ++ update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_FRAME_OVERRUN); ++ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++ break; ++ } ++ ++ disable_hc_int(hc_regs, frmovrun); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel data toggle error interrupt. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Data Toggle Error--\n", hc->hc_num); ++ ++ if (hc->ep_is_in) { ++ qtd->error_count = 0; ++ } else { ++ DWC_ERROR("Data Toggle Error on OUT transfer," ++ "channel %d\n", hc->hc_num); ++ } ++ ++ disable_hc_int(hc_regs, datatglerr); ++ ++ return 1; ++} ++ ++#ifdef DEBUG ++/** ++ * This function is for debug only. It checks that a valid halt status is set ++ * and that HCCHARn.chdis is clear. If there's a problem, corrective action is ++ * taken and a warning is issued. ++ * @return 1 if halt status is ok, 0 otherwise. ++ */ ++static inline int halt_status_ok(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; ++ hcsplt_data_t hcsplt; ++ ++ if (hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS) { ++ /* ++ * This code is here only as a check. This condition should ++ * never happen. Ignore the halt if it does occur. ++ */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); ++ hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt); ++ DWC_WARN ++ ("%s: hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS, " ++ "channel %d, hcchar 0x%08x, hctsiz 0x%08x, " ++ "hcint 0x%08x, hcintmsk 0x%08x, " ++ "hcsplt 0x%08x, qtd->complete_split %d\n", __func__, ++ hc->hc_num, hcchar.d32, hctsiz.d32, hcint.d32, ++ hcintmsk.d32, hcsplt.d32, qtd->complete_split); ++ ++ DWC_WARN("%s: no halt status, channel %d, ignoring interrupt\n", ++ __func__, hc->hc_num); ++ DWC_WARN("\n"); ++ clear_hc_int(hc_regs, chhltd); ++ return 0; ++ } ++ ++ /* ++ * This code is here only as a check. hcchar.chdis should ++ * never be set when the halt interrupt occurs. Halt the ++ * channel again if it does occur. ++ */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chdis) { ++ DWC_WARN("%s: hcchar.chdis set unexpectedly, " ++ "hcchar 0x%08x, trying to halt again\n", ++ __func__, hcchar.d32); ++ clear_hc_int(hc_regs, chhltd); ++ hc->halt_pending = 0; ++ halt_channel(hcd, hc, qtd, hc->halt_status); ++ return 0; ++ } ++ ++ return 1; ++} ++#endif ++ ++/** ++ * Handles a host Channel Halted interrupt in DMA mode. This handler ++ * determines the reason the channel halted and proceeds accordingly. ++ */ ++static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; ++ int out_nak_enh = 0; ++ ++ /* For core with OUT NAK enhancement, the flow for high- ++ * speed CONTROL/BULK OUT is handled a little differently. ++ */ ++ if (hcd->core_if->snpsid >= OTG_CORE_REV_2_71a) { ++ if (hc->speed == DWC_OTG_EP_SPEED_HIGH && !hc->ep_is_in && ++ (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || ++ hc->ep_type == DWC_OTG_EP_TYPE_BULK)) { ++ out_nak_enh = 1; ++ } ++ } ++ ++ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE || ++ (hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR ++ && !hcd->core_if->dma_desc_enable)) { ++ /* ++ * Just release the channel. A dequeue can happen on a ++ * transfer timeout. In the case of an AHB Error, the channel ++ * was forced to halt because there's no way to gracefully ++ * recover. ++ */ ++ if (hcd->core_if->dma_desc_enable) ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ hc->halt_status); ++ else ++ release_channel(hcd, hc, qtd, hc->halt_status); ++ return; ++ } ++ ++ /* Read the HCINTn register to determine the cause for the halt. */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); ++ ++ if (hcint.b.xfercomp) { ++ /** @todo This is here because of a possible hardware bug. Spec ++ * says that on SPLIT-ISOC OUT transfers in DMA mode that a HALT ++ * interrupt w/ACK bit set should occur, but I only see the ++ * XFERCOMP bit, even with it masked out. This is a workaround ++ * for that behavior. Should fix this when hardware is fixed. ++ */ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) { ++ handle_hc_ack_intr(hcd, hc, hc_regs, qtd); ++ } ++ handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.stall) { ++ handle_hc_stall_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.xacterr && !hcd->core_if->dma_desc_enable) { ++ if (out_nak_enh) { ++ if (hcint.b.nyet || hcint.b.nak || hcint.b.ack) { ++ DWC_DEBUG("XactErr with NYET/NAK/ACK\n"); ++ qtd->error_count = 0; ++ } else { ++ DWC_DEBUG("XactErr without NYET/NAK/ACK\n"); ++ } ++ } ++ ++ /* ++ * Must handle xacterr before nak or ack. Could get a xacterr ++ * at the same time as either of these on a BULK/CONTROL OUT ++ * that started with a PING. The xacterr takes precedence. ++ */ ++ handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.xcs_xact && hcd->core_if->dma_desc_enable) { ++ handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) { ++ handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.bblerr) { ++ handle_hc_babble_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.frmovrun) { ++ handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd); ++ } else if (!out_nak_enh) { ++ if (hcint.b.nyet) { ++ /* ++ * Must handle nyet before nak or ack. Could get a nyet at the ++ * same time as either of those on a BULK/CONTROL OUT that ++ * started with a PING. The nyet takes precedence. ++ */ ++ handle_hc_nyet_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.nak && !hcintmsk.b.nak) { ++ /* ++ * If nak is not masked, it's because a non-split IN transfer ++ * is in an error state. In that case, the nak is handled by ++ * the nak interrupt handler, not here. Handle nak here for ++ * BULK/CONTROL OUT transfers, which halt on a NAK to allow ++ * rewinding the buffer pointer. ++ */ ++ handle_hc_nak_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.ack && !hcintmsk.b.ack) { ++ /* ++ * If ack is not masked, it's because a non-split IN transfer ++ * is in an error state. In that case, the ack is handled by ++ * the ack interrupt handler, not here. Handle ack here for ++ * split transfers. Start splits halt on ACK. ++ */ ++ handle_hc_ack_intr(hcd, hc, hc_regs, qtd); ++ } else { ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * A periodic transfer halted with no other channel ++ * interrupts set. Assume it was halted by the core ++ * because it could not be completed in its scheduled ++ * (micro)frame. ++ */ ++#ifdef DEBUG ++ DWC_PRINTF ++ ("%s: Halt channel %d (assume incomplete periodic transfer)\n", ++ __func__, hc->hc_num); ++#endif ++ halt_channel(hcd, hc, qtd, ++ DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE); ++ } else { ++ DWC_ERROR ++ ("%s: Channel %d, DMA Mode -- ChHltd set, but reason " ++ "for halting is unknown, hcint 0x%08x, intsts 0x%08x\n", ++ __func__, hc->hc_num, hcint.d32, ++ DWC_READ_REG32(&hcd-> ++ core_if->core_global_regs-> ++ gintsts)); ++ disable_hc_int(hc_regs, chhltd); ++ } ++ ++ } ++ } else { ++ DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n", ++ hcint.d32); ++ disable_hc_int(hc_regs, chhltd); ++ } ++} ++ ++/** ++ * Handles a host channel Channel Halted interrupt. ++ * ++ * In slave mode, this handler is called only when the driver specifically ++ * requests a halt. This occurs during handling other host channel interrupts ++ * (e.g. nak, xacterr, stall, nyet, etc.). ++ * ++ * In DMA mode, this is the interrupt that occurs when the core has finished ++ * processing a transfer on a channel. Other host channel interrupts (except ++ * ahberr) are disabled in DMA mode. ++ */ ++static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Channel Halted--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_enable) { ++ handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd); ++ } else { ++#ifdef DEBUG ++ if (!halt_status_ok(hcd, hc, hc_regs, qtd)) { ++ return 1; ++ } ++#endif ++ release_channel(hcd, hc, qtd, hc->halt_status); ++ } ++ ++ return 1; ++} ++ ++/** Handles interrupt for a specific Host Channel */ ++int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num) ++{ ++ int retval = 0; ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; ++ dwc_hc_t *hc; ++ dwc_otg_hc_regs_t *hc_regs; ++ dwc_otg_qtd_t *qtd; ++ ++ DWC_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", num); ++ ++ hc = dwc_otg_hcd->hc_ptr_array[num]; ++ hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num]; ++ qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list); ++ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); ++ DWC_DEBUGPL(DBG_HCDV, ++ " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n", ++ hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32)); ++ hcint.d32 = hcint.d32 & hcintmsk.d32; ++ ++ if (!dwc_otg_hcd->core_if->dma_enable) { ++ if (hcint.b.chhltd && hcint.d32 != 0x2) { ++ hcint.b.chhltd = 0; ++ } ++ } ++ ++ if (hcint.b.xfercomp) { ++ retval |= ++ handle_hc_xfercomp_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ /* ++ * If NYET occurred at same time as Xfer Complete, the NYET is ++ * handled by the Xfer Complete interrupt handler. Don't want ++ * to call the NYET interrupt handler in this case. ++ */ ++ hcint.b.nyet = 0; ++ } ++ if (hcint.b.chhltd) { ++ retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.ahberr) { ++ retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.stall) { ++ retval |= handle_hc_stall_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.nak) { ++ retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.ack) { ++ retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.nyet) { ++ retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.xacterr) { ++ retval |= handle_hc_xacterr_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.bblerr) { ++ retval |= handle_hc_babble_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.frmovrun) { ++ retval |= ++ handle_hc_frmovrun_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.datatglerr) { ++ retval |= ++ handle_hc_datatglerr_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ ++ return retval; ++} ++ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_linux.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_linux.c +new file mode 100644 +index 0000000..7323ef3 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_linux.c +@@ -0,0 +1,840 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $ ++ * $Revision: #23 $ ++ * $Date: 2013/04/22 $ ++ * $Change: 2211149 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_DEVICE_ONLY ++ ++/** ++ * @file ++ * ++ * This file contains the implementation of the HCD. In Linux, the HCD ++ * implements the hc_driver API. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ++#include <../drivers/usb/core/hcd.h> ++#else ++#include ++#endif ++ ++#include "dwc_otg_hcd_if.h" ++#include "dwc_otg_dbg.h" ++#include "dwc_otg_driver.h" ++#include "dwc_otg_hcd.h" ++/** ++ * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is ++ * qualified with its direction (possible 32 endpoints per device). ++ */ ++#define dwc_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \ ++ ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4) ++ ++static const char dwc_otg_hcd_name[] = "dwc_otg_hcd"; ++ ++/** @name Linux HC Driver API Functions */ ++/** @{ */ ++static int urb_enqueue(struct usb_hcd *hcd, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ struct usb_host_endpoint *ep, ++#endif ++ struct urb *urb, gfp_t mem_flags); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb); ++#else ++static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status); ++#endif ++ ++static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep); ++#endif ++static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd); ++extern int hcd_start(struct usb_hcd *hcd); ++extern void hcd_stop(struct usb_hcd *hcd); ++static int get_frame_number(struct usb_hcd *hcd); ++extern int hub_status_data(struct usb_hcd *hcd, char *buf); ++extern int hub_control(struct usb_hcd *hcd, ++ u16 typeReq, ++ u16 wValue, u16 wIndex, char *buf, u16 wLength); ++ ++struct wrapper_priv_data { ++ dwc_otg_hcd_t *dwc_otg_hcd; ++}; ++ ++/** @} */ ++ ++static struct hc_driver dwc_otg_hc_driver = { ++ ++ .description = dwc_otg_hcd_name, ++ .product_desc = "DWC OTG Controller", ++ .hcd_priv_size = sizeof(struct wrapper_priv_data), ++ ++ .irq = dwc_otg_hcd_irq, ++ ++ .flags = HCD_MEMORY | HCD_USB2, ++ ++ //.reset = ++ .start = hcd_start, ++ //.suspend = ++ //.resume = ++ .stop = hcd_stop, ++ ++ .urb_enqueue = urb_enqueue, ++ .urb_dequeue = urb_dequeue, ++ .endpoint_disable = endpoint_disable, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++ .endpoint_reset = endpoint_reset, ++#endif ++ .get_frame_number = get_frame_number, ++ ++ .hub_status_data = hub_status_data, ++ .hub_control = hub_control, ++ //.bus_suspend = ++ //.bus_resume = ++}; ++ ++/** Gets the dwc_otg_hcd from a struct usb_hcd */ ++static inline dwc_otg_hcd_t *hcd_to_dwc_otg_hcd(struct usb_hcd *hcd) ++{ ++ struct wrapper_priv_data *p; ++ p = (struct wrapper_priv_data *)(hcd->hcd_priv); ++ return p->dwc_otg_hcd; ++} ++ ++/** Gets the struct usb_hcd that contains a dwc_otg_hcd_t. */ ++static inline struct usb_hcd *dwc_otg_hcd_to_hcd(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ return dwc_otg_hcd_get_priv_data(dwc_otg_hcd); ++} ++ ++/** Gets the usb_host_endpoint associated with an URB. */ ++inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb) ++{ ++ struct usb_device *dev = urb->dev; ++ int ep_num = usb_pipeendpoint(urb->pipe); ++ ++ if (usb_pipein(urb->pipe)) ++ return dev->ep_in[ep_num]; ++ else ++ return dev->ep_out[ep_num]; ++} ++ ++static int _disconnect(dwc_otg_hcd_t * hcd) ++{ ++ struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd); ++ ++ usb_hcd->self.is_b_host = 0; ++ return 0; ++} ++ ++static int _start(dwc_otg_hcd_t * hcd) ++{ ++ struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd); ++ ++ usb_hcd->self.is_b_host = dwc_otg_hcd_is_b_host(hcd); ++ hcd_start(usb_hcd); ++ ++ return 0; ++} ++ ++static int _hub_info(dwc_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr, ++ uint32_t * port_addr) ++{ ++ struct urb *urb = (struct urb *)urb_handle; ++ if (urb->dev->tt) { ++ *hub_addr = urb->dev->tt->hub->devnum; ++ } else { ++ *hub_addr = 0; ++ } ++ *port_addr = urb->dev->ttport; ++ return 0; ++} ++ ++static int _speed(dwc_otg_hcd_t * hcd, void *urb_handle) ++{ ++ struct urb *urb = (struct urb *)urb_handle; ++ return urb->dev->speed; ++} ++ ++static int _get_b_hnp_enable(dwc_otg_hcd_t * hcd) ++{ ++ struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd); ++ return usb_hcd->self.b_hnp_enable; ++} ++ ++static void allocate_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw, ++ struct urb *urb) ++{ ++ hcd_to_bus(hcd)->bandwidth_allocated += bw / urb->interval; ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ hcd_to_bus(hcd)->bandwidth_isoc_reqs++; ++ } else { ++ hcd_to_bus(hcd)->bandwidth_int_reqs++; ++ } ++} ++ ++static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw, ++ struct urb *urb) ++{ ++ hcd_to_bus(hcd)->bandwidth_allocated -= bw / urb->interval; ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ hcd_to_bus(hcd)->bandwidth_isoc_reqs--; ++ } else { ++ hcd_to_bus(hcd)->bandwidth_int_reqs--; ++ } ++} ++ ++/** ++ * Sets the final status of an URB and returns it to the device driver. Any ++ * required cleanup of the URB is performed. ++ */ ++static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle, ++ dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status) ++{ ++ struct urb *urb = (struct urb *)urb_handle; ++#ifdef DEBUG ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n", ++ __func__, urb, usb_pipedevice(urb->pipe), ++ usb_pipeendpoint(urb->pipe), ++ usb_pipein(urb->pipe) ? "IN" : "OUT", status); ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ int i; ++ for (i = 0; i < urb->number_of_packets; i++) { ++ DWC_PRINTF(" ISO Desc %d status: %d\n", ++ i, urb->iso_frame_desc[i].status); ++ } ++ } ++ } ++#endif ++ ++ urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb); ++ /* Convert status value. */ ++ switch (status) { ++ case -DWC_E_PROTOCOL: ++ status = -EPROTO; ++ break; ++ case -DWC_E_IN_PROGRESS: ++ status = -EINPROGRESS; ++ break; ++ case -DWC_E_PIPE: ++ status = -EPIPE; ++ break; ++ case -DWC_E_IO: ++ status = -EIO; ++ break; ++ case -DWC_E_TIMEOUT: ++ status = -ETIMEDOUT; ++ break; ++ case -DWC_E_OVERFLOW: ++ status = -EOVERFLOW; ++ break; ++ default: ++ if (status) { ++ DWC_PRINTF("Uknown urb status %d\n", status); ++ ++ } ++ } ++ ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ int i; ++ ++ urb->error_count = dwc_otg_hcd_urb_get_error_count(dwc_otg_urb); ++ for (i = 0; i < urb->number_of_packets; ++i) { ++ urb->iso_frame_desc[i].actual_length = ++ dwc_otg_hcd_urb_get_iso_desc_actual_length ++ (dwc_otg_urb, i); ++ urb->iso_frame_desc[i].status = ++ dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_urb, i); ++ } ++ } ++ ++ urb->status = status; ++ urb->hcpriv = NULL; ++ if (!status) { ++ if ((urb->transfer_flags & URB_SHORT_NOT_OK) && ++ (urb->actual_length < urb->transfer_buffer_length)) { ++ urb->status = -EREMOTEIO; ++ } ++ } ++ ++ if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) || ++ (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) { ++ struct usb_host_endpoint *ep = dwc_urb_to_endpoint(urb); ++ if (ep) { ++ free_bus_bandwidth(dwc_otg_hcd_to_hcd(hcd), ++ dwc_otg_hcd_get_ep_bandwidth(hcd, ++ ep->hcpriv), ++ urb); ++ } ++ } ++ ++ DWC_FREE(dwc_otg_urb); ++ ++ DWC_SPINUNLOCK(hcd->lock); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb); ++#else ++ usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status); ++#endif ++ DWC_SPINLOCK(hcd->lock); ++ ++ return 0; ++} ++ ++static struct dwc_otg_hcd_function_ops hcd_fops = { ++ .start = _start, ++ .disconnect = _disconnect, ++ .hub_info = _hub_info, ++ .speed = _speed, ++ .complete = _complete, ++ .get_b_hnp_enable = _get_b_hnp_enable, ++}; ++ ++/** ++ * Initializes the HCD. This function allocates memory for and initializes the ++ * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the ++ * USB bus with the core and calls the hc_driver->start() function. It returns ++ * a negative error on failure. ++ */ ++int hcd_init( ++#ifdef LM_INTERFACE ++ struct lm_device *_dev ++#elif defined(PCI_INTERFACE) ++ struct pci_dev *_dev ++#endif ++ ) ++{ ++ struct usb_hcd *hcd = NULL; ++ dwc_otg_hcd_t *dwc_otg_hcd = NULL; ++#ifdef LM_INTERFACE ++ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); ++#elif defined(PCI_INTERFACE) ++ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); ++#endif ++ ++ int retval = 0; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT\n"); ++ ++ /* Set device flags indicating whether the HCD supports DMA. */ ++ if (dwc_otg_is_dma_enable(otg_dev->core_if)) { ++#ifdef LM_INTERFACE ++ _dev->dev.dma_mask = (void *)~0; ++ _dev->dev.coherent_dma_mask = ~0; ++#elif defined(PCI_INTERFACE) ++ pci_set_dma_mask(_dev, DMA_BIT_MASK(32)); ++ pci_set_consistent_dma_mask(_dev, DMA_BIT_MASK(32)); ++#endif ++ ++ } else { ++#ifdef LM_INTERFACE ++ _dev->dev.dma_mask = (void *)0; ++ _dev->dev.coherent_dma_mask = 0; ++#elif defined(PCI_INTERFACE) ++ pci_set_dma_mask(_dev, 0); ++ pci_set_consistent_dma_mask(_dev, 0); ++#endif ++ } ++ ++ /* ++ * Allocate memory for the base HCD plus the DWC OTG HCD. ++ * Initialize the base HCD. ++ */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ++ hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, _dev->dev.bus_id); ++#else ++ hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, dev_name(&_dev->dev)); ++ hcd->has_tt = 1; ++// hcd->uses_new_polling = 1; ++// hcd->poll_rh = 0; ++#endif ++ if (!hcd) { ++ retval = -ENOMEM; ++ goto error1; ++ } ++ ++ hcd->regs = otg_dev->os_dep.base; ++ ++ /* Initialize the DWC OTG HCD. */ ++ dwc_otg_hcd = dwc_otg_hcd_alloc_hcd(); ++ if (!dwc_otg_hcd) { ++ goto error2; ++ } ++ ((struct wrapper_priv_data *)(hcd->hcd_priv))->dwc_otg_hcd = ++ dwc_otg_hcd; ++ otg_dev->hcd = dwc_otg_hcd; ++ ++ if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) { ++ goto error2; ++ } ++ ++ otg_dev->hcd->otg_dev = otg_dev; ++ hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel) ++ hcd->self.otg_version = dwc_otg_get_otg_version(otg_dev->core_if); ++ /* Don't support SG list at this point */ ++ hcd->self.sg_tablesize = 0; ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) ++ /* Do not to do HNP polling if not capable */ ++ if (otg_dev->core_if->otg_ver) ++ hcd->self.is_hnp_cap = dwc_otg_get_hnpcapable(otg_dev->core_if); ++#endif ++ /* ++ * Finish generic HCD initialization and start the HCD. This function ++ * allocates the DMA buffer pool, registers the USB bus, requests the ++ * IRQ line, and calls hcd_start method. ++ */ ++ retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED | IRQF_DISABLED); ++ if (retval < 0) { ++ goto error2; ++ } ++ ++ dwc_otg_hcd_set_priv_data(dwc_otg_hcd, hcd); ++ return 0; ++ ++error2: ++ usb_put_hcd(hcd); ++error1: ++ return retval; ++} ++ ++/** ++ * Removes the HCD. ++ * Frees memory and resources associated with the HCD and deregisters the bus. ++ */ ++void hcd_remove( ++#ifdef LM_INTERFACE ++ struct lm_device *_dev ++#elif defined(PCI_INTERFACE) ++ struct pci_dev *_dev ++#endif ++ ) ++{ ++#ifdef LM_INTERFACE ++ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); ++#elif defined(PCI_INTERFACE) ++ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); ++#endif ++ ++ dwc_otg_hcd_t *dwc_otg_hcd; ++ struct usb_hcd *hcd; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD REMOVE\n"); ++ ++ if (!otg_dev) { ++ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__); ++ return; ++ } ++ ++ dwc_otg_hcd = otg_dev->hcd; ++ ++ if (!dwc_otg_hcd) { ++ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__); ++ return; ++ } ++ ++ hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd); ++ ++ if (!hcd) { ++ DWC_DEBUGPL(DBG_ANY, ++ "%s: dwc_otg_hcd_to_hcd(dwc_otg_hcd) NULL!\n", ++ __func__); ++ return; ++ } ++ usb_remove_hcd(hcd); ++ dwc_otg_hcd_set_priv_data(dwc_otg_hcd, NULL); ++ dwc_otg_hcd_remove(dwc_otg_hcd); ++ usb_put_hcd(hcd); ++} ++ ++/* ========================================================================= ++ * Linux HC Driver Functions ++ * ========================================================================= */ ++ ++/** Initializes the DWC_otg controller and its root hub and prepares it for host ++ * mode operation. Activates the root port. Returns 0 on success and a negative ++ * error code on failure. */ ++int hcd_start(struct usb_hcd *hcd) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ struct usb_bus *bus; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n"); ++ bus = hcd_to_bus(hcd); ++ ++ hcd->state = HC_STATE_RUNNING; ++ if (dwc_otg_hcd_start(dwc_otg_hcd, &hcd_fops)) { ++ if (dwc_otg_hcd->core_if->otg_ver && dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) ++ dwc_otg_hcd->core_if->op_state = B_PERIPHERAL; ++ return 0; ++ } ++ ++ /* Initialize and connect root hub if one is not already attached */ ++ if (bus->root_hub) { ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Has Root Hub\n"); ++ /* Inform the HUB driver to resume. */ ++ usb_hcd_resume_root_hub(hcd); ++ } ++ ++ return 0; ++} ++ ++/** ++ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are ++ * stopped. ++ */ ++void hcd_stop(struct usb_hcd *hcd) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++ dwc_otg_hcd_stop(dwc_otg_hcd); ++} ++ ++/** Returns the current frame number. */ ++static int get_frame_number(struct usb_hcd *hcd) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++ return dwc_otg_hcd_get_frame_number(dwc_otg_hcd); ++} ++ ++#ifdef DEBUG ++static void dump_urb_info(struct urb *urb, char *fn_name) ++{ ++ DWC_PRINTF("%s, urb %p\n", fn_name, urb); ++ DWC_PRINTF(" Device address: %d\n", usb_pipedevice(urb->pipe)); ++ DWC_PRINTF(" Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe), ++ (usb_pipein(urb->pipe) ? "IN" : "OUT")); ++ DWC_PRINTF(" Endpoint type: %s\n", ( { ++ char *pipetype; ++ switch (usb_pipetype(urb->pipe)) { ++case PIPE_CONTROL: ++pipetype = "CONTROL"; break; case PIPE_BULK: ++pipetype = "BULK"; break; case PIPE_INTERRUPT: ++pipetype = "INTERRUPT"; break; case PIPE_ISOCHRONOUS: ++pipetype = "ISOCHRONOUS"; break; default: ++ pipetype = "UNKNOWN"; break;}; ++ pipetype;} ++ )) ; ++ DWC_PRINTF(" Speed: %s\n", ( { ++ char *speed; switch (urb->dev->speed) { ++case USB_SPEED_HIGH: ++speed = "HIGH"; break; case USB_SPEED_FULL: ++speed = "FULL"; break; case USB_SPEED_LOW: ++speed = "LOW"; break; default: ++ speed = "UNKNOWN"; break;}; ++ speed;} ++ )) ; ++ DWC_PRINTF(" Max packet size: %d\n", ++ usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))); ++ DWC_PRINTF(" Data buffer length: %d\n", urb->transfer_buffer_length); ++ DWC_PRINTF(" Transfer buffer: %p, Transfer DMA: %p\n", ++ urb->transfer_buffer, (void *)urb->transfer_dma); ++ DWC_PRINTF(" Setup buffer: %p, Setup DMA: %p\n", ++ urb->setup_packet, (void *)urb->setup_dma); ++ DWC_PRINTF(" Interval: %d\n", urb->interval); ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ int i; ++ for (i = 0; i < urb->number_of_packets; i++) { ++ DWC_PRINTF(" ISO Desc %d:\n", i); ++ DWC_PRINTF(" offset: %d, length %d\n", ++ urb->iso_frame_desc[i].offset, ++ urb->iso_frame_desc[i].length); ++ } ++ } ++} ++ ++#endif ++ ++/** Starts processing a USB transfer request specified by a USB Request Block ++ * (URB). mem_flags indicates the type of memory allocation to use while ++ * processing this URB. */ ++static int urb_enqueue(struct usb_hcd *hcd, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ struct usb_host_endpoint *ep, ++#endif ++ struct urb *urb, gfp_t mem_flags) ++{ ++ int retval = 0; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) ++ struct usb_host_endpoint *ep = urb->ep; ++#endif ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ dwc_otg_hcd_urb_t *dwc_otg_urb; ++ int i; ++ int alloc_bandwidth = 0; ++ uint8_t ep_type = 0; ++ uint32_t flags = 0; ++ void *buf; ++ ++#ifdef DEBUG ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ dump_urb_info(urb, "urb_enqueue"); ++ } ++#endif ++ ++ if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) ++ || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) { ++ if (!dwc_otg_hcd_is_bandwidth_allocated ++ (dwc_otg_hcd, &ep->hcpriv)) { ++ alloc_bandwidth = 1; ++ } ++ } ++ ++ switch (usb_pipetype(urb->pipe)) { ++ case PIPE_CONTROL: ++ ep_type = USB_ENDPOINT_XFER_CONTROL; ++ break; ++ case PIPE_ISOCHRONOUS: ++ ep_type = USB_ENDPOINT_XFER_ISOC; ++ break; ++ case PIPE_BULK: ++ ep_type = USB_ENDPOINT_XFER_BULK; ++ break; ++ case PIPE_INTERRUPT: ++ ep_type = USB_ENDPOINT_XFER_INT; ++ break; ++ default: ++ DWC_WARN("Wrong ep type\n"); ++ } ++ ++ dwc_otg_urb = dwc_otg_hcd_urb_alloc(dwc_otg_hcd, ++ urb->number_of_packets, ++ mem_flags == GFP_ATOMIC ? 1 : 0); ++ ++ dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe), ++ usb_pipeendpoint(urb->pipe), ep_type, ++ usb_pipein(urb->pipe), ++ usb_maxpacket(urb->dev, urb->pipe, ++ !(usb_pipein(urb->pipe)))); ++ ++ buf = urb->transfer_buffer; ++ if (hcd->self.uses_dma) { ++ /* ++ * Calculate virtual address from physical address, ++ * because some class driver may not fill transfer_buffer. ++ * In Buffer DMA mode virual address is used, ++ * when handling non DWORD aligned buffers. ++ */ ++ buf = phys_to_virt(urb->transfer_dma); ++ } ++ ++ if (!(urb->transfer_flags & URB_NO_INTERRUPT)) ++ flags |= URB_GIVEBACK_ASAP; ++ if (urb->transfer_flags & URB_ZERO_PACKET) ++ flags |= URB_SEND_ZERO_PACKET; ++ ++ dwc_otg_hcd_urb_set_params(dwc_otg_urb, urb, buf, ++ urb->transfer_dma, ++ urb->transfer_buffer_length, ++ urb->setup_packet, ++ urb->setup_dma, flags, urb->interval); ++ ++ for (i = 0; i < urb->number_of_packets; ++i) { ++ dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_urb, i, ++ urb-> ++ iso_frame_desc[i].offset, ++ urb-> ++ iso_frame_desc[i].length); ++ } ++ ++ urb->hcpriv = dwc_otg_urb; ++ retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb, &ep->hcpriv, ++ mem_flags == GFP_ATOMIC ? 1 : 0); ++ if (!retval) { ++ if (alloc_bandwidth) { ++ allocate_bus_bandwidth(hcd, ++ dwc_otg_hcd_get_ep_bandwidth ++ (dwc_otg_hcd, ep->hcpriv), urb); ++ } ++ } else { ++ if (retval == -DWC_E_NO_DEVICE) { ++ retval = -ENODEV; ++ } ++ } ++ ++ return retval; ++} ++ ++/** Aborts/cancels a USB transfer request. Always returns 0 to indicate ++ * success. */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb) ++#else ++static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ++#endif ++{ ++ dwc_irqflags_t flags; ++ dwc_otg_hcd_t *dwc_otg_hcd; ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n"); ++ ++ dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++#ifdef DEBUG ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ dump_urb_info(urb, "urb_dequeue"); ++ } ++#endif ++ ++ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); ++ ++ dwc_otg_hcd_urb_dequeue(dwc_otg_hcd, urb->hcpriv); ++ ++ DWC_FREE(urb->hcpriv); ++ urb->hcpriv = NULL; ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); ++ ++ /* Higher layer software sets URB status. */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ usb_hcd_giveback_urb(hcd, urb); ++#else ++ usb_hcd_giveback_urb(hcd, urb, status); ++#endif ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ DWC_PRINTF("Called usb_hcd_giveback_urb()\n"); ++ DWC_PRINTF(" urb->status = %d\n", urb->status); ++ } ++ ++ return 0; ++} ++ ++/* Frees resources in the DWC_otg controller related to a given endpoint. Also ++ * clears state in the HCD related to the endpoint. Any URBs for the endpoint ++ * must already be dequeued. */ ++static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++ DWC_DEBUGPL(DBG_HCD, ++ "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, " ++ "endpoint=%d\n", ep->desc.bEndpointAddress, ++ dwc_ep_addr_to_endpoint(ep->desc.bEndpointAddress)); ++ dwc_otg_hcd_endpoint_disable(dwc_otg_hcd, ep->hcpriv, 250); ++ ep->hcpriv = NULL; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++/* Resets endpoint specific parameter values, in current version used to reset ++ * the data toggle(as a WA). This function can be called from usb_clear_halt routine */ ++static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) ++{ ++ dwc_irqflags_t flags; ++ struct usb_device *udev = NULL; ++ int epnum = usb_endpoint_num(&ep->desc); ++ int is_out = usb_endpoint_dir_out(&ep->desc); ++ int is_control = usb_endpoint_xfer_control(&ep->desc); ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++#ifdef LM_INTERFACE ++ struct lm_device *_dev = dwc_otg_hcd->otg_dev->os_dep.lmdev; ++#elif defined(PCI_INTERFACE) ++ struct pci_dev *_dev = dwc_otg_hcd->otg_dev->os_dep.pcidev; ++#endif ++ ++ if (_dev) ++ udev = to_usb_device(&_dev->dev); ++ else ++ return; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD EP RESET: Endpoint Num=0x%02d\n", epnum); ++ ++ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); ++ usb_settoggle(udev, epnum, is_out, 0); ++ if (is_control) ++ usb_settoggle(udev, epnum, !is_out, 0); ++ ++ if (ep->hcpriv) { ++ dwc_otg_hcd_endpoint_reset(dwc_otg_hcd, ep->hcpriv); ++ } ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); ++} ++#endif ++ ++/** Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if ++ * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid ++ * interrupt. ++ * ++ * This function is called by the USB core when an interrupt occurs */ ++static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ int32_t retval = dwc_otg_hcd_handle_intr(dwc_otg_hcd); ++ if (retval != 0) { ++ S3C2410X_CLEAR_EINTPEND(); ++ } ++ return IRQ_RETVAL(retval); ++} ++ ++/** Creates Status Change bitmap for the root hub and root port. The bitmap is ++ * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1 ++ * is the status change indicator for the single root port. Returns 1 if either ++ * change indicator is 1, otherwise returns 0. */ ++int hub_status_data(struct usb_hcd *hcd, char *buf) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++ buf[0] = 0; ++ buf[0] |= (dwc_otg_hcd_is_status_changed(dwc_otg_hcd, 1)) << 1; ++ ++ return (buf[0] != 0); ++} ++ ++/** Handles hub class-specific requests. */ ++int hub_control(struct usb_hcd *hcd, ++ u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) ++{ ++ int retval; ++ ++ retval = dwc_otg_hcd_hub_control(hcd_to_dwc_otg_hcd(hcd), ++ typeReq, wValue, wIndex, buf, wLength); ++ ++ switch (retval) { ++ case -DWC_E_INVALID: ++ retval = -EINVAL; ++ break; ++ } ++ ++ return retval; ++} ++ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_queue.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_queue.c +new file mode 100644 +index 0000000..5682867 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_hcd_queue.c +@@ -0,0 +1,727 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $ ++ * $Revision: #45 $ ++ * $Date: 2013/01/24 $ ++ * $Change: 2150293 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_DEVICE_ONLY ++ ++/** ++ * @file ++ * ++ * This file contains the functions to manage Queue Heads and Queue ++ * Transfer Descriptors. ++ */ ++ ++#include "dwc_otg_hcd.h" ++#include "dwc_otg_regs.h" ++ ++/** ++ * Free each QTD in the QH's QTD-list then free the QH. QH should already be ++ * removed from a list. QTD list should already be empty if called from URB ++ * Dequeue. ++ * ++ * @param hcd HCD instance. ++ * @param qh The QH to free. ++ */ ++void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ dwc_otg_qtd_t *qtd, *qtd_tmp; ++ dwc_irqflags_t flags; ++ ++ /* Free each QTD in the QTD list */ ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { ++ DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry); ++ dwc_otg_hcd_qtd_free(qtd); ++ } ++ ++ if (hcd->core_if->dma_desc_enable) { ++ dwc_otg_hcd_qh_free_ddma(hcd, qh); ++ } else if (qh->dw_align_buf) { ++ uint32_t buf_size; ++ if (qh->ep_type == UE_ISOCHRONOUS) { ++ buf_size = 4096; ++ } else { ++ buf_size = hcd->core_if->core_params->max_transfer_size; ++ } ++ DWC_DMA_FREE(buf_size, qh->dw_align_buf, qh->dw_align_buf_dma); ++ } ++ ++ DWC_FREE(qh); ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ return; ++} ++ ++#define BitStuffTime(bytecount) ((8 * 7* bytecount) / 6) ++#define HS_HOST_DELAY 5 /* nanoseconds */ ++#define FS_LS_HOST_DELAY 1000 /* nanoseconds */ ++#define HUB_LS_SETUP 333 /* nanoseconds */ ++#define NS_TO_US(ns) ((ns + 500) / 1000) ++ /* convert & round nanoseconds to microseconds */ ++ ++static uint32_t calc_bus_time(int speed, int is_in, int is_isoc, int bytecount) ++{ ++ unsigned long retval; ++ ++ switch (speed) { ++ case USB_SPEED_HIGH: ++ if (is_isoc) { ++ retval = ++ ((38 * 8 * 2083) + ++ (2083 * (3 + BitStuffTime(bytecount)))) / 1000 + ++ HS_HOST_DELAY; ++ } else { ++ retval = ++ ((55 * 8 * 2083) + ++ (2083 * (3 + BitStuffTime(bytecount)))) / 1000 + ++ HS_HOST_DELAY; ++ } ++ break; ++ case USB_SPEED_FULL: ++ if (is_isoc) { ++ retval = ++ (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000; ++ if (is_in) { ++ retval = 7268 + FS_LS_HOST_DELAY + retval; ++ } else { ++ retval = 6265 + FS_LS_HOST_DELAY + retval; ++ } ++ } else { ++ retval = ++ (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000; ++ retval = 9107 + FS_LS_HOST_DELAY + retval; ++ } ++ break; ++ case USB_SPEED_LOW: ++ if (is_in) { ++ retval = ++ (67667 * (31 + 10 * BitStuffTime(bytecount))) / ++ 1000; ++ retval = ++ 64060 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY + ++ retval; ++ } else { ++ retval = ++ (66700 * (31 + 10 * BitStuffTime(bytecount))) / ++ 1000; ++ retval = ++ 64107 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY + ++ retval; ++ } ++ break; ++ default: ++ DWC_WARN("Unknown device speed\n"); ++ retval = -1; ++ } ++ ++ return NS_TO_US(retval); ++} ++ ++/** ++ * Initializes a QH structure. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh The QH to init. ++ * @param urb Holds the information about the device/endpoint that we need ++ * to initialize the QH. ++ */ ++#define SCHEDULE_SLOP 10 ++void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb) ++{ ++ char *speed, *type; ++ int dev_speed; ++ uint32_t hub_addr, hub_port; ++ ++ dwc_memset(qh, 0, sizeof(dwc_otg_qh_t)); ++ ++ /* Initialize QH */ ++ qh->ep_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info); ++ qh->ep_is_in = dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0; ++ ++ qh->data_toggle = DWC_OTG_HC_PID_DATA0; ++ qh->maxp = dwc_otg_hcd_get_mps(&urb->pipe_info); ++ DWC_CIRCLEQ_INIT(&qh->qtd_list); ++ DWC_LIST_INIT(&qh->qh_list_entry); ++ qh->channel = NULL; ++ ++ /* FS/LS Enpoint on HS Hub ++ * NOT virtual root hub */ ++ dev_speed = hcd->fops->speed(hcd, urb->priv); ++ ++ hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &hub_port); ++ qh->do_split = 0; ++ ++ if (((dev_speed == USB_SPEED_LOW) || ++ (dev_speed == USB_SPEED_FULL)) && ++ (hub_addr != 0 && hub_addr != 1)) { ++ DWC_DEBUGPL(DBG_HCD, ++ "QH init: EP %d: TT found at hub addr %d, for port %d\n", ++ dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr, ++ hub_port); ++ qh->do_split = 1; ++ } ++ ++ if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) { ++ /* Compute scheduling parameters once and save them. */ ++ hprt0_data_t hprt; ++ ++ /** @todo Account for split transfers in the bus time. */ ++ int bytecount = ++ dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp); ++ ++ qh->usecs = ++ calc_bus_time((qh->do_split ? USB_SPEED_HIGH : dev_speed), ++ qh->ep_is_in, (qh->ep_type == UE_ISOCHRONOUS), ++ bytecount); ++ /* Start in a slightly future (micro)frame. */ ++ qh->sched_frame = dwc_frame_num_inc(hcd->frame_number, ++ SCHEDULE_SLOP); ++ qh->interval = urb->interval; ++ ++#if 0 ++ /* Increase interrupt polling rate for debugging. */ ++ if (qh->ep_type == UE_INTERRUPT) { ++ qh->interval = 8; ++ } ++#endif ++ hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0); ++ if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) && ++ ((dev_speed == USB_SPEED_LOW) || ++ (dev_speed == USB_SPEED_FULL))) { ++ qh->interval *= 8; ++ qh->sched_frame |= 0x7; ++ qh->start_split_frame = qh->sched_frame; ++ } ++ ++ } ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n"); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - qh = %p\n", qh); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Device Address = %d\n", ++ dwc_otg_hcd_get_dev_addr(&urb->pipe_info)); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Endpoint %d, %s\n", ++ dwc_otg_hcd_get_ep_num(&urb->pipe_info), ++ dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT"); ++ switch (dev_speed) { ++ case USB_SPEED_LOW: ++ qh->dev_speed = DWC_OTG_EP_SPEED_LOW; ++ speed = "low"; ++ break; ++ case USB_SPEED_FULL: ++ qh->dev_speed = DWC_OTG_EP_SPEED_FULL; ++ speed = "full"; ++ break; ++ case USB_SPEED_HIGH: ++ qh->dev_speed = DWC_OTG_EP_SPEED_HIGH; ++ speed = "high"; ++ break; ++ default: ++ speed = "?"; ++ break; ++ } ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Speed = %s\n", speed); ++ ++ switch (qh->ep_type) { ++ case UE_ISOCHRONOUS: ++ type = "isochronous"; ++ break; ++ case UE_INTERRUPT: ++ type = "interrupt"; ++ break; ++ case UE_CONTROL: ++ type = "control"; ++ break; ++ case UE_BULK: ++ type = "bulk"; ++ break; ++ default: ++ type = "?"; ++ break; ++ } ++ ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Type = %s\n", type); ++ ++#ifdef DEBUG ++ if (qh->ep_type == UE_INTERRUPT) { ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - usecs = %d\n", ++ qh->usecs); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - interval = %d\n", ++ qh->interval); ++ } ++#endif ++ ++} ++ ++/** ++ * This function allocates and initializes a QH. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param urb Holds the information about the device/endpoint that we need ++ * to initialize the QH. ++ * @param atomic_alloc Flag to do atomic allocation if needed ++ * ++ * @return Returns pointer to the newly allocated QH, or NULL on error. */ ++dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd, ++ dwc_otg_hcd_urb_t * urb, int atomic_alloc) ++{ ++ dwc_otg_qh_t *qh; ++ ++ /* Allocate memory */ ++ /** @todo add memflags argument */ ++ qh = dwc_otg_hcd_qh_alloc(atomic_alloc); ++ if (qh == NULL) { ++ DWC_ERROR("qh allocation failed"); ++ return NULL; ++ } ++ ++ qh_init(hcd, qh, urb); ++ ++ if (hcd->core_if->dma_desc_enable ++ && (dwc_otg_hcd_qh_init_ddma(hcd, qh) < 0)) { ++ dwc_otg_hcd_qh_free(hcd, qh); ++ return NULL; ++ } ++ ++ return qh; ++} ++ ++/** ++ * Checks that a channel is available for a periodic transfer. ++ * ++ * @return 0 if successful, negative error code otherise. ++ */ ++static int periodic_channel_available(dwc_otg_hcd_t * hcd) ++{ ++ /* ++ * Currently assuming that there is a dedicated host channnel for each ++ * periodic transaction plus at least one host channel for ++ * non-periodic transactions. ++ */ ++ int status; ++ int num_channels; ++ ++ num_channels = hcd->core_if->core_params->host_channels; ++ if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels) ++ && (hcd->periodic_channels < num_channels - 1)) { ++ status = 0; ++ } else { ++ DWC_INFO("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n", ++ __func__, num_channels, hcd->periodic_channels, hcd->non_periodic_channels); //NOTICE ++ status = -DWC_E_NO_SPACE; ++ } ++ ++ return status; ++} ++ ++/** ++ * Checks that there is sufficient bandwidth for the specified QH in the ++ * periodic schedule. For simplicity, this calculation assumes that all the ++ * transfers in the periodic schedule may occur in the same (micro)frame. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh QH containing periodic bandwidth required. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++static int check_periodic_bandwidth(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ int status; ++ int16_t max_claimed_usecs; ++ ++ status = 0; ++ ++ if ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) || qh->do_split) { ++ /* ++ * High speed mode. ++ * Max periodic usecs is 80% x 125 usec = 100 usec. ++ */ ++ ++ max_claimed_usecs = 100 - qh->usecs; ++ } else { ++ /* ++ * Full speed mode. ++ * Max periodic usecs is 90% x 1000 usec = 900 usec. ++ */ ++ max_claimed_usecs = 900 - qh->usecs; ++ } ++ ++ if (hcd->periodic_usecs > max_claimed_usecs) { ++ DWC_INFO("%s: already claimed usecs %d, required usecs %d\n", __func__, hcd->periodic_usecs, qh->usecs); //NOTICE ++ status = -DWC_E_NO_SPACE; ++ } ++ ++ return status; ++} ++ ++/** ++ * Checks that the max transfer size allowed in a host channel is large enough ++ * to handle the maximum data transfer in a single (micro)frame for a periodic ++ * transfer. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh QH for a periodic endpoint. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++static int check_max_xfer_size(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ int status; ++ uint32_t max_xfer_size; ++ uint32_t max_channel_xfer_size; ++ ++ status = 0; ++ ++ max_xfer_size = dwc_max_packet(qh->maxp) * dwc_hb_mult(qh->maxp); ++ max_channel_xfer_size = hcd->core_if->core_params->max_transfer_size; ++ ++ if (max_xfer_size > max_channel_xfer_size) { ++ DWC_INFO("%s: Periodic xfer length %d > " "max xfer length for channel %d\n", ++ __func__, max_xfer_size, max_channel_xfer_size); //NOTICE ++ status = -DWC_E_NO_SPACE; ++ } ++ ++ return status; ++} ++ ++/** ++ * Schedules an interrupt or isochronous transfer in the periodic schedule. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh QH for the periodic transfer. The QH should already contain the ++ * scheduling information. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ int status = 0; ++ ++ status = periodic_channel_available(hcd); ++ if (status) { ++ DWC_INFO("%s: No host channel available for periodic " "transfer.\n", __func__); //NOTICE ++ return status; ++ } ++ ++ status = check_periodic_bandwidth(hcd, qh); ++ if (status) { ++ DWC_INFO("%s: Insufficient periodic bandwidth for " "periodic transfer.\n", __func__); //NOTICE ++ return status; ++ } ++ ++ status = check_max_xfer_size(hcd, qh); ++ if (status) { ++ DWC_INFO("%s: Channel max transfer size too small " "for periodic transfer.\n", __func__); //NOTICE ++ return status; ++ } ++ ++ if (hcd->core_if->dma_desc_enable) { ++ /* Don't rely on SOF and start in ready schedule */ ++ DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry); ++ } ++ else { ++ /* Always start in the inactive schedule. */ ++ DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry); ++ } ++ ++ /* Reserve the periodic channel. */ ++ hcd->periodic_channels++; ++ ++ /* Update claimed usecs per (micro)frame. */ ++ hcd->periodic_usecs += qh->usecs; ++ ++ return status; ++} ++ ++/** ++ * This function adds a QH to either the non periodic or periodic schedule if ++ * it is not already in the schedule. If the QH is already in the schedule, no ++ * action is taken. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ int status = 0; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) { ++ /* QH already in a schedule. */ ++ return status; ++ } ++ ++ /* Add the new QH to the appropriate schedule */ ++ if (dwc_qh_is_non_per(qh)) { ++ /* Always start in the inactive schedule. */ ++ DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive, ++ &qh->qh_list_entry); ++ } else { ++ status = schedule_periodic(hcd, qh); ++ if ( !hcd->periodic_qh_count ) { ++ intr_mask.b.sofintr = 1; ++ DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } ++ hcd->periodic_qh_count++; ++ } ++ ++ return status; ++} ++ ++/** ++ * Removes an interrupt or isochronous transfer from the periodic schedule. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh QH for the periodic transfer. ++ */ ++static void deschedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ DWC_LIST_REMOVE_INIT(&qh->qh_list_entry); ++ ++ /* Release the periodic channel reservation. */ ++ hcd->periodic_channels--; ++ ++ /* Update claimed usecs per (micro)frame. */ ++ hcd->periodic_usecs -= qh->usecs; ++} ++ ++/** ++ * Removes a QH from either the non-periodic or periodic schedule. Memory is ++ * not freed. ++ * ++ * @param hcd The HCD state structure. ++ * @param qh QH to remove from schedule. */ ++void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ if (DWC_LIST_EMPTY(&qh->qh_list_entry)) { ++ /* QH is not in a schedule. */ ++ return; ++ } ++ ++ if (dwc_qh_is_non_per(qh)) { ++ if (hcd->non_periodic_qh_ptr == &qh->qh_list_entry) { ++ hcd->non_periodic_qh_ptr = ++ hcd->non_periodic_qh_ptr->next; ++ } ++ DWC_LIST_REMOVE_INIT(&qh->qh_list_entry); ++ } else { ++ deschedule_periodic(hcd, qh); ++ hcd->periodic_qh_count--; ++ if( !hcd->periodic_qh_count ) { ++ intr_mask.b.sofintr = 1; ++ DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ } ++ } ++} ++ ++/** ++ * Deactivates a QH. For non-periodic QHs, removes the QH from the active ++ * non-periodic schedule. The QH is added to the inactive non-periodic ++ * schedule if any QTDs are still attached to the QH. ++ * ++ * For periodic QHs, the QH is removed from the periodic queued schedule. If ++ * there are any QTDs still attached to the QH, the QH is added to either the ++ * periodic inactive schedule or the periodic ready schedule and its next ++ * scheduled frame is calculated. The QH is placed in the ready schedule if ++ * the scheduled frame has been reached already. Otherwise it's placed in the ++ * inactive schedule. If there are no QTDs attached to the QH, the QH is ++ * completely removed from the periodic schedule. ++ */ ++void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, ++ int sched_next_periodic_split) ++{ ++ if (dwc_qh_is_non_per(qh)) { ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ /* Add back to inactive non-periodic schedule. */ ++ dwc_otg_hcd_qh_add(hcd, qh); ++ } ++ } else { ++ uint16_t frame_number = dwc_otg_hcd_get_frame_number(hcd); ++ ++ if (qh->do_split) { ++ /* Schedule the next continuing periodic split transfer */ ++ if (sched_next_periodic_split) { ++ ++ qh->sched_frame = frame_number; ++ if (dwc_frame_num_le(frame_number, ++ dwc_frame_num_inc ++ (qh->start_split_frame, ++ 1))) { ++ /* ++ * Allow one frame to elapse after start ++ * split microframe before scheduling ++ * complete split, but DONT if we are ++ * doing the next start split in the ++ * same frame for an ISOC out. ++ */ ++ if ((qh->ep_type != UE_ISOCHRONOUS) || ++ (qh->ep_is_in != 0)) { ++ qh->sched_frame = ++ dwc_frame_num_inc(qh->sched_frame, 1); ++ } ++ } ++ } else { ++ qh->sched_frame = ++ dwc_frame_num_inc(qh->start_split_frame, ++ qh->interval); ++ if (dwc_frame_num_le ++ (qh->sched_frame, frame_number)) { ++ qh->sched_frame = frame_number; ++ } ++ qh->sched_frame |= 0x7; ++ qh->start_split_frame = qh->sched_frame; ++ } ++ } else { ++ qh->sched_frame = ++ dwc_frame_num_inc(qh->sched_frame, qh->interval); ++ if (dwc_frame_num_le(qh->sched_frame, frame_number)) { ++ qh->sched_frame = frame_number; ++ } ++ } ++ ++ if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ } else { ++ /* ++ * Remove from periodic_sched_queued and move to ++ * appropriate queue. ++ */ ++ if (qh->sched_frame == frame_number) { ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready, ++ &qh->qh_list_entry); ++ } else { ++ DWC_LIST_MOVE_HEAD ++ (&hcd->periodic_sched_inactive, ++ &qh->qh_list_entry); ++ } ++ } ++ } ++} ++ ++/** ++ * This function allocates and initializes a QTD. ++ * ++ * @param urb The URB to create a QTD from. Each URB-QTD pair will end up ++ * pointing to each other so each pair should have a unique correlation. ++ * @param atomic_alloc Flag to do atomic alloc if needed ++ * ++ * @return Returns pointer to the newly allocated QTD, or NULL on error. */ ++dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, int atomic_alloc) ++{ ++ dwc_otg_qtd_t *qtd; ++ ++ qtd = dwc_otg_hcd_qtd_alloc(atomic_alloc); ++ if (qtd == NULL) { ++ return NULL; ++ } ++ ++ dwc_otg_hcd_qtd_init(qtd, urb); ++ return qtd; ++} ++ ++/** ++ * Initializes a QTD structure. ++ * ++ * @param qtd The QTD to initialize. ++ * @param urb The URB to use for initialization. */ ++void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb) ++{ ++ dwc_memset(qtd, 0, sizeof(dwc_otg_qtd_t)); ++ qtd->urb = urb; ++ if (dwc_otg_hcd_get_pipe_type(&urb->pipe_info) == UE_CONTROL) { ++ /* ++ * The only time the QTD data toggle is used is on the data ++ * phase of control transfers. This phase always starts with ++ * DATA1. ++ */ ++ qtd->data_toggle = DWC_OTG_HC_PID_DATA1; ++ qtd->control_phase = DWC_OTG_CONTROL_SETUP; ++ } ++ ++ /* start split */ ++ qtd->complete_split = 0; ++ qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL; ++ qtd->isoc_split_offset = 0; ++ qtd->in_process = 0; ++ ++ /* Store the qtd ptr in the urb to reference what QTD. */ ++ urb->qtd = qtd; ++ return; ++} ++ ++/** ++ * This function adds a QTD to the QTD-list of a QH. It will find the correct ++ * QH to place the QTD into. If it does not find a QH, then it will create a ++ * new QH. If the QH to which the QTD is added is not currently scheduled, it ++ * is placed into the proper schedule based on its EP type. ++ * ++ * @param[in] qtd The QTD to add ++ * @param[in] hcd The DWC HCD structure ++ * @param[out] qh out parameter to return queue head ++ * @param atomic_alloc Flag to do atomic alloc if needed ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, ++ dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh, int atomic_alloc) ++{ ++ int retval = 0; ++ dwc_irqflags_t flags; ++ ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ ++ /* ++ * Get the QH which holds the QTD-list to insert to. Create QH if it ++ * doesn't exist. ++ */ ++ if (*qh == NULL) { ++ *qh = dwc_otg_hcd_qh_create(hcd, urb, atomic_alloc); ++ if (*qh == NULL) { ++ retval = -1; ++ goto done; ++ } ++ } ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ retval = dwc_otg_hcd_qh_add(hcd, *qh); ++ if (retval == 0) { ++ DWC_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd, ++ qtd_list_entry); ++ } ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ ++done: ++ ++ return retval; ++} ++ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_os_dep.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_os_dep.h +new file mode 100644 +index 0000000..7e491fe +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_os_dep.h +@@ -0,0 +1,88 @@ ++#ifndef _DWC_OS_DEP_H_ ++#define _DWC_OS_DEP_H_ ++ ++/** ++ * @file ++ * ++ * This file contains OS dependent structures. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++# include ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) ++# include ++#else ++# include ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) ++# include ++#else ++# include ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++# include ++#endif ++ ++ ++#include ++#include ++#include ++#include ++ ++ ++/** The OS page size */ ++#define DWC_OS_PAGE_SIZE PAGE_SIZE ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ++typedef int gfp_t; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ++# define IRQF_SHARED SA_SHIRQ ++#endif ++ ++typedef struct os_dependent { ++ /** Base address returned from ioremap() */ ++ void *base; ++ ++ /** Register offset for Diagnostic API */ ++ uint32_t reg_offset; ++ ++ uint32_t res_start; ++ ++ struct platform_device *lmdev; ++ ++} os_dependent_t; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_OS_DEP_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd.c +new file mode 100644 +index 0000000..1382647 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd.c +@@ -0,0 +1,2932 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $ ++ * $Revision: #105 $ ++ * $Date: 2013/05/16 $ ++ * $Change: 2231774 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_HOST_ONLY ++ ++/** @file ++ * This file implements PCD Core. All code in this file is portable and doesn't ++ * use any OS specific functions. ++ * PCD Core provides Interface, defined in ++ * header file, which can be used to implement OS specific PCD interface. ++ * ++ * An important function of the PCD is managing interrupts generated ++ * by the DWC_otg controller. The implementation of the DWC_otg device ++ * mode interrupt service routines is in dwc_otg_pcd_intr.c. ++ * ++ * @todo Add Device Mode test modes (Test J mode, Test K mode, etc). ++ * @todo Does it work when the request size is greater than DEPTSIZ ++ * transfer size ++ * ++ */ ++ ++#include "dwc_otg_pcd.h" ++ ++#ifdef DWC_UTE_CFI ++#include "dwc_otg_cfi.h" ++ ++extern int init_cfi(cfiobject_t * cfiobj); ++#endif ++static int bulk_num = 0; ++/** ++ * Choose endpoint from ep arrays using usb_ep structure. ++ */ ++static dwc_otg_pcd_ep_t *get_ep_from_handle(dwc_otg_pcd_t * pcd, void *handle) ++{ ++ int i; ++ if (pcd->ep0.priv == handle) { ++ return &pcd->ep0; ++ } ++ for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) { ++ if (pcd->in_ep[i].priv == handle) ++ return &pcd->in_ep[i]; ++ if (pcd->out_ep[i].priv == handle) ++ return &pcd->out_ep[i]; ++ } ++ ++ return NULL; ++} ++ ++/** ++ * This function completes a request. It call's the request call back. ++ */ ++void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req, ++ int32_t status) ++{ ++ unsigned stopped = ep->stopped; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(ep %p req %p)\n", __func__, ep, req); ++ DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry); ++ ++ /* don't modify queue heads during completion callback */ ++ ep->stopped = 1; ++ /* spin_unlock/spin_lock now done in fops->complete() */ ++ ep->pcd->fops->complete(ep->pcd, ep->priv, req->priv, status, ++ req->actual); ++ ++ if (ep->pcd->request_pending > 0) { ++ --ep->pcd->request_pending; ++ } ++ ++ ep->stopped = stopped; ++ DWC_FREE(req); ++} ++ ++/** ++ * This function terminates all the requsts in the EP request queue. ++ */ ++void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_pcd_request_t *req; ++ ++ ep->stopped = 1; ++ ++ /* called with irqs blocked?? */ ++ while (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ dwc_otg_request_done(ep, req, -DWC_E_SHUTDOWN); ++ } ++} ++ ++void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd, ++ const struct dwc_otg_pcd_function_ops *fops) ++{ ++ pcd->fops = fops; ++} ++ ++/** ++ * PCD Callback function for initializing the PCD when switching to ++ * device mode. ++ * ++ * @param p void pointer to the dwc_otg_pcd_t ++ */ ++static int32_t dwc_otg_pcd_start_cb(void *p) ++{ ++ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ /* ++ * Initialized the Core for Device mode. ++ */ ++ if (dwc_otg_is_device_mode(core_if)) { ++ dwc_otg_core_dev_init(core_if); ++ /* Set core_if's lock pointer to the pcd->lock */ ++ core_if->lock = pcd->lock; ++ } ++ return 1; ++} ++ ++/** CFI-specific buffer allocation function for EP */ ++#ifdef DWC_UTE_CFI ++uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr, ++ size_t buflen, int flags) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ ep = get_ep_from_handle(pcd, pep); ++ if (!ep) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ return pcd->cfi->ops.ep_alloc_buf(pcd->cfi, pcd, ep, addr, buflen, ++ flags); ++} ++#else ++uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr, ++ size_t buflen, int flags); ++#endif ++ ++/** ++ * PCD Callback function for notifying the PCD when resuming from ++ * suspend. ++ * ++ * @param p void pointer to the dwc_otg_pcd_t ++ */ ++static int32_t dwc_otg_pcd_resume_cb(void *p) ++{ ++ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; ++ ++ if (pcd->fops->resume) { ++ pcd->fops->resume(pcd); ++ } ++ ++ /* Stop the SRP timeout timer. */ ++ if ((GET_CORE_IF(pcd)->core_params->phy_type != DWC_PHY_TYPE_PARAM_FS) ++ || (!GET_CORE_IF(pcd)->core_params->i2c_enable)) { ++ if (GET_CORE_IF(pcd)->srp_timer_started) { ++ GET_CORE_IF(pcd)->srp_timer_started = 0; ++ DWC_TIMER_CANCEL(GET_CORE_IF(pcd)->srp_timer); ++ } ++ } ++ return 1; ++} ++ ++/** ++ * PCD Callback function for notifying the PCD device is suspended. ++ * ++ * @param p void pointer to the dwc_otg_pcd_t ++ */ ++static int32_t dwc_otg_pcd_suspend_cb(void *p) ++{ ++ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; ++ ++ if (pcd->fops->suspend) { ++ DWC_SPINUNLOCK(pcd->lock); ++ pcd->fops->suspend(pcd); ++ DWC_SPINLOCK(pcd->lock); ++ } ++ ++ return 1; ++} ++ ++/** ++ * PCD Callback function for stopping the PCD when switching to Host ++ * mode. ++ * ++ * @param p void pointer to the dwc_otg_pcd_t ++ */ ++static int32_t dwc_otg_pcd_stop_cb(void *p) ++{ ++ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; ++ extern void dwc_otg_pcd_stop(dwc_otg_pcd_t * _pcd); ++ ++ dwc_otg_pcd_stop(pcd); ++ return 1; ++} ++ ++/** ++ * PCD Callback structure for handling mode switching. ++ */ ++static dwc_otg_cil_callbacks_t pcd_callbacks = { ++ .start = dwc_otg_pcd_start_cb, ++ .stop = dwc_otg_pcd_stop_cb, ++ .suspend = dwc_otg_pcd_suspend_cb, ++ .resume_wakeup = dwc_otg_pcd_resume_cb, ++ .p = 0, /* Set at registration */ ++}; ++ ++/** ++ * This function allocates a DMA Descriptor chain for the Endpoint ++ * buffer to be used for a transfer to/from the specified endpoint. ++ */ ++dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(dwc_dma_t * dma_desc_addr, ++ uint32_t count) ++{ ++ return DWC_DMA_ALLOC_ATOMIC(count * sizeof(dwc_otg_dev_dma_desc_t), ++ dma_desc_addr); ++} ++ ++/** ++ * This function frees a DMA Descriptor chain that was allocated by ep_alloc_desc. ++ */ ++void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr, ++ uint32_t dma_desc_addr, uint32_t count) ++{ ++ DWC_DMA_FREE(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr, ++ dma_desc_addr); ++} ++ ++#ifdef DWC_EN_ISOC ++ ++/** ++ * This function initializes a descriptor chain for Isochronous transfer ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param dwc_ep The EP to start the transfer on. ++ * ++ */ ++void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * dwc_ep) ++{ ++ ++ dsts_data_t dsts = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ int i, j; ++ uint32_t len; ++ ++ if (dwc_ep->is_in) ++ dwc_ep->desc_cnt = dwc_ep->buf_proc_intrvl / dwc_ep->bInterval; ++ else ++ dwc_ep->desc_cnt = ++ dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm / ++ dwc_ep->bInterval; ++ ++ /** Allocate descriptors for double buffering */ ++ dwc_ep->iso_desc_addr = ++ dwc_otg_ep_alloc_desc_chain(&dwc_ep->iso_dma_desc_addr, ++ dwc_ep->desc_cnt * 2); ++ if (dwc_ep->desc_addr) { ++ DWC_WARN("%s, can't allocate DMA descriptor chain\n", __func__); ++ return; ++ } ++ ++ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ /** ISO OUT EP */ ++ if (dwc_ep->is_in == 0) { ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr; ++ dma_addr_t dma_ad; ++ uint32_t data_per_desc; ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[dwc_ep->num]; ++ int offset; ++ ++ addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl; ++ dma_ad = (dma_addr_t) DWC_READ_REG32(&(out_regs->doepdma)); ++ ++ /** Buffer 0 descriptors setup */ ++ dma_ad = dwc_ep->dma_addr0; ++ ++ sts.b_iso_out.bs = BS_HOST_READY; ++ sts.b_iso_out.rxsts = 0; ++ sts.b_iso_out.l = 0; ++ sts.b_iso_out.sp = 0; ++ sts.b_iso_out.ioc = 0; ++ sts.b_iso_out.pid = 0; ++ sts.b_iso_out.framenum = 0; ++ ++ offset = 0; ++ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; ++ i += dwc_ep->pkt_per_frm) { ++ ++ for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { ++ uint32_t len = (j + 1) * dwc_ep->maxpacket; ++ if (len > dwc_ep->data_per_frame) ++ data_per_desc = ++ dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket; ++ else ++ data_per_desc = dwc_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; ++ ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ } ++ ++ for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) { ++ uint32_t len = (j + 1) * dwc_ep->maxpacket; ++ if (len > dwc_ep->data_per_frame) ++ data_per_desc = ++ dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket; ++ else ++ data_per_desc = dwc_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ ++ sts.b_iso_out.ioc = 1; ++ len = (j + 1) * dwc_ep->maxpacket; ++ if (len > dwc_ep->data_per_frame) ++ data_per_desc = ++ dwc_ep->data_per_frame - j * dwc_ep->maxpacket; ++ else ++ data_per_desc = dwc_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ dma_desc++; ++ ++ /** Buffer 1 descriptors setup */ ++ sts.b_iso_out.ioc = 0; ++ dma_ad = dwc_ep->dma_addr1; ++ ++ offset = 0; ++ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; ++ i += dwc_ep->pkt_per_frm) { ++ for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { ++ uint32_t len = (j + 1) * dwc_ep->maxpacket; ++ if (len > dwc_ep->data_per_frame) ++ data_per_desc = ++ dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket; ++ else ++ data_per_desc = dwc_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; ++ ++ data_per_desc = ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ } ++ for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) { ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ ++ sts.b_iso_out.ioc = 1; ++ sts.b_iso_out.l = 1; ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ dwc_ep->next_frame = 0; ++ ++ /** Write dma_ad into DOEPDMA register */ ++ DWC_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) dwc_ep->iso_dma_desc_addr); ++ ++ } ++ /** ISO IN EP */ ++ else { ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr; ++ dma_addr_t dma_ad; ++ dwc_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[dwc_ep->num]; ++ unsigned int frmnumber; ++ fifosize_data_t txfifosize, rxfifosize; ++ ++ txfifosize.d32 = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[dwc_ep->num]-> ++ dtxfsts); ++ rxfifosize.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); ++ ++ addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl; ++ ++ dma_ad = dwc_ep->dma_addr0; ++ ++ dsts.d32 = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ sts.b_iso_in.bs = BS_HOST_READY; ++ sts.b_iso_in.txsts = 0; ++ sts.b_iso_in.sp = ++ (dwc_ep->data_per_frame % dwc_ep->maxpacket) ? 1 : 0; ++ sts.b_iso_in.ioc = 0; ++ sts.b_iso_in.pid = dwc_ep->pkt_per_frm; ++ ++ frmnumber = dwc_ep->next_frame; ++ ++ sts.b_iso_in.framenum = frmnumber; ++ sts.b_iso_in.txbytes = dwc_ep->data_per_frame; ++ sts.b_iso_in.l = 0; ++ ++ /** Buffer 0 descriptors setup */ ++ for (i = 0; i < dwc_ep->desc_cnt - 1; i++) { ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ dma_desc++; ++ ++ dma_ad += dwc_ep->data_per_frame; ++ sts.b_iso_in.framenum += dwc_ep->bInterval; ++ } ++ ++ sts.b_iso_in.ioc = 1; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++dma_desc; ++ ++ /** Buffer 1 descriptors setup */ ++ sts.b_iso_in.ioc = 0; ++ dma_ad = dwc_ep->dma_addr1; ++ ++ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; ++ i += dwc_ep->pkt_per_frm) { ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ dma_desc++; ++ ++ dma_ad += dwc_ep->data_per_frame; ++ sts.b_iso_in.framenum += dwc_ep->bInterval; ++ ++ sts.b_iso_in.ioc = 0; ++ } ++ sts.b_iso_in.ioc = 1; ++ sts.b_iso_in.l = 1; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ dwc_ep->next_frame = sts.b_iso_in.framenum + dwc_ep->bInterval; ++ ++ /** Write dma_ad into diepdma register */ ++ DWC_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) dwc_ep->iso_dma_desc_addr); ++ } ++ /** Enable endpoint, clear nak */ ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.usbactep = 1; ++ depctl.b.cnak = 1; ++ ++ DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32); ++ depctl.d32 = DWC_READ_REG32(addr); ++} ++ ++/** ++ * This function initializes a descriptor chain for Isochronous transfer ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * ep) ++{ ++ depctl_data_t depctl = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ ++ if (ep->is_in) { ++ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; ++ } else { ++ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; ++ } ++ ++ if (core_if->dma_enable == 0 || core_if->dma_desc_enable != 0) { ++ return; ++ } else { ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ ++ ep->xfer_len = ++ ep->data_per_frame * ep->buf_proc_intrvl / ep->bInterval; ++ ep->pkt_cnt = ++ (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; ++ ep->xfer_count = 0; ++ ep->xfer_buff = ++ (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0; ++ ep->dma_addr = ++ (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0; ++ ++ if (ep->is_in) { ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ deptsiz.b.mc = ep->pkt_per_frm; ++ deptsiz.b.xfersize = ep->xfer_len; ++ deptsiz.b.pktcnt = ++ (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ dieptsiz, deptsiz.d32); ++ ++ /* Write the DMA register */ ++ DWC_WRITE_REG32(& ++ (core_if->dev_if->in_ep_regs[ep->num]-> ++ diepdma), (uint32_t) ep->dma_addr); ++ ++ } else { ++ deptsiz.b.pktcnt = ++ (ep->xfer_len + (ep->maxpacket - 1)) / ++ ep->maxpacket; ++ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; ++ ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]-> ++ doeptsiz, deptsiz.d32); ++ ++ /* Write the DMA register */ ++ DWC_WRITE_REG32(& ++ (core_if->dev_if->out_ep_regs[ep->num]-> ++ doepdma), (uint32_t) ep->dma_addr); ++ ++ } ++ /** Enable endpoint, clear nak */ ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ ++ DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32); ++ } ++} ++ ++/** ++ * This function does the setup for a data transfer for an EP and ++ * starts the transfer. For an IN transfer, the packets will be ++ * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers, ++ * the packets are unloaded from the Rx FIFO in the ISR. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++ ++static void dwc_otg_iso_ep_start_transfer(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * ep) ++{ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ if (ep->is_in) { ++ ep->desc_cnt = ep->pkt_cnt / ep->pkt_per_frm; ++ } else { ++ ep->desc_cnt = ep->pkt_cnt; ++ } ++ dwc_otg_iso_ep_start_ddma_transfer(core_if, ep); ++ } else { ++ if (core_if->pti_enh_enable) { ++ dwc_otg_iso_ep_start_buf_transfer(core_if, ep); ++ } else { ++ ep->cur_pkt_addr = ++ (ep->proc_buf_num) ? ep->xfer_buff1 : ep-> ++ xfer_buff0; ++ ep->cur_pkt_dma_addr = ++ (ep->proc_buf_num) ? ep->dma_addr1 : ep-> ++ dma_addr0; ++ dwc_otg_iso_ep_start_frm_transfer(core_if, ep); ++ } ++ } ++ } else { ++ ep->cur_pkt_addr = ++ (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0; ++ ep->cur_pkt_dma_addr = ++ (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0; ++ dwc_otg_iso_ep_start_frm_transfer(core_if, ep); ++ } ++} ++ ++/** ++ * This function stops transfer for an EP and ++ * resets the ep's variables. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++ ++void dwc_otg_iso_ep_stop_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ ++ if (ep->is_in == 1) { ++ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; ++ } else { ++ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; ++ } ++ ++ /* disable the ep */ ++ depctl.d32 = DWC_READ_REG32(addr); ++ ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ ++ DWC_WRITE_REG32(addr, depctl.d32); ++ ++ if (core_if->dma_desc_enable && ++ ep->iso_desc_addr && ep->iso_dma_desc_addr) { ++ dwc_otg_ep_free_desc_chain(ep->iso_desc_addr, ++ ep->iso_dma_desc_addr, ++ ep->desc_cnt * 2); ++ } ++ ++ /* reset varibales */ ++ ep->dma_addr0 = 0; ++ ep->dma_addr1 = 0; ++ ep->xfer_buff0 = 0; ++ ep->xfer_buff1 = 0; ++ ep->data_per_frame = 0; ++ ep->data_pattern_frame = 0; ++ ep->sync_frame = 0; ++ ep->buf_proc_intrvl = 0; ++ ep->bInterval = 0; ++ ep->proc_buf_num = 0; ++ ep->pkt_per_frm = 0; ++ ep->pkt_per_frm = 0; ++ ep->desc_cnt = 0; ++ ep->iso_desc_addr = 0; ++ ep->iso_dma_desc_addr = 0; ++} ++ ++int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf0, uint8_t * buf1, dwc_dma_t dma0, ++ dwc_dma_t dma1, int sync_frame, int dp_frame, ++ int data_per_frame, int start_frame, ++ int buf_proc_intrvl, void *req_handle, ++ int atomic_alloc) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ dwc_irqflags_t flags = 0; ++ dwc_ep_t *dwc_ep; ++ int32_t frm_data; ++ dsts_data_t dsts; ++ dwc_otg_core_if_t *core_if; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ ++ if (!ep || !ep->desc || ep->dwc_ep.num == 0) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ core_if = GET_CORE_IF(pcd); ++ dwc_ep = &ep->dwc_ep; ++ ++ if (ep->iso_req_handle) { ++ DWC_WARN("ISO request in progress\n"); ++ } ++ ++ dwc_ep->dma_addr0 = dma0; ++ dwc_ep->dma_addr1 = dma1; ++ ++ dwc_ep->xfer_buff0 = buf0; ++ dwc_ep->xfer_buff1 = buf1; ++ ++ dwc_ep->data_per_frame = data_per_frame; ++ ++ /** @todo - pattern data support is to be implemented in the future */ ++ dwc_ep->data_pattern_frame = dp_frame; ++ dwc_ep->sync_frame = sync_frame; ++ ++ dwc_ep->buf_proc_intrvl = buf_proc_intrvl; ++ ++ dwc_ep->bInterval = 1 << (ep->desc->bInterval - 1); ++ ++ dwc_ep->proc_buf_num = 0; ++ ++ dwc_ep->pkt_per_frm = 0; ++ frm_data = ep->dwc_ep.data_per_frame; ++ while (frm_data > 0) { ++ dwc_ep->pkt_per_frm++; ++ frm_data -= ep->dwc_ep.maxpacket; ++ } ++ ++ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ if (start_frame == -1) { ++ dwc_ep->next_frame = dsts.b.soffn + 1; ++ if (dwc_ep->bInterval != 1) { ++ dwc_ep->next_frame = ++ dwc_ep->next_frame + (dwc_ep->bInterval - 1 - ++ dwc_ep->next_frame % ++ dwc_ep->bInterval); ++ } ++ } else { ++ dwc_ep->next_frame = start_frame; ++ } ++ ++ if (!core_if->pti_enh_enable) { ++ dwc_ep->pkt_cnt = ++ dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm / ++ dwc_ep->bInterval; ++ } else { ++ dwc_ep->pkt_cnt = ++ (dwc_ep->data_per_frame * ++ (dwc_ep->buf_proc_intrvl / dwc_ep->bInterval) ++ - 1 + dwc_ep->maxpacket) / dwc_ep->maxpacket; ++ } ++ ++ if (core_if->dma_desc_enable) { ++ dwc_ep->desc_cnt = ++ dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm / ++ dwc_ep->bInterval; ++ } ++ ++ if (atomic_alloc) { ++ dwc_ep->pkt_info = ++ DWC_ALLOC_ATOMIC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); ++ } else { ++ dwc_ep->pkt_info = ++ DWC_ALLOC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); ++ } ++ if (!dwc_ep->pkt_info) { ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return -DWC_E_NO_MEMORY; ++ } ++ if (core_if->pti_enh_enable) { ++ dwc_memset(dwc_ep->pkt_info, 0, ++ sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); ++ } ++ ++ dwc_ep->cur_pkt = 0; ++ ep->iso_req_handle = req_handle; ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ dwc_otg_iso_ep_start_transfer(core_if, dwc_ep); ++ return 0; ++} ++ ++int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle) ++{ ++ dwc_irqflags_t flags = 0; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep || !ep->desc || ep->dwc_ep.num == 0) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ dwc_ep = &ep->dwc_ep; ++ ++ dwc_otg_iso_ep_stop_transfer(GET_CORE_IF(pcd), dwc_ep); ++ ++ DWC_FREE(dwc_ep->pkt_info); ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ if (ep->iso_req_handle != req_handle) { ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ ep->iso_req_handle = 0; ++ return 0; ++} ++ ++/** ++ * This function is used for perodical data exchnage between PCD and gadget drivers. ++ * for Isochronous EPs ++ * ++ * - Every time a sync period completes this function is called to ++ * perform data exchange between PCD and gadget ++ */ ++void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep, ++ void *req_handle) ++{ ++ int i; ++ dwc_ep_t *dwc_ep; ++ ++ dwc_ep = &ep->dwc_ep; ++ ++ DWC_SPINUNLOCK(ep->pcd->lock); ++ pcd->fops->isoc_complete(pcd, ep->priv, ep->iso_req_handle, ++ dwc_ep->proc_buf_num ^ 0x1); ++ DWC_SPINLOCK(ep->pcd->lock); ++ ++ for (i = 0; i < dwc_ep->pkt_cnt; ++i) { ++ dwc_ep->pkt_info[i].status = 0; ++ dwc_ep->pkt_info[i].offset = 0; ++ dwc_ep->pkt_info[i].length = 0; ++ } ++} ++ ++int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *iso_req_handle) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep->desc || ep->dwc_ep.num == 0) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ dwc_ep = &ep->dwc_ep; ++ ++ return dwc_ep->pkt_cnt; ++} ++ ++void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *iso_req_handle, int packet, ++ int *status, int *actual, int *offset) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep) ++ DWC_WARN("bad ep\n"); ++ ++ dwc_ep = &ep->dwc_ep; ++ ++ *status = dwc_ep->pkt_info[packet].status; ++ *actual = dwc_ep->pkt_info[packet].length; ++ *offset = dwc_ep->pkt_info[packet].offset; ++} ++ ++#endif /* DWC_EN_ISOC */ ++ ++static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep, ++ uint32_t is_in, uint32_t ep_num) ++{ ++ /* Init EP structure */ ++ pcd_ep->desc = 0; ++ pcd_ep->pcd = pcd; ++ pcd_ep->stopped = 1; ++ pcd_ep->queue_sof = 0; ++ ++ /* Init DWC ep structure */ ++ pcd_ep->dwc_ep.is_in = is_in; ++ pcd_ep->dwc_ep.num = ep_num; ++ pcd_ep->dwc_ep.active = 0; ++ pcd_ep->dwc_ep.tx_fifo_num = 0; ++ /* Control until ep is actvated */ ++ pcd_ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL; ++ pcd_ep->dwc_ep.maxpacket = MAX_PACKET_SIZE; ++ pcd_ep->dwc_ep.dma_addr = 0; ++ pcd_ep->dwc_ep.start_xfer_buff = 0; ++ pcd_ep->dwc_ep.xfer_buff = 0; ++ pcd_ep->dwc_ep.xfer_len = 0; ++ pcd_ep->dwc_ep.xfer_count = 0; ++ pcd_ep->dwc_ep.sent_zlp = 0; ++ pcd_ep->dwc_ep.total_len = 0; ++ pcd_ep->dwc_ep.desc_addr = 0; ++ pcd_ep->dwc_ep.dma_desc_addr = 0; ++ DWC_CIRCLEQ_INIT(&pcd_ep->queue); ++} ++ ++/** ++ * Initialize ep's ++ */ ++static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd) ++{ ++ int i; ++ uint32_t hwcfg1; ++ dwc_otg_pcd_ep_t *ep; ++ int in_ep_cntr, out_ep_cntr; ++ uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps; ++ uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps; ++ ++ /** ++ * Initialize the EP0 structure. ++ */ ++ ep = &pcd->ep0; ++ dwc_otg_pcd_init_ep(pcd, ep, 0, 0); ++ ++ in_ep_cntr = 0; ++ hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3; ++ for (i = 1; in_ep_cntr < num_in_eps; i++) { ++ if ((hwcfg1 & 0x1) == 0) { ++ dwc_otg_pcd_ep_t *ep = &pcd->in_ep[in_ep_cntr]; ++ in_ep_cntr++; ++ /** ++ * @todo NGS: Add direction to EP, based on contents ++ * of HWCFG1. Need a copy of HWCFG1 in pcd structure? ++ * sprintf(";r ++ */ ++ dwc_otg_pcd_init_ep(pcd, ep, 1 /* IN */ , i); ++ ++ DWC_CIRCLEQ_INIT(&ep->queue); ++ } ++ hwcfg1 >>= 2; ++ } ++ ++ out_ep_cntr = 0; ++ hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2; ++ for (i = 1; out_ep_cntr < num_out_eps; i++) { ++ if ((hwcfg1 & 0x1) == 0) { ++ dwc_otg_pcd_ep_t *ep = &pcd->out_ep[out_ep_cntr]; ++ out_ep_cntr++; ++ /** ++ * @todo NGS: Add direction to EP, based on contents ++ * of HWCFG1. Need a copy of HWCFG1 in pcd structure? ++ * sprintf(";r ++ */ ++ dwc_otg_pcd_init_ep(pcd, ep, 0 /* OUT */ , i); ++ DWC_CIRCLEQ_INIT(&ep->queue); ++ } ++ hwcfg1 >>= 2; ++ } ++ ++ pcd->ep0state = EP0_DISCONNECT; ++ pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE; ++ pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL; ++} ++ ++/** ++ * This function is called when the SRP timer expires. The SRP should ++ * complete within 6 seconds. ++ */ ++static void srp_timeout(void *ptr) ++{ ++ gotgctl_data_t gotgctl; ++ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; ++ volatile uint32_t *addr = &core_if->core_global_regs->gotgctl; ++ ++ gotgctl.d32 = DWC_READ_REG32(addr); ++ ++ core_if->srp_timer_started = 0; ++ ++ if (core_if->adp_enable) { ++ if (gotgctl.b.bsesvld == 0) { ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ DWC_PRINTF("SRP Timeout BSESSVLD = 0\n"); ++ /* Power off the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ } ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, ++ gpwrdn.d32); ++ dwc_otg_adp_probe_start(core_if); ++ } else { ++ DWC_PRINTF("SRP Timeout BSESSVLD = 1\n"); ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } ++ } ++ ++ if ((core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) && ++ (core_if->core_params->i2c_enable)) { ++ DWC_PRINTF("SRP Timeout\n"); ++ ++ if ((core_if->srp_success) && (gotgctl.b.bsesvld)) { ++ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); ++ } ++ ++ /* Clear Session Request */ ++ gotgctl.d32 = 0; ++ gotgctl.b.sesreq = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, ++ gotgctl.d32, 0); ++ ++ core_if->srp_success = 0; ++ } else { ++ __DWC_ERROR("Device not connected/responding\n"); ++ gotgctl.b.sesreq = 0; ++ DWC_WRITE_REG32(addr, gotgctl.d32); ++ } ++ } else if (gotgctl.b.sesreq) { ++ DWC_PRINTF("SRP Timeout\n"); ++ ++ __DWC_ERROR("Device not connected/responding\n"); ++ gotgctl.b.sesreq = 0; ++ DWC_WRITE_REG32(addr, gotgctl.d32); ++ } else { ++ DWC_PRINTF(" SRP GOTGCTL=%0x\n", gotgctl.d32); ++ } ++} ++ ++/** ++ * Tasklet ++ * ++ */ ++extern void start_next_request(dwc_otg_pcd_ep_t * ep); ++ ++static void start_xfer_tasklet_func(void *data) ++{ ++ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ int i; ++ depctl_data_t diepctl; ++ ++ DWC_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n"); ++ ++ diepctl.d32 = DWC_READ_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl); ++ ++ if (pcd->ep0.queue_sof) { ++ pcd->ep0.queue_sof = 0; ++ start_next_request(&pcd->ep0); ++ // break; ++ } ++ ++ for (i = 0; i < core_if->dev_if->num_in_eps; i++) { ++ depctl_data_t diepctl; ++ diepctl.d32 = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl); ++ ++ if (pcd->in_ep[i].queue_sof) { ++ pcd->in_ep[i].queue_sof = 0; ++ start_next_request(&pcd->in_ep[i]); ++ // break; ++ } ++ } ++ ++ return; ++} ++ ++/** ++ * This function initialized the PCD portion of the driver. ++ * ++ */ ++dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_pcd_t *pcd = NULL; ++ dwc_otg_dev_if_t *dev_if; ++ int i; ++ ++ /* ++ * Allocate PCD structure ++ */ ++ pcd = DWC_ALLOC(sizeof(dwc_otg_pcd_t)); ++ ++ if (pcd == NULL) { ++ return NULL; ++ } ++ ++ pcd->lock = DWC_SPINLOCK_ALLOC(); ++ if (!pcd->lock) { ++ DWC_ERROR("Could not allocate lock for pcd"); ++ DWC_FREE(pcd); ++ return NULL; ++ } ++ /* Set core_if's lock pointer to hcd->lock */ ++ core_if->lock = pcd->lock; ++ pcd->core_if = core_if; ++ ++ dev_if = core_if->dev_if; ++ dev_if->isoc_ep = NULL; ++ ++ if (core_if->hwcfg4.b.ded_fifo_en) { ++ DWC_PRINTF("Dedicated Tx FIFOs mode\n"); ++ } else { ++ DWC_PRINTF("Shared Tx FIFO mode\n"); ++ } ++ ++ /* ++ * Initialized the Core for Device mode here if there is nod ADP support. ++ * Otherwise it will be done later in dwc_otg_adp_start routine. ++ */ ++ if (dwc_otg_is_device_mode(core_if) /*&& !core_if->adp_enable */ ) { ++ dwc_otg_core_dev_init(core_if); ++ } ++ ++ /* ++ * Register the PCD Callbacks. ++ */ ++ dwc_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd); ++ ++ /* ++ * Initialize the DMA buffer for SETUP packets ++ */ ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ pcd->setup_pkt = ++ DWC_DMA_ALLOC(sizeof(*pcd->setup_pkt) * 5, ++ &pcd->setup_pkt_dma_handle); ++ if (pcd->setup_pkt == NULL) { ++ DWC_FREE(pcd); ++ return NULL; ++ } ++ ++ pcd->status_buf = ++ DWC_DMA_ALLOC(sizeof(uint16_t), ++ &pcd->status_buf_dma_handle); ++ if (pcd->status_buf == NULL) { ++ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, ++ pcd->setup_pkt, pcd->setup_pkt_dma_handle); ++ DWC_FREE(pcd); ++ return NULL; ++ } ++ ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ dev_if->setup_desc_addr[0] = ++ dwc_otg_ep_alloc_desc_chain ++ (&dev_if->dma_setup_desc_addr[0], 1); ++ dev_if->setup_desc_addr[1] = ++ dwc_otg_ep_alloc_desc_chain ++ (&dev_if->dma_setup_desc_addr[1], 1); ++ dev_if->in_desc_addr = ++ dwc_otg_ep_alloc_desc_chain ++ (&dev_if->dma_in_desc_addr, 1); ++ dev_if->out_desc_addr = ++ dwc_otg_ep_alloc_desc_chain ++ (&dev_if->dma_out_desc_addr, 1); ++ pcd->data_terminated = 0; ++ ++ if (dev_if->setup_desc_addr[0] == 0 ++ || dev_if->setup_desc_addr[1] == 0 ++ || dev_if->in_desc_addr == 0 ++ || dev_if->out_desc_addr == 0) { ++ ++ if (dev_if->out_desc_addr) ++ dwc_otg_ep_free_desc_chain ++ (dev_if->out_desc_addr, ++ dev_if->dma_out_desc_addr, 1); ++ if (dev_if->in_desc_addr) ++ dwc_otg_ep_free_desc_chain ++ (dev_if->in_desc_addr, ++ dev_if->dma_in_desc_addr, 1); ++ if (dev_if->setup_desc_addr[1]) ++ dwc_otg_ep_free_desc_chain ++ (dev_if->setup_desc_addr[1], ++ dev_if->dma_setup_desc_addr[1], 1); ++ if (dev_if->setup_desc_addr[0]) ++ dwc_otg_ep_free_desc_chain ++ (dev_if->setup_desc_addr[0], ++ dev_if->dma_setup_desc_addr[0], 1); ++ ++ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, ++ pcd->setup_pkt, ++ pcd->setup_pkt_dma_handle); ++ DWC_DMA_FREE(sizeof(*pcd->status_buf), ++ pcd->status_buf, ++ pcd->status_buf_dma_handle); ++ ++ DWC_FREE(pcd); ++ ++ return NULL; ++ } ++ } ++ } else { ++ pcd->setup_pkt = DWC_ALLOC(sizeof(*pcd->setup_pkt) * 5); ++ if (pcd->setup_pkt == NULL) { ++ DWC_FREE(pcd); ++ return NULL; ++ } ++ ++ pcd->status_buf = DWC_ALLOC(sizeof(uint16_t)); ++ if (pcd->status_buf == NULL) { ++ DWC_FREE(pcd->setup_pkt); ++ DWC_FREE(pcd); ++ return NULL; ++ } ++ } ++ ++ dwc_otg_pcd_reinit(pcd); ++ ++ /* Allocate the cfi object for the PCD */ ++#ifdef DWC_UTE_CFI ++ pcd->cfi = DWC_ALLOC(sizeof(cfiobject_t)); ++ if (NULL == pcd->cfi) ++ goto fail; ++ if (init_cfi(pcd->cfi)) { ++ CFI_INFO("%s: Failed to init the CFI object\n", __func__); ++ goto fail; ++ } ++#endif ++ ++ /* Initialize tasklets */ ++ pcd->start_xfer_tasklet = DWC_TASK_ALLOC("xfer_tasklet", ++ start_xfer_tasklet_func, pcd); ++ pcd->test_mode_tasklet = DWC_TASK_ALLOC("test_mode_tasklet", ++ do_test_mode, pcd); ++ ++ /* Initialize SRP timer */ ++ core_if->srp_timer = DWC_TIMER_ALLOC("SRP TIMER", srp_timeout, core_if); ++ ++ if (core_if->core_params->dev_out_nak) { ++ /** ++ * Initialize xfer timeout timer. Implemented for ++ * 2.93a feature "Device DDMA OUT NAK Enhancement" ++ */ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ pcd->core_if->ep_xfer_timer[i] = ++ DWC_TIMER_ALLOC("ep timer", ep_xfer_timeout, ++ &pcd->core_if->ep_xfer_info[i]); ++ } ++ } ++ ++ return pcd; ++#ifdef DWC_UTE_CFI ++fail: ++#endif ++ if (pcd->setup_pkt) ++ DWC_FREE(pcd->setup_pkt); ++ if (pcd->status_buf) ++ DWC_FREE(pcd->status_buf); ++#ifdef DWC_UTE_CFI ++ if (pcd->cfi) ++ DWC_FREE(pcd->cfi); ++#endif ++ if (pcd) ++ DWC_FREE(pcd); ++ return NULL; ++ ++} ++ ++/** ++ * Remove PCD specific data ++ */ ++void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ int i; ++ if (pcd->core_if->core_params->dev_out_nak) { ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[i]); ++ pcd->core_if->ep_xfer_info[i].state = 0; ++ } ++ } ++ ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt, ++ pcd->setup_pkt_dma_handle); ++ DWC_DMA_FREE(sizeof(uint16_t), pcd->status_buf, ++ pcd->status_buf_dma_handle); ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0], ++ dev_if->dma_setup_desc_addr ++ [0], 1); ++ dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1], ++ dev_if->dma_setup_desc_addr ++ [1], 1); ++ dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr, ++ dev_if->dma_in_desc_addr, 1); ++ dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr, ++ dev_if->dma_out_desc_addr, ++ 1); ++ } ++ } else { ++ DWC_FREE(pcd->setup_pkt); ++ DWC_FREE(pcd->status_buf); ++ } ++ DWC_SPINLOCK_FREE(pcd->lock); ++ /* Set core_if's lock pointer to NULL */ ++ pcd->core_if->lock = NULL; ++ ++ DWC_TASK_FREE(pcd->start_xfer_tasklet); ++ DWC_TASK_FREE(pcd->test_mode_tasklet); ++ if (pcd->core_if->core_params->dev_out_nak) { ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ if (pcd->core_if->ep_xfer_timer[i]) { ++ DWC_TIMER_FREE(pcd->core_if->ep_xfer_timer[i]); ++ } ++ } ++ } ++ ++/* Release the CFI object's dynamic memory */ ++#ifdef DWC_UTE_CFI ++ if (pcd->cfi->ops.release) { ++ pcd->cfi->ops.release(pcd->cfi); ++ } ++#endif ++ ++ DWC_FREE(pcd); ++} ++ ++/** ++ * Returns whether registered pcd is dual speed or not ++ */ ++uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) || ++ ((core_if->hwcfg2.b.hs_phy_type == 2) && ++ (core_if->hwcfg2.b.fs_phy_type == 1) && ++ (core_if->core_params->ulpi_fs_ls))) { ++ return 0; ++ } ++ ++ return 1; ++} ++ ++/** ++ * Returns whether registered pcd is OTG capable or not ++ */ ++uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ gusbcfg_data_t usbcfg = {.d32 = 0 }; ++ uint32_t retval = 0; ++ ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) ++ if (!usbcfg.b.srpcap || !usbcfg.b.hnpcap) ++ return 0; ++ else ++ return 1; ++# else ++ if (!usbcfg.b.srpcap) ++ return 0; ++ else ++ retval |= 1; ++ ++ if (usbcfg.b.hnpcap) ++ retval |= 2; ++ ++ if (core_if->adp_enable) ++ retval |= 4; ++#endif ++ ++ return retval; ++} ++ ++/** ++ * This function assigns periodic Tx FIFO to an periodic EP ++ * in shared Tx FIFO mode ++ */ ++static uint32_t assign_tx_fifo(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t TxMsk = 1; ++ int i; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++i) { ++ if ((TxMsk & core_if->tx_msk) == 0) { ++ core_if->tx_msk |= TxMsk; ++ return i + 1; ++ } ++ TxMsk <<= 1; ++ } ++ return 0; ++} ++ ++/** ++ * This function assigns periodic Tx FIFO to an periodic EP ++ * in shared Tx FIFO mode ++ */ ++static uint32_t assign_perio_tx_fifo(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t PerTxMsk = 1; ++ int i; ++ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; ++i) { ++ if ((PerTxMsk & core_if->p_tx_msk) == 0) { ++ core_if->p_tx_msk |= PerTxMsk; ++ return i + 1; ++ } ++ PerTxMsk <<= 1; ++ } ++ return 0; ++} ++ ++/** ++ * This function releases periodic Tx FIFO ++ * in shared Tx FIFO mode ++ */ ++static void release_perio_tx_fifo(dwc_otg_core_if_t * core_if, ++ uint32_t fifo_num) ++{ ++ core_if->p_tx_msk = ++ (core_if->p_tx_msk & (1 << (fifo_num - 1))) ^ core_if->p_tx_msk; ++} ++ ++/** ++ * This function releases periodic Tx FIFO ++ * in shared Tx FIFO mode ++ */ ++static void release_tx_fifo(dwc_otg_core_if_t * core_if, uint32_t fifo_num) ++{ ++ core_if->tx_msk = ++ (core_if->tx_msk & (1 << (fifo_num - 1))) ^ core_if->tx_msk; ++} ++ ++/** ++ * This function is being called from gadget ++ * to enable PCD endpoint. ++ */ ++int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, ++ const uint8_t * ep_desc, void *usb_ep) ++{ ++ int num, dir; ++ dwc_otg_pcd_ep_t *ep = NULL; ++ const usb_endpoint_descriptor_t *desc; ++ dwc_irqflags_t flags; ++ fifosize_data_t dptxfsiz = {.d32 = 0 }; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; ++ int retval = 0; ++ int i, epcount; ++ ++ desc = (const usb_endpoint_descriptor_t *)ep_desc; ++ ++ if (!desc) { ++ pcd->ep0.priv = usb_ep; ++ retval = -DWC_E_INVALID; ++ goto out; ++ } ++ ++ num = UE_GET_ADDR(desc->bEndpointAddress); ++ dir = UE_GET_DIR(desc->bEndpointAddress); ++ ++ if (dir == UE_DIR_IN) { ++ epcount = pcd->core_if->dev_if->num_in_eps; ++ for (i = 0; i < epcount; i++) { ++ if (num == pcd->in_ep[i].dwc_ep.num) { ++ ep = &pcd->in_ep[i]; ++ break; ++ } ++ } ++ } else { ++ epcount = pcd->core_if->dev_if->num_out_eps; ++ for (i = 0; i < epcount; i++) { ++ if (num == pcd->out_ep[i].dwc_ep.num) { ++ ep = &pcd->out_ep[i]; ++ break; ++ } ++ } ++ } ++ ++ if (!ep) { ++ DWC_WARN("bad address\n"); ++ retval = -DWC_E_INVALID; ++ goto out; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ ep->desc = desc; ++ ep->priv = usb_ep; ++ ++ /* ++ * Activate the EP ++ */ ++ ep->stopped = 0; ++ ++ ep->dwc_ep.is_in = (dir == UE_DIR_IN); ++ ep->dwc_ep.maxpacket = UGETW(desc->wMaxPacketSize); ++ ++ ep->dwc_ep.type = desc->bmAttributes & UE_XFERTYPE; ++ if (UE_BULK == ep->dwc_ep.type) ++ bulk_num = ep->dwc_ep.num; ++ ++ if (ep->dwc_ep.is_in) { ++ if (!GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ ep->dwc_ep.tx_fifo_num = 0; ++ ++ if (ep->dwc_ep.type == UE_ISOCHRONOUS) { ++ /* ++ * if ISOC EP then assign a Periodic Tx FIFO. ++ */ ++ ep->dwc_ep.tx_fifo_num = ++ assign_perio_tx_fifo(GET_CORE_IF(pcd)); ++ } ++ } else { ++ /* ++ * if Dedicated FIFOs mode is on then assign a Tx FIFO. ++ */ ++ ep->dwc_ep.tx_fifo_num = ++ assign_tx_fifo(GET_CORE_IF(pcd)); ++ } ++ ++ /* Calculating EP info controller base address */ ++ if (ep->dwc_ep.tx_fifo_num ++ && GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ gdfifocfg.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)-> ++ core_global_regs->gdfifocfg); ++ gdfifocfgbase.d32 = gdfifocfg.d32 >> 16; ++ dptxfsiz.d32 = ++ (DWC_READ_REG32 ++ (&GET_CORE_IF(pcd)->core_global_regs-> ++ dtxfsiz[ep->dwc_ep.tx_fifo_num - 1]) >> 16); ++ gdfifocfg.b.epinfobase = ++ gdfifocfgbase.d32 + dptxfsiz.d32; ++ if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) { ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)-> ++ core_global_regs->gdfifocfg, ++ gdfifocfg.d32); ++ } ++ } ++ } ++ /* Set initial data PID. */ ++ if (ep->dwc_ep.type == UE_BULK) { ++ ep->dwc_ep.data_pid_start = 0; ++ } ++ ++ /* Alloc DMA Descriptors */ ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++#ifndef DWC_UTE_PER_IO ++ if (ep->dwc_ep.type != UE_ISOCHRONOUS) { ++#endif ++ ep->dwc_ep.desc_addr = ++ dwc_otg_ep_alloc_desc_chain(&ep-> ++ dwc_ep.dma_desc_addr, ++ MAX_DMA_DESC_CNT); ++ if (!ep->dwc_ep.desc_addr) { ++ DWC_WARN("%s, can't allocate DMA descriptor\n", ++ __func__); ++ retval = -DWC_E_SHUTDOWN; ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ goto out; ++ } ++#ifndef DWC_UTE_PER_IO ++ } else { ++ ep->dwc_ep.desc_addr = ++ dwc_otg_ep_alloc_desc_chain(&ep-> ++ dwc_ep.dma_desc_addr, ++ MAX_DMA_DESC_CNT/2); ++ ep->dwc_ep.desc_addr1 = ++ dwc_otg_ep_alloc_desc_chain(&ep-> ++ dwc_ep.dma_desc_addr1, ++ MAX_DMA_DESC_CNT/2); ++ if (!ep->dwc_ep.desc_addr || !ep->dwc_ep.desc_addr1) { ++ DWC_WARN("%s, can't allocate DMA descriptor\n", ++ __func__); ++ retval = -DWC_E_SHUTDOWN; ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ goto out; ++ } ++ /* Set initial data PID. */ ++ if (ep->dwc_ep.type == UE_ISOCHRONOUS) { ++ ep->dwc_ep.iso_desc_first = 0; ++ ep->dwc_ep.iso_desc_second = 0; ++ ep->dwc_ep.iso_transfer_started = 0; ++ } ++ } ++#endif ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "Activate %s: type=%d, mps=%d desc=%p\n", ++ (ep->dwc_ep.is_in ? "IN" : "OUT"), ++ ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc); ++#ifdef DWC_UTE_PER_IO ++ ep->dwc_ep.xiso_bInterval = 1 << (ep->desc->bInterval - 1); ++#endif ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ ep->dwc_ep.bInterval = 1 << (ep->desc->bInterval - 1); ++ ep->dwc_ep.frame_num = 0xFFFFFFFF; ++ } ++ ++ dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep); ++ ++#ifdef DWC_UTE_CFI ++ if (pcd->cfi->ops.ep_enable) { ++ pcd->cfi->ops.ep_enable(pcd->cfi, pcd, ep); ++ } ++#endif ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++out: ++ return retval; ++} ++ ++/** ++ * This function is being called from gadget ++ * to disable PCD endpoint. ++ */ ++int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ dwc_irqflags_t flags; ++ dwc_otg_dev_dma_desc_t *desc_addr; ++ dwc_dma_t dma_desc_addr; ++ gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ fifosize_data_t dptxfsiz = {.d32 = 0 }; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ ++ if (!ep || !ep->desc) { ++ DWC_DEBUGPL(DBG_PCD, "bad ep address\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ dwc_otg_request_nuke(ep); ++ ++ dwc_otg_ep_deactivate(GET_CORE_IF(pcd), &ep->dwc_ep); ++ if (pcd->core_if->core_params->dev_out_nak) { ++ DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[ep->dwc_ep.num]); ++ pcd->core_if->ep_xfer_info[ep->dwc_ep.num].state = 0; ++ } ++ ep->desc = NULL; ++ ep->stopped = 1; ++ ++ gdfifocfg.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg); ++ gdfifocfgbase.d32 = gdfifocfg.d32 >> 16; ++ ++ if (ep->dwc_ep.is_in) { ++ if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ /* Flush the Tx FIFO */ ++ dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), ++ ep->dwc_ep.tx_fifo_num); ++ } ++ release_perio_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); ++ release_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); ++ if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ /* Decreasing EPinfo Base Addr */ ++ dptxfsiz.d32 = ++ (DWC_READ_REG32 ++ (&GET_CORE_IF(pcd)-> ++ core_global_regs->dtxfsiz[ep->dwc_ep.tx_fifo_num-1]) >> 16); ++ gdfifocfg.b.epinfobase = gdfifocfgbase.d32 - dptxfsiz.d32; ++ if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) { ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg, ++ gdfifocfg.d32); ++ } ++ } ++ } ++ ++ /* Free DMA Descriptors */ ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ if (ep->dwc_ep.type != UE_ISOCHRONOUS) { ++ desc_addr = ep->dwc_ep.desc_addr; ++ dma_desc_addr = ep->dwc_ep.dma_desc_addr; ++ ++ /* Cannot call dma_free_coherent() with IRQs disabled */ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr, ++ MAX_DMA_DESC_CNT); ++ ++ } else { ++ desc_addr = ep->dwc_ep.desc_addr; ++ dma_desc_addr = ep->dwc_ep.dma_desc_addr; ++ ++ /* Cannot call dma_free_coherent() with IRQs disabled */ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr, ++ MAX_DMA_DESC_CNT/2); ++ desc_addr = ep->dwc_ep.desc_addr1; ++ dma_desc_addr = ep->dwc_ep.dma_desc_addr1; ++ dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr, ++ MAX_DMA_DESC_CNT/2); ++ } ++ goto out_unlocked; ++ } ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++out_unlocked: ++ DWC_DEBUGPL(DBG_PCD, "%d %s disabled\n", ep->dwc_ep.num, ++ ep->dwc_ep.is_in ? "IN" : "OUT"); ++ return 0; ++ ++} ++ ++/** ++ * This function initializes dma descriptor chain for ISOC transfers. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++void dwc_otg_pcd_start_iso_ddma(dwc_otg_core_if_t * core_if, dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ dwc_otg_pcd_request_t *req = NULL; ++ dwc_ep_t *dwcep = NULL; ++ uint32_t frame_num = 0; ++ int i = 0; ++ int j; ++ int sync_request = 4; ++ uint16_t nat; ++ depctl_data_t depctl; ++ ++ dwcep = &ep->dwc_ep; ++ dma_desc = dwcep->desc_addr; ++ ++ nat = UGETW(ep->desc->wMaxPacketSize); ++ nat = (nat >> 11) & 0x03; ++ DWC_DEBUGPL(DBG_PCD, "nat=%u binterval =%02x\n",nat, dwcep->bInterval); ++ DWC_DEBUGPL(DBG_PCD, "frame_num = %d\n", dwcep->frame_num); ++ ++ /* Complete first three IN EP requests for the synchronization */ ++ if (dwcep->is_in) { ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ for (j = 0; j < sync_request; j++) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ DWC_PRINTF("ISOC 0x%p, req = NULL!\n", ep); ++ return; ++ } else { ++ /* Complete first request */ ++ req->actual = 0; ++ dwc_otg_request_done(ep, req, 0); ++ } ++ } ++ } else { ++ DWC_PRINTF("ISOC ep 0x%p, ep->queue empty!\n", ep); ++ return; ++ } ++ ++ frame_num = dwcep->frame_num + (sync_request -1)*dwcep->bInterval; ++ ++ DWC_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) { ++ i = i+1; ++ frame_num = (frame_num + dwcep->bInterval) & 0x3FFF; ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b_iso_in.bs = BS_HOST_BUSY; ++ dma_desc->buf = req->dma; ++ dma_desc->status.b_iso_in.txbytes = req->length; ++ dma_desc->status.b_iso_in.framenum = frame_num; ++ dma_desc->status.b_iso_in.txsts = 0; ++ dma_desc->status.b_iso_in.sp = (req->length % dwcep->maxpacket) ? 1 : 0; ++ dma_desc->status.b_iso_in.ioc = 1; ++ dma_desc->status.b_iso_in.pid = nat + 1; ++ dma_desc->status.b_iso_in.l = 0; ++ ++ if (req == DWC_CIRCLEQ_LAST(&ep->queue)) { ++ dma_desc->status.b_iso_in.l = 1; ++ } ++ dma_desc->status.b_iso_in.bs = BS_HOST_READY; ++ DWC_DEBUGPL(DBG_PCD, "ISO_DESC #%d %p status = %08x\n", i, dma_desc, dma_desc->status.d32); ++ if (i == MAX_DMA_DESC_CNT/2 - 1) { ++ dma_desc->status.b_iso_in.l = 1; ++ break; ++ } ++ dma_desc++; ++ } ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[dwcep->num]->diepdma, dwcep->dma_desc_addr); ++ DWC_DEBUGPL(DBG_PCD, "%d ISOC IN descs were programmed\n", i-1); ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->in_ep_regs[dwcep->num]->diepctl, 0, depctl.d32); ++ } else { ++ DWC_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) { ++ i = i+1; ++ frame_num = (frame_num + dwcep->bInterval) & 0x3FFF; ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b_iso_out.bs = BS_HOST_BUSY; ++ dma_desc->buf = req->dma; ++ dma_desc->status.b_iso_out.rxbytes = req->length; ++ dma_desc->status.b_iso_out.rxsts = 0; ++ dma_desc->status.b_iso_out.sp = (req->length % dwcep->maxpacket) ? 1 : 0; ++ dma_desc->status.b_iso_out.ioc = 1; ++ dma_desc->status.b_iso_out.pid = nat + 1; ++ dma_desc->status.b_iso_out.l = 0; ++ ++ if (req == DWC_CIRCLEQ_LAST(&ep->queue)) { ++ dma_desc->status.b_iso_out.l = 1; ++ } ++ dma_desc->status.b_iso_in.bs = BS_HOST_READY; ++ DWC_DEBUGPL(DBG_PCD, "ISO_DESC #%d %p status = %08x\n", i, dma_desc, dma_desc->status.d32); ++ if (i == MAX_DMA_DESC_CNT/2 - 1) { ++ dma_desc->status.b_iso_out.l = 1; ++ break; ++ } ++ dma_desc++; ++ } ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwcep->num]->doepdma, dwcep->dma_desc_addr); ++ DWC_DEBUGPL(DBG_PCD, "%d ISOC OUT descs were programmed\n", i-1); ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->out_ep_regs[dwcep->num]->doepctl, 0, depctl.d32); ++ } ++ dwcep->iso_desc_first = i; //vahrama - pay attention previous one was i-1 ++ dwcep->iso_transfer_started = 1; ++ dwcep->frame_num = frame_num; ++ dwcep->use_add_buf = 1; ++} ++/** ++ * Program next ISO request to the DMA chain ++ * ++ */ ++static void program_next_iso_request_ddma (dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req) ++{ ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ dwc_dma_t dma_desc_addr; ++ uint32_t frame_num = 0; ++ uint32_t nat; ++ uint32_t index; ++ ++ DWC_DEBUGPL(DBG_PCD, "%s", __FUNCTION__); ++ ++ if (ep->dwc_ep.use_add_buf) { ++ index = ep->dwc_ep.iso_desc_second + 1; ++ } else { ++ index = ep->dwc_ep.iso_desc_first + 1; ++ } ++ ++ if (index > MAX_DMA_DESC_CNT/2) { ++ DWC_PRINTF("There are no free descs in the chain!\n"); ++ return; ++ } ++ ++ if (ep->dwc_ep.use_add_buf) { ++ dma_desc = &ep->dwc_ep.desc_addr1[ep->dwc_ep.iso_desc_second]; ++ dma_desc_addr = ep->dwc_ep.dma_desc_addr1; ++ ep->dwc_ep.iso_desc_second += 1; ++ } else { ++ dma_desc = &ep->dwc_ep.desc_addr[ep->dwc_ep.iso_desc_first]; ++ dma_desc_addr = ep->dwc_ep.dma_desc_addr; ++ ep->dwc_ep.iso_desc_first += 1; ++ } ++ nat = (req->length + ep->dwc_ep.maxpacket - 1) ++ / ep->dwc_ep.maxpacket; ++ ++ if (nat) ++ nat--; ++ frame_num = (ep->dwc_ep.frame_num + ep->dwc_ep.bInterval) & 0x3FFF; ++ if (ep->dwc_ep.is_in) { ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b_iso_in.bs = BS_HOST_BUSY; ++ dma_desc->buf = req->dma; ++ dma_desc->status.b_iso_in.txbytes = req->length; ++ dma_desc->status.b_iso_in.framenum = frame_num; ++ dma_desc->status.b_iso_in.txsts = 0; ++ dma_desc->status.b_iso_in.sp = (req->length % ep->dwc_ep.maxpacket) ? 1 : 0; ++ dma_desc->status.b_iso_in.ioc = 1; ++ dma_desc->status.b_iso_in.pid = nat + 1; ++ dma_desc->status.b_iso_in.l = 1; ++ ++ dma_desc->status.b_iso_in.bs = BS_HOST_READY; ++ ++ /* Clear L bit on the previous desc of the chain */ ++ if (index > 1) { ++ dma_desc--; ++ dma_desc->status.b_iso_in.l = 0; ++ } ++ } else { ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b_iso_out.bs = BS_HOST_BUSY; ++ dma_desc->buf = req->dma; ++ dma_desc->status.b_iso_out.rxbytes = req->length; ++ dma_desc->status.b_iso_out.rxsts = 0; ++ dma_desc->status.b_iso_out.sp = (req->length % ep->dwc_ep.maxpacket) ? 1 : 0; ++ dma_desc->status.b_iso_out.ioc = 1; ++ dma_desc->status.b_iso_out.pid = nat + 1; ++ dma_desc->status.b_iso_out.l = 1; ++ ++ dma_desc->status.b_iso_out.bs = BS_HOST_READY; ++ ++ /* Clear L bit on the previous desc of the chain */ ++ if (index > 1) { ++ dma_desc--; ++ dma_desc->status.b_iso_out.l = 0; ++ } ++ } ++ ep->dwc_ep.frame_num = frame_num; ++ ++} ++ ++/******************************************************************************/ ++#ifdef DWC_UTE_PER_IO ++ ++/** ++ * Free the request and its extended parts ++ * ++ */ ++void dwc_pcd_xiso_ereq_free(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req) ++{ ++ DWC_FREE(req->ext_req.per_io_frame_descs); ++ DWC_FREE(req); ++} ++ ++/** ++ * Start the next request in the endpoint's queue. ++ * ++ */ ++int dwc_otg_pcd_xiso_start_next_request(dwc_otg_pcd_t * pcd, ++ dwc_otg_pcd_ep_t * ep) ++{ ++ int i; ++ dwc_otg_pcd_request_t *req = NULL; ++ dwc_ep_t *dwcep = NULL; ++ struct dwc_iso_xreq_port *ereq = NULL; ++ struct dwc_iso_pkt_desc_port *ddesc_iso; ++ uint16_t nat; ++ depctl_data_t diepctl; ++ ++ dwcep = &ep->dwc_ep; ++ ++ if (dwcep->xiso_active_xfers > 0) { ++#if 0 //Disable this to decrease s/w overhead that is crucial for Isoc transfers ++ DWC_WARN("There are currently active transfers for EP%d \ ++ (active=%d; queued=%d)", dwcep->num, dwcep->xiso_active_xfers, ++ dwcep->xiso_queued_xfers); ++#endif ++ return 0; ++ } ++ ++ nat = UGETW(ep->desc->wMaxPacketSize); ++ nat = (nat >> 11) & 0x03; ++ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ ereq = &req->ext_req; ++ ep->stopped = 0; ++ ++ /* Get the frame number */ ++ dwcep->xiso_frame_num = ++ dwc_otg_get_frame_number(GET_CORE_IF(pcd)); ++ DWC_DEBUG("FRM_NUM=%d", dwcep->xiso_frame_num); ++ ++ ddesc_iso = ereq->per_io_frame_descs; ++ ++ if (dwcep->is_in) { ++ /* Setup DMA Descriptor chain for IN Isoc request */ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ //if ((i % (nat + 1)) == 0) ++ if (i > 0) ++ dwcep->xiso_frame_num = ++ (dwcep->xiso_bInterval + ++ dwcep->xiso_frame_num) & 0x3FFF; ++ dwcep->desc_addr[i].buf = ++ req->dma + ddesc_iso[i].offset; ++ dwcep->desc_addr[i].status.b_iso_in.txbytes = ++ ddesc_iso[i].length; ++ dwcep->desc_addr[i].status.b_iso_in.framenum = ++ dwcep->xiso_frame_num; ++ dwcep->desc_addr[i].status.b_iso_in.bs = ++ BS_HOST_READY; ++ dwcep->desc_addr[i].status.b_iso_in.txsts = 0; ++ dwcep->desc_addr[i].status.b_iso_in.sp = ++ (ddesc_iso[i].length % ++ dwcep->maxpacket) ? 1 : 0; ++ dwcep->desc_addr[i].status.b_iso_in.ioc = 0; ++ dwcep->desc_addr[i].status.b_iso_in.pid = nat + 1; ++ dwcep->desc_addr[i].status.b_iso_in.l = 0; ++ ++ /* Process the last descriptor */ ++ if (i == ereq->pio_pkt_count - 1) { ++ dwcep->desc_addr[i].status.b_iso_in.ioc = 1; ++ dwcep->desc_addr[i].status.b_iso_in.l = 1; ++ } ++ } ++ ++ /* Setup and start the transfer for this endpoint */ ++ dwcep->xiso_active_xfers++; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ in_ep_regs[dwcep->num]->diepdma, ++ dwcep->dma_desc_addr); ++ diepctl.d32 = 0; ++ diepctl.b.epena = 1; ++ diepctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ in_ep_regs[dwcep->num]->diepctl, 0, ++ diepctl.d32); ++ } else { ++ /* Setup DMA Descriptor chain for OUT Isoc request */ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ //if ((i % (nat + 1)) == 0) ++ dwcep->xiso_frame_num = (dwcep->xiso_bInterval + ++ dwcep->xiso_frame_num) & 0x3FFF; ++ dwcep->desc_addr[i].buf = ++ req->dma + ddesc_iso[i].offset; ++ dwcep->desc_addr[i].status.b_iso_out.rxbytes = ++ ddesc_iso[i].length; ++ dwcep->desc_addr[i].status.b_iso_out.framenum = ++ dwcep->xiso_frame_num; ++ dwcep->desc_addr[i].status.b_iso_out.bs = ++ BS_HOST_READY; ++ dwcep->desc_addr[i].status.b_iso_out.rxsts = 0; ++ dwcep->desc_addr[i].status.b_iso_out.sp = ++ (ddesc_iso[i].length % ++ dwcep->maxpacket) ? 1 : 0; ++ dwcep->desc_addr[i].status.b_iso_out.ioc = 0; ++ dwcep->desc_addr[i].status.b_iso_out.pid = nat + 1; ++ dwcep->desc_addr[i].status.b_iso_out.l = 0; ++ ++ /* Process the last descriptor */ ++ if (i == ereq->pio_pkt_count - 1) { ++ dwcep->desc_addr[i].status.b_iso_out.ioc = 1; ++ dwcep->desc_addr[i].status.b_iso_out.l = 1; ++ } ++ } ++ ++ /* Setup and start the transfer for this endpoint */ ++ dwcep->xiso_active_xfers++; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->out_ep_regs[dwcep->num]-> ++ doepdma, dwcep->dma_desc_addr); ++ diepctl.d32 = 0; ++ diepctl.b.epena = 1; ++ diepctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->out_ep_regs[dwcep->num]-> ++ doepctl, 0, diepctl.d32); ++ } ++ ++ } else { ++ ep->stopped = 1; ++ } ++ ++ return 0; ++} ++ ++/** ++ * - Remove the request from the queue ++ */ ++void complete_xiso_ep(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_pcd_request_t *req = NULL; ++ struct dwc_iso_xreq_port *ereq = NULL; ++ struct dwc_iso_pkt_desc_port *ddesc_iso = NULL; ++ dwc_ep_t *dwcep = NULL; ++ int i; ++ ++ //DWC_DEBUG(); ++ dwcep = &ep->dwc_ep; ++ ++ /* Get the first pending request from the queue */ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); ++ return; ++ } ++ dwcep->xiso_active_xfers--; ++ dwcep->xiso_queued_xfers--; ++ /* Remove this request from the queue */ ++ DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry); ++ } else { ++ DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); ++ return; ++ } ++ ++ ep->stopped = 1; ++ ereq = &req->ext_req; ++ ddesc_iso = ereq->per_io_frame_descs; ++ ++ if (dwcep->xiso_active_xfers < 0) { ++ DWC_WARN("EP#%d (xiso_active_xfers=%d)", dwcep->num, ++ dwcep->xiso_active_xfers); ++ } ++ ++ /* Fill the Isoc descs of portable extended req from dma descriptors */ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ if (dwcep->is_in) { /* IN endpoints */ ++ ddesc_iso[i].actual_length = ddesc_iso[i].length - ++ dwcep->desc_addr[i].status.b_iso_in.txbytes; ++ ddesc_iso[i].status = ++ dwcep->desc_addr[i].status.b_iso_in.txsts; ++ } else { /* OUT endpoints */ ++ ddesc_iso[i].actual_length = ddesc_iso[i].length - ++ dwcep->desc_addr[i].status.b_iso_out.rxbytes; ++ ddesc_iso[i].status = ++ dwcep->desc_addr[i].status.b_iso_out.rxsts; ++ } ++ } ++ ++ DWC_SPINUNLOCK(ep->pcd->lock); ++ ++ /* Call the completion function in the non-portable logic */ ++ ep->pcd->fops->xisoc_complete(ep->pcd, ep->priv, req->priv, 0, ++ &req->ext_req); ++ ++ DWC_SPINLOCK(ep->pcd->lock); ++ ++ /* Free the request - specific freeing needed for extended request object */ ++ dwc_pcd_xiso_ereq_free(ep, req); ++ ++ /* Start the next request */ ++ dwc_otg_pcd_xiso_start_next_request(ep->pcd, ep); ++ ++ return; ++} ++ ++/** ++ * Create and initialize the Isoc pkt descriptors of the extended request. ++ * ++ */ ++static int dwc_otg_pcd_xiso_create_pkt_descs(dwc_otg_pcd_request_t * req, ++ void *ereq_nonport, ++ int atomic_alloc) ++{ ++ struct dwc_iso_xreq_port *ereq = NULL; ++ struct dwc_iso_xreq_port *req_mapped = NULL; ++ struct dwc_iso_pkt_desc_port *ipds = NULL; /* To be created in this function */ ++ uint32_t pkt_count; ++ int i; ++ ++ ereq = &req->ext_req; ++ req_mapped = (struct dwc_iso_xreq_port *)ereq_nonport; ++ pkt_count = req_mapped->pio_pkt_count; ++ ++ /* Create the isoc descs */ ++ if (atomic_alloc) { ++ ipds = DWC_ALLOC_ATOMIC(sizeof(*ipds) * pkt_count); ++ } else { ++ ipds = DWC_ALLOC(sizeof(*ipds) * pkt_count); ++ } ++ ++ if (!ipds) { ++ DWC_ERROR("Failed to allocate isoc descriptors"); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ /* Initialize the extended request fields */ ++ ereq->per_io_frame_descs = ipds; ++ ereq->error_count = 0; ++ ereq->pio_alloc_pkt_count = pkt_count; ++ ereq->pio_pkt_count = pkt_count; ++ ereq->tr_sub_flags = req_mapped->tr_sub_flags; ++ ++ /* Init the Isoc descriptors */ ++ for (i = 0; i < pkt_count; i++) { ++ ipds[i].length = req_mapped->per_io_frame_descs[i].length; ++ ipds[i].offset = req_mapped->per_io_frame_descs[i].offset; ++ ipds[i].status = req_mapped->per_io_frame_descs[i].status; /* 0 */ ++ ipds[i].actual_length = ++ req_mapped->per_io_frame_descs[i].actual_length; ++ } ++ ++ return 0; ++} ++ ++static void prn_ext_request(struct dwc_iso_xreq_port *ereq) ++{ ++ struct dwc_iso_pkt_desc_port *xfd = NULL; ++ int i; ++ ++ DWC_DEBUG("per_io_frame_descs=%p", ereq->per_io_frame_descs); ++ DWC_DEBUG("tr_sub_flags=%d", ereq->tr_sub_flags); ++ DWC_DEBUG("error_count=%d", ereq->error_count); ++ DWC_DEBUG("pio_alloc_pkt_count=%d", ereq->pio_alloc_pkt_count); ++ DWC_DEBUG("pio_pkt_count=%d", ereq->pio_pkt_count); ++ DWC_DEBUG("res=%d", ereq->res); ++ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ xfd = &ereq->per_io_frame_descs[0]; ++ DWC_DEBUG("FD #%d", i); ++ ++ DWC_DEBUG("xfd->actual_length=%d", xfd->actual_length); ++ DWC_DEBUG("xfd->length=%d", xfd->length); ++ DWC_DEBUG("xfd->offset=%d", xfd->offset); ++ DWC_DEBUG("xfd->status=%d", xfd->status); ++ } ++} ++ ++/** ++ * ++ */ ++int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen, ++ int zero, void *req_handle, int atomic_alloc, ++ void *ereq_nonport) ++{ ++ dwc_otg_pcd_request_t *req = NULL; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_irqflags_t flags; ++ int res; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ /* We support this extension only for DDMA mode */ ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ++ if (!GET_CORE_IF(pcd)->dma_desc_enable) ++ return -DWC_E_INVALID; ++ ++ /* Create a dwc_otg_pcd_request_t object */ ++ if (atomic_alloc) { ++ req = DWC_ALLOC_ATOMIC(sizeof(*req)); ++ } else { ++ req = DWC_ALLOC(sizeof(*req)); ++ } ++ ++ if (!req) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ /* Create the Isoc descs for this request which shall be the exact match ++ * of the structure sent to us from the non-portable logic */ ++ res = ++ dwc_otg_pcd_xiso_create_pkt_descs(req, ereq_nonport, atomic_alloc); ++ if (res) { ++ DWC_WARN("Failed to init the Isoc descriptors"); ++ DWC_FREE(req); ++ return res; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry); ++ req->buf = buf; ++ req->dma = dma_buf; ++ req->length = buflen; ++ req->sent_zlp = zero; ++ req->priv = req_handle; ++ ++ //DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ep->dwc_ep.dma_addr = dma_buf; ++ ep->dwc_ep.start_xfer_buff = buf; ++ ep->dwc_ep.xfer_buff = buf; ++ ep->dwc_ep.xfer_len = 0; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = buflen; ++ ++ /* Add this request to the tail */ ++ DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); ++ ep->dwc_ep.xiso_queued_xfers++; ++ ++//DWC_DEBUG("CP_0"); ++//DWC_DEBUG("req->ext_req.tr_sub_flags=%d", req->ext_req.tr_sub_flags); ++//prn_ext_request((struct dwc_iso_xreq_port *) ereq_nonport); ++//prn_ext_request(&req->ext_req); ++ ++ //DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ /* If the req->status == ASAP then check if there is any active transfer ++ * for this endpoint. If no active transfers, then get the first entry ++ * from the queue and start that transfer ++ */ ++ if (req->ext_req.tr_sub_flags == DWC_EREQ_TF_ASAP) { ++ res = dwc_otg_pcd_xiso_start_next_request(pcd, ep); ++ if (res) { ++ DWC_WARN("Failed to start the next Isoc transfer"); ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ DWC_FREE(req); ++ return res; ++ } ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return 0; ++} ++ ++#endif ++/* END ifdef DWC_UTE_PER_IO ***************************************************/ ++int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen, ++ int zero, void *req_handle, int atomic_alloc) ++{ ++ dwc_irqflags_t flags; ++ dwc_otg_pcd_request_t *req; ++ dwc_otg_pcd_ep_t *ep; ++ uint32_t max_transfer; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (atomic_alloc) { ++ req = DWC_ALLOC_ATOMIC(sizeof(*req)); ++ } else { ++ req = DWC_ALLOC(sizeof(*req)); ++ } ++ ++ if (!req) { ++ return -DWC_E_NO_MEMORY; ++ } ++ DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry); ++ if (!GET_CORE_IF(pcd)->core_params->opt) { ++ if (ep->dwc_ep.num != 0) { ++ DWC_ERROR("queue req %p, len %d buf %p\n", ++ req_handle, buflen, buf); ++ } ++ } ++ ++ req->buf = buf; ++ req->dma = dma_buf; ++ req->length = buflen; ++ req->sent_zlp = zero; ++ req->priv = req_handle; ++ req->dw_align_buf = NULL; ++ if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable ++ && !GET_CORE_IF(pcd)->dma_desc_enable) ++ req->dw_align_buf = DWC_DMA_ALLOC(buflen, ++ &req->dw_align_buf_dma); ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ /* ++ * After adding request to the queue for IN ISOC wait for In Token Received ++ * when TX FIFO is empty interrupt and for OUT ISOC wait for OUT Token ++ * Received when EP is disabled interrupt to obtain starting microframe ++ * (odd/even) start transfer ++ */ ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ if (req != 0) { ++ depctl_data_t depctl = {.d32 = ++ DWC_READ_REG32(&pcd->core_if->dev_if-> ++ in_ep_regs[ep->dwc_ep.num]-> ++ diepctl) }; ++ ++pcd->request_pending; ++ ++ DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); ++ if (ep->dwc_ep.is_in) { ++ depctl.b.cnak = 1; ++ DWC_WRITE_REG32(&pcd->core_if->dev_if-> ++ in_ep_regs[ep->dwc_ep.num]-> ++ diepctl, depctl.d32); ++ } ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ if (ep->dwc_ep.iso_transfer_started) { ++ /* ++ * Add next request to the descriptor chain ++ * currently not in use by HW ++ */ ++ program_next_iso_request_ddma(ep, req); ++ } else if (!ep->dwc_ep.is_in) ++ /* For OUT start first request immediately after queue */ ++ dwc_otg_pcd_start_iso_ddma(GET_CORE_IF(pcd), ep); ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ } ++ return 0; ++ } ++ ++ /* ++ * For EP0 IN without premature status, zlp is required? ++ */ ++ if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) { ++ DWC_DEBUGPL(DBG_PCDV, "%d-OUT ZLP\n", ep->dwc_ep.num); ++ //_req->zero = 1; ++ } ++ ++ /* Start the transfer */ ++ if (DWC_CIRCLEQ_EMPTY(&ep->queue) && !ep->stopped) { ++ /* EP0 Transfer? */ ++ if (ep->dwc_ep.num == 0) { ++ switch (pcd->ep0state) { ++ case EP0_IN_DATA_PHASE: ++ DWC_DEBUGPL(DBG_PCD, ++ "%s ep0: EP0_IN_DATA_PHASE\n", ++ __func__); ++ break; ++ ++ case EP0_OUT_DATA_PHASE: ++ DWC_DEBUGPL(DBG_PCD, ++ "%s ep0: EP0_OUT_DATA_PHASE\n", ++ __func__); ++ if (pcd->request_config) { ++ /* Complete STATUS PHASE */ ++ ep->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_STATUS_PHASE; ++ } ++ break; ++ ++ case EP0_IN_STATUS_PHASE: ++ DWC_DEBUGPL(DBG_PCD, ++ "%s ep0: EP0_IN_STATUS_PHASE\n", ++ __func__); ++ break; ++ ++ default: ++ DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n", ++ pcd->ep0state); ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return -DWC_E_SHUTDOWN; ++ } ++ ++ ep->dwc_ep.dma_addr = dma_buf; ++ ep->dwc_ep.start_xfer_buff = buf; ++ ep->dwc_ep.xfer_buff = buf; ++ ep->dwc_ep.xfer_len = buflen; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; ++ ++ if (zero) { ++ if ((ep->dwc_ep.xfer_len % ++ ep->dwc_ep.maxpacket == 0) ++ && (ep->dwc_ep.xfer_len != 0)) { ++ ep->dwc_ep.sent_zlp = 1; ++ } ++ ++ } ++ ++ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), ++ &ep->dwc_ep); ++ } // non-ep0 endpoints ++ else { ++#ifdef DWC_UTE_CFI ++ if (ep->dwc_ep.buff_mode != BM_STANDARD) { ++ /* store the request length */ ++ ep->dwc_ep.cfi_req_len = buflen; ++ pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ++ ep, req); ++ } else { ++#endif ++ max_transfer = ++ GET_CORE_IF(ep->pcd)->core_params-> ++ max_transfer_size; ++ ++ /* Setup and start the Transfer */ ++ if (req->dw_align_buf) { ++ if (ep->dwc_ep.is_in) ++ dwc_memcpy(req->dw_align_buf, ++ buf, buflen); ++ ep->dwc_ep.dma_addr = ++ req->dw_align_buf_dma; ++ ep->dwc_ep.start_xfer_buff = ++ req->dw_align_buf; ++ ep->dwc_ep.xfer_buff = ++ req->dw_align_buf; ++ } else { ++ ep->dwc_ep.dma_addr = dma_buf; ++ ep->dwc_ep.start_xfer_buff = buf; ++ ep->dwc_ep.xfer_buff = buf; ++ } ++ ep->dwc_ep.xfer_len = 0; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = buflen; ++ ++ ep->dwc_ep.maxxfer = max_transfer; ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ uint32_t out_max_xfer = ++ DDMA_MAX_TRANSFER_SIZE - ++ (DDMA_MAX_TRANSFER_SIZE % 4); ++ if (ep->dwc_ep.is_in) { ++ if (ep->dwc_ep.maxxfer > ++ DDMA_MAX_TRANSFER_SIZE) { ++ ep->dwc_ep.maxxfer = ++ DDMA_MAX_TRANSFER_SIZE; ++ } ++ } else { ++ if (ep->dwc_ep.maxxfer > ++ out_max_xfer) { ++ ep->dwc_ep.maxxfer = ++ out_max_xfer; ++ } ++ } ++ } ++ if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) { ++ ep->dwc_ep.maxxfer -= ++ (ep->dwc_ep.maxxfer % ++ ep->dwc_ep.maxpacket); ++ } ++ ++ if (zero) { ++ if ((ep->dwc_ep.total_len % ++ ep->dwc_ep.maxpacket == 0) ++ && (ep->dwc_ep.total_len != 0)) { ++ ep->dwc_ep.sent_zlp = 1; ++ } ++ } ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ dwc_otg_ep_start_transfer(GET_CORE_IF(pcd), ++ &ep->dwc_ep); ++ } ++ } ++ ++ if (req != 0) { ++ ++pcd->request_pending; ++ DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); ++ if (ep->dwc_ep.is_in && ep->stopped ++ && !(GET_CORE_IF(pcd)->dma_enable)) { ++ /** @todo NGS Create a function for this. */ ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ diepmsk.b.intktxfemp = 1; ++ if (GET_CORE_IF(pcd)->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->dev_global_regs->diepeachintmsk ++ [ep->dwc_ep.num], 0, ++ diepmsk.d32); ++ } else { ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->dev_global_regs-> ++ diepmsk, 0, diepmsk.d32); ++ } ++ ++ } ++ } ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ return 0; ++} ++ ++int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle) ++{ ++ dwc_irqflags_t flags; ++ dwc_otg_pcd_request_t *req; ++ dwc_otg_pcd_ep_t *ep; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) { ++ DWC_WARN("bad argument\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ /* make sure it's actually queued on this endpoint */ ++ DWC_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) { ++ if (req->priv == (void *)req_handle) { ++ break; ++ } ++ } ++ ++ if (req->priv != (void *)req_handle) { ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return -DWC_E_INVALID; ++ } ++ ++ if (!DWC_CIRCLEQ_EMPTY_ENTRY(req, queue_entry)) { ++ if(( ep != &pcd->ep0)&&(!ep->dwc_ep.is_in)) { ++ ep->dwc_ep.xfer_buff =NULL; ++ } ++ dwc_otg_request_done(ep, req, -DWC_E_RESTART); ++ } else { ++ req = NULL; ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ return req ? 0 : -DWC_E_SHUTDOWN; ++ ++} ++ ++int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ dwc_irqflags_t flags; ++ int retval = 0; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ ++ if (!ep || (!ep->desc && ep != &pcd->ep0) || ++ (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) { ++ DWC_WARN("%s, bad ep\n", __func__); ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num, ++ ep->dwc_ep.is_in ? "IN" : "OUT"); ++ retval = -DWC_E_AGAIN; ++ } else if (value == 0) { ++ ep->dwc_ep.stall_clear_flag = 0; ++ dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep); ++ } else if (value == 1) { ++ stall: ++ if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) { ++ dtxfsts_data_t txstatus; ++ fifosize_data_t txfifosize; ++ ++ txfifosize.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)-> ++ core_global_regs->dtxfsiz[ep->dwc_ep. ++ tx_fifo_num]); ++ txstatus.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->in_ep_regs[ep->dwc_ep.num]-> ++ dtxfsts); ++ ++ if (txstatus.b.txfspcavail < txfifosize.b.depth) { ++ retval = -DWC_E_AGAIN; ++ } else { ++ if (ep->dwc_ep.num == 0) { ++ pcd->ep0state = EP0_STALL; ++ } ++ ++ ep->stopped = 1; ++ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), ++ &ep->dwc_ep); ++ } ++ } else { ++ if (ep->dwc_ep.num == 0) { ++ pcd->ep0state = EP0_STALL; ++ } ++ ++ ep->stopped = 1; ++ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep); ++ } ++ } else if (value == 2) { ++ ep->dwc_ep.stall_clear_flag = 0; ++ } else if (value == 3) { ++ ep->dwc_ep.stall_clear_flag = 1; ++ goto stall; ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ return retval; ++} ++ ++/** ++ * This function initiates remote wakeup of the host from suspend state. ++ */ ++void dwc_otg_pcd_rem_wkup_from_suspend(dwc_otg_pcd_t * pcd, int set) ++{ ++ dctl_data_t dctl = { 0 }; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dsts_data_t dsts; ++ ++ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ if (!dsts.b.suspsts) { ++ DWC_WARN("Remote wakeup while is not in suspend state\n"); ++ } ++ /* Check if DEVICE_REMOTE_WAKEUP feature enabled */ ++ if (pcd->remote_wakeup_enable) { ++ if (set) { ++ ++ if (core_if->adp_enable) { ++ gpwrdn_data_t gpwrdn; ++ ++ dwc_otg_adp_probe_stop(core_if); ++ ++ /* Mask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ ++ /* Disable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Device mode. ++ */ ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ ++ dwc_otg_initiate_srp(core_if); ++ } ++ ++ dctl.b.rmtwkupsig = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, 0, dctl.d32); ++ DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n"); ++ ++ dwc_mdelay(2); ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, dctl.d32, 0); ++ DWC_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n"); ++ } ++ } else { ++ DWC_DEBUGPL(DBG_PCD, "Remote Wakeup is disabled\n"); ++ } ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++/** ++ * This function initiates remote wakeup of the host from L1 sleep state. ++ */ ++void dwc_otg_pcd_rem_wkup_from_sleep(dwc_otg_pcd_t * pcd, int set) ++{ ++ glpmcfg_data_t lpmcfg; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ ++ /* Check if we are in L1 state */ ++ if (!lpmcfg.b.prt_sleep_sts) { ++ DWC_DEBUGPL(DBG_PCD, "Device is not in sleep state\n"); ++ return; ++ } ++ ++ /* Check if host allows remote wakeup */ ++ if (!lpmcfg.b.rem_wkup_en) { ++ DWC_DEBUGPL(DBG_PCD, "Host does not allow remote wakeup\n"); ++ return; ++ } ++ ++ /* Check if Resume OK */ ++ if (!lpmcfg.b.sleep_state_resumeok) { ++ DWC_DEBUGPL(DBG_PCD, "Sleep state resume is not OK\n"); ++ return; ++ } ++ ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.en_utmi_sleep = 0; ++ lpmcfg.b.hird_thres &= (~(1 << 4)); ++ ++ /* Clear Enbl_L1Gating bit. */ ++ pcgcctl.b.enbl_sleep_gating = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,0); ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++ ++ if (set) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.b.rmtwkupsig = 1; ++ /* Set RmtWkUpSig bit to start remote wakup signaling. ++ * Hardware will automatically clear this bit. ++ */ ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ 0, dctl.d32); ++ DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n"); ++ } ++ ++} ++#endif ++ ++/** ++ * Performs remote wakeup. ++ */ ++void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_irqflags_t flags; ++ if (dwc_otg_is_device_mode(core_if)) { ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ if (core_if->lx_state == DWC_OTG_L1) { ++ dwc_otg_pcd_rem_wkup_from_sleep(pcd, set); ++ } else { ++#endif ++ dwc_otg_pcd_rem_wkup_from_suspend(pcd, set); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ } ++#endif ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ } ++ return; ++} ++ ++void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dctl_data_t dctl = { 0 }; ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ dctl.b.sftdiscon = 1; ++ DWC_PRINTF("Soft disconnect for %d useconds\n",no_of_usecs); ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ dwc_udelay(no_of_usecs); ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32,0); ++ ++ } else{ ++ DWC_PRINTF("NOT SUPPORTED IN HOST MODE\n"); ++ } ++ return; ++ ++} ++ ++int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd) ++{ ++ dsts_data_t dsts; ++ gotgctl_data_t gotgctl; ++ ++ /* ++ * This function starts the Protocol if no session is in progress. If ++ * a session is already in progress, but the device is suspended, ++ * remote wakeup signaling is started. ++ */ ++ ++ /* Check if valid session */ ++ gotgctl.d32 = ++ DWC_READ_REG32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl)); ++ if (gotgctl.b.bsesvld) { ++ /* Check if suspend state */ ++ dsts.d32 = ++ DWC_READ_REG32(& ++ (GET_CORE_IF(pcd)->dev_if-> ++ dev_global_regs->dsts)); ++ if (dsts.b.suspsts) { ++ dwc_otg_pcd_remote_wakeup(pcd, 1); ++ } ++ } else { ++ dwc_otg_pcd_initiate_srp(pcd); ++ } ++ ++ return 0; ++ ++} ++ ++void dwc_otg_pcd_pullup(dwc_otg_pcd_t *pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ depctl_data_t depctl; ++ ++ depctl.d32 = 0; ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[bulk_num]->diepctl); ++ ++ depctl.b.setd1pid = 0; ++ depctl.b.setd0pid = 1; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[bulk_num]->diepctl, depctl.d32); ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[3]->diepctl); ++} ++ ++/** ++ * Start the SRP timer to detect when the SRP does not complete within ++ * 6 seconds. ++ * ++ * @param pcd the pcd structure. ++ */ ++void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd) ++{ ++ dwc_irqflags_t flags; ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ dwc_otg_initiate_srp(GET_CORE_IF(pcd)); ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++} ++ ++int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd) ++{ ++ return dwc_otg_get_frame_number(GET_CORE_IF(pcd)); ++} ++ ++int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd) ++{ ++ return GET_CORE_IF(pcd)->core_params->lpm_enable; ++} ++ ++int dwc_otg_pcd_is_besl_enabled(dwc_otg_pcd_t * pcd) ++{ ++ return GET_CORE_IF(pcd)->core_params->besl_enable; ++} ++ ++int dwc_otg_pcd_get_param_baseline_besl(dwc_otg_pcd_t * pcd) ++{ ++ return GET_CORE_IF(pcd)->core_params->baseline_besl; ++} ++ ++int dwc_otg_pcd_get_param_deep_besl(dwc_otg_pcd_t * pcd) ++{ ++ return GET_CORE_IF(pcd)->core_params->deep_besl; ++} ++ ++uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd) ++{ ++ return pcd->b_hnp_enable; ++} ++ ++uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd) ++{ ++ return pcd->a_hnp_support; ++} ++ ++uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd) ++{ ++ return pcd->a_alt_hnp_support; ++} ++ ++int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd) ++{ ++ return pcd->remote_wakeup_enable; ++} ++ ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd.h +new file mode 100644 +index 0000000..54ced23 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd.h +@@ -0,0 +1,268 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $ ++ * $Revision: #49 $ ++ * $Date: 2013/05/16 $ ++ * $Change: 2231774 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_HOST_ONLY ++#if !defined(__DWC_PCD_H__) ++#define __DWC_PCD_H__ ++ ++#include "dwc_otg_os_dep.h" ++#include "usb.h" ++#include "dwc_otg_cil.h" ++#include "dwc_otg_pcd_if.h" ++struct cfiobject; ++ ++/** ++ * @file ++ * ++ * This file contains the structures, constants, and interfaces for ++ * the Perpherial Contoller Driver (PCD). ++ * ++ * The Peripheral Controller Driver (PCD) for Linux will implement the ++ * Gadget API, so that the existing Gadget drivers can be used. For ++ * the Mass Storage Function driver the File-backed USB Storage Gadget ++ * (FBS) driver will be used. The FBS driver supports the ++ * Control-Bulk (CB), Control-Bulk-Interrupt (CBI), and Bulk-Only ++ * transports. ++ * ++ */ ++ ++/** Invalid DMA Address */ ++#define DWC_DMA_ADDR_INVALID (~(dwc_dma_t)0) ++ ++/** Max Transfer size for any EP */ ++#define DDMA_MAX_TRANSFER_SIZE 65535 ++ ++/** ++ * Get the pointer to the core_if from the pcd pointer. ++ */ ++#define GET_CORE_IF( _pcd ) (_pcd->core_if) ++ ++/** ++ * States of EP0. ++ */ ++typedef enum ep0_state { ++ EP0_DISCONNECT, /* no host */ ++ EP0_IDLE, ++ EP0_IN_DATA_PHASE, ++ EP0_OUT_DATA_PHASE, ++ EP0_IN_STATUS_PHASE, ++ EP0_OUT_STATUS_PHASE, ++ EP0_STALL, ++} ep0state_e; ++ ++/** Fordward declaration.*/ ++struct dwc_otg_pcd; ++ ++/** DWC_otg iso request structure. ++ * ++ */ ++typedef struct usb_iso_request dwc_otg_pcd_iso_request_t; ++ ++#ifdef DWC_UTE_PER_IO ++ ++/** ++ * This shall be the exact analogy of the same type structure defined in the ++ * usb_gadget.h. Each descriptor contains ++ */ ++struct dwc_iso_pkt_desc_port { ++ uint32_t offset; ++ uint32_t length; /* expected length */ ++ uint32_t actual_length; ++ uint32_t status; ++}; ++ ++struct dwc_iso_xreq_port { ++ /** transfer/submission flag */ ++ uint32_t tr_sub_flags; ++ /** Start the request ASAP */ ++#define DWC_EREQ_TF_ASAP 0x00000002 ++ /** Just enqueue the request w/o initiating a transfer */ ++#define DWC_EREQ_TF_ENQUEUE 0x00000004 ++ ++ /** ++ * count of ISO packets attached to this request - shall ++ * not exceed the pio_alloc_pkt_count ++ */ ++ uint32_t pio_pkt_count; ++ /** count of ISO packets allocated for this request */ ++ uint32_t pio_alloc_pkt_count; ++ /** number of ISO packet errors */ ++ uint32_t error_count; ++ /** reserved for future extension */ ++ uint32_t res; ++ /** Will be allocated and freed in the UTE gadget and based on the CFC value */ ++ struct dwc_iso_pkt_desc_port *per_io_frame_descs; ++}; ++#endif ++/** DWC_otg request structure. ++ * This structure is a list of requests. ++ */ ++typedef struct dwc_otg_pcd_request { ++ void *priv; ++ void *buf; ++ dwc_dma_t dma; ++ uint32_t length; ++ uint32_t actual; ++ unsigned sent_zlp:1; ++ /** ++ * Used instead of original buffer if ++ * it(physical address) is not dword-aligned. ++ **/ ++ uint8_t *dw_align_buf; ++ dwc_dma_t dw_align_buf_dma; ++ ++ DWC_CIRCLEQ_ENTRY(dwc_otg_pcd_request) queue_entry; ++#ifdef DWC_UTE_PER_IO ++ struct dwc_iso_xreq_port ext_req; ++ //void *priv_ereq_nport; /* */ ++#endif ++} dwc_otg_pcd_request_t; ++ ++DWC_CIRCLEQ_HEAD(req_list, dwc_otg_pcd_request); ++ ++/** PCD EP structure. ++ * This structure describes an EP, there is an array of EPs in the PCD ++ * structure. ++ */ ++typedef struct dwc_otg_pcd_ep { ++ /** USB EP Descriptor */ ++ const usb_endpoint_descriptor_t *desc; ++ ++ /** queue of dwc_otg_pcd_requests. */ ++ struct req_list queue; ++ unsigned stopped:1; ++ unsigned disabling:1; ++ unsigned dma:1; ++ unsigned queue_sof:1; ++ ++#ifdef DWC_EN_ISOC ++ /** ISOC req handle passed */ ++ void *iso_req_handle; ++#endif //_EN_ISOC_ ++ ++ /** DWC_otg ep data. */ ++ dwc_ep_t dwc_ep; ++ ++ /** Pointer to PCD */ ++ struct dwc_otg_pcd *pcd; ++ ++ void *priv; ++} dwc_otg_pcd_ep_t; ++ ++/** DWC_otg PCD Structure. ++ * This structure encapsulates the data for the dwc_otg PCD. ++ */ ++struct dwc_otg_pcd { ++ const struct dwc_otg_pcd_function_ops *fops; ++ /** The DWC otg device pointer */ ++ struct dwc_otg_device *otg_dev; ++ /** Core Interface */ ++ dwc_otg_core_if_t *core_if; ++ /** State of EP0 */ ++ ep0state_e ep0state; ++ /** EP0 Request is pending */ ++ unsigned ep0_pending:1; ++ /** Indicates when SET CONFIGURATION Request is in process */ ++ unsigned request_config:1; ++ /** The state of the Remote Wakeup Enable. */ ++ unsigned remote_wakeup_enable:1; ++ /** The state of the B-Device HNP Enable. */ ++ unsigned b_hnp_enable:1; ++ /** The state of A-Device HNP Support. */ ++ unsigned a_hnp_support:1; ++ /** The state of the A-Device Alt HNP support. */ ++ unsigned a_alt_hnp_support:1; ++ /** Count of pending Requests */ ++ unsigned request_pending; ++ ++ /** SETUP packet for EP0 ++ * This structure is allocated as a DMA buffer on PCD initialization ++ * with enough space for up to 3 setup packets. ++ */ ++ union { ++ usb_device_request_t req; ++ uint32_t d32[2]; ++ } *setup_pkt; ++ ++ dwc_dma_t setup_pkt_dma_handle; ++ ++ /* Additional buffer and flag for CTRL_WR premature case */ ++ uint8_t *backup_buf; ++ unsigned data_terminated; ++ ++ /** 2-byte dma buffer used to return status from GET_STATUS */ ++ uint16_t *status_buf; ++ dwc_dma_t status_buf_dma_handle; ++ ++ /** EP0 */ ++ dwc_otg_pcd_ep_t ep0; ++ ++ /** Array of IN EPs. */ ++ dwc_otg_pcd_ep_t in_ep[MAX_EPS_CHANNELS - 1]; ++ /** Array of OUT EPs. */ ++ dwc_otg_pcd_ep_t out_ep[MAX_EPS_CHANNELS - 1]; ++ /** number of valid EPs in the above array. */ ++// unsigned num_eps : 4; ++ dwc_spinlock_t *lock; ++ ++ /** Tasklet to defer starting of TEST mode transmissions until ++ * Status Phase has been completed. ++ */ ++ dwc_tasklet_t *test_mode_tasklet; ++ ++ /** Tasklet to delay starting of xfer in DMA mode */ ++ dwc_tasklet_t *start_xfer_tasklet; ++ ++ /** The test mode to enter when the tasklet is executed. */ ++ unsigned test_mode; ++ /** The cfi_api structure that implements most of the CFI API ++ * and OTG specific core configuration functionality ++ */ ++#ifdef DWC_UTE_CFI ++ struct cfiobject *cfi; ++#endif ++ ++}; ++ ++//FIXME this functions should be static, and this prototypes should be removed ++extern void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep); ++extern void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, ++ dwc_otg_pcd_request_t * req, int32_t status); ++ ++void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep, ++ void *req_handle); ++extern void dwc_otg_pcd_start_iso_ddma(dwc_otg_core_if_t * core_if, ++ dwc_otg_pcd_ep_t * ep); ++ ++extern void do_test_mode(void *data); ++#endif ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd_if.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd_if.h +new file mode 100644 +index 0000000..6cd75fa +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd_if.h +@@ -0,0 +1,368 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $ ++ * $Revision: #13 $ ++ * $Date: 2012/12/12 $ ++ * $Change: 2125019 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_HOST_ONLY ++ ++#if !defined(__DWC_PCD_IF_H__) ++#define __DWC_PCD_IF_H__ ++ ++//#include "dwc_os.h" ++#include "dwc_otg_core_if.h" ++ ++/** @file ++ * This file defines DWC_OTG PCD Core API. ++ */ ++ ++struct dwc_otg_pcd; ++typedef struct dwc_otg_pcd dwc_otg_pcd_t; ++ ++/** Maxpacket size for EP0 */ ++#define MAX_EP0_SIZE 64 ++/** Maxpacket size for any EP */ ++#define MAX_PACKET_SIZE 1024 ++ ++/** @name Function Driver Callbacks */ ++/** @{ */ ++ ++/** This function will be called whenever a previously queued request has ++ * completed. The status value will be set to -DWC_E_SHUTDOWN to indicated a ++ * failed or aborted transfer, or -DWC_E_RESTART to indicate the device was reset, ++ * or -DWC_E_TIMEOUT to indicate it timed out, or -DWC_E_INVALID to indicate invalid ++ * parameters. */ ++typedef int (*dwc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int32_t status, ++ uint32_t actual); ++/** ++ * This function will be called whenever a previousle queued ISOC request has ++ * completed. Count of ISOC packets could be read using dwc_otg_pcd_get_iso_packet_count ++ * function. ++ * The status of each ISOC packet could be read using dwc_otg_pcd_get_iso_packet_* ++ * functions. ++ */ ++typedef int (*dwc_isoc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int proc_buf_num); ++/** This function should handle any SETUP request that cannot be handled by the ++ * PCD Core. This includes most GET_DESCRIPTORs, SET_CONFIGS, Any ++ * class-specific requests, etc. The function must non-blocking. ++ * ++ * Returns 0 on success. ++ * Returns -DWC_E_NOT_SUPPORTED if the request is not supported. ++ * Returns -DWC_E_INVALID if the setup request had invalid parameters or bytes. ++ * Returns -DWC_E_SHUTDOWN on any other error. */ ++typedef int (*dwc_setup_cb_t) (dwc_otg_pcd_t * pcd, uint8_t * bytes); ++/** This is called whenever the device has been disconnected. The function ++ * driver should take appropriate action to clean up all pending requests in the ++ * PCD Core, remove all endpoints (except ep0), and initialize back to reset ++ * state. */ ++typedef int (*dwc_disconnect_cb_t) (dwc_otg_pcd_t * pcd); ++/** This function is called when device has been connected. */ ++typedef int (*dwc_connect_cb_t) (dwc_otg_pcd_t * pcd, int speed); ++/** This function is called when device has been suspended */ ++typedef int (*dwc_suspend_cb_t) (dwc_otg_pcd_t * pcd); ++/** This function is called when device has received LPM tokens, i.e. ++ * device has been sent to sleep state. */ ++typedef int (*dwc_sleep_cb_t) (dwc_otg_pcd_t * pcd); ++/** This function is called when device has been resumed ++ * from suspend(L2) or L1 sleep state. */ ++typedef int (*dwc_resume_cb_t) (dwc_otg_pcd_t * pcd); ++/** This function is called whenever hnp params has been changed. ++ * User can call get_b_hnp_enable, get_a_hnp_support, get_a_alt_hnp_support functions ++ * to get hnp parameters. */ ++typedef int (*dwc_hnp_params_changed_cb_t) (dwc_otg_pcd_t * pcd); ++/** This function is called whenever USB RESET is detected. */ ++typedef int (*dwc_reset_cb_t) (dwc_otg_pcd_t * pcd); ++ ++typedef int (*cfi_setup_cb_t) (dwc_otg_pcd_t * pcd, void *ctrl_req_bytes); ++ ++/** ++ * ++ * @param ep_handle Void pointer to the usb_ep structure ++ * @param ereq_port Pointer to the extended request structure created in the ++ * portable part. ++ */ ++typedef int (*xiso_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int32_t status, ++ void *ereq_port); ++/** Function Driver Ops Data Structure */ ++struct dwc_otg_pcd_function_ops { ++ dwc_connect_cb_t connect; ++ dwc_disconnect_cb_t disconnect; ++ dwc_setup_cb_t setup; ++ dwc_completion_cb_t complete; ++ dwc_isoc_completion_cb_t isoc_complete; ++ dwc_suspend_cb_t suspend; ++ dwc_sleep_cb_t sleep; ++ dwc_resume_cb_t resume; ++ dwc_reset_cb_t reset; ++ dwc_hnp_params_changed_cb_t hnp_changed; ++ cfi_setup_cb_t cfi_setup; ++#ifdef DWC_UTE_PER_IO ++ xiso_completion_cb_t xisoc_complete; ++#endif ++}; ++/** @} */ ++ ++/** @name Function Driver Functions */ ++/** @{ */ ++ ++/** Call this function to get pointer on dwc_otg_pcd_t, ++ * this pointer will be used for all PCD API functions. ++ * ++ * @param core_if The DWC_OTG Core ++ */ ++extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if); ++ ++/** Frees PCD allocated by dwc_otg_pcd_init ++ * ++ * @param pcd The PCD ++ */ ++extern void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd); ++ ++/** Call this to bind the function driver to the PCD Core. ++ * ++ * @param pcd Pointer on dwc_otg_pcd_t returned by dwc_otg_pcd_init function. ++ * @param fops The Function Driver Ops data structure containing pointers to all callbacks. ++ */ ++extern void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd, ++ const struct dwc_otg_pcd_function_ops *fops); ++ ++/** Enables an endpoint for use. This function enables an endpoint in ++ * the PCD. The endpoint is described by the ep_desc which has the ++ * same format as a USB ep descriptor. The ep_handle parameter is used to refer ++ * to the endpoint from other API functions and in callbacks. Normally this ++ * should be called after a SET_CONFIGURATION/SET_INTERFACE to configure the ++ * core for that interface. ++ * ++ * Returns -DWC_E_INVALID if invalid parameters were passed. ++ * Returns -DWC_E_SHUTDOWN if any other error ocurred. ++ * Returns 0 on success. ++ * ++ * @param pcd The PCD ++ * @param ep_desc Endpoint descriptor ++ * @param ep_handle Handle on endpoint, that will be used to identify endpoint. ++ */ ++extern int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, ++ const uint8_t * ep_desc, void *ep_handle); ++ ++/** Disable the endpoint referenced by ep_handle. ++ * ++ * Returns -DWC_E_INVALID if invalid parameters were passed. ++ * Returns -DWC_E_SHUTDOWN if any other error occurred. ++ * Returns 0 on success. */ ++extern int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle); ++ ++/** Queue a data transfer request on the endpoint referenced by ep_handle. ++ * After the transfer is completes, the complete callback will be called with ++ * the request status. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param buf The buffer for the data ++ * @param dma_buf The DMA buffer for the data ++ * @param buflen The length of the data transfer ++ * @param zero Specifies whether to send zero length last packet. ++ * @param req_handle Set this handle to any value to use to reference this ++ * request in the ep_dequeue function or from the complete callback ++ * @param atomic_alloc If driver need to perform atomic allocations ++ * for internal data structures. ++ * ++ * Returns -DWC_E_INVALID if invalid parameters were passed. ++ * Returns -DWC_E_SHUTDOWN if any other error ocurred. ++ * Returns 0 on success. */ ++extern int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf, dwc_dma_t dma_buf, ++ uint32_t buflen, int zero, void *req_handle, ++ int atomic_alloc); ++#ifdef DWC_UTE_PER_IO ++/** ++ * ++ * @param ereq_nonport Pointer to the extended request part of the ++ * usb_request structure defined in usb_gadget.h file. ++ */ ++extern int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf, dwc_dma_t dma_buf, ++ uint32_t buflen, int zero, ++ void *req_handle, int atomic_alloc, ++ void *ereq_nonport); ++ ++#endif ++ ++/** De-queue the specified data transfer that has not yet completed. ++ * ++ * Returns -DWC_E_INVALID if invalid parameters were passed. ++ * Returns -DWC_E_SHUTDOWN if any other error ocurred. ++ * Returns 0 on success. */ ++extern int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle); ++ ++/** Halt (STALL) an endpoint or clear it. ++ * ++ * Returns -DWC_E_INVALID if invalid parameters were passed. ++ * Returns -DWC_E_SHUTDOWN if any other error ocurred. ++ * Returns -DWC_E_AGAIN if the STALL cannot be sent and must be tried again later ++ * Returns 0 on success. */ ++extern int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value); ++ ++/** This function should be called on every hardware interrupt */ ++extern int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd); ++ ++/** This function returns current frame number */ ++extern int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd); ++ ++/** ++ * Start isochronous transfers on the endpoint referenced by ep_handle. ++ * For isochronous transfers duble buffering is used. ++ * After processing each of buffers comlete callback will be called with ++ * status for each transaction. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param buf0 The virtual address of first data buffer ++ * @param buf1 The virtual address of second data buffer ++ * @param dma0 The DMA address of first data buffer ++ * @param dma1 The DMA address of second data buffer ++ * @param sync_frame Data pattern frame number ++ * @param dp_frame Data size for pattern frame ++ * @param data_per_frame Data size for regular frame ++ * @param start_frame Frame number to start transfers, if -1 then start transfers ASAP. ++ * @param buf_proc_intrvl Interval of ISOC Buffer processing ++ * @param req_handle Handle of ISOC request ++ * @param atomic_alloc Specefies whether to perform atomic allocation for ++ * internal data structures. ++ * ++ * Returns -DWC_E_NO_MEMORY if there is no enough memory. ++ * Returns -DWC_E_INVALID if incorrect arguments are passed to the function. ++ * Returns -DW_E_SHUTDOWN for any other error. ++ * Returns 0 on success ++ */ ++extern int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf0, uint8_t * buf1, ++ dwc_dma_t dma0, dwc_dma_t dma1, ++ int sync_frame, int dp_frame, ++ int data_per_frame, int start_frame, ++ int buf_proc_intrvl, void *req_handle, ++ int atomic_alloc); ++ ++/** Stop ISOC transfers on endpoint referenced by ep_handle. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param req_handle Handle of ISOC request ++ * ++ * Returns -DWC_E_INVALID if incorrect arguments are passed to the function ++ * Returns 0 on success ++ */ ++int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle); ++ ++/** Get ISOC packet status. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param iso_req_handle Isochronoush request handle ++ * @param packet Number of packet ++ * @param status Out parameter for returning status ++ * @param actual Out parameter for returning actual length ++ * @param offset Out parameter for returning offset ++ * ++ */ ++extern void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, ++ void *ep_handle, ++ void *iso_req_handle, int packet, ++ int *status, int *actual, ++ int *offset); ++ ++/** Get ISOC packet count. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param iso_req_handle ++ */ ++extern int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, ++ void *ep_handle, ++ void *iso_req_handle); ++ ++/** This function starts the SRP Protocol if no session is in progress. If ++ * a session is already in progress, but the device is suspended, ++ * remote wakeup signaling is started. ++ */ ++extern int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd); ++ ++extern void dwc_otg_pcd_pullup(dwc_otg_pcd_t *pcd); ++ ++/** This function returns 1 if LPM support is enabled, and 0 otherwise. */ ++extern int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd); ++ ++/** This function returns 1 if LPM Errata support is enabled, and 0 otherwise. */ ++extern int dwc_otg_pcd_is_besl_enabled(dwc_otg_pcd_t * pcd); ++ ++/** This function returns baseline_besl module parametr. */ ++extern int dwc_otg_pcd_get_param_baseline_besl(dwc_otg_pcd_t * pcd); ++ ++/** This function returns deep_besl module parametr. */ ++extern int dwc_otg_pcd_get_param_deep_besl(dwc_otg_pcd_t * pcd); ++ ++/** This function returns 1 if remote wakeup is allowed and 0, otherwise. */ ++extern int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd); ++ ++/** Initiate SRP */ ++extern void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd); ++ ++/** Starts remote wakeup signaling. */ ++extern void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set); ++ ++/** Starts micorsecond soft disconnect. */ ++extern void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs); ++/** This function returns whether device is dualspeed.*/ ++extern uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd); ++ ++/** This function returns whether device is otg. */ ++extern uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd); ++ ++/** These functions allow to get hnp parameters */ ++extern uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd); ++extern uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd); ++extern uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd); ++ ++/** CFI specific Interface functions */ ++/** Allocate a cfi buffer */ ++extern uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, ++ dwc_dma_t * addr, size_t buflen, ++ int flags); ++ ++/******************************************************************************/ ++ ++/** @} */ ++ ++#endif /* __DWC_PCD_IF_H__ */ ++ ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd_intr.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd_intr.c +new file mode 100644 +index 0000000..9a151e0 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd_intr.c +@@ -0,0 +1,5463 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $ ++ * $Revision: #125 $ ++ * $Date: 2013/05/20 $ ++ * $Change: 2234037 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_HOST_ONLY ++ ++#include "dwc_otg_pcd.h" ++ ++#ifdef DWC_UTE_CFI ++#include "dwc_otg_cfi.h" ++#endif ++ ++//#include ++ ++#ifdef DWC_UTE_PER_IO ++extern void complete_xiso_ep(dwc_otg_pcd_ep_t * ep); ++#endif ++//#define PRINT_CFI_DMA_DESCS ++ ++#define DEBUG_EP0 ++ ++/* avoid null point */ ++uint8_t readpacket_buf[1024]; ++ ++/** ++ * This function updates OTG. ++ */ ++extern int otg_usbhost_stat; ++extern void hisi_switch_func(int otg); ++static void dwc_otg_pcd_update_otg(dwc_otg_pcd_t * pcd, const unsigned reset) ++{ ++ ++ if (reset) { ++ pcd->b_hnp_enable = 0; ++ pcd->a_hnp_support = 0; ++ pcd->a_alt_hnp_support = 0; ++ } ++ ++ if (pcd->fops->hnp_changed) { ++ pcd->fops->hnp_changed(pcd); ++ } ++} ++ ++/** @file ++ * This file contains the implementation of the PCD Interrupt handlers. ++ * ++ * The PCD handles the device interrupts. Many conditions can cause a ++ * device interrupt. When an interrupt occurs, the device interrupt ++ * service routine determines the cause of the interrupt and ++ * dispatches handling to the appropriate function. These interrupt ++ * handling functions are described below. ++ * All interrupt registers are processed from LSB to MSB. ++ */ ++ ++/** ++ * This function prints the ep0 state for debug purposes. ++ */ ++static inline void print_ep0_state(dwc_otg_pcd_t * pcd) ++{ ++#ifdef DEBUG ++ char str[40]; ++ ++ switch (pcd->ep0state) { ++ case EP0_DISCONNECT: ++ dwc_strcpy(str, "EP0_DISCONNECT"); ++ break; ++ case EP0_IDLE: ++ dwc_strcpy(str, "EP0_IDLE"); ++ break; ++ case EP0_IN_DATA_PHASE: ++ dwc_strcpy(str, "EP0_IN_DATA_PHASE"); ++ break; ++ case EP0_OUT_DATA_PHASE: ++ dwc_strcpy(str, "EP0_OUT_DATA_PHASE"); ++ break; ++ case EP0_IN_STATUS_PHASE: ++ dwc_strcpy(str, "EP0_IN_STATUS_PHASE"); ++ break; ++ case EP0_OUT_STATUS_PHASE: ++ dwc_strcpy(str, "EP0_OUT_STATUS_PHASE"); ++ break; ++ case EP0_STALL: ++ dwc_strcpy(str, "EP0_STALL"); ++ break; ++ default: ++ dwc_strcpy(str, "EP0_INVALID"); ++ } ++ ++ DWC_DEBUGPL(DBG_ANY, "%s(%d)\n", str, pcd->ep0state); ++#endif ++} ++ ++/** ++ * This function calculate the size of the payload in the memory ++ * for out endpoints and prints size for debug purposes(used in ++ * 2.93a DevOutNak feature). ++ */ ++static inline void print_memory_payload(dwc_otg_pcd_t * pcd, dwc_ep_t * ep) ++{ ++#ifdef DEBUG ++ deptsiz_data_t deptsiz_init = {.d32 = 0 }; ++ deptsiz_data_t deptsiz_updt = {.d32 = 0 }; ++ int pack_num; ++ unsigned payload; ++ ++ deptsiz_init.d32 = pcd->core_if->start_doeptsiz_val[ep->num]; ++ deptsiz_updt.d32 = ++ DWC_READ_REG32(&pcd->core_if->dev_if-> ++ out_ep_regs[ep->num]->doeptsiz); ++ /* Payload will be */ ++ payload = deptsiz_init.b.xfersize - deptsiz_updt.b.xfersize; ++ /* Packet count is decremented every time a packet ++ * is written to the RxFIFO not in to the external memory ++ * So, if payload == 0, then it means no packet was sent to ext memory*/ ++ pack_num = (!payload) ? 0 : (deptsiz_init.b.pktcnt - deptsiz_updt.b.pktcnt); ++ DWC_DEBUGPL(DBG_PCDV, ++ "Payload for EP%d-%s\n", ++ ep->num, (ep->is_in ? "IN" : "OUT")); ++ DWC_DEBUGPL(DBG_PCDV, ++ "Number of transfered bytes = 0x%08x\n", payload); ++ DWC_DEBUGPL(DBG_PCDV, ++ "Number of transfered packets = %d\n", pack_num); ++#endif ++} ++ ++ ++#ifdef DWC_UTE_CFI ++static inline void print_desc(struct dwc_otg_dma_desc *ddesc, ++ const uint8_t * epname, int descnum) ++{ ++ CFI_INFO ++ ("%s DMA_DESC(%d) buf=0x%08x bytes=0x%04x; sp=0x%x; l=0x%x; sts=0x%02x; bs=0x%02x\n", ++ epname, descnum, ddesc->buf, ddesc->status.b.bytes, ++ ddesc->status.b.sp, ddesc->status.b.l, ddesc->status.b.sts, ++ ddesc->status.b.bs); ++} ++#endif ++ ++/** ++ * This function returns pointer to in ep struct with number ep_num ++ */ ++static inline dwc_otg_pcd_ep_t *get_in_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num) ++{ ++ int i; ++ int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps; ++ if (ep_num == 0) { ++ return &pcd->ep0; ++ } else { ++ for (i = 0; i < num_in_eps; ++i) { ++ if (pcd->in_ep[i].dwc_ep.num == ep_num) ++ return &pcd->in_ep[i]; ++ } ++ return 0; ++ } ++} ++ ++/** ++ * This function returns pointer to out ep struct with number ep_num ++ */ ++static inline dwc_otg_pcd_ep_t *get_out_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num) ++{ ++ int i; ++ int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps; ++ if (ep_num == 0) { ++ return &pcd->ep0; ++ } else { ++ for (i = 0; i < num_out_eps; ++i) { ++ if (pcd->out_ep[i].dwc_ep.num == ep_num) ++ return &pcd->out_ep[i]; ++ } ++ return 0; ++ } ++} ++ ++/** ++ * This functions gets a pointer to an EP from the wIndex address ++ * value of the control request. ++ */ ++dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ uint32_t ep_num = UE_GET_ADDR(wIndex); ++ ++ if (ep_num == 0) { ++ ep = &pcd->ep0; ++ } else if (UE_GET_DIR(wIndex) == UE_DIR_IN) { /* in ep */ ++ ep = &pcd->in_ep[ep_num - 1]; ++ } else { ++ ep = &pcd->out_ep[ep_num - 1]; ++ } ++ ++ return ep; ++} ++ ++/** ++ * This function checks the EP request queue, if the queue is not ++ * empty the next request is started. ++ */ ++void start_next_request(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_pcd_request_t *req = 0; ++ uint32_t max_transfer = ++ GET_CORE_IF(ep->pcd)->core_params->max_transfer_size; ++ ++#ifdef DWC_UTE_CFI ++ struct dwc_otg_pcd *pcd; ++ pcd = ep->pcd; ++#endif ++ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ ++#ifdef DWC_UTE_CFI ++ if (ep->dwc_ep.buff_mode != BM_STANDARD) { ++ ep->dwc_ep.cfi_req_len = req->length; ++ pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ep, req); ++ } else { ++#endif ++ /* Setup and start the Transfer */ ++ if (req->dw_align_buf) { ++ ep->dwc_ep.dma_addr = req->dw_align_buf_dma; ++ ep->dwc_ep.start_xfer_buff = req->dw_align_buf; ++ ep->dwc_ep.xfer_buff = req->dw_align_buf; ++ } else { ++ ep->dwc_ep.dma_addr = req->dma; ++ ep->dwc_ep.start_xfer_buff = req->buf; ++ ep->dwc_ep.xfer_buff = req->buf; ++ } ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = req->length; ++ ep->dwc_ep.xfer_len = 0; ++ ep->dwc_ep.xfer_count = 0; ++ ++ ep->dwc_ep.maxxfer = max_transfer; ++ if (GET_CORE_IF(ep->pcd)->dma_desc_enable) { ++ uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE ++ - (DDMA_MAX_TRANSFER_SIZE % 4); ++ if (ep->dwc_ep.is_in) { ++ if (ep->dwc_ep.maxxfer > ++ DDMA_MAX_TRANSFER_SIZE) { ++ ep->dwc_ep.maxxfer = ++ DDMA_MAX_TRANSFER_SIZE; ++ } ++ } else { ++ if (ep->dwc_ep.maxxfer > out_max_xfer) { ++ ep->dwc_ep.maxxfer = ++ out_max_xfer; ++ } ++ } ++ } ++ if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) { ++ ep->dwc_ep.maxxfer -= ++ (ep->dwc_ep.maxxfer % ep->dwc_ep.maxpacket); ++ } ++ if (req->sent_zlp) { ++ if ((ep->dwc_ep.total_len % ++ ep->dwc_ep.maxpacket == 0) ++ && (ep->dwc_ep.total_len != 0)) { ++ ep->dwc_ep.sent_zlp = 1; ++ } ++ ++ } ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep); ++ } else if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ diepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ intr_mask.b.nak = 1; ++ ++ if (GET_CORE_IF(ep->pcd)->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&GET_CORE_IF(ep->pcd)->dev_if->dev_global_regs-> ++ diepeachintmsk[ep->dwc_ep.num], intr_mask.d32, 0); ++ } else { ++ DWC_MODIFY_REG32(&GET_CORE_IF(ep->pcd)->dev_if->dev_global_regs->diepmsk, ++ intr_mask.d32, 0); ++ } ++ DWC_PRINTF("There are no more ISOC requests \n"); ++ ep->dwc_ep.frame_num = 0xFFFFFFFF; ++ } ++} ++ ++/** ++ * This function handles the SOF Interrupts. At this time the SOF ++ * Interrupt is disabled. ++ */ ++int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ gintsts_data_t gintsts; ++ ++ DWC_DEBUGPL(DBG_PCD, "SOF\n"); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.sofintr = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This function handles the Rx Status Queue Level Interrupt, which ++ * indicates that there is a least one packet in the Rx FIFO. The ++ * packets are moved from the FIFO to memory, where they will be ++ * processed when the Endpoint Interrupt Register indicates Transfer ++ * Complete or SETUP Phase Done. ++ * ++ * Repeat the following until the Rx Status Queue is empty: ++ * -# Read the Receive Status Pop Register (GRXSTSP) to get Packet ++ * info ++ * -# If Receive FIFO is empty then skip to step Clear the interrupt ++ * and exit ++ * -# If SETUP Packet call dwc_otg_read_setup_packet to copy the ++ * SETUP data to the buffer ++ * -# If OUT Data Packet call dwc_otg_read_packet to copy the data ++ * to the destination buffer ++ */ ++int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gintmsk_data_t gintmask = {.d32 = 0 }; ++ device_grxsts_data_t status; ++ dwc_otg_pcd_ep_t *ep; ++ gintsts_data_t gintsts; ++#ifdef DEBUG ++ static char *dpid_str[] = { "D0", "D2", "D1", "MDATA" }; ++#endif ++ ++ //DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd); ++ /* Disable the Rx Status Queue Level interrupt */ ++ gintmask.b.rxstsqlvl = 1; ++ DWC_MODIFY_REG32(&global_regs->gintmsk, gintmask.d32, 0); ++ ++ /* Get the Status from the top of the FIFO */ ++ status.d32 = DWC_READ_REG32(&global_regs->grxstsp); ++ ++ DWC_DEBUGPL(DBG_PCD, "EP:%d BCnt:%d DPID:%s " ++ "pktsts:%x Frame:%d(0x%0x)\n", ++ status.b.epnum, status.b.bcnt, ++ dpid_str[status.b.dpid], ++ status.b.pktsts, status.b.fn, status.b.fn); ++ /* Get pointer to EP structure */ ++ ep = get_out_ep(pcd, status.b.epnum); ++ if (!ep) ++ return -EINVAL; ++ ++ switch (status.b.pktsts) { ++ case DWC_DSTS_GOUT_NAK: ++ DWC_DEBUGPL(DBG_PCDV, "Global OUT NAK\n"); ++ break; ++ case DWC_STS_DATA_UPDT: ++ DWC_DEBUGPL(DBG_PCDV, "OUT Data Packet\n"); ++ if (status.b.bcnt && ep->dwc_ep.xfer_buff) { ++ /** @todo NGS Check for buffer overflow? */ ++ dwc_otg_read_packet(core_if, ++ ep->dwc_ep.xfer_buff, ++ status.b.bcnt); ++ ep->dwc_ep.xfer_count += status.b.bcnt; ++ ep->dwc_ep.xfer_buff += status.b.bcnt; ++ } ++ if (status.b.bcnt &&(status.b.bcnt<1024) ++ && !ep->dwc_ep.xfer_buff) { ++ dwc_otg_read_packet(core_if, ++ readpacket_buf, ++ status.b.bcnt); ++ ep->dwc_ep.xfer_count += status.b.bcnt; ++ } ++ break; ++ case DWC_STS_XFER_COMP: ++ DWC_DEBUGPL(DBG_PCDV, "OUT Complete\n"); ++ break; ++ case DWC_DSTS_SETUP_COMP: ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCDV, "Setup Complete\n"); ++#endif ++ break; ++ case DWC_DSTS_SETUP_UPDT: ++ dwc_otg_read_setup_packet(core_if, pcd->setup_pkt->d32); ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, ++ "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n", ++ pcd->setup_pkt->req.bmRequestType, ++ pcd->setup_pkt->req.bRequest, ++ UGETW(pcd->setup_pkt->req.wValue), ++ UGETW(pcd->setup_pkt->req.wIndex), ++ UGETW(pcd->setup_pkt->req.wLength)); ++#endif ++ ep->dwc_ep.xfer_count += status.b.bcnt; ++ break; ++ default: ++ DWC_DEBUGPL(DBG_PCDV, "Invalid Packet Status (0x%0x)\n", ++ status.b.pktsts); ++ break; ++ } ++ ++ /* Enable the Rx Status Queue Level interrupt */ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmask.d32); ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.rxstsqlvl = 1; ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ //DWC_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__); ++ return 1; ++} ++ ++/** ++ * This function examines the Device IN Token Learning Queue to ++ * determine the EP number of the last IN token received. This ++ * implementation is for the Mass Storage device where there are only ++ * 2 IN EPs (Control-IN and BULK-IN). ++ * ++ * The EP numbers for the first six IN Tokens are in DTKNQR1 and there ++ * are 8 EP Numbers in each of the other possible DTKNQ Registers. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * ++ */ ++static inline int get_ep_of_last_in_token(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_device_global_regs_t *dev_global_regs = ++ core_if->dev_if->dev_global_regs; ++ const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth; ++ /* Number of Token Queue Registers */ ++ const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8; ++ dtknq1_data_t dtknqr1; ++ uint32_t in_tkn_epnums[4]; ++ int ndx = 0; ++ int i = 0; ++ volatile uint32_t *addr = &dev_global_regs->dtknqr1; ++ int epnum = 0; ++ ++ //DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH); ++ ++ /* Read the DTKNQ Registers */ ++ for (i = 0; i < DTKNQ_REG_CNT; i++) { ++ in_tkn_epnums[i] = DWC_READ_REG32(addr); ++ DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1, ++ in_tkn_epnums[i]); ++ if (addr == &dev_global_regs->dvbusdis) { ++ addr = &dev_global_regs->dtknqr3_dthrctl; ++ } else { ++ ++addr; ++ } ++ ++ } ++ ++ /* Copy the DTKNQR1 data to the bit field. */ ++ dtknqr1.d32 = in_tkn_epnums[0]; ++ /* Get the EP numbers */ ++ in_tkn_epnums[0] = dtknqr1.b.epnums0_5; ++ ndx = dtknqr1.b.intknwptr - 1; ++ ++ //DWC_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx); ++ if (ndx == -1) { ++ /** @todo Find a simpler way to calculate the max ++ * queue position.*/ ++ int cnt = TOKEN_Q_DEPTH; ++ if (TOKEN_Q_DEPTH <= 6) { ++ cnt = TOKEN_Q_DEPTH - 1; ++ } else if (TOKEN_Q_DEPTH <= 14) { ++ cnt = TOKEN_Q_DEPTH - 7; ++ } else if (TOKEN_Q_DEPTH <= 22) { ++ cnt = TOKEN_Q_DEPTH - 15; ++ } else { ++ cnt = TOKEN_Q_DEPTH - 23; ++ } ++ epnum = (in_tkn_epnums[DTKNQ_REG_CNT - 1] >> (cnt * 4)) & 0xF; ++ } else { ++ if (ndx <= 5) { ++ epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF; ++ } else if (ndx <= 13) { ++ ndx -= 6; ++ epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF; ++ } else if (ndx <= 21) { ++ ndx -= 14; ++ epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF; ++ } else if (ndx <= 29) { ++ ndx -= 22; ++ epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF; ++ } ++ } ++ //DWC_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum); ++ return epnum; ++} ++ ++/** ++ * This interrupt occurs when the non-periodic Tx FIFO is half-empty. ++ * The active request is checked for the next packet to be loaded into ++ * the non-periodic Tx FIFO. ++ */ ++int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ dwc_otg_dev_in_ep_regs_t *ep_regs; ++ gnptxsts_data_t txstatus = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ ++ int epnum = 0; ++ dwc_otg_pcd_ep_t *ep = 0; ++ uint32_t len = 0; ++ int dwords; ++ ++ /* Get the epnum from the IN Token Learning Queue. */ ++ epnum = get_ep_of_last_in_token(core_if); ++ ep = get_in_ep(pcd, epnum); ++ if (!ep) ++ return -EINVAL; ++ ++ DWC_DEBUGPL(DBG_PCD, "NP TxFifo Empty: %d \n", epnum); ++ ++ ep_regs = core_if->dev_if->in_ep_regs[epnum]; ++ ++ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; ++ if (len > ep->dwc_ep.maxpacket) { ++ len = ep->dwc_ep.maxpacket; ++ } ++ dwords = (len + 3) / 4; ++ ++ /* While there is space in the queue and space in the FIFO and ++ * More data to tranfer, Write packets to the Tx FIFO */ ++ txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts); ++ DWC_DEBUGPL(DBG_PCDV, "b4 GNPTXSTS=0x%08x\n", txstatus.d32); ++ ++ while (txstatus.b.nptxqspcavail > 0 && ++ txstatus.b.nptxfspcavail > dwords && ++ ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len) { ++ /* Write the FIFO */ ++ dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0); ++ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; ++ ++ if (len > ep->dwc_ep.maxpacket) { ++ len = ep->dwc_ep.maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts); ++ DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", txstatus.d32); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxsts)); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.nptxfempty = 1; ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This function is called when dedicated Tx FIFO Empty interrupt occurs. ++ * The active request is checked for the next packet to be loaded into ++ * apropriate Tx FIFO. ++ */ ++static int32_t write_empty_tx_fifo(dwc_otg_pcd_t * pcd, uint32_t epnum) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dwc_otg_dev_in_ep_regs_t *ep_regs; ++ dtxfsts_data_t txstatus = {.d32 = 0 }; ++ dwc_otg_pcd_ep_t *ep = 0; ++ uint32_t len = 0; ++ int dwords; ++ ++ ep = get_in_ep(pcd, epnum); ++ if (!ep) ++ return -EINVAL; ++ ++ DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum); ++ ++ ep_regs = core_if->dev_if->in_ep_regs[epnum]; ++ ++ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; ++ ++ if (len > ep->dwc_ep.maxpacket) { ++ len = ep->dwc_ep.maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ ++ /* While there is space in the queue and space in the FIFO and ++ * More data to tranfer, Write packets to the Tx FIFO */ ++ txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32); ++ ++ while (txstatus.b.txfspcavail >= dwords && ++ ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len && ++ ep->dwc_ep.xfer_len != 0) { ++ /* Write the FIFO */ ++ dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0); ++ ++ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; ++ if (len > ep->dwc_ep.maxpacket) { ++ len = ep->dwc_ep.maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ txstatus.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum, ++ txstatus.d32); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts)); ++ ++ return 1; ++} ++ ++/** ++ * This function is called when the Device is disconnected. It stops ++ * any active requests and informs the Gadget driver of the ++ * disconnect. ++ */ ++void dwc_otg_pcd_stop(dwc_otg_pcd_t * pcd) ++{ ++ int i, num_in_eps, num_out_eps; ++ dwc_otg_pcd_ep_t *ep; ++ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_SPINLOCK(pcd->lock); ++ ++ num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps; ++ num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s() \n", __func__); ++ /* don't disconnect drivers more than once */ ++ if (pcd->ep0state == EP0_DISCONNECT) { ++ DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__); ++ DWC_SPINUNLOCK(pcd->lock); ++ return; ++ } ++ pcd->ep0state = EP0_DISCONNECT; ++ ++ /* Reset the OTG state. */ ++ dwc_otg_pcd_update_otg(pcd, 1); ++ ++ /* Disable the NP Tx Fifo Empty Interrupt. */ ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Flush the FIFOs */ ++ /**@todo NGS Flush Periodic FIFOs */ ++ dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), 0x10); ++ dwc_otg_flush_rx_fifo(GET_CORE_IF(pcd)); ++ ++ /* prevent new request submissions, kill any outstanding requests */ ++ ep = &pcd->ep0; ++ dwc_otg_request_nuke(ep); ++ /* prevent new request submissions, kill any outstanding requests */ ++ for (i = 0; i < num_in_eps; i++) { ++ dwc_otg_pcd_ep_t *ep = &pcd->in_ep[i]; ++ dwc_otg_request_nuke(ep); ++ } ++ /* prevent new request submissions, kill any outstanding requests */ ++ for (i = 0; i < num_out_eps; i++) { ++ dwc_otg_pcd_ep_t *ep = &pcd->out_ep[i]; ++ dwc_otg_request_nuke(ep); ++ } ++ ++ /* report disconnect; the driver is already quiesced */ ++ if (pcd->fops->disconnect) { ++ DWC_SPINUNLOCK(pcd->lock); ++ pcd->fops->disconnect(pcd); ++ DWC_SPINLOCK(pcd->lock); ++ } ++ DWC_SPINUNLOCK(pcd->lock); ++} ++ ++/** ++ * This interrupt indicates that ... ++ */ ++int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "i2cintr"); ++ intr_mask.b.i2cintr = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.i2cintr = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that ... ++ */ ++int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintsts_data_t gintsts; ++ ++ DWC_DEBUGPL(DBG_PCDV,"Early Suspend Detected\n"); ++ ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.erlysuspend = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This function configures EPO to receive SETUP packets. ++ * ++ * @todo NGS: Update the comments from the HW FS. ++ * ++ * -# Program the following fields in the endpoint specific registers ++ * for Control OUT EP 0, in order to receive a setup packet ++ * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back ++ * setup packets) ++ * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back ++ * to back setup packets) ++ * - In DMA mode, DOEPDMA0 Register with a memory address to ++ * store any setup packets received ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param pcd Programming view of the PCD. ++ */ ++static inline void ep0_out_start(dwc_otg_core_if_t * core_if, ++ dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ deptsiz0_data_t doeptsize0 = {.d32 = 0 }; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ depctl_data_t doepctl = {.d32 = 0 }; ++ ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, "%s() doepctl0=%0x\n", __func__, ++ DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl)); ++#endif ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl); ++ if (doepctl.b.epena) { ++ return; ++ } ++ } ++ ++ doeptsize0.b.supcnt = 3; ++ doeptsize0.b.pktcnt = 1; ++ doeptsize0.b.xfersize = 8 * 3; ++ ++ if (core_if->dma_enable) { ++ if (!core_if->dma_desc_enable) { ++ /** put here as for Hermes mode deptisz register should not be written */ ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz, ++ doeptsize0.d32); ++ ++ /** @todo dma needs to handle multiple setup packets (up to 3) */ ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma, ++ pcd->setup_pkt_dma_handle); ++ } else { ++ dev_if->setup_desc_index = ++ (dev_if->setup_desc_index + 1) & 1; ++ dma_desc = ++ dev_if->setup_desc_addr[dev_if->setup_desc_index]; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ dma_desc->status.b.sr = 0; ++ dma_desc->status.b.mtrf = 0; ++ } ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.bytes = pcd->ep0.dwc_ep.maxpacket; ++ dma_desc->buf = pcd->setup_pkt_dma_handle; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DOEPDMA0 Register write */ ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma, ++ dev_if->dma_setup_desc_addr ++ [dev_if->setup_desc_index]); ++ } ++ ++ } else { ++ /** put here as for Hermes mode deptisz register should not be written */ ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz, ++ doeptsize0.d32); ++ } ++ ++ /** DOEPCTL0 Register write cnak will be set after setup interrupt */ ++ doepctl.d32 = 0; ++ doepctl.b.epena = 1; ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) { ++ doepctl.b.cnak = 1; ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); ++ } else { ++ DWC_MODIFY_REG32(&dev_if->out_ep_regs[0]->doepctl, 0, doepctl.d32); ++ } ++ ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n", ++ DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl)); ++ DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n", ++ DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl)); ++#endif ++} ++ ++/** ++ * This interrupt occurs when a USB Reset is detected. When the USB ++ * Reset Interrupt occurs the device state is set to DEFAULT and the ++ * EP0 state is set to IDLE. ++ * -# Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1) ++ * -# Unmask the following interrupt bits ++ * - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint) ++ * - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint) ++ * - DOEPMSK.SETUP = 1 ++ * - DOEPMSK.XferCompl = 1 ++ * - DIEPMSK.XferCompl = 1 ++ * - DIEPMSK.TimeOut = 1 ++ * -# Program the following fields in the endpoint specific registers ++ * for Control OUT EP 0, in order to receive a setup packet ++ * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back ++ * setup packets) ++ * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back ++ * to back setup packets) ++ * - In DMA mode, DOEPDMA0 Register with a memory address to ++ * store any setup packets received ++ * At this point, all the required initialization, except for enabling ++ * the control 0 OUT endpoint is done, for receiving SETUP packets. ++ */ ++int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ depctl_data_t doepctl = {.d32 = 0 }; ++ depctl_data_t diepctl = {.d32 = 0 }; ++ daint_data_t daintmsk = {.d32 = 0 }; ++ doepmsk_data_t doepmsk = {.d32 = 0 }; ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ dcfg_data_t dcfg = {.d32 = 0 }; ++ grstctl_t resetctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ int i = 0; ++ gintsts_data_t gintsts; ++ pcgcctl_data_t power = {.d32 = 0 }; ++ ++ power.d32 = DWC_READ_REG32(core_if->pcgcctl); ++ if (power.b.stoppclk) { ++ power.d32 = 0; ++ power.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0); ++ ++ power.b.pwrclmp = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0); ++ ++ power.b.rstpdwnmodule = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0); ++ } ++ ++ core_if->lx_state = DWC_OTG_L0; ++ core_if->otg_sts = 0; ++ ++ ++#ifdef DWC_EN_ISOC ++ for (i = 1; i < 16; ++i) { ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ ep = get_in_ep(pcd, i); ++ if (ep != 0) { ++ dwc_ep = &ep->dwc_ep; ++ dwc_ep->next_frame = 0xffffffff; ++ } ++ } ++#endif /* DWC_EN_ISOC */ ++ ++ /* reset the HNP settings */ ++ dwc_otg_pcd_update_otg(pcd, 1); ++ ++ /* Clear the Remote Wakeup Signalling */ ++ dctl.b.rmtwkupsig = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); ++ ++ /* Set NAK for all OUT EPs */ ++ doepctl.b.snak = 1; ++ for (i = 0; i <= dev_if->num_out_eps; i++) { ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32); ++ } ++ ++ /* Flush the NP Tx FIFO */ ++ dwc_otg_flush_tx_fifo(core_if, 0x10); ++ /* Flush the Learning Queue */ ++ resetctl.b.intknqflsh = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); ++ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) { ++ core_if->start_predict = 0; ++ for (i = 0; i <= core_if->dev_if->num_in_eps; ++i) { ++ core_if->nextep_seq[i] = 0xff; // 0xff - EP not active ++ } ++ core_if->nextep_seq[0] = 0; ++ core_if->first_in_nextep_seq = 0; ++ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); ++ diepctl.b.nextep = 0; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); ++ ++ /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */ ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt = 2; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); ++ } ++ } ++ ++ if (core_if->multiproc_int_enable) { ++ daintmsk.b.inep0 = 1; ++ daintmsk.b.outep0 = 1; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, ++ daintmsk.d32); ++ ++ doepmsk.b.setup = 1; ++ doepmsk.b.xfercompl = 1; ++ doepmsk.b.ahberr = 1; ++ doepmsk.b.epdisabled = 1; ++ ++ if ((core_if->dma_desc_enable) || ++ (core_if->dma_enable ++ && core_if->snpsid >= OTG_CORE_REV_3_00a)) { ++ doepmsk.b.stsphsercvd = 1; ++ } ++ if (core_if->dma_desc_enable) ++ doepmsk.b.bna = 1; ++/* ++ doepmsk.b.babble = 1; ++ doepmsk.b.nyet = 1; ++ ++ if (core_if->dma_enable) { ++ doepmsk.b.nak = 1; ++ } ++*/ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->doepeachintmsk[0], ++ doepmsk.d32); ++ ++ diepmsk.b.xfercompl = 1; ++ diepmsk.b.timeout = 1; ++ diepmsk.b.epdisabled = 1; ++ diepmsk.b.ahberr = 1; ++ diepmsk.b.intknepmis = 1; ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) ++ diepmsk.b.intknepmis = 0; ++ ++/* if (core_if->dma_desc_enable) { ++ diepmsk.b.bna = 1; ++ } ++*/ ++/* ++ if (core_if->dma_enable) { ++ diepmsk.b.nak = 1; ++ } ++*/ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->diepeachintmsk[0], ++ diepmsk.d32); ++ } else { ++ daintmsk.b.inep0 = 1; ++ daintmsk.b.outep0 = 1; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, ++ daintmsk.d32); ++ ++ doepmsk.b.setup = 1; ++ doepmsk.b.xfercompl = 1; ++ doepmsk.b.ahberr = 1; ++ doepmsk.b.epdisabled = 1; ++ ++ if ((core_if->dma_desc_enable) || ++ (core_if->dma_enable ++ && core_if->snpsid >= OTG_CORE_REV_3_00a)) { ++ doepmsk.b.stsphsercvd = 1; ++ } ++ if (core_if->dma_desc_enable) ++ doepmsk.b.bna = 1; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32); ++ ++ diepmsk.b.xfercompl = 1; ++ diepmsk.b.timeout = 1; ++ diepmsk.b.epdisabled = 1; ++ diepmsk.b.ahberr = 1; ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) ++ diepmsk.b.intknepmis = 0; ++/* ++ if (core_if->dma_desc_enable) { ++ diepmsk.b.bna = 1; ++ } ++*/ ++ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32); ++ } ++ ++ /* Reset Device Address */ ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.devaddr = 0; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ /* setup EP0 to receive SETUP packets */ ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) ++ ep0_out_start(core_if, pcd); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.usbreset = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * Get the device speed from the device status register and convert it ++ * to USB speed constant. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static int get_device_speed(dwc_otg_core_if_t * core_if) ++{ ++ dsts_data_t dsts; ++ int speed = 0; ++ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ switch (dsts.b.enumspd) { ++ case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: ++ speed = USB_SPEED_HIGH; ++ break; ++ case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: ++ case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ: ++ speed = USB_SPEED_FULL; ++ break; ++ ++ case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ: ++ speed = USB_SPEED_LOW; ++ break; ++ } ++ ++ return speed; ++} ++ ++/** ++ * Read the device status register and set the device speed in the ++ * data structure. ++ * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate. ++ */ ++int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ gintsts_data_t gintsts; ++ gusbcfg_data_t gusbcfg; ++ dwc_otg_core_global_regs_t *global_regs = ++ GET_CORE_IF(pcd)->core_global_regs; ++ uint8_t utmi16b, utmi8b; ++ int speed; ++ dcfg_data_t dcfg; ++ ++ DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n"); ++ ++ /* WA for the case when SW gets SPEED ENUM without first USB RESET case ++ * due to USB RESET issued by the host earlier. Anyways USB Reset routine ++ * needs to be called to at least program EP 0 OUT - vahrama ++ */ ++ dcfg.d32 = DWC_READ_REG32(&pcd->core_if->dev_if->dev_global_regs->dcfg); ++ if (pcd->core_if->otg_ver && dcfg.b.devaddr) ++ dwc_otg_pcd_handle_usb_reset_intr(pcd); ++ ++ ++ if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) { ++ utmi16b = 6; //vahrama old value was 6; ++ utmi8b = 9; ++ } else { ++ utmi16b = 4; ++ utmi8b = 8; ++ } ++ dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep); ++ if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) { ++ ep0_out_start(GET_CORE_IF(pcd), pcd); ++ } ++ ++#ifdef DEBUG_EP0 ++ print_ep0_state(pcd); ++#endif ++ ++ if (pcd->ep0state == EP0_DISCONNECT) { ++ pcd->ep0state = EP0_IDLE; ++ } else if (pcd->ep0state == EP0_STALL) { ++ pcd->ep0state = EP0_IDLE; ++ } ++ ++ pcd->ep0state = EP0_IDLE; ++ ++ ep0->stopped = 0; ++ ++ speed = get_device_speed(GET_CORE_IF(pcd)); ++ pcd->fops->connect(pcd, speed); ++ ++ /* Set USB turnaround time based on device speed and PHY interface. */ ++ gusbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); ++ if (speed == USB_SPEED_HIGH) { ++ if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == ++ DWC_HWCFG2_HS_PHY_TYPE_ULPI) { ++ /* ULPI interface */ ++ gusbcfg.b.usbtrdtim = 9; ++ } ++ if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == ++ DWC_HWCFG2_HS_PHY_TYPE_UTMI) { ++ /* UTMI+ interface */ ++ if (GET_CORE_IF(pcd)->hwcfg4.b.utmi_phy_data_width == 0) { ++ gusbcfg.b.usbtrdtim = utmi8b; ++ } else if (GET_CORE_IF(pcd)->hwcfg4. ++ b.utmi_phy_data_width == 1) { ++ gusbcfg.b.usbtrdtim = utmi16b; ++ } else if (GET_CORE_IF(pcd)-> ++ core_params->phy_utmi_width == 8) { ++ gusbcfg.b.usbtrdtim = utmi8b; ++ } else { ++ gusbcfg.b.usbtrdtim = utmi16b; ++ } ++ } ++ if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == ++ DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) { ++ /* UTMI+ OR ULPI interface */ ++ if (gusbcfg.b.ulpi_utmi_sel == 1) { ++ /* ULPI interface */ ++ gusbcfg.b.usbtrdtim = 9; ++ } else { ++ /* UTMI+ interface */ ++ if (GET_CORE_IF(pcd)-> ++ core_params->phy_utmi_width == 16) { ++ gusbcfg.b.usbtrdtim = utmi16b; ++ } else { ++ gusbcfg.b.usbtrdtim = utmi8b; ++ } ++ } ++ } ++ } else { ++ /* Full or low speed */ ++ gusbcfg.b.usbtrdtim = 9; ++ } ++ DWC_WRITE_REG32(&global_regs->gusbcfg, gusbcfg.d32); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.enumdone = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that the ISO OUT Packet was dropped due to ++ * Rx FIFO full or Rx Status Queue Full. If this interrupt occurs ++ * read all the data from the Rx FIFO. ++ */ ++int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ ++ DWC_WARN("INTERRUPT Handler not implemented for %s\n", ++ "ISOC Out Dropped"); ++ ++ intr_mask.b.isooutdrop = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.isooutdrop = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates the end of the portion of the micro-frame ++ * for periodic transactions. If there is a periodic transaction for ++ * the next frame, load the packets into the EP periodic Tx FIFO. ++ */ ++int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "EOP"); ++ ++ intr_mask.b.eopframe = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.eopframe = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that EP of the packet on the top of the ++ * non-periodic Tx FIFO does not match EP of the IN Token received. ++ * ++ * The "Device IN Token Queue" Registers are read to determine the ++ * order the IN Tokens have been received. The non-periodic Tx FIFO ++ * is flushed, so it can be reloaded in the order seen in the IN Token ++ * Queue. ++ */ ++int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintsts_data_t gintsts; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dctl_data_t dctl; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) { ++ core_if->start_predict = 1; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if); ++ ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (!gintsts.b.ginnakeff) { ++ /* Disable EP Mismatch interrupt */ ++ intr_mask.d32 = 0; ++ intr_mask.b.epmismatch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32, 0); ++ /* Enable the Global IN NAK Effective Interrupt */ ++ intr_mask.d32 = 0; ++ intr_mask.b.ginnakeff = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32); ++ /* Set the global non-periodic IN NAK handshake */ ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ dctl.b.sgnpinnak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++ } else { ++ DWC_PRINTF("gintsts.b.ginnakeff = 1! dctl.b.sgnpinnak not set\n"); ++ } ++ /* Disabling of all EP's will be done in dwc_otg_pcd_handle_in_nak_effective() ++ * handler after Global IN NAK Effective interrupt will be asserted */ ++ } ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.epmismatch = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt is valid only in DMA mode. This interrupt indicates that the ++ * core has stopped fetching data for IN endpoints due to the unavailability of ++ * TxFIFO space or Request Queue space. This interrupt is used by the ++ * application for an endpoint mismatch algorithm. ++ * ++ * @param pcd The PCD ++ */ ++int32_t dwc_otg_pcd_handle_ep_fetsusp_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintsts_data_t gintsts; ++ gintmsk_data_t gintmsk_data; ++ dctl_data_t dctl; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if); ++ ++ /* Clear the global non-periodic IN NAK handshake */ ++ dctl.d32 = 0; ++ dctl.b.cgnpinnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ ++ /* Mask GINTSTS.FETSUSP interrupt */ ++ gintmsk_data.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ gintmsk_data.b.fetsusp = 0; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk_data.d32); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.fetsusp = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This funcion stalls EP0. ++ */ ++static inline void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val) ++{ ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++// usb_device_request_t *ctrl = &pcd->setup_pkt->req; ++// DWC_WARN("req %02x.%02x protocol STALL; err %d\n", ++// ctrl->bmRequestType, ctrl->bRequest, err_val); ++ ++ ep0->dwc_ep.is_in = 1; ++ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->dwc_ep); ++ ep0->dwc_ep.is_in = 0; ++ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->dwc_ep); ++ pcd->ep0.stopped = 1; ++ pcd->ep0state = EP0_IDLE; ++ ep0_out_start(GET_CORE_IF(pcd), pcd); ++} ++ ++/** ++ * This functions delegates the setup command to the gadget driver. ++ */ ++static inline void do_gadget_setup(dwc_otg_pcd_t * pcd, ++ usb_device_request_t * ctrl) ++{ ++ int ret = 0; ++ DWC_SPINUNLOCK(pcd->lock); ++ ret = pcd->fops->setup(pcd, (uint8_t *) ctrl); ++ DWC_SPINLOCK(pcd->lock); ++ if (ret < 0) { ++ ep0_do_stall(pcd, ret); ++ } ++ ++ /** @todo This is a g_file_storage gadget driver specific ++ * workaround: a DELAYED_STATUS result from the fsg_setup ++ * routine will result in the gadget queueing a EP0 IN status ++ * phase for a two-stage control transfer. Exactly the same as ++ * a SET_CONFIGURATION/SET_INTERFACE except that this is a class ++ * specific request. Need a generic way to know when the gadget ++ * driver will queue the status phase. Can we assume when we ++ * call the gadget driver setup() function that it will always ++ * queue and require the following flag? Need to look into ++ * this. ++ */ ++ ++ if (ret == 256 + 999) { ++ pcd->request_config = 1; ++ } ++} ++ ++#ifdef DWC_UTE_CFI ++/** ++ * This functions delegates the CFI setup commands to the gadget driver. ++ * This function will return a negative value to indicate a failure. ++ */ ++static inline int cfi_gadget_setup(dwc_otg_pcd_t * pcd, ++ struct cfi_usb_ctrlrequest *ctrl_req) ++{ ++ int ret = 0; ++ ++ if (pcd->fops && pcd->fops->cfi_setup) { ++ DWC_SPINUNLOCK(pcd->lock); ++ ret = pcd->fops->cfi_setup(pcd, ctrl_req); ++ DWC_SPINLOCK(pcd->lock); ++ if (ret < 0) { ++ ep0_do_stall(pcd, ret); ++ return ret; ++ } ++ } ++ ++ return ret; ++} ++#endif ++ ++/** ++ * This function starts the Zero-Length Packet for the IN status phase ++ * of a 2 stage control transfer. ++ */ ++static inline void do_setup_in_status_phase(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ if (pcd->ep0state == EP0_STALL) { ++ return; ++ } ++ ++ pcd->ep0state = EP0_IN_STATUS_PHASE; ++ ++ /* Prepare for more SETUP Packets */ ++ DWC_DEBUGPL(DBG_PCD, "EP0 IN ZLP\n"); ++ if ((GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) ++ && (pcd->core_if->dma_desc_enable) ++ && (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len)) { ++ DWC_DEBUGPL(DBG_PCDV, ++ "Data terminated wait next packet in out_desc_addr\n"); ++ pcd->backup_buf = phys_to_virt(ep0->dwc_ep.dma_addr); ++ pcd->data_terminated = 1; ++ } ++ ep0->dwc_ep.xfer_len = 0; ++ ep0->dwc_ep.xfer_count = 0; ++ ep0->dwc_ep.is_in = 1; ++ ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle; ++ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep); ++ ++ /* Prepare for more SETUP Packets */ ++ //ep0_out_start(GET_CORE_IF(pcd), pcd); ++} ++ ++/** ++ * This function starts the Zero-Length Packet for the OUT status phase ++ * of a 2 stage control transfer. ++ */ ++static inline void do_setup_out_status_phase(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ doepint_data_t doepint; ++ doepint.d32 = DWC_READ_REG32(&pcd->core_if->dev_if->out_ep_regs[0]->doepint); ++ if (pcd->ep0state == EP0_STALL) { ++ DWC_DEBUGPL(DBG_PCD, "EP0 STALLED\n"); ++ return; ++ } ++ pcd->ep0state = EP0_OUT_STATUS_PHASE; ++ ++ DWC_DEBUGPL(DBG_PCD, "EP0 OUT ZLP\n"); ++ ep0->dwc_ep.xfer_len = 0; ++ ep0->dwc_ep.xfer_count = 0; ++ ep0->dwc_ep.is_in = 0; ++ ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle; ++ /* If there is xfercomplete on EP0 OUT do not start OUT Status stage. ++ * xfercomplete means that ZLP was already received as EP0 OUT is enabled ++ * during IN Data stage ++ */ ++ if ((doepint.b.xfercompl == 1) && (pcd->core_if->snpsid >= OTG_CORE_REV_3_00a) ++ && (pcd->core_if->dma_enable == 1) && (pcd->core_if->dma_desc_enable == 0)) { ++ DWC_DEBUGPL(DBG_PCD, "Status stage already completed\n"); ++ return; ++ } ++ ++ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep); ++ ++ /* Prepare for more SETUP Packets */ ++ if (GET_CORE_IF(pcd)->dma_enable == 0) { ++ ep0_out_start(GET_CORE_IF(pcd), pcd); ++ } ++} ++ ++/** ++ * Clear the EP halt (STALL) and if pending requests start the ++ * transfer. ++ */ ++static inline void pcd_clear_halt(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep) ++{ ++ if (ep->dwc_ep.stall_clear_flag) { ++ /* Start Control Status Phase */ ++ do_setup_in_status_phase(pcd); ++ return; ++ } ++ ++ dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep); ++ ++ /* Reactive the EP */ ++ dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep); ++ if (ep->stopped) { ++ ep->stopped = 0; ++ /* If there is a request in the EP queue start it */ ++ ++ /** @todo FIXME: this causes an EP mismatch in DMA mode. ++ * epmismatch not yet implemented. */ ++ ++ /* ++ * Above fixme is solved by implmenting a tasklet to call the ++ * start_next_request(), outside of interrupt context at some ++ * time after the current time, after a clear-halt setup packet. ++ * Still need to implement ep mismatch in the future if a gadget ++ * ever uses more than one endpoint at once ++ */ ++ ep->queue_sof = 1; ++ DWC_TASK_SCHEDULE(pcd->start_xfer_tasklet); ++ } ++ /* Start Control Status Phase */ ++ do_setup_in_status_phase(pcd); ++} ++ ++/** ++ * This function is called when the SET_FEATURE TEST_MODE Setup packet ++ * is sent from the host. The Device Control register is written with ++ * the Test Mode bits set to the specified Test Mode. This is done as ++ * a tasklet so that the "Status" phase of the control transfer ++ * completes before transmitting the TEST packets. ++ * ++ * @todo This has not been tested since the tasklet struct was put ++ * into the PCD struct! ++ * ++ */ ++void do_test_mode(void *data) ++{ ++ dctl_data_t dctl; ++ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ int test_mode = pcd->test_mode; ++ ++// DWC_WARN("%s() has not been tested since being rewritten!\n", __func__); ++ ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ switch (test_mode) { ++ case 1: // TEST_J ++ dctl.b.tstctl = 1; ++ break; ++ ++ case 2: // TEST_K ++ dctl.b.tstctl = 2; ++ break; ++ ++ case 3: // TEST_SE0_NAK ++ dctl.b.tstctl = 3; ++ break; ++ ++ case 4: // TEST_PACKET ++ dctl.b.tstctl = 4; ++ break; ++ ++ case 5: // TEST_FORCE_ENABLE ++ dctl.b.tstctl = 5; ++ break; ++ case 7: ++ dwc_otg_set_hnpreq(core_if, 1); ++ } ++ DWC_PRINTF("test mode = %d\n",test_mode); ++ core_if->test_mode = test_mode; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++} ++ ++/** ++ * This function process the GET_STATUS Setup Commands. ++ */ ++static inline void do_get_status(dwc_otg_pcd_t * pcd) ++{ ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ uint16_t *status = pcd->status_buf; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, ++ "GET_STATUS %02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, ++ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), ++ UGETW(ctrl.wLength)); ++#endif ++ ++ switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { ++ case UT_DEVICE: ++ if (UGETW(ctrl.wIndex) == 0xF000) { /* OTG Status selector */ ++ DWC_PRINTF("wIndex - %d\n", UGETW(ctrl.wIndex)); ++ DWC_PRINTF("OTG VERSION - %d\n", core_if->otg_ver); ++ DWC_PRINTF("OTG CAP - %d, %d\n", ++ core_if->core_params->otg_cap, ++ DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE); ++ if (core_if->otg_ver == 1 ++ && core_if->core_params->otg_cap == ++ DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { ++ uint8_t *otgsts = (uint8_t *) pcd->status_buf; ++ *otgsts = (core_if->otg_sts & 0x1); ++ pcd->ep0_pending = 1; ++ ep0->dwc_ep.start_xfer_buff = ++ (uint8_t *) otgsts; ++ ep0->dwc_ep.xfer_buff = (uint8_t *) otgsts; ++ ep0->dwc_ep.dma_addr = ++ pcd->status_buf_dma_handle; ++ ep0->dwc_ep.xfer_len = 1; ++ ep0->dwc_ep.xfer_count = 0; ++ ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len; ++ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), ++ &ep0->dwc_ep); ++ return; ++ } else { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ break; ++ } else { ++ *status = 0x1; /* Self powered */ ++ *status |= pcd->remote_wakeup_enable << 1; ++ break; ++ } ++ case UT_INTERFACE: ++ *status = 0; ++ break; ++ ++ case UT_ENDPOINT: ++ ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex)); ++ if (ep == 0 || UGETW(ctrl.wLength) > 2) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ /** @todo check for EP stall */ ++ *status = ep->stopped; ++ break; ++ } ++ pcd->ep0_pending = 1; ++ ep0->dwc_ep.start_xfer_buff = (uint8_t *) status; ++ ep0->dwc_ep.xfer_buff = (uint8_t *) status; ++ ep0->dwc_ep.dma_addr = pcd->status_buf_dma_handle; ++ ep0->dwc_ep.xfer_len = 2; ++ ep0->dwc_ep.xfer_count = 0; ++ ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len; ++ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep); ++} ++ ++/** ++ * This function process the SET_FEATURE Setup Commands. ++ */ ++static inline void do_set_feature(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ dwc_otg_pcd_ep_t *ep = 0; ++ int32_t otg_cap_param = core_if->core_params->otg_cap; ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_PCD, "SET_FEATURE:%02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, ++ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), ++ UGETW(ctrl.wLength)); ++ DWC_DEBUGPL(DBG_PCD, "otg_cap=%d\n", otg_cap_param); ++ ++ switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { ++ case UT_DEVICE: ++ switch (UGETW(ctrl.wValue)) { ++ case UF_DEVICE_REMOTE_WAKEUP: ++ pcd->remote_wakeup_enable = 1; ++ break; ++ ++ case UF_TEST_MODE: ++ /* Setup the Test Mode tasklet to do the Test ++ * Packet generation after the SETUP Status ++ * phase has completed. */ ++ ++ /** @todo This has not been tested since the ++ * tasklet struct was put into the PCD ++ * struct! */ ++ pcd->test_mode = UGETW(ctrl.wIndex) >> 8; ++ DWC_TASK_SCHEDULE(pcd->test_mode_tasklet); ++ break; ++ ++ case UF_DEVICE_B_HNP_ENABLE: ++ DWC_DEBUGPL(DBG_PCDV, ++ "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n"); ++ ++ /* dev may initiate HNP */ ++ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { ++ gotgctl.b.devhnpen = 1; ++ if (core_if->otg_ver) { ++ DWC_MODIFY_REG32(&global_regs->gotgctl, 0, gotgctl.d32); ++ /* Ensure that USB Suspend interrupt is unmasked */ ++ gintmsk.b.usbsuspend = 1; ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); ++ } ++ else { ++ pcd->b_hnp_enable = 1; ++ dwc_otg_pcd_update_otg(pcd, 0); ++ DWC_DEBUGPL(DBG_PCD, "Request B HNP\n"); ++ /**@todo Is the gotgctl.devhnpen cleared ++ * by a USB Reset? */ ++ gotgctl.b.hnpreq = 1; ++ DWC_WRITE_REG32(&global_regs->gotgctl, gotgctl.d32); ++ } ++ } else { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ break; ++ ++ case UF_DEVICE_A_HNP_SUPPORT: ++ /* RH port supports HNP */ ++ DWC_DEBUGPL(DBG_PCDV, ++ "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n"); ++ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { ++ pcd->a_hnp_support = 1; ++ dwc_otg_pcd_update_otg(pcd, 0); ++ } else { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ break; ++ ++ case UF_DEVICE_A_ALT_HNP_SUPPORT: ++ /* other RH port does */ ++ DWC_DEBUGPL(DBG_PCDV, ++ "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n"); ++ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { ++ pcd->a_alt_hnp_support = 1; ++ dwc_otg_pcd_update_otg(pcd, 0); ++ } else { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ break; ++ ++ default: ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ ++ } ++ do_setup_in_status_phase(pcd); ++ break; ++ ++ case UT_INTERFACE: ++ do_gadget_setup(pcd, &ctrl); ++ break; ++ ++ case UT_ENDPOINT: ++ if (UGETW(ctrl.wValue) == UF_ENDPOINT_HALT) { ++ ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex)); ++ if (ep == 0) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ep->stopped = 1; ++ dwc_otg_ep_set_stall(core_if, &ep->dwc_ep); ++ } ++ do_setup_in_status_phase(pcd); ++ break; ++ } ++} ++ ++/** ++ * This function process the CLEAR_FEATURE Setup Commands. ++ */ ++static inline void do_clear_feature(dwc_otg_pcd_t * pcd) ++{ ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ dwc_otg_pcd_ep_t *ep = 0; ++ ++ DWC_DEBUGPL(DBG_PCD, ++ "CLEAR_FEATURE:%02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, ++ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), ++ UGETW(ctrl.wLength)); ++ ++ switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { ++ case UT_DEVICE: ++ switch (UGETW(ctrl.wValue)) { ++ case UF_DEVICE_REMOTE_WAKEUP: ++ pcd->remote_wakeup_enable = 0; ++ break; ++ ++ case UF_TEST_MODE: ++ /** @todo Add CLEAR_FEATURE for TEST modes. */ ++ break; ++ ++ default: ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ do_setup_in_status_phase(pcd); ++ break; ++ ++ case UT_ENDPOINT: ++ ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex)); ++ if (ep == 0) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ++ pcd_clear_halt(pcd, ep); ++ ++ break; ++ } ++} ++ ++/** ++ * This function process the SET_ADDRESS Setup Commands. ++ */ ++static inline void do_set_address(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ ++ if (ctrl.bmRequestType == UT_DEVICE) { ++ dcfg_data_t dcfg = {.d32 = 0 }; ++ ++#ifdef DEBUG_EP0 ++// DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue); ++#endif ++ dcfg.b.devaddr = UGETW(ctrl.wValue); ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32); ++ do_setup_in_status_phase(pcd); ++ } ++} ++ ++/** ++ * This function processes SETUP commands. In Linux, the USB Command ++ * processing is done in two places - the first being the PCD and the ++ * second in the Gadget Driver (for example, the File-Backed Storage ++ * Gadget Driver). ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ *
Command Driver Description
GET_STATUS PCD Command is processed as ++ * defined in chapter 9 of the USB 2.0 Specification chapter 9 ++ *
CLEAR_FEATURE PCD The Device and Endpoint ++ * requests are the ENDPOINT_HALT feature is procesed, all others the ++ * interface requests are ignored.
SET_FEATURE PCD The Device and Endpoint ++ * requests are processed by the PCD. Interface requests are passed ++ * to the Gadget Driver.
SET_ADDRESS PCD Program the DCFG reg, ++ * with device address received
GET_DESCRIPTOR Gadget Driver Return the ++ * requested descriptor
SET_DESCRIPTOR Gadget Driver Optional - ++ * not implemented by any of the existing Gadget Drivers.
SET_CONFIGURATION Gadget Driver Disable ++ * all EPs and enable EPs for new configuration.
GET_CONFIGURATION Gadget Driver Return ++ * the current configuration
SET_INTERFACE Gadget Driver Disable all ++ * EPs and enable EPs for new configuration.
GET_INTERFACE Gadget Driver Return the ++ * current interface.
SYNC_FRAME PCD Display debug ++ * message.
++ * ++ * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are ++ * processed by pcd_setup. Calling the Function Driver's setup function from ++ * pcd_setup processes the gadget SETUP commands. ++ */ ++static inline void pcd_setup(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ ++ deptsiz0_data_t doeptsize0 = {.d32 = 0 }; ++ ++#ifdef DWC_UTE_CFI ++ int retval = 0; ++ struct cfi_usb_ctrlrequest cfi_req; ++#endif ++ ++ doeptsize0.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doeptsiz); ++ ++ /** In BDMA more then 1 setup packet is not supported till 3.00a */ ++ if (core_if->dma_enable && core_if->dma_desc_enable == 0 ++ && (doeptsize0.b.supcnt < 2) ++ && (core_if->snpsid < OTG_CORE_REV_2_94a)) { ++ DWC_ERROR ++ ("\n\n----------- CANNOT handle > 1 setup packet in DMA mode\n\n"); ++ } ++ if ((core_if->snpsid >= OTG_CORE_REV_3_00a) ++ && (core_if->dma_enable == 1) && (core_if->dma_desc_enable == 0)) { ++ if (doeptsize0.b.supcnt == 3 && ep0->dwc_ep.stp_rollover == 0) { ++ DWC_ERROR(" !!! Setup packet count was not updated by the core\n"); ++ return; ++ } ++ ctrl = ++ (pcd->setup_pkt + ++ (3 - doeptsize0.b.supcnt - 1 + ++ ep0->dwc_ep.stp_rollover))->req; ++ } ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, ++ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), ++ UGETW(ctrl.wLength)); ++#endif ++ ++ /* Clean up the request queue */ ++ dwc_otg_request_nuke(ep0); ++ ep0->stopped = 0; ++ ++ if (ctrl.bmRequestType & UE_DIR_IN) { ++ ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_DATA_PHASE; ++ } else { ++ ep0->dwc_ep.is_in = 0; ++ pcd->ep0state = EP0_OUT_DATA_PHASE; ++ } ++ ++ if (UGETW(ctrl.wLength) == 0) { ++ ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_STATUS_PHASE; ++ } ++ ++ if (UT_GET_TYPE(ctrl.bmRequestType) != UT_STANDARD) { ++ ++#ifdef DWC_UTE_CFI ++ DWC_MEMCPY(&cfi_req, &ctrl, sizeof(usb_device_request_t)); ++ ++ //printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n", ++ ctrl.bRequestType, ctrl.bRequest); ++ if (UT_GET_TYPE(cfi_req.bRequestType) == UT_VENDOR) { ++ if (cfi_req.bRequest > 0xB0 && cfi_req.bRequest < 0xBF) { ++ retval = cfi_setup(pcd, &cfi_req); ++ if (retval < 0) { ++ ep0_do_stall(pcd, retval); ++ pcd->ep0_pending = 0; ++ return; ++ } ++ ++ /* if need gadget setup then call it and check the retval */ ++ if (pcd->cfi->need_gadget_att) { ++ retval = ++ cfi_gadget_setup(pcd, ++ &pcd-> ++ cfi->ctrl_req); ++ if (retval < 0) { ++ pcd->ep0_pending = 0; ++ return; ++ } ++ } ++ ++ if (pcd->cfi->need_status_in_complete) { ++ do_setup_in_status_phase(pcd); ++ } ++ return; ++ } ++ } ++#endif ++ ++ /* handle non-standard (class/vendor) requests in the gadget driver */ ++ do_gadget_setup(pcd, &ctrl); ++ return; ++ } ++ ++ /** @todo NGS: Handle bad setup packet? */ ++ ++/////////////////////////////////////////// ++//// --- Standard Request handling --- //// ++ ++ switch (ctrl.bRequest) { ++ case UR_GET_STATUS: ++ do_get_status(pcd); ++ break; ++ ++ case UR_CLEAR_FEATURE: ++ do_clear_feature(pcd); ++ break; ++ ++ case UR_SET_FEATURE: ++ do_set_feature(pcd); ++ break; ++ ++ case UR_SET_ADDRESS: ++ do_set_address(pcd); ++ break; ++ ++ case UR_SET_INTERFACE: ++ case UR_SET_CONFIG: ++// _pcd->request_config = 1; /* Configuration changed */ ++ do_gadget_setup(pcd, &ctrl); ++ break; ++ ++ case UR_SYNCH_FRAME: ++ do_gadget_setup(pcd, &ctrl); ++ break; ++ ++ default: ++ /* Call the Gadget Driver's setup functions */ ++ do_gadget_setup(pcd, &ctrl); ++ break; ++ } ++} ++ ++/** ++ * This function completes the ep0 control transfer. ++ */ ++static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dwc_otg_dev_in_ep_regs_t *in_ep_regs = ++ dev_if->in_ep_regs[ep->dwc_ep.num]; ++#ifdef DEBUG_EP0 ++ dwc_otg_dev_out_ep_regs_t *out_ep_regs = ++ dev_if->out_ep_regs[ep->dwc_ep.num]; ++#endif ++ deptsiz0_data_t deptsiz; ++ dev_dma_desc_sts_t desc_sts = {.d32 = 0 }; ++ dwc_otg_pcd_request_t *req; ++ int is_last = 0; ++ dwc_otg_pcd_t *pcd = ep->pcd; ++ ++#ifdef DWC_UTE_CFI ++ struct cfi_usb_ctrlrequest *ctrlreq; ++ int retval = -DWC_E_NOT_SUPPORTED; ++#endif ++ ++ if (pcd->ep0_pending && DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ if (ep->dwc_ep.is_in) { ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCDV, "Do setup OUT status phase\n"); ++#endif ++ do_setup_out_status_phase(pcd); ++ } else { ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCDV, "Do setup IN status phase\n"); ++#endif ++ ++#ifdef DWC_UTE_CFI ++ ctrlreq = &pcd->cfi->ctrl_req; ++ ++ if (UT_GET_TYPE(ctrlreq->bRequestType) == UT_VENDOR) { ++ if (ctrlreq->bRequest > 0xB0 ++ && ctrlreq->bRequest < 0xBF) { ++ ++ /* Return if the PCD failed to handle the request */ ++ if ((retval = ++ pcd->cfi->ops. ++ ctrl_write_complete(pcd->cfi, ++ pcd)) < 0) { ++ CFI_INFO ++ ("ERROR setting a new value in the PCD(%d)\n", ++ retval); ++ ep0_do_stall(pcd, retval); ++ pcd->ep0_pending = 0; ++ return 0; ++ } ++ ++ /* If the gadget needs to be notified on the request */ ++ if (pcd->cfi->need_gadget_att == 1) { ++ //retval = do_gadget_setup(pcd, &pcd->cfi->ctrl_req); ++ retval = ++ cfi_gadget_setup(pcd, ++ &pcd->cfi-> ++ ctrl_req); ++ ++ /* Return from the function if the gadget failed to process ++ * the request properly - this should never happen !!! ++ */ ++ if (retval < 0) { ++ CFI_INFO ++ ("ERROR setting a new value in the gadget(%d)\n", ++ retval); ++ pcd->ep0_pending = 0; ++ return 0; ++ } ++ } ++ ++ CFI_INFO("%s: RETVAL=%d\n", __func__, ++ retval); ++ /* If we hit here then the PCD and the gadget has properly ++ * handled the request - so send the ZLP IN to the host. ++ */ ++ /* @todo: MAS - decide whether we need to start the setup ++ * stage based on the need_setup value of the cfi object ++ */ ++ do_setup_in_status_phase(pcd); ++ pcd->ep0_pending = 0; ++ return 1; ++ } ++ } ++#endif ++ ++ do_setup_in_status_phase(pcd); ++ } ++ pcd->ep0_pending = 0; ++ return 1; ++ } ++ ++ if (DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ return 0; ++ } ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ ++ if (pcd->ep0state == EP0_OUT_STATUS_PHASE ++ || pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ is_last = 1; ++ } else if (ep->dwc_ep.is_in) { ++ deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz); ++ if (core_if->dma_desc_enable != 0) ++ desc_sts = dev_if->in_desc_addr->status; ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCDV, "%d len=%d xfersize=%d pktcnt=%d\n", ++ ep->dwc_ep.num, ep->dwc_ep.xfer_len, ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++#endif ++ ++ if (((core_if->dma_desc_enable == 0) ++ && (deptsiz.b.xfersize == 0)) ++ || ((core_if->dma_desc_enable != 0) ++ && (desc_sts.b.bytes == 0))) { ++ req->actual = ep->dwc_ep.xfer_count; ++ /* Is a Zero Len Packet needed? */ ++ if (req->sent_zlp) { ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n"); ++#endif ++ req->sent_zlp = 0; ++ } ++ do_setup_out_status_phase(pcd); ++ } ++ } else { ++ /* ep0-OUT */ ++#ifdef DEBUG_EP0 ++ deptsiz.d32 = DWC_READ_REG32(&out_ep_regs->doeptsiz); ++ DWC_DEBUGPL(DBG_PCDV, "%d len=%d xsize=%d pktcnt=%d\n", ++ ep->dwc_ep.num, ep->dwc_ep.xfer_len, ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++#endif ++ req->actual = ep->dwc_ep.xfer_count; ++ ++ /* Is a Zero Len Packet needed? */ ++ if (req->sent_zlp) { ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n"); ++#endif ++ req->sent_zlp = 0; ++ } ++ /* For older cores do setup in status phase in Slave/BDMA modes, ++ * starting from 3.00 do that only in slave, and for DMA modes ++ * just re-enable ep 0 OUT here*/ ++ if (core_if->dma_enable == 0 ++ || (core_if->dma_desc_enable == 0 ++ && core_if->snpsid <= OTG_CORE_REV_2_94a)) { ++ do_setup_in_status_phase(pcd); ++ } else if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ DWC_DEBUGPL(DBG_PCDV, ++ "Enable out ep before in status phase\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ ++ /* Complete the request */ ++ if (is_last) { ++ dwc_otg_request_done(ep, req, 0); ++ ep->dwc_ep.start_xfer_buff = 0; ++ ep->dwc_ep.xfer_buff = 0; ++ ep->dwc_ep.xfer_len = 0; ++ return 1; ++ } ++ return 0; ++} ++ ++#ifdef DWC_UTE_CFI ++/** ++ * This function calculates traverses all the CFI DMA descriptors and ++ * and accumulates the bytes that are left to be transfered. ++ * ++ * @return The total bytes left to transfered, or a negative value as failure ++ */ ++static inline int cfi_calc_desc_residue(dwc_otg_pcd_ep_t * ep) ++{ ++ int32_t ret = 0; ++ int i; ++ struct dwc_otg_dma_desc *ddesc = NULL; ++ struct cfi_ep *cfiep; ++ ++ /* See if the pcd_ep has its respective cfi_ep mapped */ ++ cfiep = get_cfi_ep_by_pcd_ep(ep->pcd->cfi, ep); ++ if (!cfiep) { ++ CFI_INFO("%s: Failed to find ep\n", __func__); ++ return -1; ++ } ++ ++ ddesc = ep->dwc_ep.descs; ++ ++ for (i = 0; (i < cfiep->desc_count) && (i < MAX_DMA_DESCS_PER_EP); i++) { ++ ++#if defined(PRINT_CFI_DMA_DESCS) ++ print_desc(ddesc, ep->ep.name, i); ++#endif ++ ret += ddesc->status.b.bytes; ++ ddesc++; ++ } ++ ++ if (ret) ++ CFI_INFO("!!!!!!!!!! WARNING (%s) - residue=%d\n", __func__, ++ ret); ++ ++ return ret; ++} ++#endif ++ ++/** ++ * This function completes the request for the EP. If there are ++ * additional requests for the EP in the queue they will be started. ++ */ ++static void complete_ep(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dwc_otg_dev_in_ep_regs_t *in_ep_regs = ++ dev_if->in_ep_regs[ep->dwc_ep.num]; ++ deptsiz_data_t deptsiz; ++ dev_dma_desc_sts_t desc_sts; ++ dwc_otg_pcd_request_t *req = 0; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ uint32_t byte_count = 0; ++ int is_last = 0; ++ int i; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s() %d-%s\n", __func__, ep->dwc_ep.num, ++ (ep->dwc_ep.is_in ? "IN" : "OUT")); ++ ++ /* Get any pending requests */ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); ++ return; ++ } ++ } else { ++ DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); ++ return; ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "Requests %d\n", ep->pcd->request_pending); ++ ++ if (ep->dwc_ep.is_in) { ++ deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz); ++ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ if (deptsiz.b.xfersize == 0 ++ && deptsiz.b.pktcnt == 0) { ++ byte_count = ++ ep->dwc_ep.xfer_len - ++ ep->dwc_ep.xfer_count; ++ ++ ep->dwc_ep.xfer_buff += byte_count; ++ ep->dwc_ep.dma_addr += byte_count; ++ ep->dwc_ep.xfer_count += byte_count; ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "%d-%s len=%d xfersize=%d pktcnt=%d\n", ++ ep->dwc_ep.num, ++ (ep->dwc_ep. ++ is_in ? "IN" : "OUT"), ++ ep->dwc_ep.xfer_len, ++ deptsiz.b.xfersize, ++ deptsiz.b.pktcnt); ++ ++ if (ep->dwc_ep.xfer_len < ++ ep->dwc_ep.total_len) { ++ dwc_otg_ep_start_transfer ++ (core_if, &ep->dwc_ep); ++ } else if (ep->dwc_ep.sent_zlp) { ++ /* ++ * This fragment of code should initiate 0 ++ * length transfer in case if it is queued ++ * a transfer with size divisible to EPs max ++ * packet size and with usb_request zero field ++ * is set, which means that after data is transfered, ++ * it is also should be transfered ++ * a 0 length packet at the end. For Slave and ++ * Buffer DMA modes in this case SW has ++ * to initiate 2 transfers one with transfer size, ++ * and the second with 0 size. For Descriptor ++ * DMA mode SW is able to initiate a transfer, ++ * which will handle all the packets including ++ * the last 0 length. ++ */ ++ ep->dwc_ep.sent_zlp = 0; ++ dwc_otg_ep_start_zl_transfer ++ (core_if, &ep->dwc_ep); ++ } else { ++ is_last = 1; ++ } ++ } else { ++ if (ep->dwc_ep.type == ++ DWC_OTG_EP_TYPE_ISOC) { ++ req->actual = 0; ++ dwc_otg_request_done(ep, req, 0); ++ ++ ep->dwc_ep.start_xfer_buff = 0; ++ ep->dwc_ep.xfer_buff = 0; ++ ep->dwc_ep.xfer_len = 0; ++ ++ /* If there is a request in the queue start it. */ ++ start_next_request(ep); ++ } else ++ DWC_WARN ++ ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n", ++ ep->dwc_ep.num, ++ (ep->dwc_ep.is_in ? "IN" : "OUT"), ++ deptsiz.b.xfersize, ++ deptsiz.b.pktcnt); ++ } ++ } else { ++ dma_desc = ep->dwc_ep.desc_addr; ++ byte_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ++#ifdef DWC_UTE_CFI ++ CFI_INFO("%s: BUFFER_MODE=%d\n", __func__, ++ ep->dwc_ep.buff_mode); ++ if (ep->dwc_ep.buff_mode != BM_STANDARD) { ++ int residue; ++ ++ residue = cfi_calc_desc_residue(ep); ++ if (residue < 0) ++ return; ++ ++ byte_count = residue; ++ } else { ++#endif ++ for (i = 0; i < ep->dwc_ep.desc_cnt; ++ ++i) { ++ desc_sts = dma_desc->status; ++ byte_count += desc_sts.b.bytes; ++ dma_desc++; ++ } ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ if (byte_count == 0) { ++ ep->dwc_ep.xfer_count = ++ ep->dwc_ep.total_len; ++ is_last = 1; ++ } else { ++ DWC_WARN("Incomplete transfer\n"); ++ } ++ } ++ } else { ++ if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0) { ++ DWC_DEBUGPL(DBG_PCDV, ++ "%d-%s len=%d xfersize=%d pktcnt=%d\n", ++ ep->dwc_ep.num, ++ ep->dwc_ep.is_in ? "IN" : "OUT", ++ ep->dwc_ep.xfer_len, ++ deptsiz.b.xfersize, ++ deptsiz.b.pktcnt); ++ ++ /* Check if the whole transfer was completed, ++ * if no, setup transfer for next portion of data ++ */ ++ if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { ++ dwc_otg_ep_start_transfer(core_if, ++ &ep->dwc_ep); ++ } else if (ep->dwc_ep.sent_zlp) { ++ /* ++ * This fragment of code should initiate 0 ++ * length trasfer in case if it is queued ++ * a trasfer with size divisible to EPs max ++ * packet size and with usb_request zero field ++ * is set, which means that after data is transfered, ++ * it is also should be transfered ++ * a 0 length packet at the end. For Slave and ++ * Buffer DMA modes in this case SW has ++ * to initiate 2 transfers one with transfer size, ++ * and the second with 0 size. For Desriptor ++ * DMA mode SW is able to initiate a transfer, ++ * which will handle all the packets including ++ * the last 0 legth. ++ */ ++ ep->dwc_ep.sent_zlp = 0; ++ dwc_otg_ep_start_zl_transfer(core_if, ++ &ep->dwc_ep); ++ } else { ++ is_last = 1; ++ } ++ } else { ++ DWC_WARN ++ ("Incomplete transfer (%d-%s [siz=%d pkt=%d])\n", ++ ep->dwc_ep.num, ++ (ep->dwc_ep.is_in ? "IN" : "OUT"), ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ } ++ } ++ } else { ++ dwc_otg_dev_out_ep_regs_t *out_ep_regs = ++ dev_if->out_ep_regs[ep->dwc_ep.num]; ++ desc_sts.d32 = 0; ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ dma_desc = ep->dwc_ep.desc_addr; ++ byte_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ++#ifdef DWC_UTE_CFI ++ CFI_INFO("%s: BUFFER_MODE=%d\n", __func__, ++ ep->dwc_ep.buff_mode); ++ if (ep->dwc_ep.buff_mode != BM_STANDARD) { ++ int residue; ++ residue = cfi_calc_desc_residue(ep); ++ if (residue < 0) ++ return; ++ byte_count = residue; ++ } else { ++#endif ++ ++ for (i = 0; i < ep->dwc_ep.desc_cnt; ++ ++i) { ++ desc_sts = dma_desc->status; ++ byte_count += desc_sts.b.bytes; ++ dma_desc++; ++ } ++ ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ /* Checking for interrupt Out transfers with not ++ * dword aligned mps sizes ++ */ ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_INTR && ++ (ep->dwc_ep.maxpacket % 4)) { ++ ep->dwc_ep.xfer_count = ++ ep->dwc_ep.total_len - byte_count; ++ if ((ep->dwc_ep.xfer_len % ++ ep->dwc_ep.maxpacket) ++ && (ep->dwc_ep.xfer_len / ++ ep->dwc_ep.maxpacket < ++ MAX_DMA_DESC_CNT)) ++ ep->dwc_ep.xfer_len -= ++ (ep->dwc_ep.desc_cnt - ++ 1) * ep->dwc_ep.maxpacket + ++ ep->dwc_ep.xfer_len % ++ ep->dwc_ep.maxpacket; ++ else ++ ep->dwc_ep.xfer_len -= ++ ep->dwc_ep.desc_cnt * ++ ep->dwc_ep.maxpacket; ++ if (ep->dwc_ep.xfer_len > 0) { ++ dwc_otg_ep_start_transfer ++ (core_if, &ep->dwc_ep); ++ } else { ++ is_last = 1; ++ } ++ } else { ++ ep->dwc_ep.xfer_count = ++ ep->dwc_ep.total_len - byte_count + ++ ((4 - ++ (ep->dwc_ep. ++ total_len & 0x3)) & 0x3); ++ is_last = 1; ++ } ++ } else { ++ deptsiz.d32 = 0; ++ deptsiz.d32 = ++ DWC_READ_REG32(&out_ep_regs->doeptsiz); ++ ++ byte_count = (ep->dwc_ep.xfer_len - ++ ep->dwc_ep.xfer_count - ++ deptsiz.b.xfersize); ++ ep->dwc_ep.xfer_buff += byte_count; ++ ep->dwc_ep.dma_addr += byte_count; ++ ep->dwc_ep.xfer_count += byte_count; ++ ++ /* Check if the whole transfer was completed, ++ * if no, setup transfer for next portion of data ++ */ ++ if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { ++ dwc_otg_ep_start_transfer(core_if, ++ &ep->dwc_ep); ++ } else if (ep->dwc_ep.sent_zlp) { ++ /* ++ * This fragment of code should initiate 0 ++ * length trasfer in case if it is queued ++ * a trasfer with size divisible to EPs max ++ * packet size and with usb_request zero field ++ * is set, which means that after data is transfered, ++ * it is also should be transfered ++ * a 0 length packet at the end. For Slave and ++ * Buffer DMA modes in this case SW has ++ * to initiate 2 transfers one with transfer size, ++ * and the second with 0 size. For Desriptor ++ * DMA mode SW is able to initiate a transfer, ++ * which will handle all the packets including ++ * the last 0 legth. ++ */ ++ ep->dwc_ep.sent_zlp = 0; ++ dwc_otg_ep_start_zl_transfer(core_if, ++ &ep->dwc_ep); ++ } else { ++ is_last = 1; ++ } ++ } ++ } else { ++ /* Check if the whole transfer was completed, ++ * if no, setup transfer for next portion of data ++ */ ++ if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { ++ dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep); ++ } else if (ep->dwc_ep.sent_zlp) { ++ /* ++ * This fragment of code should initiate 0 ++ * length transfer in case if it is queued ++ * a transfer with size divisible to EPs max ++ * packet size and with usb_request zero field ++ * is set, which means that after data is transfered, ++ * it is also should be transfered ++ * a 0 length packet at the end. For Slave and ++ * Buffer DMA modes in this case SW has ++ * to initiate 2 transfers one with transfer size, ++ * and the second with 0 size. For Descriptor ++ * DMA mode SW is able to initiate a transfer, ++ * which will handle all the packets including ++ * the last 0 length. ++ */ ++ ep->dwc_ep.sent_zlp = 0; ++ dwc_otg_ep_start_zl_transfer(core_if, ++ &ep->dwc_ep); ++ } else { ++ is_last = 1; ++ } ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "addr %p, %d-%s len=%d cnt=%d xsize=%d pktcnt=%d\n", ++ &out_ep_regs->doeptsiz, ep->dwc_ep.num, ++ ep->dwc_ep.is_in ? "IN" : "OUT", ++ ep->dwc_ep.xfer_len, ep->dwc_ep.xfer_count, ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ } ++ ++ /* Complete the request */ ++ if (is_last) { ++#ifdef DWC_UTE_CFI ++ if (ep->dwc_ep.buff_mode != BM_STANDARD) { ++ req->actual = ep->dwc_ep.cfi_req_len - byte_count; ++ } else { ++#endif ++ req->actual = ep->dwc_ep.xfer_count; ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ if (req->dw_align_buf) { ++ if (!ep->dwc_ep.is_in) { ++ dwc_memcpy(req->buf, req->dw_align_buf, req->length); ++ } ++ DWC_DMA_FREE(req->length, req->dw_align_buf, ++ req->dw_align_buf_dma); ++ } ++ ++ dwc_otg_request_done(ep, req, 0); ++ ++ ep->dwc_ep.start_xfer_buff = 0; ++ ep->dwc_ep.xfer_buff = 0; ++ ep->dwc_ep.xfer_len = 0; ++ ++ /* If there is a request in the queue start it. */ ++ start_next_request(ep); ++ } ++} ++/** ++ * This function completes the request for the ISO EP in DDMA. If it is last ++ * descriptor and ep was disabled, then program already prepared(during ep_queue) ++ * descriptor chain if there are more requests to process ++ */ ++static void complete_ddma_iso_ep(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); ++ dev_dma_desc_sts_t desc_sts; ++ dwc_otg_pcd_request_t *req = 0; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ dwc_dma_t dma_desc_addr; ++ dwc_ep_t *dwc_ep; ++ uint32_t depdma; ++ uint32_t index; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s() %d-%s\n", __func__, ep->dwc_ep.num, ++ (ep->dwc_ep.is_in ? "IN" : "OUT")); ++ dwc_ep = &ep->dwc_ep; ++ if (dwc_ep->use_add_buf) { ++ dma_desc_addr = dwc_ep->dma_desc_addr; ++ dma_desc = dwc_ep->desc_addr; ++ } else { ++ dma_desc_addr = dwc_ep->dma_desc_addr1; ++ dma_desc = dwc_ep->desc_addr1; ++ } ++ /* Get any pending requests */ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); ++ return; ++ } ++ } else { ++ DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); ++ return; ++ } ++ ++ if (dwc_ep->is_in) { ++ depdma = DWC_READ_REG32(&core_if->dev_if->in_ep_regs[dwc_ep->num]->diepdma); ++ index = (depdma - dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t) - 1; ++ desc_sts = dma_desc[index].status; ++ req->actual = req->length - desc_sts.b_iso_in.txbytes; ++ } else { ++ depdma = DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepdma); ++ index = (depdma - dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t) - 1; ++ desc_sts = dma_desc[index].status; ++ if (req->length%4) ++ req->actual = req->length - desc_sts.b_iso_out.rxbytes + (4 - req->length%4); ++ else ++ req->actual = req->length - desc_sts.b_iso_out.rxbytes; ++ } ++ ++ /* Complete the request */ ++ dwc_otg_request_done(ep, req, 0); ++} ++ ++#ifdef DWC_EN_ISOC ++ ++/** ++ * This function BNA interrupt for Isochronous EPs ++ * ++ */ ++static void dwc_otg_pcd_handle_iso_bna(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_ep_t *dwc_ep = &ep->dwc_ep; ++ volatile uint32_t *addr; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dwc_otg_pcd_t *pcd = ep->pcd; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ int i; ++ ++ dma_desc = ++ dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * (dwc_ep->proc_buf_num); ++ ++ if (dwc_ep->is_in) { ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) { ++ sts.d32 = dma_desc->status.d32; ++ sts.b_iso_in.bs = BS_HOST_READY; ++ dma_desc->status.d32 = sts.d32; ++ } ++ } else { ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) { ++ sts.d32 = dma_desc->status.d32; ++ sts.b_iso_out.bs = BS_HOST_READY; ++ dma_desc->status.d32 = sts.d32; ++ } ++ } ++ ++ if (dwc_ep->is_in == 0) { ++ addr = ++ &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep-> ++ num]->doepctl; ++ } else { ++ addr = ++ &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl; ++ } ++ depctl.b.epena = 1; ++ DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32); ++} ++ ++/** ++ * This function sets latest iso packet information(non-PTI mode) ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void set_current_pkt_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ dma_addr_t dma_addr; ++ uint32_t offset; ++ ++ if (ep->proc_buf_num) ++ dma_addr = ep->dma_addr1; ++ else ++ dma_addr = ep->dma_addr0; ++ ++ if (ep->is_in) { ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[ep->num]->dieptsiz); ++ offset = ep->data_per_frame; ++ } else { ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->num]->doeptsiz); ++ offset = ++ ep->data_per_frame + ++ (0x4 & (0x4 - (ep->data_per_frame & 0x3))); ++ } ++ ++ if (!deptsiz.b.xfersize) { ++ ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame; ++ ep->pkt_info[ep->cur_pkt].offset = ++ ep->cur_pkt_dma_addr - dma_addr; ++ ep->pkt_info[ep->cur_pkt].status = 0; ++ } else { ++ ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame; ++ ep->pkt_info[ep->cur_pkt].offset = ++ ep->cur_pkt_dma_addr - dma_addr; ++ ep->pkt_info[ep->cur_pkt].status = -DWC_E_NO_DATA; ++ } ++ ep->cur_pkt_addr += offset; ++ ep->cur_pkt_dma_addr += offset; ++ ep->cur_pkt++; ++} ++ ++/** ++ * This function sets latest iso packet information(DDMA mode) ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param dwc_ep The EP to start the transfer on. ++ * ++ */ ++static void set_ddma_iso_pkts_info(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * dwc_ep) ++{ ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ iso_pkt_info_t *iso_packet; ++ uint32_t data_per_desc; ++ uint32_t offset; ++ int i, j; ++ ++ iso_packet = dwc_ep->pkt_info; ++ ++ /** Reinit closed DMA Descriptors*/ ++ /** ISO OUT EP */ ++ if (dwc_ep->is_in == 0) { ++ dma_desc = ++ dwc_ep->iso_desc_addr + ++ dwc_ep->desc_cnt * dwc_ep->proc_buf_num; ++ offset = 0; ++ ++ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; ++ i += dwc_ep->pkt_per_frm) { ++ for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep-> ++ data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - ++ data_per_desc % ++ 4) : 0; ++ ++ sts.d32 = dma_desc->status.d32; ++ ++ /* Write status in iso_packet_decsriptor */ ++ iso_packet->status = ++ sts.b_iso_out.rxsts + ++ (sts.b_iso_out.bs ^ BS_DMA_DONE); ++ if (iso_packet->status) { ++ iso_packet->status = -DWC_E_NO_DATA; ++ } ++ ++ /* Received data length */ ++ if (!sts.b_iso_out.rxbytes) { ++ iso_packet->length = ++ data_per_desc - ++ sts.b_iso_out.rxbytes; ++ } else { ++ iso_packet->length = ++ data_per_desc - ++ sts.b_iso_out.rxbytes + (4 - ++ dwc_ep->data_per_frame ++ % 4); ++ } ++ ++ iso_packet->offset = offset; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ iso_packet++; ++ } ++ } ++ ++ for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) { ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ ++ sts.d32 = dma_desc->status.d32; ++ ++ /* Write status in iso_packet_decsriptor */ ++ iso_packet->status = ++ sts.b_iso_out.rxsts + ++ (sts.b_iso_out.bs ^ BS_DMA_DONE); ++ if (iso_packet->status) { ++ iso_packet->status = -DWC_E_NO_DATA; ++ } ++ ++ /* Received data length */ ++ iso_packet->length = ++ dwc_ep->data_per_frame - sts.b_iso_out.rxbytes; ++ ++ iso_packet->offset = offset; ++ ++ offset += data_per_desc; ++ iso_packet++; ++ dma_desc++; ++ } ++ ++ sts.d32 = dma_desc->status.d32; ++ ++ /* Write status in iso_packet_decsriptor */ ++ iso_packet->status = ++ sts.b_iso_out.rxsts + (sts.b_iso_out.bs ^ BS_DMA_DONE); ++ if (iso_packet->status) { ++ iso_packet->status = -DWC_E_NO_DATA; ++ } ++ /* Received data length */ ++ if (!sts.b_iso_out.rxbytes) { ++ iso_packet->length = ++ dwc_ep->data_per_frame - sts.b_iso_out.rxbytes; ++ } else { ++ iso_packet->length = ++ dwc_ep->data_per_frame - sts.b_iso_out.rxbytes + ++ (4 - dwc_ep->data_per_frame % 4); ++ } ++ ++ iso_packet->offset = offset; ++ } else { ++/** ISO IN EP */ ++ ++ dma_desc = ++ dwc_ep->iso_desc_addr + ++ dwc_ep->desc_cnt * dwc_ep->proc_buf_num; ++ ++ for (i = 0; i < dwc_ep->desc_cnt - 1; i++) { ++ sts.d32 = dma_desc->status.d32; ++ ++ /* Write status in iso packet descriptor */ ++ iso_packet->status = ++ sts.b_iso_in.txsts + ++ (sts.b_iso_in.bs ^ BS_DMA_DONE); ++ if (iso_packet->status != 0) { ++ iso_packet->status = -DWC_E_NO_DATA; ++ ++ } ++ /* Bytes has been transfered */ ++ iso_packet->length = ++ dwc_ep->data_per_frame - sts.b_iso_in.txbytes; ++ ++ dma_desc++; ++ iso_packet++; ++ } ++ ++ sts.d32 = dma_desc->status.d32; ++ while (sts.b_iso_in.bs == BS_DMA_BUSY) { ++ sts.d32 = dma_desc->status.d32; ++ } ++ ++ /* Write status in iso packet descriptor ??? do be done with ERROR codes */ ++ iso_packet->status = ++ sts.b_iso_in.txsts + (sts.b_iso_in.bs ^ BS_DMA_DONE); ++ if (iso_packet->status != 0) { ++ iso_packet->status = -DWC_E_NO_DATA; ++ } ++ ++ /* Bytes has been transfered */ ++ iso_packet->length = ++ dwc_ep->data_per_frame - sts.b_iso_in.txbytes; ++ } ++} ++ ++/** ++ * This function reinitialize DMA Descriptors for Isochronous transfer ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param dwc_ep The EP to start the transfer on. ++ * ++ */ ++static void reinit_ddma_iso_xfer(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep) ++{ ++ int i, j; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ dma_addr_t dma_ad; ++ volatile uint32_t *addr; ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ uint32_t data_per_desc; ++ ++ if (dwc_ep->is_in == 0) { ++ addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl; ++ } else { ++ addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl; ++ } ++ ++ if (dwc_ep->proc_buf_num == 0) { ++ /** Buffer 0 descriptors setup */ ++ dma_ad = dwc_ep->dma_addr0; ++ } else { ++ /** Buffer 1 descriptors setup */ ++ dma_ad = dwc_ep->dma_addr1; ++ } ++ ++ /** Reinit closed DMA Descriptors*/ ++ /** ISO OUT EP */ ++ if (dwc_ep->is_in == 0) { ++ dma_desc = ++ dwc_ep->iso_desc_addr + ++ dwc_ep->desc_cnt * dwc_ep->proc_buf_num; ++ ++ sts.b_iso_out.bs = BS_HOST_READY; ++ sts.b_iso_out.rxsts = 0; ++ sts.b_iso_out.l = 0; ++ sts.b_iso_out.sp = 0; ++ sts.b_iso_out.ioc = 0; ++ sts.b_iso_out.pid = 0; ++ sts.b_iso_out.framenum = 0; ++ ++ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; ++ i += dwc_ep->pkt_per_frm) { ++ for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep-> ++ data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - ++ data_per_desc % ++ 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ dma_ad += data_per_desc; ++ dma_desc++; ++ } ++ } ++ ++ for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) { ++ ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ ++ sts.b_iso_out.ioc = 1; ++ sts.b_iso_out.l = dwc_ep->proc_buf_num; ++ ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ } else { ++/** ISO IN EP */ ++ ++ dma_desc = ++ dwc_ep->iso_desc_addr + ++ dwc_ep->desc_cnt * dwc_ep->proc_buf_num; ++ ++ sts.b_iso_in.bs = BS_HOST_READY; ++ sts.b_iso_in.txsts = 0; ++ sts.b_iso_in.sp = 0; ++ sts.b_iso_in.ioc = 0; ++ sts.b_iso_in.pid = dwc_ep->pkt_per_frm; ++ sts.b_iso_in.framenum = dwc_ep->next_frame; ++ sts.b_iso_in.txbytes = dwc_ep->data_per_frame; ++ sts.b_iso_in.l = 0; ++ ++ for (i = 0; i < dwc_ep->desc_cnt - 1; i++) { ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ sts.b_iso_in.framenum += dwc_ep->bInterval; ++ dma_ad += dwc_ep->data_per_frame; ++ dma_desc++; ++ } ++ ++ sts.b_iso_in.ioc = 1; ++ sts.b_iso_in.l = dwc_ep->proc_buf_num; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ dwc_ep->next_frame = ++ sts.b_iso_in.framenum + dwc_ep->bInterval * 1; ++ } ++ dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1; ++} ++ ++/** ++ * This function is to handle Iso EP transfer complete interrupt ++ * in case Iso out packet was dropped ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param dwc_ep The EP for wihich transfer complete was asserted ++ * ++ */ ++static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * dwc_ep) ++{ ++ uint32_t dma_addr; ++ uint32_t drp_pkt; ++ uint32_t drp_pkt_cnt; ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ int i; ++ ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[dwc_ep->num]->doeptsiz); ++ ++ drp_pkt = dwc_ep->pkt_cnt - deptsiz.b.pktcnt; ++ drp_pkt_cnt = dwc_ep->pkt_per_frm - (drp_pkt % dwc_ep->pkt_per_frm); ++ ++ /* Setting dropped packets status */ ++ for (i = 0; i < drp_pkt_cnt; ++i) { ++ dwc_ep->pkt_info[drp_pkt].status = -DWC_E_NO_DATA; ++ drp_pkt++; ++ deptsiz.b.pktcnt--; ++ } ++ ++ if (deptsiz.b.pktcnt > 0) { ++ deptsiz.b.xfersize = ++ dwc_ep->xfer_len - (dwc_ep->pkt_cnt - ++ deptsiz.b.pktcnt) * dwc_ep->maxpacket; ++ } else { ++ deptsiz.b.xfersize = 0; ++ deptsiz.b.pktcnt = 0; ++ } ++ ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz, ++ deptsiz.d32); ++ ++ if (deptsiz.b.pktcnt > 0) { ++ if (dwc_ep->proc_buf_num) { ++ dma_addr = ++ dwc_ep->dma_addr1 + dwc_ep->xfer_len - ++ deptsiz.b.xfersize; ++ } else { ++ dma_addr = ++ dwc_ep->dma_addr0 + dwc_ep->xfer_len - ++ deptsiz.b.xfersize;; ++ } ++ ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ out_ep_regs[dwc_ep->num]->doepdma, dma_addr); ++ ++ /** Re-enable endpoint, clear nak */ ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ ++ DWC_MODIFY_REG32(&core_if->dev_if-> ++ out_ep_regs[dwc_ep->num]->doepctl, depctl.d32, ++ depctl.d32); ++ return 0; ++ } else { ++ return 1; ++ } ++} ++ ++/** ++ * This function sets iso packets information(PTI mode) ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++static uint32_t set_iso_pkts_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ int i, j; ++ dma_addr_t dma_ad; ++ iso_pkt_info_t *packet_info = ep->pkt_info; ++ uint32_t offset; ++ uint32_t frame_data; ++ deptsiz_data_t deptsiz; ++ ++ if (ep->proc_buf_num == 0) { ++ /** Buffer 0 descriptors setup */ ++ dma_ad = ep->dma_addr0; ++ } else { ++ /** Buffer 1 descriptors setup */ ++ dma_ad = ep->dma_addr1; ++ } ++ ++ if (ep->is_in) { ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ dieptsiz); ++ } else { ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[ep->num]-> ++ doeptsiz); ++ } ++ ++ if (!deptsiz.b.xfersize) { ++ offset = 0; ++ for (i = 0; i < ep->pkt_cnt; i += ep->pkt_per_frm) { ++ frame_data = ep->data_per_frame; ++ for (j = 0; j < ep->pkt_per_frm; ++j) { ++ ++ /* Packet status - is not set as initially ++ * it is set to 0 and if packet was sent ++ successfully, status field will remain 0*/ ++ ++ /* Bytes has been transfered */ ++ packet_info->length = ++ (ep->maxpacket < ++ frame_data) ? ep->maxpacket : frame_data; ++ ++ /* Received packet offset */ ++ packet_info->offset = offset; ++ offset += packet_info->length; ++ frame_data -= packet_info->length; ++ ++ packet_info++; ++ } ++ } ++ return 1; ++ } else { ++ /* This is a workaround for in case of Transfer Complete with ++ * PktDrpSts interrupts merging - in this case Transfer complete ++ * interrupt for Isoc Out Endpoint is asserted without PktDrpSts ++ * set and with DOEPTSIZ register non zero. Investigations showed, ++ * that this happens when Out packet is dropped, but because of ++ * interrupts merging during first interrupt handling PktDrpSts ++ * bit is cleared and for next merged interrupts it is not reset. ++ * In this case SW hadles the interrupt as if PktDrpSts bit is set. ++ */ ++ if (ep->is_in) { ++ return 1; ++ } else { ++ return handle_iso_out_pkt_dropped(core_if, ep); ++ } ++ } ++} ++ ++/** ++ * This function is to handle Iso EP transfer complete interrupt ++ * ++ * @param pcd The PCD ++ * @param ep The EP for which transfer complete was asserted ++ * ++ */ ++static void complete_iso_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); ++ dwc_ep_t *dwc_ep = &ep->dwc_ep; ++ uint8_t is_last = 0; ++ ++ if (ep->dwc_ep.next_frame == 0xffffffff) { ++ DWC_WARN("Next frame is not set!\n"); ++ return; ++ } ++ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ set_ddma_iso_pkts_info(core_if, dwc_ep); ++ reinit_ddma_iso_xfer(core_if, dwc_ep); ++ is_last = 1; ++ } else { ++ if (core_if->pti_enh_enable) { ++ if (set_iso_pkts_info(core_if, dwc_ep)) { ++ dwc_ep->proc_buf_num = ++ (dwc_ep->proc_buf_num ^ 1) & 0x1; ++ dwc_otg_iso_ep_start_buf_transfer ++ (core_if, dwc_ep); ++ is_last = 1; ++ } ++ } else { ++ set_current_pkt_info(core_if, dwc_ep); ++ if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { ++ is_last = 1; ++ dwc_ep->cur_pkt = 0; ++ dwc_ep->proc_buf_num = ++ (dwc_ep->proc_buf_num ^ 1) & 0x1; ++ if (dwc_ep->proc_buf_num) { ++ dwc_ep->cur_pkt_addr = ++ dwc_ep->xfer_buff1; ++ dwc_ep->cur_pkt_dma_addr = ++ dwc_ep->dma_addr1; ++ } else { ++ dwc_ep->cur_pkt_addr = ++ dwc_ep->xfer_buff0; ++ dwc_ep->cur_pkt_dma_addr = ++ dwc_ep->dma_addr0; ++ } ++ ++ } ++ dwc_otg_iso_ep_start_frm_transfer(core_if, ++ dwc_ep); ++ } ++ } ++ } else { ++ set_current_pkt_info(core_if, dwc_ep); ++ if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { ++ is_last = 1; ++ dwc_ep->cur_pkt = 0; ++ dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1; ++ if (dwc_ep->proc_buf_num) { ++ dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff1; ++ dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr1; ++ } else { ++ dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff0; ++ dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr0; ++ } ++ ++ } ++ dwc_otg_iso_ep_start_frm_transfer(core_if, dwc_ep); ++ } ++ if (is_last) ++ dwc_otg_iso_buffer_done(pcd, ep, ep->iso_req_handle); ++} ++#endif /* DWC_EN_ISOC */ ++ ++/** ++ * This function handle BNA interrupt for Non Isochronous EPs ++ * ++ */ ++static void dwc_otg_pcd_handle_noniso_bna(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_ep_t *dwc_ep = &ep->dwc_ep; ++ volatile uint32_t *addr; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dwc_otg_pcd_t *pcd = ep->pcd; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if = ep->pcd->core_if; ++ int i, start; ++ ++ if (!dwc_ep->desc_cnt) ++ DWC_WARN("Ep%d %s Descriptor count = %d \n", dwc_ep->num, ++ (dwc_ep->is_in ? "IN" : "OUT"), dwc_ep->desc_cnt); ++ ++ if (core_if->core_params->cont_on_bna && !dwc_ep->is_in ++ && dwc_ep->type != DWC_OTG_EP_TYPE_CONTROL) { ++ uint32_t doepdma; ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[dwc_ep->num]; ++ doepdma = DWC_READ_REG32(&(out_regs->doepdma)); ++ start = (doepdma - dwc_ep->dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t); ++ dma_desc = &(dwc_ep->desc_addr[start]); ++ } else { ++ start = 0; ++ dma_desc = dwc_ep->desc_addr; ++ } ++ ++ ++ for (i = start; i < dwc_ep->desc_cnt; ++i, ++dma_desc) { ++ sts.d32 = dma_desc->status.d32; ++ sts.b.bs = BS_HOST_READY; ++ dma_desc->status.d32 = sts.d32; ++ } ++ ++ if (dwc_ep->is_in == 0) { ++ addr = ++ &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]-> ++ doepctl; ++ } else { ++ addr = ++ &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl; ++ } ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ DWC_MODIFY_REG32(addr, 0, depctl.d32); ++} ++ ++/** ++ * This function handles EP0 Control transfers. ++ * ++ * The state of the control transfers are tracked in ++ * ep0state. ++ */ ++static void handle_ep0(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ dev_dma_desc_sts_t desc_sts; ++ deptsiz0_data_t deptsiz; ++ uint32_t byte_count; ++ ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__); ++ print_ep0_state(pcd); ++#endif ++ ++ switch (pcd->ep0state) { ++ case EP0_DISCONNECT: ++ break; ++ ++ case EP0_IDLE: ++ pcd->request_config = 0; ++ ++ pcd_setup(pcd); ++ break; ++ ++ case EP0_IN_DATA_PHASE: ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, "DATA_IN EP%d-%s: type=%d, mps=%d\n", ++ ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"), ++ ep0->dwc_ep.type, ep0->dwc_ep.maxpacket); ++#endif ++ ++ if (core_if->dma_enable != 0) { ++ /* ++ * For EP0 we can only program 1 packet at a time so we ++ * need to do the make calculations after each complete. ++ * Call write_packet to make the calculations, as in ++ * slave mode, and use those values to determine if we ++ * can complete. ++ */ ++ if (core_if->dma_desc_enable == 0) { ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if-> ++ dev_if->in_ep_regs[0]-> ++ dieptsiz); ++ byte_count = ++ ep0->dwc_ep.xfer_len - deptsiz.b.xfersize; ++ } else { ++ desc_sts = ++ core_if->dev_if->in_desc_addr->status; ++ byte_count = ++ ep0->dwc_ep.xfer_len - desc_sts.b.bytes; ++ } ++ ep0->dwc_ep.xfer_count += byte_count; ++ ep0->dwc_ep.xfer_buff += byte_count; ++ ep0->dwc_ep.dma_addr += byte_count; ++ } ++ if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) { ++ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), ++ &ep0->dwc_ep); ++ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); ++ } else if (ep0->dwc_ep.sent_zlp) { ++ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), ++ &ep0->dwc_ep); ++ ep0->dwc_ep.sent_zlp = 0; ++ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n"); ++ } else { ++ ep0_complete_request(ep0); ++ DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); ++ } ++ break; ++ case EP0_OUT_DATA_PHASE: ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, "DATA_OUT EP%d-%s: type=%d, mps=%d\n", ++ ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"), ++ ep0->dwc_ep.type, ep0->dwc_ep.maxpacket); ++#endif ++ if (core_if->dma_enable != 0) { ++ if (core_if->dma_desc_enable == 0) { ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if-> ++ dev_if->out_ep_regs[0]-> ++ doeptsiz); ++ byte_count = ++ ep0->dwc_ep.maxpacket - deptsiz.b.xfersize; ++ } else { ++ desc_sts = ++ core_if->dev_if->out_desc_addr->status; ++ byte_count = ++ ep0->dwc_ep.maxpacket - desc_sts.b.bytes; ++ } ++ ep0->dwc_ep.xfer_count += byte_count; ++ ep0->dwc_ep.xfer_buff += byte_count; ++ ep0->dwc_ep.dma_addr += byte_count; ++ } ++ if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) { ++ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), ++ &ep0->dwc_ep); ++ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); ++ } else if (ep0->dwc_ep.sent_zlp) { ++ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), ++ &ep0->dwc_ep); ++ ep0->dwc_ep.sent_zlp = 0; ++ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n"); ++ } else { ++ ep0_complete_request(ep0); ++ DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); ++ } ++ break; ++ ++ case EP0_IN_STATUS_PHASE: ++ case EP0_OUT_STATUS_PHASE: ++ DWC_DEBUGPL(DBG_PCD, "CASE: EP0_STATUS\n"); ++ ep0_complete_request(ep0); ++ pcd->ep0state = EP0_IDLE; ++ ep0->stopped = 1; ++ ep0->dwc_ep.is_in = 0; /* OUT for next SETUP */ ++ ++ /* Prepare for more SETUP Packets */ ++ if (core_if->dma_enable) { ++ ep0_out_start(core_if, pcd); ++ } ++ break; ++ ++ case EP0_STALL: ++ DWC_ERROR("EP0 STALLed, should not get here pcd_setup()\n"); ++ break; ++ } ++#ifdef DEBUG_EP0 ++ print_ep0_state(pcd); ++#endif ++} ++ ++/** ++ * Restart transfer ++ */ ++static void restart_transfer(dwc_otg_pcd_t * pcd, const uint32_t epnum) ++{ ++ dwc_otg_core_if_t *core_if; ++ dwc_otg_dev_if_t *dev_if; ++ deptsiz_data_t dieptsiz = {.d32 = 0 }; ++ dwc_otg_pcd_ep_t *ep; ++ ++ ep = get_in_ep(pcd, epnum); ++ if (!ep) ++ return; ++ ++#ifdef DWC_EN_ISOC ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ return; ++ } ++#endif /* DWC_EN_ISOC */ ++ ++ core_if = GET_CORE_IF(pcd); ++ dev_if = core_if->dev_if; ++ ++ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz); ++ ++ DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x xfer_len=%0x" ++ " stopped=%d\n", ep->dwc_ep.xfer_buff, ++ ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len, ep->stopped); ++ /* ++ * If xfersize is 0 and pktcnt in not 0, resend the last packet. ++ */ ++ if (dieptsiz.b.pktcnt && dieptsiz.b.xfersize == 0 && ++ ep->dwc_ep.start_xfer_buff != 0) { ++ if (ep->dwc_ep.total_len <= ep->dwc_ep.maxpacket) { ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.xfer_buff = ep->dwc_ep.start_xfer_buff; ++ ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count; ++ } else { ++ ep->dwc_ep.xfer_count -= ep->dwc_ep.maxpacket; ++ /* convert packet size to dwords. */ ++ ep->dwc_ep.xfer_buff -= ep->dwc_ep.maxpacket; ++ ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count; ++ } ++ ep->stopped = 0; ++ DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x " ++ "xfer_len=%0x stopped=%d\n", ++ ep->dwc_ep.xfer_buff, ++ ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len, ++ ep->stopped); ++ if (epnum == 0) { ++ dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep); ++ } else { ++ dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep); ++ } ++ } ++} ++ ++/* ++ * This function create new nextep sequnce based on Learn Queue. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ */ ++void predict_nextep_seq( dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_device_global_regs_t *dev_global_regs = ++ core_if->dev_if->dev_global_regs; ++ const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth; ++ /* Number of Token Queue Registers */ ++ const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8; ++ dtknq1_data_t dtknqr1; ++ uint32_t in_tkn_epnums[4]; ++ uint8_t seqnum[MAX_EPS_CHANNELS]; ++ uint8_t intkn_seq[TOKEN_Q_DEPTH]; ++ grstctl_t resetctl = {.d32 = 0 }; ++ uint8_t temp; ++ int ndx = 0; ++ int start = 0; ++ int end = 0; ++ int sort_done = 0; ++ int i = 0; ++ volatile uint32_t *addr = &dev_global_regs->dtknqr1; ++ ++ DWC_DEBUGPL(DBG_PCD, "dev_token_q_depth=%d\n", TOKEN_Q_DEPTH); ++ ++ /* Read the DTKNQ Registers */ ++ for (i = 0; i < DTKNQ_REG_CNT; i++) { ++ in_tkn_epnums[i] = DWC_READ_REG32(addr); ++ DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1, ++ in_tkn_epnums[i]); ++ if (addr == &dev_global_regs->dvbusdis) { ++ addr = &dev_global_regs->dtknqr3_dthrctl; ++ } else { ++ ++addr; ++ } ++ ++ } ++ ++ /* Copy the DTKNQR1 data to the bit field. */ ++ dtknqr1.d32 = in_tkn_epnums[0]; ++ if (dtknqr1.b.wrap_bit) { ++ ndx = dtknqr1.b.intknwptr; ++ end = ndx - 1; ++ if (end < 0) ++ end = TOKEN_Q_DEPTH - 1; ++ } else { ++ ndx = 0; ++ end = dtknqr1.b.intknwptr - 1; ++ if (end < 0) ++ end = 0; ++ } ++ start = ndx; ++ ++ /* Fill seqnum[] by initial values: EP number + 31 */ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ seqnum[i] = i + 31; ++ } ++ ++ /* Fill intkn_seq[] from in_tkn_epnums[0] */ ++ for (i = 0; i < 6; i++) ++ intkn_seq[i] = (in_tkn_epnums[0] >> ((7 - i) * 4)) & 0xf; ++ ++ if (TOKEN_Q_DEPTH > 6) { ++ /* Fill intkn_seq[] from in_tkn_epnums[1] */ ++ for (i = 6; i < 14; i++) ++ intkn_seq[i] = ++ (in_tkn_epnums[1] >> ((7 - (i - 6)) * 4)) & 0xf; ++ } ++ ++ if (TOKEN_Q_DEPTH > 14) { ++ /* Fill intkn_seq[] from in_tkn_epnums[1] */ ++ for (i = 14; i < 22; i++) ++ intkn_seq[i] = ++ (in_tkn_epnums[2] >> ((7 - (i - 14)) * 4)) & 0xf; ++ } ++ ++ if (TOKEN_Q_DEPTH > 22) { ++ /* Fill intkn_seq[] from in_tkn_epnums[1] */ ++ for (i = 22; i < 30; i++) ++ intkn_seq[i] = ++ (in_tkn_epnums[3] >> ((7 - (i - 22)) * 4)) & 0xf; ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s start=%d end=%d intkn_seq[]:\n", __func__, ++ start, end); ++ for (i = 0; i < TOKEN_Q_DEPTH; i++) ++ DWC_DEBUGPL(DBG_PCDV, "%d\n", intkn_seq[i]); ++ ++ /* Update seqnum based on intkn_seq[] */ ++ i = 0; ++ do { ++ seqnum[intkn_seq[ndx]] = i; ++ ndx++; ++ i++; ++ if (ndx == TOKEN_Q_DEPTH) ++ ndx = 0; ++ } while (i < TOKEN_Q_DEPTH); ++ ++ /* Mark non active EP's in seqnum[] by 0xff */ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ if (core_if->nextep_seq[i] == 0xff) ++ seqnum[i] = 0xff; ++ } ++ ++ /* Sort seqnum[] */ ++ sort_done = 0; ++ while (!sort_done) { ++ sort_done = 1; ++ for (i = 0; i < core_if->dev_if->num_in_eps; i++) { ++ if (seqnum[i] > seqnum[i + 1]) { ++ temp = seqnum[i]; ++ seqnum[i] = seqnum[i + 1]; ++ seqnum[i + 1] = temp; ++ sort_done = 0; ++ } ++ } ++ } ++ ++ ndx = start + seqnum[0]; ++ if (ndx >= TOKEN_Q_DEPTH) ++ ndx = ndx % TOKEN_Q_DEPTH; ++ core_if->first_in_nextep_seq = intkn_seq[ndx]; ++ ++ /* Update seqnum[] by EP numbers */ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ ndx = start + i; ++ if (seqnum[i] < 31) { ++ ndx = start + seqnum[i]; ++ if (ndx >= TOKEN_Q_DEPTH) ++ ndx = ndx % TOKEN_Q_DEPTH; ++ seqnum[i] = intkn_seq[ndx]; ++ } else { ++ if (seqnum[i] < 0xff) { ++ seqnum[i] = seqnum[i] - 31; ++ } else { ++ break; ++ } ++ } ++ } ++ ++ /* Update nextep_seq[] based on seqnum[] */ ++ for (i = 0; i < core_if->dev_if->num_in_eps; i++) { ++ if (seqnum[i] != 0xff) { ++ if (seqnum[i + 1] != 0xff) { ++ core_if->nextep_seq[seqnum[i]] = seqnum[i + 1]; ++ } else { ++ core_if->nextep_seq[seqnum[i]] = core_if->first_in_nextep_seq; ++ break; ++ } ++ } else { ++ break; ++ } ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); ++ } ++ ++ /* Flush the Learning Queue */ ++ resetctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->grstctl); ++ resetctl.b.intknqflsh = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); ++ ++ ++} ++ ++/** ++ * handle the IN EP disable interrupt. ++ */ ++static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ deptsiz_data_t dieptsiz = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ gintmsk_data_t gintmsk_data; ++ depctl_data_t depctl; ++ uint32_t diepdma; ++ uint32_t remain_to_transfer = 0; ++ uint8_t i; ++ uint32_t xfer_size; ++ ++ ep = get_in_ep(pcd, epnum); ++ if (!ep) ++ return; ++ ++ dwc_ep = &ep->dwc_ep; ++ if (!dwc_ep) ++ return; ++ ++ if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num); ++ complete_ep(ep); ++ return; ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "diepctl%d=%0x\n", epnum, ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl)); ++ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz); ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); ++ ++ DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n", ++ dieptsiz.b.pktcnt, dieptsiz.b.xfersize); ++ ++ if ((core_if->start_predict == 0) || (depctl.b.eptype & 1)) { ++ if (ep->stopped) { ++ if (core_if->en_multiple_tx_fifo) ++ /* Flush the Tx FIFO */ ++ dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num); ++ /* Clear the Global IN NP NAK */ ++ dctl.d32 = 0; ++ dctl.b.cgnpinnak = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ /* Restart the transaction */ ++ if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { ++ restart_transfer(pcd, epnum); ++ } ++ } else { ++ /* Restart the transaction */ ++ if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { ++ restart_transfer(pcd, epnum); ++ } ++ DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n"); ++ } ++ return; ++ } ++ ++ if (core_if->start_predict > 2) { // NP IN EP ++ core_if->start_predict--; ++ return; ++ } ++ ++ core_if->start_predict--; ++ ++ if (core_if->start_predict == 1) { // All NP IN Ep's disabled now ++ ++ predict_nextep_seq(core_if); ++ ++ /* Update all active IN EP's NextEP field based of nextep_seq[] */ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (core_if->nextep_seq[i] != 0xff) { // Active NP IN EP ++ depctl.b.nextep = core_if->nextep_seq[i]; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); ++ } ++ } ++ /* Flush Shared NP TxFIFO */ ++ dwc_otg_flush_tx_fifo(core_if, 0); ++ /* Rewind buffers */ ++ if (!core_if->dma_desc_enable) { ++ i = core_if->first_in_nextep_seq; ++ do { ++ ep = get_in_ep(pcd, i); ++ if (!ep) ++ return; ++ ++ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz); ++ xfer_size = ep->dwc_ep.total_len - ep->dwc_ep.xfer_count; ++ if (xfer_size > ep->dwc_ep.maxxfer) ++ xfer_size = ep->dwc_ep.maxxfer; ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (dieptsiz.b.pktcnt != 0) { ++ if (xfer_size == 0) { ++ remain_to_transfer = 0; ++ } else { ++ if ((xfer_size % ep->dwc_ep.maxpacket) == 0) { ++ remain_to_transfer = ++ dieptsiz.b.pktcnt * ep->dwc_ep.maxpacket; ++ } else { ++ remain_to_transfer = ((dieptsiz.b.pktcnt -1) * ep->dwc_ep.maxpacket) ++ + (xfer_size % ep->dwc_ep.maxpacket); ++ } ++ } ++ diepdma = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepdma); ++ dieptsiz.b.xfersize = remain_to_transfer; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, dieptsiz.d32); ++ diepdma = ep->dwc_ep.dma_addr + (xfer_size - remain_to_transfer); ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, diepdma); ++ } ++ i = core_if->nextep_seq[i]; ++ } while (i != core_if->first_in_nextep_seq); ++ } else { // dma_desc_enable ++ DWC_PRINTF("%s Learning Queue not supported in DDMA\n", __func__); ++ } ++ ++ /* Restart transfers in predicted sequences */ ++ i = core_if->first_in_nextep_seq; ++ do { ++ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz); ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (dieptsiz.b.pktcnt != 0) { ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); ++ } ++ i = core_if->nextep_seq[i]; ++ } while (i != core_if->first_in_nextep_seq); ++ ++ /* Clear the global non-periodic IN NAK handshake */ ++ dctl.d32 = 0; ++ dctl.b.cgnpinnak = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ ++ /* Unmask EP Mismatch interrupt */ ++ gintmsk_data.d32 = 0; ++ gintmsk_data.b.epmismatch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk_data.d32); ++ ++ core_if->start_predict = 0; ++ ++ } ++} ++ ++/** ++ * Handler for the IN EP timeout handshake interrupt. ++ */ ++static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ ++#ifdef DEBUG ++ deptsiz_data_t dieptsiz = {.d32 = 0 }; ++ uint32_t num = 0; ++#endif ++ dctl_data_t dctl = {.d32 = 0 }; ++ dwc_otg_pcd_ep_t *ep; ++ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ ep = get_in_ep(pcd, epnum); ++ if (!ep) ++ return; ++ ++ /* Disable the NP Tx Fifo Empty Interrrupt */ ++ if (!core_if->dma_enable) { ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ } ++ /** @todo NGS Check EP type. ++ * Implement for Periodic EPs */ ++ /* ++ * Non-periodic EP ++ */ ++ /* Enable the Global IN NAK Effective Interrupt */ ++ intr_mask.b.ginnakeff = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32); ++ ++ /* Set Global IN NAK */ ++ dctl.b.sgnpinnak = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ ++ ep->stopped = 1; ++ ++#ifdef DEBUG ++ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[num]->dieptsiz); ++ DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n", ++ dieptsiz.b.pktcnt, dieptsiz.b.xfersize); ++#endif ++ ++#ifdef DISABLE_PERIODIC_EP ++ /* ++ * Set the NAK bit for this EP to ++ * start the disable process. ++ */ ++ diepctl.d32 = 0; ++ diepctl.b.snak = 1; ++ DWC_MODIFY_REG32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32, ++ diepctl.d32); ++ ep->disabling = 1; ++ ep->stopped = 1; ++#endif ++} ++ ++/** ++ * Handler for the IN EP NAK interrupt. ++ */ ++static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ /** @todo implement ISR */ ++ dwc_otg_core_if_t *core_if; ++ diepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "IN EP NAK"); ++ core_if = GET_CORE_IF(pcd); ++ intr_mask.b.nak = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ diepeachintmsk[epnum], intr_mask.d32, 0); ++ } else { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->diepmsk, ++ intr_mask.d32, 0); ++ } ++ ++ return 1; ++} ++ ++/** ++ * Handler for the OUT EP Babble interrupt. ++ */ ++static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ /** @todo implement ISR */ ++ dwc_otg_core_if_t *core_if; ++ doepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", ++ "OUT EP Babble"); ++ core_if = GET_CORE_IF(pcd); ++ intr_mask.b.babble = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[epnum], intr_mask.d32, 0); ++ } else { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, ++ intr_mask.d32, 0); ++ } ++ ++ return 1; ++} ++ ++/** ++ * Handler for the OUT EP NAK interrupt. ++ */ ++static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ /** @todo implement ISR */ ++ dwc_otg_core_if_t *core_if; ++ doepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_ANY, "INTERRUPT Handler not implemented for %s\n", "OUT EP NAK"); ++ core_if = GET_CORE_IF(pcd); ++ intr_mask.b.nak = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[epnum], intr_mask.d32, 0); ++ } else { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, ++ intr_mask.d32, 0); ++ } ++ ++ return 1; ++} ++ ++/** ++ * Handler for the OUT EP NYET interrupt. ++ */ ++static inline int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ /** @todo implement ISR */ ++ dwc_otg_core_if_t *core_if; ++ doepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NYET"); ++ core_if = GET_CORE_IF(pcd); ++ intr_mask.b.nyet = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[epnum], intr_mask.d32, 0); ++ } else { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, ++ intr_mask.d32, 0); ++ } ++ ++ return 1; ++} ++static void handle_xfercompl_iso_ddma (dwc_otg_dev_if_t *dev_if, dwc_otg_pcd_ep_t *ep) ++{ ++ depctl_data_t depctl; ++ dwc_ep_t *dwc_ep; ++ uint32_t doepdma; ++ dwc_dma_t dma_desc_addr; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ int index = 0, i = 0; ++ uint8_t epnum; ++ ++ dwc_ep = &ep->dwc_ep; ++ epnum = dwc_ep->num; ++ ++ complete_ddma_iso_ep(ep); ++ ++ if (dwc_ep->is_in) { ++ do { ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); ++ if (!depctl.b.epena) ++ break; ++ udelay(1); ++ } while (i++ < 125); ++ ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); ++ if (!depctl.b.epena) { ++ if (dwc_ep->use_add_buf) { ++ DWC_DEBUGPL(DBG_PCD, "go to second buffer \n"); ++ dwc_ep->use_add_buf = 0; ++ dwc_ep->iso_desc_first = 0; ++ if (dwc_ep->iso_desc_second) { ++ depctl_data_t diepctl; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepdma, ++ dwc_ep->dma_desc_addr1); ++ diepctl.d32 = 0; ++ diepctl.b.epena = 1; ++ diepctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&dev_if->in_ep_regs[epnum]->diepctl, ++ 0, diepctl.d32); ++ } else { ++ DWC_DEBUGPL(DBG_PCD, "DDMA: No more ISOC requests 1\n"); ++ } ++ } else { ++ DWC_DEBUGPL(DBG_PCD, "go to first buffer \n"); ++ dwc_ep->use_add_buf = 1; ++ dwc_ep->iso_desc_second = 0; ++ if (dwc_ep->iso_desc_first) { ++ depctl_data_t diepctl; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepdma, ++ dwc_ep->dma_desc_addr); ++ diepctl.d32 = 0; ++ diepctl.b.epena = 1; ++ diepctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&dev_if->in_ep_regs[epnum]->diepctl, ++ 0, diepctl.d32); ++ } else { ++ DWC_DEBUGPL(DBG_PCD, "DDMA: No more ISOC requests 2\n"); ++ } ++ } ++ } ++ } else { ++ depctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl); ++ doepdma = DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepdma); ++ ++ if (dwc_ep->use_add_buf) { ++ index = dwc_ep->iso_desc_first; ++ dma_desc_addr = dwc_ep->dma_desc_addr; ++ } else { ++ index = dwc_ep->iso_desc_second; ++ dma_desc_addr = dwc_ep->dma_desc_addr1; ++ } ++ ++ if (index == (doepdma - dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t)) { ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ DWC_MODIFY_REG32(&dev_if->out_ep_regs[epnum]->doepctl, 0, depctl.d32); ++ } ++ dma_desc = dwc_ep->desc_addr + dwc_ep->iso_desc_first; ++ if (!depctl.b.epena) { ++ if (dwc_ep->use_add_buf) { ++ DWC_DEBUGPL(DBG_PCD, "go to second buffer \n"); ++ dwc_ep->use_add_buf = 0; ++ dwc_ep->iso_desc_first = 0; ++ if (dwc_ep->iso_desc_second) { ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepdma, dwc_ep->dma_desc_addr1); ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&dev_if->out_ep_regs[epnum]->doepctl, 0, depctl.d32); ++ } else { ++ DWC_DEBUGPL(DBG_PCD, "DDMA: There are no more ISOC requests 1!!! \n"); ++ } ++ } else { ++ dwc_ep->use_add_buf = 1; ++ dwc_ep->iso_desc_second = 0; ++ if (dwc_ep->iso_desc_first) { ++ DWC_DEBUGPL(DBG_PCD, "go to first buffer"); ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepdma, dwc_ep->dma_desc_addr); ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&dev_if->out_ep_regs[epnum]->doepctl, 0, depctl.d32); ++ } else { ++ DWC_DEBUGPL(DBG_PCD, "DDMA: There are no more ISOC requests 2!!! \n"); ++ } ++ } ++ } ++ } ++} ++/** ++ * This interrupt indicates that an IN EP has a pending Interrupt. ++ * The sequence for handling the IN EP interrupt is shown below: ++ * -# Read the Device All Endpoint Interrupt register ++ * -# Repeat the following for each IN EP interrupt bit set (from ++ * LSB to MSB). ++ * -# Read the Device Endpoint Interrupt (DIEPINTn) register ++ * -# If "Transfer Complete" call the request complete function ++ * -# If "Endpoint Disabled" complete the EP disable procedure. ++ * -# If "AHB Error Interrupt" log error ++ * -# If "Time-out Handshake" log error ++ * -# If "IN Token Received when TxFIFO Empty" write packet to Tx ++ * FIFO. ++ * -# If "IN Token EP Mismatch" (disable, this is handled by EP ++ * Mismatch Interrupt) ++ */ ++static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd) ++{ ++#define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \ ++do { \ ++ diepint_data_t diepint = {.d32=0}; \ ++ diepint.b.__intr = 1; \ ++ DWC_WRITE_REG32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \ ++ diepint.d32); \ ++} while (0) ++ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ diepint_data_t diepint = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ uint32_t ep_intr; ++ uint32_t epnum = 0; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, pcd); ++ ++ /* Read in the device interrupt bits */ ++ ep_intr = dwc_otg_read_dev_all_in_ep_intr(core_if); ++ ++ /* Service the Device IN interrupts for each endpoint */ ++ while (ep_intr) { ++ if (ep_intr & 0x1) { ++ uint32_t empty_msk; ++ /* Get EP pointer */ ++ ep = get_in_ep(pcd, epnum); ++ if (!ep) ++ return -EINVAL; ++ ++ dwc_ep = &ep->dwc_ep; ++ if (!dwc_ep) ++ return -EINVAL; ++ ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); ++ empty_msk = ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->dtknqr4_fifoemptymsk); ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "IN EP INTERRUPT - %d\nepmty_msk - %8x diepctl - %8x\n", ++ epnum, empty_msk, depctl.d32); ++ ++ DWC_DEBUGPL(DBG_PCD, ++ "EP%d-%s: type=%d, mps=%d\n", ++ dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"), ++ dwc_ep->type, dwc_ep->maxpacket); ++ ++ diepint.d32 = ++ dwc_otg_read_dev_in_ep_intr(core_if, dwc_ep); ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "EP %d Interrupt Register - 0x%x\n", epnum, ++ diepint.d32); ++ /* Transfer complete */ ++ if (diepint.b.xfercompl) { ++ /* Disable the NP Tx FIFO Empty ++ * Interrupt */ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32 ++ (&core_if->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ } else { ++ /* Disable the Tx FIFO Empty Interrupt for this EP */ ++ uint32_t fifoemptymsk = ++ 0x1 << dwc_ep->num; ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ fifoemptymsk, 0); ++ } ++ /* Clear the bit in DIEPINTn for this interrupt */ ++ CLEAR_IN_EP_INTR(core_if, epnum, xfercompl); ++ ++ /* Complete the transfer */ ++ if (epnum == 0) { ++ handle_ep0(pcd); ++ } ++#ifdef DWC_EN_ISOC ++ else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (!ep->stopped) ++ complete_iso_ep(pcd, ep); ++ } ++#endif /* DWC_EN_ISOC */ ++#ifdef DWC_UTE_PER_IO ++ else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (!ep->stopped) ++ complete_xiso_ep(ep); ++ } ++#endif /* DWC_UTE_PER_IO */ ++ else { ++ if (core_if->dma_desc_enable && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ handle_xfercompl_iso_ddma(dev_if, ep); ++ } else { ++ if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC && ++ dwc_ep->bInterval > 1) { ++ dwc_ep->frame_num += dwc_ep->bInterval; ++ if (dwc_ep->frame_num > 0x3FFF) ++ { ++ dwc_ep->frm_overrun = 1; ++ dwc_ep->frame_num &= 0x3FFF; ++ } else ++ dwc_ep->frm_overrun = 0; ++ } ++ complete_ep(ep); ++ if(diepint.b.nak) ++ CLEAR_IN_EP_INTR(core_if, epnum, nak); ++ } ++ } ++ } ++ /* Endpoint disable */ ++ if (diepint.b.epdisabled) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d IN disabled\n", ++ epnum); ++ handle_in_ep_disable_intr(pcd, epnum); ++ ++ /* Clear the bit in DIEPINTn for this interrupt */ ++ CLEAR_IN_EP_INTR(core_if, epnum, epdisabled); ++ } ++ /* AHB Error */ ++ if (diepint.b.ahberr) { ++ DWC_ERROR("EP%d IN AHB Error\n", epnum); ++ /* Clear the bit in DIEPINTn for this interrupt */ ++ CLEAR_IN_EP_INTR(core_if, epnum, ahberr); ++ } ++ /* TimeOUT Handshake (non-ISOC IN EPs) */ ++ if (diepint.b.timeout) { ++ DWC_ERROR("EP%d IN Time-out\n", epnum); ++ handle_in_ep_timeout_intr(pcd, epnum); ++ ++ CLEAR_IN_EP_INTR(core_if, epnum, timeout); ++ } ++ /** IN Token received with TxF Empty */ ++ if (diepint.b.intktxfemp) { ++ DWC_DEBUGPL(DBG_ANY, ++ "EP%d IN TKN TxFifo Empty\n", ++ epnum); ++ if (!ep->stopped && epnum != 0) { ++ ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ diepmsk.b.intktxfemp = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32 ++ (&dev_if->dev_global_regs->diepeachintmsk ++ [epnum], diepmsk.d32, 0); ++ } else { ++ DWC_MODIFY_REG32 ++ (&dev_if->dev_global_regs->diepmsk, ++ diepmsk.d32, 0); ++ } ++ } else if (core_if->dma_desc_enable ++ && epnum == 0 ++ && pcd->ep0state == ++ EP0_OUT_STATUS_PHASE) { ++ // EP0 IN set STALL ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs ++ [epnum]->diepctl); ++ ++ /* set the disable and stall bits */ ++ if (depctl.b.epena) { ++ depctl.b.epdis = 1; ++ } ++ depctl.b.stall = 1; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs ++ [epnum]->diepctl, ++ depctl.d32); ++ } ++ CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp); ++ } ++ /** IN Token Received with EP mismatch */ ++ if (diepint.b.intknepmis) { ++ DWC_DEBUGPL(DBG_ANY, ++ "EP%d IN TKN EP Mismatch\n", epnum); ++ CLEAR_IN_EP_INTR(core_if, epnum, intknepmis); ++ } ++ /** IN Endpoint NAK Effective */ ++ if (diepint.b.inepnakeff) { ++ DWC_DEBUGPL(DBG_ANY, ++ "EP%d IN EP NAK Effective\n", ++ epnum); ++ /* Periodic EP */ ++ if (ep->disabling) { ++ depctl.d32 = 0; ++ depctl.b.snak = 1; ++ depctl.b.epdis = 1; ++ DWC_MODIFY_REG32(&dev_if->in_ep_regs ++ [epnum]->diepctl, ++ depctl.d32, ++ depctl.d32); ++ } ++ CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff); ++ ++ } ++ ++ /** IN EP Tx FIFO Empty Intr */ ++ if (diepint.b.emptyintr) { ++ DWC_DEBUGPL(DBG_ANY, ++ "EP%d Tx FIFO Empty Intr \n", ++ epnum); ++ write_empty_tx_fifo(pcd, epnum); ++ ++ CLEAR_IN_EP_INTR(core_if, epnum, emptyintr); ++ ++ } ++ ++ /** IN EP BNA Intr */ ++ if (diepint.b.bna) { ++ CLEAR_IN_EP_INTR(core_if, epnum, bna); ++ if (core_if->dma_desc_enable) { ++#ifdef DWC_EN_ISOC ++ if (dwc_ep->type == ++ DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * This checking is performed to prevent first "false" BNA ++ * handling occuring right after reconnect ++ */ ++ if (dwc_ep->next_frame != ++ 0xffffffff) ++ dwc_otg_pcd_handle_iso_bna(ep); ++ } else ++#endif /* DWC_EN_ISOC */ ++ { ++ dwc_otg_pcd_handle_noniso_bna(ep); ++ } ++ } ++ } ++ /* NAK Interrupt */ ++ if (diepint.b.nak) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n", ++ epnum); ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ if (core_if->dma_desc_enable) { ++ if (ep->dwc_ep.frame_num == 0xFFFFFFFF) { ++ ep->dwc_ep.frame_num = core_if->frame_num; ++ dwc_otg_pcd_start_iso_ddma(core_if, ep); ++ } else { ++ ep->dwc_ep.frame_num = core_if->frame_num + ep->dwc_ep.bInterval; ++ CLEAR_IN_EP_INTR(core_if, epnum, nak); ++ } ++ } else { ++ depctl_data_t depctl; ++ if (ep->dwc_ep.frame_num == 0xFFFFFFFF) { ++ ep->dwc_ep.frame_num = core_if->frame_num; ++ if (ep->dwc_ep.bInterval > 1) { ++ depctl.d32 = 0; ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); ++ if (ep->dwc_ep.frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ depctl.b.setd0pid = 0; ++ } else { ++ depctl.b.setd0pid = 1; ++ depctl.b.setd1pid = 0; ++ } ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepctl, depctl.d32); ++ } ++ start_next_request(ep); ++ } ++ ep->dwc_ep.frame_num += ep->dwc_ep.bInterval; ++ if (dwc_ep->frame_num > 0x3FFF) { ++ dwc_ep->frm_overrun = 1; ++ dwc_ep->frame_num &= 0x3FFF; ++ } else { ++ dwc_ep->frm_overrun = 0; ++ } ++ } ++ } ++ ++ CLEAR_IN_EP_INTR(core_if, epnum, nak); ++ } ++ } ++ epnum++; ++ ep_intr >>= 1; ++ } ++ ++ return 1; ++#undef CLEAR_IN_EP_INTR ++} ++ ++/** ++ * This interrupt indicates that an OUT EP has a pending Interrupt. ++ * The sequence for handling the OUT EP interrupt is shown below: ++ * -# Read the Device All Endpoint Interrupt register ++ * -# Repeat the following for each OUT EP interrupt bit set (from ++ * LSB to MSB). ++ * -# Read the Device Endpoint Interrupt (DOEPINTn) register ++ * -# If "Transfer Complete" call the request complete function ++ * -# If "Endpoint Disabled" complete the EP disable procedure. ++ * -# If "AHB Error Interrupt" log error ++ * -# If "Setup Phase Done" process Setup Packet (See Standard USB ++ * Command Processing) ++ */ ++static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd) ++{ ++#define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \ ++do { \ ++ doepint_data_t doepint = {.d32=0}; \ ++ doepint.b.__intr = 1; \ ++ DWC_WRITE_REG32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \ ++ doepint.d32); \ ++} while (0) ++ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ uint32_t ep_intr; ++ doepint_data_t doepint = {.d32 = 0 }; ++ uint32_t epnum = 0; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ dctl_data_t dctl = {.d32 = 0 }; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__); ++ ++ /* Read in the device interrupt bits */ ++ ep_intr = dwc_otg_read_dev_all_out_ep_intr(core_if); ++ ++ while (ep_intr) { ++ if (ep_intr & 0x1) { ++ /* Get EP pointer */ ++ ep = get_out_ep(pcd, epnum); ++ if (!ep) ++ return -EINVAL; ++ ++ dwc_ep = &ep->dwc_ep; ++ if (!dwc_ep) ++ return -EINVAL; ++ ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, ++ "EP%d-%s: type=%d, mps=%d\n", ++ dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"), ++ dwc_ep->type, dwc_ep->maxpacket); ++#endif ++ doepint.d32 = ++ dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep); ++ ++ /* Transfer complete */ ++ if (doepint.b.xfercompl) { ++ ++ if (epnum == 0) { ++ /* Clear the bit in DOEPINTn for this interrupt */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl); ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ DWC_DEBUGPL(DBG_PCDV, "in xfer xomplete DOEPINT=%x doepint=%x\n", ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepint), ++ doepint.d32); ++ DWC_DEBUGPL(DBG_PCDV, "DOEPCTL=%x \n", ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepctl)); ++ ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a ++ && core_if->dma_enable == 0) { ++ doepint_data_t doepint; ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepint); ++ if (pcd->ep0state == EP0_IDLE && doepint.b.sr) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, sr); ++ if (doepint.b.stsphsercvd) ++ CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd); ++ goto exit_xfercompl; ++ } ++ } ++ /* In case of DDMA look at SR bit to go to the Data Stage */ ++ if (core_if->dma_desc_enable) { ++ dev_dma_desc_sts_t status = {.d32 = 0}; ++ if (pcd->ep0state == EP0_IDLE) { ++ status.d32 = core_if->dev_if->setup_desc_addr[core_if-> ++ dev_if->setup_desc_index]->status.d32; ++ if(pcd->data_terminated) { ++ pcd->data_terminated = 0; ++ status.d32 = core_if->dev_if->out_desc_addr->status.d32; ++ dwc_memcpy(&pcd->setup_pkt->req, pcd->backup_buf, 8); ++ } ++ if (status.b.sr) { ++ if (doepint.b.setup) { ++ DWC_DEBUGPL(DBG_PCDV, "DMA DESC EP0_IDLE SR=1 setup=1\n"); ++ /* Already started data stage, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ /* Prepare for more setup packets */ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE || ++ pcd->ep0state == EP0_IN_DATA_PHASE) { ++ ep0_out_start(core_if, pcd); ++ } ++ ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ DWC_DEBUGPL(DBG_PCDV, ++ "EP0_IDLE SR=1 setup=0 new setup comes\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ } else { ++ dwc_otg_pcd_request_t *req; ++ dev_dma_desc_sts_t status = {.d32 = 0}; ++ diepint_data_t diepint0; ++ diepint0.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ ++ if (pcd->ep0state == EP0_STALL || pcd->ep0state == EP0_DISCONNECT) { ++ DWC_ERROR("EP0 is stalled/disconnected\n"); ++ } ++ ++ /* Clear IN xfercompl if set */ ++ if (diepint0.b.xfercompl && (pcd->ep0state == EP0_IN_STATUS_PHASE ++ || pcd->ep0state == EP0_IN_DATA_PHASE)) { ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint, diepint0.d32); ++ } ++ ++ status.d32 = core_if->dev_if->setup_desc_addr[core_if-> ++ dev_if->setup_desc_index]->status.d32; ++ ++ if ((pcd->ep0state == EP0_OUT_STATUS_PHASE) || ++ (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len ++ && pcd->ep0state == EP0_OUT_DATA_PHASE)) ++ status.d32 = core_if->dev_if->out_desc_addr->status.d32; ++ if (status.b.sr) { ++ if (DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n"); ++ } else { ++ DWC_DEBUGPL(DBG_PCDV, "complete req!!\n"); ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len && ++ pcd->ep0state == EP0_OUT_DATA_PHASE) { ++ /* Read arrived setup packet from req->buf */ ++ dwc_memcpy(&pcd->setup_pkt->req, ++ req->buf + ep->dwc_ep.xfer_count, 8); ++ } ++ req->actual = ep->dwc_ep.xfer_count; ++ dwc_otg_request_done(ep, req, -ECONNRESET); ++ ep->dwc_ep.start_xfer_buff = 0; ++ ep->dwc_ep.xfer_buff = 0; ++ ep->dwc_ep.xfer_len = 0; ++ } ++ pcd->ep0state = EP0_IDLE; ++ if (doepint.b.setup) { ++ DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n"); ++ /* Data stage started, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ /* Prepare for setup packets if ep0in was enabled*/ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ ep0_out_start(core_if, pcd); ++ } ++ ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ DWC_DEBUGPL(DBG_PCDV, ++ "EP0_IDLE SR=1 setup=0 new setup comes 2\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ } ++ } ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a && core_if->dma_enable ++ && core_if->dma_desc_enable == 0) { ++ doepint_data_t doepint_temp = {.d32 = 0}; ++ deptsiz0_data_t doeptsize0 = {.d32 = 0 }; ++ doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->dwc_ep.num]->doepint); ++ doeptsize0.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->dwc_ep.num]->doeptsiz); ++ if (((ep->dwc_ep.xfer_count == ep->dwc_ep.total_len || doeptsize0.b.xfersize == 64) && ++ pcd->ep0state == EP0_OUT_DATA_PHASE && doepint.b.stsphsercvd) || ++ (doeptsize0.b.xfersize == 24 && pcd->ep0state == EP0_IN_STATUS_PHASE)) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl); ++ DWC_DEBUGPL(DBG_PCDV, "WA for xfercompl along with stsphs \n"); ++ doepint.b.xfercompl = 0; ++ ep0_out_start(core_if, pcd); ++ goto exit_xfercompl; ++ } ++ ++ if (pcd->ep0state == EP0_IDLE) { ++ if (doepint_temp.b.sr) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, sr); ++ } ++ /* Delay is needed for core to update setup ++ * packet count from 3 to 2 after receiving ++ * setup packet*/ ++ dwc_udelay(100); ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepint); ++ if (doeptsize0.b.supcnt == 3) { ++ DWC_DEBUGPL(DBG_ANY, "Rolling over!!!!!!!\n"); ++ ep->dwc_ep.stp_rollover = 1; ++ } ++ if (doepint.b.setup) { ++retry: ++ /* Already started data stage, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ ep->dwc_ep.stp_rollover = 0; ++ /* Prepare for more setup packets */ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE || ++ pcd->ep0state == EP0_IN_DATA_PHASE) { ++ depctl_data_t depctl = {.d32 = 0}; ++ depctl.b.cnak = 1; ++ ep0_out_start(core_if, pcd); ++ /* Core not updating setup packet count ++ * in case of PET testing - @TODO vahrama ++ * to check with HW team further */ ++ if (!core_if->otg_ver) { ++ DWC_MODIFY_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepctl, 0, depctl.d32); ++ } ++ } ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ DWC_DEBUGPL(DBG_ANY, ++ "EP0_IDLE SR=1 setup=0 new setup comes\n"); ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepint); ++ if(doepint.b.setup) ++ goto retry; ++ ep0_out_start(core_if, pcd); ++ } ++ } else { ++ dwc_otg_pcd_request_t *req; ++ diepint_data_t diepint0 = {.d32 = 0}; ++ doepint_data_t doepint_temp = {.d32 = 0}; ++ depctl_data_t diepctl0; ++ diepint0.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ diepctl0.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepctl); ++ ++ if (pcd->ep0state == EP0_IN_DATA_PHASE ++ || pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ if (diepint0.b.xfercompl) { ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint, diepint0.d32); ++ } ++ if (diepctl0.b.epena) { ++ diepint_data_t diepint = {.d32 = 0}; ++ diepctl0.b.snak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepctl, diepctl0.d32); ++ do { ++ dwc_udelay(10); ++ diepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ } while (!diepint.b.inepnakeff); ++ diepint.b.inepnakeff = 1; ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint, diepint.d32); ++ diepctl0.d32 = 0; ++ diepctl0.b.epdis = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl, ++ diepctl0.d32); ++ do { ++ dwc_udelay(10); ++ diepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ } while (!diepint.b.epdisabled); ++ diepint.b.epdisabled = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepint, ++ diepint.d32); ++ } ++ } ++ doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->dwc_ep.num]->doepint); ++ if (doepint_temp.b.sr) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, sr); ++ if (DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n"); ++ } else { ++ DWC_DEBUGPL(DBG_PCDV, "complete req!!\n"); ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len && ++ pcd->ep0state == EP0_OUT_DATA_PHASE) { ++ /* Read arrived setup packet from req->buf */ ++ dwc_memcpy(&pcd->setup_pkt->req, ++ req->buf + ep->dwc_ep.xfer_count, 8); ++ } ++ req->actual = ep->dwc_ep.xfer_count; ++ dwc_otg_request_done(ep, req, -ECONNRESET); ++ ep->dwc_ep.start_xfer_buff = 0; ++ ep->dwc_ep.xfer_buff = 0; ++ ep->dwc_ep.xfer_len = 0; ++ } ++ pcd->ep0state = EP0_IDLE; ++ if (doepint.b.setup) { ++ DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n"); ++ /* Data stage started, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ /* Prepare for setup packets if ep0in was enabled*/ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ depctl_data_t depctl = {.d32 = 0}; ++ depctl.b.cnak = 1; ++ ep0_out_start(core_if, pcd); ++ /* Core not updating setup packet count ++ * in case of PET testing - @TODO vahrama ++ * to check with HW team further */ ++ if (!core_if->otg_ver) { ++ DWC_MODIFY_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepctl, 0, depctl.d32); ++ } ++ } ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ DWC_DEBUGPL(DBG_PCDV, ++ "EP0_IDLE SR=1 setup=0 new setup comes 2\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ } ++ } ++ if (core_if->dma_enable == 0 || pcd->ep0state != EP0_IDLE) ++ handle_ep0(pcd); ++exit_xfercompl: ++ DWC_DEBUGPL(DBG_PCDV, "after DOEPINT=%x doepint=%x\n", ++ dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep), doepint.d32); ++ } else { ++ if (core_if->dma_desc_enable == 0 ++ || pcd->ep0state != EP0_IDLE) ++ handle_ep0(pcd); ++ } ++#ifdef DWC_EN_ISOC ++ } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (doepint.b.pktdrpsts == 0) { ++ /* Clear the bit in DOEPINTn for this interrupt */ ++ CLEAR_OUT_EP_INTR(core_if, ++ epnum, ++ xfercompl); ++ complete_iso_ep(pcd, ep); ++ } else { ++ ++ doepint_data_t doepint = {.d32 = 0 }; ++ doepint.b.xfercompl = 1; ++ doepint.b.pktdrpsts = 1; ++ DWC_WRITE_REG32 ++ (&core_if->dev_if->out_ep_regs ++ [epnum]->doepint, ++ doepint.d32); ++ if (handle_iso_out_pkt_dropped ++ (core_if, dwc_ep)) { ++ complete_iso_ep(pcd, ++ ep); ++ } ++ } ++#endif /* DWC_EN_ISOC */ ++#ifdef DWC_UTE_PER_IO ++ } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl); ++ if (!ep->stopped) ++ complete_xiso_ep(ep); ++#endif /* DWC_UTE_PER_IO */ ++ } else { ++ /* Clear the bit in DOEPINTn for this interrupt */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, ++ xfercompl); ++ ++ if (core_if->core_params->dev_out_nak) { ++ DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[epnum]); ++ pcd->core_if->ep_xfer_info[epnum].state = 0; ++#ifdef DEBUG ++ print_memory_payload(pcd, dwc_ep); ++#endif ++ } ++ if (core_if->dma_desc_enable && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ handle_xfercompl_iso_ddma(core_if->dev_if, ep); ++ } else { ++ complete_ep(ep); ++ } ++ } ++ ++ } ++ if (doepint.b.stsphsercvd) { ++ deptsiz0_data_t deptsiz; ++ CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd); ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doeptsiz); ++ if ((core_if->dma_desc_enable) || (core_if->dma_enable && ++ core_if->snpsid >= OTG_CORE_REV_3_00a)) { ++ do_setup_in_status_phase(pcd); ++ } ++ } ++ ++ /* Endpoint disable */ ++ if (doepint.b.epdisabled) { ++ ++ /* Clear the bit in DOEPINTn for this interrupt */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled); ++ if (core_if->core_params->dev_out_nak) { ++#ifdef DEBUG ++ print_memory_payload(pcd, dwc_ep); ++#endif ++ /* In case of timeout condition */ ++ if (core_if->ep_xfer_info[epnum].state == 2) { ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dctl); ++ dctl.b.cgoutnak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ /* Unmask goutnakeff interrupt which was masked ++ * during handle nak out interrupt */ ++ gintmsk.b.goutnakeff = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, ++ 0, gintmsk.d32); ++ ++ complete_ep(ep); ++ } ++ } ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ++ { ++ dctl_data_t dctl; ++ gintmsk_data_t intr_mask = {.d32 = 0}; ++ dwc_otg_pcd_request_t *req = 0; ++ ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dctl); ++ dctl.b.cgoutnak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ ++ intr_mask.d32 = 0; ++ intr_mask.b.incomplisoout = 1; ++ ++ /* Get any pending requests */ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); ++ } else { ++ dwc_otg_request_done(ep, req, 0); ++ start_next_request(ep); ++ } ++ } else { ++ DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); ++ } ++ } ++ } ++ /* AHB Error */ ++ if (doepint.b.ahberr) { ++ DWC_ERROR("EP%d OUT AHB Error\n", epnum); ++ DWC_ERROR("EP%d DEPDMA=0x%08x \n", ++ epnum, core_if->dev_if->out_ep_regs[epnum]->doepdma); ++ CLEAR_OUT_EP_INTR(core_if, epnum, ahberr); ++ } ++ /* Setup Phase Done (contorl EPs) */ ++ if (doepint.b.setup) { ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n", epnum); ++#endif ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ ++ handle_ep0(pcd); ++ } ++ ++ /** OUT EP BNA Intr */ ++ if (doepint.b.bna) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, bna); ++ if (core_if->dma_desc_enable) { ++#ifdef DWC_EN_ISOC ++ if (dwc_ep->type == ++ DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * This checking is performed to prevent first "false" BNA ++ * handling occuring right after reconnect ++ */ ++ if (dwc_ep->next_frame != ++ 0xffffffff) ++ dwc_otg_pcd_handle_iso_bna(ep); ++ } else ++#endif /* DWC_EN_ISOC */ ++ if (ep->dwc_ep.type != DWC_OTG_EP_TYPE_ISOC) { ++ dwc_otg_pcd_handle_noniso_bna(ep); ++ } ++ } ++ } ++ /* Babble Interrupt */ ++ if (doepint.b.babble) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d OUT Babble\n", ++ epnum); ++ handle_out_ep_babble_intr(pcd, epnum); ++ ++ CLEAR_OUT_EP_INTR(core_if, epnum, babble); ++ } ++ if (doepint.b.outtknepdis) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d OUT Token received when EP is \ ++ disabled\n",epnum); ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ if (core_if->dma_desc_enable) { ++ if (!ep->dwc_ep.iso_transfer_started) { ++ ep->dwc_ep.frame_num = core_if->frame_num; ++ dwc_otg_pcd_start_iso_ddma(core_if, ep); ++ } ++ } else { ++ doepmsk_data_t doepmsk = {.d32 = 0}; ++ ep->dwc_ep.frame_num = core_if->frame_num; ++ if (ep->dwc_ep.bInterval > 1) { ++ depctl_data_t depctl; ++ depctl.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[epnum]->doepctl); ++ if (ep->dwc_ep.frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ depctl.b.setd0pid = 0; ++ } else { ++ depctl.b.setd0pid = 1; ++ depctl.b.setd1pid = 0; ++ } ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ out_ep_regs[epnum]->doepctl, depctl.d32); ++ } ++ ++ start_next_request(ep); ++ doepmsk.b.outtknepdis = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, ++ doepmsk.d32, 0); ++ } ++ } ++ CLEAR_OUT_EP_INTR(core_if, epnum, outtknepdis); ++ } ++ ++ /* NAK Interrutp */ ++ if (doepint.b.nak) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d OUT NAK\n", epnum); ++ handle_out_ep_nak_intr(pcd, epnum); ++ ++ CLEAR_OUT_EP_INTR(core_if, epnum, nak); ++ } ++ /* NYET Interrutp */ ++ if (doepint.b.nyet) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d OUT NYET\n", epnum); ++ handle_out_ep_nyet_intr(pcd, epnum); ++ ++ CLEAR_OUT_EP_INTR(core_if, epnum, nyet); ++ } ++ } ++ ++ epnum++; ++ ep_intr >>= 1; ++ } ++ ++ return 1; ++ ++#undef CLEAR_OUT_EP_INTR ++} ++static int drop_transfer(uint32_t trgt_fr, uint32_t curr_fr, uint8_t frm_overrun) ++{ ++ int retval = 0; ++ if(!frm_overrun && curr_fr >= trgt_fr) ++ retval = 1; ++ else if (frm_overrun ++ && (curr_fr >= trgt_fr && ((curr_fr - trgt_fr) < 0x3FFF / 2))) ++ retval = 1; ++ return retval; ++} ++ ++/** ++ * Incomplete ISO IN Transfer Interrupt. ++ * This interrupt indicates one of the following conditions occurred ++ * while transmitting an ISOC transaction. ++ * - Corrupted IN Token for ISOC EP. ++ * - Packet not complete in FIFO. ++ * The follow actions will be taken: ++ * -# Determine the EP ++ * -# Set incomplete flag in dwc_ep structure ++ * -# Disable EP; when "Endpoint Disabled" interrupt is received ++ * Flush FIFO ++ */ ++int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintsts_data_t gintsts; ++ ++#ifdef DWC_EN_ISOC ++ dwc_otg_dev_if_t *dev_if; ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dsts_data_t dsts = {.d32 = 0 }; ++ dwc_ep_t *dwc_ep; ++ int i; ++ ++ dev_if = GET_CORE_IF(pcd)->dev_if; ++ ++ for (i = 1; i <= dev_if->num_in_eps; ++i) { ++ dwc_ep = &pcd->in_ep[i].dwc_ep; ++ if (dwc_ep->active && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ deptsiz.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz); ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ ++ if (depctl.b.epdis && deptsiz.d32) { ++ set_current_pkt_info(GET_CORE_IF(pcd), dwc_ep); ++ if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { ++ dwc_ep->cur_pkt = 0; ++ dwc_ep->proc_buf_num = ++ (dwc_ep->proc_buf_num ^ 1) & 0x1; ++ ++ if (dwc_ep->proc_buf_num) { ++ dwc_ep->cur_pkt_addr = ++ dwc_ep->xfer_buff1; ++ dwc_ep->cur_pkt_dma_addr = ++ dwc_ep->dma_addr1; ++ } else { ++ dwc_ep->cur_pkt_addr = ++ dwc_ep->xfer_buff0; ++ dwc_ep->cur_pkt_dma_addr = ++ dwc_ep->dma_addr0; ++ } ++ ++ } ++ ++ dsts.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ dev_global_regs->dsts); ++ dwc_ep->next_frame = dsts.b.soffn; ++ ++ dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF ++ (pcd), ++ dwc_ep); ++ } ++ } ++ } ++ ++#else ++ depctl_data_t depctl = {.d32 = 0 }; ++ dwc_ep_t *dwc_ep; ++ dwc_otg_dev_if_t *dev_if; ++ int i; ++ dev_if = GET_CORE_IF(pcd)->dev_if; ++ ++ DWC_DEBUGPL(DBG_PCD,"Incomplete ISO IN \n"); ++ ++ for (i = 1; i <= dev_if->num_in_eps; ++i) { ++ dwc_ep = &pcd->in_ep[i-1].dwc_ep; ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (depctl.b.epena && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (drop_transfer(dwc_ep->frame_num, GET_CORE_IF(pcd)->frame_num, ++ dwc_ep->frm_overrun)) ++ { ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ depctl.b.snak = 1; ++ depctl.b.epdis = 1; ++ DWC_MODIFY_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32, depctl.d32); ++ } ++ } ++ } ++ ++ /*intr_mask.b.incomplisoin = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); */ ++#endif //DWC_EN_ISOC ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.incomplisoin = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * Incomplete ISO OUT Transfer Interrupt. ++ * ++ * This interrupt indicates that the core has dropped an ISO OUT ++ * packet. The following conditions can be the cause: ++ * - FIFO Full, the entire packet would not fit in the FIFO. ++ * - CRC Error ++ * - Corrupted Token ++ * The follow actions will be taken: ++ * -# Determine the EP ++ * -# Set incomplete flag in dwc_ep structure ++ * -# Read any data from the FIFO ++ * -# Disable EP. When "Endpoint Disabled" interrupt is received ++ * re-enable EP. ++ */ ++int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd) ++{ ++ ++ gintsts_data_t gintsts; ++ ++#ifdef DWC_EN_ISOC ++ dwc_otg_dev_if_t *dev_if; ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dsts_data_t dsts = {.d32 = 0 }; ++ dwc_ep_t *dwc_ep; ++ int i; ++ ++ dev_if = GET_CORE_IF(pcd)->dev_if; ++ ++ for (i = 1; i <= dev_if->num_out_eps; ++i) { ++ dwc_ep = &pcd->in_ep[i].dwc_ep; ++ if (pcd->out_ep[i].dwc_ep.active && ++ pcd->out_ep[i].dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ deptsiz.d32 = ++ DWC_READ_REG32(&dev_if->out_ep_regs[i]->doeptsiz); ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); ++ ++ if (depctl.b.epdis && deptsiz.d32) { ++ set_current_pkt_info(GET_CORE_IF(pcd), ++ &pcd->out_ep[i].dwc_ep); ++ if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { ++ dwc_ep->cur_pkt = 0; ++ dwc_ep->proc_buf_num = ++ (dwc_ep->proc_buf_num ^ 1) & 0x1; ++ ++ if (dwc_ep->proc_buf_num) { ++ dwc_ep->cur_pkt_addr = ++ dwc_ep->xfer_buff1; ++ dwc_ep->cur_pkt_dma_addr = ++ dwc_ep->dma_addr1; ++ } else { ++ dwc_ep->cur_pkt_addr = ++ dwc_ep->xfer_buff0; ++ dwc_ep->cur_pkt_dma_addr = ++ dwc_ep->dma_addr0; ++ } ++ ++ } ++ ++ dsts.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ dev_global_regs->dsts); ++ dwc_ep->next_frame = dsts.b.soffn; ++ ++ dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF ++ (pcd), ++ dwc_ep); ++ } ++ } ++ } ++#else ++ /** @todo implement ISR */ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if; ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ dwc_ep_t *dwc_ep = NULL; ++ int i; ++ core_if = GET_CORE_IF(pcd); ++ ++ for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { ++ dwc_ep = &pcd->out_ep[i].dwc_ep; ++ depctl.d32 = ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl); ++ if (depctl.b.epena && depctl.b.dpid == (core_if->frame_num & 0x1)) { ++ core_if->dev_if->isoc_ep = dwc_ep; ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz); ++ break; ++ } ++ } ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ intr_mask.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ ++ if (!intr_mask.b.goutnakeff) { ++ /* Unmask it */ ++ intr_mask.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32); ++ } ++ if (!gintsts.b.goutnakeff) { ++ dctl.b.sgoutnak = 1; ++ } ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++ ++ depctl.d32 = DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl); ++ if (depctl.b.epena) { ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ } ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl, depctl.d32); ++ ++ intr_mask.d32 = 0; ++ intr_mask.b.incomplisoout = 1; ++ ++#endif /* DWC_EN_ISOC */ ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.incomplisoout = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This function handles the Global IN NAK Effective interrupt. ++ * ++ */ ++int32_t dwc_otg_pcd_handle_in_nak_effective(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ depctl_data_t diepctl = {.d32 = 0 }; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ int i; ++ ++ DWC_DEBUGPL(DBG_PCD, "Global IN NAK Effective\n"); ++ ++ /* Disable all active IN EPs */ ++ for (i = 0; i <= dev_if->num_in_eps; i++) { ++ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (!(diepctl.b.eptype & 1) && diepctl.b.epena) { ++ if (core_if->start_predict > 0) ++ core_if->start_predict++; ++ diepctl.b.epdis = 1; ++ diepctl.b.snak = 1; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, diepctl.d32); ++ } ++ } ++ ++ ++ /* Disable the Global IN NAK Effective Interrupt */ ++ intr_mask.b.ginnakeff = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.ginnakeff = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * OUT NAK Effective. ++ * ++ */ ++int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ depctl_data_t doepctl; ++ int i; ++ ++ /* Disable the Global OUT NAK Effective Interrupt */ ++ intr_mask.b.goutnakeff = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* If DEV OUT NAK enabled */ ++ if (pcd->core_if->core_params->dev_out_nak) { ++ /* Run over all out endpoints to determine the ep number on ++ * which the timeout has happened ++ */ ++ for (i = 0; i <= dev_if->num_out_eps; i++) { ++ if (pcd->core_if->ep_xfer_info[i].state == 2) ++ break; ++ } ++ if (i > dev_if->num_out_eps) { ++ dctl_data_t dctl; ++ dctl.d32 = ++ DWC_READ_REG32(&dev_if->dev_global_regs->dctl); ++ dctl.b.cgoutnak = 1; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ goto out; ++ } ++ ++ /* Disable the endpoint */ ++ doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); ++ if (doepctl.b.epena) { ++ doepctl.b.epdis = 1; ++ doepctl.b.snak = 1; ++ } ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32); ++ return 1; ++ } ++ /* We come here from Incomplete ISO OUT handler */ ++ if (dev_if->isoc_ep) { ++ dwc_ep_t *dwc_ep = (dwc_ep_t *) dev_if->isoc_ep; ++ uint32_t epnum = dwc_ep->num; ++ doepint_data_t doepint; ++ doepint.d32 = ++ DWC_READ_REG32(&dev_if->out_ep_regs[dwc_ep->num]->doepint); ++ dev_if->isoc_ep = NULL; ++ doepctl.d32 = ++ DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl); ++ DWC_PRINTF("Before disable DOEPCTL = %08x\n", doepctl.d32); ++ if (doepctl.b.epena) { ++ doepctl.b.epdis = 1; ++ doepctl.b.snak = 1; ++ } ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepctl, ++ doepctl.d32); ++ return 1; ++ } else ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", ++ "Global OUT NAK Effective\n"); ++ ++out: ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * PCD interrupt handler. ++ * ++ * The PCD handles the device interrupts. Many conditions can cause a ++ * device interrupt. When an interrupt occurs, the device interrupt ++ * service routine determines the cause of the interrupt and ++ * dispatches handling to the appropriate function. These interrupt ++ * handling functions are described below. ++ * ++ * All interrupt registers are processed from LSB to MSB. ++ * ++ */ ++int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++#ifdef VERBOSE ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++#endif ++ gintsts_data_t gintr_status; ++ int32_t retval = 0; ++ ++ if (dwc_otg_check_haps_status(core_if) == -1 ) { ++ DWC_WARN("HAPS is disconnected"); ++ return retval; ++ } ++ ++ /* Exit from ISR if core is hibernated */ ++ if (core_if->hibernation_suspend == 1) { ++ return retval; ++ } ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_ANY, "%s() gintsts=%08x gintmsk=%08x\n", ++ __func__, ++ DWC_READ_REG32(&global_regs->gintsts), ++ DWC_READ_REG32(&global_regs->gintmsk)); ++#endif ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ DWC_SPINLOCK(pcd->lock); ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%08x gintmsk=%08x\n", ++ __func__, ++ DWC_READ_REG32(&global_regs->gintsts), ++ DWC_READ_REG32(&global_regs->gintmsk)); ++#endif ++ ++ gintr_status.d32 = dwc_otg_read_core_intr(core_if); ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s: gintsts&gintmsk=%08x\n", ++ __func__, gintr_status.d32); ++ ++ if (gintr_status.b.sofintr) { ++ retval |= dwc_otg_pcd_handle_sof_intr(pcd); ++ } ++ if (gintr_status.b.rxstsqlvl) { ++ retval |= ++ dwc_otg_pcd_handle_rx_status_q_level_intr(pcd); ++ } ++ if (gintr_status.b.nptxfempty) { ++ retval |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr(pcd); ++ } ++ if (gintr_status.b.goutnakeff) { ++ retval |= dwc_otg_pcd_handle_out_nak_effective(pcd); ++ } ++ if (gintr_status.b.i2cintr) { ++ retval |= dwc_otg_pcd_handle_i2c_intr(pcd); ++ } ++ if (gintr_status.b.erlysuspend) { ++ retval |= dwc_otg_pcd_handle_early_suspend_intr(pcd); ++ otg_usbhost_stat = 0; ++ hisi_switch_func(0); ++ } ++ if (gintr_status.b.usbreset) { ++ otg_usbhost_stat = 1; ++ retval |= dwc_otg_pcd_handle_usb_reset_intr(pcd); ++ hisi_switch_func(0); ++ } ++ if (gintr_status.b.enumdone) { ++ retval |= dwc_otg_pcd_handle_enum_done_intr(pcd); ++ } ++ if (gintr_status.b.isooutdrop) { ++ retval |= ++ dwc_otg_pcd_handle_isoc_out_packet_dropped_intr ++ (pcd); ++ } ++ if (gintr_status.b.eopframe) { ++ retval |= ++ dwc_otg_pcd_handle_end_periodic_frame_intr(pcd); ++ } ++ if (gintr_status.b.inepint) { ++ if (!core_if->multiproc_int_enable) { ++ retval |= dwc_otg_pcd_handle_in_ep_intr(pcd); ++ } ++ } ++ if (gintr_status.b.outepintr) { ++ otg_usbhost_stat = 1; ++ if (!core_if->multiproc_int_enable) { ++ retval |= dwc_otg_pcd_handle_out_ep_intr(pcd); ++ } ++ } ++ if (gintr_status.b.epmismatch) { ++ retval |= dwc_otg_pcd_handle_ep_mismatch_intr(pcd); ++ } ++ if (gintr_status.b.fetsusp) { ++ retval |= dwc_otg_pcd_handle_ep_fetsusp_intr(pcd); ++ } ++ if (gintr_status.b.ginnakeff) { ++ retval |= dwc_otg_pcd_handle_in_nak_effective(pcd); ++ } ++ if (gintr_status.b.incomplisoin) { ++ retval |= ++ dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd); ++ } ++ if (gintr_status.b.incomplisoout) { ++ retval |= ++ dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd); ++ } ++ ++ /* In MPI mode Device Endpoints interrupts are asserted ++ * without setting outepintr and inepint bits set, so these ++ * Interrupt handlers are called without checking these bit-fields ++ */ ++ if (core_if->multiproc_int_enable) { ++ retval |= dwc_otg_pcd_handle_in_ep_intr(pcd); ++ retval |= dwc_otg_pcd_handle_out_ep_intr(pcd); ++ } ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__, ++ DWC_READ_REG32(&global_regs->gintsts)); ++#endif ++ DWC_SPINUNLOCK(pcd->lock); ++ } ++ return retval; ++} ++ ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd_linux.c b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd_linux.c +new file mode 100644 +index 0000000..109ac01 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_pcd_linux.c +@@ -0,0 +1,1460 @@ ++ /* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $ ++ * $Revision: #28 $ ++ * $Date: 2013/05/07 $ ++ * $Change: 2224063 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 DWC_HOST_ONLY ++ ++/** @file ++ * This file implements the Peripheral Controller Driver. ++ * ++ * The Peripheral Controller Driver (PCD) is responsible for ++ * translating requests from the Function Driver into the appropriate ++ * actions on the DWC_otg controller. It isolates the Function Driver ++ * from the specifics of the controller by providing an API to the ++ * Function Driver. ++ * ++ * The Peripheral Controller Driver for Linux will implement the ++ * Gadget API, so that the existing Gadget drivers can be used. ++ * (Gadget Driver is the Linux terminology for a Function Driver.) ++ * ++ * The Linux Gadget API is defined in the header file ++ * . The USB EP operations API is ++ * defined in the structure usb_ep_ops and the USB ++ * Controller API is defined in the structure ++ * usb_gadget_ops. ++ * ++ */ ++ ++#include "dwc_otg_os_dep.h" ++#include "dwc_otg_pcd_if.h" ++#include "dwc_otg_pcd.h" ++#include "dwc_otg_driver.h" ++#include "dwc_otg_dbg.h" ++ ++static struct gadget_wrapper { ++ dwc_otg_pcd_t *pcd; ++ ++ struct usb_gadget gadget; ++ struct usb_gadget_driver *driver; ++ ++ struct usb_ep ep0; ++ struct usb_ep in_ep[16]; ++ struct usb_ep out_ep[16]; ++ ++} *gadget_wrapper; ++ ++/* Display the contents of the buffer */ ++extern void dump_msg(const u8 * buf, unsigned int length); ++ ++int udc_attach_driver(const char *name, struct usb_gadget_driver *driver) ++{ ++ //do nothing ,only make ++ return 0; ++} ++EXPORT_SYMBOL_GPL(udc_attach_driver); ++ ++void usb_gadget_set_state(struct usb_gadget *gadget, ++ enum usb_device_state state) ++{ ++ gadget->state = state; ++} ++EXPORT_SYMBOL_GPL(usb_gadget_set_state); ++ ++static int usb_gadget_map_req(struct usb_gadget *gadget, ++ struct usb_request *req, struct dwc_otg_pcd_ep *ep) ++{ ++ if (req->length == 0) ++ return 0; ++ ++ if (req->num_sgs) { ++ dev_err(&gadget->dev, "controller not support scatter/gather dma\n"); ++ return -EFAULT; ++ ++ } else { ++ ++ if (ep == &gadget_wrapper->pcd->ep0) { ++ req->dma = dma_map_single(&gadget->dev, req->buf, req->length, ++ DMA_BIDIRECTIONAL); ++ } else { ++ req->dma = dma_map_single(&gadget->dev, req->buf, req->length, ++ ep->dwc_ep.is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); ++ } ++ ++ if (dma_mapping_error(&gadget->dev, req->dma)) { ++ dev_err(&gadget->dev, "failed to map buffer\n"); ++ return -EFAULT; ++ } ++ } ++ ++ return 0; ++} ++ ++static void usb_gadget_unmap_req(struct usb_gadget *gadget, ++ struct usb_request *req, struct dwc_otg_pcd_ep *ep) ++{ ++ if (req->length == 0) ++ return; ++ ++ if (req->num_mapped_sgs) { ++ dev_err(&gadget->dev, "controller not support scatter/gather dma\n"); ++ } else { ++ ++ if (ep == &gadget_wrapper->pcd->ep0) { ++ dma_unmap_single(&gadget->dev, req->dma, req->length, ++ DMA_BIDIRECTIONAL); ++ } else { ++ dma_unmap_single(&gadget->dev, req->dma, req->length, ++ ep->dwc_ep.is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); ++ } ++ } ++} ++ ++/** ++ * Get the dwc_otg_pcd_ep_t* from usb_ep* pointer - NULL in case ++ * if the endpoint is not found ++ */ ++static struct dwc_otg_pcd_ep *ep_from_handle(dwc_otg_pcd_t * pcd, void *handle) ++{ ++ int i; ++ if (pcd->ep0.priv == handle) { ++ return &pcd->ep0; ++ } ++ ++ for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) { ++ if (pcd->in_ep[i].priv == handle) ++ return &pcd->in_ep[i]; ++ if (pcd->out_ep[i].priv == handle) ++ return &pcd->out_ep[i]; ++ } ++ ++ return NULL; ++} ++ ++/* USB Endpoint Operations */ ++/* ++ * The following sections briefly describe the behavior of the Gadget ++ * API endpoint operations implemented in the DWC_otg driver ++ * software. Detailed descriptions of the generic behavior of each of ++ * these functions can be found in the Linux header file ++ * include/linux/usb_gadget.h. ++ * ++ * The Gadget API provides wrapper functions for each of the function ++ * pointers defined in usb_ep_ops. The Gadget Driver calls the wrapper ++ * function, which then calls the underlying PCD function. The ++ * following sections are named according to the wrapper ++ * functions. Within each section, the corresponding DWC_otg PCD ++ * function name is specified. ++ * ++ */ ++ ++/** ++ * This function is called by the Gadget Driver for each EP to be ++ * configured for the current configuration (SET_CONFIGURATION). ++ * ++ * This function initializes the dwc_otg_ep_t data structure, and then ++ * calls dwc_otg_ep_activate. ++ */ ++static int ep_enable(struct usb_ep *usb_ep, ++ const struct usb_endpoint_descriptor *ep_desc) ++{ ++ int retval; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, ep_desc); ++ ++ if (!usb_ep || !ep_desc || ep_desc->bDescriptorType != USB_DT_ENDPOINT) { ++ DWC_WARN("%s, bad ep or descriptor\n", __func__); ++ return -EINVAL; ++ } ++ if (usb_ep == &gadget_wrapper->ep0) { ++ DWC_WARN("%s, bad ep(0)\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* Check FIFO size? */ ++ if (!ep_desc->wMaxPacketSize) { ++ DWC_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name); ++ return -ERANGE; ++ } ++ ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ DWC_WARN("%s, bogus device state\n", __func__); ++ return -ESHUTDOWN; ++ } ++ ++ /* Delete after check - MAS */ ++#if 0 ++ nat = (uint32_t) ep_desc->wMaxPacketSize; ++ printk(KERN_ALERT "%s: nat (before) =%d\n", __func__, nat); ++ nat = (nat >> 11) & 0x03; ++ printk(KERN_ALERT "%s: nat (after) =%d\n", __func__, nat); ++#endif ++ retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd, ++ (const uint8_t *)ep_desc, ++ (void *)usb_ep); ++ if (retval) { ++ DWC_WARN("dwc_otg_pcd_ep_enable failed\n"); ++ return -EINVAL; ++ } ++ ++ usb_ep->maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize); ++ ++ if (usb_ep->maxpacket == 5120) ++ usb_ep->maxpacket = 3072; ++ else if (usb_ep->maxpacket == 3072) ++ usb_ep->maxpacket = 2048; ++ ++ return 0; ++} ++ ++/** ++ * This function is called when an EP is disabled due to disconnect or ++ * change in configuration. Any pending requests will terminate with a ++ * status of -ESHUTDOWN. ++ * ++ * This function modifies the dwc_otg_ep_t data structure for this EP, ++ * and then calls dwc_otg_ep_deactivate. ++ */ ++static int ep_disable(struct usb_ep *usb_ep) ++{ ++ int retval; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, usb_ep); ++ if (!usb_ep) { ++ DWC_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__, ++ usb_ep ? usb_ep->name : NULL); ++ return -EINVAL; ++ } ++ ++ retval = dwc_otg_pcd_ep_disable(gadget_wrapper->pcd, usb_ep); ++ if (retval) { ++ retval = -EINVAL; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function allocates a request object to use with the specified ++ * endpoint. ++ * ++ * @param ep The endpoint to be used with with the request ++ * @param gfp_flags the GFP_* flags to use. ++ */ ++static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *ep, ++ gfp_t gfp_flags) ++{ ++ struct usb_request *usb_req; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d)\n", __func__, ep, gfp_flags); ++ if (0 == ep) { ++ DWC_WARN("%s() %s\n", __func__, "Invalid EP!\n"); ++ return 0; ++ } ++ usb_req = kmalloc(sizeof(*usb_req), gfp_flags); ++ if (0 == usb_req) { ++ DWC_WARN("%s() %s\n", __func__, "request allocation failed!\n"); ++ return 0; ++ } ++ memset(usb_req, 0, sizeof(*usb_req)); ++ usb_req->dma = DWC_DMA_ADDR_INVALID; ++ ++ return usb_req; ++} ++ ++/** ++ * This function frees a request object. ++ * ++ * @param ep The endpoint associated with the request ++ * @param req The request being freed ++ */ ++static void dwc_otg_pcd_free_request(struct usb_ep *ep, struct usb_request *req) ++{ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, ep, req); ++ ++ if (0 == ep || 0 == req) { ++ DWC_WARN("%s() %s\n", __func__, ++ "Invalid ep or req argument!\n"); ++ return; ++ } ++ ++ kfree(req); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++/** ++ * This function allocates an I/O buffer to be used for a transfer ++ * to/from the specified endpoint. ++ * ++ * @param usb_ep The endpoint to be used with with the request ++ * @param bytes The desired number of bytes for the buffer ++ * @param dma Pointer to the buffer's DMA address; must be valid ++ * @param gfp_flags the GFP_* flags to use. ++ * @return address of a new buffer or null is buffer could not be allocated. ++ */ ++static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes, ++ dma_addr_t * dma, gfp_t gfp_flags) ++{ ++ void *buf; ++ dwc_otg_pcd_t *pcd = 0; ++ ++ pcd = gadget_wrapper->pcd; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d,%p,%0x)\n", __func__, usb_ep, bytes, ++ dma, gfp_flags); ++ ++ /* Check dword alignment */ ++ if ((bytes & 0x3UL) != 0) { ++ DWC_WARN("%s() Buffer size is not a multiple of" ++ "DWORD size (%d)", __func__, bytes); ++ } ++ ++ buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags); ++ ++ /* Check dword alignment */ ++ if (((int)buf & 0x3UL) != 0) { ++ DWC_WARN("%s() Buffer is not DWORD aligned (%p)", ++ __func__, buf); ++ } ++ ++ return buf; ++} ++ ++/** ++ * This function frees an I/O buffer that was allocated by alloc_buffer. ++ * ++ * @param usb_ep the endpoint associated with the buffer ++ * @param buf address of the buffer ++ * @param dma The buffer's DMA address ++ * @param bytes The number of bytes of the buffer ++ */ ++static void dwc_otg_pcd_free_buffer(struct usb_ep *usb_ep, void *buf, ++ dma_addr_t dma, unsigned bytes) ++{ ++ dwc_otg_pcd_t *pcd = 0; ++ ++ pcd = gadget_wrapper->pcd; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%0x,%d)\n", __func__, buf, dma, bytes); ++ ++ dma_free_coherent(NULL, bytes, buf, dma); ++} ++#endif ++ ++/** ++ * This function is used to submit an I/O Request to an EP. ++ * ++ * - When the request completes the request's completion callback ++ * is called to return the request to the driver. ++ * - An EP, except control EPs, may have multiple requests ++ * pending. ++ * - Once submitted the request cannot be examined or modified. ++ * - Each request is turned into one or more packets. ++ * - A BULK EP can queue any amount of data; the transfer is ++ * packetized. ++ * - Zero length Packets are specified with the request 'zero' ++ * flag. ++ */ ++static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req, ++ gfp_t gfp_flags) ++{ ++ dwc_otg_pcd_t *pcd; ++ struct dwc_otg_pcd_ep *ep; ++ int retval, is_isoc_ep; ++ dma_addr_t dma_addr = 0; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p,%d)\n", ++ __func__, usb_ep, usb_req, gfp_flags); ++ ++ if (!usb_req || !usb_req->complete || !usb_req->buf) { ++ DWC_WARN("bad params\n"); ++ return -EINVAL; ++ } ++ ++ if (!usb_ep) { ++ DWC_WARN("bad ep\n"); ++ return -EINVAL; ++ } ++ ++ pcd = gadget_wrapper->pcd; ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n", ++ gadget_wrapper->gadget.speed); ++ DWC_WARN("bogus device state\n"); ++ return -ESHUTDOWN; ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "%s queue req %p, len %d buf %p\n", ++ usb_ep->name, usb_req, usb_req->length, usb_req->buf); ++ ++ usb_req->status = -EINPROGRESS; ++ usb_req->actual = 0; ++ ++ ep = ep_from_handle(pcd, usb_ep); ++ if (ep == NULL) ++ return -EINVAL; ++ else ++ is_isoc_ep = (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ? 1 : 0; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ dma_addr = usb_req->dma; ++#else ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ retval = usb_gadget_map_req(&gadget_wrapper->gadget, ++ usb_req, ep); ++ if (retval) { ++ return -EINVAL; ++ } ++ dma_addr =usb_req->dma; ++ } ++#endif ++ ++#ifdef DWC_UTE_PER_IO ++ if (is_isoc_ep == 1) { ++ retval = ++ dwc_otg_pcd_xiso_ep_queue(pcd, usb_ep, usb_req->buf, ++ dma_addr, usb_req->length, ++ usb_req->zero, usb_req, ++ gfp_flags == GFP_ATOMIC ? 1 : 0, ++ &usb_req->ext_req); ++ if (retval) ++ return -EINVAL; ++ ++ return 0; ++ } ++#endif ++ retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr, ++ usb_req->length, usb_req->zero, usb_req, ++ gfp_flags == GFP_ATOMIC ? 1 : 0); ++ if (retval) { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/** ++ * This function cancels an I/O request from an EP. ++ */ ++static int ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req) ++{ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, usb_req); ++ ++ if (!usb_ep || !usb_req) { ++ DWC_WARN("bad argument\n"); ++ return -EINVAL; ++ } ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ DWC_WARN("bogus device state\n"); ++ return -ESHUTDOWN; ++ } ++ if (dwc_otg_pcd_ep_dequeue(gadget_wrapper->pcd, usb_ep, usb_req)) { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/** ++ * usb_ep_set_halt stalls an endpoint. ++ * ++ * usb_ep_clear_halt clears an endpoint halt and resets its data ++ * toggle. ++ * ++ * Both of these functions are implemented with the same underlying ++ * function. The behavior depends on the value argument. ++ * ++ * @param[in] usb_ep the Endpoint to halt or clear halt. ++ * @param[in] value ++ * - 0 means clear_halt. ++ * - 1 means set_halt, ++ * - 2 means clear stall lock flag. ++ * - 3 means set stall lock flag. ++ */ ++static int ep_halt(struct usb_ep *usb_ep, int value) ++{ ++ int retval = 0; ++ ++ DWC_DEBUGPL(DBG_PCD, "HALT %s %d\n", usb_ep->name, value); ++ ++ if (!usb_ep) { ++ DWC_WARN("bad ep\n"); ++ return -EINVAL; ++ } ++ ++ retval = dwc_otg_pcd_ep_halt(gadget_wrapper->pcd, usb_ep, value); ++ if (retval == -DWC_E_AGAIN) { ++ return -EAGAIN; ++ } else if (retval) { ++ retval = -EINVAL; ++ } ++ ++ return retval; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) ++static int ep_wedge(struct usb_ep *usb_ep) ++{ ++ DWC_DEBUGPL(DBG_PCD, "WEDGE %s\n", usb_ep->name); ++ ++ return ep_halt(usb_ep, 3); ++} ++#endif ++ ++#ifdef DWC_EN_ISOC ++/** ++ * This function is used to submit an ISOC Transfer Request to an EP. ++ * ++ * - Every time a sync period completes the request's completion callback ++ * is called to provide data to the gadget driver. ++ * - Once submitted the request cannot be modified. ++ * - Each request is turned into periodic data packets untill ISO ++ * Transfer is stopped.. ++ */ ++static int iso_ep_start(struct usb_ep *usb_ep, struct usb_iso_request *req, ++ gfp_t gfp_flags) ++{ ++ int retval = 0; ++ ++ if (!req || !req->process_buffer || !req->buf0 || !req->buf1) { ++ DWC_WARN("bad params\n"); ++ return -EINVAL; ++ } ++ ++ if (!usb_ep) { ++ DWC_PRINTF("bad params\n"); ++ return -EINVAL; ++ } ++ ++ req->status = -EINPROGRESS; ++ ++ retval = ++ dwc_otg_pcd_iso_ep_start(gadget_wrapper->pcd, usb_ep, req->buf0, ++ req->buf1, req->dma0, req->dma1, ++ req->sync_frame, req->data_pattern_frame, ++ req->data_per_frame, ++ req-> ++ flags & USB_REQ_ISO_ASAP ? -1 : ++ req->start_frame, req->buf_proc_intrvl, ++ req, gfp_flags == GFP_ATOMIC ? 1 : 0); ++ ++ if (retval) { ++ return -EINVAL; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function stops ISO EP Periodic Data Transfer. ++ */ ++static int iso_ep_stop(struct usb_ep *usb_ep, struct usb_iso_request *req) ++{ ++ int retval = 0; ++ if (!usb_ep) { ++ DWC_WARN("bad ep\n"); ++ } ++ ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n", ++ gadget_wrapper->gadget.speed); ++ DWC_WARN("bogus device state\n"); ++ } ++ ++ dwc_otg_pcd_iso_ep_stop(gadget_wrapper->pcd, usb_ep, req); ++ if (retval) { ++ retval = -EINVAL; ++ } ++ ++ return retval; ++} ++ ++static struct usb_iso_request *alloc_iso_request(struct usb_ep *ep, ++ int packets, gfp_t gfp_flags) ++{ ++ struct usb_iso_request *pReq = NULL; ++ uint32_t req_size; ++ ++ req_size = sizeof(struct usb_iso_request); ++ req_size += ++ (2 * packets * (sizeof(struct usb_gadget_iso_packet_descriptor))); ++ ++ pReq = kmalloc(req_size, gfp_flags); ++ if (!pReq) { ++ DWC_WARN("Can't allocate Iso Request\n"); ++ return 0; ++ } ++ pReq->iso_packet_desc0 = (void *)(pReq + 1); ++ ++ pReq->iso_packet_desc1 = pReq->iso_packet_desc0 + packets; ++ ++ return pReq; ++} ++ ++static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req) ++{ ++ kfree(req); ++} ++ ++static struct usb_isoc_ep_ops dwc_otg_pcd_ep_ops = { ++ .ep_ops = { ++ .enable = ep_enable, ++ .disable = ep_disable, ++ ++ .alloc_request = dwc_otg_pcd_alloc_request, ++ .free_request = dwc_otg_pcd_free_request, ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ .alloc_buffer = dwc_otg_pcd_alloc_buffer, ++ .free_buffer = dwc_otg_pcd_free_buffer, ++#endif ++ ++ .queue = ep_queue, ++ .dequeue = ep_dequeue, ++ ++ .set_halt = ep_halt, ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) ++ .set_wedge = ep_wedge, ++ #endif ++ .fifo_status = 0, ++ .fifo_flush = 0, ++ }, ++ ++ .iso_ep_start = iso_ep_start, ++ .iso_ep_stop = iso_ep_stop, ++ .alloc_iso_request = alloc_iso_request, ++ .free_iso_request = free_iso_request, ++}; ++ ++#else ++ ++static struct usb_ep_ops dwc_otg_pcd_ep_ops = { ++ .enable = ep_enable, ++ .disable = ep_disable, ++ ++ .alloc_request = dwc_otg_pcd_alloc_request, ++ .free_request = dwc_otg_pcd_free_request, ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ .alloc_buffer = dwc_otg_pcd_alloc_buffer, ++ .free_buffer = dwc_otg_pcd_free_buffer, ++#endif ++ ++ .queue = ep_queue, ++ .dequeue = ep_dequeue, ++ ++ .set_halt = ep_halt, ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) ++ .set_wedge = ep_wedge, ++ #endif ++ ++ .fifo_status = 0, ++ .fifo_flush = 0, ++ ++}; ++ ++#endif /* _EN_ISOC_ */ ++/* Gadget Operations */ ++/** ++ * The following gadget operations will be implemented in the DWC_otg ++ * PCD. Functions in the API that are not described below are not ++ * implemented. ++ * ++ * The Gadget API provides wrapper functions for each of the function ++ * pointers defined in usb_gadget_ops. The Gadget Driver calls the ++ * wrapper function, which then calls the underlying PCD function. The ++ * following sections are named according to the wrapper functions ++ * (except for ioctl, which doesn't have a wrapper function). Within ++ * each section, the corresponding DWC_otg PCD function name is ++ * specified. ++ * ++ */ ++ ++/** ++ *Gets the USB Frame number of the last SOF. ++ */ ++static int get_frame_number(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget); ++ ++ if (gadget == 0) { ++ return -ENODEV; ++ } ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ return dwc_otg_pcd_get_frame_number(d->pcd); ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++static int test_lpm_enabled(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ ++ return dwc_otg_pcd_is_lpm_enabled(d->pcd); ++} ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) ++static int test_besl_enabled(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ ++ return dwc_otg_pcd_is_besl_enabled(d->pcd); ++} ++static int get_param_baseline_besl(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ ++ return dwc_otg_pcd_get_param_baseline_besl(d->pcd); ++} ++static int get_param_deep_besl(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ ++ return dwc_otg_pcd_get_param_deep_besl(d->pcd); ++} ++#endif ++#endif ++ ++/** ++ * Initiates Session Request Protocol (SRP) to wakeup the host if no ++ * session is in progress. If a session is already in progress, but ++ * the device is suspended, remote wakeup signaling is started. ++ * ++ */ ++static int wakeup(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget); ++ ++ if (gadget == 0) { ++ return -ENODEV; ++ } else { ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ } ++ dwc_otg_pcd_wakeup(d->pcd); ++ return 0; ++} ++ ++static int pullup(struct usb_gadget *gadget, int is_on) ++{ ++ struct gadget_wrapper *d; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget); ++ ++ if (gadget == 0) { ++ return -ENODEV; ++ } else { ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ } ++ ++ if (!is_on) ++ dwc_otg_pcd_pullup(d->pcd); ++ ++ return 0; ++} ++ ++static const struct usb_gadget_ops dwc_otg_pcd_ops = { ++ .get_frame = get_frame_number, ++ .wakeup = wakeup, ++ .pullup = pullup, ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ .lpm_support = test_lpm_enabled, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) ++ .besl_support = test_besl_enabled, ++ .get_baseline_besl = get_param_baseline_besl, ++ .get_deep_besl = get_param_deep_besl, ++#endif ++#endif ++ // current versions must always be self-powered ++}; ++ ++static int _setup(dwc_otg_pcd_t * pcd, uint8_t * bytes) ++{ ++ int retval = -DWC_E_NOT_SUPPORTED; ++ if (gadget_wrapper->driver && gadget_wrapper->driver->setup) { ++ retval = gadget_wrapper->driver->setup(&gadget_wrapper->gadget, ++ (struct usb_ctrlrequest ++ *)bytes); ++ } ++ ++ if (retval == -ENOTSUPP) { ++ retval = -DWC_E_NOT_SUPPORTED; ++ } else if (retval < 0) { ++ retval = -DWC_E_INVALID; ++ } ++ ++ return retval; ++} ++ ++#ifdef DWC_EN_ISOC ++static int _isoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int proc_buf_num) ++{ ++ int i, packet_count; ++ struct usb_gadget_iso_packet_descriptor *iso_packet = 0; ++ struct usb_iso_request *iso_req = req_handle; ++ ++ if (proc_buf_num) { ++ iso_packet = iso_req->iso_packet_desc1; ++ } else { ++ iso_packet = iso_req->iso_packet_desc0; ++ } ++ packet_count = ++ dwc_otg_pcd_get_iso_packet_count(pcd, ep_handle, req_handle); ++ for (i = 0; i < packet_count; ++i) { ++ int status; ++ int actual; ++ int offset; ++ dwc_otg_pcd_get_iso_packet_params(pcd, ep_handle, req_handle, ++ i, &status, &actual, &offset); ++ switch (status) { ++ case -DWC_E_NO_DATA: ++ status = -ENODATA; ++ break; ++ default: ++ if (status) { ++ DWC_PRINTF("unknown status in isoc packet\n"); ++ } ++ ++ } ++ iso_packet[i].status = status; ++ iso_packet[i].offset = offset; ++ iso_packet[i].actual_length = actual; ++ } ++ ++ iso_req->status = 0; ++ iso_req->process_buffer(ep_handle, iso_req); ++ ++ return 0; ++} ++#endif /* DWC_EN_ISOC */ ++ ++#ifdef DWC_UTE_PER_IO ++/** ++ * Copy the contents of the extended request to the Linux usb_request's ++ * extended part and call the gadget's completion. ++ * ++ * @param pcd Pointer to the pcd structure ++ * @param ep_handle Void pointer to the usb_ep structure ++ * @param req_handle Void pointer to the usb_request structure ++ * @param status Request status returned from the portable logic ++ * @param ereq_port Void pointer to the extended request structure ++ * created in the the portable part that contains the ++ * results of the processed iso packets. ++ */ ++static int _xisoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int32_t status, void *ereq_port) ++{ ++ struct dwc_ute_iso_req_ext *ereqorg = NULL; ++ struct dwc_iso_xreq_port *ereqport = NULL; ++ struct dwc_ute_iso_packet_descriptor *desc_org = NULL; ++ int i; ++ struct usb_request *req; ++ //struct dwc_ute_iso_packet_descriptor * ++ //int status = 0; ++ ++ req = (struct usb_request *)req_handle; ++ ereqorg = &req->ext_req; ++ ereqport = (struct dwc_iso_xreq_port *)ereq_port; ++ desc_org = ereqorg->per_io_frame_descs; ++ ++ if (req && req->complete) { ++ /* Copy the request data from the portable logic to our request */ ++ for (i = 0; i < ereqport->pio_pkt_count; i++) { ++ desc_org[i].actual_length = ++ ereqport->per_io_frame_descs[i].actual_length; ++ desc_org[i].status = ++ ereqport->per_io_frame_descs[i].status; ++ } ++ ++ switch (status) { ++ case -DWC_E_SHUTDOWN: ++ req->status = -ESHUTDOWN; ++ break; ++ case -DWC_E_RESTART: ++ req->status = -ECONNRESET; ++ break; ++ case -DWC_E_INVALID: ++ req->status = -EINVAL; ++ break; ++ case -DWC_E_TIMEOUT: ++ req->status = -ETIMEDOUT; ++ break; ++ default: ++ req->status = status; ++ } ++ ++ /* And call the gadget's completion */ ++ req->complete(ep_handle, req); ++ } ++ ++ return 0; ++} ++#endif /* DWC_UTE_PER_IO */ ++static int _complete(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int32_t status, uint32_t actual) ++{ ++ struct usb_request *req = (struct usb_request *)req_handle; ++ struct dwc_otg_pcd_ep *ep = NULL; ++ ++ ep = ep_from_handle(pcd, ep_handle); ++ if (!ep) ++ return -EINVAL; ++ ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ if (req->dma) ++ usb_gadget_unmap_req(&gadget_wrapper->gadget, ++ req, ep); ++ req->dma = (dma_addr_t)0; ++ } ++ ++ if (req && req->complete) { ++ switch (status) { ++ case -DWC_E_SHUTDOWN: ++ req->status = -ESHUTDOWN; ++ break; ++ case -DWC_E_RESTART: ++ req->status = -ECONNRESET; ++ break; ++ case -DWC_E_INVALID: ++ req->status = -EINVAL; ++ break; ++ case -DWC_E_TIMEOUT: ++ req->status = -ETIMEDOUT; ++ break; ++ default: ++ req->status = status; ++ ++ } ++ ++ req->actual = actual; ++ DWC_SPINUNLOCK(pcd->lock); ++ req->complete(ep_handle, req); ++ DWC_SPINLOCK(pcd->lock); ++ } ++#ifdef PCI_INTERFACE ++ dev = gadget_wrapper->pcd->otg_dev->os_dep.pcidev; ++ ep = ep_from_handle(pcd, ep_handle); ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ if (req->length != 0) ++ pci_unmap_single(dev, req->dma, req->length, ++ ep->dwc_ep.is_in ? PCI_DMA_TODEVICE : ++ PCI_DMA_FROMDEVICE); ++ } ++#endif ++ ++ return 0; ++} ++ ++static int _connect(dwc_otg_pcd_t * pcd, int speed) ++{ ++ gadget_wrapper->gadget.speed = speed; ++ return 0; ++} ++ ++static int _disconnect(dwc_otg_pcd_t * pcd) ++{ ++ if (gadget_wrapper->driver && gadget_wrapper->driver->disconnect) { ++ gadget_wrapper->driver->disconnect(&gadget_wrapper->gadget); ++ } ++ return 0; ++} ++ ++static int _resume(dwc_otg_pcd_t * pcd) ++{ ++ if (gadget_wrapper->driver && gadget_wrapper->driver->resume) { ++ gadget_wrapper->driver->resume(&gadget_wrapper->gadget); ++ } ++ ++ return 0; ++} ++ ++static int _suspend(dwc_otg_pcd_t * pcd) ++{ ++ if (gadget_wrapper->driver && gadget_wrapper->driver->suspend) { ++ gadget_wrapper->driver->suspend(&gadget_wrapper->gadget); ++ } ++ return 0; ++} ++ ++/** ++ * This function updates the otg values in the gadget structure. ++ */ ++static int _hnp_changed(dwc_otg_pcd_t * pcd) ++{ ++ ++ if (!gadget_wrapper->gadget.is_otg) ++ return 0; ++ ++ gadget_wrapper->gadget.b_hnp_enable = get_b_hnp_enable(pcd); ++ gadget_wrapper->gadget.a_hnp_support = get_a_hnp_support(pcd); ++ gadget_wrapper->gadget.a_alt_hnp_support = get_a_alt_hnp_support(pcd); ++ return 0; ++} ++ ++static int _reset(dwc_otg_pcd_t * pcd) ++{ ++ return 0; ++} ++ ++#ifdef DWC_UTE_CFI ++static int _cfi_setup(dwc_otg_pcd_t * pcd, void *cfi_req) ++{ ++ int retval = -DWC_E_INVALID; ++ if (gadget_wrapper->driver->cfi_feature_setup) { ++ retval = ++ gadget_wrapper->driver-> ++ cfi_feature_setup(&gadget_wrapper->gadget, ++ (struct cfi_usb_ctrlrequest *)cfi_req); ++ } ++ ++ return retval; ++} ++#endif ++ ++static const struct dwc_otg_pcd_function_ops fops = { ++ .complete = _complete, ++#ifdef DWC_EN_ISOC ++ .isoc_complete = _isoc_complete, ++#endif ++ .setup = _setup, ++ .disconnect = _disconnect, ++ .connect = _connect, ++ .resume = _resume, ++ .suspend = _suspend, ++ .hnp_changed = _hnp_changed, ++ .reset = _reset, ++#ifdef DWC_UTE_CFI ++ .cfi_setup = _cfi_setup, ++#endif ++#ifdef DWC_UTE_PER_IO ++ .xisoc_complete = _xisoc_complete, ++#endif ++}; ++ ++/** ++ * This function is the top level PCD interrupt handler. ++ */ ++static irqreturn_t dwc_otg_pcd_irq(int irq, void *dev) ++{ ++ dwc_otg_pcd_t *pcd = dev; ++ int32_t retval = IRQ_NONE; ++ ++ retval = dwc_otg_pcd_handle_intr(pcd); ++ if (retval != 0) { ++ S3C2410X_CLEAR_EINTPEND(); ++ } ++ return IRQ_RETVAL(retval); ++} ++ ++/** ++ * This function initialized the usb_ep structures to there default ++ * state. ++ * ++ * @param d Pointer on gadget_wrapper. ++ */ ++void gadget_add_eps(struct gadget_wrapper *d) ++{ ++ static const char *names[] = { ++ ++ "ep0", ++ "ep1in", ++ "ep2in", ++ "ep3in", ++ "ep4in", ++ "ep5in", ++ "ep6in", ++ "ep7in", ++ "ep8in", ++ "ep9in", ++ "ep10in", ++ "ep11in", ++ "ep12in", ++ "ep13in", ++ "ep14in", ++ "ep15in", ++ "ep1out", ++ "ep2out", ++ "ep3out", ++ "ep4out", ++ "ep5out", ++ "ep6out", ++ "ep7out", ++ "ep8out", ++ "ep9out", ++ "ep10out", ++ "ep11out", ++ "ep12out", ++ "ep13out", ++ "ep14out", ++ "ep15out" ++ }; ++ ++ int i; ++ struct usb_ep *ep; ++ int8_t dev_endpoints; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__); ++ ++ INIT_LIST_HEAD(&d->gadget.ep_list); ++ d->gadget.ep0 = &d->ep0; ++ d->gadget.speed = USB_SPEED_UNKNOWN; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) ++ d->gadget.max_speed = USB_SPEED_HIGH; ++#endif ++ ++ INIT_LIST_HEAD(&d->gadget.ep0->ep_list); ++ ++ /** ++ * Initialize the EP0 structure. ++ */ ++ ep = &d->ep0; ++ ++ /* Init the usb_ep structure. */ ++ ep->name = names[0]; ++ ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; ++ ++ /** ++ * @todo NGS: What should the max packet size be set to ++ * here? Before EP type is set? ++ */ ++ ep->maxpacket = MAX_PACKET_SIZE; ++ dwc_otg_pcd_ep_enable(d->pcd, NULL, ep); ++ ++ list_add_tail(&ep->ep_list, &d->gadget.ep_list); ++ ++ /** ++ * Initialize the EP structures. ++ */ ++ dev_endpoints = d->pcd->core_if->dev_if->num_in_eps; ++ ++ for (i = 0; i < dev_endpoints; i++) { ++ ep = &d->in_ep[i]; ++ ++ /* Init the usb_ep structure. */ ++ ep->name = names[d->pcd->in_ep[i].dwc_ep.num]; ++ ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; ++ ++ /** ++ * @todo NGS: What should the max packet size be set to ++ * here? Before EP type is set? ++ */ ++ ep->maxpacket = MAX_PACKET_SIZE; ++ ep->maxpacket_limit = MAX_PACKET_SIZE; ++ list_add_tail(&ep->ep_list, &d->gadget.ep_list); ++ } ++ ++ dev_endpoints = d->pcd->core_if->dev_if->num_out_eps; ++ ++ for (i = 0; i < dev_endpoints; i++) { ++ ep = &d->out_ep[i]; ++ ++ /* Init the usb_ep structure. */ ++ ep->name = names[15 + d->pcd->out_ep[i].dwc_ep.num]; ++ ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; ++ ++ /** ++ * @todo NGS: What should the max packet size be set to ++ * here? Before EP type is set? ++ */ ++ ep->maxpacket = MAX_PACKET_SIZE; ++ ep->maxpacket_limit = MAX_PACKET_SIZE; ++ ++ list_add_tail(&ep->ep_list, &d->gadget.ep_list); ++ } ++ ++ /* remove ep0 from the list. There is a ep0 pointer. */ ++ list_del_init(&d->ep0.ep_list); ++ ++ d->ep0.maxpacket = MAX_EP0_SIZE; ++} ++ ++/** ++ * This function releases the Gadget device. ++ * required by device_unregister(). ++ * ++ * @todo Should this do something? Should it free the PCD? ++ */ ++static void dwc_otg_pcd_gadget_release(struct device *dev) ++{ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev); ++} ++ ++static struct gadget_wrapper *alloc_wrapper( ++ struct platform_device *_dev ++ ) ++{ ++ static char pcd_name[] = "dwc_otg_pcd"; ++ ++ dwc_otg_device_t *otg_dev =platform_get_drvdata(_dev); ++ ++ ++ struct gadget_wrapper *d; ++ int retval; ++ ++ d = DWC_ALLOC(sizeof(*d)); ++ if (d == NULL) { ++ return NULL; ++ } ++ ++ memset(d, 0, sizeof(*d)); ++ ++ d->gadget.name = pcd_name; ++ d->pcd = otg_dev->pcd; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ++ strcpy(d->gadget.dev.bus_id, "gadget"); ++#else ++ dev_set_name(&d->gadget.dev, "%s", "gadget"); ++#endif ++ ++ d->gadget.dev.parent = &_dev->dev; ++ d->gadget.dev.release = dwc_otg_pcd_gadget_release; ++ d->gadget.ops = &dwc_otg_pcd_ops; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) ++ d->gadget.is_dualspeed = dwc_otg_pcd_is_dualspeed(otg_dev->pcd); ++#endif ++ d->gadget.is_otg = dwc_otg_pcd_is_otg(otg_dev->pcd); ++ ++ d->driver = 0; ++ /* Register the gadget device */ ++ retval = device_register(&d->gadget.dev); ++ if (retval != 0) { ++ DWC_ERROR("device_register failed\n"); ++ DWC_FREE(d); ++ return NULL; ++ } ++ ++ return d; ++} ++ ++static void free_wrapper(struct gadget_wrapper *d) ++{ ++ if (d->driver) { ++ /* should have been done already by driver model core */ ++ DWC_WARN("driver '%s' is still registered\n", ++ d->driver->driver.name); ++ usb_gadget_unregister_driver(d->driver); ++ } ++ ++ device_unregister(&d->gadget.dev); ++ DWC_FREE(d); ++} ++ ++/** ++ * This function initialized the PCD portion of the driver. ++ * ++ */ ++int pcd_init(struct platform_device *_dev, int irqnum ) ++{ ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); ++ ++ int retval = 0; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _dev); ++ ++ otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if); ++ ++ if (!otg_dev->pcd) { ++ DWC_ERROR("dwc_otg_pcd_init failed\n"); ++ return -ENOMEM; ++ } ++ ++ otg_dev->pcd->otg_dev = otg_dev; ++ gadget_wrapper = alloc_wrapper(_dev); ++ ++ /* ++ * Initialize EP structures ++ */ ++ gadget_add_eps(gadget_wrapper); ++ /* ++ * Setup interupt handler ++ */ ++ DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n", irqnum); ++ retval = request_irq(irqnum, dwc_otg_pcd_irq, ++ IRQF_SHARED | IRQF_DISABLED, ++ gadget_wrapper->gadget.name, otg_dev->pcd); ++ if (retval != 0) { ++ DWC_ERROR("request of irq%d failed\n", irqnum); ++ free_wrapper(gadget_wrapper); ++ return -EBUSY; ++ } ++ ++ ++ dwc_otg_pcd_start(gadget_wrapper->pcd, &fops); ++ ++ return retval; ++} ++ ++/** ++ * Cleanup the PCD. ++ */ ++void pcd_remove( struct platform_device *_dev ) ++{ ++ ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); ++ ++ dwc_otg_pcd_t *pcd = otg_dev->pcd; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _dev); ++ ++ /* ++ * Free the IRQ ++ */ ++ free_irq(_dev->resource[1].start, pcd); ++ free_wrapper(gadget_wrapper); ++ dwc_otg_pcd_remove(otg_dev->pcd); ++ otg_dev->pcd = 0; ++} ++ ++/** ++ * This function registers a gadget driver with the PCD. ++ * ++ * When a driver is successfully registered, it will receive control ++ * requests including set_configuration(), which enables non-control ++ * requests. then usb traffic follows until a disconnect is reported. ++ * then a host may connect again, or the driver might get unbound. ++ * ++ * @param driver The driver being registered ++ * @param bind The bind function of gadget driver ++ */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) ++int usb_gadget_register_driver(struct usb_gadget_driver *driver) ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ int usb_gadget_probe_driver(struct usb_gadget_driver *driver) ++#else ++int usb_gadget_probe_driver(struct usb_gadget_driver *driver, ++ int (*bind)(struct usb_gadget *)) ++#endif ++{ ++ int retval; ++ ++ DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n", ++ driver->driver.name); ++ ++ if (!driver || ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) ++ driver->speed == USB_SPEED_UNKNOWN || ++#else ++ driver->max_speed == USB_SPEED_UNKNOWN || ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ !driver->bind || ++#else ++ !bind || ++#endif ++ !driver->unbind || !driver->disconnect || !driver->setup) { ++ DWC_DEBUGPL(DBG_PCDV, "EINVAL\n"); ++ return -EINVAL; ++ } ++ if (gadget_wrapper == 0) { ++ DWC_DEBUGPL(DBG_PCDV, "ENODEV\n"); ++ return -ENODEV; ++ } ++ if (gadget_wrapper->driver != 0) { ++ DWC_DEBUGPL(DBG_PCDV, "EBUSY (%p)\n", gadget_wrapper->driver); ++ return -EBUSY; ++ } ++ ++ /* hook up the driver */ ++ gadget_wrapper->driver = driver; ++ gadget_wrapper->gadget.dev.driver = &driver->driver; ++ ++ DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) ++ retval = driver->bind(&gadget_wrapper->gadget); ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ retval = driver->bind(&gadget_wrapper->gadget,gadget_wrapper->driver); ++#else ++ retval = bind(&gadget_wrapper->gadget); ++#endif ++ if (retval) { ++ DWC_ERROR("bind to driver %s --> error %d\n", ++ driver->driver.name, retval); ++ gadget_wrapper->driver = 0; ++ gadget_wrapper->gadget.dev.driver = 0; ++ return retval; ++ } ++ DWC_DEBUGPL(DBG_ANY, "registered gadget driver '%s'\n", ++ driver->driver.name); ++ return 0; ++} ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) ++EXPORT_SYMBOL(usb_gadget_register_driver); ++#else ++EXPORT_SYMBOL(usb_gadget_probe_driver); ++#endif ++ ++/** ++ * This function unregisters a gadget driver ++ * ++ * @param driver The driver being unregistered ++ */ ++int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) ++{ ++ //DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _driver); ++ ++ if (gadget_wrapper == 0) { ++ DWC_DEBUGPL(DBG_ANY, "%s Return(%d): s_pcd==0\n", __func__, ++ -ENODEV); ++ return -ENODEV; ++ } ++ if (driver == 0 || driver != gadget_wrapper->driver) { ++ DWC_DEBUGPL(DBG_ANY, "%s Return(%d): driver?\n", __func__, ++ -EINVAL); ++ return -EINVAL; ++ } ++ ++ driver->disconnect(&gadget_wrapper->gadget); ++ driver->unbind(&gadget_wrapper->gadget); ++ gadget_wrapper->driver = 0; ++ ++ DWC_DEBUGPL(DBG_ANY, "unregistered driver '%s'\n", driver->driver.name); ++ return 0; ++} ++ ++EXPORT_SYMBOL(usb_gadget_unregister_driver); ++ ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/gadget/udc/hiudc/dwc_otg_regs.h b/drivers/usb/gadget/udc/hiudc/dwc_otg_regs.h +new file mode 100644 +index 0000000..782976b +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/dwc_otg_regs.h +@@ -0,0 +1,2557 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $ ++ * $Revision: #99 $ ++ * $Date: 2012/12/10 $ ++ * $Change: 2123206 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 __DWC_OTG_REGS_H__ ++#define __DWC_OTG_REGS_H__ ++ ++#include "dwc_otg_core_if.h" ++ ++/** ++ * @file ++ * ++ * This file contains the data structures for accessing the DWC_otg core registers. ++ * ++ * The application interfaces with the HS OTG core by reading from and ++ * writing to the Control and Status Register (CSR) space through the ++ * AHB Slave interface. These registers are 32 bits wide, and the ++ * addresses are 32-bit-block aligned. ++ * CSRs are classified as follows: ++ * - Core Global Registers ++ * - Device Mode Registers ++ * - Device Global Registers ++ * - Device Endpoint Specific Registers ++ * - Host Mode Registers ++ * - Host Global Registers ++ * - Host Port CSRs ++ * - Host Channel Specific Registers ++ * ++ * Only the Core Global registers can be accessed in both Device and ++ * Host modes. When the HS OTG core is operating in one mode, either ++ * Device or Host, the application must not access registers from the ++ * other mode. When the core switches from one mode to another, the ++ * registers in the new mode of operation must be reprogrammed as they ++ * would be after a power-on reset. ++ */ ++ ++/****************************************************************************/ ++/** DWC_otg Core registers . ++ * The dwc_otg_core_global_regs structure defines the size ++ * and relative field offsets for the Core Global registers. ++ */ ++typedef struct dwc_otg_core_global_regs { ++ /** OTG Control and Status Register. Offset: 000h */ ++ volatile uint32_t gotgctl; ++ /** OTG Interrupt Register. Offset: 004h */ ++ volatile uint32_t gotgint; ++ /**Core AHB Configuration Register. Offset: 008h */ ++ volatile uint32_t gahbcfg; ++ ++#define DWC_GLBINTRMASK 0x0001 ++#define DWC_DMAENABLE 0x0020 ++#define DWC_NPTXEMPTYLVL_EMPTY 0x0080 ++#define DWC_NPTXEMPTYLVL_HALFEMPTY 0x0000 ++#define DWC_PTXEMPTYLVL_EMPTY 0x0100 ++#define DWC_PTXEMPTYLVL_HALFEMPTY 0x0000 ++ ++ /**Core USB Configuration Register. Offset: 00Ch */ ++ volatile uint32_t gusbcfg; ++ /**Core Reset Register. Offset: 010h */ ++ volatile uint32_t grstctl; ++ /**Core Interrupt Register. Offset: 014h */ ++ volatile uint32_t gintsts; ++ /**Core Interrupt Mask Register. Offset: 018h */ ++ volatile uint32_t gintmsk; ++ /**Receive Status Queue Read Register (Read Only). Offset: 01Ch */ ++ volatile uint32_t grxstsr; ++ /**Receive Status Queue Read & POP Register (Read Only). Offset: 020h*/ ++ volatile uint32_t grxstsp; ++ /**Receive FIFO Size Register. Offset: 024h */ ++ volatile uint32_t grxfsiz; ++ /**Non Periodic Transmit FIFO Size Register. Offset: 028h */ ++ volatile uint32_t gnptxfsiz; ++ /**Non Periodic Transmit FIFO/Queue Status Register (Read ++ * Only). Offset: 02Ch */ ++ volatile uint32_t gnptxsts; ++ /**I2C Access Register. Offset: 030h */ ++ volatile uint32_t gi2cctl; ++ /**PHY Vendor Control Register. Offset: 034h */ ++ volatile uint32_t gpvndctl; ++ /**General Purpose Input/Output Register. Offset: 038h */ ++ volatile uint32_t ggpio; ++ /**User ID Register. Offset: 03Ch */ ++ volatile uint32_t guid; ++ /**Synopsys ID Register (Read Only). Offset: 040h */ ++ volatile uint32_t gsnpsid; ++ /**User HW Config1 Register (Read Only). Offset: 044h */ ++ volatile uint32_t ghwcfg1; ++ /**User HW Config2 Register (Read Only). Offset: 048h */ ++ volatile uint32_t ghwcfg2; ++#define DWC_SLAVE_ONLY_ARCH 0 ++#define DWC_EXT_DMA_ARCH 1 ++#define DWC_INT_DMA_ARCH 2 ++ ++#define DWC_MODE_HNP_SRP_CAPABLE 0 ++#define DWC_MODE_SRP_ONLY_CAPABLE 1 ++#define DWC_MODE_NO_HNP_SRP_CAPABLE 2 ++#define DWC_MODE_SRP_CAPABLE_DEVICE 3 ++#define DWC_MODE_NO_SRP_CAPABLE_DEVICE 4 ++#define DWC_MODE_SRP_CAPABLE_HOST 5 ++#define DWC_MODE_NO_SRP_CAPABLE_HOST 6 ++ ++ /**User HW Config3 Register (Read Only). Offset: 04Ch */ ++ volatile uint32_t ghwcfg3; ++ /**User HW Config4 Register (Read Only). Offset: 050h*/ ++ volatile uint32_t ghwcfg4; ++ /** Core LPM Configuration register Offset: 054h*/ ++ volatile uint32_t glpmcfg; ++ /** Global PowerDn Register Offset: 058h */ ++ volatile uint32_t gpwrdn; ++ /** Global DFIFO SW Config Register Offset: 05Ch */ ++ volatile uint32_t gdfifocfg; ++ /** ADP Control Register Offset: 060h */ ++ volatile uint32_t adpctl; ++ /** Reserved Offset: 064h-0FFh */ ++ volatile uint32_t reserved39[39]; ++ /** Host Periodic Transmit FIFO Size Register. Offset: 100h */ ++ volatile uint32_t hptxfsiz; ++ /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled, ++ otherwise Device Transmit FIFO#n Register. ++ * Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15). */ ++ volatile uint32_t dtxfsiz[MAX_EPS_CHANNELS]; ++} dwc_otg_core_global_regs_t; ++ ++/** ++ * This union represents the bit fields of the Core OTG Control ++ * and Status Register (GOTGCTL). Set the bits using the bit ++ * fields then write the d32 value to the register. ++ */ ++typedef union gotgctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned sesreqscs:1; ++ unsigned sesreq:1; ++ unsigned vbvalidoven:1; ++ unsigned vbvalidovval:1; ++ unsigned avalidoven:1; ++ unsigned avalidovval:1; ++ unsigned bvalidoven:1; ++ unsigned bvalidovval:1; ++ unsigned hstnegscs:1; ++ unsigned hnpreq:1; ++ unsigned hstsethnpen:1; ++ unsigned devhnpen:1; ++ unsigned reserved12_15:4; ++ unsigned conidsts:1; ++ unsigned dbnctime:1; ++ unsigned asesvld:1; ++ unsigned bsesvld:1; ++ unsigned otgver:1; ++ unsigned reserved1:1; ++ unsigned multvalidbc:5; ++ unsigned chirpen:1; ++ unsigned reserved28_31:4; ++ } b; ++} gotgctl_data_t; ++ ++/** ++ * This union represents the bit fields of the Core OTG Interrupt Register ++ * (GOTGINT). Set/clear the bits using the bit fields then write the d32 ++ * value to the register. ++ */ ++typedef union gotgint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Current Mode */ ++ unsigned reserved0_1:2; ++ ++ /** Session End Detected */ ++ unsigned sesenddet:1; ++ ++ unsigned reserved3_7:5; ++ ++ /** Session Request Success Status Change */ ++ unsigned sesreqsucstschng:1; ++ /** Host Negotiation Success Status Change */ ++ unsigned hstnegsucstschng:1; ++ ++ unsigned reserved10_16:7; ++ ++ /** Host Negotiation Detected */ ++ unsigned hstnegdet:1; ++ /** A-Device Timeout Change */ ++ unsigned adevtoutchng:1; ++ /** Debounce Done */ ++ unsigned debdone:1; ++ /** Multi-Valued input changed */ ++ unsigned mvic:1; ++ ++ unsigned reserved31_21:11; ++ ++ } b; ++} gotgint_data_t; ++ ++/** ++ * This union represents the bit fields of the Core AHB Configuration ++ * Register (GAHBCFG). Set/clear the bits using the bit fields then ++ * write the d32 value to the register. ++ */ ++typedef union gahbcfg_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned glblintrmsk:1; ++#define DWC_GAHBCFG_GLBINT_ENABLE 1 ++ ++ unsigned hburstlen:4; ++#define DWC_GAHBCFG_INT_DMA_BURST_SINGLE 0 ++#define DWC_GAHBCFG_INT_DMA_BURST_INCR 1 ++#define DWC_GAHBCFG_INT_DMA_BURST_INCR4 3 ++#define DWC_GAHBCFG_INT_DMA_BURST_INCR8 5 ++#define DWC_GAHBCFG_INT_DMA_BURST_INCR16 7 ++ ++ unsigned dmaenable:1; ++#define DWC_GAHBCFG_DMAENABLE 1 ++ unsigned reserved:1; ++ unsigned nptxfemplvl_txfemplvl:1; ++ unsigned ptxfemplvl:1; ++#define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY 1 ++#define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0 ++ unsigned reserved9_20:12; ++ unsigned remmemsupp:1; ++ unsigned notialldmawrit:1; ++ unsigned ahbsingle:1; ++ unsigned reserved24_31:8; ++ } b; ++} gahbcfg_data_t; ++ ++/** ++ * This union represents the bit fields of the Core USB Configuration ++ * Register (GUSBCFG). Set the bits using the bit fields then write ++ * the d32 value to the register. ++ */ ++typedef union gusbcfg_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned toutcal:3; ++ unsigned phyif:1; ++ unsigned ulpi_utmi_sel:1; ++ unsigned fsintf:1; ++ unsigned physel:1; ++ unsigned ddrsel:1; ++ unsigned srpcap:1; ++ unsigned hnpcap:1; ++ unsigned usbtrdtim:4; ++ unsigned reserved1:1; ++ unsigned phylpwrclksel:1; ++ unsigned otgutmifssel:1; ++ unsigned ulpi_fsls:1; ++ unsigned ulpi_auto_res:1; ++ unsigned ulpi_clk_sus_m:1; ++ unsigned ulpi_ext_vbus_drv:1; ++ unsigned ulpi_int_vbus_indicator:1; ++ unsigned term_sel_dl_pulse:1; ++ unsigned indicator_complement:1; ++ unsigned indicator_pass_through:1; ++ unsigned ulpi_int_prot_dis:1; ++ unsigned ic_usb_cap:1; ++ unsigned ic_traffic_pull_remove:1; ++ unsigned tx_end_delay:1; ++ unsigned force_host_mode:1; ++ unsigned force_dev_mode:1; ++ unsigned reserved31:1; ++ } b; ++} gusbcfg_data_t; ++ ++/** ++ * This union represents the bit fields of the Core Reset Register ++ * (GRSTCTL). Set/clear the bits using the bit fields then write the ++ * d32 value to the register. ++ */ ++typedef union grstctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Core Soft Reset (CSftRst) (Device and Host) ++ * ++ * The application can flush the control logic in the ++ * entire core using this bit. This bit resets the ++ * pipelines in the AHB Clock domain as well as the ++ * PHY Clock domain. ++ * ++ * The state machines are reset to an IDLE state, the ++ * control bits in the CSRs are cleared, all the ++ * transmit FIFOs and the receive FIFO are flushed. ++ * ++ * The status mask bits that control the generation of ++ * the interrupt, are cleared, to clear the ++ * interrupt. The interrupt status bits are not ++ * cleared, so the application can get the status of ++ * any events that occurred in the core after it has ++ * set this bit. ++ * ++ * Any transactions on the AHB are terminated as soon ++ * as possible following the protocol. Any ++ * transactions on the USB are terminated immediately. ++ * ++ * The configuration settings in the CSRs are ++ * unchanged, so the software doesn't have to ++ * reprogram these registers (Device ++ * Configuration/Host Configuration/Core System ++ * Configuration/Core PHY Configuration). ++ * ++ * The application can write to this bit, any time it ++ * wants to reset the core. This is a self clearing ++ * bit and the core clears this bit after all the ++ * necessary logic is reset in the core, which may ++ * take several clocks, depending on the current state ++ * of the core. ++ */ ++ unsigned csftrst:1; ++ /** Hclk Soft Reset ++ * ++ * The application uses this bit to reset the control logic in ++ * the AHB clock domain. Only AHB clock domain pipelines are ++ * reset. ++ */ ++ unsigned hsftrst:1; ++ /** Host Frame Counter Reset (Host Only)
++ * ++ * The application can reset the (micro)frame number ++ * counter inside the core, using this bit. When the ++ * (micro)frame counter is reset, the subsequent SOF ++ * sent out by the core, will have a (micro)frame ++ * number of 0. ++ */ ++ unsigned hstfrm:1; ++ /** In Token Sequence Learning Queue Flush ++ * (INTknQFlsh) (Device Only) ++ */ ++ unsigned intknqflsh:1; ++ /** RxFIFO Flush (RxFFlsh) (Device and Host) ++ * ++ * The application can flush the entire Receive FIFO ++ * using this bit. The application must first ++ * ensure that the core is not in the middle of a ++ * transaction. The application should write into ++ * this bit, only after making sure that neither the ++ * DMA engine is reading from the RxFIFO nor the MAC ++ * is writing the data in to the FIFO. The ++ * application should wait until the bit is cleared ++ * before performing any other operations. This bit ++ * will takes 8 clocks (slowest of PHY or AHB clock) ++ * to clear. ++ */ ++ unsigned rxfflsh:1; ++ /** TxFIFO Flush (TxFFlsh) (Device and Host). ++ * ++ * This bit is used to selectively flush a single or ++ * all transmit FIFOs. The application must first ++ * ensure that the core is not in the middle of a ++ * transaction. The application should write into ++ * this bit, only after making sure that neither the ++ * DMA engine is writing into the TxFIFO nor the MAC ++ * is reading the data out of the FIFO. The ++ * application should wait until the core clears this ++ * bit, before performing any operations. This bit ++ * will takes 8 clocks (slowest of PHY or AHB clock) ++ * to clear. ++ */ ++ unsigned txfflsh:1; ++ ++ /** TxFIFO Number (TxFNum) (Device and Host). ++ * ++ * This is the FIFO number which needs to be flushed, ++ * using the TxFIFO Flush bit. This field should not ++ * be changed until the TxFIFO Flush bit is cleared by ++ * the core. ++ * - 0x0 : Non Periodic TxFIFO Flush ++ * - 0x1 : Periodic TxFIFO #1 Flush in device mode ++ * or Periodic TxFIFO in host mode ++ * - 0x2 : Periodic TxFIFO #2 Flush in device mode. ++ * - ... ++ * - 0xF : Periodic TxFIFO #15 Flush in device mode ++ * - 0x10: Flush all the Transmit NonPeriodic and ++ * Transmit Periodic FIFOs in the core ++ */ ++ unsigned txfnum:5; ++ /** Reserved */ ++ unsigned reserved11_29:19; ++ /** DMA Request Signal. Indicated DMA request is in ++ * probress. Used for debug purpose. */ ++ unsigned dmareq:1; ++ /** AHB Master Idle. Indicates the AHB Master State ++ * Machine is in IDLE condition. */ ++ unsigned ahbidle:1; ++ } b; ++} grstctl_t; ++ ++/** ++ * This union represents the bit fields of the Core Interrupt Mask ++ * Register (GINTMSK). Set/clear the bits using the bit fields then ++ * write the d32 value to the register. ++ */ ++typedef union gintmsk_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned reserved0:1; ++ unsigned modemismatch:1; ++ unsigned otgintr:1; ++ unsigned sofintr:1; ++ unsigned rxstsqlvl:1; ++ unsigned nptxfempty:1; ++ unsigned ginnakeff:1; ++ unsigned goutnakeff:1; ++ unsigned ulpickint:1; ++ unsigned i2cintr:1; ++ unsigned erlysuspend:1; ++ unsigned usbsuspend:1; ++ unsigned usbreset:1; ++ unsigned enumdone:1; ++ unsigned isooutdrop:1; ++ unsigned eopframe:1; ++ unsigned restoredone:1; ++ unsigned epmismatch:1; ++ unsigned inepintr:1; ++ unsigned outepintr:1; ++ unsigned incomplisoin:1; ++ unsigned incomplisoout:1; ++ unsigned fetsusp:1; ++ unsigned resetdet:1; ++ unsigned portintr:1; ++ unsigned hcintr:1; ++ unsigned ptxfempty:1; ++ unsigned lpmtranrcvd:1; ++ unsigned conidstschng:1; ++ unsigned disconnect:1; ++ unsigned sessreqintr:1; ++ unsigned wkupintr:1; ++ } b; ++} gintmsk_data_t; ++/** ++ * This union represents the bit fields of the Core Interrupt Register ++ * (GINTSTS). Set/clear the bits using the bit fields then write the ++ * d32 value to the register. ++ */ ++typedef union gintsts_data { ++ /** raw register data */ ++ uint32_t d32; ++#define DWC_SOF_INTR_MASK 0x0008 ++ /** register bits */ ++ struct { ++#define DWC_HOST_MODE 1 ++ unsigned curmode:1; ++ unsigned modemismatch:1; ++ unsigned otgintr:1; ++ unsigned sofintr:1; ++ unsigned rxstsqlvl:1; ++ unsigned nptxfempty:1; ++ unsigned ginnakeff:1; ++ unsigned goutnakeff:1; ++ unsigned ulpickint:1; ++ unsigned i2cintr:1; ++ unsigned erlysuspend:1; ++ unsigned usbsuspend:1; ++ unsigned usbreset:1; ++ unsigned enumdone:1; ++ unsigned isooutdrop:1; ++ unsigned eopframe:1; ++ unsigned restoredone:1; ++ unsigned epmismatch:1; ++ unsigned inepint:1; ++ unsigned outepintr:1; ++ unsigned incomplisoin:1; ++ unsigned incomplisoout:1; ++ unsigned fetsusp:1; ++ unsigned resetdet:1; ++ unsigned portintr:1; ++ unsigned hcintr:1; ++ unsigned ptxfempty:1; ++ unsigned lpmtranrcvd:1; ++ unsigned conidstschng:1; ++ unsigned disconnect:1; ++ unsigned sessreqintr:1; ++ unsigned wkupintr:1; ++ } b; ++} gintsts_data_t; ++ ++/** ++ * This union represents the bit fields in the Device Receive Status Read and ++ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the d32 ++ * element then read out the bits using the bit elements. ++ */ ++typedef union device_grxsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned epnum:4; ++ unsigned bcnt:11; ++ unsigned dpid:2; ++ ++#define DWC_STS_DATA_UPDT 0x2 // OUT Data Packet ++#define DWC_STS_XFER_COMP 0x3 // OUT Data Transfer Complete ++ ++#define DWC_DSTS_GOUT_NAK 0x1 // Global OUT NAK ++#define DWC_DSTS_SETUP_COMP 0x4 // Setup Phase Complete ++#define DWC_DSTS_SETUP_UPDT 0x6 // SETUP Packet ++ unsigned pktsts:4; ++ unsigned fn:4; ++ unsigned reserved25_31:7; ++ } b; ++} device_grxsts_data_t; ++ ++/** ++ * This union represents the bit fields in the Host Receive Status Read and ++ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the d32 ++ * element then read out the bits using the bit elements. ++ */ ++typedef union host_grxsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned chnum:4; ++ unsigned bcnt:11; ++ unsigned dpid:2; ++ ++ unsigned pktsts:4; ++#define DWC_GRXSTS_PKTSTS_IN 0x2 ++#define DWC_GRXSTS_PKTSTS_IN_XFER_COMP 0x3 ++#define DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5 ++#define DWC_GRXSTS_PKTSTS_CH_HALTED 0x7 ++ ++ unsigned reserved21_31:11; ++ } b; ++} host_grxsts_data_t; ++ ++/** ++ * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ, ++ * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the d32 element ++ * then read out the bits using the bit elements. ++ */ ++typedef union fifosize_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned startaddr:16; ++ unsigned depth:16; ++ } b; ++} fifosize_data_t; ++ ++/** ++ * This union represents the bit fields in the Non-Periodic Transmit ++ * FIFO/Queue Status Register (GNPTXSTS). Read the register into the ++ * d32 element then read out the bits using the bit ++ * elements. ++ */ ++typedef union gnptxsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned nptxfspcavail:16; ++ unsigned nptxqspcavail:8; ++ /** Top of the Non-Periodic Transmit Request Queue ++ * - bit 24 - Terminate (Last entry for the selected ++ * channel/EP) ++ * - bits 26:25 - Token Type ++ * - 2'b00 - IN/OUT ++ * - 2'b01 - Zero Length OUT ++ * - 2'b10 - PING/Complete Split ++ * - 2'b11 - Channel Halt ++ * - bits 30:27 - Channel/EP Number ++ */ ++ unsigned nptxqtop_terminate:1; ++ unsigned nptxqtop_token:2; ++ unsigned nptxqtop_chnep:4; ++ unsigned reserved:1; ++ } b; ++} gnptxsts_data_t; ++ ++/** ++ * This union represents the bit fields in the Transmit ++ * FIFO Status Register (DTXFSTS). Read the register into the ++ * d32 element then read out the bits using the bit ++ * elements. ++ */ ++typedef union dtxfsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned txfspcavail:16; ++ unsigned reserved:16; ++ } b; ++} dtxfsts_data_t; ++ ++/** ++ * This union represents the bit fields in the I2C Control Register ++ * (I2CCTL). Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++typedef union gi2cctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned rwdata:8; ++ unsigned regaddr:8; ++ unsigned addr:7; ++ unsigned i2cen:1; ++ unsigned ack:1; ++ unsigned i2csuspctl:1; ++ unsigned i2cdevaddr:2; ++ unsigned i2cdatse0:1; ++ unsigned reserved:1; ++ unsigned rw:1; ++ unsigned bsydne:1; ++ } b; ++} gi2cctl_data_t; ++ ++/** ++ * This union represents the bit fields in the PHY Vendor Control Register ++ * (GPVNDCTL). Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++typedef union gpvndctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned regdata:8; ++ unsigned vctrl:8; ++ unsigned regaddr16_21:6; ++ unsigned regwr:1; ++ unsigned reserved23_24:2; ++ unsigned newregreq:1; ++ unsigned vstsbsy:1; ++ unsigned vstsdone:1; ++ unsigned reserved28_30:3; ++ unsigned disulpidrvr:1; ++ } b; ++} gpvndctl_data_t; ++ ++/** ++ * This union represents the bit fields in the General Purpose ++ * Input/Output Register (GGPIO). ++ * Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++typedef union ggpio_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned gpi:16; ++ unsigned gpo:16; ++ } b; ++} ggpio_data_t; ++ ++/** ++ * This union represents the bit fields in the User ID Register ++ * (GUID). Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++typedef union guid_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned rwdata:32; ++ } b; ++} guid_data_t; ++ ++/** ++ * This union represents the bit fields in the Synopsys ID Register ++ * (GSNPSID). Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++typedef union gsnpsid_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned rwdata:32; ++ } b; ++} gsnpsid_data_t; ++ ++/** ++ * This union represents the bit fields in the User HW Config1 ++ * Register. Read the register into the d32 element then read ++ * out the bits using the bit elements. ++ */ ++typedef union hwcfg1_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned ep_dir0:2; ++ unsigned ep_dir1:2; ++ unsigned ep_dir2:2; ++ unsigned ep_dir3:2; ++ unsigned ep_dir4:2; ++ unsigned ep_dir5:2; ++ unsigned ep_dir6:2; ++ unsigned ep_dir7:2; ++ unsigned ep_dir8:2; ++ unsigned ep_dir9:2; ++ unsigned ep_dir10:2; ++ unsigned ep_dir11:2; ++ unsigned ep_dir12:2; ++ unsigned ep_dir13:2; ++ unsigned ep_dir14:2; ++ unsigned ep_dir15:2; ++ } b; ++} hwcfg1_data_t; ++ ++/** ++ * This union represents the bit fields in the User HW Config2 ++ * Register. Read the register into the d32 element then read ++ * out the bits using the bit elements. ++ */ ++typedef union hwcfg2_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /* GHWCFG2 */ ++ unsigned op_mode:3; ++#define DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG 0 ++#define DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1 ++#define DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2 ++#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3 ++#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4 ++#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5 ++#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6 ++ ++ unsigned architecture:2; ++ unsigned point2point:1; ++ unsigned hs_phy_type:2; ++#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0 ++#define DWC_HWCFG2_HS_PHY_TYPE_UTMI 1 ++#define DWC_HWCFG2_HS_PHY_TYPE_ULPI 2 ++#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3 ++ ++ unsigned fs_phy_type:2; ++ unsigned num_dev_ep:4; ++ unsigned num_host_chan:4; ++ unsigned perio_ep_supported:1; ++ unsigned dynamic_fifo:1; ++ unsigned multi_proc_int:1; ++ unsigned reserved21:1; ++ unsigned nonperio_tx_q_depth:2; ++ unsigned host_perio_tx_q_depth:2; ++ unsigned dev_token_q_depth:5; ++ unsigned otg_enable_ic_usb:1; ++ } b; ++} hwcfg2_data_t; ++ ++/** ++ * This union represents the bit fields in the User HW Config3 ++ * Register. Read the register into the d32 element then read ++ * out the bits using the bit elements. ++ */ ++typedef union hwcfg3_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /* GHWCFG3 */ ++ unsigned xfer_size_cntr_width:4; ++ unsigned packet_size_cntr_width:3; ++ unsigned otg_func:1; ++ unsigned i2c:1; ++ unsigned vendor_ctrl_if:1; ++ unsigned optional_features:1; ++ unsigned synch_reset_type:1; ++ unsigned adp_supp:1; ++ unsigned otg_enable_hsic:1; ++ unsigned bc_support:1; ++ unsigned otg_lpm_en:1; ++ unsigned dfifo_depth:16; ++ } b; ++} hwcfg3_data_t; ++ ++/** ++ * This union represents the bit fields in the User HW Config4 ++ * Register. Read the register into the d32 element then read ++ * out the bits using the bit elements. ++ */ ++typedef union hwcfg4_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned num_dev_perio_in_ep:4; ++ unsigned power_optimiz:1; ++ unsigned min_ahb_freq:1; ++ unsigned hiber:1; ++ unsigned xhiber:1; ++ unsigned reserved:6; ++ unsigned utmi_phy_data_width:2; ++ unsigned num_dev_mode_ctrl_ep:4; ++ unsigned iddig_filt_en:1; ++ unsigned vbus_valid_filt_en:1; ++ unsigned a_valid_filt_en:1; ++ unsigned b_valid_filt_en:1; ++ unsigned session_end_filt_en:1; ++ unsigned ded_fifo_en:1; ++ unsigned num_in_eps:4; ++ unsigned desc_dma:1; ++ unsigned desc_dma_dyn:1; ++ } b; ++} hwcfg4_data_t; ++ ++/** ++ * This union represents the bit fields of the Core LPM Configuration ++ * Register (GLPMCFG). Set the bits using bit fields then write ++ * the d32 value to the register. ++ */ ++typedef union glpmctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** LPM-Capable (LPMCap) (Device and Host) ++ * The application uses this bit to control ++ * the DWC_otg core LPM capabilities. ++ */ ++ unsigned lpm_cap_en:1; ++ /** LPM response programmed by application (AppL1Res) (Device) ++ * Handshake response to LPM token pre-programmed ++ * by device application software. ++ */ ++ unsigned appl_resp:1; ++ /** Host Initiated Resume Duration (HIRD) (Device and Host) ++ * In Host mode this field indicates the value of HIRD ++ * to be sent in an LPM transaction. ++ * In Device mode this field is updated with the ++ * Received LPM Token HIRD bmAttribute ++ * when an ACK/NYET/STALL response is sent ++ * to an LPM transaction. ++ */ ++ unsigned hird:4; ++ /** RemoteWakeEnable (bRemoteWake) (Device and Host) ++ * In Host mode this bit indicates the value of remote ++ * wake up to be sent in wIndex field of LPM transaction. ++ * In Device mode this field is updated with the ++ * Received LPM Token bRemoteWake bmAttribute ++ * when an ACK/NYET/STALL response is sent ++ * to an LPM transaction. ++ */ ++ unsigned rem_wkup_en:1; ++ /** Enable utmi_sleep_n (EnblSlpM) (Device and Host) ++ * The application uses this bit to control ++ * the utmi_sleep_n assertion to the PHY when in L1 state. ++ */ ++ unsigned en_utmi_sleep:1; ++ /** HIRD Threshold (HIRD_Thres) (Device and Host) ++ */ ++ unsigned hird_thres:5; ++ /** LPM Response (CoreL1Res) (Device and Host) ++ * In Host mode this bit contains handsake response to ++ * LPM transaction. ++ * In Device mode the response of the core to ++ * LPM transaction received is reflected in these two bits. ++ - 0x0 : ERROR (No handshake response) ++ - 0x1 : STALL ++ - 0x2 : NYET ++ - 0x3 : ACK ++ */ ++ unsigned lpm_resp:2; ++ /** Port Sleep Status (SlpSts) (Device and Host) ++ * This bit is set as long as a Sleep condition ++ * is present on the USB bus. ++ */ ++ unsigned prt_sleep_sts:1; ++ /** Sleep State Resume OK (L1ResumeOK) (Device and Host) ++ * Indicates that the application or host ++ * can start resume from Sleep state. ++ */ ++ unsigned sleep_state_resumeok:1; ++ /** LPM channel Index (LPM_Chnl_Indx) (Host) ++ * The channel number on which the LPM transaction ++ * has to be applied while sending ++ * an LPM transaction to the local device. ++ */ ++ unsigned lpm_chan_index:4; ++ /** LPM Retry Count (LPM_Retry_Cnt) (Host) ++ * Number host retries that would be performed ++ * if the device response was not valid response. ++ */ ++ unsigned retry_count:3; ++ /** Send LPM Transaction (SndLPM) (Host) ++ * When set by application software, ++ * an LPM transaction containing two tokens ++ * is sent. ++ */ ++ unsigned send_lpm:1; ++ /** LPM Retry status (LPM_RetryCnt_Sts) (Host) ++ * Number of LPM Host Retries still remaining ++ * to be transmitted for the current LPM sequence ++ */ ++ unsigned retry_count_sts:3; ++ /** Enable Best Effort Service Latency (BESL) (Device and Host) ++ * This bit enables the BESL features as defined in the LPM errata ++ */ ++ unsigned en_besl:1; ++ ++ unsigned reserved29:1; ++ /** In host mode once this bit is set, the host ++ * configures to drive the HSIC Idle state on the bus. ++ * It then waits for the device to initiate the Connect sequence. ++ * In device mode once this bit is set, the device waits for ++ * the HSIC Idle line state on the bus. Upon receving the Idle ++ * line state, it initiates the HSIC Connect sequence. ++ */ ++ unsigned hsic_connect:1; ++ /** This bit overrides and functionally inverts ++ * the if_select_hsic input port signal. ++ */ ++ unsigned inv_sel_hsic:1; ++ } b; ++} glpmcfg_data_t; ++ ++/** ++ * This union represents the bit fields of the Core ADP Timer, Control and ++ * Status Register (ADPTIMCTLSTS). Set the bits using bit fields then write ++ * the d32 value to the register. ++ */ ++typedef union adpctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Probe Discharge (PRB_DSCHG) ++ * These bits set the times for TADP_DSCHG. ++ * These bits are defined as follows: ++ * 2'b00 - 4 msec ++ * 2'b01 - 8 msec ++ * 2'b10 - 16 msec ++ * 2'b11 - 32 msec ++ */ ++ unsigned prb_dschg:2; ++ /** Probe Delta (PRB_DELTA) ++ * These bits set the resolution for RTIM value. ++ * The bits are defined in units of 32 kHz clock cycles as follows: ++ * 2'b00 - 1 cycles ++ * 2'b01 - 2 cycles ++ * 2'b10 - 3 cycles ++ * 2'b11 - 4 cycles ++ * For example if this value is chosen to 2'b01, it means that RTIM ++ * increments for every 3(three) 32Khz clock cycles. ++ */ ++ unsigned prb_delta:2; ++ /** Probe Period (PRB_PER) ++ * These bits sets the TADP_PRD as shown in Figure 4 as follows: ++ * 2'b00 - 0.625 to 0.925 sec (typical 0.775 sec) ++ * 2'b01 - 1.25 to 1.85 sec (typical 1.55 sec) ++ * 2'b10 - 1.9 to 2.6 sec (typical 2.275 sec) ++ * 2'b11 - Reserved ++ */ ++ unsigned prb_per:2; ++ /** These bits capture the latest time it took for VBUS to ramp from ++ * VADP_SINK to VADP_PRB. ++ * 0x000 - 1 cycles ++ * 0x001 - 2 cycles ++ * 0x002 - 3 cycles ++ * etc ++ * 0x7FF - 2048 cycles ++ * A time of 1024 cycles at 32 kHz corresponds to a time of 32 msec. ++ */ ++ unsigned rtim:11; ++ /** Enable Probe (EnaPrb) ++ * When programmed to 1'b1, the core performs a probe operation. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned enaprb:1; ++ /** Enable Sense (EnaSns) ++ * When programmed to 1'b1, the core performs a Sense operation. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned enasns:1; ++ /** ADP Reset (ADPRes) ++ * When set, ADP controller is reset. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adpres:1; ++ /** ADP Enable (ADPEn) ++ * When set, the core performs either ADP probing or sensing ++ * based on EnaPrb or EnaSns. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adpen:1; ++ /** ADP Probe Interrupt (ADP_PRB_INT) ++ * When this bit is set, it means that the VBUS ++ * voltage is greater than VADP_PRB or VADP_PRB is reached. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_prb_int:1; ++ /** ++ * ADP Sense Interrupt (ADP_SNS_INT) ++ * When this bit is set, it means that the VBUS voltage is greater than ++ * VADP_SNS value or VADP_SNS is reached. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_sns_int:1; ++ /** ADP Tomeout Interrupt (ADP_TMOUT_INT) ++ * This bit is relevant only for an ADP probe. ++ * When this bit is set, it means that the ramp time has ++ * completed ie ADPCTL.RTIM has reached its terminal value ++ * of 0x7FF. This is a debug feature that allows software ++ * to read the ramp time after each cycle. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_tmout_int:1; ++ /** ADP Probe Interrupt Mask (ADP_PRB_INT_MSK) ++ * When this bit is set, it unmasks the interrupt due to ADP_PRB_INT. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_prb_int_msk:1; ++ /** ADP Sense Interrupt Mask (ADP_SNS_INT_MSK) ++ * When this bit is set, it unmasks the interrupt due to ADP_SNS_INT. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_sns_int_msk:1; ++ /** ADP Timoeout Interrupt Mask (ADP_TMOUT_MSK) ++ * When this bit is set, it unmasks the interrupt due to ADP_TMOUT_INT. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_tmout_int_msk:1; ++ /** Access Request ++ * 2'b00 - Read/Write Valid (updated by the core) ++ * 2'b01 - Read ++ * 2'b00 - Write ++ * 2'b00 - Reserved ++ */ ++ unsigned ar:2; ++ /** Reserved */ ++ unsigned reserved29_31:3; ++ } b; ++} adpctl_data_t; ++ ++//////////////////////////////////////////// ++// Device Registers ++/** ++ * Device Global Registers. Offsets 800h-BFFh ++ * ++ * The following structures define the size and relative field offsets ++ * for the Device Mode Registers. ++ * ++ * These registers are visible only in Device mode and must not be ++ * accessed in Host mode, as the results are unknown. ++ */ ++typedef struct dwc_otg_dev_global_regs { ++ /** Device Configuration Register. Offset 800h */ ++ volatile uint32_t dcfg; ++ /** Device Control Register. Offset: 804h */ ++ volatile uint32_t dctl; ++ /** Device Status Register (Read Only). Offset: 808h */ ++ volatile uint32_t dsts; ++ /** Reserved. Offset: 80Ch */ ++ uint32_t unused; ++ /** Device IN Endpoint Common Interrupt Mask ++ * Register. Offset: 810h */ ++ volatile uint32_t diepmsk; ++ /** Device OUT Endpoint Common Interrupt Mask ++ * Register. Offset: 814h */ ++ volatile uint32_t doepmsk; ++ /** Device All Endpoints Interrupt Register. Offset: 818h */ ++ volatile uint32_t daint; ++ /** Device All Endpoints Interrupt Mask Register. Offset: ++ * 81Ch */ ++ volatile uint32_t daintmsk; ++ /** Device IN Token Queue Read Register-1 (Read Only). ++ * Offset: 820h */ ++ volatile uint32_t dtknqr1; ++ /** Device IN Token Queue Read Register-2 (Read Only). ++ * Offset: 824h */ ++ volatile uint32_t dtknqr2; ++ /** Device VBUS discharge Register. Offset: 828h */ ++ volatile uint32_t dvbusdis; ++ /** Device VBUS Pulse Register. Offset: 82Ch */ ++ volatile uint32_t dvbuspulse; ++ /** Device IN Token Queue Read Register-3 (Read Only). / ++ * Device Thresholding control register (Read/Write) ++ * Offset: 830h */ ++ volatile uint32_t dtknqr3_dthrctl; ++ /** Device IN Token Queue Read Register-4 (Read Only). / ++ * Device IN EPs empty Inr. Mask Register (Read/Write) ++ * Offset: 834h */ ++ volatile uint32_t dtknqr4_fifoemptymsk; ++ /** Device Each Endpoint Interrupt Register (Read Only). / ++ * Offset: 838h */ ++ volatile uint32_t deachint; ++ /** Device Each Endpoint Interrupt mask Register (Read/Write). / ++ * Offset: 83Ch */ ++ volatile uint32_t deachintmsk; ++ /** Device Each In Endpoint Interrupt mask Register (Read/Write). / ++ * Offset: 840h */ ++ volatile uint32_t diepeachintmsk[MAX_EPS_CHANNELS]; ++ /** Device Each Out Endpoint Interrupt mask Register (Read/Write). / ++ * Offset: 880h */ ++ volatile uint32_t doepeachintmsk[MAX_EPS_CHANNELS]; ++} dwc_otg_device_global_regs_t; ++ ++/** ++ * This union represents the bit fields in the Device Configuration ++ * Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. Write the ++ * d32 member to the dcfg register. ++ */ ++typedef union dcfg_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Device Speed */ ++ unsigned devspd:2; ++ /** Non Zero Length Status OUT Handshake */ ++ unsigned nzstsouthshk:1; ++#define DWC_DCFG_SEND_STALL 1 ++ ++ unsigned ena32khzs:1; ++ /** Device Addresses */ ++ unsigned devaddr:7; ++ /** Periodic Frame Interval */ ++ unsigned perfrint:2; ++#define DWC_DCFG_FRAME_INTERVAL_80 0 ++#define DWC_DCFG_FRAME_INTERVAL_85 1 ++#define DWC_DCFG_FRAME_INTERVAL_90 2 ++#define DWC_DCFG_FRAME_INTERVAL_95 3 ++ ++ /** Enable Device OUT NAK for bulk in DDMA mode */ ++ unsigned endevoutnak:1; ++ ++ unsigned reserved14_17:4; ++ /** In Endpoint Mis-match count */ ++ unsigned epmscnt:5; ++ /** Enable Descriptor DMA in Device mode */ ++ unsigned descdma:1; ++ unsigned perschintvl:2; ++ unsigned resvalid:6; ++ } b; ++} dcfg_data_t; ++ ++/** ++ * This union represents the bit fields in the Device Control ++ * Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union dctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Remote Wakeup */ ++ unsigned rmtwkupsig:1; ++ /** Soft Disconnect */ ++ unsigned sftdiscon:1; ++ /** Global Non-Periodic IN NAK Status */ ++ unsigned gnpinnaksts:1; ++ /** Global OUT NAK Status */ ++ unsigned goutnaksts:1; ++ /** Test Control */ ++ unsigned tstctl:3; ++ /** Set Global Non-Periodic IN NAK */ ++ unsigned sgnpinnak:1; ++ /** Clear Global Non-Periodic IN NAK */ ++ unsigned cgnpinnak:1; ++ /** Set Global OUT NAK */ ++ unsigned sgoutnak:1; ++ /** Clear Global OUT NAK */ ++ unsigned cgoutnak:1; ++ /** Power-On Programming Done */ ++ unsigned pwronprgdone:1; ++ /** Reserved */ ++ unsigned reserved:1; ++ /** Global Multi Count */ ++ unsigned gmc:2; ++ /** Ignore Frame Number for ISOC EPs */ ++ unsigned ifrmnum:1; ++ /** NAK on Babble */ ++ unsigned nakonbble:1; ++ /** Enable Continue on BNA */ ++ unsigned encontonbna:1; ++ /** Enable deep sleep besl reject feature*/ ++ unsigned besl_reject:1; ++ ++ unsigned reserved17_31:13; ++ } b; ++} dctl_data_t; ++ ++/** ++ * This union represents the bit fields in the Device Status ++ * Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union dsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Suspend Status */ ++ unsigned suspsts:1; ++ /** Enumerated Speed */ ++ unsigned enumspd:2; ++#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0 ++#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1 ++#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ 2 ++#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ 3 ++ /** Erratic Error */ ++ unsigned errticerr:1; ++ unsigned reserved4_7:4; ++ /** Frame or Microframe Number of the received SOF */ ++ unsigned soffn:14; ++ unsigned reserved22_31:10; ++ } b; ++} dsts_data_t; ++ ++/** ++ * This union represents the bit fields in the Device IN EP Interrupt ++ * Register and the Device IN EP Common Mask Register. ++ * ++ * - Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++typedef union diepint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer complete mask */ ++ unsigned xfercompl:1; ++ /** Endpoint disable mask */ ++ unsigned epdisabled:1; ++ /** AHB Error mask */ ++ unsigned ahberr:1; ++ /** TimeOUT Handshake mask (non-ISOC EPs) */ ++ unsigned timeout:1; ++ /** IN Token received with TxF Empty mask */ ++ unsigned intktxfemp:1; ++ /** IN Token Received with EP mismatch mask */ ++ unsigned intknepmis:1; ++ /** IN Endpoint NAK Effective mask */ ++ unsigned inepnakeff:1; ++ /** Reserved */ ++ unsigned emptyintr:1; ++ ++ unsigned txfifoundrn:1; ++ ++ /** BNA Interrupt mask */ ++ unsigned bna:1; ++ ++ unsigned reserved10_12:3; ++ /** BNA Interrupt mask */ ++ unsigned nak:1; ++ ++ unsigned reserved14_31:18; ++ } b; ++} diepint_data_t; ++ ++/** ++ * This union represents the bit fields in the Device IN EP ++ * Common/Dedicated Interrupt Mask Register. ++ */ ++typedef union diepint_data diepmsk_data_t; ++ ++/** ++ * This union represents the bit fields in the Device OUT EP Interrupt ++ * Registerand Device OUT EP Common Interrupt Mask Register. ++ * ++ * - Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++typedef union doepint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer complete */ ++ unsigned xfercompl:1; ++ /** Endpoint disable */ ++ unsigned epdisabled:1; ++ /** AHB Error */ ++ unsigned ahberr:1; ++ /** Setup Phase Done (contorl EPs) */ ++ unsigned setup:1; ++ /** OUT Token Received when Endpoint Disabled */ ++ unsigned outtknepdis:1; ++ ++ unsigned stsphsercvd:1; ++ /** Back-to-Back SETUP Packets Received */ ++ unsigned back2backsetup:1; ++ ++ unsigned reserved7:1; ++ /** OUT packet Error */ ++ unsigned outpkterr:1; ++ /** BNA Interrupt */ ++ unsigned bna:1; ++ ++ unsigned reserved10:1; ++ /** Packet Drop Status */ ++ unsigned pktdrpsts:1; ++ /** Babble Interrupt */ ++ unsigned babble:1; ++ /** NAK Interrupt */ ++ unsigned nak:1; ++ /** NYET Interrupt */ ++ unsigned nyet:1; ++ /** Bit indicating setup packet received */ ++ unsigned sr:1; ++ ++ unsigned reserved16_31:16; ++ } b; ++} doepint_data_t; ++ ++/** ++ * This union represents the bit fields in the Device OUT EP ++ * Common/Dedicated Interrupt Mask Register. ++ */ ++typedef union doepint_data doepmsk_data_t; ++ ++/** ++ * This union represents the bit fields in the Device All EP Interrupt ++ * and Mask Registers. ++ * - Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++typedef union daint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** IN Endpoint bits */ ++ unsigned in:16; ++ /** OUT Endpoint bits */ ++ unsigned out:16; ++ } ep; ++ struct { ++ /** IN Endpoint bits */ ++ unsigned inep0:1; ++ unsigned inep1:1; ++ unsigned inep2:1; ++ unsigned inep3:1; ++ unsigned inep4:1; ++ unsigned inep5:1; ++ unsigned inep6:1; ++ unsigned inep7:1; ++ unsigned inep8:1; ++ unsigned inep9:1; ++ unsigned inep10:1; ++ unsigned inep11:1; ++ unsigned inep12:1; ++ unsigned inep13:1; ++ unsigned inep14:1; ++ unsigned inep15:1; ++ /** OUT Endpoint bits */ ++ unsigned outep0:1; ++ unsigned outep1:1; ++ unsigned outep2:1; ++ unsigned outep3:1; ++ unsigned outep4:1; ++ unsigned outep5:1; ++ unsigned outep6:1; ++ unsigned outep7:1; ++ unsigned outep8:1; ++ unsigned outep9:1; ++ unsigned outep10:1; ++ unsigned outep11:1; ++ unsigned outep12:1; ++ unsigned outep13:1; ++ unsigned outep14:1; ++ unsigned outep15:1; ++ } b; ++} daint_data_t; ++ ++/** ++ * This union represents the bit fields in the Device IN Token Queue ++ * Read Registers. ++ * - Read the register into the d32 member. ++ * - READ-ONLY Register ++ */ ++typedef union dtknq1_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** In Token Queue Write Pointer */ ++ unsigned intknwptr:5; ++ /** Reserved */ ++ unsigned reserved05_06:2; ++ /** write pointer has wrapped. */ ++ unsigned wrap_bit:1; ++ /** EP Numbers of IN Tokens 0 ... 4 */ ++ unsigned epnums0_5:24; ++ } b; ++} dtknq1_data_t; ++ ++/** ++ * This union represents Threshold control Register ++ * - Read and write the register into the d32 member. ++ * - READ-WRITABLE Register ++ */ ++typedef union dthrctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** non ISO Tx Thr. Enable */ ++ unsigned non_iso_thr_en:1; ++ /** ISO Tx Thr. Enable */ ++ unsigned iso_thr_en:1; ++ /** Tx Thr. Length */ ++ unsigned tx_thr_len:9; ++ /** AHB Threshold ratio */ ++ unsigned ahb_thr_ratio:2; ++ /** Reserved */ ++ unsigned reserved13_15:3; ++ /** Rx Thr. Enable */ ++ unsigned rx_thr_en:1; ++ /** Rx Thr. Length */ ++ unsigned rx_thr_len:9; ++ unsigned reserved26:1; ++ /** Arbiter Parking Enable*/ ++ unsigned arbprken:1; ++ /** Reserved */ ++ unsigned reserved28_31:4; ++ } b; ++} dthrctl_data_t; ++ ++/** ++ * Device Logical IN Endpoint-Specific Registers. Offsets ++ * 900h-AFCh ++ * ++ * There will be one set of endpoint registers per logical endpoint ++ * implemented. ++ * ++ * These registers are visible only in Device mode and must not be ++ * accessed in Host mode, as the results are unknown. ++ */ ++typedef struct dwc_otg_dev_in_ep_regs { ++ /** Device IN Endpoint Control Register. Offset:900h + ++ * (ep_num * 20h) + 00h */ ++ volatile uint32_t diepctl; ++ /** Reserved. Offset:900h + (ep_num * 20h) + 04h */ ++ uint32_t reserved04; ++ /** Device IN Endpoint Interrupt Register. Offset:900h + ++ * (ep_num * 20h) + 08h */ ++ volatile uint32_t diepint; ++ /** Reserved. Offset:900h + (ep_num * 20h) + 0Ch */ ++ uint32_t reserved0C; ++ /** Device IN Endpoint Transfer Size ++ * Register. Offset:900h + (ep_num * 20h) + 10h */ ++ volatile uint32_t dieptsiz; ++ /** Device IN Endpoint DMA Address Register. Offset:900h + ++ * (ep_num * 20h) + 14h */ ++ volatile uint32_t diepdma; ++ /** Device IN Endpoint Transmit FIFO Status Register. Offset:900h + ++ * (ep_num * 20h) + 18h */ ++ volatile uint32_t dtxfsts; ++ /** Device IN Endpoint DMA Buffer Register. Offset:900h + ++ * (ep_num * 20h) + 1Ch */ ++ volatile uint32_t diepdmab; ++} dwc_otg_dev_in_ep_regs_t; ++ ++/** ++ * Device Logical OUT Endpoint-Specific Registers. Offsets: ++ * B00h-CFCh ++ * ++ * There will be one set of endpoint registers per logical endpoint ++ * implemented. ++ * ++ * These registers are visible only in Device mode and must not be ++ * accessed in Host mode, as the results are unknown. ++ */ ++typedef struct dwc_otg_dev_out_ep_regs { ++ /** Device OUT Endpoint Control Register. Offset:B00h + ++ * (ep_num * 20h) + 00h */ ++ volatile uint32_t doepctl; ++ /** Reserved. Offset:B00h + (ep_num * 20h) + 04h */ ++ uint32_t reserved04; ++ /** Device OUT Endpoint Interrupt Register. Offset:B00h + ++ * (ep_num * 20h) + 08h */ ++ volatile uint32_t doepint; ++ /** Reserved. Offset:B00h + (ep_num * 20h) + 0Ch */ ++ uint32_t reserved0C; ++ /** Device OUT Endpoint Transfer Size Register. Offset: ++ * B00h + (ep_num * 20h) + 10h */ ++ volatile uint32_t doeptsiz; ++ /** Device OUT Endpoint DMA Address Register. Offset:B00h ++ * + (ep_num * 20h) + 14h */ ++ volatile uint32_t doepdma; ++ /** Reserved. Offset:B00h + * (ep_num * 20h) + 18h */ ++ uint32_t unused; ++ /** Device OUT Endpoint DMA Buffer Register. Offset:B00h ++ * + (ep_num * 20h) + 1Ch */ ++ uint32_t doepdmab; ++} dwc_otg_dev_out_ep_regs_t; ++ ++/** ++ * This union represents the bit fields in the Device EP Control ++ * Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union depctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Maximum Packet Size ++ * IN/OUT EPn ++ * IN/OUT EP0 - 2 bits ++ * 2'b00: 64 Bytes ++ * 2'b01: 32 ++ * 2'b10: 16 ++ * 2'b11: 8 */ ++ unsigned mps:11; ++#define DWC_DEP0CTL_MPS_64 0 ++#define DWC_DEP0CTL_MPS_32 1 ++#define DWC_DEP0CTL_MPS_16 2 ++#define DWC_DEP0CTL_MPS_8 3 ++ ++ /** Next Endpoint ++ * IN EPn/IN EP0 ++ * OUT EPn/OUT EP0 - reserved */ ++ unsigned nextep:4; ++ ++ /** USB Active Endpoint */ ++ unsigned usbactep:1; ++ ++ /** Endpoint DPID (INTR/Bulk IN and OUT endpoints) ++ * This field contains the PID of the packet going to ++ * be received or transmitted on this endpoint. The ++ * application should program the PID of the first ++ * packet going to be received or transmitted on this ++ * endpoint , after the endpoint is ++ * activated. Application use the SetD1PID and ++ * SetD0PID fields of this register to program either ++ * D0 or D1 PID. ++ * ++ * The encoding for this field is ++ * - 0: D0 ++ * - 1: D1 ++ */ ++ unsigned dpid:1; ++ ++ /** NAK Status */ ++ unsigned naksts:1; ++ ++ /** Endpoint Type ++ * 2'b00: Control ++ * 2'b01: Isochronous ++ * 2'b10: Bulk ++ * 2'b11: Interrupt */ ++ unsigned eptype:2; ++ ++ /** Snoop Mode ++ * OUT EPn/OUT EP0 ++ * IN EPn/IN EP0 - reserved */ ++ unsigned snp:1; ++ ++ /** Stall Handshake */ ++ unsigned stall:1; ++ ++ /** Tx Fifo Number ++ * IN EPn/IN EP0 ++ * OUT EPn/OUT EP0 - reserved */ ++ unsigned txfnum:4; ++ ++ /** Clear NAK */ ++ unsigned cnak:1; ++ /** Set NAK */ ++ unsigned snak:1; ++ /** Set DATA0 PID (INTR/Bulk IN and OUT endpoints) ++ * Writing to this field sets the Endpoint DPID (DPID) ++ * field in this register to DATA0. Set Even ++ * (micro)frame (SetEvenFr) (ISO IN and OUT Endpoints) ++ * Writing to this field sets the Even/Odd ++ * (micro)frame (EO_FrNum) field to even (micro) ++ * frame. ++ */ ++ unsigned setd0pid:1; ++ /** Set DATA1 PID (INTR/Bulk IN and OUT endpoints) ++ * Writing to this field sets the Endpoint DPID (DPID) ++ * field in this register to DATA1 Set Odd ++ * (micro)frame (SetOddFr) (ISO IN and OUT Endpoints) ++ * Writing to this field sets the Even/Odd ++ * (micro)frame (EO_FrNum) field to odd (micro) frame. ++ */ ++ unsigned setd1pid:1; ++ ++ /** Endpoint Disable */ ++ unsigned epdis:1; ++ /** Endpoint Enable */ ++ unsigned epena:1; ++ } b; ++} depctl_data_t; ++ ++/** ++ * This union represents the bit fields in the Device EP Transfer ++ * Size Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union deptsiz_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer size */ ++ unsigned xfersize:19; ++/** Max packet count for EP (pow(2,10)-1) */ ++#define MAX_PKT_CNT 1023 ++ /** Packet Count */ ++ unsigned pktcnt:10; ++ /** Multi Count - Periodic IN endpoints */ ++ unsigned mc:2; ++ unsigned reserved:1; ++ } b; ++} deptsiz_data_t; ++ ++/** ++ * This union represents the bit fields in the Device EP 0 Transfer ++ * Size Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union deptsiz0_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer size */ ++ unsigned xfersize:7; ++ /** Reserved */ ++ unsigned reserved7_18:12; ++ /** Packet Count */ ++ unsigned pktcnt:2; ++ /** Reserved */ ++ unsigned reserved21_28:8; ++ /**Setup Packet Count (DOEPTSIZ0 Only) */ ++ unsigned supcnt:2; ++ unsigned reserved31; ++ } b; ++} deptsiz0_data_t; ++ ++///////////////////////////////////////////////// ++// DMA Descriptor Specific Structures ++// ++ ++/** Buffer status definitions */ ++ ++#define BS_HOST_READY 0x0 ++#define BS_DMA_BUSY 0x1 ++#define BS_DMA_DONE 0x2 ++#define BS_HOST_BUSY 0x3 ++ ++/** Receive/Transmit status definitions */ ++ ++#define RTS_SUCCESS 0x0 ++#define RTS_BUFFLUSH 0x1 ++#define RTS_RESERVED 0x2 ++#define RTS_BUFERR 0x3 ++ ++/** ++ * This union represents the bit fields in the DMA Descriptor ++ * status quadlet. Read the quadlet into the d32 member then ++ * set/clear the bits using the bit, b_iso_out and ++ * b_iso_in elements. ++ */ ++typedef union dev_dma_desc_sts { ++ /** raw register data */ ++ uint32_t d32; ++ /** quadlet bits */ ++ struct { ++ /** Received number of bytes */ ++ unsigned bytes:16; ++ /** NAK bit - only for OUT EPs */ ++ unsigned nak:1; ++ unsigned reserved17_22:6; ++ /** Multiple Transfer - only for OUT EPs */ ++ unsigned mtrf:1; ++ /** Setup Packet received - only for OUT EPs */ ++ unsigned sr:1; ++ /** Interrupt On Complete */ ++ unsigned ioc:1; ++ /** Short Packet */ ++ unsigned sp:1; ++ /** Last */ ++ unsigned l:1; ++ /** Receive Status */ ++ unsigned sts:2; ++ /** Buffer Status */ ++ unsigned bs:2; ++ } b; ++ ++//#ifdef DWC_EN_ISOC ++ /** iso out quadlet bits */ ++ struct { ++ /** Received number of bytes */ ++ unsigned rxbytes:11; ++ ++ unsigned reserved11:1; ++ /** Frame Number */ ++ unsigned framenum:11; ++ /** Received ISO Data PID */ ++ unsigned pid:2; ++ /** Interrupt On Complete */ ++ unsigned ioc:1; ++ /** Short Packet */ ++ unsigned sp:1; ++ /** Last */ ++ unsigned l:1; ++ /** Receive Status */ ++ unsigned rxsts:2; ++ /** Buffer Status */ ++ unsigned bs:2; ++ } b_iso_out; ++ ++ /** iso in quadlet bits */ ++ struct { ++ /** Transmited number of bytes */ ++ unsigned txbytes:12; ++ /** Frame Number */ ++ unsigned framenum:11; ++ /** Transmited ISO Data PID */ ++ unsigned pid:2; ++ /** Interrupt On Complete */ ++ unsigned ioc:1; ++ /** Short Packet */ ++ unsigned sp:1; ++ /** Last */ ++ unsigned l:1; ++ /** Transmit Status */ ++ unsigned txsts:2; ++ /** Buffer Status */ ++ unsigned bs:2; ++ } b_iso_in; ++//#endif /* DWC_EN_ISOC */ ++} dev_dma_desc_sts_t; ++ ++/** ++ * DMA Descriptor structure ++ * ++ * DMA Descriptor structure contains two quadlets: ++ * Status quadlet and Data buffer pointer. ++ */ ++typedef struct dwc_otg_dev_dma_desc { ++ /** DMA Descriptor status quadlet */ ++ dev_dma_desc_sts_t status; ++ /** DMA Descriptor data buffer pointer */ ++ uint32_t buf; ++} dwc_otg_dev_dma_desc_t; ++ ++/** ++ * The dwc_otg_dev_if structure contains information needed to manage ++ * the DWC_otg controller acting in device mode. It represents the ++ * programming view of the device-specific aspects of the controller. ++ */ ++typedef struct dwc_otg_dev_if { ++ /** Pointer to device Global registers. ++ * Device Global Registers starting at offset 800h ++ */ ++ dwc_otg_device_global_regs_t *dev_global_regs; ++#define DWC_DEV_GLOBAL_REG_OFFSET 0x800 ++ ++ /** ++ * Device Logical IN Endpoint-Specific Registers 900h-AFCh ++ */ ++ dwc_otg_dev_in_ep_regs_t *in_ep_regs[MAX_EPS_CHANNELS]; ++#define DWC_DEV_IN_EP_REG_OFFSET 0x900 ++#define DWC_EP_REG_OFFSET 0x20 ++ ++ /** Device Logical OUT Endpoint-Specific Registers B00h-CFCh */ ++ dwc_otg_dev_out_ep_regs_t *out_ep_regs[MAX_EPS_CHANNELS]; ++#define DWC_DEV_OUT_EP_REG_OFFSET 0xB00 ++ ++ /* Device configuration information */ ++ uint8_t speed; /**< Device Speed 0: Unknown, 1: LS, 2:FS, 3: HS */ ++ uint8_t num_in_eps; /**< Number # of Tx EP range: 0-15 exept ep0 */ ++ uint8_t num_out_eps; /**< Number # of Rx EP range: 0-15 exept ep 0*/ ++ ++ /** Size of periodic FIFOs (Bytes) */ ++ uint16_t perio_tx_fifo_size[MAX_PERIO_FIFOS]; ++ ++ /** Size of Tx FIFOs (Bytes) */ ++ uint16_t tx_fifo_size[MAX_TX_FIFOS]; ++ ++ /** Thresholding enable flags and length varaiables **/ ++ uint16_t rx_thr_en; ++ uint16_t iso_tx_thr_en; ++ uint16_t non_iso_tx_thr_en; ++ ++ uint16_t rx_thr_length; ++ uint16_t tx_thr_length; ++ ++ /** ++ * Pointers to the DMA Descriptors for EP0 Control ++ * transfers (virtual and physical) ++ */ ++ ++ /** 2 descriptors for SETUP packets */ ++ dwc_dma_t dma_setup_desc_addr[2]; ++ dwc_otg_dev_dma_desc_t *setup_desc_addr[2]; ++ ++ /** Pointer to Descriptor with latest SETUP packet */ ++ dwc_otg_dev_dma_desc_t *psetup; ++ ++ /** Index of current SETUP handler descriptor */ ++ uint32_t setup_desc_index; ++ ++ /** Descriptor for Data In or Status In phases */ ++ dwc_dma_t dma_in_desc_addr; ++ dwc_otg_dev_dma_desc_t *in_desc_addr; ++ ++ /** Descriptor for Data Out or Status Out phases */ ++ dwc_dma_t dma_out_desc_addr; ++ dwc_otg_dev_dma_desc_t *out_desc_addr; ++ ++ /** Setup Packet Detected - if set clear NAK when queueing */ ++ uint32_t spd; ++ /** Isoc ep pointer on which incomplete happens */ ++ void *isoc_ep; ++ ++} dwc_otg_dev_if_t; ++ ++///////////////////////////////////////////////// ++// Host Mode Register Structures ++// ++/** ++ * The Host Global Registers structure defines the size and relative ++ * field offsets for the Host Mode Global Registers. Host Global ++ * Registers offsets 400h-7FFh. ++*/ ++typedef struct dwc_otg_host_global_regs { ++ /** Host Configuration Register. Offset: 400h */ ++ volatile uint32_t hcfg; ++ /** Host Frame Interval Register. Offset: 404h */ ++ volatile uint32_t hfir; ++ /** Host Frame Number / Frame Remaining Register. Offset: 408h */ ++ volatile uint32_t hfnum; ++ /** Reserved. Offset: 40Ch */ ++ uint32_t reserved40C; ++ /** Host Periodic Transmit FIFO/ Queue Status Register. Offset: 410h */ ++ volatile uint32_t hptxsts; ++ /** Host All Channels Interrupt Register. Offset: 414h */ ++ volatile uint32_t haint; ++ /** Host All Channels Interrupt Mask Register. Offset: 418h */ ++ volatile uint32_t haintmsk; ++ /** Host Frame List Base Address Register . Offset: 41Ch */ ++ volatile uint32_t hflbaddr; ++} dwc_otg_host_global_regs_t; ++ ++/** ++ * This union represents the bit fields in the Host Configuration Register. ++ * Read the register into the d32 member then set/clear the bits using ++ * the bit elements. Write the d32 member to the hcfg register. ++ */ ++typedef union hcfg_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** FS/LS Phy Clock Select */ ++ unsigned fslspclksel:2; ++#define DWC_HCFG_30_60_MHZ 0 ++#define DWC_HCFG_48_MHZ 1 ++#define DWC_HCFG_6_MHZ 2 ++ ++ /** FS/LS Only Support */ ++ unsigned fslssupp:1; ++ unsigned reserved3_6:4; ++ /** Enable 32-KHz Suspend Mode */ ++ unsigned ena32khzs:1; ++ /** Resume Validation Periiod */ ++ unsigned resvalid:8; ++ unsigned reserved16_22:7; ++ /** Enable Scatter/gather DMA in Host mode */ ++ unsigned descdma:1; ++ /** Frame List Entries */ ++ unsigned frlisten:2; ++ /** Enable Periodic Scheduling */ ++ unsigned perschedena:1; ++ unsigned reserved27_30:4; ++ unsigned modechtimen:1; ++ } b; ++} hcfg_data_t; ++ ++/** ++ * This union represents the bit fields in the Host Frame Remaing/Number ++ * Register. ++ */ ++typedef union hfir_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ unsigned frint:16; ++ unsigned hfirrldctrl:1; ++ unsigned reserved:15; ++ } b; ++} hfir_data_t; ++ ++/** ++ * This union represents the bit fields in the Host Frame Remaing/Number ++ * Register. ++ */ ++typedef union hfnum_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ unsigned frnum:16; ++#define DWC_HFNUM_MAX_FRNUM 0x3FFF ++ unsigned frrem:16; ++ } b; ++} hfnum_data_t; ++ ++typedef union hptxsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ unsigned ptxfspcavail:16; ++ unsigned ptxqspcavail:8; ++ /** Top of the Periodic Transmit Request Queue ++ * - bit 24 - Terminate (last entry for the selected channel) ++ * - bits 26:25 - Token Type ++ * - 2'b00 - Zero length ++ * - 2'b01 - Ping ++ * - 2'b10 - Disable ++ * - bits 30:27 - Channel Number ++ * - bit 31 - Odd/even microframe ++ */ ++ unsigned ptxqtop_terminate:1; ++ unsigned ptxqtop_token:2; ++ unsigned ptxqtop_chnum:4; ++ unsigned ptxqtop_odd:1; ++ } b; ++} hptxsts_data_t; ++ ++/** ++ * This union represents the bit fields in the Host Port Control and Status ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. Write the d32 member to the ++ * hprt0 register. ++ */ ++typedef union hprt0_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned prtconnsts:1; ++ unsigned prtconndet:1; ++ unsigned prtena:1; ++ unsigned prtenchng:1; ++ unsigned prtovrcurract:1; ++ unsigned prtovrcurrchng:1; ++ unsigned prtres:1; ++ unsigned prtsusp:1; ++ unsigned prtrst:1; ++ unsigned reserved9:1; ++ unsigned prtlnsts:2; ++ unsigned prtpwr:1; ++ unsigned prttstctl:4; ++ unsigned prtspd:2; ++#define DWC_HPRT0_PRTSPD_HIGH_SPEED 0 ++#define DWC_HPRT0_PRTSPD_FULL_SPEED 1 ++#define DWC_HPRT0_PRTSPD_LOW_SPEED 2 ++ unsigned reserved19_31:13; ++ } b; ++} hprt0_data_t; ++ ++/** ++ * This union represents the bit fields in the Host All Interrupt ++ * Register. ++ */ ++typedef union haint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned ch0:1; ++ unsigned ch1:1; ++ unsigned ch2:1; ++ unsigned ch3:1; ++ unsigned ch4:1; ++ unsigned ch5:1; ++ unsigned ch6:1; ++ unsigned ch7:1; ++ unsigned ch8:1; ++ unsigned ch9:1; ++ unsigned ch10:1; ++ unsigned ch11:1; ++ unsigned ch12:1; ++ unsigned ch13:1; ++ unsigned ch14:1; ++ unsigned ch15:1; ++ unsigned reserved:16; ++ } b; ++ ++ struct { ++ unsigned chint:16; ++ unsigned reserved:16; ++ } b2; ++} haint_data_t; ++ ++/** ++ * This union represents the bit fields in the Host All Interrupt ++ * Register. ++ */ ++typedef union haintmsk_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned ch0:1; ++ unsigned ch1:1; ++ unsigned ch2:1; ++ unsigned ch3:1; ++ unsigned ch4:1; ++ unsigned ch5:1; ++ unsigned ch6:1; ++ unsigned ch7:1; ++ unsigned ch8:1; ++ unsigned ch9:1; ++ unsigned ch10:1; ++ unsigned ch11:1; ++ unsigned ch12:1; ++ unsigned ch13:1; ++ unsigned ch14:1; ++ unsigned ch15:1; ++ unsigned reserved:16; ++ } b; ++ ++ struct { ++ unsigned chint:16; ++ unsigned reserved:16; ++ } b2; ++} haintmsk_data_t; ++ ++/** ++ * Host Channel Specific Registers. 500h-5FCh ++ */ ++typedef struct dwc_otg_hc_regs { ++ /** Host Channel 0 Characteristic Register. Offset: 500h + (chan_num * 20h) + 00h */ ++ volatile uint32_t hcchar; ++ /** Host Channel 0 Split Control Register. Offset: 500h + (chan_num * 20h) + 04h */ ++ volatile uint32_t hcsplt; ++ /** Host Channel 0 Interrupt Register. Offset: 500h + (chan_num * 20h) + 08h */ ++ volatile uint32_t hcint; ++ /** Host Channel 0 Interrupt Mask Register. Offset: 500h + (chan_num * 20h) + 0Ch */ ++ volatile uint32_t hcintmsk; ++ /** Host Channel 0 Transfer Size Register. Offset: 500h + (chan_num * 20h) + 10h */ ++ volatile uint32_t hctsiz; ++ /** Host Channel 0 DMA Address Register. Offset: 500h + (chan_num * 20h) + 14h */ ++ volatile uint32_t hcdma; ++ volatile uint32_t reserved; ++ /** Host Channel 0 DMA Buffer Address Register. Offset: 500h + (chan_num * 20h) + 1Ch */ ++ volatile uint32_t hcdmab; ++} dwc_otg_hc_regs_t; ++ ++/** ++ * This union represents the bit fields in the Host Channel Characteristics ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. Write the d32 member to the ++ * hcchar register. ++ */ ++typedef union hcchar_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** Maximum packet size in bytes */ ++ unsigned mps:11; ++ ++ /** Endpoint number */ ++ unsigned epnum:4; ++ ++ /** 0: OUT, 1: IN */ ++ unsigned epdir:1; ++ ++ unsigned reserved:1; ++ ++ /** 0: Full/high speed device, 1: Low speed device */ ++ unsigned lspddev:1; ++ ++ /** 0: Control, 1: Isoc, 2: Bulk, 3: Intr */ ++ unsigned eptype:2; ++ ++ /** Packets per frame for periodic transfers. 0 is reserved. */ ++ unsigned multicnt:2; ++ ++ /** Device address */ ++ unsigned devaddr:7; ++ ++ /** ++ * Frame to transmit periodic transaction. ++ * 0: even, 1: odd ++ */ ++ unsigned oddfrm:1; ++ ++ /** Channel disable */ ++ unsigned chdis:1; ++ ++ /** Channel enable */ ++ unsigned chen:1; ++ } b; ++} hcchar_data_t; ++ ++typedef union hcsplt_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** Port Address */ ++ unsigned prtaddr:7; ++ ++ /** Hub Address */ ++ unsigned hubaddr:7; ++ ++ /** Transaction Position */ ++ unsigned xactpos:2; ++#define DWC_HCSPLIT_XACTPOS_MID 0 ++#define DWC_HCSPLIT_XACTPOS_END 1 ++#define DWC_HCSPLIT_XACTPOS_BEGIN 2 ++#define DWC_HCSPLIT_XACTPOS_ALL 3 ++ ++ /** Do Complete Split */ ++ unsigned compsplt:1; ++ ++ /** Reserved */ ++ unsigned reserved:14; ++ ++ /** Split Enble */ ++ unsigned spltena:1; ++ } b; ++} hcsplt_data_t; ++ ++/** ++ * This union represents the bit fields in the Host All Interrupt ++ * Register. ++ */ ++typedef union hcint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer Complete */ ++ unsigned xfercomp:1; ++ /** Channel Halted */ ++ unsigned chhltd:1; ++ /** AHB Error */ ++ unsigned ahberr:1; ++ /** STALL Response Received */ ++ unsigned stall:1; ++ /** NAK Response Received */ ++ unsigned nak:1; ++ /** ACK Response Received */ ++ unsigned ack:1; ++ /** NYET Response Received */ ++ unsigned nyet:1; ++ /** Transaction Err */ ++ unsigned xacterr:1; ++ /** Babble Error */ ++ unsigned bblerr:1; ++ /** Frame Overrun */ ++ unsigned frmovrun:1; ++ /** Data Toggle Error */ ++ unsigned datatglerr:1; ++ /** Buffer Not Available (only for DDMA mode) */ ++ unsigned bna:1; ++ /** Exessive transaction error (only for DDMA mode) */ ++ unsigned xcs_xact:1; ++ /** Frame List Rollover interrupt */ ++ unsigned frm_list_roll:1; ++ /** Reserved */ ++ unsigned reserved14_31:18; ++ } b; ++} hcint_data_t; ++ ++/** ++ * This union represents the bit fields in the Host Channel Interrupt Mask ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. Write the d32 member to the ++ * hcintmsk register. ++ */ ++typedef union hcintmsk_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ unsigned xfercompl:1; ++ unsigned chhltd:1; ++ unsigned ahberr:1; ++ unsigned stall:1; ++ unsigned nak:1; ++ unsigned ack:1; ++ unsigned nyet:1; ++ unsigned xacterr:1; ++ unsigned bblerr:1; ++ unsigned frmovrun:1; ++ unsigned datatglerr:1; ++ unsigned bna:1; ++ unsigned xcs_xact:1; ++ unsigned frm_list_roll:1; ++ unsigned reserved14_31:18; ++ } b; ++} hcintmsk_data_t; ++ ++/** ++ * This union represents the bit fields in the Host Channel Transfer Size ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. Write the d32 member to the ++ * hcchar register. ++ */ ++ ++typedef union hctsiz_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** Total transfer size in bytes */ ++ unsigned xfersize:19; ++ ++ /** Data packets to transfer */ ++ unsigned pktcnt:10; ++ ++ /** ++ * Packet ID for next data packet ++ * 0: DATA0 ++ * 1: DATA2 ++ * 2: DATA1 ++ * 3: MDATA (non-Control), SETUP (Control) ++ */ ++ unsigned pid:2; ++#define DWC_HCTSIZ_DATA0 0 ++#define DWC_HCTSIZ_DATA1 2 ++#define DWC_HCTSIZ_DATA2 1 ++#define DWC_HCTSIZ_MDATA 3 ++#define DWC_HCTSIZ_SETUP 3 ++ ++ /** Do PING protocol when 1 */ ++ unsigned dopng:1; ++ } b; ++ ++ /** register bits */ ++ struct { ++ /** Scheduling information */ ++ unsigned schinfo:8; ++ ++ /** Number of transfer descriptors. ++ * Max value: ++ * 64 in general, ++ * 256 only for HS isochronous endpoint. ++ */ ++ unsigned ntd:8; ++ ++ /** Data packets to transfer */ ++ unsigned reserved16_28:13; ++ ++ /** ++ * Packet ID for next data packet ++ * 0: DATA0 ++ * 1: DATA2 ++ * 2: DATA1 ++ * 3: MDATA (non-Control) ++ */ ++ unsigned pid:2; ++ ++ /** Do PING protocol when 1 */ ++ unsigned dopng:1; ++ } b_ddma; ++} hctsiz_data_t; ++ ++/** ++ * This union represents the bit fields in the Host DMA Address ++ * Register used in Descriptor DMA mode. ++ */ ++typedef union hcdma_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned reserved0_2:3; ++ /** Current Transfer Descriptor. Not used for ISOC */ ++ unsigned ctd:8; ++ /** Start Address of Descriptor List */ ++ unsigned dma_addr:21; ++ } b; ++} hcdma_data_t; ++ ++/** ++ * This union represents the bit fields in the DMA Descriptor ++ * status quadlet for host mode. Read the quadlet into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union host_dma_desc_sts { ++ /** raw register data */ ++ uint32_t d32; ++ /** quadlet bits */ ++ ++ /* for non-isochronous */ ++ struct { ++ /** Number of bytes */ ++ unsigned n_bytes:17; ++ /** QTD offset to jump when Short Packet received - only for IN EPs */ ++ unsigned qtd_offset:6; ++ /** ++ * Set to request the core to jump to alternate QTD if ++ * Short Packet received - only for IN EPs ++ */ ++ unsigned a_qtd:1; ++ /** ++ * Setup Packet bit. When set indicates that buffer contains ++ * setup packet. ++ */ ++ unsigned sup:1; ++ /** Interrupt On Complete */ ++ unsigned ioc:1; ++ /** End of List */ ++ unsigned eol:1; ++ unsigned reserved27:1; ++ /** Rx/Tx Status */ ++ unsigned sts:2; ++#define DMA_DESC_STS_PKTERR 1 ++ unsigned reserved30:1; ++ /** Active Bit */ ++ unsigned a:1; ++ } b; ++ /* for isochronous */ ++ struct { ++ /** Number of bytes */ ++ unsigned n_bytes:12; ++ unsigned reserved12_24:13; ++ /** Interrupt On Complete */ ++ unsigned ioc:1; ++ unsigned reserved26_27:2; ++ /** Rx/Tx Status */ ++ unsigned sts:2; ++ unsigned reserved30:1; ++ /** Active Bit */ ++ unsigned a:1; ++ } b_isoc; ++} host_dma_desc_sts_t; ++ ++#define MAX_DMA_DESC_SIZE 131071 ++#define MAX_DMA_DESC_NUM_GENERIC 64 ++#define MAX_DMA_DESC_NUM_HS_ISOC 256 ++#define MAX_FRLIST_EN_NUM 64 ++/** ++ * Host-mode DMA Descriptor structure ++ * ++ * DMA Descriptor structure contains two quadlets: ++ * Status quadlet and Data buffer pointer. ++ */ ++typedef struct dwc_otg_host_dma_desc { ++ /** DMA Descriptor status quadlet */ ++ host_dma_desc_sts_t status; ++ /** DMA Descriptor data buffer pointer */ ++ uint32_t buf; ++} dwc_otg_host_dma_desc_t; ++ ++/** OTG Host Interface Structure. ++ * ++ * The OTG Host Interface Structure structure contains information ++ * needed to manage the DWC_otg controller acting in host mode. It ++ * represents the programming view of the host-specific aspects of the ++ * controller. ++ */ ++typedef struct dwc_otg_host_if { ++ /** Host Global Registers starting at offset 400h.*/ ++ dwc_otg_host_global_regs_t *host_global_regs; ++#define DWC_OTG_HOST_GLOBAL_REG_OFFSET 0x400 ++ ++ /** Host Port 0 Control and Status Register */ ++ volatile uint32_t *hprt0; ++#define DWC_OTG_HOST_PORT_REGS_OFFSET 0x440 ++ ++ /** Host Channel Specific Registers at offsets 500h-5FCh. */ ++ dwc_otg_hc_regs_t *hc_regs[MAX_EPS_CHANNELS]; ++#define DWC_OTG_HOST_CHAN_REGS_OFFSET 0x500 ++#define DWC_OTG_CHAN_REGS_OFFSET 0x20 ++ ++ /* Host configuration information */ ++ /** Number of Host Channels (range: 1-16) */ ++ uint8_t num_host_channels; ++ /** Periodic EPs supported (0: no, 1: yes) */ ++ uint8_t perio_eps_supported; ++ /** Periodic Tx FIFO Size (Only 1 host periodic Tx FIFO) */ ++ uint16_t perio_tx_fifo_size; ++ ++} dwc_otg_host_if_t; ++ ++/** ++ * This union represents the bit fields in the Power and Clock Gating Control ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++typedef union pcgcctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** Stop Pclk */ ++ unsigned stoppclk:1; ++ /** Gate Hclk */ ++ unsigned gatehclk:1; ++ /** Power Clamp */ ++ unsigned pwrclmp:1; ++ /** Reset Power Down Modules */ ++ unsigned rstpdwnmodule:1; ++ /** Reserved */ ++ unsigned reserved:1; ++ /** Enable Sleep Clock Gating (Enbl_L1Gating) */ ++ unsigned enbl_sleep_gating:1; ++ /** PHY In Sleep (PhySleep) */ ++ unsigned phy_in_sleep:1; ++ /** Deep Sleep*/ ++ unsigned deep_sleep:1; ++ unsigned resetaftsusp:1; ++ unsigned restoremode:1; ++ unsigned enbl_extnd_hiber:1; ++ unsigned extnd_hiber_pwrclmp:1; ++ unsigned extnd_hiber_switch:1; ++ unsigned ess_reg_restored:1; ++ unsigned prt_clk_sel:2; ++ unsigned port_power:1; ++ unsigned max_xcvrselect:2; ++ unsigned max_termsel:1; ++ unsigned mac_dev_addr:7; ++ unsigned p2hd_dev_enum_spd:2; ++ unsigned p2hd_prt_spd:2; ++ unsigned if_dev_mode:1; ++ } b; ++} pcgcctl_data_t; ++ ++/** ++ * This union represents the bit fields in the Global Data FIFO Software ++ * Configuration Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union gdfifocfg_data { ++ /* raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** OTG Data FIFO depth */ ++ unsigned gdfifocfg:16; ++ /** Start address of EP info controller */ ++ unsigned epinfobase:16; ++ } b; ++} gdfifocfg_data_t; ++ ++/** ++ * This union represents the bit fields in the Global Power Down Register ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++typedef union gpwrdn_data { ++ /* raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** PMU Interrupt Select */ ++ unsigned pmuintsel:1; ++ /** PMU Active */ ++ unsigned pmuactv:1; ++ /** Restore */ ++ unsigned restore:1; ++ /** Power Down Clamp */ ++ unsigned pwrdnclmp:1; ++ /** Power Down Reset */ ++ unsigned pwrdnrstn:1; ++ /** Power Down Switch */ ++ unsigned pwrdnswtch:1; ++ /** Disable VBUS */ ++ unsigned dis_vbus:1; ++ /** Line State Change */ ++ unsigned lnstschng:1; ++ /** Line state change mask */ ++ unsigned lnstchng_msk:1; ++ /** Reset Detected */ ++ unsigned rst_det:1; ++ /** Reset Detect mask */ ++ unsigned rst_det_msk:1; ++ /** Disconnect Detected */ ++ unsigned disconn_det:1; ++ /** Disconnect Detect mask */ ++ unsigned disconn_det_msk:1; ++ /** Connect Detected*/ ++ unsigned connect_det:1; ++ /** Connect Detected Mask*/ ++ unsigned connect_det_msk:1; ++ /** SRP Detected */ ++ unsigned srp_det:1; ++ /** SRP Detect mask */ ++ unsigned srp_det_msk:1; ++ /** Status Change Interrupt */ ++ unsigned sts_chngint:1; ++ /** Status Change Interrupt Mask */ ++ unsigned sts_chngint_msk:1; ++ /** Line State */ ++ unsigned linestate:2; ++ /** Indicates current mode(status of IDDIG signal) */ ++ unsigned idsts:1; ++ /** B Session Valid signal status*/ ++ unsigned bsessvld:1; ++ /** ADP Event Detected */ ++ unsigned adp_int:1; ++ /** Multi Valued ID pin */ ++ unsigned mult_val_id_bc:5; ++ /** Reserved 24_31 */ ++ unsigned reserved29_31:3; ++ } b; ++} gpwrdn_data_t; ++ ++#endif +diff --git a/drivers/usb/gadget/udc/hiudc/usb.h b/drivers/usb/gadget/udc/hiudc/usb.h +new file mode 100644 +index 0000000..27bda82 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc/usb.h +@@ -0,0 +1,946 @@ ++/* ++ * Copyright (c) 1998 The NetBSD Foundation, Inc. ++ * All rights reserved. ++ * ++ * This code is derived from software contributed to The NetBSD Foundation ++ * by Lennart Augustsson (lennart@augustsson.net) at ++ * Carlstedt Research & Technology. ++ * ++ * 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. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by the NetBSD ++ * Foundation, Inc. and its contributors. ++ * 4. Neither the name of The NetBSD Foundation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. ++ */ ++ ++/* Modified by Synopsys, Inc, 12/12/2007 */ ++ ++ ++#ifndef _USB_H_ ++#define _USB_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* ++ * The USB records contain some unaligned little-endian word ++ * components. The U[SG]ETW macros take care of both the alignment ++ * and endian problem and should always be used to access non-byte ++ * values. ++ */ ++typedef u_int8_t uByte; ++typedef u_int8_t uWord[2]; ++typedef u_int8_t uDWord[4]; ++ ++#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h)) ++#define UCONSTW(x) { (x) & 0xff, ((x) >> 8) & 0xff } ++#define UCONSTDW(x) { (x) & 0xff, ((x) >> 8) & 0xff, \ ++ ((x) >> 16) & 0xff, ((x) >> 24) & 0xff } ++ ++#if 1 ++#define UGETW(w) ((w)[0] | ((w)[1] << 8)) ++#define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8)) ++#define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24)) ++#define USETDW(w,v) ((w)[0] = (u_int8_t)(v), \ ++ (w)[1] = (u_int8_t)((v) >> 8), \ ++ (w)[2] = (u_int8_t)((v) >> 16), \ ++ (w)[3] = (u_int8_t)((v) >> 24)) ++#else ++/* ++ * On little-endian machines that can handle unanliged accesses ++ * (e.g. i386) these macros can be replaced by the following. ++ */ ++#define UGETW(w) (*(u_int16_t *)(w)) ++#define USETW(w,v) (*(u_int16_t *)(w) = (v)) ++#define UGETDW(w) (*(u_int32_t *)(w)) ++#define USETDW(w,v) (*(u_int32_t *)(w) = (v)) ++#endif ++ ++/* ++ * Macros for accessing UAS IU fields, which are big-endian ++ */ ++#define IUSETW2(w,h,l) ((w)[0] = (u_int8_t)(h), (w)[1] = (u_int8_t)(l)) ++#define IUCONSTW(x) { ((x) >> 8) & 0xff, (x) & 0xff } ++#define IUCONSTDW(x) { ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \ ++ ((x) >> 8) & 0xff, (x) & 0xff } ++#define IUGETW(w) (((w)[0] << 8) | (w)[1]) ++#define IUSETW(w,v) ((w)[0] = (u_int8_t)((v) >> 8), (w)[1] = (u_int8_t)(v)) ++#define IUGETDW(w) (((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3]) ++#define IUSETDW(w,v) ((w)[0] = (u_int8_t)((v) >> 24), \ ++ (w)[1] = (u_int8_t)((v) >> 16), \ ++ (w)[2] = (u_int8_t)((v) >> 8), \ ++ (w)[3] = (u_int8_t)(v)) ++ ++#define UPACKED __attribute__((__packed__)) ++ ++typedef struct { ++ uByte bmRequestType; ++ uByte bRequest; ++ uWord wValue; ++ uWord wIndex; ++ uWord wLength; ++} UPACKED usb_device_request_t; ++ ++#define UT_GET_DIR(a) ((a) & 0x80) ++#define UT_WRITE 0x00 ++#define UT_READ 0x80 ++ ++#define UT_GET_TYPE(a) ((a) & 0x60) ++#define UT_STANDARD 0x00 ++#define UT_CLASS 0x20 ++#define UT_VENDOR 0x40 ++ ++#define UT_GET_RECIPIENT(a) ((a) & 0x1f) ++#define UT_DEVICE 0x00 ++#define UT_INTERFACE 0x01 ++#define UT_ENDPOINT 0x02 ++#define UT_OTHER 0x03 ++ ++#define UT_READ_DEVICE (UT_READ | UT_STANDARD | UT_DEVICE) ++#define UT_READ_INTERFACE (UT_READ | UT_STANDARD | UT_INTERFACE) ++#define UT_READ_ENDPOINT (UT_READ | UT_STANDARD | UT_ENDPOINT) ++#define UT_WRITE_DEVICE (UT_WRITE | UT_STANDARD | UT_DEVICE) ++#define UT_WRITE_INTERFACE (UT_WRITE | UT_STANDARD | UT_INTERFACE) ++#define UT_WRITE_ENDPOINT (UT_WRITE | UT_STANDARD | UT_ENDPOINT) ++#define UT_READ_CLASS_DEVICE (UT_READ | UT_CLASS | UT_DEVICE) ++#define UT_READ_CLASS_INTERFACE (UT_READ | UT_CLASS | UT_INTERFACE) ++#define UT_READ_CLASS_OTHER (UT_READ | UT_CLASS | UT_OTHER) ++#define UT_READ_CLASS_ENDPOINT (UT_READ | UT_CLASS | UT_ENDPOINT) ++#define UT_WRITE_CLASS_DEVICE (UT_WRITE | UT_CLASS | UT_DEVICE) ++#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE) ++#define UT_WRITE_CLASS_OTHER (UT_WRITE | UT_CLASS | UT_OTHER) ++#define UT_WRITE_CLASS_ENDPOINT (UT_WRITE | UT_CLASS | UT_ENDPOINT) ++#define UT_READ_VENDOR_DEVICE (UT_READ | UT_VENDOR | UT_DEVICE) ++#define UT_READ_VENDOR_INTERFACE (UT_READ | UT_VENDOR | UT_INTERFACE) ++#define UT_READ_VENDOR_OTHER (UT_READ | UT_VENDOR | UT_OTHER) ++#define UT_READ_VENDOR_ENDPOINT (UT_READ | UT_VENDOR | UT_ENDPOINT) ++#define UT_WRITE_VENDOR_DEVICE (UT_WRITE | UT_VENDOR | UT_DEVICE) ++#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE) ++#define UT_WRITE_VENDOR_OTHER (UT_WRITE | UT_VENDOR | UT_OTHER) ++#define UT_WRITE_VENDOR_ENDPOINT (UT_WRITE | UT_VENDOR | UT_ENDPOINT) ++ ++/* Requests */ ++#define UR_GET_STATUS 0x00 ++#define USTAT_STANDARD_STATUS 0x00 ++#define WUSTAT_WUSB_FEATURE 0x01 ++#define WUSTAT_CHANNEL_INFO 0x02 ++#define WUSTAT_RECEIVED_DATA 0x03 ++#define WUSTAT_MAS_AVAILABILITY 0x04 ++#define WUSTAT_CURRENT_TRANSMIT_POWER 0x05 ++#define UR_CLEAR_FEATURE 0x01 ++#define UR_SET_FEATURE 0x03 ++#define UR_SET_AND_TEST_FEATURE 0x0c ++#define UR_SET_ADDRESS 0x05 ++#define UR_GET_DESCRIPTOR 0x06 ++#define UDESC_DEVICE 0x01 ++#define UDESC_CONFIG 0x02 ++#define UDESC_STRING 0x03 ++#define UDESC_INTERFACE 0x04 ++#define UDESC_ENDPOINT 0x05 ++#define UDESC_SS_USB_COMPANION 0x30 ++#define UDESC_DEVICE_QUALIFIER 0x06 ++#define UDESC_OTHER_SPEED_CONFIGURATION 0x07 ++#define UDESC_INTERFACE_POWER 0x08 ++#define UDESC_OTG 0x09 ++#define WUDESC_SECURITY 0x0c ++#define WUDESC_KEY 0x0d ++#define WUD_GET_KEY_INDEX(_wValue_) ((_wValue_) & 0xf) ++#define WUD_GET_KEY_TYPE(_wValue_) (((_wValue_) & 0x30) >> 4) ++#define WUD_KEY_TYPE_ASSOC 0x01 ++#define WUD_KEY_TYPE_GTK 0x02 ++#define WUD_GET_KEY_ORIGIN(_wValue_) (((_wValue_) & 0x40) >> 6) ++#define WUD_KEY_ORIGIN_HOST 0x00 ++#define WUD_KEY_ORIGIN_DEVICE 0x01 ++#define WUDESC_ENCRYPTION_TYPE 0x0e ++#define WUDESC_BOS 0x0f ++#define WUDESC_DEVICE_CAPABILITY 0x10 ++#define WUDESC_WIRELESS_ENDPOINT_COMPANION 0x11 ++#define UDESC_BOS 0x0f ++#define UDESC_DEVICE_CAPABILITY 0x10 ++#define UDESC_CS_DEVICE 0x21 /* class specific */ ++#define UDESC_CS_CONFIG 0x22 ++#define UDESC_CS_STRING 0x23 ++#define UDESC_CS_INTERFACE 0x24 ++#define UDESC_CS_ENDPOINT 0x25 ++#define UDESC_HUB 0x29 ++#define UR_SET_DESCRIPTOR 0x07 ++#define UR_GET_CONFIG 0x08 ++#define UR_SET_CONFIG 0x09 ++#define UR_GET_INTERFACE 0x0a ++#define UR_SET_INTERFACE 0x0b ++#define UR_SYNCH_FRAME 0x0c ++#define WUR_SET_ENCRYPTION 0x0d ++#define WUR_GET_ENCRYPTION 0x0e ++#define WUR_SET_HANDSHAKE 0x0f ++#define WUR_GET_HANDSHAKE 0x10 ++#define WUR_SET_CONNECTION 0x11 ++#define WUR_SET_SECURITY_DATA 0x12 ++#define WUR_GET_SECURITY_DATA 0x13 ++#define WUR_SET_WUSB_DATA 0x14 ++#define WUDATA_DRPIE_INFO 0x01 ++#define WUDATA_TRANSMIT_DATA 0x02 ++#define WUDATA_TRANSMIT_PARAMS 0x03 ++#define WUDATA_RECEIVE_PARAMS 0x04 ++#define WUDATA_TRANSMIT_POWER 0x05 ++#define WUR_LOOPBACK_DATA_WRITE 0x15 ++#define WUR_LOOPBACK_DATA_READ 0x16 ++#define WUR_SET_INTERFACE_DS 0x17 ++ ++/* Feature numbers */ ++#define UF_ENDPOINT_HALT 0 ++#define UF_DEVICE_REMOTE_WAKEUP 1 ++#define UF_TEST_MODE 2 ++#define UF_DEVICE_B_HNP_ENABLE 3 ++#define UF_DEVICE_A_HNP_SUPPORT 4 ++#define UF_DEVICE_A_ALT_HNP_SUPPORT 5 ++#define WUF_WUSB 3 ++#define WUF_TX_DRPIE 0x0 ++#define WUF_DEV_XMIT_PACKET 0x1 ++#define WUF_COUNT_PACKETS 0x2 ++#define WUF_CAPTURE_PACKETS 0x3 ++#define UF_FUNCTION_SUSPEND 0 ++#define UF_U1_ENABLE 48 ++#define UF_U2_ENABLE 49 ++#define UF_LTM_ENABLE 50 ++ ++/* Class requests from the USB 2.0 hub spec, table 11-15 */ ++#define UCR_CLEAR_HUB_FEATURE (0x2000 | UR_CLEAR_FEATURE) ++#define UCR_CLEAR_PORT_FEATURE (0x2300 | UR_CLEAR_FEATURE) ++#define UCR_GET_HUB_DESCRIPTOR (0xa000 | UR_GET_DESCRIPTOR) ++#define UCR_GET_HUB_STATUS (0xa000 | UR_GET_STATUS) ++#define UCR_GET_PORT_STATUS (0xa300 | UR_GET_STATUS) ++#define UCR_SET_HUB_FEATURE (0x2000 | UR_SET_FEATURE) ++#define UCR_SET_PORT_FEATURE (0x2300 | UR_SET_FEATURE) ++#define UCR_SET_AND_TEST_PORT_FEATURE (0xa300 | UR_SET_AND_TEST_FEATURE) ++ ++#ifdef _MSC_VER ++#include ++#endif ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDescriptorSubtype; ++} UPACKED usb_descriptor_t; ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++} UPACKED usb_descriptor_header_t; ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord bcdUSB; ++#define UD_USB_2_0 0x0200 ++#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0) ++ uByte bDeviceClass; ++ uByte bDeviceSubClass; ++ uByte bDeviceProtocol; ++ uByte bMaxPacketSize; ++ /* The fields below are not part of the initial descriptor. */ ++ uWord idVendor; ++ uWord idProduct; ++ uWord bcdDevice; ++ uByte iManufacturer; ++ uByte iProduct; ++ uByte iSerialNumber; ++ uByte bNumConfigurations; ++} UPACKED usb_device_descriptor_t; ++#define USB_DEVICE_DESCRIPTOR_SIZE 18 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wTotalLength; ++ uByte bNumInterface; ++ uByte bConfigurationValue; ++ uByte iConfiguration; ++#define UC_ATT_ONE (1 << 7) /* must be set */ ++#define UC_ATT_SELFPOWER (1 << 6) /* self powered */ ++#define UC_ATT_WAKEUP (1 << 5) /* can wakeup */ ++#define UC_ATT_BATTERY (1 << 4) /* battery powered */ ++ uByte bmAttributes; ++#define UC_BUS_POWERED 0x80 ++#define UC_SELF_POWERED 0x40 ++#define UC_REMOTE_WAKEUP 0x20 ++ uByte bMaxPower; /* max current in 2 mA units */ ++#define UC_POWER_FACTOR 2 ++} UPACKED usb_config_descriptor_t; ++#define USB_CONFIG_DESCRIPTOR_SIZE 9 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bInterfaceNumber; ++ uByte bAlternateSetting; ++ uByte bNumEndpoints; ++ uByte bInterfaceClass; ++ uByte bInterfaceSubClass; ++ uByte bInterfaceProtocol; ++ uByte iInterface; ++} UPACKED usb_interface_descriptor_t; ++#define USB_INTERFACE_DESCRIPTOR_SIZE 9 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bEndpointAddress; ++#define UE_GET_DIR(a) ((a) & 0x80) ++#define UE_SET_DIR(a,d) ((a) | (((d)&1) << 7)) ++#define UE_DIR_IN 0x80 ++#define UE_DIR_OUT 0x00 ++#define UE_ADDR 0x0f ++#define UE_GET_ADDR(a) ((a) & UE_ADDR) ++ uByte bmAttributes; ++#define UE_XFERTYPE 0x03 ++#define UE_CONTROL 0x00 ++#define UE_ISOCHRONOUS 0x01 ++#define UE_BULK 0x02 ++#define UE_INTERRUPT 0x03 ++#define UE_GET_XFERTYPE(a) ((a) & UE_XFERTYPE) ++#define UE_ISO_TYPE 0x0c ++#define UE_ISO_ASYNC 0x04 ++#define UE_ISO_ADAPT 0x08 ++#define UE_ISO_SYNC 0x0c ++#define UE_GET_ISO_TYPE(a) ((a) & UE_ISO_TYPE) ++ uWord wMaxPacketSize; ++ uByte bInterval; ++} UPACKED usb_endpoint_descriptor_t; ++#define USB_ENDPOINT_DESCRIPTOR_SIZE 7 ++ ++typedef struct ss_endpoint_companion_descriptor { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bMaxBurst; ++#define USSE_GET_MAX_STREAMS(a) ((a) & 0x1f) ++#define USSE_SET_MAX_STREAMS(a, b) ((a) | ((b) & 0x1f)) ++#define USSE_GET_MAX_PACKET_NUM(a) ((a) & 0x03) ++#define USSE_SET_MAX_PACKET_NUM(a, b) ((a) | ((b) & 0x03)) ++ uByte bmAttributes; ++ uWord wBytesPerInterval; ++} UPACKED ss_endpoint_companion_descriptor_t; ++#define USB_SS_ENDPOINT_COMPANION_DESCRIPTOR_SIZE 6 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord bString[127]; ++} UPACKED usb_string_descriptor_t; ++#define USB_MAX_STRING_LEN 128 ++#define USB_LANGUAGE_TABLE 0 /* # of the string language id table */ ++ ++/* Hub specific request */ ++#define UR_GET_BUS_STATE 0x02 ++#define UR_CLEAR_TT_BUFFER 0x08 ++#define UR_RESET_TT 0x09 ++#define UR_GET_TT_STATE 0x0a ++#define UR_STOP_TT 0x0b ++ ++/* Hub features */ ++#define UHF_C_HUB_LOCAL_POWER 0 ++#define UHF_C_HUB_OVER_CURRENT 1 ++#define UHF_PORT_CONNECTION 0 ++#define UHF_PORT_ENABLE 1 ++#define UHF_PORT_SUSPEND 2 ++#define UHF_PORT_OVER_CURRENT 3 ++#define UHF_PORT_RESET 4 ++#define UHF_PORT_L1 5 ++#define UHF_PORT_POWER 8 ++#define UHF_PORT_LOW_SPEED 9 ++#define UHF_PORT_HIGH_SPEED 10 ++#define UHF_C_PORT_CONNECTION 16 ++#define UHF_C_PORT_ENABLE 17 ++#define UHF_C_PORT_SUSPEND 18 ++#define UHF_C_PORT_OVER_CURRENT 19 ++#define UHF_C_PORT_RESET 20 ++#define UHF_C_PORT_L1 23 ++#define UHF_PORT_TEST 21 ++#define UHF_PORT_INDICATOR 22 ++ ++typedef struct { ++ uByte bDescLength; ++ uByte bDescriptorType; ++ uByte bNbrPorts; ++ uWord wHubCharacteristics; ++#define UHD_PWR 0x0003 ++#define UHD_PWR_GANGED 0x0000 ++#define UHD_PWR_INDIVIDUAL 0x0001 ++#define UHD_PWR_NO_SWITCH 0x0002 ++#define UHD_COMPOUND 0x0004 ++#define UHD_OC 0x0018 ++#define UHD_OC_GLOBAL 0x0000 ++#define UHD_OC_INDIVIDUAL 0x0008 ++#define UHD_OC_NONE 0x0010 ++#define UHD_TT_THINK 0x0060 ++#define UHD_TT_THINK_8 0x0000 ++#define UHD_TT_THINK_16 0x0020 ++#define UHD_TT_THINK_24 0x0040 ++#define UHD_TT_THINK_32 0x0060 ++#define UHD_PORT_IND 0x0080 ++ uByte bPwrOn2PwrGood; /* delay in 2 ms units */ ++#define UHD_PWRON_FACTOR 2 ++ uByte bHubContrCurrent; ++ uByte DeviceRemovable[32]; /* max 255 ports */ ++#define UHD_NOT_REMOV(desc, i) \ ++ (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1) ++ /* deprecated */ uByte PortPowerCtrlMask[1]; ++} UPACKED usb_hub_descriptor_t; ++#define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */ ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord bcdUSB; ++ uByte bDeviceClass; ++ uByte bDeviceSubClass; ++ uByte bDeviceProtocol; ++ uByte bMaxPacketSize0; ++ uByte bNumConfigurations; ++ uByte bReserved; ++} UPACKED usb_device_qualifier_t; ++#define USB_DEVICE_QUALIFIER_SIZE 10 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bmAttributes; ++#define UOTG_SRP 0x01 ++#define UOTG_HNP 0x02 ++} UPACKED usb_otg_descriptor_t; ++ ++/* OTG feature selectors */ ++#define UOTG_B_HNP_ENABLE 3 ++#define UOTG_A_HNP_SUPPORT 4 ++#define UOTG_A_ALT_HNP_SUPPORT 5 ++ ++typedef struct { ++ uWord wStatus; ++/* Device status flags */ ++#define UDS_SELF_POWERED 0x0001 ++#define UDS_REMOTE_WAKEUP 0x0002 ++/* Endpoint status flags */ ++#define UES_HALT 0x0001 ++} UPACKED usb_status_t; ++ ++typedef struct { ++ uWord wHubStatus; ++#define UHS_LOCAL_POWER 0x0001 ++#define UHS_OVER_CURRENT 0x0002 ++ uWord wHubChange; ++} UPACKED usb_hub_status_t; ++ ++typedef struct { ++ uWord wPortStatus; ++#define UPS_CURRENT_CONNECT_STATUS 0x0001 ++#define UPS_PORT_ENABLED 0x0002 ++#define UPS_SUSPEND 0x0004 ++#define UPS_OVERCURRENT_INDICATOR 0x0008 ++#define UPS_RESET 0x0010 ++#define UPS_PORT_POWER 0x0100 ++#define UPS_LOW_SPEED 0x0200 ++#define UPS_HIGH_SPEED 0x0400 ++#define UPS_PORT_TEST 0x0800 ++#define UPS_PORT_INDICATOR 0x1000 ++ uWord wPortChange; ++#define UPS_C_CONNECT_STATUS 0x0001 ++#define UPS_C_PORT_ENABLED 0x0002 ++#define UPS_C_SUSPEND 0x0004 ++#define UPS_C_OVERCURRENT_INDICATOR 0x0008 ++#define UPS_C_PORT_RESET 0x0010 ++} UPACKED usb_port_status_t; ++ ++#ifdef _MSC_VER ++#include ++#endif ++ ++/* Device class codes */ ++#define UDCLASS_IN_INTERFACE 0x00 ++#define UDCLASS_COMM 0x02 ++#define UDCLASS_HUB 0x09 ++#define UDSUBCLASS_HUB 0x00 ++#define UDPROTO_FSHUB 0x00 ++#define UDPROTO_HSHUBSTT 0x01 ++#define UDPROTO_HSHUBMTT 0x02 ++#define UDCLASS_DIAGNOSTIC 0xdc ++#define UDCLASS_WIRELESS 0xe0 ++#define UDSUBCLASS_RF 0x01 ++#define UDPROTO_BLUETOOTH 0x01 ++#define UDCLASS_VENDOR 0xff ++ ++/* Interface class codes */ ++#define UICLASS_UNSPEC 0x00 ++ ++#define UICLASS_AUDIO 0x01 ++#define UISUBCLASS_AUDIOCONTROL 1 ++#define UISUBCLASS_AUDIOSTREAM 2 ++#define UISUBCLASS_MIDISTREAM 3 ++ ++#define UICLASS_CDC 0x02 /* communication */ ++#define UISUBCLASS_DIRECT_LINE_CONTROL_MODEL 1 ++#define UISUBCLASS_ABSTRACT_CONTROL_MODEL 2 ++#define UISUBCLASS_TELEPHONE_CONTROL_MODEL 3 ++#define UISUBCLASS_MULTICHANNEL_CONTROL_MODEL 4 ++#define UISUBCLASS_CAPI_CONTROLMODEL 5 ++#define UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6 ++#define UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7 ++#define UIPROTO_CDC_AT 1 ++ ++#define UICLASS_HID 0x03 ++#define UISUBCLASS_BOOT 1 ++#define UIPROTO_BOOT_KEYBOARD 1 ++ ++#define UICLASS_PHYSICAL 0x05 ++ ++#define UICLASS_IMAGE 0x06 ++ ++#define UICLASS_PRINTER 0x07 ++#define UISUBCLASS_PRINTER 1 ++#define UIPROTO_PRINTER_UNI 1 ++#define UIPROTO_PRINTER_BI 2 ++#define UIPROTO_PRINTER_1284 3 ++ ++#define UICLASS_MASS 0x08 ++#define UISUBCLASS_RBC 1 ++#define UISUBCLASS_SFF8020I 2 ++#define UISUBCLASS_QIC157 3 ++#define UISUBCLASS_UFI 4 ++#define UISUBCLASS_SFF8070I 5 ++#define UISUBCLASS_SCSI 6 ++#define UIPROTO_MASS_CBI_I 0 ++#define UIPROTO_MASS_CBI 1 ++#define UIPROTO_MASS_BBB_OLD 2 /* Not in the spec anymore */ ++#define UIPROTO_MASS_BBB 80 /* 'P' for the Iomega Zip drive */ ++ ++#define UICLASS_HUB 0x09 ++#define UISUBCLASS_HUB 0 ++#define UIPROTO_FSHUB 0 ++#define UIPROTO_HSHUBSTT 0 /* Yes, same as previous */ ++#define UIPROTO_HSHUBMTT 1 ++ ++#define UICLASS_CDC_DATA 0x0a ++#define UISUBCLASS_DATA 0 ++#define UIPROTO_DATA_ISDNBRI 0x30 /* Physical iface */ ++#define UIPROTO_DATA_HDLC 0x31 /* HDLC */ ++#define UIPROTO_DATA_TRANSPARENT 0x32 /* Transparent */ ++#define UIPROTO_DATA_Q921M 0x50 /* Management for Q921 */ ++#define UIPROTO_DATA_Q921 0x51 /* Data for Q921 */ ++#define UIPROTO_DATA_Q921TM 0x52 /* TEI multiplexer for Q921 */ ++#define UIPROTO_DATA_V42BIS 0x90 /* Data compression */ ++#define UIPROTO_DATA_Q931 0x91 /* Euro-ISDN */ ++#define UIPROTO_DATA_V120 0x92 /* V.24 rate adaption */ ++#define UIPROTO_DATA_CAPI 0x93 /* CAPI 2.0 commands */ ++#define UIPROTO_DATA_HOST_BASED 0xfd /* Host based driver */ ++#define UIPROTO_DATA_PUF 0xfe /* see Prot. Unit Func. Desc.*/ ++#define UIPROTO_DATA_VENDOR 0xff /* Vendor specific */ ++ ++#define UICLASS_SMARTCARD 0x0b ++ ++/*#define UICLASS_FIRM_UPD 0x0c*/ ++ ++#define UICLASS_SECURITY 0x0d ++ ++#define UICLASS_DIAGNOSTIC 0xdc ++ ++#define UICLASS_WIRELESS 0xe0 ++#define UISUBCLASS_RF 0x01 ++#define UIPROTO_BLUETOOTH 0x01 ++ ++#define UICLASS_APPL_SPEC 0xfe ++#define UISUBCLASS_FIRMWARE_DOWNLOAD 1 ++#define UISUBCLASS_IRDA 2 ++#define UIPROTO_IRDA 0 ++ ++#define UICLASS_VENDOR 0xff ++ ++#define USB_HUB_MAX_DEPTH 5 ++ ++/* ++ * Minimum time a device needs to be powered down to go through ++ * a power cycle. XXX Are these time in the spec? ++ */ ++#define USB_POWER_DOWN_TIME 200 /* ms */ ++#define USB_PORT_POWER_DOWN_TIME 100 /* ms */ ++ ++#if 0 ++/* These are the values from the spec. */ ++#define USB_PORT_RESET_DELAY 10 /* ms */ ++#define USB_PORT_ROOT_RESET_DELAY 50 /* ms */ ++#define USB_PORT_RESET_RECOVERY 10 /* ms */ ++#define USB_PORT_POWERUP_DELAY 100 /* ms */ ++#define USB_SET_ADDRESS_SETTLE 2 /* ms */ ++#define USB_RESUME_DELAY (20*5) /* ms */ ++#define USB_RESUME_WAIT 10 /* ms */ ++#define USB_RESUME_RECOVERY 10 /* ms */ ++#define USB_EXTRA_POWER_UP_TIME 0 /* ms */ ++#else ++/* Allow for marginal (i.e. non-conforming) devices. */ ++#define USB_PORT_RESET_DELAY 50 /* ms */ ++#define USB_PORT_ROOT_RESET_DELAY 250 /* ms */ ++#define USB_PORT_RESET_RECOVERY 250 /* ms */ ++#define USB_PORT_POWERUP_DELAY 300 /* ms */ ++#define USB_SET_ADDRESS_SETTLE 10 /* ms */ ++#define USB_RESUME_DELAY (50*5) /* ms */ ++#define USB_RESUME_WAIT 50 /* ms */ ++#define USB_RESUME_RECOVERY 50 /* ms */ ++#define USB_EXTRA_POWER_UP_TIME 20 /* ms */ ++#endif ++ ++#define USB_MIN_POWER 100 /* mA */ ++#define USB_MAX_POWER 500 /* mA */ ++ ++#define USB_BUS_RESET_DELAY 100 /* ms XXX?*/ ++ ++#define USB_UNCONFIG_NO 0 ++#define USB_UNCONFIG_INDEX (-1) ++ ++/*** ioctl() related stuff ***/ ++ ++struct usb_ctl_request { ++ int ucr_addr; ++ usb_device_request_t ucr_request; ++ void *ucr_data; ++ int ucr_flags; ++#define USBD_SHORT_XFER_OK 0x04 /* allow short reads */ ++ int ucr_actlen; /* actual length transferred */ ++}; ++ ++struct usb_alt_interface { ++ int uai_config_index; ++ int uai_interface_index; ++ int uai_alt_no; ++}; ++ ++#define USB_CURRENT_CONFIG_INDEX (-1) ++#define USB_CURRENT_ALT_INDEX (-1) ++ ++struct usb_config_desc { ++ int ucd_config_index; ++ usb_config_descriptor_t ucd_desc; ++}; ++ ++struct usb_interface_desc { ++ int uid_config_index; ++ int uid_interface_index; ++ int uid_alt_index; ++ usb_interface_descriptor_t uid_desc; ++}; ++ ++struct usb_endpoint_desc { ++ int ued_config_index; ++ int ued_interface_index; ++ int ued_alt_index; ++ int ued_endpoint_index; ++ usb_endpoint_descriptor_t ued_desc; ++}; ++ ++struct usb_full_desc { ++ int ufd_config_index; ++ u_int ufd_size; ++ u_char *ufd_data; ++}; ++ ++struct usb_string_desc { ++ int usd_string_index; ++ int usd_language_id; ++ usb_string_descriptor_t usd_desc; ++}; ++ ++struct usb_ctl_report_desc { ++ int ucrd_size; ++ u_char ucrd_data[1024]; /* filled data size will vary */ ++}; ++ ++typedef struct { u_int32_t cookie; } usb_event_cookie_t; ++ ++#define USB_MAX_DEVNAMES 4 ++#define USB_MAX_DEVNAMELEN 16 ++struct usb_device_info { ++ u_int8_t udi_bus; ++ u_int8_t udi_addr; /* device address */ ++ usb_event_cookie_t udi_cookie; ++ char udi_product[USB_MAX_STRING_LEN]; ++ char udi_vendor[USB_MAX_STRING_LEN]; ++ char udi_release[8]; ++ u_int16_t udi_productNo; ++ u_int16_t udi_vendorNo; ++ u_int16_t udi_releaseNo; ++ u_int8_t udi_class; ++ u_int8_t udi_subclass; ++ u_int8_t udi_protocol; ++ u_int8_t udi_config; ++ u_int8_t udi_speed; ++#define USB_SPEED_UNKNOWN 0 ++#define USB_SPEED_LOW 1 ++#define USB_SPEED_FULL 2 ++#define USB_SPEED_HIGH 3 ++#define USB_SPEED_VARIABLE 4 ++#define USB_SPEED_SUPER 5 ++ int udi_power; /* power consumption in mA, 0 if selfpowered */ ++ int udi_nports; ++ char udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN]; ++ u_int8_t udi_ports[16];/* hub only: addresses of devices on ports */ ++#define USB_PORT_ENABLED 0xff ++#define USB_PORT_SUSPENDED 0xfe ++#define USB_PORT_POWERED 0xfd ++#define USB_PORT_DISABLED 0xfc ++}; ++ ++struct usb_ctl_report { ++ int ucr_report; ++ u_char ucr_data[1024]; /* filled data size will vary */ ++}; ++ ++struct usb_device_stats { ++ u_long uds_requests[4]; /* indexed by transfer type UE_* */ ++}; ++ ++#define WUSB_MIN_IE 0x80 ++#define WUSB_WCTA_IE 0x80 ++#define WUSB_WCONNECTACK_IE 0x81 ++#define WUSB_WHOSTINFO_IE 0x82 ++#define WUHI_GET_CA(_bmAttributes_) ((_bmAttributes_) & 0x3) ++#define WUHI_CA_RECONN 0x00 ++#define WUHI_CA_LIMITED 0x01 ++#define WUHI_CA_ALL 0x03 ++#define WUHI_GET_MLSI(_bmAttributes_) (((_bmAttributes_) & 0x38) >> 3) ++#define WUSB_WCHCHANGEANNOUNCE_IE 0x83 ++#define WUSB_WDEV_DISCONNECT_IE 0x84 ++#define WUSB_WHOST_DISCONNECT_IE 0x85 ++#define WUSB_WRELEASE_CHANNEL_IE 0x86 ++#define WUSB_WWORK_IE 0x87 ++#define WUSB_WCHANNEL_STOP_IE 0x88 ++#define WUSB_WDEV_KEEPALIVE_IE 0x89 ++#define WUSB_WISOCH_DISCARD_IE 0x8A ++#define WUSB_WRESETDEVICE_IE 0x8B ++#define WUSB_WXMIT_PACKET_ADJUST_IE 0x8C ++#define WUSB_MAX_IE 0x8C ++ ++/* Device Notification Types */ ++ ++#define WUSB_DN_MIN 0x01 ++#define WUSB_DN_CONNECT 0x01 ++# define WUSB_DA_OLDCONN 0x00 ++# define WUSB_DA_NEWCONN 0x01 ++# define WUSB_DA_SELF_BEACON 0x02 ++# define WUSB_DA_DIR_BEACON 0x04 ++# define WUSB_DA_NO_BEACON 0x06 ++#define WUSB_DN_DISCONNECT 0x02 ++#define WUSB_DN_EPRDY 0x03 ++#define WUSB_DN_MASAVAILCHANGED 0x04 ++#define WUSB_DN_REMOTEWAKEUP 0x05 ++#define WUSB_DN_SLEEP 0x06 ++#define WUSB_DN_ALIVE 0x07 ++#define WUSB_DN_MAX 0x07 ++ ++#ifdef _MSC_VER ++#include ++#endif ++ ++/* WUSB Handshake Data. Used during the SET/GET HANDSHAKE requests */ ++typedef struct wusb_hndshk_data { ++ uByte bMessageNumber; ++ uByte bStatus; ++ uByte tTKID[3]; ++ uByte bReserved; ++ uByte CDID[16]; ++ uByte Nonce[16]; ++ uByte MIC[8]; ++} UPACKED wusb_hndshk_data_t; ++#define WUSB_HANDSHAKE_LEN_FOR_MIC 38 ++ ++/* WUSB Connection Context */ ++typedef struct wusb_conn_context { ++ uByte CHID [16]; ++ uByte CDID [16]; ++ uByte CK [16]; ++} UPACKED wusb_conn_context_t; ++ ++/* WUSB Security Descriptor */ ++typedef struct wusb_security_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wTotalLength; ++ uByte bNumEncryptionTypes; ++} UPACKED wusb_security_desc_t; ++ ++/* WUSB Encryption Type Descriptor */ ++typedef struct wusb_encrypt_type_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ ++ uByte bEncryptionType; ++#define WUETD_UNSECURE 0 ++#define WUETD_WIRED 1 ++#define WUETD_CCM_1 2 ++#define WUETD_RSA_1 3 ++ ++ uByte bEncryptionValue; ++ uByte bAuthKeyIndex; ++} UPACKED wusb_encrypt_type_desc_t; ++ ++/* WUSB Key Descriptor */ ++typedef struct wusb_key_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte tTKID[3]; ++ uByte bReserved; ++ uByte KeyData[1]; /* variable length */ ++} UPACKED wusb_key_desc_t; ++ ++/* WUSB BOS Descriptor (Binary device Object Store) */ ++typedef struct wusb_bos_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wTotalLength; ++ uByte bNumDeviceCaps; ++} UPACKED wusb_bos_desc_t; ++ ++#define USB_DEVICE_CAPABILITY_20_EXTENSION 0x02 ++typedef struct usb_dev_cap_20_ext_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++#define USB_20_EXT_LPM 0x02 ++ uDWord bmAttributes; ++} UPACKED usb_dev_cap_20_ext_desc_t; ++ ++#define USB_DEVICE_CAPABILITY_SS_USB 0x03 ++typedef struct usb_dev_cap_ss_usb { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++#define USB_DC_SS_USB_LTM_CAPABLE 0x02 ++ uByte bmAttributes; ++#define USB_DC_SS_USB_SPEED_SUPPORT_LOW 0x01 ++#define USB_DC_SS_USB_SPEED_SUPPORT_FULL 0x02 ++#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH 0x04 ++#define USB_DC_SS_USB_SPEED_SUPPORT_SS 0x08 ++ uWord wSpeedsSupported; ++ uByte bFunctionalitySupport; ++ uByte bU1DevExitLat; ++ uWord wU2DevExitLat; ++} UPACKED usb_dev_cap_ss_usb_t; ++ ++#define USB_DEVICE_CAPABILITY_CONTAINER_ID 0x04 ++typedef struct usb_dev_cap_container_id { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++ uByte bReserved; ++ uByte containerID[16]; ++} UPACKED usb_dev_cap_container_id_t; ++ ++/* Device Capability Type Codes */ ++#define WUSB_DEVICE_CAPABILITY_WIRELESS_USB 0x01 ++ ++/* Device Capability Descriptor */ ++typedef struct wusb_dev_cap_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++ uByte caps[1]; /* Variable length */ ++} UPACKED wusb_dev_cap_desc_t; ++ ++/* Device Capability Descriptor */ ++typedef struct wusb_dev_cap_uwb_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++ uByte bmAttributes; ++ uWord wPHYRates; /* Bitmap */ ++ uByte bmTFITXPowerInfo; ++ uByte bmFFITXPowerInfo; ++ uWord bmBandGroup; ++ uByte bReserved; ++} UPACKED wusb_dev_cap_uwb_desc_t; ++ ++/* Wireless USB Endpoint Companion Descriptor */ ++typedef struct wusb_endpoint_companion_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bMaxBurst; ++ uByte bMaxSequence; ++ uWord wMaxStreamDelay; ++ uWord wOverTheAirPacketSize; ++ uByte bOverTheAirInterval; ++ uByte bmCompAttributes; ++} UPACKED wusb_endpoint_companion_desc_t; ++ ++/* Wireless USB Numeric Association M1 Data Structure */ ++typedef struct wusb_m1_data { ++ uByte version; ++ uWord langId; ++ uByte deviceFriendlyNameLength; ++ uByte sha_256_m3[32]; ++ uByte deviceFriendlyName[256]; ++} UPACKED wusb_m1_data_t; ++ ++typedef struct wusb_m2_data { ++ uByte version; ++ uWord langId; ++ uByte hostFriendlyNameLength; ++ uByte pkh[384]; ++ uByte hostFriendlyName[256]; ++} UPACKED wusb_m2_data_t; ++ ++typedef struct wusb_m3_data { ++ uByte pkd[384]; ++ uByte nd; ++} UPACKED wusb_m3_data_t; ++ ++typedef struct wusb_m4_data { ++ uDWord _attributeTypeIdAndLength_1; ++ uWord associationTypeId; ++ ++ uDWord _attributeTypeIdAndLength_2; ++ uWord associationSubTypeId; ++ ++ uDWord _attributeTypeIdAndLength_3; ++ uDWord length; ++ ++ uDWord _attributeTypeIdAndLength_4; ++ uDWord associationStatus; ++ ++ uDWord _attributeTypeIdAndLength_5; ++ uByte chid[16]; ++ ++ uDWord _attributeTypeIdAndLength_6; ++ uByte cdid[16]; ++ ++ uDWord _attributeTypeIdAndLength_7; ++ uByte bandGroups[2]; ++} UPACKED wusb_m4_data_t; ++ ++#ifdef _MSC_VER ++#include ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _USB_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc3/Kconfig b/drivers/usb/gadget/udc/hiudc3/Kconfig +new file mode 100644 +index 0000000..dc4c087 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/Kconfig +@@ -0,0 +1,44 @@ ++# ++# hisilicon usb2 device controller version 3.00a ++# ++ ++menuconfig HI_SS_DEVICE ++ tristate "hisilicon usb3 device controller version 2.50a driver" ++ default n ++ select USB_GADGET_DUALSPEED ++ select USB_GADGET_SELECTED ++ help ++ hisilicon usb3 device controller version 3.00a. ++ ++if HI_SS_DEVICE ++ ++config HIUSB_XHCI_REG_BASE_ADDRESS ++ hex "hiusb3dev system control register base address" ++ default "0xf98a0000" if ARCH_S40 ++ default "0x60180000" if ARCH_GODBOX ++ default "0x10180000" if ARCH_HI3519 ++ default "0x10180000" if ARCH_HI3519V101 ++ default "0x10180000" if ARCH_HI3559 ++ default "0x10180000" if ARCH_HI3556 ++ default "0x10180000" if ARCH_HI3516AV200 ++ ++config HIUSB_XHCI_REG_BASE_ADDRESS_LEN ++ hex "hiusb3dev system control register size length" ++ default "0x10000" if ARCH_S40 ++ default "0x10000" if ARCH_GODBOX ++ default "0x10000" if ARCH_HI3519 ++ default "0x10000" if ARCH_HI3519V101 ++ default "0x10000" if ARCH_HI3559 ++ default "0x10000" if ARCH_HI3556 ++ default "0x10000" if ARCH_HI3516AV200 ++ ++config HIUSB_XHCI_IRQ_NUMBER ++ int "hiusb3dev system control register interrupt number" ++ default "100" if ARCH_S40 ++ default "103" if ARCH_GODBOX ++ default "54" if ARCH_HI3519 ++ default "54" if ARCH_HI3519V101 ++ default "54" if ARCH_HI3559 ++ default "54" if ARCH_HI3556 ++ default "54" if ARCH_HI3516AV200 ++endif # HI_SS_DEVICE +diff --git a/drivers/usb/gadget/udc/hiudc3/Makefile b/drivers/usb/gadget/udc/hiudc3/Makefile +new file mode 100644 +index 0000000..094fdbd +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/Makefile +@@ -0,0 +1,99 @@ ++# ++# Makefile for DWC_usb3 SuperSpeed USB controller driver ++# ++ ++ifneq ($(KERNELRELEASE),) ++ ++# This line is required for 2.6.37 era kernels, or else files in ++# subdirectories won't compile ++EXTRA_CFLAGS += -I$(KBUILD_EXTMOD) ++ ++ifneq ($(NOOS),) ++EXTRA_CFLAGS += -DLINUXTEST ++else ++ifneq ($(SELA),) ++EXTRA_CFLAGS += -DLINUXTEST ++else ++ifneq ($(PLATFORM),) ++EXTRA_CFLAGS += -DDWC_PLATFORM_DEV ++endif ++endif ++endif ++ ++# Uncomment these for debug messages ++EXTRA_CFLAGS += -DDEBUG ++EXTRA_CFLAGS += -DVERBOSE ++EXTRA_CFLAGS += -DDEBUG_EP0 ++ ++# Uncomment this, and comment out the previous 3, for minimal debug for ISOC ++#EXTRA_CFLAGS += -DISOC_DEBUG ++ ++# Uncomment to force gasket regs to be accessed in BAR 2. Not needed if the ++# PCI device ID is 0xabce. ++#EXTRA_CFLAGS += -DDWC_BAR2_GASKET_REG ++ ++# Uncomment for OTG ++#EXTRA_CFLAGS += -DCONFIG_USB_OTG_DWC ++ ++# Uncomment for SSIC ++#EXTRA_CFLAGS += -DSSIC ++ ++# Uncomment this to support the UTE gadget, and also uncomment the line with ++# "dwc_usb3-objs += linux/ute_if.o" below ++#EXTRA_CFLAGS += -DDWC_UTE -I$(KBUILD_SRC)/../UTE-3.0/common -I$(KBUILD_EXTMOD)/../UTE-3.0/common ++ ++#EXTRA_CFLAGS += -DDWC_ISOC_INTR_MODERATION ++#EXTRA_CFLAGS += -DDWC_TEST_ISOC_CHAIN ++#EXTRA_CFLAGS += -DLECROY ++ ++#EXTRA_CFLAGS += -DDWC_STAR_9000446947_WORKAROUND ++#EXTRA_CFLAGS += -DDWC_STAR_9000449814_WORKAROUND ++#EXTRA_CFLAGS += -DDWC_STAR_9000459034_WORKAROUND ++#EXTRA_CFLAGS += -DDWC_STAR_9000463548_WORKAROUND ++#EXTRA_CFLAGS += -DDWC_STAR_9000468158_WORKAROUND ++#EXTRA_CFLAGS += -DDWC_STAR_9000483510_WORKAROUND ++ ++#obj-m := dwc_usb3.o ++obj-$(CONFIG_USB_HISI_UDC3) := dwc_usb3.o ++ ++dwc_usb3-objs := cil.o cil_intr.o ++dwc_usb3-objs += pcd.o pcd_intr.o pcd_hiber.o ep0.o ++#dwc_usb3-objs += hiusb3.o ++ ++ifneq ($(NOOS),) ++dwc_usb3-objs += no_os/no_os_init.o no_os/no_os_hiber.o no_os/no_os_ep0.o ++dwc_usb3-objs += no_os/no_os_gadget.o no_os/no_os_src_sink_lpbk.o ++else ++ifneq ($(SELA),) ++dwc_usb3-objs += sela/sela_bm_defs.o sela/sela_driver.o sela/sela_ep0.o ++dwc_usb3-objs += sela/sela_funcs.o sela/sela_gadget.o ++else ++dwc_usb3-objs += linux_gadget.o linux_hiber.o linux_sysfs.o ++#ifneq ($(PLATFORM),) ++dwc_usb3-objs += linux_plat.o ++#else ++#dwc_usb3-objs += linux/linux_pci.o ++#endif ++endif ++endif ++ ++# Uncomment this to support the UTE gadget, and also uncomment the line with ++# "-DDWC_UTE" above ++#dwc_usb3-objs += linux/ute_if.o ++ ++else ++endif ++ ++#ifneq ($(NOOS),) ++# ln -s no_os/no_os_defs.h os_defs.h ++# ln -s no_os/no_os_dev.h os_dev.h ++#else ++#ifneq ($(SELA),) ++# ln -s sela/sela_defs.h os_defs.h ++# ln -s sela/sela_dev.h os_dev.h ++#else ++# ln -s linux/linux_defs.h os_defs.h ++# ln -s linux/linux_dev.h os_dev.h ++# ln -s linux/ute_if.h ute_if.h ++#endif ++#endif +diff --git a/drivers/usb/gadget/udc/hiudc3/Makefile.no_os b/drivers/usb/gadget/udc/hiudc3/Makefile.no_os +new file mode 100644 +index 0000000..b0074d4 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/Makefile.no_os +@@ -0,0 +1,84 @@ ++# ++# Makefile for DWC_usb3 SuperSpeed USB controller driver ++# ++ ++CFLAGS := -O2 -Wall -Wno-pointer-sign -g -I. ++LDFLAGS := -g ++ ++CFLAGS += -DTESTCOMPILE ++ ++# Uncomment these for debug messages ++CFLAGS += -DDEBUG ++CFLAGS += -DVERBOSE ++CFLAGS += -DDEBUG_EP0 ++ ++# Uncomment this, and comment out the previous 3, for minimal debug for ISOC ++#CFLAGS += -DISOC_DEBUG ++ ++# Uncomment this to enable Bulk Streams, to support the UASP gadget ++CFLAGS += -DDWC_UASP_GADGET_STREAMS ++ ++# Uncomment this to support the UTE gadget, and also uncomment the line with ++# "dwc_usb3-objs += ute_if.o" below ++#CFLAGS += -DDWC_UTE -I$(KBUILD_SRC)/../UTE-3.0/common ++ ++#CFLAGS += -DDWC_ISOC_INTR_MODERATION ++#CFLAGS += -DDWC_TEST_ISOC_CHAIN ++#CFLAGS += -DLECROY ++ ++#CFLAGS += -DDWC_STAR_9000446947_WORKAROUND ++#CFLAGS += -DDWC_STAR_9000449814_WORKAROUND ++#CFLAGS += -DDWC_STAR_9000459034_WORKAROUND ++#CFLAGS += -DDWC_STAR_9000463548_WORKAROUND ++#CFLAGS += -DDWC_STAR_9000468158_WORKAROUND ++#CFLAGS += -DDWC_STAR_9000483510_WORKAROUND ++ ++obj-m := dwc_usb3 ++ ++dwc_usb3-objs := cil.o cil_intr.o ++dwc_usb3-objs += pcd.o pcd_intr.o pcd_hiber.o ep0.o ++dwc_usb3-objs += no_os/no_os_init.o no_os/no_os_hiber.o no_os/no_os_ep0.o ++dwc_usb3-objs += no_os/no_os_gadget.o no_os/no_os_src_sink_lpbk.o ++ ++# Uncomment this to support the UTE gadget, and also uncomment the line with ++# "-DDWC_UTE" above ++#dwc_usb3-objs += ute_if.o ++ ++PWD := $(shell pwd) ++ ++# Command paths ++CTAGS := /usr/bin/ctags ++DOXYGEN := /depot/doxygen-1.5.8/bin/doxygen ++ ++default: all ++ ++docs: ++ cd doc ; \ ++ $(DOXYGEN) ; \ ++ cp doxygen.sty latex/ ; \ ++ cp synopsys.eps latex/ ; \ ++ cp synopsys.pdf latex/ ; \ ++ make -C latex/ ; \ ++ cd .. ++ ++tags: $(wildcard *.[ch]) ++ $(CTAGS) -e $(wildcard *.[ch]) $(wildcard linux/*.[ch]) \ ++ $(wildcard $(KDIR)/include/linux/usb*.h) ++ ++driver: links $(obj-m) ++ ++$(obj-m): $(dwc_usb3-objs) ++ $(CC) $(LDFLAGS) -o $(obj-m) $(dwc_usb3-objs) ++ ++links: ++ rm -f os_defs.h os_dev.h ++ ln -s no_os/no_os_defs.h os_defs.h ++ ln -s no_os/no_os_dev.h os_dev.h ++ ++clean: ++ rm -rf $(obj-m) *.o no_os/*.o ++ ++cleanall: clean ++ rm -rf doc/html doc/latex doc/rtf ++ ++all: driver +diff --git a/drivers/usb/gadget/udc/hiudc3/cil.c b/drivers/usb/gadget/udc/hiudc3/cil.c +new file mode 100644 +index 0000000..66601ac +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/cil.c +@@ -0,0 +1,2066 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/DWC_usb3/driver/cil.c $ ++ * $Revision: #110 $ ++ * $Date: 2014/11/11 $ ++ * $Change: 2664766 $ ++ * ++ * Synopsys SS USB3 Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ * The Core Interface Layer provides basic services for accessing and ++ * managing the DWC_usb3 hardware. These services are used by both the ++ * Peripheral Controller Driver and the On The Go Driver. ++ * ++ * The CIL manages the memory map for the core so that the PCD and OTG drivers ++ * don't have to do this separately. The CIL also performs basic services ++ * that are not specific to either the Device or OTG modes of operation. ++ * These services include all functionality that requires specific ++ * knowledge of the CSR layout or the DMA descriptor (TRB) layout. Also ++ * included are services for invoking each of the commands provided by ++ * the DGCMD and DEPCMD registers (see the "Control and Status Registers" ++ * chapter of the USB3 controller databook for details). ++ * ++ * The Core Interface Layer has the following requirements: ++ * - Provides basic controller operations. ++ * - Minimal use of OS services. ++ * - The OS services used will be abstracted by using inline functions ++ * or macros. ++ * ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++ ++/** ++ * Fill in the four dwords of a DMA descriptor (aka a TRB). ++ */ ++void dwc_usb3_fill_desc(dwc_usb3_dma_desc_t *desc, dwc_dma_t dma_addr, ++ u32 dma_len, u32 stream, u32 type, ++ u32 ctrlbits, int own) ++{ ++ desc->bptl = (u32)(dma_addr & 0xffffffffU); ++#ifdef DWC_64_BIT_ARCH ++ desc->bpth = (u32)(dma_addr >> 32U & 0xffffffffU); ++#else ++ desc->bpth = 0; ++#endif ++ desc->status = dma_len << DWC_DSCSTS_XFRCNT_SHIFT; ++ ++ /* Note: If type is 0, leave original control bits intact (for isoc) */ ++ if (type) ++ desc->control = type << DWC_DSCCTL_TRBCTL_SHIFT; ++ ++ desc->control |= stream << DWC_DSCCTL_STRMID_SOFN_SHIFT | ctrlbits; ++ ++ /* Must do this last! */ ++ if (own) { ++ wmb(); ++ desc->control |= DWC_DSCCTL_HWO_BIT; ++ } ++} ++ ++/** ++ * Make a DMA descriptor the start of a chain by setting its CHN bit and ++ * clearing its IOC bit. ++ * ++ * @param desc The DMA descriptor (TRB) to operate on. ++ */ ++void dwc_usb3_start_desc_chain(dwc_usb3_dma_desc_t *desc) ++{ ++ desc->control |= DWC_DSCCTL_CHN_BIT; ++ desc->control &= ~DWC_DSCCTL_IOC_BIT; ++} ++ ++/** ++ * Make a DMA descriptor the end of a chain by clearing its CHN bit and ++ * setting its IOC bit. ++ * ++ * @param desc The DMA descriptor (TRB) to operate on. ++ */ ++void dwc_usb3_end_desc_chain(dwc_usb3_dma_desc_t *desc) ++{ ++ desc->control &= ~DWC_DSCCTL_CHN_BIT; ++ desc->control |= DWC_DSCCTL_IOC_BIT; ++} ++ ++/** ++ * Enable a DMA descriptor by setting its HWO bit. ++ * ++ * @param desc The DMA descriptor (TRB) to operate on. ++ */ ++void dwc_usb3_enable_desc(dwc_usb3_dma_desc_t *desc) ++{ ++ wmb(); ++ desc->control |= DWC_DSCCTL_HWO_BIT; ++} ++ ++/** ++ * Disable a DMA descriptor by clearing its HWO bit. ++ * ++ * NOTE: This must only be called if it is known that the hardware has finished ++ * with the DMA descriptor, but for some reason the hardware has not cleared ++ * the HWO bit. ++ * ++ * @param desc The DMA descriptor (TRB) to operate on. ++ */ ++void dwc_usb3_disable_desc(dwc_usb3_dma_desc_t *desc) ++{ ++ desc->control &= ~DWC_DSCCTL_HWO_BIT; ++ wmb(); ++} ++ ++/** ++ * Spin on register bit until handshake completes or times out. ++ * ++ * @param dev Programming view of DWC_usb3 controller. ++ * @param ptr Address of register to read. ++ * @param mask Bit to look at in result of read. ++ * @param done Value of the bit when handshake succeeds. ++ * @return 1 when the mask bit has the specified value (handshake done), ++ * 0 when timeout has passed (handshake failed). ++ */ ++static int _handshake(dwc_usb3_device_t *dev, volatile u32 __iomem *ptr, ++ u32 mask, u32 done) ++{ ++ u32 usec = 100000; ++ u32 result; ++ ++ dwc_debug1(dev, "%s()\n", __func__); ++ ++ do { ++ result = dwc_rd32(dev, ptr); ++ if ((result & mask) == done) { ++ dwc_debug1(dev, "after DEPCMD=%08x\n", result); ++ return 1; ++ } ++ ++ dwc_udelay(dev, 1); ++ usec -= 1; ++ } while (usec > 0); ++ ++ return 0; ++} ++ ++/* ++ * Routines for sending the various Device commands to the hardware. ++ * See description of DGCMD register in "Control and Status Registers" ++ * section of the USB3 controller databook. ++ */ ++ ++/** ++ * Send TRANSMIT FUNCTION WAKE DEVICE NOTIFICATION command to Device ++ */ ++int dwc_usb3_xmit_fn_remote_wake(dwc_usb3_pcd_t *pcd, u32 intf) ++{ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ ++ /* Use the generic Transmit Device Notification command if the core ++ * supports it ++ */ ++ if (pcd->usb3_dev->snpsid >= 0x5533210a) { ++ /* Set param */ ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dgcmdpar, ++ intf << DWC_DGCMDPAR_DEV_NOTIF_PARAM_SHIFT | ++ DWC_DGCMD_FUNCTION_WAKE_DEV_NOTIF); ++ dwc_debug1(pcd->usb3_dev, "DGCMDPAR=%08x\n", ++ intf << DWC_DGCMDPAR_DEV_NOTIF_PARAM_SHIFT | ++ DWC_DGCMD_FUNCTION_WAKE_DEV_NOTIF); ++ ++ /* Start the command */ ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dgcmd, ++ DWC_DGCMD_XMIT_DEV_NOTIF | DWC_DGCMD_ACT_BIT); ++ dwc_debug1(pcd->usb3_dev, "DGCMD=%08x\n", ++ DWC_DGCMD_XMIT_DEV_NOTIF | DWC_DGCMD_ACT_BIT); ++ } else { ++ /* Set param */ ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dgcmdpar, intf); ++ dwc_debug1(pcd->usb3_dev, "DGCMDPAR=%08x\n", intf); ++ ++ /* Start the command */ ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dgcmd, ++ DWC_DGCMD_XMIT_FUNC_WAKE_DEV_NOTIF | DWC_DGCMD_ACT_BIT); ++ dwc_debug1(pcd->usb3_dev, "DGCMD=%08x\n", ++ DWC_DGCMD_XMIT_FUNC_WAKE_DEV_NOTIF | DWC_DGCMD_ACT_BIT); ++ } ++ ++ /* Wait for command completion */ ++ handshake(pcd->usb3_dev, &pcd->dev_global_regs->dgcmd, ++ DWC_DGCMD_ACT_BIT, 0); ++ ++ return 0; ++} ++ ++/** ++ * Send LATENCY TOLERANCE MESSAGE DEVICE NOTIFICATION command to Device ++ */ ++int dwc_usb3_xmit_ltm(dwc_usb3_pcd_t *pcd, u32 value) ++{ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ ++ /* Use the generic Transmit Device Notification command if the core ++ * supports it. Otherwise this function is a no-op. ++ */ ++ if (pcd->usb3_dev->snpsid >= 0x5533210a) { ++ /* Set param */ ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dgcmdpar, ++ value << DWC_DGCMDPAR_DEV_NOTIF_PARAM_SHIFT | ++ DWC_DGCMD_LATENCY_TOL_DEV_NOTIF); ++ dwc_debug1(pcd->usb3_dev, "DGCMDPAR=%08x\n", ++ value << DWC_DGCMDPAR_DEV_NOTIF_PARAM_SHIFT | ++ DWC_DGCMD_LATENCY_TOL_DEV_NOTIF); ++ ++ /* Start the command */ ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dgcmd, ++ DWC_DGCMD_XMIT_DEV_NOTIF | DWC_DGCMD_ACT_BIT); ++ dwc_debug1(pcd->usb3_dev, "DGCMD=%08x\n", ++ DWC_DGCMD_XMIT_DEV_NOTIF | DWC_DGCMD_ACT_BIT); ++ ++ /* Wait for command completion */ ++ handshake(pcd->usb3_dev, &pcd->dev_global_regs->dgcmd, ++ DWC_DGCMD_ACT_BIT, 0); ++ } ++ ++ return 0; ++} ++ ++#ifdef CONFIG_USB_OTG_DWC ++/** ++ * Send ROLE REQUEST DEVICE NOTIFICATION command to Device ++ */ ++int dwc_usb3_xmit_host_role_request(dwc_usb3_pcd_t *pcd, u32 param) ++{ ++#ifdef DEBUG ++ char *type = "UNKNOWN"; ++ ++ if (param == DWC_DGCMDPAR_HOST_ROLE_REQ_INITIATE) ++ type = "INITIATE"; ++ else if (param == DWC_DGCMDPAR_HOST_ROLE_REQ_CONFIRM) ++ type = "CONFIRM"; ++ ++ dwc_debug2(pcd->usb3_dev, "%s() - %s\n", __func__, type); ++#endif ++ ++ /* Use the generic Transmit Device Notification command if the core ++ * supports it ++ */ ++ if (pcd->usb3_dev->snpsid >= 0x5533210a) { ++ /* Set param */ ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dgcmdpar, ++ param << DWC_DGCMDPAR_DEV_NOTIF_PARAM_SHIFT | ++ DWC_DGCMD_HOST_ROLE_REQ_DEV_NOTIF); ++ dwc_debug1(pcd->usb3_dev, "DGCMDPAR=%08x\n", ++ param << DWC_DGCMDPAR_DEV_NOTIF_PARAM_SHIFT | ++ DWC_DGCMD_HOST_ROLE_REQ_DEV_NOTIF); ++ ++ /* Start the command */ ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dgcmd, ++ DWC_DGCMD_XMIT_DEV_NOTIF | DWC_DGCMD_ACT_BIT); ++ dwc_debug1(pcd->usb3_dev, "DGCMD=%08x\n", ++ DWC_DGCMD_XMIT_DEV_NOTIF | DWC_DGCMD_ACT_BIT); ++ } else { ++ /* Set param */ ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dgcmdpar, param); ++ dwc_debug1(pcd->usb3_dev, "DGCMDPAR=%08x\n", param); ++ ++ /* Start the command */ ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dgcmd, ++ DWC_DGCMD_XMIT_HOST_ROLE_REQUEST | DWC_DGCMD_ACT_BIT); ++ ++ dwc_debug1(pcd->usb3_dev, "DGCMD=%08x\n", ++ DWC_DGCMD_XMIT_HOST_ROLE_REQUEST | DWC_DGCMD_ACT_BIT); ++ } ++ ++ /* Wait for command completion */ ++ handshake(pcd->usb3_dev, &pcd->dev_global_regs->dgcmd, ++ DWC_DGCMD_ACT_BIT, 0); ++ ++ return 0; ++} ++#endif ++ ++/** ++ * Send SET SCRATCHPAD BUFFER ARRAY command to Device ++ */ ++int dwc_usb3_set_scratchpad_buf_array(dwc_usb3_pcd_t *pcd, dwc_dma_t dma_addr) ++{ ++ dwc_debug2(pcd->usb3_dev, "%s(%lx)\n", __func__, ++ (unsigned long)dma_addr); ++ ++ /* Set param */ ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dgcmdpar, ++ dma_addr & 0xffffffffU); ++ dwc_debug1(pcd->usb3_dev, "DGCMDPAR=%08lx\n", ++ (unsigned long)(dma_addr & 0xffffffffU)); ++ ++ /* Start the command */ ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dgcmd, ++ DWC_DGCMD_SET_SCRATCHPAD_ARRAY_ADR_LO | DWC_DGCMD_ACT_BIT); ++ dwc_debug1(pcd->usb3_dev, "DGCMD=%08x\n", ++ DWC_DGCMD_SET_SCRATCHPAD_ARRAY_ADR_LO | DWC_DGCMD_ACT_BIT); ++ ++ /* Wait for command completion */ ++ handshake(pcd->usb3_dev, &pcd->dev_global_regs->dgcmd, ++ DWC_DGCMD_ACT_BIT, 0); ++ ++ return 0; ++} ++ ++/** ++ * Send SELECTED FIFO FLUSH command to Device ++ */ ++int dwc_usb3_flush_fifo(dwc_usb3_pcd_t *pcd, u32 fifo_sel) ++{ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ ++ /* Set param */ ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dgcmdpar, fifo_sel); ++ dwc_debug1(pcd->usb3_dev, "DGCMDPAR=%08x\n", fifo_sel); ++ ++ /* Start the command */ ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dgcmd, ++ DWC_DGCMD_SELECTED_FIFO_FLUSH | DWC_DGCMD_ACT_BIT); ++ dwc_debug1(pcd->usb3_dev, "DGCMD=%08x\n", ++ DWC_DGCMD_SELECTED_FIFO_FLUSH | DWC_DGCMD_ACT_BIT); ++ ++ /* Wait for command completion */ ++ handshake(pcd->usb3_dev, &pcd->dev_global_regs->dgcmd, ++ DWC_DGCMD_ACT_BIT, 0); ++ ++ return 0; ++} ++ ++/* ++ * Routines for sending the various Endpoint commands to the hardware. ++ * See description of DEPCMDn register in "Control and Status Registers" ++ * section of the USB3 controller databook. ++ */ ++ ++/** ++ * Send DEPCFG command to EP ++ */ ++int dwc_usb3_dep_cfg(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, ++ u32 depcfg0, u32 depcfg1, u32 depcfg2) ++{ ++ dwc_debug1(pcd->usb3_dev, "dep_cfg, ep_reg=%lx\n", ++ (unsigned long)ep_reg); ++ ++ /* Set param 2 */ ++ dwc_wr32(pcd->usb3_dev, &ep_reg->depcmdpar2, depcfg2); ++ dwc_debug1(pcd->usb3_dev, "DEPCFG2=%08x\n", depcfg2); ++ ++ /* Set param 1 */ ++ dwc_wr32(pcd->usb3_dev, &ep_reg->depcmdpar1, depcfg1); ++ dwc_debug1(pcd->usb3_dev, "DEPCFG1=%08x\n", depcfg1); ++ ++ /* Set param 0 */ ++ dwc_wr32(pcd->usb3_dev, &ep_reg->depcmdpar0, depcfg0); ++ dwc_debug1(pcd->usb3_dev, "DEPCFG0=%08x\n", depcfg0); ++ ++ /* Start the command */ ++ dwc_wr32(pcd->usb3_dev, &ep_reg->depcmd, ++ DWC_EPCMD_SET_EP_CFG | DWC_EPCMD_ACT_BIT); ++ dwc_debug1(pcd->usb3_dev, "DEPCMD=%08x\n", ++ DWC_EPCMD_SET_EP_CFG | DWC_EPCMD_ACT_BIT); ++ ++ /* Wait for command completion */ ++ handshake(pcd->usb3_dev, &ep_reg->depcmd, DWC_EPCMD_ACT_BIT, 0); ++ ++ return 0; ++} ++ ++/** ++ * Send DEPXFERCFG command to EP ++ */ ++int dwc_usb3_dep_xfercfg(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, ++ u32 depstrmcfg) ++{ ++ dwc_debug1(pcd->usb3_dev, "dep_xfercfg, ep_reg=%lx\n", ++ (unsigned long)ep_reg); ++ ++ /* Set param 0 */ ++ dwc_wr32(pcd->usb3_dev, &ep_reg->depcmdpar0, depstrmcfg); ++ dwc_debug1(pcd->usb3_dev, "DEPSTRMCFG=%08x\n", depstrmcfg); ++ ++ /* Start the command */ ++ dwc_wr32(pcd->usb3_dev, &ep_reg->depcmd, ++ DWC_EPCMD_SET_XFER_CFG | DWC_EPCMD_ACT_BIT); ++ dwc_debug1(pcd->usb3_dev, "DEPCMD=%08x\n", ++ DWC_EPCMD_SET_XFER_CFG | DWC_EPCMD_ACT_BIT); ++ ++ /* Wait for command completion */ ++ handshake(pcd->usb3_dev, &ep_reg->depcmd, DWC_EPCMD_ACT_BIT, 0); ++ ++ return 0; ++} ++ ++/** ++ * Send DEPGETEPSTATE command to EP ++ */ ++u32 dwc_usb3_dep_getepstate(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg) ++{ ++ u32 retval; ++ ++ dwc_debug1(pcd->usb3_dev, "dep_getepstate, ep_reg=%lx\n", ++ (unsigned long)ep_reg); ++ ++ /* Start the command */ ++ dwc_wr32(pcd->usb3_dev, &ep_reg->depcmd, ++ DWC_EPCMD_GET_EP_STATE | DWC_EPCMD_ACT_BIT); ++ dwc_debug1(pcd->usb3_dev, "DEPCMD=%08x\n", ++ DWC_EPCMD_GET_EP_STATE | DWC_EPCMD_ACT_BIT); ++ ++ /* Wait for command completion */ ++ handshake(pcd->usb3_dev, &ep_reg->depcmd, DWC_EPCMD_ACT_BIT, 0); ++ ++ /* Get state returned in DEPCMDPAR2 */ ++ retval = dwc_rd32(pcd->usb3_dev, &ep_reg->depcmdpar2); ++ ++ return retval; ++} ++ ++/** ++ * Send DEPSSTALL command to EP ++ */ ++int dwc_usb3_dep_sstall(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg) ++{ ++ dwc_debug1(pcd->usb3_dev, "dep_sstall, ep_reg=%lx\n", ++ (unsigned long)ep_reg); ++ ++ /* Start the command */ ++ dwc_wr32(pcd->usb3_dev, &ep_reg->depcmd, ++ DWC_EPCMD_SET_STALL | DWC_EPCMD_ACT_BIT); ++ dwc_debug1(pcd->usb3_dev, "DEPCMD=%08x\n", ++ DWC_EPCMD_SET_STALL | DWC_EPCMD_ACT_BIT); ++ ++ /* Wait for command completion */ ++ handshake(pcd->usb3_dev, &ep_reg->depcmd, DWC_EPCMD_ACT_BIT, 0); ++ ++ return 0; ++} ++ ++/** ++ * Send DEPCSTALL command to EP ++ */ ++int dwc_usb3_dep_cstall(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, int clr_pend) ++{ ++ u32 depcmd; ++ ++ dwc_debug1(pcd->usb3_dev, "dep_cstall, ep_reg=%lx\n", ++ (unsigned long)ep_reg); ++ ++ /* Fill clear stall command */ ++ depcmd = DWC_EPCMD_CLR_STALL | DWC_EPCMD_ACT_BIT; ++ if (clr_pend) ++ depcmd |= DWC_EPCMD_HP_FRM_BIT; ++ ++ /* Start the command */ ++ dwc_wr32(pcd->usb3_dev, &ep_reg->depcmd, depcmd); ++ dwc_debug1(pcd->usb3_dev, "DEPCMD=%08x\n", depcmd); ++ ++ /* Wait for command completion */ ++ handshake(pcd->usb3_dev, &ep_reg->depcmd, DWC_EPCMD_ACT_BIT, 0); ++ ++ return 0; ++} ++ ++/** ++ * Send DEPSTRTXFER command to EP ++ */ ++int dwc_usb3_dep_startxfer(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, ++ dwc_dma_t dma_addr, u32 stream_or_uf) ++{ ++ u32 retval; ++ ++ dwc_debug1(pcd->usb3_dev, "dep_startxfer, ep_reg=%lx\n", ++ (unsigned long)ep_reg); ++ ++ /* Set param 1 */ ++ dwc_wr32(pcd->usb3_dev, &ep_reg->depcmdpar1, dma_addr & 0xffffffffU); ++ dwc_debug1(pcd->usb3_dev, "TDADDRLO=%08lx\n", ++ (unsigned long)(dma_addr & 0xffffffffU)); ++ ++ /* Set param 0 */ ++#ifdef DWC_64_BIT_ARCH ++ dwc_wr32(pcd->usb3_dev, &ep_reg->depcmdpar0, ++ dma_addr >> 32U & 0xffffffffU); ++ dwc_debug1(pcd->usb3_dev, "TDADDRHI=%08lx\n", ++ (unsigned long)(dma_addr >> 32U & 0xffffffffU)); ++#else ++ dwc_wr32(pcd->usb3_dev, &ep_reg->depcmdpar0, 0); ++ dwc_debug1(pcd->usb3_dev, "TDADDRHI=%08x\n", 0); ++#endif ++ /* Start the command */ ++ dwc_wr32(pcd->usb3_dev, &ep_reg->depcmd, ++ stream_or_uf << DWC_EPCMD_STR_NUM_OR_UF_SHIFT | ++ DWC_EPCMD_START_XFER | DWC_EPCMD_ACT_BIT); ++ dwc_debug1(pcd->usb3_dev, "DEPCMD=%08x\n", ++ stream_or_uf << DWC_EPCMD_STR_NUM_OR_UF_SHIFT | ++ DWC_EPCMD_START_XFER | DWC_EPCMD_ACT_BIT); ++ ++ /* Wait for command completion */ ++ handshake(pcd->usb3_dev, &ep_reg->depcmd, DWC_EPCMD_ACT_BIT, 0); ++ ++ retval = dwc_rd32(pcd->usb3_dev, &ep_reg->depcmd); ++ ++ return retval >> DWC_EPCMD_XFER_RSRC_IDX_SHIFT & ++ DWC_EPCMD_XFER_RSRC_IDX_BITS >> DWC_EPCMD_XFER_RSRC_IDX_SHIFT; ++} ++ ++/** ++ * Send DEPUPDTXFER command to EP ++ */ ++int dwc_usb3_dep_updatexfer(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, ++ u32 tri) ++{ ++ dwc_debug1(pcd->usb3_dev, "dep_updxfer, ep_reg=%lx\n", ++ (unsigned long)ep_reg); ++ ++ /* Start the command */ ++ dwc_wr32(pcd->usb3_dev, &ep_reg->depcmd, ++ tri << DWC_EPCMD_XFER_RSRC_IDX_SHIFT | ++ DWC_EPCMD_UPDATE_XFER | DWC_EPCMD_ACT_BIT); ++ dwc_debug1(pcd->usb3_dev, "DEPCMD=%08x\n", ++ tri << DWC_EPCMD_XFER_RSRC_IDX_SHIFT | ++ DWC_EPCMD_UPDATE_XFER | DWC_EPCMD_ACT_BIT); ++ ++ /* Wait for command completion */ ++ handshake(pcd->usb3_dev, &ep_reg->depcmd, DWC_EPCMD_ACT_BIT, 0); ++ ++ return 0; ++} ++ ++/** ++ * Send DEPENDXFER command to EP ++ */ ++int dwc_usb3_dep_endxfer(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, ++ u32 tri, int flags, void *condition) ++{ ++ u32 depcmd; ++ ++ dwc_debug1(pcd->usb3_dev, "dep_endxfer, ep_reg=%lx\n", ++ (unsigned long)ep_reg); ++ ++ /* Fill end transfer command */ ++ depcmd = tri << DWC_EPCMD_XFER_RSRC_IDX_SHIFT | DWC_EPCMD_END_XFER; ++ depcmd |= DWC_EPCMD_ACT_BIT; ++ if (flags & DWC_ENDXFER_FORCE) ++ depcmd |= DWC_EPCMD_HP_FRM_BIT; ++ ++ /* Start the command. */ ++ dwc_wr32(pcd->usb3_dev, &ep_reg->depcmd, depcmd); ++ dwc_debug1(pcd->usb3_dev, "DEPCMD=%08x\n", depcmd); ++ ++ /* Wait for command completion */ ++ handshake(pcd->usb3_dev, &ep_reg->depcmd, DWC_EPCMD_ACT_BIT, 0); ++ if (!(flags & DWC_ENDXFER_NODELAY)) ++ dwc_udelay(dev, 100); ++ ++ return 0; ++} ++ ++#ifdef DWC_STAR_9000463548_WORKAROUND ++int dwc_usb3_dep_endxfer_nowait(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, ++ u32 tri, int flags) ++{ ++ u32 depcmd; ++ ++ dwc_debug1(pcd->usb3_dev, "dep_endxfer_nowait, ep_reg=%lx\n", ++ (unsigned long)ep_reg); ++ ++ /* Fill end transfer command */ ++ depcmd = tri << DWC_EPCMD_XFER_RSRC_IDX_SHIFT | DWC_EPCMD_END_XFER; ++ depcmd |= DWC_EPCMD_ACT_BIT; ++ if (flags & DWC_ENDXFER_FORCE) ++ depcmd |= DWC_EPCMD_HP_FRM_BIT; ++ ++ /* Start the command. */ ++ dwc_wr32(pcd->usb3_dev, &ep_reg->depcmd, depcmd); ++ dwc_debug1(pcd->usb3_dev, "DEPCMD=%08x\n", depcmd); ++ ++ return 0; ++} ++ ++int dwc_usb3_dep_wait_endxfer(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, ++ void *condition) ++{ ++ /* Wait for command completion */ ++ handshake(pcd->usb3_dev, &ep_reg->depcmd, DWC_EPCMD_ACT_BIT, 0); ++ dwc_udelay(dev, 100); ++ ++ return 0; ++} ++#endif ++ ++/** ++ * Send DEPSTRTNEWCFG command to EP ++ */ ++int dwc_usb3_dep_startnewcfg(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, ++ u32 rsrcidx) ++{ ++ dwc_debug1(pcd->usb3_dev, "dep_startnewcfg, ep_reg=%lx\n", ++ (unsigned long)ep_reg); ++ ++ /* Start the command */ ++ dwc_wr32(pcd->usb3_dev, &ep_reg->depcmd, ++ rsrcidx << DWC_EPCMD_XFER_RSRC_IDX_SHIFT | ++ DWC_EPCMD_START_NEW_CFG | DWC_EPCMD_ACT_BIT); ++ dwc_debug1(pcd->usb3_dev, "DEPCMD=%08x\n", ++ rsrcidx << DWC_EPCMD_XFER_RSRC_IDX_SHIFT | ++ DWC_EPCMD_START_NEW_CFG | DWC_EPCMD_ACT_BIT); ++ ++ /* Wait for command completion */ ++ handshake(pcd->usb3_dev, &ep_reg->depcmd, DWC_EPCMD_ACT_BIT, 0); ++ ++ return 0; ++} ++ ++/**********************/ ++ ++/** ++ * Enable an EP in the DALEPENA register. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param ep The EP to enable. ++ * @return 0 if succesful, -DWC_E_BUSY if already enabled. ++ */ ++int dwc_usb3_enable_ep(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep) ++{ ++ u32 ep_index_num, dalepena; ++ ++ ep_index_num = ep->dwc_ep.num * 2; ++ ++ if (ep->dwc_ep.is_in) ++ ep_index_num += 1; ++ ++ dalepena = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dalepena); ++ ++ /* If we have already enabled this EP, leave it alone ++ * (shouldn't happen) ++ */ ++ if (dalepena & 1 << ep_index_num) ++ return -DWC_E_BUSY; ++ ++ dalepena |= 1 << ep_index_num; ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dalepena, dalepena); ++ dwc_debug1(pcd->usb3_dev, "enable_ep: DALEPENA=%08x\n", dalepena); ++ return 0; ++} ++ ++/** ++ * Disable an EP in the DALEPENA register. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param ep The EP to disable. ++ * @return 0 if succesful, -DWC_E_INVALID if already disabled. ++ */ ++int dwc_usb3_disable_ep(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep) ++{ ++ u32 ep_index_num, dalepena; ++ ++ ep_index_num = ep->dwc_ep.num * 2; ++ ++ if (ep->dwc_ep.is_in) ++ ep_index_num += 1; ++ ++ dalepena = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dalepena); ++ ++ /* If we have already disabled this EP, leave it alone ++ * (shouldn't happen) ++ */ ++ if (!(dalepena & 1 << ep_index_num)) ++ return -DWC_E_INVALID; ++ ++ dalepena &= ~(1 << ep_index_num); ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dalepena, dalepena); ++ dwc_debug1(pcd->usb3_dev, "disable_ep: DALEPENA=%08x\n", dalepena); ++ return 0; ++} ++ ++/** ++ * Get the device speed from the device status register and convert it ++ * to USB speed constant. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @return The device speed. ++ */ ++int dwc_usb3_get_device_speed(dwc_usb3_pcd_t *pcd) ++{ ++ u32 dsts; ++ int speed = USB_SPEED_UNKNOWN; ++ ++ dsts = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dsts); ++ ++ switch (dsts >> DWC_DSTS_CONNSPD_SHIFT & ++ DWC_DSTS_CONNSPD_BITS >> DWC_DSTS_CONNSPD_SHIFT) { ++ case DWC_SPEED_HS_PHY_30MHZ_OR_60MHZ: ++ dwc_debug0(pcd->usb3_dev, "HIGH SPEED\n"); ++ speed = USB_SPEED_HIGH; ++ break; ++ ++ case DWC_SPEED_FS_PHY_30MHZ_OR_60MHZ: ++ case DWC_SPEED_FS_PHY_48MHZ: ++ dwc_debug0(pcd->usb3_dev, "FULL SPEED\n"); ++ speed = USB_SPEED_FULL; ++ break; ++ ++ case DWC_SPEED_LS_PHY_6MHZ: ++ dwc_debug0(pcd->usb3_dev, "LOW SPEED\n"); ++ speed = USB_SPEED_LOW; ++ break; ++ ++ case DWC_SPEED_SS_PHY_125MHZ_OR_250MHZ: ++ dwc_debug0(pcd->usb3_dev, "SUPER SPEED\n"); ++ speed = USB_SPEED_SUPER; ++ break; ++ } ++ ++ return speed; ++} ++ ++/** ++ * Get the current microframe number. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @return The current microframe number. ++ */ ++int dwc_usb3_get_frame(dwc_usb3_pcd_t *pcd) ++{ ++ u32 dsts; ++ ++ /* read current frame/microframe number from DSTS register */ ++ dsts = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dsts); ++ ++ return dsts >> DWC_DSTS_SOF_FN_SHIFT & ++ DWC_DSTS_SOF_FN_BITS >> DWC_DSTS_SOF_FN_SHIFT; ++} ++ ++/** ++ * Get the current link state. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @return The current link state. ++ */ ++int dwc_usb3_pcd_get_link_state(dwc_usb3_pcd_t *pcd) ++{ ++ u32 status, state; ++ ++ status = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dsts); ++ state = status >> DWC_DSTS_USBLNK_STATE_SHIFT & ++ DWC_DSTS_USBLNK_STATE_BITS >> DWC_DSTS_USBLNK_STATE_SHIFT; ++ dwc_debug2(pcd->usb3_dev, "status=0x%08x state=%d\n", status, state); ++ ++ return state; ++} ++ ++/** ++ * Set state of USB link. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param state Link state to set. ++ */ ++void dwc_usb3_pcd_set_link_state(dwc_usb3_pcd_t *pcd, int state) ++{ ++ u32 dctl; ++ ++ dctl = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dctl); ++ dctl &= ~DWC_DCTL_ULST_CHNG_REQ_BITS; ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dctl, dctl); ++ ++ dctl = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dctl); ++ dctl &= ~DWC_DCTL_ULST_CHNG_REQ_BITS; ++ dctl |= state << DWC_DCTL_ULST_CHNG_REQ_SHIFT; ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dctl, dctl); ++} ++ ++/** ++ * Send a Remote Wakeup to the host. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param function Function that caused the remote wakeup. ++ */ ++void dwc_usb3_pcd_remote_wake(dwc_usb3_pcd_t *pcd, int function) ++{ ++ /* For USB 3.0, send function remote wake notification */ ++ if (pcd->speed == USB_SPEED_SUPER) ++ dwc_usb3_xmit_fn_remote_wake(pcd, function); ++} ++ ++/** ++ * Set the Device Address. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param addr The address to set. ++ */ ++void dwc_usb3_set_address(dwc_usb3_pcd_t *pcd, int addr) ++{ ++ u32 dcfg; ++ ++ dcfg = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dcfg); ++ dcfg &= ~DWC_DCFG_DEVADDR_BITS; ++ dcfg |= addr << DWC_DCFG_DEVADDR_SHIFT; ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dcfg, dcfg); ++} ++ ++/** ++ * Enable USB2 Phy suspend. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ */ ++static void dwc_usb3_ena_usb2_phy_suspend(dwc_usb3_pcd_t *pcd) ++{ ++ dwc_usb3_device_t *dev = pcd->usb3_dev; ++ int hiber = dev->core_params->hibernate && ++ (dev->hwparams1 & DWC_HWP1_EN_PWROPT_BITS) == ++ DWC_EN_PWROPT_HIBERNATION << DWC_HWP1_EN_PWROPT_SHIFT; ++ int writeit = 0; ++ u32 usb2phycfg; ++ ++ if (dev->core_params->phyctl || hiber || dev->core_params->lpmctl) { ++ usb2phycfg = dwc_rd32(dev, ++ &dev->core_global_regs->gusb2phycfg[0]); ++ ++ if ((dev->core_params->phyctl || hiber) && ++ !(usb2phycfg & DWC_USB2PHYCFG_SUS_PHY_BIT)) { ++ usb2phycfg |= DWC_USB2PHYCFG_SUS_PHY_BIT; ++ writeit = 1; ++ } ++ ++ if (dev->core_params->lpmctl && ++ !(usb2phycfg & DWC_USB2PHYCFG_ENBL_SLP_M_BIT)) { ++ usb2phycfg |= DWC_USB2PHYCFG_ENBL_SLP_M_BIT; ++ writeit = 1; ++ } ++ ++ if (writeit) ++ dwc_wr32(dev, &dev->core_global_regs->gusb2phycfg[0], ++ usb2phycfg); ++ } ++} ++ ++/** ++ * Disable USB2 Phy suspend. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ */ ++static void dwc_usb3_dis_usb2_phy_suspend(dwc_usb3_pcd_t *pcd) ++{ ++ u32 usb2phycfg; ++ ++ usb2phycfg = dwc_rd32(pcd->usb3_dev, ++ &pcd->usb3_dev->core_global_regs->gusb2phycfg[0]); ++ ++ if (usb2phycfg & (DWC_USB2PHYCFG_SUS_PHY_BIT | ++ DWC_USB2PHYCFG_ENBL_SLP_M_BIT)) { ++ usb2phycfg &= ~DWC_USB2PHYCFG_SUS_PHY_BIT; ++ usb2phycfg &= ~DWC_USB2PHYCFG_ENBL_SLP_M_BIT; ++ dwc_wr32(pcd->usb3_dev, ++ &pcd->usb3_dev->core_global_regs->gusb2phycfg[0], ++ usb2phycfg); ++ } ++} ++ ++/** ++ * Enable USB3 Phy suspend. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ */ ++static void dwc_usb3_ena_usb3_phy_suspend(dwc_usb3_pcd_t *pcd) ++{ ++#ifndef SELA_PLATFORM ++ u32 pipectl; ++ ++ pipectl = dwc_rd32(pcd->usb3_dev, ++ &pcd->usb3_dev->core_global_regs->gusb3pipectl[0]); ++ if (!(pipectl & DWC_PIPECTL_SUS_PHY_BIT)) { ++ pipectl |= DWC_PIPECTL_SUS_PHY_BIT; ++ dwc_wr32(pcd->usb3_dev, ++ &pcd->usb3_dev->core_global_regs->gusb3pipectl[0], ++ pipectl); ++ } ++#endif ++} ++ ++/** ++ * Disable USB3 Phy suspend. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ */ ++static void dwc_usb3_dis_usb3_phy_suspend(dwc_usb3_pcd_t *pcd) ++{ ++#ifndef SELA_PLATFORM ++ u32 pipectl; ++ ++ pipectl = dwc_rd32(pcd->usb3_dev, ++ &pcd->usb3_dev->core_global_regs->gusb3pipectl[0]); ++ if (pipectl & DWC_PIPECTL_SUS_PHY_BIT) { ++ pipectl &= ~DWC_PIPECTL_SUS_PHY_BIT; ++ dwc_wr32(pcd->usb3_dev, ++ &pcd->usb3_dev->core_global_regs->gusb3pipectl[0], ++ pipectl); ++ } ++#endif ++} ++ ++/** ++ * Enable USB2 Phy suspend if the device is connected at HS or FS. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ */ ++void dwc_usb3_ena_usb2_suspend(dwc_usb3_pcd_t *pcd) ++{ ++ if (pcd->speed == USB_SPEED_SUPER) ++ return; ++ ++ dwc_usb3_ena_usb2_phy_suspend(pcd); ++} ++ ++/** ++ * Disable USB2 Phy suspend if the device is connected at HS or FS. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ */ ++void dwc_usb3_dis_usb2_suspend(dwc_usb3_pcd_t *pcd) ++{ ++ if (pcd->speed == USB_SPEED_SUPER) ++ return; ++ ++ dwc_usb3_dis_usb2_phy_suspend(pcd); ++} ++ ++/** ++ * Enable the Device to accept U1 control commands from the Host. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ */ ++void dwc_usb3_accept_u1(dwc_usb3_pcd_t *pcd) ++{ ++ u32 dctl; ++ ++ dctl = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dctl); ++ dctl |= DWC_DCTL_ACCEPT_U1_EN_BIT; ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dctl, dctl); ++} ++ ++/** ++ * Enable the Device to accept U2 control commands from the Host. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ */ ++void dwc_usb3_accept_u2(dwc_usb3_pcd_t *pcd) ++{ ++#if 0 ++ u32 dctl; ++ ++ dctl = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dctl); ++ dctl |= DWC_DCTL_ACCEPT_U2_EN_BIT; ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dctl, dctl); ++#endif ++} ++ ++/** ++ * Enable U1 sleep. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ */ ++void dwc_usb3_enable_u1(dwc_usb3_pcd_t *pcd) ++{ ++ u32 dctl; ++ ++ dctl = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dctl); ++ dctl |= DWC_DCTL_INIT_U1_EN_BIT; ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dctl, dctl); ++} ++ ++/** ++ * Enable U2 sleep. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ */ ++void dwc_usb3_enable_u2(dwc_usb3_pcd_t *pcd) ++{ ++} ++ ++/** ++ * Disable U1 sleep. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ */ ++void dwc_usb3_disable_u1(dwc_usb3_pcd_t *pcd) ++{ ++} ++ ++/** ++ * Disable U2 sleep. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ */ ++void dwc_usb3_disable_u2(dwc_usb3_pcd_t *pcd) ++{ ++ u32 dctl; ++ ++ dctl = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dctl); ++ dctl &= ~DWC_DCTL_INIT_U2_EN_BIT; ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dctl, dctl); ++} ++ ++/** ++ * Test whether U1 sleep is enabled. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @return 1 if enabled, 0 if not. ++ */ ++int dwc_usb3_u1_enabled(dwc_usb3_pcd_t *pcd) ++{ ++ u32 dctl; ++ ++ dctl = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dctl); ++ return !!(dctl & DWC_DCTL_INIT_U1_EN_BIT); ++} ++ ++/** ++ * Test whether U2 sleep is enabled. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @return 1 if enabled, 0 if not. ++ */ ++int dwc_usb3_u2_enabled(dwc_usb3_pcd_t *pcd) ++{ ++ u32 dctl; ++ ++ dctl = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dctl); ++ return !!(dctl & DWC_DCTL_INIT_U2_EN_BIT); ++} ++ ++/** ++ * Clear 'eps_enabled' flag and 'ena_once' flags for all EPs, so EPs will get ++ * completely reconfigured by SetConfig and SetInterface. ++ */ ++void dwc_usb3_clr_eps_enabled(dwc_usb3_pcd_t *pcd) ++{ ++ dwc_usb3_pcd_ep_t *ep; ++ int i; ++ ++ pcd->eps_enabled = 0; ++ ++ for (i = 0; i < pcd->num_in_eps; i++) { ++ ep = pcd->in_ep[i]; ++ if (ep) ++ ep->dwc_ep.ena_once = 0; ++ } ++ ++ for (i = 0; i < pcd->num_out_eps; i++) { ++ ep = pcd->out_ep[i]; ++ if (ep) ++ ep->dwc_ep.ena_once = 0; ++ } ++} ++ ++/** ++ * This routine is called when the SET_FEATURE TEST_MODE Setup packet ++ * is sent from the host. The Device Control register is written with ++ * the Test Mode bits set to the specified Test Mode. This is done as ++ * a tasklet so that the "Status" phase of the control transfer ++ * completes before transmitting the TEST packets. ++ */ ++void dwc_usb3_pcd_do_test_mode(unsigned long data) ++{ ++ dwc_usb3_pcd_t *pcd = (dwc_usb3_pcd_t *)data; ++ int test_mode = pcd->test_mode; ++ u32 dctl; ++ ++#ifdef CONFIG_USB_OTG_DWC ++ struct usb_phy *phy; ++ struct usb_otg *otg; ++#endif ++ ++ dctl = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dctl); ++ dctl &= ~DWC_DCTL_TSTCTL_BITS; ++ ++ switch (test_mode) { ++ case 1: // TEST_J ++ dctl |= 1 << DWC_DCTL_TSTCTL_SHIFT; ++ break; ++ ++ case 2: // TEST_K ++ dctl |= 2 << DWC_DCTL_TSTCTL_SHIFT; ++ break; ++ ++ case 3: // TEST_SE0_NAK ++ dctl |= 3 << DWC_DCTL_TSTCTL_SHIFT; ++ break; ++ ++ case 4: // TEST_PACKET ++ dctl |= 4 << DWC_DCTL_TSTCTL_SHIFT; ++ break; ++ ++ case 5: // TEST_FORCE_ENABLE ++ dctl |= 5 << DWC_DCTL_TSTCTL_SHIFT; ++ break; ++ ++#ifdef CONFIG_USB_OTG_DWC ++ case 6: // otg_srp_reqd ++ dwc_error0(pcd->usb3_dev, "otg_srp_reqd\n"); ++ phy = usb_get_phy(USB_PHY_TYPE_USB3); ++ if (IS_ERR(phy)) ++ break; ++ if (!phy) { ++ usb_put_phy(phy); ++ break; ++ } ++ otg = phy->otg; ++ if (!otg) { ++ usb_put_phy(phy); ++ break; ++ } ++ otg_start_srp(otg); ++ usb_put_phy(phy); ++ return; ++ ++ case 7: // otg_hnp_reqd ++ dwc_error0(pcd->usb3_dev, "otg_hnp_reqd\n"); ++ phy = usb_get_phy(USB_PHY_TYPE_USB3); ++ if (IS_ERR(phy)) ++ break; ++ if (!phy) { ++ usb_put_phy(phy); ++ break; ++ } ++ otg = phy->otg; ++ if (!otg) { ++ usb_put_phy(phy); ++ break; ++ } ++ otg_start_hnp(otg); ++ usb_put_phy(phy); ++ return; ++#endif ++ } ++ ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dctl, dctl); ++} ++ ++/** ++ * This routine calculates the number of IN EPs (excluding EP0) ++ * using GHWPARAMS3 register values ++ * ++ * @param dev Programming view of DWC_usb3 controller. ++ */ ++static int calc_num_in_eps(dwc_usb3_device_t *dev) ++{ ++ u32 num_in_eps = dev->hwparams3 >> DWC_HWP3_NUM_IN_EPS_SHIFT & ++ DWC_HWP3_NUM_IN_EPS_BITS >> DWC_HWP3_NUM_IN_EPS_SHIFT; ++ ++ return num_in_eps - 1; ++} ++ ++/** ++ * This routine calculates the number of OUT EPs (excluding EP0) ++ * using GHWPARAMS3 register values ++ * ++ * @param dev Programming view of DWC_usb3 controller. ++ */ ++static int calc_num_out_eps(dwc_usb3_device_t *dev) ++{ ++ u32 num_eps = dev->hwparams3 >> DWC_HWP3_NUM_EPS_SHIFT & ++ DWC_HWP3_NUM_EPS_BITS >> DWC_HWP3_NUM_EPS_SHIFT; ++ u32 num_in_eps = dev->hwparams3 >> DWC_HWP3_NUM_IN_EPS_SHIFT & ++ DWC_HWP3_NUM_IN_EPS_BITS >> DWC_HWP3_NUM_IN_EPS_SHIFT; ++ ++ return num_eps - num_in_eps - 1; ++} ++ ++/** ++ * This routine is called to initialize the DWC_usb3 CSR data structures. The ++ * register addresses in the device structures are initialized from the ++ * base address supplied by the caller. The calling ++ * routine must make the OS calls to get the base address of the DWC_usb3 ++ * controller registers. The core_params argument ++ * holds the parameters that specify how the core should be configured. ++ * ++ * @param dev Programming view of DWC_usb3 controller. ++ * @param base Base address of DWC_usb3 core registers. ++ * @param core_params Pointer to the core configuration parameters. ++ */ ++int dwc_usb3_pcd_common_init(dwc_usb3_device_t *dev, volatile u8 __iomem *base, ++ dwc_usb3_core_params_t *core_params) ++{ ++ dwc_usb3_pcd_t *pcd; ++ u32 temp; ++ ++ dwc_debug3(dev, "%s(%lx,%lx)\n", __func__, (unsigned long)base, ++ (unsigned long)core_params); ++ ++ dev->core_params = core_params; ++ dev->core_global_regs = (dwc_usb3_core_global_regs_t __iomem *) ++ (base + DWC_CORE_GLOBAL_REG_OFFSET); ++ ++#ifdef COSIM ++ /* scramble-off, scaledown */ ++ dwc_wr32(dev, &dev->core_global_regs->gctl, 0x38); ++#endif ++ ++ pcd = &dev->pcd; ++ ++ pcd->dev_global_regs = (dwc_usb3_dev_global_regs_t __iomem *) ++ (base + DWC_DEV_GLOBAL_REG_OFFSET); ++ pcd->in_ep_regs = (dwc_usb3_dev_ep_regs_t __iomem *) ++ (base + DWC_DEV_IN_EP_REG_OFFSET); ++ pcd->out_ep_regs = (dwc_usb3_dev_ep_regs_t __iomem *) ++ (base + DWC_DEV_OUT_EP_REG_OFFSET); ++ ++#ifdef SSIC ++ dev->ssic_regs = (dwc_usb3_ssic_regs_t __iomem *) ++ (base + DWC_SSIC_REG_OFFSET); ++#endif ++ ++ /* ++ * Store the contents of the hardware configuration registers here for ++ * easy access later. ++ */ ++ dev->hwparams0 = dwc_rd32(dev, &dev->core_global_regs->ghwparams0); ++ dev->hwparams1 = dwc_rd32(dev, &dev->core_global_regs->ghwparams1); ++ dev->hwparams2 = dwc_rd32(dev, &dev->core_global_regs->ghwparams2); ++ dev->hwparams3 = dwc_rd32(dev, &dev->core_global_regs->ghwparams3); ++ dev->hwparams4 = dwc_rd32(dev, &dev->core_global_regs->ghwparams4); ++ dev->hwparams5 = dwc_rd32(dev, &dev->core_global_regs->ghwparams5); ++ dev->hwparams6 = dwc_rd32(dev, &dev->core_global_regs->ghwparams6); ++ dev->hwparams7 = dwc_rd32(dev, &dev->core_global_regs->ghwparams7); ++ dev->hwparams8 = dwc_rd32(dev, &dev->core_global_regs->ghwparams8); ++ ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dcfg); ++ dwc_debug1(dev, "dcfg=%08x\n", temp); ++ ++#ifndef SELA_PLATFORM ++ dwc_debug1(dev, "mode=%0x\n", ++ dev->hwparams0 >> DWC_HWP0_MODE_SHIFT & ++ DWC_HWP0_MODE_BITS >> DWC_HWP0_MODE_SHIFT); ++ dwc_debug1(dev, "num_ep=%d\n", ++ dev->hwparams3 >> DWC_HWP3_NUM_EPS_SHIFT & ++ DWC_HWP3_NUM_EPS_BITS >> DWC_HWP3_NUM_EPS_SHIFT); ++ dwc_debug1(dev, "num_in_ep=%d\n", ++ dev->hwparams3 >> DWC_HWP3_NUM_IN_EPS_SHIFT & ++ DWC_HWP3_NUM_IN_EPS_BITS >> DWC_HWP3_NUM_IN_EPS_SHIFT); ++ dwc_debug1(dev, "dfq_fifo_depth=%d\n", ++ dev->hwparams5 >> DWC_HWP5_DFQ_FIFO_DEPTH_SHIFT & ++ DWC_HWP5_DFQ_FIFO_DEPTH_BITS >> DWC_HWP5_DFQ_FIFO_DEPTH_SHIFT); ++ dwc_debug1(dev, "dwq_fifo_depth=%d\n", ++ dev->hwparams5 >> DWC_HWP5_DWQ_FIFO_DEPTH_SHIFT & ++ DWC_HWP5_DWQ_FIFO_DEPTH_BITS >> DWC_HWP5_DWQ_FIFO_DEPTH_SHIFT); ++ dwc_debug1(dev, "txq_fifo_depth=%d\n", ++ dev->hwparams5 >> DWC_HWP5_TXQ_FIFO_DEPTH_SHIFT & ++ DWC_HWP5_TXQ_FIFO_DEPTH_BITS >> DWC_HWP5_TXQ_FIFO_DEPTH_SHIFT); ++ dwc_debug1(dev, "rxq_fifo_depth=%d\n", ++ dev->hwparams5 >> DWC_HWP5_RXQ_FIFO_DEPTH_SHIFT & ++ DWC_HWP5_RXQ_FIFO_DEPTH_BITS >> DWC_HWP5_RXQ_FIFO_DEPTH_SHIFT); ++#endif ++ ++ /* Initialize parameters from Hardware configuration registers. */ ++ dev->pcd.num_in_eps = calc_num_in_eps(dev); ++ dev->pcd.num_in_eps = 4; ++ printk("\n###%s,%d,dev->pcd.num_in_eps=0x%x\n",__func__,__LINE__,dev->pcd.num_in_eps); ++ if (dev->pcd.num_in_eps > 15) { ++ dwc_debug1(dev, "Number of IN endpoints (%d) too large\n", ++ dev->pcd.num_in_eps); ++ return -DWC_E_INVALID; ++ } ++ ++ dev->pcd.num_out_eps = calc_num_out_eps(dev); ++ dev->pcd.num_out_eps = 2; ++ printk("\n###%s,%d,dev->pcd.num_out_eps=0x%x\n",__func__,__LINE__,dev->pcd.num_out_eps); ++ if (dev->pcd.num_out_eps > 15) { ++ dwc_debug1(dev, "Number of OUT endpoints (%d) too large\n", ++ dev->pcd.num_out_eps); ++ return -DWC_E_INVALID; ++ } ++ ++#ifdef SELA_PLATFORM ++ /* Limit the number of EPs to speed up simulation */ ++ if (dev->pcd.num_in_eps > dev->pcd.max_in_eps) ++ dev->pcd.num_in_eps = dev->pcd.max_in_eps; ++ if (dev->pcd.num_out_eps > dev->pcd.max_out_eps) ++ dev->pcd.num_out_eps = dev->pcd.max_out_eps; ++#endif ++ ++ return 0; ++} ++ ++/** ++ * This routine frees any allocations made by dwc_usb3_pcd_common_init(). ++ * ++ * @param dev Programming view of DWC_usb3 controller. ++ */ ++void dwc_usb3_pcd_common_remove(dwc_usb3_device_t *dev) ++{ ++} ++ ++/** ++ * This routine ensures the device is really a DWC_usb3 controller, by reading ++ * and verifying the SNPSID register contents. The value should be 0x5533XXXX, ++ * which corresponds to "U3", as in "USB3 version X.XXX". ++ * ++ * The SNPSID value is also saved in dev->snpsid for later use in ++ * determining if any version-specific operations need to be performed. ++ * ++ * This routine should be called before any other initialization routines, to ++ * ensure that the dev->snpsid value is set in case any of the other ++ * routines need it. ++ * ++ * @param dev Programming view of DWC_usb3 controller. ++ * @param addr_ofs Offset to the Device registers in the CSR space. It is ++ * needed because this routine is called early, before the ++ * normal register access routines are functional. ++ * @return 0 if the SNPSID value is valid, -DWC_E_INVALID if not. ++ */ ++int dwc_usb3_pcd_check_snpsid(dwc_usb3_device_t *dev, u32 addr_ofs) ++{ ++ dev->snpsid = dwc_rd32(dev, (volatile u32 __iomem *) ++ (dev->base + addr_ofs + 0x120)); ++ if ((dev->snpsid & 0xffff0000) != 0x55330000) { ++ dwc_error1(dev, "bad value for SNPSID: 0x%08x!\n", dev->snpsid); ++ return -DWC_E_INVALID; ++ } ++ ++ return 0; ++} ++ ++/** ++ * This routine dumps the core's internal debug registers ++ * ++ * @param dev Programming view of DWC_usb3 controller. ++ */ ++void dwc_usb3_dump_dbgregs(dwc_usb3_device_t *dev) ++{ ++ u32 rd_data, rd_data2; ++ unsigned int i, num_eps; ++ ++ /* Dump the 11 LSP debug registers */ ++ for (i = 0; i < 11; i++) { ++ dwc_wr32(dev, &dev->core_global_regs->gdbglspmux, i << 4); ++ rd_data = dwc_rd32(dev, &dev->core_global_regs->gdbglsp); ++ dwc_info2(dev, "lsp%d: %08x\n", i, rd_data); ++ } ++ ++ /* Dump the EP debug registers */ ++ num_eps = dev->hwparams3 >> DWC_HWP3_NUM_EPS_SHIFT & ++ DWC_HWP3_NUM_EPS_BITS >> DWC_HWP3_NUM_EPS_SHIFT; ++ for (i = 0; i < num_eps; i++) { ++ dwc_wr32(dev, &dev->core_global_regs->gdbglspmux, i); ++ rd_data = dwc_rd32(dev, &dev->core_global_regs->gdbgepinfo0); ++ rd_data2 = dwc_rd32(dev, &dev->core_global_regs->gdbgepinfo1); ++ dwc_info3(dev, " ep%d: %08x %08x\n", i, rd_data, rd_data2); ++ } ++ ++ /* Dump the BMU debug register */ ++ rd_data = dwc_rd32(dev, &dev->core_global_regs->gdbgbmu); ++ dwc_info1(dev, "bmu: %08x\n", rd_data); ++} ++ ++/** ++ * This routine reads the core global registers and prints them ++ * ++ * @param dev Programming view of DWC_usb3 controller. ++ */ ++void dwc_usb3_dump_global_registers(dwc_usb3_device_t *dev) ++{ ++ volatile u32 __iomem *addr; ++ ++ dwc_print0(dev, "Core Global Registers\n"); ++ addr = &dev->core_global_regs->gsbuscfg0; ++ dwc_print2(dev, "GSBUSCFG0 @0x%08lx : 0x%08x\n", ++ (unsigned long)addr, dwc_rd32(dev, addr)); ++ addr = &dev->core_global_regs->gsbuscfg1; ++ dwc_print2(dev, "GSBUSCFG1 @0x%08lx : 0x%08x\n", ++ (unsigned long)addr, dwc_rd32(dev, addr)); ++ addr = &dev->core_global_regs->gusb2phycfg[0]; ++ dwc_print2(dev, "USB2PHYCFG0 @0x%08lx : 0x%08x\n", ++ (unsigned long)addr, dwc_rd32(dev, addr)); ++ addr = &dev->core_global_regs->gevten; ++ dwc_print2(dev, "GEVTEN @0x%08lx : 0x%08x\n", ++ (unsigned long)addr, dwc_rd32(dev, addr)); ++ addr = &dev->core_global_regs->grxfifosiz[0]; ++ dwc_print2(dev, "GRXFIFOSIZ0 @0x%08lx : 0x%08x\n", ++ (unsigned long)addr, dwc_rd32(dev, addr)); ++ addr = &dev->core_global_regs->gtxfifosiz[0]; ++ dwc_print2(dev, "GTXFIFOSIZ0 @0x%08lx : 0x%08x\n", ++ (unsigned long)addr, dwc_rd32(dev, addr)); ++ addr = &dev->core_global_regs->gtxfifosiz[1]; ++ dwc_print2(dev, "GTXFIFOSIZ1 @0x%08lx : 0x%08x\n", ++ (unsigned long)addr, dwc_rd32(dev, addr)); ++ addr = &dev->core_global_regs->gtxfifosiz[2]; ++ dwc_print2(dev, "GTXFIFOSIZ2 @0x%08lx : 0x%08x\n", ++ (unsigned long)addr, dwc_rd32(dev, addr)); ++ addr = &dev->core_global_regs->gtxfifosiz[3]; ++ dwc_print2(dev, "GTXFIFOSIZ3 @0x%08lx : 0x%08x\n", ++ (unsigned long)addr, dwc_rd32(dev, addr)); ++ addr = &dev->core_global_regs->gusb2i2cctl[0]; ++ dwc_print2(dev, "GUSB2I2CCTL0 @0x%08lx : 0x%08x\n", ++ (unsigned long)addr, dwc_rd32(dev, addr)); ++ addr = &dev->core_global_regs->ggpio; ++ dwc_print2(dev, "GGPIO @0x%08lx : 0x%08x\n", ++ (unsigned long)addr, dwc_rd32(dev, addr)); ++ addr = &dev->core_global_regs->guid; ++ dwc_print2(dev, "GUID @0x%08lx : 0x%08x\n", ++ (unsigned long)addr, dwc_rd32(dev, addr)); ++ addr = &dev->core_global_regs->gsnpsid; ++ dwc_print2(dev, "GSNPSID @0x%08lx : 0x%08x\n", ++ (unsigned long)addr, dwc_rd32(dev, addr)); ++} ++ ++/** ++ * This routine reads the device registers and prints them ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ */ ++void dwc_usb3_dump_dev_registers(dwc_usb3_pcd_t *pcd) ++{ ++ volatile u32 __iomem *addr; ++ ++ dwc_print0(pcd->usb3_dev, "Device Global Registers\n"); ++ addr = &pcd->dev_global_regs->dcfg; ++ dwc_print2(pcd->usb3_dev, "DCFG @0x%08lx : 0x%08x\n", ++ (unsigned long)addr, dwc_rd32(pcd->usb3_dev, addr)); ++ addr = &pcd->dev_global_regs->dctl; ++ dwc_print2(pcd->usb3_dev, "DCTL @0x%08lx : 0x%08x\n", ++ (unsigned long)addr, dwc_rd32(pcd->usb3_dev, addr)); ++ addr = &pcd->dev_global_regs->dsts; ++ dwc_print2(pcd->usb3_dev, "DSTS @0x%08lx : 0x%08x\n", ++ (unsigned long)addr, dwc_rd32(pcd->usb3_dev, addr)); ++} ++ ++/** ++ * Set the size of the Tx FIFOs ++ * ++ * NOTE: The following code for setting the FIFO sizes only ++ * works for cores configured with the 3 RAM option. Setting ++ * FIFO sizes for the 2 RAM option is not implemented. ++ * ++ * @param dev Programming view of DWC_usb3 controller. ++ * @param sz New sizes for the FIFOs. ++ */ ++void dwc_usb3_set_tx_fifo_size(dwc_usb3_device_t *dev, int *sz) ++{ ++ dwc_usb3_core_global_regs_t __iomem *global_regs = ++ dev->core_global_regs; ++ int i, ram_width, ram_depth, size, prev_start, txsz[DWC_MAX_TX_FIFOS]; ++ ++ ram_width = (dev->hwparams0 >> DWC_HWP0_MDWIDTH_SHIFT & ++ DWC_HWP0_MDWIDTH_BITS >> DWC_HWP0_MDWIDTH_SHIFT) ++ / 8; ++ ram_depth = (dev->hwparams7 >> DWC_HWP7_RAM1_DEPTH_SHIFT & ++ DWC_HWP7_RAM1_DEPTH_BITS >> DWC_HWP7_RAM1_DEPTH_SHIFT) ++ * ram_width; ++ size = dwc_rd32(dev, &global_regs->gtxfifosiz[0]); ++ prev_start = size >> DWC_FIFOSZ_STARTADDR_SHIFT & ++ DWC_FIFOSZ_STARTADDR_BITS >> DWC_FIFOSZ_STARTADDR_SHIFT; ++ ++ for (i = 0; i < dev->pcd.num_in_eps + 1; i++) { ++ size = sz[i]; ++ ++ if (i == 0 && size && size < 512 + 2 * ram_width) { ++ dwc_print1(dev, "Requested Tx FIFO %d size too small\n", ++ i); ++ dwc_print0(dev, "Not setting Tx FIFO sizes\n"); ++ goto txerr; ++ } ++ ++ if (!size) { ++ /* Default to 512 for EP0, 1K for others */ ++ size = i ? 1024 : 512; ++ size += 2 * ram_width; ++ } ++ ++ size = (size + ram_width - 1) & ~(ram_width - 1); ++ dwc_debug3(dev, ++ "Tx FIFO %d size = %d bytes out of %d available\n", ++ i, size, ram_depth); ++ if (size > ram_depth) { ++ dwc_print1(dev, "Requested Tx FIFO %d size too large\n", ++ i); ++ dwc_print0(dev, "Not setting Tx FIFO sizes\n"); ++ goto txerr; ++ } ++ ++ txsz[i] = size; ++ ram_depth -= size; ++ } ++ ++ for (i = 0; i < dev->pcd.num_in_eps + 1; i++) { ++ size = txsz[i]; ++ dwc_debug2(dev, "Setting GTXFIFOSIZ%d = 0x%08x\n", i, ++ (size / ram_width) << DWC_FIFOSZ_DEPTH_SHIFT | ++ prev_start << DWC_FIFOSZ_STARTADDR_SHIFT); ++ dwc_wr32(dev, &global_regs->gtxfifosiz[i], ++ (size / ram_width) << DWC_FIFOSZ_DEPTH_SHIFT | ++ prev_start << DWC_FIFOSZ_STARTADDR_SHIFT); ++ dwc_debug2(dev, "GTXFIFOSIZ%d = 0x%08x\n", i, ++ dwc_rd32(dev, &global_regs->gtxfifosiz[i])); ++ prev_start += size / ram_width; ++ } ++txerr: ++ return; ++} ++ ++/** ++ * Set the size of the Rx FIFO ++ * ++ * NOTE: The following code for setting the FIFO sizes only ++ * works for cores configured with the 3 RAM option. Setting ++ * FIFO sizes for the 2 RAM option is not implemented. ++ * ++ * @param dev Programming view of DWC_usb3 controller. ++ * @param size New size for the FIFO. ++ */ ++void dwc_usb3_set_rx_fifo_size(dwc_usb3_device_t *dev, int size) ++{ ++ dwc_usb3_core_global_regs_t __iomem *global_regs = ++ dev->core_global_regs; ++ u32 sz, rxthrcfg; ++ int ram_width, ram_depth, prev_start, cnt, bst; ++ ++ ram_width = (dev->hwparams0 >> DWC_HWP0_MDWIDTH_SHIFT & ++ DWC_HWP0_MDWIDTH_BITS >> DWC_HWP0_MDWIDTH_SHIFT) ++ / 8; ++ ram_depth = (dev->hwparams7 >> DWC_HWP7_RAM2_DEPTH_SHIFT & ++ DWC_HWP7_RAM2_DEPTH_BITS >> DWC_HWP7_RAM2_DEPTH_SHIFT) ++ * ram_width; ++ sz = dwc_rd32(dev, &global_regs->grxfifosiz[0]); ++ prev_start = sz >> DWC_FIFOSZ_STARTADDR_SHIFT & ++ DWC_FIFOSZ_STARTADDR_BITS >> DWC_FIFOSZ_STARTADDR_SHIFT; ++ ++ if (size < 512 + 24 + 16 + (ram_width == 16 ? 24 : 0)) { ++ dwc_print0(dev, "Requested Rx FIFO size too small\n"); ++ dwc_print0(dev, "Not setting Rx FIFO size\n"); ++ goto rxerr; ++ } ++ ++ size = (size + ram_width - 1) & ~(ram_width - 1); ++ if (size > ram_depth) { ++ dwc_print0(dev, "Requested Rx FIFO size too large\n"); ++ dwc_print0(dev, "Not setting Rx FIFO size\n"); ++ goto rxerr; ++ } ++ ++ dwc_debug1(dev, "Setting GRXFIFOSIZ0 = 0x%08x\n", ++ (size / ram_width) << DWC_FIFOSZ_DEPTH_SHIFT | ++ prev_start << DWC_FIFOSZ_STARTADDR_SHIFT); ++ dwc_wr32(dev, &global_regs->grxfifosiz[0], ++ (size / ram_width) << DWC_FIFOSZ_DEPTH_SHIFT | ++ prev_start << DWC_FIFOSZ_STARTADDR_SHIFT); ++ dwc_debug1(dev, "GRXFIFOSIZ0 = 0x%08x\n", ++ dwc_rd32(dev, &global_regs->grxfifosiz[0])); ++ dwc_debug2(dev, "Rx FIFO size = %d bytes out of %d available\n", ++ size, ram_depth); ++ ++ /* ++ * If thresholding is enabled in GRXTHRCFG, update USBRxPktCnt according ++ * to the new FIFO size ++ */ ++ rxthrcfg = dwc_rd32(dev, &global_regs->grxthrcfg); ++ dwc_debug1(dev, "GRXTHRCFG = 0x%08x\n", rxthrcfg); ++ if (rxthrcfg & DWC_RXTHRCTL_USB_RX_PKT_CNT_EN_BIT) { ++ cnt = (size - ram_width * 4) / 1024; ++ if (cnt > 0) { ++ if (cnt > DWC_RXTHRCTL_USB_RX_PKT_CNT_BITS >> ++ DWC_RXTHRCTL_USB_RX_PKT_CNT_SHIFT) ++ cnt = DWC_RXTHRCTL_USB_RX_PKT_CNT_BITS >> ++ DWC_RXTHRCTL_USB_RX_PKT_CNT_SHIFT; ++ bst = rxthrcfg >> ++ DWC_RXTHRCTL_USB_MAX_RX_BURST_SIZE_SHIFT & ++ DWC_RXTHRCTL_USB_MAX_RX_BURST_SIZE_BITS >> ++ DWC_RXTHRCTL_USB_MAX_RX_BURST_SIZE_SHIFT; ++ if (cnt > bst) ++ cnt = bst; ++ if (cnt < 1) ++ goto disable; ++ rxthrcfg &= ~DWC_RXTHRCTL_USB_RX_PKT_CNT_BITS; ++ rxthrcfg |= cnt << DWC_RXTHRCTL_USB_RX_PKT_CNT_SHIFT; ++ } else { ++disable: ++ rxthrcfg &= ~DWC_RXTHRCTL_USB_RX_PKT_CNT_EN_BIT; ++ } ++ dwc_debug1(dev, "Setting GRXTHRCFG = 0x%08x\n", rxthrcfg); ++ dwc_wr32(dev, &global_regs->grxthrcfg, rxthrcfg); ++ } ++rxerr: ++ return; ++} ++ ++/** ++ * This routine initializes the DWC_usb3 controller registers. ++ * ++ * If the soft_reset parameter is ++ * true, then this routine must be called in a context that ++ * allows dwc_msleep() to be used, because that function is called ++ * while waiting for the core to come out of reset. ++ * ++ * This routine is called by dwc_usb3_pcd_init() when the driver is loaded, ++ * so it normally does not need to be called separately, except in special ++ * circumstances, such as when exiting from hibernation. ++ * ++ * @param dev Programming view of DWC_usb3 controller. ++ * @param soft_reset True if doing a soft reset of the core. ++ * @param restore True if restoring register state after hibernation. ++ */ ++void dwc_usb3_pcd_device_init(dwc_usb3_device_t *dev, int soft_reset, ++ int restore) ++{ ++ dwc_usb3_core_global_regs_t __iomem *global_regs = ++ dev->core_global_regs; ++ dwc_usb3_pcd_t *pcd = &dev->pcd; ++ u32 temp; ++ int i, ram_width, ram_depth, size; ++ ++ dwc_debug1(dev, "%s()\n", __func__); ++ ++ if (dev->program_gsbuscfg) { ++ dwc_debug2(dev, "Programming SBUSCFG0,1 to %08x %08x\n", ++ dev->gsbuscfg0, dev->gsbuscfg1); ++ dwc_wr32(dev, &global_regs->gsbuscfg0, dev->gsbuscfg0); ++ dwc_wr32(dev, &global_regs->gsbuscfg1, dev->gsbuscfg1); ++ } ++ ++ if (dev->soft_reset_hook) { ++ dev->soft_reset_hook(dev, soft_reset, restore); ++ } else { ++ /* ++ * TODO Workaround: PCD can't handle soft reset during HNP. ++ * RTL issue will be fixed. Skip the reset when called with ++ * soft_reset=0. When not configured for OTG do the reset ++ * unconditionally. ++ */ ++ if (soft_reset) { ++ /* Soft-reset the core */ ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dctl); ++ temp &= ~DWC_DCTL_RUN_STOP_BIT; ++ temp |= DWC_DCTL_CSFT_RST_BIT; ++ dwc_wr32(dev, &pcd->dev_global_regs->dctl, temp); ++ ++ /* Wait for core to come out of reset */ ++ do { ++ dwc_msleep(dev, 1); ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dctl); ++ } while (temp & DWC_DCTL_CSFT_RST_BIT); ++ ++ /* Wait for at least 3 PHY clocks */ ++ dwc_msleep(dev, 1); ++ } ++ } ++ ++ /* Soft reset clears the GSBUSCFG registers, so write them again */ ++ if (dev->program_gsbuscfg) { ++ dwc_debug2(dev, "Programming SBUSCFG0,1 to %08x %08x\n", ++ dev->gsbuscfg0, dev->gsbuscfg1); ++ dwc_wr32(dev, &global_regs->gsbuscfg0, dev->gsbuscfg0); ++ dwc_wr32(dev, &global_regs->gsbuscfg1, dev->gsbuscfg1); ++ } ++ ++ pcd->link_state = 0; ++ pcd->wkup_rdy = 0; ++ ++ if (dev->phy_config_hook) { ++ dev->phy_config_hook(dev, soft_reset, restore); ++ } ++ ++ if (dev->fifo_sizing_hook) { ++ dev->fifo_sizing_hook(dev, soft_reset, restore); ++ } else { ++ /* ++ * Set Tx FIFO sizes ++ */ ++ ram_width = (dev->hwparams0 >> DWC_HWP0_MDWIDTH_SHIFT & ++ DWC_HWP0_MDWIDTH_BITS >> DWC_HWP0_MDWIDTH_SHIFT) ++ / 8; ++ ram_depth = (dev->hwparams7 >> DWC_HWP7_RAM1_DEPTH_SHIFT & ++ DWC_HWP7_RAM1_DEPTH_BITS >> DWC_HWP7_RAM1_DEPTH_SHIFT) ++ * ram_width; ++ dwc_debug2(dev, "RAM width:%d RAM1 depth:%d\n", ram_width, ram_depth); ++ ++ for (i = 0; i < pcd->num_in_eps + 1; i++) { ++ size = dwc_rd32(dev, &global_regs->gtxfifosiz[i]); ++ dwc_debug2(dev, "Initial GTXFIFOSIZ%d = 0x%08x\n", i, size); ++ } ++ ++ /* Only set if non-default Tx FIFO sizes were requested */ ++ if (dev->core_params->txfsz_cnt) ++ dwc_usb3_set_tx_fifo_size(dev, dev->core_params->txfsz); ++ ++ /* ++ * Set Rx FIFO size ++ */ ++ ram_depth = (dev->hwparams7 >> DWC_HWP7_RAM2_DEPTH_SHIFT & ++ DWC_HWP7_RAM2_DEPTH_BITS >> DWC_HWP7_RAM2_DEPTH_SHIFT) ++ * ram_width; ++ dwc_debug1(dev, "RAM2 depth:%d\n", ram_depth); ++ size = dwc_rd32(dev, &global_regs->grxfifosiz[0]); ++ dwc_debug1(dev, "Initial GRXFIFOSIZ0 = 0x%08x\n", size); ++ size = dev->core_params->rxfsz; ++ ++ /* Only set if non-default Rx FIFO size was requested */ ++ if (size) ++ dwc_usb3_set_rx_fifo_size(dev, size); ++ } ++ ++#if 1 ++ if (dev->gctl_init_hook) { ++ dev->gctl_init_hook(dev, soft_reset, restore); ++ } else { ++ temp = dwc_rd32(dev, &global_regs->gctl); ++ temp &= ~(DWC_GCTL_PRT_CAP_DIR_BITS | DWC_GCTL_SCALE_DOWN_BITS); ++ ++#ifdef DWC_STAR_9000468158_WORKAROUND ++ temp |= DWC_GCTL_U2RSTECN_BIT; ++#endif ++#ifdef CONFIG_USB_OTG_DWC ++ temp |= DWC_GCTL_PRT_CAP_OTG << DWC_GCTL_PRT_CAP_DIR_SHIFT; ++#else ++ temp |= DWC_GCTL_PRT_CAP_DEVICE << DWC_GCTL_PRT_CAP_DIR_SHIFT; ++#endif ++#ifdef COSIM ++ /* Scale down, disable scrambling */ ++ temp |= 3 << DWC_GCTL_SCALE_DOWN_SHIFT | DWC_GCTL_DIS_SCRAMBLE_BIT; ++#else ++# if 1 ++ temp &= ~DWC_GCTL_PWR_DN_SCALE_BITS; ++ ++ switch (dev->core_params->phy) { ++ case 3: // 16-bit UTMI+ SNPS Phy ++ case 2: // 8-bit UTMI+ / ULPI TI or SNPS Phy ++ /* Set power down scale */ ++ temp |= 0x270 << DWC_GCTL_PWR_DN_SCALE_SHIFT; ++ break; ++ case 1: // old 8-bit UTMI+ SNPS Phy ++ /* Set LFPS filter */ ++ dwc_wr32(dev, &global_regs->gusb3pipectl[0], ++ DWC_PIPECTL_LFPS_FILTER_BIT | ++ 1 << DWC_PIPECTL_TX_DEMPH_SHIFT); ++ ++ /* Set power down scale */ ++ temp |= 0x270 << DWC_GCTL_PWR_DN_SCALE_SHIFT; ++ break; ++ default: // RocketIO Phy ++ /* Set power down scale, disable scrambling */ ++ temp |= 0x1e84 << DWC_GCTL_PWR_DN_SCALE_SHIFT | ++ DWC_GCTL_DEBUG_ATTACH_BIT | ++ DWC_GCTL_DIS_SCRAMBLE_BIT; ++ } ++# endif ++#endif ++ dwc_wr32(dev, &global_regs->gctl, temp); ++ } ++#endif ++ /* Initialize the Event Buffer registers */ ++ dwc_usb3_init_eventbuf(dev, 0, dev->event_buf[0], DWC_EVENT_BUF_SIZE, ++ dev->event_buf_dma[0]); ++ dev->event_ptr[0] = dev->event_buf[0]; ++ ++#ifdef CONFIG_USB_OTG_DWC ++ /* TODO Workaround: this is a workaround for OTG 3.0 where the utmi ++ * clock doesn't come unless the device speed is momentarily programmed ++ * to HS. This causes the peripheral state on OSTS to not get set ++ * properly. ++ */ ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dcfg); ++ temp &= ~(DWC_DCFG_DEVSPD_BITS << DWC_DCFG_DEVSPD_SHIFT); ++ temp |= DWC_SPEED_HS_PHY_30MHZ_OR_60MHZ << DWC_DCFG_DEVSPD_SHIFT; ++ dwc_wr32(dev, &pcd->dev_global_regs->dcfg, temp); ++ dwc_udelay(dev, 200); ++#endif ++ ++ /* If forcing to a USB2 mode was requested */ ++ if (dev->core_params->usb2mode == 1) { ++ /* Set speed to Full */ ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dcfg); ++ temp &= ~(DWC_DCFG_DEVSPD_BITS << DWC_DCFG_DEVSPD_SHIFT); ++ temp |= DWC_SPEED_FS_PHY_30MHZ_OR_60MHZ ++ << DWC_DCFG_DEVSPD_SHIFT; ++ dwc_wr32(dev, &pcd->dev_global_regs->dcfg, temp); ++ ++ } else if ((dev->core_params->usb2mode == 2) ++#ifdef CONFIG_USB_OTG_DWC ++ /* Check the OTG_SS bit when in OTG mode to see if superspeed ++ * is supported ++ */ ++ || !(dev->hwparams6 & DWC_HWP6_EN_OTG_BIT) ++#endif ++ ) { ++ /* Set speed to High */ ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dcfg); ++ temp &= ~(DWC_DCFG_DEVSPD_BITS << DWC_DCFG_DEVSPD_SHIFT); ++ temp |= DWC_SPEED_HS_PHY_30MHZ_OR_60MHZ ++ << DWC_DCFG_DEVSPD_SHIFT; ++ dwc_wr32(dev, &pcd->dev_global_regs->dcfg, temp); ++ ++ } else { ++ /* Set speed to Super */ ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dcfg); ++ temp &= ~(DWC_DCFG_DEVSPD_BITS << DWC_DCFG_DEVSPD_SHIFT); ++ ++ if ((dev->hwparams3 & DWC_HWP3_SSPHY_IFC_BITS) == 0) ++ temp |= DWC_SPEED_HS_PHY_30MHZ_OR_60MHZ ++ << DWC_DCFG_DEVSPD_SHIFT; ++ else ++ temp |= DWC_SPEED_SS_PHY_125MHZ_OR_250MHZ ++ << DWC_DCFG_DEVSPD_SHIFT; ++ dwc_wr32(dev, &pcd->dev_global_regs->dcfg, temp); ++ } ++ ++ /* If LPM enable was requested */ ++ if (dev->core_params->lpmctl) { ++ /* Set LPMCap bit */ ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dcfg); ++ temp |= DWC_DCFG_LPM_CAP_BIT; ++ dwc_wr32(dev, &pcd->dev_global_regs->dcfg, temp); ++ ++ if (dev->core_params->lpmctl > 1) { ++ /* Set AppL1Res bit */ ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dctl); ++ temp |= DWC_DCTL_APP_L1_RES_BIT; ++ dwc_wr32(dev, &pcd->dev_global_regs->dctl, temp); ++ } ++ } ++ ++ /* If non-default NUMP was requested */ ++ if (dev->core_params->nump > 0 && dev->core_params->nump <= 16) { ++ /* Set NUMP */ ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dcfg); ++ temp &= ~DWC_DCFG_NUM_RCV_BUF_BITS; ++ temp |= dev->core_params->nump << DWC_DCFG_NUM_RCV_BUF_SHIFT; ++ dwc_wr32(dev, &pcd->dev_global_regs->dcfg, temp); ++ } ++ ++ if (dev->set_address_hook) { ++ dev->set_address_hook(dev, soft_reset, restore); ++ } else { ++ if (!restore) ++ /* Set device address to 0 */ ++ dwc_usb3_set_address(pcd, 0); ++ } ++ ++ /* Enable hibernation if supported */ ++ if (dev->core_params->hibernate && ++ (dev->hwparams1 & DWC_HWP1_EN_PWROPT_BITS) == ++ DWC_EN_PWROPT_HIBERNATION << DWC_HWP1_EN_PWROPT_SHIFT) { ++ /* Enable global hibernation bit */ ++ temp = dwc_rd32(dev, &global_regs->gctl); ++ temp |= DWC_GCTL_GBL_HIBER_EN_BIT; ++ if (dev->core_params->clkgatingen) ++ temp &= ~DWC_GCTL_DSBL_CLCK_GTNG_BIT; ++ else ++ temp |= DWC_GCTL_DSBL_CLCK_GTNG_BIT; ++ dwc_wr32(dev, &global_regs->gctl, temp); ++ ++ if (dev->core_params->lpmctl) { ++ /* Set L1 hibernation values */ ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dctl); ++ temp &= ~DWC_DCTL_HIRD_THR_BITS; ++ if (dev->hird_thresh) ++ temp |= dev->hird_thresh << DWC_DCTL_HIRD_THR_SHIFT & ++ DWC_DCTL_HIRD_THR_BITS; ++ else ++ temp |= 0x1c << DWC_DCTL_HIRD_THR_SHIFT; ++ ++ /* Enable L1 hibernation */ ++ temp |= DWC_DCTL_L1_HIBER_EN_BIT; ++ dwc_wr32(dev, &pcd->dev_global_regs->dctl, temp); ++ } ++ ++ if (!restore) { ++ /* Issue Set Scratchpad Buffer Array command */ ++ dwc_usb3_set_scratchpad_buf_array(pcd, ++ pcd->hiber_scratchpad_array_dma); ++ } ++ ++ /* Set GUSB2PHYCFG[6] (suspend 2.0 phy) */ ++ temp = dwc_rd32(dev, &global_regs->gusb2phycfg[0]); ++ temp |= DWC_USB2PHYCFG_SUS_PHY_BIT; ++ if (dev->core_params->lpmctl) ++ temp |= DWC_USB2PHYCFG_ENBL_SLP_M_BIT; ++ dwc_wr32(dev, &global_regs->gusb2phycfg[0], temp); ++ ++#ifndef SELA_PLATFORM ++ /* Set GUSB3PIPECTL[17] (suspend SS phy) */ ++ temp = dwc_rd32(dev, &global_regs->gusb3pipectl[0]); ++ temp |= DWC_PIPECTL_SUS_PHY_BIT; ++ dwc_wr32(dev, &global_regs->gusb3pipectl[0], temp); ++#endif ++ } else { ++ if (dev->core_params->phyctl) { ++ /* Enable Phy suspend */ ++ dwc_usb3_ena_usb3_phy_suspend(pcd); ++ dwc_usb3_ena_usb2_phy_suspend(pcd); ++ } else { ++ /* Disable Phy suspend */ ++ dwc_usb3_dis_usb3_phy_suspend(pcd); ++ dwc_usb3_dis_usb2_phy_suspend(pcd); ++ } ++ } ++ ++#ifndef CONFIG_USB_OTG_DWC ++ /* Enable Global and Device interrupts */ ++ dwc_usb3_enable_device_interrupts(dev); ++#endif ++ /* Activate EP0 */ ++ dwc_usb3_ep0_activate(pcd, restore); ++ ++ if (dev->ep0_start_hook) { ++ dev->ep0_start_hook(dev, soft_reset, restore); ++ } else { ++ /* Start EP0 to receive SETUP packets */ ++ dwc_usb3_pcd_ep0_out_start(pcd); ++ } ++ ++ /* Enable EP0-OUT/IN in DALEPENA register */ ++ dwc_wr32(dev, &pcd->dev_global_regs->dalepena, 3); ++ ++ pcd->eps_enabled = 0; ++ ++#ifndef CONFIG_USB_OTG_DWC ++ /* Set Run/Stop bit, and Keep-Connect bit if hibernation enabled */ ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dctl); ++ temp |= DWC_DCTL_RUN_STOP_BIT; ++ if (dev->core_params->hibernate && ++ (dev->hwparams1 & DWC_HWP1_EN_PWROPT_BITS) == ++ DWC_EN_PWROPT_HIBERNATION << DWC_HWP1_EN_PWROPT_SHIFT) ++ temp |= DWC_DCTL_KEEP_CONNECT_BIT; ++ dwc_wr32(dev, &pcd->dev_global_regs->dctl, temp); ++#endif ++ ++#ifdef SSIC ++ dwc_debug(dev, "SSIC Initialization\n"); ++ temp = dwc_rd32(dev, &dev->core_global_regs->gusb3pipectl[0]); ++ temp |= DWC_PIPECTL_SSIC_EN_BIT; ++ temp |= DWC_PIPECTL_PHY_SOFT_RST_BIT; ++ dwc_wr32(dev, &dev->core_global_regs->gusb3pipectl[0], temp); ++ dwc_wr32(dev, &dev->ssic_regs->sctl[0], 0); ++ dwc_wr32(dev, &dev->ssic_regs->sevt[0], 0xffffffff); ++ dwc_wr32(dev, &dev->ssic_regs->sevten[0], 0); ++ dwc_wr32(dev, &dev->ssic_regs->sevten[0], ++ DWC_SEVTEN_ROM_INIT_CMPLT_EN_BIT | DWC_SEVTEN_MPHY_ST_CHNGD_EN_BIT); ++ ++ temp = dwc_rd32(dev, &dev->core_global_regs->gusb3rmmictl[0]); ++ temp &= ~(DWC_RMMICTL_AUTO_EXIT_RRAP_BIT | DWC_RMMICTL_AUTO_ROM_RRAP_BIT | ++ DWC_RMMICTL_AUTO_EXIT_H8_BIT | DWC_RMMICTL_AUTO_ROM_H8_BIT); ++ dwc_wr32(dev, &dev->core_global_regs->gusb3rmmictl[0], temp); ++ ++ temp = dwc_rd32(dev, &dev->core_global_regs->gusb3pipectl[0]); ++ temp &= ~DWC_PIPECTL_PHY_SOFT_RST_BIT; ++ dwc_wr32(dev, &dev->core_global_regs->gusb3pipectl[0], temp); ++ ++ if (!handshake(dev, &dev->core_global_regs->gusb3rmmictl[0], ++ DWC_RMMICTL_MPHY_STATE_BITS, ++ (DWC_MPHY_STATE_HIBERN8 << DWC_RMMICTL_MPHY_STATE_SHIFT))) { ++ dwc_error(dev, "%s: wait for mphy state hibern8 timed out\n", __func__); ++ } ++ ++ temp = dwc_rd32(dev, &dev->ssic_regs->sevten[0]); ++ temp |= (DWC_SEVTEN_RCMD_RES_SENT_EN_BIT | ++ DWC_SEVTEN_RCMD_RES_RCVD_EN_BIT | ++ DWC_SEVTEN_LACC_CMPLT_EN_BIT); ++ dwc_wr32(dev, &dev->ssic_regs->sevten[0], temp); ++ ++ temp = dwc_rd32(dev, &dev->ssic_regs->sctl[0]); ++ temp |= DWC_SCTL_CFG_DONE_BIT; ++ dwc_wr32(dev, &dev->ssic_regs->sctl[0], temp); ++ ++ if (!handshake(dev, &dev->ssic_regs->sctl[0], ++ DWC_SCTL_CFG_DONE_BIT, 0)) { ++ dwc_error(dev, "%s: cfg done timed out\n", __func__); ++ } ++#endif ++} ++ ++/** ++ * This routine deinitializes the DWC_usb3 controller registers. ++ * ++ * This routine is called by dwc_usb3_pcd_remove() when the driver is unloaded, ++ * so it normally does not need to be called separately, ++ * ++ * @param dev Programming view of DWC_usb3 controller. ++ */ ++void dwc_usb3_pcd_device_remove(dwc_usb3_device_t *dev) ++{ ++ dwc_usb3_core_global_regs_t __iomem *global_regs = ++ dev->core_global_regs; ++ dwc_usb3_pcd_t *pcd = &dev->pcd; ++ u32 temp; ++ ++ if (dev->hibernate >= DWC_HIBER_SLEEPING) ++ return; ++ ++ /* Clear the Run/Stop and Keep-Connect bits */ ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dctl); ++ temp &= ~(DWC_DCTL_RUN_STOP_BIT | DWC_DCTL_KEEP_CONNECT_BIT); ++ dwc_wr32(dev, &pcd->dev_global_regs->dctl, temp); ++ ++ /* Disable device interrupts */ ++ dwc_wr32(dev, &pcd->dev_global_regs->devten, 0); ++ ++ /* Disable hibernation if supported */ ++ if (dev->core_params->hibernate && ++ (dev->hwparams1 & DWC_HWP1_EN_PWROPT_BITS) == ++ DWC_EN_PWROPT_HIBERNATION << DWC_HWP1_EN_PWROPT_SHIFT) { ++ /* Clear GUSB3PIPECTL[17] (suspend SS phy) */ ++ temp = dwc_rd32(dev, &global_regs->gusb3pipectl[0]); ++ temp &= ~DWC_PIPECTL_SUS_PHY_BIT; ++ dwc_wr32(dev, &global_regs->gusb3pipectl[0], temp); ++ ++ /* Clear GUSB2PHYCFG[6] (suspend 2.0 phy) */ ++ temp = dwc_rd32(dev, &global_regs->gusb2phycfg[0]); ++ temp &= ~DWC_USB2PHYCFG_SUS_PHY_BIT; ++ temp &= ~DWC_USB2PHYCFG_ENBL_SLP_M_BIT; ++ dwc_wr32(dev, &global_regs->gusb2phycfg[0], temp); ++ ++ /* Disable L1 hibernation */ ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dctl); ++ temp &= ~DWC_DCTL_L1_HIBER_EN_BIT; ++ dwc_wr32(dev, &pcd->dev_global_regs->dctl, temp); ++ ++ /* Disable global hibernation bit */ ++ temp = dwc_rd32(dev, &global_regs->gctl); ++ temp &= ~DWC_GCTL_GBL_HIBER_EN_BIT; ++ temp |= DWC_GCTL_DSBL_CLCK_GTNG_BIT; ++ dwc_wr32(dev, &global_regs->gctl, temp); ++ } ++} +diff --git a/drivers/usb/gadget/udc/hiudc3/cil.h b/drivers/usb/gadget/udc/hiudc3/cil.h +new file mode 100644 +index 0000000..1799e2a +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/cil.h +@@ -0,0 +1,211 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/DWC_usb3/driver/cil.h $ ++ * $Revision: #45 $ ++ * $Date: 2014/11/11 $ ++ * $Change: 2664766 $ ++ * ++ * Synopsys SS USB3 Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 _DWC_CIL_H_ ++#define _DWC_CIL_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * @file ++ * This file contains the interface to the Core Interface Layer. ++ */ ++ ++/** @addtogroup init_api_grp Initialization API Routines ++ * ++ * These routines handle initialization of the CIL and PCD driver components ++ * and the DWC_usb3 controller. ++ */ ++/** @{ */ ++extern int dwc_usb3_pcd_check_snpsid(dwc_usb3_device_t *dev, u32 addr_ofs); ++extern int dwc_usb3_pcd_common_init(dwc_usb3_device_t *dev, ++ volatile u8 __iomem *base, ++ dwc_usb3_core_params_t *core_params); ++extern void dwc_usb3_pcd_common_remove(dwc_usb3_device_t *dev); ++extern void dwc_usb3_pcd_device_init(dwc_usb3_device_t *dev, int soft_reset, ++ int restore); ++extern void dwc_usb3_pcd_device_remove(dwc_usb3_device_t *dev); ++/** @} */ ++ ++/** @addtogroup misc_api_grp */ ++/** @{ */ ++extern int dwc_usb3_pcd_get_link_state(dwc_usb3_pcd_t *pcd); ++extern void dwc_usb3_pcd_set_link_state(dwc_usb3_pcd_t *pcd, int state); ++extern void dwc_usb3_pcd_remote_wake(dwc_usb3_pcd_t *pcd, int function); ++extern void dwc_usb3_pcd_do_test_mode(unsigned long data); ++/** @} */ ++ ++/* Peripheral CIL Routines ++ * ++ * The following routines support managing the DWC_usb3 controller in ++ * peripheral mode. ++ */ ++extern void dwc_usb3_fill_desc(dwc_usb3_dma_desc_t *desc, dwc_dma_t dma_addr, ++ u32 dma_len, u32 stream, u32 type, ++ u32 ctrlbits, int own); ++extern void dwc_usb3_start_desc_chain(dwc_usb3_dma_desc_t *desc); ++extern void dwc_usb3_end_desc_chain(dwc_usb3_dma_desc_t *desc); ++extern void dwc_usb3_enable_desc(dwc_usb3_dma_desc_t *desc); ++extern void dwc_usb3_disable_desc(dwc_usb3_dma_desc_t *desc); ++extern int dwc_usb3_xmit_fn_remote_wake(dwc_usb3_pcd_t *pcd, u32 intf); ++extern int dwc_usb3_xmit_ltm(dwc_usb3_pcd_t *pcd, u32 value); ++extern int dwc_usb3_xmit_host_role_request(dwc_usb3_pcd_t *pcd, u32 param); ++extern int dwc_usb3_set_scratchpad_buf_array(dwc_usb3_pcd_t *pcd, ++ dwc_dma_t dma_addr); ++extern int dwc_usb3_flush_fifo(dwc_usb3_pcd_t *pcd, u32 fifo_sel); ++extern int dwc_usb3_dep_cfg(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, ++ u32 depcfg0, u32 depcfg1, ++ u32 depcfg2); ++extern int dwc_usb3_dep_xfercfg(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, ++ u32 depstrmcfg); ++extern u32 dwc_usb3_dep_getepstate(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg); ++extern int dwc_usb3_dep_sstall(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg); ++extern int dwc_usb3_dep_cstall(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, ++ int clr_pend); ++extern int dwc_usb3_dep_startxfer(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, ++ dwc_dma_t dma_addr, u32 stream_or_uf); ++extern int dwc_usb3_dep_updatexfer(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, ++ u32 tri); ++extern int dwc_usb3_dep_endxfer(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, ++ u32 tri, int flags, void *condition); ++#define DWC_ENDXFER_FORCE 1 ++#define DWC_ENDXFER_NODELAY 2 ++ ++#ifdef DWC_STAR_9000463548_WORKAROUND ++extern int dwc_usb3_dep_endxfer_nowait(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, ++ u32 tri, int flags); ++extern int dwc_usb3_dep_wait_endxfer(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, ++ void *condition); ++#endif ++extern int dwc_usb3_dep_startnewcfg(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, ++ u32 rsrcidx); ++extern int dwc_usb3_enable_ep(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep); ++extern int dwc_usb3_disable_ep(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep); ++extern int dwc_usb3_get_device_speed(dwc_usb3_pcd_t *pcd); ++extern int dwc_usb3_get_frame(dwc_usb3_pcd_t *pcd); ++extern void dwc_usb3_set_address(dwc_usb3_pcd_t *pcd, int addr); ++extern void dwc_usb3_ena_usb2_suspend(dwc_usb3_pcd_t *pcd); ++extern void dwc_usb3_dis_usb2_suspend(dwc_usb3_pcd_t *pcd); ++extern void dwc_usb3_accept_u1(dwc_usb3_pcd_t *pcd); ++extern void dwc_usb3_accept_u2(dwc_usb3_pcd_t *pcd); ++extern void dwc_usb3_enable_u1(dwc_usb3_pcd_t *pcd); ++extern void dwc_usb3_enable_u2(dwc_usb3_pcd_t *pcd); ++extern void dwc_usb3_disable_u1(dwc_usb3_pcd_t *pcd); ++extern void dwc_usb3_disable_u2(dwc_usb3_pcd_t *pcd); ++extern int dwc_usb3_u1_enabled(dwc_usb3_pcd_t *pcd); ++extern int dwc_usb3_u2_enabled(dwc_usb3_pcd_t *pcd); ++extern void dwc_usb3_clr_eps_enabled(dwc_usb3_pcd_t *pcd); ++ ++extern void dwc_usb3_dump_dev_registers(dwc_usb3_pcd_t *pcd); ++ ++#define dwc_usb3_is_hwo(desc) ((desc)->control & DWC_DSCCTL_HWO_BIT) ++#define dwc_usb3_is_ioc(desc) ((desc)->control & DWC_DSCCTL_IOC_BIT) ++ ++#define dwc_usb3_get_xfercnt(desc) \ ++ ((desc)->status >> DWC_DSCSTS_XFRCNT_SHIFT & \ ++ DWC_DSCSTS_XFRCNT_BITS >> DWC_DSCSTS_XFRCNT_SHIFT) ++ ++#define dwc_usb3_get_xfersts(desc) \ ++ ((desc)->status >> DWC_DSCSTS_TRBRSP_SHIFT & \ ++ DWC_DSCSTS_TRBRSP_BITS >> DWC_DSCSTS_TRBRSP_SHIFT) ++ ++#define dwc_usb3_get_xfersofn(desc) \ ++ ((desc)->control >> DWC_DSCCTL_STRMID_SOFN_SHIFT & \ ++ DWC_DSCCTL_STRMID_SOFN_BITS >> DWC_DSCCTL_STRMID_SOFN_SHIFT) ++ ++#define dwc_usb3_get_eventsofn(event) \ ++ ((event) >> DWC_DEPEVT_ISOC_UFRAME_NUM_SHIFT & \ ++ DWC_DEPEVT_ISOC_UFRAME_NUM_BITS >> DWC_DEPEVT_ISOC_UFRAME_NUM_SHIFT) ++ ++/* Common CIL Routines ++ */ ++extern void dwc_usb3_dump_dbgregs(dwc_usb3_device_t *dev); ++extern void dwc_usb3_dump_global_registers(dwc_usb3_device_t *dev); ++extern void dwc_usb3_set_tx_fifo_size(dwc_usb3_device_t *dev, int *sz); ++extern void dwc_usb3_set_rx_fifo_size(dwc_usb3_device_t *dev, int size); ++extern void dwc_usb3_init_eventbuf(dwc_usb3_device_t *dev, int bufno, ++ u32 *addr, unsigned int size, dwc_dma_t dma_addr); ++extern void dwc_usb3_dis_flush_eventbuf_intr(dwc_usb3_device_t *dev, int bufno); ++extern void dwc_usb3_enable_common_interrupts(dwc_usb3_device_t *dev); ++extern void dwc_usb3_enable_device_interrupts(dwc_usb3_device_t *dev); ++extern int dwc_usb3_handle_event(dwc_usb3_device_t *dev); ++extern int dwc_usb3_irq(dwc_usb3_device_t *dev, int irq); ++ ++/** ++ * This routine returns the current operating mode, host or device. ++ * ++ * @return 0 - Device Mode, 1 - Host Mode ++ */ ++static __inline u32 dwc_usb3_mode(dwc_usb3_device_t *dev) ++{ ++ return dwc_rd32(dev, &dev->core_global_regs->gsts) & 0x1; ++} ++ ++/** ++ * This routine returns true if the current operating mode is Device. ++ * ++ * @return 1 - Device mode, 0 - Not Device mode ++ */ ++static __inline int dwc_usb3_is_device_mode(dwc_usb3_device_t *dev) ++{ ++ return dwc_usb3_mode(dev) != DWC_GSTS_HOST_MODE; ++} ++ ++/** ++ * This routine returns true if the current operating mode is Host. ++ * ++ * @return 1 - Host mode, 0 - Not Host mode ++ */ ++static __inline int dwc_usb3_is_host_mode(dwc_usb3_device_t *dev) ++{ ++ return dwc_usb3_mode(dev) == DWC_GSTS_HOST_MODE; ++} ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_CIL_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc3/cil_intr.c b/drivers/usb/gadget/udc/hiudc3/cil_intr.c +new file mode 100644 +index 0000000..300faca +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/cil_intr.c +@@ -0,0 +1,596 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/DWC_usb3/driver/cil_intr.c $ ++ * $Revision: #39 $ ++ * $Date: 2014/11/11 $ ++ * $Change: 2664766 $ ++ * ++ * Synopsys SS USB3 Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ * The Core Interface Layer provides basic services for accessing and ++ * managing the DWC_usb3 hardware. These services are used by both the ++ * Peripheral Controller Driver and the On The Go Driver. ++ * ++ * This file contains the common interrupt handling functions. ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++ ++/** ++ * This routine enables the Event Buffer interrupt. ++ */ ++static void ena_eventbuf_intr(dwc_usb3_device_t *dev, int bufno) ++{ ++ u32 eventsiz; ++ ++ eventsiz = ++ dwc_rd32(dev, &dev->core_global_regs->geventbuf[bufno].geventsiz); ++ eventsiz &= ~DWC_EVENTSIZ_INT_MSK_BIT; ++ dwc_wr32(dev, &dev->core_global_regs->geventbuf[bufno].geventsiz, ++ eventsiz); ++} ++ ++/** ++ * This routine disables the Event Buffer interrupt. ++ */ ++static void dis_eventbuf_intr(dwc_usb3_device_t *dev, int bufno) ++{ ++ u32 eventsiz; ++ ++ eventsiz = ++ dwc_rd32(dev, &dev->core_global_regs->geventbuf[bufno].geventsiz); ++ eventsiz |= DWC_EVENTSIZ_INT_MSK_BIT; ++ dwc_wr32(dev, &dev->core_global_regs->geventbuf[bufno].geventsiz, ++ eventsiz); ++} ++ ++/** ++ * This routine disables the Event Buffer interrupt and flushes any pending ++ * events from the buffer. ++ */ ++void dwc_usb3_dis_flush_eventbuf_intr(dwc_usb3_device_t *dev, int bufno) ++{ ++ u32 cnt; ++ ++ if (dev->hibernate >= DWC_HIBER_SLEEPING) ++ return; ++ ++ dis_eventbuf_intr(dev, bufno); ++ cnt = dwc_rd32(dev, &dev->core_global_regs->geventbuf[bufno].geventcnt); ++ dwc_wr32(dev, &dev->core_global_regs->geventbuf[bufno].geventcnt, cnt); ++} ++ ++/** ++ * This routine reads the current Event Buffer count. ++ */ ++static int get_eventbuf_count(dwc_usb3_device_t *dev, int bufno) ++{ ++ u32 cnt; ++ ++ cnt = dwc_rd32(dev, &dev->core_global_regs->geventbuf[bufno].geventcnt); ++ return cnt & DWC_EVENTCNT_CNT_BITS; ++} ++ ++/** ++ * This routine writes the Event Buffer count. ++ */ ++static void update_eventbuf_count(dwc_usb3_device_t *dev, int bufno, int cnt) ++{ ++ dwc_wr32(dev, &dev->core_global_regs->geventbuf[bufno].geventcnt, cnt); ++} ++ ++/** ++ * This routine fetches the next event from the Event Buffer. ++ */ ++static u32 get_eventbuf_event(dwc_usb3_device_t *dev, int bufno, int size) ++{ ++ u32 event; ++ ++ event = *dev->event_ptr[bufno]++; ++ if (dev->event_ptr[bufno] >= dev->event_buf[bufno] + size) ++ dev->event_ptr[bufno] = dev->event_buf[bufno]; ++ return event; ++} ++ ++/** ++ * This routine initializes an Event Buffer. ++ */ ++void dwc_usb3_init_eventbuf(dwc_usb3_device_t *dev, int bufno, ++ u32 *addr, unsigned int size, dwc_dma_t dma_addr) ++{ ++ dwc_debug4(dev, "Event buf %d addr 0x%08lx phys 0x%08lx size %d\n", ++ bufno, (unsigned long)addr, (unsigned long)dma_addr, size); ++ dwc_wr32(dev, &dev->core_global_regs->geventbuf[bufno].geventadr_lo, ++ dma_addr & 0xffffffffU); ++#ifdef DWC_64_BIT_ARCH ++ dwc_wr32(dev, &dev->core_global_regs->geventbuf[bufno].geventadr_hi, ++ dma_addr >> 32U & 0xffffffffU); ++#else ++ dwc_wr32(dev, &dev->core_global_regs->geventbuf[bufno].geventadr_hi, 0); ++#endif ++ dwc_wr32(dev, &dev->core_global_regs->geventbuf[bufno].geventsiz, ++ size << 2); ++ dwc_wr32(dev, &dev->core_global_regs->geventbuf[bufno].geventcnt, 0); ++} ++ ++/** ++ * This routine initializes the commmon interrupts. ++ * ++ * @param dev Programming view of DWC_usb3 controller. ++ */ ++void dwc_usb3_enable_common_interrupts(dwc_usb3_device_t *dev) ++{ ++ /* Clear any pending interrupts */ ++ dwc_usb3_dis_flush_eventbuf_intr(dev, 0); ++ ++ ena_eventbuf_intr(dev, 0); ++} ++ ++/** ++ * This routine enables the Device mode interrupts. ++ * ++ * @param dev Programming view of DWC_usb3 controller. ++ */ ++void dwc_usb3_enable_device_interrupts(dwc_usb3_device_t *dev) ++{ ++ u32 devten; ++ ++ dwc_debug1(dev, "%s()\n", __func__); ++ ++ /* Enable global interrupts */ ++ dwc_usb3_enable_common_interrupts(dev); ++ ++ devten = DWC_DEVTEN_DISCONN_BIT | DWC_DEVTEN_CONNDONE_BIT | ++ DWC_DEVTEN_USBRESET_BIT | DWC_DEVTEN_HIBER_REQ_BIT | ++ DWC_DEVTEN_WKUP_BIT; ++ ++ if (dev->snpsid >= 0x5533230a) ++ devten |= DWC_DEVTEN_U3_L2L1_SUSP_BIT; ++ else ++ devten |= DWC_DEVTEN_ULST_CHNG_BIT; ++ ++ /* Enable device interrupts */ ++ dwc_wr32(dev, &dev->pcd.dev_global_regs->devten, devten); ++ ++ dwc_debug2(dev, "%s() devten=%0x\n", __func__, ++ dwc_rd32(dev, &dev->pcd.dev_global_regs->devten)); ++} ++ ++/** ++ * This routine handles all interrupt events. It is called by the ++ * dwc_usb3_irq() interrupt handler routine, and by the enter_hibernation() ++ * routine after clearing the Run/Stop bit and waiting for the Halted bit to ++ * be set. ++ * ++ * @param dev Programming view of DWC_usb3 controller. ++ * return 1 if an interrupt event was seen, 0 if not. ++ */ ++int dwc_usb3_handle_event(dwc_usb3_device_t *dev) ++{ ++ dwc_usb3_pcd_t *pcd = &dev->pcd; ++ u32 event; ++ int count, intr, physep, i; ++ int ret = 0; ++ static int msg_cnt; ++ ++ count = get_eventbuf_count(dev, 0); ++ if (count) ++ dwc_debug1(dev, "Interrupt count %d\n", count); ++ ++ if ((count & DWC_EVENTCNT_CNT_BITS) == ++ (0xffffffff & DWC_EVENTCNT_CNT_BITS) || ++ count >= DWC_EVENT_BUF_SIZE * 4) { ++ if (msg_cnt > 100) { ++ msg_cnt = 100; ++ dwc_warn0(dev, "Too many bad events!!\n"); ++ } else { ++ msg_cnt++; ++ dwc_warn1(dev, ++ "Bad event count 0x%01x in dwc_usb3_irq() !!\n", ++ count); ++ } ++ ++ dis_eventbuf_intr(dev, 0); ++ update_eventbuf_count(dev, 0, count); ++ count = 0; ++ } ++ ++ if (!count) ++ goto out; ++ ret = 1; ++ ++#if defined(CONFIG_IPMATE) || defined(COSIM) || defined(VIRTIO_MODEL) ++ dis_eventbuf_intr(dev, 0); ++#endif ++ ++ for (i = 0; i < count; i += 4) { ++ dwc_debug1(dev, "Event addr 0x%08lx\n", ++ (unsigned long)dev->event_ptr[0]); ++ event = get_eventbuf_event(dev, 0, DWC_EVENT_BUF_SIZE); ++ update_eventbuf_count(dev, 0, 4); ++ if (event == 0) { ++ dwc_print0(dev, "## Null event! ##\n"); ++ ++ /* Ignore null events */ ++ continue; ++ } ++ ++ //dwc_debug1(dev, "Interrupt event 0x%08x\n", event); ++ if (event & DWC_EVENT_NON_EP_BIT) { ++ //dwc_debug0(dev, "Non-EP interrupt event\n"); ++ intr = event & DWC_EVENT_INTTYPE_BITS; ++ ++ if (intr == ++ DWC_EVENT_DEV_INT << DWC_EVENT_INTTYPE_SHIFT) { ++ dwc_debug1(dev, ++ "## Device interrupt 0x%08x ##\n", ++ event); ++ ret = dwc_usb3_handle_dev_intr(pcd, event); ++ if (ret) { ++ ret = 2; ++ goto out; ++ } ++ ret = 1; ++ } else { ++ dwc_debug1(dev, "## Core interrupt 0x%08x ##\n", ++ event); ++ ++ /* @todo Handle non-Device interrupts ++ * (OTG, CarKit, I2C) ++ */ ++ } ++ } else { ++ physep = event >> DWC_DEPEVT_EPNUM_SHIFT & ++ DWC_DEPEVT_EPNUM_BITS >> DWC_DEPEVT_EPNUM_SHIFT; ++ dwc_debug2(dev, ++ "## Physical EP%d interrupt 0x%08x ##\n", ++ physep, event); ++ dwc_debug2(dev, "[EP%d] %s\n", physep >> 1 & 0xf, ++ physep & 1 ? "IN" : "OUT"); ++ dwc_usb3_handle_ep_intr(pcd, physep, event); ++ } ++ } ++ ++#if defined(CONFIG_IPMATE) || defined(COSIM) || defined(VIRTIO_MODEL) ++ ena_eventbuf_intr(dev, 0); ++#endif ++out: ++ return ret; ++} ++ ++#ifdef SSIC ++ ++static int ssic_read_attr(dwc_usb3_device_t *dev, u32 aid, u32 *aval) ++{ ++ int i; ++ u32 sevt = 0; ++ u32 sctl = 0; ++ u32 data = 0; ++ ++ dwc_debug(dev, "%s: aid=0x%0x\n", __func__, aid); ++ ++ sctl |= DWC_SCTL_GO_ACC_BIT; ++ sctl |= (aid << DWC_SCTL_AID_SHIFT); ++ ++ dwc_debug(dev, "%s: writing sctl=0x%08x\n", __func__, sctl); ++ dwc_wr32(dev, &dev->ssic_regs->sctl[0], sctl); ++ ++ i = 100000; ++ do { ++ sevt = dwc_rd32(dev, &dev->ssic_regs->sevt[0]); ++ if (sevt & DWC_SEVT_LACC_CMPLT_BIT) ++ break; ++ dwc_udelay(dev, 1); ++ } while (--i > 0); ++ ++ if (i == 0) { ++ dwc_error(dev, "%s: lacc timeout\n", __func__); ++ return -1; ++ } ++ ++ data = (sevt & DWC_SEVT_RDATA_RCVD_BITS) >> DWC_SEVT_RDATA_RCVD_SHIFT; ++ if (aval) ++ *aval = (u8)data; ++ ++ dwc_debug(dev, "%s: rdata=%02x\n", __func__, data); ++ return 0; ++} ++ ++static int ssic_write_attr(dwc_usb3_device_t *dev, u32 aid, u32 aval) ++{ ++ int i; ++ u32 sctl = 0; ++ u32 sevt = 0; ++ ++ dwc_debug(dev, "%s: aid=0x%0x aval=%0x\n", __func__, aid, aval); ++ sctl |= (DWC_SCTL_GO_ACC_BIT | DWC_SCTL_RD_WR_N_BIT); ++ sctl |= (aid << DWC_SCTL_AID_SHIFT); ++ sctl |= (aval << DWC_SCTL_ADATA_SHIFT); ++ dwc_debug(dev, "%s: writing sctl=0x%08x\n", __func__, sctl); ++ dwc_wr32(dev, &dev->ssic_regs->sctl[0], sctl); ++ ++ i = 100000; ++ do { ++ sevt = dwc_rd32(dev, &dev->ssic_regs->sevt[0]); ++ if (sevt & DWC_SEVT_LACC_CMPLT_BIT) ++ break; ++ dwc_udelay(dev, 1); ++ } while (--i > 0); ++ ++ if (i == 0 ) { ++ dwc_error(dev, "%s: lacc timeout\n", __func__); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ssic_rrap_response(dwc_usb3_device_t *dev, int write, u32 aid, u32 aeid, u32 aval) ++{ ++ int i; ++ u32 sctl = 0; ++ u32 sevt = 0; ++ ++ dwc_debug(dev, "%s: aid=0x%0x, aeid=%0x, aval=%0x, write=%d\n", ++ __func__, aid, aeid, aval, write); ++ ++ sctl |= (DWC_SCTL_GO_ACC_BIT | DWC_SCTL_RACC_BIT); ++ if (write) ++ sctl |= (DWC_SCTL_RD_WR_N_BIT); ++ ++ sctl |= ((aid << DWC_SCTL_AID_SHIFT) & DWC_SCTL_AID_BITS); ++ sctl |= ((aeid << DWC_SCTL_EAID_SHIFT) & DWC_SCTL_EAID_BITS); ++ sctl |= ((aval << DWC_SCTL_ADATA_SHIFT) & DWC_SCTL_ADATA_BITS); ++ ++ dwc_debug(dev, "%s: writing sctl=0x%08x\n", __func__, sctl); ++ dwc_wr32(dev, &dev->ssic_regs->sctl[0], sctl); ++ ++ i = 100000; ++ do { ++ sevt = dwc_rd32(dev, &dev->ssic_regs->sevt[0]); ++ if (sevt & DWC_SEVT_RCMD_RES_SENT_BIT) ++ break; ++ dwc_udelay(dev, 1); ++ } while(--i > 0); ++ ++ if (i == 0) { ++ dwc_error(dev, "%s: racc response send timeout\n", __func__); ++ return -1; ++ } ++ ++ dwc_debug(dev, "%s: racc response sent result=0x%0x\n", __func__, ++ (sevt & DWC_SEVT_RACC_RESULT_BITS) >> DWC_SEVT_RACC_RESULT_SHIFT); ++ ++ return 0; ++} ++ ++static int ssic_cfg_done(dwc_usb3_device_t *dev) ++{ ++ u32 temp; ++ int usec = 100000; ++ dwc_debug1(dev, "%s\n", __func__); ++ ++ temp = dwc_rd32(dev, &dev->ssic_regs->sctl[0]); ++ temp |= DWC_SCTL_CFG_DONE_BIT; ++ dwc_wr32(dev, &dev->ssic_regs->sctl[0], temp); ++ ++ do { ++ u32 result = dwc_rd32(dev, &dev->core_global_regs->gusb3rmmictl[0]); ++ if (((result & DWC_RMMICTL_MPHY_STATE_BITS) >> ++ DWC_RMMICTL_MPHY_STATE_SHIFT) != DWC_MPHY_STATE_HIBERN8) { ++ break; ++ } ++ ++ dwc_udelay(dev, 1); ++ usec -= 1; ++ } while (usec > 0); ++ ++ if (!usec) { ++ dwc_error(dev, "%s: cfg done timed out\n", __func__); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int dwc_usb3_handle_ssic_event(dwc_usb3_device_t *dev) ++{ ++ int retval = -1; ++ u32 sevt = dwc_rd32(dev, &dev->ssic_regs->sevt[0]); ++ u32 temp = sevt; ++ dwc_debug(dev, "%s: SSIC Event 0x%08x\n", __func__, sevt); ++ ++ sevt &= (DWC_SEVT_ROM_INIT_CMPLT_BIT | ++ DWC_SEVT_LACC_CMPLT_BIT | ++ DWC_SEVT_RCMD_RES_RCVD_BIT | ++ DWC_SEVT_RCMD_RES_SENT_BIT | ++ DWC_SEVT_MPHY_ST_CHNG_BIT | ++ DWC_SEVT_OK_STRT_RRAP_BIT | ++ DWC_SEVT_RRAP_ERROR_BIT); ++ ++ dwc_wr32(dev, &dev->ssic_regs->sevt[0], sevt); ++ ++ sevt = temp; ++ ++ if (sevt & DWC_SEVT_MPHY_ST_CHNG_BIT) { ++ u32 rmmictl = dwc_rd32(dev, &dev->core_global_regs->gusb3rmmictl[0]); ++ if (((rmmictl & DWC_RMMICTL_MPHY_STATE_BITS) >> DWC_RMMICTL_MPHY_STATE_SHIFT) == ++ DWC_MPHY_STATE_HIBERN8) { ++ ssic_cfg_done(dev); ++ } ++ } ++ ++ if (sevt & DWC_SEVT_RCMD_RES_RCVD_BIT) { ++ u8 rdata = (sevt & DWC_SEVT_RDATA_RCVD_BITS) >> DWC_SEVT_RDATA_RCVD_SHIFT; ++ u8 rladdr = (sevt & DWC_SEVT_RLADDR_RCVD_BITS) >> DWC_SEVT_RLADDR_RCVD_SHIFT; ++ u8 ruaddr = (sevt & DWC_SEVT_RUADDR_RCVD_BITS) >> DWC_SEVT_RUADDR_RCVD_SHIFT; ++ int read = !!(sevt & DWC_SEVT_READ_RCVD_BIT); ++ ++ dwc_debug4(dev, "rdata=0x%02x, rladdr=0x%02x, ruaddr=0x%02x, read=%d\n", ++ rdata, rladdr, ruaddr, read); ++ ++ if (ruaddr <= 0x3) { ++ if (read) ++ dwc_error(dev, "Read not handled\n"); ++ else ++ dwc_error(dev, "Write not handled\n"); ++ } else if (ruaddr == 0x4) { ++ /* DSP_DISCONNECT */ ++ if (rladdr == 0x0) { ++ dwc_error(dev, "DSP_DISCONNECT not handled\n"); ++ /* CONFIGURE_FOR_HS */ ++ } else if (rladdr == 0x1) { ++ dwc_debug(dev, "CONFIGURE_FOR_HS\n"); ++ ssic_rrap_response(dev, !read, rladdr, ruaddr, 0x0); ++ ssic_write_attr(dev, 0x21, 0x2); ++ ssic_write_attr(dev, 0xa1, 0x2); ++ retval = 0; ++ /* BURST_CLOSURE */ ++ } else if (rladdr == 0x2) { ++ dwc_debug(dev, "BURST_CLOSURE\n"); ++ ssic_rrap_response(dev, !read, rladdr, ruaddr, 0x0); ++ ssic_cfg_done(dev); ++ /* DISABLE_SCRAMBLING */ ++ } else if (rladdr == 0x3) { ++ dwc_error(dev, "DISABLE_SCRAMBLING not handled\n"); ++ /* DISABLE_STALL_IN_U0 */ ++ } else if (rladdr == 0x4) { ++ dwc_error(dev, "DISABLE_STALL_IN_U0 not handled\n"); ++ /* TEST_MODE */ ++ } else if (rladdr == 0xff) { ++ dwc_error(dev, "DISABLE_TEST_MODE not handled\n"); ++ } else { ++ dwc_error(dev, "UNKNOWN\n"); ++ } ++ } else if (ruaddr == 0x5) { ++ dwc_error(dev, "UNKNOWN\n"); ++ } else if (ruaddr == 0x6) { ++ dwc_error(dev, "UNKNOWN\n"); ++ } else { ++ dwc_error(dev, "UNKNOWN\n"); ++ } ++ } ++ ++ return retval; ++} ++ ++#endif ++ ++ ++/** ++ * This is the common interrupt handler routine. ++ * ++ * @param dev Programming view of DWC_usb3 controller. ++ * @param irq IRQ number passed in by Linux kernel. ++ * @return 1 if an interrupt event was seen, 0 if not. ++ */ ++int dwc_usb3_irq(dwc_usb3_device_t *dev, int irq) ++{ ++ int state, temp, ret; ++ ++#ifdef SSIC ++ u32 gsts, sevt; ++ ++ gsts = dwc_rd32(dev, &dev->core_global_regs->gsts); ++ sevt = dwc_rd32(dev, &dev->ssic_regs->sevt[0]); ++ dwc_debug(dev, "%s: gsts=0x%08x, sevt=0x%08x\n", __func__, gsts, sevt); ++#endif ++ ++ if (!dev->cmn_irq_installed) ++ return 0; ++ ++#ifdef SSIC ++ gsts = dwc_rd32(dev, &dev->core_global_regs->gsts); ++ if (gsts & DWC_GSTS_SSIC_IP_BIT) { ++ dwc_usb3_handle_ssic_event(dev); ++ ret = 1; ++ } ++#endif ++ ++ state = dev->hibernate; ++ ++ if (state != DWC_HIBER_SLEEPING && dev->snpsid >= 0x5533230a && ++ dev->hiber_wait_u0) { ++ /* Handle waiting for U0 after requesting link state RECOVERY, ++ * because we don't have the link state change event enabled. ++ * We also do this in dwc_wait_pme_thread() in case an event ++ * doesn't come. ++ */ ++ temp = dwc_usb3_pcd_get_link_state(&dev->pcd); ++ dev->pcd.link_state = temp; ++ dwc_debug1(dev, "intr WAIT_U0 state=%d\n", temp); ++ ++ if (temp == DWC_LINK_STATE_U0) { ++ dwc_debug0(dev, "intr WAIT_U0 setting speed\n"); ++ dev->pcd.speed = dwc_usb3_get_device_speed(&dev->pcd); ++ if (dev->pcd.remote_wakeup_enable) ++ dwc_usb3_pcd_remote_wake(&dev->pcd, 0); ++ dev->hiber_wait_u0 = 0; ++ } ++ } ++ ++ if (state >= DWC_HIBER_SLEEPING) { ++ if (state == DWC_HIBER_WAIT_U0 || ++ state == DWC_HIBER_SS_DIS_QUIRK) { ++ dev->hibernate = DWC_HIBER_AWAKE; ++ } else { ++ if (dev->pme_ready) { ++#ifndef SELA_PLATFORM ++ ret = dwc_usb3_handle_pme_intr(dev); ++ return ret; ++#else ++ return 1; ++#endif ++ } else { ++ if (state != DWC_HIBER_WAIT_LINK_UP) ++ dwc_info0(dev, "Intr in hibernate but" ++ " pme_ready not set\n"); ++ return 1; ++ } ++ } ++ } ++ ++ ret = dwc_usb3_handle_event(dev); ++ if (ret == 2) ++ ret = 1; ++ ++#ifdef SSIC ++ gsts = dwc_rd32(dev, &dev->core_global_regs->gsts); ++ sevt = dwc_rd32(dev, &dev->ssic_regs->sevt[0]); ++ dwc_debug(dev, "%s DONE: gsts=0x%08x, sevt=0x%08x\n", __func__, gsts, sevt); ++#endif ++ ++ return ret; ++} +diff --git a/drivers/usb/gadget/udc/hiudc3/dev.h b/drivers/usb/gadget/udc/hiudc3/dev.h +new file mode 100644 +index 0000000..5f6a303 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/dev.h +@@ -0,0 +1,210 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/DWC_usb3/driver/dev.h $ ++ * $Revision: #12 $ ++ * $Date: 2014/11/11 $ ++ * $Change: 2664766 $ ++ * ++ * Synopsys SS USB3 Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 _DWC_DEV_H_ ++#define _DWC_DEV_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ * This file contains the interface to the Linux driver. ++ */ ++ ++/** ++ * This structure is a wrapper that encapsulates the driver components used to ++ * manage a single DWC_usb3 controller. ++ */ ++typedef struct dwc_usb3_device { ++ /** ++ * OS-specific stuff. KEEP THIS AT THE VERY BEGINNING OF THE DEVICE ++ * STRUCT. OSes such as FreeBSD and NetBSD require this. ++ */ ++ ++ /** Base address returned from ioremap() */ ++ volatile u8 __iomem *base; ++ volatile u8 __iomem *gasket_base; ++ ++ /** Offset to 'gasket' registers (Synopsys FPGA only) */ ++ int gasket_ofs; ++ ++#if defined(__linux__) || defined(LINUXTEST) ++ /** Device context */ ++ struct device *dev; ++ ++ /** Start address of IOMEM region */ ++ resource_size_t rsrc_start; ++ resource_size_t gasket_start; ++ ++ /** Length of IOMEM region */ ++ resource_size_t rsrc_len; ++ resource_size_t gasket_len; ++ ++ /** IRQ resource */ ++ int irq; ++ ++ struct task_struct *pme_thread; ++#endif ++ /* ==== End of OS-specific stuff ==== */ ++ ++ /** Count of threads inside Gadget API */ ++ int hiber_cnt; ++ ++ /** Hibernation state */ ++ int hibernate; ++ ++#define DWC_HIBER_AWAKE 0 ++#define DWC_HIBER_ENTER_NOSAVE 1 ++#define DWC_HIBER_ENTER_SAVE 2 ++#define DWC_HIBER_SLEEPING 3 ++#define DWC_HIBER_WAIT_LINK_UP 4 ++#define DWC_HIBER_WAIT_U0 5 ++#define DWC_HIBER_SS_DIS_QUIRK 6 ++ ++ int pme_ready; ++ ++ /** PCD structure */ ++ struct dwc_usb3_pcd pcd; ++ ++ /** Value from SNPSID register */ ++ u32 snpsid; ++ ++ /** Parameters that define how the core should be configured */ ++ dwc_usb3_core_params_t *core_params; ++ ++ /** Core Global registers starting at offset 100h */ ++ dwc_usb3_core_global_regs_t __iomem *core_global_regs; ++ ++#ifdef SSIC ++ dwc_usb3_ssic_regs_t __iomem *ssic_regs; ++#endif ++ ++ /** @{ */ ++#define DWC_EVENT_BUF_SIZE 256 // size in dwords ++#define DWC_NUM_EVENT_BUFS 1 ++ /** Event Buffers for receiving interrupts. Up to 32 buffers are ++ * supported by the hardware, but we only use 1. ++ */ ++ u32 *event_ptr[DWC_NUM_EVENT_BUFS]; ++ u32 *event_buf[DWC_NUM_EVENT_BUFS]; ++ dwc_dma_t event_buf_dma[DWC_NUM_EVENT_BUFS]; ++ /** @} */ ++ ++ /** Total RAM for FIFOs (Bytes) */ ++ u16 total_fifo_size; ++ ++ /** Size of Rx FIFO (Bytes) */ ++ u16 rx_fifo_size; ++ ++ /** @{ */ ++ /** Hardware Configuration - stored here for convenience */ ++ u32 hwparams0; ++ u32 hwparams1; ++ u32 hwparams2; ++ u32 hwparams3; ++ u32 hwparams4; ++ u32 hwparams5; ++ u32 hwparams6; ++ u32 hwparams7; ++ u32 hwparams8; ++ /** @} */ ++ ++ /** @{ */ ++ /** Register state, saved across core hibernation */ ++ u32 dcfg_save; ++ u32 dctl_save; ++ u32 gtxfifosiz0_save; ++ u32 gtxfifosiz1_save; ++ u32 gtxfifosiz2_save; ++ u32 gtxfifosiz3_save; ++ u32 grxfifosiz0_save; ++ u32 guctl_save; ++ u32 guctl1_save; ++ /** @} */ ++ ++ /** @{ */ ++ /** Hooks for customizing device initialization. See ++ * dwc_usb3_pcd_device_init() in cil.c to see how these work. ++ */ ++ void (*soft_reset_hook)(struct dwc_usb3_device *dev, int softrst, int rstor); ++ void (*phy_config_hook)(struct dwc_usb3_device *dev, int softrst, int rstor); ++ void (*fifo_sizing_hook)(struct dwc_usb3_device *dev, int softrst, int rstor); ++ void (*gctl_init_hook)(struct dwc_usb3_device *dev, int softrst, int rstor); ++ void (*set_address_hook)(struct dwc_usb3_device *dev, int softrst, int rstor); ++ void (*ep0_start_hook)(struct dwc_usb3_device *dev, int softrst, int rstor); ++ /** @} */ ++ ++ /** Value to write into the DCTL HIRD_Thresh field on register ++ * initialization. If 0 then a default value of 0x1c will be used. ++ */ ++ u32 hird_thresh; ++ ++ /** Values to write into GSBUSCFG0 and GSBUSCFG1 on initialization or ++ * when exiting from hibernation. 'program_gsbuscfg' below must also be ++ * set to 1 to enable the writing of these values. ++ */ ++ u32 gsbuscfg0; ++ u32 gsbuscfg1; ++ ++ /** True if common functionality has been initialized */ ++ unsigned int cmn_initialized : 1; ++ ++ /** True if Gadget has been initialized */ ++ unsigned int gadget_initialized : 1; ++ ++ /** True if PCD has been initialized */ ++ unsigned int pcd_initialized : 1; ++ ++ /** True if common IRQ handler has been installed */ ++ unsigned int cmn_irq_installed : 1; ++ ++ /** True if sysfs functions have been installed */ ++ unsigned int sysfs_initialized : 1; ++ ++ /** True if waiting for connect before resuming from hibernation */ ++ unsigned int hiber_wait_connect : 1; ++ ++ /** True if waiting for U0 state before sending remote wake */ ++ unsigned int hiber_wait_u0 : 1; ++ ++ /** True if GBUSCFG0/GBUSCFG1 should be written with the above ++ * values when exiting hibernation */ ++ unsigned int program_gsbuscfg : 1; ++} dwc_usb3_device_t; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_DEV_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc3/dox.h b/drivers/usb/gadget/udc/hiudc3/dox.h +new file mode 100644 +index 0000000..d58532b +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/dox.h +@@ -0,0 +1,615 @@ ++#ifndef _DWC_DOX_H_ ++#define _DWC_DOX_H_ ++ ++/** ++ * @file ++ * ++ * image html synopsys.png "Synopsys Logo" ++ * image latex synopsys.eps "Synopsys Logo" ++ * ++ * This file contains the Doxygen comments that create the Functional ++ * Specification document for the driver. ++ * ++ * @page intro_chapter Introduction ++ * ++ * The DWC_usb3 Subsystem Version 2.90b is a host and peripheral controller ++ * that is compliant with the USB 3.0 specification. The peripheral controller ++ * has a Synopsys-proprietary programming interface, which bears some ++ * resemblance to the Intel xHCI host interface. This is because the controller ++ * supports xHCI when acting as a host, and some of the logic is shared between ++ * the host and peripheral modes. ++ * ++ * The 2.90b version supports SuperSpeed USB 3.0, and HS and FS USB 2.0. ++ * ++ * Source level driver software will be shipped with the controller. Customers ++ * can use this software as a reference for developing drivers for other ++ * platforms or operating environments. ++ * ++ * @section scope_sec Scope ++ * ++ * This document defines the functionality of the driver software that will ++ * be shipped with the DWC_usb3 Version 2.90b controller. It specifies what ++ * the software will do, not how it will accomplish these tasks. ++ * ++ * The driver software for DWC_usb3 Version 2.90b will support only Linux as ++ * its operating environment. Therefore, this document currently defines ++ * behavior under Linux. However, it is desired that many aspects of the driver ++ * software can be easily ported to other operating systems or environments, ++ * and towards that end, it has been written in a way to ease the porting ++ * effort (see section 1.2.3 @ref env_and_hw_deps_subsec). ++ * ++ * For subsequent releases of the DWC_usb3 controller, this document will be ++ * modified to include updates required in the driver software. These updates ++ * may be made to support new features in the controller or to support new ++ * operating environments. ++ * ++ * @section overview_sec Overview ++ * ++ * @subsection sw_arch_subsec Software Architecture ++ * ++ * The DWC_usb3 controller can act as either a host or a peripheral on the ++ * USB. Figure 1.1 shows the software architecture for the DWC_usb3 controller. ++ * ++ * There are two stacks in the software architecture - the Host Stack and the ++ * Peripheral Stack. Brief descriptions of each of these stacks are given ++ * below to set the context for the driver software. Since the host part of ++ * the DWC_usb3 controller conforms to the xHCI standard, the xHCI HCD ++ * driver in the host OS will provide the host stack functionality. Therefore, ++ * only the peripheral stack functionality will be implemented in the DWC_usb3 ++ * controller driver software. See the OTG 3.0 user manual for a description ++ * of the DRD/OTG functionality. ++ * ++ * The Host Stack is used to request transfers to or from USB devices when ++ * the DWC_usb3 component is acting in the role of a host. The top-level ++ * component in this stack is a Host Application that acts as a producer or ++ * consumer of data. The Class Drivers translate application requests into a ++ * protocol specific to a certain type (or class) of devices. They use I/O ++ * Request Packets (IRPs) to transfer data to or from USB devices. The USB ++ * Driver (USBD) provides services to allow multiple Class Drivers to ++ * configure, control, and exchange data with their associated devices. The ++ * Hub Driver is also involved in the configuration process. The USBD handles ++ * all communication with the Host Controller Driver (HCD), which must ++ * understand the hardware architecture of the host controller. The HCD ++ * interacts with the host controller hardware to execute the USB transfers ++ * requested by the USBD. ++ * ++ * The Peripheral Stack is used to respond to requests received from a USB ++ * host when the DWC_usb3 component is acting in the role of a peripheral. ++ * The Peripheral Function is the sink or source of data requested by the host. ++ * The Function Driver handles some USB requests directly. It also provides ++ * endpoint read/write data interfaces and notification services to the ++ * Peripheral Function. The Peripheral Controller Driver (PCD) understands ++ * the hardware architecture of the peripheral controller. The PCD interacts ++ * with the peripheral controller hardware to transfer data via the USB and ++ * notifies the Function Driver of USB requests. ++ * ++ * @image html sw_stack.png "Figure 1.1: Generic USB Software Architecture" ++ * @image latex sw_stack.eps "Generic USB Software Architecture" width=6.50in ++ * ++ * @subsection driver_sw_comp_subsec Driver Software Components ++ * ++ * There are two main driver software components - the Peripheral Controller ++ * Driver and the Core Interface Layer (CIL). Basic functionality of the PCD ++ * is described in section 1.2.1 @ref sw_arch_subsec above. A little more ++ * elaboration of the PCD and a description of the CIL are given below. ++ * ++ * The PCD and CIL can be viewed as a hardware abstraction layer. In other ++ * words, the Function Driver does not know or care about the underlying ++ * hardware of the peripheral controller. It merely transfers data and ++ * transmits commands via a software interface with the PCD. Changes made to ++ * the peripheral controller do not require changes to this interface ++ * (although the internal operation of the PCD and CIL would have to be ++ * modified). ++ * ++ * The CIL provides common services for accessing and managing the DWC_usb3 ++ * hardware. These services include initialization, mapping of registers, ++ * interrupt control, and low-level access to the CSRs and DMA descriptors ++ * (TRBs). ++ * ++ * @subsection env_and_hw_deps_subsec Environment and Hardware Dependencies ++ * ++ * As noted above, changes to the underlying hardware will require changes to ++ * the internal operation of the driver components. This is true for both of the ++ * driver components (PCD and CIL). Both of these components are aware of the ++ * internal architecture of the controller, so each of these components may need ++ * to change to adapt to any hardware changes. However, for a given operating ++ * system (such as Linux), the layers above the PCD would not require any ++ * changes. They would continue to use the same API to communicate with the PCD. ++ * That is why the PCD is considered a hardware abstraction layer. ++ * ++ * Most of the driver components are designed to be reasonably operating system ++ * independent, by making the low-level routines OS-agnostic and placing them ++ * into separate source files. The Linux-specific code is likewise contained in ++ * a few separate source files. That should simplify porting the driver software ++ * between operating environments. ++ * ++ * Starting with the 2.20a release, the software provides support for an ++ * additional platform, called No-OS. No-OS means the code contains no ++ * OS-specific dependencies at all. See the Porting Guide document for more ++ * information about the No-OS platform, and for general information about ++ * porting the driver to platforms other than Linux. ++ * ++ * Note, however, that the driver has only been completely tested under Linux ++ * 3.6.3. ++ * ++ * @section deliverables_sec Deliverables ++ * ++ * This section describes the driver components, documentation, and demo ++ * software included with the SuperSpeed USB3 Controller Linux Driver ++ * Software. ++ * ++ * @subsection driver_sw_subsec Driver Software ++ * ++ * All driver components will be developed for the Linux operating ++ * system on a PC + HAPS platform. The following components will be ++ * packaged and released: ++ * ++ * - Peripheral Controller Driver source code ++ * - Core Interface Layer source code ++ * - USB Attached SCSI Protocol (UASP) Gadget Driver source code ++ * ++ * These components will support the following features: ++ * ++ * - Control and Bulk transfers in Peripheral Mode using the legacy Mass ++ * Storage Class protocol ++ * - Control and Bulk transfers in Peripheral Mode using the new USB Attached ++ * SCSI protocol ++ * ++ * New for the 2.50b release: ++ * ++ * - "Bringup" driver source code. This is a stripped-down version of the PCD, ++ * with just enough logic for testing the registers, event interrupt, and DMA ++ * loopback features of the controller. It is intended to verify the basic ++ * functionality of the controller without needing any USB-specific support ++ * code in the OS. ++ * ++ * The bringup driver source, along with a README file describing how to build ++ * and run the driver, can be found in the bringup/ directory. ++ * ++ * @subsection sw_doc_subsec Software Documentation ++ * ++ * Source documentation in HTML or PDF format will be delivered for the driver ++ * components released with the DWC_usb3 controller. This will include ++ * documentation of the API for each of the driver components. ++ * ++ * Instructions for acquiring and installing the Linux kernel sources and ++ * applying any required patches will be included in the release. ++ * ++ * @subsection demo_sw_subsec Demo Software ++ * ++ * No need for special demo software is anticipated for the 2.90b release. ++ * The demo will consist of using the controller as a mass-storage device, ++ * and copying/streaming large files to and from the device from a host PC. ++ * ++ * @subsection bin_subsec Binaries ++ * ++ * No binaries will be distributed with the 2.90b release. ++ * ++ */ ++ ++/** ++ * @page env_chapter Environment Specific Features ++ * ++ * This section defines functionality of the driver software that depends on ++ * a particular operating system or operating environment. Since Linux is the ++ * only environment currently supported, the Linux implementation is described ++ * here. In the future, this section may include descriptions of wrappers to ++ * glue generic driver components into various operating system environments. ++ * ++ * @section linux_arch_sec Linux Architecture ++ * ++ * The Linux architecture is very similar to the generic DWC_usb3 software ++ * architecture shown in Figure 1.1. Figure 2.1 shows the Linux version of this ++ * architecture. ++ * ++ * The USB Core component in Linux includes the USB Driver functionality plus a ++ * framework to support Host Controller Drivers. The HCD framework is intended ++ * to allow different HCDs to share code. This makes it easier to write new ++ * HCDs and reduces the number of bugs. Only functionality that needs to be ++ * aware of the underlying hardware is implemented in the HCD. This is ++ * accomplished by defining the hc_driver interface. This interface consists of ++ * the functions and data that must be supplied by an HCD in order to plug into ++ * the Linux HCD framework. The OS-supplied xHCI HCD will implement the ++ * hc_driver interface. ++ * ++ * In Linux, peripheral devices are called gadgets. So the Peripheral Function ++ * is called a Gadget Application and the Function Driver is called a Gadget ++ * Driver. Linux defines a Gadget API which is the interface between the Gadget ++ * Driver and the Peripheral Controller Driver. Similar to the hc_driver ++ * interface, the Gadget API is intended to isolate hardware-specific behavior ++ * to the Peripheral Controller Driver. The Linux version of the DWC_usb3 PCD ++ * will implement the Gadget API. See section 4.2.1 @ref gadget_api_subsec for ++ * more information. ++ * ++ * The API of the Core Interface Layer is independent of the operating system. ++ * Services provided by this component are the same regardless of the operating ++ * system. ++ * ++ * @image html linux_stack.png "Figure 2.1: Linux USB Software Architecture with UASP Gadget" ++ * @image latex linux_stack.eps "Linux USB Software Architecture with UASP Gadget" width=6.50in ++ * ++ * @section linux_driver_sec Linux Driver Module ++ * ++ * All of the driver components are contained in a single driver module. The ++ * module wrapper code, including the module initialization and cleanup ++ * functions, is Linux dependent. This section describes the Linux module ++ * functionality. ++ * ++ * The dwc_usb3 module provides the initialization and cleanup entry points for ++ * the DWC_usb3 driver. This module will be dynamically installed after Linux is ++ * booted using the insmod command. When the module is installed, the ++ * dwc_usb3_driver_init function is called. When the module is removed (using ++ * rmmod), the dwc_usb3_driver_exit function is called. ++ * ++ * This module also defines a data structure for the dwc_usb3_device. This ++ * structure allows the DWC_usb3 driver to comply with the standard Linux driver ++ * model in which devices and drivers are registered with a bus driver. This has ++ * the benefit that Linux can expose attributes of the driver and device in its ++ * special sysfs file system. Users can then read or write files in this file ++ * system to perform diagnostics on the driver components or the device. ++ * ++ * @subsection data_struct_subsec Data Structures ++ * ++ * These are the main data structures used by the DWC_usb3 driver module. ++ * ++ * - struct dwc_usb3_device ++ * ++ * @subsection init_and_clean_subsec Initialization and Cleanup Functions ++ * ++ * These are the initialization and cleanup functions of the DWC_usb3 driver ++ * module. ++ * ++ * - dwc_usb3_driver_init() ++ * - dwc_usb3_driver_probe() ++ * - dwc_usb3_driver_remove() ++ * - dwc_usb3_driver_exit() ++ * ++ */ ++ ++/** ++ * @page cil_chapter Core Interface Layer ++ * ++ * The Core Interface Layer provides basic services for accessing and managing ++ * the DWC_usb3 hardware. The CIL also manages the memory map for the core so ++ * that the PCD doesn't have to do this separately. ++ * ++ * @section csr_sec Control and Status Register Structures ++ * ++ * The following structures define the size and relative field offsets for ++ * each register in the DWC_usb3 controller. These structures are not created ++ * in memory through normal memory allocation methods. After mapping memory ++ * for the controller into the OS memory space, these structures are overlaid ++ * on the mapped memory by setting the appropriate base address for each ++ * structure. Each register can then be accessed via its address in one of ++ * these structures. ++ * ++ * The precise method for accessing registers is OS-specific. It may be as ++ * simple as directly reading or writing a register field in one of these ++ * structures. Or it may require passing the mapped register address to a ++ * read/write method defined by the OS. ++ * ++ * @subsection core_glbl_regs_subsec Core Global Registers Structure ++ * ++ * The following structure defines the size and relative field offsets for ++ * the Core Global registers. ++ * ++ * - struct dwc_usb3_core_global_regs ++ * ++ * @subsection dev_glbl_regs_subsec Peripheral Mode Global Registers Structure ++ * ++ * The following structure defines the size and relative field offsets for ++ * the Peripheral Mode Global Registers. ++ * ++ * - struct dwc_usb3_dev_global_regs ++ * ++ * @subsection dev_ep_regs_subsec Peripheral Mode Per-Endpoint Registers Structures ++ * ++ * The following structure defines the size and relative field offsets for ++ * the Peripheral Mode Per-Endpoint Registers. There is one set of these ++ * registers for each endpoint that is instantiated in the core. ++ * ++ * - struct dwc_usb3_dev_ep_regs ++ * ++ * @section cil_func_sec Functions ++ * ++ * These are the main functions provided by the CIL. ++ * ++ * - dwc_usb3_pcd_common_init() ++ * - dwc_usb3_pcd_common_remove() ++ * - dwc_usb3_pcd_device_init() ++ * - dwc_usb3_enable_common_interrupts() ++ * - dwc_usb3_enable_device_interrupts() ++ * - dwc_usb3_mode() ++ * - dwc_usb3_is_device_mode() ++ * - dwc_usb3_is_host_mode() ++ * - dwc_usb3_dump_global_registers() ++ * - dwc_usb3_fill_desc() ++ * - dwc_usb3_start_desc_chain() ++ * - dwc_usb3_end_desc_chain() ++ * - dwc_usb3_enable_desc() ++ * - dwc_usb3_xmit_fn_remote_wake() ++ * - dwc_usb3_dep_cfg() ++ * - dwc_usb3_dep_xfercfg() ++ * - dwc_usb3_dep_sstall() ++ * - dwc_usb3_dep_cstall() ++ * - dwc_usb3_dep_startxfer() ++ * - dwc_usb3_dep_updatexfer() ++ * - dwc_usb3_dep_endxfer() ++ * - dwc_usb3_dep_startnewcfg() ++ * - dwc_usb3_enable_ep() ++ * - dwc_usb3_disable_ep() ++ * - dwc_usb3_get_device_speed() ++ * - dwc_usb3_get_frame() ++ * - dwc_usb3_pcd_get_link_state() ++ * - dwc_usb3_pcd_set_link_state() ++ * - dwc_usb3_set_address() ++ * - dwc_usb3_ena_usb2_suspend() ++ * - dwc_usb3_dis_usb2_suspend() ++ * - dwc_usb3_accept_u1() ++ * - dwc_usb3_accept_u2() ++ * - dwc_usb3_enable_u1() ++ * - dwc_usb3_enable_u2() ++ * - dwc_usb3_disable_u1() ++ * - dwc_usb3_disable_u2() ++ * - dwc_usb3_u1_enabled() ++ * - dwc_usb3_u2_enabled() ++ * - dwc_usb3_pcd_remote_wake() ++ */ ++ ++/** ++ * @page pcd_chapter Peripheral Controller Driver ++ * ++ * The Peripheral Controller Driver (PCD) is responsible for translating ++ * requests from the Function Driver into the appropriate actions on the ++ * DWC_usb3 controller. It isolates the Function Driver from the specifics of ++ * the controller by providing an API to the Function Driver. This API may ++ * vary between operating systems, but it remains constant within a given OS. ++ * Section 4.2 @ref fun_drvr_ifc_sec describes this API for supported ++ * operating systems. ++ * ++ * A USB device responds to commands issued from the host. Section 4.3 ++ * @ref std_usb_cmd_proc_sec describes handling of the standard USB ++ * commands within the DWC_usb3 software environment. ++ * ++ * An important function of the PCD is managing interrupts generated by the ++ * DWC_usb3 controller. The behaviors for each DWC_usb3 peripheral mode ++ * interrupt are described in section 4.4 @ref dev_intr_svc_rtn_sec. ++ * ++ * @section pcd_data_st_sec Data Structures ++ * ++ * These are the main data structures used by the PCD. ++ * ++ * @subsection pcd_subsec PCD Data Structure ++ * ++ * The following structure encapsulates the data for the dwc_usb3 PCD. ++ * ++ * - struct dwc_usb3_pcd ++ * ++ * @subsection pcd_ep_subsec Endpoint Data Structure ++ * ++ * The following structure describes an endpoint. There is an array of these ++ * in the PCD structure, one for each endpoint. ++ * ++ * - struct dwc_usb3_pcd_ep ++ * ++ * @subsection ep_subsec Endpoint State Structure ++ * ++ * The following structure represents the state of a single endpoint when ++ * acting in peripheral mode. It contains the data items needed for an endpoint ++ * to be activated and transfer packets. One of these structures is contained ++ * in each dwc_usb3_pcd_ep structure. ++ * ++ * - struct dwc_ep ++ * ++ * @subsection pcd_req_subsec Transfer Request Data Structure ++ * ++ * The following structure describes a transfer request. It is used to form ++ * a list of requests. ++ * ++ * - struct dwc_usb3_pcd_req ++ * ++ * @subsection req_subsec Transfer Request State Structure ++ * ++ * The following structure represents the state of a single transfer request ++ * when acting in peripheral mode. It contains the data items needed for a ++ * request to be started and completed. ++ * ++ * - struct dwc_req ++ * ++ * @subsection dev_dma_subsec DMA Descriptor Structure ++ * ++ * The following structure represents the DMA descriptors used by the dwc_usb3 ++ * controller in peripheral mode. These descriptors are also referred to as ++ * Transfer Request Blocks or TRBs (as in the xHCI spec). ++ * ++ * - struct dwc_usb3_dma_desc ++ * ++ * @section fun_drvr_ifc_sec Function Driver Interface ++ * ++ * This section describes the API that the PCD presents to the Function Driver ++ * for each supported operating system. Currently, Linux is the only supported ++ * OS. ++ * ++ * @subsection gadget_api_subsec Linux Gadget API ++ * ++ * The Peripheral Controller Driver for Linux will implement the Gadget API, ++ * so that the existing Gadget drivers can be used. (Gadget Driver is the ++ * Linux terminology for a Function Driver.) ++ * ++ * The Linux Gadget API is defined in the header file . ++ * The following data structures define the functions implemented in the PCD ++ * to provide the interface. The USB EP operations API is defined in the ++ * structure usb_ep_ops and the USB Controller API is defined in the structure ++ * struct usb_gadget_ops. ++ * ++ * @subsection usb_ep_ops_subsec USB Endpoint Operations ++ * ++ * The following sections briefly describe the behavior of the Gadget API ++ * endpoint operations implemented in the DWC_usb3 driver software. Detailed ++ * descriptions of the generic behavior of each of these functions can be ++ * found in the Linux header file include/linux/usb_gadget.h. ++ * ++ * The Gadget API provides wrapper functions for each of the function pointers ++ * defined in usb_ep_ops. The Gadget Driver calls the wrapper function, which ++ * then calls the underlying PCD function. The following sections are named ++ * according to the wrapper functions. Within each section, the corresponding ++ * DWC_usb3 PCD function name is specified. ++ * ++ * Functions in the API that are not described below are not implemented. ++ * ++ * usb_ep_enable ++ * ++ * - ep_enable() ++ * ++ * usb_ep_disable ++ * ++ * - ep_disable() ++ * ++ * usb_ep_alloc_request ++ * ++ * - alloc_request() ++ * ++ * usb_ep_free_request ++ * ++ * - free_request() ++ * ++ * usb_ep_queue ++ * ++ * - ep_queue() ++ * ++ * usb_ep_dequeue ++ * ++ * - ep_dequeue() ++ * ++ * usb_ep_set_halt, usb_ep_clear_halt ++ * ++ * - ep_set_halt() ++ * ++ * @subsection gadget_ops_subsec Gadget Operations ++ * ++ * The following gadget operations will be implemented in the DWC_usb3 PCD. ++ * Functions in the API that are not described below are not implemented. ++ * ++ * The Gadget API provides wrapper functions for each of the function pointers ++ * defined in usb_gadget_ops. The Gadget Driver calls the wrapper function, ++ * which then calls the underlying PCD function. The following sections are ++ * named according to the wrapper functions. Within each section, the ++ * corresponding DWC_usb3 PCD function name is specified. ++ * ++ * usb_gadget_get_frame ++ * ++ * - dwc_get_frame() ++ * ++ * usb_gadget_wakeup ++ * ++ * - dwc_usb3_wakeup() ++ * ++ * @subsection streams_ext_subsec USB 3.0 Bulk Streams Extension ++ * ++ * USB 3.0 introduces the concept of Bulk Streams. Bulk Streams provide ++ * the ability to move multiple streams of data over a single Bulk endpoint. ++ * This is used by a new version of the Mass Storage Class protocol, called USB ++ * Attached SCSI Protocol (UASP). It allows multiple transfer requests to be ++ * queued up by the Host, which can then be completed in whatever order the data ++ * becomes available from the Peripheral. ++ * ++ * This requires some modifications to the Gadget API and the underlying USB ++ * request functions, to allow the stream capabilities of an endpoint to be set, ++ * and to indicate the stream ID associated with a transfer request. It also ++ * requires a new File Storage gadget which has the needed Bulk Streams support. ++ * ++ * @section std_usb_cmd_proc_sec Standard USB Command Processing ++ * ++ * In Linux, the USB Command processing is done in two places - the first ++ * being the PCD and the second being the Gadget Driver (for example, the ++ * Mass Storage Gadget Driver). See pcd_setup() for a detailed explanation. ++ * ++ * @section dev_intr_svc_rtn_sec Peripheral Interrupt Service Routine ++ * ++ * The PCD handles the peripheral interrupts. Many conditions can cause a ++ * peripheral interrupt. When an interrupt occurs, the peripheral interrupt ++ * service routine determines the cause of the interrupt and dispatches ++ * handling to the appropriate function. These interrupt handling functions ++ * are described below. ++ * ++ * Global Peripheral Interrupts ++ * ++ * - dwc_usb3_handle_dev_intr() ++ * - handle_disconnect_intr() ++ * - handle_usb_reset_intr() ++ * - dwc_usb3_handle_connect_done_intr() ++ * - handle_link_status_change_intr() ++ * - handle_wakeup_detected_intr() ++ * - handle_sof_intr() ++ * - handle_hiber_req_intr() ++ * ++ * Endpoint-Specific Peripheral Interrupts ++ * ++ * - dwc_usb3_handle_ep_intr() ++ * ++ * @section pcd_func_sec Other Functions ++ * ++ * These are the remaining functions provided by the PCD. ++ * ++ * - dwc_usb3_pcd_init() ++ * - dwc_usb3_pcd_remove() ++ * - dwc_usb3_pcd_ep_enable() ++ * - dwc_usb3_pcd_ep_disable() ++ * - dwc_usb3_pcd_ep_submit_req() ++ * - dwc_usb3_pcd_ep_cancel_req() ++ * - dwc_usb3_pcd_ep_set_halt() ++ * - dwc_usb3_pcd_get_frame_number() ++ * - dwc_usb3_ep0_activate() ++ * - dwc_usb3_pcd_ep0_out_start() ++ * - dwc_usb3_stop_all_xfers() ++ * - dwc_usb3_get_out_ep() ++ * - dwc_usb3_get_in_ep() ++ * - dwc_usb3_handle_ep0() ++ * - dwc_usb3_ep_complete_request() ++ * - usb_gadget_register_driver() / usb_gadget_probe_driver() ++ * - usb_gadget_unregister_driver() ++ */ ++ ++/** ++ * @page hiber_chapter Hibernation ++ * ++ * DWC_usb3 Subsystem Version 2.00a and above implements a new functionality, ++ * hibernation. Hibernation allows power to be removed from most parts of the ++ * controller during periods of inactivity. This is done through a combination ++ * of hardware and software. ++ * ++ * The controller signals a device event when the host has requested a low-power ++ * state suitable for the device to enter hibernation. When this event is ++ * received, the PCD will stop the controller, command it to save critical state ++ * information to main memory, save the content of the CSRs, and then shut off ++ * Vcc power to the core. ++ * ++ * When a condition is detected that requires the core to resume operation, the ++ * driver will receive an interrupt from the monitoring hardware, causing it to ++ * switch Vcc back on, restore the content of the CSRs, and command the ++ * controller to restore its critical state from main memory. ++ * ++ * The bulk of the hibernation code is contained in the files pcd_hiber.c and ++ * linux_hiber.c. Note that this is not a complete implementation; the HAPS ++ * platform on which it has been tested does not provide the normal PCIe PME ++ * mechanism, instead there is special logic in the custom PCIe "gasket" to ++ * handle power control and provide an interrupt to awaken the core from ++ * hibernation. Therefore, the code in linux_hiber.c which handles power ++ * control and wakeup will need to be rewritten for a "real" implementation. ++ * Also, since the CPU is still running while the controller is in the ++ * hibernated state, code has been added to linux_gadget.c to prevent any calls ++ * that would try to touch the controller hardware from entering the driver ++ * while hibernation is active. A "real" implementation should not require this. ++ * ++ * @section hiber_func_sec Hibernation Functions ++ * ++ * These are the functions provided by pcd_hiber.c and linux_hiber.c ++ * ++ * - dwc_enter_hibernation() ++ * - dwc_exit_hibernation_after_connect() ++ * - dwc_exit_hibernation() ++ * - dwc_wait_pme_thread() ++ * - dwc_usb3_handle_pme_intr() ++ * - dwc_usb3_power_ctl() ++ */ ++#endif /* _DWC_DOX_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc3/dox_port.h b/drivers/usb/gadget/udc/hiudc3/dox_port.h +new file mode 100644 +index 0000000..4cd573e +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/dox_port.h +@@ -0,0 +1,619 @@ ++#ifndef _DWC_DOX_PORT_H_ ++#define _DWC_DOX_PORT_H_ ++ ++/** ++ * @file ++ * ++ * image html synopsys.png "Synopsys Logo" ++ * image latex synopsys.eps "Synopsys Logo" ++ * ++ * This file contains the Doxygen comments that create the Porting Guide ++ * document for the driver. ++ * ++ * @page intro_chap Introduction ++ * ++ * This document gives some tips on how to port the DWC_usb3 example drivers to ++ * an operating system other than Linux. This document focuses on the Peripheral ++ * Controller Driver (PCD) in the \a driver/ source directory. The OTG3 and UAS ++ * Gadget drivers in the \a otg3/ and \a gadget/ directories are not covered. ++ * ++ * The PCD source code includes an example platform port in the \a driver/no_os/ ++ * directory. \a no_os stands for "No OS", which means the code contains no ++ * OS-specific dependencies at all. ++ * ++ * The \a no_os/ code also contains an implementation of a simple loopback-class ++ * Function Driver. This driver provides one Bulk OUT and one Bulk IN endpoint, ++ * and can either loop all packets received on the OUT endpoint back to the IN ++ * endpoint, or can sink any packets received on the OUT endpoint while ++ * simultaneously sourcing 0-filled packets on the IN endpoint. One of these two ++ * behaviors can be selected at compile time by changing a single line of source ++ * code. ++ * ++ * @page pcd_chap The PCD ++ * ++ * @section pcd_rules_sec Rules When Calling Into the PCD ++ * ++ * - The @ref dwc_usb3_pcd_init API routine in pcd.c must be called from process ++ * context or equivalent, because it uses the @ref dwc_msleep routine to delay ++ * while waiting for the DWC_usb3 core to come out of reset. The same is true ++ * for @ref dwc_usb3_pcd_device_init if its soft_reset ++ * parameter is true. ++ * ++ * - To protect against the IRQ handler corrupting core registers or data ++ * structures, interrupts should be disabled before calling any of the ++ * non-initialization routines in the PCD API. In addition, on multiprocessor ++ * platforms a spinlock should also be taken, to protect against two CPUs ++ * running at the same time and causing corruption. The lock field in ++ * struct dwc_usb3_pcd is provided for this purpose. ++ * ++ * - If the above spinlock is used, then it must be released in the @ref ++ * dwc_usb3_gadget_complete API routine before calling any Function Driver ++ * routines which may try to take the spinlock again to call back into the PCD. ++ * The spinlock must be retaken before @ref dwc_usb3_gadget_complete returns. ++ * ++ * @section comp_pcd_sec Porting the PCD ++ * ++ * First, try porting just the PCD code, which is cil.c, cil_intr.c, pcd.c, ++ * pcd_intr.c, pcd_hiber.c, and ep0.c. This code should be easy to port because ++ * it uses very few OS services. The following sections will walk you through ++ * how to do this. ++ * ++ * @subsection os_defs_and_dev_sec Create the os_defs.h and os_dev.h Files ++ * ++ * Create \a os_defs.h and \a os_dev.h files for your platform. You can ++ * either create a subdirectory (e.g. \a driver/myplat/) to contain these ++ * files, and replace the existing \a os_defs.h and \a os_dev.h symlinks with ++ * links to these files, or you can remove the symlinks and create these files ++ * directly in the \a driver/ directory. ++ * ++ * We recommend that you start with the no_os_defs.h and no_os_dev.h files and ++ * modify them as needed for your platform. ++ * ++ * @subsubsection os_defs_sec The os_defs.h File ++ * ++ * The \a os_defs.h file should contain all the \a \#include directives ++ * needed to compile the PCD code on your platform, as well as definitions ++ * needed to provide any missing types etc. that the PCD code requires. ++ * ++ * Specific things that need to be defined here include: ++ *

    ++ *
  • Definitions of the types \a u8, \a u16, \a u32, \a u64, \a u_int8_t, ++ * \a u_int16_t, \a u_int32_t, \a u_char, \a u_short, \a u_int, and \a ++ * u_long. ++ * ++ *
  • Definition of the type \a dwc_dma_t to hold a DMA address for your ++ * platform. This must be an integral type, not a pointer. ++ * ++ *
  • Definition of the \a UPACKED attribute for the compiler. If you are ++ * using GCC, or ARMCC with the \a --gnu flag, this should be: ++ *

        \#define UPACKED __attribute__ ((__packed__)) ++ *

    ++ * ++ *

    If you are using a Microsoft compiler, you should define this to ++ * nothing:

    ++ *

        \#define UPACKED

    ++ * ++ *

    The \a \#include  and \a \#include  ++ * directives, as shown in the usb.h file, handle structure packing for ++ * Microsoft compilers.

    ++ * ++ *

    If you are using some other compiler, check the compiler manual to see ++ * how to accomplish this.

    ++ * ++ *
  • Definition of the \a __iomem data attribute. For any platform except ++ * Linux, this should be defined to nothing: ++ *

        \#define __iomem

    ++ * ++ *
  • Definition of the @ref wmb macro (write memory barrier). For ++ * uniprocessor platforms, this can be defined to a null function. For ++ * multiprocessor platforms, the definition of this macro is highly ++ * platform-dependent. ++ * ++ *

    This macro is only used by the DWC_usb3 hibernation code, so ++ * if you are not using the hibernation feature you can safely ++ * define it to a null function:

    ++ *

        \#define wmb() do {} while (0)

    ++ * ++ *
  • Definitions of the usb_request and usb_ep data types. The content of ++ * these structures is completely user-defined, but they must be defined here ++ * because the PCD embeds them into its own request and endpoint structures. ++ * This allows them to be passed back to the platform code when the PCD ++ * completes a USB transfer. ++ * ++ *
  • Definitions of all the \a DWC_E_* error codes that the PCD uses. If ++ * your platform uses POSIX error codes, they can be easily mapped to the ++ * \a DWC_E_* error codes. ++ * ++ *

    The only error codes with any operational significance are \a ++ * DWC_E_NOT_SUPPORTED, \a DWC_E_IN_PROGRESS, and \a DWC_E_SHUTDOWN, so these ++ * three error codes must be distinct, while the rest can be mapped to a ++ * single value if so desired.

    ++ * ++ *

    See the no_os_defs.h file for a complete list of the DWC_E_* error ++ * codes.

    ++ * ++ *
  • Definition of the dwc_usb3_core_params struct. This contains an entry ++ * for each option that the PCD driver supports. It is defined here so that you ++ * can add additional options for your platform code if you wish. See the ++ * no_os_defs.h file for a minimal implementation of this structure. ++ *
++ * ++ * @subsubsection os_dev_sec The os_dev.h File ++ * ++ * Because the \a os_defs.h file is included first by the PCD code, it does not ++ * have access to any of the definitions in the PCD header files. Therefore, any ++ * of your definitions which need such access should be placed in the \a ++ * os_dev.h file instead, which is included last by the PCD code. Specific ++ * things that need to be defined here include: ++ *
    ++ *
  • Definitions of the @ref dwc_rd32 and @ref dwc_wr32 inline functions. ++ * Given an offset from the beginning of the DWC_usb3 core address space to a ++ * particular register, these functions read from or write to that register. ++ * ++ *
  • Definitions of the @ref dwc_usb3_get_pcd_req and @ref dwc_usb3_get_pcd_ep ++ * macros. Given a pointer to a usb_request or usb_ep, these macros return a ++ * pointer to the enclosing dwc_usb3_pcd_req or dwc_usb3_pcd_ep struct. For ++ * any compiler that provides the \a offsetof macro, these should be: ++ * ++ *

        \#define dwc_usb3_get_pcd_req(usbreq) \\ \n ++ *         ++ * ((dwc_usb3_pcd_req_t *)((char *)(usbreq) - \\ \n ++ *             ++ * offsetof(struct dwc_usb3_pcd_req, usb_req)))

    ++ *

     

    ++ *

        \#define dwc_usb3_get_pcd_ep(usbep) \\ \n ++ *         ++ * ((dwc_usb3_pcd_ep_t *)((char *)(usbep) - \\ \n ++ *             ++ * offsetof(struct dwc_usb3_pcd_ep, usb_ep)))

    ++ *
    ++ * ++ *
  • Definitions of the @ref dwc_udelay and @ref dwc_mdelay non-sleeping delay ++ * routines. Given a delay value in microseconds or milliseconds respectively, ++ * these routines must delay for at least as long as the delay value. ++ * Non-sleeping means these routines may be called from any context, including ++ * interrupt context, so they must not reschedule or require an interrupt to ++ * indicate the end of the delay. Typically these routines would be implemented ++ * using a calibrated busy loop or a dedicated hardware timer. ++ * ++ *
  • Definition of the @ref dwc_msleep sleeping delay routine. Given a delay ++ * value in milliseconds, this routine must delay for at least as long as the ++ * delay value. Sleeping means this routine will only be called from process ++ * context, so it can reschedule or require an interrupt to indicate the end of ++ * the delay. Typically this routine would be implemented using a system timer. ++ * ++ *
  • Definitions of the @ref dwc_print\, @ref dwc_error\, @ref ++ * dwc_warn\, @ref dwc_info\, @ref dwc_isocdbg\, and @ref dwc_debug\ ++ * logging routines. ++ * Given a \a printf style format string and the number of arguments indicated ++ * by the last digit of the routine's name, they print a message to the system ++ * message log, or to the console. ++ * ++ *

    The different routine names indicate the importance of the message, ++ * where @ref dwc_print\ is the highest importance and @ref dwc_debug\ ++ * is the lowest.

    ++ * ++ *

    Typically these routines would be implemented using a \a printf type ++ * function if one is available, but the explicit argument count means they ++ * can be implemented without needing a \a varargs facility, if necessary.

    ++ *
++ * ++ * @subsection modify_pcd_h_sec Modify the pcd.h File ++ * ++ * The pcd.h file contains a few platform-dependent definitions, and may need ++ * some minor modifications to work on your platform: ++ *
    ++ *
  • dwc_usb3_pcd_req contains an \a entry field, which is used to link a ++ * request into the queue of requests for an endpoint. If your platform will ++ * use request queuing, then this field may need to be modified. ++ * ++ *

    Since the \a entry field is not used by the PCD, it can be commented out ++ * for the purpose of test-compiling the PCD.

    ++ * ++ *
  • dwc_ep contains a \a queue field, which is the head of the request ++ * queue for an endpoint. Again, this field may need to be modified for your ++ * platform, or it can be commented out for the purpose of test-compiling the ++ * PCD. ++ * ++ *
  • dwc_usb3_pcd contains a \a lock field, which is used for protecting ++ * the driver data from simultaneous access by multiple processors. If your ++ * platform is uniprocessor, then this field is not needed and you can comment ++ * it out, otherwise it may need to be modified for your platform. ++ * ++ *

    Since the \a lock field is not used by the PCD, it can be commented out ++ * for the purpose of test-compiling the PCD.

    ++ *
++ * ++ * @subsection makefile_or_project_sec Create the Makefile / Project File ++ * ++ * Create a makefile / project file for your platform, and add \a cil.o, \a ++ * cil_intr.o, \a pcd.o, \a pcd_intr.o, \a pcd_hiber.o, and \a ep0.o as the ++ * target object files. Because the result will not link successfully yet due ++ * to missing Function Driver routines, you should omit the link step, if ++ * possible. ++ * ++ * @subsection test_compile_sec Test Compile the PCD ++ * ++ *

Now try compiling your project.

++ * ++ *

If there are errors during the compile phase, you must modify your \a ++ * os_defs.h and \a os_dev.h files, and/or pcd.h, to attempt to eliminate them. ++ *

++ * ++ *

You may need to modify some of the other PCD source files to achieve a ++ * successful compile. For example, your compiler may require a different method ++ * of packing data structures, which may require you to modify usb.h.

++ * ++ *

If there are warnings during the compile phase, you should investigate ++ * each one carefully to determine whether it signifies a real problem or not. ++ *

++ * ++ *

If your makefile / project file contains a link step, you should expect ++ * it to fail, since at this point all of the Function Driver routines are ++ * missing.

++ * ++ *

If there are no errors or warnings during the compile phase, then the ++ * initial porting phase is complete.

++ * ++ * @page func_drvr_chap The Function Driver ++ * ++ * Porting the Function Driver is not as straightforward as the PCD, because ++ * there are more external factors to take into account. ++ * ++ * Because of this, we have provided the No-OS platform port. This port needs ++ * minimal support from the operating environment, and is designed to run as ++ * close to the hardware as possible. It is also self-contained, implementing ++ * its own Function Driver, so no OS support for USB functions is required. ++ * ++ * The Function implements a simple loopback test mode, where any data received ++ * from the host on the OUT endpoint is sent back to the host on the IN ++ * endpoint. Or, by changing the second line in ++ * no_os_src_sink_lpbk.c:dwc_usb3_function_init() to this: ++ * ++ *

    loopbk.src_sink = 1;

++ * ++ * the Function will implement a source/sink test mode, which sinks any packets ++ * received on the OUT endpoint while simultaneously sourcing 0-filled packets ++ * on the IN endpoint. ++ * ++ * The major limitation of the No-OS port is that all DMA data structures are ++ * statically allocated in the C code. This will only work in very simple ++ * operating environments where the system memory is mapped with virtual ++ * address == physical address. If you have an environment where this is not the ++ * case, then at a minimum you will need to replace these static allocations ++ * with calls to OS routines to perform proper DMA allocations. ++ * ++ * To help while debugging the No-OS port, we have included Linux code that is ++ * conditionally compiled if the LINUXTEST macro is defined. This allows the ++ * No-OS code to compile and run on a Linux platform, as a completely ++ * self-contained driver that does not use the Linux Gadget framework. The ++ * No-OS port can be built for Linux in this way by invoking "make" as follows: ++ * ++ *

    make NOOS=1

++ * ++ * The no_os/ platform code consists of the following files: ++ * ++ * - no_os_init.c: Initialization code and "bus glue". ++ * - no_os_gadget.c: Implements a custom Function Driver API. ++ * - no_os_ep0.c: Contains the USB descriptors for the Function. ++ * - no_os_src_sink_lpbk.c: Contains an implementation of a simple ++ * source-sink/loopback Function. ++ * - no_os_hiber.c: Implements the platform-specific code needed to support the ++ * DWC_usb3 hibernation feature. Note: This code is incomplete, so you should ++ * consider DWC_usb3 hibernation as unsupported by the No-OS Function Driver ++ * at this time. ++ * ++ * @section func_walk_sec Code Walkthrough of the No-OS Function Driver ++ * ++ * @subsection func_init_sec Initialization ++ * ++ * At initialization time, @ref dwc_usb3_driver_init in no_os_init.c is called, ++ * which does the following: ++ * - Allocates memory for the \a usb3_dev driver data struct. ++ * - Maps the DWC_usb3 registers into the processor's memory space. ++ * - Calls the @ref dwc_usb3_pcd_check_snpsid API routine to make sure this is a ++ * DWC_usb3 device, and to save the value from the SNPSID register in the ++ * \a usb3_dev struct. ++ * - Allocates DMAable memory for the event buffer, and for the EP0 DMA ++ * descriptors and data buffers. ++ * - Calls the @ref dwc_usb3_pcd_common_init API routine. ++ * - Calls the @ref dwc_usb3_gadget_init API routine in no_os_gadget.c, which ++ * does the following: ++ * - Sets the dwc_ep.num field for each physical endpoint to the USB endpoint ++ * number associated with that endpoint. ++ * - Initializes the dwc_ep.queue field for each physical endpoint. This is ++ * the head of the queue where each transfer request for that endpoint will ++ * be queued. ++ * - Calls @ref dwc_usb3_function_init in no_os_src_sink_lpbk.c, which allocates ++ * data buffers for each Bulk endpoint. ++ * - Calls the @ref dwc_usb3_pcd_init API routine. ++ * - Hooks the @ref dwc_usb3_common_irq top-level interrupt handler routine to ++ * the DWC_usb3 IRQ vector. ++ * ++ * At this point the DWC_usb3 core and the driver are initialized, and waiting ++ * for the Device to be connected to a Host. ++ * ++ * @subsection func_conn_enum_sec Connection and Enumeration ++ * ++ * When a connection to a Host is established, a USBRst event ++ * is generated, followed by a ConnectDone event. ++ * ++ * The USBRst event is handled internally by the PCD. ++ * ++ * The ConnectDone event results in the following: ++ * - The PCD calls the @ref dwc_usb3_gadget_connect API routine in no_os_gadget.c. ++ * - @ref dwc_usb3_gadget_connect in turn calls @ref dwc_usb3_function_connect ++ * in no_os_src_sink_lpbk.c. ++ * - @ref dwc_usb3_function_connect sets the function's Bulk max packet size ++ * according to the connection speed. ++ * ++ * Once the connection sequence completes, the Host starts sending Control ++ * requests to the Device to enumerate it. The general flow for Control requests ++ * is as follows: ++ * - The PCD code in ep0.c handles most Control requests internally. ++ * - For those requests it cannot handle, the PCD calls the ++ * @ref dwc_usb3_gadget_setup API routine in no_os_gadget.c. ++ * - @ref dwc_usb3_gadget_setup in turn calls @ref dwc_usb3_no_os_setup in ++ * no_os_ep0.c. ++ * - @ref dwc_usb3_no_os_setup handles GET_DESCRIPTOR Control ++ * requests (except for the BOS descriptor, which is handled by ep0.c), using ++ * the information encoded in the USB descriptors in no_os_ep0.c. See @ref ++ * usb_desc_sec for details. ++ * - For all remaining Control requests, the no_os_ep0.c code calls @ref ++ * dwc_usb3_function_setup in no_os_src_sink_lpbk.c. ++ * ++ * @subsection func_config_sec Configuration ++ * ++ * Once the Host has enumerated the Device, it will configure it as follows: ++ * - The host sends a SET_CONFIGURATION Control request with a ++ * bConfigurationValue of 1 (since that is ++ * the value given in the Config descriptors in no_os_ep0.c), followed by a ++ * SET_INTERFACE Control request with a ++ * bInterfaceNumber of 0 and a ++ * bAlternateSetting of 0 (since those are ++ * the values given in the Interface descriptors in no_os_ep0.c). ++ * - SET_CONFIGURATION and SET_INTERFACE are ++ * two of the Control requests that are handled by @ref dwc_usb3_function_setup ++ * in no_os_src_sink_lpbk.c, so that routine will be called. ++ * - @ref dwc_usb3_function_setup in turn calls @ref set_interface (in the same file) ++ * with an alt parameter of 0. ++ * - @ref set_interface calls @ref enable_eps (in the same file). ++ * - @ref enable_eps calls @ref dwc_usb3_ep_enable in no_os_gadget.c for each of ++ * the Bulk endpoints, with pointers to the USB descriptors from no_os_ep0.c ++ * corresponding to the speed of the connection. ++ * - @ref dwc_usb3_ep_enable does the following: ++ * - Gets the endpoint info from the Endpoint descriptor for that EP. ++ * - Decides how many TRBs to allocate for the EP. ++ * - Calls the @ref dwc_usb3_pcd_trb_alloc API routine to allocate the TRBs. ++ * Note: @ref dwc_usb3_pcd_trb_alloc will call back to the @ref ++ * dwc_usb3_gadget_alloc_dma API routine in no_os_gadget.c to do the ++ * memory allocation. ++ * - Calls the @ref dwc_usb3_pcd_ep_enable API routine to enable the endpoint ++ * in the DWC_usb3 core. ++ * - @ref set_interface then calls @ref dwc_usb3_alloc_request in no_os_gadget.c ++ * repeatedly, to allocate a number of transfer requests for each of the Bulk ++ * endpoints. ++ * - @ref dwc_usb3_alloc_request does the following: ++ * - Allocates a PCD request from the gadget's pool of requests. ++ * - Returns a pointer to the usb_request member of the PCD request. ++ * - @ref set_interface then fills in a number of fields in each usb_request, ++ * among them the \a complete function pointer, then calls @ref dwc_usb3_ep_queue ++ * in no_os_gadget.c to queue it for transfer. ++ * - @ref dwc_usb3_ep_queue does the following: ++ * - Sets the usb_request \a status field to -DWC_E_IN_PROGRESS. ++ * - Fills in a number of required fields in the PCD request. ++ * - Decides whether to start the request immediately, or to queue it to be ++ * started later. If it decides to start the request immediately, it: ++ * - Calls the @ref dwc_usb3_pcd_fill_trbs API routine to fill in the TRB ++ * for the request. ++ * - Calls the @ref dwc_usb3_pcd_ep_submit_req API routine to start the ++ * transfer in the DWC_usb3 core. ++ * - Adds the request to the endpoint's request queue. ++ * ++ * At this point the Device is in the Configured state, ready to receive Bulk ++ * transfers from the Host. ++ * ++ * @subsection func_oper_sec Operation ++ * ++ * When the Host requests a Bulk data transfer to or from the Device, the PCD ++ * will receive a XferComplete event from the DWC_usb3 core ++ * when the transfer completes. This will result in the following: ++ * - The PCD calls the @ref dwc_usb3_gadget_get_request API routine in ++ * no_os_gadget.c. ++ * - @ref dwc_usb3_gadget_get_request returns the request that is at the head of ++ * the endpoint's request queue. This will be the request whose transfer has ++ * just completed. ++ * - The PCD then calls the @ref dwc_usb3_gadget_complete API routine in ++ * no_os_gadget.c. ++ * - @ref dwc_usb3_gadget_complete removes the request from the endpoint's queue, ++ * fills in the \a status and \a actual fields in the usb_request, and calls ++ * the \a complete function pointer in the usb_request. ++ * - The \a complete function pointer points to @ref loopbk_complete in ++ * no_os_src_sink_lpbk.c, which does the following: ++ * - Checks the \a status field in the usb_request. If it is not ++ * 0 then an error or a disconnect occurred, which are ++ * handled appropriately. ++ * - If the \a status field is 0, then the endpoint is ++ * checked. If it is the OUT EP, @ref dwc_usb3_ep_queue in no_os_gadget.c is ++ * called to requeue the usb_request on the IN EP for sending the data back ++ * to the host. If it is the IN EP, @ref dwc_usb3_ep_queue is called to requeue ++ * the usb_request on the OUT EP for receiving more data from the host. ++ * - The PCD then calls the @ref dwc_usb3_gadget_start_next_request API routine ++ * in no_os_gadget.c. ++ * - If there are any more requests queued for the endpoint, ++ * @ref dwc_usb3_gadget_start_next_request takes the first one and does the ++ * following: ++ * - Calls the @ref dwc_usb3_pcd_fill_trbs API routine to fill in the TRB for ++ * the request. ++ * - Calls the @ref dwc_usb3_pcd_ep_submit_req API routine to start the ++ * transfer in the DWC_usb3 core. ++ * ++ * @section usb_desc_sec USB Descriptors ++ * ++ * no_os_ep0.c contains a minimal set of USB descriptors - a set of String ++ * descriptors, a Device descriptor, a Device Qualifier descriptor, and three ++ * Configuration descriptors, one for each of the speeds that the DWC_usb3 core ++ * supports. Each of the Configuration descriptors contains two Endpoint ++ * descriptors, one for a Bulk IN endpoint and one for a Bulk OUT endpoint. The ++ * Super Speed Configuration descriptor also contains two Super Speed Endpoint ++ * Companion descriptors, one for each of the Bulk endpoints. All of these ++ * descriptors may need to be modified for your platform's particular Function ++ * implementation. ++ * ++ * ep0.c contains the required BOS descriptor. Fields that must be modified here ++ * are \a bU1DevExitLat and \a wU2DevExitLat in the Super Speed Device ++ * Capability descriptor, and \a containerID in the optional Container ID ++ * Capability descriptor (if used). ++ * ++ * The compiler must be instructed not to add padding between the fields in any ++ * of these descriptors. This is the purpose of the \a UPACKED attribute macro ++ * for the GCC compiler (or the ARMCC compiler with the \a --gnu flag). The ++ * \a \#include  and \a \#include  directives, ++ * as shown in usb.h and no_os_ep0.c, accomplish the same thing for the ++ * Microsoft compilers. ++ * ++ * The exact format for all of these descriptors is described in detail in ++ * Chapter 9 of the USB 3.0 specification. ++ * ++ * @section comp_func_sec Porting the No-OS Function Driver ++ * ++ * Copy all the .c files from the \a driver/no_os/ directory into the platform ++ * directory that you created earlier to hold your \a os_defs.h and \a os_dev.h ++ * files (e.g. \a driver/myplat/). Rename all the .c files accordingly (e.g. ++ * \a no_os_init.c -> \a myplat_init.c, \a no_os_gadget.c -> \a myplat_gadget.c ++ * ...). ++ * ++ * Modify the source code as necessary to work on your platform. ++ * ++ * Modify the makefile / project file for your platform and add e.g. \a ++ * myplat_init.o, \a myplat_gadget.o ... to the target object files. You should ++ * also add a link step if one does not exist already. ++ * ++ * Now try compiling your project. As with @ref test_compile_sec, you must ++ * modify the source files as necessary until the compile phase completes ++ * successfully. ++ * ++ * Once the compile phase is successful, try to resolve any errors that occur ++ * in the link phase. Most likely these will be due to missing support routines, ++ * such as \a memcpy or \a printf. You must either add libraries to the link step ++ * to provide these routines, write your own routines and include them in the ++ * build, or modify the driver source files to use alternate versions of these ++ * routines. ++ * ++ * @page pcd_api_chap PCD to Function Driver API ++ * ++ * @section pcd_funcs_sec API Routines in the PCD ++ * ++ * These routines are provided by the PCD (and the CIL), and make up the PCD ++ * side of the API. ++ * ++ * @subsection init_funcs_sec Initialization Routines ++ * ++ * These routines handle initialization of the CIL and PCD driver components ++ * and the DWC_usb3 core. ++ * ++ * See @ref init_api_grp for a detailed description of these routines. ++ * ++ * - dwc_usb3_pcd_check_snpsid() ++ * - dwc_usb3_pcd_common_init() ++ * - dwc_usb3_pcd_common_remove() ++ * - dwc_usb3_pcd_init() ++ * - dwc_usb3_pcd_remove() ++ * - dwc_usb3_pcd_device_init() ++ * - dwc_usb3_pcd_device_remove() ++ * ++ * @subsection trb_funcs_sec TRB Routines ++ * ++ * These routines handle the allocation, deallocation, and setup of TRBs. ++ * ++ * See @ref trb_api_grp for a detailed description of these routines. ++ * ++ * - dwc_usb3_pcd_trb_alloc() ++ * - dwc_usb3_pcd_trb_free() ++ * - dwc_usb3_pcd_fill_trbs() ++ * ++ * @subsection ep_funcs_sec Endpoint Routines ++ * ++ * These routines handle all the functionality required for configuring, ++ * enabling, controlling, and submitting transfers to an endpoint. ++ * ++ * Note: For Control endpoint 0, only the submit_req, cancel_req, request_done, ++ * and set_halt routines are used; the remaining functionality is handled either ++ * by the @ref ep0_funcs_sec below or internally by the PCD. ++ * ++ * See @ref ep_api_grp for a detailed description of these routines. ++ * ++ * - dwc_usb3_pcd_ep_enable() ++ * - dwc_usb3_pcd_ep_disable() ++ * - dwc_usb3_pcd_ep_submit_req() ++ * - dwc_usb3_pcd_ep_cancel_req() ++ * - dwc_usb3_pcd_request_done() ++ * - dwc_usb3_pcd_ep_start_transfer() ++ * - dwc_usb3_pcd_ep_set_stall() ++ * - dwc_usb3_pcd_ep_clear_stall() ++ * - dwc_usb3_pcd_ep_set_halt() ++ * ++ * @subsection ep0_funcs_sec Control Endpoint 0 Routines ++ * ++ * These routines are only used for Control endpoint 0. ++ * ++ * See @ref ep0_api_grp for a detailed description of these routines. ++ * ++ * - dwc_usb3_pcd_ep0_out_start() ++ * - dwc_usb3_pcd_ep0_start_transfer() ++ * - dwc_usb3_pcd_ep0_continue_transfer() ++ * - dwc_usb3_pcd_ep0_data_stage() ++ * ++ * @subsection misc_funcs_sec Miscellaneous Routines ++ * ++ * These are miscellaneous routines that don't fit into any of the other ++ * categories. ++ * ++ * See @ref misc_api_grp for a detailed description of these routines. ++ * ++ * - dwc_usb3_pcd_get_ep_by_addr() ++ * - dwc_usb3_pcd_get_frame_number() ++ * - dwc_usb3_pcd_isoc_ep_hiber_restart() ++ * - dwc_usb3_pcd_stop() ++ * - dwc_usb3_pcd_get_link_state() ++ * - dwc_usb3_pcd_set_link_state() ++ * - dwc_usb3_pcd_remote_wake() ++ * - dwc_usb3_pcd_do_test_mode() ++ * ++ * @section gadget_funcs_sec API Routines in the Function Driver ++ * ++ * These routines need to be implemented by the platform code, and make up the ++ * Function Driver side of the API. ++ * ++ * @subsection gadget_notif_sec Function Driver Notification Routines ++ * ++ * These routines receive notifications from the PCD when certain events occur ++ * which the Function Driver may need to be aware of. ++ * ++ * See @ref gadget_notif_grp for a detailed description of these routines. ++ * ++ * - dwc_usb3_gadget_connect() ++ * - dwc_usb3_gadget_disconnect() ++ * - dwc_usb3_gadget_suspend() ++ * - dwc_usb3_gadget_resume() ++ * - dwc_usb3_gadget_setup() ++ * - dwc_usb3_gadget_complete() ++ * ++ * @subsection gadget_callbk_sec Function Driver Callback Routines ++ * ++ * The PCD calls these routines when it needs something from the Function ++ * Driver. ++ * ++ * See @ref gadget_callbk_grp for a detailed description of these routines. ++ * ++ * - dwc_usb3_gadget_alloc_dma() ++ * - dwc_usb3_gadget_free_dma() ++ * - dwc_usb3_gadget_get_request() ++ * - dwc_usb3_gadget_start_next_request() ++ * - dwc_usb3_gadget_isoc_ep_start() ++ * - dwc_usb3_gadget_request_nuke() ++ * - dwc_usb3_gadget_set_ep_not_started() ++ * ++ */ ++ ++#endif /* _DWC_DOX_PORT_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc3/driver.sln b/drivers/usb/gadget/udc/hiudc3/driver.sln +new file mode 100644 +index 0000000..849a645 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/driver.sln +@@ -0,0 +1,20 @@ ++锘 ++Microsoft Visual Studio Solution File, Format Version 12.00 ++# Visual Studio 11 ++Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "driver", "driver.vcxproj", "{876C75FB-DB73-46F3-9ED0-92D9FA45FCA4}" ++EndProject ++Global ++ GlobalSection(SolutionConfigurationPlatforms) = preSolution ++ Debug|Win32 = Debug|Win32 ++ Release|Win32 = Release|Win32 ++ EndGlobalSection ++ GlobalSection(ProjectConfigurationPlatforms) = postSolution ++ {876C75FB-DB73-46F3-9ED0-92D9FA45FCA4}.Debug|Win32.ActiveCfg = Debug|Win32 ++ {876C75FB-DB73-46F3-9ED0-92D9FA45FCA4}.Debug|Win32.Build.0 = Debug|Win32 ++ {876C75FB-DB73-46F3-9ED0-92D9FA45FCA4}.Release|Win32.ActiveCfg = Release|Win32 ++ {876C75FB-DB73-46F3-9ED0-92D9FA45FCA4}.Release|Win32.Build.0 = Release|Win32 ++ EndGlobalSection ++ GlobalSection(SolutionProperties) = preSolution ++ HideSolutionNode = FALSE ++ EndGlobalSection ++EndGlobal +diff --git a/drivers/usb/gadget/udc/hiudc3/driver.vcxproj b/drivers/usb/gadget/udc/hiudc3/driver.vcxproj +new file mode 100644 +index 0000000..b6d357d +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/driver.vcxproj +@@ -0,0 +1,91 @@ ++ ++ ++ ++ ++ Debug ++ Win32 ++ ++ ++ Release ++ Win32 ++ ++ ++ ++ $(VCTargetsPath11) ++ ++ ++ {876C75FB-DB73-46F3-9ED0-92D9FA45FCA4} ++ driver ++ ++ ++ ++ Application ++ true ++ v110 ++ MultiByte ++ ++ ++ Application ++ false ++ v110 ++ true ++ MultiByte ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Level3 ++ Disabled ++ $(ProjectDir);%(AdditionalIncludeDirectories) ++ ++ ++ true ++ ++ ++ ++ ++ Level3 ++ MaxSpeed ++ true ++ true ++ $(ProjectDir);%(AdditionalIncludeDirectories) ++ ++ ++ true ++ true ++ true ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +\ No newline at end of file +diff --git a/drivers/usb/gadget/udc/hiudc3/driver.vcxproj.filters b/drivers/usb/gadget/udc/hiudc3/driver.vcxproj.filters +new file mode 100644 +index 0000000..b25fc0c +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/driver.vcxproj.filters +@@ -0,0 +1,66 @@ ++锘 ++ ++ ++ ++ {4FC737F1-C7A5-4376-A066-2A32D752A2FF} ++ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx ++ ++ ++ {93995380-89BD-4b04-88EB-625FBE52EBFB} ++ h;hpp;hxx;hm;inl;inc;xsd ++ ++ ++ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} ++ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms ++ ++ ++ ++ ++ Header Files ++ ++ ++ Header Files ++ ++ ++ Header Files ++ ++ ++ Header Files ++ ++ ++ Header Files ++ ++ ++ Header Files ++ ++ ++ Header Files ++ ++ ++ ++ ++ Source Files ++ ++ ++ Source Files ++ ++ ++ Source Files ++ ++ ++ Source Files ++ ++ ++ Source Files ++ ++ ++ Source Files ++ ++ ++ Source Files ++ ++ ++ Source Files ++ ++ ++ +\ No newline at end of file +diff --git a/drivers/usb/gadget/udc/hiudc3/dwc_list.h b/drivers/usb/gadget/udc/hiudc3/dwc_list.h +new file mode 100644 +index 0000000..9224bd6 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/dwc_list.h +@@ -0,0 +1,468 @@ ++/* $OpenBSD: queue.h,v 1.26 2004/05/04 16:59:32 grange Exp $ */ ++/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ ++ ++/* ++ * Copyright (c) 1991, 1993 ++ * The Regents of the University of California. 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. ++ * 3. Neither the name of the University nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. ++ * ++ * @(#)queue.h 8.5 (Berkeley) 8/20/94 ++ */ ++ ++#ifndef _DWC_LIST_H_ ++#define _DWC_LIST_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ * ++ * This file defines linked list operations. It is derived from BSD with ++ * only the MACRO names being prefixed with DWC_. This is because a few of ++ * these names conflict with those on Linux. For documentation on use, see the ++ * inline comments in the source code. The original license for this source ++ * code applies and is preserved in the dwc_list.h source file. ++ */ ++ ++/* ++ * This file defines five types of data structures: singly-linked lists, ++ * lists, simple queues, tail queues, and circular queues. ++ * ++ * ++ * A singly-linked list is headed by a single forward pointer. The elements ++ * are singly linked for minimum space and pointer manipulation overhead at ++ * the expense of O(n) removal for arbitrary elements. New elements can be ++ * added to the list after an existing element or at the head of the list. ++ * Elements being removed from the head of the list should use the explicit ++ * macro for this purpose for optimum efficiency. A singly-linked list may ++ * only be traversed in the forward direction. Singly-linked lists are ideal ++ * for applications with large datasets and few or no removals or for ++ * implementing a LIFO queue. ++ * ++ * A list is headed by a single forward pointer (or an array of forward ++ * pointers for a hash table header). The elements are doubly linked ++ * so that an arbitrary element can be removed without a need to ++ * traverse the list. New elements can be added to the list before ++ * or after an existing element or at the head of the list. A list ++ * may only be traversed in the forward direction. ++ * ++ * A simple queue is headed by a pair of pointers, one the head of the ++ * list and the other to the tail of the list. The elements are singly ++ * linked to save space, so elements can only be removed from the ++ * head of the list. New elements can be added to the list before or after ++ * an existing element, at the head of the list, or at the end of the ++ * list. A simple queue may only be traversed in the forward direction. ++ * ++ * A tail queue is headed by a pair of pointers, one to the head of the ++ * list and the other to the tail of the list. The elements are doubly ++ * linked so that an arbitrary element can be removed without a need to ++ * traverse the list. New elements can be added to the list before or ++ * after an existing element, at the head of the list, or at the end of ++ * the list. A tail queue may be traversed in either direction. ++ * ++ * A circle queue is headed by a pair of pointers, one to the head of the ++ * list and the other to the tail of the list. The elements are doubly ++ * linked so that an arbitrary element can be removed without a need to ++ * traverse the list. New elements can be added to the list before or after ++ * an existing element, at the head of the list, or at the end of the list. ++ * A circle queue may be traversed in either direction, but has a more ++ * complex end of list detection. ++ * ++ * For details on the use of these macros, see the queue(3) manual page. ++ */ ++ ++/* ++ * Singly-linked List definitions. ++ */ ++#define DWC_SLIST_HEAD(name, type) \ ++struct name { \ ++ struct type *slh_first; /* first element */ \ ++} ++ ++#define DWC_SLIST_HEAD_INITIALIZER(head) \ ++ { NULL } ++ ++#define DWC_SLIST_ENTRY(type) \ ++struct { \ ++ struct type *sle_next; /* next element */ \ ++} ++ ++/* ++ * Singly-linked List access methods. ++ */ ++#define DWC_SLIST_FIRST(head) ((head)->slh_first) ++#define DWC_SLIST_END(head) NULL ++#define DWC_SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) ++#define DWC_SLIST_NEXT(elm, field) ((elm)->field.sle_next) ++ ++#define DWC_SLIST_FOREACH(var, head, field) \ ++ for((var) = SLIST_FIRST(head); \ ++ (var) != SLIST_END(head); \ ++ (var) = SLIST_NEXT(var, field)) ++ ++#define DWC_SLIST_FOREACH_PREVPTR(var, varp, head, field) \ ++ for((varp) = &SLIST_FIRST((head)); \ ++ ((var) = *(varp)) != SLIST_END(head); \ ++ (varp) = &SLIST_NEXT((var), field)) ++ ++/* ++ * Singly-linked List functions. ++ */ ++#define DWC_SLIST_INIT(head) { \ ++ SLIST_FIRST(head) = SLIST_END(head); \ ++} ++ ++#define DWC_SLIST_INSERT_AFTER(slistelm, elm, field) do { \ ++ (elm)->field.sle_next = (slistelm)->field.sle_next; \ ++ (slistelm)->field.sle_next = (elm); \ ++} while (0) ++ ++#define DWC_SLIST_INSERT_HEAD(head, elm, field) do { \ ++ (elm)->field.sle_next = (head)->slh_first; \ ++ (head)->slh_first = (elm); \ ++} while (0) ++ ++#define DWC_SLIST_REMOVE_NEXT(head, elm, field) do { \ ++ (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ ++} while (0) ++ ++#define DWC_SLIST_REMOVE_HEAD(head, field) do { \ ++ (head)->slh_first = (head)->slh_first->field.sle_next; \ ++} while (0) ++ ++#define DWC_SLIST_REMOVE(head, elm, type, field) do { \ ++ if ((head)->slh_first == (elm)) { \ ++ SLIST_REMOVE_HEAD((head), field); \ ++ } \ ++ else { \ ++ struct type *curelm = (head)->slh_first; \ ++ while( curelm->field.sle_next != (elm) ) \ ++ curelm = curelm->field.sle_next; \ ++ curelm->field.sle_next = \ ++ curelm->field.sle_next->field.sle_next; \ ++ } \ ++} while (0) ++ ++/* ++ * Simple queue definitions. ++ */ ++#define DWC_SIMPLEQ_HEAD(name, type) \ ++struct name { \ ++ struct type *sqh_first; /* first element */ \ ++ struct type **sqh_last; /* addr of last next element */ \ ++} ++ ++#define DWC_SIMPLEQ_HEAD_INITIALIZER(head) \ ++ { NULL, &(head).sqh_first } ++ ++#define DWC_SIMPLEQ_ENTRY(type) \ ++struct { \ ++ struct type *sqe_next; /* next element */ \ ++} ++ ++/* ++ * Simple queue access methods. ++ */ ++#define DWC_SIMPLEQ_FIRST(head) ((head)->sqh_first) ++#define DWC_SIMPLEQ_END(head) NULL ++#define DWC_SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) ++#define DWC_SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) ++ ++#define DWC_SIMPLEQ_FOREACH(var, head, field) \ ++ for((var) = SIMPLEQ_FIRST(head); \ ++ (var) != SIMPLEQ_END(head); \ ++ (var) = SIMPLEQ_NEXT(var, field)) ++ ++/* ++ * Simple queue functions. ++ */ ++#define DWC_SIMPLEQ_INIT(head) do { \ ++ (head)->sqh_first = NULL; \ ++ (head)->sqh_last = &(head)->sqh_first; \ ++} while (0) ++ ++#define DWC_SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ ++ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ ++ (head)->sqh_last = &(elm)->field.sqe_next; \ ++ (head)->sqh_first = (elm); \ ++} while (0) ++ ++#define DWC_SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ ++ (elm)->field.sqe_next = NULL; \ ++ *(head)->sqh_last = (elm); \ ++ (head)->sqh_last = &(elm)->field.sqe_next; \ ++} while (0) ++ ++#define DWC_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ ++ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ ++ (head)->sqh_last = &(elm)->field.sqe_next; \ ++ (listelm)->field.sqe_next = (elm); \ ++} while (0) ++ ++#define DWC_SIMPLEQ_REMOVE_HEAD(head, field) do { \ ++ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ ++ (head)->sqh_last = &(head)->sqh_first; \ ++} while (0) ++ ++/* ++ * Tail queue definitions. ++ */ ++#define DWC_TAILQ_HEAD(name, type) \ ++struct name { \ ++ struct type *tqh_first; /* first element */ \ ++ struct type **tqh_last; /* addr of last next element */ \ ++} ++ ++#define DWC_TAILQ_HEAD_INITIALIZER(head) \ ++ { NULL, &(head).tqh_first } ++ ++#define DWC_TAILQ_ENTRY(type) \ ++struct { \ ++ struct type *tqe_next; /* next element */ \ ++ struct type **tqe_prev; /* address of previous next element */ \ ++} ++ ++/* ++ * tail queue access methods ++ */ ++#define DWC_TAILQ_FIRST(head) ((head)->tqh_first) ++#define DWC_TAILQ_END(head) NULL ++#define DWC_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) ++#define DWC_TAILQ_LAST(head, headname) \ ++ (*(((struct headname *)((head)->tqh_last))->tqh_last)) ++/* XXX */ ++#define DWC_TAILQ_PREV(elm, headname, field) \ ++ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) ++#define DWC_TAILQ_EMPTY(head) \ ++ (TAILQ_FIRST(head) == TAILQ_END(head)) ++ ++#define DWC_TAILQ_FOREACH(var, head, field) \ ++ for((var) = TAILQ_FIRST(head); \ ++ (var) != TAILQ_END(head); \ ++ (var) = TAILQ_NEXT(var, field)) ++ ++#define DWC_TAILQ_FOREACH_REVERSE(var, head, headname, field) \ ++ for((var) = TAILQ_LAST(head, headname); \ ++ (var) != TAILQ_END(head); \ ++ (var) = TAILQ_PREV(var, headname, field)) ++ ++/* ++ * Tail queue functions. ++ */ ++#define DWC_TAILQ_INIT(head) do { \ ++ (head)->tqh_first = NULL; \ ++ (head)->tqh_last = &(head)->tqh_first; \ ++} while (0) ++ ++#define DWC_TAILQ_INSERT_HEAD(head, elm, field) do { \ ++ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ ++ (head)->tqh_first->field.tqe_prev = \ ++ &(elm)->field.tqe_next; \ ++ else \ ++ (head)->tqh_last = &(elm)->field.tqe_next; \ ++ (head)->tqh_first = (elm); \ ++ (elm)->field.tqe_prev = &(head)->tqh_first; \ ++} while (0) ++ ++#define DWC_TAILQ_INSERT_TAIL(head, elm, field) do { \ ++ (elm)->field.tqe_next = NULL; \ ++ (elm)->field.tqe_prev = (head)->tqh_last; \ ++ *(head)->tqh_last = (elm); \ ++ (head)->tqh_last = &(elm)->field.tqe_next; \ ++} while (0) ++ ++#define DWC_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ ++ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ ++ (elm)->field.tqe_next->field.tqe_prev = \ ++ &(elm)->field.tqe_next; \ ++ else \ ++ (head)->tqh_last = &(elm)->field.tqe_next; \ ++ (listelm)->field.tqe_next = (elm); \ ++ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ ++} while (0) ++ ++#define DWC_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ ++ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ ++ (elm)->field.tqe_next = (listelm); \ ++ *(listelm)->field.tqe_prev = (elm); \ ++ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ ++} while (0) ++ ++#define DWC_TAILQ_REMOVE(head, elm, field) do { \ ++ if (((elm)->field.tqe_next) != NULL) \ ++ (elm)->field.tqe_next->field.tqe_prev = \ ++ (elm)->field.tqe_prev; \ ++ else \ ++ (head)->tqh_last = (elm)->field.tqe_prev; \ ++ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ ++} while (0) ++ ++#define DWC_TAILQ_REPLACE(head, elm, elm2, field) do { \ ++ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ ++ (elm2)->field.tqe_next->field.tqe_prev = \ ++ &(elm2)->field.tqe_next; \ ++ else \ ++ (head)->tqh_last = &(elm2)->field.tqe_next; \ ++ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ ++ *(elm2)->field.tqe_prev = (elm2); \ ++} while (0) ++ ++/* ++ * Circular queue definitions. ++ */ ++#define DWC_CIRCLEQ_HEAD(name, type) \ ++struct name { \ ++ struct type *cqh_first; /* first element */ \ ++ struct type *cqh_last; /* last element */ \ ++} ++ ++#define DWC_CIRCLEQ_HEAD_INITIALIZER(head) \ ++ { DWC_CIRCLEQ_END(&head), DWC_CIRCLEQ_END(&head) } ++ ++#define DWC_CIRCLEQ_ENTRY(type) \ ++struct { \ ++ struct type *cqe_next; /* next element */ \ ++ struct type *cqe_prev; /* previous element */ \ ++} ++ ++/* ++ * Circular queue access methods ++ */ ++#define DWC_CIRCLEQ_FIRST(head) ((head)->cqh_first) ++#define DWC_CIRCLEQ_LAST(head) ((head)->cqh_last) ++#define DWC_CIRCLEQ_END(head) ((void *)(head)) ++#define DWC_CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) ++#define DWC_CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) ++#define DWC_CIRCLEQ_EMPTY(head) \ ++ (DWC_CIRCLEQ_FIRST(head) == DWC_CIRCLEQ_END(head)) ++ ++#define DWC_CIRCLEQ_EMPTY_ENTRY(elm, field) (((elm)->field.cqe_next == NULL) && ((elm)->field.cqe_prev == NULL)) ++ ++#define DWC_CIRCLEQ_FOREACH(var, head, field) \ ++ for((var) = DWC_CIRCLEQ_FIRST(head); \ ++ (var) != DWC_CIRCLEQ_END(head); \ ++ (var) = DWC_CIRCLEQ_NEXT(var, field)) ++ ++#define DWC_CIRCLEQ_FOREACH_SAFE(var, var2, head, field) \ ++ for((var) = DWC_CIRCLEQ_FIRST(head), var2 = DWC_CIRCLEQ_NEXT(var, field); \ ++ (var) != DWC_CIRCLEQ_END(head); \ ++ (var) = var2, var2 = DWC_CIRCLEQ_NEXT(var, field)) ++ ++#define DWC_CIRCLEQ_FOREACH_REVERSE(var, head, field) \ ++ for((var) = DWC_CIRCLEQ_LAST(head); \ ++ (var) != DWC_CIRCLEQ_END(head); \ ++ (var) = DWC_CIRCLEQ_PREV(var, field)) ++ ++/* ++ * Circular queue functions. ++ */ ++#define DWC_CIRCLEQ_INIT(head) do { \ ++ (head)->cqh_first = DWC_CIRCLEQ_END(head); \ ++ (head)->cqh_last = DWC_CIRCLEQ_END(head); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INIT_ENTRY(elm, field) do { \ ++ (elm)->field.cqe_next = NULL; \ ++ (elm)->field.cqe_prev = NULL; \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ ++ (elm)->field.cqe_next = (listelm)->field.cqe_next; \ ++ (elm)->field.cqe_prev = (listelm); \ ++ if ((listelm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_last = (elm); \ ++ else \ ++ (listelm)->field.cqe_next->field.cqe_prev = (elm); \ ++ (listelm)->field.cqe_next = (elm); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ ++ (elm)->field.cqe_next = (listelm); \ ++ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ ++ if ((listelm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_first = (elm); \ ++ else \ ++ (listelm)->field.cqe_prev->field.cqe_next = (elm); \ ++ (listelm)->field.cqe_prev = (elm); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ ++ (elm)->field.cqe_next = (head)->cqh_first; \ ++ (elm)->field.cqe_prev = DWC_CIRCLEQ_END(head); \ ++ if ((head)->cqh_last == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_last = (elm); \ ++ else \ ++ (head)->cqh_first->field.cqe_prev = (elm); \ ++ (head)->cqh_first = (elm); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ ++ (elm)->field.cqe_next = DWC_CIRCLEQ_END(head); \ ++ (elm)->field.cqe_prev = (head)->cqh_last; \ ++ if ((head)->cqh_first == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_first = (elm); \ ++ else \ ++ (head)->cqh_last->field.cqe_next = (elm); \ ++ (head)->cqh_last = (elm); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_REMOVE(head, elm, field) do { \ ++ if ((elm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_last = (elm)->field.cqe_prev; \ ++ else \ ++ (elm)->field.cqe_next->field.cqe_prev = \ ++ (elm)->field.cqe_prev; \ ++ if ((elm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_first = (elm)->field.cqe_next; \ ++ else \ ++ (elm)->field.cqe_prev->field.cqe_next = \ ++ (elm)->field.cqe_next; \ ++} while (0) ++ ++#define DWC_CIRCLEQ_REMOVE_INIT(head, elm, field) do { \ ++ DWC_CIRCLEQ_REMOVE(head, elm, field); \ ++ DWC_CIRCLEQ_INIT_ENTRY(elm, field); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ ++ if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ ++ DWC_CIRCLEQ_END(head)) \ ++ (head).cqh_last = (elm2); \ ++ else \ ++ (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ ++ if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ ++ DWC_CIRCLEQ_END(head)) \ ++ (head).cqh_first = (elm2); \ ++ else \ ++ (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ ++} while (0) ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_LIST_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc3/ep0.c b/drivers/usb/gadget/udc/hiudc3/ep0.c +new file mode 100644 +index 0000000..da09604 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/ep0.c +@@ -0,0 +1,1252 @@ ++/** @file ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++ ++#ifdef DWC_UTE ++#include "ute_if.h" ++#endif ++ ++/*=======================================================================*/ ++/* ++ * EP0 routines ++ */ ++ ++#if !defined(__linux__) || !defined(DWC_BOS_IN_GADGET) ++ ++/** The BOS Descriptor */ ++ ++static usb_dev_cap_20_ext_desc_t cap1_desc = { ++ sizeof(usb_dev_cap_20_ext_desc_t), /* bLength */ ++ UDESC_DEVICE_CAPABILITY, /* bDescriptorType */ ++ USB_DEVICE_CAPABILITY_20_EXTENSION, /* bDevCapabilityType */ ++ UCONSTDW(USB_20_EXT_LPM), /* bmAttributes */ ++}; ++ ++static usb_dev_cap_ss_usb_t cap2_desc = { ++ sizeof(usb_dev_cap_ss_usb_t), /* bLength */ ++ UDESC_DEVICE_CAPABILITY, /* bDescriptorType */ ++ USB_DEVICE_CAPABILITY_SS_USB, /* bDevCapabilityType */ ++ 0x0, /* bmAttributes */ ++ UCONSTW(USB_DC_SS_USB_SPEED_SUPPORT_SS /* wSpeedsSupported */ ++ | USB_DC_SS_USB_SPEED_SUPPORT_HIGH ++ | USB_DC_SS_USB_SPEED_SUPPORT_FULL), ++ USB_DC_SS_USB_SPEED_SUPPORT_FULL, /* bFunctionalitySupport */ ++ /* @todo set these to correct values */ ++ 10, /* bU1DevExitLat (10 us) */ ++ UCONSTW(256), /* wU2DevExitLat (256 us) */ ++}; ++ ++#ifdef DWC_OPTIONAL_UUID ++ /* The Denali host (and Win8) chokes on the optional container ID */ ++ ++static usb_dev_cap_container_id_t cap3_desc = { ++ sizeof(usb_dev_cap_container_id_t), /* bLength */ ++ UDESC_DEVICE_CAPABILITY, /* bDescriptorType */ ++ USB_DEVICE_CAPABILITY_CONTAINER_ID, /* bDevCapabilityType */ ++ 0, /* bReserved */ ++ /* @todo Create UUID */ ++ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, /* containerID */ ++}; ++#endif ++ ++static wusb_bos_desc_t bos_desc = { ++ sizeof(wusb_bos_desc_t), /* bLength */ ++ WUDESC_BOS, /* bDescriptorType */ ++ ++#ifdef DWC_OPTIONAL_UUID ++ UCONSTW(sizeof(wusb_bos_desc_t) /* wTotalLength */ ++ + sizeof(cap1_desc) + sizeof(cap2_desc) + sizeof(cap3_desc)), ++ 3, /* bNumDeviceCaps */ ++#else ++ UCONSTW(sizeof(wusb_bos_desc_t) /* wTotalLength */ ++ + sizeof(cap1_desc) + sizeof(cap2_desc)), ++ 2, /* bNumDeviceCaps */ ++#endif ++}; ++ ++#endif /* !__linux__ || ... */ ++ ++/** ++ * This routine starts the data stage of a 3-stage control command. ++ * pcd->ep0state must be set to EP0_OUT_DATA_PHASE or EP0_IN_DATA_PHASE, and ++ * pcd->ep0->dwc_ep.is_in must be set to 0 or 1 before calling this routine. ++ * For IN, the data to be sent must be placed in pcd->ep0_status_buf before ++ * the call. ++ */ ++void dwc_usb3_pcd_ep0_data_stage(dwc_usb3_pcd_t *pcd, int length) ++{ ++ pcd->ep0_req->dwc_req.buf[0] = (char *)pcd->ep0_status_buf; ++ pcd->ep0_req->dwc_req.bufdma[0] = pcd->ep0_status_buf_dma; ++ pcd->ep0_req->dwc_req.length = length; ++ pcd->ep0_req->dwc_req.actual = 0; ++ pcd->ep0_status_pending = 1; ++ pcd->ep0->dwc_ep.send_zlp = 0; ++ dwc_usb3_pcd_ep0_start_transfer(pcd, pcd->ep0_req); ++} ++ ++/** ++ * This routine processes the SET_ADDRESS Setup Commands. ++ */ ++static void do_set_address(dwc_usb3_pcd_t *pcd) ++{ ++ usb_device_request_t ctrl = pcd->ep0_setup_pkt->req; ++ ++ dwc_debug0(pcd->usb3_dev, "SET ADDRESS\n"); ++ ++ if (ctrl.bmRequestType == UT_DEVICE) { ++#ifdef DEBUG_EP0 ++ dwc_debug1(pcd->usb3_dev, "SET_ADDRESS %d\n", ++ UGETW(ctrl.wValue)); ++#endif ++ dwc_usb3_set_address(pcd, UGETW(ctrl.wValue)); ++ pcd->ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_WAIT_NRDY; ++ if (UGETW(ctrl.wValue)) ++ pcd->state = DWC_STATE_ADDRESSED; ++ else ++ pcd->state = DWC_STATE_DEFAULT; ++ } ++} ++ ++/** ++ * This routine stalls EP0. ++ */ ++static void ep0_do_stall(dwc_usb3_pcd_t *pcd, int err_val) ++{ ++ usb_device_request_t ctrl = pcd->ep0_setup_pkt->req; ++ dwc_usb3_pcd_ep_t *ep0 = pcd->ep0; ++ ++ dwc_print3(pcd->usb3_dev, "req %02x.%02x protocol STALL; err %d\n", ++ ctrl.bmRequestType, ctrl.bRequest, err_val); ++ ep0->dwc_ep.is_in = 0; ++ dwc_usb3_pcd_ep_set_stall(pcd, ep0); ++ ep0->dwc_ep.stopped = 1; ++ pcd->ep0state = EP0_IDLE; ++ dwc_usb3_pcd_ep0_out_start(pcd); ++} ++ ++/** ++ * Clear the EP halt (STALL), and if there are pending requests start ++ * the transfer. ++ */ ++static void do_clear_halt(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep) ++{ ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg; ++ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ ++ if (ep->dwc_ep.stall_clear_flag == 0) { ++ if (ep != pcd->ep0) ++ dwc_usb3_pcd_ep_clear_stall(pcd, ep); ++ ++ if (ep->dwc_ep.stopped) { ++ ep->dwc_ep.stopped = 0; ++ ++ /* If there is a request in the EP queue start it */ ++ if (ep != pcd->ep0 && ep->dwc_ep.is_in) ++ dwc_usb3_gadget_start_next_request(pcd, ep); ++ } ++ } else { ++ dwc_usb3_dis_usb2_suspend(pcd); ++ ++ /* Clear sequence number using DEPCFG */ ++ if (ep->dwc_ep.is_in) { ++ ep_reg = ep->dwc_ep.in_ep_reg; ++ dwc_usb3_dep_cfg(pcd, ep_reg, ep->dwc_ep.param0in, ++ ep->dwc_ep.param1in, 0); ++ } else { ++ ep_reg = ep->dwc_ep.out_ep_reg; ++ dwc_usb3_dep_cfg(pcd, ep_reg, ep->dwc_ep.param0out, ++ ep->dwc_ep.param1out, 0); ++ } ++ ++ dwc_usb3_ena_usb2_suspend(pcd); ++ } ++ ++ /* Start Control Status Phase */ ++ pcd->ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_WAIT_NRDY; ++} ++ ++/** ++ * This routine handles the Get Descriptor request for the BOS descriptor ++ * and the OTG descriptor, and passes all other requests to the Gadget driver. ++ */ ++static void do_get_descriptor(dwc_usb3_pcd_t *pcd) ++{ ++ usb_device_request_t ctrl = pcd->ep0_setup_pkt->req; ++ u8 desc_type = UGETW(ctrl.wValue) >> 8; ++ int ret; ++ ++#if defined(CONFIG_USB_OTG_DWC) || !defined(__linux__) || !defined(DWC_BOS_IN_GADGET) ++ u16 max = UGETW(ctrl.wLength); ++ u8 *buf = pcd->ep0_status_buf; ++ int length; ++#endif ++ ++#ifdef DEBUG_EP0 ++ dwc_debug5(pcd->usb3_dev, "GET_DESCRIPTOR %02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, UGETW(ctrl.wValue), ++ UGETW(ctrl.wIndex), UGETW(ctrl.wLength)); ++#endif ++ ++ switch (desc_type) { ++ ++#ifdef CONFIG_USB_OTG_DWC ++ case UDESC_OTG: ++ dwc_debug0(pcd->usb3_dev, "\nGET_DESCRIPTOR(OTG)\n\n"); ++ buf[0] = 5; ++ buf[1] = UDESC_OTG; ++ if (pcd->speed == USB_SPEED_SUPER) ++ buf[2] = 0xd; ++ else ++ buf[2] = 0x7; ++ ++ buf[3] = 0; ++ if (pcd->speed == USB_SPEED_SUPER) ++ buf[4] = 0x3; ++ else ++ buf[4] = 0x2; ++ ++ length = 5; ++ dwc_usb3_pcd_ep0_data_stage(pcd, length < max ? length : max); ++ break; ++#endif ++ ++ case UDESC_BOS: ++ dwc_debug0(pcd->usb3_dev, "\nGET_DESCRIPTOR(BOS)\n\n"); ++ if (pcd->speed != USB_SPEED_SUPER && ++ pcd->usb3_dev->core_params->nobos) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ++#if !defined(__linux__) || !defined(DWC_BOS_IN_GADGET) ++ memcpy(buf, &bos_desc, sizeof(bos_desc)); ++ buf += sizeof(bos_desc); ++ ++ if (pcd->usb3_dev->core_params->besl) { ++ u32 d = UGETDW(cap1_desc.bmAttributes); ++ ++ d |= USB_20_EXT_BESL | USB_20_EXT_BASELINE_BESL_VALID | ++ USB_20_EXT_DEEP_BESL_VALID; ++ d &= ~(USB_20_EXT_BASELINE_BESL_BITS | ++ USB_20_EXT_DEEP_BESL_BITS); ++ d |= pcd->usb3_dev->core_params->baseline_besl << ++ USB_20_EXT_BASELINE_BESL_SHIFT; ++ d |= pcd->usb3_dev->core_params->deep_besl << ++ USB_20_EXT_DEEP_BESL_SHIFT; ++ USETDW(cap1_desc.bmAttributes, d); ++ } ++ ++ if (pcd->usb3_dev->core_params->lpmctl == 0) ++ USETDW(cap1_desc.bmAttributes, 0); ++ ++ memcpy(buf, &cap1_desc, sizeof(cap1_desc)); ++ buf += sizeof(cap1_desc); ++ memcpy(buf, &cap2_desc, sizeof(cap2_desc)); ++ ++#ifdef DWC_OPTIONAL_UUID ++ buf += sizeof(cap2_desc); ++ memcpy(buf, &cap3_desc, sizeof(cap3_desc)); ++#endif ++ length = UGETW(bos_desc.wTotalLength); ++ dwc_usb3_pcd_ep0_data_stage(pcd, length < max ? length : max); ++ break; ++#else ++ /* FALL THROUGH */ ++#endif ++ ++ default: ++ /* Call the Gadget driver's setup routine */ ++ ret = dwc_usb3_gadget_setup(pcd, &ctrl); ++ if (ret < 0) ++ ep0_do_stall(pcd, ret); ++ break; ++ } ++} ++ ++/** ++ * This routine processes the GET_STATUS Setup Commands. ++ */ ++static void do_get_status(dwc_usb3_pcd_t *pcd) ++{ ++ usb_device_request_t ctrl = pcd->ep0_setup_pkt->req; ++ u8 *status = pcd->ep0_status_buf; ++ dwc_usb3_pcd_ep_t *ep; ++ int length; ++ ++#ifdef DEBUG_EP0 ++ dwc_debug5(pcd->usb3_dev, "GET_STATUS %02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, UGETW(ctrl.wValue), ++ UGETW(ctrl.wIndex), UGETW(ctrl.wLength)); ++#endif ++ ++ if (UGETW(ctrl.wLength) != 2 ++#ifdef CONFIG_USB_OTG_DWC ++ && UGETW(ctrl.wIndex) != 0xf000 ++#endif ++ ) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ++ switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { ++ case UT_DEVICE: ++#ifdef CONFIG_USB_OTG_DWC ++ /* HNP Polling */ ++ if (UGETW(ctrl.wIndex) == 0xf000) ++ *status = pcd->wants_host ? 1 : 0; ++ else ++#endif ++ { ++ *status = 1; /* Self powered */ ++ ++ if (pcd->speed == USB_SPEED_SUPER) { ++ if (pcd->state == DWC_STATE_CONFIGURED) { ++ if (dwc_usb3_u1_enabled(pcd)) ++ *status |= 1 << 2; ++ ++ if (dwc_usb3_u2_enabled(pcd)) ++ *status |= 1 << 3; ++ ++ *status |= pcd->ltm_enable << 4; ++ } ++ } else { ++ *status |= pcd->remote_wakeup_enable << 1; ++ } ++ } ++ ++ dwc_debug1(pcd->usb3_dev, "GET_STATUS(Device)=%02x\n", *status); ++ *(status + 1) = 0; ++ break; ++ ++ case UT_INTERFACE: ++ *status = 0; ++ if (pcd->usb3_dev->core_params->wakeup) ++ *status |= 1; ++ *status |= pcd->remote_wakeup_enable << 1; ++ dwc_debug2(pcd->usb3_dev, "GET_STATUS(Interface %d)=%02x\n", ++ UGETW(ctrl.wIndex), *status); ++ *(status + 1) = 0; ++ break; ++ ++ case UT_ENDPOINT: ++ ep = dwc_usb3_pcd_get_ep_by_addr(pcd, UGETW(ctrl.wIndex)); ++ ++ /* @todo check for EP stall */ ++ *status = ep->dwc_ep.stopped; ++ dwc_debug2(pcd->usb3_dev, "GET_STATUS(Endpoint %d)=%02x\n", ++ UGETW(ctrl.wIndex), *status); ++ *(status + 1) = 0; ++ break; ++ ++ default: ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ++#ifdef CONFIG_USB_OTG_DWC ++ if (UGETW(ctrl.wIndex) == 0xf000) ++ length = 1; ++ else ++#endif ++ length = 2; ++ dwc_usb3_pcd_ep0_data_stage(pcd, length); ++} ++ ++/** ++ * This routine processes the SET_FEATURE Setup Commands. ++ */ ++static void do_set_feature(dwc_usb3_pcd_t *pcd) ++{ ++ usb_device_request_t ctrl = pcd->ep0_setup_pkt->req; ++ dwc_usb3_pcd_ep_t *ep; ++ int ret; ++ ++#ifdef DEBUG_EP0 ++ dwc_debug5(pcd->usb3_dev, "SET_FEATURE %02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, UGETW(ctrl.wValue), ++ UGETW(ctrl.wIndex), UGETW(ctrl.wLength)); ++#endif ++ ++ switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { ++ case UT_DEVICE: ++ switch (UGETW(ctrl.wValue)) { ++ case UF_DEVICE_REMOTE_WAKEUP: ++ pcd->remote_wakeup_enable = 1; ++ break; ++ ++ case UF_TEST_MODE: ++ /* Setup the Test Mode tasklet to do the Test ++ * Packet generation after the SETUP Status ++ * phase has completed. */ ++ pcd->test_mode = UGETW(ctrl.wIndex) >> 8; ++ dwc_usb3_task_schedule(&pcd->test_mode_tasklet); ++ break; ++ ++ case UF_DEVICE_B_HNP_ENABLE: ++ dwc_debug0(pcd->usb3_dev, ++ "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n"); ++#ifdef CONFIG_USB_OTG_DWC ++ if (pcd->wants_host) { ++ pcd->b_hnp_enable = 0; ++ pcd->wants_host = 0; ++ dwc_usb3_start_hnp(pcd); ++ } else { ++ pcd->b_hnp_enable = 1; ++ } ++#endif ++ break; ++ ++ case UOTG_NTF_HOST_REL: ++ dwc_debug0(pcd->usb3_dev, ++ "SET_FEATURE: USB_NTF_HOST_REL\n"); ++#ifdef CONFIG_USB_OTG_DWC ++ dwc_usb3_host_release(pcd); ++#endif ++ break; ++ ++ case UOTG_B3_RSP_ENABLE: ++ dwc_debug0(pcd->usb3_dev, ++ "SET_FEATURE: USB_B3_RSP_ENABLE\n"); ++ break; ++ ++ case UF_DEVICE_A_HNP_SUPPORT: ++ /* RH port supports HNP */ ++ dwc_debug0(pcd->usb3_dev, ++ "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n"); ++ break; ++ ++ case UF_DEVICE_A_ALT_HNP_SUPPORT: ++ /* other RH port does */ ++ dwc_debug0(pcd->usb3_dev, ++ "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n"); ++ break; ++ ++ case UF_U1_ENABLE: ++ dwc_debug0(pcd->usb3_dev, "SET_FEATURE: UF_U1_ENABLE\n"); ++ if (pcd->speed != USB_SPEED_SUPER || ++ pcd->state != DWC_STATE_CONFIGURED) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ++ if (pcd->usb3_dev->core_params->pwrctl & 1) ++ dwc_usb3_enable_u1(pcd); ++ break; ++ ++ case UF_U2_ENABLE: ++ dwc_debug0(pcd->usb3_dev, "SET_FEATURE: UF_U2_ENABLE\n"); ++ if (pcd->speed != USB_SPEED_SUPER || ++ pcd->state != DWC_STATE_CONFIGURED) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ++ if (pcd->usb3_dev->core_params->pwrctl & 2) ++ dwc_usb3_enable_u2(pcd); ++ break; ++ ++ case UF_LTM_ENABLE: ++ dwc_debug0(pcd->usb3_dev, ++ "SET_FEATURE: UF_LTM_ENABLE\n"); ++ if (pcd->speed != USB_SPEED_SUPER || ++ pcd->state != DWC_STATE_CONFIGURED || ++ UGETW(ctrl.wIndex) != 0) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ++ pcd->ltm_enable = 1; ++ pcd->send_lpm = 1; ++ break; ++ ++ default: ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ++ break; ++ ++ case UT_INTERFACE: ++ /* if FUNCTION_SUSPEND ... */ ++ if (UGETW(ctrl.wValue) == 0) { ++ /* if Function Remote Wake Enabled ... */ ++ if (UGETW(ctrl.wIndex) >> 8 & 2) ++ pcd->remote_wakeup_enable = 1; ++ else ++ pcd->remote_wakeup_enable = 0; ++ ++ /* if Function Low Power Suspend ... */ ++ // TODO ++ ++ break; ++ } ++ ++ ret = dwc_usb3_gadget_setup(pcd, &ctrl); ++ if (ret < 0) ++ ep0_do_stall(pcd, ret); ++ return; ++ ++ case UT_ENDPOINT: ++ ep = dwc_usb3_pcd_get_ep_by_addr(pcd, UGETW(ctrl.wIndex)); ++ if (UGETW(ctrl.wValue) != UF_ENDPOINT_HALT) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ++ ep->dwc_ep.stopped = 1; ++ dwc_usb3_pcd_ep_set_stall(pcd, ep); ++ break; ++ } ++ ++ pcd->ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_WAIT_NRDY; ++} ++ ++/** ++ * This routine processes the CLEAR_FEATURE Setup Commands. ++ */ ++static void do_clear_feature(dwc_usb3_pcd_t *pcd) ++{ ++ usb_device_request_t ctrl = pcd->ep0_setup_pkt->req; ++ dwc_usb3_pcd_ep_t *ep; ++ ++#ifdef DEBUG_EP0 ++ dwc_debug5(pcd->usb3_dev, "CLEAR_FEATURE %02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, UGETW(ctrl.wValue), ++ UGETW(ctrl.wIndex), UGETW(ctrl.wLength)); ++#endif ++ ++ switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { ++ case UT_DEVICE: ++ switch (UGETW(ctrl.wValue)) { ++ case UF_DEVICE_REMOTE_WAKEUP: ++ pcd->remote_wakeup_enable = 0; ++ break; ++ ++ case UF_TEST_MODE: ++ /* @todo Add CLEAR_FEATURE for TEST modes. */ ++ break; ++ ++ case UF_U1_ENABLE: ++ dwc_debug0(pcd->usb3_dev, ++ "CLEAR_FEATURE: UF_U1_ENABLE\n"); ++ if (pcd->speed != USB_SPEED_SUPER || ++ pcd->state != DWC_STATE_CONFIGURED) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ++ dwc_usb3_disable_u1(pcd); ++ break; ++ ++ case UF_U2_ENABLE: ++ dwc_debug0(pcd->usb3_dev, ++ "CLEAR_FEATURE: UF_U2_ENABLE\n"); ++ if (pcd->speed != USB_SPEED_SUPER || ++ pcd->state != DWC_STATE_CONFIGURED) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ++ dwc_usb3_disable_u2(pcd); ++ break; ++ ++ case UF_LTM_ENABLE: ++ dwc_debug0(pcd->usb3_dev, ++ "CLEAR_FEATURE: UF_LTM_ENABLE\n"); ++ if (pcd->speed != USB_SPEED_SUPER || ++ pcd->state != DWC_STATE_CONFIGURED || ++ UGETW(ctrl.wIndex) != 0) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ++ pcd->ltm_enable = 0; ++ pcd->send_lpm = 1; ++ break; ++ ++ default: ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ++ break; ++ ++ case UT_INTERFACE: ++ /* if FUNCTION_SUSPEND ... */ ++ if (UGETW(ctrl.wValue) == 0) { ++ /* if Function Remote Wake Enabled ... */ ++ if (UGETW(ctrl.wIndex) >> 8 & 2) { ++ pcd->remote_wakeup_enable = 0; ++ } ++ ++ /* if Function Low Power Suspend ... */ ++ // TODO ++ ++ break; ++ } ++ ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ ++ case UT_ENDPOINT: ++ ep = dwc_usb3_pcd_get_ep_by_addr(pcd, UGETW(ctrl.wIndex)); ++ if (UGETW(ctrl.wValue) != UF_ENDPOINT_HALT) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ++ do_clear_halt(pcd, ep); ++ return; ++ } ++ ++ pcd->ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_WAIT_NRDY; ++} ++ ++/** ++ * This routine processes SETUP commands. The USB Command processing is ++ * done in two places - the first being the PCD and the second being the ++ * Gadget driver (for example, the File-Backed Storage Gadget driver). ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ *
Command Driver Description
GET_STATUS PCD Command is processed ++ * as defined in chapter 9 of the USB 2.0 Specification.
SET_FEATURE PCD / Gadget driver Device ++ * and Endpoint requests are processed by the PCD. Interface requests ++ * are passed to the Gadget driver.
CLEAR_FEATURE PCD Device and Endpoint ++ * requests are processed by the PCD. Interface requests are ignored. ++ * The only Endpoint feature handled is ENDPOINT_HALT.
SET_ADDRESS PCD Program the DCFG register ++ * with device address received.
GET_DESCRIPTOR Gadget driver Return the ++ * requested descriptor.
SET_DESCRIPTOR Gadget driver Optional - ++ * not implemented by any of the existing Gadget drivers.
GET_CONFIGURATION Gadget driver Return ++ * the current configuration.
SET_CONFIGURATION Gadget driver Disable ++ * all EPs and enable EPs for new configuration.
GET_INTERFACE Gadget driver Return the ++ * current interface.
SET_INTERFACE Gadget driver Disable all ++ * EPs and enable EPs for new interface.
++ * ++ * When the SETUP Phase Done interrupt occurs, the generic SETUP commands ++ * are processed by this routine. Calling the Gadget driver's ++ * dwc_usb3_gadget_setup() routine from here processes the gadget-specific ++ * SETUP commands. ++ */ ++void dwc_usb3_pcd_do_setup(dwc_usb3_pcd_t *pcd) ++{ ++ usb_device_request_t ctrl = pcd->ep0_setup_pkt->req; ++ dwc_usb3_pcd_ep_t *ep0 = pcd->ep0; ++ u16 wvalue, wlength; ++ int ret; ++ ++ dwc_debug2(pcd->usb3_dev, "%s(%lx)\n", __func__, (unsigned long)pcd); ++ wvalue = UGETW(ctrl.wValue); ++ wlength = UGETW(ctrl.wLength); ++#if 0 ++#ifdef DEBUG_EP0 ++ dwc_debug0(pcd->usb3_dev, "\n"); ++ dwc_print1(pcd->usb3_dev, "setup_pkt[0]=0x%08x\n", ++ pcd->ep0_setup_pkt->d32[0]); ++ dwc_print1(pcd->usb3_dev, "setup_pkt[1]=0x%08x\n", ++ pcd->ep0_setup_pkt->d32[1]); ++ dwc_print5(pcd->usb3_dev, "SETUP %02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, wvalue, ++ UGETW(ctrl.wIndex), wlength); ++ dwc_debug0(pcd->usb3_dev, "\n"); ++#endif ++#endif ++ /* Clean up the request queue */ ++ dwc_usb3_gadget_request_nuke(pcd, ep0); ++ ep0->dwc_ep.stopped = 0; ++ ep0->dwc_ep.three_stage = 1; ++ ++ if (ctrl.bmRequestType & UE_DIR_IN) { ++ ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_DATA_PHASE; ++ } else { ++ ep0->dwc_ep.is_in = 0; ++ pcd->ep0state = EP0_OUT_DATA_PHASE; ++ } ++ ++ if (wlength == 0) { ++ ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_WAIT_GADGET; ++ ep0->dwc_ep.three_stage = 0; ++ } ++ ++ if ((UT_GET_TYPE(ctrl.bmRequestType)) != UT_STANDARD) { ++ /* handle non-standard (class/vendor) requests ++ * in the gadget driver ++ */ ++ ret = dwc_usb3_gadget_setup(pcd, &ctrl); ++ if (ret < 0) ++ ep0_do_stall(pcd, ret); ++ return; ++ } ++ ++ /* @todo NGS: Handle bad setup packet? */ ++ ++/////////////////////////////////////////// ++//// --- Standard Request handling --- //// ++ ++ switch (ctrl.bRequest) { ++ case UR_GET_STATUS: ++ do_get_status(pcd); ++ break; ++ ++ case UR_CLEAR_FEATURE: ++ do_clear_feature(pcd); ++ break; ++ ++ case UR_SET_FEATURE: ++ do_set_feature(pcd); ++ break; ++ ++ case UR_SET_ADDRESS: ++ do_set_address(pcd); ++ break; ++ ++ case UR_SET_INTERFACE: ++ dwc_debug0(pcd->usb3_dev, "USB_REQ_SET_INTERFACE\n"); ++#ifndef DWC_UTE ++ dwc_usb3_clr_eps_enabled(pcd); ++ ++# ifdef DWC_STAR_9000463548_WORKAROUND ++ pcd->configuring = 1; ++# endif ++#endif ++ ret = dwc_usb3_gadget_setup(pcd, &ctrl); ++ if (ret < 0) { ++#ifndef DWC_UTE ++# ifdef DWC_STAR_9000463548_WORKAROUND ++ pcd->configuring = 0; ++# endif ++#endif ++ ep0_do_stall(pcd, ret); ++ return; ++ } ++ ++ break; ++ ++ case UR_SET_CONFIG: ++ dwc_debug0(pcd->usb3_dev, "USB_REQ_SET_CONFIGURATION\n"); ++#ifdef DWC_UTE ++ if (wvalue != 0) ++ dwc_usb3_ute_config(pcd->usb3_dev); ++#endif ++ dwc_usb3_clr_eps_enabled(pcd); ++ ++#ifdef DWC_STAR_9000463548_WORKAROUND ++ pcd->configuring = 1; ++#endif ++ if (pcd->ltm_enable) ++ pcd->send_lpm = 1; ++ ++ ret = dwc_usb3_gadget_setup(pcd, &ctrl); ++ if (ret >= 0) { ++ if (wvalue != 0) ++ pcd->state = DWC_STATE_CONFIGURED; ++ else ++ pcd->state = DWC_STATE_ADDRESSED; ++ } else { ++ ep0_do_stall(pcd, ret); ++#ifdef DWC_STAR_9000463548_WORKAROUND ++ pcd->configuring = 0; ++#endif ++ return; ++ } ++ ++ /* Must wait until SetConfig before accepting U1/U2 link ++ * control, otherwise we have problems with VIA hubs ++ */ ++ if (pcd->usb3_dev->core_params->pwrctl & 1) ++ dwc_usb3_accept_u1(pcd); ++ if (pcd->usb3_dev->core_params->pwrctl & 2) ++ dwc_usb3_accept_u2(pcd); ++ ++ pcd->ltm_enable = 0; ++ break; ++ ++ case UR_GET_DESCRIPTOR: ++ do_get_descriptor(pcd); ++ break; ++ ++ case UR_SET_SEL: ++ dwc_debug0(pcd->usb3_dev, "USB_REQ_SET_SEL\n"); ++ ++ /* For now this is a no-op */ ++ dwc_usb3_pcd_ep0_data_stage(pcd, DWC_STATUS_BUF_SIZE < wlength ? ++ DWC_STATUS_BUF_SIZE : wlength); ++ break; ++ ++ case UR_SET_ISOC_DELAY: ++ dwc_debug0(pcd->usb3_dev, "USB_REQ_SET_ISOC_DELAY\n"); ++ ++ /* For now this is a no-op */ ++ pcd->ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_WAIT_NRDY; ++ break; ++ ++ default: ++ /* Call the Gadget driver's setup routine */ ++ ret = dwc_usb3_gadget_setup(pcd, &ctrl); ++ if (ret < 0) ++ ep0_do_stall(pcd, ret); ++ break; ++ } ++} ++ ++/** ++ * This routine starts the Zero-Length Packet for the IN status phase of a ++ * control write transfer. ++ */ ++static void setup_in_status_phase(dwc_usb3_pcd_t *pcd, void *buf, ++ dwc_dma_t dma) ++{ ++ dwc_usb3_pcd_ep_t *ep0 = pcd->ep0; ++ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ ++ if (pcd->ep0state == EP0_STALL) { ++ dwc_debug0(pcd->usb3_dev, "EP0 STALLED\n"); ++ return; ++ } ++ ++ ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_STATUS_PHASE; ++ ++ dwc_debug0(pcd->usb3_dev, "EP0 IN ZLP\n"); ++ ++ pcd->ep0_req->dwc_req.buf[0] = buf; ++ pcd->ep0_req->dwc_req.bufdma[0] = dma; ++ pcd->ep0_req->dwc_req.length = 0; ++ pcd->ep0_req->dwc_req.actual = 0; ++ dwc_usb3_pcd_ep0_start_transfer(pcd, pcd->ep0_req); ++} ++ ++/** ++ * This routine starts the Zero-Length Packet for the OUT status phase of a ++ * control read transfer. ++ */ ++static void setup_out_status_phase(dwc_usb3_pcd_t *pcd, void *buf, ++ dwc_dma_t dma) ++{ ++ dwc_usb3_pcd_ep_t *ep0 = pcd->ep0; ++ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ ++ if (pcd->ep0state == EP0_STALL) { ++ dwc_debug0(pcd->usb3_dev, "EP0 STALLED\n"); ++ return; ++ } ++ ++ ep0->dwc_ep.is_in = 0; ++ pcd->ep0state = EP0_OUT_STATUS_PHASE; ++ ++ dwc_debug0(pcd->usb3_dev, "EP0 OUT ZLP\n"); ++ ++ pcd->ep0_req->dwc_req.buf[0] = buf; ++ pcd->ep0_req->dwc_req.bufdma[0] = dma; ++ pcd->ep0_req->dwc_req.length = 0; ++ pcd->ep0_req->dwc_req.actual = 0; ++ dwc_usb3_pcd_ep0_start_transfer(pcd, pcd->ep0_req); ++} ++ ++#ifdef DEBUG_EP0 ++/** ++ * This routine prints the ep0 state for debug purposes. ++ */ ++void dwc_usb3_print_ep0_state(dwc_usb3_pcd_t *pcd) ++{ ++#ifdef DEBUG ++ char *str; ++ ++ switch (pcd->ep0state) { ++ case EP0_IDLE: ++ str = "EP0_IDLE"; ++ break; ++ case EP0_IN_DATA_PHASE: ++ str = "EP0_IN_DATA_PHASE"; ++ break; ++ case EP0_OUT_DATA_PHASE: ++ str = "EP0_OUT_DATA_PHASE"; ++ break; ++ case EP0_IN_WAIT_GADGET: ++ str = "EP0_IN_WAIT_GADGET"; ++ break; ++ case EP0_OUT_WAIT_GADGET: ++ str = "EP0_OUT_WAIT_GADGET"; ++ break; ++ case EP0_IN_WAIT_NRDY: ++ str = "EP0_IN_WAIT_NRDY"; ++ break; ++ case EP0_OUT_WAIT_NRDY: ++ str = "EP0_OUT_WAIT_NRDY"; ++ break; ++ case EP0_IN_STATUS_PHASE: ++ str = "EP0_IN_STATUS_PHASE"; ++ break; ++ case EP0_OUT_STATUS_PHASE: ++ str = "EP0_OUT_STATUS_PHASE"; ++ break; ++ case EP0_STALL: ++ str = "EP0_STALL"; ++ break; ++ default: ++ str = "EP0_INVALID"; ++ } ++ ++ dwc_debug2(pcd->usb3_dev, "%s(%d)\n", str, pcd->ep0state); ++#endif ++} ++#endif ++ ++/** ++ * This routine completes the ep0 control transfer. ++ */ ++static int ep0_complete_request(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_req_t *req, ++ dwc_usb3_dma_desc_t *desc, int status) ++{ ++ dwc_usb3_pcd_ep_t *ep = pcd->ep0; ++ int is_last = 0; ++ ++ dwc_debug4(pcd->usb3_dev, "%s(%lx,%lx,%d)\n", __func__, ++ (unsigned long)req, (unsigned long)desc, status); ++ ++ if (pcd->ep0_status_pending && !req) { ++ if (ep->dwc_ep.is_in) { ++#ifdef DEBUG_EP0 ++ dwc_debug0(pcd->usb3_dev, ++ "Do setup OUT status phase\n"); ++#endif ++ pcd->ep0->dwc_ep.is_in = 0; ++ pcd->ep0state = EP0_OUT_WAIT_NRDY; ++ } else { ++#ifdef DEBUG_EP0 ++ dwc_debug0(pcd->usb3_dev, "Do setup IN status phase\n"); ++#endif ++ pcd->ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_WAIT_NRDY; ++ } ++ ++ pcd->ep0_status_pending = 0; ++ return 1; ++ } ++ ++ if (!req) ++ return 0; ++ ++ dwc_debug1(pcd->usb3_dev, "req=%lx\n", (unsigned long)req); ++ ++ if (pcd->ep0state == EP0_OUT_STATUS_PHASE || ++ pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ is_last = 1; ++ ++ } else if (ep->dwc_ep.is_in) { ++#ifdef DEBUG_EP0 ++ dwc_debug4(pcd->usb3_dev, ++ "IN len=%d actual=%d xfrcnt=%d trbrsp=0x%02x\n", ++ req->dwc_req.length, req->dwc_req.actual, ++ dwc_usb3_get_xfercnt(desc), ++ dwc_usb3_get_xfersts(desc)); ++#endif ++ if (dwc_usb3_get_xfercnt(desc) == 0) { ++ /* Is a Zero Len Packet needed? */ ++ if (req->dwc_req.flags & DWC_PCD_REQ_ZERO) { ++#ifdef DEBUG_EP0 ++ dwc_debug0(pcd->usb3_dev, "Setup Rx ZLP\n"); ++#endif ++ req->dwc_req.flags &= ~DWC_PCD_REQ_ZERO; ++ } ++ ++ pcd->ep0->dwc_ep.is_in = 0; ++ pcd->ep0state = EP0_OUT_WAIT_NRDY; ++ } ++ } else { ++#ifdef DEBUG_EP0 ++ dwc_debug4(pcd->usb3_dev, ++ "OUT len=%d actual=%d xfrcnt=%d trbrsp=0x%02x\n", ++ req->dwc_req.length, req->dwc_req.actual, ++ dwc_usb3_get_xfercnt(desc), ++ dwc_usb3_get_xfersts(desc)); ++#endif ++ /* Is a Zero Len Packet needed? */ ++ if (req->dwc_req.flags & DWC_PCD_REQ_ZERO) { ++#ifdef DEBUG_EP0 ++ dwc_debug0(pcd->usb3_dev, "Setup Tx ZLP\n"); ++#endif ++ req->dwc_req.flags &= ~DWC_PCD_REQ_ZERO; ++ } ++ ++ pcd->ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_WAIT_NRDY; ++ } ++ ++ /* Complete the request */ ++ if (is_last) { ++ dwc_debug2(pcd->usb3_dev, "is_last len=%d actual=%d\n", ++ req->dwc_req.length, req->dwc_req.actual); ++ dwc_usb3_pcd_request_done(pcd, ep, req, status); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++/** ++ * This routine handles EP0 Control transfers. ++ * ++ * The state of the control tranfers are tracked in ep0state. ++ */ ++static void dwc_usb3_handle_ep0(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_req_t *req, ++ u32 event) ++{ ++ dwc_usb3_pcd_ep_t *ep0 = pcd->ep0; ++ dwc_usb3_dma_desc_t *desc; ++ u32 byte_count, len; ++ int status; ++ ++#ifdef DEBUG_EP0 ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ dwc_usb3_print_ep0_state(pcd); ++#endif ++ dwc_debug0(pcd->usb3_dev, "HANDLE EP0\n"); ++ ++ switch (pcd->ep0state) { ++ case EP0_IN_DATA_PHASE: ++ if (!req) ++ req = pcd->ep0_req; ++ desc = dwc_usb3_ep0_in_desc(pcd); ++ dwc_debug1(pcd->usb3_dev, "req=%lx\n", (unsigned long)req); ++#ifdef DEBUG_EP0 ++ dwc_debug5(pcd->usb3_dev, ++ "DATA_IN EP%d-%s: type=%d mps=%d trb.status=0x%08x\n", ++ ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"), ++ ep0->dwc_ep.type, ep0->dwc_ep.maxpacket, desc->status); ++#endif ++ if (dwc_usb3_is_hwo(desc)) { ++ dwc_print3(pcd->usb3_dev, ++ "### %s, EP%d-%s HWO bit set 1! ###\n", ++ __func__, ep0->dwc_ep.num, ep0->dwc_ep.is_in ? ++ "IN" : "OUT"); ++ goto out; ++ } ++ ++ status = dwc_usb3_get_xfersts(desc); ++ if (status & DWC_TRBRSP_SETUP_PEND) { ++ /* Start of a new Control transfer */ ++ dwc_debug0(pcd->usb3_dev, "IN SETUP PENDING\n"); ++ desc->status = 0; ++ } ++ ++ byte_count = req->dwc_req.length - dwc_usb3_get_xfercnt(desc); ++ req->dwc_req.actual += byte_count; ++ req->dwc_req.buf[0] += byte_count; ++ req->dwc_req.bufdma[0] += byte_count; ++ dwc_debug3(pcd->usb3_dev, "length=%d byte_count=%d actual=%d\n", ++ req->dwc_req.length, byte_count, req->dwc_req.actual); ++ ++ if (req->dwc_req.actual < req->dwc_req.length) { ++#ifdef DEBUG_EP0 ++ dwc_usb3_dump_dbgregs(pcd->usb3_dev); ++#endif ++ dwc_debug0(pcd->usb3_dev, "IN CONTINUE\n"); ++ //dwc_usb3_pcd_ep0_continue_transfer(pcd, req); ++ //dwc_debug0(pcd->usb3_dev, "CONTINUE TRANSFER\n"); ++ dwc_debug0(pcd->usb3_dev, "Stall EP0\n"); ++ ep0->dwc_ep.is_in = 0; ++ dwc_usb3_pcd_ep_set_stall(pcd, ep0); ++ ep0->dwc_ep.stopped = 1; ++ pcd->ep0state = EP0_IDLE; ++ dwc_usb3_pcd_ep0_out_start(pcd); ++ ++ } else if (ep0->dwc_ep.send_zlp) { ++ dwc_debug0(pcd->usb3_dev, "IN ZLP\n"); ++ dwc_usb3_pcd_ep0_continue_transfer(pcd, req); ++ ep0->dwc_ep.send_zlp = 0; ++ dwc_debug0(pcd->usb3_dev, "CONTINUE TRANSFER\n"); ++ ++ } else { ++ dwc_debug0(pcd->usb3_dev, "IN COMPLETE\n"); ++ /* This sets ep0state = EP0_IN/OUT_WAIT_NRDY */ ++ ep0_complete_request(pcd, req, desc, 0); ++ dwc_debug0(pcd->usb3_dev, "COMPLETE TRANSFER\n"); ++ } ++ ++ break; ++ ++ case EP0_OUT_DATA_PHASE: ++ if (!req) ++ req = pcd->ep0_req; ++ desc = dwc_usb3_ep0_out_desc(pcd); ++ dwc_debug1(pcd->usb3_dev, "req=%lx\n", (unsigned long)req); ++#ifdef DEBUG_EP0 ++ dwc_debug5(pcd->usb3_dev, ++ "DATA_OUT EP%d-%s: type=%d mps=%d trb.status=0x%08x\n", ++ ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"), ++ ep0->dwc_ep.type, ep0->dwc_ep.maxpacket, desc->status); ++#endif ++ if (dwc_usb3_is_hwo(desc)) { ++ dwc_print3(pcd->usb3_dev, ++ "### %s, EP%d-%s HWO bit set 2! ###\n", ++ __func__, ep0->dwc_ep.num, ep0->dwc_ep.is_in ? ++ "IN" : "OUT"); ++ goto out; ++ } ++ ++ status = dwc_usb3_get_xfersts(desc); ++ if (status & DWC_TRBRSP_SETUP_PEND) { ++ /* Start of a new Control transfer */ ++ dwc_debug0(pcd->usb3_dev, "OUT SETUP PENDING\n"); ++ } ++ ++ len = (req->dwc_req.length + ep0->dwc_ep.maxpacket - 1) & ++ ~(ep0->dwc_ep.maxpacket - 1); ++ byte_count = len - dwc_usb3_get_xfercnt(desc); ++ req->dwc_req.actual += byte_count; ++ req->dwc_req.buf[0] += byte_count; ++ req->dwc_req.bufdma[0] += byte_count; ++ dwc_debug3(pcd->usb3_dev, "length=%d byte_count=%d actual=%d\n", ++ req->dwc_req.length, byte_count, req->dwc_req.actual); ++ ++ /*if (req->dwc_req.actual < req->dwc_req.length) { ++ dwc_debug0(pcd->usb3_dev, "OUT CONTINUE\n"); ++ dwc_usb3_pcd_ep0_continue_transfer(pcd, req); ++ dwc_debug0(pcd->usb3_dev, "CONTINUE TRANSFER\n"); ++ ++ } else*/ if (ep0->dwc_ep.send_zlp) { ++ dwc_debug0(pcd->usb3_dev, "OUT ZLP\n"); ++ dwc_usb3_pcd_ep0_continue_transfer(pcd, req); ++ ep0->dwc_ep.send_zlp = 0; ++ dwc_debug0(pcd->usb3_dev, "CONTINUE TRANSFER\n"); ++ ++ } else { ++ dwc_debug0(pcd->usb3_dev, "OUT COMPLETE\n"); ++ /* This sets ep0state = EP0_IN/OUT_WAIT_NRDY */ ++ ep0_complete_request(pcd, req, desc, 0); ++ dwc_debug0(pcd->usb3_dev, "COMPLETE TRANSFER\n"); ++ } ++ ++ break; ++ ++ case EP0_IN_WAIT_GADGET: ++ pcd->ep0state = EP0_IN_WAIT_NRDY; ++ break; ++ ++ case EP0_OUT_WAIT_GADGET: ++ pcd->ep0state = EP0_OUT_WAIT_NRDY; ++ break; ++ ++ case EP0_IN_WAIT_NRDY: ++ case EP0_OUT_WAIT_NRDY: ++ if (ep0->dwc_ep.is_in) ++ setup_in_status_phase(pcd, dwc_usb3_ep0_setup_pkt(pcd), ++ dwc_usb3_ep0_setup_pkt_dma(pcd)); ++ else ++ setup_out_status_phase(pcd, dwc_usb3_ep0_setup_pkt(pcd), ++ dwc_usb3_ep0_setup_pkt_dma(pcd)); ++ break; ++ ++ case EP0_IN_STATUS_PHASE: ++ case EP0_OUT_STATUS_PHASE: ++ if (ep0->dwc_ep.is_in) ++ desc = dwc_usb3_ep0_in_desc(pcd); ++ else ++ desc = dwc_usb3_ep0_out_desc(pcd); ++#ifdef DEBUG_EP0 ++ dwc_debug2(pcd->usb3_dev, "STATUS EP%d-%s\n", ep0->dwc_ep.num, ++ (ep0->dwc_ep.is_in ? "IN" : "OUT")); ++#endif ++ ep0_complete_request(pcd, req, desc, 0); ++ pcd->ep0state = EP0_IDLE; ++ ep0->dwc_ep.stopped = 1; ++ ep0->dwc_ep.is_in = 0; /* OUT for next SETUP */ ++ ++ if (pcd->send_lpm) { ++ pcd->send_lpm = 0; ++ ++#if 0 // This is only for testing ++ dwc_usb3_xmit_ltm(pcd, ++ 32 << DWC_DGCMDPAR_BELT_VALUE_SHIFT | ++ DWC_LATENCY_VALUE_MULT_32768 << ++ DWC_DGCMDPAR_BELT_SCALE_SHIFT); ++#endif ++ } ++ ++ /* Prepare for more SETUP Packets */ ++ dwc_usb3_pcd_ep0_out_start(pcd); ++ break; ++ ++ case EP0_STALL: ++ dwc_error0(pcd->usb3_dev, "EP0 STALLed, should not get here\n"); ++ break; ++ ++ case EP0_IDLE: ++ dwc_error0(pcd->usb3_dev, "EP0 IDLE, should not get here\n"); ++ break; ++ } ++out: ++#ifdef DEBUG_EP0 ++ dwc_usb3_print_ep0_state(pcd); ++#endif ++ return; ++} ++ ++/** ++ * This routine handles EP0 transfers. ++ * ++ * This routine gets the request corresponding to the current EP0 transfer. If ++ * EP0 is in IDLE state, it calls dwc_usb3_do_setup() to begin processing ++ * the next Setup request, otherwise it calls dwc_usb3_handle_ep0() to handle ++ * the next stage of the current transfer. ++ */ ++void dwc_usb3_handle_ep0_xfer(dwc_usb3_pcd_t *pcd, u32 event) ++{ ++ dwc_usb3_pcd_ep_t *ep0 = pcd->ep0; ++ dwc_usb3_pcd_req_t *req = NULL; ++ ++#ifdef DEBUG_EP0 ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++#endif ++ req = dwc_usb3_gadget_get_request(pcd, ep0); ++ ++ if (pcd->ep0state == EP0_IDLE) { ++#ifdef DEBUG_EP0 ++ dwc_usb3_print_ep0_state(pcd); ++ dwc_debug2(pcd->usb3_dev, "IDLE EP%d-%s\n", ep0->dwc_ep.num, ++ (ep0->dwc_ep.is_in ? "IN" : "OUT")); ++#endif ++ pcd->request_config = 0; ++ dwc_usb3_gadget_do_setup(pcd); ++ } else { ++ dwc_usb3_handle_ep0(pcd, req, event); ++ } ++} +diff --git a/drivers/usb/gadget/udc/hiudc3/hiusb3.c b/drivers/usb/gadget/udc/hiudc3/hiusb3.c +new file mode 100644 +index 0000000..85e981f +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/hiusb3.c +@@ -0,0 +1,64 @@ ++#include ++#include ++#include ++#include ++#include "os_dev.h" ++//#include "xhci.h" ++//#include "hiusb3.h" ++ ++ ++MODULE_LICENSE("Dual MIT/GPL"); ++ ++static struct resource hiusb_xhci_res[] = { ++ [0] = { ++ .start = CONFIG_HIUSB_XHCI_REG_BASE_ADDRESS, ++ .end = CONFIG_HIUSB_XHCI_REG_BASE_ADDRESS ++ + CONFIG_HIUSB_XHCI_REG_BASE_ADDRESS_LEN - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = CONFIG_HIUSB_XHCI_IRQ_NUMBER, ++ .end = CONFIG_HIUSB_XHCI_IRQ_NUMBER, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++static void usb_xhci_platdev_release(struct device *dev) ++{ ++ /* These don't need to do anything because the ++ pdev structures are statically allocated. */ ++} ++ ++//u64 usb_dmamask = DMA_BIT_MASK(32); ++ ++static struct platform_device hiusb_xhci_platdev = { ++ .name = "dwc_usb3", ++ .id = -1, ++ .dev = { ++ .init_name = "dwc_usb3", ++ .platform_data = NULL, ++ .dma_mask = DMA_BIT_MASK(32), ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ .release = usb_xhci_platdev_release, ++ }, ++ .num_resources = ARRAY_SIZE(hiusb_xhci_res), ++ .resource = hiusb_xhci_res, ++}; ++ ++static int __init xhci_device_init(void) ++{ ++// if (usb_disabled()) ++ // return -ENODEV; ++ int reg; ++// reg = readl(IO_ADDRESS(0x11080430)); ++ printk("\n########################################################%s,%d\n",__func__,__LINE__); ++ return 0; ++ return platform_device_register(&hiusb_xhci_platdev); ++} ++ ++static void __exit xhci_device_exit(void) ++{ ++ platform_device_unregister(&hiusb_xhci_platdev); ++} ++ ++module_init(xhci_device_init); ++module_exit(xhci_device_exit); +diff --git a/drivers/usb/gadget/udc/hiudc3/hw.h b/drivers/usb/gadget/udc/hiudc3/hw.h +new file mode 100644 +index 0000000..5967a13 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/hw.h +@@ -0,0 +1,1967 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/DWC_usb3/driver/hw.h $ ++ * $Revision: #65 $ ++ * $Date: 2014/11/11 $ ++ * $Change: 2664766 $ ++ * ++ * Synopsys SS USB3 Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 _DWC_USB3_REGS_H_ ++#define _DWC_USB3_REGS_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * @file ++ * ++ * This file contains the data structures for accessing the DWC_usb3 core ++ * registers and DMA descriptor fields. ++ * ++ * The application interfaces with the HS OTG core by reading from and ++ * writing to the Control and Status Register (CSR) space through the ++ * AHB Slave interface. These registers are 32 bits wide, and the ++ * addresses are 32-bit-block aligned. ++ * CSRs are classified as follows: ++ * - Core Global Registers ++ * - Device Global Registers ++ * - Device Endpoint Specific Registers ++ */ ++ ++ ++/****************************************************************************/ ++/* Core Global Registers */ ++ ++/** ++ * This enum represents the bit fields of the Core SoC Bus Configuration 0 ++ * Register (GSBUSCFG0). ++ */ ++typedef enum gsbuscfg0_data { ++ /** Bus Burst Len Access: R_W. ++ * - 0: single ++ * - 1: incr ++ * - 3: incr4 ++ * - 7: incr8 ++ * - 15: incr16 ++ * - 31: incr32 (non-AHB mode only) ++ * - 63: incr64 (non-AHB mode only) ++ * - 127: incr128 (non-AHB mode only) ++ * - 255: incr256 (non-AHB mode only) ++ */ ++ DWC_SBUSCFG0_HBURSTLEN_BITS = 0x000000ff, ++ DWC_SBUSCFG0_HBURSTLEN_SHIFT = 0, ++ ++ DWC_SBUSCFG0_INT_DMA_BURST_SINGLE = 0, ++ DWC_SBUSCFG0_INT_DMA_BURST_INCR = 1, ++ DWC_SBUSCFG0_INT_DMA_BURST_INCR4 = 3, ++ DWC_SBUSCFG0_INT_DMA_BURST_INCR8 = 7, ++ DWC_SBUSCFG0_INT_DMA_BURST_INCR16 = 15, ++ DWC_SBUSCFG0_INT_DMA_BURST_INCR32 = 31, ++ DWC_SBUSCFG0_INT_DMA_BURST_INCR64 = 63, ++ DWC_SBUSCFG0_INT_DMA_BURST_INCR128 = 127, ++ DWC_SBUSCFG0_INT_DMA_BURST_INCR256 = 255, ++ ++ /** Descriptor Write is Posted Access: R_W */ ++ DWC_SBUSCFG0_DES_WR_POST_BIT = 0x00000100, ++ DWC_SBUSCFG0_DES_WR_POST_SHIFT = 8, ++ ++ /** Data Write is Posted Access: R_W */ ++ DWC_SBUSCFG0_DAT_WR_POST_BIT = 0x00000200, ++ DWC_SBUSCFG0_DAT_WR_POST_SHIFT = 9, ++ ++ /** Descriptor Access is Big-Endian Access: R_W */ ++ DWC_SBUSCFG0_DES_BIG_END_BIT = 0x00000400, ++ DWC_SBUSCFG0_DES_BIG_END_SHIFT = 10, ++ ++ /** Data Access is Big-Endian Access: R_W */ ++ DWC_SBUSCFG0_DAT_BIG_END_BIT = 0x00000800, ++ DWC_SBUSCFG0_DAT_BIG_END_SHIFT = 11, ++ ++ /** Store and Forward Mode Access: R_W */ ++ DWC_SBUSCFG0_STORE_AND_FORWARD_BIT = 0x00001000, ++ DWC_SBUSCFG0_STORE_AND_FORWARD_SHIFT = 12, ++ ++ /** Force Single Request Access: R_W */ ++ DWC_SBUSCFG0_SING_REQ_BIT = 0x00004000, ++ DWC_SBUSCFG0_SING_REQ_SHIFT = 14, ++ ++ /** Descriptor Readback Enable Access: R_W */ ++ DWC_SBUSCFG0_READ_AFTER_WRITE_BIT = 0x00008000, ++ DWC_SBUSCFG0_READ_AFTER_WRITE_SHIFT = 15, ++ ++ /** Descriptor Write Request Info Access: R_W */ ++ DWC_SBUSCFG0_DES_WR_REQ_INFO_BITS = 0x000f0000, ++ DWC_SBUSCFG0_DES_WR_REQ_INFO_SHIFT = 16, ++ ++ /** Data Write Request Info Access: R_W */ ++ DWC_SBUSCFG0_DAT_WR_REQ_INFO_BITS = 0x00f00000, ++ DWC_SBUSCFG0_DAT_WR_REQ_INFO_SHIFT = 20, ++ ++ /** Descriptor Read Request Info Access: R_W */ ++ DWC_SBUSCFG0_DES_RD_REQ_INFO_BITS = 0x0f000000, ++ DWC_SBUSCFG0_DES_RD_REQ_INFO_SHIFT = 24, ++ ++ /** Data Read Request Info Access: R_W */ ++ DWC_SBUSCFG0_DAT_RD_REQ_INFO_BITS = 0xf0000000, ++ DWC_SBUSCFG0_DAT_RD_REQ_INFO_SHIFT = 28, ++} gsbuscfg0_data_t; ++ ++/** ++ * This enum represents the bit fields of the Core SoC Bus Configuration 1 ++ * Register (GSBUSCFG1). ++ */ ++typedef enum gsbuscfg1_data { ++ /** OCP Address Space For Descriptor Access: R_W */ ++ DWC_SBUSCFG1_DES_ADDR_SPC_BITS = 0x0000000f, ++ DWC_SBUSCFG1_DES_ADDR_SPC_SHIFT = 0, ++ ++ /** OCP Address Space For Data Access: R_W */ ++ DWC_SBUSCFG1_DAT_ADDR_SPC_BITS = 0x000000f0, ++ DWC_SBUSCFG1_DAT_ADDR_SPC_SHIFT = 4, ++} gsbuscfg1_data_t; ++ ++/** ++ * This enum represents the bit fields of the Core Tx Threshold Control ++ * Register (GTXTHRCFG). ++ */ ++typedef enum gtxthrcfg_data { ++ /** Maximum Tx Burst Size Access: R_W */ ++ DWC_TXTHRCTL_USB_MAX_TX_BURST_SIZE_BITS = 0x00ff0000, ++ DWC_TXTHRCTL_USB_MAX_TX_BURST_SIZE_SHIFT = 16, ++ ++ /** Tx Multi-Packet Threshold Count Access: R_W */ ++ DWC_TXTHRCTL_USB_TX_PKT_CNT_BITS = 0x1f000000, ++ DWC_TXTHRCTL_USB_TX_PKT_CNT_SHIFT = 24, ++ ++ /** Tx Multi-Packet Threshold Enable Access: R_W */ ++ DWC_TXTHRCTL_USB_TX_PKT_CNT_EN_BIT = 0x20000000, ++ DWC_TXTHRCTL_USB_TX_PKT_CNT_EN_SHIFT = 29, ++} gtxthrcfg_data_t; ++ ++/** ++ * This enum represents the bit fields of the Core Rx Threshold Control ++ * Register (GRXTHRCFG). ++ */ ++typedef enum grxthrcfg_data { ++ /** Maximum Rx Burst Size Access: R_W */ ++ DWC_RXTHRCTL_USB_MAX_RX_BURST_SIZE_BITS = 0x00f80000, ++ DWC_RXTHRCTL_USB_MAX_RX_BURST_SIZE_SHIFT = 19, ++ ++ /** Rx Multi-Packet Threshold Count Access: R_W */ ++ DWC_RXTHRCTL_USB_RX_PKT_CNT_BITS = 0x0f000000, ++ DWC_RXTHRCTL_USB_RX_PKT_CNT_SHIFT = 24, ++ ++ /** Rx Multi-Packet Threshold Enable Access: R_W */ ++ DWC_RXTHRCTL_USB_RX_PKT_CNT_EN_BIT = 0x20000000, ++ DWC_RXTHRCTL_USB_RX_PKT_CNT_EN_SHIFT = 29, ++} grxthrcfg_data_t; ++ ++/** ++ * This enum represents the bit fields of the Core Control ++ * Register (GCTL). ++ */ ++typedef enum gctl_data { ++ /** Disable Clock Gating Access: R_W */ ++ DWC_GCTL_DSBL_CLCK_GTNG_BIT = 0x00000001, ++ DWC_GCTL_DSBL_CLCK_GTNG_SHIFT = 0, ++ ++ /** Global Hibernation Enable Access: R_W */ ++ DWC_GCTL_GBL_HIBER_EN_BIT = 0x00000002, ++ DWC_GCTL_GBL_HIBER_EN_SHIFT = 1, ++ ++ /** Disable Scrambling Access: R_W */ ++ DWC_GCTL_DIS_SCRAMBLE_BIT = 0x00000008, ++ DWC_GCTL_DIS_SCRAMBLE_SHIFT = 3, ++ ++ /** Scale-down Mode Access: R_W */ ++ DWC_GCTL_SCALE_DOWN_BITS = 0x00000030, ++ DWC_GCTL_SCALE_DOWN_SHIFT = 4, ++ ++ /** RAM Clock Select Access: R_W */ ++ DWC_GCTL_RAM_CLK_SEL_BITS = 0x000000c0, ++ DWC_GCTL_RAM_CLK_SEL_SHIFT = 6, ++ ++ /** Debug Attach Access: R_W */ ++ DWC_GCTL_DEBUG_ATTACH_BIT = 0x00000100, ++ DWC_GCTL_DEBUG_ATTACH_SHIFT = 8, ++ ++ /** Disable U1/U2 Timer Scaledown Access: R_W */ ++ DWC_GCTL_U1U2_TIMER_SCALE_BIT = 0x00000200, ++ DWC_GCTL_U1U2_TIMER_SCALE_SHIFT = 9, ++ ++ /** SOF ITP SYNC Access: R_W */ ++ DWC_GCTL_SOFITPSYNC_BIT = 0x00000400, ++ DWC_GCTL_SOFITPSYNC_SHIFT = 10, ++ ++ /** Core Soft Reset Access: R_W */ ++ DWC_GCTL_CORE_SOFT_RST_BIT = 0x00000800, ++ DWC_GCTL_CORE_SOFT_RST_SHIFT = 11, ++ ++ /** Port Capability Direction Access: R_W */ ++ DWC_GCTL_PRT_CAP_DIR_BITS = 0x00003000, ++ DWC_GCTL_PRT_CAP_DIR_SHIFT = 12, ++ ++ /** Port Capability Values */ ++ DWC_GCTL_PRT_CAP_HOST = 1, ++ DWC_GCTL_PRT_CAP_DEVICE = 2, ++ DWC_GCTL_PRT_CAP_OTG = 3, ++ ++ /** Frame Scale Down Access: R_W */ ++ DWC_GCTL_FRMSCLDWN_BITS = 0x0000c000, ++ DWC_GCTL_FRMSCLDWN_SHIFT = 14, ++ ++ /** U2 Reset ECN Access: R_W */ ++ DWC_GCTL_U2RSTECN_BIT = 0x00010000, ++ DWC_GCTL_U2RSTECN_SHIFT = 16, ++ ++ /** Bypass SetAddress Access: R_W */ ++ DWC_GCTL_BYPSSETADDR_BIT = 0x00020000, ++ DWC_GCTL_BYPSSETADDR_SHIFT = 17, ++ ++ /** Master Filter Bypass Access: R_W */ ++ DWC_GCTL_MASTERFILTBYPASS_BIT = 0x00040000, ++ DWC_GCTL_MASTERFILTBYPASS_SHIFT = 18, ++ ++ /** Power Down Scale Access: R_W */ ++ DWC_GCTL_PWR_DN_SCALE_BITS = 0xfff80000, ++ DWC_GCTL_PWR_DN_SCALE_SHIFT = 19, ++} gctl_data_t; ++ ++/** ++ * This enum represents the bit fields of the Core Interrupt Mask ++ * Register (GEVTEN). ++ */ ++typedef enum gevten_data { ++ /** ULPI Carkit Event Enable Access: R_W */ ++ DWC_GEVTEN_ULPI_CK_EVT_EN_BIT = 0x00000001, ++ DWC_GEVTEN_ULPI_CK_EVT_SHIFT = 0, ++ ++ /** I2C Event Enable Access: R_W */ ++ DWC_GEVTEN_I2C_EVT_EN_BIT = 0x00000002, ++ DWC_GEVTEN_I2C_EVT_EN_SHIFT = 1, ++} gevten_data_t; ++ ++/** ++ * This enum represents the bit fields of the Core Status ++ * Register (GSTS). ++ */ ++typedef enum gsts_data { ++ /** Current Mode Access: RO. ++ * - 0: Device Mode ++ * - 1: Host Mode ++ * - 2: DRD Mode ++ */ ++ DWC_GSTS_CURMODE_BITS = 0x00000003, ++ DWC_GSTS_CURMODE_SHIFT = 0, ++ ++ DWC_GSTS_DEVICE_MODE = 0, ++ DWC_GSTS_HOST_MODE = 1, ++ DWC_GSTS_DRD_MODE = 2, ++ ++ /** Bus Error Address Valid Access: RO */ ++ DWC_GSTS_BUS_ERR_ADDR_VLD_BIT = 0x00000010, ++ DWC_GSTS_BUS_ERR_ADDR_VLD_SHIFT = 4, ++ ++ /** CSR Timeout */ ++ DWC_GSTS_CSR_TIMEOUT_BIT = 0x00000020, ++ DWC_GSTS_CSR_TIMEOUT_SHIFT = 5, ++ ++ /** Device Interrupt Pending */ ++ DWC_GSTS_DEV_EVT_PENDING_BIT = 0x00000040, ++ DWC_GSTS_DEV_EVT_PENDING_SHIFT = 6, ++ ++ /** Host Interrupt Pending */ ++ DWC_GSTS_HOST_EVT_PENDING_BIT = 0x00000080, ++ DWC_GSTS_HOST_EVT_PENDING_SHIFT = 7, ++ ++ /** ADP Interrupt Pending */ ++ DWC_GSTS_ADP_EVT_PENDING_BIT = 0x00000100, ++ DWC_GSTS_ADP_EVT_PENDING_SHIFT = 8, ++ ++ /** BC Interrupt Pending */ ++ DWC_GSTS_BC_EVT_PENDING_BIT = 0x00000200, ++ DWC_GSTS_BC_EVT_PENDING_SHIFT = 9, ++ ++ /** OTG Interrupt Pending */ ++ DWC_GSTS_OTG_EVT_PENDING_BIT = 0x00000400, ++ DWC_GSTS_OTG_EVT_PENDING_SHIFT = 10, ++ ++ /** SSIC Interrupt Pending */ ++ DWC_GSTS_SSIC_IP_BIT = 0x00000800, ++ DWC_GSTS_SSIC_IP_SHIFT = 11, ++ ++ /** Current BELT Value Access: RO */ ++ DWC_GSTS_CBELT_BITS = 0xfff00000, ++ DWC_GSTS_CBELT_SHIFT = 20, ++} gsts_data_t; ++ ++/** ++ * This enum represents the bit fields of the Hardware Parameters 0 ++ * Register (GHWPARAMS0). ++ */ ++typedef enum ghwparams0_data { ++ DWC_HWP0_MODE_BITS = 0x00000007, ++ DWC_HWP0_MODE_SHIFT = 0, ++ ++ DWC_HWP0_MBUS_TYPE_BITS = 0x00000038, ++ DWC_HWP0_MBUS_TYPE_SHIFT = 3, ++ ++ DWC_HWP0_SBUS_TYPE_BITS = 0x000000c0, ++ DWC_HWP0_SBUS_TYPE_SHIFT = 6, ++ ++ DWC_HWP0_MDWIDTH_BITS = 0x0000ff00, ++ DWC_HWP0_MDWIDTH_SHIFT = 8, ++ ++ DWC_HWP0_SDWIDTH_BITS = 0x00ff0000, ++ DWC_HWP0_SDWIDTH_SHIFT = 16, ++ ++ DWC_HWP0_AWIDTH_BITS = 0x3f000000, ++ DWC_HWP0_AWIDTH_SHIFT = 24, ++} ghwparams0_data_t; ++ ++/** ++ * This enum represents the bit fields of the Hardware Parameters 1 ++ * Register (GHWPARAMS1). ++ */ ++typedef enum ghwparams1_data { ++ DWC_HWP1_IDWIDTH_M1_BITS = 0x00000007, ++ DWC_HWP1_IDWIDTH_M1_SHIFT = 0, ++ ++ DWC_HWP1_BURSTWIDTH_M1_BITS = 0x00000038, ++ DWC_HWP1_BURSTWIDTH_M1_SHIFT = 3, ++ ++ DWC_HWP1_DATAINFOWIDTH_BITS = 0x000001c0, ++ DWC_HWP1_DATAINFOWIDTH_SHIFT = 6, ++ ++ DWC_HWP1_REQINFOWIDTH_BITS = 0x00000e00, ++ DWC_HWP1_REQINFOWIDTH_SHIFT = 9, ++ ++ DWC_HWP1_ASPACEWIDTH_BITS = 0x00007000, ++ DWC_HWP1_ASPACEWIDTH_SHIFT = 12, ++ ++ DWC_HWP1_DEV_NUM_INT_BITS = 0x001f8000, ++ DWC_HWP1_DEV_NUM_INT_SHIFT = 15, ++ ++ DWC_HWP1_NUM_RAMS_BITS = 0x00600000, ++ DWC_HWP1_NUM_RAMS_SHIFT = 21, ++ ++ DWC_HWP1_SPRAM_TYP_BIT = 0x00800000, ++ DWC_HWP1_SPRAM_TYP_SHIFT = 23, ++ ++ DWC_HWP1_EN_PWROPT_BITS = 0x03000000, ++ DWC_HWP1_EN_PWROPT_SHIFT = 24, ++ ++ DWC_EN_PWROPT_NONE = 0, ++ DWC_EN_PWROPT_CLK_GATING_ONLY = 1, ++ DWC_EN_PWROPT_HIBERNATION = 2, ++ ++ DWC_HWP1_MAC_PHY_CLKS_SYNC_BIT = 0x04000000, ++ DWC_HWP1_MAC_PHY_CLKS_SYNC_SHIFT = 26, ++ ++ DWC_HWP1_MAC_RAM_CLKS_SYNC_BIT = 0x08000000, ++ DWC_HWP1_MAC_RAM_CLKS_SYNC_SHIFT = 27, ++ ++ DWC_HWP1_RAM_BUS_CLKS_SYNC_BIT = 0x10000000, ++ DWC_HWP1_RAM_BUS_CLKS_SYNC_SHIFT = 28, ++ ++ DWC_HWP1_RM_OPT_FEATURES_BIT = 0x40000000, ++ DWC_HWP1_RM_OPT_FEATURES_SHIFT = 30, ++} ghwparams1_data_t; ++ ++/** ++ * This enum represents the bit fields of the Hardware Parameters 2 ++ * Register (GHWPARAMS2). ++ */ ++typedef enum ghwparams2_data { ++ DWC_HWP2_USERID_BITS = 0xffffffff, ++ DWC_HWP2_USERID_SHIFT = 0, ++} ghwparams2_data_t; ++ ++/** ++ * This enum represents the bit fields of the Hardware Parameters 3 ++ * Register (GHWPARAMS3). ++ */ ++typedef enum ghwparams3_data { ++ DWC_HWP3_SSPHY_IFC_BITS = 0x00000003, ++ DWC_HWP3_SSPHY_IFC_SHIFT = 0, ++ ++ DWC_HWP3_HSPHY_IFC_BITS = 0x0000000c, ++ DWC_HWP3_HSPHY_IFC_SHIFT = 2, ++ ++ DWC_HWP3_FSPHY_IFC_BITS = 0x00000030, ++ DWC_HWP3_FSPHY_IFC_SHIFT = 4, ++ ++ DWC_HWP3_HSPHY_DWIDTH_BITS = 0x000000c0, ++ DWC_HWP3_HSPHY_DWIDTH_SHIFT = 6, ++ ++ DWC_HWP3_VEND_CTL_IFC_BIT = 0x00000400, ++ DWC_HWP3_VEND_CTL_IFC_SHIFT = 10, ++ ++ DWC_HWP3_ULPI_CARKIT_BIT = 0x00000800, ++ DWC_HWP3_ULPI_CARKIT_SHIFT = 11, ++ ++ DWC_HWP3_NUM_EPS_BITS = 0x0003f000, ++ DWC_HWP3_NUM_EPS_SHIFT = 12, ++ ++ DWC_HWP3_NUM_IN_EPS_BITS = 0x007c0000, ++ DWC_HWP3_NUM_IN_EPS_SHIFT = 18, ++ ++ DWC_HWP3_TOT_XFR_RSRC_BITS = 0x7f800000, ++ DWC_HWP3_TOT_XFR_RSRC_SHIFT = 23, ++} ghwparams3_data_t; ++ ++/** ++ * This enum represents the bit fields of the Hardware Parameters 4 ++ * Register (GHWPARAMS4). ++ */ ++typedef enum ghwparams4_data { ++ DWC_HWP4_TRBS_PER_XFER_BITS = 0x0000003f, ++ DWC_HWP4_TRBS_PER_XFER_SHIFT = 0, ++ ++ DWC_HWP4_HIBER_SPAD_BITS = 0x0001e000, ++ DWC_HWP4_HIBER_SPAD_SHIFT = 13, ++ ++ DWC_HWP4_NUM_SS_USB_INST_BITS = 0x001e0000, ++ DWC_HWP4_NUM_SS_USB_INST_SHIFT = 17, ++ ++ DWC_HWP4_EN_ISOC_SUPT_BIT = 0x00800000, ++ DWC_HWP4_EN_ISOC_SUPT_SHIFT = 23, ++ ++ DWC_HWP4_BMU_PTL_DEPTH_BITS = 0x0f000000, ++ DWC_HWP4_BMU_PTL_DEPTH_SHIFT = 24, ++ ++ DWC_HWP4_BMU_LSP_DEPTH_BITS = 0xf0000000, ++ DWC_HWP4_BMU_LSP_DEPTH_SHIFT = 28, ++} ghwparams4_data_t; ++ ++/** ++ * This enum represents the bit fields of the Hardware Parameters 5 ++ * Register (GHWPARAMS5). ++ */ ++typedef enum ghwparams5_data { ++ DWC_HWP5_BMU_BUSGM_DEPTH_BITS = 0x0000000f, ++ DWC_HWP5_BMU_BUSGM_DEPTH_SHIFT = 0, ++ ++ DWC_HWP5_RXQ_FIFO_DEPTH_BITS = 0x000003f0, ++ DWC_HWP5_RXQ_FIFO_DEPTH_SHIFT = 4, ++ ++ DWC_HWP5_TXQ_FIFO_DEPTH_BITS = 0x0000fc00, ++ DWC_HWP5_TXQ_FIFO_DEPTH_SHIFT = 10, ++ ++ DWC_HWP5_DWQ_FIFO_DEPTH_BITS = 0x003f0000, ++ DWC_HWP5_DWQ_FIFO_DEPTH_SHIFT = 16, ++ ++ DWC_HWP5_DFQ_FIFO_DEPTH_BITS = 0x0fc00000, ++ DWC_HWP5_DFQ_FIFO_DEPTH_SHIFT = 22, ++} ghwparams5_data_t; ++ ++/** ++ * This enum represents the bit fields of the Hardware Parameters 6 ++ * Register (GHWPARAMS6). ++ */ ++typedef enum ghwparams6_data { ++ DWC_HWP6_PSQ_FIFO_DEPTH_BITS = 0x0000003f, ++ DWC_HWP6_PSQ_FIFO_DEPTH_SHIFT = 0, ++ ++ DWC_HWP6_EN_DBG_PORTS_BIT = 0x00000040, ++ DWC_HWP6_EN_DBG_PORTS_SHIFT = 6, ++ ++ DWC_HWP6_EN_FPGA_BIT = 0x00000080, ++ DWC_HWP6_EN_FPGA_SHIFT = 7, ++ ++ DWC_HWP6_EN_SRP_BIT = 0x00000400, ++ DWC_HWP6_EN_SRP_SHIFT = 10, ++ ++ DWC_HWP6_EN_HNP_BIT = 0x00000800, ++ DWC_HWP6_EN_HNP_SHIFT = 11, ++ ++ DWC_HWP6_EN_ADP_BIT = 0x00001000, ++ DWC_HWP6_EN_ADP_SHIFT = 12, ++ ++ DWC_HWP6_EN_OTG_BIT = 0x00002000, ++ DWC_HWP6_EN_OTG_SHIFT = 13, ++ ++ DWC_HWP6_EN_BC_BIT = 0x00004000, ++ DWC_HWP6_EN_BC_SHIFT = 14, ++ ++ DWC_HWP6_EN_BUS_FILTERS_BIT = 0x00008000, ++ DWC_HWP6_EN_BUS_FILTERS_SHIFT = 15, ++ ++ DWC_HWP6_RAM0_DEPTH_BITS = 0xffff0000, ++ DWC_HWP6_RAM0_DEPTH_SHIFT = 16, ++} ghwparams6_data_t; ++ ++/** ++ * This enum represents the bit fields of the Hardware Parameters 7 ++ * Register (GHWPARAMS7). ++ */ ++typedef enum ghwparams7_data { ++ DWC_HWP7_RAM1_DEPTH_BITS = 0x0000ffff, ++ DWC_HWP7_RAM1_DEPTH_SHIFT = 0, ++ ++ DWC_HWP7_RAM2_DEPTH_BITS = 0xffff0000, ++ DWC_HWP7_RAM2_DEPTH_SHIFT = 16, ++} ghwparams7_data_t; ++ ++/** ++ * This enum represents the bit fields of the Hardware Parameters 8 ++ * Register (GHWPARAMS8). ++ */ ++typedef enum ghwparams8_data { ++ DWC_HWP8_DCACHE_DEPTH_BITS = 0xffffffff, ++ DWC_HWP8_DCACHE_DEPTH_SHIFT = 0, ++} ghwparams8_data_t; ++ ++/** ++ * This enum represents the bit fields of the Debug Queue/FIFO Space ++ * Register (GDBGFIFOSPACE). ++ */ ++typedef enum gdbgfifospace_data { ++ /** FIFO/Queue Select Access: R_W */ ++ DWC_DBGFIFOSPACE_FIFO_QUEUE_SEL_BITS = 0x000000ff, ++ DWC_DBGFIFOSPACE_FIFO_QUEUE_SEL_SHIFT = 0, ++ ++ /* 0 - 31 TxFIFO Number */ ++ /* 32 - 63 RxFIFO Number */ ++ /* 64 - 95 TxReqQ Number */ ++ /* 96 - 127 RxReqQ Number */ ++ /* 128 - 159 RxInfoQ Number */ ++ /* 160 DescFetchQ */ ++ /* 161 EventQ */ ++ /* 162 ProtocolStatusQ */ ++ ++ /** Space Available Access: R */ ++ DWC_DBGFIFOSPACE_SPACE_AVAIL_BITS = 0xffff0000, ++ DWC_DBGFIFOSPACE_SPACE_AVAIL_SHIFT = 16, ++} gdbgfifospace_data_t; ++ ++/** ++ * This enum represents the bit fields of the Debug LTSSM ++ * Register (GDBGLTSSM). ++ */ ++typedef enum gdbgltssm_data { ++ /** Pipe Status Access: R */ ++ DWC_DBGLTSSM_PIPE_STATUS_BITS = 0x0003ffff, ++ DWC_DBGLTSSM_PIPE_STATUS_SHIFT = 0, ++ ++ /** LTDB SubState Access: R */ ++ DWC_DBGLTSSM_LTDB_SUB_STATE_BITS = 0x003c0000, ++ DWC_DBGLTSSM_LTDB_SUB_STATE_SHIFT = 18, ++ ++ /** LTDB State Access: R */ ++ DWC_DBGLTSSM_LTDB_STATE_BITS = 0x03c00000, ++ DWC_DBGLTSSM_LTDB_STATE_SHIFT = 22, ++ ++ /** LTDB Timeout Access: R */ ++ DWC_DBGLTSSM_LTDB_TIMEOUT_BIT = 0x04000000, ++ DWC_DBGLTSSM_LTDB_TIMEOUT_SHIFT = 26, ++} gdbgltssm_data_t; ++ ++/** ++ * This enum represents the bit fields of the Core RMMI PHY Control ++ * Registers (GUSB3RMMICTLn). ++ */ ++typedef enum gusb3rmmictl_data { ++ DWC_RMMICTL_MPHY_STATE_BITS = 0x0e000000, ++ DWC_RMMICTL_MPHY_STATE_SHIFT = 25, ++ ++#define DWC_MPHY_STATE_DISABLED 0 ++#define DWC_MPHY_STATE_HIBERN8 1 ++#define DWC_MPHY_STATE_SLEEP 2 ++#define DWC_MPHY_STATE_STALL 3 ++#define DWC_MPHY_STATE_PWM_BURST 4 ++#define DWC_MPHY_STATE_HS_BURST 5 ++#define DWC_MPHY_STATE_LINE_CFG 6 ++#define DWC_MPHY_STATE_LINE_RESET 7 ++ ++ DWC_RMMICTL_AUTO_EXIT_RRAP_BIT = 0x10000000, ++ DWC_RMMICTL_AUTO_EXIT_RRAP_SHIFT = 28, ++ ++ DWC_RMMICTL_AUTO_ROM_RRAP_BIT = 0x20000000, ++ DWC_RMMICTL_AUTO_ROM_RRAP_SHIFT = 29, ++ ++ DWC_RMMICTL_AUTO_EXIT_H8_BIT = 0x40000000, ++ DWC_RMMICTL_AUTO_EXIT_H8_SHIFT = 30, ++ ++ DWC_RMMICTL_AUTO_ROM_H8_BIT = 0x80000000, ++ DWC_RMMICTL_AUTO_ROM_H8_SHIFT = 31, ++} gusb3rmmictl_data_t; ++ ++/** ++ * This enum represents the bit fields of the Core USB2 PHY Configuration ++ * Registers (GUSB2PHYCFGn). ++ */ ++typedef enum gusb2phycfg_data { ++ /** HS/FS Timeout Calibration Access: R_W */ ++ DWC_USB2PHYCFG_TOUT_CAL_BITS = 0x00000007, ++ DWC_USB2PHYCFG_TOUT_CAL_SHIFT = 0, ++ ++ /** UTMI+ PHY Intf Width (8-bit/16-bit) SelecT Access: R_W */ ++ DWC_USB2PHYCFG_16B_PHY_IF_BIT = 0x00000008, ++ DWC_USB2PHYCFG_16B_PHY_IF_SHIFT = 3, ++ /*--------*/ ++ /** ULPI DDR Select Access: R_W */ ++ DWC_USB2PHYCFG_DDR_SEL_BIT = 0x00000008, ++ DWC_USB2PHYCFG_DDR_SEL_SHIFT = 3, ++ ++ /** UTMI+ / ULPI Select Access: R_W */ ++ DWC_USB2PHYCFG_UTMI_ULPI_BIT = 0x00000010, ++ DWC_USB2PHYCFG_UTMI_ULPI_SHIFT = 4, ++ ++ /** Full-speed Serial Interface Select Access: R_W */ ++ DWC_USB2PHYCFG_FSINTF_BIT = 0x00000020, ++ DWC_USB2PHYCFG_FSINTF_SHIFT = 5, ++ ++ /** Suspend USB2 Phy Access: R_W */ ++ DWC_USB2PHYCFG_SUS_PHY_BIT = 0x00000040, ++ DWC_USB2PHYCFG_SUS_PHY_SHIFT = 6, ++ ++ /** USB2.0 HS PHY/USB1.1 FS Serial Xcvr Select Access: R_W */ ++ DWC_USB2PHYCFG_PHY_SEL_BIT = 0x00000080, ++ DWC_USB2PHYCFG_PHY_SEL_SHIFT = 7, ++ ++ /** Enable UTMI Sleep Access: R_W */ ++ DWC_USB2PHYCFG_ENBL_SLP_M_BIT = 0x00000100, ++ DWC_USB2PHYCFG_ENBL_SLP_M_SHIFT = 8, ++ ++ /** USB2.0 Turnaround Time Access: R_W */ ++ DWC_USB2PHYCFG_USB_TRD_TIM_BITS = 0x00003c00, ++ DWC_USB2PHYCFG_USB_TRD_TIM_SHIFT = 10, ++ ++ /** PHY Low-power Clock Select Access: R_W */ ++ DWC_USB2PHYCFG_PHY_LPWR_CLK_SEL_BIT = 0x00004000, ++ DWC_USB2PHYCFG_PHY_LPWR_CLK_SEL_SHIFT = 14, ++ ++ /** ULPI Auto Resume Access: R_W */ ++ DWC_USB2PHYCFG_ULPI_AUTO_RES_BIT = 0x00008000, ++ DWC_USB2PHYCFG_ULPI_AUTO_RES_SHIFT = 15, ++ ++ /** ULPI Clock SuspendM Access: R_W */ ++ DWC_USB2PHYCFG_ULPI_CLK_SUS_M_BIT = 0x00010000, ++ DWC_USB2PHYCFG_ULPI_CLK_SUS_M_SHIFT = 16, ++ ++ /** ULPI External Vbus Drive Access: R_W */ ++ DWC_USB2PHYCFG_ULPI_EXT_VBUS_DRV_BIT = 0x00020000, ++ DWC_USB2PHYCFG_ULPI_EXT_VBUS_DRV_SHIFT = 17, ++ ++ /** ULPI External Vbus Indicator Access: R_W */ ++ DWC_USB2PHYCFG_ULPI_EXT_VBUS_IND_BIT = 0x00040000, ++ DWC_USB2PHYCFG_ULPI_EXT_VBUS_IND_SHIFT = 18, ++ ++ /** PHY Interrupt Number Access: R_W */ ++ DWC_USB2PHYCFG_PHY_INTR_NUM_BITS = 0x01f80000, ++ DWC_USB2PHYCFG_PHY_INTR_NUM_SHIFT = 19, ++ ++ /** OTG Interrupt Number Access: R_W */ ++ DWC_USB2PHYCFG_OTG_INTR_NUM_BITS = 0x7e000000, ++ DWC_USB2PHYCFG_OTG_INTR_NUM_SHIFT = 25, ++ ++ /** PHY Soft Reset Access: R_W */ ++ DWC_USB2PHYCFG_PHY_SOFT_RST_BIT = 0x80000000, ++ DWC_USB2PHYCFG_PHY_SOFT_RST_SHIFT = 31, ++} gusb2phycfg_data_t; ++ ++/** ++ * This enum represents the bit fields in the USB2 I2C Control ++ * Registers (GUSB2I2CCTLn). ++ */ ++typedef enum gusb2i2cctl_data { ++ /** All bits are reserved */ ++ DWC_USB2I2C_RSVD_BITS = 0xffffffff, ++ DWC_USB2I2C_RSVD_SHIFT = 0, ++} gusb2i2cctl_data_t; ++ ++/** ++ * This enum represents the bit fields in the USB2 Phy Vendor Control ++ * Registers (GUSB2PHYACCn). ++ */ ++typedef enum gusb2phyacc_data { ++ /** Register Data Access: R_W */ ++ DWC_USB2PHY_REGDATA_BITS = 0x000000ff, ++ DWC_USB2PHY_REGDATA_SHIFT = 0, ++ ++ /** UTMI+ Vendor Ctrl Register Address Access: R_W */ ++ DWC_USB2PHY_VCTRL_BITS = 0x0000ff00, ++ DWC_USB2PHY_VCTRL_SHIFT = 8, ++ /*--------*/ ++ /** ULPI Extended Register Address Access: R_W */ ++ DWC_USB2PHY_EXTREGADDR_BITS = 0x00003f00, ++ DWC_USB2PHY_EXTREGADDR_SHIFT = 8, ++ ++ /** Register Address Access: R_W */ ++ DWC_USB2PHY_REGADDR_BITS = 0x003f0000, ++ DWC_USB2PHY_REGADDR_SHIFT = 16, ++ ++ /** Register Write Access: R_W */ ++ DWC_USB2PHY_REGWR_BIT = 0x00400000, ++ DWC_USB2PHY_REGWR_SHIFT = 22, ++ ++ /** VStatus Busy Access: RO */ ++ DWC_USB2PHY_VSTSBSY_BIT = 0x00800000, ++ DWC_USB2PHY_VSTSBSY_SHIFT = 23, ++ ++ /** VStatus Done Access: R_SS_SC */ ++ DWC_USB2PHY_VSTSDONE_BIT = 0x01000000, ++ DWC_USB2PHY_VSTSDONE_SHIFT = 24, ++ ++ /** New Register Request Access: R_WS_SC */ ++ DWC_USB2PHY_NEWREGREQ_BIT = 0x02000000, ++ DWC_USB2PHY_NEWREGREQ_SHIFT = 25, ++ ++ /** Disable ULPI Drivers Access: R_WS_SC */ ++ DWC_USB2PHY_DIS_ULPI_DRVR_BIT = 0x04000000, ++ DWC_USB2PHY_DIS_ULPI_DRVR_SHIFT = 26, ++} gusb2phyacc_data_t; ++ ++/** ++ * This enum represents the bit fields of the USB3 Pipe Control ++ * Registers (GUSB3PIPECTLn). ++ */ ++typedef enum gusb3pipectl_data { ++ /** Elastic Buffer Mode Access: R_W */ ++ DWC_PIPECTL_ELAS_BUF_MODE_BIT = 0x00000001, ++ DWC_PIPECTL_ELAS_BUF_MODE_SHIFT = 0, ++ ++ /** Tx De-Emphasis Access: R_W */ ++ DWC_PIPECTL_TX_DEMPH_BITS = 0x00000006, ++ DWC_PIPECTL_TX_DEMPH_SHIFT = 1, ++ ++ /** Tx Margin Access: R_W */ ++ DWC_PIPECTL_TX_MARGIN_BITS = 0x00000038, ++ DWC_PIPECTL_TX_MARGIN_SHIFT = 3, ++ ++ /** Tx Swing Access: R_W */ ++ DWC_PIPECTL_TX_SWING_BIT = 0x00000040, ++ DWC_PIPECTL_TX_SWING_SHIFT = 6, ++ ++ /** USB3 SSIC Enable Access: R_W */ ++ DWC_PIPECTL_SSIC_EN_BIT = 0x00000080, ++ DWC_PIPECTL_SSIC_EN_SHIFT = 7, ++ ++ /** LFPS Filter Access: R_W */ ++ DWC_PIPECTL_LFPS_FILTER_BIT = 0x00000200, ++ DWC_PIPECTL_LFPS_FILTER_SHIFT = 9, ++ ++ /** P3 Exit Signal In P2 Access: R_W */ ++ DWC_PIPECTL_P3_EX_SIG_P2_BIT = 0x00000400, ++ DWC_PIPECTL_P3_EX_SIG_P2_SHIFT = 10, ++ ++ /** P3-P2 Transitions OK Access: R_W */ ++ DWC_PIPECTL_P3_P2_TRAN_OK_BIT = 0x00000800, ++ DWC_PIPECTL_P3_P2_TRAN_OK_SHIFT = 11, ++ ++ /** LFPS P0 Align Access: R_W */ ++ DWC_PIPECTL_LFPS_P0_ALGN_BIT = 0x00001000, ++ DWC_PIPECTL_LFPS_P0_ALGN_SHIFT = 12, ++ ++ /** Pipe Data Width Access: R_W */ ++ DWC_PIPECTL_DATA_WIDTH_BITS = 0x00018000, ++ DWC_PIPECTL_DATA_WIDTH_SHIFT = 15, ++ ++ /** Suspend USB3 Phy Access: R_W */ ++ DWC_PIPECTL_SUS_PHY_BIT = 0x00020000, ++ DWC_PIPECTL_SUS_PHY_SHIFT = 17, ++ ++ /** PHY Soft Reset Access: R_W */ ++ DWC_PIPECTL_PHY_SOFT_RST_BIT = 0x80000000, ++ DWC_PIPECTL_PHY_SOFT_RST_SHIFT = 31, ++} gusb3pipectl_data_t; ++ ++/** ++ * This enum represents the bit fields in the FIFO Size Registers. ++ */ ++typedef enum gfifosize_data { ++ /** Depth Access: R_W */ ++ DWC_FIFOSZ_DEPTH_BITS = 0x0000ffff, ++ DWC_FIFOSZ_DEPTH_SHIFT = 0, ++ ++ /** Starting Address Access: RO or R_W */ ++ DWC_FIFOSZ_STARTADDR_BITS = 0xffff0000, ++ DWC_FIFOSZ_STARTADDR_SHIFT = 16, ++} gfifosize_data_t; ++ ++/** ++ * This enum represents the bit fields of the Event Buffer Size ++ * Registers (GEVENTSIZn). ++ */ ++typedef enum geventsiz_data { ++ /** Event Buffer Size Access: R_W */ ++ DWC_EVENTSIZ_SIZ_BITS = 0x0000ffff, ++ DWC_EVENTSIZ_SIZ_SHIFT = 0, ++ ++ /** Event Interrupt Mask (1 == disable) Access: R_W */ ++ DWC_EVENTSIZ_INT_MSK_BIT = 0x80000000, ++ DWC_EVENTSIZ_INT_MSK_SHIFT = 31, ++} geventsiz_data_t; ++ ++/** ++ * This enum represents the bit fields of the Event Buffer Count ++ * Registers (GEVENTCNTn). ++ */ ++typedef enum geventcnt_data { ++ /** Event Count Access: R_W */ ++ DWC_EVENTCNT_CNT_BITS = 0x0000ffff, ++ DWC_EVENTCNT_CNT_SHIFT = 0, ++} geventcnt_data_t; ++ ++/** ++ * This enum represents the bit fields of a generic Event Buffer entry. ++ */ ++typedef enum gevent_data { ++ /** Non-Endpoint Specific Event flag */ ++ DWC_EVENT_NON_EP_BIT = 0x01, ++ DWC_EVENT_NON_EP_SHIFT = 0, ++ ++ /** Non-Endpoint Specific Event Type */ ++ DWC_EVENT_INTTYPE_BITS = 0xfe, ++ DWC_EVENT_INTTYPE_SHIFT = 1, ++ ++ /** Non-Endpoint Specific Event Type values */ ++ DWC_EVENT_DEV_INT = 0, /** @< */ ++ DWC_EVENT_OTG_INT = 1, /** @< */ ++ DWC_EVENT_CARKIT_INT = 3, /** @< */ ++ DWC_EVENT_I2C_INT = 4, ++} gevent_data_t; ++ ++/** ++ * This enum represents the non-generic bit fields of an Event Buffer entry ++ * for Device Specific events (DEVT). ++ */ ++typedef enum devt_data { ++ /** Device Specific Event Type */ ++ DWC_DEVT_BITS = 0x00000f00, ++ DWC_DEVT_SHIFT = 8, ++ ++ /** Device Specific Event Type values */ ++ DWC_DEVT_DISCONN = 0, /** @< */ ++ DWC_DEVT_USBRESET = 1, /** @< */ ++ DWC_DEVT_CONNDONE = 2, /** @< */ ++ DWC_DEVT_ULST_CHNG = 3, /** @< */ ++ DWC_DEVT_WKUP = 4, /** @< */ ++ DWC_DEVT_HIBER_REQ = 5, /** @< */ ++ DWC_DEVT_U3_L2L1_SUSP = 6, /** @< */ ++ DWC_DEVT_SOF = 7, /** @< */ ++ DWC_DEVT_ERRATICERR = 9, /** @< */ ++ DWC_DEVT_CMD_CMPL = 10, /** @< */ ++ DWC_DEVT_OVERFLOW = 11, /** @< */ ++ DWC_DEVT_VNDR_DEV_TST_RCVD = 12, /** @< */ ++ DWC_DEVT_INACT_TIMEOUT_RCVD = 13, ++ ++ /** Event Information */ ++ DWC_DEVT_EVT_INFO_BITS = 0xffff0000, ++ DWC_DEVT_EVT_INFO_SHIFT = 16, ++ ++ /** USB/Link State */ ++ DWC_DEVT_ULST_STATE_BITS = 0x000f0000, ++ DWC_DEVT_ULST_STATE_SHIFT = 16, ++ ++ /** USB/Link State values in SS */ ++ DWC_LINK_STATE_U0 = 0, /** @< */ ++ DWC_LINK_STATE_U1 = 1, /** @< */ ++ DWC_LINK_STATE_U2 = 2, /** @< */ ++ DWC_LINK_STATE_U3 = 3, /** @< */ ++ DWC_LINK_STATE_SS_DIS = 4, /** @< */ ++ DWC_LINK_STATE_RX_DET = 5, /** @< */ ++ DWC_LINK_STATE_SS_INACT = 6, /** @< */ ++ DWC_LINK_STATE_POLL = 7, /** @< */ ++ DWC_LINK_STATE_RECOV = 8, /** @< */ ++ DWC_LINK_STATE_HRESET = 9, /** @< */ ++ DWC_LINK_STATE_CMPLY = 10, /** @< */ ++ DWC_LINK_STATE_LPBK = 11, /** @< */ ++ DWC_LINK_STATE_RESET = 14, /** @< */ ++ DWC_LINK_STATE_RESUME = 15, ++ ++ /** USB/Link State values in HS/FS/LS */ ++ DWC_LINK_STATE_ON = 0, /** @< */ ++ DWC_LINK_STATE_SLEEP = 2, /** @< */ ++ DWC_LINK_STATE_SUSPEND = 3, /** @< */ ++ DWC_LINK_STATE_EARLY_SUSPEND = 5, ++ ++ DWC_DEVT_ULST_SS_BIT = 0x00100000, ++ DWC_DEVT_ULST_SS_SHIFT = 20, ++ ++#define DWC_DEVT_HIBER_STATE_BITS DWC_DEVT_ULST_STATE_BITS ++#define DWC_DEVT_HIBER_STATE_SHIFT DWC_DEVT_ULST_STATE_SHIFT ++ ++#define DWC_DEVT_HIBER_SS_BIT DWC_DEVT_ULST_SS_BIT ++#define DWC_DEVT_HIBER_SS_SHIFT DWC_DEVT_ULST_SS_SHIFT ++ ++ DWC_DEVT_HIBER_HIRD_BITS = 0x0f000000, ++ DWC_DEVT_HIBER_HIRD_SHIFT = 24, ++} devt_data_t; ++ ++/** ++ * This enum represents the bit fields of an Event Buffer entry for ++ * Endpoint Specific events (DEPEVT). ++ */ ++typedef enum depevt_data { ++ /** Endpoint Number */ ++ DWC_DEPEVT_EPNUM_BITS = 0x0000003e, ++ DWC_DEPEVT_EPNUM_SHIFT = 1, ++ ++ /** Endpoint Event Type */ ++ DWC_DEPEVT_INTTYPE_BITS = 0x000003c0, ++ DWC_DEPEVT_INTTYPE_SHIFT = 6, ++ ++ /** Endpoint Event Type values */ ++ DWC_DEPEVT_XFER_CMPL = 1, /** @< */ ++ DWC_DEPEVT_XFER_IN_PROG = 2, /** @< */ ++ DWC_DEPEVT_XFER_NRDY = 3, /** @< */ ++ DWC_DEPEVT_FIFOXRUN = 4, /** @< */ ++ DWC_DEPEVT_STRM_EVT = 6, /** @< */ ++ DWC_DEPEVT_EPCMD_CMPL = 7, ++ ++ /** Event Status for Start Xfer Command */ ++ DWC_DEPEVT_NO_MORE_RSCS_BIT = 0x00001000, ++ DWC_DEPEVT_NO_MORE_RSCS_SHIFT = 12, ++ DWC_DEPEVT_ISOC_TIME_PASSED_BIT = 0x00002000, ++ DWC_DEPEVT_ISOC_TIME_PASSED_SHIFT = 13, ++ ++ /** Event Status for Stream Event */ ++ DWC_DEPEVT_STRM_EVT_BITS = 0x0000f000, ++ DWC_DEPEVT_STRM_EVT_SHIFT = 12, ++ ++ /** Stream Event Status values */ ++ DWC_DEPEVT_STRM_FOUND = 1, /** @< */ ++ DWC_DEPEVT_STRM_NOT_FOUND = 2, ++ ++ /** Event Status for Xfer Complete or Xfer In Progress Event */ ++ DWC_DEPEVT_BUS_ERR_BIT = 0x00001000, ++ DWC_DEPEVT_BUS_ERR_SHIFT = 12, ++ DWC_DEPEVT_SHORT_PKT_BIT = 0x00002000, ++ DWC_DEPEVT_SHORT_PKT_SHIFT = 13, ++ DWC_DEPEVT_IOC_BIT = 0x00004000, ++ DWC_DEPEVT_IOC_SHIFT = 14, ++ DWC_DEPEVT_LST_BIT = 0x00008000, ++ DWC_DEPEVT_LST_SHIFT = 15, ++#define DWC_DEPEVT_MISSED_ISOC_BIT DWC_DEPEVT_LST_BIT ++#define DWC_DEPEVT_MISSED_ISOC_SHIFT DWC_DEPEVT_LST_SHIFT ++ ++ /** Event Status for Xfer Not Ready Event */ ++ DWC_DEPEVT_CTRL_BITS = 0x00003000, ++ DWC_DEPEVT_CTRL_SHIFT = 12, ++ DWC_DEPEVT_XFER_ACTIVE_BIT = 0x00008000, ++ DWC_DEPEVT_XFER_ACTIVE_SHIFT = 15, ++ ++ /** Xfer Not Ready Event Status values */ ++ DWC_DEPEVT_CTRL_SETUP = 0, /** @< */ ++ DWC_DEPEVT_CTRL_DATA = 1, /** @< */ ++ DWC_DEPEVT_CTRL_STATUS = 2, ++ ++ /** Stream ID */ ++ DWC_DEPEVT_STRM_ID_BITS = 0xffff0000, ++ DWC_DEPEVT_STRM_ID_SHIFT = 16, ++ ++ /** Isoc uFrame Number (for Xfer Not Ready on Isoc EP) */ ++ DWC_DEPEVT_ISOC_UFRAME_NUM_BITS = 0xffff0000, ++ DWC_DEPEVT_ISOC_UFRAME_NUM_SHIFT = 16, ++ ++ /** Xfer Resource Index (for Start Xfer Command) */ ++ DWC_DEPEVT_XFER_RSC_IDX_BITS = 0x007f0000, ++ DWC_DEPEVT_XFER_RSC_IDX_SHIFT = 16, ++ ++ /** Current Data Sequence Number (for Get Endpoint State Command) */ ++ DWC_DEPEVT_CUR_DAT_SEQ_NUM_BITS = 0x001f0000, ++ DWC_DEPEVT_CUR_DAT_SEQ_NUM_SHIFT = 16, ++ ++ /** Flow Control State (for Get Endpoint State Command) */ ++ DWC_DEPEVT_FLOW_CTRL_BIT = 0x00200000, ++ DWC_DEPEVT_FLOW_CTRL_SHIFT = 21, ++} depevt_data_t; ++ ++/** ++ * This enum represents the non-generic bit fields of an Event Buffer entry ++ * for other Core events (GEVT). ++ */ ++typedef enum gevt_data { ++ /** PHY Port Number */ ++ DWC_GINT_PHY_PORT_BITS = 0xf00, ++ DWC_GINT_PHY_PORT_SHIFT = 8, ++} gevt_data_t; ++ ++/** ++ * This struct represents the 32-bit register fields of the Event Buffer ++ * Registers (GEVENTBUFn). ++ */ ++typedef struct geventbuf_data { ++ /** Event Buffer Address Register Low Word */ ++ volatile u32 geventadr_lo; ++ ++ /** Event Buffer Address Register High Word */ ++ volatile u32 geventadr_hi; ++ ++ /** Event Buffer Size Register. ++ * Fields defined in enum @ref geventsiz_data. */ ++ volatile u32 geventsiz; ++ ++ /** Event Buffer Count Register. ++ * Fields defined in enum @ref geventcnt_data. */ ++ volatile u32 geventcnt; ++} geventbuf_data_t; ++ ++/** ++ * Core Global Registers Offsets 100h-5FCh. ++ * ++ * The dwc_usb3_core_global_regs structure defines the size ++ * and relative field offsets for the Core Global Registers. ++ */ ++typedef struct dwc_usb3_core_global_regs { ++ ++#define DWC_CORE_GLOBAL_REG_OFFSET 0x100 ++ ++ /** Core BIU Configuration 0 Register Offset: 100h. ++ * Fields defined in enum @ref gsbuscfg0_data. */ ++ volatile u32 gsbuscfg0; ++ ++ /** Core BIU Configuration 1 Register Offset: 104h. ++ * Fields defined in enum @ref gsbuscfg1_data. */ ++ volatile u32 gsbuscfg1; ++ ++ /** Core Tx Threshold Control Register Offset: 108h. ++ * Fields defined in enum @ref gtxthrcfg_data. */ ++ volatile u32 gtxthrcfg; ++ ++ /** Core Threshold Control Register Offset: 10Ch. ++ * Fields defined in enum @ref grxthrcfg_data. */ ++ volatile u32 grxthrcfg; ++ ++ /** Core Control Register Offset: 110h. ++ * Fields defined in enum @ref gctl_data. */ ++ volatile u32 gctl; ++ ++ /** Core Interrupt Mask Register Offset: 114h. ++ * Fields defined in enum @ref gevten_data. */ ++ volatile u32 gevten; ++ ++ /** Core Status Register Offset: 118h. ++ * Fields defined in enum @ref gsts_data. */ ++ volatile u32 gsts; ++ ++ /** Core User Control 1 Register Offset: 11Ch */ ++ volatile u32 guctl1; ++ ++ /** Synopsys ID Register Offset: 120h */ ++ volatile u32 gsnpsid; ++ ++ /** General Purpose I/O Register Offset: 124h */ ++ volatile u32 ggpio; ++ ++ /** User ID Register Offset: 128h */ ++ volatile u32 guid; ++ ++ /** Core User Control Register Offset: 12Ch */ ++ volatile u32 guctl; ++ ++ /** Bus Error Address Register Offset: 130h */ ++ volatile u32 gbuserraddrlo; ++ ++ /** Bus Error Address Register Offset: 134h */ ++ volatile u32 gbuserraddrhi; ++ ++ /** SS Port to Bus Instance Mapping Register Offset: 138h */ ++ volatile u32 gprtbimap_lo; ++ ++ /** SS Port to Bus Instance Mapping Register Offset: 13Ch */ ++ volatile u32 gprtbimap_hi; ++ ++ /** Hardware Parameter 0 Register Offset: 140h. ++ * Fields defined in enum @ref ghwparams0_data. */ ++ volatile u32 ghwparams0; ++ ++ /** Hardware Parameter 1 Register Offset: 144h. ++ * Fields defined in enum @ref ghwparams1_data. */ ++ volatile u32 ghwparams1; ++ ++ /** Hardware Parameter 2 Register Offset: 148h. ++ * Fields defined in enum @ref ghwparams2_data. */ ++ volatile u32 ghwparams2; ++ ++ /** Hardware Parameter 3 Register Offset: 14Ch. ++ * Fields defined in enum @ref ghwparams3_data. */ ++ volatile u32 ghwparams3; ++ ++ /** Hardware Parameter 4 Register Offset: 150h. ++ * Fields defined in enum @ref ghwparams4_data. */ ++ volatile u32 ghwparams4; ++ ++ /** Hardware Parameter 5 Register Offset: 154h. ++ * Fields defined in enum @ref ghwparams5_data. */ ++ volatile u32 ghwparams5; ++ ++ /** Hardware Parameter 6 Register Offset: 158h. ++ * Fields defined in enum @ref ghwparams6_data. */ ++ volatile u32 ghwparams6; ++ ++ /** Hardware Parameter 7 Register Offset: 15Ch. ++ * Fields defined in enum @ref ghwparams7_data. */ ++ volatile u32 ghwparams7; ++ ++ /** Debug Queue/FIFO Space Register Offset: 160h. ++ * Fields defined in enum @ref gdbgfifospace_data. */ ++ volatile u32 gdbgfifospace; ++ ++ /** Debug LTSSM Register Offset: 164h. ++ * Fields defined in enum @ref gdbgltssm_data */ ++ volatile u32 gdbgltssm; ++ ++ /** Debug LNMCC Register Offset: 168h */ ++ volatile u32 gdbglnmcc; ++ ++ /** Debug BMU Register Offset: 16Ch */ ++ volatile u32 gdbgbmu; ++ ++ /** Debug LSP Mux Register Offset: 170h */ ++ volatile u32 gdbglspmux; ++ ++ /** Debug LSP Register Offset: 174h */ ++ volatile u32 gdbglsp; ++ ++ /** Debug EP Info 0 Register Offset: 178h */ ++ volatile u32 gdbgepinfo0; ++ ++ /** Debug EP Info 1 Register Offset: 17Ch */ ++ volatile u32 gdbgepinfo1; ++ ++ /** HS Port to Bus Instance Mapping Register Offset: 180h */ ++ volatile u32 gprtbimap_hs_lo; ++ ++ /** HS Port to Bus Instance Mapping Register Offset: 184h */ ++ volatile u32 gprtbimap_hs_hi; ++ ++ /** FS Port to Bus Instance Mapping Register Offset: 188h */ ++ volatile u32 gprtbimap_fs_lo; ++ ++ /** FS Port to Bus Instance Mapping Register Offset: 18Ch */ ++ volatile u32 gprtbimap_fs_hi; ++ ++ /** reserved Offset: 190h-1BCh */ ++ volatile u32 reserved4[12]; ++ ++ /** Global RMMI PHY Control Register Offset: 1C0h-200h */ ++ volatile u32 gusb3rmmictl[16]; ++ ++ /** USB2 Configuration Registers Offset: 200h-23Ch. ++ * Fields defined in enum @ref gusb2phycfg_data. */ ++ volatile u32 gusb2phycfg[16]; ++ ++ /** USB2 I2C Access Registers Offset: 240h-27Ch. ++ * Fields defined in enum @ref gusb2i2cctl_data. */ ++ volatile u32 gusb2i2cctl[16]; ++ ++ /** USB2 PHY Vendor Control Registers Offset: 280h-2BCh. ++ * Fields defined in enum @ref gusb2phyacc_data. */ ++ volatile u32 gusb2phyacc[16]; ++ ++ /** USB3 Pipe Control Registers Offset: 2C0h-2FCh. ++ * Fields defined in enum @ref gusb3pipectl_data. */ ++ volatile u32 gusb3pipectl[16]; ++ ++ /** Transmit FIFO Size Registers Offset: 300h-37Ch. ++ * Fields defined in enum @ref gfifosize_data. */ ++ volatile u32 gtxfifosiz[32]; ++ ++ /** Receive FIFO Size Registers Offset: 380h-3FC0h. ++ * Fields defined in enum @ref gfifosize_data. */ ++ volatile u32 grxfifosiz[32]; ++ ++ /** Event Buffer Registers Offset: 400h-5FCh. ++ * Fields defined in struct @ref geventbuf_data. */ ++ struct geventbuf_data geventbuf[32]; ++ ++ /** Hardware Parameter 8 Register Offset: 600h. ++ * Fields defined in enum @ref ghwparams8_data. */ ++ volatile u32 ghwparams8; ++} dwc_usb3_core_global_regs_t; ++ ++ ++/****************************************************************************/ ++/* Device Global Registers */ ++ ++/** ++ * This enum represents the bit fields in the Device Configuration ++ * Register (DCFG). ++ */ ++typedef enum dcfg_data { ++ /** Device Speed Access: R_W */ ++ DWC_DCFG_DEVSPD_BITS = 0x000007, ++ DWC_DCFG_DEVSPD_SHIFT = 0, ++ ++ /** Device Speed values */ ++ DWC_SPEED_HS_PHY_30MHZ_OR_60MHZ = 0, /** @< */ ++ DWC_SPEED_FS_PHY_30MHZ_OR_60MHZ = 1, /** @< */ ++ DWC_SPEED_LS_PHY_6MHZ = 2, /** @< */ ++ DWC_SPEED_FS_PHY_48MHZ = 3, /** @< */ ++ DWC_SPEED_SS_PHY_125MHZ_OR_250MHZ = 4, ++ ++ /** Device Address Access: R_W */ ++ DWC_DCFG_DEVADDR_BITS = 0x0003f8, ++ DWC_DCFG_DEVADDR_SHIFT = 3, ++ ++ /** Periodic Frame Interval Access: R_W */ ++ DWC_DCFG_PER_FR_INTVL_BITS = 0x000c00, ++ DWC_DCFG_PER_FR_INTVL_SHIFT = 10, ++ ++ /** Periodic Frame Interval values */ ++ DWC_DCFG_PER_FR_INTVL_80 = 0, /** @< */ ++ DWC_DCFG_PER_FR_INTVL_85 = 1, /** @< */ ++ DWC_DCFG_PER_FR_INTVL_90 = 2, /** @< */ ++ DWC_DCFG_PER_FR_INTVL_95 = 3, ++ ++ /** Device Interrupt Number Access: R_W */ ++ DWC_DCFG_DEV_INTR_NUM_BITS = 0x01f000, ++ DWC_DCFG_DEV_INTR_NUM_SHIFT = 12, ++ ++ /** Number of Receive Buffers Access: R_W */ ++ DWC_DCFG_NUM_RCV_BUF_BITS = 0x3e0000, ++ DWC_DCFG_NUM_RCV_BUF_SHIFT = 17, ++ ++ /** LPM Capable Access: R_W */ ++ DWC_DCFG_LPM_CAP_BIT = 0x400000, ++ DWC_DCFG_LPM_CAP_SHIFT = 22, ++} dcfg_data_t; ++ ++/** ++ * This enum represents the bit fields in the Device Control ++ * Register (DCTL). ++ */ ++typedef enum dctl_data { ++ /** Soft Disconnect Access: R_W */ ++ DWC_DCTL_SFT_DISCONN_BIT = 0x00000001, ++ DWC_DCTL_SFT_DISCONN_SHIFT = 0, ++ ++ /** Test Control Access: R_W */ ++ DWC_DCTL_TSTCTL_BITS = 0x0000001e, ++ DWC_DCTL_TSTCTL_SHIFT = 1, ++ ++ /** USB/Link State Change Request Access: R_W */ ++ DWC_DCTL_ULST_CHNG_REQ_BITS = 0x000001e0, ++ DWC_DCTL_ULST_CHNG_REQ_SHIFT = 5, ++ ++ /** Requested Link State Transition/Action In SS Mode */ ++ DWC_LINK_STATE_REQ_NO_ACTION = 0, /** @< */ ++ DWC_LINK_STATE_REQ_SS_DISABLED = 4, /** @< */ ++ DWC_LINK_STATE_REQ_RX_DETECT = 5, /** @< */ ++ DWC_LINK_STATE_REQ_INACTIVE = 6, /** @< */ ++ DWC_LINK_STATE_REQ_RECOVERY = 8, /** @< */ ++ DWC_LINK_STATE_REQ_COMPLIANCE = 10, /** @< */ ++ DWC_LINK_STATE_REQ_LOOPBACK = 11, /** @< */ ++ DWC_LINK_STATE_REQ_HOST_MODE_ONLY = 15, ++ ++ /** Requested Link State Transition/Action In HS/FS/LS Mode */ ++ DWC_LINK_STATE_REQ_REMOTE_WAKEUP = 8, ++ ++ /** U1/U2 control Access: R_W */ ++ DWC_DCTL_ACCEPT_U1_EN_BIT = 0x00000200, ++ DWC_DCTL_ACCEPT_U1_EN_SHIFT = 9, ++ DWC_DCTL_INIT_U1_EN_BIT = 0x00000400, ++ DWC_DCTL_INIT_U1_EN_SHIFT = 10, ++ DWC_DCTL_ACCEPT_U2_EN_BIT = 0x00000800, ++ DWC_DCTL_ACCEPT_U2_EN_SHIFT = 11, ++ DWC_DCTL_INIT_U2_EN_BIT = 0x00001000, ++ DWC_DCTL_INIT_U2_EN_SHIFT = 12, ++ ++ /** Controller Save State Access: R_W */ ++ DWC_DCTL_CSS_BIT = 0x00010000, ++ DWC_DCTL_CSS_SHIFT = 16, ++ ++ /** Controller Restore State Access: R_W */ ++ DWC_DCTL_CRS_BIT = 0x00020000, ++ DWC_DCTL_CRS_SHIFT = 17, ++ ++ /** L1 Hibernation Enable Access: R_W */ ++ DWC_DCTL_L1_HIBER_EN_BIT = 0x00040000, ++ DWC_DCTL_L1_HIBER_EN_RES_SHIFT = 18, ++ ++ /** Keep Connect (for hibernation) Access: R_W */ ++ DWC_DCTL_KEEP_CONNECT_BIT = 0x00080000, ++ DWC_DCTL_KEEP_CONNECT_SHIFT = 19, ++ ++ /** LPM NYET Response Threshold Access: R_W */ ++ DWC_DCTL_LPM_NYET_THRESH_BITS = 0x00f00000, ++ DWC_DCTL_LPM_NYET_THRESH_SHIFT = 20, ++ ++ /** LPM Response Access: R_W */ ++ DWC_DCTL_APP_L1_RES_BIT = 0x00800000, ++ DWC_DCTL_APP_L1_RES_SHIFT = 23, ++ ++ /* HIRD Threshold Access: R_W */ ++ DWC_DCTL_HIRD_THR_BITS = 0x1f000000, ++ DWC_DCTL_HIRD_THR_SHIFT = 24, ++ ++ /** Light Soft Reset Access: R_W */ ++ DWC_DCTL_LSFT_RST_BIT = 0x20000000, ++ DWC_DCTL_LSFT_RST_SHIFT = 29, ++ ++ /** Core Soft Reset Access: R_W */ ++ DWC_DCTL_CSFT_RST_BIT = 0x40000000, ++ DWC_DCTL_CSFT_RST_SHIFT = 30, ++ ++ /** Run/Stop Access: R_W */ ++ DWC_DCTL_RUN_STOP_BIT = 0x80000000, ++ DWC_DCTL_RUN_STOP_SHIFT = 31, ++} dctl_data_t; ++ ++/** ++ * This enum represents the bit fields of the Device Event Enable ++ * Register (DEVTEN). ++ */ ++typedef enum devten_data { ++ /** Disconnect Detected Event Enable Access: R_W */ ++ DWC_DEVTEN_DISCONN_BIT = 0x0001, ++ DWC_DEVTEN_DISCONN_SHIFT = 0, ++ ++ /** USB Reset Enable Access: R_W */ ++ DWC_DEVTEN_USBRESET_BIT = 0x0002, ++ DWC_DEVTEN_USBRESET_SHIFT = 1, ++ ++ /** Connect Done Enable Access: R_W */ ++ DWC_DEVTEN_CONNDONE_BIT = 0x0004, ++ DWC_DEVTEN_CONNDONE_SHIFT = 2, ++ ++ /** USB/Link State Change Event Enable Access: R_W */ ++ DWC_DEVTEN_ULST_CHNG_BIT = 0x0008, ++ DWC_DEVTEN_ULST_CHNG_SHIFT = 3, ++ ++ /** Resume/Remote-Wakeup Event Enable Access: R_W */ ++ DWC_DEVTEN_WKUP_BIT = 0x0010, ++ DWC_DEVTEN_WKUP_SHIFT = 4, ++ ++ /** Hibernation Request Event Enable Access: R_W */ ++ DWC_DEVTEN_HIBER_REQ_BIT = 0x0020, ++ DWC_DEVTEN_HIBER_REQ_SHIFT = 5, ++ ++ /** End of Periodic Frame Event Enable Access: R_W */ ++ DWC_DEVTEN_U3_L2L1_SUSP_BIT = 0x0040, ++ DWC_DEVTEN_U3_L2L1_SUSP_SHIFT = 6, ++ ++ /** Start of (Micro)Frame Enable Access: R_W */ ++ DWC_DEVTEN_SOF_BIT = 0x0080, ++ DWC_DEVTEN_SOF_SHIFT = 7, ++ ++ /** Erratic Error Event Enable Access: R_W */ ++ DWC_DEVTEN_ERRATICERR_BIT = 0x0200, ++ DWC_DEVTEN_ERRATICERR_SHIFT = 9, ++ ++ /** U2 Inactivity Timeout Enable Access: R_W */ ++ DWC_DEVTEN_INACT_TIMEOUT_BIT = 0x2000, ++ DWC_DEVTEN_INACT_TIMEOUT_SHIFT = 13, ++} devten_data_t; ++ ++/** ++ * This enum represents the bit fields in the Device Status ++ * Register (DSTS). ++ */ ++typedef enum dsts_data { ++ /** Connected Speed Access: RO. ++ * (see enum @ref dcfg_data for values) */ ++ DWC_DSTS_CONNSPD_BITS = 0x00000007, ++ DWC_DSTS_CONNSPD_SHIFT = 0, ++ ++ /** (Micro)Frame Number of Received SOF Access: RO */ ++ DWC_DSTS_SOF_FN_BITS = 0x0001fff8, ++ DWC_DSTS_SOF_FN_SHIFT = 3, ++ ++ /** RX Fifo Empty Access: RO */ ++ DWC_DSTS_RXFIFO_EMPTY_BIT = 0x00020000, ++ DWC_DSTS_RXFIFO_EMPTY_SHIFT = 17, ++ ++ /** USB/Link State Access: RO */ ++ DWC_DSTS_USBLNK_STATE_BITS = 0x003c0000, ++ DWC_DSTS_USBLNK_STATE_SHIFT = 18, ++ ++ /** USB/Link State values same as for devt_data_t */ ++ ++ /** Device Controller Halted Access: RO */ ++ DWC_DSTS_DEV_CTRL_HLT_BIT = 0x00400000, ++ DWC_DSTS_DEV_CTRL_HLT_SHIFT = 22, ++ ++ /** Core Idle Access: RO */ ++ DWC_DSTS_CORE_IDLE_BIT = 0x00800000, ++ DWC_DSTS_CORE_IDLE_SHIFT = 23, ++ ++ /** Save State Status Access: RO */ ++ DWC_DSTS_SSS_BIT = 0x01000000, ++ DWC_DSTS_SSS_SHIFT = 24, ++ ++ /** Restore State Status Access: RO */ ++ DWC_DSTS_RSS_BIT = 0x02000000, ++ DWC_DSTS_RSS_SHIFT = 25, ++ ++ /** Save/Restore Error Access: RO */ ++ DWC_DSTS_SRE_BIT = 0x10000000, ++ DWC_DSTS_SRE_SHIFT = 28, ++ ++ /** Link-state Not Ready Access: RO */ ++ DWC_DSTS_LNR_BIT = 0x20000000, ++ DWC_DSTS_LNR_SHIFT = 29, ++} dsts_data_t; ++ ++/** ++ * This enum represents the bit fields in the Device Generic Command Parameter ++ * Register (DGCMDPARn) for the various commands. ++ */ ++typedef enum dgcmdpar_data { ++ /** Periodic Parameters - for DWC_DGCMD_SET_PERIODIC_PARAMS command */ ++ DWC_DGCMD_PER_PARAM_SEL_BITS = 0x000003ff, ++ DWC_DGCMD_PER_PARAM_SEL_SHIFT = 0, ++ ++ /** Host Role Request - for DWC_DGCMD_XMIT_HOST_ROLE_REQUEST command */ ++ DWC_DGCMDPAR_HOST_ROLE_REQ_BITS = 0x00000003, ++ DWC_DGCMDPAR_HOST_ROLE_REQ_SHIFT = 0, ++ ++ /** RSP Phase values - for DWC_DGCMD_XMIT_HOST_ROLE_REQUEST (older ++ * cores) or DWC_DGCMD_HOST_ROLE_REQ_DEV_NOTIF (newer cores) */ ++ DWC_DGCMDPAR_HOST_ROLE_REQ_INITIATE = 1, /** @< */ ++ DWC_DGCMDPAR_HOST_ROLE_REQ_CONFIRM = 2, ++ ++ /** Notification Type - for DWC_DGCMD_XMIT_DEV_NOTIF command */ ++ DWC_DGCMDPAR_DEV_NOTIF_TYPE_BITS = 0x0000000f, ++ DWC_DGCMDPAR_DEV_NOTIF_TYPE_SHIFT = 0, ++ ++ /** Notification Type values - for DWC_DGCMD_XMIT_DEV_NOTIF command */ ++ DWC_DGCMD_FUNCTION_WAKE_DEV_NOTIF = 1, /** @< */ ++ DWC_DGCMD_LATENCY_TOL_DEV_NOTIF = 2, /** @< */ ++ DWC_DGCMD_BUS_INTVL_ADJ_DEV_NOTIF = 3, /** @< */ ++ DWC_DGCMD_HOST_ROLE_REQ_DEV_NOTIF = 4, ++ ++ /** Notification Parameters - for DWC_DGCMD_XMIT_DEV_NOTIF command */ ++ DWC_DGCMDPAR_DEV_NOTIF_PARAM_BITS = 0xfffffff0, ++ DWC_DGCMDPAR_DEV_NOTIF_PARAM_SHIFT = 4, ++ ++ /** Best Effort Latency Tolerance Value - for ++ * DWC_DGCMD_LATENCY_TOL_DEV_NOTIF command type */ ++ DWC_DGCMDPAR_BELT_VALUE_BITS = 0x000003ff, ++ DWC_DGCMDPAR_BELT_VALUE_SHIFT = 0, ++ ++ /** Best Effort Latency Tolerance Scale - for ++ * DWC_DGCMD_LATENCY_TOL_DEV_NOTIF command type */ ++ DWC_DGCMDPAR_BELT_SCALE_BITS = 0x00000c00, ++ DWC_DGCMDPAR_BELT_SCALE_SHIFT = 10, ++ ++ /** Latency Scale values (ns) */ ++ DWC_LATENCY_VALUE_MULT_1024 = 1, /** @< */ ++ DWC_LATENCY_VALUE_MULT_32768 = 2, /** @< */ ++ DWC_LATENCY_VALUE_MULT_1048576 = 3, ++} dgcmdpar_data_t; ++ ++/** ++ * This enum represents the bit fields in the Device Generic Command ++ * Register (DGCMDn). ++ */ ++typedef enum dgcmd_data { ++ /** Command Type Access: R_W */ ++ DWC_DGCMD_TYP_BITS = 0x0ff, ++ DWC_DGCMD_TYP_SHIFT = 0, ++ ++ /** Command Type values */ ++ DWC_DGCMD_SET_PERIODIC_PARAMS = 2, /** @< */ ++ DWC_DGCMD_XMIT_FUNC_WAKE_DEV_NOTIF = 3, /** @< */ ++ DWC_DGCMD_SET_SCRATCHPAD_ARRAY_ADR_LO = 4, /** @< */ ++ DWC_DGCMD_SET_SCRATCHPAD_ARRAY_ADR_HI = 5, /** @< */ ++ DWC_DGCMD_XMIT_HOST_ROLE_REQUEST = 6, /** @< */ ++ DWC_DGCMD_XMIT_DEV_NOTIF = 7, /** @< */ ++ DWC_DGCMD_SELECTED_FIFO_FLUSH = 9, /** @< */ ++ DWC_DGCMD_ALL_FIFO_FLUSH = 10, /** @< */ ++ DWC_DGCMD_SET_EP_NRDY = 12, /** @< */ ++ DWC_DGCMD_RUN_SOC_BUS_LOOPBK_TST = 16, ++ ++ /** Command Interrupt on Complete Access: R_W */ ++ DWC_DGCMD_IOC_BIT = 0x100, ++ DWC_DGCMD_IOC_SHIFT = 8, ++ ++ /** Command Active Access: R_W */ ++ DWC_DGCMD_ACT_BIT = 0x400, ++ DWC_DGCMD_ACT_SHIFT = 10, ++ ++ /** Command Status Access: R_W */ ++ DWC_DGCMD_STS_BITS = 0xf000, ++ DWC_DGCMD_STS_SHIFT = 12, ++ ++ /** Command Status values */ ++ DWC_DGCMD_STS_ERROR = 15, ++} dgcmd_data_t; ++ ++/** ++ * This enum represents the bit fields in the Device Endpoint Mapping ++ * Registers (DEPMAPn). ++ */ ++typedef enum depmap_data { ++ /** Resource Number Access: R_W / RO */ ++ DWC_EPMAP_RES_NUM_BITS = 0x1f, ++ DWC_EPMAP_RES_NUM_SHIFT = 0, ++} depmap_data_t; ++ ++/** ++ * Device Global Registers Offsets 700h-7FCh. ++ * ++ * The following structures define the size and relative field offsets ++ * for the Device Mode Global Registers. ++ */ ++typedef struct dwc_usb3_dev_global_regs { ++ ++#define DWC_DEV_GLOBAL_REG_OFFSET 0x700 ++ ++ /** Device Configuration Register Offset: 700h. ++ * Fields defined in enum @ref dcfg_data. */ ++ volatile u32 dcfg; ++ ++ /** Device Control Register Offset: 704h. ++ * Fields defined in enum @ref dctl_data. */ ++ volatile u32 dctl; ++ ++ /** Device All Endpoints Interrupt Mask Register Offset: 708h. ++ * Fields defined in enum @ref devten_data. */ ++ volatile u32 devten; ++ ++ /** Device Status Register Offset: 70Ch. ++ * Fields defined in enum @ref dsts_data. */ ++ volatile u32 dsts; ++ ++ /** Device Generic Command Parameter Register Offset: 710h. ++ * Fields defined in enum @ref dgcmdpar_data. */ ++ volatile u32 dgcmdpar; ++ ++ /** Device Generic Command Register Offset: 714h. ++ * Fields defined in enum @ref dgcmd_data. */ ++ volatile u32 dgcmd; ++ ++ /** reserved Offset: 718h-71Ch */ ++ volatile u32 reserved[2]; ++ ++ /** Device Active Logical Endpoint Enable Register Offset: 720h. ++ * One bit per logical endpoint, bit0=EP0 ... bit31=EP31. */ ++ volatile u32 dalepena; ++} dwc_usb3_dev_global_regs_t; ++ ++ ++/****************************************************************************/ ++/* Device Endpoint Specific Registers */ ++ ++/** ++ * This enum represents the bit fields in the Device Endpoint Command ++ * Parameter 1 Register (DEPCMDPAR1n) for the Set Endpoint Configuration ++ * (DEPCFG) command. ++ */ ++typedef enum depcfgpar1_data { ++ /** Interrupt number */ ++ DWC_EPCFG1_INTRNUM_BITS = 0x0000003f, ++ DWC_EPCFG1_INTRNUM_SHIFT = 0, ++ ++ /** Stream Completed */ ++ DWC_EPCFG1_XFER_CMPL_BIT = 0x00000100, ++ DWC_EPCFG1_XFER_CMPL_SHIFT = 8, ++ ++ /** Stream In Progress */ ++ DWC_EPCFG1_XFER_IN_PROG_BIT = 0x00000200, ++ DWC_EPCFG1_XFER_IN_PROG_SHIFT = 9, ++ ++ /** Stream Not Ready */ ++ DWC_EPCFG1_XFER_NRDY_BIT = 0x00000400, ++ DWC_EPCFG1_XFER_NRDY_SHIFT = 10, ++ ++ /** Rx FIFO Underrun / Tx FIFO Overrun */ ++ DWC_EPCFG1_FIFOXRUN_BIT = 0x00000800, ++ DWC_EPCFG1_FIFOXRUN_SHIFT = 11, ++ ++ /** Back-to-Back Setup Packets Received */ ++ DWC_EPCFG1_SETUP_PNDG_BIT = 0x00001000, ++ DWC_EPCFG1_SETUP_PNDG_SHIFT = 12, ++ ++ /** Endpoint Command Complete */ ++ DWC_EPCFG1_EPCMD_CMPL_BIT = 0x00002000, ++ DWC_EPCFG1_EPCMD_CMPL_SHIFT = 13, ++ ++ /** Endpoint EBC Mode */ ++ DWC_EPCFG1_EBC_MODE_BIT = 0x00008000, ++ DWC_EPCFG1_EBC_MODE_SHIFT = 15, ++ ++ /** Endpoint bInterval */ ++ DWC_EPCFG1_BINTERVAL_BITS = 0x00ff0000, ++ DWC_EPCFG1_BINTERVAL_SHIFT = 16, ++ ++ /** Endpoint Stream Capability */ ++ DWC_EPCFG1_STRM_CAP_BIT = 0x01000000, ++ DWC_EPCFG1_STRM_CAP_SHIFT = 24, ++ ++ /** Endpoint Direction */ ++ DWC_EPCFG1_EP_DIR_BIT = 0x02000000, ++ DWC_EPCFG1_EP_DIR_SHIFT = 25, ++ ++ /** Endpoint Number */ ++ DWC_EPCFG1_EP_NUM_BITS = 0x3c000000, ++ DWC_EPCFG1_EP_NUM_SHIFT = 26, ++} depcfgpar1_data_t; ++ ++/** ++ * This enum represents the bit fields in the Device Endpoint Command ++ * Parameter 0 Register (DEPCMDPAR0n) for the Set Endpoint Configuration ++ * (DWC_EPCMD_SET_EP_CFG) command. ++ */ ++typedef enum depcfgpar0_data { ++ /** Endpoint Type Access: R_W */ ++ DWC_EPCFG0_EPTYPE_BITS = 0x00000006, ++ DWC_EPCFG0_EPTYPE_SHIFT = 1, ++ ++ /** Endpoint Type values */ ++ DWC_USB3_EP_TYPE_CONTROL = 0, /** @< */ ++ DWC_USB3_EP_TYPE_ISOC = 1, /** @< */ ++ DWC_USB3_EP_TYPE_BULK = 2, /** @< */ ++ DWC_USB3_EP_TYPE_INTR = 3, ++ ++ /** Maximum Packet Size Access: R_W */ ++ DWC_EPCFG0_MPS_BITS = 0x00003ff8, ++ DWC_EPCFG0_MPS_SHIFT = 3, ++ ++ /** Flow Control State Access: R_W */ ++ DWC_EPCFG0_FLOW_CTRL_STATE_BIT = 0x00010000, ++ DWC_EPCFG0_FLOW_CTRL_STATE_SHIFT = 16, ++ ++ /** Tx Fifo Number (IN endpoints only) Access: R_W */ ++ DWC_EPCFG0_TXFNUM_BITS = 0x003e0000, ++ DWC_EPCFG0_TXFNUM_SHIFT = 17, ++ ++ /** Burst Size Access: R_W */ ++ DWC_EPCFG0_BRSTSIZ_BITS = 0x03c00000, ++ DWC_EPCFG0_BRSTSIZ_SHIFT = 22, ++ ++ /** Data Sequence Num (old) Access: R_W */ ++ DWC_EPCFG0_DSNUM_BITS = 0x7c000000, ++ DWC_EPCFG0_DSNUM_SHIFT = 26, ++ ++ /** Ignore Data Sequence Num (old) Access: R_W */ ++ DWC_EPCFG0_IGN_DSNUM_BIT = 0x80000000, ++ DWC_EPCFG0_IGN_DSNUM_SHIFT = 31, ++ ++ /** Config Action (new) Access: R_W */ ++ DWC_EPCFG0_CFG_ACTION_BITS = 0xc0000000, ++ DWC_EPCFG0_CFG_ACTION_SHIFT = 30, ++ ++ /** Config Action values (new) */ ++ DWC_CFG_ACTION_INIT = 0, /** @< */ ++ DWC_CFG_ACTION_RESTORE = 1, /** @< */ ++ DWC_CFG_ACTION_MODIFY = 2, ++} depcfgpar0_data_t; ++ ++/** ++ * This enum represents the bit fields in the Device Endpoint Command ++ * Register (DEPCMDn). ++ */ ++typedef enum depcmd_data { ++ /** Command Type Access: R_W */ ++ DWC_EPCMD_TYP_BITS = 0x0ff, ++ DWC_EPCMD_TYP_SHIFT = 0, ++ ++ /** Command Type values */ ++ DWC_EPCMD_SET_EP_CFG = 1, /** @< */ ++ DWC_EPCMD_SET_XFER_CFG = 2, /** @< */ ++ DWC_EPCMD_GET_EP_STATE = 3, /** @< */ ++ DWC_EPCMD_SET_STALL = 4, /** @< */ ++ DWC_EPCMD_CLR_STALL = 5, /** @< */ ++ DWC_EPCMD_START_XFER = 6, /** @< */ ++ DWC_EPCMD_UPDATE_XFER = 7, /** @< */ ++ DWC_EPCMD_END_XFER = 8, /** @< */ ++ DWC_EPCMD_START_NEW_CFG = 9, ++ ++ /** Command Interrupt on Complete Access: R_W */ ++ DWC_EPCMD_IOC_BIT = 0x100, ++ DWC_EPCMD_IOC_SHIFT = 8, ++ ++ /** Command Active Access: R_W */ ++ DWC_EPCMD_ACT_BIT = 0x400, ++ DWC_EPCMD_ACT_SHIFT = 10, ++ ++ /** High Priority / Force RM Bit Access: R_W */ ++ DWC_EPCMD_HP_FRM_BIT = 0x800, ++ DWC_EPCMD_HP_FRM_SHIFT = 11, ++ ++ /** Command Completion Status Access: R_W */ ++ DWC_EPCMD_CMPL_STS_BITS = 0xf000, ++ DWC_EPCMD_CMPL_STS_SHIFT = 12, ++ ++ /** Stream Number or uFrame (input) Access: R_W */ ++ DWC_EPCMD_STR_NUM_OR_UF_BITS = 0xffff0000, ++ DWC_EPCMD_STR_NUM_OR_UF_SHIFT = 16, ++ ++ /** Transfer Resource Index (output) Access: R_W */ ++ DWC_EPCMD_XFER_RSRC_IDX_BITS = 0x007f0000, ++ DWC_EPCMD_XFER_RSRC_IDX_SHIFT = 16, ++} depcmd_data_t; ++ ++/** ++ * Device Endpoint Specific Registers Offsets 800h-9ECh for OUT, ++ * 810h-9FCh for IN. ++ * There will be one set of endpoint registers per logical endpoint ++ * implemented. ++ */ ++typedef struct dwc_usb3_dev_ep_regs { ++ ++#define DWC_DEV_OUT_EP_REG_OFFSET 0x800 ++#define DWC_DEV_IN_EP_REG_OFFSET 0x810 ++#define DWC_EP_REG_OFFSET 0x20 ++ ++ /** Device Endpoint Command Parameter 2 Register Offset: 800h/810h + ++ * (ep_num * 20h) + 00h */ ++ volatile u32 depcmdpar2; ++ ++ /** Device Endpoint Command Parameter 1 Register Offset: 800h/810h + ++ * (ep_num * 20h) + 04h */ ++ volatile u32 depcmdpar1; ++ ++ /** Device Endpoint Command Parameter 0 Register Offset: 800h/810h + ++ * (ep_num * 20h) + 08h */ ++ volatile u32 depcmdpar0; ++ ++ /** Device Endpoint Command Register Offset: 800h/810h + ++ * (ep_num * 20h) + 0Ch. ++ * Fields defined in enum @ref depcmd_data. */ ++ volatile u32 depcmd; ++ ++ /** reserved Offset: 800h/810h + ++ * (ep_num * 20h) + 10h-1Ch */ ++ volatile u32 reserved[4]; ++} dwc_usb3_dev_ep_regs_t; ++ ++ ++/****************************************************************************/ ++/* DMA Descriptor Specific Structures */ ++ ++/** ++ * This enum represents the bit fields in the DMA Descriptor ++ * Status quadlet. ++ */ ++typedef enum desc_sts_data { ++ /** Transfer Count */ ++ DWC_DSCSTS_XFRCNT_BITS = 0x00ffffff, ++ DWC_DSCSTS_XFRCNT_SHIFT = 0, ++ ++ /** Packet Count Minus 1 (for HS IN transfers) */ ++ DWC_DSCSTS_PCM1_BITS = 0x03000000, ++ DWC_DSCSTS_PCM1_SHIFT = 24, ++ ++ /** Transfer Request Block Response */ ++ DWC_DSCSTS_TRBRSP_BITS = 0xf0000000, ++ DWC_DSCSTS_TRBRSP_SHIFT = 28, ++ ++ /** Response values */ ++ DWC_TRBRSP_MISSED_ISOC_IN = 1, /** @< */ ++ DWC_TRBRSP_SETUP_PEND = 2, /** @< */ ++ DWC_TRBRSP_XFER_IN_PROG = 4, ++} desc_sts_data_t; ++ ++/** ++ * This enum represents the bit fields in the DMA Descriptor ++ * Control quadlet. ++ */ ++typedef enum desc_ctl_data { ++ /** Hardware-Owned bit */ ++ DWC_DSCCTL_HWO_BIT = 0x00000001, ++ DWC_DSCCTL_HWO_SHIFT = 0, ++ ++ /** Last Descriptor bit */ ++ DWC_DSCCTL_LST_BIT = 0x00000002, ++ DWC_DSCCTL_LST_SHIFT = 1, ++ ++ /** Chain Buffer bit */ ++ DWC_DSCCTL_CHN_BIT = 0x00000004, ++ DWC_DSCCTL_CHN_SHIFT = 2, ++ ++ /** Continue on Short Packet bit */ ++ DWC_DSCCTL_CSP_BIT = 0x00000008, ++ DWC_DSCCTL_CSP_SHIFT = 3, ++ ++ /** Transfer Request Block Control field */ ++ DWC_DSCCTL_TRBCTL_BITS = 0x000003f0, ++ DWC_DSCCTL_TRBCTL_SHIFT = 4, ++ ++ /** Transfer Request Block Control types */ ++ DWC_DSCCTL_TRBCTL_NORMAL = 1, /** @< */ ++ DWC_DSCCTL_TRBCTL_SETUP = 2, /** @< */ ++ DWC_DSCCTL_TRBCTL_STATUS_2 = 3, /** @< */ ++ DWC_DSCCTL_TRBCTL_STATUS_3 = 4, /** @< */ ++ DWC_DSCCTL_TRBCTL_CTLDATA_1ST = 5, /** @< */ ++ DWC_DSCCTL_TRBCTL_ISOC_1ST = 6, /** @< */ ++ DWC_DSCCTL_TRBCTL_ISOC = 7, /** @< */ ++ DWC_DSCCTL_TRBCTL_LINK = 8, ++ ++ /** Interrupt on Short Packet bit */ ++ DWC_DSCCTL_ISP_BIT = 0x00000400, ++ DWC_DSCCTL_ISP_SHIFT = 10, ++#define DWC_DSCCTL_IMI_BIT DWC_DSCCTL_ISP_BIT ++#define DWC_DSCCTL_IMI_SHIFT DWC_DSCCTL_ISP_SHIFT ++ ++ /** Interrupt on Completion bit */ ++ DWC_DSCCTL_IOC_BIT = 0x00000800, ++ DWC_DSCCTL_IOC_SHIFT = 11, ++ ++ /** Stream ID / SOF Number */ ++ DWC_DSCCTL_STRMID_SOFN_BITS = 0x3fffc000, ++ DWC_DSCCTL_STRMID_SOFN_SHIFT = 14, ++} desc_ctl_data_t; ++ ++/** ++ * DMA Descriptor structure ++ * ++ * DMA Descriptor structure contains 4 quadlets: ++ * Buffer Pointer Low address, Buffer Pointer High address, Status, and Control. ++ */ ++typedef struct dwc_usb3_dma_desc { ++ /** Buffer Pointer - Low address quadlet */ ++ u32 bptl; ++ ++ /** Buffer Pointer - High address quadlet */ ++ u32 bpth; ++ ++ /** Status quadlet. Fields defined in enum @ref desc_sts_data. */ ++ u32 status; ++ ++ /** Control quadlet. Fields defined in enum @ref desc_ctl_data. */ ++ u32 control; ++} dwc_usb3_dma_desc_t; ++ ++#ifdef SSIC ++ ++/* SSIC Registers */ ++typedef struct dwc_usb3_ssic_regs { ++ ++#define DWC_SSIC_REG_OFFSET 0xc40 ++ ++ volatile u32 sctl[16]; ++ volatile u32 sevt[16]; ++ volatile u32 sevten[16]; ++ volatile u32 gscfg; ++ volatile u32 gsser; ++ volatile u32 gsdbg; ++} dwc_usb3_ssic_regs_t; ++ ++typedef enum sevten_data { ++ DWC_SEVTEN_ROM_INIT_CMPLT_EN_BIT = 0x00000001, ++ DWC_SEVTEN_ROM_INIT_CMPLT_EN_SHIFT = 0, ++ ++ DWC_SEVTEN_LACC_CMPLT_EN_BIT = 0x00000002, ++ DWC_SEVTEN_LACC_CMPLT_EN_SHIFT = 1, ++ ++ DWC_SEVTEN_RCMD_RES_RCVD_EN_BIT = 0x00000004, ++ DWC_SEVTEN_RCMD_RES_RCVD_EN_SHIFT = 2, ++ ++ DWC_SEVTEN_RCMD_RES_SENT_EN_BIT = 0x00000008, ++ DWC_SEVTEN_RCMD_RES_SENT_EN_SHIFT = 3, ++ ++ DWC_SEVTEN_MPHY_ST_CHNGD_EN_BIT = 0x00000010, ++ DWC_SEVTEN_MPHY_ST_CHNGD_EN_SHIFT = 4, ++ ++ DWC_SEVTEN_OK_STRT_RRAP_EN_BIT = 0x00000020, ++ DWC_SEVTEN_OK_STRT_RRAP_EN_SHIFT = 5, ++ ++ DWC_SEVTEN_RRAP_ERROR_EN_BIT = 0x00000040, ++ DWC_SEVTEN_RRAP_ERROR_EN_SHIFT = 6, ++} sevten_data_t; ++ ++typedef enum sevt_data { ++ DWC_SEVT_ROM_INIT_CMPLT_BIT = 0x00000001, ++ DWC_SEVT_ROM_INIT_CMPLT_SHIFT = 0, ++ ++ DWC_SEVT_LACC_CMPLT_BIT = 0x00000002, ++ DWC_SEVT_LACC_CMPLT_SHIFT = 1, ++ ++ DWC_SEVT_RCMD_RES_RCVD_BIT = 0x00000004, ++ DWC_SEVT_RCMD_RES_RCVD_SHIFT = 2, ++ ++ DWC_SEVT_RCMD_RES_SENT_BIT = 0x00000008, ++ DWC_SEVT_RCMD_RES_SENT_SHIFT = 3, ++ ++ DWC_SEVT_MPHY_ST_CHNG_BIT = 0x00000010, ++ DWC_SEVT_MPHY_ST_CHNG_SHIFT = 4, ++ ++ DWC_SEVT_OK_STRT_RRAP_BIT = 0x00000020, ++ DWC_SEVT_OK_STRT_RRAP_SHIFT = 5, ++ ++ DWC_SEVT_RRAP_ERROR_BIT = 0x00000040, ++ DWC_SEVT_RRAP_ERROR_SHIFT = 6, ++ ++ DWC_SEVT_RACC_RESULT_BITS = 0x00000300, ++ DWC_SEVT_RACC_RESULT_SHIFT = 8, ++ ++ DWC_SEVT_LACC_RESULT_BIT = 0x00000400, ++ DWC_SEVT_LACC_RESULT_SHIFT = 10, ++ ++ DWC_SEVT_READ_RCVD_BIT = 0x00000800, ++ DWC_SEVT_READ_RCVD_SHIFT = 11, ++ ++ DWC_SEVT_RUADDR_RCVD_BITS = 0x0000f000, ++ DWC_SEVT_RUADDR_RCVD_SHIFT = 12, ++ ++ DWC_SEVT_RLADDR_RCVD_BITS = 0x00ff0000, ++ DWC_SEVT_RLADDR_RCVD_SHIFT = 16, ++ ++ DWC_SEVT_RDATA_RCVD_BITS = 0xff000000, ++ DWC_SEVT_RDATA_RCVD_SHIFT = 24, ++} sevt_data_t; ++ ++typedef enum sctl_data { ++ DWC_SCTL_GO_ACC_BIT = 0x00000001, ++ DWC_SCTL_GO_ACC_SHIFT = 0, ++ ++ DWC_SCTL_RACC_BIT = 0x00000002, ++ DWC_SCTL_RACC_SHIFT = 1, ++ ++ DWC_SCTL_RD_WR_N_BIT = 0x00000004, ++ DWC_SCTL_RD_WR_N_SHIFT = 2, ++ ++ DWC_SCTL_BCW_BIT = 0x00000008, ++ DWC_SCTL_BCW_SHIFT = 3, ++ ++ DWC_SCTL_IN_LN_CFG_BIT = 0x00000010, ++ DWC_SCTL_IN_LN_CFG_SHIFT = 4, ++ ++ DWC_SCTL_CFG_DONE_BIT = 0x00000020, ++ DWC_SCTL_CFG_DEON_SHIFT = 5, ++ ++ DWC_SCTL_CBS_ACC_BIT = 0x00000040, ++ DWC_SCTL_CBS_ACC_SHIFT = 6, ++ ++ DWC_SCTL_RXS_ACC_BIT = 0x00000080, ++ DWC_SCTL_RXS_ACC_SHIFT = 7, ++ ++ DWC_SCTL_EAID_BITS = 0x0000f000, ++ DWC_SCTL_EAID_SHIFT = 12, ++ ++ DWC_SCTL_AID_BITS = 0x00ff0000, ++ DWC_SCTL_AID_SHIFT = 16, ++ ++ DWC_SCTL_ADATA_BITS = 0xff000000, ++ DWC_SCTL_ADATA_SHIFT = 24, ++} sctl_data_t; ++ ++#endif /* SSIC */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_USB3_REGS_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc3/linux_defs.h b/drivers/usb/gadget/udc/hiudc3/linux_defs.h +new file mode 100644 +index 0000000..b013072 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/linux_defs.h +@@ -0,0 +1,162 @@ ++#ifndef _DWC_LINUX_DEFS_H_ ++#define _DWC_LINUX_DEFS_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * @file ++ * ++ * This file contains OS-specific includes and definitions. ++ * ++ */ ++ ++#define DWC_DRIVER_VERSION "2.90b - November 2014" ++#define DWC_DRIVER_DESC "SS USB3 Controller driver" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++# include ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) ++# include ++#else ++# include ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) ++# include ++# include ++#else ++# include ++# include ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++# include ++#endif ++ ++# include ++# include ++# include ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ++typedef int gfp_t; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ++# define IRQF_SHARED SA_SHIRQ ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) ++# define DWC_BOS_IN_GADGET ++#endif ++ ++/** @name Error Codes */ ++/** @{ */ ++#define DWC_E_INVALID EINVAL ++#define DWC_E_NO_MEMORY ENOMEM ++#define DWC_E_NO_DEVICE ENODEV ++#define DWC_E_NOT_SUPPORTED EOPNOTSUPP ++#define DWC_E_TIMEOUT ETIMEDOUT ++#define DWC_E_BUSY EBUSY ++#define DWC_E_AGAIN EAGAIN ++#define DWC_E_ABORT ECONNABORTED ++#define DWC_E_SHUTDOWN ESHUTDOWN ++#define DWC_E_NO_DATA ENODATA ++#define DWC_E_DISCONNECT ECONNRESET ++#define DWC_E_UNKNOWN EINVAL ++#define DWC_E_NO_STREAM_RES ENOSR ++#define DWC_E_COMMUNICATION ECOMM ++#define DWC_E_OVERFLOW EOVERFLOW ++#define DWC_E_PROTOCOL EPROTO ++#define DWC_E_IN_PROGRESS EINPROGRESS ++#define DWC_E_PIPE EPIPE ++#define DWC_E_IO EIO ++#define DWC_E_NO_SPACE ENOSPC ++#define DWC_E_DOMAIN EDOM ++/** @} */ ++ ++/** Compiler 'packed' attribute for structs */ ++#define UPACKED __attribute__ ((__packed__)) ++ ++/** @{ */ ++/** Type for DMA addresses */ ++typedef dma_addr_t dwc_dma_t; ++#define DWC_DMA_ADDR_INVALID (~(dwc_dma_t)0) ++/** @} */ ++ ++/** ++ * The number of DMA Descriptors (TRBs) to allocate for each endpoint type. ++ * NOTE: The driver currently supports more than 1 TRB for Isoc EPs only. ++ * So the values for Bulk and Intr must be 1. ++ */ ++#define DWC_NUM_BULK_TRBS 1 ++#define DWC_NUM_INTR_TRBS 1 ++#define DWC_NUM_ISOC_TRBS 256 ++ ++/** ++ * These parameters may be specified when loading the module. They define how ++ * the DWC_usb3 controller should be configured. The parameter values are passed ++ * to the CIL initialization routine dwc_usb3_pcd_common_init(). ++ */ ++typedef struct dwc_usb3_core_params { ++ int burst; ++ int newcore; ++ int phy; ++ int wakeup; ++ int pwrctl; ++ int lpmctl; ++ int phyctl; ++ int usb2mode; ++ int hibernate; ++ int hiberdisc; ++ int clkgatingen; ++ int ssdisquirk; ++ int nobos; ++ int loop; ++ int nump; ++ int newcsr; ++ int rxfsz; ++ int txfsz[16]; ++ int txfsz_cnt; ++ int baseline_besl; ++ int deep_besl; ++ int besl; ++ int ebc; ++} dwc_usb3_core_params_t; ++ ++extern dwc_usb3_core_params_t dwc_usb3_module_params; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_LINUX_DEFS_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc3/linux_dev.h b/drivers/usb/gadget/udc/hiudc3/linux_dev.h +new file mode 100644 +index 0000000..fb30136 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/linux_dev.h +@@ -0,0 +1,165 @@ ++#ifndef _DWC_LINUX_DEV_H_ ++#define _DWC_LINUX_DEV_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ */ ++ ++/** Wrapper function for _handshake(), shows the source line for any failure */ ++#define handshake(_dev_, _ptr_, _mask_, _done_) ({ \ ++ int _retval_ = _handshake(_dev_, _ptr_, _mask_, _done_); \ ++ if (!_retval_) \ ++ dwc_error2(_dev_, "handshake failed in %s():%d\n", \ ++ __func__, __LINE__); \ ++ _retval_; \ ++}) ++ ++/** Takes a usb req pointer and returns the associated pcd req pointer */ ++#define dwc_usb3_get_pcd_req(usbreq) \ ++ container_of((usbreq), dwc_usb3_pcd_req_t, usb_req) ++ ++/** Takes a usb ep pointer and returns the associated pcd ep pointer */ ++#define dwc_usb3_get_pcd_ep(usbep) \ ++ container_of((usbep), dwc_usb3_pcd_ep_t, usb_ep) ++ ++/** @{ */ ++/** ++ * Register read/write. ++ */ ++static inline u32 dwc_rd32(struct dwc_usb3_device *dev, ++ volatile u32 __iomem *adr) ++{ ++ return readl(adr); ++} ++ ++static inline void dwc_wr32(struct dwc_usb3_device *dev, ++ volatile u32 __iomem *adr, u32 val) ++{ ++ writel(val, adr); ++} ++/** @} */ ++ ++/** @{ */ ++/** ++ * Non-sleeping delays. ++ */ ++#define dwc_udelay(dev, us) udelay(us) ++#define dwc_mdelay(dev, ms) mdelay(ms) ++/** @} */ ++ ++/** ++ * Sleeping delay. ++ */ ++#define dwc_msleep(dev, ms) msleep(ms) ++ ++/** ++ * Debugging support - vanishes in non-debug builds. ++ */ ++ ++/** Prefix string for print macros. */ ++#define USB3_DWC "dwc_usb3: " ++#ifdef DEBUG ++//# define dwc_debug(dev, x...) printk(KERN_DEBUG USB3_DWC x ) ++# define dwc_debug(dev, x...) printk(KERN_ERR USB3_DWC x ) ++#else ++# define dwc_debug(dev, x...) printk(KERN_ERR USB3_DWC x ) ++//# define dwc_debug(dev, x...) do {} while (0) ++#endif /* DEBUG */ ++ ++# define dwc_debug0(dev, fmt) dwc_debug(dev, fmt) ++# define dwc_debug1(dev, fmt, a) dwc_debug(dev, fmt, a) ++# define dwc_debug2(dev, fmt, a, b) dwc_debug(dev, fmt, a, b) ++# define dwc_debug3(dev, fmt, a, b, c) dwc_debug(dev, fmt, a, b, c) ++# define dwc_debug4(dev, fmt, a, b, c, d) dwc_debug(dev, fmt, a, b, c, d) ++# define dwc_debug5(dev, fmt, a, b, c, d, e) \ ++ dwc_debug(dev, fmt, a, b, c, d, e) ++# define dwc_debug6(dev, fmt, a, b, c, d, e, f) \ ++ dwc_debug(dev, fmt, a, b, c, d, e, f) ++# define dwc_debug7(dev, fmt, a, b, c, d, e, f, g) \ ++ dwc_debug(dev, fmt, a, b, c, d, e, f, g) ++# define dwc_debug8(dev, fmt, a, b, c, d, e, f, g, h) \ ++ dwc_debug(dev, fmt, a, b, c, d, e, f, g, h) ++# define dwc_debug9(dev, fmt, a, b, c, d, e, f, g, h, i) \ ++ dwc_debug(dev, fmt, a, b, c, d, e, f, g, h, i) ++# define dwc_debug10(dev, fmt, a, b, c, d, e, f, g, h, i, j) \ ++ dwc_debug(dev, fmt, a, b, c, d, e, f, g, h, i, j) ++ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++# define dwc_isocdbg(dev, x...) printk(USB3_DWC x ) ++#else ++# define dwc_isocdbg(dev, x...) do {} while (0) ++#endif ++ ++# define dwc_isocdbg0(dev, fmt) dwc_isocdbg(dev, fmt) ++# define dwc_isocdbg1(dev, fmt, a) dwc_isocdbg(dev, fmt, a) ++# define dwc_isocdbg2(dev, fmt, a, b) dwc_isocdbg(dev, fmt, a, b) ++# define dwc_isocdbg3(dev, fmt, a, b, c) dwc_isocdbg(dev, fmt, a, b, c) ++# define dwc_isocdbg4(dev, fmt, a, b, c, d) \ ++ dwc_isocdbg(dev, fmt, a, b, c, d) ++# define dwc_isocdbg5(dev, fmt, a, b, c, d, e) \ ++ dwc_isocdbg(dev, fmt, a, b, c, d, e) ++# define dwc_isocdbg6(dev, fmt, a, b, c, d, e, f) \ ++ dwc_isocdbg(dev, fmt, a, b, c, d, e, f) ++ ++/** ++ * Print an Error message. ++ */ ++#define dwc_error(dev, x...) printk(KERN_ERR USB3_DWC x ) ++ ++#define dwc_error0(dev, fmt) dwc_error(dev, fmt) ++#define dwc_error1(dev, fmt, a) dwc_error(dev, fmt, a) ++#define dwc_error2(dev, fmt, a, b) dwc_error(dev, fmt, a, b) ++#define dwc_error3(dev, fmt, a, b, c) dwc_error(dev, fmt, a, b, c) ++#define dwc_error4(dev, fmt, a, b, c, d) dwc_error(dev, fmt, a, b, c, d) ++ ++/** ++ * Print a Warning message. ++ */ ++#define dwc_warn(dev, x...) printk(KERN_WARNING USB3_DWC x ) ++ ++#define dwc_warn0(dev, fmt) dwc_warn(dev, fmt) ++#define dwc_warn1(dev, fmt, a) dwc_warn(dev, fmt, a) ++#define dwc_warn2(dev, fmt, a, b) dwc_warn(dev, fmt, a, b) ++#define dwc_warn3(dev, fmt, a, b, c) dwc_warn(dev, fmt, a, b, c) ++#define dwc_warn4(dev, fmt, a, b, c, d) dwc_warn(dev, fmt, a, b, c, d) ++ ++/** ++ * Print an Informational message (normal but significant). ++ */ ++#define dwc_info(dev, x...) printk(KERN_INFO USB3_DWC x ) ++ ++#define dwc_info0(dev, fmt) dwc_info(dev, fmt) ++#define dwc_info1(dev, fmt, a) dwc_info(dev, fmt, a) ++#define dwc_info2(dev, fmt, a, b) dwc_info(dev, fmt, a, b) ++#define dwc_info3(dev, fmt, a, b, c) dwc_info(dev, fmt, a, b, c) ++#define dwc_info4(dev, fmt, a, b, c, d) dwc_info(dev, fmt, a, b, c, d) ++ ++/** ++ * Basic message printing. ++ */ ++#define dwc_print(dev, x...) 0 ++//#define dwc_print(dev, x...) printk(USB3_DWC x ) ++ ++#define dwc_print0(dev, fmt) dwc_print(dev, fmt) ++#define dwc_print1(dev, fmt, a) dwc_print(dev, fmt, a) ++#define dwc_print2(dev, fmt, a, b) dwc_print(dev, fmt, a, b) ++#define dwc_print3(dev, fmt, a, b, c) dwc_print(dev, fmt, a, b, c) ++#define dwc_print4(dev, fmt, a, b, c, d) dwc_print(dev, fmt, a, b, c, d) ++#define dwc_print5(dev, fmt, a, b, c, d, e) \ ++ dwc_print(dev, fmt, a, b, c, d, e) ++ ++extern int dwc_usb3_gadget_init(struct dwc_usb3_device *usb3_dev, struct device *dev); ++extern void dwc_usb3_gadget_remove(struct dwc_usb3_device *usb3_dev, struct device *dev); ++extern int dwc_usb3_create_dev_files(struct device *dev); ++extern void dwc_usb3_remove_dev_files(struct device *dev); ++extern int dwc_usb3_wakeup(struct usb_gadget *gadget); ++extern int dwc_wait_pme_thread(void *data); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_LINUX_DEV_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc3/linux_gadget.c b/drivers/usb/gadget/udc/hiudc3/linux_gadget.c +new file mode 100644 +index 0000000..d6e2656 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/linux_gadget.c +@@ -0,0 +1,2693 @@ ++/** @file ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++ ++#ifdef DWC_UTE ++# include "ute_if.h" ++#endif ++ ++#ifdef CONFIG_USB_OTG_DWC ++extern void dwc_otg3_set_peripheral(struct usb_otg *otg, int yes); ++extern int otg_host_release(struct usb_otg *otg); ++extern int otg_start_rsp(struct usb_otg *otg); ++#endif ++ ++#define dwc_wait_if_hibernating(_pcd_, _flags_) \ ++{ \ ++ int _temp_ = (_pcd_)->usb3_dev->hibernate; \ ++ while (_temp_ >= DWC_HIBER_SLEEPING && \ ++ _temp_ != DWC_HIBER_WAIT_U0 && \ ++ _temp_ != DWC_HIBER_SS_DIS_QUIRK) { \ ++ spin_unlock_irqrestore(&(_pcd_)->lock, (_flags_)); \ ++ msleep(1); \ ++ spin_lock_irqsave(&(_pcd_)->lock, (_flags_)); \ ++ _temp_ = (_pcd_)->usb3_dev->hibernate; \ ++ } \ ++} ++ ++/** ++ * NOTE: These strings MUST reflect the number and type of endpoints that the ++ * core was configured with in CoreConsultant, and their intended usage. In ++ * particular, the type (bulk/int/iso) determines how many TRBs will be ++ * allocated for each endpoint. See gadget_init_eps() and trb_alloc() below. ++ * ++ * Naming convention is described in drivers/usb/gadget/epautoconf.c ++ */ ++#if 0 ++static const char *g_ep_names[] = { "ep0", "ep1out", "ep1in", "ep2out", ++ "ep2in", "ep3out", "ep3in", "ep4out", "ep4in", "ep5out", "ep5in", ++ "ep6out", "ep6in", "ep7out", "ep7in", "ep8out", "ep8in", "ep9out", ++ "ep9in", "ep10out", "ep10in", "ep11out", "ep11in", "ep12out", "ep12in", ++ "ep13out", "ep13in", "ep14out", "ep14in", "ep15out", "ep15in" }; ++#endif ++#if 0 ++static const char *g_ep_names[] = { "ep0", "ep1out", "ep1in", "ep2out", ++ "ep3in", "ep2in", "ep4in", "ep4out", "ep5out", "ep5in", ++ "ep6out", "ep6in", "ep7out", "ep7in", "ep8out", "ep8in", "ep9out", ++ "ep9in", "ep10out", "ep10in", "ep11out", "ep11in", "ep12out", "ep12in", ++ "ep13out", "ep13in", "ep14out", "ep14in", "ep15out", "ep15in" }; ++#endif ++static const char *g_ep_names[] = { "ep0", "ep1out", "ep1in", "ep2out", ++ "ep2in", "ep3in", "ep4in", "ep4out", "ep4in", "ep5out", "ep5in", ++ "ep6out", "ep6in", "ep7out", "ep7in", "ep8out", "ep8in", "ep9out", ++ "ep9in", "ep10out", "ep10in", "ep11out", "ep11in", "ep12out", "ep12in", ++ "ep13out", "ep13in", "ep14out", "ep14in", "ep15out", "ep15in" }; ++/*========================================================================*/ ++/* ++ * Linux Gadget API related functions ++ */ ++ ++/* Gadget wrapper */ ++ ++static struct gadget_wrapper { ++ dwc_usb3_pcd_t *pcd; ++ ++ char ep_names[DWC_MAX_EPS * 2 - 1][16]; ++ ++ struct usb_gadget gadget; ++ struct usb_gadget_driver *driver; ++ ++ dwc_usb3_pcd_req_t ep0_req; ++ ++ dwc_usb3_pcd_ep_t ep0; ++ dwc_usb3_pcd_ep_t out_ep[DWC_MAX_EPS - 1]; ++ dwc_usb3_pcd_ep_t in_ep[DWC_MAX_EPS - 1]; ++} *gadget_wrapper; ++ ++ ++/** ++ * Passes a Setup request to the Gadget driver ++ */ ++static int gadget_setup(dwc_usb3_pcd_t *pcd, void *data) ++{ ++ int retval = -DWC_E_NOT_SUPPORTED; ++ ++ dwc_debug(pcd->usb3_dev, "%s()\n", __func__); ++ ++ if (!gadget_wrapper) { ++ dwc_warn(pcd->usb3_dev, "%s null wrapper!\n", __func__); ++ return -DWC_E_INVALID; ++ } ++ ++ if (gadget_wrapper->driver && gadget_wrapper->driver->setup) { ++ spin_unlock(&pcd->lock); ++ retval = gadget_wrapper->driver->setup(&gadget_wrapper->gadget, ++ (struct usb_ctrlrequest *)data); ++ spin_lock(&pcd->lock); ++ if (retval == -ENOTSUPP) ++ retval = -DWC_E_NOT_SUPPORTED; ++ else if (retval < 0) ++ retval = -DWC_E_INVALID; ++ } ++ ++ return retval; ++} ++ ++/***************************************************************************** ++ * Gadget notification functions ++ * ++ * These functions receive notifications from the PCD when certain events ++ * occur which the Gadget must be aware of. ++ * ++ * These functions *must* have the exact names and parameters shown here, ++ * since they are part of the API between the PCD and the Gadget. ++ * ++ *****************************************************************************/ ++ ++/** ++ * This function receives Connect notifications from the PCD ++ */ ++int dwc_usb3_gadget_connect(dwc_usb3_pcd_t *pcd, int speed) ++{ ++ dwc_debug(pcd->usb3_dev, "%s()\n", __func__); ++ ++ if (!gadget_wrapper) { ++ dwc_warn(pcd->usb3_dev, "%s null wrapper!\n", __func__); ++ return -DWC_E_INVALID; ++ } ++ ++ gadget_wrapper->gadget.speed = speed; ++ pcd->ep0->usb_ep.maxpacket = pcd->ep0->dwc_ep.maxpacket; ++ ++ return 0; ++} ++ ++/** ++ * This function receives Disconnect notifications from the PCD ++ */ ++int dwc_usb3_gadget_disconnect(dwc_usb3_pcd_t *pcd) ++{ ++ dwc_debug(pcd->usb3_dev, "%s()\n", __func__); ++ ++ if (!gadget_wrapper) { ++ dwc_warn(pcd->usb3_dev, "%s null wrapper!\n", __func__); ++ return -DWC_E_INVALID; ++ } ++ ++ if (gadget_wrapper->driver && gadget_wrapper->driver->disconnect) { ++ spin_unlock(&pcd->lock); ++ gadget_wrapper->driver->disconnect(&gadget_wrapper->gadget); ++ spin_lock(&pcd->lock); ++ } ++ ++ return 0; ++} ++ ++/** ++ * This function receives Setup request notifications from the PCD ++ */ ++int dwc_usb3_gadget_setup(dwc_usb3_pcd_t *pcd, usb_device_request_t *ctrl) ++{ ++ int ret; ++ ++ dwc_debug(pcd->usb3_dev, "%s()\n", __func__); ++ ++ ret = gadget_setup(pcd, ctrl); ++ ++ /* @todo This is a g_file_storage gadget driver specific ++ * workaround: a DELAYED_STATUS result from the fsg_setup ++ * routine will result in the gadget queueing a EP0 IN status ++ * phase for a two-stage control transfer. Exactly the same as ++ * a SET_CONFIGURATION/SET_INTERFACE except that this is a class ++ * specific request. Need a generic way to know when the gadget ++ * driver will queue the status phase. Can we assume when we ++ * call the gadget driver setup() function that it will always ++ * queue and require the following flag? Need to look into ++ * this. ++ */ ++ if (ret >= 256 + 999) ++ pcd->request_config = 1; ++ ++ return ret; ++} ++ ++/** ++ * This function receives Suspend notifications from the PCD ++ */ ++int dwc_usb3_gadget_suspend(dwc_usb3_pcd_t *pcd) ++{ ++ dwc_debug(pcd->usb3_dev, "%s()\n", __func__); ++ ++ if (!gadget_wrapper) { ++ dwc_warn(pcd->usb3_dev, "%s null wrapper!\n", __func__); ++ return -DWC_E_INVALID; ++ } ++ ++ if (gadget_wrapper->driver && gadget_wrapper->driver->suspend) { ++ spin_unlock(&pcd->lock); ++ gadget_wrapper->driver->suspend(&gadget_wrapper->gadget); ++ spin_lock(&pcd->lock); ++ } ++ ++ return 0; ++} ++ ++/** ++ * This function receives Resume notifications from the PCD ++ */ ++int dwc_usb3_gadget_resume(dwc_usb3_pcd_t *pcd) ++{ ++ dwc_debug(pcd->usb3_dev, "%s()\n", __func__); ++ ++ if (!gadget_wrapper) { ++ dwc_warn(pcd->usb3_dev, "%s null wrapper!\n", __func__); ++ return -DWC_E_INVALID; ++ } ++ ++ if (gadget_wrapper->driver && gadget_wrapper->driver->resume) { ++ spin_unlock(&pcd->lock); ++ gadget_wrapper->driver->resume(&gadget_wrapper->gadget); ++ spin_lock(&pcd->lock); ++ } ++ ++ return 0; ++} ++ ++static void map_buffers(struct device *dev, struct usb_request *usb_req, ++ dwc_usb3_pcd_ep_t *pcd_ep, int *req_flags) ++{ ++ if (dwc_usb3_pcd_ep_is_in(pcd_ep)) { ++# ifdef DWC_TEST_ISOC_CHAIN ++ if (dwc_usb3_pcd_ep_type(pcd_ep) == UE_ISOCHRONOUS) { ++ if (usb_req->length > 58 && usb_req->buf2[0]) { ++ usb_req->dma2[0] = dma_map_single(dev, ++ usb_req->buf2[0], 29, DMA_TO_DEVICE); ++ } ++ if (usb_req->length > 58) { ++ usb_req->dma = dma_map_single(dev, usb_req->buf, ++ usb_req->length - 58, DMA_TO_DEVICE); ++ } else { ++ usb_req->dma = dma_map_single(dev, usb_req->buf, ++ usb_req->length, DMA_TO_DEVICE); ++ } ++ if (usb_req->length > 58 && usb_req->buf2[1]) { ++ usb_req->dma2[1] = dma_map_single(dev, ++ usb_req->buf2[1], 29, DMA_TO_DEVICE); ++ } ++ } else ++# endif ++ usb_req->dma = dma_map_single(dev, usb_req->buf, ++ usb_req->length, DMA_TO_DEVICE); ++ *req_flags |= DWC_PCD_REQ_MAP_DMA | DWC_PCD_REQ_IN; ++ } else { ++# ifdef DWC_TEST_ISOC_CHAIN ++ if (dwc_usb3_pcd_ep_type(pcd_ep) == UE_ISOCHRONOUS) { ++ if (usb_req->length > 58 && usb_req->buf2[0]) { ++ usb_req->dma2[0] = dma_map_single(dev, ++ usb_req->buf2[0], 29, DMA_FROM_DEVICE); ++ } ++ if (usb_req->length > 58) { ++ usb_req->dma = dma_map_single(dev, usb_req->buf, ++ usb_req->length - 58, DMA_FROM_DEVICE); ++ } else { ++ usb_req->dma = dma_map_single(dev, usb_req->buf, ++ usb_req->length, DMA_FROM_DEVICE); ++ } ++ if (usb_req->length > 58 && usb_req->buf2[1]) { ++ usb_req->dma2[1] = dma_map_single(dev, ++ usb_req->buf2[1], 29, DMA_FROM_DEVICE); ++ } ++ } else ++# endif ++ usb_req->dma = dma_map_single(dev, usb_req->buf, ++ usb_req->length, DMA_FROM_DEVICE); ++ *req_flags |= DWC_PCD_REQ_MAP_DMA; ++ } ++} ++ ++static void unmap_buffers(struct device *dev, struct usb_request *usb_req, ++ dwc_usb3_pcd_ep_t *pcd_ep, int *req_flags) ++{ ++ if (*req_flags & DWC_PCD_REQ_IN) { ++# ifdef DWC_TEST_ISOC_CHAIN ++ if (dwc_usb3_pcd_ep_type(pcd_ep) == UE_ISOCHRONOUS) { ++ if (usb_req->dma2[1] != DWC_DMA_ADDR_INVALID) { ++ dma_unmap_single(dev, usb_req->dma2[1], 29, ++ DMA_TO_DEVICE); ++ } ++ if (usb_req->dma2[1] != DWC_DMA_ADDR_INVALID || ++ usb_req->dma2[0] != DWC_DMA_ADDR_INVALID) { ++ dma_unmap_single(dev, usb_req->dma, ++ usb_req->length - 58, DMA_TO_DEVICE); ++ } else { ++ dma_unmap_single(dev, usb_req->dma, ++ usb_req->length, DMA_TO_DEVICE); ++ } ++ if (usb_req->dma2[0] != DWC_DMA_ADDR_INVALID) { ++ dma_unmap_single(dev, usb_req->dma2[0], 29, ++ DMA_TO_DEVICE); ++ } ++ } else ++# endif ++ dma_unmap_single(dev, usb_req->dma, usb_req->length, ++ DMA_TO_DEVICE); ++ } else { ++# ifdef DWC_TEST_ISOC_CHAIN ++ if (dwc_usb3_pcd_ep_type(pcd_ep) == UE_ISOCHRONOUS) { ++ if (usb_req->dma2[1] != DWC_DMA_ADDR_INVALID) { ++ dma_unmap_single(dev, usb_req->dma2[1], 29, ++ DMA_FROM_DEVICE); ++ } ++ if (usb_req->dma2[1] != DWC_DMA_ADDR_INVALID || ++ usb_req->dma2[0] != DWC_DMA_ADDR_INVALID) { ++ dma_unmap_single(dev, usb_req->dma, ++ usb_req->length - 58, DMA_FROM_DEVICE); ++ } else { ++ dma_unmap_single(dev, usb_req->dma, ++ usb_req->length, DMA_FROM_DEVICE); ++ } ++ if (usb_req->dma2[0] != DWC_DMA_ADDR_INVALID) { ++ dma_unmap_single(dev, usb_req->dma2[0], 29, ++ DMA_FROM_DEVICE); ++ } ++ } else ++# endif ++ dma_unmap_single(dev, usb_req->dma, usb_req->length, ++ DMA_FROM_DEVICE); ++ } ++ ++ *req_flags &= ~(DWC_PCD_REQ_MAP_DMA | DWC_PCD_REQ_IN); ++ ++# ifdef DWC_TEST_ISOC_CHAIN ++ usb_req->dma2[0] = DWC_DMA_ADDR_INVALID; ++ usb_req->dma2[1] = DWC_DMA_ADDR_INVALID; ++# endif ++ usb_req->dma = DWC_DMA_ADDR_INVALID; ++} ++ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++static void dbg_databuf(dwc_usb3_pcd_t *pcd, struct usb_request *usb_req, ++ dwc_usb3_pcd_ep_t *pcd_ep, u32 actual, ++ dma_addr_t dma ++#ifdef DWC_TEST_ISOC_CHAIN ++ , dma_addr_t dma2[2] ++#endif ++ ) ++{ ++ if (dwc_usb3_pcd_ep_type(pcd_ep) == UE_ISOCHRONOUS) { ++ unsigned char *buf = (unsigned char *)usb_req->buf; ++# ifdef DWC_TEST_ISOC_CHAIN ++ unsigned char *buf0 = (unsigned char *)usb_req->buf2[0]; ++ unsigned char *buf1 = (unsigned char *)usb_req->buf2[1]; ++# endif ++ if (buf) { ++ if (actual >= 4) { ++# ifdef DWC_TEST_ISOC_CHAIN ++ dwc_isocdbg(pcd->usb3_dev, ++ "%p %1lx %1lx %1lx bdata: %02x %02x %02x " ++ "%02x .. %02x %02x %02x %02x .. %02x " ++ "%02x %02x %02x\n", ++ buf, ++ (unsigned long)dma, ++ (unsigned long)dma2[0], ++ (unsigned long)dma2[1], ++ buf[0], buf[1], buf[2], buf[3], ++ buf0[0], buf0[1], buf0[2], buf0[3], ++ buf1[0], buf1[1], buf1[2], buf1[3]); ++# else ++ dwc_isocdbg(pcd->usb3_dev, ++ "%p %1lx bdata: %02x %02x %02x %02x\n", ++ buf, ++ (unsigned long)dma, ++ buf[0], buf[1], buf[2], buf[3]); ++# endif ++ } else if (actual > 0) { ++ dwc_isocdbg(pcd->usb3_dev, ++ "%p %1lx bdata: %02x ...\n", ++ buf, ++ (unsigned long)dma, buf[0]); ++ } else { ++ dwc_isocdbg(pcd->usb3_dev, ++ "%p %1lx bdata: 0-len!\n", ++ buf, ++ (unsigned long)dma); ++ } ++ } else { ++ dwc_isocdbg(pcd->usb3_dev, "bdata: buf NULL!\n"); ++ } ++ } ++} ++#endif ++ ++/** ++ * This function receives Transfer Complete notifications from the PCD ++ */ ++int dwc_usb3_gadget_complete(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *pcd_ep, ++ dwc_usb3_pcd_req_t *pcd_req, int status) ++{ ++ struct usb_ep *usb_ep = &pcd_ep->usb_ep; ++ struct usb_request *usb_req = &pcd_req->usb_req; ++ u32 actual = pcd_req->dwc_req.actual; ++ int *req_flags = &pcd_req->dwc_req.flags; ++ dma_addr_t dma; ++#ifdef DWC_TEST_ISOC_CHAIN ++ dma_addr_t dma2[2]; ++#endif ++ ++ /* Remove the request from the queue */ ++ list_del_init(&pcd_req->entry); ++ ++ /* Save DMA address for debug */ ++ dma = usb_req->dma; ++#ifdef DWC_TEST_ISOC_CHAIN ++ dma2[0] = usb_req->dma2[0]; ++ dma2[1] = usb_req->dma2[1]; ++#endif ++ ++ /* Unmap DMA */ ++ if (*req_flags & DWC_PCD_REQ_MAP_DMA) { ++ dwc_debug(pcd->usb3_dev, "DMA unmap req %p\n", usb_req); ++ unmap_buffers(pcd->usb3_dev->dev, usb_req, pcd_ep, req_flags); ++ } ++ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ dbg_databuf(pcd, usb_req, pcd_ep, actual, dma ++# ifdef DWC_TEST_ISOC_CHAIN ++ , dma2 ++# endif ++ ); ++#endif ++ ++ if (usb_req->complete) { ++ usb_req->status = status; ++ usb_req->actual = actual; ++ spin_unlock(&pcd->lock); ++ usb_req->complete(usb_ep, usb_req); ++ spin_lock(&pcd->lock); ++ } ++ ++ if (pcd->request_pending > 0) ++ --pcd->request_pending; ++ ++ return 0; ++} ++ ++/** ++ * This function allows overriding the standard Control transfer handling ++ * (currently only done by the axs101 test gadget) ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ */ ++void dwc_usb3_gadget_do_setup(dwc_usb3_pcd_t *pcd) ++{ ++ /* Call the standard Control transfer handler */ ++ dwc_usb3_pcd_do_setup(pcd); ++} ++ ++/* ++ * Gadget EP ops ++ */ ++ ++/** ++ * This function fills in an I/O Request for an EP. ++ */ ++static void fill_req(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep, ++ dwc_usb3_pcd_req_t *req, int numbuf, char **buf, ++ dwc_dma_t *bufdma, u32 *buflen, u32 stream, int req_flags) ++{ ++ int i; ++ ++ dwc_debug(pcd->usb3_dev, "req_flags=0x%1x\n", req_flags); ++ ++ req->dwc_req.length = 0; ++ req->dwc_req.numbuf = numbuf; ++ ++ for (i = 0; i < numbuf; i++) { ++ req->dwc_req.buf[i] = buf[i]; ++ req->dwc_req.bufdma[i] = bufdma[i]; ++ req->dwc_req.buflen[i] = buflen[i]; ++ req->dwc_req.length += buflen[i]; ++ } ++ ++ req->dwc_req.actual = 0; ++ req->dwc_req.stream = stream; ++ req->dwc_req.flags = req_flags; ++ ++ /* For EP0 IN without premature status, zlp is required? */ ++ if (ep == pcd->ep0 && ep->dwc_ep.is_in) { ++ dwc_debug(pcd->usb3_dev, "%d-OUT ZLP\n", ep->dwc_ep.num); ++ //req->dwc_req.flags |= DWC_PCD_REQ_ZERO; ++ } ++} ++ ++/** ++ * This function enables an EP ++ */ ++static int ep_enable(struct usb_ep *usb_ep, ++ const struct usb_endpoint_descriptor *ep_desc) ++{ ++ dwc_usb3_pcd_ep_t *pcd_ep; ++ dwc_usb3_pcd_t *pcd; ++ dwc_usb3_dma_desc_t *desc; ++ dma_addr_t desc_dma; ++ int num, dir, type, num_trbs, maxpacket, link; ++ int retval = 0; ++ unsigned long flags; ++ ss_endpoint_companion_descriptor_t ep_comp = { 0, }; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) ++ int maxstreams = 0, mult = 0, maxburst = 0; ++#endif ++ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ printk(KERN_DEBUG USB3_DWC "%s(%p,%p)\n", __func__, usb_ep, ep_desc); ++#endif ++ if (!gadget_wrapper) { ++ printk(KERN_WARNING USB3_DWC "%s null wrapper!\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (!usb_ep || !ep_desc || ++ ep_desc->bDescriptorType != USB_DT_ENDPOINT) { ++ printk(KERN_WARNING USB3_DWC ++ "%s, bad ep or descriptor %p %p %d!\n", ++ __func__, usb_ep, ep_desc, ++ ep_desc ? ep_desc->bDescriptorType : 0); ++ return -EINVAL; ++ } ++ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ printk(USB3_DWC "usb_ep->name = %s\n", usb_ep->name); ++#endif ++ if (usb_ep == &gadget_wrapper->ep0.usb_ep) { ++ printk(KERN_WARNING USB3_DWC "%s called for EP0!\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (!ep_desc->wMaxPacketSize) { ++ printk(KERN_WARNING USB3_DWC "%s, zero %s wMaxPacketSize!\n", ++ __func__, usb_ep->name); ++ return -ERANGE; ++ } ++ ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ printk(KERN_WARNING USB3_DWC "%s, bogus device state!\n", ++ __func__); ++ return -ESHUTDOWN; ++ } ++ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ printk(KERN_DEBUG USB3_DWC "usb_ep->maxpacket = %d\n", ++ le16_to_cpu(ep_desc->wMaxPacketSize)); ++#endif ++ pcd = gadget_wrapper->pcd; ++ pcd_ep = dwc_usb3_get_pcd_ep(usb_ep); ++ ++ if (pcd_ep->dwc_ep.phys >= DWC_MAX_PHYS_EP) { ++ dwc_warn(pcd->usb3_dev, "%s, bad %s phys EP # %d!\n", ++ __func__, usb_ep->name, pcd_ep->dwc_ep.phys); ++ return -ERANGE; ++ } ++ ++ /* Free any existing TRB allocation for this EP */ ++ dwc_usb3_pcd_trb_free(pcd_ep); ++ ++ num = UE_GET_ADDR(ep_desc->bEndpointAddress); ++ dir = UE_GET_DIR(ep_desc->bEndpointAddress); ++ type = UE_GET_XFERTYPE(ep_desc->bmAttributes); ++ link = 0; ++ ++ /* Allocate the number of TRBs based on EP type */ ++ switch (type) { ++ case UE_INTERRUPT: ++ num_trbs = DWC_NUM_INTR_TRBS; ++ break; ++ case UE_ISOCHRONOUS: ++ num_trbs = DWC_NUM_ISOC_TRBS; ++ link = 1; ++ break; ++ default: ++ num_trbs = DWC_NUM_BULK_TRBS; ++ break; ++ } ++ ++ dwc_debug(pcd->usb3_dev, "ep%d-%s=%p phys=%d pcd_ep=%p\n", ++ num, dir == UE_DIR_IN ? "IN" : "OUT", usb_ep, ++ pcd_ep->dwc_ep.phys, pcd_ep); ++ ++ /* Set the TRB allocation for this EP */ ++ desc = dwc_usb3_pcd_trb_alloc(pcd_ep, num_trbs, type, ++ ep_desc->bInterval - 1, link, ++ &desc_dma); ++ if (!desc) ++ return -ENOMEM; ++ ++ maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize); ++ ++ spin_lock_irqsave(&pcd->lock, flags); ++ dwc_wait_if_hibernating(pcd, flags); ++ pcd->usb3_dev->hiber_cnt++; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) ++ if (gadget_wrapper->gadget.speed == USB_SPEED_SUPER) { ++ if (usb_ep->comp_desc) { ++ if (type == UE_ISOCHRONOUS) ++ mult = usb_ep->comp_desc->bmAttributes; ++ maxburst = usb_ep->comp_desc->bMaxBurst; ++ if (type == UE_BULK) ++ maxstreams = usb_ep->comp_desc->bmAttributes; ++ } ++ } else { ++ if (type == UE_ISOCHRONOUS) ++ mult = maxpacket >> 11 & 3; ++ } ++ ++ if (mult > 2 || maxburst > 15 || maxstreams > 16) { ++ pcd->usb3_dev->hiber_cnt--; ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ dwc_usb3_pcd_trb_free(pcd_ep); ++ return -EINVAL; ++ } ++ ++ ep_comp.bmAttributes = USSE_SET_MAX_STREAMS(0, maxstreams); ++ ep_comp.bmAttributes = USSE_SET_MAX_PACKET_NUM(ep_comp.bmAttributes, ++ mult); ++ ep_comp.bMaxBurst = maxburst; ++#else ++ if (type == UE_BULK) ++ ep_comp.bmAttributes = USSE_SET_MAX_STREAMS(0, ++ usb_ep->numstreams); ++ if (type == UE_ISOCHRONOUS) ++ ep_comp.bmAttributes = USSE_SET_MAX_PACKET_NUM(0, usb_ep->mult); ++ ++ ep_comp.bMaxBurst = usb_ep->maxburst; ++#endif ++ ++ retval = dwc_usb3_pcd_ep_enable(pcd, pcd_ep, ++ (usb_endpoint_descriptor_t *)ep_desc, &ep_comp); ++ if (!retval) ++ usb_ep->maxpacket = maxpacket; ++ ++ if (gadget_wrapper->gadget.speed == USB_SPEED_HIGH) { ++ if (usb_ep->maxpacket == 5120) ++ usb_ep->maxpacket = 3072; ++ else if (usb_ep->maxpacket == 3072) ++ usb_ep->maxpacket = 2048; ++ } ++ ++ pcd->usb3_dev->hiber_cnt--; ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ ++ if (retval) { ++ dwc_usb3_pcd_trb_free(pcd_ep); ++ retval = -ENOMEM; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function disables an EP ++ */ ++static int ep_disable(struct usb_ep *usb_ep) ++{ ++ int retval = 0; ++ dwc_usb3_pcd_ep_t *pcd_ep; ++ dwc_usb3_pcd_t *pcd; ++ unsigned long flags; ++ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ printk(KERN_DEBUG USB3_DWC "%s()\n", __func__); ++#endif ++ if (!gadget_wrapper) { ++ printk(KERN_WARNING USB3_DWC "%s null wrapper!\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (!usb_ep) { ++ printk(KERN_WARNING USB3_DWC "EP not enabled!\n"); ++ return -EINVAL; ++ } ++ ++ pcd = gadget_wrapper->pcd; ++ ++ spin_lock_irqsave(&pcd->lock, flags); ++ dwc_wait_if_hibernating(pcd, flags); ++ pcd->usb3_dev->hiber_cnt++; ++ ++ pcd_ep = dwc_usb3_get_pcd_ep(usb_ep); ++ retval = dwc_usb3_pcd_ep_disable(pcd, pcd_ep); ++ ++ pcd->usb3_dev->hiber_cnt--; ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ ++ /* Free any existing TRB allocation for this EP */ ++ dwc_usb3_pcd_trb_free(pcd_ep); ++ ++ return retval ? -EINVAL : 0; ++} ++ ++/** ++ * This function allocates a request object to use with the specified USB EP. ++ * ++ * @param usb_ep The USB EP to be used with with the request. ++ * @param gfp_flags The GFP_* flags to use. ++ */ ++static struct usb_request *alloc_request(struct usb_ep *usb_ep, gfp_t gfp_flags) ++{ ++ dwc_usb3_pcd_req_t *pcd_req; ++ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ printk(KERN_DEBUG USB3_DWC "%s(%p,%d)\n", __func__, usb_ep, gfp_flags); ++#endif ++ if (!usb_ep) { ++ printk(USB3_DWC "%s() %s\n", __func__, "Invalid EP!\n"); ++ return NULL; ++ } ++ ++ pcd_req = kmalloc(sizeof(dwc_usb3_pcd_req_t), gfp_flags); ++ if (!pcd_req) { ++ printk(USB3_DWC "%s() pcd request allocation failed!\n", ++ __func__); ++ return NULL; ++ } ++ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ //printk(USB3_DWC "%s() allocated %p\n", __func__, pcd_req); ++#endif ++ memset(pcd_req, 0, sizeof(dwc_usb3_pcd_req_t)); ++ pcd_req->usb_req.dma = DWC_DMA_ADDR_INVALID; ++ ++#ifdef DWC_TEST_ISOC_CHAIN ++ pcd_req->usb_req.dma2[0] = DWC_DMA_ADDR_INVALID; ++ pcd_req->usb_req.dma2[1] = DWC_DMA_ADDR_INVALID; ++#endif ++ return &pcd_req->usb_req; ++} ++ ++/** ++ * This function frees a request object. ++ * ++ * @param usb_ep The USB EP associated with the request. ++ * @param usb_req The request being freed. ++ */ ++static void free_request(struct usb_ep *usb_ep, struct usb_request *usb_req) ++{ ++ dwc_usb3_pcd_req_t *pcd_req; ++ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ printk(KERN_DEBUG USB3_DWC "%s(%p,%p)\n", __func__, usb_ep, usb_req); ++#endif ++ if (!usb_ep || !usb_req) { ++ printk(KERN_WARNING USB3_DWC "%s() %s\n", __func__, ++ "Invalid ep or req argument!"); ++ return; ++ } ++ ++ pcd_req = dwc_usb3_get_pcd_req(usb_req); ++ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ //printk(USB3_DWC "%s() freed %p\n", __func__, pcd_req); ++#endif ++ kfree(pcd_req); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) ++/** ++ * This function allocates an I/O buffer to be used for a transfer ++ * to/from the specified USB EP. ++ * ++ * @param usb_ep The USB EP to be used with with the request. ++ * @param bytes The desired number of bytes for the buffer. ++ * @param dma Pointer to the buffer's DMA address; must be valid. ++ * @param gfp_flags The GFP_* flags to use. ++ * @return Address of a new buffer or null if buffer could not be ++ * allocated. ++ */ ++static void *alloc_buffer(struct usb_ep *usb_ep, unsigned bytes, ++ dma_addr_t *dma, gfp_t gfp_flags) ++{ ++ gfp_t gfp_flags = GFP_KERNEL | GFP_DMA32; ++ void *buf; ++ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ printk(KERN_DEBUG USB3_DWC "%s(%p,%d,%p,%0x)\n", __func__, ++ usb_ep, bytes, dma, gfp_flags); ++#endif ++ /* Check dword alignment */ ++ if ((bytes & 0x3) != 0) { ++ printk(KERN_WARNING USB3_DWC ++ "%s() Buffer size is not a multiple of DWORD size (%d)\n", ++ __func__, bytes); ++ } ++ ++ buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags); ++ if (buf) { ++ /* Check dword alignment */ ++ if (((unsigned long)buf & 0x3) != 0) { ++ printk(KERN_WARNING USB3_DWC ++ "%s() Buffer is not DWORD aligned (%p)\n", ++ __func__, buf); ++ } ++ } ++ ++ return buf; ++} ++ ++/** ++ * This function frees an I/O buffer that was allocated by alloc_buffer. ++ * ++ * @param usb_ep The USB EP associated with the buffer. ++ * @param buf Address of the buffer. ++ * @param dma The buffer's DMA address. ++ * @param bytes The number of bytes of the buffer. ++ */ ++static void free_buffer(struct usb_ep *usb_ep, void *buf, ++ dma_addr_t dma, unsigned bytes) ++{ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ printk(KERN_DEBUG USB3_DWC "%s(%p,%p,%0x,%d)\n", __func__, ++ usb_ep, buf, dma, bytes); ++#endif ++ dma_free_coherent(NULL, bytes, buf, dma); ++} ++#endif ++ ++/** ++ * This function queues a request to a USB EP ++ */ ++static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req, ++ gfp_t gfp_flags) ++{ ++ int is_atomic = 0; ++ int retval = 0; ++ int req_flags = 0; ++ dwc_usb3_pcd_ep_t *pcd_ep; ++ dwc_usb3_pcd_req_t *pcd_req; ++ int numbufs; ++ char *bufs[3]; ++ dma_addr_t bufdmas[3]; ++ u32 buflens[3]; ++ dwc_usb3_pcd_t *pcd; ++ unsigned long flags; ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG USB3_DWC "%s(%p,%p,%d)\n", __func__, ++ usb_ep, usb_req, gfp_flags); ++#endif ++ if (!gadget_wrapper) { ++ printk(KERN_WARNING USB3_DWC "%s null wrapper!\n", __func__); ++ return -EINVAL; ++ } ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG USB3_DWC "pcd=%p\n", gadget_wrapper->pcd); ++#endif ++ if (!usb_req || !usb_req->complete || !usb_req->buf) { ++ printk(KERN_WARNING USB3_DWC "%s, bad params\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (!usb_ep) { ++ printk(KERN_WARNING USB3_DWC "%s, bad ep\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ printk(KERN_DEBUG USB3_DWC "gadget.speed=%d\n", ++ gadget_wrapper->gadget.speed); ++ printk(KERN_WARNING USB3_DWC "%s, bogus device state\n", ++ __func__); ++ return -ESHUTDOWN; ++ } ++ ++ if (!gadget_wrapper->pcd) { ++ printk(KERN_WARNING USB3_DWC ++ "%s, gadget_wrapper->pcd is NULL!\n", __func__); ++ return -EINVAL; ++ } ++ ++ pcd_ep = dwc_usb3_get_pcd_ep(usb_ep); ++ pcd_req = dwc_usb3_get_pcd_req(usb_req); ++ pcd = dwc_usb3_pcd_ep_to_pcd(pcd_ep); ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG USB3_DWC "%s 0x%p queue req 0x%p, len %d buf 0x%p\n", ++ usb_ep->name, pcd_ep, usb_req, usb_req->length, usb_req->buf); ++#endif ++ usb_req->status = -EINPROGRESS; ++ usb_req->actual = 0; ++ ++ if (gfp_flags == GFP_ATOMIC) ++ is_atomic = 1; ++ ++ if (usb_req->zero) ++ req_flags |= DWC_PCD_REQ_ZERO; ++ ++ if (usb_req->length != 0 && usb_req->dma == DWC_DMA_ADDR_INVALID) { ++ dwc_debug(pcd->usb3_dev, "DMA map req %p\n", usb_req); ++ dwc_debug(pcd->usb3_dev, "dev=%p\n", pcd->usb3_dev->dev); ++ map_buffers(pcd->usb3_dev->dev, usb_req, pcd_ep, &req_flags); ++ } ++ ++ bufs[0] = usb_req->buf; ++ bufdmas[0] = usb_req->dma; ++ buflens[0] = usb_req->length; ++ numbufs = 1; ++ ++#ifdef DWC_TEST_ISOC_CHAIN ++ if (dwc_usb3_pcd_ep_type(pcd_ep) == UE_ISOCHRONOUS) { ++ buflens[0] = usb_req->length - 58; ++ ++ bufs[1] = usb_req->buf2[0]; ++ bufdmas[1] = usb_req->dma2[0]; ++ buflens[1] = 29; ++ ++ bufs[2] = usb_req->buf2[1]; ++ bufdmas[2] = usb_req->dma2[1]; ++ buflens[2] = 29; ++ ++ numbufs = 3; ++ } ++#endif ++ if (dwc_usb3_pcd_ep_num(pcd_ep) != 0 && !pcd_ep->dwc_ep.usb_ep_desc) { ++ dwc_debug(pcd->usb3_dev, "%s, bad ep!\n", __func__); ++ return -EINVAL; ++ } ++ ++ spin_lock_irqsave(&pcd->lock, flags); ++ dwc_wait_if_hibernating(pcd, flags); ++ pcd->usb3_dev->hiber_cnt++; ++ ++ dwc_debug(pcd->usb3_dev, "%s: EP%d-%s %p stream %d req %p\n", ++ __func__, dwc_usb3_pcd_ep_num(pcd_ep), ++ dwc_usb3_pcd_ep_is_in(pcd_ep) ? "IN" : "OUT", ++ pcd_ep, usb_req->stream_id, pcd_req); ++ ++ dwc_debug(pcd->usb3_dev, "%s(%p,%p,%p,%p,%lx)\n", __func__, pcd, ++ usb_ep, usb_req, bufs[0], (unsigned long)bufdmas[0]); ++ ++ INIT_LIST_HEAD(&pcd_req->entry); ++ ++ fill_req(pcd, pcd_ep, pcd_req, numbufs, bufs, bufdmas, buflens, ++ usb_req->stream_id, req_flags); ++ ++ if (!list_empty(&pcd_ep->dwc_ep.queue)) { ++ /* If queue is not empty, then don't start the transfer, unless ++ * this is an Isoc transfer. But we still queue the request. ++ */ ++ dwc_debug(pcd->usb3_dev, ++ " q not empty %d, stopped %d, avail %d, istart %d\n", ++ pcd->request_pending, pcd_ep->dwc_ep.stopped, ++ pcd_ep->dwc_ep.desc_avail, ++ pcd_ep->dwc_ep.xfer_started); ++ ++ if (!pcd_ep->dwc_ep.stopped && ++ pcd_ep->dwc_ep.type == UE_ISOCHRONOUS && ++ pcd_ep->dwc_ep.desc_avail > 0 && ++ pcd_ep->dwc_ep.xfer_started) ++ goto do_start; ++ ++ } else if (pcd_ep->dwc_ep.stopped || ++ (pcd_ep != pcd->ep0 && pcd_ep->dwc_ep.desc_avail <= 0) || ++ (pcd_ep->dwc_ep.type == UE_ISOCHRONOUS && ++ !pcd_ep->dwc_ep.xfer_started)) { ++ /* If EP is stopped, or there is no TRB available, or this ++ * is an Isoc transfer and the EP is not started, then don't ++ * start the transfer. But we still queue the request. ++ */ ++ dwc_debug(pcd->usb3_dev, ++ " q empty %d, stopped %d, avail %d, istart %d\n", ++ pcd->request_pending, pcd_ep->dwc_ep.stopped, ++ pcd_ep->dwc_ep.desc_avail, pcd_ep->dwc_ep.xfer_started); ++ } else { ++do_start: ++ /* Setup and start the transfer */ ++ dwc_usb3_pcd_fill_trbs(pcd, pcd_ep, pcd_req); ++ retval = dwc_usb3_pcd_ep_submit_req(pcd, pcd_ep, pcd_req, ++ req_flags); ++ } ++ ++ if (!retval) { ++ list_add_tail(&pcd_req->entry, &pcd_ep->dwc_ep.queue); ++ ++pcd->request_pending; ++ } ++ ++ pcd->usb3_dev->hiber_cnt--; ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ ++ /* dwc_usb3_pcd_ep_submit_req() can return positive values for ++ * Control transfers, don't propagate those from this function ++ */ ++ if (retval < 0) ++ return -EINVAL; ++ return 0; ++} ++ ++/** ++ * This function dequeues a request from a USB EP ++ */ ++static int ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req) ++{ ++ dwc_usb3_pcd_req_t *pcd_req = NULL; ++ dwc_usb3_pcd_ep_t *pcd_ep; ++ dwc_usb3_pcd_t *pcd; ++ struct list_head *list_item; ++ unsigned long flags; ++ ++#ifdef DEBUG ++ printk(KERN_DEBUG USB3_DWC "%s(%p,%p)\n", __func__, usb_ep, usb_req); ++#endif ++ if (!gadget_wrapper) { ++ printk(KERN_WARNING USB3_DWC "%s null wrapper!\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (!usb_ep || !usb_req) { ++ printk(KERN_WARNING USB3_DWC "%s, bad argument!\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ printk(KERN_WARNING USB3_DWC "%s, bogus device state!\n", ++ __func__); ++ return -ESHUTDOWN; ++ } ++ ++ if (!gadget_wrapper->pcd) { ++ printk(KERN_WARNING USB3_DWC ++ "%s, gadget_wrapper->pcd is NULL!\n", __func__); ++ return -EINVAL; ++ } ++ ++ pcd = gadget_wrapper->pcd; ++ ++ spin_lock_irqsave(&pcd->lock, flags); ++ dwc_wait_if_hibernating(pcd, flags); ++ pcd->usb3_dev->hiber_cnt++; ++ ++ pcd_ep = dwc_usb3_get_pcd_ep(usb_ep); ++ ++ if (dwc_usb3_pcd_ep_num(pcd_ep) != 0 && !pcd_ep->dwc_ep.usb_ep_desc) { ++ //dwc_warn(pcd->usb3_dev, "%s, bad pcd_ep!\n", __func__); ++ pcd->usb3_dev->hiber_cnt--; ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ return -EINVAL; ++ } ++ ++ /* make sure it's actually queued on this EP */ ++ list_for_each (list_item, &pcd_ep->dwc_ep.queue) { ++ pcd_req = list_entry(list_item, dwc_usb3_pcd_req_t, entry); ++ if (&pcd_req->usb_req == usb_req) ++ break; ++ } ++ ++ if (!pcd_req) { ++ dwc_warn(pcd->usb3_dev, "%s, no request in queue!\n", __func__); ++ pcd->usb3_dev->hiber_cnt--; ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ return 0; ++ } ++ ++ dwc_usb3_pcd_ep_cancel_req(pcd, pcd_ep, pcd_req, usb_req->stream_id); ++ ++ pcd->usb3_dev->hiber_cnt--; ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ return 0; ++} ++ ++/** ++ * This routine allocates coherent DMA memory. It is used by the PCD to ++ * allocate memory for TRBs. The block of memory returned must have a start ++ * address aligned to a 16-byte boundary. ++ * ++ * @param ep PCD EP that memory block will be associated with. ++ * @param size Size of memory block to allocate, in bytes. ++ * @param mem_dma_ret DMA address of allocated memory block is returned ++ * through this pointer. ++ * @return Address of allocated memory block, or NULL if allocation ++ * fails. ++ */ ++void *dwc_usb3_gadget_alloc_dma(dwc_usb3_pcd_ep_t *ep, int size, ++ dwc_dma_t *mem_dma_ret) ++{ ++ void *mem; ++ ++ mem = dma_alloc_coherent(NULL, size, mem_dma_ret, ++ GFP_ATOMIC | GFP_DMA32); ++ if (!mem) ++ return NULL; ++ memset(mem, 0, size); ++ return mem; ++} ++ ++/** ++ * This routine frees DMA memory allocated by dwc_usb3_gadget_alloc_dma(). ++ * ++ * @param ep PCD EP that memory block is associated with. ++ * @param size Size of memory block to free, in bytes. ++ * @param mem Address of memory block. ++ * @param mem_dma DMA address of memory block. ++ */ ++void dwc_usb3_gadget_free_dma(dwc_usb3_pcd_ep_t *ep, int size, void *mem, ++ dwc_dma_t mem_dma) ++{ ++ dma_free_coherent(NULL, size, mem, mem_dma); ++} ++ ++/** ++ * This routine returns the PCD request corresponding to the current transfer ++ * request for an endpoint. The current transfer request is the first request ++ * submitted that has not been completed yet. ++ */ ++dwc_usb3_pcd_req_t *dwc_usb3_gadget_get_request(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep) ++{ ++ dwc_usb3_pcd_req_t *req; ++ ++ /* Check for a pending request */ ++ if (list_empty(&ep->dwc_ep.queue)) { ++ dwc_debug(pcd->usb3_dev, "%s(%p), ep->dwc_ep.queue empty!\n", ++ __func__, ep); ++ return NULL; ++ } ++ ++ req = list_first_entry(&ep->dwc_ep.queue, dwc_usb3_pcd_req_t, entry); ++ return req; ++} ++ ++/** ++ * This function checks the EP request queue, if the queue is not empty then ++ * the next transfer is started. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param ep EP to operate on. ++ */ ++void dwc_usb3_gadget_start_next_request(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep) ++{ ++ dwc_usb3_pcd_req_t *req = NULL; ++ struct list_head *list_item; ++ ++ dwc_debug(pcd->usb3_dev, "%s(%p)\n", __func__, ep); ++ ++ if (list_empty(&ep->dwc_ep.queue)) { ++ dwc_debug(pcd->usb3_dev, "start_next EP%d-%s: queue empty\n", ++ ep->dwc_ep.num, ep->dwc_ep.is_in ? "IN" : "OUT"); ++ return; ++ } ++ ++ list_for_each (list_item, &ep->dwc_ep.queue) { ++ req = list_entry(list_item, dwc_usb3_pcd_req_t, entry); ++ if (!(req->dwc_req.flags & DWC_PCD_REQ_STARTED)) { ++ if (ep->dwc_ep.desc_avail <= 0) { ++ dwc_debug(pcd->usb3_dev, ++ "start_next EP%d-%s: no TRB avail\n", ++ ep->dwc_ep.num, ep->dwc_ep.is_in ? ++ "IN" : "OUT"); ++ return; ++ } ++ ++ dwc_debug(pcd->usb3_dev, "start_next EP%d-%s: OK\n", ++ ep->dwc_ep.num, ++ ep->dwc_ep.is_in ? "IN" : "OUT"); ++ ++ /* Setup and start the transfer */ ++ //dwc_debug(pcd->usb3_dev, ++ // " -> starting xfer (start_next_req) %s %s\n", ++ // ep->dwc_ep.ep.name, ++ // ep->dwc_ep.is_in ? "IN" : "OUT"); ++ dwc_usb3_pcd_fill_trbs(pcd, ep, req); ++ dwc_usb3_pcd_ep_start_transfer(pcd, ep, req, 0); ++ return; ++ } ++ } ++ ++ dwc_debug(pcd->usb3_dev, "start_next EP%d-%s: all req active\n", ++ ep->dwc_ep.num, ep->dwc_ep.is_in ? "IN" : "OUT"); ++} ++ ++/** ++ * This function terminates all the requests in the EP request queue. ++ */ ++void dwc_usb3_gadget_request_nuke(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep) ++{ ++ dwc_usb3_pcd_req_t *req; ++ ++ dwc_debug(pcd->usb3_dev, "%s(%p)\n", __func__, ep); ++ ep->dwc_ep.stopped = 1; ++ ++ /* called with irqs blocked?? */ ++ while (!list_empty(&ep->dwc_ep.queue)) { ++ req = list_first_entry(&ep->dwc_ep.queue, dwc_usb3_pcd_req_t, ++ entry); ++ dwc_usb3_pcd_request_done(pcd, ep, req, -DWC_E_SHUTDOWN); ++ } ++ ++ if (ep != pcd->ep0) { ++ ep->dwc_ep.desc_idx = 0; ++ ep->dwc_ep.hiber_desc_idx = 0; ++ } ++} ++ ++/** ++ * This function marks all requests in an EP queue as not started. ++ */ ++void dwc_usb3_gadget_set_ep_not_started(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep) ++{ ++ dwc_usb3_pcd_req_t *req; ++ struct list_head *list_item; ++ ++ list_for_each (list_item, &ep->dwc_ep.queue) { ++ req = list_entry(list_item, dwc_usb3_pcd_req_t, entry); ++ if (req->dwc_req.flags & DWC_PCD_REQ_STARTED) ++ req->dwc_req.flags &= ~DWC_PCD_REQ_STARTED; ++ if (req->dwc_req.trb) { ++ dwc_usb3_disable_desc(req->dwc_req.trb); ++ (req->dwc_req.trb)->bpth = ep->dwc_ep.desc_avail; ++ ep->dwc_ep.desc_avail++; ++ req->dwc_req.trb = NULL; ++ } ++ ++ } ++} ++ ++/** ++ * Start an Isoc EP running at the proper interval, after receiving the initial ++ * XferNrdy event. ++ */ ++void dwc_usb3_gadget_isoc_ep_start(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep, ++ u32 event) ++{ ++ dwc_usb3_pcd_req_t *req = NULL; ++ struct list_head *list_item; ++ ++ dwc_debug(pcd->usb3_dev, "%s(%p,%p,%x)\n", __func__, pcd, ep, event); ++ dwc_isocdbg(pcd->usb3_dev, "%s(%08x)\n", __func__, event); ++ ++ if (list_empty(&ep->dwc_ep.queue)) { ++ dwc_debug(pcd->usb3_dev, "%s(%p), ep->dwc_ep.queue empty!\n", ++ __func__, ep); ++ return; ++ } ++ ++ if (ep->dwc_ep.desc_avail <= 0) { ++ dwc_print(pcd->usb3_dev, "EP%d-%s: no TRB avail!\n", ++ ep->dwc_ep.num, ep->dwc_ep.is_in ? "IN" : "OUT"); ++ return; ++ } ++ ++ /* If need to restart after hibernation, handle that and return */ ++ if (dwc_usb3_pcd_isoc_ep_hiber_restart(pcd, ep)) ++ return; ++ ++ /* ++ * Start the next queued transfer at the target uFrame ++ */ ++ ++ list_for_each (list_item, &ep->dwc_ep.queue) { ++ req = list_entry(list_item, dwc_usb3_pcd_req_t, entry); ++ if (req->dwc_req.flags & DWC_PCD_REQ_STARTED) ++ req = NULL; ++ else ++ break; ++ } ++ ++ dwc_debug(pcd->usb3_dev, "req=%p\n", req); ++ if (!req) { ++ dwc_print(pcd->usb3_dev, "EP%d-%s: no requests to start!\n", ++ ep->dwc_ep.num, ep->dwc_ep.is_in ? "IN" : "OUT"); ++ return; ++ } ++ ++ dwc_usb3_pcd_fill_trbs(pcd, ep, req); ++ dwc_usb3_pcd_ep_start_transfer(pcd, ep, req, event); ++ ++ /* ++ * Now start any remaining queued transfers ++ */ ++ ++ while (!list_is_last(list_item, &ep->dwc_ep.queue)) { ++ list_item = list_item->next; ++ req = list_entry(list_item, dwc_usb3_pcd_req_t, entry); ++ if (!(req->dwc_req.flags & DWC_PCD_REQ_STARTED)) { ++ if (ep->dwc_ep.desc_avail <= 0) { ++ dwc_debug(pcd->usb3_dev, ++ "start_next EP%d-%s: no TRB avail!\n", ++ ep->dwc_ep.num, ep->dwc_ep.is_in ? ++ "IN" : "OUT"); ++ return; ++ } ++ ++ dwc_usb3_pcd_fill_trbs(pcd, ep, req); ++ dwc_usb3_pcd_ep_start_transfer(pcd, ep, req, 0); ++ } ++ } ++} ++ ++/** ++ * This function sets/clears halt on a USB EP ++ */ ++static int ep_set_halt(struct usb_ep *usb_ep, int value) ++{ ++ dwc_usb3_pcd_ep_t *pcd_ep; ++ dwc_usb3_pcd_t *pcd; ++ unsigned long flags; ++ ++ if (!gadget_wrapper) { ++ printk(KERN_WARNING USB3_DWC "%s null wrapper!\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (!usb_ep) { ++ printk(KERN_WARNING USB3_DWC "%s, bad usb_ep!\n", __func__); ++ return -EINVAL; ++ } ++ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ printk(KERN_DEBUG USB3_DWC "HALT %s %d\n", usb_ep->name, value); ++#endif ++ ++ pcd = gadget_wrapper->pcd; ++ ++ spin_lock_irqsave(&pcd->lock, flags); ++ dwc_wait_if_hibernating(pcd, flags); ++ pcd->usb3_dev->hiber_cnt++; ++ ++ pcd_ep = dwc_usb3_get_pcd_ep(usb_ep); ++ dwc_debug(pcd->usb3_dev, "pcd_ep=%p\n", pcd_ep); ++ dwc_debug(pcd->usb3_dev, "pcd->ep0=%p\n", pcd->ep0); ++ dwc_debug(pcd->usb3_dev, "epnum=%d is_in=%d\n", ++ dwc_usb3_pcd_ep_num(pcd_ep), dwc_usb3_pcd_ep_is_in(pcd_ep)); ++ ++ if ((!pcd_ep->dwc_ep.usb_ep_desc && dwc_usb3_pcd_ep_num(pcd_ep) != 0) || ++ (pcd_ep->dwc_ep.usb_ep_desc && dwc_usb3_pcd_ep_type(pcd_ep) ++ == UE_ISOCHRONOUS)) { ++ dwc_warn(pcd->usb3_dev, "%s, bad pcd_ep!\n", __func__); ++ pcd->usb3_dev->hiber_cnt--; ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ return -EINVAL; ++ } ++ ++ if (!list_empty(&pcd_ep->dwc_ep.queue)) { ++ dwc_warn(pcd->usb3_dev, "%s, Xfer in process!\n", __func__); ++ pcd->usb3_dev->hiber_cnt--; ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ return -EAGAIN; ++ } ++ ++ dwc_usb3_pcd_ep_set_halt(pcd, pcd_ep, value); ++ ++ pcd->usb3_dev->hiber_cnt--; ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) ++static int ep_set_wedge(struct usb_ep *usb_ep) ++{ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ printk(KERN_DEBUG USB3_DWC "WEDGE %s\n", usb_ep->name); ++#endif ++ return ep_set_halt(usb_ep, 3); ++} ++#endif ++ ++static struct usb_ep_ops pcd_ep_ops = { ++ .enable = ep_enable, ++ .disable = ep_disable, ++ ++ .alloc_request = alloc_request, ++ .free_request = free_request, ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) ++ .alloc_buffer = alloc_buffer, ++ .free_buffer = free_buffer, ++#endif ++ .queue = ep_queue, ++ .dequeue = ep_dequeue, ++ ++ .set_halt = ep_set_halt, ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) ++ .set_wedge = ep_set_wedge, ++#endif ++ .fifo_status = NULL, ++ .fifo_flush = NULL, ++}; ++ ++ ++/* Gadget ops */ ++ ++#ifdef CONFIG_USB_OTG_DWC ++ ++void dwc_usb3_start_hnp(dwc_usb3_pcd_t *pcd) ++{ ++ struct usb_phy *phy = usb_get_phy(USB_PHY_TYPE_USB3); ++ struct usb_otg *otg; ++ ++ dwc_debug(pcd->usb3_dev, "%s()\n", __func__); ++ if (IS_ERR(phy) || !phy) { ++ dwc_info(pcd->usb3_dev, "NO PHY!!\n"); ++ if (!IS_ERR(phy)) ++ usb_put_phy(phy); ++ return; ++ } ++ ++ otg = phy->otg; ++ if (!otg) { ++ dwc_info(pcd->usb3_dev, "NO OTG!!\n"); ++ usb_put_phy(phy); ++ return; ++ } ++ ++ otg_start_hnp(otg); ++ usb_put_phy(phy); ++} ++ ++void dwc_usb3_host_release(dwc_usb3_pcd_t *pcd) ++{ ++ struct usb_phy *phy = usb_get_phy(USB_PHY_TYPE_USB3); ++ struct usb_otg *otg; ++ ++ dwc_debug(pcd->usb3_dev, "%s()\n", __func__); ++ if (IS_ERR(phy) || !phy) { ++ dwc_info(pcd->usb3_dev, "NO PHY!!\n"); ++ if (!IS_ERR(phy)) ++ usb_put_phy(phy); ++ return; ++ } ++ ++ otg = phy->otg; ++ if (!otg) { ++ dwc_info(pcd->usb3_dev, "NO OTG!!\n"); ++ usb_put_phy(phy); ++ return; ++ } ++ ++ otg_host_release(otg); ++ usb_put_phy(phy); ++} ++ ++static int pcd_stop_peripheral(struct usb_gadget *gadget, ++ struct usb_gadget_driver *driver) ++{ ++ struct gadget_wrapper *d; ++ dwc_usb3_pcd_t *pcd; ++ unsigned long flags; ++ u32 temp; ++ int count = 0; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ pcd = d->pcd; ++ ++ spin_lock_irqsave(&pcd->lock, flags); ++ ++ dwc_usb3_pcd_stop(pcd); ++ ++ /* Disable device interrupts */ ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->devten, 0); ++ ++ /* Clear Run/Stop bit */ ++ temp = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dctl); ++ temp &= ~DWC_DCTL_RUN_STOP_BIT; ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dctl, temp); ++ ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ ++ /* Wait for core stopped */ ++ do { ++ msleep(1); ++ temp = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dsts); ++ } while (!(temp & DWC_DSTS_DEV_CTRL_HLT_BIT) && (++count < 30)); ++ ++ return 0; ++} ++ ++static int pcd_start_peripheral(struct usb_gadget *gadget, ++ struct usb_gadget_driver *driver) ++{ ++ struct gadget_wrapper *d; ++ dwc_usb3_pcd_t *pcd; ++ unsigned long flags; ++ u32 temp; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ pcd = d->pcd; ++ ++ spin_lock_irqsave(&pcd->lock, flags); ++ ++ dwc_usb3_pcd_device_init(pcd->usb3_dev, 0, 0); ++ ++ /* Enable Device mode interrupts */ ++ dwc_usb3_enable_device_interrupts(pcd->usb3_dev); ++ ++ /* Set Run/Stop bit, and Keep-Connect bit if hibernation enabled */ ++ temp = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dctl); ++ temp |= DWC_DCTL_RUN_STOP_BIT; ++ ++ if (pcd->usb3_dev->core_params->hibernate && ++ (pcd->usb3_dev->hwparams1 & DWC_HWP1_EN_PWROPT_BITS) == ++ DWC_EN_PWROPT_HIBERNATION << DWC_HWP1_EN_PWROPT_SHIFT) ++ temp |= DWC_DCTL_KEEP_CONNECT_BIT; ++ ++ dwc_wr32(pcd->usb3_dev, &pcd->dev_global_regs->dctl, temp); ++ pcd->wants_host = 0; ++ ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ ++ return 0; ++} ++ ++static int pcd_send_hrr(struct usb_gadget *gadget, int is_init) ++{ ++ struct gadget_wrapper *d; ++ dwc_usb3_pcd_t *pcd; ++ unsigned long flags; ++ u32 param; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ pcd = d->pcd; ++ ++ spin_lock_irqsave(&pcd->lock, flags); ++ ++ param = is_init ? DWC_DGCMDPAR_HOST_ROLE_REQ_INITIATE : ++ DWC_DGCMDPAR_HOST_ROLE_REQ_CONFIRM; ++ dwc_usb3_xmit_host_role_request(pcd, param); ++ ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ ++ return 0; ++} ++ ++#endif /* CONFIG_USB_OTG_DWC */ ++ ++/** ++ * This function returns the current USB frame number. ++ * ++ * @param gadget The gadget context. ++ */ ++static int dwc_get_frame(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ dwc_usb3_pcd_t *pcd; ++ dwc_usb3_device_t *dev; ++ unsigned long flags; ++ int ret; ++ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ printk(KERN_DEBUG USB3_DWC "%s()\n", __func__); ++#endif ++ if (!gadget) ++ return -ENODEV; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ pcd = d->pcd; ++ dev = pcd->usb3_dev; ++ ++ spin_lock_irqsave(&pcd->lock, flags); ++ dwc_wait_if_hibernating(pcd, flags); ++ pcd->usb3_dev->hiber_cnt++; ++ ++ ret = dwc_usb3_pcd_get_frame_number(pcd); ++ ++ pcd->usb3_dev->hiber_cnt--; ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ return ret; ++} ++ ++/** ++ * This function sends a remote wakeup to the host. ++ * ++ * @param gadget The gadget context. ++ */ ++int dwc_usb3_wakeup(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ dwc_usb3_pcd_t *pcd; ++ dwc_usb3_device_t *dev; ++ unsigned long timeout, flags; ++ int state; ++ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ printk(KERN_DEBUG USB3_DWC "%s()\n", __func__); ++#endif ++ if (!gadget) ++ return -ENODEV; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ pcd = d->pcd; ++ dev = pcd->usb3_dev; ++ ++ if (!pcd->remote_wakeup_enable) { ++ dwc_info(dev, "hardware not enabled for wakeup\n"); ++ return -ENOTSUPP; ++ } ++ ++ spin_lock_irqsave(&pcd->lock, flags); ++ ++ if (dev->hibernate != DWC_HIBER_AWAKE) { ++ state = dwc_exit_hibernation(pcd, 1); ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ printk(USB3_DWC "dwc_exit_hibernation() returned %d\n", state); ++ return 0; ++ } ++ ++ dwc_wait_if_hibernating(pcd, flags); ++ pcd->usb3_dev->hiber_cnt++; ++ ++ state = dwc_usb3_pcd_get_link_state(pcd); ++ pcd->link_state = state; ++ dwc_usb3_pcd_set_link_state(pcd, DWC_LINK_STATE_REQ_REMOTE_WAKEUP); ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ ++ dwc_info(dev, "link state before: %d\n", state); ++#if 0 ++ /* Clear DCTL bits after 2 ms */ ++ msleep(2); ++ ++ spin_lock_irqsave(&pcd->lock, flags); ++ dwc_usb3_pcd_set_link_state(pcd, 0); ++ spin_unlock_irqrestore(&pcd->lock, flags); ++#endif ++ /* Wait 500 ms for link state to go to U0 */ ++ timeout = jiffies + msecs_to_jiffies(500); ++ ++ while (!time_after(jiffies, timeout)) { ++ spin_lock_irqsave(&pcd->lock, flags); ++ state = dwc_usb3_pcd_get_link_state(pcd); ++ pcd->link_state = state; ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ if (state == DWC_LINK_STATE_U0) ++ break; ++ else ++ msleep(1); ++ } ++ ++ dwc_info(dev, "link state after: %d\n", state); ++ ++ if (state != DWC_LINK_STATE_U0) { ++ spin_lock_irqsave(&pcd->lock, flags); ++ pcd->usb3_dev->hiber_cnt--; ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ return -ETIMEDOUT; ++ } ++ ++ /* Send function remote wake notification */ ++ spin_lock_irqsave(&pcd->lock, flags); ++ dwc_usb3_pcd_remote_wake(pcd, 0); ++ pcd->wkup_rdy = 0; ++ pcd->usb3_dev->hiber_cnt--; ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ dwc_info(dev, "remote wake sent\n"); ++ ++ return 0; ++} ++ ++static int dwc_usb3_pullup(struct usb_gadget *gadget, int is_on) ++{ ++ return 0; ++} ++ ++static const struct usb_gadget_ops pcd_ops = { ++ .get_frame = dwc_get_frame, ++ .wakeup = dwc_usb3_wakeup, ++ .pullup = dwc_usb3_pullup, ++ // current versions must always be self-powered ++ ++#ifdef CONFIG_USB_OTG_DWC ++ .udc_start = pcd_start_peripheral, ++ .udc_stop = pcd_stop_peripheral, ++ ++ .send_hrr = pcd_send_hrr, ++#endif ++}; ++ ++ ++/*=======================================================================*/ ++ ++/** ++ * Initialize the Linux gadget specific parts of the default Control EP (EP0). ++ */ ++static void gadget_init_ep0(dwc_usb3_pcd_t *pcd, struct gadget_wrapper *d) ++{ ++ dwc_usb3_pcd_ep_t *pcd_ep; ++ struct usb_ep *ep0; ++ ++ dwc_debug(pcd->usb3_dev, "%s()\n", __func__); ++ ++ d->gadget.ep0 = &d->ep0.usb_ep; ++ INIT_LIST_HEAD(&d->gadget.ep0->ep_list); ++ ++ pcd_ep = &d->ep0; ++ ep0 = &pcd_ep->usb_ep; ++ dwc_debug(pcd->usb3_dev, "ep0=%p\n", ep0); ++ ++ INIT_LIST_HEAD(&pcd_ep->dwc_ep.queue); ++ ++ /* Init the usb_ep structure */ ++ ep0->name = d->ep_names[0]; ++ ep0->ops = (struct usb_ep_ops *)&pcd_ep_ops; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) ++ ep0->maxpacket = DWC_MAX_EP0_SIZE; ++#else ++ usb_ep_set_maxpacket_limit(ep0, DWC_MAX_EP0_SIZE); ++#endif ++ ++ dwc_debug(pcd->usb3_dev, "EP0 name=%s\n", ep0->name); ++ dwc_debug(pcd->usb3_dev, "ep0 eplist: %p(%p,%p) = %p(%p,%p)\n", ++ &d->gadget.ep0->ep_list, d->gadget.ep0->ep_list.prev, ++ d->gadget.ep0->ep_list.next, &ep0->ep_list, ++ ep0->ep_list.prev, ep0->ep_list.next); ++} ++ ++/** ++ * Initialize the Linux gadget specific parts of the non-EP0 EPs. ++ */ ++static int gadget_init_eps(dwc_usb3_pcd_t *pcd, struct gadget_wrapper *d) ++{ ++ dwc_usb3_pcd_ep_t *pcd_ep; ++ struct usb_ep *ep; ++ const char *name, *tmp, *ttmp; ++ int i, num, ep_in, ep_out; ++ ++ dwc_debug(pcd->usb3_dev, "%s()\n", __func__); ++ ++ INIT_LIST_HEAD(&d->gadget.ep_list); ++ ++ for (i = 1, ep_in = 0, ep_out = 0; i < ARRAY_SIZE(d->ep_names); i++) { ++ name = d->ep_names[i]; ++ if (!name || !name[0]) ++ break; ++ ++ /* Find '-' in e.g. "ep1in-bulk" */ ++ tmp = strrchr(name, '-'); ++ if (!tmp) ++ /* If no '-' then find end of string */ ++ tmp = name + strlen(name); ++ ++ /* If not 0-len string then back up 1 char */ ++ if (tmp != name) ++ tmp--; ++ ++ /* Get the EP number */ ++ num = 0; ++ ttmp = tmp; ++ ++ if (*tmp == 't') { ++ /* If "out", back up to the number before the 'o' */ ++ if (tmp >= name + 3) ++ tmp -= 3; ++ } else if (*tmp == 'n') { ++ /* If "in", back up to the number before the 'i' */ ++ if (tmp >= name + 2) ++ tmp -= 2; ++ } ++ ++ if (isdigit(*tmp)) { ++ /* If numeric, handle 1 or 2 digits */ ++ if (tmp > name && isdigit(*(tmp - 1))) ++ num = simple_strtol(tmp - 1, NULL, 10); ++ else ++ num = simple_strtol(tmp, NULL, 10); ++ } ++ ++ dwc_debug(pcd->usb3_dev, "num=%d\n", num); ++ tmp = ttmp; ++ if (num < 1 || num >= DWC_MAX_EPS) ++ goto bad; ++ ++ /* If e.g. "ep1" or "ep1out" then OUT ep */ ++ if ((isdigit(*tmp) || *tmp == 't') && (ep_out < 2)) { ++ ep_out++; ++ pcd_ep = &d->out_ep[ep_out - 1]; ++ ep = &pcd_ep->usb_ep; ++ dwc_debug(pcd->usb3_dev, ++ "ep%d-OUT=%p name=%s phys=%d pcd_ep=%p\n", ++ num, ep, name, ep_out, pcd_ep); ++ dwc_error(pcd->usb3_dev, ++ "ep%d-OUT=%p name=%s phys=%d pcd_ep=%p\n", ++ num, ep, name, ep_out, pcd_ep); ++ ++ pcd_ep->dwc_ep.num = num; ++ INIT_LIST_HEAD(&pcd_ep->dwc_ep.queue); ++ ++ /* Init the usb_ep structure */ ++ ep->name = name; ++ ep->ops = (struct usb_ep_ops *)&pcd_ep_ops; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) ++ ep->maxpacket = DWC_MAX_PACKET_SIZE; ++#else ++ usb_ep_set_maxpacket_limit(ep, DWC_MAX_PACKET_SIZE); ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) ++ ep->max_streams = 15; ++#else ++ ep->numstreams = 0; ++#endif ++ ep->mult = 0; ++ ep->maxburst = 0; ++ ++ dwc_debug(pcd->usb3_dev, ++ "ep%d-OUT eplist pre: %p(%p,%p) = %p(%p,%p)\n", ++ num, &d->gadget.ep_list, d->gadget.ep_list.prev, ++ d->gadget.ep_list.next, &ep->ep_list, ++ ep->ep_list.prev, ep->ep_list.next); ++ list_add_tail(&ep->ep_list, &d->gadget.ep_list); ++ dwc_debug(pcd->usb3_dev, ++ "ep%d-OUT eplist post: %p(%p,%p) = %p(%p,%p)\n", ++ num, &d->gadget.ep_list, d->gadget.ep_list.prev, ++ d->gadget.ep_list.next, &ep->ep_list, ++ ep->ep_list.prev, ep->ep_list.next); ++ } ++ ++ /* If e.g. "ep1" or "ep1in" then IN ep */ ++ if ((isdigit(*tmp) || *tmp == 'n')&&(ep_in < 4)) { ++ ep_in++; ++ pcd_ep = &d->in_ep[ep_in - 1]; ++ ep = &pcd_ep->usb_ep; ++ dwc_debug(pcd->usb3_dev, ++ "ep%d-IN=%p name=%s phys=%d pcd_ep=%p\n", ++ num, ep, name, ep_in, pcd_ep); ++ dwc_error(pcd->usb3_dev, ++ "ep%d-IN=%p name=%s phys=%d pcd_ep=%p\n", ++ num, ep, name, ep_in, pcd_ep); ++ ++ pcd_ep->dwc_ep.num = num; ++ INIT_LIST_HEAD(&pcd_ep->dwc_ep.queue); ++ /* Init the usb_ep structure */ ++ ep->name = name; ++ ep->ops = (struct usb_ep_ops *)&pcd_ep_ops; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) ++ ep->maxpacket = DWC_MAX_PACKET_SIZE; ++#else ++ usb_ep_set_maxpacket_limit(ep, DWC_MAX_PACKET_SIZE); ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) ++ ep->max_streams = 15; ++#else ++ ep->numstreams = 0; ++#endif ++ ep->mult = 0; ++ ep->maxburst = 0; ++ ++ dwc_debug(pcd->usb3_dev, ++ "ep%d-IN eplist pre: %p(%p,%p) = %p(%p,%p)\n", ++ num, &d->gadget.ep_list, d->gadget.ep_list.prev, ++ d->gadget.ep_list.next, &ep->ep_list, ++ ep->ep_list.prev, ep->ep_list.next); ++ list_add_tail(&ep->ep_list, &d->gadget.ep_list); ++ dwc_debug(pcd->usb3_dev, ++ "ep%d-IN eplist post: %p(%p,%p) = %p(%p,%p)\n", ++ num, &d->gadget.ep_list, d->gadget.ep_list.prev, ++ d->gadget.ep_list.next, &ep->ep_list, ++ ep->ep_list.prev, ep->ep_list.next); ++ } ++ ++ if (!isdigit(*tmp) && *tmp != 't' && *tmp != 'n') { ++bad: ++ dwc_debug(pcd->usb3_dev, "ep%d ????\n", num); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * Free any descriptor allocations made for each non-EP0 EP. ++ */ ++static void gadget_free_ep_allocations(dwc_usb3_pcd_t *pcd, ++ struct gadget_wrapper *d) ++{ ++ dwc_usb3_pcd_ep_t *pcd_ep; ++ int i; ++ ++ for (i = DWC_MAX_EPS - 1; i > 0; i--) { ++ pcd_ep = &d->in_ep[i - 1]; ++ dwc_debug(pcd->usb3_dev, "physpair%d-IN=%p\n", i, pcd_ep); ++ dwc_usb3_pcd_trb_free(pcd_ep); ++ ++ pcd_ep = &d->out_ep[i - 1]; ++ dwc_debug(pcd->usb3_dev, "physpair%d-OUT=%p\n", i, pcd_ep); ++ dwc_usb3_pcd_trb_free(pcd_ep); ++ } ++} ++ ++/** ++ * This function releases the Gadget device. ++ * Required by device_unregister(). ++ * ++ * @param dev The device context. ++ */ ++static void gadget_release(struct device *dev) ++{ ++ /* @todo Should this do something? Should it free the PCD? ++ */ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ printk(KERN_DEBUG USB3_DWC "%s()\n", __func__); ++#endif ++} ++ ++ ++#ifdef DWC_UTE ++/*=======================================================================*/ ++/* ++ * UTE support functions ++ */ ++ ++/** ++ * Return the PCD pointer for a given gadget instance. ++ */ ++dwc_usb3_pcd_t *dwc_usb3_get_pcd_instance(unsigned devnum) ++{ ++ if (!gadget_wrapper) { ++ printk(KERN_WARNING USB3_DWC "%s null wrapper!\n", __func__); ++ return NULL; ++ } ++ ++ return gadget_wrapper->pcd; ++} ++ ++/** ++ * Set mapping of a USB EP to a physical EP, by changing the contents of the ++ * gadget instance's ep_names[] array. ++ */ ++int dwc_usb3_set_usb_ep_map(unsigned devnum, unsigned phys_ep_num, ++ unsigned usb_ep_num) ++{ ++ unsigned usb_ep, usb_dir, usb_type; ++ char *dirstr, *typestr, *buf; ++ static char *ep_type_str[] = { "ctrl", "iso", "bulk", "int" }; ++ ++ if (!gadget_wrapper) { ++ printk(KERN_WARNING USB3_DWC "%s null wrapper!\n", __func__); ++ return -ENODEV; ++ } ++ ++ /* Phys EP 0 & 1 cannot be remapped */ ++ if (phys_ep_num < 2 || phys_ep_num >= DWC_MAX_PHYS_EP) ++ return -EINVAL; ++ ++ /* ep_names[] has a single entry for both EP0 IN & OUT */ ++ phys_ep_num--; ++ ++ /* These fields are defined by UTE */ ++ usb_ep = usb_ep_num & 0xf; ++ usb_dir = usb_ep_num >> 4 & 0x3; ++ usb_type = usb_ep_num >> 6 & 0x7; ++ ++ /* Cannot remap the default Control EP */ ++ if (usb_ep == 0) ++ return -EINVAL; ++ ++ switch (usb_dir) { ++ case 0: ++ dirstr = "out"; ++ break; ++ case 1: ++ dirstr = "in"; ++ break; ++ default: ++ /* USB3 does not have bidirectional physical EPs */ ++ return -EINVAL; ++ } ++ ++ buf = gadget_wrapper->ep_names[phys_ep_num]; ++ ++ if (usb_type >= 4) { ++ snprintf(buf, sizeof(gadget_wrapper->ep_names[0]), ++ "ep%u%s", usb_ep, dirstr); ++ } else { ++ typestr = ep_type_str[usb_type]; ++ snprintf(buf, sizeof(gadget_wrapper->ep_names[0]), ++ "ep%u%s-%s", usb_ep, dirstr, typestr); ++ } ++ ++ return 0; ++} ++ ++/** ++ * Get mapping of a USB EP to a physical EP, by reading the contents of the ++ * gadget instance's ep_names[] array. ++ */ ++int dwc_usb3_get_usb_ep_map(unsigned devnum, unsigned phys_ep_num, ++ unsigned *usb_ep_num_ret) ++{ ++ unsigned usb_ep, usb_dir, usb_type; ++ char dirstr[16], typestr[16], *dashp, *buf; ++ int ret; ++ ++ if (!gadget_wrapper) { ++ printk(KERN_WARNING USB3_DWC "%s null wrapper!\n", __func__); ++ return -ENODEV; ++ } ++ ++ /* Phys EP 0 & 1 cannot be remapped */ ++ if (phys_ep_num < 2 || phys_ep_num >= DWC_MAX_PHYS_EP) ++ return -EINVAL; ++ ++ /* ep_names[] has a single entry for both EP0 IN & OUT */ ++ phys_ep_num--; ++ ++ buf = gadget_wrapper->ep_names[phys_ep_num]; ++ printk("phys EP %d, config=\"%s\"\n", phys_ep_num, buf); ++ usb_ep=16; ++ dirstr[0] = 0; ++ typestr[0] = 0; ++ dashp = strchr(buf, '-'); ++ if (dashp) { ++ *dashp = ' '; ++ ret = sscanf(buf, "ep%u%15s %15s", &usb_ep, dirstr, typestr); ++ *dashp = '-'; ++ printk("sscanf() ret=%d\n", ret); ++ if (ret != 3) ++ return -EINVAL; ++ } else { ++ ret = sscanf(buf, "ep%u%15s", &usb_ep, dirstr); ++ printk("sscanf() ret=%d\n", ret); ++ if (ret != 2) ++ return -EINVAL; ++ } ++ ++ if (usb_ep > 15) ++ return -ERANGE; ++ ++ if (strcmp(dirstr, "out") == 0) ++ usb_dir = 0; ++ else if (strcmp(dirstr, "in") == 0) ++ usb_dir = 1; ++ else ++ return -ERANGE; ++ ++ if (strcmp(typestr, "ctrl") == 0) ++ usb_type = 0; ++ else if (strcmp(typestr, "iso") == 0) ++ usb_type = 1; ++ else if (strcmp(typestr, "bulk") == 0) ++ usb_type = 2; ++ else if (strcmp(typestr, "int") == 0) ++ usb_type = 3; ++ else ++ usb_type = 4; ++ ++ *usb_ep_num_ret = usb_ep | usb_dir << 4 | usb_type << 6; ++ return 0; ++} ++ ++/** ++ * Activate the changes made by the UTE to the core's features. ++ */ ++void dwc_usb3_ute_config(dwc_usb3_device_t *usb3_dev) ++{ ++ dwc_usb3_pcd_t *pcd = &usb3_dev->pcd; ++ int i, cnt, txsz[DWC_MAX_TX_FIFOS]; ++ ++ dwc_debug(usb3_dev, "%s()\n", __func__); ++ ++ if (!gadget_wrapper) { ++ dwc_warn(usb3_dev, "%s null wrapper!\n", __func__); ++ return; ++ } ++ ++ if (pcd->ute_change) { ++ /* Free any remaining descriptor allocations made for ++ * non-EP0 EPs ++ */ ++ gadget_free_ep_allocations(pcd, gadget_wrapper); ++ ++ /* Set the Tx FIFO sizes */ ++ for (i = 0, cnt = 0; i < pcd->num_in_eps + 1; i++) { ++ txsz[i] = pcd->txf_size[i]; ++ if (txsz[i]) ++ cnt++; ++ } ++ if (cnt) ++ dwc_usb3_set_tx_fifo_size(usb3_dev, txsz); ++ ++ /* Set the Rx FIFO size */ ++ if (pcd->rxf_size) ++ dwc_usb3_set_rx_fifo_size(usb3_dev, pcd->rxf_size); ++ ++ /* Re-initialize non-EP0 EPs to pick up any mapping changes */ ++ if (gadget_init_eps(pcd, gadget_wrapper)) { ++ dwc_error(usb3_dev, "%s, gadget_init_eps error!\n", ++ __func__); ++ } ++ ++ pcd->ute_change = 0; ++ } ++} ++ ++/** ++ * Reset usb endpoint mapping to it's default state. ++ */ ++int dwc_usb3_reset_usb_ep_map(unsigned devnum) ++{ ++ struct gadget_wrapper *d; ++ dwc_usb3_pcd_t *pcd; ++ int i; ++ ++ if (!gadget_wrapper) { ++ printk(KERN_WARNING USB3_DWC "%s null wrapper!\n", __func__); ++ return -ENODEV; ++ } ++ ++ d = gadget_wrapper; ++ pcd = d->pcd; ++ ++ for (i = 0; i < ARRAY_SIZE(g_ep_names) && ++ i < ARRAY_SIZE(d->ep_names) && ++ i < pcd->num_in_eps + pcd->num_out_eps + 1; i++) { ++ strncpy(d->ep_names[i], g_ep_names[i], ++ sizeof(d->ep_names[0]) - 1); ++ d->ep_names[i][sizeof(d->ep_names[0]) - 1] = 0; ++ dwc_debug(pcd->usb3_dev, "~phys EP%d name=%s\n", i, d->ep_names[i]); ++ } ++ ++ return gadget_init_eps(pcd, d); ++} ++ ++int dwc_usb3_switch_speed(unsigned devnum, int speed) ++{ ++ int ret = 0; ++ struct gadget_wrapper *d; ++ dwc_usb3_pcd_t *pcd; ++ dwc_usb3_device_t *usb3_dev; ++ //u32 temp; ++ ++ if (!gadget_wrapper) { ++ printk(KERN_WARNING USB3_DWC "%s null wrapper!\n", __func__); ++ return -ENODEV; ++ } ++ ++ d = gadget_wrapper; ++ pcd = d->pcd; ++ usb3_dev = pcd->usb3_dev; ++ /* ++ temp = dwc_rd32(usb3_dev, &pcd->dev_global_regs->dctl); ++ temp &= ~DWC_DCTL_RUN_STOP_BIT; ++ dwc_wr32(usb3_dev, &pcd->dev_global_regs->dctl, temp); ++ ++ dwc_udelay(usb3_dev, 1500); */ ++ /* Soft-reset the core */ ++ /* temp = dwc_rd32(usb3_dev, &pcd->dev_global_regs->dctl); ++ temp &= ~DWC_DCTL_RUN_STOP_BIT; ++ temp |= DWC_DCTL_CSFT_RST_BIT; ++ dwc_wr32(usb3_dev, &pcd->dev_global_regs->dctl, temp); */ ++ ++ /* Wait for core to come out of reset */ ++ /* do { ++ dwc_udelay(usb3_dev, 1); ++ temp = dwc_rd32(usb3_dev, &pcd->dev_global_regs->dctl); ++ } while (temp & DWC_DCTL_CSFT_RST_BIT); ++ ++ dwc_mdelay(usb3_dev, 2); */ ++ ++ if (speed == 3) { ++ /* Set device speed feature to Super Speed */ ++ speed = 0; ++ } ++ usb3_dev->core_params->usb2mode = speed; ++ ++ dwc_usb3_pcd_device_init(usb3_dev, 1, 0); ++ ++ return ret; ++} ++ ++int dwc_usb3_get_dev_speed(unsigned devnum) ++{ ++ struct gadget_wrapper *d; ++ dwc_usb3_pcd_t *pcd; ++ int ret; ++ ++ if (!gadget_wrapper) { ++ printk(KERN_WARNING USB3_DWC "%s null wrapper!\n", __func__); ++ return -ENODEV; ++ } ++ ++ d = gadget_wrapper; ++ pcd = d->pcd; ++ ++ ret = pcd->usb3_dev->core_params->usb2mode; ++ if (ret == 0) { ++ /* If speed feature is set to Super Speed */ ++ ret = 3; ++ } ++ return ret; ++} ++ ++#endif /* DWC_UTE */ ++ ++/** ++ * This function initializes the Gadget portion of the driver. ++ * ++ * @param usb3_dev Programming view of DWC_usb3 controller. ++ * @param dev The device context. ++ */ ++int dwc_usb3_gadget_init(dwc_usb3_device_t *usb3_dev, struct device *dev) ++{ ++ dwc_usb3_pcd_t *pcd = &usb3_dev->pcd; ++ int retval = -ENOMEM; ++ int hiberbufs = 0; ++ dma_addr_t dma_addr = 0; ++ int i; ++ ++ dwc_debug(usb3_dev, "%s()\n", __func__); ++ dwc_debug(usb3_dev, "pcd=%p\n", pcd); ++ ++ gadget_wrapper = kmalloc(sizeof(struct gadget_wrapper), GFP_KERNEL); ++ if (!gadget_wrapper) ++ goto out1; ++ ++ memset(gadget_wrapper, 0, sizeof(*gadget_wrapper)); ++ gadget_wrapper->pcd = pcd; ++ ++ for (i = 0; i < ARRAY_SIZE(g_ep_names) && ++ i < ARRAY_SIZE(gadget_wrapper->ep_names) && ++ i < pcd->num_in_eps + pcd->num_out_eps + 1; i++) { ++ strncpy(gadget_wrapper->ep_names[i], g_ep_names[i], ++ sizeof(gadget_wrapper->ep_names[0]) - 1); ++ gadget_wrapper->ep_names[i][sizeof(gadget_wrapper->ep_names[0]) - 1] = 0; ++ dwc_debug(usb3_dev, "~phys EP%d name=%s\n", i, ++ gadget_wrapper->ep_names[i]); ++ } ++ ++ gadget_wrapper->gadget.name = "dwc_usb3_pcd"; ++ dwc_debug(usb3_dev, "gadget.name=%s\n", gadget_wrapper->gadget.name); ++ ++#ifdef CONFIG_USB_OTG_DWC ++ gadget_wrapper->gadget.is_otg = 1; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ++ strcpy(gadget_wrapper->gadget.dev.bus_id, "gadget"); ++#else ++ dev_set_name(&gadget_wrapper->gadget.dev, "%s", "gadget"); ++#endif ++ gadget_wrapper->gadget.dev.parent = dev; ++ gadget_wrapper->gadget.dev.release = gadget_release; ++ gadget_wrapper->gadget.speed = USB_SPEED_UNKNOWN; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) ++ gadget_wrapper->gadget.is_dualspeed = 1; ++#else ++ gadget_wrapper->gadget.max_speed = USB_SPEED_SUPER; ++#endif ++ gadget_wrapper->gadget.ops = &pcd_ops; ++ gadget_wrapper->driver = NULL; ++ dwc_debug(usb3_dev, "gadget=%p ops=%p\n", &gadget_wrapper->gadget, ++ gadget_wrapper->gadget.ops); ++ ++ /* Set the PCD's EP0 request pointer to the wrapper's request */ ++ pcd->ep0_req = &gadget_wrapper->ep0_req; ++ ++ /* Set the PCD's EP array pointers to the wrapper's EPs */ ++ pcd->ep0 = &gadget_wrapper->ep0; ++ for (i = 0; i < DWC_MAX_EPS - 1; i++) { ++ pcd->out_ep[i] = &gadget_wrapper->out_ep[i]; ++ pcd->in_ep[i] = &gadget_wrapper->in_ep[i]; ++ } ++ ++ /* Allocate the EP0 packet buffers */ ++ pcd->ep0_setup_pkt = dma_alloc_coherent(NULL, ++ sizeof(*pcd->ep0_setup_pkt) * 5, ++ &pcd->ep0_setup_pkt_dma, GFP_KERNEL | GFP_DMA32); ++ if (!pcd->ep0_setup_pkt) ++ goto out2; ++ ++ pcd->ep0_status_buf = dma_alloc_coherent(NULL, DWC_STATUS_BUF_SIZE, ++ &pcd->ep0_status_buf_dma, GFP_KERNEL | GFP_DMA32); ++ if (!pcd->ep0_status_buf) ++ goto out3; ++ ++ /* Allocate the EP0 DMA descriptors */ ++ pcd->ep0_setup_desc = dma_alloc_coherent(NULL, ++ sizeof(dwc_usb3_dma_desc_t), &pcd->ep0_setup_desc_dma, ++ GFP_KERNEL | GFP_DMA32); ++ if (!pcd->ep0_setup_desc) ++ goto out4; ++ ++ pcd->ep0_in_desc = dma_alloc_coherent(NULL, sizeof(dwc_usb3_dma_desc_t), ++ &pcd->ep0_in_desc_dma, GFP_KERNEL | GFP_DMA32); ++ if (!pcd->ep0_in_desc) ++ goto out5; ++ ++ pcd->ep0_out_desc = dma_alloc_coherent(NULL, ++ sizeof(dwc_usb3_dma_desc_t), &pcd->ep0_out_desc_dma, ++ GFP_KERNEL | GFP_DMA32); ++ if (!pcd->ep0_out_desc) ++ goto out6; ++ ++ /* If hibernation is supported */ ++ if (usb3_dev->core_params->hibernate && ++ (usb3_dev->hwparams1 & DWC_HWP1_EN_PWROPT_BITS) == ++ DWC_EN_PWROPT_HIBERNATION << DWC_HWP1_EN_PWROPT_SHIFT) { ++ hiberbufs = usb3_dev->hwparams4 >> DWC_HWP4_HIBER_SPAD_SHIFT & ++ DWC_HWP4_HIBER_SPAD_BITS >> DWC_HWP4_HIBER_SPAD_SHIFT; ++ if (hiberbufs) { ++ /* Allocate scratch buffer pointer array */ ++ pcd->hiber_scratchpad_array = ++ dma_alloc_coherent(NULL, ++ sizeof(*pcd->hiber_scratchpad_array), ++ &pcd->hiber_scratchpad_array_dma, ++ GFP_KERNEL | GFP_DMA32); ++ if (!pcd->hiber_scratchpad_array) { ++ dwc_debug(usb3_dev, ++ "%s hibernation array allocation error\n", ++ __func__); ++ goto out7; ++ } ++ } ++ ++ /* Allocate scratch buffers */ ++ for (i = 0; i < hiberbufs; i++) { ++ pcd->hiber_scratchpad[i] = ++ dma_alloc_coherent(NULL, 4096, &dma_addr, ++ GFP_KERNEL | GFP_DMA32); ++ if (!pcd->hiber_scratchpad[i]) { ++ dwc_debug(usb3_dev, ++ "%s hibernation buf allocation error\n", ++ __func__); ++ while (i-- > 0) { ++ dma_addr = (dma_addr_t)pcd-> ++ hiber_scratchpad_array->dma_addr[i]; ++ dma_free_coherent(NULL, 4096, ++ pcd->hiber_scratchpad[i], ++ dma_addr); ++ pcd->hiber_scratchpad[i] = NULL; ++ } ++ ++ goto out8; ++ } ++ ++ pcd->hiber_scratchpad_array->dma_addr[i] = (u64)dma_addr; ++ } ++ } ++ ++ /* Initialize all the EP structures */ ++ gadget_init_ep0(pcd, gadget_wrapper); ++ retval = gadget_init_eps(pcd, gadget_wrapper); ++ if (retval) { ++ dwc_debug(usb3_dev, "%s gadget_init_eps error\n", __func__); ++ goto out9; ++ } ++ ++ /* Register the gadget device */ ++ retval = device_register(&gadget_wrapper->gadget.dev); ++ if (retval) { ++ dwc_debug(usb3_dev, "%s cannot register gadget device\n", ++ __func__); ++ goto out10; ++ } ++ ++ return 0; ++ ++out10: ++ gadget_free_ep_allocations(pcd, gadget_wrapper); ++out9: ++ for (i = hiberbufs - 1; i >= 0; i--) { ++ if (pcd->hiber_scratchpad[i]) { ++ dma_addr = (dma_addr_t) ++ pcd->hiber_scratchpad_array->dma_addr[i]; ++ dma_free_coherent(NULL, 4096, pcd->hiber_scratchpad[i], ++ dma_addr); ++ pcd->hiber_scratchpad[i] = NULL; ++ } ++ } ++out8: ++ if (hiberbufs) ++ dma_free_coherent(NULL, sizeof(*pcd->hiber_scratchpad_array), ++ pcd->hiber_scratchpad_array, ++ pcd->hiber_scratchpad_array_dma); ++out7: ++ dma_free_coherent(NULL, sizeof(dwc_usb3_dma_desc_t), pcd->ep0_out_desc, ++ pcd->ep0_out_desc_dma); ++out6: ++ dma_free_coherent(NULL, sizeof(dwc_usb3_dma_desc_t), pcd->ep0_in_desc, ++ pcd->ep0_in_desc_dma); ++out5: ++ dma_free_coherent(NULL, sizeof(dwc_usb3_dma_desc_t), ++ pcd->ep0_setup_desc, pcd->ep0_setup_desc_dma); ++out4: ++ dma_free_coherent(NULL, DWC_STATUS_BUF_SIZE, pcd->ep0_status_buf, ++ pcd->ep0_status_buf_dma); ++out3: ++ dma_free_coherent(NULL, sizeof(*pcd->ep0_setup_pkt) * 5, ++ pcd->ep0_setup_pkt, pcd->ep0_setup_pkt_dma); ++out2: ++ kfree(gadget_wrapper); ++ gadget_wrapper = NULL; ++out1: ++ return retval; ++} ++ ++/** ++ * Cleanup the Gadget. ++ * ++ * @param usb3_dev Programming view of DWC_usb3 controller. ++ * @param dev The device context. ++ */ ++void dwc_usb3_gadget_remove(dwc_usb3_device_t *usb3_dev, struct device *dev) ++{ ++ dwc_usb3_pcd_t *pcd = &usb3_dev->pcd; ++ int hiberbufs, i; ++ void *addr; ++ dma_addr_t dma_addr; ++ ++ dwc_debug(usb3_dev, "%s()\n", __func__); ++ dwc_debug(usb3_dev, "pcd=%p\n", pcd); ++ ++ if (!gadget_wrapper) { ++ dwc_warn(usb3_dev, "%s null wrapper!\n", __func__); ++ return; ++ } ++ ++ /* start with the driver above us */ ++ if (gadget_wrapper->driver) { ++ /* should have been done already by driver model core */ ++ dwc_warn(usb3_dev, "driver '%s' is still registered!\n", ++ gadget_wrapper->driver->driver.name); ++ usb_gadget_unregister_driver(gadget_wrapper->driver); ++ } ++ ++ device_unregister(&gadget_wrapper->gadget.dev); ++ gadget_free_ep_allocations(pcd, gadget_wrapper); ++ ++ /* If hibernation is supported */ ++ if (usb3_dev->core_params->hibernate && ++ (usb3_dev->hwparams1 & DWC_HWP1_EN_PWROPT_BITS) == ++ DWC_EN_PWROPT_HIBERNATION << DWC_HWP1_EN_PWROPT_SHIFT) { ++ hiberbufs = usb3_dev->hwparams4 >> DWC_HWP4_HIBER_SPAD_SHIFT & ++ DWC_HWP4_HIBER_SPAD_BITS >> DWC_HWP4_HIBER_SPAD_SHIFT; ++ ++ /* Free hibernation scratch buffers */ ++ for (i = hiberbufs - 1; i >= 0; i--) { ++ addr = pcd->hiber_scratchpad[i]; ++ dma_addr = (dma_addr_t)pcd->hiber_scratchpad_array->dma_addr[i]; ++ pcd->hiber_scratchpad[i] = NULL; ++ if (addr) ++ dma_free_coherent(NULL, 4096, addr, dma_addr); ++ } ++ ++ if (hiberbufs) ++ dma_free_coherent(NULL, ++ sizeof(*pcd->hiber_scratchpad_array), ++ pcd->hiber_scratchpad_array, ++ pcd->hiber_scratchpad_array_dma); ++ } ++ ++ dma_free_coherent(NULL, sizeof(dwc_usb3_dma_desc_t), pcd->ep0_out_desc, ++ pcd->ep0_out_desc_dma); ++ dma_free_coherent(NULL, sizeof(dwc_usb3_dma_desc_t), pcd->ep0_in_desc, ++ pcd->ep0_in_desc_dma); ++ dma_free_coherent(NULL, sizeof(dwc_usb3_dma_desc_t), pcd->ep0_setup_desc, ++ pcd->ep0_setup_desc_dma); ++ dma_free_coherent(NULL, DWC_STATUS_BUF_SIZE, pcd->ep0_status_buf, ++ pcd->ep0_status_buf_dma); ++ dma_free_coherent(NULL, sizeof(*pcd->ep0_setup_pkt) * 5, ++ pcd->ep0_setup_pkt, pcd->ep0_setup_pkt_dma); ++ ++ kfree(gadget_wrapper); ++ gadget_wrapper = NULL; ++} ++ ++/** ++ * This function registers a gadget driver with the PCD. ++ * ++ * When a driver is successfully registered, it will receive control ++ * requests including set_configuration(), which enables non-control ++ * requests. Then usb traffic follows until a disconnect is reported. ++ * Then a host may connect again, or the driver might get unbound. ++ * ++ * @param driver The driver being registered. ++ * @param bind The gadget driver's bind function. ++ */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) ++int usb_gadget_register_driver(struct usb_gadget_driver *driver) ++#else ++int usb_gadget_probe_driver(struct usb_gadget_driver *driver ++# if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) ++ , int (*bind)(struct usb_gadget *) ++# endif ++ ) ++#endif ++{ ++ dwc_usb3_pcd_t *pcd; ++ int retval = -ENODEV; ++#ifdef CONFIG_USB_OTG_DWC ++ struct usb_phy *phy; ++ struct usb_otg *otg; ++#endif ++ ++ printk(KERN_DEBUG USB3_DWC "%s(%p)\n", __func__, driver); ++ printk(KERN_DEBUG USB3_DWC "gdt_wrp=%p\n", gadget_wrapper); ++ ++ if (!gadget_wrapper) ++ goto out; ++ ++ pcd = gadget_wrapper->pcd; ++ printk(KERN_DEBUG USB3_DWC "pcd=%p\n", pcd); ++ ++ if (!pcd) { ++ printk(KERN_DEBUG USB3_DWC "ENODEV\n"); ++ goto out; ++ } ++ ++ if (!driver || ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) ++ driver->speed == USB_SPEED_UNKNOWN || ++#else ++ driver->max_speed == USB_SPEED_UNKNOWN || ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) || \ ++ LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ !driver->bind || ++#endif ++ !driver->unbind || ++ !driver->disconnect || !driver->setup) { ++ printk(KERN_DEBUG USB3_DWC "EINVAL\n"); ++ retval = -EINVAL; ++ goto out; ++ } ++ ++ printk(KERN_DEBUG USB3_DWC "registering gadget driver '%s'\n", ++ driver->driver.name); ++ ++ if (gadget_wrapper->driver) { ++ printk(KERN_DEBUG USB3_DWC "EBUSY (%p)\n", ++ gadget_wrapper->driver); ++ retval = -EBUSY; ++ goto out; ++ } ++ ++#ifdef CONFIG_USB_OTG_DWC ++ /* Check that the otg transceiver driver is loaded */ ++ phy = usb_get_phy(USB_PHY_TYPE_USB3); ++ if (IS_ERR(phy) || !phy) { ++ printk(KERN_DEBUG USB3_DWC "OTG PHY not available!\n"); ++ if (!IS_ERR(phy)) ++ usb_put_phy(phy); ++ goto out; ++ } ++ ++ otg = phy->otg; ++ usb_put_phy(phy); ++ if (!otg) { ++ printk(KERN_DEBUG USB3_DWC "OTG not available!\n"); ++ goto out; ++ } ++#endif ++ ++ /* hook up the driver */ ++ gadget_wrapper->driver = driver; ++ gadget_wrapper->gadget.dev.driver = &driver->driver; ++ pcd->gadget = &gadget_wrapper->gadget; ++ ++ dwc_debug(pcd->usb3_dev, "bind to driver %s\n", driver->driver.name); ++ dwc_debug(pcd->usb3_dev, "&gadget_gadget_wrapper->gadget = %p\n", ++ &gadget_wrapper->gadget); ++ dwc_debug(pcd->usb3_dev, "gadget_gadget_wrapper->driver = %p\n", ++ gadget_wrapper->driver); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) ++ retval = driver->bind(&gadget_wrapper->gadget); ++#else ++# if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ retval = driver->bind(&gadget_wrapper->gadget, ++ gadget_wrapper->driver); ++# else ++ retval = bind(&gadget_wrapper->gadget); ++# endif ++#endif ++ if (retval) { ++ dwc_error(pcd->usb3_dev, "bind to driver %s --> error %d\n", ++ driver->driver.name, retval); ++ gadget_wrapper->driver = NULL; ++ gadget_wrapper->gadget.dev.driver = NULL; ++ pcd->gadget = NULL; ++ goto out; ++ } ++ ++#ifdef CONFIG_USB_OTG_DWC ++ phy = usb_get_phy(USB_PHY_TYPE_USB3); ++ if (!IS_ERR(phy)) { ++ if (phy && phy->otg) ++ otg_set_peripheral(phy->otg, &gadget_wrapper->gadget); ++ usb_put_phy(phy); ++ } ++#endif ++ ++ printk(KERN_DEBUG USB3_DWC "registered gadget driver '%s'\n", ++ driver->driver.name); ++out: ++#ifdef CONFIG_USB_OTG_DWC ++ /* Switch otg to host mode now that gadget is bound */ ++ phy = usb_get_phy(USB_PHY_TYPE_USB3); ++ if (!IS_ERR(phy)) { ++ if (phy && phy->otg) ++ dwc_otg3_set_peripheral(phy->otg, 0); ++ usb_put_phy(phy); ++ } ++#endif ++ return retval; ++} ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) ++EXPORT_SYMBOL_GPL(usb_gadget_register_driver); ++#else ++EXPORT_SYMBOL_GPL(usb_gadget_probe_driver); ++#endif ++ ++/** ++ * This function unregisters a gadget driver ++ * ++ * @param driver The driver being unregistered. ++ */ ++int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) ++{ ++#ifdef CONFIG_USB_OTG_DWC ++ struct usb_phy *phy; ++ struct usb_otg *otg; ++#endif ++ ++ printk(KERN_DEBUG USB3_DWC "%s(%p)\n", __func__, driver); ++ printk(KERN_DEBUG USB3_DWC "unregistering gadget driver '%s'\n", ++ driver->driver.name); ++ ++ if (!gadget_wrapper) ++ return -ENODEV; ++ ++ if (!gadget_wrapper->pcd) { ++ printk(KERN_DEBUG USB3_DWC "%s Return(%d): pcd==NULL\n", ++ __func__, -ENODEV); ++ return -ENODEV; ++ } ++ ++ if (!gadget_wrapper->driver || driver != gadget_wrapper->driver) { ++ printk(KERN_DEBUG USB3_DWC "%s Return(%d): driver?\n", ++ __func__, -EINVAL); ++ return -EINVAL; ++ } ++ ++#ifdef CONFIG_USB_OTG_DWC ++ phy = usb_get_phy(USB_PHY_TYPE_USB3); ++ otg = phy->otg; ++ otg_set_peripheral(otg, NULL); ++ usb_put_phy(phy); ++#endif ++ ++ driver->disconnect(&gadget_wrapper->gadget); ++ driver->unbind(&gadget_wrapper->gadget); ++ gadget_wrapper->driver = NULL; ++ gadget_wrapper->gadget.dev.driver = NULL; ++ gadget_wrapper->pcd->gadget = NULL; ++ ++ printk(KERN_DEBUG USB3_DWC "unregistered gadget driver '%s'\n", ++ driver->driver.name); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(usb_gadget_unregister_driver); ++ ++//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) ++int udc_attach_driver(const char *name, struct usb_gadget_driver *driver) ++{ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(udc_attach_driver); ++//#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) ++void usb_gadget_set_state(struct usb_gadget *gadget, ++ enum usb_device_state state) ++{ ++ gadget->state = state; ++} ++EXPORT_SYMBOL_GPL(usb_gadget_set_state); ++#endif ++ ++MODULE_DESCRIPTION(DWC_DRIVER_DESC); ++MODULE_AUTHOR("Synopsys Inc."); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/usb/gadget/udc/hiudc3/linux_hiber.c b/drivers/usb/gadget/udc/hiudc3/linux_hiber.c +new file mode 100644 +index 0000000..8e77e97 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/linux_hiber.c +@@ -0,0 +1,282 @@ ++/** @file ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++ ++void dwc_usb3_task_schedule(struct tasklet_struct *tasklet) ++{ ++ tasklet_schedule(tasklet); ++} ++ ++/** ++ * Helper routine for dwc_wait_pme_thread() ++ */ ++static void dwc_wait_for_link_up(dwc_usb3_pcd_t *pcd) ++{ ++ unsigned long flags; ++ u32 state; ++ int count = 5; ++ ++ while (count-- > 0) { ++ msleep(20); ++ spin_lock_irqsave(&pcd->lock, flags); ++ state = dwc_usb3_pcd_get_link_state(pcd); ++ pcd->link_state = state; ++ if (state == DWC_LINK_STATE_U0) { ++ dwc_debug(pcd->usb3_dev, ++ "Exiting from hibernation 2\n"); ++ pcd->usb3_dev->hiber_wait_connect = 0; ++ ++ /* Perform the steps in Section 9.1.3 "Initialization on ++ * Connect Done" in [DWSS]. ++ */ ++ dwc_usb3_handle_connect_done_intr(pcd); ++ dwc_exit_hibernation_after_connect(pcd, 0); ++ count = 0; ++ } ++ ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ } ++} ++ ++/** ++ * Kernel thread that monitors the usb3_dev->hibernate variable. usb3_dev-> ++ * hibernate is set to 1 or 2 from the interrupt handler when the core is ++ * requesting to enter hibernation. This thread checks whether it is safe to ++ * do so (usb3_dev->hiber_cnt == 0) and then sets usb3_dev->hibernate to 3 and ++ * puts the core into hibernation. usb3_dev->hibernate >= 3 tells the rest of ++ * the driver that it cannot access the hardware. ++ * ++ * This thread also handles some housekeeping work that must be done after the ++ * core has exited from hibernation. ++ * ++ * Note that this is NOT the way a "real" device would enter hibernation. This ++ * code is ONLY for testing hibernation on the Synopsys HAPS platform. ++ */ ++int dwc_wait_pme_thread(void *data) ++{ ++ dwc_usb3_pcd_t *pcd = (dwc_usb3_pcd_t *)data; ++ dwc_usb3_device_t *dev = pcd->usb3_dev; ++ unsigned long flags; ++ u32 state, temp; ++ int i; ++ int cnt = 0; ++ ++ dwc_debug(dev, "%s(%p)\n", __func__, data); ++ ++ /* Allow the thread to be killed by a signal, but set the signal mask ++ * to block everything but INT, TERM, KILL, and USR1. */ ++ allow_signal(SIGINT); ++ allow_signal(SIGTERM); ++ allow_signal(SIGKILL); ++ allow_signal(SIGUSR1); ++ ++ set_user_nice(current, -10); ++ ++ /* Allow the thread to be frozen */ ++ set_freezable(); ++ ++ for (;;) { ++ spin_lock_irqsave(&pcd->lock, flags); ++ state = dev->hibernate; ++ ++ if (dev->hiber_cnt == 0) { ++ if (state == DWC_HIBER_ENTER_NOSAVE || ++ state == DWC_HIBER_ENTER_SAVE) { ++ dwc_enter_hibernation(pcd, ++ state == DWC_HIBER_ENTER_SAVE); ++ state = DWC_HIBER_SLEEPING; ++ } ++ } ++ ++ if (state != DWC_HIBER_SLEEPING && dev->snpsid >= 0x5533230a && ++ dev->hiber_wait_u0) { ++ /* Handle waiting for U0 after requesting link state ++ * RECOVERY, because we don't have the link state ++ * change event enabled. We also do this in ++ * dwc_usb3_irq() in case an event comes first. ++ */ ++ temp = dwc_usb3_pcd_get_link_state(pcd); ++ pcd->link_state = temp; ++ ++ if (cnt-- == 0) { ++ cnt = 500; ++ dwc_debug1(pcd->usb3_dev, ++ "thread WAIT_U0 state=%d\n", temp); ++ } ++ ++ if (temp == DWC_LINK_STATE_U0) { ++ dwc_debug0(dev, ++ "thread WAIT_U0 setting speed\n"); ++ pcd->speed = dwc_usb3_get_device_speed(pcd); ++ if (pcd->remote_wakeup_enable) ++ dwc_usb3_pcd_remote_wake(pcd, 0); ++ dev->hiber_wait_u0 = 0; ++ } ++ } ++ ++ if (state == DWC_HIBER_WAIT_LINK_UP) { ++ dev->hibernate = DWC_HIBER_AWAKE; ++ state = DWC_HIBER_AWAKE; ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ dwc_wait_for_link_up(pcd); ++ spin_lock_irqsave(&pcd->lock, flags); ++ } ++ ++ if (state == DWC_HIBER_SS_DIS_QUIRK) { ++ for (i = 0; i < 500; i++) { ++ if (dev->hibernate != DWC_HIBER_SS_DIS_QUIRK) { ++ dwc_info(dev, ++ "breaking loop after %d ms\n", ++ i); ++ break; ++ } ++ ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ msleep(1); ++ spin_lock_irqsave(&pcd->lock, flags); ++ } ++ ++ if (dev->hibernate == DWC_HIBER_SS_DIS_QUIRK) { ++ temp = dwc_usb3_pcd_get_link_state(pcd); ++ pcd->link_state = temp; ++ if (temp == DWC_LINK_STATE_SS_DIS) ++ dwc_enter_hibernation(pcd, 0); ++ else ++ dev->hibernate = DWC_HIBER_AWAKE; ++ } ++ } ++ ++ spin_unlock_irqrestore(&pcd->lock, flags); ++ if (kthread_should_stop()) ++ break; ++ msleep(1); ++ } ++ ++ return 0; ++} ++ ++/** ++ * Fake PME interrupt handler, called from dwc_usb3_irq() in cil_intr.c if ++ * the core is in hibernation and any interrupt is received. The custom PCIe ++ * "gasket" on the HAPS platform generates an interrupt when the core requests ++ * to exit hibernation. ++ * ++ * This function reads the Debug register at offset 16 in the gasket, to make ++ * sure the core is requesting to exit hibernation. If so, it brings the core ++ * out of hibernation. ++ * ++ * Note that this is NOT the way a "real" device would exit hibernation. This ++ * code is ONLY for testing hibernation on the Synopsys HAPS platform. ++ */ ++int dwc_usb3_handle_pme_intr(dwc_usb3_device_t *dev) ++{ ++ u32 temp, test1, test2; ++ u8 __iomem *base_addr; ++ int ret; ++ ++ dwc_debug(dev, "%s()\n", __func__); ++ ++ if (dev->gasket_base) ++ base_addr = (u8 __iomem *)dev->gasket_base; ++ else ++ base_addr = (u8 __iomem *)dev->base + dev->gasket_ofs; ++ ++ if ((dev->hwparams3 & DWC_HWP3_SSPHY_IFC_BITS) == 0) { ++ test1 = 0x40; ++ test2 = 0x80; ++ } else { ++ test1 = 0x44; ++ test2 = 0x88; ++ } ++ ++ temp = dwc_rd32(dev, (volatile u32 __iomem *)(base_addr + 16)); ++ if ((temp & test1) != 0) { ++ dwc_debug(dev, "calling dwc_exit_hibernation() Debug=%01x\n", ++ temp); ++ ret = dwc_exit_hibernation(&dev->pcd, (temp & test2) != 0); ++ if (ret) ++ dwc_debug(dev, "dwc_exit_hibernation() returned %d\n", ++ ret); ++ } ++ ++ return 1; ++} ++ ++/** ++ * Routine to enable and disable power to the core. The custom PCIe "gasket" on ++ * the HAPS platform provides this capability through the R1 register at offset ++ * 4. ++ * ++ * Note that this is NOT the way a "real" device would control the power. This ++ * code is ONLY for testing hibernation on the Synopsys HAPS platform. ++ */ ++void dwc_usb3_power_ctl(dwc_usb3_device_t *dev, int on) ++{ ++ u32 temp, test; ++ u8 __iomem *base_addr; ++ int cnt; ++ ++ dwc_debug(dev, "%s(%1x)\n", __func__, on); ++ ++ if (dev->gasket_base) ++ base_addr = (u8 __iomem *)dev->gasket_base; ++ else ++ base_addr = (u8 __iomem *)dev->base + dev->gasket_ofs; ++ ++ if ((dev->hwparams3 & DWC_HWP3_SSPHY_IFC_BITS) == 0) ++ test = 0x30; ++ else ++ test = 0x33; ++ ++ if (on) { ++ temp = dwc_rd32(dev, (volatile u32 __iomem *)(base_addr + 4)); ++ dwc_debug(dev, "R1=%01x before write\n", temp); ++ temp &= ~0x3000; ++ dwc_wr32(dev, (volatile u32 __iomem *)(base_addr + 4), temp); ++ temp = dwc_rd32(dev, (volatile u32 __iomem *)(base_addr + 4)); ++ dwc_debug(dev, "R1=%01x after write\n", temp); ++ ++ /* Wait until both PMUs confirm that they have entered D0 */ ++ dwc_debug(dev, "Asked for D0 state, waiting for response\n"); ++ cnt = 0; ++ do { ++ udelay(1); ++ temp = dwc_rd32(dev, (volatile u32 __iomem *) ++ (base_addr + 16)); ++ if (++cnt > 10000000) { ++ cnt = 0; ++ dwc_debug(dev, "%01x\n", temp); ++ //break; ++ } ++ } while ((temp & test) != 0); ++ } else { ++ temp = dwc_rd32(dev, (volatile u32 __iomem *)(base_addr + 4)); ++ dwc_debug(dev, "R1=%01x before write\n", temp); ++ temp |= 0x3000; ++ dwc_wr32(dev, (volatile u32 __iomem *)(base_addr + 4), temp); ++ temp = dwc_rd32(dev, (volatile u32 __iomem *)(base_addr + 4)); ++ dwc_debug(dev, "R1=%01x after write\n", temp); ++ ++ /* Wait until both PMUs confirm that they have entered D3 */ ++ dwc_debug(dev, "Asked for D3 state, waiting for response\n"); ++ ++ cnt = 0; ++ do { ++ udelay(1); ++ temp = dwc_rd32(dev, (volatile u32 __iomem *) ++ (base_addr + 16)); ++ if (++cnt > 10000000) { ++ cnt = 0; ++ dwc_debug(dev, "%01x\n", temp); ++ //break; ++ } ++ } while ((temp & test) != test); ++ } ++} +diff --git a/drivers/usb/gadget/udc/hiudc3/linux_pci.c b/drivers/usb/gadget/udc/hiudc3/linux_pci.c +new file mode 100644 +index 0000000..fd27cfa +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/linux_pci.c +@@ -0,0 +1,689 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/DWC_usb3/driver/linux/linux_pci.c $ ++ * $Revision: #16 $ ++ * $Date: 2014/11/11 $ ++ * $Change: 2664766 $ ++ * ++ * Synopsys SS USB3 Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++/** @file ++ * The driver module provides the initialization and cleanup entry ++ * points for the DWC_usb3 driver. This module will be dynamically installed ++ * after Linux is booted using the insmod command. When the module is ++ * installed, the driver_init function is called. When the module is ++ * removed (using rmmod), the driver_cleanup function is called. ++ * ++ * This module also defines a data structure for the driver, which is ++ * used in conjunction with the standard pci_dev structure. These ++ * structures allow the USB3 driver to comply with the standard Linux driver ++ * model in which devices and drivers are registered with a bus driver. This ++ * has the benefit that Linux can expose attributes of the driver and device ++ * in its special sysfs file system. Users can then read or write files in ++ * this file system to perform diagnostics on the driver components or the ++ * device. ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++ ++#ifdef CONFIG_USB_OTG_DWC ++extern int dwc_otg3_irq(struct usb_otg *otg); ++extern void dwc_otg3_set_peripheral(struct usb_otg *otg, int yes); ++#endif ++ ++#define PCI_VENDOR_ID_SYNOPSYS 0x16c3 ++#define PCI_DEVICE_ID_SYNOPSYS_SITKA 0xabcd ++#define PCI_DEVICE_ID_SYNOPSYS_HAPS_AXI 0xabce ++ ++static const char dwc_driver_name[] = "dwc_usb3"; ++ ++/* ++ * Hook to override the default Phy configuration in dwc_usb3_pcd_device_init() ++ * with a HAPS-specific one ++ */ ++static void haps_phy_config_hook(struct dwc_usb3_device *dev, int soft_reset, ++ int restore) ++{ ++ dwc_usb3_core_global_regs_t __iomem *global_regs = ++ dev->core_global_regs; ++ u32 temp; ++ ++ switch (dev->core_params->phy) { ++ case 3: // 16-bit UTMI+ SNPS Phy ++ temp = dwc_rd32(dev, &global_regs->gusb2phycfg[0]); ++ temp &= ~DWC_USB2PHYCFG_USB_TRD_TIM_BITS; ++ temp |= DWC_USB2PHYCFG_16B_PHY_IF_BIT; ++ temp |= 5 << DWC_USB2PHYCFG_USB_TRD_TIM_SHIFT; ++ dwc_wr32(dev, &global_regs->gusb2phycfg[0], temp); ++ break; ++ case 2: // 8-bit UTMI+ / ULPI TI or SNPS Phy ++ case 1: // old 8-bit UTMI+ SNPS Phy ++ temp = dwc_rd32(dev, &global_regs->gusb2phycfg[0]); ++ temp &= ~DWC_USB2PHYCFG_USB_TRD_TIM_BITS; ++ temp &= ~DWC_USB2PHYCFG_16B_PHY_IF_BIT; ++ temp |= 9 << DWC_USB2PHYCFG_USB_TRD_TIM_SHIFT; ++ dwc_wr32(dev, &global_regs->gusb2phycfg[0], temp); ++ break; ++ default: // RocketIO Phy ++ if (dev->core_params->usb2mode == 0) { ++ /* Set rx-eq, differential swing */ ++ dwc_wr32(dev, (volatile u32 __iomem *) ++ (dev->base + dev->gasket_ofs + 8), 0x41); ++#ifdef LECROY ++ /* Rx-detect for LeCroy */ ++ dwc_wr32(dev, (volatile u32 __iomem *) ++ (dev->base + dev->gasket_ofs + 4), 0x200); ++#else ++ dwc_wr32(dev, (volatile u32 __iomem *) ++ (dev->base + dev->gasket_ofs + 4), 0); ++#endif ++ } ++ } ++} ++ ++/** ++ * This function is the top level interrupt handler for the Common ++ * (Core and Device) interrupts. ++ */ ++static irqreturn_t dwc_usb3_common_irq(int irq, void *dev ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ++ , struct pt_regs *regs ++#endif ++ ) ++{ ++ dwc_usb3_device_t *usb3_dev = dev; ++ int retval = 0; ++ ++#ifdef CONFIG_USB_OTG_DWC ++ u32 gsts = 0; ++ int temp = usb3_dev->hibernate; ++ ++ /* Skip OTG IRQ handler if in hibernation */ ++ if (temp < DWC_HIBER_SLEEPING) { ++ gsts = dwc_rd32(usb3_dev, &usb3_dev->core_global_regs->gsts); ++ } else { ++ dwc_info(usb3_dev, "%s() possible OTG IRQ in hibernation\n", ++ __func__); ++ retval = 1; ++ } ++ ++ if (gsts & DWC_GSTS_OTG_EVT_PENDING_BIT || ++ gsts & DWC_GSTS_ADP_EVT_PENDING_BIT || ++ gsts & DWC_GSTS_BC_EVT_PENDING_BIT) { ++ struct usb_phy *phy = usb_get_phy(USB_PHY_TYPE_USB3); ++ ++ if (!IS_ERR(phy)) { ++ dwc_info(usb3_dev, "%s() OTG IRQ\n", __func__); ++ dwc_info(usb3_dev, "gsts = %08x\n", gsts); ++ if (phy && phy->otg) ++ dwc_otg3_irq(phy->otg); ++ else ++ dwc_info(usb3_dev, "OTG IRQ but no OTG\n"); ++ usb_put_phy(phy); ++ } else { ++ dwc_info(usb3_dev, "%s() OTG IRQ but no PHY\n", ++ __func__); ++ } ++ ++ retval = 1; ++ } ++ ++ if (temp >= DWC_HIBER_SLEEPING || (gsts & DWC_GSTS_DEV_EVT_PENDING_BIT)) ++#endif ++ { ++ spin_lock(&usb3_dev->pcd.lock); ++ retval = dwc_usb3_irq(usb3_dev, irq); ++ spin_unlock(&usb3_dev->pcd.lock); ++ } ++ ++ return IRQ_RETVAL(retval); ++} ++ ++#ifdef DWC_UTE ++static void dwc_usb3_save_fifosiz_def_vals(dwc_usb3_device_t *dev) ++{ ++ unsigned i, size; ++ dwc_usb3_pcd_t *pcd; ++ ++ if (!dev) ++ return; ++ ++ pcd = &dev->pcd; ++ ++ for (i = 0; i < pcd->num_in_eps + 1; i++) { ++ size = dwc_rd32(dev, &dev->core_global_regs->gtxfifosiz[i]) & ++ DWC_FIFOSZ_DEPTH_BITS; ++ dwc_print(dev, "Saving %d TxFIFO default size: %d\n", i, size); ++ pcd->def_txf_size[i] = size; ++ } ++ ++ size = dwc_rd32(dev, &dev->core_global_regs->grxfifosiz[0]) & ++ DWC_FIFOSZ_DEPTH_BITS; ++ pcd->def_rxf_size = size; ++ ++ dwc_print(dev, "Saving RxFIFO default size: %d\n", size); ++} ++#endif ++ ++/** ++ * This function is called when a pci_dev is unregistered with the ++ * dwc_usb3_driver. This happens, for example, when the rmmod command is ++ * executed. The device may or may not be electrically present. If it is ++ * present, the driver stops device processing. Any resources used on behalf ++ * of this device are freed. ++ * ++ * @param dev pci_dev struct ++ */ ++static void dwc_usb3_driver_remove(struct pci_dev *dev) ++{ ++ dwc_usb3_device_t *usb3_dev = pci_get_drvdata(dev); ++ u32 *event_buf; ++ dwc_dma_t event_buf_dma; ++ ++#ifdef CONFIG_USB_OTG_DWC ++ struct usb_phy *phy; ++#endif ++ ++ dev_dbg(&dev->dev, "%s(%p)\n", __func__, dev); ++ ++ if (!usb3_dev) { ++ /* Memory allocation for the dwc_usb3_device failed */ ++ dev_dbg(&dev->dev, "%s: usb3_dev NULL\n", __func__); ++ goto disable; ++ } ++ ++#ifdef CONFIG_USB_OTG_DWC ++ /* Switch otg to peripheral mode */ ++ phy = usb_get_phy(USB_PHY_TYPE_USB3); ++ if (!IS_ERR(phy)) { ++ if (phy && phy->otg) ++ dwc_otg3_set_peripheral(phy->otg, 1); ++ usb_put_phy(phy); ++ } ++#endif ++ ++ /* ++ * Free the IRQ ++ */ ++ if (usb3_dev->cmn_irq_installed) { ++ usb3_dev->cmn_irq_installed = 0; ++ free_irq(dev->irq, usb3_dev); ++ } ++ ++ if (usb3_dev->pme_thread) { ++ kthread_stop(usb3_dev->pme_thread); ++ usb3_dev->pme_thread = NULL; ++ } ++ ++ if (usb3_dev->pcd_initialized) { ++ usb3_dev->pcd_initialized = 0; ++ dwc_usb3_pcd_remove(usb3_dev); ++ } ++ ++ if (usb3_dev->gadget_initialized) { ++ usb3_dev->gadget_initialized = 0; ++ dwc_usb3_gadget_remove(usb3_dev, &dev->dev); ++ } ++ ++ if (usb3_dev->cmn_initialized) { ++ usb3_dev->cmn_initialized = 0; ++ dwc_usb3_pcd_common_remove(usb3_dev); ++ } ++ ++ event_buf = usb3_dev->event_buf[0]; ++ event_buf_dma = usb3_dev->event_buf_dma[0]; ++ if (event_buf) { ++ dwc_usb3_dis_flush_eventbuf_intr(usb3_dev, 0); ++ usb3_dev->event_buf[0] = NULL; ++ dma_free_coherent(NULL, DWC_EVENT_BUF_SIZE * sizeof(u32), ++ event_buf, event_buf_dma); ++ } ++ ++ if (usb3_dev->sysfs_initialized) { ++ dwc_usb3_remove_dev_files(&dev->dev); ++ usb3_dev->sysfs_initialized = 0; ++ } ++ ++ /* ++ * Clear the drvdata pointer. ++ */ ++ pci_set_drvdata(dev, NULL); ++ ++ /* ++ * Return the memory. ++ */ ++ if (usb3_dev->base) ++ iounmap((void __iomem *)usb3_dev->base); ++ if (usb3_dev->rsrc_start) ++ release_mem_region(usb3_dev->rsrc_start, usb3_dev->rsrc_len); ++ if (usb3_dev->gasket_base) ++ iounmap((void __iomem *)usb3_dev->gasket_base); ++ if (usb3_dev->gasket_start) ++ release_mem_region(usb3_dev->gasket_start, usb3_dev->gasket_len); ++ ++ kfree(usb3_dev); ++ ++disable: ++ //pci_disable_device(dev); ++ return; ++} ++ ++/** ++ * This function is called when a pci_dev is bound to a ++ * dwc_usb3_driver. It creates the driver components required to ++ * control the device (CIL and PCD) and it initializes the ++ * device. The driver components are stored in a dwc_usb3_device ++ * structure. A reference to the dwc_usb3_device is saved in the ++ * pci_dev. This allows the driver to access the dwc_usb3_device ++ * structure on subsequent calls to driver methods for this device. ++ * ++ * @param dev pci_dev struct ++ * @param id pci_dev_id struct ++ */ ++static int dwc_usb3_driver_probe(struct pci_dev *dev, const struct pci_device_id *id) ++{ ++ dwc_usb3_device_t *usb3_dev; ++ u32 addr_ofs = 0xc000; ++ int retval = 0; ++ ++#ifdef CONFIG_USB_OTG_DWC ++ struct usb_phy *phy; ++ struct usb_otg *otg; ++#endif ++ ++ printk(KERN_DEBUG "%s: driver_probe()\n", dwc_driver_name); ++ dev_dbg(&dev->dev, "dwc_usb3_driver_probe(%p)\n", dev); ++ ++ dev_dbg(&dev->dev, "start=0x%08x\n", ++ (unsigned)pci_resource_start(dev, 0)); ++ dev_dbg(&dev->dev, "len=0x%08x\n", (unsigned)pci_resource_len(dev, 0)); ++ ++#ifndef DWC_BAR2_GASKET_REG ++ if (id->device == PCI_DEVICE_ID_SYNOPSYS_HAPS_AXI) ++#endif ++ { ++ dev_dbg(&dev->dev, "start2=0x%08x\n", ++ (unsigned)pci_resource_start(dev, 2)); ++ dev_dbg(&dev->dev, "len2=0x%08x\n", ++ (unsigned)pci_resource_len(dev, 2)); ++ } ++ ++ if (!id) { ++ dev_err(&dev->dev, "id parameter NULL!\n"); ++ return -EINVAL; ++ } ++ ++ if (pci_enable_device(dev) < 0) { ++ dev_err(&dev->dev, "pci_enable_device() failed!\n"); ++ return -ENODEV; ++ } ++ ++ dev->current_state = PCI_D0; ++ dev->dev.power.power_state = PMSG_ON; ++ ++ if (!dev->irq) { ++ dev_err(&dev->dev, "no IRQ for PCI device!\n"); ++ retval = -ENODEV; ++ goto fail; ++ } ++ ++ usb3_dev = kmalloc(sizeof(dwc_usb3_device_t), GFP_KERNEL); ++ if (!usb3_dev) { ++ dev_err(&dev->dev, "kmalloc of dwc_usb3_device failed!\n"); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ memset(usb3_dev, 0, sizeof(*usb3_dev)); ++ usb3_dev->dev = &dev->dev; ++ usb3_dev->rsrc_start = pci_resource_start(dev, 0); ++ usb3_dev->rsrc_len = pci_resource_len(dev, 0); ++ ++#ifndef DWC_BAR2_GASKET_REG ++ if (id->device == PCI_DEVICE_ID_SYNOPSYS_HAPS_AXI) ++#endif ++ { ++ usb3_dev->gasket_start = pci_resource_start(dev, 2); ++ usb3_dev->gasket_len = pci_resource_len(dev, 2); ++ } ++ ++ /* ++ * Initialize driver data to point to the global DWC_usb3 ++ * Device structure. ++ */ ++ pci_set_drvdata(dev, usb3_dev); ++ dev_dbg(&dev->dev, "dwc_usb3_device=0x%p\n", usb3_dev); ++ ++ if (!usb3_dev->rsrc_start || !usb3_dev->rsrc_len) { ++ dev_err(&dev->dev, "bad PCI resource!\n"); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++#ifndef DWC_BAR2_GASKET_REG ++ if (id->device == PCI_DEVICE_ID_SYNOPSYS_HAPS_AXI) ++#endif ++ { ++ if (!usb3_dev->gasket_start || !usb3_dev->gasket_len) { ++ dev_err(&dev->dev, "bad PCI resource 2!\n"); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ } ++ ++ /* ++ * Map the DWC_usb3 Core memory into virtual address space. ++ */ ++ if (!request_mem_region(usb3_dev->rsrc_start, usb3_dev->rsrc_len, ++ "usb3")) { ++ dev_err(&dev->dev, "request_mem_region() failed!\n"); ++ ++ /* Flag for dwc_usb3_driver_remove() that we failed */ ++ usb3_dev->rsrc_start = 0; ++ ++ retval = -EBUSY; ++ goto fail; ++ } ++ ++ usb3_dev->base = ioremap_nocache(usb3_dev->rsrc_start, ++ usb3_dev->rsrc_len); ++ if (!usb3_dev->base) { ++ dev_err(&dev->dev, "ioremap_nocache() failed!\n"); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ dev_dbg(&dev->dev, "base=%p\n", usb3_dev->base); ++ ++#ifndef DWC_BAR2_GASKET_REG ++ if (id->device == PCI_DEVICE_ID_SYNOPSYS_HAPS_AXI) ++#endif ++ { ++ if (!request_mem_region(usb3_dev->gasket_start, ++ usb3_dev->gasket_len, "usb3")) { ++ dev_err(&dev->dev, "request_mem_region() 2 failed!\n"); ++ ++ /* Flag for dwc_usb3_driver_remove() that we failed */ ++ usb3_dev->gasket_start = 0; ++ ++ retval = -EBUSY; ++ goto fail; ++ } ++ ++ usb3_dev->gasket_base = ioremap_nocache(usb3_dev->gasket_start, ++ usb3_dev->gasket_len); ++ if (!usb3_dev->gasket_base) { ++ dev_err(&dev->dev, "ioremap_nocache() 2 failed!\n"); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ dev_dbg(&dev->dev, "gasket_base=%p\n", usb3_dev->gasket_base); ++ } ++ ++ if (dwc_usb3_module_params.newcsr) ++ usb3_dev->gasket_ofs = 0xf000; ++ else ++ usb3_dev->gasket_ofs = 0x80000; ++ ++#ifdef CONFIG_USB_OTG_DWC ++ /* Switch otg to peripheral mode */ ++ phy = usb_get_phy(USB_PHY_TYPE_USB3); ++ if (IS_ERR(phy) || !phy) { ++ dev_err(&dev->dev, "OTG PHY not available!\n"); ++ if (!IS_ERR(phy)) ++ usb_put_phy(phy); ++ retval = -ENODEV; ++ goto fail; ++ } ++ ++ otg = phy->otg; ++ if (!otg) { ++ dev_err(&dev->dev, "OTG not available!\n"); ++ usb_put_phy(phy); ++ retval = -ENODEV; ++ goto fail; ++ } ++ ++ phy->io_priv = (void __iomem *)usb3_dev->base; ++ dwc_otg3_set_peripheral(otg, 1); ++ usb_put_phy(phy); ++#endif ++ ++ retval = dwc_usb3_create_dev_files(&dev->dev); ++ if (retval) { ++ dev_err(&dev->dev, "sysfs initialization failed!\n"); ++ goto fail; ++ } ++ ++ usb3_dev->sysfs_initialized = 1; ++ ++ /* ++ * Checks that this device is really a DWC_usb3 controller. Also saves ++ * the SNPSID register value in usb3_dev->snpsid for later use by the ++ * PCD. ++ */ ++ retval = dwc_usb3_pcd_check_snpsid(usb3_dev, addr_ofs); ++ if (retval) { ++ dev_err(&dev->dev, "bad value for SNPSID!\n"); ++ goto fail; ++ } ++ ++ if (dwc_usb3_module_params.newcore && usb3_dev->snpsid < 0x5533109a) ++ usb3_dev->snpsid = 0x5533109a; ++ ++ /* ++ * Up to 32 Event Buffers are supported by the hardware, ++ * but we only use 1 ++ */ ++ usb3_dev->event_buf[0] = dma_alloc_coherent(NULL, ++ DWC_EVENT_BUF_SIZE * sizeof(u32), ++ &usb3_dev->event_buf_dma[0], ++ GFP_KERNEL | GFP_DMA32); ++ if (!usb3_dev->event_buf[0]) { ++ dev_err(&dev->dev, "allocation of event_buf failed!\n"); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ /* ++ * Add our hook to override the default Phy register setup ++ */ ++ usb3_dev->phy_config_hook = haps_phy_config_hook; ++ ++ /* ++ * Initialize the DWC_usb3 Core. ++ */ ++ retval = dwc_usb3_pcd_common_init(usb3_dev, usb3_dev->base + addr_ofs, ++ &dwc_usb3_module_params); ++ if (retval) { ++ dev_err(&dev->dev, "CIL initialization failed!\n"); ++ goto fail; ++ } ++ ++ usb3_dev->cmn_initialized = 1; ++ ++#ifdef DWC_UTE ++ dwc_usb3_save_fifosiz_def_vals(usb3_dev); ++#endif ++ ++ spin_lock_init(&usb3_dev->pcd.lock); ++ ++ /* ++ * Initialize the Gadget ++ */ ++ retval = dwc_usb3_gadget_init(usb3_dev, &dev->dev); ++ if (retval) { ++ dev_err(&dev->dev, "gadget initialization failed!\n"); ++ goto fail; ++ } ++ ++ usb3_dev->gadget_initialized = 1; ++ ++ /* ++ * Initialize the PCD ++ */ ++ retval = dwc_usb3_pcd_init(usb3_dev); ++ if (retval) { ++ dev_err(&dev->dev, "PCD initialization failed!\n"); ++ goto fail; ++ } ++ ++ usb3_dev->pcd_initialized = 1; ++ ++ /* Allocate the test mode tasklet */ ++ tasklet_init(&usb3_dev->pcd.test_mode_tasklet, ++ dwc_usb3_pcd_do_test_mode, ++ (unsigned long)&usb3_dev->pcd); ++ ++ /* Start the hibernation thread */ ++ usb3_dev->pme_thread = kthread_run(dwc_wait_pme_thread, &usb3_dev->pcd, ++ "pmethr"); ++ if (IS_ERR(usb3_dev->pme_thread)) { ++ retval = PTR_ERR(usb3_dev->pme_thread); ++ usb3_dev->pme_thread = NULL; ++ goto fail; ++ } ++ ++ /* ++ * Install the interrupt handler for the common interrupts. ++ */ ++ dev_dbg(&dev->dev, "registering (common) handler for irq%d\n", ++ dev->irq); ++ retval = request_irq(dev->irq, dwc_usb3_common_irq, ++ IRQF_SHARED | IRQF_DISABLED, ++ dwc_driver_name, usb3_dev); ++ if (retval) { ++ dev_err(&dev->dev, "request of irq%d failed!\n", dev->irq); ++ goto fail; ++ } ++ ++ usb3_dev->cmn_irq_installed = 1; ++#if 0 ++ if (dwc_usb3_module_params.hibernate && ++ (usb3_dev->hwparams1 & DWC_HWP1_EN_PWROPT_BITS) == ++ DWC_EN_PWROPT_HIBERNATION << DWC_HWP1_EN_PWROPT_SHIFT) { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&usb3_dev->pcd.lock, flags); ++ dwc_enter_hibernation(&usb3_dev->pcd, 0); ++ spin_unlock_irqrestore(&usb3_dev->pcd.lock, flags); ++ } ++#endif ++ return 0; ++ ++fail: ++ dwc_usb3_driver_remove(dev); ++ return retval; ++} ++ ++static const struct pci_device_id pci_ids[] = { ++ { ++ /* The Synopsys PCIe card */ ++ PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, ++ PCI_DEVICE_ID_SYNOPSYS_SITKA), ++ .driver_data = (unsigned long)0xdeadbeef, ++ }, ++ { ++ /* The Synopsys HAPS PCIe card with AXI, with gasket registers ++ * moved to 2nd BAR ++ */ ++ PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, ++ PCI_DEVICE_ID_SYNOPSYS_HAPS_AXI), ++ .driver_data = (unsigned long)0xdeadbeef, ++ }, ++ { 0, } /* end: all zeroes */ ++}; ++MODULE_DEVICE_TABLE(pci, pci_ids); ++ ++/** ++ * This structure defines the methods to be called by a bus driver ++ * during the lifecycle of a device on that bus. Both drivers and ++ * devices are registered with a bus driver. The bus driver matches ++ * devices to drivers based on information in the device and driver ++ * structures. ++ * ++ * The probe function is called when the bus driver matches a device ++ * to this driver. The remove function is called when a device is ++ * unregistered with the bus driver. ++ */ ++static struct pci_driver dwc_usb3_driver = { ++ .name = (char *)dwc_driver_name, ++ .id_table = pci_ids, ++ .probe = dwc_usb3_driver_probe, ++ .remove = dwc_usb3_driver_remove, ++ .driver = { ++ .name = (char *)dwc_driver_name, ++ }, ++}; ++ ++/** ++ * This function is called when the DWC_usb3 driver is loaded into the kernel ++ * with the insmod command. It registers the dwc_usb3_driver structure with the ++ * appropriate bus driver. This will cause the dwc_usb3_driver_probe function ++ * to be called. In addition, the bus driver will automatically expose ++ * attributes defined for the device and driver in the special sysfs file ++ * system. ++ */ ++static int __init dwc_usb3_driver_init(void) ++{ ++ int retval; ++ ++ printk(KERN_INFO "%s: %s version %s\n", dwc_driver_name, ++ DWC_DRIVER_DESC, DWC_DRIVER_VERSION); ++ ++ retval = pci_register_driver(&dwc_usb3_driver); ++ if (retval < 0) { ++ printk(KERN_ERR "%s retval=%d\n", __func__, retval); ++ return retval; ++ } ++ ++ printk(KERN_INFO "%s: module installed\n", dwc_driver_name); ++ return retval; ++} ++module_init(dwc_usb3_driver_init); ++ ++/** ++ * This function is called when the DWC_usb3 driver is removed from the kernel ++ * with the rmmod command. The driver unregisters itself with its bus driver. ++ * ++ */ ++static void __exit dwc_usb3_driver_exit(void) ++{ ++ printk(KERN_DEBUG "%s: driver_exit()\n", dwc_driver_name); ++ ++ pci_unregister_driver(&dwc_usb3_driver); ++ ++ printk(KERN_INFO "%s: module removed\n", dwc_driver_name); ++} ++module_exit(dwc_usb3_driver_exit); +diff --git a/drivers/usb/gadget/udc/hiudc3/linux_plat.c b/drivers/usb/gadget/udc/hiudc3/linux_plat.c +new file mode 100644 +index 0000000..3102844 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/linux_plat.c +@@ -0,0 +1,701 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/DWC_usb3/driver/linux/linux_plat.c $ ++ * $Revision: #16 $ ++ * $Date: 2014/11/11 $ ++ * $Change: 2664766 $ ++ * ++ * Synopsys SS USB3 Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++/** @file ++ * The driver module provides the initialization and cleanup entry ++ * points for the DWC_usb3 driver. This module will be dynamically installed ++ * after Linux is booted using the insmod command. When the module is ++ * installed, the driver_init function is called. When the module is ++ * removed (using rmmod), the driver_cleanup function is called. ++ * ++ * This module also defines a data structure for the driver, which is ++ * used in conjunction with the standard pci_dev structure. These ++ * structures allow the USB3 driver to comply with the standard Linux driver ++ * model in which devices and drivers are registered with a bus driver. This ++ * has the benefit that Linux can expose attributes of the driver and device ++ * in its special sysfs file system. Users can then read or write files in ++ * this file system to perform diagnostics on the driver components or the ++ * device. ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++#include ++#include ++//#include "../../host/hiusb.h" ++ ++#ifndef __devinit ++# define __devinit ++# define __devexit ++# define __devexit_p(x) x ++#endif ++ ++#ifdef CONFIG_USB_OTG_DWC ++extern int dwc_otg3_irq(struct usb_otg *otg); ++extern void dwc_otg3_set_peripheral(struct usb_otg *otg, int yes); ++#endif ++ ++//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) ++//#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) ++/* Enable this to replace the DWC3 driver in recent Linux kernels */ ++# define DWC_REPLACE_DWC3 ++//#endif ++ ++/* Enable this to support the Synopsys Xplorer platform */ ++//#define DWC_XPLORER ++ ++static const char dwc_driver_name[] = "dwc_usb3"; ++ ++/* ++ * Hook to override the default Phy configuration in dwc_usb3_pcd_device_init() ++ * with a HAPS-specific one ++ */ ++static void haps_phy_config_hook(struct dwc_usb3_device *dev, int soft_reset, ++ int restore) ++{ ++ dwc_usb3_core_global_regs_t __iomem *global_regs = ++ dev->core_global_regs; ++ u32 temp; ++ ++ switch (dev->core_params->phy) { ++ case 3: // 16-bit UTMI+ SNPS Phy ++ temp = dwc_rd32(dev, &global_regs->gusb2phycfg[0]); ++ temp &= ~DWC_USB2PHYCFG_USB_TRD_TIM_BITS; ++ temp |= DWC_USB2PHYCFG_16B_PHY_IF_BIT; ++ temp |= 5 << DWC_USB2PHYCFG_USB_TRD_TIM_SHIFT; ++ dwc_wr32(dev, &global_regs->gusb2phycfg[0], temp); ++ break; ++ case 2: // 8-bit UTMI+ / ULPI TI or SNPS Phy ++ case 1: // old 8-bit UTMI+ SNPS Phy ++ temp = dwc_rd32(dev, &global_regs->gusb2phycfg[0]); ++ temp &= ~DWC_USB2PHYCFG_USB_TRD_TIM_BITS; ++ temp &= ~DWC_USB2PHYCFG_16B_PHY_IF_BIT; ++ temp |= 9 << DWC_USB2PHYCFG_USB_TRD_TIM_SHIFT; ++ dwc_wr32(dev, &global_regs->gusb2phycfg[0], temp); ++ break; ++ default: // RocketIO Phy ++ if (dev->core_params->usb2mode == 0) { ++ /* Set rx-eq, differential swing */ ++ dwc_wr32(dev, (volatile u32 __iomem *) ++ (dev->base + dev->gasket_ofs + 8), 0x41); ++#ifdef LECROY ++ /* Rx-detect for LeCroy */ ++ dwc_wr32(dev, (volatile u32 __iomem *) ++ (dev->base + dev->gasket_ofs + 4), 0x200); ++#else ++ dwc_wr32(dev, (volatile u32 __iomem *) ++ (dev->base + dev->gasket_ofs + 4), 0); ++#endif ++ } ++ } ++} ++ ++/** ++ * This function is the top level interrupt handler for the Common ++ * (Core and Device) interrupts. ++ */ ++static irqreturn_t dwc_usb3_common_irq(int irq, void *dev ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ++ , struct pt_regs *regs ++#endif ++ ) ++{ ++ dwc_usb3_device_t *usb3_dev = dev; ++ int retval = 0; ++ ++#ifdef CONFIG_USB_OTG_DWC ++ u32 gsts = 0; ++ int temp = usb3_dev->hibernate; ++ ++ /* Skip OTG IRQ handler if in hibernation */ ++ if (temp < DWC_HIBER_SLEEPING) { ++ gsts = dwc_rd32(usb3_dev, &usb3_dev->core_global_regs->gsts); ++ } else { ++ dwc_info(usb3_dev, "%s() possible OTG IRQ in hibernation\n", ++ __func__); ++ retval = 1; ++ } ++ ++ if (gsts & DWC_GSTS_OTG_EVT_PENDING_BIT || ++ gsts & DWC_GSTS_ADP_EVT_PENDING_BIT || ++ gsts & DWC_GSTS_BC_EVT_PENDING_BIT) { ++ struct usb_phy *phy = usb_get_phy(USB_PHY_TYPE_USB3); ++ ++ if (!IS_ERR(phy)) { ++ dwc_info(usb3_dev, "%s() OTG IRQ\n", __func__); ++ dwc_info(usb3_dev, "gsts = %08x\n", gsts); ++ if (phy && phy->otg) ++ dwc_otg3_irq(phy->otg); ++ else ++ dwc_info(usb3_dev, "OTG IRQ but no OTG\n"); ++ usb_put_phy(phy); ++ } else { ++ dwc_info(usb3_dev, "%s() OTG IRQ but no PHY\n", ++ __func__); ++ } ++ ++ retval = 1; ++ } ++ ++ if (temp >= DWC_HIBER_SLEEPING || (gsts & DWC_GSTS_DEV_EVT_PENDING_BIT)) ++#endif ++ { ++ spin_lock(&usb3_dev->pcd.lock); ++ retval = dwc_usb3_irq(usb3_dev, irq); ++ spin_unlock(&usb3_dev->pcd.lock); ++ } ++ ++ return IRQ_RETVAL(retval); ++} ++ ++#ifdef DWC_UTE ++static void dwc_usb3_save_fifosiz_def_vals(dwc_usb3_device_t *dev) ++{ ++ unsigned i, size; ++ dwc_usb3_pcd_t *pcd; ++ ++ if (!dev) ++ return; ++ ++ pcd = &dev->pcd; ++ ++ for (i = 0; i < pcd->num_in_eps + 1; i++) { ++ size = dwc_rd32(dev, &dev->core_global_regs->gtxfifosiz[i]) & ++ DWC_FIFOSZ_DEPTH_BITS; ++ dwc_print(dev, "Saving %d TxFIFO default size: %d\n", i, size); ++ pcd->def_txf_size[i] = size; ++ } ++ ++ size = dwc_rd32(dev, &dev->core_global_regs->grxfifosiz[0]) & ++ DWC_FIFOSZ_DEPTH_BITS; ++ pcd->def_rxf_size = size; ++ ++ dwc_print(dev, "Saving RxFIFO default size: %d\n", size); ++} ++#endif ++ ++/** ++ * This function is called when a platform_device is unregistered with the ++ * dwc_usb3_driver. This happens, for example, when the rmmod command is ++ * executed. The device may or may not be electrically present. If it is ++ * present, the driver stops device processing. Any resources used on behalf ++ * of this device are freed. ++ * ++ * @param dev platform_device struct ++ */ ++static int dwc_usb3_platform_remove(struct platform_device *dev) ++{ ++ dwc_usb3_device_t *usb3_dev = platform_get_drvdata(dev); ++ u32 *event_buf; ++ dwc_dma_t event_buf_dma; ++ ++#ifdef CONFIG_USB_OTG_DWC ++ struct usb_phy *phy; ++#endif ++ ++ dev_dbg(&dev->dev, "%s(%p)\n", __func__, dev); ++ ++ if (!usb3_dev) { ++ /* Memory allocation for the dwc_usb3_device failed */ ++ dev_dbg(&dev->dev, "%s: usb3_dev NULL\n", __func__); ++ goto disable; ++ } ++ ++#ifdef CONFIG_USB_OTG_DWC ++ /* Switch otg to peripheral mode */ ++ phy = usb_get_phy(USB_PHY_TYPE_USB3); ++ if (!IS_ERR(phy)) { ++ if (phy && phy->otg) ++ dwc_otg3_set_peripheral(phy->otg, 1); ++ usb_put_phy(phy); ++ } ++#endif ++ ++ /* ++ * Free the IRQ ++ */ ++ if (usb3_dev->cmn_irq_installed) { ++ usb3_dev->cmn_irq_installed = 0; ++ free_irq(usb3_dev->irq, usb3_dev); ++ } ++ ++ if (usb3_dev->pme_thread) { ++ kthread_stop(usb3_dev->pme_thread); ++ usb3_dev->pme_thread = NULL; ++ } ++ ++ if (usb3_dev->pcd_initialized) { ++ usb3_dev->pcd_initialized = 0; ++ dwc_usb3_pcd_remove(usb3_dev); ++ } ++ ++ if (usb3_dev->gadget_initialized) { ++ usb3_dev->gadget_initialized = 0; ++ dwc_usb3_gadget_remove(usb3_dev, &dev->dev); ++ } ++ ++ if (usb3_dev->cmn_initialized) { ++ usb3_dev->cmn_initialized = 0; ++ dwc_usb3_pcd_common_remove(usb3_dev); ++ } ++ ++ event_buf = usb3_dev->event_buf[0]; ++ event_buf_dma = usb3_dev->event_buf_dma[0]; ++ if (event_buf) { ++ dwc_usb3_dis_flush_eventbuf_intr(usb3_dev, 0); ++ usb3_dev->event_buf[0] = NULL; ++ dma_free_coherent(NULL, DWC_EVENT_BUF_SIZE * sizeof(u32), ++ event_buf, event_buf_dma); ++ } ++ ++ if (usb3_dev->sysfs_initialized) { ++ dwc_usb3_remove_dev_files(&dev->dev); ++ usb3_dev->sysfs_initialized = 0; ++ } ++ ++ /* ++ * Clear the drvdata pointer. ++ */ ++ platform_set_drvdata(dev, NULL); ++ ++ /* ++ * Return the memory. ++ */ ++ if (usb3_dev->base) ++ iounmap((void __iomem *)usb3_dev->base); ++ if (usb3_dev->rsrc_start) ++ release_mem_region(usb3_dev->rsrc_start, usb3_dev->rsrc_len); ++ if (usb3_dev->gasket_base) ++ iounmap((void __iomem *)usb3_dev->gasket_base); ++ if (usb3_dev->gasket_start) ++ release_mem_region(usb3_dev->gasket_start, usb3_dev->gasket_len); ++ ++ kfree(usb3_dev); ++ ++disable: ++ return 0; ++} ++ ++static u64 dwc3_vexpress_dma_mask = DMA_BIT_MASK(32); ++ ++/** ++ * This function is called when a platform_device is bound to a ++ * dwc_usb3_driver. It creates the driver components required to ++ * control the device (CIL and PCD) and it initializes the ++ * device. The driver components are stored in a dwc_usb3_device ++ * structure. A reference to the dwc_usb3_device is saved in the ++ * platform_device. This allows the driver to access the dwc_usb3_device ++ * structure on subsequent calls to driver methods for this device. ++ * ++ * @param dev platform_device struct ++ */ ++static int __devinit dwc_usb3_platform_probe(struct platform_device *dev) ++{ ++#if 0 ++ int reg; ++ reg = dwc_rd32(dev, IO_ADDRESS(0x10180430)); ++ reg = dwc_rd32(dev, IO_ADDRESS(0x1018c110)); ++ reg &= ~(3 << 12); ++ reg |= (2 << 12); ++ dwc_wr32(dev, IO_ADDRESS(0x1018c110), reg); ++#endif ++ dwc_usb3_device_t *usb3_dev; ++ struct resource *res_mem; ++ u32 addr_ofs = 0xc000; ++ int irq, retval = 0; ++ ++#ifdef DWC_BAR2_GASKET_REG ++ struct resource *res_mem2; ++#endif ++ ++#ifdef CONFIG_USB_OTG_DWC ++ struct usb_phy *phy; ++ struct usb_otg *otg; ++#endif ++ ++ printk(KERN_DEBUG "%s: platform_probe()\n", dwc_driver_name); ++ dev_dbg(&dev->dev, "dwc_usb3_platform_probe(%p)\n", dev); ++ ++ if (!dev->dev.dma_mask) ++ dev->dev.dma_mask = &dwc3_vexpress_dma_mask; ++ ++ irq = platform_get_irq(dev, 0); ++ if (irq < 0) { ++ dev_err(&dev->dev, "no irq provided"); ++ return irq; ++ } ++ ++ res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); ++ if (!res_mem) { ++ dev_err(&dev->dev, "no memory resource provided"); ++ return -ENXIO; ++ } ++ ++#ifdef DWC_BAR2_GASKET_REG ++ res_mem2 = platform_get_resource(dev, IORESOURCE_MEM, 2); ++ if (!res_mem2) { ++ dev_err(&dev->dev, "no memory resource 2 provided"); ++ return -ENXIO; ++ } ++#endif ++ ++ usb3_dev = kmalloc(sizeof(dwc_usb3_device_t), GFP_KERNEL); ++ if (!usb3_dev) { ++ dev_err(&dev->dev, "kmalloc of dwc_usb3_device failed!\n"); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ memset(usb3_dev, 0, sizeof(*usb3_dev)); ++ usb3_dev->dev = &dev->dev; ++ usb3_dev->irq = irq; ++ ++ /* ++ * Initialize driver data to point to the global DWC_usb3 ++ * Device structure. ++ */ ++ platform_set_drvdata(dev, usb3_dev); ++ dev_dbg(&dev->dev, "dwc_usb3_device=0x%p\n", usb3_dev); ++ ++ /* ++ * Map the DWC_usb3 Core memory into virtual address space. ++ */ ++#if 0 ++ if (!request_mem_region(res_mem->start, resource_size(res_mem), ++ "usb3")) { ++ dev_err(&dev->dev, "request_mem_region() failed!\n"); ++ retval = -EBUSY; ++ goto fail; ++ } ++#endif ++ usb3_dev->rsrc_start = res_mem->start; ++ usb3_dev->rsrc_len = resource_size(res_mem); ++ ++ usb3_dev->base = ioremap_nocache(usb3_dev->rsrc_start, ++ usb3_dev->rsrc_len); ++ if (!usb3_dev->base) { ++ dev_err(&dev->dev, "ioremap_nocache() failed!\n"); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ dev_dbg(&dev->dev, "base=%p\n", usb3_dev->base); ++ ++#ifdef DWC_BAR2_GASKET_REG ++ if (!request_mem_region(res_mem2->start, resource_size(res_mem2), ++ "usb3")) { ++ dev_err(&dev->dev, "request_mem_region() 2 failed!\n"); ++ retval = -EBUSY; ++ goto fail; ++ } ++ ++ usb3_dev->gasket_start = res_mem2->start; ++ usb3_dev->gasket_len = resource_size(res_mem2); ++ ++ usb3_dev->gasket_base = ioremap_nocache(usb3_dev->gasket_start, ++ usb3_dev->gasket_len); ++ if (!usb3_dev->gasket_base) { ++ dev_err(&dev->dev, "ioremap_nocache() 2 failed!\n"); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ dev_dbg(&dev->dev, "gasket_base=%p\n", usb3_dev->gasket_base); ++#endif ++ ++ if (dwc_usb3_module_params.newcsr) ++ usb3_dev->gasket_ofs = 0xf000; ++ else ++ usb3_dev->gasket_ofs = 0x80000; ++ ++#ifdef CONFIG_USB_OTG_DWC ++ /* Switch otg to peripheral mode */ ++ phy = usb_get_phy(USB_PHY_TYPE_USB3); ++ if (IS_ERR(phy) || !phy) { ++ dev_err(&dev->dev, "OTG PHY not available!\n"); ++ if (!IS_ERR(phy)) ++ usb_put_phy(phy); ++ retval = -ENODEV; ++ goto fail; ++ } ++ ++ otg = phy->otg; ++ if (!otg) { ++ dev_err(&dev->dev, "OTG not available!\n"); ++ usb_put_phy(phy); ++ retval = -ENODEV; ++ goto fail; ++ } ++ ++ phy->io_priv = (void __iomem *)usb3_dev->base; ++ dwc_otg3_set_peripheral(otg, 1); ++ usb_put_phy(phy); ++#endif ++ ++ retval = dwc_usb3_create_dev_files(&dev->dev); ++ if (retval) { ++ dev_err(&dev->dev, "sysfs initialization failed!\n"); ++ goto fail; ++ } ++ ++ usb3_dev->sysfs_initialized = 1; ++ ++ /* ++ * Checks that this device is really a DWC_usb3 controller. Also saves ++ * the SNPSID register value in usb3_dev->snpsid for later use by the ++ * PCD. ++ */ ++ retval = dwc_usb3_pcd_check_snpsid(usb3_dev, addr_ofs); ++ if (retval) { ++ dev_err(&dev->dev, "bad value for SNPSID!\n"); ++ goto fail; ++ } ++ ++ if (dwc_usb3_module_params.newcore && usb3_dev->snpsid < 0x5533109a) ++ usb3_dev->snpsid = 0x5533109a; ++ ++ /* ++ * Up to 32 Event Buffers are supported by the hardware, ++ * but we only use 1 ++ */ ++ usb3_dev->event_buf[0] = dma_alloc_coherent(NULL, ++ DWC_EVENT_BUF_SIZE * sizeof(u32), ++ &usb3_dev->event_buf_dma[0], ++ GFP_KERNEL | GFP_DMA32); ++ if (!usb3_dev->event_buf[0]) { ++ dev_err(&dev->dev, "allocation of event_buf failed!\n"); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ /* ++ * Add our hook to override the default Phy register setup ++ */ ++ usb3_dev->phy_config_hook = haps_phy_config_hook; ++ ++ /* ++ * Initialize the DWC_usb3 Core. ++ */ ++ retval = dwc_usb3_pcd_common_init(usb3_dev, usb3_dev->base + addr_ofs, ++ &dwc_usb3_module_params); ++ if (retval) { ++ dev_err(&dev->dev, "CIL initialization failed!\n"); ++ goto fail; ++ } ++ ++ usb3_dev->cmn_initialized = 1; ++ ++#ifdef DWC_UTE ++ dwc_usb3_save_fifosiz_def_vals(usb3_dev); ++#endif ++ ++ spin_lock_init(&usb3_dev->pcd.lock); ++ ++ /* ++ * Initialize the Gadget ++ */ ++ retval = dwc_usb3_gadget_init(usb3_dev, &dev->dev); ++ if (retval) { ++ dev_err(&dev->dev, "gadget initialization failed!\n"); ++ goto fail; ++ } ++ ++ usb3_dev->gadget_initialized = 1; ++ ++ /* ++ * Initialize the PCD ++ */ ++ retval = dwc_usb3_pcd_init(usb3_dev); ++ if (retval) { ++ dev_err(&dev->dev, "PCD initialization failed!\n"); ++ goto fail; ++ } ++ ++ usb3_dev->pcd_initialized = 1; ++ ++ /* Allocate the test mode tasklet */ ++ tasklet_init(&usb3_dev->pcd.test_mode_tasklet, ++ dwc_usb3_pcd_do_test_mode, ++ (unsigned long)&usb3_dev->pcd); ++ ++ /* Start the hibernation thread */ ++ usb3_dev->pme_thread = kthread_run(dwc_wait_pme_thread, &usb3_dev->pcd, ++ "pmethr"); ++ if (IS_ERR(usb3_dev->pme_thread)) { ++ retval = PTR_ERR(usb3_dev->pme_thread); ++ usb3_dev->pme_thread = NULL; ++ goto fail; ++ } ++ ++ /* ++ * Install the interrupt handler for the common interrupts. ++ */ ++ dev_dbg(&dev->dev, "registering (common) handler for irq%d\n", ++ usb3_dev->irq); ++ retval = request_irq(usb3_dev->irq, dwc_usb3_common_irq, ++ IRQF_SHARED | IRQF_DISABLED, ++ dwc_driver_name, usb3_dev); ++ if (retval) { ++ dev_err(&dev->dev, "request of irq%d failed!\n", usb3_dev->irq); ++ goto fail; ++ } ++ ++ usb3_dev->cmn_irq_installed = 1; ++#if 0 ++ if (dwc_usb3_module_params.hibernate && ++ (usb3_dev->hwparams1 & DWC_HWP1_EN_PWROPT_BITS) == ++ DWC_EN_PWROPT_HIBERNATION << DWC_HWP1_EN_PWROPT_SHIFT) { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&usb3_dev->pcd.lock, flags); ++ dwc_enter_hibernation(&usb3_dev->pcd, 0); ++ spin_unlock_irqrestore(&usb3_dev->pcd.lock, flags); ++ } ++#endif ++ return 0; ++ ++fail: ++ dwc_usb3_platform_remove(dev); ++ return retval; ++} ++ ++#ifdef DWC_REPLACE_DWC3 ++ ++#ifdef CONFIG_OF ++static const struct of_device_id of_dwc_usb3_match[] = { ++#if 0 ++#ifdef DWC_XPLORER ++ { ++ .compatible = "snps,xplorer-dwusb3" ++ }, ++#else ++ { ++ .compatible = "synopsys,dwc3" ++ }, ++#endif ++#endif ++ { .compatible = "dwc_usb3", }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, of_dwc_usb3_match); ++#endif ++ ++static struct platform_driver dwc_usb3_platform_driver = { ++ .probe = dwc_usb3_platform_probe, ++ .remove = dwc_usb3_platform_remove, ++ .driver = { ++#ifdef DWC_XPLORER ++ .name = "xplorer-dwc3", ++#else ++ .name = (char *)dwc_driver_name, ++// .name = "dwc3", ++#endif ++ .of_match_table = of_dwc_usb3_match, ++ }, ++}; ++ ++module_platform_driver(dwc_usb3_platform_driver); ++ ++#ifdef DWC_XPLORER ++MODULE_ALIAS("platform:xplorer-dwc3"); ++#else ++MODULE_ALIAS("platform:dwc3"); ++#endif ++ ++#else /* DWC_REPLACE_DWC3 */ ++ ++static const struct platform_device_id dwc_usb3_platform_ids[] = { ++ { "dwc-usb3-platform", 0 }, ++ { "dwc_usb3", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(platform, dwc_usb3_platform_ids); ++ ++static struct platform_driver dwc_usb3_platform_driver = { ++ .id_table = dwc_usb3_platform_ids, ++ .probe = dwc_usb3_platform_probe, ++ .remove = __devexit_p(dwc_usb3_platform_remove), ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "dwc_usb3", ++ } ++}; ++ ++/** ++ * This function is called when the DWC_usb3 driver is loaded into the kernel ++ * with the insmod command. It registers the dwc_usb3_driver structure with the ++ * appropriate bus driver. This will cause the dwc_usb3_platform_probe function ++ * to be called. In addition, the bus driver will automatically expose ++ * attributes defined for the device and driver in the special sysfs file ++ * system. ++ */ ++static int __init dwc_usb3_driver_init(void) ++{ ++ int retval; ++ ++ printk("\n###%s,%d,reg(c110)=0x%x\n",__func__,__LINE__,readl((IO_ADDRESS(0x1018c110)))); ++ printk("\n###%s,%d\n",__func__,__LINE__); ++ printk(KERN_INFO "%s: %s version %s\n", dwc_driver_name, ++ DWC_DRIVER_DESC, DWC_DRIVER_VERSION); ++ ++ retval = platform_driver_register(&dwc_usb3_platform_driver); ++ if (retval < 0) { ++ printk(KERN_ERR "%s retval=%d\n", __func__, retval); ++ return retval; ++ } ++ ++ printk(KERN_INFO "%s: module installed\n", dwc_driver_name); ++ return retval; ++} ++module_init(dwc_usb3_driver_init); ++ ++/** ++ * This function is called when the DWC_usb3 driver is removed from the kernel ++ * with the rmmod command. The driver unregisters itself with its bus driver. ++ * ++ */ ++static void __exit dwc_usb3_driver_exit(void) ++{ ++ printk(KERN_DEBUG "%s: driver_exit()\n", dwc_driver_name); ++ ++ platform_driver_unregister(&dwc_usb3_platform_driver); ++ ++ printk(KERN_INFO "%s: module removed\n", dwc_driver_name); ++} ++module_exit(dwc_usb3_driver_exit); ++#endif +diff --git a/drivers/usb/gadget/udc/hiudc3/linux_sysfs.c b/drivers/usb/gadget/udc/hiudc3/linux_sysfs.c +new file mode 100644 +index 0000000..5502de1 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/linux_sysfs.c +@@ -0,0 +1,469 @@ ++/** @file ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) ++# undef VERIFY_OCTAL_PERMISSIONS ++# define VERIFY_OCTAL_PERMISSIONS(perms) \ ++ (BUILD_BUG_ON_ZERO((perms) < 0) + \ ++ BUILD_BUG_ON_ZERO((perms) > 0777) + \ ++ /* User perms >= group perms >= other perms */ \ ++ BUILD_BUG_ON_ZERO(((perms) >> 6) < (((perms) >> 3) & 7)) + \ ++ BUILD_BUG_ON_ZERO((((perms) >> 3) & 7) < ((perms) & 7)) + \ ++ (perms)) ++#endif ++ ++#ifdef CONFIG_USB_OTG_DWC ++extern int otg_start_rsp(struct usb_otg *otg); ++extern int otg_end_session(struct usb_otg *otg); ++#endif ++ ++/*-------------------------------------------------------------------------*/ ++/* Encapsulate the module parameter settings */ ++ ++dwc_usb3_core_params_t dwc_usb3_module_params = { ++ .burst = 1, ++ .newcore = 0, ++ .phy = 2, ++ .wakeup = 0, ++#ifdef DWC_STAR_9000446947_WORKAROUND ++ .pwrctl = 0, ++#else ++# if defined(DWC_STAR_9000449814_WORKAROUND) || \ ++ defined(DWC_STAR_9000459034_WORKAROUND) ++ .pwrctl = 2, ++# else ++ .pwrctl = 3, ++# endif ++#endif ++ .lpmctl = 1, ++ .phyctl = 1, ++ .usb2mode = 0, ++ .hibernate = 0, ++ .hiberdisc = 1, ++ .clkgatingen = 1, ++ .ssdisquirk = 1, ++ .nobos = 0, ++ .loop = 0, ++ .nump = 16, ++ .newcsr = 1, ++ .rxfsz = 0, ++ .txfsz = { 0, }, ++ .txfsz_cnt = 0, ++ .besl = 0, ++ .baseline_besl = 0, ++ .deep_besl = 0, ++ .ebc = 0, ++}; ++ ++module_param_named(burst, dwc_usb3_module_params.burst, int, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(burst, "Enable gadget to set USB 3.0 max burst size " ++ "(0=no, 1=yes) (default=yes)"); ++ ++module_param_named(new, dwc_usb3_module_params.newcore, int, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(new, "Force new core behavior [rev >= 1.09a] (0=no, 1=yes) " ++ "(default=no)"); ++ ++module_param_named(phy, dwc_usb3_module_params.phy, int, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(phy, "Select PHY type (0=RocketIO, 1=old-Synopsys, " ++ "2=TI/Synopsys-8bit-UTMI/ULPI 3=Synopsys-16bit-UTMI) " ++ "(default=2)"); ++ ++module_param_named(wakeup, dwc_usb3_module_params.wakeup, int, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(wakeup, "Enable remote wakeup (0=no, 1=yes) (default=no)"); ++ ++module_param_named(pwrctl, dwc_usb3_module_params.pwrctl, int, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(pwrctl, "Enable U1/U2 power states (bit0=U1, bit1=U2) " ++ "(default=U1+U2)"); ++ ++module_param_named(lpmctl, dwc_usb3_module_params.lpmctl, int, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(lpmctl, "Enable LPM power control (0=no, 1=AppL1Res-0, " ++ "2=AppL1Res-1) (default=1)"); ++ ++module_param_named(phyctl, dwc_usb3_module_params.phyctl, int, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(phyctl, "Enable PHY suspend (0=no, 1=yes) (default=yes)"); ++ ++module_param_named(usb2mode, dwc_usb3_module_params.usb2mode, int, ++ S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(usb2mode, "Force the core to connect in USB 2.0 mode at the " ++ "given speed (0=no, 1=FS, 2=HS) (default=no)"); ++ ++module_param_named(hibernate, dwc_usb3_module_params.hibernate, int, ++ S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(hibernate, "Enable hibernation mode (0=no, 1=yes) " ++ "(default=no)"); ++ ++module_param_named(hiberdisc, dwc_usb3_module_params.hiberdisc, int, ++ S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(hiberdisc, "Enter hibernation when disconnected " ++ "(0=no, 1=yes) (default=yes)"); ++ ++module_param_named(clkgatingen, dwc_usb3_module_params.clkgatingen, int, ++ S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(clkgatingen, "Enable clock gating (0=no, 1=yes) " ++ "(default=yes)"); ++ ++module_param_named(ssdisquirk, dwc_usb3_module_params.ssdisquirk, int, ++ S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(ssdisquirk, "Enable SS_DIS Quirk (0=no, 1=yes) (default=yes)"); ++ ++module_param_named(nobos, dwc_usb3_module_params.nobos, int, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(nobos, "Fail GetDescriptor(BOS) request at USB2 speeds " ++ "(0=no, 1=yes) (default=no)"); ++ ++module_param_named(nump, dwc_usb3_module_params.nump, int, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(nump, "Set NUMP to given value (1-16) (default=16)"); ++ ++module_param_named(newcsr, dwc_usb3_module_params.newcsr, int, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(newcsr, "Use a newer HAPS bitfile with a 64K PCI BAR size " ++ "instead of the older 1MB PCI BAR size (0=no, 1=yes) " ++ "(default=yes)"); ++ ++module_param_named(loop, dwc_usb3_module_params.loop, int, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(loop, "Number of times to loop in reset (for debug only)"); ++ ++module_param_named(rxfsz, dwc_usb3_module_params.rxfsz, int, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(rxfsz, "Size of Rx FIFO in bytes"); ++ ++module_param_array_named(txfsz, dwc_usb3_module_params.txfsz, int, ++ &dwc_usb3_module_params.txfsz_cnt, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(txfsz, "Size of Tx FIFOs in bytes"); ++ ++module_param_named(besl, dwc_usb3_module_params.besl, int, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(besl, "Enable besl support"); ++ ++module_param_named(baseline_besl, dwc_usb3_module_params.baseline_besl, int, ++ S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(baseline_besl, "Set the baseline besl value"); ++ ++module_param_named(deep_besl, dwc_usb3_module_params.deep_besl, int, ++ S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(deep_besl, "Set the deep besl value"); ++ ++module_param_named(ebc, dwc_usb3_module_params.ebc, int, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(ebc, "Enable EBC support on all Bulk endpoints"); ++ ++static dwc_usb3_device_t *get_usb3_device(struct device *dev) ++{ ++#ifdef DWC_PLATFORM_DEV ++ struct platform_device *device = ++ container_of(dev, struct platform_device, dev); ++ dwc_usb3_device_t *usb3_dev = platform_get_drvdata(device); ++#else ++ struct pci_dev *device = container_of(dev, struct pci_dev, dev); ++ dwc_usb3_device_t *usb3_dev = pci_get_drvdata(device); ++#endif ++ ++ return usb3_dev; ++} ++ ++static ssize_t show_wakeup(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ dwc_usb3_device_t *usb3_dev = get_usb3_device(dev); ++ ++ return sprintf(buf, "%d\n", usb3_dev->pcd.wkup_rdy); ++} ++ ++static ssize_t store_wakeup(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ dwc_usb3_device_t *usb3_dev = get_usb3_device(dev); ++ int ret; ++ ++ ret = dwc_usb3_wakeup(usb3_dev->pcd.gadget); ++ ++ return ret < 0 ? ret : count; ++} ++ ++/* /sys/module/dwc_usb3/drivers/pci:dwc_usb3/nnnn:nn:nn.n/wakeup */ ++static DEVICE_ATTR(wakeup, 0666, show_wakeup, store_wakeup); ++ ++static ssize_t show_disrupt(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ return sprintf(buf, "%d\n", 0); ++} ++ ++static ssize_t store_disrupt(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ dwc_usb3_device_t *usb3_dev = get_usb3_device(dev); ++ unsigned long tmp = 0; ++ ssize_t rc; ++ unsigned long flags; ++ ++ sscanf(buf, "%ld", &tmp); ++ rc = strnlen(buf, count); ++ printk(USB3_DWC "disrupt: %ld ms\n", tmp); ++ ++ spin_lock_irqsave(&usb3_dev->pcd.lock, flags); ++ mdelay(tmp); ++ spin_unlock_irqrestore(&usb3_dev->pcd.lock, flags); ++ return rc; ++} ++ ++/* /sys/module/dwc_usb3/drivers/pci:dwc_usb3/nnnn:nn:nn.n/disrupt */ ++static DEVICE_ATTR(disrupt, 0666, show_disrupt, store_disrupt); ++ ++static ssize_t show_hiber(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ return sprintf(buf, "%d\n", 0); ++} ++ ++static ssize_t store_hiber(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ dwc_usb3_device_t *usb3_dev = get_usb3_device(dev); ++ int tmp = 0; ++ ssize_t rc; ++ unsigned long flags; ++ ++ sscanf(buf, "%d", &tmp); ++ rc = strnlen(buf, count); ++ printk(USB3_DWC "hibernate: save_state=%d\n", tmp); ++ ++ spin_lock_irqsave(&usb3_dev->pcd.lock, flags); ++ dwc_enter_hibernation(&usb3_dev->pcd, tmp); ++ spin_unlock_irqrestore(&usb3_dev->pcd.lock, flags); ++ return rc; ++} ++ ++/* /sys/module/dwc_usb3/drivers/pci:dwc_usb3/nnnn:nn:nn.n/hibernate */ ++static DEVICE_ATTR(hibernate, 0666, show_hiber, store_hiber); ++ ++static ssize_t show_restore(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ return sprintf(buf, "%d\n", 0); ++} ++ ++static ssize_t store_restore(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ dwc_usb3_device_t *usb3_dev = get_usb3_device(dev); ++ int tmp = 0; ++ ssize_t rc; ++ unsigned long flags; ++ ++ sscanf(buf, "%d", &tmp); ++ rc = strnlen(buf, count); ++ printk(USB3_DWC "restore: restore_state=%d\n", tmp); ++ ++ spin_lock_irqsave(&usb3_dev->pcd.lock, flags); ++ tmp = dwc_exit_hibernation(&usb3_dev->pcd, tmp); ++ spin_unlock_irqrestore(&usb3_dev->pcd.lock, flags); ++ printk(USB3_DWC "dwc_exit_hibernation() returned %d\n", tmp); ++ return rc; ++} ++ ++/* /sys/module/dwc_usb3/drivers/pci:dwc_usb3/nnnn:nn:nn.n/restore */ ++static DEVICE_ATTR(restore, 0666, show_restore, store_restore); ++ ++#ifdef CONFIG_USB_OTG_DWC ++ ++static ssize_t store_srp(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct usb_phy *phy; ++ struct usb_otg *otg; ++ ++ phy = usb_get_phy(USB_PHY_TYPE_USB3); ++ if (IS_ERR(phy) || !phy) { ++ if (!IS_ERR(phy)) ++ usb_put_phy(phy); ++ return count; ++ } ++ ++ otg = phy->otg; ++ if (!otg) { ++ usb_put_phy(phy); ++ return count; ++ } ++ ++ otg_start_srp(otg); ++ usb_put_phy(phy); ++ return count; ++} ++static DEVICE_ATTR(srp, 0222, NULL, store_srp); ++ ++static ssize_t store_end(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct usb_phy *phy; ++ struct usb_otg *otg; ++ ++ phy = usb_get_phy(USB_PHY_TYPE_USB3); ++ if (IS_ERR(phy) || !phy) { ++ if (!IS_ERR(phy)) ++ usb_put_phy(phy); ++ return count; ++ } ++ ++ otg = phy->otg; ++ if (!otg) { ++ usb_put_phy(phy); ++ return count; ++ } ++ ++ otg_end_session(otg); ++ usb_put_phy(phy); ++ return count; ++} ++static DEVICE_ATTR(end, 0222, NULL, store_end); ++ ++static ssize_t store_hnp(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ dwc_usb3_device_t *usb3_dev = get_usb3_device(dev); ++ ++ if (usb3_dev->pcd.b_hnp_enable) { ++ dev_info(dev, "b_hnp_enable is TRUE\n"); ++ usb3_dev->pcd.b_hnp_enable = 0; ++ usb3_dev->pcd.wants_host = 0; ++ dwc_usb3_start_hnp(&usb3_dev->pcd); ++ } else { ++ dev_info(dev, "b_hnp_enable is FALSE\n"); ++ usb3_dev->pcd.wants_host = 1; ++ /* TODO if we don't receive the SET_FEATURE within 4 secs, ++ * reset this value ++ */ ++ } ++ return count; ++} ++static DEVICE_ATTR(hnp, 0222, NULL, store_hnp); ++ ++static ssize_t store_rsp(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct usb_phy *phy; ++ struct usb_otg *otg; ++ ++ phy = usb_get_phy(USB_PHY_TYPE_USB3); ++ if (IS_ERR(phy) || !phy) { ++ if (!IS_ERR(phy)) ++ usb_put_phy(phy); ++ return count; ++ } ++ ++ otg = phy->otg; ++ if (!otg) { ++ usb_put_phy(phy); ++ return count; ++ } ++ ++ otg_start_rsp(otg); ++ usb_put_phy(phy); ++ return count; ++} ++static DEVICE_ATTR(rsp, 0222, NULL, store_rsp); ++ ++#endif /* CONFIG_USB_OTG_DWC */ ++ ++static ssize_t show_lpm_nyet(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ dwc_usb3_device_t *usb3_dev = get_usb3_device(dev); ++ dwc_usb3_dev_global_regs_t __iomem *regs = ++ usb3_dev->pcd.dev_global_regs; ++ u32 dctl = dwc_rd32(usb3_dev, ®s->dctl); ++ u32 nyet = (dctl & DWC_DCTL_LPM_NYET_THRESH_BITS) >> ++ DWC_DCTL_LPM_NYET_THRESH_SHIFT; ++ ++ return sprintf(buf, "0x%x\n", nyet); ++} ++ ++static ssize_t store_lpm_nyet(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ dwc_usb3_device_t *usb3_dev = get_usb3_device(dev); ++ dwc_usb3_dev_global_regs_t __iomem *regs = ++ usb3_dev->pcd.dev_global_regs; ++ u32 dctl = dwc_rd32(usb3_dev, ®s->dctl); ++ u32 value = simple_strtol(buf, NULL, 16); ++ ++ value = (value << DWC_DCTL_LPM_NYET_THRESH_SHIFT) & ++ DWC_DCTL_LPM_NYET_THRESH_BITS; ++ ++ dctl &= ~(DWC_DCTL_LPM_NYET_THRESH_BITS); ++ dctl |= value; ++ ++ dwc_wr32(usb3_dev, ®s->dctl, dctl); ++ return count; ++} ++ ++/* /sys/module/dwc_usb3/drivers/pci:dwc_usb3/nnnn:nn:nn.n/wakeup */ ++static DEVICE_ATTR(lpm_nyet, 0666, show_lpm_nyet, store_lpm_nyet); ++ ++void dwc_usb3_remove_dev_files(struct device *dev) ++{ ++#ifdef CONFIG_USB_OTG_DWC ++ device_remove_file(dev, &dev_attr_end); ++ device_remove_file(dev, &dev_attr_srp); ++ device_remove_file(dev, &dev_attr_rsp); ++ device_remove_file(dev, &dev_attr_hnp); ++#endif ++ device_remove_file(dev, &dev_attr_restore); ++ device_remove_file(dev, &dev_attr_hibernate); ++ device_remove_file(dev, &dev_attr_disrupt); ++ device_remove_file(dev, &dev_attr_wakeup); ++ device_remove_file(dev, &dev_attr_lpm_nyet); ++} ++ ++int dwc_usb3_create_dev_files(struct device *dev) ++{ ++ int retval; ++ ++ retval = device_create_file(dev, &dev_attr_wakeup); ++ if (retval) ++ goto fail; ++ ++ retval = device_create_file(dev, &dev_attr_disrupt); ++ if (retval) ++ goto fail; ++ ++ retval = device_create_file(dev, &dev_attr_hibernate); ++ if (retval) ++ goto fail; ++ ++ retval = device_create_file(dev, &dev_attr_restore); ++ if (retval) ++ goto fail; ++ ++#ifdef CONFIG_USB_OTG_DWC ++ retval = device_create_file(dev, &dev_attr_hnp); ++ if (retval) ++ goto fail; ++ ++ retval = device_create_file(dev, &dev_attr_rsp); ++ if (retval) ++ goto fail; ++ ++ retval = device_create_file(dev, &dev_attr_srp); ++ if (retval) ++ goto fail; ++ ++ retval = device_create_file(dev, &dev_attr_end); ++ if (retval) ++ goto fail; ++#endif ++ ++ retval = device_create_file(dev, &dev_attr_lpm_nyet); ++ if (retval) ++ goto fail; ++ ++ return 0; ++ ++fail: ++ dev_err(dev, "Failed to create one or more sysfs files!!\n"); ++ return retval; ++} +diff --git a/drivers/usb/gadget/udc/hiudc3/no_os/no_os_defs.h b/drivers/usb/gadget/udc/hiudc3/no_os/no_os_defs.h +new file mode 100644 +index 0000000..54d2af2 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/no_os/no_os_defs.h +@@ -0,0 +1,363 @@ ++#ifndef _DWC_NO_OS_DEFS_H_ ++#define _DWC_NO_OS_DEFS_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * @file ++ * ++ * This file contains OS-specific includes and definitions. ++ * ++ */ ++ ++#undef linux ++#undef __linux ++#undef __linux__ ++ ++#ifdef LINUXTEST ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++# include ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++# include ++#endif ++ ++#include ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ++typedef int gfp_t; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ++# define IRQF_SHARED SA_SHIRQ ++#endif ++ ++/** @{ */ ++/** Data type for DMA addresses */ ++typedef dma_addr_t dwc_dma_t; ++#define DWC_DMA_ADDR_INVALID (~(dwc_dma_t)0) ++/** @} */ ++ ++/** Compiler 'packed' attribute */ ++#define UPACKED __attribute__ ((__packed__)) ++ ++/** Compiler 'aligned(16)' attribute */ ++#define UALIGNED16 __attribute__ ((__aligned__(16))) ++ ++#define dwc_init_spinlock(d, p) spin_lock_init(p) ++#define dwc_acquire_spinlock(d, p) spin_lock(p) ++#define dwc_release_spinlock(d, p) spin_unlock(p) ++#define dwc_acquire_spinlock_irq(d, p, f) spin_lock_irqsave(p, f) ++#define dwc_release_spinlock_irq(d, p, f) spin_unlock_irqrestore(p, f) ++ ++#else /* !LINUXTEST */ ++ ++#include ++#include ++#include ++#include // for printf ++#include // for memcpy ++ ++/** @{ */ ++/** Data types needed by the PCD */ ++typedef uint64_t u64, u_int64_t; ++typedef uint32_t u32, u_int32_t; ++typedef uint16_t u16, u_int16_t; ++typedef uint8_t u8, u_int8_t; ++ ++typedef int64_t s64; ++typedef int32_t s32; ++typedef int16_t s16; ++typedef int8_t s8; ++ ++typedef unsigned long u_long; ++typedef unsigned int u_int; ++typedef unsigned short u_short; ++typedef unsigned char u_char; ++/** @} */ ++ ++/** @{ */ ++/** Data type for DMA addresses */ ++typedef unsigned long dwc_dma_t; ++#define DWC_DMA_ADDR_INVALID (~(dwc_dma_t)0) ++/** @} */ ++ ++/** Compiler 'packed' attribute */ ++#define UPACKED __attribute__ ((__packed__)) ++ ++/** Compiler 'aligned(16)' attribute */ ++#define UALIGNED16 __attribute__ ((__aligned__(16))) ++ ++/** I/O memory attribute for pointers. Needed for Linux "sparse" tool. */ ++#define __iomem /* */ ++ ++#define KERN_DEBUG "" /* debug messages */ ++#define KERN_INFO "" /* informational messages */ ++#define KERN_WARNING "" /* warning messages */ ++#define KERN_ERR "" /* error messages */ ++ ++// from /usr/include/asm-x86_64/errno.h ++#define EIO 5 /* I/O error */ ++#define EAGAIN 11 /* Try again */ ++#define ENOMEM 12 /* Out of memory */ ++#define EBUSY 16 /* Device or resource busy */ ++#define ENODEV 19 /* No such device */ ++#define EINVAL 22 /* Invalid argument */ ++#define ENOSPC 28 /* No space left on device */ ++#define EPIPE 32 /* Broken pipe */ ++#define EDOM 33 /* Math argument out of domain of func */ ++#define ENODATA 61 /* No data available */ ++#define ENOSR 63 /* Out of streams resources */ ++#define ECOMM 70 /* Communication error on send */ ++#define EPROTO 71 /* Protocol error */ ++#define EOVERFLOW 75 /* Value too large for defined data type */ ++#define ERESTART 85 /* Interrupted system call should be restarted */ ++#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ ++#define ECONNABORTED 103 /* Software caused connection abort */ ++#define ECONNRESET 104 /* Connection reset by peer */ ++#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ ++#define ETIMEDOUT 110 /* Connection timed out */ ++#define EINPROGRESS 115 /* Operation now in progress */ ++ ++/** Write memory barrier macro */ ++#define wmb() do {} while (0) ++ ++#define interrupt_disable() 0 ++#define interrupt_enable() do {} while (0) ++ ++#define dwc_init_spinlock(d, p) do {} while (0) ++#define dwc_acquire_spinlock(d, p) do {} while (0) ++#define dwc_release_spinlock(d, p) do {} while (0) ++#define dwc_acquire_spinlock_irq(d, p, f) do { (f) = interrupt_disable(); } while (0) ++#define dwc_release_spinlock_irq(d, p, f) do { if (f) interrupt_enable(); } while (0) ++ ++struct task_struct { ++ int dummy; ++}; ++ ++struct tasklet_struct { ++ int dummy; ++}; ++ ++#endif /* !LINUXTEST */ ++ ++#include "usb.h" ++#include "dwc_list.h" ++ ++/** @name Error Codes */ ++/** @{ */ ++#define DWC_E_INVALID EINVAL ++#define DWC_E_NO_MEMORY ENOMEM ++#define DWC_E_NO_DEVICE ENODEV ++#define DWC_E_NOT_SUPPORTED EOPNOTSUPP ++#define DWC_E_TIMEOUT ETIMEDOUT ++#define DWC_E_BUSY EBUSY ++#define DWC_E_AGAIN EAGAIN ++#define DWC_E_RESTART ERESTART ++#define DWC_E_ABORT ECONNABORTED ++#define DWC_E_SHUTDOWN ESHUTDOWN ++#define DWC_E_NO_DATA ENODATA ++#define DWC_E_DISCONNECT ECONNRESET ++#define DWC_E_UNKNOWN EINVAL ++#define DWC_E_NO_STREAM_RES ENOSR ++#define DWC_E_COMMUNICATION ECOMM ++#define DWC_E_OVERFLOW EOVERFLOW ++#define DWC_E_PROTOCOL EPROTO ++#define DWC_E_IN_PROGRESS EINPROGRESS ++#define DWC_E_PIPE EPIPE ++#define DWC_E_IO EIO ++#define DWC_E_NO_SPACE ENOSPC ++#define DWC_E_DOMAIN EDOM ++/** @} */ ++ ++/** ++ * The number of DMA Descriptors (TRBs) to allocate for each endpoint type. ++ * NOTE: The driver currently supports more than 1 TRB for Isoc EPs only. ++ * So the values for Bulk and Intr must be 1. ++ */ ++#define DWC_NUM_BULK_TRBS 1 ++#define DWC_NUM_INTR_TRBS 1 ++#define DWC_NUM_ISOC_TRBS 32 ++ ++/** ++ * These parameters may be specified when loading the module. They define how ++ * the DWC_usb3 controller should be configured. The parameter values are passed ++ * to the CIL initialization routine dwc_usb3_pcd_common_init(). ++ */ ++typedef struct dwc_usb3_core_params { ++ int burst; ++ int newcore; ++ int phy; ++ int wakeup; ++ int pwrctl; ++ int lpmctl; ++ int phyctl; ++ int usb2mode; ++ int hibernate; ++ int hiberdisc; ++ int clkgatingen; ++ int ssdisquirk; ++ int nobos; ++ int loop; ++ int nump; ++ int newcsr; ++ int rxfsz; ++ int txfsz[16]; ++ int txfsz_cnt; ++ int baseline_besl; ++ int deep_besl; ++ int besl; ++ int ebc; ++} dwc_usb3_core_params_t; ++ ++// linux/usb/gadget.h ++ ++/** ++ * Platform-specific USB endpoint ++ */ ++typedef struct usb_ep { ++ const void *desc; ++ const void *comp_desc; ++ unsigned maxpacket:16; ++ u8 address; ++} usb_ep_t; ++ ++/** ++ * Platform-specific USB request ++ */ ++typedef struct usb_request { ++ void *buf; ++ unsigned length; ++ dwc_dma_t dma; ++ ++ unsigned stream_id:16; ++ unsigned zero:1; ++ ++ void (*complete)(usb_ep_t *ep, struct usb_request *req); ++ ++ int status; ++ unsigned actual; ++} usb_request_t; ++ ++/** ++ */ ++static inline void dwc_usb3_task_schedule(struct tasklet_struct *tasklet) ++{ ++#ifdef LINUXTEST ++ tasklet_schedule(tasklet); ++#endif ++} ++ ++/* Make the following structure type definitions "packed" if using a Microsoft ++ * compiler. The UPACKED attribute (defined above) embedded in the structure ++ * type definitions does the same thing for GCC. Other compilers may need ++ * something different. ++ */ ++#ifdef _MSC_VER ++#include ++#endif ++ ++/** ++ */ ++typedef struct fs_config_desc_st { ++ usb_config_descriptor_t config_desc; ++ usb_interface_descriptor_t intf_desc; ++ usb_endpoint_descriptor_t bulk_in_ep_desc; ++ usb_endpoint_descriptor_t bulk_out_ep_desc; ++} UPACKED fs_config_desc_t; ++ ++/** ++ */ ++typedef struct hs_config_desc_st { ++ usb_config_descriptor_t config_desc; ++ usb_interface_descriptor_t intf_desc; ++ usb_endpoint_descriptor_t bulk_in_ep_desc; ++ usb_endpoint_descriptor_t bulk_out_ep_desc; ++} UPACKED hs_config_desc_t; ++ ++/** ++ */ ++typedef struct ss_config_desc_st { ++ usb_config_descriptor_t config_desc; ++ usb_interface_descriptor_t intf_desc; ++ usb_endpoint_descriptor_t bulk_in_ep_desc; ++ ss_endpoint_companion_descriptor_t bulk_in_ss_ep_comp_desc; ++ usb_endpoint_descriptor_t bulk_out_ep_desc; ++ ss_endpoint_companion_descriptor_t bulk_out_ss_ep_comp_desc; ++} UPACKED ss_config_desc_t; ++ ++/* Stop packing structure type definitions */ ++#ifdef _MSC_VER ++#include ++#endif ++ ++/* These structures are defined in no_os_ep0.c */ ++extern fs_config_desc_t fs_config_desc; ++extern hs_config_desc_t hs_config_desc; ++extern ss_config_desc_t ss_config_desc; ++ ++/** ++ * Function driver API routines ++ */ ++ ++struct dwc_usb3_device; /* so the simulation code can include just this file */ ++ ++extern dwc_usb3_core_params_t usb3ss_module_params; ++ ++#ifndef LINUXTEST ++extern struct dwc_usb3_device *dwc_usb3_driver_init(u32 base_addr_dwc); ++extern void dwc_usb3_driver_remove(void); ++extern void dwc_usb3_common_irq(int irq, void *dev); ++#endif ++ ++extern usb_ep_t *dwc_usb3_ep_enable(struct dwc_usb3_device *usb3_dev, const void *epdesc, ++ const void *epcomp); ++extern int dwc_usb3_ep_disable(struct dwc_usb3_device *usb3_dev, usb_ep_t *usb_ep); ++extern usb_request_t *dwc_usb3_alloc_request(struct dwc_usb3_device *usb3_dev, usb_ep_t *usb_ep); ++extern void dwc_usb3_free_request(struct dwc_usb3_device *usb3_dev, usb_ep_t *usb_ep, ++ usb_request_t *usb_req); ++extern int dwc_usb3_ep_queue(struct dwc_usb3_device *usb3_dev, usb_ep_t *usb_ep, ++ usb_request_t *usb_req); ++extern int dwc_usb3_ep_dequeue(struct dwc_usb3_device *usb3_dev, usb_ep_t *usb_ep, ++ usb_request_t *usb_req); ++extern int dwc_usb3_wait_pme(struct dwc_usb3_device *usb3_dev); ++extern int dwc_usb3_handle_pme_intr(struct dwc_usb3_device *usb3_dev); ++ ++extern int dwc_usb3_function_init(struct dwc_usb3_device *usb3_dev); ++extern void dwc_usb3_function_remove(struct dwc_usb3_device *usb3_dev); ++extern int dwc_usb3_function_connect(struct dwc_usb3_device *usb3_dev, int speed); ++extern int dwc_usb3_function_disconnect(struct dwc_usb3_device *usb3_dev); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_NO_OS_DEFS_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc3/no_os/no_os_dev.h b/drivers/usb/gadget/udc/hiudc3/no_os/no_os_dev.h +new file mode 100644 +index 0000000..0daeb86 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/no_os/no_os_dev.h +@@ -0,0 +1,198 @@ ++#ifndef _DWC_NO_OS_DEV_H_ ++#define _DWC_NO_OS_DEV_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ */ ++ ++/** Wrapper routine for _handshake() */ ++#define handshake(_dev_, _ptr_, _mask_, _done_) \ ++ _handshake(_dev_, _ptr_, _mask_, _done_) ++ ++/** Takes a usb req pointer and returns the associated pcd req pointer */ ++#define dwc_usb3_get_pcd_req(usbreq) \ ++ ((dwc_usb3_pcd_req_t *)((char *)(usbreq) - \ ++ offsetof(struct dwc_usb3_pcd_req, usb_req))) ++ ++/** Takes a usb ep pointer and returns the associated pcd ep pointer */ ++#define dwc_usb3_get_pcd_ep(usbep) \ ++ ((dwc_usb3_pcd_ep_t *)((char *)(usbep) - \ ++ offsetof(struct dwc_usb3_pcd_ep, usb_ep))) ++ ++#ifdef LINUXTEST ++ ++#define printf printk ++ ++/** @{ */ ++/** ++ * Register read/write. ++ */ ++static inline u32 dwc_rd32(struct dwc_usb3_device *dev, volatile u32 __iomem *adr) ++{ ++ return readl(adr); ++} ++ ++static inline void dwc_wr32(struct dwc_usb3_device *dev, volatile u32 __iomem *adr, u32 val) ++{ ++ writel(val, adr); ++} ++/** @} */ ++ ++/** @{ */ ++/** ++ * Non-sleeping delays. ++ */ ++#define dwc_udelay(dev, us) udelay(us) ++#define dwc_mdelay(dev, ms) mdelay(ms) ++/** @} */ ++ ++/** ++ * Sleeping delay. ++ */ ++#define dwc_msleep(dev, ms) msleep(ms) ++ ++#else /* !LINUXTEST */ ++ ++/** @{ */ ++/** ++ * Register read/write. ++ */ ++static inline u32 dwc_rd32(struct dwc_usb3_device *dev, volatile u32 __iomem *adr) ++{ ++ return *adr; ++} ++ ++static inline void dwc_wr32(struct dwc_usb3_device *dev, volatile u32 __iomem *adr, u32 val) ++{ ++ *adr = val; ++} ++/** @} */ ++ ++/** @{ */ ++/** ++ * Non-sleeping delays. ++ */ ++#define dwc_udelay(dev, us) do {} while (0) ++#define dwc_mdelay(dev, ms) do {} while (0) ++/** @} */ ++ ++/** ++ * Sleeping delay. ++ */ ++#define dwc_msleep(dev, ms) do {} while (0) ++ ++#endif /* LINUXTEST */ ++ ++/* ++ * Debugging support - vanishes in non-debug builds. ++ */ ++ ++/** Prefix string for print macros */ ++#define USB3_DWC "dwc_usb3: " ++ ++/** @{ */ ++/** Print a debug message */ ++#ifdef DEBUG ++# define dwc_debug(dev, x...) printf(KERN_DEBUG USB3_DWC x ) ++#else ++# define dwc_debug(dev, x...) do {} while (0) ++#endif /* DEBUG */ ++ ++# define dwc_debug0(dev, fmt) dwc_debug(dev, fmt) ++# define dwc_debug1(dev, fmt, a) dwc_debug(dev, fmt, a) ++# define dwc_debug2(dev, fmt, a, b) dwc_debug(dev, fmt, a, b) ++# define dwc_debug3(dev, fmt, a, b, c) dwc_debug(dev, fmt, a, b, c) ++# define dwc_debug4(dev, fmt, a, b, c, d) dwc_debug(dev, fmt, a, b, c, d) ++# define dwc_debug5(dev, fmt, a, b, c, d, e) \ ++ dwc_debug(dev, fmt, a, b, c, d, e) ++# define dwc_debug6(dev, fmt, a, b, c, d, e, f) \ ++ dwc_debug(dev, fmt, a, b, c, d, e, f) ++# define dwc_debug7(dev, fmt, a, b, c, d, e, f, g) \ ++ dwc_debug(dev, fmt, a, b, c, d, e, f, g) ++# define dwc_debug8(dev, fmt, a, b, c, d, e, f, g, h) \ ++ dwc_debug(dev, fmt, a, b, c, d, e, f, g, h) ++# define dwc_debug9(dev, fmt, a, b, c, d, e, f, g, h, i) \ ++ dwc_debug(dev, fmt, a, b, c, d, e, f, g, h, i) ++# define dwc_debug10(dev, fmt, a, b, c, d, e, f, g, h, i, j) \ ++ dwc_debug(dev, fmt, a, b, c, d, e, f, g, h, i, j) ++/** @} */ ++ ++/** @{ */ ++/** Print an isochronous debug message */ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++# define dwc_isocdbg(dev, x...) printf(KERN_DEBUG USB3_DWC x ) ++#else ++# define dwc_isocdbg(dev, x...) do {} while (0) ++#endif ++ ++# define dwc_isocdbg0(dev, fmt) dwc_isocdbg(dev, fmt) ++# define dwc_isocdbg1(dev, fmt, a) dwc_isocdbg(dev, fmt, a) ++# define dwc_isocdbg2(dev, fmt, a, b) dwc_isocdbg(dev, fmt, a, b) ++# define dwc_isocdbg3(dev, fmt, a, b, c) dwc_isocdbg(dev, fmt, a, b, c) ++# define dwc_isocdbg4(dev, fmt, a, b, c, d) \ ++ dwc_isocdbg(dev, fmt, a, b, c, d) ++# define dwc_isocdbg5(dev, fmt, a, b, c, d, e) \ ++ dwc_isocdbg(dev, fmt, a, b, c, d, e) ++# define dwc_isocdbg6(dev, fmt, a, b, c, d, e, f) \ ++ dwc_isocdbg(dev, fmt, a, b, c, d, e, f) ++/** @} */ ++ ++/** @{ */ ++/** Print an Error message */ ++#define dwc_error(dev, x...) printf(KERN_ERR USB3_DWC x ) ++ ++#define dwc_error0(dev, fmt) dwc_error(dev, fmt) ++#define dwc_error1(dev, fmt, a) dwc_error(dev, fmt, a) ++#define dwc_error2(dev, fmt, a, b) dwc_error(dev, fmt, a, b) ++#define dwc_error3(dev, fmt, a, b, c) dwc_error(dev, fmt, a, b, c) ++#define dwc_error4(dev, fmt, a, b, c, d) dwc_error(dev, fmt, a, b, c, d) ++/** @} */ ++ ++/** @{ */ ++/** Print a Warning message */ ++#define dwc_warn(dev, x...) printf(KERN_WARNING USB3_DWC x ) ++ ++#define dwc_warn0(dev, fmt) dwc_warn(dev, fmt) ++#define dwc_warn1(dev, fmt, a) dwc_warn(dev, fmt, a) ++#define dwc_warn2(dev, fmt, a, b) dwc_warn(dev, fmt, a, b) ++#define dwc_warn3(dev, fmt, a, b, c) dwc_warn(dev, fmt, a, b, c) ++#define dwc_warn4(dev, fmt, a, b, c, d) dwc_warn(dev, fmt, a, b, c, d) ++/** @} */ ++ ++/** @{ */ ++/** Print an Informational message (normal but significant) */ ++#define dwc_info(dev, x...) printf(KERN_INFO USB3_DWC x ) ++ ++#define dwc_info0(dev, fmt) dwc_info(dev, fmt) ++#define dwc_info1(dev, fmt, a) dwc_info(dev, fmt, a) ++#define dwc_info2(dev, fmt, a, b) dwc_info(dev, fmt, a, b) ++#define dwc_info3(dev, fmt, a, b, c) dwc_info(dev, fmt, a, b, c) ++#define dwc_info4(dev, fmt, a, b, c, d) dwc_info(dev, fmt, a, b, c, d) ++/** @} */ ++ ++/** @{ */ ++/** Basic message printing */ ++#define dwc_print(dev, x...) printf(USB3_DWC x ) ++ ++#define dwc_print0(dev, fmt) dwc_print(dev, fmt) ++#define dwc_print1(dev, fmt, a) dwc_print(dev, fmt, a) ++#define dwc_print2(dev, fmt, a, b) dwc_print(dev, fmt, a, b) ++#define dwc_print3(dev, fmt, a, b, c) dwc_print(dev, fmt, a, b, c) ++#define dwc_print4(dev, fmt, a, b, c, d) dwc_print(dev, fmt, a, b, c, d) ++#define dwc_print5(dev, fmt, a, b, c, d, e) \ ++ dwc_print(dev, fmt, a, b, c, d, e) ++/** @} */ ++ ++extern int dwc_usb3_gadget_init(struct dwc_usb3_device *usb3_dev); ++extern void dwc_usb3_gadget_remove(struct dwc_usb3_device *usb3_dev); ++extern int dwc_usb3_no_os_setup(dwc_usb3_pcd_t *pcd, usb_device_request_t *ctrl); ++extern int dwc_usb3_function_setup(dwc_usb3_pcd_t *pcd, usb_device_request_t *ctrl); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_NO_OS_DEV_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc3/no_os/no_os_ep0.c b/drivers/usb/gadget/udc/hiudc3/no_os/no_os_ep0.c +new file mode 100644 +index 0000000..26bab51 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/no_os/no_os_ep0.c +@@ -0,0 +1,560 @@ ++/** @file ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++ ++#ifdef DWC_UTE ++#include "ute_if.h" ++#endif ++ ++/*=======================================================================*/ ++/* ++ * EP0 routines ++ */ ++ ++#ifdef DWC_MASS_STORAGE_GADGET ++# define DWC_VENDOR_ID 0x16c3 ++# define DWC_PRODUCT_ID 0x1234 ++#else ++/* We simulate the Linux gadget-zero device */ ++//# define DWC_VENDOR_ID 0x0525 ++//# define DWC_PRODUCT_ID 0xa4a0 ++# define DWC_VENDOR_ID 0x1e08 ++# define DWC_PRODUCT_ID 0x0001 ++#endif ++ ++/* Make the following structure type definitions "packed" if using a Microsoft ++ * compiler. The UPACKED attribute (defined in no_os_defs.h) embedded in the ++ * structure type definitions does the same thing for GCC. Other compilers may ++ * need something different. ++ */ ++#ifdef _MSC_VER ++#include ++#endif ++ ++/* The language string always has string index 0 */ ++static struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wString[1]; ++} UPACKED language_string = { ++ 4, /* bLength (size of string array + 2) */ ++ UDESC_STRING, /* bDescriptorType */ ++ { /* wString[] */ ++ UCONSTW(0x0409), /* US English */ ++ /* others can be added here */ ++ }, ++}; ++ ++static struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wString[8]; ++} UPACKED manuf_string = { ++ 18, /* bLength (size of string array + 2) */ ++ UDESC_STRING, /* bDescriptorType */ ++ { /* wString[] */ ++ UCONSTW('S'), UCONSTW('y'), UCONSTW('n'), UCONSTW('o'), ++ UCONSTW('p'), UCONSTW('s'), UCONSTW('y'), UCONSTW('s'), ++ }, ++}; ++#define DWC_STRING_MANUFACTURER 1 ++ ++static struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wString[8]; ++} UPACKED product_string = { ++ 18, /* bLength (size of string array + 2) */ ++ UDESC_STRING, /* bDescriptorType */ ++ { /* wString[] */ ++ UCONSTW('D'), UCONSTW('W'), UCONSTW('C'), UCONSTW(' '), ++ UCONSTW('U'), UCONSTW('S'), UCONSTW('B'), UCONSTW('3'), ++ }, ++}; ++#define DWC_STRING_PRODUCT 2 ++ ++static struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wString[10]; ++} UPACKED serial_string = { ++ 22, /* bLength (size of string array + 2) */ ++ UDESC_STRING, /* bDescriptorType */ ++ { /* wString[] */ ++ UCONSTW('0'), UCONSTW('1'), UCONSTW('2'), UCONSTW('3'), ++ UCONSTW('4'), UCONSTW('5'), UCONSTW('6'), UCONSTW('7'), ++ UCONSTW('8'), UCONSTW('9'), ++ }, ++}; ++#define DWC_STRING_SERIAL 3 ++ ++/* Stop packing structure type definitions */ ++#ifdef _MSC_VER ++#include ++#endif ++ ++/* These standard USB descriptor types are defined in usb.h */ ++ ++static usb_device_descriptor_t device_desc = { ++ USB_DEVICE_DESCRIPTOR_SIZE, /* bLength */ ++ UDESC_DEVICE, /* bDescriptorType */ ++ ++ UCONSTW(0), /* bcdUSB (filled in later) */ ++ ++#ifdef DWC_MASS_STORAGE_GADGET ++ UDCLASS_IN_INTERFACE, /* bDeviceClass */ ++#else ++ UDCLASS_VENDOR, /* bDeviceClass */ ++#endif ++ 0, /* bDeviceSubClass */ ++ 0, /* bDeviceProtocol */ ++ 0, /* bMaxPacketSize */ ++ ++ UCONSTW(DWC_VENDOR_ID), /* idVendor */ ++ UCONSTW(DWC_PRODUCT_ID), /* idProduct */ ++ UCONSTW(0xffff), /* bcdDevice */ ++ ++ DWC_STRING_MANUFACTURER, /* iManufacturer */ ++ DWC_STRING_PRODUCT, /* iProduct */ ++ DWC_STRING_SERIAL, /* iSerialNumber */ ++ ++ 1, /* bNumConfigurations */ ++}; ++ ++static usb_device_qualifier_t dev_qualifier = { ++ USB_DEVICE_QUALIFIER_SIZE, /* bLength */ ++ UDESC_DEVICE_QUALIFIER, /* bDescriptorType */ ++ ++ UCONSTW(0), /* bcdUSB (filled in later) */ ++ ++#ifdef DWC_MASS_STORAGE_GADGET ++ UDCLASS_IN_INTERFACE, /* bDeviceClass */ ++#else ++ UDCLASS_VENDOR, /* bDeviceClass */ ++#endif ++ 0, /* bDeviceSubClass */ ++ 0, /* bDeviceProtocol */ ++ 0, /* bMaxPacketSize0 */ ++ 1, /* bNumConfigurations */ ++ 0, /* bReserved */ ++}; ++ ++/* These application-specific config descriptor types are defined in ++ * no_os_defs.h ++ */ ++ ++fs_config_desc_t fs_config_desc = { ++ /* config descriptor */ ++ { ++ USB_CONFIG_DESCRIPTOR_SIZE, /* bLength */ ++ UDESC_CONFIG, /* bDescriptorType */ ++ UCONSTW(0), /* wTotalLength (filled in later) */ ++ 1, /* bNumInterface */ ++ 1, /* bConfigurationValue */ ++ 0, /* iConfiguration */ ++ UC_ATT_ONE | UC_ATT_SELFPOWER, /* bmAttributes */ ++ 100 / UC_POWER_FACTOR, /* bMaxPower (100 ma) */ ++ }, ++ /* interface descriptor */ ++ { ++ USB_INTERFACE_DESCRIPTOR_SIZE, /* bLength */ ++ UDESC_INTERFACE, /* bDescriptorType */ ++ 0, /* bInterfaceNumber */ ++ 0, /* bAlternateSetting */ ++ 2, /* bNumEndpoints */ ++ ++#ifdef DWC_MASS_STORAGE_GADGET ++ UICLASS_MASS, /* bInterfaceClass */ ++ UISUBCLASS_SCSI, /* bInterfaceSubClass */ ++ UIPROTO_MASS_BBB, /* bInterfaceProtocol */ ++#else ++ UICLASS_VENDOR, /* bInterfaceClass */ ++ 0, /* bInterfaceSubClass */ ++ 0, /* bInterfaceProtocol */ ++#endif ++ 0, /* iInterface */ ++ }, ++ /* bulk IN endpoint descriptor */ ++ { ++ USB_ENDPOINT_DESCRIPTOR_SIZE, /* bLength */ ++ UDESC_ENDPOINT, /* bDescriptorType */ ++ 1 | UE_DIR_IN, /* bEndpointAddress */ ++ UE_BULK, /* bmAttributes */ ++ UCONSTW(64), /* wMaxPacketSize */ ++ 0, /* bInterval */ ++ }, ++ /* bulk OUT endpoint descriptor */ ++ { ++ USB_ENDPOINT_DESCRIPTOR_SIZE, /* bLength */ ++ UDESC_ENDPOINT, /* bDescriptorType */ ++ 2 | UE_DIR_OUT, /* bEndpointAddress */ ++ UE_BULK, /* bmAttributes */ ++ UCONSTW(64), /* wMaxPacketSize */ ++ 0, /* bInterval */ ++ }, ++}; ++ ++hs_config_desc_t hs_config_desc = { ++ /* config descriptor */ ++ { ++ USB_CONFIG_DESCRIPTOR_SIZE, /* bLength */ ++ UDESC_CONFIG, /* bDescriptorType */ ++ UCONSTW(0), /* wTotalLength (filled in later) */ ++ 1, /* bNumInterface */ ++ 1, /* bConfigurationValue */ ++ 0, /* iConfiguration */ ++ UC_ATT_ONE | UC_ATT_SELFPOWER, /* bmAttributes */ ++ 100 / UC_POWER_FACTOR, /* bMaxPower (100 ma) */ ++ }, ++ /* interface descriptor */ ++ { ++ USB_INTERFACE_DESCRIPTOR_SIZE, /* bLength */ ++ UDESC_INTERFACE, /* bDescriptorType */ ++ 0, /* bInterfaceNumber */ ++ 0, /* bAlternateSetting */ ++ 2, /* bNumEndpoints */ ++ ++#ifdef DWC_MASS_STORAGE_GADGET ++ UICLASS_MASS, /* bInterfaceClass */ ++ UISUBCLASS_SCSI, /* bInterfaceSubClass */ ++ UIPROTO_MASS_BBB, /* bInterfaceProtocol */ ++#else ++ UICLASS_VENDOR, /* bInterfaceClass */ ++ 0, /* bInterfaceSubClass */ ++ 0, /* bInterfaceProtocol */ ++#endif ++ 0, /* iInterface */ ++ }, ++ /* bulk IN endpoint descriptor */ ++ { ++ USB_ENDPOINT_DESCRIPTOR_SIZE, /* bLength */ ++ UDESC_ENDPOINT, /* bDescriptorType */ ++ 1 | UE_DIR_IN, /* bEndpointAddress */ ++ UE_BULK, /* bmAttributes */ ++ UCONSTW(512), /* wMaxPacketSize */ ++ 0, /* bInterval */ ++ }, ++ /* bulk OUT endpoint descriptor */ ++ { ++ USB_ENDPOINT_DESCRIPTOR_SIZE, /* bLength */ ++ UDESC_ENDPOINT, /* bDescriptorType */ ++ 2 | UE_DIR_OUT, /* bEndpointAddress */ ++ UE_BULK, /* bmAttributes */ ++ UCONSTW(512), /* wMaxPacketSize */ ++ 1, /* bInterval (every uframe) */ ++ }, ++}; ++ ++ss_config_desc_t ss_config_desc = { ++ /* config descriptor */ ++ { ++ USB_CONFIG_DESCRIPTOR_SIZE, /* bLength */ ++ UDESC_CONFIG, /* bDescriptorType */ ++ UCONSTW(0), /* wTotalLength (filled in later) */ ++ 1, /* bNumInterface */ ++ 1, /* bConfigurationValue */ ++ 0, /* iConfiguration */ ++ UC_ATT_ONE | UC_ATT_SELFPOWER, /* bmAttributes */ ++ 100 / UC_POWER_FACTOR, /* bMaxPower (100 ma) */ ++ }, ++ /* interface descriptor */ ++ { ++ USB_INTERFACE_DESCRIPTOR_SIZE, /* bLength */ ++ UDESC_INTERFACE, /* bDescriptorType */ ++ 0, /* bInterfaceNumber */ ++ 0, /* bAlternateSetting */ ++ 2, /* bNumEndpoints */ ++ ++#ifdef DWC_MASS_STORAGE_GADGET ++ UICLASS_MASS, /* bInterfaceClass */ ++ UISUBCLASS_SCSI, /* bInterfaceSubClass */ ++ UIPROTO_MASS_BBB, /* bInterfaceProtocol */ ++#else ++ UICLASS_VENDOR, /* bInterfaceClass */ ++ 0, /* bInterfaceSubClass */ ++ 0, /* bInterfaceProtocol */ ++#endif ++ 0, /* iInterface */ ++ }, ++ /* bulk IN endpoint descriptor */ ++ { ++ USB_ENDPOINT_DESCRIPTOR_SIZE, /* bLength */ ++ UDESC_ENDPOINT, /* bDescriptorType */ ++ 1 | UE_DIR_IN, /* bEndpointAddress */ ++ UE_BULK, /* bmAttributes */ ++ UCONSTW(1024), /* wMaxPacketSize */ ++ 0, /* bInterval */ ++ }, ++ /* bulk IN companion descriptor */ ++ { ++ USB_SS_ENDPOINT_COMPANION_DESCRIPTOR_SIZE, /* bLength */ ++ UDESC_SS_USB_COMPANION, /* bDescriptorType */ ++ 15, /* bMaxBurst */ ++ 0, /* bmAttributes */ ++ UCONSTW(0), /* wBytesPerInterval */ ++ }, ++ /* bulk OUT endpoint descriptor */ ++ { ++ USB_ENDPOINT_DESCRIPTOR_SIZE, /* bLength */ ++ UDESC_ENDPOINT, /* bDescriptorType */ ++ 2 | UE_DIR_OUT, /* bEndpointAddress */ ++ UE_BULK, /* bmAttributes */ ++ UCONSTW(1024), /* wMaxPacketSize */ ++ 0, /* bInterval */ ++ }, ++ /* bulk OUT companion descriptor */ ++ { ++ USB_SS_ENDPOINT_COMPANION_DESCRIPTOR_SIZE, /* bLength */ ++ UDESC_SS_USB_COMPANION, /* bDescriptorType */ ++ 15, /* bMaxBurst */ ++ 0, /* bmAttributes */ ++ UCONSTW(0), /* wBytesPerInterval */ ++ }, ++}; ++ ++/** ++ * This routine handles Get Descriptor requests. ++ */ ++static int no_os_get_descriptor(dwc_usb3_pcd_t *pcd, usb_device_request_t *ctrl) ++{ ++ u8 desc_type = UGETW(ctrl->wValue) >> 8; ++ u8 desc_idx = UGETW(ctrl->wValue); ++ u16 max = UGETW(ctrl->wLength); ++ u8 *buf = pcd->ep0_status_buf; ++ u16 len; ++ ++#ifdef DEBUG_EP0 ++ dwc_debug5(pcd->usb3_dev, "GET_DESCRIPTOR %02x.%02x v%04x i%04x l%04x\n", ++ ctrl->bmRequestType, ctrl->bRequest, UGETW(ctrl->wValue), ++ UGETW(ctrl->wIndex), UGETW(ctrl->wLength)); ++#endif ++ switch (desc_type) { ++ case UDESC_DEVICE: ++ if (desc_idx) ++ return -DWC_E_NOT_SUPPORTED; ++ ++ switch (pcd->speed) { ++ case USB_SPEED_SUPER: ++ USETW(device_desc.bcdUSB, 0x300); ++ device_desc.bMaxPacketSize = 9; ++ break; ++ ++ case USB_SPEED_HIGH: ++ USETW(device_desc.bcdUSB, 0x200); ++ device_desc.bMaxPacketSize = 64; ++ break; ++ ++ default: ++ USETW(device_desc.bcdUSB, 0x200); ++ device_desc.bMaxPacketSize = 64; ++ break; ++ } ++ ++ memcpy(buf, &device_desc, sizeof(device_desc)); ++ len = sizeof(device_desc); ++ break; ++ ++ case UDESC_CONFIG: ++ if (desc_idx) ++ return -DWC_E_NOT_SUPPORTED; ++ ++ switch (pcd->speed) { ++ case USB_SPEED_SUPER: ++ USETW(ss_config_desc.config_desc.wTotalLength, ++ sizeof(ss_config_desc)); ++ memcpy(buf, &ss_config_desc, sizeof(ss_config_desc)); ++ len = sizeof(ss_config_desc); ++ break; ++ ++ case USB_SPEED_HIGH: ++ USETW(hs_config_desc.config_desc.wTotalLength, ++ sizeof(hs_config_desc)); ++ memcpy(buf, &hs_config_desc, sizeof(hs_config_desc)); ++ len = sizeof(hs_config_desc); ++ break; ++ ++ default: ++ USETW(fs_config_desc.config_desc.wTotalLength, ++ sizeof(fs_config_desc)); ++ memcpy(buf, &fs_config_desc, sizeof(fs_config_desc)); ++ len = sizeof(fs_config_desc); ++ break; ++ } ++ ++ break; ++ ++ case UDESC_STRING: ++ switch (desc_idx) { ++ case 0: ++ memcpy(buf, &language_string, sizeof(language_string)); ++ len = sizeof(language_string); ++ break; ++ ++ case DWC_STRING_MANUFACTURER: ++ memcpy(buf, &manuf_string, sizeof(manuf_string)); ++ len = sizeof(manuf_string); ++ break; ++ ++ case DWC_STRING_PRODUCT: ++ memcpy(buf, &product_string, sizeof(product_string)); ++ len = sizeof(product_string); ++ break; ++ ++ case DWC_STRING_SERIAL: ++ memcpy(buf, &serial_string, sizeof(serial_string)); ++ len = sizeof(serial_string); ++ break; ++ ++ default: ++ return -DWC_E_NOT_SUPPORTED; ++ } ++ ++ break; ++ ++ case UDESC_DEVICE_QUALIFIER: ++ if (desc_idx || pcd->speed == USB_SPEED_SUPER) ++ return -DWC_E_NOT_SUPPORTED; ++ ++ USETW(dev_qualifier.bcdUSB, 0x200); ++ dev_qualifier.bMaxPacketSize0 = 9; ++ memcpy(buf, &dev_qualifier, sizeof(dev_qualifier)); ++ len = sizeof(dev_qualifier); ++ break; ++ ++ case UDESC_OTHER_SPEED_CONFIGURATION: ++ if (desc_idx || pcd->speed == USB_SPEED_SUPER) ++ return -DWC_E_NOT_SUPPORTED; ++ ++ switch (pcd->speed) { ++ case USB_SPEED_HIGH: ++ ss_config_desc.config_desc.bDescriptorType = ++ UDESC_OTHER_SPEED_CONFIGURATION; ++ USETW(ss_config_desc.config_desc.wTotalLength, ++ sizeof(ss_config_desc)); ++ memcpy(buf, &ss_config_desc, sizeof(ss_config_desc)); ++ ss_config_desc.config_desc.bDescriptorType = UDESC_CONFIG; ++ len = sizeof(ss_config_desc); ++ break; ++ ++ default: ++ hs_config_desc.config_desc.bDescriptorType = ++ UDESC_OTHER_SPEED_CONFIGURATION; ++ USETW(hs_config_desc.config_desc.wTotalLength, ++ sizeof(hs_config_desc)); ++ memcpy(buf, &hs_config_desc, sizeof(hs_config_desc)); ++ hs_config_desc.config_desc.bDescriptorType = UDESC_CONFIG; ++ len = sizeof(hs_config_desc); ++ break; ++ } ++ ++ break; ++ ++ default: ++ return -DWC_E_NOT_SUPPORTED; ++ } ++ ++ pcd->ep0state = EP0_IN_DATA_PHASE; ++ pcd->ep0_req->dwc_req.length = len < max ? len : max; ++ pcd->ep0_status_pending = 1; ++ pcd->ep0_req->dwc_req.buf[0] = pcd->ep0_status_buf; ++ pcd->ep0_req->dwc_req.bufdma[0] = pcd->ep0_status_buf_dma; ++ pcd->ep0_req->dwc_req.actual = 0; ++ dwc_usb3_pcd_ep0_start_transfer(pcd, pcd->ep0_req); ++ ++ return 0; ++} ++ ++/** ++ * This routine processes SETUP commands. The USB Command processing is ++ * done in two places - the first being the PCD and the second being the ++ * Gadget driver (for example, the File-Backed Storage Gadget driver). ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ *
Command Driver Description
SET_FEATURE PCD / Gadget driver Device ++ * and Endpoint requests are processed by the PCD. Interface requests ++ * are passed to the Gadget driver.
CLEAR_FEATURE PCD Device and Endpoint ++ * requests are processed by the PCD. Interface requests are ignored. ++ * The only Endpoint feature handled is ENDPOINT_HALT.
GET_DESCRIPTOR Gadget driver Return the ++ * requested descriptor.
SET_DESCRIPTOR Gadget driver Optional - ++ * not implemented by any of the existing Gadget drivers.
GET_CONFIGURATION Gadget driver Return ++ * the current configuration.
SET_CONFIGURATION Gadget driver Disable ++ * all EPs and enable EPs for new configuration.
GET_INTERFACE Gadget driver Return the ++ * current interface.
SET_INTERFACE Gadget driver Disable all ++ * EPs and enable EPs for new interface.
++ * ++ * When the SETUP Phase Done interrupt occurs, the generic SETUP commands ++ * are processed by dwc_usb3_do_setup(). Calling the gadget driver's ++ * dwc_usb3_gadget_setup() routine from dwc_usb3_do_setup() in turn calls ++ * this routine to process the gadget-specific SETUP commands. Any requests ++ * not handled here are passed to the Function Driver's ++ * dwc_usb3_function_setup() routine. ++ */ ++int dwc_usb3_no_os_setup(dwc_usb3_pcd_t *pcd, usb_device_request_t *ctrl) ++{ ++ dwc_debug2(pcd->usb3_dev, "%s(%lx)\n", __func__, (unsigned long)pcd); ++ ++ if ((UT_GET_TYPE(ctrl->bmRequestType)) != UT_STANDARD) { ++ /* handle non-standard (class/vendor) requests ++ * in the Function Driver ++ */ ++ return dwc_usb3_function_setup(pcd, ctrl); ++ } ++ ++ /* @todo NGS: Handle bad setup packet? */ ++ ++/////////////////////////////////////////// ++//// --- Standard Request handling --- //// ++ ++ switch (ctrl->bRequest) { ++ case UR_SET_FEATURE: ++ return dwc_usb3_function_setup(pcd, ctrl); ++ ++ case UR_SET_INTERFACE: ++ return dwc_usb3_function_setup(pcd, ctrl); ++ ++ case UR_GET_INTERFACE: ++ return dwc_usb3_function_setup(pcd, ctrl); ++ ++ case UR_SET_CONFIG: ++ return dwc_usb3_function_setup(pcd, ctrl); ++ ++ case UR_GET_CONFIG: ++ return dwc_usb3_function_setup(pcd, ctrl); ++ ++ case UR_SYNCH_FRAME: ++ return dwc_usb3_function_setup(pcd, ctrl); ++ ++ case UR_GET_DESCRIPTOR: ++ return no_os_get_descriptor(pcd, ctrl); ++ ++ default: ++ /* Call the Function Driver setup routines */ ++ return dwc_usb3_function_setup(pcd, ctrl); ++ } ++ ++ return 0; ++} +diff --git a/drivers/usb/gadget/udc/hiudc3/no_os/no_os_gadget.c b/drivers/usb/gadget/udc/hiudc3/no_os/no_os_gadget.c +new file mode 100644 +index 0000000..5bd2c6a +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/no_os/no_os_gadget.c +@@ -0,0 +1,733 @@ ++/** @file ++ * ++ * Application-specific Function Driver interface ++ * ++ * Simple applications may wish to implement their entire Function Driver here. ++ * ++ * More complex applications, or environments with an existing Function Driver ++ * framework (such as the Linux Gadget framework) will implement the interface ++ * to their Function Driver here. ++ * ++ * See the linux/ subdirectory for an example implementation of a Linux Gadget ++ * framework interface. ++ * ++ * For historical reasons, the PCD API uses the Linux term "gadget" to refer to ++ * a Function Driver. ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++ ++/** Driver context struct - defined in no_os_init.c */ ++extern dwc_usb3_device_t g_usb3_dev; ++ ++/** @{ */ ++/** PCD request pool - defined in no_os_init.c */ ++extern dwc_usb3_pcd_req_t g_pcd_req[]; ++extern u32 g_pcd_req_bm; ++/** @} */ ++ ++#ifndef LINUXTEST ++/** @{ */ ++/** DMA descriptor (TRB) pools for non-EP0 EPs - defined in no_os_init.c */ ++extern dwc_usb3_dma_desc_t g_out_trb_pool[][DWC_NUM_ISOC_TRBS + 1]; ++extern dwc_usb3_dma_desc_t g_in_trb_pool[][DWC_NUM_ISOC_TRBS + 1]; ++/** @} */ ++#endif ++ ++/****************************************************************************** ++ * Function Driver notification routines ++ * ++ * These routines receive notifications from the PCD when certain events occur ++ * which the Function Driver may need to be aware of. ++ * ++ * These routines *must* have the exact names and parameters shown here, ++ * because they are part of the API between the PCD and the Function Driver. ++ ******************************************************************************/ ++ ++/** ++ * This routine receives Connect notifications from the PCD ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param speed Speed of the connection (as defined in usb.h). ++ * @return 0 for success, else negative error code. ++ */ ++int dwc_usb3_gadget_connect(dwc_usb3_pcd_t *pcd, int speed) ++{ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ dwc_usb3_function_connect(pcd->usb3_dev, speed); ++ return 0; ++} ++ ++/** ++ * This routine receives Disconnect notifications from the PCD ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @return 0 for success, else negative error code. ++ */ ++int dwc_usb3_gadget_disconnect(dwc_usb3_pcd_t *pcd) ++{ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ dwc_usb3_function_disconnect(pcd->usb3_dev); ++ return 0; ++} ++ ++/** ++ * This routine receives Suspend notifications from the PCD ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @return 0 for success, else negative error code. ++ */ ++int dwc_usb3_gadget_suspend(dwc_usb3_pcd_t *pcd) ++{ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ return 0; ++} ++ ++/** ++ * This routine receives Resume notifications from the PCD ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @return 0 for success, else negative error code. ++ */ ++int dwc_usb3_gadget_resume(dwc_usb3_pcd_t *pcd) ++{ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ return 0; ++} ++ ++/** ++ * This routine receives Setup request notifications from the PCD ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param ctrl Pointer to the Setup packet for the request. ++ * @return 0 for success, else negative error code. ++ */ ++int dwc_usb3_gadget_setup(dwc_usb3_pcd_t *pcd, usb_device_request_t *ctrl) ++{ ++ int ret; ++ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ ++ ret = dwc_usb3_no_os_setup(pcd, ctrl); ++ ++ return ret; ++} ++ ++/** ++ * This routine receives Transfer Complete notifications from the PCD ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param pcd_ep PCD EP for the transfer. ++ * @param pcd_req PCD request for the transfer. ++ * @param status Transfer status, 0 for success else negative error code. ++ * @return 0 for success, else negative error code. ++ */ ++int dwc_usb3_gadget_complete(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *pcd_ep, ++ dwc_usb3_pcd_req_t *pcd_req, int status) ++{ ++ usb_ep_t *usb_ep = &pcd_ep->usb_ep; ++ usb_request_t *usb_req = &pcd_req->usb_req; ++ u32 actual = pcd_req->dwc_req.actual; ++ ++ dwc_debug2(pcd->usb3_dev, "%s(%lx)\n", __func__, (unsigned long)pcd_ep); ++ ++ /* Remove the request from the queue */ ++ DWC_CIRCLEQ_REMOVE_INIT(&pcd_ep->dwc_ep.queue, pcd_req, entry); ++ ++ usb_req->status = status; ++ usb_req->actual = actual; ++ ++ if (usb_req->complete) { ++ dwc_release_spinlock(pcd->usb3_dev, &pcd->lock); ++ usb_req->complete(usb_ep, usb_req); ++ dwc_acquire_spinlock(pcd->usb3_dev, &pcd->lock); ++ } ++ ++ if (pcd->request_pending > 0) ++ --pcd->request_pending; ++ ++ return 0; ++} ++ ++/** ++ * This routine allows overriding the standard Control transfer handling ++ * (currently only done by the axs101 test gadget) ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ */ ++void dwc_usb3_gadget_do_setup(dwc_usb3_pcd_t *pcd) ++{ ++ /* Call the standard Control transfer handler */ ++ dwc_usb3_pcd_do_setup(pcd); ++} ++ ++/****************************************************************************** ++ * Function Driver callback routines ++ * ++ * The PCD calls these routines when it needs something from the Function ++ * Driver. ++ * ++ * These routines *must* have the exact names and parameters shown here, ++ * because they are part of the API between the PCD and the Function Driver. ++ ******************************************************************************/ ++ ++/** ++ * This routine allocates coherent DMA memory. It is used by the PCD to ++ * allocate memory for TRBs. The block of memory returned must have a start ++ * address aligned to a 16-byte boundary. ++ * ++ * This routine may be called from interrupt context, so it must be able to ++ * allocate coherent DMA memory in that context. One strategy would be to ++ * preallocate a block of memory at initialization time, and hand out chunks ++ * from that block in this routine. ++ * ++ * @param pcd_ep PCD EP that memory block will be associated with. ++ * @param size Size of memory block to allocate, in bytes. ++ * @param mem_dma_ret Physical address of allocated memory block is returned ++ * through this pointer. ++ * @return Address of allocated memory block, or NULL if allocation ++ * fails. ++ */ ++void *dwc_usb3_gadget_alloc_dma(dwc_usb3_pcd_ep_t *pcd_ep, int size, dwc_dma_t *mem_dma_ret) ++{ ++ void *mem; ++ dwc_dma_t mem_dma; ++ ++ dwc_debug2(pcd_ep->dwc_ep.pcd->usb3_dev, "%s(%lx)\n", __func__, (unsigned long)pcd_ep); ++ ++ if (!pcd_ep->dwc_ep.num) { ++ dwc_error0(pcd_ep->dwc_ep.pcd->usb3_dev, "USB epnum is 0 for pcd_ep\n"); ++ return NULL; ++ } ++ ++#ifdef LINUXTEST ++ mem = dma_alloc_coherent(g_usb3_dev.dev, size, &mem_dma, GFP_ATOMIC | GFP_DMA32); ++ if (!mem) ++ return NULL; ++#else ++ if (pcd_ep->dwc_ep.is_in) ++ mem = (void *)&g_in_trb_pool[pcd_ep->dwc_ep.num - 1]; ++ else ++ mem = (void *)&g_out_trb_pool[pcd_ep->dwc_ep.num - 1]; ++ ++ mem_dma = (dwc_dma_t)mem; ++#endif ++ *mem_dma_ret = mem_dma; ++ ++ return mem; ++} ++ ++/** ++ * This routine frees DMA memory allocated by dwc_usb3_gadget_alloc_dma(). ++ * ++ * @param pcd_ep PCD EP that memory block is associated with. ++ * @param size Size of memory block to free, in bytes. ++ * @param mem Address of memory block. ++ * @param mem_dma Physical address of memory block. ++ */ ++void dwc_usb3_gadget_free_dma(dwc_usb3_pcd_ep_t *pcd_ep, int size, void *mem, dwc_dma_t mem_dma) ++{ ++ dwc_debug2(pcd_ep->dwc_ep.pcd->usb3_dev, "%s(%lx)\n", __func__, (unsigned long)pcd_ep); ++ ++#ifdef LINUXTEST ++ dma_free_coherent(g_usb3_dev.dev, size, mem, mem_dma); ++#endif ++} ++ ++/** ++ * This routine returns the PCD request corresponding to the current transfer ++ * request for an endpoint. The current transfer request is the first request ++ * submitted that has not been completed yet. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param pcd_ep PCD EP to operate on. ++ * @return Pointer to PCD request, or NULL if no request available. ++ */ ++dwc_usb3_pcd_req_t *dwc_usb3_gadget_get_request(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *pcd_ep) ++{ ++ dwc_usb3_pcd_req_t *pcd_req; ++ ++ dwc_debug2(pcd->usb3_dev, "%s(%lx)\n", __func__, (unsigned long)pcd_ep); ++ ++ /* Check for a pending request */ ++ if (DWC_CIRCLEQ_EMPTY(&pcd_ep->dwc_ep.queue)) { ++ dwc_debug0(pcd->usb3_dev, "ep->dwc_ep.queue empty\n"); ++ return NULL; ++ } ++ ++ pcd_req = DWC_CIRCLEQ_FIRST(&pcd_ep->dwc_ep.queue); ++ return pcd_req; ++} ++ ++/** ++ * This routine checks to see if there is another transfer request waiting ++ * on an endpoint that has not been started yet. If so then that transfer is ++ * started. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param pcd_ep PCD EP to operate on. ++ */ ++void dwc_usb3_gadget_start_next_request(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *pcd_ep) ++{ ++ dwc_usb3_pcd_req_t *pcd_req = NULL; ++ ++ dwc_debug2(pcd->usb3_dev, "%s(%lx)\n", __func__, (unsigned long)pcd_ep); ++ ++ if (DWC_CIRCLEQ_EMPTY(&pcd_ep->dwc_ep.queue)) { ++ dwc_debug2(pcd->usb3_dev, "start_next EP%d-%s: queue empty\n", ++ pcd_ep->dwc_ep.num, pcd_ep->dwc_ep.is_in ? "IN" : "OUT"); ++ return; ++ } ++ ++ DWC_CIRCLEQ_FOREACH(pcd_req, &pcd_ep->dwc_ep.queue, entry) { ++ if (!(pcd_req->dwc_req.flags & DWC_PCD_REQ_STARTED)) { ++ dwc_debug2(pcd->usb3_dev, "start_next EP%d-%s: OK\n", ++ pcd_ep->dwc_ep.num, pcd_ep->dwc_ep.is_in ? "IN" : "OUT"); ++ ++ /* Setup and start the transfer */ ++ dwc_usb3_pcd_fill_trbs(pcd, pcd_ep, pcd_req); ++ dwc_usb3_pcd_ep_start_transfer(pcd, pcd_ep, pcd_req, 0); ++ return; ++ } ++ } ++ ++ dwc_debug2(pcd->usb3_dev, "start_next EP%d-%s: all req active\n", ++ pcd_ep->dwc_ep.num, pcd_ep->dwc_ep.is_in ? "IN" : "OUT"); ++} ++ ++/** ++ * Start an Isoc EP running at the proper interval, after receiving the initial ++ * XferNrdy event. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param pcd_ep EP to operate on. ++ * @param event Event data containing the XferNrdy microframe. ++ */ ++void dwc_usb3_gadget_isoc_ep_start(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *pcd_ep, u32 event) ++{ ++ dwc_usb3_pcd_req_t *pcd_req = NULL; ++ ++ dwc_debug3(pcd->usb3_dev, "%s(%lx,%x)\n", __func__, (unsigned long)pcd_ep, event); ++ dwc_isocdbg2(pcd->usb3_dev, "%s(%08x)\n", __func__, event); ++ ++ if (DWC_CIRCLEQ_EMPTY(&pcd_ep->dwc_ep.queue)) { ++ dwc_debug2(pcd->usb3_dev, "%s(%lx), ep->dwc_ep.queue empty\n", ++ __func__, (unsigned long)pcd_ep); ++ return; ++ } ++ ++ if (pcd_ep->dwc_ep.desc_avail <= 0) { ++ dwc_debug2(pcd->usb3_dev, "EP%d-%s: no TRB avail\n", ++ pcd_ep->dwc_ep.num, pcd_ep->dwc_ep.is_in ? "IN" : "OUT"); ++ return; ++ } ++ ++ /* If need to restart after hibernation, handle that and return */ ++ if (dwc_usb3_pcd_isoc_ep_hiber_restart(pcd, pcd_ep)) ++ return; ++ ++ /* ++ * Start the next queued transfer at the target uFrame ++ */ ++ ++ DWC_CIRCLEQ_FOREACH(pcd_req, &pcd_ep->dwc_ep.queue, entry) { ++ if (pcd_req->dwc_req.flags & DWC_PCD_REQ_STARTED) ++ pcd_req = NULL; ++ else ++ break; ++ } ++ ++ dwc_debug1(pcd->usb3_dev, "req=%lx\n", (unsigned long)pcd_req); ++ if (!pcd_req) { ++ dwc_debug2(pcd->usb3_dev, "EP%d-%s: no requests to start\n", ++ pcd_ep->dwc_ep.num, pcd_ep->dwc_ep.is_in ? "IN" : "OUT"); ++ return; ++ } ++ ++ dwc_usb3_pcd_fill_trbs(pcd, pcd_ep, pcd_req); ++ dwc_usb3_pcd_ep_start_transfer(pcd, pcd_ep, pcd_req, event); ++ ++ /* ++ * Now start any remaining queued transfers ++ */ ++ ++ while (pcd_req != DWC_CIRCLEQ_LAST(&pcd_ep->dwc_ep.queue)) { ++ pcd_req = DWC_CIRCLEQ_NEXT(pcd_req, entry); ++ if (!(pcd_req->dwc_req.flags & DWC_PCD_REQ_STARTED)) { ++ dwc_usb3_pcd_fill_trbs(pcd, pcd_ep, pcd_req); ++ dwc_usb3_pcd_ep_start_transfer(pcd, pcd_ep, pcd_req, 0); ++ } ++ } ++} ++ ++/** ++ * This routine terminates all requests which are pending on an endpoint. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param pcd_ep EP to operate on. ++ */ ++void dwc_usb3_gadget_request_nuke(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *pcd_ep) ++{ ++ dwc_usb3_pcd_req_t *pcd_req; ++ ++ dwc_debug2(pcd->usb3_dev, "%s(%lx)\n", __func__, (unsigned long)pcd_ep); ++ pcd_ep->dwc_ep.stopped = 1; ++ ++ while (!DWC_CIRCLEQ_EMPTY(&pcd_ep->dwc_ep.queue)) { ++ pcd_req = DWC_CIRCLEQ_FIRST(&pcd_ep->dwc_ep.queue); ++ dwc_usb3_pcd_request_done(pcd, pcd_ep, pcd_req, -DWC_E_SHUTDOWN); ++ } ++ ++ if (pcd_ep != pcd->ep0) ++ pcd_ep->dwc_ep.hiber_desc_idx = 0; ++} ++ ++/** ++ * This routine marks all pending requests for an EP as not started. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param pcd_ep EP to operate on. ++ */ ++void dwc_usb3_gadget_set_ep_not_started(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *pcd_ep) ++{ ++ dwc_usb3_pcd_req_t *pcd_req; ++ ++ dwc_debug2(pcd->usb3_dev, "%s(%lx)\n", __func__, (unsigned long)pcd_ep); ++ ++ DWC_CIRCLEQ_FOREACH(pcd_req, &pcd_ep->dwc_ep.queue, entry) { ++ if (pcd_req->dwc_req.flags & DWC_PCD_REQ_STARTED) ++ pcd_req->dwc_req.flags &= ~DWC_PCD_REQ_STARTED; ++ } ++} ++ ++/****************************************************************************** ++ * Function Driver user-defined routines ++ * ++ * These routines are completely user-defined, and can implement whatever is ++ * required for the application's Function Driver. ++ * ++ * The example code here implements a simple interface which allows external ++ * code to implement the application's Function Driver by calling these ++ * routines. ++ ******************************************************************************/ ++ ++/** ++ * This routine enables a USB endpoint ++ * ++ * @param usb3_dev Programming view of DWC_usb3 device. ++ * @param epdesc USB endpoint descriptor for the EP. ++ * @param epcomp USB SS endpoint companion descriptor for the EP. ++ * @return Pointer to USB EP context, or NULL on failure. ++ */ ++usb_ep_t *dwc_usb3_ep_enable(struct dwc_usb3_device *usb3_dev, const void *epdesc, const void *epcomp) ++{ ++ const usb_endpoint_descriptor_t *ep_desc = epdesc; ++ const ss_endpoint_companion_descriptor_t *ep_comp = epcomp; ++ dwc_usb3_pcd_t *pcd = &usb3_dev->pcd; ++ dwc_usb3_pcd_ep_t *pcd_ep; ++ dwc_usb3_dma_desc_t *desc; ++ dwc_dma_t desc_dma; ++ usb_ep_t *usb_ep; ++ int ep_num, ep_dir, ep_type; ++ int link, num_trbs, retval; ++ ++ dwc_debug1(usb3_dev, "%s()\n", __func__); ++ ++ ep_num = UE_GET_ADDR(ep_desc->bEndpointAddress); ++ ep_dir = UE_GET_DIR(ep_desc->bEndpointAddress); ++ ep_type = UE_GET_XFERTYPE(ep_desc->bmAttributes); ++ link = 0; ++ ++ if (ep_num < 1 || ep_num >= DWC_MAX_EPS) ++ return NULL; ++ ++ if (ep_dir == UE_DIR_IN) ++ pcd_ep = pcd->in_ep[ep_num - 1]; ++ else ++ pcd_ep = pcd->out_ep[ep_num - 1]; ++ usb_ep = &pcd_ep->usb_ep; ++ ++ /* Allocate the number of TRBs based on EP type */ ++ switch (ep_type) { ++ case UE_INTERRUPT: ++ num_trbs = DWC_NUM_INTR_TRBS; ++ break; ++ case UE_ISOCHRONOUS: ++ num_trbs = DWC_NUM_ISOC_TRBS; ++ link = 1; ++ break; ++ default: ++ num_trbs = DWC_NUM_BULK_TRBS; ++ break; ++ } ++ ++ dwc_debug5(usb3_dev, "ep%d-%s=%lx phys=%d pcd_ep=%lx\n", ep_num, ++ ep_dir == UE_DIR_IN ? "IN" : "OUT", (unsigned long)usb_ep, ++ pcd_ep->dwc_ep.phys, (unsigned long)pcd_ep); ++ ++ /* Set the TRB allocation for this EP */ ++ desc = dwc_usb3_pcd_trb_alloc(pcd_ep, num_trbs, ep_type, ep_desc->bInterval - 1, ++ link, &desc_dma); ++ if (!desc) ++ return NULL; ++ ++ /* Call the PCD API routine to enable the endpoint */ ++ retval = dwc_usb3_pcd_ep_enable(pcd, pcd_ep, ep_desc, ep_comp); ++ if (retval) { ++ dwc_usb3_pcd_trb_free(pcd_ep); ++ return NULL; ++ } ++ ++ usb_ep->maxpacket = UGETW(ep_desc->wMaxPacketSize); ++ usb_ep->desc = epdesc; ++ ++ return usb_ep; ++} ++ ++/** ++ * This routine disables a USB endpoint ++ * ++ * @param usb3_dev Programming view of DWC_usb3 device. ++ * @param usb_ep USB EP to disable. ++ * @return 0 for success, else negative error code. ++ */ ++int dwc_usb3_ep_disable(struct dwc_usb3_device *usb3_dev, usb_ep_t *usb_ep) ++{ ++ dwc_usb3_pcd_t *pcd = &usb3_dev->pcd; ++ dwc_usb3_pcd_ep_t *pcd_ep; ++ int retval; ++ ++ dwc_debug2(usb3_dev, "%s(%lx)\n", __func__, (unsigned long)usb_ep); ++ pcd_ep = dwc_usb3_get_pcd_ep(usb_ep); ++ ++ /* Call the PCD API routine to disable the endpoint */ ++ retval = dwc_usb3_pcd_ep_disable(pcd, pcd_ep); ++ ++ dwc_usb3_pcd_trb_free(pcd_ep); ++ ++ return retval; ++} ++ ++/** ++ * This routine allocates a USB request object to use with the specified USB ++ * endpoint. The contents of a USB request are defined by the Function Driver, ++ * and are opaque to the PCD. The USB request is embedded inside of an enclosing ++ * PCD request object (see the definition of struct dwc_usb3_pcd_req in pcd.h). ++ * One request object is needed for each transfer that is submitted to the PCD. ++ * ++ * @param usb3_dev Programming view of DWC_usb3 device. ++ * @param usb_ep USB EP for the request. ++ */ ++usb_request_t *dwc_usb3_alloc_request(struct dwc_usb3_device *usb3_dev, usb_ep_t *usb_ep) ++{ ++ dwc_usb3_pcd_req_t *pcd_req; ++ unsigned int req_idx; ++ ++ dwc_debug2(usb3_dev, "%s(%lx)\n", __func__, (unsigned long)usb_ep); ++ ++ for (req_idx = 0; req_idx < 32; req_idx++) { ++ if (g_pcd_req_bm & (1 << req_idx)) { ++ g_pcd_req_bm &= ~(1 << req_idx); ++ pcd_req = &g_pcd_req[req_idx]; ++ memset(pcd_req, 0, sizeof(*pcd_req)); ++ pcd_req->usb_req.dma = DWC_DMA_ADDR_INVALID; ++ return &pcd_req->usb_req; ++ } ++ } ++ ++ return NULL; ++} ++ ++/** ++ * This routine frees a USB request object ++ * ++ * @param usb3_dev Programming view of DWC_usb3 device. ++ * @param usb_ep USB EP for the request. ++ * @param usb_req USB request to be freed. ++ */ ++void dwc_usb3_free_request(struct dwc_usb3_device *usb3_dev, usb_ep_t *usb_ep, usb_request_t *usb_req) ++{ ++ dwc_usb3_pcd_req_t *pcd_req = dwc_usb3_get_pcd_req(usb_req); ++ unsigned int req_idx = pcd_req - &g_pcd_req[0]; ++ ++ dwc_debug2(usb3_dev, "%s(%lx)\n", __func__, (unsigned long)usb_ep); ++ ++ if (req_idx >= 32) { ++ dwc_error1(usb3_dev, "Bad request index %u\n", req_idx); ++ return; ++ } ++ ++ g_pcd_req_bm |= 1 << req_idx; ++} ++ ++/** ++ * This routine submits a transfer request for a USB endpoint. The example code ++ * maintains a queue of requests for each endpoint, so that the application can ++ * start another transfer on the same endpoint without having to wait for the ++ * first transfer to complete. ++ * ++ * @param usb3_dev Programming view of DWC_usb3 device. ++ * @param usb_ep USB EP for the transfer. ++ * @param usb_req USB request for the transfer. ++ * @return 0 for success, else negative error code. ++ */ ++int dwc_usb3_ep_queue(struct dwc_usb3_device *usb3_dev, usb_ep_t *usb_ep, usb_request_t *usb_req) ++{ ++ dwc_usb3_pcd_t *pcd = &usb3_dev->pcd; ++ dwc_usb3_pcd_ep_t *pcd_ep = dwc_usb3_get_pcd_ep(usb_ep); ++ dwc_usb3_pcd_req_t *pcd_req = dwc_usb3_get_pcd_req(usb_req); ++ int retval = 0, req_flags = 0; ++ ++ dwc_debug2(usb3_dev, "%s(%lx)\n", __func__, (unsigned long)usb_ep); ++ ++ usb_req->status = -DWC_E_IN_PROGRESS; ++ usb_req->actual = 0; ++ ++ if (usb_req->zero) ++ req_flags |= DWC_PCD_REQ_ZERO; ++ ++ pcd_req->dwc_req.buf[0] = usb_req->buf; ++ pcd_req->dwc_req.bufdma[0] = usb_req->dma; ++ pcd_req->dwc_req.buflen[0] = usb_req->length; ++ pcd_req->dwc_req.numbuf = 1; ++ pcd_req->dwc_req.length = usb_req->length; ++ pcd_req->dwc_req.actual = 0; ++ pcd_req->dwc_req.stream = usb_req->stream_id; ++ pcd_req->dwc_req.flags = req_flags; ++ ++ DWC_CIRCLEQ_INIT_ENTRY(pcd_req, entry); ++#if 1 ++ if (!DWC_CIRCLEQ_EMPTY(&pcd_ep->dwc_ep.queue)) { ++ /* If queue is not empty, and this is not an Isoc transfer, then ++ * don't submit the transfer. But we still queue the request so ++ * it can be submitted later. ++ */ ++ dwc_debug4(usb3_dev, "q !empty, pend %d, stop %d, avail %d, start %d\n", ++ pcd->request_pending, pcd_ep->dwc_ep.stopped, ++ pcd_ep->dwc_ep.desc_avail, pcd_ep->dwc_ep.xfer_started); ++ ++ if (!pcd_ep->dwc_ep.stopped && pcd_ep->dwc_ep.type == UE_ISOCHRONOUS && ++ pcd_ep->dwc_ep.desc_avail > 0 && pcd_ep->dwc_ep.xfer_started) ++ goto do_start; ++ } else ++#endif ++ if (pcd_ep->dwc_ep.stopped || (pcd_ep != pcd->ep0 && pcd_ep->dwc_ep.desc_avail <= 0) || ++ (pcd_ep->dwc_ep.type == UE_ISOCHRONOUS && !pcd_ep->dwc_ep.xfer_started)) { ++ /* If EP is stopped, or there is no TRB available, or this ++ * is an Isoc transfer and the EP is not started, then don't ++ * submit the transfer. But we still queue the request so it ++ * can be submitted later. ++ */ ++ dwc_debug4(usb3_dev, ++ " q empty, pend %d, stop %d, avail %d, start %d\n", ++// " pend %d, stop %d, avail %d, start %d\n", ++ pcd->request_pending, pcd_ep->dwc_ep.stopped, ++ pcd_ep->dwc_ep.desc_avail, pcd_ep->dwc_ep.xfer_started); ++ } else { ++do_start: ++ /* Call the PCD API routine to set up the request TRBs */ ++ dwc_usb3_pcd_fill_trbs(pcd, pcd_ep, pcd_req); ++ ++ /* Call the PCD API routine to submit the transfer request */ ++ retval = dwc_usb3_pcd_ep_submit_req(pcd, pcd_ep, pcd_req, req_flags); ++ } ++ ++ if (!retval) { ++ DWC_CIRCLEQ_INSERT_TAIL(&pcd_ep->dwc_ep.queue, pcd_req, entry); ++ ++pcd->request_pending; ++ } ++ ++ /* dwc_usb3_pcd_ep_submit_req() can return positive values for ++ * Control transfers, don't propagate those from this function ++ */ ++ return retval < 0 ? retval : 0; ++} ++ ++/** ++ * This routine cancels a transfer request for a USB endpoint. This is only ++ * needed in exceptional cases, a normal transfer completion does not require ++ * this. ++ * ++ * @param usb3_dev Programming view of DWC_usb3 device. ++ * @param usb_ep USB EP for the transfer. ++ * @param usb_req USB request for the transfer. ++ * @return 0 for success, else negative error code. ++ */ ++int dwc_usb3_ep_dequeue(struct dwc_usb3_device *usb3_dev, usb_ep_t *usb_ep, usb_request_t *usb_req) ++{ ++ dwc_usb3_pcd_t *pcd = &usb3_dev->pcd; ++ dwc_usb3_pcd_ep_t *pcd_ep = dwc_usb3_get_pcd_ep(usb_ep); ++ dwc_usb3_pcd_req_t *pcd_req; ++ ++ dwc_debug2(usb3_dev, "%s(%lx)\n", __func__, (unsigned long)usb_ep); ++ ++ if (dwc_usb3_pcd_ep_num(pcd_ep) != 0 && !pcd_ep->dwc_ep.usb_ep_desc) { ++ dwc_warn1(usb3_dev, "%s, bad pcd_ep\n", __func__); ++ return -DWC_E_INVALID; ++ } ++ ++ /* Make sure it's actually queued on this EP */ ++ DWC_CIRCLEQ_FOREACH(pcd_req, &pcd_ep->dwc_ep.queue, entry) { ++ if (&pcd_req->usb_req == usb_req) ++ break; ++ } ++ ++ if (!pcd_req) { ++ dwc_warn1(usb3_dev, "%s, no request in queue\n", __func__); ++ return 0; ++ } ++ ++ /* Call the PCD API routine to cancel the transfer request */ ++ dwc_usb3_pcd_ep_cancel_req(pcd, pcd_ep, pcd_req, usb_req->stream_id); ++ ++ return 0; ++} ++ ++/** ++ * Function Driver initialization routine ++ * ++ * @param usb3_dev Programming view of DWC_usb3 device. ++ * @return 0 for success, else negative error code. ++ */ ++int dwc_usb3_gadget_init(dwc_usb3_device_t *usb3_dev) ++{ ++ dwc_usb3_pcd_t *pcd = &usb3_dev->pcd; ++ dwc_usb3_pcd_ep_t *ep; ++ int i; ++ ++ dwc_debug1(usb3_dev, "%s()\n", __func__); ++ ++ ep = pcd->ep0; ++ ep->dwc_ep.num = 0; ++ DWC_CIRCLEQ_INIT(&ep->dwc_ep.queue); ++ ++ for (i = 0; i < pcd->num_out_eps; i++) { ++ ep = pcd->out_ep[i]; ++ ep->dwc_ep.num = i + 1; ++ DWC_CIRCLEQ_INIT(&ep->dwc_ep.queue); ++ } ++ ++ for (i = 0; i < pcd->num_in_eps; i++) { ++ ep = pcd->in_ep[i]; ++ ep->dwc_ep.num = i + 1; ++ DWC_CIRCLEQ_INIT(&ep->dwc_ep.queue); ++ } ++ ++ return 0; ++} ++ ++/** ++ * Function Driver removal routine ++ * ++ * @param usb3_dev Programming view of DWC_usb3 device. ++ */ ++void dwc_usb3_gadget_remove(dwc_usb3_device_t *usb3_dev) ++{ ++ dwc_debug1(usb3_dev, "%s()\n", __func__); ++} +diff --git a/drivers/usb/gadget/udc/hiudc3/no_os/no_os_hiber.c b/drivers/usb/gadget/udc/hiudc3/no_os/no_os_hiber.c +new file mode 100644 +index 0000000..995eb40a +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/no_os/no_os_hiber.c +@@ -0,0 +1,136 @@ ++/** @file ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++ ++/** ++ * Helper routine for dwc_wait_pme_thread() ++ */ ++static void dwc_wait_for_link_up(dwc_usb3_pcd_t *pcd) ++{ ++ unsigned long flags; ++ u32 temp; ++ int count = 5; ++ ++ while (count-- > 0) { ++ dwc_msleep(pcd->usb3_dev, 20); ++ dwc_acquire_spinlock_irq(pcd->usb3_dev, &pcd->lock, flags); ++ temp = dwc_usb3_pcd_get_link_state(pcd); ++ if (temp == 0) { ++ dwc_info0(pcd->usb3_dev, "Exiting from hibernation 2\n"); ++ pcd->usb3_dev->hiber_wait_connect = 0; ++ ++ /* Perform the steps in Section 9.1.3 "Initialization on ++ * Connect Done" in [DWSS]. ++ */ ++ dwc_usb3_handle_connect_done_intr(pcd); ++ dwc_exit_hibernation_after_connect(pcd, 0); ++ count = 0; ++ } ++ ++ dwc_release_spinlock_irq(pcd->usb3_dev, &pcd->lock, flags); ++ } ++} ++ ++/** ++ * Routine that monitors the dev->hibernate variable and the 'debug' ++ * register in the FPGA. dev->hibernate is set to 1 or 2 from the interrupt ++ * handler when the core is requesting to enter hibernation. This routine ++ * checks whether it is safe to do so (dev->hiber_cnt == 0) and then sets ++ * dev->hibernate to 3 and puts the core into hibernation. dev->hibernate >= 3 ++ * tells the rest of the driver that it cannot access the hardware. ++ * ++ * When the core is in hibernation, this routine should be called periodically ++ * to read the 'debug' register to see if the core is requesting to exit ++ * hibernation. If so, it brings the core out of hibernation. ++ * ++ * Note that this is NOT the way a "real" device would enter and exit ++ * hibernation. This code is ONLY for testing hibernation on the Synopsys ++ * HAPS platform. ++ */ ++int dwc_usb3_wait_pme(dwc_usb3_device_t *dev) ++{ ++ dwc_usb3_pcd_t *pcd = &dev->pcd; ++ unsigned long flags; ++ u32 temp; ++ int state, i; ++ ++ dwc_acquire_spinlock_irq(dev, &pcd->lock, flags); ++ temp = dev->hibernate; ++ ++ if (dev->hiber_cnt == 0) { ++ if (temp == DWC_HIBER_ENTER_NOSAVE || temp == DWC_HIBER_ENTER_SAVE) { ++ dwc_enter_hibernation(pcd, temp == DWC_HIBER_ENTER_SAVE); ++ temp = DWC_HIBER_SLEEPING; ++ } ++ } ++ ++ if (temp == DWC_HIBER_WAIT_LINK_UP) { ++ dev->hibernate = DWC_HIBER_AWAKE; ++ temp = DWC_HIBER_AWAKE; ++ dwc_release_spinlock_irq(dev, &pcd->lock, flags); ++ dwc_wait_for_link_up(pcd); ++ dwc_acquire_spinlock_irq(dev, &pcd->lock, flags); ++ } ++ ++ if (temp == DWC_HIBER_WAIT_U0) { ++ state = dwc_usb3_pcd_get_link_state(pcd); ++ if (state == 0) { ++ dev->hibernate = DWC_HIBER_AWAKE; ++ temp = DWC_HIBER_AWAKE; ++ } ++ } ++ ++ if (temp == DWC_HIBER_SS_DIS_QUIRK) { ++ for (i = 0; i < 500; i++) { ++ temp = dev->hibernate; ++ if (temp != DWC_HIBER_SS_DIS_QUIRK) { ++ dwc_debug1(dev, "breaking loop after %d ms\n", i); ++ break; ++ } ++ ++ dwc_release_spinlock_irq(dev, &pcd->lock, flags); ++ dwc_msleep(dev, 1); ++ dwc_acquire_spinlock_irq(dev, &pcd->lock, flags); ++ } ++ ++ if (temp == DWC_HIBER_SS_DIS_QUIRK) { ++ if (dwc_usb3_pcd_get_link_state(pcd) == DWC_LINK_STATE_SS_DIS) { ++ dwc_enter_hibernation(pcd, 0); ++ temp = DWC_HIBER_SLEEPING; ++ } else { ++ dev->hibernate = DWC_HIBER_AWAKE; ++ temp = DWC_HIBER_AWAKE; ++ } ++ } ++ } ++ ++ dwc_release_spinlock_irq(dev, &pcd->lock, flags); ++ dwc_msleep(dev, 1); ++ ++ return temp; ++} ++ ++int dwc_usb3_handle_pme_intr(dwc_usb3_device_t *dev) ++{ ++ int ret; ++ ++ dwc_debug1(dev, "%s()\n", __func__); ++ ++ dwc_debug0(dev, "calling dwc_exit_hibernation()\n"); ++ ret = dwc_exit_hibernation(&dev->pcd, 1); ++ if (ret) ++ dwc_info1(dev, "dwc_exit_hibernation() returned %d\n", ret); ++ ++ return 1; ++} ++ ++void dwc_usb3_power_ctl(dwc_usb3_device_t *dev, int on) ++{ ++} +diff --git a/drivers/usb/gadget/udc/hiudc3/no_os/no_os_init.c b/drivers/usb/gadget/udc/hiudc3/no_os/no_os_init.c +new file mode 100644 +index 0000000..939b323 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/no_os/no_os_init.c +@@ -0,0 +1,674 @@ ++/** @file ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++ ++#ifdef LINUXTEST ++#define DWC_DRIVER_VERSION "2.90b - November 2014" ++#define DWC_DRIVER_DESC "SS USB3 Controller driver" ++ ++static const char dwc_driver_name[] = "dwc_usb3"; ++#endif ++ ++/** ++ * The simulation environment doesn't have a malloc() function, so all data ++ * structures are statically allocated ++ */ ++ ++/** Driver context struct */ ++dwc_usb3_device_t g_usb3_dev; ++ ++/** @{ */ ++/** Endpoint context structs */ ++static dwc_usb3_pcd_ep_t g_ep0; ++static dwc_usb3_pcd_ep_t g_out_ep[DWC_MAX_EPS - 1]; ++static dwc_usb3_pcd_ep_t g_in_ep[DWC_MAX_EPS - 1]; ++/** @} */ ++ ++/** EP0 PCD request */ ++static dwc_usb3_pcd_req_t g_ep0_req; ++ ++/** @{ */ ++/** PCD request pool */ ++dwc_usb3_pcd_req_t g_pcd_req[32]; ++u32 g_pcd_req_bm; ++/** @} */ ++ ++/** Driver options struct, default values are defined here */ ++dwc_usb3_core_params_t usb3ss_module_params = { ++ .burst = 1, ++ .newcore = 0, ++ .phy = 2, ++ .wakeup = 0, ++ .pwrctl = 3, ++ .lpmctl = 1, ++ .phyctl = 1, ++ .usb2mode = 0, ++ .hibernate = 0, ++ .hiberdisc = 1, ++ .clkgatingen = 0, ++ .ssdisquirk = 0, ++ .nobos = 0, ++ .loop = 0, ++ .nump = 16, ++ .newcsr = 0, ++ .rxfsz = 0, ++ .txfsz = { 0, }, ++ .txfsz_cnt = 0, ++}; ++ ++#ifndef LINUXTEST ++/*** The following data structures must be in coherent DMA capable memory. ++ *** All memory in the simulation environment is such, and physical address ++ *** == virtual address, so we can just allocate these statically. ++ ***/ ++ ++/** Event buffer */ ++static u32 g_event_buf[DWC_EVENT_BUF_SIZE]; ++ ++/** EP0 SETUP packet buffer */ ++static char g_ep0_setup_pkt[8]; ++ ++/** Data packet buffer used to return data for GET_STATUS and ++ * GET_DESCRIPTOR requests, up to 512 bytes in length ++ */ ++static u8 g_ep0_status_buf[DWC_STATUS_BUF_SIZE]; ++ ++/** DMA descriptor (TRB) for EP0 SETUP packets */ ++static UALIGNED16 dwc_usb3_dma_desc_t g_ep0_setup_desc; ++ ++/** DMA descriptor (TRB) for EP0 Data Out and Status Out phases */ ++static UALIGNED16 dwc_usb3_dma_desc_t g_ep0_out_desc; ++ ++/** DMA descriptor (TRB) for EP0 Data In and Status In phases */ ++static UALIGNED16 dwc_usb3_dma_desc_t g_ep0_in_desc; ++ ++/** @{ */ ++/** DMA descriptor (TRB) pools for non-EP0 EPs */ ++UALIGNED16 dwc_usb3_dma_desc_t g_out_trb_pool[DWC_MAX_EPS - 1][DWC_NUM_ISOC_TRBS + 1]; ++UALIGNED16 dwc_usb3_dma_desc_t g_in_trb_pool[DWC_MAX_EPS - 1][DWC_NUM_ISOC_TRBS + 1]; ++/** @} */ ++ ++/** @{ */ ++/** Scratchpad buffers for hibernation support */ ++static char g_hiber_scratchpad[15][64]; ++static struct dwc_hiber_scratchpad_array g_hiber_scratchpad_array; ++/** @} */ ++#endif ++ ++#ifdef LINUXTEST ++module_param_named(newcsr, usb3ss_module_params.newcsr, int, S_IRUGO|S_IWUSR); ++MODULE_PARM_DESC(newcsr, "'gasket' has new, smaller CSR space (0=no, 1=yes)"); ++#endif ++ ++/* ++ * Hook to override the default Phy configuration in dwc_usb3_pcd_device_init() ++ * with a HAPS-specific one ++ */ ++static void haps_phy_config_hook(struct dwc_usb3_device *dev, int soft_reset, ++ int restore) ++{ ++ dwc_usb3_core_global_regs_t __iomem *global_regs = ++ dev->core_global_regs; ++ u32 temp; ++ ++ switch (dev->core_params->phy) { ++ case 3: // 16-bit UTMI+ SNPS Phy ++ temp = dwc_rd32(dev, &global_regs->gusb2phycfg[0]); ++ temp &= ~DWC_USB2PHYCFG_USB_TRD_TIM_BITS; ++ temp |= DWC_USB2PHYCFG_16B_PHY_IF_BIT; ++ temp |= 5 << DWC_USB2PHYCFG_USB_TRD_TIM_SHIFT; ++ dwc_wr32(dev, &global_regs->gusb2phycfg[0], temp); ++ break; ++ case 2: // 8-bit UTMI+ / ULPI TI or SNPS Phy ++ case 1: // old 8-bit UTMI+ SNPS Phy ++ temp = dwc_rd32(dev, &global_regs->gusb2phycfg[0]); ++ temp &= ~DWC_USB2PHYCFG_USB_TRD_TIM_BITS; ++ temp &= ~DWC_USB2PHYCFG_16B_PHY_IF_BIT; ++ temp |= 9 << DWC_USB2PHYCFG_USB_TRD_TIM_SHIFT; ++ dwc_wr32(dev, &global_regs->gusb2phycfg[0], temp); ++ break; ++ default: // RocketIO Phy ++ if (dev->core_params->usb2mode == 0) { ++ /* Set rx-eq, differential swing */ ++ dwc_wr32(dev, (volatile u32 __iomem *) ++ (dev->base + dev->gasket_ofs + 8), 0x41); ++#ifdef LECROY ++ /* Rx-detect for LeCroy */ ++ dwc_wr32(dev, (volatile u32 __iomem *) ++ (dev->base + dev->gasket_ofs + 4), 0x200); ++#else ++ dwc_wr32(dev, (volatile u32 __iomem *) ++ (dev->base + dev->gasket_ofs + 4), 0); ++#endif ++ } ++ } ++} ++ ++#ifdef LINUXTEST ++static irqreturn_t dwc_usb3_common_irq(int irq, void *dev ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ++ , struct pt_regs *regs ++#endif ++ ) ++{ ++ dwc_usb3_device_t *usb3_dev = dev; ++ int retval; ++ ++ dwc_acquire_spinlock(usb3_dev, &usb3_dev->pcd.lock); ++ retval = dwc_usb3_irq(usb3_dev, irq); ++ dwc_release_spinlock(usb3_dev, &usb3_dev->pcd.lock); ++ ++ return IRQ_RETVAL(retval); ++} ++#else ++/** ++ * This routine is the top level interrupt handler for the Common ++ * (Core and Device) interrupts ++ */ ++void dwc_usb3_common_irq(int irq, void *dev) ++{ ++ dwc_usb3_device_t *usb3_dev = dev; ++ ++ dwc_acquire_spinlock(usb3_dev, &usb3_dev->pcd.lock); ++ dwc_usb3_irq(usb3_dev, irq); ++ dwc_release_spinlock(usb3_dev, &usb3_dev->pcd.lock); ++} ++#endif ++ ++/** ++ * This routine de-initializes the driver ++ */ ++#ifdef LINUXTEST ++static void dwc_usb3_driver_remove(struct pci_dev *dev) ++#else ++void dwc_usb3_driver_remove(void) ++#endif ++{ ++ dwc_usb3_device_t *usb3_dev = &g_usb3_dev; ++ u32 *event_buf; ++ dwc_dma_t event_buf_dma; ++ ++ dwc_debug0(usb3_dev, "usb3ss_driver_remove()\n"); ++ ++ if (usb3_dev->cmn_irq_installed) { ++ usb3_dev->cmn_irq_installed = 0; ++#ifdef LINUXTEST ++ free_irq(dev->irq, usb3_dev); ++#endif ++ } ++ ++ if (usb3_dev->pcd_initialized) { ++ usb3_dev->pcd_initialized = 0; ++ dwc_usb3_pcd_remove(usb3_dev); ++ } ++ ++ if (usb3_dev->gadget_initialized) { ++ usb3_dev->gadget_initialized = 0; ++ dwc_usb3_function_remove(usb3_dev); ++ dwc_usb3_gadget_remove(usb3_dev); ++ } ++ ++ if (usb3_dev->cmn_initialized) { ++ usb3_dev->cmn_initialized = 0; ++ dwc_usb3_pcd_common_remove(usb3_dev); ++ } ++ ++#ifdef LINUXTEST ++ if (usb3_dev->pcd.ep0_setup_pkt) ++ dma_free_coherent(&dev->dev, ++ sizeof(*usb3_dev->pcd.ep0_setup_pkt) * 5, ++ usb3_dev->pcd.ep0_setup_pkt, ++ usb3_dev->pcd.ep0_setup_pkt_dma); ++ ++ if (usb3_dev->pcd.ep0_status_buf) ++ dma_free_coherent(&dev->dev, ++ DWC_STATUS_BUF_SIZE, ++ usb3_dev->pcd.ep0_status_buf, ++ usb3_dev->pcd.ep0_status_buf_dma); ++ ++ if (usb3_dev->pcd.ep0_in_desc) ++ dma_free_coherent(&dev->dev, ++ sizeof(dwc_usb3_dma_desc_t), ++ usb3_dev->pcd.ep0_in_desc, ++ usb3_dev->pcd.ep0_in_desc_dma); ++ ++ if (usb3_dev->pcd.ep0_out_desc) ++ dma_free_coherent(&dev->dev, ++ sizeof(dwc_usb3_dma_desc_t), ++ usb3_dev->pcd.ep0_out_desc, ++ usb3_dev->pcd.ep0_out_desc_dma); ++ ++ if (usb3_dev->pcd.ep0_setup_desc) ++ dma_free_coherent(&dev->dev, ++ sizeof(dwc_usb3_dma_desc_t), ++ usb3_dev->pcd.ep0_setup_desc, ++ usb3_dev->pcd.ep0_setup_desc_dma); ++#endif ++ ++ event_buf = usb3_dev->event_buf[0]; ++ event_buf_dma = usb3_dev->event_buf_dma[0]; ++ if (event_buf) { ++ dwc_usb3_dis_flush_eventbuf_intr(usb3_dev, 0); ++ usb3_dev->event_buf[0] = NULL; ++#ifdef LINUXTEST ++ dma_free_coherent(&dev->dev, DWC_EVENT_BUF_SIZE * sizeof(u32), ++ event_buf, event_buf_dma); ++#endif ++ } ++ ++ if (usb3_dev->sysfs_initialized) ++ usb3_dev->sysfs_initialized = 0; ++ ++#ifdef LINUXTEST ++ /* ++ * Clear the drvdata pointer. ++ */ ++ pci_set_drvdata(dev, NULL); ++ ++ /* ++ * Return the memory. ++ */ ++ if (usb3_dev->base) ++ iounmap(usb3_dev->base); ++ if (usb3_dev->rsrc_start) ++ release_mem_region(usb3_dev->rsrc_start, usb3_dev->rsrc_len); ++ ++ //pci_disable_device(dev); ++#endif ++ ++ return; ++} ++ ++/** ++ * This routine initializes the driver ++ * ++ * This routine must be called in a context that allows dwc_msleep() ++ * to be used, because that function is called while waiting for the ++ * core to come out of reset. ++ */ ++#ifdef LINUXTEST ++static int dwc_usb3_driver_probe(struct pci_dev *dev, ++ const struct pci_device_id *id) ++#else ++dwc_usb3_device_t *dwc_usb3_driver_init(u32 base_addr_dwc) ++#endif ++{ ++ dwc_usb3_device_t *usb3_dev = &g_usb3_dev; ++ u32 addr_ofs = 0xc000; ++ int retval, i; ++ ++ dwc_debug0(usb3_dev, "usb3ss_driver_init()\n"); ++ ++ memset(usb3_dev, 0, sizeof(*usb3_dev)); ++ dwc_init_spinlock(usb3_dev, &usb3_dev->pcd.lock); ++ ++#ifdef LINUXTEST ++ dev_dbg(&dev->dev, "start=0x%08x\n", (unsigned)pci_resource_start(dev, 0)); ++ dev_dbg(&dev->dev, "len=0x%08x\n", (unsigned)pci_resource_len(dev, 0)); ++ ++ if (!id) { ++ dev_err(&dev->dev, "id parameter NULL!\n"); ++ return -EINVAL; ++ } ++ ++ if (pci_enable_device(dev) < 0) { ++ dev_err(&dev->dev, "pci_enable_device() failed!\n"); ++ return -ENODEV; ++ } ++ ++ dev->current_state = PCI_D0; ++ dev->dev.power.power_state = PMSG_ON; ++ ++ if (!dev->irq) { ++ dev_err(&dev->dev, "no IRQ for PCI device!\n"); ++ retval = -ENODEV; ++ goto fail; ++ } ++ ++ usb3_dev->dev = &dev->dev; ++ pci_set_drvdata(dev, usb3_dev); ++ ++ dev_dbg(&dev->dev, "dwc_usb3_device=%lx\n", (unsigned long)usb3_dev); ++ ++ usb3_dev->rsrc_start = pci_resource_start(dev, 0); ++ usb3_dev->rsrc_len = pci_resource_len(dev, 0); ++ ++ if (!usb3_dev->rsrc_start || !usb3_dev->rsrc_len) { ++ dev_err(&dev->dev, "bad PCI resource!\n"); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ /* ++ * Map the DWC_usb3 Core memory into virtual address space. ++ */ ++ if (!request_mem_region(usb3_dev->rsrc_start, ++ usb3_dev->rsrc_len, "usb3")) { ++ dev_err(&dev->dev, "request_mem_region() failed!\n"); ++ ++ /* Flag for dwc_usb3_driver_remove() that we failed */ ++ usb3_dev->rsrc_start = 0; ++ ++ retval = -EBUSY; ++ goto fail; ++ } ++ ++ usb3_dev->base = ioremap_nocache(usb3_dev->rsrc_start, ++ usb3_dev->rsrc_len); ++ if (!usb3_dev->base) { ++ dev_err(&dev->dev, "ioremap_nocache() failed!\n"); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ if (usb3ss_module_params.newcsr) ++ usb3_dev->gasket_ofs = 0xf000; ++ else ++ usb3_dev->gasket_ofs = 0x80000; ++ ++ dev_dbg(&dev->dev, "base=%lx\n", (unsigned long)usb3_dev->base); ++ ++ usb3_dev->sysfs_initialized = 1; ++#else ++ usb3_dev->base = (volatile u8 __iomem *)(long)base_addr_dwc; ++#endif ++ ++ /* ++ * Checks that this device is really a DWC_usb3 controller. Also saves ++ * the SNPSID register value in usb3_dev->snpsid for later use by the ++ * PCD. ++ */ ++ retval = dwc_usb3_pcd_check_snpsid(usb3_dev, addr_ofs); ++ if (retval) { ++ dwc_error0(&dev->dev, "bad value for SNPSID!\n"); ++ goto fail; ++ } ++ ++ if (usb3ss_module_params.newcore && usb3_dev->snpsid < 0x5533109a) ++ usb3_dev->snpsid = 0x5533109a; ++ ++#ifdef LINUXTEST ++ retval = -ENOMEM; ++ ++ /* ++ * Up to 32 Event Buffers are supported by the hardware, but we only ++ * use 1 ++ */ ++ usb3_dev->event_buf[0] = dma_alloc_coherent(&dev->dev, ++ DWC_EVENT_BUF_SIZE * sizeof(u32), ++ &usb3_dev->event_buf_dma[0], ++ GFP_KERNEL | GFP_DMA32); ++ if (!usb3_dev->event_buf[0]) { ++ dev_err(&dev->dev, "allocation of event_buf failed!\n"); ++ goto fail; ++ } ++ ++ /* ++ * Allocate all the data structures that must be in DMA memory ++ */ ++ usb3_dev->pcd.ep0_setup_desc = dma_alloc_coherent( ++ &dev->dev, sizeof(dwc_usb3_dma_desc_t), ++ &usb3_dev->pcd.ep0_setup_desc_dma, ++ GFP_KERNEL | GFP_DMA32); ++ if (!usb3_dev->pcd.ep0_setup_desc) ++ goto fail; ++ ++ usb3_dev->pcd.ep0_out_desc = dma_alloc_coherent( ++ &dev->dev, sizeof(dwc_usb3_dma_desc_t), ++ &usb3_dev->pcd.ep0_out_desc_dma, ++ GFP_KERNEL | GFP_DMA32); ++ if (!usb3_dev->pcd.ep0_out_desc) ++ goto fail; ++ ++ usb3_dev->pcd.ep0_in_desc = dma_alloc_coherent( ++ &dev->dev, sizeof(dwc_usb3_dma_desc_t), ++ &usb3_dev->pcd.ep0_in_desc_dma, ++ GFP_KERNEL | GFP_DMA32); ++ if (!usb3_dev->pcd.ep0_in_desc) ++ goto fail; ++ ++ usb3_dev->pcd.ep0_status_buf = dma_alloc_coherent( ++ &dev->dev, DWC_STATUS_BUF_SIZE, ++ &usb3_dev->pcd.ep0_status_buf_dma, ++ GFP_KERNEL | GFP_DMA32); ++ if (!usb3_dev->pcd.ep0_status_buf) ++ goto fail; ++ ++ usb3_dev->pcd.ep0_setup_pkt = dma_alloc_coherent( ++ &dev->dev, sizeof(*usb3_dev->pcd.ep0_setup_pkt) * 5, ++ &usb3_dev->pcd.ep0_setup_pkt_dma, ++ GFP_KERNEL | GFP_DMA32); ++ if (!usb3_dev->pcd.ep0_setup_pkt) ++ goto fail; ++#else ++ /* ++ * Up to 32 Event Buffers are supported by the hardware, but we only ++ * use 1 ++ */ ++ usb3_dev->event_buf[0] = g_event_buf; ++ usb3_dev->event_buf_dma[0] = (dwc_dma_t)g_event_buf; ++ ++ /* ++ * "allocate" all the data structures that must be in DMA memory ++ */ ++ usb3_dev->pcd.ep0_setup_desc = &g_ep0_setup_desc; ++ usb3_dev->pcd.ep0_setup_desc_dma = (dwc_dma_t)&g_ep0_setup_desc; ++ usb3_dev->pcd.ep0_out_desc = &g_ep0_out_desc; ++ usb3_dev->pcd.ep0_out_desc_dma = (dwc_dma_t)&g_ep0_out_desc; ++ usb3_dev->pcd.ep0_in_desc = &g_ep0_in_desc; ++ usb3_dev->pcd.ep0_in_desc_dma = (dwc_dma_t)&g_ep0_in_desc; ++ usb3_dev->pcd.ep0_status_buf = g_ep0_status_buf; ++ usb3_dev->pcd.ep0_status_buf_dma = (dwc_dma_t)g_ep0_status_buf; ++ usb3_dev->pcd.ep0_setup_pkt = (union dwc_setup_pkt *)g_ep0_setup_pkt; ++ usb3_dev->pcd.ep0_setup_pkt_dma = (dwc_dma_t)g_ep0_setup_pkt; ++ ++ for (i = 0; i < 15; i++) { ++ g_hiber_scratchpad_array.dma_addr[i] = (u64)(long)&g_hiber_scratchpad[i]; ++ usb3_dev->pcd.hiber_scratchpad[i] = &g_hiber_scratchpad[i]; ++ } ++ ++ usb3_dev->pcd.hiber_scratchpad_array = &g_hiber_scratchpad_array; ++ usb3_dev->pcd.hiber_scratchpad_array_dma = (dwc_dma_t)&g_hiber_scratchpad_array; ++#endif ++ ++ /* ++ * Now "allocate" the remaining data structures ++ */ ++ usb3_dev->pcd.ep0_req = &g_ep0_req; ++ usb3_dev->pcd.ep0 = &g_ep0; ++ for (i = 0; i < DWC_MAX_EPS - 1; i++) { ++ usb3_dev->pcd.out_ep[i] = &g_out_ep[i]; ++ usb3_dev->pcd.in_ep[i] = &g_in_ep[i]; ++ } ++ ++ g_pcd_req_bm = 0xffffffff; ++ ++ /* ++ * Add our hook to override the default Phy register setup ++ */ ++ usb3_dev->phy_config_hook = haps_phy_config_hook; ++ ++ /* ++ * Initialize the DWC_usb3 core ++ */ ++ retval = dwc_usb3_pcd_common_init(usb3_dev, usb3_dev->base + addr_ofs, ++ &usb3ss_module_params); ++ if (retval) { ++ dwc_error0(usb3_dev, "CIL initialization failed!\n"); ++ goto fail; ++ } ++ ++ usb3_dev->cmn_initialized = 1; ++ ++ /* ++ * Initialize the Function Driver interface ++ */ ++ retval = dwc_usb3_gadget_init(usb3_dev); ++ if (retval) { ++ dwc_error0(usb3_dev, "gadget initialization failed!\n"); ++ goto fail; ++ } ++ ++ /* ++ * Initialize the Function Driver ++ */ ++ retval = dwc_usb3_function_init(usb3_dev); ++ if (retval) { ++ dwc_error0(usb3_dev, "loopback gadget initialization failed!\n"); ++ dwc_usb3_gadget_remove(usb3_dev); ++ goto fail; ++ } ++ ++ usb3_dev->gadget_initialized = 1; ++ ++ /* ++ * Initialize the PCD ++ */ ++ retval = dwc_usb3_pcd_init(usb3_dev); ++ if (retval) { ++ dwc_error0(usb3_dev, "PCD initialization failed!\n"); ++ goto fail; ++ } ++ ++ usb3_dev->pcd_initialized = 1; ++ ++#ifdef LINUXTEST ++ /* ++ * Install the interrupt handler for the common interrupts. ++ */ ++ dev_dbg(&dev->dev, "registering (common) handler for irq%d\n", ++ dev->irq); ++ retval = request_irq(dev->irq, dwc_usb3_common_irq, ++ IRQF_SHARED | IRQF_DISABLED, ++ dwc_driver_name, usb3_dev); ++ if (retval) { ++ dev_err(&dev->dev, "request of irq%d failed!\n", dev->irq); ++ retval = -EBUSY; ++ goto fail; ++ } ++#else ++# if 0 // Interrupt handler is hooked up before this routine is called ++ // Register interrupt service routine for DWC interrupt ++ interrupt_priority_set(USB3SS_DWC_INT, 5); ++ interrupt_target_set(USB3SS_DWC_INT, CPU0, 1); ++ intRegister(USB3SS_DWC_INT, usb3ss_common_irq, usb3_dev); ++ interrupt_enable(USB3SS_DWC_INT, 1); ++# endif ++#endif ++ usb3_dev->cmn_irq_installed = 1; ++ ++#ifdef LINUXTEST ++ return 0; ++#else ++ return usb3_dev; ++#endif ++ ++fail: ++#ifdef LINUXTEST ++ dwc_usb3_driver_remove(dev); ++ ++ return retval; ++#else ++ dwc_usb3_driver_remove(); ++ ++ return NULL; ++#endif ++} ++ ++#ifdef LINUXTEST ++ ++#define PCI_VENDOR_ID_SYNOPSYS 0x16c3 ++#define PCI_DEVICE_ID_SYNOPSYS_SITKA 0xabcd ++ ++static const struct pci_device_id pci_ids[] = { ++ { ++ /* The Synopsys PCIe card */ ++ PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, ++ PCI_DEVICE_ID_SYNOPSYS_SITKA), ++ .driver_data = (unsigned long)0xdeadbeef, ++ }, ++ { 0, } /* end: all zeroes */ ++}; ++MODULE_DEVICE_TABLE(pci, pci_ids); ++ ++/** ++ * This structure defines the methods to be called by a bus driver ++ * during the lifecycle of a device on that bus. Both drivers and ++ * devices are registered with a bus driver. The bus driver matches ++ * devices to drivers based on information in the device and driver ++ * structures. ++ * ++ * The probe routine is called when the bus driver matches a device ++ * to this driver. The remove routine is called when a device is ++ * unregistered with the bus driver. ++ */ ++static struct pci_driver dwc_usb3_driver = { ++ .name = (char *)dwc_driver_name, ++ .id_table = pci_ids, ++ .probe = dwc_usb3_driver_probe, ++ .remove = dwc_usb3_driver_remove, ++ .driver = { ++ .name = (char *)dwc_driver_name, ++ }, ++}; ++ ++/** ++ * This routine is called when the DWC_usb3 driver is loaded into the kernel ++ * with the insmod command. It registers the dwc_usb3_driver structure with the ++ * appropriate bus driver. This will cause the dwc_usb3_driver_probe routine ++ * to be called. In addition, the bus driver will automatically expose ++ * attributes defined for the device and driver in the special sysfs file ++ * system. ++ */ ++static int __init dwc_usb3_driver_init(void) ++{ ++ int retval = 0; ++ ++ printk(KERN_INFO "%s: %s version %s\n", dwc_driver_name, ++ DWC_DRIVER_DESC, DWC_DRIVER_VERSION); ++ retval = pci_register_driver(&dwc_usb3_driver); ++ ++ if (retval < 0) { ++ printk(KERN_ERR "%s retval=%d\n", __func__, retval); ++ return retval; ++ } ++ ++ printk(KERN_INFO "%s: module installed\n", dwc_driver_name); ++ return retval; ++} ++module_init(dwc_usb3_driver_init); ++ ++/** ++ * This routine is called when the DWC_usb3 driver is removed from the kernel ++ * with the rmmod command. The driver unregisters itself with its bus driver. ++ * ++ */ ++static void __exit dwc_usb3_driver_exit(void) ++{ ++ printk(KERN_DEBUG "%s: driver_exit()\n", dwc_driver_name); ++ ++ pci_unregister_driver(&dwc_usb3_driver); ++ ++ printk(KERN_INFO "%s: module removed\n", dwc_driver_name); ++} ++module_exit(dwc_usb3_driver_exit); ++ ++MODULE_DESCRIPTION(DWC_DRIVER_DESC); ++MODULE_AUTHOR("Synopsys Inc."); ++MODULE_LICENSE("GPL"); ++ ++#else /* !LINUXTEST */ ++ ++int main(int argc, char *argv[]) ++{ ++ return 0; ++} ++ ++#endif +diff --git a/drivers/usb/gadget/udc/hiudc3/no_os/no_os_src_sink_lpbk.c b/drivers/usb/gadget/udc/hiudc3/no_os/no_os_src_sink_lpbk.c +new file mode 100644 +index 0000000..66f3efa +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/no_os/no_os_src_sink_lpbk.c +@@ -0,0 +1,485 @@ ++/** @file ++ * ++ * Loopback/source-sink Function Driver which uses the application-specific ++ * interface in no_os_gadget.c ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++ ++#define DWC_BUF_SIZ (1024 * 1024) ++ ++/** Driver context struct - defined in no_os_init.c */ ++extern dwc_usb3_device_t g_usb3_dev; ++ ++#ifndef LINUXTEST ++/** @{ */ ++/** Transfer buffers - 1MB each */ ++static char g_in_buf[DWC_BUF_SIZ]; ++static char g_out_buf[DWC_BUF_SIZ]; ++/** @} */ ++#endif ++ ++/** ++ * The FPGA configuration is limited to a maximum transfer size of 128K by ++ * default, so allocate 8 128K requests for each 1MB buffer. ++ * NOTE: DWC_NUM_REQ * DWC_REQ_SIZ must be <= DWC_BUF_SIZ ! ++ */ ++/** @{ */ ++#define DWC_NUM_REQ 8 ++#define DWC_REQ_SIZ (128 * 1024) ++/** @} */ ++ ++/** ++ * Function Driver context struct ++ */ ++typedef struct dwc_usb3_loopbk { ++ usb_ep_t *in_ep, *out_ep; ++ char *in_buf, *out_buf; ++ dwc_dma_t in_dma, out_dma; ++ int speed, maxp; ++ u8 cfg, ifc, next0, src_sink; ++} dwc_usb3_loopbk_t; ++ ++/** ++ * The Function Driver context ++ */ ++static dwc_usb3_loopbk_t loopbk; ++ ++/** ++ * Function Driver transfer complete callback routine ++ */ ++static void loopbk_complete(usb_ep_t *ep, usb_request_t *req) ++{ ++ int ret; ++ ++ dwc_debug1(&g_usb3_dev, "%s()\n", __func__); ++ ++ switch (req->status) { ++ case 0: ++ if (loopbk.src_sink) { ++ if (ep == loopbk.out_ep) { ++ dwc_debug0(&g_usb3_dev, "OUT req, requeuing\n"); ++ req->length = DWC_REQ_SIZ; ++ ret = dwc_usb3_ep_queue(&g_usb3_dev, loopbk.out_ep, req); ++ if (ret == 0) ++ return; ++ dwc_error0(&g_usb3_dev, "Failed to requeue OUT req\n"); ++ } else { ++ dwc_debug0(&g_usb3_dev, "IN req, requeuing\n"); ++ req->length = DWC_REQ_SIZ; ++ ret = dwc_usb3_ep_queue(&g_usb3_dev, loopbk.in_ep, req); ++ if (ret == 0) ++ return; ++ dwc_error0(&g_usb3_dev, "Failed to requeue IN req\n"); ++ } ++ } else { ++ if (ep == loopbk.out_ep) { ++ dwc_debug0(&g_usb3_dev, "OUT req, requeuing on IN\n"); ++ ++ /* Handle 0-length marker packet */ ++ if (req->actual && (req->actual & (loopbk.maxp - 1)) == 0) ++ loopbk.next0 = 1; ++ ++ /* Echo packet back to host on IN EP */ ++ req->length = req->actual; ++ ret = dwc_usb3_ep_queue(&g_usb3_dev, loopbk.in_ep, req); ++ if (ret == 0) ++ return; ++ loopbk.next0 = 0; ++ dwc_error0(&g_usb3_dev, "Failed to queue IN req, requeuing on OUT\n"); ++ } else { ++ dwc_debug0(&g_usb3_dev, "IN req, requeuing on OUT\n"); ++ } ++ ++ /* Handle 0-length marker packet */ ++ if (loopbk.next0) { ++ loopbk.next0 = 0; ++ req->length = 0; ++ ret = dwc_usb3_ep_queue(&g_usb3_dev, loopbk.in_ep, req); ++ if (ret == 0) ++ return; ++ dwc_error0(&g_usb3_dev, "Failed to queue IN 0-length req, requeuing on OUT\n"); ++ } ++ ++ /* Requeue for a future OUT EP transfer */ ++ req->length = DWC_REQ_SIZ; ++ ret = dwc_usb3_ep_queue(&g_usb3_dev, loopbk.out_ep, req); ++ if (ret == 0) ++ return; ++ dwc_error0(&g_usb3_dev, "Failed to queue OUT req\n"); ++ } ++ ++ dwc_usb3_free_request(&g_usb3_dev, ep, req); ++ break; ++ ++ default: ++ dwc_error0(&g_usb3_dev, "Bad completion status\n"); ++ ++ /* Requeue for a future OUT EP transfer */ ++ req->length = DWC_REQ_SIZ; ++ ret = dwc_usb3_ep_queue(&g_usb3_dev, loopbk.out_ep, req); ++ if (ret == 0) ++ return; ++ dwc_error0(&g_usb3_dev, "Failed to queue OUT req\n"); ++ /* FALL-THRU */ ++ ++ case -DWC_E_SHUTDOWN: ++ dwc_debug0(&g_usb3_dev, "Shutdown status\n"); ++ dwc_usb3_free_request(&g_usb3_dev, ep, req); ++ break; ++ } ++} ++ ++/** ++ * Function Driver EP enable routine ++ */ ++static int enable_eps(dwc_usb3_device_t *usb3_dev, dwc_usb3_loopbk_t *loopbk) ++{ ++ usb_ep_t *in_ep, *out_ep; ++ ++ switch (loopbk->speed) { ++ case USB_SPEED_SUPER: ++ in_ep = dwc_usb3_ep_enable(usb3_dev, &ss_config_desc.bulk_in_ep_desc, ++ &ss_config_desc.bulk_in_ss_ep_comp_desc); ++ if (!in_ep) ++ return -DWC_E_INVALID; ++ ++ out_ep = dwc_usb3_ep_enable(usb3_dev, &ss_config_desc.bulk_out_ep_desc, ++ &ss_config_desc.bulk_out_ss_ep_comp_desc); ++ if (!out_ep) { ++ dwc_usb3_ep_disable(usb3_dev, in_ep); ++ return -DWC_E_INVALID; ++ } ++ ++ break; ++ ++ case USB_SPEED_HIGH: ++ in_ep = dwc_usb3_ep_enable(usb3_dev, &hs_config_desc.bulk_in_ep_desc, NULL); ++ if (!in_ep) ++ return -DWC_E_INVALID; ++ ++ out_ep = dwc_usb3_ep_enable(usb3_dev, &hs_config_desc.bulk_out_ep_desc, NULL); ++ if (!out_ep) { ++ dwc_usb3_ep_disable(usb3_dev, in_ep); ++ return -DWC_E_INVALID; ++ } ++ ++ break; ++ ++ case USB_SPEED_FULL: ++ in_ep = dwc_usb3_ep_enable(usb3_dev, &fs_config_desc.bulk_in_ep_desc, NULL); ++ if (!in_ep) ++ return -DWC_E_INVALID; ++ ++ out_ep = dwc_usb3_ep_enable(usb3_dev, &fs_config_desc.bulk_out_ep_desc, NULL); ++ if (!out_ep) { ++ dwc_usb3_ep_disable(usb3_dev, in_ep); ++ return -DWC_E_INVALID; ++ } ++ ++ break; ++ ++ default: ++ return -DWC_E_INVALID; ++ } ++ ++ loopbk->in_ep = in_ep; ++ loopbk->out_ep = out_ep; ++ ++ return 0; ++} ++ ++/** ++ * Function Driver EP disable routine ++ */ ++static void disable_eps(dwc_usb3_device_t *usb3_dev, dwc_usb3_loopbk_t *loopbk) ++{ ++ if (loopbk->out_ep) { ++ dwc_usb3_ep_disable(usb3_dev, loopbk->out_ep); ++ loopbk->out_ep = NULL; ++ } ++ ++ if (loopbk->in_ep) { ++ dwc_usb3_ep_disable(usb3_dev, loopbk->in_ep); ++ loopbk->in_ep = NULL; ++ } ++} ++ ++/** ++ * Function Driver SET_INTERFACE routine ++ */ ++static int set_interface(dwc_usb3_device_t *usb3_dev, dwc_usb3_loopbk_t *loopbk, int alt) ++{ ++ usb_request_t *req; ++ int i, ret = 0; ++ ++ if (alt == -1) ++ goto cleanup; ++ ++ /* Already set? */ ++ if (loopbk->out_ep) ++ return 0; ++ ++ ret = enable_eps(usb3_dev, loopbk); ++ if (ret) ++ return ret; ++ ++ ret = -DWC_E_NO_MEMORY; ++ ++ if (loopbk->src_sink) { ++ for (i = 0; i < DWC_NUM_REQ; i++) { ++ req = dwc_usb3_alloc_request(usb3_dev, loopbk->in_ep); ++ if (!req) ++ goto cleanup; ++ req->buf = loopbk->in_buf + DWC_REQ_SIZ * i; ++ req->dma = loopbk->in_dma + DWC_REQ_SIZ * i; ++ req->length = DWC_REQ_SIZ; ++ req->complete = loopbk_complete; ++ ret = dwc_usb3_ep_queue(usb3_dev, loopbk->in_ep, req); ++ if (ret) ++ goto cleanup; ++ } ++ } ++ ++ for (i = 0; i < DWC_NUM_REQ; i++) { ++ req = dwc_usb3_alloc_request(usb3_dev, loopbk->out_ep); ++ if (!req) ++ goto cleanup; ++ req->buf = loopbk->out_buf + DWC_REQ_SIZ * i; ++ req->dma = loopbk->out_dma + DWC_REQ_SIZ * i; ++ req->length = DWC_REQ_SIZ; ++ req->complete = loopbk_complete; ++ ret = dwc_usb3_ep_queue(usb3_dev, loopbk->out_ep, req); ++ if (ret) ++ goto cleanup; ++ } ++ ++ return 0; ++ ++cleanup: ++ /* disable_eps() will eventually dequeue all requests queued on each EP, ++ * and call the ->complete routine with -DWC_E_SHUTDOWN status for each ++ * one. That in turn will free the request. So all cleanup is done for ++ * us by this one call. ++ */ ++ disable_eps(usb3_dev, loopbk); ++ loopbk->next0 = 0; ++ return ret; ++} ++ ++/** ++ * This routine handles Function Driver specific Setup requests. Generic ++ * requests are handled in ep0.c and no_os_ep0.c. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param ctrl Pointer to the Setup packet for the request. ++ * @return 0 for success, else negative error code. ++ */ ++int dwc_usb3_function_setup(dwc_usb3_pcd_t *pcd, usb_device_request_t *ctrl) ++{ ++ u16 windex = UGETW(ctrl->wIndex); ++ u16 wvalue = UGETW(ctrl->wValue); ++ u16 wlength = UGETW(ctrl->wLength); ++ int len = 0, ret = 0; ++ ++ switch (ctrl->bRequest) { ++ case UR_SET_FEATURE: ++ dwc_debug0(pcd->usb3_dev, "USB_REQ_SET_FEATURE\n"); ++ ++ /* We don't need to do anything for this */ ++ pcd->ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_WAIT_NRDY; ++ return 0; ++ ++ case UR_SET_INTERFACE: ++ dwc_debug0(pcd->usb3_dev, "USB_REQ_SET_INTERFACE\n"); ++ if (!loopbk.cfg || windex) { ++ dwc_error2(pcd->usb3_dev, "cfg=%x wIndex=%x\n", loopbk.cfg, windex); ++ return -DWC_E_NOT_SUPPORTED; ++ } ++ ++ dwc_debug1(pcd->usb3_dev, "ifc=%x\n", wvalue); ++ ++ /* If interface has changed, disable the old EPs and enable the new ones */ ++ if (loopbk.ifc != wvalue) { ++ set_interface(pcd->usb3_dev, &loopbk, -1); ++ ret = set_interface(pcd->usb3_dev, &loopbk, wvalue); ++ if (ret) ++ return ret; ++ } ++ ++ loopbk.ifc = wvalue; ++ pcd->ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_WAIT_NRDY; ++ return 0; ++ ++ case UR_GET_INTERFACE: ++ dwc_debug0(pcd->usb3_dev, "USB_REQ_GET_INTERFACE\n"); ++ if (!loopbk.cfg) { ++ dwc_error1(pcd->usb3_dev, "cfg=%x\n", loopbk.cfg); ++ return -DWC_E_NOT_SUPPORTED; ++ } ++ ++ if (windex) { ++ dwc_error1(pcd->usb3_dev, "wIndex=%x\n", windex); ++ return -DWC_E_DOMAIN; ++ } ++ ++ pcd->ep0_status_buf[0] = loopbk.ifc; ++ len = 1; ++ break; ++ ++ case UR_SET_CONFIG: ++ dwc_debug0(pcd->usb3_dev, "USB_REQ_SET_CONFIG\n"); ++ if (wvalue != 0 && wvalue != 1) { // we only have one configuration ++ dwc_error1(pcd->usb3_dev, "wValue=%x\n", wvalue); ++ return -DWC_E_NOT_SUPPORTED; ++ } ++ ++ /* If config already set, clear it and disable the EPs */ ++ if (loopbk.cfg) { ++ loopbk.cfg = 0; ++ loopbk.ifc = 0; ++ set_interface(pcd->usb3_dev, &loopbk, -1); ++ } ++ ++ /* If new config is 1, enable the EPs for interface 0 */ ++ if (wvalue) { ++ loopbk.cfg = wvalue; ++ loopbk.ifc = 0; ++ ret = set_interface(pcd->usb3_dev, &loopbk, 0); ++ if (ret) ++ loopbk.cfg = 0; ++ } ++ ++ dwc_debug1(pcd->usb3_dev, "cfg=%x\n", loopbk.cfg); ++ if (ret) ++ return ret; ++ pcd->ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_WAIT_NRDY; ++ return 0; ++ ++ case UR_GET_CONFIG: ++ dwc_debug0(pcd->usb3_dev, "USB_REQ_GET_CONFIG\n"); ++ pcd->ep0_status_buf[0] = loopbk.cfg; ++ len = 1; ++ break; ++ ++ case UR_SYNCH_FRAME: ++ dwc_debug0(pcd->usb3_dev, "USB_REQ_SYNCH_FRAME\n"); ++ ++ /* We don't need to do anything for this */ ++ pcd->ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_WAIT_NRDY; ++ return 0; ++ ++ default: ++ dwc_debug0(pcd->usb3_dev, "Unknown request!\n"); ++ return -DWC_E_NOT_SUPPORTED; ++ } ++ ++ /* Start the data phase for 3-stage transfers */ ++ pcd->ep0state = EP0_IN_DATA_PHASE; ++ dwc_usb3_pcd_ep0_data_stage(pcd, len < wlength ? len : wlength); ++ ++ return 0; ++} ++ ++/** ++ * Function Driver CONNECT routine ++ */ ++int dwc_usb3_function_connect(struct dwc_usb3_device *usb3_dev, int speed) ++{ ++ loopbk.speed = speed; ++ ++ switch (speed) { ++ case USB_SPEED_SUPER: ++ loopbk.maxp = 1024; ++ break; ++ ++ case USB_SPEED_HIGH: ++ loopbk.maxp = 512; ++ break; ++ ++ case USB_SPEED_FULL: ++ loopbk.maxp = 64; ++ break; ++ } ++ ++ return 0; ++} ++ ++/** ++ * Function Driver DISCONNECT routine ++ */ ++int dwc_usb3_function_disconnect(struct dwc_usb3_device *usb3_dev) ++{ ++ return 0; ++} ++ ++/** ++ * Function Driver initialization routine ++ * ++ * @param usb3_dev Programming view of DWC_usb3 device. ++ * @return 0 for success, else negative error code. ++ */ ++int dwc_usb3_function_init(dwc_usb3_device_t *usb3_dev) ++{ ++ dwc_debug1(usb3_dev, "%s()\n", __func__); ++ ++ loopbk.src_sink = 0; /* for now */ ++ ++#ifndef LINUXTEST ++ if (loopbk.src_sink) { ++ loopbk.in_buf = g_in_buf; ++ loopbk.in_dma = (dwc_dma_t)g_in_buf; ++ } ++ ++ loopbk.out_buf = g_out_buf; ++ loopbk.out_dma = (dwc_dma_t)g_out_buf; ++ ++ return 0; ++#else ++ if (loopbk.src_sink) { ++ loopbk.in_buf = dma_alloc_coherent(usb3_dev->dev, DWC_BUF_SIZ, ++ &loopbk.in_dma, GFP_KERNEL | GFP_DMA32); ++ if (!loopbk.in_buf) ++ goto out0; ++ } ++ ++ loopbk.out_buf = dma_alloc_coherent(usb3_dev->dev, DWC_BUF_SIZ, ++ &loopbk.out_dma, GFP_KERNEL | GFP_DMA32); ++ if (!loopbk.out_buf) ++ goto out1; ++ ++ return 0; ++ ++out1: ++ if (loopbk.src_sink) ++ dma_free_coherent(usb3_dev->dev, DWC_BUF_SIZ, loopbk.in_buf, loopbk.in_dma); ++out0: ++ return -DWC_E_NO_MEMORY; ++#endif ++} ++ ++/** ++ * Function Driver removal routine ++ * ++ * @param usb3_dev Programming view of DWC_usb3 device. ++ */ ++void dwc_usb3_function_remove(dwc_usb3_device_t *usb3_dev) ++{ ++ dwc_debug1(usb3_dev, "%s()\n", __func__); ++ ++#ifdef LINUXTEST ++ dma_free_coherent(usb3_dev->dev, DWC_BUF_SIZ, loopbk.out_buf, loopbk.out_dma); ++ if (loopbk.src_sink) ++ dma_free_coherent(usb3_dev->dev, DWC_BUF_SIZ, loopbk.in_buf, loopbk.in_dma); ++#endif ++} +diff --git a/drivers/usb/gadget/udc/hiudc3/os_defs.h b/drivers/usb/gadget/udc/hiudc3/os_defs.h +new file mode 100644 +index 0000000..b013072 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/os_defs.h +@@ -0,0 +1,162 @@ ++#ifndef _DWC_LINUX_DEFS_H_ ++#define _DWC_LINUX_DEFS_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * @file ++ * ++ * This file contains OS-specific includes and definitions. ++ * ++ */ ++ ++#define DWC_DRIVER_VERSION "2.90b - November 2014" ++#define DWC_DRIVER_DESC "SS USB3 Controller driver" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++# include ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) ++# include ++#else ++# include ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) ++# include ++# include ++#else ++# include ++# include ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++# include ++#endif ++ ++# include ++# include ++# include ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ++typedef int gfp_t; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ++# define IRQF_SHARED SA_SHIRQ ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) ++# define DWC_BOS_IN_GADGET ++#endif ++ ++/** @name Error Codes */ ++/** @{ */ ++#define DWC_E_INVALID EINVAL ++#define DWC_E_NO_MEMORY ENOMEM ++#define DWC_E_NO_DEVICE ENODEV ++#define DWC_E_NOT_SUPPORTED EOPNOTSUPP ++#define DWC_E_TIMEOUT ETIMEDOUT ++#define DWC_E_BUSY EBUSY ++#define DWC_E_AGAIN EAGAIN ++#define DWC_E_ABORT ECONNABORTED ++#define DWC_E_SHUTDOWN ESHUTDOWN ++#define DWC_E_NO_DATA ENODATA ++#define DWC_E_DISCONNECT ECONNRESET ++#define DWC_E_UNKNOWN EINVAL ++#define DWC_E_NO_STREAM_RES ENOSR ++#define DWC_E_COMMUNICATION ECOMM ++#define DWC_E_OVERFLOW EOVERFLOW ++#define DWC_E_PROTOCOL EPROTO ++#define DWC_E_IN_PROGRESS EINPROGRESS ++#define DWC_E_PIPE EPIPE ++#define DWC_E_IO EIO ++#define DWC_E_NO_SPACE ENOSPC ++#define DWC_E_DOMAIN EDOM ++/** @} */ ++ ++/** Compiler 'packed' attribute for structs */ ++#define UPACKED __attribute__ ((__packed__)) ++ ++/** @{ */ ++/** Type for DMA addresses */ ++typedef dma_addr_t dwc_dma_t; ++#define DWC_DMA_ADDR_INVALID (~(dwc_dma_t)0) ++/** @} */ ++ ++/** ++ * The number of DMA Descriptors (TRBs) to allocate for each endpoint type. ++ * NOTE: The driver currently supports more than 1 TRB for Isoc EPs only. ++ * So the values for Bulk and Intr must be 1. ++ */ ++#define DWC_NUM_BULK_TRBS 1 ++#define DWC_NUM_INTR_TRBS 1 ++#define DWC_NUM_ISOC_TRBS 256 ++ ++/** ++ * These parameters may be specified when loading the module. They define how ++ * the DWC_usb3 controller should be configured. The parameter values are passed ++ * to the CIL initialization routine dwc_usb3_pcd_common_init(). ++ */ ++typedef struct dwc_usb3_core_params { ++ int burst; ++ int newcore; ++ int phy; ++ int wakeup; ++ int pwrctl; ++ int lpmctl; ++ int phyctl; ++ int usb2mode; ++ int hibernate; ++ int hiberdisc; ++ int clkgatingen; ++ int ssdisquirk; ++ int nobos; ++ int loop; ++ int nump; ++ int newcsr; ++ int rxfsz; ++ int txfsz[16]; ++ int txfsz_cnt; ++ int baseline_besl; ++ int deep_besl; ++ int besl; ++ int ebc; ++} dwc_usb3_core_params_t; ++ ++extern dwc_usb3_core_params_t dwc_usb3_module_params; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_LINUX_DEFS_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc3/os_dev.h b/drivers/usb/gadget/udc/hiudc3/os_dev.h +new file mode 100644 +index 0000000..1c5cd83 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/os_dev.h +@@ -0,0 +1,176 @@ ++#ifndef _DWC_LINUX_DEV_H_ ++#define _DWC_LINUX_DEV_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#if defined(CONFIG_ARCH_HI3519) || defined(CONFIG_ARCH_HI3519V101) || defined(CONFIG_ARCH_HI3516AV200) ++#ifdef readl ++#undef readl ++#undef readl_relaxed ++#undef writel ++#undef writel_relaxed ++#define readl hi_readl ++#define readl_relaxed hi_readl_relaxed ++#define writel hi_writel ++#define writel_relaxed hi_writel_relaxed ++#endif /* readl */ ++#endif /* defined(CONFIG_ARCH_HI3519) || defined(CONFIG_ARCH_HI3519V101) || defined(CONFIG_ARCH_HI3516AV200)*/ ++ ++/** @file ++ */ ++ ++/** Wrapper function for _handshake(), shows the source line for any failure */ ++#define handshake(_dev_, _ptr_, _mask_, _done_) ({ \ ++ int _retval_ = _handshake(_dev_, _ptr_, _mask_, _done_); \ ++ if (!_retval_) \ ++ dwc_error2(_dev_, "handshake failed in %s():%d\n", \ ++ __func__, __LINE__); \ ++ _retval_; \ ++}) ++ ++/** Takes a usb req pointer and returns the associated pcd req pointer */ ++#define dwc_usb3_get_pcd_req(usbreq) \ ++ container_of((usbreq), dwc_usb3_pcd_req_t, usb_req) ++ ++/** Takes a usb ep pointer and returns the associated pcd ep pointer */ ++#define dwc_usb3_get_pcd_ep(usbep) \ ++ container_of((usbep), dwc_usb3_pcd_ep_t, usb_ep) ++ ++/** @{ */ ++/** ++ * Register read/write. ++ */ ++static inline u32 dwc_rd32(struct dwc_usb3_device *dev, ++ volatile u32 __iomem *adr) ++{ ++ return readl(adr); ++} ++ ++static inline void dwc_wr32(struct dwc_usb3_device *dev, ++ volatile u32 __iomem *adr, u32 val) ++{ ++ writel(val, adr); ++} ++/** @} */ ++ ++/** @{ */ ++/** ++ * Non-sleeping delays. ++ */ ++#define dwc_udelay(dev, us) udelay(us) ++#define dwc_mdelay(dev, ms) mdelay(ms) ++/** @} */ ++ ++/** ++ * Sleeping delay. ++ */ ++#define dwc_msleep(dev, ms) msleep(ms) ++ ++/** ++ * Debugging support - vanishes in non-debug builds. ++ */ ++ ++/** Prefix string for print macros. */ ++#define USB3_DWC "dwc_usb3: " ++/* #define DEBUG */ ++#ifdef DEBUG ++# define dwc_debug(dev, x...) printk(KERN_DEBUG USB3_DWC x ) ++#else ++# define dwc_debug(dev, x...) do {} while (0) ++#endif /* DEBUG */ ++ ++# define dwc_debug0(dev, fmt) dwc_debug(dev, fmt) ++# define dwc_debug1(dev, fmt, a) dwc_debug(dev, fmt, a) ++# define dwc_debug2(dev, fmt, a, b) dwc_debug(dev, fmt, a, b) ++# define dwc_debug3(dev, fmt, a, b, c) dwc_debug(dev, fmt, a, b, c) ++# define dwc_debug4(dev, fmt, a, b, c, d) dwc_debug(dev, fmt, a, b, c, d) ++# define dwc_debug5(dev, fmt, a, b, c, d, e) \ ++ dwc_debug(dev, fmt, a, b, c, d, e) ++# define dwc_debug6(dev, fmt, a, b, c, d, e, f) \ ++ dwc_debug(dev, fmt, a, b, c, d, e, f) ++# define dwc_debug7(dev, fmt, a, b, c, d, e, f, g) \ ++ dwc_debug(dev, fmt, a, b, c, d, e, f, g) ++# define dwc_debug8(dev, fmt, a, b, c, d, e, f, g, h) \ ++ dwc_debug(dev, fmt, a, b, c, d, e, f, g, h) ++# define dwc_debug9(dev, fmt, a, b, c, d, e, f, g, h, i) \ ++ dwc_debug(dev, fmt, a, b, c, d, e, f, g, h, i) ++# define dwc_debug10(dev, fmt, a, b, c, d, e, f, g, h, i, j) \ ++ dwc_debug(dev, fmt, a, b, c, d, e, f, g, h, i, j) ++ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++# define dwc_isocdbg(dev, x...) printk(USB3_DWC x ) ++#else ++# define dwc_isocdbg(dev, x...) do {} while (0) ++#endif ++ ++# define dwc_isocdbg0(dev, fmt) dwc_isocdbg(dev, fmt) ++# define dwc_isocdbg1(dev, fmt, a) dwc_isocdbg(dev, fmt, a) ++# define dwc_isocdbg2(dev, fmt, a, b) dwc_isocdbg(dev, fmt, a, b) ++# define dwc_isocdbg3(dev, fmt, a, b, c) dwc_isocdbg(dev, fmt, a, b, c) ++# define dwc_isocdbg4(dev, fmt, a, b, c, d) \ ++ dwc_isocdbg(dev, fmt, a, b, c, d) ++# define dwc_isocdbg5(dev, fmt, a, b, c, d, e) \ ++ dwc_isocdbg(dev, fmt, a, b, c, d, e) ++# define dwc_isocdbg6(dev, fmt, a, b, c, d, e, f) \ ++ dwc_isocdbg(dev, fmt, a, b, c, d, e, f) ++ ++/** ++ * Print an Error message. ++ */ ++#define dwc_error(dev, x...) printk(KERN_ERR USB3_DWC x ) ++ ++#define dwc_error0(dev, fmt) dwc_error(dev, fmt) ++#define dwc_error1(dev, fmt, a) dwc_error(dev, fmt, a) ++#define dwc_error2(dev, fmt, a, b) dwc_error(dev, fmt, a, b) ++#define dwc_error3(dev, fmt, a, b, c) dwc_error(dev, fmt, a, b, c) ++#define dwc_error4(dev, fmt, a, b, c, d) dwc_error(dev, fmt, a, b, c, d) ++ ++/** ++ * Print a Warning message. ++ */ ++#define dwc_warn(dev, x...) printk(KERN_WARNING USB3_DWC x ) ++ ++#define dwc_warn0(dev, fmt) dwc_warn(dev, fmt) ++#define dwc_warn1(dev, fmt, a) dwc_warn(dev, fmt, a) ++#define dwc_warn2(dev, fmt, a, b) dwc_warn(dev, fmt, a, b) ++#define dwc_warn3(dev, fmt, a, b, c) dwc_warn(dev, fmt, a, b, c) ++#define dwc_warn4(dev, fmt, a, b, c, d) dwc_warn(dev, fmt, a, b, c, d) ++ ++/** ++ * Print an Informational message (normal but significant). ++ */ ++#define dwc_info(dev, x...) printk(KERN_INFO USB3_DWC x ) ++ ++#define dwc_info0(dev, fmt) dwc_info(dev, fmt) ++#define dwc_info1(dev, fmt, a) dwc_info(dev, fmt, a) ++#define dwc_info2(dev, fmt, a, b) dwc_info(dev, fmt, a, b) ++#define dwc_info3(dev, fmt, a, b, c) dwc_info(dev, fmt, a, b, c) ++#define dwc_info4(dev, fmt, a, b, c, d) dwc_info(dev, fmt, a, b, c, d) ++ ++/** ++ * Basic message printing. ++ */ ++#define dwc_print(dev, x...) printk(USB3_DWC x ) ++ ++#define dwc_print0(dev, fmt) dwc_print(dev, fmt) ++#define dwc_print1(dev, fmt, a) dwc_print(dev, fmt, a) ++#define dwc_print2(dev, fmt, a, b) dwc_print(dev, fmt, a, b) ++#define dwc_print3(dev, fmt, a, b, c) dwc_print(dev, fmt, a, b, c) ++#define dwc_print4(dev, fmt, a, b, c, d) dwc_print(dev, fmt, a, b, c, d) ++#define dwc_print5(dev, fmt, a, b, c, d, e) \ ++ dwc_print(dev, fmt, a, b, c, d, e) ++ ++extern int dwc_usb3_gadget_init(struct dwc_usb3_device *usb3_dev, struct device *dev); ++extern void dwc_usb3_gadget_remove(struct dwc_usb3_device *usb3_dev, struct device *dev); ++extern int dwc_usb3_create_dev_files(struct device *dev); ++extern void dwc_usb3_remove_dev_files(struct device *dev); ++extern int dwc_usb3_wakeup(struct usb_gadget *gadget); ++extern int dwc_wait_pme_thread(void *data); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_LINUX_DEV_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc3/pcd.c b/drivers/usb/gadget/udc/hiudc3/pcd.c +new file mode 100644 +index 0000000..6bf93aa +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/pcd.c +@@ -0,0 +1,1992 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/DWC_usb3/driver/pcd.c $ ++ * $Revision: #110 $ ++ * $Date: 2014/11/11 $ ++ * $Change: 2664766 $ ++ * ++ * Synopsys SS USB3 Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++/** @file ++ * This file implements the Peripheral Controller Driver. ++ * ++ * The Peripheral Controller Driver (PCD) is responsible for translating ++ * requests from the Function Driver into the appropriate actions on the ++ * DWC_usb3 controller. It isolates the Function Driver from the specifics ++ * of the controller by providing an API to the Function Driver. ++ * ++ * The Peripheral Controller Driver for Linux will implement the Gadget API, ++ * so that the existing Gadget drivers can be used. (Gadget Driver is the ++ * Linux terminology for a Function Driver.) ++ * ++ * The Linux Gadget API is defined in the header file ++ * . The USB EP operations API is defined ++ * in the structure usb_ep_ops and the USB Controller API is ++ * defined in the structure usb_gadget_ops. ++ * ++ * An important function of the PCD is managing interrupts generated by the ++ * DWC_usb3 controller. The implementation of the DWC_usb3 device mode ++ * interrupt service routines is in pcd_intr.c. ++ */ ++/* ++ * todo Add Device Mode test modes (Test J mode, Test K mode, etc). ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++ ++#ifdef DWC_UTE ++# include "ute_if.h" ++#endif ++ ++/** ++ * This routine allocates the TRBs for an EP. ++ * ++ * @param ep The EP for the allocation. ++ * @param num_trbs Number of TRBs to allocate. ++ * @param trb_type Type of the TRB. ++ * @param iso_intvl bInterval if this is an Isoc EP. ++ * @param link True if the TRBs should be linked in a circular chain ++ * (only supported for Isoc EPs for now). ++ * @param trbs_dma_ret The DMA address of the allocation is returned through ++ * this pointer. ++ * @return The address of the allocated memory, or NULL if the ++ * allocation fails. ++ */ ++dwc_usb3_dma_desc_t *dwc_usb3_pcd_trb_alloc(dwc_usb3_pcd_ep_t *ep, int num_trbs, ++ int trb_type, int iso_intvl, int link, dwc_dma_t *trbs_dma_ret) ++{ ++ dwc_usb3_dma_desc_t *trbs, *cur_trb; ++ dwc_dma_t trbs_dma = 0; ++ int size, i; ++#ifdef DWC_TEST_ISOC_CHAIN ++ int j; ++#endif ++ ++#ifdef DWC_TEST_ISOC_CHAIN ++ size = num_trbs * 3 * 16; ++ if (link) ++ size += 16 * 3; ++#else ++ size = num_trbs * 16; ++ if (link) ++ size += 16; ++#endif ++ ++ trbs = cur_trb = dwc_usb3_gadget_alloc_dma(ep, size, &trbs_dma); ++ if (!trbs) ++ return NULL; ++ ++ /* Now initialize the TRBs */ ++ for (i = 0; i < num_trbs; i++, cur_trb++) { ++ if (trb_type == UE_ISOCHRONOUS) { ++#ifdef DWC_ISOC_INTR_MODERATION ++ /* ++ * For small intervals, only set the IOC bit in every ++ * 8th TRB, for interrupt moderation purposes ++ */ ++ if (iso_intvl > 3 || (i & 7) == 7 || i == num_trbs - 1) ++#endif ++ dwc_usb3_fill_desc(cur_trb, 0, 0, 0, ++ DWC_DSCCTL_TRBCTL_ISOC_1ST, ++ DWC_DSCCTL_IOC_BIT | ++ DWC_DSCCTL_IMI_BIT | ++ DWC_DSCCTL_CSP_BIT, 0); ++#ifdef DWC_ISOC_INTR_MODERATION ++ else ++ dwc_usb3_fill_desc(cur_trb, 0, 0, 0, ++ DWC_DSCCTL_TRBCTL_ISOC_1ST, ++ DWC_DSCCTL_IMI_BIT | ++ DWC_DSCCTL_CSP_BIT, 0); ++#endif ++#ifdef DWC_TEST_ISOC_CHAIN ++ /* Add 2 more TRBs per entry, chain them to the 1st */ ++ dwc_usb3_start_desc_chain(cur_trb); ++ cur_trb++; ++ ++ for (j = 0; j < 2; j++, cur_trb++) ++ dwc_usb3_fill_desc(cur_trb, 0, 0, 0, ++ DWC_DSCCTL_TRBCTL_ISOC, ++ DWC_DSCCTL_IMI_BIT | ++ DWC_DSCCTL_CSP_BIT | ++ DWC_DSCCTL_CHN_BIT, 0); ++ cur_trb--; ++ dwc_usb3_end_desc_chain(cur_trb); ++#endif ++ } ++ ++ /* For types other than Isoc, the TRBs are initialized just ++ * before the transfer is started. ++ */ ++ } ++ ++ if (link) { ++ dwc_usb3_fill_desc(cur_trb, trbs_dma, 0, 0, ++ DWC_DSCCTL_TRBCTL_LINK, 0, 1); ++ } ++ ++ /* Init the pcd_ep structure */ ++ ep->dwc_ep.dma_desc = trbs; ++ ep->dwc_ep.dma_desc_dma = trbs_dma; ++ ep->dwc_ep.desc_size = size; ++ ep->dwc_ep.desc_link = link; ++ ep->dwc_ep.num_desc = num_trbs; ++ ep->dwc_ep.desc_avail = num_trbs; ++ ep->dwc_ep.desc_idx = 0; ++ ep->dwc_ep.hiber_desc_idx = 0; ++ ++ if (trbs_dma_ret) ++ *trbs_dma_ret = trbs_dma; ++ return trbs; ++} ++ ++/** ++ * This routine frees the TRBs allocated by dwc_usb3_pcd_trb_alloc(). ++ * ++ * @param ep The EP for the allocation. ++ */ ++void dwc_usb3_pcd_trb_free(dwc_usb3_pcd_ep_t *ep) ++{ ++ dwc_usb3_dma_desc_t *trbs; ++ dwc_dma_t trbs_dma; ++ int size; ++ ++ if (ep->dwc_ep.dma_desc) { ++ trbs = ep->dwc_ep.dma_desc; ++ trbs_dma = ep->dwc_ep.dma_desc_dma; ++ size = ep->dwc_ep.desc_size; ++ ep->dwc_ep.dma_desc = NULL; ++ ep->dwc_ep.dma_desc_dma = 0; ++ ++ dwc_usb3_gadget_free_dma(ep, size, trbs, trbs_dma); ++ } ++} ++ ++/** ++ * This routine assigns and fills in the TRBs for a request. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param ep The EP for the transfer. ++ * @param req The request that needs the TRBs. ++ */ ++void dwc_usb3_pcd_fill_trbs(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep, ++ dwc_usb3_pcd_req_t *req) ++{ ++ dwc_usb3_dma_desc_t *desc; ++ dwc_dma_t desc_dma; ++ u32 len, tlen, pkts, ctrl; ++ int i; ++ ++ if (ep == pcd->ep0) ++ return; ++ ++ /* Get the next DMA Descriptor (TRB) for this EP */ ++ desc = ep->dwc_ep.dma_desc + ep->dwc_ep.desc_idx * req->dwc_req.numbuf; ++ desc_dma = (dwc_dma_t)((unsigned long)ep->dwc_ep.dma_desc_dma + ++ (unsigned long)ep->dwc_ep.desc_idx * req->dwc_req.numbuf * 16); ++ ++ if (++ep->dwc_ep.desc_idx >= ep->dwc_ep.num_desc) ++ ep->dwc_ep.desc_idx = 0; ++ ep->dwc_ep.desc_avail--; ++ ++ req->dwc_req.trb = desc; ++ req->dwc_req.trbdma = desc_dma; ++ ++ pkts = 0; ++ ++ if (ep->dwc_ep.is_in) { ++ /* For IN, TRB length is just xfer length */ ++ len = req->dwc_req.length; ++ ++ if (ep->dwc_ep.type == UE_ISOCHRONOUS && ++ pcd->speed == USB_SPEED_HIGH) { ++ pkts = (len + ep->dwc_ep.maxpacket - 1) ++ / ep->dwc_ep.maxpacket; ++ if (pkts) ++ pkts--; ++ } ++ } else { ++ /* For OUT, TRB length must be multiple of maxpacket */ ++ if ((ep->dwc_ep.type == UE_ISOCHRONOUS || ++ ep->dwc_ep.type == UE_INTERRUPT) && ++ ep->dwc_ep.maxpacket != 1024) ++ /* Might not be power of 2, so use (expensive?) ++ * divide/multiply ++ */ ++ len = ((req->dwc_req.length + ep->dwc_ep.maxpacket - 1) ++ / ep->dwc_ep.maxpacket) * ep->dwc_ep.maxpacket; ++ else ++ /* Must be power of 2, use cheap AND */ ++ len = (req->dwc_req.length + ep->dwc_ep.maxpacket - 1) ++ & ~(ep->dwc_ep.maxpacket - 1); ++ ++ req->dwc_req.length = len; ++ } ++ ++ /* DMA Descriptor Setup */ ++ for (i = 0; i < req->dwc_req.numbuf; i++, desc++) { ++ if (ep->dwc_ep.type == UE_ISOCHRONOUS) { ++ if (i != req->dwc_req.numbuf - 1) { ++ tlen = req->dwc_req.buflen[i]; ++ len -= tlen; ++ } else { ++ tlen = len; ++ } ++ ++ if (i == 0) ++ tlen |= pkts << DWC_DSCSTS_PCM1_SHIFT; ++ ++ dwc_usb3_fill_desc(desc, req->dwc_req.bufdma[i], tlen, ++ 0, 0, 0, i != 0); ++ } else { ++ if (i != req->dwc_req.numbuf - 1) { ++ ctrl = 0; ++ tlen = req->dwc_req.buflen[i]; ++ len -= tlen; ++ } else { ++ ctrl = DWC_DSCCTL_LST_BIT; ++ tlen = len; ++ } ++ ++ dwc_usb3_fill_desc(desc, req->dwc_req.bufdma[i], tlen, ++ req->dwc_req.stream, ++ DWC_DSCCTL_TRBCTL_NORMAL, ctrl, ++ i != 0); ++ } ++ } ++ ++ /* Must do this last! */ ++ desc = req->dwc_req.trb; ++ dwc_usb3_enable_desc(desc); ++} ++ ++/** ++ * This routine configures EP0 OUT to receive SETUP packets and configures ++ * EP0 IN for transmitting packets. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param restore True if restoring endpoint state after hibernation. ++ */ ++void dwc_usb3_ep0_activate(dwc_usb3_pcd_t *pcd, int restore) ++{ ++ u32 diepcfg0, doepcfg0, diepcfg1, doepcfg1; ++ u32 diepcfg2 = 0, doepcfg2 = 0; ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg; ++ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ ++ diepcfg0 = DWC_USB3_EP_TYPE_CONTROL << DWC_EPCFG0_EPTYPE_SHIFT; ++ diepcfg1 = DWC_EPCFG1_XFER_CMPL_BIT | DWC_EPCFG1_XFER_IN_PROG_BIT | ++ DWC_EPCFG1_XFER_NRDY_BIT | DWC_EPCFG1_EP_DIR_BIT; ++ ++ doepcfg0 = DWC_USB3_EP_TYPE_CONTROL << DWC_EPCFG0_EPTYPE_SHIFT; ++ doepcfg1 = DWC_EPCFG1_XFER_CMPL_BIT | DWC_EPCFG1_XFER_IN_PROG_BIT | ++ DWC_EPCFG1_XFER_NRDY_BIT; ++ ++ /* Default to MPS of 512 (will reconfigure after ConnectDone event) */ ++ diepcfg0 |= 512 << DWC_EPCFG0_MPS_SHIFT; ++ doepcfg0 |= 512 << DWC_EPCFG0_MPS_SHIFT; ++ ++#ifdef DWC_UTE ++ pcd->ep0->dwc_ep.tx_fifo_num = pcd->txf_map[1]; ++#endif ++ diepcfg0 |= pcd->ep0->dwc_ep.tx_fifo_num << DWC_EPCFG0_TXFNUM_SHIFT; ++ ++ if (restore) { ++ diepcfg0 |= DWC_CFG_ACTION_RESTORE ++ << DWC_EPCFG0_CFG_ACTION_SHIFT; ++ diepcfg2 = pcd->ep0_in_save_state; ++ dwc_debug1(pcd->usb3_dev, "IN restore state=%08x\n", diepcfg2); ++ doepcfg0 |= DWC_CFG_ACTION_RESTORE ++ << DWC_EPCFG0_CFG_ACTION_SHIFT; ++ doepcfg2 = pcd->ep0_out_save_state; ++ dwc_debug1(pcd->usb3_dev, "OUT restore state=%08x\n", doepcfg2); ++ } ++ ++ /* ++ * Issue "DEPCFG" command to EP0-OUT ++ */ ++ ++ ep_reg = &pcd->out_ep_regs[0]; ++ dwc_usb3_dis_usb2_suspend(pcd); ++ ++ /* If core is version 1.09a or later */ ++ if ((pcd->usb3_dev->snpsid & 0xffff) >= 0x109a) { ++ /* Must issue DEPSTRTNEWCFG command first */ ++ dwc_usb3_dep_startnewcfg(pcd, ep_reg, 0); ++ } ++ ++ dwc_usb3_dep_cfg(pcd, ep_reg, doepcfg0, doepcfg1, doepcfg2); ++ ++ /* ++ * Issue "DEPSTRMCFG" command to EP0-OUT ++ */ ++ ++ /* One stream */ ++ dwc_usb3_dep_xfercfg(pcd, ep_reg, 1); ++ ++ /* ++ * Issue "DEPCFG" command to EP0-IN ++ */ ++ ++ ep_reg = &pcd->in_ep_regs[0]; ++ dwc_usb3_dep_cfg(pcd, ep_reg, diepcfg0, diepcfg1, diepcfg2); ++ ++ /* ++ * Issue "DEPSTRMCFG" command to EP0-IN ++ */ ++ ++ /* One stream */ ++ dwc_usb3_dep_xfercfg(pcd, ep_reg, 1); ++ ++ dwc_usb3_ena_usb2_suspend(pcd); ++ pcd->ep0->dwc_ep.active = 1; ++} ++ ++/** ++ * This routine activates an EP. The Device EP control registers for the EP ++ * are configured as defined in the EP structure. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param ep The EP to activate. ++ * @param restore True if restoring endpoint state after hibernation. ++ */ ++void dwc_usb3_ep_activate(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep, ++ int restore) ++{ ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg, *ep0_reg; ++ u32 depcfg0, depcfg1, depcfg2 = 0; ++ ++ dwc_debug3(pcd->usb3_dev, "%s() EP%d-%s\n", __func__, ep->dwc_ep.num, ++ (ep->dwc_ep.is_in ? "IN" : "OUT")); ++ ++ ep->dwc_ep.hiber_desc_idx = 0; ++ ++#ifdef DWC_STAR_9000463548_WORKAROUND ++ if (pcd->configuring) ++ goto skip; ++#endif ++ /* ++ * Get the appropriate EP registers ++ */ ++ if (ep->dwc_ep.is_in) ++ ep_reg = ep->dwc_ep.in_ep_reg; ++ else ++ ep_reg = ep->dwc_ep.out_ep_reg; ++ ++ dwc_usb3_dis_usb2_suspend(pcd); ++ ++ /* If this is first EP enable (ie. start of a new configuration) */ ++ if (!pcd->eps_enabled) { ++ ++#ifdef DWC_STAR_9000463548_WORKAROUND ++ dwc_usb3_dev_ep_regs_t __iomem *eptmp_reg; ++ dwc_usb3_pcd_ep_t *eptmp; ++ int i; ++ ++ /* For the workaround, we must wait for all EndXfers on all EPs ++ * to complete before continuing ++ */ ++ for (i = 0; i < pcd->num_in_eps; i++) { ++ eptmp = pcd->in_ep[i]; ++ dwc_print3(pcd->usb3_dev, "DWC IN EP%d=%lx tri-in=%d\n", ++ i, (unsigned long)eptmp, eptmp->dwc_ep.tri_in); ++ if (eptmp->dwc_ep.tri_in) { ++ eptmp_reg = eptmp->dwc_ep.in_ep_reg; ++ eptmp->dwc_ep.condition = 0; ++ dwc_usb3_dep_wait_endxfer(pcd, eptmp_reg, ++ &eptmp->dwc_ep.condition); ++ eptmp->dwc_ep.tri_in = 0; ++ } ++ } ++ ++ for (i = 0; i < pcd->num_out_eps; i++) { ++ eptmp = pcd->out_ep[i]; ++ dwc_print3(pcd->usb3_dev, ++ "DWC OUT EP%d=%lx tri-out=%d\n", ++ i, (unsigned long)eptmp, eptmp->dwc_ep.tri_out); ++ if (eptmp->dwc_ep.tri_out) { ++ eptmp_reg = eptmp->dwc_ep.out_ep_reg; ++ eptmp->dwc_ep.condition = 0; ++ dwc_usb3_dep_wait_endxfer(pcd, eptmp_reg, ++ &eptmp->dwc_ep.condition); ++ eptmp->dwc_ep.tri_out = 0; ++ } ++ } ++#endif ++ pcd->eps_enabled = 1; ++ ++ /* NOTE: When setting a new configuration, we must issue a ++ * "DEPCFG" command to physical EP1 (logical EP0-IN) first. ++ * This resets the core's Tx FIFO mapping table ++ */ ++ depcfg0 = DWC_USB3_EP_TYPE_CONTROL << DWC_EPCFG0_EPTYPE_SHIFT; ++ depcfg0 |= DWC_CFG_ACTION_MODIFY << DWC_EPCFG0_CFG_ACTION_SHIFT; ++ depcfg1 = DWC_EPCFG1_XFER_CMPL_BIT | DWC_EPCFG1_XFER_IN_PROG_BIT ++ | DWC_EPCFG1_XFER_NRDY_BIT | DWC_EPCFG1_EP_DIR_BIT; ++ ++ switch (pcd->speed) { ++ case USB_SPEED_SUPER: ++ depcfg0 |= 512 << DWC_EPCFG0_MPS_SHIFT; ++ break; ++ ++ case USB_SPEED_HIGH: ++ case USB_SPEED_FULL: ++ depcfg0 |= 64 << DWC_EPCFG0_MPS_SHIFT; ++ break; ++ ++ case USB_SPEED_LOW: ++ depcfg0 |= 8 << DWC_EPCFG0_MPS_SHIFT; ++ break; ++ } ++ ++ ep0_reg = &pcd->in_ep_regs[0]; ++ dwc_usb3_dep_cfg(pcd, ep0_reg, depcfg0, depcfg1, 0); ++ ++ /* If core is version 1.09a or later */ ++ if ((pcd->usb3_dev->snpsid & 0xffff) >= 0x109a) { ++ /* Must issue DEPSTRTNEWCFG command first */ ++ ep0_reg = &pcd->out_ep_regs[0]; ++ dwc_usb3_dep_startnewcfg(pcd, ep0_reg, 2); ++ } ++ } ++ ++ /* ++ * Issue "DEPCFG" command to EP ++ */ ++ depcfg0 = ep->dwc_ep.type << DWC_EPCFG0_EPTYPE_SHIFT; ++ depcfg0 |= ep->dwc_ep.maxpacket << DWC_EPCFG0_MPS_SHIFT; ++ ++ if (ep->dwc_ep.is_in) { ++#ifdef DWC_UTE ++ ep->dwc_ep.tx_fifo_num = pcd->txf_map[ep->dwc_ep.phys]; ++#endif ++ depcfg0 |= ep->dwc_ep.tx_fifo_num << DWC_EPCFG0_TXFNUM_SHIFT; ++ } ++ ++ if (pcd->usb3_dev->core_params->burst) { ++ dwc_debug1(pcd->usb3_dev, "Setting maxburst to %u\n", ++ ep->dwc_ep.maxburst); ++ depcfg0 |= ep->dwc_ep.maxburst << DWC_EPCFG0_BRSTSIZ_SHIFT; ++ } ++ ++ if (restore) { ++ depcfg0 |= DWC_CFG_ACTION_RESTORE ++ << DWC_EPCFG0_CFG_ACTION_SHIFT; ++ depcfg2 = ep->dwc_ep.save_state; ++ } ++ ++ depcfg1 = ep->dwc_ep.num << DWC_EPCFG1_EP_NUM_SHIFT; ++ if (ep->dwc_ep.is_in) ++ depcfg1 |= DWC_EPCFG1_EP_DIR_BIT; ++ ++ depcfg1 |= DWC_EPCFG1_XFER_CMPL_BIT; ++ depcfg1 |= DWC_EPCFG1_XFER_IN_PROG_BIT; ++ depcfg1 |= DWC_EPCFG1_XFER_NRDY_BIT; ++ dwc_isocdbg1(pcd->usb3_dev, "Setting bInterval-1 to %u\n", ++ ep->dwc_ep.intvl); ++ depcfg1 |= ep->dwc_ep.intvl << DWC_EPCFG1_BINTERVAL_SHIFT; ++ ++ if (ep->dwc_ep.num_streams) { ++ dwc_debug0(pcd->usb3_dev, "Setting stream-capable bit\n"); ++ depcfg1 |= DWC_EPCFG1_STRM_CAP_BIT; ++ } ++ ++ if (pcd->usb3_dev->core_params->ebc) { ++ if (pcd->speed == USB_SPEED_SUPER || ++ pcd->speed == USB_SPEED_HIGH) { ++ dwc_debug0(pcd->usb3_dev, "Setting EBC enable bit\n"); ++ depcfg1 |= DWC_EPCFG1_EBC_MODE_BIT; ++ } ++ } ++ ++ /* Save the DEPCFG parameters for later */ ++ if (ep->dwc_ep.is_in) { ++ ep->dwc_ep.param0in = depcfg0 & ~DWC_EPCFG0_CFG_ACTION_BITS; ++ ep->dwc_ep.param1in = depcfg1; ++ } else { ++ ep->dwc_ep.param0out = depcfg0 & ~DWC_EPCFG0_CFG_ACTION_BITS; ++ ep->dwc_ep.param1out = depcfg1; ++ } ++ ++ dwc_usb3_dep_cfg(pcd, ep_reg, depcfg0, depcfg1, depcfg2); ++ ++ /* ++ * Issue "DEPSTRMCFG" command to EP ++ */ ++ ++ /* If this EP hasn't been enabled yet in this configuration */ ++ if (!ep->dwc_ep.ena_once) { ++ ep->dwc_ep.ena_once = 1; ++ ++ /* One stream */ ++ dwc_debug0(pcd->usb3_dev, "Setting 1 stream resource\n"); ++ dwc_usb3_dep_xfercfg(pcd, ep_reg, 1); ++ } ++ ++ dwc_usb3_ena_usb2_suspend(pcd); ++ ++#ifdef DWC_STAR_9000463548_WORKAROUND ++skip: ++#endif ++ /* Enable EP in DALEPENA reg */ ++ dwc_usb3_enable_ep(pcd, ep); ++ ++ ep->dwc_ep.active = 1; ++ ep->dwc_ep.stall_clear_flag = 0; ++} ++ ++/** ++ * This routine deactivates an EP. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param ep The EP to deactivate. ++ */ ++static void ep_deactivate(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep) ++{ ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg; ++ u8 tri; ++ ++ dwc_debug3(pcd->usb3_dev, "%s() EP%d-%s\n", __func__, ep->dwc_ep.num, ++ (ep->dwc_ep.is_in ? "IN" : "OUT")); ++ /* ++ * Get the appropriate EP registers ++ */ ++ if (ep->dwc_ep.is_in) { ++ ep_reg = ep->dwc_ep.in_ep_reg; ++ tri = ep->dwc_ep.tri_in; ++ ep->dwc_ep.tri_in = 0; ++ } else { ++ ep_reg = ep->dwc_ep.out_ep_reg; ++ tri = ep->dwc_ep.tri_out; ++ ep->dwc_ep.tri_out = 0; ++ } ++ ++ dwc_print2(pcd->usb3_dev, "end: DWC EP=%lx tri=%d\n", ++ (unsigned long)ep, tri); ++ dwc_usb3_dis_usb2_suspend(pcd); ++ ++ /* Execute clear stall command */ ++ dwc_usb3_dep_cstall(pcd, ep_reg, 0); ++ ++ if (tri) { ++#ifdef DWC_STAR_9000463548_WORKAROUND ++ /* For the workaround, we wait until the EP is re-enabled ++ * before waiting for the end transfer to complete ++ */ ++ dwc_usb3_dep_endxfer_nowait(pcd, ep_reg, tri - 1, ++ DWC_ENDXFER_FORCE); ++ if (ep->dwc_ep.is_in) ++ ep->dwc_ep.tri_in = tri; ++ else ++ ep->dwc_ep.tri_out = tri; ++#else ++ /* Execute end transfer command */ ++ ep->dwc_ep.condition = 0; ++ dwc_usb3_dep_endxfer(pcd, ep_reg, tri - 1, DWC_ENDXFER_FORCE, ++ &ep->dwc_ep.condition); ++#endif ++ } ++ ++ dwc_usb3_ena_usb2_suspend(pcd); ++ ep->dwc_ep.xfer_started = 0; ++ ++ /* Disable EP in DALEPENA reg */ ++ dwc_usb3_disable_ep(pcd, ep); ++ ++ ep->dwc_ep.active = 0; ++} ++ ++/** ++ * This routine sets up a SETUP stage transfer for EP0 and starts the transfer. ++ * ++ * @param pcd Programming view of the PCD. ++ */ ++void dwc_usb3_pcd_ep0_out_start(dwc_usb3_pcd_t *pcd) ++{ ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg; ++ dwc_usb3_dma_desc_t *desc; ++ dwc_dma_t desc_dma; ++ u8 tri; ++ ++ /* Get the SETUP packet DMA Descriptor (TRB) */ ++ desc = dwc_usb3_ep0_setup_desc(pcd); ++ desc_dma = dwc_usb3_ep0_setup_desc_dma(pcd); ++ ++ /* DMA Descriptor setup */ ++ dwc_usb3_fill_desc(desc, dwc_usb3_ep0_setup_pkt_dma(pcd), ++ pcd->ep0->dwc_ep.maxpacket, 0, ++ DWC_DSCCTL_TRBCTL_SETUP, DWC_DSCCTL_LST_BIT, 1); ++ dwc_debug5(pcd->usb3_dev, ++ "%s() desc=0x%08lx xfercnt=%u bptr=0x%08x:%08x\n", ++ __func__, (unsigned long)desc, dwc_usb3_get_xfercnt(desc), ++ desc->bpth, desc->bptl); ++#ifdef VERBOSE ++ dwc_debug4(pcd->usb3_dev, "0x%08x 0x%08x 0x%08x 0x%08x\n", ++ *((unsigned *)desc), *((unsigned *)desc + 1), ++ *((unsigned *)desc + 2), *((unsigned *)desc + 3)); ++#endif ++ ++ ep_reg = &pcd->out_ep_regs[0]; ++ dwc_usb3_dis_usb2_suspend(pcd); ++ ++ /* Issue "DEPSTRTXFER" command to EP0-OUT */ ++ wmb(); ++ tri = dwc_usb3_dep_startxfer(pcd, ep_reg, desc_dma, 0); ++ pcd->ep0->dwc_ep.tri_out = tri + 1; ++ ++ dwc_usb3_ena_usb2_suspend(pcd); ++} ++ ++/** ++ * This routine sets up a data/status stage transfer for EP0 and starts the ++ * transfer. If pcd->ep0->dwc_ep.is_in is 0 it will be an OUT transfer, ++ * otherwise it will be an IN transfer. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param req The request to start. ++ */ ++void dwc_usb3_pcd_ep0_start_transfer(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_req_t *req) ++{ ++ dwc_usb3_pcd_ep_t *ep0 = pcd->ep0; ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg; ++ dwc_usb3_dma_desc_t *desc; ++ dwc_dma_t desc_dma; ++ u32 desc_type, len; ++ u8 tri; ++ ++ dwc_debug7(pcd->usb3_dev, ++ "%s(): ep%d-%s req=%lx xfer_len=%d xfer_cnt=%d xfer_buf=%lx\n", ++ __func__, ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"), ++ (unsigned long)req, req->dwc_req.length, req->dwc_req.actual, ++ (unsigned long)req->dwc_req.buf[0]); ++ ++ /* Get the DMA Descriptor (TRB) for this request */ ++ if (ep0->dwc_ep.is_in) { ++ req->dwc_req.trb = dwc_usb3_ep0_in_desc(pcd); ++ req->dwc_req.trbdma = dwc_usb3_ep0_in_desc_dma(pcd); ++ } else { ++ req->dwc_req.trb = dwc_usb3_ep0_out_desc(pcd); ++ req->dwc_req.trbdma = dwc_usb3_ep0_out_desc_dma(pcd); ++ } ++ ++ desc = req->dwc_req.trb; ++ desc_dma = req->dwc_req.trbdma; ++ dwc_usb3_dis_usb2_suspend(pcd); ++ ++ if (ep0->dwc_ep.is_in) { ++ /* ++ * Start DMA on EP0-IN ++ */ ++ ep_reg = ep0->dwc_ep.in_ep_reg; ++ ++ /* DMA Descriptor (TRB) setup */ ++ len = req->dwc_req.length; ++ ++ dwc_debug1(pcd->usb3_dev, "IN EP0STATE=%d\n", pcd->ep0state); ++ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ if (ep0->dwc_ep.three_stage) ++ desc_type = DWC_DSCCTL_TRBCTL_STATUS_3; ++ else ++ desc_type = DWC_DSCCTL_TRBCTL_STATUS_2; ++ } else { ++ desc_type = DWC_DSCCTL_TRBCTL_CTLDATA_1ST; ++ } ++ ++ dwc_usb3_fill_desc(desc, req->dwc_req.bufdma[0], ++ len, 0, desc_type, DWC_DSCCTL_LST_BIT, 1); ++ dwc_debug4(pcd->usb3_dev, ++ "IN desc=0x%08lx xferlen=%u bptr=0x%08x:%08x\n", ++ (unsigned long)desc, dwc_usb3_get_xfercnt(desc), ++ desc->bpth, desc->bptl); ++#ifdef VERBOSE ++ dwc_debug4(pcd->usb3_dev, "0x%08x 0x%08x 0x%08x 0x%08x\n", ++ *((unsigned *)desc), *((unsigned *)desc + 1), ++ *((unsigned *)desc + 2), *((unsigned *)desc + 3)); ++#endif ++ /* Issue "DEPSTRTXFER" command to EP0-IN */ ++ wmb(); ++ tri = dwc_usb3_dep_startxfer(pcd, ep_reg, desc_dma, 0); ++ ep0->dwc_ep.tri_in = tri + 1; ++ } else { ++ /* ++ * Start DMA on EP0-OUT ++ */ ++ ep_reg = ep0->dwc_ep.out_ep_reg; ++ ++ /* DMA Descriptor (TRB) setup */ ++ len = (req->dwc_req.length + ep0->dwc_ep.maxpacket - 1) & ++ ~(ep0->dwc_ep.maxpacket - 1); ++ ++ dwc_debug1(pcd->usb3_dev, "OUT EP0STATE=%d\n", pcd->ep0state); ++ ++ if (pcd->ep0state == EP0_OUT_STATUS_PHASE) { ++ if (ep0->dwc_ep.three_stage) ++ desc_type = DWC_DSCCTL_TRBCTL_STATUS_3; ++ else ++ desc_type = DWC_DSCCTL_TRBCTL_STATUS_2; ++ } else { ++ desc_type = DWC_DSCCTL_TRBCTL_CTLDATA_1ST; ++ } ++ ++ dwc_usb3_fill_desc(desc, req->dwc_req.bufdma[0], ++ len, 0, desc_type, DWC_DSCCTL_LST_BIT, 1); ++ dwc_debug4(pcd->usb3_dev, ++ "OUT desc=0x%08lx xferlen=%u bptr=0x%08x:%08x\n", ++ (unsigned long)desc, dwc_usb3_get_xfercnt(desc), ++ desc->bpth, desc->bptl); ++#ifdef VERBOSE ++ dwc_debug4(pcd->usb3_dev, "0x%08x 0x%08x 0x%08x 0x%08x\n", ++ *((unsigned *)desc), *((unsigned *)desc + 1), ++ *((unsigned *)desc + 2), *((unsigned *)desc + 3)); ++#endif ++ /* Issue "DEPSTRTXFER" command to EP0-OUT */ ++ wmb(); ++ tri = dwc_usb3_dep_startxfer(pcd, ep_reg, desc_dma, 0); ++ ep0->dwc_ep.tri_out = tri + 1; ++ } ++ ++ dwc_usb3_ena_usb2_suspend(pcd); ++} ++ ++/** ++ * This routine continues control IN transfers started by ep0_start_transfer, ++ * when the transfer does not fit in a single request. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param req The request to continue. ++ */ ++void dwc_usb3_pcd_ep0_continue_transfer(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_req_t *req) ++{ ++ dwc_usb3_pcd_ep_t *ep0 = pcd->ep0; ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg; ++ dwc_usb3_dma_desc_t *desc; ++ dwc_dma_t desc_dma; ++ u8 tri; ++ ++ /* Currently the EP0 buffer size in the gadget is at least 256 bytes, ++ * and all control transfers are smaller than that, so this routine is ++ * never called to continue a transfer. However it can be called to ++ * send a 0-length packet after the end of a transfer, so the code here ++ * only supports that case. ++ */ ++ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ ++ if (ep0->dwc_ep.is_in) { ++ desc = dwc_usb3_ep0_in_desc(pcd); ++ desc_dma = dwc_usb3_ep0_in_desc_dma(pcd); ++ ep_reg = ep0->dwc_ep.in_ep_reg; ++ ++ /* DMA Descriptor Setup */ ++ dwc_usb3_fill_desc(desc, req->dwc_req.bufdma[0], 0, 0, ++ DWC_DSCCTL_TRBCTL_NORMAL, DWC_DSCCTL_LST_BIT, ++ 1); ++ ++ /* Make sure all writes to TRB have completed */ ++ wmb(); ++ ++ dwc_usb3_dis_usb2_suspend(pcd); ++ tri = dwc_usb3_dep_startxfer(pcd, ep_reg, desc_dma, 0); ++ ep0->dwc_ep.tri_in = tri + 1; ++ dwc_usb3_ena_usb2_suspend(pcd); ++ } ++} ++ ++/** ++ * This routine does the setup for a data transfer for an EP and starts ++ * the transfer. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param ep The EP to start the transfer on. ++ * @param req The request to start. ++ * @param event If non-zero, this is the first transfer for an Isoc EP, so we ++ * must calculate the starting uFrame and do a startxfer instead ++ * of an updatexfer. ++ */ ++void dwc_usb3_pcd_ep_start_transfer(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep, ++ dwc_usb3_pcd_req_t *req, u32 event) ++{ ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg; ++ dwc_usb3_dma_desc_t *desc; ++ dwc_dma_t desc_dma; ++ u32 dsts; ++ u16 current_uf, intvl, mask, now, target_uf = 0; ++ u8 tri; ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ u32 dcfg; ++#endif ++ ++ dwc_debug10(pcd->usb3_dev, ++ "%s(): ep%d-%s (%d phys) %lx max_pkt=%d req=%lx" ++ " xfer_len=%d xfer_cnt=%d xfer_buf=%lx\n", ++ __func__, ep->dwc_ep.num, (ep->dwc_ep.is_in ? "IN" : "OUT"), ++ ep->dwc_ep.phys, (unsigned long)ep, ep->dwc_ep.maxpacket, ++ (unsigned long)req, req->dwc_req.length, ++ req->dwc_req.actual, (unsigned long)req->dwc_req.buf[0]); ++ ++ ep->dwc_ep.hiber_desc_idx = 0; ++ ++ /* If first transfer for Isoc */ ++ if (event) { ++ /* Get the uFrame of the host request */ ++ current_uf = event >> DWC_DEPEVT_ISOC_UFRAME_NUM_SHIFT & ++ DWC_DEPEVT_ISOC_UFRAME_NUM_BITS >> ++ DWC_DEPEVT_ISOC_UFRAME_NUM_SHIFT; ++ ++ /* Get the EP's interval */ ++ intvl = 1 << ep->dwc_ep.intvl; ++ ++ /* Get the EP's interval mask */ ++ mask = ~(intvl - 1); ++ ++ dsts = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dsts); ++ now = dsts >> DWC_DSTS_SOF_FN_SHIFT & ++ DWC_DSTS_SOF_FN_BITS >> DWC_DSTS_SOF_FN_SHIFT; ++ if (now < (current_uf & 0x3fff)) ++ now += 0x4000; ++ now += current_uf & 0xc000; ++ ++ /* Calculate a start time which is 2 or 4 intervals in the ++ * future ++ */ ++ target_uf = current_uf & mask; ++again: ++#ifdef SELA_PLATFORM ++ target_uf += intvl; ++#else ++ if (intvl <= 8) ++ target_uf += intvl << 2; ++ else ++ target_uf += intvl << 1; ++#endif ++ dwc_isocdbg3(pcd->usb3_dev, "tgt:%1x now:%1x tgt-now:%1x\n", ++ target_uf, now, target_uf - now); ++ if (target_uf - now >= 0x8000U) ++ goto again; ++ ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ dcfg = dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dcfg); ++ dwc_debug6(pcd->usb3_dev, ++ "dcfg:0x%1x dsts:0x%1x uf:0x%1x" ++ " intvl:0x%1x cur_uf:0x%1x tgt_uf:0x%1x\n", ++ dcfg, dsts, dsts >> 3 & 0x3fff, intvl, current_uf, ++ target_uf); ++ dwc_isocdbg4(pcd->usb3_dev, ++ "now:%1x bIvl:%1x ivl:%1x(u)f tgt:%1x\n", ++ now, ep->dwc_ep.intvl + 1, intvl, target_uf); ++#endif ++ /* Make sure 'target_uf' is non-zero so the code below knows ++ * that this is the first Isoc xfer. It will decrement the ++ * value by 1 before using it ++ */ ++ target_uf++; ++ } ++ ++ ep->dwc_ep.send_zlp = 0; ++ req->dwc_req.flags |= DWC_PCD_REQ_STARTED; ++ desc = req->dwc_req.trb; ++ desc_dma = req->dwc_req.trbdma; ++ dwc_usb3_dis_usb2_suspend(pcd); ++ wmb(); ++ ++ if (ep->dwc_ep.is_in) { ++ /* ++ * Start DMA on EPn-IN ++ */ ++ ep_reg = ep->dwc_ep.in_ep_reg; ++ dwc_debug4(pcd->usb3_dev, ++ "IN desc=0x%08lx xferlen=%u bptr=0x%08x:%08x\n", ++ (unsigned long)desc, dwc_usb3_get_xfercnt(desc), ++ desc->bpth, desc->bptl); ++#ifdef VERBOSE ++ dwc_debug5(pcd->usb3_dev, "%08x %08x %08x %08x (%08x)\n", ++ *((unsigned *)desc), *((unsigned *)desc + 1), ++ *((unsigned *)desc + 2), *((unsigned *)desc + 3), ++ (unsigned)desc_dma); ++#endif ++ /* If Isoc */ ++ if (ep->dwc_ep.type == UE_ISOCHRONOUS) { ++ if (ep->dwc_ep.xfer_started) { ++ /* Issue "DEPUPDTXFER" command to EP */ ++ dwc_usb3_dep_updatexfer(pcd, ep_reg, ++ ep->dwc_ep.tri_in - 1); ++ } else if (target_uf) { ++ /* Issue "DEPSTRTXFER" command to EP */ ++ tri = dwc_usb3_dep_startxfer(pcd, ep_reg, ++ desc_dma, ++ target_uf - 1); ++ ep->dwc_ep.tri_in = tri + 1; ++ ep->dwc_ep.xfer_started = 1; ++ } else { ++ //dwc_print0(pcd->usb3_dev, ++ // "Not starting isoc IN!\n"); ++ } ++ } else { ++ if (ep->dwc_ep.xfer_started) { ++ /* Issue "DEPUPDTXFER" command to EP */ ++ dwc_usb3_dep_updatexfer(pcd, ep_reg, ++ ep->dwc_ep.tri_in - 1); ++ } else { ++ /* Issue "DEPSTRTXFER" command to EP */ ++ tri = dwc_usb3_dep_startxfer(pcd, ep_reg, ++ desc_dma, ++ req->dwc_req.stream); ++ ep->dwc_ep.tri_in = tri + 1; ++ ep->dwc_ep.xfer_started = 1; ++ } ++ } ++ } else { ++ /* ++ * Start DMA on EPn-OUT ++ */ ++ ep_reg = ep->dwc_ep.out_ep_reg; ++ dwc_debug4(pcd->usb3_dev, ++ "OUT desc=0x%08lx xferlen=%u bptr=0x%08x:%08x\n", ++ (unsigned long)desc, dwc_usb3_get_xfercnt(desc), ++ desc->bpth, desc->bptl); ++#ifdef VERBOSE ++ dwc_debug5(pcd->usb3_dev, "%08x %08x %08x %08x (%08x)\n", ++ *((unsigned *)desc), *((unsigned *)desc + 1), ++ *((unsigned *)desc + 2), *((unsigned *)desc + 3), ++ (unsigned)desc_dma); ++#endif ++ /* If Isoc */ ++ if (ep->dwc_ep.type == UE_ISOCHRONOUS) { ++ if (ep->dwc_ep.xfer_started) { ++ /* Issue "DEPUPDTXFER" command to EP */ ++ dwc_usb3_dep_updatexfer(pcd, ep_reg, ++ ep->dwc_ep.tri_out - 1); ++ } else if (target_uf) { ++ /* Issue "DEPSTRTXFER" command to EP */ ++ tri = dwc_usb3_dep_startxfer(pcd, ep_reg, ++ desc_dma, ++ target_uf - 1); ++ ep->dwc_ep.tri_out = tri + 1; ++ ep->dwc_ep.xfer_started = 1; ++ } else { ++ //dwc_print0(pcd->usb3_dev, ++ // "Not starting isoc OUT!\n"); ++ } ++ } else { ++ if (ep->dwc_ep.xfer_started) { ++ /* Issue "DEPUPDTXFER" command to EP */ ++ dwc_usb3_dep_updatexfer(pcd, ep_reg, ++ ep->dwc_ep.tri_out - 1); ++ } else { ++ /* Issue "DEPSTRTXFER" command to EP */ ++ tri = dwc_usb3_dep_startxfer(pcd, ep_reg, ++ desc_dma, ++ req->dwc_req.stream); ++ ep->dwc_ep.tri_out = tri + 1; ++ ep->dwc_ep.xfer_started = 1; ++ } ++ } ++ } ++ ++ dwc_usb3_ena_usb2_suspend(pcd); ++} ++ ++/** ++ * For restart after hibernation, we need to restart the transfer with the ++ * address of the TRB that was last active before the hibernation. That address ++ * was saved in the hiber_desc_idx field of struct dwc_ep by the ++ * hibernation wakeup code. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param ep The EP to restart the transfer on. ++ * @return 1 if a transfer was restarted, 0 if not. ++ */ ++int dwc_usb3_pcd_isoc_ep_hiber_restart(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep) ++{ ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg; ++ dwc_usb3_dma_desc_t *desc; ++ dwc_dma_t desc_dma; ++ int owned; ++ u8 *tri; ++ ++ /* Need to restart after hibernation? */ ++ owned = ep->dwc_ep.hiber_desc_idx - 1; ++ if (owned < 0) ++ return 0; ++ ++ if (ep->dwc_ep.is_in) { ++ ep_reg = ep->dwc_ep.in_ep_reg; ++ tri = &ep->dwc_ep.tri_in; ++ } else { ++ ep_reg = ep->dwc_ep.out_ep_reg; ++ tri = &ep->dwc_ep.tri_out; ++ } ++ ++ dwc_debug0(pcd->usb3_dev, "Restarting Isoc xfer\n"); ++ desc = ep->dwc_ep.dma_desc + owned; ++ desc_dma = (dwc_dma_t) ++ ((unsigned long)ep->dwc_ep.dma_desc_dma + owned * 16); ++ dwc_debug1(pcd->usb3_dev, "desc=%08lx\n", (unsigned long)desc); ++ ++#ifdef VERBOSE ++ dwc_debug5(pcd->usb3_dev, "%08x %08x %08x %08x (%08x)\n", ++ *((unsigned *)desc), *((unsigned *)desc + 1), ++ *((unsigned *)desc + 2), *((unsigned *)desc + 3), ++ (unsigned)desc_dma); ++#endif ++ ++ dwc_usb3_dis_usb2_suspend(pcd); ++ wmb(); ++ *tri = dwc_usb3_dep_startxfer(pcd, ep_reg, desc_dma, 0) + 1; ++ dwc_usb3_ena_usb2_suspend(pcd); ++ ++ return 1; ++} ++ ++/** ++ * Stop any active xfer on a non-EP0 endpoint. ++ */ ++static void dwc_usb3_stop_xfer(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep) ++{ ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg; ++ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ ++ if (ep->dwc_ep.is_in) { ++ if (ep->dwc_ep.active && ep->dwc_ep.tri_in) { ++ ep_reg = ep->dwc_ep.in_ep_reg; ++ ep->dwc_ep.condition = 0; ++ dwc_usb3_dep_endxfer(pcd, ep_reg, ep->dwc_ep.tri_in - 1, ++ DWC_ENDXFER_FORCE, ++ &ep->dwc_ep.condition); ++ ep->dwc_ep.tri_in = 0; ++ } ++ } else { ++ if (ep->dwc_ep.active && ep->dwc_ep.tri_out) { ++ ep_reg = ep->dwc_ep.out_ep_reg; ++ ep->dwc_ep.condition = 0; ++ dwc_usb3_dep_endxfer(pcd, ep_reg, ep->dwc_ep.tri_out - 1, ++ DWC_ENDXFER_FORCE, ++ &ep->dwc_ep.condition); ++ ep->dwc_ep.tri_out = 0; ++ } ++ } ++} ++ ++/** ++ * Stop any active xfers on the non-EP0 endpoints. ++ */ ++void dwc_usb3_stop_all_xfers(dwc_usb3_pcd_t *pcd) ++{ ++ int i; ++ dwc_usb3_pcd_ep_t *ep; ++ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ dwc_usb3_dis_usb2_suspend(pcd); ++ ++ /* Stop any active xfers on the non-EP0 IN endpoints */ ++ printk("\n####%s,%d,pcd->num_in_eps=0x%x,pcd->num_out_eps=0x%x\n",__func__,__LINE__,pcd->num_in_eps,pcd->num_out_eps); ++ for (i = pcd->num_in_eps; i > 0; i--) { ++ ep = pcd->in_ep[i - 1]; ++ dwc_debug3(pcd->usb3_dev, "DWC IN EP%d=%lx tri-in=%d\n", ++ i, (unsigned long)ep, ep->dwc_ep.tri_in); ++ dwc_error(pcd->usb3_dev, "DWC IN EP%d=%lx tri-in=%d\n", ++ i, (unsigned long)ep, ep->dwc_ep.tri_in); ++ dwc_usb3_stop_xfer(pcd, ep); ++ dwc_usb3_gadget_request_nuke(pcd, ep); ++ ep->dwc_ep.xfer_started = 0; ++ } ++ ++ /* Stop any active xfers on the non-EP0 OUT endpoints */ ++ for (i = pcd->num_out_eps; i > 0; i--) { ++ ep = pcd->out_ep[i - 1]; ++ dwc_debug3(pcd->usb3_dev, "DWC OUT EP%d=%lx tri-out=%d\n", ++ i, (unsigned long)ep, ep->dwc_ep.tri_out); ++ dwc_error(pcd->usb3_dev, "DWC OUT EP%d=%lx tri-out=%d\n", ++ i, (unsigned long)ep, ep->dwc_ep.tri_out); ++ dwc_usb3_stop_xfer(pcd, ep); ++ dwc_usb3_gadget_request_nuke(pcd, ep); ++ ep->dwc_ep.xfer_started = 0; ++ } ++ ++ dwc_usb3_ena_usb2_suspend(pcd); ++} ++ ++/** ++ * This routine completes the request for the EP. If there are additional ++ * requests for the EP in the queue they will be started. ++ */ ++static int dwc_usb3_ep_complete_request(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep, ++ dwc_usb3_pcd_req_t *req, u32 event) ++{ ++ int is_last = 0, ret = 0; ++ int now_uf, evt_uf, i; ++ dwc_usb3_dma_desc_t *desc; ++ u32 byte_count; ++#if defined(DEBUG) || defined(ISOC_DEBUG) ++ dwc_usb3_device_t *dev = pcd->usb3_dev; ++ u32 bmudbg; ++ static u32 old0, old1, old2, old3, old4; ++#endif ++ ++ dwc_debug1(dev, "%s()\n", __func__); ++ ++ ep->dwc_ep.send_zlp = 0; ++ desc = req->dwc_req.trb; ++ dwc_debug2(dev, "req=%lx desc=%lx\n", (unsigned long)req, ++ (unsigned long)desc); ++ ++ if (!desc) { ++ dwc_isocdbg3(dev, "### %s, EP%d-%s request TRB is NULL! ###\n", ++ __func__, ep->dwc_ep.num, ep->dwc_ep.is_in ? ++ "IN" : "OUT"); ++ return ret; ++ } ++ ++ if (!(req->dwc_req.flags & DWC_PCD_REQ_STARTED)) { ++ dwc_isocdbg3(dev, "### %s, EP%d-%s request not started! ###\n", ++ __func__, ep->dwc_ep.num, ep->dwc_ep.is_in ? ++ "IN" : "OUT"); ++ if (ep->dwc_ep.type == UE_ISOCHRONOUS && ++ (event & DWC_DEPEVT_INTTYPE_BITS) == ++ DWC_DEPEVT_XFER_IN_PROG << DWC_DEPEVT_INTTYPE_SHIFT && ++ ep->dwc_ep.xfer_started == 0) { ++ is_last = 1; ++ goto done; ++ } ++ return ret; ++ } ++ ++ if (dwc_usb3_is_hwo(desc)) { ++ dwc_isocdbg3(dev, "### %s, EP%d-%s HWO bit set! ###\n", ++ __func__, ep->dwc_ep.num, ep->dwc_ep.is_in ? ++ "IN" : "OUT"); ++ return ret; ++ } ++ ++ if (ep->dwc_ep.type == UE_ISOCHRONOUS) { ++ now_uf = dwc_usb3_get_frame(pcd); ++ evt_uf = dwc_usb3_get_eventsofn(event); ++ dwc_isocdbg6(dev, ++ "ep:%1x evt:%08x frm:%04x now:%04x trb:%1lx len:%04x\n", ++ ep->dwc_ep.num, event, evt_uf, now_uf, ++ ((unsigned long)req->dwc_req.trbdma - ++ (unsigned long)ep->dwc_ep.dma_desc_dma) / ++ (req->dwc_req.numbuf * 16), dwc_usb3_get_xfercnt(desc)); ++ /*dwc_isocdbg4(dev, "this trb: %08x %08x %08x %08x\n", ++ *((unsigned *)desc), *((unsigned *)desc + 1), ++ *((unsigned *)desc + 2), *((unsigned *)desc + 3)); ++ dwc_isocdbg4(dev, "next trb: %08x %08x %08x %08x\n", ++ *((unsigned *)desc + 4), *((unsigned *)desc + 5), ++ *((unsigned *)desc + 6), *((unsigned *)desc + 7));*/ ++ } ++ ++ if (ep->dwc_ep.is_in) { /* IN endpoint */ ++ for (i = 0; i < req->dwc_req.numbuf; i++, desc++) { ++ req->dwc_req.actual += req->dwc_req.length; ++ if (i == req->dwc_req.numbuf - 1) ++ is_last = 1; ++ } ++ ++ if (i) ++ desc--; ++ dwc_debug3(dev, "IN len=%d cnt=%d rem=%d\n", ++ req->dwc_req.length, req->dwc_req.actual, ++ dwc_usb3_get_xfercnt(desc)); ++ ++ } else { /* OUT endpoint */ ++ for (i = 0; i < req->dwc_req.numbuf; i++, desc++) { ++ byte_count = req->dwc_req.length - ++ dwc_usb3_get_xfercnt(desc); ++ req->dwc_req.actual += byte_count; ++ } ++ ++ if (i) ++ desc--; ++ dwc_debug3(dev, "OUT len=%d cnt=%d rem=%d\n", ++ req->dwc_req.length, req->dwc_req.actual, ++ dwc_usb3_get_xfercnt(desc)); ++ is_last = 1; ++ } ++done: ++ if ((event & DWC_DEPEVT_INTTYPE_BITS) == ++ DWC_DEPEVT_XFER_CMPL << DWC_DEPEVT_INTTYPE_SHIFT) { ++ if (ep->dwc_ep.is_in) ++ ep->dwc_ep.tri_in = 0; ++ else ++ ep->dwc_ep.tri_out = 0; ++ } ++ ++ /* Complete the request */ ++ if (is_last) { ++ dwc_usb3_pcd_request_done(pcd, ep, req, 0); ++ //dwc_info2(dev, "ep_complete_request - start req %d-%s\n", ++ // ep->dwc_ep.num, ep->dwc_ep.is_in ? "IN" : "OUT"); ++ if (ep->dwc_ep.type != UE_ISOCHRONOUS || ++ ep->dwc_ep.xfer_started) ++ /* If there is a request in the queue start it. */ ++ dwc_usb3_gadget_start_next_request(pcd, ep); ++ ++#ifdef DWC_ISOC_INTR_MODERATION ++ /* Handle Isoc interrupt moderation */ ++ if (ep->dwc_ep.type == UE_ISOCHRONOUS && ++ ep->dwc_ep.xfer_started && !dwc_usb3_is_ioc(desc)) ++ /* Tell caller we want to process next TRB */ ++ ret = 1; ++#endif ++ } else { ++ dwc_print2(dev, "### EP%d-%s is_last not set! ###\n", ++ ep->dwc_ep.num, ep->dwc_ep.is_in ? "IN" : "OUT"); ++ } ++ ++ return ret; ++} ++ ++/** ++ * This routine handles non-EP0 transfers. ++ * ++ * This routine gets the request corresponding to the completed transfer ++ * and then calls the core routine for handling the completion. ++ */ ++void dwc_usb3_complete_request(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep, ++ u32 event) ++{ ++ dwc_usb3_pcd_req_t *req; ++ dwc_usb3_dma_desc_t *desc; ++ int ret; ++ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ dwc_debug1(pcd->usb3_dev, "Requests %d\n", pcd->request_pending); ++ ++ req = dwc_usb3_gadget_get_request(pcd, ep); ++ if (!req) { ++ dwc_print2(pcd->usb3_dev, "%s(%lx), ep->dwc_ep.queue empty!\n", ++ __func__, (unsigned long)ep); ++ return; ++ } ++next: ++ ret = dwc_usb3_ep_complete_request(pcd, ep, req, event); ++ dwc_debug1(pcd->usb3_dev, ++ "dwc_usb3_ep_complete_request() returned %d\n", ret); ++ if (!ret) ++ return; ++ ++ req = dwc_usb3_gadget_get_request(pcd, ep); ++ if (!req) ++ return; ++ ++ if (ret < 0) { ++ /* Isoc restart - mark all requests in queue as not started */ ++ dwc_usb3_gadget_set_ep_not_started(pcd, ep); ++ } else { ++ /* ep_complete_request() wants to process next TRB */ ++ dwc_debug1(pcd->usb3_dev, "Requests2 %d\n", ++ pcd->request_pending); ++ desc = req->dwc_req.trb; ++ if (desc && (req->dwc_req.flags & DWC_PCD_REQ_STARTED) && ++ !dwc_usb3_is_hwo(desc)) { ++ dwc_debug0(pcd->usb3_dev, "Processing next TRB\n"); ++ goto next; ++ } ++ } ++} ++ ++/** ++ * Set the EP STALL. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param ep The EP to set the stall on. ++ */ ++void dwc_usb3_pcd_ep_set_stall(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep) ++{ ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg; ++ ++ dwc_info2(pcd->usb3_dev, "%s(%lx)\n", __func__, (unsigned long)ep); ++ dwc_info2(pcd->usb3_dev, "ep_num=%d is_in=%d\n", ++ ep->dwc_ep.num, ep->dwc_ep.is_in); ++ ++ if (ep->dwc_ep.is_in) ++ ep_reg = ep->dwc_ep.in_ep_reg; ++ else ++ ep_reg = ep->dwc_ep.out_ep_reg; ++ ++ dwc_usb3_dis_usb2_suspend(pcd); ++ dwc_usb3_dep_sstall(pcd, ep_reg); ++ dwc_usb3_ena_usb2_suspend(pcd); ++} ++ ++/** ++ * Clear the EP STALL. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param ep The EP to clear the stall on. ++ */ ++void dwc_usb3_pcd_ep_clear_stall(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep) ++{ ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg; ++ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ dwc_debug2(pcd->usb3_dev, "ep_num=%d is_in=%d\n", ++ ep->dwc_ep.num, ep->dwc_ep.is_in); ++ ++ if (ep->dwc_ep.is_in) ++ ep_reg = ep->dwc_ep.in_ep_reg; ++ else ++ ep_reg = ep->dwc_ep.out_ep_reg; ++ ++ dwc_usb3_dis_usb2_suspend(pcd); ++ dwc_usb3_dep_cstall(pcd, ep_reg, 0); ++ dwc_usb3_ena_usb2_suspend(pcd); ++} ++ ++/** ++ * This routine returns a pointer to Out EP struct with number ep_num. ++ */ ++dwc_usb3_pcd_ep_t *dwc_usb3_get_out_ep(dwc_usb3_pcd_t *pcd, u32 ep_num) ++{ ++ //dwc_debug2(pcd->usb3_dev, "%s(%d)\n", __func__, ep_num); ++ ++ if (ep_num == 0) ++ return pcd->ep0; ++ else ++ return pcd->out_ep[ep_num - 1]; ++} ++ ++/** ++ * This routine returns a pointer to In EP struct with number ep_num. ++ */ ++dwc_usb3_pcd_ep_t *dwc_usb3_get_in_ep(dwc_usb3_pcd_t *pcd, u32 ep_num) ++{ ++ //dwc_debug2(pcd->usb3_dev, "%s(%d)\n", __func__, ep_num); ++ ++ if (ep_num == 0) ++ return pcd->ep0; ++ else ++ return pcd->in_ep[ep_num - 1]; ++} ++ ++/** ++ * This routine gets a pointer to an EP from the wIndex address value of the ++ * control request. ++ */ ++dwc_usb3_pcd_ep_t *dwc_usb3_pcd_get_ep_by_addr(dwc_usb3_pcd_t *pcd, u16 index) ++{ ++ u32 ep_num = UE_GET_ADDR(index); ++ ++ //dwc_debug2(pcd->usb3_dev, "%s(%d)\n", __func__, index); ++ ++ if (UE_GET_DIR(index) == UE_DIR_IN) ++ return dwc_usb3_get_in_ep(pcd, ep_num); ++ else ++ return dwc_usb3_get_out_ep(pcd, ep_num); ++} ++ ++/* USB Endpoint Operations */ ++/* ++ * The following sections briefly describe the behavior of the Gadget API ++ * endpoint operations implemented in the DWC_usb3 driver software. Detailed ++ * descriptions of the generic behavior of each of these routines can be ++ * found in the Linux header file include/linux/usb_gadget.h. ++ * ++ * The Gadget API provides wrapper routines for each of the function ++ * pointers defined in usb_ep_ops. The Gadget Driver calls the wrapper ++ * routine, which then calls the underlying PCD routine. The following ++ * sections are named according to the wrapper routines. Within each ++ * section, the corresponding DWC_usb3 PCD routine name is specified. ++ * ++ */ ++ ++/** ++ * This routine is called by the Function Driver for each EP (except EP0) to ++ * be configured for the current configuration (SET_CONFIGURATION). ++ * ++ * This routine initializes the dwc_usb3_ep_t data structure, and then ++ * calls dwc_usb3_ep_activate. ++ */ ++int dwc_usb3_pcd_ep_enable(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep, ++ const usb_endpoint_descriptor_t *ep_desc, ++ const ss_endpoint_companion_descriptor_t *ep_comp) ++{ ++ int num, dir; ++ u16 maxpacket; ++ u8 type; ++ ++ dwc_debug5(pcd->usb3_dev, "%s(%lx,%lx,%lx,%lx)\n", __func__, ++ (unsigned long)pcd, (unsigned long)ep, ++ (unsigned long)ep_desc, (unsigned long)ep_comp); ++ dwc_debug2(pcd->usb3_dev, "ep=%lx is_in=%d\n", (unsigned long)ep, ++ ep->dwc_ep.is_in); ++ ++ if (ep->dwc_ep.usb_ep_desc) { ++ dwc_print1(pcd->usb3_dev, "%s, bad ep or descriptor!\n", ++ __func__); ++ return -DWC_E_INVALID; ++ } ++ ++ ep->dwc_ep.usb_ep_desc = ep_desc; ++ ++ /* ++ * Activate the EP ++ */ ++ ep->dwc_ep.stopped = 0; ++ ++ num = UE_GET_ADDR(ep_desc->bEndpointAddress); ++ if (ep->dwc_ep.num != num) { ++ dwc_print3(pcd->usb3_dev, ++ "%s, EP num mismatch, is %d asked %d!\n", ++ __func__, ep->dwc_ep.num, num); ++ } ++ ++ dir = UE_GET_DIR(ep_desc->bEndpointAddress); ++ if (ep->dwc_ep.is_in != (dir == UE_DIR_IN)) { ++ dwc_print3(pcd->usb3_dev, ++ "%s, EP dir mismatch, is %d asked %d!\n", ++ __func__, ep->dwc_ep.is_in, dir == UE_DIR_IN); ++ } ++ ++ type = UE_GET_XFERTYPE(ep_desc->bmAttributes); ++ maxpacket = UGETW(ep_desc->wMaxPacketSize); ++ ++ ep->dwc_ep.type = type; ++ ep->dwc_ep.maxpacket = maxpacket & 0x7ff; ++ ep->dwc_ep.intvl = 0; ++ ep->dwc_ep.mult = 0; ++ ep->dwc_ep.maxburst = 0; ++ ep->dwc_ep.num_streams = 0; ++ ep->dwc_ep.xfer_started = 0; ++ ++ if (pcd->speed == USB_SPEED_SUPER && ep_comp) ++ ep->dwc_ep.maxburst = ep_comp->bMaxBurst; ++ ++ switch (type) { ++ case UE_ISOCHRONOUS: ++ if (pcd->speed == USB_SPEED_SUPER && ep_comp) { ++ ep->dwc_ep.mult = USSE_GET_MAX_PACKET_NUM( ++ ep_comp->bmAttributes) + 1; ++ /* 3 packets at most */ ++ if (ep->dwc_ep.mult > 3) ++ return -DWC_E_INVALID; ++ } ++ /* FALL THRU */ ++ case UE_INTERRUPT: ++ if (pcd->speed == USB_SPEED_SUPER) { ++ ep->dwc_ep.intvl = ep_desc->bInterval - 1; ++ break; ++ } ++ ++ ep->dwc_ep.intvl = ep_desc->bInterval - 1; ++ ++ /* ++ * Bits 12:11 specify number of _additional_ ++ * packets per microframe. ++ */ ++ ep->dwc_ep.mult = (maxpacket >> 11 & 3) + 1; ++ ++ /* 3 packets at most */ ++ if (ep->dwc_ep.mult > 3) ++ return -DWC_E_INVALID; ++ ++ break; ++ ++ case UE_BULK: ++ if (pcd->speed == USB_SPEED_SUPER && ep_comp) ++ ep->dwc_ep.num_streams = ++ USSE_GET_MAX_STREAMS(ep_comp->bmAttributes); ++ ++ /* Set initial data PID */ ++ ep->dwc_ep.data_pid_start = 0; ++ break; ++ } ++ ++ dwc_debug5(pcd->usb3_dev, ++ "type=%u maxpkt=%u mult=%u maxbst=%u numstrm=%u\n", ++ type, maxpacket, ep->dwc_ep.mult, ep->dwc_ep.maxburst, ++ ep->dwc_ep.num_streams); ++ ++ dwc_usb3_ep_activate(pcd, ep, 0); ++ return 0; ++} ++ ++/** ++ * This routine is called when an EP (except EP0) is disabled due to ++ * disconnect or change in configuration. Any pending requests will ++ * terminate with a status of -ESHUTDOWN. ++ * ++ * This routine modifies the dwc_usb3_ep_t data structure for this EP, ++ * and then calls ep_deactivate. ++ */ ++int dwc_usb3_pcd_ep_disable(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep) ++{ ++ dwc_debug2(pcd->usb3_dev, "%s(%lx)\n", __func__, (unsigned long)ep); ++ dwc_debug2(pcd->usb3_dev, "ep=%lx is_in=%d\n", (unsigned long)ep, ++ ep->dwc_ep.is_in); ++ ++ if (!ep->dwc_ep.usb_ep_desc) ++ return -DWC_E_INVALID; ++ ++ ep_deactivate(ep->dwc_ep.pcd, ep); ++ dwc_usb3_gadget_request_nuke(pcd, ep); ++ ep->dwc_ep.usb_ep_desc = NULL; ++ ++ return 0; ++} ++ ++/** ++ * This routine submits an I/O Request to an EP. ++ * ++ * - When the request completes the request's completion callback is called ++ * to return the request to the driver. ++ * - An EP, except control EPs, may have multiple requests pending. ++ * - Once submitted the request cannot be examined or modified. ++ * - Each request is turned into one or more packets. ++ * - A BULK EP can queue any amount of data; the transfer is packetized. ++ * - Zero-length packets are specified with the request 'zero' flag. ++ */ ++int dwc_usb3_pcd_ep_submit_req(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep, ++ dwc_usb3_pcd_req_t *req, int req_flags) ++{ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ ++ /* EP0 Transfer? */ ++ if (ep == pcd->ep0) { ++ switch (pcd->ep0state) { ++ case EP0_IN_DATA_PHASE: ++ dwc_debug1(pcd->usb3_dev, "%s ep0: EP0_IN_DATA_PHASE\n", ++ __func__); ++ break; ++ ++ case EP0_OUT_DATA_PHASE: ++ dwc_debug1(pcd->usb3_dev, ++ "%s ep0: EP0_OUT_DATA_PHASE\n", __func__); ++ if (pcd->request_config) { ++ /* Complete STATUS PHASE */ ++ ep->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_WAIT_NRDY; ++ return 1; ++ } ++ ++ break; ++ ++ case EP0_IN_WAIT_GADGET: ++ dwc_debug1(pcd->usb3_dev, ++ "%s ep0: EP0_IN_WAIT_GADGET\n", __func__); ++ pcd->ep0state = EP0_IN_WAIT_NRDY; ++ return 2; ++ ++ case EP0_OUT_WAIT_GADGET: ++ dwc_debug1(pcd->usb3_dev, ++ "%s ep0: EP0_OUT_WAIT_GADGET\n", __func__); ++ pcd->ep0state = EP0_OUT_WAIT_NRDY; ++ return 3; ++ ++ case EP0_IN_WAIT_NRDY: ++ dwc_debug1(pcd->usb3_dev, "%s ep0: EP0_IN_WAIT_NRDY\n", ++ __func__); ++ pcd->ep0state = EP0_IN_STATUS_PHASE; ++ break; ++ ++ case EP0_OUT_WAIT_NRDY: ++ dwc_debug1(pcd->usb3_dev, "%s ep0: EP0_OUT_WAIT_NRDY\n", ++ __func__); ++ pcd->ep0state = EP0_OUT_STATUS_PHASE; ++ break; ++ ++ default: ++ dwc_print2(pcd->usb3_dev, "%s ep0: odd state %d!\n", ++ __func__, pcd->ep0state); ++ return -DWC_E_SHUTDOWN; ++ } ++ ++ ep->dwc_ep.send_zlp = 0; ++ ++ if ((req_flags & DWC_PCD_REQ_ZERO) && ++ req->dwc_req.length != 0 && ++ (req->dwc_req.length & ++ (ep->dwc_ep.maxpacket - 1)) == 0) { ++ ep->dwc_ep.send_zlp = 1; ++ } ++ ++ dwc_usb3_pcd_ep0_start_transfer(pcd, req); ++ ++#ifdef DWC_STAR_9000463548_WORKAROUND ++ if (pcd->configuring) { ++ dwc_usb3_pcd_ep_t *ept; ++ int i; ++ ++ pcd->configuring = 0; ++ ++ for (i = 0; i < pcd->num_in_eps; i++) { ++ ept = pcd->in_ep[i]; ++ if (ept->dwc_ep.active) ++ dwc_usb3_ep_activate(pcd, ept, 0); ++ } ++ ++ for (i = 0; i < pcd->num_out_eps; i++) { ++ ept = pcd->out_ep[i]; ++ if (ept->dwc_ep.active) ++ dwc_usb3_ep_activate(pcd, ept, 0); ++ } ++ } ++#endif ++ } else { ++ /* Setup and start the Transfer */ ++ dwc_usb3_pcd_ep_start_transfer(pcd, ep, req, 0); ++ } ++ ++ return 0; ++} ++ ++/** ++ * This routine cancels an I/O request from an EP. ++ */ ++void dwc_usb3_pcd_ep_cancel_req(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep, ++ dwc_usb3_pcd_req_t *req, u32 stream) ++{ ++ dwc_debug4(pcd->usb3_dev, "%s(%lx,%lx) stream %d\n", __func__, ++ (unsigned long)ep, (unsigned long)req, stream); ++ ++ dwc_usb3_dis_usb2_suspend(pcd); ++ dwc_usb3_stop_xfer(pcd, ep); ++ dwc_usb3_ena_usb2_suspend(pcd); ++ ++ ep->dwc_ep.xfer_started = 0; ++ dwc_usb3_pcd_request_done(pcd, ep, req, -DWC_E_DISCONNECT); ++} ++ ++/** ++ * usb_ep_set_halt stalls an endpoint. ++ * ++ * usb_ep_clear_halt clears an endpoint stall and resets its data toggle. ++ * ++ * Both of these routines are implemented with the same underlying routine. ++ * The behavior depends on the value argument. ++ * ++ * @param pcd The PCD structure. ++ * @param ep The endpoint to set halt or clear halt. ++ * @param value - 0 means clear_halt. ++ * - 1 means set_halt. ++ * - 2 means clear stall lock flag. ++ * - 3 means set stall lock flag. ++ */ ++void dwc_usb3_pcd_ep_set_halt(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep, ++ int value) ++{ ++ dwc_debug3(pcd->usb3_dev, "%s(%lx,%d)\n", __func__, ++ (unsigned long)ep, value); ++ ++ if (value == 0) { ++ ep->dwc_ep.stall_clear_flag = 0; ++ if (ep != pcd->ep0) ++ dwc_usb3_pcd_ep_clear_stall(pcd, ep); ++ ++ if (ep->dwc_ep.stopped) { ++ ep->dwc_ep.stopped = 0; ++ ++ /* If there is a request in the EP queue start it */ ++ if (ep != pcd->ep0 && ep->dwc_ep.is_in) ++ dwc_usb3_gadget_start_next_request(pcd, ep); ++ } ++ } else if (value == 1) { ++stall: ++ if (ep == pcd->ep0) { ++ ep->dwc_ep.is_in = 0; ++ dwc_usb3_pcd_ep_set_stall(pcd, ep); ++ pcd->ep0state = EP0_STALL; ++ } else { ++ dwc_usb3_pcd_ep_set_stall(pcd, ep); ++ } ++ ++ ep->dwc_ep.stopped = 1; ++ ++ } else if (value == 2) { ++ ep->dwc_ep.stall_clear_flag = 0; ++ ++ } else if (value == 3) { ++ ep->dwc_ep.stall_clear_flag = 1; ++ goto stall; ++ } ++} ++ ++/** ++ * This routine completes a request. It calls the request callback. ++ */ ++void dwc_usb3_pcd_request_done(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep, ++ dwc_usb3_pcd_req_t *req, int status) ++{ ++ unsigned stopped = ep->dwc_ep.stopped; ++ ++ dwc_debug4(pcd->usb3_dev, "%s(%lx,%lx,%d)\n", __func__, ++ (unsigned long)ep, (unsigned long)req, status); ++ ++// printk("\n###%s,%d,=0x%x\n",__func__,__LINE__,req->dwc_req); ++// printk("\n###%s,%d\n",__func__,__LINE__); ++ if (ep != pcd->ep0) { ++// printk("\n###%s,%d\n",__func__,__LINE__); ++ req->dwc_req.flags &= ~DWC_PCD_REQ_STARTED; ++// printk("\n###%s,%d\n",__func__,__LINE__); ++ if (req->dwc_req.trb) { ++ ++// printk("\n###%s,%d\n",__func__,__LINE__); ++ dwc_usb3_disable_desc(req->dwc_req.trb); ++// printk("\n###%s,%d\n",__func__,__LINE__); ++ ep->dwc_ep.desc_avail++; ++// printk("\n###%s,%d\n",__func__,__LINE__); ++ req->dwc_req.trb = NULL; ++ } ++ } ++ ++ /* don't modify queue heads during completion callback */ ++ ep->dwc_ep.stopped = 1; ++ ++ dwc_usb3_gadget_complete(pcd, ep, req, status); ++// printk("\n###%s,%d\n",__func__,__LINE__); ++ ++ //req->dwc_req.actual = 0; ++ ep->dwc_ep.stopped = stopped; ++// printk("\n###%s,%d\n",__func__,__LINE__); ++} ++ ++/** ++ * This routine is called when the Device is disconnected. It stops any ++ * active requests and informs the Function Driver of the disconnect. ++ */ ++void dwc_usb3_pcd_stop(dwc_usb3_pcd_t *pcd) ++{ ++ dwc_usb3_pcd_ep_t *ep; ++ int i; ++ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ ++ /* don't disconnect drivers more than once */ ++ if (pcd->state == DWC_STATE_UNCONNECTED) { ++ dwc_debug1(pcd->usb3_dev, "%s() Already Disconnected\n", ++ __func__); ++ } else { ++ pcd->state = DWC_STATE_UNCONNECTED; ++ ++ /* report disconnect; the driver is already quiesced */ ++ dwc_usb3_gadget_disconnect(pcd); ++ } ++ ++ dwc_usb3_dis_usb2_suspend(pcd); ++ ++ /* kill any outstanding requests, prevent new request submissions */ ++ for (i = 0; i < pcd->num_in_eps; i++) { ++ ep = pcd->in_ep[i]; ++ dwc_usb3_stop_xfer(pcd, ep); ++ dwc_usb3_gadget_request_nuke(pcd, ep); ++ ep->dwc_ep.xfer_started = 0; ++ } ++ ++ for (i = 0; i < pcd->num_out_eps; i++) { ++ ep = pcd->out_ep[i]; ++ dwc_usb3_stop_xfer(pcd, ep); ++ dwc_usb3_gadget_request_nuke(pcd, ep); ++ ep->dwc_ep.xfer_started = 0; ++ } ++ ++ dwc_usb3_ena_usb2_suspend(pcd); ++} ++ ++/** ++ * Gets the current USB frame number. ++ */ ++int dwc_usb3_pcd_get_frame_number(dwc_usb3_pcd_t *pcd) ++{ ++ return dwc_usb3_get_frame(pcd); ++} ++ ++/** ++ * Initialize the PCD EP structures to their default state. ++ * ++ * @param pcd The PCD structure. ++ */ ++static void pcd_epinit(dwc_usb3_pcd_t *pcd) ++{ ++ int num_out_eps = pcd->num_out_eps; ++ int num_in_eps = pcd->num_in_eps; ++ int ep_cntr, i; ++ dwc_usb3_pcd_ep_t *ep; ++ ++ dwc_debug2(pcd->usb3_dev, "%s(%lx)\n", __func__, (unsigned long)pcd); ++ dwc_debug1(pcd->usb3_dev, "num_out_eps=%d\n", num_out_eps); ++ dwc_debug1(pcd->usb3_dev, "num_in_eps=%d\n", num_in_eps); ++ ++ /* ++ * Initialize the EP0 structure ++ */ ++ ep = pcd->ep0; ++ ++ /* Init EP structure */ ++ ep->dwc_ep.dma_desc = NULL; ++ ep->dwc_ep.dma_desc_dma = 0; ++ ep->dwc_ep.usb_ep_desc = NULL; ++ ep->dwc_ep.pcd = pcd; ++ ep->dwc_ep.stopped = 1; ++ ep->dwc_ep.is_in = 0; ++ ep->dwc_ep.active = 0; ++ ep->dwc_ep.phys = 0; ++ ep->dwc_ep.num = 0; ++#ifdef DWC_UTE ++ pcd->txf_map[1] = 0; ++#endif ++ ep->dwc_ep.tx_fifo_num = 0; ++ ep->dwc_ep.out_ep_reg = &pcd->out_ep_regs[0]; ++ ep->dwc_ep.in_ep_reg = &pcd->in_ep_regs[0]; ++ ++ ep->dwc_ep.type = DWC_USB3_EP_TYPE_CONTROL; ++ ep->dwc_ep.maxpacket = DWC_MAX_EP0_SIZE; ++ ep->dwc_ep.send_zlp = 0; ++ ep->dwc_ep.queue_sof = 0; ++ ++ pcd->ep0_req->dwc_req.buf[0] = NULL; ++ pcd->ep0_req->dwc_req.bufdma[0] = 0; ++ pcd->ep0_req->dwc_req.buflen[0] = 0; ++ pcd->ep0_req->dwc_req.length = 0; ++ pcd->ep0_req->dwc_req.actual = 0; ++ ++ /* ++ * Initialize the EP1-n structures ++ */ ++ ep_cntr = 0; ++ ++ for (i = 1; ep_cntr < num_out_eps; i++) { ++ dwc_debug2(pcd->usb3_dev, ++ "initializing EP%d-OUT (out_ep[%d])\n", i, ep_cntr); ++ ep = pcd->out_ep[ep_cntr]; ++ ep_cntr++; ++ ++ /* Init EP structure - but don't overwrite '.num', the gadget ++ * has already set that ++ */ ++ ep->dwc_ep.dma_desc = NULL; ++ ep->dwc_ep.dma_desc_dma = 0; ++ ep->dwc_ep.usb_ep_desc = NULL; ++ ep->dwc_ep.pcd = pcd; ++ ep->dwc_ep.stopped = 1; ++ ep->dwc_ep.is_in = 0; ++ ep->dwc_ep.active = 0; ++ ep->dwc_ep.phys = ep_cntr << 1; ++ ep->dwc_ep.tx_fifo_num = 0; ++ ep->dwc_ep.out_ep_reg = &pcd->out_ep_regs[ep_cntr]; ++ ++ /* Control until EP is activated */ ++ ep->dwc_ep.type = DWC_USB3_EP_TYPE_CONTROL; ++ ep->dwc_ep.maxpacket = DWC_MAX_EP0_SIZE; ++ ep->dwc_ep.send_zlp = 0; ++ ep->dwc_ep.queue_sof = 0; ++ } ++ ++ ep_cntr = 0; ++ ++ for (i = 1; ep_cntr < num_in_eps; i++) { ++ dwc_debug2(pcd->usb3_dev, ++ "initializing EP%d-IN (in_ep[%d])\n", i, ep_cntr); ++ ep = pcd->in_ep[ep_cntr]; ++ ep_cntr++; ++ ++ /* Init EP structure - but don't overwrite '.num', the gadget ++ * has already set that ++ */ ++ ep->dwc_ep.dma_desc = NULL; ++ ep->dwc_ep.dma_desc_dma = 0; ++ ep->dwc_ep.usb_ep_desc = NULL; ++ ep->dwc_ep.pcd = pcd; ++ ep->dwc_ep.stopped = 1; ++ ep->dwc_ep.is_in = 1; ++ ep->dwc_ep.active = 0; ++ ep->dwc_ep.phys = ep_cntr << 1 | 1; ++#ifdef DWC_UTE ++ pcd->txf_map[ep_cntr << 1 | 1] = ep_cntr; ++#endif ++ ep->dwc_ep.tx_fifo_num = ep_cntr; ++ ep->dwc_ep.in_ep_reg = &pcd->in_ep_regs[ep_cntr]; ++ ++ /* Control until EP is activated */ ++ ep->dwc_ep.type = DWC_USB3_EP_TYPE_CONTROL; ++ ep->dwc_ep.maxpacket = DWC_MAX_EP0_SIZE; ++ ep->dwc_ep.send_zlp = 0; ++ ep->dwc_ep.queue_sof = 0; ++ } ++ ++ pcd->ep0state = EP0_IDLE; ++ pcd->ep0->dwc_ep.maxpacket = DWC_MAX_EP0_SIZE; ++ pcd->ep0->dwc_ep.type = DWC_USB3_EP_TYPE_CONTROL; ++} ++ ++/** ++ * Initialize the PCD portion of the driver. ++ * ++ * This routine should be called after dwc_usb3_pcd_common_init() and any ++ * platform-specific initialization routines have been called. ++ * ++ * This routine must be called in a context that allows dwc_msleep() ++ * to be used, because that function is called while waiting for the core to ++ * come out of reset. ++ * ++ * @param dev Programming view of DWC_usb3 controller. ++ */ ++int dwc_usb3_pcd_init(dwc_usb3_device_t *dev) ++{ ++ dwc_debug1(dev, "%s()\n", __func__); ++ ++ dev->pcd.usb3_dev = dev; ++ dev->pcd.speed = USB_SPEED_UNKNOWN; ++ ++ /* ++ * Initialize EP structures ++ */ ++ pcd_epinit(&dev->pcd); ++ ++ /* ++ * Initialize the Core (also enables interrupts and sets Run/Stop bit) ++ */ ++ dwc_usb3_pcd_device_init(dev, 1, 0); ++ ++ return 0; ++} ++ ++/** ++ * Deinitialize the PCD portion of the driver. ++ * ++ * This routine should be called before any platform-specific deinitialization ++ * routines and dwc_usb3_pcd_common_remove() are called. ++ * ++ * @param dev Programming view of DWC_usb3 controller. ++ */ ++void dwc_usb3_pcd_remove(dwc_usb3_device_t *dev) ++{ ++ dwc_debug1(dev, "%s()\n", __func__); ++ ++ dwc_usb3_pcd_device_remove(dev); ++} +diff --git a/drivers/usb/gadget/udc/hiudc3/pcd.h b/drivers/usb/gadget/udc/hiudc3/pcd.h +new file mode 100644 +index 0000000..a71bc86 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/pcd.h +@@ -0,0 +1,658 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/DWC_usb3/driver/pcd.h $ ++ * $Revision: #71 $ ++ * $Date: 2014/11/11 $ ++ * $Change: 2664766 $ ++ * ++ * Synopsys SS USB3 Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 _DWC_PCD_H_ ++#define _DWC_PCD_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * @file ++ * ++ * This file contains the structures, constants, and interfaces for ++ * the Perpherial Contoller Driver (PCD). ++ * ++ * The Peripheral Controller Driver (PCD) for Linux will implement the ++ * Gadget API, so that the existing Gadget drivers can be used. For ++ * the Mass Storage function, the File-backed USB Storage Gadget (FBS) ++ * driver will be used. The FBS driver supports the Control-Bulk (CB), ++ * Control-Bulk-Interrupt (CBI), and Bulk-Only transports. ++ * ++ */ ++ ++/** Maximum number of Tx FIFOs. Depends on the RTL configuration. No way to ++ * probe the value at runtime ++ */ ++#define DWC_MAX_TX_FIFOS 16 ++ ++/** Maximum number of physical EPs. Depends on the RTL configuration. No way to ++ * probe the value at runtime ++ */ ++#define DWC_MAX_PHYS_EP 32 ++ ++/** Maximum number of data buffers per TRB. OS/application specific */ ++#define DWC_MAX_DATA_BUFS 13 ++ ++/** Maximum number of EPs, defined by USB spec */ ++#define DWC_MAX_EPS 16 ++ ++/** Maxpacket size for EP0, defined by USB3 spec */ ++#define DWC_MAX_EP0_SIZE 512 ++ ++/** Maxpacket size for any EP, defined by USB3 spec */ ++#define DWC_MAX_PACKET_SIZE 1024 ++ ++/** ++ * States of EP0 ++ */ ++typedef enum ep0_state { ++ EP0_IDLE, ++ EP0_IN_DATA_PHASE, ++ EP0_OUT_DATA_PHASE, ++ EP0_IN_WAIT_GADGET, ++ EP0_OUT_WAIT_GADGET, ++ EP0_IN_WAIT_NRDY, ++ EP0_OUT_WAIT_NRDY, ++ EP0_IN_STATUS_PHASE, ++ EP0_OUT_STATUS_PHASE, ++ EP0_STALL, ++} ep0state_e; ++ ++typedef enum pcd_state { ++ DWC_STATE_UNCONNECTED, /* no host */ ++ DWC_STATE_DEFAULT, ++ DWC_STATE_ADDRESSED, ++ DWC_STATE_CONFIGURED, ++} pcdstate_e; ++ ++struct dwc_usb3_device; ++struct dwc_usb3_pcd; ++ ++/** ++ * The dwc_req structure represents the state of a single ++ * transfer request when acting in device mode. It contains the data items ++ * needed for a request to be started and completed. ++ */ ++typedef struct dwc_req { ++ dwc_usb3_dma_desc_t *trb; /**< TRB or TRB chain for this req */ ++ dwc_dma_t trbdma; /**< DMA address of TRB or TRB chain */ ++ u32 length; /**< total length of data bufs */ ++ u32 actual; /**< actual amt of data transferred */ ++ u32 stream; /**< stream # of this request */ ++ ++ int flags; /**< request flags - bits 8-31 are OS-specific */ ++#define DWC_PCD_REQ_ZERO 0x001 ++#define DWC_PCD_REQ_STARTED 0x002 ++#define DWC_PCD_REQ_MAP_DMA 0x100 ++#define DWC_PCD_REQ_IN 0x200 ++ ++ int numbuf; /**< number of data bufs */ ++ char *buf[DWC_MAX_DATA_BUFS]; /**< data buffers */ ++ dwc_dma_t bufdma[DWC_MAX_DATA_BUFS]; /**< DMA addrs of data bufs */ ++ u32 buflen[DWC_MAX_DATA_BUFS]; /**< length of data bufs */ ++} dwc_req_t; ++ ++/** DWC_usb3 request structure. ++ * This structure is used to form a list of requests. ++ */ ++typedef struct dwc_usb3_pcd_req { ++ /** DWC_usb3 request data */ ++ dwc_req_t dwc_req; ++ ++ /* ==== The rest is OS-specific ==== */ ++ ++ /** List entry for EP queue */ ++#if defined(__linux__) || defined(SELA_PLATFORM) ++ struct list_head entry; ++#else ++ DWC_CIRCLEQ_ENTRY(dwc_usb3_pcd_req) entry; ++#endif ++ /** USB request */ ++ struct usb_request usb_req; ++} dwc_usb3_pcd_req_t; ++ ++/** ++ * The dwc_ep structure represents the state of a single EP ++ * when acting in device mode. It contains the data items needed for an EP ++ * to be activated and transfer packets. ++ */ ++typedef struct dwc_ep { ++ /** Pointer to PCD */ ++ struct dwc_usb3_pcd *pcd; ++ ++ /** Pointer to OUT EP register */ ++ dwc_usb3_dev_ep_regs_t __iomem *out_ep_reg; ++ ++ /** Pointer to IN EP register */ ++ dwc_usb3_dev_ep_regs_t __iomem *in_ep_reg; ++ ++ /** Physical EP number */ ++ u8 phys; ++ ++ /** USB EP number */ ++ u8 num; ++ ++ /** EP type: 0 - Control, 1 - ISOC, 2 - BULK, 3 - INTR */ ++ u8 type; ++ ++ /** 'bInterval' value for Isoc EPs */ ++ u8 intvl; ++ ++ /** Max Packet bytes */ ++ u16 maxpacket; ++ ++ /** 'mult' value for SS Isoc EPs */ ++ u8 mult; ++ ++ /** Max burst size for SS EPs (0 - 15, actual burst is 1 - 16) */ ++ u8 maxburst; ++ ++ /** Number of streams for SS Bulk EPs (0 - 16, actual number is 2^n) */ ++ u8 num_streams; ++ ++ /** Tx FIFO # for IN EPs */ ++ u8 tx_fifo_num; ++ ++ /** @{ */ ++ /** Transfer Resource Index from the Start Transfer command */ ++ u8 tri_out; ++ u8 tri_in; ++ /** @} */ ++ ++ /** @{ */ ++ /** Status of the queue */ ++ unsigned int stopped : 1; ++ unsigned int disabling : 1; ++ unsigned int queue_sof : 1; ++ /** @} */ ++ ++ /** @{ */ ++ /** Send ZLP */ ++ unsigned int send_zlp : 1; ++ ++ /** Stall clear flag */ ++ unsigned int stall_clear_flag : 1; ++ ++ /** True if 3-stage control transfer */ ++ unsigned int three_stage : 1; ++ ++ /** True if transfer has been started on EP */ ++ unsigned int xfer_started : 1; ++ /** @} */ ++ ++ /** EP direction 0 = OUT */ ++ unsigned int is_in : 1; ++ ++ /** EP active */ ++ unsigned int active : 1; ++ ++ /** True if TRB array has a link TRB at the end */ ++ unsigned int desc_link : 1; ++ ++ /** DATA start PID for INTR and BULK EP */ ++ unsigned int data_pid_start : 1; ++ ++ /** EP has been enabled for this configuration */ ++ unsigned int ena_once : 1; ++ ++ /** EP was in stalled state when entering hibernation */ ++ unsigned int stalled_save : 1; ++ ++ /** @{ */ ++ /** Saved parameters from the last DEPCFG for this EP. Used when ++ * resetting the sequence number ++ */ ++ u32 param0out; ++ u32 param1out; ++ u32 param0in; ++ u32 param1in; ++ /** @} */ ++ ++ /** EP state, saved across core hibernation */ ++ u32 save_state; ++ ++ /** Pointer to USB EP descriptor */ ++ const usb_endpoint_descriptor_t *usb_ep_desc; ++ ++ /** @{ */ ++ /** Array of DMA descriptors (TRBs) for this EP */ ++ dwc_usb3_dma_desc_t *dma_desc; ++ dwc_dma_t dma_desc_dma; ++ int desc_size; ++ int num_desc; ++ /** @} */ ++ ++ /** Number of DMA descriptors available */ ++ int desc_avail; ++ ++ /** Index to next free DMA descriptor in array */ ++ int desc_idx; ++ ++ /** Index to DMA descriptor that was active before hibernation */ ++ int hiber_desc_idx; ++ ++ /* ==== The rest is OS-specific ==== */ ++ ++ /** Condition variable for EPCMD_CMPL interrupt */ ++ u32 condition; ++ ++ /** Queue of dwc_usb3_pcd_reqs */ ++#if defined(__linux__) || defined(SELA_PLATFORM) ++ struct list_head queue; ++#else ++ DWC_CIRCLEQ_HEAD(circleq, dwc_usb3_pcd_req) queue; ++#endif ++} dwc_ep_t; ++ ++/** PCD EP structure. ++ * This structure describes an EP, there is an array of EP pointers in the ++ * PCD structure. ++ */ ++typedef struct dwc_usb3_pcd_ep { ++ /** DWC_usb3 EP data */ ++ dwc_ep_t dwc_ep; ++ ++ /* ==== The rest is OS-specific ==== */ ++ ++ /** USB EP */ ++ struct usb_ep usb_ep; ++} dwc_usb3_pcd_ep_t; ++ ++/** @{ */ ++/** PCD EP accessor functions */ ++#define dwc_usb3_pcd_ep_to_pcd(pcd_ep) ((pcd_ep)->dwc_ep.pcd) ++#define dwc_usb3_pcd_ep_num(pcd_ep) ((pcd_ep)->dwc_ep.num) ++#define dwc_usb3_pcd_ep_type(pcd_ep) ((pcd_ep)->dwc_ep.type) ++#define dwc_usb3_pcd_ep_is_in(pcd_ep) ((pcd_ep)->dwc_ep.is_in) ++/** @} */ ++ ++struct dwc_hiber_scratchpad_array { ++ u64 dma_addr[15]; ++}; ++ ++/** DWC_usb3 PCD Structure. ++ * This structure encapsulates the data for the dwc_usb3 PCD. ++ */ ++typedef struct dwc_usb3_pcd { ++ /** The DWC otg device pointer */ ++ struct dwc_usb3_device *usb3_dev; ++ ++ /** USB3 link state */ ++ int link_state; ++ ++ /** State of the device */ ++ pcdstate_e state; ++ ++ /** State of EP0 */ ++ ep0state_e ep0state; ++ ++ /** EP0 Status Request is pending */ ++ unsigned int ep0_status_pending : 1; ++ ++ /** Indicates when SET CONFIGURATION Request is in process */ ++ unsigned int request_config : 1; ++ ++ /** State of the Remote Wakeup Enable */ ++ unsigned int remote_wakeup_enable : 1; ++ ++ /** State of the Latency Tolerance Messaging Enable */ ++ unsigned int ltm_enable : 1; ++ ++ /** True if we should send an LPM notification after the status stage */ ++ unsigned int send_lpm : 1; ++ ++ /** True if ready for remote wakeup request from user */ ++ unsigned int wkup_rdy : 1; ++ ++ /** True if we have enabled some EPs */ ++ unsigned int eps_enabled : 1; ++ ++ /** True if UTE has made some config changes */ ++ unsigned int ute_change : 1; ++ ++#ifdef DWC_STAR_9000463548_WORKAROUND ++ unsigned int configuring : 1; ++#endif ++ ++#ifdef CONFIG_USB_OTG_DWC ++ /** Set when user writes to 'hnp' sysfs attribute */ ++ unsigned int wants_host : 1; ++ ++ /** For set feature (b_hnp_enable) */ ++ unsigned int b_hnp_enable : 1; ++#endif ++ /** EP0 */ ++ dwc_usb3_pcd_ep_t *ep0; ++ ++ /** Array of OUT EPs (not including EP0) */ ++ dwc_usb3_pcd_ep_t *out_ep[DWC_MAX_EPS - 1]; ++ ++ /** Array of IN EPs (not including EP0) */ ++ dwc_usb3_pcd_ep_t *in_ep[DWC_MAX_EPS - 1]; ++ ++ /** Pointer to device Global registers. ++ * Device Global Registers starting at offset 700h ++ */ ++ dwc_usb3_dev_global_regs_t __iomem *dev_global_regs; ++ ++ /** Device Logical OUT EP-Specific Registers 800h-9ECh */ ++ dwc_usb3_dev_ep_regs_t __iomem *out_ep_regs; ++ ++ /** Device Logical IN EP-Specific Registers 810h-9FCh */ ++ dwc_usb3_dev_ep_regs_t __iomem *in_ep_regs; ++ ++ /** @{ */ ++ /** Scratchpad buffers for hibernation support */ ++ void *hiber_scratchpad[15]; ++ struct dwc_hiber_scratchpad_array *hiber_scratchpad_array; ++ dwc_dma_t hiber_scratchpad_array_dma; ++ /** @} */ ++ ++ /** @{ */ ++ /** EP0 state, saved across core hibernation */ ++ u32 ep0_out_save_state; ++ u32 ep0_in_save_state; ++ /** @} */ ++ ++ /** 'dummy' request, for EP0 only */ ++ dwc_usb3_pcd_req_t *ep0_req; ++ ++#ifdef DWC_UTE ++ /** size of Rx FIFO, requested by UTE */ ++ unsigned rxf_size; ++ ++ /** size of Tx FIFOs, requested by UTE */ ++ unsigned txf_size[DWC_MAX_TX_FIFOS]; ++ ++ /** mapping of Tx FIFO for each physical EP, requested by UTE */ ++ unsigned txf_map[DWC_MAX_PHYS_EP]; ++ ++ /** Rx FIFO default size */ ++ unsigned def_rxf_size; ++ ++ /** Tx FIFOs, default size */ ++ unsigned def_txf_size[DWC_MAX_TX_FIFOS]; ++#endif ++ ++ /** @{ */ ++ /** Thresholding enable flags and length variables */ ++ u16 rx_thr_en; ++ u16 iso_tx_thr_en; ++ u16 non_iso_tx_thr_en; ++ u16 rx_thr_length; ++ u16 tx_thr_length; ++ /** @} */ ++ ++ /** Device configuration information */ ++ u8 speed; /**< Device Speed - 0:Unk 1:LS 2:FS 3:HS 4:Var 5:SS */ ++ u8 num_out_eps; /**< Number # of Rx EP range: 0-15 except ep0 */ ++ u8 num_in_eps; /**< Number # of Tx EP range: 0-15 except ep0 */ ++ ++ /** The TEST mode to enter when test_mode_tasklet is executed */ ++ u8 test_mode; ++ ++ /** Count of pending Requests */ ++ unsigned request_pending; ++ ++ /* ==== The rest is OS-specific ==== */ ++#ifdef SELA_PLATFORM ++ /** Limit the number of EPs to speed up simulation */ ++ int max_in_eps, max_out_eps; ++ ++ /** Pointers for passing event codes back to the test code */ ++ int *dev_event, *ep_event; ++#endif ++#if defined(__linux__) || defined(LINUXTEST) ++ /** The spinlock for the PCD */ ++ spinlock_t lock; ++#endif ++#ifdef __linux__ ++ /** The associated gadget */ ++ struct usb_gadget *gadget; ++#endif ++ /** Tasklet to defer starting of TEST mode transmissions until ++ * Status Phase has been completed ++ */ ++ struct tasklet_struct test_mode_tasklet; ++ ++ /** ++ * Pointers to the DMA Descriptors for EP0 Control transfers ++ * (virtual and physical) ++ */ ++ ++ /** @{ */ ++ /** Descriptor for SETUP packets */ ++ dwc_usb3_dma_desc_t *ep0_setup_desc; ++ dwc_dma_t ep0_setup_desc_dma; ++ /** @} */ ++ ++ /** @{ */ ++ /** Descriptor for Data Out or Status Out phases */ ++ dwc_usb3_dma_desc_t *ep0_out_desc; ++ dwc_dma_t ep0_out_desc_dma; ++ /** @} */ ++ ++ /** @{ */ ++ /** Descriptor for Data In or Status In phases */ ++ dwc_usb3_dma_desc_t *ep0_in_desc; ++ dwc_dma_t ep0_in_desc_dma; ++ /** @} */ ++ ++ /** @{ */ ++ /** Data packet buffer used to return data for GET_STATUS and ++ * GET_DESCRIPTOR(BOS) up to 512 bytes in length ++ */ ++ u8 *ep0_status_buf; ++ dwc_dma_t ep0_status_buf_dma; ++#define DWC_STATUS_BUF_SIZE 512 ++ /** @} */ ++ ++ /** @{ */ ++ /** SETUP packet buffer for EP0 */ ++ union dwc_setup_pkt { ++ usb_device_request_t req; ++ u32 d32[2]; ++ char d8[8]; ++ } *ep0_setup_pkt; ++ dwc_dma_t ep0_setup_pkt_dma; ++ /** @} */ ++} dwc_usb3_pcd_t; ++ ++/** @{ */ ++/** PCD accessor functions */ ++#define dwc_usb3_ep0_setup_desc(pcd) (pcd)->ep0_setup_desc ++#define dwc_usb3_ep0_setup_desc_dma(pcd) (pcd)->ep0_setup_desc_dma ++#define dwc_usb3_ep0_out_desc(pcd) (pcd)->ep0_out_desc ++#define dwc_usb3_ep0_out_desc_dma(pcd) (pcd)->ep0_out_desc_dma ++#define dwc_usb3_ep0_in_desc(pcd) (pcd)->ep0_in_desc ++#define dwc_usb3_ep0_in_desc_dma(pcd) (pcd)->ep0_in_desc_dma ++#define dwc_usb3_ep0_setup_pkt(pcd) (pcd)->ep0_setup_pkt ++#define dwc_usb3_ep0_setup_pkt_dma(pcd) (pcd)->ep0_setup_pkt_dma ++/** @} */ ++ ++extern void dwc_usb3_ep0_activate(dwc_usb3_pcd_t *pcd, int restore); ++extern void dwc_usb3_ep_activate(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep, ++ int restore); ++extern void dwc_usb3_stop_all_xfers(dwc_usb3_pcd_t *pcd); ++extern void dwc_usb3_complete_request(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep, u32 event); ++extern dwc_usb3_pcd_ep_t *dwc_usb3_get_out_ep(dwc_usb3_pcd_t *pcd, u32 ep_num); ++extern dwc_usb3_pcd_ep_t *dwc_usb3_get_in_ep(dwc_usb3_pcd_t *pcd, u32 ep_num); ++extern void dwc_usb3_handle_ep0_xfer(dwc_usb3_pcd_t *pcd, u32 event); ++#ifdef DEBUG_EP0 ++extern void dwc_usb3_print_ep0_state(dwc_usb3_pcd_t *pcd); ++#endif ++extern void dwc_usb3_handle_ep_intr(dwc_usb3_pcd_t *pcd, int physep, u32 event); ++extern int dwc_usb3_handle_dev_intr(dwc_usb3_pcd_t *pcd, u32 event); ++extern void dwc_usb3_handle_connect_done_intr(dwc_usb3_pcd_t *pcd); ++extern void dwc_enter_hibernation(dwc_usb3_pcd_t *pcd, int save_state); ++extern void dwc_exit_hibernation_after_connect(dwc_usb3_pcd_t *pcd, ++ int connected); ++extern int dwc_exit_hibernation(dwc_usb3_pcd_t *pcd, int restore_state); ++extern int dwc_usb3_handle_pme_intr(struct dwc_usb3_device *dev); ++extern void dwc_usb3_power_ctl(struct dwc_usb3_device *dev, int on); ++ ++/** @addtogroup init_api_grp */ ++/** @{ */ ++extern int dwc_usb3_pcd_init(struct dwc_usb3_device *dev); ++extern void dwc_usb3_pcd_remove(struct dwc_usb3_device *dev); ++/** @} */ ++ ++/** @addtogroup trb_api_grp TRB API Routines ++ * ++ * These routines handle the allocation, deallocation, and setup of TRBs. ++ */ ++/** @{ */ ++extern dwc_usb3_dma_desc_t *dwc_usb3_pcd_trb_alloc(dwc_usb3_pcd_ep_t *ep, ++ int num_trbs, int trb_type, int iso_intvl, int link, ++ dwc_dma_t *trbs_dma_ret); ++extern void dwc_usb3_pcd_trb_free(dwc_usb3_pcd_ep_t *ep /*, int num_trbs, int link, ++ void *trbs, dwc_dma_t trbs_dma*/); ++extern void dwc_usb3_pcd_fill_trbs(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep, ++ dwc_usb3_pcd_req_t *req); ++/** @} */ ++ ++/** @addtogroup ep_api_grp Endpoint API Routines ++ * ++ * These routines handle all the functionality required for configuring, ++ * enabling, controlling, and submitting transfers to an endpoint\n\n ++ * Note: For Control endpoint 0, only the submit_req, cancel_req, request_done, ++ * and set_halt routines are used; the remaining functionality is handled either ++ * by the @ref ep0_api_grp below or internally by the PCD. ++ */ ++/** @{ */ ++extern int dwc_usb3_pcd_ep_enable(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep, ++ const usb_endpoint_descriptor_t *ep_desc, ++ const ss_endpoint_companion_descriptor_t *ep_comp); ++extern int dwc_usb3_pcd_ep_disable(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep); ++extern int dwc_usb3_pcd_ep_submit_req(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep, ++ dwc_usb3_pcd_req_t *req, int req_flags); ++extern void dwc_usb3_pcd_ep_cancel_req(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep, ++ dwc_usb3_pcd_req_t *req, u32 stream); ++extern void dwc_usb3_pcd_request_done(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep, ++ dwc_usb3_pcd_req_t *req, int status); ++extern void dwc_usb3_pcd_ep_start_transfer(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep, ++ dwc_usb3_pcd_req_t *req, u32 event); ++extern void dwc_usb3_pcd_ep_set_stall(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep); ++extern void dwc_usb3_pcd_ep_clear_stall(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep); ++extern void dwc_usb3_pcd_ep_set_halt(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep, ++ int value); ++/** @} */ ++ ++/** @addtogroup ep0_api_grp Control Endpoint 0 API Routines ++ * ++ * These routines are only used for Control endpoint 0. ++ */ ++/** @{ */ ++extern void dwc_usb3_pcd_do_setup(dwc_usb3_pcd_t *pcd); ++extern void dwc_usb3_pcd_ep0_out_start(dwc_usb3_pcd_t *pcd); ++extern void dwc_usb3_pcd_ep0_start_transfer(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_req_t *req); ++extern void dwc_usb3_pcd_ep0_continue_transfer(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_req_t *req); ++extern void dwc_usb3_pcd_ep0_data_stage(dwc_usb3_pcd_t *pcd, int length); ++/** @} */ ++ ++/** @addtogroup misc_api_grp Miscellaneous API Routines ++ * ++ * These are miscellaneous routines that don't fit into any of the other ++ * categories. ++ */ ++/** @{ */ ++extern dwc_usb3_pcd_ep_t *dwc_usb3_pcd_get_ep_by_addr(dwc_usb3_pcd_t *pcd, ++ u16 index); ++extern int dwc_usb3_pcd_get_frame_number(dwc_usb3_pcd_t *pcd); ++extern int dwc_usb3_pcd_isoc_ep_hiber_restart(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep); ++extern void dwc_usb3_pcd_stop(dwc_usb3_pcd_t *pcd); ++/** @} */ ++ ++/** @addtogroup gadget_notif_grp Function Driver notification routines ++ * ++ * These routines receive notifications from the PCD when certain events occur ++ * which the Function Driver may need to be aware of. ++ */ ++/** @{ */ ++extern int dwc_usb3_gadget_connect(dwc_usb3_pcd_t *pcd, int speed); ++extern int dwc_usb3_gadget_disconnect(dwc_usb3_pcd_t *pcd); ++extern int dwc_usb3_gadget_suspend(dwc_usb3_pcd_t *pcd); ++extern int dwc_usb3_gadget_resume(dwc_usb3_pcd_t *pcd); ++extern int dwc_usb3_gadget_setup(dwc_usb3_pcd_t *pcd, ++ usb_device_request_t *ctrl); ++extern int dwc_usb3_gadget_complete(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *ep, ++ dwc_usb3_pcd_req_t *pcd_req, int status); ++extern void dwc_usb3_gadget_do_setup(dwc_usb3_pcd_t *pcd); ++/** @} */ ++ ++/** @addtogroup gadget_callbk_grp Function Driver callback routines ++ * ++ * The PCD calls these routines when it needs something from the Function ++ * Driver. ++ */ ++/** @{ */ ++extern void *dwc_usb3_gadget_alloc_dma(dwc_usb3_pcd_ep_t *ep, int size, ++ dwc_dma_t *mem_dma_ret); ++extern void dwc_usb3_gadget_free_dma(dwc_usb3_pcd_ep_t *ep, int size, void *mem, ++ dwc_dma_t mem_dma); ++extern dwc_usb3_pcd_req_t *dwc_usb3_gadget_get_request(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep); ++extern void dwc_usb3_gadget_start_next_request(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep); ++extern void dwc_usb3_gadget_isoc_ep_start(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep, u32 event); ++extern void dwc_usb3_gadget_request_nuke(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep); ++extern void dwc_usb3_gadget_set_ep_not_started(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep); ++/** @} */ ++ ++/* OS-specific routines called from core code */ ++extern void dwc_usb3_task_schedule(struct tasklet_struct *tasklet); ++ ++#ifdef CONFIG_USB_OTG_DWC ++extern void dwc_usb3_start_hnp(dwc_usb3_pcd_t *pcd); ++extern void dwc_usb3_host_release(dwc_usb3_pcd_t *pcd); ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_PCD_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc3/pcd_hiber.c b/drivers/usb/gadget/udc/hiudc3/pcd_hiber.c +new file mode 100644 +index 0000000..d401ef1 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/pcd_hiber.c +@@ -0,0 +1,679 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/DWC_usb3/driver/pcd_hiber.c $ ++ * $Revision: #16 $ ++ * $Date: 2014/11/11 $ ++ * $Change: 2664766 $ ++ * ++ * Synopsys SS USB3 Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++/** @file ++ * This file contains the PCD hibernation code. ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++ ++/** ++ * This routine sends the core into hibernation, saving the core's runtime ++ * state if requested. ++ */ ++void dwc_enter_hibernation(dwc_usb3_pcd_t *pcd, int save_state) ++{ ++ dwc_usb3_device_t *dev = pcd->usb3_dev; ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg; ++ dwc_usb3_pcd_ep_t *ep; ++ int num_in_eps, num_out_eps, i; ++ u32 temp; ++ ++ dwc_debug2(dev, "%s(%d)\n", __func__, save_state); ++ num_in_eps = pcd->num_in_eps; ++ num_out_eps = pcd->num_out_eps; ++ ++ dev->hiber_wait_u0 = 0; ++ dwc_usb3_dis_usb2_suspend(pcd); ++ ++ /* Issue an "End Transfer" command for all active transfers with the ++ * ForceRM field set to 0, including the default control endpoint 0. ++ */ ++ ep = pcd->ep0; ++ if (ep->dwc_ep.active) { ++ if (ep->dwc_ep.tri_in) { ++ dwc_debug0(dev, "EndXfer on phys EP1 (IN)\n"); ++ ep_reg = ep->dwc_ep.in_ep_reg; ++ ep->dwc_ep.condition = 0; ++ dwc_usb3_dep_endxfer(pcd, ep_reg, ep->dwc_ep.tri_in - 1, ++ 0, &ep->dwc_ep.condition); ++ ep->dwc_ep.tri_in = 0; ++ } ++ ++ if (ep->dwc_ep.tri_out) { ++ dwc_debug0(dev, "EndXfer on phys EP0 (OUT)\n"); ++ ep_reg = ep->dwc_ep.out_ep_reg; ++ ep->dwc_ep.condition = 0; ++ dwc_usb3_dep_endxfer(pcd, ep_reg, ep->dwc_ep.tri_out - 1, ++ 0, &ep->dwc_ep.condition); ++ ep->dwc_ep.tri_out = 0; ++ } ++ } ++ ++ for (i = 0; i < num_in_eps; i++) { ++ ep = pcd->in_ep[i]; ++ if (ep->dwc_ep.active && ep->dwc_ep.tri_in) { ++ dwc_debug1(dev, "EndXfer on phys EP%d (IN)\n", ++ i * 2 + 3); ++ ep_reg = ep->dwc_ep.in_ep_reg; ++ ep->dwc_ep.condition = 0; ++ dwc_usb3_dep_endxfer(pcd, ep_reg, ep->dwc_ep.tri_in - 1, ++ 0, &ep->dwc_ep.condition); ++ ep->dwc_ep.tri_in = 0; ++ } ++ ep->dwc_ep.xfer_started = 0; ++ } ++ ++ for (i = 0; i < num_out_eps; i++) { ++ ep = pcd->out_ep[i]; ++ if (ep->dwc_ep.active && ep->dwc_ep.tri_out) { ++ dwc_debug1(dev, "EndXfer on phys EP%d (OUT)\n", ++ i * 2 + 2); ++ ep_reg = ep->dwc_ep.out_ep_reg; ++ ep->dwc_ep.condition = 0; ++ dwc_usb3_dep_endxfer(pcd, ep_reg, ep->dwc_ep.tri_out - 1, ++ 0, &ep->dwc_ep.condition); ++ ep->dwc_ep.tri_out = 0; ++ } ++ ep->dwc_ep.xfer_started = 0; ++ } ++ ++ if (save_state) { ++ dwc_debug0(dev, "Saving state - 1\n"); ++ ++ /* Issue a "Get Endpoint State" endpoint command for each active ++ * endpoint, and save the bits that are returned for use after ++ * coming out of hibernation. ++ * ++ * In addition, software must remember if the endpoint is ++ * currently in a Halted state. The endpoint is in a Halted ++ * state if software has issued a "Set STALL" command and has ++ * not issued a "Clear STALL" command. ++ */ ++ ep = pcd->ep0; ++ if (ep->dwc_ep.active) { ++ dwc_debug0(dev, "Saving state of phys EP1 (IN)\n"); ++ ep_reg = ep->dwc_ep.in_ep_reg; ++ pcd->ep0_in_save_state = ++ dwc_usb3_dep_getepstate(pcd, ep_reg); ++ dwc_debug1(dev, "IN save state=%08x\n", ++ pcd->ep0_in_save_state); ++ dwc_debug0(dev, "Saving state of phys EP0 (OUT)\n"); ++ ep_reg = ep->dwc_ep.out_ep_reg; ++ pcd->ep0_out_save_state = ++ dwc_usb3_dep_getepstate(pcd, ep_reg); ++ dwc_debug1(dev, "OUT save state=%08x\n", ++ pcd->ep0_out_save_state); ++ ep->dwc_ep.stalled_save = ep->dwc_ep.stopped; ++ } ++ ++ for (i = 0; i < num_in_eps; i++) { ++ ep = pcd->in_ep[i]; ++ if (ep->dwc_ep.active) { ++ dwc_debug1(dev, ++ "Saving state of phys EP%d (IN)\n", ++ i * 2 + 3); ++ ep_reg = ep->dwc_ep.in_ep_reg; ++ ep->dwc_ep.save_state = ++ dwc_usb3_dep_getepstate(pcd, ep_reg); ++ ep->dwc_ep.stalled_save = ep->dwc_ep.stopped; ++ } ++ } ++ ++ for (i = 0; i < num_out_eps; i++) { ++ ep = pcd->out_ep[i]; ++ if (ep->dwc_ep.active) { ++ dwc_debug1(dev, ++ "Saving state of phys EP%d (OUT)\n", ++ i * 2 + 2); ++ ep_reg = ep->dwc_ep.out_ep_reg; ++ ep->dwc_ep.save_state = ++ dwc_usb3_dep_getepstate(pcd, ep_reg); ++ ep->dwc_ep.stalled_save = ep->dwc_ep.stopped; ++ } ++ } ++ } else { ++ pcd->ep0state = EP0_IDLE; ++ } ++ ++ dwc_usb3_ena_usb2_suspend(pcd); ++ dev->hibernate = DWC_HIBER_SLEEPING; ++ ++ /* Set DCTL.RunStop to 0, DCTL.KeepConnect to 1 (or 0 if disconnected), ++ * and wait for DSTS.Halted to be set to 1. Software must service any ++ * events that are generated while it is waiting for Halted to be set ++ * to 1. ++ */ ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dctl); ++ temp &= ~DWC_DCTL_RUN_STOP_BIT; ++ if (!save_state) ++ temp &= ~DWC_DCTL_KEEP_CONNECT_BIT; ++ dwc_wr32(dev, &pcd->dev_global_regs->dctl, temp); ++ ++ dwc_debug0(dev, "Cleared Run/Stop bit, waiting for Halt bit\n"); ++ i = 25000; ++ do { ++ if (!dwc_usb3_handle_event(dev)) ++ dwc_udelay(dev, 1); ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dsts); ++ if (--i == 0) { ++ /* If there is data stuck in the Rx FIFO, then the ++ * controller will never set the DevCtrlHlt bit. To ++ * handle that case, after about 25ms flush any data ++ * that remains in the Rx FIFO. ++ */ ++ if (!(temp & DWC_DSTS_RXFIFO_EMPTY_BIT)) ++ dwc_usb3_flush_fifo(pcd, 0); // 0 = Rx FIFO ++ } ++ } while (!(temp & DWC_DSTS_DEV_CTRL_HLT_BIT)); ++ ++ /* Unconditionally save GUCTL/GUCTL1 */ ++ dev->guctl_save = dwc_rd32(dev, &dev->core_global_regs->guctl); ++ dev->guctl1_save = dwc_rd32(dev, &dev->core_global_regs->guctl1); ++ ++ if (save_state) { ++ dwc_debug0(dev, "Saving state - 2\n"); ++ ++ /* Read the D* registers (DCTL, DCFG, DEVTEN) and G* registers ++ * (GSBUSCFG0/1, GCTL, GTXTHRCFG, GRXTHRCFG, GTXFIFOSIZn, ++ * GRXFIFOSIZ0, GUSB3PIPECTL0, GUSB2PHYCFG0) and save their ++ * state. ++ */ ++ dev->dcfg_save = dwc_rd32(dev, &pcd->dev_global_regs->dcfg); ++ dwc_debug1(dev, "DCFG=%08x\n", dev->dcfg_save); ++ dev->dctl_save = dwc_rd32(dev, &pcd->dev_global_regs->dctl); ++ dev->gtxfifosiz0_save = ++ dwc_rd32(dev, &dev->core_global_regs->gtxfifosiz[0]); ++ dev->gtxfifosiz1_save = ++ dwc_rd32(dev, &dev->core_global_regs->gtxfifosiz[1]); ++ dev->gtxfifosiz2_save = ++ dwc_rd32(dev, &dev->core_global_regs->gtxfifosiz[2]); ++ dev->gtxfifosiz3_save = ++ dwc_rd32(dev, &dev->core_global_regs->gtxfifosiz[3]); ++ dev->grxfifosiz0_save = ++ dwc_rd32(dev, &dev->core_global_regs->grxfifosiz[0]); ++ dwc_usb3_set_scratchpad_buf_array(pcd, ++ pcd->hiber_scratchpad_array_dma); ++ ++ /* Set the DCTL.CSS bit and wait for the save state process to ++ * complete by polling for DSTS.SSS to equal 0. ++ */ ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dsts); ++ dwc_debug1(dev, "DSTS before=%1x\n", temp); ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dctl); ++ dwc_debug1(dev, "DCTL before=%1x\n", temp); ++ temp |= DWC_DCTL_CSS_BIT; ++ dwc_wr32(dev, &pcd->dev_global_regs->dctl, temp); ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dctl); ++ dwc_debug1(dev, "DCTL after=%1x\n", temp); ++ ++ dwc_debug0(dev, "Set CSS bit, waiting for SSS bit clear\n"); ++ do { ++ dwc_udelay(dev, 1); ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dsts); ++ } while (temp & DWC_DSTS_SSS_BIT); ++ dwc_debug1(dev, "DSTS after=%1x\n", temp); ++#if 0 ++ /* If the save failed, the DSTS.SRE field will indicate an ++ * error. ++ */ ++ if (temp & DWC_DSTS_SRE_BIT) { ++ dwc_error0(dev, "### Save state failed! ###\n"); ++ ++ /* What should we do here ?? */ ++ return; ++ } ++#endif ++ } ++ ++ /* Communicate with the power controller to set the power state to D3 */ ++ dwc_usb3_power_ctl(dev, 0); ++ dev->pme_ready = 1; ++ ++ dwc_info0(dev, "In D3\n"); ++ ++ /* Remove core well power */ ++ // This is "faked" by the FPGA ++} ++ ++/** ++ * This routine restarts any transfer that was in progress on an EP when the ++ * core entered hibernation. ++ */ ++static void dwc_reenable_xfer_and_restart(dwc_usb3_pcd_t *pcd, ++ dwc_usb3_pcd_ep_t *ep) ++{ ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg; ++ dwc_usb3_dma_desc_t *desc; ++ dwc_dma_t desc_dma; ++ u8 *tri; ++ int i, owned; ++ ++ dwc_debug1(pcd->usb3_dev, "%s()\n", __func__); ++ dwc_debug2(pcd->usb3_dev, "phys EP%d-%s\n", ep->dwc_ep.phys, ++ ep->dwc_ep.is_in ? "IN" : "OUT"); ++ desc = ep->dwc_ep.dma_desc; ++ ++ /* Find the first non-hw-owned TRB */ ++ for (i = 0; i < ep->dwc_ep.num_desc; i++, desc++) { ++ if (!dwc_usb3_is_hwo(desc) && ++ !(dwc_usb3_get_xfersts(desc) & DWC_TRBRSP_XFER_IN_PROG)) { ++ dwc_debug1(pcd->usb3_dev, ++ "Found non-hw-owned TRB at %d\n", i); ++ break; ++ } ++ } ++ ++ if (i == ep->dwc_ep.num_desc) ++ desc = ep->dwc_ep.dma_desc; ++ ++ /* Find the first hw-owned TRB */ ++ for (i = 0, owned = -1; i < ep->dwc_ep.num_desc; i++) { ++ /* If status == 4, this TRB's xfer was in progress prior to ++ * entering hibernation ++ */ ++ if (dwc_usb3_get_xfersts(desc) & DWC_TRBRSP_XFER_IN_PROG) { ++ dwc_debug1(pcd->usb3_dev, ++ "Found in-progress TRB at %d\n", i); ++ ++ /* Set HWO back to 1 so the xfer can continue */ ++ desc->control |= DWC_DSCCTL_HWO_BIT; ++ owned = i; ++ break; ++ } ++ ++ /* Save the index of the first TRB with the HWO bit set */ ++ if (dwc_usb3_is_hwo(desc)) { ++ dwc_debug1(pcd->usb3_dev, "Found hw-owned TRB at %d\n", ++ i); ++ ++ owned = i; ++ break; ++ } ++ ++ desc++; ++ if (desc == ep->dwc_ep.dma_desc + ep->dwc_ep.num_desc) ++ desc = ep->dwc_ep.dma_desc; ++ } ++ ++ wmb(); ++ ep->dwc_ep.hiber_desc_idx = 0; ++ ++ if (owned < 0) ++ /* No TRB had HWO bit set, fine */ ++ return; ++ ++ dwc_debug1(pcd->usb3_dev, "desc=%08lx\n", (unsigned long)desc); ++ ++ /* Restart of Isoc EPs is deferred until the host polls the EP */ ++ if (ep->dwc_ep.type == UE_ISOCHRONOUS) { ++ dwc_debug0(pcd->usb3_dev, ++ "Deferring restart until host polls\n"); ++ ep->dwc_ep.hiber_desc_idx = owned + 1; ++ return; ++ } ++ ++#ifdef VERBOSE ++ dwc_debug4(pcd->usb3_dev, "%08x %08x %08x %08x\n", ++ *((unsigned *)desc), *((unsigned *)desc + 1), ++ *((unsigned *)desc + 2), *((unsigned *)desc + 3)); ++#endif ++ /* Now restart at the first TRB found with HWO set */ ++ if (ep->dwc_ep.is_in) { ++ ep_reg = ep->dwc_ep.in_ep_reg; ++ tri = &ep->dwc_ep.tri_in; ++ } else { ++ ep_reg = ep->dwc_ep.out_ep_reg; ++ tri = &ep->dwc_ep.tri_out; ++ } ++ ++ dwc_debug0(pcd->usb3_dev, "Restarting xfer\n"); ++ desc = ep->dwc_ep.dma_desc + owned; ++ desc_dma = (dwc_dma_t) ++ ((unsigned long)ep->dwc_ep.dma_desc_dma + owned * 16); ++ dwc_debug1(pcd->usb3_dev, "desc=%08lx\n", (unsigned long)desc); ++ ++#ifdef VERBOSE ++ dwc_debug5(pcd->usb3_dev, "%08x %08x %08x %08x (%08x)\n", ++ *((unsigned *)desc), *((unsigned *)desc + 1), ++ *((unsigned *)desc + 2), *((unsigned *)desc + 3), ++ (unsigned)desc_dma); ++#endif ++ ++ dwc_usb3_dis_usb2_suspend(pcd); ++ *tri = dwc_usb3_dep_startxfer(pcd, ep_reg, desc_dma, 0) + 1; ++ dwc_usb3_ena_usb2_suspend(pcd); ++} ++ ++/** ++ * This routine finishes exiting from hibernation once the device is connected. ++ */ ++void dwc_exit_hibernation_after_connect(dwc_usb3_pcd_t *pcd, int connected) ++{ ++ dwc_usb3_pcd_ep_t *ep; ++ int num_in_eps, num_out_eps, i; ++ u32 temp; ++ ++ dwc_debug2(pcd->usb3_dev, "%s(%d)\n", __func__, connected); ++ ++ /* Perform the steps in Section 9.1.5 "Initialization on ++ * SetConfiguration or SetInterface Command" in [DWSS]. ++ * ++ * While issuing the DEPCFG commands, set each endpoint's sequence ++ * number and flow control state to the value read during the save. ++ * ++ * If the endpoint was in the Halted state prior to entering ++ * hibernation, software must issue the "Set STALL" endpoint command ++ * to put the endpoint back into the Halted state. ++ */ ++ num_in_eps = pcd->num_in_eps; ++ num_out_eps = pcd->num_out_eps; ++ ++ pcd->eps_enabled = 0; ++ ++ ep = pcd->ep0; ++ if (ep->dwc_ep.active) ++ /* Setting STALL on EP0 caused problems */ ++ ep->dwc_ep.stalled_save = 0; ++ ++ for (i = 0; i < num_in_eps; i++) { ++ ep = pcd->in_ep[i]; ++ if (ep->dwc_ep.active) { ++ ep->dwc_ep.ena_once = 0; ++ dwc_debug1(pcd->usb3_dev, "Activating phys EP%d (IN)\n", ++ i * 2 + 3); ++ dwc_usb3_ep_activate(pcd, ep, 1); ++ if (ep->dwc_ep.stalled_save) { ++ ep->dwc_ep.stalled_save = 0; ++ dwc_debug1(pcd->usb3_dev, ++ "Stalling phys EP%d (IN)\n", ++ i * 2 + 3); ++ dwc_usb3_pcd_ep_set_stall(pcd, ep); ++ ep->dwc_ep.stopped = 1; ++ } ++ } ++ } ++ ++ for (i = 0; i < num_out_eps; i++) { ++ ep = pcd->out_ep[i]; ++ if (ep->dwc_ep.active) { ++ ep->dwc_ep.ena_once = 0; ++ dwc_debug1(pcd->usb3_dev, ++ "Activating phys EP%d (OUT)\n", i * 2 + 2); ++ dwc_usb3_ep_activate(pcd, ep, 1); ++ if (ep->dwc_ep.stalled_save) { ++ ep->dwc_ep.stalled_save = 0; ++ dwc_debug1(pcd->usb3_dev, ++ "Stalling phys EP%d (OUT)\n", ++ i * 2 + 2); ++ dwc_usb3_pcd_ep_set_stall(pcd, ep); ++ ep->dwc_ep.stopped = 1; ++ } ++ } ++ } ++ ++ /* (In this step, software re-configures the existing endpoints and ++ * starts their transfers). ++ * ++ * When software issued the EndXfer command with the ForceRM field set ++ * to '0' prior to entering hibernation, the core may have written back ++ * an active TRB for the transfer, setting the HWO bit to '0'. Software ++ * must ensure that the TRB is valid and set the HWO bit back to '1' ++ * prior to re-starting the transfer in this step. ++ */ ++ for (i = 0; i < num_in_eps; i++) { ++ ep = pcd->in_ep[i]; ++ if (ep->dwc_ep.active) { ++ dwc_debug1(pcd->usb3_dev, ++ "Restarting xfer on phys EP%d (IN)\n", ++ i * 2 + 3); ++ dwc_reenable_xfer_and_restart(pcd, ep); ++ } ++ } ++ ++ for (i = 0; i < num_out_eps; i++) { ++ ep = pcd->out_ep[i]; ++ if (ep->dwc_ep.active) { ++ dwc_debug1(pcd->usb3_dev, ++ "Restarting xfer on phys EP%d (OUT)\n", ++ i * 2 + 2); ++ dwc_reenable_xfer_and_restart(pcd, ep); ++ } ++ } ++ ++ /* If the core is already connected to the host (DSTS.USBLnkSt == 0, 2, ++ * 3, 14, or 15), set DCTL.ULStChngReq to '8' as described in Table 7-47 ++ * of [DWSS]. ++ * ++ * If the host initiated resume, this step completes the transition to ++ * U0. If the host did not initiate resume, this step causes the device ++ * to initiate resume (remote wakeup). ++ */ ++ if (connected) { ++ dwc_debug0(pcd->usb3_dev, "Already connected," ++ " requesting link state Recovery\n"); ++ dwc_usb3_pcd_set_link_state(pcd, DWC_LINK_STATE_REQ_RECOVERY); ++ //dwc_udelay(pcd->usb3_dev, 1); ++ //dwc_usb3_pcd_set_link_state(pcd, 0); ++ pcd->usb3_dev->hiber_wait_u0 = 1; ++ pcd->usb3_dev->hibernate = DWC_HIBER_WAIT_U0; ++ temp = dwc_usb3_pcd_get_link_state(pcd); ++ dwc_debug1(pcd->usb3_dev, "Link state %d\n", temp); ++ pcd->link_state = temp; ++ } else { ++ pcd->usb3_dev->hiber_wait_u0 = 0; ++ } ++} ++ ++/** ++ * This routine wakes the core from hibernation. ++ */ ++int dwc_exit_hibernation(dwc_usb3_pcd_t *pcd, int restore_state) ++{ ++ dwc_usb3_device_t *dev = pcd->usb3_dev; ++ u32 temp; ++ ++ dwc_debug2(dev, "%s(%d)\n", __func__, restore_state); ++ ++ /* Enable core well power */ ++ // This is "faked" by the FPGA ++ ++ /* Communicate with the power controller to set the power state to D0 */ ++ dwc_usb3_power_ctl(dev, 1); ++ dev->pme_ready = 0; ++ ++ dwc_info0(dev, "In D0\n"); ++ dev->hibernate = DWC_HIBER_AWAKE; ++ ++ /* Unconditionally restore GUCTL/GUCTL1 */ ++ dwc_wr32(dev, &dev->core_global_regs->guctl, dev->guctl_save); ++ dwc_wr32(dev, &dev->core_global_regs->guctl1, dev->guctl1_save); ++ ++ /* If the reset value of GSBUSCFG0/1 is not correct, write these ++ * registers with the desired values. ++ */ ++ if (dev->program_gsbuscfg) { ++ dwc_wr32(dev, &dev->core_global_regs->gsbuscfg0, ++ dev->gsbuscfg0); ++ dwc_wr32(dev, &dev->core_global_regs->gsbuscfg1, ++ dev->gsbuscfg1); ++ } ++ ++ if (restore_state) { ++ dwc_debug0(dev, "Restoring state\n"); ++ ++ /* Issue a "Set Scratchpad Buffer Array" device generic command ++ * and wait for completion by polling the DGCMD.CmdAct bit. ++ */ ++ dwc_usb3_set_scratchpad_buf_array(pcd, ++ pcd->hiber_scratchpad_array_dma); ++ ++ /* Write '1' to DCTL.CRS to start the restore process and wait ++ * for completion by polling the DSTS.RSS bit. ++ */ ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dsts); ++ dwc_debug1(dev, "DSTS before=%1x\n", temp); ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dctl); ++ dwc_debug1(dev, "DCTL before=%1x\n", temp); ++ temp |= DWC_DCTL_CRS_BIT; ++ dwc_wr32(dev, &pcd->dev_global_regs->dctl, temp); ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dctl); ++ dwc_debug1(dev, "DCTL after=%1x\n", temp); ++ ++ dwc_debug0(dev, "Set CRS bit, waiting for RSS bit clear\n"); ++ do { ++ dwc_udelay(dev, 1); ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dsts); ++ } while (temp & DWC_DSTS_RSS_BIT); ++ dwc_debug1(dev, "DSTS after=%1x\n", temp); ++#if 0 ++ /* If the restore failed, the DSTS.SRE field will indicate an ++ * error. ++ */ ++ if (temp & DWC_DSTS_SRE_BIT) { ++ dwc_error0(dev, "### Restore state failed! ###\n"); ++ ++ /* What should we do here ?? */ ++ return 1; ++ } ++#endif ++ /* (Restore the remaining D* and G* registers) */ ++ dwc_wr32(dev, &pcd->dev_global_regs->dcfg, dev->dcfg_save); ++ dwc_debug1(dev, "DCFG=%08x\n", dev->dcfg_save); ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dcfg); ++ dwc_debug1(dev, "DCFG read back %08x\n", temp); ++ dwc_wr32(dev, &pcd->dev_global_regs->dctl, dev->dctl_save); ++ dwc_wr32(dev, &dev->core_global_regs->gtxfifosiz[0], ++ dev->gtxfifosiz0_save); ++ dwc_wr32(dev, &dev->core_global_regs->gtxfifosiz[1], ++ dev->gtxfifosiz1_save); ++ dwc_wr32(dev, &dev->core_global_regs->gtxfifosiz[2], ++ dev->gtxfifosiz2_save); ++ dwc_wr32(dev, &dev->core_global_regs->gtxfifosiz[3], ++ dev->gtxfifosiz3_save); ++ dwc_wr32(dev, &dev->core_global_regs->grxfifosiz[0], ++ dev->grxfifosiz0_save); ++ } ++ ++ /* Configure the core as described in [DWSS] Section 9.1.1 "Device ++ * Power-On or Soft Reset," excluding the first step (Soft Reset). ++ */ ++ dwc_usb3_pcd_device_init(dev, 0, restore_state); ++ ++#ifdef CONFIG_USB_OTG_DWC ++ /* Enable Device mode interrupts */ ++ dwc_usb3_enable_device_interrupts(dev); ++ ++ /* Set Run/Stop bit, and Keep-Connect bit if hibernation enabled */ ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dctl); ++ temp |= DWC_DCTL_RUN_STOP_BIT; ++ if (dev->core_params->hibernate && ++ (dev->hwparams1 & DWC_HWP1_EN_PWROPT_BITS) == ++ DWC_EN_PWROPT_HIBERNATION << DWC_HWP1_EN_PWROPT_SHIFT) ++ temp |= DWC_DCTL_KEEP_CONNECT_BIT; ++ dwc_wr32(dev, &pcd->dev_global_regs->dctl, temp); ++#endif ++ ++ /* ++ * If the LNR (Link-state Not Ready) field of DSTS is set to 1, ++ * continue polling the DSTS register until LNR=0. ++ */ ++ for (;;) { ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dsts); ++ if (temp & DWC_DSTS_LNR_BIT) ++ dwc_udelay(dev, 1); ++ else ++ break; ++ } ++ ++ /* Read the DSTS register to see the current link state. */ ++ temp = dwc_usb3_pcd_get_link_state(pcd); ++ pcd->link_state = temp; ++ ++ if (temp > DWC_LINK_STATE_U3 && temp != DWC_LINK_STATE_EARLY_SUSPEND && ++ temp != DWC_LINK_STATE_RESUME) { ++ /* If the core is not connected to the host, wait for a Connect ++ * Done event. ++ */ ++ if (temp != DWC_LINK_STATE_RESET) { ++ dev->hiber_wait_connect = 1; ++ ++ if (temp == DWC_LINK_STATE_SS_DIS && ++ /*pcd->speed != USB_SPEED_SUPER &&*/ ++ dev->core_params->ssdisquirk) { ++ dwc_debug0(dev, ++ "Link state SS_DIS, enabling quirk\n"); ++ dev->hibernate = DWC_HIBER_SS_DIS_QUIRK; ++ return DWC_HIBER_SS_DIS_QUIRK; ++ } ++ ++ dwc_debug1(dev, "Link state %d, waiting for connect" ++ " before exiting from hibernation\n", temp); ++ } else { ++ /* If the DSTS.USBLnkSt equals 14, it means a USB reset ++ * was received while the core was entering or exiting ++ * hibernation. Prior to performing the steps in ++ * sections 9.1.2 and 9.1.3, software must write Resume ++ * (8) into the DCTL.ULStChngReq field. ++ */ ++ dwc_debug0(dev, "USB Reset received during hibernation," ++ " requesting link state Recovery\n"); ++ dwc_usb3_pcd_set_link_state(pcd, ++ DWC_LINK_STATE_REQ_RECOVERY); ++ //dwc_mdelay(dev, 1); ++ //dwc_usb3_pcd_set_link_state(pcd, 0); ++ dwc_usb3_set_address(pcd, 0); ++ dev->hibernate = DWC_HIBER_WAIT_LINK_UP; ++ return DWC_HIBER_WAIT_LINK_UP; ++ } ++ } else { ++ dwc_debug1(dev, "Link state %d, exiting from hibernation\n", ++ temp); ++ dev->hiber_wait_connect = 0; ++ ++ /* Perform the steps in Section 9.1.3 "Initialization on ++ * Connect Done" in [DWSS]. ++ */ ++ dwc_usb3_handle_connect_done_intr(pcd); ++ ++ dwc_exit_hibernation_after_connect(pcd, 1); ++ } ++ ++ return 0; ++} +diff --git a/drivers/usb/gadget/udc/hiudc3/pcd_intr.c b/drivers/usb/gadget/udc/hiudc3/pcd_intr.c +new file mode 100644 +index 0000000..fbdc652 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/pcd_intr.c +@@ -0,0 +1,691 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/DWC_usb3/driver/pcd_intr.c $ ++ * $Revision: #114 $ ++ * $Date: 2014/11/11 $ ++ * $Change: 2664766 $ ++ * ++ * Synopsys SS USB3 Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++/** @file ++ * This file contains the implementation of the PCD Interrupt handlers. ++ * ++ * The PCD handles the device interrupts. Many conditions can cause a ++ * device interrupt. When an interrupt occurs, the device interrupt ++ * service routine determines the cause of the interrupt and ++ * dispatches handling to the appropriate routine. These interrupt ++ * handling routines are described below. ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++ ++#ifdef DWC_UTE ++# include "ute_if.h" ++#endif ++ ++/** ++ * This interrupt indicates that the USB link state has changed to L2, U3, or ++ * (if L1 Hibernation is enabled) L1, and software intervention is required. ++ */ ++static int handle_hiber_req_intr(dwc_usb3_pcd_t *pcd, u32 event) ++{ ++ int hird, is_superspeed; ++ u32 state; ++ ++ dwc_print0(pcd->usb3_dev, "HIBERNATION REQUEST\n"); ++ ++ is_superspeed = !!(event & DWC_DEVT_HIBER_SS_BIT); ++ state = event >> DWC_DEVT_HIBER_STATE_SHIFT & ++ DWC_DEVT_HIBER_STATE_BITS >> DWC_DEVT_HIBER_STATE_SHIFT; ++ dwc_print2(pcd->usb3_dev, "state=%x, is_superspeed=%d\n", ++ state, is_superspeed); ++ ++ /* TODO: Workaround */ ++ if (!(state == DWC_LINK_STATE_U3 || ++ //state == DWC_LINK_STATE_SS_DIS || ++ (!is_superspeed && (state == DWC_LINK_STATE_SLEEP)))) { ++ dwc_print0(pcd->usb3_dev, "HIBERNATION not handled\n"); ++ return 1; ++ } /* End workaround */ ++ ++ hird = event >> DWC_DEVT_HIBER_HIRD_SHIFT & ++ DWC_DEVT_HIBER_HIRD_BITS >> DWC_DEVT_HIBER_HIRD_SHIFT; ++ dwc_debug5(pcd->usb3_dev, "%s(%u), state=%d hird=%d ss=%d\n", ++ __func__, event, state, hird, is_superspeed); ++ ++ /* Enter hibernation if supported */ ++ if (pcd->usb3_dev->core_params->hibernate && ++ (pcd->usb3_dev->hwparams1 & DWC_HWP1_EN_PWROPT_BITS) == ++ DWC_EN_PWROPT_HIBERNATION << DWC_HWP1_EN_PWROPT_SHIFT) { ++ /* Tell kernel thread to save state and enter hibernation */ ++ pcd->usb3_dev->hibernate = DWC_HIBER_ENTER_SAVE; ++ return 1; ++ } ++ ++ return 0; ++} ++ ++/** ++ * This interrupt indicates that the device has been disconnected. ++ */ ++static int handle_disconnect_intr(dwc_usb3_pcd_t *pcd) ++{ ++ dwc_usb3_device_t *dev = pcd->usb3_dev; ++ u32 temp; ++ ++ dwc_print0(dev, "DISCONNECT\n"); ++ ++ /* Must set DCTL[8:5] to 5, according to 2.40a and later databook. ++ * Assuming here this will be harmless on earlier cores. ++ */ ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dctl); ++ temp &= ~DWC_DCTL_ULST_CHNG_REQ_BITS; ++ temp |= DWC_LINK_STATE_REQ_RX_DETECT << DWC_DCTL_ULST_CHNG_REQ_SHIFT; ++ dwc_wr32(dev, &pcd->dev_global_regs->dctl, temp); ++ ++ dwc_usb3_clr_eps_enabled(pcd); ++ dwc_usb3_pcd_stop(pcd); ++ ++ /* Enter hibernation if supported */ ++ if (dev->core_params->hibernate && dev->core_params->hiberdisc && ++ (dev->hwparams1 & DWC_HWP1_EN_PWROPT_BITS) == ++ DWC_EN_PWROPT_HIBERNATION << DWC_HWP1_EN_PWROPT_SHIFT) { ++ /* Tell kernel thread to enter hibernation */ ++ dev->hibernate = DWC_HIBER_ENTER_NOSAVE; ++ return 1; ++ } ++ ++ return 0; ++} ++ ++/** ++ * This interrupt occurs when a USB Reset is detected. When the USB Reset ++ * Interrupt occurs, all transfers are stopped and the device state is set ++ * to DEFAULT. ++ */ ++static void handle_usb_reset_intr(dwc_usb3_pcd_t *pcd) ++{ ++ dwc_usb3_pcd_ep_t *ep; ++ int i; ++ ++ dwc_print0(pcd->usb3_dev, "USB RESET\n"); ++ ++ /* If UsbReset comes without Disconnect first, fake it, because the ++ * gadget may need to see a disconnect first. The Synopsys UAS gadget ++ * needs this. ++ */ ++#if 1 ++ if (pcd->state != DWC_STATE_UNCONNECTED) { ++// dwc_print0(pcd->usb3_dev, "fake DISCONNECT\n"); ++ dwc_usb3_clr_eps_enabled(pcd); ++ dwc_usb3_pcd_stop(pcd); ++ } else ++#endif ++ { ++ /* Stop any active xfers on the non-EP0 endpoints */ ++ dwc_usb3_stop_all_xfers(pcd); ++ dwc_usb3_clr_eps_enabled(pcd); ++ } ++ ++ /* Clear stall on each EP */ ++ for (i = 0; i < pcd->num_in_eps; i++) { ++ ep = pcd->in_ep[i]; ++ if (ep->dwc_ep.active && ep->dwc_ep.stopped) ++ dwc_usb3_pcd_ep_clear_stall(pcd, ep); ++ } ++ for (i = 0; i < pcd->num_out_eps; i++) { ++ ep = pcd->out_ep[i]; ++ if (ep->dwc_ep.active && ep->dwc_ep.stopped) ++ dwc_usb3_pcd_ep_clear_stall(pcd, ep); ++ } ++ ++#ifndef SELA_PLATFORM_NOCTL ++ /* Set Device Address to 0 */ ++ dwc_usb3_set_address(pcd, 0); ++#endif ++ ++ pcd->remote_wakeup_enable = 0; ++ pcd->ltm_enable = 0; ++} ++ ++/** ++ * This interrupt occurs when a Connect Done is detected. ++ * Read the device status register and set the device speed in the data ++ * structure. Set up EP0 to receive SETUP packets. ++ */ ++void dwc_usb3_handle_connect_done_intr(dwc_usb3_pcd_t *pcd) ++{ ++ dwc_usb3_device_t *dev = pcd->usb3_dev; ++ dwc_usb3_pcd_ep_t *ep0 = pcd->ep0; ++ int speed; ++#ifndef SELA_PLATFORM_NOCTL ++ u32 temp; ++ u32 diepcfg0, doepcfg0, diepcfg1, doepcfg1; ++ dwc_usb3_dev_ep_regs_t __iomem *ep_reg; ++#endif ++ ++#ifndef SELA_PLATFORM_NOCTL ++ /* The timing on reconnect after hibernation is so tight that we ++ * cannot afford the overhead of printing this to the dmesg log! ++ */ ++ if (!dev->core_params->hibernate || ++ (dev->hwparams1 & DWC_HWP1_EN_PWROPT_BITS) != ++ DWC_EN_PWROPT_HIBERNATION << DWC_HWP1_EN_PWROPT_SHIFT) ++ dwc_print0(dev, "CONNECT\n"); ++ ++// printk("\n###%s,%d\n",__func__,__LINE__); ++# ifdef DEBUG_EP0 ++ dwc_usb3_print_ep0_state(pcd); ++# endif ++#endif /* SELA_PLATFORM_NOCTL */ ++ ++ ep0->dwc_ep.stopped = 0; ++ speed = dwc_usb3_get_device_speed(pcd); ++// printk("\n###%s,%d\n",__func__,__LINE__); ++ pcd->speed = speed; ++ ++#ifndef SELA_PLATFORM_NOCTL ++# ifdef DWC_STAR_9000483510_WORKAROUND ++ if (speed == USB_SPEED_SUPER) ++ handle_usb_reset_intr(pcd); ++# endif ++ ++ /* If LPM enable was requested */ ++// printk("\n###%s,%d\n",__func__,__LINE__); ++ if (dev->core_params->lpmctl) { ++ temp = dwc_rd32(dev, &pcd->dev_global_regs->dctl); ++ ++ /* HIRD threshold must be set to 0 when in SS */ ++ temp &= ~DWC_DCTL_HIRD_THR_BITS; ++ ++ /* If not SS */ ++ if (speed != USB_SPEED_SUPER) { ++ /* If hibernation enabled and non-default threshold */ ++ if (dev->core_params->hibernate && ++ (dev->hwparams1 & DWC_HWP1_EN_PWROPT_BITS) == ++ DWC_EN_PWROPT_HIBERNATION << DWC_HWP1_EN_PWROPT_SHIFT && ++ dev->hird_thresh) { ++ /* Set requested threshold value */ ++ temp |= dev->hird_thresh << DWC_DCTL_HIRD_THR_SHIFT & ++ DWC_DCTL_HIRD_THR_BITS; ++ } else { ++ /* Set default threshold value */ ++ temp |= 0x1c << DWC_DCTL_HIRD_THR_SHIFT; ++ } ++ } ++ ++ dwc_wr32(dev, &pcd->dev_global_regs->dctl, temp); ++ } ++ ++// printk("\n###%s,%d\n",__func__,__LINE__); ++ /* Set the MPS of EP0 based on the connection speed */ ++ switch (speed) { ++ case USB_SPEED_SUPER: ++ pcd->ep0->dwc_ep.maxpacket = 512; ++ break; ++ ++ case USB_SPEED_HIGH: ++ case USB_SPEED_FULL: ++ pcd->ep0->dwc_ep.maxpacket = 64; ++ break; ++ ++ case USB_SPEED_LOW: ++ pcd->ep0->dwc_ep.maxpacket = 8; ++ break; ++ } ++ ++ diepcfg0 = DWC_USB3_EP_TYPE_CONTROL << DWC_EPCFG0_EPTYPE_SHIFT; ++ diepcfg0 |= DWC_CFG_ACTION_MODIFY << DWC_EPCFG0_CFG_ACTION_SHIFT; ++ diepcfg1 = DWC_EPCFG1_XFER_CMPL_BIT | DWC_EPCFG1_XFER_IN_PROG_BIT | ++ DWC_EPCFG1_XFER_NRDY_BIT | DWC_EPCFG1_EP_DIR_BIT; ++ ++ doepcfg0 = DWC_USB3_EP_TYPE_CONTROL << DWC_EPCFG0_EPTYPE_SHIFT; ++ doepcfg0 |= DWC_CFG_ACTION_MODIFY << DWC_EPCFG0_CFG_ACTION_SHIFT; ++ doepcfg1 = DWC_EPCFG1_XFER_CMPL_BIT | DWC_EPCFG1_XFER_IN_PROG_BIT | ++ DWC_EPCFG1_XFER_NRDY_BIT; ++ ++ diepcfg0 |= pcd->ep0->dwc_ep.maxpacket << DWC_EPCFG0_MPS_SHIFT; ++ doepcfg0 |= pcd->ep0->dwc_ep.maxpacket << DWC_EPCFG0_MPS_SHIFT; ++ ++# ifdef DWC_UTE ++ ep0->dwc_ep.tx_fifo_num = pcd->txf_map[0]; ++# endif ++ diepcfg0 |= ep0->dwc_ep.tx_fifo_num << DWC_EPCFG0_TXFNUM_SHIFT; ++ ++ dwc_usb3_dis_usb2_suspend(pcd); ++ ++ /* Issue "DEPCFG" command to EP0-OUT */ ++ ep_reg = &pcd->out_ep_regs[0]; ++// printk("\n###%s,%d\n",__func__,__LINE__); ++ dwc_usb3_dep_cfg(pcd, ep_reg, doepcfg0, doepcfg1, 0); ++ ++// printk("\n###%s,%d\n",__func__,__LINE__); ++ /* Issue "DEPCFG" command to EP0-IN */ ++ ep_reg = &pcd->in_ep_regs[0]; ++ dwc_usb3_dep_cfg(pcd, ep_reg, diepcfg0, diepcfg1, 0); ++// printk("\n###%s,%d\n",__func__,__LINE__); ++ ++ dwc_usb3_ena_usb2_suspend(pcd); ++// printk("\n###%s,%d\n",__func__,__LINE__); ++#endif /* SELA_PLATFORM_NOCTL */ ++ ++ if (pcd->state == DWC_STATE_UNCONNECTED) ++ pcd->state = DWC_STATE_DEFAULT; ++ ++ /* Inform the gadget of the connection and the speed */ ++// printk("\n###%s,%d\n",__func__,__LINE__); ++ dwc_usb3_gadget_connect(pcd, speed); ++// printk("\n###%s,%d\n",__func__,__LINE__); ++ ++ if (dev->hiber_wait_connect) { ++ /* Already did 'Perform the steps in Section 9.1.3 ++ * "Initialization on Connect Done" in [DWSS]'. ++ */ ++ ++ dwc_debug0(dev, "Hibernation wait connect\n"); ++ dev->hiber_wait_connect = 0; ++ dwc_exit_hibernation_after_connect(pcd, 0); ++ } ++} ++ ++/** ++ * This interrupt indicates that the USB link state has changed. ++ */ ++static void handle_link_status_change_intr(dwc_usb3_pcd_t *pcd) ++{ ++ int state; ++ int speed; ++ ++ if (pcd->usb3_dev->snpsid >= 0x5533230a) ++ return; ++ ++ state = dwc_usb3_pcd_get_link_state(pcd); ++ speed = dwc_usb3_get_device_speed(pcd); ++ pcd->speed = speed; ++ dwc_debug2(pcd->usb3_dev, "LINK state=%d speed=%d\n", state, speed); ++ ++ switch (state) { ++ case DWC_LINK_STATE_U0: ++ if (pcd->usb3_dev->hiber_wait_u0) { ++ pcd->speed = speed; ++ if (pcd->remote_wakeup_enable) ++ dwc_usb3_pcd_remote_wake(pcd, 0); ++ pcd->usb3_dev->hiber_wait_u0 = 0; ++ } ++ ++ /* If transitioning from 3->0 */ ++ if (pcd->link_state == DWC_LINK_STATE_U3) { ++ dwc_debug0(pcd->usb3_dev, ++ "Enabling function remote wake\n"); ++ pcd->wkup_rdy = 1; ++ } else { ++ pcd->wkup_rdy = 0; ++ } ++ ++ pcd->link_state = state; ++ break; ++ ++ case DWC_LINK_STATE_U3: ++ /* If transitioning to 3 */ ++ if (pcd->link_state != DWC_LINK_STATE_U3) ++ dwc_usb3_gadget_suspend(pcd); ++ /* FALL-THRU */ ++ ++ default: ++ pcd->link_state = state; ++ pcd->wkup_rdy = 0; ++ break; ++ } ++} ++ ++/** ++ * This interrupt indicates that the DWC_usb3 controller has detected a ++ * resume or remote wakeup sequence. ++ */ ++static void handle_wakeup_detected_intr(dwc_usb3_pcd_t *pcd) ++{ ++ int state; ++ ++ dwc_debug0(pcd->usb3_dev, ++ "++Resume or Remote Wakeup Detected Interrupt++\n"); ++ dwc_debug1(pcd->usb3_dev, "DSTS=0x%01x\n", ++ dwc_rd32(pcd->usb3_dev, &pcd->dev_global_regs->dsts)); ++ state = dwc_usb3_pcd_get_link_state(pcd); ++ pcd->link_state = state; ++ ++ if (state == DWC_LINK_STATE_U0) ++ dwc_usb3_gadget_resume(pcd); ++} ++ ++/** ++ * This interrupt indicates that a U3/L2-L1 Suspend event has occurred. ++ */ ++static void handle_u3_l2l1_susp_intr(dwc_usb3_pcd_t *pcd) ++{ ++ int state; ++ ++ if (pcd->usb3_dev->snpsid < 0x5533230a) ++ return; ++ ++ state = dwc_usb3_pcd_get_link_state(pcd); ++ dwc_debug1(pcd->usb3_dev, "LINK state=%d\n", state); ++ ++ switch (state) { ++ case DWC_LINK_STATE_U0: ++ /* If transitioning from 3->0 */ ++ if (pcd->link_state == DWC_LINK_STATE_U3) { ++ dwc_debug0(pcd->usb3_dev, ++ "Enabling function remote wake\n"); ++ pcd->wkup_rdy = 1; ++ } else { ++ pcd->wkup_rdy = 0; ++ } ++ ++ pcd->link_state = state; ++ break; ++ ++ case DWC_LINK_STATE_U3: ++ /* If transitioning to 3 */ ++ if (pcd->link_state != DWC_LINK_STATE_U3) ++ dwc_usb3_gadget_suspend(pcd); ++ /* FALL-THRU */ ++ ++ default: ++ pcd->link_state = state; ++ pcd->wkup_rdy = 0; ++ break; ++ } ++} ++ ++/** ++ * This routine handles the SOF Interrupts. At this time the SOF Interrupt ++ * is disabled. ++ */ ++static void handle_sof_intr(dwc_usb3_pcd_t *pcd) ++{ ++ dwc_debug0(pcd->usb3_dev, "SOF\n"); ++} ++ ++/** ++ * This interrupt indicates that an EP has a pending interrupt. ++ */ ++void dwc_usb3_handle_ep_intr(dwc_usb3_pcd_t *pcd, int physep, u32 event) ++{ ++ dwc_usb3_pcd_ep_t *ep; ++ int epnum, is_in, temp; ++ char *dir; ++ ++ dwc_debug4(pcd->usb3_dev, "%s(%lx,%d,0x%08x)\n", __func__, ++ (unsigned long)pcd, physep, event); ++ ++ /* Physical Out EPs are even, physical In EPs are odd */ ++ is_in = physep & 1; ++ epnum = physep >> 1 & 0xf; ++ ++ /* Get EP pointer */ ++ if (is_in) { ++ ep = dwc_usb3_get_in_ep(pcd, epnum); ++ dir = "IN"; ++ } else { ++ ep = dwc_usb3_get_out_ep(pcd, epnum); ++ dir = "OUT"; ++ } ++ ++ dwc_debug1(pcd->usb3_dev, "%s EP intr\n", dir); ++ ++#ifdef VERBOSE ++ dwc_debug4(pcd->usb3_dev, "EP%d-%s: type=%d mps=%d\n", ++ ep->dwc_ep.num, (ep->dwc_ep.is_in ? "IN" : "OUT"), ++ ep->dwc_ep.type, ep->dwc_ep.maxpacket); ++#endif ++#ifdef SELA_PLATFORM ++ if (pcd->ep_event) { ++ int evt = event >> DWC_DEPEVT_INTTYPE_SHIFT & ++ DWC_DEPEVT_INTTYPE_BITS >> DWC_DEPEVT_INTTYPE_SHIFT; ++ evt |= epnum << 8 | is_in << 15; ++ *pcd->ep_event = evt; ++ } ++#endif ++ ++ temp = pcd->usb3_dev->hibernate; ++ if (temp >= DWC_HIBER_SLEEPING && temp != DWC_HIBER_WAIT_U0 && ++ temp != DWC_HIBER_SS_DIS_QUIRK) { ++ dwc_info3(pcd->usb3_dev, ++ "EP%d-%s: got event 0x%08x while hibernating\n", ++ ep->dwc_ep.num, (ep->dwc_ep.is_in ? "IN" : "OUT"), ++ event); ++ return; ++ } ++ ++ switch (event & DWC_DEPEVT_INTTYPE_BITS) { ++ case DWC_DEPEVT_XFER_CMPL << DWC_DEPEVT_INTTYPE_SHIFT: ++#ifdef VERBOSE ++ dwc_debug2(pcd->usb3_dev, "[EP%d] %s xfer complete\n", ++ epnum, dir); ++#endif ++ ep->dwc_ep.xfer_started = 0; ++ ++ if (ep->dwc_ep.type != UE_ISOCHRONOUS) { ++ /* Complete the transfer */ ++ if (epnum == 0) ++ dwc_usb3_handle_ep0_xfer(pcd, event); ++ else ++ dwc_usb3_complete_request(pcd, ep, event); ++ } else { ++ dwc_print2(pcd->usb3_dev, ++ "[EP%d] %s xfer complete for ISOC EP!\n", ++ epnum, dir); ++ } ++ ++ break; ++ ++ case DWC_DEPEVT_XFER_IN_PROG << DWC_DEPEVT_INTTYPE_SHIFT: ++#ifdef VERBOSE ++ dwc_debug2(pcd->usb3_dev, "[EP%d] %s xfer in progress\n", ++ epnum, dir); ++#endif ++ if (ep->dwc_ep.type == UE_ISOCHRONOUS) { ++#if 0 ++ u32 now_uf, evt_uf; ++ ++ /* Don't complete transfer if it's way in the past */ ++ now_uf = dwc_usb3_get_frame(pcd); ++ evt_uf = dwc_usb3_get_eventsofn(event); ++ now_uf &= DWC_DEPEVT_ISOC_UFRAME_NUM_BITS >> ++ DWC_DEPEVT_ISOC_UFRAME_NUM_SHIFT; ++ if (now_uf - evt_uf < 0x8000) ++#endif ++ /* Complete the transfer */ ++ dwc_usb3_complete_request(pcd, ep, event); ++ } else { ++// dwc_print2(pcd->usb3_dev, ++// "[EP%d] %s xfer in progress for non-ISOC EP!\n", ++// epnum, dir); ++ ++ /* Complete the transfer */ ++ if (epnum == 0) ++ dwc_usb3_handle_ep0_xfer(pcd, event); ++ else ++ dwc_usb3_complete_request(pcd, ep, event); ++ } ++ ++ break; ++ ++ case DWC_DEPEVT_XFER_NRDY << DWC_DEPEVT_INTTYPE_SHIFT: ++ dwc_debug2(pcd->usb3_dev, "[EP%d] %s xfer not ready\n", ++ epnum, dir); ++ ++ if (epnum == 0) { ++ switch (pcd->ep0state) { ++ case EP0_IN_WAIT_GADGET: ++ case EP0_IN_WAIT_NRDY: ++ if (is_in) ++ dwc_usb3_handle_ep0_xfer(pcd, event); ++ break; ++ case EP0_OUT_WAIT_GADGET: ++ case EP0_OUT_WAIT_NRDY: ++ if (!is_in) ++ dwc_usb3_handle_ep0_xfer(pcd, event); ++ break; ++ default: ++ break; ++ } ++ } else if (ep->dwc_ep.type == UE_ISOCHRONOUS) { ++ dwc_isocdbg2(pcd->usb3_dev, ++ "[EP%d] %s xfer not ready for ISOC EP!\n", ++ epnum, dir); ++ if (!ep->dwc_ep.xfer_started) ++ dwc_usb3_gadget_isoc_ep_start(pcd, ep, event); ++ } ++ ++ break; ++ ++ case DWC_DEPEVT_FIFOXRUN << DWC_DEPEVT_INTTYPE_SHIFT: ++ dwc_error2(pcd->usb3_dev, "[EP%d] %s FIFO Underrun Error!\n", ++ epnum, dir); ++ break; ++ ++ case DWC_DEPEVT_EPCMD_CMPL << DWC_DEPEVT_INTTYPE_SHIFT: ++ dwc_error2(pcd->usb3_dev, "[EP%d] %s Command Complete!\n", ++ epnum, dir); ++ break; ++ ++ default: ++ dwc_error2(pcd->usb3_dev, "[EP%d] %s Unknown event!\n", ++ epnum, dir); ++ break; ++ } ++} ++ ++/** ++ * PCD interrupt handler. ++ * ++ * The PCD handles the device interrupts. Many conditions can cause a ++ * device interrupt. When an interrupt occurs, the device interrupt ++ * service routine determines the cause of the interrupt and ++ * dispatches handling to the appropriate routine. ++ */ ++int dwc_usb3_handle_dev_intr(dwc_usb3_pcd_t *pcd, u32 event) ++{ ++ u32 dint = event >> DWC_DEVT_SHIFT & DWC_DEVT_BITS >> DWC_DEVT_SHIFT; ++ int temp, ret = 0; ++ ++#ifdef VERBOSE ++ dwc_debug2(pcd->usb3_dev, "%s() event=%08x\n", __func__, event); ++#endif ++#ifdef SELA_PLATFORM ++ if (pcd->dev_event) ++ *pcd->dev_event = dint; ++#endif ++ ++ temp = pcd->usb3_dev->hibernate; ++ if (temp >= DWC_HIBER_SLEEPING && temp != DWC_HIBER_WAIT_U0 && ++ temp != DWC_HIBER_SS_DIS_QUIRK) { ++ dwc_info1(pcd->usb3_dev, ++ "Device: got event 0x%08x while hibernating\n", ++ event); ++ return 0; ++ } ++ ++// printk("\n#####%s,%d,dint=0x%x\n",__func__,__LINE__,dint); ++ switch (dint) { ++ case DWC_DEVT_DISCONN: ++ dwc_debug0(pcd->usb3_dev, "Disconnect\n"); ++ printk("Disconnect\n"); ++ ret = handle_disconnect_intr(pcd); ++ break; ++ ++ case DWC_DEVT_USBRESET: ++ dwc_debug0(pcd->usb3_dev, "USB Reset\n"); ++ printk("USB Reset\n"); ++ handle_usb_reset_intr(pcd); ++ break; ++ ++ case DWC_DEVT_CONNDONE: ++ dwc_debug0(pcd->usb3_dev, "Connect Done\n"); ++ printk("Connect Done\n"); ++ dwc_usb3_handle_connect_done_intr(pcd); ++ break; ++ ++ case DWC_DEVT_ULST_CHNG: ++ printk("Link Status Change\n"); ++ handle_link_status_change_intr(pcd); ++ break; ++ ++ case DWC_DEVT_WKUP: ++ dwc_debug0(pcd->usb3_dev, "Wakeup\n"); ++ printk("Wakeup\n"); ++ handle_wakeup_detected_intr(pcd); ++ break; ++ ++ case DWC_DEVT_HIBER_REQ: ++ dwc_debug0(pcd->usb3_dev, "Hibernation Request\n"); ++ printk("Hibernation Request\n"); ++ ret = handle_hiber_req_intr(pcd, event); ++ break; ++ ++ case DWC_DEVT_U3_L2L1_SUSP: ++ dwc_debug0(pcd->usb3_dev, "U3/L2-L1 Suspend Event\n"); ++ printk("U3/L2-L1 Suspend Event\n"); ++ handle_u3_l2l1_susp_intr(pcd); ++ break; ++ ++ case DWC_DEVT_SOF: ++ dwc_debug0(pcd->usb3_dev, "Start of Frame\n"); ++ printk("Start of Frame\n"); ++ handle_sof_intr(pcd); ++ break; ++ ++ case DWC_DEVT_ERRATICERR: ++ dwc_debug0(pcd->usb3_dev, "Erratic Error\n"); ++ printk("Erratic Error\n"); ++ break; ++ ++ case DWC_DEVT_CMD_CMPL: ++ dwc_debug0(pcd->usb3_dev, "Command Complete\n"); ++ printk("Command Complete\n"); ++ break; ++ ++ case DWC_DEVT_OVERFLOW: ++ dwc_debug0(pcd->usb3_dev, "Overflow\n"); ++ printk("Overflow\n"); ++ break; ++ ++ default: ++ dwc_debug0(pcd->usb3_dev, "Unknown event!\n"); ++ printk("Unknown event!\n"); ++ break; ++ } ++ ++ return ret; ++} +diff --git a/drivers/usb/gadget/udc/hiudc3/usb.h b/drivers/usb/gadget/udc/hiudc3/usb.h +new file mode 100644 +index 0000000..3317776 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/usb.h +@@ -0,0 +1,961 @@ ++/* ++ * Copyright (c) 1998 The NetBSD Foundation, Inc. ++ * All rights reserved. ++ * ++ * This code is derived from software contributed to The NetBSD Foundation ++ * by Lennart Augustsson (lennart@augustsson.net) at ++ * Carlstedt Research & Technology. ++ * ++ * 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. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by the NetBSD ++ * Foundation, Inc. and its contributors. ++ * 4. Neither the name of The NetBSD Foundation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. ++ */ ++ ++/* Modified by Synopsys, Inc, 12/12/2007 */ ++ ++ ++#ifndef _USB_H_ ++#define _USB_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * @file ++ */ ++ ++/* ++ * The USB records contain some unaligned little-endian word ++ * components. The U[SG]ETW macros take care of both the alignment ++ * and endian problem and should always be used to access non-byte ++ * values. ++ */ ++typedef u_int8_t uByte; ++typedef u_int8_t uWord[2]; ++typedef u_int8_t uDWord[4]; ++ ++#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h)) ++#define UCONSTW(x) { (x) & 0xff, ((x) >> 8) & 0xff } ++#define UCONSTDW(x) { (x) & 0xff, ((x) >> 8) & 0xff, \ ++ ((x) >> 16) & 0xff, ((x) >> 24) & 0xff } ++ ++#if 1 ++#define UGETW(w) ((w)[0] | ((w)[1] << 8)) ++#define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8)) ++#define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24)) ++#define USETDW(w,v) ((w)[0] = (u_int8_t)(v), \ ++ (w)[1] = (u_int8_t)((v) >> 8), \ ++ (w)[2] = (u_int8_t)((v) >> 16), \ ++ (w)[3] = (u_int8_t)((v) >> 24)) ++#else ++/* ++ * On little-endian machines that can handle unaligned accesses ++ * (e.g. i386) these macros can be replaced by the following. ++ */ ++#define UGETW(w) (*(u_int16_t *)(w)) ++#define USETW(w,v) (*(u_int16_t *)(w) = (v)) ++#define UGETDW(w) (*(u_int32_t *)(w)) ++#define USETDW(w,v) (*(u_int32_t *)(w) = (v)) ++#endif ++ ++/* ++ * Macros for accessing UAS IU fields, which are big-endian ++ */ ++#define IUSETW2(w,h,l) ((w)[0] = (u_int8_t)(h), (w)[1] = (u_int8_t)(l)) ++#define IUCONSTW(x) { ((x) >> 8) & 0xff, (x) & 0xff } ++#define IUCONSTDW(x) { ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \ ++ ((x) >> 8) & 0xff, (x) & 0xff } ++#define IUGETW(w) (((w)[0] << 8) | (w)[1]) ++#define IUSETW(w,v) ((w)[0] = (u_int8_t)((v) >> 8), (w)[1] = (u_int8_t)(v)) ++#define IUGETDW(w) (((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3]) ++#define IUSETDW(w,v) ((w)[0] = (u_int8_t)((v) >> 24), \ ++ (w)[1] = (u_int8_t)((v) >> 16), \ ++ (w)[2] = (u_int8_t)((v) >> 8), \ ++ (w)[3] = (u_int8_t)(v)) ++ ++//#define UPACKED __attribute__ ((__packed__)) ++ ++typedef struct { ++ uByte bmRequestType; ++ uByte bRequest; ++ uWord wValue; ++ uWord wIndex; ++ uWord wLength; ++} UPACKED usb_device_request_t; ++ ++#define UT_GET_DIR(a) ((a) & 0x80) ++#define UT_WRITE 0x00 ++#define UT_READ 0x80 ++ ++#define UT_GET_TYPE(a) ((a) & 0x60) ++#define UT_STANDARD 0x00 ++#define UT_CLASS 0x20 ++#define UT_VENDOR 0x40 ++ ++#define UT_GET_RECIPIENT(a) ((a) & 0x1f) ++#define UT_DEVICE 0x00 ++#define UT_INTERFACE 0x01 ++#define UT_ENDPOINT 0x02 ++#define UT_OTHER 0x03 ++ ++#define UT_READ_DEVICE (UT_READ | UT_STANDARD | UT_DEVICE) ++#define UT_READ_INTERFACE (UT_READ | UT_STANDARD | UT_INTERFACE) ++#define UT_READ_ENDPOINT (UT_READ | UT_STANDARD | UT_ENDPOINT) ++#define UT_WRITE_DEVICE (UT_WRITE | UT_STANDARD | UT_DEVICE) ++#define UT_WRITE_INTERFACE (UT_WRITE | UT_STANDARD | UT_INTERFACE) ++#define UT_WRITE_ENDPOINT (UT_WRITE | UT_STANDARD | UT_ENDPOINT) ++#define UT_READ_CLASS_DEVICE (UT_READ | UT_CLASS | UT_DEVICE) ++#define UT_READ_CLASS_INTERFACE (UT_READ | UT_CLASS | UT_INTERFACE) ++#define UT_READ_CLASS_OTHER (UT_READ | UT_CLASS | UT_OTHER) ++#define UT_READ_CLASS_ENDPOINT (UT_READ | UT_CLASS | UT_ENDPOINT) ++#define UT_WRITE_CLASS_DEVICE (UT_WRITE | UT_CLASS | UT_DEVICE) ++#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE) ++#define UT_WRITE_CLASS_OTHER (UT_WRITE | UT_CLASS | UT_OTHER) ++#define UT_WRITE_CLASS_ENDPOINT (UT_WRITE | UT_CLASS | UT_ENDPOINT) ++#define UT_READ_VENDOR_DEVICE (UT_READ | UT_VENDOR | UT_DEVICE) ++#define UT_READ_VENDOR_INTERFACE (UT_READ | UT_VENDOR | UT_INTERFACE) ++#define UT_READ_VENDOR_OTHER (UT_READ | UT_VENDOR | UT_OTHER) ++#define UT_READ_VENDOR_ENDPOINT (UT_READ | UT_VENDOR | UT_ENDPOINT) ++#define UT_WRITE_VENDOR_DEVICE (UT_WRITE | UT_VENDOR | UT_DEVICE) ++#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE) ++#define UT_WRITE_VENDOR_OTHER (UT_WRITE | UT_VENDOR | UT_OTHER) ++#define UT_WRITE_VENDOR_ENDPOINT (UT_WRITE | UT_VENDOR | UT_ENDPOINT) ++ ++/* Requests */ ++#define UR_GET_STATUS 0x00 ++#define USTAT_STANDARD_STATUS 0x00 ++#define WUSTAT_WUSB_FEATURE 0x01 ++#define WUSTAT_CHANNEL_INFO 0x02 ++#define WUSTAT_RECEIVED_DATA 0x03 ++#define WUSTAT_MAS_AVAILABILITY 0x04 ++#define WUSTAT_CURRENT_TRANSMIT_POWER 0x05 ++#define UR_CLEAR_FEATURE 0x01 ++#define UR_SET_FEATURE 0x03 ++#define UR_SET_AND_TEST_FEATURE 0x0c ++#define UR_SET_ADDRESS 0x05 ++#define UR_GET_DESCRIPTOR 0x06 ++#define UDESC_DEVICE 0x01 ++#define UDESC_CONFIG 0x02 ++#define UDESC_STRING 0x03 ++#define UDESC_INTERFACE 0x04 ++#define UDESC_ENDPOINT 0x05 ++#define UDESC_SS_USB_COMPANION 0x30 ++#define UDESC_DEVICE_QUALIFIER 0x06 ++#define UDESC_OTHER_SPEED_CONFIGURATION 0x07 ++#define UDESC_INTERFACE_POWER 0x08 ++#define UDESC_OTG 0x09 ++#define WUDESC_SECURITY 0x0c ++#define WUDESC_KEY 0x0d ++#define WUD_GET_KEY_INDEX(_wValue_) ((_wValue_) & 0xf) ++#define WUD_GET_KEY_TYPE(_wValue_) (((_wValue_) & 0x30) >> 4) ++#define WUD_KEY_TYPE_ASSOC 0x01 ++#define WUD_KEY_TYPE_GTK 0x02 ++#define WUD_GET_KEY_ORIGIN(_wValue_) (((_wValue_) & 0x40) >> 6) ++#define WUD_KEY_ORIGIN_HOST 0x00 ++#define WUD_KEY_ORIGIN_DEVICE 0x01 ++#define WUDESC_ENCRYPTION_TYPE 0x0e ++#define WUDESC_BOS 0x0f ++#define WUDESC_DEVICE_CAPABILITY 0x10 ++#define WUDESC_WIRELESS_ENDPOINT_COMPANION 0x11 ++#define UDESC_BOS 0x0f ++#define UDESC_DEVICE_CAPABILITY 0x10 ++#define UDESC_CS_DEVICE 0x21 /* class specific */ ++#define UDESC_CS_CONFIG 0x22 ++#define UDESC_CS_STRING 0x23 ++#define UDESC_CS_INTERFACE 0x24 ++#define UDESC_CS_ENDPOINT 0x25 ++#define UDESC_HUB 0x29 ++#define UR_SET_DESCRIPTOR 0x07 ++#define UR_GET_CONFIG 0x08 ++#define UR_SET_CONFIG 0x09 ++#define UR_GET_INTERFACE 0x0a ++#define UR_SET_INTERFACE 0x0b ++#define UR_SYNCH_FRAME 0x0c ++#define UR_SET_SEL 0x30 ++#define UR_SET_ISOC_DELAY 0x31 ++#define WUR_SET_ENCRYPTION 0x0d ++#define WUR_GET_ENCRYPTION 0x0e ++#define WUR_SET_HANDSHAKE 0x0f ++#define WUR_GET_HANDSHAKE 0x10 ++#define WUR_SET_CONNECTION 0x11 ++#define WUR_SET_SECURITY_DATA 0x12 ++#define WUR_GET_SECURITY_DATA 0x13 ++#define WUR_SET_WUSB_DATA 0x14 ++#define WUDATA_DRPIE_INFO 0x01 ++#define WUDATA_TRANSMIT_DATA 0x02 ++#define WUDATA_TRANSMIT_PARAMS 0x03 ++#define WUDATA_RECEIVE_PARAMS 0x04 ++#define WUDATA_TRANSMIT_POWER 0x05 ++#define WUR_LOOPBACK_DATA_WRITE 0x15 ++#define WUR_LOOPBACK_DATA_READ 0x16 ++#define WUR_SET_INTERFACE_DS 0x17 ++ ++/* Feature numbers */ ++#define UF_ENDPOINT_HALT 0 ++#define UF_DEVICE_REMOTE_WAKEUP 1 ++#define UF_TEST_MODE 2 ++#define UF_DEVICE_B_HNP_ENABLE 3 ++#define UF_DEVICE_A_HNP_SUPPORT 4 ++#define UF_DEVICE_A_ALT_HNP_SUPPORT 5 ++#define WUF_WUSB 3 ++#define WUF_TX_DRPIE 0x0 ++#define WUF_DEV_XMIT_PACKET 0x1 ++#define WUF_COUNT_PACKETS 0x2 ++#define WUF_CAPTURE_PACKETS 0x3 ++#define UF_FUNCTION_SUSPEND 0 ++#define UF_U1_ENABLE 48 ++#define UF_U2_ENABLE 49 ++#define UF_LTM_ENABLE 50 ++ ++/* Class requests from the USB 2.0 hub spec, table 11-15 */ ++#define UCR_CLEAR_HUB_FEATURE (0x2000 | UR_CLEAR_FEATURE) ++#define UCR_CLEAR_PORT_FEATURE (0x2300 | UR_CLEAR_FEATURE) ++#define UCR_GET_HUB_DESCRIPTOR (0xa000 | UR_GET_DESCRIPTOR) ++#define UCR_GET_HUB_STATUS (0xa000 | UR_GET_STATUS) ++#define UCR_GET_PORT_STATUS (0xa300 | UR_GET_STATUS) ++#define UCR_SET_HUB_FEATURE (0x2000 | UR_SET_FEATURE) ++#define UCR_SET_PORT_FEATURE (0x2300 | UR_SET_FEATURE) ++#define UCR_SET_AND_TEST_PORT_FEATURE (0xa300 | UR_SET_AND_TEST_FEATURE) ++ ++#ifdef _MSC_VER ++#include ++#endif ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDescriptorSubtype; ++} UPACKED usb_descriptor_t; ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++} UPACKED usb_descriptor_header_t; ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord bcdUSB; ++#define UD_USB_2_0 0x0200 ++#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0) ++ uByte bDeviceClass; ++ uByte bDeviceSubClass; ++ uByte bDeviceProtocol; ++ uByte bMaxPacketSize; ++ /* The fields below are not part of the initial descriptor. */ ++ uWord idVendor; ++ uWord idProduct; ++ uWord bcdDevice; ++ uByte iManufacturer; ++ uByte iProduct; ++ uByte iSerialNumber; ++ uByte bNumConfigurations; ++} UPACKED usb_device_descriptor_t; ++#define USB_DEVICE_DESCRIPTOR_SIZE 18 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wTotalLength; ++ uByte bNumInterface; ++ uByte bConfigurationValue; ++ uByte iConfiguration; ++#define UC_ATT_ONE (1 << 7) /* must be set */ ++#define UC_ATT_SELFPOWER (1 << 6) /* self powered */ ++#define UC_ATT_WAKEUP (1 << 5) /* can wakeup */ ++#define UC_ATT_BATTERY (1 << 4) /* battery powered */ ++ uByte bmAttributes; ++#define UC_BUS_POWERED 0x80 ++#define UC_SELF_POWERED 0x40 ++#define UC_REMOTE_WAKEUP 0x20 ++ uByte bMaxPower; /* max current in 2 mA units */ ++#define UC_POWER_FACTOR 2 ++} UPACKED usb_config_descriptor_t; ++#define USB_CONFIG_DESCRIPTOR_SIZE 9 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bInterfaceNumber; ++ uByte bAlternateSetting; ++ uByte bNumEndpoints; ++ uByte bInterfaceClass; ++ uByte bInterfaceSubClass; ++ uByte bInterfaceProtocol; ++ uByte iInterface; ++} UPACKED usb_interface_descriptor_t; ++#define USB_INTERFACE_DESCRIPTOR_SIZE 9 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bEndpointAddress; ++#define UE_GET_DIR(a) ((a) & 0x80) ++#define UE_SET_DIR(a,d) ((a) | (((d)&1) << 7)) ++#define UE_DIR_IN 0x80 ++#define UE_DIR_OUT 0x00 ++#define UE_ADDR 0x0f ++#define UE_GET_ADDR(a) ((a) & UE_ADDR) ++ uByte bmAttributes; ++#define UE_XFERTYPE 0x03 ++#define UE_CONTROL 0x00 ++#define UE_ISOCHRONOUS 0x01 ++#define UE_BULK 0x02 ++#define UE_INTERRUPT 0x03 ++#define UE_GET_XFERTYPE(a) ((a) & UE_XFERTYPE) ++#define UE_ISO_TYPE 0x0c ++#define UE_ISO_ASYNC 0x04 ++#define UE_ISO_ADAPT 0x08 ++#define UE_ISO_SYNC 0x0c ++#define UE_GET_ISO_TYPE(a) ((a) & UE_ISO_TYPE) ++ uWord wMaxPacketSize; ++ uByte bInterval; ++} UPACKED usb_endpoint_descriptor_t; ++#define USB_ENDPOINT_DESCRIPTOR_SIZE 7 ++ ++typedef struct ss_endpoint_companion_descriptor { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bMaxBurst; ++#define USSE_GET_MAX_STREAMS(a) ((a) & 0x1f) ++#define USSE_SET_MAX_STREAMS(a, b) ((a) | ((b) & 0x1f)) ++#define USSE_GET_MAX_PACKET_NUM(a) ((a) & 0x03) ++#define USSE_SET_MAX_PACKET_NUM(a, b) ((a) | ((b) & 0x03)) ++ uByte bmAttributes; ++ uWord wBytesPerInterval; ++} UPACKED ss_endpoint_companion_descriptor_t; ++#define USB_SS_ENDPOINT_COMPANION_DESCRIPTOR_SIZE 6 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord bString[127]; ++} UPACKED usb_string_descriptor_t; ++#define USB_MAX_STRING_LEN 128 ++#define USB_LANGUAGE_TABLE 0 /* # of the string language id table */ ++ ++/* Hub specific request */ ++#define UR_GET_BUS_STATE 0x02 ++#define UR_CLEAR_TT_BUFFER 0x08 ++#define UR_RESET_TT 0x09 ++#define UR_GET_TT_STATE 0x0a ++#define UR_STOP_TT 0x0b ++ ++/* Hub features */ ++#define UHF_C_HUB_LOCAL_POWER 0 ++#define UHF_C_HUB_OVER_CURRENT 1 ++#define UHF_PORT_CONNECTION 0 ++#define UHF_PORT_ENABLE 1 ++#define UHF_PORT_SUSPEND 2 ++#define UHF_PORT_OVER_CURRENT 3 ++#define UHF_PORT_RESET 4 ++#define UHF_PORT_L1 5 ++#define UHF_PORT_POWER 8 ++#define UHF_PORT_LOW_SPEED 9 ++#define UHF_PORT_HIGH_SPEED 10 ++#define UHF_C_PORT_CONNECTION 16 ++#define UHF_C_PORT_ENABLE 17 ++#define UHF_C_PORT_SUSPEND 18 ++#define UHF_C_PORT_OVER_CURRENT 19 ++#define UHF_C_PORT_RESET 20 ++#define UHF_C_PORT_L1 23 ++#define UHF_PORT_TEST 21 ++#define UHF_PORT_INDICATOR 22 ++ ++typedef struct { ++ uByte bDescLength; ++ uByte bDescriptorType; ++ uByte bNbrPorts; ++ uWord wHubCharacteristics; ++#define UHD_PWR 0x0003 ++#define UHD_PWR_GANGED 0x0000 ++#define UHD_PWR_INDIVIDUAL 0x0001 ++#define UHD_PWR_NO_SWITCH 0x0002 ++#define UHD_COMPOUND 0x0004 ++#define UHD_OC 0x0018 ++#define UHD_OC_GLOBAL 0x0000 ++#define UHD_OC_INDIVIDUAL 0x0008 ++#define UHD_OC_NONE 0x0010 ++#define UHD_TT_THINK 0x0060 ++#define UHD_TT_THINK_8 0x0000 ++#define UHD_TT_THINK_16 0x0020 ++#define UHD_TT_THINK_24 0x0040 ++#define UHD_TT_THINK_32 0x0060 ++#define UHD_PORT_IND 0x0080 ++ uByte bPwrOn2PwrGood; /* delay in 2 ms units */ ++#define UHD_PWRON_FACTOR 2 ++ uByte bHubContrCurrent; ++ uByte DeviceRemovable[32]; /* max 255 ports */ ++#define UHD_NOT_REMOV(desc, i) \ ++ (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1) ++ /* deprecated */ uByte PortPowerCtrlMask[1]; ++} UPACKED usb_hub_descriptor_t; ++#define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */ ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord bcdUSB; ++ uByte bDeviceClass; ++ uByte bDeviceSubClass; ++ uByte bDeviceProtocol; ++ uByte bMaxPacketSize0; ++ uByte bNumConfigurations; ++ uByte bReserved; ++} UPACKED usb_device_qualifier_t; ++#define USB_DEVICE_QUALIFIER_SIZE 10 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bmAttributes; ++#define UOTG_SRP 0x01 ++#define UOTG_HNP 0x02 ++} UPACKED usb_otg_descriptor_t; ++ ++/* OTG feature selectors */ ++#define UOTG_B_HNP_ENABLE 3 ++#define UOTG_A_HNP_SUPPORT 4 ++#define UOTG_A_ALT_HNP_SUPPORT 5 ++#define UOTG_NTF_HOST_REL 51 ++#define UOTG_B3_RSP_ENABLE 52 ++ ++typedef struct { ++ uWord wStatus; ++/* Device status flags */ ++#define UDS_SELF_POWERED 0x0001 ++#define UDS_REMOTE_WAKEUP 0x0002 ++/* Endpoint status flags */ ++#define UES_HALT 0x0001 ++} UPACKED usb_status_t; ++ ++typedef struct { ++ uWord wHubStatus; ++#define UHS_LOCAL_POWER 0x0001 ++#define UHS_OVER_CURRENT 0x0002 ++ uWord wHubChange; ++} UPACKED usb_hub_status_t; ++ ++typedef struct { ++ uWord wPortStatus; ++#define UPS_CURRENT_CONNECT_STATUS 0x0001 ++#define UPS_PORT_ENABLED 0x0002 ++#define UPS_SUSPEND 0x0004 ++#define UPS_OVERCURRENT_INDICATOR 0x0008 ++#define UPS_RESET 0x0010 ++#define UPS_PORT_POWER 0x0100 ++#define UPS_LOW_SPEED 0x0200 ++#define UPS_HIGH_SPEED 0x0400 ++#define UPS_PORT_TEST 0x0800 ++#define UPS_PORT_INDICATOR 0x1000 ++ uWord wPortChange; ++#define UPS_C_CONNECT_STATUS 0x0001 ++#define UPS_C_PORT_ENABLED 0x0002 ++#define UPS_C_SUSPEND 0x0004 ++#define UPS_C_OVERCURRENT_INDICATOR 0x0008 ++#define UPS_C_PORT_RESET 0x0010 ++} UPACKED usb_port_status_t; ++ ++#ifdef _MSC_VER ++#include ++#endif ++ ++/* Device class codes */ ++#define UDCLASS_IN_INTERFACE 0x00 ++#define UDCLASS_COMM 0x02 ++#define UDCLASS_HUB 0x09 ++#define UDSUBCLASS_HUB 0x00 ++#define UDPROTO_FSHUB 0x00 ++#define UDPROTO_HSHUBSTT 0x01 ++#define UDPROTO_HSHUBMTT 0x02 ++#define UDCLASS_DIAGNOSTIC 0xdc ++#define UDCLASS_WIRELESS 0xe0 ++#define UDSUBCLASS_RF 0x01 ++#define UDPROTO_BLUETOOTH 0x01 ++#define UDCLASS_VENDOR 0xff ++ ++/* Interface class codes */ ++#define UICLASS_UNSPEC 0x00 ++ ++#define UICLASS_AUDIO 0x01 ++#define UISUBCLASS_AUDIOCONTROL 1 ++#define UISUBCLASS_AUDIOSTREAM 2 ++#define UISUBCLASS_MIDISTREAM 3 ++ ++#define UICLASS_CDC 0x02 /* communication */ ++#define UISUBCLASS_DIRECT_LINE_CONTROL_MODEL 1 ++#define UISUBCLASS_ABSTRACT_CONTROL_MODEL 2 ++#define UISUBCLASS_TELEPHONE_CONTROL_MODEL 3 ++#define UISUBCLASS_MULTICHANNEL_CONTROL_MODEL 4 ++#define UISUBCLASS_CAPI_CONTROLMODEL 5 ++#define UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6 ++#define UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7 ++#define UIPROTO_CDC_AT 1 ++ ++#define UICLASS_HID 0x03 ++#define UISUBCLASS_BOOT 1 ++#define UIPROTO_BOOT_KEYBOARD 1 ++ ++#define UICLASS_PHYSICAL 0x05 ++ ++#define UICLASS_IMAGE 0x06 ++ ++#define UICLASS_PRINTER 0x07 ++#define UISUBCLASS_PRINTER 1 ++#define UIPROTO_PRINTER_UNI 1 ++#define UIPROTO_PRINTER_BI 2 ++#define UIPROTO_PRINTER_1284 3 ++ ++#define UICLASS_MASS 0x08 ++#define UISUBCLASS_RBC 1 ++#define UISUBCLASS_SFF8020I 2 ++#define UISUBCLASS_QIC157 3 ++#define UISUBCLASS_UFI 4 ++#define UISUBCLASS_SFF8070I 5 ++#define UISUBCLASS_SCSI 6 ++#define UIPROTO_MASS_CBI_I 0 ++#define UIPROTO_MASS_CBI 1 ++#define UIPROTO_MASS_BBB_OLD 2 /* Not in the spec anymore */ ++#define UIPROTO_MASS_BBB 80 /* 'P' for the Iomega Zip drive */ ++ ++#define UICLASS_HUB 0x09 ++#define UISUBCLASS_HUB 0 ++#define UIPROTO_FSHUB 0 ++#define UIPROTO_HSHUBSTT 0 /* Yes, same as previous */ ++#define UIPROTO_HSHUBMTT 1 ++ ++#define UICLASS_CDC_DATA 0x0a ++#define UISUBCLASS_DATA 0 ++#define UIPROTO_DATA_ISDNBRI 0x30 /* Physical iface */ ++#define UIPROTO_DATA_HDLC 0x31 /* HDLC */ ++#define UIPROTO_DATA_TRANSPARENT 0x32 /* Transparent */ ++#define UIPROTO_DATA_Q921M 0x50 /* Management for Q921 */ ++#define UIPROTO_DATA_Q921 0x51 /* Data for Q921 */ ++#define UIPROTO_DATA_Q921TM 0x52 /* TEI multiplexer for Q921 */ ++#define UIPROTO_DATA_V42BIS 0x90 /* Data compression */ ++#define UIPROTO_DATA_Q931 0x91 /* Euro-ISDN */ ++#define UIPROTO_DATA_V120 0x92 /* V.24 rate adaption */ ++#define UIPROTO_DATA_CAPI 0x93 /* CAPI 2.0 commands */ ++#define UIPROTO_DATA_HOST_BASED 0xfd /* Host based driver */ ++#define UIPROTO_DATA_PUF 0xfe /* see Prot. Unit Func. Desc.*/ ++#define UIPROTO_DATA_VENDOR 0xff /* Vendor specific */ ++ ++#define UICLASS_SMARTCARD 0x0b ++ ++/*#define UICLASS_FIRM_UPD 0x0c*/ ++ ++#define UICLASS_SECURITY 0x0d ++ ++#define UICLASS_DIAGNOSTIC 0xdc ++ ++#define UICLASS_WIRELESS 0xe0 ++#define UISUBCLASS_RF 0x01 ++#define UIPROTO_BLUETOOTH 0x01 ++ ++#define UICLASS_APPL_SPEC 0xfe ++#define UISUBCLASS_FIRMWARE_DOWNLOAD 1 ++#define UISUBCLASS_IRDA 2 ++#define UIPROTO_IRDA 0 ++ ++#define UICLASS_VENDOR 0xff ++ ++#define USB_HUB_MAX_DEPTH 5 ++ ++/* ++ * Minimum time a device needs to be powered down to go through ++ * a power cycle. XXX Are these time in the spec? ++ */ ++#define USB_POWER_DOWN_TIME 200 /* ms */ ++#define USB_PORT_POWER_DOWN_TIME 100 /* ms */ ++ ++#if 0 ++/* These are the values from the spec. */ ++#define USB_PORT_RESET_DELAY 10 /* ms */ ++#define USB_PORT_ROOT_RESET_DELAY 50 /* ms */ ++#define USB_PORT_RESET_RECOVERY 10 /* ms */ ++#define USB_PORT_POWERUP_DELAY 100 /* ms */ ++#define USB_SET_ADDRESS_SETTLE 2 /* ms */ ++#define USB_RESUME_DELAY (20*5) /* ms */ ++#define USB_RESUME_WAIT 10 /* ms */ ++#define USB_RESUME_RECOVERY 10 /* ms */ ++#define USB_EXTRA_POWER_UP_TIME 0 /* ms */ ++#else ++/* Allow for marginal (i.e. non-conforming) devices. */ ++#define USB_PORT_RESET_DELAY 50 /* ms */ ++#define USB_PORT_ROOT_RESET_DELAY 250 /* ms */ ++#define USB_PORT_RESET_RECOVERY 250 /* ms */ ++#define USB_PORT_POWERUP_DELAY 300 /* ms */ ++#define USB_SET_ADDRESS_SETTLE 10 /* ms */ ++#define USB_RESUME_DELAY (50*5) /* ms */ ++#define USB_RESUME_WAIT 50 /* ms */ ++#define USB_RESUME_RECOVERY 50 /* ms */ ++#define USB_EXTRA_POWER_UP_TIME 20 /* ms */ ++#endif ++ ++#define USB_MIN_POWER 100 /* mA */ ++#define USB_MAX_POWER 500 /* mA */ ++ ++#define USB_BUS_RESET_DELAY 100 /* ms XXX?*/ ++ ++#define USB_UNCONFIG_NO 0 ++#define USB_UNCONFIG_INDEX (-1) ++ ++/*** ioctl() related stuff ***/ ++ ++struct usb_ctl_request { ++ int ucr_addr; ++ usb_device_request_t ucr_request; ++ void *ucr_data; ++ int ucr_flags; ++#define USBD_SHORT_XFER_OK 0x04 /* allow short reads */ ++ int ucr_actlen; /* actual length transferred */ ++}; ++ ++struct usb_alt_interface { ++ int uai_config_index; ++ int uai_interface_index; ++ int uai_alt_no; ++}; ++ ++#define USB_CURRENT_CONFIG_INDEX (-1) ++#define USB_CURRENT_ALT_INDEX (-1) ++ ++struct usb_config_desc { ++ int ucd_config_index; ++ usb_config_descriptor_t ucd_desc; ++}; ++ ++struct usb_interface_desc { ++ int uid_config_index; ++ int uid_interface_index; ++ int uid_alt_index; ++ usb_interface_descriptor_t uid_desc; ++}; ++ ++struct usb_endpoint_desc { ++ int ued_config_index; ++ int ued_interface_index; ++ int ued_alt_index; ++ int ued_endpoint_index; ++ usb_endpoint_descriptor_t ued_desc; ++}; ++ ++struct usb_full_desc { ++ int ufd_config_index; ++ u_int ufd_size; ++ u_char *ufd_data; ++}; ++ ++struct usb_string_desc { ++ int usd_string_index; ++ int usd_language_id; ++ usb_string_descriptor_t usd_desc; ++}; ++ ++struct usb_ctl_report_desc { ++ int ucrd_size; ++ u_char ucrd_data[1024]; /* filled data size will vary */ ++}; ++ ++typedef struct { u_int32_t cookie; } usb_event_cookie_t; ++ ++#define USB_MAX_DEVNAMES 4 ++#define USB_MAX_DEVNAMELEN 16 ++struct usb_device_info { ++ u_int8_t udi_bus; ++ u_int8_t udi_addr; /* device address */ ++ usb_event_cookie_t udi_cookie; ++ char udi_product[USB_MAX_STRING_LEN]; ++ char udi_vendor[USB_MAX_STRING_LEN]; ++ char udi_release[8]; ++ u_int16_t udi_productNo; ++ u_int16_t udi_vendorNo; ++ u_int16_t udi_releaseNo; ++ u_int8_t udi_class; ++ u_int8_t udi_subclass; ++ u_int8_t udi_protocol; ++ u_int8_t udi_config; ++ u_int8_t udi_speed; ++#define USB_SPEED_UNKNOWN 0 ++#define USB_SPEED_LOW 1 ++#define USB_SPEED_FULL 2 ++#define USB_SPEED_HIGH 3 ++#define USB_SPEED_VARIABLE 4 ++#define USB_SPEED_SUPER 5 ++ int udi_power; /* power consumption in mA, 0 if selfpowered */ ++ int udi_nports; ++ char udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN]; ++ u_int8_t udi_ports[16];/* hub only: addresses of devices on ports */ ++#define USB_PORT_ENABLED 0xff ++#define USB_PORT_SUSPENDED 0xfe ++#define USB_PORT_POWERED 0xfd ++#define USB_PORT_DISABLED 0xfc ++}; ++ ++struct usb_ctl_report { ++ int ucr_report; ++ u_char ucr_data[1024]; /* filled data size will vary */ ++}; ++ ++struct usb_device_stats { ++ u_long uds_requests[4]; /* indexed by transfer type UE_* */ ++}; ++ ++#define WUSB_MIN_IE 0x80 ++#define WUSB_WCTA_IE 0x80 ++#define WUSB_WCONNECTACK_IE 0x81 ++#define WUSB_WHOSTINFO_IE 0x82 ++#define WUHI_GET_CA(_bmAttributes_) ((_bmAttributes_) & 0x3) ++#define WUHI_CA_RECONN 0x00 ++#define WUHI_CA_LIMITED 0x01 ++#define WUHI_CA_ALL 0x03 ++#define WUHI_GET_MLSI(_bmAttributes_) (((_bmAttributes_) & 0x38) >> 3) ++#define WUSB_WCHCHANGEANNOUNCE_IE 0x83 ++#define WUSB_WDEV_DISCONNECT_IE 0x84 ++#define WUSB_WHOST_DISCONNECT_IE 0x85 ++#define WUSB_WRELEASE_CHANNEL_IE 0x86 ++#define WUSB_WWORK_IE 0x87 ++#define WUSB_WCHANNEL_STOP_IE 0x88 ++#define WUSB_WDEV_KEEPALIVE_IE 0x89 ++#define WUSB_WISOCH_DISCARD_IE 0x8A ++#define WUSB_WRESETDEVICE_IE 0x8B ++#define WUSB_WXMIT_PACKET_ADJUST_IE 0x8C ++#define WUSB_MAX_IE 0x8C ++ ++/* Device Notification Types */ ++ ++#define WUSB_DN_MIN 0x01 ++#define WUSB_DN_CONNECT 0x01 ++# define WUSB_DA_OLDCONN 0x00 ++# define WUSB_DA_NEWCONN 0x01 ++# define WUSB_DA_SELF_BEACON 0x02 ++# define WUSB_DA_DIR_BEACON 0x04 ++# define WUSB_DA_NO_BEACON 0x06 ++#define WUSB_DN_DISCONNECT 0x02 ++#define WUSB_DN_EPRDY 0x03 ++#define WUSB_DN_MASAVAILCHANGED 0x04 ++#define WUSB_DN_REMOTEWAKEUP 0x05 ++#define WUSB_DN_SLEEP 0x06 ++#define WUSB_DN_ALIVE 0x07 ++#define WUSB_DN_MAX 0x07 ++ ++#ifdef _MSC_VER ++#include ++#endif ++ ++/* WUSB Handshake Data. Used during the SET/GET HANDSHAKE requests */ ++typedef struct wusb_hndshk_data { ++ uByte bMessageNumber; ++ uByte bStatus; ++ uByte tTKID[3]; ++ uByte bReserved; ++ uByte CDID[16]; ++ uByte Nonce[16]; ++ uByte MIC[8]; ++} UPACKED wusb_hndshk_data_t; ++#define WUSB_HANDSHAKE_LEN_FOR_MIC 38 ++ ++/* WUSB Connection Context */ ++typedef struct wusb_conn_context { ++ uByte CHID [16]; ++ uByte CDID [16]; ++ uByte CK [16]; ++} UPACKED wusb_conn_context_t; ++ ++/* WUSB Security Descriptor */ ++typedef struct wusb_security_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wTotalLength; ++ uByte bNumEncryptionTypes; ++} UPACKED wusb_security_desc_t; ++ ++/* WUSB Encryption Type Descriptor */ ++typedef struct wusb_encrypt_type_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ ++ uByte bEncryptionType; ++#define WUETD_UNSECURE 0 ++#define WUETD_WIRED 1 ++#define WUETD_CCM_1 2 ++#define WUETD_RSA_1 3 ++ ++ uByte bEncryptionValue; ++ uByte bAuthKeyIndex; ++} UPACKED wusb_encrypt_type_desc_t; ++ ++/* WUSB Key Descriptor */ ++typedef struct wusb_key_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte tTKID[3]; ++ uByte bReserved; ++ uByte KeyData[1]; /* variable length */ ++} UPACKED wusb_key_desc_t; ++ ++/* WUSB BOS Descriptor (Binary device Object Store) */ ++typedef struct wusb_bos_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wTotalLength; ++ uByte bNumDeviceCaps; ++} UPACKED wusb_bos_desc_t; ++ ++#define USB_DEVICE_CAPABILITY_20_EXTENSION 0x02 ++typedef struct usb_dev_cap_20_ext_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++#define USB_20_EXT_LPM 0x02 ++#define USB_20_EXT_BESL 0x04 ++#define USB_20_EXT_BASELINE_BESL_VALID 0x08 ++#define USB_20_EXT_DEEP_BESL_VALID 0x10 ++#define USB_20_EXT_BASELINE_BESL_BITS 0x00f00 ++#define USB_20_EXT_BASELINE_BESL_SHIFT 8 ++#define USB_20_EXT_DEEP_BESL_BITS 0x0f000 ++#define USB_20_EXT_DEEP_BESL_SHIFT 12 ++ uDWord bmAttributes; ++} UPACKED usb_dev_cap_20_ext_desc_t; ++ ++#define USB_DEVICE_CAPABILITY_SS_USB 0x03 ++typedef struct usb_dev_cap_ss_usb { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++#define USB_DC_SS_USB_LTM_CAPABLE 0x02 ++ uByte bmAttributes; ++#define USB_DC_SS_USB_SPEED_SUPPORT_LOW 0x01 ++#define USB_DC_SS_USB_SPEED_SUPPORT_FULL 0x02 ++#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH 0x04 ++#define USB_DC_SS_USB_SPEED_SUPPORT_SS 0x08 ++ uWord wSpeedsSupported; ++ uByte bFunctionalitySupport; ++ uByte bU1DevExitLat; ++ uWord wU2DevExitLat; ++} UPACKED usb_dev_cap_ss_usb_t; ++ ++#define USB_DEVICE_CAPABILITY_CONTAINER_ID 0x04 ++typedef struct usb_dev_cap_container_id { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++ uByte bReserved; ++ uByte containerID[16]; ++} UPACKED usb_dev_cap_container_id_t; ++ ++/* Device Capability Type Codes */ ++#define WUSB_DEVICE_CAPABILITY_WIRELESS_USB 0x01 ++ ++/* Device Capability Descriptor */ ++typedef struct wusb_dev_cap_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++ uByte caps[1]; /* Variable length */ ++} UPACKED wusb_dev_cap_desc_t; ++ ++/* Device Capability Descriptor */ ++typedef struct wusb_dev_cap_uwb_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++ uByte bmAttributes; ++ uWord wPHYRates; /* Bitmap */ ++ uByte bmTFITXPowerInfo; ++ uByte bmFFITXPowerInfo; ++ uWord bmBandGroup; ++ uByte bReserved; ++} UPACKED wusb_dev_cap_uwb_desc_t; ++ ++/* Wireless USB Endpoint Companion Descriptor */ ++typedef struct wusb_endpoint_companion_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bMaxBurst; ++ uByte bMaxSequence; ++ uWord wMaxStreamDelay; ++ uWord wOverTheAirPacketSize; ++ uByte bOverTheAirInterval; ++ uByte bmCompAttributes; ++} UPACKED wusb_endpoint_companion_desc_t; ++ ++/* Wireless USB Numeric Association M1 Data Structure */ ++typedef struct wusb_m1_data { ++ uByte version; ++ uWord langId; ++ uByte deviceFriendlyNameLength; ++ uByte sha_256_m3[32]; ++ uByte deviceFriendlyName[256]; ++} UPACKED wusb_m1_data_t; ++ ++typedef struct wusb_m2_data { ++ uByte version; ++ uWord langId; ++ uByte hostFriendlyNameLength; ++ uByte pkh[384]; ++ uByte hostFriendlyName[256]; ++} UPACKED wusb_m2_data_t; ++ ++typedef struct wusb_m3_data { ++ uByte pkd[384]; ++ uByte nd; ++} UPACKED wusb_m3_data_t; ++ ++typedef struct wusb_m4_data { ++ uDWord _attributeTypeIdAndLength_1; ++ uWord associationTypeId; ++ ++ uDWord _attributeTypeIdAndLength_2; ++ uWord associationSubTypeId; ++ ++ uDWord _attributeTypeIdAndLength_3; ++ uDWord length; ++ ++ uDWord _attributeTypeIdAndLength_4; ++ uDWord associationStatus; ++ ++ uDWord _attributeTypeIdAndLength_5; ++ uByte chid[16]; ++ ++ uDWord _attributeTypeIdAndLength_6; ++ uByte cdid[16]; ++ ++ uDWord _attributeTypeIdAndLength_7; ++ uByte bandGroups[2]; ++} UPACKED wusb_m4_data_t; ++ ++#ifdef _MSC_VER ++#include ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _USB_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc3/ute_if.c b/drivers/usb/gadget/udc/hiudc3/ute_if.c +new file mode 100644 +index 0000000..0e00835 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/ute_if.c +@@ -0,0 +1,574 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/DWC_usb3/driver/linux/ute_if.c $ ++ * $Revision: #11 $ ++ * $Date: 2014/11/11 $ ++ * $Change: 2664766 $ ++ * ++ * Synopsys SS USB3 Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++#include "dwc_pcd_cfi.h" ++#include "ute_if.h" ++ ++static struct cfi_ft_lst pcd_feats = { ++ .hdr = { ++ //.totlen = (set at runtime), ++ .cfiver = 0x100, ++ .coreID = 4, ++ //.ftcount = (set at runtime), ++ }, ++ .desc[0] = { /* Rx FIFO size */ ++ .ftparm = { ++ .fid = UTE_FID_RXFIFO_SIZE, ++ .paramcount = 1, ++ .param1 = 0xffffffff, /* shared */ ++ }, ++ //.fdlen = sizeof(struct cfi_feature_desc), ++ .dlen = 4, ++ .bmattr = FT_ATTR_RW, ++ .ftname = "rxfsz", ++ }, ++ .desc[1] = { /* Tx FIFO 0 size */ ++ .ftparm = { ++ .fid = UTE_FID_TXFIFO_SIZE, ++ .paramcount = 1, ++ .param1 = 0, ++ }, ++ //.fdlen = sizeof(struct cfi_feature_desc), ++ .dlen = 4, ++ .bmattr = FT_ATTR_RW, ++ .ftname = "txfsz0", ++ }, ++ .desc[2] = { /* Tx FIFO 1 size */ ++ .ftparm = { ++ .fid = UTE_FID_TXFIFO_SIZE, ++ .paramcount = 1, ++ .param1 = 1, ++ }, ++ //.fdlen = sizeof(struct cfi_feature_desc), ++ .dlen = 4, ++ .bmattr = FT_ATTR_RW, ++ .ftname = "txfsiz1", ++ }, ++ .desc[3] = { /* Tx FIFO 2 size */ ++ .ftparm = { ++ .fid = UTE_FID_TXFIFO_SIZE, ++ .paramcount = 1, ++ .param1 = 2, ++ }, ++ //.fdlen = sizeof(struct cfi_feature_desc), ++ .dlen = 4, ++ .bmattr = FT_ATTR_RW, ++ .ftname = "txfsz2", ++ }, ++ .desc[4] = { /* Tx FIFO 3 size */ ++ .ftparm = { ++ .fid = UTE_FID_TXFIFO_SIZE, ++ .paramcount = 1, ++ .param1 = 3, ++ }, ++ //.fdlen = sizeof(struct cfi_feature_desc), ++ .dlen = 4, ++ .bmattr = FT_ATTR_RW, ++ .ftname = "txfsz3", ++ }, ++ .desc[5] = { /* FIFO 0 physical EP mapping */ ++ .ftparm = { ++ .fid = UTE_FID_TXFIFO_MAP, ++ .paramcount = 1, ++ .param1 = 0, ++ }, ++ //.fdlen = sizeof(struct cfi_feature_desc), ++ .dlen = 4, ++ .bmattr = FT_ATTR_RW, ++ .ftname = "txfmap0", ++ }, ++ .desc[6] = { /* FIFO 1 physical EP mapping */ ++ .ftparm = { ++ .fid = UTE_FID_TXFIFO_MAP, ++ .paramcount = 1, ++ .param1 = 1, ++ }, ++ //.fdlen = sizeof(struct cfi_feature_desc), ++ .dlen = 4, ++ .bmattr = FT_ATTR_RW, ++ .ftname = "txfmap1", ++ }, ++ .desc[7] = { /* FIFO 2 physical EP mapping */ ++ .ftparm = { ++ .fid = UTE_FID_TXFIFO_MAP, ++ .paramcount = 1, ++ .param1 = 2, ++ }, ++ //.fdlen = sizeof(struct cfi_feature_desc), ++ .dlen = 4, ++ .bmattr = FT_ATTR_RW, ++ .ftname = "txfmap2", ++ }, ++ .desc[8] = { /* FIFO 3 physical EP mapping */ ++ .ftparm = { ++ .fid = UTE_FID_TXFIFO_MAP, ++ .paramcount = 1, ++ .param1 = 3, ++ }, ++ //.fdlen = sizeof(struct cfi_feature_desc), ++ .dlen = 4, ++ .bmattr = FT_ATTR_RW, ++ .ftname = "txfmap3", ++ }, ++ .desc[9] = { /* Physical OUT EP 1 USB EP mapping */ ++ .ftparm = { ++ .fid = UTE_FID_EP_MAP, ++ .paramcount = 1, ++ .param1 = 0x01, ++ }, ++ //.fdlen = sizeof(struct cfi_feature_desc), ++ .dlen = 4, ++ .bmattr = FT_ATTR_RW, ++ .ftname = "epmap1-out", ++ }, ++ .desc[10] = { /* Physical IN EP 1 USB EP mapping */ ++ .ftparm = { ++ .fid = UTE_FID_EP_MAP, ++ .paramcount = 1, ++ .param1 = 0x11, ++ }, ++ //.fdlen = sizeof(struct cfi_feature_desc), ++ .dlen = 4, ++ .bmattr = FT_ATTR_RW, ++ .ftname = "epmap1-in", ++ }, ++ .desc[11] = { /* Physical OUT EP 2 USB EP mapping */ ++ .ftparm = { ++ .fid = UTE_FID_EP_MAP, ++ .paramcount = 1, ++ .param1 = 0x02, ++ }, ++ //.fdlen = sizeof(struct cfi_feature_desc), ++ .dlen = 4, ++ .bmattr = FT_ATTR_RW, ++ .ftname = "epmap2-out", ++ }, ++ .desc[12] = { /* Physical IN EP 2 USB EP mapping */ ++ .ftparm = { ++ .fid = UTE_FID_EP_MAP, ++ .paramcount = 1, ++ .param1 = 0x12, ++ }, ++ //.fdlen = sizeof(struct cfi_feature_desc), ++ .dlen = 4, ++ .bmattr = FT_ATTR_RW, ++ .ftname = "epmap2-in", ++ }, ++ .desc[13] = { /* Physical OUT EP 3 USB EP mapping */ ++ .ftparm = { ++ .fid = UTE_FID_EP_MAP, ++ .paramcount = 1, ++ .param1 = 0x03, ++ }, ++ //.fdlen = sizeof(struct cfi_feature_desc), ++ .dlen = 4, ++ .bmattr = FT_ATTR_RW, ++ .ftname = "epmap3-out", ++ }, ++ .desc[14] = { /* Physical IN EP 3 USB EP mapping */ ++ .ftparm = { ++ .fid = UTE_FID_EP_MAP, ++ .paramcount = 1, ++ .param1 = 0x13, ++ }, ++ //.fdlen = sizeof(struct cfi_feature_desc), ++ .dlen = 4, ++ .bmattr = FT_ATTR_RW, ++ .ftname = "epmap3-in", ++ }, ++ .desc[15] = { /* Super Speed */ ++ .ftparm = { ++ .fid = UTE_FID_DEV_SPEED, ++ .paramcount = 1, ++ .param1 = 0xffffffff, ++ }, ++ //.fdlen = sizeof(struct cfi_feature_desc), ++ .dlen = 4, ++ .bmattr = FT_ATTR_RW, ++ .ftname = "dev speed", ++ }, ++}; ++ ++static void *cficb_get_ft_list(struct cfiobject *cfi) ++{ ++ return cfi->features; ++} ++ ++static int cficb_get_ft_value(struct cfiobject *cfi, ++ struct cfi_ft_params *params, ++ unsigned long valptr) ++{ ++ dwc_usb3_pcd_t *pcd; ++ dwc_usb3_device_t *dev; ++ dwc_usb3_core_global_regs_t __iomem *global_regs; ++ unsigned val, index, ram_width; ++ int ret = 0; ++ ++ printk(KERN_DEBUG USB3_DWC "%s(%p,%p,%1lx)\n", __func__, ++ cfi, params, valptr); ++ pcd = cfi->pcd; ++ printk(KERN_DEBUG USB3_DWC "pcd=%p\n", pcd); ++ dev = pcd->usb3_dev; ++ if (params) { ++ printk(KERN_DEBUG USB3_DWC "params->param1=%1x ->fid=%1d\n", ++ params->param1, params->fid); ++ } else { ++ printk(KERN_ERR USB3_DWC "params=NULL!\n"); ++ return -EINVAL; ++ } ++ if (!valptr) { ++ printk(KERN_ERR USB3_DWC "valptr=NULL!\n"); ++ return -EINVAL; ++ } ++ ++ switch (params->fid) { ++ case UTE_FID_RXFIFO_SIZE: ++ /* get Rx FIFO size */ ++ /* val is FIFO size in bytes */ ++ if (params->param1 != 0xffffffff) { ++ ret = -EINVAL; ++ } else { ++ global_regs = dev->core_global_regs; ++ val = dwc_rd32(dev, &global_regs->grxfifosiz[0]); ++ val = (val >> DWC_FIFOSZ_DEPTH_SHIFT) & ++ (DWC_FIFOSZ_DEPTH_BITS >> DWC_FIFOSZ_DEPTH_SHIFT); ++ ram_width = ++ ((dev->hwparams0 >> DWC_HWP0_MDWIDTH_SHIFT) & ++ (DWC_HWP0_MDWIDTH_BITS >> DWC_HWP0_MDWIDTH_SHIFT)) ++ / 8; ++ val *= ram_width; ++ *(unsigned *)valptr = val; ++ } ++ break; ++ ++ case UTE_FID_TXFIFO_SIZE: ++ /* get Tx FIFO size */ ++ /* param1 is Tx FIFO #, val is FIFO size in bytes */ ++ if (params->param1 >= DWC_MAX_TX_FIFOS) { ++ ret = -EINVAL; ++ } else { ++ global_regs = dev->core_global_regs; ++ val = dwc_rd32(dev, ++ &global_regs->gtxfifosiz[params->param1]); ++ val = (val >> DWC_FIFOSZ_DEPTH_SHIFT) & ++ (DWC_FIFOSZ_DEPTH_BITS >> DWC_FIFOSZ_DEPTH_SHIFT); ++ ram_width = ++ ((dev->hwparams0 >> DWC_HWP0_MDWIDTH_SHIFT) & ++ (DWC_HWP0_MDWIDTH_BITS >> DWC_HWP0_MDWIDTH_SHIFT)) ++ / 8; ++ val *= ram_width; ++ *(unsigned *)valptr = val; ++ } ++ break; ++ ++ case UTE_FID_RXFIFO_MAP: ++ /* Rx FIFO mapping not possible for USB3 core */ ++ ret = -EINVAL; ++ break; ++ ++ case UTE_FID_TXFIFO_MAP: ++ /* get Tx FIFO mapping */ ++ /* param1 is Tx FIFO #, val is physical EP # */ ++ if (params->param1 >= DWC_MAX_TX_FIFOS) { ++ ret = -EINVAL; ++ } else { ++ /* find matching FIFO # in EP array */ ++ for (index = 1; index < DWC_MAX_PHYS_EP; index += 2) { ++ if (pcd->txf_map[index] == params->param1) ++ break; ++ } ++ if (index >= DWC_MAX_PHYS_EP) { ++ ret = -EINVAL; ++ } else { ++ /* convert EP array index to physical EP # */ ++ /* Note: have to drop the direction bit, UTE ++ * doesn't expect it to be set ++ */ ++ val = (index >> 1) & 0xf; ++ *(unsigned *)valptr = val; ++ } ++ } ++ break; ++ ++ case UTE_FID_EP_MAP: ++ /* get EP mapping */ ++ /* param1 is physical EP #, val is USB EP # */ ++ index = (params->param1 & 0xf) << 1 | ++ ((params->param1 >> 4) & 0x1); ++ ret = dwc_usb3_get_usb_ep_map(0, index, &val); ++ if (!ret) ++ *(unsigned *)valptr = val; ++ break; ++ case UTE_FID_DEV_SPEED: ++ /* get current device speed */ ++ val = dwc_usb3_get_dev_speed(0); ++ *(unsigned *)valptr = val; ++ break; ++ ++ default: ++ ret = -EINVAL; ++ } ++ ++ if (ret == 0) ++ printk(KERN_DEBUG USB3_DWC "*valptr=%1x\n", ++ *(unsigned *)valptr); ++ return ret; ++} ++ ++static void reset_txfifosize_ft_value(struct cfiobject *cfi) ++{ ++ int i; ++ dwc_usb3_pcd_t *pcd = cfi->pcd; ++ ++ for (i = 0; i < DWC_MAX_TX_FIFOS; i++) { ++ pcd->txf_size[i] = pcd->def_txf_size[i]; ++ } ++} ++ ++static void reset_txfifomap_ft_value(struct cfiobject *cfi) ++{ ++ int i; ++ dwc_usb3_pcd_t *pcd = cfi->pcd; ++ ++ for (i = 0; i < pcd->num_in_eps + 1; i++) { ++ pcd->txf_map[(i << 1) | 1] = i; ++ } ++} ++ ++static int cficb_reset_ft_value(struct cfiobject *cfi, ++ struct cfi_ft_params *params) ++{ ++ int ret = 0; ++ dwc_usb3_pcd_t *pcd = cfi->pcd; ++ ++ printk(KERN_DEBUG USB3_DWC "%s(%p,%p)\n", __func__, cfi, params); ++ ++ if (params) { ++ printk(KERN_DEBUG USB3_DWC "params->param1=%1x ->fid=%1d\n", ++ params->param1, params->fid); ++ } else { ++ printk(KERN_ERR USB3_DWC "params=NULL!\n"); ++ return -EINVAL; ++ } ++ ++ switch (params->fid) { ++ case UTE_FID_EP_MAP: ++ if (params->param1 == 0) ++ ret = dwc_usb3_reset_usb_ep_map(0); ++ break; ++ case UTE_FID_RXFIFO_SIZE: ++ if (params->param1 == 0 && pcd->rxf_size != 0) { ++ pcd->rxf_size = pcd->def_rxf_size; ++ pcd->ute_change = 1; ++ } ++ break; ++ case UTE_FID_TXFIFO_SIZE: ++ if (params->param1 == 0) { ++ reset_txfifosize_ft_value(cfi); ++ pcd->ute_change = 1; ++ } ++ break; ++ case UTE_FID_TXFIFO_MAP: ++ if (params->param1) { ++ reset_txfifomap_ft_value(cfi); ++ pcd->ute_change = 1; ++ } ++ break; ++ default: ++ ret = -ENOTSUPP; ++ break; ++ } ++ ++ if (ret == 0) ++ pcd->ute_change = 1; ++ ++ return ret; ++} ++ ++ ++static int cficb_set_ft_value(struct cfiobject *cfi, ++ struct cfi_ft_params *params, ++ unsigned long valptr) ++{ ++ dwc_usb3_pcd_t *pcd; ++ unsigned val, index; ++ int ret = 0; ++ ++ printk(KERN_DEBUG USB3_DWC "%s(%p,%p,%1lx)\n", __func__, ++ cfi, params, valptr); ++ pcd = cfi->pcd; ++ printk(KERN_DEBUG USB3_DWC "pcd=%p\n", pcd); ++ if (params) { ++ printk(KERN_DEBUG USB3_DWC "params->param1=%1x ->fid=%1d\n", ++ params->param1, params->fid); ++ } else { ++ printk(KERN_ERR USB3_DWC "params=NULL!\n"); ++ return -EINVAL; ++ } ++ if (valptr) { ++ printk(KERN_DEBUG USB3_DWC "*valptr=%1x\n", ++ *(unsigned *)valptr); ++ } else { ++ printk(KERN_ERR USB3_DWC "valptr=NULL!\n"); ++ return -EINVAL; ++ } ++ ++ switch (params->fid) { ++ case UTE_FID_RXFIFO_SIZE: ++ /* set Rx FIFO size */ ++ /* val is FIFO size in bytes */ ++ val = *(unsigned *)valptr; ++ if (params->param1 != 0xffffffff) ++ ret = -EINVAL; ++ else ++ pcd->rxf_size = val; ++ break; ++ ++ case UTE_FID_TXFIFO_SIZE: ++ /* set Tx FIFO size */ ++ /* param1 is Tx FIFO #, val is FIFO size in bytes */ ++ val = *(unsigned *)valptr; ++ if (params->param1 >= DWC_MAX_TX_FIFOS) ++ ret = -EINVAL; ++ else ++ pcd->txf_size[params->param1] = val; ++ break; ++ ++ case UTE_FID_RXFIFO_MAP: ++ /* Rx FIFO mapping not possible for USB3 core */ ++ ret = -EINVAL; ++ break; ++ ++ case UTE_FID_TXFIFO_MAP: ++ /* set Tx FIFO mapping */ ++ /* param1 is Tx FIFO #, val is physical EP # */ ++ val = *(unsigned *)valptr; ++ /* convert physical EP # to EP array index */ ++ /* Note: have to force the direction bit to 1, UTE ++ * doesn't set it ++ */ ++ index = ((val & 0xf) << 1) | 1; ++ if (params->param1 >= DWC_MAX_TX_FIFOS || ++ index >= DWC_MAX_PHYS_EP) ++ ret = -EINVAL; ++ else ++ pcd->txf_map[index] = params->param1; ++ break; ++ ++ case UTE_FID_EP_MAP: ++ /* set EP mapping */ ++ /* param1 is physical EP #, val is USB EP # */ ++ val = *(unsigned *)valptr; ++ index = (params->param1 & 0xf) << 1 | ++ ((params->param1 >> 4) & 0x1); ++ ret = dwc_usb3_set_usb_ep_map(0, index, val); ++ break; ++ case UTE_FID_DEV_SPEED: ++ index = params->param1; ++ printk("UTE_FID_DEV_SPEED is received: new speed %d", index); ++ ret = dwc_usb3_switch_speed(0, index); ++ break; ++ default: ++ ret = -EINVAL; ++ } ++ ++ if (ret == 0) { ++ pcd->ute_change = 1; ++ printk(KERN_DEBUG USB3_DWC "Set UTE change bit\n"); ++ } ++ ++ return ret; ++} ++ ++static struct cfiobject *cfi_create_object(dwc_usb3_pcd_t *pcd) ++{ ++ struct cfiobject *cfi; ++ ++ /* Set the ftcount field in the features header */ ++ pcd_feats.hdr.ftcount = 16; ++ ++ /* Calculate the total length of the feature descriptors for all ++ * features plus the features header descriptor length, and write it ++ * to the totlen field in the features header ++ */ ++ pcd_feats.hdr.totlen = sizeof(struct cfi_features_hdr) + ++ sizeof(struct cfi_feature_desc) * pcd_feats.hdr.ftcount; ++ ++ /* Allocate the cfi object */ ++ cfi = kmalloc(sizeof(*cfi), GFP_KERNEL); ++ if (!cfi) ++ return NULL; ++ memset(cfi, 0, sizeof(*cfi)); ++ ++ /* Assign the PCD pointer */ ++ cfi->pcd = pcd; ++ ++ /* Assign the features pointer */ ++ cfi->features = &pcd_feats; ++ ++ /* Assign the callbacks */ ++ cfi->ops.get_ft_list = cficb_get_ft_list; ++ cfi->ops.get_ft_value = cficb_get_ft_value; ++ cfi->ops.set_ft_value = cficb_set_ft_value; ++ cfi->ops.reset_ft_value = cficb_reset_ft_value; ++ ++ return cfi; ++} ++ ++static void *dwc_cfi_get_object(void) ++{ ++ struct cfiobject *cfi; ++ dwc_usb3_pcd_t *pcd; ++ ++ pcd = dwc_usb3_get_pcd_instance(0); ++ if (!pcd) ++ return NULL; ++ ++ cfi = cfi_create_object(pcd); ++ if (!cfi) ++ return NULL; ++ ++ return cfi; ++}; ++EXPORT_SYMBOL(dwc_cfi_get_object); +diff --git a/drivers/usb/gadget/udc/hiudc3/ute_if.h b/drivers/usb/gadget/udc/hiudc3/ute_if.h +new file mode 100644 +index 0000000..ec05269 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/ute_if.h +@@ -0,0 +1,60 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/DWC_usb3/driver/linux/ute_if.h $ ++ * $Revision: #10 $ ++ * $Date: 2014/11/11 $ ++ * $Change: 2664766 $ ++ * ++ * Synopsys SS USB3 Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 _DWC_UTE_IFC_H_ ++#define _DWC_UTE_IFC_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ * ++ */ ++ ++extern dwc_usb3_pcd_t *dwc_usb3_get_pcd_instance(unsigned devnum); ++extern int dwc_usb3_set_usb_ep_map(unsigned devnum, unsigned phys_ep_num, ++ unsigned usb_ep_num); ++extern int dwc_usb3_get_usb_ep_map(unsigned devnum, unsigned phys_ep_num, ++ unsigned *usb_ep_num_ret); ++extern void dwc_usb3_ute_config(dwc_usb3_device_t *usb3_dev); ++ ++extern int dwc_usb3_reset_usb_ep_map(unsigned devnum); ++extern int dwc_usb3_switch_speed(unsigned devnum, int speed); ++extern int dwc_usb3_get_dev_speed(unsigned devnum); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_UTE_IFC_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc3/win/win_defs.h b/drivers/usb/gadget/udc/hiudc3/win/win_defs.h +new file mode 100644 +index 0000000..042614f +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/win/win_defs.h +@@ -0,0 +1,145 @@ ++#ifndef _DWC_WIN_DEFS_H_ ++#define _DWC_WIN_DEFS_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * @file ++ * ++ * This file contains OS-specific includes and definitions. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++typedef unsigned long long u64, u_int64_t; ++typedef unsigned long u_long; ++typedef unsigned int u32, u_int32_t, u_int; ++typedef unsigned short u16, u_int16_t, u_short; ++typedef unsigned char u8, u_int8_t, u_char; ++ ++typedef long long s64; ++typedef int s32; ++typedef short s16; ++typedef char s8; ++ ++/** Type for DMA addresses */ ++typedef unsigned long dwc_dma_t; ++#define DWC_DMA_ADDR_INVALID (~(dwc_dma_t)0) ++ ++/** Compiler 'packed' attribute for structs */ ++#define UPACKED /* */ ++ ++#define __iomem /* */ ++#define __func__ __FUNCTION__ ++ ++#define KERN_DEBUG "" /* debug messages */ ++#define KERN_INFO "" /* informational messages */ ++#define KERN_WARNING "" /* warning messages */ ++#define KERN_ERR "" /* error messages */ ++ ++#define ESHUTDOWN 1001 ++ ++#include "dwc_list.h" ++ ++/** @name Error Codes */ ++#define DWC_E_INVALID EINVAL ++#define DWC_E_NO_MEMORY ENOMEM ++#define DWC_E_NO_DEVICE ENODEV ++#define DWC_E_NOT_SUPPORTED EOPNOTSUPP ++#define DWC_E_TIMEOUT ETIMEDOUT ++#define DWC_E_BUSY EBUSY ++#define DWC_E_AGAIN EAGAIN ++#define DWC_E_ABORT ECONNABORTED ++#define DWC_E_SHUTDOWN ESHUTDOWN ++#define DWC_E_NO_DATA ENODATA ++#define DWC_E_DISCONNECT ECONNRESET ++#define DWC_E_UNKNOWN EINVAL ++#define DWC_E_NO_STREAM_RES ENOSR ++#define DWC_E_COMMUNICATION ECOMM ++#define DWC_E_OVERFLOW EOVERFLOW ++#define DWC_E_PROTOCOL EPROTO ++#define DWC_E_IN_PROGRESS EINPROGRESS ++#define DWC_E_PIPE EPIPE ++#define DWC_E_IO EIO ++#define DWC_E_NO_SPACE ENOSPC ++#define DWC_E_DOMAIN EDOM ++ ++/** ++ * The number of DMA Descriptors (TRBs) to allocate for each endpoint type. ++ * NOTE: The driver currently supports more than 1 TRB for Isoc EPs only. ++ * So the values for Bulk and Intr must be 1. ++ */ ++#define DWC_NUM_BULK_TRBS 1 ++#define DWC_NUM_INTR_TRBS 1 ++#define DWC_NUM_ISOC_TRBS 32 ++ ++/** ++ * These parameters may be specified when loading the module. They define how ++ * the DWC_usb3 controller should be configured. The parameter values are passed ++ * to the CIL initialization routine dwc_usb3_pcd_common_init(). ++ */ ++typedef struct dwc_usb3_core_params { ++ int burst; ++ int newcore; ++ int phy; ++ int wakeup; ++ int pwrctl; ++ int lpmctl; ++ int phyctl; ++ int usb2mode; ++ int hibernate; ++ int hiberdisc; ++ int clkgatingen; ++ int ssdisquirk; ++ int nobos; ++ int loop; ++ int nump; ++ int newcsr; ++ int rxfsz; ++ int txfsz[16]; ++ int txfsz_cnt; ++ int baseline_besl; ++ int deep_besl; ++ int besl; ++ int ebc; ++} dwc_usb3_core_params_t; ++ ++#define wmb() do {} while (0) ++ ++#define interrupt_disable() 0 ++#define interrupt_enable() do {} while (0) ++ ++#define spin_lock_init(p) do {} while (0) ++#define spin_lock(p) do {} while (0) ++#define spin_unlock(p) do {} while (0) ++#define spin_lock_irqsave(p, f) do { (f) = interrupt_disable(); } while (0) ++#define spin_unlock_irqrestore(p, f) do { if (f) interrupt_enable(); } while (0) ++ ++struct task_struct { ++ int dummy; ++}; ++ ++struct tasklet_struct { ++ int dummy; ++}; ++ ++struct usb_ep { ++ int dummy; ++}; ++ ++struct usb_request { ++ int dummy; ++}; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_WIN_DEFS_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc3/win/win_dev.h b/drivers/usb/gadget/udc/hiudc3/win/win_dev.h +new file mode 100644 +index 0000000..c20e5f2 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/win/win_dev.h +@@ -0,0 +1,183 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/DWC_usb3/driver/win/win_dev.h $ ++ * $Revision: #9 $ ++ * $Date: 2014/11/11 $ ++ * $Change: 2664766 $ ++ * ++ * Synopsys SS USB3 Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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 _DWC_WIN_DEV_H_ ++#define _DWC_WIN_DEV_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ */ ++ ++/** Wrapper function for _handshake() */ ++#define handshake(_dev_, _ptr_, _mask_, _done_) \ ++ _handshake(_dev_, _ptr_, _mask_, _done_) ++ ++/** Takes a usb req pointer and returns the associated pcd req pointer */ ++#define dwc_usb3_get_pcd_req(usbreq) \ ++ ((dwc_usb3_pcd_req_t *)((char *)(usbreq) - \ ++ offsetof(struct dwc_usb3_pcd_req, usb_req))) ++ ++/** Takes a usb ep pointer and returns the associated pcd ep pointer */ ++#define dwc_usb3_get_pcd_ep(usbep) \ ++ ((dwc_usb3_pcd_ep_t *)((char *)(usbep) - \ ++ offsetof(struct dwc_usb3_pcd_ep, usb_ep))) ++ ++/** ++ * Register read/write. ++ */ ++static __inline u32 dwc_rd32(struct dwc_usb3_device *dev, volatile u32 *adr) ++{ ++ return *adr; ++} ++ ++static __inline void dwc_wr32(struct dwc_usb3_device *dev, volatile u32 *adr, u32 val) ++{ ++ *adr = val; ++} ++ ++/** ++ * Non-sleeping delays. ++ */ ++#define dwc_udelay(dev, us) do {} while (0) ++#define dwc_mdelay(dev, ms) do {} while (0) ++ ++/** ++ * Sleeping delay. ++ */ ++#define dwc_msleep(dev, ms) do {} while (0) ++ ++/** ++ * Debugging support - vanishes in non-debug builds. ++ */ ++ ++/** Prefix string for print macros. */ ++#define USB3_DWC "dwc_usb3: " ++ ++//#ifdef DEBUG ++# define dwc_debug printf ++//#else ++//# define dwc_debug(dev, x) do {} while (0) ++//#endif /* DEBUG */ ++ ++# define dwc_debug0(dev, fmt) dwc_debug(fmt) ++# define dwc_debug1(dev, fmt, a) dwc_debug(fmt, a) ++# define dwc_debug2(dev, fmt, a, b) dwc_debug(fmt, a, b) ++# define dwc_debug3(dev, fmt, a, b, c) dwc_debug(fmt, a, b, c) ++# define dwc_debug4(dev, fmt, a, b, c, d) dwc_debug(fmt, a, b, c, d) ++# define dwc_debug5(dev, fmt, a, b, c, d, e) \ ++ dwc_debug(fmt, a, b, c, d, e) ++# define dwc_debug6(dev, fmt, a, b, c, d, e, f) \ ++ dwc_debug(fmt, a, b, c, d, e, f) ++# define dwc_debug7(dev, fmt, a, b, c, d, e, f, g) \ ++ dwc_debug(fmt, a, b, c, d, e, f, g) ++# define dwc_debug8(dev, fmt, a, b, c, d, e, f, g, h) \ ++ dwc_debug(fmt, a, b, c, d, e, f, g, h) ++# define dwc_debug9(dev, fmt, a, b, c, d, e, f, g, h, i) \ ++ dwc_debug(fmt, a, b, c, d, e, f, g, h, i) ++# define dwc_debug10(dev, fmt, a, b, c, d, e, f, g, h, i, j) \ ++ dwc_debug(fmt, a, b, c, d, e, f, g, h, i, j) ++ ++//#if defined(DEBUG) || defined(ISOC_DEBUG) ++# define dwc_isocdbg printf ++//#else ++//# define dwc_isocdbg(dev, x) do {} while (0) ++//#endif ++ ++# define dwc_isocdbg0(dev, fmt) dwc_isocdbg(fmt) ++# define dwc_isocdbg1(dev, fmt, a) dwc_isocdbg(fmt, a) ++# define dwc_isocdbg2(dev, fmt, a, b) dwc_isocdbg(fmt, a, b) ++# define dwc_isocdbg3(dev, fmt, a, b, c) dwc_isocdbg(fmt, a, b, c) ++# define dwc_isocdbg4(dev, fmt, a, b, c, d) \ ++ dwc_isocdbg(fmt, a, b, c, d) ++# define dwc_isocdbg5(dev, fmt, a, b, c, d, e) \ ++ dwc_isocdbg(fmt, a, b, c, d, e) ++# define dwc_isocdbg6(dev, fmt, a, b, c, d, e, f) \ ++ dwc_isocdbg(fmt, a, b, c, d, e, f) ++ ++/** ++ * Print an Error message. ++ */ ++#define dwc_error printf ++ ++#define dwc_error0(dev, fmt) dwc_error(fmt) ++#define dwc_error1(dev, fmt, a) dwc_error(fmt, a) ++#define dwc_error2(dev, fmt, a, b) dwc_error(fmt, a, b) ++#define dwc_error3(dev, fmt, a, b, c) dwc_error(fmt, a, b, c) ++#define dwc_error4(dev, fmt, a, b, c, d) dwc_error(fmt, a, b, c, d) ++ ++/** ++ * Print a Warning message. ++ */ ++#define dwc_warn printf ++ ++#define dwc_warn0(dev, fmt) dwc_warn(fmt) ++#define dwc_warn1(dev, fmt, a) dwc_warn(fmt, a) ++#define dwc_warn2(dev, fmt, a, b) dwc_warn(fmt, a, b) ++#define dwc_warn3(dev, fmt, a, b, c) dwc_warn(fmt, a, b, c) ++#define dwc_warn4(dev, fmt, a, b, c, d) dwc_warn(fmt, a, b, c, d) ++ ++/** ++ * Print an Informational message (normal but significant). ++ */ ++#define dwc_info printf ++ ++#define dwc_info0(dev, fmt) dwc_info(fmt) ++#define dwc_info1(dev, fmt, a) dwc_info(fmt, a) ++#define dwc_info2(dev, fmt, a, b) dwc_info(fmt, a, b) ++#define dwc_info3(dev, fmt, a, b, c) dwc_info(fmt, a, b, c) ++#define dwc_info4(dev, fmt, a, b, c, d) dwc_info(fmt, a, b, c, d) ++ ++/** ++ * Basic message printing. ++ */ ++#define dwc_print printf ++ ++#define dwc_print0(dev, fmt) dwc_print(fmt) ++#define dwc_print1(dev, fmt, a) dwc_print(fmt, a) ++#define dwc_print2(dev, fmt, a, b) dwc_print(fmt, a, b) ++#define dwc_print3(dev, fmt, a, b, c) dwc_print(fmt, a, b, c) ++#define dwc_print4(dev, fmt, a, b, c, d) dwc_print(fmt, a, b, c, d) ++#define dwc_print5(dev, fmt, a, b, c, d, e) \ ++ dwc_print(fmt, a, b, c, d, e) ++ ++extern int dwc_usb3_gadget_init(struct dwc_usb3_device *usb3_dev, struct device *dev); ++extern void dwc_usb3_gadget_remove(struct dwc_usb3_device *usb3_dev, struct device *dev); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_WIN_DEV_H_ */ +diff --git a/drivers/usb/gadget/udc/hiudc3/win/win_gadget.c b/drivers/usb/gadget/udc/hiudc3/win/win_gadget.c +new file mode 100644 +index 0000000..a15da82 +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/win/win_gadget.c +@@ -0,0 +1,205 @@ ++/** @file ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++ ++int main(int argc, char *argv[]) ++{ ++ return 0; ++} ++ ++/****************************************************************************** ++ * Function driver notification routines ++ * ++ * These routines receive notifications from the PCD when certain events ++ * occur which the Function driver may need to be aware of. ++ * ++ * These routines *must* have the exact names and parameters shown here, ++ * because they are part of the API between the PCD and the Function driver. ++ ******************************************************************************/ ++ ++/** ++ * This routine receives Connect notifications from the PCD ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param speed Speed of the connection (as defined in usb.h) ++ * @return 0 for success, else negative error code. ++ */ ++int dwc_usb3_gadget_connect(dwc_usb3_pcd_t *pcd, int speed) ++{ ++ return 0; ++} ++ ++/** ++ * This routine receives Disconnect notifications from the PCD ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @return 0 for success, else negative error code. ++ */ ++int dwc_usb3_gadget_disconnect(dwc_usb3_pcd_t *pcd) ++{ ++ return 0; ++} ++ ++/** ++ * This routine receives Setup request notifications from the PCD ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param ctrl Pointer to the Setup packet for the request. ++ * @return 0 for success, else negative error code. ++ */ ++int dwc_usb3_gadget_setup(dwc_usb3_pcd_t *pcd, usb_device_request_t *ctrl) ++{ ++ return 0; ++} ++ ++/** ++ * This routine receives Suspend notifications from the PCD ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @return 0 for success, else negative error code. ++ */ ++int dwc_usb3_gadget_suspend(dwc_usb3_pcd_t *pcd) ++{ ++ return 0; ++} ++ ++/** ++ * This routine receives Resume notifications from the PCD ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @return 0 for success, else negative error code. ++ */ ++int dwc_usb3_gadget_resume(dwc_usb3_pcd_t *pcd) ++{ ++ return 0; ++} ++ ++/** ++ * This routine receives Transfer Complete notifications from the PCD ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param pcd_ep PCD EP for the transfer. ++ * @param pcd_req PCD request for the transfer. ++ * @param status Transfer status, 0 for success else negative error code. ++ * @return 0 for success, else negative error code. ++ */ ++int dwc_usb3_gadget_complete(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *pcd_ep, ++ dwc_usb3_pcd_req_t *pcd_req, int status) ++{ ++ return 0; ++} ++ ++/** ++ * This routine allows overriding the standard Control transfer handling ++ * (currently only done by the axs101 test gadget) ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ */ ++void dwc_usb3_gadget_do_setup(dwc_usb3_pcd_t *pcd) ++{ ++ /* TODO */ ++} ++ ++/****************************************************************************** ++ * Function driver callback routines ++ * ++ * The PCD calls these routines when it needs something from the Function ++ * driver. ++ * ++ * These routines *must* have the exact names and parameters shown here, ++ * because they are part of the API between the PCD and the Function driver. ++ ******************************************************************************/ ++ ++/** ++ * This routine allocates coherent DMA memory. It is used by the PCD to ++ * allocate memory for TRBs. The block of memory returned must have a start ++ * address aligned to a 16-byte boundary. ++ * ++ * @param pcd_ep PCD EP that memory block will be associated with. ++ * @param size Size of memory block to allocate, in bytes. ++ * @param mem_dma_ret Physical address of allocated memory block is returned ++ * through this pointer. ++ * @return Address of allocated memory block, or NULL if allocation ++ * fails. ++ */ ++void *dwc_usb3_gadget_alloc_dma(dwc_usb3_pcd_ep_t *pcd_ep, int size, dwc_dma_t *mem_dma_ret) ++{ ++ return NULL; ++} ++ ++/** ++ * This routine frees DMA memory allocated by dwc_usb3_gadget_alloc_dma(). ++ * ++ * @param pcd_ep PCD EP that memory block is associated with. ++ * @param size Size of memory block to free, in bytes. ++ * @param mem Address of memory block. ++ * @param mem_dma Physical address of memory block. ++ */ ++void dwc_usb3_gadget_free_dma(dwc_usb3_pcd_ep_t *pcd_ep, int size, void *mem, dwc_dma_t mem_dma) ++{ ++} ++ ++/** ++ * This routine returns the PCD request corresponding to the current transfer ++ * request for an endpoint. The current transfer request is the first request ++ * submitted that has not been completed yet. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param pcd_ep PCD EP to operate on. ++ * @return Pointer to PCD request, or NULL if no request available. ++ */ ++dwc_usb3_pcd_req_t *dwc_usb3_gadget_get_request(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *pcd_ep) ++{ ++ return NULL; ++} ++ ++/** ++ * This routine checks to see if there is another transfer request waiting ++ * on an endpoint that has not been started yet. If so then that transfer is ++ * started. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param pcd_ep PCD EP to operate on. ++ */ ++void dwc_usb3_gadget_start_next_request(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *pcd_ep) ++{ ++} ++ ++/** ++ * This routine terminates all requests which are pending on an endpoint. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param pcd_ep EP to operate on. ++ */ ++void dwc_usb3_gadget_request_nuke(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *pcd_ep) ++{ ++} ++ ++/** ++ * This routine marks all pending requests for an EP as not started. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param pcd_ep EP to operate on. ++ */ ++void dwc_usb3_gadget_set_ep_not_started(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *pcd_ep) ++{ ++} ++ ++/** ++ * Start an Isoc EP running at the proper interval, after receiving the initial ++ * XferNrdy event. ++ * ++ * @param pcd Programming view of DWC_usb3 peripheral controller. ++ * @param pcd_ep EP to operate on. ++ * @param event Event data containing the XferNrdy microframe. ++ */ ++void dwc_usb3_gadget_isoc_ep_start(dwc_usb3_pcd_t *pcd, dwc_usb3_pcd_ep_t *pcd_ep, u32 event) ++{ ++} +diff --git a/drivers/usb/gadget/udc/hiudc3/win/win_hiber.c b/drivers/usb/gadget/udc/hiudc3/win/win_hiber.c +new file mode 100644 +index 0000000..303f08c +--- /dev/null ++++ b/drivers/usb/gadget/udc/hiudc3/win/win_hiber.c +@@ -0,0 +1,35 @@ ++/** @file ++ */ ++ ++#include "os_defs.h" ++#include "hw.h" ++#include "usb.h" ++#include "pcd.h" ++#include "dev.h" ++#include "os_dev.h" ++#include "cil.h" ++ ++void dwc_usb3_task_schedule(struct tasklet_struct *tasklet) ++{ ++} ++ ++/** ++ * Helper routine for dwc_wait_pme_thread() ++ */ ++static void dwc_wait_for_link_up(dwc_usb3_pcd_t *pcd) ++{ ++} ++ ++int dwc_wait_pme_thread(void *data) ++{ ++ return 0; ++} ++ ++int dwc_usb3_handle_pme_intr(dwc_usb3_device_t *dev) ++{ ++ return 0; ++} ++ ++void dwc_usb3_power_ctl(dwc_usb3_device_t *dev, int on) ++{ ++} +diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c +index f205465..382d8b6 100644 +--- a/drivers/usb/gadget/udc/udc-core.c ++++ b/drivers/usb/gadget/udc/udc-core.c +@@ -400,7 +400,15 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri + driver->unbind(udc->gadget); + goto err1; + } +- usb_gadget_connect(udc->gadget); ++ /* ++ * HACK: The Android gadget driver disconnects the gadget ++ * on bind and expects the gadget to stay disconnected until ++ * it calls usb_gadget_connect when userspace is ready. Remove ++ * the call to usb_gadget_connect bellow to avoid enabling the ++ * pullup before userspace is ready. ++ * ++ * usb_gadget_connect(udc->gadget); ++ */ + + kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); + return 0; +diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig +index a3ca137..aa0fd91 100644 +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -50,6 +50,14 @@ config USB_XHCI_RCAR + Say 'Y' to enable the support for the xHCI host controller + found in Renesas R-Car ARM SoCs. + ++config USB_XHCI_HISILICON ++ tristate "xHCI support for Hisilicon SoCs" ++ select USB_XHCI_PLATFORM ++ ---help--- ++ Say 'Y' to enable the support for the xHCI host controller ++ found in Hisilicon ARM SOCs. When you select the option, usb ++ driver can be loaded. ++ + endif # USB_XHCI_HCD + + config USB_EHCI_HCD +diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c +index 3df32fa..9dadcba 100644 +--- a/drivers/usb/host/ehci-hcd.c ++++ b/drivers/usb/host/ehci-hcd.c +@@ -109,6 +109,9 @@ MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); + #include "ehci.h" + #include "pci-quirks.h" + ++#ifdef CONFIG_ARCH_HI3516CV300 ++void usb2_low_power(int); ++#endif + static void compute_tt_budget(u8 budget_table[EHCI_BANDWIDTH_SIZE], + struct ehci_tt *tt); + +@@ -777,7 +780,9 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) + continue; + pstatus = ehci_readl(ehci, + &ehci->regs->port_status[i]); +- ++#ifdef CONFIG_ARCH_HI3516CV300 ++ usb2_low_power(pstatus); ++#endif + if (pstatus & PORT_OWNER) + continue; + if (!(test_bit(i, &ehci->suspended_ports) && +diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c +index ecd5d6a..bf45624 100644 +--- a/drivers/usb/host/ehci-hub.c ++++ b/drivers/usb/host/ehci-hub.c +@@ -30,7 +30,21 @@ + #include + + #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) ++#if defined(CONFIG_ARCH_HI3519) || defined(CONFIG_ARCH_HI3519V101) \ ++ || defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556) \ ++ || defined(CONFIG_ARCH_HI3516AV200) ++#define BASE_REG 0x120100b4 ++#define USBPHY_PORT0_TREQ (0x1 << 2) ++#endif ++#ifdef CONFIG_ARCH_HI3531D ++#define BASE_REG 0x12040000 ++#define USBPHY_PORT0_TREQ 0x0134 ++#endif + ++#ifdef CONFIG_ARCH_HI3516CV300 ++#define BASE_REG 0x120100b8 ++#define USBPHY_PORT0_TREQ (0x1 << 14) ++#endif + #ifdef CONFIG_PM + + static int persist_enabled_on_companion(struct usb_device *udev, void *unused) +@@ -1219,7 +1233,32 @@ int ehci_hub_control( + ehci->reset_done [wIndex] = jiffies + + msecs_to_jiffies (50); + } ++ ++ if (!(temp & PORT_CONNECT) && !PORT_USB11 (temp)) ++ mdelay(100); ++ ++#if defined(CONFIG_ARCH_HI3519) || defined(CONFIG_ARCH_HI3559) || defined(CONFIG_ARCH_HI3556)\ ++ || defined(CONFIG_ARCH_HI3519V101) || defined(CONFIG_ARCH_HI3516CV300) || defined(CONFIG_ARCH_HI3516AV200) \ ++ || defined(CONFIG_ARCH_HI3531D) ++ if (ehci_readl(ehci, status_reg) == 0x1005) { ++ unsigned int reg, reg1; ++ void __iomem *base_reg; ++ ++ base_reg = ioremap_nocache(BASE_REG, 0x4); ++ ++ ehci_writel(ehci, temp, status_reg); ++ reg = reg1 = ehci_readl(ehci, base_reg); ++ reg1 |= USBPHY_PORT0_TREQ; ++ ehci_writel(ehci, reg1, base_reg); ++ ehci_writel(ehci, reg, base_reg); ++ ++ iounmap(base_reg); ++ } else ++ ehci_writel(ehci, temp, status_reg); ++ ++#else + ehci_writel(ehci, temp, status_reg); ++#endif + break; + + /* For downstream facing ports (these): one hub port is put +diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c +index 2f5b9ce..2ea6968 100644 +--- a/drivers/usb/host/ehci-platform.c ++++ b/drivers/usb/host/ehci-platform.c +@@ -43,7 +43,8 @@ + struct ehci_platform_priv { + struct clk *clks[EHCI_MAX_CLKS]; + struct reset_control *rst; +- struct phy *phy; ++ struct phy **phys; ++ int num_phys; + }; + + static const char hcd_name[] = "ehci-platform"; +@@ -78,7 +79,7 @@ static int ehci_platform_power_on(struct platform_device *dev) + { + struct usb_hcd *hcd = platform_get_drvdata(dev); + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); +- int clk, ret; ++ int clk, ret, phy_num; + + for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++) { + ret = clk_prepare_enable(priv->clks[clk]); +@@ -86,20 +87,24 @@ static int ehci_platform_power_on(struct platform_device *dev) + goto err_disable_clks; + } + +- if (priv->phy) { +- ret = phy_init(priv->phy); +- if (ret) +- goto err_disable_clks; +- +- ret = phy_power_on(priv->phy); ++ for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { ++ ret = phy_init(priv->phys[phy_num]); + if (ret) + goto err_exit_phy; ++ ret = phy_power_on(priv->phys[phy_num]); ++ if (ret) { ++ phy_exit(priv->phys[phy_num]); ++ goto err_exit_phy; ++ } + } + + return 0; + + err_exit_phy: +- phy_exit(priv->phy); ++ while (--phy_num >= 0) { ++ phy_power_off(priv->phys[phy_num]); ++ phy_exit(priv->phys[phy_num]); ++ } + err_disable_clks: + while (--clk >= 0) + clk_disable_unprepare(priv->clks[clk]); +@@ -111,11 +116,11 @@ static void ehci_platform_power_off(struct platform_device *dev) + { + struct usb_hcd *hcd = platform_get_drvdata(dev); + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); +- int clk; ++ int clk, phy_num; + +- if (priv->phy) { +- phy_power_off(priv->phy); +- phy_exit(priv->phy); ++ for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { ++ phy_power_off(priv->phys[phy_num]); ++ phy_exit(priv->phys[phy_num]); + } + + for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--) +@@ -143,7 +148,7 @@ static int ehci_platform_probe(struct platform_device *dev) + struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev); + struct ehci_platform_priv *priv; + struct ehci_hcd *ehci; +- int err, irq, clk = 0; ++ int err, irq, phy_num, clk = 0; + + if (usb_disabled()) + return -ENODEV; +@@ -190,12 +195,24 @@ static int ehci_platform_probe(struct platform_device *dev) + if (of_property_read_bool(dev->dev.of_node, "big-endian")) + ehci->big_endian_mmio = ehci->big_endian_desc = 1; + +- priv->phy = devm_phy_get(&dev->dev, "usb"); +- if (IS_ERR(priv->phy)) { +- err = PTR_ERR(priv->phy); +- if (err == -EPROBE_DEFER) +- goto err_put_hcd; +- priv->phy = NULL; ++ priv->num_phys = of_count_phandle_with_args(dev->dev.of_node, ++ "phys", "#phy-cells"); ++ ++ if (priv->num_phys > 0) { ++ priv->phys = devm_kcalloc(&dev->dev, priv->num_phys, ++ sizeof(struct phy *), GFP_KERNEL); ++ if (!priv->phys) ++ return -ENOMEM; ++ } else ++ priv->num_phys = 0; ++ ++ for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { ++ priv->phys[phy_num] = devm_of_phy_get_by_index( ++ &dev->dev, dev->dev.of_node, phy_num); ++ if (IS_ERR(priv->phys[phy_num])) { ++ err = PTR_ERR(priv->phys[phy_num]); ++ goto err_put_hcd; ++ } + } + + for (clk = 0; clk < EHCI_MAX_CLKS; clk++) { +@@ -311,7 +328,7 @@ static int ehci_platform_remove(struct platform_device *dev) + return 0; + } + +-#ifdef CONFIG_PM ++#ifdef CONFIG_PM_SLEEP + + static int ehci_platform_suspend(struct device *dev) + { +@@ -349,10 +366,7 @@ static int ehci_platform_resume(struct device *dev) + return 0; + } + +-#else /* !CONFIG_PM */ +-#define ehci_platform_suspend NULL +-#define ehci_platform_resume NULL +-#endif /* CONFIG_PM */ ++#endif /* CONFIG_PM_SLEEP */ + + static const struct of_device_id vt8500_ehci_ids[] = { + { .compatible = "via,vt8500-ehci", }, +@@ -368,10 +382,8 @@ static const struct platform_device_id ehci_platform_table[] = { + }; + MODULE_DEVICE_TABLE(platform, ehci_platform_table); + +-static const struct dev_pm_ops ehci_platform_pm_ops = { +- .suspend = ehci_platform_suspend, +- .resume = ehci_platform_resume, +-}; ++static SIMPLE_DEV_PM_OPS(ehci_platform_pm_ops, ehci_platform_suspend, ++ ehci_platform_resume); + + static struct platform_driver ehci_platform_driver = { + .id_table = ehci_platform_table, +diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c +index d664eda..098de14 100644 +--- a/drivers/usb/host/ohci-hcd.c ++++ b/drivers/usb/host/ohci-hcd.c +@@ -97,7 +97,9 @@ static void io_watchdog_func(unsigned long _ohci); + #define IRQ_NOTMINE IRQ_NONE + #endif + +- ++#ifdef CONFIG_ARCH_HI3516CV300 ++void usb2_low_power(int); ++#endif + /* Some boards misreport power switching/overcurrent */ + static bool distrust_firmware = 1; + module_param (distrust_firmware, bool, 0); +@@ -231,7 +233,6 @@ static int ohci_urb_enqueue ( + /* Start up the I/O watchdog timer, if it's not running */ + if (!timer_pending(&ohci->io_watchdog) && + list_empty(&ohci->eds_in_use)) { +- ohci->prev_frame_no = ohci_frame_no(ohci); + mod_timer(&ohci->io_watchdog, + jiffies + IO_WATCHDOG_DELAY); + } +@@ -729,7 +730,6 @@ static void io_watchdog_func(unsigned long _ohci) + u32 head; + struct ed *ed; + struct td *td, *td_start, *td_next; +- unsigned frame_no; + unsigned long flags; + + spin_lock_irqsave(&ohci->lock, flags); +@@ -745,7 +745,6 @@ static void io_watchdog_func(unsigned long _ohci) + if (!(status & OHCI_INTR_WDH) && ohci->wdh_cnt == ohci->prev_wdh_cnt) { + if (ohci->prev_donehead) { + ohci_err(ohci, "HcDoneHead not written back; disabled\n"); +- died: + usb_hc_died(ohci_to_hcd(ohci)); + ohci_dump(ohci); + ohci_shutdown(ohci_to_hcd(ohci)); +@@ -806,35 +805,7 @@ static void io_watchdog_func(unsigned long _ohci) + ohci_work(ohci); + + if (ohci->rh_state == OHCI_RH_RUNNING) { +- +- /* +- * Sometimes a controller just stops working. We can tell +- * by checking that the frame counter has advanced since +- * the last time we ran. +- * +- * But be careful: Some controllers violate the spec by +- * stopping their frame counter when no ports are active. +- */ +- frame_no = ohci_frame_no(ohci); +- if (frame_no == ohci->prev_frame_no) { +- int active_cnt = 0; +- int i; +- unsigned tmp; +- +- for (i = 0; i < ohci->num_ports; ++i) { +- tmp = roothub_portstatus(ohci, i); +- /* Enabled and not suspended? */ +- if ((tmp & RH_PS_PES) && !(tmp & RH_PS_PSS)) +- ++active_cnt; +- } +- +- if (active_cnt > 0) { +- ohci_err(ohci, "frame counter not updating; disabled\n"); +- goto died; +- } +- } + if (!list_empty(&ohci->eds_in_use)) { +- ohci->prev_frame_no = frame_no; + ohci->prev_wdh_cnt = ohci->wdh_cnt; + ohci->prev_donehead = ohci_readl(ohci, + &ohci->regs->donehead); +@@ -900,6 +871,16 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) + } + + if (ints & OHCI_INTR_RHSC) { ++#ifdef CONFIG_ARCH_HI3516CV300 ++ unsigned i = ohci->num_ports; ++ ++ while (i--) { ++ int pstatus; ++ ++ pstatus = roothub_portstatus (ohci, i); ++ usb2_low_power(pstatus); ++ } ++#endif + ohci_dbg(ohci, "rhsc\n"); + ohci->next_statechange = jiffies + STATECHANGE_DELAY; + ohci_writel(ohci, OHCI_INTR_RD | OHCI_INTR_RHSC, +diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c +index 4369299..00a6b0f 100644 +--- a/drivers/usb/host/ohci-platform.c ++++ b/drivers/usb/host/ohci-platform.c +@@ -38,7 +38,8 @@ + struct ohci_platform_priv { + struct clk *clks[OHCI_MAX_CLKS]; + struct reset_control *rst; +- struct phy *phy; ++ struct phy **phys; ++ int num_phys; + }; + + static const char hcd_name[] = "ohci-platform"; +@@ -61,7 +62,7 @@ static int ohci_platform_power_on(struct platform_device *dev) + { + struct usb_hcd *hcd = platform_get_drvdata(dev); + struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd); +- int clk, ret; ++ int clk, ret, phy_num; + + for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++) { + ret = clk_prepare_enable(priv->clks[clk]); +@@ -69,20 +70,24 @@ static int ohci_platform_power_on(struct platform_device *dev) + goto err_disable_clks; + } + +- if (priv->phy) { +- ret = phy_init(priv->phy); +- if (ret) +- goto err_disable_clks; +- +- ret = phy_power_on(priv->phy); ++ for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { ++ ret = phy_init(priv->phys[phy_num]); + if (ret) + goto err_exit_phy; ++ ret = phy_power_on(priv->phys[phy_num]); ++ if (ret) { ++ phy_exit(priv->phys[phy_num]); ++ goto err_exit_phy; ++ } + } + + return 0; + + err_exit_phy: +- phy_exit(priv->phy); ++ while (--phy_num >= 0) { ++ phy_power_off(priv->phys[phy_num]); ++ phy_exit(priv->phys[phy_num]); ++ } + err_disable_clks: + while (--clk >= 0) + clk_disable_unprepare(priv->clks[clk]); +@@ -94,11 +99,11 @@ static void ohci_platform_power_off(struct platform_device *dev) + { + struct usb_hcd *hcd = platform_get_drvdata(dev); + struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd); +- int clk; ++ int clk, phy_num; + +- if (priv->phy) { +- phy_power_off(priv->phy); +- phy_exit(priv->phy); ++ for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { ++ phy_power_off(priv->phys[phy_num]); ++ phy_exit(priv->phys[phy_num]); + } + + for (clk = OHCI_MAX_CLKS - 1; clk >= 0; clk--) +@@ -127,7 +132,7 @@ static int ohci_platform_probe(struct platform_device *dev) + struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev); + struct ohci_platform_priv *priv; + struct ohci_hcd *ohci; +- int err, irq, clk = 0; ++ int err, irq, phy_num, clk = 0; + + if (usb_disabled()) + return -ENODEV; +@@ -175,12 +180,24 @@ static int ohci_platform_probe(struct platform_device *dev) + if (of_property_read_bool(dev->dev.of_node, "big-endian")) + ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC; + +- priv->phy = devm_phy_get(&dev->dev, "usb"); +- if (IS_ERR(priv->phy)) { +- err = PTR_ERR(priv->phy); +- if (err == -EPROBE_DEFER) ++ priv->num_phys = of_count_phandle_with_args(dev->dev.of_node, ++ "phys", "#phy-cells"); ++ ++ if (priv->num_phys > 0) { ++ priv->phys = devm_kcalloc(&dev->dev, priv->num_phys, ++ sizeof(struct phy *), GFP_KERNEL); ++ if (!priv->phys) ++ return -ENOMEM; ++ } else ++ priv->num_phys = 0; ++ ++ for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { ++ priv->phys[phy_num] = devm_of_phy_get_by_index( ++ &dev->dev, dev->dev.of_node, phy_num); ++ if (IS_ERR(priv->phys[phy_num])) { ++ err = PTR_ERR(priv->phys[phy_num]); + goto err_put_hcd; +- priv->phy = NULL; ++ } + } + + for (clk = 0; clk < OHCI_MAX_CLKS; clk++) { +@@ -298,7 +315,7 @@ static int ohci_platform_remove(struct platform_device *dev) + return 0; + } + +-#ifdef CONFIG_PM ++#ifdef CONFIG_PM_SLEEP + + static int ohci_platform_suspend(struct device *dev) + { +@@ -335,11 +352,7 @@ static int ohci_platform_resume(struct device *dev) + ohci_resume(hcd, false); + return 0; + } +- +-#else /* !CONFIG_PM */ +-#define ohci_platform_suspend NULL +-#define ohci_platform_resume NULL +-#endif /* CONFIG_PM */ ++#endif /* CONFIG_PM_SLEEP */ + + static const struct of_device_id ohci_platform_ids[] = { + { .compatible = "generic-ohci", }, +@@ -353,10 +366,8 @@ static const struct platform_device_id ohci_platform_table[] = { + }; + MODULE_DEVICE_TABLE(platform, ohci_platform_table); + +-static const struct dev_pm_ops ohci_platform_pm_ops = { +- .suspend = ohci_platform_suspend, +- .resume = ohci_platform_resume, +-}; ++static SIMPLE_DEV_PM_OPS(ohci_platform_pm_ops, ohci_platform_suspend, ++ ohci_platform_resume); + + static struct platform_driver ohci_platform_driver = { + .id_table = ohci_platform_table, +diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h +index 59f4245..0548f5c 100644 +--- a/drivers/usb/host/ohci.h ++++ b/drivers/usb/host/ohci.h +@@ -421,7 +421,6 @@ struct ohci_hcd { + + // there are also chip quirks/bugs in init logic + +- unsigned prev_frame_no; + unsigned wdh_cnt, prev_wdh_cnt; + u32 prev_donehead; + struct timer_list io_watchdog; +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 54f386f..8a6354b 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -33,6 +33,19 @@ + #include "xhci-ext-caps.h" + #include "pci-quirks.h" + ++#if defined(CONFIG_ARCH_HI3519) || defined(CONFIG_ARCH_HI3519V101) || defined(CONFIG_ARCH_HI3516AV200) ++#ifdef readl ++#undef readl ++#undef readl_relaxed ++#undef writel ++#undef writel_relaxed ++#define readl hi_readl ++#define readl_relaxed hi_readl_relaxed ++#define writel hi_writel ++#define writel_relaxed hi_writel_relaxed ++#endif /* readl */ ++#endif /* defined(CONFIG_ARCH_HI3519) || defined(CONFIG_ARCH_HI3519V101) || defined(CONFIG_ARCH_HI3516AV200) */ ++ + /* xHCI PCI Configuration Registers */ + #define XHCI_SBRN_OFFSET (0x60) + +diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig +index 0cd1f44..77ef4bb 100644 +--- a/drivers/usb/phy/Kconfig ++++ b/drivers/usb/phy/Kconfig +@@ -6,6 +6,14 @@ menu "USB Physical Layer drivers" + config USB_PHY + def_bool n + ++config USB_OTG_WAKELOCK ++ bool "Hold a wakelock when USB connected" ++ depends on WAKELOCK ++ select USB_OTG_UTILS ++ help ++ Select this to automatically hold a wakelock when USB is ++ connected, preventing suspend. ++ + # + # USB Transceiver Drivers + # +@@ -213,4 +221,13 @@ config USB_ULPI_VIEWPORT + Provides read/write operations to the ULPI phy register set for + controllers with a viewport register (e.g. Chipidea/ARC controllers). + ++config DUAL_ROLE_USB_INTF ++ bool "Generic DUAL ROLE sysfs interface" ++ depends on SYSFS && USB_PHY ++ help ++ A generic sysfs interface to track and change the state of ++ dual role usb phys. The usb phy drivers can register to ++ this interface to expose it capabilities to the userspace ++ and thereby allowing userspace to change the port mode. ++ + endmenu +diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile +index 75f2bba..5cd7871 100644 +--- a/drivers/usb/phy/Makefile ++++ b/drivers/usb/phy/Makefile +@@ -3,6 +3,8 @@ + # + obj-$(CONFIG_USB_PHY) += phy.o + obj-$(CONFIG_OF) += of.o ++obj-$(CONFIG_USB_OTG_WAKELOCK) += otg-wakelock.o ++obj-$(CONFIG_DUAL_ROLE_USB_INTF) += class-dual-role.o + + # transceiver drivers, keep the list sorted + +diff --git a/drivers/usb/phy/class-dual-role.c b/drivers/usb/phy/class-dual-role.c +new file mode 100644 +index 0000000..51fcb54 +--- /dev/null ++++ b/drivers/usb/phy/class-dual-role.c +@@ -0,0 +1,529 @@ ++/* ++ * class-dual-role.c ++ * ++ * Copyright (C) 2015 Google, 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. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DUAL_ROLE_NOTIFICATION_TIMEOUT 2000 ++ ++static ssize_t dual_role_store_property(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count); ++static ssize_t dual_role_show_property(struct device *dev, ++ struct device_attribute *attr, ++ char *buf); ++ ++#define DUAL_ROLE_ATTR(_name) \ ++{ \ ++ .attr = { .name = #_name }, \ ++ .show = dual_role_show_property, \ ++ .store = dual_role_store_property, \ ++} ++ ++static struct device_attribute dual_role_attrs[] = { ++ DUAL_ROLE_ATTR(supported_modes), ++ DUAL_ROLE_ATTR(mode), ++ DUAL_ROLE_ATTR(power_role), ++ DUAL_ROLE_ATTR(data_role), ++ DUAL_ROLE_ATTR(powers_vconn), ++}; ++ ++struct class *dual_role_class; ++EXPORT_SYMBOL_GPL(dual_role_class); ++ ++static struct device_type dual_role_dev_type; ++ ++static char *kstrdupcase(const char *str, gfp_t gfp, bool to_upper) ++{ ++ char *ret, *ustr; ++ ++ ustr = ret = kmalloc(strlen(str) + 1, gfp); ++ ++ if (!ret) ++ return NULL; ++ ++ while (*str) ++ *ustr++ = to_upper ? toupper(*str++) : tolower(*str++); ++ ++ *ustr = 0; ++ ++ return ret; ++} ++ ++static void dual_role_changed_work(struct work_struct *work) ++{ ++ struct dual_role_phy_instance *dual_role = ++ container_of(work, struct dual_role_phy_instance, ++ changed_work); ++ ++ dev_dbg(&dual_role->dev, "%s\n", __func__); ++ kobject_uevent(&dual_role->dev.kobj, KOBJ_CHANGE); ++} ++ ++void dual_role_instance_changed(struct dual_role_phy_instance *dual_role) ++{ ++ dev_dbg(&dual_role->dev, "%s\n", __func__); ++ pm_wakeup_event(&dual_role->dev, DUAL_ROLE_NOTIFICATION_TIMEOUT); ++ schedule_work(&dual_role->changed_work); ++} ++EXPORT_SYMBOL_GPL(dual_role_instance_changed); ++ ++int dual_role_get_property(struct dual_role_phy_instance *dual_role, ++ enum dual_role_property prop, ++ unsigned int *val) ++{ ++ return dual_role->desc->get_property(dual_role, prop, val); ++} ++EXPORT_SYMBOL_GPL(dual_role_get_property); ++ ++int dual_role_set_property(struct dual_role_phy_instance *dual_role, ++ enum dual_role_property prop, ++ const unsigned int *val) ++{ ++ if (!dual_role->desc->set_property) ++ return -ENODEV; ++ ++ return dual_role->desc->set_property(dual_role, prop, val); ++} ++EXPORT_SYMBOL_GPL(dual_role_set_property); ++ ++int dual_role_property_is_writeable(struct dual_role_phy_instance *dual_role, ++ enum dual_role_property prop) ++{ ++ if (!dual_role->desc->property_is_writeable) ++ return -ENODEV; ++ ++ return dual_role->desc->property_is_writeable(dual_role, prop); ++} ++EXPORT_SYMBOL_GPL(dual_role_property_is_writeable); ++ ++static void dual_role_dev_release(struct device *dev) ++{ ++ struct dual_role_phy_instance *dual_role = ++ container_of(dev, struct dual_role_phy_instance, dev); ++ pr_debug("device: '%s': %s\n", dev_name(dev), __func__); ++ kfree(dual_role); ++} ++ ++static struct dual_role_phy_instance *__must_check ++__dual_role_register(struct device *parent, ++ const struct dual_role_phy_desc *desc) ++{ ++ struct device *dev; ++ struct dual_role_phy_instance *dual_role; ++ int rc; ++ ++ dual_role = kzalloc(sizeof(*dual_role), GFP_KERNEL); ++ if (!dual_role) ++ return ERR_PTR(-ENOMEM); ++ ++ dev = &dual_role->dev; ++ ++ device_initialize(dev); ++ ++ dev->class = dual_role_class; ++ dev->type = &dual_role_dev_type; ++ dev->parent = parent; ++ dev->release = dual_role_dev_release; ++ dev_set_drvdata(dev, dual_role); ++ dual_role->desc = desc; ++ ++ rc = dev_set_name(dev, "%s", desc->name); ++ if (rc) ++ goto dev_set_name_failed; ++ ++ INIT_WORK(&dual_role->changed_work, dual_role_changed_work); ++ ++ rc = device_init_wakeup(dev, true); ++ if (rc) ++ goto wakeup_init_failed; ++ ++ rc = device_add(dev); ++ if (rc) ++ goto device_add_failed; ++ ++ dual_role_instance_changed(dual_role); ++ ++ return dual_role; ++ ++device_add_failed: ++ device_init_wakeup(dev, false); ++wakeup_init_failed: ++dev_set_name_failed: ++ put_device(dev); ++ kfree(dual_role); ++ ++ return ERR_PTR(rc); ++} ++ ++static void dual_role_instance_unregister(struct dual_role_phy_instance ++ *dual_role) ++{ ++ cancel_work_sync(&dual_role->changed_work); ++ device_init_wakeup(&dual_role->dev, false); ++ device_unregister(&dual_role->dev); ++} ++ ++static void devm_dual_role_release(struct device *dev, void *res) ++{ ++ struct dual_role_phy_instance **dual_role = res; ++ ++ dual_role_instance_unregister(*dual_role); ++} ++ ++struct dual_role_phy_instance *__must_check ++devm_dual_role_instance_register(struct device *parent, ++ const struct dual_role_phy_desc *desc) ++{ ++ struct dual_role_phy_instance **ptr, *dual_role; ++ ++ ptr = devres_alloc(devm_dual_role_release, sizeof(*ptr), GFP_KERNEL); ++ ++ if (!ptr) ++ return ERR_PTR(-ENOMEM); ++ dual_role = __dual_role_register(parent, desc); ++ if (IS_ERR(dual_role)) { ++ devres_free(ptr); ++ } else { ++ *ptr = dual_role; ++ devres_add(parent, ptr); ++ } ++ return dual_role; ++} ++EXPORT_SYMBOL_GPL(devm_dual_role_instance_register); ++ ++static int devm_dual_role_match(struct device *dev, void *res, void *data) ++{ ++ struct dual_role_phy_instance **r = res; ++ ++ if (WARN_ON(!r || !*r)) ++ return 0; ++ ++ return *r == data; ++} ++ ++void devm_dual_role_instance_unregister(struct device *dev, ++ struct dual_role_phy_instance ++ *dual_role) ++{ ++ int rc; ++ ++ rc = devres_release(dev, devm_dual_role_release, ++ devm_dual_role_match, dual_role); ++ WARN_ON(rc); ++} ++EXPORT_SYMBOL_GPL(devm_dual_role_instance_unregister); ++ ++void *dual_role_get_drvdata(struct dual_role_phy_instance *dual_role) ++{ ++ return dual_role->drv_data; ++} ++EXPORT_SYMBOL_GPL(dual_role_get_drvdata); ++ ++/***************** Device attribute functions **************************/ ++ ++/* port type */ ++static char *supported_modes_text[] = { ++ "ufp dfp", "dfp", "ufp" ++}; ++ ++/* current mode */ ++static char *mode_text[] = { ++ "ufp", "dfp", "none" ++}; ++ ++/* Power role */ ++static char *pr_text[] = { ++ "source", "sink", "none" ++}; ++ ++/* Data role */ ++static char *dr_text[] = { ++ "host", "device", "none" ++}; ++ ++/* Vconn supply */ ++static char *vconn_supply_text[] = { ++ "n", "y" ++}; ++ ++static ssize_t dual_role_show_property(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ssize_t ret = 0; ++ struct dual_role_phy_instance *dual_role = dev_get_drvdata(dev); ++ const ptrdiff_t off = attr - dual_role_attrs; ++ unsigned int value; ++ ++ if (off == DUAL_ROLE_PROP_SUPPORTED_MODES) { ++ value = dual_role->desc->supported_modes; ++ } else { ++ ret = dual_role_get_property(dual_role, off, &value); ++ ++ if (ret < 0) { ++ if (ret == -ENODATA) ++ dev_dbg(dev, ++ "driver has no data for `%s' property\n", ++ attr->attr.name); ++ else if (ret != -ENODEV) ++ dev_err(dev, ++ "driver failed to report `%s' property: %zd\n", ++ attr->attr.name, ret); ++ return ret; ++ } ++ } ++ ++ if (off == DUAL_ROLE_PROP_SUPPORTED_MODES) { ++ BUILD_BUG_ON(DUAL_ROLE_PROP_SUPPORTED_MODES_TOTAL != ++ ARRAY_SIZE(supported_modes_text)); ++ if (value < DUAL_ROLE_PROP_SUPPORTED_MODES_TOTAL) ++ return snprintf(buf, PAGE_SIZE, "%s\n", ++ supported_modes_text[value]); ++ else ++ return -EIO; ++ } else if (off == DUAL_ROLE_PROP_MODE) { ++ BUILD_BUG_ON(DUAL_ROLE_PROP_MODE_TOTAL != ++ ARRAY_SIZE(mode_text)); ++ if (value < DUAL_ROLE_PROP_MODE_TOTAL) ++ return snprintf(buf, PAGE_SIZE, "%s\n", ++ mode_text[value]); ++ else ++ return -EIO; ++ } else if (off == DUAL_ROLE_PROP_PR) { ++ BUILD_BUG_ON(DUAL_ROLE_PROP_PR_TOTAL != ARRAY_SIZE(pr_text)); ++ if (value < DUAL_ROLE_PROP_PR_TOTAL) ++ return snprintf(buf, PAGE_SIZE, "%s\n", ++ pr_text[value]); ++ else ++ return -EIO; ++ } else if (off == DUAL_ROLE_PROP_DR) { ++ BUILD_BUG_ON(DUAL_ROLE_PROP_DR_TOTAL != ARRAY_SIZE(dr_text)); ++ if (value < DUAL_ROLE_PROP_DR_TOTAL) ++ return snprintf(buf, PAGE_SIZE, "%s\n", ++ dr_text[value]); ++ else ++ return -EIO; ++ } else if (off == DUAL_ROLE_PROP_VCONN_SUPPLY) { ++ BUILD_BUG_ON(DUAL_ROLE_PROP_VCONN_SUPPLY_TOTAL != ++ ARRAY_SIZE(vconn_supply_text)); ++ if (value < DUAL_ROLE_PROP_VCONN_SUPPLY_TOTAL) ++ return snprintf(buf, PAGE_SIZE, "%s\n", ++ vconn_supply_text[value]); ++ else ++ return -EIO; ++ } else ++ return -EIO; ++} ++ ++static ssize_t dual_role_store_property(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ssize_t ret; ++ struct dual_role_phy_instance *dual_role = dev_get_drvdata(dev); ++ const ptrdiff_t off = attr - dual_role_attrs; ++ unsigned int value; ++ int total, i; ++ char *dup_buf, **text_array; ++ bool result = false; ++ ++ dup_buf = kstrdupcase(buf, GFP_KERNEL, false); ++ switch (off) { ++ case DUAL_ROLE_PROP_MODE: ++ total = DUAL_ROLE_PROP_MODE_TOTAL; ++ text_array = mode_text; ++ break; ++ case DUAL_ROLE_PROP_PR: ++ total = DUAL_ROLE_PROP_PR_TOTAL; ++ text_array = pr_text; ++ break; ++ case DUAL_ROLE_PROP_DR: ++ total = DUAL_ROLE_PROP_DR_TOTAL; ++ text_array = dr_text; ++ break; ++ case DUAL_ROLE_PROP_VCONN_SUPPLY: ++ ret = strtobool(dup_buf, &result); ++ value = result; ++ if (!ret) ++ goto setprop; ++ default: ++ ret = -EINVAL; ++ goto error; ++ } ++ ++ for (i = 0; i <= total; i++) { ++ if (i == total) { ++ ret = -ENOTSUPP; ++ goto error; ++ } ++ if (!strncmp(*(text_array + i), dup_buf, ++ strlen(*(text_array + i)))) { ++ value = i; ++ break; ++ } ++ } ++ ++setprop: ++ ret = dual_role->desc->set_property(dual_role, off, &value); ++ ++error: ++ kfree(dup_buf); ++ ++ if (ret < 0) ++ return ret; ++ ++ return count; ++} ++ ++static umode_t dual_role_attr_is_visible(struct kobject *kobj, ++ struct attribute *attr, int attrno) ++{ ++ struct device *dev = container_of(kobj, struct device, kobj); ++ struct dual_role_phy_instance *dual_role = dev_get_drvdata(dev); ++ umode_t mode = S_IRUSR | S_IRGRP | S_IROTH; ++ int i; ++ ++ if (attrno == DUAL_ROLE_PROP_SUPPORTED_MODES) ++ return mode; ++ ++ for (i = 0; i < dual_role->desc->num_properties; i++) { ++ int property = dual_role->desc->properties[i]; ++ ++ if (property == attrno) { ++ if (dual_role->desc->property_is_writeable && ++ dual_role_property_is_writeable(dual_role, property) ++ > 0) ++ mode |= S_IWUSR; ++ ++ return mode; ++ } ++ } ++ ++ return 0; ++} ++ ++static struct attribute *__dual_role_attrs[ARRAY_SIZE(dual_role_attrs) + 1]; ++ ++static struct attribute_group dual_role_attr_group = { ++ .attrs = __dual_role_attrs, ++ .is_visible = dual_role_attr_is_visible, ++}; ++ ++static const struct attribute_group *dual_role_attr_groups[] = { ++ &dual_role_attr_group, ++ NULL, ++}; ++ ++void dual_role_init_attrs(struct device_type *dev_type) ++{ ++ int i; ++ ++ dev_type->groups = dual_role_attr_groups; ++ ++ for (i = 0; i < ARRAY_SIZE(dual_role_attrs); i++) ++ __dual_role_attrs[i] = &dual_role_attrs[i].attr; ++} ++ ++int dual_role_uevent(struct device *dev, struct kobj_uevent_env *env) ++{ ++ struct dual_role_phy_instance *dual_role = dev_get_drvdata(dev); ++ int ret = 0, j; ++ char *prop_buf; ++ char *attrname; ++ ++ dev_dbg(dev, "uevent\n"); ++ ++ if (!dual_role || !dual_role->desc) { ++ dev_dbg(dev, "No dual_role phy yet\n"); ++ return ret; ++ } ++ ++ dev_dbg(dev, "DUAL_ROLE_NAME=%s\n", dual_role->desc->name); ++ ++ ret = add_uevent_var(env, "DUAL_ROLE_NAME=%s", dual_role->desc->name); ++ if (ret) ++ return ret; ++ ++ prop_buf = (char *)get_zeroed_page(GFP_KERNEL); ++ if (!prop_buf) ++ return -ENOMEM; ++ ++ for (j = 0; j < dual_role->desc->num_properties; j++) { ++ struct device_attribute *attr; ++ char *line; ++ ++ attr = &dual_role_attrs[dual_role->desc->properties[j]]; ++ ++ ret = dual_role_show_property(dev, attr, prop_buf); ++ if (ret == -ENODEV || ret == -ENODATA) { ++ ret = 0; ++ continue; ++ } ++ ++ if (ret < 0) ++ goto out; ++ line = strnchr(prop_buf, PAGE_SIZE, '\n'); ++ if (line) ++ *line = 0; ++ ++ attrname = kstrdupcase(attr->attr.name, GFP_KERNEL, true); ++ if (!attrname) ++ ret = -ENOMEM; ++ ++ dev_dbg(dev, "prop %s=%s\n", attrname, prop_buf); ++ ++ ret = add_uevent_var(env, "DUAL_ROLE_%s=%s", attrname, ++ prop_buf); ++ kfree(attrname); ++ if (ret) ++ goto out; ++ } ++ ++out: ++ free_page((unsigned long)prop_buf); ++ ++ return ret; ++} ++ ++/******************* Module Init ***********************************/ ++ ++static int __init dual_role_class_init(void) ++{ ++ dual_role_class = class_create(THIS_MODULE, "dual_role_usb"); ++ ++ if (IS_ERR(dual_role_class)) ++ return PTR_ERR(dual_role_class); ++ ++ dual_role_class->dev_uevent = dual_role_uevent; ++ dual_role_init_attrs(&dual_role_dev_type); ++ ++ return 0; ++} ++ ++static void __exit dual_role_class_exit(void) ++{ ++ class_destroy(dual_role_class); ++} ++ ++subsys_initcall(dual_role_class_init); ++module_exit(dual_role_class_exit); +diff --git a/drivers/usb/phy/otg-wakelock.c b/drivers/usb/phy/otg-wakelock.c +new file mode 100644 +index 0000000..479376b +--- /dev/null ++++ b/drivers/usb/phy/otg-wakelock.c +@@ -0,0 +1,173 @@ ++/* ++ * otg-wakelock.c ++ * ++ * Copyright (C) 2011 Google, 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. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TEMPORARY_HOLD_TIME 2000 ++ ++static bool enabled = true; ++static struct usb_phy *otgwl_xceiv; ++static struct notifier_block otgwl_nb; ++ ++/* ++ * otgwl_spinlock is held while the VBUS lock is grabbed or dropped and the ++ * held field is updated to match. ++ */ ++ ++static DEFINE_SPINLOCK(otgwl_spinlock); ++ ++/* ++ * Only one lock, but since these 3 fields are associated with each other... ++ */ ++ ++struct otgwl_lock { ++ char name[40]; ++ struct wake_lock wakelock; ++ bool held; ++}; ++ ++/* ++ * VBUS present lock. Also used as a timed lock on charger ++ * connect/disconnect and USB host disconnect, to allow the system ++ * to react to the change in power. ++ */ ++ ++static struct otgwl_lock vbus_lock; ++ ++static void otgwl_hold(struct otgwl_lock *lock) ++{ ++ if (!lock->held) { ++ wake_lock(&lock->wakelock); ++ lock->held = true; ++ } ++} ++ ++static void otgwl_temporary_hold(struct otgwl_lock *lock) ++{ ++ wake_lock_timeout(&lock->wakelock, ++ msecs_to_jiffies(TEMPORARY_HOLD_TIME)); ++ lock->held = false; ++} ++ ++static void otgwl_drop(struct otgwl_lock *lock) ++{ ++ if (lock->held) { ++ wake_unlock(&lock->wakelock); ++ lock->held = false; ++ } ++} ++ ++static void otgwl_handle_event(unsigned long event) ++{ ++ unsigned long irqflags; ++ ++ spin_lock_irqsave(&otgwl_spinlock, irqflags); ++ ++ if (!enabled) { ++ otgwl_drop(&vbus_lock); ++ spin_unlock_irqrestore(&otgwl_spinlock, irqflags); ++ return; ++ } ++ ++ switch (event) { ++ case USB_EVENT_VBUS: ++ case USB_EVENT_ENUMERATED: ++ otgwl_hold(&vbus_lock); ++ break; ++ ++ case USB_EVENT_NONE: ++ case USB_EVENT_ID: ++ case USB_EVENT_CHARGER: ++ otgwl_temporary_hold(&vbus_lock); ++ break; ++ ++ default: ++ break; ++ } ++ ++ spin_unlock_irqrestore(&otgwl_spinlock, irqflags); ++} ++ ++static int otgwl_otg_notifications(struct notifier_block *nb, ++ unsigned long event, void *unused) ++{ ++ otgwl_handle_event(event); ++ return NOTIFY_OK; ++} ++ ++static int set_enabled(const char *val, const struct kernel_param *kp) ++{ ++ int rv = param_set_bool(val, kp); ++ ++ if (rv) ++ return rv; ++ ++ if (otgwl_xceiv) ++ otgwl_handle_event(otgwl_xceiv->last_event); ++ ++ return 0; ++} ++ ++static struct kernel_param_ops enabled_param_ops = { ++ .set = set_enabled, ++ .get = param_get_bool, ++}; ++ ++module_param_cb(enabled, &enabled_param_ops, &enabled, 0644); ++MODULE_PARM_DESC(enabled, "enable wakelock when VBUS present"); ++ ++static int __init otg_wakelock_init(void) ++{ ++ int ret; ++ struct usb_phy *phy; ++ ++ phy = usb_get_phy(USB_PHY_TYPE_USB2); ++ ++ if (IS_ERR(phy)) { ++ pr_err("%s: No USB transceiver found\n", __func__); ++ return PTR_ERR(phy); ++ } ++ otgwl_xceiv = phy; ++ ++ snprintf(vbus_lock.name, sizeof(vbus_lock.name), "vbus-%s", ++ dev_name(otgwl_xceiv->dev)); ++ wake_lock_init(&vbus_lock.wakelock, WAKE_LOCK_SUSPEND, ++ vbus_lock.name); ++ ++ otgwl_nb.notifier_call = otgwl_otg_notifications; ++ ret = usb_register_notifier(otgwl_xceiv, &otgwl_nb); ++ ++ if (ret) { ++ pr_err("%s: usb_register_notifier on transceiver %s" ++ " failed\n", __func__, ++ dev_name(otgwl_xceiv->dev)); ++ otgwl_xceiv = NULL; ++ wake_lock_destroy(&vbus_lock.wakelock); ++ return ret; ++ } ++ ++ otgwl_handle_event(otgwl_xceiv->last_event); ++ return ret; ++} ++ ++late_initcall(otg_wakelock_init); +diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c +index cb84f69..313f09a 100644 +--- a/drivers/vhost/scsi.c ++++ b/drivers/vhost/scsi.c +@@ -1251,7 +1251,7 @@ tcm_vhost_send_evt(struct vhost_scsi *vs, + * lun[4-7] need to be zero according to virtio-scsi spec. + */ + evt->event.lun[0] = 0x01; +- evt->event.lun[1] = tpg->tport_tpgt & 0xFF; ++ evt->event.lun[1] = tpg->tport_tpgt; + if (lun->unpacked_lun >= 256) + evt->event.lun[2] = lun->unpacked_lun >> 8 | 0x40 ; + evt->event.lun[3] = lun->unpacked_lun & 0xFF; +@@ -2122,12 +2122,12 @@ tcm_vhost_make_tpg(struct se_wwn *wwn, + struct tcm_vhost_tport, tport_wwn); + + struct tcm_vhost_tpg *tpg; +- unsigned long tpgt; ++ u16 tpgt; + int ret; + + if (strstr(name, "tpgt_") != name) + return ERR_PTR(-EINVAL); +- if (kstrtoul(name + 5, 10, &tpgt) || tpgt > UINT_MAX) ++ if (kstrtou16(name + 5, 10, &tpgt) || tpgt >= VHOST_SCSI_MAX_TARGET) + return ERR_PTR(-EINVAL); + + tpg = kzalloc(sizeof(struct tcm_vhost_tpg), GFP_KERNEL); +diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig +index 8bf495f..49fcbb1 100644 +--- a/drivers/video/Kconfig ++++ b/drivers/video/Kconfig +@@ -31,6 +31,7 @@ source "drivers/video/fbdev/Kconfig" + endmenu + + source "drivers/video/backlight/Kconfig" ++source "drivers/video/adf/Kconfig" + + config VGASTATE + tristate +diff --git a/drivers/video/Makefile b/drivers/video/Makefile +index 9ad3c17..1a8c4ce 100644 +--- a/drivers/video/Makefile ++++ b/drivers/video/Makefile +@@ -1,6 +1,7 @@ + obj-$(CONFIG_VGASTATE) += vgastate.o + obj-$(CONFIG_HDMI) += hdmi.o + ++obj-$(CONFIG_ADF) += adf/ + obj-$(CONFIG_VT) += console/ + obj-$(CONFIG_LOGO) += logo/ + obj-y += backlight/ +diff --git a/drivers/video/adf/Kconfig b/drivers/video/adf/Kconfig +new file mode 100644 +index 0000000..33858b7 +--- /dev/null ++++ b/drivers/video/adf/Kconfig +@@ -0,0 +1,14 @@ ++menuconfig ADF ++ depends on SYNC ++ depends on DMA_SHARED_BUFFER ++ tristate "Atomic Display Framework" ++ ++menuconfig ADF_FBDEV ++ depends on ADF ++ depends on FB ++ tristate "Helper for implementing the fbdev API in ADF drivers" ++ ++menuconfig ADF_MEMBLOCK ++ depends on ADF ++ depends on HAVE_MEMBLOCK ++ tristate "Helper for using memblocks as buffers in ADF drivers" +diff --git a/drivers/video/adf/Makefile b/drivers/video/adf/Makefile +new file mode 100644 +index 0000000..78d0915 +--- /dev/null ++++ b/drivers/video/adf/Makefile +@@ -0,0 +1,15 @@ ++ccflags-y := -Idrivers/staging/android ++ ++CFLAGS_adf.o := -I$(src) ++ ++obj-$(CONFIG_ADF) += adf.o \ ++ adf_client.o \ ++ adf_fops.o \ ++ adf_format.o \ ++ adf_sysfs.o ++ ++obj-$(CONFIG_COMPAT) += adf_fops32.o ++ ++obj-$(CONFIG_ADF_FBDEV) += adf_fbdev.o ++ ++obj-$(CONFIG_ADF_MEMBLOCK) += adf_memblock.o +diff --git a/drivers/video/adf/adf.c b/drivers/video/adf/adf.c +new file mode 100644 +index 0000000..42c30c0 +--- /dev/null ++++ b/drivers/video/adf/adf.c +@@ -0,0 +1,1188 @@ ++/* ++ * Copyright (C) 2013 Google, Inc. ++ * adf_modeinfo_{set_name,set_vrefresh} modified from ++ * drivers/gpu/drm/drm_modes.c ++ * adf_format_validate_yuv modified from framebuffer_check in ++ * drivers/gpu/drm/drm_crtc.c ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include